- WS response 파일에 _from_ws 마커 추가하여 processResponseFile 삭제 방지 - extractContextFromNearby에 sibling 탐색 추가 (AG Native DOM 구조 대응) - thinking 블록 (max-h-[200px]) 필터링으로 내부 사고 릴레이 차단 - DOM 탐색 depth 5→10 확대 + pre.font-mono 우선 탐색 - 사용자 메시지 셀렉터 (.select-text.rounded-lg) 추가
9.1 KiB
AG Native 릴레이 아키텍처 분석
이 문서는 AG Native ↔ Discord 릴레이의 데이터 흐름 SSOT입니다. 구현/디버깅 전 반드시 확인합니다.
1. 데이터 경로 요약
AG Native에서 Discord로 메시지를 전달하는 경로는 크게 2개:
| # | 경로 | 소스 | 실시간? | 상태 |
|---|---|---|---|---|
| 1 | Observer DOM | workbench.html 인라인 스크립트 → DOM 관찰 → HTTP POST → http-bridge | ✅ 실시간 | AI 응답: ✅ 작동 (v0.5.72+), 사용자 메시지: ✅ 작동 (v0.5.74+) |
| 2 | Step Probe (trajectory API) | LS RPC GetCascadeTrajectorySteps → step 분석 |
❌ cascade 완료 후에만 | AI 응답: ❌ 실시간 불가, 사용자 메시지: ❌ 실시간 불가 |
1.1 핵심 API 제약 (2026-04-18 확인)
Caution
GetCascadeTrajectorySteps는 진행 중인 cascade의 step을 실시간으로 반환하지 않습니다. step count는 cascade가 완전히 종료(IDLE 전환)된 후에만 업데이트됩니다. 따라서 Step Probe의 RT-CAPTURE, HB-CAPTURE 모두 현재 진행 중인 대화에서는 작동하지 않습니다.
검증 데이터:
- POLL에서
status=CASCADE_RUN_STATUS_IDLE,steps=928,delta=0고정 - HEARTBEAT probe:
offset=927 got=1 real=928 known=928→ 변함 없음 - 실제로 수십 개의 tool call이 실행되었지만 step count 불변
- Cascade 종료 후 다음 poll에서 step count가 점프 (예: 733 → 865 → 928)
1.2 AG Native SDK EventMonitor
SDK에 이벤트 시스템이 있으나 모두 polling 기반:
EventMonitor.onStepCountChanged— getDiagnostics 기반 pollingEventMonitor.onActiveSessionChanged— state.vscdb 기반 polling- 실시간 push (WebSocket/SSE)는 없음
- 현재 상태: ERR_CONNECTION_REFUSED 문제로 비활성화됨
2. Observer DOM 경로 상세
2.1 Observer 스크립트 삽입 체인
extension.ts activate()
→ html-patcher.ts setupApprovalObserver()
→ observer-script.ts generateApprovalObserverScript(port)
→ workbench-jetski-agent.html에 인라인 <script> 삽입
→ AG 재시작 시 렌더러가 로드
2.2 Observer 주요 함수
| 함수 | 역할 |
|---|---|
scanChatBodies() |
3초마다 실행, conversation view에서 메시지 블록 탐색 |
extractCleanStepText(el) |
DOM 클론 → style/script/button 제거 → textContent 추출 |
extractContextFromNearby(btn) |
승인 버튼 주변 DOM에서 명령어 텍스트 추출 |
pollResponseGroup(rid, btnRefs) |
response 파일 polling → 버튼 자동 클릭 |
2.3 AI 응답 감지 셀렉터
var responseBlocks = cv.querySelectorAll(
'.leading-relaxed.select-text, ' // ← AI 응답 마크다운 블록 (주력)
+ '.text-ide-message-block-user-color, ' // ← 사용자 메시지 (미매칭)
+ '.text-ide-message-block-bot-color, ' // ← NUX tooltip 전용 (오매칭)
+ '.bg-ide-message-block-user-background, '// ← 사용자 메시지 (미매칭)
+ '[data-message-role="user"], ' // ← 사용자 메시지 (미매칭)
+ '[data-role="user"]' // ← 사용자 메시지 (미매칭)
);
Note
v0.5.74에서 사용자 메시지 셀렉터가 추가되었습니다. AG Native 소스(
jetskiAgent/main.js)의Esn컴포넌트 분석으로 사용자 메시지 CSS 클래스(msn = "bg-gray-500/10 border border-gray-500/20 p-2 rounded-lg w-full text-sm select-text")를 식별. 셀렉터:.select-text.rounded-lg, 역할 판별:rounded-lg있고leading-relaxed없으면 → user
2.4 AI 응답 추출 흐름
scanChatBodies() 3초 간격
→ cv = document.querySelector('#conversation')
→ responseBlocks = cv.querySelectorAll('.leading-relaxed.select-text, ...')
→ lastBlock = responseBlocks[last] (가장 최근 블록)
→ 이미 scrape 됐으면 skip
→ blockText = extractCleanStepText(lastBlock)
→ 안정화 대기 (3초 동안 텍스트 변경 없으면)
→ POST /chat { text, source, block_index, role }
→ http-bridge → writeChatSnapshot() → WS → Discord
2.5 Observer 업데이트 제약
Caution
Observer 코드는 workbench.html에 인라인 삽입됩니다. extension reload만으로는 Observer 코드가 업데이트되지 않습니다. AG 재시작 + V8 CachedData 삭제가 필요합니다. (단, product.json 체크섬이 맞으면 CachedData 삭제 없이 AG 재시작만으로 충분할 수 있음)
3. 승인 버튼 (Auto-Approve) 경로
3.1 "Always run" 자동 승인 흐름
Observer DOM scan
→ "Always run" 버튼 텍스트 감지
→ POST /pending { command: "Always run", description: "...", buttons: [...] }
→ http-bridge _handlePending()
→ alwaysRunDetected = true
→ enrichment 시도:
1. rawDesc에서 > 프롬프트 마커 찾기 → ✅ 성공 (buttons=2일 때 desc에 프롬프트 포함)
2. rawDesc 최장 라인 사용 → buttons=1일 때 desc="Always run"이라 실패
3. v20 fallback: bridge/pending/ 최신 파일에서 command 읽기 → Step Probe pending 있을 때만
→ response 파일 작성 → Observer pollResponseGroup → 버튼 클릭
→ WS sendPending { status: 'auto_approved', command: displayCmd }
→ Discord embed 표시
3.2 명령어 enrichment 현황 (2026-04-18 검증)
| 조건 | 결과 | 빈도 |
|---|---|---|
Observer가 buttons=2 (["Always run","Cancel"])이고 desc에 > 포함 |
✅ 명령어 표시 | ~50% |
Observer가 buttons=1 (["Always run"])이고 desc="Always run" |
❌ "Always run" 표시 | ~50% |
로그 증거 (04:25:59):
AUTO-APPROVE raw: cmd="Always run" desc="…\extension > npm.cmd run compile..." buttons=["Always run","Cancel"]
→ cmd="npm.cmd run compile 2>&1; npm.cmd version patch..." ✅ 성공
AUTO-APPROVE raw: cmd="Always run" desc="Always run" buttons=["Always run"]
→ cmd="Always run" ❌ 실패
buttons=2인 경우("Always run" + "Cancel")는 Observer가 code 블록을 찾아 description에 포함. buttons=1인 경우는 code 블록이 DOM에서 아직 렌더링되지 않았거나 접근 불가.
4. 사용자 메시지 릴레이 상태
4.1 현재 상태: ✅ 작동 (v0.5.74+)
| 경로 | 상태 | 비고 |
|---|---|---|
| Observer DOM | ✅ | .select-text.rounded-lg 셀렉터로 캡처 (v0.5.74) |
| Step Probe (trajectory API) | ❌ | cascade 진행 중 step 조회 불가 |
| Step Probe (observer [USER-MSG]) | ❌ | lastUserInputStepIndex가 갱신되지 않음 |
4.2 해결 방안
- DOM 덤프에서 사용자 메시지 클래스 식별 → Observer 셀렉터 추가
- Cascade 완료 후 Step Probe HB-CAPTURE에서
USER_INPUTstep 캡처 (지연 릴레이)
5. 파일/포트 매핑
| 항목 | 값 |
|---|---|
| Observer 삽입 대상 | workbench-jetski-agent.html |
| HTTP Bridge 포트 | getDeterministicPort('gravity_control') = 18080 |
| Extension 로그 | ~/.gemini/antigravity/bridge/extension.log |
| Pending 파일 | ~/.gemini/antigravity/bridge/pending/*.json |
| Response 파일 | ~/.gemini/antigravity/bridge/response/*.json |
| Chat Snapshot 파일 | ~/.gemini/antigravity/bridge/chat_snapshots/*.json |
| Discord 채널 | #ag-gravity_control (ID: 1483082084540223663) |
| Discord Bot 토큰 | .env → DISCORD_TOKEN |
6. 디버깅 도구
| 도구 | 경로 | 용도 |
|---|---|---|
| Discord 메시지 읽기 | extension/scratch/discord_read.js |
API로 채널 최근 메시지 조회 |
| Discord 채널 목록 | extension/scratch/discord_channels.js |
서버 채널 목록 조회 |
| Extension 로그 확인 | Select-String -Path $logFile -Pattern "패턴" |
실시간 로그 분석 |
| DOM 구조 덤프 | Observer 자동 (CV-CHILDREN 로그) | AG Native DOM 클래스 식별 |
7. 버전 히스토리 (v0.5.67~)
| 버전 | 변경 | 결과 |
|---|---|---|
| v0.5.67 | Observer DOM relay 비활성화, Step Probe RT-CAPTURE로 전환 | ❌ API가 진행중 step 미반환 |
| v0.5.68 | auto-approve enrichment 디버그 로그 추가, 조건 >10 → >3 완화 | Observer가 desc="Always run" 보냄 확인 |
| v0.5.69 | pending 파일 fallback으로 auto-approve 명령어 enrichment | 일부 개선 (Step Probe pending 있을 때만) |
| v0.5.70 | heartbeat 로깅 강화 | API step count 동결 확인 |
| v0.5.71 | heartbeat 3 poll마다 실행, HB-CAPTURE 추가 | API가 진행중 step 미반환 재확인 |
| v0.5.72 | Observer DOM relay 재활성화 | AG 재시작 필요 (Observer HTML 캐시) |
8. 남은 작업 (TODO)
- AG 재시작하여 Observer 반영 확인 — ✅ v0.5.72 작동 확인
- Observer의 AI 응답 릴레이가 작동하는지 Discord에서 확인 — ✅ 작동
- v0.5.73 설치 (MSG-BLOCKS 로그 추가) → AG 재시작 → 사용자 메시지 DOM 클래스 식별
- 사용자 메시지 셀렉터 추가 후 테스트
- "Always run" enrichment 개선 — buttons=1일 때 code 블록 추출 개선
- AI 응답이 마지막 블록만 캡처되는 문제 개선 (전문 캡처)