diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index 71da18c3..b73499de 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -4,6 +4,7 @@ ### Fixed +- Fixed GitHub Copilot Claude adaptive-thinking effort metadata to match manually checked Copilot model capabilities ([#4637](https://github.com/earendil-works/pi/issues/4637)). - Fixed OpenCode/OpenCode Go completion models that reject `prompt_cache_retention` to omit long-retention cache fields when `cacheRetention` is `long` ([#5702](https://github.com/earendil-works/pi/issues/5702)). ## [0.79.3] - 2026-06-13 diff --git a/packages/ai/scripts/generate-models.ts b/packages/ai/scripts/generate-models.ts index 63c54a56..dfb8f061 100644 --- a/packages/ai/scripts/generate-models.ts +++ b/packages/ai/scripts/generate-models.ts @@ -196,6 +196,14 @@ const OPENCODE_OPENAI_COMPLETIONS_LONG_CACHE_RETENTION_UNSUPPORTED_MODELS = new "opencode-go:kimi-k2.6", ]); +// Checked manually against the authenticated GitHub Copilot /models endpoint on 2026-06-15. +// Keep this to narrow corrections over models.dev metadata instead of snapshotting Copilot's catalog. +const GITHUB_COPILOT_THINKING_LEVEL_OVERRIDES = { + "claude-opus-4.7": { minimal: "low" }, + "claude-opus-4.8": { minimal: "low" }, + "claude-sonnet-4.6": { minimal: "low", xhigh: "max" }, +} satisfies Record["thinkingLevelMap"]>>; + function mergeThinkingLevelMap(model: Model, map: NonNullable["thinkingLevelMap"]>): void { model.thinkingLevelMap = { ...model.thinkingLevelMap, ...map }; } @@ -358,6 +366,12 @@ function applyThinkingLevelMetadata(model: Model): void { // Ring reasons by default. Only high/xhigh have documented explicit effort controls. mergeThinkingLevelMap(model, ANT_LING_RING_THINKING_LEVEL_MAP); } + if (model.provider === "github-copilot") { + const override = GITHUB_COPILOT_THINKING_LEVEL_OVERRIDES[model.id]; + if (override) { + mergeThinkingLevelMap(model, override); + } + } } function getAnthropicMessagesCompat(provider: string, modelId: string): AnthropicMessagesCompat | undefined { diff --git a/packages/ai/src/models.generated.ts b/packages/ai/src/models.generated.ts index 35295e5d..b1d877fa 100644 --- a/packages/ai/src/models.generated.ts +++ b/packages/ai/src/models.generated.ts @@ -4194,7 +4194,7 @@ export const MODELS = { headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"}, compat: {"forceAdaptiveThinking":true,"supportsTemperature":false}, reasoning: true, - thinkingLevelMap: {"xhigh":"xhigh"}, + thinkingLevelMap: {"xhigh":"xhigh","minimal":"low"}, input: ["text", "image"], cost: { input: 5, @@ -4214,7 +4214,7 @@ export const MODELS = { headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"}, compat: {"forceAdaptiveThinking":true,"supportsTemperature":false}, reasoning: true, - thinkingLevelMap: {"xhigh":"xhigh"}, + thinkingLevelMap: {"xhigh":"xhigh","minimal":"low"}, input: ["text", "image"], cost: { input: 5, @@ -4272,6 +4272,7 @@ export const MODELS = { headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"}, compat: {"forceAdaptiveThinking":true}, reasoning: true, + thinkingLevelMap: {"minimal":"low","xhigh":"max"}, input: ["text", "image"], cost: { input: 3, @@ -4831,6 +4832,42 @@ export const MODELS = { contextWindow: 262144, maxTokens: 32768, } satisfies Model<"google-generative-ai">, + "gemma-4-E2B-it": { + id: "gemma-4-E2B-it", + name: "Gemma 4 E2B IT", + api: "google-generative-ai", + provider: "google", + baseUrl: "https://generativelanguage.googleapis.com/v1beta", + reasoning: true, + thinkingLevelMap: {"off":null,"minimal":"MINIMAL","low":null,"medium":null,"high":"HIGH"}, + input: ["text", "image"], + cost: { + input: 0, + output: 0, + cacheRead: 0, + cacheWrite: 0, + }, + contextWindow: 131072, + maxTokens: 8192, + } satisfies Model<"google-generative-ai">, + "gemma-4-E4B-it": { + id: "gemma-4-E4B-it", + name: "Gemma 4 E4B IT", + api: "google-generative-ai", + provider: "google", + baseUrl: "https://generativelanguage.googleapis.com/v1beta", + reasoning: true, + thinkingLevelMap: {"off":null,"minimal":"MINIMAL","low":null,"medium":null,"high":"HIGH"}, + input: ["text", "image"], + cost: { + input: 0, + output: 0, + cacheRead: 0, + cacheWrite: 0, + }, + contextWindow: 131072, + maxTokens: 8192, + } satisfies Model<"google-generative-ai">, }, "google-vertex": { "gemini-1.5-flash": { @@ -9432,13 +9469,13 @@ export const MODELS = { thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"xhigh"}, input: ["text"], cost: { - input: 0.098, - output: 0.196, + input: 0.09, + output: 0.18, cacheRead: 0.02, cacheWrite: 0, }, contextWindow: 1048576, - maxTokens: 4096, + maxTokens: 65536, } satisfies Model<"openai-completions">, "deepseek/deepseek-v4-pro": { id: "deepseek/deepseek-v4-pro", @@ -13304,6 +13341,25 @@ export const MODELS = { contextWindow: 262144, maxTokens: 131000, } satisfies Model<"openai-completions">, + "moonshotai/Kimi-K2.7-Code": { + id: "moonshotai/Kimi-K2.7-Code", + name: "Kimi K2.7 Code", + api: "openai-completions", + provider: "together", + baseUrl: "https://api.together.ai/v1", + compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false,"thinkingFormat":"together"}, + reasoning: true, + thinkingLevelMap: {"minimal":null,"low":null,"medium":null}, + input: ["text"], + cost: { + input: 0.95, + output: 4, + cacheRead: 0.19, + cacheWrite: 0, + }, + contextWindow: 262144, + maxTokens: 131072, + } satisfies Model<"openai-completions">, "nvidia/nemotron-3-ultra-550b-a55b": { id: "nvidia/nemotron-3-ultra-550b-a55b", name: "Nemotron 3 Ultra 550B A55B", diff --git a/packages/ai/test/github-copilot-anthropic.test.ts b/packages/ai/test/github-copilot-anthropic.test.ts index ee3de3e8..ace2bd8f 100644 --- a/packages/ai/test/github-copilot-anthropic.test.ts +++ b/packages/ai/test/github-copilot-anthropic.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it, vi } from "vitest"; -import { getModel } from "../src/models.ts"; +import { getModel, getSupportedThinkingLevels } from "../src/models.ts"; import { streamAnthropic } from "../src/providers/anthropic.ts"; import type { Context } from "../src/types.ts"; @@ -54,6 +54,16 @@ describe("Copilot Claude via Anthropic Messages", () => { messages: [{ role: "user", content: "Hello", timestamp: Date.now() }], }; + it("applies Copilot-specific adaptive thinking effort overrides", () => { + const opus47 = getModel("github-copilot", "claude-opus-4.7"); + expect(opus47.thinkingLevelMap).toMatchObject({ minimal: "low", xhigh: "xhigh" }); + expect(getSupportedThinkingLevels(opus47)).toContain("xhigh"); + + const sonnet46 = getModel("github-copilot", "claude-sonnet-4.6"); + expect(sonnet46.thinkingLevelMap).toMatchObject({ minimal: "low", xhigh: "max" }); + expect(getSupportedThinkingLevels(sonnet46)).toContain("xhigh"); + }); + it("uses Bearer auth, Copilot headers, and valid Anthropic Messages payload", async () => { const model = getModel("github-copilot", "claude-sonnet-4.6"); expect(model.api).toBe("anthropic-messages");