dsh-context 0.45.0 → 0.46.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.
Files changed (2) hide show
  1. package/lib/client.js +136 -37
  2. package/package.json +1 -1
package/lib/client.js CHANGED
@@ -234,6 +234,8 @@ window.__ModuleLoader__.load({
234
234
  "browser.missingLive": "… 另有 {n} 条更早的消息也在上下文中(超出展示窗口)",
235
235
  "browser.approx": "该步骤涉及的部分已移除消息超出保留范围,以下为近似构成",
236
236
  "browser.deltaHint": "对比上轮末步的变动",
237
+ "browser.dna": "DNA 模式",
238
+ "browser.dnaTip": "按模型读取上下文的次序逐条展示每一项:系统提示词、工具定义,然后是按时间排列的消息;悬停查看条目,点击定位到下方列表",
237
239
  "browser.noHeader": "此数据来自旧版插件:仅提供 token 估算,无实际内容",
238
240
  "browser.noEpoch": "该步骤的头部内容(系统提示词 / 工具定义)不在保留范围内",
239
241
  "browser.headerMetaOnly": "此环境不支持按需读取头部内容,仅显示 token 估算",
@@ -518,6 +520,8 @@ window.__ModuleLoader__.load({
518
520
  "browser.missingLive": "… {n} earlier messages are also part of the context (outside the served window)",
519
521
  "browser.approx": "Some removed messages of this step exceed retention — the makeup below is approximate",
520
522
  "browser.deltaHint": "vs previous turn",
523
+ "browser.dna": "DNA Mode",
524
+ "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",
521
525
  "browser.noHeader": "Served by an older plugin build: token estimates only, no content",
522
526
  "browser.noEpoch": "The header content (System Prompt / Tool Schemas) of this step is outside retention",
523
527
  "browser.headerMetaOnly": "This environment cannot fetch header content on demand; token estimates only",
@@ -715,6 +719,8 @@ window.__ModuleLoader__.load({
715
719
  color: "#14b8a6"
716
720
  }
717
721
  ];
722
+ /** Category key → bar color, for per-item bands (the browser's DNA mode) that bypass the CATS-order part builders. */
723
+ const CAT_COLOR = Object.fromEntries(CATS.map((c) => [c.key, c.color]));
718
724
  const MESSAGE_CATS = [
719
725
  "user",
720
726
  "inject",
@@ -1891,6 +1897,32 @@ window.__ModuleLoader__.load({
1891
1897
  };
1892
1898
  }
1893
1899
  //#endregion
1900
+ //#region src/client/dna.ts
1901
+ function dnaOf(view) {
1902
+ const items = [];
1903
+ if (view.header !== null) {
1904
+ if (view.header.systemTokens !== void 0) items.push({
1905
+ key: "sys",
1906
+ cat: "system",
1907
+ tokens: view.header.systemTokens,
1908
+ time: view.header.time
1909
+ });
1910
+ for (const tool of view.header.tools) items.push({
1911
+ key: "tool:" + tool.name,
1912
+ cat: "tools",
1913
+ tokens: tool.tokens
1914
+ });
1915
+ }
1916
+ for (const n of view.nodes) items.push({
1917
+ key: "n" + String(n.seq),
1918
+ cat: n.cat,
1919
+ tokens: n.tokens,
1920
+ node: n,
1921
+ ...n.time !== void 0 ? { time: n.time } : {}
1922
+ });
1923
+ return items;
1924
+ }
1925
+ //#endregion
1894
1926
  //#region src/shared/fileOps.ts
1895
1927
  /** Parse a call's raw JSON arguments; non-string/malformed/non-record inputs yield null. */
1896
1928
  function parseCallArgs(raw) {
@@ -3193,6 +3225,11 @@ window.__ModuleLoader__.load({
3193
3225
  for (let i = requests.length - 1; i >= 0; i--) if ((requests[i].turn ?? 0) === turn) return requests[i];
3194
3226
  return null;
3195
3227
  }
3228
+ /**
3229
+ * DNA bands keep at least this share of the occupied region, so a tiny item (a 25-token user message in a 40k
3230
+ * context) stays a hoverable/clickable filament instead of a sub-pixel sliver. Tooltips still report true shares.
3231
+ */
3232
+ const DNA_MIN_BAND = .35;
3196
3233
  function makeContextBrowser(kit, StackedBar) {
3197
3234
  const { t, fmt, fmtTime, catLabel } = kit;
3198
3235
  const DetailNote = makeDetailNote(kit);
@@ -3207,6 +3244,8 @@ window.__ModuleLoader__.load({
3207
3244
  const [openElem, setOpenElem] = (0, react.useState)(null);
3208
3245
  const [rowQuery, setRowQuery] = (0, react.useState)("");
3209
3246
  const [toolSort, setToolSort] = (0, react.useState)("size");
3247
+ const [dna, setDna] = (0, react.useState)(false);
3248
+ const [dnaKey, setDnaKey] = (0, react.useState)(null);
3210
3249
  const onOpenCat = props.onOpenCat;
3211
3250
  const setCat = (c) => {
3212
3251
  setOpenCat(c);
@@ -3269,6 +3308,7 @@ window.__ModuleLoader__.load({
3269
3308
  const breakdown = req !== null ? req : data.current;
3270
3309
  const parts = partsOf(breakdown);
3271
3310
  const total = breakdown.total;
3311
+ const pinKey = openCat !== null && (breakdown[openCat] || 0) > 0 ? openCat : null;
3272
3312
  const pick = (v) => {
3273
3313
  setSel(v === "live" ? "live" : Number(v));
3274
3314
  setCat(null);
@@ -3278,6 +3318,33 @@ window.__ModuleLoader__.load({
3278
3318
  const prevView = refReq !== null ? assemble(data, headers, refReq.seq) : null;
3279
3319
  const prevByCat = prevView !== null ? byCatOf(prevView) : null;
3280
3320
  const byCat = byCatOf(view);
3321
+ const dnaLabel = (it) => {
3322
+ let base;
3323
+ if (!("node" in it)) base = it.cat === "system" ? catLabel("system") : it.key.slice(5);
3324
+ else {
3325
+ const n = it.node;
3326
+ base = n.skill !== void 0 ? t("node.skillTag", { name: n.skill }) : n.cat === "tool" ? n.tool ?? "?" : n.cat === "inject" ? t("form." + (n.form || "context")) : catLabel(n.cat);
3327
+ }
3328
+ return it.time !== void 0 ? base + " · " + fmtTime(it.time) : base;
3329
+ };
3330
+ const dnaItems = dna ? dnaOf(view) : null;
3331
+ const dnaByKey = new Map(dnaItems?.map((it) => [it.key, it]) ?? []);
3332
+ const dnaParts = dnaItems?.map((it) => ({
3333
+ key: it.key,
3334
+ color: CAT_COLOR[it.cat],
3335
+ value: it.tokens,
3336
+ label: dnaLabel(it),
3337
+ group: it.cat
3338
+ })) ?? null;
3339
+ const pickDna = (key) => {
3340
+ const it = dnaByKey.get(key);
3341
+ /* v8 ignore next 1 -- the bar only reports keys of the parts it was handed; defensive. */
3342
+ if (it === void 0) return;
3343
+ setCat(it.cat);
3344
+ setRowQuery("");
3345
+ setOpenElem(key);
3346
+ focusScrollRef.current = true;
3347
+ };
3281
3348
  const toolCount = (c) => countOf(view, byCat, c);
3282
3349
  const singleKeyOf = (c) => {
3283
3350
  if (c === "system") return view.header?.systemTokens !== void 0 ? "sys" : null;
@@ -3511,6 +3578,19 @@ window.__ModuleLoader__.load({
3511
3578
  className: "lc-card-title-text",
3512
3579
  children: t("browser.title")
3513
3580
  }),
3581
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3582
+ className: "lc-gran lc-br-dna-ctl",
3583
+ role: "group",
3584
+ title: t("browser.dnaTip"),
3585
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3586
+ type: "button",
3587
+ className: "lc-gran-btn" + (dna ? " lc-gran-on" : ""),
3588
+ onClick: () => {
3589
+ setDna((on) => !on);
3590
+ },
3591
+ children: t("browser.dna")
3592
+ })
3593
+ }),
3514
3594
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3515
3595
  className: "lc-br-hint",
3516
3596
  children: t("browser.deltaHint")
@@ -3554,13 +3634,15 @@ window.__ModuleLoader__.load({
3554
3634
  ]
3555
3635
  }),
3556
3636
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3557
- className: "lc-br-bar",
3637
+ className: "lc-br-bar" + (dna ? " lc-br-bar-dna" : ""),
3558
3638
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StackedBar, {
3559
- parts,
3639
+ parts: dnaParts ?? parts,
3560
3640
  height: 10,
3561
- hoverKey: linked ? linkKey : void 0,
3562
- onHoverKey: linked ? props.onHoverKey : void 0,
3563
- tip: false
3641
+ hoverKey: dna ? dnaKey ?? linkKey ?? pinKey : linkKey ?? pinKey,
3642
+ onHoverKey: dna ? setDnaKey : linked ? props.onHoverKey : void 0,
3643
+ tip: dna,
3644
+ onPickKey: dna ? pickDna : void 0,
3645
+ minBand: dna ? DNA_MIN_BAND : void 0
3564
3646
  })
3565
3647
  }),
3566
3648
  view.missingLive > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -3674,6 +3756,24 @@ window.__ModuleLoader__.load({
3674
3756
  const usedPct = scale > 0 ? total / scale * 100 : 0;
3675
3757
  const hovering = props.hoverKey !== null && props.hoverKey !== void 0;
3676
3758
  const showBox = free > 0 && hovering;
3759
+ const pickKey = props.onPickKey;
3760
+ const minBand = props.minBand !== void 0 && props.minBand > 0 ? props.minBand : 0;
3761
+ const visible = total > 0 ? props.parts.filter((p) => p.value > 0) : [];
3762
+ const widths = (() => {
3763
+ if (minBand === 0 || visible.length < 2) return visible.map((p) => p.value / scale * 100);
3764
+ const shares = visible.map((p) => p.value / total * 100);
3765
+ const floor = Math.min(minBand, 100 / visible.length);
3766
+ let pinned = 0;
3767
+ let pinnedRaw = 0;
3768
+ for (const s of shares) if (s < floor) {
3769
+ pinned += 1;
3770
+ pinnedRaw += s;
3771
+ }
3772
+ if (pinned === 0) return visible.map((p) => p.value / scale * 100);
3773
+ const restRoom = 100 - pinned * floor;
3774
+ const restRaw = 100 - pinnedRaw;
3775
+ return shares.map((s) => (s < floor ? floor : s * restRoom / restRaw) * total / scale);
3776
+ })();
3677
3777
  const reserve = props.reserve !== void 0 && props.max !== void 0 && props.max > 0 ? {
3678
3778
  ...props.reserve,
3679
3779
  max: props.max
@@ -3696,17 +3796,17 @@ window.__ModuleLoader__.load({
3696
3796
  let acc = 0;
3697
3797
  let rawTotal = 0;
3698
3798
  for (const p of props.parts) rawTotal += p.raw ?? p.value;
3699
- for (const p of props.parts) {
3700
- const pct = scale > 0 ? p.value / scale * 100 : 0;
3701
- if (p.key === props.hoverKey && p.value > 0) {
3799
+ for (let i = 0; i < visible.length; i++) {
3800
+ const p = visible[i];
3801
+ if (p.key === props.hoverKey) {
3702
3802
  const count = p.raw ?? p.value;
3703
3803
  tip = {
3704
- text: `${catLabel(p.key)} ≈${fmt(count)} (${rawTotal > 0 ? Math.round(count / rawTotal * 100) : 0}%) ` + t("overview.ofUsed"),
3705
- leftPct: Math.max(12, Math.min(acc + pct / 2, 88))
3804
+ text: `${p.label ?? catLabel(p.key)} ≈${fmt(count)} (${rawTotal > 0 ? Math.round(count / rawTotal * 100) : 0}%) ` + t("overview.ofUsed"),
3805
+ leftPct: Math.max(12, Math.min(acc + widths[i] / 2, 88))
3706
3806
  };
3707
3807
  break;
3708
3808
  }
3709
- acc += pct;
3809
+ acc += widths[i];
3710
3810
  }
3711
3811
  }
3712
3812
  }
@@ -3720,20 +3820,22 @@ window.__ModuleLoader__.load({
3720
3820
  setReserveOn(false);
3721
3821
  },
3722
3822
  children: [
3723
- total > 0 ? props.parts.map((p) => {
3724
- if (!p.value) return null;
3725
- const on = props.hoverKey !== void 0 && props.hoverKey === p.key;
3823
+ visible.map((p, i) => {
3824
+ const on = props.hoverKey !== void 0 && (props.hoverKey === p.key || p.group !== void 0 && props.hoverKey === p.group);
3726
3825
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3727
- className: "lc-stacked-seg" + (on ? " lc-stacked-seg-on" : ""),
3826
+ className: "lc-stacked-seg" + (on ? " lc-stacked-seg-on" : "") + (pickKey !== void 0 ? " lc-stacked-seg-pick" : ""),
3728
3827
  style: {
3729
- width: `${p.value / scale * 100}%`,
3828
+ width: `${widths[i]}%`,
3730
3829
  background: p.color
3731
3830
  },
3732
3831
  onMouseEnter: () => {
3733
3832
  if (props.onHoverKey !== void 0) props.onHoverKey(p.key);
3734
- }
3833
+ },
3834
+ onClick: pickKey !== void 0 ? () => {
3835
+ pickKey(p.key);
3836
+ } : void 0
3735
3837
  }, p.key);
3736
- }) : null,
3838
+ }),
3737
3839
  free > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3738
3840
  className: "lc-stacked-free" + (props.hoverKey === "free" ? " lc-stacked-free-on" : ""),
3739
3841
  style: { width: `${free / scale * 100}%` },
@@ -6343,7 +6445,7 @@ window.__ModuleLoader__.load({
6343
6445
  return function PluginInfo() {
6344
6446
  const [latest, setLatest] = (0, react.useState)(null);
6345
6447
  (0, react.useEffect)(() => {
6346
- if ("0.45.0".includes("-dev")) return;
6448
+ if ("0.46.0".includes("-dev")) return;
6347
6449
  let on = true;
6348
6450
  fetchLatestVersion().then((v) => {
6349
6451
  if (on && v) setLatest(v);
@@ -6352,8 +6454,8 @@ window.__ModuleLoader__.load({
6352
6454
  on = false;
6353
6455
  };
6354
6456
  }, []);
6355
- const update = latest !== null && isNewerVersion(latest, "0.45.0") ? latest : null;
6356
- const nameText = "dsh-context (v0.45.0)";
6457
+ const update = latest !== null && isNewerVersion(latest, "0.46.0") ? latest : null;
6458
+ const nameText = "dsh-context (v0.46.0)";
6357
6459
  const nameValue = [nameText];
6358
6460
  if (update) nameValue.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6359
6461
  className: "lc-pi-update",
@@ -7362,17 +7464,17 @@ window.__ModuleLoader__.load({
7362
7464
  const LABEL_FONT = 10;
7363
7465
  const LABEL_FONT_MIN = 6;
7364
7466
  const estTurnLabel = (turn) => 6.5 * String(turn).length;
7365
- const anchorOf = (req) => typeof req.prompt === "number" && req.prompt > 0 && req.total > 0 ? req.prompt / req.total : 1;
7366
- const barTotalOf = (req) => typeof req.prompt === "number" && req.prompt > 0 ? req.prompt : req.total;
7367
7467
  /**
7368
- * Focus a bar on one category (the browser's open category): the kept bucket carries its provider-anchored
7369
- * value, the other buckets zero, and the provider prompt drops — the downstream stack/anchor/tooltip math
7370
- * reads the derived record unchanged (`total` IS the plotted figure; the anchor becomes a no-op).
7468
+ * Focus a bar on one category (the browser's open category): the kept bucket carries its fold figure, the other
7469
+ * buckets zero, and `total` IS the plotted figure — the downstream stack/tooltip math reads the derived record
7470
+ * unchanged. The raw fold figures are plotted as-is: a per-request rescale against the provider prompt would drift
7471
+ * with the heuristic's ratio error and fake growth into constant categories (a never-changing system prompt must
7472
+ * plot flat).
7371
7473
  */
7372
7474
  const focusOf = (req, cat) => {
7373
7475
  const key = cat;
7374
- const { prompt: _prompt, output: _output, ...out } = req;
7375
- const v = Math.round((req[key] || 0) * anchorOf(req));
7476
+ const out = { ...req };
7477
+ const v = req[key] || 0;
7376
7478
  out.total = v;
7377
7479
  for (const c of CATS) out[c.key] = c.key === key ? v : 0;
7378
7480
  return out;
@@ -7448,7 +7550,7 @@ window.__ModuleLoader__.load({
7448
7550
  })] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7449
7551
  className: "lc-bar-stack",
7450
7552
  children: CATS.map((c) => {
7451
- const v = (req[c.key] || 0) * anchorOf(req);
7553
+ const v = req[c.key] || 0;
7452
7554
  if (!v) return null;
7453
7555
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7454
7556
  "data-cat": c.key,
@@ -7488,10 +7590,7 @@ window.__ModuleLoader__.load({
7488
7590
  if (up > maxUp) maxUp = up;
7489
7591
  if (down > maxDown) maxDown = down;
7490
7592
  }
7491
- else for (const req of requests) {
7492
- const bt = barTotalOf(req);
7493
- if (bt > maxTotal) maxTotal = bt;
7494
- }
7593
+ else for (const req of requests) if (req.total > maxTotal) maxTotal = req.total;
7495
7594
  const span = Math.max(1, maxUp + maxDown);
7496
7595
  const deltaScale = CHART_H / span;
7497
7596
  const upPx = Math.round(maxUp * deltaScale);
@@ -7633,8 +7732,8 @@ window.__ModuleLoader__.load({
7633
7732
  }
7634
7733
  return [head, focus !== null ? t("tip.cat", {
7635
7734
  cat: catLabel(focus),
7636
- n: fmt(barTotalOf(req))
7637
- }) : t("tip.total", { n: fmt(barTotalOf(req)) })];
7735
+ n: fmt(req.total)
7736
+ }) : t("tip.total", { n: fmt(req.total) })];
7638
7737
  };
7639
7738
  const hoveredIdx = props.hoveredSeq !== null ? requests.findIndex((r) => r.seq === props.hoveredSeq) : -1;
7640
7739
  const hoveredReq = hoveredIdx >= 0 ? requests[hoveredIdx] : null;
@@ -8515,7 +8614,7 @@ window.__ModuleLoader__.load({
8515
8614
  }
8516
8615
  //#endregion
8517
8616
  //#region \0dsh-global-css:/home/runner/work/dsh-context/dsh-context/src/client/styles/stackedBar.css.mjs
8518
- const css$9 = ".lc-stacked-wrap{width:100%;position:relative}.lc-stacked{background:#8080802e;border-radius:5px;width:100%;display:flex;position:relative;overflow:hidden}.lc-occupied-box{border:2px solid var(--dsw-alias-label-tertiary);box-sizing:border-box;pointer-events:none;opacity:0;box-shadow:0 0 0 1px var(--dsw-alias-bg-layer-2);transition:opacity var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-radius:5px;position:absolute;top:0;bottom:0;left:0}.lc-occupied-box-on{opacity:1}.lc-bar-tip{z-index:5;white-space:nowrap;padding:3px 8px;bottom:calc(100% + 6px);transform:translate(-50%)}.lc-bar-tip-on{opacity:1}.lc-stacked>div{height:100%}.lc-stacked-seg{transition:filter var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out), opacity var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out)}.lc-stacked-free{box-sizing:border-box;transition:box-shadow var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out), opacity var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out)}.lc-stacked-seg-on{filter:brightness(1.18)}.lc-reserve{z-index:1;pointer-events:auto;cursor:help;background:repeating-linear-gradient(45deg, color-mix(in srgb, var(--dsw-alias-state-warn-primary) 24%, transparent) 0 5px, transparent 5px 10px);position:absolute;top:0;bottom:0}.lc-stacked-free-on{border:2px dashed var(--dsw-alias-label-secondary);border-radius:3px}.lc-stacked-dim .lc-stacked-seg{opacity:.35}.lc-stacked-dim .lc-stacked-seg-on{opacity:1}.lc-stacked-dim .lc-stacked-free{opacity:.35}.lc-stacked-dim .lc-stacked-free-on{opacity:1}.lc-legend{grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:6px 14px;margin-top:10px;display:grid}.lc-chip{min-width:0;color:var(--dsw-alias-label-primary);cursor:pointer;transition:background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-radius:6px;align-items:center;gap:5px;padding:1px 6px;display:flex}.lc-chip-label{white-space:nowrap;text-overflow:ellipsis;min-width:0;font-weight:600;overflow:hidden}.lc-chip-nums{white-space:nowrap;flex:none;align-items:baseline;gap:6px;margin-left:auto;display:inline-flex}.lc-chip i,.lc-detail-row i{border-radius:2px;width:8px;height:8px;display:inline-block}.lc-chip i{transition:box-shadow var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out)}.lc-chip em{color:var(--dsw-alias-label-secondary);font-style:normal}.lc-chip-on{background:var(--dsw-alias-interactive-bg-hover);font-weight:600}.lc-chip-on i{box-shadow:0 0 0 1px var(--dsw-alias-brand-primary)}";
8617
+ const css$9 = ".lc-stacked-wrap{width:100%;position:relative}.lc-stacked{background:#8080802e;border-radius:5px;width:100%;display:flex;position:relative;overflow:hidden}.lc-occupied-box{border:2px solid var(--dsw-alias-label-tertiary);box-sizing:border-box;pointer-events:none;opacity:0;box-shadow:0 0 0 1px var(--dsw-alias-bg-layer-2);transition:opacity var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-radius:5px;position:absolute;top:0;bottom:0;left:0}.lc-occupied-box-on{opacity:1}.lc-bar-tip{z-index:5;white-space:nowrap;padding:3px 8px;bottom:calc(100% + 6px);transform:translate(-50%)}.lc-bar-tip-on{opacity:1}.lc-stacked>div{height:100%}.lc-stacked-seg-pick{cursor:pointer}.lc-stacked-seg{transition:filter var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out), opacity var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out)}.lc-stacked-free{box-sizing:border-box;transition:box-shadow var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out), opacity var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out)}.lc-stacked-seg-on{filter:brightness(1.18)}.lc-reserve{z-index:1;pointer-events:auto;cursor:help;background:repeating-linear-gradient(45deg, color-mix(in srgb, var(--dsw-alias-state-warn-primary) 24%, transparent) 0 5px, transparent 5px 10px);position:absolute;top:0;bottom:0}.lc-stacked-free-on{border:2px dashed var(--dsw-alias-label-secondary);border-radius:3px}.lc-stacked-dim .lc-stacked-seg{opacity:.35}.lc-stacked-dim .lc-stacked-seg-on{opacity:1}.lc-stacked-dim .lc-stacked-free{opacity:.35}.lc-stacked-dim .lc-stacked-free-on{opacity:1}.lc-legend{grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:6px 14px;margin-top:10px;display:grid}.lc-chip{min-width:0;color:var(--dsw-alias-label-primary);cursor:pointer;transition:background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-radius:6px;align-items:center;gap:5px;padding:1px 6px;display:flex}.lc-chip-label{white-space:nowrap;text-overflow:ellipsis;min-width:0;font-weight:600;overflow:hidden}.lc-chip-nums{white-space:nowrap;flex:none;align-items:baseline;gap:6px;margin-left:auto;display:inline-flex}.lc-chip i,.lc-detail-row i{border-radius:2px;width:8px;height:8px;display:inline-block}.lc-chip i{transition:box-shadow var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out)}.lc-chip em{color:var(--dsw-alias-label-secondary);font-style:normal}.lc-chip-on{background:var(--dsw-alias-interactive-bg-hover);font-weight:600}.lc-chip-on i{box-shadow:0 0 0 1px var(--dsw-alias-brand-primary)}";
8519
8618
  const tagId$9 = "dsh-context/stackedBar.css";
8520
8619
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$9) + "]") === null) {
8521
8620
  const tag = document.createElement("style");
@@ -8581,7 +8680,7 @@ window.__ModuleLoader__.load({
8581
8680
  }
8582
8681
  //#endregion
8583
8682
  //#region \0dsh-global-css:/home/runner/work/dsh-context/dsh-context/src/client/styles/browser.css.mjs
8584
- const css$3 = ".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-actual{color:var(--dsw-alias-state-success-primary)}.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-retry:hover{filter:brightness(1.15)}.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-row:hover,.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-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-elem-row:hover{background:var(--dsw-alias-interactive-bg-hover)}.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{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)}";
8683
+ const css$3 = ".lc-br-dna-ctl{flex:none;margin-left:0}.lc-br-bar-dna .lc-stacked-seg{box-shadow:inset -1px 0 0 var(--dsw-alias-bg-layer-1)}.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-actual{color:var(--dsw-alias-state-success-primary)}.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-retry:hover{filter:brightness(1.15)}.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-row:hover,.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-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-elem-row:hover{background:var(--dsw-alias-interactive-bg-hover)}.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{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)}";
8585
8684
  const tagId$3 = "dsh-context/browser.css";
8586
8685
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
8587
8686
  const tag = document.createElement("style");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-context",
3
- "version": "0.45.0",
3
+ "version": "0.46.0",
4
4
  "description": "A DeepSeek Harness plugin for context insight and management, with context dashboard and context command, for understanding how the context is made of, and how it evolves.",
5
5
  "author": "bowenliang123",
6
6
  "repository": {