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:
@@ -54,15 +54,22 @@ export class ConversationService {
|
||||
|
||||
// 키보드 데이터 파싱
|
||||
let keyboardData: KeyboardData | null = null;
|
||||
const keyboardMatch = responseText.match(/__KEYBOARD__(.+?)__END__\n?/);
|
||||
// s 플래그로 .이 줄바꿈도 매칭하도록 (멀티라인 JSON 대응)
|
||||
const keyboardMatch = responseText.match(/__KEYBOARD__(.+?)__END__\n?/s);
|
||||
|
||||
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 {
|
||||
keyboardData = JSON.parse(keyboardMatch[1]) as KeyboardData;
|
||||
console.log('[ConversationService] Keyboard parsed successfully:', keyboardData.type);
|
||||
} catch (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 {
|
||||
|
||||
@@ -386,7 +386,15 @@ ${integratedProfile}
|
||||
- 도메인 추천, 도메인 제안, 도메인 아이디어 요청은 반드시 suggest_domains 도구를 사용하세요. 직접 도메인을 나열하지 마세요.
|
||||
- 도메인/TLD 가격 조회(".com 가격", ".io 가격" 등)는 manage_domain 도구의 action=price를 사용하세요.
|
||||
- 기타 도메인 관련 요청(조회, 등록, 네임서버, 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) => ({
|
||||
|
||||
@@ -8,6 +8,7 @@ import { weatherTool, executeWeather } from './weather-tool';
|
||||
import { searchWebTool, lookupDocsTool, executeSearchWeb, executeLookupDocs } from './search-tool';
|
||||
import { manageDomainTool, suggestDomainsTool, executeManageDomain, executeSuggestDomains } from './domain-tool';
|
||||
import { manageDepositTool, executeManageDeposit } from './deposit-tool';
|
||||
import { manageServerTool, executeManageServer } from './server-tool';
|
||||
import { getCurrentTimeTool, calculateTool, executeGetCurrentTime, executeCalculate } from './utility-tools';
|
||||
import type { Env } from '../types';
|
||||
|
||||
@@ -54,6 +55,21 @@ const SuggestDomainsArgsSchema = z.object({
|
||||
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)
|
||||
export const tools = [
|
||||
weatherTool,
|
||||
@@ -63,6 +79,7 @@ export const tools = [
|
||||
lookupDocsTool,
|
||||
manageDomainTool,
|
||||
manageDepositTool,
|
||||
manageServerTool,
|
||||
suggestDomainsTool,
|
||||
];
|
||||
|
||||
@@ -70,6 +87,7 @@ export const tools = [
|
||||
export const TOOL_CATEGORIES: Record<string, string[]> = {
|
||||
domain: [manageDomainTool.function.name, suggestDomainsTool.function.name],
|
||||
deposit: [manageDepositTool.function.name],
|
||||
server: [manageServerTool.function.name],
|
||||
weather: [weatherTool.function.name],
|
||||
search: [searchWebTool.function.name, lookupDocsTool.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> = {
|
||||
domain: /도메인|네임서버|whois|dns|tld|등록|\.com|\.net|\.io|\.kr|\.org/i,
|
||||
deposit: /입금|충전|잔액|계좌|예치금|송금|돈/i,
|
||||
server: /서버|VPS|호스팅|클라우드|리눅스|우분투|인스턴스|가상서버|Linode|Vultr|VM/i,
|
||||
weather: /날씨|기온|비|눈|맑|흐림|더워|추워/i,
|
||||
search: /검색|찾아|뭐야|뉴스|최신/i,
|
||||
};
|
||||
@@ -196,6 +215,15 @@ export async function executeTool(
|
||||
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:
|
||||
return `알 수 없는 도구: ${name}`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user