Skip to content

release v0.4.1#587

Merged
github-actions[bot] merged 18 commits intomainfrom
dev
Jan 10, 2026
Merged

release v0.4.1#587
github-actions[bot] merged 18 commits intomainfrom
dev

Conversation

@ding113
Copy link
Owner

@ding113 ding113 commented Jan 10, 2026

Summary

Release v0.4.0 introduces several major features: thinking signature rectifier, FluxFix response fixer, OpenCode support, manual model pricing, and automatic provider priority sorting. This release also includes numerous bug fixes and performance optimizations.

Related Issues

BREAKING CHANGE

Custom models previously added via JSON configuration will no longer work. Users must re-add custom models using the new manual price management UI.

New Features

Thinking Signature Rectifier (#576)

  • Automatically fixes "Invalid signature in thinking block" errors during cross-channel switching
  • Minimal request rectification (removes thinking/redacted_thinking and signature fields) with same-provider retry
  • System setting toggle enableThinkingSignatureRectifier (default: enabled)
  • Audit trail via specialSettings for request logging

FluxFix Response Fixer (#570)

  • Three-stage fix pipeline: Encoding -> SSE -> JSON
  • Automatically repairs malformed upstream responses:
    • UTF-8 BOM markers and null bytes
    • Malformed SSE streams (missing data: prefix, line endings)
    • Truncated/malformed JSON (unclosed brackets, trailing commas)
  • Configurable per-fixer toggles in system settings
  • Full audit trail via ResponseFixerSpecialSetting

Manual Model Pricing (#573)

  • New source field distinguishes litellm vs manual prices
  • Full CRUD for manual model prices (all modes: chat, image_generation, embedding, etc.)
  • LiteLLM sync automatically skips manual prices to prevent overwriting
  • Conflict detection UI with batch resolution support

Auto-Sort Provider Priority (#569)

  • Automatically assigns priorities based on cost multiplier (lower cost = higher priority)
  • Preview/confirm workflow before applying changes
  • Groups providers with same cost into same priority tier

OpenCode Support (#582, #586)

  • Comprehensive setup guide for OpenCode CLI integration
  • Installation instructions for macOS, Linux, Windows
  • Configuration examples covering Claude, GPT-5.2, and Gemini 3 models

Statistics Summary (#559)

  • New getMyStatsSummary API with model breakdown aggregation
  • Statistics Summary card with auto-refresh (30s) and visibility API integration
  • Collapsible quota and logs sections with header metrics
  • Infinity icon for unlimited quotas

Bug Fixes

Infrastructure Improvements

TOML Cloud Price Table (#580)

  • Migrated from LiteLLM JSON to official TOML format
  • New source: https://claude-code-hub.app/config/prices-base.toml
  • Fail-open billing: requests proceed when price missing, triggers async sync
  • Scheduled 30-minute cron job for automatic price updates
  • Fixed N+1 query problem in price sync (O(n) -> O(1))

Database Changes

  • Migration 0049: Fix idempotency
  • Migration 0050: Add enable_response_fixer and response_fixer_config columns
  • Migration 0051: Add enable_thinking_signature_rectifier column
  • Migration 0052: Add source column to model_prices table

UI/UX Improvements

  • Price table: display_name priority, capability icons, quick filters
  • Usage logs: improved provider chain popover layout
  • Error details: hide invalid cost multiplier badges
  • Session messages: accessibility improvements (aria-labels)

Changes Summary

Core Changes (91 files)

  • Response fixer pipeline with 87 new test cases
  • Thinking signature rectifier with comprehensive coverage
  • Manual price management with 20 unit tests
  • Auto-sort priority with preview workflow

i18n

  • All 5 languages updated (zh-CN, zh-TW, en, ja, ru)
  • New translations for response fixer, rectifier, pricing, and statistics

Tests

  • 600+ passing tests
  • New integration test configuration separating DB-dependent tests

Pre-commit Verification

bun run build      # Production build
bun run lint       # Biome check
bun run typecheck  # TypeScript check
bun run test       # Vitest tests

Checklist

  • Code follows project conventions (no emojis, proper i18n)
  • Self-review completed
  • Tests pass locally
  • i18n translations provided for all 5 languages
  • Database migrations are backward-compatible

Description enhanced by Claude AI

NieiR and others added 17 commits January 9, 2026 00:43
#559)

* feat(my-usage): add Statistics Summary with auto-refresh, improve UX

- Add StatisticsSummaryCard with date range picker and 30s auto-refresh
- Add getMyStatsSummary API for fetching stats by time range
- Show expiration date in parentheses for Expired status
- Remove Today's Statistics (functionality merged into Statistics Summary)
- Remove subtitle from header
- Add translations for stats section (en/ru/ja/zh-CN/zh-TW)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* test(my-usage): add unit tests for getMyStatsSummary

- Register getMyStatsSummary endpoint in Actions API with OpenAPI schema
- Add 3 tests: unauthorized 401, basic aggregation with warmup exclusion,
  date range filtering
- Tests verify key/user breakdown separation and data isolation

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(ui): logs table and heading style improvements

- Use currency symbol instead of code in logs table
- Improve Russian translations
- Unify heading style in provider-group-info

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(my-usage): collapsible usage logs with header summary

Make Usage Logs section collapsible like Quota card with informative
header showing:
- Last request status with relative time (color-coded)
- Success rate percentage with ✓/✗ indicator
- Active filters count badge
- Auto-refresh indicator

Header adapts for mobile with compact layout. Collapsed by default.

- Replace Card with Radix Collapsible component
- Add metrics calculation (lastLog, successRate, activeFiltersCount)
- Add responsive header (desktop/mobile variants)
- Add logsCollapsible translations for all 5 locales

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(ui): correct RefreshCw animation in usage-logs-section

Animation should trigger on isRefreshing state, not on autoRefreshSeconds config value.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(ui): address CodeRabbit review feedback

- Add optional chaining for CURRENCY_CONFIG to prevent runtime errors
- Use ∞ symbol for unlimited RPM instead of "neverExpires" text
- Add index to React keys in model breakdown to prevent duplicates

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* chore: format code (fix-my-usage-43169ad)

---------

Co-authored-by: John Doe <johndoe@example.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Add new error rule to handle Claude API's media count limit error when
total media (document pages + images) exceeds 100.

- Pattern: "Too much media" (contains match)
- Category: media_limit
- Priority: 79 (after PDF limit rules)
- Override message explains the limit and suggests reducing media count

Closes #571
* feat: port FluxFix response fixer

* fix: polish response fixer and usage date parsing
* feat: unify special settings display

* fix: address review feedback for special settings

* fix(ui): move special settings display into details dialog
* feat(providers): add auto-sort priority by costMultiplier (#555)

* 变更概要:
  - 5 个语言的 dashboard.json 添加顶层 actions 翻译键
  - 2 个测试文件 import 真实 locale 文件替代硬编码 mock
  - 测试断言收敛到具体 tab 容器作用域
  - CLAUDE.md 语言列表校正 (ko/de → ru/zh-TW)

  fix(i18n): add top-level dashboard.actions keys and improve test i18n strategy

  - Add `actions` (copy/download/copied) to dashboard.json for all 5 locales
    to fix CodeDisplay component missing translation keys
  - Refactor test files to import real locale messages instead of hardcoded
    mocks, ensuring tests stay in sync with actual translations
  - Scope test assertions to specific tab containers for better precision
  - Fix CLAUDE.md language list to match actual locales (ru/zh-TW, not ko/de)

* 变更概要:
  - tsconfig.json 添加 @messages/* 路径别名
  - tsconfig.json 移除 src/components/ui/** exclude
  - vitest.config.ts 添加 @messages 别名
  - 测试文件使用新别名,修复类型断言

  chore(config): add @messages path alias and fix TypeScript exclude

  - Add `@messages/*` path alias to tsconfig.json and vitest.config.ts
    for cleaner locale imports in tests
  - Remove `src/components/ui/**` from tsconfig exclude to enable
    TypeScript checking and IDE support for UI component tests
  - Update test imports to use @messages/en/dashboard.json
  - Fix non-null assertion in code-display.test.tsx to resolve TS error

* fix(ui): 为纯图标导出按钮补充 aria-label,修复相关单测

- 为请求复制/下载两个纯图标按钮添加 aria-label,避免依赖 Tooltip 文本,同时提升可访问性
- 单测改为按 aria-label 定位按钮,并补齐 SessionMessagesDetailsTabs 的 mock(提供复制响应按钮)

* fix(ui): 修复 session-messages-client 组件缩进混乱问题

  - 将 Tab+空格混合缩进统一为纯空格,符合项目 Biome 规范
  - 测试文件长行拆分以保持代码风格一致

* fix(providers): 统一 React Query QueryClient,改用 invalidate 刷新供应商列表

- 移除 ProviderManagerLoader 内部 QueryClientProvider,避免页面存在两个 QueryClient 导致 invalidate 不生效
- 将 staleTime/refetchOnWindowFocus 下沉到各个 useQuery,保持原有缓存/刷新行为一致
- AutoSortPriorityDialog 应用后改为 invalidateQueries(["providers"]),不再使用 window.location.reload()

* ⏺ fix(test): 将需要数据库的 API 测试移入集成测试配置

  - vitest.config.ts: 排除 my-usage-readonly.test.ts(需要 DSN)
  - vitest.integration.config.ts: 统一管理所有需要 DB 的 API 测试
    - users-actions.test.ts
    - providers-actions.test.ts
    - keys-actions.test.ts
    - my-usage-readonly.test.ts

  确保 `bun run test` 在无数据库环境下正常通过,
  需要 DB 的测试通过 `bun run test:integration` 单独运行。

* fix(ui): 修复 AlertDialogDescription 内嵌套 div 导致的 hydration 错误

  AlertDialogDescription 默认渲染为 <p> 标签,内部嵌套 <div> 违反 HTML 规范,
  导致 React hydration mismatch 警告。使用 asChild 属性让其渲染为 <div> 解决。

* fix(ui): remove duplicate aria-label
* feat: add thinking signature rectifier

* fix: skip rectifier retry when no-op
* fix: enable provider group editing in edit user dialog

- Always show providerGroup field in edit mode (was hidden when user had no providerGroup)
- Replace read-only Badge display with editable ProviderGroupSelect component
- Move modelSuggestions hook after form declaration to support dynamic updates

Regression from #539

* fix: add complete translations for ProviderGroupSelect in edit user dialog

Pass full translations object to ProviderGroupSelect including:
- tagInputErrors for validation messages (empty, duplicate, too_long, etc.)
- errors.loadFailed for API error handling
- providersSuffix for provider count display

This fixes untranslated error messages when users input invalid provider group tags.

* feat(prices): 添加手动模型价格管理功能

- 新增 source 字段区分 litellm/manual 来源
- 支持手动添加、编辑、删除模型价格
- LiteLLM 同步时自动跳过手动价格,避免覆盖
- 添加冲突检测和解决 UI,支持批量处理
- 完整的单元测试覆盖

closes #405

* fix: 修复 CI 检查问题

- 移除未使用的 ModelPriceSource 导入
- 修复 useEffect 依赖数组 (fetchPrices)
- 修复 fetchPrices 声明前使用问题
- 添加价格非负数验证
- 格式化代码

* fix: wrap upsertModelPrice in transaction for data integrity
* fix: disable thinking when tool_use is first block

- Extend thinking signature rectifier to detect tool_use-first error and drop top-level thinking on retry
- Add default error rule guidance for thinking/tool_use mismatch
- Add unit tests for rectifier, forwarder retry path, and default rule sync

* fix: improve thinking/tool_use error fallback
* fix(db): make latest drizzle migrations idempotent

Use ADD COLUMN IF NOT EXISTS in 0044_uneven_donald_blake.sql (line 1)
Use ADD COLUMN IF NOT EXISTS in 0049_shocking_ultimatum.sql (line 1)
Use ADD COLUMN IF NOT EXISTS in 0050_flippant_jack_flag.sql (line 1)
Use ADD COLUMN IF NOT EXISTS in 0051_silent_maelstrom.sql (line 1)
Use ADD COLUMN IF NOT EXISTS in 0052_model_price_source.sql (line 1)

* config: 添加 .codex 目录到 .gitignore
* refactor(prices): sync TOML cloud price table and harden billing

* fix(prices): address PR review feedback
* fix: prevent provider badge overflow in logs table

* fix: make provider chain trigger shrinkable

* fix: hide invalid cost multiplier badge

* fix: avoid invalid multiplier in usage logs

* fix: hide invalid multiplier in error details

* test: add provider chain popover layout regression

* test: cover invalid multiplier rendering branches

* test: cover empty and undefined cost multiplier
* feat: update pricing table UI

* chore: format code (feat-prices-ui-custom-model-6ffe413)

* fix: address pricing UI review feedback
* docs: add OpenCode config guide to usage-doc

* docs: fix OpenCode Scoop command and refactor config snippet

* docs: remove OpenAI-compatible wording from OpenCode guide

* docs: refine OpenCode install and config
* chore: remove seed price table and force cloud sync

* Update src/lib/price-sync/seed-initializer.ts

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* chore: format code (chore-force-cloud-price-table-f1ab426)

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
@coderabbitai
Copy link

coderabbitai bot commented Jan 10, 2026

Important

Review skipped

Too many files!

5 files out of 155 files are above the max files limit of 150.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

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

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

@greptile-apps
Copy link

greptile-apps bot commented Jan 10, 2026

Too many files changed for review. (155 files found, 100 file limit)

@github-actions github-actions bot added the size/XL Extra Large PR (> 1000 lines) label Jan 10, 2026
@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!

此版本发布了 v0.4.1,引入了多项核心功能,旨在提升系统的健壮性、灵活性和用户体验。通过新增的整流器和响应修复器,系统能够更智能地处理上游服务问题。对模型价格管理进行了全面升级,支持更精细的控制和更友好的同步机制。同时,扩展了对新 CLI 工具的集成,并对用户界面进行了优化,以提供更直观的信息展示。

Highlights

  • 新增整流器功能: 引入了 Thinking Signature Rectifier,用于自动修复 Anthropic 模型返回的 thinking 签名不兼容或非法请求错误,通过移除不兼容的 thinking 块并重试来提高请求成功率。此功能默认启用,并可在系统设置中配置。
  • 新增响应整流器: 新增 Response Fixer,可自动修复上游响应中常见的编码、SSE 和截断 JSON 格式问题,确保响应的可用性和稳定性。此功能默认启用,并可在系统设置中进行详细配置。
  • 支持 OpenCode CLI: 新增了对 OpenCode CLI 的支持,提供了详细的安装和配置指南,允许用户通过 CCH 代理服务访问 Claude、GPT 和 Gemini 模型。
  • 增强自定义模型价格管理: 模型价格管理功能得到显著增强,支持手动添加、编辑和删除模型价格。引入了云端价格表同步冲突检测机制,允许管理员选择性覆盖手动价格,并支持 TOML 格式的价格表上传。模型价格列表现在支持按来源和 LiteLLM 供应商进行筛选,并展示模型能力和缓存定价。
  • 自动排序供应商优先级: 新增了自动排序供应商优先级的功能,可根据成本倍率自动调整供应商的优先级,以优化路由决策。
  • 我的用量页面重构: 重构了“我的用量”页面,移除了“今日使用”卡片,并引入了可折叠的配额使用卡片和统计摘要卡片,提供更清晰的用量概览和模型消耗明细。同时,增强了过期信息显示,并增加了用户 RPM 限制和访问限制(允许的模型/客户端)的展示。
  • 日志详情优化: 优化了日志详情弹窗,现在可以显示会话的特殊设置、更详细的错误信息(包括过滤掉的供应商)、以及模型重定向的计费来源。同时,改进了状态码和倍率的显示逻辑。
  • 数据库架构更新: 数据库架构进行了更新,包括为 message_request 表添加 special_settings 字段,为 system_settings 表添加 enable_response_fixerresponse_fixer_configenable_thinking_signature_rectifier 字段,以及为 model_prices 表添加 source 字段和索引,以支持新功能。
  • BREAKING CHANGE: 此前用户通过自定义 JSON 方式添加的自定义模型将不再有效,需要重新添加。
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/release.yml
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

Choose a reason for hiding this comment

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

[Medium] [TYPE-ANY-USAGE] Unsafe use of any type in object destructuring

Why this is a problem: Using as any to destructure and discard the signature property bypasses type safety. While this works, it sets a precedent for untyped code and loses compiler assistance for catching refactoring errors.

Suggested fix:

// Replace this:
const { signature: _signature, ...rest } = blockObj as any;

// With this typed version:
const { signature: _signature, ...rest } = blockObj as Record<string, unknown> & { signature?: unknown };

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 release PR (v0.4.1) adding rectifier support, OpenCode compatibility, custom model pricing, and provider auto-sorting. The changes are extensive but well-structured with comprehensive test coverage. The core proxy pipeline changes are well-designed with proper error handling and audit logging.

PR Size: XL

  • Lines changed: 56,844 (22,923 additions, 33,921 deletions)
  • Files changed: 155

Split Suggestion: For future releases, consider breaking changes into feature-specific PRs:

  • Response Fixer module (encoding, SSE, JSON fixers)
  • Thinking Signature Rectifier
  • Model Price Management UI & API
  • Provider Auto-Sort feature
  • i18n updates

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 2 0
Comments/Docs 0 0 0 0
Tests 0 0 0 0
Simplification 0 0 0 0

High Priority Issues (Should Fix)

None identified.

Medium Priority Issues (Consider Fixing)

  1. [TYPE-ANY-USAGE] src/app/v1/_lib/proxy/thinking-signature-rectifier.ts - Two instances of as any type casts (lines ~110 and ~180) that could be replaced with proper typing for better type safety.

Positive Observations (Not requiring action)

  • Error Handling: Good error handling patterns throughout. The ResponseFixer.process() wrapper in response-handler.ts properly catches exceptions and falls back gracefully.
  • Logging: Consistent use of structured logging with context.
  • Test Coverage: New features have corresponding test files with good coverage.
  • Security: The isPriceDataEqual function includes prototype pollution protection.
  • DoS Protection: The ChunkBuffer in response-fixer has memory bounds checking to prevent unbounded growth.

Review Coverage

  • Logic and correctness - Clean
  • Security (OWASP Top 10) - Clean
  • Error handling - Clean (proper try/catch with logging)
  • Type safety - Minor issues noted
  • Documentation accuracy - Clean
  • Test coverage - Adequate (new tests for all major features)
  • Code clarity - Good

Automated review by Claude AI

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 包含了一系列重要的功能增强和重构,显著提升了系统的稳定性和用户体验。主要亮点包括:

  • 响应整流器 (Response Fixer):这是一个非常出色的功能,能够自动修复上游供应商常见的响应问题(如编码、SSE 格式、截断的 JSON),极大地增强了系统的健壮性。
  • Thinking 签名整流器:针对 Anthropic 模型的特定错误增加了自动修复和重试机制,这是一个非常精细和实用的优化。
  • 模型价格管理重构:完全重构了模型价格管理页面,支持了手动添加/编辑模型、从云端同步价格,并增加了冲突检测,用户体验得到了巨大提升。
  • 供应商自动排序:新增了根据成本倍率自动排序供应商优先级的功​​能,简化了配置。
  • “我的用量”页面重构:用一个更强大、支持日期范围选择的统计卡片替换了原有的“今日用量”,并用可折叠卡片优化了布局,信息展示更清晰、灵活。
  • OpenCode 支持:增加了对新的 AI 编程代理 OpenCode 的支持。
  • 代码健壮性:在成本计算、Redis 追踪等关键路径上增加了 try...catch 保护,防止因次要错误导致整个请求失败,这是一个很好的防御性编程实践。

代码质量很高,改动考虑周全。我只发现了一个可以进一步优化的地方,关于一个自定义的深度相等比较函数。

总体来说,这是一次非常出色的更新,恭喜!

Comment on lines 34 to 67
function isPriceDataEqual(data1: ModelPriceData, data2: ModelPriceData): boolean {
// 深度比较两个价格对象
return JSON.stringify(data1) === JSON.stringify(data2);
const stableStringify = (value: unknown): string => {
const seen = new WeakSet<object>();

const canonicalize = (node: unknown): unknown => {
if (node === null || node === undefined) return node;
if (typeof node !== "object") return node;

if (seen.has(node as object)) {
return null;
}
seen.add(node as object);

if (Array.isArray(node)) {
return node.map(canonicalize);
}

const obj = node as Record<string, unknown>;
const result: Record<string, unknown> = Object.create(null);
for (const key of Object.keys(obj).sort()) {
// 防御:避免 __proto__/constructor/prototype 触发原型链污染
if (key === "__proto__" || key === "constructor" || key === "prototype") {
continue;
}
result[key] = canonicalize(obj[key]);
}
return result;
};

return JSON.stringify(canonicalize(value));
};

return stableStringify(data1) === stableStringify(data2);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

isPriceDataEqual 函数实现了一个自定义的、用于深层对象比较的规范化字符串转换函数。虽然这个实现考虑了键排序和原型链污染等问题,显得很巧妙,但它也相对复杂,并且重新实现了一个常见的功能。

建议使用一个经过充分测试的库(如 fast-deep-equal)来代替。这样做有几个好处:

  1. 简化代码:可以移除大约 30 行的自定义实现,使代码更简洁易读。
  2. 增强健壮性:库函数通常能处理更多的边界情况(例如 DateRegExp 对象,或属性值为 undefined 的情况),减少了潜在的细微 bug。
  3. 降低维护成本:依赖于一个标准的库,未来维护会更容易。

虽然当前的实现可能满足需求,但从长期维护和代码清晰度的角度来看,使用标准库是更好的选择。

您还需要在文件顶部导入 isEqual 并将 fast-deep-equal 添加到您的依赖项中:

import isEqual from "fast-deep-equal";
function isPriceDataEqual(data1: ModelPriceData, data2: ModelPriceData): boolean {
  return isEqual(data1, data2);
}

@github-actions github-actions bot merged commit efc75ed into main Jan 10, 2026
17 checks passed
@github-project-automation github-project-automation bot moved this from Backlog to Done in Claude Code Hub Roadmap Jan 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

Status: Done

4 participants