Passer au contenu principal
P

dsh-plugin-archive-manager

piaohua/dsh-plugin-archive-manager

(DSH) Web plugin that makes session archiving reversible and visible

Installer

dsh plugin --profile web add github:piaohua/dsh-plugin-archive-manager

README

dsh-plugin-archive-manager

A DeepSeek Harness (DSH) Web plugin that makes session archiving reversible and visible:

  • View archived sessions in place — archived sessions reappear in the workspace list at their original position (workspace accounting slots are preserved by DSH), with their titles dimmed compared to unarchived ones.
  • Filter group in the view options — the workspace view options menu gains a Filter group with two independently checkable items: Archived and Not archived (default: Not archived checked). Check Archived to see archived sessions; uncheck Not archived to see archived sessions only.
  • Unarchive from the row menu — for an archived session the row action becomes Unarchive (with a dedicated unarchive icon) instead of Archive session; clicking it restores the session durably.

中文说明见 README.zh.md

Why this exists

DSH already archives sessions (they disappear from every grouping surface), but the shipped UI has no way to view or unarchive archived sessions — the official dsh-client-ui-workspace README states: "sessions can be archived, but archived sessions have no viewing or unarchive surface." The underlying data model was built for unarchiving (an archived session keeps its workspace accounting slot; the registry comment says "unarchiving restores its position"), but no API or UI exists.

This plugin fills that gap.

How it works

Two halves, one npm package:

HalfFileWhat it does
Host (node)lib/index.jsPatches ctx.workspaceRegistry with the missing unarchiveSession(sessionId) (mirrors the official archiveSession: idempotent, durable, same domain/changedhost/archived-sessions-changed broadcast chain), and registers an exact HTTP route POST /api/dsh-archive-manager/unarchive for the browser half.
Browser (web)lib/client.jsShadows the sidebar.workspaces slot (priority -1 vs the official 0; lowest priority renders — a framework-supported mechanism) with a faithful re-implementation of the workspace browsing region: section header + view options, search, grouped/flat lists, drag reorder, rename/fork/archive dialogs, workspace rename/delete — plus the Filter group, dimmed archived titles, and the Unarchive row action.

The unarchive data flow

  1. Click Unarchive on an archived session row.
  2. The browser half fetches POST /api/dsh-archive-manager/unarchive (same origin) with { sessionId } and the required custom header x-dsh-archive-manager: 1.
  3. The host route calls the patched unarchiveSession, which writes the durable registry state (removing the id from the global archive set) through the same setState path the official archive uses.
  4. The registry write emits domain/changed; the host API proxy diffs the archive set and broadcasts host/archived-sessions-changed to every connected client (including other tabs).
  5. The client runtime updates archivedSessionIds; the browsing region re-renders — the row un-dims, the menu swaps back to Archive session, and the filter rules apply immediately.

Because the mutation goes through the official persistence path, everything is durable across restarts and consistent across tabs — no custom RPC protocol, no event plumbing of our own.

Viewing an archived session's conversation

Stock DSH force-clears the conversation selection whenever the current session is archived (that is part of "archived sessions have no viewing surface"), so clicking an archived row would instantly bounce back to the empty New Session view. This plugin disables that rule (a small patch on the client WorkspaceRuntime.project() projection, removed again on uninstall), so clicking an archived session opens and reads its conversation normally. Behavior change that comes with it: archiving the current session no longer auto-returns the conversation to New Session — the session stays open and remains visible as a dimmed row.

Filter semantics

A session is visible when (archived && showArchived) || (!archived && showUnarchived). Defaults: showUnarchived: true, showArchived: false — identical to the stock behavior. Both can be checked at once (see everything); both unchecked shows an empty list. Filter state is persisted in the plugin's own localStorage key and survives reloads. Grouping/ordering preferences are migrated once from the official dsh.workspace.view.v5 key.

Install

The plugin targets DSH 0.1.0-rc.x (tested on 0.1.0-rc.6).

npx @deepseek-ai/dsh plugin --profile web add github:piaohua/dsh-plugin-archive-manager

From npm (once published)

npx @deepseek-ai/dsh plugin --profile web add dsh-plugin-archive-manager

Then restart dsh web. The plugin is a profile bundle (it ships a cordis.patch.yml that inserts its loader row), so it is picked up by the normal dsh plugin reconcile flow.

To uninstall, run dsh plugin --profile web remove dsh-plugin-archive-manager and restart — the stock workspace browser returns exactly as before (shadowing is reversible by design).

Local development

# in this repository
npm run build     # assemble lib/client.js from src/ (client bundle + embedded CSS)
npm run verify    # pre-publish structural checks
node scripts/smoke.mjs   # execute the bundle factory in a stubbed browser environment

# install the local checkout into your web profile (path specs are anchored to your cwd)
npx @deepseek-ai/dsh plugin --profile web add file:/absolute/path/to/dsh-plugin-archive-manager

Package layout

dsh-plugin-archive-manager/
├── package.json        # dsh.bundle.patch + dsh.client declaration
├── cordis.patch.yml    # composition patch: inserts this plugin's loader row
├── lib/
│   ├── index.js        # Host half: registry unarchiveSession + exact HTTP route
│   └── client.js       # Browser half: __ModuleLoader__ bundle (shadow browser + new UI)
├── scripts/
│   ├── build.mjs       # assemble lib/client.js from src/
│   ├── verify.mjs      # pre-publish checks
│   └── smoke.mjs       # bundle factory smoke test
├── src/
│   ├── client.src.js   # browser bundle source (CSS placeholder)
│   ├── rows.css        # official row styles (re-tagged, self-contained)
│   ├── browser.css     # official browser styles (re-tagged, self-contained)
│   ├── picker.css      # official picker styles (re-tagged, self-contained)
│   └── extra.css       # plugin-only styles (dimmed archived titles)
├── README.md           # this file
├── README.zh.md        # 中文说明
└── LICENSE             # MIT

Publishing

The built artifacts (lib/) are committed, so the repository itself is installable via the GitHub route above. To also publish to the npm registry:

npm publish

Install from npm as shown above.

Known trade-offs & compatibility

  • The browsing region is a faithful re-implementation, not the official component. DSH 0.1.0-rc.x exposes no extension slots inside the workspace browser (only the two directory-flow holes), so the only supported way to change its behavior is to shadow the slot. The implementation copies the official logic and styles (MIT, re-tagged CSS injected independently), so visuals and interactions match; but future DSH UI changes to the workspace browser will not automatically flow into this plugin — update the plugin to track DSH releases.
  • "Add workspace" uses the host native directory picker (pickDirectory) with a path-input dialog fallback, instead of the official directory-flow hole (which is declared by the shadowed entry and therefore cannot be rendered by this plugin). The conversation empty-state picker is unaffected.
  • The row menu keeps Rename / Fork for archived sessions (both remain valid on archived sessions).
  • Removing the plugin restores the stock browser; the plugin's filter state lives in its own localStorage key and leaves no residue.

License

MIT

Plugins associés