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:
@@ -0,0 +1,96 @@
|
||||
import { getConfig } from '../../config';
|
||||
import { estimateTokens, estimateModelParamsB } from '../contextManager';
|
||||
import { isCasualConversationPrompt } from './promptDetection';
|
||||
import { isAstraModeArchitectureQuestion } from './astraModeArchitecture';
|
||||
import { shouldPreflightLocalProjectPath } from './localProjectIntent';
|
||||
|
||||
/**
|
||||
* 단일-LLM vs Multi-Agent (5단계 파이프라인) 라우팅 결정. 사용자가 명시 토글을
|
||||
* 켰거나 (configEnabled), 작은 모델인데 prompt 가 크거나, 복합 작업 키워드가
|
||||
* 매치되면 multi-agent 활성화. 잡담/짧은 prompt 는 무조건 단일 LLM.
|
||||
*
|
||||
* Priority (위→아래로 evaluated, 먼저 매치되면 그 결정 사용):
|
||||
* 1) Astra-mode meta question / local-path preflight → 단일 (false)
|
||||
* 2) mode='off' 인 사용자 — legacy 키워드+길이 휴리스틱만 사용
|
||||
* 3) casual prompt / 너무 짧음 (<12자) → 단일
|
||||
* 4) mode='always' → 무조건 multi (위 가드 통과 시)
|
||||
* 5) mode='auto' — 작은 모델 / context fraction / 키워드 / 길이 중 하나라도
|
||||
* 매치되면 multi. 단 prompt tokens 가 `chunkedSwitchTokens` 미만이면 *모든*
|
||||
* 트리거 무시하고 단일 (큰 context 모델에서 키워드만으로 chunked 강제 발동
|
||||
* 되는 회귀 차단 — 사용자 명시 요청).
|
||||
*
|
||||
* Stateless — agent.ts 의 private 메서드를 그대로 추출. 의존: config / token
|
||||
* 추정기 / 다른 detection 함수 (모두 이미 stateless).
|
||||
*/
|
||||
export function shouldUseMultiAgentWorkflow(prompt: string, configEnabled: boolean): boolean {
|
||||
if (!prompt || isAstraModeArchitectureQuestion(prompt)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (shouldPreflightLocalProjectPath(prompt)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const cfg = getConfig();
|
||||
const mode = cfg.workflowMultiAgentMode || 'auto';
|
||||
|
||||
// 'off' → 기존 키워드/길이 휴리스틱만 사용 (legacy multiAgentEnabled 토글 존중).
|
||||
if (mode === 'off') {
|
||||
const legacyComplex = prompt.length > 180 || /(보고서|심층|종합\s*분석|리서치|조사|전략\s*수립|기획안|제안서|roadmap|research|report|deep\s*analysis|strategy|proposal)/i.test(prompt);
|
||||
if (!legacyComplex) return false;
|
||||
return configEnabled || /(보고서|심층|종합\s*분석|리서치|조사|전략\s*수립|기획안|제안서|research|report|deep\s*analysis|strategy|proposal)/i.test(prompt);
|
||||
}
|
||||
|
||||
// 인사·잡담은 5단계 파이프라인 낭비. 짧은 casual prompt 는 제외.
|
||||
if (isCasualConversationPrompt(prompt)) {
|
||||
return false;
|
||||
}
|
||||
if (prompt.trim().length < 12) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 'always' → 위 가드만 통과하면 무조건 발동.
|
||||
if (mode === 'always') return true;
|
||||
|
||||
// 'auto' → 다음 중 하나라도 만족하면 발동:
|
||||
// (1) 사용자가 multiAgentEnabled 를 명시적으로 켰다,
|
||||
// (2) 작은 모델 (≤4B params) 이라 한 번에 처리하기 위험,
|
||||
// (3) prompt 토큰이 효과적 context window 의 임계 이상을 차지한다,
|
||||
// (4) "보고서/리뷰/심층 분석" 같은 명백한 복합 작업 키워드 매치,
|
||||
// (5) prompt 길이 자체가 큼 (>240 chars).
|
||||
if (configEnabled) return true;
|
||||
|
||||
const paramB = estimateModelParamsB(cfg.defaultModel);
|
||||
if (paramB !== null && paramB <= 4) return true;
|
||||
|
||||
// ── 절대 임계값 게이트 (사용자 명시 요청) ────────────────────────────
|
||||
// 입력 prompt 가 `chunkedSwitchTokens` 미만이면 *키워드·길이 트리거 모두 무시*
|
||||
// 하고 단일 LLM 호출. 큰 컨텍스트 모델(131k 등)에서 "요약/리뷰" 같은 키워드만
|
||||
// 써도 chunked 가 강제 발동해 답변이 느려지던 문제 해결.
|
||||
//
|
||||
// 이 게이트는 fraction 안전 체크보다 *먼저* 평가됨 — 사용자가 절대 임계값을
|
||||
// 명시한 의도(50k 미만은 한 번에 처리)를 fraction 이 뒤집지 못하게. 작은
|
||||
// 컨텍스트 모델 사용자는 config 에서 이 값을 모델 윈도우의 ~30% 로 낮춰야 함.
|
||||
try {
|
||||
const promptTokensForGate = estimateTokens(prompt);
|
||||
if (promptTokensForGate < cfg.chunkedSwitchTokens) {
|
||||
return false;
|
||||
}
|
||||
} catch { /* fall through — 안전 측 fraction/keyword 체크가 처리 */ }
|
||||
|
||||
try {
|
||||
const effectiveCtx = cfg.smallModelContextCap > 0 && paramB !== null && paramB <= 4
|
||||
? cfg.smallModelContextCap
|
||||
: cfg.contextLength;
|
||||
const promptTokens = estimateTokens(prompt);
|
||||
const threshold = Math.floor(effectiveCtx * cfg.workflowAutoCtxFractionThreshold);
|
||||
if (promptTokens >= threshold) return true;
|
||||
} catch { /* 안전한 폴백: 키워드/길이 체크로 진행 */ }
|
||||
|
||||
if (/(보고서|심층|종합\s*분석|리서치|조사|전략\s*수립|기획안|제안서|코드\s*리뷰|리뷰|아키텍처|architecture|research|report|deep\s*analysis|strategy|proposal|review)/i.test(prompt)) {
|
||||
return true;
|
||||
}
|
||||
if (prompt.length > 240) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user