fix: 修复 anthropic 煞笔的四个 bug (#352)

* fix: 移除文件编辑前必须先读取的限制

移除 FileEditTool 和 FileWriteTool 中的 "read before edit" 校验,
允许直接编辑未读取过的文件。保留文件修改过期检测。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs: 更新 teach-me 自动写 note 笔记的功能

* fix: 修复 DeepSeek V4 reasoning_content 回传导致的 400 错误

- 扩大模型名称检测范围,匹配所有 deepseek 模型(V4、R1 等)
- 始终保留 thinking blocks 为 reasoning_content 回传给 API
- 移除有 bug 的 turn boundary 剥离逻辑

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix: Opus 4.6/4.7 默认推理 effort 从 medium 改为 high

Pro 和 Max/Team 订阅者的 Opus 默认 effort 之前被降级为 medium,
导致用户感知模型「变笨」。恢复为 high。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix: 移除 thinkingClearLatched sticky-on 机制

空闲超过 1 小时后 thinkingClearLatched 会被触发且永不重置,
导致每轮 API 调用都清除 thinking 历史。完整移除该 latch 机制,
clearAllThinking 硬编码为 false。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix: 移除 numeric_length_anchors 系统指令

删除「工具调用间文字 ≤25 词、最终回复 ≤100 词」的硬性限制。
ablation 测试显示该约束使整体智能下降 3%。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix: 修复测试中 reasoning_content 类型断言

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
claude-code-best
2026-04-24 20:07:18 +08:00
committed by GitHub
parent 8613d558a8
commit da6d06365d
13 changed files with 98 additions and 163 deletions

View File

@@ -124,14 +124,12 @@ import {
getPromptCache1hAllowlist,
getPromptCache1hEligible,
getSessionId,
getThinkingClearLatched,
setAfkModeHeaderLatched,
setCacheEditingHeaderLatched,
setFastModeHeaderLatched,
setLastMainRequestId,
setPromptCache1hAllowlist,
setPromptCache1hEligible,
setThinkingClearLatched,
} from 'src/bootstrap/state.js'
import {
AFK_MODE_BETA_HEADER,
@@ -1492,20 +1490,6 @@ async function* queryModel(
}
}
// Only latch from agentic queries so a classifier call doesn't flip the
// main thread's context_management mid-turn.
let thinkingClearLatched = getThinkingClearLatched() === true
if (!thinkingClearLatched && isAgenticQuery) {
const lastCompletion = getLastApiCompletionTimestamp()
if (
lastCompletion !== null &&
Date.now() - lastCompletion > CACHE_TTL_1HOUR_MS
) {
thinkingClearLatched = true
setThinkingClearLatched(true)
}
}
const effort = resolveAppliedEffort(options.model, options.effortValue)
if (feature('PROMPT_CACHE_BREAK_DETECTION')) {
@@ -1684,7 +1668,7 @@ async function* queryModel(
const contextManagement = getAPIContextManagement({
hasThinking,
isRedactThinkingActive: betasParams.includes(REDACT_THINKING_BETA_HEADER),
clearAllThinking: thinkingClearLatched,
clearAllThinking: false,
})
const enablePromptCaching =

View File

@@ -100,16 +100,28 @@ describe('isOpenAIThinkingEnabled', () => {
expect(isOpenAIThinkingEnabled('TokenService/deepseek-v3.2')).toBe(true)
})
test('returns false when model name is "deepseek-chat"', () => {
expect(isOpenAIThinkingEnabled('deepseek-chat')).toBe(false)
test('returns true when model name is "deepseek-chat"', () => {
expect(isOpenAIThinkingEnabled('deepseek-chat')).toBe(true)
})
test('returns false when model name is "deepseek-v3"', () => {
expect(isOpenAIThinkingEnabled('deepseek-v3')).toBe(false)
test('returns true when model name is "deepseek-v3"', () => {
expect(isOpenAIThinkingEnabled('deepseek-v3')).toBe(true)
})
test('returns false when model name contains "deepseek" but not "reasoner" or "v3.2"', () => {
expect(isOpenAIThinkingEnabled('deepseek-coder')).toBe(false)
test('returns true when model name is "deepseek-v4"', () => {
expect(isOpenAIThinkingEnabled('deepseek-v4')).toBe(true)
})
test('returns true when model name is "deepseek-v4-pro"', () => {
expect(isOpenAIThinkingEnabled('deepseek-v4-pro')).toBe(true)
})
test('returns true when model name is "deepseek-r1"', () => {
expect(isOpenAIThinkingEnabled('deepseek-r1')).toBe(true)
})
test('returns true when model name contains "deepseek"', () => {
expect(isOpenAIThinkingEnabled('deepseek-coder')).toBe(true)
})
test('returns false when model name is "gpt-4o"', () => {
@@ -126,6 +138,7 @@ describe('isOpenAIThinkingEnabled', () => {
process.env.OPENAI_ENABLE_THINKING = '1'
expect(isOpenAIThinkingEnabled('gpt-4o')).toBe(true)
expect(isOpenAIThinkingEnabled('deepseek-v3')).toBe(true)
expect(isOpenAIThinkingEnabled('qwen-3')).toBe(true)
})
test('OPENAI_ENABLE_THINKING=false disables thinking even for deepseek-reasoner', () => {

View File

@@ -25,9 +25,9 @@ export function isOpenAIThinkingEnabled(model: string): boolean {
if (isEnvDefinedFalsy(process.env.OPENAI_ENABLE_THINKING)) return false
// Explicit enable
if (isEnvTruthy(process.env.OPENAI_ENABLE_THINKING)) return true
// Auto-detect from model name (deepseek-reasoner and DeepSeek-V3.2 support thinking mode)
// Auto-detect from model name (all DeepSeek models support thinking mode)
const modelLower = model.toLowerCase()
return modelLower.includes('deepseek-reasoner') || modelLower.includes('deepseek-v3.2')
return modelLower.includes('deepseek')
}
/**

View File

@@ -6,14 +6,12 @@ export type getFastModeHeaderLatched = any;
export type getLastApiCompletionTimestamp = any;
export type getPromptCache1hAllowlist = any;
export type getPromptCache1hEligible = any;
export type getThinkingClearLatched = any;
export type setAfkModeHeaderLatched = any;
export type setCacheEditingHeaderLatched = any;
export type setFastModeHeaderLatched = any;
export type setLastMainRequestId = any;
export type setPromptCache1hAllowlist = any;
export type setPromptCache1hEligible = any;
export type setThinkingClearLatched = any;
export type addToTotalDurationState = any;
export type consumePostCompaction = any;
export type getIsNonInteractiveSession = any;