feat(usage): add anthropic effort tracking and display. #900#901
feat(usage): add anthropic effort tracking and display. #900#901ding113 merged 2 commits intoding113:devfrom
Conversation
| "noLogs": "ログがありません", | ||
| "unknownModel": "不明なモデル", | ||
| "billingModel": "課金: {model}" | ||
| "billingModel": "課金: {model}", |
There was a problem hiding this 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 patternmessages/ru/dashboard.json— same patternmessages/zh-CN/dashboard.json— same patternmessages/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.
📝 WalkthroughWalkthrough此PR为系统添加了Anthropic Effort指标支持,包括多语言翻译条目、数据模型扩展、UI组件、工具函数、特殊设置类型定义和数据库层映射。 Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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
📒 Files selected for processing (21)
messages/en/dashboard.jsonmessages/en/myUsage.jsonmessages/ja/dashboard.jsonmessages/ja/myUsage.jsonmessages/ru/dashboard.jsonmessages/ru/myUsage.jsonmessages/zh-CN/dashboard.jsonmessages/zh-CN/myUsage.jsonmessages/zh-TW/dashboard.jsonmessages/zh-TW/myUsage.jsonsrc/actions/my-usage.tssrc/app/[locale]/dashboard/logs/_components/model-display-with-redirect.tsxsrc/app/[locale]/dashboard/logs/_components/usage-logs-table.tsxsrc/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsxsrc/app/[locale]/my-usage/_components/usage-logs-table.tsxsrc/app/v1/_lib/proxy/message-service.tssrc/components/customs/anthropic-effort-badge.tsxsrc/lib/utils/anthropic-effort.tssrc/lib/utils/special-settings.tssrc/repository/usage-logs.tssrc/types/special-settings.ts
| "nonBilling": "非计费", | ||
| "skipped": "已跳过", | ||
| "specialSettings": "特殊设置", | ||
| "anthropicEffort": "Effort: {effort}", |
There was a problem hiding this comment.
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.
| "billingModel": "计费:{model}", | ||
| "anthropicEffort": "Effort: {effort}" |
There was a problem hiding this comment.
这里还没有真正完成本地化。
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'.
Summary of ChangesHello, 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 Highlights
Changelog
Activity
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
|
There was a problem hiding this comment.
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}", |
There was a problem hiding this comment.
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}.
| "anthropicEffort": "Effort: {effort}", | |
| "anthropicEffort": "エフォート: {effort}", |
| "unknownModel": "不明なモデル", | ||
| "billingModel": "課金: {model}" | ||
| "billingModel": "課金: {model}", | ||
| "anthropicEffort": "Effort: {effort}" |
There was a problem hiding this comment.
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}.
| "anthropicEffort": "Effort: {effort}" | |
| "anthropicEffort": "エフォート: {effort}" |
| "nonBilling": "Не тарифицируется", | ||
| "skipped": "Пропущено", | ||
| "specialSettings": "Особые", | ||
| "anthropicEffort": "Effort: {effort}", |
There was a problem hiding this comment.
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}.
| "anthropicEffort": "Effort: {effort}", | |
| "anthropicEffort": "Усилие: {effort}", |
| "unknownModel": "Неизвестная модель", | ||
| "billingModel": "Биллинг: {model}" | ||
| "billingModel": "Биллинг: {model}", | ||
| "anthropicEffort": "Effort: {effort}" |
There was a problem hiding this comment.
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}.
| "anthropicEffort": "Effort: {effort}" | |
| "anthropicEffort": "Усилие: {effort}" |
| "nonBilling": "非计费", | ||
| "skipped": "已跳过", | ||
| "specialSettings": "特殊设置", | ||
| "anthropicEffort": "Effort: {effort}", |
There was a problem hiding this comment.
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}".
| "anthropicEffort": "Effort: {effort}", | |
| "anthropicEffort": "算力: {effort}", |
| "unknownModel": "未知模型", | ||
| "billingModel": "计费:{model}" | ||
| "billingModel": "计费:{model}", | ||
| "anthropicEffort": "Effort: {effort}" |
There was a problem hiding this comment.
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}".
| "anthropicEffort": "Effort: {effort}" | |
| "anthropicEffort": "算力: {effort}" |
| "nonBilling": "非計費", | ||
| "skipped": "已跳過", | ||
| "specialSettings": "特殊設定", | ||
| "anthropicEffort": "Effort: {effort}", |
There was a problem hiding this comment.
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}".
| "anthropicEffort": "Effort: {effort}", | |
| "anthropicEffort": "算力: {effort}", |
| "unknownModel": "未知的模型", | ||
| "billingModel": "計費:{model}" | ||
| "billingModel": "計費:{model}", | ||
| "anthropicEffort": "Effort: {effort}" |
There was a problem hiding this comment.
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}".
| "anthropicEffort": "Effort: {effort}" | |
| "anthropicEffort": "算力: {effort}" |
* 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>
Summary
Add tracking and display of Anthropic's
effortparameter in usage logs. When requests includeoutput_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
output_config.effortfrom request bodies for Anthropic providersanthropic_effortspecial setting typeChanges
Core Changes
AnthropicEffortSpecialSettingtype tosrc/types/special-settings.tsextractAnthropicEffortFromRequestBody()utility insrc/lib/utils/anthropic-effort.tsextractAnthropicEffortFromSpecialSettings()for retrievalProxyMessageServicefor Anthropic providersanthropicEffortfield to usage log data structuresUI Changes
AnthropicEffortBadgecomponent with effort-level-specific styling:auto- sky/cyan gradientlow- slatemedium- amberhigh- rosemax- redModelDisplayWithRedirectto show effort badgei18n
anthropicEffortkey to all 5 languages (en, ja, ru, zh-CN, zh-TW)Screenshots
Checklist
Description enhanced by Claude AI
Greptile Summary
This PR adds end-to-end tracking and display of the Anthropic
output_config.effortrequest parameter, surfacing it as a colour-coded badge in both the admin dashboard logs table and the user's personal usage view.Key changes:
AnthropicEffortSpecialSettingtype added to theSpecialSettingunion for audit/display purposes.extractAnthropicEffortFromRequestBody,extractAnthropicEffortFromSpecialSettings) safely extract effort from the raw request body and from persisted special settings with proper type guards.claude/claude-auth), with an idempotency guard to avoid duplicate entries on retry.findUsageLogsBatch,findUsageLogsForKeySlim,findUsageLogsWithDetails) derivesanthropicEffortfrom the unified special settings on every query path.AnthropicEffortBadgecomponent renders per-level colour coding (auto/low/medium/high/max) with a neutral default for unrecognised values."Effort: {effort}") untranslated, unlike the already-translatedbillingModelsibling key.Confidence Score: 4/5
billingModelkey), and the ledger-fallback path infindUsageLogsBatchomits an explicitanthropicEffort: nullassignment (safe due to optional typing but asymmetric).messages/ja,messages/ru,messages/zh-CN,messages/zh-TW) for the untranslated label, and the ledger fallback block insrc/repository/usage-logs.ts.Important Files Changed
AnthropicEffortSpecialSettingtype to theSpecialSettingunion; well-documented with JSDoc comment following the existing pattern.extractAnthropicEffortFromRequestBodysafely navigatesoutput_config.effortwith proper type guards, andextractAnthropicEffortFromSpecialSettingsiterates the settings array — both are well-guarded and clean.output_config.effortfrom the request body for Anthropic providers and records it as a special setting; the idempotency guard (!hasAnthropicEffortAudit) correctly prevents duplicate entries on retry.anthropicEffortextraction to three query paths (batch cursor, slim for key, and with-details); the ledger fallback infindUsageLogsBatchomitsanthropicEfforton returned rows (handled safely via the optional field, but inconsistent).anthropicEfforttoMyUsageLogEntryand passes it through from the slim row; straightforward addition with no issues.anthropicEffortkey but leaves the value untranslated ("Effort: {effort}"), inconsistent with howbillingModelis 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" })Comments Outside Diff (1)
src/repository/usage-logs.ts, line 388-389 (link)Missing
anthropicEffortin ledger fallback path offindUsageLogsBatchIn the ledger fallback path (lines ~349–390, building
fallbackLogsfromusageLedger), theanthropicEffortfield is never set on the returnedUsageLogRowobjects. SinceanthropicEffortis declared as optional (anthropicEffort?: string | null) onUsageLogRow, TypeScript will not flag this, and UI components handleundefinedas falsy — so no crash occurs. However, the omission is asymmetric with the non-fallback path whereanthropicEffortis always populated.For consistency and future-proofing, consider explicitly setting
anthropicEffort: nullinfallbackLogs:Prompt To Fix With AI
Last reviewed commit: e13f968