dsh-session-mover
Moves a session from one workspace to another in the DSH Web UI. DSH can archive,
rename and inspect sessions, but a session belongs to the workspace whose directory
matches the cwd in its stored header — changing that membership means moving the
log itself.
- Pick a target. The session menu gains "Move to workspace…", which opens a picker listing every other workspace with its directory and session count.
- Everything follows. The Host half flushes the session writer, copies the
session directory to
<home>/sessions/<projectKey(target)>/<id>/, rewrites the header'scwd, detaches the session from the old workspace and attaches it to the new one. - Only the header frame is touched. A log is a concatenation of zstd frames
(one per append batch) and
zstdDecompressSynconly decodes the first one, so the rewrite walks the first frame's block table, replaces that frame, and appends the remaining bytes untouched. - Reversible until the end. The old directory is renamed aside rather than deleted, so any failure — a busy log, a stale registry, a missing directory — rolls back to a byte-identical state before the error is reported.
- Opened sessions too. A session that has been opened stays in the Host's
live store with two in-memory copies of its header — the
Sessionobject and the persistence write handle. Both are swapped for copies carrying the newcwd(and the handle's primed log path), so the next turn appends to the new location instead of the old, missing one. The session'sworkingDirectoryprojection is re-recorded as aworking-directory/changeevent, otherwise an opened session would keep reporting — and working in — its old directory.
Install
This repository is the plugin package. Install it from the git spec:
plugin_manager install_bundle target="github:gongyehuahe/dsh-session-mover"
or, from a shell in the DSH profile directory:
pnpm add "github:gongyehuahe/dsh-session-mover"
Then reload the plugin row (disable/enable) and refresh the Web UI page.
The npm name dsh-session-mover belongs to an unrelated package, so install from this
repository rather than from the registry. A local clone works too: point
install_bundle at the directory.
Usage
Right-click a session → Move to workspace… → pick a target → Move. The dialog reports how much log data moved. Only workspaces other than the session's current one are offered.
What it refuses
| Code | Situation |
|---|---|
session-busy |
the session still has running work (workspace/session-activity) |
session-in-use |
the log file cannot be renamed because DSH still holds it open |
session-no-cwd |
the stored header has no project directory, so it cannot belong to a workspace |
target-conflict |
the target workspace already holds a session directory with this id |
workspace-missing-dir |
the target workspace's directory no longer exists |
registry-rejected |
the workspace registry did not accept the new cwd; files were rolled back |
The id is validated against session-<uuid>, the source directory must be named
after the id and live under <home>/sessions, and every write is verified by
decoding the rewritten log again before it is used. Archiving and pinning are
global flags, so a moved session keeps both.
The browser half talks to POST /session-mover/api, which only answers
same-origin, loopback/trusted requests.
Requirements
- DSH with the Web UI (desktop app or
dsh web). - Node.js 22.15 or newer — the rewrite uses the built-in
zlibzstd codec.
Layout
| File | Purpose |
|---|---|
index.js |
Host half: the JSON endpoint, the header rewrite, the directory move, the registry hand-over |
client.js |
Browser half: the session menu row and the workspace picker |
cordis.patch.yml |
The loader row inserted into the profile |
locale/{en,zh}.json |
Plugin title and description |
icon.svg |
Plugin icon |
test/integration.mjs |
Integration tests: a throwaway DSH home, a stub registry, the real HTTP handler |
Development
npm test # integration tests against a temporary DSH home
npm run check
Licence
MIT
No comments yet. Be the first to write one.