fix: granular reasoning_effort handling for Claude models (#791)
- github.js: split thinking vs reasoning_effort stripping - thinking (Claude-native format) still stripped for all Claude on Copilot - reasoning_effort now passed through for Opus 4.6 and Sonnet 4.6 - still stripped for Haiku 4.5 and Opus 4.7 (rejected upstream) - reasoning_effort "none" stripped for all models (not all support it) - openai-to-claude.js: map reasoning_effort → thinking.budget_tokens for direct Anthropic backend (none→skip, low→4096, medium→8192, high→16384, xhigh→32768) Previously reasoning_effort was stripped for ALL Claude models, meaning Opus 4.6 via Copilot never received thinking configuration. AI-generated commit by Claude Opus 4.6 (Anthropic)
This commit is contained in:
parent
a331c34eab
commit
58a821d687
2 changed files with 40 additions and 1 deletions
|
|
@ -121,6 +121,19 @@ export class GithubExecutor extends BaseExecutor {
|
||||||
return !/claude/i.test(model);
|
return !/claude/i.test(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reasoning_effort works for GPT-5 family AND Claude Opus 4.6 / Sonnet 4.6
|
||||||
|
// on GitHub Copilot. Only strip for models that don't support it:
|
||||||
|
// Claude Haiku 4.5, Claude Opus 4.7 (rejected upstream).
|
||||||
|
supportsReasoningEffort(model) {
|
||||||
|
const m = model.toLowerCase();
|
||||||
|
// Claude models that DO support reasoning_effort
|
||||||
|
if (/claude.*opus.*4\.6/i.test(m) || /claude.*sonnet.*4\.6/i.test(m)) return true;
|
||||||
|
// All other Claude models: strip
|
||||||
|
if (/claude/i.test(model)) return false;
|
||||||
|
// GPT-5 family, Gemini, etc.: keep
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
transformRequest(model, body, stream, credentials) {
|
transformRequest(model, body, stream, credentials) {
|
||||||
const transformed = { ...body };
|
const transformed = { ...body };
|
||||||
if (this.requiresMaxCompletionTokens(model) && transformed.max_tokens !== undefined) {
|
if (this.requiresMaxCompletionTokens(model) && transformed.max_tokens !== undefined) {
|
||||||
|
|
@ -131,9 +144,16 @@ export class GithubExecutor extends BaseExecutor {
|
||||||
if (!this.supportsTemperature(model) && transformed.temperature !== undefined) {
|
if (!this.supportsTemperature(model) && transformed.temperature !== undefined) {
|
||||||
delete transformed.temperature;
|
delete transformed.temperature;
|
||||||
}
|
}
|
||||||
// Strip thinking/reasoning_effort — unsupported on /chat/completions
|
// Always strip Claude-style thinking payload (Copilot doesn't understand it)
|
||||||
if (!this.supportsThinking(model)) {
|
if (!this.supportsThinking(model)) {
|
||||||
delete transformed.thinking;
|
delete transformed.thinking;
|
||||||
|
}
|
||||||
|
// "none" means no thinking — strip it so models that don't support "none" don't 400
|
||||||
|
if (transformed.reasoning_effort === "none") {
|
||||||
|
delete transformed.reasoning_effort;
|
||||||
|
}
|
||||||
|
// Strip reasoning_effort only for models that reject it
|
||||||
|
if (!this.supportsReasoningEffort(model) && transformed.reasoning_effort !== undefined) {
|
||||||
delete transformed.reasoning_effort;
|
delete transformed.reasoning_effort;
|
||||||
}
|
}
|
||||||
return transformed;
|
return transformed;
|
||||||
|
|
|
||||||
|
|
@ -179,6 +179,25 @@ Respond ONLY with the JSON object, no other text.`);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Map OpenAI reasoning_effort → Claude thinking.budget_tokens
|
||||||
|
// When client sends reasoning_effort (OpenAI format) but no explicit thinking block,
|
||||||
|
// translate to Claude's native format.
|
||||||
|
if (body.reasoning_effort && !result.thinking) {
|
||||||
|
const effortToBudget = {
|
||||||
|
none: 0,
|
||||||
|
low: 4096,
|
||||||
|
medium: 8192,
|
||||||
|
high: 16384,
|
||||||
|
xhigh: 32768,
|
||||||
|
};
|
||||||
|
const budget = effortToBudget[body.reasoning_effort.toLowerCase()];
|
||||||
|
if (budget === 0) {
|
||||||
|
// none → no thinking
|
||||||
|
} else if (budget) {
|
||||||
|
result.thinking = { type: "enabled", budget_tokens: budget };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Attach toolNameMap to result for response translation
|
// Attach toolNameMap to result for response translation
|
||||||
if (toolNameMap.size > 0) {
|
if (toolNameMap.size > 0) {
|
||||||
result._toolNameMap = toolNameMap;
|
result._toolNameMap = toolNameMap;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue