Skip to content

feat(usage): add anthropic effort tracking and display. #900#901

Merged
ding113 merged 2 commits intoding113:devfrom
Hwwwww-dev:effort-tag
Mar 14, 2026
Merged

feat(usage): add anthropic effort tracking and display. #900#901
ding113 merged 2 commits intoding113:devfrom
Hwwwww-dev:effort-tag

Conversation

@Hwwwww-dev
Copy link
Contributor

@Hwwwww-dev Hwwwww-dev commented Mar 11, 2026

Summary

Add tracking and display of Anthropic's effort parameter in usage logs. When requests include output_config.effort, this value is now captured and displayed as a color-coded badge in the dashboard and my-usage pages.

Problem

Usage logs did not display the Anthropic effort level configured in requests, making it difficult to identify which effort level was used for each request.

Fixes #900 - Add effort indicator to usage records

Solution

  • Extract output_config.effort from request bodies for Anthropic providers
  • Store effort as a new anthropic_effort special setting type
  • Display effort in usage log tables with color-coded badges

Changes

Core Changes

  • Add AnthropicEffortSpecialSetting type to src/types/special-settings.ts
  • Add extractAnthropicEffortFromRequestBody() utility in src/lib/utils/anthropic-effort.ts
  • Add extractAnthropicEffortFromSpecialSettings() for retrieval
  • Capture effort in ProxyMessageService for Anthropic providers
  • Add anthropicEffort field to usage log data structures

UI Changes

  • Create AnthropicEffortBadge component with effort-level-specific styling:
    • auto - sky/cyan gradient
    • low - slate
    • medium - amber
    • high - rose
    • max - red
  • Update ModelDisplayWithRedirect to show effort badge
  • Update usage logs tables to display effort

i18n

  • Add anthropicEffort key to all 5 languages (en, ja, ru, zh-CN, zh-TW)

Screenshots

image

Checklist

  • Code follows project conventions
  • i18n keys added for all 5 languages
  • No breaking changes

Description enhanced by Claude AI

Greptile Summary

This PR adds end-to-end tracking and display of the Anthropic output_config.effort request parameter, surfacing it as a colour-coded badge in both the admin dashboard logs table and the user's personal usage view.

Key changes:

  • New AnthropicEffortSpecialSetting type added to the SpecialSetting union for audit/display purposes.
  • New utility functions (extractAnthropicEffortFromRequestBody, extractAnthropicEffortFromSpecialSettings) safely extract effort from the raw request body and from persisted special settings with proper type guards.
  • Proxy message service captures the effort at request ingestion time for Anthropic providers (claude / claude-auth), with an idempotency guard to avoid duplicate entries on retry.
  • Repository layer (findUsageLogsBatch, findUsageLogsForKeySlim, findUsageLogsWithDetails) derives anthropicEffort from the unified special settings on every query path.
  • New AnthropicEffortBadge component renders per-level colour coding (auto / low / medium / high / max) with a neutral default for unrecognised values.
  • i18n strings are added to all five locale files, but the non-English locales leave the label prefix ("Effort: {effort}") untranslated, unlike the already-translated billingModel sibling key.

Confidence Score: 4/5

  • This PR is safe to merge; no logic errors or data-integrity risks were identified.
  • The implementation is well-structured and follows existing codebase patterns. The only issues found are minor: the non-English locale files leave "Effort:" untranslated (inconsistent with the translated billingModel key), and the ledger-fallback path in findUsageLogsBatch omits an explicit anthropicEffort: null assignment (safe due to optional typing but asymmetric).
  • Non-English i18n files (messages/ja, messages/ru, messages/zh-CN, messages/zh-TW) for the untranslated label, and the ledger fallback block in src/repository/usage-logs.ts.

Important Files Changed

Filename Overview
src/types/special-settings.ts Adds AnthropicEffortSpecialSetting type to the SpecialSetting union; well-documented with JSDoc comment following the existing pattern.
src/lib/utils/anthropic-effort.ts New utility file; extractAnthropicEffortFromRequestBody safely navigates output_config.effort with proper type guards, and extractAnthropicEffortFromSpecialSettings iterates the settings array — both are well-guarded and clean.
src/components/customs/anthropic-effort-badge.tsx New badge component with per-effort-level colour-coding (auto/low/medium/high/max) and a safe default style for unrecognised values; implementation is clean.
src/app/v1/_lib/proxy/message-service.ts Extracts output_config.effort from the request body for Anthropic providers and records it as a special setting; the idempotency guard (!hasAnthropicEffortAudit) correctly prevents duplicate entries on retry.
src/repository/usage-logs.ts Adds anthropicEffort extraction to three query paths (batch cursor, slim for key, and with-details); the ledger fallback in findUsageLogsBatch omits anthropicEffort on returned rows (handled safely via the optional field, but inconsistent).
src/app/[locale]/dashboard/logs/_components/model-display-with-redirect.tsx Renders the effort badge below the model name in both redirect and non-redirect variants; layout restructured to a flex-col container cleanly.
src/actions/my-usage.ts Adds anthropicEffort to MyUsageLogEntry and passes it through from the slim row; straightforward addition with no issues.
messages/ja/myUsage.json Adds anthropicEffort key but leaves the value untranslated ("Effort: {effort}"), inconsistent with how billingModel is translated in each locale.

