deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
PROJECT README
A DeepSeek Harness plugin that manages archived sessions. The official workspace browser only has an "archive session" action — archived sessions then disappear from every view, with no way to list, restore, or permanently delete them. This plugin fills that gap and adds a red Delete permanently item to the session context menu.
Hover a session row in the left sidebar → ⋯ menu: below the built-in Rename / Fork session / Archive session items, a red Delete permanently item appears (native danger styling, same confirm dialog).
The official workspace browser exposes no slot for session menus, so the plugin augments the rendered popup via DOM observation + React-fiber resolution. The augmentation is passive: if the host UI structure changes and resolution fails, the button simply does not appear — nothing else is affected.
| Tool | Notes |
|---|---|
session_list_archived |
List archived sessions as JSON |
session_restore_archived |
Restore by id (reversible, no confirmation) |
session_delete_permanently |
Delete by id; requires confirm: true; refuses running sessions |
git clone https://github.com/SunshineR04/dsh-session-manager.git
dsh plugin --profile <name> add "file:/path/to/dsh-session-manager"
dsh plugin add installs through pnpm and appends the package to
dsh.profile.bundles; this package's cordis.patch.yml bundle layer mounts
the plugin row automatically. Restart the dsh desktop app afterwards
(new bundles are not hot-loaded).
Alternatively mount it manually in the profile's cordis.patch.yml (the
bundle channel above is easier):
- insert:
- id: session-manager
name: dsh-session-manager
Deleting runs in this order:
sessionIds and removes it from the global archive set.
The detach does not trust the workspace's filtered sessionIds view alone —
a stale registry header index can hide the id from that getter (which used
to let deleted sessions survive, resurfacing as ungrouped entries), so
the raw workspace record is checked as a fallback.~/.dsh/sessions/<encoded-project>/<session-id>/ (session.jsonl.zstd).
The directory is resolved through three seams in turn — registry header +
persistence locate, the persistence header listing, then a raw scan of
the sessions root for a directory named exactly the session id — so a
degenerated header seam can no longer silently skip the deletion.~/.dsh/storages/session_projcache/sessions/<id>.json (and .bak-*).api-session/removed event, so every connected
client drops the session from its list store immediately. (The host itself
only emits this event when a live session is disposed, which a cold delete
never is.)The SQLite search index reconciles itself once the source files are gone; attachments are content-addressed and intentionally kept.
session/data-gone), not just hidden by the UI.sessionIds slot, so the session returns to its previous position.
A queued-for-deletion id is refused with session/pending (cancel it first
when its files are still on disk); restoring one would expose an
artifact-less husk.| Field | Default | Description |
|---|---|---|
sessionListLimit |
500 |
Max entries per list call |
allowDeleteRunning |
false |
Force-delete sessions with a running task (skips the refusal and the tombstone — dangerous; open-idle sessions delete immediately either way) |
toolDeleteRequiresConfirm |
true |
Agent delete tool requires confirm: true |
menuDeleteAvailable |
true |
Mount the red menu item |
pnpm install
pnpm test # syntax check + host unit tests + client render smoke tests
The render tests mount the real client settings section with React inside
jsdom (test/client.render.test.mjs) — they catch UI crashes the host tests
cannot see.
Boots a throwaway dsh web instance against an isolated DSH_HOME (never your
real data) and drives the UI with puppeteer-core + local Chrome:
cp scripts/e2e-seed.local.example.json scripts/e2e-seed.local.json
# ^ fill in your own session/workspace data (gitignored, never committed)
node scripts/e2e-seed.mjs <e2e-home> ~/.dsh # 1. seed the isolated test HOME
# 2. create a profile in that HOME with this plugin, then start the test web instance.
# ⚠ The desktop `dsh` shim hardcodes DSH_HOME=<real home>, so prefixing the
# command with DSH_HOME=<e2e-home> does NOT isolate (verified: the profile
# lands in the real home). Invoke the CLI entry directly instead — verified
# for `plugin add`; use the same form for the serve flags:
# ELECTRON_RUN_AS_NODE=1 DSH_HOME=<e2e-home> "<DSH Desktop.exe>" --expose-internals \
# "<app.asar>/lib/desktop-cli.js" plugin --profile sm-test add <tarball>
# ELECTRON_RUN_AS_NODE=1 DSH_HOME=<e2e-home> "<DSH Desktop.exe>" --expose-internals \
# "<app.asar>/lib/desktop-cli.js" --profile sm-test --port 43123 --no-open
node scripts/e2e-check.mjs <printed token URL> # 3. read-only checks: menu item / settings page
node scripts/e2e-mutations.mjs <URL> <e2e-home> # 4. closed loop: restore → archive → delete
Built after studying these projects (some locally inspectable under
~/.dsh/profiles/desktop/node_modules):
MIT
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。