dsh-context 0.14.0 → 0.16.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
@@ -1,4 +1,4 @@
1
- <p align="center"><img src="https://raw.githubusercontent.com/bowenliang123/dsh-context/main/docs/social-preview.png" width="840" alt="Social preview"></p>
1
+ ![Social preview](https://raw.githubusercontent.com/bowenliang123/dsh-context/main/docs/social-preview.png)
2
2
 
3
3
  # dsh-context
4
4
 
package/lib/client.js CHANGED
@@ -9,11 +9,11 @@ window.__ModuleLoader__.load({
9
9
  // src/client/i18n.ts
10
10
  var DICT_ZH = {
11
11
  "tab": "\u4E0A\u4E0B\u6587",
12
- "cat.system": "\u7CFB\u7EDF\u63D0\u793A",
12
+ "cat.system": "\u7CFB\u7EDF\u63D0\u793A\u8BCD",
13
13
  "cat.tools": "\u5DE5\u5177\u5B9A\u4E49",
14
14
  "cat.user": "\u7528\u6237\u6D88\u606F",
15
- "cat.inject": "\u6CE8\u5165\u4E0A\u4E0B\u6587",
16
- "cat.assistant": "\u52A9\u624B\u56DE\u590D",
15
+ "cat.inject": "\u6CE8\u5165\u5185\u5BB9",
16
+ "cat.assistant": "\u52A9\u624B\u6D88\u606F",
17
17
  "cat.tool": "\u5DE5\u5177\u7ED3\u679C",
18
18
  "overview.title": "\u5F53\u524D\u6784\u6210",
19
19
  "overview.estimate": "tokens\uFF08\u4F30\u7B97\uFF09",
@@ -89,36 +89,44 @@ var DICT_ZH = {
89
89
  "browser.missingLive": "\u2026 \u53E6\u6709 {n} \u6761\u66F4\u65E9\u7684\u6D88\u606F\u4E5F\u5728\u4E0A\u4E0B\u6587\u4E2D\uFF08\u8D85\u51FA\u5C55\u793A\u7A97\u53E3\uFF09",
90
90
  "browser.approx": "\u8BE5\u6B65\u9AA4\u6D89\u53CA\u7684\u90E8\u5206\u5DF2\u79FB\u9664\u6D88\u606F\u8D85\u51FA\u4FDD\u7559\u8303\u56F4\uFF0C\u4EE5\u4E0B\u4E3A\u8FD1\u4F3C\u6784\u6210",
91
91
  "browser.noHeader": "\u6B64\u6570\u636E\u6765\u81EA\u65E7\u7248\u63D2\u4EF6\uFF1A\u4EC5\u63D0\u4F9B token \u4F30\u7B97\uFF0C\u65E0\u5B9E\u9645\u5185\u5BB9",
92
- "browser.noEpoch": "\u8BE5\u6B65\u9AA4\u7684\u5934\u90E8\u5185\u5BB9\uFF08\u7CFB\u7EDF\u63D0\u793A / \u5DE5\u5177\u5B9A\u4E49\uFF09\u4E0D\u5728\u4FDD\u7559\u8303\u56F4\u5185",
92
+ "browser.noEpoch": "\u8BE5\u6B65\u9AA4\u7684\u5934\u90E8\u5185\u5BB9\uFF08\u7CFB\u7EDF\u63D0\u793A\u8BCD / \u5DE5\u5177\u5B9A\u4E49\uFF09\u4E0D\u5728\u4FDD\u7559\u8303\u56F4\u5185",
93
93
  "browser.noContent": "\u5B8C\u6574\u5185\u5BB9\u4E0D\u5728\u5F53\u524D\u52A0\u8F7D\u7684\u6D88\u606F\u7A97\u53E3\u5185\uFF08\u5728\u804A\u5929\u9875\u52A0\u8F7D\u66F4\u65E9\u5386\u53F2\u540E\u53EF\u67E5\u770B\uFF09",
94
94
  "browser.loading": "\u6B63\u5728\u4ECE\u66F4\u65E9\u7684\u4F1A\u8BDD\u5386\u53F2\u52A0\u8F7D\u5B8C\u6574\u5185\u5BB9\u2026",
95
- "browser.preview": "\u9884\u89C8"
95
+ "browser.preview": "\u9884\u89C8",
96
+ // Tool schema browser card: parsed parameter table sits above the (collapsed
97
+ // by default) raw JSON so the common case — skimming arguments — stays
98
+ // scannable; the JSON is still one click away for the full payload.
99
+ "tool.desc": "\u63CF\u8FF0",
100
+ "tool.params": "\u53C2\u6570",
101
+ "tool.paramsEmpty": "\uFF08\u65E0\u53C2\u6570\uFF09",
102
+ "tool.jsonToggle": "\u67E5\u770B\u539F\u59CB JSON",
103
+ "tool.jsonHide": "\u6536\u8D77"
96
104
  };
97
105
  var DICT_EN = {
98
106
  "tab": "Context",
99
- "cat.system": "System",
100
- "cat.tools": "Tool schemas",
101
- "cat.user": "User",
102
- "cat.inject": "Injected",
103
- "cat.assistant": "Assistant",
104
- "cat.tool": "Tool results",
107
+ "cat.system": "System Prompt",
108
+ "cat.tools": "Tool Schemas",
109
+ "cat.user": "User Messages",
110
+ "cat.inject": "Injected Context",
111
+ "cat.assistant": "Assistant Messages",
112
+ "cat.tool": "Tool Results",
105
113
  "overview.title": "Current Context",
106
114
  "overview.estimate": "tokens (estimated)",
107
- "overview.free": "Free window",
115
+ "overview.free": "Free Window",
108
116
  "overview.used": "of context used",
109
117
  "overview.ofUsed": "of used context",
110
- "stats.title": "Context stats",
118
+ "stats.title": "Context Stats",
111
119
  "stats.hint": "Over the retained history window (same as the History chart)",
112
120
  "stats.turns": "Turns",
113
121
  "stats.steps": "Steps",
114
122
  "stats.injects": "Injections",
115
123
  "stats.compactions": "Compactions",
116
124
  "stats.prunes": "Prunes",
117
- "plugin.title": "Plugin info",
125
+ "plugin.title": "Plugin Info",
118
126
  "plugin.hint": "The best DSH context plugin \u2B50",
119
127
  "plugin.name": "Plugin",
120
128
  "plugin.github": "GitHub",
121
- "tools.top": "Top tool schemas:",
129
+ "tools.top": "Top Tool Schemas:",
122
130
  "tools.more": "of {n}",
123
131
  "trend.title": "Context History",
124
132
  "gran.step": "Step",
@@ -127,11 +135,11 @@ var DICT_EN = {
127
135
  "trend.empty": "Send a message and each model request\u2019s context makeup shows up here",
128
136
  "detail.step": "Turn {t} \xB7 Step {s}",
129
137
  "detail.turn": "Turn {t} \xB7 {n} steps",
130
- "detail.lastStep": "last step",
131
- "detail.estTotal": "estimated \u2248 {n}",
132
- "detail.actual": "actual prompt {n}",
133
- "detail.output": "output {n}",
134
- "events.title": "Context events",
138
+ "detail.lastStep": "Last Step",
139
+ "detail.estTotal": "Estimated \u2248 {n}",
140
+ "detail.actual": "Actual Prompt {n}",
141
+ "detail.output": "Output {n}",
142
+ "events.title": "Context Events",
135
143
  "events.empty": "No context events yet (compaction, injections, model switches appear here)",
136
144
  "events.at": "Turn {t} \xB7 Step {s}",
137
145
  "events.range": "Turn {t} \xB7 Step {a}\u2192{b}",
@@ -149,37 +157,45 @@ var DICT_EN = {
149
157
  "footer": "Estimate: same fixed-density heuristic as dsh\u2019s built-in tokenMeter (~4 chars \u2248 1 token); \u201Cactual\u201D is provider-reported usage.",
150
158
  "tip.step": "Turn {t} \xB7 Step {s}",
151
159
  "tip.turn": "Turn {t} \xB7 {n} steps",
152
- "tip.total": "total \u2248 {n}",
160
+ "tip.total": "Total \u2248 {n}",
153
161
  "tip.actual": " (actual {n})",
154
162
  "ev.compaction": "Context compacted (summary replaced {n} messages)",
155
163
  "ev.prune": "Tool output pruned",
156
164
  "ev.skill": "Skill injected ({name})",
157
165
  "ev.model": "Model switched: {a} \u2192 {b}",
158
166
  "form.instructions": "Instructions",
159
- "form.catalog": "Catalog update",
160
- "form.snapshot": "State snapshot",
167
+ "form.catalog": "Catalog Update",
168
+ "form.snapshot": "State Snapshot",
161
169
  "form.notice": "Notice",
162
- "form.relay": "Agent relay",
170
+ "form.relay": "Agent Relay",
163
171
  "form.recall": "Recall",
164
- "form.context": "Context injection",
165
- "node.toolResult": "Tool result",
166
- "node.calls": "calls ",
172
+ "form.context": "Context Injection",
173
+ "node.toolResult": "Tool Result",
174
+ "node.calls": "Calls ",
167
175
  "node.empty": "(empty reply)",
168
176
  "node.nonText": "(non-text message)",
169
- "node.snapshot": "snapshot: ",
177
+ "node.snapshot": "Snapshot: ",
170
178
  "cmd.desc": "View context makeup and how it evolves",
171
179
  "cmd.close": "Close",
172
180
  "browser.title": "Context Browser",
173
- "browser.live": "Live (next request)",
174
- "browser.liveNow": "Live \xB7 next request",
175
- "browser.items": "{n} items",
181
+ "browser.live": "Live (Next Request)",
182
+ "browser.liveNow": "Live \xB7 Next Request",
183
+ "browser.items": "{n} Items",
176
184
  "browser.missingLive": "\u2026 {n} earlier messages are also part of the context (outside the served window)",
177
185
  "browser.approx": "Some removed messages of this step exceed retention \u2014 the makeup below is approximate",
178
186
  "browser.noHeader": "Served by an older plugin build: token estimates only, no content",
179
- "browser.noEpoch": "The header content (system prompt / tool schemas) of this step is outside retention",
187
+ "browser.noEpoch": "The header content (System Prompt / Tool Schemas) of this step is outside retention",
180
188
  "browser.noContent": "Full content is outside the loaded message window (load older history in Chat to view)",
181
189
  "browser.loading": "Loading full content from older session history\u2026",
182
- "browser.preview": "preview"
190
+ "browser.preview": "Preview",
191
+ // Tool schema browser card: parsed parameter table sits above the (collapsed
192
+ // by default) raw JSON so the common case — skimming arguments — stays
193
+ // scannable; the JSON is still one click away for the full payload.
194
+ "tool.desc": "Description",
195
+ "tool.params": "Parameters",
196
+ "tool.paramsEmpty": "(no parameters)",
197
+ "tool.jsonToggle": "View Raw JSON",
198
+ "tool.jsonHide": "Collapse"
183
199
  };
184
200
 
185
201
  // src/client/modalStore.ts
@@ -753,7 +769,14 @@ var STYLES = [
753
769
  ".lc-chip-on { font-weight: 600; background: var(--dsw-alias-interactive-bg-hover); }",
754
770
  ".lc-chip-on i { box-shadow: 0 0 0 1px var(--dsw-alias-brand-primary); }",
755
771
  ".lc-tools { margin-top: 10px; color: var(--dsw-alias-label-secondary); display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }",
756
- ".lc-tool-chip { background: var(--dsw-alias-bg-layer-2); border-radius: 4px; padding: 1px 7px; font-size: 12px; color: var(--dsw-alias-label-primary); }",
772
+ // The overview tool list links into the Context browser: the "工具定义 Top"
773
+ // label, its "等 N 个" overflow link, and every tool chip are buttons, and
774
+ // hover underlines them (the chip already reads as a tag, so the underline
775
+ // is the only affordance).
776
+ ".lc-tools-label, .lc-tools-more { border: 0; background: transparent; padding: 0; color: var(--dsw-alias-label-secondary); font-family: inherit; font-size: 12px; cursor: pointer; }",
777
+ ".lc-tools-label:hover, .lc-tools-more:hover { text-decoration: underline; }",
778
+ ".lc-tool-chip { background: var(--dsw-alias-bg-layer-2); border: 0; border-radius: 4px; padding: 1px 7px; font: inherit; font-size: 12px; color: var(--dsw-alias-label-primary); cursor: pointer; }",
779
+ ".lc-tool-chip:hover { text-decoration: underline; }",
757
780
  ".lc-chartrow { display: flex; gap: 6px; align-items: stretch; }",
758
781
  ".lc-axis { position: relative; width: 40px; height: 150px; padding-top: 18px; box-sizing: border-box; color: var(--dsw-alias-label-secondary); font-size: 11px; }",
759
782
  ".lc-axis span { position: absolute; right: 0; line-height: 1; }",
@@ -904,7 +927,36 @@ var STYLES = [
904
927
  ".lc-br-content { padding: 2px 6px 8px 26px; display: flex; flex-direction: column; gap: 6px; }",
905
928
  ".lc-br-pre { margin: 0; padding: 8px 10px; background: var(--dsw-alias-bg-layer-2); border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px; color: var(--dsw-alias-label-primary); font-size: 12px; line-height: 1.55; white-space: pre-wrap; word-break: break-word; max-height: 320px; overflow-y: auto; scrollbar-width: thin; }",
906
929
  ".lc-br-dim { color: var(--dsw-alias-label-secondary); }",
907
- ".lc-br-call { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }"
930
+ ".lc-br-call { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }",
931
+ // ---- Tool schema body (browser card, tools category). The description
932
+ // and parameter table share one "card with a small title" chrome — a
933
+ // labeled bordered block so a reader can scan three stacked sections
934
+ // without losing track of which is which. The raw JSON sits below as a
935
+ // collapsed toggle (no card chrome — it's a debug view, not a primary
936
+ // section). ----
937
+ ".lc-ts-card { background: var(--dsw-alias-bg-layer-2); border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px; overflow: hidden; }",
938
+ ".lc-ts-card-head { display: flex; align-items: center; gap: 8px; padding: 6px 10px; font-size: 11px; font-weight: 600; color: var(--dsw-alias-label-secondary); border-bottom: 1px solid var(--dsw-alias-border-l1); }",
939
+ ".lc-ts-card-head b { color: var(--dsw-alias-label-primary); }",
940
+ ".lc-ts-card-count { margin-left: auto; }",
941
+ ".lc-ts-desc-body { margin: 0; padding: 8px 10px; color: var(--dsw-alias-label-primary); font-size: 12px; line-height: 1.55; white-space: pre-wrap; word-break: break-word; max-height: 160px; overflow-y: auto; scrollbar-width: thin; }",
942
+ // Grid: name + type + required chip + description. Columns wrap on narrow
943
+ // rows; the description cell spans the full second row so a long blurb
944
+ // never breaks the one-line rhythm of name/type/required.
945
+ ".lc-ts-param-row { display: grid; grid-template-columns: 140px 90px 56px 1fr; column-gap: 10px; row-gap: 2px; padding: 6px 10px; border-top: 1px solid var(--dsw-alias-border-l1); font-size: 12px; align-items: baseline; }",
946
+ ".lc-ts-param-row:first-of-type { border-top: 0; }",
947
+ ".lc-ts-param-name { font-weight: 600; color: var(--dsw-alias-label-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }",
948
+ ".lc-ts-param-type { color: var(--dsw-alias-label-secondary); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }",
949
+ ".lc-ts-param-req { color: var(--dsw-alias-state-warn-primary); font-size: 11px; font-weight: 600; }",
950
+ ".lc-ts-param-req-off { color: var(--dsw-alias-label-secondary); font-size: 11px; }",
951
+ ".lc-ts-param-desc { grid-column: 1 / -1; color: var(--dsw-alias-label-secondary); line-height: 1.5; }",
952
+ ".lc-ts-params-empty { padding: 8px 10px; color: var(--dsw-alias-label-secondary); font-size: 12px; }",
953
+ // Raw JSON toggle: a slim button that owns the open/closed state, sitting
954
+ // just under the parameter table. The <pre> itself only mounts when open
955
+ // (avoids stringifying the schema on every render and keeps the default
956
+ // body compact).
957
+ ".lc-ts-json { display: flex; flex-direction: column; gap: 4px; }",
958
+ ".lc-ts-json-toggle { align-self: flex-start; border: 0; background: transparent; color: var(--dsw-alias-label-secondary); font: inherit; font-size: 11px; padding: 0; cursor: pointer; }",
959
+ ".lc-ts-json-toggle:hover { color: var(--dsw-alias-label-primary); text-decoration: underline; }"
908
960
  ].join("\n");
909
961
 
910
962
  // src/client/assemble.ts
@@ -975,6 +1027,92 @@ function makeNodeList(kit) {
975
1027
  }
976
1028
 
977
1029
  // src/client/components/browser.tsx
1030
+ function unionTypesOf(p) {
1031
+ const branches = [];
1032
+ if (Array.isArray(p.anyOf)) branches.push(...p.anyOf);
1033
+ if (Array.isArray(p.oneOf)) branches.push(...p.oneOf);
1034
+ if (branches.length === 0) return null;
1035
+ const parts = [];
1036
+ for (const b of branches) {
1037
+ if (b !== null && typeof b === "object") parts.push(typeOf(b));
1038
+ }
1039
+ return parts.length > 0 ? parts.join(" | ") : null;
1040
+ }
1041
+ function typeOf(p) {
1042
+ const u = unionTypesOf(p);
1043
+ if (u !== null) return u;
1044
+ const t = p.type;
1045
+ if (t === "array") {
1046
+ const items = p.items;
1047
+ if (items !== null && typeof items === "object") {
1048
+ const inner = typeOf(items);
1049
+ return "array<" + inner + ">";
1050
+ }
1051
+ return "array";
1052
+ }
1053
+ if (typeof t === "string") {
1054
+ if (t === "object") {
1055
+ const props = p.properties;
1056
+ if (props !== null && typeof props === "object" && Object.keys(props).length > 0) {
1057
+ return "object{" + Object.keys(props).length + "}";
1058
+ }
1059
+ }
1060
+ if (Array.isArray(p.enum) && p.enum.length > 0) {
1061
+ return t + " (enum)";
1062
+ }
1063
+ return t;
1064
+ }
1065
+ if (Array.isArray(p.enum) && p.enum.length > 0) return "(enum)";
1066
+ return "unknown";
1067
+ }
1068
+ function paramsOf(schema) {
1069
+ if (schema === null || typeof schema !== "object") return null;
1070
+ const s = schema;
1071
+ const candidate = (v) => v !== null && typeof v === "object" ? v : null;
1072
+ const nested = candidate(s.parameters) ?? candidate(s.input_schema) ?? candidate(s.inputSchema);
1073
+ if (nested !== null) return nested;
1074
+ if (s.type === "object" && s.properties !== void 0 && typeof s.properties === "object") {
1075
+ return s;
1076
+ }
1077
+ return null;
1078
+ }
1079
+ function ParamRow(props) {
1080
+ const typeLabel = typeOf(props.schema);
1081
+ const desc = props.schema.description;
1082
+ return /* @__PURE__ */ React.createElement("div", { className: "lc-ts-param-row" }, /* @__PURE__ */ React.createElement("span", { className: "lc-ts-param-name" }, props.name), /* @__PURE__ */ React.createElement("span", { className: "lc-ts-param-type" }, typeLabel), /* @__PURE__ */ React.createElement("span", { className: props.required ? "lc-ts-param-req" : "lc-ts-param-req-off" }, props.required ? "\u2713" : "\xB7"), typeof desc === "string" && desc !== "" ? /* @__PURE__ */ React.createElement("span", { className: "lc-ts-param-desc" }, desc) : null);
1083
+ }
1084
+ function ToolSchema(props) {
1085
+ const [jsonOpen, setJsonOpen] = React.useState(false);
1086
+ const params = React.useMemo(() => paramsOf(props.schema), [props.schema]);
1087
+ const rows = React.useMemo(() => {
1088
+ if (params === null) return [];
1089
+ const props2 = params.properties;
1090
+ if (props2 === null || typeof props2 !== "object") return [];
1091
+ const req = Array.isArray(params.required) ? new Set(params.required.filter((x) => typeof x === "string")) : /* @__PURE__ */ new Set();
1092
+ const out = [];
1093
+ for (const k of Object.keys(props2)) {
1094
+ const v = props2[k];
1095
+ if (v === null || typeof v !== "object") continue;
1096
+ out.push({ name: k, schema: v, required: req.has(k) });
1097
+ }
1098
+ return out;
1099
+ }, [params]);
1100
+ const schemaJson = React.useMemo(
1101
+ () => props.schema !== void 0 ? JSON.stringify(props.schema, null, 2) : "",
1102
+ [props.schema]
1103
+ );
1104
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, props.description !== void 0 ? /* @__PURE__ */ React.createElement("div", { className: "lc-ts-card" }, /* @__PURE__ */ React.createElement("div", { className: "lc-ts-card-head" }, /* @__PURE__ */ React.createElement("b", null, props.labels.desc)), /* @__PURE__ */ React.createElement("pre", { className: "lc-ts-desc-body" }, props.description)) : null, params !== null && rows.length > 0 ? /* @__PURE__ */ React.createElement("div", { className: "lc-ts-card" }, /* @__PURE__ */ React.createElement("div", { className: "lc-ts-card-head" }, /* @__PURE__ */ React.createElement("b", null, props.labels.title), /* @__PURE__ */ React.createElement("span", { className: "lc-ts-card-count" }, rows.length)), rows.map((r) => /* @__PURE__ */ React.createElement(ParamRow, { key: r.name, name: r.name, schema: r.schema, required: r.required }))) : params !== null ? /* @__PURE__ */ React.createElement("div", { className: "lc-ts-params-empty" }, props.labels.empty) : null, schemaJson !== "" ? /* @__PURE__ */ React.createElement("div", { className: "lc-ts-json" }, /* @__PURE__ */ React.createElement(
1105
+ "button",
1106
+ {
1107
+ type: "button",
1108
+ className: "lc-ts-json-toggle",
1109
+ onClick: () => {
1110
+ setJsonOpen((o) => !o);
1111
+ }
1112
+ },
1113
+ (jsonOpen ? "\u25BE " : "\u25B8 ") + (jsonOpen ? props.labels.hide : props.labels.show)
1114
+ ), jsonOpen ? /* @__PURE__ */ React.createElement("pre", { className: "lc-br-pre lc-br-dim" }, schemaJson) : null) : null);
1115
+ }
978
1116
  function RawBlocks(props) {
979
1117
  return /* @__PURE__ */ React.createElement(React.Fragment, null, props.blocks.map((b, i) => {
980
1118
  const blk = b;
@@ -1066,6 +1204,14 @@ function makeContextBrowser(kit, StackedBar) {
1066
1204
  setOpenCat(null);
1067
1205
  setOpenElem(null);
1068
1206
  }, [pinSeq]);
1207
+ const toolFocus = props.toolFocus;
1208
+ React.useEffect(() => {
1209
+ if (toolFocus === null || toolFocus === void 0) return;
1210
+ setSel("live");
1211
+ setOpenCat("tools");
1212
+ setOpenElem(toolFocus.tool !== void 0 ? "tool:" + toolFocus.tool : null);
1213
+ if (props.onToolFocusHandled !== void 0) props.onToolFocusHandled();
1214
+ }, [toolFocus, props.onToolFocusHandled]);
1069
1215
  const awaiting = missingSeq !== null && !exhausted && loadOlderHistory !== void 0 && hasMore;
1070
1216
  const requests = data.requests || [];
1071
1217
  const hoverReq = props.previewSeq !== null && props.previewSeq !== void 0 ? requests.find((r) => r.seq === props.previewSeq) ?? null : null;
@@ -1118,19 +1264,25 @@ function makeContextBrowser(kit, StackedBar) {
1118
1264
  }
1119
1265
  if (c === "tools") {
1120
1266
  if (view.header === null) return /* @__PURE__ */ React.createElement("div", { className: "lc-br-note" }, t(headers === null ? "browser.noHeader" : "browser.noEpoch"));
1121
- return view.header.tools.map((tool) => {
1122
- const schema = tool.schema !== void 0 ? JSON.stringify(tool.schema, null, 2) : "";
1267
+ const labels = {
1268
+ desc: t("tool.desc"),
1269
+ title: t("tool.params"),
1270
+ empty: t("tool.paramsEmpty"),
1271
+ show: t("tool.jsonToggle"),
1272
+ hide: t("tool.jsonHide")
1273
+ };
1274
+ return view.header.tools.slice().sort((a, b) => b.tokens - a.tokens).map((tool) => {
1123
1275
  return elemRow(
1124
1276
  "tool:" + tool.name,
1125
1277
  null,
1126
1278
  tool.name,
1127
1279
  tool.tokens,
1128
1280
  void 0,
1129
- /* @__PURE__ */ React.createElement("div", { className: "lc-br-content" }, tool.description !== void 0 ? /* @__PURE__ */ React.createElement("pre", { className: "lc-br-pre" }, tool.description) : null, schema !== "" ? /* @__PURE__ */ React.createElement("pre", { className: "lc-br-pre lc-br-dim" }, schema) : null)
1281
+ /* @__PURE__ */ React.createElement("div", { className: "lc-br-content" }, /* @__PURE__ */ React.createElement(ToolSchema, { description: tool.description, schema: tool.schema, labels }))
1130
1282
  );
1131
1283
  });
1132
1284
  }
1133
- const nodes = byCat[c] ?? [];
1285
+ const nodes = (byCat[c] ?? []).slice().reverse();
1134
1286
  return nodes.map((n) => {
1135
1287
  let tag = null;
1136
1288
  let preview = nodeText(n);
@@ -1288,7 +1440,7 @@ function makeEventList(kit) {
1288
1440
 
1289
1441
  // src/client/meta.ts
1290
1442
  var PLUGIN_NAME = "dsh-context";
1291
- var PLUGIN_VERSION = true ? "0.14.0" : "0.0.0-dev";
1443
+ var PLUGIN_VERSION = true ? "0.16.0" : "0.0.0-dev";
1292
1444
  var PLUGIN_REPO = true ? "https://github.com/bowenliang123/dsh-context" : "https://github.com/bowenliang123/dsh-context";
1293
1445
  var PLUGIN_REPO_SHORT = PLUGIN_REPO.replace(/^https?:\/\/github\.com\//, "");
1294
1446
 
@@ -1393,6 +1545,10 @@ function makeContextView(ctx, kit) {
1393
1545
  return p.length === 1 ? [...EVENT_KINDS] : p.filter((x) => x !== k);
1394
1546
  });
1395
1547
  };
1548
+ const [toolFocus, setToolFocus] = React.useState(null);
1549
+ const clearToolFocus = React.useCallback(() => {
1550
+ setToolFocus(null);
1551
+ }, []);
1396
1552
  const rootRef = React.useRef(null);
1397
1553
  const scrollerRef = React.useRef(null);
1398
1554
  const restoredRef = React.useRef(null);
@@ -1448,9 +1604,40 @@ function makeContextView(ctx, kit) {
1448
1604
  }
1449
1605
  }
1450
1606
  const head = headlineOf(data, pressure);
1451
- return /* @__PURE__ */ React.createElement("div", { className: "lc-root", ref: rootRef }, /* @__PURE__ */ React.createElement("div", { className: "lc-cols lc-head" }, /* @__PURE__ */ React.createElement(StatsBoard, { requests, events }), /* @__PURE__ */ React.createElement(PluginInfo, null)), /* @__PURE__ */ React.createElement("div", { className: "lc-cols" }, /* @__PURE__ */ React.createElement("div", { className: "lc-col" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card-title" }, /* @__PURE__ */ React.createElement("span", { className: "lc-card-title-text" }, t("overview.title")), /* @__PURE__ */ React.createElement("span", { className: "lc-card-sub" }, (data.model ? data.model : "") + (data.provider ? " \xB7 " + data.provider : ""))), /* @__PURE__ */ React.createElement("div", { className: "lc-overview-num" }, /* @__PURE__ */ React.createElement("b", null, fmt3(head.tokens)), /* @__PURE__ */ React.createElement("span", null, head.window ? " / " + fmt3(head.window) + " tokens" : " " + t("overview.estimate")), head.pct !== null ? /* @__PURE__ */ React.createElement("span", { className: "lc-overview-pct" }, /* @__PURE__ */ React.createElement("b", null, head.pct + "%"), t("overview.used")) : null), /* @__PURE__ */ React.createElement(StackedBar, { parts: head.parts, height: 16, max: head.window, hoverKey: hoverCat, onHoverKey: setHoverCat }), /* @__PURE__ */ React.createElement(Legend, { parts: head.parts, hoverKey: hoverCat, onHoverKey: setHoverCat }), data.toolList && data.toolList.length > 0 ? /* @__PURE__ */ React.createElement("div", { className: "lc-tools" }, t("tools.top"), data.toolList.slice().sort((a, b) => b.tokens - a.tokens).slice(0, 5).map((tool) => {
1452
- return /* @__PURE__ */ React.createElement("span", { key: tool.name, className: "lc-tool-chip" }, tool.name + " " + fmt3(tool.tokens));
1453
- }), data.toolList.length > 5 ? /* @__PURE__ */ React.createElement("span", { className: "lc-card-sub" }, " " + t("tools.more", { n: data.toolList.length })) : null) : null), /* @__PURE__ */ React.createElement("div", { className: "lc-card" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card-title" }, /* @__PURE__ */ React.createElement("span", { className: "lc-card-title-text" }, t("trend.title")), /* @__PURE__ */ React.createElement("span", { className: "lc-card-sub" }, t("trend.hint")), /* @__PURE__ */ React.createElement("div", { className: "lc-gran" }, /* @__PURE__ */ React.createElement(
1607
+ return /* @__PURE__ */ React.createElement("div", { className: "lc-root", ref: rootRef }, /* @__PURE__ */ React.createElement("div", { className: "lc-cols lc-head" }, /* @__PURE__ */ React.createElement(StatsBoard, { requests, events }), /* @__PURE__ */ React.createElement(PluginInfo, null)), /* @__PURE__ */ React.createElement("div", { className: "lc-cols" }, /* @__PURE__ */ React.createElement("div", { className: "lc-col" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card-title" }, /* @__PURE__ */ React.createElement("span", { className: "lc-card-title-text" }, t("overview.title")), /* @__PURE__ */ React.createElement("span", { className: "lc-card-sub" }, (data.model ? data.model : "") + (data.provider ? " \xB7 " + data.provider : ""))), /* @__PURE__ */ React.createElement("div", { className: "lc-overview-num" }, /* @__PURE__ */ React.createElement("b", null, fmt3(head.tokens)), /* @__PURE__ */ React.createElement("span", null, head.window ? " / " + fmt3(head.window) + " tokens" : " " + t("overview.estimate")), head.pct !== null ? /* @__PURE__ */ React.createElement("span", { className: "lc-overview-pct" }, /* @__PURE__ */ React.createElement("b", null, head.pct + "%"), t("overview.used")) : null), /* @__PURE__ */ React.createElement(StackedBar, { parts: head.parts, height: 16, max: head.window, hoverKey: hoverCat, onHoverKey: setHoverCat }), /* @__PURE__ */ React.createElement(Legend, { parts: head.parts, hoverKey: hoverCat, onHoverKey: setHoverCat }), data.toolList && data.toolList.length > 0 ? /* @__PURE__ */ React.createElement("div", { className: "lc-tools" }, /* @__PURE__ */ React.createElement(
1608
+ "button",
1609
+ {
1610
+ type: "button",
1611
+ className: "lc-tools-label",
1612
+ onClick: () => {
1613
+ setToolFocus({});
1614
+ }
1615
+ },
1616
+ t("tools.top")
1617
+ ), data.toolList.slice().sort((a, b) => b.tokens - a.tokens).slice(0, 5).map((tool) => {
1618
+ return /* @__PURE__ */ React.createElement(
1619
+ "button",
1620
+ {
1621
+ key: tool.name,
1622
+ type: "button",
1623
+ className: "lc-tool-chip",
1624
+ onClick: () => {
1625
+ setToolFocus({ tool: tool.name });
1626
+ }
1627
+ },
1628
+ tool.name + " " + fmt3(tool.tokens)
1629
+ );
1630
+ }), data.toolList.length > 5 ? /* @__PURE__ */ React.createElement(
1631
+ "button",
1632
+ {
1633
+ type: "button",
1634
+ className: "lc-tools-more",
1635
+ onClick: () => {
1636
+ setToolFocus({});
1637
+ }
1638
+ },
1639
+ t("tools.more", { n: data.toolList.length })
1640
+ ) : null) : null), /* @__PURE__ */ React.createElement("div", { className: "lc-card" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card-title" }, /* @__PURE__ */ React.createElement("span", { className: "lc-card-title-text" }, t("trend.title")), /* @__PURE__ */ React.createElement("span", { className: "lc-card-sub" }, t("trend.hint")), /* @__PURE__ */ React.createElement("div", { className: "lc-gran" }, /* @__PURE__ */ React.createElement(
1454
1641
  "button",
1455
1642
  {
1456
1643
  className: "lc-gran-btn" + (granularity === "step" ? " lc-gran-on" : ""),
@@ -1492,7 +1679,9 @@ function makeContextView(ctx, kit) {
1492
1679
  previewSeq: hoveredSeq,
1493
1680
  pinSeq: pinnedReq !== null ? pinnedReq.seq : null,
1494
1681
  hoverKey: hoverCat,
1495
- onHoverKey: setHoverCat
1682
+ onHoverKey: setHoverCat,
1683
+ toolFocus,
1684
+ onToolFocusHandled: clearToolFocus
1496
1685
  }
1497
1686
  ))), /* @__PURE__ */ React.createElement("div", { className: "lc-cols" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card lc-col" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card-title" }, /* @__PURE__ */ React.createElement("span", { className: "lc-card-title-text" }, t("events.title")), /* @__PURE__ */ React.createElement("div", { className: "lc-kinds" }, EVENT_KINDS.map((k) => /* @__PURE__ */ React.createElement(
1498
1687
  "button",
package/lib/index.js CHANGED
@@ -980,7 +980,7 @@ var alwaysPolicySchema = Schema.object({
980
980
  var RetryPolicySchema = Schema.union([normalPolicySchema, alwaysPolicySchema]);
981
981
  var { version } = createRequire(import.meta.url)("../package.json");
982
982
 
983
- // node_modules/.pnpm/@deepseek-ai+dsh-session@0.1.0-rc.7_6fd26f59436a18b115f326d6060415e6/node_modules/@deepseek-ai/dsh-session/lib/index.js
983
+ // node_modules/.pnpm/@deepseek-ai+dsh-session@0.1.0-rc.8_6fd26f59436a18b115f326d6060415e6/node_modules/@deepseek-ai/dsh-session/lib/index.js
984
984
  function deriveEventMessage(event) {
985
985
  switch (event.type) {
986
986
  case "user/message":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-context",
3
- "version": "0.14.0",
3
+ "version": "0.16.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": {
@@ -31,7 +31,8 @@
31
31
  "test": "npm run typecheck && node tests/host.test.mjs && node tests/client.test.mjs",
32
32
  "release": "bash scripts/publish.sh",
33
33
  "hooks": "bash scripts/install-hooks.sh",
34
- "repro": "node tests/repro-real-react.mjs"
34
+ "repro": "node tests/repro-real-react.mjs",
35
+ "social-preview": "node docs/social-preview/generate.mjs"
35
36
  },
36
37
  "dsh": {
37
38
  "bundle": {
@@ -58,18 +59,17 @@
58
59
  ],
59
60
  "license": "Apache-2.0",
60
61
  "dependencies": {
61
- "playwright-core": "^1.62.1",
62
62
  "zod": "^4.4.3"
63
63
  },
64
64
  "devDependencies": {
65
65
  "@deepseek-ai/cordis": "^4.0.1",
66
- "@deepseek-ai/dsh-client-ui-primitives": "0.1.0-rc.7",
67
- "@deepseek-ai/dsh-session": "0.1.0-rc.7",
68
- "@deepseek-ai/dsh-session-projection": "0.1.0-rc.7",
69
- "@deepseek-ai/dsh-token-meter": "0.1.0-rc.7",
66
+ "@deepseek-ai/dsh-client-ui-primitives": "0.1.0-rc.8",
67
+ "@deepseek-ai/dsh-session": "0.1.0-rc.8",
68
+ "@deepseek-ai/dsh-session-projection": "0.1.0-rc.8",
70
69
  "@types/react": "^18.3.31",
71
70
  "esbuild": "^0.28.2",
72
71
  "jsdom": "^30.0.1",
72
+ "playwright-core": "^1.62.1",
73
73
  "react": "^18.3.1",
74
74
  "react-dom": "^18.3.1",
75
75
  "typescript": "^7.0.2"