Sequence Diagram

sequenceDiagram
    participant Client
    participant ProxyMessageService
    participant Session
    participant DB as Database (message_request)
    participant Repo as usage-logs.ts
    participant UI as Dashboard / MyUsage UI

    Client->>ProxyMessageService: POST /v1/messages (body includes output_config.effort)
    ProxyMessageService->>Session: getSpecialSettings() — check for existing anthropic_effort
    ProxyMessageService->>ProxyMessageService: extractAnthropicEffortFromRequestBody(body)
    ProxyMessageService->>Session: addSpecialSetting({ type: "anthropic_effort", effort, hit: true })
    ProxyMessageService->>DB: createMessageRequest({ special_settings: [...anthropic_effort] })

    Repo->>DB: SELECT specialSettings FROM message_request
    Repo->>Repo: buildUnifiedSpecialSettings(...)
    Repo->>Repo: extractAnthropicEffortFromSpecialSettings(unifiedSettings)
    Repo-->>UI: UsageLogRow { anthropicEffort: "high" }

    UI->>UI: AnthropicEffortBadge({ effort: "high", label: "Effort: high" })
Loading

Comments Outside Diff (1)

  1. src/repository/usage-logs.ts, line 388-389 (link)

    Missing anthropicEffort in ledger fallback path of findUsageLogsBatch

    In the ledger fallback path (lines ~349–390, building fallbackLogs from usageLedger), the anthropicEffort field is never set on the returned UsageLogRow objects. Since anthropicEffort is declared as optional (anthropicEffort?: string | null) on UsageLogRow, TypeScript will not flag this, and UI components handle undefined as falsy — so no crash occurs. However, the omission is asymmetric with the non-fallback path where anthropicEffort is always populated.

    For consistency and future-proofing, consider explicitly setting anthropicEffort: null in fallbackLogs:

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: src/repository/usage-logs.ts
    Line: 388-389
    
    Comment:
    **Missing `anthropicEffort` in ledger fallback path of `findUsageLogsBatch`**
    
    In the ledger fallback path (lines ~349–390, building `fallbackLogs` from `usageLedger`), the `anthropicEffort` field is never set on the returned `UsageLogRow` objects. Since `anthropicEffort` is declared as optional (`anthropicEffort?: string | null`) on `UsageLogRow`, TypeScript will not flag this, and UI components handle `undefined` as falsy — so no crash occurs. However, the omission is asymmetric with the non-fallback path where `anthropicEffort` is always populated.
    
    For consistency and future-proofing, consider explicitly setting `anthropicEffort: null` in `fallbackLogs`:
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: e13f968

Greptile also left 1 inline comment on this PR.

"noLogs": "ログがありません",
"unknownModel": "不明なモデル",
"billingModel": "課金: {model}"
"billingModel": "課金: {model}",
Copy link

Choose a reason for hiding this comment

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

anthropicEffort label not translated

The billingModel label is properly translated in all non-English locales (e.g. "課金: {model}" in Japanese, "Биллинг: {model}" in Russian, "计费:{model}" in Chinese), but anthropicEffort is left as "Effort: {effort}" across all non-English locales. For consistency, this label should be translated.

This same issue applies to:

  • messages/ja/myUsage.json:61"Effort: {effort}" (should be e.g. "エフォート: {effort}")
  • messages/ru/myUsage.json:61"Effort: {effort}" (should be e.g. "Уровень сложности: {effort}")
  • messages/zh-CN/myUsage.json:61"Effort: {effort}" (should be e.g. "思考强度: {effort}")
  • messages/zh-TW/myUsage.json:61"Effort: {effort}" (should be e.g. "思考強度: {effort}")
  • messages/ja/dashboard.json — same pattern
  • messages/ru/dashboard.json — same pattern
  • messages/zh-CN/dashboard.json — same pattern
  • messages/zh-TW/dashboard.json — same pattern
Prompt To Fix With AI
This is a comment left during a code review.
Path: messages/ja/myUsage.json
Line: 61

Comment:
**`anthropicEffort` label not translated**

The `billingModel` label is properly translated in all non-English locales (e.g. `"課金: {model}"` in Japanese, `"Биллинг: {model}"` in Russian, `"计费:{model}"` in Chinese), but `anthropicEffort` is left as `"Effort: {effort}"` across all non-English locales. For consistency, this label should be translated.

