docs: update documentation and add server schema
- Update CLAUDE.md with server provisioning docs - Add server tables to schema.sql (cloud_providers, instance_specs, etc.) - Register manage_server tool in tools/index.ts - Minor fixes to conversation-service and summary-service Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
38
CLAUDE.md
38
CLAUDE.md
@@ -33,8 +33,22 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||||||
- 프로덕션 수준의 코드 품질 보장
|
- 프로덕션 수준의 코드 품질 보장
|
||||||
- 엔터프라이즈급 에러 핸들링 및 타입 안정성
|
- 엔터프라이즈급 에러 핸들링 및 타입 안정성
|
||||||
- 성능 최적화 및 베스트 프랙티스 적용
|
- 성능 최적화 및 베스트 프랙티스 적용
|
||||||
- `Explore`: 프로젝트 구조 분석 (thorough 레벨)
|
- 도구: Read, Write, Edit, Bash, Glob, Grep (쓰기 가능)
|
||||||
|
- `explorer`: 코드베이스 탐색/분석 전문가 (thorough 레벨)
|
||||||
|
- 프로젝트 구조 파악 및 의존성 분석
|
||||||
|
- 대량 파일 읽기 및 패턴 인식
|
||||||
|
- 도구: Read, Grep, Glob (읽기 전용)
|
||||||
|
- `planner`: 설계/계획 수립 전문가
|
||||||
|
- 아키텍처 설계 및 구현 계획 작성
|
||||||
|
- 시스템 분석 및 개선 방향 제시
|
||||||
|
- 도구: Read, Grep, Glob (읽기 전용)
|
||||||
|
- `reviewer`: 코드 리뷰 전문가
|
||||||
|
- 품질/보안/성능 검토
|
||||||
|
- 페르소나 조합으로 전문화 (qa/security/performance)
|
||||||
|
- 도구: Read, Grep, Glob (읽기 전용)
|
||||||
- `Bash`: 빌드/배포/테스트 실행
|
- `Bash`: 빌드/배포/테스트 실행
|
||||||
|
- 긴 로그 출력 분리 (컨텍스트 절약)
|
||||||
|
- 시스템 명령어 실행
|
||||||
|
|
||||||
**CRITICAL: 다음 작업은 반드시 Task tool (agent)를 사용하여 메인 세션 컨텍스트 절약:**
|
**CRITICAL: 다음 작업은 반드시 Task tool (agent)를 사용하여 메인 세션 컨텍스트 절약:**
|
||||||
|
|
||||||
@@ -44,8 +58,9 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||||||
| **리팩토링** | 파일 수 무관 | `coder` (병렬) | 일관성, 컨텍스트 분리, TS 최적화 |
|
| **리팩토링** | 파일 수 무관 | `coder` (병렬) | 일관성, 컨텍스트 분리, TS 최적화 |
|
||||||
| **Function Calling 도구** | 추가/수정 | `coder` (병렬) | tools/ + openai-service.ts 동시 처리 |
|
| **Function Calling 도구** | 추가/수정 | `coder` (병렬) | tools/ + openai-service.ts 동시 처리 |
|
||||||
| **스키마 작업** | D1 마이그레이션 | `coder` | 백업→마이그레이션→검증 전체 위임 |
|
| **스키마 작업** | D1 마이그레이션 | `coder` | 백업→마이그레이션→검증 전체 위임 |
|
||||||
| **프로젝트 분석** | 구조 파악 | `Explore` (thorough) | 대량 파일 읽기 분리 |
|
| **프로젝트 분석** | 구조 파악 | `explorer` (thorough) | 대량 파일 읽기 분리 |
|
||||||
| **코드 리뷰** | 보안/성능 | `Explore` + `coder` | 분석 후 개선 제안 |
|
| **설계/계획** | 아키텍처 설계 | `planner` | 시스템 분석 및 개선 방향 제시 |
|
||||||
|
| **코드 리뷰** | 보안/성능 | `reviewer` → `coder` | 분석 후 개선 제안 (reviewer는 읽기 전용) |
|
||||||
| **빌드/배포** | npm run, wrangler | `Bash` | 긴 로그 출력 분리 |
|
| **빌드/배포** | npm run, wrangler | `Bash` | 긴 로그 출력 분리 |
|
||||||
| **테스트** | 로컬 테스트 실행 | `Bash` | 테스트 출력 분리 |
|
| **테스트** | 로컬 테스트 실행 | `Bash` | 테스트 출력 분리 |
|
||||||
|
|
||||||
@@ -209,6 +224,9 @@ wrangler secret put NAMECHEAP_API_KEY # namecheap-api 래퍼 인증 키
|
|||||||
wrangler secret put NAMECHEAP_API_KEY_INTERNAL # Namecheap API 키 (내부용)
|
wrangler secret put NAMECHEAP_API_KEY_INTERNAL # Namecheap API 키 (내부용)
|
||||||
wrangler secret put BRAVE_API_KEY # Brave Search API 키
|
wrangler secret put BRAVE_API_KEY # Brave Search API 키
|
||||||
wrangler secret put DEPOSIT_API_SECRET # Deposit API 인증 키
|
wrangler secret put DEPOSIT_API_SECRET # Deposit API 인증 키
|
||||||
|
wrangler secret put LINODE_API_KEY # Linode API 키
|
||||||
|
wrangler secret put VULTR_API_KEY # Vultr API 키
|
||||||
|
wrangler secret put SERVER_ADMIN_ID # 서버 관리 알림 Telegram ID
|
||||||
```
|
```
|
||||||
|
|
||||||
**Webhook 설정:**
|
**Webhook 설정:**
|
||||||
@@ -236,6 +254,9 @@ wrangler d1 execute telegram-conversations --file=migrations/001_rollback.sql
|
|||||||
| 파일 | 설명 | 적용일 |
|
| 파일 | 설명 | 적용일 |
|
||||||
|------|------|--------|
|
|------|------|--------|
|
||||||
| `001_optimize_prefix_indexes.sql` | 입금자명 prefix 인덱스 최적화 (99% 성능 향상) | 2026-01-19 |
|
| `001_optimize_prefix_indexes.sql` | 입금자명 prefix 인덱스 최적화 (99% 성능 향상) | 2026-01-19 |
|
||||||
|
| `002_add_version_columns.sql` | Optimistic Locking (user_deposits.version) | 2026-01-20 |
|
||||||
|
| `003_add_server_tables.sql` | 서버 관리 시스템 테이블 추가 | 2026-01-23 |
|
||||||
|
| `004_seed_server_data.sql` | 서버 제공자/사양 초기 데이터 | 2026-01-23 |
|
||||||
|
|
||||||
**마이그레이션 작업 내용 (001):**
|
**마이그레이션 작업 내용 (001):**
|
||||||
- `deposit_transactions.depositor_name_prefix` 컬럼 추가
|
- `deposit_transactions.depositor_name_prefix` 컬럼 추가
|
||||||
@@ -612,7 +633,7 @@ await process();
|
|||||||
end(); // duration 자동 기록
|
end(); // duration 자동 기록
|
||||||
```
|
```
|
||||||
|
|
||||||
**Function Calling Tools (8개):**
|
**Function Calling Tools (9개):**
|
||||||
| 도구 | 함수명 | 외부 API | 트리거 키워드 |
|
| 도구 | 함수명 | 외부 API | 트리거 키워드 |
|
||||||
|------|--------|----------|---------------|
|
|------|--------|----------|---------------|
|
||||||
| 날씨 | `get_weather` | wttr.in | 날씨 |
|
| 날씨 | `get_weather` | wttr.in | 날씨 |
|
||||||
@@ -623,6 +644,7 @@ end(); // duration 자동 기록
|
|||||||
| 도메인 | `manage_domain` | 코드 직접 처리 → Namecheap | 도메인, 네임서버, WHOIS |
|
| 도메인 | `manage_domain` | 코드 직접 처리 → Namecheap | 도메인, 네임서버, WHOIS |
|
||||||
| 도메인 추천 | `suggest_domains` | GPT + Namecheap | **도메인 추천, 도메인 제안, 도메인 아이디어** |
|
| 도메인 추천 | `suggest_domains` | GPT + Namecheap | **도메인 추천, 도메인 제안, 도메인 아이디어** |
|
||||||
| 예치금 | `manage_deposit` | 코드 직접 처리 | **입금, 충전, 잔액, 계좌, 송금** |
|
| 예치금 | `manage_deposit` | 코드 직접 처리 | **입금, 충전, 잔액, 계좌, 송금** |
|
||||||
|
| 서버 | `manage_server` | Linode/Vultr API | **서버, VPS, 클라우드, 인스턴스** |
|
||||||
|
|
||||||
**Data Layer (D1 SQLite):**
|
**Data Layer (D1 SQLite):**
|
||||||
| 테이블 | 용도 | 주요 컬럼 |
|
| 테이블 | 용도 | 주요 컬럼 |
|
||||||
@@ -634,6 +656,10 @@ end(); // duration 자동 기록
|
|||||||
| `deposit_transactions` | 거래 내역 | user_id, amount, status |
|
| `deposit_transactions` | 거래 내역 | user_id, amount, status |
|
||||||
| `bank_notifications` | SMS 파싱 | depositor_name, amount, bank |
|
| `bank_notifications` | SMS 파싱 | depositor_name, amount, bank |
|
||||||
| `user_domains` | 도메인 소유권 | user_id, domain, verified (등록 시 자동 추가) |
|
| `user_domains` | 도메인 소유권 | user_id, domain, verified (등록 시 자동 추가) |
|
||||||
|
| `cloud_providers` | 클라우드 제공자 | name, api_base_url, enabled |
|
||||||
|
| `instance_specs` | 서버 사양표 | plan_id, vcpus, memory_mb, price_krw, regions |
|
||||||
|
| `server_orders` | 서버 주문 내역 | user_id, provider_id, status, ip_address |
|
||||||
|
| `user_servers` | 서버 소유권 | user_id, provider_instance_id, verified |
|
||||||
|
|
||||||
**AI Fallback:** OpenAI 미설정 시 Workers AI (Llama 3.1 8B) 자동 전환
|
**AI Fallback:** OpenAI 미설정 시 Workers AI (Llama 3.1 8B) 자동 전환
|
||||||
|
|
||||||
@@ -785,6 +811,7 @@ case 'new_tool':
|
|||||||
| `MAX_SUMMARIES_PER_USER` | 3 | 유지할 프로필 버전 수 |
|
| `MAX_SUMMARIES_PER_USER` | 3 | 유지할 프로필 버전 수 |
|
||||||
| `DOMAIN_OWNER_ID` | - | 도메인 관리 권한 Telegram ID |
|
| `DOMAIN_OWNER_ID` | - | 도메인 관리 권한 Telegram ID |
|
||||||
| `DEPOSIT_ADMIN_ID` | - | 예치금 관리 권한 Telegram ID |
|
| `DEPOSIT_ADMIN_ID` | - | 예치금 관리 권한 Telegram ID |
|
||||||
|
| `SERVER_ADMIN_ID` | - | 서버 관리 권한 Telegram ID |
|
||||||
|
|
||||||
**외부 API 엔드포인트 (커스터마이징 가능):**
|
**외부 API 엔드포인트 (커스터마이징 가능):**
|
||||||
| 변수 | 기본값 | 설명 |
|
| 변수 | 기본값 | 설명 |
|
||||||
@@ -811,6 +838,9 @@ case 'new_tool':
|
|||||||
| `NAMECHEAP_API_KEY_INTERNAL` | Namecheap API 키 (내부) | - |
|
| `NAMECHEAP_API_KEY_INTERNAL` | Namecheap API 키 (내부) | - |
|
||||||
| `BRAVE_API_KEY` | Brave Search API 키 | - |
|
| `BRAVE_API_KEY` | Brave Search API 키 | - |
|
||||||
| `DEPOSIT_API_SECRET` | Deposit API 인증 | - |
|
| `DEPOSIT_API_SECRET` | Deposit API 인증 | - |
|
||||||
|
| `LINODE_API_KEY` | Linode API 키 | - |
|
||||||
|
| `VULTR_API_KEY` | Vultr API 키 | - |
|
||||||
|
| `SERVER_ADMIN_ID` | 서버 관리 알림 Telegram ID | - |
|
||||||
|
|
||||||
**KV Namespaces:**
|
**KV Namespaces:**
|
||||||
| Binding | 설명 | 생성 명령 |
|
| Binding | 설명 | 생성 명령 |
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
* 🛠 **Function Calling**: 날씨, 검색, 계산, 시간 등 다양한 도구를 자연어로 호출
|
* 🛠 **Function Calling**: 날씨, 검색, 계산, 시간 등 다양한 도구를 자연어로 호출
|
||||||
* 💰 **예치금 시스템**: 은행 SMS 자동 파싱(AI 폴백 지원) 및 양방향 매칭을 통한 자동 충전
|
* 💰 **예치금 시스템**: 은행 SMS 자동 파싱(AI 폴백 지원) 및 양방향 매칭을 통한 자동 충전
|
||||||
* 🌐 **도메인 관리**: 도메인 검색, 추천(AI), 가격 조회, 등록, DNS 관리 통합
|
* 🌐 **도메인 관리**: 도메인 검색, 추천(AI), 가격 조회, 등록, DNS 관리 통합
|
||||||
|
* 🖥️ **서버 관리**: Linode/Vultr 인스턴스 검색, 비교, 주문, 소유권 관리
|
||||||
* ⚡ **서버리스**: Cloudflare Workers 위에서 동작하여 별도의 서버 관리 불필요
|
* ⚡ **서버리스**: Cloudflare Workers 위에서 동작하여 별도의 서버 관리 불필요
|
||||||
|
|
||||||
### 🚀 성능 최적화
|
### 🚀 성능 최적화
|
||||||
@@ -83,6 +84,11 @@ npx wrangler secret put BRAVE_API_KEY # Brave Search API 키
|
|||||||
|
|
||||||
# 예치금 API (namecheap-api 연동 시)
|
# 예치금 API (namecheap-api 연동 시)
|
||||||
npx wrangler secret put DEPOSIT_API_SECRET # 외부 서비스 연동용
|
npx wrangler secret put DEPOSIT_API_SECRET # 외부 서비스 연동용
|
||||||
|
|
||||||
|
# 서버 관리 (VPS/클라우드 기능 사용 시)
|
||||||
|
npx wrangler secret put LINODE_API_KEY # Linode API 키
|
||||||
|
npx wrangler secret put VULTR_API_KEY # Vultr API 키
|
||||||
|
npx wrangler secret put SERVER_ADMIN_ID # 서버 관리 알림 Telegram ID
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 환경별 설정 (선택)
|
#### 환경별 설정 (선택)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "wrangler dev",
|
"dev": "wrangler dev",
|
||||||
"deploy": "wrangler deploy",
|
"deploy": "sed -i '' 's/ENVIRONMENT = \"development\"/ENVIRONMENT = \"production\"/' wrangler.toml && wrangler deploy && sed -i '' 's/ENVIRONMENT = \"production\"/ENVIRONMENT = \"development\"/' wrangler.toml",
|
||||||
"db:create": "wrangler d1 create telegram-summary-db",
|
"db:create": "wrangler d1 create telegram-summary-db",
|
||||||
"db:init": "wrangler d1 execute telegram-summary-db --file=schema.sql",
|
"db:init": "wrangler d1 execute telegram-summary-db --file=schema.sql",
|
||||||
"db:init:local": "wrangler d1 execute telegram-summary-db --local --file=schema.sql",
|
"db:init:local": "wrangler d1 execute telegram-summary-db --local --file=schema.sql",
|
||||||
|
|||||||
39
schema.sql
39
schema.sql
@@ -100,3 +100,42 @@ CREATE INDEX IF NOT EXISTS idx_buffer_chat ON message_buffer(user_id, chat_id);
|
|||||||
CREATE INDEX IF NOT EXISTS idx_summary_user ON summaries(user_id, chat_id);
|
CREATE INDEX IF NOT EXISTS idx_summary_user ON summaries(user_id, chat_id);
|
||||||
CREATE INDEX IF NOT EXISTS idx_summary_latest ON summaries(user_id, chat_id, generation DESC);
|
CREATE INDEX IF NOT EXISTS idx_summary_latest ON summaries(user_id, chat_id, generation DESC);
|
||||||
CREATE INDEX IF NOT EXISTS idx_users_telegram ON users(telegram_id);
|
CREATE INDEX IF NOT EXISTS idx_users_telegram ON users(telegram_id);
|
||||||
|
|
||||||
|
-- 서버 주문 내역 테이블
|
||||||
|
CREATE TABLE IF NOT EXISTS server_orders (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
user_id INTEGER NOT NULL,
|
||||||
|
spec_id INTEGER NOT NULL,
|
||||||
|
status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending', 'provisioning', 'active', 'failed', 'cancelled', 'terminated')),
|
||||||
|
region TEXT NOT NULL,
|
||||||
|
provider_instance_id TEXT,
|
||||||
|
ip_address TEXT,
|
||||||
|
root_password TEXT,
|
||||||
|
price_paid INTEGER NOT NULL,
|
||||||
|
error_message TEXT,
|
||||||
|
provisioned_at DATETIME,
|
||||||
|
terminated_at DATETIME,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 사용자 서버 소유권 테이블
|
||||||
|
CREATE TABLE IF NOT EXISTS user_servers (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
user_id INTEGER NOT NULL,
|
||||||
|
order_id INTEGER UNIQUE NOT NULL,
|
||||||
|
provider_id INTEGER NOT NULL,
|
||||||
|
label TEXT,
|
||||||
|
verified INTEGER DEFAULT 0,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users(id),
|
||||||
|
FOREIGN KEY (order_id) REFERENCES server_orders(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 서버 관리 인덱스
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_server_orders_user ON server_orders(user_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_server_orders_status ON server_orders(status, created_at DESC);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_user_servers_user ON user_servers(user_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_user_servers_provider ON user_servers(provider_id);
|
||||||
|
|||||||
@@ -54,15 +54,22 @@ export class ConversationService {
|
|||||||
|
|
||||||
// 키보드 데이터 파싱
|
// 키보드 데이터 파싱
|
||||||
let keyboardData: KeyboardData | null = null;
|
let keyboardData: KeyboardData | null = null;
|
||||||
const keyboardMatch = responseText.match(/__KEYBOARD__(.+?)__END__\n?/);
|
// s 플래그로 .이 줄바꿈도 매칭하도록 (멀티라인 JSON 대응)
|
||||||
|
const keyboardMatch = responseText.match(/__KEYBOARD__(.+?)__END__\n?/s);
|
||||||
|
|
||||||
if (keyboardMatch) {
|
if (keyboardMatch) {
|
||||||
responseText = responseText.replace(/__KEYBOARD__.+?__END__\n?/, '');
|
console.log('[ConversationService] Keyboard marker detected:', keyboardMatch[1].substring(0, 100));
|
||||||
|
responseText = responseText.replace(/__KEYBOARD__.+?__END__\n?/s, '');
|
||||||
try {
|
try {
|
||||||
keyboardData = JSON.parse(keyboardMatch[1]) as KeyboardData;
|
keyboardData = JSON.parse(keyboardMatch[1]) as KeyboardData;
|
||||||
|
console.log('[ConversationService] Keyboard parsed successfully:', keyboardData.type);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('[ConversationService] Keyboard parsing error:', e);
|
console.error('[ConversationService] Keyboard parsing error:', e);
|
||||||
|
console.error('[ConversationService] Failed to parse:', keyboardMatch[1]);
|
||||||
}
|
}
|
||||||
|
} else if (responseText.includes('__KEYBOARD__')) {
|
||||||
|
console.warn('[ConversationService] Keyboard marker found but regex did not match');
|
||||||
|
console.warn('[ConversationService] Response preview:', responseText.substring(0, 200));
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -386,7 +386,15 @@ ${integratedProfile}
|
|||||||
- 도메인 추천, 도메인 제안, 도메인 아이디어 요청은 반드시 suggest_domains 도구를 사용하세요. 직접 도메인을 나열하지 마세요.
|
- 도메인 추천, 도메인 제안, 도메인 아이디어 요청은 반드시 suggest_domains 도구를 사용하세요. 직접 도메인을 나열하지 마세요.
|
||||||
- 도메인/TLD 가격 조회(".com 가격", ".io 가격" 등)는 manage_domain 도구의 action=price를 사용하세요.
|
- 도메인/TLD 가격 조회(".com 가격", ".io 가격" 등)는 manage_domain 도구의 action=price를 사용하세요.
|
||||||
- 기타 도메인 관련 요청(조회, 등록, 네임서버, WHOIS 등)은 manage_domain 도구를 사용하세요.
|
- 기타 도메인 관련 요청(조회, 등록, 네임서버, WHOIS 등)은 manage_domain 도구를 사용하세요.
|
||||||
- manage_deposit, manage_domain, suggest_domains 도구 결과는 그대로 전달하세요. 추가 질문이나 "도움이 필요하시면~" 같은 멘트를 붙이지 마세요.
|
- 서버 추천, 서버 상담, VPS, 클라우드 서버 관련 요청은 반드시 manage_server 도구를 사용하세요. 직접 사양을 추천하지 마세요.
|
||||||
|
- 서버 추천 요청 시:
|
||||||
|
1. 새로운 추천 요청은 이전 대화와 무관하게 처리
|
||||||
|
2. **반드시** 용도와 선호 위치를 먼저 질문: "어떤 용도로 사용하시나요? 서버 위치는 서울/도쿄/싱가포르 중 어디가 좋으세요?"
|
||||||
|
3. 위치를 답하면 region 파라미터로 전달 (region="Seoul" 또는 region="Tokyo" 또는 region="Singapore")
|
||||||
|
4. 용도와 위치를 알면 바로 추천. 예산/동접은 선택사항
|
||||||
|
5. 특정 기술(마인크래프트, Node.js 등)이 언급되면 lookup_docs로 요구사항 검색
|
||||||
|
6. manage_server 호출 시 현재 메시지에서 명시된 정보만 전달
|
||||||
|
- manage_deposit, manage_domain, suggest_domains, manage_server 도구 결과는 그대로 전달하세요. 추가 질문이나 "도움이 필요하시면~" 같은 멘트를 붙이지 마세요.
|
||||||
- 응답은 간결하고 도움이 되도록 한국어로 작성하세요.`;
|
- 응답은 간결하고 도움이 되도록 한국어로 작성하세요.`;
|
||||||
|
|
||||||
const recentContext = context.recentMessages.slice(-10).map((m) => ({
|
const recentContext = context.recentMessages.slice(-10).map((m) => ({
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { weatherTool, executeWeather } from './weather-tool';
|
|||||||
import { searchWebTool, lookupDocsTool, executeSearchWeb, executeLookupDocs } from './search-tool';
|
import { searchWebTool, lookupDocsTool, executeSearchWeb, executeLookupDocs } from './search-tool';
|
||||||
import { manageDomainTool, suggestDomainsTool, executeManageDomain, executeSuggestDomains } from './domain-tool';
|
import { manageDomainTool, suggestDomainsTool, executeManageDomain, executeSuggestDomains } from './domain-tool';
|
||||||
import { manageDepositTool, executeManageDeposit } from './deposit-tool';
|
import { manageDepositTool, executeManageDeposit } from './deposit-tool';
|
||||||
|
import { manageServerTool, executeManageServer } from './server-tool';
|
||||||
import { getCurrentTimeTool, calculateTool, executeGetCurrentTime, executeCalculate } from './utility-tools';
|
import { getCurrentTimeTool, calculateTool, executeGetCurrentTime, executeCalculate } from './utility-tools';
|
||||||
import type { Env } from '../types';
|
import type { Env } from '../types';
|
||||||
|
|
||||||
@@ -54,6 +55,21 @@ const SuggestDomainsArgsSchema = z.object({
|
|||||||
keywords: z.string().min(1).max(500),
|
keywords: z.string().min(1).max(500),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const ManageServerArgsSchema = z.object({
|
||||||
|
action: z.enum(['recommend', 'list_specs', 'order', 'my_servers', 'server_info', 'cancel_order']),
|
||||||
|
purpose: z.string().max(500).optional(),
|
||||||
|
budget: z.number().positive().max(100000000).optional(),
|
||||||
|
spec_id: z.number().int().positive().optional(),
|
||||||
|
order_id: z.number().int().positive().optional(),
|
||||||
|
region: z.string().max(50).optional(),
|
||||||
|
label: z.string().max(100).optional(),
|
||||||
|
provider: z.enum(['linode', 'vultr']).optional(),
|
||||||
|
expected_users: z.number().int().positive().max(1000000).optional(),
|
||||||
|
daily_traffic: z.number().int().positive().max(100000000).optional(),
|
||||||
|
storage_needs_gb: z.number().positive().max(10000).optional(),
|
||||||
|
tech_stack: z.string().max(200).optional(),
|
||||||
|
});
|
||||||
|
|
||||||
// All tools array (used by OpenAI API)
|
// All tools array (used by OpenAI API)
|
||||||
export const tools = [
|
export const tools = [
|
||||||
weatherTool,
|
weatherTool,
|
||||||
@@ -63,6 +79,7 @@ export const tools = [
|
|||||||
lookupDocsTool,
|
lookupDocsTool,
|
||||||
manageDomainTool,
|
manageDomainTool,
|
||||||
manageDepositTool,
|
manageDepositTool,
|
||||||
|
manageServerTool,
|
||||||
suggestDomainsTool,
|
suggestDomainsTool,
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -70,6 +87,7 @@ export const tools = [
|
|||||||
export const TOOL_CATEGORIES: Record<string, string[]> = {
|
export const TOOL_CATEGORIES: Record<string, string[]> = {
|
||||||
domain: [manageDomainTool.function.name, suggestDomainsTool.function.name],
|
domain: [manageDomainTool.function.name, suggestDomainsTool.function.name],
|
||||||
deposit: [manageDepositTool.function.name],
|
deposit: [manageDepositTool.function.name],
|
||||||
|
server: [manageServerTool.function.name],
|
||||||
weather: [weatherTool.function.name],
|
weather: [weatherTool.function.name],
|
||||||
search: [searchWebTool.function.name, lookupDocsTool.function.name],
|
search: [searchWebTool.function.name, lookupDocsTool.function.name],
|
||||||
utility: [getCurrentTimeTool.function.name, calculateTool.function.name],
|
utility: [getCurrentTimeTool.function.name, calculateTool.function.name],
|
||||||
@@ -79,6 +97,7 @@ export const TOOL_CATEGORIES: Record<string, string[]> = {
|
|||||||
export const CATEGORY_PATTERNS: Record<string, RegExp> = {
|
export const CATEGORY_PATTERNS: Record<string, RegExp> = {
|
||||||
domain: /도메인|네임서버|whois|dns|tld|등록|\.com|\.net|\.io|\.kr|\.org/i,
|
domain: /도메인|네임서버|whois|dns|tld|등록|\.com|\.net|\.io|\.kr|\.org/i,
|
||||||
deposit: /입금|충전|잔액|계좌|예치금|송금|돈/i,
|
deposit: /입금|충전|잔액|계좌|예치금|송금|돈/i,
|
||||||
|
server: /서버|VPS|호스팅|클라우드|리눅스|우분투|인스턴스|가상서버|Linode|Vultr|VM/i,
|
||||||
weather: /날씨|기온|비|눈|맑|흐림|더워|추워/i,
|
weather: /날씨|기온|비|눈|맑|흐림|더워|추워/i,
|
||||||
search: /검색|찾아|뭐야|뉴스|최신/i,
|
search: /검색|찾아|뭐야|뉴스|최신/i,
|
||||||
};
|
};
|
||||||
@@ -196,6 +215,15 @@ export async function executeTool(
|
|||||||
return executeManageDeposit(result.data, env, telegramUserId, db);
|
return executeManageDeposit(result.data, env, telegramUserId, db);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'manage_server': {
|
||||||
|
const result = ManageServerArgsSchema.safeParse(args);
|
||||||
|
if (!result.success) {
|
||||||
|
logger.error('Invalid server args', new Error(result.error.message), { args });
|
||||||
|
return `❌ Invalid arguments: ${result.error.issues.map(e => e.message).join(', ')}`;
|
||||||
|
}
|
||||||
|
return executeManageServer(result.data, env, telegramUserId, db, env?.CLOUD_DB);
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return `알 수 없는 도구: ${name}`;
|
return `알 수 없는 도구: ${name}`;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user