feat: v2.2.92 → v2.2.158 — god-file 분해 + Stocks feature + 대화 연속성
R56–R59: agent.ts 2731→1529줄 god-file 분해 (25 modules) · attrParsers + LLM 메서드 8개 (callNonStreaming, streamChatOnce 등) · executeActions 415줄 → 8 handler 그룹 (file/run/list/brain/calendar/sheets/tasks) · handlePrompt 1100줄 → 7 phase 모듈 (system prompt + budget + autoContinue 등) R50–R55: extension.ts 1145→349줄 (telegram/settings/provider commands 분리) Stocks feature 신규: /stocks slash command (v2.2.152~158) · .astra/stocks.json 저장소 + Yahoo Finance 현재가 갱신 · 8 키워드 필터 (ROE/성장성/유동성/수익성/영업효율/기술력/안정성/PBR) · Naver 시가총액 페이지 JSON API (m.stock.naver.com) 발굴 · LLM Top 5 매력도 분석 + Telegram 자동 보고서 · KST 09:00/15:00 watcher 자동 모니터링 대화 연속성 (v2.2.150~157): · [PRIOR TURN CONCLUSION] block 으로 직전 결론 anchor · thin follow-up 분류 → boilerplate 헤더 suppression · slash 명령 결과 chatHistory mirror (capture wrapper) · echo/parrot 금지 system prompt rule 기타: /stocks 슬래시 자동완성 dropdown UI, Naver JSON API 전환 (cheerio 제거) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -35,12 +35,38 @@ export async function handleChatMessage(provider: SidebarChatProvider, data: any
|
||||
return true;
|
||||
}
|
||||
logInfo(`[SLASH] handleSlashCommand entering`);
|
||||
await handleSlashCommand(data.value, provider._view.webview, provider._context);
|
||||
logInfo(`[SLASH] handleSlashCommand returned`);
|
||||
// Slash 명령 결과를 *chatHistory 에도* mirror — 다음 turn 의 LLM 이
|
||||
// 직전 명령 출력 (예: /stocks discover 발굴 결과) 을 컨텍스트로 보게 한다.
|
||||
// 안 하면 LLM 은 webview UI 만 보고 history 는 비어 있어서 "주식 데이터
|
||||
// 없음" 같은 환각 응답이 나옴.
|
||||
const realWebview = provider._view.webview;
|
||||
const captured: string[] = [];
|
||||
const captureWebview = {
|
||||
postMessage: (msg: any) => {
|
||||
if (msg && msg.type === 'streamChunk' && typeof msg.value === 'string') {
|
||||
captured.push(msg.value);
|
||||
}
|
||||
return realWebview.postMessage(msg);
|
||||
},
|
||||
};
|
||||
await handleSlashCommand(data.value, captureWebview as any, provider._context);
|
||||
const collected = captured.join('').trim();
|
||||
if (collected) {
|
||||
// CRITICAL: getHistory() 는 *filtered copy* 를 반환하므로 직접 push 하면
|
||||
// 원본 chatHistory 에 안 들어감 (silent fail). 새 배열로 setHistory.
|
||||
const current = provider._agent.getHistory();
|
||||
const updated = [
|
||||
...current,
|
||||
{ role: 'user' as const, content: data.value },
|
||||
{ role: 'assistant' as const, content: collected, internal: false },
|
||||
];
|
||||
provider._agent.setHistory(updated);
|
||||
}
|
||||
logInfo(`[SLASH] handleSlashCommand returned, captured ${collected.length} chars → history len ${provider._agent.getHistory().length}`);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
await provider._context.globalState.update(SidebarChatProvider.blankChatStateKey, false);
|
||||
await provider._sessionState.setBlankChatActive(false);
|
||||
// ── 1인 기업 모드 우선 분기 ──
|
||||
// 회사 모드일 땐 들어온 메시지를 intent classifier에 한 번 통과시켜
|
||||
// (a) 잡담/질문/짧은 응답 → 일반 채팅 경로, (b) 후속 대화 → 일반 채팅
|
||||
@@ -214,6 +240,14 @@ export async function handleChatMessage(provider: SidebarChatProvider, data: any
|
||||
await provider._sendChronicleProjects();
|
||||
await provider._restoreActiveSessionIntoView();
|
||||
await provider._sendReadyStatus();
|
||||
// Slash 명령 목록 — webview 의 `/` 자동완성 dropdown 이 사용.
|
||||
try {
|
||||
const { listSlashCommands } = await import('../features/datacollect/slashRouter');
|
||||
const cmds = listSlashCommands().map(c => ({ name: c.name, description: c.description || '' }));
|
||||
provider._view?.webview.postMessage({ type: 'slashCommandList', commands: cmds });
|
||||
} catch (e: any) {
|
||||
// Slash 라우터 로드 실패해도 채팅 자체는 동작해야 — silent skip.
|
||||
}
|
||||
// Restore the Project Architecture chip + watcher if the active project
|
||||
// was already running in architecture mode in a previous VS Code session.
|
||||
await provider._sendArchitectureStatus();
|
||||
@@ -243,9 +277,9 @@ export async function handleChatMessage(provider: SidebarChatProvider, data: any
|
||||
provider._currentSessionId = null;
|
||||
provider._currentSessionBrainId = getActiveBrainProfile().id;
|
||||
provider._agent.resetConversation();
|
||||
await provider._context.globalState.update(SidebarChatProvider.activeSessionStateKey, null);
|
||||
await provider._context.globalState.update(SidebarChatProvider.lastVisibleChatStateKey, null);
|
||||
await provider._context.globalState.update(SidebarChatProvider.blankChatStateKey, true);
|
||||
await provider._sessionState.setActiveSessionId(null);
|
||||
await provider._sessionState.setLastVisibleChat(null);
|
||||
await provider._sessionState.setBlankChatActive(true);
|
||||
// 직전 회사 turn 컨텍스트 캐시 비우기 — 새 세션은 followup 기준점이 없다.
|
||||
provider.clearLastCompanyTurnSummary();
|
||||
// 진행 중이던 alignment도 새 세션과 함께 폐기.
|
||||
|
||||
Reference in New Issue
Block a user