v2.2.299~307: 아키텍처 수렴 + 채팅 정리 + 벤치마킹 강화 + Claude 구독 엔진

- v2.2.299 아키텍처 수렴: coreChat 통일(엔진 휴리스틱 3벌 제거), 기업 모드
  검색 오케스트레이터 승격, lib/execUtil(실행 래퍼 6곳·Python 탐지 3벌 단일화),
  lib/kstSchedule(워처 4개 nowInKst 통합), estimateTokens 통합, 설정 접근 규칙 명문화
- v2.2.300 채팅 화면 정리: LiveReasoningFilter(스트리밍 중 <think>/Harmony 추론
  토큰 단위 차단), 확신도·검토요청 footer 기본 숨김(계산·Reflection 은 유지)
- v2.2.301 문맥·의도 이해: [답변 전 이해 원칙] 상시 주입, 워크플로우 의도 브리핑,
  Report QA 루프(규칙 레지스트리+실측치+회귀 게이트, 블로그_v3 개념 이식)
- v2.2.302 /benchmark 비즈니스 렌즈(가격·수익·운영)+빌드 프롬프트 모드+QA 연계
- v2.2.303 handoff 모드(측정치 무손실 인수인계 문서)+/claude(Claude Code 터미널 위임)
- v2.2.304 이식성: 지식 경로 두뇌-상대 규약(pickWikiDir 상대 해석), 이사 체크리스트
- v2.2.305 Claude 구독 엔진: claude: 프로바이더(CLI 위임, 모델 드롭다운 자동 노출,
  coreChat 지원 — 워크플로우·QA도 구독 모델 가능)
- v2.2.306 Tone Guard: AI 상투어 금지 레지스트리(상담사 화법 실사례 8종+대조 예시)
- v2.2.307 /benchmark 레이아웃 골격(sectionRoles 결정론 분석, 롤링 배너 즉답),
  파트별 실패 격리, 합성 타임아웃 120→300초

검증: tsc 무오류 + jest 888 통과 + esbuild 정상

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-11 21:02:15 +09:00
parent 98d533f045
commit 47b3b9f93a
66 changed files with 2421 additions and 459 deletions
+10 -37
View File
@@ -17,6 +17,8 @@
* 위치: 답변 streaming 완료 후, `usedScope` 메시지 전송 직전. 비동기 — 답변
* 표시를 *블록 하지 않음*. 결과는 webview 에 별도 메시지로 push.
*/
import { coreChat } from '../core/services';
export interface SelfCheckOptions {
ollamaUrl: string;
@@ -141,53 +143,24 @@ export async function postHocSelfCheck(
const sourcesCap = (sources || []).slice(0, options.maxSources);
const { system, user } = buildPrompt(userPrompt, answer, sourcesCap, options.excerptLength);
const isOllama = options.ollamaUrl.includes(':11434') || options.ollamaUrl.includes('ollama');
const endpoint = isOllama ? `${options.ollamaUrl}/api/chat` : `${options.ollamaUrl}/v1/chat/completions`;
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), options.timeoutMs);
// [코어 수렴] 자체 fetch·엔진 휴리스틱 제거 — coreChat 으로 통일 (온도 0, 200토큰).
// (이 모듈은 원래 import 0개의 자립 모듈이었으나, 엔진 폴백·로깅 일원화가 더 큰 가치)
let raw = '';
try {
const body = isOllama
? {
model: options.model, stream: false,
messages: [
{ role: 'system', content: system },
{ role: 'user', content: user },
],
options: { temperature: 0.0, num_predict: 200 },
}
: {
model: options.model, stream: false, temperature: 0.0, max_tokens: 200,
messages: [
{ role: 'system', content: system },
{ role: 'user', content: user },
],
};
const res = await fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
signal: controller.signal,
const result = await coreChat({
system, user, model: options.model,
timeoutMs: options.timeoutMs,
temperature: 0.0,
maxTokens: 200,
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data: any = await res.json();
raw = String(
data?.message?.content ??
data?.choices?.[0]?.message?.content ??
data?.choices?.[0]?.text ??
data?.response ??
'',
);
raw = String(result.content || '');
} catch (e: any) {
clearTimeout(timer);
return {
...FAILURE_RESULT,
note: `LLM call failed: ${e?.name || e?.message || 'unknown'}`,
durationMs: Date.now() - start,
rawResponse: '',
};
} finally {
clearTimeout(timer);
}
const parsed = parseResult(raw);