dsh-workspace-mover 2.0.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/LICENSE +21 -0
- package/README.md +239 -0
- package/client/client.js +1918 -0
- package/cordis.patch.yml +14 -0
- package/docs/ARCHITECTURE.md +141 -0
- package/docs/media/batch_move_selection.png +0 -0
- package/docs/media/confirm_popup.png +0 -0
- package/docs/media/drag_session_to_another_workspace.png +0 -0
- package/docs/media/original_workspace.png +0 -0
- package/docs/media/remove_popup.png +0 -0
- package/docs/media/setting_dialogue_repair.png +0 -0
- package/docs/media/workspace_after_move.png +0 -0
- package/docs/media/workspace_after_rename.png +0 -0
- package/docs/media/workspace_examination.png +0 -0
- package/docs/media/workspace_move.png +0 -0
- package/lib/index.js +2446 -0
- package/package.json +62 -0
- package/test/core.test.mjs +124 -0
- package/test/e2e-sandbox.test.mjs +1804 -0
- package/test/release-downloads.test.mjs +102 -0
- package/test/traffic-badge.test.mjs +66 -0
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# dsh-workspace-mover bundle patch
|
|
2
|
+
#
|
|
3
|
+
# 通过官方 CLI 安装时(dsh plugin --profile <name> add dsh-workspace-mover),
|
|
4
|
+
# 安装器会把本包追加进 dsh.profile.bundles 并在启动时合并本补丁,
|
|
5
|
+
# 等价于手工在 profile 的 cordis.patch.yml 里挂载一行:
|
|
6
|
+
#
|
|
7
|
+
# - insert:
|
|
8
|
+
# - id: workspace-mover
|
|
9
|
+
# name: 'dsh-workspace-mover'
|
|
10
|
+
#
|
|
11
|
+
# 单包单插件,无配置项。
|
|
12
|
+
- insert:
|
|
13
|
+
- id: workspace-mover
|
|
14
|
+
name: 'dsh-workspace-mover'
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
Technical reference for contributors and advanced users. Product-facing install/usage docs live in [README.md](../README.md) / [README_EN.md](../README_EN.md). This file is the **single source of truth** for implementation details; do not duplicate it into READMEs.
|
|
4
|
+
|
|
5
|
+
## Plugin mount (DSH 0.1.5)
|
|
6
|
+
|
|
7
|
+
- Package is pure JavaScript source-as-product (no TypeScript, no build step).
|
|
8
|
+
- Host half mounts through a standard `insert` row in [`cordis.patch.yml`](../cordis.patch.yml).
|
|
9
|
+
- Client half is injected via `package.json` → `dsh.client` (`@deepseek-ai/dsh-client-connection`, `@deepseek-ai/dsh-client-ui-slots`, platform `web`).
|
|
10
|
+
- Official bundles are never rewritten; only event listeners and official slots are used.
|
|
11
|
+
- From GitHub, pnpm runs no install scripts, so `allowBuilds` is not required.
|
|
12
|
+
|
|
13
|
+
## Host / Client split
|
|
14
|
+
|
|
15
|
+
| Half | Entry | Role |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| Host | `lib/index.js` | RPC, disk archives, workspace registry, backups, trash, history, locks |
|
|
18
|
+
| Client | `client/client.js` | Sidebar drag intercept, multi-select, confirmation UI, rescue panel (settings slot) |
|
|
19
|
+
|
|
20
|
+
Client locates rows by ARIA semantics only:
|
|
21
|
+
|
|
22
|
+
- session rows: `[aria-selected]`
|
|
23
|
+
- workspace title rows: `[aria-expanded]`
|
|
24
|
+
|
|
25
|
+
It never depends on CSS-module hash class names. UI uses official design tokens (`--dsw-alias-*`) for theme adaptation.
|
|
26
|
+
|
|
27
|
+
Only cross-group drops are intercepted; official same-group reorder stays untouched. After a successful move the client actively refreshes and reconciles the official workspace projection; a page reload remains the user-facing fallback.
|
|
28
|
+
|
|
29
|
+
## RPC channel
|
|
30
|
+
|
|
31
|
+
Single logical channel `/workspace-mover` via `ctx.connection.rpc.handle('/workspace-mover', …)`. No independent REST routes.
|
|
32
|
+
|
|
33
|
+
| Endpoint | Purpose |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| `mover.status` | Capability report (detected services / degraded items) |
|
|
36
|
+
| `mover.workspaces` | List workspaces |
|
|
37
|
+
| `mover.move` | Single-session true move |
|
|
38
|
+
| `mover.moveMany` | Bulk move (≤50 / batch) |
|
|
39
|
+
| `mover.scan` | Classified rescue scan |
|
|
40
|
+
| `mover.repair` | Attach / relink one item |
|
|
41
|
+
| `mover.repairAll` | Batch repair (per-item isolation) |
|
|
42
|
+
| `mover.history` | Recent moves (≤100) |
|
|
43
|
+
| `mover.undo` | Undo one history entry |
|
|
44
|
+
| `mover.ws.audit` | Workspace path health |
|
|
45
|
+
| `mover.repoint` | Move-home wizard |
|
|
46
|
+
| `mover.archived` / `mover.unarchive` | List / restore archived sessions |
|
|
47
|
+
| `mover.openFolder` | Open group directory in OS file manager |
|
|
48
|
+
| `mover.session.delete` | Session → recycle bin |
|
|
49
|
+
| `mover.trash.list` / `mover.trash.restore` / `mover.trash.purge` | Recycle bin |
|
|
50
|
+
| `mover.backups.list` / `mover.backups.restore` / `mover.backups.deleteOne` | Backup management |
|
|
51
|
+
| `mover.tasks.list` / `mover.tasks.retry` / `mover.tasks.forget` | Migration task center |
|
|
52
|
+
| `mover.data.cleanup` | Dry-run and clean aged plugin data |
|
|
53
|
+
|
|
54
|
+
Errors carry stable codes (`busy`, `conflict`, `not-found`, `rollback-failed`, …). Host logs write failures under `MOVE FAILED`.
|
|
55
|
+
|
|
56
|
+
## Session archives (v3)
|
|
57
|
+
|
|
58
|
+
- Naming: `session.v3.jsonl.zstd` or `session.v3.jsonl` (highest generation wins).
|
|
59
|
+
- Mixed compression in one persistence root is rejected explicitly.
|
|
60
|
+
- True move keeps the session id and all frames; only the header `cwd` (first frame) is rewritten; other frames stay byte-identical. Publish via temp file + atomic rename.
|
|
61
|
+
|
|
62
|
+
## Move pipeline
|
|
63
|
+
|
|
64
|
+
Order of operations for a cross-workspace move:
|
|
65
|
+
|
|
66
|
+
1. **Running check** — reject only mid-turn sessions (`agents.get(id)?.status === 'running'`); idle resident sessions may move.
|
|
67
|
+
2. **Read authority header** from disk; verify target ≠ source.
|
|
68
|
+
3. **Preflight** — dual-accounting detect, target writability probe, disk-space hint.
|
|
69
|
+
4. **Byte backup** to `$DSH_HOME/workspace-mover/backups/` (rolling 20 per session) **before any side effect**.
|
|
70
|
+
5. **Rewrite first frame** (header cwd) only.
|
|
71
|
+
6. **Move directory** (Windows: exponential-backoff retry on EPERM; fallback copy+delete).
|
|
72
|
+
7. **In-memory closeout** — invalidate three registry indexes; for resident sessions clear stale persistence-coordinator write state; retarget live header `cwd` before official `attachSession`.
|
|
73
|
+
8. **Accounting** — source `detachSession` then target `attachSession`.
|
|
74
|
+
9. **Verify** — read archive back; id + cwd must match or the move fails.
|
|
75
|
+
10. **Rollback on any failure** — restore live header + index snapshot → original bytes back to source dir → reattach source workspace.
|
|
76
|
+
|
|
77
|
+
Concurrency: same session / same target workspace try-acquire a lock; concurrent ops return `busy` (never queue). Bulk moves de-duplicate first.
|
|
78
|
+
|
|
79
|
+
If “rollback also failed”, a durable recovery record is written and shown as a red manual-recovery row. Session files and backups stay in place — never auto-deleted.
|
|
80
|
+
|
|
81
|
+
## Workspace repoint (move-home)
|
|
82
|
+
|
|
83
|
+
Official workspace entity writes prune members using in-memory session cwd indexes. The wizard:
|
|
84
|
+
|
|
85
|
+
1. Audits path validity (`mover.ws.audit`).
|
|
86
|
+
2. Pre-seeds all affected sessions’ three indexes to the new path.
|
|
87
|
+
3. Rewrites the entity path through the unified `mutate` channel so members are not pruned.
|
|
88
|
+
4. Batch-migrates member sessions and strays from the old path through the same move pipeline.
|
|
89
|
+
5. Running sessions skip; an interrupted run resumes with only the remainder.
|
|
90
|
+
|
|
91
|
+
If `mutate` is unavailable after a host upgrade, the wizard aborts before the first file change.
|
|
92
|
+
|
|
93
|
+
## Plugin-owned data
|
|
94
|
+
|
|
95
|
+
All plugin metadata lives under `$DSH_HOME/workspace-mover/` and never overwrites official session archives in place except through the move pipeline.
|
|
96
|
+
|
|
97
|
+
| Path | Use |
|
|
98
|
+
| --- | --- |
|
|
99
|
+
| `backups/` | Byte-level pre-move backups |
|
|
100
|
+
| `history.json` | Last 100 cross-workspace moves |
|
|
101
|
+
| trash / task / recovery files | Recycle bin manifest, task center, recovery ledger |
|
|
102
|
+
|
|
103
|
+
Official session files and workspace registry are only mutated via host APIs: registry `mutate` / `attachSession` / `detachSession` and durable domain state.
|
|
104
|
+
|
|
105
|
+
## Compatibility boundary
|
|
106
|
+
|
|
107
|
+
Verified:
|
|
108
|
+
|
|
109
|
+
- DeepSeek Harness `0.1.5-rc.1`
|
|
110
|
+
- dsh-market `1.45.1`
|
|
111
|
+
- Node.js `≥ 22`
|
|
112
|
+
- `package.json` → `engines.dsh`: `>= 0.1.5-rc.1`
|
|
113
|
+
|
|
114
|
+
GitHub-only packages may show “host requirement unknown” in dsh-market when no npm manifest is published; that is metadata, not runtime incompatibility.
|
|
115
|
+
|
|
116
|
+
Version-sensitive host behaviors degrade with explicit UI messages (not silent failure):
|
|
117
|
+
|
|
118
|
+
- Unarchive needs the registry durable state channel.
|
|
119
|
+
- Projection-cache titles parse defensively against v3; missing file falls back to archive header title.
|
|
120
|
+
- Host upgrades that rename registry cache fields hit the degrade path (feature still usable; ownership refresh may need a restart).
|
|
121
|
+
|
|
122
|
+
## Coexistence notes (implementation)
|
|
123
|
+
|
|
124
|
+
- CSS classes `wsm-*` and DOM attributes `data-wsm-*` are private namespaces.
|
|
125
|
+
- Settings panel uses the official `settings.section` slot.
|
|
126
|
+
- Sidebar redraw plugins that replace workspace DOM can break ARIA row lookup — features stop triggering; data is not damaged.
|
|
127
|
+
- Do not install a second document-level drag interceptor for cross-workspace moves.
|
|
128
|
+
|
|
129
|
+
## Tests & release
|
|
130
|
+
|
|
131
|
+
- `npm test` runs `test/core.test.mjs`, `test/e2e-sandbox.test.mjs`, `test/traffic-badge.test.mjs`, `test/release-downloads.test.mjs` (95 cases at v2.0.1).
|
|
132
|
+
- Coverage includes rollback, rescue scan/repair, history undo, workspace repoint, post-move verification, recycle bin / backup restore, task center, data-protection cleanup, concurrency locks, error codes.
|
|
133
|
+
- CI: `.github/workflows/test.yml`.
|
|
134
|
+
- Release assets may ship a `.tgz` install package (`dsh-workspace-mover-*.tgz`).
|
|
135
|
+
- Traffic/clones and release-download badges are refreshed by `.github/workflows/traffic-badge.yml` via Gist JSON endpoints (not part of the runtime plugin).
|
|
136
|
+
|
|
137
|
+
## Related docs
|
|
138
|
+
|
|
139
|
+
- User install/usage: [README.md](../README.md), [README_EN.md](../README_EN.md)
|
|
140
|
+
- Full version history: [CHANGELOG.md](../CHANGELOG.md)
|
|
141
|
+
- Security policy: [SECURITY.md](../SECURITY.md)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|