Skip to content

release v0.5.3#712

Merged
ding113 merged 6 commits intomainfrom
dev
Feb 3, 2026
Merged

release v0.5.3#712
ding113 merged 6 commits intomainfrom
dev

Conversation

@ding113
Copy link
Owner

@ding113 ding113 commented Feb 3, 2026

Release v0.5.3

This release includes major architectural improvements, new features, bug fixes, and deployment enhancements.


🎯 Highlights

Major Refactoring

  • Removed format converters (~8,800 lines): Enforces strict same-format routing (Claude→Claude, OpenAI→OpenAI, Gemini→Gemini)
  • Simplified proxy architecture: Removed cross-format conversion complexity for better maintainability

New Features

  • Anthropic provider overrides: Configure max_tokens and thinking.budget_tokens at provider level
  • Thinking budget rectifier: Automatic error recovery for thinking budget validation failures
  • Extended readonly API access: Regular user API keys can now access more endpoints with proper data isolation
  • Zeabur deployment support: Added standalone Dockerfile for PaaS platforms

Bug Fixes

  • Fixed Gemini URL duplication issue (version prefix handling)
  • Fixed billing calculation for Gemini SSE responses
  • Fixed provider exhaustion after model redirect

📦 What's Included

This release merges the following PRs from dev branch:

🔧 Refactoring & Architecture

  • refactor(proxy): remove format converters and enforce same-format routing #709 - Remove format converters and enforce same-format routing
    • Deleted ~8,800 lines of converter code (claude↔openai, codex↔*, gemini-cli↔*)
    • Removed Codex CLI adapter and instruction injection
    • Simplified proxy pipeline (forwarder, response handler, format mapper)
    • Breaking Change: Cross-format conversion no longer supported

✨ Features

🐛 Bug Fixes


🗄️ Database Migrations

Two new migrations included:

  • 0060_bored_gertrude_yorkes.sql: Adds anthropic_max_tokens_preference and anthropic_thinking_budget_preference columns to providers table
  • 0061_exotic_trauma.sql: Adds enable_thinking_budget_rectifier boolean to system_settings table

Migration required: Run bun run db:migrate or set AUTO_MIGRATE=true


⚠️ Breaking Changes

Format Converter Removal (PR #709)

Cross-format conversion is no longer supported.

Requests must be routed to providers with matching API formats:

  • Claude API requests → Claude-compatible providers only
  • OpenAI API requests → OpenAI-compatible providers only
  • Gemini CLI requests → Gemini CLI-compatible providers only

Migration Path:

  1. Ensure your providers' providerType matches the API format you're sending
  2. If you need format conversion, use an upstream converter (e.g., CCR) before CCH
  3. Review provider routing configuration - mismatched formats will now be rejected

Removed Features:

  • joinClaudePool provider configuration option
  • codexInstructionsStrategy provider configuration option
  • All format converters (claude↔openai, codex↔*, gemini-cli↔*)

📊 Statistics

  • 100 files changed
  • ~9,000 lines removed (converters, Codex adapter, obsolete tests)
  • ~1,200 lines added (new features, tests, migrations)
  • Net reduction: ~7,800 lines (cleaner, more maintainable codebase)

🔗 Related Issues


🧪 Testing

  • All existing tests pass (1,786 tests)
  • 36 new unit tests for Anthropic provider overrides
  • 209 new tests for thinking budget rectifier
  • 358 lines of integration tests for readonly access
  • Comprehensive format compatibility test suite

📝 Upgrade Notes

  1. Database Migration: Required - run bun run db:migrate or use AUTO_MIGRATE=true
  2. Provider Configuration: Review your providers to ensure format compatibility
  3. API Keys: Regular user API keys now have extended access to readonly endpoints
  4. Format Conversion: If you relied on cross-format conversion, implement upstream conversion
  5. Deployment: New Dockerfile available for Zeabur and other PaaS platforms

🙏 Contributors

  • @ding113 - Core development and architecture
  • Community contributors for bug reports and feature requests

Release description generated by Claude AI

Greptile Overview

Greptile Summary

This release (v0.5.3) introduces major breaking changes by removing cross-format API conversion capabilities and enforcing same-format routing between clients and providers.

Major Changes

BREAKING: Format Converters Removed

  • Deleted all format conversion logic (~8,000 lines): codex-to-claude, openai-to-claude, claude-to-openai, gemini-cli converters
  • Removed Codex CLI adapter, instruction injection, and request sanitizer
  • Simplified ProxyForwarder and ResponseHandler to pass-through requests/responses without transformation
  • Updated ProxyProviderResolver to enforce strict format compatibility: openai requests must route to openai-compatible providers, claude requests to claude providers, response API requests to codex providers

Provider Configuration Changes

  • Removed joinClaudePool field (allowed non-Anthropic providers to handle claude models)
  • Removed codexInstructionsStrategy field
  • Added anthropicMaxTokensPreference and anthropicThinkingBudgetPreference for Anthropic-specific parameter overrides
  • New database migrations: 0060 (provider columns), 0061 (system settings)

New Features

UI & Configuration

  • Removed joinClaudePool and Codex instructions strategy controls from provider forms
  • Added Anthropic parameter override controls for claude/claude-auth providers
  • Updated i18n messages across 5 languages (en, ja, ru, zh-CN, zh-TW)
  • New system setting: enableThinkingBudgetRectifier (defaults to true)

Testing

  • Added comprehensive test suites: provider-selector-format-compatibility (289 lines), readonly-access-endpoints (358 lines), anthropic-provider-overrides (775 lines), thinking-budget-rectifier (209 lines)
  • Removed obsolete test files for deleted converters and Codex sanitizer

Confidence Score: 4/5

  • This PR is safe to merge after verifying that client applications are prepared for the breaking format conversion removal
  • Score reflects well-tested major refactoring with comprehensive test coverage, but the breaking changes require careful deployment coordination
  • Pay close attention to migration scripts and ensure all client applications no longer rely on cross-format conversion before deploying

Important Files Changed

Filename Overview
src/app/v1/_lib/proxy/forwarder.ts Added thinking budget rectifier for handling Anthropic API budget_tokens errors, plus Anthropic provider overrides integration
src/app/v1/_lib/proxy/thinking-budget-rectifier.ts New rectifier for API validation errors, automatically adjusts request parameters and retries once
src/lib/anthropic/provider-overrides.ts New provider override system for Anthropic API parameters (max_tokens, thinking.budget_tokens) with audit trail
src/app/v1/_lib/proxy/provider-selector.ts Removed joinClaudePool logic, enforcing strict format compatibility between client requests and provider types
src/app/v1/_lib/url.ts Fixed URL building logic to handle version prefixes correctly using regex matching instead of hardcoded paths
src/types/provider.ts Removed joinClaudePool and codexInstructionsStrategy fields, added anthropicMaxTokensPreference and anthropicThinkingBudgetPreference
drizzle/0060_bored_gertrude_yorkes.sql Migration adds anthropic_max_tokens_preference and anthropic_thinking_budget_preference columns to providers table
drizzle/0061_exotic_trauma.sql Migration adds enable_thinking_budget_rectifier column to system_settings table with default true
src/app/v1/_lib/proxy/response-handler.ts Removed all format conversion logic, switched Gemini SSE usage extraction to last-wins strategy for accurate token counts

Sequence Diagram

sequenceDiagram
    participant Client
    participant Forwarder as ProxyForwarder
    participant Selector as ProviderSelector
    participant Overrides as AnthropicOverrides
    participant Provider as Upstream Provider
    participant ResponseHandler

    Client->>Forwarder: Request (format: openai/claude/response)
    Forwarder->>Selector: Pick provider for request
    
    Note over Selector: NEW: Strict format matching<br/>openai to openai-compatible only<br/>claude to claude/claude-auth only<br/>response to codex only
    
    Selector-->>Forwarder: Selected provider
    
    alt Anthropic Provider (claude/claude-auth)
        Forwarder->>Overrides: Apply parameter overrides
        Note over Overrides: Override max_tokens<br/>Override thinking budget<br/>(if configured)
        Overrides-->>Forwarder: Modified request
    end
    
    Forwarder->>Provider: Forward request
    Provider-->>Forwarder: Response or Error
    
    alt Anthropic budget validation error
        Note over Forwarder: Detect budget validation failure
        Forwarder->>Forwarder: Rectify: set budget to 32000<br/>set max_tokens to 64000 if needed
        Forwarder->>Provider: Retry with rectified request
        Provider-->>Forwarder: Response (success)
    end
    
    Forwarder->>ResponseHandler: Process response
    
    Note over ResponseHandler: REMOVED: Format conversion<br/>Pass-through only<br/>Gemini: last-wins usage extraction
    
    ResponseHandler-->>Client: Final response (same format as request)
Loading

ding113 and others added 6 commits February 2, 2026 10:19
…errides

feat(provider): add Anthropic max_tokens and thinking budget override settings
…691)

Gemini SSE streams return usageMetadata in every event, but only the
final event contains complete token counts (candidatesTokenCount,
thoughtsTokenCount). The existing first-wins strategy in applyUsageValue
caused output tokens to be missed since early events only have
promptTokenCount.

