Files
connectai/ARCHITECTURE_ANALYSIS.md
T

15 KiB
Raw Blame History

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
  • 역할:
    • VS Code 확장 활성화/비활성화
    • 환경 검사 및 설정 검증
    • 브레인 디렉토리 초기화
    • LM Studio Lifecycle Subsystem 초기화 및 의존성 주입
    • AgentExecutor, SidebarChatProvider, BridgeServer 초기화
    • 핵심 명령(command) 등록

2.2 Agent Executor

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

2.3 브릿지 서버

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

2.4 서비스 레이어

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

2.5 구성 및 보안

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

2.6 에이전트 팩토리

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

2.7 워크플로우 매니저

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

2.8 에이전트 엔진

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

2.9 기억 솔루션

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

2.10 검색(Retrieval)

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

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

  • 폴더: src/lmstudio/
  • 역할:
    • LM Studio 모델의 명시적 load / idle 기반 auto-eject 관리
    • @lmstudio/sdk(WebSocket 기반) 위에 얇은 어댑터 + 상태 머신 구성
  • 구성:
    • src/lmstudio/client.tsLMStudioClient
      • SDK 인스턴스 lazy 생성, http://...:1234ws://...:1234로 자동 변환
      • load(modelKey, signal?) / unload(modelKey) / listLoaded() / isReachable() 노출
      • 모든 SDK 호출을 LMStudioLifecycleError로 정규화
    • src/lmstudio/activityTracker.tsActivityTracker
      • vscode.EventEmitter<void> 기반 이벤트 버스. bump() / onActivity 인터페이스
    • src/lmstudio/lifecycleManager.tsModelLifecycleManager
      • 상태: idleloadingloadedstreamingunloadingidle
      • 진입 신호: 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/
  • 역할:
    • SidebarChatProvider.onDidReceiveMessage의 ~43개 case branches를 도메인별로 분리
    • 메인 provider는 라우터 6줄로 압축되어 가독성 / 점검 비용 대폭 절감
  • 구성:
  • 컨벤션: 각 핸들러는 (provider, data) => Promise<boolean> 시그니처. 처리한 메시지면 true 반환, 미처리는 false. 라우터가 chain으로 위임. 대응 case 없는 메시지는 logInfo로 기록.
  • 핸들러가 SidebarChatProvider 인스턴스 멤버에 직접 접근하므로 instance-level visibility는 모두 풀려 있음. 단 _-prefix는 "internal use only" 컨벤션으로 유지되며 readonly는 보존됨.

2.13 웹뷰 정적 자산

  • 폴더: media/
  • 역할: 사이드바 웹뷰의 HTML/CSS/JS를 esbuild 번들에서 분리하여 IDE syntax highlighting / lint이 정상 동작하도록 외부화
  • 구성:
  • 로딩 흐름: SidebarChatProvider._getHtml()이 템플릿 파일을 한 번 읽어 정적 캐시(_htmlTemplateCache)에 보관하고, webview.asWebviewUri로 placeholder를 치환

3. 프로젝트 설계도 요약

핵심 데이터 흐름

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

사이드바 메시지 흐름

  1. 웹뷰 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로 외부 시스템 연결 가능
  • MemoryManagerRetrievalOrchestrator를 통한 RAG+메모리 결합
  • 도메인별 사이드바 핸들러 모듈로 메시지 처리 흐름 명확화

5. 최근 적용된 최적화

항목 위치 효과
모델 목록 30초 TTL 캐시 src/sidebarProvider.ts _sendModels() 사이드바 토글마다의 /v1/models HTTP 왕복 제거. 사용자 명시적 새로고침(refreshModels)은 force=true로 캐시 우회
findBrainFiles 5초 TTL 메모이제이션 src/utils.ts 매 프롬프트마다 반복되던 동기 재귀 fs walk를 캐시. 명시적 무효화 hook(invalidateBrainFilesCache) 노출
secondBrainTrace 슬롯별 재스캔 제거 src/features/secondBrainTrace.ts scoreFile을 terms-independent scanFile(파일 읽기·분류 1회)과 terms-dependent scoreScan으로 분리. N파일×(1+S슬롯) readFileSync → N회로 압축
marked 미사용 의존성 제거 package.json, .vscodeignore 웹뷰는 CDN 사용 중. node_modules 460KB 정리 + stale axios 화이트리스트 정리
웹뷰 자산 외부화 media/ esbuild 번들 67KB. webview JS/CSS는 IDE에서 syntax highlighting/lint 정상 동작
사이드바 핸들러 도메인별 모듈 분리 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 — VS Code 확장 메타데이터, 명령, 확장 포인트, 신규 g1nation.lmStudio.* 설정
  • src/extension.ts — 확장 활성화, lifecycle 서브시스템 wiring, deactivate 시 best-effort eject
  • src/agent.ts — 프롬프트/대화/세션/트랜잭션 핵심 + onStreamLifecycle 콜백
  • src/bridge.ts — 외부 HTTP 브릿지 (port 4825)
  • src/config.ts — 설정, Brain 프로필, 보안 정책
  • src/utils.ts — 공용 헬퍼, brain 파일 캐시 포함

Agent 파이프라인

메모리 / 검색 / 분류

LM Studio Lifecycle

사이드바

테스트

8. 결론

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

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


문서 갱신일: 2026-05-08