dsh-context 0.10.3 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -8
- package/lib/client.js +122 -51
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -5,21 +5,26 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/dsh-context)
|
|
6
6
|
[](https://github.com/bowenliang123/dsh-context)
|
|
7
7
|
|
|
8
|
-
**
|
|
8
|
+
**The best [DeepSeek Harness plugin](https://www.deepseek.com/harness/) for Agent's context insights and management.**
|
|
9
9
|
|
|
10
|
-
`dsh-context`
|
|
10
|
+
`dsh-context` provides full context lifecycle management features.
|
|
11
|
+
- **Context tab** — an UI context dashboard for DeepSeek Harness’s context stats, composition, history, events, and messages.
|
|
12
|
+
- **`/context` command** — the slash command shows the context model for current context composition and recent context evolution.
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
- **The `/context` command** — the same headline and recent trend as a centered dialog straight from the composer (the screenshot above).
|
|
14
|
+
## Install / Update
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
One command, from any DeepSeek Harness installation:
|
|
16
|
+
To Install from any DeepSeek Harness installation:
|
|
18
17
|
|
|
19
18
|
```sh
|
|
20
19
|
dsh plugin --profile web add dsh-context
|
|
21
20
|
```
|
|
22
21
|
|
|
22
|
+
Or to update the `dsh-context` plugin:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
dsh plugin --profile web update dsh-context@latest
|
|
26
|
+
```
|
|
27
|
+
|
|
23
28
|
Then start the web UI with `dsh web`. No build step, no restart.
|
|
24
29
|
|
|
25
30
|
## Use it
|
|
@@ -60,7 +65,7 @@ In **Step** granularity, hovering any bar shows that single step's context info
|
|
|
60
65
|
|
|
61
66
|
### ⚡ Context events — when and why the window changed
|
|
62
67
|
|
|
63
|
-
Every compaction, tool-output prune, skill or plugin context injection, and model switch — each with its token delta, turn/step attribution, and timestamp:
|
|
68
|
+
Every compaction, tool-output prune, skill or plugin context injection, and model switch — each with its token delta, turn/step attribution, and timestamp. Filter by category (**Inject / Compact / Prune / Switch**) to see exactly when each kind of event happened and its impact — e.g. when a skill was injected, when instructions were added, or how much a compaction reclaimed:
|
|
64
69
|
|
|
65
70
|

|
|
66
71
|
|
package/lib/client.js
CHANGED
|
@@ -29,11 +29,9 @@ var DICT_ZH = {
|
|
|
29
29
|
"stats.compactions": "\u538B\u7F29",
|
|
30
30
|
"stats.prunes": "\u526A\u679D",
|
|
31
31
|
"plugin.title": "\u63D2\u4EF6\u4FE1\u606F",
|
|
32
|
-
"plugin.hint": "
|
|
32
|
+
"plugin.hint": "The best DSH context plugin \u2B50",
|
|
33
33
|
"plugin.name": "\u63D2\u4EF6",
|
|
34
|
-
"plugin.
|
|
35
|
-
"plugin.updateBadge": "Update!",
|
|
36
|
-
"plugin.updateTip": "\u65B0\u7248\u672C v{v} \u53EF\u7528 \xB7 \u6267\u884C dsh plugin --profile web add dsh-context \u66F4\u65B0\uFF08\u70B9\u51FB\u524D\u5F80 npm\uFF09",
|
|
34
|
+
"plugin.github": "GitHub",
|
|
37
35
|
"tools.top": "\u5DE5\u5177\u5B9A\u4E49 Top\uFF1A",
|
|
38
36
|
"tools.more": "\u7B49 {n} \u4E2A",
|
|
39
37
|
"trend.title": "\u5386\u53F2\u8D8B\u52BF",
|
|
@@ -52,6 +50,10 @@ var DICT_ZH = {
|
|
|
52
50
|
"events.at": "\u7B2C {t} \u8F6E \xB7 \u7B2C {s} \u6B65",
|
|
53
51
|
"events.range": "\u7B2C {t} \u8F6E \xB7 \u7B2C {a}\u2192{b} \u6B65",
|
|
54
52
|
"events.rangeTo": "\u7B2C {a} \u8F6E \xB7 \u7B2C {as} \u6B65 \u2192 \u7B2C {b} \u8F6E \xB7 \u7B2C {bs} \u6B65",
|
|
53
|
+
"kind.inject": "\u6CE8\u5165",
|
|
54
|
+
"kind.compaction": "\u538B\u7F29",
|
|
55
|
+
"kind.prune": "\u526A\u679D",
|
|
56
|
+
"kind.model": "\u5207\u6362",
|
|
55
57
|
"nodes.title": "\u6D88\u606F\u6784\u6210",
|
|
56
58
|
"nodes.hint": "\u5F53\u524D\u6A21\u578B\u53EF\u89C1\u7684\u6D88\u606F\uFF0C\u6700\u65B0\u5728\u524D",
|
|
57
59
|
"nodes.more": "\u2026 \u66F4\u65E9\u7684 {n} \u6761\u6D88\u606F\u5DF2\u7701\u7565",
|
|
@@ -104,11 +106,9 @@ var DICT_EN = {
|
|
|
104
106
|
"stats.compactions": "Compactions",
|
|
105
107
|
"stats.prunes": "Prunes",
|
|
106
108
|
"plugin.title": "Plugin info",
|
|
107
|
-
"plugin.hint": "
|
|
109
|
+
"plugin.hint": "The best DSH context plugin \u2B50",
|
|
108
110
|
"plugin.name": "Plugin",
|
|
109
|
-
"plugin.
|
|
110
|
-
"plugin.updateBadge": "Update!",
|
|
111
|
-
"plugin.updateTip": "v{v} available \u2014 run `dsh plugin --profile web add dsh-context` to update (click for npm)",
|
|
111
|
+
"plugin.github": "GitHub",
|
|
112
112
|
"tools.top": "Top tool schemas:",
|
|
113
113
|
"tools.more": "of {n}",
|
|
114
114
|
"trend.title": "History",
|
|
@@ -127,6 +127,10 @@ var DICT_EN = {
|
|
|
127
127
|
"events.at": "Turn {t} \xB7 Step {s}",
|
|
128
128
|
"events.range": "Turn {t} \xB7 Step {a}\u2192{b}",
|
|
129
129
|
"events.rangeTo": "Turn {a} \xB7 Step {as} \u2192 Turn {b} \xB7 Step {bs}",
|
|
130
|
+
"kind.inject": "Inject",
|
|
131
|
+
"kind.compaction": "Compact",
|
|
132
|
+
"kind.prune": "Prune",
|
|
133
|
+
"kind.model": "Switch",
|
|
130
134
|
"nodes.title": "Messages",
|
|
131
135
|
"nodes.hint": "currently model-visible, newest first",
|
|
132
136
|
"nodes.more": "\u2026 {n} earlier messages omitted",
|
|
@@ -664,7 +668,7 @@ var STYLES = [
|
|
|
664
668
|
".lc-stat-value { color: var(--dsw-alias-label-primary); font-size: 14px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: center; }",
|
|
665
669
|
".lc-stat-sub { color: var(--dsw-alias-label-secondary); font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }",
|
|
666
670
|
".lc-card-sub { font-weight: 400; color: var(--dsw-alias-label-secondary); font-size: 12px; }",
|
|
667
|
-
".lc-gran { margin-left: auto; display: flex; gap: 2px; background: var(--dsw-alias-bg-layer-2); border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px; padding: 1px; }",
|
|
671
|
+
".lc-gran, .lc-kinds { margin-left: auto; display: flex; gap: 2px; background: var(--dsw-alias-bg-layer-2); border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px; padding: 1px; }",
|
|
668
672
|
".lc-gran-btn { border: 0; background: transparent; color: var(--dsw-alias-label-secondary); font-size: 11px; line-height: 1; padding: 3px 8px; border-radius: 5px; cursor: pointer; font-family: inherit; }",
|
|
669
673
|
".lc-gran-btn:hover { color: var(--dsw-alias-label-primary); }",
|
|
670
674
|
".lc-gran-on, .lc-gran-on:hover { background: var(--dsw-alias-button-primary-fill); color: var(--dsw-alias-label-primary-foreground); }",
|
|
@@ -750,27 +754,47 @@ var STYLES = [
|
|
|
750
754
|
".lc-detail-pct { width: 34px; text-align: right; color: var(--dsw-alias-label-secondary); }",
|
|
751
755
|
".lc-cols { display: flex; gap: 14px; flex-wrap: wrap; }",
|
|
752
756
|
".lc-col { flex: 1; min-width: 280px; }",
|
|
753
|
-
// Head row:
|
|
754
|
-
//
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
//
|
|
759
|
-
//
|
|
760
|
-
|
|
761
|
-
".lc-
|
|
762
|
-
".lc-
|
|
763
|
-
|
|
764
|
-
//
|
|
765
|
-
|
|
757
|
+
// Head row: stats board + plugin info sit side by side under the shared
|
|
758
|
+
// `lc-cols` flex — stats takes ~7/10 of the row, plugin info ~3/10, both
|
|
759
|
+
// wrap onto their own line when the available width falls below each card's
|
|
760
|
+
// min-width (so a narrow viewport keeps both readable). Both children are
|
|
761
|
+
// `.lc-card` themselves (rendered by StatsBoard / PluginInfo); the flex
|
|
762
|
+
// sizing lives on the head row's direct children so the existing card
|
|
763
|
+
// chrome doesn't change.
|
|
764
|
+
".lc-head > .lc-card { margin-bottom: 0; }",
|
|
765
|
+
".lc-head > .lc-card:first-child { flex: 7 1 0; min-width: 360px; }",
|
|
766
|
+
".lc-head > .lc-card:last-child { flex: 3 1 0; min-width: 220px; }",
|
|
767
|
+
// Plugin info: two full-width rows (Plugin / GitHub), each one horizontal
|
|
768
|
+
// line with the label on the left and the value on the right — a compact
|
|
769
|
+
// definition list rather than a multi-cell grid.
|
|
770
|
+
".lc-pi-grid { display: grid; grid-template-columns: 1fr; gap: 8px; }",
|
|
771
|
+
// The row IS the link: an `<a>` with the label + value on one baseline.
|
|
772
|
+
// Hovering a row underlines its value — the only hover affordance.
|
|
773
|
+
".lc-pi-row { display: flex; flex-direction: row; justify-content: space-between; align-items: baseline; gap: 12px; min-width: 0; text-decoration: none; color: inherit; }",
|
|
774
|
+
".lc-pi-row:hover .lc-pi-value { text-decoration: underline; }",
|
|
775
|
+
// Upgrade chip appended to the Plugin value when the npm registry has a
|
|
776
|
+
// newer version than the baked-in one.
|
|
777
|
+
".lc-pi-update { color: var(--dsw-alias-state-warn-primary); font-size: 11px; margin-left: 6px; white-space: nowrap; }",
|
|
778
|
+
".lc-pi-label { flex: none; color: var(--dsw-alias-label-secondary); font-size: 11px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }",
|
|
779
|
+
// min-width: 0 lets the value shrink inside the flex row and truncate with
|
|
780
|
+
// an ellipsis; without it a narrow card pushes the value over the label.
|
|
781
|
+
".lc-pi-value { min-width: 0; color: var(--dsw-alias-label-primary); font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: right; }",
|
|
766
782
|
".lc-events, .lc-nodes { display: flex; flex-direction: column; gap: 2px; max-height: 320px; overflow-y: auto; }",
|
|
767
783
|
".lc-event { display: flex; align-items: center; gap: 8px; padding: 3px 0; }",
|
|
768
784
|
".lc-event-icon { width: 18px; text-align: center; color: var(--dsw-alias-state-warn-primary); }",
|
|
769
785
|
".lc-event-icon.lc-event-inject { color: #a855f7; }",
|
|
770
786
|
".lc-event-icon.lc-event-model { color: var(--dsw-alias-brand-primary); }",
|
|
787
|
+
// Kind chip: the event classification at a glance; the tint matches the
|
|
788
|
+
// impact direction (inject = adds context, compaction/prune = frees it,
|
|
789
|
+
// model switch = neutral), mirroring the token sign colors below.
|
|
790
|
+
".lc-kind { flex: none; font-size: 10px; font-weight: 600; padding: 1px 6px; border-radius: 4px; white-space: nowrap; }",
|
|
791
|
+
".lc-kind-inject { background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 15%, transparent); color: var(--dsw-alias-state-success-primary); }",
|
|
792
|
+
".lc-kind-compaction { background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 15%, transparent); color: var(--dsw-alias-state-error-primary); }",
|
|
793
|
+
".lc-kind-prune { background: color-mix(in srgb, #8b5cf6 15%, transparent); color: #8b5cf6; }",
|
|
794
|
+
".lc-kind-model { background: color-mix(in srgb, var(--dsw-alias-brand-primary) 15%, transparent); color: var(--dsw-alias-brand-primary); }",
|
|
771
795
|
".lc-event-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }",
|
|
772
796
|
".lc-event-at { flex: none; color: var(--dsw-alias-label-secondary); font-size: 11px; white-space: nowrap; }",
|
|
773
|
-
".lc-event-tokens { color: var(--dsw-alias-state-success-primary); }",
|
|
797
|
+
".lc-event-tokens { color: var(--dsw-alias-state-success-primary); font-weight: 600; white-space: nowrap; }",
|
|
774
798
|
".lc-event-tokens.lc-up { color: var(--dsw-alias-state-warn-primary); }",
|
|
775
799
|
".lc-event-time { color: var(--dsw-alias-label-secondary); font-size: 12px; }",
|
|
776
800
|
".lc-node { display: flex; align-items: center; gap: 8px; padding: 3px 0; }",
|
|
@@ -846,12 +870,25 @@ function makeEventList(kit) {
|
|
|
846
870
|
if (props.events.length === 0) {
|
|
847
871
|
return /* @__PURE__ */ React.createElement("div", { className: "lc-empty" }, t("events.empty"));
|
|
848
872
|
}
|
|
873
|
+
const rootRef = React.useRef(null);
|
|
874
|
+
React.useLayoutEffect(() => {
|
|
875
|
+
const root = rootRef.current;
|
|
876
|
+
if (!root) return;
|
|
877
|
+
const sync = () => {
|
|
878
|
+
for (const el of root.querySelectorAll(".lc-event-label")) {
|
|
879
|
+
el.title = el.scrollWidth > el.clientWidth ? el.textContent || "" : "";
|
|
880
|
+
}
|
|
881
|
+
};
|
|
882
|
+
sync();
|
|
883
|
+
window.addEventListener("resize", sync);
|
|
884
|
+
return () => window.removeEventListener("resize", sync);
|
|
885
|
+
});
|
|
849
886
|
const sorted = props.events.slice().reverse();
|
|
850
|
-
return /* @__PURE__ */ React.createElement("div", { className: "lc-events" }, sorted.map((ev, i) => {
|
|
887
|
+
return /* @__PURE__ */ React.createElement("div", { className: "lc-events", ref: rootRef }, sorted.map((ev, i) => {
|
|
851
888
|
const label = eventLabel(ev);
|
|
852
889
|
const at = eventAt(ev);
|
|
853
890
|
const glyph = ev.kind === "inject" ? /* @__PURE__ */ React.createElement(import_dsh_client_ui_primitives.IconPlusOutline16, null) : ev.kind === "model" ? /* @__PURE__ */ React.createElement(import_dsh_client_ui_primitives.IconBranchOutline16, null) : EVENT_ICONS[ev.kind] || "\u2022";
|
|
854
|
-
return /* @__PURE__ */ React.createElement("div", { key: ev.seq + "-" + i, className: "lc-event" }, /* @__PURE__ */ React.createElement("span", { className: "lc-event-icon lc-event-" + ev.kind }, glyph), /* @__PURE__ */ React.createElement("span", { className: "lc-
|
|
891
|
+
return /* @__PURE__ */ React.createElement("div", { key: ev.seq + "-" + i, className: "lc-event" }, /* @__PURE__ */ React.createElement("span", { className: "lc-event-icon lc-event-" + ev.kind }, glyph), /* @__PURE__ */ React.createElement("span", { className: "lc-kind lc-kind-" + ev.kind }, t("kind." + ev.kind)), /* @__PURE__ */ React.createElement("span", { className: "lc-event-label" }, label), at !== null ? /* @__PURE__ */ React.createElement("span", { className: "lc-event-at" }, at) : null, ev.tokens ? /* @__PURE__ */ React.createElement("span", { className: "lc-event-tokens" + (ev.kind === "inject" ? " lc-up" : " lc-down") }, (ev.kind === "inject" ? "+" : "\u2212") + fmt3(ev.tokens)) : null, /* @__PURE__ */ React.createElement("span", { className: "lc-event-time" }, fmtTime2(ev.time)));
|
|
855
892
|
}));
|
|
856
893
|
};
|
|
857
894
|
}
|
|
@@ -886,41 +923,55 @@ function makeNodeList(kit) {
|
|
|
886
923
|
|
|
887
924
|
// src/client/meta.ts
|
|
888
925
|
var PLUGIN_NAME = "dsh-context";
|
|
889
|
-
var PLUGIN_VERSION = true ? "0.
|
|
926
|
+
var PLUGIN_VERSION = true ? "0.11.1" : "0.0.0-dev";
|
|
890
927
|
var PLUGIN_REPO = true ? "https://github.com/bowenliang123/dsh-context" : "https://github.com/bowenliang123/dsh-context";
|
|
891
|
-
var PLUGIN_NPM = "https://www.npmjs.com/package/" + PLUGIN_NAME;
|
|
892
928
|
var PLUGIN_REPO_SHORT = PLUGIN_REPO.replace(/^https?:\/\/github\.com\//, "");
|
|
893
929
|
|
|
930
|
+
// src/client/latestVersion.ts
|
|
931
|
+
var REGISTRY_URL = "https://registry.npmjs.org/" + PLUGIN_NAME + "/latest";
|
|
932
|
+
var TTL_MS = 60 * 60 * 1e3;
|
|
933
|
+
var cached = null;
|
|
934
|
+
function fetchLatestVersion() {
|
|
935
|
+
if (!cached || Date.now() - cached.at >= TTL_MS) {
|
|
936
|
+
cached = {
|
|
937
|
+
at: Date.now(),
|
|
938
|
+
promise: fetch(REGISTRY_URL).then((res) => res.ok ? res.json() : null).then((body) => body && typeof body.version === "string" ? body.version : null).catch(() => null)
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
return cached.promise;
|
|
942
|
+
}
|
|
943
|
+
function isNewerVersion(latest, current) {
|
|
944
|
+
const parse = (v) => v.replace(/^v/, "").split("-", 1)[0].split(".").map((n) => parseInt(n, 10) || 0);
|
|
945
|
+
const a = parse(latest);
|
|
946
|
+
const b = parse(current);
|
|
947
|
+
for (let i = 0; i < Math.max(a.length, b.length); i++) {
|
|
948
|
+
const x = a[i] || 0;
|
|
949
|
+
const y = b[i] || 0;
|
|
950
|
+
if (x !== y) return x > y;
|
|
951
|
+
}
|
|
952
|
+
return false;
|
|
953
|
+
}
|
|
954
|
+
|
|
894
955
|
// src/client/components/pluginInfo.tsx
|
|
895
|
-
var latestCache;
|
|
896
956
|
function makePluginInfo(kit) {
|
|
897
|
-
const { t
|
|
957
|
+
const { t } = kit;
|
|
958
|
+
const row = (label, value, href) => /* @__PURE__ */ React.createElement("a", { className: "lc-pi-row", href, target: "_blank", rel: "noreferrer" }, /* @__PURE__ */ React.createElement("div", { className: "lc-pi-label" }, label), /* @__PURE__ */ React.createElement("div", { className: "lc-pi-value" }, value));
|
|
898
959
|
return function PluginInfo() {
|
|
899
|
-
const [latest, setLatest] = React.useState(
|
|
960
|
+
const [latest, setLatest] = React.useState(null);
|
|
900
961
|
React.useEffect(() => {
|
|
901
|
-
if (
|
|
902
|
-
let
|
|
903
|
-
|
|
904
|
-
if (
|
|
905
|
-
latestCache = body && typeof body.version === "string" ? body.version : null;
|
|
906
|
-
setLatest(latestCache);
|
|
907
|
-
}).catch(() => {
|
|
908
|
-
if (!alive) return;
|
|
909
|
-
latestCache = null;
|
|
910
|
-
setLatest(null);
|
|
962
|
+
if (PLUGIN_VERSION.includes("-dev")) return;
|
|
963
|
+
let on = true;
|
|
964
|
+
fetchLatestVersion().then((v) => {
|
|
965
|
+
if (on && v) setLatest(v);
|
|
911
966
|
});
|
|
912
967
|
return () => {
|
|
913
|
-
|
|
968
|
+
on = false;
|
|
914
969
|
};
|
|
915
970
|
}, []);
|
|
916
|
-
const update =
|
|
917
|
-
const
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
/* @__PURE__ */ React.createElement(React.Fragment, null, "v" + PLUGIN_VERSION, update ? /* @__PURE__ */ React.createElement("span", { className: "lc-update-badge" }, t("plugin.updateBadge")) : null),
|
|
921
|
-
PLUGIN_NPM,
|
|
922
|
-
update ? tr("plugin.updateTip", { v: latest ?? "" }) : void 0
|
|
923
|
-
), cell("GitHub", PLUGIN_REPO_SHORT + " \u2197", PLUGIN_REPO)));
|
|
971
|
+
const update = latest !== null && isNewerVersion(latest, PLUGIN_VERSION) ? latest : null;
|
|
972
|
+
const nameValue = [PLUGIN_NAME + " (v" + PLUGIN_VERSION + ")"];
|
|
973
|
+
if (update) nameValue.push(/* @__PURE__ */ React.createElement("span", { key: "update", className: "lc-pi-update" }, "\u2191 v" + update));
|
|
974
|
+
return /* @__PURE__ */ React.createElement("div", { className: "lc-card" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card-title" }, t("plugin.title"), /* @__PURE__ */ React.createElement("span", { className: "lc-card-sub" }, t("plugin.hint"))), /* @__PURE__ */ React.createElement("div", { className: "lc-pi-grid" }, row(t("plugin.name"), nameValue, PLUGIN_REPO + "/releases"), row(t("plugin.github"), PLUGIN_REPO_SHORT, PLUGIN_REPO)));
|
|
924
975
|
};
|
|
925
976
|
}
|
|
926
977
|
|
|
@@ -946,6 +997,7 @@ function makeStatsBoard(kit) {
|
|
|
946
997
|
|
|
947
998
|
// src/client/components/contextView.tsx
|
|
948
999
|
var viewScroll = /* @__PURE__ */ new Map();
|
|
1000
|
+
var EVENT_KINDS = ["inject", "compaction", "prune", "model"];
|
|
949
1001
|
function makeContextView(ctx, kit) {
|
|
950
1002
|
const { t, tr, fmt: fmt3, fmtTime: fmtTime2, catLabel } = kit;
|
|
951
1003
|
const StackedBar = makeStackedBar(kit);
|
|
@@ -966,6 +1018,14 @@ function makeContextView(ctx, kit) {
|
|
|
966
1018
|
const [tick, setTick] = React.useState(0);
|
|
967
1019
|
const [granularity, setGranularity] = React.useState("step");
|
|
968
1020
|
const [hoverCat, setHoverCat] = React.useState(null);
|
|
1021
|
+
const [pickedKinds, setPickedKinds] = React.useState([...EVENT_KINDS]);
|
|
1022
|
+
const toggleKind = (k) => {
|
|
1023
|
+
setPickedKinds((p) => {
|
|
1024
|
+
if (p.length === EVENT_KINDS.length) return [k];
|
|
1025
|
+
if (!p.includes(k)) return [...p, k];
|
|
1026
|
+
return p.length === 1 ? [...EVENT_KINDS] : p.filter((x) => x !== k);
|
|
1027
|
+
});
|
|
1028
|
+
};
|
|
969
1029
|
const rootRef = React.useRef(null);
|
|
970
1030
|
const scrollerRef = React.useRef(null);
|
|
971
1031
|
const restoredRef = React.useRef(null);
|
|
@@ -997,6 +1057,7 @@ function makeContextView(ctx, kit) {
|
|
|
997
1057
|
}
|
|
998
1058
|
const requests = data.requests || [];
|
|
999
1059
|
const events = data.events || [];
|
|
1060
|
+
const shownEvents = pickedKinds.length === EVENT_KINDS.length ? events : events.filter((e) => pickedKinds.includes(e.kind));
|
|
1000
1061
|
const nodes = data.nodes || [];
|
|
1001
1062
|
const displayRequests = granularity === "turn" ? aggregateByTurn(requests) : requests;
|
|
1002
1063
|
const markers = attachMarkers(displayRequests, events);
|
|
@@ -1020,7 +1081,7 @@ function makeContextView(ctx, kit) {
|
|
|
1020
1081
|
}
|
|
1021
1082
|
}
|
|
1022
1083
|
const head = headlineOf(data, pressure);
|
|
1023
|
-
return /* @__PURE__ */ React.createElement("div", { className: "lc-root", ref: rootRef }, /* @__PURE__ */ React.createElement("div", { className: "lc-cols" }, /* @__PURE__ */ React.createElement(StatsBoard, { requests, events }), /* @__PURE__ */ React.createElement(PluginInfo, null)), /* @__PURE__ */ React.createElement("div", { className: "lc-card" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card-title" }, 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) + " " + tr("overview.ofWindow", { p: head.pct ?? 0 }) : " " + t("overview.estimate")), !head.estimated ? /* @__PURE__ */ React.createElement("span", { className: "lc-card-sub" }, t("overview.splitEst")) : 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) => {
|
|
1084
|
+
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-card" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card-title" }, 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) + " " + tr("overview.ofWindow", { p: head.pct ?? 0 }) : " " + t("overview.estimate")), !head.estimated ? /* @__PURE__ */ React.createElement("span", { className: "lc-card-sub" }, t("overview.splitEst")) : 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) => {
|
|
1024
1085
|
return /* @__PURE__ */ React.createElement("span", { key: tool.name, className: "lc-tool-chip" }, tool.name + " " + fmt3(tool.tokens));
|
|
1025
1086
|
}), data.toolList.length > 5 ? /* @__PURE__ */ React.createElement("span", { className: "lc-card-sub" }, " " + tr("tools.more", { n: data.toolList.length })) : null) : null), /* @__PURE__ */ React.createElement("div", { className: "lc-card" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card-title" }, t("trend.title"), /* @__PURE__ */ React.createElement("span", { className: "lc-card-sub" }, t("trend.hint")), /* @__PURE__ */ React.createElement("div", { className: "lc-gran" }, /* @__PURE__ */ React.createElement(
|
|
1026
1087
|
"button",
|
|
@@ -1054,7 +1115,17 @@ function makeContextView(ctx, kit) {
|
|
|
1054
1115
|
onHover: setHoveredSeq,
|
|
1055
1116
|
onHoverTurn: setHoverTurn
|
|
1056
1117
|
}
|
|
1057
|
-
), /* @__PURE__ */ React.createElement(RequestDetail, { request: activeReq, marker: activeReq !== null ? markerOf(activeReq) : void 0 }))), /* @__PURE__ */ React.createElement("div", { className: "lc-cols" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card lc-col" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card-title" }, t("events.title")
|
|
1118
|
+
), /* @__PURE__ */ React.createElement(RequestDetail, { request: activeReq, marker: activeReq !== null ? markerOf(activeReq) : void 0 }))), /* @__PURE__ */ React.createElement("div", { className: "lc-cols" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card lc-col" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card-title" }, t("events.title"), /* @__PURE__ */ React.createElement("div", { className: "lc-kinds" }, EVENT_KINDS.map((k) => /* @__PURE__ */ React.createElement(
|
|
1119
|
+
"button",
|
|
1120
|
+
{
|
|
1121
|
+
key: k,
|
|
1122
|
+
className: "lc-gran-btn" + (pickedKinds.includes(k) ? " lc-gran-on lc-kind-" + k : ""),
|
|
1123
|
+
onClick: () => {
|
|
1124
|
+
toggleKind(k);
|
|
1125
|
+
}
|
|
1126
|
+
},
|
|
1127
|
+
t("kind." + k)
|
|
1128
|
+
)))), /* @__PURE__ */ React.createElement(EventList, { events: shownEvents })), /* @__PURE__ */ React.createElement("div", { className: "lc-card lc-col" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card-title" }, t("nodes.title"), /* @__PURE__ */ React.createElement("span", { className: "lc-card-sub" }, t("nodes.hint"))), /* @__PURE__ */ React.createElement(NodeList, { nodes, dropped: data.droppedNodes || 0 }))), /* @__PURE__ */ React.createElement("div", { className: "lc-foot" }, t("footer")));
|
|
1058
1129
|
};
|
|
1059
1130
|
}
|
|
1060
1131
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-context",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "A DeepSeek Harness plugin for context dashboard and context command, for understanding how the context is made of, and how it evolves.",
|
|
3
|
+
"version": "0.11.1",
|
|
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": {
|
|
7
7
|
"type": "git",
|