@estebanforge/pi-antigravity-bridge 1.3.2 → 1.3.3

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,6 +2,12 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [1.3.3] - 2026-09-01
6
+
7
+ ### Added
8
+
9
+ - pi system prompt injection (G10): pi's composed system prompt - operating instructions plus the global agent-dir `AGENTS.md` and ancestor `AGENTS.md`/`CLAUDE.md` files - is prepended as a delimited block to the first prompt of each NEW agy conversation. agy has no system-prompt flag, so the prompt text is the only delivery path; the block is sent once per conversation and stays byte-identical afterwards, so agy's server-side prompt cache keeps hitting (unlike the per-turn G1 digest, which stays off by default for that reason). On by default (`config.systemPrompt`, `AGY_SYSTEM_PROMPT`, `/agy system-prompt on|off`); existing conversations keep the version they started with.
10
+
5
11
  ## [1.3.2] - 2026-09-01
6
12
 
7
13
  ### Removed
package/README.md CHANGED
@@ -91,8 +91,9 @@ If `agy models` fails at load (binary missing, auth not done, network stall), a
91
91
  | --- | --- | --- |
92
92
  | `bridgeTools` | `none` (bridge off), `mcp` (pi-mcp-adapter tools), `all` (every non-builtin tool, incl. other `Ask*` delegations) | `mcp` |
93
93
  | `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` |
94
+ | `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` |
94
95
 
95
- Env overrides: `AGY_BRIDGE_TOOLS`, `AGY_DIGEST`.
96
+ 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.
96
97
 
97
98
  ### The /agy command
98
99
 
@@ -108,6 +109,7 @@ Env overrides: `AGY_BRIDGE_TOOLS`, `AGY_DIGEST`.
108
109
  /agy model flash|pro|gemini default model alias for the AskAntigravity tool
109
110
  /agy thinking low|medium|high default thinking tier for the AskAntigravity tool
110
111
  /agy digest on|off inject pi-side context into agy prompts (default off; see table above)
112
+ /agy system-prompt on|off send pi's system prompt + AGENTS.md to new agy conversations (default on)
111
113
  /agy patch-cleanup restore the original pi files if an older version patched them
112
114
  /agy clear drop all session bindings (force fresh conversations)
