Skip to content

feat(logs): make cost column toggleable with improved type safety#715

Merged
ding113 merged 6 commits intoding113:devfrom
Lynricsy:main
Feb 3, 2026
Merged

feat(logs): make cost column toggleable with improved type safety#715
ding113 merged 6 commits intoding113:devfrom
Lynricsy:main

Conversation

@Lynricsy
Copy link
Contributor

@Lynricsy Lynricsy commented Feb 3, 2026

Summary

  • Add cost column to visibility toggle settings, allowing users to show/hide the cost column in logs table
  • Consolidate duplicate type definitions to prevent type drift between components
  • Improve test coverage for column visibility toggle functionality

Problem

Related Issues:

Solution

Move the cost column from ALWAYS_VISIBLE_COLUMNS to DEFAULT_VISIBLE_COLUMNS, making it toggleable while keeping it visible by default. This provides flexibility without changing the default UI for most users.

Changes

Features

  • Cost column is now toggleable via column visibility dropdown (previously always visible)
  • Added cost to LogsTableColumn type and DEFAULT_VISIBLE_COLUMNS

Refactoring

  • Removed duplicate VirtualizedLogsTableColumn type definition
  • Reuse shared LogsTableColumn type from column-visibility.ts to ensure type consistency

Tests

  • Added assertion that DEFAULT_VISIBLE_COLUMNS contains cost
  • Added toggleColumn('cost') test to verify toggle functionality works correctly

Files Changed

File Change
src/lib/column-visibility.ts Added cost to type and default columns; removed from always-visible columns
src/lib/column-visibility.test.ts Added cost column test coverage
src/app/[locale]/dashboard/logs/_components/column-visibility-dropdown.tsx Added cost label to dropdown
src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsx Consolidated type, added conditional rendering

Verification

  • TypeScript type check passes
  • All 18 column-visibility tests pass
  • Full test suite passes (1802 tests)
  • Production build succeeds
  • i18n key logs.columns.cost exists in all 5 locales

Description enhanced by Claude AI

Greptile Overview

Greptile Summary

This PR successfully implements toggleable visibility for the cost column in logs tables, addressing user needs for flat-rate subscriptions where cost is always zero.

Key changes:

  • Moved cost from ALWAYS_VISIBLE_COLUMNS to DEFAULT_VISIBLE_COLUMNS, making it toggleable while keeping it visible by default
  • Consolidated duplicate VirtualizedLogsTableColumn type definition, now using shared LogsTableColumn type from column-visibility.ts
  • Added conditional rendering logic for cost column header and cells in virtualized-logs-table.tsx
  • Improved null checks for costUsd from truthy check to explicit null check (!= null), correctly handling zero-cost scenarios
  • Added comprehensive test coverage including cost column toggle tests
  • Updated i18n mappings in column-visibility-dropdown.tsx

Quality improvements:

  • Type consolidation prevents type drift between components
  • The log.costUsd != null check in both table components is a bug fix that correctly displays zero costs instead of treating them as falsy
  • Test coverage is thorough with dedicated cost column toggle tests

The implementation is clean, well-tested, and maintains backward compatibility by keeping cost visible by default.

Confidence Score: 5/5

  • This PR is safe to merge with no identified issues
  • All changes are well-implemented with proper type safety, comprehensive test coverage, and backward compatibility. The refactoring consolidates duplicate types and improves null handling.
  • No files require special attention

Important Files Changed

Filename Overview
src/lib/column-visibility.ts Added cost to LogsTableColumn type and DEFAULT_VISIBLE_COLUMNS, removed from ALWAYS_VISIBLE_COLUMNS - clean implementation
src/lib/column-visibility.test.ts Added comprehensive test coverage for cost column toggle functionality
src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsx Removed duplicate type definition, added conditional rendering for cost column, improved cost check from truthy to null check
src/app/[locale]/dashboard/logs/_components/usage-logs-table.tsx Improved null check for costUsd from truthy to explicit null check (handles zero cost correctly)

Sequence Diagram