This same issue applies to:
- `messages/ja/myUsage.json:61``"Effort: {effort}"` (should be e.g. `"エフォート: {effort}"`)
- `messages/ru/myUsage.json:61``"Effort: {effort}"` (should be e.g. `"Уровень сложности: {effort}"`)
- `messages/zh-CN/myUsage.json:61``"Effort: {effort}"` (should be e.g. `"思考强度: {effort}"`)
- `messages/zh-TW/myUsage.json:61``"Effort: {effort}"` (should be e.g. `"思考強度: {effort}"`)
- `messages/ja/dashboard.json` — same pattern
- `messages/ru/dashboard.json` — same pattern
- `messages/zh-CN/dashboard.json` — same pattern
- `messages/zh-TW/dashboard.json` — same pattern

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

@coderabbitai
Copy link

coderabbitai bot commented Mar 11, 2026

📝 Walkthrough

Walkthrough

此PR为系统添加了Anthropic Effort指标支持,包括多语言翻译条目、数据模型扩展、UI组件、工具函数、特殊设置类型定义和数据库层映射。

Changes

Cohort / File(s) Summary
多语言翻译文件
messages/en/dashboard.json, messages/en/myUsage.json, messages/ja/dashboard.json, messages/ja/myUsage.json, messages/ru/dashboard.json, messages/ru/myUsage.json, messages/zh-CN/dashboard.json, messages/zh-CN/myUsage.json, messages/zh-TW/dashboard.json, messages/zh-TW/myUsage.json
在dashboard和myUsage的多个语言版本中添加anthropicEffort翻译条目,值为"Effort: {effort}",用于UI展示。
特殊设置类型和工具函数
src/types/special-settings.ts, src/lib/utils/anthropic-effort.ts, src/lib/utils/special-settings.ts
添加AnthropicEffortSpecialSetting类型,实现effort值的提取和规范化函数,扩展特殊设置键生成逻辑以支持anthropic_effort类型。
UI组件
src/components/customs/anthropic-effort-badge.tsx
创建新的AnthropicEffortBadge组件,支持多个effort级别(auto、low、medium、high、max)的样式映射和展示。
数据模型和业务逻辑
src/actions/my-usage.ts, src/repository/usage-logs.ts
MyUsageLogEntryUsageLogRowUsageLogSlimRow中添加anthropicEffort字段,在数据查询和映射路径中计算并填充该字段。
日志表UI组件
src/app/[locale]/dashboard/logs/_components/model-display-with-redirect.tsx, src/app/[locale]/dashboard/logs/_components/usage-logs-table.tsx, src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsx
在模型显示组件中添加anthropicEffort属性,更新布局以展示effort badge,在使用日志表中传递和渲染此属性。
我的使用页面UI组件
src/app/[locale]/my-usage/_components/usage-logs-table.tsx
在用户使用日志表中添加条件渲染的AnthropicEffortBadge,当存在anthropicEffort数据时显示。
代理服务
src/app/v1/_lib/proxy/message-service.ts
在ProxyMessageService的ensureContext方法中添加audit逻辑,为Claude/Claude-auth提供者从请求体中提取anthropic effort并创建特殊设置记录。

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed PR标题清晰准确地总结了主要变更:添加Anthropic effort追踪和显示功能,并关联了issue #900
Description check ✅ Passed PR描述详细说明了问题、解决方案、核心变更、UI变更和i18n更新,与变更集完全相关。

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests 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.

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: 2

🧹 Nitpick comments (1)
src/actions/my-usage.ts (1)

150-155: 统一 anthropicEffort 的空值语义。

这里把字段声明成 ?: string | null,但下面的映射已经稳定产出 string | null。如果 undefined 没有独立语义,建议去掉可选标记,避免调用方再处理第三种状态。

Based on learnings "In TypeScript interfaces, explicitly document and enforce distinct meanings for null and undefined. Example: for numeric limits like limitTotalUsd, use 'number | null | undefined' when null signifies explicitly unlimited (e.g., matches DB schema or special UI logic) and undefined signifies 'inherit default'. This pattern should be consistently reflected in type definitions across related fields to preserve semantic clarity between database constraints and UI behavior."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/actions/my-usage.ts` around lines 150 - 155, The MyUsageLogEntry type
declares anthropicEffort as optional (anthropicEffort?: string | null) but your
data mapping always yields string | null, so remove the optional marker and make
the field strictly "anthropicEffort: string | null" in the MyUsageLogEntry
interface (update any callers that currently check for undefined to only handle
string or null); reference the MyUsageLogEntry interface and the anthropicEffort
property when making this change to keep null/undefined semantics consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@messages/zh-CN/dashboard.json`:
- Line 161: The zh-CN translation for the key "anthropicEffort" contains an
untranslated English label; update the value for "anthropicEffort" in
messages/zh-CN/dashboard.json to a proper Chinese string (e.g., "努力程度:{effort}"
or "努力:{effort}") so it matches surrounding translated fields and follows i18n
rules.

