# AI Agent Team — 최종 설계서 `C:\Users\CafeVariet-GL552VW\Desktop\source_diff` --- ## 1. 해결할 문제 | 문제 | 원인 | |------|------| | 컨텍스트 포화 → 멈춤/유실 | Gemini CLI Context Rot (20~50%에서 발생) | | 전체 프로젝트 스캔 → Rate Limit | 무차별 파일 읽기 | | 추상적 명령 처리 불가 | 단일 에이전트의 작업 분해 한계 | | 수동 Git/CI 워크플로우 | 자동화 없음 | ## 2. 아키텍처 ``` ┌─ Interface Layer ────────────────────┐ │ Discord Adapter ←→ API Server (FastAPI) │ Web UI Adapter ←→ ↕ │ (CLI Adapter) ←→ REST + SSE/WebSocket └──────────────────────┬───────────────┘ │ ┌──────────────────────▼───────────────┐ │ Orchestrator │ │ │ │ ┌─────────────┐ ┌────────────────┐ │ │ │Project Index │ │Context Manager │ │ │ │구조/import/ │ │파일 선별 │ │ │ │시그니처 캐시 │ │토큰 예산 제어 │ │ │ └──────┬──────┘ └───────┬────────┘ │ │ └────────┬────────┘ │ │ ┌────────▼────────┐ │ │ │ Task Pipeline │ │ │ │ Plan → Code │ │ │ │ → Review → Test │ │ │ │ → Ship │ │ │ └────────┬────────┘ │ │ ┌────────▼────────┐ │ │ │ Rate Limiter │ │ │ │ Session Manager │ │ │ └────────┬────────┘ │ └──────────────────┼───────────────────┘ ┌─────────┼─────────┐ ┌────▼───┐ ┌───▼────┐ ┌──▼───────┐ │Gemini │ │Gitea │ │Vikunja │ │CLI -p │ │API │ │API │ │headless│ │PR/CI │ │태스크 │ └────────┘ └────────┘ └──────────┘ ``` --- ## 3. 핵심 컴포넌트 ### 3.1 API Server ```python # api/server.py — FastAPI POST /projects # 프로젝트 목록 (Gitea 레포 조회) POST /projects/{id}/select # 작업 대상 설정 POST /tasks # 작업 요청 GET /tasks/{id}/status # 진행 상황 (SSE 스트림) POST /tasks/{id}/confirm # 승인/거부 GET /tasks/history # 이력 ``` Discord Bot과 Web UI 모두 이 API를 호출. Orchestrator는 인터페이스를 모름. ### 3.2 Context Manager (핵심 차별화) Gemini CLI의 Context Rot를 구조적으로 해결: ```python class ContextManager: def __init__(self, project_index: ProjectIndex): self.index = project_index self.token_budget = 50_000 # 호출당 토큰 예산 def gather(self, task: str) -> str: """태스크에 필요한 파일만 선별하여 컨텍스트 생성""" # 1. 태스크에서 언급된 파일/함수 추출 targets = self.index.find_relevant(task) # 2. import/caller 관계로 관련 파일 확장 related = self.index.expand_dependencies(targets, depth=2) # 3. 토큰 예산 내에서 관련도 순 포함 context_files = self.fit_budget(related, self.token_budget) # 4. 프롬프트 형식으로 조합 return self.format_context(context_files) ``` ### 3.3 Project Indexer 최초 1회 프로젝트 구조 분석 → 캐시: ```python class ProjectIndex: files: dict[str, FileInfo] # 파일별 메타 (크기, 언어, 라인수) imports: dict[str, list[str]] # import 관계 그래프 signatures: dict[str, list] # 함수/클래스 시그니처 structure: str # 요약된 디렉토리 구조 def find_relevant(self, task: str) -> list[str]: """태스크 설명에서 관련 파일 추출""" def expand_dependencies(self, files, depth) -> list[str]: """import 관계로 관련 파일 확장""" ``` ### 3.4 Task Pipeline ```python class TaskPipeline: async def execute(self, user_request: str, project: str): ctx = self.context_manager # Plan plan_ctx = ctx.gather(f"프로젝트 구조 파악: {user_request}") plan = await gemini_call("planner", plan_ctx + user_request) await self.notify("plan", plan) # Discord/Web에 보고 await self.wait_confirm() # 사용자 승인 대기 # Code + Review (태스크별) for task in plan.tasks: code_ctx = ctx.gather(task.description) code = await gemini_call("coder", code_ctx + task) review_ctx = ctx.gather(f"리뷰: {task.description}") review = await gemini_call("reviewer", review_ctx + code) if not review.passed: code = await gemini_call("coder", code_ctx + review.feedback) # Test test_ctx = ctx.gather("테스트 관련") await gemini_call("tester", test_ctx + changes) # Ship pr = await self.gitea.create_pr(changes) ci = await self.gitea.wait_ci(pr.id) await self.vikunja.complete_tasks(plan.tasks) await self.notify("complete", pr, ci) ``` ### 3.5 GeminiCaller ```python class GeminiCaller: async def call(self, role: str, context: str) -> str: prompt = load_role_prompt(role) cmd = [ "gemini", "-p", context, "--system", prompt, "--approval-mode", "yolo", "-o", "json" ] proc = await asyncio.create_subprocess_exec(*cmd, ...) self.rate_limiter.record() return parse_result(proc.stdout) ``` --- ## 4. 보안 정책 (Mode A 전환) API Server에 `mode` 파라미터: | Mode | Context 생성 | Gemini 접근 | |------|-------------|-------------| | `general` | Context Manager가 원본 파일 전달 | 소스 직접 읽기 가능 | | `secure` | 로컬 LLM이 추상화/마스킹 후 전달 | 소스 원본 접근 불가 | → VEGA 핸드오프 문서 참조 (`docs/vega_handoff.md`) --- ## 5. 디렉토리 구조 ``` source_diff/ ├── main.py # 진입점 ├── config.py # 설정 ├── requirements.txt # fastapi, discord.py, httpx, pydantic, rich ├── api/ │ ├── server.py # FastAPI 서버 │ ├── models.py # 요청/응답 모델 │ └── discord_bot.py # Discord Bot (API 클라이언트) ├── core/ │ ├── orchestrator.py # 작업 흐름 제어 │ ├── context_manager.py # 파일 선별 + 토큰 예산 (핵심) │ ├── project_indexer.py # 프로젝트 구조 분석/캐시 │ ├── gemini_caller.py # gemini -p 역할별 호출 │ ├── task_pipeline.py # Plan→Code→Review→Test→Ship │ ├── rate_limiter.py # 120 RPM / 2,000 RPD │ └── session_manager.py # WorkUnit 관리 ├── integrations/ │ ├── gitea_client.py # git.variet.net API │ ├── vikunja_client.py # plan.variet.net API │ └── ci_monitor.py # Woodpecker CI 결과 대기 ├── prompts/ │ ├── planner.md # 작업 분해 │ ├── coder.md # 코드 수정 │ ├── reviewer.md # 코드 리뷰 │ └── tester.md # 테스트 작성/실행 ├── docs/ │ ├── design_document.md # 이 문서 │ ├── vega_handoff.md # VEGA 핸드오프 │ └── architecture_critique.md # 비판적 검토 └── sessions/ # 작업 로그 ``` --- ## 6. 실전 테스트 계획 ### 테스트 1: Context Manager 단독 효과 ``` [비교 대상] A: gemini -i --include-directories ./src (Gemini CLI 단독) B: gemini -p + Context Manager (관련 파일 4개만 주입) [테스트 시나리오] 기존 프로젝트에서 "interpolation.py의 선형보간을 큐빅스플라인으로 변경" [측정] - 응답 정확도 (관련 파일 잘 찾았는가) - 수정 범위 정확도 (불필요한 수정 없는가) - 토큰 사용량 - 응답 시간 ``` ### 테스트 2: Task Pipeline E2E ``` [시나리오] "README에 설치 방법 섹션 추가해줘" [검증 항목] - Planner가 합리적으로 분해하는가 - Coder가 파일을 정확히 수정하는가 - Reviewer가 문제 발견 시 Coder 재호출이 작동하는가 - Git commit + PR 생성 성공하는가 ``` ### 테스트 3: 대규모 프로젝트 분석 ``` [시나리오] VEGA 프로젝트 (수백 파일)에서 "검색 로직 흐름을 설명해줘" [비교] A: gemini -i (전체 스캔 → Context Rot 예상) B: Context Manager → 검색 관련 파일 10개 선별 → gemini -p [측정] - 분석 완료율 (A는 중간에 멈출 수 있음) - 설명 정확도 - Rate Limit 소모량 ``` --- ## 7. 구현 순서 (실전 테스트 중심) | Step | 작업 | 테스트 | |------|------|--------| | **1** | Project Indexer + Context Manager | 테스트 1 실행 | | **2** | GeminiCaller (역할별 호출) | 역할 전환 동작 확인 | | **3** | Task Pipeline (Plan→Code→Review) | 테스트 2 실행 | | **4** | API Server + Discord Bot | 디스코드→파이프라인 연결 | | **5** | Gitea 연동 (PR/CI) | 테스트 2 E2E | | **6** | Vikunja 연동 | 태스크 자동 등록/완료 | | **7** | 대규모 테스트 | 테스트 3 실행 |