This fix introduces last-wins strategy specifically for Gemini SSE
usageMetadata while preserving first-wins for other formats (Claude,
Codex) where usage is returned complete in a single event.

Fixes: Gemini streaming responses showing 0 output tokens in billing
* fix: 修复 buildProxyUrl 重复拼接版本前缀的问题

* refactor(proxy): optimize regex compilation in buildProxyUrl

- Move escapeRegExp helper to module scope to avoid recreation
- Remove case-insensitive flag from version endpoint regex

* refactor(proxy): optimize endpoint regex compilation in URL builder

Move endpoint regex compilation outside the loop to avoid repeated regex creation on every request. Pre-compile endpoint patterns at module load time for better performance.
* Create Dockerfile

Signed-off-by: h7ml <h7ml@qq.com>

* Update Dockerfile

Signed-off-by: h7ml <h7ml@qq.com>

* Update Dockerfile

Signed-off-by: h7ml <h7ml@qq.com>

---------

Signed-off-by: h7ml <h7ml@qq.com>
- 为多个API端点添加allowReadOnlyAccess标志,允许只读密钥访问
- 受影响的端点包括:getUsers、getUserLimitUsage、getUserStatistics、getUsageLogs、getOverviewData、getActiveSessions
- 更新现有测试以验证只读密钥可访问这些端点
- 新增集成测试全面验证只读访问权限和数据隔离
- 修复Issue #687:只读密钥现在可以访问用户数据相关端点,但仅限查看自身数据

