fix(daemon): grok-build — pass prompt inline as -p value, drop stdin#2259
fix(daemon): grok-build — pass prompt inline as -p value, drop stdin#2259srirsiva wants to merge 2 commits into
Conversation
…p stdin Grok Build CLI 0.1.212 enforces `-p, --single <PROMPT>` as a value-requiring flag — invoking with bare `-p` and piping the prompt to stdin now fails with: error: a value is required for '--single <PROMPT>' but none was supplied The previous runtime def used `promptViaStdin: true` + `buildArgs` returning `['-p']`, which only worked against earlier grok builds that read the prompt from stdin when `-p` had no inline value. This change inlines the prompt as the `-p` argument value and flips `promptViaStdin: false`. Linux `MAX_ARG_STRLEN` (128 KB) is enough headroom for typical Open Design prompts; if we ever hit `E2BIG` on a very large brief, a follow-up could shell out to `--prompt-file <tempfile>`. Verified against grok 0.1.212 (b7b8204a4) — single-turn invocations now return clean text replies instead of exit 2.
lefarcen
left a comment
There was a problem hiding this comment.
Hi @srirsiva! 👋 The Summary does a clear job explaining the Grok CLI 0.1.212 flag behavior change and why the daemon needs to stop piping the prompt over stdin.
One quick PR-body tidy-up before pool review: could you add the new template’s Surface area checklist (this touches daemon runtime behavior) and a Validation section with the build/UI checks you already listed? No need to rename the existing Summary — the context there is useful as-is.
|
@lefarcen thanks for the quick read 🙏 Updated the body to follow the template:
Kept the original context (now under Why) so the Grok CLI 0.1.212 flag-behavior explanation isn't lost. Let me know if anything else is missing for pool review. |
| // Grok Build CLI v0.1.212 enforces `-p, --single <PROMPT>` as value- | ||
| // required — stdin piping no longer satisfies it. Inline the prompt. | ||
| // Linux MAX_ARG_STRLEN=128KB headroom is enough for typical OD prompts. | ||
| buildArgs: (prompt, _imagePaths, _extra = [], options = {}) => { |
There was a problem hiding this comment.
Switching buildArgs to [-p, prompt] and promptViaStdin: false moves the full composed OD prompt back onto argv, but this adapter still does not declare a maxPromptArgBytes budget or any prompt-budget regression coverage. That matters because the daemon only preflights argv-bound adapters when maxPromptArgBytes is set (apps/daemon/src/runtimes/prompt-budget.ts), and those composed prompts can include system text, history, skills, and design-system content. In this shape, a large Grok run will regress from the old stdin path to a raw spawn E2BIG/ENAMETOOLONG failure instead of the actionable chat error we already emit for other argv-only adapters like DeepSeek. Please either keep the prompt off argv (for example via a temp --prompt-file shim) or add a conservative maxPromptArgBytes limit plus prompt-budget tests before we rely on inline prompts here.
@mrcfps' review on nexu-io#2259 flagged that moving the Grok Build adapter from the (no-longer-working) stdin path to argv would regress oversized composed prompts from the actionable AGENT_PROMPT_TOO_LARGE error we already emit for DeepSeek to a raw spawn ENAMETOOLONG / E2BIG instead. Fixed by mirroring the DeepSeek argv-budget shape: - grok-build.ts: `maxPromptArgBytes: 30_000` (same headroom as DeepSeek, ~2.7 KB under the Windows CreateProcess 32_767-char cap) so `checkPromptArgvBudget` pre-flights composed prompts (system + history + skills + design-system content + user message) before spawn. - prompt-budget.ts: Grok-Build-specific message — names the `-p / --single` flag, the xAI CLI 0.1.212+ behavior change, and points the user at stdin-capable adapters (claude / codex / hermes) when they need to ship large local context. - Tests: 3 new vitest cases in prompt-budget.test.ts — pin the budget field, exercise the strict-overrun + at-limit + CJK byte-count guards exactly like the DeepSeek regression set, and assert the Grok-named diagnostic copy. New `grokBuild` + `grokBuildMaxPromptArgBytes` helpers exported alongside the existing `deepseek*` ones. All 23 prompt-budget tests pass locally (`pnpm exec vitest run tests/runtimes/prompt-budget.test.ts`).
|
@mrcfps thanks — sharp catch on the prompt-budget regression. Fixed in da51b59:
I deliberately stuck with inline argv + budget rather than pivoting to a |
mrcfps
left a comment
There was a problem hiding this comment.
@srirsiva I re-checked the updated Grok Build runtime changes on da51b5942bd0b38886af6813ad49bd43a172515f: the adapter now passes the prompt inline, restores the argv-budget guard with Grok-specific messaging, and adds focused regression coverage for the prompt-budget path. I also reran pnpm --filter @open-design/daemon exec vitest run tests/runtimes/prompt-budget.test.ts and pnpm --filter @open-design/daemon build, both of which passed locally. Thanks for turning around the follow-up quickly — this looks solid.
|
@mrcfps thanks for the quick re-review and approval! Local Grok Build runs cleanly against PR is still showing |
Why
I hit this myself while wiring Grok Build into a self-hosted Open Design install. The runtime registers fine and shows
available: truein/api/agents, but every single-turn invocation fails immediately with:Grok Build CLI 0.1.212 (
grok 0.1.212 (b7b8204a4)) enforces-p, --single <PROMPT>as a value-requiring flag. Bare-pno longer falls back to stdin —claprejects it before the binary ever reads piped input. The previous runtime def relied on that fallback (promptViaStdin: true+buildArgsreturning['-p']), so every Grok agent run died before it started.What users will see
-p <prompt>is the same canonical form they always accepted; the previous "bare-p+ stdin" path was the looser/non-canonical one.AGENT_PROMPT_TOO_LARGESSE error path DeepSeek already uses, naming the-p / --singleflag and suggesting stdin-capable adapters (claude / codex / hermes) for large-context runs — instead of a generic spawnENAMETOOLONG/E2BIGbanner.Surface area
OD_*env vars +odsubcommands unchanged)RuntimeAgentDefshape change; only per-runtime config values + an extra branch inpromptArgvBudgetMessage)grok -p <prompt>andpromptViaStdin: false. Existing Grok Build users were getting exit 2 100 % of the time, so this is fix-default-broken-state, not a silent UX rewrite.Bug fix verification
curl -fsSL https://x.ai/cli/install.sh | bash. Confirm withgrok --version→grok 0.1.212 (b7b8204a4).error: a value is required for '--single <PROMPT>'.apps/daemon/tests/runtimes/prompt-budget.test.tsmirror the DeepSeek pattern — they go red onmain(nomaxPromptArgBytesdeclared ongrok-build) and green on this branch:grok-build declares a conservative argv-byte budget for the prompt— pins the field is set + under the Windows CreateProcess 32 KB cap.checkPromptArgvBudget flags oversized Grok Build prompts and lets short prompts through— strict-overrun + at-limit + CJK byte-count guards.checkPromptArgvBudget gives Grok-Build-specific guidance for large contexts— pins the-p / --single, "xAI CLI 0.1.212+", and "stdin support" copy.grokbuild to prove the exit-2-vs-clean-reply behavior would need a fixture binary underapps/daemon/tests/fixtures/. Happy to add one if maintainers point me at the preferred shape (e.g. a tiny native or scripted binary that exits 2 when invoked asargv = ['-p']and 0 when invoked asargv = ['-p', 'hi']).Validation
pnpm --filter @open-design/daemon run build→ clean (tsc strict, no diagnostics).pnpm --filter @open-design/daemon exec vitest run tests/runtimes/prompt-budget.test.ts→ 23/23 passed, ~490 ms.apps/daemon/dist/runtimes/defs/grok-build.jscontainsargs = ['-p', prompt],promptViaStdin: false, andmaxPromptArgBytes: 30000.grok -p "say hi in 5 words"→Hi, good to see you(clean exit 0, single-turn reply).OD_PORT=7456, restart user-systemd) — Grok Build agent now returns text instead of exit-2 banner. No regression on adjacent runtimes (claude / codex / opencode / hermes / deepseek / pi still spawn cleanly).spawn ENAMETOOLONGon very large prompts (the new argv-budget guard plus the existingcheckWindowsCmdShimCommandLineBudget/checkWindowsDirectExeCommandLineBudgethelpers should cover it the same way they cover DeepSeek today, but I'm on Linux only).Why not
--prompt-fileinsteadConsidered, but
-p <prompt>is the canonical headless form documented ingrok --helpand matches the Claude Code pattern thatruntimes/defs/claude.tsfollows. With themaxPromptArgBytes: 30_000guard in place (~2.7 KB under the Windows CreateProcess limit, identical to DeepSeek), oversized composed prompts now surface the same actionableAGENT_PROMPT_TOO_LARGEerror DeepSeek emits — pointing the user at stdin-capable adapters (claude / codex / hermes) when they need to ship large local context.--prompt-fileadds tempfile lifecycle (cleanup, errors mid-stream, Windows path quoting) for no behavior win until prompts actually need to exceed the argv budget — at which point the runtime can grow a shim wrapper without changing the public OD surface.🤖 Generated with Claude Code