Overview
@kagurazakayashi/dsh-delete-session
README / EN
Package documentation
Registry summary
dsh.pub verifies the pinned bundle contract, runtime facts, and distribution semantics. The complete README remains in the source repository.
Read the full README on GitHubLIMITATIONS
Known limitations
- **Running sessions refused**: `ctx.agents.get(id)?.status !== 'idle'` returns 409, and a second check runs right before deletion. Only idle sessions resident in memory are exempt. - **Auto-archive before delete**: the destructive `rm` is preceded by `workspaceRegistry.archiveSession(id)`, which lets the sidebar hide the session immediately via the `host/archived-sessions-changed` broadcast (and lets the client auto-clear the current selection), so it does not linger in the list until restart. Archiving is idempotent; a failure does not block the main deletion flow. - **Session locating strategy**: the core no longer exposes the `supportsRawArtifacts` flag. The plugin first calls the JSONL backend's public API `resolveCurrentLog(id)` (async, returning the absolute path of the current-format-generation log); for sessions that have not been migrated yet — filenames without a `vN` marker — it returns `undefined` (on this machine only 4 of 89 existing sessions were in the new format), so the plugin falls back to the backend's still-present-at-runtime `locate(header)` (returning `{ kind, path }`). When neither yields a path it returns 501. If the backend throws an error carrying `kind: 'jsonl'` and `path` diagnostics (for example a log in a newer version), the plugin reuses that path to complete the deletion. - **Deletes only the session directory**: `rm(dirname(logPath), { recursive: true, force: false })`; an archive marker is written first, but workspace groups, projection caches, and shared attachments are left untouched. Before deleting, the target directory name must be **exactly the session id** (the backend names it with `encodeSegment(id)`, and session ids only contain `[A-Za-z0-9._-]`), so the whole project directory can never be recursively removed. - **Irreversible**: deletion is a recursive `rm` with no recycle bin; operate with care. - **In-memory two-step state** (`click-again` mode only): the warning state lives only in browser memory (per session id, 8-second window) and disappears on plugin unmount, page refresh, or timeout; no persistent state is produced. Switching to another mode stops showing it. - **Official session-menu slot, no DOM injection**: the plugin contributes a normal entry to the `sidebar.workspaces.session.menu.item` list (registration id `delete-session`, order `450`), which the host menu renders as one `role="menuitem"` button. The slot supplies `{ sessionId, displayTitle }` plus a `useMenuOpenState` hook, so the plugin receives the exact session id and never captures the row's `…` button click, runs a `MutationObserver` over `document.body`, parses the row's `aria-label` (`会话“{name}”的操作` / `Session actions for {name}`), re-implements the core's relative-time bucketing, or clones the "Archive session" item. Keyboard traversal, focus return and menu dismissal are handled by the host menu, so no DOM structure and no localized text is depended upon. - **Availability follows the slot**: the item shows up wherever the host renders the session menu; the plugin waits for that slot to be declared, so a deployment that does not compose `@deepseek-ai/dsh-client-ui-workspace` leaves no trace of it.
