dsh-context 0.67.0 → 0.68.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.
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,11 @@ interface PluginSettings {
230
232
  defaultFileSort: DefaultFileSort;
231
233
  insightsEntry: InsightsEntry;
232
234
  defaultDurationCurve: DefaultDurationCurve;
235
+ fleetTab: FleetTab;
236
+ /** Free text joined ahead of the harness's assembled system prompt; empty disables. */
237
+ promptPrefix: string;
238
+ /** Free text joined behind the harness's assembled system prompt; empty disables. */
239
+ promptSuffix: string;
233
240
  }
234
241
  interface Snapshot {
235
242
  ok: boolean;
@@ -559,6 +566,9 @@ export declare const Config: z$1<Schemastery.ObjectS<NoInfer<{
559
566
  defaultFileSort: z$1<"count" | "latest" | "path", "count" | "latest" | "path", "defined">;
560
567
  insightsEntry: z$1<"hide" | "show", "hide" | "show", "defined">;
561
568
  defaultDurationCurve: z$1<"hide" | "show", "hide" | "show", "defined">;
569
+ fleetTab: z$1<"hide" | "show", "hide" | "show", "defined">;
570
+ promptPrefix: z$1<string, string, "defined">;
571
+ promptSuffix: z$1<string, string, "defined">;
562
572
  }>>, Schemastery.ObjectT<NoInfer<{
563
573
  maxRequestSteps: z$1<number, number, "defined">;
564
574
  maxKeptTurns: z$1<number, number, "defined">;
@@ -574,6 +584,9 @@ export declare const Config: z$1<Schemastery.ObjectS<NoInfer<{
574
584
  defaultFileSort: z$1<"count" | "latest" | "path", "count" | "latest" | "path", "defined">;
575
585
  insightsEntry: z$1<"hide" | "show", "hide" | "show", "defined">;
576
586
  defaultDurationCurve: z$1<"hide" | "show", "hide" | "show", "defined">;
587
+ fleetTab: z$1<"hide" | "show", "hide" | "show", "defined">;
588
+ promptPrefix: z$1<string, string, "defined">;
589
+ promptSuffix: z$1<string, string, "defined">;
577
590
  }>>, "plain">;
578
591
  //#endregion
579
592
  //#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.1
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-11T13:11:54+00:00
8
+ * @commit 2c8095c34da3
9
+ * @commit-date 2026-10-11T21:08:45+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,10 @@ 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()),
1562
+ promptPrefix: volatileField(z$1.string().default("").loose()),
1563
+ promptSuffix: volatileField(z$1.string().default("").loose())
1561
1564
  });
