# ConnectAI Architecture and Code Review

## 1. 프로젝트 개요

`ConnectAI`는 VS Code 확장형 AI 어시스턴트인 `Astra`의 핵심 구현체입니다. 이 프로젝트는 로컬 AI 모델 서버(예: Ollama, LM Studio)를 사용하여:

- 개발자와 프로젝트의 맥락을 유지
- 로컬 지식 베이스(`Second Brain`)를 읽고 쓰기
- 멀티 에이전트 워크플로우로 복잡한 요청을 처리
- 확장형 브릿지 서버로 외부 도구와 통합

## 2. 주요 아키텍처 모듈

### 2.1 Extension Entry Point

- 파일: [src/extension.ts](src/extension.ts)
- 역할:
  - VS Code 확장 활성화/비활성화
  - 환경 검사 및 설정 검증
  - 브레인 디렉토리 초기화
  - LM Studio Lifecycle Subsystem 초기화 및 의존성 주입
  - `AgentExecutor`, `SidebarChatProvider`, `BridgeServer` 초기화
  - 핵심 명령(command) 등록

### 2.2 Agent Executor

- 파일: [src/agent.ts](src/agent.ts)
- 역할:
  - 채팅 세션 관리
  - 메시지 히스토리 유지 및 복원
  - 트랜잭션 기반 변경 승인/거부
  - 메시지 전송 처리 및 다중 에이전트 워크플로우 분기
  - 메모리/검색/상태 로깅 통합
  - `AgentExecutorOptions.onStreamLifecycle` 콜백으로 외부 시스템(LM Studio idle eject)에 stream start/end 알림

### 2.3 브릿지 서버

- 파일: [src/bridge.ts](src/bridge.ts)
- 역할:
  - 외부 HTTP 클라이언트와 통신
  - `/ping`, `/api/exam`, `/api/evaluate`, `/api/evaluate-history`, `/api/brain-inject` 엔드포인트 제공
  - AI 호출과 Brain 주입 비즈니스 로직 분리

### 2.4 서비스 레이어

- 파일: [src/core/services.ts](src/core/services.ts)
- 역할:
  - AI 모델 호출 및 브레인 파일 시스템 조작을 추상화
  - `IAIService`, `IBrainService` 인터페이스 정의
  - Ollama/LM Studio 폴백 로직 구현

### 2.5 구성 및 보안

- 파일: [src/config.ts](src/config.ts)
- 역할:
  - VS Code 설정을 읽고 `IAgentConfig`로 변환
  - Brain 프로필, 활성 Brain, URL, 모델, 메모리 설정을 통합
  - 설정 검증 및 기본값 제공
  - 보안 정책 상수(`SECURITY_POLICY`, `EXCLUDED_DIRS`) 정의

### 2.6 에이전트 팩토리

- 파일: [src/agents/factory.ts](src/agents/factory.ts)
- 역할:
  - `PlannerAgent`, `ResearcherAgent`, `WriterAgent` 정의
  - 각 에이전트가 담당하는 역할 및 프롬프트 템플릿 구현
  - LLM 호출을 담당하는 공통 `BaseAgent` 제공

### 2.7 워크플로우 매니저

- 파일: [src/agents/AgentWorkflowManager.ts](src/agents/AgentWorkflowManager.ts)
- 역할:
  - Planner → Researcher → Writer로 이어지는 엄격한 워크플로우 실행
  - 상태 변환을 UI 이벤트로 매핑

### 2.8 에이전트 엔진

- 파일: [src/lib/engine.ts](src/lib/engine.ts)
- 역할:
  - 전체 에이전트 파이프라인 실행
  - 상태/감사 추적(`MissionState`)
  - 에러 분류 및 복구 로직
  - 캐시 및 중복 제거(`CacheManager`)
  - 미션 재개(Resumption) 및 동시 실행 잠금(`lockManager`)
  - 프롬프트/컨텍스트 증폭, proactive advice 생성

