fix(bridge): rawRPC direct polling + SDK analysis docs + trial-and-error log
- Root cause: getDiagnostics.lastStepIndex is stale, SDK EventMonitor cannot detect real-time step changes
- Fix: Direct rawRPC('GetCascadeTrajectorySteps') polling every 5s
- Relay: PLANNER_RESPONSE, NOTIFY_USER, TASK_BOUNDARY, WAITING steps
- Added: docs/discord-bridge-analysis.md (full SDK architecture analysis)
- Added: docs/devlog/entries/20260308-003.md (trial-and-error history)
- Added: antigravity-sdk-main/ source reference
- Vikunja: #252 done, #253 created, #251 commented
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
# 2026-03-08 Devlog — Bridge 프로토콜 수정
|
||||
# 2026-03-08 Devlog — Bridge 프로토콜 수정 + 딥 디버깅
|
||||
|
||||
| # | 시간 | 작업 | 커밋 | 상태 |
|
||||
|---|------|------|------|------|
|
||||
| 1 | 01:00 | Extension↔Bot 프로토콜 불일치 3건 수정 + sql-wasm 번들링 | `e4dc1b1` | 🔧 |
|
||||
| 2 | 01:45~02:25 | Discord Bridge 디버깅: step 구조 파악, 승인 버튼, AI 텍스트 릴레이 | `0c3d6cd` | ✅ |
|
||||
| 3 | 05:30 | 모든 WAITING step relay 구현 + Step type 전체 매핑 (775 steps, 17 types) | - | ✅ |
|
||||
| 4 | 06:10 | 채널 등록 자동화 (writeRegistration) + Bot 파이프라인 검증 | - | ✅ |
|
||||
| 5 | 06:30 | **근본 원인 발견**: getDiagnostics.lastStepIndex stale 문제 | - | ✅ |
|
||||
| 6 | 06:45 | SDK 소스 전체 분석 (antigravity-sdk v1.6.0 — EventMonitor, CascadeManager) | - | ✅ |
|
||||
| 7 | 06:55 | **PRIMARY RELAY 재작성** — rawRPC 직접 5초 폴링으로 전환 | - | 🔧 |
|
||||
|
||||
46
docs/devlog/entries/20260308-003.md
Normal file
46
docs/devlog/entries/20260308-003.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Discord Bridge 딥 디버깅 — 시행착오 기록
|
||||
|
||||
- **시간**: 2026-03-08 05:30~07:00
|
||||
- **Vikunja**: #252 → done, #253 진행중, #251 코멘트 추가
|
||||
|
||||
## 시행착오 요약 (소거법)
|
||||
|
||||
### ❌ 시도 1: Bot 재시작 불필요
|
||||
- **가설**: Bot이 죽어서 메시지가 안 간다
|
||||
- **현실**: Bot은 PID 25508로 정상 동작 중이었음
|
||||
- **배움**: Bot 프로세스 확인은 `Get-Process -Name python | Select PID,StartTime`
|
||||
|
||||
### ❌ 시도 2: 수동 테스트 파일 깨짐 (BOM 인코딩)
|
||||
- **가설**: Bot이 파일을 안 읽는다
|
||||
- **현실**: `cmd /c echo {...} > file.json`이 BOM(FF FE) 포함 UTF-16 생성
|
||||
- **배움**: **테스트 파일은 PowerShell Set-Content -Encoding UTF8 사용**
|
||||
- **증거**: Bot 로그에 `Expecting property name enclosed in double quotes` 반복
|
||||
|
||||
### ❌ 시도 3: getDiagnostics 기반 진단 폴링 무의미
|
||||
- **가설**: getDiagnostics 데이터로 step 변화를 잡을 수 있다
|
||||
- **현실**: `getDiagnostics.recentTrajectories.lastStepIndex`가 **실시간 업데이트 안 됨**
|
||||
- **증거**: POLL#1~#2 모두 `steps=1237 known=0` 고정 (실제 step은 1239+)
|
||||
- **배움**: **getDiagnostics는 세션 메타데이터용, 실시간 step 추적 불가**
|
||||
|
||||
### ❌ 시도 4: SDK EventMonitor 의존 불가
|
||||
- **가설**: SDK monitor.onStepCountChanged가 실시간 감지
|
||||
- **현실**: EventMonitor._pollTrajectories()가 getDiagnostics 사용 → stale
|
||||
- **배움**: **SDK EventMonitor는 실시간 step 추적에 부적합**
|
||||
|
||||
### ✅ 최종 해결: rawRPC 직접 폴링
|
||||
- `GetCascadeTrajectorySteps` rawRPC는 **실시간 step 데이터를 정확히 반환**
|
||||
- 5초 간격 폴링으로 PLANNER_RESPONSE, NOTIFY_USER, TASK_BOUNDARY, WAITING 릴레이
|
||||
- `getDiagnostics`는 active session ID 확인 용도로만 (최초 + 60초마다)
|
||||
|
||||
## 핵심 교훈
|
||||
|
||||
| # | 교훈 | 카테고리 |
|
||||
|---|------|----------|
|
||||
| 1 | `cmd /c echo`로 JSON 만들지 마라 (BOM) | Windows |
|
||||
| 2 | `getDiagnostics.lastStepIndex`는 stale | SDK |
|
||||
| 3 | SDK EventMonitor는 getDiagnostics 의존 | SDK |
|
||||
| 4 | `rawRPC('GetCascadeTrajectorySteps')`만 실시간 | SDK |
|
||||
| 5 | Step control은 `vscode.commands` 사용 | SDK |
|
||||
| 6 | 분석 문서는 brain이 아닌 프로젝트 docs에 저장 | 프로세스 |
|
||||
|
||||
## 참조: `docs/discord-bridge-analysis.md`
|
||||
147
docs/discord-bridge-analysis.md
Normal file
147
docs/discord-bridge-analysis.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# Discord Bridge 디버깅 분석 로그
|
||||
|
||||
> 날짜: 2026-03-08
|
||||
> 세션: e7b46728-6c7d-4220-b45a-d79e5a8c2318
|
||||
|
||||
## 1. Step Type 전체 매핑 (775 steps)
|
||||
|
||||
`GetCascadeTrajectorySteps` RPC로 현재 세션의 775개 step을 덤프한 결과:
|
||||
|
||||
| Step Type | 횟수 | Statuses | Data Key | Discord 전달 여부 |
|
||||
|-----------|------|----------|----------|------------------|
|
||||
| PLANNER_RESPONSE | 218 | DONE | plannerResponse | ✅ AI 응답 (핵심) |
|
||||
| EPHEMERAL_MESSAGE | 186 | DONE | ephemeralMessage | ❌ 내부 시스템 알림 |
|
||||
| RUN_COMMAND | 81 | DONE, CANCELED | runCommand | ✅ 명령 실행 (WAITING 시) |
|
||||
| TASK_BOUNDARY | 71 | DONE | taskBoundary | 🟡 작업 진행 상태 |
|
||||
| USER_INPUT | 38 | DONE | userInput | 🟡 사용자 입력 |
|
||||
| VIEW_FILE | 38 | DONE | viewFile, permissions | ❌ 파일 읽기 |
|
||||
| CODE_ACTION | 36 | DONE, ERROR | codeAction, error | ✅ 파일 수정/생성 (WAITING 시) |
|
||||
| ERROR_MESSAGE | 33 | DONE | errorMessage | ❌ 에러 |
|
||||
| GREP_SEARCH | 18 | DONE | grepSearch | ❌ 검색 |
|
||||
| NOTIFY_USER | 18 | DONE | notifyUser | ✅ 사용자 알림 |
|
||||
| VIEW_CODE_ITEM | 9 | DONE | viewCodeItem | ❌ 코드 조회 |
|
||||
| CONVERSATION_HISTORY | 7 | DONE | conversationHistory | ❌ 대화 이력 주입 |
|
||||
| KNOWLEDGE_ARTIFACTS | 7 | DONE | knowledgeArtifacts | ❌ KI 주입 |
|
||||
| CHECKPOINT | 7 | DONE | checkpoint | ❌ 세션 체크포인트 |
|
||||
| LIST_DIRECTORY | 4 | DONE | listDirectory, permissions | ❌ 디렉토리 조회 |
|
||||
| VIEW_FILE_OUTLINE | 2 | DONE | viewFileOutline | ❌ 파일 아웃라인 |
|
||||
| FIND | 2 | DONE | find | ❌ 파일 검색 |
|
||||
|
||||
### PLANNER_RESPONSE 구조
|
||||
```json
|
||||
{
|
||||
"thinking": "내부 사고 과정 (SKIP)",
|
||||
"response": "사용자 대면 텍스트",
|
||||
"modifiedResponse": "정리된 버전 (있으면 우선 사용)",
|
||||
"toolCalls": [{"name": "...", "argumentsJson": "..."}],
|
||||
"thinkingDuration": "0.9s",
|
||||
"stopReason": "STOP_REASON_STOP_PATTERN"
|
||||
}
|
||||
```
|
||||
|
||||
### WAITING 상태 미관측
|
||||
775 steps 중 `WAITING` 상태가 **0개**. 이유:
|
||||
1. `SafeToAutoRun=true` → WAITING 없이 바로 실행
|
||||
2. 이미 승인/거부된 step → DONE/CANCELED로 변환
|
||||
3. `GetCascadeTrajectorySteps`는 완료된 step만 반환하는 것으로 보임
|
||||
|
||||
---
|
||||
|
||||
## 2. SDK 아키텍처 분석 (antigravity-sdk v1.6.0)
|
||||
|
||||
### 전체 구조
|
||||
```
|
||||
AntigravitySDK
|
||||
├── commands: CommandBridge ← vscode.commands.executeCommand 래퍼
|
||||
├── state: StateBridge ← state.vscdb (USS) 직접 읽기
|
||||
├── cascade: CascadeManager ← 대화 관리 + step control
|
||||
├── monitor: EventMonitor ← 상태 변화 감지 (polling)
|
||||
├── ls: LSBridge ← Language Server RPC (rawRPC)
|
||||
└── integration: IntegrationManager ← Agent View UI 커스터마이즈
|
||||
```
|
||||
|
||||
### EventMonitor (transport/event-monitor.ts)
|
||||
- **USS 폴링**: `state.vscdb` 키 크기 변화 감지 (setInterval)
|
||||
- **Trajectory 폴링**: `antigravity.getDiagnostics` → `recentTrajectories[].lastStepIndex` 비교
|
||||
- 데이터 소스: `vscode.commands.executeCommand('antigravity.getDiagnostics')`
|
||||
- `recentTrajectories`는 최근 10개 대화만 포함
|
||||
|
||||
### Step Control (cascade/cascade-manager.ts)
|
||||
|
||||
| 메서드 | VS Code 명령어 | 용도 |
|
||||
|--------|----------------|------|
|
||||
| `acceptStep()` | `antigravity.agent.acceptAgentStep` | 코드 수정 승인 |
|
||||
| `rejectStep()` | `antigravity.agent.rejectAgentStep` | 코드 수정 거부 |
|
||||
| `acceptTerminalCommand()` | `antigravity.terminalCommand.accept` | 터미널 명령 승인 |
|
||||
| `rejectTerminalCommand()` | `antigravity.terminalCommand.reject` | 터미널 명령 거부 |
|
||||
| `acceptCommand()` | `antigravity.command.accept` | 비터미널 액션 승인 |
|
||||
| `rejectCommand()` | `antigravity.command.reject` | 비터미널 액션 거부 |
|
||||
|
||||
> **핵심**: Step control은 **vscode.commands**, rawRPC가 아님!
|
||||
|
||||
---
|
||||
|
||||
## 3. 파이프라인 테스트 (소거법)
|
||||
|
||||
### 파이프라인 구조
|
||||
```
|
||||
Extension step event → 텍스트 추출 → chat_snapshots/*.json 쓰기
|
||||
→ Bot scanner (5초) → Discord 전송
|
||||
```
|
||||
|
||||
### 테스트 결과
|
||||
|
||||
| Stage | 테스트 | 결과 |
|
||||
|-------|--------|------|
|
||||
| 1. Step 감지 | onStepCountChanged | ✅ step 1239 (+2) |
|
||||
| 1. 등록 | register 파일 | ✅ e7b46728→gravity_control |
|
||||
| 2. 텍스트 추출 | PLANNER_RESPONSE | ✅ 24 chars |
|
||||
| 3. 파일 쓰기 | chat_snapshots/*.json | ✅ 파일 생성됨 |
|
||||
| 4. Bot 스캔 | chat_snapshot_scanner | ✅ 정상 동작 (정상 JSON) |
|
||||
| 5. Discord 전송 | 채널 전송 | ✅ 수동 테스트 파일 도착 |
|
||||
|
||||
### 핵심 문제 발견
|
||||
|
||||
**`getDiagnostics.recentTrajectories.lastStepIndex`가 실시간 업데이트되지 않는다.**
|
||||
|
||||
Console POLL 데이터:
|
||||
```
|
||||
[POLL#1] e7b46728 steps=1237 known=0 "Debugging Discord Bridge"
|
||||
[POLL#2] e7b46728 steps=1237 known=0 "Debugging Discord Bridge"
|
||||
```
|
||||
|
||||
- `steps=1237` — getDiagnostics에서 반환하는 lastStepIndex
|
||||
- 실제로는 1239+ steps가 존재 (step event는 1239 감지)
|
||||
- 이후 대화 턴에서 step이 계속 추가되지만 `lastStepIndex`는 1237에서 변하지 않음
|
||||
- 결과: SDK EventMonitor가 변화를 감지 못함 → `onStepCountChanged` 미발생
|
||||
|
||||
### `known=0` 문제
|
||||
- POLL에서 `known=0` = `lastSeenStep` 맵이 비어있음
|
||||
- step event에서 `lastSeenStep.set()`이 실행되어야 하지만,
|
||||
one-time full dump의 async 대기 중에 POLL이 먼저 실행될 수 있음
|
||||
- MISSED STEPS 복구 조건이 `known > 0`이라 초기 상태에서 작동 안 함
|
||||
|
||||
---
|
||||
|
||||
## 4. 남은 문제 & 다음 단계
|
||||
|
||||
### 근본 원인
|
||||
`getDiagnostics`의 `lastStepIndex`가 실시간 반영되지 않아
|
||||
SDK EventMonitor의 trajectory polling이 새 step을 감지하지 못함.
|
||||
|
||||
### 적용된 해결책 (2026-03-08 06:55)
|
||||
|
||||
**PRIMARY RELAY 완전 재작성**: `getDiagnostics` 의존 제거, 직접 `rawRPC` 폴링
|
||||
|
||||
```
|
||||
setInterval (5초마다):
|
||||
1. getDiagnostics로 active session ID 확보 (초회 + 60초마다 갱신)
|
||||
2. rawRPC('GetCascadeTrajectorySteps', {cascadeId, startStepIndex}) 직접 호출
|
||||
3. step count 변화 감지 → 새 step 추출
|
||||
4. PLANNER_RESPONSE → chat_snapshots (AI 응답)
|
||||
5. NOTIFY_USER → chat_snapshots (알림)
|
||||
6. TASK_BOUNDARY → chat_snapshots (작업 상태)
|
||||
7. WAITING → pending approval (승인 대기)
|
||||
```
|
||||
|
||||
이 방식은 `getDiagnostics.lastStepIndex`의 stale 문제를 완전히 우회함.
|
||||
Reference in New Issue
Block a user