dsh-context 0.59.2 → 0.60.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 CHANGED
@@ -123,6 +123,10 @@ Pick **Live (next request)** or any retained step, and browse what that request
123
123
 
124
124
  ![Tool schemas with source chips, filter, and sort](https://raw.githubusercontent.com/bowenliang123/dsh-context/main/docs/context-browser-tools.png)
125
125
 
126
+ - **Filter assistant replies by kind** — the assistant category's search box carries **Thinking / Tools / Answer** chips, each with the shown step's message count (one reply can carry several); click one to keep only the matching replies, click again to clear:
127
+
128
+ ![Assistant replies with kind filter chips](https://raw.githubusercontent.com/bowenliang123/dsh-context/main/docs/context-browser-assistant-kinds.png)
129
+
126
130
  - **Tool results open into the full call** — the tool name and arguments with its **OK/error** status, the result body with line count and a **Raw / Markdown** toggle:
127
131
 
128
132
  ![A tool result expanded with Raw/Markdown toggle](https://raw.githubusercontent.com/bowenliang123/dsh-context/main/docs/context-browser-tool-result.png)
package/lib/client.js CHANGED
@@ -107,6 +107,7 @@ window.__ModuleLoader__.load({
107
107
  "insightsEntry.hide": "隐藏",
108
108
  "settings.gran": "趋势图 · 默认粒度",
109
109
  "settings.mode": "趋势图 · 默认展示方式",
110
+ "settings.deltaBase": "上下文浏览器 · 对比基线",
110
111
  "settings.toolSort": "工具定义 · 默认排序",
111
112
  "settings.fileSort": "文件活动 · 默认排序",
112
113
  "settings.expand": "展开",
@@ -279,7 +280,9 @@ window.__ModuleLoader__.load({
279
280
  "browser.items": "{n} 项",
280
281
  "browser.missingLive": "… 另有 {n} 条更早的消息也在上下文中(超出展示窗口)",
281
282
  "browser.approx": "该步骤涉及的部分已移除消息超出保留范围,以下为近似构成",
282
- "browser.deltaHint": "对比上轮末步的变动",
283
+ "browser.base.step": "比前步",
284
+ "browser.base.turn": "比前轮",
285
+ "browser.base.tip": "变动对比的基线:比前步=与上一步对比;比前轮=与上一轮最后一步对比(首轮无基线,全部计为变动)",
283
286
  "browser.dna": "DNA 模式",
284
287
  "browser.dnaTip": "按模型读取上下文的次序逐条展示每一项:系统提示词、工具定义,然后是按时间排列的消息;悬停查看条目,点击定位到下方列表",
285
288
  "browser.noHeader": "此数据来自旧版插件:仅提供 token 估算,无实际内容",
@@ -290,8 +293,12 @@ window.__ModuleLoader__.load({
290
293
  "browser.search.user": "按消息内容过滤…",
291
294
  "browser.search.inject": "按注入内容过滤…",
292
295
  "browser.search.skill": "按技能过滤…",
293
- "browser.search.assistant": "按回复或调用过滤…",
296
+ "browser.search.assistant": "按回复、调用或思考过滤…",
294
297
  "browser.search.tool": "按工具或参数过滤…",
298
+ "browser.kind.think": "思考",
299
+ "browser.kind.tool": "工具",
300
+ "browser.kind.answer": "回答",
301
+ "browser.kindTip": "按内容种类过滤回复:思考、工具调用、回答文本",
295
302
  "browser.rowNoMatch": "没有匹配当前过滤条件的行",
296
303
  "browser.loading": "正在从更早的会话历史加载完整内容…",
297
304
  "browser.notInLog": "会话日志中未找到该条目的完整内容(可能已被压缩或清理)",
@@ -494,6 +501,7 @@ window.__ModuleLoader__.load({
494
501
  "insightsEntry.hide": "Hide",
495
502
  "settings.gran": "Trend Chart · Default granularity",
496
503
  "settings.mode": "Trend Chart · Default display",
504
+ "settings.deltaBase": "Context Browser · Diff baseline",
497
505
  "settings.toolSort": "Tool Schemas · Default sort",
498
506
  "settings.fileSort": "File Activity · Default sort",
499
507
  "settings.expand": "Expand",
@@ -666,7 +674,9 @@ window.__ModuleLoader__.load({
666
674
  "browser.items": "{n} Items",
667
675
  "browser.missingLive": "… {n} earlier messages are also part of the context (outside the served window)",
668
676
  "browser.approx": "Some removed messages of this step exceed retention — the makeup below is approximate",
669
- "browser.deltaHint": "vs previous turn",
677
+ "browser.base.step": "prev step",
678
+ "browser.base.turn": "prev turn",
679
+ "browser.base.tip": "Diff baseline: the previous step, or the previous turn’s last step — with no predecessor, everything counts as change",
670
680
  "browser.dna": "DNA Mode",
671
681
  "browser.dnaTip": "One band per item in the order the model reads the context — system prompt, tool schemas, then messages chronologically; hover for details, click to open its row below",
672
682
  "browser.noHeader": "Served by an older plugin build: token estimates only, no content",
@@ -677,8 +687,12 @@ window.__ModuleLoader__.load({
677
687
  "browser.search.user": "Filter by message text…",
678
688
  "browser.search.inject": "Filter injected context…",
679
689
  "browser.search.skill": "Filter skills…",
680
- "browser.search.assistant": "Filter by reply or calls…",
690
+ "browser.search.assistant": "Filter by reply, calls, or thinking…",
681
691
  "browser.search.tool": "Filter by tool or arguments…",
692
+ "browser.kind.think": "Thinking",
693
+ "browser.kind.tool": "Tools",
694
+ "browser.kind.answer": "Answer",
695
+ "browser.kindTip": "Filter replies by content kind: thinking, tool calls, or answer text",
682
696
  "browser.rowNoMatch": "No rows match the current filter",
683
697
  "browser.loading": "Loading full content from older session history…",
684
698
  "browser.notInLog": "This item is not in the session log anymore (it may have been compacted away or cleared)",
@@ -708,7 +722,7 @@ window.__ModuleLoader__.load({
708
722
  "rich.md.copied": "Copied",
709
723
  "rich.md.footnotes": "Footnotes",
710
724
  "block.thinking": "Reasoning",
711
- "block.answer": "Response",
725
+ "block.answer": "Answer",
712
726
  "block.content": "Content",
713
727
  "block.result": "Result",
714
728
  "block.summary": "Summary",
@@ -2179,6 +2193,15 @@ window.__ModuleLoader__.load({
2179
2193
  * stops the trailing until the head moves again. With no detail at all,
2180
2194
  * failure surfaces as a retryable note on the detail cards instead of an
2181
2195
  * empty chart.
2196
+ *
2197
+ * The cold start: a session can sit with NO pushed `contextTimeline` value
2198
+ * at all — the enable recomposition raced its open baseline (and the
2199
+ * projection store clears a key its baseline omits), or its checkpoint row
2200
+ * is missing or version-stale on a cold-observed session. Waiting for a
2201
+ * push that never comes would stall the view on "loading" forever, so the
2202
+ * source opens the detail channel on its own (rev 0): the route folds the
2203
+ * durable log on demand and serves the slim head beside the collections,
2204
+ * and the next pushed head takes the channel back per its own revision.
2182
2205
  */
2183
2206
  const DETAIL_ROUTE = "/api/dsh-context/detail";
2184
2207
  /**
@@ -2370,30 +2393,39 @@ window.__ModuleLoader__.load({
2370
2393
  const sessionId = typeof props.sessionId === "string" ? props.sessionId : "";
2371
2394
  const headRev = head !== null && typeof head.detailRev === "number" ? head.detailRev : null;
2372
2395
  const slim = headRev !== null;
2373
- const store = (0, react.useMemo)(() => slim ? detailStoreOf(ctx, sessionId) : null, [
2396
+ const cold = head === null;
2397
+ const store = (0, react.useMemo)(() => slim || cold ? detailStoreOf(ctx, sessionId) : null, [
2374
2398
  ctx,
2375
2399
  sessionId,
2376
- slim
2400
+ slim,
2401
+ cold
2377
2402
  ]);
2378
2403
  const snap = (0, react.useSyncExternalStore)(store !== null ? store.subscribe : noopSubscribe, store !== null ? store.getSnapshot : () => EMPTY_SNAP);
2379
2404
  (0, react.useEffect)(() => {
2380
- if (store !== null && headRev !== null) store.request(headRev);
2405
+ if (store !== null) store.request(headRev ?? 0);
2381
2406
  }, [store, headRev]);
2382
2407
  return (0, react.useMemo)(() => {
2383
- if (head === null) return {
2384
- data: null,
2385
- detailState: "loading",
2386
- retryDetail: noopRetry
2387
- };
2388
- if (!slim || store === null) return {
2408
+ const detail = snap.detail;
2409
+ const retry = store !== null ? store.retry : noopRetry;
2410
+ if (head !== null && !slim) return {
2389
2411
  data: head,
2390
2412
  detailState: "legacy",
2391
2413
  retryDetail: noopRetry
2392
2414
  };
2393
- const detail = snap.detail;
2415
+ const base = head !== null ? head : detail !== null ? detail.head ?? null : null;
2416
+ if (base === null) return {
2417
+ data: null,
2418
+ detailState: store !== null && (snap.failed || detail !== null) ? "failed" : "loading",
2419
+ retryDetail: retry
2420
+ };
2421
+ if (detail === null) return {
2422
+ data: base,
2423
+ detailState: snap.failed ? "failed" : "loading",
2424
+ retryDetail: retry
2425
+ };
2394
2426
  return {
2395
- data: detail === null ? head : {
2396
- ...head,
2427
+ data: {
2428
+ ...base,
2397
2429
  requests: detail.requests,
2398
2430
  events: detail.events,
2399
2431
  nodes: detail.nodes,
@@ -2404,8 +2436,8 @@ window.__ModuleLoader__.load({
2404
2436
  ...detail.fileOps !== void 0 ? { fileOps: detail.fileOps } : {},
2405
2437
  ...detail.fileOpsFloor !== void 0 ? { fileOpsFloor: detail.fileOpsFloor } : {}
2406
2438
  },
2407
- detailState: detail !== null ? "ready" : snap.failed ? "failed" : "loading",
2408
- retryDetail: store.retry
2439
+ detailState: "ready",
2440
+ retryDetail: retry
2409
2441
  };
2410
2442
  }, [
2411
2443
  head,
@@ -4496,6 +4528,58 @@ window.__ModuleLoader__.load({
4496
4528
  function nodeNameOf(n) {
4497
4529
  return typeof n.name === "string" ? n.name : "";
4498
4530
  }
4531
+ /**
4532
+ * The content kinds one assistant message proves, as the assistant category's
4533
+ * kind chips count and filter them: thinking (a reasoning block — only the
4534
+ * conversation join can prove it), tool calls (join blocks, else the fold's
4535
+ * text-less-reply `calls` stamp), and answer text (join blocks, else the
4536
+ * node's `text`). Legacy `content` joins classify the same way the body
4537
+ * renders them. The flags are independent, so a combined reply lights
4538
+ * several chips.
4539
+ */
4540
+ function msgKindsOf(n, conv) {
4541
+ let think = false;
4542
+ let tool = false;
4543
+ let answer = false;
4544
+ for (const blocks of [conv?.blocks, conv?.content]) {
4545
+ if (!Array.isArray(blocks)) continue;
4546
+ for (const b of blocks) {
4547
+ const blk = b !== null && typeof b === "object" ? b : null;
4548
+ const k = blk !== null ? typeof blk.kind === "string" ? blk.kind : typeof blk.type === "string" ? blk.type : "" : "";
4549
+ if (k === "reasoning") think = true;
4550
+ else if (k === "tool-call") tool = true;
4551
+ else if (k === "text") answer = true;
4552
+ }
4553
+ }
4554
+ return {
4555
+ think,
4556
+ tool: tool || Array.isArray(n.calls) && n.calls.length > 0,
4557
+ answer: answer || typeof n.text === "string" && n.text !== ""
4558
+ };
4559
+ }
4560
+ /**
4561
+ * The reasoning texts one assistant row's conversation join proves, concatenated for the row filter's scan —
4562
+ * the fold stamps no reasoning on the node, so this is the only scan face the thinking blocks expose. Both block
4563
+ * vocabularies classify here (the body renders the same blocks as the Reasoning sections); malformed blocks drop.
4564
+ */
4565
+ function reasoningTextOf(conv) {
4566
+ if (conv === void 0) return "";
4567
+ let out = "";
4568
+ for (const blocks of [conv.blocks, conv.content]) {
4569
+ if (!Array.isArray(blocks)) continue;
4570
+ for (const b of blocks) {
4571
+ const blk = b !== null && typeof b === "object" ? b : null;
4572
+ if ((blk !== null ? typeof blk.kind === "string" ? blk.kind : typeof blk.type === "string" ? blk.type : "" : "") === "reasoning" && typeof blk?.text === "string") out += blk.text + "\n";
4573
+ }
4574
+ }
4575
+ return out;
4576
+ }
4577
+ /** The assistant rows' kind chips, in display order. */
4578
+ const ROW_KINDS = [
4579
+ "think",
4580
+ "tool",
4581
+ "answer"
4582
+ ];
4499
4583
  function countOf(asm, byCat, c) {
4500
4584
  if (c === "system") return asm.system !== null ? 1 : 0;
4501
4585
  if (c === "tools") return asm.header !== null ? asm.header.tools.length : 0;
@@ -4523,9 +4607,11 @@ window.__ModuleLoader__.load({
4523
4607
  const [openCat, setOpenCat] = (0, react.useState)(null);
4524
4608
  const [openElem, setOpenElem] = (0, react.useState)(null);
4525
4609
  const [rowQuery, setRowQuery] = (0, react.useState)("");
4610
+ const [rowKind, setRowKind] = (0, react.useState)(null);
4526
4611
  const [toolSort, setToolSort] = (0, react.useState)(() => settings.defaultToolSort());
4527
4612
  const [dna, setDna] = (0, react.useState)(false);
4528
4613
  const [dnaKey, setDnaKey] = (0, react.useState)(null);
4614
+ const [deltaBase, setDeltaBase] = (0, react.useState)(() => settings.defaultDeltaBase());
4529
4615
  const onOpenCat = props.onOpenCat;
4530
4616
  const setCat = (c) => {
4531
4617
  setOpenCat(c);
@@ -4596,7 +4682,14 @@ window.__ModuleLoader__.load({
4596
4682
  setCat(null);
4597
4683
  setOpenElem(null);
4598
4684
  };
4599
- const refReq = req === null ? requests.length > 0 ? requests[requests.length - 1] : null : lastOfTurn(requests, (req.turn ?? 0) - 1);
4685
+ const prevRecordOf = (r) => {
4686
+ const i = requests.findIndex((x) => x.seq === r.seq);
4687
+ return i > 0 ? requests[i - 1] : null;
4688
+ };
4689
+ const lastReq = requests.length > 0 ? requests[requests.length - 1] : null;
4690
+ const turnBaseOf = (r) => lastOfTurn(requests, (r.turn ?? 0) - 1);
4691
+ const refReq = req === null ? deltaBase === "step" ? lastReq : lastReq === null ? null : turnBaseOf(lastReq) : deltaBase === "turn" ? turnBaseOf(req) : prevRecordOf(req);
4692
+ const zeroBase = refReq === null && lastReq !== null;
4600
4693
  const prevView = refReq !== null ? assemble(data, headers, refReq.seq) : null;
4601
4694
  const prevByCat = prevView !== null ? byCatOf(prevView) : null;
4602
4695
  const byCat = byCatOf(view);
@@ -4628,6 +4721,7 @@ window.__ModuleLoader__.load({
4628
4721
  if (it === void 0) return;
4629
4722
  setCat(it.cat);
4630
4723
  setRowQuery("");
4724
+ setRowKind(null);
4631
4725
  setOpenElem(key);
4632
4726
  focusScrollRef.current = true;
4633
4727
  };
@@ -4652,6 +4746,7 @@ window.__ModuleLoader__.load({
4652
4746
  }
4653
4747
  setCat(c);
4654
4748
  setRowQuery("");
4749
+ setRowKind(null);
4655
4750
  setOpenElem(singleKeyOf(c));
4656
4751
  };
4657
4752
  const toggleElem = (key) => {
@@ -4678,7 +4773,7 @@ window.__ModuleLoader__.load({
4678
4773
  title: t("node.failed")
4679
4774
  }) : null,
4680
4775
  tag !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4681
- className: "lc-br-tag",
4776
+ className: "lc-br-tags",
4682
4777
  children: tag
4683
4778
  }) : null,
4684
4779
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
@@ -4701,6 +4796,19 @@ window.__ModuleLoader__.load({
4701
4796
  }) : null]
4702
4797
  }, key);
4703
4798
  };
4799
+ const rowTagNode = (tag, names) => {
4800
+ if (tag === null) return null;
4801
+ if (names === null) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4802
+ className: "lc-br-tag",
4803
+ children: tag
4804
+ });
4805
+ const counts = /* @__PURE__ */ new Map();
4806
+ for (const name of names) counts.set(name, (counts.get(name) ?? 0) + 1);
4807
+ return [...counts.entries()].map(([name, count]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4808
+ className: "lc-br-tag",
4809
+ children: count > 1 ? name + " ×" + String(count) : name
4810
+ }, name));
4811
+ };
4704
4812
  const catBody = (c) => {
4705
4813
  if (c === "system") {
4706
4814
  const sys = view.system;
@@ -4803,22 +4911,27 @@ window.__ModuleLoader__.load({
4803
4911
  const conv = bySeq.get(n.seq);
4804
4912
  const rowErr = (n.cat === "tool" || n.cat === "skill") && toolErrOf(n, conv).err;
4805
4913
  let tag = null;
4914
+ let tagNames = null;
4806
4915
  let preview = nodeText(n);
4807
4916
  const id = nodeNameOf(n);
4808
4917
  if (n.cat === "tool") {
4809
4918
  tag = n.tool ?? "?";
4919
+ tagNames = n.tool !== void 0 ? [n.tool] : null;
4810
4920
  preview = callSummaryOf(conv) ?? t("node.toolResult");
4811
4921
  } else if (n.cat === "skill") {
4812
4922
  tag = n.skill !== void 0 ? t("node.skillTag", { name: n.skill }) : t("form." + (n.form || "context"));
4813
4923
  preview = (n.skill === void 0 && id !== "" ? id : null) ?? (n.text !== void 0 && n.text !== "" ? n.text : null) ?? callSummaryOf(conv) ?? preview;
4814
- } else if (n.cat === "assistant" && Array.isArray(n.calls) && n.calls.length > 0) {
4815
- tag = n.calls.join(" › ");
4816
- preview = (n.text !== void 0 && n.text !== "" ? n.text : null) ?? blockSummaryOf(conv) ?? t("node.empty");
4817
- } else if (n.cat === "assistant" && (n.text === void 0 || n.text === "")) preview = blockSummaryOf(conv) ?? preview;
4818
- else if (n.cat === "user") {
4924
+ } else if (n.cat === "assistant") {
4925
+ const names = Array.isArray(n.calls) && n.calls.length > 0 ? n.calls : callNamesOf(conv);
4926
+ if (names.length > 0) {
4927
+ tag = names.join(" › ");
4928
+ tagNames = names;
4929
+ preview = (n.text !== void 0 && n.text !== "" ? n.text : null) ?? blockSummaryOf(conv) ?? t("node.empty");
4930
+ } else if (n.text === void 0 || n.text === "") preview = blockSummaryOf(conv) ?? preview;
4931
+ } else if (n.cat === "user") {
4819
4932
  const imgCount = conv !== void 0 && Array.isArray(conv.content) ? conv.content.filter((b) => imageRefOf(b) !== null).length : 0;
4820
4933
  if (imgCount > 0 && openElem !== `n${n.seq}`) tag = t("attach.image") + (imgCount > 1 ? " ×" + String(imgCount) : "");
4821
- } else if (n.cat === "inject") {
4934
+ } else {
4822
4935
  tag = t("form." + (n.form || "context"));
4823
4936
  if (id !== "") preview = id;
4824
4937
  else if (n.text !== void 0 && n.text !== "") preview = n.form === "snapshot" ? t("node.snapshot") + n.text : n.text;
@@ -4828,21 +4941,44 @@ window.__ModuleLoader__.load({
4828
4941
  conv,
4829
4942
  rowErr,
4830
4943
  tag,
4831
- preview
4944
+ tagNames,
4945
+ preview,
4946
+ reasoning: n.cat === "assistant" ? reasoningTextOf(conv) : "",
4947
+ kinds: msgKindsOf(n, conv)
4832
4948
  };
4833
4949
  });
4834
4950
  const q = rowQuery.trim().toLowerCase();
4835
- const shown = q === "" ? rows : rows.filter((r) => (r.tag ?? "").toLowerCase().includes(q) || r.preview.toLowerCase().includes(q) || typeof r.n.text === "string" && r.n.text.toLowerCase().includes(q));
4836
- const rowctl = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowToolbar, {
4951
+ const kindCounts = c === "assistant" ? ROW_KINDS.map((k) => ({
4952
+ k,
4953
+ n: rows.reduce((acc, r) => acc + (r.kinds[k] ? 1 : 0), 0)
4954
+ })) : null;
4955
+ const shown = q === "" && rowKind === null ? rows : rows.filter((r) => (rowKind === null || r.kinds[rowKind]) && (q === "" || (r.tag ?? "").toLowerCase().includes(q) || r.preview.toLowerCase().includes(q) || typeof r.n.text === "string" && r.n.text.toLowerCase().includes(q) || r.reasoning.toLowerCase().includes(q)));
4956
+ const rowctl = kindCounts === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowToolbar, {
4837
4957
  value: rowQuery,
4838
4958
  placeholder: t("browser.search." + c),
4839
4959
  onChange: setRowQuery
4960
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowToolbar, {
4961
+ value: rowQuery,
4962
+ placeholder: t("browser.search." + c),
4963
+ tip: t("browser.kindTip"),
4964
+ onChange: setRowQuery,
4965
+ children: kindCounts.map(({ k, n }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
4966
+ type: "button",
4967
+ className: "lc-gran-btn" + (rowKind === k ? " lc-gran-on" : ""),
4968
+ onClick: () => {
4969
+ setRowKind(rowKind === k ? null : k);
4970
+ },
4971
+ children: [t("browser.kind." + k), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4972
+ className: "lc-kind-n",
4973
+ children: fmt(n)
4974
+ })]
4975
+ }, k))
4840
4976
  });
4841
4977
  if (shown.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [rowctl, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4842
4978
  className: "lc-br-note",
4843
4979
  children: t("browser.rowNoMatch")
4844
4980
  })] });
4845
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [rowctl, shown.map(({ n, conv, rowErr, tag, preview }) => elemRow(`n${n.seq}`, tag, preview, n.tokens, n.time, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NodeContent, {
4981
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [rowctl, shown.map(({ n, conv, rowErr, tag, tagNames, preview }) => elemRow(`n${n.seq}`, rowTagNode(tag, tagNames), preview, n.tokens, n.time, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NodeContent, {
4846
4982
  node: n,
4847
4983
  conv,
4848
4984
  rich,
@@ -4891,9 +5027,25 @@ window.__ModuleLoader__.load({
4891
5027
  children: t("browser.dna")
4892
5028
  })
4893
5029
  }),
4894
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4895
- className: "lc-br-hint",
4896
- children: t("browser.deltaHint")
5030
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5031
+ className: "lc-gran",
5032
+ role: "group",
5033
+ title: t("browser.base.tip"),
5034
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5035
+ type: "button",
5036
+ className: "lc-gran-btn" + (deltaBase === "step" ? " lc-gran-on" : ""),
5037
+ onClick: () => {
5038
+ setDeltaBase("step");
5039
+ },
5040
+ children: t("browser.base.step")
5041
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5042
+ type: "button",
5043
+ className: "lc-gran-btn" + (deltaBase === "turn" ? " lc-gran-on" : ""),
5044
+ onClick: () => {
5045
+ setDeltaBase("turn");
5046
+ },
5047
+ children: t("browser.base.turn")
5048
+ })]
4897
5049
  }),
4898
5050
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
4899
5051
  className: "lc-br-pick",
@@ -4910,7 +5062,7 @@ window.__ModuleLoader__.load({
4910
5062
  t: r.turn ?? 0,
4911
5063
  s: r.step ?? 0,
4912
5064
  n: stepsOf(r.turn)
4913
- }) + " · " + fmtTime(r.time)
5065
+ })
4914
5066
  }, r.seq))]
4915
5067
  })
4916
5068
  ]
@@ -4965,9 +5117,9 @@ window.__ModuleLoader__.load({
4965
5117
  children: CATS.map((c) => {
4966
5118
  const count = toolCount(c.key);
4967
5119
  const v = breakdown[c.key] || 0;
4968
- const prevCount = prevView !== null && prevByCat !== null ? countOf(prevView, prevByCat, c.key) : null;
5120
+ const prevCount = zeroBase ? 0 : prevView !== null && prevByCat !== null ? countOf(prevView, prevByCat, c.key) : null;
4969
5121
  const countDelta = prevCount !== null ? count - prevCount : null;
4970
- const prevTokens = refReq !== null ? refReq[c.key] || 0 : null;
5122
+ const prevTokens = zeroBase ? 0 : refReq !== null ? refReq[c.key] || 0 : null;
4971
5123
  const tokenDelta = prevTokens !== null ? v - prevTokens : null;
4972
5124
  const openable = count > 0 || (c.key === "system" || c.key === "tools") && view.header === null;
4973
5125
  const open = openCat === c.key && openable;
@@ -5358,6 +5510,7 @@ window.__ModuleLoader__.load({
5358
5510
  const StackedBar = makeStackedBar(kit);
5359
5511
  const CurrentComposition = makeCurrentComposition(kit, StackedBar, makeLegend(kit));
5360
5512
  const ContextBrowser = makeContextBrowser(kit, StackedBar, settings);
5513
+ const DetailNote = makeDetailNote(kit);
5361
5514
  const ErrorBoundary = makeErrorBoundary(t);
5362
5515
  function ContextModalBody(props) {
5363
5516
  const sessionId = typeof props.sessionId === "string" ? props.sessionId : "";
@@ -5425,7 +5578,10 @@ window.__ModuleLoader__.load({
5425
5578
  onClick: close,
5426
5579
  children: "×"
5427
5580
  })]
5428
- }), data === null || head === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5581
+ }), data === null || head === null ? source.detailState === "failed" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DetailNote, {
5582
+ state: "failed",
5583
+ onRetry: source.retryDetail
5584
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5429
5585
  className: "lc-empty",
5430
5586
  children: t("loading")
5431
5587
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CurrentComposition, {
@@ -8314,7 +8470,7 @@ window.__ModuleLoader__.load({
8314
8470
  //#endregion
8315
8471
  //#region src/client/components/settingsCard.tsx
8316
8472
  /**
8317
- * The dsh-context preference cards — two seats over the same six rows. The
8473
+ * The dsh-context preference cards — two seats over the same seven rows. The
8318
8474
  * settings-section card (`settings.plugin.item`, the older harness lines)
8319
8475
  * renders a collapsible list item in Settings → Plugins → Plugin
8320
8476
  * configuration; the Plugins-page card (`plugins.bundle.config`, the
@@ -8361,7 +8517,7 @@ window.__ModuleLoader__.load({
8361
8517
  })]
8362
8518
  });
8363
8519
  }
8364
- /** The six preference rows shared by both seats. */
8520
+ /** The seven preference rows shared by both seats. */
8365
8521
  function PreferenceRows(props) {
8366
8522
  const { t, state, set } = props;
8367
8523
  const disabled = state.status !== "ready" || !state.writable;
@@ -8433,6 +8589,21 @@ window.__ModuleLoader__.load({
8433
8589
  set?.("defaultTrendMode", id);
8434
8590
  }
8435
8591
  }),
8592
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PrefRow, {
8593
+ label: t("settings.deltaBase"),
8594
+ value: state.deltaBase,
8595
+ disabled,
8596
+ options: [{
8597
+ id: "step",
8598
+ label: t("browser.base.step")
8599
+ }, {
8600
+ id: "turn",
8601
+ label: t("browser.base.turn")
8602
+ }],
8603
+ onPick: (id) => {
8604
+ set?.("defaultDeltaBase", id);
8605
+ }
8606
+ }),
8436
8607
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PrefRow, {
8437
8608
  label: t("settings.toolSort"),
8438
8609
  value: state.toolSort,
@@ -8563,6 +8734,7 @@ window.__ModuleLoader__.load({
8563
8734
  ...v.defaultPlacement === "all" || v.defaultPlacement === "tab" || v.defaultPlacement === "sidebar" ? { placement: v.defaultPlacement } : {},
8564
8735
  ...v.defaultGranularity === "step" || v.defaultGranularity === "turn" ? { granularity: v.defaultGranularity } : {},
8565
8736
  ...v.defaultTrendMode === "total" || v.defaultTrendMode === "delta" ? { mode: v.defaultTrendMode } : {},
8737
+ ...v.defaultDeltaBase === "step" || v.defaultDeltaBase === "turn" ? { deltaBase: v.defaultDeltaBase } : {},
8566
8738
  ...v.defaultToolSort === "size" || v.defaultToolSort === "count" || v.defaultToolSort === "name" ? { toolSort: v.defaultToolSort } : {},
8567
8739
  ...v.defaultFileSort === "count" || v.defaultFileSort === "latest" || v.defaultFileSort === "path" ? { fileSort: v.defaultFileSort } : {},
8568
8740
  ...v.insightsEntry === "show" || v.insightsEntry === "hide" ? { insightsEntry: v.insightsEntry } : {}
@@ -8574,6 +8746,7 @@ window.__ModuleLoader__.load({
8574
8746
  placement: "all",
8575
8747
  granularity: "step",
8576
8748
  mode: "total",
8749
+ deltaBase: "step",
8577
8750
  toolSort: "count",
8578
8751
  fileSort: "count",
8579
8752
  insightsEntry: "show",
@@ -8582,7 +8755,7 @@ window.__ModuleLoader__.load({
8582
8755
  let scope;
8583
8756
  const listeners = /* @__PURE__ */ new Set();
8584
8757
  const publish = (next) => {
8585
- if (next.status === state.status && next.placement === state.placement && next.granularity === state.granularity && next.mode === state.mode && next.toolSort === state.toolSort && next.fileSort === state.fileSort && next.insightsEntry === state.insightsEntry && next.writable === state.writable) return;
8758
+ if (next.status === state.status && next.placement === state.placement && next.granularity === state.granularity && next.mode === state.mode && next.deltaBase === state.deltaBase && next.toolSort === state.toolSort && next.fileSort === state.fileSort && next.insightsEntry === state.insightsEntry && next.writable === state.writable) return;
8586
8759
  state = next;
8587
8760
  for (const listener of listeners) listener();
8588
8761
  };
@@ -8595,6 +8768,7 @@ window.__ModuleLoader__.load({
8595
8768
  placement: prefs.placement ?? (raw?.defaultPlacement === void 0 ? state.placement : "all"),
8596
8769
  granularity: prefs.granularity ?? state.granularity,
8597
8770
  mode: prefs.mode ?? state.mode,
8771
+ deltaBase: prefs.deltaBase ?? state.deltaBase,
8598
8772
  toolSort: prefs.toolSort ?? state.toolSort,
8599
8773
  fileSort: prefs.fileSort ?? state.fileSort,
8600
8774
  insightsEntry: prefs.insightsEntry ?? (raw?.insightsEntry === void 0 ? state.insightsEntry : "show"),
@@ -8618,6 +8792,7 @@ window.__ModuleLoader__.load({
8618
8792
  defaultPlacement: () => state.placement,
8619
8793
  defaultGranularity: () => state.granularity,
8620
8794
  defaultTrendMode: () => state.mode,
8795
+ defaultDeltaBase: () => state.deltaBase,
8621
8796
  defaultToolSort: () => state.toolSort,
8622
8797
  defaultFileSort: () => state.fileSort,
8623
8798
  insightsEntry: () => state.insightsEntry,
@@ -10784,7 +10959,7 @@ window.__ModuleLoader__.load({
10784
10959
  return function PluginInfo() {
10785
10960
  const [latest, setLatest] = (0, react.useState)(null);
10786
10961
  (0, react.useEffect)(() => {
10787
- if ("0.59.2".includes("-dev")) return;
10962
+ if ("0.60.0".includes("-dev")) return;
10788
10963
  let on = true;
10789
10964
  fetchLatestVersion().then((v) => {
10790
10965
  if (on && v) setLatest(v);
@@ -10793,8 +10968,8 @@ window.__ModuleLoader__.load({
10793
10968
  on = false;
10794
10969
  };
10795
10970
  }, []);
10796
- const update = latest !== null && isNewerVersion(latest, "0.59.2") ? latest : null;
10797
- const nameText = "dsh-context (v0.59.2)";
10971
+ const update = latest !== null && isNewerVersion(latest, "0.60.0") ? latest : null;
10972
+ const nameText = "dsh-context (v0.60.0)";
10798
10973
  const nameValue = [nameText];
10799
10974
  if (update) nameValue.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
10800
10975
  className: "lc-pi-update",
@@ -11932,7 +12107,10 @@ window.__ModuleLoader__.load({
11932
12107
  if (!data) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
11933
12108
  className: "lc-root",
11934
12109
  ref: rootRef,
11935
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
12110
+ children: source.detailState === "failed" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DetailNote, {
12111
+ state: "failed",
12112
+ onRetry: source.retryDetail
12113
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
11936
12114
  className: "lc-empty",
11937
12115
  children: t("loading")
11938
12116
  })
@@ -12412,7 +12590,7 @@ window.__ModuleLoader__.load({
12412
12590
  }
12413
12591
  //#endregion
12414
12592
  //#region \0dsh-global-css:/home/runner/work/dsh-context/dsh-context/src/client/styles/requestDetail.css.mjs
12415
- const css$8 = ".lc-detail{border-top:1px solid var(--dsw-alias-border-l1);margin-top:12px;padding-top:12px}.lc-detail-head{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;align-items:center;gap:6px 8px;margin-bottom:10px;display:flex}.lc-detail-head b{color:var(--dsw-alias-label-primary);font-size:13px}.lc-detail-time{font-variant-numeric:tabular-nums;white-space:nowrap;margin-left:auto;font-size:12px}.lc-detail-marker{color:var(--dsw-alias-state-warn-primary);background:color-mix(in srgb, var(--dsw-alias-state-warn-primary) 12%, transparent);border-radius:6px;padding:1px 7px;font-size:11px}.lc-detail-tag{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-secondary);border-radius:4px;padding:0 6px;font-size:11px}.lc-detail-metric{font-variant-numeric:tabular-nums;white-space:nowrap;color:var(--dsw-alias-label-primary);background:color-mix(in srgb, var(--dsw-alias-label-secondary) 14%, transparent);border-radius:6px;padding:2px 8px;font-size:12px;font-weight:600}.lc-detail-metric-up{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 15%, transparent)}.lc-detail-metric-down{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 15%, transparent)}.lc-detail-rows{grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:4px 24px;margin-top:10px;display:grid}.lc-brief{flex-direction:column;gap:2px;min-height:76px;margin:-4px 0 10px;display:flex}.lc-brief-row{min-width:0;color:var(--dsw-alias-label-primary);text-align:left;transition:background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border:0;border-radius:6px;align-items:center;gap:8px;margin-left:-6px;margin-right:-6px;padding:3px 6px;font-family:inherit;font-size:12px;line-height:1.5;display:flex}button.lc-brief-row-link{cursor:pointer}.lc-brief-tag{box-sizing:border-box;text-align:center;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);min-width:56px;color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:0 6px;font-size:11px;position:relative}.lc-brief-tip{white-space:normal;text-align:left;max-width:240px;font-weight:400;line-height:1.5;bottom:calc(100% + 6px);left:0}.lc-brief-text{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.lc-brief-empty{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-tertiary);flex:1;overflow:hidden}.lc-brief-fact{box-sizing:border-box;text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);max-width:160px;color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:0 6px;font-size:11px;overflow:hidden}.lc-brief-chip{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);min-width:0;max-width:260px;color:var(--dsw-alias-label-primary);transition:background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-radius:5px;align-items:center;gap:5px;padding:0 7px;font-size:12px;display:inline-flex;overflow:hidden}.lc-brief-chip-grow{flex:1;max-width:none}.lc-brief-chip-tag{text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);max-width:120px;color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:0 6px;font-size:11px;overflow:hidden}.lc-brief-chip-text{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.lc-brief-chip-link{cursor:pointer}.lc-brief-more{color:var(--dsw-alias-label-secondary);flex:none;font-size:11px}.lc-detail-row{transition:background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-radius:4px;align-items:center;gap:8px;margin:-1px -4px;padding:1px 4px;display:flex}.lc-detail-row i{transition:box-shadow var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out)}.lc-detail-row-on{background:var(--dsw-alias-interactive-bg-hover)}.lc-detail-row-on i{box-shadow:0 0 0 1px var(--dsw-alias-brand-primary)}.lc-detail-row-on .lc-detail-label{font-weight:600}.lc-detail-label{white-space:nowrap;min-width:70px;color:var(--dsw-alias-label-secondary)}.lc-bar-track{background:color-mix(in srgb, var(--color-neutral-500) 18%, transparent);border-radius:3px;flex:1;height:5px;display:block;position:relative;overflow:hidden}.lc-bar-fill{border-radius:3px;height:100%;display:block}.lc-bar-zero{border-left:1px solid color-mix(in srgb, var(--color-neutral-500) 45%, transparent);position:absolute;top:0;bottom:0;left:50%}.lc-bar-fill-up,.lc-bar-fill-down{height:100%;display:block;position:absolute;top:0}.lc-bar-fill-up{border-radius:0 3px 3px 0;left:50%}.lc-bar-fill-down{border-radius:3px 0 0 3px;right:50%}.lc-detail-num{text-align:right;font-variant-numeric:tabular-nums;width:52px}.lc-detail-num-up{color:var(--dsw-alias-state-success-primary)}.lc-detail-num-down{color:var(--dsw-alias-state-error-primary)}.lc-detail-pct{text-align:right;width:34px;color:var(--dsw-alias-label-secondary)}";
12593
+ const css$8 = ".lc-detail{border-top:1px solid var(--dsw-alias-border-l1);margin-top:12px;padding-top:12px}.lc-detail-head{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;align-items:center;gap:6px 8px;margin-bottom:10px;display:flex}.lc-detail-head b{color:var(--dsw-alias-label-primary);font-size:13px}.lc-detail-time{font-variant-numeric:tabular-nums;white-space:nowrap;margin-left:auto;font-size:12px}.lc-detail-marker{color:var(--dsw-alias-state-warn-primary);background:color-mix(in srgb, var(--dsw-alias-state-warn-primary) 12%, transparent);border-radius:6px;padding:1px 7px;font-size:11px}.lc-detail-tag{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-secondary);border-radius:4px;padding:0 6px;font-size:11px}.lc-detail-metric{font-variant-numeric:tabular-nums;white-space:nowrap;color:var(--dsw-alias-label-primary);background:color-mix(in srgb, var(--dsw-alias-label-secondary) 14%, transparent);border-radius:6px;padding:2px 8px;font-size:12px;font-weight:600}.lc-detail-metric-up{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 15%, transparent)}.lc-detail-metric-down{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 15%, transparent)}.lc-detail-rows{grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:4px 24px;margin-top:10px;display:grid}.lc-brief{flex-direction:column;gap:2px;min-height:76px;margin:-4px 0 10px;display:flex}.lc-brief-row{min-width:0;color:var(--dsw-alias-label-primary);text-align:left;transition:background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border:0;border-radius:6px;align-items:center;gap:8px;margin-left:-6px;margin-right:-6px;padding:3px 6px;font-family:inherit;font-size:12px;line-height:1.5;display:flex}button.lc-brief-row-link{cursor:pointer}.lc-brief-tag{box-sizing:border-box;text-align:center;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);min-width:56px;color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:0 6px;font-size:11px;position:relative}.lc-brief-tip{white-space:normal;text-align:left;max-width:240px;font-weight:400;line-height:1.5;bottom:calc(100% + 6px);left:0}.lc-brief-text{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.lc-brief-empty{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-tertiary);flex:1;overflow:hidden}.lc-brief-fact{box-sizing:border-box;text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);max-width:160px;color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:0 6px;font-size:11px;overflow:hidden}.lc-brief-chip{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);min-width:0;max-width:260px;color:var(--dsw-alias-label-primary);transition:background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-radius:5px;align-items:center;gap:5px;padding:0 7px;font-size:12px;display:inline-flex;overflow:hidden}.lc-brief-chip-grow{flex:1;max-width:none}.lc-brief-chip-tag{text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);max-width:120px;color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:0 6px;font-size:11px;overflow:hidden}.lc-brief-chip-text{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.lc-brief-chip-link{cursor:pointer}.lc-brief-more{color:var(--dsw-alias-label-secondary);flex:none;font-size:11px}.lc-detail-row{transition:background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-radius:4px;align-items:center;gap:8px;margin:-1px -4px;padding:1px 4px;display:flex}.lc-detail-row i{transition:box-shadow var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out)}.lc-detail-row-on{background:var(--dsw-alias-interactive-bg-hover)}.lc-detail-row-on i{box-shadow:0 0 0 1px var(--dsw-alias-brand-primary)}.lc-detail-row-on .lc-detail-label{font-weight:600}.lc-detail-label{white-space:nowrap;min-width:70px;color:var(--dsw-alias-label-secondary)}.lc-bar-track{background:color-mix(in srgb, var(--color-neutral-500) 18%, transparent);border-radius:3px;flex:1;height:5px;display:block;position:relative;overflow:hidden}.lc-bar-fill{border-radius:3px;height:100%;display:block}.lc-bar-zero{border-left:1px solid color-mix(in srgb, var(--color-neutral-500) 45%, transparent);position:absolute;top:0;bottom:0;left:50%}.lc-bar-fill-up,.lc-bar-fill-down{height:100%;display:block;position:absolute;top:0}.lc-bar-fill-up{border-radius:0 3px 3px 0;left:50%}.lc-bar-fill-down{border-radius:3px 0 0 3px;right:50%}.lc-detail-num{text-align:right;font-variant-numeric:tabular-nums;width:52px}.lc-detail-num-up{color:var(--dsw-alias-state-success-primary)}.lc-detail-num-down{color:var(--dsw-alias-state-error-primary)}.lc-detail-pct{text-align:right;width:34px;color:var(--dsw-alias-label-secondary)}";
12416
12594
  const tagId$8 = "dsh-context/requestDetail.css";
12417
12595
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$8) + "]") === null) {
12418
12596
  const tag = document.createElement("style");
@@ -12434,7 +12612,7 @@ window.__ModuleLoader__.load({
12434
12612
  }
12435
12613
  //#endregion
12436
12614
  //#region \0dsh-global-css:/home/runner/work/dsh-context/dsh-context/src/client/styles/fileCard.css.mjs
12437
- const css$6 = ".lc-fa-ctl,.lc-br-toolctl{flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:8px;display:flex}.lc-fa-ctl .lc-gran{margin-left:0}.lc-fa-n{opacity:.75;margin-left:4px;font-weight:700}.lc-fa-search,.lc-br-tool-search{min-width:80px;font:inherit;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;outline:none;flex:1;padding:3px 8px;font-size:12px}.lc-fa-meta{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:6px;font-size:12px;display:flex}.lc-fa-meta .lc-fa-sort{flex:none}.lc-fa-meta-delta{position:relative}.lc-fa-meta-tip{white-space:normal;max-width:260px;line-height:1.5;top:calc(100% + 6px);left:0}.lc-fa-item{transition:background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out), border-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border:1px solid #0000;border-radius:8px}.lc-fa-item-on{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-border-l2)}.lc-fa-row{width:100%;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;text-align:left;transition:background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border:0;border-radius:7px;align-items:center;gap:7px;padding:6px 8px;font-size:12px;display:flex}.lc-fa-form{opacity:.85;flex:none;justify-content:center;align-items:center;width:20px;height:14px;font-size:11px;display:flex}.lc-fa-lang{border-radius:4px;justify-content:center;align-items:center;min-width:16px;height:13px;padding:0 2px;font-size:8px;font-weight:700;line-height:1;display:inline-flex}.lc-fa-row .lc-br-chev{margin-right:-2px}.lc-fa-path{word-break:break-all;min-width:0}.lc-fa-file{cursor:pointer}.lc-fa-path em{color:var(--dsw-alias-label-secondary);font-style:normal}.lc-fa-badge{font-variant-numeric:tabular-nums;white-space:nowrap;border-radius:999px;flex:none;align-items:center;gap:4px;padding:1px 7px;font-size:11px;font-weight:600;display:inline-flex}.lc-fa-badge i{background:currentColor;border-radius:50%;width:5px;height:5px;display:inline-block}.lc-fa-b-read{color:var(--dsw-alias-brand-primary);background:color-mix(in srgb, var(--dsw-alias-brand-primary) 14%, transparent)}.lc-fa-b-write{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 14%, transparent)}.lc-fa-b-search{color:var(--dsw-alias-state-warn-primary);background:color-mix(in srgb, var(--dsw-alias-state-warn-primary) 14%, transparent)}.lc-fa-chip-read,.lc-fa-chip-read:hover{color:var(--dsw-alias-brand-primary)}.lc-fa-chip-write,.lc-fa-chip-write:hover{color:var(--dsw-alias-state-success-primary)}.lc-fa-chip-search,.lc-fa-chip-search:hover{color:var(--dsw-alias-state-warn-primary)}.lc-fa-chip-read.lc-gran-on,.lc-fa-chip-read.lc-gran-on:hover{background:color-mix(in srgb, var(--dsw-alias-brand-primary) 14%, transparent);color:var(--dsw-alias-brand-primary)}.lc-fa-chip-write.lc-gran-on,.lc-fa-chip-write.lc-gran-on:hover{background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 14%, transparent);color:var(--dsw-alias-state-success-primary)}.lc-fa-chip-search.lc-gran-on,.lc-fa-chip-search.lc-gran-on:hover{background:color-mix(in srgb, var(--dsw-alias-state-warn-primary) 14%, transparent);color:var(--dsw-alias-state-warn-primary)}.lc-fa-delta{font-variant-numeric:tabular-nums;white-space:nowrap;flex:none;gap:5px;font-size:11px;font-weight:600;display:inline-flex}.lc-fa-up{color:var(--dsw-alias-state-success-primary)}.lc-fa-down{color:var(--dsw-alias-state-error-primary)}.lc-fa-time{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex:none;font-size:11px}.lc-fa-ops{border-left:2px solid var(--dsw-alias-border-l1);flex-direction:column;gap:1px;margin:0 8px 8px 15px;padding:2px 0 2px 10px;display:flex}.lc-fa-op{min-width:0;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;transition:background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border:0;border-radius:5px;align-items:center;gap:8px;padding:3px 6px;font-size:11px;display:flex}.lc-fa-op-link{cursor:pointer}.lc-fa-op-time{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex:none;margin-left:auto}.lc-fa-op-tool{text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);max-width:220px;color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:0 6px;font-size:11px;overflow:hidden}.lc-fa-op-detail{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-secondary);flex:1;overflow:hidden}.lc-fa-read{color:var(--dsw-alias-brand-primary);font-variant-numeric:tabular-nums;white-space:nowrap;flex:none;font-size:11px;font-weight:600}";
12615
+ const css$6 = ".lc-fa-ctl,.lc-br-toolctl{flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:8px;display:flex}.lc-fa-ctl .lc-gran{margin-left:0}.lc-fa-n{opacity:.75;margin-left:4px;font-weight:700}.lc-fa-search,.lc-br-tool-search{min-width:80px;font:inherit;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;outline:none;flex:1;padding:3px 8px;font-size:12px}.lc-fa-meta{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:6px;font-size:12px;display:flex}.lc-fa-meta .lc-fa-sort{flex:none}.lc-fa-meta-delta{position:relative}.lc-fa-meta-tip{white-space:normal;max-width:260px;line-height:1.5;top:calc(100% + 6px);left:0}.lc-fa-item{transition:background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out), border-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border:1px solid #0000;border-radius:8px}.lc-fa-item-on{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-border-l2)}.lc-fa-row{width:100%;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;text-align:left;transition:background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border:0;border-radius:7px;align-items:center;gap:7px;padding:6px 8px;font-size:12px;display:flex}.lc-fa-form{opacity:.85;flex:none;justify-content:center;align-items:center;width:20px;height:14px;font-size:11px;display:flex}.lc-fa-lang{border-radius:4px;justify-content:center;align-items:center;min-width:16px;height:13px;padding:0 2px;font-size:8px;font-weight:700;line-height:1;display:inline-flex}.lc-fa-row .lc-br-chev{margin-right:-2px}.lc-fa-path{word-break:break-all;min-width:0}.lc-fa-file{cursor:pointer}.lc-fa-path em{color:var(--dsw-alias-label-secondary);font-style:normal}.lc-fa-badge{font-variant-numeric:tabular-nums;white-space:nowrap;border-radius:999px;flex:none;align-items:center;gap:4px;padding:1px 7px;font-size:11px;font-weight:600;display:inline-flex}.lc-fa-badge i{background:currentColor;border-radius:50%;width:5px;height:5px;display:inline-block}.lc-fa-b-read{color:var(--dsw-alias-brand-primary);background:color-mix(in srgb, var(--dsw-alias-brand-primary) 14%, transparent)}.lc-fa-b-write{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 14%, transparent)}.lc-fa-b-search{color:var(--dsw-alias-state-warn-primary);background:color-mix(in srgb, var(--dsw-alias-state-warn-primary) 14%, transparent)}.lc-fa-chip-read,.lc-fa-chip-read:hover{color:var(--dsw-alias-brand-primary)}.lc-fa-chip-write,.lc-fa-chip-write:hover{color:var(--dsw-alias-state-success-primary)}.lc-fa-chip-search,.lc-fa-chip-search:hover{color:var(--dsw-alias-state-warn-primary)}.lc-fa-chip-read.lc-gran-on,.lc-fa-chip-read.lc-gran-on:hover{background:color-mix(in srgb, var(--dsw-alias-brand-primary) 14%, transparent);color:var(--dsw-alias-brand-primary)}.lc-fa-chip-write.lc-gran-on,.lc-fa-chip-write.lc-gran-on:hover{background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 14%, transparent);color:var(--dsw-alias-state-success-primary)}.lc-fa-chip-search.lc-gran-on,.lc-fa-chip-search.lc-gran-on:hover{background:color-mix(in srgb, var(--dsw-alias-state-warn-primary) 14%, transparent);color:var(--dsw-alias-state-warn-primary)}.lc-fa-delta{font-variant-numeric:tabular-nums;white-space:nowrap;flex:none;gap:5px;font-size:11px;font-weight:600;display:inline-flex}.lc-fa-up{color:var(--dsw-alias-state-success-primary)}.lc-fa-down{color:var(--dsw-alias-state-error-primary)}.lc-fa-time{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex:none;font-size:11px}.lc-fa-ops{border-left:2px solid var(--dsw-alias-border-l1);flex-direction:column;gap:1px;margin:0 8px 8px 15px;padding:2px 0 2px 10px;display:flex}.lc-fa-op{min-width:0;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;transition:background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border:0;border-radius:5px;align-items:center;gap:8px;padding:3px 6px;font-size:11px;display:flex}.lc-fa-op-link{cursor:pointer}.lc-fa-op-time{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex:none;margin-left:auto}.lc-fa-op-tool{text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);max-width:220px;color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:0 6px;font-size:11px;overflow:hidden}.lc-fa-op-detail{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-secondary);flex:1;overflow:hidden}.lc-fa-read{color:var(--dsw-alias-brand-primary);font-variant-numeric:tabular-nums;white-space:nowrap;flex:none;font-size:11px;font-weight:600}";
12438
12616
  const tagId$6 = "dsh-context/fileCard.css";
12439
12617
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$6) + "]") === null) {
12440
12618
  const tag = document.createElement("style");
@@ -12456,7 +12634,7 @@ window.__ModuleLoader__.load({
12456
12634
  }
12457
12635
  //#endregion
12458
12636
  //#region \0dsh-global-css:/home/runner/work/dsh-context/dsh-context/src/client/styles/browser.css.mjs
12459
- const css$4 = ".lc-br-dna-ctl{flex:none;margin-left:0}.lc-br-bar-dna .lc-stacked-seg{background-image:linear-gradient(to right, transparent calc(100% - min(.5px, 12.5%)), var(--dsw-alias-bg-layer-1) 0)}.lc-br-hint{color:var(--dsw-alias-label-secondary);white-space:nowrap;margin-left:auto;font-size:11px;font-weight:400}.lc-br-pick{font:inherit;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;max-width:240px;padding:3px 6px;font-size:12px}.lc-br-meta{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;gap:6px 16px;margin-bottom:8px;display:flex}.lc-br-meta b{color:var(--dsw-alias-label-primary)}.lc-br-meta .lc-est{margin-left:auto}.lc-br-note{color:var(--dsw-alias-label-secondary);margin-top:8px;font-size:12px}.lc-br-retry{color:var(--dsw-alias-brand-primary);font:inherit;cursor:pointer;text-underline-offset:2px;transition:filter var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border:0;padding:0;font-size:12px;text-decoration:underline}.lc-br-cats{flex-direction:column;gap:4px;margin-top:10px;display:flex}.lc-br-cat{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);border-radius:8px;overflow:hidden}.lc-br-cat-empty{opacity:.55}.lc-br-cat-row{width:100%;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;text-align:left;transition:background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border:0;align-items:center;gap:8px;padding:7px 10px;display:flex}.lc-br-cat-on{background:var(--dsw-alias-interactive-bg-hover)}.lc-br-cat-on i{box-shadow:0 0 0 1px var(--dsw-alias-brand-primary)}.lc-br-cat-open{background:var(--dsw-alias-interactive-bg-hover)}.lc-br-cat-row i{width:8px;height:8px;transition:box-shadow var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-radius:2px;flex:none;display:inline-block}.lc-br-cat-label{font-weight:600}.lc-br-cat-count{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-size:12px}.lc-br-count-grp{flex:1;align-items:center;gap:4px;min-width:0;display:inline-flex}.lc-br-chev{width:12px;height:14px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:center;align-items:center;display:flex}.lc-br-chev:before{content:\"\";width:5px;height:5px;transition:transform var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-bottom:1px solid;border-right:1px solid;transform:rotate(-45deg)}.lc-br-chev-on:before{transform:rotate(45deg)}.lc-br-tokens{color:var(--dsw-alias-label-secondary);flex:none;font-size:12px}.lc-br-delta,.lc-br-tdelta{white-space:nowrap;border-radius:4px;flex:none;padding:0 5px;font-size:11px;font-weight:600}.lc-br-delta-up,.lc-br-tdelta-up{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 15%, transparent)}.lc-br-delta-down,.lc-br-tdelta-down{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 15%, transparent)}.lc-br-tokens-grp{flex:none;align-items:center;gap:4px;min-width:0;display:inline-flex}.lc-br-pct{text-align:right;width:36px;color:var(--dsw-alias-label-secondary);flex:none;font-size:12px}.lc-br-body{border-top:1px solid var(--dsw-alias-border-l1);flex-direction:column;gap:2px;padding:4px 6px;display:flex}.lc-br-elem{border-radius:6px}.lc-br-elem-on{background:var(--dsw-alias-interactive-bg-active)}.lc-br-elem-row{width:100%;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;text-align:left;transition:background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border:0;border-radius:6px;align-items:center;gap:8px;padding:5px 6px;font-size:12px;display:flex}.lc-br-err-dot{background:var(--dsw-alias-state-error-primary);width:6px;height:6px;box-shadow:0 0 0 2px color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, transparent);border-radius:50%;flex:none}.lc-br-tag{min-width:0;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);text-overflow:ellipsis;white-space:nowrap;border-radius:4px;max-width:220px;padding:0 6px;font-size:11px;overflow:hidden}.lc-br-tool-plugin{color:var(--dsw-alias-brand-primary);background:color-mix(in srgb, var(--dsw-alias-brand-primary) 14%, transparent);border-color:#0000;border-radius:6px;font-size:12px}.lc-br-preview{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.lc-br-time,.lc-br-hits{color:var(--dsw-alias-label-secondary);flex:none;font-size:11px}.lc-br-content{flex-direction:column;gap:6px;padding:2px 6px 8px 26px;display:flex}.lc-br-dim{color:var(--dsw-alias-label-secondary)}";
12637
+ const css$4 = ".lc-br-dna-ctl{flex:none;margin-left:0}.lc-br-bar-dna .lc-stacked-seg{background-image:linear-gradient(to right, transparent calc(100% - min(.5px, 12.5%)), var(--dsw-alias-bg-layer-1) 0)}.lc-br-pick{font:inherit;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;max-width:240px;padding:3px 6px;font-size:12px}.lc-br-meta{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;gap:6px 16px;margin-bottom:8px;display:flex}.lc-br-meta b{color:var(--dsw-alias-label-primary)}.lc-br-meta .lc-est{margin-left:auto}.lc-br-note{color:var(--dsw-alias-label-secondary);margin-top:8px;font-size:12px}.lc-br-retry{color:var(--dsw-alias-brand-primary);font:inherit;cursor:pointer;text-underline-offset:2px;transition:filter var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border:0;padding:0;font-size:12px;text-decoration:underline}.lc-br-cats{flex-direction:column;gap:4px;margin-top:10px;display:flex}.lc-br-cat{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);border-radius:8px;overflow:hidden}.lc-br-cat-empty{opacity:.55}.lc-br-cat-row{width:100%;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;text-align:left;transition:background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border:0;align-items:center;gap:8px;padding:7px 10px;display:flex}.lc-br-cat-on{background:var(--dsw-alias-interactive-bg-hover)}.lc-br-cat-on i{box-shadow:0 0 0 1px var(--dsw-alias-brand-primary)}.lc-br-cat-open{background:var(--dsw-alias-interactive-bg-hover)}.lc-br-cat-row i{width:8px;height:8px;transition:box-shadow var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-radius:2px;flex:none;display:inline-block}.lc-br-cat-label{font-weight:600}.lc-br-cat-count{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-size:12px}.lc-br-count-grp{flex:1;align-items:center;gap:4px;min-width:0;display:inline-flex}.lc-br-chev{width:12px;height:14px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:center;align-items:center;display:flex}.lc-br-chev:before{content:\"\";width:5px;height:5px;transition:transform var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-bottom:1px solid;border-right:1px solid;transform:rotate(-45deg)}.lc-br-chev-on:before{transform:rotate(45deg)}.lc-br-tokens{color:var(--dsw-alias-label-secondary);flex:none;font-size:12px}.lc-br-delta,.lc-br-tdelta{white-space:nowrap;border-radius:4px;flex:none;padding:0 5px;font-size:11px;font-weight:600}.lc-br-delta-up,.lc-br-tdelta-up{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 15%, transparent)}.lc-br-delta-down,.lc-br-tdelta-down{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 15%, transparent)}.lc-br-tokens-grp{flex:none;align-items:center;gap:4px;min-width:0;display:inline-flex}.lc-br-pct{text-align:right;width:36px;color:var(--dsw-alias-label-secondary);flex:none;font-size:12px}.lc-br-body{border-top:1px solid var(--dsw-alias-border-l1);flex-direction:column;gap:2px;padding:4px 6px;display:flex}.lc-br-elem{border-radius:6px}.lc-br-elem-on{background:var(--dsw-alias-interactive-bg-active)}.lc-br-elem-row{width:100%;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;text-align:left;transition:background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border:0;border-radius:6px;align-items:center;gap:8px;padding:5px 6px;font-size:12px;display:flex}.lc-br-err-dot{background:var(--dsw-alias-state-error-primary);width:6px;height:6px;box-shadow:0 0 0 2px color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, transparent);border-radius:50%;flex:none}.lc-br-tag{min-width:0;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);text-overflow:ellipsis;white-space:nowrap;border-radius:4px;max-width:220px;padding:0 6px;font-size:11px;overflow:hidden}.lc-br-tags{align-items:center;gap:4px;min-width:0;display:inline-flex}.lc-br-tool-plugin{color:var(--dsw-alias-brand-primary);background:color-mix(in srgb, var(--dsw-alias-brand-primary) 14%, transparent);border-color:#0000;border-radius:6px;font-size:12px}.lc-br-preview{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.lc-br-time,.lc-br-hits{color:var(--dsw-alias-label-secondary);flex:none;font-size:11px}.lc-br-content{flex-direction:column;gap:6px;padding:2px 6px 8px 26px;display:flex}.lc-br-dim{color:var(--dsw-alias-label-secondary)}";
12460
12638
  const tagId$4 = "dsh-context/browser.css";
12461
12639
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
12462
12640
  const tag = document.createElement("style");
package/lib/index.d.ts CHANGED
@@ -865,6 +865,7 @@ export declare const Config: z$1<Schemastery.ObjectS<NoInfer<{
865
865
  defaultPlacement: z$1<"all" | "sidebar" | "tab", "all" | "sidebar" | "tab", Mode>;
866
866
  defaultGranularity: z$1<"step" | "turn", "step" | "turn", Mode>;
867
867
  defaultTrendMode: z$1<"delta" | "total", "delta" | "total", Mode>;
868
+ defaultDeltaBase: z$1<"step" | "turn", "step" | "turn", Mode>;
868
869
  defaultToolSort: z$1<"count" | "name" | "size", "count" | "name" | "size", Mode>;
869
870
  defaultFileSort: z$1<"count" | "latest" | "path", "count" | "latest" | "path", Mode>;
870
871
  insightsEntry: z$1<"hide" | "show", "hide" | "show", Mode>;
@@ -878,6 +879,7 @@ export declare const Config: z$1<Schemastery.ObjectS<NoInfer<{
878
879
  defaultPlacement: z$1<"all" | "sidebar" | "tab", "all" | "sidebar" | "tab", Mode>;
879
880
  defaultGranularity: z$1<"step" | "turn", "step" | "turn", Mode>;
880
881
  defaultTrendMode: z$1<"delta" | "total", "delta" | "total", Mode>;
882
+ defaultDeltaBase: z$1<"step" | "turn", "step" | "turn", Mode>;
881
883
  defaultToolSort: z$1<"count" | "name" | "size", "count" | "name" | "size", Mode>;
882
884
  defaultFileSort: z$1<"count" | "latest" | "path", "count" | "latest" | "path", Mode>;
883
885
  insightsEntry: z$1<"hide" | "show", "hide" | "show", Mode>;
package/lib/index.js CHANGED
@@ -2659,6 +2659,7 @@ const Config = z$1.object({
2659
2659
  ]).default("all").loose()),
2660
2660
  defaultGranularity: volatileField(z$1.union(["step", "turn"]).default("step").loose()),
2661
2661
  defaultTrendMode: volatileField(z$1.union(["total", "delta"]).default("total").loose()),
2662
+ defaultDeltaBase: volatileField(z$1.union(["step", "turn"]).default("step").loose()),
2662
2663
  defaultToolSort: volatileField(z$1.union([
2663
2664
  "size",
2664
2665
  "count",
@@ -3403,6 +3404,7 @@ const SettingsSchema = z$1.object({
3403
3404
  ]).default("all").loose(),
3404
3405
  defaultGranularity: z$1.union(["step", "turn"]).default("step"),
3405
3406
  defaultTrendMode: z$1.union(["total", "delta"]).default("total").loose(),
3407
+ defaultDeltaBase: z$1.union(["step", "turn"]).default("step").loose(),
3406
3408
  defaultToolSort: z$1.union([
3407
3409
  "size",
3408
3410
  "count",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-context",
3
- "version": "0.59.2",
3
+ "version": "0.60.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",