dsh-context 0.50.0 → 0.51.0
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/README.md +3 -3
- package/lib/client.js +610 -260
- package/lib/index.d.ts +24 -17
- package/lib/index.js +76 -54
- package/package.json +6 -2
package/lib/index.d.ts
CHANGED
|
@@ -128,11 +128,12 @@ interface TimelineState {
|
|
|
128
128
|
*/
|
|
129
129
|
archived: SurfaceNode[];
|
|
130
130
|
/**
|
|
131
|
-
* Session-cost raw material: cumulative billed-token totals per
|
|
132
|
-
* model
|
|
133
|
-
* totals — never trimmed, so
|
|
134
|
-
*
|
|
135
|
-
*
|
|
131
|
+
* Session-cost raw material: cumulative billed-token totals per
|
|
132
|
+
* (provider, model), split into pricing periods for DeepSeek (see
|
|
133
|
+
* SessionCostUsage / CostModelUsage). Running totals — never trimmed, so
|
|
134
|
+
* the estimate always covers the COMPLETE session log even after the
|
|
135
|
+
* request/event retention bounds cut in. Absent until a usage-reporting
|
|
136
|
+
* request with a known model folds.
|
|
136
137
|
*/
|
|
137
138
|
cost?: SessionCostUsage;
|
|
138
139
|
/**
|
|
@@ -374,9 +375,9 @@ interface Snapshot {
|
|
|
374
375
|
requests: RequestRecord[];
|
|
375
376
|
events: ContextEventRecord[];
|
|
376
377
|
/**
|
|
377
|
-
* Cumulative session-cost raw material (per-
|
|
378
|
-
* token totals — see SessionCostUsage). Absent until a
|
|
379
|
-
*
|
|
378
|
+
* Cumulative session-cost raw material (per-provider, per-model billed
|
|
379
|
+
* token totals — see SessionCostUsage). Absent until a request with a
|
|
380
|
+
* known model reports usage.
|
|
380
381
|
*/
|
|
381
382
|
cost?: SessionCostUsage;
|
|
382
383
|
/**
|
|
@@ -573,22 +574,28 @@ interface TimingTotals {
|
|
|
573
574
|
/** Per-tool-name tallies behind the timing card's ranking (bounded). */
|
|
574
575
|
tools: Record<string, ToolTimingTotals>;
|
|
575
576
|
}
|
|
576
|
-
/**
|
|
577
|
-
|
|
577
|
+
/**
|
|
578
|
+
* One billed model's cumulative totals split by pricing period. Providers
|
|
579
|
+
* without period-based pricing book everything under `peak` (the list-price
|
|
580
|
+
* period); DeepSeek splits at fold time — peak windows bill at list price,
|
|
581
|
+
* off-peak (all other hours) at half.
|
|
582
|
+
*/
|
|
583
|
+
interface CostModelUsage {
|
|
578
584
|
peak?: CostBucketTotals;
|
|
579
585
|
off?: CostBucketTotals;
|
|
580
586
|
}
|
|
581
587
|
/**
|
|
582
588
|
* The session-cost estimate's raw material: cumulative provider-reported
|
|
583
|
-
* token totals
|
|
584
|
-
*
|
|
585
|
-
*
|
|
586
|
-
*
|
|
587
|
-
* usage.
|
|
589
|
+
* billed-token totals, keyed by the request envelope's DSH provider id (''
|
|
590
|
+
* when a log carries none) and then by its model id — the exact (provider,
|
|
591
|
+
* model) faces the Client's model-price book resolves (the models.dev
|
|
592
|
+
* registry, client/modelPrices.ts). Running totals per key; absent until a
|
|
593
|
+
* request with a known model reports usage.
|
|
588
594
|
*/
|
|
589
595
|
interface SessionCostUsage {
|
|
590
|
-
|
|
591
|
-
|
|
596
|
+
[provider: string]: {
|
|
597
|
+
[model: string]: CostModelUsage;
|
|
598
|
+
};
|
|
592
599
|
}
|
|
593
600
|
/** One model-visible message on the surface, with its heuristic token price. */
|
|
594
601
|
interface SurfaceNode {
|
package/lib/index.js
CHANGED
|
@@ -293,6 +293,29 @@ function resolveBounds(config) {
|
|
|
293
293
|
return Config.parse(config ?? {});
|
|
294
294
|
}
|
|
295
295
|
//#endregion
|
|
296
|
+
//#region src/shared/providers.ts
|
|
297
|
+
/**
|
|
298
|
+
* The provider-id seam between dsh request envelopes and the models.dev
|
|
299
|
+
* registry: client/cost.ts resolves price-book branches through it, and
|
|
300
|
+
* host/fold.ts uses the DeepSeek resolution to split the session-cost totals
|
|
301
|
+
* into peak/off-peak periods. Only the renames live here — an id absent
|
|
302
|
+
* from the table passes through verbatim.
|
|
303
|
+
*/
|
|
304
|
+
const MODELS_DEV_PROVIDER_IDS = {
|
|
305
|
+
"deepseek-official": "deepseek",
|
|
306
|
+
"kimi-coding": "moonshotai",
|
|
307
|
+
"minimax-cn": "minimax",
|
|
308
|
+
"zai-coding-cn": "zhipuai"
|
|
309
|
+
};
|
|
310
|
+
/** The models.dev provider id that prices a dsh provider (identity for unmapped ids). */
|
|
311
|
+
function modelsDevProviderOf(dshProviderId) {
|
|
312
|
+
return MODELS_DEV_PROVIDER_IDS[dshProviderId] ?? dshProviderId;
|
|
313
|
+
}
|
|
314
|
+
/** Whether a dsh provider prices through DeepSeek's period-based list (peak / half-price off-peak). */
|
|
315
|
+
function isDeepSeekProvider(dshProviderId) {
|
|
316
|
+
return modelsDevProviderOf(dshProviderId) === "deepseek";
|
|
317
|
+
}
|
|
318
|
+
//#endregion
|
|
296
319
|
//#region src/shared/estimate.ts
|
|
297
320
|
/**
|
|
298
321
|
* Token heuristics shared by the host fold and the client boundary — the
|
|
@@ -1274,31 +1297,16 @@ function tokenCountOf(value) {
|
|
|
1274
1297
|
return null;
|
|
1275
1298
|
}
|
|
1276
1299
|
/**
|
|
1277
|
-
*
|
|
1278
|
-
*
|
|
1279
|
-
*
|
|
1280
|
-
* here). The name must carry a DeepSeek marker (`v4` or `deepseek`) so a
|
|
1281
|
-
* foreign flash/pro-named model (gemini-2.0-flash) is never priced.
|
|
1282
|
-
*/
|
|
1283
|
-
function costFamilyOf(model) {
|
|
1284
|
-
if (model === void 0) return null;
|
|
1285
|
-
const m = model.toLowerCase();
|
|
1286
|
-
if (!m.includes("v4") && !m.includes("deepseek")) return null;
|
|
1287
|
-
if (m.includes("flash")) return "flash";
|
|
1288
|
-
if (m.includes("pro")) return "pro";
|
|
1289
|
-
return null;
|
|
1290
|
-
}
|
|
1291
|
-
/**
|
|
1292
|
-
* DeepSeek's peak windows (Beijing Time, UTC+8): 09:00-12:00 and 14:00-18:00
|
|
1293
|
-
* on weekdays; off-peak (half the peak rate) covers all other hours plus all
|
|
1294
|
-
* of Saturday and Sunday.
|
|
1300
|
+
* DeepSeek's peak windows (the official list: UTC 01:00–04:00 and 06:00–10:00,
|
|
1301
|
+
* Monday through Friday — Beijing Time 09:00–12:00 and 14:00–18:00). All other
|
|
1302
|
+
* hours, plus entire weekends, bill at the half-price off-peak rate.
|
|
1295
1303
|
*/
|
|
1296
1304
|
function isPeakUtc(time) {
|
|
1297
|
-
const
|
|
1298
|
-
const day =
|
|
1305
|
+
const at = new Date(time);
|
|
1306
|
+
const day = at.getUTCDay();
|
|
1299
1307
|
if (day === 0 || day === 6) return false;
|
|
1300
|
-
const h =
|
|
1301
|
-
return h >=
|
|
1308
|
+
const h = at.getUTCHours();
|
|
1309
|
+
return h >= 1 && h < 4 || h >= 6 && h < 10;
|
|
1302
1310
|
}
|
|
1303
1311
|
/**
|
|
1304
1312
|
* Fold one billed request into the session-cost totals, cloning along the
|
|
@@ -1306,29 +1314,42 @@ function isPeakUtc(time) {
|
|
|
1306
1314
|
* previous state — the apply contract never mutates it in place). The
|
|
1307
1315
|
* buckets arrive sanitized ({@link BilledUsage}), so the totals stay at the
|
|
1308
1316
|
* schemas' non-negative safe integers no matter what the provider reported.
|
|
1317
|
+
* The key is the request envelope's (provider, model) face — the exact
|
|
1318
|
+
* lookup the Client's model-price book resolves (models.dev). A request
|
|
1319
|
+
* without a provider still accumulates (under the '' key) and the Client
|
|
1320
|
+
* prices it when the model id is unambiguous; without a model there is
|
|
1321
|
+
* nothing to price. DeepSeek's period-based list splits the buckets
|
|
1322
|
+
* (peak windows at list price, all other hours half price); every other
|
|
1323
|
+
* provider books everything under the list-price period.
|
|
1309
1324
|
*/
|
|
1310
1325
|
function accumulateCost(st, time, usage) {
|
|
1311
|
-
const
|
|
1312
|
-
if (
|
|
1313
|
-
const
|
|
1314
|
-
const
|
|
1315
|
-
const
|
|
1316
|
-
const
|
|
1326
|
+
const model = st.model;
|
|
1327
|
+
if (model === void 0) return;
|
|
1328
|
+
const provider = st.provider ?? "";
|
|
1329
|
+
const period = isDeepSeekProvider(provider) && !isPeakUtc(time) ? "off" : "peak";
|
|
1330
|
+
const models = st.cost?.[provider] ?? {};
|
|
1331
|
+
const periods = models[model] ?? {};
|
|
1332
|
+
const b = periods[period] ?? {
|
|
1317
1333
|
uncached: 0,
|
|
1318
1334
|
cacheRead: 0,
|
|
1319
1335
|
cacheWrite: 0,
|
|
1320
1336
|
output: 0
|
|
1321
1337
|
};
|
|
1322
|
-
const
|
|
1323
|
-
|
|
1338
|
+
const nextPeriods = { ...periods };
|
|
1339
|
+
nextPeriods[period] = {
|
|
1324
1340
|
uncached: b.uncached + usage.input,
|
|
1325
1341
|
cacheRead: b.cacheRead + usage.cacheRead,
|
|
1326
1342
|
cacheWrite: b.cacheWrite + usage.cacheWrite,
|
|
1327
1343
|
output: b.output + usage.output
|
|
1328
1344
|
};
|
|
1329
|
-
const
|
|
1330
|
-
|
|
1331
|
-
|
|
1345
|
+
const nextModels = {
|
|
1346
|
+
...models,
|
|
1347
|
+
[model]: nextPeriods
|
|
1348
|
+
};
|
|
1349
|
+
st.cost = {
|
|
1350
|
+
...st.cost ?? {},
|
|
1351
|
+
[provider]: nextModels
|
|
1352
|
+
};
|
|
1332
1353
|
}
|
|
1333
1354
|
/**
|
|
1334
1355
|
* Advance the fold over ONE committed session event under the projection
|
|
@@ -1791,18 +1812,18 @@ function headFieldsOf(state) {
|
|
|
1791
1812
|
archive: []
|
|
1792
1813
|
};
|
|
1793
1814
|
if (state.cost !== void 0) {
|
|
1794
|
-
const copyFam = (f) => {
|
|
1795
|
-
if (f === void 0) return void 0;
|
|
1796
|
-
const out = {};
|
|
1797
|
-
if (f.peak !== void 0) out.peak = { ...f.peak };
|
|
1798
|
-
if (f.off !== void 0) out.off = { ...f.off };
|
|
1799
|
-
return out;
|
|
1800
|
-
};
|
|
1801
1815
|
const cost = {};
|
|
1802
|
-
const
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1816
|
+
for (const provider in state.cost) {
|
|
1817
|
+
const models = {};
|
|
1818
|
+
for (const model in state.cost[provider]) {
|
|
1819
|
+
const periods = state.cost[provider][model];
|
|
1820
|
+
const copy = {};
|
|
1821
|
+
if (periods.peak !== void 0) copy.peak = { ...periods.peak };
|
|
1822
|
+
if (periods.off !== void 0) copy.off = { ...periods.off };
|
|
1823
|
+
models[model] = copy;
|
|
1824
|
+
}
|
|
1825
|
+
cost[provider] = models;
|
|
1826
|
+
}
|
|
1806
1827
|
result.cost = cost;
|
|
1807
1828
|
}
|
|
1808
1829
|
if (state.timing !== void 0) {
|
|
@@ -2340,10 +2361,12 @@ const costBucketsSchema = z.object({
|
|
|
2340
2361
|
cacheWrite: z.number().int().nonnegative(),
|
|
2341
2362
|
output: z.number().int().nonnegative()
|
|
2342
2363
|
}).strict();
|
|
2343
|
-
const
|
|
2364
|
+
const costModelSchema = z.object({
|
|
2344
2365
|
peak: costBucketsSchema.optional(),
|
|
2345
2366
|
off: costBucketsSchema.optional()
|
|
2346
2367
|
}).strict();
|
|
2368
|
+
const costModelsSchema = z.record(z.string(), costModelSchema);
|
|
2369
|
+
const costUsageSchema = z.record(z.string(), costModelsSchema);
|
|
2347
2370
|
const toolTimingSchema = z.object({
|
|
2348
2371
|
calls: z.number().int().nonnegative(),
|
|
2349
2372
|
ms: z.number().nonnegative()
|
|
@@ -2402,10 +2425,7 @@ const contextTimelineSchema = z.object({
|
|
|
2402
2425
|
detailRev: z.number().int().nonnegative().optional(),
|
|
2403
2426
|
requests: z.array(requestRecordSchema).optional(),
|
|
2404
2427
|
events: z.array(contextEventSchema).optional(),
|
|
2405
|
-
cost:
|
|
2406
|
-
flash: costFamilySchema.optional(),
|
|
2407
|
-
pro: costFamilySchema.optional()
|
|
2408
|
-
}).strict().optional(),
|
|
2428
|
+
cost: costUsageSchema.optional(),
|
|
2409
2429
|
timing: timingTotalsSchema.optional(),
|
|
2410
2430
|
systems: z.array(systemPromptNodeSchema).optional(),
|
|
2411
2431
|
nodes: z.array(surfaceNodeSchema).optional(),
|
|
@@ -2441,10 +2461,7 @@ const timelineStateSchema = z.object({
|
|
|
2441
2461
|
requests: z.array(requestRecordSchema),
|
|
2442
2462
|
events: z.array(contextEventSchema),
|
|
2443
2463
|
archived: z.array(surfaceNodeSchema),
|
|
2444
|
-
cost:
|
|
2445
|
-
flash: costFamilySchema.optional(),
|
|
2446
|
-
pro: costFamilySchema.optional()
|
|
2447
|
-
}).strict().optional(),
|
|
2464
|
+
cost: costUsageSchema.optional(),
|
|
2448
2465
|
archiveFloor: z.number().optional(),
|
|
2449
2466
|
timing: timingTotalsSchema.optional(),
|
|
2450
2467
|
humanInputs: z.number().int().nonnegative().optional(),
|
|
@@ -2522,7 +2539,7 @@ function createContextTimelineDefinition(config, slim) {
|
|
|
2522
2539
|
},
|
|
2523
2540
|
init: () => createTimelineState(),
|
|
2524
2541
|
apply: (state, event) => applyTimeline(state, event, bounds),
|
|
2525
|
-
stateVersion:
|
|
2542
|
+
stateVersion: 18
|
|
2526
2543
|
};
|
|
2527
2544
|
}
|
|
2528
2545
|
//#endregion
|
|
@@ -2625,6 +2642,11 @@ const SettingsSchema = z$1.object({
|
|
|
2625
2642
|
]).default("all").loose(),
|
|
2626
2643
|
defaultGranularity: z$1.union(["step", "turn"]).default("step"),
|
|
2627
2644
|
defaultTrendMode: z$1.union(["total", "delta"]).default("total").loose(),
|
|
2645
|
+
defaultToolSort: z$1.union([
|
|
2646
|
+
"size",
|
|
2647
|
+
"count",
|
|
2648
|
+
"name"
|
|
2649
|
+
]).default("count").loose(),
|
|
2628
2650
|
defaultFileSort: z$1.union([
|
|
2629
2651
|
"count",
|
|
2630
2652
|
"latest",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-context",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.51.0",
|
|
4
4
|
"description": "A DeepSeek Harness plugin for context insight and management, with context dashboard and context command, for understanding how the context is made of, and how it evolves.",
|
|
5
5
|
"author": "bowenliang123",
|
|
6
6
|
"repository": {
|
|
@@ -109,7 +109,10 @@
|
|
|
109
109
|
"@deepseek-ai/dsh-settings": "0.1.2-rc.1",
|
|
110
110
|
"@deepseek-ai/dsh-util-workspace-path": "0.1.5-rc.1",
|
|
111
111
|
"@deepseek-ai/schemastery": "^3.18.2",
|
|
112
|
+
"@opencode-ai/models": "^0.0.72",
|
|
112
113
|
"@stylistic/eslint-plugin": "^5.10.0",
|
|
114
|
+
"@tailwindcss/node": "4.3.3",
|
|
115
|
+
"@tailwindcss/oxide": "4.3.3",
|
|
113
116
|
"@types/node": "^26.2.0",
|
|
114
117
|
"@types/react": "^18.3.31",
|
|
115
118
|
"@types/react-dom": "^18.3.7",
|
|
@@ -117,12 +120,13 @@
|
|
|
117
120
|
"eslint-plugin-sonarjs": "^4.2.0",
|
|
118
121
|
"husky": "^9.1.7",
|
|
119
122
|
"jsdom": "^30.0.1",
|
|
120
|
-
"lightningcss": "
|
|
123
|
+
"lightningcss": "1.32.0",
|
|
121
124
|
"oxlint": "1.82.0",
|
|
122
125
|
"oxlint-tsgolint": "7.0.2001",
|
|
123
126
|
"playwright-core": "^1.62.1",
|
|
124
127
|
"react": "^18.3.1",
|
|
125
128
|
"react-dom": "^18.3.1",
|
|
129
|
+
"tailwindcss": "4.3.3",
|
|
126
130
|
"tsdown": "^0.23.0",
|
|
127
131
|
"typescript": "^7.0.2",
|
|
128
132
|
"vitest": "^4.1.11",
|