dsh-context 0.24.0 → 0.25.2

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/lib/index.d.ts CHANGED
@@ -108,6 +108,12 @@ interface Snapshot {
108
108
  name: string;
109
109
  tokens: number;
110
110
  }[];
111
+ /**
112
+ * Cumulative image-block count over the COMPLETE session log (user uploads
113
+ * plus tool-result images) — never trimmed, like `cost`. Absent from older
114
+ * hosts; clients treat absence as zero.
115
+ */
116
+ images?: number;
111
117
  requests: RequestRecord[];
112
118
  events: ContextEventRecord[];
113
119
  /**
@@ -167,11 +173,11 @@ interface CostBucketTotals {
167
173
  /** Billed output tokens (reasoning included). */
168
174
  output: number;
169
175
  }
170
- /** One model family's totals split by DeepSeek's UTC pricing period. */
176
+ /** One model family's totals split by DeepSeek's pricing period (Beijing Time). */
171
177
  interface CostFamilyUsage {
172
- /** Peak windows: 01:00-04:00 and 06:00-10:00 UTC. */
178
+ /** Peak windows: 09:00-12:00 and 14:00-18:00 Beijing Time, weekdays only. */
173
179
  peak?: CostBucketTotals;
174
- /** All other hours (half the peak rate). */
180
+ /** All other hours plus all of Saturday/Sunday (half the peak rate). */
175
181
  off?: CostBucketTotals;
176
182
  }
177
183
  /**
@@ -327,6 +333,12 @@ interface TimelineState {
327
333
  * Absent until a v4-flash / v4-pro request reports usage.
328
334
  */
329
335
  cost?: SessionCostUsage;
336
+ /**
337
+ * Cumulative image-block count over the COMPLETE session log (user uploads
338
+ * plus tool-result images, nested blocks included) — running total, never
339
+ * trimmed, so the stats board's image cell stays whole-session like cost.
340
+ */
341
+ images: number;
330
342
  /** Newest `gone` among archive entries dropped by the retention bounds. */
331
343
  archiveFloor?: number;
332
344
  /**
package/lib/index.js CHANGED
@@ -231,6 +231,18 @@ function estimateSystem(text) {
231
231
  function estimateToolSchema(tool) {
232
232
  return Math.ceil(JSON.stringify(tool).length / CHARS_PER_TOKEN) + BLOCK_OVERHEAD;
233
233
  }
234
+ /**
235
+ * Count image blocks in a message payload, recursing into nested content
236
+ * (tool-result blocks carry their inner blocks) — feeds the stats board's
237
+ * whole-session image-file cell.
238
+ */
239
+ function imageCountOf(blocks) {
240
+ let count = 0;
241
+ if (!Array.isArray(blocks)) return 0;
242
+ for (const block of blocks) if (block.type === "image") count++;
243
+ else if (Array.isArray(block.content)) count += imageCountOf(block.content);
244
+ return count;
245
+ }
234
246
  function firstText(blocks) {
235
247
  if (!Array.isArray(blocks)) return "";
236
248
  for (const b of blocks) if (b.type === "text" && typeof b.text === "string" && b.text.trim() !== "") return b.text.replace(/\s+/g, " ").trim().slice(0, 80);
@@ -404,7 +416,8 @@ function createTimelineState() {
404
416
  requests: [],
405
417
  events: [],
406
418
  archived: [],
407
- callNames: {}
419
+ callNames: {},
420
+ images: 0
408
421
  };
409
422
  }
410
423
  function categoryOf(type, message) {
@@ -426,6 +439,7 @@ function archiveRemoved(st, removed, goneSeq) {
426
439
  }
427
440
  function applySurface(st, ev, type, data, message) {
428
441
  const cat = categoryOf(type, message ?? void 0);
442
+ st.images = st.images + imageCountOf(message?.content);
429
443
  const node = {
430
444
  seq: ev.seq,
431
445
  time: ev.time,
@@ -519,10 +533,17 @@ function costFamilyOf(model) {
519
533
  if (m.includes("pro")) return "pro";
520
534
  return null;
521
535
  }
522
- /** DeepSeek's UTC peak windows: 01:00-04:00 and 06:00-10:00 (off-peak is half price). */
536
+ /**
537
+ * DeepSeek's peak windows (Beijing Time, UTC+8): 09:00-12:00 and 14:00-18:00
538
+ * on weekdays; off-peak (half the peak rate) covers all other hours plus all
539
+ * of Saturday and Sunday.
540
+ */
523
541
  function isPeakUtc(time) {
524
- const h = new Date(time).getUTCHours();
525
- return h >= 1 && h < 4 || h >= 6 && h < 10;
542
+ const bj = new Date(time + 288e5);
543
+ const day = bj.getUTCDay();
544
+ if (day === 0 || day === 6) return false;
545
+ const h = bj.getUTCHours();
546
+ return h >= 9 && h < 12 || h >= 14 && h < 18;
526
547
  }
527
548
  /**
528
549
  * Fold one billed request into the session-cost totals, cloning along the
@@ -706,6 +727,7 @@ function buildTimelineView(state, bounds) {
706
727
  total: surfaceTotal + state.systemTokens + state.toolsTokens
707
728
  },
708
729
  toolList: state.toolList,
730
+ images: state.images,
709
731
  requests: state.requests.map((r) => ({ ...r })),
710
732
  events: state.events.map((e) => ({ ...e })),
711
733
  nodes: [],
@@ -862,6 +884,7 @@ const contextTimelineSchema = z.object({
862
884
  name: z.string(),
863
885
  tokens: z.number().int().nonnegative()
864
886
  }).strict()),
887
+ images: z.number().int().nonnegative().optional(),
865
888
  requests: z.array(requestRecordSchema),
866
889
  events: z.array(contextEventSchema),
867
890
  cost: z.object({
@@ -905,6 +928,7 @@ const timelineStateSchema = z.object({
905
928
  flash: costFamilySchema.optional(),
906
929
  pro: costFamilySchema.optional()
907
930
  }).strict().optional(),
931
+ images: z.number().int().nonnegative().optional(),
908
932
  archiveFloor: z.number().optional(),
909
933
  callNames: z.record(z.string(), z.string()),
910
934
  pendingShadowedSeqs: z.array(z.number()).optional()
@@ -940,7 +964,7 @@ function createContextTimelineDefinition(config) {
940
964
  },
941
965
  init: () => createTimelineState(),
942
966
  apply: (state, event) => applyTimeline(state, event, bounds),
943
- stateVersion: 6
967
+ stateVersion: 7
944
968
  };
945
969
  }
946
970
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-context",
3
- "version": "0.24.0",
3
+ "version": "0.25.2",
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": {
@@ -23,7 +23,9 @@
23
23
  "./package.json": "./package.json"
24
24
  },
25
25
  "files": [
26
- "lib",
26
+ "lib/client.js",
27
+ "lib/index.js",
28
+ "lib/index.d.ts",
27
29
  "cordis.patch.yml",
28
30
  "README.md",
29
31
  "LICENSE"
@@ -38,7 +40,7 @@
38
40
  "test": "npm run typecheck && vitest run",
39
41
  "release": "bash scripts/publish.sh",
40
42
  "hooks": "bash scripts/install-hooks.sh",
41
- "social-preview": "node docs/social-preview/generate.mjs"
43
+ "social-preview": "node docs/social-preview/generate.ts"
42
44
  },
43
45
  "dsh": {
44
46
  "bundle": {