mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-14 12:02:27 +08:00
fix(claude): 🐛 补齐 thinking block binding beta
Co-authored-by: Wine Fox <fox@ling.plus>
This commit is contained in:
@@ -20,11 +20,12 @@ const (
|
||||
BetaFastMode = "fast-mode-2026-02-01"
|
||||
|
||||
// 新增(对齐官方 CLI 2.1.9x 以来的流量)
|
||||
BetaPromptCachingScope = "prompt-caching-scope-2026-01-05"
|
||||
BetaEffort = "effort-2025-11-24"
|
||||
BetaRedactThinking = "redact-thinking-2026-02-12"
|
||||
BetaContextManagement = "context-management-2025-06-27"
|
||||
BetaExtendedCacheTTL = "extended-cache-ttl-2025-04-11"
|
||||
BetaPromptCachingScope = "prompt-caching-scope-2026-01-05"
|
||||
BetaEffort = "effort-2025-11-24"
|
||||
BetaRedactThinking = "redact-thinking-2026-02-12"
|
||||
BetaContextManagement = "context-management-2025-06-27"
|
||||
BetaThinkingBindingControls = "thinking-binding-controls-2026-08-01"
|
||||
BetaExtendedCacheTTL = "extended-cache-ttl-2025-04-11"
|
||||
|
||||
// server-side refusal fallback beta 字段族(beta Messages API 专有)。
|
||||
// 客户端(Claude Code / SDK / OpenCode 等)会默认透传 body.fallbacks /
|
||||
@@ -99,6 +100,7 @@ func FullClaudeCodeMimicryBetas() []string {
|
||||
BetaPromptCachingScope,
|
||||
BetaEffort,
|
||||
BetaContextManagement,
|
||||
BetaThinkingBindingControls,
|
||||
BetaExtendedCacheTTL,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +114,23 @@ func TestSanitizeAnthropicBodyForBetaTokens_EmptyBody(t *testing.T) {
|
||||
require.Empty(t, out)
|
||||
}
|
||||
|
||||
func TestSanitizeAnthropicBodyForBetaTokens_ThinkingBlockBindingKeptWhenBetaPresent(t *testing.T) {
|
||||
body := []byte(`{"model":"claude-fable-5-1","thinking":{"type":"adaptive","display":"summarized","block_binding":{"prefix_mismatch_behavior":"drop_block"}},"messages":[]}`)
|
||||
out, changed := sanitizeAnthropicBodyForBetaTokens(body, claude.BetaThinkingBindingControls)
|
||||
require.False(t, changed)
|
||||
require.Equal(t, "drop_block",
|
||||
gjson.GetBytes(out, "thinking.block_binding.prefix_mismatch_behavior").String())
|
||||
}
|
||||
|
||||
func TestSanitizeAnthropicBodyForBetaTokens_ThinkingBlockBindingStrippedWhenBetaMissing(t *testing.T) {
|
||||
body := []byte(`{"model":"claude-fable-5-1","thinking":{"type":"adaptive","display":"summarized","block_binding":{"prefix_mismatch_behavior":"drop_block"}},"messages":[]}`)
|
||||
out, changed := sanitizeAnthropicBodyForBetaTokens(body, claude.BetaContextManagement)
|
||||
require.True(t, changed)
|
||||
require.False(t, gjson.GetBytes(out, "thinking.block_binding").Exists())
|
||||
require.Equal(t, "adaptive", gjson.GetBytes(out, "thinking.type").String())
|
||||
require.Equal(t, "summarized", gjson.GetBytes(out, "thinking.display").String())
|
||||
}
|
||||
|
||||
// ★ 关键回归断言:能力维度 sanitize 解决了 "真 CC + haiku" 路径的过度删除问题。
|
||||
// 真实 Claude Code CLI 2.1.87+ 客户端 header 含 context-management beta;
|
||||
// 即使 model 是 haiku,sanitize 也不应剥离功能字段。
|
||||
@@ -145,6 +162,8 @@ func TestComputeFinalAnthropicBeta_OAuthMimic_NonHaiku_IncludesContextManagement
|
||||
"OAuth mimic non-haiku 必须注入完整 CC mimicry beta,含 context-management-2025-06-27")
|
||||
require.True(t, anthropicBetaTokensContains(final, claude.BetaOAuth))
|
||||
require.True(t, anthropicBetaTokensContains(final, claude.BetaClaudeCode))
|
||||
require.True(t, anthropicBetaTokensContains(final, claude.BetaThinkingBindingControls),
|
||||
"OAuth mimic 必须注入 thinking block binding 所需的 beta")
|
||||
}
|
||||
|
||||
func TestComputeFinalAnthropicBeta_OAuthMimic_Haiku_IncludesFullClaudeCodeBetas(t *testing.T) {
|
||||
|
||||
@@ -912,6 +912,12 @@ const anthropicBetaContextManagementToken = "context-management-2025-06-27"
|
||||
// FullClaudeCodeMimicryBetas 覆盖客户端 beta(该列表不含 fallback beta),
|
||||
// 若不 strip,body 字段与 header 不对称 → 所有模型 400
|
||||
//
|
||||
// thinking.block_binding 场景:
|
||||
// - Claude Fable 5.1 的会话前缀绑定控制受
|
||||
// `thinking-binding-controls-2026-08-01` beta 保护
|
||||
// - 缺 token 时上游拒收:
|
||||
// "thinking.adaptive.block_binding: Extra inputs are not permitted"
|
||||
//
|
||||
// 本函数按最终发送的 anthropic-beta header 决定是否保留 body 中的上述字段:
|
||||
// 缺对应 beta token → strip;客户端 header 已带对应 beta → 保留(不过度删除)。
|
||||
// 这将限制完全建立在 "能力维度" 上,与 model 名 / token type / mimicry 子路径无关。
|
||||
@@ -935,6 +941,13 @@ func sanitizeAnthropicBodyForBetaTokens(body []byte, anthropicBetaHeader string)
|
||||
body, changed = b, true
|
||||
}
|
||||
|
||||
// thinking.block_binding:需要 thinking-binding-controls beta。
|
||||
if b, deleted := stripAnthropicBodyFieldUnlessBeta(
|
||||
body, "thinking.block_binding", anthropicBetaHeader, claude.BetaThinkingBindingControls,
|
||||
); deleted {
|
||||
body, changed = b, true
|
||||
}
|
||||
|
||||
// fallbacks:server-side refusal fallback,仅接受 server-side-fallback beta。
|
||||
if b, deleted := stripAnthropicBodyFieldUnlessBeta(
|
||||
body, "fallbacks", anthropicBetaHeader, claude.BetaServerSideFallback,
|
||||
|
||||
Reference in New Issue
Block a user