@estebanforge/pi-antigravity-bridge 1.3.3 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,63 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [1.4.1] - 2026-09-04
6
+
7
+ ### Added
8
+
9
+ - Self-service ACP setup (`src/acp/setup.ts`): `/agy engine acp` now prepares the whole engine instead of printing instructions. It installs the official server binary from the antigravity-acp registry entry (`agentclientprotocol/registry`) into the pinned layout `~/.local/opt/agy-acp/<build>/` with a `current` symlink and the zip sha256 recorded (no upstream checksums exist; plan §12), points `acp.bin` at it, and prepares the login: `oauth-personal` by default, which is the user's own Antigravity subscription (the same Google account and plan as the `agy` CLI; the server opens the browser on the first ACP message, tokens persist). Credential values are never read or written (`acp_token.json` is only stat()ed); `gemini-api-key` stays a manual headless option, never the default. A `session_start` self-heal repeats the check silently when everything is ready and surfaces the manual steps only on failure; `AcpDriverOptions.bin` accepts a resolver so a mid-session install is picked up by the next turn without a restart; `/agy doctor` shows binary source and auth type. Tests inject the registry, archive, and unpacker, so the suite stays offline.
10
+
11
+ ### Fixed
12
+
13
+ - Stream-json frames split across pipe chunks are now reassembled instead of dropped: `AgyDriver` buffers the trailing partial stdout line (the scheme `JsonRpcSession.feed` already used on the ACP engine). Previously a large `tool` frame or the `result` frame split by a pipe boundary was lost whole, which could turn a successful turn into a bogus "agy exited with status 0" error. Regression test drives a fake agy whose reply is deliberately split mid-line.
14
+ - Both drivers attach an `'error'` listener on the child's stdin: an async pipe failure (EPIPE when agy/the ACP server dies mid-write) now fails the turn (ACP: tears the connection down) instead of escaping as an uncaught exception that kills the whole pi process.
15
+ - ACP permission answering is fail-closed: `session/request_permission` selects the first reject option unless the turn runs with `skipPermissions`. Previously every request was auto-approved regardless of the `permissions` setting shown by `/agy status`. The unsupported `engine=acp` + `mode=plan` combination is now refused at `/agy engine`, `/agy mode`, and the settings picker, and fails the turn with a visible error instead of silently running non-plan (ACP has no review-only mode in RC01).
16
+ - Startup-log fix hardening: four genuine ACP failure events (`session-load-failed-creating-fresh`, `connection-exited`, `cancel-failed`, `unsupported-server-request`) surface again; the dead MCP entries (`capability-missing`, `self-patch-error`) are gone; `call-tool-fail` no longer toasts for the routine fail-all on turn end / session shutdown.
17
+ - Startup log leaks: the ACP driver log sink now forwards only genuine failures (`start-failed`, `spawn-error`, `parse-error`, `write-failed`, `mode-apply-failed`, `timeout`, `stall`, `auth-required`) to stderr; routine lifecycle (`driver-created`, spawn, session new/load) stays in the `#lifecycle` ring buffer under `/agy doctor`. The MCP bridge logger no longer toasts (or headless-stderr-logs) normal startup/teardown events (`listening`, `bridge-config-written`, `bridge-config-removed`, `closed`); only failures surface, as warning toasts. The stream-json engine already had no terminal sink.
18
+
19
+ ## [1.4.0] - 2026-09-04
20
+
21
+ ### Added
22
+
23
+ - The official-server ACP engine as a second turn engine behind `config.engine` (env `AGY_ENGINE`, `/agy engine acp|stream-json`), default off: the tested stream-json engine stays default until upstream ships usage fields. New modules: `src/acp/jsonrpc.ts` (NDJSON JSON-RPC session with line buffering - stdio chunks are not newline-aligned), `src/acp/connection.ts` (initialize, session/new and load, config options, in-connection auto permissions, cancel probing), `src/acp/events.ts` (update mapping), `src/acp/driver.ts` (AcpDriver over the shared `TurnDriver` contract in `src/driver-types.ts`). Sessions are engine-scoped (`sid:<id>@acp`) so switching engines never crosses conversations.
24
+ - `/agy engine acp|stream-json` command and `/agy acp-auth` (one-time credential setup for the ACP server, which keeps its own auth state). `/agy doctor` is engine-aware.
25
+ - `scripts/smoke-acp.mjs` (live ACP smoke), `scripts/smoke-acp-bridge.mjs` (live Gate F bridge e2e), `scripts/parity-live.mjs` (live parity run: 7 scenarios through BOTH engines). All quota-gated via `AGY_ACP_LIVE=1`.
26
+ - `docs/ACP-ADOPTION-PLAN.md` (adoption plan, gates, progress tracking) and `docs/ACP-PROTOCOL-REFERENCE.md` (captured wire shapes of the ACP server).
27
+ - Image prompt support on the ACP engine: pi image attachments ride as typed content blocks (`DriverTurnRequest.images`, forwarded by `connection.prompt` ahead of the text block). Models advertise `input: ["text","image"]` only when the engine is `acp` (read at extension load; engine switches require a restart), so the text-only legacy CLI never offers an attach button it cannot honor. Verified live: a 64x64 two-tone PNG answered correctly through the full driver stack (`scripts/smoke-acp-image.mjs`, quota-gated) and in the phase-2 probe (`scripts/probe-acp-phase2.mjs`).
28
+ - `scripts/probe-acp-phase2.mjs`: live probe capturing thought-chunk sparsity, image end-to-end, full tool_call/tool_call_update frames, and the `/plan` command flow (raw frames in `probe-logs/`).
29
+
30
+ ### Changed
31
+
32
+ - `McpServerHandle` exposes the shared-secret token (`token`), and `TOKEN_HEADER` is exported: engines other than the stream-json discovery file need the header to reach the bridge (the ACP registration was silently sending no header and would have been 403'd).
33
+ - Driver exit handling is connection-scoped in `AcpDriver`: a killed connection's late exit (the current ACP build intercepts SIGTERM and can outlive its replacement) no longer clobbers the live connection or fails the recovery turn.
34
+ - `tool_call_update` display: the completed call's output now prefers the `content[]` text over `rawOutput`, which the server fills with a display title ("Call bridge_echo") rather than the result. The result itself reaches the model out-of-band; only the activity display was wrong.
35
+ - Tool-frame mapping fixes from the phase-2 probe: MCP `rawInput` args unwrap the `arguments` envelope, and the tool name prefers `_meta.mcp.tool` over the "<server>_<tool>" title.
36
+ - Gate C consolidation on the ACP engine: `native-tools.ts` re-exec and `WrapperReplay` parking are retired for ACP turns (tool steps render as thinking labels; `bridge_call` round-trips unaffected); ACP-native edit diffs from `tool_call` `content[]` render directly into the thinking stream via the new in-memory `formatInlineDiff` (same line-numbered format, zero git subprocesses). The git-sourced `diff-render.ts` path remains solely for the `stream-json` engine.
37
+ - G1 digest delivery split by engine: on ACP the digest ships as a native `embeddedContext` resource block in the prompt array (`promptCapabilities.embeddedContext` verified live: a resource block with a secret word was read and answered correctly); `stream-json` keeps the inline text default.
38
+ - `/agy doctor` (ACP): shows server reconnects (connections beyond the first = Gate D kills + replacements) and the handshake `agentInfo` name/title next to the server version.
39
+
40
+ ### Fixed
41
+
42
+ - `tool_call_update` failed frames whose `rawOutput` matches the RC01
43
+ approved-but-never-executed sentinel are dropped instead of rendering as a
44
+ bogus tool error next to a successful edit (run 6, finding 7).
45
+ - `AcpDriver` kills a leaked server process when the initialize handshake
46
+ fails (spawn succeeded, init timed out) - the detached process would
47
+ otherwise outlive pi.
48
+ - `AcpDriver` snapshot prefers the active session id over the last settled
49
+ one, so `/agy doctor` during a live turn shows the correct session.
50
+ - Text dedupe guard: the cumulative-mode flip now requires a respectable
51
+ accumulation (32+ chars), and a cumulative frame that stops extending the
52
+ accumulator falls back to append mode - a short markdown opener (`**`,
53
+ `#`) followed by an ordinary delta no longer corrupts the remaining output
54
+ (round-7 review, applies to both engines).
55
+
56
+ - No usage fields anywhere: token display shows zero (Gate B; the stream-json engine stays default until upstream ships usage).
57
+ - No `session/cancel` (-32601): abort tears the connection down and reloads on the next turn; `cancelSupported` is probed once and shown in `/agy doctor`.
58
+ - `tool_call` activity output shows the server's display string, not the MCP result content (the model receives the result out-of-band; only the activity display lacks it).
59
+ - `agent_thought_chunk` is sparse on RC01 (a step-by-step prompt produced zero; reasoning ships as plain message text). The thinking pipeline handles deltas when they occur.
60
+ - ACP has NO review-only mode: the three modes are permission modes only, and the server-intercepted `/plan` command writes its artifact under auto policy. Plan delegations keep the legacy `agy -p --mode plan` path (committed exception).
61
+
5
62
  ## [1.3.3] - 2026-09-01
6
63
 
7
64
  ### Added
package/README.md CHANGED
@@ -1,8 +1,12 @@
1
1
  # pi-antigravity-bridge
2
2
 
3
- A Gemini model provider **and** the `AskAntigravity` delegation tool for [pi](https://github.com/earendil-works/pi-coding-agent), both built on Google's `agy` CLI. It registers `antigravity/gemini-*` models in pi's `/model` picker (streaming), and provides the `AskAntigravity` tool for one-shot delegation - the same combined shape as `pi-claude-bridge`.
3
+ A Gemini model provider **and** the `AskAntigravity` delegation tool for [pi](https://github.com/earendil-works/pi-coding-agent), built on Google's official Antigravity binaries: the `agy` CLI by default, or **Google's official ACP server** (opt-in). It registers `antigravity/gemini-*` models in pi's `/model` picker (streaming), and provides the `AskAntigravity` tool for one-shot delegation - the same combined shape as `pi-claude-bridge`.
4
4
 
5
- <img width="3024" height="1774" alt="image" src="https://github.com/user-attachments/assets/9fc2f368-7292-4dde-851b-db2bd579263c" align="center" />
5
+ <img width="2566" height="1723" alt="SCR-20260903-sefo" src="https://github.com/user-attachments/assets/20f0c04c-d622-4b11-962a-3478f64570c2" align="center"/>
6
+
7
+ <br/><br/>
8
+
9
+ <img width="1272" height="842" alt="SCR-20260903-sfcu" src="https://github.com/user-attachments/assets/c483613b-10ff-4d2f-9893-027d84130ac6" align="center" />
6
10
 
7
11
  If you also have [`@estebanforge/pi-ask-antigravity`](https://github.com/EstebanForge/pi-ask-antigravity) installed, this bridge takes over: pi-ask-antigravity detects the bridge and registers nothing, so the `AskAntigravity` tool is never duplicated.
8
12
 
@@ -12,6 +16,17 @@ You pick a Gemini model in pi's `/model` picker. pi routes each turn through thi
12
16
 
13
17
  Multi-turn works. The provider binds a pi session to an agy conversation id (persisted under `~/.pi/agent/antigravity-bridge/sessions.json`) and resumes it on the next turn via `--conversation <id>`. agy keeps its own history, so only the latest user message is sent each turn.
14
18
 
19
+ ### Two engines
20
+
21
+ Turns run through one of two engines behind the same provider surface (`config.engine`, default `stream-json`):
22
+
23
+ - **stream-json** (default): the persistent `agy` CLI process. The tested default; live token usage; conversation resume via `--conversation`.
24
+ - **acp**: Google's official ACP server (`agy_acp_server.par`), JSON-RPC 2.0 over stdio. Opt-in while it matures: the current build (RC01) ships no usage fields (token display shows zero) and no cancel (abort tears the server down and reloads it next turn). Everything else is parity-verified live - text streaming, multi-turn resume via `session/load`, bridge tools, effort switching, serialization, abort recovery - see `scripts/parity-live.mjs`.
25
+
26
+ Engine-dependent features: pi image attachments ride natively only on the ACP engine (the picker offers image attach automatically when `config.engine` is `acp`; the stream-json CLI prompt is text-only). With the optional G1 digest enabled, its delivery also differs: ACP ships it as a native `embeddedContext` resource block, stream-json prepends it to the prompt text.
27
+
28
+ Switch with `/agy engine acp|stream-json` (takes effect on restart). Setup is automatic: switching to `acp` installs Google's official ACP server binary from the [antigravity-acp registry entry](https://github.com/agentclientprotocol/registry) (`~/.local/opt/agy-acp/<build>/` + a `current` symlink, zip sha256 recorded; layout and pinning in [docs/ACP-ADOPTION-PLAN.md](docs/ACP-ADOPTION-PLAN.md)) and prepares the login. The login is your Antigravity subscription: on your first ACP message the server opens the Google login in your browser, and you sign in with the same account and plan you use for the Antigravity CLI (`agy`). It is no different from logging into the CLI; the server just keeps its own token file on your machine, like any Google tool, and this extension never sees your credentials. If you also export `GEMINI_API_KEY`, it is ignored: the server uses the auth type in settings.json, and setup always writes `oauth-personal`. A session start self-heals the same way, silently when everything is ready. Manual instructions (`/agy acp-auth`) surface only when a step fails. Sessions are engine-scoped, so switching engines never crosses conversations.
29
+
15
30
  ## What it cannot do
16
31
 
17
32
  agy runs its own closed tool loop (`read_file`, `write_file`, `edit_file`, `run_command`) against `--add-dir`. Its read-only steps (`view_file`, `list_dir`, `grep_search`, `find_by_name`) re-run as real pi builtins (`read`, `ls`, `grep`, `find`) so their cards render natively; mutating steps never execute in pi - they replay through a display-only `antigravity` wrapper tool. What used to be a hard wall for pi's other tools is bridgeable; see [MCP tool bridge](#mcp-tool-bridge-agy-uses-pis-tools) below.
@@ -110,6 +125,8 @@ Env overrides: `AGY_BRIDGE_TOOLS`, `AGY_DIGEST`, `AGY_SYSTEM_PROMPT`. Env wins o
110
125
  /agy thinking low|medium|high default thinking tier for the AskAntigravity tool
111
126
  /agy digest on|off inject pi-side context into agy prompts (default off; see table above)
112
127
  /agy system-prompt on|off send pi's system prompt + AGENTS.md to new agy conversations (default on)
128
+ /agy engine acp|stream-json switch the turn engine (restart to apply; default stream-json; acp runs self-service setup: binary install + auth bootstrap)
129
+ /agy acp-auth manual ACP credential setup (fallback; auto-setup normally covers this; default login = your Antigravity subscription, same account as the agy CLI)
113
130
  /agy patch-cleanup restore the original pi files if an older version patched them
114
131
  /agy clear drop all session bindings (force fresh conversations)
115
132
  ```
@@ -131,6 +148,8 @@ For isolation when running any agent that executes commands without a confirmati
131
148
  | Variable | Purpose |
132
149
  | --- | --- |
133
150
  | `AGY_BIN` | Path to the agy binary. Defaults to `agy` on PATH. |
151
+ | `AGY_ENGINE` | Turn engine: `stream-json` (default) or `acp`. Wins over the config file. |
152
+ | `AGY_ACP_BIN` | Path to the ACP server binary (`agy_acp_server.par`). Defaults to `agy_acp_server.par` on PATH. Wins over `config.acp.bin`. When neither points at a binary, auto-setup installs one. |
134
153
  | `AGY_EXTRA_ARGS` | Extra args appended to every invocation. Whitespace-split. |
135
154
  | `AGY_CONVERSATIONS_DIR` | Override the conversations DB directory. |
136
155
  | `AGY_MODE` | Override execution mode: `plan` (review-only) or `accept-edits` (default). Wins over the config file. |
@@ -146,7 +165,7 @@ Build, test, and debug instructions live in [docs/DEVELOPMENT.md](docs/DEVELOPME
146
165
 
147
166
  Google's [Antigravity ToS](https://antigravity.google/terms) (Section 6) prohibits accessing the service "in connection with products not provided by us", and names as its example using tools like Hermes/OpenClaw with Antigravity OAuth. That targets reusing your credentials in a non-Google harness that calls Google's backend directly.
148
167
 
149
- This extension does not do that. It spawns the official, unmodified `agy` binary as a subprocess; `agy` performs its own OAuth and makes its own calls to Google. This code never sees, extracts, or reuses your token, and never contacts Antigravity's backend. It only reads what `agy` itself produces locally: its stream-json output. From Google's server-side view there is no signal that distinguishes "agy launched by pi" from "agy launched by a terminal, an IDE task runner, or cron": same signed binary, same authenticated calls.
168
+ This extension does not do that. It spawns official, unmodified Google binaries as subprocesses - the `agy` CLI, or the official ACP server when enabled - which perform their own OAuth and make their own calls to Google. This code never sees, extracts, or reuses your token, and never contacts Antigravity's backend. It only reads what the binary itself produces locally: its stream-json output, or its ACP JSON-RPC messages. From Google's server-side view there is no signal that distinguishes "agy launched by pi" from "agy launched by a terminal, an IDE task runner, or cron": same signed binaries, same authenticated calls.
150
169
 
151
170
  Google's reported enforcement to date (the February 2026 suspensions) targeted token-reuse tools, not spawning the official CLI.
152
171