`corepack prepare pnpm@latest` now resolves to pnpm 11, which promotes
ERR_PNPM_IGNORED_BUILDS to a hard error and breaks the frontend stage of
`docker build`. Pin pnpm to v9 to match the CI workflow
(pnpm/action-setup version: 9) and keep image builds reproducible.
Fixes#2442
Vue's scoped-CSS compiler was dropping the `:global(.dark) .settings-tabs-shell`
rules in the production build, so the tab strip kept its light-mode white
background and the inactive tab labels (text-gray-300) showed at ~1.6:1
contrast — effectively unreadable.
Hoist the three dark-mode overrides into an unscoped `<style>` block so they
survive the scoped-CSS transform.
`fixCallIDPrefix` builds malformed ids when the input has the standard
OpenAI `call_<nanoid>` prefix:
input: call_YYen1qxDejd2myJwcTCf7Nyp
output: fcYYen1qxDejd2myJwcTCf7Nyp ← no underscore between 'fc' and the nanoid
ChatGPT's codex backend then rejects the replayed item with:
400 Invalid 'input[N].id': 'fcYYen1qxDejd2myJwcTCf7Nyp'.
Expected an ID that contains letters, numbers, underscores, or
dashes, but this value contained additional characters.
Sub2api wraps that into 502 to the client. Clients using the OpenAI SDK
on the OAuth/codex path see every multi-hop turn (after the first tool
call) fail because the item_reference rewritten this way gets sent on
every subsequent hop.
The other two branches of the same function correctly emit `fc_`
(line 1029: pass-through when already `fc*`; line 1035 fallback:
`fc_" + id`). Only the `call_` → `fc_` rewrite was missing the
underscore — looks like a copy-paste slip during the original commit.
Fix: change `"fc"` to `"fc_"` on the call_ branch. One character.
Repro:
client (OpenAI SDK) sends a function_call_output whose call_id is
`call_<nanoid>` (default OpenAI format). The sub2api request body
also contains an item_reference whose id mirrors the call_id (also
`call_<nanoid>`). On the codex OAuth path, this rewrite fires for
the item_reference's id, producing the malformed value.
Affects: `platform=openai type=oauth` accounts whose clients use the
official OpenAI SDK / Responses API conventions (id prefix `call_`).
API-key accounts and bridge-mode requests are untouched.
Claude Code can send one assistant turn with multiple tool_use blocks followed by a user turn containing matching tool_result blocks. The OpenAI /v1/messages compatibility path trimmed continuation input to the last user turn plus adjacent tool outputs, which could leave a function_call_output without its earlier function_call when previous_response_id was attached.
This keeps all function_call items needed by retained function_call_output entries so the upstream Responses API can resolve every call_id.
Constraint: Applies only to the OpenAI /v1/messages -> Responses compatibility continuation path.
Rejected: Disable previous_response_id for all tool outputs | loses continuation and cache benefits for valid turns.
Confidence: high
Scope-risk: narrow
Directive: Do not trim function_call_output entries without preserving their matching function_call call_id context.
Tested: go test ./internal/service -run 'TestForwardAsAnthropic_(PreviousResponseIDKeepsMultiToolCallContext|AttachesPreviousResponseIDForCompatContinuation|OAuthPreservesClaudeCodeToolCallID)' -count=1
Tested: go test ./internal/service -run 'TestForwardAsAnthropic|TestApplyAnthropicCompatFullReplayGuard|TestOpenAICompat|Test.*ToolContinuation' -count=1
Tested: go test ./internal/pkg/apicompat -count=1
Related: #2337
The Claude Code mimic path rewrites tool names in tools[] (and
tool_choice) but left tool_use blocks in messages[] with their
original names. Anthropic validates that every tool referenced by
a tool_use block is declared in tools[], so the mismatch produces:
messages.N.content.M: Input tag 'original_name' not found in tools
(surfaced as HTTP 400 directly, or wrapped as 424 by upstream proxies
such as Bedrock gateways.)
The previous code comment asserted 'this matches Parrot; response-side
bytes.Replace will restore the names'. Parrot's behavior is fine for
Claude Code's own tool set, but breaks once the upstream client sends
additional tools (e.g. web_search) that are not part of Claude Code
and therefore get renamed here.
Fix: apply the same ToolNameRewrite to messages[].content[] blocks
where type == 'tool_use', keeping tools[], tool_choice and messages
self-consistent before the request reaches Anthropic. tool_result
blocks reference tools via tool_use_id, not name, so no change is
needed there.
A new unit test covers the full rewrite flow and guards against
server tools (type != '') being affected.