close ding113/claude-code-hub #687
…ting (#709)

* refactor(proxy): remove format converters and enforce same-format routing

BREAKING CHANGE: Cross-format conversion is no longer supported.
Requests must be routed to providers with matching API formats.

- Delete all converters (claude-to-openai, openai-to-claude, codex-*, gemini-cli-*)
- Remove Codex CLI adapter, instruction injection, and request sanitizer
- Simplify ProxyForwarder to pass-through without format transformation
- Update provider-selector to enforce format compatibility
- Remove ResponseTransformer conversion logic from response-handler
- Clean up session-extractor to remove Codex-specific handling
- Delete related test files for removed functionality

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* chore(ui): remove joinClaudePool and codexInstructionsStrategy from provider forms

- Remove legacy pool joining and instruction strategy UI controls
- Clean up i18n messages for removed provider form fields (all 5 languages)
- Update provider actions and form context/types
- Remove unused routing section options
- Update related test mocks

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: update README to reflect strict same-format routing

- Remove outdated claims about format conversion and Codex CLI injection
- Clarify that proxy enforces same-format routing with no cross-format conversion
- Add format-compatibility unit tests for provider-selector

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* chore: remove unused imports (lint fix)

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

---------

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@coderabbitai
Copy link

coderabbitai bot commented Feb 3, 2026

📝 Walkthrough

概述

该PR实现了Anthropic预算整流机制、删除了格式转换器系统、添加了提供商级参数覆盖、并扩展了只读访问支持。包含多阶段Docker构建、数据库迁移、新型重试逻辑、UI重构和多语言更新。

变更

组件 / 文件(s) 摘要
基础设施与部署
Dockerfile, drizzle/0060_*.sql, drizzle/0061_*.sql, drizzle/meta/*, src/drizzle/schema.ts
添加多阶段Docker构建(deps/builder/runner)、两个数据库迁移(Anthropic偏好字段、thinking预算整流器开关)及其快照。
Thinking预算整流功能
src/app/v1/_lib/proxy/thinking-budget-rectifier.ts, src/app/v1/_lib/proxy/thinking-budget-rectifier.test.ts, src/lib/utils/special-settings.ts, src/types/special-settings.ts
新增Thinking预算整流检测与修正逻辑,处理anthropic budget_tokens < 1024错误。
Anthropic提供商覆盖
src/lib/anthropic/provider-overrides.ts, tests/unit/proxy/anthropic-provider-overrides.test.ts
实现max_tokens和thinking.budget_tokens的提供商级覆盖与审计功能。
删除格式转换系统
src/app/v1/_lib/converters/* (所有转换器、注册表、工具名称映射器已删除)
移除Claude↔Codex、OpenAI↔Claude、Gemini CLI等所有格式转换器和全局转换器注册表(~4000+行删除)。
代理转发与响应处理
src/app/v1/_lib/proxy/forwarder.ts, src/app/v1/_lib/proxy/response-handler.ts, src/app/v1/_lib/proxy/provider-selector.ts, src/app/v1/_lib/url.ts
添加Anthropic/Codex覆盖与审计集成、多层次重试机制、正则表达式基础端点检测、Gemini SSE使用元数据聚合更新。
Codex会话提取
src/app/v1/_lib/codex/session-extractor.ts, src/app/v1/_lib/codex/session-extractor.test.ts
删除userAgent参数和isCodexClient检测,简化会话ID提取。
删除Codex相关模块
src/app/v1/_lib/codex/chat-completions-handler.ts, src/app/v1/_lib/codex/codex-cli-adapter.ts, src/app/v1/_lib/codex/constants/*, src/app/v1/_lib/codex/utils/request-sanitizer.ts
删除OpenAI兼容聊天完成处理器、Codex CLI适配器、指令常量和请求清理器。
API路由变更
src/app/v1/[...route]/route.ts, src/app/api/actions/[...route]/route.ts
将/chat/completions和/responses端点路由从handleChatCompletions改为handleProxyRequest;为13个my-usage和用户端点添加allowReadOnlyAccess标志。
系统设置与配置
src/actions/system-config.ts, src/lib/config/system-settings-cache.ts, src/repository/system-config.ts, src/types/system-config.ts
添加enableThinkingBudgetRectifier布尔字段到系统设置及相关仓储/缓存/验证层。
提供商数据结构
src/actions/providers.ts, src/repository/provider.ts, src/types/provider.ts, src/repository/_shared/transformers.ts
删除joinClaudePool和codexInstructionsStrategy;添加anthropicMaxTokensPreference和anthropicThinkingBudgetPreference字段。
验证与类型
src/lib/validation/schemas.ts, src/app/[locale]/settings/providers/_components/forms/provider-form/provider-form-types.ts
添加Anthropic偏好验证schema、跨字段验证(thinking预算 < max_tokens)、provider表单上下文中的新状态/操作类型。
UI设置表单
src/app/[locale]/settings/config/_components/system-settings-form.tsx, src/app/[locale]/settings/providers/_components/forms/provider-form/*.tsx
添加Thinking预算整流开关UI、删除Claude加入池UI、替换Codex策略为Anthropic参数覆盖UI。
UI路由/代理部分
src/app/[locale]/settings/providers/_components/forms/provider-form/sections/routing-section.tsx
删除Claude池加入块、用Anthropic覆盖部分(max_tokens/thinking预算)替换Codex策略配置。
多语言消息
messages/{en,ja,ru,zh-CN,zh-TW}/settings/config.json, messages/{en,ja,ru,zh-CN,zh-TW}/settings/providers/form/{sections,strings}.json, messages/zh-CN/provider-form-temp.json, messages/providers-i18n-additions.json
在所有语言中添加enableThinkingBudgetRectifier配置条目;删除Codex策略和Claude池相关字符串。
只读访问测试
tests/api/my-usage-readonly.test.ts, tests/integration/readonly-access-endpoints.test.ts
更新测试预期以反映只读键对allowReadOnlyAccess端点的访问;添加全面的集成测试套件(Issue #687)。
单元测试清理
tests/unit/proxy/{chat-completions-handler-guard-pipeline,codex-request-sanitizer,converters-tool-result-nonstream,openai-to-codex-request}.test.ts (已删除), tests/unit/proxy/provider-selector-format-compatibility.test.ts (新增)
删除已弃用转换器和Codex处理器的测试;新增提供商格式兼容性测试。
其他测试更新
tests/unit/*
从提供商/UI测试fixture中移除joinClaudePool和codexInstructionsStrategy;重命名未使用的参数。
杂项UI清理
src/app/[locale]/dashboard/**, src/components/ui/relative-time.tsx, src/app/[locale]/settings/notifications/**, src/app/[locale]/settings/prices/**
删除未使用的导入(RefreshCw、Power、cn等)、重命名未使用的变量。
allowlist
scripts/audit-settings-placeholders.allowlist.json
删除codexStrategyConfig allowlist条目。
README文档
README.en.md, README.md, README.zh-CN.md
更新OpenAI兼容端点描述,强调端点原生格式保留和同格式路由;移除ResponseTransformer提及。

代码审查工作量评估

🎯 4 (复杂) | ⏱️ ~75 分钟

原因

  • 规模庞大:100+ 文件变更,跨越多个子系统
  • 架构重构:删除整个格式转换器系统(~4000+ 行删除),需验证移除的完整性及后续调用位置
  • 多层逻辑:Thinking 预算整流、Anthropic 覆盖审计、多层重试机制、会话状态持久化相互交织
  • 异构变更:包含删除(转换器)、新增(整流器、覆盖系统)、修改(路由、UI、验证)多种模式
  • 高影响范围:影响代理转发、响应处理、API 路由、UI 表单、数据验证层

可能相关的PR

  • PR #689:直接相关 — 同样添加 Anthropic 提供商覆盖字段、DB 迁移、类型定义和验证,触及相同文件与符号
  • PR #709:核心重构相关 — 执行相同的大规模重构:删除格式转换器、强制同格式路由、修改提供商类型与 UI
  • PR #522:代码级相关 — 同时修改 src/app/v1/_lib/proxy/forwarder.ts,添加 Anthropic/Gemini 请求转发与头部构建逻辑
🚥 Pre-merge checks | ❌ 3
❌ Failed checks (3 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning 标题"release v0.5.3"与变更集的主要内容不符。变更集涉及多个重大功能变更(移除格式转换器、添加Anthropic预算纠正机制、修改数据库架构等),但标题仅表示版本发布,未能准确反映具体的功能变更。 建议将标题改为更具体的描述,如"Remove format converters and add thinking budget rectifier"或"Refactor proxy format handling and add Anthropic overrides",以准确反映核心变更。
Description check ⚠️ Warning 拉取请求缺少描述。作者未提供任何说明文档来解释变更的目的、影响范围或实现细节。 添加详细的拉取请求描述,说明为什么进行这些变更、主要功能变更有哪些、对系统的影响,以及任何需要注意的迁移或测试信息。
Docstring Coverage ⚠️ Warning Docstring coverage is 52.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 3, 2026

🧪 测试结果

测试类型 状态
代码质量
单元测试
集成测试
API 测试

总体结果: ✅ 所有测试通过

@github-actions github-actions bot added enhancement New feature or request area:core area:i18n labels Feb 3, 2026
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

9 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +69 to +70
if (currentMaxTokens !== null && budgetTokens >= currentMaxTokens) {
budgetTokens = currentMaxTokens - 1;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anthropic API requires budget_tokens < max_tokens (strict less than), but this clamping uses budgetTokens = currentMaxTokens - 1. If currentMaxTokens is exactly 1024, this results in budgetTokens = 1023 which fails the >= 1024 minimum requirement.

Suggested change
if (currentMaxTokens !== null && budgetTokens >= currentMaxTokens) {
budgetTokens = currentMaxTokens - 1;
if (currentMaxTokens !== null && budgetTokens >= currentMaxTokens) {
budgetTokens = Math.max(MIN_BUDGET_TOKENS, currentMaxTokens - 1);
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/lib/anthropic/provider-overrides.ts
Line: 69:70

Comment:
Anthropic API requires `budget_tokens < max_tokens` (strict less than), but this clamping uses `budgetTokens = currentMaxTokens - 1`. If `currentMaxTokens` is exactly 1024, this results in `budgetTokens = 1023` which fails the >= 1024 minimum requirement.

```suggestion
    if (currentMaxTokens !== null && budgetTokens >= currentMaxTokens) {
      budgetTokens = Math.max(MIN_BUDGET_TOKENS, currentMaxTokens - 1);
    }
```

How can I resolve this? If you propose a fix, please make it concise.

COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/drizzle ./drizzle
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trailing whitespace after ./drizzle

Prompt To Fix With AI
This is a comment left during a code review.
Path: Dockerfile
Line: 26:26

Comment:
trailing whitespace after `./drizzle`

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +1 to +3
ALTER TABLE "notification_target_bindings" ALTER COLUMN "schedule_timezone" DROP DEFAULT;--> statement-breakpoint
ALTER TABLE "providers" ADD COLUMN "anthropic_max_tokens_preference" varchar(20);--> statement-breakpoint
ALTER TABLE "providers" ADD COLUMN "anthropic_thinking_budget_preference" varchar(20); No newline at end of file
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

verify this migration includes DROP COLUMN statements for removed join_claude_pool and codex_instructions_strategy fields - current migration only adds new columns without cleaning up deprecated ones

Prompt To Fix With AI
This is a comment left during a code review.
Path: drizzle/0060_bored_gertrude_yorkes.sql
Line: 1:3

Comment:
verify this migration includes DROP COLUMN statements for removed `join_claude_pool` and `codex_instructions_strategy` fields - current migration only adds new columns without cleaning up deprecated ones

How can I resolve this? If you propose a fix, please make it concise.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/app/[locale]/dashboard/logs/_components/error-details-dialog/components/LogicTraceTab.tsx (1)

51-58: ⚠️ Potential issue | 🟠 Major

PR 目标分支应为 dev

当前 PR 目标分支是 main,与仓库约定不一致。请先将目标分支调整为 dev,再继续评审流程。Based on learnings All pull requests must target the dev branch (https://github.com/ding113/claude-code-hub).

src/app/[locale]/dashboard/availability/_components/endpoint/latency-curve.tsx (1)

16-21: ⚠️ Potential issue | 🟠 Major

用户可见文案需使用 i18n

图表标签与状态文案仍是硬编码,违反 i18n 约定。建议改为使用 t(...)

建议修改
-const chartConfig = {
-  latency: {
-    label: "Latency",
-    color: "var(--chart-1)",
-  },
-} satisfies ChartConfig;
-
-export function LatencyCurve({ logs, className }: LatencyCurveProps) {
-  const t = useTranslations("dashboard.availability.latencyCurve");
+export function LatencyCurve({ logs, className }: LatencyCurveProps) {
+  const t = useTranslations("dashboard.availability.latencyCurve");
+  const chartConfig = {
+    latency: {
+      label: t("latency"),
+      color: "var(--chart-1)",
+    },
+  } satisfies ChartConfig;
@@
-                    <div className={cn("text-xs", data?.ok ? "text-emerald-500" : "text-rose-500")}>
-                      {data?.statusCode || (data?.ok ? "OK" : "FAIL")}
+                    <div className={cn("text-xs", data?.ok ? "text-emerald-500" : "text-rose-500")}>
+                      {data?.statusCode || (data?.ok ? t("ok") : t("fail"))}
                     </div>

Also applies to: 121-126

src/app/[locale]/dashboard/availability/_components/provider/latency-chart.tsx (1)

16-28: ⚠️ Potential issue | 🟠 Major

图例与提示文案需 i18n 化

P50/P95/P99 和 tooltip 的 dataKey 作为显示文本仍是硬编码或原始值,需改为 i18n。

建议修改
-const chartConfig = {
-  p50: {
-    label: "P50",
-    color: "var(--chart-2)",
-  },
-  p95: {
-    label: "P95",
-    color: "var(--chart-4)",
-  },
-  p99: {
-    label: "P99",
-    color: "var(--chart-1)",
-  },
-} satisfies ChartConfig;
-
-export function LatencyChart({ providers, className }: LatencyChartProps) {
-  const t = useTranslations("dashboard.availability.latencyChart");
+export function LatencyChart({ providers, className }: LatencyChartProps) {
+  const t = useTranslations("dashboard.availability.latencyChart");
+  const chartConfig = {
+    p50: {
+      label: t("p50"),
+      color: "var(--chart-2)",
+    },
+    p95: {
+      label: t("p95"),
+      color: "var(--chart-4)",
+    },
+    p99: {
+      label: t("p99"),
+      color: "var(--chart-1)",
+    },
+  } satisfies ChartConfig;
@@
-                          {chartConfig[item.dataKey as keyof typeof chartConfig]?.label ||
-                            item.dataKey}
+                          {chartConfig[item.dataKey as keyof typeof chartConfig]?.label ??
+                            t("unknownSeries")}

Also applies to: 153-162

🤖 Fix all issues with AI agents
In `@Dockerfile`:
- Around line 18-19: The Dockerfile sets the container port to 8080 but the app
and health checks expect port 3000; update the ENV PORT value and the EXPOSE
directive so they match the runtime configuration by changing ENV PORT to 3000
and EXPOSE to 3000 (adjust the ENV PORT and EXPOSE lines accordingly).

In `@src/app/v1/_lib/proxy/thinking-budget-rectifier.test.ts`:
- Around line 2-5: The test imports detectThinkingBudgetRectifierTrigger and
rectifyThinkingBudget using a relative path; update the import statement to use
the project path alias (start imports with "@/") so modules are resolved from
src via the alias—for example replace the relative import of
"./thinking-budget-rectifier" with
"@/app/v1/_lib/proxy/thinking-budget-rectifier" (keeping the same exported
symbols detectThinkingBudgetRectifierTrigger and rectifyThinkingBudget) to
follow the coding guideline.

In `@src/app/v1/_lib/proxy/thinking-budget-rectifier.ts`:
- Around line 73-78: Current check treats arrays as objects and will mutate
them; change the guard so message.thinking is only reused when it's a non-null
plain object (i.e., typeof message.thinking === "object" && message.thinking !==
null && !Array.isArray(message.thinking)), otherwise reassign message.thinking =
{}; then cast to thinkingObj and set thinkingObj.type = "enabled" as before
(referencing message.thinking and thinkingObj).

In `@src/lib/utils/special-settings.ts`:
- Around line 78-90: The deduplication key for the "thinking_budget_rectifier"
case omits thinkingType, which can merge distinct events; update the key
generation in the switch branch handling "thinking_budget_rectifier" (in
special-settings.ts) to include setting.before.thinkingType and
setting.after.thinkingType in the JSON.stringify array alongside the existing
fields (e.g., setting.before.maxTokens, setting.before.thinkingBudgetTokens,
setting.after.maxTokens, setting.after.thinkingBudgetTokens) so events that
differ only by thinkingType remain distinct.
🧹 Nitpick comments (5)
src/app/[locale]/dashboard/logs/_components/error-details-dialog/components/LogicTraceTab.tsx (1)

51-58: 考虑移除未使用的 statusCode 参数或在组件中使用它

目前仅改名为 _statusCode 来消除未使用告警,但仍对外暴露该字段,容易误导调用方。若确认不再需要,请同步从 LogicTraceTabProps 与调用处移除;若需要,请在渲染中实际消费它。

可选修改(仅限本文件)
-export function LogicTraceTab({
-  statusCode: _statusCode,
+export function LogicTraceTab({
   providerChain,
   blockedBy,
   blockedReason,
   requestSequence,
   initialExpandedChainIndex,
 }: LogicTraceTabProps) {
src/app/[locale]/dashboard/availability/_components/endpoint/probe-terminal.tsx (1)

43-65: levelConfig 中的 icon 属性是死代码。

根据 AI 摘要,const Icon = config.icon; 的使用已被移除,但 levelConfig 中仍然定义了 icon 属性(第 45、52、59 行)。这些属性现在未被使用,应当清理以保持代码整洁。

此外,AI 摘要声称 XCircle 已从导入中移除,但实际上它仍存在于第 4 行的导入语句中,并在第 52 行被引用。

♻️ 建议移除未使用的 icon 属性
 const levelConfig = {
   success: {
-    icon: CheckCircle2,
     label: "OK",
     color: "text-emerald-500",
     bgColor: "bg-emerald-500/5",
     borderColor: "border-l-emerald-500",
   },
   error: {
-    icon: XCircle,
     label: "FAIL",
     color: "text-rose-500",
     bgColor: "bg-rose-500/5",
     borderColor: "border-l-rose-500",
   },
   warn: {
-    icon: AlertCircle,
     label: "WARN",
     color: "text-amber-500",
     bgColor: "bg-amber-500/5",
     borderColor: "border-l-amber-500",
   },
 };

移除 icon 属性后,也需要清理未使用的导入:

-import { AlertCircle, CheckCircle2, Download, XCircle } from "lucide-react";
+import { Download } from "lucide-react";
src/app/[locale]/settings/prices/_components/price-list.tsx (1)

73-73: 可以考虑移除未使用的 Hook 调用

变量 _localeuseLocale() 获取后在组件中从未被使用。如果确实不需要 locale 信息,建议直接移除这行代码以保持代码简洁。

♻️ 建议的修改
- const _locale = useLocale();

如果将来需要使用 locale,可以随时重新添加。

tests/unit/app/v1/url.test.ts (1)

58-83: 测试覆盖新的正则匹配逻辑

新增的三个测试用例很好地覆盖了版本前缀处理:

  • v1beta 标准 beta 版本
  • v1internal 内部版本标识
  • v2 未来版本兼容性

建议考虑补充以下边界情况测试:

📝 可选:补充边界情况测试
test("处理带尾部斜杠的请求路径", () => {
  const out = buildProxyUrl(
    "https://example.com/api/models",
    new URL("https://dummy.com/v1/models/")
  );
  expect(out).toBe("https://example.com/api/models/");
});

test("不匹配无效版本前缀如 vbeta", () => {
  const out = buildProxyUrl(
    "https://example.com/api/models",
    new URL("https://dummy.com/vbeta/models/some-model")
  );
  // 应走标准拼接逻辑
  expect(out).toBe("https://example.com/api/models/vbeta/models/some-model");
});
tests/integration/readonly-access-endpoints.test.ts (1)

41-100: 测试辅助函数和清理逻辑实现规范。

  • createTestUsercreateTestKey 提供了明确的错误消息
  • afterAll 使用软删除避免外键约束问题
  • beforeEach 正确重置认证状态

唯一建议:可以考虑将这些辅助函数抽取到共享的 test-utils 中,因为 tests/api/my-usage-readonly.test.ts 中有几乎相同的实现。

Comment on lines +18 to +19
ENV PORT=8080
EXPOSE 8080
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 查找所有端口相关的配置
rg -n "PORT|8080|23000" --type-list | head -5
fd -type f -name "README*" -o -name "docker-compose*" -o -name ".env*" -o -name "Dockerfile*" | head -20

Repository: ding113/claude-code-hub

Length of output: 627


🏁 Script executed:

#!/bin/bash
# 在配置文件中查找端口配置
rg "8080|23000|APP_PORT|PORT" . --type md --type yml --type yaml --type dockerfile -A 2 -B 2 | head -50

Repository: ding113/claude-code-hub

Length of output: 94


🏁 Script executed:

#!/bin/bash
# 找到配置相关文件
fd -type f \( -name "README*" -o -name "docker-compose*" -o -name ".env*" -o -name "Dockerfile*" \)

Repository: ding113/claude-code-hub

Length of output: 237


🏁 Script executed:

#!/bin/bash
# 在Dockerfile中查找端口配置
cat Dockerfile | grep -n "PORT\|EXPOSE\|8080\|23000"

Repository: ding113/claude-code-hub

Length of output: 98


🏁 Script executed:

#!/bin/bash
# 在README和其他配置文件中查找端口
rg "PORT|8080|23000" . -A 2 -B 2 2>/dev/null | head -100

Repository: ding113/claude-code-hub

Length of output: 7556


🏁 Script executed:

#!/bin/bash
# 查找README文件
fd -type f -name "README*" | head -10

Repository: ding113/claude-code-hub

Length of output: 237


🏁 Script executed:

#!/bin/bash
# 查找所有提及APP_PORT的文件
rg "APP_PORT" . 2>/dev/null | head -20

Repository: ding113/claude-code-hub

Length of output: 1499


🏁 Script executed:

#!/bin/bash
# 查找所有提及23000的文件
rg "23000" . 2>/dev/null | head -20

Repository: ding113/claude-code-hub

Length of output: 2016


🏁 Script executed:

#!/bin/bash
# 读取docker-compose.yaml文件了解端口配置
cat docker-compose.yaml | head -100

Repository: ding113/claude-code-hub

Length of output: 2149


🏁 Script executed:

#!/bin/bash
# 检查应用代码中PORT的使用方式
rg "process.env.PORT|process.env.APP_PORT" src --type ts --type tsx -B 2 -A 2

Repository: ding113/claude-code-hub

Length of output: 94


🏁 Script executed:

#!/bin/bash
# 查看Dockerfile完整内容
cat Dockerfile

Repository: ding113/claude-code-hub

Length of output: 774


🏁 Script executed:

#!/bin/bash
# 查看src目录下env schema配置
cat src/lib/config/env.schema.ts | grep -A 5 -B 5 "PORT"

Repository: ding113/claude-code-hub

Length of output: 721


Dockerfile 端口配置错误:应为 3000 而非 8080

Dockerfile 第 18-19 行设置 PORT=8080 与实际部署配置不一致。根据 docker-compose.yaml,容器内部应监听端口 3000(对外通过 APP_PORT 映射为 23000)。健康检查亦使用 http://localhost:3000/api/actions/health。建议改为:

ENV PORT=3000
EXPOSE 3000
🤖 Prompt for AI Agents
In `@Dockerfile` around lines 18 - 19, The Dockerfile sets the container port to
8080 but the app and health checks expect port 3000; update the ENV PORT value
and the EXPOSE directive so they match the runtime configuration by changing ENV
PORT to 3000 and EXPOSE to 3000 (adjust the ENV PORT and EXPOSE lines
accordingly).

Comment on lines +2 to +5
import {
detectThinkingBudgetRectifierTrigger,
rectifyThinkingBudget,
} from "./thinking-budget-rectifier";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

使用 @/ 路径别名导入 src 文件
该测试位于 src/ 下,建议改用 @/ 路径别名以保持一致并减少相对路径移动风险。

修改建议
import {
  detectThinkingBudgetRectifierTrigger,
  rectifyThinkingBudget,
-} from "./thinking-budget-rectifier";
+} from "@/app/v1/_lib/proxy/thinking-budget-rectifier";

As per coding guidelines: Use path alias @/ to reference files in ./src/ directory.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import {
detectThinkingBudgetRectifierTrigger,
rectifyThinkingBudget,
} from "./thinking-budget-rectifier";
import {
detectThinkingBudgetRectifierTrigger,
rectifyThinkingBudget,
} from "@/app/v1/_lib/proxy/thinking-budget-rectifier";
🤖 Prompt for AI Agents
In `@src/app/v1/_lib/proxy/thinking-budget-rectifier.test.ts` around lines 2 - 5,
The test imports detectThinkingBudgetRectifierTrigger and rectifyThinkingBudget
using a relative path; update the import statement to use the project path alias
(start imports with "@/") so modules are resolved from src via the alias—for
example replace the relative import of "./thinking-budget-rectifier" with
"@/app/v1/_lib/proxy/thinking-budget-rectifier" (keeping the same exported
symbols detectThinkingBudgetRectifierTrigger and rectifyThinkingBudget) to
follow the coding guideline.

Comment on lines +73 to +78
if (!message.thinking || typeof message.thinking !== "object") {
message.thinking = {};
}

const thinkingObj = message.thinking as Record<string, unknown>;
thinkingObj.type = "enabled";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

thinking 为数组时应视为无效并重建
数组同样是 object,当前逻辑会把数组当作对象写入字段,建议显式排除。

修改建议
-  if (!message.thinking || typeof message.thinking !== "object") {
+  if (
+    !message.thinking ||
+    typeof message.thinking !== "object" ||
+    Array.isArray(message.thinking)
+  ) {
     message.thinking = {};
   }
🤖 Prompt for AI Agents
In `@src/app/v1/_lib/proxy/thinking-budget-rectifier.ts` around lines 73 - 78,
Current check treats arrays as objects and will mutate them; change the guard so
message.thinking is only reused when it's a non-null plain object (i.e., typeof
message.thinking === "object" && message.thinking !== null &&
!Array.isArray(message.thinking)), otherwise reassign message.thinking = {};
then cast to thinkingObj and set thinkingObj.type = "enabled" as before
(referencing message.thinking and thinkingObj).

Comment on lines +78 to +90
case "thinking_budget_rectifier":
return JSON.stringify([
setting.type,
setting.hit,
setting.providerId ?? null,
setting.trigger,
setting.attemptNumber,
setting.retryAttemptNumber,
setting.before.maxTokens,
setting.before.thinkingBudgetTokens,
setting.after.maxTokens,
setting.after.thinkingBudgetTokens,
]);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

去重键遗漏 thinkingType,可能合并不同事件。

如果仅 thinkingType 发生变化而 tokens 不变,当前 key 会把两次事件合并,导致审计信息丢失。建议把 before/after 的 thinkingType 纳入 key。

修复建议
     case "thinking_budget_rectifier":
       return JSON.stringify([
         setting.type,
         setting.hit,
         setting.providerId ?? null,
         setting.trigger,
         setting.attemptNumber,
         setting.retryAttemptNumber,
         setting.before.maxTokens,
+        setting.before.thinkingType,
         setting.before.thinkingBudgetTokens,
         setting.after.maxTokens,
+        setting.after.thinkingType,
         setting.after.thinkingBudgetTokens,
       ]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
case "thinking_budget_rectifier":
return JSON.stringify([
setting.type,
setting.hit,
setting.providerId ?? null,
setting.trigger,
setting.attemptNumber,
setting.retryAttemptNumber,
setting.before.maxTokens,
setting.before.thinkingBudgetTokens,
setting.after.maxTokens,
setting.after.thinkingBudgetTokens,
]);
case "thinking_budget_rectifier":
return JSON.stringify([
setting.type,
setting.hit,
setting.providerId ?? null,
setting.trigger,
setting.attemptNumber,
setting.retryAttemptNumber,
setting.before.maxTokens,
setting.before.thinkingType,
setting.before.thinkingBudgetTokens,
setting.after.maxTokens,
setting.after.thinkingType,
setting.after.thinkingBudgetTokens,
]);
🤖 Prompt for AI Agents
In `@src/lib/utils/special-settings.ts` around lines 78 - 90, The deduplication
key for the "thinking_budget_rectifier" case omits thinkingType, which can merge
distinct events; update the key generation in the switch branch handling
"thinking_budget_rectifier" (in special-settings.ts) to include
setting.before.thinkingType and setting.after.thinkingType in the JSON.stringify
array alongside the existing fields (e.g., setting.before.maxTokens,
setting.before.thinkingBudgetTokens, setting.after.maxTokens,
setting.after.thinkingBudgetTokens) so events that differ only by thinkingType
remain distinct.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ding113, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This release focuses on simplifying the core API gateway by removing complex cross-format request/response conversion layers, promoting a more direct and native API interaction model. Concurrently, it introduces advanced control mechanisms for Anthropic providers through configurable parameter overrides and an automated error rectification system for thinking budget issues. Additionally, the update enhances the utility of read-only API keys by extending access to several informational endpoints, improving integration capabilities for external clients.

Highlights

  • API Gateway Simplification: Removed all cross-format API conversion logic (e.g., Claude to OpenAI, Codex to Gemini), streamlining the API gateway to enforce strict native format routing. This significantly simplifies the proxy's internal architecture and reduces potential conversion-related issues.
  • Anthropic Parameter Overrides: Introduced new provider-level configuration options to allow administrators to override max_tokens and thinking.budget_tokens for Anthropic providers. This includes validation, clamping logic (e.g., budget_tokens must be less than max_tokens), and detailed auditing of applied overrides.
  • Anthropic Thinking Budget Rectifier: Implemented a new system-level rectifier that automatically detects and corrects budget_tokens < 1024 errors from Anthropic APIs. When triggered, it sets thinking.budget_tokens to its maximum (32000) and max_tokens to 64000 (if needed), then retries the request once.
  • Enhanced Read-Only API Access: Expanded read-only access for several WebUI API endpoints, including user lists, usage statistics, and active sessions. API keys with canLoginWebUi=false can now access these endpoints, improving flexibility for client integrations while maintaining data isolation for individual users.
  • Database Schema Migrations: Added new columns anthropic_max_tokens_preference and anthropic_thinking_budget_preference to the providers table, and enable_thinking_budget_rectifier to the system_settings table to support the new features.
  • Codex Session Extraction Refinement: Simplified the Codex session ID extraction logic by removing the isCodexClient check and related User-Agent pattern matching, focusing solely on session ID parsing from headers and body.
Changelog
  • Dockerfile
    • Added drizzle directory to be copied during the Docker build process, ensuring database migration files are included.
  • README.en.md
    • Updated description of 'OpenAI compatibility layer' to 'OpenAI-compatible endpoint', clarifying support for /v1/chat/completions with strict same-format routing and no cross-format conversion.
    • Revised description of 'Forwarding & compatibility' to 'Forwarding & response handling', detailing ProxyForwarder and ProxyResponseHandler roles in preserving endpoint-native formats.
  • README.md
    • Updated Chinese description of 'OpenAI 兼容层' to 'OpenAI 兼容端点', clarifying strict same-format routing.
    • Revised Chinese description of '转发与兼容' to '转发与响应处理', detailing ProxyForwarder and ProxyResponseHandler roles.
  • drizzle/0060_bored_gertrude_yorkes.sql
    • Added anthropic_max_tokens_preference (varchar(20)) to the providers table.
    • Added anthropic_thinking_budget_preference (varchar(20)) to the providers table.
    • Dropped default value for schedule_timezone in notification_target_bindings table.
  • drizzle/0061_exotic_trauma.sql
    • Added enable_thinking_budget_rectifier (boolean, default true, not null) to the system_settings table.
  • drizzle/meta/0060_snapshot.json
    • Updated Drizzle ORM snapshot to reflect schema changes from 0060_bored_gertrude_yorkes.sql.
  • drizzle/meta/0061_snapshot.json
    • Updated Drizzle ORM snapshot to reflect schema changes from 0061_exotic_trauma.sql.
  • drizzle/meta/_journal.json
    • Added new migration entries for 0060_bored_gertrude_yorkes and 0061_exotic_trauma.
  • messages/en/settings/config.json
    • Added new translation keys for enableThinkingBudgetRectifier and enableThinkingBudgetRectifierDesc.
  • messages/en/settings/providers/form/sections.json
    • Removed the 'Codex Instructions Policy' section and related fields.
    • Added 'Codex Parameter Overrides' section with title and desc.
    • Removed the 'Join Claude Routing Pool' section.
    • Added 'Anthropic Overrides' section including maxTokens and thinkingBudget override options with labels, help texts, and placeholders.
  • messages/en/settings/providers/form/strings.json
    • Removed various translation keys related to 'Codex Strategy' and 'Join Claude Pool'.
  • messages/ja/settings/config.json
    • Added Japanese translation keys for enableThinkingBudgetRectifier and enableThinkingBudgetRectifierDesc.
  • messages/ja/settings/providers/form/sections.json
    • Removed Japanese translation for 'Codex Instructions Policy' section.
    • Added Japanese translation for 'Codex パラメータオーバーライド' section.
    • Removed Japanese translation for 'Claude ルーティングプールに参加' section.
    • Added Japanese translation for 'Anthropic オーバーライド' section including Max Tokens オーバーライド and 思考予算オーバーライド.
  • messages/ja/settings/providers/form/strings.json
    • Removed various Japanese translation keys related to 'Codex Strategy' and 'Join Claude Pool'.
  • messages/providers-i18n-additions.json
    • Removed Chinese and English translation keys related to 'joinClaudePool' and 'codexStrategyConfig'.
  • messages/ru/settings/config.json
    • Added Russian translation keys for enableThinkingBudgetRectifier and enableThinkingBudgetRectifierDesc.
  • messages/ru/settings/providers/form/sections.json
    • Removed Russian translation for 'Политика Codex Instructions' section.
    • Added Russian translation for 'Переопределение параметров Codex' section.
    • Removed Russian translation for 'Включить пул маршрутизации Claude' section.
    • Added Russian translation for 'Anthropic Overrides' section including Переопределение Max Tokens and Переопределение бюджета размышлений.
  • messages/ru/settings/providers/form/strings.json
    • Removed various Russian translation keys related to 'Codex Strategy' and 'Join Claude Pool'.
  • messages/zh-CN/provider-form-temp.json
    • Removed Chinese translation keys related to 'joinClaudePool' and 'codexStrategy'.
  • messages/zh-CN/settings/config.json
    • Added Chinese translation keys for enableThinkingBudgetRectifier and enableThinkingBudgetRectifierDesc.
  • messages/zh-CN/settings/providers/form/sections.json
    • Removed Chinese translation for '加入 Claude 调度池' section.
    • Added Chinese translation for 'Codex 参数覆写' section.
    • Added Chinese translation for 'Anthropic 覆写' section including Max Tokens 覆写 and 思考预算覆写.
  • messages/zh-CN/settings/providers/form/strings.json
    • Removed various Chinese translation keys related to 'joinClaudePool' and 'codexStrategyConfig'.
  • messages/zh-TW/settings/config.json
    • Added Traditional Chinese translation keys for enableThinkingBudgetRectifier and enableThinkingBudgetRectifierDesc.
  • messages/zh-TW/settings/providers/form/sections.json
    • Removed Traditional Chinese translation for 'Codex Instructions 策略設定' section.
    • Added Traditional Chinese translation for 'Codex 參數覆寫' section.
    • Removed Traditional Chinese translation for '加入 Claude 調度池' section.
    • Added Traditional Chinese translation for 'Anthropic 覆寫' section including Max Tokens 覆寫 and 思考預算覆寫.
  • messages/zh-TW/settings/providers/form/strings.json
    • Removed various Traditional Chinese translation keys related to 'Codex Strategy' and 'Join Claude Pool'.
  • scripts/audit-settings-placeholders.allowlist.json
    • Removed providers.form.codexStrategyConfig from the allowlist, reflecting its removal.
  • src/actions/providers.ts
    • Removed joinClaudePool and codexInstructionsStrategy from provider data structures.
    • Added anthropicMaxTokensPreference and anthropicThinkingBudgetPreference to provider data structures.
  • src/actions/system-config.ts
    • Added enableThinkingBudgetRectifier to saveSystemSettings function parameters and update logic.
  • src/app/[locale]/dashboard/availability/_components/endpoint/endpoint-tab.tsx
    • Removed RefreshCw icon import, indicating minor UI adjustments.
  • src/app/[locale]/dashboard/availability/_components/endpoint/latency-curve.tsx
    • Removed ResponsiveContainer and ChartTooltipContent imports, simplifying chart rendering.
  • src/app/[locale]/dashboard/availability/_components/endpoint/probe-terminal.tsx
    • Removed Trash2 icon import, indicating minor UI adjustments.
    • Updated useEffect dependency for auto-scrolling to logs.length for more precise re-scroll triggering.
    • Removed unused Icon variable in map function.
  • src/app/[locale]/dashboard/availability/_components/provider/latency-chart.tsx
    • Removed ResponsiveContainer and ChartTooltipContent imports, simplifying chart rendering.
  • src/app/[locale]/dashboard/logs/_components/error-details-dialog/components/LogicTraceTab.tsx
    • Renamed statusCode prop to _statusCode to mark it as unused in the component logic.
  • src/app/[locale]/settings/config/_components/system-settings-form.tsx
    • Integrated enableThinkingBudgetRectifier into the system settings form, including state management, update logic, and UI rendering with a new switch component.
  • src/app/[locale]/settings/config/page.tsx
    • Added enableThinkingBudgetRectifier to the initial system settings fetched and passed to the form component.
  • src/app/[locale]/settings/notifications/_components/global-settings-card.tsx
    • Removed Power icon import, indicating minor UI adjustments.
  • src/app/[locale]/settings/notifications/_components/webhook-targets-section.tsx
    • Removed cn utility import, indicating minor UI adjustments.
  • src/app/[locale]/settings/prices/_components/price-list.tsx
    • Renamed locale prop to _locale to mark it as unused in the component logic.
  • src/app/[locale]/settings/providers/_components/forms/provider-form.legacy.tsx
    • Removed joinClaudePool state and related logic.
    • Updated provider creation and update payloads to remove join_claude_pool.
  • src/app/[locale]/settings/providers/_components/forms/provider-form/index.tsx
    • Removed join_claude_pool from provider creation/update payloads.
    • Added anthropic_max_tokens_preference and anthropic_thinking_budget_preference to provider creation/update payloads.
  • src/app/[locale]/settings/providers/_components/forms/provider-form/provider-form-context.tsx
    • Removed joinClaudePool from initial state and reducer actions.
    • Added anthropicMaxTokensPreference and anthropicThinkingBudgetPreference to initial state and reducer actions.
  • src/app/[locale]/settings/providers/_components/forms/provider-form/provider-form-types.ts
    • Removed CodexInstructionsStrategy type.
    • Removed joinClaudePool from RoutingState and ProviderFormAction.
    • Added AnthropicMaxTokensPreference and AnthropicThinkingBudgetPreference types.
    • Added anthropicMaxTokensPreference and anthropicThinkingBudgetPreference to RoutingState.
    • Added SET_ANTHROPIC_MAX_TOKENS and SET_ANTHROPIC_THINKING_BUDGET actions to ProviderFormAction.
  • src/app/[locale]/settings/providers/_components/forms/provider-form/sections/routing-section.tsx
    • Removed Users icon import.
    • Removed joinClaudePool logic and UI elements.
    • Updated 'Codex Overrides' section title and description.
    • Added 'Anthropic Overrides' section with UI for maxTokens and thinkingBudget preferences, including select, input, and tooltip components.
  • src/app/v1/_lib/codex/tests/session-extractor.test.ts
    • Removed isCodexClient import and related tests.
    • Simplified extractCodexSessionId calls by removing the userAgent parameter.
  • src/app/v1/_lib/codex/chat-completions-handler.ts
    • Removed this file, indicating the removal of the OpenAI Compatible API handler for chat completions and its underlying conversion logic.
  • src/app/v1/_lib/codex/codex-cli-adapter.ts
    • Removed this file, indicating the removal of Codex CLI adapter logic for injecting system instructions.
  • src/app/v1/_lib/codex/constants/codex-cli-instructions.ts
    • Removed this file, which contained Codex CLI system instructions constants.
  • src/app/v1/_lib/codex/constants/codex-instructions.ts
    • Removed this file, which contained official Codex instructions and related utility functions.
  • src/app/v1/_lib/codex/session-extractor.ts
    • Removed isCodexClient function and CODEX_CLI_PATTERN constant.
    • Removed isCodexClient from CodexSessionExtractionResult interface.
    • Simplified extractCodexSessionId function by removing userAgent parameter and isCodexClient logic.
  • src/app/v1/_lib/codex/utils/request-sanitizer.ts
    • Removed this file, indicating the removal of Codex request sanitization logic.
  • src/app/v1/_lib/converters/claude-to-codex/index.ts
    • Removed this file, indicating the removal of Claude to Codex converter registration.
  • src/app/v1/_lib/converters/claude-to-codex/request.ts
    • Removed this file, which contained Claude to Codex request transformation logic.
  • src/app/v1/_lib/converters/claude-to-codex/response.ts
    • Removed this file, which contained Claude to Codex response transformation logic.
  • src/app/v1/_lib/converters/claude-to-openai/index.ts
    • Removed this file, indicating the removal of Claude to OpenAI converter registration.
  • src/app/v1/_lib/converters/claude-to-openai/request.ts
    • Removed this file, which contained Claude to OpenAI request transformation logic.
  • src/app/v1/_lib/converters/codex-to-claude/index.ts
    • Removed this file, indicating the removal of Codex to Claude converter registration.
  • src/app/v1/_lib/converters/codex-to-claude/request.ts
    • Removed this file, which contained Codex to Claude request transformation logic.
  • src/app/v1/_lib/converters/codex-to-claude/response.ts
    • Removed this file, which contained Codex to Claude response transformation logic.
  • src/app/v1/_lib/converters/codex-to-openai/index.ts
    • Removed this file, indicating the removal of Codex to OpenAI converter registration.
  • src/app/v1/_lib/converters/codex-to-openai/request.ts
    • Removed this file, which contained Codex to OpenAI request transformation logic.
  • src/app/v1/_lib/converters/codex-to-openai/response.ts
    • Removed this file, which contained Codex to OpenAI response transformation logic.
  • src/app/v1/_lib/converters/gemini-cli-to-claude/index.ts
    • Removed this file, indicating the removal of Gemini CLI to Claude converter registration.
  • src/app/v1/_lib/converters/gemini-cli-to-claude/request.ts
    • Removed this file, which contained Gemini CLI to Claude request transformation logic.
  • src/app/v1/_lib/converters/gemini-cli-to-claude/response.ts
    • Removed this file, which contained Gemini CLI to Claude response transformation logic.
  • src/app/v1/_lib/converters/gemini-cli-to-openai/index.ts
    • Removed this file, indicating the removal of Gemini CLI to OpenAI converter registration.
  • src/app/v1/_lib/converters/gemini-cli-to-openai/request.ts
    • Removed this file, which contained Gemini CLI to OpenAI request transformation logic.
  • src/app/v1/_lib/converters/gemini-cli-to-openai/response.ts
    • Removed this file, which contained Gemini CLI to OpenAI response transformation logic.
  • src/app/v1/_lib/converters/index.ts
    • Removed this file, which served as the main entry point for converter registrations.
  • src/app/v1/_lib/converters/openai-to-claude/index.ts
    • Removed this file, indicating the removal of OpenAI to Claude converter registration.
  • src/app/v1/_lib/converters/openai-to-claude/request.ts
    • Removed this file, which contained OpenAI to Claude request transformation logic.
  • src/app/v1/_lib/converters/openai-to-claude/response.ts
    • Removed this file, which contained OpenAI to Claude response transformation logic.
  • src/app/v1/_lib/converters/openai-to-codex/index.ts
    • Removed this file, indicating the removal of OpenAI to Codex converter registration.
  • src/app/v1/_lib/converters/openai-to-codex/request.ts
    • Removed this file, which contained OpenAI to Codex request transformation logic.
  • src/app/v1/_lib/converters/registry.ts
    • Removed this file, which contained the core TransformerRegistry class and related functions.
  • src/app/v1/_lib/converters/tool-name-mapper.ts
    • Removed this file, which contained the ToolNameMapper class for handling tool name length limits.
  • src/app/v1/_lib/converters/types.ts
    • Removed this file, which contained common types for API format converters.
  • src/app/v1/_lib/proxy/format-mapper.ts
    • Removed mapClientFormatToTransformer, mapProviderTypeToTransformer, and mapTransformerFormatToClient functions, reflecting the removal of explicit format conversion layers.
  • src/app/v1/_lib/proxy/forwarder.ts
    • Removed Agent import from undici.
    • Removed getProxyAgentForProvider type import ProxyConfigWithCacheKey.
    • Removed imports for isOfficialCodexClient, sanitizeCodexRequest, defaultRegistry, mapClientFormatToTransformer, mapProviderTypeToTransformer.
    • Added applyAnthropicProviderOverridesWithAudit import.
    • Added detectThinkingBudgetRectifierTrigger and rectifyThinkingBudget imports.
    • Removed request format transformation logic.
    • Removed Codex request sanitization logic.
    • Implemented Anthropic provider parameter overrides with auditing, applying max_tokens and thinking.budget_tokens preferences.
    • Implemented Anthropic thinking budget rectifier logic, detecting errors and retrying with adjusted parameters.
  • src/app/v1/_lib/proxy/provider-selector.ts
    • Simplified providerSupportsModel logic by removing checks for joinClaudePool for non-Anthropic providers, aligning with the removal of cross-format conversion.
  • src/app/v1/_lib/proxy/response-handler.ts
    • Removed imports for defaultRegistry, Format, TransformState, mapClientFormatToTransformer, mapProviderTypeToTransformer.
    • Removed all response format transformation logic for both non-stream and stream responses, reflecting the shift to native format routing.
  • src/app/v1/_lib/proxy/thinking-budget-rectifier.test.ts
    • Added new unit tests for detectThinkingBudgetRectifierTrigger and rectifyThinkingBudget functions, covering various scenarios including error message detection, parameter adjustments, and audit tracking.
  • src/app/v1/_lib/proxy/thinking-budget-rectifier.ts
    • Added new file containing detectThinkingBudgetRectifierTrigger and rectifyThinkingBudget functions for Anthropic thinking budget error rectification.
  • src/app/v1/_lib/url.ts
    • Refactored buildProxyUrl to use regex for more robust endpoint matching, supporting version prefixes like v1beta and v1internal.
  • src/components/ui/relative-time.tsx
    • Removed format as formatDate import, indicating minor dependency cleanup.
  • src/drizzle/schema.ts
    • Added anthropicMaxTokensPreference and anthropicThinkingBudgetPreference columns to the providers table.
    • Added enableThinkingBudgetRectifier column to the system_settings table.
  • src/lib/anthropic/provider-overrides.ts
    • Added new file containing applyAnthropicProviderOverrides and applyAnthropicProviderOverridesWithAudit functions for applying and auditing Anthropic provider parameter overrides.
  • src/lib/config/system-settings-cache.ts
    • Added enableThinkingBudgetRectifier to DEFAULT_SETTINGS and getCachedSystemSettings.
  • src/lib/session-manager.ts
    • Simplified extractClientSessionId by removing _userAgent parameter and isCodexClient check from extractCodexSessionId call.
  • src/lib/utils/special-settings.ts
    • Added thinking_budget_rectifier type to SpecialSetting and implemented its key building logic.
  • src/lib/validation/schemas.ts
    • Added ANTHROPIC_MAX_TOKENS_PREFERENCE and ANTHROPIC_THINKING_BUDGET_PREFERENCE schemas for validation.
    • Removed join_claude_pool and codex_instructions_strategy from CreateProviderSchema and UpdateProviderSchema.
    • Added anthropic_max_tokens_preference and anthropic_thinking_budget_preference to CreateProviderSchema and UpdateProviderSchema.
    • Added superRefine logic to provider schemas to ensure thinking.budget_tokens is less than max_tokens when both are set.
    • Added enableThinkingBudgetRectifier to UpdateSystemSettingsSchema.
  • src/repository/_shared/transformers.ts
    • Removed codexInstructionsStrategy and joinClaudePool from toProvider transformation.
    • Added anthropicMaxTokensPreference and anthropicThinkingBudgetPreference to toProvider transformation.
    • Added enableThinkingBudgetRectifier to toSystemSettings transformation.
  • src/repository/provider.ts
    • Removed joinClaudePool and codexInstructionsStrategy from provider creation and update logic.
    • Added anthropicMaxTokensPreference and anthropicThinkingBudgetPreference to provider creation and update logic.
  • src/repository/system-config.ts
    • Added enableThinkingBudgetRectifier to createFallbackSettings and getSystemSettings.
    • Added logic to updateSystemSettings to handle enableThinkingBudgetRectifier updates.
  • src/types/provider.ts
    • Removed CodexInstructionsStrategy type.
    • Removed joinClaudePool and codexInstructionsStrategy from Provider and ProviderDisplay interfaces.
    • Added AnthropicMaxTokensPreference and AnthropicThinkingBudgetPreference types.
    • Added anthropicMaxTokensPreference and anthropicThinkingBudgetPreference to Provider and ProviderDisplay interfaces.
    • Removed join_claude_pool and codex_instructions_strategy from CreateProviderData and UpdateProviderData.
    • Added anthropic_max_tokens_preference and anthropic_thinking_budget_preference to CreateProviderData and UpdateProviderData.
  • src/types/special-settings.ts
    • Added ThinkingBudgetRectifierSpecialSetting type and included it in the SpecialSetting union type.
  • src/types/system-config.ts
    • Added enableThinkingBudgetRectifier to SystemSettings and UpdateSystemSettingsInput interfaces.
  • tests/api/my-usage-readonly.test.ts
    • Updated test descriptions to reflect that allowReadOnlyAccess endpoints are now supported for read-only keys.
    • Modified tests to assert successful access (status 200) for getUsers and getUsageLogs with read-only keys, and verified data isolation.
  • tests/integration/readonly-access-endpoints.test.ts
    • Added new integration test file to verify that API keys with canLoginWebUi=false can access endpoints marked with allowReadOnlyAccess: true.
    • Includes tests for getUsers, getUserLimitUsage, getUserStatistics, getUsageLogs, getOverviewData, getActiveSessions, and verifies data isolation and admin-only endpoint restrictions.
  • tests/unit/actions/providers.test.ts
    • Removed joinClaudePool and codexInstructionsStrategy from mock provider data.
  • tests/unit/actions/user-all-limit-window.test.ts
    • Updated getTimeRangeForPeriodWithModeMock implementation to use _resetTime parameter, indicating it's unused in the mock.
  • tests/unit/app/v1/url.test.ts
    • Added new tests for buildProxyUrl to ensure correct handling of version prefixes (e.g., v1beta, v1internal, v2) when the base URL ends with /models.
  • tests/unit/proxy/anthropic-provider-overrides.test.ts
    • Added new unit test file for applyAnthropicProviderOverrides and applyAnthropicProviderOverridesWithAudit functions, covering provider type filtering, max_tokens and thinking.budget_tokens overrides, clamping logic, and audit trail generation.
  • tests/unit/proxy/chat-completions-handler-guard-pipeline.test.ts
    • Removed this test file, corresponding to the removal of the chat completions handler and its pipeline.
  • tests/unit/proxy/codex-request-sanitizer.test.ts
    • Removed this test file, corresponding to the removal of Codex request sanitization logic.
  • tests/unit/proxy/converters-tool-result-nonstream.test.ts
    • Removed this test file, corresponding to the removal of non-stream converter tests.
  • tests/unit/proxy/openai-to-codex-request.test.ts
    • Removed this test file, corresponding to the removal of OpenAI to Codex request conversion tests.
  • tests/unit/proxy/provider-selector-format-compatibility.test.ts
    • Added new unit test file for ProxyProviderResolver.pickRandomProvider to verify format/providerType compatibility, ensuring correct provider selection and rejection based on client request format.
  • tests/unit/proxy/proxy-forwarder-endpoint-audit.test.ts
    • Removed joinClaudePool and codexInstructionsStrategy from mock provider data.
  • tests/unit/proxy/proxy-forwarder-retry-limit.test.ts
    • Removed joinClaudePool and codexInstructionsStrategy from mock provider data.
  • tests/unit/settings/providers/provider-form-total-limit-ui.test.tsx
    • Removed joinClaudePool and codexInstructionsStrategy from mock provider data.
  • tests/unit/settings/providers/provider-vendor-view-circuit-ui.test.tsx
    • Removed joinClaudePool and codexInstructionsStrategy from mock provider data.
  • tests/unit/settings/providers/vendor-keys-compact-list-ui.test.tsx
    • Removed joinClaudePool and codexInstructionsStrategy from mock provider data.
Activity
  • No human activity (comments, reviews, progress) was detected for this pull request.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a major architectural refactoring by removing the complex format converters, which significantly simplifies the codebase and improves maintainability. It also adds several valuable features, including Anthropic provider overrides and a thinking budget rectifier, along with important bug fixes and expanded readonly API access. The changes are extensive but well-structured and thoroughly tested. My review found one area for improvement in the new Dockerfile to optimize the production image size.

# 关键:确保复制了所有必要的文件,特别是 drizzle 文件夹
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The runner stage copies the node_modules directory from the builder stage. The builder stage installs all dependencies, including devDependencies, by running bun install. This means the final production image contains development dependencies, which increases its size and potential security surface.

It's a best practice to only include production dependencies in the final image. You can achieve this by adding a new stage specifically for production dependencies:

# After the 'builder' stage
FROM oven/bun:debian AS prod-deps
WORKDIR /app
COPY package.json bun.lockb* ./
RUN bun install --frozen-lockfile --production

# In the 'runner' stage
# ...
COPY --from=prod-deps /app/node_modules ./node_modules
# ...

This change will result in a smaller and more secure production image.

@github-actions github-actions bot added the size/XL Extra Large PR (> 1000 lines) label Feb 3, 2026
@ding113 ding113 merged commit 1136b0f into main Feb 3, 2026
26 of 32 checks passed
@github-project-automation github-project-automation bot moved this from Backlog to Done in Claude Code Hub Roadmap Feb 3, 2026
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

This is a major release (v0.5.3) that removes the format conversion layer (~8,800 lines) and introduces Anthropic provider parameter overrides with a thinking budget rectifier. The code changes are well-structured with comprehensive test coverage (209 tests for rectifier, 36 for overrides, 358 lines for readonly access).

PR Size: XL

  • Lines changed: 18,341 (8,908 additions + 9,433 deletions)
  • Files changed: 114

Split Suggestion for XL PR: This PR combines multiple features that could have been separate PRs:

  1. Format converter removal (breaking change)
  2. Anthropic provider overrides feature
  3. Thinking budget rectifier feature
  4. Readonly API access extension
  5. Zeabur deployment support

For future releases, consider splitting breaking changes from new features.

Issues Found

Category Critical High Medium Low
Logic/Bugs 0 0 0 0
Security 0 0 0 0
Error Handling 0 0 0 0
Types 0 0 0 0
Comments/Docs 0 0 1 0
Tests 0 0 0 0
Simplification 0 0 0 0

Medium Priority Issues (Should Fix)

[COMMENT-OUTDATED] CLAUDE.md not updated after converter removal

CLAUDE.md (lines 89-90, 117) still references converters/ and codex/ directories that were removed in this PR. While CLAUDE.md is not part of the diff, it should be updated to maintain documentation accuracy:

  • Line 89: ├── converters/ # Format converters (claude/openai/codex/gemini) - directory removed
  • Line 90: └── codex/ # Codex CLI adapter - directory removed
  • Line 117: - **Format Converters** (converters/): Bidirectional format translation - feature removed

Suggested action: Update CLAUDE.md in a follow-up commit or separate PR.

Review Coverage

  • Logic and correctness - Clean
  • Security (OWASP Top 10) - Clean
  • Error handling - Clean (non-blocking persistence failures are intentional)
  • Type safety - Clean
  • Documentation accuracy - 1 issue (CLAUDE.md outdated)
  • Test coverage - Excellent (209 + 36 + 358 new test lines)
  • Code clarity - Good

Positive Observations (for context only)

The new code demonstrates good practices:

  • Thinking budget rectifier has single-retry enforcement to prevent infinite loops
  • Provider overrides include audit trail for debugging
  • Clamping logic correctly handles edge cases (budget_tokens < 1024 skip)
  • Comprehensive test coverage for all new features

Automated review by Claude AI

z
.string()
.regex(/^\d+$/, "max_tokens must be 'inherit' or a numeric string")
.refine(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MEDIUM] [STANDARD-VIOLATION] Non-i18n validation strings added for Anthropic override preferences

Why this is a problem: Repo rule requires: "i18n Required - All user-facing strings must use i18n (5 languages supported). Never hardcode display text". These .regex(..., "max_tokens must be ...") / .refine(..., { message: "..." }) messages can reach the UI (provider form shows res.error in a toast), so users will see hardcoded English regardless of locale.

Suggested fix (use error codes + existing zod helpers, consistent with other actions):

// src/lib/validation/schemas.ts
import { ERROR_CODES } from "@/lib/utils/error-messages";

const ANTHROPIC_MAX_TOKENS_PREFERENCE = z.union([
  z.literal("inherit"),
  z
    .string()
    .regex(/^\d+$/, ERROR_CODES.INVALID_FORMAT)
    .refine(
      (val) => {
        const num = Number.parseInt(val, 10);
        return num >= 1 && num <= 64000;
      },
      { message: ERROR_CODES.INVALID_RANGE }
    ),
]);

// src/actions/providers.ts
import { extractZodErrorCode, formatZodError } from "@/lib/utils/zod-i18n";

const parsed = UpdateProviderSchema.safeParse(data);
if (!parsed.success) {
  return {
    ok: false,
    error: formatZodError(parsed.error),
    errorCode: extractZodErrorCode(parsed.error),
  };
}

// Gemini usageMetadata - 改为 last-wins 策略
// 跳过 applyUsageValue(它是 first-wins),直接更新
if (data.usageMetadata && typeof data.usageMetadata === "object") {
const extracted = extractUsageMetrics(data.usageMetadata);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[HIGH] [TEST-MISSING-CRITICAL] Gemini SSE usageMetadata last-wins logic has no regression test

Why this is a problem: This PR changes SSE usage parsing to treat Gemini usageMetadata as last-wins (to avoid missing output tokens in streaming). Without a unit test, it is easy to regress back to first-wins and silently undercount output_tokens again (billing/usage impact).

Suggested fix (add a focused test case):

// tests/unit/proxy/extract-usage-metrics.test.ts
it("Gemini SSE: uses the last usageMetadata event (last-wins)", () => {
  const sse = [
    'data: {"usageMetadata":{"promptTokenCount":1000}}',
    "",
    'data: {"usageMetadata":{"promptTokenCount":1000,"candidatesTokenCount":500,"thoughtsTokenCount":100}}',
    "",
  ].join("\n");

  const result = parseUsageFromResponseText(sse, "gemini");

  expect(result.usageMetrics?.output_tokens).toBe(600);
});

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

This is an XL PR spanning multiple independent areas (proxy behavior, permissions, billing usage parsing, provider UI/schema/migrations). The breadth and size make it difficult to validate critical paths thoroughly in one review and increase regression risk.

PR Size: XL

  • Lines changed: 18341
  • Files changed: 114
  • Split suggestions:
    • Split the proxy “same-format routing / converter removal” refactor into its own PR.
    • Split the read-only key access expansion (+ integration tests) into its own PR.
    • Split Anthropic provider overrides + thinking budget rectifier + DB migrations + UI changes into its own PR.
    • Split URL builder changes (buildProxyUrl) + unit tests + docs/Dockerfile into a separate PR.

Issues Found

Category Critical High Medium Low
Logic/Bugs 0 0 0 0
Security 0 0 0 0
Error Handling 0 0 1 0
Types 0 0 0 0
Comments/Docs 0 0 0 0
Tests 0 1 0 0
Simplification 0 0 0 0

Critical Issues (Must Fix)

None.

High Priority Issues (Should Fix)

  • (Confidence 90) src/app/v1/_lib/proxy/response-handler.ts:1556 – Gemini SSE usageMetadata last-wins logic was added/changed but lacks a regression unit test to prevent output token undercount in streaming.
  • (Confidence 80) src/lib/validation/schemas.ts:34 – New hardcoded English validation messages for Anthropic override preferences can surface to UI error toasts, violating the i18n requirement.

Review Coverage

  • Logic and correctness
  • Security (OWASP Top 10)
  • Error handling
  • Type safety
  • Documentation accuracy
  • Test coverage
  • Code clarity

Automated review by Codex AI

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Identified PR #712 (release v0.5.3) and applied label size/XL.
  • Posted 2 inline review comments (diff-only):
    • src/app/v1/_lib/proxy/response-handler.ts (Gemini SSE usageMetadata last-wins): missing regression unit test.
    • src/lib/validation/schemas.ts (Anthropic override preference schemas): hardcoded (non-i18n) validation strings that can surface to UI toasts.
  • Submitted the required PR review summary via gh pr review --comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core area:i18n enhancement New feature or request size/XL Extra Large PR (> 1000 lines)

Projects

Status: Done

5 participants