From 8e90ce6197297b8ea67660843c1c4788ae1d56e8 Mon Sep 17 00:00:00 2001 From: James Date: Fri, 21 Aug 2026 15:31:40 +0100 Subject: [PATCH] fix(server): alias Grok's product-name model slug to a valid ACP modelId MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Grok's ACP session/set_model only accepts "grok-4.6"/"grok-4.5", but T3 sent "grok-build" verbatim as the default modelId — that's the Grok Build CLI's own product name, not a model id, so every Grok session start failed with "unknown model id" immediately. Add a MODEL_SLUG_ALIASES_BY_PROVIDER entry for the Grok driver, same as Claude and Codex already have for their own display/legacy slugs, so normalizeModelSlug resolves it to "grok-4.6" before it ever reaches the wire. Updated the mock ACP agent used by GrokAdapter's tests to accept "grok-4.6" instead of the never-actually-valid "grok-build", matching what the real Grok ACP accepts. Fixes #7791 --- apps/server/scripts/acp-mock-agent.ts | 6 ++++-- apps/server/src/provider/acp/GrokAcpSupport.test.ts | 7 +++++-- packages/contracts/src/model.ts | 8 ++++++++ packages/shared/src/model.test.ts | 6 ++++++ 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/apps/server/scripts/acp-mock-agent.ts b/apps/server/scripts/acp-mock-agent.ts index bc7828dd8547..23d30cec867d 100644 --- a/apps/server/scripts/acp-mock-agent.ts +++ b/apps/server/scripts/acp-mock-agent.ts @@ -278,15 +278,17 @@ function modeState(): AcpSchema.SessionModeState { }; } +// Mirrors the real Grok ACP: it only accepts "grok-4.6"/"grok-4.5" as +// modelIds, never the CLI's own "grok-build" product name (see #7791). const grokAcpModels: ReadonlyArray = [ - { modelId: "grok-build", name: "Grok Build" }, + { modelId: "grok-4.6", name: "Grok 4.6" }, { modelId: "grok-mock-alt", name: "Grok Mock Alt" }, ]; function modelState(): AcpSchema.SessionModelState { const modelId = grokAcpModels.some((model) => model.modelId === currentModelId) ? currentModelId - : "grok-build"; + : "grok-4.6"; return { currentModelId: modelId, availableModels: grokAcpModels, diff --git a/apps/server/src/provider/acp/GrokAcpSupport.test.ts b/apps/server/src/provider/acp/GrokAcpSupport.test.ts index 02d60976b24c..443cfaee8789 100644 --- a/apps/server/src/provider/acp/GrokAcpSupport.test.ts +++ b/apps/server/src/provider/acp/GrokAcpSupport.test.ts @@ -10,8 +10,11 @@ import { describe("resolveGrokAcpBaseModelId", () => { it("normalizes empty and custom Grok model ids", () => { - expect(resolveGrokAcpBaseModelId(undefined)).toBe("grok-build"); - expect(resolveGrokAcpBaseModelId(" ")).toBe("grok-build"); + // "grok-build" is the CLI's product name, not a modelId its ACP accepts — + // it must resolve to a real model alias, not pass through verbatim. + expect(resolveGrokAcpBaseModelId(undefined)).toBe("grok-4.6"); + expect(resolveGrokAcpBaseModelId(" ")).toBe("grok-4.6"); + expect(resolveGrokAcpBaseModelId("grok-build")).toBe("grok-4.6"); expect(resolveGrokAcpBaseModelId(" grok-test-custom-model ")).toBe("grok-test-custom-model"); }); }); diff --git a/packages/contracts/src/model.ts b/packages/contracts/src/model.ts index 9fcd0d266dd6..290cf4616b7c 100644 --- a/packages/contracts/src/model.ts +++ b/packages/contracts/src/model.ts @@ -211,6 +211,14 @@ export const MODEL_SLUG_ALIASES_BY_PROVIDER: Partial< "opus-4.5-thinking": "claude-opus-4-5", "opus-4.5": "claude-opus-4-5", }, + [GROK_DRIVER_KIND]: { + // "grok-build" is the Grok Build CLI's own product name, not a model id + // its ACP accepts — sending it verbatim as `session/set_model`'s modelId + // fails with "unknown model id". Grok's ACP only knows "grok-4.6" and + // "grok-4.5"; alias the default/display slug to the current one so the + // wire-level id is always valid. + "grok-build": "grok-4.6", + }, [OPENCODE_DRIVER_KIND]: {}, }; diff --git a/packages/shared/src/model.test.ts b/packages/shared/src/model.test.ts index b67c45744734..4bc641c8cbba 100644 --- a/packages/shared/src/model.test.ts +++ b/packages/shared/src/model.test.ts @@ -154,4 +154,10 @@ describe("model slug normalization", () => { expect(normalizeModelSlug("opus", claude)).toBe("claude-opus-5"); expect(normalizeCustomModelSlug(" opus ")).toBe("opus"); }); + + it("aliases Grok's product-name slug to a modelId its ACP accepts", () => { + const grok = ProviderDriverKind.make("grok"); + + expect(normalizeModelSlug("grok-build", grok)).toBe("grok-4.6"); + }); });