In `@messages/zh-CN/myUsage.json`:
- Around line 61-62: The translation key "anthropicEffort" currently inserts the
raw {effort} value which leaves English levels visible; add discrete locale keys
for each level (e.g., "effort.low", "effort.medium", "effort.high") in the
messages/zh-CN/myUsage.json and change the rendering code that uses the
"anthropicEffort" key to first map the effort value to its localized string
(e.g. localizedEffort = t(`effort.${effort}`)) and then pass that
localizedEffort into t('anthropicEffort', { effort: localizedEffort }) instead
of injecting the raw 'low/medium/high'.

---

Nitpick comments:
In `@src/actions/my-usage.ts`:
- Around line 150-155: The MyUsageLogEntry type declares anthropicEffort as
optional (anthropicEffort?: string | null) but your data mapping always yields
string | null, so remove the optional marker and make the field strictly
"anthropicEffort: string | null" in the MyUsageLogEntry interface (update any
callers that currently check for undefined to only handle string or null);
reference the MyUsageLogEntry interface and the anthropicEffort property when
making this change to keep null/undefined semantics consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c15e4a69-2579-4b77-99db-d6be9ae06e41

📥 Commits

Reviewing files that changed from the base of the PR and between 14740d1 and e13f968.

📒 Files selected for processing (21)
  • messages/en/dashboard.json
  • messages/en/myUsage.json
  • messages/ja/dashboard.json
  • messages/ja/myUsage.json
  • messages/ru/dashboard.json
  • messages/ru/myUsage.json
  • messages/zh-CN/dashboard.json
  • messages/zh-CN/myUsage.json
  • messages/zh-TW/dashboard.json
  • messages/zh-TW/myUsage.json
  • src/actions/my-usage.ts
  • src/app/[locale]/dashboard/logs/_components/model-display-with-redirect.tsx
  • src/app/[locale]/dashboard/logs/_components/usage-logs-table.tsx
  • src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsx
  • src/app/[locale]/my-usage/_components/usage-logs-table.tsx
  • src/app/v1/_lib/proxy/message-service.ts
  • src/components/customs/anthropic-effort-badge.tsx
  • src/lib/utils/anthropic-effort.ts
  • src/lib/utils/special-settings.ts
  • src/repository/usage-logs.ts
  • src/types/special-settings.ts

"nonBilling": "非计费",
"skipped": "已跳过",
"specialSettings": "特殊设置",
"anthropicEffort": "Effort: {effort}",
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

zh-CN 文案不要直接回退成英文。

这里会直接显示在中文界面里,Effort 没有本地化,会和周围已翻译字段不一致。请补上对应的中文文案。

As per coding guidelines "All user-facing strings must use i18n (5 languages supported: zh-CN, zh-TW, en, ja, ru). Never hardcode display text".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@messages/zh-CN/dashboard.json` at line 161, The zh-CN translation for the key
"anthropicEffort" contains an untranslated English label; update the value for
"anthropicEffort" in messages/zh-CN/dashboard.json to a proper Chinese string
(e.g., "努力程度:{effort}" or "努力:{effort}") so it matches surrounding translated
fields and follows i18n rules.

Comment on lines +61 to +62
"billingModel": "计费:{model}",
"anthropicEffort": "Effort: {effort}"
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

这里还没有真正完成本地化。

anthropicEffort 直接插入了 {effort},但当前新增文案没有提供 low / medium / high 的 locale 映射。这样中文界面大概率还是会显示英文等级。建议把 effort 等级拆成独立翻译键,再由渲染层按值映射后插入。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@messages/zh-CN/myUsage.json` around lines 61 - 62, The translation key
"anthropicEffort" currently inserts the raw {effort} value which leaves English
levels visible; add discrete locale keys for each level (e.g., "effort.low",
"effort.medium", "effort.high") in the messages/zh-CN/myUsage.json and change
the rendering code that uses the "anthropicEffort" key to first map the effort
value to its localized string (e.g. localizedEffort = t(`effort.${effort}`)) and
then pass that localizedEffort into t('anthropicEffort', { effort:
localizedEffort }) instead of injecting the raw 'low/medium/high'.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, 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 significant enhancement by integrating Anthropic's effort parameter into the application's usage tracking and display system. The change allows for the capture, storage, and visual representation of the effort level associated with Anthropic API requests, making it easier for users to understand and analyze their model usage patterns directly within the UI. This improves the transparency of API interactions and aids in debugging or optimizing model configurations.

