dsh-ws-recency 0.10.2 → 0.10.3
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 +1 -1
- package/client.js +86 -22
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -110,7 +110,7 @@ dsh plugin --profile <profile> add github:chyxhtc/dsh-ws-recency
|
|
|
110
110
|
或固定版本的预构建包:
|
|
111
111
|
|
|
112
112
|
```powershell
|
|
113
|
-
dsh plugin --profile <profile> add https://github.com/chyxhtc/dsh-ws-recency/releases/download/v0.10.
|
|
113
|
+
dsh plugin --profile <profile> add https://github.com/chyxhtc/dsh-ws-recency/releases/download/v0.10.3/dsh-ws-recency-0.10.3.tgz
|
|
114
114
|
```
|
|
115
115
|
|
|
116
116
|
装完把 `dsh-ws-recency` 加进 `~/.hypers-work/profiles/<profile>/package.json` 的 `dsh.profile.bundles`,重启应用。
|
package/client.js
CHANGED
|
@@ -230,13 +230,27 @@
|
|
|
230
230
|
"trash.failed": "Delete failed: ",
|
|
231
231
|
};
|
|
232
232
|
|
|
233
|
-
|
|
233
|
+
/* Resolved lazily: the dictionaries are declared further down this closure. */
|
|
234
|
+
var resolvedDictionary = null;
|
|
235
|
+
|
|
236
|
+
function fallbackDictionary() {
|
|
237
|
+
if (resolvedDictionary !== null) return resolvedDictionary;
|
|
238
|
+
var language = "";
|
|
239
|
+
/* The page's own lang wins: it is what the UI is actually rendered in. */
|
|
240
|
+
try { if (typeof document !== "undefined" && document.documentElement !== null && document.documentElement !== undefined) language = document.documentElement.lang || ""; } catch (error) { language = ""; }
|
|
241
|
+
try { if (language === "" && typeof navigator !== "undefined" && navigator.language) language = navigator.language; } catch (error) { /* keep empty */ }
|
|
242
|
+
resolvedDictionary = String(language).toLowerCase().indexOf("zh") === 0 ? ZH : EN;
|
|
243
|
+
return resolvedDictionary;
|
|
244
|
+
}
|
|
234
245
|
|
|
235
246
|
function t(key, params) {
|
|
236
247
|
if (typeof data.t === "function") {
|
|
237
|
-
|
|
248
|
+
var translated = null;
|
|
249
|
+
try { translated = data.t(key, params); } catch (error) { translated = null; }
|
|
250
|
+
if (typeof translated === "string" && translated !== key) return translated;
|
|
238
251
|
}
|
|
239
|
-
var
|
|
252
|
+
var dictionary = fallbackDictionary();
|
|
253
|
+
var text = (dictionary && dictionary[key]) || key;
|
|
240
254
|
if (params !== undefined && params.n !== undefined) text = text.replace("{n}", String(params.n));
|
|
241
255
|
return text;
|
|
242
256
|
}
|
|
@@ -799,12 +813,47 @@
|
|
|
799
813
|
return typeof id === "string" && id !== "" ? id : null;
|
|
800
814
|
}
|
|
801
815
|
|
|
816
|
+
/** The nearest horizontal flex row above the stats: the whole footer dock. */
|
|
817
|
+
function composerDockOf(row) {
|
|
818
|
+
var node = row;
|
|
819
|
+
for (var depth = 0; depth < 4; depth += 1) {
|
|
820
|
+
var parent = node.parentElement;
|
|
821
|
+
if (parent === null) break;
|
|
822
|
+
var style = null;
|
|
823
|
+
try {
|
|
824
|
+
style = typeof window !== "undefined" && typeof window.getComputedStyle === "function"
|
|
825
|
+
? window.getComputedStyle(parent)
|
|
826
|
+
: null;
|
|
827
|
+
} catch (error) {
|
|
828
|
+
style = null;
|
|
829
|
+
}
|
|
830
|
+
if (style !== null && style.display === "flex" && (style.flexDirection === "row" || style.flexDirection === "")) return parent;
|
|
831
|
+
node = parent;
|
|
832
|
+
}
|
|
833
|
+
return row.parentElement === null ? row : row.parentElement;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
/** The host's own pill in that row, used as the visual template. */
|
|
837
|
+
function pillTemplateOf(row) {
|
|
838
|
+
if (typeof row.querySelector !== "function") return null;
|
|
839
|
+
var button = row.querySelector('button[class*="_pill"]');
|
|
840
|
+
return button !== null ? button : row.querySelector('[class*="_pill"]');
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
function cloneIconOf(template) {
|
|
844
|
+
if (template === null || typeof template.querySelector !== "function") return null;
|
|
845
|
+
var icon = template.querySelector("svg");
|
|
846
|
+
if (icon === null || typeof icon.cloneNode !== "function") return null;
|
|
847
|
+
try { return icon.cloneNode(true); } catch (error) { return null; }
|
|
848
|
+
}
|
|
849
|
+
|
|
802
850
|
/**
|
|
803
|
-
* Add one pill
|
|
804
|
-
*
|
|
851
|
+
* Add one pill at the END of the composer footer that opens the analysis
|
|
852
|
+
* panel for the conversation on screen.
|
|
805
853
|
*
|
|
806
|
-
*
|
|
807
|
-
*
|
|
854
|
+
* It reuses the host pill's own class names and icon so it reads as part of
|
|
855
|
+
* the same row, sits after the context ring rather than between the stats,
|
|
856
|
+
* is re-attached whenever the host re-renders, and disappears with the row.
|
|
808
857
|
*/
|
|
809
858
|
function decorateComposerStats() {
|
|
810
859
|
if (typeof document === "undefined") return;
|
|
@@ -818,12 +867,24 @@
|
|
|
818
867
|
}
|
|
819
868
|
var row = anchors[0].parentElement;
|
|
820
869
|
if (row === null) return;
|
|
870
|
+
var dock = composerDockOf(row);
|
|
871
|
+
|
|
821
872
|
if (existing === null) {
|
|
873
|
+
var template = pillTemplateOf(row);
|
|
822
874
|
var button = document.createElement("button");
|
|
823
875
|
button.type = "button";
|
|
824
|
-
button.className = "wsr-pill";
|
|
825
876
|
button.setAttribute("data-wsr-composer-analysis", "true");
|
|
826
|
-
|
|
877
|
+
var base = template !== null && typeof template.className === "string" ? template.className : "";
|
|
878
|
+
button.className = base === "" ? "wsr-pill" : base + " wsr-pill";
|
|
879
|
+
var icon = cloneIconOf(template);
|
|
880
|
+
if (icon !== null) button.appendChild(icon);
|
|
881
|
+
var label = document.createElement("span");
|
|
882
|
+
var labelTemplate = template === null || typeof template.querySelector !== "function" ? null : template.querySelector('[class*="_label"]');
|
|
883
|
+
label.className = labelTemplate !== null && typeof labelTemplate.className === "string" && labelTemplate.className !== ""
|
|
884
|
+
? labelTemplate.className
|
|
885
|
+
: "wsr-pill-label";
|
|
886
|
+
label.textContent = t("composer.analysis");
|
|
887
|
+
button.appendChild(label);
|
|
827
888
|
button.addEventListener("click", function () {
|
|
828
889
|
var id = currentConversationId();
|
|
829
890
|
if (id !== null) openStatsPanel(id);
|
|
@@ -832,7 +893,10 @@
|
|
|
832
893
|
} else {
|
|
833
894
|
composerPill = existing;
|
|
834
895
|
}
|
|
835
|
-
|
|
896
|
+
var children = dock.children || [];
|
|
897
|
+
if (composerPill.parentElement !== dock || children[children.length - 1] !== composerPill) {
|
|
898
|
+
dock.appendChild(composerPill);
|
|
899
|
+
}
|
|
836
900
|
}
|
|
837
901
|
|
|
838
902
|
function apply() {
|
|
@@ -903,7 +967,7 @@
|
|
|
903
967
|
return h(Item, {
|
|
904
968
|
icon: typeof Icon === "function" ? h(Icon, {}) : undefined,
|
|
905
969
|
onSelect: function () { props.actions.toggleFollowUp(props.sessionId); },
|
|
906
|
-
},
|
|
970
|
+
}, t(flagged ? "menu.unflag" : "menu.flag"));
|
|
907
971
|
}
|
|
908
972
|
|
|
909
973
|
/**
|
|
@@ -967,7 +1031,7 @@
|
|
|
967
1031
|
if (typeof window.alert === "function") window.alert(t("trash.failed") + (error && error.message ? error.message : error));
|
|
968
1032
|
});
|
|
969
1033
|
},
|
|
970
|
-
},
|
|
1034
|
+
}, t("menu.trash"));
|
|
971
1035
|
}
|
|
972
1036
|
|
|
973
1037
|
/* ------------------------- token statistics ------------------------- */
|
|
@@ -1175,7 +1239,7 @@
|
|
|
1175
1239
|
return h(Item, {
|
|
1176
1240
|
icon: typeof Icon === "function" ? h(Icon, {}) : undefined,
|
|
1177
1241
|
onSelect: function () { openStatsPanel(props.sessionId); },
|
|
1178
|
-
},
|
|
1242
|
+
}, t("menu.stats"));
|
|
1179
1243
|
}
|
|
1180
1244
|
|
|
1181
1245
|
/** Settings -> General row: how old a session must be before it is folded. */
|
|
@@ -1184,11 +1248,11 @@
|
|
|
1184
1248
|
var days = Number(settings.foldDays);
|
|
1185
1249
|
if (!Number.isFinite(days)) days = DEFAULT_DAYS;
|
|
1186
1250
|
var keep = settings.keepActive !== false;
|
|
1187
|
-
var text =
|
|
1251
|
+
var text = t("settings.title");
|
|
1188
1252
|
return h("div", { className: "wsr-setRow" },
|
|
1189
1253
|
h("div", { className: "wsr-setText" },
|
|
1190
1254
|
h("div", { className: "wsr-setTitle" }, text),
|
|
1191
|
-
h("div", { className: "wsr-setDesc" },
|
|
1255
|
+
h("div", { className: "wsr-setDesc" }, t("settings.description")),
|
|
1192
1256
|
),
|
|
1193
1257
|
h("div", { className: "wsr-controls" },
|
|
1194
1258
|
h("button", {
|
|
@@ -1218,7 +1282,7 @@
|
|
|
1218
1282
|
checked: keep,
|
|
1219
1283
|
onChange: function (event) { props.actions.setKeepActive(event.target.checked); },
|
|
1220
1284
|
}),
|
|
1221
|
-
|
|
1285
|
+
t("settings.exempt")),
|
|
1222
1286
|
),
|
|
1223
1287
|
);
|
|
1224
1288
|
}
|
|
@@ -1227,11 +1291,11 @@
|
|
|
1227
1291
|
function ColorsRow(props) {
|
|
1228
1292
|
var settings = props.useStore(function (state) { return state; });
|
|
1229
1293
|
var enabled = settings.colors !== false;
|
|
1230
|
-
var text =
|
|
1294
|
+
var text = t("color.title");
|
|
1231
1295
|
return h("div", { className: "wsr-setRow" },
|
|
1232
1296
|
h("div", { className: "wsr-setText" },
|
|
1233
1297
|
h("div", { className: "wsr-setTitle" }, text),
|
|
1234
|
-
h("div", { className: "wsr-setDesc" },
|
|
1298
|
+
h("div", { className: "wsr-setDesc" }, t("color.description")),
|
|
1235
1299
|
),
|
|
1236
1300
|
h("div", { className: "wsr-controls" },
|
|
1237
1301
|
h("label", { className: "wsr-exempt" },
|
|
@@ -1240,7 +1304,7 @@
|
|
|
1240
1304
|
checked: enabled,
|
|
1241
1305
|
onChange: function (event) { props.actions.setColors(event.target.checked); },
|
|
1242
1306
|
}),
|
|
1243
|
-
|
|
1307
|
+
t("color.enabled")),
|
|
1244
1308
|
),
|
|
1245
1309
|
);
|
|
1246
1310
|
}
|
|
@@ -1249,11 +1313,11 @@
|
|
|
1249
1313
|
function PinSectionRow(props) {
|
|
1250
1314
|
var settings = props.useStore(function (state) { return state; });
|
|
1251
1315
|
var enabled = settings.pinnedSection !== false;
|
|
1252
|
-
var text =
|
|
1316
|
+
var text = t("pin.title");
|
|
1253
1317
|
return h("div", { className: "wsr-setRow" },
|
|
1254
1318
|
h("div", { className: "wsr-setText" },
|
|
1255
1319
|
h("div", { className: "wsr-setTitle" }, text),
|
|
1256
|
-
h("div", { className: "wsr-setDesc" },
|
|
1320
|
+
h("div", { className: "wsr-setDesc" }, t("pin.description")),
|
|
1257
1321
|
),
|
|
1258
1322
|
h("div", { className: "wsr-controls" },
|
|
1259
1323
|
h("label", { className: "wsr-exempt" },
|
|
@@ -1262,7 +1326,7 @@
|
|
|
1262
1326
|
checked: enabled,
|
|
1263
1327
|
onChange: function (event) { props.actions.setPinnedSection(event.target.checked); },
|
|
1264
1328
|
}),
|
|
1265
|
-
|
|
1329
|
+
t("pin.enabled")),
|
|
1266
1330
|
),
|
|
1267
1331
|
);
|
|
1268
1332
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-ws-recency",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.3",
|
|
4
4
|
"description": "Sidebar session management for DeepSeek Harness: workspace groups sorted by latest activity, stale history folded, a global pinned section, follow-up marks, session delete into a recoverable trash, and per-session token statistics split by tool.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "chyxhtc",
|