@sagentlab/navarch-runtime 0.1.86 → 0.1.87

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/README.md CHANGED
@@ -691,6 +691,14 @@ post-tool answer as the report, and reads aggregate `input_tokens` and
691
691
  `output_tokens` from the terminal `result` event. Gemini does not report USD
692
692
  cost, so an unknown value remains absent rather than becoming zero.
693
693
 
694
+ Gemini's native sandbox launcher converts piped stdin back into a `--prompt`
695
+ argument for its child. The adapter rejects prompts of 128 KiB or more when
696
+ that sandbox is enabled, with an explicit diagnostic; reducing context or
697
+ selecting another runtime preserves the worktree boundary. Navarch Docker
698
+ mode disables the nested Gemini sandbox by default and can still pipe larger
699
+ prompts. All Gemini runs reject prompts above 8 MiB because Gemini's stdin
700
+ reader silently truncates input beyond that limit. These checks use UTF-8 bytes.
701
+
694
702
  The OpenCode adapter uses `opencode run --format json` with the prompt on
695
703
  stdin, and normalizes `text` and `step_finish` JSONL events into
696
704
  the shared report/token/cost boundary. It translates the lease MCP document
@@ -722,6 +730,9 @@ rejects any single argv or environment string over 128 KiB
722
730
  (`MAX_ARG_STRLEN`), so an argv prompt made large review sessions fail with
723
731
  `spawn E2BIG` before the agent started. Docker-mode sessions forward the same
724
732
  stdin through `docker exec -i`.
733
+ Gemini's own sandbox relaunch is an exception to this transport guarantee,
734
+ as described above; moving the initial spawn to stdin does not remove its
735
+ internal argv limit.
725
736
 
726
737
  ## Architecture
727
738
 
@@ -16,10 +16,20 @@ const kill_agent_cjs_1 = require("../kill-agent.cjs");
16
16
  * temporary system-settings file and restricts the run to those server names.
17
17
  *
18
18
  * The prompt arrives on stdin rather than `--prompt`: Gemini runs headlessly
19
- * whenever stdin is not a TTY and uses the piped text as the prompt, and
20
- * Linux rejects any single argv string over 128 KiB (`spawn E2BIG`).
19
+ * whenever stdin is not a TTY and uses the piped text as the prompt. Its
20
+ * native sandbox puts stdin back into argv, so that path still has Linux's
21
+ * 128 KiB per-string limit. Gemini also caps stdin at 8 MiB.
21
22
  */
22
23
  async function runGeminiAdapter(options) {
24
+ if (options.signal?.aborted) {
25
+ return { exitCode: null, timedOut: false, killedByLeaseLoss: true, stdout: "", stderr: "" };
26
+ }
27
+ const promptBytes = Buffer.byteLength(options.prompt, "utf8");
28
+ // Gemini's readStdin() silently truncates at 8 MiB. Reject before any
29
+ // settings writes or process launch rather than execute a partial task.
30
+ if (promptBytes > 8 * 1024 * 1024) {
31
+ return inputFailure(`Gemini CLI stdin is limited to 8 MiB; the task prompt is ${promptBytes} bytes. Reduce the context bundle or select another runtime.`);
32
+ }
23
33
  const args = [];
24
34
  const env = { ...options.env };
25
35
  if (!hasArg(options.extraArgs, "--output-format", "-o")) {
@@ -57,12 +67,41 @@ async function runGeminiAdapter(options) {
57
67
  args.push(...options.extraArgs);
58
68
  if (options.model)
59
69
  args.push("--model", options.model);
70
+ // Gemini's sandbox launcher reads stdin and injects it back into --prompt
71
+ // for its child process (packages/cli/src/gemini.tsx injectStdinIntoArgs).
72
+ // Moving our first spawn's prompt to stdin cannot fix that second spawn.
73
+ // Check the effective flag, including operator overrides, without disabling
74
+ // the worktree guard. Even on macOS a Docker sandbox may launch on Linux.
75
+ if (geminiSandboxEnabled(args) && promptBytes >= 128 * 1024) {
76
+ return inputFailure(`Gemini CLI re-encodes stdin as --prompt when launching its native sandbox; the ${promptBytes}-byte task prompt exceeds Linux's argv limit. Reduce the context bundle or select another runtime that supports large prompts in its sandbox.`);
77
+ }
60
78
  const runOptions = { ...options, env };
61
79
  const raw = runOptions.dockerExec
62
80
  ? await runViaDocker(runOptions, args)
63
81
  : await runOnHost(runOptions, args);
64
82
  return attachGeminiOutput(raw);
65
83
  }
84
+ function inputFailure(stderr) {
85
+ return { exitCode: 1, timedOut: false, killedByLeaseLoss: false, stdout: "", stderr };
86
+ }
87
+ function geminiSandboxEnabled(args) {
88
+ // There is always a generated --sandbox flag unless extraArgs supplies one.
89
+ // Like yargs, later explicit values override earlier ones.
90
+ let enabled = false;
91
+ for (let index = 0; index < args.length; index++) {
92
+ const arg = args[index];
93
+ if (arg === "--sandbox" || arg === "-s") {
94
+ enabled = args[index + 1] !== "false";
95
+ }
96
+ else if (arg.startsWith("--sandbox=") || arg.startsWith("-s=")) {
97
+ enabled = arg.slice(arg.indexOf("=") + 1) !== "false";
98
+ }
99
+ else if (arg === "--no-sandbox") {
100
+ enabled = false;
101
+ }
102
+ }
103
+ return enabled;
104
+ }
66
105
  function hasArg(args, ...flags) {
67
106
  return args.some((arg) => flags.some((flag) => arg === flag || arg.startsWith(`${flag}=`)));
68
107
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sagentlab/navarch-runtime",
3
- "version": "0.1.86",
3
+ "version": "0.1.87",
4
4
  "description": "Navarch machine-side session manager: claims delivery tasks and runs them through local coding agents.",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",