Highlights

  • Anthropic Effort Tracking: Implemented end-to-end tracking of Anthropic's output_config.effort parameter from request to display.
  • Visual Display: The effort value is now displayed as a color-coded badge in both the dashboard and 'my usage' pages, providing quick visual identification.
  • Data Persistence: A new AnthropicEffortSpecialSetting type was introduced to store the effort level within usage logs.
  • Internationalization: Added anthropicEffort translation keys across five different languages to support global users.
  • Utility Functions: Created dedicated utility functions to safely extract Anthropic effort from request bodies and existing special settings.
Changelog
  • messages/en/dashboard.json
    • Added the 'anthropicEffort' translation key.
  • messages/en/myUsage.json
    • Added the 'anthropicEffort' translation key.
  • messages/ja/dashboard.json
    • Added the 'anthropicEffort' translation key.
  • messages/ja/myUsage.json
    • Added the 'anthropicEffort' translation key.
  • messages/ru/dashboard.json
    • Added the 'anthropicEffort' translation key.
  • messages/ru/myUsage.json
    • Added the 'anthropicEffort' translation key.
  • messages/zh-CN/dashboard.json
    • Added the 'anthropicEffort' translation key.
  • messages/zh-CN/myUsage.json
    • Added the 'anthropicEffort' translation key.
  • messages/zh-TW/dashboard.json
    • Added the 'anthropicEffort' translation key.
  • messages/zh-TW/myUsage.json
    • Added the 'anthropicEffort' translation key.
  • src/actions/my-usage.ts
    • Updated the MyUsageLogEntry interface and getMyUsageLogs function to include and populate anthropicEffort.
  • src/app/[locale]/dashboard/logs/_components/model-display-with-redirect.tsx
    • Imported AnthropicEffortBadge and updated ModelDisplayWithRedirect to display the Anthropic effort badge.
  • src/app/[locale]/dashboard/logs/_components/usage-logs-table.tsx
    • Passed anthropicEffort to the ModelDisplayWithRedirect component in the usage logs table.
  • src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsx
    • Passed anthropicEffort to the ModelDisplayWithRedirect component in the virtualized logs table.
  • src/app/[locale]/my-usage/_components/usage-logs-table.tsx
    • Imported AnthropicEffortBadge and rendered it in the my usage logs table.
  • src/app/v1/_lib/proxy/message-service.ts
    • Imported extractAnthropicEffortFromRequestBody and added logic to capture and store Anthropic effort as a special setting.
  • src/components/customs/anthropic-effort-badge.tsx
    • Added a new component AnthropicEffortBadge to display color-coded Anthropic effort levels.
  • src/lib/utils/anthropic-effort.ts
    • Added new utility functions to extract and normalize Anthropic effort from request bodies and special settings.
  • src/lib/utils/special-settings.ts
    • Updated buildSettingKey to correctly serialize anthropic_effort special settings.
  • src/repository/usage-logs.ts
    • Updated usage log interfaces and data retrieval functions to include and process anthropicEffort from special settings, and introduced mapUsageLogSlimRow.
  • src/types/special-settings.ts
    • Defined a new AnthropicEffortSpecialSetting type and added it to the SpecialSetting union.
Activity
  • The pull request description was enhanced by Claude AI.
  • Greptile provided a detailed summary, confidence score, important files changed, sequence diagram, and 1 inline comment.
Using Gemini Code Assist

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

Invoking Gemini

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

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

Customization

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

Limitations & Feedback

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

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

Footnotes

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

Copy link
Contributor

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

Choose a reason for hiding this comment

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

Code Review

This pull request effectively adds tracking and display for Anthropic's effort parameter. The implementation is well-structured, with new types, utility functions, and UI components that are clean and robust. The changes to the data-access layer and proxy service are also solid.

My main feedback is related to internationalization. The new anthropicEffort i18n key has been added to all language files, but the values have not been translated for non-English locales. I've left specific suggestions for each language file to ensure a consistent user experience across all supported languages.

Note: Security Review did not run due to the size of the PR.

"nonBilling": "非課金",
"skipped": "スキップ",
"specialSettings": "特殊設定",
"anthropicEffort": "Effort: {effort}",
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The new i18n key anthropicEffort has been added, but its value is untranslated. For consistency with other translated keys like billingModel, please provide a Japanese translation for "Effort: {effort}". A common translation would be エフォート: {effort}.

Suggested change
"anthropicEffort": "Effort: {effort}",
"anthropicEffort": "エフォート: {effort}",

"unknownModel": "不明なモデル",
"billingModel": "課金: {model}"
"billingModel": "課金: {model}",
"anthropicEffort": "Effort: {effort}"
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The new i18n key anthropicEffort has been added, but its value is untranslated. For consistency with other translated keys like billingModel, please provide a Japanese translation for "Effort: {effort}". A common translation would be エフォート: {effort}.

