DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Dialogue Cleanup — DeepSeek Harness 插件(DSH Plugin)
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins
D

dsh-dialogue-cleanup

Dialogue Cleanup

从正在运行的 Web runtime 中删除 DeepSeek Harness 会话:分离实时存储条目、删除工作区记录,并移除磁盘上的构件。在一个软件包中包含主机端和 Web 客户端两部分。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add github:Winnie-0721/dsh-dialogue-cleanup#23fb6b0a1815f8dd8cbc785ee0f23019c56a7422
README兼容性版本

兼容性与来源证明

Dialogue Cleanup 以 dsh-dialogue-cleanup 发布,当前版本为 1.0.2。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
github
Registry 更新时间
2026/10/16

版本

1.0.2stable
2026/10/16

相关插件

正在加载相关插件…

最新版
1.0.2
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
web
许可证
MIT
发布源
github
GitHub
★ 2
周下载
0
最近提交
2026/10/16
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

相关插件

继续浏览 memory-context 分类下经过校验的插件。

Hindsight Coding Agents@vectorize-io/hindsight-coding-agents面向编程代理的仅反思式 Hindsight 长期记忆(可插拔支持多种运行框架:opencode、……),自动在后台导入(无需设置 CLI)。Memsearch Dsh@zilliz/memsearch-dsh适用于 DeepSeek Harness 的 MemSearch 插件:在多个代理之间共享 Markdown 记忆,支持捕获、步骤前上下文注入、记忆召回技能和技能候选审核面板。Memory@furongjun1999/dsh-memory灵枢(Lingshu·líng shū)DeepSeek Harness 插件:完整大脑——长期记忆/知识飞轮/自我认知/递归反思接入 DSH,对话自动沉淀进 md_cg 认知图(md 文档)Archive Manager@michengai/dsh-archive-manager归档、恢复、收藏和永久删除会话,并诊断损坏的会话日志。

README

dsh-dialogue-cleanup

English · 简体中文

Delete DeepSeek Harness sessions from the running Web GUI — without restarting, without leaving the window.

One row in the session ... menu for a single delete, plus a bulk management page inside Settings.

Bulk management panel in Settings: search, filters, per-row status badges and 16 session rows

Install · Gallery · How it works · Releasing · Releases

Why it exists

One-line positioning: deleting a session should actually delete it. DeepSeek Harness keeps a session in four places at once — the live store, the workspace records, the registry leftovers (pin / archive), and the files on disk. Removing one of them leaves a ghost row, a stale workspace, or a directory that silently keeps occupying disk. Everything below is that positioning made concrete:

  • One irreversible operation, implemented once. deleteSession lives in the Host (lib/service.js) and is reached through two thin adapters — the HTTP contract and the slot UI — so the single-delete path and the bulk path cannot drift apart.
  • A running session is refused, not guessed at. The Host decides deletable and the UI simply does not offer what the Host would reject. The panel never decides by itself whether something is safe to delete.
  • Archived sessions are still shown by default. Archiving is not deleting: an archived session still occupies disk, so hiding it by default would hide exactly the files you came to clean up. (The official sidebar hides them; here it is a tri-state filter — hide archived / all / archived only — and archived are shown by default.)
  • Subagent rows are labelled. The official sidebar hides origin: 'subagent' rows entirely, so whenever those rows do appear (kind = subagent / all) each one is explicitly badged — a subagent session must never look like an ordinary conversation.
  • It says what it actually did. The result line reports ok / failed / degraded / directories removed, and each failure keeps its own reason verbatim. When the live store entry cannot be detached, the plugin reports detached: false rather than claiming success.
  • Errors are semantically truthful. Unlike the upstream package (which always answered 200), this one uses real status codes: 400 / 403 / 404 / 405 / 409 / 429 / 500.

UI at a glance

The confirmation overlay: irreversible, and it says so. Two closing paths only — an explicit Cancel button, or Esc. Clicking the scrim deliberately does not dismiss it, because a mis-click on an irreversible delete should not cost you your chance to confirm:

Delete confirmation: permanent deletion warning, session id, and Cancel / 永久删除 buttons

The overlay is a native <dialog> driven by showModal(), so it enters the browser's top layer and therefore stacks above the Settings panel it was opened from (a plain positioned element could not). That also brings a real focus trap and correct Esc semantics for free — and it needs no portal outside the component tree.

