refactor: .agents + .agent 단일 .agent 디렉토리로 통합 (agent_guide 포맷, 12→7 워크플로우 축소)
This commit is contained in:
75
.agent/references/architecture.md
Normal file
75
.agent/references/architecture.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Architecture
|
||||
|
||||
> Variet Agent — Gemini CLI 기반 AI Agent Team 시스템
|
||||
|
||||
## 프로젝트 개요
|
||||
|
||||
사용자가 디스코드에서 자연어 명령 → AI Agent Team이 코드 분석/분해/실행 → Gitea CI로 PR/빌드/배포.
|
||||
Gemini CLI를 서브프로세스(`asyncio.create_subprocess_exec`)로 래핑하여 역할별 독립 컨텍스트로 호출.
|
||||
|
||||
## 디렉토리 구조
|
||||
|
||||
```
|
||||
variet-agent/
|
||||
├── main.py # 진입점 (FastAPI + Discord Bot 동시 실행)
|
||||
├── config.py # .env 기반 설정 관리
|
||||
├── api/
|
||||
│ ├── server.py # FastAPI REST 서버
|
||||
│ ├── discord_bot.py # Discord Bot (NLU + PCRS 파이프라인 + 애니 핸들러)
|
||||
│ └── models.py # 요청/응답 모델
|
||||
├── core/
|
||||
│ ├── task_pipeline.py # PCRS: Plan → Code → Review → Summarize
|
||||
│ ├── gemini_caller.py # Gemini CLI 래퍼 (text/agent 모드)
|
||||
│ ├── context_manager.py # 관련 파일 선별 + 토큰 예산 제어
|
||||
│ ├── project_indexer.py # 프로젝트 구조 스캔/캐시
|
||||
│ ├── workspace.py # 워크스페이스 관리 (채널 ↔ 프로젝트 매핑)
|
||||
│ ├── file_applier.py # 코드 변경 적용
|
||||
│ └── docs_manager.py # 문서/세션 기록
|
||||
├── tools/ # 자동화 도구 (애니메이션 파이프라인)
|
||||
│ ├── anime_pipeline.py # 통합 파이프라인 (검색/다운/자막/상태)
|
||||
│ ├── anissia_client.py # Anissia 편성표 API
|
||||
│ ├── nyaa_client.py # Nyaa 토렌트 검색
|
||||
│ ├── qbit_client.py # qBittorrent 제어
|
||||
│ ├── nas_scanner.py # NAS 파일 스캔
|
||||
│ ├── title_matcher.py # 제목 매칭 (로마지/퍼지)
|
||||
│ └── subtitle_downloader.py # 자막 다운로더
|
||||
├── integrations/
|
||||
│ ├── gitea_client.py # Gitea API (PR/이슈)
|
||||
│ ├── vikunja_client.py # Vikunja 태스크 관리
|
||||
│ └── ci_monitor.py # CI 결과 모니터링
|
||||
└── prompts/ # AI 역할별 프롬프트
|
||||
├── unified.md # NLU 분류 (chat/task/anime/clarify)
|
||||
├── planner.md # 태스크 분해
|
||||
├── coder.md # 코드 구현
|
||||
├── reviewer.md # 코드 리뷰
|
||||
└── summarizer.md # 총평 생성
|
||||
```
|
||||
|
||||
## 핵심 모듈
|
||||
|
||||
| 모듈 | 역할 | 의존성 |
|
||||
|------|------|--------|
|
||||
| `discord_bot.py` | 사용자 인터페이스 + NLU 분류 | `workspace.py`, `gemini_caller.py`, `task_pipeline.py` |
|
||||
| `task_pipeline.py` | PCRS 오케스트레이션 (Inner/Outer 루프) | `gemini_caller.py`, `context_manager.py`, `project_indexer.py` |
|
||||
| `gemini_caller.py` | Gemini CLI 서브프로세스 호출 (text/agent) | `prompts/` |
|
||||
| `context_manager.py` | 태스크 기반 파일 선별 + 토큰 예산 | `project_indexer.py` |
|
||||
| `workspace.py` | 채널 ↔ 프로젝트 경로 매핑, workspaces.json 관리 | — |
|
||||
| `anime_pipeline.py` | 애니 자동화 통합 | `anissia_client.py`, `nyaa_client.py`, `qbit_client.py`, `nas_scanner.py` |
|
||||
|
||||
## 데이터 흐름
|
||||
|
||||
```
|
||||
Discord 메시지
|
||||
→ on_message()
|
||||
→ _unified_call() — NLU 분류 (chat/task/anime/clarify)
|
||||
├─ chat → 즉답
|
||||
├─ clarify → 질문 임베드
|
||||
├─ anime → _handle_anime() → AnimePipeline
|
||||
└─ task → _handle_task()
|
||||
→ TaskPipeline.plan() — Planner (태스크 분해)
|
||||
→ TaskPipeline.code_parallel() — Coder (에이전트 모드, cwd=프로젝트)
|
||||
→ TaskPipeline.planner_verify() — 내부 자가검증 (Inner Loop)
|
||||
→ TaskPipeline.batch_review() — Reviewer (Outer Loop)
|
||||
→ TaskPipeline.summarize() — 총평
|
||||
→ Discord Embed 보고
|
||||
```
|
||||
45
.agent/references/conventions.md
Normal file
45
.agent/references/conventions.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Coding Conventions
|
||||
|
||||
> AI 에이전트는 코드를 작성하기 전 이 컨벤션을 확인합니다.
|
||||
|
||||
## 네이밍
|
||||
|
||||
| 대상 | 규칙 | 예시 |
|
||||
|------|------|------|
|
||||
| 변수/함수 | camelCase | `getUserData()` |
|
||||
| 클래스 | PascalCase | `UserService` |
|
||||
| 상수 | UPPER_SNAKE_CASE | `MAX_RETRY_COUNT` |
|
||||
| 파일명 | kebab-case | `user-service.js` |
|
||||
| CSS 클래스 | kebab-case | `.nav-header` |
|
||||
|
||||
## 코드 스타일
|
||||
|
||||
- 들여쓰기: (2 spaces / 4 spaces / tab)
|
||||
- 세미콜론: (사용 / 미사용)
|
||||
- 따옴표: (single / double)
|
||||
- 줄바꿈: LF (Unix style)
|
||||
|
||||
## 커밋 메시지
|
||||
|
||||
```
|
||||
<type>(<scope>): <description>
|
||||
|
||||
type: feat|fix|refactor|test|docs|chore|ci|infra
|
||||
scope: (선택)
|
||||
```
|
||||
|
||||
**예시:**
|
||||
- `feat(server): add WebSocket reconnection logic`
|
||||
- `fix(frontend): resolve button overlap on mobile`
|
||||
- `docs: update API documentation`
|
||||
|
||||
## 주석
|
||||
|
||||
- 한국어/영어 혼용 가능
|
||||
- TODO 주석: `// TODO: 설명` 형식
|
||||
- 복잡한 로직에는 반드시 WHY(왜) 주석 추가
|
||||
|
||||
## 테스트
|
||||
|
||||
- 테스트 파일 위치: (예: `__tests__/` 또는 `*.test.js`)
|
||||
- 테스트 네이밍: `should [expected behavior] when [condition]`
|
||||
59
.agent/references/known-issues.md
Normal file
59
.agent/references/known-issues.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# Known Issues & Lessons Learned
|
||||
|
||||
> **이 파일은 SSOT(Single Source of Truth)입니다.**
|
||||
> 디버깅이나 구현 전에 **반드시** 이 파일을 확인하세요.
|
||||
> 세션 종료 시 새로 발견된 이슈를 이 파일에 추가합니다.
|
||||
|
||||
---
|
||||
|
||||
## 포맷
|
||||
|
||||
각 항목은 아래 형식을 따릅니다:
|
||||
|
||||
```markdown
|
||||
### [날짜] [키워드] — 한줄 요약
|
||||
- **증상**: 무엇이 잘못되었는가
|
||||
- **원인**: 근본 원인
|
||||
- **해결**: 올바른 해결 방법
|
||||
- **주의**: 재발 방지를 위한 교훈
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 공통 이슈
|
||||
|
||||
### [2026-03-08] PowerShell curl — Invoke-WebRequest 충돌
|
||||
- **증상**: `curl` 명령이 예상과 다른 응답 형식을 반환
|
||||
- **원인**: PowerShell에서 `curl`은 `Invoke-WebRequest`의 별칭
|
||||
- **해결**: **`curl.exe`**를 명시적으로 사용
|
||||
- **주의**: HTTP 관련 모든 명령에서 `curl.exe` 사용 필수
|
||||
|
||||
### [2026-03-08] PowerShell npm — 실행 정책 오류
|
||||
- **증상**: `npm run` 명령이 `실행 정책` 관련 오류로 실패
|
||||
- **원인**: PowerShell 스크립트 실행 정책이 제한적으로 설정됨
|
||||
- **해결**: `cmd /c npm run dev` 형식으로 cmd를 통해 실행
|
||||
- **주의**: npm 관련 명령은 항상 `cmd /c` 접두어 사용 권장
|
||||
|
||||
---
|
||||
|
||||
## 프로젝트별 이슈
|
||||
|
||||
> 아래에 프로젝트 특화 이슈를 추가하세요.
|
||||
|
||||
### [2026-03-08] nas_scanner docstring — Unicode escape SyntaxError
|
||||
- **증상**: `from tools.nas_scanner import NasScanner` 시 `SyntaxError: (unicode error) 'unicodeescape' codec can't decode \N`
|
||||
- **원인**: docstring 내 `\\NasData` 경로에서 `\N`이 Python Unicode named escape로 해석
|
||||
- **해결**: docstring을 `r"""..."""` (raw string)으로 변경
|
||||
- **주의**: Windows 경로(`\\`, `\N`, `\U` 등)가 포함된 docstring은 반드시 `r"""`로 작성
|
||||
|
||||
### [2026-03-08] title_matcher _kata_to_hira — 장음기호 깨짐
|
||||
- **증상**: `フリーレン` → `ふり゜れん` (ー가 ゜로 변환)
|
||||
- **원인**: 카타카나 범위 `0x30A0~0x30FF`에 기호 문자(`ー` U+30FC) 포함
|
||||
- **해결**: 범위를 `0x30A1~0x30F6`으로 좁혀 실제 문자만 변환
|
||||
- **주의**: 유니코드 범위 지정 시 기호/구두점 문자 포함 여부 확인 필수
|
||||
|
||||
### [2026-03-08] anime_pipeline — Nyaa 검색 0건 반환
|
||||
- **증상**: 한자 포함 원제의 로마자 변환 결과(`葬送nofuriren`) + suffix 고정으로 Nyaa 검색 실패
|
||||
- **원인**: 단일 검색 전략, suffix(ASW HEVC) 항상 부착
|
||||
- **해결**: 6단계 fallback 전략 (romaji±suffix → 원제±suffix → 한글±suffix)
|
||||
- **주의**: 외부 API 검색 시 반드시 다중 전략 + suffix 토글 구현
|
||||
59
.agent/references/tech-stack.md
Normal file
59
.agent/references/tech-stack.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# Tech Stack
|
||||
|
||||
> AI 에이전트는 구현 전 이 문서를 확인하여 올바른 기술/버전을 사용합니다.
|
||||
|
||||
## 언어 & 런타임
|
||||
|
||||
| 항목 | 버전 | 비고 |
|
||||
|------|------|------|
|
||||
| Python | 3.12+ | `C:\ProgramData\miniforge3\envs\variet-agent\python.exe` |
|
||||
| Gemini CLI | v0.32+ (AI Ultra) | `gemini --model gemini-3-flash-preview` |
|
||||
|
||||
## 프레임워크
|
||||
|
||||
| 항목 | 버전 | 용도 |
|
||||
|------|------|------|
|
||||
| FastAPI | 최신 | REST API 서버 |
|
||||
| discord.py | 2.x | Discord Bot |
|
||||
| uvicorn | 최신 | ASGI 서버 |
|
||||
| httpx | 최신 | 비동기 HTTP 클라이언트 (tools/) |
|
||||
|
||||
## 패키지 관리
|
||||
|
||||
- 패키지 매니저: pip (conda env `variet-agent`)
|
||||
- 의존성 파일: `requirements.txt`
|
||||
- 가상환경: `C:\ProgramData\miniforge3\envs\variet-agent`
|
||||
|
||||
## 개발 도구
|
||||
|
||||
| 도구 | 명령어 |
|
||||
|------|--------|
|
||||
| 봇 실행 | `run_bot.bat` 또는 `C:\ProgramData\miniforge3\envs\variet-agent\python.exe main.py` |
|
||||
| 테스트 | `C:\ProgramData\miniforge3\envs\variet-agent\python.exe -m pytest tests/ -v` |
|
||||
| Vikunja 조회 | `C:\ProgramData\miniforge3\envs\variet-agent\python.exe .agent\workflows\helpers\vikunja_helper.py list todo` |
|
||||
|
||||
## 환경 변수 (.env)
|
||||
|
||||
| 변수명 | 용도 | 기본값 |
|
||||
|--------|------|--------|
|
||||
| DISCORD_BOT_TOKEN | Discord 봇 토큰 | (필수) |
|
||||
| API_HOST | API 서버 호스트 | 0.0.0.0 |
|
||||
| API_PORT | API 서버 포트 | 8000 |
|
||||
| GITEA_URL | Gitea 서버 | https://git.variet.net |
|
||||
| GITEA_TOKEN | Gitea API 토큰 | (필수) |
|
||||
| GITEA_REPO | Gitea 저장소 | Variet/variet-agent |
|
||||
| VIKUNJA_URL | Vikunja 서버 | https://plan.variet.net |
|
||||
| VIKUNJA_TOKEN | Vikunja API 토큰 | (필수) |
|
||||
| VIKUNJA_PROJECT_ID | Vikunja 프로젝트 ID | 7 |
|
||||
| QBIT_URL | qBittorrent URL | http://localhost:8080 |
|
||||
| NAS_ANIME_PATH | NAS 애니 경로 | \\\\192.168.10.10\NasData\Video\Animation |
|
||||
|
||||
## 외부 서비스
|
||||
|
||||
| 서비스 | URL | 용도 |
|
||||
|--------|-----|------|
|
||||
| Gitea | git.variet.net | Git 저장소, PR, CI |
|
||||
| Vikunja | plan.variet.net | 태스크 관리 (프로젝트 #7) |
|
||||
| Anissia | anissia.net | 애니 편성표/자막 |
|
||||
| Nyaa | nyaa.si | 토렌트 검색 |
|
||||
| qBittorrent | localhost:8080 | 토렌트 다운로드 |
|
||||
Reference in New Issue
Block a user