dsh-context 0.48.0 → 0.49.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
@@ -10,7 +10,7 @@
10
10
 
11
11
  [`dsh-context`](https://www.npmjs.com/package/dsh-context) provides full context lifecycle management features.
12
12
  - **Context tab** — an UI context dashboard for DeepSeek Harness's context stats, composition, trend, events, and messages.
13
- - **Context panel** — the same dashboard as a right-sidebar tab (dsh 0.1.5-alpha.2+): pick **Context** on the sidebar's guide page and the panel opens beside the chat.
13
+ - **Context panel** — the same dashboard as a right-sidebar tab (dsh 0.1.5-rc.1+): pick **Context** on the sidebar's guide page and the panel opens beside the chat.
14
14
  - **`/context` command** — the slash command shows the context model for current context composition and recent context evolution.
15
15
 
16
16
  ## Install / Update
package/lib/client.js CHANGED
@@ -10,6 +10,7 @@ window.__ModuleLoader__.load({
10
10
  //#region src/client/i18n.ts
11
11
  const DICT_ZH = {
12
12
  "tab": "上下文",
13
+ "sidebar.guideDescription": "查看这个会话的上下文构成、每步变化与消息列表。",
13
14
  "cat.system": "系统提示词",
14
15
  "cat.tools": "工具定义",
15
16
  "cat.user": "用户消息",
@@ -31,7 +32,7 @@ window.__ModuleLoader__.load({
31
32
  "stats.toolCalls": "工具调用",
32
33
  "stats.images": "图片",
33
34
  "stats.cost": "预估费用",
34
- "stats.costTip": "按 DeepSeek 官方刊例价估算整个会话的累计费用:输入区分缓存命中/未命中,输出含思考;按请求时间区分高峰(北京时间工作日 9:00–12:00、14:00–18:00)与空闲时段(半价,周末全天均为空闲时段)。适用于 deepseek-v4.1-flash / deepseek-v4-pro(不限 provider;V4.1 Pro 上线前,V4 Pro 请求将被路由并按 V4.1 Flash 单价计费),价格写死在代码中,仅供参考。",
35
+ "stats.costTip": "按 DeepSeek 官方刊例价估算整个会话的累计费用:输入区分缓存命中/未命中,输出含思考;按请求时间区分高峰(北京时间工作日 9:00–12:00、14:00–18:00)与空闲时段(半价,周末全天均为空闲时段)。适用于 deepseek-v4.1-flash / deepseek-flash / deepseek-v4-pro(不限 provider;V4.1 Pro 上线前,V4 Pro 请求将被路由并按 V4.1 Flash 单价计费),价格写死在代码中,仅供参考。",
35
36
  "stats.costPriceHead": "每百万 tokens 价格(高峰 | 空闲半价):",
36
37
  "stats.costHit": "命中",
37
38
  "stats.costMiss": "未命中",
@@ -270,6 +271,8 @@ window.__ModuleLoader__.load({
270
271
  "rich.md": "Markdown",
271
272
  "rich.toMd": "按 Markdown 渲染查看",
272
273
  "rich.toRaw": "查看原始文本",
274
+ "rich.copy": "复制原文",
275
+ "rich.copied": "已复制",
273
276
  "rich.md.copy": "复制",
274
277
  "rich.md.copied": "已复制",
275
278
  "rich.md.footnotes": "脚注",
@@ -299,6 +302,7 @@ window.__ModuleLoader__.load({
299
302
  };
300
303
  const DICT_EN = {
301
304
  "tab": "Context",
305
+ "sidebar.guideDescription": "Inspect this session's context composition, per-step history, and messages.",
302
306
  "cat.system": "System Prompt",
303
307
  "cat.tools": "Tool Schemas",
304
308
  "cat.user": "User Messages",
@@ -320,7 +324,7 @@ window.__ModuleLoader__.load({
320
324
  "stats.toolCalls": "Tool Calls",
321
325
  "stats.images": "Images",
322
326
  "stats.cost": "Cost",
323
- "stats.costTip": "Rough cumulative cost of the whole session at DeepSeek’s list prices: input split by cache hit/miss, output includes reasoning; each request is priced at the peak (Beijing Time weekdays 09:00–12:00, 14:00–18:00) or half-price off-peak rate by its time — weekends bill at off-peak all day. Applies to deepseek-v4.1-flash / deepseek-v4-pro on any provider (until V4.1 Pro ships, Pro requests are routed to and billed at V4.1 Flash rates); prices are hardcoded, for reference only.",
327
+ "stats.costTip": "Rough cumulative cost of the whole session at DeepSeek’s list prices: input split by cache hit/miss, output includes reasoning; each request is priced at the peak (Beijing Time weekdays 09:00–12:00, 14:00–18:00) or half-price off-peak rate by its time — weekends bill at off-peak all day. Applies to deepseek-v4.1-flash / deepseek-flash / deepseek-v4-pro on any provider (until V4.1 Pro ships, Pro requests are routed to and billed at V4.1 Flash rates); prices are hardcoded, for reference only.",
324
328
  "stats.costPriceHead": "Per-1M-token rates (peak | off-peak at half price):",
325
329
  "stats.costHit": "hit",
326
330
  "stats.costMiss": "miss",
@@ -559,6 +563,8 @@ window.__ModuleLoader__.load({
559
563
  "rich.md": "Markdown",
560
564
  "rich.toMd": "View as Markdown",
561
565
  "rich.toRaw": "View Raw Text",
566
+ "rich.copy": "Copy Raw Text",
567
+ "rich.copied": "Copied",
562
568
  "rich.md.copy": "Copy",
563
569
  "rich.md.copied": "Copied",
564
570
  "rich.md.footnotes": "Footnotes",
@@ -2814,7 +2820,7 @@ window.__ModuleLoader__.load({
2814
2820
  /**
2815
2821
  * RichText — the raw/markdown body for the Context browser's detail sections. Markdown renders via the harness's shared MarkdownText (GFM,
2816
2822
  * sanitized, resolved from the platform module table — zero plugin-side markdown dependency); raw is a line-numbered `<pre>`. The Raw/MD
2817
- * switch sits at a section head's right edge (RichSwitch; per-card mode via useRichMode).
2823
+ * switch sits at a section head's right edge (RichSwitch; per-card mode via useRichMode), with the copy-raw control (RichCopy) beside it.
2818
2824
  */
2819
2825
  const Markdown = _deepseek_ai_dsh_client_ui_primitives.MarkdownText;
2820
2826
  function makeRichText(kit) {
@@ -2851,6 +2857,28 @@ window.__ModuleLoader__.load({
2851
2857
  }, index))
2852
2858
  });
2853
2859
  }
2860
+ function RichCopy(props) {
2861
+ const [copied, setCopied] = (0, react.useState)(false);
2862
+ const onCopy = (0, react.useCallback)(() => {
2863
+ if (copied) return;
2864
+ (0, _deepseek_ai_dsh_client_ui_primitives.writeClipboard)(props.text).then((ok) => {
2865
+ if (!ok) return;
2866
+ setCopied(true);
2867
+ window.setTimeout(() => {
2868
+ setCopied(false);
2869
+ }, 1200);
2870
+ });
2871
+ }, [copied, props.text]);
2872
+ const label = copied ? t("rich.copied") : t("rich.copy");
2873
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2874
+ type: "button",
2875
+ className: "lc-rich-copy" + (copied ? " lc-rich-copy-on" : ""),
2876
+ title: label,
2877
+ "aria-label": label,
2878
+ onClick: onCopy,
2879
+ children: copied ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCheckOutline16, { size: 13 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCopyOutline16, { size: 13 })
2880
+ });
2881
+ }
2854
2882
  function RichText(props) {
2855
2883
  const mdLabels = (0, react.useMemo)(() => ({
2856
2884
  code: {
@@ -2871,6 +2899,7 @@ window.__ModuleLoader__.load({
2871
2899
  return {
2872
2900
  RichText,
2873
2901
  RichSwitch,
2902
+ RichCopy,
2874
2903
  useRichMode
2875
2904
  };
2876
2905
  }
@@ -2952,7 +2981,7 @@ window.__ModuleLoader__.load({
2952
2981
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2953
2982
  className: "lc-ts-card",
2954
2983
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2955
- className: "lc-ts-card-head",
2984
+ className: "lc-ts-card-head" + (props.foldHead === true ? " lc-ts-card-head-wrap" : ""),
2956
2985
  children: [
2957
2986
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", {
2958
2987
  className: props.labelClass,
@@ -2980,10 +3009,11 @@ window.__ModuleLoader__.load({
2980
3009
  const lineCount = (0, react.useMemo)(() => lineCountOf(props.text), [props.text]);
2981
3010
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Section, {
2982
3011
  label: props.label,
2983
- actions: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(rich.RichSwitch, {
3012
+ foldHead: true,
3013
+ actions: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(rich.RichSwitch, {
2984
3014
  mode,
2985
3015
  onPick: setMode
2986
- }),
3016
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(rich.RichCopy, { text: props.text })] }),
2987
3017
  meta: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2988
3018
  className: "lc-ts-card-meta",
2989
3019
  children: props.lines(lineCount)
@@ -6604,7 +6634,7 @@ window.__ModuleLoader__.load({
6604
6634
  return function PluginInfo() {
6605
6635
  const [latest, setLatest] = (0, react.useState)(null);
6606
6636
  (0, react.useEffect)(() => {
6607
- if ("0.48.0".includes("-dev")) return;
6637
+ if ("0.49.0".includes("-dev")) return;
6608
6638
  let on = true;
6609
6639
  fetchLatestVersion().then((v) => {
6610
6640
  if (on && v) setLatest(v);
@@ -6613,8 +6643,8 @@ window.__ModuleLoader__.load({
6613
6643
  on = false;
6614
6644
  };
6615
6645
  }, []);
6616
- const update = latest !== null && isNewerVersion(latest, "0.48.0") ? latest : null;
6617
- const nameText = "dsh-context (v0.48.0)";
6646
+ const update = latest !== null && isNewerVersion(latest, "0.49.0") ? latest : null;
6647
+ const nameText = "dsh-context (v0.49.0)";
6618
6648
  const nameValue = [nameText];
6619
6649
  if (update) nameValue.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6620
6650
  className: "lc-pi-update",
@@ -7148,7 +7178,7 @@ window.__ModuleLoader__.load({
7148
7178
  */
7149
7179
  function sessionPrices(currency) {
7150
7180
  return ["flash", "pro"].map((id) => ({
7151
- family: id === "flash" ? "deepseek-v4.1-flash" : "deepseek-v4-pro",
7181
+ family: id === "flash" ? "deepseek-v4.1-flash / deepseek-flash" : "deepseek-v4-pro",
7152
7182
  peak: PRICES[currency][id].peak,
7153
7183
  off: PRICES[currency][id].off
7154
7184
  }));
@@ -8722,7 +8752,7 @@ window.__ModuleLoader__.load({
8722
8752
  //#endregion
8723
8753
  //#region src/client/sidebar.ts
8724
8754
  /**
8725
- * The right Sidebar's Context tab (dsh 0.1.5-alpha.2+).
8755
+ * The right Sidebar's Context tab (dsh 0.1.5-rc.1+).
8726
8756
  *
8727
8757
  * The tab reuses the Context conversation-view component VERBATIM: the
8728
8758
  * `sidebar.right.pane.tab` seat is session-scoped and delivers the same
@@ -8731,10 +8761,10 @@ window.__ModuleLoader__.load({
8731
8761
  * one component with one data path. The tab type contributes a guide entry, so
8732
8762
  * the sidebar's guide page offers "Context" and picking it opens the panel —
8733
8763
  * the product's own path, exactly as the shipped Files type does: a capsule of
8734
- * glyph + title.
8764
+ * glyph, title, and description line.
8735
8765
  *
8736
8766
  * OPTIONAL BY CONTRACT. `ctx.sidebarRightTabs` and the seat ship only on the
8737
- * 0.1.5 line (0.1.5-alpha.2+ supported); the registration therefore rides a
8767
+ * 0.1.5 line (0.1.5-rc.1+ supported); the registration therefore rides a
8738
8768
  * DEFERRED inject (the plugin's hard injects stay `slots` + `locale`), so on
8739
8769
  * every older supported line the callback never fires, the plugin fiber never
8740
8770
  * pends, and nothing is registered. The registry is re-proved structurally and
@@ -8792,6 +8822,7 @@ window.__ModuleLoader__.load({
8792
8822
  guide: [{
8793
8823
  order: GUIDE_ORDER,
8794
8824
  title: () => t("tab"),
8825
+ description: () => t("sidebar.guideDescription"),
8795
8826
  icon: guideIcon()
8796
8827
  }]
8797
8828
  });
@@ -8939,7 +8970,7 @@ window.__ModuleLoader__.load({
8939
8970
  }
8940
8971
  //#endregion
8941
8972
  //#region \0dsh-global-css:/home/runner/work/dsh-context/dsh-context/src/client/styles/browser.css.mjs
8942
- const css$3 = ".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(1px, 25%)), 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-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)}";
8973
+ const css$3 = ".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-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)}";
8943
8974
  const tagId$3 = "dsh-context/browser.css";
8944
8975
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
8945
8976
  const tag = document.createElement("style");
@@ -8950,7 +8981,7 @@ window.__ModuleLoader__.load({
8950
8981
  }
8951
8982
  //#endregion
8952
8983
  //#region \0dsh-global-css:/home/runner/work/dsh-context/dsh-context/src/client/styles/detailSections.css.mjs
8953
- const css$2 = ".lc-ts-card{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;min-width:0;overflow:hidden}.lc-ts-card-head{color:var(--dsw-alias-label-secondary);border-bottom:1px solid var(--dsw-alias-border-l1);align-items:center;gap:8px;padding:6px 10px;font-size:11px;font-weight:600;display:flex}.lc-ts-card-head b{color:var(--dsw-alias-label-primary)}.lc-ts-call-name{font-size:13px;font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, monospace);text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.lc-ts-card-count{margin-left:auto}.lc-ts-card-right{align-items:center;gap:8px;margin-left:auto;display:inline-flex}.lc-ts-card-meta{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-variant-numeric:tabular-nums;font-size:11px;font-weight:400}.lc-ts-call-state{white-space:nowrap;font-size:11px;font-weight:600;line-height:1;font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, monospace);border-radius:999px;flex:none;align-items:center;gap:4px;padding:2px 7px;display:inline-flex}.lc-ts-call-state i{background:currentColor;border-radius:50%;flex:none;width:6px;height:6px}.lc-ts-call-ok{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 12%, transparent)}.lc-ts-call-err{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent)}.lc-ts-desc-body{color:var(--dsw-alias-label-primary);white-space:pre-wrap;word-break:break-word;scrollbar-width:thin;max-height:320px;margin:0;padding:8px 10px;font-size:12px;line-height:1.55;overflow-y:auto}.lc-ts-lines{counter-reset:lc-line}.lc-ts-line{padding-left:26px;display:block;position:relative}.lc-ts-line:before{content:counter(lc-line);counter-increment:lc-line;text-align:right;width:20px;color:var(--dsw-alias-label-tertiary);user-select:none;padding-right:6px;font-size:11px;position:absolute;left:0}.lc-ts-line:empty:after{content:\"​\"}.lc-ts-param-row{border-top:1px solid var(--dsw-alias-border-l1);grid-template-columns:minmax(0,140px) minmax(0,90px) 56px minmax(0,1fr);align-items:baseline;gap:2px 10px;padding:6px 10px;font-size:12px;display:grid}.lc-ts-param-row:first-of-type{border-top:0}.lc-ts-param-name{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-weight:600;overflow:hidden}.lc-ts-param-type{color:var(--dsw-alias-label-secondary);font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, monospace);text-overflow:ellipsis;white-space:nowrap;font-size:11px;overflow:hidden}.lc-ts-param-req{color:var(--dsw-alias-state-warn-primary);font-size:11px;font-weight:600}.lc-ts-param-req-off{color:var(--dsw-alias-label-secondary);font-size:11px}.lc-ts-param-desc{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;grid-column:1/-1;line-height:1.5}.lc-ts-params-empty{color:var(--dsw-alias-label-secondary);padding:8px 10px;font-size:12px}.lc-ts-arg-row{border-top:1px solid var(--dsw-alias-border-l1);grid-template-columns:minmax(0,96px) 1fr;align-items:start;column-gap:12px;padding:6px 10px;font-size:12px;display:grid}.lc-ts-arg-row:first-of-type{border-top:0}.lc-ts-arg-row .lc-ts-param-name{text-overflow:unset;white-space:normal;overflow-wrap:anywhere;overflow:visible}.lc-ts-arg-val{color:var(--dsw-alias-label-primary);font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, monospace);white-space:pre-wrap;word-break:break-word;scrollbar-width:thin;max-height:200px;font-size:12px;line-height:1.55;overflow-y:auto}.lc-ts-json{flex-direction:column;gap:4px;display:flex}.lc-ts-json-toggle{color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;transition:color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border:0;align-self:flex-start;padding:0;font-size:11px}.lc-ts-json-toggle:hover{color:var(--dsw-alias-label-primary);text-decoration:underline}.lc-rich-seg{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;gap:2px;margin-left:auto;padding:1px;display:flex}.lc-rich-seg-btn{color:var(--dsw-alias-label-secondary);cursor:pointer;transition:color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border:0;border-radius:5px;padding:3px 8px;font-family:inherit;font-size:11px;line-height:1}.lc-rich-seg-btn:hover{color:var(--dsw-alias-label-primary)}.lc-rich-seg-on,.lc-rich-seg-on:hover{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.lc-ts-desc-md{color:var(--dsw-alias-label-primary);word-break:break-word;overflow-wrap:anywhere;scrollbar-width:thin;min-width:0;max-height:320px;padding:4px 10px;font-size:12px;line-height:1.55;overflow:hidden auto}.lc-ts-desc-md>div{font-size:13px;line-height:1.55}.lc-ts-desc-md div :is(h1,h2,h3,h4,h5,h6){margin:10px 0 4px;font-size:13px;font-weight:600}.lc-ts-desc-md div p{white-space:pre-line;margin:6px 0}.lc-ts-desc-md div p br{display:none}.lc-ts-desc-md div pre{white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word;margin:6px 0}.lc-ts-desc-md div :not(pre)>code{box-decoration-break:clone;padding:1px 5px;line-height:1.3;font-size:1em!important}.lc-ts-desc-md div table code{font-size:inherit}";
8984
+ const css$2 = ".lc-ts-card{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;min-width:0;overflow:hidden}.lc-ts-card-head{color:var(--dsw-alias-label-secondary);border-bottom:1px solid var(--dsw-alias-border-l1);align-items:center;gap:8px;padding:6px 10px;font-size:11px;font-weight:600;display:flex}.lc-ts-card-head-wrap{flex-wrap:wrap}.lc-ts-card-head b{color:var(--dsw-alias-label-primary)}.lc-ts-call-name{font-size:13px;font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, monospace);text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.lc-ts-card-count{margin-left:auto}.lc-ts-card-right{align-items:center;gap:8px;margin-left:auto;display:inline-flex}.lc-ts-card-meta{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-variant-numeric:tabular-nums;font-size:11px;font-weight:400}.lc-ts-call-state{white-space:nowrap;font-size:11px;font-weight:600;line-height:1;font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, monospace);border-radius:999px;flex:none;align-items:center;gap:4px;padding:2px 7px;display:inline-flex}.lc-ts-call-state i{background:currentColor;border-radius:50%;flex:none;width:6px;height:6px}.lc-ts-call-ok{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 12%, transparent)}.lc-ts-call-err{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent)}.lc-ts-desc-body{color:var(--dsw-alias-label-primary);white-space:pre-wrap;word-break:break-word;scrollbar-width:thin;max-height:320px;margin:0;padding:8px 10px;font-size:12px;line-height:1.55;overflow-y:auto}.lc-ts-lines{counter-reset:lc-line}.lc-ts-line{padding-left:26px;display:block;position:relative}.lc-ts-line:before{content:counter(lc-line);counter-increment:lc-line;text-align:right;width:20px;color:var(--dsw-alias-label-tertiary);user-select:none;padding-right:6px;font-size:11px;position:absolute;left:0}.lc-ts-line:empty:after{content:\"​\"}.lc-ts-param-row{border-top:1px solid var(--dsw-alias-border-l1);grid-template-columns:minmax(0,140px) minmax(0,90px) 56px minmax(0,1fr);align-items:baseline;gap:2px 10px;padding:6px 10px;font-size:12px;display:grid}.lc-ts-param-row:first-of-type{border-top:0}.lc-ts-param-name{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-weight:600;overflow:hidden}.lc-ts-param-type{color:var(--dsw-alias-label-secondary);font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, monospace);text-overflow:ellipsis;white-space:nowrap;font-size:11px;overflow:hidden}.lc-ts-param-req{color:var(--dsw-alias-state-warn-primary);font-size:11px;font-weight:600}.lc-ts-param-req-off{color:var(--dsw-alias-label-secondary);font-size:11px}.lc-ts-param-desc{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;grid-column:1/-1;line-height:1.5}.lc-ts-params-empty{color:var(--dsw-alias-label-secondary);padding:8px 10px;font-size:12px}.lc-ts-arg-row{border-top:1px solid var(--dsw-alias-border-l1);grid-template-columns:minmax(0,96px) 1fr;align-items:start;column-gap:12px;padding:6px 10px;font-size:12px;display:grid}.lc-ts-arg-row:first-of-type{border-top:0}.lc-ts-arg-row .lc-ts-param-name{text-overflow:unset;white-space:normal;overflow-wrap:anywhere;overflow:visible}.lc-ts-arg-val{color:var(--dsw-alias-label-primary);font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, monospace);white-space:pre-wrap;word-break:break-word;scrollbar-width:thin;max-height:200px;font-size:12px;line-height:1.55;overflow-y:auto}.lc-ts-json{flex-direction:column;gap:4px;display:flex}.lc-ts-json-toggle{color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;transition:color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border:0;align-self:flex-start;padding:0;font-size:11px}.lc-ts-json-toggle:hover{color:var(--dsw-alias-label-primary);text-decoration:underline}.lc-rich-seg{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;gap:2px;margin-left:auto;padding:1px;display:flex}.lc-rich-seg-btn{color:var(--dsw-alias-label-secondary);cursor:pointer;transition:color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border:0;border-radius:5px;padding:3px 8px;font-family:inherit;font-size:11px;line-height:1}.lc-rich-seg-btn:hover{color:var(--dsw-alias-label-primary)}.lc-rich-seg-on,.lc-rich-seg-on:hover{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.lc-rich-copy{color:var(--dsw-alias-label-secondary);cursor:pointer;transition: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;padding:2px;display:inline-flex}.lc-rich-copy:hover{color:var(--dsw-alias-label-primary)}.lc-rich-copy-on,.lc-rich-copy-on:hover{color:var(--dsw-alias-state-success-primary)}.lc-ts-desc-md{color:var(--dsw-alias-label-primary);word-break:break-word;overflow-wrap:anywhere;scrollbar-width:thin;min-width:0;max-height:320px;padding:4px 10px;font-size:12px;line-height:1.55;overflow:hidden auto}.lc-ts-desc-md>div{font-size:13px;line-height:1.55}.lc-ts-desc-md div :is(h1,h2,h3,h4,h5,h6){margin:10px 0 4px;font-size:13px;font-weight:600}.lc-ts-desc-md div p{white-space:pre-line;margin:6px 0}.lc-ts-desc-md div p br{display:none}.lc-ts-desc-md div pre{white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word;margin:6px 0}.lc-ts-desc-md div :not(pre)>code{box-decoration-break:clone;padding:1px 5px;line-height:1.3;font-size:1em!important}.lc-ts-desc-md div table code{font-size:inherit}";
8954
8985
  const tagId$2 = "dsh-context/detailSections.css";
8955
8986
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
8956
8987
  const tag = document.createElement("style");
package/lib/index.d.ts CHANGED
@@ -129,10 +129,10 @@ interface TimelineState {
129
129
  archived: SurfaceNode[];
130
130
  /**
131
131
  * Session-cost raw material: cumulative billed-token totals per DeepSeek
132
- * V4 model family and pricing period (see SessionCostUsage). Running
132
+ * model family and pricing period (see SessionCostUsage). Running
133
133
  * totals — never trimmed, so the estimate always covers the COMPLETE
134
134
  * session log even after the request/event retention bounds cut in.
135
- * Absent until a v4-flash / v4-pro request reports usage.
135
+ * Absent until a DeepSeek flash/pro request reports usage.
136
136
  */
137
137
  cost?: SessionCostUsage;
138
138
  archiveFloor?: number;
@@ -565,10 +565,11 @@ interface CostFamilyUsage {
565
565
  }
566
566
  /**
567
567
  * The session-cost estimate's raw material: cumulative provider-reported
568
- * token totals per DeepSeek V4 model family (matched on the model NAME,
568
+ * token totals per DeepSeek model family (matched on the model NAME,
569
569
  * provider-agnostic) and pricing period. The Client prices these with its
570
570
  * hardcoded list-price table in the locale's currency. Absent until a
571
- * deepseek-v4.1-flash / deepseek-v4-pro request reports usage.
571
+ * deepseek-flash / deepseek-v4.1-flash / deepseek-v4-pro request reports
572
+ * usage.
572
573
  */
573
574
  interface SessionCostUsage {
574
575
  flash?: CostFamilyUsage;
package/lib/index.js CHANGED
@@ -1274,15 +1274,16 @@ function tokenCountOf(value) {
1274
1274
  return null;
1275
1275
  }
1276
1276
  /**
1277
- * The DeepSeek V4 model family a model name prices as — matched on the NAME
1277
+ * The DeepSeek model family a model name prices as — matched on the NAME
1278
1278
  * alone (provider-agnostic: official API, proxies, OpenRouter spellings like
1279
- * `deepseek/deepseek-v4.1-flash` all land here). Null for any other model:
1280
- * non-V4 usage is simply not priced.
1279
+ * `deepseek/deepseek-v4.1-flash` and `deepseek/deepseek-flash` all land
1280
+ * here). The name must carry a DeepSeek marker (`v4` or `deepseek`) so a
1281
+ * foreign flash/pro-named model (gemini-2.0-flash) is never priced.
1281
1282
  */
1282
1283
  function costFamilyOf(model) {
1283
1284
  if (model === void 0) return null;
1284
1285
  const m = model.toLowerCase();
1285
- if (!m.includes("v4")) return null;
1286
+ if (!m.includes("v4") && !m.includes("deepseek")) return null;
1286
1287
  if (m.includes("flash")) return "flash";
1287
1288
  if (m.includes("pro")) return "pro";
1288
1289
  return null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-context",
3
- "version": "0.48.0",
3
+ "version": "0.49.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": {
@@ -66,7 +66,7 @@
66
66
  "dshReleases": {
67
67
  "0.1.2-rc.1": "compatible",
68
68
  "0.1.3-alpha.2": "compatible",
69
- "0.1.5-alpha.2": "compatible"
69
+ "0.1.5-rc.1": "compatible"
70
70
  }
71
71
  }
72
72
  },