diff --git a/open-sse/executors/base.ts b/open-sse/executors/base.ts index f0ecea2dc8..3d33b7f900 100644 --- a/open-sse/executors/base.ts +++ b/open-sse/executors/base.ts @@ -856,6 +856,11 @@ export class BaseExecutor { // CLI fingerprint ordering — always-on for native Claude OAuth, opt-in // for other providers. Header + body field order is itself a fingerprint. let finalHeaders = headers; + // Strip internal sentinel fields set by remapToolNamesInRequest before + // serializing — Anthropic rejects unknown top-level fields (issue #2260). + delete (transformedBody as Record)[ + "_claudeCodeRequiresLowercaseToolNames" + ]; let bodyString = JSON.stringify(transformedBody); const shouldFingerprint = diff --git a/open-sse/services/claudeCodeCompatible.ts b/open-sse/services/claudeCodeCompatible.ts index f48912d1f9..2b67bc7092 100644 --- a/open-sse/services/claudeCodeCompatible.ts +++ b/open-sse/services/claudeCodeCompatible.ts @@ -354,7 +354,8 @@ export async function buildAndSignClaudeCodeRequest( obfuscateInBody(body); } - // Step 7: Serialize with CCH placeholder + // Step 7: Serialize with CCH placeholder (strip internal sentinel fields) + delete (body as Record)["_claudeCodeRequiresLowercaseToolNames"]; const serialized = JSON.stringify(body); // Step 8: Sign with xxHash64