sequenceDiagram
    participant User
    participant Dropdown as ColumnVisibilityDropdown
    participant Storage as localStorage
    participant Table as VirtualizedLogsTable
    
    User->>Dropdown: Click column visibility button
    Dropdown->>Storage: getHiddenColumns(userId, tableId)
    Storage-->>Dropdown: Return hidden columns array
    
    User->>Dropdown: Toggle "cost" column
    Dropdown->>Dropdown: Update hiddenColumns state
    Dropdown->>Storage: setHiddenColumns(userId, tableId, newHidden)
    Storage-->>Storage: Save to localStorage
    Dropdown->>Table: onVisibilityChange(newHidden)
    Table->>Table: Update hideCostColumn flag
    Table->>Table: Re-render with cost column hidden/shown
    
    Note over Table: Cost column conditionally rendered<br/>based on hiddenColumns prop
    
    User->>Dropdown: Click reset button
    Dropdown->>Storage: setHiddenColumns(userId, tableId, [])
    Storage-->>Storage: Remove from localStorage
    Dropdown->>Table: onVisibilityChange([])
    Table->>Table: Show all columns (default state)
Loading

(2/5) Greptile learns from your feedback when you react with thumbs up/down!

github-actions bot and others added 5 commits February 3, 2026 03:23
…st coverage

- Remove duplicate VirtualizedLogsTableColumn type, reuse LogsTableColumn from column-visibility.ts
- Add toggleColumn cost column visibility test to ensure proper toggle functionality

Co-authored-by: Wine Fox <fox@ling.plus>
Copilot AI review requested due to automatic review settings February 3, 2026 11:35
@coderabbitai
Copy link

coderabbitai bot commented Feb 3, 2026

📝 Walkthrough

Walkthrough

将“cost”作为可切换的日志列引入:更新列可见性类型与默认配置,调整虚拟化表格与使用日志表的渲染与工具提示,添加相关单元测试;同时更新 .gitignore 并新增 v0.5.3 的 CHANGELOG 条目(文档性修改)。

Changes

Cohort / File(s) Summary
列可见性基础设施
src/lib/column-visibility.ts, src/lib/column-visibility.test.ts
"cost" 添加到 LogsTableColumn 联合类型并加入 DEFAULT_VISIBLE_COLUMNS(不再位于 ALWAYS_VISIBLE_COLUMNS);增加测试覆盖列显示/隐藏的切换行为。
日志表格 UI 组件
src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsx, src/app/[locale]/dashboard/logs/_components/column-visibility-dropdown.tsx, src/app/[locale]/dashboard/logs/_components/usage-logs-table.tsx
hiddenColumns 类型调整为 LogsTableColumn[];引入基于隐藏列表的 cost 列显示控制;cost 单元格及表头按可见性条件渲染,调整 cost 的显示逻辑(包含货币格式、tooltip、1M 徽章),并在列标签映射中添加 cost 键。
配置和文档
.gitignore, CHANGELOG.md
新增 .ace-tool/.gitignore;为 v0.5.3 添加详尽的 CHANGELOG 条目(新增/优化/修复/其他)。

估计代码审查工作量

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Fix/logs provider badge overflow #581: 修改了日志表组件中与 cost/列布局相关的渲染逻辑,与本次变更在同一文件集(virtualized-logs-table.tsx、usage-logs-table.tsx 等)存在代码层面关联。

概述

本次提交为日志仪表板引入了新的"成本"列,包括列可见性切换、类型定义更新、UI 组件逻辑和测试覆盖。更新了类型签名、日志表格渲染,并添加了相关的配置和文档。

变更内容

分组 / 文件 摘要
列可见性基础设施
src/lib/column-visibility.ts, src/lib/column-visibility.test.ts
将"cost"添加到 LogsTableColumn 类型联合中;将其包含在 DEFAULT_VISIBLE_COLUMNS 数组中,使其默认可见;从 ALWAYS_VISIBLE_COLUMNS 中移除;添加测试用例验证"cost"列的切换和可见列行为。
日志表格 UI 组件
src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsx, src/app/[locale]/dashboard/logs/_components/column-visibility-dropdown.tsx, src/app/[locale]/dashboard/logs/_components/usage-logs-table.tsx
更新 VirtualizedLogsTableProps 的 hiddenColumns 属性接收 LogsTableColumn[];实现"cost"列的条件渲染,包括成本格式化、1M 徽章显示和上下文工具提示;为列标签映射添加"cost"条目。
配置和文档
.gitignore, CHANGELOG.md
.ace-tool/ 添加到忽略列表;添加 v0.5.3 版本更新日志,包含新增、优化、修复和其他部分的详细条目。

估计代码审查工作量

