泄露代码里看到的 Claude Code:Think / Extended Thinking 机制详解

18 阅读6分钟

Claude Code意外泄漏51.2万行TS核心代码

来源:github.com/instructkr/…

备份:github.com/GuiminChen/…

Think / Extended Thinking 机制详解

本文档说明本仓库中与 模型侧 Extended Thinking(API thinking 参数)  相关的配置、默认策略、与 Effort / UI / 消息管线 / 上下文管理的关系,并区分 Think Back 插件产品功能。核心类型与开关在 src/utils/thinking.ts,请求组装在 src/services/api/claude.ts 的 queryModel → paramsFromContext


1. 概念:两套「Think」

含义说明
Extended Thinking调用 Anthropic Messages API 时在请求体中设置 thinkingadaptive 或 enabled + budget_tokens),模型在工具/回答前进行可计费或可摘要的推理;响应中带 thinking / redacted_thinking 内容块。
Think Back(/think-back)独立插件与命令(src/commands/thinkback/thinkback-play),生成年终回顾动画等,不是 API extended thinking 开关。

下文默认指 Extended Thinking,除非单独标注 Think Back。


2. 配置类型:ThinkingConfig

定义于 src/utils/thinking.ts

export type ThinkingConfig =
  | { type'adaptive' }           // 逻辑含义:允许走 API 自适应思考(实际下发见 §4)
  | { type'enabled'; budgetTokens: number }  // 非自适应模型下的 token 预算提示
  | { type'disabled' }           // 完全关闭 thinking 请求
  • adaptive / enabled 的 CLI 语义src/main.tsx 在用户传入 --thinking adaptive|enabled 时把 thinkingConfig 设为 { type: 'adaptive' };与 MAX_THINKING_TOKENS--max-thinking-tokens(若存在)等组合时,thinkingEnabled 与 thinkingConfig 会同步更新。
  • 会话内关闭AppState.thinkingEnabled === false 时,REPL 构造的 toolUseContext.options.thinkingConfig 会强制为 { type: 'disabled' }(见 src/screens/REPL.tsx 中 s.thinkingEnabled !== false ? thinkingConfig : { type: 'disabled' })。

3. 默认是否开启:shouldEnableThinkingByDefault()

src/utils/thinking.ts

  1. 若设置环境变量 MAX_THINKING_TOKENS:解析为整数,> 0 视为默认开启 thinking
  2. 否则读合并设置:若 alwaysThinkingEnabled === falsesettings.json / ConfigTool 等,src/utils/settings/types.ts),则默认 关闭
  3. 否则默认 开启(注释要求变更需同步 model launch)。

QueryEngine.submitMessagesrc/QueryEngine.ts)在未传入 thinkingConfig 时,用 shouldEnableThinkingByDefault() !== false 决定初始为 { type: 'adaptive' } 还是 { type: 'disabled' }


4. API 层:何时发 thinking、adaptive 还是 budget

src/services/api/claude.ts 中 paramsFromContext(摘要逻辑):

  1. hasThinkingthinkingConfig.type !== 'disabled' 且  设置 CLAUDE_CODE_DISABLE_THINKING
  2. modelSupportsThinking(model)src/utils/thinking.ts):按 provider(1P / Foundry / Bedrock / Vertex)与 canonical 模型名判断;3P 能力可被 get3PModelCapabilityOverride(model, 'thinking') 覆盖;内部注释警告勿随意改名单。
  3. 若二者满足:
    • 若 CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING 且 modelSupportsAdaptiveThinking(model):请求使用 { type: 'adaptive' }(无 budget)。
    • 否则:使用 { type: 'enabled', budget_tokens },默认 budget 为 getMaxThinkingTokensForModel(model)src/utils/context.tsupperLimit - 1,与 max output 对齐);若 thinkingConfig.type === 'enabled' 且提供了 budgetTokens 则采用用户值,并与 maxOutputTokens - 1 取 min。
  4. 温度hasThinking 为真时不单独下发 temperature(API 在 thinking 开启时期望默认为 1)。

自适应支持modelSupportsAdaptiveThinking:对已知 opus-4-6 / sonnet-4-6 等显式允许;其它 legacy opus/sonnet/haiku 名返回 false;对 未知模型字符串 在 1P / Foundry 上默认 true(注释:避免悄悄降级新模型)。


5. Beta 头:交错思考、脱敏思考、与 UI

src/utils/betas.ts

  • INTERLEAVED_THINKING_BETA_HEADER:未 DISABLE_INTERLEAVED_THINKING 且 modelSupportsISP(model) 时加入。
  • REDACT_THINKING_BETA_HEADER(1P、交互会话):在满足仅 1P beta、modelSupportsISP、非 non-interactive、且 showThinkingSummaries !== true 时加入。效果是 API 返回 redacted_thinking 而非完整 thinking 文本摘要;TUI 用 AssistantRedactedThinkingMessage 显示 stub「✻ Thinking…」,完整内容用 Ctrl+O 展开的场景减少(见 betas.ts 注释)。

交互模式下完整 thinking 的展示:AssistantThinkingMessagesrc/components/messages/AssistantThinkingMessage.tsx)——非 verbose / 非 transcript 时仅显示「∴ Thinking」+ 展开提示;verbose 或 transcript 模式下列出 Markdown 正文。


6. 上下文管理:clear_thinking_20251015

src/services/compact/apiMicrocompact.ts 中 getAPIContextManagement

  • 当 hasThinking 且  处于 redact-thinking(!isRedactThinkingActive)时,加入策略 clear_thinking_20251015
    • 默认 keep: 'all'(保留历史 assistant turn 中的 thinking)。
    • clearAllThinking(见 §7)为 true:keep: { type: 'thinking_turns', value: 1 },只保留最后一轮 thinking,避免长间隔后缓存与 schema 默认行为不一致。