Suggested change
"anthropicEffort": "Effort: {effort}"
"anthropicEffort": "エフォート: {effort}"

"nonBilling": "Не тарифицируется",
"skipped": "Пропущено",
"specialSettings": "Особые",
"anthropicEffort": "Effort: {effort}",
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The new i18n key anthropicEffort has been added, but its value is untranslated. For consistency with other translated keys like billingModel, please provide a Russian translation for "Effort: {effort}". A possible translation is Усилие: {effort}.

Suggested change
"anthropicEffort": "Effort: {effort}",
"anthropicEffort": "Усилие: {effort}",

"unknownModel": "Неизвестная модель",
"billingModel": "Биллинг: {model}"
"billingModel": "Биллинг: {model}",
"anthropicEffort": "Effort: {effort}"
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The new i18n key anthropicEffort has been added, but its value is untranslated. For consistency with other translated keys like billingModel, please provide a Russian translation for "Effort: {effort}". A possible translation is Усилие: {effort}.

Suggested change
"anthropicEffort": "Effort: {effort}"
"anthropicEffort": "Усилие: {effort}"

"nonBilling": "非计费",
"skipped": "已跳过",
"specialSettings": "特殊设置",
"anthropicEffort": "Effort: {effort}",
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The new i18n key anthropicEffort has been added, but its value is untranslated. For consistency with other translated keys like billingModel ("计费:{model}"), please provide a Chinese (Simplified) translation for "Effort: {effort}". A possible translation could be "算力: {effort}".

Suggested change
"anthropicEffort": "Effort: {effort}",
"anthropicEffort": "算力: {effort}",

"unknownModel": "未知模型",
"billingModel": "计费:{model}"
"billingModel": "计费:{model}",
"anthropicEffort": "Effort: {effort}"
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The new i18n key anthropicEffort has been added, but its value is untranslated. For consistency with other translated keys like billingModel ("计费:{model}"), please provide a Chinese (Simplified) translation for "Effort: {effort}". A possible translation could be "算力: {effort}".

Suggested change
"anthropicEffort": "Effort: {effort}"
"anthropicEffort": "算力: {effort}"

"nonBilling": "非計費",
"skipped": "已跳過",
"specialSettings": "特殊設定",
"anthropicEffort": "Effort: {effort}",
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The new i18n key anthropicEffort has been added, but its value is untranslated. For consistency with other translated keys like billingModel ("計費:{model}"), please provide a Chinese (Traditional) translation for "Effort: {effort}". A possible translation could be "算力: {effort}".

Suggested change
"anthropicEffort": "Effort: {effort}",
"anthropicEffort": "算力: {effort}",

"unknownModel": "未知的模型",
"billingModel": "計費:{model}"
"billingModel": "計費:{model}",
"anthropicEffort": "Effort: {effort}"
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The new i18n key anthropicEffort has been added, but its value is untranslated. For consistency with other translated keys like billingModel ("計費:{model}"), please provide a Chinese (Traditional) translation for "Effort: {effort}". A possible translation could be "算力: {effort}".

Suggested change
"anthropicEffort": "Effort: {effort}"
"anthropicEffort": "算力: {effort}"

@ding113 ding113 merged commit d11e024 into ding113:dev Mar 14, 2026
23 of 24 checks passed
@github-project-automation github-project-automation bot moved this from Backlog to Done in Claude Code Hub Roadmap Mar 14, 2026
@coderabbitai coderabbitai bot mentioned this pull request Mar 14, 2026
10 tasks
ding113 added a commit that referenced this pull request Mar 14, 2026
* fix(proxy): prevent TypeError in NON_RETRYABLE_CLIENT_ERROR handler with transport errors

Fixes a regression where native transport errors (SocketError, UND_ERR_SOCKET)
could be misclassified as NON_RETRYABLE_CLIENT_ERROR by error rule matching,
causing the error handler to crash with "TypeError: getDetailedErrorMessage is
not a function" instead of properly rethrowing the original error.

Changes:
1. errors.ts: Add transport-error guard in categorizeErrorAsync() at priority 1.5
   - Detects SocketError, undici error codes (UND_ERR_SOCKET, ECONNREFUSED, etc.)
   - Returns SYSTEM_ERROR before error rule matching to prevent misclassification
   - Preserves correct failover behavior for network-level failures

2. forwarder.ts: Bifurcate NON_RETRYABLE_CLIENT_ERROR branch on instanceof check
   - ProxyError path: uses full ProxyError fields (statusCode, upstreamError, etc.)
   - Plain Error path: uses only base Error fields, avoids calling non-existent methods
   - Both paths preserve original error rethrow and provider chain recording

3. Add regression tests:
   - Test A: Verifies plain SocketError + forced NON_RETRYABLE_CLIENT_ERROR doesn't throw TypeError
   - Test B: Verifies categorizeErrorAsync returns SYSTEM_ERROR for transport errors

