@estebanforge/pi-antigravity-bridge 1.4.5 → 1.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,11 +2,28 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [1.4.6] - 2026-09-04
6
+
7
+ ### Added
8
+
9
+ - Tool-priority note in the system prompt block (`systemPrompt` setting, on by default): agy runs embedded in pi, so its native interactive tools (the live example was `ask_question` vs the bridge's `ask_user_question`) never reach the user. The note tells agy to always prefer the Pi Bridge tool when one covers the same purpose. The old preamble sentence that allowed "your own tools or the pi tool bridge" is gone, since that ambiguity was the cause.
10
+
11
+ ### Fixed
12
+
13
+ - `/agy auth` reports a distinct failure instead of a false "Signed in." when the server accepts the sign-in but `acp_token.json` never appears within the 5 s post-authenticate grace window (peer-review find; the poll result was never read).
14
+ - Test-infra: the fake ACP server's request log was lost on SIGTERM (buffered write stream + Gate D teardown), which flaked the Gate D abort test ~1-in-3 suite runs; the log now appends synchronously.
15
+
16
+ ### Changed
17
+
18
+ - The sign-in URL toast fences the URL with blank lines so it stays readable and copyable next to the ssh port-forward hint.
19
+
5
20
  ## [1.4.5] - 2026-09-04
6
21
 
7
22
  ### Added
8
23
 
9
- - `/agy auth` subcommand: runs the antigravity-acp sign-in on demand (spawns the server, sends `authenticate`, waits for the browser round-trip to complete; minutes-scale). Signing in no longer rides the first Antigravity message, and both login-pending moments now point at `/agy auth`. The sign-in URL toast (and its ssh port-forward hint) fires during `/agy auth` exactly as it does during turns. After the authenticate reply the run waits up to 5 s for `acp_token.json` before killing the sign-in server, and a second concurrent `/agy auth` fails fast instead of racing the token write.
24
+ - Tool-priority note in the system prompt block (`systemPrompt` setting, on by default): agy runs embedded in pi, so its native interactive tools (the live example was `ask_question` vs the bridge's `ask_user_question`) never reach the user. The note tells agy to always prefer the Pi Bridge tool when one covers the same purpose. The old preamble sentence that allowed "your own tools or the pi tool bridge" is gone, since that ambiguity was the cause.
25
+
26
+ - `/agy auth` subcommand: runs the antigravity-acp sign-in on demand (spawns the server, sends `authenticate`, waits for the browser round-trip to complete; minutes-scale). Signing in no longer rides the first Antigravity message, and both login-pending moments now point at `/agy auth`. The sign-in URL toast (and its ssh port-forward hint) fires during `/agy auth` exactly as it does during turns, and a second concurrent `/agy auth` fails fast instead of racing the token write.
10
27
 
11
28
  ### Changed
12
29
 
package/README.md CHANGED
@@ -107,7 +107,7 @@ If `agy models` fails at load (binary missing, auth not done, network stall), a
107
107
  | `askTool` | `on` (register the AskAntigravity delegation tool), `off` (no delegation tool; provider and models only) | `on` |
108
108
  | `bridgeTools` | `none` (bridge off), `all` (every non-builtin tool, incl. other `Ask*` delegations), `mcp` (pi-mcp-adapter tools + skills bridge only) | `all` |
109
109
  | `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` |
110
- | `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
+ | `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, plus a tool-priority note: Pi Bridge tools win over agy's native interactive ones, which never reach the user) or `off` (agy-native behavior) | `on` |
111
111
 
112
112
  Env overrides: `AGY_BRIDGE_TOOLS`, `AGY_ASK_TOOL`, `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.
113
113
 
@@ -129,7 +129,7 @@ The `activate_skill` catalog mirrors pi's directory-based skill discovery: the t
129
129
  /agy model flash|pro|gemini fallback model for the AskAntigravity tool; callers may override per call
130
130
  /agy thinking low|medium|high fallback thinking tier for the AskAntigravity tool; callers may override per call
131
131
  /agy digest on|off inject pi-side context into agy prompts (default off; see table above)
132
- /agy system-prompt on|off send pi's system prompt + AGENTS.md to new agy conversations (default on)
132
+ /agy system-prompt on|off send pi's system prompt + AGENTS.md + the Pi Bridge tool-priority note to new agy conversations (default on)
133
133
  /agy bridge all|mcp|none which pi tools the MCP bridge exposes to agy (default all; none = bridge off)
134
134
  /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)
135
135
  /agy engine acp|stream-json switch the turn engine (restart to apply; default stream-json; acp runs self-service setup: binary install + auth bootstrap)
@@ -142,8 +142,17 @@ export default async function (pi: ExtensionAPI): Promise<void> {
142
142
  if (msg === "auth-url") {
143
143
  const { url, port } = (data ?? {}) as { url?: string; port?: number | null };
144
144
  if (!url) return;
145
- const ssh = port ? `\nSSH session? Forward the port on your machine first:\n ssh -N -L ${port}:127.0.0.1:${port} <user@host>` : "";
146
- const text = `Google sign-in URL for the ACP engine:\n${url}${ssh}`;
145
+ // Blank lines fence the URL off from the rest of the text: it is long
146
+ // and wraps, so separation keeps it readable and copyable.
147
+ const parts = ["Google sign-in URL for the ACP engine:", "", url];
148
+ if (port) {
149
+ parts.push(
150
+ "",
151
+ "SSH session? Forward the port on your machine first:",
152
+ ` ssh -N -L ${port}:127.0.0.1:${port} <user@host>`,
153
+ );
154
+ }
155
+ const text = parts.join("\n");
147
156
  if (activeUi) activeUi.notify(text, "warning");
148
157
  else console.error(`[antigravity-bridge acp] ${text}`);
149
158
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@estebanforge/pi-antigravity-bridge",
3
- "version": "1.4.5",
3
+ "version": "1.4.6",
4
4
  "description": "Gemini provider for Pi on the Antigravity ACP server (official Google ACP) or the stream-json agy CLI. antigravity/* models in Pi's /model picker, no-patch MCP bridge: agy runs Pi's tools. ToS safe to use.",
5
5
  "keywords": [
6
6
  "pi-package",
package/src/acp/auth.ts CHANGED
@@ -18,10 +18,14 @@ export interface AcpAuthOptions {
18
18
  cwd?: string;
19
19
  extraEnv?: Record<string, string>;
20
20
  authUrlFile?: string;
21
+ /** Directory holding acp_token.json. Default: ~/.gemini/antigravity-acp.
22
+ * Tests point this at a fixture dir; production callers use the default. */
23
+ tokenDir?: string;
21
24
  /** The server is expected to have written acp_token.json by the time
22
25
  * authenticate replies, but write-after-reply is unverified; after a
23
26
  * successful reply the run polls for the token up to this long before
24
- * SIGTERM, so a laggard write is never killed mid-flight. */
27
+ * SIGTERM, so a laggard write is never killed mid-flight. A token that
28
+ * never appears is a distinct failure, not silent success. */
25
29
  tokenGraceMs?: number;
26
30
  timeoutMs?: number;
27
31
  log?: (msg: string, data?: unknown) => void;
@@ -53,7 +57,13 @@ export function runAcpAuth(opts: AcpAuthOptions): Promise<AcpAuthResult> {
53
57
  await conn.start();
54
58
  await conn.request("authenticate", { methodId: "oauth-personal" }, opts.timeoutMs ?? AUTH_TIMEOUT_MS);
55
59
  const deadline = Date.now() + grace;
56
- while (!hasAcpToken() && Date.now() < deadline) await sleep(200);
60
+ while (!hasAcpToken(opts.tokenDir) && Date.now() < deadline) await sleep(200);
61
+ if (!hasAcpToken(opts.tokenDir)) {
62
+ return {
63
+ ok: false,
64
+ error: `the server accepted the sign-in, but no token file appeared in ${opts.tokenDir ?? "~/.gemini/antigravity-acp"} within ${Math.round(grace / 1000)}s`,
65
+ };
66
+ }
57
67
  return { ok: true };
58
68
  } catch (err) {
59
69
  return { ok: false, error: err instanceof Error ? err.message : String(err) };
package/src/provider.ts CHANGED
@@ -108,10 +108,19 @@ const DIGEST_PREAMBLE =
108
108
  // afterwards, and agy's server-side prompt cache keeps hitting.
109
109
 
110
110
  export const SYSTEM_PROMPT_PREAMBLE =
111
- "[The following is the system prompt of the pi session that spawned this conversation: operating instructions plus project context (AGENTS.md files). Apply it for this whole conversation. Tool guidance may reference pi-side tools; use your own tools or the pi tool bridge for those actions.]";
111
+ "[The following is the system prompt of the pi session that spawned this conversation: operating instructions plus project context (AGENTS.md files). Apply it for this whole conversation.]";
112
112
 
113
113
  export const SYSTEM_PROMPT_END = "[END SYSTEM PROMPT]";
114
114
 
115
+ /** Brief tool-priority note appended inside every system prompt block: agy
116
+ * runs embedded in pi, so its native interactive tools never reach the
117
+ * user. Equivalent Pi Bridge tools must win. Concrete clash observed live:
118
+ * agy picked its native ask_question over the bridge's ask_user_question
119
+ * and the question never displayed. Rides the systemPrompt gate: the note
120
+ * ships only when the system prompt ships. */
121
+ export const TOOL_PRIORITY_NOTE =
122
+ "[Tool priority: this conversation runs inside pi, not as a standalone agy session; the user only sees what surfaces in pi. Native interactive tools, for example ask_question, never reach the user. When a Pi Bridge tool covers the same purpose, always use the Pi Bridge tool; for user questions use ask_user_question.]";
123
+
115
124
  /** Assemble the full agy prompt: system prompt block, pi-side digest, user
116
125
  * prompt. Empty parts are dropped. Pure; exported for unit testing.
117
126
  * Pass systemPrompt only on a fresh conversation (see runTurnDriver). */
@@ -122,7 +131,7 @@ export function buildFullPrompt(
122
131
  ): string {
123
132
  const parts: string[] = [];
124
133
  if (systemPrompt) {
125
- parts.push(`${SYSTEM_PROMPT_PREAMBLE}\n\n${systemPrompt}\n\n${SYSTEM_PROMPT_END}`);
134
+ parts.push(`${SYSTEM_PROMPT_PREAMBLE}\n\n${systemPrompt}\n\n${TOOL_PRIORITY_NOTE}\n\n${SYSTEM_PROMPT_END}`);
126
135
  }
127
136
  if (digest) {
128
137
  parts.push(`${DIGEST_PREAMBLE}\n\n${digest}`);