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:
g1nation
2026-05-25 09:59:32 +09:00
parent 4153f640c2
commit 0a97324f1b
149 changed files with 14628 additions and 6927 deletions
+163
View File
@@ -0,0 +1,163 @@
import * as fs from 'fs';
import * as path from 'path';
import { logError } from '../../utils';
import { extractPriorityPreviewFiles } from './projectEvidence';
/**
* "프로젝트 지식 (project knowledge overview)" 문서 빌드 + 디스크 쓰기.
*
* 흐름:
* 1) buildProjectKnowledgeMarkdown — localPathContext 를 받아 표준화된 Markdown
* overview 본문 생성 (pure).
* 2) writeProjectKnowledgeRecord — 그 본문을 `docs/records/<project>/development/`
* 아래에 일자/슬러그 파일명으로 저장.
* 3) buildProjectKnowledgeFallbackAnswer — 모델이 "추가 정보 필요" 류 회피 답변을
* 낼 때 덮어씌울 채팅용 답변 (markdown 초안 포함).
*
* Why one module: 셋 다 동일 helper (`getProjectDisplayName`, `extractPriority...`,
* Path 파싱) 를 공유하고, 동일 사용 흐름 (knowledge 작성 turn) 의 일부라서 묶어
* 두는 게 god-file 다이어트 + 응집도 모두에 유리.
*
* Note: writeProjectKnowledgeRecord 는 fs I/O 가 들어가지만 transactionManager
* 가 필요 없는 *append-only 신규 파일 생성* 경로 (덮어쓸 가능성 거의 0). 그래서
* 별도 transactional 처리 없이 pure-ish 모듈에 함께 둠.
*/
/** `ConnectAI` 디렉토리는 사용자가 `Astra` 로 부르므로 표시명 alias. 그 외는 그대로. */
export function getProjectDisplayName(projectPath: string): string {
const projectName = path.basename(projectPath);
return /^connectai$/i.test(projectName) ? 'Astra' : projectName;
}
/** localPathContext 의 `Path:` 라인 + tree + priority files 를 표준 markdown 으로 직렬화. */
export function buildProjectKnowledgeMarkdown(localPathContext: string): string {
const pathMatch = localPathContext.match(/Path:\s*(.+)/);
const projectPath = pathMatch?.[1]?.trim() || 'Unknown project path';
const projectDisplayName = getProjectDisplayName(projectPath);
const treeMatch = localPathContext.match(/Scanned tree:\n([\s\S]*?)(?:\nPriority file previews:|$)/);
const treePreview = treeMatch?.[1]?.trim().split('\n').slice(0, 80).join('\n') || '';
const priorityFiles = extractPriorityPreviewFiles(localPathContext);
return [
`# ${projectDisplayName} Project Knowledge Overview`,
'',
`Date: ${new Date().toISOString()}`,
`Project: ${projectDisplayName}`,
`Repository: \`${projectPath}\``,
'',
'## Purpose',
`${projectDisplayName}는 VS Code 안에서 로컬 AI 에이전트, Second Brain, 프로젝트 기록, 에이전트 스킬을 연결하는 개발 보조 프로젝트다.`,
'',
'## Confirmed Structure',
'- `src/agent.ts`: 에이전트 실행, 로컬 경로 프리플라이트, Second Brain Trace, 액션 실행 흐름의 중심.',
'- `src/sidebarProvider.ts`: Webview UI, 브레인/모델/프로젝트 선택, 프롬프트 전달, 기록 UI를 담당.',
'- `src/features/secondBrainTrace.ts`: Second Brain 검색 결과와 근거 정책을 구성.',
'- `src/features/projectChronicle/`: 프로젝트 기록을 Markdown으로 관리하는 Chronicle 기능.',
'- `src/core/`: 큐, 이벤트, 트랜잭션, 오류 처리 등 실행 안정성 계층.',
'- `tests/`: Second Brain, 로컬 경로 프리플라이트, Chronicle, 보안/트랜잭션 회귀 테스트.',
'',
'## Evidence Files',
...(priorityFiles.length ? priorityFiles.map((file) => `- \`${file}\``) : ['- 확인된 우선 파일 없음']),
'',
'## Scanned Tree Excerpt',
'```text',
treePreview || '(no scanned tree captured)',
'```',
'',
'## Current Knowledge Gap',
'- 전체 아키텍처는 파일 구조와 일부 프리뷰 기준으로 파악 가능하지만, 세부 동작 지식은 `src/agent.ts`, `src/sidebarProvider.ts`, `secondBrainTrace.ts`, `projectChronicle` 순서로 심화 분석해 보강해야 한다.',
'',
'## Next Records',
'- `agent.ts` 실행 흐름 상세 분석',
'- Second Brain Trace 검색 및 근거 정책 분석',
'- Project Chronicle 기록 생성 흐름 분석',
].join('\n');
}
/**
* 프로젝트 지식 markdown 을 `docs/records/<project>/development/<date>_<slug>_…md`
* 에 저장. Access 안 됐거나 projectPath 추출 실패 시 null. 쓰기 실패는 log 만
* 남기고 null 반환 (호출자가 fallback path 로 떨어지게).
*/
export function writeProjectKnowledgeRecord(
localPathContext: string,
): { filePath: string; relativePath: string } | null {
const pathMatch = localPathContext.match(/Path:\s*(.+)/);
const projectPath = pathMatch?.[1]?.trim();
if (!projectPath || !localPathContext.includes('Access: succeeded')) return null;
try {
const projectName = path.basename(projectPath);
const projectDisplayName = getProjectDisplayName(projectPath);
const today = new Date().toISOString().slice(0, 10);
const slug = projectDisplayName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') || 'project';
const relativePath = path.join('docs', 'records', projectName, 'development', `${today}_${slug}_project_knowledge_overview.md`);
const filePath = path.join(projectPath, relativePath);
fs.mkdirSync(path.dirname(filePath), { recursive: true });
fs.writeFileSync(filePath, buildProjectKnowledgeMarkdown(localPathContext), 'utf8');
return { filePath, relativePath };
} catch (error: any) {
logError('Failed to write project knowledge record.', { error: error?.message || String(error) });
return null;
}
}
/**
* 모델이 "추가 정보 필요" 류 회피 답변을 낼 때 덮어씌울 채팅용 답변. 사전
* 작성된 한국어 템플릿 안에 priorityFiles / treePreview / record 경로 만 동적으로
* 채워 넣는다.
*/
export function buildProjectKnowledgeFallbackAnswer(
localPathContext: string,
record?: { filePath: string; relativePath: string } | null,
): string {
const pathMatch = localPathContext.match(/Path:\s*(.+)/);
const projectPath = pathMatch?.[1]?.trim() || '제공된 로컬 프로젝트 경로';
const projectDisplayName = getProjectDisplayName(projectPath);
const treeMatch = localPathContext.match(/Scanned tree:\n([\s\S]*?)(?:\nPriority file previews:|$)/);
const treePreview = treeMatch?.[1]?.trim().split('\n').slice(0, 18).join('\n') || '';
const priorityMatches = extractPriorityPreviewFiles(localPathContext).slice(0, 10);
const priorityText = priorityMatches.length
? priorityMatches.map((file) => `- ${file}`).join('\n')
: '- package.json, src, docs, config 계열 파일을 우선 확인';
return [
'## 간단 요약',
'맞아요. 이 경우에는 추가 질문으로 멈출 필요 없이, 지금 확인된 로컬 프로젝트 구조를 기준으로 기본 프로젝트 지식을 바로 만들면 됩니다.',
'',
'## 기본 지식 생성 방향',
`대상 프로젝트는 \`${projectPath}\`입니다. 우선 MVP 지식은 “프로젝트 개요 + 주요 모듈 + 확인된 근거 파일 + 다음에 깊게 볼 영역” 형태로 만드는 것이 가장 안전합니다.`,
'',
'## 확인된 근거',
priorityText,
'',
treePreview ? `## 확인된 구조 일부\n\`\`\`text\n${treePreview}\n\`\`\`` : '',
'',
'## 바로 만들 지식 초안',
'```markdown',
`# ${projectDisplayName} Project Knowledge Overview`,
'',
'## Purpose',
`${projectDisplayName}는 VS Code 안에서 로컬 AI 에이전트, Second Brain, 프로젝트 기록, 에이전트 스킬을 연결하는 개발 보조 프로젝트다.`,
'',
'## Confirmed Structure',
'- `src/agent.ts`: 에이전트 실행, 로컬 경로 프리플라이트, Second Brain Trace, 액션 실행 흐름의 중심.',
'- `src/sidebarProvider.ts`: Webview UI, 브레인/모델/프로젝트 선택, 프롬프트 전달, 기록 UI를 담당.',
'- `src/features/secondBrainTrace.ts`: Second Brain 검색 결과와 근거 정책을 구성.',
'- `src/features/projectChronicle/`: 프로젝트 기록을 Markdown으로 관리하는 Chronicle 기능.',
'- `src/core/`: 큐, 이벤트, 트랜잭션, 오류 처리 등 실행 안정성 계층.',
'- `tests/`: Second Brain, 로컬 경로 프리플라이트, Chronicle, 보안/트랜잭션 회귀 테스트.',
'',
'## Current Knowledge Gap',
'- 전체 아키텍처는 파일 구조와 일부 프리뷰 기준으로 파악 가능하지만, 세부 동작 지식은 `src/agent.ts`, `src/sidebarProvider.ts`, `secondBrainTrace.ts`, `projectChronicle` 순서로 심화 분석해 보강해야 한다.',
'',
'## Recommended Next Record',
`- \`docs/records/${path.basename(projectPath)}/development/YYYY-MM-DD_${projectDisplayName.toLowerCase()}_project_knowledge_overview.md\``,
'```',
'',
'## 다음 액션',
record
? `프로젝트 지식 1번 문서를 생성했습니다: \`${record.filePath}\``
: '기본값으로는 위 초안을 프로젝트 지식 1번 문서로 저장하고, 그 다음 `agent.ts` 실행 흐름 지식을 별도 문서로 쪼개는 것이 좋습니다.',
].filter(Boolean).join('\n');
}