diff --git a/docs/grok-cli-contract.md b/docs/grok-cli-contract.md index c1b4f1befc..76a0055c17 100644 --- a/docs/grok-cli-contract.md +++ b/docs/grok-cli-contract.md @@ -32,12 +32,13 @@ The previously documented https://github.com/superagent-ai/grok-cli contract is Fusion's `GrokRuntimeAdapter` drives Grok as an ACP (Agent Client Protocol) agent over JSON-RPC/stdio, following [xAI Headless & Scripting](https://docs.x.ai/build/cli/headless-scripting#acp): ```bash -# Official automation shape (docs.x.ai): suppress update checks in CI/scripts -grok --no-auto-update agent stdio +grok agent stdio # with optional model + session skills plugin: -grok --no-auto-update agent --plugin-dir -m grok-4.6 stdio +grok agent --plugin-dir -m grok-4.6 stdio ``` +xAI's [Headless & Scripting docs](https://docs.x.ai/build/cli/headless-scripting#acp) suggest `--no-auto-update`, but released Grok CLI v1.0.0 exits with "unexpected argument" when it is passed. Fusion therefore defaults it OFF and exposes it only as the opt-in `buildGrokAcpArgs({ noAutoUpdate: true })` argument, which prepends the flag before `agent`. + ACP session lifecycle (official contract): 1. `initialize` (protocolVersion 1) diff --git a/packages/engine/src/__tests__/grok-runtime-routing.test.ts b/packages/engine/src/__tests__/grok-runtime-routing.test.ts index 5ce2248995..bcc51384ac 100644 --- a/packages/engine/src/__tests__/grok-runtime-routing.test.ts +++ b/packages/engine/src/__tests__/grok-runtime-routing.test.ts @@ -230,12 +230,16 @@ describe("Grok CLI runtime routing (FN-7725)", () => { expect(result.runtimeId).toBe("grok"); expect(result.wasConfigured).toBe(true); expect(mockCreateFnAgent).not.toHaveBeenCalled(); - // FNXC:GrokAcp 2026-07-11-14:00 / 15:00: ACP args include --no-auto-update - // (official headless scripting docs), session-scoped --plugin-dir for Fusion - // skills, then stdio (optional -m when a model is set). + /* + FNXC:GrokAcp 2026-08-15-12:41: + Default ACP argv omits `--no-auto-update` because released Grok CLI v1.0.0 + rejects it as an unexpected argument. The flag remains an explicit opt-in; + session argv starts with agent, scopes Fusion skills by --plugin-dir, may add + -m, and ends with stdio. + */ const acpArgs = settingsOut[0]?.acpArgs as string[]; - expect(acpArgs).toContain("--no-auto-update"); - expect(acpArgs).toContain("agent"); + expect(acpArgs).not.toContain("--no-auto-update"); + expect(acpArgs[0]).toBe("agent"); expect(acpArgs).toContain("--plugin-dir"); expect(acpArgs.at(-1)).toBe("stdio"); diff --git a/plugins/fusion-plugin-grok-runtime/src/__tests__/acp-settings.test.ts b/plugins/fusion-plugin-grok-runtime/src/__tests__/acp-settings.test.ts index 587a63ec22..a938f0d4bc 100644 --- a/plugins/fusion-plugin-grok-runtime/src/__tests__/acp-settings.test.ts +++ b/plugins/fusion-plugin-grok-runtime/src/__tests__/acp-settings.test.ts @@ -13,6 +13,7 @@ describe("acp-settings", () => { // --no-auto-update is opt-in only; the released Grok CLI does not support it. expect(buildGrokAcpArgs()).toEqual(["agent", "stdio"]); expect(buildGrokAcpArgs({})).toEqual(["agent", "stdio"]); + expect(buildGrokAcpArgs({ noAutoUpdate: false })).toEqual(["agent", "stdio"]); expect(buildGrokAcpArgs({ noAutoUpdate: true })).toEqual(["--no-auto-update", "agent", "stdio"]); }); @@ -58,6 +59,7 @@ describe("acp-settings", () => { const settings = buildGrokAcpRuntimeSettings({ binary: "/usr/local/bin/grok", model: "grok-cli/grok-4.5" }); expect(settings.acpBinaryPath).toBe("/usr/local/bin/grok"); expect(settings.acpArgs).toEqual(["agent", "-m", "grok-4.5", "stdio"]); + expect(settings.acpArgs).not.toContain("--no-auto-update"); expect(settings.acpEnvAllowList).toEqual([...GROK_ACP_ENV_ALLOWLIST]); expect(settings.acpFsRead).toBe(false); expect(settings.acpFsWrite).toBe(false); diff --git a/plugins/fusion-plugin-grok-runtime/src/__tests__/runtime-adapter.test.ts b/plugins/fusion-plugin-grok-runtime/src/__tests__/runtime-adapter.test.ts index 0763b8e777..1a035befee 100644 --- a/plugins/fusion-plugin-grok-runtime/src/__tests__/runtime-adapter.test.ts +++ b/plugins/fusion-plugin-grok-runtime/src/__tests__/runtime-adapter.test.ts @@ -64,6 +64,11 @@ function makeFakeAcpAdapter(overrides?: { } describe("GrokRuntimeAdapter (ACP)", () => { + /* + FNXC:GrokAcp 2026-08-15-12:41: + Grok CLI v1.0.0 rejects `--no-auto-update`, so default ACP sessions must + omit it. The low-level argv builder retains the flag as an explicit opt-in. + */ it("creates a session with default model fallback", async () => { const settingsOut: Record[] = []; const adapter = new GrokRuntimeAdapter({ createAcpAdapter: makeFakeAcpAdapter({ settingsOut }) }); @@ -71,7 +76,7 @@ describe("GrokRuntimeAdapter (ACP)", () => { expect(result.session.model).toBe("grok/default"); expect(result.session.systemPrompt).toBe("sys"); const args = settingsOut[0]?.acpArgs as string[]; - expect(args).toContain("--no-auto-update"); + expect(args).not.toContain("--no-auto-update"); expect(args).toContain("agent"); expect(args).toContain("--plugin-dir"); expect(args.at(-1)).toBe("stdio"); @@ -85,12 +90,13 @@ describe("GrokRuntimeAdapter (ACP)", () => { expect(session.model).toBe("grok-4.5"); expect(settingsOut[0]?.acpBinaryPath).toBe("grok"); const args = settingsOut[0]?.acpArgs as string[]; - expect(args).toContain("--no-auto-update"); + expect(args).not.toContain("--no-auto-update"); expect(args).toContain("--plugin-dir"); expect(args).toEqual(expect.arrayContaining(["-m", "grok-4.5", "stdio"])); - // plugin-dir precedes model flag; no-auto-update precedes agent - expect(args.indexOf("--no-auto-update")).toBeLessThan(args.indexOf("agent")); + // Agent leads the argv; plugin-dir precedes the selected model. + expect(args[0]).toBe("agent"); expect(args.indexOf("--plugin-dir")).toBeLessThan(args.indexOf("-m")); + expect(args.at(-1)).toBe("stdio"); }); it("forwards operator MCP servers and Fusion custom tools into createSession", async () => {