🎯 3 (Moderate) | ⏱️ ~25 分钟

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly describes the main change: making the cost column toggleable with improved type safety, which aligns with the primary objective to allow users to show/hide the cost column.
Linked Issues check ✅ Passed The PR fully addresses issue #713 by making the cost column toggleable, allowing users with flat-rate subscriptions to hide the unnecessary cost column as requested.
Out of Scope Changes check ✅ Passed All changes are in scope: cost column toggling, type consolidation, test coverage additions, and a null-check fix for proper $0.00 display are all related to the linked issues.
Description check ✅ Passed 拉取请求描述详细说明了成本列的可切换功能、类型整合和测试覆盖改进,与实际变更完全相关。

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 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.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @Lynricsy, 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 to the logs table by allowing users to dynamically show or hide the 'cost' column, improving customization of the user interface. Concurrently, it refactors the codebase to eliminate redundant type definitions, leading to a more robust and maintainable type system. The changes are thoroughly validated with new test coverage, ensuring the reliability of the column visibility feature.

Highlights

  • Cost Column Toggle: The 'cost' column in the logs table can now be toggled on/off by users, providing more control over the displayed data.
  • Type Safety Improvement: Duplicate type definitions for log table columns have been removed and consolidated, enhancing type consistency and preventing potential type drift across components.
  • Enhanced Test Coverage: New test cases have been added to specifically verify the correct functionality of the 'cost' column visibility toggle and ensure DEFAULT_VISIBLE_COLUMNS includes 'cost'.
Changelog
  • .gitignore
    • Added .ace-tool/ to ignored files.
  • CHANGELOG.md
    • Updated with new entries for v0.5.3, including new features (read-only key access, Zeabur deployment, Anthropic parameter override), optimizations (proxy architecture refactor, Thinking Budget rectifier), bug fixes (Gemini proxy URL, SSE usageMetadata), and other updates (Thinking Budget unit tests, i18n).
  • src/app/[locale]/dashboard/logs/_components/column-visibility-dropdown.tsx
    • Added 'cost' to COLUMN_LABEL_KEYS to enable localization for the cost column in the visibility dropdown.
  • src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsx
    • Imported the shared LogsTableColumn type.
    • Removed the previously duplicated VirtualizedLogsTableColumn type definition.
    • Updated the hiddenColumns prop to use the consolidated LogsTableColumn type.
    • Implemented conditional rendering for the 'cost' column header and its data cells, allowing it to be hidden based on user preferences.
  • src/lib/column-visibility.test.ts
    • Added a new test case to verify the toggleColumn function correctly hides and shows the 'cost' column.
    • Included an assertion to confirm that DEFAULT_VISIBLE_COLUMNS array correctly contains 'cost'.
  • src/lib/column-visibility.ts
    • Extended the LogsTableColumn type to include 'cost'.
    • Added 'cost' to the DEFAULT_VISIBLE_COLUMNS array.
    • Removed 'cost' from the ALWAYS_VISIBLE_COLUMNS array, making it toggleable.
Activity
  • No specific activity (comments, reviews, etc.) has been recorded for this pull request yet.
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 successfully makes the 'cost' column in the logs table toggleable, which is a great enhancement for user customization. The refactoring to consolidate duplicated type definitions into a single source of truth significantly improves type safety and maintainability. Additionally, the new tests for the column visibility functionality ensure the changes are well-covered. I have one suggestion to further improve code maintainability by reducing some repetitive logic.

@github-actions github-actions bot added the size/XS Extra Small PR (< 50 lines) label Feb 3, 2026
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 PR successfully implements cost column toggleability with improved type safety. The changes are clean, well-tested, and follow project conventions.

PR Size: XS

  • Lines changed: 150 (95 additions + 55 deletions)
  • Files changed: 6

Issues Found

Category Critical High Medium Low
Logic/Bugs 0 0 0 0
Security 0 0 0 0
Error Handling 0 0 0 0
Types 0 0 0 0
Comments/Docs 0 0 0 0
Tests 0 0 0 0
Simplification 0 0 0 0

Review Coverage

  • Logic and correctness - Clean
  • Security (OWASP Top 10) - Clean
  • Error handling - Clean
  • Type safety - Clean
  • Documentation accuracy - Clean
  • Test coverage - Adequate
  • Code clarity - Good

