Skip to content

Comments

release v0.5.7#785

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

release v0.5.7#785
ding113 merged 6 commits intomainfrom
dev

Conversation

@ding113
Copy link
Owner

@ding113 ding113 commented Feb 14, 2026

Summary

Release v0.5.7 - This release introduces a new billing header rectifier feature, strengthens rate limiting and session management, improves statistics query performance, and enhances agent pool stability.

Key Changes

1. Billing Header Rectifier (New Feature)

  • Added `enable_billing_header_rectifier` system setting (default: `true`)
  • New proxy component `billing-header-rectifier.ts` strips `x-anthropic-billing-header` from upstream responses
  • Prevents billing header leakage to clients while preserving internal tracking
  • Fixes compatibility with non-native Anthropic upstreams (e.g., Amazon Bedrock)
  • Resolves 400 errors for Claude Code client v2.1.36+

2. Rate Limit & Session Management Improvements

  • Fixed: Concurrent session limit bypass issue with multi-key scenarios (修复多 Key 并发下 User 并发 Session 上限可能被击穿 #776)
  • Enhanced: Request cost precision in rate limiting (now using string multiplication for accuracy)
  • Improved: Special settings handling for rate limit configurations
  • Refactored: Rate limit guard logic for better maintainability
  • Added: Atomic Lua script for dual-dimension (key + user) concurrent session checking

3. Statistics & Query Performance

  • Optimized: Total cost queries on quotas/users page now use batch queries
  • Fixed: Date underflow issue in billing queries with large `maxAgeDays` values
  • Fixed: All-time total cost queries now correctly skip date filters
  • Added: Batch query functions `sumUserTotalCostBatch` and `sumKeyTotalCostBatchByIds`
  • Changed: `ALL_TIME_MAX_AGE_DAYS` from 36500 to `Infinity` for proper all-time queries

4. Agent Pool & Connection Management

  • Strengthened: Agent pool cleanup logic with better stats transparency
  • Enhanced: Error handling and logging in agent pool operations
  • Fixed: Critical blocking issue - changed `close()` to `destroy()` for agent cleanup
  • Improved: Fire-and-forget pattern to avoid waiting on in-flight requests

5. Infrastructure & Refactoring

  • Database migration 0067: Added `enable_billing_header_rectifier` column to `system_settings`
  • Added i18n strings for the new billing header rectifier setting (5 languages)
  • Improved TypeScript types for session and rate limit handling
  • Enhanced test coverage across multiple modules
  • Added auto-recovery for ZSET migration from legacy Set format

Database Migrations

  • `drizzle/0067_gorgeous_mulholland_black.sql` - Adds `enable_billing_header_rectifier` setting

Testing

  • New unit tests for `billing-header-rectifier.ts`
  • Enhanced tests for rate limiting, session management, and statistics
  • All existing tests pass

Configuration

New system setting:

  • `enable_billing_header_rectifier` (boolean, default: `true`) - Controls whether to strip billing headers from responses

Related Issues


Release v0.5.7 - ding113

ding113 and others added 6 commits February 13, 2026 13:46
修复 PostgreSQL 查询中的日期计算 bug,当 maxAgeDays = 36500(100年)时,
使用 Date.setDate() 会导致日期回退到 1926-03-10,引发数据库错误。

**问题根因**:
- JavaScript Date.setDate() 在处理超大天数减法时会产生不合理的历史日期
- 查询参数 1926-03-10 导致 PostgreSQL 共享内存段调整失败

**修复方案**:
- 使用时间戳计算:`new Date(Date.now() - days * 24 * 60 * 60 * 1000)`
- 替代原有的 `setDate(getDate() - days)` 方式
- 适用于任意大的天数值(包括 36500 天 = 100 年)

**影响范围**:
- src/repository/statistics.ts:
  - sumKeyTotalCost() - Key 历史总消费查询
  - sumUserTotalCost() - 用户历史总消费查询

**测试覆盖**:
- 新增单元测试验证 36500 天和 100000 天的场景
- 验证日期计算结果在合理范围内(非 1926 年)
- 全量测试通过(262 文件,2245 测试)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: Key/User 并发 Session 原子化校验与追踪

* 并发 Session:补齐 global 清理并移除非原子降级

- Lua:增加 global:active_sessions 的过期清理,避免长时间流量下膨胀\n- RateLimitGuard:sessionId 缺失时兜底生成,并继续走原子 check+track,避免回退到非原子路径\n- Tests:补充 sessionId 缺失用例;稳定 endpoint-circuit-breaker 的动态 import mock

* RateLimitGuard:sessionId 缺失时记录告警

- 当 sessionId 在 rate-limit-guard 阶段缺失时记录 warn 日志,便于定位异常链路\n- 提示可能存在原子性缺口(SessionGuard 未按预期分配 sessionId)

* fix(rate-limit): 统一 active_sessions key 并修复空 sessionId 兜底

* fix(session): terminate 时清理 user active_sessions

* fix(rate-limit): 禁止 key ZSET 绕过 user 并发上限

* 修复并发会话限制:补齐清理与错误码

- resetUserAllStatistics 同步清理 user 级 active_sessions\n- checkAndTrackKeyUserSession 改为返回 reasonCode/reasonParams(便于 i18n)\n- 更新相关单元测试与脚本导入路径

* refactor(concurrent): 统一 Key/User 并发上限解析

* docs(concurrent): 补齐导出函数注释并去除测试硬编码 key

* docs(rate-limit): 补齐守卫与测试辅助函数注释

* docs(session): 补齐 SessionManager header 解析注释

* docs: 补齐限流服务与批量更新错误注释

* docs(users): 补齐批量接口类型注释

---------

Co-authored-by: tesgth032 <tesgth032@users.noreply.github.com>
…r from system prompt (#784)

Claude Code client v2.1.36+ injects x-anthropic-billing-header as a text
block inside the request body's system content array. Non-native Anthropic
upstreams (e.g. Amazon Bedrock) reject this with 400. This proactive
rectifier strips these blocks before forwarding, with a system settings
toggle (default: enabled).

- New rectifier module with regex-based detection
- Full backend wiring: schema, repository, cache, validation, action
- UI toggle in system settings form with i18n (5 locales)
- SpecialSetting audit trail for removed blocks
- 14 unit tests covering all edge cases
- Drizzle migration for new boolean column
The previous fix (67c2940) incorrectly diagnosed the issue as a
Date.setDate() overflow. In reality, 36500 days ago IS 1926 — both
setDate() and timestamp subtraction produce the same result. The actual
problem was that querying a 100-year date range caused PostgreSQL to
exhaust shared memory on resource-constrained instances.

Change ALL_TIME_MAX_AGE_DAYS from 36500 to Infinity, and make
sumKeyTotalCost/sumUserTotalCost conditionally omit the created_at
filter when maxAgeDays is non-finite, zero, or negative.
The previous fix removed the date filter but the page still crashed
PostgreSQL shared memory. Root cause: N+M concurrent SUM(cost_usd)
queries (one per user + one per key) via Promise.all.

Add sumUserTotalCostBatch and sumKeyTotalCostBatchByIds that use
GROUP BY to aggregate all users/keys in a single SQL query each.
Rewrite quotas/users page to use 2 batch queries instead of N+M
individual ones.
@coderabbitai
Copy link

coderabbitai bot commented Feb 14, 2026

📝 Walkthrough

工作流概述

本PR添加了账单标头整流器功能,移除Claude Code客户端注入的x-anthropic-billing-header文本块,以防止非原生Anthropic上游返回400错误。同时引入数据库迁移、系统设置配置、代理转发逻辑、会话跟踪改进和批量统计查询优化。

变更

队列 / 文件 摘要
数据库迁移与架构
drizzle/0067_gorgeous_mulholland_black.sql, drizzle/meta/0067_snapshot.json, drizzle/meta/_journal.json, src/drizzle/schema.ts
添加系统设置表中的enableBillingHeaderRectifier布尔列(默认为true),包含完整架构快照和迁移日志。
本地化设置配置
messages/*/settings/config.json
在英文、日文、俄文、简体中文、繁体中文配置中添加enableBillingHeaderRectifier和enableBillingHeaderRectifierDesc文案。
账单标头整流器实现
src/app/v1/_lib/proxy/billing-header-rectifier.ts, src/types/special-settings.ts, src/lib/utils/special-settings.ts
实现新的整流器实用程序,移除系统提示中的账单标头块;添加BillingHeaderRectifierSpecialSetting类型和相应的特殊设置键构建逻辑。
系统配置与类型
src/types/system-config.ts, src/lib/config/system-settings-cache.ts, src/lib/validation/schemas.ts, src/repository/system-config.ts
添加enableBillingHeaderRectifier字段至系统设置类型、验证模式、缓存默认值和存储库逻辑,支持端到端的配置流程。
服务端操作与表单
src/actions/system-config.ts, src/app/[locale]/settings/config/page.tsx, src/app/[locale]/settings/config/_components/system-settings-form.tsx
集成enableBillingHeaderRectifier至系统配置保存流程、设置初始化和UI表单组件,包括状态管理和表单提交。
代理转发集成
src/app/v1/_lib/proxy/forwarder.ts
在Anthropic提供商处添加账单标头整流器调用,加载系统设置、应用整流器、记录和持久化应用结果。
会话与速率限制改进
src/lib/redis/active-session-keys.ts, src/lib/redis/lua-scripts.ts, src/lib/rate-limit/service.ts, src/lib/rate-limit/concurrent-session-limit.ts, src/app/v1/_lib/proxy/rate-limit-guard.ts, src/app/v1/_lib/proxy/session-guard.ts
引入Redis活跃会话键生成器、原子的key/user会话检查Lua脚本、并发会话限制规范化函数和综合会话检查方法,改进会话跟踪和限制解析。
会话管理与跟踪
src/lib/session-manager.ts, src/lib/session-tracker.ts, scripts/clear-session-bindings.ts
用集中式活跃会话键生成器替换硬编码的Redis键,更新会话清理、追踪和终止路径以使用新的键生成器。
代理响应与代理池
src/app/v1/_lib/proxy/response-handler.ts, src/lib/proxy-agent/agent-pool.ts
重构流式响应缓冲为分割的头/尾模式,改进SSE检测;添加火焰射击的代理清理追踪和优雅关闭等待逻辑。
统计与批量操作
src/repository/statistics.ts, src/actions/users.ts, src/actions/my-usage.ts
添加批量用户/键总成本查询函数,支持无穷大的all-time时间范围;实现GetUsersBatchParams、GetUsersBatchResult等批量操作接口,优化配额页面查询。
配额页面优化
src/app/[locale]/dashboard/quotas/users/page.tsx
将逐个用户/键的总成本查询替换为并行批量端点调用,提高查询效率。
单元测试
tests/unit/**/*
添加账单标头整流器、速率限制守卫、会话管理终止、并发会话限制、统计总成本批量查询等全面的测试覆盖;更新现有测试以反映Infinity的all-time语义和新的会话检查接口。

评估代码审查工作量

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

可能相关的PR

  • PR #784: 实现完全相同的账单标头整流器功能——添加DB列、整流器实用程序、系统设置/类型/UI集成和相应测试。
  • PR #776: 实现相同的原子key/user并发会话检查——新增Redis Lua脚本、RateLimitService方法、限制解析函数、活跃会话键生成器和相关代理/会话管理更新。
  • PR #643: 修改会话跟踪和并发会话限制逻辑——涉及SessionTracker/session-guard和速率限制服务,使用相同的Redis活跃会话/跟踪函数和限制解析。
🚥 Pre-merge checks | ✅ 1 | ❌ 3
❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 65.63% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Merge Conflict Detection ⚠️ Warning ❌ Merge conflicts detected (43 files):

⚔️ CHANGELOG.md (content)
⚔️ drizzle/meta/_journal.json (content)
⚔️ messages/en/settings/config.json (content)
⚔️ messages/ja/settings/config.json (content)
⚔️ messages/ru/settings/config.json (content)
⚔️ messages/zh-CN/settings/config.json (content)
⚔️ messages/zh-TW/settings/config.json (content)
⚔️ scripts/clear-session-bindings.ts (content)
⚔️ src/actions/my-usage.ts (content)
⚔️ src/actions/system-config.ts (content)
⚔️ src/actions/users.ts (content)
⚔️ src/app/[locale]/dashboard/quotas/users/page.tsx (content)
⚔️ src/app/[locale]/settings/config/_components/system-settings-form.tsx (content)
⚔️ src/app/[locale]/settings/config/page.tsx (content)
⚔️ src/app/v1/_lib/proxy/forwarder.ts (content)
⚔️ src/app/v1/_lib/proxy/rate-limit-guard.ts (content)
⚔️ src/app/v1/_lib/proxy/response-handler.ts (content)
⚔️ src/app/v1/_lib/proxy/session-guard.ts (content)
⚔️ src/drizzle/schema.ts (content)
⚔️ src/lib/config/system-settings-cache.ts (content)
⚔️ src/lib/proxy-agent/agent-pool.ts (content)
⚔️ src/lib/rate-limit/concurrent-session-limit.ts (content)
⚔️ src/lib/rate-limit/service.ts (content)
⚔️ src/lib/redis/lua-scripts.ts (content)
⚔️ src/lib/session-manager.ts (content)
⚔️ src/lib/session-tracker.ts (content)
⚔️ src/lib/utils/special-settings.ts (content)
⚔️ src/lib/validation/schemas.ts (content)
⚔️ src/repository/_shared/transformers.ts (content)
⚔️ src/repository/statistics.ts (content)
⚔️ src/repository/system-config.ts (content)
⚔️ src/types/special-settings.ts (content)
⚔️ src/types/system-config.ts (content)
⚔️ tests/unit/actions/system-config-save.test.ts (content)
⚔️ tests/unit/actions/total-usage-semantics.test.ts (content)
⚔️ tests/unit/lib/config/system-settings-cache.test.ts (content)
⚔️ tests/unit/lib/endpoint-circuit-breaker.test.ts (content)
⚔️ tests/unit/lib/proxy-agent/agent-pool.test.ts (content)
⚔️ tests/unit/lib/rate-limit/concurrent-session-limit.test.ts (content)
⚔️ tests/unit/lib/rate-limit/service-extra.test.ts (content)
⚔️ tests/unit/lib/session-tracker-cleanup.test.ts (content)
⚔️ tests/unit/lib/session-ttl-validation.test.ts (content)
⚔️ tests/unit/proxy/rate-limit-guard.test.ts (content)

These conflicts must be resolved before merging into main.
Resolve conflicts locally and push changes to this branch.
Description check ❓ Inconclusive 虽然未提供拉取请求描述,但标题本身清晰指示这是一个版本发布,足以传达提交意图。 建议添加详细的变更描述,说明此版本发布包含的主要功能和改进内容。
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed 标题「release v0.5.7」与变更集直接相关,清晰地描述了这是版本发布提交。

✏️ 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
⚔️ Resolve merge conflicts (beta)
  • Auto-commit resolved conflicts to branch dev
  • Create stacked PR with resolved conflicts
  • Post resolved changes as copyable diffs in a comment

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.

@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 pull request introduces a new billing header rectification feature to improve compatibility with Anthropic upstreams, alongside significant performance enhancements for the user quota dashboard through batch database queries. It also strengthens concurrent session limit enforcement with atomic Redis operations and standardizes Redis key management for better Redis Cluster compatibility. Additionally, memory efficiency for handling large streaming responses has been improved, and all-time usage queries now provide more accurate historical data.

Highlights

  • New Feature: Billing Header Rectifier: Introduced a new system setting and proxy logic to proactively remove x-anthropic-billing-header text blocks injected by the Claude Code client from system prompts. This prevents 400 errors from non-native Anthropic upstreams like Amazon Bedrock.
  • Performance Optimization: Batch Usage Queries: Refactored the user quota dashboard to utilize batch database queries for calculating total user and key usage, significantly reducing the number of SQL queries and improving performance for pages displaying multiple users and keys.
  • Improved Concurrent Session Limit Enforcement: Enhanced the concurrent session limit logic by implementing an atomic Redis Lua script (CHECK_AND_TRACK_KEY_USER_SESSION). This prevents race conditions and ensures accurate tracking and enforcement of concurrent session limits for both individual keys and users.
  • Redis Cluster Compatibility for Active Sessions: Standardized the Redis keys for active sessions (global:active_sessions, key:*:active_sessions, user:*:active_sessions) to include a shared hash tag ({active_sessions}). This ensures compatibility with Redis Cluster when executing multi-key Lua scripts.
  • Memory-Efficient Response Buffering: Updated the proxy response handler to use a 'head + tail window' approach for buffering large streaming responses. This change allows for efficient collection of data for statistics and billing by preserving initial metadata and final usage information while discarding intermediate data, preventing potential Out-Of-Memory (OOM) errors.
  • Accurate All-Time Usage Queries: Modified the ALL_TIME_MAX_AGE_DAYS constant for total usage queries from a fixed large number (36500) to Infinity. This ensures that 'all-time' usage calculations truly query all historical data without an arbitrary date filter, providing more accurate long-term statistics.
Changelog
  • drizzle/0067_gorgeous_mulholland_black.sql
    • Added the enable_billing_header_rectifier column to the system_settings table.
  • drizzle/meta/0067_snapshot.json
    • Updated the Drizzle ORM snapshot to include the new enable_billing_header_rectifier column.
  • drizzle/meta/_journal.json
    • Updated the Drizzle ORM migration journal to reflect the new migration.
  • messages/en/settings/config.json
    • Added English localization strings for the new billing header rectifier setting.
  • messages/ja/settings/config.json
    • Added Japanese localization strings for the new billing header rectifier setting.
  • messages/ru/settings/config.json
    • Added Russian localization strings for the new billing header rectifier setting.
  • messages/zh-CN/settings/config.json
    • Added Simplified Chinese localization strings for the new billing header rectifier setting.
  • messages/zh-TW/settings/config.json
    • Added Traditional Chinese localization strings for the new billing header rectifier setting.
  • scripts/clear-session-bindings.ts
    • Updated Redis key generation for active sessions to use new helper functions.
  • src/actions/my-usage.ts
    • Changed ALL_TIME_MAX_AGE_DAYS to Infinity for all-time usage queries.
  • src/actions/system-config.ts
    • Added enableBillingHeaderRectifier to the system settings save action.
  • src/actions/users.ts
    • Added JSDoc comments to interfaces, changed ALL_TIME_MAX_AGE_DAYS to Infinity, and updated Redis key generation for active sessions.
  • src/app/[locale]/dashboard/quotas/users/page.tsx
    • Refactored user quota page to use batch database queries for total usage.
  • src/app/[locale]/settings/config/_components/system-settings-form.tsx
    • Added a UI component for the new billing header rectifier setting.
  • src/app/[locale]/settings/config/page.tsx
    • Integrated the new billing header rectifier setting into the system settings page.
  • src/app/v1/_lib/proxy/billing-header-rectifier.ts
    • Added a new file implementing the rectifyBillingHeader function.
  • src/app/v1/_lib/proxy/forwarder.ts
    • Integrated rectifyBillingHeader into the proxy forwarder for Claude requests.
  • src/app/v1/_lib/proxy/rate-limit-guard.ts
    • Updated concurrent session limit logic to use an atomic Redis Lua script and new helper functions.
  • src/app/v1/_lib/proxy/response-handler.ts
    • Modified response buffering logic for statistics to use a head+tail window and updated SSE detection.
  • src/app/v1/_lib/proxy/session-guard.ts
    • Modified session tracking logic to conditionally track sessions based on concurrent session limits.
  • src/drizzle/schema.ts
    • Added the enableBillingHeaderRectifier column definition to the Drizzle schema.
  • src/lib/config/system-settings-cache.ts
    • Added enableBillingHeaderRectifier to default system settings and cache.
  • src/lib/proxy-agent/agent-pool.ts
    • Improved agent pool shutdown logic to gracefully wait for pending cleanup tasks.
  • src/lib/rate-limit/concurrent-session-limit.ts
    • Added normalizeConcurrentSessionLimit and resolveKeyUserConcurrentSessionLimits functions.
  • src/lib/rate-limit/service.ts
    • Added checkAndTrackKeyUserSession method using a new Lua script for atomic concurrent session checks.
  • src/lib/redis/active-session-keys.ts
    • Added a new file with helper functions for generating active session Redis keys with hash tags.
  • src/lib/redis/lua-scripts.ts
    • Added the CHECK_AND_TRACK_KEY_USER_SESSION Lua script.
  • src/lib/session-manager.ts
    • Updated terminateSession to use new active session Redis key helper functions and retrieve userId.
  • src/lib/session-tracker.ts
    • Updated active session Redis keys to use new helper functions with hash tags.
  • src/lib/utils/special-settings.ts
    • Added billing_header_rectifier to special settings.
  • src/lib/validation/schemas.ts
    • Added enableBillingHeaderRectifier to the system settings validation schema.
  • src/repository/_shared/transformers.ts
    • Added enableBillingHeaderRectifier to the system settings transformer.
  • src/repository/statistics.ts
    • Modified sumKeyTotalCost and sumUserTotalCost to handle Infinity for maxAgeDays, and added sumUserTotalCostBatch and sumKeyTotalCostBatchByIds.
  • src/repository/system-config.ts
    • Added enableBillingHeaderRectifier to fallback settings and update logic.
  • src/types/special-settings.ts
    • Added BillingHeaderRectifierSpecialSetting type.
  • src/types/system-config.ts
    • Added enableBillingHeaderRectifier to SystemSettings and UpdateSystemSettingsInput types.
  • tests/unit/actions/system-config-save.test.ts
    • Updated tests for system settings save action to include the new rectifier.
  • tests/unit/actions/total-usage-semantics.test.ts
    • Updated tests to reflect ALL_TIME_MAX_AGE_DAYS as Infinity.
  • tests/unit/lib/config/system-settings-cache.test.ts
    • Updated tests for system settings cache to include the new rectifier.
  • tests/unit/lib/endpoint-circuit-breaker.test.ts
    • Added module cache priming for dynamic imports in tests.
  • tests/unit/lib/proxy-agent/agent-pool.test.ts
    • Added assertions for mock functions in agent pool tests.
  • tests/unit/lib/rate-limit/concurrent-session-limit.test.ts
    • Added new tests for concurrent session limit resolution and normalization.
  • tests/unit/lib/rate-limit/service-extra.test.ts
    • Added new tests for checkAndTrackKeyUserSession in the rate limit service.
  • tests/unit/lib/session-manager-terminate-session.test.ts
    • Added a new test file for SessionManager.terminateSession.
  • tests/unit/lib/session-tracker-cleanup.test.ts
    • Updated tests to use new active session Redis key helper functions.
  • tests/unit/lib/session-ttl-validation.test.ts
    • Updated tests to use new active session Redis key helper functions.
  • tests/unit/proxy/billing-header-rectifier.test.ts
    • Added a new test file for rectifyBillingHeader.
Activity
  • The pull request was created by ding113.
  • The pull request is titled "release v0.5.7", indicating a version release.
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.

@github-actions
Copy link
Contributor

🧪 测试结果

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

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

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 is an excellent release pull request that not only introduces the new "Billing Header Rectifier" feature but also includes significant improvements to performance, correctness, and robustness across the application. The implementation of atomic session tracking via a Lua script is a standout change, effectively resolving a critical race condition in concurrent session limiting. Furthermore, the performance optimization on the user quotas page, which replaces N+M queries with a few batch operations, is a major improvement. Other refactorings, such as centralizing Redis key generation with cluster support and making the agent pool shutdown more resilient, demonstrate great attention to detail and system stability. The code quality is high, and the changes are well-executed. Great work on this release.

@ding113 ding113 merged commit c44ffe1 into main Feb 14, 2026
19 of 20 checks passed
@github-project-automation github-project-automation bot moved this from Backlog to Done in Claude Code Hub Roadmap Feb 14, 2026
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: 1

Caution

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

⚠️ Outside diff range comments (1)
src/repository/system-config.ts (1)

402-435: ⚠️ Potential issue | 🔴 Critical

returning 子句中缺少 enableBillingHeaderRectifier 字段。

更新操作的 .returning() 中包含了 enableThinkingBudgetRectifier(第 422 行)后直接跳到了 enableCodexSessionIdCompletion(第 423 行),遗漏了 enableBillingHeaderRectifier。该字段已在回退设置(第 154 行)、select 查询(第 198 行)和更新处理(第 355-356 行)中定义,但在返回子句中缺失,导致更新后返回的对象中该字段为 undefined

🔧 建议修复
         enableThinkingBudgetRectifier: systemSettings.enableThinkingBudgetRectifier,
+        enableBillingHeaderRectifier: systemSettings.enableBillingHeaderRectifier,
         enableCodexSessionIdCompletion: systemSettings.enableCodexSessionIdCompletion,
🤖 Fix all issues with AI agents
In `@src/app/v1/_lib/proxy/response-handler.ts`:
- Around line 1156-1174: The current byte-wise split using value.subarray(0,
remainingHeadBytes) can cut a multibyte UTF‑8 character; change the split to a
safe UTF‑8 boundary: before slicing, scan backward from remainingHeadBytes up to
3 bytes to find a byte where (byte & 0xC0) != 0x80 (a UTF‑8 start byte) and use
that index as splitIndex; if none found, set splitIndex = remainingHeadBytes
(fallback). Replace uses of value.subarray(0, remainingHeadBytes) and
value.subarray(remainingHeadBytes) with value.subarray(0, splitIndex) and
value.subarray(splitIndex) and keep decoder.decode(..., { stream: true }) and
pushChunk calls the same (adjust counts passed to pushChunk to reflect
splitIndex instead of remainingHeadBytes). Ensure the helper logic is used in
the branch that references inTailMode, headBufferedBytes, MAX_STATS_HEAD_BYTES,
decoder, pushChunk, value, and chunkSize.
🧹 Nitpick comments (6)
src/lib/proxy-agent/agent-pool.ts (1)

385-398: 建议:将 destroy 优先于 close 的策略选择记录为更显眼的注释或常量。

当前的中文注释已解释了为何优先使用 destroyclose() 可能等待 in-flight 请求导致长期阻塞)。这是一个关键的设计决策。可以考虑在类级别或方法签名处用英文 JSDoc 简要说明这一策略,方便不同语言背景的开发者理解。

此外,如果未来需要支持"等待 in-flight 请求完成后再关闭"的场景(例如优雅关闭时),可能需要区分两种关闭模式。当前的实现对 eviction 场景是正确的。

src/app/v1/_lib/proxy/response-handler.ts (1)

1008-1038: pushToTail 在每次 pushChunk 调用时都会重新创建闭包。

pushToTail 定义在 pushChunk 内部,意味着每次调用 pushChunk(即每接收到一个流 chunk)都会创建一个新的函数对象。对于高吞吐的流式响应场景(可能上千个 chunk),可以将 pushToTail 提升到与 pushChunk 同一作用域以避免不必要的分配。

现代 V8 引擎对此有较好的优化,实际影响有限,可作为后续优化项。

将 pushToTail 提升到外层作用域
+          const pushToTail = (text: string, bytes: number) => {
+            tailChunks.push(text);
+            tailChunkBytes.push(bytes);
+            tailBufferedBytes += bytes;
+
+            while (tailBufferedBytes > MAX_STATS_TAIL_BYTES && tailHead < tailChunkBytes.length) {
+              tailBufferedBytes -= tailChunkBytes[tailHead] ?? 0;
+              tailChunks[tailHead] = "";
+              tailChunkBytes[tailHead] = 0;
+              tailHead += 1;
+              wasTruncated = true;
+            }
+
+            if (tailHead > 4096) {
+              tailChunks.splice(0, tailHead);
+              tailChunkBytes.splice(0, tailHead);
+              tailHead = 0;
+            }
+
+            const keptCount = tailChunks.length - tailHead;
+            if (keptCount > MAX_STATS_TAIL_CHUNKS) {
+              const joined = joinTailChunks();
+              tailChunks.length = 0;
+              tailChunkBytes.length = 0;
+              tailHead = 0;
+              tailChunks.push(joined);
+              tailChunkBytes.push(tailBufferedBytes);
+            }
+          };
+
           const pushChunk = (text: string, bytes: number) => {
             if (!text) return;
-            const pushToTail = () => {
-              tailChunks.push(text);
-              tailChunkBytes.push(bytes);
-              // ... rest of pushToTail
-            };
 
             if (!inTailMode) {
               if (headBufferedBytes + bytes <= MAX_STATS_HEAD_BYTES) {
                 headChunks.push(text);
                 headBufferedBytes += bytes;
                 return;
               }
               inTailMode = true;
             }
 
-            pushToTail();
+            pushToTail(text, bytes);
           };
src/repository/statistics.ts (1)

819-845: sumUserTotalCostBatch 批量查询实现合理。

先零初始化所有请求的 userId,再用查询结果覆盖,确保无记录的用户也会返回 0。需注意当 userIds 数组非常大时,inArray 生成的 SQL IN (...) 子句可能影响性能。如果未来有超大批量场景,可考虑分批查询。

src/lib/utils/special-settings.ts (1)

100-101: 去重键未包含 extractedValues 字段。

buildSettingKey 仅序列化了 [type, hit, removedCount],遗漏了 extractedValues。若同一请求中出现两条 removedCount 相同但 extractedValues 不同的审计记录,它们会被误判为重复而丢弃。

其他类似 case(如 thinking_signature_rectifier)均将主要字段纳入了 key 计算。建议补齐:

建议修改
     case "billing_header_rectifier":
-      return JSON.stringify([setting.type, setting.hit, setting.removedCount]);
+      return JSON.stringify([setting.type, setting.hit, setting.removedCount, setting.extractedValues]);
tests/unit/repository/statistics-total-cost.test.ts (1)

13-36: 条件断言可以更严格,但当前实现可接受。

注释提到 "should not contain a date filter",但 Line 35 实际只断言了 capturedConditions 不为 undefined,没有验证条件数量或是否缺少日期过滤器。考虑到 Drizzle ORM 内部条件对象结构较复杂,当前做法是务实的,但如果希望提高测试置信度,可以对 where 调用参数做更细粒度的快照比较。

src/lib/rate-limit/service.ts (1)

527-558: checkSessionLimit 方法进行弃用或移除,因为该方法已由原子化的 checkAndTrackKeyUserSession 完全取代。

搜索结果确认该方法在整个代码库中没有任何调用方。checkAndTrackKeyUserSession 相比之下提供了更安全的原子性操作,使用 Lua 脚本完成"检查 + 追踪",并能区分新会话与已存在会话的处理。建议尽快标记为 @deprecated 或直接移除,避免维护两套非原子化的会话检查路径。

Comment on lines +1156 to +1174

// 尽量填满 head:边界 chunk 可能跨过 head 上限,按 byte 切分以避免 head 少于 1MB
if (!inTailMode && headBufferedBytes < MAX_STATS_HEAD_BYTES) {
const remainingHeadBytes = MAX_STATS_HEAD_BYTES - headBufferedBytes;
if (remainingHeadBytes > 0 && chunkSize > remainingHeadBytes) {
const headPart = value.subarray(0, remainingHeadBytes);
const tailPart = value.subarray(remainingHeadBytes);

const headText = decoder.decode(headPart, { stream: true });
pushChunk(headText, remainingHeadBytes);

const tailText = decoder.decode(tailPart, { stream: true });
pushChunk(tailText, chunkSize - remainingHeadBytes);
} else {
pushChunk(decoder.decode(value, { stream: true }), chunkSize);
}
} else {
pushChunk(decoder.decode(value, { stream: true }), chunkSize);
}
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

在任意字节边界切分 Uint8Array 可能截断多字节 UTF-8 字符。

value.subarray(0, remainingHeadBytes) 按字节偏移量切分,如果恰好在一个多字节 UTF-8 字符中间(如中文、emoji 等)切开:

  • decoder.decode(headPart, { stream: true }) 会将不完整的尾部字节缓存到 decoder 内部状态
  • 随后 decoder.decode(tailPart, { stream: true }) 会将缓存字节与 tailPart 合并,导致该字符出现在 tail 而非 head

结果:不会丢失数据(TextDecoder 的 stream 模式保证了跨调用的正确拼接),但 headBufferedBytes 的实际文本内容可能比记录的字节数少几个字节。对统计/结算场景影响极小(head 缓冲区最多少几个字节),但值得了解这一行为。

🤖 Prompt for AI Agents
In `@src/app/v1/_lib/proxy/response-handler.ts` around lines 1156 - 1174, The
current byte-wise split using value.subarray(0, remainingHeadBytes) can cut a
multibyte UTF‑8 character; change the split to a safe UTF‑8 boundary: before
slicing, scan backward from remainingHeadBytes up to 3 bytes to find a byte
where (byte & 0xC0) != 0x80 (a UTF‑8 start byte) and use that index as
splitIndex; if none found, set splitIndex = remainingHeadBytes (fallback).
Replace uses of value.subarray(0, remainingHeadBytes) and
value.subarray(remainingHeadBytes) with value.subarray(0, splitIndex) and
value.subarray(splitIndex) and keep decoder.decode(..., { stream: true }) and
pushChunk calls the same (adjust counts passed to pushChunk to reflect
splitIndex instead of remainingHeadBytes). Ensure the helper logic is used in
the branch that references inTailMode, headBufferedBytes, MAX_STATS_HEAD_BYTES,
decoder, pushChunk, value, and chunkSize.

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

No significant issues identified in this PR. The code demonstrates solid engineering practices across all reviewed dimensions.

PR Size: XL

  • Lines changed: 4,858 (4,569 additions, 289 deletions)
  • Files changed: 49

Note: This is a large release PR (v0.5.7). While reviewing, I verified that the changes are cohesive and focused on the release theme (billing header rectifier, rate limiting improvements, statistics optimization, and agent pool stability).

Review Coverage

  • Logic and correctness - Clean. The concurrent session limit resolution logic correctly handles edge cases (NaN, Infinity, negative values). The Lua script for atomic session tracking properly guards against invalid TTL values.

  • Security (OWASP Top 10) - Clean. No injection vulnerabilities detected. Redis Lua scripts use proper key/argument separation. No hardcoded secrets or credentials in the diff.

  • Error handling - Clean. Proper fail-open patterns in rate limiting (return { allowed: true } on errors). Error logging is comprehensive with appropriate context. No silent failures detected.

  • Type safety - Clean. TypeScript types are properly defined and used. Generic constraints are appropriate. No any type abuse detected in the changed code.

  • Documentation accuracy - Clean. Comments match code behavior. The Lua script documentation accurately describes the return values and parameters. Function-level JSDoc is present and accurate.

  • Test coverage - Adequate. Unit tests cover the key concurrent session limit resolution logic with comprehensive edge cases (NaN, Infinity, negative values, decimal truncation).

  • Code clarity - Good. Functions are appropriately sized. Variable names are descriptive. The rate limit guard logic follows a clear priority order as documented.

Notable Observations

  1. Good defensive programming: The normalizePositiveLimit function correctly handles edge cases like NaN, Infinity, and negative values.

  2. Proper Redis Lua script practices: The CHECK_AND_TRACK_SESSION Lua script includes a guard against invalid TTL values (if ttl <= 0 then ttl = 300000 end), preventing potential issues.

  3. Clean agent pool cleanup: The change from close() to destroy() with fire-and-forget pattern properly handles the blocking issue mentioned in the PR description.

  4. Comprehensive i18n: All 5 supported languages have been updated with the new billing header rectifier setting strings.


Automated review by Claude AI

scope: "request",
hit: true,
removedCount: billingResult.removedCount,
extractedValues: billingResult.extractedValues,
Copy link
Contributor

Choose a reason for hiding this comment

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

[HIGH] [SECURITY-VULNERABILITY] Persisting extractedValues stores unbounded, user-controlled prompt content

Why this is a problem: billingResult.extractedValues comes from message.system (request body) and can be arbitrarily long. Persisting it into specialSettings writes raw user-controlled text to Redis/DB via persistSpecialSettings(), bypassing the default prompt redaction behavior (STORE_SESSION_MESSAGES false redacts system). This creates an avoidable data-retention/privacy risk and a potential DoS vector via oversized specialSettings payloads.

Suggested fix:

// src/app/v1/_lib/proxy/forwarder.ts
session.addSpecialSetting({
  type: "billing_header_rectifier",
  scope: "request",
  hit: true,
  removedCount: billingResult.removedCount,
  // Do not persist user-controlled header text.
});

// src/types/special-settings.ts
export type BillingHeaderRectifierSpecialSetting = {
  type: "billing_header_rectifier";
  scope: "request";
  hit: boolean;
  removedCount: number;
};

if (typeof system === "string") {
if (BILLING_HEADER_PATTERN.test(system)) {
const extractedValues = [system.trim()];
delete message.system;
Copy link
Contributor

Choose a reason for hiding this comment

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

[MEDIUM] [LOGIC-BUG] String system handling deletes the entire system prompt

Why this is a problem: In the string system case, BILLING_HEADER_PATTERN.test(system) matches when the prompt starts with x-anthropic-billing-header:. If the string prompt is multi-line (header line + real system instructions), the current code does delete message.system; and drops the remaining instructions.

Suggested fix (remove only leading billing-header lines; keep the rest):

if (typeof system === "string") {
  const lines = system.split(/\r?\n/);
  const extractedValues: string[] = [];
  const remaining: string[] = [];

  for (const line of lines) {
    if (remaining.length === 0 && BILLING_HEADER_PATTERN.test(line)) {
      extractedValues.push(line.trim());
      continue;
    }
    remaining.push(line);
  }

  if (extractedValues.length === 0) {
    return { applied: false, removedCount: 0, extractedValues: [] };
  }

  const nextSystem = remaining.join("\n").trim();
  if (nextSystem) {
    message.system = nextSystem;
  } else {
    delete message.system;
  }

  return { applied: true, removedCount: extractedValues.length, extractedValues };
}

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 PR is XL and spans proxy request/response handling, rate limiting/session tracking, database schema, and UI settings, which increases rollback and review risk. The main problems are (1) persisting unbounded user-controlled billing-header text into audit storage, and (2) a request-mutation edge case that can drop legitimate system prompts in the new billing-header rectifier.

PR Size: XL

  • Lines changed: 4858
  • Files changed: 49
  • Split suggestions:
    • Billing Header Rectifier (new rectifier + system setting + i18n + tests)
    • Concurrent session limit work (Redis key hashing + Lua scripts + RateLimit/Session guards + tests)
    • Quota dashboard batching (repository batch SUM queries + page changes)
    • Misc scripts/cleanup fixes

Issues Found

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

Critical Issues (Must Fix)

None.

High Priority Issues (Should Fix)

  • src/app/v1/_lib/proxy/forwarder.ts:1783 [HIGH] [SECURITY-VULNERABILITY] Persisting extractedValues stores unbounded, user-controlled prompt content (bypasses redaction). (Confidence: 90/100)
  • src/app/v1/_lib/proxy/billing-header-rectifier.ts:39 [MEDIUM] [LOGIC-BUG] String system handling deletes the entire system prompt when the billing header is prefixed. (Confidence: 85/100)

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.

Applied PR size label size/XL, then reviewed PR #785 and submitted:

  • 2 inline review comments on diff lines:
    • src/app/v1/_lib/proxy/forwarder.ts:1783 — persisting extractedValues stores unbounded user-controlled content (security/DoS + redaction bypass).
    • src/app/v1/_lib/proxy/billing-header-rectifier.ts:39 — string system path deletes the entire system prompt (logic bug).
  • A summary review comment (with XL split suggestions and issue table) via gh pr review --comment.

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

Labels

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants