9.7 KiB
9.7 KiB
Observer Script 개발 가이드 — SSOT
이 문서는 Observer 코드 변경 전 반드시 확인하는 SSOT입니다. 모든 Observer 관련 설계, 배포, 제약사항이 이 문서에 있습니다.
1. Observer 코드 특성
1.1 실행 환경
- Observer는 workbench-jetski-agent.html에 인라인
<script>로 삽입됨 - AG Native의 Electron 렌더러 프로세스에서 실행 (VS Code extension host가 아님)
- 렌더러는 strict mode 아님 (확인 필요), 하지만 V8 parser는 일부 strict-like 규칙 적용
generateApprovalObserverScript(port)함수가 TypeScript template literal로 스크립트 생성
1.2 코드 작성 규칙 (위반 시 Observer 전체 크래시)
| 규칙 | 이유 | 예시 |
|---|---|---|
| for 루프 안에 function 선언 금지 | V8 strict mode error | var fn = function(){} 사용 |
| 문자열 리터럴에 특수문자 금지 | template literal 이스케이핑 깨짐 | '??' → 'MAX' |
regex에 \\s 등 이스케이프 금지 |
template literal이 \\\\s → \\s (리터럴) |
문자열 비교 사용 |
| ES6+ 구문 금지 | 구 V8 호환 | var 사용, let/const/arrow 금지 |
| 배포 전 SYNTAX CHECK 필수 | Observer 크래시 방지 | 아래 검증 명령어 참조 |
1.3 필수 검증 명령어 (모든 빌드 전 실행)
npm.cmd run compile; node -e "const {generateApprovalObserverScript}=require('./out/observer-script'); let s=generateApprovalObserverScript(18080); try { new Function(s); console.log('SYNTAX OK'); } catch(e) { console.log('ERROR:', e.message); }"
SYNTAX OK가 나오지 않으면 절대 배포하지 않는다.
1.4 배포 전 자기검증 체크리스트 (MANDATORY)
재시작을 요구하기 전 반드시 다음을 모두 통과해야 한다:
- SYNTAX CHECK 통과:
new Function(s)→SYNTAX OK - 수정 방향 검증: 이 수정이 문제를 해결하는 올바른 접근인지 스스로 2번 재검증
- template literal 규칙 위반 없음: regex 이스케이프, 특수문자, function 선언 등
- 변경 범위 최소화: 불필요한 코드 포함 여부 확인
- 재시작 사유 명시: 사용자에게 (a) 무엇을 수정했고 (b) 왜 재시작이 필요한지 1~2줄로 설명
- 재시작 횟수 명시: Observer 변경 = 2회, Extension host만 변경 = 1회
- log() relay 필터 확인: 새 로그 키워드 추가 시 log() 함수의 키워드 필터에도 추가했는지 확인 (섹션 3.5 참조)
- regex E2E 테스트: Observer에서 사용하는 새 regex는 생성된 코드에서 직접 실행하여 매칭 검증
- 구현 전 가정 검증: 새 접근을 코딩하기 전에, 핵심 가정이 성립하는지 로그 1줄로 먼저 확인 (예: "Step Probe가 WAITING을 볼 수 있는가?" →
STEP-PROBE.*WAITING로그 검색)
정당한 사유 없이 재시작을 요구하지 않는다. DOM 구조를 먼저 파악하고 설계한 후 코드를 작성한다. 시행착오식(trial-and-error) 접근을 하지 않는다. 추측으로 코딩하지 않는다. 로그/데이터로 확인한 사실에 기반하여 코딩한다.
2. 배포 프로세스
2.1 Observer 코드가 포함된 변경
Observer 코드 변경은 extension host 코드 변경보다 비용이 높다:
VSIX 빌드 → VSIX 설치 → AG 재시작 #1 (extension이 HTML 패치)
→ AG 재시작 #2 (패치된 HTML 로드) → Observer 실행
총 2번 AG 재시작 필요
2.2 Extension host 코드만 변경 (approval-handler, http-bridge 등)
VSIX 빌드 → VSIX 설치 → AG 재시작 #1 → 즉시 적용
1번 AG 재시작 필요
2.3 VSIX 설치 확인
Get-ChildItem "$env:USERPROFILE\.vscode\extensions" -Filter "*gravity*" -Directory |
ForEach-Object { $j = Get-Content (Join-Path $_.FullName "package.json") | ConvertFrom-Json; "$($_.Name): v$($j.version)" }
2.4 HTML 패치 확인 (Observer 코드가 반영되었는지)
Select-String -Path "$env:LOCALAPPDATA\Programs\Antigravity\resources\app\out\vs\code\electron-browser\workbench\workbench-jetski-agent.html" -Pattern "검색할_함수명" -Quiet
3. AG Native DOM 구조
3.1 Chat Panel (Observer가 접근 가능)
- 위치:
document.querySelector('#conversation')또는document.querySelector('[class*="conversation"]') - AI 응답 블록:
.leading-relaxed.select-text - 사용자 메시지 블록:
.select-text.rounded-lg(v0.5.74+) - Thinking 블록: 조상에
max-h-[200px]클래스 있음 → 필터링
3.2 승인 버튼 — "Always run" (v0.5.93 BTN-DOM-DUMP 확인)
실제 DOM 구조 (v0.5.92 로그로 확인):
- d0: button.flex.cursor-pointer (Always run 버튼)
- d1: div.min-w-0
- d2: div.flex.items-center.justify-between.rounded-b.border-t (버튼 바)
- d3: div (이름 없는 컨테이너)
- div.mb-1 = "Running command" (헤더)
- div.flex = "❯ gravity_control > ..." (실제 명령어, plain div!)
- div.flex = "Always run Cancel" (버튼들)
명령어는 pre.font-mono나 code가 아닌 plain div.flex에 있음. v30: "Running command" div의 형제를 탐색하여 프롬프트 마커 뒤의 명령어 추출.
- "Retry" 버튼: button 태그, chat panel 내
3.3 Diff Review (Accept all / Reject all) — Observer 접근 불가
- 에디터 webview에 렌더링, Observer document에서 접근 불가
- 해결: Extension host에서 antigravity.acceptAgentStep 명령 실행
3.4 DOM 렌더링 타이밍
- "Always run" 버튼이 DOM에 나타날 때 명령어 div도 함께 렌더링됨
- v30의 "Running command" div 탐색은 즉시 성공
3.5 log() relay 필터 규칙
Observer의 log() 함수는 키워드 필터로 일부 로그만 extension.log에 relay. 새 로그 키워드 추가 시 반드시 필터도 함께 수정해야 함.
현재 필터 키워드 (v0.5.92+): CV-CLASSES, CV-CHILDREN, child[, CV found, Conversation view, BEACON, ERROR, chat relay, user-cls, CONTEXT, BTN-DOM, DEFERRED, DETECTED
4. 파일 경로 매핑
| 항목 | 경로 |
|---|---|
| AG 설치 경로 | $env:LOCALAPPDATA\Programs\Antigravity\ |
| workbench HTML | ...\resources\app\out\vs\code\electron-browser\workbench\workbench-jetski-agent.html |
| Extension 로그 | $env:USERPROFILE\.gemini\antigravity\bridge\extension.log |
| Pending 파일 | $env:USERPROFILE\.gemini\antigravity\bridge\pending\*.json |
| Response 파일 | $env:USERPROFILE\.gemini\antigravity\bridge\response\*.json |
| VSIX extensions | $env:USERPROFILE\.vscode\extensions\variet.gravity-bridge-*\ |
| HTTP Bridge 포트 | 34332 (또는 getDeterministicPort('gravity_control')) |
| Discord 채널 | #ag-gravity_control (ID: 1483082084540223663) |
5. 과거 실수 및 교훈
5.1 VSIX 미설치 (v0.5.78~83)
- 증상: 빌드만 하고
code --install-extension실행 안 함 - 결과: 설치된 버전이 v0.5.50, 모든 수정사항 미적용
- 교훈: 빌드 후 반드시
code --install-extension *.vsix --force실행 - 확인:
Get-ChildItem "$env:USERPROFILE\.vscode\extensions" -Filter "*gravity*"
5.2 function 선언 → Observer 크래시 (v0.5.84~86)
- 증상:
function _isGenericDesc(d){}를 for 루프 내부에 선언 - 결과: Observer 전체 크래시, chat relay + auto-approve 중단
- 교훈:
var fn = function(){}사용, 배포 전 SYNTAX CHECK 필수
5.3 깨진 문자열 리터럴 (v0.5.86)
- 증상:
{tag:'??',...}(특수문자가 따옴표 깨뜨림) - 결과: SYNTAX ERROR, Observer 미작동
- 교훈: template literal 안에서 특수문자/이모지 사용 주의
5.4 regex 이스케이핑 실패 (v0.5.83~84)
- 증상:
/Always\\s+run/→ 생성 시\\s(리터럴 백슬래시+s)로 출력 - 결과: "Always run" 매칭 실패
- 교훈: template literal 안에서 regex 대신 문자열 비교 사용
5.5 _from_ws 파일 무한 누적 (v0.5.78~84)
- 증상: response 파일에
_from_ws: true마커 → processResponseFile이 스킵 → 영원히 삭제 안 됨 - 결과: 3초마다 4개 파일 × SKIP 로그 → 로그 스팸, 다른 처리 방해
- 교훈: 보존 파일에는 반드시 TTL(자동 만료) 추가
6. 디버깅 체크리스트
Observer가 작동하지 않을 때
extension.log에서setup complete확인 → Observer 로드 여부OBSERVER-LOG패턴 검색 → 스캔 활동 여부HTTP-REQ검색 → HTTP bridge에 요청 도달 여부- SYNTAX CHECK 실행 → 생성 스크립트 문법 검증
SKIP _from_ws반복 확인 → stale response 파일 정리
Discord에 메시지가 안 올 때
POST /chat검색 → chat relay 전송 여부WS.*send검색 → WebSocket 전송 여부- Discord API로 직접 확인:
node extension/scratch/discord_read.js - stale response 파일 확인:
Get-ChildItem $env:USERPROFILE\.gemini\antigravity\bridge\response\*.json
7. 버전 히스토리 요약
| 버전 | 핵심 변경 | 결과 |
|---|---|---|
| v0.5.50 | 기본 릴레이 시스템 | ✅ 안정 |
| v0.5.78 | _from_ws 마커 (Retry 보존) |
✅ 작동 (TTL 미구현) |
| v0.5.79 | sibling 탐색 + thinking 필터 | ✅ 작동 |
| v0.5.80~81 | Accept all offsetParent 완화 | ❌ 구조적 불가 (에디터 webview) |
| v0.5.82 | 버튼 셀렉터 확장 + ACCEPT-SCAN | 진단용 |
| v0.5.83 | DEFERRED 컨텍스트 500ms | regex 이스케이핑 실패 |
| v0.5.84 | regex → 문자열 비교 | function 선언 크래시 |
| v0.5.85 | _from_ws TTL 60초 |
✅ stale 정리 |
| v0.5.86 | function → var expression | 깨진 문자열 미발견 |
| v0.5.87 | 깨진 문자열 2건 수정 | ✅ SYNTAX OK |