diff --git a/src/commands.ts b/src/commands.ts
index c6d895e..0ac1f03 100644
--- a/src/commands.ts
+++ b/src/commands.ts
@@ -1,5 +1,11 @@
import { Env } from './types';
import { getConversationContext, getLatestSummary } from './summary-service';
+import {
+ getConversationHistory,
+ searchConversations,
+ getConversationStats,
+ extractKeywords
+} from './services/conversation-storage';
export async function handleCommand(
env: Env,
@@ -26,6 +32,8 @@ export async function handleCommand(
/server - 내 서버 목록
/security - DDoS 방어 현황
/phantomx - PhantomX VPN
+/history - 대화 기록
+/search - 대화 검색
무엇을 도와드릴까요?`;
@@ -38,6 +46,8 @@ export async function handleCommand(
/server - 내 서버 목록
/security - DDoS 방어 서비스
/phantomx - PhantomX VPN 서비스
+/history [N] - 대화 기록 (기본 20개)
+/search 키워드 - 대화 검색
자연어로 요청:
• "도메인 등록" - 도메인 검색/등록
@@ -90,19 +100,88 @@ ${summary.summary}
업데이트: ${createdAt}`;
}
+ case '/history': {
+ const limit = _args ? parseInt(_args, 10) : 20;
+ const validLimit = Math.min(Math.max(limit, 1), 100); // 1-100 제한
+
+ const messages = await getConversationHistory(env.DB, chatId, validLimit);
+
+ if (messages.length === 0) {
+ return '📜 저장된 대화가 없습니다.';
+ }
+
+ const formatted = messages.map(m => {
+ const time = m.created_at
+ ? new Date(m.created_at).toLocaleString('ko-KR', {
+ timeZone: 'Asia/Seoul',
+ month: '2-digit',
+ day: '2-digit',
+ hour: '2-digit',
+ minute: '2-digit'
+ })
+ : '';
+ const role = m.role === 'user' ? '나' : '봇';
+ const content = m.content.length > 50
+ ? m.content.substring(0, 50) + '...'
+ : m.content;
+ return `[${time}] ${role}: ${content}`;
+ }).join('\n');
+
+ return `📜 최근 대화 (${messages.length}개)\n\n${formatted}\n\n/history 50 으로 더 보기`;
+ }
+
+ case '/search': {
+ if (!_args || _args.trim().length < 2) {
+ return '🔍 검색어를 입력해주세요.\n예: /search 도메인';
+ }
+
+ const keywords = extractKeywords(_args);
+ if (keywords.length === 0) {
+ return '🔍 유효한 검색어가 없습니다.';
+ }
+
+ const results = await searchConversations(env.DB, chatId, keywords, 15);
+
+ if (results.length === 0) {
+ return `🔍 "${_args}" 검색 결과가 없습니다.`;
+ }
+
+ const formatted = results.map(m => {
+ const date = m.created_at
+ ? new Date(m.created_at).toLocaleDateString('ko-KR')
+ : '';
+ const content = m.content.length > 60
+ ? m.content.substring(0, 60) + '...'
+ : m.content;
+ return `[${date}] ${content}`;
+ }).join('\n');
+
+ return `🔍 "${_args}" 검색 결과 (${results.length}건)\n\n${formatted}`;
+ }
+
case '/stats': {
- const ctx = await getConversationContext(env.DB, userId, chatId);
- const profileCount = await env.DB
- .prepare('SELECT COUNT(*) as cnt FROM summaries WHERE user_id = ?')
- .bind(userId)
- .first<{ cnt: number }>();
+ const stats = await getConversationStats(env.DB, chatId);
+
+ if (!stats) {
+ return '📈 아직 대화 기록이 없습니다.';
+ }
+
+ const firstDate = stats.first_message_at
+ ? new Date(stats.first_message_at).toLocaleDateString('ko-KR')
+ : '없음';
+ const lastDate = stats.last_message_at
+ ? new Date(stats.last_message_at).toLocaleDateString('ko-KR')
+ : '없음';
return `📈 대화 통계
-총 메시지: ${ctx.totalMessages}개
-프로필 버전: ${ctx.previousSummary?.generation ?? 0}
-저장된 프로필: ${profileCount?.cnt ?? 0}개
-버퍼 대기: ${ctx.recentMessages.length}개`;
+총 메시지: ${stats.message_count.toLocaleString()}개
+첫 대화: ${firstDate}
+최근 대화: ${lastDate}
+아카이브된 요약: ${stats.archived_summaries}개
+
+/history - 대화 기록 보기
+/search 키워드 - 대화 검색`;
}
case '/domain': {