The bulk panel (inside Settings) — search, project / state / session-kind / archive filters, sort, paging, and per-row status badges. The badges in the screenshot above come from real render output: 空闲 (idle) / 运行中 (running, not selectable) / 子代理 (subagent) / 已归档 (archived).

The two screenshots are generated from the actual component tree and the actual CSS by scripts/render-shot.mjs (the same React stand-in the render tests use), rasterised with headless Edge. They are not hand-drawn mockups; they are also not a photograph of a live GUI — see Honest limitations.

Quick Start

dsh plugin --profile web add dsh-dialogue-cleanup
  1. Single delete — hover a session row in the sidebar, open the ... menu and pick Delete session (registered at order: 500, right after the shipped Archive entry at 400). A themed confirmation appears; confirming removes the live entry, the workspace records, the registry leftovers and the on-disk artifacts.
  2. Bulk delete — open Settings → Dialogue Cleanup. Tick rows (or Select all deletable), then delete them in one request.
  3. Host-side changes need a restart of the DSH process; client-side changes do not (see the table in docs/RELEASING.md).

Compatible with DSH 0.2.0-rc.2. The npm package and the GitHub Release are published together; versioning rules and the release chain live in docs/RELEASING.md.

How it works

One npm package carries both halves, installed into the host per the official plugin spec:

  • Host half (repo process) — lib/index.js is a Cordis function plugin exporting only name / inject / apply. It registers a single ctx.webServer prefix route and keeps the entire deletion implementation in lib/service.js. Filesystem removal and path containment live in lib/artifacts.js; the audit trail in lib/audit.js.
  • Client half (browser) — client.js, a single-file bundle registered through window.__ModuleLoader__.load({ id, factory }), with zero dependencies beyond require("react").
  • Both entry points are official slots; neither touches the DOM:
    • sidebar.workspaces.session.menu.item at order: 500 → the single-delete row.
    • settings.section (id: dialogue-cleanup, order: 25, after the shipped account(-10) / general(0) / models(10) / plugins(15) / agent-presets(20)) → entry and panel. One registration is one Settings page, whose content renders in the panel's content column.
  • Because the panel lives in Settings it needs no layout service and does not compete for space in main or the sidebar — one fewer optional dependency and one fewer degradation branch.
  • The stylesheet travels with the component. The menu item renders its own <style> beside itself (finding H1 of the project's own audit: the row was rendering unstyled because the stylesheet was only injected on the settings path).

The deletion sequence

  1. Refuse a running session — 409 refused.
  2. Detach the live store entry — otherwise the deleted row survives as a ghost.
  3. Drop workspace records — counting only workspaces that actually detached.
  4. Clear registry leftovers — pin / archive records, via the public idempotent API.
  5. Remove on-disk artifacts — <DSH_HOME>/sessions/<project>/<sessionId>, plus the derived projection cache.
  6. Write an audit line — <DSH_HOME>/logs/dialogue-cleanup.jsonl.

HTTP contract

MethodPathPurpose
POST/api-ext/dialogue-cleanup/delete{ "sessionId": "..." } → delete one; { "sessionIds": [...] } → delete many (the Host runs the same deleteSession per id and returns a per-id result)
POST/GET/api-ext/dialogue-cleanup/listsession rows with deletable / blockedReason
GET/api-ext/dialogue-cleanup/statuscapabilities, config, runtime paths

Envelope: { ok: true, value } / { ok: false, error: { code, message, hint? } }.

Configuration

All tunables live in the plugin Config (lib/config.js), so a user's patch layer survives upgrades. A matching override replaces the whole config — write every field you care about.

KeyDefaultMeaning
maxBodyBytes65536request-body ceiling (upstream: 1 MiB)
readTimeoutMs10000body-read timeout (upstream: none)
audit / auditPathtrue / nullaudit log; null → <DSH_HOME>/logs/...
rateLimitPerMinute60per-minute delete request budget (a batch counts once); 0 disables
requireIdleSessiontruesafety valve for the running-session refusal
stopIdleAgentfalsesee the honest-degradation note below
matchAlternateIdSpellingtrueprobe the other session- spelling, guarded
removeProjectionCachetruealso drop the derived projection cache
clearRegistryRecordstrueunpin / unarchive leftovers
confirmInUitrueUI confirmation (the Host does not trust it)
titleCacheTtlMs300000title-fold cache TTL; 0 disables
titleFetchConcurrency8shard concurrency when folding titles
titleLimit100max rows per page to fold titles for; 0 skips title reading
runningProbeTtlMs1000how long a running-state snapshot is reused. Turns batch delete from O(N) full-corpus list calls into O(1); 0 re-probes every item

Honest limitations

These are measured against the live runtime and differ from what the upstream package assumes. They are reported truthfully rather than papered over:

  • No public stop for an idle agent. The public Agent type is { readonly id: SessionId } — no status, no ctx. Upstream's agent.status === "running" and agent.ctx.fiber._unload() therefore cannot be relied on (_unload is a Cordis private method and is deliberately never called). "Is it running?" comes from the public sessionController.list() → SessionSummary.running. A session that still has an attached agent and cannot be stopped safely is refused, and the UI shows why.
  • Detaching the live entry is best-effort. The public sessions service exposes create/prepare/enter/announce/flush/get/list/fork — no public detach. The plugin tries the public method first, then the internal store entry, and reports detached: false when neither is available instead of claiming success.
  • Two on-disk id spellings coexist. Observed in one <DSH_HOME>: ...\<uuid>\session.v4.jsonl.zstd and ...\session-<uuid>\session.v4.jsonl.zstd. An exact-id join can never delete the prefixed half. This plugin probes the alternate spelling only when it can confirm the candidate is not a different live session; with no such evidence it deletes nothing rather than risk a neighbour.
  • The screenshots are real render output, not a live-GUI photograph. They come from the actual component tree + actual CSS, rasterised headless; the theme tokens are pinned to a light theme and the row data is a demo fixture. What the panel looks like inside a running GUI with the real theme has not been captured here.

Development and acceptance

# Full gate: node --check + migration/contract/render/release regression suites
node --test "test/**/*.test.mjs"

# Release gate only (no version change, no packing, no publishing)
pwsh -File scripts/release.ps1 -LocalOnly

# Regenerate the two documentation screenshots from the real component tree
node scripts/render-shot.mjs

The suites are currently 161 tests across 9 files:

SuiteCovers
contract.test.mjsthe host ↔ client contract and slot declarations (largest suite)
service.test.mjsdeleteSession end-to-end behaviour and refusals
client.test.mjsregistration surface, ids, no-cross-package requires
render.test.mjscomponents actually rendered through a React stand-in
artifacts.test.mjspath containment, symlink refusal, alternate-spelling guards
session-id.test.mjsid validation (no separators or dots)
eol.test.mjsline endings, and that every tracked file is git-declared eol=lf
release-workflow.test.mjsthe OIDC publishing structure (reverse assertion: pack-release.yml must not contain its own publish steps)
ps-script.test.mjsPowerShell 5.1 BOM / encoding pitfalls

Two of these exist because the corresponding bug actually shipped and was caught afterwards:

  • eol.test.mjs — the first release produced different bytes from CI (pnpm pack) and from local (npm pack): icon.svg and LICENSE were CRLF in CI, because .gitattributes declared only * text=auto and the GitHub Windows runner defaults to core.autocrlf=true. The first version of this test missed it (it scanned a hardcoded extension list, so *.svg and the extension-less LICENSE were invisible); it now sweeps every git-tracked file and reads the effective attribute via git check-attr. Fixing it also caught .gitignore.
  • release-workflow.test.mjs — the OIDC trust is bound to a workflow filename, and writing the publish steps a second time is exactly the bug that broke that other repository's releases twice. See docs/RELEASING.md.

Repository layout

PathContents
lib/index.jsapply(ctx, config) — assembles and registers the host routes
lib/service.jsdeleteSession — the single deletion implementation
lib/artifacts.jsdisk removal + path containment
lib/http.jssame-origin checks, body limits, status codes
lib/config.jsConfig schema + defaults
lib/audit.jsJSONL audit trail
client.jsthe web client half: slot registrations (menu row + confirm overlay + settings section)
cordis.patch.ymlinserts the host half, inject: [webServer]
.github/workflows/pack-release.yml (tag → gate → pack → GitHub Release) and publish-npm.yml (the only npm-publish implementation, reused via workflow_call)
docs/RELEASING.mdversion rules and the release chain
scripts/release.ps1version bump + gate (+ CI pack/release)
scripts/render-shot.mjsregenerates the documentation screenshots
test/the 161-test regression suite

License

MIT