@firespoon/pi-antigravity-bridge 0.0.0-stage → 1.10.7
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 +902 -0
- package/LICENSE +21 -0
- package/README.md +235 -3
- package/extensions/index.ts +1993 -0
- package/package.json +71 -6
- package/src/acp/connection.ts +623 -0
- package/src/acp/driver.ts +953 -0
- package/src/acp/events.ts +331 -0
- package/src/acp/home.ts +238 -0
- package/src/acp/jsonrpc.ts +232 -0
- package/src/acp/setup.ts +107 -0
- package/src/acp/usage-estimate.ts +61 -0
- package/src/agents.ts +64 -0
- package/src/agy-install.ts +85 -0
- package/src/agy-paths.ts +30 -0
- package/src/agy-setup.ts +72 -0
- package/src/agy-version.ts +283 -0
- package/src/approval-detect.ts +146 -0
- package/src/approval-gate.ts +208 -0
- package/src/approval-hook.ts +270 -0
- package/src/artifacts-ui.ts +88 -0
- package/src/artifacts.ts +144 -0
- package/src/ask-tool.ts +1222 -0
- package/src/background-watch.ts +225 -0
- package/src/bridge-catalog.ts +27 -0
- package/src/config.ts +485 -0
- package/src/daily-log.ts +196 -0
- package/src/dialog-lock.ts +48 -0
- package/src/diff-render.ts +205 -0
- package/src/driver-types.ts +172 -0
- package/src/driver.ts +907 -0
- package/src/engine-picker.ts +160 -0
- package/src/frame-guard.ts +38 -0
- package/src/mcp-registration.ts +382 -0
- package/src/mcp-server.ts +620 -0
- package/src/models.ts +407 -0
- package/src/native-tools.ts +104 -0
- package/src/parked-turn.ts +125 -0
- package/src/patch-cleanup.ts +519 -0
- package/src/poll-fold.ts +55 -0
- package/src/prompt-images.ts +92 -0
- package/src/provider.ts +2066 -0
- package/src/queued-messages.ts +152 -0
- package/src/redact.ts +27 -0
- package/src/sessions.ts +185 -0
- package/src/skills.ts +192 -0
- package/src/stream-events.ts +122 -0
- package/src/stream-sanitizer.ts +180 -0
- package/src/subagent-roster.ts +245 -0
- package/src/sysprompt-agent.ts +163 -0
- package/src/tasks-ui.ts +90 -0
- package/src/tasks.ts +174 -0
- package/src/usage.ts +174 -0
- package/src/web-tools.ts +320 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 EstebanForge
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,235 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# pi-antigravity-bridge
|
|
2
|
+
|
|
3
|
+
A Gemini model provider **and** the `AskAntigravity` delegation tool for [pi](https://github.com/earendil-works/pi), built on the official `agy` CLI: **`agy acp`** by default, with the stream-json CLI engine kept as the fallback. 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
|
+
|
|
5
|
+
> **Fork notice:** Maintained at [FireSpoonYZ/pi-extensions](https://github.com/FireSpoonYZ/pi-extensions) and published as `@firespoon/pi-antigravity-bridge`, forked from upstream [EstebanForge/pi-extensions](https://github.com/EstebanForge/pi-extensions/tree/main/packages/pi-antigravity-bridge) (`@estebanforge/pi-antigravity-bridge`).
|
|
6
|
+
|
|
7
|
+
If you also have [`@estebanforge/pi-ask-antigravity`](https://github.com/EstebanForge/pi-extensions/tree/main/packages/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
|
+
|
|
9
|
+
## What it does
|
|
10
|
+
|
|
11
|
+
You pick a Gemini model in pi's `/model` picker. pi routes each turn through this provider. A single persistent `agy` process runs in your workspace; pi feeds it each turn, parses its stream-json events, and streams the agent text back into pi token by token. Token usage is live.
|
|
12
|
+
|
|
13
|
+
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
|
+
|
|
15
|
+
### Two engines
|
|
16
|
+
|
|
17
|
+
Turns run through one of two engines behind the same provider surface (`config.engine`, default `acp`):
|
|
18
|
+
|
|
19
|
+
- **acp** (default): the ACP server built into the `agy` CLI (`agy acp`), JSON-RPC 2.0 over stdio. Verified live on agy 1.5.3: text streaming, exact token usage, multi-turn resume via `session/load`, bridge tools, separate model/thinking options, and notification-based cancellation. Client-side usage estimates remain as a fallback if the server omits usage.
|
|
20
|
+
- **stream-json** (fallback): the persistent `agy` CLI process. Live token usage; conversation resume via `--conversation`.
|
|
21
|
+
|
|
22
|
+
The choice of engine is left to the user: a first-run picker asks once on a fresh install (acp preselected; `esc` defers), and `/agy engine` reopens it anytime. Both engines use the same `agy` installation and cached Google credentials. A restart applies an engine switch. Sessions are engine-scoped, so switching engines never crosses conversations.
|
|
23
|
+
|
|
24
|
+
Full capability comparison, switching, and setup/auth details: [docs/ENGINES.md](docs/ENGINES.md). Existing installs remove only old ACP builds with managed-install evidence under the bridge's old install root. Unmarked binaries and unrelated files stay untouched. Retired standalone credentials are reported for manual removal, never deleted automatically.
|
|
25
|
+
|
|
26
|
+
## What it cannot do
|
|
27
|
+
|
|
28
|
+
On the default **acp** engine, the provider spawns `agy acp` with a generated restricted custom agent (`--agent generated`, `--include-default-customizations=false`, `excludeDefaultComponents: true`, `tools: []`, `inheritMcp: true`, `inheritCustomizations: false`, and empty `skills`/`rules`/`agents`/`hooks`/`plugins`). The private agent frontmatter declares an explicit list-of-objects entry for the current session's `pi-bridge` MCP server (no foreign global MCP entries; `session/new`/`session/load` `mcpServers` remains in place and global config stays untouched), and the agent body carries a concise live MCP tool catalog with JSON Schemas and the `call_mcp_tool` calling convention. Tool execution routes through Pi's MCP tool bridge (`call_mcp_tool` -> `toolUse -> Pi executes -> toolResult completes MCP`), so Pi's own tool loop, renderers, and inline diff/hook/permission flow handle them. Because ACP uses a new versioned session key, older ACP conversations are preserved and not reused automatically; start a **new Pi conversation** to use the new restricted profile.
|
|
29
|
+
|
|
30
|
+
**Known limit (retained runtime tools):** Official component exclusion (`excludeDefaultComponents: true`, `tools: []`) removes agy's workspace native file and shell tools, but does not turn agy into a bare model: foundational MCP, resource, and task infrastructure (`call_mcp_tool`, `list_resources`, `read_resource`, `manage_task`) remains available in the runtime, and `call_mcp_tool` is the required MCP dispatcher. File, shell, and user-facing tools are provided by Pi through the bridge, and the agent body instructs the model to use the Pi bridge rather than claiming complete removal of all agy runtime tools.
|
|
31
|
+
|
|
32
|
+
On the **stream-json** fallback engine, agy still runs its own closed native tool loop (`read_file`, `write_file`, `edit_file`, `run_command`) against `--add-dir`: 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, while mutating steps replay through a display-only `antigravity` wrapper tool. See [MCP tool bridge](#mcp-tool-bridge-agy-uses-pis-tools) below.
|
|
33
|
+
|
|
34
|
+
Residual limits:
|
|
35
|
+
|
|
36
|
+
- On **acp** with `bridgeTools: "none"` (or `"mcp"` without adapter tools), no Pi workspace file/shell/extension tools are bridged (leaving only agy's retained foundational runtime tools under `none`, or `pi-mcp-adapter` tools + skills under `mcp`).
|
|
37
|
+
- On **stream-json** (where agy's native workspace tools remain active), agy's own edits land directly on disk without pi's inline diff review, and agy commands run without per-action approval by default unless the [Approval gate](docs/APPROVAL-GATE.md) is enabled (`auto` turns it on only when a pi permission extension is installed). See also [Permissions](#permissions) below.
|
|
38
|
+
- No cost accounting: cost stays zero because agy runs on your subscription quota. Token usage is live.
|
|
39
|
+
|
|
40
|
+
## MCP tool bridge (agy uses pi's tools)
|
|
41
|
+
|
|
42
|
+
While agy is the active model it normally cannot see pi's universe of extensions: agentmemory, codegraph, web search, slack/asana, the `Ask*` delegations, and any other installed pi tool. This extension optionally bridges that gap.
|
|
43
|
+
|
|
44
|
+
The bridge starts a localhost MCP server inside pi's process. The exposed catalog is computed live from pi's active tools on every `tools/list` and re-checked immediately before every `tools/call`: the `bridgeTools` mode, the session's `/agy tools` hidden set, and the bridge's own internal tools (`AskAntigravity`, the display-only `antigravity` wrapper, `activate_skill`, `bridge_poll_result`, the `agy_web_search`/`agy_read_url` wrappers) are filtered each time, and a call for anything outside the fresh set is rejected - a cached MCP catalog is not authorization. A call that passes routes into pi's own tool loop via the round-trip described below. Discovery has two layers. The provider's agy gets a per-invocation config: the bridge writes `.agents/mcp_config.json` into a bridge-controlled dir (`~/.pi/agent/antigravity-bridge/agy-mcp-<pid>/`) and the driver passes that dir as an extra `--add-dir` when it spawns agy. A per-pid entry (`pi-bridge-<pid>`) is also registered in the user's global agy config (`~/.gemini/config/mcp_config.json`; foreign servers preserved, stale entries swept at start), so agy builds that read only the global config still find the bridge.
|
|
45
|
+
|
|
46
|
+
**Upstream pi APIs only.** Bridge calls park in the provider's round-trip store; the provider ends the pi assistant message with a `toolUse` stop reason for the real pi tool, pi executes it in its own loop (native cards, permissions, hooks), and the toolResult completes the parked MCP response on the next stream call.
|
|
47
|
+
|
|
48
|
+
**Long calls don't die.** agy's MCP client abandons a `tools/call` request at a flat ~180s, which used to kill any pi tool that ran longer (a long peer review, a build, a commit preview waiting for you). A call still running after ~20 seconds now settles its HTTP request with a `STILL RUNNING` answer carrying a `callId` while pi keeps executing; agy fetches the result through the bridge-local `bridge_poll_result` tool and polls until it lands. Delegation-shaped tools (pi subagent/delegation tools, e.g. `subagent_run`, `agent_spawn`) hold the synchronous window 120s instead (issue #6: orchestrators expect a plain result across the 30-120s subagent range, and 120s stays under the 180s wall); `escalateLongTools` in config.json adds custom names. Escalated calls get their own 30-minute budget, so human-gated tools can take as long as the human takes. Fast calls stay fully synchronous and never see any of this. If a park does fail (abort, timeout, recycle), the late result is re-routed to agy as a follow-up prompt in the same conversation instead of being lost. If pi retries a failed turn and drops the attempt from the projected context (pi core `_omitRecoveryAttempt`), leaving a toolResult or assistant tail with no live turn, the provider re-opens the bound conversation with a synthetic resume prompt instead of the unretryable "No user message" hard error (issue #8); a first-ever turn that parks binds its conversation at park time, so a retry-dropped tail has a conversation to resume into unless the park produced no conversation id or the later failure proved the conversation dead. Consecutive polls render as ONE ♊︎-marked counted line (`♊︎ bridge_poll_result Poll git_commit (x30)`) instead of one entry per poll, with a live muted status counter while a run is open.
|
|
49
|
+
|
|
50
|
+
**Session isolation.** Both engines isolate agy from other pi sessions' bridges (issue #14): ACP injects **only** the current Pi bridge (via `session/new`/`session/load` `mcpServers` and the explicit list-of-objects MCP spec in the private generated agent frontmatter) with no foreign globally inherited MCP (`inheritCustomizations: false`, `inheritMcp: true`, global MCP config untouched), while stream-json stages a private MCP home via the top-level `--gemini_dir` flag (filtering out every global `pi-bridge` and `pi-bridge-<pid>` entry while sharing CLI credentials, settings, and conversation state; a quota-free capability probe verifies the flag per agy version). If stream-json refuses the flag or the home cannot be staged, stream-json falls back to the legacy global per-pid registration plus the delegation suppression machinery, with a one-time warning.
|
|
51
|
+
|
|
52
|
+
**Recursion safety.** Only the provider's agy receives the extra `--add-dir`. `AskAntigravity` is also filtered from the exposed tool list. Its delegated `agy -p` spawns with just the workspace, and for the whole delegated run the bridge hides its global per-pid entries: disabled before the spawn, released only on process close or error - agy watches the config and hot-reloads MCP servers on file changes, so a mid-run re-enable would poke the live delegation back into pi. A cross-process marker (`suppression.json` in the bridge's extensions-data dir) coordinates concurrent delegations: entries come back only when no live delegation remains, a session starting mid-delegation registers its own entry disabled, and the session-start heal re-enables only once the last delegator is gone (dead entries pruned by pid liveness with a 24h age bound). The inner agy therefore sees no bridge and cannot re-enter pi. Foreign servers in the global config are never touched.
|
|
53
|
+
|
|
54
|
+
**Cost / fan-out.** Every active pi tool — including active pi builtins (`read`, `write`, `edit`, `bash`, etc.) — except the bridge's own internal tools is exposed (respecting the `bridgeTools` mode and any `/agy tools` hides), including other delegation tools like `AskClaude`/`AskCodex`. agy can therefore chain into other models via the bridge, which is a new cost/time fan-out vector that did not exist before this feature.
|
|
55
|
+
|
|
56
|
+
**Security.** The MCP server binds to `127.0.0.1` only and requires a per-session shared-secret header (`x-bridge-token`) that agy sends from the bridge config; browsers cannot set custom headers on a simple cross-origin POST, so this blocks web CSRF against the loopback server. Request bodies are size-capped. This is intended for single-user developer machines: any local process running as the same user can read the token from the per-pid config and call the exposed tools, so do not run it on a shared host where you do not trust other same-user processes.
|
|
57
|
+
|
|
58
|
+
### Native cards, wrapper replay, and skills
|
|
59
|
+
|
|
60
|
+
Read-only agy steps (view_file, list_dir, grep_search, find_by_name) re-run as
|
|
61
|
+
real pi builtins (`read`, `ls`, `grep`, `find`) when those builtins are active,
|
|
62
|
+
so their cards render with pi's own renderers. Mutating and agy-specialty steps
|
|
63
|
+
render through a display-only `antigravity` wrapper tool: its `execute()`
|
|
64
|
+
replays the output agy already recorded, so the transcript gets proper
|
|
65
|
+
toolCall/toolResult pairs without any double execution. Neither path re-runs
|
|
66
|
+
anything with side effects.
|
|
67
|
+
|
|
68
|
+
When the bridge is on, agy also gets one `activate_skill` tool whose enum is
|
|
69
|
+
your pi Agent Skills catalog; calling it returns the SKILL.md body. The bridge
|
|
70
|
+
answers it directly, no pi round-trip. `/agy doctor` prints driver counters,
|
|
71
|
+
bridge port, and the last lifecycle events without spending tokens.
|
|
72
|
+
|
|
73
|
+
On the ACP engine, the default restricted provider agent removes agy's workspace file/shell tools (`tools: []`), so workspace tool calls route through Pi's MCP bridge round-trips (`call_mcp_tool` -> `toolUse -> Pi executes -> toolResult completes MCP`) and render as genuine Pi tool cards. Display-only rendering for native ACP tool steps (a status icon plus the file path with colored diff lines, command line, or captured output) remains in place as event compatibility. The stream-json engine keeps its native re-exec cards for read-only steps and `antigravity` wrapper replay for mutating steps.
|
|
74
|
+
|
|
75
|
+
## Approval gate (agy native tools)
|
|
76
|
+
|
|
77
|
+
agy runs its own agent loop with native tools (`run_command`, `create_file`, `edit_file`, ...), which pi's permission extensions never saw. The optional approval gate routes those calls through a pi-side approval: a staged PreToolUse hook parks the call, the provider surfaces it as a shadow `bash`/`write`/`edit` toolUse, and your permission extension (or the built-in ask/allow/deny fallback) decides before agy executes it. Off by default (`approvals.gateMode: auto` enables it only when a pi permission extension is detected); denials fail closed; read-only agy tools stay ungated. On ACP turns the server has its own per-tool permission ask: when one fires (`skipPermissions` off), the request parks on a real pi dialog instead of a silent deny, and allow-always choices are remembered per connection.
|
|
78
|
+
|
|
79
|
+
Full mechanics, configuration, and a sample gate extension: [docs/APPROVAL-GATE.md](docs/APPROVAL-GATE.md).
|
|
80
|
+
|
|
81
|
+
## Install
|
|
82
|
+
|
|
83
|
+
> The bridge runs on pi's public APIs; the extension never edits your pi install.
|
|
84
|
+
|
|
85
|
+
Install with pi's package manager:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pi install npm:@firespoon/pi-antigravity-bridge
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Requires the **`agy` CLI** installed and authenticated. On an interactive start without it, the extension offers once per process to run Google's official installer after your confirmation, without blocking bridge startup. Linux and macOS use `set -o pipefail; curl -fsSL https://antigravity.google/cli/install.sh | bash`; Windows PowerShell uses `irm https://antigravity.google/cli/install.ps1 | iex`. Installation is verified before the success message. Then run `agy` once to complete Google OAuth and restart pi. The extension resolves `agy` on `$PATH`, or via `AGY_BIN`; a bad explicit override gets correction instructions instead of an install. Headless sessions print the instructions without installing.
|
|
92
|
+
|
|
93
|
+
## Usage
|
|
94
|
+
|
|
95
|
+
Pick a model and talk to pi as usual:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
/model
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Look for the models namespaced as: antigravity
|
|
102
|
+
|
|
103
|
+
Or specify a model directly:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
/model antigravity/gemini-3-6-flash-medium
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Model ids are slugified from the `agy models` output (`Gemini 3.6 Flash (Medium)` becomes `gemini-3-6-flash-medium`). Discovery runs once at extension load. Run `/reload` after an `agy update` to refresh the list.
|
|
110
|
+
|
|
111
|
+
If `agy models` fails at load (binary missing, auth not done, network stall), a fallback catalog still populates the picker so you get a clear runtime error instead of an empty list.
|
|
112
|
+
|
|
113
|
+
### Bridge surface
|
|
114
|
+
|
|
115
|
+
`config.json` selects the bridge surface:
|
|
116
|
+
|
|
117
|
+
| Key | Values | Default |
|
|
118
|
+
| --- | --- | --- |
|
|
119
|
+
| `askTool` | `on` (register the AskAntigravity delegation tool), `off` (no delegation tool; provider and models only) | `on` |
|
|
120
|
+
| `webTools` | `off` (no web tools), `on` (register `agy_web_search` + `agy_read_url` as Pi tools, usable by ANY provider's model). Each call spawns a one-shot search-only `agy` agent (plan mode, bridge MCP inheritance off), gates the answer on an observed native `search_web`/`read_url_content` step, and spends Antigravity quota. Off by default: Antigravity `stream-json` sessions already have native web tools (and `agy_web_search`/`agy_read_url` remain excluded from the MCP bridge catalog); these serve other providers | `off` |
|
|
121
|
+
| `bridgeTools` | `none` (bridge off — on the restricted ACP agent, no Pi file/shell/extension tools are exposed, leaving only agy's retained foundational runtime tools; on `stream-json`, agy still uses its own native tools), `all` (every active pi tool, including active pi builtins such as `read`/`write`/`edit`/`bash`, extensions, `pi-mcp-adapter` tools, and other `Ask*` delegations, excluding the bridge's own internal tools), `mcp` (active `pi-mcp-adapter` tools + skills bridge only — no pi builtins or non-adapter extensions; on restricted ACP this limits Pi-bridged tools to adapter tools + skills) | `all` |
|
|
122
|
+
| `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` |
|
|
123
|
+
| `systemPrompt` | `on` (send pi's system prompt - operating instructions plus the global agent-dir `AGENTS.md` and ancestor `AGENTS.md`/`CLAUDE.md` - plus a Pi Bridge tool-priority note. Delivery: **acp** carries it in the generated restricted custom agent's body via `--agent generated` and `--include-default-customizations=false` (`excludeDefaultComponents: true`, `tools: []`, `inheritMcp: true`, `inheritCustomizations: false`, empty `skills`/`rules`/`agents`/`hooks`/`plugins`), with the current `pi-bridge` MCP spec in frontmatter and the live MCP tool catalog + JSON Schemas + `call_mcp_tool` calling convention in the body, not in the first ACP user message; **stream-json** stages it as an agy agent file via `--agent` off the ~25KB prompt line, declaring the productive native toolset explicitly per issue #13 plus `subagent: false` + `agents: []`, or honors `/agy agent`, which remains stream-json only) or `off` (on **acp**, omits Pi system prompt text only while still keeping the bridge protocol, live tool catalog, and restricted agent profile; on **stream-json**, uses agy-native behavior). ACP uses a new versioned session key so old conversations are preserved and not reused automatically — start a new Pi conversation to use the new profile | `on` |
|
|
124
|
+
| `turnTimeoutMin` | Overall cap on ONE agy turn, minutes, both engines. Parked time (pi-tool round-trips, escalated calls, human-gated approvals) does not count against it on either engine: the cap pauses with remaining-budget semantics and resumes on unpark. When it fires, the bridge kills the agy process mid-task ("ACP turn exceeded the 10m deadline" / "agy exceeded the 10m turn timeout") - it is a bridge cap, not a Google server limit. Default is TTY-aware: `0` (no cap) on an interactive pi - you are the backstop with Esc; `20` headless, where nobody can abort and one runaway turn blocks the serialized turn queue. Opt into a gate with 1-1440 (free type via `config.json` or `/agy timeout <1-1440|off>`, or the `/agy` picker's preset list); `0` disables explicitly; anything else falls back to the TTY-aware default. The 5m inactivity stall guard always still bounds a hung server | `0` TTY / `20` headless |
|
|
125
|
+
| `inactivityTimeoutMin` | Silence cap, minutes, both engines: no stream-json stdout / no ACP session/update for this long fails the turn as a stall. `0` disables the guard. Parks (bridge calls, escalated calls, ACP permission dialogs) pause it; agy-native long steps such as builds do not. A false kill costs the whole turn, and on stream-json a stall kill with no result frame clears the conversation binding. Keep `5`; use `2`-`3` only when native steps are known to be short; do not use `1` | `5` |
|
|
126
|
+
|
|
127
|
+
Env overrides: `AGY_BRIDGE_TOOLS`, `AGY_ASK_TOOL`, `AGY_WEB_TOOLS`, `AGY_DIGEST`, `AGY_SYSTEM_PROMPT`, `AGY_TURN_TIMEOUT_MIN`, `AGY_INACTIVITY_TIMEOUT_MIN`. 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.
|
|
128
|
+
|
|
129
|
+
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.
|
|
130
|
+
|
|
131
|
+
### The /agy command
|
|
132
|
+
|
|
133
|
+
`/agy` configures the provider at runtime. Settings persist to `~/.pi/agent/antigravity-bridge/config.json` and take effect on the next turn.
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
/agy status summary, or open the full settings picker (TUI)
|
|
137
|
+
/agy doctor single status surface: bridge state, driver counters, versions, acp state, lifecycle, settings, log dir
|
|
138
|
+
/agy auth show the shared agy CLI sign-in instruction
|
|
139
|
+
/agy mode plan provider turns are REFUSED (the CLI cannot enforce review-only, #1181)
|
|
140
|
+
/agy mode accept-edits agy applies edits directly (default)
|
|
141
|
+
/agy permissions on|off auto-approve / prompt for tool calls (see warning)
|
|
142
|
+
/agy ask on|off register the AskAntigravity delegation tool (default on; off keeps only the provider and models, even with pi-ask-antigravity installed)
|
|
143
|
+
/agy model flash|pro|gemini fallback model for the AskAntigravity tool; callers may override per call
|
|
144
|
+
/agy thinking low|medium|high fallback thinking tier for the AskAntigravity tool; callers may override per call
|
|
145
|
+
/agy digest on|off inject pi-side context into agy prompts (default off; see table above)
|
|
146
|
+
/agy system-prompt on|off send pi's system prompt + AGENTS.md + Pi Bridge tool-priority note (on ACP: in the generated restricted agent body; off omits Pi text only while keeping the bridge protocol, tool catalog, and restricted profile)
|
|
147
|
+
/agy bridge all|mcp|none which active pi tools the MCP bridge exposes to agy (default all, incl. active builtins; mcp = pi-mcp-adapter + skills only; none = bridge off, no Pi tools on restricted ACP; a running server picks up the new catalog immediately, a stopped one on the next start)
|
|
148
|
+
/agy tools [hide|show <name>|reset] session-only bridge-catalog hides (multi-word names OK; reset restores the full set; bare lists exposed + hidden; never touches saved config)
|
|
149
|
+
/agy web on|off register the agy_web_search + agy_read_url pi tools for ANY provider's model (default off; applies on the next pi start or /reload; every call spawns agy and spends Antigravity quota)
|
|
150
|
+
/agy engine acp|stream-json switch the turn engine (restart to apply; default acp, stream-json is the fallback; both use the agy CLI). No arguments opens the engine picker modal (TUI)
|
|
151
|
+
/agy auth-manual manual agy install and authentication commands
|
|
152
|
+
/agy clear drop all session bindings (force fresh conversations)
|
|
153
|
+
/agy-stop [runId] stop a background AskAntigravity run (id prefix, or the only running one with no argument)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Permissions
|
|
157
|
+
|
|
158
|
+
pi itself has no built-in approval gate. Unlike codex, claude, or agy running interactively, pi does not prompt you to confirm each tool action before it runs. That is the host environment this extension lives in.
|
|
159
|
+
|
|
160
|
+
Because agy runs non-interactively under this provider (nothing can answer a `y/n` prompt), this extension passes `--dangerously-skip-permissions` by default on `accept-edits` runs. It is technically necessary there: `accept-edits` auto-approves file edits but not shell commands, so a `run_command` would otherwise hang forever waiting for a prompt nothing can answer (upstream [google-antigravity/antigravity-cli#318](https://github.com/google-antigravity/antigravity-cli/issues/318)). The net effect is that agy executes commands the same way pi already executes your other tools: without per-action review.
|
|
161
|
+
|
|
162
|
+
Plan mode never receives the flag: the flag auto-approves every permission request, so an auto-approved plan run is a write-capable run (the CLI does not gate writes under plan mode, see next paragraph). Do not combine `--sandbox` with skip-permissions ([#36](https://github.com/google-antigravity/antigravity-cli/issues/36)).
|
|
163
|
+
|
|
164
|
+
**Provider turns cannot run review-only.** Probed 2026-10-07 ([google-antigravity/antigravity-cli#1181](https://github.com/google-antigravity/antigravity-cli/issues/1181)): on every tested path (one-shot `-p` and the stream-json I/O format, with and without `--add-dir`), `--mode plan` stages a plan, asks for review and approval, and executes the requested file write in the same turn (`permission_mode: "request-review"` is reported; no permission event appears for the write). With `--disable-slash-commands` the CLI additionally warns that `--mode plan` has no effect. The `readOnly` knob below exists because of this: plan-shaped provider turns refuse visibly instead of pretending. `AskAntigravity` with `mode: "plan"` adds a staged restricted agent whose toolset omits file-editing tools (probed 2026-09-28 on agy 1.2.12; re-verify on 1.3.x), but plan mode itself does not gate writes anywhere. Treat host-side pi tool restrictions as the only hard read-only wall.
|
|
165
|
+
|
|
166
|
+
### readOnly
|
|
167
|
+
|
|
168
|
+
`"readOnly": true` in the config (or `AGY_READONLY=1`, or `/agy readonly on`) is a fail-closed kill switch: every provider turn AND the `AskAntigravity` tool are refused with a visible error instead of running write-capable under a read-only label. Built for callers like `pi -p --no-tools --model antigravity/...` health checks that must never mutate a workspace: with no review-only enforcement available in the CLI (see Permissions), a visible refusal is the only honest behavior. The knob covers provider turns and the ask tool; the web tools still spawn agy for searches. Default false.
|
|
169
|
+
|
|
170
|
+
For per-action review of agy's mutating native tools (`run_command`, `create_file`, `edit_file`, ...), see the [Approval gate](docs/APPROVAL-GATE.md): with it on, the call must pass a pi-side approval (your permission extension, or the built-in ask/allow/deny fallback) before agy executes it.
|
|
171
|
+
|
|
172
|
+
### Run pi inside a sandbox
|
|
173
|
+
|
|
174
|
+
For isolation when running any agent that executes commands without a confirmation gate, run pi inside [**construct-cli**](https://github.com/EstebanForge/construct-cli) - EstebanForge's sandbox for AI agents. Isolated container, no path escape, ephemeral filesystem, `strict` / `offline` network modes, secret redaction. The blast radius of a bad command stays in the container, not your host. Install and usage instructions are in that repo.
|
|
175
|
+
|
|
176
|
+
### Environment variables
|
|
177
|
+
|
|
178
|
+
| Variable | Purpose |
|
|
179
|
+
| --- | --- |
|
|
180
|
+
| `AGY_BIN` | Path to the agy binary. Defaults to `agy` on PATH. |
|
|
181
|
+
| `AGY_ENGINE` | Engine: `acp` (default) or `stream-json`. Wins over the config file. |
|
|
182
|
+
| `AGY_EXTRA_ARGS` | Extra args appended to every invocation. Whitespace-split. |
|
|
183
|
+
| `AGY_CONVERSATIONS_DIR` | Override the conversations DB directory. |
|
|
184
|
+
| `AGY_MODE` | Override execution mode: `plan` (provider turns are refused, see Permissions) or `accept-edits` (default). Wins over the config file. |
|
|
185
|
+
| `AGY_READONLY` | `1`/`true`/`on` (or any set value except `0`/`false`/`off`/empty) turns every provider turn and the `AskAntigravity` tool into a visible refusal (fail-closed: the CLI has no review-only enforcement on any path, [#1181](https://github.com/google-antigravity/antigravity-cli/issues/1181)). Wins over the config file. |
|
|
186
|
+
| `AGY_SKIP_PERMISSIONS` | `1`/`true` (default) to pass `--dangerously-skip-permissions` so commands don't hang on an unanswerable prompt in `-p` mode. `0`/`false` to prompt (hangs any `run_command` non-interactively). Wins over the config file. |
|
|
187
|
+
| `AGY_USAGE_ESTIMATE` | Fallback ACP token display when the server omits usage: `estimate` (default; live client-side per-delta estimates), `direct`, `off`. Exact server usage always wins. Wins over the config file. |
|
|
188
|
+
| `AGY_DEFAULT_MODEL` | Default model for the `AskAntigravity` tool: `flash`/`pro`/`gemini`, or an exact id such as `gemini-4-hydrogen`. Default `gemini-4-hydrogen`; the tier suffix rides `AGY_DEFAULT_THINKING`. Wins over the config file. |
|
|
189
|
+
| `AGY_DEFAULT_THINKING` | Default thinking tier for the `AskAntigravity` tool: `low`/`medium`/`high`. Anything else falls back to `medium`. Wins over the config file. |
|
|
190
|
+
| `AGY_DEBUG` | `1`/`true`/`on` writes the full trail to the daily log (driver lifecycle, raw bridge traffic). Default off: **only `error` records land on disk** - routine disk writes are zero for regular users, and warnings surface as UI toasts instead. |
|
|
191
|
+
| `AGY_APPROVALS` | Approval gate mode: `auto` (default; gate on only when a pi permission extension is detected), `shadow` (force the shadow-tool gate on), `dedicated`, `off`. Unknown values fall back to `auto`, so a typo can never force the gate on. Wins over `config.approvals.gateMode`. |
|
|
192
|
+
| `AGY_APPROVALS_MODE` | Fallback decision when no permission extension answers a gated call: `ask` (interactive prompt), `allow`, `deny` (headless default). Wins over `config.approvals.mode`. |
|
|
193
|
+
|
|
194
|
+
## Debug logs
|
|
195
|
+
|
|
196
|
+
The extension keeps a daily log on your machine, sorted by day:
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
~/.pi/extensions-data/estebanforge/pi-antigravity-bridge/logs/<YYYY-MM-DD>.ndjson
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
One JSON record per line. Two verbosity tiers keep the disk cost at zero for regular users: by default only `error` records land on disk - everything routine (turn starts, tool calls, escalations, commands, driver failures) is withheld. Warnings are not lost: the extension toasts each one in the pi UI (bridge tool failures, stalls, timeouts, process exits), so users see them and can report them; deliberate aborts and failures pi already renders as the turn's own error block stay silent. Set `AGY_DEBUG=1` before reproducing a problem for the full trail: per-event driver lifecycle (spawn, exit, session load/new, unparks), turn starts and outcomes, bridge tool calls, escalations and poll traffic, late deliveries, list-tools traffic, recycle causes, and the raw bridge chatter. `/agy doctor` prints the log directory.
|
|
203
|
+
|
|
204
|
+
Notes:
|
|
205
|
+
|
|
206
|
+
- Retention: 14 days. Older files are pruned automatically.
|
|
207
|
+
- Privacy: prompt text, tool arguments, and tool output never land in the log. Secret-shaped values (tokens, API keys, credentials, header blocks) are redacted, and long strings are truncated. The `auth-url` record strips the login URL's query string.
|
|
208
|
+
- Logging never throws: an unwritable directory is skipped silently and retried on the next record.
|
|
209
|
+
- SSD wear: default volume is effectively zero until something actually errors. Verbose mode (`AGY_DEBUG=1`) writes more; turn it off after reproducing.
|
|
210
|
+
|
|
211
|
+
When you report an issue, attach the last day or two of files from that directory. For anything that needs reproduction, run with `AGY_DEBUG=1` once and attach that day's file. They usually contain the exact failure sequence (engine, session, bridge call, error) with no need to guess.
|
|
212
|
+
|
|
213
|
+
## Development
|
|
214
|
+
|
|
215
|
+
Build, test, and debug instructions live in [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md). For the internal architecture (engines, bridge round-trips, conversation discovery) see [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md).
|
|
216
|
+
|
|
217
|
+
## Terms of Service notice
|
|
218
|
+
|
|
219
|
+
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.
|
|
220
|
+
|
|
221
|
+
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.
|
|
222
|
+
|
|
223
|
+
Google's reported enforcement to date (the February 2026 suspensions) targeted token-reuse tools, not spawning the official CLI.
|
|
224
|
+
|
|
225
|
+
pi-antigravity-bridge practical risk is low, near zero. But not zero: the "in connection with" wording is broad, and Google can suspend accounts at its discretion regardless of whether a breach is provable. Grey area. Safe for now. You should read "news" about this online from time to time.
|
|
226
|
+
|
|
227
|
+
This is engineering analysis, not legal advice. Use against your own Antigravity account at your own risk; I am not responsible for any consequence to your account.
|
|
228
|
+
|
|
229
|
+
## Delegation tool: background runs
|
|
230
|
+
|
|
231
|
+
`AskAntigravity` accepts `background: true` (1:1 with the standalone pi-ask-antigravity extension): the call returns a `bg_` runId at once and the full answer arrives later as an UNTRUSTED-tagged message (secret-redacted) carrying the resume handle. `/agy-stop [runId]` stops a run by id prefix, or the only running one with no argument; the concurrency cap is 4. A stop landing after agy already closed but before the result settles (the discovery window) is refused with "already finished; its result is being delivered" instead of dropping the answer. Background is refused in pi's print/json modes (the process exits before the message could arrive), and `/new`, `/resume`, `/fork`, `/reload` kill in-flight runs. Delegation always spawns a one-shot `agy -p` process - never the ACP or stream-json turn engine.
|
|
232
|
+
|
|
233
|
+
## License
|
|
234
|
+
|
|
235
|
+
MIT.
|