feat: add /history and /search commands
- Add /history [N] command to view recent conversation history - Default 20 messages, max 100 - Shows date/time, role (user/bot), and message preview - Add /search <keyword> command to search conversations - Uses extractKeywords() for smart keyword extraction - Shows up to 15 results with date and content preview - Update /stats command to use new conversation-storage service - Shows total message count, first/last message dates - Shows archived summary count - Links to /history and /search commands - Update /start and /help commands to include new commands - Import conversation-storage functions Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -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 키워드 - 대화 검색
|
||||
|
||||
<b>자연어로 요청:</b>
|
||||
• "도메인 등록" - 도메인 검색/등록
|
||||
@@ -90,19 +100,88 @@ ${summary.summary}
|
||||
<i>업데이트: ${createdAt}</i>`;
|
||||
}
|
||||
|
||||
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 `📜 <b>최근 대화</b> (${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 `🔍 <b>"${_args}"</b> 검색 결과 (${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 `📈 <b>대화 통계</b>
|
||||
|
||||
총 메시지: ${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': {
|
||||
|
||||
Reference in New Issue
Block a user