Files
gravity_control/.agents/references/relay-architecture.md

9.9 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 기반 polling
  • EventMonitor.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에서 명령어 텍스트 추출 (v23: sibling 탐색 포함)
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 있을 때만
      4. v23 sibling: Observer가 footer 형제 요소에서 pre.font-mono 탐색 → ✅ 성공
    → 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 해결 방안

  1. DOM 덤프에서 사용자 메시지 클래스 식별 → Observer 셀렉터 추가
  2. Cascade 완료 후 Step Probe HB-CAPTURE에서 USER_INPUT step 캡처 (지연 릴레이)

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 토큰 .envDISCORD_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 캐시)
v0.5.74 사용자 메시지 셀렉터 추가 (.select-text.rounded-lg) 사용자 메시지 릴레이 작동
v0.5.76 DOM 탐색 depth 5→10, pre.font-mono 우선 탐색 Observer HTML 업데이트 필요
v0.5.77 WS response 파일 작성 (pollResponseGroup용) Retry 클릭 경로 추가
v0.5.78 _from_ws 마커로 processResponseFile 삭제 방지 Retry auto-approve 작동
v0.5.79 sibling 탐색 추가 + thinking 블록 필터링 명령어 컨텍스트 부분 추출

8. 남은 작업 (TODO)

  • AG 재시작하여 Observer 반영 확인 — v0.5.72 작동 확인
  • Observer의 AI 응답 릴레이가 작동하는지 Discord에서 확인 — 작동
  • 사용자 메시지 셀렉터 추가 — v0.5.74
  • Retry auto-approve 흐름 복구 — v0.5.78 (_from_ws 마커)
  • 명령어 컨텍스트 sibling 탐색 — v0.5.79
  • Thinking 블록 필터링 — v0.5.79
  • 명령어 컨텍스트 추출 타이밍 이슈 (DOM 렌더링 전 scan 시 추출 실패) #636
  • Observer pollResponseGroup 미시작 케이스 (trigger-click 선점)
  • AI 응답이 마지막 블록만 캡처되는 문제 개선 (전문 캡처)