Key Improvements in This PR

  1. Type Safety: Removed duplicate VirtualizedLogsTableColumn type definition, now reuses shared LogsTableColumn type to prevent type drift
  2. Feature Completeness: Cost column moved from ALWAYS_VISIBLE_COLUMNS to toggleable columns, following same pattern as other columns
  3. Test Coverage: Added comprehensive tests for cost column toggle functionality
  4. i18n Compliance: Verified logs.columns.cost key exists in all 5 supported locales

The refactoring to consolidate duplicate types is particularly valuable for long-term maintainability.


Automated review by Claude AI

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 PR successfully implements cost column toggleability with improved type safety. The changes are clean, well-tested, and follow project conventions.

PR Size: XS

  • Lines changed: 150 (95 additions + 55 deletions)
  • Files changed: 6

Issues Found

Category Critical High Medium Low
Logic/Bugs 0 0 0 0
Security 0 0 0 0
Error Handling 0 0 0 0
Types 0 0 0 0
Comments/Docs 0 0 0 0
Tests 0 0 0 0
Simplification 0 0 0 0

Review Coverage

  • Logic and correctness - Clean
  • Security (OWASP Top 10) - Clean
  • Error handling - Clean
  • Type safety - Clean
  • Documentation accuracy - Clean
  • Test coverage - Adequate
  • Code clarity - Good

Key Improvements in This PR

  1. Type Safety: Removed duplicate VirtualizedLogsTableColumn type definition, now reuses shared LogsTableColumn type to prevent type drift
  2. Feature Completeness: Cost column moved from ALWAYS_VISIBLE_COLUMNS to toggleable columns, following same pattern as other columns
  3. Test Coverage: Added comprehensive tests for cost column toggle functionality
  4. i18n Compliance: Verified logs.columns.cost key exists in all 5 supported locales

The refactoring to consolidate duplicate types is particularly valuable for long-term maintainability.


Automated review by Claude AI

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR makes the logs table cost column user-toggleable via the existing column-visibility system, improves type sharing across components, and updates tests and metadata accordingly.

Changes:

  • Extend LogsTableColumn and DEFAULT_VISIBLE_COLUMNS to include "cost" and adjust ALWAYS_VISIBLE_COLUMNS so cost is no longer classified as always-visible.
  • Update the virtualized logs table and column-visibility dropdown to use the shared LogsTableColumn type and to conditionally render the cost column based on hiddenColumns.
  • Add unit tests for cost visibility behavior in the column-visibility utilities, and update CHANGELOG and .gitignore.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/lib/column-visibility.ts Adds "cost" to the LogsTableColumn union and DEFAULT_VISIBLE_COLUMNS, and updates ALWAYS_VISIBLE_COLUMNS so cost is no longer treated as always visible, enabling persistence of the cost column’s visibility.
