@estebanforge/pi-antigravity-bridge 1.4.0 → 1.4.2
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 +22 -0
- package/README.md +11 -7
- package/docs/ACP-ADOPTION-PLAN.md +33 -33
- package/docs/ACP-PROTOCOL-REFERENCE.md +1 -1
- package/extensions/index.ts +207 -49
- package/package.json +5 -4
- package/src/acp/connection.ts +22 -8
- package/src/acp/driver.ts +14 -10
- package/src/acp/setup.ts +355 -0
- package/src/config.ts +8 -4
- package/src/driver.ts +20 -1
- package/src/provider.ts +8 -0
- package/src/skills.ts +109 -32
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.4.2] - 2026-09-04
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- `bridgeTools` now defaults to `all` (every registered non-builtin pi tool) instead of `mcp`. The `mcp` surface filters to pi-mcp-adapter tools and serves an empty catalog on installs without that adapter, which left the bridge registered but tool-less from the model's point of view. `none` still opts out entirely; explicit `"bridgeTools": "mcp"` in an existing config keeps pinning the narrow surface.
|
|
10
|
+
- Skill discovery now mirrors pi's directory-based scan (docs/skills.md): global `~/.pi/agent/skills` AND `~/.agents/skills`, project `.pi/skills` plus `.agents/skills` in cwd and ancestors up to the git root (project dirs only when pi has trusted the project, same gate pi applies), recursive SKILL.md discovery with grouping folders, per-style root/`.md` rules, hidden entries skipped, and description-less skills dropped. Pi's other skill sources (`skills` settings array, `package.json`, `--skill`) are not mirrored. Previously only one flat level of two directories was scanned, and `~/.agents/skills` (where pi actually reads most skills) was missing entirely, so `activate_skill` never appeared.
|
|
11
|
+
- `/agy` now exposes the full runtime config surface: new `/agy bridge all|mcp|none` (which pi tools the MCP bridge hands to agy) and `/agy acp-bin <path|auto>` (target a specific ACP server binary; applies on the next ACP turn), plus Bridge tools, Context digest, and System prompt rows in the bare `/agy` settings picker. Usage strings and `/agy status` list every knob.
|
|
12
|
+
|
|
13
|
+
## [1.4.1] - 2026-09-04
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- 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.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- 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.
|
|
22
|
+
- 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.
|
|
23
|
+
- 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).
|
|
24
|
+
- 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.
|
|
25
|
+
- 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.
|
|
26
|
+
|
|
5
27
|
## [1.4.0] - 2026-09-04
|
|
6
28
|
|
|
7
29
|
### Added
|
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ Turns run through one of two engines behind the same provider surface (`config.e
|
|
|
25
25
|
|
|
26
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
27
|
|
|
28
|
-
Switch with `/agy engine acp|stream-json` (takes effect on restart).
|
|
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
29
|
|
|
30
30
|
## What it cannot do
|
|
31
31
|
|
|
@@ -104,19 +104,21 @@ If `agy models` fails at load (binary missing, auth not done, network stall), a
|
|
|
104
104
|
|
|
105
105
|
| Key | Values | Default |
|
|
106
106
|
| --- | --- | --- |
|
|
107
|
-
| `bridgeTools` | `none` (bridge off), `
|
|
107
|
+
| `bridgeTools` | `none` (bridge off), `all` (every non-builtin tool, incl. other `Ask*` delegations), `mcp` (pi-mcp-adapter tools + skills bridge only) | `all` |
|
|
108
108
|
| `digest` | `off` (stable prompts; agy's prompt cache hits) or `on` (inject a delta of pi-side context - compaction summaries, other-provider turns - into each agy prompt; the delta changes every turn, so agy re-bills the full context). Enable for mixed-provider sessions where agy must see pi-side context | `off` |
|
|
109
109
|
| `systemPrompt` | `on` (prepend pi's system prompt - operating instructions plus the global agent-dir `AGENTS.md` and ancestor `AGENTS.md`/`CLAUDE.md` - to the first prompt of each new agy conversation) or `off` (agy-native behavior) | `on` |
|
|
110
110
|
|
|
111
111
|
Env overrides: `AGY_BRIDGE_TOOLS`, `AGY_DIGEST`, `AGY_SYSTEM_PROMPT`. Env wins over the file, so while `AGY_DIGEST` or `AGY_SYSTEM_PROMPT` is set, the matching `/agy digest` or `/agy system-prompt` toggle persists a value that never takes effect.
|
|
112
112
|
|
|
113
|
+
The `activate_skill` catalog mirrors pi's directory-based skill discovery: the two global dirs plus project dirs, the latter only when pi has trusted the project (same gate pi itself applies). Pi's other skill sources - the `skills` settings array, `package.json` entries, and `--skill` CLI paths - are not mirrored and won't appear in the catalog.
|
|
114
|
+
|
|
113
115
|
### The /agy command
|
|
114
116
|
|
|
115
117
|
`/agy` configures the provider at runtime. Settings persist to `~/.pi/agent/antigravity-bridge/config.json` and take effect on the next turn.
|
|
116
118
|
|
|
117
119
|
```
|
|
118
|
-
/agy status, or open the
|
|
119
|
-
/agy status print current
|
|
120
|
+
/agy status, or open the full settings picker (TUI)
|
|
121
|
+
/agy status print current settings + session counts
|
|
120
122
|
/agy doctor bridge state, driver counters, bridge port, last lifecycle events
|
|
121
123
|
/agy mode plan review-only: agy plans but writes nothing
|
|
122
124
|
/agy mode accept-edits agy applies edits directly (default)
|
|
@@ -125,8 +127,10 @@ Env overrides: `AGY_BRIDGE_TOOLS`, `AGY_DIGEST`, `AGY_SYSTEM_PROMPT`. Env wins o
|
|
|
125
127
|
/agy thinking low|medium|high default thinking tier for the AskAntigravity tool
|
|
126
128
|
/agy digest on|off inject pi-side context into agy prompts (default off; see table above)
|
|
127
129
|
/agy system-prompt on|off send pi's system prompt + AGENTS.md to new agy conversations (default on)
|
|
128
|
-
/agy
|
|
129
|
-
/agy acp-
|
|
130
|
+
/agy bridge all|mcp|none which pi tools the MCP bridge exposes to agy (default all; none = bridge off)
|
|
131
|
+
/agy acp-bin <path|auto> point the ACP engine at a specific server binary (auto = setup installs, or AGY_ACP_BIN; applies on the next ACP turn)
|
|
132
|
+
/agy engine acp|stream-json switch the turn engine (restart to apply; default stream-json; acp runs self-service setup: binary install + auth bootstrap)
|
|
133
|
+
/agy acp-auth manual ACP credential setup (fallback; auto-setup normally covers this; default login = your Antigravity subscription, same account as the agy CLI)
|
|
130
134
|
/agy patch-cleanup restore the original pi files if an older version patched them
|
|
131
135
|
/agy clear drop all session bindings (force fresh conversations)
|
|
132
136
|
```
|
|
@@ -149,7 +153,7 @@ For isolation when running any agent that executes commands without a confirmati
|
|
|
149
153
|
| --- | --- |
|
|
150
154
|
| `AGY_BIN` | Path to the agy binary. Defaults to `agy` on PATH. |
|
|
151
155
|
| `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`. |
|
|
156
|
+
| `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. |
|
|
153
157
|
| `AGY_EXTRA_ARGS` | Extra args appended to every invocation. Whitespace-split. |
|
|
154
158
|
| `AGY_CONVERSATIONS_DIR` | Override the conversations DB directory. |
|
|
155
159
|
| `AGY_MODE` | Override execution mode: `plan` (review-only) or `accept-edits` (default). Wins over the config file. |
|
|
@@ -6,7 +6,7 @@ PASS through the full stack. Gate F VERIFIED live (`scripts/smoke-acp-bridge.mjs
|
|
|
6
6
|
the real server lists bridge tools and completes a tool call through the
|
|
7
7
|
registered mcpServers entry. §6 parity run LIVE on both engines: 14/14
|
|
8
8
|
(`scripts/parity-live.mjs`). Phase-1 acceptance: ALL `[x]` (docs included).
|
|
9
|
-
Gates: A PASS, B ABSENT (managed —
|
|
9
|
+
Gates: A PASS, B ABSENT (managed — streaming engine retained
|
|
10
10
|
until upstream ships usage), C PASS, D FAIL on RC01 (kill+reload fallback
|
|
11
11
|
VERIFIED live, incl. the stale-exit race fix), E PASS, F PASS (verified
|
|
12
12
|
live 2026-09-03). Verdicts in section 8.1; full captured protocol data in
|
|
@@ -20,7 +20,7 @@ Peer review 2: Antigravity (agy), 2026-09-03. Verdict PROCEED WITH CHANGES.
|
|
|
20
20
|
7 findings integrated: Gate A made a blocking gate for the default flip (the
|
|
21
21
|
ACP binary takes no model flags, so the recycle fallback could not carry a
|
|
22
22
|
model), sessions re-keyed per engine (`@acp` suffix) after the engine-field
|
|
23
|
-
design was shown to erase
|
|
23
|
+
design was shown to erase streaming bindings on rollback, parked-timer pause
|
|
24
24
|
changed to remaining-budget semantics, acp-permission plumbing specified
|
|
25
25
|
through a TurnDriver interface, session/cancel + session/close pulled into
|
|
26
26
|
phase 1, AskAntigravity migration moved from phase 3 to phase 4.
|
|
@@ -47,7 +47,7 @@ Adopt the official Google ACP server (`agy_acp_server.par`, registry id
|
|
|
47
47
|
switch. The existing stream-json engine stays the default until the ACP
|
|
48
48
|
engine proves parity. Every change is an improvement or a one-to-one
|
|
49
49
|
replacement. No functionality is removed until a later phase deletes the
|
|
50
|
-
|
|
50
|
+
streaming engine on purpose.
|
|
51
51
|
|
|
52
52
|
Cross-references: [ARCHITECTURE.md](./ARCHITECTURE.md),
|
|
53
53
|
[PI-BRIDGE-GAPS.md](./PI-BRIDGE-GAPS.md), [DEVELOPMENT.md](./DEVELOPMENT.md).
|
|
@@ -165,8 +165,8 @@ is an unmaintained contract. ACP is the maintained one.
|
|
|
165
165
|
| Module | Role today | Disposition under ACP |
|
|
166
166
|
| --- | --- | --- |
|
|
167
167
|
| `src/provider.ts` | streamSimple: pi Context to agy turn to pi events; G9 round-trips; G1 digest; G10 system prompt | KEEP unchanged (additive thought-delta `if` only). Engine-agnostic by contract |
|
|
168
|
-
| `src/driver.ts` | persistent stream-json process, turn queue, recycle, timers | KEEP as
|
|
169
|
-
| `src/stream-events.ts` | NDJSON parser + usage mapping | KEEP as
|
|
168
|
+
| `src/driver.ts` | persistent stream-json process, turn queue, recycle, timers | KEEP as streaming engine. DELETE in phase 4 |
|
|
169
|
+
| `src/stream-events.ts` | NDJSON parser + usage mapping | KEEP as streaming. DELETE in phase 4 |
|
|
170
170
|
| `src/sessions.ts` | pi session to agy conversation store | KEEP. Add `engine` tag (section 9.4) |
|
|
171
171
|
| `src/config.ts` | runtime config | KEEP. Add engine + acp block (section 9.5) |
|
|
172
172
|
| `src/models.ts` | `agy models` to pi Model projection | KEEP. Catalog source stays the CLI until ACP exposes one (probe A.6) |
|
|
@@ -256,10 +256,10 @@ Every box must be `[x]` on the ACP engine before phase 4 flips the default.
|
|
|
256
256
|
Tested with the parity suite (section 11) and `scripts/parity-live.mjs`
|
|
257
257
|
(live, both engines: 14/14, 2026-09-03).
|
|
258
258
|
|
|
259
|
-
- [x] Text streams token-adjacent to
|
|
259
|
+
- [x] Text streams token-adjacent to streaming (no full-text re-sends) — live
|
|
260
260
|
both engines, delta stream + cumulative-resend guard held
|
|
261
261
|
- [x] Multi-turn conversation continuity via `session/load` or our store —
|
|
262
|
-
live: ACP `session/load` (history suppressed, clean reply),
|
|
262
|
+
live: ACP `session/load` (history suppressed, clean reply), streaming
|
|
263
263
|
`--conversation` resume; the provider's session store supplies the id
|
|
264
264
|
- [x] Turn serialization: two concurrent streamSimple calls never interleave
|
|
265
265
|
— live both engines (queue releases only on settle) + driver tests
|
|
@@ -276,23 +276,23 @@ Tested with the parity suite (section 11) and `scripts/parity-live.mjs`
|
|
|
276
276
|
- [x] Abort: pi user abort produces `aborted`, the server process survives,
|
|
277
277
|
the next turn on the session works — live both engines (aborted=true,
|
|
278
278
|
recovery turn OK). "Process survives" holds on NEITHER engine and is
|
|
279
|
-
the documented Gate D behavior:
|
|
279
|
+
the documented Gate D behavior: streaming kills the child; RC01 has no
|
|
280
280
|
cancel, ACP tears down after the -32601 probe and reloads next turn
|
|
281
281
|
- [x] pi session restart resumes the right conversation (engine-tagged) —
|
|
282
282
|
engine-scoped key tests + live `session/load`
|
|
283
283
|
- [x] Engine rollback preserves the other engine's conversation bindings
|
|
284
284
|
(engine-scoped keys, 9.4) — sessions tests (per-entry engine field
|
|
285
|
-
rejected precisely because set() would erase the
|
|
285
|
+
rejected precisely because set() would erase the streaming binding)
|
|
286
286
|
- [x] Model catalog: same `antigravity/*` model ids and effort tiers resolve
|
|
287
287
|
— shared provider catalog, engine-independent by construction
|
|
288
288
|
- [x] Model/effort switch takes effect (gate A mechanism) — live: ACP
|
|
289
|
-
`set_config_option` on a LOADED session;
|
|
289
|
+
`set_config_option` on a LOADED session; streaming recycle+resume
|
|
290
290
|
- [x] G1 digest and G10 system prompt reach the prompt identically — shared
|
|
291
291
|
prompt assembly in the provider; the driver receives the final prompt
|
|
292
292
|
- [x] Skills `activate_skill` answered by the bridge as today — bridge
|
|
293
293
|
server dep, same server serves both engines (ACP transport live)
|
|
294
294
|
- [x] Usage counters: present (mapped) or documented-absent (zero-usage),
|
|
295
|
-
per gate B — live:
|
|
295
|
+
per gate B — live: streaming mapped, ACP absent (Gate B row in the
|
|
296
296
|
parity matrix)
|
|
297
297
|
- [x] `/agy doctor` shows connection state, session id, prompt/session stats,
|
|
298
298
|
lifecycle log — implemented engine-aware (phase 1); re-verify in pi
|
|
@@ -303,7 +303,7 @@ Tested with the parity suite (section 11) and `scripts/parity-live.mjs`
|
|
|
303
303
|
as a visible `ACP session failed: Invalid params` turn error in the
|
|
304
304
|
first parity attempt, exactly as designed
|
|
305
305
|
- [x] `ask-tool` one-shot returns text, duration, abort/timeout states, and a
|
|
306
|
-
resumable session id — unchanged
|
|
306
|
+
resumable session id — unchanged `agy -p` path (phase-2 probe
|
|
307
307
|
decides whether it moves to ACP)
|
|
308
308
|
- [x] Overall-turn timer pauses while any round-trip is parked; a slow human
|
|
309
309
|
permission decision cannot kill the turn — fake tests (park/kickIdle
|
|
@@ -396,8 +396,8 @@ What to record for each gate:
|
|
|
396
396
|
| A | Model + effort switch per session? | `set_config_option` (or equivalent) switches both; next prompt uses them | NONE viable: the ACP binary takes no model flags, so respawn-per-switch cannot carry a model; a settings.json rewrite per switch is the only theoretical path and is rejected (unproven, racy). Gate A FAIL blocks the phase 4 default flip; ACP stays opt-in; the gap goes upstream |
|
|
397
397
|
| B | Usage anywhere? | Any update or `_meta` carries token counts | Zero-usage documented; README notes it |
|
|
398
398
|
| C | `tool_call` content richness | rawInput/output/locations enough to retire WrapperReplay + native-tools | Keep current replay machinery unchanged |
|
|
399
|
-
| D | Cancel latency + state | `stopReason: cancelled` within ~2s; session reusable after | Keep kill semantics on
|
|
400
|
-
| E | Startup cost | Cold start < 5s, steady RSS sane for a long-lived process | Spawn per turn-group only (like
|
|
399
|
+
| D | Cancel latency + state | `stopReason: cancelled` within ~2s; session reusable after | Keep kill semantics on streaming; on ACP keep kill as escalation path |
|
|
400
|
+
| E | Startup cost | Cold start < 5s, steady RSS sane for a long-lived process | Spawn per turn-group only (like the streaming recycle cadence) |
|
|
401
401
|
| F | MCP `mcpServers` registration | Bridge `tools/list` visible to the agent mid-turn | Keep bridge wired some other protocol-sanctioned way; if none, G9 parking breaks and phase 1 is BLOCKED |
|
|
402
402
|
| F.7 | Slash behavior | Commands not auto-expanded against our prompt text | Prefix-safe prompt assembly unchanged |
|
|
403
403
|
|
|
@@ -478,7 +478,7 @@ scripts/smoke-acp.mjs live smoke, gated by AGY_ACP_LIVE=1 (spends quota),
|
|
|
478
478
|
`AcpDriver` matches the existing `AgyDriver` public surface: `state`,
|
|
479
479
|
`activeHandle`, `run()`, `reentry()`, `kickIdle()`, `set onTurnEnd()`,
|
|
480
480
|
`snapshot()`, `close()`. `DriverActivity` gains one additive variant; the
|
|
481
|
-
|
|
481
|
+
streaming engine never emits it:
|
|
482
482
|
|
|
483
483
|
```ts
|
|
484
484
|
// stream-events/driver today: { type: "thought"; tokens: number }
|
|
@@ -487,7 +487,7 @@ legacy engine never emits it:
|
|
|
487
487
|
```
|
|
488
488
|
|
|
489
489
|
`provider.ts` change: when `delta` is present call `appendThinking`, else keep
|
|
490
|
-
the current token-count behavior. One `if`, additive,
|
|
490
|
+
the current token-count behavior. One `if`, additive, streaming untouched.
|
|
491
491
|
|
|
492
492
|
Interface extraction (review 2, finding 7): `provider.ts` imports the
|
|
493
493
|
concrete `AgyDriver` class today; deleting `driver.ts` in phase 4 would break
|
|
@@ -504,7 +504,7 @@ correlation-map entry (the pending `session/prompt` request, any unanswered
|
|
|
504
504
|
client-side requests), the driver settles the turn outcome as
|
|
505
505
|
`ERROR`/`aborted` (never left pending), and `onTurnEnd` fires so the
|
|
506
506
|
provider's `roundTrips.failAll()` fails parked round-trips exactly as the
|
|
507
|
-
|
|
507
|
+
streaming driver's `failTurn` path does. Nothing is ever written to a dead
|
|
508
508
|
socket; no promise survives the kill. Mirrors `ToolRoundTrips.failAll()`.
|
|
509
509
|
|
|
510
510
|
Event mapping (`src/acp/events.ts`):
|
|
@@ -524,7 +524,7 @@ Event mapping (`src/acp/events.ts`):
|
|
|
524
524
|
| `refusal` / `max_turn_requests` / `max_tokens` | TurnOutcome ERROR / OK+note | `error` / `stop` + `errorMessage` |
|
|
525
525
|
| `user_message_chunk` (during `session/load` only) | suppressed (history replay) | never emitted to pi as live text |
|
|
526
526
|
|
|
527
|
-
Defensive guard ported from the
|
|
527
|
+
Defensive guard ported from the streaming engine: if an `agent_message_chunk`
|
|
528
528
|
repeats the full accumulated text instead of a delta, detect and slice (the
|
|
529
529
|
`isCumulativeResend` lesson; same agy binary lineage, same quirk class).
|
|
530
530
|
Guard plus test ship in phase 1. Honest labeling: the ACP spec defines chunks
|
|
@@ -575,24 +575,24 @@ parked and, on settle, re-arms it with the REMAINING budget (`deadline -
|
|
|
575
575
|
now`), never a fresh cap: the overall timer is a turn DEADLINE, not an
|
|
576
576
|
inactivity guard. Every park carries its own timeout (`BRIDGE_TIMEOUT_MS`),
|
|
577
577
|
so a paused deadline cannot hang forever. Driver-local (AcpDriver only);
|
|
578
|
-
|
|
578
|
+
streaming behavior untouched; ships in phase 1.
|
|
579
579
|
|
|
580
580
|
### 9.4 Sessions schema (engine-scoped keys)
|
|
581
581
|
|
|
582
582
|
The first design (a per-entry `engine` field) was rejected in review 2:
|
|
583
583
|
`set()` overwrites the single `sid:<pi-session>` key, so one ACP turn ERASES
|
|
584
|
-
the
|
|
584
|
+
the streaming conversation binding, and a rollback loses continuity, breaking
|
|
585
585
|
the section 13 guarantee. Engines scope at the KEY level instead:
|
|
586
586
|
|
|
587
587
|
```jsonc
|
|
588
588
|
// ~/.pi/agent/antigravity-bridge/sessions.json
|
|
589
589
|
{
|
|
590
|
-
"sid:<pi-session>": { "conversationId": "<
|
|
590
|
+
"sid:<pi-session>": { "conversationId": "<streaming id>", "lastStepIdx": -1, "lastMessageCount": 42 },
|
|
591
591
|
"sid:<pi-session>@acp": { "conversationId": "<ACP sessionId>", "lastStepIdx": -1, "lastMessageCount": 42 }
|
|
592
592
|
}
|
|
593
593
|
```
|
|
594
594
|
|
|
595
|
-
- Un-suffixed keys belong to the
|
|
595
|
+
- Un-suffixed keys belong to the streaming engine, byte-compatible with every
|
|
596
596
|
persisted store; ACP keys carry an `@acp` suffix appended by
|
|
597
597
|
`sessionKey()` when `config.engine === "acp"`.
|
|
598
598
|
- Engines never touch each other's keys: rollback keeps both continuations,
|
|
@@ -747,11 +747,11 @@ ACP-PROTOCOL-REFERENCE.md "Phase-2 probe findings".
|
|
|
747
747
|
|
|
748
748
|
### Phase 3: consolidation (immediate priority, opt-in only)
|
|
749
749
|
|
|
750
|
-
Hard rule: Keep both engines in the extension. Default engine remains `stream-json`. All items below are non-breaking opt-in enhancements for the ACP engine that do NOT alter default behavior or touch
|
|
750
|
+
Hard rule: Keep both engines in the extension. Default engine remains `stream-json`. All items below are non-breaking opt-in enhancements for the ACP engine that do NOT alter default behavior or touch streaming paths.
|
|
751
751
|
|
|
752
752
|
Queue:
|
|
753
|
-
1. [x] Gate C evaluation: `native-tools.ts` + `WrapperReplay` retired on the ACP engine (retained for
|
|
754
|
-
2. [x] Retire `diff-render.ts` (git path) on the ACP engine — DONE 2026-09-04. The phase-2 probe proved ACP surfaces edit diffs natively (`tool_call` `content[]` `{type:"diff", path, oldText?, newText}`), which is richer AND cheaper than the git-sourced path: implemented as (a) `events.ts` extracts the first diff entry into the `tool_done` activity (`AcpEditDiff`); (b) `provider.ts` renders it on ACP turns via the new `formatInlineDiff` (in-memory `generateDiffString`, same line-numbered format, ZERO git subprocesses) instead of `TurnDiffContext.diffEdit`; (c) `diff-render.ts` git machinery remains solely for the `stream-json` engine. Tests: diff extraction (with/without `oldText`), ACP thinking-stream rendering (`+2 B` line-numbered), label-only fallback, no parking,
|
|
753
|
+
1. [x] Gate C evaluation: `native-tools.ts` + `WrapperReplay` retired on the ACP engine (retained for the streaming (`stream-json`) engine). ACP turns emit thinking labels for tool executions without parking turns for synthetic re-execution or wrapper cards; bridge MCP tools (`bridge_call`) continue parking natively. Verified: live parity 14/14 held.
|
|
754
|
+
2. [x] Retire `diff-render.ts` (git path) on the ACP engine — DONE 2026-09-04. The phase-2 probe proved ACP surfaces edit diffs natively (`tool_call` `content[]` `{type:"diff", path, oldText?, newText}`), which is richer AND cheaper than the git-sourced path: implemented as (a) `events.ts` extracts the first diff entry into the `tool_done` activity (`AcpEditDiff`); (b) `provider.ts` renders it on ACP turns via the new `formatInlineDiff` (in-memory `generateDiffString`, same line-numbered format, ZERO git subprocesses) instead of `TurnDiffContext.diffEdit`; (c) `diff-render.ts` git machinery remains solely for the `stream-json` engine. Tests: diff extraction (with/without `oldText`), ACP thinking-stream rendering (`+2 B` line-numbered), label-only fallback, no parking, streaming path unchanged. Verified: 165/165 vitest, tsc clean, live parity 14/14.
|
|
755
755
|
3. [x] `/agy doctor` diagnostics expansion — DONE 2026-09-04. The ACP
|
|
756
756
|
snapshot now carries `reconnects` (connections beyond the first =
|
|
757
757
|
Gate D kills + stale-exit replacements) and the handshake `agentInfo`
|
|
@@ -773,17 +773,17 @@ Status: 🚧 Phase 3 remaining items are COMPLETE (2026-09-04): 168/168 tests,
|
|
|
773
773
|
tsc clean, live parity 14/14, embeddedContext verified live (resource block
|
|
774
774
|
with a secret word answered correctly). Remaining phase-3 acceptance:
|
|
775
775
|
deleted-code census lands with phase 4's deletions (nothing deletes in
|
|
776
|
-
phase 3 — the
|
|
776
|
+
phase 3 — the streaming modules stay for the `stream-json` engine).
|
|
777
777
|
|
|
778
|
-
### Phase 4: default flip and
|
|
778
|
+
### Phase 4: default flip and streaming deletion (deferred, next month)
|
|
779
779
|
|
|
780
780
|
All items below are deferred until a full soak cycle of both engines has completed and upstream conditions are met:
|
|
781
781
|
|
|
782
|
-
1. AskAntigravity migration to ACP one-shot (migrating while `stream-json` is default breaks
|
|
782
|
+
1. AskAntigravity migration to ACP one-shot (migrating while `stream-json` is default breaks streaming-only users who haven't onboarded ACP auth; streaming conversation ids cannot resume under ACP). `mode: "plan"` delegations keep the `agy -p --mode plan` path (committed exception).
|
|
783
783
|
2. Delete `src/discovery.ts` (`/proc` fd-scan) once AskAntigravity migration completes.
|
|
784
784
|
3. Default flip: `config.engine` default becomes `"acp"` after one full release soak cycle with both engines shipping. Gate A PASS is verified.
|
|
785
785
|
4. Upstream Gate B resolution: Google ships usage counters in ACP payloads.
|
|
786
|
-
5.
|
|
786
|
+
5. Streaming engine deletion: `src/driver.ts`, `src/stream-events.ts`, and streaming tests deleted one release after the flip AND only once Gate B has lifted (so zero-usage is never forced).
|
|
787
787
|
|
|
788
788
|
Acceptance: default-flip release ships with the parity suite as acceptance evidence; deletion release has zero references to the removed modules.
|
|
789
789
|
|
|
@@ -801,7 +801,7 @@ Acceptance: default-flip release ships with the parity suite as acceptance evide
|
|
|
801
801
|
- **Provider**: the existing `provider-streaming` / `provider-digest` /
|
|
802
802
|
`provider-sysprompt` suites run against both engines via the shared driver
|
|
803
803
|
contract. New case: thought delta path.
|
|
804
|
-
- **Sessions**: engine-tag matching,
|
|
804
|
+
- **Sessions**: engine-tag matching, streaming-file compatibility (no tag),
|
|
805
805
|
cross-engine miss starts fresh.
|
|
806
806
|
- **Config**: narrowing of stale/garbage `engine` values, env precedence.
|
|
807
807
|
- **Parity suite**: the section 6 checklist encoded as an integration run
|
|
@@ -836,8 +836,8 @@ Install layout:
|
|
|
836
836
|
## 13. Rollback
|
|
837
837
|
|
|
838
838
|
At any phase: `AGY_ENGINE=stream-json` (or `/agy engine stream-json`) returns
|
|
839
|
-
to the
|
|
840
|
-
engine resumes its own conversations untouched. The
|
|
839
|
+
to the streaming engine. Sessions are keyed per engine (9.4), so the streaming
|
|
840
|
+
engine resumes its own conversations untouched. The streaming engine is only deleted in
|
|
841
841
|
phase 4, one release after the flip, so rollback stays possible throughout.
|
|
842
842
|
|
|
843
843
|
## 14. Documentation updates
|
|
@@ -856,7 +856,7 @@ phase 4, one release after the flip, so rollback stays possible throughout.
|
|
|
856
856
|
| # | Risk | L | I | Response |
|
|
857
857
|
| --- | --- | --- | --- | --- |
|
|
858
858
|
| R1 | Gate A fails (no model switch) | M | H | default flip blocked; ACP stays opt-in; escalate upstream. No ship-anyway: model switching is not optional |
|
|
859
|
-
| R2 | Gate F fails (bridge not registrable) | L | H | BLOCKS phase 1; escalate upstream, keep
|
|
859
|
+
| R2 | Gate F fails (bridge not registrable) | L | H | BLOCKS phase 1; escalate upstream, keep streaming |
|
|
860
860
|
| R3 | Usage absent (CONFIRMED, Gate B) | H | M | zero-usage documented on ACP; stream-json retained as secondary engine; phase-4 deletion conditioned on Gate B lift (review 4) |
|
|
861
861
|
| R4 | Binary churn (hourly registry, RC builds) | M | M | pin by build id, record sha256 |
|
|
862
862
|
| R5 | Server rejects second simultaneous session | L | M | one session per connection (today's model), N connections instead |
|
|
@@ -247,7 +247,7 @@ unreachable on RC01 — no cancel method).
|
|
|
247
247
|
|
|
248
248
|
- Chunks are pure DELTAS. Verified by content: numbers split mid-token across
|
|
249
249
|
chunk boundaries (`"...\n39\n40\n4"` then `"1\n42\n43..."`), and no chunk
|
|
250
|
-
ever contained a full prefix of the accumulated text. The
|
|
250
|
+
ever contained a full prefix of the accumulated text. The stream-json
|
|
251
251
|
cumulative-resend failure mode was NOT observed over ACP (defensive guard
|
|
252
252
|
stays cheap insurance).
|
|
253
253
|
- Throughput: 300 numbers (~600 tokens) completed within one 25 s poll;
|