### 2.9 기억 솔루션

- 파일: [src/memory/index.ts](src/memory/index.ts)
- 역할:
  - `MemoryManager`로 5계층 메모리 관리
  - Short-Term, Long-Term, Project, Procedural, Episodic 메모리 통합
  - 세션 종료 시 메모리 추출 및 저장

### 2.10 검색(Retrieval)

- 파일: [src/retrieval/index.ts](src/retrieval/index.ts)
- 역할:
  - RAG 기반 검색 오케스트레이션
  - Brain 파일, 메모리 레이어, 프로젝트/에피소드 검색
  - TF-IDF 유사도 기반 스코어링
  - 컨텍스트 예산 내에서 선택

### 2.11 LM Studio 라이프사이클 서브시스템

- 폴더: [src/lmstudio/](src/lmstudio/)
- 역할:
  - LM Studio 모델의 명시적 load / idle 기반 auto-eject 관리
  - `@lmstudio/sdk`(WebSocket 기반) 위에 얇은 어댑터 + 상태 머신 구성
- 구성:
  - [src/lmstudio/client.ts](src/lmstudio/client.ts) — `LMStudioClient`
    - SDK 인스턴스 lazy 생성, `http://...:1234`를 `ws://...:1234`로 자동 변환
    - `load(modelKey, signal?)` / `unload(modelKey)` / `listLoaded()` / `isReachable()` 노출
    - 모든 SDK 호출을 `LMStudioLifecycleError`로 정규화
  - [src/lmstudio/activityTracker.ts](src/lmstudio/activityTracker.ts) — `ActivityTracker`
    - `vscode.EventEmitter<void>` 기반 이벤트 버스. `bump()` / `onActivity` 인터페이스
  - [src/lmstudio/lifecycleManager.ts](src/lmstudio/lifecycleManager.ts) — `ModelLifecycleManager`
    - 상태: `idle` → `loading` → `loaded` → `streaming` → `unloading` → `idle`
    - 진입 신호: `onModelSelected`, `onStreamStart`, `onStreamEnd`, `onActivity`(bump 구독), `setEngine`
    - idle 타이머는 `g1nation.lmStudio.idleTimeoutMs`(기본 300000ms, 0이면 비활성화) 기반으로 자동 unload
    - `AbortController`로 빠른 모델 전환 시 진행 중 load 취소, 디바운스 300ms
    - `disposeAndUnload(timeoutMs)`로 deactivate 시 best-effort eject

### 2.12 사이드바 핸들러 모듈

- 폴더: [src/sidebar/](src/sidebar/)
- 역할:
  - `SidebarChatProvider.onDidReceiveMessage`의 ~43개 case branches를 도메인별로 분리
  - 메인 provider는 라우터 6줄로 압축되어 가독성 / 점검 비용 대폭 절감
- 구성:
  - [src/sidebar/chatHandlers.ts](src/sidebar/chatHandlers.ts) — prompt, ready, model 선택, 세션 CRUD, exportResponse, approve/reject 등 chat-domain
  - [src/sidebar/brainHandlers.ts](src/sidebar/brainHandlers.ts) — Brain 프로필 관리, syncBrain, saveWikiRaw
  - [src/sidebar/chronicleHandlers.ts](src/sidebar/chronicleHandlers.ts) — Project Chronicle CRUD + 6개 record-write 엔트리포인트
  - [src/sidebar/agentHandlers.ts](src/sidebar/agentHandlers.ts) — Agent skill CRUD + 마지막 선택 저장
- 컨벤션: 각 핸들러는 `(provider, data) => Promise<boolean>` 시그니처. 처리한 메시지면 true 반환, 미처리는 false. 라우터가 chain으로 위임. 대응 case 없는 메시지는 `logInfo`로 기록.
- 핸들러가 `SidebarChatProvider` 인스턴스 멤버에 직접 접근하므로 instance-level visibility는 모두 풀려 있음. 단 `_`-prefix는 "internal use only" 컨벤션으로 유지되며 `readonly`는 보존됨.