src/lib/column-visibility.test.ts Extends tests to assert that DEFAULT_VISIBLE_COLUMNS includes "cost" and that toggleColumn correctly hides/shows "cost" and updates visible columns.
src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsx Replaces the local VirtualizedLogsTableColumn type with the shared LogsTableColumn, derives a hideCostColumn flag from hiddenColumns, and conditionally renders both the header and body cost column segments.
src/app/[locale]/dashboard/logs/_components/column-visibility-dropdown.tsx Adds a label key mapping for the cost column so it appears in the column-visibility dropdown and can be toggled.
src/app/[locale]/dashboard/logs/_components/usage-logs-view-virtualized.tsx Wires the ColumnVisibilityDropdown’s hiddenColumns into VirtualizedLogsTable, allowing cost (and other columns) to be hidden in the full-screen virtualized logs view.
CHANGELOG.md Adds a new v0.5.3 release section summarizing unrelated feature, optimization, and bugfix work for the upcoming release.
.gitignore Ignores the .ace-tool/ directory to avoid committing local tooling artifacts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 609 to 655
{/* Cost */}
<div className="flex-[0.7] min-w-[60px] text-right font-mono text-xs px-1.5">
{isNonBilling ? (
"-"
) : log.costUsd ? (
<TooltipProvider>
<Tooltip delayDuration={250}>
<TooltipTrigger asChild>
<span className="cursor-help inline-flex items-center gap-1">
{formatCurrency(log.costUsd, currencyCode, 6)}
{hideCostColumn ? null : (
<div className="flex-[0.7] min-w-[60px] text-right font-mono text-xs px-1.5">
{isNonBilling ? (
"-"
) : log.costUsd ? (
<TooltipProvider>
<Tooltip delayDuration={250}>
<TooltipTrigger asChild>
<span className="cursor-help inline-flex items-center gap-1">
{formatCurrency(log.costUsd, currencyCode, 6)}
{log.context1mApplied && (
<Badge
variant="outline"
className="text-[10px] leading-tight px-1 bg-purple-50 text-purple-700 border-purple-200 dark:bg-purple-950/30 dark:text-purple-300 dark:border-purple-800"
>
1M
</Badge>
)}
</span>
</TooltipTrigger>
<TooltipContent
align="end"
className="text-xs space-y-1 max-w-[300px]"
>
{log.context1mApplied && (
<Badge
variant="outline"
className="text-[10px] leading-tight px-1 bg-purple-50 text-purple-700 border-purple-200 dark:bg-purple-950/30 dark:text-purple-300 dark:border-purple-800"
>
1M
</Badge>
<div className="text-purple-600 dark:text-purple-400 font-medium">
{t("logs.billingDetails.context1m")}
</div>
)}
</span>
</TooltipTrigger>
<TooltipContent align="end" className="text-xs space-y-1 max-w-[300px]">
{log.context1mApplied && (
<div className="text-purple-600 dark:text-purple-400 font-medium">
{t("logs.billingDetails.context1m")}
<div>
{t("logs.billingDetails.input")}:{" "}
{formatTokenAmount(log.inputTokens)} tokens
</div>
)}
<div>
{t("logs.billingDetails.input")}:{" "}
{formatTokenAmount(log.inputTokens)} tokens
</div>
<div>
{t("logs.billingDetails.output")}:{" "}
{formatTokenAmount(log.outputTokens)} tokens
</div>
</TooltipContent>
</Tooltip>
</TooltipProvider>
) : (
"-"
)}
</div>
<div>
{t("logs.billingDetails.output")}:{" "}
{formatTokenAmount(log.outputTokens)} tokens
</div>
</TooltipContent>
</Tooltip>
</TooltipProvider>
) : (
"-"
)}
</div>
)}

Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The new hideCostColumn conditional render path isn’t covered by tests, even though similar column-visibility behavior for provider is explicitly tested in virtualized-logs-table.test.tsx. To avoid regressions (e.g., the cost column accidentally becoming always visible again), consider adding tests that verify the cost header and body cells are hidden/shown appropriately when hiddenColumns includes/excludes "cost".

Copilot uses AI. Check for mistakes.
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

🤖 Fix all issues with AI agents
In `@src/app/`[locale]/dashboard/logs/_components/virtualized-logs-table.tsx:
- Around line 612-615: The current rendering uses a truthy check on log.costUsd
which treats 0 as missing and renders "-"; update the conditional in the
virtualized-logs-table component so it checks explicitly for null/undefined
(e.g., use log.costUsd == null) instead of a truthy test before rendering the
TooltipProvider branch; touch the isNonBilling branch and the expression that
reads log.costUsd so zero values are rendered correctly.
- Around line 621-646: Replace the hardcoded "1M" badge label and the literal
"tokens" suffixes with i18n keys: update the Badge content to use
t("logs.billingDetails.context1m") or a new key like
t("logs.billingDetails.context1mLabel") and replace the "tokens" text in the
TooltipContent lines with t("logs.billingDetails.tokens") so the strings for the
badge and the token unit are localized for zh-CN/zh-TW/en/ja/ru; ensure you call
the same i18n function used in this file (t) and keep the numeric values
produced by formatTokenAmount(log.inputTokens) and
formatTokenAmount(log.outputTokens) unchanged.

