# Architecture > AI 에이전트는 구현 전 이 문서를 반드시 확인합니다. ## 1. 프로젝트 개요 **Gravity Control**은 Antigravity AI 코딩 에이전트와 Discord를 실시간으로 연결하는 브릿지 시스템이다. ### 핵심 목적 - AI 에이전트의 **승인 요청**(코드 실행, 파일 수정 등)을 Discord로 전달하고 사용자 응답을 반환 - AI 에이전트의 **작업 스냅샷**(대화 요약, 진행 상황)을 Discord에 실시간 표시 - **코드 리뷰**(diff review) accept/reject을 Discord에서 처리 - 사용자의 Discord **명령어**(!approve, !reject, !auto 등)를 AG Extension으로 전달 - **Auto-approve 모드**로 무인 작업 지원 ### 시스템 구성 ``` ┌────────────────┐ WebSocket ┌──────────────┐ Discord API ┌─────────┐ │ VS Code │◄──────────────────►│ Hub Server │◄───────────────────►│ Discord │ │ AG Extension │ type:auth/chat │ (hub.py + │ discord.py bot │ 서버 │ │ (TypeScript) │ /pending/resp │ gateway.py)│ │ │ └────────────────┘ └──────────────┘ └─────────┘ ↕ AG SDK (RPC) ↕ ┌────────────────┐ ┌──────────────┐ │ Antigravity │ │ 파일 bridge │ ← 레거시 fallback │ AI Engine │ │ (bridge.py) │ (WS 미사용 시) └────────────────┘ └──────────────┘ ``` --- ## 2. 디렉토리 구조 ``` gravity_control/ ├── main.py # 진입점: Bot + Hub + Watcher 통합 시작 ├── config.py # 환경변수 + .env 로드 (66줄) │ ├── ── 서버 측 (Python) ── ├── bot.py # Discord 봇: 승인 UI, 채널 관리, Hub 핸들러 (1,286줄) ├── hub.py # WebSocket Hub: 연결 관리, 메시지 라우팅 (580줄) ├── auth.py # JWT 토큰 + registration code 인증 (127줄) ├── gateway.py # HTTP REST API + /ws endpoint (310줄) ├── bridge.py # 파일 기반 IPC (레거시 fallback) (479줄) ├── watcher.py # Brain 디렉토리 변경 감시 (290줄) ├── parser.py # Markdown → Discord 변환 (245줄) ├── collector.py # 원격 파일→HTTP 릴레이 (Phase 2 삭제 예정) (517줄) │ ├── ── Extension 측 (TypeScript) ── ├── extension/src/ │ ├── extension.ts # 메인: SDK init, activate, 오케스트레이션 (650줄) │ ├── step-probe.ts # 폴링 + 응답 처리 + 승인 전략 (1,479줄) │ │ # setupMonitor(), processResponseFile(), │ │ # writePendingApproval(), tryApprovalStrategies() │ ├── http-bridge.ts # HTTP 서버 (Renderer↔Extension Host 통신) (280줄) │ │ # startHttpBridge(), getDeterministicPort() │ ├── html-patcher.ts # AG HTML 패치 + product.json 체크섬 (280줄) │ │ # setupApprovalObserver(), updateProductChecksums() │ ├── command-handler.ts # Discord→AG 명령어 처리 (175줄) │ │ # watchCommandsDir(), handleWSCommand() │ ├── observer-script.ts # DOM Observer 스크립트 생성 (698줄) │ │ # generateApprovalObserverScript() │ ├── ws-client.ts # WSBridgeClient: Hub 연결, 재연결, 큐 (505줄) │ ├── step-utils.ts # Step 파싱 순수 함수 4개 (114줄) │ │ # extractPlannerText, filterEphemeral, │ │ # extractToolCommand, extractToolDescription │ └── sdk/ # Antigravity SDK 로컬 임베드 │ ├── index.js # SDK 런타임 (4,014줄) │ └── index.d.ts # SDK 타입 정의 (2,297줄) │ ├── ── 테스트 ── ├── tests/ │ ├── test_ws_hub.py # Hub WS 연결 테스트 │ └── test_syntax.py # Python 구문 검증 │ ├── ── 문서 / 설정 ── ├── .env # 환경변수 (git 제외) ├── .agents/references/ # AI 에이전트 레퍼런스 ├── docs/devlog/ # 작업 로그 └── start_bot.bat # 윈도우용 봇 시작 스크립트 ``` --- ## 3. 핵심 모듈 상세 ### 3.1 Hub (hub.py) — WebSocket 메시지 허브 **역할**: Extension ↔ Bot 간 실시간 양방향 통신 중계 | 기능 | 설명 | |------|------| | 연결 관리 | 프로젝트별 다중 인스턴스, 인스턴스 번호 자동 부여 | | JWT 인증 | registration_code → JWT 발급 → 이후 토큰 재인증 | | 메시지 라우팅 | pending, chat, register, auto_resolve, brain_event | | 응답 역라우팅 | request_id → pending_owners → 원본 Extension으로 전달 | | Rate limiting | per-connection 100msg/10s | | Dedup | msg_id 기반 60s TTL 중복 제거 | | Heartbeat | 30s 간격 ping/pong | **프로토콜**: ``` 1. Client → Server: {type:"auth", registration_code/token, project, pc} 2. Server → Client: {type:"auth_ok", conn_id, instance_number, session_token} 3. 양방향 메시지 교환: - Extension→Hub: pending, chat, register, auto_resolve, brain_event - Hub→Extension: response, command, instance_update, error ``` ### 3.2 Auth (auth.py) — 인증 관리 | 기능 | 설명 | |------|------| | Registration Code | 사전 공유 코드로 최초 인증 | | JWT 발급 | HMAC-SHA256, 24시간 유효 | | 토큰 검증 | 만료/위조 감지, 프로젝트+PC 메타데이터 포함 | ### 3.3 Bot (bot.py) — Discord 인터페이스 | 기능 | 설명 | |------|------| | 승인 UI | Approve/Reject 버튼, diff_review Accept/Reject | | Auto-approve | `!auto` 토글, 세션 간 초기화 | | 채널 관리 | `#ag-{project}` 자동 채널 매칭 | | 스냅샷 전달 | 2000자 초과 시 파일 첨부 | | 명령어 | !approve, !reject, !auto, !status, !send | | Hub 연동 | on_hub_pending, on_hub_chat, on_hub_register 핸들러 | | IDLE 알림 | AI step 종료 시 Discord 알림 | ### 3.4 Extension (extension.ts) — VS Code 확장 (오케스트레이터) | 기능 | 설명 | |------|------| | AG SDK 연동 | getCascadeStatus, getAllTrajectories RPC | | 세션 감지 | activeSessionId 자동 추적 | | 프로젝트 자동 감지 | git remote URL 기반 | | 모듈 초기화 | HTTP bridge, observer, command handler 시작 | | WS bridge | WSBridgeClient 통한 Hub 연결 (우선) | | Status bar | SDK 상태 + 연결 상태 표시 | ### 3.4a HTTP Bridge (http-bridge.ts) `HttpBridgeContext` 인터페이스로 extension.ts의 공유 상태 참조: | 기능 | 설명 | |------|------| | POST /pending | Renderer가 발견한 승인 버튼 보고 | | GET /response/:rid | Renderer가 Discord 응답 폴링 | | GET /trigger-click | Extension→Renderer 클릭 트리거 | | GET/POST /deep-inspect* | DOM 심층 검사 | | getDeterministicPort | 프로젝트명 기반 결정적 포트 | ### 3.4b HTML Patcher (html-patcher.ts) | 기능 | 설명 | |------|------| | setupApprovalObserver | AG Workbench HTML 파일에 observer 스크립트 인라인 삽입 | | updateProductChecksums | product.json SHA256 체크섬 업데이트 (vscode-file:// 프로토콜용) | | CSP 패치 | script-src에 'unsafe-inline' 추가 | | .orig 백업 | 최초 패치 전 원본 백업, 손상 시 자동 복구 | ### 3.4c Command Handler (command-handler.ts) `CommandHandlerContext` 인터페이스로 extension.ts 상태 참조: | 기능 | 설명 | |------|------| | watchCommandsDir | commands/ 디렉토리 fs.watch + 3s 폴링 | | handleWSCommand | WS Hub 경유 명령어 처리 | | !stop, !auto | AG 에이전트 제어 명령어 | | 텍스트 전달 | Discord → AG `sendPromptToAgentPanel` | ### 3.5 Step Probe (step-probe.ts) — 상태 폴링 `BridgeContext` 인터페이스로 extension.ts와 상태 공유: | 기능 | 설명 | |------|------| | setupMonitor | 3초 간격 SDK 폴링, 세션/step 변화 감지 | | processResponseFile | Discord 응답 → AG RPC 실행 | | writePendingApproval | 승인 요청 파일/WS 전송 | | tryApprovalStrategies | 다단계 승인: DOM click → VS Code command → RPC | | setupResponseWatcher | response/ 디렉토리 파일 감시 | **BridgeContext 필드** (14개): `bridgePath`, `projectName`, `sdk`, `wsBridge`, `logToFile`, `autoApproveEnabled`, `activeSessionId`, `setClickTrigger`, `recentDiscordSentTexts`, `writeChatSnapshot`, `writeChatSnapshotWithFiles`, `workspaceUri`, `diffReviewMetadata`, `sessionStalled`, `lastPendingStepIndex`, `stallProbed`, `sawRunningAfterPending` ### 3.6 WS Client (ws-client.ts) — Hub 클라이언트 | 기능 | 설명 | |------|------| | 연결 관리 | WebSocket + 자동 재연결 | | Backoff | 1s→60s 지수 백오프 + ±30% jitter | | 메시지 큐 | 200개 버퍼, 재연결 시 자동 flush | | Heartbeat | 25s 간격 ping | | 인증 | registration_code 또는 session_token | | API | sendPending, sendChat, sendRegister, sendAutoResolve | ### 3.7 Observer Script (observer-script.ts) AG Webview의 DOM을 관찰하여 승인 버튼을 자동 감지/클릭: - MutationObserver로 `.actions-container` 감시 - 버튼 텍스트 매칭으로 Approve/Reject 자동 실행 - `postMessage`로 Extension과 통신 ### 3.8 Step Utils (step-utils.ts) 순수 함수 4개: - `extractPlannerText(content)` — AI 응답 텍스트 추출 - `filterEphemeral(text)` — 시스템 메시지 필터링 - `extractToolCommand(content)` — 도구 명령어 추출 - `extractToolDescription(content)` — 도구 설명 추출 --- ## 4. 데이터 흐름 ### 4.1 승인 요청 플로우 ``` AG Engine → SDK RPC → Extension(step-probe.ts) → setupMonitor: WAITING step 감지 → writePendingApproval: pending 데이터 생성 → [WS] wsBridge.sendPending() → Hub → Bot → Discord (버튼 UI) → [파일] bridge/pending/{id}.json (fallback) ``` ### 4.2 승인 응답 플로우 ``` Discord (사용자 버튼 클릭) → Bot → [Hub connected] Hub.route_response() → WS → Extension → [File fallback] bridge/response/{id}.json → setupResponseWatcher → processResponseFile → tryApprovalStrategies 1차: DOM observer script (webview inject) 2차: VS Code command (cascade.approveCurrentStep) 3차: Direct RPC (acknowledgeCodeActionStep) ``` ### 4.3 채팅 스냅샷 플로우 ``` Extension(step-probe.ts) → 새 step 텍스트 감지 → writeChatSnapshot(text) → truncation + dedup → [WS] wsBridge.sendChat() → Hub → Bot → Discord (#ag-{project}) → [파일] bridge/pending/ snapshot 파일 (fallback) ``` ### 4.4 Diff Review 플로우 ``` AG Engine → 파일 수정 → Extension(step-probe.ts) → edit_step_indices + modified_files 메타데이터 수집 → writePendingApproval (step_type="diff_review") → Discord (Accept all / Reject all 버튼) → 응답 → acknowledgeCodeActionStep RPC ``` --- ## 5. 통신 프로토콜 ### 5.1 WebSocket 메시지 타입 **Extension → Hub (upstream)**: | type | data 필드 | 설명 | |------|-----------|------| | `auth` | registration_code/token, project, pc | 최초 인증 | | `pending` | request_id, command, description, buttons | 승인 요청 | | `chat` | content, attached_files, conversation_id | 채팅 스냅샷 | | `register` | conversation_id, project_name | 세션 등록 | | `auto_resolve` | request_id | 자동 해결 알림 | | `brain_event` | (payload) | 브레인 이벤트 | | `heartbeat` | - | 연결 유지 | **Hub → Extension (downstream)**: | type | data 필드 | 설명 | |------|-----------|------| | `auth_ok` | conn_id, instance_number, session_token | 인증 성공 | | `auth_fail` | reason | 인증 실패 | | `response` | request_id, approved, button_index | 승인 응답 | | `command` | text, action | Discord 명령어 | | `instance_update` | active_count, instances[] | 인스턴스 변경 | | `error` | error | 에러 | ### 5.2 BOT_MODE 동작 차이 | 모드 | Watcher | Hub/Gateway | 용도 | |------|---------|-------------|------| | `local` | ✅ (brain 감시) | ❌ | 로컬 개발 (Extension과 같은 PC) | | `gateway` | ❌ | ✅ (port 8585) | 서버 배포 (WS Hub + Gateway) | | `remote` | ✅ | ❌ | 원격 브릿지 (레거시 Collector) | --- ## 6. 보안 | 항목 | 구현 | |------|------| | WS 인증 | Registration Code → JWT (HMAC-SHA256, 24h) | | Gateway API | API Key 헤더 (`X-API-Key`) | | Rate limit | per-connection 100msg/10s | | 메시지 dedup | msg_id 기반 60s TTL | | Discord | Bot 토큰 + Guild ID 제한 | --- ## 7. Extension 설정 (VS Code) | 설정 키 | 설명 | 기본값 | |---------|------|--------| | `gravityBridge.bridgePath` | Bridge 디렉토리 경로 | `~/.gemini/antigravity/bridge` | | `gravityBridge.projectName` | 프로젝트 이름 | git remote 자동 감지 | | `gravityBridge.hubUrl` | WebSocket Hub URL | (비어있으면 WS 비활성) | | `gravityBridge.registrationCode` | Hub 등록 코드 | (서버에서 발급) |