### 2.13 웹뷰 정적 자산

- 폴더: [media/](media/)
- 역할: 사이드바 웹뷰의 HTML/CSS/JS를 esbuild 번들에서 분리하여 IDE syntax highlighting / lint이 정상 동작하도록 외부화
- 구성:
  - [media/sidebar.html](media/sidebar.html) — 골격 + `__STYLES_URI__` / `__SCRIPT_URI__` placeholder
  - [media/sidebar.css](media/sidebar.css) — 디자인 토큰, 컴포넌트 스타일
  - [media/sidebar.js](media/sidebar.js) — 웹뷰 측 이벤트 처리, postMessage 연동
- 로딩 흐름: `SidebarChatProvider._getHtml()`이 템플릿 파일을 한 번 읽어 정적 캐시(`_htmlTemplateCache`)에 보관하고, `webview.asWebviewUri`로 placeholder를 치환

## 3. 프로젝트 설계도 요약

### 핵심 데이터 흐름

1. 사용자 요청 → `AgentExecutor.handlePrompt()`
2. 설정/메모리/검색 컨텍스트 수집
3. `AgentWorkflowManager` → `AgentEngine.runMission()` 호출
4. Planner, Researcher, Writer 순차 실행
5. 결과를 캐시하고 `SidebarChatProvider`로 스트리밍
6. 필요 시 브레인에 지식 주입 또는 외부 브릿지 응답

### 사이드바 메시지 흐름

1. 웹뷰 JS([media/sidebar.js](media/sidebar.js))가 `vscode.postMessage({ type, ... })` 발신
2. `SidebarChatProvider.onDidReceiveMessage` 라우터가 도메인 핸들러 4개에 chain 위임
3. 각 핸들러는 provider의 internal method를 호출, 결과를 `webview.postMessage`로 회신
4. LM Studio 엔진 사용 중이면 `prompt`/`activity`/`model` 케이스가 `ModelLifecycleManager`에 신호 전달

### 핵심 설계 원칙

- **모듈 분리**: UI, AI 호출, 브레인 IO, 메모리, 검색, 에이전트 워크플로우, 모델 라이프사이클이 명확하게 분리됨
- **상태 내구성**: `MissionState`를 `.astra/missions`에 저장하여 진행 상태 추적
- **복원력**: 트랜잭션, 잠금, 재시도, 오류 분류, 캐시를 통한 내결함성 확보
- **로컬 우선**: 로컬 브레인, 로컬 모델 서버, VS Code 환경과의 통합에 중심을 둠
- **확장성**: 프로필 기반 Brain 선택, multi-agent toggle, memory layer 설정, 도메인별 핸들러 모듈

## 4. 강점

- 확장성과 유지보수성이 높은 분리된 아키텍처
- 에이전트 워크플로우를 위한 명시적 `IAgent` 인터페이스
- `MissionState` 기반 감사/복원 로깅
- 로컬 AI 엔진(Ollama/LM Studio) 폴백 지원
- LM Studio 모델 lifecycle 자동 관리 — 메모리 점유 최소화
- `BridgeServer`로 외부 시스템 연결 가능
- `MemoryManager`와 `RetrievalOrchestrator`를 통한 RAG+메모리 결합
- 도메인별 사이드바 핸들러 모듈로 메시지 처리 흐름 명확화

## 5. 최근 적용된 최적화