Comment on lines +621 to +646
<Badge
variant="outline"
className="text-[10px] leading-tight px-1 bg-purple-50 text-purple-700 border-purple-200 dark:bg-purple-950/30 dark:text-purple-300 dark:border-purple-800"
>
1M
</Badge>
)}
</span>
</TooltipTrigger>
<TooltipContent
align="end"
className="text-xs space-y-1 max-w-[300px]"
>
{log.context1mApplied && (
<Badge
variant="outline"
className="text-[10px] leading-tight px-1 bg-purple-50 text-purple-700 border-purple-200 dark:bg-purple-950/30 dark:text-purple-300 dark:border-purple-800"
>
1M
</Badge>
<div className="text-purple-600 dark:text-purple-400 font-medium">
{t("logs.billingDetails.context1m")}
</div>
)}
</span>
</TooltipTrigger>
<TooltipContent align="end" className="text-xs space-y-1 max-w-[300px]">
{log.context1mApplied && (
<div className="text-purple-600 dark:text-purple-400 font-medium">
{t("logs.billingDetails.context1m")}
<div>
{t("logs.billingDetails.input")}:{" "}
{formatTokenAmount(log.inputTokens)} tokens
</div>
)}
<div>
{t("logs.billingDetails.input")}:{" "}
{formatTokenAmount(log.inputTokens)} tokens
</div>
<div>
{t("logs.billingDetails.output")}:{" "}
{formatTokenAmount(log.outputTokens)} tokens
</div>
</TooltipContent>
</Tooltip>
</TooltipProvider>
) : (
"-"
)}
</div>
<div>
{t("logs.billingDetails.output")}:{" "}
{formatTokenAmount(log.outputTokens)} tokens
</div>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

将成本提示中的 "1M" 与 "tokens" 文案接入 i18n。

当前为硬编码字符串,需改为翻译键并补齐各语言文案。

建议修改
-                                      1M
+                                      {t("logs.billingDetails.context1mShort")}
...
-                                  {formatTokenAmount(log.inputTokens)} tokens
+                                  {formatTokenAmount(log.inputTokens)} {t("logs.billingDetails.tokensUnit")}
...
-                                  {formatTokenAmount(log.outputTokens)} tokens
+                                  {formatTokenAmount(log.outputTokens)} {t("logs.billingDetails.tokensUnit")}
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
In `@src/app/`[locale]/dashboard/logs/_components/virtualized-logs-table.tsx
around lines 621 - 646, Replace the hardcoded "1M" badge label and the literal
"tokens" suffixes with i18n keys: update the Badge content to use
t("logs.billingDetails.context1m") or a new key like
t("logs.billingDetails.context1mLabel") and replace the "tokens" text in the
TooltipContent lines with t("logs.billingDetails.tokens") so the strings for the
badge and the token unit are localized for zh-CN/zh-TW/en/ja/ru; ensure you call
the same i18n function used in this file (t) and keep the numeric values
produced by formatTokenAmount(log.inputTokens) and
formatTokenAmount(log.outputTokens) unchanged.

Change costUsd falsy check to null check so \$0.00 displays properly
instead of showing "-" for legitimate zero-cost requests.

Co-authored-by: Wine Fox <fox@ling.plus>
@ding113 ding113 merged commit 4735d62 into ding113:dev Feb 3, 2026
8 checks passed
@github-project-automation github-project-automation bot moved this from Backlog to Done in Claude Code Hub Roadmap Feb 3, 2026
@github-actions github-actions bot mentioned this pull request Feb 7, 2026
10 tasks
ding113 added a commit that referenced this pull request Feb 7, 2026
* fix(proxy): add 'cannot be modified' error detection to thinking signature rectifier

Extend the thinking signature rectifier to detect and handle the
Anthropic API error when thinking/redacted_thinking blocks have been
modified from their original response. This error occurs when clients
inadvertently modify these blocks in multi-turn conversations.

The rectifier will now remove these blocks and retry the request,
similar to how it handles other thinking-related signature errors.

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

* chore(deps): bump jspdf in the npm_and_yarn group across 1 directory

