Root cause: GetCascadeTrajectorySteps has 775-step hard limit, startStepIndex parameter is completely ignored (verified via direct RPC). Solution: GetAllCascadeTrajectories returns: - stepCount: real-time (verified 1413->1457 live) - latestNotifyUserStep: full notificationContent - latestTaskBoundaryStep: full taskName/Status/Summary - stepIndex on each for dedup E2E verified: Python script -> RPC -> snapshot -> Bot -> Discord
6.8 KiB
6.8 KiB
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 구조
{
"thinking": "내부 사고 과정 (SKIP)",
"response": "사용자 대면 텍스트",
"modifiedResponse": "정리된 버전 (있으면 우선 사용)",
"toolCalls": [{"name": "...", "argumentsJson": "..."}],
"thinkingDuration": "0.9s",
"stopReason": "STOP_REASON_STOP_PATTERN"
}
WAITING 상태 미관측
775 steps 중 WAITING 상태가 0개. 이유:
SafeToAutoRun=true→ WAITING 없이 바로 실행- 이미 승인/거부된 step → DONE/CANCELED로 변환
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 문제를 완전히 우회함.
추가 발견 (2026-03-08 07:10)
rawRPC GetCascadeTrajectorySteps 775-step 한계
- RPC는 항상 최대 775 steps 반환 (0-774)
startStepIndex파라미터가 무시됨 — 항상 처음부터 775개- 현재 대화가 1275+ steps이면, steps 775-1274는 접근 불가
- 마지막 PLANNER_RESPONSE (24 chars)가 step 774의 오래된 텍스트
수정: getDiagnostics로 step count 변화 감지 (3초 폴링) + rawRPC는 content 조회용으로만 사용.
currentMax 계산 버그 제거 — getDiagnostics.lastStepIndex를 직접 비교.