diff --git a/src/agents/deposit-agent.ts b/src/agents/deposit-agent.ts index 0386b5c..7d2175b 100644 --- a/src/agents/deposit-agent.ts +++ b/src/agents/deposit-agent.ts @@ -17,7 +17,7 @@ import { createLogger } from '../utils/logger'; import { executeWithOptimisticLock, OptimisticLockError } from '../utils/optimistic-lock'; import { TRANSACTION_STATUS, TRANSACTION_TYPE } from '../constants'; -import type { Env, ManageDepositArgs, DepositFunctionResult, DepositSession, DepositSessionStatus, OpenAIToolCall, OpenAIMessage, OpenAIAPIResponse } from '../types'; +import type { Env, ManageDepositArgs, DepositFunctionResult, DepositSession, OpenAIToolCall, OpenAIAPIResponse } from '../types'; import { SessionManager } from '../utils/session-manager'; import { getSessionConfig } from '../constants/agent-config'; diff --git a/src/agents/domain-agent.ts b/src/agents/domain-agent.ts index 99272af..b8bb488 100644 --- a/src/agents/domain-agent.ts +++ b/src/agents/domain-agent.ts @@ -8,7 +8,7 @@ * - 추천 후 사용자 선택 및 등록 흐름 */ -import type { Env, DomainSession, DomainSessionStatus } from '../types'; +import type { Env, DomainSession } from '../types'; import { createLogger } from '../utils/logger'; import { executeDomainAction, executeSuggestDomains } from '../tools/domain-tool'; import { DomainSessionManager } from '../utils/session-manager'; @@ -137,7 +137,7 @@ const DOMAIN_TOOLS = [ ]; // Import OpenAI types from centralized types -import type { OpenAIToolCall, OpenAIMessage, OpenAIAPIResponse } from '../types'; +import type { OpenAIToolCall, OpenAIAPIResponse } from '../types'; /** * Domain Expert AI 호출 (Function Calling 지원) diff --git a/src/agents/server-agent.ts b/src/agents/server-agent.ts index b826a84..702ca98 100644 --- a/src/agents/server-agent.ts +++ b/src/agents/server-agent.ts @@ -15,7 +15,7 @@ * 4. Expected: Order confirmation */ -import type { Env, ServerSession, ServerSessionStatus, BandwidthInfo, RecommendResponse, OpenAIToolCall, OpenAIMessage, OpenAIAPIResponse } from '../types'; +import type { Env, ServerSession, BandwidthInfo, RecommendResponse, OpenAIToolCall, OpenAIAPIResponse } from '../types'; import { createLogger } from '../utils/logger'; import { executeSearchWeb, executeLookupDocs } from '../tools/search-tool'; import { formatTrafficInfo } from '../utils/formatters'; diff --git a/src/agents/troubleshoot-agent.ts b/src/agents/troubleshoot-agent.ts index b894eac..b776663 100644 --- a/src/agents/troubleshoot-agent.ts +++ b/src/agents/troubleshoot-agent.ts @@ -14,7 +14,7 @@ * 4. Expected: Session deleted */ -import type { Env, TroubleshootSession, TroubleshootSessionStatus, OpenAIToolCall, OpenAIMessage, OpenAIAPIResponse } from '../types'; +import type { Env, TroubleshootSession, OpenAIToolCall, OpenAIAPIResponse } from '../types'; import { createLogger } from '../utils/logger'; import { executeSearchWeb, executeLookupDocs } from '../tools/search-tool'; import { SessionManager } from '../utils/session-manager'; diff --git a/src/routes/api/chat.ts b/src/routes/api/chat.ts index 2f2a2a7..1c418ec 100644 --- a/src/routes/api/chat.ts +++ b/src/routes/api/chat.ts @@ -331,8 +331,10 @@ async function handleChatApi(request: Request, env: Env): Promise { const orderData = JSON.parse(orderSessionData); // 1. 서버 세션에서 가격 정보 가져오기 - const { getServerSession, deleteServerSession } = await import('../../agents/server-agent'); - const session = await getServerSession(env.DB, telegramUserId); + const { ServerSessionManager } = await import('../../utils/session-manager'); + const { getSessionConfig } = await import('../../constants/agent-config'); + const sessionManager = new ServerSessionManager(getSessionConfig('server')); + const session = await sessionManager.get(env.DB, telegramUserId); if (!session || !session.last_recommendation) { await env.SESSION_KV.delete(orderSessionKey); @@ -348,7 +350,7 @@ async function handleChatApi(request: Request, env: Env): Promise { const selected = session.last_recommendation.recommendations[orderData.index]; if (!selected) { await env.SESSION_KV.delete(orderSessionKey); - await deleteServerSession(env.DB, telegramUserId); + await sessionManager.delete(env.DB, telegramUserId); const processingTimeMs = Date.now() - startTime; return Response.json({ @@ -409,7 +411,7 @@ async function handleChatApi(request: Request, env: Env): Promise { // 5. 세션 정리 await env.SESSION_KV.delete(orderSessionKey); - await deleteServerSession(env.DB, telegramUserId); + await sessionManager.delete(env.DB, telegramUserId); // 6. 즉시 응답 const processingTimeMs = Date.now() - startTime; diff --git a/src/routes/handlers/message-handler.ts b/src/routes/handlers/message-handler.ts index a275403..bc07d27 100644 --- a/src/routes/handlers/message-handler.ts +++ b/src/routes/handlers/message-handler.ts @@ -121,8 +121,10 @@ export async function handleMessage( const orderData = JSON.parse(orderSessionData); // 1. 서버 세션에서 가격 정보 가져오기 - const { getServerSession, deleteServerSession } = await import('../../agents/server-agent'); - const session = await getServerSession(env.DB, telegramUserId); + const { ServerSessionManager } = await import('../../utils/session-manager'); + const { getSessionConfig } = await import('../../constants/agent-config'); + const sessionManager = new ServerSessionManager(getSessionConfig('server')); + const session = await sessionManager.get(env.DB, telegramUserId); if (!session || !session.last_recommendation) { await env.SESSION_KV.delete(orderSessionKey); @@ -137,7 +139,7 @@ export async function handleMessage( const selected = session.last_recommendation.recommendations[orderData.index]; if (!selected) { await env.SESSION_KV.delete(orderSessionKey); - await deleteServerSession(env.DB, telegramUserId); + await sessionManager.delete(env.DB, telegramUserId); await sendMessage(env.BOT_TOKEN, chatId, '❌ 선택한 서버를 찾을 수 없습니다.'); return; } @@ -190,7 +192,7 @@ export async function handleMessage( // 5. 세션 정리 await env.SESSION_KV.delete(orderSessionKey); - await deleteServerSession(env.DB, telegramUserId); + await sessionManager.delete(env.DB, telegramUserId); // 6. 즉시 응답 await sendMessage( diff --git a/src/tools/server-tool.ts b/src/tools/server-tool.ts index 10962e9..79cd861 100644 --- a/src/tools/server-tool.ts +++ b/src/tools/server-tool.ts @@ -663,9 +663,6 @@ export async function executeServerAction( switch (action) { case 'start_consultation': { - // Import session functions - const { createServerSession, saveServerSession } = await import('../agents/server-agent'); - if (!telegramUserId) { return '🚫 사용자 인증이 필요합니다.'; } @@ -674,10 +671,8 @@ export async function executeServerAction( return '🚫 세션 저장소가 설정되지 않았습니다.'; } - const session = createServerSession(telegramUserId, 'gathering'); - await saveServerSession(env.DB, session); - - logger.info('상담 세션 생성', { userId: maskUserId(telegramUserId) }); + // Note: Session is created automatically in processServerConsultation when first message arrives + logger.info('상담 시작 요청', { userId: maskUserId(telegramUserId) }); return '안녕하세요! 서버 추천을 도와드리겠습니다. 😊\n\n어떤 서비스를 운영하실 건가요?\n\n1. 웹 서비스 (SaaS, 랜딩페이지)\n2. 모바일 앱 백엔드\n3. AI/ML 서비스 (챗봇, 모델 서빙)\n4. 게임 서버\n5. Discord/Telegram 봇\n6. 자동화 서버 (n8n, 크롤링)\n7. 미디어 스트리밍\n8. 개발/테스트 환경\n9. 데이터베이스 서버\n10. 기타 (직접 입력)\n\n번호나 용도를 말씀해주세요!'; } @@ -702,8 +697,6 @@ export async function executeServerAction( } case 'cancel_consultation': { - const { deleteServerSession } = await import('../agents/server-agent'); - if (!telegramUserId) { return '🚫 사용자 인증이 필요합니다.'; } @@ -712,7 +705,11 @@ export async function executeServerAction( return '🚫 세션 저장소가 설정되지 않았습니다.'; } - await deleteServerSession(env.DB, telegramUserId); + // Import sessionManager to delete session + const { ServerSessionManager } = await import('../utils/session-manager'); + const { getSessionConfig } = await import('../constants/agent-config'); + const sessionManager = new ServerSessionManager(getSessionConfig('server')); + await sessionManager.delete(env.DB, telegramUserId); logger.info('상담 세션 취소', { userId: maskUserId(telegramUserId) }); @@ -758,14 +755,16 @@ export async function executeServerAction( // 세션에 추천 결과 저장 (선택 기능 활성화) if (telegramUserId && env?.DB && recommendationData.recommendations && recommendationData.recommendations.length > 0) { try { - const { getServerSession, saveServerSession, createServerSession } = await import('../agents/server-agent'); + const { ServerSessionManager } = await import('../utils/session-manager'); + const { getSessionConfig } = await import('../constants/agent-config'); + const sessionManager = new ServerSessionManager(getSessionConfig('server')); // 기존 세션 조회 또는 새로 생성 - let session = await getServerSession(env.DB, telegramUserId); + let session = await sessionManager.get(env.DB, telegramUserId); if (!session) { // 세션이 없으면 새로 생성 - session = createServerSession(telegramUserId, 'selecting'); + session = sessionManager.create(telegramUserId, 'selecting'); session.collected_info = { useCase: use_case, scale: expected_users <= 50 ? 'personal' : 'business', @@ -809,7 +808,7 @@ export async function executeServerAction( session.status = 'selecting'; session.updated_at = Date.now(); - await saveServerSession(env.DB, session); + await sessionManager.save(env.DB, session); logger.info('추천 결과 세션 저장 완료', { userId: telegramUserId, recommendationCount: session.last_recommendation.recommendations.length, @@ -1324,8 +1323,10 @@ export async function executeServerDelete( // Clear server consultation session (if any) try { - const { deleteServerSession } = await import('../agents/server-agent'); - await deleteServerSession(env.DB, telegramUserId); + const { ServerSessionManager } = await import('../utils/session-manager'); + const { getSessionConfig } = await import('../constants/agent-config'); + const sessionManager = new ServerSessionManager(getSessionConfig('server')); + await sessionManager.delete(env.DB, telegramUserId); } catch (error) { provisionLogger.error('서버 세션 삭제 실패 (무시)', error as Error); } @@ -1413,8 +1414,10 @@ export async function executeServerOrder( // Clear server consultation session try { - const { deleteServerSession } = await import('../agents/server-agent'); - await deleteServerSession(env.DB, telegramUserId); + const { ServerSessionManager } = await import('../utils/session-manager'); + const { getSessionConfig } = await import('../constants/agent-config'); + const sessionManager = new ServerSessionManager(getSessionConfig('server')); + await sessionManager.delete(env.DB, telegramUserId); } catch (error) { provisionLogger.error('서버 세션 삭제 실패 (무시)', error as Error); } diff --git a/src/tools/troubleshoot-tool.ts b/src/tools/troubleshoot-tool.ts index 0720e5a..71db784 100644 --- a/src/tools/troubleshoot-tool.ts +++ b/src/tools/troubleshoot-tool.ts @@ -35,15 +35,17 @@ export async function executeManageTroubleshoot( return '🚫 트러블슈팅 기능을 사용할 수 없습니다.'; } - const { getTroubleshootSession, createTroubleshootSession, saveTroubleshootSession, deleteTroubleshootSession } = await import('../agents/troubleshoot-agent'); + const { SessionManager } = await import('../utils/session-manager'); + const { getSessionConfig } = await import('../constants/agent-config'); + const sessionManager = new SessionManager(getSessionConfig('troubleshoot')); if (action === 'cancel') { - await deleteTroubleshootSession(env.DB, telegramUserId); + await sessionManager.delete(env.DB, telegramUserId); return '✅ 트러블슈팅 세션이 취소되었습니다.'; } // action === 'start' - const existingSession = await getTroubleshootSession(env.DB, telegramUserId); + const existingSession = await sessionManager.get(env.DB, telegramUserId); if (existingSession && existingSession.status !== 'completed') { return '이미 진행 중인 트러블슈팅 세션이 있습니다. 계속 진행해주세요.\n\n현재까지 파악된 정보:\n' + @@ -52,9 +54,9 @@ export async function executeManageTroubleshoot( } // Create new session - const newSession = createTroubleshootSession(telegramUserId, 'gathering'); + const newSession = sessionManager.create(telegramUserId, 'gathering'); - await saveTroubleshootSession(env.DB, newSession); + await sessionManager.save(env.DB, newSession); logger.info('트러블슈팅 세션 시작', { userId: telegramUserId }); diff --git a/src/utils/session-manager.ts b/src/utils/session-manager.ts index 47d5a43..2f1eeef 100644 --- a/src/utils/session-manager.ts +++ b/src/utils/session-manager.ts @@ -123,7 +123,6 @@ export class SessionManager { // Build additional columns from subclass const additionalColumns = this.getAdditionalColumns(session); const additionalColumnNames = Object.keys(additionalColumns); - const additionalColumnPlaceholders = additionalColumnNames.map(() => '?').join(', '); const additionalColumnValues = Object.values(additionalColumns); // Build SQL with optional additional columns @@ -277,10 +276,10 @@ export class SessionManager { * Override this method in subclasses to parse additional fields from DB result * (e.g., target_domain for DomainSession, last_recommendation for ServerSession) * - * @param result - Raw DB result + * @param _result - Raw DB result * @returns Additional fields to merge into session */ - protected parseAdditionalFields(result: Record): Partial { + protected parseAdditionalFields(_result: Record): Partial { return {}; } @@ -288,10 +287,10 @@ export class SessionManager { * Override this method in subclasses to provide additional columns for saving * (e.g., target_domain for DomainSession, last_recommendation for ServerSession) * - * @param session - Session to save + * @param _session - Session to save * @returns Additional column values */ - protected getAdditionalColumns(session: T): Record { + protected getAdditionalColumns(_session: T): Record { return {}; } }