Integrate new conversation-storage.ts system while maintaining backward compatibility with existing message_buffer system: - Import saveConversationMessage from conversation-storage.ts - Save user messages to both new system (role: 'user') and old buffer - Save assistant responses to both new system (role: 'assistant') and old buffer - Preserve existing functionality during migration period Changes: - Add saveConversationMessage import - Call saveConversationMessage before addToBuffer for user messages - Call saveConversationMessage before addToBuffer for bot responses - Updated step numbering in comments (1-7) Note: Old buffer system will be removed after migration is complete. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
107 lines
3.5 KiB
TypeScript
107 lines
3.5 KiB
TypeScript
import type { Env, KeyboardData } from '../types';
|
|
import {
|
|
addToBuffer,
|
|
processAndSummarize,
|
|
generateAIResponse,
|
|
} from '../summary-service';
|
|
import { sendChatAction } from '../telegram';
|
|
import { createLogger } from '../utils/logger';
|
|
import { saveConversationMessage } from './conversation-storage';
|
|
|
|
const logger = createLogger('conversation');
|
|
|
|
export interface ConversationResult {
|
|
responseText: string;
|
|
isProfileUpdated: boolean;
|
|
keyboardData?: KeyboardData | null;
|
|
}
|
|
|
|
export class ConversationService {
|
|
constructor(private env: Env) {}
|
|
|
|
/**
|
|
* 사용자 메시지를 처리하고 AI 응답을 생성합니다.
|
|
* 버퍼링, AI 생성, 요약 프로세스를 포함합니다.
|
|
*/
|
|
async processUserMessage(
|
|
userId: number,
|
|
chatId: string,
|
|
text: string,
|
|
telegramUserId: string
|
|
): Promise<ConversationResult> {
|
|
// 1. 타이핑 액션 전송 (비동기로 실행, 기다리지 않음)
|
|
sendChatAction(this.env.BOT_TOKEN, Number(chatId), 'typing').catch(err =>
|
|
logger.error('타이핑 액션 전송 실패', err as Error)
|
|
);
|
|
|
|
// 2. 새 시스템에 사용자 메시지 저장
|
|
await saveConversationMessage(this.env.DB, telegramUserId, {
|
|
role: 'user',
|
|
content: text,
|
|
});
|
|
|
|
// 3. 기존 버퍼에도 저장 (호환성 - 나중에 제거)
|
|
await addToBuffer(this.env.DB, userId, chatId, 'user', text);
|
|
|
|
// 4. AI 응답 생성
|
|
let responseText = await generateAIResponse(
|
|
this.env,
|
|
userId,
|
|
chatId,
|
|
text,
|
|
telegramUserId
|
|
);
|
|
|
|
// __DIRECT__ 마커 제거 (AI가 그대로 전달한 경우 대비)
|
|
if (responseText.includes('__DIRECT__')) {
|
|
const directIndex = responseText.indexOf('__DIRECT__');
|
|
responseText = responseText.slice(directIndex + '__DIRECT__'.length).trim();
|
|
}
|
|
|
|
// 5. 새 시스템에 봇 응답 저장
|
|
await saveConversationMessage(this.env.DB, telegramUserId, {
|
|
role: 'assistant',
|
|
content: responseText,
|
|
});
|
|
|
|
// 6. 기존 버퍼에도 저장 (호환성 - 나중에 제거)
|
|
// 봇 응답 버퍼에 추가 (키보드 데이터 마커 등은 그대로 저장)
|
|
// 실제 사용자에게 보여질 텍스트만 저장하는 것이 좋으나,
|
|
// 현재 구조상 전체를 저장하고 나중에 컨텍스트로 활용 시 정제될 수 있음
|
|
await addToBuffer(this.env.DB, userId, chatId, 'bot', responseText);
|
|
|
|
// 7. 임계값 도달 시 프로필 업데이트 (요약)
|
|
const { summarized } = await processAndSummarize(
|
|
this.env,
|
|
userId,
|
|
chatId
|
|
);
|
|
|
|
// 키보드 데이터 파싱
|
|
let keyboardData: KeyboardData | null = null;
|
|
// s 플래그로 .이 줄바꿈도 매칭하도록 (멀티라인 JSON 대응)
|
|
const keyboardMatch = responseText.match(/__KEYBOARD__(.+?)__END__\n?/s);
|
|
|
|
if (keyboardMatch) {
|
|
logger.debug('키보드 마커 감지', { preview: keyboardMatch[1].substring(0, 100) });
|
|
responseText = responseText.replace(/__KEYBOARD__.+?__END__\n?/s, '');
|
|
try {
|
|
keyboardData = JSON.parse(keyboardMatch[1]) as KeyboardData;
|
|
logger.debug('키보드 파싱 성공', { type: keyboardData.type });
|
|
} catch (e) {
|
|
logger.error('키보드 파싱 오류', e as Error, { rawData: keyboardMatch[1] });
|
|
}
|
|
} else if (responseText.includes('__KEYBOARD__')) {
|
|
logger.warn('키보드 마커 발견했으나 정규식 매칭 실패', {
|
|
preview: responseText.substring(0, 200)
|
|
});
|
|
}
|
|
|
|
return {
|
|
responseText,
|
|
isProfileUpdated: summarized,
|
|
keyboardData
|
|
};
|
|
}
|
|
}
|