1562
1565
  function resolveBounds(config) {
1563
1566
  const resolved = Config(config ?? {});
@@ -2185,7 +2188,7 @@ function createToolAttribution(ctx) {
2185
2188
  }
2186
2189
  //#endregion
2187
2190
  //#region src/host/record.ts
2188
- function asRecord(value) {
2191
+ function asRecord$1(value) {
2189
2192
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
2190
2193
  }
2191
2194
  //#endregion
@@ -2226,9 +2229,9 @@ function deepseekSectionOf(ctx) {
2226
2229
  if (!Array.isArray(rows)) return null;
2227
2230
  let shaped = null;
2228
2231
  for (const row of rows) try {
2229
- const record = asRecord(row);
2232
+ const record = asRecord$1(row);
2230
2233
  if (record === null) continue;
2231
- const value = asRecord(record.value);
2234
+ const value = asRecord$1(record.value);
2232
2235
  if (value === null || typeof value.apiKeyEnv !== "string" || value.apiKeyEnv === "") continue;
2233
2236
  if (record.ns === DEEPSEEK_SETTINGS_NS || record.ns === "llm-deepseek-api-key") return value;
2234
2237
  shaped ??= value;
@@ -2261,12 +2264,12 @@ async function resolveFacts(ctx) {
2261
2264
  };
2262
2265
  }
2263
2266
  function balanceOfPayload(value) {
2264
- const data = asRecord(value);
2267
+ const data = asRecord$1(value);
2265
2268
  if (data === null) return null;
2266
2269
  const infos = Array.isArray(data.balance_infos) ? data.balance_infos : [];
2267
2270
  const balances = [];
2268
2271
  for (const info of infos) try {
2269
- const entry = asRecord(info);
2272
+ const entry = asRecord$1(info);
2270
2273
  if (entry === null) continue;
2271
2274
  const currency = entry.currency;
2272
2275
  const granted = amountOf(entry.granted_balance);
@@ -2359,7 +2362,7 @@ const BACKFILL_ROUTE = "/api/dsh-context/backfill";
2359
2362
  const YIELD_MS = 100;
2360
2363
  const UNSUPPORTED_FORMAT = "SessionFormatUnsupported";
2361
2364
  function headerOf(record) {
2362
- const header = asRecord(asRecord(record)?.header);
2365
+ const header = asRecord$1(asRecord$1(record)?.header);
2363
2366
  if (header === null) return null;
2364
2367
  if (typeof header.id !== "string" || header.id === "") return null;
2365
2368
  return header;
@@ -2367,7 +2370,7 @@ function headerOf(record) {
2367
2370
  const PROBE_KEYS = ["contextActivity", "contextTimeline"];
2368
2371
  function servesRows(cache, header) {
2369
2372
  try {
2370
- const values = asRecord(asRecord(cache.cachedSnapshot(header, PROBE_KEYS))?.values);
2373
+ const values = asRecord$1(asRecord$1(cache.cachedSnapshot(header, PROBE_KEYS))?.values);
2371
2374
  return values !== null && values.contextActivity !== void 0 && values.contextTimeline !== void 0;
2372
2375
  } catch {
2373
2376
  return false;
@@ -2377,7 +2380,7 @@ async function readColdLog(persistence, id, signal) {
2377
2380
  const handle = await persistence.open(id, "read", { signal });
2378
2381
  let events;
2379
2382
  try {
2380
- const result = asRecord(await handle.read(0, void 0, { signal }))?.events;
2383
+ const result = asRecord$1(await handle.read(0, void 0, { signal }))?.events;
2381
2384
  events = Array.isArray(result) ? result : [];
2382
2385
  } catch (error) {
2383
2386
  try {
@@ -2402,12 +2405,12 @@ function isLive(sessions, id) {
2402
2405
  }
2403
2406
  function isUnsupportedFormat(error) {
2404
2407
  try {
2405
- return String(asRecord(error)?.name).startsWith(UNSUPPORTED_FORMAT);
2408
+ return String(asRecord$1(error)?.name).startsWith(UNSUPPORTED_FORMAT);
2406
2409
  } catch {
2407
2410
  return false;
2408
2411
  }
2409
2412
  }
2410
- function messageOf(error) {
2413
+ function messageOf$1(error) {
2411
2414
  try {
2412
2415
  return String(error);
2413
2416
  } catch {
@@ -2438,13 +2441,13 @@ function watchActivityBackfill(ctx, coldReads = makeColdReadGate()) {
2438
2441
  "sessions"
2439
2442
  ], (raw) => {
2440
2443
  const injected = raw;
2441
- const query = asRecord(injected.sessionQuery);
2442
- const cache = asRecord(injected.sessionProjectionCache);
2443
- const persistence = asRecord(injected.sessionPersistence);
2444
+ const query = asRecord$1(injected.sessionQuery);
2445
+ const cache = asRecord$1(injected.sessionProjectionCache);
2446
+ const persistence = asRecord$1(injected.sessionPersistence);
2444
2447
  if (query === null || typeof query.listSessions !== "function") return;
2445
2448
  if (cache === null || typeof cache.cachedSnapshot !== "function" || typeof cache.coldSnapshot !== "function") return;
2446
2449
  if (persistence === null || typeof persistence.open !== "function") return;
2447
- const sessions = asRecord(injected.sessions);
2450
+ const sessions = asRecord$1(injected.sessions);
2448
2451
  const abort = new AbortController();
2449
2452
  const run = async () => {
2450
2453
  const listed = await query.listSessions(abort.signal);
@@ -2471,8 +2474,8 @@ function watchActivityBackfill(ctx, coldReads = makeColdReadGate()) {
2471
2474
  } catch (error) {
2472
2475
  if (isUnsupportedFormat(error)) {
2473
2476
  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)})`);
2477
+ ctx.logger.debug(`dsh-context: projection backfill skipped "${header.id}" (${messageOf$1(error)})`);
2478
+ } else ctx.logger.warn(`dsh-context: projection backfill skipped "${header.id}" (${messageOf$1(error)})`);
2476
2479
  }
2477
2480
  await new Promise((resolve) => setTimeout(resolve, YIELD_MS));
2478
2481
  }
@@ -2482,7 +2485,7 @@ function watchActivityBackfill(ctx, coldReads = makeColdReadGate()) {
2482
2485
  };
2483
2486
  launch = () => {
2484
2487
  run().catch((error) => {
2485
- if (!abort.signal.aborted) ctx.logger.warn(`dsh-context: projection backfill stopped early (${messageOf(error)})`);
2488
+ if (!abort.signal.aborted) ctx.logger.warn(`dsh-context: projection backfill stopped early (${messageOf$1(error)})`);
2486
2489
  });
2487
2490
  };
2488
2491
  tryLaunch();
@@ -2494,11 +2497,11 @@ function watchActivityBackfill(ctx, coldReads = makeColdReadGate()) {
2494
2497
  for (const fiber of [routeFiber, runnerFiber]) fiber?.dispose?.();
2495
2498
  };
2496
2499
  }
2497
- function reply(value) {
2500
+ function reply$1(value) {
2498
2501
  return Response.json(value, { headers: { "cache-control": "no-store" } });
2499
2502
  }
2500
- function failure(code, message) {
2501
- return reply({
2503
+ function failure$1(code, message) {
2504
+ return reply$1({
2502
2505
  ok: false,
2503
2506
  error: {
2504
2507
  code,
@@ -2519,29 +2522,29 @@ function watchDetailChannel(ctx, bounds, coldReads = makeColdReadGate()) {
2519
2522
  const body = await request.json();
2520
2523
  sessionId = body !== null && typeof body === "object" ? body.sessionId : void 0;
2521
2524
  } catch {
2522
- return failure("dsh-context/bad-request", "body is not JSON");
2525
+ return failure$1("dsh-context/bad-request", "body is not JSON");
2523
2526
  }
2524
- if (typeof sessionId !== "string" || sessionId === "") return failure("dsh-context/bad-request", "missing sessionId");
2527
+ if (typeof sessionId !== "string" || sessionId === "") return failure$1("dsh-context/bad-request", "missing sessionId");
2525
2528
  try {
2526
2529
  const session = getSession(sessionId);
2527
2530
  if (session !== void 0 && session !== null) {
2528
2531
  const state = projections.stateOf(session, "contextTimeline");
2529
- if (state === void 0) return reply({
2532
+ if (state === void 0) return reply$1({
2530
2533
  ok: true,
2531
2534
  value: null
2532
2535
  });
2533
- return reply({
2536
+ return reply$1({
2534
2537
  ok: true,
2535
2538
  value: buildTimelineDetail(state, bounds)
2536
2539
  });
2537
2540
  }
2538
2541
  const query = ctx.get("sessionQuery");
2539
2542
  const observe = typeof query?.observeSession === "function" ? query.observeSession.bind(query) : void 0;
2540
- if (observe === void 0) return reply({
2543
+ if (observe === void 0) return reply$1({
2541
2544
  ok: true,
2542
2545
  value: null
2543
2546
  });
2544
- return reply({
2547
+ return reply$1({
2545
2548
  ok: true,
2546
2549
  value: await coldReads.admit(async () => {
2547
2550
  const observation = await observe(sessionId, { projectionMode: "none" });
@@ -2558,7 +2561,7 @@ function watchDetailChannel(ctx, bounds, coldReads = makeColdReadGate()) {
2558
2561
  }) ?? null
2559
2562
  });
2560
2563
  } catch (err) {
2561
- return failure("gateway/internal", err instanceof Error ? err.message : String(err));
2564
+ return failure$1("gateway/internal", err instanceof Error ? err.message : String(err));
2562
2565
  }
2563
2566
  };
2564
2567
  if (!registerPostRoute(c, c.get("connection"), "/api/dsh-context/detail", handler, "dsh-context: detail route")) return;
@@ -2738,6 +2741,275 @@ function createFallbackActivityDefinition() {
2738
2741
  return fallbackDefinition("contextActivity", contextActivitySchema, { days: {} });
2739
2742
  }
2740
2743
  //#endregion
2744
+ //#region src/host/fleet.ts
2745
+ const FLEET_ROUTE = "/api/dsh-context/fleet";
2746
+ const MESSAGES_MAX = 40;
2747
+ const MESSAGE_TEXT_MAX = 400;
2748
+ const PROMPT_TEXT_MAX = 1600;
2749
+ const REPLY_TEXT_MAX = 300;
2750
+ function reply(value) {
2751
+ return Response.json(value, { headers: { "cache-control": "no-store" } });
2752
+ }
2753
+ function failure(code, message) {
2754
+ return reply({
2755
+ ok: false,
2756
+ error: {
2757
+ code,
2758
+ message
2759
+ }
2760
+ });
2761
+ }
2762
+ function asRecord(value) {
2763
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
2764
+ }
2765
+ function textOfContent(content) {
2766
+ if (!Array.isArray(content)) return "";
2767
+ let out = "";
2768
+ for (const block of content) {
2769
+ const text = asRecord(block)?.text;
2770
+ if (typeof text === "string") out += text;
2771
+ }
2772
+ return out;
2773
+ }
2774
+ const REMINDER_PREFIX = /^\s*<system-reminder>[\s\S]*?<\/system-reminder>\s*/;
2775
+ function clip(text, max) {
2776
+ return text.length > max ? {
2777
+ text: text.slice(0, max) + "…",
2778
+ cut: true
2779
+ } : {
2780
+ text,
2781
+ cut: false
2782
+ };
2783
+ }
2784
+ function descriptorOf(data) {
2785
+ const mode = data.mode;
2786
+ if (mode !== "one-shot" && mode !== "continuable") return null;
2787
+ const out = { mode };
2788
+ for (const key of [
2789
+ "label",
2790
+ "provider",
2791
+ "agentProvider",
2792
+ "agentModel",
2793
+ "persona"
2794
+ ]) {
2795
+ const value = data[key];
2796
+ if (typeof value === "string" && value !== "") out[key] = value;
2797
+ }
2798
+ return out;
2799
+ }
2800
+ const MAILBOX_PREFIX = /^Team message \S+ from [^:]{1,64}:\s*/;
2801
+ const RELAY_PREFIX = /^(?:Agent \S+ sent a message: |Team message from [^:\n]{1,64}:\s*)/;
2802
+ function messageOf(seq, time, data) {
2803
+ const source = asRecord(data.source);
2804
+ const kind = source?.kind;
2805
+ let message = null;
2806
+ if (kind === "agent-message" || kind === "team-message") {
2807
+ let text = textOfContent(data.content);
2808
+ text = text.replace(kind === "team-message" ? MAILBOX_PREFIX : RELAY_PREFIX, "");
2809
+ if (text.trim() === "") return null;
2810
+ message = {
2811
+ seq,
2812
+ time,
2813
+ kind: kind === "agent-message" ? "relay" : "mailbox",
2814
+ text
2815
+ };
2816
+ const from = kind === "agent-message" ? source?.senderSessionId : source?.senderId;
2817
+ if (typeof from === "string" && from !== "") message.from = from;
2818
+ const fromName = source?.senderName;
2819
+ if (typeof fromName === "string" && fromName !== "") message.fromName = fromName;
2820
+ } else if (kind === "subagent-settled") {
2821
+ const summary = source?.summary;
2822
+ const text = typeof summary === "string" && summary.trim() !== "" ? summary : textOfContent(data.content);
2823
+ if (text.trim() === "") return null;
2824
+ message = {
2825
+ seq,
2826
+ time,
2827
+ kind: "settled",
2828
+ text
2829
+ };
2830
+ const from = source?.senderSessionId;
2831
+ if (typeof from === "string" && from !== "") message.from = from;
2832
+ }
2833
+ if (message === null) return null;
2834
+ const cut = clip(message.text, MESSAGE_TEXT_MAX);
2835
+ message.text = cut.text;
2836
+ return message;
2837
+ }
2838
+ function isPlainPrompt(source) {
2839
+ if (source === null) return true;
2840
+ return source.kind === "user";
2841
+ }
2842
+ function rosterMemberOf(data) {
2843
+ const member = asRecord(data.member);
2844
+ if (member === null) return null;
2845
+ if (typeof member.name !== "string" || member.name === "") return null;
2846
+ const out = {
2847
+ name: member.name,
2848
+ description: typeof member.description === "string" ? member.description : ""
2849
+ };
2850
+ if (typeof member.provider === "string" && member.provider !== "") out.provider = member.provider;
2851
+ if (member.context === "fresh" || member.context === "fork") out.context = member.context;
2852
+ return out;
2853
+ }
2854
+ function lastReplyOf(events) {
2855
+ for (let i = events.length - 1; i >= 0; i--) {
2856
+ const ev = asRecord(events[i]);
2857
+ if (ev === null || ev.type !== "assistant/message") continue;
2858
+ const content = asRecord(asRecord(ev.data)?.message)?.content;
2859
+ if (!Array.isArray(content)) continue;
2860
+ let text = "";
2861
+ for (const block of content) {
2862
+ const b = asRecord(block);
2863
+ if (b?.type === "text" && typeof b.text === "string") text += b.text;
2864
+ }
2865
+ if (text.trim() === "") continue;
2866
+ const time = typeof ev.time === "number" && Number.isFinite(ev.time) ? ev.time : 0;
2867
+ const cut = clip(text, REPLY_TEXT_MAX);
2868
+ return {
2869
+ time,
2870
+ text: cut.text,
2871
+ cut: cut.cut
2872
+ };
2873
+ }
2874
+ return null;
2875
+ }
2876
+ function fleetDetailOfEvents(events) {
2877
+ let descriptor;
2878
+ let initialPrompt;
2879
+ let truncated = false;
2880
+ const messages = [];
2881
+ const roster = new Map();
2882
+ for (const entry of events) {
2883
+ const ev = asRecord(entry);
2884
+ if (ev === null) continue;
2885
+ const type = ev.type;
2886
+ if (typeof type !== "string") continue;
2887
+ const seq = typeof ev.seq === "number" && Number.isFinite(ev.seq) ? ev.seq : 0;
2888
+ const time = typeof ev.time === "number" && Number.isFinite(ev.time) ? ev.time : 0;
2889
+ const data = asRecord(ev.data);
2890
+ if (data === null) continue;
2891
+ if (type === "subagent/descriptor") {
2892
+ const next = descriptorOf(data);
2893
+ if (next !== null) descriptor = next;
2894
+ continue;
2895
+ }
2896
+ if (type === "team/member") {
2897
+ const member = rosterMemberOf(data);
2898
+ if (member !== null) roster.set(member.name, member);
2899
+ continue;
2900
+ }
2901
+ if (type !== "user/message") continue;
2902
+ const message = messageOf(seq, time, data);
2903
+ if (message !== null) {
2904
+ if (message.text.endsWith("…")) truncated = true;
2905
+ messages.push(message);
2906
+ continue;
2907
+ }
2908
+ if (initialPrompt === void 0 && isPlainPrompt(asRecord(data.source))) {
2909
+ const text = textOfContent(data.content).replace(REMINDER_PREFIX, "");
2910
+ if (text.trim() !== "") {
2911
+ const cut = clip(text, PROMPT_TEXT_MAX);
2912
+ initialPrompt = cut.text;
2913
+ if (cut.cut) truncated = true;
2914
+ }
2915
+ }
2916
+ }
2917
+ messages.sort((a, b) => b.seq - a.seq);
2918
+ if (messages.length > MESSAGES_MAX) {
2919
+ messages.length = MESSAGES_MAX;
2920
+ truncated = true;
2921
+ }
2922
+ const reply = lastReplyOf(events);
2923
+ if (reply !== null && reply.cut) truncated = true;
2924
+ return {
2925
+ ...descriptor !== void 0 ? { descriptor } : {},
2926
+ ...initialPrompt !== void 0 ? { initialPrompt } : {},
2927
+ ...reply !== null ? { lastReply: {
2928
+ time: reply.time,
2929
+ text: reply.text
2930
+ } } : {},
2931
+ ...roster.size > 0 ? { roster: [...roster.values()] } : {},
2932
+ messages,
2933
+ truncated
2934
+ };
2935
+ }
2936
+ function watchFleetChannel(ctx, coldReads = makeColdReadGate()) {
2937
+ ctx.inject(["connection"], (c) => {
2938
+ const handler = async (request) => {
2939
+ let sessionId;
2940
+ try {
2941
+ sessionId = asRecord(await request.json())?.sessionId;
2942
+ } catch {
2943
+ return failure("dsh-context/bad-request", "body is not JSON");
2944
+ }
2945
+ if (typeof sessionId !== "string" || sessionId === "") return failure("dsh-context/bad-request", "missing sessionId");
2946
+ try {
2947
+ const query = ctx.get("sessionQuery");
2948
+ const observe = typeof query?.observeSession === "function" ? query.observeSession.bind(query) : void 0;
2949
+ if (observe === void 0) return reply({
2950
+ ok: true,
2951
+ value: null
2952
+ });
2953
+ return reply({
2954
+ ok: true,
2955
+ value: await coldReads.admit(async () => {
2956
+ const observation = await observe(sessionId, { projectionMode: "none" });
2957
+ const events = observation?.events;
2958
+ if (!Array.isArray(events)) return null;
2959
+ try {
2960
+ return fleetDetailOfEvents(events);
2961
+ } finally {
2962
+ const dispose = observation?.[Symbol.dispose];
2963
+ if (typeof dispose === "function") dispose.call(observation);
2964
+ }
2965
+ }) ?? null
2966
+ });
2967
+ } catch (err) {
2968
+ return failure("gateway/internal", err instanceof Error ? err.message : String(err));
2969
+ }
2970
+ };
2971
+ registerPostRoute(c, c.get("connection"), FLEET_ROUTE, handler, "dsh-context: fleet route");
2972
+ });
2973
+ }
2974
+ //#endregion
2975
+ //#region src/host/promptInjection.ts
2976
+ function liveText(value) {
2977
+ if (value !== null && typeof value === "object" && typeof value.get === "function") {
2978
+ const get = value.get;
2979
+ return () => {
2980
+ const text = get();
2981
+ return typeof text === "string" ? text : "";
2982
+ };
2983
+ }
2984
+ const text = typeof value === "string" ? value : "";
2985
+ return () => text;
2986
+ }
2987
+ function sectionText(read) {
2988
+ return () => {
2989
+ const text = read();
2990
+ return text.trim().length === 0 ? "" : text;
2991
+ };
2992
+ }
2993
+ const ORDER_CLEARANCE = 1e3;
2994
+ function watchPromptInjection(ctx, config) {
2995
+ ctx.inject(["systemPrompt"], (inner) => {
2996
+ const systemPrompt = inner.systemPrompt;
2997
+ if (systemPrompt === null || systemPrompt === void 0 || typeof systemPrompt.section !== "function" || typeof systemPrompt.getSectionOrder !== "function") return;
2998
+ systemPrompt.section({
2999
+ name: "dsh-context:prompt-prefix",
3000
+ order: systemPrompt.getSectionOrder("HARNESS_IDENTITY") - ORDER_CLEARANCE,
3001
+ text: sectionText(liveText(config.promptPrefix)),
3002
+ interpolate: false
3003
+ });
3004
+ systemPrompt.section({
3005
+ name: "dsh-context:prompt-suffix",
3006
+ order: systemPrompt.getSectionOrder("DEPLOYMENT_PERSONA_SUFFIX") + ORDER_CLEARANCE,
3007
+ text: sectionText(liveText(config.promptSuffix)),
3008
+ interpolate: false
3009
+ });
3010
+ });
3011
+ }
3012
+ //#endregion
2741
3013
  //#region src/host/stepIdentity.ts
2742
3014
  const MINTED_ID_PREFIX = "dshctx-";
2743
3015
  function lacksId(message) {
@@ -2795,7 +3067,7 @@ async function disposeOf(resource) {
2795
3067
  } catch {}
2796
3068
  }
2797
3069
  function skillInfoOf(value) {
2798
- const record = asRecord(value);
3070
+ const record = asRecord$1(value);
2799
3071
  if (record === null || typeof record.name !== "string" || record.name === "") return null;
2800
3072
  return {
2801
3073
  name: record.name,
@@ -2806,7 +3078,7 @@ function skillInfoOf(value) {
2806
3078
  }
2807
3079
  async function sessionViewOf(ctx, sessionId) {
2808
3080
  if (sessionId === void 0) return {};
2809
- const query = asRecord(ctx.get("sessionQuery"));
3081
+ const query = asRecord$1(ctx.get("sessionQuery"));
2810
3082
  if (typeof query?.observeSession !== "function") return {};
2811
3083
  let observation;
2812
3084
  try {
@@ -2815,9 +3087,9 @@ async function sessionViewOf(ctx, sessionId) {
2815
3087
  return {};
2816
3088
  }
2817
3089
  try {
2818
- const obs = asRecord(observation);
2819
- const cwd = stringOf(asRecord(obs?.header)?.cwd);
2820
- const agentPreset = stringOf(asRecord(asRecord(obs?.projections)?.values)?.agentPreset);
3090
+ const obs = asRecord$1(observation);
3091
+ const cwd = stringOf(asRecord$1(obs?.header)?.cwd);
3092
+ const agentPreset = stringOf(asRecord$1(asRecord$1(obs?.projections)?.values)?.agentPreset);
2821
3093
  return {
2822
3094
  ...cwd === void 0 ? {} : { cwd },
2823
3095
  ...agentPreset === void 0 ? {} : { agentPreset }
@@ -2827,10 +3099,10 @@ async function sessionViewOf(ctx, sessionId) {
2827
3099
  }
2828
3100
  }
2829
3101
  async function resolveRegistry(ctx, sessionId, agentPreset) {
2830
- const presets = asRecord(ctx.get("agentPresets"));
3102
+ const presets = asRecord$1(ctx.get("agentPresets"));
2831
3103
  let live;
2832
3104
  if (sessionId !== void 0) {
2833
- const agents = asRecord(ctx.get("agents"));
3105
+ const agents = asRecord$1(ctx.get("agents"));
2834
3106
  if (typeof agents?.get === "function") try {
2835
3107
  live = agents.get.call(agents, sessionId);
2836
3108
  } catch {
@@ -2838,20 +3110,20 @@ async function resolveRegistry(ctx, sessionId, agentPreset) {
2838
3110
  }
2839
3111
  }
2840
3112
  if (live !== void 0 && live !== null && typeof presets?.serviceFor === "function") {
2841
- const scoped = asRecord(presets.serviceFor.call(presets, live, "skills"));
3113
+ const scoped = asRecord$1(presets.serviceFor.call(presets, live, "skills"));
2842
3114
  if (scoped !== null && typeof scoped.list === "function") return {
2843
3115
  registry: scoped,
2844
3116
  scope: live,
2845
3117
  lease: void 0
2846
3118
  };
2847
3119
  }
2848
- const registry = asRecord(ctx.get("skills"));
3120
+ const registry = asRecord$1(ctx.get("skills"));
2849
3121
  if (registry === null || typeof registry.list !== "function") return null;
2850
3122
  let scope;
2851
3123
  let lease;
2852
3124
  if (typeof presets?.acquireScope === "function") try {
2853
3125
  lease = await presets.acquireScope.call(presets, agentPreset);
2854
- scope = asRecord(lease)?.key;
3126
+ scope = asRecord$1(lease)?.key;
2855
3127
  } catch {
2856
3128
  lease = void 0;
2857
3129
  }
@@ -2867,7 +3139,7 @@ function watchSkillCatalog(ctx) {
2867
3139
  let value = null;
2868
3140
  let lease;
2869
3141
  try {
2870
- const body = asRecord(await request.json());
3142
+ const body = asRecord$1(await request.json());
2871
3143
  const sessionId = stringOf(body?.sessionId);
2872
3144
  const view = await sessionViewOf(ctx, sessionId);
2873
3145
  const cwd = view.cwd ?? stringOf(body?.cwd);
@@ -2991,8 +3263,10 @@ function detectHarnessVersion(ctx, resolveUrl = resolveRunningModule, pluginRoot
2991
3263
  const name = "dsh-context";
2992
3264
  const inject = ["sessionProjections"];
2993
3265
  function apply(ctx, config) {
3266
+ const coldReads = makeColdReadGate();
2994
3267
  watchBalanceChannel(ctx);
2995
3268
  watchSkillCatalog(ctx);
3269
+ watchFleetChannel(ctx, coldReads);
2996
3270
  const harnessVersion = detectHarnessVersion(ctx);
2997
3271
  if (harnessVersion !== void 0 && !meetsBaseline(harnessVersion)) {
2998
3272
  ctx.sessionProjections.register(createFallbackTimelineDefinition(harnessVersion));
@@ -3002,12 +3276,12 @@ function apply(ctx, config) {
3002
3276
  }
3003
3277
  const attribution = createToolAttribution(ctx);
3004
3278
  watchStepIdentity(ctx);
3005
- const coldReads = makeColdReadGate();
3006
3279
  const gate = watchDetailChannel(ctx, resolveBounds(config), coldReads);
3007
3280
  ctx.sessionProjections.register(createContextTimelineDefinition(config, () => gate.live));
3008
3281
  ctx.sessionProjections.register(createContextHeadersDefinition((name) => attribution.ownerOf(name)));
3009
3282
  ctx.sessionProjections.register(createContextActivityDefinition());
3010
3283
  watchActivityBackfill(ctx, coldReads);
3284
+ watchPromptInjection(ctx, config);
3011
3285
  }
3012
3286
  //#endregion
3013
3287
  export { Config, apply, inject, 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.1",
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",