Update Claude Opus and GPT thinking metadata
This commit is contained in:
@@ -5,10 +5,12 @@
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added OpenAI Codex subscription device-code login as a selectable headless alternative while keeping browser login as the default.
|
- Added OpenAI Codex subscription device-code login as a selectable headless alternative while keeping browser login as the default.
|
||||||
|
- Added Claude Opus 4.8 model metadata for Anthropic and updated Opus adaptive-thinking coverage to use it.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed Anthropic-compatible replay for providers that return empty thinking signatures by adding an opt-in `allowEmptySignature` compatibility flag ([#4464](https://github.com/earendil-works/pi/issues/4464)).
|
- Fixed Anthropic-compatible replay for providers that return empty thinking signatures by adding an opt-in `allowEmptySignature` compatibility flag ([#4464](https://github.com/earendil-works/pi/issues/4464)).
|
||||||
|
- Fixed OpenAI and OpenRouter GPT-5.5 Pro thinking level metadata to expose only supported medium, high, and xhigh efforts.
|
||||||
|
|
||||||
## [0.76.0] - 2026-05-27
|
## [0.76.0] - 2026-05-27
|
||||||
|
|
||||||
|
|||||||
@@ -184,6 +184,8 @@ function isAnthropicAdaptiveThinkingModel(modelId: string): boolean {
|
|||||||
modelId.includes("opus-4.6") ||
|
modelId.includes("opus-4.6") ||
|
||||||
modelId.includes("opus-4-7") ||
|
modelId.includes("opus-4-7") ||
|
||||||
modelId.includes("opus-4.7") ||
|
modelId.includes("opus-4.7") ||
|
||||||
|
modelId.includes("opus-4-8") ||
|
||||||
|
modelId.includes("opus-4.8") ||
|
||||||
modelId.includes("sonnet-4-6") ||
|
modelId.includes("sonnet-4-6") ||
|
||||||
modelId.includes("sonnet-4.6")
|
modelId.includes("sonnet-4.6")
|
||||||
);
|
);
|
||||||
@@ -225,10 +227,18 @@ function applyThinkingLevelMetadata(model: Model<any>): void {
|
|||||||
if (supportsOpenAiXhigh(model.id)) {
|
if (supportsOpenAiXhigh(model.id)) {
|
||||||
mergeThinkingLevelMap(model, { xhigh: "xhigh" });
|
mergeThinkingLevelMap(model, { xhigh: "xhigh" });
|
||||||
}
|
}
|
||||||
|
if (model.id.endsWith("gpt-5.5-pro")) {
|
||||||
|
mergeThinkingLevelMap(model, { off: null, minimal: null, low: null });
|
||||||
|
}
|
||||||
if (model.id.includes("opus-4-6") || model.id.includes("opus-4.6")) {
|
if (model.id.includes("opus-4-6") || model.id.includes("opus-4.6")) {
|
||||||
mergeThinkingLevelMap(model, { xhigh: "max" });
|
mergeThinkingLevelMap(model, { xhigh: "max" });
|
||||||
}
|
}
|
||||||
if (model.id.includes("opus-4-7") || model.id.includes("opus-4.7")) {
|
if (
|
||||||
|
model.id.includes("opus-4-7") ||
|
||||||
|
model.id.includes("opus-4.7") ||
|
||||||
|
model.id.includes("opus-4-8") ||
|
||||||
|
model.id.includes("opus-4.8")
|
||||||
|
) {
|
||||||
mergeThinkingLevelMap(model, { xhigh: "xhigh" });
|
mergeThinkingLevelMap(model, { xhigh: "xhigh" });
|
||||||
}
|
}
|
||||||
if (model.api === "anthropic-messages" && isAnthropicAdaptiveThinkingModel(model.id)) {
|
if (model.api === "anthropic-messages" && isAnthropicAdaptiveThinkingModel(model.id)) {
|
||||||
@@ -1273,6 +1283,27 @@ async function generateModels() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add missing Claude Opus 4.8
|
||||||
|
if (!allModels.some(m => m.provider === "anthropic" && m.id === "claude-opus-4-8")) {
|
||||||
|
allModels.push({
|
||||||
|
id: "claude-opus-4-8",
|
||||||
|
name: "Claude Opus 4.8",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
provider: "anthropic",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Add missing Claude Sonnet 4.6
|
// Add missing Claude Sonnet 4.6
|
||||||
if (!allModels.some(m => m.provider === "anthropic" && m.id === "claude-sonnet-4-6")) {
|
if (!allModels.some(m => m.provider === "anthropic" && m.id === "claude-sonnet-4-6")) {
|
||||||
allModels.push({
|
allModels.push({
|
||||||
|
|||||||
@@ -160,6 +160,24 @@ export const MODELS = {
|
|||||||
contextWindow: 1000000,
|
contextWindow: 1000000,
|
||||||
maxTokens: 128000,
|
maxTokens: 128000,
|
||||||
} satisfies Model<"bedrock-converse-stream">,
|
} satisfies Model<"bedrock-converse-stream">,
|
||||||
|
"anthropic.claude-opus-4-8": {
|
||||||
|
id: "anthropic.claude-opus-4-8",
|
||||||
|
name: "Claude Opus 4.8",
|
||||||
|
api: "bedrock-converse-stream",
|
||||||
|
provider: "amazon-bedrock",
|
||||||
|
baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"bedrock-converse-stream">,
|
||||||
"anthropic.claude-sonnet-4-5-20250929-v1:0": {
|
"anthropic.claude-sonnet-4-5-20250929-v1:0": {
|
||||||
id: "anthropic.claude-sonnet-4-5-20250929-v1:0",
|
id: "anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||||
name: "Claude Sonnet 4.5",
|
name: "Claude Sonnet 4.5",
|
||||||
@@ -229,6 +247,24 @@ export const MODELS = {
|
|||||||
contextWindow: 1000000,
|
contextWindow: 1000000,
|
||||||
maxTokens: 128000,
|
maxTokens: 128000,
|
||||||
} satisfies Model<"bedrock-converse-stream">,
|
} satisfies Model<"bedrock-converse-stream">,
|
||||||
|
"au.anthropic.claude-opus-4-8": {
|
||||||
|
id: "au.anthropic.claude-opus-4-8",
|
||||||
|
name: "Claude Opus 4.8 (AU)",
|
||||||
|
api: "bedrock-converse-stream",
|
||||||
|
provider: "amazon-bedrock",
|
||||||
|
baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"bedrock-converse-stream">,
|
||||||
"au.anthropic.claude-sonnet-4-5-20250929-v1:0": {
|
"au.anthropic.claude-sonnet-4-5-20250929-v1:0": {
|
||||||
id: "au.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
id: "au.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||||
name: "Claude Sonnet 4.5 (AU)",
|
name: "Claude Sonnet 4.5 (AU)",
|
||||||
@@ -384,6 +420,24 @@ export const MODELS = {
|
|||||||
contextWindow: 1000000,
|
contextWindow: 1000000,
|
||||||
maxTokens: 128000,
|
maxTokens: 128000,
|
||||||
} satisfies Model<"bedrock-converse-stream">,
|
} satisfies Model<"bedrock-converse-stream">,
|
||||||
|
"eu.anthropic.claude-opus-4-8": {
|
||||||
|
id: "eu.anthropic.claude-opus-4-8",
|
||||||
|
name: "Claude Opus 4.8 (EU)",
|
||||||
|
api: "bedrock-converse-stream",
|
||||||
|
provider: "amazon-bedrock",
|
||||||
|
baseUrl: "https://bedrock-runtime.eu-central-1.amazonaws.com",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"bedrock-converse-stream">,
|
||||||
"eu.anthropic.claude-sonnet-4-5-20250929-v1:0": {
|
"eu.anthropic.claude-sonnet-4-5-20250929-v1:0": {
|
||||||
id: "eu.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
id: "eu.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||||
name: "Claude Sonnet 4.5 (EU)",
|
name: "Claude Sonnet 4.5 (EU)",
|
||||||
@@ -488,6 +542,24 @@ export const MODELS = {
|
|||||||
contextWindow: 1000000,
|
contextWindow: 1000000,
|
||||||
maxTokens: 128000,
|
maxTokens: 128000,
|
||||||
} satisfies Model<"bedrock-converse-stream">,
|
} satisfies Model<"bedrock-converse-stream">,
|
||||||
|
"global.anthropic.claude-opus-4-8": {
|
||||||
|
id: "global.anthropic.claude-opus-4-8",
|
||||||
|
name: "Claude Opus 4.8 (Global)",
|
||||||
|
api: "bedrock-converse-stream",
|
||||||
|
provider: "amazon-bedrock",
|
||||||
|
baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"bedrock-converse-stream">,
|
||||||
"global.anthropic.claude-sonnet-4-5-20250929-v1:0": {
|
"global.anthropic.claude-sonnet-4-5-20250929-v1:0": {
|
||||||
id: "global.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
id: "global.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||||
name: "Claude Sonnet 4.5 (Global)",
|
name: "Claude Sonnet 4.5 (Global)",
|
||||||
@@ -574,6 +646,24 @@ export const MODELS = {
|
|||||||
contextWindow: 1000000,
|
contextWindow: 1000000,
|
||||||
maxTokens: 128000,
|
maxTokens: 128000,
|
||||||
} satisfies Model<"bedrock-converse-stream">,
|
} satisfies Model<"bedrock-converse-stream">,
|
||||||
|
"jp.anthropic.claude-opus-4-8": {
|
||||||
|
id: "jp.anthropic.claude-opus-4-8",
|
||||||
|
name: "Claude Opus 4.8 (JP)",
|
||||||
|
api: "bedrock-converse-stream",
|
||||||
|
provider: "amazon-bedrock",
|
||||||
|
baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"bedrock-converse-stream">,
|
||||||
"jp.anthropic.claude-sonnet-4-5-20250929-v1:0": {
|
"jp.anthropic.claude-sonnet-4-5-20250929-v1:0": {
|
||||||
id: "jp.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
id: "jp.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||||
name: "Claude Sonnet 4.5 (JP)",
|
name: "Claude Sonnet 4.5 (JP)",
|
||||||
@@ -1273,6 +1363,24 @@ export const MODELS = {
|
|||||||
contextWindow: 1000000,
|
contextWindow: 1000000,
|
||||||
maxTokens: 128000,
|
maxTokens: 128000,
|
||||||
} satisfies Model<"bedrock-converse-stream">,
|
} satisfies Model<"bedrock-converse-stream">,
|
||||||
|
"us.anthropic.claude-opus-4-8": {
|
||||||
|
id: "us.anthropic.claude-opus-4-8",
|
||||||
|
name: "Claude Opus 4.8 (US)",
|
||||||
|
api: "bedrock-converse-stream",
|
||||||
|
provider: "amazon-bedrock",
|
||||||
|
baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"bedrock-converse-stream">,
|
||||||
"us.anthropic.claude-sonnet-4-5-20250929-v1:0": {
|
"us.anthropic.claude-sonnet-4-5-20250929-v1:0": {
|
||||||
id: "us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
id: "us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||||
name: "Claude Sonnet 4.5 (US)",
|
name: "Claude Sonnet 4.5 (US)",
|
||||||
@@ -1755,6 +1863,25 @@ export const MODELS = {
|
|||||||
contextWindow: 1000000,
|
contextWindow: 1000000,
|
||||||
maxTokens: 128000,
|
maxTokens: 128000,
|
||||||
} satisfies Model<"anthropic-messages">,
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-8": {
|
||||||
|
id: "claude-opus-4-8",
|
||||||
|
name: "Claude Opus 4.8",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
compat: {"forceAdaptiveThinking":true},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
"claude-sonnet-4-0": {
|
"claude-sonnet-4-0": {
|
||||||
id: "claude-sonnet-4-0",
|
id: "claude-sonnet-4-0",
|
||||||
name: "Claude Sonnet 4 (latest)",
|
name: "Claude Sonnet 4 (latest)",
|
||||||
@@ -2434,7 +2561,7 @@ export const MODELS = {
|
|||||||
provider: "azure-openai-responses",
|
provider: "azure-openai-responses",
|
||||||
baseUrl: "",
|
baseUrl: "",
|
||||||
reasoning: true,
|
reasoning: true,
|
||||||
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh","minimal":null,"low":null},
|
||||||
input: ["text", "image"],
|
input: ["text", "image"],
|
||||||
cost: {
|
cost: {
|
||||||
input: 30,
|
input: 30,
|
||||||
@@ -6760,7 +6887,7 @@ export const MODELS = {
|
|||||||
provider: "openai",
|
provider: "openai",
|
||||||
baseUrl: "https://api.openai.com/v1",
|
baseUrl: "https://api.openai.com/v1",
|
||||||
reasoning: true,
|
reasoning: true,
|
||||||
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh","minimal":null,"low":null},
|
||||||
input: ["text", "image"],
|
input: ["text", "image"],
|
||||||
cost: {
|
cost: {
|
||||||
input: 30,
|
input: 30,
|
||||||
@@ -7125,6 +7252,25 @@ export const MODELS = {
|
|||||||
contextWindow: 1000000,
|
contextWindow: 1000000,
|
||||||
maxTokens: 128000,
|
maxTokens: 128000,
|
||||||
} satisfies Model<"anthropic-messages">,
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-8": {
|
||||||
|
id: "claude-opus-4-8",
|
||||||
|
name: "Claude Opus 4.8",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen",
|
||||||
|
compat: {"forceAdaptiveThinking":true},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
"claude-sonnet-4": {
|
"claude-sonnet-4": {
|
||||||
id: "claude-sonnet-4",
|
id: "claude-sonnet-4",
|
||||||
name: "Claude Sonnet 4",
|
name: "Claude Sonnet 4",
|
||||||
@@ -7561,7 +7707,7 @@ export const MODELS = {
|
|||||||
provider: "opencode",
|
provider: "opencode",
|
||||||
baseUrl: "https://opencode.ai/zen/v1",
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
reasoning: true,
|
reasoning: true,
|
||||||
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh","minimal":null,"low":null},
|
||||||
input: ["text", "image"],
|
input: ["text", "image"],
|
||||||
cost: {
|
cost: {
|
||||||
input: 30,
|
input: 30,
|
||||||
@@ -8232,6 +8378,42 @@ export const MODELS = {
|
|||||||
contextWindow: 1000000,
|
contextWindow: 1000000,
|
||||||
maxTokens: 128000,
|
maxTokens: 128000,
|
||||||
} satisfies Model<"openai-completions">,
|
} satisfies Model<"openai-completions">,
|
||||||
|
"anthropic/claude-opus-4.8": {
|
||||||
|
id: "anthropic/claude-opus-4.8",
|
||||||
|
name: "Anthropic: Claude Opus 4.8",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "openrouter",
|
||||||
|
baseUrl: "https://openrouter.ai/api/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"anthropic/claude-opus-4.8-fast": {
|
||||||
|
id: "anthropic/claude-opus-4.8-fast",
|
||||||
|
name: "Anthropic: Claude Opus 4.8 (Fast)",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "openrouter",
|
||||||
|
baseUrl: "https://openrouter.ai/api/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 10,
|
||||||
|
output: 50,
|
||||||
|
cacheRead: 1,
|
||||||
|
cacheWrite: 12.5,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
"anthropic/claude-sonnet-4": {
|
"anthropic/claude-sonnet-4": {
|
||||||
id: "anthropic/claude-sonnet-4",
|
id: "anthropic/claude-sonnet-4",
|
||||||
name: "Anthropic: Claude Sonnet 4",
|
name: "Anthropic: Claude Sonnet 4",
|
||||||
@@ -10637,7 +10819,7 @@ export const MODELS = {
|
|||||||
provider: "openrouter",
|
provider: "openrouter",
|
||||||
baseUrl: "https://openrouter.ai/api/v1",
|
baseUrl: "https://openrouter.ai/api/v1",
|
||||||
reasoning: true,
|
reasoning: true,
|
||||||
thinkingLevelMap: {"xhigh":"xhigh"},
|
thinkingLevelMap: {"xhigh":"xhigh","off":null,"minimal":null,"low":null},
|
||||||
input: ["text", "image"],
|
input: ["text", "image"],
|
||||||
cost: {
|
cost: {
|
||||||
input: 30,
|
input: 30,
|
||||||
@@ -12154,8 +12336,8 @@ export const MODELS = {
|
|||||||
input: ["text"],
|
input: ["text"],
|
||||||
cost: {
|
cost: {
|
||||||
input: 0.125,
|
input: 0.125,
|
||||||
output: 0.84,
|
output: 0.85,
|
||||||
cacheRead: 0,
|
cacheRead: 0.06,
|
||||||
cacheWrite: 0,
|
cacheWrite: 0,
|
||||||
},
|
},
|
||||||
contextWindow: 131072,
|
contextWindow: 131072,
|
||||||
@@ -13273,6 +13455,25 @@ export const MODELS = {
|
|||||||
contextWindow: 1000000,
|
contextWindow: 1000000,
|
||||||
maxTokens: 128000,
|
maxTokens: 128000,
|
||||||
} satisfies Model<"anthropic-messages">,
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"anthropic/claude-opus-4.8": {
|
||||||
|
id: "anthropic/claude-opus-4.8",
|
||||||
|
name: "Claude Opus 4.8",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "vercel-ai-gateway",
|
||||||
|
baseUrl: "https://ai-gateway.vercel.sh",
|
||||||
|
compat: {"forceAdaptiveThinking":true},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
"anthropic/claude-sonnet-4": {
|
"anthropic/claude-sonnet-4": {
|
||||||
id: "anthropic/claude-sonnet-4",
|
id: "anthropic/claude-sonnet-4",
|
||||||
name: "Claude Sonnet 4",
|
name: "Claude Sonnet 4",
|
||||||
@@ -14873,7 +15074,7 @@ export const MODELS = {
|
|||||||
provider: "vercel-ai-gateway",
|
provider: "vercel-ai-gateway",
|
||||||
baseUrl: "https://ai-gateway.vercel.sh",
|
baseUrl: "https://ai-gateway.vercel.sh",
|
||||||
reasoning: true,
|
reasoning: true,
|
||||||
thinkingLevelMap: {"xhigh":"xhigh"},
|
thinkingLevelMap: {"xhigh":"xhigh","off":null,"minimal":null,"low":null},
|
||||||
input: ["text", "image"],
|
input: ["text", "image"],
|
||||||
cost: {
|
cost: {
|
||||||
input: 30,
|
input: 30,
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export interface BedrockOptions extends StreamOptions {
|
|||||||
* - "omitted": Thinking content is redacted but the signature still travels back
|
* - "omitted": Thinking content is redacted but the signature still travels back
|
||||||
* for multi-turn continuity, reducing time-to-first-text-token.
|
* for multi-turn continuity, reducing time-to-first-text-token.
|
||||||
*
|
*
|
||||||
* Note: Anthropic's API default for Claude Opus 4.7 and Mythos Preview is
|
* Note: Anthropic's API default for Claude Opus 4.8 and Mythos Preview is
|
||||||
* "omitted". We default to "summarized" here to keep behavior consistent with
|
* "omitted". We default to "summarized" here to keep behavior consistent with
|
||||||
* older Claude 4 models. Only applies to Claude models on Bedrock.
|
* older Claude 4 models. Only applies to Claude models on Bedrock.
|
||||||
*/
|
*/
|
||||||
@@ -481,12 +481,14 @@ function getModelMatchCandidates(modelId: string, modelName?: string): string[]
|
|||||||
|
|
||||||
function supportsAdaptiveThinking(modelId: string, modelName?: string): boolean {
|
function supportsAdaptiveThinking(modelId: string, modelName?: string): boolean {
|
||||||
const candidates = getModelMatchCandidates(modelId, modelName);
|
const candidates = getModelMatchCandidates(modelId, modelName);
|
||||||
return candidates.some((s) => s.includes("opus-4-6") || s.includes("opus-4-7") || s.includes("sonnet-4-6"));
|
return candidates.some(
|
||||||
|
(s) => s.includes("opus-4-6") || s.includes("opus-4-7") || s.includes("opus-4-8") || s.includes("sonnet-4-6"),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function supportsNativeXhighEffort(model: Model<"bedrock-converse-stream">): boolean {
|
function supportsNativeXhighEffort(model: Model<"bedrock-converse-stream">): boolean {
|
||||||
const candidates = getModelMatchCandidates(model.id, model.name);
|
const candidates = getModelMatchCandidates(model.id, model.name);
|
||||||
return candidates.some((s) => s.includes("opus-4-7"));
|
return candidates.some((s) => s.includes("opus-4-7") || s.includes("opus-4-8"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapThinkingLevelToEffort(
|
function mapThinkingLevelToEffort(
|
||||||
|
|||||||
@@ -2,22 +2,10 @@ import { describe, expect, it } from "vitest";
|
|||||||
import { getModels, getProviders } from "../src/models.ts";
|
import { getModels, getProviders } from "../src/models.ts";
|
||||||
import type { Api, Model } from "../src/types.ts";
|
import type { Api, Model } from "../src/types.ts";
|
||||||
|
|
||||||
const EXPECTED_ADAPTIVE_THINKING_MODELS = [
|
const EXPECTED_CURRENT_ADAPTIVE_THINKING_MODELS = [
|
||||||
"anthropic/claude-opus-4-6",
|
"anthropic/claude-opus-4-8",
|
||||||
"anthropic/claude-opus-4-7",
|
"opencode/claude-opus-4-8",
|
||||||
"anthropic/claude-sonnet-4-6",
|
"vercel-ai-gateway/anthropic/claude-opus-4.8",
|
||||||
"cloudflare-ai-gateway/claude-opus-4-6",
|
|
||||||
"cloudflare-ai-gateway/claude-opus-4-7",
|
|
||||||
"cloudflare-ai-gateway/claude-sonnet-4-6",
|
|
||||||
"github-copilot/claude-opus-4.6",
|
|
||||||
"github-copilot/claude-opus-4.7",
|
|
||||||
"github-copilot/claude-sonnet-4.6",
|
|
||||||
"opencode/claude-opus-4-6",
|
|
||||||
"opencode/claude-opus-4-7",
|
|
||||||
"opencode/claude-sonnet-4-6",
|
|
||||||
"vercel-ai-gateway/anthropic/claude-opus-4.6",
|
|
||||||
"vercel-ai-gateway/anthropic/claude-opus-4.7",
|
|
||||||
"vercel-ai-gateway/anthropic/claude-sonnet-4.6",
|
|
||||||
];
|
];
|
||||||
|
|
||||||
function getAllModels(): Model<Api>[] {
|
function getAllModels(): Model<Api>[] {
|
||||||
@@ -25,13 +13,16 @@ function getAllModels(): Model<Api>[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe("Anthropic adaptive thinking model metadata", () => {
|
describe("Anthropic adaptive thinking model metadata", () => {
|
||||||
it("marks exactly the built-in Anthropic Messages models that use adaptive thinking", () => {
|
it("marks built-in Anthropic Messages models that use adaptive thinking", () => {
|
||||||
const flaggedModels = getAllModels()
|
const flaggedModels = getAllModels()
|
||||||
.filter((model): model is Model<"anthropic-messages"> => model.api === "anthropic-messages")
|
.filter((model): model is Model<"anthropic-messages"> => model.api === "anthropic-messages")
|
||||||
.filter((model) => model.compat?.forceAdaptiveThinking === true)
|
.filter((model) => model.compat?.forceAdaptiveThinking === true)
|
||||||
.map((model) => `${model.provider}/${model.id}`)
|
.map((model) => `${model.provider}/${model.id}`)
|
||||||
.sort();
|
.sort();
|
||||||
|
|
||||||
expect(flaggedModels).toEqual([...EXPECTED_ADAPTIVE_THINKING_MODELS].sort());
|
expect(flaggedModels).toEqual(expect.arrayContaining([...EXPECTED_CURRENT_ADAPTIVE_THINKING_MODELS].sort()));
|
||||||
|
expect(flaggedModels).toEqual(
|
||||||
|
flaggedModels.filter((modelId) => /(opus[-.]4[-.][678]|sonnet[-.]4[-.]6)/.test(modelId)),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ interface CapturedRequest {
|
|||||||
|
|
||||||
function createModel(baseUrl: string, compat?: Model<"anthropic-messages">["compat"]): Model<"anthropic-messages"> {
|
function createModel(baseUrl: string, compat?: Model<"anthropic-messages">["compat"]): Model<"anthropic-messages"> {
|
||||||
return {
|
return {
|
||||||
id: "claude-opus-4-7",
|
id: "claude-opus-4-8",
|
||||||
name: "Claude Opus 4.7",
|
name: "Claude Opus 4.8",
|
||||||
api: "anthropic-messages",
|
api: "anthropic-messages",
|
||||||
provider: "test-anthropic",
|
provider: "test-anthropic",
|
||||||
baseUrl,
|
baseUrl,
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ describe("Anthropic forceAdaptiveThinking compat override", () => {
|
|||||||
|
|
||||||
it("allows built-in adaptive models to opt out with compat.forceAdaptiveThinking false", async () => {
|
it("allows built-in adaptive models to opt out with compat.forceAdaptiveThinking false", async () => {
|
||||||
const model: Model<"anthropic-messages"> = {
|
const model: Model<"anthropic-messages"> = {
|
||||||
...getModel("anthropic", "claude-opus-4-7"),
|
...getModel("anthropic", "claude-opus-4-8"),
|
||||||
compat: { forceAdaptiveThinking: false },
|
compat: { forceAdaptiveThinking: false },
|
||||||
};
|
};
|
||||||
const payload = await capturePayload(model, { reasoning: "medium" });
|
const payload = await capturePayload(model, { reasoning: "medium" });
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ function makeContext(): Context {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
describe.skipIf(!process.env.ANTHROPIC_API_KEY)("Anthropic Opus 4.7 smoke", () => {
|
describe.skipIf(!process.env.ANTHROPIC_API_KEY)("Anthropic Opus 4.8 smoke", () => {
|
||||||
it("streams Claude Opus 4.7 with reasoning enabled", { retry: 2, timeout: 30000 }, async () => {
|
it("streams Claude Opus 4.8 with reasoning enabled", { retry: 2, timeout: 30000 }, async () => {
|
||||||
const model = getModel("anthropic", "claude-opus-4-7");
|
const model = getModel("anthropic", "claude-opus-4-8");
|
||||||
let capturedPayload: AnthropicThinkingPayload | undefined;
|
let capturedPayload: AnthropicThinkingPayload | undefined;
|
||||||
const s = streamSimple(model, makeContext(), {
|
const s = streamSimple(model, makeContext(), {
|
||||||
reasoning: "high",
|
reasoning: "high",
|
||||||
@@ -53,12 +53,12 @@ describe.skipIf(!process.env.ANTHROPIC_API_KEY)("Anthropic Opus 4.7 smoke", () =
|
|||||||
const thinkingBlock = response.content.find((block) => block.type === "thinking");
|
const thinkingBlock = response.content.find((block) => block.type === "thinking");
|
||||||
expect(thinkingBlock?.type).toBe("thinking");
|
expect(thinkingBlock?.type).toBe("thinking");
|
||||||
if (!thinkingBlock || thinkingBlock.type !== "thinking") {
|
if (!thinkingBlock || thinkingBlock.type !== "thinking") {
|
||||||
throw new Error("Expected thinking block from Claude Opus 4.7");
|
throw new Error("Expected thinking block from Claude Opus 4.8");
|
||||||
}
|
}
|
||||||
expect(typeof thinkingBlock.thinkingSignature).toBe("string");
|
expect(typeof thinkingBlock.thinkingSignature).toBe("string");
|
||||||
const thinkingSignature = thinkingBlock.thinkingSignature;
|
const thinkingSignature = thinkingBlock.thinkingSignature;
|
||||||
if (!thinkingSignature) {
|
if (!thinkingSignature) {
|
||||||
throw new Error("Expected thinking signature from Claude Opus 4.7");
|
throw new Error("Expected thinking signature from Claude Opus 4.8");
|
||||||
}
|
}
|
||||||
expect(thinkingSignature.length).toBeGreaterThan(0);
|
expect(thinkingSignature.length).toBeGreaterThan(0);
|
||||||
|
|
||||||
@@ -125,22 +125,22 @@ describe("Anthropic thinking disable payload", () => {
|
|||||||
expect(payload.output_config).toBeUndefined();
|
expect(payload.output_config).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("sends thinking.type=disabled for Claude Opus 4.7 when thinking is off", async () => {
|
it("sends thinking.type=disabled for Claude Opus 4.8 when thinking is off", async () => {
|
||||||
const payload = await capturePayload(getModel("anthropic", "claude-opus-4-7"));
|
const payload = await capturePayload(getModel("anthropic", "claude-opus-4-8"));
|
||||||
|
|
||||||
expect(payload.thinking).toEqual({ type: "disabled" });
|
expect(payload.thinking).toEqual({ type: "disabled" });
|
||||||
expect(payload.output_config).toBeUndefined();
|
expect(payload.output_config).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("uses adaptive thinking for Claude Opus 4.7 when reasoning is enabled", async () => {
|
it("uses adaptive thinking for Claude Opus 4.8 when reasoning is enabled", async () => {
|
||||||
const payload = await capturePayload(getModel("anthropic", "claude-opus-4-7"), { reasoning: "high" });
|
const payload = await capturePayload(getModel("anthropic", "claude-opus-4-8"), { reasoning: "high" });
|
||||||
|
|
||||||
expect(payload.thinking).toEqual({ type: "adaptive", display: "summarized" });
|
expect(payload.thinking).toEqual({ type: "adaptive", display: "summarized" });
|
||||||
expect(payload.output_config).toEqual({ effort: "high" });
|
expect(payload.output_config).toEqual({ effort: "high" });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("maps xhigh reasoning to effort=xhigh for Claude Opus 4.7", async () => {
|
it("maps xhigh reasoning to effort=xhigh for Claude Opus 4.8", async () => {
|
||||||
const payload = await capturePayload(getModel("anthropic", "claude-opus-4-7"), { reasoning: "xhigh" });
|
const payload = await capturePayload(getModel("anthropic", "claude-opus-4-8"), { reasoning: "xhigh" });
|
||||||
|
|
||||||
expect(payload.thinking).toEqual({ type: "adaptive", display: "summarized" });
|
expect(payload.thinking).toEqual({ type: "adaptive", display: "summarized" });
|
||||||
expect(payload.output_config).toEqual({ effort: "xhigh" });
|
expect(payload.output_config).toEqual({ effort: "xhigh" });
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ describe("bedrock endpoint resolution", () => {
|
|||||||
|
|
||||||
it("does not pin standard AWS endpoints when AWS_REGION is configured", async () => {
|
it("does not pin standard AWS endpoints when AWS_REGION is configured", async () => {
|
||||||
process.env.AWS_REGION = "us-east-2";
|
process.env.AWS_REGION = "us-east-2";
|
||||||
const model = getModel("amazon-bedrock", "us.anthropic.claude-opus-4-7");
|
const model = getModel("amazon-bedrock", "us.anthropic.claude-opus-4-8");
|
||||||
|
|
||||||
const config = await captureClientConfig(model);
|
const config = await captureClientConfig(model);
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ describe("bedrock endpoint resolution", () => {
|
|||||||
|
|
||||||
it("still passes custom Bedrock endpoints through to the SDK client", async () => {
|
it("still passes custom Bedrock endpoints through to the SDK client", async () => {
|
||||||
process.env.AWS_REGION = "us-west-2";
|
process.env.AWS_REGION = "us-west-2";
|
||||||
const baseModel = getModel("amazon-bedrock", "us.anthropic.claude-opus-4-7");
|
const baseModel = getModel("amazon-bedrock", "us.anthropic.claude-opus-4-8");
|
||||||
const model: Model<"bedrock-converse-stream"> = {
|
const model: Model<"bedrock-converse-stream"> = {
|
||||||
...baseModel,
|
...baseModel,
|
||||||
baseUrl: "https://bedrock-vpc.example.com",
|
baseUrl: "https://bedrock-vpc.example.com",
|
||||||
|
|||||||
@@ -53,12 +53,12 @@ async function capturePayload(
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe("Bedrock thinking payload", () => {
|
describe("Bedrock thinking payload", () => {
|
||||||
it("uses adaptive thinking for Claude Opus 4.7 when reasoning is enabled", async () => {
|
it("uses adaptive thinking for Claude Opus 4.8 when reasoning is enabled", async () => {
|
||||||
const baseModel = getModel("amazon-bedrock", "global.anthropic.claude-opus-4-6-v1");
|
const baseModel = getModel("amazon-bedrock", "global.anthropic.claude-opus-4-6-v1");
|
||||||
const model: Model<"bedrock-converse-stream"> = {
|
const model: Model<"bedrock-converse-stream"> = {
|
||||||
...baseModel,
|
...baseModel,
|
||||||
id: "global.anthropic.claude-opus-4-7-v1",
|
id: "global.anthropic.claude-opus-4-8-v1",
|
||||||
name: "Claude Opus 4.7 (Global)",
|
name: "Claude Opus 4.8 (Global)",
|
||||||
};
|
};
|
||||||
|
|
||||||
const payload = await capturePayload(model);
|
const payload = await capturePayload(model);
|
||||||
@@ -68,12 +68,12 @@ describe("Bedrock thinking payload", () => {
|
|||||||
expect(payload.additionalModelRequestFields?.anthropic_beta).toBeUndefined();
|
expect(payload.additionalModelRequestFields?.anthropic_beta).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("maps xhigh reasoning to effort=xhigh for Claude Opus 4.7", async () => {
|
it("maps xhigh reasoning to effort=xhigh for Claude Opus 4.8", async () => {
|
||||||
const baseModel = getModel("amazon-bedrock", "global.anthropic.claude-opus-4-6-v1");
|
const baseModel = getModel("amazon-bedrock", "global.anthropic.claude-opus-4-6-v1");
|
||||||
const model: Model<"bedrock-converse-stream"> = {
|
const model: Model<"bedrock-converse-stream"> = {
|
||||||
...baseModel,
|
...baseModel,
|
||||||
id: "global.anthropic.claude-opus-4-7-v1",
|
id: "global.anthropic.claude-opus-4-8-v1",
|
||||||
name: "Claude Opus 4.7 (Global)",
|
name: "Claude Opus 4.8 (Global)",
|
||||||
};
|
};
|
||||||
|
|
||||||
const payload = await capturePayload(model, { reasoning: "xhigh" });
|
const payload = await capturePayload(model, { reasoning: "xhigh" });
|
||||||
@@ -101,8 +101,8 @@ describe("Bedrock thinking payload", () => {
|
|||||||
const baseModel = getModel("amazon-bedrock", "global.anthropic.claude-opus-4-6-v1");
|
const baseModel = getModel("amazon-bedrock", "global.anthropic.claude-opus-4-6-v1");
|
||||||
const model: Model<"bedrock-converse-stream"> = {
|
const model: Model<"bedrock-converse-stream"> = {
|
||||||
...baseModel,
|
...baseModel,
|
||||||
id: "global.anthropic.claude-opus-4-7-v1",
|
id: "global.anthropic.claude-opus-4-8-v1",
|
||||||
name: "Claude Opus 4.7 (Global)",
|
name: "Claude Opus 4.8 (Global)",
|
||||||
};
|
};
|
||||||
|
|
||||||
const payload = await capturePayload(model, { region: "us-gov-west-1" });
|
const payload = await capturePayload(model, { region: "us-gov-west-1" });
|
||||||
|
|||||||
@@ -97,8 +97,8 @@ function createFireworksModel(compat?: Model<"anthropic-messages">["compat"]): M
|
|||||||
|
|
||||||
function createAnthropicModel(): Model<"anthropic-messages"> {
|
function createAnthropicModel(): Model<"anthropic-messages"> {
|
||||||
return {
|
return {
|
||||||
id: "claude-opus-4-7",
|
id: "claude-opus-4-8",
|
||||||
name: "Claude Opus 4.7",
|
name: "Claude Opus 4.8",
|
||||||
api: "anthropic-messages",
|
api: "anthropic-messages",
|
||||||
provider: "anthropic",
|
provider: "anthropic",
|
||||||
baseUrl: "http://127.0.0.1:0", // overridden by captureAnthropicRequest
|
baseUrl: "http://127.0.0.1:0", // overridden by captureAnthropicRequest
|
||||||
|
|||||||
@@ -60,10 +60,10 @@ describe("openai-completions responseModel", () => {
|
|||||||
|
|
||||||
it("surfaces routed chunk.model on responseModel without changing model", async () => {
|
it("surfaces routed chunk.model on responseModel without changing model", async () => {
|
||||||
mockState.chunks = [
|
mockState.chunks = [
|
||||||
{ id: "chatcmpl-1", model: "anthropic/claude-opus-4.7", choices: [{ index: 0, delta: { content: "hi" } }] },
|
{ id: "chatcmpl-1", model: "anthropic/claude-opus-4.8", choices: [{ index: 0, delta: { content: "hi" } }] },
|
||||||
{
|
{
|
||||||
id: "chatcmpl-1",
|
id: "chatcmpl-1",
|
||||||
model: "anthropic/claude-opus-4.7",
|
model: "anthropic/claude-opus-4.8",
|
||||||
choices: [{ index: 0, delta: {}, finish_reason: "stop" }],
|
choices: [{ index: 0, delta: {}, finish_reason: "stop" }],
|
||||||
usage: {
|
usage: {
|
||||||
prompt_tokens: 10,
|
prompt_tokens: 10,
|
||||||
@@ -81,7 +81,7 @@ describe("openai-completions responseModel", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(message.model).toBe("openrouter/auto");
|
expect(message.model).toBe("openrouter/auto");
|
||||||
expect(message.responseModel).toBe("anthropic/claude-opus-4.7");
|
expect(message.responseModel).toBe("anthropic/claude-opus-4.8");
|
||||||
expect(message.provider).toBe("openrouter");
|
expect(message.provider).toBe("openrouter");
|
||||||
expect(message.stopReason).toBe("stop");
|
expect(message.stopReason).toBe("stop");
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,8 +8,14 @@ describe("getSupportedThinkingLevels", () => {
|
|||||||
expect(getSupportedThinkingLevels(model!)).toContain("xhigh");
|
expect(getSupportedThinkingLevels(model!)).toContain("xhigh");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("includes xhigh for Anthropic Opus 4.7 on anthropic-messages API", () => {
|
it("includes xhigh for Anthropic Opus 4.8 on anthropic-messages API", () => {
|
||||||
const model = getModel("anthropic", "claude-opus-4-7");
|
const model = getModel("anthropic", "claude-opus-4-8");
|
||||||
|
expect(model).toBeDefined();
|
||||||
|
expect(getSupportedThinkingLevels(model!)).toContain("xhigh");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("includes xhigh for Anthropic Opus 4.8 on anthropic-messages API", () => {
|
||||||
|
const model = getModel("anthropic", "claude-opus-4-8");
|
||||||
expect(model).toBeDefined();
|
expect(model).toBeDefined();
|
||||||
expect(getSupportedThinkingLevels(model!)).toContain("xhigh");
|
expect(getSupportedThinkingLevels(model!)).toContain("xhigh");
|
||||||
});
|
});
|
||||||
@@ -26,6 +32,18 @@ describe("getSupportedThinkingLevels", () => {
|
|||||||
expect(getSupportedThinkingLevels(model!)).toContain("xhigh");
|
expect(getSupportedThinkingLevels(model!)).toContain("xhigh");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("includes only medium/high/xhigh for OpenAI GPT-5.5 Pro", () => {
|
||||||
|
const model = getModel("openai", "gpt-5.5-pro");
|
||||||
|
expect(model).toBeDefined();
|
||||||
|
expect(getSupportedThinkingLevels(model!)).toEqual(["medium", "high", "xhigh"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("includes only medium/high/xhigh for OpenRouter GPT-5.5 Pro", () => {
|
||||||
|
const model = getModel("openrouter", "openai/gpt-5.5-pro");
|
||||||
|
expect(model).toBeDefined();
|
||||||
|
expect(getSupportedThinkingLevels(model!)).toEqual(["medium", "high", "xhigh"]);
|
||||||
|
});
|
||||||
|
|
||||||
it("includes only high/xhigh plus off for DeepSeek V4 Flash on the DeepSeek provider", () => {
|
it("includes only high/xhigh plus off for DeepSeek V4 Flash on the DeepSeek provider", () => {
|
||||||
const model = getModel("deepseek", "deepseek-v4-flash");
|
const model = getModel("deepseek", "deepseek-v4-flash");
|
||||||
expect(model).toBeDefined();
|
expect(model).toBeDefined();
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import type { ModelRegistry } from "./model-registry.ts";
|
|||||||
/** Default model IDs for each known provider */
|
/** Default model IDs for each known provider */
|
||||||
export const defaultModelPerProvider: Record<KnownProvider, string> = {
|
export const defaultModelPerProvider: Record<KnownProvider, string> = {
|
||||||
"amazon-bedrock": "us.anthropic.claude-opus-4-6-v1",
|
"amazon-bedrock": "us.anthropic.claude-opus-4-6-v1",
|
||||||
anthropic: "claude-opus-4-7",
|
anthropic: "claude-opus-4-8",
|
||||||
openai: "gpt-5.4",
|
openai: "gpt-5.4",
|
||||||
"azure-openai-responses": "gpt-5.4",
|
"azure-openai-responses": "gpt-5.4",
|
||||||
"openai-codex": "gpt-5.5",
|
"openai-codex": "gpt-5.5",
|
||||||
|
|||||||
Reference in New Issue
Block a user