@kenz1117/dsh-ui-usage-billing 1.5.1 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.en.md +1 -1
  2. package/README.md +1 -1
  3. package/lib/client.js +5 -5
  4. package/lib/index.js +728 -420
  5. package/lib/types/client/TokenPanel.d.ts +1 -1
  6. package/lib/types/client/UsageBilling.d.ts +7 -347
  7. package/lib/types/client/api/balance.d.ts +24 -0
  8. package/lib/types/client/api/pricing.d.ts +26 -0
  9. package/lib/types/client/api/relay.d.ts +13 -0
  10. package/lib/types/client/api/subscriptions.d.ts +13 -0
  11. package/lib/types/client/api/usage-stats.d.ts +11 -0
  12. package/lib/types/client/api/usage-tool.d.ts +16 -0
  13. package/lib/types/client/budget-store.d.ts +6 -0
  14. package/lib/types/client/constants.d.ts +28 -0
  15. package/lib/types/client/domain/forecast.d.ts +24 -0
  16. package/lib/types/client/domain/host-version.d.ts +18 -0
  17. package/lib/types/client/domain/icons.d.ts +9 -0
  18. package/lib/types/client/domain/kpi.d.ts +34 -0
  19. package/lib/types/client/domain/model-budget.d.ts +13 -0
  20. package/lib/types/client/domain/notify.d.ts +14 -0
  21. package/lib/types/client/domain/provider-aliases.d.ts +28 -0
  22. package/lib/types/client/domain/provider-merge.d.ts +26 -0
  23. package/lib/types/client/domain/recharge.d.ts +15 -0
  24. package/lib/types/client/domain/recost.d.ts +10 -0
  25. package/lib/types/client/domain/session-viewer.d.ts +13 -0
  26. package/lib/types/client/domain/streak.d.ts +25 -0
  27. package/lib/types/client/domain/subscription-vendors.d.ts +11 -0
  28. package/lib/types/client/domain/types.d.ts +312 -0
  29. package/lib/types/client/domain/week.d.ts +35 -0
  30. package/lib/types/client/locales.d.ts +1 -1
  31. package/lib/types/client/settings-search.d.ts +12 -0
  32. package/lib/types/config.d.ts +79 -0
  33. package/lib/types/guard.d.ts +49 -0
  34. package/lib/types/index.d.ts +3 -100
  35. package/lib/types/routes/balance.d.ts +37 -0
  36. package/lib/types/routes/notify-claim.d.ts +24 -0
  37. package/lib/types/routes/pricing.d.ts +26 -0
  38. package/lib/types/routes/relay-quotas.d.ts +27 -0
  39. package/lib/types/routes/subscriptions.d.ts +28 -0
  40. package/lib/types/routes/usage-stats.d.ts +44 -0
  41. package/lib/types/routes/usage-tool.d.ts +27 -0
  42. package/lib/types/silent.d.ts +21 -0
  43. package/package.json +14 -7
