feat: add Server Expert AI with search/docs tools for trend-aware recommendations
- Add server-agent.ts with 30-year senior architect persona - Implement KV-based session management for multi-turn conversations - Add search_trends (Brave Search) and lookup_framework_docs (Context7) tools - Function Calling support with max 3 tool calls per request - Auto-infer tech stack and expected users from use case/scale - Prohibit competitor provider mentions (AWS, GCP, Azure, etc.) - Simplify main AI system prompt, delegate complex logic to expert AI Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -136,32 +136,33 @@ export const manageServerTool = {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'manage_server',
|
||||
description: '클라우드 서버 관리 및 추천. "서버", "VPS", "클라우드", "호스팅" 등의 키워드가 포함되면 사용하세요.',
|
||||
description: '클라우드 서버 관리 및 추천. 서버/VPS/클라우드/호스팅 관련 요청 시 사용. 상담 시작: start_consultation',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
action: {
|
||||
type: 'string',
|
||||
enum: ['recommend', 'order', 'start', 'stop', 'delete', 'list'],
|
||||
description: 'recommend: 서버 추천, order: 서버 신청 (준비 중), start: 서버 켜기 (준비 중), stop: 서버 끄기 (준비 중), delete: 서버 해지 (준비 중), list: 내 서버 목록 (준비 중)',
|
||||
enum: ['recommend', 'order', 'start', 'stop', 'delete', 'list',
|
||||
'start_consultation', 'continue_consultation', 'cancel_consultation'],
|
||||
description: 'start_consultation: 서버 추천 상담 시작, continue_consultation: 상담 계속, recommend: 직접 추천',
|
||||
},
|
||||
tech_stack: {
|
||||
type: 'array',
|
||||
items: { type: 'string' },
|
||||
description: '사용할 기술 스택 (예: ["nodejs", "nginx", "postgresql"]). recommend action에서 필수',
|
||||
description: '기술 스택. 용도에서 추론 (블로그→wordpress, 쇼핑몰→ecommerce, 커뮤니티→php,mysql). 모르면 ["web"]',
|
||||
},
|
||||
expected_users: {
|
||||
type: 'number',
|
||||
description: '예상 동시 접속자 수. recommend action에서 필수',
|
||||
description: '예상 사용자 수. 모르면 개인용=100, 사업용=500 사용',
|
||||
},
|
||||
use_case: {
|
||||
type: 'string',
|
||||
description: '사용 목적 설명 (예: "웹사이트 호스팅", "API 서버"). recommend action에서 필수',
|
||||
description: '용도 (예: "블로그", "쇼핑몰", "커뮤니티")',
|
||||
},
|
||||
traffic_pattern: {
|
||||
type: 'string',
|
||||
enum: ['steady', 'spiky', 'growing'],
|
||||
description: '트래픽 패턴. steady: 일정한 트래픽, spiky: 순간 급증, growing: 점진적 성장. recommend action에서 선택',
|
||||
description: '생략 가능. 기본값: steady',
|
||||
},
|
||||
region_preference: {
|
||||
type: 'array',
|
||||
@@ -189,6 +190,10 @@ export const manageServerTool = {
|
||||
type: 'string',
|
||||
description: '서버 라벨 (예: "myapp-prod"). order action에서 필수',
|
||||
},
|
||||
message: {
|
||||
type: 'string',
|
||||
description: '사용자 메시지. continue_consultation action에서 필수',
|
||||
},
|
||||
},
|
||||
required: ['action'],
|
||||
},
|
||||
@@ -314,7 +319,7 @@ function formatRecommendations(data: RecommendResponse): string {
|
||||
}
|
||||
|
||||
// 서버 작업 직접 실행
|
||||
async function executeServerAction(
|
||||
export async function executeServerAction(
|
||||
action: string,
|
||||
args: {
|
||||
tech_stack?: string[];
|
||||
@@ -327,6 +332,7 @@ async function executeServerAction(
|
||||
server_id?: string;
|
||||
region_code?: string;
|
||||
label?: string;
|
||||
message?: string;
|
||||
},
|
||||
env?: Env,
|
||||
telegramUserId?: string
|
||||
@@ -338,6 +344,76 @@ async function executeServerAction(
|
||||
});
|
||||
|
||||
switch (action) {
|
||||
case 'start_consultation': {
|
||||
// Import session functions
|
||||
const { saveServerSession } = await import('../server-agent');
|
||||
|
||||
if (!telegramUserId) {
|
||||
return '🚫 사용자 인증이 필요합니다.';
|
||||
}
|
||||
|
||||
if (!env?.SESSION_KV) {
|
||||
return '🚫 세션 저장소가 설정되지 않았습니다.';
|
||||
}
|
||||
|
||||
const session: import('../types').ServerSession = {
|
||||
telegramUserId,
|
||||
status: 'gathering',
|
||||
collectedInfo: {},
|
||||
messages: [],
|
||||
createdAt: Date.now(),
|
||||
updatedAt: Date.now(),
|
||||
};
|
||||
|
||||
await saveServerSession(env.SESSION_KV, telegramUserId, session);
|
||||
|
||||
logger.info('상담 세션 생성', { userId: maskUserId(telegramUserId) });
|
||||
|
||||
return '안녕하세요! 서버 추천을 도와드리겠습니다. 😊\n\n어떤 서비스를 운영하실 건가요?\n예: 블로그, 쇼핑몰, 커뮤니티, API 서버 등';
|
||||
}
|
||||
|
||||
case 'continue_consultation': {
|
||||
const { getServerSession, processServerConsultation } = await import('../server-agent');
|
||||
|
||||
if (!telegramUserId) {
|
||||
return '🚫 사용자 인증이 필요합니다.';
|
||||
}
|
||||
|
||||
if (!env?.SESSION_KV) {
|
||||
return '🚫 세션 저장소가 설정되지 않았습니다.';
|
||||
}
|
||||
|
||||
if (!args.message) {
|
||||
return '🚫 메시지가 필요합니다.';
|
||||
}
|
||||
|
||||
const session = await getServerSession(env.SESSION_KV, telegramUserId);
|
||||
if (!session) {
|
||||
return '세션이 만료되었습니다. 다시 시작하려면 "서버 추천"이라고 말씀해주세요.';
|
||||
}
|
||||
|
||||
const result = await processServerConsultation(args.message, session, env);
|
||||
return result;
|
||||
}
|
||||
|
||||
case 'cancel_consultation': {
|
||||
const { deleteServerSession } = await import('../server-agent');
|
||||
|
||||
if (!telegramUserId) {
|
||||
return '🚫 사용자 인증이 필요합니다.';
|
||||
}
|
||||
|
||||
if (!env?.SESSION_KV) {
|
||||
return '🚫 세션 저장소가 설정되지 않았습니다.';
|
||||
}
|
||||
|
||||
await deleteServerSession(env.SESSION_KV, telegramUserId);
|
||||
|
||||
logger.info('상담 세션 취소', { userId: maskUserId(telegramUserId) });
|
||||
|
||||
return '상담이 취소되었습니다. 다시 시작하려면 "서버 추천"이라고 말씀해주세요.';
|
||||
}
|
||||
|
||||
case 'recommend': {
|
||||
const { tech_stack, expected_users, use_case, traffic_pattern, region_preference, budget_limit, lang } = args;
|
||||
|
||||
@@ -438,6 +514,7 @@ export async function executeManageServer(
|
||||
server_id?: string;
|
||||
region_code?: string;
|
||||
label?: string;
|
||||
message?: string;
|
||||
},
|
||||
env?: Env,
|
||||
telegramUserId?: string
|
||||
|
||||
Reference in New Issue
Block a user