| name | antigravity-autoaccept |
| version | 2.0.0 |
| author | LazyGravity / WJ |
| license | MIT |
| tags | ["cdp","ipc","antigravity","autoaccept","electron","vscode-extension","lazygravity","go","wails"] |
| description | This skill documents how to integrate a Go/Wails application (LazyGravity) with
the AntiGravity AutoAccept VS Code extension via an IPC HTTP bridge, eliminating
CDP WebSocket competition for the workbench.html target.
Trigger this skill when:
- Setting up LazyGravity bot CDP integration with Antigravity IDE
- Diagnosing "CDP WebSocket conflict" or "connection kicked" errors
- Implementing IPC delegation between a Go process and the AutoAccept plugin
- Verifying port usage on :9222, :9333, :27182
- Adding /inject, /eval, /ping endpoints to a VS Code extension
- Adapting a Go CDP client to use IPC instead of direct WebSocket
- Debugging ipcEval timeout during long AI generation (see Gotcha #1)
- IDE launch race conditions on startup
- Concurrent message processing with mutex vs IPC path
|
| dependencies | {"go_packages":["net/http","encoding/json","sync","sync/atomic"],"node_packages":["http (builtin)","worker_threads (builtin)"],"ide":["Antigravity IDE with --remote-debugging-port=9222 flag","AntiGravity AutoAccept extension v3.13.8+"]} |
| changelog | [{"version":"2.0.0","date":"2026-04-15","changes":["æ°å¢ãå·²ç¥é·é±ãç« èïŒå#1~#8ïŒ","å#1: ipcEval åºçš evalHTTP(35s) èé ipcHTTP(3s)","å#2: InjectMessageWithImages äžçå鿣æ¥å±è¯Žæ","å#3: IDE å¯åšç«æçŒè§£çç¥","å#7: å¹¶å worker + cdpMu 讟计å³ç","æ°å¢ãæåç»éªãç« èïŒL1~L5ïŒ","è¡¥å
Troubleshooting è¡šæ ŒïŒeval è¶
æ¶ãçååºè¿æ»€çïŒ","ä¿®æ£ go test è·¯åŸè¯Žæ","æŽæ°ç®åœç»æè¯Žæ"]},{"version":"1.0.0","date":"2026-04-07","changes":["åçååžïŒIPC å§ææ¡¥æ¥å®æŽè®Ÿè®¡"]}] |
antigravity-autoaccept IPC Integration Skill
ð Architecture Overview
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â USER / TELEGRAM â
ââââââââââââââââââââââââââââ¬âââââââââââââââââââââââââââââââ
â message
âŒ
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â LazyGravity (Go / Wails App) â
â â
â IsAutoAcceptAvailable() â
â GET http://127.0.0.1:27182/ping â
â {"ok":true, "workbenchReady":true} â
â â YES â NO (IPC offline) â
â ⌠⌠â
â POST /inject InitCDP() â Discover() â
â POST /eval Direct WebSocket (fallback) â
ââââââââââ¬ââââââââââââââââââââââââ¬âââââââââââââââââââââââââ
â IPC (HTTP loopback) â CDP WebSocket (fallback)
⌠âŒ
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â AntiGravity AutoAccept Extension (Node.js) â
â â
â IPC Server :27182 â
â GET /ping â {ok, sessions, workbenchReady} â
â POST /inject â injectText(text) via CDP â
â POST /eval â evalInWorkbench(expr) via CDP â
â â
â ConnectionManager â Worker Thread â WebSocket â
â Port :9333 (primary) â :9222 (fallback) â
ââââââââââââââââââââââââââââââââââ¬ââââââââââââââââââââââââ
â CDP WebSocket (single owner)
âŒ
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â Antigravity IDE (Electron / Chromium) â
â workbench.html @ :9333 or :9222 â
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Design Principle: AutoAccept holds the only persistent CDP WebSocket to
workbench.html. LazyGravity never opens a competing connection when IPC is
available. Two clients cannot share a CDP WebSocket to the same target without
kicking each other off.
ð IPC Protocol Specification
Full spec â references/ipc-protocol.md
Quick Reference
| Method | Path | Request Body | Response |
|---|
GET | /ping | â | {"ok":bool,"sessions":int,"workbenchReady":bool} |
POST | /inject | {"text":"<message>"} | {"ok":bool,"error":"..."} |
POST | /eval | {"expression":"<js>"} | {"ok":bool,"value":any,"error":"..."} |
- Base URL:
http://127.0.0.1:27182
- Auth: None (loopback-only,
Access-Control-Allow-Origin: 127.0.0.1)
- Timeout recommended: 3 s for
/ping, 30 s for /eval
ð ïž Implementation Guide
Step 1 â Add IPC Server to AutoAccept Extension
File: src/extension.js
Add inside activate() at the very end, after all handlers are wired:
startIPCServer();
Add stopIPCServer() inside deactivate().
Implement the server â see examples/extension-ipc-server.js.
Constraints:
- MUST bind to
'127.0.0.1' only (not '0.0.0.0')
- MUST handle
EADDRINUSE silently (second IDE window may also try to bind)
- Port MUST be
27182 (LazyGravity hardcodes this)
/ping MUST report workbenchReady from connectionManager._getWorkbenchSession()
/eval delegates to connectionManager.evalInWorkbench(expression)
/inject delegates to connectionManager.injectText(text)
Step 2 â Add _getWorkbenchSession() and evalInWorkbench() to ConnectionManager
File: src/cdp/ConnectionManager.js
_getWorkbenchSession() {
for (const [, info] of this.sessions) {
if (info.url && (
info.url.includes('workbench') ||
info.url.startsWith('vscode-file://')
)) {
return info;
}
}
return null;
}
async evalInWorkbench(expression) {
const session = this._getWorkbenchSession();
if (!session) throw new Error('No workbench CDP session');
const result = await this._workerEval(session.wsUrl, expression);
return (result?.result?.result?.value) !== undefined
? result.result.result.value
: null;
}
async injectText(text) {
const session = this._getWorkbenchSession();
if (!session) throw new Error('No workbench CDP session â AutoAccept not connected');
const escapedText = JSON.stringify(text);
const script = `(function() {
const editors = Array.from(document.querySelectorAll(
'div[role="textbox"]:not(.xterm-helper-textarea)'));
const visible = editors.filter(el => el.offsetParent !== null);
const editor = visible[visible.length - 1];
if (!editor) return { ok: false, error: 'No editor found' };
editor.focus();
document.execCommand('selectAll', false, null);
document.execCommand('delete', false, null);
document.execCommand('insertText', false, ${escapedText});
['keydown','keypress','keyup'].forEach(type => {
editor.dispatchEvent(new KeyboardEvent(type, {
key: 'Enter', code: 'Enter', keyCode: 13,
bubbles: true, cancelable: true
}));
});
return { ok: true };
})()`;
const result = await this._workerEval(session.wsUrl, script);
const val = result?.result?.result?.value;
if (!val?.ok) throw new Error(val?.error || 'Text injection failed');
return val;
}
Step 3 â Add IPC Client to Go Project
File: internal/platform/cdp/antigravity.go
See full implementation â examples/go-ipc-client.go
const ipcBase = "http://127.0.0.1:27182"
var ipcHTTP = &http.Client{Timeout: 3 * time.Second}
func IsAutoAcceptAvailable() bool {
resp, err := ipcHTTP.Get(ipcBase + "/ping")
if err != nil { return false }
defer resp.Body.Close()
if resp.StatusCode != 200 { return false }
var result struct {
OK bool `json:"ok"`
WorkbenchReady bool `json:"workbenchReady"`
}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return false
}
return result.OK && result.WorkbenchReady
}
Step 4 â Wire IPC Fast-Path in Message Handler
File: app.go â inside processSingleMessage():
if len(attachments) == 0 && cdp.IsAutoAcceptAvailable() {
if err := cdp.InjectViaAutoAccept(msg.Content()); err != nil {
return
}
resp, err := cdp.MonitorResponseViaIPC(ctx, 15*time.Minute)
return
}
Negative constraints â do NOT:
- Do NOT call
IsAutoAcceptAvailable() inside a hot loop (it makes an HTTP call each time)
- Do NOT use IPC path for messages with image attachments (IPC does not support file upload)
- Do NOT open a competing CDP WebSocket to
workbench.html when IPC is active
â
Verification Checklist
Execute these in order before declaring the integration working:
1. Check listening ports
netstat -ano | findstr "9222 9333 27182" | findstr LISTEN
Expected:
TCP 127.0.0.1:9222 LISTENING <antigravity-pid>
TCP 127.0.0.1:27182 LISTENING <node-extension-pid>
2. Ping IPC server
(Invoke-WebRequest 'http://127.0.0.1:27182/ping').Content
Expected:
{"ok":true,"sessions":3,"workbenchReady":true}
sessions should be ⥠1
workbenchReady MUST be true for IPC path to activate
3. Test /inject manually
Invoke-WebRequest 'http://127.0.0.1:27182/inject' `
-Method POST -ContentType 'application/json' `
-Body '{"text":"hello from IPC test"}'
Expected: {"ok":true}
4. Test /eval manually
Invoke-WebRequest 'http://127.0.0.1:27182/eval' `
-Method POST -ContentType 'application/json' `
-Body '{"expression":"document.title"}'
Expected: {"ok":true,"value":"<page title>"}
5. Verify Go build
cd d:\AI\work\GO
go build ./...
go test ./internal/platform/cdp/...
ð¥ Troubleshooting
| Symptom | Cause | Fix |
|---|
/ping returns workbenchReady: false | AutoAccept not yet connected to workbench | Wait 5â10s, toggle AutoAccept OFF/ON |
/ping connection refused | IPC server not started | Reload AutoAccept extension in IDE |
| Go falls back to direct CDP every time | IsAutoAcceptAvailable() returns false | Check steps 1â2 above |
| Two IDE instances, port already in use | Second IDE tries to bind :27182 | Expected â EADDRINUSE silently ignored, first instance wins |
/inject succeeds but chat empty | injectText regex misses editor | Check div[role="textbox"] selector matches current IDE version |
| CDP WebSocket conflict (Go + AutoAccept both connecting) | IPC check skipped | Ensure IsAutoAcceptAvailable() is called BEFORE InitCDP() |
9333 port not listening, only 9222 | IDE launched with --remote-debugging-port=9222 flag | AutoAccept falls back to 9222 automatically â this is fine |
/eval 3s timeout during AI generation | ipcHTTP(3s) used for eval calls | å#1 â 䜿çšç¬ç«ç evalHTTP(35s) client |
| Monitor returns empty string | Activity-log filter over-eager on short responses | æ£æ¥ looksLikeActivityLog ç 250 char äžéïŒåè§å#6 |
| Message queue full warning | Burst of Telegram messages, 100-cap buffer | å¢å msgQueue çŒå²åºæå èåä¿¡å· |
â ïž å·²ç¥é·é± (Gotchas)
å#1 â ipcEval å¿
é¡»çš evalHTTP(35s) èé ipcHTTP(3s)
ç°è±¡ïŒ é¿èæ¶ AI çææ¶ïŒè¶
3s ç忬¡ /evalïŒïŒGo æ¥ IPC eval repeatedly failedã
æ ¹æ¬åå ïŒ ç产代ç antigravity.go äž ipcEval() åŠæå€çšäº ipcHTTPïŒ3s timeoutïŒïŒåš AI çææéŽ eval è°çšäŒè¶
æ¶ãç€ºäŸæä»¶ go-ipc-client.go å·²æ£ç¡®å®ä¹ç¬ç«ç evalHTTPïŒ35sïŒã
æ£ç¡®åæ³ïŒ
var ipcHTTP = &http.Client{Timeout: 3 * time.Second}
var evalHTTP = &http.Client{Timeout: 35 * time.Second}
func ipcEval(expression string) (interface{}, error) {
body, _ := json.Marshal(map[string]string{"expression": expression})
resp, err := evalHTTP.Post(ipcBase+"/eval", "application/json", bytes.NewReader(body))
}
æ£éªïŒ Select-String "evalHTTP" internal\platform\cdp\antigravity.go åºæç»æã
å#2 â InjectMessageWithImages å
æç¬¬äºå± IPC æ£æ¥ïŒå鿣æ¥ïŒ
ç°è±¡ïŒ é
读 antigravity.go æ¶åç° InjectMessageWithImages() å
éšä¹æ IPC å¿«éè·¯åŸïŒç䌌å app.go çæ£æ¥éå€ã
å®é
æ
åµïŒ app.go layer 1 åœäžæ¶çŽæ¥è°çš cdp.InjectViaAutoAccept()ïŒäžèµ° InjectMessageWithImages()ïŒæä»¥äž€å±äžäŒéå€ãLayer 2 ä»
åš CDP fallback è·¯åŸå
å¶ååœäžïŒä¿é©çšïŒã
ç»è®ºïŒ åœå讟计å®å
šïŒäœååšåäœãåç»éæå»ºè®®ç§»é€ layer 2ïŒä¿æè·¯åŸæž
æ°ã
å#3 â IDE å¯åšç«æïŒLazyGravity å
就绪ïŒIDE æªå°±ç»ª
ç°è±¡ïŒ App å¯åšåç«å³æ¶å° Telegram æ¶æ¯ïŒCDP Discover() æ /ping 倱莥ã
æ ¹æ¬åå ïŒ startup() çš cmd.Start() åŒæ¥å¯åš IDEïŒCDP 端å£å AutoAccept æä»¶éèŠé¢å€ 5~15 ç§åå§åã
å·²æçŒè§£ïŒ å¯åšå 2s åå° goroutine è°çš bringToFront()ïŒéŠæ¡æ¶æ¯å°æ¥æ¶ååå¯çšæ§æ£æ¥ïŒIsAutoAcceptAvailable() è¶
æ¶èªåš fallbackïŒã
æäœ³å®è·µïŒ äžèŠå讟 startup() è¿åå IPC/CDP ç«å³å¯çšãå©çšç°æ fallback æºå¶èªæå³å¯ã
å#4 â examples/go-ipc-client.go æ //go:build ignoreïŒè®Ÿè®¡åŠæ€ïŒ
ç°è±¡ïŒ go build ./... å go test ./... äžå€ç examples/ äžçæä»¶ã
æ ¹æ¬åå ïŒ ç€ºäŸæä»¶å€Žéšæ //go:build ignoreïŒæ
ææé€åšå€ã
ç»è®ºïŒ è¿æ¯æ£ç¡®è¡äžºââç€ºäŸæ¯åè代ç ïŒäžæ¯çŒè¯ç®æ ã
å#5 â AutoAccept æä»¶å级å IPC æ¹é 䞢倱
ç°è±¡ïŒ IDE èªåšæŽæ°/éè£
AutoAccept æ©å±åïŒ/ping connection refusedã
æ ¹æ¬åå ïŒ IPC server ä»£ç æ¯æåšæ³šå
¥çïŒäžåšå®æ¹æä»¶äžïŒå级äŒèŠçã
è§£å³æ¹æ¡ïŒ æ¹é ååº git commit 已修æ¹çæä»¶æä»¶è·¯åŸïŒå级åéæ°æ³šå
¥ãé¿æè§£æ³æ¯åäžæžžæ PRã
å#6 â looksLikeActivityLog å¯èœè¯¯è¿æ»€çååº
ç°è±¡ïŒ AI åå€åŸçïŒ< 250 å笊ïŒäžä»¥åšè¯åŒå€ŽïŒè¢«è¯¯å€äžºå·¥å
·è°çšæ¥å¿ïŒè¿å空å笊䞲ã
æ ¹æ¬åå ïŒ æ£å norm.length <= 250 çéåŒè¿äºå®œæŸã
åœåç¶æïŒ å·²ç¥ limitationïŒå®é
圱åæå°ãåºç°æ¶å¯å° 250 è°äœå° 100ã
å#7 â 3 䞪 Worker å¹¶å + cdpMuïŒIPC è·¯åŸäžå mutex 纊æ
讟计å³çïŒ cdpMu åªä¿æ€çŽè¿ CDP è·¯åŸïŒCDP WebSocket äžæ¯æå¹¶åïŒãIPC è·¯åŸïŒHTTP loopbackïŒå€©ç¶å¹¶åå®å
šïŒäžéèŠä¹äžåºè¯¥æŸåš cdpMu ä¿æ€äžã
äžèŠè¿æ ·åïŒ äžèŠå° cdp.IsAutoAcceptAvailable() æ cdp.InjectViaAutoAccept() æŸè¿ cdpMu.Lock() èåŽå
ã
å#8 â stopGoneCount >= 3 çäžæ¬¡ç¡®è®€éåŒäžå¯éäœ
ç°è±¡ïŒ å°éåŒæ¹äžº 1 äŒå¯ŒèŽå¶å"èå宿"ïŒAI æèäžçå顿被误å€äžºçæå®æ¯ã
æ ¹æ¬åå ïŒ Antigravity ç Stop æé®åš DOM å·æ°æ¶å¯èœçææ¶å€±ååºç°ã
ç»è®ºïŒ ä¿æ 3 次éåŒïŒèœ®è¯¢éŽé 2s â è³å° 6s ç¡®è®€å®æïŒã
âš æåç»éª (Lessons Learned)
L1 â IPC å¿«éè·¯åŸçåå±è®Ÿè®¡ïŒapp.go + åºå± fallbackïŒ
app.go ç processSingleMessage() æ¯äž»å¹²å³çç¹ïŒ
- IPC å¿«éè·¯åŸïŒlayer 1ïŒïŒææ¬æ¶æ¯ + AutoAccept å¯çš â HTTP å§æïŒäžå¯åš CDP stack
- çŽè¿ CDP fallbackïŒlayer 2ïŒïŒåŸçæ¶æ¯ OR AutoAccept äžå¯çš â åæ WebSocket è·¯åŸ
è¿ç§è®Ÿè®¡é犻æž
æ°ïŒfallback è·¯åŸå®æŽïŒæ éä¿®æ¹åºå± CDP é»èŸã
L2 â execCommand åš Electron å
äŒäº Input.insertText
åš Electron Chromium å
ïŒInput.insertText 泚å
¥ææ¬åæ Enter äžè§Šå React onChangeãdocument.execCommand('insertText') + åæ KeyboardEvent èœæ£ç¡®è§ŠåãIPC è·¯åŸéè¿ AutoAccept åš workbench äžäžæå
éšæ§è¡ JSïŒå€©ç¶ç»è¿è¿äžªé®é¢ã
L3 â è§£å³ CDP ç¬å çæ£ç¡®æè·¯ïŒ"æ¶èŽä»£çæ"èé"å
񄧮"
Chromium ç CDP WebSocket æ¯ç¬å æºå¶ïŒæ æ³å
±äº«ãå¯äžæ£ç¡®è§£æ³æ¯è®© AutoAccept ç¬å ïŒGo éå䞺纯 HTTP 客æ·ç«¯ãä»»äœè¯åŸ"蜮æµäœ¿çš"æ"åè°è¿æ¥"çæ¹æ¡éœäŒå€±èŽ¥ã
L4 â atomic.CompareAndSwapInt32 鲿¢éå€å¯åšäŒäº mutex
StartBot() çš atomic CAS é²å¹¶åå¯åšïŒå€±èŽ¥æ¶ç«å³è¿åé误ïŒfast failïŒãmutex æ¹æ¡äŒé»å¡çåŸ
ïŒå¯èœé æ Wails åç«¯åæ»ã
L5 â sendReplyChunked çš 3800 rune åç䞺 Telegram 4096 åèéå¶é¢çå®å
šäœé
Telegram äžé 4096 åèïŒUTF-8ïŒïŒäžæ 3 åè/åã3800 rune çæ··åææ¬ç»æµè¯äžè¶
éïŒæ¯å®å
šçä¿å®åŒã
ð Port Reference
| Port | Owner | Purpose |
|---|
| 9222 | Antigravity IDE (Electron) | CDP debuggingïŒå¯åšåæ°æå®ïŒåœåå¯äžçå¬ïŒ |
| 9333 | Antigravity IDE (Electron) | CDP debuggingïŒAutoAccept éŠéïŒèªåš fallback å° 9222ïŒ |
| 27182 | AutoAccept Extension (Node.js) | IPC HTTP server for LazyGravity delegation |
Rule: LazyGravity Go app opens zero ports. It is purely a client.
诎æïŒ startup() 以 --remote-debugging-port=9222 å¯åš IDEïŒå æ€ 9333 äžäŒçå¬ãAutoAccept å
éšå
å°è¯ 9333 倱莥åèªåš fallback å° 9222 ââ è¿æ¯é¢æè¡äžºïŒäžåœ±ååèœã
ð Skill Directory Structure
Skills/antigravity-autoaccept/
âââ SKILL.md â æ¬æä»¶ïŒAI Agent äž»å
¥å£ïŒfrontmatter çšäºèªåšåç°ïŒ
âââ README.md â 人类å¯è¯»è¯ŽæïŒäžæïŒå«æ¹é èæ¯å Step by StepïŒ
âââ plugin.json â Skill å
æ°æ®ïŒnameãversionãIPC 端å£çïŒ
âââ references/
â âââ ipc-protocol.md â IPC API 宿Žè§èïŒç«¯ç¹/åæ®µ/è¶
æ¶/å®å
šïŒ
âââ examples/
âââ extension-ipc-server.js â AutoAccept ç«¯å®æŽå®ç°ïŒå¯çŽæ¥å€å¶ïŒ
âââ go-ipc-client.go â Go ç«¯å®æŽå®ç°ïŒå«æ£ç¡®ç evalHTTP clientïŒ
â ïž éèŠïŒ examples/go-ipc-client.go äžäœ¿çšäºæ£ç¡®çå HTTP client 讟计ïŒipcHTTP + evalHTTPïŒã
å°ä»£ç å€å¶å°ç产æä»¶æ¶ïŒå¡å¿
åæ¶å€å¶ evalHTTP åéïŒé¿å
å#1ã
çæ¬ïŒv2.0.0 | æåæŽæ°ïŒ2026-04-15 | 绎æ€è
ïŒWJ