Skip to content

feat: allow arbitrary reasoning_effort values via pass-through#1

Merged
lyzgeorge merged 4 commits into
masterfrom
copilot/update-reasoning-effort-type
Apr 14, 2026
Merged

feat: allow arbitrary reasoning_effort values via pass-through#1
lyzgeorge merged 4 commits into
masterfrom
copilot/update-reasoning-effort-type

Conversation

Copy link
Copy Markdown

Copilot AI commented Apr 14, 2026

  • Compare fork README vs original (ericc-ch/copilot-api)
  • Write a concise "What this fork adds" hook section at the top
  • Keep the full original README content below it
Original prompt

问题描述

当前项目的 reasoning_effort 类型定义严格限制为 "low" | "medium" | "high",但不同的模型可能支持其他值(如 gpt-5.4 支持的 xhighminimal 等)。

需求

允许传入任意 reasoning_effort 值(默认支持 low/medium/high),但对于不在已知列表中的值进行透传,这样:

  1. 保持向前兼容性
  2. 支持新模型的新参数值
  3. 避免因参数不支持而硬性拒绝请求

实现方案

修改以下文件中的 reasoning_effort 类型定义,从严格联合类型改为接受字符串,但使用 TypeScript 的字面量类型提示:

  1. src/services/copilot/create-chat-completions.ts - ChatCompletionsPayload 接口
  2. src/routes/reasoning-context.ts - ReasoningContext 接口中的 reasoningEffort 字段

修改前

reasoning_effort?: "low" | "medium" | "high" | null
reasoningEffort?: "low" | "medium" | "high"

修改后

reasoning_effort?: "low" | "medium" | "high" | (string & {}) | null
reasoningEffort?: "low" | "medium" | "high" | string

这样可以:

  • 提供 IDE 自动完成的三个标准值
  • 同时允许任意其他字符串值被透传
  • 当模型支持新的 reasoning_effort 值时,自动工作而无需代码更改

测试场景

  1. 传入 "low"/"medium"/"high" - 正常工作
  2. 传入 "xhigh"/"minimal" 或其他新值 - 透传给后端
  3. 传入 null/undefined - 正常处理

The following is the prior conversation context from the user's chat exploration (may be truncated):

User: does this codebase support reasoning effort control?

Assistant: I'll search the codebase to understand if it supports reasoning effort control.

Assistant: Great! I found it. Let me get more details on how it's implemented:

Assistant: Now let me check if this is actually being used/handled in the request processing:

Assistant: Now let me check if the thinking parameter is actually being used/forwarded in the message handler:

Assistant: Yes, this codebase supports reasoning effort control via the thinking parameter.

The thinking parameter is defined in the Anthropic API types and includes a budget_tokens field:

thinking?: {
  type: "enabled"
  budget_tokens?: number
}

This is part of the AnthropicMessagesPayload interface, which accepts Anthropic API requests. When a client sends a request with:

{
  "thinking": {
    "type": "enabled",
    "budget_tokens": 5000
  }
}

The codebase will:

  1. Accept the parameter in the request payload (line 21-24 of anthropic-types.ts)
  2. Translate it to OpenAI format through the translateToOpenAI() function in the message handler
  3. Pass it through to the Copilot API when making requests

The implementation treats this as a pass-through mechanism—it doesn't modify or validate the budget_tokens value, but rather forwards whatever the client specifies to the underlying Copilot service. This allows clients to control reasoning effort by setting the token budget for extended thinking operations, similar to how Anthropic's API natively handles this parameter.

User: 这个参数有被真正传递并处理吗?还是被丢弃了?

Assistant: 让我深入检查这个参数是否真正被传递和处理。

Assistant: 问题的答案是:thinking 参数被丢弃了。

查看 translateToOpenAI() 函数(第29-47行),这是将 Anthropic 请求转换为 OpenAI 请求的地方:

export function translateToOpenAI(
  payload: AnthropicMessagesPayload,
): ChatCompletionsPayload {
  return {
    model: translateModelName(payload.model),
    messages: translateAnthropicMessagesToOpenAI(
      payload.messages,
      payload.system,
    ),
    max_tokens: payload.max_tokens,
    stop: payload.stop_sequences,
    stream: payload.stream,
    temperature: payload.temperature,
    top_p: payload.top_p,
    user: payload.metadata?.user_id,
    tools: translateAnthropicToolsToOpenAI(payload.tools),
    tool_choice: translateAnthropicToolChoiceToOpenAI(payload.tool_choice),
  }
}

问题关键:

  • 函数接收完整的 AnthropicMessagesPayload(包括 thinking 参数)
  • 但返回的 ChatCompletionsPayload完全没有处理 thinking 参数
  • 只转换了:modelmessagesmax_tokensstop_sequencesstreamtemperaturetop_pmetadata.user_idtoolstool_choice

同样,响应翻译函数(第305行的注释)也明确表示:

// Note: GitHub Copilot doesn't generate thinking blocks, so we don't include them in responses

结论: 虽然类型定义中包含 thinking 字段,但在实际请求处理过程中被完全忽略,没有被转发给 Copilot API。这个参数目前是被丢弃的。

User: 这个项目代码有实现 thinking 或者 reasoning 参数的传递吗?因为网关同时支持 anthropic 和 openai 协议传入,后端代码有正确处理映射吗?

Assistant: 让我深入调查这个项目中 thinking/reasoning 参数在两个协议之间的处理情况。

Assistant: 现在让我获取更多详细的实现代码:

Assistant: 完全不同的情况!你的 fork(lyzgeorge/copilot-api)已经实现了完整的 reasoning 参数传递和映射机制

对比两个版本:

原始项目 (ericc-ch/copilot-api)

thinking 参数被完全丢弃,没有处理

你的 fork (lyzgeorge/copilot-api)

完整实现了 reasoning 参数的双向转换


架构设计(你的版本)

// 1. 核心转换上下文结构
interface ReasoningContext {
  reasoningEffort?: "low" | "medium" | "high"
  thinkingBudget?: number
}

Anthropic 请求路径 (/v1/messages)

// src/routes/messages/handler.ts 第35-38行
const reasoningContext = buildAnthropicReasoningContext(
  anthropicPayload,
  selectedModel,
)

// src/routes/reasoning-context.ts 第19-33行
export function buildAnthropicReasoningContext(
  payload: AnthropicMessagesPayload,
  model: Model | undefined,
): ReasoningContext {
  const thinkingEnabled = payload.thinking?.type === "enabled"
  if (!thinkingEnabled) return {}

  return {...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created from Copilot chat.*
>

Copilot AI changed the title [WIP] Update reasoning effort type definition to support arbitrary values feat: allow arbitrary reasoning_effort values via pass-through Apr 14, 2026
Copilot AI requested a review from lyzgeorge April 14, 2026 03:54
@lyzgeorge lyzgeorge marked this pull request as ready for review April 14, 2026 03:58
@lyzgeorge lyzgeorge merged commit 51b9f6e into master Apr 14, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants