mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-08-04 11:43:57 +08:00
fix(usage): pricing routing, SSE lifecycle, and validation hardening
* model pricing routing: extend prefix-match families (gpt-/o1-o5/
gemini-/deepseek-/qwen-/glm-/kimi-/minimax-) with per-family dash
thresholds so short base IDs like gpt-5 no longer mis-match
gpt-5-mini; strip ISO and 8-digit date suffixes via UTF-8-safe
byte matching so claude-haiku-4-5-20251001 falls back to
claude-haiku-4-5 pricing
* SSE collector: SseUsageFinishGuard (RAII) guarantees finish() on
early return or panic; AtomicBool fast path lets push() skip the
Mutex once first-event time is recorded
* validation: shared validate_cost_multiplier / validate_pricing_source
helpers across DAO and service layers; PRICING_SOURCE_RESPONSE /
PRICING_SOURCE_REQUEST constants replace string literals; price
fields in update_model_pricing now reject empty / non-decimal /
negative input before INSERT
* backfill: add backfill_missing_usage_costs_for_model so a single
price edit only scans matching rows instead of the full log table;
startup backfill remains full-scan
* session_usage{,_codex,_gemini}: share find_model_pricing helper from
usage_stats; metadata_modified_nanos centralizes mtime precision
* frontend: NON_NEGATIVE_DECIMAL_REGEX + isNonNegativeDecimalString
replace three copies of the same multiplier regex; isUnpricedUsage
surfaces zero-cost rows that have usage tokens (cached per row to
avoid double evaluation); invalidate usageKeys.all on pricing mutate
so backfilled rows refresh
This commit is contained in:
@@ -6,7 +6,7 @@ import {
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { useRequestDetail } from "@/lib/query/usage";
|
||||
import { getFreshInputTokens } from "@/types/usage";
|
||||
import { getFreshInputTokens, isUnpricedUsage } from "@/types/usage";
|
||||
|
||||
interface RequestDetailPanelProps {
|
||||
requestId: string;
|
||||
@@ -53,6 +53,7 @@ export function RequestDetailPanel({
|
||||
|
||||
const freshInput = getFreshInputTokens(request);
|
||||
const isCacheInclusive = request.inputTokens !== freshInput;
|
||||
const unpriced = isUnpricedUsage(request);
|
||||
|
||||
return (
|
||||
<Dialog open onOpenChange={onClose}>
|
||||
@@ -255,8 +256,14 @@ export function RequestDetailPanel({
|
||||
</span>
|
||||
)}
|
||||
</dt>
|
||||
<dd className="text-lg font-semibold text-primary">
|
||||
${parseFloat(request.totalCostUsd).toFixed(6)}
|
||||
<dd
|
||||
className={`text-lg font-semibold ${
|
||||
unpriced ? "text-muted-foreground" : "text-primary"
|
||||
}`}
|
||||
>
|
||||
{unpriced
|
||||
? t("usage.unpriced", "未定价")
|
||||
: `$${parseFloat(request.totalCostUsd).toFixed(6)}`}
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
|
||||
Reference in New Issue
Block a user