113
115
  ```
@@ -27,7 +27,13 @@ credentials, so a secret never crosses the bridge, and a long call renders in
27
27
  pi's native UI while it runs. agy's file edits surface as git-sourced diffs in
28
28
  pi's thinking stream. A delta digest of pi-side context (compaction summaries,
29
29
  other-provider turns) is available but OFF by default (`/agy digest on`): the
30
- digest changes every turn and defeats agy's server-side prompt cache.
30
+ digest changes every turn and defeats agy's server-side prompt cache. The
31
+ reverse direction is on by default (`/agy system-prompt off` to disable):
32
+ pi's composed system prompt - its operating instructions plus the global
33
+ agent-dir `AGENTS.md` and ancestor `AGENTS.md`/`CLAUDE.md` files - is
34
+ prepended as a delimited block to the first prompt of each new agy
35
+ conversation, once, so the prompt cache keeps hitting (G10 in
36
+ `CHANGELOG.md`).
31
37
 
32
38
  ## Open gaps
33
39
 
@@ -302,8 +302,9 @@ function statusText(ctx: AgyCommandCtx): string {
302
302
  ` config: ${CONFIG_PATH}`,
303
303
  ` bridge tools: ${config.bridgeTools}`,
304
304
  ` digest: ${config.digest ? "on" : "off"}`,
305
+ ` system prompt: ${config.systemPrompt ? "on" : "off"}`,
305
306
  "",
306
- "Subcommands: /agy mode plan|accept-edits, /agy permissions on|off, /agy model flash|pro|gemini, /agy thinking low|medium|high, /agy clear",
307
+ "Subcommands: /agy mode plan|accept-edits, /agy permissions on|off, /agy model flash|pro|gemini, /agy thinking low|medium|high, /agy digest on|off, /agy system-prompt on|off, /agy clear",
307
308
  ].join("\n");
308
309
  }
309
310
 
@@ -311,7 +312,7 @@ function statusText(ctx: AgyCommandCtx): string {
311
312
  function registerAgyCommand(pi: ExtensionAPI, ctx: AgyCommandCtx): void {
312
313
  pi.registerCommand("agy", {
313
314
  description:
314
- "Antigravity provider: status, doctor, mode picker, clear sessions. Usage: /agy [status|doctor|mode [plan|accept-edits]|digest on|off|patch-cleanup|clear]",
315
+ "Antigravity provider: status, doctor, mode picker, clear sessions. Usage: /agy [status|doctor|mode [plan|accept-edits]|digest on|off|system-prompt on|off|patch-cleanup|clear]",
315
316
  handler: async (args, cmdCtx: ExtensionCommandContext) => {
316
317
  const ui = cmdCtx.ui;
317
318
  const mode = cmdCtx.mode;
@@ -406,6 +407,20 @@ function registerAgyCommand(pi: ExtensionAPI, ctx: AgyCommandCtx): void {
406
407
  }
407
408
  return;
408
409
  }
410
+ if (sub === "system-prompt") {
411
+ if (val === "on" || val === "off") {
412
+ const next = saveConfig({ systemPrompt: val === "on" });
413
+ ui?.notify(
414
+ next.systemPrompt
415
+ ? "system-prompt on. pi's system prompt (incl. global and project AGENTS.md) is prepended to the first prompt of each new agy conversation. Existing conversations keep the version they started with."
416
+ : "system-prompt off. agy runs on its own system prompt; pi instructions and AGENTS.md files are not sent.",
417
+ "info",
418
+ );
419
+ } else {
420
+ ui?.notify(`system-prompt: ${loadConfig().systemPrompt ? "on" : "off"}\nusage: /agy system-prompt on|off`, "info");
421
+ }
422
+ return;
423
+ }
409
424
 
410
425
  if (sub === "thinking") {
411
426
  if (val === "low" || val === "medium" || val === "high") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@estebanforge/pi-antigravity-bridge",
3
- "version": "1.3.2",
3
+ "version": "1.3.3",
4
4
  "description": "Streaming Gemini provider for pi, built on the agy CLI. Registers antigravity/* models in pi's /model picker; drives agy through its stream-json protocol (persistent process, tool round-trips, live usage).",
5
5
  "keywords": [
6
6
  "pi-package",
package/src/config.ts CHANGED
@@ -60,6 +60,16 @@ export interface AgyConfig {
60
60
  * sessions gain nothing: agy already keeps its own history, and bridge
61
61
  * round-trips deliver tool results through the bridge, not the digest. */
62
62
  digest: boolean;
63
+ /** Prepend pi's composed system prompt (pi tool guidance + the global
64
+ * agent-dir AGENTS.md and ancestor AGENTS.md/CLAUDE.md) to the FIRST
65
+ * prompt of each fresh agy conversation.
66
+ *
67
+ * Default ON: agy keeps its own history, so the prefix is sent once per
68
+ * conversation and stays byte-identical afterwards - agy's server-side
69
+ * prompt cache keeps hitting. This is why it is safe here while the G1
70
+ * digest (per-turn) is not. Turn off for agy-native behavior (agy's own
71
+ * system prompt only). */
72
+ systemPrompt: boolean;
63
73
  }
64
74
 
65
75
  const DEFAULTS: AgyConfig = {
@@ -69,6 +79,7 @@ const DEFAULTS: AgyConfig = {
69
79
  defaultThinking: "medium",
70
80
  bridgeTools: "mcp",
71
81
  digest: false,
82
+ systemPrompt: true,
72
83
  };
73
84
 
74
85
  /** Load config merged over defaults. Env vars override the file when set. */
@@ -121,6 +132,11 @@ export function loadConfig(configPath: string = CONFIG_PATH): AgyConfig {
121
132
  ? ["1", "true", "on"].includes(process.env.AGY_DIGEST.toLowerCase())
122
133
  : file.digest ?? false;
123
134
 
135
+ const envSys = process.env.AGY_SYSTEM_PROMPT;
136
+ const systemPrompt = envSys !== undefined
137
+ ? ["1", "true", "on"].includes(envSys.toLowerCase())
138
+ : file.systemPrompt ?? DEFAULTS.systemPrompt;
139
+
124
140
  return {
125
141
  mode,
126
142
  skipPermissions,
@@ -128,6 +144,7 @@ export function loadConfig(configPath: string = CONFIG_PATH): AgyConfig {
128
144
  defaultThinking,
129
145
  bridgeTools,
130
146
  digest,
147
+ systemPrompt,
131
148
  patchCleanupNotified: file.patchCleanupNotified === true,
132
149
  };
133
150
  }
package/src/provider.ts CHANGED
@@ -84,6 +84,43 @@ const COMPACTION_MARKER = "compacted into the following summary";
84
84
  const DIGEST_PREAMBLE =
85
85
  "[The following is context from the broader pi session that this Antigravity turn was not directly spawned for: compaction summaries and turns handled by other providers or pi's own tools. Your own prior turns are already in your conversation history. Use this for continuity only.]";
86
86
 
87
+ // --- pi system prompt (G10) ----------------------------------------------------
88
+ //
89
+ // pi composes context.systemPrompt every turn: its own operating instructions
90
+ // plus every AGENTS.md/CLAUDE.md it loaded (global agent dir first, then
91
+ // ancestors). The provider used to drop it, so agy models never saw the user's
92
+ // machine-level or project-level instructions. agy has no system-prompt flag
93
+ // (verified against `agy --help`), so the only delivery path is the prompt
94
+ // text. We prepend it as a delimited block on the FIRST prompt of a fresh
95
+ // conversation only: agy keeps its own history, the block stays byte-identical
96
+ // afterwards, and agy's server-side prompt cache keeps hitting.
97
+
98
+ export const SYSTEM_PROMPT_PREAMBLE =
99
+ "[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.]";
100
+
101
+ export const SYSTEM_PROMPT_END = "[END SYSTEM PROMPT]";
102
+
103
+ /** Assemble the full agy prompt: system prompt block, pi-side digest, user
104
+ * prompt. Empty parts are dropped. Pure; exported for unit testing.
105
+ * Pass systemPrompt only on a fresh conversation (see runTurnDriver). */
106
+ export function buildFullPrompt(
107
+ systemPrompt: string | undefined,
108
+ digest: string,
109
+ prompt: string,
110
+ ): string {
111
+ const parts: string[] = [];
112
+ if (systemPrompt) {
113
+ parts.push(`${SYSTEM_PROMPT_PREAMBLE}\n\n${systemPrompt}\n\n${SYSTEM_PROMPT_END}`);
114
+ }
115
+ if (digest) {
116
+ parts.push(`${DIGEST_PREAMBLE}\n\n${digest}`);
117
+ }
118
+ if (prompt) {
119
+ parts.push(prompt);
120
+ }
121
+ return parts.join("\n\n---\n\n");
122
+ }
123
+
87
124
  /** Flatten any message content shape (string or content-block array) to text.
88
125
  * Drops images, thinking, and tool-call blocks. */
89
126
  function blocksToText(content: unknown): string {
@@ -623,7 +660,11 @@ async function runTurnDriver(
623
660
  const effort = entry?.efforts?.length ? toAgyEffort(options?.reasoning, entry.efforts) : undefined;
624
661
  const watermark = existing?.lastMessageCount ?? 0;
625
662
  const digest = config.digest ? buildContextDigest(context.messages, watermark) : "";
626
- const fullPrompt = digest ? `${DIGEST_PREAMBLE}\n\n${digest}\n\n---\n\n${prompt}` : prompt;
663
+ // Fresh conversation only: agy stores the block in its own history, so
664
+ // re-sending it every turn would bloat each prompt and bust the cache.
665
+ const sysPrompt =
666
+ config.systemPrompt && !existing?.conversationId ? context.systemPrompt : undefined;
667
+ const fullPrompt = buildFullPrompt(sysPrompt, digest, prompt);
627
668
  try {
628
669
  handle = await deps.driver.run({
629
670
  cwd,