fix(catalog): route copilot grok-4.6 through responses api

GitHub Copilot serves grok-4.6 / grok-4.6-1m only via /responses, but
isCopilotResponsesModelId matched grok-4.5 exactly, so both the static
generator and dynamic discovery classified grok-4.6 as openai-completions
and requests 400d with unsupported_api_for_model.

- match grok-4.6 in isCopilotResponsesModelId
- add grok-4.6 / grok-4.6-1m to COPILOT_CACHE_INVALIDATED_MODEL_IDS so
  stale cached completion routes drop on refresh
- regenerate github-copilot/grok-4.6 to api openai-responses (compat
  block dropped, xhigh effort added by the responses policy)
- cover discovery routing and cache migration in tests

Fixes #8807
This commit is contained in:
roboomp
2026-08-19 09:27:16 +00:00
parent d94bdfa1bb
commit 565d09b13a
4 changed files with 30 additions and 9 deletions
+1
View File
@@ -14,6 +14,7 @@
- Fixed SuperGrok (`xai-oauth`) Grok 4.6 hiding the thinking-level picker: the Responses effort-capable allowlist now includes `grok-4.6`, so `/model` can select the documented `low`/`medium`/`high`/`xhigh` ladder (`max` is rejected by api.x.ai).
- Marked CoreWeave runtime discovery as authoritative so stale bundled model ids that the endpoint no longer serves stop appearing as selectable models.
- ChatGPT Codex discovery that advertises only worker `-wm` SKUs now also registers the plain model route, so a configured `openai-codex/<model>` keeps resolving instead of fuzzy-falling-back to the `-wm` SKU some accounts reject.
- Fixed GitHub Copilot `grok-4.6` / `grok-4.6-1m` failing with HTTP 400 `unsupported_api_for_model` by routing them through the OpenAI Responses API (`/responses`) instead of `/chat/completions`, matching `grok-4.5`. Stale cached completion routes are invalidated on refresh ([#8807](https://github.com/can1357/oh-my-pi/issues/8807)).
## [17.3.6] - 2026-08-17
+3 -7
View File
@@ -24448,7 +24448,7 @@
"grok-4.6": {
"id": "grok-4.6",
"name": "Grok 4.6",
"api": "openai-completions",
"api": "openai-responses",
"provider": "github-copilot",
"baseUrl": "https://api.githubcopilot.com",
"reasoning": true,
@@ -24468,18 +24468,14 @@
"User-Agent": "opencode/1.3.15",
"X-GitHub-Api-Version": "2026-06-01"
},
"compat": {
"supportsStore": false,
"supportsDeveloperRole": false,
"supportsReasoningEffort": false
},
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high"
"high",
"xhigh"
]
}
},
@@ -5081,8 +5081,18 @@ export interface GithubCopilotModelManagerConfig {
const COPILOT_ANTHROPIC_MODEL_PATTERN = /^claude-(haiku|sonnet|opus|fable|mythos)-\d/;
const isCopilotResponsesModelId = (modelId: string): boolean =>
modelId === "grok-4.5" || modelId.startsWith("gpt-5") || modelId.startsWith("oswe") || modelId.startsWith("mai-");
const COPILOT_CACHE_INVALIDATED_MODEL_IDS = ["grok-4.5", "grok-4.5-1m", "mai-code-1-flash-picker"];
modelId === "grok-4.5" ||
modelId === "grok-4.6" ||
modelId.startsWith("gpt-5") ||
modelId.startsWith("oswe") ||
modelId.startsWith("mai-");
const COPILOT_CACHE_INVALIDATED_MODEL_IDS = [
"grok-4.5",
"grok-4.5-1m",
"grok-4.6",
"grok-4.6-1m",
"mai-code-1-flash-picker",
];
function inferCopilotApi(modelId: string): Api {
if (COPILOT_ANTHROPIC_MODEL_PATTERN.test(modelId)) {
@@ -390,9 +390,23 @@ describe("github copilot model limits mapping", () => {
const model = models.find(candidate => candidate.id === "grok-4.5");
expect(model?.api).toBe("openai-responses");
});
it("routes grok-4.6 to the openai-responses endpoint (#8807)", async () => {
const { models } = await discoverCopilotModels({
data: [
{
id: "grok-4.6",
name: "Grok 4.6",
},
],
});
const model = models.find(candidate => candidate.id === "grok-4.6");
expect(model?.api).toBe("openai-responses");
});
for (const migration of [
{ id: "mai-code-1-flash-picker", name: "MAI-Code-1-Flash" },
{ id: "grok-4.5", name: "Grok 4.5" },
{ id: "grok-4.6", name: "Grok 4.6" },
]) {
it(`refreshes a cached ${migration.name} completion route after the endpoint migration`, async () => {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), `pi-ai-copilot-${migration.id}-cache-`));