Conversation
lidge-jun#1780 normalizes tool call ids in the Anthropic and Google adapters, but anthropicNativePassthrough bypasses the adapter by design and forwarded message bodies verbatim. Sessions that carry third-party tool call ids — e.g. `Bash:0#<hex>` minted by non-Anthropic models — therefore still 400 (`tool_use.id: String should match pattern '^[a-zA-Z0-9_-]+$'`) the moment the model is switched to a real Anthropic model with native credentials. Run the same createToolCallIdAllocator over *tool_use / *tool_result blocks before the body is serialized: conforming ids pass through byte-identical, non-conforming ids are rewritten deterministically with a hash suffix, and call/result pairing stays stable. Covers /v1/messages and /v1/messages/count_tokens, which share this branch.
|
✅ Deterministic PR hygiene checks passed. |
⏳ DRAFT
What to do
Review readiness checklist
0/4 boxes ticked. This PR stays in draft until every box above is ticked. |
리뷰 · 우선순위 64 / 80클로드 본사로 요청을 거의 그대로 넘기는 길에서는 도구 호출 번호(tool_use id)를 고치지 않았습니다. 번호 고치기는 번역 어댑터에만 있었습니다. 다른 모델이 만든 번호가 대화에 남아 있으면, 예를 들어 이 PR은 보내기 직전에 같은 고치기를 이 길에도 넣습니다. 규칙에 맞는 번호는 한 글자도 안 바꿉니다. 안 맞는 번호는 같은 입력이면 항상 같은 값으로 바뀌고, 호출과 결과의 짝은 유지됩니다. 라인 - 라인 - 라인 - 상태 · draft — 준비 체크리스트 네 칸이 비어 있습니다. 최신 메인테이너의 판단이 필요한 지점
빈 번호를 이번 PR에서 막을지, 너의 추천 닫지 않는 편이 맞습니다. 같은 수정을 담은 다른 열린 PR은 없습니다. 빈 번호는 요청에 남기지 말고, 번호가 겹치는 테스트를 하나 넣은 다음 체크리스트를 채우고 Ready로 올리면 됩니다. 이 댓글은 grok-bot이 작성했습니다 |
…riptions, launchd levers, passthrough tool ids (#5678) * test(claude): cover bounded skill marker paths and document pass-through Carries #5606. Adds the exact 4,096/4,097 UTF-16 code unit boundary cases for POSIX and Windows skill directory markers and a long newline-free carrier, and documents that a longer directory line is sent unchanged. The seven translated Claude Code guides now state the same pass-through rule as the English guide. Supersedes #5606. Co-authored-by: Epinephrine <27862058+luvs01@users.noreply.github.com> * fix(system-env): refresh and drop the launchd levers opencodex owns Carries #5622. A lever opencodex already tracks as injected is refreshed instead of skipped, a tracked lever the current config no longer produces is unset, and PUT /api/claude-code reconciles on every model slot and lever field, not only systemEnv and authMode. A launchd value the user set before injection is never touched. The management API structure note records the PUT reconciliation. Supersedes #5622. Co-authored-by: terin <100397903+sh940701@users.noreply.github.com> * feat(claude): describe routed models instead of "From gateway" Carries #5621. Readable Claude Code /v1/models rows carry a description naming the native model or provider/model they route to, which Claude Code 2.1.257 and later shows in the picker; the 1M copy keeps it and a Fast sibling appends " · Fast". The gateway-model cache preserves string descriptions. The Claude Desktop structure note records the picker description contract. Supersedes #5621. Co-authored-by: terin <100397903+sh940701@users.noreply.github.com> * fix(claude): keep routed model windows without disabling compact Carries #5665. Claude Code aliases are minted as ocx-claude-/ocx-claude2- so the picker keeps them while Claude Code applies CLAUDE_CODE_MAX_CONTEXT_TOKENS without DISABLE_COMPACT; saved claude-ocx-/claude-ocx2- ids keep decoding. maxContextTokens now injects only the window. The gateway cache mirrors the picker's contains-claude rule and keeps #5621's descriptions. Folded review fixes: native fallback recognizes the current prefixes; the context-window map keeps registering the legacy spellings at the same window; no compact lever is ever derived from maxContextTokens (pinned for values outside the 100k-1M compact range); the tracked DISABLE_COMPACT from older releases is removed by the system-env produced-key sweep instead of a one-off cleanup; the Claude Desktop structure note records the alias and env contract. Supersedes #5665. Co-authored-by: terin <100397903+sh940701@users.noreply.github.com> * fix(claude): sanitize tool_use ids on native Anthropic passthrough Carries #5628. The native passthrough bypasses the Anthropic adapter, so tool call ids minted by routed models (Devin's Bash:0#<hex>) reached api.anthropic.com verbatim and 400ed. The request-scoped allocator now rewrites non-conforming and overlength ids, keeps call/result pairing, and leaves conforming ids byte-identical. Folded review fixes: an empty id fails locally with a 400 before the upstream fetch instead of being forwarded; regressions cover the empty id, an overlength id and a collision with an existing valid id; the Claude Desktop structure note and the Claude Code guide in all eight languages describe the id rewrite. Supersedes #5628. Co-authored-by: wuwei <27188611+Haven2026@users.noreply.github.com> * fix(claude): keep legacy slot selectors and hand-edited DISABLE_COMPACT safe on upgrade Folds the bundle's adversarial review into the #5665 and #5622 carries. A legacy claude-ocx-/claude-ocx2- selector configured in an OpenCodex model slot is emitted in its current ocx-claude spelling on every env path. The route is identical, and Claude Code then applies the configured window instead of falling back to 200k accounting now that DISABLE_COMPACT is no longer paired with maxContextTokens. A selection saved by Claude Code's own picker stays a documented re-pick. The system-env sweep removes a tracked DISABLE_COMPACT only while it still holds the 1 older releases injected; a value the user changed by hand is released from tracking without being deleted. Co-authored-by: terin <100397903+sh940701@users.noreply.github.com> * fix(claude): keep legacy picker selectors on connected clients and Fable passthrough Folds the Codex and CodeRabbit review of the bundle. A legacy claude-ocx-native--claude-fable-* picker value compared only against the new ocx-claude spelling and fell off the native Anthropic passthrough; both spellings are accepted again, with the legacy value back in the endpoint test. The connected-client context-window map registers the legacy route and native spellings like the local map does, so a saved legacy selector keeps its [1m] subagent marker on a connected hub. Co-authored-by: terin <100397903+sh940701@users.noreply.github.com> --------- Co-authored-by: Epinephrine <27862058+luvs01@users.noreply.github.com> Co-authored-by: terin <100397903+sh940701@users.noreply.github.com> Co-authored-by: wuwei <27188611+Haven2026@users.noreply.github.com>
Summary
createToolCallIdAllocatorand wired it intoadapters/anthropic.tsandadapters/google.ts, so translated Anthropic requests replay cross-provider tool history safely.anthropicNativePassthroughinsrc/server/claude-messages.tsbypasses that adapter by design and serialized the request body verbatim — sessions carrying non-Anthropic tool call ids (e.g.Bash:0#<hex>minted by third-party models) still 400 withtool_use.id: String should match pattern '^[a-zA-Z0-9_-]+$'when switched to a native Claude model on a realsk-ant-*credential.*tool_use/*tool_resultblocks before the body is serialized. Conforming ids pass through byte-identical (prompt-cache keys untouched); non-conforming ids get the deterministic sanitize+hash rewrite with stable call/result pairing. Covers/v1/messagesand/v1/messages/count_tokens, which share the branch.Test plan
tests/claude-integration/claude-native-passthrough.test.ts: pollutedtool_use/server_tool_use/web_search_tool_result/tool_resultids rewritten to conforming wire ids, pairing preserved, conformingtoolu_*ids byte-identical, deterministic across requests (messages vs count_tokens)bun test tests/claude-integration/claude-native-passthrough.test.ts— 17/17 passbun run typecheck— cleanbun run structure:check— pass (no contract change: docs describe the passthrough as "forwards without translation"; id sanitization is the same class as the image normalization already applied on this branch)bun run privacy:scan— passbun run test:changed— 2626 pass / 20 fail; all 20 aremanagement-provider-validationcases that fail identically on cleandev(api.example.testprovider POST → 400; unrelated environment issue)Bash:0#<hex>history → 400 before this change, 200 after (claude-haiku-4-5 via passthrough)Refs #1767, #1780.
Review readiness checklist
This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:
Required local validation passed; commands, results, and any full-suite exception are documented.
I pushed my PR to the latest dev commit.
I resolved all correct Codex and CodeRabbit findings.
My PR is ready for review.