diff --git a/.gitignore b/.gitignore index a4544510..e4798deb 100644 --- a/.gitignore +++ b/.gitignore @@ -91,3 +91,4 @@ docs-site/node_modules/ tmp/ .trae/ .sisyphus +.ace-tool/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b99ae02..11f488ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,31 @@ --- +## v0.5.3 (2026-02-03) + +### 新增 + +- 扩展只读密钥访问权限,支持更多 API 端点访问 (#704) [@AptS:1547](https://github.com/AptS1547) +- 支持 Zeabur 一键部署 (#679) [@h7ml](https://github.com/h7ml) +- Anthropic 供应商支持参数覆写功能,可自定义 API 请求参数 (#689) + +### 优化 + +- 重构代理架构,移除格式转换器并强制同格式路由,提升性能和稳定性 (#709) +- 优化 Thinking Budget 整流器,改进思考模式下的令牌预算管理 + +### 修复 + +- 修复 Gemini 供应商 buildProxyUrl 重复拼接版本前缀的问题 (#693) [@sunxyw](https://github.com/sunxyw) +- 修复 Gemini SSE 响应中 usageMetadata 提取逻辑,采用 last-wins 策略 (#691) [@sususu98](https://github.com/sususu98) + +### 其他 + +- 新增 Thinking Budget 整流器单元测试覆盖 +- 更新 i18n 翻译和系统配置 + +--- + ## [v0.5.2](https://github.com/ding113/claude-code-hub/releases/tag/v0.5.2) - 2026-01-29 ### 新增 diff --git a/src/app/[locale]/dashboard/logs/_components/column-visibility-dropdown.tsx b/src/app/[locale]/dashboard/logs/_components/column-visibility-dropdown.tsx index 2b26f8be..417e4f9e 100644 --- a/src/app/[locale]/dashboard/logs/_components/column-visibility-dropdown.tsx +++ b/src/app/[locale]/dashboard/logs/_components/column-visibility-dropdown.tsx @@ -33,6 +33,7 @@ const COLUMN_LABEL_KEYS: Record = { sessionId: "logs.columns.sessionId", provider: "logs.columns.provider", tokens: "logs.columns.tokens", + cost: "logs.columns.cost", cache: "logs.columns.cache", performance: "logs.columns.performance", }; diff --git a/src/app/[locale]/dashboard/logs/_components/usage-logs-table.tsx b/src/app/[locale]/dashboard/logs/_components/usage-logs-table.tsx index 39e986df..9b643ac8 100644 --- a/src/app/[locale]/dashboard/logs/_components/usage-logs-table.tsx +++ b/src/app/[locale]/dashboard/logs/_components/usage-logs-table.tsx @@ -361,7 +361,7 @@ export function UsageLogsTable({ ) : isNonBilling ? ( "-" - ) : log.costUsd ? ( + ) : log.costUsd != null ? ( diff --git a/src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsx b/src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsx index c1d82252..48e5ccfe 100644 --- a/src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsx +++ b/src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsx @@ -11,6 +11,7 @@ import { Button } from "@/components/ui/button"; import { RelativeTime } from "@/components/ui/relative-time"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; import { useVirtualizer } from "@/hooks/use-virtualizer"; +import type { LogsTableColumn } from "@/lib/column-visibility"; import { cn, formatTokenAmount } from "@/lib/utils"; import { copyTextToClipboard } from "@/lib/utils/clipboard"; import type { CurrencyCode } from "@/lib/utils/currency"; @@ -44,15 +45,6 @@ export interface VirtualizedLogsTableFilters { minRetryCount?: number; } -type VirtualizedLogsTableColumn = - | "user" - | "key" - | "sessionId" - | "provider" - | "tokens" - | "cache" - | "performance"; - interface VirtualizedLogsTableProps { filters: VirtualizedLogsTableFilters; currencyCode?: CurrencyCode; @@ -61,7 +53,7 @@ interface VirtualizedLogsTableProps { autoRefreshIntervalMs?: number; hideStatusBar?: boolean; hideScrollToTop?: boolean; - hiddenColumns?: VirtualizedLogsTableColumn[]; + hiddenColumns?: LogsTableColumn[]; bodyClassName?: string; } @@ -87,6 +79,7 @@ export function VirtualizedLogsTable({ const hideSessionIdColumn = hiddenColumns?.includes("sessionId") ?? false; const hideTokensColumn = hiddenColumns?.includes("tokens") ?? false; const hideCacheColumn = hiddenColumns?.includes("cache") ?? false; + const hideCostColumn = hiddenColumns?.includes("cost") ?? false; const hidePerformanceColumn = hiddenColumns?.includes("performance") ?? false; // Dialog state for model redirect click and chain item click @@ -273,12 +266,14 @@ export function VirtualizedLogsTable({ {t("logs.columns.cache")} )} -
- {t("logs.columns.cost")} -
+ {hideCostColumn ? null : ( +
+ {t("logs.columns.cost")} +
+ )} {hidePerformanceColumn ? null : (
- {isNonBilling ? ( - "-" - ) : log.costUsd ? ( - - - - - {formatCurrency(log.costUsd, currencyCode, 6)} + {hideCostColumn ? null : ( +
+ {isNonBilling ? ( + "-" + ) : log.costUsd != null ? ( + + + + + {formatCurrency(log.costUsd, currencyCode, 6)} + {log.context1mApplied && ( + + 1M + + )} + + + {log.context1mApplied && ( - - 1M - +
+ {t("logs.billingDetails.context1m")} +
)} - - - - {log.context1mApplied && ( -
- {t("logs.billingDetails.context1m")} +
+ {t("logs.billingDetails.input")}:{" "} + {formatTokenAmount(log.inputTokens)} tokens
- )} -
- {t("logs.billingDetails.input")}:{" "} - {formatTokenAmount(log.inputTokens)} tokens -
-
- {t("logs.billingDetails.output")}:{" "} - {formatTokenAmount(log.outputTokens)} tokens -
- - - - ) : ( - "-" - )} -
+
+ {t("logs.billingDetails.output")}:{" "} + {formatTokenAmount(log.outputTokens)} tokens +
+
+
+
+ ) : ( + "-" + )} +
+ )} {/* Performance */} {hidePerformanceColumn ? null : ( diff --git a/src/lib/column-visibility.test.ts b/src/lib/column-visibility.test.ts index 0deffda5..b27f64a8 100644 --- a/src/lib/column-visibility.test.ts +++ b/src/lib/column-visibility.test.ts @@ -179,6 +179,16 @@ describe("column-visibility", () => { const result3 = toggleColumn(userId, tableId, "user"); expect(result3).toEqual(["provider"]); }); + + test("toggles cost column visibility", () => { + const hiddenAfterToggle = toggleColumn(userId, tableId, "cost"); + expect(hiddenAfterToggle).toContain("cost"); + expect(getVisibleColumns(userId, tableId)).not.toContain("cost"); + + const visibleAfterToggleBack = toggleColumn(userId, tableId, "cost"); + expect(visibleAfterToggleBack).not.toContain("cost"); + expect(getVisibleColumns(userId, tableId)).toContain("cost"); + }); }); describe("resetColumns", () => { @@ -209,6 +219,7 @@ describe("column-visibility", () => { expect(DEFAULT_VISIBLE_COLUMNS).toContain("sessionId"); expect(DEFAULT_VISIBLE_COLUMNS).toContain("provider"); expect(DEFAULT_VISIBLE_COLUMNS).toContain("tokens"); + expect(DEFAULT_VISIBLE_COLUMNS).toContain("cost"); expect(DEFAULT_VISIBLE_COLUMNS).toContain("cache"); expect(DEFAULT_VISIBLE_COLUMNS).toContain("performance"); }); diff --git a/src/lib/column-visibility.ts b/src/lib/column-visibility.ts index ac8f2e6b..a854ec41 100644 --- a/src/lib/column-visibility.ts +++ b/src/lib/column-visibility.ts @@ -17,7 +17,8 @@ export type LogsTableColumn = | "provider" | "tokens" | "cache" - | "performance"; + | "performance" + | "cost"; /** * Default visible columns (all visible by default) @@ -30,12 +31,13 @@ export const DEFAULT_VISIBLE_COLUMNS: LogsTableColumn[] = [ "tokens", "cache", "performance", + "cost", ]; /** * Columns that cannot be hidden (always visible) */ -export const ALWAYS_VISIBLE_COLUMNS = ["time", "model", "cost", "status"] as const; +export const ALWAYS_VISIBLE_COLUMNS = ["time", "model", "status"] as const; /** * Get the storage key for a specific user and table