@estebanforge/pi-antigravity-bridge 1.6.2 → 1.6.4
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 +6 -0
- package/README.md +1 -1
- package/extensions/index.ts +17 -8
- package/package.json +5 -21
- package/src/approval-hook.ts +116 -98
- package/src/driver.ts +6 -1
- package/docs/ACP-ADOPTION-PLAN.md +0 -940
- package/docs/ACP-PROTOCOL-REFERENCE.md +0 -462
- package/docs/ANTIGRAVITY-INTEGRATIONS.md +0 -50
- package/docs/APPROVAL-GATE.md +0 -33
- package/docs/ARCHITECTURE.md +0 -116
- package/docs/DEVELOPMENT.md +0 -110
- package/docs/ENGINES.md +0 -46
- package/docs/PI-BRIDGE-GAPS.md +0 -97
- package/docs/TODO.md +0 -21
package/docs/ARCHITECTURE.md
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
# Architecture
|
|
2
|
-
|
|
3
|
-
How the provider works internally. For build/test/debug workflow see [DEVELOPMENT.md](./DEVELOPMENT.md).
|
|
4
|
-
|
|
5
|
-
## Engine
|
|
6
|
-
|
|
7
|
-
The provider ships two turn engines behind one contract (`TurnDriver`,
|
|
8
|
-
`src/driver-types.ts`): the default **stream-json engine** (below) and the
|
|
9
|
-
opt-in **ACP engine** (bottom of this doc). Turns are fed over stdin; agy emits NDJSON events on stdout; the driver parses them and streams text into pi token by token. Conversation binding comes from the `init` event, tool steps arrive as typed events (no protobuf decoding), and token usage is live.
|
|
10
|
-
|
|
11
|
-
Shared infrastructure: session binding (`sessions.json`), runtime config, the `AskAntigravity` tool, the MCP tool bridge surface, and the G1 context digest (off by default - see below).
|
|
12
|
-
|
|
13
|
-
## Module map
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
extensions/index.ts pi extension entry: provider registration, model discovery, /agy command, lifecycle notices
|
|
17
|
-
src/provider.ts streamSimple: pi Context -> agy turn -> pi event stream; owns the G9 round-trip store and the G1 digest
|
|
18
|
-
src/driver.ts stream-json driver: persistent agy process, turn serialization, conversation binding, idle/abort timers
|
|
19
|
-
src/stream-events.ts agy NDJSON event parser (init / step_update / result) + usage mapping onto pi's Usage
|
|
20
|
-
src/native-tools.ts maps agy read-only tool steps to real pi builtins (read/ls/grep/find) for native re-execution
|
|
21
|
-
src/skills.ts activate_skill bridge: exposes the pi Agent Skills catalog to agy, answered by the bridge directly
|
|
22
|
-
src/patch-cleanup.ts detects a leftover invokeTool patch from pre-1.3.0 installs; /agy patch-cleanup restores the backup
|
|
23
|
-
src/discovery.ts conversation-id binding for the AskAntigravity one-shot tool (agy -p never prints its conversation id)
|
|
24
|
-
src/models.ts agy models -> pi Model projection (full catalog, per-model effort)
|
|
25
|
-
src/sessions.ts atomic JSON store: pi session -> agy conversation + watermark
|
|
26
|
-
src/config.ts persisted runtime config (engine + acp block, bridgeTools, digest, mode, permissions, model/thinking defaults)
|
|
27
|
-
src/daily-log.ts daily NDJSON support log (one file per day, 14-day retention, secret redaction, AGY_DEBUG verbose gate); fed by both drivers, the bridge, round-trips, /agy, and ask-tool
|
|
28
|
-
src/ask-tool.ts the AskAntigravity one-shot delegation tool (model/thinking defaults)
|
|
29
|
-
src/mcp-server.ts MCP tool bridge server: ferries tools/list + tools/call; calls park in the provider round-trip. Also the approval park: POST /approval (ticket early-ack) + GET /approval/<id>, fail-closed on timeout/unwired/close
|
|
30
|
-
src/mcp-registration.ts registers/unregisters the bridge in ~/.gemini/config/mcp_config.json for the stream-json CLI (per-pid, atomic, stale sweep) and flips our entries off around AskAntigravity spawns (refcounted; session start re-enables)
|
|
31
|
-
src/approval-gate.ts shadow tool factory (bash/write/edit): marker calls are ticket-verified approval round-trips, non-marker calls delegate; maps agy native tools onto the shadow surface
|
|
32
|
-
src/approval-detect.ts third-party pi permission-extension detection; resolves approvals.gateMode auto (off until a gate extension exists)
|
|
33
|
-
src/approval-hook.ts merge-safe .agents/hooks.json staging (PreToolUse) + generated 0600 early-ack/poll hook script; staged timeout exceeds the park budget (hook timeouts soft-pass)
|
|
34
|
-
src/diff-render.ts stream-json: render agy's file edits as git diffs in pi's thinking stream; formatInlineDiff (no git) renders ACP's native diffs
|
|
35
|
-
src/engine-picker.ts first-run onboarding: engine picker overlay (SelectList + DynamicBorder), first-run gate (no config file + no AGY_ENGINE), agy binary detection (PATH / AGY_BIN), missing-CLI toast copy
|
|
36
|
-
src/driver-types.ts TurnDriver contract shared by both engines (request/handle/snapshot types)
|
|
37
|
-
src/acp/jsonrpc.ts NDJSON JSON-RPC 2.0 framing with line buffering and typed error results
|
|
38
|
-
src/acp/connection.ts ACP server process + protocol (initialize, session/new+load, prompt with image/resource blocks, config options, cancel probing, auto permissions)
|
|
39
|
-
src/acp/events.ts session/update -> DriverActivity mapping (pure; probe-frame regressions pinned)
|
|
40
|
-
src/acp/driver.ts AcpDriver: serialized turns, remaining-budget timer pause, Gate D abort, connection-scoped exit handling, reconnect/agentInfo snapshots
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
No generated protobuf code, no SQLite dependency.
|
|
44
|
-
|
|
45
|
-
## Stream-json engine
|
|
46
|
-
|
|
47
|
-
### Process and events
|
|
48
|
-
|
|
49
|
-
The driver spawns `agy --input-format stream-json --output-format stream-json` once per provider and keeps it alive across turns (`/agy doctor` shows the reuse counter). A turn writes the prompt to stdin and reads NDJSON events until the terminal `result`:
|
|
50
|
-
|
|
51
|
-
| event | meaning |
|
|
52
|
-
| --- | --- |
|
|
53
|
-
| `init` | conversation binding (`conversation_id`); the driver remembers it and resumes later turns via `--conversation <id>` |
|
|
54
|
-
| `step_update` | `user_input` / `checkpoint` / `agent_response` / `tool` steps; agent text arrives as `text_delta` on live agy (1.1.13+), with `usage` attached |
|
|
55
|
-
| `result` | terminal; live builds report status `SUCCESS` (older builds `OK` - both accepted) |
|
|
56
|
-
|
|
57
|
-
Unknown event kinds parse as `{kind:"unknown"}` so a future agy release degrades instead of crashing the reader loop. Shapes were captured from live output and cross-checked against tianzuo/pi-antigravity `lib/events.ts` (MIT).
|
|
58
|
-
|
|
59
|
-
Usage maps onto pi's `Usage` (input/output/thinking/cache-read tokens); cost stays zero because agy runs on subscription quota.
|
|
60
|
-
|
|
61
|
-
### No-patch tool round-trip (G9)
|
|
62
|
-
|
|
63
|
-
The MCP bridge server executes no tools itself. A `tools/call` parks in the provider's round-trip store; the provider ends the current pi assistant message with a `toolUse` stop reason for the real pi tool; pi executes it in its own loop (native cards, permissions, hooks); the `toolResult` completes the parked MCP response on the next stream call. No pi patch, no privileged API.
|
|
64
|
-
|
|
65
|
-
Display follows the same split: agy read-only steps (`view_file`, `list_dir`, `grep_search`, `find_by_name`) re-run as real pi builtins via `native-tools.ts`, so their cards render with pi's own renderers. Mutating and agy-specialty steps replay through a display-only `antigravity` wrapper tool - recorded output only, nothing re-executes. The skills bridge exposes one `activate_skill` tool whose enum is the pi Agent Skills catalog; the bridge answers it directly, no round-trip.
|
|
66
|
-
|
|
67
|
-
### Context digest (G1)
|
|
68
|
-
|
|
69
|
-
By default the prompt agy receives is only the latest user message: agy keeps its own history. When `config.digest` is on (`AGY_DIGEST`, `/agy digest on`), the provider prepends a DELTA digest of pi-side context agy was not spawned for - compaction summaries, other-provider turns, pi-tool results. Off by default because the digest changes every turn and defeats agy's server-side prompt cache (~25-30k tokens re-billed per turn). Enable it for mixed-provider sessions where agy must see pi-side context; pure antigravity sessions gain nothing, and bridge round-trips deliver tool results through the bridge, not the digest.
|
|
70
|
-
|
|
71
|
-
### Removed: the legacy-sqlite engine (1.3.2)
|
|
72
|
-
|
|
73
|
-
The pre-1.3.0 engine (spawn `agy -p`, poll the SQLite conversation DB, decode protobuf step payloads) was removed in 1.3.2. agy 1.1.18 changed the step-row storage to a two-phase write (a metadata-only placeholder row that grows in place), which the polling decoder read once as an empty placeholder and never re-read: turns completed with the full reply in the database and zero text streamed to pi (issue #1, reported by @imatimba). The engine reverse-engineered an undocumented storage format, so every agy storage change risked repeating that silent failure. The stream-json engine shares none of that code path and is unaffected by storage-format changes. `AGY_ENGINE` and the `engine` config key are gone; a stale value in an existing `config.json` is ignored.
|
|
74
|
-
|
|
75
|
-
## ACP engine (opt-in, official server)
|
|
76
|
-
|
|
77
|
-
`config.engine: "acp"` (or `/agy engine acp`) routes turns through Google's
|
|
78
|
-
official ACP server (`agy_acp_server.par`, registry id `antigravity-acp`)
|
|
79
|
-
over JSON-RPC stdio. Off by default; stream-json remains the default. BOTH
|
|
80
|
-
engines are permanently maintained peers (standing decision - no deletion,
|
|
81
|
-
regardless of Gate B). Gate B (absent usage fields) is informational:
|
|
82
|
-
zero-usage is documented on ACP. See docs/ACP-ADOPTION-PLAN.md section 17.
|
|
83
|
-
|
|
84
|
-
Modules: `src/acp/jsonrpc.ts` (framing/correlation), `src/acp/connection.ts`
|
|
85
|
-
(process + protocol methods + in-connection `auto` permission answering),
|
|
86
|
-
`src/acp/events.ts` (update mapping, pure), `src/acp/driver.ts`
|
|
87
|
-
(`AcpDriver`). Both engines implement `TurnDriver`; `provider.ts` depends on
|
|
88
|
-
the interface only and is otherwise unchanged.
|
|
89
|
-
|
|
90
|
-
Phase-2/3 additions (all ACP-only, verified live):
|
|
91
|
-
|
|
92
|
-
- **Images**: pi image attachments ride as typed content blocks in the
|
|
93
|
-
prompt array; models advertise `input: ["text","image"]` only when the
|
|
94
|
-
engine is `acp` (decided at extension load). stream-json prompt input
|
|
95
|
-
stays text-only (tool-RESULT images ride both engines; see
|
|
96
|
-
PI-BRIDGE-GAPS).
|
|
97
|
-
- **Digest delivery**: with `config.digest` on, ACP ships the G1 digest as
|
|
98
|
-
a native `embeddedContext` resource block (images → resource → text);
|
|
99
|
-
stream-json keeps it inline. Same cache churn either way.
|
|
100
|
-
- **Tool display (Gate C)**: ACP tool steps render as thinking labels -
|
|
101
|
-
native re-exec and wrapper replay are retired on ACP turns (the server
|
|
102
|
-
already executed the tool). Edits render their server-supplied diff
|
|
103
|
-
(`tool_call content[]` → `formatInlineDiff`, no git subprocesses).
|
|
104
|
-
- **Diagnostics**: the ACP snapshot reports reconnects (connections beyond
|
|
105
|
-
the first: Gate D kills + stale-exit replacements) and the handshake
|
|
106
|
-
`agentInfo` name/title; `/agy doctor` surfaces both.
|
|
107
|
-
|
|
108
|
-
Engine-specific behavior: session ids are scoped per engine
|
|
109
|
-
(`sid:<x>@acp`); model/effort ship as one full slug via
|
|
110
|
-
`session/set_config_option` and are RE-APPLIED after every server restart
|
|
111
|
-
(config does not persist); `session/load` history replay is swallowed (never
|
|
112
|
-
live text); abort is teardown+kill+reload while `session/cancel` is
|
|
113
|
-
unimplemented (RC01); usage tokens are absent (zero-usage fallback).
|
|
114
|
-
Verified protocol shapes and the auth flow:
|
|
115
|
-
docs/ACP-PROTOCOL-REFERENCE.md. Raw captures: `probe-logs/` (gitignored,
|
|
116
|
-
local only).
|
package/docs/DEVELOPMENT.md
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
# Development & Debugging
|
|
2
|
-
|
|
3
|
-
How to build, test, and debug this extension outside pi.
|
|
4
|
-
|
|
5
|
-
## Build, test, typecheck
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install
|
|
9
|
-
npm test # unit tests via vitest (no agy spawn, no network)
|
|
10
|
-
npm run build # tsc --noEmit type check
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
The integration scripts below spawn a real `agy` process and need a logged-in account. The unit tests (`npm test`) need neither.
|
|
14
|
-
|
|
15
|
-
## Standalone scripts
|
|
16
|
-
|
|
17
|
-
These exercise the pipeline without pi. Useful for isolating where a bug lives (driver? provider? pi loader?).
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
# Drive the provider's streamSimple directly (no pi TUI) and assert the
|
|
21
|
-
# full event lifecycle: start -> text_start -> text_delta -> text_end ->
|
|
22
|
-
# done. The closest thing to a pi turn without pi.
|
|
23
|
-
npx tsx scripts/test-provider.ts
|
|
24
|
-
|
|
25
|
-
# Load the extension through a mock ExtensionAPI and assert registerProvider
|
|
26
|
-
# + registerCommand (/agy) fire with the right shape. No agy spawn.
|
|
27
|
-
npx tsx scripts/test-extension.ts
|
|
28
|
-
|
|
29
|
-
# Load the extension through pi's REAL loader and confirm the antigravity/*
|
|
30
|
-
# models register. This is the in-pi smoke test.
|
|
31
|
-
npm run smoke:pi
|
|
32
|
-
|
|
33
|
-
# Live smoke for the stream-json engine. OPT-IN: spends a little Antigravity
|
|
34
|
-
# quota. Proves the persistent process: init binds a conversation, text deltas
|
|
35
|
-
# arrive, the result settles, and a second turn reuses the process.
|
|
36
|
-
AGY_LIVE=1 node --experimental-strip-types scripts/smoke-stream-json.mjs
|
|
37
|
-
|
|
38
|
-
# Live smoke for the ACP engine through OUR driver stack. OPT-IN: spends a
|
|
39
|
-
# little quota. Needs AGY_ACP_BIN (or acp on PATH) and a one-time
|
|
40
|
-
# /agy auth-manual credential setup.
|
|
41
|
-
AGY_ACP_LIVE=1 AGY_ACP_BIN=~/.local/opt/agy-acp/current/agy_acp_server.par \
|
|
42
|
-
npx tsx scripts/smoke-acp.mjs
|
|
43
|
-
|
|
44
|
-
# Live smoke for the Gate F bridge e2e: the real ACP server lists the bridge
|
|
45
|
-
# catalog and completes a tool call through the registered mcpServers entry.
|
|
46
|
-
AGY_ACP_LIVE=1 AGY_ACP_BIN=~/.local/opt/agy-acp/current/agy_acp_server.par \
|
|
47
|
-
npx tsx scripts/smoke-acp-bridge.mjs
|
|
48
|
-
|
|
49
|
-
# Live smoke for image prompts on the ACP engine: builds a 64x64 two-tone PNG
|
|
50
|
-
# in-process and asserts the model identifies both halves through the full
|
|
51
|
-
# driver stack.
|
|
52
|
-
AGY_ACP_LIVE=1 AGY_ACP_BIN=~/.local/opt/agy-acp/current/agy_acp_server.par \
|
|
53
|
-
npx tsx scripts/smoke-acp-image.mjs
|
|
54
|
-
|
|
55
|
-
# Live probe: thought-chunk sparsity, tool_call content[]/rawInput shapes,
|
|
56
|
-
# and the /plan command flow, captured to probe-logs/ (local only).
|
|
57
|
-
AGY_ACP_LIVE=1 AGY_ACP_BIN=~/.local/opt/agy-acp/current/agy_acp_server.par \
|
|
58
|
-
npx tsx scripts/probe-acp-phase2.mjs
|
|
59
|
-
|
|
60
|
-
# Live probe: does the ACP server deliver MCP tool-result IMAGE content to
|
|
61
|
-
# the model? One bridge tool returns a two-tone PNG in its result; the model
|
|
62
|
-
# must name both halves from the tool result alone.
|
|
63
|
-
AGY_ACP_LIVE=1 AGY_ACP_BIN=~/.local/opt/agy-acp/current/agy_acp_server.par \
|
|
64
|
-
npx tsx scripts/probe-acp-image-result.mjs
|
|
65
|
-
|
|
66
|
-
# Live probe: same image question for the stream-json engine. AGY
|
|
67
|
-
# bridge tool returns a two-tone PNG in its result; model must name both
|
|
68
|
-
# halves. AGY_PROBE_REG_ONLY=1 skips the turn and dumps MCP registration
|
|
69
|
-
# state (no quota).
|
|
70
|
-
AGY_LIVE=1 npx tsx scripts/probe-stream-json-image.mjs
|
|
71
|
-
|
|
72
|
-
# Live parity run: the SAME scenario set (streaming, continuity, bridge
|
|
73
|
-
# round-trip, effort switch, serialization, abort+recover, usage) through
|
|
74
|
-
# BOTH engines. Needs the agy CLI AND the ACP binary. Spends ~13 flash-low
|
|
75
|
-
# turns; prints a per-scenario matrix and exits non-zero on any mismatch.
|
|
76
|
-
AGY_ACP_LIVE=1 AGY_ACP_BIN=~/.local/opt/agy-acp/current/agy_acp_server.par \
|
|
77
|
-
npx tsx scripts/parity-live.mjs
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
## Debugging a hang or "stuck" turn
|
|
81
|
-
|
|
82
|
-
Most "stuck" reports trace to one of:
|
|
83
|
-
|
|
84
|
-
1. **agy blocked on a permission prompt.** `accept-edits` auto-approves file edits but NOT shell commands. Any `run_command` prompts `y/n`, which hangs forever in non-interactive mode. The provider passes `--dangerously-skip-permissions` by default to avoid this. If you turned it off (`/agy permissions off`), that is why. See the README Permissions section.
|
|
85
|
-
2. **agy never started.** Check `AGY_BIN` is on PATH (or set explicitly). The spawner swallows spawn ENOENT into the result's stderr, surfaced by the provider as an error event.
|
|
86
|
-
3. **Conversation id never bound.** On `stream-json` the `init` event carries the id, so a missing binding means the turn never produced a result event. `/agy doctor` prints the last lifecycle events.
|
|
87
|
-
4. **Print-mode environmental hang.** `pi -p` can hang with zero output in some containers (upstream [google-antigravity/antigravity-cli#318](https://github.com/google-antigravity/antigravity-cli/issues/318)). It affects built-in providers too, not this extension. Validate the turn with `scripts/test-provider.ts` instead.
|
|
88
|
-
|
|
89
|
-
## Regression tests worth knowing
|
|
90
|
-
|
|
91
|
-
- `tests/stream-roundtrip.test.ts` - the stream-json engine pieces: NDJSON parser, native re-exec mapping, and the no-patch toolUse round-trip store.
|
|
92
|
-
- `tests/provider-streaming.test.ts` - drives streamSimple with an injected fake driver (no agy) and asserts how pi's reasoning level maps onto the agy `--effort` tier (forward, clamp, omit).
|
|
93
|
-
- `tests/provider-digest.test.ts` - the G1 context digest builder: injects pi-side context without replaying agy's own history.
|
|
94
|
-
- `tests/patch-cleanup.test.ts` - legacy-patch detection and restore, real fs via tmpdirs, no mocks.
|
|
95
|
-
- `tests/mcp-server.test.ts` - the MCP tool bridge end-to-end against a real (port 0) server: capability gate, per-pid config lifecycle, shared-secret token gate, 1 MB body cap, protocol-version clamp. The provider owns the tool catalog and the round-trip; the server only ferries list/call.
|
|
96
|
-
- `tests/acp-jsonrpc.test.ts` - the JSON-RPC stdio session: id correlation, typed error results, server-to-client requests, notifications, line framing (partial frames buffered across chunk boundaries, garbage lines counted not fatal).
|
|
97
|
-
- `tests/acp-events.test.ts` - ACP session/update mapping onto pi activities (text, thought, tool cards) and the session/load replay suppression.
|
|
98
|
-
- `tests/acp-driver.test.ts` - the ACP driver over the fake server (`tests/helpers/fake-acp-server.mjs`, scenario-selected): happy flow, load-replay, permission auto-answer, Gate D abort (cancel probe, teardown, `cancelSupported` memory), the stale-exit race (a killed connection's late exit must not fail its replacement - `ACP_FAKE_SLOW_DEATH_MS`), auth errors, park/kickIdle timer pause with remaining budget.
|
|
99
|
-
- `tests/acp-config.test.ts` - engine selection narrowing (`AGY_ENGINE`/`config.engine`), acp block parsing.
|
|
100
|
-
- `tests/daily-log.test.ts` - the support log: day rotation, retention cutoff boundary, secret redaction (incl. header blocks), the 4 KB record cap, never-throw on a broken dir, and the two-tier gate (debug records dropped unless `AGY_DEBUG`).
|
|
101
|
-
- `tests/mcp-registration.test.ts` - the `~/.gemini/config/mcp_config.json` registration for the stream-json CLI: exact agy entry shape, foreign servers preserved, corrupt config refused, atomic writes, stale-entry sweep, delegation suppression (`setBridgeEntriesDisabled` flip/restore/idempotence, refcounted `acquireBridgeSuppression`) and the cross-process marker (concurrent two-session simulation, dead and stale delegator pruning, marker-aware `healBridgeSuppression`, the registration guard).
|
|
102
|
-
- `tests/ask-tool-suppression.test.ts` - the AskAntigravity delegation path end-to-end over a fake `AGY_BIN` that outlives the old grace: exactly one suppression release, at process close, never on a timer.
|
|
103
|
-
- `tests/engine-picker.test.ts` - first-run onboarding: picker gate (no config file + no AGY_ENGINE, fail-closed fs), option order (stream-json first), the ACP download/sign-in disclosure pins (intro + saved toast), agy binary detection (PATH scan, explicit path, fail-closed), missing-CLI toast copy.
|
|
104
|
-
- `tests/provider-escalation.test.ts` - the early-ack + poll pipeline (escalation registry, poll views, late-delivery tombstones) and tool-result image forwarding on both engines.
|
|
105
|
-
- `tests/approval-gate.test.ts` - the shadow tool factory: marker calls never execute, ticket verification denies forged/stale markers before the policy, denials throw, native-to-shadow mapping.
|
|
106
|
-
- `tests/approval-park.test.ts` - the approval park end-to-end over a real (port 0) server: POST ticket early-ack, poll pending -> terminal, timeout deny, ungated/unwired deny, close fail-closed, provider round-trip (allow / block-deny / timeout), `__agy*` strip on G9 args.
|
|
107
|
-
|
|
108
|
-
## Module map
|
|
109
|
-
|
|
110
|
-
See [ARCHITECTURE.md](./ARCHITECTURE.md) for the module map and the engine internals (stream-json events, no-patch round-trip).
|
package/docs/ENGINES.md
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
# Engines
|
|
2
|
-
|
|
3
|
-
Turns run through one of two engines behind the same provider surface (`config.engine`, default `stream-json`). The choice of engine is left to the user: a first-run picker explains the trade-offs and asks once, and `/agy engine` (no arguments, TUI) reopens the same modal anytime. Direct switches work too: `/agy engine acp|stream-json`.
|
|
4
|
-
|
|
5
|
-
- **stream-json** (default): the persistent `agy` CLI process. The tested default; live token usage; conversation resume via `--conversation`.
|
|
6
|
-
- **acp** (beta): Google's official ACP server (`agy_acp_server.par`), JSON-RPC 2.0 over stdio. Beta: parity-verified live against the current build (RC01) - text streaming, multi-turn resume via `session/load`, bridge tools, effort switching, serialization, abort recovery (see `scripts/parity-live.mjs`). Two known RC01 gaps remain: no usage fields (token display shows client-side ESTIMATES until Google ships usage; `acp.usageEstimate` off to keep zeros) and no cancel (abort tears the server down and reloads it next turn).
|
|
7
|
-
|
|
8
|
-
## First run
|
|
9
|
-
|
|
10
|
-
On a fresh install (no `config.json` yet), the first interactive pi start opens a picker modal that explains both engines - stream-json needs the `agy` CLI installed and authenticated; ACP needs a second Google sign-in plus a ~1.5 GB server binary downloaded from Google. stream-json is preselected (the default); `esc` decides later (nothing is written, the modal reappears on the next start).
|
|
11
|
-
|
|
12
|
-
Picking **acp** starts the server download immediately (progress in the status bar, milestones in the chat), then opens the Google sign-in; a restart applies the engine. Picking **stream-json** persists and toasts; while that engine is active and the `agy` binary is missing, pi warns on every start with the install link until the binary shows up.
|
|
13
|
-
|
|
14
|
-
## Capabilities
|
|
15
|
-
|
|
16
|
-
| Capability | `stream-json` (default) | `acp` (beta) |
|
|
17
|
-
| --- | --- | --- |
|
|
18
|
-
| Show thinking text | No (token count only, floor 64, no text body) | Yes (streams thought text via `agent_thought_chunk`; sparse on RC01 where reasoning often arrives in message text) |
|
|
19
|
-
| Live token usage | Yes (live metrics from CLI step events) | Estimated client-side (absent in RC01; `acp.usageEstimate`, default on) |
|
|
20
|
-
| Image prompt input | No (CLI prompt is text-only; images dropped) | Yes (native image blocks forwarded to server) |
|
|
21
|
-
| Image tool results | Yes (bridge tool results carry pixels; probe-verified 2026-09-07) | Yes (probe-verified 2026-09-05) |
|
|
22
|
-
| Audio prompt input | No (dropped) | Protocol advertised (`promptCapabilities.audio: true`) |
|
|
23
|
-
| Review-only plan mode | Yes (`--mode plan` review-only via `/agy mode plan`) | No (RC01 modes are permission levels; plan mode refused) |
|
|
24
|
-
| Leading slash commands in prompt | Disabled via `--disable-slash-commands` (sent as plain text) | Server intercepts recognized commands (e.g. `/plan`) and executes them under the active policy |
|
|
25
|
-
| Dynamic model / effort switch | Recycles process on model or effort change | Dynamic per-turn via `session/set_config_option` (no restart) |
|
|
26
|
-
| Process lifecycle | 1 persistent `agy` process per provider; recycles on drift | 1 persistent server process hosting N sessions concurrently |
|
|
27
|
-
| Session resume & persistence | Client-side map in `sessions.json` via `--conversation <id>` | Server-side session store via `session/load` and `session/new` |
|
|
28
|
-
| Turn cancel / abort | Kills process group; in-flight turn terminates | Teardown, kill, and auto-reload on RC01 (-32601 fallback) |
|
|
29
|
-
| MCP tool bridge routing | Injected filesystem config via `--add-dir` | Direct `mcpServers` param in `session/new` and `session/load` |
|
|
30
|
-
| Tool execution & visibility | Native re-exec (read-only) + wrapper replay (mutating) | Server executes tools natively; events stream with content |
|
|
31
|
-
| Inline file edit diffs | Sourced from git working tree in thinking block | Sourced from `tool_call content[]` or disk vs git HEAD |
|
|
32
|
-
| Permission handling | `--dangerously-skip-permissions` (unattended CLI requirement) | Protocol-native `session/request_permission` (auto-approve when `skipPermissions` is on; auto-deny when off) |
|
|
33
|
-
| Context digest delivery (G1) | Prepend plain text inline in prompt | Native `embeddedContext` resource block |
|
|
34
|
-
| System prompt delivery (G10) | Prepend to first prompt of conversation | Prepend to first prompt of conversation |
|
|
35
|
-
| Authentication methods | Inherits existing `agy` CLI OAuth state | 4 methods: `oauth-personal`, `oauth-business`, `gemini-api-key`, `agent-platform` |
|
|
36
|
-
| Wire protocol | Undocumented CLI NDJSON stream format | Versioned JSON-RPC 2.0 over stdio (`protocolVersion: 1`) |
|
|
37
|
-
| Diagnostics (`/agy doctor`) | Child PID, state, process spawns, recycles, queue stats | Server version, agentInfo, session counts, reconnect count, cancel support |
|
|
38
|
-
| Integration channel | Spawns internal CLI stream-json dialect | Official Google first-party ACP server binary |
|
|
39
|
-
|
|
40
|
-
## Engine-dependent features
|
|
41
|
-
|
|
42
|
-
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. The `AskAntigravity` delegation tool is unaffected by `config.engine` and runs the `stream-json` CLI (`agy -p`) across both configurations.
|
|
43
|
-
|
|
44
|
-
## Switching and setup
|
|
45
|
-
|
|
46
|
-
Switch with `/agy engine acp|stream-json` (takes effect on restart), or run `/agy engine` with no arguments for the same picker modal as first run (an `acp` pick there runs the same download + sign-in chain). 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](ACP-ADOPTION-PLAN.md)) and prepares the login. The login is your Antigravity subscription: the same account and plan you use for the Antigravity CLI (`agy`). Sign in explicitly with `/agy auth` (engine `acp` selected): it opens the Google login in your browser and completes when you finish it. If no browser is available (an SSH session on a remote machine), pi shows the sign-in URL to copy, plus the ssh port-forward command for the login redirect. 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 auth-manual`) surface only when a step fails. Sessions are engine-scoped, so switching engines never crosses conversations.
|
package/docs/PI-BRIDGE-GAPS.md
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
# pi-antigravity-bridge: capability gaps
|
|
2
|
-
|
|
3
|
-
Open capability gaps only — things the bridge cannot do today, each blocked
|
|
4
|
-
on something outside this repo. For how the bridge works (engines, G9
|
|
5
|
-
round-trip, digest), see [ARCHITECTURE.md](./ARCHITECTURE.md). For shipped
|
|
6
|
-
work, see `CHANGELOG.md`. Historical gap labels (G1 digest, G8 edit diffs,
|
|
7
|
-
G9 round-trip, G10 system prompt) live in the CHANGELOG and source comments;
|
|
8
|
-
they are closed and not used here.
|
|
9
|
-
|
|
10
|
-
## Open gaps
|
|
11
|
-
|
|
12
|
-
### pi UI primitives
|
|
13
|
-
|
|
14
|
-
**Status:** Open. **Blocked by:** pi exposing a public API surface for these
|
|
15
|
-
without a patch (the old plan of patching `AgentSession.ui` into pi's dist is
|
|
16
|
-
dead; the bridge no longer patches pi).
|
|
17
|
-
|
|
18
|
-
**Objective:** Let agy drive pi's native UI: confirm dialogs, toasts,
|
|
19
|
-
file/directory pickers, status/footer updates. agy can already
|
|
20
|
-
`ask_user_question`; missing are confirm/permission dialogs for destructive
|
|
21
|
-
ops, notification toasts, native file pickers, and status-bar updates. This
|
|
22
|
-
does NOT unlock a native diff viewer for agy edits — on stream-json that path
|
|
23
|
-
is closed (G8 renders diffs as thinking text); on ACP the server supplies
|
|
24
|
-
edit diffs in `tool_call content[]`, rendered the same way.
|
|
25
|
-
|
|
26
|
-
**Scope when unblocked:** wrappers in `src/mcp-server.ts`
|
|
27
|
-
(`pi_confirm`, `pi_notify`, `pi_select_file`, `pi_select_directory`,
|
|
28
|
-
`pi_set_status`), each parking through the provider round-trip; tests with a
|
|
29
|
-
mocked `ui` seam per primitive.
|
|
30
|
-
|
|
31
|
-
### Lifecycle event subscription
|
|
32
|
-
|
|
33
|
-
**Status:** Open. **Blocked by:** a confirmed real consumer.
|
|
34
|
-
|
|
35
|
-
**Objective:** Let a long-lived agy session observe pi events: `turn_start`,
|
|
36
|
-
`turn_end`, `tool_call`, `tool_result`, `compaction`. Today the bridge
|
|
37
|
-
handles only `session_start` and `session_shutdown`. Scope would be a
|
|
38
|
-
provider-side event tap plus a `pi_subscribe(event)` bridge tool with an SSE
|
|
39
|
-
channel.
|
|
40
|
-
|
|
41
|
-
**Caveat:** agy is request-response per turn even when the engine keeps a
|
|
42
|
-
process alive. Before building, confirm a consumer that can act on an async
|
|
43
|
-
event stream; otherwise this risks the same "no consumer" failure that sank
|
|
44
|
-
file-watching (see graveyard).
|
|
45
|
-
|
|
46
|
-
## Discarded ideas (graveyard)
|
|
47
|
-
|
|
48
|
-
Weighed and rejected; kept so they are not re-proposed.
|
|
49
|
-
|
|
50
|
-
- **Expose pi's other MCP clients** — REMOVED. pi has no native
|
|
51
|
-
MCP-client support and no MCP extension is in use, so there are no pi
|
|
52
|
-
MCP-client tools to double-expose. The bridge already surfaces every tool pi
|
|
53
|
-
actually registers.
|
|
54
|
-
- **Refresh tool list mid-session** — DECLINED. The bridge already
|
|
55
|
-
re-queries `pi.getAllTools()` on every `tools/list` (stateless server), and
|
|
56
|
-
agy reconnects and re-lists every turn (`-p`), so a tool registered
|
|
57
|
-
mid-session appears next turn. The heartbeat would only help a long-lived
|
|
58
|
-
client that caches the list, and there is none.
|
|
59
|
-
- **Settings, env, and secrets access** — DECLINED. Tools exposed via
|
|
60
|
-
the bridge run in pi's process and self-authenticate with pi's own
|
|
61
|
-
credentials, so agy already uses pi's creds for every tool; a
|
|
62
|
-
credential never crosses the bridge. A `pi_get_setting` accessor was
|
|
63
|
-
predicated on credential reuse that does not apply.
|
|
64
|
-
- **Image / binary content blocks over the bridge** — DONE (ACP engine).
|
|
65
|
-
Reopened 2026-09-05: the prior verdict below was falsified. On the ACP
|
|
66
|
-
engine, native `view_file` rejects real filesystem paths (artifact sandbox;
|
|
67
|
-
the tool-priority note steers agy to bridge tools), and bridge `read`
|
|
68
|
-
flattened pi's tool result with `blocksToText`, which drops the image block.
|
|
69
|
-
agy received only the label text and fell back to shell + `mcp-cli-ent
|
|
70
|
-
ai-vision`. Probe `scripts/probe-acp-image-result.mjs` (2026-09-05) proved
|
|
71
|
-
the ACP server delivers MCP tool-result image content to the model (PASS:
|
|
72
|
-
the model identified a two-tone PNG from the tool result alone, with no
|
|
73
|
-
image in the prompt). Fix: image blocks in parked pi tool results now ride
|
|
74
|
-
bridge results as MCP image content on the ACP engine (fast resolve path,
|
|
75
|
-
escalation registry, and `bridge_poll_result`), so `read` on an image file
|
|
76
|
-
gives agy real pixels. DONE on stream-json too (probe
|
|
77
|
-
`scripts/probe-stream-json-image.mjs`, 2026-09-07: the CLI's MCP client
|
|
78
|
-
delivers tool-result image content to the model — two-tone PNG named from
|
|
79
|
-
the result alone, bridge tool called once, zero decoders in the frame
|
|
80
|
-
trail). Image blocks now ride parked pi tool results on both engines
|
|
81
|
-
(fast resolve path, escalation registry, and `bridge_poll_result`), so
|
|
82
|
-
`read` on an image file gives agy real pixels everywhere. Still
|
|
83
|
-
text-only, deliberately: the late-delivery prompt
|
|
84
|
-
(`buildLateResultPrompt`), and the stream-json prompt attachments.
|
|
85
|
-
Superseded verdict (kept for the record): NOT NEEDED. pi shares the path to
|
|
86
|
-
any image it produces (e.g. `/tmp/pi-clipboard-<uuid>.png`), and agy
|
|
87
|
-
reaches and reads those files directly via the bridge's `read` tool, so
|
|
88
|
-
returning image content blocks over the transport would duplicate a path
|
|
89
|
-
that already works end-to-end. No agy transport change or pi patch
|
|
90
|
-
required. Update (2026-09-04): user-provided image *attachments* now ride
|
|
91
|
-
natively on the ACP engine as typed prompt content blocks (see README, Two
|
|
92
|
-
engines); the stream-json CLI prompt stays text-only, and the bridge
|
|
93
|
-
direction above is unchanged.
|
|
94
|
-
- **File-watching / live state** — DECLINED. agy is request-response
|
|
95
|
-
per turn, not event-reactive; nothing consumes a file-watch SSE stream, and
|
|
96
|
-
re-reads are cheap and correct. Watchers would add inotify/FSEvents handles,
|
|
97
|
-
races, and cleanup for no gain.
|
package/docs/TODO.md
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# TODO
|
|
2
|
-
|
|
3
|
-
## 1. Approval gate: live end-to-end verification
|
|
4
|
-
|
|
5
|
-
The gate is wired and unit-pinned (333 tests) but has never run against a live
|
|
6
|
-
agy turn. Enable it, drive an agy turn that mutates a file, and watch the
|
|
7
|
-
round trip: PreToolUse hook -> POST /approval park -> shadow toolUse ->
|
|
8
|
-
decision -> hook stdout -> agy enforces.
|
|
9
|
-
|
|
10
|
-
- Enable without a third-party extension: `AGY_APPROVALS=shadow AGY_APPROVALS_MODE=ask` (interactive pi; headless denies). Deny path: a fake gate extension that blocks marker calls (`pi.on("tool_call")` + `{block: true, reason}`).
|
|
11
|
-
- Probe artifacts live outside the repo: `~/tmp/pi-antigravity-bridge-probes/` (run scripts via `npx tsx` from the repo cwd - they import src/*.ts).
|
|
12
|
-
- Live-behavior risks to watch: hook timeout soft-passes (V3) - the staged timeout must keep exceeding the park budget; denied calls emit no `tool_call` session/update frames on ACP (V2); edit-class arg names beyond `create_file` are docs-attested, never live-captured - check the confirm-dialog text on a real `run_command` and a real `replace_file_content`.
|
|
13
|
-
- On pass: clear the "NOT yet live-verified" notes (AGENTS.md, this file).
|
|
14
|
-
|
|
15
|
-
## 2. Explicit `antigravity_approve` variant (dedicated mode)
|
|
16
|
-
|
|
17
|
-
`approvals.gateMode: "dedicated"` currently stages the same shadow tools
|
|
18
|
-
(warn-logged remap). Planned: one registered tool `antigravity_approve` with
|
|
19
|
-
input `{toolName, args}`, for setups that prefer explicit names (gotgenes
|
|
20
|
-
`shellTools` alias users). Full v2 spec preserved in git history:
|
|
21
|
-
`dd7845b:docs/TODO.md` (sections 2.1-2.9).
|