All 657 proxy unit tests pass. Type check and lint pass.

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

* chore: format code (dev-a3fd666)

* fix: assorted UI/UX and logic small fixes

* feat(request-filters): advanced mode operations and execution engine (#912)

* feat(request-filters): add advanced mode operations and final execution phase

Introduce two new axes for request filters: rule mode (simple/advanced)
and execution phase (guard/final). Advanced mode supports a JSON-defined
operation DSL with set, remove, merge, and insert operations. The final
phase executes after all provider overrides, enabling post-processing
use cases like system message injection with dedup and cache_control
manipulation.

Key changes:
- Schema: add rule_mode, execution_phase, operations columns + index
- Types: new FilterOperation DSL (SetOp, RemoveOp, MergeOp, InsertOp)
- Engine: 4-bucket cache split, applyFinal() method, operation executors
  with deep merge (null-as-delete), deep equal dedup, anchor matching
- Forwarder: integrate applyFinal in standard and Gemini branches
- Validation: validateOperations with ReDoS prevention via safe-regex
- UI: rule mode toggle, execution phase selector, JSON operations editor
- i18n: new keys for all 5 locales (en, zh-CN, zh-TW, ja, ru)
- Tests: 29 new tests covering all operation types and edge cases

* chore: format code (feat-request-filter-advanced-mode-ccee157)

* fix(security): harden request filter engine against prototype pollution and ReDoS bypass

- Block __proto__/constructor/prototype traversal in parsePath, deepMerge, and validation
- Add runtime safe-regex check in matchElement for regex matchers
- Fix ReDoS bypass in updateRequestFilterAction by checking effective target/matchType/action
- Add operations array length limit (max 50) and value validation for set/merge/insert ops
- Fix UI default executionPhase to match server default (guard, not final)
- Fix parsePath regex corruption from edit tool (double-escaped backslashes)

* fix(i18n,a11y): address code review findings for request filters

- Remove console.error from filter-dialog.tsx (error already shown via toast)
- Fix ja table.actions translation to "操作"
- Fix ru table.createdAt to "Дата создания"
- Fix zh-CN confirmDelete halfwidth ? to fullwidth ?
- Show operations count in target column for advanced mode filters
- Add aria-label to filter toggle Switch for accessibility

* fix(request-filters): address CodeRabbit review findings across 8 issues

Security:
- parsePath now rejects entire path on unsafe key instead of silently
  dropping segments (e.g. `a.__proto__.b` no longer becomes `a.b`)
- getValueByPath returns undefined on rejected paths instead of root object
- MergeOp/InsertOp types narrowed to scope:"body" with runtime validation

Correctness:
- GET/HEAD requests now run final-phase filters for header-only operations
  (both Gemini and non-Gemini branches)
- Gemini branch clones body via structuredClone before applyFinal to prevent
  in-place mutation of session.request.message on retries
- Reject advanced+guard combo at validation layer (create + update paths)

Quality:
- Consolidate 3 redundant getRequestFilterById calls into 1 per update
- Fix Switch aria-label to describe toggle purpose with filter name
- Add $type<FilterOperation[]|null> annotation to operations schema column
- Add toggleStatus i18n key across all 5 locales

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* fix(proxy): distinguish local client abort 499 from upstream HTTP 499

Adds isLocalAbort flag to ProxyError to differentiate CCH-synthesized 499
errors (client disconnection) from upstream providers returning HTTP 499.

Previously, isClientAbortError() matched any ProxyError with statusCode 499,
causing upstream 499 responses to bypass circuit-breaker and fallback logic.
Now only ProxyError instances explicitly marked with isLocalAbort=true are
treated as client aborts.

Also removes the broad "aborted" substring match from the message whitelist
to avoid false positives on upstream error messages containing that word.

* chore: format code (dev-bcdc6b7)

* fix: speed up users last usage lookup

* fix(db): add covering index for getUsers LATERAL join and fix CASE type mismatch in cache-hit-rate-alert

1. Add idx_usage_ledger_key_created_at_desc_cover index on (key, created_at
   DESC NULLS LAST, final_provider_id) with partial filter WHERE blocked_by IS
   NULL. This enables index-only scans for the LATERAL last-usage-per-key
   subquery in getUsers, reducing query time from ~28s to ~6.4ms.

2. Fix "CASE types integer and text cannot be matched" error in
   cache-hit-rate-alert by adding explicit ::integer casts to the
   ttlFallbackSecondsExpr CASE branches. PostgreSQL inferred parameterized
   values as text, which conflicted with integer literals (3600, 300) in the
   outer ttlSecondsExpr CASE.

3. Add regression test verifying ::integer casts are present in the generated
   SQL for cache-hit-rate-alert queries.

* chore: format code (dev-63c4c9c)

* feat(proxy): support codex desktop alias matching

* feat(billing): remove 1M context premium and add Codex 272k badge

Anthropic has GA'd the 1M context window for Opus 4.6 and Sonnet 4.6,
eliminating the long-context surcharge. The beta header
`context-1m-2025-08-07` is no longer needed.

Backend:
- Remove CONTEXT_1M_SUPPORTED_MODEL_PREFIXES, CONTEXT_1M_BETA_HEADER,
  Context1mPreference type, isContext1mSupportedModel, shouldApplyContext1m
- Remove AnthropicContext1mHeaderOverrideSpecialSetting type and derived logic
- Simplify forwarder 1M decision: just record client header, no injection
- Remove provider-selector Step 2.5 context1mPreference filter
- Add Codex 272k badge: set context1mApplied when input > 272k tokens

Frontend:
- Remove 1M Context Window setting from provider forms (options-section,
  provider-form-context, provider-form-types, batch-edit, legacy form)
- Remove premium pricing tooltips from usage-logs-table

i18n:
- Remove context1m provider config keys (5 languages)
- Remove context1mPricing premium text from dashboard (5 languages)

Tests:
- Remove anthropic_context_1m_header_override test cases
- Remove context1mPreference UI and patch draft tests

* chore: format code (dev-5a7db40)

* feat(usage): add anthropic effort tracking and display. #900 (#901)

* feat(usage): add anthropic effort tracking and display. #900

* chore: format code (effort-tag-558c8fd)

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* feat(deploy): support incremental updates to preserve secrets on re-deploy

Previously, re-running deploy.sh/deploy.ps1 would regenerate DB_PASSWORD,
ADMIN_TOKEN, and SUFFIX, causing database connection failures because the
PostgreSQL data volume still held the old password.

Now the scripts auto-detect existing deployments (.env + docker-compose.yaml)
and enter update mode: preserving DB_PASSWORD, ADMIN_TOKEN, SUFFIX, APP_PORT,
and any user-added custom env vars (e.g. LANGFUSE_*, FETCH_*). A --force-new
/ -ForceNew flag allows forcing a fresh install when needed.

* feat: support long-context pricing metadata

* feat: support long-context pricing metadata

* fix: return billing metadata when pricing is missing

* refactor: extract utilities, i18n fixes, and codex threshold constant

- Extract getUserFacingProviderTypes() to filter internal provider types
- Extract CODEX_1M_CONTEXT_TOKEN_THRESHOLD constant and maybeSetCodexContext1m helper
- Refactor limit-rule-picker to use t() shorthand for getTranslation
- i18n: add templateClaudeApi/GeminiApi/OpenaiApi keys to errorRules (5 locales)
- i18n: replace hardcoded API names in override-section with t() calls
- Add codex desktop alias matching tests for detectClientFull
- Improve error logging in edit-key-form provider group fetch
- Remove default parameter value from data-table actions column title

* refactor: move effort badge from table to request detail dialog

Move the Anthropic effort badge display from the usage logs table
(both admin and my-usage) into the SummaryTab's Session Info section
within the ErrorDetailsDialog. This declutters the table view and
provides richer context by showing override information (original vs
overridden effort) when a provider parameter override changes the
effort value.

- Add extractAnthropicEffortInfo utility combining anthropic_effort
  and provider_parameter_override special settings
- Display effort badge(s) in SummaryTab with override arrow notation
- Remove effort badge from ModelDisplayWithRedirect, both usage tables
- Add i18n keys (effort.label, effort.overridden) for all 5 languages
- Add 11 table-driven unit tests covering all branches

* fix: return proper object type in updateRequestCostFromUsage (#914)

Fixed TypeScript error where bare 'return;' returned undefined instead
of the expected object type with costUsd, resolvedPricing,
longContextPricing, and longContextPricingApplied properties.

Error: src/app/v1/_lib/proxy/response-handler.ts(3111,7): error TS2322:
Type 'undefined' is not assignable to type '{ costUsd: string | null;
resolvedPricing: ResolvedPricing | null; longContextPricing:
ResolvedLongContextPricing | null; longContextPricingApplied: boolean; }'.

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

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: return proper type in calculateAndUpdateRequestCost early exit (#915)

The early return when no price data is found was returning undefined
instead of the expected object type. Fixed to return consistent object
structure matching other early returns in the function.

Fixed:
- Type 'undefined' is not assignable to type return object in response-handler.ts:3111

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

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: miraserver <20286838+miraserver@users.noreply.github.com>
Co-authored-by: Night <lzy200816@gmail.com>
Co-authored-by: Hwwwww-dev <47653238+Hwwwww-dev@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:Anthropic area:i18n area:UI enhancement New feature or request size/M Medium PR (< 500 lines)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants