The running dashboard loads the compiled plugin dist, which was stale and
invoked `grok --prompt <text> --format json --directory <cwd>` — flags grok
0.2.93 rejects ("unexpected argument '--prompt'"), yielding a non-zero exit,
no JSON, and an empty "No message" bubble. The source already switched to the
valid `grok -p <text> --output-format json [-m <model>] [--cwd <dir>]`
contract (FN-7790/FN-7796); this rebuilds dist to match.
Also reconcile the FN-7779 test suite: a genuinely empty response is a parsed
`{text:"",stopReason:"EndTurn"}` object, not zero stdout bytes, so the
"stays silent" test now models that shape instead of contradicting the
FN-7796 zero-stdout wrong-binary diagnostic. All 64 plugin tests pass.
Fusion-Task-Id: FN-7779
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Narrative: the streaming-json headless contract intermittently emitted only thought events then stopReason:Cancelled with zero text, leaving Chat replies silently empty; the adapter now spawns grok with --output-format json, buffers stdout, and parses the single JSON response on process close, with streaming-json parsing kept only as a diagnostic fallback.
- Change grok CLI invocation from --output-format streaming-json to --output-format json (cli-stream.ts)
- Add GrokCliJsonResponse type ({text, stopReason, sessionId, requestId, thought}) and parseJsonOutput() to stream-parser.ts, keeping legacy NDJSON line parsing for fallback/diagnostics
- Rework runtime-adapter.ts to buffer full stdout, parse it via parsePromptOutput (JSON object first, NDJSON fallback), and surface a formatTerminalNoTextDiagnostic when a non-EndTurn stopReason yields no assistant text
- Rename first-line/inactivity timeout bookkeeping from line-based to output/chunk-based (FIRST_OUTPUT_TIMEOUT_MS, firstOutputReceived, firstStdoutChunk) since stdout is no longer consumed via readline
- Update cli-stream/runtime-adapter/stream-parser tests to cover the JSON response path and the Cancelled/no-text diagnostic
- Update docs/grok-cli-contract.md and plugin README to document the json output-format contract and diagnostics
- Add changeset fn-7796-grok-cli-reliable-headless.md (patch, fix)
Files changed:
.changeset/fn-7796-grok-cli-reliable-headless.md | 7 +
docs/grok-cli-contract.md | 108 ++++++++-----
plugins/fusion-plugin-grok-runtime/README.md | 16 +-
.../src/__tests__/cli-stream.test.ts | 4 +-
.../src/__tests__/runtime-adapter.test.ts | 73 ++++++++-
.../src/__tests__/stream-parser.test.ts | 80 +++++----
.../fusion-plugin-grok-runtime/src/cli-stream.ts | 14 +-
.../src/runtime-adapter.ts | 180 ++++++++++++---------
.../src/stream-parser.ts | 65 ++++++--
plugins/fusion-plugin-grok-runtime/src/types.ts | 13 +-
10 files changed, 373 insertions(+), 187 deletions(-)
Fusion-Task-Id: FN-7796
Fusion-Task-Lineage: c920fcf0-98f8-42ec-867a-7f76c0aca1b7
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Align the Grok CLI runtime plugin adapter with the real xAI grok CLI stream contract so tool responses are no longer silently dropped, and update tests/docs to match.
- Rework stream-parser.ts to parse the actual grok CLI event/message shape instead of the previously assumed schema
- Trim runtime-adapter.ts and types.ts down to the fields the real CLI contract emits, removing speculative/unsupported fields
- Update cli-stream.ts to match the corrected event handling
- Rewrite runtime-adapter, stream-parser, and cli-stream test suites to exercise the real CLI contract end-to-end
- Update docs/grok-cli-contract.md and plugin README to document the verified contract
- Add changeset for the grok-runtime plugin fix
Files changed:
.changeset/fn-7790-grok-cli-real-contract.md | 7 +
docs/grok-cli-contract.md | 432 +++++++--------------
plugins/fusion-plugin-grok-runtime/README.md | 149 ++-----
.../src/__tests__/cli-stream.test.ts | 22 +-
.../src/__tests__/runtime-adapter.test.ts | 250 ++++--------
.../src/__tests__/stream-parser.test.ts | 108 ++----
.../fusion-plugin-grok-runtime/src/cli-stream.ts | 22 +-
.../src/runtime-adapter.ts | 109 ++----
.../src/stream-parser.ts | 27 +-
plugins/fusion-plugin-grok-runtime/src/types.ts | 104 +----
10 files changed, 338 insertions(+), 892 deletions(-)
Fusion-Task-Id: FN-7790
Fusion-Task-Lineage: 377e86c4-c005-46a5-9eb4-69e858c38b79
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fixes the residual "Grok CLI still returns no message immediately" case where a headless run exits code 0 but never emits any parsed NDJSON event, previously treated as a silent success.
- Detect a code-0 close with zero parsed NDJSON events and surface a diagnostic explaining the likely cause (wrong/unsupported grok binary falling into interactive mode and hitting EOF on stdin).
- Track and emit assistant text/diagnostics via a new appendMessage/emitDiagnosticText path so onText and session.state.errorMessage stay in sync, including on spawn failure and inactivity/first-line timeouts.
- Add first-line/inactivity timeout diagnostics with concrete elapsed-time messaging instead of silent kills.
- Add regression coverage in runtime-adapter.test.ts and grok-runtime-routing.test.ts for the zero-NDJSON exit path.
- Document the contract update in docs/grok-cli-contract.md.
- Add a patch changeset for @runfusion/fusion.
Files changed:
$(cat /tmp/diffstat_fn7788.txt)
Fusion-Task-Id: FN-7788
Fusion-Task-Lineage: dbb238a9-9601-47fc-8a88-40817d749337
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Root-causes the Grok CLI empty-response bug: readline close no longer finalizes the session before the subprocess close event can attach exit code/stderr diagnostics, so failures were silently swallowed as empty assistant messages.
- Wait for subprocess close/error (not readline close) to finalize the Grok CLI session, so non-zero exits can attach stderr before callers inspect the result
- Add GrokSession.state.errorMessage to carry concrete diagnostics (spawn failure, process error, non-zero exit + stderr, or NDJSON error event) through the resolve-never-reject runtime contract
- Track whether any text was received so error diagnostics are only recorded when the run actually produced nothing
- Add a changeset documenting the fix for @runfusion/fusion
- Extend runtime-adapter tests to cover spawn failure, process error, non-zero exit with/without stderr, and NDJSON error-event diagnostics
Files changed:
.changeset/fn-7782-grok-cli-no-response.md | 7 ++
.../src/__tests__/runtime-adapter.test.ts | 98 ++++++++++++++++++++--
.../src/runtime-adapter.ts | 75 +++++++++++++----
plugins/fusion-plugin-grok-runtime/src/types.ts | 1 +
4 files changed, 161 insertions(+), 20 deletions(-)
Fusion-Task-Id: FN-7782
Fusion-Task-Lineage: c2907a70-0556-488f-bda3-132657b64071
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Route grok-cli model selections through the grok CLI runtime when no Fusion-visible GROK_API_KEY is available.
- Add read-only isGrokApiKeyFusionVisible() in packages/core/src/grok-provider.ts, refactored to share user-settings-file reading with hydrateGrokApiKeyFromUserSettings without mutating process.env or logging key material.
- In packages/engine/src/agent-session-helpers.ts, auto-derive the existing "grok" runtimeHint when defaultProvider is grok-cli, no key is Fusion-visible, and the grok plugin runtime is registered; explicit runtime hints and mock/test-mode routing remain unchanged, and the provider-qualified model prefix is stripped before handoff.
- Normalize provider-qualified model ids (grok-cli/<id>, grok/<id>) in the grok-runtime plugin's runtime-adapter and CLI stream spawn so the concrete model reaches `grok --model`, with the historical grok/default fallback preserved for the no-model path.
- Update docs (grok-cli-contract.md, settings-reference.md, plugin README) and add/extend tests covering the new fallback behavior, model normalization, and CLI streaming.
- Add changeset fn-7753-grok-cli-no-key-fallback.md (patch, fix).
Files changed:
.changeset/fn-7753-grok-cli-no-key-fallback.md | 7 ++
docs/grok-cli-contract.md | 83 ++++++++++------
docs/settings-reference.md | 6 +-
.../__tests__/grok-provider-user-settings.test.ts | 46 +++++++++
packages/core/src/grok-provider.ts | 39 +++++++-
packages/core/src/index.gate.ts | 1 +
packages/core/src/index.ts | 1 +
.../src/__tests__/grok-runtime-routing.test.ts | 107 +++++++++++++++++++--
packages/engine/src/agent-session-helpers.ts | 52 +++++++++-
plugins/fusion-plugin-grok-runtime/README.md | 46 +++++----
.../src/__tests__/cli-stream.test.ts | 70 ++++++++++++++
.../src/__tests__/runtime-adapter.test.ts | 28 ++++++
.../fusion-plugin-grok-runtime/src/cli-stream.ts | 6 ++
.../src/runtime-adapter.ts | 24 ++++-
14 files changed, 443 insertions(+), 73 deletions(-)
Fusion-Task-Id: FN-7753
Fusion-Task-Lineage: 30ef7265-1ba9-47fd-8c4e-87b02f6a1d78
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Grok CLI provider readiness now mirrors the Cursor CLI provider: it is derived from the `grok` binary being available rather than requiring a Fusion-visible GROK_API_KEY or ~/.grok/user-settings.json, since the CLI manages its own auth.
- probeGrokBinary now derives `authenticated` from binary availability (readiness) instead of API-key/user-settings presence; key detection surfaces as a non-blocking `apiKeyDetected` hint
- /auth/status treats the grok-cli provider as authenticated when enabled + binary available
- GrokCliProviderCard drops the blocking "Set GROK_API_KEY" state
- Direct xAI streaming path is unchanged and still uses $GROK_API_KEY when present (FN-7711/FN-7714)
- Added changeset for @runfusion/fusion (patch)
Files changed:
$(cat /tmp/diffstat_fn7716.txt)
Fusion-Task-Id: FN-7716
Fusion-Task-Lineage: ac0efc79-2510-465e-9cd2-4938c08989c9
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Documents that GrokRuntimeAdapter.promptWithFallback is an intentional no-op rather than unfinished work, and updates its regression test to assert that contract explicitly.
- Add FNXC:GrokCli comment on promptWithFallback explaining Grok streaming already flows through the pi/xAI OpenAI-compatible path from FN-7711, that the grok CLI has no documented non-interactive prompt/stream subcommand, and that this stub is only reached via an unused runtimeConfig.runtimeHint === "grok" path
- Remove the stale TODO(FN-7705) comment
- Rename/expand the promptWithFallback test to assert the intentional no-op contract (resolves without throwing, returns undefined)
Files changed:
.../src/__tests__/runtime-adapter.test.ts | 11 ++++++++++-
.../fusion-plugin-grok-runtime/src/runtime-adapter.ts | 18 ++++++++++++++++--
2 files changed, 26 insertions(+), 3 deletions(-)
Fusion-Task-Id: FN-7715
Fusion-Task-Lineage: 118639d3-5530-45d5-bc66-de9b1f18fbc4
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fixes the Grok CLI model picker showing raw prompt/preamble text instead of real model names by rewriting parseModelLines to match the actual verified `grok models` output shape.
- Rewrote parseModelLines in process-manager.ts to strip the login/"Default model:"/"Available models:" preamble
- Strip `*`/`-` bullet markers and the `(default)` annotation from each model line
- Preserve existing legacy `id - Label`, columnar, and JSON parsing paths
- Added regression tests covering the real grok models output shape
- Added changeset (patch) documenting the fix
Files changed:
.changeset/fn-7712-grok-model-parse.md | 7 ++++
.../src/__tests__/process-manager.test.ts | 39 ++++++++++++++++++++++
.../src/process-manager.ts | 34 ++++++++++++-------
3 files changed, 68 insertions(+), 12 deletions(-)
Fusion-Task-Id: FN-7712
Fusion-Task-Lineage: 93e34513-07b9-41b3-8b8b-ecdb763b4208
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>