Bumps the npm_and_yarn group with 1 update in the / directory: [jspdf](https://github.com/parallax/jsPDF).


Updates `jspdf` from 3.0.4 to 4.1.0
- [Release notes](https://github.com/parallax/jsPDF/releases)
- [Changelog](https://github.com/parallax/jsPDF/blob/master/RELEASE.md)
- [Commits](parallax/jsPDF@v3.0.4...v4.1.0)

---
updated-dependencies:
- dependency-name: jspdf
  dependency-version: 4.1.0
  dependency-type: direct:production
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix: Hot-reload cache invalidation for Request Filters and Sensitive Words (#710)

* fix: hot-reload request filters via globalThis singleton pattern

EventEmitter and RequestFilterEngine now use globalThis caching to ensure
the same instance is shared across different Next.js worker contexts.
This fixes the issue where filter changes required Docker restart.

Added diagnostic logging for event subscription and propagation.

* fix(redis): wait for subscriber connection ready before subscribe

- ensureSubscriber now returns Promise<Redis>, waits for 'ready' event
- subscribeCacheInvalidation returns null on failure instead of noop
- RequestFilterEngine checks cleanup !== null before logging success
- Fixes false "Subscribed" log when Redis connection fails

* feat(sensitive-words): add hot-reload via Redis pub/sub

Enable real-time cache invalidation for sensitive words detector,
matching the pattern used by request-filter-engine and error-rule-detector.

* fix(redis): harden cache invalidation subscriptions

Ensure sensitive-words CRUD emits update events so hot-reload propagates across workers. Roll back failed pub/sub subscriptions, add retry/timeout coverage, and avoid sticky provider-cache subscription state.

* fix(codex): bump default User-Agent fallback

Update the hardcoded Codex UA used when requests lack an effective user-agent (e.g. filtered out). Keep unit tests in sync with the new default.

* fix(redis): resubscribe cache invalidation after reconnect

Clear cached subscription state on disconnect and resubscribe on ready so cross-worker cache invalidation survives transient Redis reconnects. Add unit coverage, avoid misleading publish logs, track detector cleanup handlers, and translate leftover Russian comments to English.

* fix(sensitive-words): use globalThis singleton detector

Align SensitiveWordDetector with existing __CCH_* singleton pattern to avoid duplicate instances across module reloads. Extend singleton unit tests to cover the detector.

* chore: format code (req-fix-dda97fd)

* fix: address PR review comments

- pubsub.ts: use `once` instead of `on` for ready event to prevent
  duplicate resubscription handlers on reconnect
- forwarder.ts: extract DEFAULT_CODEX_USER_AGENT constant
- provider-cache.ts: wrap subscribeCacheInvalidation in try/catch
- tests: use exported constant instead of hardcoded UA string

* fix(redis): resubscribe across repeated reconnects

Ensure pub/sub resubscribe runs on every reconnect, extend unit coverage, and keep emitRequestFiltersUpdated resilient when logger import fails.

---------

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

* feat(logs): make cost column toggleable with improved type safety (#715)

close #713

* fix(proxy): add OpenAI chat completion format support in usage extraction (#705) (#716)

The `extractUsageMetrics` function was missing support for OpenAI chat
completion format fields (`prompt_tokens`/`completion_tokens`), causing
token statistics to not be recorded for OpenAI-compatible providers.

Changes:
- Add `prompt_tokens` -> `input_tokens` mapping
- Add `completion_tokens` -> `output_tokens` mapping
- Preserve priority: Claude > Gemini > OpenAI format
- Add 5 unit tests for OpenAI format handling

Closes #705

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* fix(currency): respect system currencyDisplay setting in UI (#717)

Fixes #678 - Currency display unit configuration was not applied.

Root cause:
- `users-page-client.tsx` hardcoded `currencyCode="USD"`
- `UserLimitBadge` and `LimitStatusIndicator` had hardcoded `unit="$"` default
- `big-screen/page.tsx` used hardcoded "$" in multiple places

Changes:
- Add `getCurrencySymbol()` helper function to currency.ts
- Fetch system settings in `users-page-client.tsx` and pass to table
- Pass `currencySymbol` from `user-key-table-row.tsx` to limit badges
- Remove hardcoded "$" defaults from badge components
- Update big-screen page to fetch settings and use dynamic symbol
- Add unit tests for `getCurrencySymbol`

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* feat(gemini): add Google Search web access preference for Gemini providers (#721)

* feat(gemini): add Google Search web access preference for Gemini providers

Add provider-level preference for Gemini API type providers to control
Google Search (web access) tool injection:

- inherit: Follow client request (default)
- enabled: Force inject googleSearch tool into request
- disabled: Force remove googleSearch tool from request

Changes:
- Add geminiGoogleSearchPreference field to provider schema
- Add GeminiGoogleSearchPreference type and validation
- Implement applyGeminiGoogleSearchOverride with audit trail
- Add UI controls in provider form (Gemini Overrides section)
- Add i18n translations for 5 languages (en, zh-CN, zh-TW, ja, ru)
- Integrate override logic in proxy forwarder for Gemini requests
- Add 22 unit tests for the override logic

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

* fix(gemini): address code review feedback

- Use explicit else-if for disabled preference check (gemini-code-assist)
- Use i18n for SelectValue placeholder instead of hardcoded string (coderabbitai)
- Sync overridden body back to session.request.message for log consistency (coderabbitai)
- Persist Gemini special settings immediately, matching Anthropic pattern (coderabbitai)

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

* fix(gemini): use strict types for provider config and audit

- Narrow preference type to "enabled" | "disabled" (exclude unreachable "inherit")
- Use ProviderType and GeminiGoogleSearchPreference types instead of string

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

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* fix(api): 透传 /api/actions 认证会话以避免 getUsers 返回空数据 (#720)

* fix(api): 透传 /api/actions 认证会话以避免 getUsers 返回空数据

* fix(auth): 让 scoped session 继承 allowReadOnlyAccess 语义并支持内部降权校验

* chore: format code (dev-93585fa)

* fix: bound SessionTracker active_sessions zsets by env TTL (#718)

* fix(session): bound active_sessions zsets by env ttl

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(rate-limit): pass session ttl to lua cleanup

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(session): validate SESSION_TTL env and prevent ZSET leak on invalid values

- Add input validation for SESSION_TTL (reject NaN, 0, negative; default 300)
- Guard against invalid TTL in Lua script to prevent clearing all sessions
- Use dynamic EXPIRE based on SESSION_TTL instead of hardcoded 3600s
- Add unit tests for TTL validation and dynamic expiry behavior

---------

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(provider): stop standard-path fallback to legacy provider url

* feat(providers): expose vendor endpoint pools in settings UI (#719)

* feat(providers): add endpoint status mapping

* feat(providers): add endpoint pool hover

* feat(providers): show vendor endpoints in list rows

* feat(providers): extract vendor endpoint CRUD table

* chore(i18n): add provider endpoint UI strings

* fix(providers): integrate endpoint pool into provider form

* fix(provider): wrap endpoint sync in transactions to prevent race conditions (#730)

* fix(provider): wrap provider create/update endpoint sync in transactions

Provider create and update operations now run vendor resolution and
endpoint sync inside database transactions to prevent race conditions
that could leave orphaned or inconsistent endpoint rows.

Key changes:
- createProvider: wrap vendor + insert + endpoint seed in a single tx
- updateProvider: wrap vendor + update + endpoint sync in a single tx
- Add syncProviderEndpointOnProviderEdit for atomic URL/type/vendor
  migration with in-place update, soft-delete, and conflict handling
- Vendor cleanup failures degrade to warnings instead of propagating
- Add comprehensive unit and integration tests for sync edge cases

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

* fix(provider): defer endpoint circuit reset until transaction commit

Avoid running endpoint circuit reset side effects inside DB transactions to prevent rollback inconsistency. Run resets only after commit and add regression tests for deferred reset behavior in helper and provider update flows.

* fix(provider): distinguish noop from created-next in endpoint sync action label

When ensureNextEndpointActive() returns "noop" (concurrent transaction
already created an active next endpoint), the action was incorrectly
labelled "kept-previous-and-created-next". Add a new
"kept-previous-and-kept-next" action to ProviderEndpointSyncAction and
use a three-way branch so callers and logs reflect the true outcome.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address review comments from PR #731

- fix(auth): prevent scoped session access widening via ?? -> && guard
- fix(i18n): standardize zh-CN provider terminology to "服务商"
- fix(i18n): use consistent Russian translations for circuit status
- fix(i18n): replace raw formatDistanceToNow with locale-aware RelativeTime
- fix(gemini): log warning for unknown google search preference values
- fix(error-rules): check subscribeCacheInvalidation return value
- fix(test): correct endpoint hover sort test to assert URLs not labels

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: export auth session storage and fix test mock types

- Export authSessionStorage from auth-session-storage.node.ts to prevent
  undefined on named imports; remove duplicate declare global block
- Fix mockEndpoints in provider-endpoint-hover test: remove nonexistent
  lastOk/lastLatencyMs fields, add missing lastProbe* fields, use Date
  objects for createdAt/updatedAt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: miraserver <20286838+miraserver@users.noreply.github.com>
Co-authored-by: John Doe <johndoe@example.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: 泠音 <im@ling.plus>
Co-authored-by: Longlone <41830147+WAY29@users.noreply.github.com>
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:UI enhancement New feature or request size/XS Extra Small PR (< 50 lines)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants