dsh-claude-style 0.19.3 → 0.19.4-dev.49
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.
- package/docs/CHANGELOG.md +58 -0
- package/docs/STYLE.md +36 -11
- package/lib/assets/212c8e3d551b.js.br +0 -0
- package/lib/assets/976cd6c95f4b.js.br +0 -0
- package/lib/assets/d1be2553f5b3.js.br +0 -0
- package/lib/assets/manifest.json +12 -12
- package/lib/client.js +10 -10
- package/lib/host/index.js +2 -0
- package/lib/host/routes.js +12 -3
- package/lib/host/session-cost.js +78 -10
- package/lib/host/settings.js +7 -0
- package/lib/host/widget-usage.js +164 -0
- package/lib/prices.json +30 -20
- package/package.json +1 -1
- package/lib/assets/cbbadac799d3.js.br +0 -0
- package/lib/assets/d021d0e8b40f.js.br +0 -0
- package/lib/assets/dd2226ba435f.js.br +0 -0
package/lib/host/index.js
CHANGED
|
@@ -4,6 +4,7 @@ var PACKAGE_NAME = "dsh-claude-style";
|
|
|
4
4
|
// packages/host/src/index.ts
|
|
5
5
|
import { registerRoutes } from "./routes.js";
|
|
6
6
|
import { registerSettings } from "./settings.js";
|
|
7
|
+
import { registerWidgetUsage } from "./widget-usage.js";
|
|
7
8
|
import { Config } from "./settings.js";
|
|
8
9
|
var name = PACKAGE_NAME;
|
|
9
10
|
function apply(ctx) {
|
|
@@ -12,6 +13,7 @@ function apply(ctx) {
|
|
|
12
13
|
});
|
|
13
14
|
else registerRoutes(ctx, ctx);
|
|
14
15
|
registerSettings(ctx);
|
|
16
|
+
registerWidgetUsage(ctx);
|
|
15
17
|
}
|
|
16
18
|
export {
|
|
17
19
|
Config,
|
package/lib/host/routes.js
CHANGED
|
@@ -173,10 +173,17 @@ import { packageRoot } from "./package-root.js";
|
|
|
173
173
|
import { createPeakRate } from "./peakrate.js";
|
|
174
174
|
import { createPrices } from "./prices.js";
|
|
175
175
|
import { QUERY_MAX, createSessionSearch } from "./search.js";
|
|
176
|
-
import { createSessionCost } from "./session-cost.js";
|
|
176
|
+
import { billingRowsOf, createSessionCost } from "./session-cost.js";
|
|
177
177
|
import { sessionDirectoryName } from "./session-name.js";
|
|
178
178
|
import { createUsage } from "./usage.js";
|
|
179
179
|
var COPY_FILE = "model-descriptions.json";
|
|
180
|
+
var BILLING_ROWS_MAX = 32;
|
|
181
|
+
var BILLING_ROW_MAX = 256;
|
|
182
|
+
function readBillingRows(query) {
|
|
183
|
+
const currency = query.get("cur");
|
|
184
|
+
const rows = query.getAll("b").slice(0, BILLING_ROWS_MAX).filter((row) => row.length <= BILLING_ROW_MAX);
|
|
185
|
+
return billingRowsOf(rows, currency === "CNY" || currency === "USD" ? currency : null);
|
|
186
|
+
}
|
|
180
187
|
var FONT_FILES = {
|
|
181
188
|
"JetBrainsMonoVariable.ttf": "font/ttf",
|
|
182
189
|
"JetBrainsMonoItalicVariable.ttf": "font/ttf",
|
|
@@ -451,12 +458,14 @@ function registerRoutes(ctx, scope) {
|
|
|
451
458
|
handler: (req, res) => {
|
|
452
459
|
if (methodRefused(req, res, ["GET"])) return;
|
|
453
460
|
if (fenceRefused(ctx, req, res)) return;
|
|
454
|
-
const
|
|
461
|
+
const query = new URL(req.url ?? "/", "http://local").searchParams;
|
|
462
|
+
const sessionId = (query.get("id") ?? "").trim();
|
|
455
463
|
if (!SESSION_ID_RE.test(sessionId)) {
|
|
456
464
|
sendJson(res, 400, { ok: false, error: "invalid session id" });
|
|
457
465
|
return;
|
|
458
466
|
}
|
|
459
|
-
|
|
467
|
+
const billing = readBillingRows(query);
|
|
468
|
+
sendPayload(res, sessionCost.get(sessionId, billing).then((value) => ({ value })));
|
|
460
469
|
}
|
|
461
470
|
});
|
|
462
471
|
for (const { label, route } of brandRoutes(ctx)) register(label, route);
|
package/lib/host/session-cost.js
CHANGED
|
@@ -100,8 +100,8 @@ function priceFor(document, modelId, currency) {
|
|
|
100
100
|
const parts = (published ?? document.catalog?.[catalogId] ?? "").split(" ").map(Number);
|
|
101
101
|
if (parts.length !== 3 || !parts.every((value) => Number.isFinite(value) && value >= 0)) return void 0;
|
|
102
102
|
if (parts[0] === 0 && parts[2] === 0) return void 0;
|
|
103
|
-
const
|
|
104
|
-
const tier = { cacheHit: parts[1] *
|
|
103
|
+
const rate2 = published !== void 0 ? 1 : currency === "CNY" ? document.usdToCny ?? 7.2 : 1;
|
|
104
|
+
const tier = { cacheHit: parts[1] * rate2, cacheMiss: parts[0] * rate2, output: parts[2] * rate2 };
|
|
105
105
|
return { offPeak: tier, peak: tier };
|
|
106
106
|
}
|
|
107
107
|
function priceTierAt(price, atMs, schedule) {
|
|
@@ -113,6 +113,55 @@ function costMicro(usage, tier) {
|
|
|
113
113
|
return Number.isFinite(cost) && cost > 0 ? cost : 0;
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
// packages/contracts/src/billing-table.ts
|
|
117
|
+
function splitBillingRow(entry) {
|
|
118
|
+
const parts = entry.split("|");
|
|
119
|
+
return [parts[0] ?? "", parts[1] ?? "", parts[2] ?? "", parts[3] ?? ""].map((part) => part.trim());
|
|
120
|
+
}
|
|
121
|
+
function parseBillingRow(entry) {
|
|
122
|
+
const [model, input, cacheRead, output] = splitBillingRow(entry);
|
|
123
|
+
if (model === "") return null;
|
|
124
|
+
return { model, cacheMiss: rate(input), cacheHit: rate(cacheRead), output: rate(output) };
|
|
125
|
+
}
|
|
126
|
+
function rate(text) {
|
|
127
|
+
if (text === "") return null;
|
|
128
|
+
const value = Number(text);
|
|
129
|
+
return Number.isFinite(value) && value >= 0 ? value : null;
|
|
130
|
+
}
|
|
131
|
+
function parseBillingTable(entries) {
|
|
132
|
+
const rows = [];
|
|
133
|
+
for (const entry of entries) {
|
|
134
|
+
const row = parseBillingRow(entry);
|
|
135
|
+
if (row !== null) rows.push(row);
|
|
136
|
+
}
|
|
137
|
+
return rows;
|
|
138
|
+
}
|
|
139
|
+
function billingModelKey(modelId) {
|
|
140
|
+
const raw = modelId.trim().toLowerCase();
|
|
141
|
+
if (raw === "") return null;
|
|
142
|
+
return raw.includes("/") ? raw.slice(raw.lastIndexOf("/") + 1) : raw;
|
|
143
|
+
}
|
|
144
|
+
function billingRowFor(rows, modelId) {
|
|
145
|
+
const key = billingModelKey(modelId);
|
|
146
|
+
if (key === null) return null;
|
|
147
|
+
for (const row of rows) {
|
|
148
|
+
if (billingModelKey(row.model) === key) return row;
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
function overlayBilling(rows, modelId, table) {
|
|
153
|
+
const row = billingRowFor(rows, modelId);
|
|
154
|
+
if (row === null) return table;
|
|
155
|
+
const base = table ?? { cacheHit: 0, cacheMiss: 0, output: 0 };
|
|
156
|
+
const tier = {
|
|
157
|
+
cacheMiss: row.cacheMiss ?? base.cacheMiss,
|
|
158
|
+
cacheHit: row.cacheHit ?? base.cacheHit,
|
|
159
|
+
output: row.output ?? base.output
|
|
160
|
+
};
|
|
161
|
+
if (tier.cacheMiss === 0 && tier.cacheHit === 0 && tier.output === 0) return void 0;
|
|
162
|
+
return tier;
|
|
163
|
+
}
|
|
164
|
+
|
|
116
165
|
// packages/engine/node/session-events.ts
|
|
117
166
|
function eventsOf(events) {
|
|
118
167
|
return Array.isArray(events) ? events : null;
|
|
@@ -154,6 +203,11 @@ async function readEvents(ctx, packageName, sessionId, label) {
|
|
|
154
203
|
// packages/host/src/session-cost.ts
|
|
155
204
|
import { modelOf, usageOf } from "./usage-fold.js";
|
|
156
205
|
var KEPT_SESSIONS = 128;
|
|
206
|
+
var NO_BILLING = { rows: [], currency: null };
|
|
207
|
+
function billingRowsOf(entries, currency) {
|
|
208
|
+
const rows = parseBillingTable(entries);
|
|
209
|
+
return rows.length === 0 ? NO_BILLING : { rows, currency };
|
|
210
|
+
}
|
|
157
211
|
function count(value) {
|
|
158
212
|
const number = Number(value);
|
|
159
213
|
return Number.isFinite(number) && number > 0 ? number : 0;
|
|
@@ -171,7 +225,7 @@ function usageOfSample(event) {
|
|
|
171
225
|
function sameUsage(settlement, usage) {
|
|
172
226
|
return settlement.input === usage.input && settlement.output === usage.output && settlement.cacheRead === usage.cacheRead && settlement.cacheWrite === usage.cacheWrite;
|
|
173
227
|
}
|
|
174
|
-
function applyCostEvent(state, event, document) {
|
|
228
|
+
function applyCostEvent(state, event, document, billing = NO_BILLING) {
|
|
175
229
|
const type = event?.type;
|
|
176
230
|
if (type === "llm/retry-started") {
|
|
177
231
|
const turn2 = event.data?.turn;
|
|
@@ -195,8 +249,10 @@ function applyCostEvent(state, event, document) {
|
|
|
195
249
|
let partial = state.partial;
|
|
196
250
|
const priced = (currency) => {
|
|
197
251
|
const price = model === null ? void 0 : priceFor(document, model, currency);
|
|
198
|
-
|
|
199
|
-
|
|
252
|
+
const tier = price === void 0 ? void 0 : priceTierAt(price, time, document.schedule);
|
|
253
|
+
const overlaid = model === null || billing.currency !== null && billing.currency !== currency ? tier : overlayBilling(billing.rows, model, tier);
|
|
254
|
+
if (overlaid === void 0) return null;
|
|
255
|
+
return costMicro(usage, overlaid);
|
|
200
256
|
};
|
|
201
257
|
const cnyCost = priced("CNY");
|
|
202
258
|
const usdCost = priced("USD");
|
|
@@ -223,14 +279,16 @@ function applyCostEvent(state, event, document) {
|
|
|
223
279
|
model: modelOf(event) ?? state.model
|
|
224
280
|
};
|
|
225
281
|
}
|
|
226
|
-
function foldSessionCost(events, document) {
|
|
282
|
+
function foldSessionCost(events, document, billing = NO_BILLING) {
|
|
227
283
|
let state = { cny: 0, usd: 0, partial: false, last: null, model: null };
|
|
228
|
-
for (let i = 0; i < events.length; i++) state = applyCostEvent(state, events[i], document);
|
|
284
|
+
for (let i = 0; i < events.length; i++) state = applyCostEvent(state, events[i], document, billing);
|
|
229
285
|
return state;
|
|
230
286
|
}
|
|
231
287
|
var STALE_MS = 1e4;
|
|
232
288
|
function createSessionCost(ctx, prices) {
|
|
233
289
|
const states = /* @__PURE__ */ new Map();
|
|
290
|
+
let liveBilling = NO_BILLING;
|
|
291
|
+
let billingSignature = "";
|
|
234
292
|
const touchedAt = /* @__PURE__ */ new Map();
|
|
235
293
|
const pending = /* @__PURE__ */ new Map();
|
|
236
294
|
const offPriceChange = prices.onChange(() => {
|
|
@@ -253,7 +311,7 @@ function createSessionCost(ctx, prices) {
|
|
|
253
311
|
if (state === void 0) return;
|
|
254
312
|
const document = prices.document();
|
|
255
313
|
if (document === null) return;
|
|
256
|
-
const next = applyCostEvent(state, event, document);
|
|
314
|
+
const next = applyCostEvent(state, event, document, liveBilling);
|
|
257
315
|
if (next !== state) states.set(sessionId, next);
|
|
258
316
|
touchedAt.set(sessionId, Date.now());
|
|
259
317
|
}
|
|
@@ -264,8 +322,16 @@ function createSessionCost(ctx, prices) {
|
|
|
264
322
|
if (id !== "") observe(id, event);
|
|
265
323
|
});
|
|
266
324
|
}
|
|
267
|
-
async function get(sessionId) {
|
|
325
|
+
async function get(sessionId, billing = NO_BILLING) {
|
|
268
326
|
prices.ensure();
|
|
327
|
+
const signature = billing.currency === null ? "" : billing.rows.map((row) => `${row.model}|${row.cacheMiss}|${row.cacheHit}|${row.output}`).join(";");
|
|
328
|
+
if (signature !== billingSignature) {
|
|
329
|
+
billingSignature = signature;
|
|
330
|
+
liveBilling = billing;
|
|
331
|
+
states.clear();
|
|
332
|
+
touchedAt.clear();
|
|
333
|
+
pending.clear();
|
|
334
|
+
}
|
|
269
335
|
const held = states.get(sessionId);
|
|
270
336
|
const touched = touchedAt.get(sessionId);
|
|
271
337
|
if (held !== void 0 && touched !== void 0 && Date.now() - touched < STALE_MS) return answer(held);
|
|
@@ -276,7 +342,7 @@ function createSessionCost(ctx, prices) {
|
|
|
276
342
|
const work = readEvents(ctx, PACKAGE_NAME, sessionId, "the session cost").then((events) => {
|
|
277
343
|
pending.delete(sessionId);
|
|
278
344
|
if (events === null) return null;
|
|
279
|
-
const state = foldSessionCost(events, document);
|
|
345
|
+
const state = foldSessionCost(events, document, liveBilling);
|
|
280
346
|
states.set(sessionId, state);
|
|
281
347
|
touchedAt.set(sessionId, Date.now());
|
|
282
348
|
trim();
|
|
@@ -300,7 +366,9 @@ function createSessionCost(ctx, prices) {
|
|
|
300
366
|
};
|
|
301
367
|
}
|
|
302
368
|
export {
|
|
369
|
+
NO_BILLING,
|
|
303
370
|
applyCostEvent,
|
|
371
|
+
billingRowsOf,
|
|
304
372
|
createSessionCost,
|
|
305
373
|
foldSessionCost
|
|
306
374
|
};
|
package/lib/host/settings.js
CHANGED
|
@@ -115,6 +115,7 @@ var SODIUM_MODES = [SODIUM_UNDECIDED, SODIUM_ON, SODIUM_OFF];
|
|
|
115
115
|
var USERNAME_MAX = 64;
|
|
116
116
|
var QUICK_PROVIDERS_MAX = 64;
|
|
117
117
|
var PROVIDER_ID_MAX = 128;
|
|
118
|
+
var PRICE_ROWS_MAX = 32;
|
|
118
119
|
var PREFS = {
|
|
119
120
|
brand: { type: "choice", values: BRANDS, default: BRAND_CLAUDE, legacy: { [BRAND_DEEPSEEK_LEGACY]: BRAND_DEEPSEEK } },
|
|
120
121
|
brandName: { type: "text", default: "", max: BRAND_NAME_MAX },
|
|
@@ -169,6 +170,12 @@ var PREFS = {
|
|
|
169
170
|
statsFooterAlign: { type: "choice", values: STATS_FOOTER_ALIGNS, default: "center" },
|
|
170
171
|
/** Which official price table the session's cost follows, or off for no figure at all. */
|
|
171
172
|
billingCurrency: { type: "choice", values: BILLING_CHOICES, default: CURRENCY_CNY },
|
|
173
|
+
/**
|
|
174
|
+
* The reader's own prices, one row each: `model|input|cacheRead|output` per
|
|
175
|
+
* million tokens, in the billing currency. A row overrides the table for that
|
|
176
|
+
* model (billing-table.ts); a blank bucket leaves that rate to the table.
|
|
177
|
+
*/
|
|
178
|
+
billingTable: { type: "list", default: [], max: PRICE_ROWS_MAX, entryMax: 256, drop: [] },
|
|
172
179
|
workspaceView: { type: "boolean", default: true },
|
|
173
180
|
dockCards: { type: "boolean", default: true },
|
|
174
181
|
sidebarSearch: { type: "boolean", default: true },
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// packages/host/src/widget-usage.ts
|
|
2
|
+
import { createUsage } from "./usage.js";
|
|
3
|
+
var WIDGET_USAGE_CAPABILITY = "usage";
|
|
4
|
+
var WIDGET_USAGE_PROVIDER = "dsh-claude-style";
|
|
5
|
+
var WIDGET_BOARD_API_VERSION = 3;
|
|
6
|
+
var WIDGET_BOARD_SERVICE = "widgetBoard";
|
|
7
|
+
var WIDGET_USAGE_WAIT_MS = 12e3;
|
|
8
|
+
var NUMBER = { type: "number", minimum: 0 };
|
|
9
|
+
var WIDGET_USAGE_INPUT = { type: "object", additionalProperties: false, properties: {} };
|
|
10
|
+
var WIDGET_USAGE_OUTPUT = {
|
|
11
|
+
type: "object",
|
|
12
|
+
additionalProperties: false,
|
|
13
|
+
required: ["ready", "computedAt", "error", "days", "models", "hours", "totals", "firstDay", "lastDay"],
|
|
14
|
+
properties: {
|
|
15
|
+
ready: { type: "boolean" },
|
|
16
|
+
computedAt: { type: ["number", "null"] },
|
|
17
|
+
error: { type: ["string", "null"] },
|
|
18
|
+
days: {
|
|
19
|
+
type: "array",
|
|
20
|
+
items: {
|
|
21
|
+
type: "object",
|
|
22
|
+
additionalProperties: false,
|
|
23
|
+
required: ["date", "input", "output", "cacheRead", "cacheWrite", "calls", "sessions"],
|
|
24
|
+
properties: {
|
|
25
|
+
date: { type: "string" },
|
|
26
|
+
input: NUMBER,
|
|
27
|
+
output: NUMBER,
|
|
28
|
+
cacheRead: NUMBER,
|
|
29
|
+
cacheWrite: NUMBER,
|
|
30
|
+
calls: NUMBER,
|
|
31
|
+
sessions: NUMBER,
|
|
32
|
+
hours: { type: "array", items: NUMBER }
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
models: {
|
|
37
|
+
type: "array",
|
|
38
|
+
items: {
|
|
39
|
+
type: "object",
|
|
40
|
+
additionalProperties: false,
|
|
41
|
+
required: ["id", "tokens"],
|
|
42
|
+
properties: { id: { type: "string" }, tokens: NUMBER }
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
hours: { type: ["array", "null"], items: NUMBER },
|
|
46
|
+
totals: {
|
|
47
|
+
type: "object",
|
|
48
|
+
additionalProperties: false,
|
|
49
|
+
required: ["input", "output", "cacheRead", "cacheWrite", "calls", "sessions", "activeDays"],
|
|
50
|
+
properties: {
|
|
51
|
+
input: NUMBER,
|
|
52
|
+
output: NUMBER,
|
|
53
|
+
cacheRead: NUMBER,
|
|
54
|
+
cacheWrite: NUMBER,
|
|
55
|
+
calls: NUMBER,
|
|
56
|
+
sessions: NUMBER,
|
|
57
|
+
activeDays: NUMBER
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
firstDay: { type: ["string", "null"] },
|
|
61
|
+
lastDay: { type: ["string", "null"] }
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
function count(value) {
|
|
65
|
+
const number = Number(value);
|
|
66
|
+
return Number.isFinite(number) && number > 0 ? number : 0;
|
|
67
|
+
}
|
|
68
|
+
function pending(error) {
|
|
69
|
+
return {
|
|
70
|
+
ready: false,
|
|
71
|
+
computedAt: null,
|
|
72
|
+
error,
|
|
73
|
+
days: [],
|
|
74
|
+
models: [],
|
|
75
|
+
hours: null,
|
|
76
|
+
totals: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, calls: 0, sessions: 0, activeDays: 0 },
|
|
77
|
+
firstDay: null,
|
|
78
|
+
lastDay: null
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function widgetUsageAnswer(value) {
|
|
82
|
+
const days = Array.isArray(value.days) ? value.days : [];
|
|
83
|
+
const totals = value.totals ?? {};
|
|
84
|
+
const hours = Array.isArray(value.hours) ? Array.from({ length: 24 }, (_, hour) => count(value.hours?.[hour])) : null;
|
|
85
|
+
return {
|
|
86
|
+
ready: true,
|
|
87
|
+
computedAt: typeof value.computedAt === "number" ? value.computedAt : null,
|
|
88
|
+
error: null,
|
|
89
|
+
days: days.map((day) => ({
|
|
90
|
+
date: String(day.date ?? ""),
|
|
91
|
+
input: count(day.input),
|
|
92
|
+
output: count(day.output),
|
|
93
|
+
cacheRead: count(day.cacheRead),
|
|
94
|
+
cacheWrite: count(day.cacheWrite),
|
|
95
|
+
calls: count(day.calls),
|
|
96
|
+
sessions: count(day.sessions),
|
|
97
|
+
...Array.isArray(day.hours) ? { hours: Array.from({ length: 24 }, (_, hour) => count(day.hours[hour])) } : {}
|
|
98
|
+
})),
|
|
99
|
+
models: (Array.isArray(value.models) ? value.models : []).map((model) => ({
|
|
100
|
+
id: String(model.id ?? ""),
|
|
101
|
+
tokens: count(model.tokens)
|
|
102
|
+
})),
|
|
103
|
+
hours,
|
|
104
|
+
totals: {
|
|
105
|
+
input: count(totals.input),
|
|
106
|
+
output: count(totals.output),
|
|
107
|
+
cacheRead: count(totals.cacheRead),
|
|
108
|
+
cacheWrite: count(totals.cacheWrite),
|
|
109
|
+
calls: count(totals.calls),
|
|
110
|
+
sessions: count(totals.sessions),
|
|
111
|
+
activeDays: count(totals.activeDays)
|
|
112
|
+
},
|
|
113
|
+
firstDay: typeof value.firstDay === "string" ? value.firstDay : null,
|
|
114
|
+
lastDay: typeof value.lastDay === "string" ? value.lastDay : null
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
async function waitForSummary(usage, signal) {
|
|
118
|
+
const deadline = Date.now() + WIDGET_USAGE_WAIT_MS;
|
|
119
|
+
let snapshot = usage.snapshot();
|
|
120
|
+
while (snapshot.value === null && !signal.aborted && Date.now() < deadline) {
|
|
121
|
+
usage.refresh();
|
|
122
|
+
await new Promise((resolve) => setTimeout(resolve, 250));
|
|
123
|
+
snapshot = usage.snapshot();
|
|
124
|
+
if (snapshot.value === null && snapshot.computing !== true && snapshot.error !== void 0) return snapshot;
|
|
125
|
+
}
|
|
126
|
+
return snapshot;
|
|
127
|
+
}
|
|
128
|
+
function registerWidgetUsage(ctx) {
|
|
129
|
+
const register = (scope) => {
|
|
130
|
+
const board = scope.get(WIDGET_BOARD_SERVICE);
|
|
131
|
+
if (board === void 0 || board.apiVersion !== WIDGET_BOARD_API_VERSION) return;
|
|
132
|
+
const usage = createUsage(ctx);
|
|
133
|
+
ctx.effect?.(() => {
|
|
134
|
+
usage.dispose();
|
|
135
|
+
});
|
|
136
|
+
board.registerCapability({
|
|
137
|
+
apiVersion: WIDGET_BOARD_API_VERSION,
|
|
138
|
+
provider: WIDGET_USAGE_PROVIDER,
|
|
139
|
+
id: WIDGET_USAGE_CAPABILITY,
|
|
140
|
+
title: { zh: "\u7528\u91CF\u6C47\u603B", en: "Usage roll-up" },
|
|
141
|
+
description: {
|
|
142
|
+
zh: "\u8BFB\u53D6\u672C\u63D2\u4EF6\u5DF2\u7ECF\u6298\u597D\u7684\u4F1A\u8BDD\u7528\u91CF\uFF1A\u6BCF\u5929\u7684\u5206\u6876\u3001\u6309\u5C0F\u65F6\u7684\u7ED3\u7B97\u6B21\u6570\u4E0E\u5404\u6A21\u578B\u7684 token \u603B\u91CF\u3002",
|
|
143
|
+
en: "Reads the session usage this plugin has already folded: per-day buckets, hourly settlements and per-model token totals."
|
|
144
|
+
},
|
|
145
|
+
permission: {},
|
|
146
|
+
input: WIDGET_USAGE_INPUT,
|
|
147
|
+
output: WIDGET_USAGE_OUTPUT,
|
|
148
|
+
timeoutMs: 14e3,
|
|
149
|
+
async call(_instance, _args, signal) {
|
|
150
|
+
const snapshot = await waitForSummary(usage, signal);
|
|
151
|
+
if (snapshot.value === null) return pending(snapshot.error ?? null);
|
|
152
|
+
return widgetUsageAnswer(snapshot.value);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
};
|
|
156
|
+
if (typeof ctx.inject === "function") ctx.inject([WIDGET_BOARD_SERVICE], register);
|
|
157
|
+
else register(ctx);
|
|
158
|
+
}
|
|
159
|
+
export {
|
|
160
|
+
WIDGET_USAGE_CAPABILITY,
|
|
161
|
+
WIDGET_USAGE_PROVIDER,
|
|
162
|
+
registerWidgetUsage,
|
|
163
|
+
widgetUsageAnswer
|
|
164
|
+
};
|
package/lib/prices.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"updatedAt": "2026-10-
|
|
4
|
-
"capturedAt": "2026-10-
|
|
3
|
+
"updatedAt": "2026-10-26",
|
|
4
|
+
"capturedAt": "2026-10-26T08:51:01.697Z",
|
|
5
5
|
"source": {
|
|
6
6
|
"zh": "https://api-docs.deepseek.com/zh-cn/quick_start/pricing/",
|
|
7
7
|
"en": "https://api-docs.deepseek.com/quick_start/pricing/"
|
|
@@ -227,6 +227,7 @@
|
|
|
227
227
|
"au.anthropic.claude-sonnet-4-5-20250929-v1:0": "3.3 0.33 16.5",
|
|
228
228
|
"au.anthropic.claude-sonnet-4-6": "3.3 0.33 16.5",
|
|
229
229
|
"au.anthropic.claude-sonnet-5": "2.2 0.22 11",
|
|
230
|
+
"au.anthropic.claude-sonnet-5-5": "2.2 0.11 11",
|
|
230
231
|
"auto": "0.85 0.85 1.55",
|
|
231
232
|
"auto-model-basic": "9.996 4.998 19.992",
|
|
232
233
|
"auto-model-premium": "9.996 4.998 19.992",
|
|
@@ -472,10 +473,10 @@
|
|
|
472
473
|
"deepseek-chat-v3.1": "0.25 0.13 0.95",
|
|
473
474
|
"deepseek-flash": "0.15 0.003 0.6",
|
|
474
475
|
"deepseek-flash-latest": "0.02 0.015 1",
|
|
475
|
-
"deepseek-latest": "0.
|
|
476
|
+
"deepseek-latest": "0.45 0.065 0.8",
|
|
476
477
|
"deepseek-ocr": "0.2 0.2 0.7",
|
|
477
478
|
"deepseek-ocr-2": "0.45985 0.0612 0.74875",
|
|
478
|
-
"deepseek-pro-latest": "0.
|
|
479
|
+
"deepseek-pro-latest": "0.2565 0.26 8",
|
|
479
480
|
"deepseek-r1": "0.648895 0.639855 2.39558",
|
|
480
481
|
"deepseek-r1-0528": "0.548833 0.35 2.249667",
|
|
481
482
|
"deepseek-r1-0528-qwen3-8b": "0.06 0.06 0.09",
|
|
@@ -513,23 +514,23 @@
|
|
|
513
514
|
"deepseek-v4-flash": "0.14 0.022 0.28",
|
|
514
515
|
"deepseek-v4-flash-0423": "0.14 0.028 0.28",
|
|
515
516
|
"deepseek-v4-flash-0423:thinking": "0.14 0.028 0.28",
|
|
516
|
-
"deepseek-v4-flash-0731": "0.
|
|
517
|
+
"deepseek-v4-flash-0731": "0.15 0.028 0.3",
|
|
517
518
|
"deepseek-v4-flash-0731-fast": "0.28 0.07 0.7",
|
|
518
519
|
"deepseek-v4-flash-0731-tee": "0.44 0.044 1.32",
|
|
519
|
-
"deepseek-v4-flash-0731:thinking": "0.
|
|
520
|
+
"deepseek-v4-flash-0731:thinking": "0.05 0.013 0.16",
|
|
520
521
|
"deepseek-v4-flash-0731@eu": "0.1995 0.0439 0.399",
|
|
521
522
|
"deepseek-v4-flash-el": "0.14 0.14 0.28",
|
|
522
523
|
"deepseek-v4-flash-fast": "0.28 0.07 0.56",
|
|
523
524
|
"deepseek-v4-flash-flex": "0.091 0.0182 0.182",
|
|
524
525
|
"deepseek-v4-flash-ga-260731": "0.4453 0.01484 1.3359",
|
|
525
|
-
"deepseek-v4-flash-latest": "0.
|
|
526
|
+
"deepseek-v4-flash-latest": "0.07375 0.028 0.2184",
|
|
526
527
|
"deepseek-v4-flash-speed": "0.14 0.028 0.28",
|
|
527
528
|
"deepseek-v4-flash-vision-exp": "0.2156 0.00686 0.6468",
|
|
528
529
|
"deepseek-v4-flash:thinking": "0.14 0.0028 0.28",
|
|
529
530
|
"deepseek-v4-pro": "1.32 0.13 3.2",
|
|
530
531
|
"deepseek-v4-pro-0423": "1.485 0.9 3.63",
|
|
531
|
-
"deepseek-v4-pro-0813": "1.32 0.
|
|
532
|
-
"deepseek-v4-pro-0813:thinking": "0.
|
|
532
|
+
"deepseek-v4-pro-0813": "1.32 0.045953 3.96",
|
|
533
|
+
"deepseek-v4-pro-0813:thinking": "0.45 0.065 0.8",
|
|
533
534
|
"deepseek-v4-pro-0813@eu": "1.75 0.44 3.5",
|
|
534
535
|
"deepseek-v4-pro-el": "1.67 1.67 3.33",
|
|
535
536
|
"deepseek-v4-pro-ga-260813": "1.3359 0.04453 4.00771",
|
|
@@ -551,7 +552,7 @@
|
|
|
551
552
|
"deepseek-v4.1-flash:1017": "0.15 0.003 0.6",
|
|
552
553
|
"deepseek-v4.1-flash:fast": "0.6 0.012 2.4",
|
|
553
554
|
"deepseek-v4.1-flash:peft:262144": "0.6 0.12 3.6",
|
|
554
|
-
"deepseek-v4.1-flash:thinking": "0.
|
|
555
|
+
"deepseek-v4.1-flash:thinking": "0.09 0.006 0.25",
|
|
555
556
|
"deepseek-v4.1-flash@eu": "0.5 0.05 1.5",
|
|
556
557
|
"deepseek-v4p1-flash": "0.3 0.006 1.2",
|
|
557
558
|
"deepseek-v4p1-flash-1017": "0.3 0.006 1.2",
|
|
@@ -780,7 +781,7 @@
|
|
|
780
781
|
"gemma-4-26b-a4b-it-musica": "0.12 0.06 0.38",
|
|
781
782
|
"gemma-4-26b-a4b-it-opusdistill": "0.12 0.06 0.38",
|
|
782
783
|
"gemma-4-26b-a4b-it-shadowsiren": "0.12 0.06 0.38",
|
|
783
|
-
"gemma-4-26b-a4b-it:thinking": "0.
|
|
784
|
+
"gemma-4-26b-a4b-it:thinking": "0.09 0.05 0.3",
|
|
784
785
|
"gemma-4-26b-a4b-meromero": "0.12 0.06 0.38",
|
|
785
786
|
"gemma-4-26b-a4b-meromero:thinking": "0.12 0.06 0.38",
|
|
786
787
|
"gemma-4-26b-a4b-uncensored": "0.15 0.075 0.7",
|
|
@@ -869,8 +870,8 @@
|
|
|
869
870
|
"glm-4.7-flash:thinking": "0.07 0.01 0.4",
|
|
870
871
|
"glm-4.7-flashx": "0.07 0.01 0.4",
|
|
871
872
|
"glm-4.7-maas": "0.6 0.06 2.2",
|
|
872
|
-
"glm-4.7-original": "0.
|
|
873
|
-
"glm-4.7-original:thinking": "0.
|
|
873
|
+
"glm-4.7-original": "0.4004 0.08008 1.9292",
|
|
874
|
+
"glm-4.7-original:thinking": "0.4004 0.08008 1.9292",
|
|
874
875
|
"glm-4.7:thinking": "0.4004 0.08008 1.9292",
|
|
875
876
|
"glm-5": "1 0.2 3.2",
|
|
876
877
|
"glm-5-1": "0.825 0.165 3.301",
|
|
@@ -905,7 +906,7 @@
|
|
|
905
906
|
"glm-5.2-ponytail-lite": "1.738325 0.4486 5.1589",
|
|
906
907
|
"glm-5.2-ponytail-ultra": "1.738325 0.4486 5.1589",
|
|
907
908
|
"glm-5.2-tee": "1.25 0.125 3.95",
|
|
908
|
-
"glm-5.2:thinking": "0.
|
|
909
|
+
"glm-5.2:thinking": "0.91 0.389 2.86",
|
|
909
910
|
"glm-5.2@eu": "1.2 0.26 4.2",
|
|
910
911
|
"glm-5.3": "1.4 0.26 4.4",
|
|
911
912
|
"glm-5.3-fast": "2.45 0.385 7.7",
|
|
@@ -937,8 +938,8 @@
|
|
|
937
938
|
"glm-5v-turbo": "1.2 0.24 4",
|
|
938
939
|
"glm-5v-turbo:thinking": "1.2 0.24 4",
|
|
939
940
|
"glm-fast-latest": "2.1 0.39 6.6",
|
|
940
|
-
"glm-flash-latest": "0.
|
|
941
|
-
"glm-latest": "0.6 0.1733 4
|
|
941
|
+
"glm-flash-latest": "0.09565 0.03 0.2879",
|
|
942
|
+
"glm-latest": "0.6 0.1733 1.4",
|
|
942
943
|
"glm-z1-9b-0414": "0.2 0.1 0.2",
|
|
943
944
|
"glm-z1-airx": "0.7 0.35 0.7",
|
|
944
945
|
"glm5.2": "2.31 2.31 6",
|
|
@@ -1273,7 +1274,7 @@
|
|
|
1273
1274
|
"kimi-k2.6-nitro": "0.275 0.275 1.1",
|
|
1274
1275
|
"kimi-k2.6-tee": "0.45 0.045 1.95",
|
|
1275
1276
|
"kimi-k2.6:peft:131072": "2.205 0.441 5.49",
|
|
1276
|
-
"kimi-k2.6:thinking": "0.
|
|
1277
|
+
"kimi-k2.6:thinking": "0.45 0.045 1.95",
|
|
1277
1278
|
"kimi-k2.6@eu": "0.95 0.95 4",
|
|
1278
1279
|
"kimi-k2.7-code": "0.95 0.19 4",
|
|
1279
1280
|
"kimi-k2.7-code-fast": "0.95 0.095 4",
|
|
@@ -1294,7 +1295,7 @@
|
|
|
1294
1295
|
"kimi-k3.1-pro-highspeed": "4 0.2 20",
|
|
1295
1296
|
"kimi-k3:fast": "6 0.6 30",
|
|
1296
1297
|
"kimi-k3@eu": "3 0.45 15",
|
|
1297
|
-
"kimi-latest": "1.
|
|
1298
|
+
"kimi-latest": "1.791 0.204 15",
|
|
1298
1299
|
"kloker": "0.23 0.23 1.16",
|
|
1299
1300
|
"kloker-integration-architect": "0.23 0.23 1.16",
|
|
1300
1301
|
"kloker-integration-developer": "0.23 0.23 1.16",
|
|
@@ -1471,6 +1472,7 @@
|
|
|
1471
1472
|
"minimax-m3-1-flash": "0.15 0.015 0.6",
|
|
1472
1473
|
"minimax-m3-preview": "0.3 0.06 1.2",
|
|
1473
1474
|
"minimax-m3.1-flash": "0.15 0.015 0.6",
|
|
1475
|
+
"minimax-m3.1-flash@eu": "0.3 0.07 1.2",
|
|
1474
1476
|
"minimax-m3:fast": "0.6 0.12 2.4",
|
|
1475
1477
|
"minimax-m3:thinking": "0.23 0.05 0.96",
|
|
1476
1478
|
"minimax-m3@eu": "0.4 0.1 2",
|
|
@@ -1569,6 +1571,14 @@
|
|
|
1569
1571
|
"moonshot-kimi-k2-instruct": "0.574 0.574 2.294",
|
|
1570
1572
|
"moonshot.kimi-k2-thinking": "0.6 0.6 2.5",
|
|
1571
1573
|
"moonshotai.kimi-k2.5": "0.6 0.6 3",
|
|
1574
|
+
"morph-dsv41flash": "0.12 0.008 0.8",
|
|
1575
|
+
"morph-dsv41flash-1017": "0.12 0.008 0.8",
|
|
1576
|
+
"morph-dsv4flash": "0.141953 0.035937 0.399625",
|
|
1577
|
+
"morph-glm52-744b": "1.19 0.1955 6",
|
|
1578
|
+
"morph-glm53-744b": "1.19 0.1955 6",
|
|
1579
|
+
"morph-glm53flash": "0.2 0.04 0.7",
|
|
1580
|
+
"morph-kimik3": "2.5 0.29 14",
|
|
1581
|
+
"morph-kimik3-fast": "6 0.6 22.5",
|
|
1572
1582
|
"morph-v3-fast": "0.8 0.8 1.2",
|
|
1573
1583
|
"morph-v3-large": "0.9 0.9 1.9",
|
|
1574
1584
|
"motif-3": "0.5 0.2 2",
|
|
@@ -1918,7 +1928,7 @@
|
|
|
1918
1928
|
"qwen3-vl-instruct": "0.2 0.11 0.88",
|
|
1919
1929
|
"qwen3-vl-plus": "0.2 0.04 1.6",
|
|
1920
1930
|
"qwen3.5-122b": "1.1215 1.1215 4.7103",
|
|
1921
|
-
"qwen3.5-122b-a10b": "0.
|
|
1931
|
+
"qwen3.5-122b-a10b": "0.29 0.29 2.345",
|
|
1922
1932
|
"qwen3.5-122b-a10b-fp8": "0.5 0.5 3.97",
|
|
1923
1933
|
"qwen3.5-122b-a10b:thinking": "0.26 0.103788 2.08",
|
|
1924
1934
|
"qwen3.5-27b": "0.28 0.265 2.28",
|
|
@@ -1949,7 +1959,7 @@
|
|
|
1949
1959
|
"qwen3.5-plus-20260420": "0.3 0.3 1.8",
|
|
1950
1960
|
"qwen3.5-plus:thinking": "0.4 0.04 2.4",
|
|
1951
1961
|
"qwen3.6": "0.04 0.02 0.35",
|
|
1952
|
-
"qwen3.6-27b": "0.438 0.3923 3.
|
|
1962
|
+
"qwen3.6-27b": "0.438 0.3923 3.195",
|
|
1953
1963
|
"qwen3.6-27b-tee": "0.25 0.025 2",
|
|
1954
1964
|
"qwen3.6-27b:thinking": "0.203 0.1015 2.24",
|
|
1955
1965
|
"qwen3.6-35b": "0.229112 0.098613 0.855375",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-claude-style",
|
|
3
3
|
"description": "Claude Code Desktop theme for DeepSeek Harness (dsh) web GUI — visual & interaction overhaul",
|
|
4
|
-
"version": "0.19.
|
|
4
|
+
"version": "0.19.4-dev.49",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/host/index.js",
|
|
7
7
|
"icon": "lib/claude-mark.svg",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|