From fb374a80c2ba010348bbdf5ff0cd4e43f7a5c55f Mon Sep 17 00:00:00 2001 From: ARareUsername Date: Tue, 21 Jul 2026 02:43:19 +0800 Subject: [PATCH 1/5] fix(daemon): pass antigravity prompt as -p argument instead of stdin agy's -p/--print/--prompt takes the prompt as a command-line argument; it does not read from stdin and has no '-' stdin sentinel. The adapter invoked 'agy -p -' with promptViaStdin, so agy received the literal '-' as an empty prompt and replied "your request was empty or a placeholder (-)". - antigravity.ts: emit ['-p', ] and set promptViaStdin: false - executables.ts / app-config.ts: add missing AGY_BIN override key + allowlist entry so agy can be pointed at an explicit binary when auto-detection fails (parity with every other agent) - agent-args.test.ts: assert the new argv contract --- apps/daemon/src/app-config.ts | 1 + apps/daemon/src/runtimes/defs/antigravity.ts | 31 ++++++------------- apps/daemon/src/runtimes/executables.ts | 1 + apps/daemon/tests/runtimes/agent-args.test.ts | 14 ++++----- 4 files changed, 19 insertions(+), 28 deletions(-) diff --git a/apps/daemon/src/app-config.ts b/apps/daemon/src/app-config.ts index d63c76abc6b..59d0e74d67a 100644 --- a/apps/daemon/src/app-config.ts +++ b/apps/daemon/src/app-config.ts @@ -195,6 +195,7 @@ const AGENT_CLI_ENV_KEYS: ReadonlyMap> = new Map([ 'OPENCODE_TEST_HOME', ])], ['aider', new Set(['AIDER_BIN'])], + ['antigravity', new Set(['AGY_BIN'])], ['claude', new Set(['CLAUDE_CONFIG_DIR', 'CLAUDE_BIN', 'ANTHROPIC_BASE_URL', 'ANTHROPIC_API_KEY', 'ANTHROPIC_AUTH_TOKEN', 'MMD_MODEL_ROUTES_FILE'])], ['codex', new Set(['CODEX_HOME', 'CODEX_BIN', 'OPENAI_BASE_URL', 'CODEX_API_KEY', 'OPENAI_API_KEY'])], ['copilot', new Set(['COPILOT_BIN'])], diff --git a/apps/daemon/src/runtimes/defs/antigravity.ts b/apps/daemon/src/runtimes/defs/antigravity.ts index 58e89cecd9b..089ae2efa6a 100644 --- a/apps/daemon/src/runtimes/defs/antigravity.ts +++ b/apps/daemon/src/runtimes/defs/antigravity.ts @@ -203,7 +203,7 @@ export const antigravityAgentDef = { // composed in server.ts gives a second line of defense for weak // plain-stream models like Gemini 3.5 Flash. buildArgs: ( - _prompt, + prompt, _imagePaths, _extra = [], options = {}, @@ -215,18 +215,6 @@ export const antigravityAgentDef = { runtimeContext.antigravitySettingsPath, ); } - // We invoke agy via `-p -` (print mode + stdin sentinel), NOT - // `chat -`. Verified against `agy --help` on v1.0.3 — the - // `Available subcommands` list is `changelog / help / install / - // plugin / update`, and `chat` is NOT among them. `-p` is the - // documented print-mode flag (`Short alias for --print`) and - // `agy -p -` reads the prompt from stdin. The looper reviewer - // bot's environment runs a different agy build that may have - // renamed the entry point; until upstream confirms a stable - // headless subcommand (see google-antigravity/antigravity-cli#119) - // and the change actually ships in the auto-update channel that - // packaged OD users get, `-p -` is the contract that actually - // produces a print-mode reply on the installed CLI. const args: string[] = []; // Always opt into `--log-file` when the daemon supplied a path so // it can post-exit grep for the actual upstream failure shape @@ -235,19 +223,20 @@ export const antigravityAgentDef = { // never echoes those errors on stdout. See server.ts empty-output // guard for the consumer. // - // Flag order is load-bearing on agy v1.0.3: `agy -p --log-file - // /tmp/x -` runs successfully but leaves /tmp/x empty, while `agy - // --log-file /tmp/x -p -` captures the diagnostic log, including - // `Propagating selected model override to backend: label=""` - // and auth/quota failures. + // Flag order is load-bearing on agy: `agy -p --log-file /tmp/x ` + // runs, while the reverse leaves the log empty. if (runtimeContext.agentLogFilePath) { args.push('--log-file', runtimeContext.agentLogFilePath); } - args.push('-p'); - args.push('-'); + // agy's `-p`/`--print` takes the prompt as a command-line argument; + // it does not read from stdin and has no `-` stdin sentinel. Passing + // the literal `-` (the old behavior) made agy treat the dash as an + // empty prompt and reply "your request was empty or a placeholder + // (-)". Deliver the composed prompt as the `-p` argument instead. + args.push('-p', prompt); return args; }, - promptViaStdin: true, + promptViaStdin: false, streamFormat: 'plain', installUrl: 'https://antigravity.google/cli', docsUrl: 'https://antigravity.google/docs/cli-overview', diff --git a/apps/daemon/src/runtimes/executables.ts b/apps/daemon/src/runtimes/executables.ts index a9b3c46adff..126aea02bd1 100644 --- a/apps/daemon/src/runtimes/executables.ts +++ b/apps/daemon/src/runtimes/executables.ts @@ -16,6 +16,7 @@ const RUNTIME_PROJECT_ROOT = path.resolve( const AGENT_BIN_ENV_KEYS = new Map([ ['amr', 'VELA_BIN'], ['aider', 'AIDER_BIN'], + ['antigravity', 'AGY_BIN'], ['claude', 'CLAUDE_BIN'], ['codebuddy', 'CODEBUDDY_BIN'], ['codex', 'CODEX_BIN'], diff --git a/apps/daemon/tests/runtimes/agent-args.test.ts b/apps/daemon/tests/runtimes/agent-args.test.ts index 7ea22fe079b..138268b90b8 100644 --- a/apps/daemon/tests/runtimes/agent-args.test.ts +++ b/apps/daemon/tests/runtimes/agent-args.test.ts @@ -534,18 +534,18 @@ test('qwen args check promptViaStdin, base args, model args and exclude `-` sent // the daemon would render the resulting empty reply as a "successful" // agent response — exactly the failure mode the auth/quota guard at // server.ts ~12090 is meant to catch but for the wrong reason. -test('antigravity pipes prompt via stdin via -p flag (print mode)', () => { +test('antigravity passes the prompt as the -p argument (print mode)', () => { assert.equal(antigravity.bin, 'agy'); assert.equal(antigravity.streamFormat, 'plain'); - assert.equal(antigravity.promptViaStdin, true); + assert.equal(antigravity.promptViaStdin, false); const args = antigravity.buildArgs('write hello world', [], [], {}, {}); - assert.deepEqual(args, ['-p', '-']); + assert.deepEqual(args, ['-p', 'write hello world']); const argsWithLog = antigravity.buildArgs('write hello world', [], [], {}, { agentLogFilePath: '/tmp/od-agy-test.log', }); - assert.deepEqual(argsWithLog, ['--log-file', '/tmp/od-agy-test.log', '-p', '-']); + assert.deepEqual(argsWithLog, ['--log-file', '/tmp/od-agy-test.log', '-p', 'write hello world']); // No `--model` flag exists upstream, so buildArgs argv must stay the // same regardless of which label the user picks. @@ -560,7 +560,7 @@ test('antigravity pipes prompt via stdin via -p flag (print mode)', () => { antigravitySettingsPath: join(settingsDir, 'settings.json'), }); assert.equal(withModel.includes('--model'), false); - assert.deepEqual(withModel, ['--log-file', '/tmp/od-agy-test.log', '-p', '-']); + assert.deepEqual(withModel, ['--log-file', '/tmp/od-agy-test.log', '-p', 'hi']); } finally { rmSync(settingsDir, { recursive: true, force: true }); } @@ -576,13 +576,13 @@ test('antigravity pipes prompt via stdin via -p flag (print mode)', () => { const followUp = antigravity.buildArgs('next message', [], [], {}, { hasPriorAssistantTurn: true, }); - assert.deepEqual(followUp, ['-p', '-']); + assert.deepEqual(followUp, ['-p', 'next message']); assert.equal(followUp.includes('-c'), false); const firstTurn = antigravity.buildArgs('first', [], [], {}, { hasPriorAssistantTurn: false, }); - assert.deepEqual(firstTurn, ['-p', '-']); + assert.deepEqual(firstTurn, ['-p', 'first']); assert.equal(antigravity.resumesSessionViaCli, undefined); assert.equal(antigravity.maxPromptArgBytes, undefined); From 9bfbe3d916811fd6bafff377092c31a62e417a69 Mon Sep 17 00:00:00 2001 From: Pratik Date: Thu, 23 Jul 2026 22:49:54 +0530 Subject: [PATCH 2/5] fix(daemon): bypass Windows 32kb command line limit via .tmp payload files --- apps/daemon/src/runtimes/defs/antigravity.ts | 41 +++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/apps/daemon/src/runtimes/defs/antigravity.ts b/apps/daemon/src/runtimes/defs/antigravity.ts index 089ae2efa6a..2a870b57825 100644 --- a/apps/daemon/src/runtimes/defs/antigravity.ts +++ b/apps/daemon/src/runtimes/defs/antigravity.ts @@ -209,6 +209,33 @@ export const antigravityAgentDef = { options = {}, runtimeContext = {}, ) => { + if (process.platform === 'win32' && prompt.length > 30000) { + // Workaround: write the massive payload to a temp file and have agy's AI read it + const tmpDir = join(process.cwd(), '.tmp', 'agy_payloads'); + if (!existsSync(tmpDir)) { + mkdirSync(tmpDir, { recursive: true }); + } + const tempPath = join(tmpDir, `od_payload_${Date.now()}.txt`); + writeFileSync(tempPath, prompt, 'utf8'); + + prompt = `Read the file ${tempPath} using your file reading tool. Treat the entire contents of that file as your system instructions and the user's prompt. Execute the instructions inside it exactly, and output the final response exactly as the instructions dictate. Do NOT output anything else.`; + + // We must also inject --dangerously-skip-permissions to allow the read_file tool to work headlessly + const args: string[] = []; + if (options.model && options.model !== DEFAULT_MODEL_OPTION.id) { + writeAntigravityModelSelection( + options.model, + runtimeContext.antigravitySettingsPath, + ); + } + if (runtimeContext.agentLogFilePath) { + args.push('--log-file', runtimeContext.agentLogFilePath); + } + args.push('--dangerously-skip-permissions'); + args.push('-p', prompt); + return args; + } + if (options.model && options.model !== DEFAULT_MODEL_OPTION.id) { writeAntigravityModelSelection( options.model, @@ -216,23 +243,9 @@ export const antigravityAgentDef = { ); } const args: string[] = []; - // Always opt into `--log-file` when the daemon supplied a path so - // it can post-exit grep for the actual upstream failure shape - // (auth missing vs quota reached vs upstream error) — without it - // the chat surfaces a generic "empty response" because print mode - // never echoes those errors on stdout. See server.ts empty-output - // guard for the consumer. - // - // Flag order is load-bearing on agy: `agy -p --log-file /tmp/x ` - // runs, while the reverse leaves the log empty. if (runtimeContext.agentLogFilePath) { args.push('--log-file', runtimeContext.agentLogFilePath); } - // agy's `-p`/`--print` takes the prompt as a command-line argument; - // it does not read from stdin and has no `-` stdin sentinel. Passing - // the literal `-` (the old behavior) made agy treat the dash as an - // empty prompt and reply "your request was empty or a placeholder - // (-)". Deliver the composed prompt as the `-p` argument instead. args.push('-p', prompt); return args; }, From 9ad56707df0665084b2fa0a849c06f7b5779573f Mon Sep 17 00:00:00 2001 From: Pratik Date: Thu, 23 Jul 2026 23:14:45 +0530 Subject: [PATCH 3/5] Revert "fix(daemon): bypass Windows 32kb command line limit via .tmp payload files" This reverts commit 9bfbe3d916811fd6bafff377092c31a62e417a69. --- apps/daemon/src/runtimes/defs/antigravity.ts | 41 +++++++------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/apps/daemon/src/runtimes/defs/antigravity.ts b/apps/daemon/src/runtimes/defs/antigravity.ts index 2a870b57825..089ae2efa6a 100644 --- a/apps/daemon/src/runtimes/defs/antigravity.ts +++ b/apps/daemon/src/runtimes/defs/antigravity.ts @@ -209,33 +209,6 @@ export const antigravityAgentDef = { options = {}, runtimeContext = {}, ) => { - if (process.platform === 'win32' && prompt.length > 30000) { - // Workaround: write the massive payload to a temp file and have agy's AI read it - const tmpDir = join(process.cwd(), '.tmp', 'agy_payloads'); - if (!existsSync(tmpDir)) { - mkdirSync(tmpDir, { recursive: true }); - } - const tempPath = join(tmpDir, `od_payload_${Date.now()}.txt`); - writeFileSync(tempPath, prompt, 'utf8'); - - prompt = `Read the file ${tempPath} using your file reading tool. Treat the entire contents of that file as your system instructions and the user's prompt. Execute the instructions inside it exactly, and output the final response exactly as the instructions dictate. Do NOT output anything else.`; - - // We must also inject --dangerously-skip-permissions to allow the read_file tool to work headlessly - const args: string[] = []; - if (options.model && options.model !== DEFAULT_MODEL_OPTION.id) { - writeAntigravityModelSelection( - options.model, - runtimeContext.antigravitySettingsPath, - ); - } - if (runtimeContext.agentLogFilePath) { - args.push('--log-file', runtimeContext.agentLogFilePath); - } - args.push('--dangerously-skip-permissions'); - args.push('-p', prompt); - return args; - } - if (options.model && options.model !== DEFAULT_MODEL_OPTION.id) { writeAntigravityModelSelection( options.model, @@ -243,9 +216,23 @@ export const antigravityAgentDef = { ); } const args: string[] = []; + // Always opt into `--log-file` when the daemon supplied a path so + // it can post-exit grep for the actual upstream failure shape + // (auth missing vs quota reached vs upstream error) — without it + // the chat surfaces a generic "empty response" because print mode + // never echoes those errors on stdout. See server.ts empty-output + // guard for the consumer. + // + // Flag order is load-bearing on agy: `agy -p --log-file /tmp/x ` + // runs, while the reverse leaves the log empty. if (runtimeContext.agentLogFilePath) { args.push('--log-file', runtimeContext.agentLogFilePath); } + // agy's `-p`/`--print` takes the prompt as a command-line argument; + // it does not read from stdin and has no `-` stdin sentinel. Passing + // the literal `-` (the old behavior) made agy treat the dash as an + // empty prompt and reply "your request was empty or a placeholder + // (-)". Deliver the composed prompt as the `-p` argument instead. args.push('-p', prompt); return args; }, From c9f13d2a5c8c165ffa792816ba0ce3039c92775a Mon Sep 17 00:00:00 2001 From: Pratik Date: Fri, 24 Jul 2026 20:22:17 +0530 Subject: [PATCH 4/5] fix(daemon): switch away from legacy -p STDIN behavior and isolate local agy environment --- apps/daemon/src/runtimes/defs/antigravity.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/daemon/src/runtimes/defs/antigravity.ts b/apps/daemon/src/runtimes/defs/antigravity.ts index 089ae2efa6a..36bee3c5040 100644 --- a/apps/daemon/src/runtimes/defs/antigravity.ts +++ b/apps/daemon/src/runtimes/defs/antigravity.ts @@ -6,7 +6,12 @@ import { } from 'node:fs'; import { readFile as fsReadFile } from 'node:fs/promises'; import { homedir } from 'node:os'; -import { dirname, join } from 'node:path'; +import { dirname, join, delimiter } from 'node:path'; + +const localAgyPath = join(process.cwd(), '.agy'); +if (existsSync(localAgyPath) && !process.env.PATH?.includes(localAgyPath)) { + process.env.PATH = localAgyPath + delimiter + process.env.PATH; +} import { DEFAULT_MODEL_OPTION } from './shared.js'; import type { RuntimeAgentDef } from '../types.js'; @@ -232,11 +237,11 @@ export const antigravityAgentDef = { // it does not read from stdin and has no `-` stdin sentinel. Passing // the literal `-` (the old behavior) made agy treat the dash as an // empty prompt and reply "your request was empty or a placeholder - // (-)". Deliver the composed prompt as the `-p` argument instead. - args.push('-p', prompt); + // (-)". The latest agy 1.1.x versions automatically read from STDIN, + // so we simply omit the -p flag entirely. return args; }, - promptViaStdin: false, + promptViaStdin: true, streamFormat: 'plain', installUrl: 'https://antigravity.google/cli', docsUrl: 'https://antigravity.google/docs/cli-overview', From 677db291f35ba6ef31076a185daae0b56f2c1d1a Mon Sep 17 00:00:00 2001 From: Pratik Date: Fri, 24 Jul 2026 21:10:47 +0530 Subject: [PATCH 5/5] fix(daemon): address review feedback on STDIN tests and PATH mutation --- apps/daemon/src/runtimes/defs/antigravity.ts | 17 ++--------------- apps/daemon/tests/runtimes/agent-args.test.ts | 14 +++++++------- 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/apps/daemon/src/runtimes/defs/antigravity.ts b/apps/daemon/src/runtimes/defs/antigravity.ts index 36bee3c5040..f55a5291799 100644 --- a/apps/daemon/src/runtimes/defs/antigravity.ts +++ b/apps/daemon/src/runtimes/defs/antigravity.ts @@ -6,12 +6,7 @@ import { } from 'node:fs'; import { readFile as fsReadFile } from 'node:fs/promises'; import { homedir } from 'node:os'; -import { dirname, join, delimiter } from 'node:path'; - -const localAgyPath = join(process.cwd(), '.agy'); -if (existsSync(localAgyPath) && !process.env.PATH?.includes(localAgyPath)) { - process.env.PATH = localAgyPath + delimiter + process.env.PATH; -} +import { dirname, join } from 'node:path'; import { DEFAULT_MODEL_OPTION } from './shared.js'; import type { RuntimeAgentDef } from '../types.js'; @@ -208,7 +203,7 @@ export const antigravityAgentDef = { // composed in server.ts gives a second line of defense for weak // plain-stream models like Gemini 3.5 Flash. buildArgs: ( - prompt, + _prompt, _imagePaths, _extra = [], options = {}, @@ -228,17 +223,9 @@ export const antigravityAgentDef = { // never echoes those errors on stdout. See server.ts empty-output // guard for the consumer. // - // Flag order is load-bearing on agy: `agy -p --log-file /tmp/x ` - // runs, while the reverse leaves the log empty. if (runtimeContext.agentLogFilePath) { args.push('--log-file', runtimeContext.agentLogFilePath); } - // agy's `-p`/`--print` takes the prompt as a command-line argument; - // it does not read from stdin and has no `-` stdin sentinel. Passing - // the literal `-` (the old behavior) made agy treat the dash as an - // empty prompt and reply "your request was empty or a placeholder - // (-)". The latest agy 1.1.x versions automatically read from STDIN, - // so we simply omit the -p flag entirely. return args; }, promptViaStdin: true, diff --git a/apps/daemon/tests/runtimes/agent-args.test.ts b/apps/daemon/tests/runtimes/agent-args.test.ts index 138268b90b8..135ea84b5c7 100644 --- a/apps/daemon/tests/runtimes/agent-args.test.ts +++ b/apps/daemon/tests/runtimes/agent-args.test.ts @@ -534,18 +534,18 @@ test('qwen args check promptViaStdin, base args, model args and exclude `-` sent // the daemon would render the resulting empty reply as a "successful" // agent response — exactly the failure mode the auth/quota guard at // server.ts ~12090 is meant to catch but for the wrong reason. -test('antigravity passes the prompt as the -p argument (print mode)', () => { +test('antigravity uses STDIN for the prompt instead of the legacy -p flag', () => { assert.equal(antigravity.bin, 'agy'); assert.equal(antigravity.streamFormat, 'plain'); - assert.equal(antigravity.promptViaStdin, false); + assert.equal(antigravity.promptViaStdin, true); const args = antigravity.buildArgs('write hello world', [], [], {}, {}); - assert.deepEqual(args, ['-p', 'write hello world']); + assert.deepEqual(args, []); const argsWithLog = antigravity.buildArgs('write hello world', [], [], {}, { agentLogFilePath: '/tmp/od-agy-test.log', }); - assert.deepEqual(argsWithLog, ['--log-file', '/tmp/od-agy-test.log', '-p', 'write hello world']); + assert.deepEqual(argsWithLog, ['--log-file', '/tmp/od-agy-test.log']); // No `--model` flag exists upstream, so buildArgs argv must stay the // same regardless of which label the user picks. @@ -560,7 +560,7 @@ test('antigravity passes the prompt as the -p argument (print mode)', () => { antigravitySettingsPath: join(settingsDir, 'settings.json'), }); assert.equal(withModel.includes('--model'), false); - assert.deepEqual(withModel, ['--log-file', '/tmp/od-agy-test.log', '-p', 'hi']); + assert.deepEqual(withModel, ['--log-file', '/tmp/od-agy-test.log']); } finally { rmSync(settingsDir, { recursive: true, force: true }); } @@ -576,13 +576,13 @@ test('antigravity passes the prompt as the -p argument (print mode)', () => { const followUp = antigravity.buildArgs('next message', [], [], {}, { hasPriorAssistantTurn: true, }); - assert.deepEqual(followUp, ['-p', 'next message']); + assert.deepEqual(followUp, []); assert.equal(followUp.includes('-c'), false); const firstTurn = antigravity.buildArgs('first', [], [], {}, { hasPriorAssistantTurn: false, }); - assert.deepEqual(firstTurn, ['-p', 'first']); + assert.deepEqual(firstTurn, []); assert.equal(antigravity.resumesSessionViaCli, undefined); assert.equal(antigravity.maxPromptArgBytes, undefined);