`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