7. 长时间空闲后的「清 thinking」锁存:thinkingClearLatched

src/services/api/claude.ts

  • 仅对 agentic 主路径isAgenticQuery)考虑:若距离上次 API 完成超过约 1 小时(CACHE_TTL_1HOUR_MS),将 thinkingClearLatched 置 true 并写入 bootstrap state(setThinkingClearLatched)。
  • 该标志参与 getAPIContextManagement({ clearAllThinking: thinkingClearLatched }),从而触发 §6 中「只保留最后一轮 thinking」的策略。
  • 设计意图:与 prompt cache / 长 idle 后的上下文策略对齐;且注释说明 classifier 等非 agentic 调用不应误触发锁存。

状态读写:src/bootstrap/state.tsthinkingClearLatched)。


8. 与其它子系统的关系

8.1 Effort 与 Ultrathink

  • Effortsrc/utils/effort.ts):独立 API 参数,决定「任务投入度」;与 thinking 并行存在,claude.ts 中 configureEffortParams 与 thinking 同一次 paramsFromContext 内组装。
  • Ultrathinksrc/utils/thinking.ts):feature('ULTRATHINK') + GrowthBook tengu_turtle_carbon。开启且模型支持 effort 时,getDefaultEffortForModel 等路径可把默认 effort 设为 medium,用户在输入里写 ultrathink 时由 src/utils/attachments.ts 的 getUltrathinkEffortAttachment 附加 ultrathink_effort(level high)并打 tengu_ultrathink 事件;PromptInput 用 findThinkingTriggerPositions / getRainbowColor 做关键词高亮。

8.2 子 Agent / Hook / 侧路查询

  • Fork 子 Agentsrc/tools/AgentTool/runAgent.ts):默认继承父级 toolUseContext.options.thinkingConfiguseExactTools 等分支仍会传入同一 thinking 配置(见文件内注释)。
  • 若干 hook 与辅助查询 显式 thinkingConfig: { type: 'disabled' },避免在分类器、prompt hook、agent hook、API query helper、skill improvement 等路径上浪费 thinking 配额或破坏缓存键预期(src/utils/hooks/*.ts)。
  • sideQuestionsrc/utils/sideQuestion.ts):注释说明 不要覆盖thinkingConfig,因其参与 API cache key

8.3 消息与持久化

  • src/utils/messages.ts:区分 thinking / redacted_thinking; assistant 消息 不能以 thinking 块结尾(API 约束)时有 strip/merge 逻辑;另有去掉签名类 block 的路径供压缩/导出。
  • Token 估算(src/services/tokenEstimation.ts):对 thinking 类 block 使用固定预算常数简化计数。

8.4 分类器(YOLO)

  • src/utils/permissions/yoloClassifier.tsgetClassifierThinkingConfig 可按模型关闭 thinking 或增加 padding,避免分类用小请求触发 thinking。

8.5 Web 搜索子调用

  • src/tools/WebSearchTool/WebSearchTool.ts:使用 Haiku 时可对子查询关闭 thinking,否则跟随 context.options.thinkingConfig

9. UI:ThinkingToggle

src/components/ThinkingToggle.tsx:会话级开关文案为「Claude will think before responding」;若在 对话中途 修改,会先 二次确认(警告延迟与质量风险)。


10. 环境变量与设置速查

变量/设置作用
CLAUDE_CODE_DISABLE_THINKING强制不向 API 发送 thinking(即使 ThinkingConfig 非 disabled)。
CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING有 thinking 时退回 budget 模式而非 adaptive。
DISABLE_INTERLEAVED_THINKING不请求交错 thinking beta。
MAX_THINKING_TOKENS影响默认是否启用 thinking(shouldEnableThinkingByDefault)及 CLI/main 初始化分支。
alwaysThinkingEnabled(settings)false 时默认关闭 thinking。
showThinkingSummariestrue 时可不走 redact-thinking beta,偏向可读的 thinking 摘要路径(见 betas.ts)。

ConfigTool 暴露项见 src/tools/ConfigTool/supportedSettings.ts(含 alwaysThinkingEnabled)。


11. Think Back(插件,非 Extended Thinking)

  • 命令:/think-backthinkback-play 等(src/commands/thinkback/thinkback-play/)。
  • 依赖 Statsig gate tengu_thinkback;通过 Skill 工具调用 thinkback skill 生成动画资源。
  • 与上文的 API thinking 参数 无直接关系;命名上易混淆,故单独列出。

12. 关键源文件索引

主题路径
类型、模型能力、默认开关、Ultrathink feature 标志src/utils/thinking.ts
请求体 thinking + context_management + 空闲锁存src/services/api/claude.ts
clear_thinking_20251015 策略src/services/compact/apiMicrocompact.ts
Beta 头(interleaved / redact)src/utils/betas.ts
Thinking token 上限辅助src/utils/context.tsgetMaxThinkingTokensForModel
主循环初始 thinkingConfigsrc/QueryEngine.ts
REPL 注入 toolUseContext.options.thinkingConfigsrc/screens/REPL.tsx
CLI 启动 --thinking / MAX_THINKING_TOKENSsrc/main.tsx
展示:完整 vs 脱敏AssistantThinkingMessage.tsxAssistantRedactedThinkingMessage.tsx
Ultrathink 输入附件src/utils/attachments.ts
Effort 默认与 ultrathink 交互src/utils/effort.ts

13. 与仓库内其它文档

若存在 SKILLS.md ARCHITECTURE.md,Extended Thinking 属于 模型调用层 横切 concern;Skill 的 effort 与主循环 thinkingConfig 仍独立,需分别在 API 请求中理解。