When a Gemini OAuth account receives a 401, ratelimit_service sets
expires_at=now() to force a refresh. Previously GetAccessToken would
return the stale cached token before checking expires_at, causing
repeated 401s until the cache TTL expired.
Fix: check needsRefresh before attempting cache lookup.
- Silently block verification code for IPs with 2+ registered accounts
- Silently block Gmail alias emails (containing + or . in local part)
- Add CountByRegistrationIP to UserRepository interface
- Pass client IP to SendVerifyCodeAsync for abuse detection
Both checks return fake success to prevent enumeration attacks.
The default socks5 proxy (172.16.32.16:3389) was unreachable for most
deployments, causing version check to timeout after 30 seconds.
Setting the default to empty string allows direct connection to the
Gitea API, which is the expected behavior for most users.
Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
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.