@@ -0,0 +1,14 @@
1
+ /**
2
+ * 跨实例提醒认领(issue #44):多实例(CLI + 桌面等)合法共存,各自轮询会
3
+ * 重复弹通知。两级去重——进程内 Set 挡同进程的并发/重渲染;跨进程走宿主
4
+ * 认领端点(先到先得),另一实例刚发过则跳过。端点不可达(旧版本/网络故障)
5
+ * 时放行,退化为原有 per-客户端去重。通知构造失败(平台限制)静默。
6
+ *
7
+ * Set 导出供测试重置(模块级状态会跨用例泄漏)。
8
+ */
9
+ export declare const notifiedKeys: Set<string>;
10
+ /** 浏览器通知可用且已授权;三处提醒发送前的同一前置判断。 */
11
+ export declare function notifyAllowed(): boolean;
12
+ /** 跨进程认领:另一实例已发则跳过;端点不可达放行。 */
13
+ export declare function notifyAcrossInstances(key: string, send: () => void): void;
14
+ //# sourceMappingURL=notify.d.ts.map
@@ -0,0 +1,28 @@
1
+ /**
2
+ * 厂商别名与匹配:PROVIDER_ALIASES 是中文厂商显示名 → 多英文/拼音别名
3
+ * 列表,反向查 `providerFromModelKey` 用作「目录未收录」模型的兜底厂商推断。
4
+ * 纯函数,无 React 依赖;导出供测试。
5
+ */
6
+ /**
7
+ * The dashboard's display names (中文厂商名) never equal the provider names a
8
+ * user actually configures (deepseek, zhipu, qwen…), so the dot match also
9
+ * accepts a bidirectional substring hit and a display-name alias list.
10
+ * 导出供一致性守卫测试:catalog 每个厂商都必须在此登记(Custom 除外),
11
+ * 防止新增厂商漏配导致健康绿灯不亮。
12
+ */
13
+ export declare const PROVIDER_ALIASES: Readonly<Record<string, readonly string[]>>;
14
+ /** Normalize a provider name for dot matching: lower case, no spaces. */
15
+ export declare function normalizeProvider(name: string): string;
16
+ /** Whether one normalized name is a substring of the other (length-guarded). */
17
+ export declare function providerNameHits(display: string, live: string): boolean;
18
+ /** Whether a catalog display name matches one live provider name. */
19
+ export declare function providerMatches(display: string, live: string): boolean;
20
+ /**
21
+ * 从真实 model id 反推提供方显示名:目录未收录的模型(key 落回「其他」)
22
+ * 只靠 entry.provider(Custom)永远点不亮健康灯,这里用厂商别名对 model id
23
+ * 做强匹配(别名作为完整 id / 前缀 / 独立段)与弱匹配(长别名子串),
24
+ * 命中即显示厂商名并点亮健康点;无命中保持 Custom。
25
+ * 导出供守卫测试:短别名(mi/yi)仅允许前缀形式,防止 minimax 等误吞。
26
+ */
27
+ export declare function providerFromModelKey(modelKey: string): string | undefined;
28
+ //# sourceMappingURL=provider-aliases.d.ts.map
@@ -0,0 +1,26 @@
1
+ /**
2
+ * 会话明细展示归组(issue #42 + 子智能体归并):同标题合并顶层行,再把子智能体
3
+ * 行(parentId 指向父会话)挂到最近存活的顶层组下(多级委派沿父链拍平到根
4
+ * 对话),挂靠目标命中合并组的任一段即可。父行不在切片内(服务端封顶或日志
5
+ * 已删)的子行回退为独立行,仍带子智能体徽标,不丢数据。
6
+ *
7
+ * `mergeSessionRows` 是 issue #42 的核心:fork/resume 派生的多段会话共用同一
8
+ * 标题但各自成行——同标题归并为一行作为一级(calls/cost 求和、lastActive 取 max、
9
+ * 任一子行 stale 即组 stale),各段明细收进 children 默认收起、点击展开。
10
+ */
11
+ import type { SessionBillingRow } from './types.ts';
12
+ /**
13
+ * 同标题会话合并:fork/resume 派生的多段会话共用同一标题但各自成行——同标题
14
+ * 归并为一行作为一级(calls/cost 求和、lastActive 取 max、任一子行 stale 即
15
+ * 组 stale),各段明细收进 children 默认收起、点击展开。无标题行保持独立。
16
+ * 输入必须已排除子智能体行(它们按 parentId 归位,不参与标题归并——子会话与
17
+ * 顶层会话撞标题时会错并)。费用倒序保持紧凑。
18
+ */
19
+ export declare function mergeSessionRows(rows: readonly SessionBillingRow[]): SessionBillingRow[];
20
+ /**
21
+ * 会话明细的展示归组:先同标题合并顶层行(issue #42),再把子智能体行
22
+ * (parentId 指向父会话)挂到最近存活的顶层组下(多级委派沿父链拍平到根
23
+ * 对话),挂靠目标命中合并组的任一段即可。
24
+ */
25
+ export declare function buildSessionDisplay(rows: readonly SessionBillingRow[]): SessionBillingRow[];
26
+ //# sourceMappingURL=provider-merge.d.ts.map
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 厂商官方充值页(issue #47):账单 Tab 余额列「充值」外链的映射表。
3
+ * key 为归一化 provider id(前缀匹配,`minimax-cn` 命中 `minimax`);
4
+ * 未收录厂商不渲染按钮(宁缺毋错链)。
5
+ *
6
+ * 多别名厂商共享的充值页常量(表内键去重引用,控制 bundle 体积)。
7
+ */
8
+ /**
9
+ * 余额 provider → 官方充值页 URL。匹配顺序:归一化名精确/前缀命中 →
10
+ * 经 PROVIDER_ALIASES 反查(余额 provider 名多为中文显示名,归一化仍是中文,
11
+ * 需先命中 display 名再用其英文别名重试)。未收录返回 undefined。
12
+ * 导出供测试:纯函数,不依赖组件。
13
+ */
14
+ export declare function rechargeUrlOf(provider: string): string | undefined;
15
+ //# sourceMappingURL=recharge.d.ts.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * 用户自定义单价显示重估:聚合发生在宿主进程(按内置目录计价),用户价只在
3
+ * 客户端显示层生效。对 byDayModels(day×model 完整二维)中命中用户价的模型
4
+ * 逐格平价重算 cost,并派生 byDay / byModel / total 的 cost。其余视图
5
+ * (bySite / byTier / bySession / byTurn)保持宿主原值——逐格时刻或行级归属
6
+ * 在客户端不可得,口径差异在设置面板注明。导出供测试:纯函数。
7
+ */
8
+ import type { UsageStats } from './types.ts';
9
+ export declare function recostWithUserPrices(stats: UsageStats): UsageStats;
10
+ //# sourceMappingURL=recost.d.ts.map
@@ -0,0 +1,13 @@
1
+ /**
2
+ * U-7 会话全屏查看器的会话过滤:按标题 / 项目路径 / 会话 id 做大小写不敏感
3
+ * 子串匹配。查询为空(或纯空白)返回全量。纯函数,导出供测试。
4
+ */
5
+ /** 会话行的最小形状(StatsBySession 行的超集兼容)。 */
6
+ interface SessionRowLike {
7
+ id: string;
8
+ title?: string;
9
+ cwd?: string;
10
+ }
11
+ export declare function filterSessionsForViewer<T extends SessionRowLike>(rows: readonly T[], query: string): readonly T[];
12
+ export {};
13
+ //# sourceMappingURL=session-viewer.d.ts.map
@@ -0,0 +1,25 @@
1
+ /**
2
+ * 按日活跃统计:活跃天数、连续使用天数、单日 token 口径。
3
+ * `dayTokensOf` 是全仓按日 Token 的统一口径(输入 + 输出,与 cacheHit/cacheMiss
4
+ * 互斥——stats.input 已含两者),趋势图 / 热力图 / 触发卡 / KPI 峰值日一律走它。
5
+ */
6
+ /** 近 7 天费用序列(含今天,缺日补 0):触发卡 hover 速览的迷你柱数据源。
7
+ * 导出供测试:纯函数(日期取本地时区)。 */
8
+ export declare function activeDaysOf(byDay: Record<string, {
9
+ cost: number;
10
+ }>): number;
11
+ /** 连续使用天数:从今天往前连续「有调用记录」的天数;今天无记录则为 0。
12
+ * 导出供测试:纯函数(日期取本地时区)。 */
13
+ export declare function streakDaysOf(byDay: Record<string, {
14
+ cost: number;
15
+ }>, now?: number): number;
16
+ /** 按日 Token 口径:输入 + 输出。stats.input 本身已含缓存命中与未命中
17
+ * (aggregate foldUsage:input = cacheHit + cacheMiss),再叠加缓存字段即重复
18
+ * 计数——趋势图/热力图/触发卡/峰值日的按日 Token 一律走本函数(issue #85);
19
+ * 跨日合计在各行之上累加(KPI 见 kpiAgg,触发卡见 month/weekTokens)。
20
+ * 导出供测试:纯函数。 */
21
+ export declare function dayTokensOf(day: {
22
+ input: number;
23
+ output: number;
24
+ }): number;
25
+ //# sourceMappingURL=streak.d.ts.map
@@ -0,0 +1,11 @@
1
+ /**
2
+ * 订阅套餐 provider id → 所属模型厂商:用于把订阅额度归并到对应厂商组。
3
+ * 厂商名与 PROVIDER_ALIASES 保持一致,使订阅卡片与模型用量落在同一组下。
4
+ * opencode 是跨厂商订阅通道、无单一模型厂商,按自身显示名独立成组。
5
+ */
6
+ export declare const SUBSCRIPTION_VENDORS: Readonly<Record<string, string>>;
7
+ /** 仅供测试:暴露厂商映射表(subscriptionVendorOf 仍是唯一消费入口)。 */
8
+ export declare const SUBSCRIPTION_VENDORS_FOR_TEST: Readonly<Record<string, string>>;
9
+ /** 订阅套餐归并到的厂商显示名;未知 id 回退为从 model id 反推或 id 本身。 */
10
+ export declare function subscriptionVendorOf(provider: string): string;
11
+ //# sourceMappingURL=subscription-vendors.d.ts.map
@@ -0,0 +1,312 @@
1
+ /**
2
+ * 客户端共享类型(无运行时副作用):UsageBilling.tsx 与各 domain/api/ 助手之间
3
+ * 的接口契约。`UsageStats` 是服务端聚合文档,100+ 字段按需扩展;本文件是
4
+ * 唯一权威定义点,不要在别处重复。
5
+ */
6
+ import type { CatalogModel } from '../pricing.ts';
7
+ import type { ClientPerf } from '../PerfPanel.tsx';
8
+ import type { ProviderBalance, SubscriptionQuota } from '../../pricing-shared.ts';
9
+ export type { ProviderBalance, RelayQuota, SubscriptionQuota } from '../../pricing-shared.ts';
10
+ /** Model-connectivity health reported by the host model directory probe. */
11
+ export interface ModelHealth {
12
+ /** Whether the probe completed (false while still loading). */
13
+ checked: boolean;
14
+ /** True when at least one connected provider answered its model catalog. */
15
+ available: boolean;
16
+ /** 可用模型总数:累加每个厂商成功 advertise 的模型数,而非厂商数。 */
17
+ models: number;
18
+ /** 失效厂商数(目录探测失败的厂商;失败信息不细分到模型级)。 */
19
+ failures: number;
20
+ /** Display names of providers that answered their model catalog (live). */
21
+ okProviders: readonly string[];
22
+ /** Display names of providers whose catalog probe failed. */
23
+ badProviders: readonly string[];
24
+ /** 探活得到的模型清单(系统里实际配置/预制的模型;无价格,费率表据此对标)。 */
25
+ catalog?: readonly CatalogModel[];
26
+ }
27
+ /** Idle health state before the probe settles. */
28
+ export declare const IDLE_HEALTH: ModelHealth;
29
+ /** 仪表盘分区 Tab id。 */
30
+ export type DashboardTab = 'overview' | 'token' | 'trends' | 'providers' | 'pricing' | 'settings';
31
+ import type { UsageBillingKey } from '../locales.ts';
32
+ /**
33
+ * Tab 定义(顺序即渲染顺序):概览=主数字/KPI/热力图,账单=厂商计费与订阅,
34
+ * 用量=Token 用量,趋势=趋势图/每轮费用,费率=模型单价表,设置=预算与峰谷提醒。
35
+ * 导出供测试断言 tab 与文案 key 对齐、decor 锚点落在正确分区。
36
+ */
37
+ export declare const DASHBOARD_TABS: readonly {
38
+ id: DashboardTab;
39
+ labelKey: UsageBillingKey;
40
+ }[];
41
+ /** 平均成本的统计范围(issue #47);`all` = 全量累计,不进逐日求和。 */
42
+ export type AvgCostRange = 'today' | '7d' | 'week' | 'month' | 'all';
43
+ /** 全局 KPI 按日聚合行的最小字段(byDay 行 = ModelUsage,结构兼容)。 */
44
+ export interface KpiDayRow {
45
+ cost: number;
46
+ calls: number;
47
+ input: number;
48
+ output: number;
49
+ cacheHit: number;
50
+ cacheMiss: number;
51
+ reasoning?: number;
52
+ }
53
+ /** 全局 KPI 聚合结果:KPI 七卡按所选范围重算所需的全部字段。 */
54
+ export interface KpiAgg {
55
+ cost: number;
56
+ calls: number;
57
+ input: number;
58
+ output: number;
59
+ cacheHit: number;
60
+ cacheMiss: number;
61
+ reasoning: number;
62
+ /** 范围内总处理 Token(缓存读+缓存写+输出)最大的日期戳;窗口无数据时 undefined。 */
63
+ peakDay: string | undefined;
64
+ /** 峰值日的总处理 Token 量;窗口无数据时 0。 */
65
+ peakTokens: number;
66
+ }
67
+ /** v1.5 Tab 徽章数据信号:空字符串 / 数字 / 状态字。`kind` 决定色调。 */
68
+ export type TabBadgeKind = 'warn' | 'hot' | 'violet' | 'neutral';
69
+ /** v1.5 Tab 徽章。 */
70
+ export interface TabBadge {
71
+ label: string;
72
+ kind: TabBadgeKind;
73
+ }
74
+ /** 各 Tab 数据信号聚合:调用方传 dashboardBadgeState(避免每个 Tab 重复声明) */
75
+ export interface DashboardBadgeState {
76
+ providersCount: number;
77
+ tokenTotal: number;
78
+ rateAgeMinutes: number | null;
79
+ settingsDirty: number;
80
+ }
81
+ /** 会话明细行(与服务端 SessionUsageRow 同形;旧快照可能缺失整个 bySession)。 */
82
+ export interface SessionBillingRow {
83
+ id: string;
84
+ title?: string;
85
+ cwd?: string;
86
+ /**
87
+ * 直接父会话 id(仅子智能体会话携带):宿主把子智能体落成独立会话,
88
+ * header 的 origin: subagent + parentSession 指向委派它的对话。
89
+ */
90
+ parentId?: string;
91
+ /** 全部后代子会话费用合计(服务端递归算好);无后代时缺失。 */
92
+ subCost?: number;
93
+ /** 全部后代子会话调用数;无后代时缺失。 */
94
+ subCalls?: number;
95
+ /** 数据来自旧算法折叠的持久账本行(原始日志已删,无法重算)。 */
96
+ stale?: boolean;
97
+ calls: number;
98
+ cost: number;
99
+ lastActive: number;
100
+ /** 展示层合并标记(issue #42):同标题会话归并后的段数(>1 时行尾显示 ×N)。 */
101
+ mergedCount?: number;
102
+ /** 合并组的段明细(展示层专用):一级行默认收起,展开后逐段显示。合并函数需 push,故非 readonly。 */
103
+ children?: SessionBillingRow[];
104
+ /** 挂到本组下的子智能体行(展示层专用):与段明细并列展开,带子智能体徽标。 */
105
+ subs?: SessionBillingRow[];
106
+ }
107
+ /** One model row derived from stats + the pricing catalog. */
108
+ export interface ModelRow {
109
+ key: string;
110
+ name: string;
111
+ provider: string;
112
+ color: string;
113
+ calls: number;
114
+ input: number;
115
+ output: number;
116
+ cacheHitRate: number;
117
+ estimated: number;
118
+ actual?: number;
119
+ /** Billed through a subscription plan (no per-token cost). */
120
+ plan: boolean;
121
+ /** 真实 model id 不在计费目录(落回「其他」):费用未估算,标注反馈。 */
122
+ uncatalogued: boolean;
123
+ /** 目录单价为估算价(厂商未公布官方按量价):标注以免误当正式定价。 */
124
+ estimatedPricing: boolean;
125
+ /** 走官方 DeepSeek 直连的调用数(其余为第三方中转/代理)。 */
126
+ officialCalls: number;
127
+ /** 走官方渠道的费用(CNY);三方费用 = actual - officialCost。 */
128
+ officialCost: number;
129
+ }
130
+ /** 组的入口种类:组头徽章用(direct=直连路由、site=中转站点、unknown=未知入口、vendor=纯订阅/余额组)。 */
131
+ export type ProviderChannelKind = 'direct' | 'site' | 'unknown' | 'vendor';
132
+ /**
133
+ * 按厂商聚合的计费组:模型用量 + 订阅额度 + 厂商余额。
134
+ * 余额与健康点只挂在厂商组头部(同厂商只显示一次),不再随每行重复。
135
+ */
136
+ export interface ProviderBillingGroup {
137
+ /**
138
+ * 跨语言/显示名稳定的组标识,用于展开状态持久化(issue #77 审计 S2):
139
+ * 通道组 `ch:<siteKey>`、纯订阅组 `sub:<vendorId>`、纯余额组 `bal:<providerId>`。
140
+ * name 会随语言切换变化,不能做持久化 key。
141
+ */
142
+ id: string;
143
+ /** 厂商显示名(模型厂商;订阅通道无厂商时用订阅名/自身 id)。 */
144
+ name: string;
145
+ /** 该厂商下的模型用量行(按费用降序,已过滤 calls>0)。 */
146
+ models: readonly ModelRow[];
147
+ /** 归并到该厂商的订阅额度卡片。 */
148
+ subscriptions: readonly SubscriptionQuota[];
149
+ /** 该厂商余额(同厂商只显示一次)。 */
150
+ balance: ProviderBalance | undefined;
151
+ /** 健康点状态:按厂商名与 health 的在线/失效列表匹配。 */
152
+ dot: string | undefined;
153
+ /** 入口种类;纯订阅/余额组无入口为 vendor。 */
154
+ channelKind: ProviderChannelKind;
155
+ }
156
+ /** 组件注入面:探活 + 计费指标写入(billing 自身写入,主题插件经服务读取)。 */
157
+ export interface UsageBillingInjected {
158
+ checkModels: () => Promise<ModelHealth>;
159
+ publishCosts: (costs: {
160
+ todayCost: number;
161
+ monthCost: number;
162
+ }) => void;
163
+ registerOpen: (handler: () => void) => () => void;
164
+ }
165
+ /** Usage stats structure from `.dsh-usage-stats.json`. */
166
+ export interface UsageStats {
167
+ /** 服务端聚合时间戳(毫秒);旧快照可能缺失。 */
168
+ updatedAt?: number;
169
+ /** 宿主进程时区(IANA 名 + UTC 偏移):天按此切分,副标题据此标注;旧快照可能缺失。 */
170
+ timezone?: {
171
+ name: string;
172
+ offset: string;
173
+ };
174
+ /** 月度预算(人民币元):宿主 Config 注入;未配置时不渲染预算条。 */
175
+ budget?: number;
176
+ /** 余额不足告警阈值(人民币元):宿主 Config 注入;未配置时客户端用默认值。 */
177
+ lowBalanceThreshold?: number;
178
+ /** 会话明细(按费用倒序,服务端已封顶);旧快照可能缺失。 */
179
+ bySession?: readonly SessionBillingRow[];
180
+ total: {
181
+ calls: number;
182
+ input: number;
183
+ output: number;
184
+ cacheHit: number;
185
+ cacheMiss: number;
186
+ /** 显式缓存写入(cacheMiss 子集,部分厂商单独报告);1.0.8 起新增,旧快照缺失。 */
187
+ cacheWrite?: number;
188
+ cost: number;
189
+ /** 输出中的 reasoning(思考)token;已含在 output 内。 */
190
+ reasoning: number;
191
+ /** 联网搜索请求的估算调用数(已按次估值计入 cost);1.0.9 起新增,旧快照缺失。 */
192
+ searchCalls?: number;
193
+ };
194
+ byModel: Record<string, {
195
+ calls: number;
196
+ input: number;
197
+ output: number;
198
+ cacheHit: number;
199
+ cacheMiss: number;
200
+ cost: number;
201
+ reasoning: number;
202
+ /** Billed through a subscription plan (no per-token cost). */
203
+ plan?: boolean;
204
+ /** 走官方 DeepSeek 直连的调用数(其余为第三方);旧快照可能缺失。 */
205
+ officialCalls?: number;
206
+ /** 走官方渠道的费用(CNY);旧快照可能缺失。 */
207
+ officialCost?: number;
208
+ }>;
209
+ byDay: Record<string, {
210
+ calls: number;
211
+ input: number;
212
+ output: number;
213
+ cacheHit: number;
214
+ cacheMiss: number;
215
+ cost: number;
216
+ reasoning: number;
217
+ }>;
218
+ /** 模型 × 日期 二维统计(趋势图堆叠柱的输入);旧快照可能缺失,渲染时降级为单色柱。 */
219
+ byDayModels?: Record<string, Record<string, {
220
+ calls: number;
221
+ input: number;
222
+ output: number;
223
+ cacheHit: number;
224
+ cacheMiss: number;
225
+ cost: number;
226
+ }>>;
227
+ /** 模型 × 日期 × 站点 三维统计([date][modelKey][siteKey]):按 origin 绑定自定义价的
228
+ * 显示层重估数据源;旧快照可能缺失。 */
229
+ byDayModelsSite?: Record<string, Record<string, Record<string, {
230
+ calls: number;
231
+ input: number;
232
+ output: number;
233
+ cacheHit: number;
234
+ cacheMiss: number;
235
+ cost: number;
236
+ /** 该格全部调用都走订阅通道(聚合侧按三维格置位);旧快照缺失,回退全局口径。 */
237
+ plan?: boolean;
238
+ }>>>;
239
+ /**
240
+ * 峰谷分桶(全量逐调用真实判档):1.0.8 起服务端按调用时刻精确归桶,
241
+ * 峰谷占比条优先用它(覆盖全部历史调用);旧快照缺失时回退逐轮估算。
242
+ */
243
+ byTier?: {
244
+ peak: {
245
+ cost: number;
246
+ calls: number;
247
+ };
248
+ offPeak: {
249
+ cost: number;
250
+ calls: number;
251
+ };
252
+ };
253
+ /** 工具调用次数排行(键 = 工具名,按次数倒序);旧快照缺失。 */
254
+ byTool?: Record<string, number>;
255
+ /** 每轮费用明细(服务端聚合路径恒带);旧快照可能缺失。 */
256
+ byTurn?: readonly {
257
+ sessionId: string;
258
+ turn: number;
259
+ model: string;
260
+ input: number;
261
+ output: number;
262
+ cacheHit: number;
263
+ cacheMiss: number;
264
+ cost: number;
265
+ startedAt: number;
266
+ endedAt?: number;
267
+ }[];
268
+ /** 工作区聚合(按 cwd 末级目录);旧快照可能缺失。 */
269
+ byWorkspace?: readonly {
270
+ name: string;
271
+ calls: number;
272
+ cost: number;
273
+ input: number;
274
+ output: number;
275
+ lastActive: number;
276
+ }[];
277
+ /** 中转站归组(key = `site:<origin>` / `direct:<provider>` / `unknown`);旧快照可能缺失。 */
278
+ bySite?: Record<string, {
279
+ calls: number;
280
+ input: number;
281
+ output: number;
282
+ cacheHit: number;
283
+ cacheMiss: number;
284
+ cost: number;
285
+ reasoning: number;
286
+ }>;
287
+ /** 不可计价模型 id(未收录/无价,费用按 0 计);旧快照可能缺失。 */
288
+ unpricedModels?: readonly string[];
289
+ /** 联网搜索请求的单次费用估算(人民币元,配置回显);0 或缺省 = 未启用估算。 */
290
+ searchCallEstimateCny?: number;
291
+ /** 按角色费用归因(估算口径:输出实测,输入按消息长度摊分);旧快照可能缺失。 */
292
+ byRole?: {
293
+ user: number;
294
+ assistant: number;
295
+ tool: number;
296
+ };
297
+ /** 性能指标(TTFT/生成速度/总延迟)按模型与按小时;旧快照可能缺失。 */
298
+ perf?: ClientPerf;
299
+ /** 旧版算法账本行兜底的会话数(模型归属可能失真);0 或缺省 = 全部数据可信。 */
300
+ staleLedgerSessions?: number;
301
+ /** 本轮未完整计入的会话数(跨轮次稳定);0 或缺省 = 全部会话已统计。 */
302
+ unreadableSessions?: number;
303
+ /** 未统计中因会话格式拒读的子集(过新待宿主升级、过旧需迁移);0 或缺省 = 无格式拒读。 */
304
+ unreadableFormatSessions?: number;
305
+ /** 未统计中无账本存档、完全未计入的子集;0 或缺省 = 拒读会话均有存档兜底。 */
306
+ unreadableNoLedgerSessions?: number;
307
+ /** 插件版本号(服务端读自包 package.json;旧快照缺失)。 */
308
+ pluginVersion?: string;
309
+ }
310
+ /** Empty snapshot: shown before (or without) real host data — zeros, never fabricated samples. */
311
+ export declare const EMPTY_STATS: UsageStats;
312
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,35 @@
1
+ /**
2
+ * 周/7天窗口聚合:KPI 范围求和、自然周累计(issue #39 口径)、近 7 天费用序列。
3
+ * 纯函数(日期取本地时区),无 React 依赖。`KpiDayRow` 是 byDay 行的最小字段,
4
+ * `dayTokensOf` 在 `streak.ts` 内已抽出,复用同口径。
5
+ */
6
+ import type { AvgCostRange, KpiAgg, KpiDayRow } from './types.ts';
7
+ /**
8
+ * 近 7 天费用序列(含今天,缺日补 0):触发卡 hover 速览的迷你柱数据源。
9
+ * 导出供测试:纯函数(日期取本地时区)。
10
+ * @param byDay - 按日费用表。
11
+ * @returns 7 个 `{ date, cost }`,最旧在前。
12
+ */
13
+ export declare function lastSevenDays(byDay: Record<string, {
14
+ cost: number;
15
+ }>): readonly {
16
+ date: string;
17
+ cost: number;
18
+ }[];
19
+ /**
20
+ * 本自然周(周一起算)到 `today` 的累计值(issue #39):标签「本周」的语义是
21
+ * 自然周,近 7 天滚动窗口会在周一把上周用量卷进来(周一时它与当月几乎相等,
22
+ * 用户误解为统计错误)。周一 = `getDay() === 1`;`pick` 决定日行取哪个维度。
23
+ * @param byDay - 按日聚合表(key = `YYYY-MM-DD` 本地时区)。
24
+ * @param today - 今天的本地日期戳。
25
+ * @param pick - 日行取值(缺省取 cost;token 视角传 input+output 合计)。
26
+ * @returns 本周一到今天的合计;`today` 本身不在表里(无调用)时为 0。
27
+ */
28
+ export declare function sinceMondayOf<T>(byDay: Record<string, T>, today: string, pick?: (row: T) => number): number;
29
+ /**
30
+ * 按范围聚合 byDay(issue #47):今日 / 近 7 天(含今天)/ 本周(周一起)/
31
+ * 本月。日期戳字典序即时间序(与 dailyBurnRate 同口径);累计口径由调用方
32
+ * 直接取 total(含搜索估值兜底),不走此函数。
33
+ */
34
+ export declare function sumByDayRange(byDay: Record<string, KpiDayRow>, today: string, range: Exclude<AvgCostRange, 'all'>): KpiAgg;
35
+ //# sourceMappingURL=week.d.ts.map
@@ -1,5 +1,5 @@
1
1
  /** Locale dictionaries for the usage billing surface. */
2
- export type UsageBillingKey = 'title' | 'cost' | 'todayCost' | 'monthCost' | 'yearCost' | 'monthProjected' | 'liveTurn' | 'liveSession' | 'liveSessionSub' | 'calls' | 'cacheHitRate' | 'tokens' | 'inputTokens' | 'outputTokens' | 'avgCost' | 'kpiRange' | 'avgRangeToday' | 'avgRange7d' | 'avgRangeWeek' | 'avgRangeMonth' | 'avgRangeAll' | 'trend' | 'trend7d' | 'trend30d' | 'trendMetric' | 'trendMetricCost' | 'trendMetricTokens' | 'pricingSearch' | 'bandPinHint' | 'trendEmpty' | 'trendTotal' | 'roundsUnit' | 'healthModelsLive' | 'healthVendorsDown' | 'healthVendorsUnavailable' | 'budget' | 'budgetRemain' | 'budgetAmount' | 'budgetSummary' | 'sessions' | 'sessionTitle' | 'lastActive' | 'sessionOverflow' | 'budgetTierBody' | 'models' | 'providerBilling' | 'channelUnknown' | 'directTag' | 'relayTag' | 'unknownTag' | 'unknownChannelHint' | 'planCountUnit' | 'actual' | 'pricing' | 'input' | 'output' | 'cacheHit' | 'peak' | 'offPeak' | 'flat' | 'band' | 'close' | 'footer' | 'footerCredit' | 'lastUpdated' | 'noData' | 'todayRate' | 'rateLive' | 'rateBuiltin' | 'pricingSyncedAt' | 'pricingSyncNow' | 'pricingSyncing' | 'promoBadge' | 'promoUntil' | 'promoOpenEnded' | 'pricingTip' | 'pricingUnit' | 'pricingNotes' | 'ubPeak' | 'ubOff' | 'ubStd' | 'peakBand' | 'pricingSource' | 'noteCache' | 'noteBand' | 'noteSource' | 'balance' | 'recharge' | 'rechargeHint' | 'balanceUnconfigured' | 'balanceUnauthorized' | 'balanceUnreachable' | 'uncatalogued' | 'estimatedPricing' | 'balanceDays' | 'balanceLowBody' | 'reconcileDrift' | 'reconcileDismiss' | 'subscriptionNotConfigured' | 'subscriptionUnauthorized' | 'subscriptionUnavailable' | 'subscriptionInvalid' | 'subscriptionRateLimited' | 'subscriptionSession' | 'subscriptionWeekly' | 'subscriptionMonthly' | 'subscriptionBilling' | 'subscriptionRemaining' | 'subscriptionExhausted' | 'subscriptionReset' | 'subscriptionNoApi' | 'floatWindow' | 'floatModeCombined' | 'floatModeSubscription' | 'floatMode' | 'floatTargets' | 'floatWindowHint' | 'floatPrimaryToday' | 'floatPrimaryWeek' | 'floatPrimaryMonth' | 'floatNoTargets' | 'floatNoTargetsHint' | 'cardDisplay' | 'cardDisplayHint' | 'cardMetric' | 'cardMetricMoney' | 'cardMetricTokens' | 'cardSpan' | 'cardSpanDay' | 'cardSpanWeek' | 'cardSpanMonth' | 'cardDeltaBadge' | 'cardDeltaShow' | 'cardDeltaHide' | 'triggerMonthTokens' | 'triggerTodayTokens' | 'triggerWeekTokens' | 'subscriptionsStale' | 'staleLedgerNotice' | 'unreadableNotice' | 'unreadableFormatNotice' | 'unreadableNoLedgerNotice' | 'tokenCacheWrite' | 'toolRank' | 'toolName' | 'userPrices' | 'userPricesHint' | 'userPriceSave' | 'userPriceModel' | 'userPriceSource' | 'userPriceSourceHint' | 'userPriceOffPeak' | 'userPriceNormal' | 'userPriceCurrency' | 'userPriceAdd' | 'userPriceRemoveSelected' | 'userPriceSelect' | 'sessionStaleBadge' | 'sessionUntitled' | 'sessionSubCost' | 'sessionSubCalls' | 'sessionSubRow' | 'heatmapLess' | 'heatmapMore' | 'currency' | 'currencyCny' | 'currencyUsd' | 'currencyEur' | 'language' | 'heatmap' | 'rounds' | 'roundsHint' | 'anomaly' | 'model' | 'thModel' | 'thInputMiss' | 'thInputHit' | 'costAbbr' | 'tabOverview' | 'tabTrends' | 'tabProviders' | 'tabPricing' | 'tabSettings' | 'budgetHint' | 'peakAlertHint' | 'peakAlertDescPeak' | 'peakAlertDescOff' | 'peakAlertDescPeakZhipu' | 'peakAlertDescOffZhipu' | 'export' | 'exportCsvDay' | 'exportCsvSession' | 'exportJson' | 'peakShare' | 'peakSharePerCall' | 'offPeakSavings' | 'perfMax' | 'weekCost' | 'roleCost' | 'roleUser' | 'roleAssistant' | 'roleTool' | 'roleHint' | 'tierPeak' | 'tierOff' | 'tierToPeak' | 'tierToOff' | 'tierAlertEnterPeak' | 'tierAlertEnterOff' | 'tierAlertEnterPeakZhipu' | 'tierAlertEnterOffZhipu' | 'peakAlertTitlePeak' | 'peakAlertTitleOff' | 'peakAlert' | 'peakAlertLeadMin' | 'peakAlertPos' | 'peakAlertMode' | 'peakAlertPosCorner' | 'peakAlertPosCenter' | 'peakAlertModePeak' | 'peakAlertModeOff' | 'peakAlertModeBoth' | 'peakAlertWebNotify' | 'peakAlertPreview' | 'planTypeCode' | 'planTypeToken' | 'subscriptionFeePerMonth' | 'triggerToday' | 'triggerMonth' | 'subscriptionTag' | 'cellEstimateHint' | 'free' | 'perfSamples' | 'perfTtft' | 'perfP50' | 'perfP90' | 'perfTps' | 'perfLatency' | 'perfEstimated' | 'perfEmpty' | 'perfTpsUnit' | 'perfTitle' | 'perfHint' | 'perfAll' | 'perfChartEmpty' | 'heatmapYear' | 'heatmapHalf' | 'heatmapMonth' | 'metricCost' | 'metricTokens' | 'heatmapTotal' | 'activeDays' | 'streakDays' | 'subscriptionAutoDetect' | 'pluginAuthor' | 'pluginRepository' | 'pluginNpm' | 'pluginLicense' | 'tabToken' | 'tokenExport' | 'tokenExportCsv' | 'tokenReasoningShare' | 'tokenReasoningShort' | 'tokenIo' | 'tokenPeak' | 'densityLabel' | 'densityHint' | 'densityCompact' | 'densityDefault' | 'densityComfortable' | 'motionLabel' | 'motionHint' | 'motionOff' | 'motionSubtle' | 'motionRich' | 'settingsNavBudget' | 'settingsNavAlert' | 'settingsNavDisplay' | 'settingsNavAdvanced' | 'settingsNavAbout' | 'settingsSectionDisplay' | 'emptyHint' | 'tokenDaily' | 'tokenByModel' | 'tokenMiss' | 'tokenHit' | 'tokenOutput' | 'tokenViewStructure' | 'tokenViewModel' | 'tokenHitShort' | 'tokenMissShort' | 'tokenTotal' | 'tokenShare' | 'usageStatsTool' | 'usageStatsToolHint' | 'balanceGranted' | 'balanceTopped' | 'balanceDaily' | 'balanceDaysLong' | 'balanceDaysUnit' | 'popTodayModel' | 'popNoConsumption' | 'popTitle' | 'popDirectLead' | 'popSubLead' | 'unpricedHint' | 'searchEstimateHint' | 'siteListDisplay' | 'siteListDisplayHint' | 'liveCostBar' | 'liveCostBarHint' | 'liveCostBarPosition' | 'liveCostBarPosBelow' | 'liveCostBarPosAbove' | 'liveCostBarPosToolbar' | 'exportCsvSite' | 'panelRelayQuota' | 'relayBalance' | 'relayNoQuota' | 'relayWindowUsed' | 'relayKindNewApi' | 'relayKindSub2Api' | 'relayKindUnknown' | 'expandAll' | 'collapseAll' | 'todayOnly' | 'todayNoConsumption';
2
+ export type UsageBillingKey = 'title' | 'cost' | 'todayCost' | 'monthCost' | 'yearCost' | 'monthProjected' | 'liveTurn' | 'liveSession' | 'liveSessionSub' | 'calls' | 'cacheHitRate' | 'tokens' | 'inputTokens' | 'outputTokens' | 'avgCost' | 'kpiRange' | 'avgRangeToday' | 'avgRange7d' | 'avgRangeWeek' | 'avgRangeMonth' | 'avgRangeAll' | 'trend' | 'trend7d' | 'trend30d' | 'trendMetric' | 'trendMetricCost' | 'trendMetricTokens' | 'pricingSearch' | 'bandPinHint' | 'trendEmpty' | 'trendTotal' | 'roundsUnit' | 'healthModelsLive' | 'healthVendorsDown' | 'healthVendorsUnavailable' | 'budget' | 'budgetRemain' | 'budgetAmount' | 'budgetSummary' | 'sessions' | 'sessionTitle' | 'lastActive' | 'sessionOverflow' | 'budgetTierBody' | 'models' | 'providerBilling' | 'channelUnknown' | 'directTag' | 'relayTag' | 'unknownTag' | 'unknownChannelHint' | 'planCountUnit' | 'actual' | 'pricing' | 'input' | 'output' | 'cacheHit' | 'peak' | 'offPeak' | 'flat' | 'band' | 'close' | 'footer' | 'footerCredit' | 'lastUpdated' | 'noData' | 'todayRate' | 'rateLive' | 'rateBuiltin' | 'pricingSyncedAt' | 'pricingSyncNow' | 'pricingSyncing' | 'promoBadge' | 'promoUntil' | 'promoOpenEnded' | 'pricingTip' | 'pricingUnit' | 'pricingNotes' | 'ubPeak' | 'ubOff' | 'ubStd' | 'peakBand' | 'pricingSource' | 'noteCache' | 'noteBand' | 'noteSource' | 'balance' | 'recharge' | 'rechargeHint' | 'balanceUnconfigured' | 'balanceUnauthorized' | 'balanceUnreachable' | 'uncatalogued' | 'estimatedPricing' | 'balanceDays' | 'balanceLowBody' | 'reconcileDrift' | 'reconcileDismiss' | 'subscriptionNotConfigured' | 'subscriptionUnauthorized' | 'subscriptionUnavailable' | 'subscriptionInvalid' | 'subscriptionRateLimited' | 'subscriptionSession' | 'subscriptionWeekly' | 'subscriptionMonthly' | 'subscriptionBilling' | 'subscriptionRemaining' | 'subscriptionExhausted' | 'subscriptionReset' | 'subscriptionNoApi' | 'floatWindow' | 'floatModeCombined' | 'floatModeSubscription' | 'floatMode' | 'floatTargets' | 'floatWindowHint' | 'floatPrimaryToday' | 'floatPrimaryWeek' | 'floatPrimaryMonth' | 'floatNoTargets' | 'floatNoTargetsHint' | 'cardDisplay' | 'cardDisplayHint' | 'cardMetric' | 'cardMetricMoney' | 'cardMetricTokens' | 'cardSpan' | 'cardSpanDay' | 'cardSpanWeek' | 'cardSpanMonth' | 'cardDeltaBadge' | 'cardDeltaShow' | 'cardDeltaHide' | 'triggerMonthTokens' | 'triggerTodayTokens' | 'triggerWeekTokens' | 'subscriptionsStale' | 'staleLedgerNotice' | 'unreadableNotice' | 'unreadableFormatNotice' | 'unreadableNoLedgerNotice' | 'tokenCacheWrite' | 'toolRank' | 'toolName' | 'userPrices' | 'userPricesHint' | 'userPriceSave' | 'userPriceModel' | 'userPriceSource' | 'userPriceSourceHint' | 'userPriceOffPeak' | 'userPriceNormal' | 'userPriceCurrency' | 'userPriceAdd' | 'userPriceRemoveSelected' | 'userPriceSelect' | 'sessionStaleBadge' | 'sessionUntitled' | 'sessionSubCost' | 'sessionSubCalls' | 'sessionSubRow' | 'heatmapLess' | 'heatmapMore' | 'currency' | 'currencyCny' | 'currencyUsd' | 'currencyEur' | 'language' | 'heatmap' | 'rounds' | 'roundsHint' | 'anomaly' | 'model' | 'thModel' | 'thInputMiss' | 'thInputHit' | 'costAbbr' | 'tabOverview' | 'tabTrends' | 'tabProviders' | 'tabPricing' | 'tabSettings' | 'budgetHint' | 'peakAlertHint' | 'peakAlertDescPeak' | 'peakAlertDescOff' | 'peakAlertDescPeakZhipu' | 'peakAlertDescOffZhipu' | 'export' | 'exportCsvDay' | 'exportCsvSession' | 'exportJson' | 'peakShare' | 'peakSharePerCall' | 'offPeakSavings' | 'perfMax' | 'weekCost' | 'roleCost' | 'roleUser' | 'roleAssistant' | 'roleTool' | 'roleHint' | 'tierPeak' | 'tierOff' | 'tierToPeak' | 'tierToOff' | 'tierAlertEnterPeak' | 'tierAlertEnterOff' | 'tierAlertEnterPeakZhipu' | 'tierAlertEnterOffZhipu' | 'peakAlertTitlePeak' | 'peakAlertTitleOff' | 'peakAlert' | 'peakAlertLeadMin' | 'peakAlertPos' | 'peakAlertMode' | 'peakAlertPosCorner' | 'peakAlertPosCenter' | 'peakAlertModePeak' | 'peakAlertModeOff' | 'peakAlertModeBoth' | 'peakAlertWebNotify' | 'peakAlertPreview' | 'planTypeCode' | 'planTypeToken' | 'subscriptionFeePerMonth' | 'triggerToday' | 'triggerMonth' | 'subscriptionTag' | 'cellEstimateHint' | 'free' | 'perfSamples' | 'perfTtft' | 'perfP50' | 'perfP90' | 'perfTps' | 'perfLatency' | 'perfEstimated' | 'perfEmpty' | 'perfTpsUnit' | 'perfTitle' | 'perfHint' | 'perfAll' | 'perfChartEmpty' | 'heatmapYear' | 'heatmapHalf' | 'heatmapMonth' | 'metricCost' | 'metricTokens' | 'heatmapTotal' | 'activeDays' | 'streakDays' | 'subscriptionAutoDetect' | 'pluginAuthor' | 'pluginRepository' | 'pluginNpm' | 'pluginLicense' | 'tabToken' | 'tokenExport' | 'tokenExportCsv' | 'tokenReasoningShare' | 'tokenReasoningShort' | 'tokenIo' | 'tokenPeak' | 'densityLabel' | 'densityHint' | 'densityCompact' | 'densityDefault' | 'densityComfortable' | 'motionLabel' | 'motionHint' | 'motionOff' | 'motionSubtle' | 'motionRich' | 'settingsNavDisplayPref' | 'settingsNavBudget' | 'settingsNavAlert' | 'settingsNavDisplay' | 'settingsNavAdvanced' | 'settingsNavAbout' | 'settingsSearchPlaceholder' | 'settingsSearchEmpty' | 'sessionsViewAll' | 'sessionViewerSearch' | 'modelBudgetTitle' | 'modelBudgetHint' | 'modelBudgetBody' | 'modelBudgetPlaceholder' | 'moreWorksTitle' | 'adEngramName' | 'adEngramDesc' | 'adRainbowName' | 'adRainbowDesc' | 'kpiDescCacheHit' | 'kpiDescTokens' | 'kpiDescAvgCost' | 'kpiDescCalls' | 'kpiDescReasoning' | 'kpiDescIo' | 'kpiDescPeak' | 'healthDotLive' | 'healthDotFailed' | 'healthDotUnknown' | 'settingsSectionDisplay' | 'emptyHint' | 'tokenDaily' | 'tokenByModel' | 'tokenMiss' | 'tokenHit' | 'tokenOutput' | 'tokenViewStructure' | 'tokenViewModel' | 'tokenHitShort' | 'tokenMissShort' | 'tokenTotal' | 'tokenShare' | 'usageStatsTool' | 'usageStatsToolHint' | 'balanceGranted' | 'balanceTopped' | 'balanceDaily' | 'balanceDaysLong' | 'balanceDaysUnit' | 'popTodayModel' | 'popNoConsumption' | 'popTitle' | 'popDirectLead' | 'popSubLead' | 'unpricedHint' | 'searchEstimateHint' | 'siteListDisplay' | 'siteListDisplayHint' | 'liveCostBar' | 'liveCostBarHint' | 'liveCostBarPosition' | 'liveCostBarPosBelow' | 'liveCostBarPosAbove' | 'liveCostBarPosToolbar' | 'exportCsvSite' | 'panelRelayQuota' | 'relayBalance' | 'relayNoQuota' | 'relayWindowUsed' | 'relayKindNewApi' | 'relayKindSub2Api' | 'relayKindUnknown' | 'expandAll' | 'collapseAll' | 'todayOnly' | 'todayNoConsumption';
3
3
  export declare const NS = "usageBilling";
4
4
  export declare const zh: Record<UsageBillingKey, string>;
5
5
  export declare const en: Record<UsageBillingKey, string>;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * 设置页全文搜索(U-4):按关键词过滤设置分区。
3
+ *
4
+ * 每个分区带一组中英文关键词(覆盖其标题、说明与常见同义词),查询串对
5
+ * 关键词做大小写不敏感的子串匹配——任意关键词命中即显示该分区。查询为空
6
+ * (或纯空白)时全部分区显示。
7
+ *
8
+ * 纯函数,导出供测试。
9
+ */
10
+ /** 一个设置分区的隐藏判定:查询非空且没有任何关键词命中时隐藏。 */
11
+ export declare function settingsSectionHidden(query: string, keywords: readonly string[]): boolean;
12
+ //# sourceMappingURL=settings-search.d.ts.map
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Plugin configuration(v1.5.2 抽出):UsageBillingConfig 原本声明在 src/index.ts
3
+ * 顶部,src/index.ts 收缩为装配器后被 src/routes/usage-stats.ts 等路由文件
4
+ * 引用(作为 Deps 类型签名),把它单独放这里让 route 文件能从 src/ 根 import。
5
+ * 仍由 src/index.ts 的 apply(ctx, config) 消费:路由层只通过 Deps 拿到它,
6
+ * 不直接构造。
7
+ */
8
+ import type { CustomBalanceConfig, DeclaredEndpointConfig, SubscriptionPlanConfig } from './pricing-shared.ts';
9
+ /** 宿主 0.1.7+ 经 Config schema 解析后,volatile 字段在 config 中的稳定引用形态
10
+ * (cosmokit `Volatile<T>` 的最小结构镜像,避免为类型引入直接依赖)。 */
11
+ export interface VolatileToggle {
12
+ /** @returns 当前生效的布尔快照(设置写入后原位更新,无需重载插件)。 */
13
+ get(): boolean;
14
+ }
15
+ /** Plugin configuration. */
16
+ export interface UsageBillingConfig {
17
+ /** Absolute path to a `.dsh-usage-stats.json` fallback file. */
18
+ statsPath?: string;
19
+ /** 统计快照的持久化路径;默认 `<harness home>/.dsh-usage-stats.json`
20
+ * (harness home = `DSH_HOME` 环境变量或 `~/.dsh`,见 resolveDshHome)。
21
+ * 测试注入临时目录以隔离真实家目录(聚合失败回退与快照落盘都走此路径)。 */
22
+ snapshotPath?: string;
23
+ /** 独立持久用量账本的绝对路径;默认 `<harness home>/.dsh-usage-ledger.json`。
24
+ * 账本与会话日志解耦,因此永久删除会话不会抹掉已经观测到的用量。 */
25
+ ledgerPath?: string;
26
+ /** 余额差对账基准的持久化路径;默认 `<harness home>/.dsh-usage-reconcile.json`。 */
27
+ reconcilePath?: string;
28
+ /** 订阅制(coding / token / agent plan)provider id 列表;默认 kimi-coding、xiaomi-token-plan-cn。 */
29
+ subscriptionProviders?: string[];
30
+ /** 订阅套餐额度适配器(kimi / zai / opencode-go);默认全部内置。 */
31
+ subscriptionPlans?: readonly SubscriptionPlanConfig[];
32
+ /** 余额查询用的 DeepSeek 凭据引用(环境变量名);默认 DEEPSEEK_API_KEY。 */
33
+ balanceApiKeyEnv?: string;
34
+ /** 月度预算(人民币元);设置后随 usage-stats 下发,仪表盘显示预算进度条。 */
35
+ monthlyBudget?: number;
36
+ /** 余额不足告警阈值(人民币元):余额低于此值时仪表盘每天提醒一次;
37
+ 不设置则客户端按默认阈值(50 元)兜底。 */
38
+ lowBalanceThreshold?: number;
39
+ /** 自定义 Provider 余额查询(任意 HTTP 端点 + extract 规则,适配 NewApi/LiteLLM 等)。 */
40
+ customBalances?: readonly CustomBalanceConfig[];
41
+ /**
42
+ * 声明端点(declarative endpoints):为内置表没有的供应商自声明余额/额度接口。
43
+ * 绑定到某条已配置 provider 的同源地址,`fields` / `windows` 写响应里的取值路径;
44
+ * 安全边界(origin 绑定、单斜杠 path、只 GET、跨源重定向失败、凭据取自 apiKeyEnv)
45
+ * 写死在 declarative.ts。缺省空。
46
+ */
47
+ declaredEndpoints?: readonly DeclaredEndpointConfig[];
48
+ /**
49
+ * 允许通过 Host 头校验的额外主机名(反向代理场景);缺省空,行为与历史版本完全一致。
50
+ * 仅在 peer socket 已通过回环校验后才参考:socket 校验仍为强制且不受本字段影响,
51
+ * 本名单只放宽「纵深防御」的第二层。匹配为**精确主机名**,忽略大小写与端口;
52
+ * 不支持后缀 / 通配符,因此 `evil.com` 永远无法满足 `trusted.com`。
53
+ * 例:`['llm.example.com']`。
54
+ */
55
+ trustedHosts?: string[];
56
+ /** `usage_stats` 工具注入开关(默认 false:不注入)。宿主 0.1.7+ 经 Config
57
+ * 解析后是 volatile 引用(设置写入即时反映),直连 apply(测试)是普通布尔;
58
+ * 读取统一走 readUsageStatsToggle。该工具占用每次请求的上下文,coding 场景多在仪表盘查看。 */
59
+ enableUsageStatsTool?: boolean | VolatileToggle;
60
+ /**
61
+ * 联网搜索请求(`web/deepseek-search-llm-request`,日志只有请求、无用量事件)
62
+ * 的单次费用估算(人民币元)。这类调用直连官方 api.deepseek.com,开放平台照常
63
+ * 计费但本地日志无 usage,按次估值计入今日/本月费用;默认 0.02 元/次,设 0 关闭。
64
+ */
65
+ searchCallEstimateCny?: number;
66
+ /**
67
+ * 历史路由别名(旧 provider 路由名 → 当前路由名):改过名/删除过的路由,其
68
+ * 历史用量原会落「未知路由」桶且站点/订阅/官方判定全部失效;配置别名后按
69
+ * 目标路由归位。例:`{ "deepseek-official": "tencent", "tencent-cloud": "tencent" }`。
70
+ */
71
+ routeAliases?: Record<string, string>;
72
+ /**
73
+ * 用户自定义模型别名(真实日志 model id → 计费目录键):目录外的新模型无需
74
+ * 等发版,配置一条别名即完成识别与计价(值必须是 MODEL_CATALOG 的既有 key,
75
+ * 如 `{ "hy4-preview": "hunyuan" }`)。聚合折叠与客户端渲染共用同一映射。
76
+ */
77
+ modelKeyAliases?: Record<string, string>;
78
+ }
79
+ //# sourceMappingURL=config.d.ts.map