Skip to content

release#297

Merged
ding113 merged 36 commits intomainfrom
dev
Dec 10, 2025
Merged

release#297
ding113 merged 36 commits intomainfrom
dev

Conversation

@ding113
Copy link
Owner

@ding113 ding113 commented Dec 8, 2025

Summary

Release PR merging dev into main with multiple feature enhancements, bug fixes, and infrastructure improvements including provider IP passthrough, session binding management tools, CORS handling fixes, and billing details in dashboard.

Changes Overview

This release includes contributions from multiple PRs:

Features

  • Provider IP Passthrough (from Feature/supplier-ip-passthrough #294): New preserve_client_ip toggle allowing selective forwarding of client IP headers to upstream providers
  • Session Binding Cleanup Tool (from feat: 添加会话绑定清理工具 #268): CLI utility for clearing Redis session bindings with filtering options (priority, provider ID, name pattern)
  • Billing Details in Dashboard: Enhanced session message handling with cost visibility
  • Docker Tools Container: New deploy/docker-compose.tools.yaml for running maintenance scripts in Docker environments

Bug Fixes

Supporting Changes

  • Updated LiteLLM prices seed data
  • Added i18n translations for new features (zh-CN, zh-TW, en, ja, ru)
  • Database migration: 0033_preserve_client_ip.sql adding preserve_client_ip boolean column to providers table

Related Issues

Related PRs (Merged into dev)

Database Migration

ALTER TABLE "providers" ADD COLUMN "preserve_client_ip" boolean NOT NULL DEFAULT false;

Migration Notes:

  • Non-breaking: existing providers default to false (privacy-preserving behavior maintained)
  • Auto-migration will run on startup if AUTO_MIGRATE=true

Breaking Changes

None. All changes maintain backward compatibility.

Checklist

  • All merged PRs have passed CI
  • Database migrations included
  • i18n translations complete for all 5 locales
  • Code follows project conventions

Description enhanced by Claude AI

github-actions bot and others added 26 commits December 7, 2025 16:32
Fixed:
- Added IF NOT EXISTS to CREATE INDEX in 0032_add_request_sequence.sql

CI Run: https://github.com/ding113/claude-code-hub/actions/runs/20007050140

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
新增供应商会话绑定清理 CLI 工具:
- `scripts/clear-session-bindings.ts`: 交互式或命令行清理工具
  - 支持按优先级、供应商 ID、名称模式或类型筛选
  - 支持 dry-run 模式预览操作
  - 使用 Redis pipeline 批量处理优化性能
- `deploy/docker-compose.tools.yaml`: 用于在容器化环境中运行维护脚本

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add ProviderType type definition with validation
- Reorder imports alphabetically
- Apply code formatting improvements
- usage-logs-table.tsx: (log.cost ?? 0).toFixed(4)
- today-usage-card.tsx: Number(item.costUsd ?? 0).toFixed(4)

Fixes 'e.toFixed is not a function' error when cost is null/undefined
- Introduced a new column "preserve_client_ip" in the providers table to control the forwarding of client IP addresses.
- Updated relevant JSON files for localization support in settings.
- Enhanced provider forms and actions to include the new preserveClientIp property.
- Modified header processing to conditionally retain client IP headers based on the new setting.
- Updated validation schemas to accommodate the new property for provider creation and updates.
- Added 'preserve_client_ip' property to the ProviderForm component to support client IP address forwarding configuration.
- Added max height and overflow properties to DialogContent for better UI handling.
- Updated getAvailableProviderGroups to accept an optional userId parameter for filtering provider groups based on user configuration.
- Modified AddKeyForm and EditKeyForm components to load provider group suggestions conditionally based on the user's ID.
- Implemented cascading updates for user provider groups in editUser function to ensure key provider groups are updated when user groups change.
fix: add IF NOT EXISTS to migration index for idempotency
feat: 添加会话绑定清理工具
fix: resolve TypeError immutable when applying CORS headers
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
fix: update DialogContent styling in KeyListHeader component #293
…ndling

- Introduced billing details section in multiple language files (English, Japanese, Russian, Simplified Chinese, Traditional Chinese) with relevant fields.
- Enhanced `hasSessionMessages` function to accept an optional request sequence parameter for more precise message checks.
- Updated `ErrorDetailsDialog` and `UsageLogsTable` components to display billing details, including input/output tokens and cache information.
- Implemented a retry mechanism for storing session information and messages in the session manager.
- Improved session statistics aggregation to include cache TTL information.
- Add error rule for tool_use_id/tool_result validation errors (priority 88)
- Fix provider group not saved to database (String(null) issue)
- Replace TagInputField with ProviderGroupSelect dropdown component
- Add server-side validation for providerGroup in addKey/editKey
- Prevent key from setting providerGroup when user has none (security fix)
- Add accessibility improvements: aria-invalid, aria-describedby, role=alert
- Add i18n translations for providerGroupSelect in all 5 locales
@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 delivers a suite of improvements across provider configuration, session management, and user interface observability. It introduces a new capability for providers to selectively forward client IP addresses, alongside a dedicated CLI tool for efficient Redis session cleanup. The changes also enhance the display of billing details in the UI, refine CORS header management, and strengthen key security through robust provider group validation and cascading updates. Overall, these updates aim to provide greater control, transparency, and operational stability.

Highlights

  • New Docker Compose Tool Service: A docker-compose.tools.yaml file has been added, defining a tools service based on oven/bun:1.3.2-slim. This service is specifically designed for running maintenance scripts, such as the new session cleanup script, within the Docker environment, allowing it to share the main network and access PostgreSQL and Redis.
  • Client IP Forwarding for Providers: A new boolean column preserve_client_ip has been added to the providers database table, defaulting to false. This allows individual providers to be configured to forward client IP headers (x-forwarded-for, x-real-ip, etc.) to upstream services, offering more control over privacy and integration needs. The proxy's header processing logic has been updated to respect this setting.
  • Session Binding Cleanup Script: A new Bun script, scripts/clear-session-bindings.ts, has been introduced. This powerful command-line tool enables administrators to clean up Redis session bindings for specific providers, with options to filter by priority, ID, name, or type. It supports both interactive and automated modes, including a dry-run feature for previewing changes.
  • Enhanced Session Message Checking: The hasSessionMessages function has been improved to support checking for messages related to a specific request sequence within a session, or to determine if any messages exist for a given session, accommodating both new and older message storage formats.
  • Key Provider Group Validation and Cascade Updates: Key management now includes validation to ensure that a key's providerGroup is a valid subset of the user's allowed provider groups. Additionally, if a user's providerGroup is updated and certain groups are removed, the system will automatically cascade these changes to all associated keys, removing any no-longer-permitted groups from their configurations.
  • Detailed Billing Information in UI: The dashboard logs and session messages user interfaces now display more comprehensive billing details. This includes breakdowns of input/output tokens, cache write/read tokens, the applied cache TTL, and cost multipliers, providing a clearer view of how costs are calculated for each request.
  • Improved CORS Header Handling: The applyCors function has been refactored to consistently return a new Response object with correctly merged headers. This change addresses potential issues with immutable headers in environments like Next.js App Router and enhances the logic for merging Vary headers to prevent duplicates.
  • Redis Operation Resilience with Retries: Asynchronous Redis operations for storing session information and messages now incorporate a retry mechanism (executeWithRetry). This significantly improves the system's resilience against transient Redis connection issues, ensuring more robust session data persistence.
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 github-actions bot added the enhancement New feature or request label Dec 8, 2025
@github-actions github-actions bot added the size/XL Extra Large PR (> 1000 lines) label Dec 8, 2025
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

这次的 PR 引入了几个重要功能和改进,包括保留客户端 IP 的能力、一个用于清除会话绑定的新工具,以及对供应商分组的增强验证。代码质量总体很高,在健壮性方面有显著提升,例如为 Redis 操作增加了重试逻辑,并使 CORS 处理更具弹性。新的维护脚本对于运维来说是一个很有价值的补充。我的审查主要集中在改进一些新的、复杂组件的代码结构和可维护性上。总的来说,这是一次很棒的发布。

Comment on lines +6 to +31
/**
* 带重试的异步操作执行器
* @param fn - 要执行的异步函数
* @param maxRetries - 最大重试次数(默认 2 次)
* @param delayMs - 重试间隔基数(毫秒,默认 100ms)
*/
async function executeWithRetry(
fn: () => Promise<void>,
maxRetries = 2,
delayMs = 100
): Promise<void> {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
await fn();
return;
} catch (error) {
if (attempt === maxRetries) {
throw error;
}
// 指数退避:100ms, 200ms, 400ms...
const delay = delayMs * 2 ** attempt;
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
}

Copy link
Contributor

Choose a reason for hiding this comment

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

medium

executeWithRetry 函数是一个非常通用的重试工具。建议将其提取到一个共享的工具函数文件中,例如 src/lib/utils/retry.ts

这样做可以提高代码的可复用性,未来在其他需要处理临时网络错误的地方也可以直接调用,避免重复实现。

Comment on lines +301 to +321
{(() => {
const successfulProvider =
log.providerChain && log.providerChain.length > 0
? [...log.providerChain]
.reverse()
.find(
(item) =>
item.reason === "request_success" ||
item.reason === "retry_success"
)
: null;
const actualCostMultiplier =
successfulProvider?.costMultiplier ?? log.costMultiplier;
return actualCostMultiplier &&
parseFloat(String(actualCostMultiplier)) !== 1.0 ? (
<div>
{t("logs.billingDetails.multiplier")}:{" "}
{parseFloat(String(actualCostMultiplier)).toFixed(2)}x
</div>
) : null;
})()}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

建议将计算 actualCostMultiplier 的逻辑移到后端。

目前,在组件内部通过遍历 providerChain 来确定最终成功的供应商并获取其成本倍率,这部分属于业务逻辑。
为了更好的代码分离和可维护性,推荐将这部分逻辑移到获取日志数据的后端 Action 中。这样,组件可以直接从 log 对象中获取最终的 actualCostMultiplier,使组件更专注于展示,也让该逻辑更易于复用和测试。

例如,在后端处理数据时:

// 在后端的 Action 或数据获取层
const logs = await fetchLogs();
const processedLogs = logs.map(log => {
  const successfulProvider =
    log.providerChain?.findLast(
      (item) => item.reason === "request_success" || item.reason === "retry_success"
    );
  const actualCostMultiplier = successfulProvider?.costMultiplier ?? log.costMultiplier;
  return { ...log, actualCostMultiplier };
});
return processedLogs;

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 large PR (XL: 3424+ lines, 70 files) that introduces several new features including the preserveClientIp provider setting, cacheTtlApplied tracking, tool_use validation error rules, and an improved fallback sequence mechanism. The changes are generally well-implemented with proper error handling and logging.

PR Size: XL

  • Lines changed: 3424+
  • Files changed: 70

Split Suggestion (L/XL PR): Consider splitting future large releases into:

  1. Database schema changes + migrations
  2. Core feature implementations (preserveClientIp, cacheTtlApplied)
  3. UI/localization changes
  4. Utility scripts (clear-session-bindings.ts)

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 0 0
Tests 0 0 0 0
Simplification 0 0 0 0

Review Notes

  1. preserveClientIp Feature: The implementation correctly:

    • Adds the field to schema, types, repository, and UI
    • Uses preserveClientIpHeaders flag in HeaderProcessor to conditionally filter IP-related headers
    • Adds overrides for x-forwarded-for and x-real-ip when enabled
    • Properly defaults to false for privacy protection
  2. Fallback Sequence Improvement (src/lib/session-manager.ts:99-106): The change from returning 1 to using timestamp + random provides better uniqueness when Redis is unavailable. The formula (Date.now() % 1000000) + Math.floor(Math.random() * 1000) generates values up to ~1,001,000, which is reasonable for temporary sequences.

  3. New Error Rules: Added validation error patterns for tool_use ID uniqueness and tool_result matching - these are correctly marked as non-retryable.

  4. cacheTtlApplied Tracking: Properly propagated through session cache types, repository queries, and aggregation functions.

  5. clear-session-bindings.ts Script: Well-structured utility with proper Redis and PostgreSQL client handling, interactive prompts, and dry-run support.

Review Coverage

  • Logic and correctness - Clean
  • Security (OWASP Top 10) - Clean
  • Error handling - Clean (all error paths log appropriately)
  • Type safety - Clean
  • Documentation accuracy - Clean
  • Test coverage - No new tests added (consider adding tests for new features in future PRs)
  • Code clarity - Good

Automated review by Claude AI

ding113 and others added 10 commits December 9, 2025 01:44
- Add handling for data.message.usage in SSE parsing (Claude format)
- Prioritize message.usage over direct data.usage for correct extraction
- Fixes cache creation 5m/1h tokens not displaying in UI tooltips
- 在用户创建过程中增加了`isEnabled`和`expiresAt`字段。
- 更新了响应模式,包含详细的用户信息和默认密钥,以响应用户创建。
- 在API文档中引入了各种用户创建场景的请求示例。
- 优化了`expiresAt`的验证,确保其为未来日期且在10年限制内。
- 更新了`addUser`和`editUser`函数,包括更详细的响应结构,增加了额外的用户字段。
- 引入了一个新的`UserFormSchema`用于前端验证,允许`expiresAt`为字符串日期。
- 加强了验证逻辑,确保`expiresAt`是未来日期,并且不超过10年限制。
- 重构验证方案中的日期处理,以改进错误报告并保持一致性。
…n-bug

Fix/expiry-time-format-conversion-bug
改进错误规则同步逻辑,避免重复插入导致的冲突:
- 使用 upsert 策略替代删除重建
- 保留用户自定义规则不被覆盖
- 清理过期的默认规则
…rendering bug

- Add missing cacheCreation5mInputTokens, cacheCreation1hInputTokens, cacheTtlApplied
  fields to updateMessageRequestDetails calls in handleNonStream and finalizeStream
- Fix React short-circuit rendering bug where '0 && expr' renders literal '0'
  in error-details-dialog.tsx and usage-logs-table.tsx billing tooltips
- Change conditional renders from 'x && x > 0 &&' to '(x ?? 0) > 0 &&'
fix: 修复点击同步规则时的错误
fix: save cache creation 5m/1h tokens and TTL to database, fix React …
@ding113 ding113 merged commit 92a5eff into main Dec 10, 2025
1 check passed
@github-project-automation github-project-automation bot moved this from Backlog to Done in Claude Code Hub Roadmap Dec 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[Bug] 新增 KEY Dialog 铺满屏幕(默认 Key 正常) feat:增加在新建令牌时选择供应商分组的功能

4 participants

Comments