@estebanforge/pi-ask-antigravity 1.2.5 → 1.2.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 ADDED
@@ -0,0 +1,228 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [1.2.7] - 2026-09-25
6
+
7
+ ### Fixed
8
+
9
+ - **Plan mode never receives `--dangerously-skip-permissions`.** agy's plan-mode no-write gate IS a permission request ("File creation requires plan approval"), and the skip flag auto-approves every permission request — so a `mode: "plan"` delegation could edit the workspace inside the `--add-dir` grant despite the review-only contract. The default `skipPermissions` knob made this the out-of-the-box behavior. Probe evidence transfers directly (same binary, same `-p` path): with the flag a plan run wrote files; without it, file-write and run_command attempts end exit 0 in ~20-30 s with a "confirm plan" message — fail-visible, never the upstream #318 prompt-hang. Plan runs now never receive the flag, and the tool description and README state the enforcement instead of the aspirational claim.
10
+
11
+ Version 1.2.6 was a fleet-wide version stamp with no package changes.
12
+
13
+ ## [1.2.5] - 2026-09-18
14
+
15
+ ### Added
16
+
17
+ - **`thinking` / `effort` params on AskAntigravity (synonyms).** Port of the pi-antigravity-bridge fix: delegation calls had no direct tier knob (only tier sugar inside `model`, "flash high"), so a caller told "peer review on high thinking" fell through to the configured default with no signal anything was dropped. `thinking` takes pi vocabulary (minimal|low|medium|high|xhigh|max, clamped to agy's low|medium|high; unknown values fall back to low) and `effort` is the same knob under agy's own name. Explicit level beats a tier embedded in `model` and the config default; different values on both errors; fixed-thinking families ignore it because agy rejects `--effort` for them.
18
+
19
+ ## [1.2.4] - 2026-08-13
20
+
21
+ ### Added
22
+
23
+ - **Model, thinking tier, and mode shown next to the tool name.** While a
24
+ delegation runs, the TUI now renders
25
+ `AskAntigravity [model=gemini-3.6-flash, thinking=high]` with a prompt
26
+ preview, plus a tidy result row (`✓ AskAntigravity 12.3s`) with an
27
+ expandable body. Built on pi's `renderCall`/`renderResult` hooks; the
28
+ values shown are the resolved config defaults (model alias + tier), not
29
+ just the args the caller passed. `AgyDetails` gained a `thinking` field.
30
+ - **Opt-in full-context delegation (`includeContext`).** New boolean param
31
+ (default `false`, isolated one-shot unchanged). When `true`, the current pi
32
+ conversation is exported as resolved markdown to
33
+ `~/.pi/extensions-data/estebanforge/pi-ask-antigravity/` and the prompt
34
+ tells agy to read it first. The run passes `--add-dir` for that folder so
35
+ the sandbox can read it; the temp file is removed after the run.
36
+
37
+ ## [1.2.3] - 2026-08-10
38
+
39
+ ### Fixed
40
+
41
+ - **Model parsing now handles agy's real two-column output.** `agy models`
42
+ prints `<slug> <display label>` per line, and `--model` accepts only the
43
+ slug. `parseModelLine` swallowed the whole line and the static
44
+ `sonnet`/`opus`/`gpt-oss` overlay used display labels, so `--model` was
45
+ rejected. It now splits column 1; the overlay uses real slugs
46
+ (`claude-sonnet-4-6`, `claude-opus-4-6-thinking`, `gpt-oss-120b-medium`);
47
+ and `resolveModel` returns a `{model, effort?}` shape that sends
48
+ Gemini-family bases' tier to `--effort` while fixed-thinking families keep
49
+ the exact slug with no `--effort` (agy rejects it for them).
50
+ `parseModelLine`/`mergeCatalog`/`resolveModel` are now exported, with
51
+ two-column parser tests on the verified live `agy models` fixture.
52
+
53
+ ## [1.2.1] - 2026-08-06
54
+
55
+ ### Changed
56
+ - **Dependencies updated.** Raised the `pi-coding-agent`, `pi-ai`, `pi-tui` dev pins to `^0.84.0`. Audited against the pi v0.84.0 breaking changes (renamed `ModelsRequestTransforms`, null-tolerant `getApiKeyAndHeaders` headers, dropped `message_update` partial fields, v4 session APIs); no code changes were needed and `tsc`/`typecheck` passes against 0.84.0.
57
+
58
+ ## [1.2.0] - 2026-07-26
59
+
60
+ ### Added
61
+
62
+ - **`permissions` config + `/agy` row + `AGY_SKIP_PERMISSIONS` env.** Controls
63
+ the new flag. Default `auto-approved` (required for non-interactive use); set
64
+ to `prompt` (`/agy` picker, or `AGY_SKIP_PERMISSIONS=0`) to disable - but
65
+ then any `run_command` hangs until you kill the call. Matches the bridge's
66
+ permissions knob.
67
+
68
+ ### Changed
69
+
70
+ - **Defers to `pi-antigravity-bridge` when it is installed.** The bridge now
71
+ ships both the streaming antigravity provider AND the `AskAntigravity` tool
72
+ (same shape as `pi-claude-bridge`). To avoid a duplicate-tool clash, this
73
+ extension detects the bridge at load and, if present, registers nothing -
74
+ silently. Detection does not use module resolution (pi isolates each
75
+ package's module root); it checks an in-process `Symbol.for` flag the bridge
76
+ sets AND the bridge's package.json at pi's install paths
77
+ (`@estebanforge/pi-antigravity-bridge/package.json`). Order-independent for
78
+ npm/git installs; for local/source installs relies on the in-process flag
79
+ (install the bridge first so it loads first). Without the bridge, behavior is
80
+ unchanged.
81
+
82
+ ### Fixed
83
+
84
+ - **`run_command` no longer hangs the tool.** `--mode accept-edits` auto-approves
85
+ file edits but NOT shell commands, so any task that triggered a `run_command`
86
+ hung forever on an unanswerable `y/n` prompt in non-interactive `-p` mode
87
+ (same root cause the pi-antigravity-bridge provider hit). The tool now passes
88
+ `--dangerously-skip-permissions` by default. Backported from the bridge.
89
+
90
+ ## [1.1.0] - 2026-07-25
91
+
92
+ ### Fixed
93
+
94
+ - **`CONV_ID_RE` rejected real agy conversation ids, silently breaking the
95
+ "continued conversation" feature.** The regex was
96
+ `/^[A-Za-z0-9]{1,128}$/` (no hyphens in the character class), but agy
97
+ conversation ids are hyphenated UUIDs (e.g.
98
+ `9e6fdc2f-f9f9-4096-95fc-7852528b50cc`, the very example in the source
99
+ comment). Every legitimate id failed validation, so `isContinuation`
100
+ was always `false`, `--conversation <id>` was never passed, and every
101
+ "continued" call quietly started a brand-new agy conversation instead
102
+ of resuming. Now allows hyphens in the body
103
+ (`/^[A-Za-z0-9][A-Za-z0-9-]{0,127}$/`) while preserving the threat
104
+ model: first char must be alphanumeric, so leading-dash flag-injection
105
+ values are still rejected. Present since 1.0.0; found by peer review.
106
+
107
+ ### Added
108
+
109
+ - **`mode` parameter** — replaces the previous `skipPermissions` boolean
110
+ with an explicit two-way enum: `plan` (review-only, `--mode plan`) and
111
+ `accept-edits` (agy applies edits, `--mode accept-edits`, default).
112
+ Use `plan` for cross-review and read-only tasks, `accept-edits` for
113
+ implementation.
114
+ - **`digest` parameter** — when true, the prompt is prefixed with
115
+ `(Use compact digests, not full file contents.)` to keep `agy` from
116
+ returning full file payloads. Default: `true` for `plan`,
117
+ `false` for `accept-edits`. Override per call.
118
+ - **Non-Gemini alias overlay** — `sonnet`, `opus`, and `gpt-oss` now
119
+ resolve to the exact agy strings `Claude Sonnet 4.6 (Thinking)`,
120
+ `Claude Opus 4.6 (Thinking)`, and `GPT-OSS 120B (Medium)`. A
121
+ static short-alias map is checked before the family parser, so
122
+ these names resolve even when `agy models` does not surface them
123
+ in the live catalog (older agy builds, plan-gated models). The
124
+ overlay entries are also merged with the live catalog at
125
+ extension load; live entries always win on case-insensitive
126
+ full-string equality, so an updated `agy models` listing takes
127
+ precedence over the hardcoded fallback. Borrowed from
128
+ `@bacnh85/pi-agy`'s static model map.
129
+ - **Effective `mode` and `digest` surfaced in `details`** — every
130
+ tool result now reports the resolved mode and whether the digest
131
+ prefix was applied, so the orchestrating model (and humans reading
132
+ logs) can see what flags were actually passed to `agy`.
133
+ - **Case-insensitive live-catalog lookup for overlay aliases.** When
134
+ `sonnet` / `opus` / `gpt-oss` resolve via the overlay, the lookup
135
+ against the live catalog is now case-insensitive so the
136
+ "live entries win" guarantee holds even if `agy models` lists the
137
+ same model under different casing than the hardcoded overlay.
138
+ Matches `mergeCatalog`'s dedup logic.
139
+
140
+ ### Changed
141
+
142
+ - **Breaking: `skipPermissions` parameter is removed.** Use `mode`
143
+ instead. The previous `skipPermissions: true` (which passed
144
+ `--dangerously-skip-permissions`) was a coarse proxy for the new
145
+ `mode: "accept-edits"` and is no longer the right primitive. Use
146
+ `mode: "plan"` for review-only flows. No callers in the wild
147
+ depend on the old boolean (the package shipped 2026-07-07), so
148
+ the break is contained to a single minor bump.
149
+ - **No `sandbox` enum value.** A peer review caught that agy's
150
+ `--sandbox` flag is an orthogonal shell-containment setting,
151
+ not an "edit preview" mode. Users who need shell containment
152
+ should set `AGY_EXTRA_ARGS=--sandbox` in their environment.
153
+ - **Tool description** now documents the `mode` and `digest`
154
+ affordances so the orchestrating model knows about them.
155
+
156
+ ## [1.0.1] - 2026-07-23
157
+
158
+ ### Fixed
159
+
160
+ - **`gemini-flash-latest` and `gemini-pro-latest` aliases now win over
161
+ versioned entries when no version is pinned.** Previously, asking for
162
+ `flash` resolved to the highest version of the flash family (e.g.
163
+ `Gemini 3.6 Flash (Medium)`), which is a concrete snapshot — not
164
+ Google's "latest release" pointer. The resolver now prefers entries
165
+ with `version: null` (the aliases that `parseModelLine` produces from
166
+ names like `Gemini Flash Latest`) over versioned entries. Falls back
167
+ to the highest version if no alias is present in the catalog, so
168
+ older agy builds without `*-latest` entries keep working.
169
+ - **Leading-dash values passed as `model` are rejected before reaching
170
+ argv.** A value like `--dangerously-skip-permissions` used to land
171
+ verbatim as the `--model` token; the tool now refuses it with a clear
172
+ error message, matching the `CONV_ID_RE` threat model already applied
173
+ to conversation ids.
174
+
175
+ ### Changed
176
+
177
+ - `modelParam` is now a plain `Type.String()` instead of a conditional
178
+ `StringEnum` built from the live catalog. The enum was too restrictive
179
+ when discovery succeeded (the common case): any tiered or pinned
180
+ alias like `"flash high"` or `"3.5 flash"` failed AJV validation
181
+ before `resolveModel` ever saw it. Plain `Type.String()` lets the
182
+ resolver handle every documented form and falls back to agy for
183
+ unknown slugs. The now-unused `StringEnum` import is gone.
184
+
185
+ ## [1.0.0] - 2026-07-07
186
+
187
+ Initial release.
188
+
189
+ ### Added
190
+
191
+ - **`AskAntigravity` tool** — delegates a self-contained sub-task to Google
192
+ Antigravity's `agy` CLI (the CLI for Gemini) via `agy -p`, streams stdout
193
+ as partial output, and returns the final response. The tool answers to
194
+ three names the CLI is known by — **gemini**, **antigravity**, and **agy**
195
+ — surfaced in its description so the model maps any of them to this single
196
+ tool.
197
+ - **Multi-turn conversations with agy** — optional `conversationId` param.
198
+ Omit for a one-shot (agy starts fresh); pass the id returned in a prior
199
+ call's result (`details.conversationId`) to resume that conversation with
200
+ full context. The agent decides per call which mode to use. On fresh runs
201
+ the extension discovers the new conversation id agy creates (snapshot +
202
+ diff of agy's conversations dir, the one technique borrowed from
203
+ [`antigravity-acp`](https://github.com/shubzkothekar/antigravity-acp)'s
204
+ `scan.ts`); on continued runs it passes `--conversation <id>` which agy
205
+ resumes natively. agy holds all state in its own SQLite DB; the extension
206
+ is otherwise stateless.
207
+ - **Friendly model aliases** — `flash`, `pro`, `gemini`, plus tier/version
208
+ qualifiers (`flash high`, `3.1 pro`). Aliases resolve to the exact
209
+ `agy models` string using numeric version comparison, with nearest-tier
210
+ fallback (Pro has no Medium → falls back to High; ties break toward the
211
+ higher tier so "latest and greatest" wins).
212
+ - **`/agy` slash command** — interactive picker (`SettingsList`) for the
213
+ default model and default thinking tier. If the project config shadows the
214
+ global, the change is written there so it actually takes effect; otherwise
215
+ it writes to global. Outside TUI (RPC/headless), prints a read-only status
216
+ snapshot.
217
+ - **Config file** — `~/.pi/agent/ask-antigravity.json` (global) merged over
218
+ `.pi/ask-antigravity.json` (project). Atomic writes (temp + rename).
219
+ - **Defaults** — model `flash`, thinking `medium` (Gemini 3.5 Flash Medium).
220
+ - **Circular-delegation guard** — refuses to spawn agy when the active Pi
221
+ provider is already `antigravity`/`agy`.
222
+ - **Process lifecycle** — spawned `agy` runs in a detached process group so
223
+ its own exec subprocesses are killed on abort/timeout (not orphaned); a
224
+ watchdog enforces the timeout cap directly (not just via agy's
225
+ `--print-timeout`); stdout/stderr decoded at the stream level for UTF-8
226
+ safety across pipe chunks; throttled status updates avoid O(n²) re-renders.
227
+ - **Environment support** — `AGY_BIN`, `AGY_EXTRA_ARGS`,
228
+ `AGY_CONVERSATIONS_DIR`.
package/README.md CHANGED
@@ -1,10 +1,8 @@
1
1
  # @estebanforge/pi-ask-antigravity
2
2
 
3
- A [Pi](https://github.com/earendil-works/pi-coding-agent) extension that exposes the **`AskAntigravity`** tool: delegate a self-contained sub-task to Google Antigravity's `agy` CLI and stream its response back into the Pi session.
3
+ A [Pi](https://github.com/earendil-works/pi) extension that exposes the **`AskAntigravity`** tool: delegate a self-contained sub-task to Google Antigravity's `agy` CLI and stream its response back into the Pi session.
4
4
 
5
- It is the `AskClaude`-style delegation pattern (from pi-claude-bride extension), pointed at Gemini via `agy`. The tool answers to three names the CLI is known by — **gemini**, **antigravity**, and **agy** — surfaced in its description so the model maps any of them to this single tool.
6
-
7
- <img width="1512" height="845" alt="image" src="https://github.com/user-attachments/assets/3e1a8f19-64d2-43ab-a30f-47f39daa151d" />
5
+ It is the `AskClaude`-style delegation pattern (from pi-claude-bridge extension), pointed at Gemini via `agy`. The tool answers to three names the CLI is known by — **gemini**, **antigravity**, and **agy** — surfaced in its description so the model maps any of them to this single tool.
8
6
 
9
7
  ## Install
10
8
 
@@ -65,7 +63,7 @@ Verbose `agy models` strings (`Gemini 3.5 Flash (Medium)`) are hostile to natura
65
63
 
66
64
  | Mode | Flag | Use when |
67
65
  | --- | --- | --- |
68
- | `plan` | `--mode plan` | agy reviews and plans without writing. Use for cross-review and read-only tasks. |
66
+ | `plan` | `--mode plan` | agy reviews and plans without writing. Use for cross-review and read-only tasks. Enforced: the skip-permissions flag is never passed in plan mode, so write and command attempts fail visibly at plan approval instead of executing. |
69
67
  | `accept-edits` (default) | `--mode accept-edits` | agy applies edits directly inside the workspace. |
70
68
 
71
69
  For agy's orthogonal `--sandbox` shell-containment flag, set `AGY_EXTRA_ARGS=--sandbox` in your environment. The extension does not expose it as a `mode` value because `--sandbox` controls command containment, not edit persistence.
@@ -113,7 +111,7 @@ Interactive picker for the default model and default thinking. If the project co
113
111
  | `prompt` | yes | Self-contained task. agy cannot see the Pi conversation. |
114
112
  | `cwd` | no | Workspace agy runs in. Defaults to the project root. |
115
113
  | `model` | no | Alias or exact id. Omit for the configured default. |
116
- | `mode` | no | `plan` (review-only) or `accept-edits` (agy applies edits, default). |
114
+ | `mode` | no | `plan` (review-only; enforced via plan approval) or `accept-edits` (agy applies edits, default). |
117
115
  | `digest` | no | Prefix the prompt with `(Use compact digests, not full file contents.)`. Defaults on for `plan`, off for `accept-edits`. |
118
116
  | `conversationId` | no | Omit for a one-shot (agy starts fresh). Pass the id from a prior call's result (`details.conversationId`) to resume that agy conversation with full context. See [Two modes](#two-modes-one-shot-vs-continued-conversation). |
119
117
  | `timeoutMinutes` | no | Hard cap on the run. Default 10. |
@@ -96,7 +96,9 @@ function levelToTier(level: string): ThinkingTier {
96
96
  }
97
97
 
98
98
  // Mode = which agy tool-loop policy to apply. Distinct from the alias layer.
99
- // "plan" → --mode plan (no edits; review-only)
99
+ // "plan" → --mode plan (no edits; review-only — the skip-
100
+ // permissions flag is withheld in plan
101
+ // mode so the plan-approval gate holds)
100
102
  // "accept-edits" → --mode accept-edits (agy applies edits)
101
103
  //
102
104
  // Note: agy's --sandbox flag is an orthogonal shell-containment setting
@@ -154,7 +156,7 @@ TWO MODES (you choose):
154
156
  - **Continued conversation**: pass the conversationId returned in the PREVIOUS call's details (details.conversationId). agy resumes that conversation with full context intact — use for follow-ups, multi-turn refinement, or when the user says "ask agy to follow up / continue / now do X based on what you just did". Thread the id from each result into the next call.
155
157
 
156
158
  EXECUTION MODES (param: mode):
157
- - **plan**: agy reviews and plans without writing. Use for cross-review and read-only tasks.
159
+ - **plan**: agy reviews and plans without writing. Use for cross-review and read-only tasks. Enforced: plan runs never receive the skip-permissions flag, so a write or command attempt ends the run quickly with a "confirm plan" message instead of executing.
158
160
  - **accept-edits** (default): agy applies edits directly inside the workspace.
159
161
  - For agy's orthogonal \`--sandbox\` shell-containment flag, set the \`AGY_EXTRA_ARGS=--sandbox\` env var.
160
162
 
@@ -949,7 +951,7 @@ export default async function (pi: ExtensionAPI) {
949
951
  ],
950
952
  {
951
953
  description:
952
- "agy execution mode. 'plan' = review-only, no edits (--mode plan). 'accept-edits' = agy applies edits directly (--mode accept-edits, default). For agy's orthogonal --sandbox shell-containment flag, set the AGY_EXTRA_ARGS env var.",
954
+ "agy execution mode. 'plan' = review-only, no edits (--mode plan; the skip-permissions flag is never passed, so write and command attempts fail visibly at plan approval). 'accept-edits' = agy applies edits directly (--mode accept-edits, default). For agy's orthogonal --sandbox shell-containment flag, set the AGY_EXTRA_ARGS env var.",
953
955
  default: "accept-edits",
954
956
  },
955
957
  ),
@@ -1199,7 +1201,16 @@ export default async function (pi: ExtensionAPI) {
1199
1201
  // accept-edits auto-approves file edits but NOT shell commands, so a
1200
1202
  // run_command would hang on an unanswerable y/n prompt in non-interactive
1201
1203
  // -p mode. Honor the shared permissions setting (same knob as the bridge).
1202
- if (config.skipPermissions) args.push("--dangerously-skip-permissions");
1204
+ // Plan mode never gets the flag even when the knob is on: the flag
1205
+ // auto-approves ALL permission requests including plan mode's own
1206
+ // approval gate, which would silently turn "review-only" into full
1207
+ // write access inside --add-dir (probed 2026-09-25: with the flag a
1208
+ // plan run wrote files; without it, file and command attempts end
1209
+ // exit 0 in ~20-30s with a "confirm plan" message - fail-visible,
1210
+ // never a hang). Same fix as the bridge's ask-tool and driver.
1211
+ if (mode !== "plan" && config.skipPermissions) {
1212
+ args.push("--dangerously-skip-permissions");
1213
+ }
1203
1214
  if (isContinuation) args.push("--conversation", rawConvId as string);
1204
1215
  args.push("--print-timeout", `${timeoutMin}m`);
1205
1216
  if (contextFile) args.push("--add-dir", askContextDir());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@estebanforge/pi-ask-antigravity",
3
- "version": "1.2.5",
3
+ "version": "1.2.7",
4
4
  "description": "Pi tool that delegates a self-contained sub-task to Google Antigravity's agy CLI (the CLI for Gemini). Friendly model aliases (flash/pro/gemini), configurable default model + thinking, and the AskAntigravity delegation tool.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -20,20 +20,18 @@
20
20
  },
21
21
  "repository": {
22
22
  "type": "git",
23
- "url": "git+https://github.com/EstebanForge/pi-ask-antigravity.git"
23
+ "url": "git+https://github.com/EstebanForge/pi-extensions.git",
24
+ "directory": "packages/pi-ask-antigravity"
24
25
  },
25
26
  "publishConfig": {
26
27
  "access": "public"
27
28
  },
28
29
  "type": "module",
29
- "scripts": {
30
- "typecheck": "tsc --noEmit",
31
- "test": "vitest run",
32
- "prepublishOnly": "npm run typecheck && npm test"
33
- },
34
30
  "files": [
35
31
  "extensions",
36
- "README.md"
32
+ "README.md",
33
+ "CHANGELOG.md",
34
+ "LICENSE"
37
35
  ],
38
36
  "pi": {
39
37
  "extensions": [
@@ -47,15 +45,5 @@
47
45
  "@earendil-works/pi-coding-agent": {
48
46
  "optional": true
49
47
  }
50
- },
51
- "devDependencies": {
52
- "@earendil-works/pi-ai": "^0.85.0",
53
- "@earendil-works/pi-coding-agent": "^0.85.0",
54
- "@earendil-works/pi-server": "^0.85.0",
55
- "@earendil-works/pi-tui": "^0.85.0",
56
- "@types/node": "^22.0.0",
57
- "typebox": "^1.1.38",
58
- "typescript": "^5.8.0",
59
- "vitest": "^4.1.7"
60
48
  }
61
49
  }