Files
connectai/src/sidebar/builders/architecturePayloads.ts
T
g1nation 0a97324f1b 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>
2026-05-25 09:59:32 +09:00

108 lines
4.2 KiB
TypeScript

import * as fs from 'fs';
import type { ProjectProfile } from '../../features/projectChronicle';
import { formatArchitectureContextForPrompt } from '../../features/projectArchitecture';
/**
* Architecture (chronicle 프로젝트 자동 attach) 관련 webview payload + prompt
* context 빌더. webview send / fs write / scan 같은 *상태성* 부분은 provider 와
* `ArchitectureWatchManager` 가 계속 책임 — 이 모듈은 데이터 변환만.
*
* - buildArchitectureStatusPayload(profile, hasDoc, wasDetached)
* → 'architectureStatus' 메시지의 active/inactive/hidden 분기
* - buildProjectArchitectureContext(profile)
* → agent.ts 가 prompt 에 prepend 하는 architecture context string
*/
/**
* Sidebar chip 의 3 가지 상태:
* 1) active — auto-attach 켜져 있고 doc 존재. 칩에 "마지막 갱신 N분 전" 표시.
* 2) inactive (canAttach) — workspace + project 는 있으나 doc 미생성 or detached.
* 칩에 [Attach] 버튼 노출. `detached` 플래그로 "Activate" vs "Re-attach" 구분.
* 3) hidden — profile null. 호출자가 `{ active: false }` 만 보내고 끝.
*
* 빌더는 (1)(2) 만 만들고, hidden 은 호출자가 직접 보낸다 (profile 이 없는데
* 빌더에 넘겨봤자 의미 없음).
*/
export function buildArchitectureStatusPayload(profile: ProjectProfile, hasDoc: boolean, wasDetached: boolean) {
const fullyActive = hasDoc && !wasDetached;
if (fullyActive) {
return {
type: 'architectureStatus' as const,
value: {
active: true,
projectId: profile.projectId,
projectName: profile.projectName,
docPath: profile.architectureDocPath,
lastUpdated: profile.architectureLastUpdated || '',
autoUpdate: profile.architectureAutoUpdate !== false,
},
};
}
return {
type: 'architectureStatus' as const,
value: {
active: false,
canAttach: !!profile.projectRoot,
projectId: profile.projectId,
projectName: profile.projectName,
// "never activated" 와 "detached" 구분 — chip 라벨 결정용.
detached: wasDetached,
},
};
}
/** Workspace 도 profile 도 없는 hidden 상태 — chip 자체 숨김. */
export function buildArchitectureHiddenPayload() {
return {
type: 'architectureStatus' as const,
value: { active: false as const },
};
}
/**
* Refresh / Attach 가 사전 가드에서 실패 (활성 project 없음 / projectRoot 없음).
* webview 는 spinner 를 해제하고 사용자에게 안내 띄움.
*/
export function buildArchitectureRefreshFailedPayload(reason: string) {
return {
type: 'architectureRefreshFailed' as const,
value: { reason },
};
}
/**
* Refresh 가 성공적으로 수행된 후 webview 에 보낼 결과. 3가지 숫자 (newly /
* cached / deleted) 가 함께 가야 사용자가 "Refresh 가 실제로 뭘 했는가" 를
* 신뢰할 수 있다 — 그냥 timestamp 만 바뀐 경우와 분 단위로 큰 작업이 일어난
* 경우를 구분.
*/
export function buildArchitectureRefreshResultPayload(opts: {
projectName: string;
docPath: string;
newlyAnalyzed: number;
cached: number;
deleted: number;
durationMs: number;
}) {
return {
type: 'architectureRefreshResult' as const,
value: opts,
};
}
/**
* Agent 의 prompt 에 prepend 되는 architecture context block. auto-attach 가 off
* 거나 doc 이 없거나 디스크에서 사라졌으면 빈 문자열 (agent.ts 가 알아서 skip).
*/
export function buildProjectArchitectureContext(profile: ProjectProfile | null): string {
if (!profile || profile.architectureAutoAttach === false || !profile.architectureDocPath) return '';
if (!fs.existsSync(profile.architectureDocPath)) return '';
return formatArchitectureContextForPrompt({
projectName: profile.projectName,
docPath: profile.architectureDocPath,
// project root 를 같이 넘겨 Source: 헤더가 workspace-relative 로 출력되게.
projectRoot: profile.projectRoot,
lastUpdated: profile.architectureLastUpdated,
});
}