dsh-ws-recency 0.11.2 → 0.11.4
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 +6 -0
- package/index.js +35 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -130,7 +130,7 @@ dsh plugin --profile <profile> add github:chyxhtc/dsh-ws-recency
|
|
|
130
130
|
或固定版本的预构建包:
|
|
131
131
|
|
|
132
132
|
```powershell
|
|
133
|
-
dsh plugin --profile <profile> add https://github.com/chyxhtc/dsh-ws-recency/releases/download/v0.11.
|
|
133
|
+
dsh plugin --profile <profile> add https://github.com/chyxhtc/dsh-ws-recency/releases/download/v0.11.4/dsh-ws-recency-0.11.4.tgz
|
|
134
134
|
```
|
|
135
135
|
|
|
136
136
|
装完把 `dsh-ws-recency` 加进 `~/.hypers-work/profiles/<profile>/package.json` 的 `dsh.profile.bundles`,重启应用。
|
package/client.js
CHANGED
|
@@ -213,6 +213,7 @@
|
|
|
213
213
|
"move.working": "移动中…(会先停止会话)",
|
|
214
214
|
"move.done": "已移动到「{workspace}」。若列表没刷新,切换一下工作区或重启应用。",
|
|
215
215
|
"move.doneLive": "\n\n这个会话刚才是打开状态:建议重启应用后再继续对话,避免它沿用旧的目录。",
|
|
216
|
+
"move.repaired": "已补登记到「{workspace}」:上一次移动只搬了日志、没登记工作区,这次把它补上了。",
|
|
216
217
|
"move.failed": "移动失败:",
|
|
217
218
|
"stats.chart": "消耗分布",
|
|
218
219
|
"stats.details.show": "显示明细 ▾",
|
|
@@ -267,6 +268,7 @@
|
|
|
267
268
|
"move.working": "Moving\u2026 (the session is stopped first)",
|
|
268
269
|
"move.done": "Moved to \"{workspace}\". If the list has not refreshed, switch workspaces or restart the app.",
|
|
269
270
|
"move.doneLive": "\n\nThe session was open: restart the app before continuing it so it does not keep using the old directory.",
|
|
271
|
+
"move.repaired": "Registered in \"{workspace}\": the previous attempt moved the log without the bookkeeping, and this repaired it.",
|
|
270
272
|
"move.failed": "Move failed: ",
|
|
271
273
|
"stats.chart": "Where the tokens went",
|
|
272
274
|
"stats.details.show": "Show details",
|
|
@@ -1448,6 +1450,10 @@
|
|
|
1448
1450
|
})
|
|
1449
1451
|
.then(function (result) {
|
|
1450
1452
|
if (result.json !== null && result.json.ok === true) {
|
|
1453
|
+
if (result.json.repaired === true) {
|
|
1454
|
+
body.textContent = t("move.repaired", { workspace: label });
|
|
1455
|
+
return;
|
|
1456
|
+
}
|
|
1451
1457
|
body.textContent = t("move.done", { workspace: label });
|
|
1452
1458
|
if (result.json.live === true) body.textContent += t("move.doneLive");
|
|
1453
1459
|
return;
|
package/index.js
CHANGED
|
@@ -469,7 +469,28 @@ export async function moveSessionToWorkspace(ctx, sessionId, workspaceId) {
|
|
|
469
469
|
?? workspaces.find((workspace) => workspace.path === workspaceId);
|
|
470
470
|
if (target === undefined) return { ok: false, error: "workspace not found" };
|
|
471
471
|
const targetPath = target.path;
|
|
472
|
-
if (header.cwd === targetPath)
|
|
472
|
+
if (header.cwd === targetPath) {
|
|
473
|
+
/* Already pointed at the target: a previous attempt moved the log but died
|
|
474
|
+
before the bookkeeping (the app's in-memory header refused it). Repair the
|
|
475
|
+
membership instead of failing, so such a session is not left unlisted. */
|
|
476
|
+
try {
|
|
477
|
+
await target.attachSession(sessionId);
|
|
478
|
+
} catch (error) {
|
|
479
|
+
return { ok: false, error: `session is already in that directory but the workspace refused it: ${error instanceof Error ? error.message : String(error)}` };
|
|
480
|
+
}
|
|
481
|
+
const stale = [];
|
|
482
|
+
for (const workspace of workspaces) {
|
|
483
|
+
if (!Array.isArray(workspace.sessionIds) || !workspace.sessionIds.includes(sessionId)) continue;
|
|
484
|
+
if (workspace.id === target.id) continue;
|
|
485
|
+
try {
|
|
486
|
+
await workspace.detachSession(sessionId);
|
|
487
|
+
stale.push(workspace.id);
|
|
488
|
+
} catch {
|
|
489
|
+
/* a stale membership that filters itself out anyway */
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return { ok: true, repaired: true, workspace: target.id, path: targetPath, detached: stale };
|
|
493
|
+
}
|
|
473
494
|
|
|
474
495
|
let targetDirectory;
|
|
475
496
|
try {
|
|
@@ -550,8 +571,15 @@ export async function moveSessionToWorkspace(ctx, sessionId, workspaceId) {
|
|
|
550
571
|
has the session open. The registry validates against its own view, so both the
|
|
551
572
|
cached header and the live one have to follow - otherwise an open session is
|
|
552
573
|
refused with its old directory. */
|
|
574
|
+
let wasLive = false;
|
|
575
|
+
try {
|
|
553
576
|
const movedHeader = { ...header, cwd: targetPath };
|
|
554
|
-
|
|
577
|
+
/* Cordis throws on an undeclared service, so the probe is guarded. */
|
|
578
|
+
try {
|
|
579
|
+
wasLive = typeof ctx.sessions?.get === "function" && ctx.sessions.get(sessionId) !== undefined;
|
|
580
|
+
} catch {
|
|
581
|
+
wasLive = false;
|
|
582
|
+
}
|
|
555
583
|
try {
|
|
556
584
|
if (typeof ctx.workspaceRegistry.indexHeader === "function") await ctx.workspaceRegistry.indexHeader(movedHeader);
|
|
557
585
|
} catch {
|
|
@@ -577,6 +605,10 @@ export async function moveSessionToWorkspace(ctx, sessionId, workspaceId) {
|
|
|
577
605
|
await rollback();
|
|
578
606
|
return { ok: false, error: `the app still holds this session's old directory (${seenCwd}); restart the app and move it again` };
|
|
579
607
|
}
|
|
608
|
+
} catch (error) {
|
|
609
|
+
await rollback();
|
|
610
|
+
return { ok: false, error: error instanceof Error ? error.message : String(error) };
|
|
611
|
+
}
|
|
580
612
|
|
|
581
613
|
/* Attach first, detach second: a refused attach must not orphan the session. */
|
|
582
614
|
try {
|
|
@@ -692,7 +724,7 @@ export function apply(ctx) {
|
|
|
692
724
|
}), "ws-recency: stats route");
|
|
693
725
|
});
|
|
694
726
|
|
|
695
|
-
webCtx.inject(["sessionPersistence", "workspaceRegistry"], (moveCtx) => {
|
|
727
|
+
webCtx.inject(["sessionPersistence", "workspaceRegistry", "sessions"], (moveCtx) => {
|
|
696
728
|
moveMounted = true;
|
|
697
729
|
webCtx.effect(() => server.register({
|
|
698
730
|
kind: "exact",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-ws-recency",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.4",
|
|
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, per-session token statistics split by tool, and moving a session to another workspace.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "chyxhtc",
|