| 항목 | 위치 | 효과 |
|---|---|---|
| 모델 목록 30초 TTL 캐시 | [src/sidebarProvider.ts](src/sidebarProvider.ts) `_sendModels()` | 사이드바 토글마다의 `/v1/models` HTTP 왕복 제거. 사용자 명시적 새로고침(`refreshModels`)은 `force=true`로 캐시 우회 |
| `findBrainFiles` 5초 TTL 메모이제이션 | [src/utils.ts](src/utils.ts) | 매 프롬프트마다 반복되던 동기 재귀 fs walk를 캐시. 명시적 무효화 hook(`invalidateBrainFilesCache`) 노출 |
| `secondBrainTrace` 슬롯별 재스캔 제거 | [src/features/secondBrainTrace.ts](src/features/secondBrainTrace.ts) | `scoreFile`을 terms-independent `scanFile`(파일 읽기·분류 1회)과 terms-dependent `scoreScan`으로 분리. N파일×(1+S슬롯) `readFileSync` → N회로 압축 |
| `marked` 미사용 의존성 제거 | [package.json](package.json), [.vscodeignore](.vscodeignore) | 웹뷰는 CDN 사용 중. node_modules 460KB 정리 + stale axios 화이트리스트 정리 |
| 웹뷰 자산 외부화 | [media/](media/) | esbuild 번들 –67KB. webview JS/CSS는 IDE에서 syntax highlighting/lint 정상 동작 |
| 사이드바 핸들러 도메인별 모듈 분리 | [src/sidebar/](src/sidebar/) | `sidebarProvider.ts` 3,535줄 → 1,920줄 (–46%). `onDidReceiveMessage` switch가 라우터 6줄로 |

전체 회귀: 15 테스트 스위트 / 141 테스트 통과 (LM Studio lifecycle 15개 + brain files 캐시 6개 신규 포함).

## 6. 추가 개선 제안

### 6.1 캐시 키 일관성 (미적용)

- `CacheManager.get()`과 `set()`은 prompt+context 해시를 사용
- `context`가 모델 또는 옵션을 포함하지 않으면 모델 변경 시 캐시 혼선 가능
- 권장: 캐시 키에 모델명/temperature/엔진 종류를 명시적으로 포함

### 6.2 에러 로그 세분화 (미적용)

- `AgentEngine.handleMissionFailure()`는 오류를 `error` 상태로 전환만 함
- 사용자에게 직접 표시할 추가 요약 메시지를 생성하면 UI 피드백 향상
- LM Studio lifecycle은 이미 `notifyError` → 웹뷰 `lmStudioError` 토스트 패턴을 사용 중. 동일 패턴을 mission failure에도 적용 가능

### 6.3 핫패스 캐시 무효화 와이어링 (선택)

- `invalidateBrainFilesCache(dir)`는 export되어 있지만 mutation 지점(syncBrain 직후 / chronicle write 직후)에 wiring되어 있지 않음
- 5초 TTL이 충분히 짧아 보류 상태. "방금 쓴 chronicle이 즉시 검색 안 됨" 같은 freshness 이슈가 보고되면 그때 추가

### 6.4 SidebarChatProvider 추가 분할 (선택, L effort)

- 현재 1,920줄. 도메인 메시지 라우팅은 분리됐지만 chronicle / brain / session / agent 관련 internal method가 한 클래스에 공존
- 실제 sub-provider로 분할(상태 분리 포함)하는 것은 큰 리팩터링이며 회귀 위험이 있음. 다음 큰 기능 추가 시 함께 진행하는 것이 ROI 측면에서 바람직

### 6.5 PDF 파이프라인 의존성 (미적용)

- `pdf-parse`(+ transitive `pdfjs-dist` 13MB, `@napi-rs/canvas` native binary)가 .vsix에 동봉되지 않고 esbuild 번들에 700KB 포함되는 구조
- external 처리 시 .vsix 다운로드가 17배 증가하여 사용자 측 손해
- 더 가벼운 PDF 텍스트 추출 라이브러리로 교체하거나 PDF 기능 자체를 옵션화하는 별도 검토 필요

## 7. 주요 파일 및 담당 영역

