0a97324f1b
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>
117 lines
4.3 KiB
TypeScript
117 lines
4.3 KiB
TypeScript
import type { RequirementContract } from '../../features/company';
|
|
|
|
/**
|
|
* 1인 기업 모드 turn 의 runtime 상태 — *진행 중* turn 의 abort handle 과
|
|
* *방금 끝난* turn 의 요약 스냅샷을 함께 보관.
|
|
*
|
|
* 옛 코드는 sidebarProvider 의 두 slot(`_companyAbort`, `_lastCompanyTurnSummary`)
|
|
* 으로 흩어져 있어, "turn 끝" 시 abort 정리와 summary 갱신이 서로 다른 분기에서
|
|
* 일어났음. Manager 로 묶어 turn lifecycle 의 진입/종료 책임을 한 곳에 모았다.
|
|
*
|
|
* Summary 슬롯은 *완료된* turn 만 채운다 (abort/error 는 비움 유지) — intent
|
|
* classifier 가 "이전 turn 후속" vs "신규 task" 를 판단할 때 abort 된 turn 을
|
|
* 후속의 기준으로 삼으면 안 되기 때문.
|
|
*/
|
|
export class CompanyTurnRuntime {
|
|
private abortController?: AbortController;
|
|
private lastSummary?: {
|
|
brief: string;
|
|
reportTail: string;
|
|
finishedAt: number;
|
|
};
|
|
|
|
/** Turn 시작 — fresh AbortController 등록. dispatcher signal 로 전달됨. */
|
|
startTurn(): AbortController {
|
|
const ctrl = new AbortController();
|
|
this.abortController = ctrl;
|
|
return ctrl;
|
|
}
|
|
|
|
/**
|
|
* Turn 종료(완료/실패/abort 무관) — finally 절에서 호출. 우리가 발급한 그
|
|
* controller 일 때만 비워 race 방지 (느린 cleanup 이 새 turn 의 controller
|
|
* 를 잘못 지우는 경우 차단).
|
|
*/
|
|
endTurn(ctrl: AbortController): void {
|
|
if (this.abortController === ctrl) this.abortController = undefined;
|
|
}
|
|
|
|
/**
|
|
* Stop 버튼 — abort 신호 emit. 호출 시점에 진행 중 turn 없으면 false.
|
|
* 호출자(provider) 는 추가로 ApprovalGateManager.abortAll() 도 호출해야
|
|
* dispatcher 의 stage gate await 가 함께 깨어남.
|
|
*/
|
|
abort(): boolean {
|
|
if (!this.abortController) return false;
|
|
this.abortController.abort();
|
|
return true;
|
|
}
|
|
|
|
/** report-done 시점에 호출. abort / error 케이스는 호출 안 됨 (intent 의도). */
|
|
recordSummary(brief: string, reportTail: string): void {
|
|
this.lastSummary = { brief, reportTail, finishedAt: Date.now() };
|
|
}
|
|
|
|
/** Intent classifier 가 follow-up 판단할 때 읽음. cold start 면 undefined. */
|
|
getLastSummary() {
|
|
return this.lastSummary;
|
|
}
|
|
|
|
/** 새 chat / 다른 세션 load 시 — 옛 report 가 의도 분류 오염하지 않게. */
|
|
clearLastSummary(): void {
|
|
this.lastSummary = undefined;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Intent Alignment 의 *현재 미해결* 상태. 분석기가 round 를 끝낸 후 사용자
|
|
* 확인이 필요한 경우 이 슬롯에 contract 를 보관 → 다음 사용자 메시지를 답변으로
|
|
* 해석. 한 번에 한 alignment 만 진행 (회사 모드는 sequential).
|
|
*
|
|
* 옛 코드는 sidebarProvider 의 단일 slot 으로 4개 메서드에 흩어져 있었음.
|
|
* Manager 로 모아 set/get/clear 책임 단일화 + 외부에서는 isPending() / consume()
|
|
* 으로 안전하게 사용.
|
|
*/
|
|
export interface PendingAlignment {
|
|
userOriginalPrompt: string;
|
|
contract: RequirementContract;
|
|
/** 이번 alignment 동안 사용자가 답한 누적 라운드 수 — 무한 라운드 방지. */
|
|
roundsAsked: number;
|
|
/** 이번 turn 한정 pipeline override (Phase 4 분류기에서 전달된 추천). */
|
|
pipelineIdOverride?: string;
|
|
}
|
|
|
|
export class AlignmentSession {
|
|
private pending?: PendingAlignment;
|
|
|
|
isPending(): boolean {
|
|
return !!this.pending;
|
|
}
|
|
|
|
/** 카드 push 시 호출 — 분석기 결과 보관. */
|
|
set(state: PendingAlignment): void {
|
|
this.pending = state;
|
|
}
|
|
|
|
/** 현재 보류 상태 조회 (consume 안 함). */
|
|
get(): PendingAlignment | undefined {
|
|
return this.pending;
|
|
}
|
|
|
|
/**
|
|
* 한 번에 *읽고 비움* — 사용자가 진행 / 답변 시 호출. consume 패턴으로 race
|
|
* (사용자가 진행 누르고 곧바로 답변 메시지 보내는 경우) 의 두 번째 호출이
|
|
* 자동으로 noop 이 되어 안전.
|
|
*/
|
|
consume(): PendingAlignment | undefined {
|
|
const cur = this.pending;
|
|
this.pending = undefined;
|
|
return cur;
|
|
}
|
|
|
|
/** 취소 — 카드 / streamEnd push 는 호출자(provider) 책임. */
|
|
clear(): void {
|
|
this.pending = undefined;
|
|
}
|
|
}
|