Conversation
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
Feature/supplier-ip-passthrough
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
fix: update DialogContent styling in KeyListHeader component #293
fix: key provider group #281
…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
Summary of ChangesHello @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
Using Gemini Code AssistThe 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
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 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
|
| /** | ||
| * 带重试的异步操作执行器 | ||
| * @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)); | ||
| } | ||
| } | ||
| } | ||
|
|
| {(() => { | ||
| 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; | ||
| })()} |
There was a problem hiding this comment.
建议将计算 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;There was a problem hiding this comment.
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:
- Database schema changes + migrations
- Core feature implementations (preserveClientIp, cacheTtlApplied)
- UI/localization changes
- 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
-
preserveClientIp Feature: The implementation correctly:
- Adds the field to schema, types, repository, and UI
- Uses
preserveClientIpHeadersflag inHeaderProcessorto conditionally filter IP-related headers - Adds overrides for
x-forwarded-forandx-real-ipwhen enabled - Properly defaults to
falsefor privacy protection
-
Fallback Sequence Improvement (
src/lib/session-manager.ts:99-106): The change from returning1to 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. -
New Error Rules: Added validation error patterns for tool_use ID uniqueness and tool_result matching - these are correctly marked as non-retryable.
-
cacheTtlApplied Tracking: Properly propagated through session cache types, repository queries, and aggregation functions.
-
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
- 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 …
Summary
Release PR merging
devintomainwith 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
preserve_client_iptoggle allowing selective forwarding of client IP headers to upstream providersdeploy/docker-compose.tools.yamlfor running maintenance scripts in Docker environmentsBug Fixes
TypeError: immutablewhen applying CORS headers in Next.js App RouterIF NOT EXISTSto migration index creationtool_use_iderror ruleSupporting Changes
0033_preserve_client_ip.sqladdingpreserve_client_ipboolean column to providers tableRelated Issues
Related PRs (Merged into dev)
Database Migration
Migration Notes:
false(privacy-preserving behavior maintained)AUTO_MIGRATE=trueBreaking Changes
None. All changes maintain backward compatibility.
Checklist
Description enhanced by Claude AI