### 진입점 / 코어
- [package.json](package.json) — VS Code 확장 메타데이터, 명령, 확장 포인트, 신규 `g1nation.lmStudio.*` 설정
- [src/extension.ts](src/extension.ts) — 확장 활성화, lifecycle 서브시스템 wiring, deactivate 시 best-effort eject
- [src/agent.ts](src/agent.ts) — 프롬프트/대화/세션/트랜잭션 핵심 + `onStreamLifecycle` 콜백
- [src/bridge.ts](src/bridge.ts) — 외부 HTTP 브릿지 (port 4825)
- [src/config.ts](src/config.ts) — 설정, Brain 프로필, 보안 정책
- [src/utils.ts](src/utils.ts) — 공용 헬퍼, brain 파일 캐시 포함

### Agent 파이프라인
- [src/agents/factory.ts](src/agents/factory.ts) — Planner/Researcher/Writer 에이전트
- [src/agents/AgentWorkflowManager.ts](src/agents/AgentWorkflowManager.ts) — 다중 에이전트 워크플로우
- [src/lib/engine.ts](src/lib/engine.ts) — 에이전트 실행 파이프라인, 상태, 캐시, 오류 복구

### 메모리 / 검색 / 분류
- [src/memory/index.ts](src/memory/index.ts) — 다중 메모리 계층 관리
- [src/retrieval/index.ts](src/retrieval/index.ts) — 검색/컨텍스트 예산 관리
- [src/features/secondBrainTrace.ts](src/features/secondBrainTrace.ts) — Second Brain 추적, scanFile/scoreScan 분리

### LM Studio Lifecycle
- [src/lmstudio/client.ts](src/lmstudio/client.ts) — SDK wrapper
- [src/lmstudio/activityTracker.ts](src/lmstudio/activityTracker.ts) — 활동 이벤트 버스
- [src/lmstudio/lifecycleManager.ts](src/lmstudio/lifecycleManager.ts) — 모델 상태 머신

### 사이드바
- [src/sidebarProvider.ts](src/sidebarProvider.ts) — 사이드바 webview provider, 라우터
- [src/sidebar/chatHandlers.ts](src/sidebar/chatHandlers.ts) — chat domain 메시지
- [src/sidebar/brainHandlers.ts](src/sidebar/brainHandlers.ts) — brain domain 메시지
- [src/sidebar/chronicleHandlers.ts](src/sidebar/chronicleHandlers.ts) — chronicle domain 메시지
- [src/sidebar/agentHandlers.ts](src/sidebar/agentHandlers.ts) — agent domain 메시지
- [media/sidebar.html](media/sidebar.html) / [media/sidebar.css](media/sidebar.css) / [media/sidebar.js](media/sidebar.js) — 웹뷰 정적 자산

### 테스트
- [tests/lmStudioLifecycle.test.ts](tests/lmStudioLifecycle.test.ts) — 상태 머신 15개 케이스
- [tests/findBrainFilesCache.test.ts](tests/findBrainFilesCache.test.ts) — TTL 캐시 6개 케이스
- [tests/secondBrainTrace.test.ts](tests/secondBrainTrace.test.ts) — scanFile/scoreScan 리팩터 후에도 12개 케이스 통과로 동작 보존 확인

## 8. 결론

`ConnectAI`는 로컬 AI 기반 VS Code 어시스턴트로서 좋은 설계 기반 위에 점진적 모듈화가 진행 중인 상태입니다. 다층 메모리, 멀티 에이전트 파이프라인, 브릿지 서버, LM Studio 라이프사이클 관리, 도메인별 사이드바 핸들러까지 갖춰져 있어 신규 기능 추가의 진입 비용이 낮아졌습니다.

남은 개선 여지는 (1) 캐시 키 일관성 강화, (2) mission failure UI 메시지 다듬기, (3) PDF 의존성 정책 재검토 정도로, 모두 명확한 trade-off가 있는 항목들입니다.

---

문서 갱신일: 2026-05-08
