dsh-context 0.67.0 → 0.68.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/lib/index.d.ts CHANGED
@@ -221,6 +221,8 @@ type DefaultToolSort = 'size' | 'count' | 'name';
221
221
  type DefaultPlacement = 'all' | 'tab' | 'sidebar';
222
222
  type InsightsEntry = 'show' | 'hide';
223
223
  type DefaultDurationCurve = 'show' | 'hide';
224
+ /** Whether the Fleet conversation tab is served. */
225
+ type FleetTab = 'show' | 'hide';
224
226
  interface PluginSettings {
225
227
  defaultPlacement: DefaultPlacement;
226
228
  defaultGranularity: DefaultGranularity;
@@ -230,6 +232,7 @@ interface PluginSettings {
230
232
  defaultFileSort: DefaultFileSort;
231
233
  insightsEntry: InsightsEntry;
232
234
  defaultDurationCurve: DefaultDurationCurve;
235
+ fleetTab: FleetTab;
233
236
  }
234
237
  interface Snapshot {
235
238
  ok: boolean;
@@ -559,6 +562,7 @@ export declare const Config: z$1<Schemastery.ObjectS<NoInfer<{
559
562
  defaultFileSort: z$1<"count" | "latest" | "path", "count" | "latest" | "path", "defined">;
560
563
  insightsEntry: z$1<"hide" | "show", "hide" | "show", "defined">;
561
564
  defaultDurationCurve: z$1<"hide" | "show", "hide" | "show", "defined">;
565
+ fleetTab: z$1<"hide" | "show", "hide" | "show", "defined">;
562
566
  }>>, Schemastery.ObjectT<NoInfer<{
563
567
  maxRequestSteps: z$1<number, number, "defined">;
564
568
  maxKeptTurns: z$1<number, number, "defined">;
@@ -574,6 +578,7 @@ export declare const Config: z$1<Schemastery.ObjectS<NoInfer<{
574
578
  defaultFileSort: z$1<"count" | "latest" | "path", "count" | "latest" | "path", "defined">;
575
579
  insightsEntry: z$1<"hide" | "show", "hide" | "show", "defined">;
576
580
  defaultDurationCurve: z$1<"hide" | "show", "hide" | "show", "defined">;
581
+ fleetTab: z$1<"hide" | "show", "hide" | "show", "defined">;
577
582
  }>>, "plain">;
578
583
  //#endregion
579
584
  //#region src/host/index.d.ts
package/lib/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  /**
2
- * dsh-context v0.67.0
2
+ * dsh-context v0.68.0
3
3
  * 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.
4
4
  * @author bowenliang123
5
5
  * @license Apache-2.0
6
6
  * @homepage https://github.com/bowenliang123/dsh-context
7
- * @built 2026-10-10T10:12:42+00:00
8
- * @commit df136da57dac
9
- * @commit-date 2026-10-10T18:10:23+08:00
7
+ * @built 2026-10-11T02:40:54+00:00
8
+ * @commit 425fd2e7b82e
9
+ * @commit-date 2026-10-11T10:37:14+08:00
10
10
  */
11
11
 
12
12
  import { createRequire } from "node:module";
@@ -946,7 +946,7 @@ function removeSurfaceSeqs(st, claimed, goneSeq) {
946
946
  st.surface = kept;
947
947
  return removed;
948
948
  }
949
- function messageOf$1(data) {
949
+ function messageOf$2(data) {
950
950
  const message = data?.message;
951
951
  return message !== null && typeof message === "object" ? message : null;
952
952
  }
@@ -1127,7 +1127,7 @@ function applyTimeline(state, event, bounds) {
1127
1127
  pushSystem(s, {
1128
1128
  seq: event.seq,
1129
1129
  time: event.time,
1130
- tokens: estimateSystemContent(messageOf$1(data)?.content)
1130
+ tokens: estimateSystemContent(messageOf$2(data)?.content)
1131
1131
  });
1132
1132
  break;
1133
1133
  }
@@ -1284,7 +1284,7 @@ function applyTimeline(state, event, bounds) {
1284
1284
  case "user/message":
1285
1285
  case "developer/message": {
1286
1286
  const developer = event.type === "developer/message";
1287
- const msg = developer ? messageOf$1(data) : deriveEventMessage(event);
1287
+ const msg = developer ? messageOf$2(data) : deriveEventMessage(event);
1288
1288
  if (developer && (msg === null || !Array.isArray(msg.content))) return state;
1289
1289
  const s = ensure([
1290
1290
  "surface",
@@ -1557,7 +1557,8 @@ const Config = z$1.object({
1557
1557
  "path"
1558
1558
  ]).default("count").loose()),
1559
1559
  insightsEntry: volatileField(z$1.union(["show", "hide"]).default("show").loose()),
1560
- defaultDurationCurve: volatileField(z$1.union(["show", "hide"]).default("show").loose())
1560
+ defaultDurationCurve: volatileField(z$1.union(["show", "hide"]).default("show").loose()),
1561
+ fleetTab: volatileField(z$1.union(["show", "hide"]).default("show").loose())
1561
1562
  });
1562
1563
  function resolveBounds(config) {
1563
1564
  const resolved = Config(config ?? {});
@@ -2185,7 +2186,7 @@ function createToolAttribution(ctx) {
2185
2186
  }
2186
2187
  //#endregion
2187
2188
  //#region src/host/record.ts
2188
- function asRecord(value) {
2189
+ function asRecord$1(value) {
2189
2190
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
2190
2191
  }
2191
2192
  //#endregion
@@ -2226,9 +2227,9 @@ function deepseekSectionOf(ctx) {
2226
2227
  if (!Array.isArray(rows)) return null;
2227
2228
  let shaped = null;
2228
2229
  for (const row of rows) try {
2229
- const record = asRecord(row);
2230
+ const record = asRecord$1(row);
2230
2231
  if (record === null) continue;
2231
- const value = asRecord(record.value);
2232
+ const value = asRecord$1(record.value);
2232
2233
  if (value === null || typeof value.apiKeyEnv !== "string" || value.apiKeyEnv === "") continue;
2233
2234
  if (record.ns === DEEPSEEK_SETTINGS_NS || record.ns === "llm-deepseek-api-key") return value;
2234
2235
  shaped ??= value;
@@ -2261,12 +2262,12 @@ async function resolveFacts(ctx) {
2261
2262
  };
2262
2263
  }
2263
2264
  function balanceOfPayload(value) {
2264
- const data = asRecord(value);
2265
+ const data = asRecord$1(value);
2265
2266
  if (data === null) return null;
2266
2267
  const infos = Array.isArray(data.balance_infos) ? data.balance_infos : [];
2267
2268
  const balances = [];
2268
2269
  for (const info of infos) try {
2269
- const entry = asRecord(info);
2270
+ const entry = asRecord$1(info);
2270
2271
  if (entry === null) continue;
2271
2272
  const currency = entry.currency;
2272
2273
  const granted = amountOf(entry.granted_balance);
@@ -2359,7 +2360,7 @@ const BACKFILL_ROUTE = "/api/dsh-context/backfill";
2359
2360
  const YIELD_MS = 100;
2360
2361
  const UNSUPPORTED_FORMAT = "SessionFormatUnsupported";
2361
2362
  function headerOf(record) {
2362
- const header = asRecord(asRecord(record)?.header);
2363
+ const header = asRecord$1(asRecord$1(record)?.header);
2363
2364
  if (header === null) return null;
2364
2365
  if (typeof header.id !== "string" || header.id === "") return null;
2365
2366
  return header;
@@ -2367,7 +2368,7 @@ function headerOf(record) {
2367
2368
  const PROBE_KEYS = ["contextActivity", "contextTimeline"];
2368
2369
  function servesRows(cache, header) {
2369
2370
  try {
2370
- const values = asRecord(asRecord(cache.cachedSnapshot(header, PROBE_KEYS))?.values);
2371
+ const values = asRecord$1(asRecord$1(cache.cachedSnapshot(header, PROBE_KEYS))?.values);
2371
2372
  return values !== null && values.contextActivity !== void 0 && values.contextTimeline !== void 0;
2372
2373
  } catch {
2373
2374
  return false;
@@ -2377,7 +2378,7 @@ async function readColdLog(persistence, id, signal) {
2377
2378
  const handle = await persistence.open(id, "read", { signal });
2378
2379
  let events;
2379
2380
  try {
2380
- const result = asRecord(await handle.read(0, void 0, { signal }))?.events;
2381
+ const result = asRecord$1(await handle.read(0, void 0, { signal }))?.events;
2381
2382
  events = Array.isArray(result) ? result : [];
2382
2383
  } catch (error) {
2383
2384
  try {
@@ -2402,12 +2403,12 @@ function isLive(sessions, id) {
2402
2403
  }
2403
2404
  function isUnsupportedFormat(error) {
2404
2405
  try {
2405
- return String(asRecord(error)?.name).startsWith(UNSUPPORTED_FORMAT);
2406
+ return String(asRecord$1(error)?.name).startsWith(UNSUPPORTED_FORMAT);
2406
2407
  } catch {
2407
2408
  return false;
2408
2409
  }
2409
2410
  }
2410
- function messageOf(error) {
2411
+ function messageOf$1(error) {
2411
2412
  try {
2412
2413
  return String(error);
2413
2414
  } catch {
@@ -2438,13 +2439,13 @@ function watchActivityBackfill(ctx, coldReads = makeColdReadGate()) {
2438
2439
  "sessions"
2439
2440
  ], (raw) => {
2440
2441
  const injected = raw;
2441
- const query = asRecord(injected.sessionQuery);
2442
- const cache = asRecord(injected.sessionProjectionCache);
2443
- const persistence = asRecord(injected.sessionPersistence);
2442
+ const query = asRecord$1(injected.sessionQuery);
2443
+ const cache = asRecord$1(injected.sessionProjectionCache);
2444
+ const persistence = asRecord$1(injected.sessionPersistence);
2444
2445
  if (query === null || typeof query.listSessions !== "function") return;
2445
2446
  if (cache === null || typeof cache.cachedSnapshot !== "function" || typeof cache.coldSnapshot !== "function") return;
2446
2447
  if (persistence === null || typeof persistence.open !== "function") return;
2447
- const sessions = asRecord(injected.sessions);
2448
+ const sessions = asRecord$1(injected.sessions);
2448
2449
  const abort = new AbortController();
2449
2450
  const run = async () => {
2450
2451
  const listed = await query.listSessions(abort.signal);
@@ -2471,8 +2472,8 @@ function watchActivityBackfill(ctx, coldReads = makeColdReadGate()) {
2471
2472
  } catch (error) {
2472
2473
  if (isUnsupportedFormat(error)) {
2473
2474
  refused++;
2474
- ctx.logger.debug(`dsh-context: projection backfill skipped "${header.id}" (${messageOf(error)})`);
2475
- } else ctx.logger.warn(`dsh-context: projection backfill skipped "${header.id}" (${messageOf(error)})`);
2475
+ ctx.logger.debug(`dsh-context: projection backfill skipped "${header.id}" (${messageOf$1(error)})`);
2476
+ } else ctx.logger.warn(`dsh-context: projection backfill skipped "${header.id}" (${messageOf$1(error)})`);
2476
2477
  }
2477
2478
  await new Promise((resolve) => setTimeout(resolve, YIELD_MS));
2478
2479
  }
@@ -2482,7 +2483,7 @@ function watchActivityBackfill(ctx, coldReads = makeColdReadGate()) {
2482
2483
  };
2483
2484
  launch = () => {
2484
2485
  run().catch((error) => {
2485
- if (!abort.signal.aborted) ctx.logger.warn(`dsh-context: projection backfill stopped early (${messageOf(error)})`);
2486
+ if (!abort.signal.aborted) ctx.logger.warn(`dsh-context: projection backfill stopped early (${messageOf$1(error)})`);
2486
2487
  });
2487
2488
  };
2488
2489
  tryLaunch();
@@ -2494,11 +2495,11 @@ function watchActivityBackfill(ctx, coldReads = makeColdReadGate()) {
2494
2495
  for (const fiber of [routeFiber, runnerFiber]) fiber?.dispose?.();
2495
2496
  };
2496
2497
  }
2497
- function reply(value) {
2498
+ function reply$1(value) {
2498
2499
  return Response.json(value, { headers: { "cache-control": "no-store" } });
2499
2500
  }
2500
- function failure(code, message) {
2501
- return reply({
2501
+ function failure$1(code, message) {
2502
+ return reply$1({
2502
2503
  ok: false,
2503
2504
  error: {
2504
2505
  code,
@@ -2519,29 +2520,29 @@ function watchDetailChannel(ctx, bounds, coldReads = makeColdReadGate()) {
2519
2520
  const body = await request.json();
2520
2521
  sessionId = body !== null && typeof body === "object" ? body.sessionId : void 0;
2521
2522
  } catch {
2522
- return failure("dsh-context/bad-request", "body is not JSON");
2523
+ return failure$1("dsh-context/bad-request", "body is not JSON");
2523
2524
  }
2524
- if (typeof sessionId !== "string" || sessionId === "") return failure("dsh-context/bad-request", "missing sessionId");
2525
+ if (typeof sessionId !== "string" || sessionId === "") return failure$1("dsh-context/bad-request", "missing sessionId");
2525
2526
  try {
2526
2527
  const session = getSession(sessionId);
2527
2528
  if (session !== void 0 && session !== null) {
2528
2529
  const state = projections.stateOf(session, "contextTimeline");
2529
- if (state === void 0) return reply({
2530
+ if (state === void 0) return reply$1({
2530
2531
  ok: true,
2531
2532
  value: null
2532
2533
  });
2533
- return reply({
2534
+ return reply$1({
2534
2535
  ok: true,
2535
2536
  value: buildTimelineDetail(state, bounds)
2536
2537
  });
2537
2538
  }
2538
2539
  const query = ctx.get("sessionQuery");
2539
2540
  const observe = typeof query?.observeSession === "function" ? query.observeSession.bind(query) : void 0;
2540
- if (observe === void 0) return reply({
2541
+ if (observe === void 0) return reply$1({
2541
2542
  ok: true,
2542
2543
  value: null
2543
2544
  });
2544
- return reply({
2545
+ return reply$1({
2545
2546
  ok: true,
2546
2547
  value: await coldReads.admit(async () => {
2547
2548
  const observation = await observe(sessionId, { projectionMode: "none" });
@@ -2558,7 +2559,7 @@ function watchDetailChannel(ctx, bounds, coldReads = makeColdReadGate()) {
2558
2559
  }) ?? null
2559
2560
  });
2560
2561
  } catch (err) {
2561
- return failure("gateway/internal", err instanceof Error ? err.message : String(err));
2562
+ return failure$1("gateway/internal", err instanceof Error ? err.message : String(err));
2562
2563
  }
2563
2564
  };
2564
2565
  if (!registerPostRoute(c, c.get("connection"), "/api/dsh-context/detail", handler, "dsh-context: detail route")) return;
@@ -2738,6 +2739,237 @@ function createFallbackActivityDefinition() {
2738
2739
  return fallbackDefinition("contextActivity", contextActivitySchema, { days: {} });
2739
2740
  }
2740
2741
  //#endregion
2742
+ //#region src/host/fleet.ts
2743
+ const FLEET_ROUTE = "/api/dsh-context/fleet";
2744
+ const MESSAGES_MAX = 40;
2745
+ const MESSAGE_TEXT_MAX = 400;
2746
+ const PROMPT_TEXT_MAX = 1600;
2747
+ const REPLY_TEXT_MAX = 300;
2748
+ function reply(value) {
2749
+ return Response.json(value, { headers: { "cache-control": "no-store" } });
2750
+ }
2751
+ function failure(code, message) {
2752
+ return reply({
2753
+ ok: false,
2754
+ error: {
2755
+ code,
2756
+ message
2757
+ }
2758
+ });
2759
+ }
2760
+ function asRecord(value) {
2761
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
2762
+ }
2763
+ function textOfContent(content) {
2764
+ if (!Array.isArray(content)) return "";
2765
+ let out = "";
2766
+ for (const block of content) {
2767
+ const text = asRecord(block)?.text;
2768
+ if (typeof text === "string") out += text;
2769
+ }
2770
+ return out;
2771
+ }
2772
+ const REMINDER_PREFIX = /^\s*<system-reminder>[\s\S]*?<\/system-reminder>\s*/;
2773
+ function clip(text, max) {
2774
+ return text.length > max ? {
2775
+ text: text.slice(0, max) + "…",
2776
+ cut: true
2777
+ } : {
2778
+ text,
2779
+ cut: false
2780
+ };
2781
+ }
2782
+ function descriptorOf(data) {
2783
+ const mode = data.mode;
2784
+ if (mode !== "one-shot" && mode !== "continuable") return null;
2785
+ const out = { mode };
2786
+ for (const key of [
2787
+ "label",
2788
+ "provider",
2789
+ "agentProvider",
2790
+ "agentModel",
2791
+ "persona"
2792
+ ]) {
2793
+ const value = data[key];
2794
+ if (typeof value === "string" && value !== "") out[key] = value;
2795
+ }
2796
+ return out;
2797
+ }
2798
+ const MAILBOX_PREFIX = /^Team message \S+ from [^:]{1,64}:\s*/;
2799
+ const RELAY_PREFIX = /^(?:Agent \S+ sent a message: |Team message from [^:\n]{1,64}:\s*)/;
2800
+ function messageOf(seq, time, data) {
2801
+ const source = asRecord(data.source);
2802
+ const kind = source?.kind;
2803
+ let message = null;
2804
+ if (kind === "agent-message" || kind === "team-message") {
2805
+ let text = textOfContent(data.content);
2806
+ text = text.replace(kind === "team-message" ? MAILBOX_PREFIX : RELAY_PREFIX, "");
2807
+ if (text.trim() === "") return null;
2808
+ message = {
2809
+ seq,
2810
+ time,
2811
+ kind: kind === "agent-message" ? "relay" : "mailbox",
2812
+ text
2813
+ };
2814
+ const from = kind === "agent-message" ? source?.senderSessionId : source?.senderId;
2815
+ if (typeof from === "string" && from !== "") message.from = from;
2816
+ const fromName = source?.senderName;
2817
+ if (typeof fromName === "string" && fromName !== "") message.fromName = fromName;
2818
+ } else if (kind === "subagent-settled") {
2819
+ const summary = source?.summary;
2820
+ const text = typeof summary === "string" && summary.trim() !== "" ? summary : textOfContent(data.content);
2821
+ if (text.trim() === "") return null;
2822
+ message = {
2823
+ seq,
2824
+ time,
2825
+ kind: "settled",
2826
+ text
2827
+ };
2828
+ const from = source?.senderSessionId;
2829
+ if (typeof from === "string" && from !== "") message.from = from;
2830
+ }
2831
+ if (message === null) return null;
2832
+ const cut = clip(message.text, MESSAGE_TEXT_MAX);
2833
+ message.text = cut.text;
2834
+ return message;
2835
+ }
2836
+ function isPlainPrompt(source) {
2837
+ if (source === null) return true;
2838
+ return source.kind === "user";
2839
+ }
2840
+ function rosterMemberOf(data) {
2841
+ const member = asRecord(data.member);
2842
+ if (member === null) return null;
2843
+ if (typeof member.name !== "string" || member.name === "") return null;
2844
+ const out = {
2845
+ name: member.name,
2846
+ description: typeof member.description === "string" ? member.description : ""
2847
+ };
2848
+ if (typeof member.provider === "string" && member.provider !== "") out.provider = member.provider;
2849
+ if (member.context === "fresh" || member.context === "fork") out.context = member.context;
2850
+ return out;
2851
+ }
2852
+ function lastReplyOf(events) {
2853
+ for (let i = events.length - 1; i >= 0; i--) {
2854
+ const ev = asRecord(events[i]);
2855
+ if (ev === null || ev.type !== "assistant/message") continue;
2856
+ const content = asRecord(asRecord(ev.data)?.message)?.content;
2857
+ if (!Array.isArray(content)) continue;
2858
+ let text = "";
2859
+ for (const block of content) {
2860
+ const b = asRecord(block);
2861
+ if (b?.type === "text" && typeof b.text === "string") text += b.text;
2862
+ }
2863
+ if (text.trim() === "") continue;
2864
+ const time = typeof ev.time === "number" && Number.isFinite(ev.time) ? ev.time : 0;
2865
+ const cut = clip(text, REPLY_TEXT_MAX);
2866
+ return {
2867
+ time,
2868
+ text: cut.text,
2869
+ cut: cut.cut
2870
+ };
2871
+ }
2872
+ return null;
2873
+ }
2874
+ function fleetDetailOfEvents(events) {
2875
+ let descriptor;
2876
+ let initialPrompt;
2877
+ let truncated = false;
2878
+ const messages = [];
2879
+ const roster = new Map();
2880
+ for (const entry of events) {
2881
+ const ev = asRecord(entry);
2882
+ if (ev === null) continue;
2883
+ const type = ev.type;
2884
+ if (typeof type !== "string") continue;
2885
+ const seq = typeof ev.seq === "number" && Number.isFinite(ev.seq) ? ev.seq : 0;
2886
+ const time = typeof ev.time === "number" && Number.isFinite(ev.time) ? ev.time : 0;
2887
+ const data = asRecord(ev.data);
2888
+ if (data === null) continue;
2889
+ if (type === "subagent/descriptor") {
2890
+ const next = descriptorOf(data);
2891
+ if (next !== null) descriptor = next;
2892
+ continue;
2893
+ }
2894
+ if (type === "team/member") {
2895
+ const member = rosterMemberOf(data);
2896
+ if (member !== null) roster.set(member.name, member);
2897
+ continue;
2898
+ }
2899
+ if (type !== "user/message") continue;
2900
+ const message = messageOf(seq, time, data);
2901
+ if (message !== null) {
2902
+ if (message.text.endsWith("…")) truncated = true;
2903
+ messages.push(message);
2904
+ continue;
2905
+ }
2906
+ if (initialPrompt === void 0 && isPlainPrompt(asRecord(data.source))) {
2907
+ const text = textOfContent(data.content).replace(REMINDER_PREFIX, "");
2908
+ if (text.trim() !== "") {
2909
+ const cut = clip(text, PROMPT_TEXT_MAX);
2910
+ initialPrompt = cut.text;
2911
+ if (cut.cut) truncated = true;
2912
+ }
2913
+ }
2914
+ }
2915
+ messages.sort((a, b) => b.seq - a.seq);
2916
+ if (messages.length > MESSAGES_MAX) {
2917
+ messages.length = MESSAGES_MAX;
2918
+ truncated = true;
2919
+ }
2920
+ const reply = lastReplyOf(events);
2921
+ if (reply !== null && reply.cut) truncated = true;
2922
+ return {
2923
+ ...descriptor !== void 0 ? { descriptor } : {},
2924
+ ...initialPrompt !== void 0 ? { initialPrompt } : {},
2925
+ ...reply !== null ? { lastReply: {
2926
+ time: reply.time,
2927
+ text: reply.text
2928
+ } } : {},
2929
+ ...roster.size > 0 ? { roster: [...roster.values()] } : {},
2930
+ messages,
2931
+ truncated
2932
+ };
2933
+ }
2934
+ function watchFleetChannel(ctx, coldReads = makeColdReadGate()) {
2935
+ ctx.inject(["connection"], (c) => {
2936
+ const handler = async (request) => {
2937
+ let sessionId;
2938
+ try {
2939
+ sessionId = asRecord(await request.json())?.sessionId;
2940
+ } catch {
2941
+ return failure("dsh-context/bad-request", "body is not JSON");
2942
+ }
2943
+ if (typeof sessionId !== "string" || sessionId === "") return failure("dsh-context/bad-request", "missing sessionId");
2944
+ try {
2945
+ const query = ctx.get("sessionQuery");
2946
+ const observe = typeof query?.observeSession === "function" ? query.observeSession.bind(query) : void 0;
2947
+ if (observe === void 0) return reply({
2948
+ ok: true,
2949
+ value: null
2950
+ });
2951
+ return reply({
2952
+ ok: true,
2953
+ value: await coldReads.admit(async () => {
2954
+ const observation = await observe(sessionId, { projectionMode: "none" });
2955
+ const events = observation?.events;
2956
+ if (!Array.isArray(events)) return null;
2957
+ try {
2958
+ return fleetDetailOfEvents(events);
2959
+ } finally {
2960
+ const dispose = observation?.[Symbol.dispose];
2961
+ if (typeof dispose === "function") dispose.call(observation);
2962
+ }
2963
+ }) ?? null
2964
+ });
2965
+ } catch (err) {
2966
+ return failure("gateway/internal", err instanceof Error ? err.message : String(err));
2967
+ }
2968
+ };
2969
+ registerPostRoute(c, c.get("connection"), FLEET_ROUTE, handler, "dsh-context: fleet route");
2970
+ });
2971
+ }
2972
+ //#endregion
2741
2973
  //#region src/host/stepIdentity.ts
2742
2974
  const MINTED_ID_PREFIX = "dshctx-";
2743
2975
  function lacksId(message) {
@@ -2795,7 +3027,7 @@ async function disposeOf(resource) {
2795
3027
  } catch {}
2796
3028
  }
2797
3029
  function skillInfoOf(value) {
2798
- const record = asRecord(value);
3030
+ const record = asRecord$1(value);
2799
3031
  if (record === null || typeof record.name !== "string" || record.name === "") return null;
2800
3032
  return {
2801
3033
  name: record.name,
@@ -2806,7 +3038,7 @@ function skillInfoOf(value) {
2806
3038
  }
2807
3039
  async function sessionViewOf(ctx, sessionId) {
2808
3040
  if (sessionId === void 0) return {};
2809
- const query = asRecord(ctx.get("sessionQuery"));
3041
+ const query = asRecord$1(ctx.get("sessionQuery"));
2810
3042
  if (typeof query?.observeSession !== "function") return {};
2811
3043
  let observation;
2812
3044
  try {
@@ -2815,9 +3047,9 @@ async function sessionViewOf(ctx, sessionId) {
2815
3047
  return {};
2816
3048
  }
2817
3049
  try {
2818
- const obs = asRecord(observation);
2819
- const cwd = stringOf(asRecord(obs?.header)?.cwd);
2820
- const agentPreset = stringOf(asRecord(asRecord(obs?.projections)?.values)?.agentPreset);
3050
+ const obs = asRecord$1(observation);
3051
+ const cwd = stringOf(asRecord$1(obs?.header)?.cwd);
3052
+ const agentPreset = stringOf(asRecord$1(asRecord$1(obs?.projections)?.values)?.agentPreset);
2821
3053
  return {
2822
3054
  ...cwd === void 0 ? {} : { cwd },
2823
3055
  ...agentPreset === void 0 ? {} : { agentPreset }
@@ -2827,10 +3059,10 @@ async function sessionViewOf(ctx, sessionId) {
2827
3059
  }
2828
3060
  }
2829
3061
  async function resolveRegistry(ctx, sessionId, agentPreset) {
2830
- const presets = asRecord(ctx.get("agentPresets"));
3062
+ const presets = asRecord$1(ctx.get("agentPresets"));
2831
3063
  let live;
2832
3064
  if (sessionId !== void 0) {
2833
- const agents = asRecord(ctx.get("agents"));
3065
+ const agents = asRecord$1(ctx.get("agents"));
2834
3066
  if (typeof agents?.get === "function") try {
2835
3067
  live = agents.get.call(agents, sessionId);
2836
3068
  } catch {
@@ -2838,20 +3070,20 @@ async function resolveRegistry(ctx, sessionId, agentPreset) {
2838
3070
  }
2839
3071
  }
2840
3072
  if (live !== void 0 && live !== null && typeof presets?.serviceFor === "function") {
2841
- const scoped = asRecord(presets.serviceFor.call(presets, live, "skills"));
3073
+ const scoped = asRecord$1(presets.serviceFor.call(presets, live, "skills"));
2842
3074
  if (scoped !== null && typeof scoped.list === "function") return {
2843
3075
  registry: scoped,
2844
3076
  scope: live,
2845
3077
  lease: void 0
2846
3078
  };
2847
3079
  }
2848
- const registry = asRecord(ctx.get("skills"));
3080
+ const registry = asRecord$1(ctx.get("skills"));
2849
3081
  if (registry === null || typeof registry.list !== "function") return null;
2850
3082
  let scope;
2851
3083
  let lease;
2852
3084
  if (typeof presets?.acquireScope === "function") try {
2853
3085
  lease = await presets.acquireScope.call(presets, agentPreset);
2854
- scope = asRecord(lease)?.key;
3086
+ scope = asRecord$1(lease)?.key;
2855
3087
  } catch {
2856
3088
  lease = void 0;
2857
3089
  }
@@ -2867,7 +3099,7 @@ function watchSkillCatalog(ctx) {
2867
3099
  let value = null;
2868
3100
  let lease;
2869
3101
  try {
2870
- const body = asRecord(await request.json());
3102
+ const body = asRecord$1(await request.json());
2871
3103
  const sessionId = stringOf(body?.sessionId);
2872
3104
  const view = await sessionViewOf(ctx, sessionId);
2873
3105
  const cwd = view.cwd ?? stringOf(body?.cwd);
@@ -2991,8 +3223,10 @@ function detectHarnessVersion(ctx, resolveUrl = resolveRunningModule, pluginRoot
2991
3223
  const name = "dsh-context";
2992
3224
  const inject = ["sessionProjections"];
2993
3225
  function apply(ctx, config) {
3226
+ const coldReads = makeColdReadGate();
2994
3227
  watchBalanceChannel(ctx);
2995
3228
  watchSkillCatalog(ctx);
3229
+ watchFleetChannel(ctx, coldReads);
2996
3230
  const harnessVersion = detectHarnessVersion(ctx);
2997
3231
  if (harnessVersion !== void 0 && !meetsBaseline(harnessVersion)) {
2998
3232
  ctx.sessionProjections.register(createFallbackTimelineDefinition(harnessVersion));
@@ -3002,7 +3236,6 @@ function apply(ctx, config) {
3002
3236
  }
3003
3237
  const attribution = createToolAttribution(ctx);
3004
3238
  watchStepIdentity(ctx);
3005
- const coldReads = makeColdReadGate();
3006
3239
  const gate = watchDetailChannel(ctx, resolveBounds(config), coldReads);
3007
3240
  ctx.sessionProjections.register(createContextTimelineDefinition(config, () => gate.live));
3008
3241
  ctx.sessionProjections.register(createContextHeadersDefinition((name) => attribution.ownerOf(name)));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-context",
3
- "version": "0.67.0",
3
+ "version": "0.68.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
  "icon": "icon.svg",
6
6
  "author": "bowenliang123",