🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

会话中枢套件 chc-1986/dsh-session-suite

DeepSeek Harness
chc-198612 天前有提交已提供中文文档扫描:含敏感能力

跨会话收发消息,统一信箱分发并唤醒未归档会话

29.9/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/24 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add chc-1986/dsh-session-suite
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么[目录]—
dsh 原生插件 · market
暂无时间戳·判据 →
装得上吗[实装验证]—
本站尚未做安装检查
暂无时间戳·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 12 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →

可信度证据

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 94 处,展示前 48 条)
  • 读取本地文件
    lib/index.js:3326
    for (const name of readdirSync(item.path)) {
  • 读取本地文件
    lib/index.js:3329
    const st = statSync(file);
  • 删除本地文件
    lib/index.js:3332
    rmSync(file, { force: true });
  • 读取本地文件
    lib/index.js:3363
    st = statSync(file);
  • 读取本地文件
    lib/index.js:3373
    const parsed = JSON.parse(readFileSync(file, 'utf8'));
  • 写入本地文件
    lib/index.js:3597
    try { mkdirSync(dir, { recursive: true }); } catch { }
  • 读取本地文件
    lib/index.js:3605
    if (!existsSync(file)) return fallback;
  • 读取本地文件
    lib/index.js:3606
    return JSON.parse(readFileSync(file, 'utf8'));
  • 写入本地文件
    lib/index.js:3614
    writeFileSync(file, JSON.stringify(value, null, 2), 'utf8');
  • 写入本地文件
    lib/index.js:3833
    try { mkdirSync(dir, { recursive: true }); } catch { }
  • 写入本地文件
    lib/index.js:3891
    writeFileSync(join(root, 'status.json'), JSON.stringify(payload, null, 2), 'utf8');
  • 写入本地文件
    lib/index.js:3918
    writeFileSync(tmp, JSON.stringify(record, null, 2), 'utf8');
  • 写入本地文件
    lib/index.js:3919
    renameSync(tmp, file);
  • 删除本地文件递归
    lib/index.js:5166
    rmSync(join(root, name), { recursive: true, force: true });
  • 执行外部命令固定命令
    lib/index.js:5188
    spawn('explorer.exe', [`/select,${file}`], { windowsHide: true, detached: true, stdio: 'ignore' }).unref();
  • 执行外部命令固定命令
    lib/index.js:5190
    spawn('open', ['-R', file], { detached: true, stdio: 'ignore' }).unref();
  • 执行外部命令固定命令
    lib/index.js:5192
    spawn('xdg-open', [dirname(file)], { detached: true, stdio: 'ignore' }).unref();
  • 删除本地文件
    lib/index.js:5967
    try { rmSync(uploadTemp, { force: true }); } catch { }
  • 发起网络请求
    lib/client.js:522
    const res = await fetch(LIST_ENDPOINT, {
  • 发起网络请求
    lib/client.js:543
    const res = await fetch(GATE_ENDPOINT, {
  • 发起网络请求
    lib/client.js:575
    const res = await fetch(GATE_ENDPOINT, {
  • 发起网络请求
    lib/client.js:611
    const res = await fetch(PASSCODE_ENDPOINT, {
  • 发起网络请求
    lib/client.js:639
    const res = await fetch(TRASH_EMPTY_ENDPOINT, {
  • 发起网络请求
    lib/client.js:665
    const res = await fetch(REDELIVER_ENDPOINT, {
  • 写入剪贴板
    lib/client.js:814
    Promise.resolve(clipboard.writeText(text)).then(() => showToast("ok", tr("copied"))).catch(() => fallback());
  • 读取本地文件
    lib/session-package.mjs:61
    if (!existsSync(root)) return undefined;
  • 读取本地文件
    lib/session-package.mjs:62
    for (const entry of readdirSync(root)) {
  • 读取本地文件
    lib/session-package.mjs:66
    if (statSync(candidate).isDirectory()) return candidate;
  • 读取本地文件
    lib/session-package.mjs:75
    return existsSync(direct) ? direct : undefined;
  • 读取本地文件
    lib/session-package.mjs:81
    const decoded = decodeSessionLogBuffer(readFileSync(file));
  • 写入本地文件
    lib/session-package.mjs:103
    mkdirSync(target, { recursive: true });
  • 读取本地文件
    lib/session-package.mjs:104
    for (const entry of readdirSync(source, { withFileTypes: true })) {
  • 写入本地文件
    lib/session-package.mjs:108
    else if (entry.isFile()) copyFileSync(from, to);
  • 执行外部命令来自配置/变量
    lib/session-package.mjs:136
    const result = spawnSync(tarBinary(), args, { encoding: 'utf8', windowsHide: true });
  • 写入本地文件
    lib/session-package.mjs:145
    mkdirSync(destDir, { recursive: true });
  • 执行外部命令来自配置/变量
    lib/session-package.mjs:146
    const result = spawnSync(tarBinary(), ['-x', '-f', zipPath, '-C', destDir], { encoding: 'utf8', windowsHide: true });
  • 写入本地文件
    lib/session-package.mjs:172
    mkdirSync(targetDir, { recursive: true });
  • 写入本地文件
    lib/session-package.mjs:207
    writeFileSync(join(packageDir, EXPORT_MANIFEST), JSON.stringify(manifest, null, 2), 'utf8');
  • 删除本地文件递归
    lib/session-package.mjs:217
    try { rmSync(stage, { recursive: true, force: true }); } catch { }
  • 写入本地文件
    lib/session-package.mjs:234
    mkdirSync(root, { recursive: true });
  • 删除本地文件递归
    lib/session-package.mjs:290
    try { rmSync(stage, { recursive: true, force: true }); } catch { }
  • 发起网络请求
    src/client/panel.ts:651
    const res = await fetch(LIST_ENDPOINT, {
  • 发起网络请求
    src/client/panel.ts:675
    const res = await fetch(GATE_ENDPOINT, { cache: 'no-store', signal: AbortSignal.timeout(15000) });
  • 发起网络请求
    src/client/panel.ts:707
    const res = await fetch(GATE_ENDPOINT, {
  • 发起网络请求
    src/client/panel.ts:742
    const res = await fetch(PASSCODE_ENDPOINT, {
  • 发起网络请求
    src/client/panel.ts:766
    const res = await fetch(TRASH_EMPTY_ENDPOINT, {
  • 发起网络请求
    src/client/panel.ts:792
    const res = await fetch(REDELIVER_ENDPOINT, {
  • 写入剪贴板
    src/client/panel.ts:941
    void Promise.resolve(clipboard.writeText(text))
扫描于 2026/11/4(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

社区实装还没有人打卡 · 装过的第一个就是你
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-agent@deepseek-ai/dsh-llm@deepseek-ai/dsh-session@deepseek-ai/dsh-tools@deepseek-ai/schemastery
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

跨会话聊天、目录即队列并带守门人的邮箱、会话中心面板,以及 DeepSeek Harness(DSH)的会话原地交接——全在一个 Cordis 插件里。

README

由 DeepSeek 最新模型翻译生成
dsh-session-suite 跨会话对话、目录即队列信箱、工作区登记,以及 DeepSeek Harness (DSH) 的会话中枢面板——打包为一个 Cordis 插件。 跨会话对话 + 目录即队列信箱 + 会话工作区登记 + 「会话中枢」面板,打包为一个 DSH 插件。 状态:beta(0.2.x)。目标 DSH >=0.2.1-0 <0.3.0。 Why use it / 为什么用它 - 一个总信箱 + 一个心跳,替代 N 个专用信箱。 One shared mailbox beats one mailbox per session. 信箱最初是给每个会话各设一个;加入信箱守卫(gatekeeper)——拦截垃圾信件、把来信分派给正确的会话——之后,不再需要给单个会话专设信箱:所有来信统一投到总信箱,配一个心跳即可完成分发。
展开完整文档(README 剩余 1 节)
dsh-session-suite

跨会话对话、目录即队列信箱、工作区登记,以及 DeepSeek Harness (DSH) 的会话中枢面板——打包为一个 Cordis 插件。

跨会话对话 + 目录即队列信箱 + 会话工作区登记 + 「会话中枢」面板,打包为一个 DSH 插件。

状态:beta(0.2.x)。目标 DSH >=0.2.1-0 <0.3.0。

Why use it / 为什么用它

- 一个总信箱 + 一个心跳,替代 N 个专用信箱。 One shared mailbox beats one mailbox per session. 信箱最初是给每个会话各设一个;加入信箱守卫(gatekeeper)——拦截垃圾信件、把来信分派给正确的会话——之后,不再需要给单个会话专设信箱:所有来信统一投到总信箱,配一个心跳即可完成分发。
Mailbox started as one inbox per session. With a gatekeeper triaging spam and routing letters, you no longer
need per-session mailboxes: everything lands in one shared mailbox, and a single heartbeat drives delivery.

- 按名投送,不用查 ID。 Address sessions by name, not by id. talk_to_session 直接写会话名字(targetName)就能投;会话 ID 对用户隐藏,只有重名时才追问编号,且30 分钟内记住你的选择,不重复问。
talk_to_session takes the session name (targetName) directly — ids stay hidden. Only duplicate names ask for a numbered pick, and that pick is remembered for 30 minutes.

- 免辨活踢醒:未归档就能派活。 No "is it alive?" check — if it is not archived, it can be woken.
wakeable = 记录存在 && 未归档;不用人工分辨会话是活的还是死的,未归档的直接唤醒派活,只有归档过的才踢不醒。
wakeable = record exists && not archived: hand work to any unarchived session; only archived ones stay asleep.

- 找出并清掉「官方列表里看不到」的会话。 Find every unarchived session — even ones DSH does not list. session_probe 做全量盘点(含误建、被隐藏的会话);配合会话中枢面板的归档 / 软删除 / 回收站清空与宿主侧真删除, 补上 DSH 官方「会话删不掉」的缺口。
session_probe inventories every session (including mis-created or hidden ones); the Session Hub panel adds
archive / soft-delete / trash-empty and a host-side hard delete — covering DSH's missing "delete a session" path.

删除不静默:软删除先进回收站,硬删除有二次确认;归档只是隐藏,随时可恢复。

Deletes are explicit: soft delete goes to a trash area, hard delete asks for confirmation, and archive is a
reversible hide.

Origin / 出身

始于「跨会话对话」与「信箱」两个独立插件,合并之后生长出「会话中枢」(面板 + 工作区登记)与「会话交棒」。

始于「跨会话对话」与「信箱」两个独立插件,合并之后生长出「会话中枢」与「会话交棒」。

Features / 特性

- 跨会话对话——智能体之间按会话名或 ID 互相说话:talk_to_session、steer_session、 stop_session、session_contacts、session_probe、create_session、update_session。
- 会话交棒——一次调用重建会话,上下文不丢:交棒包 → 同一路由上的继任会话 → 改名 → 迁移定时任务 → 更新会话清单表 → 最后归档旧会话。
- 目录即队列信箱——任何外部程序都能把 JSON 信件丢进 inbox/;插件把它投递给目标会话,等这一轮结束,再把回信文件写进 outbox/。不用端口,不用服务器。
- 工作区注册 —— 通过插件创建的会话(或之后挂接的会话)会注册到与 cwd 匹配的工作区,因此在侧边栏里出现在正确的分组下。
- 会话导出 / 导入 —— 把整个会话打包成一个 .zip(归档会话同样适用),之后可以恢复;附件只记录引用,不复制,导入也绝不会覆盖已有会话。
- Session Hub 面板 —— 侧边栏入口 + 分组会话清单(重命名 / 归档 / 软删除)、信箱闸门标签页(允许列表、通行码、闸门模型),以及信件标签页(回执、重投、统计)。
- Gatekeeper(可选) —— 信件的 LLM 分诊步骤:白名单、可选的共享密钥、可选的临时通行码、提示词注入加固(信件文本只是数据,永远不是指令)。

Install / 安装

dsh plugin add dsh-session-suite

或者把它加到你的配置档 cordis.patch.yml 里:

- id: dsh-session-suite
name: "dsh-session-suite"
config:
writeEnabled: true # cross-session write path (OFF by default)
dir: "" # mailbox root; empty = <DSH_HOME or ~/.dsh>/mailbox

插件自带 bundle 补丁(cordis.patch.yml)和浏览器端部分(./client),所以正常执行 dsh plugin add 就够了 —— 不用手动接线。

Tools / 工具

| 工具 | 作用 |
| session_contacts | 列出可寻址的会话(id、cwd、状态、可唤醒、已归档)。 |
| talk_to_session | 给另一个会话发消息,并(可选)等待它的回复。 |
| steer_session | 往运行中的回合注入消息(重定向,但不结束该回合)。 |
| stop_session | 停止会话当前回合(效果等同于界面上的停止按钮)。 |
| session_handover | 五步会话重建:交接 → 继任者 → 重命名 → 定时任务 → 最后归档旧会话。 |
| create_session | 在指定的 cwd / 服务商 / 模型 / effort 上创建会话,并注册到对应工作区。 |
| update_session | 通过追加一条持久标题事件来重命名会话。 |
| session_probe | 只读查看每个会话的运行时表面(状态、cwd、seq、可用方法)。 |
| session_host_probe | 只读能力探测:当前 Host 实际挂载了哪些跨会话服务。 |
| workspace_lookup | 只读:查找与 cwd 匹配的工作区(优先实时服务,否则读 storages/workspace.json)。 |
| read_session_log | 把会话日志(多帧 zstd)读成过滤后的文本 —— 看看另一个会话到底做了什么。 |

Export / Import · 导出 / 导入(0.2.0)

导出:会话清单每行都有「导出」(归档与回收站里的会话也能导出——这正是"先归档、需要时再启用"的主场景)。
宿主把整个会话目录原样打成一个 .zip,默认落在 ~/.dsh/exports/,导出成功后自动在文件管理器里定位该文件。

dsh-session-export/
manifest.json # schemaVersion, sessionId, title, cwd, encodedDir,
exportedAt, pluginVersion, byteSize, turnCount, attachmentRefs
session/<session-id>/ # 会话目录原样(session.v4.jsonl.zstd + 伴随文件)

- 全程只读源目录;导出后源会话不受影响。
- 附件放在全局内容寻址库(~/.dsh/attachments/),不随包导出;manifest 里的 attachmentRefs 和导出提示会如实告诉你「含 N 处附件引用,未包含在包内」。

导入:面板顶部「导入会话包」→ 选 .zip。宿主依次校验 manifest.schemaVersion、会话日志的 zstd 完整性、sessionId 格式;然后解到临时目录,原子 rename 进 sessions/<编码工作区>/<sessionId>/,目标工作区不存在会自动创建;该 cwd 还没登记工作区时,走插件现有的工作区登记路径。

- ID 冲突一律拒绝:目标已有同 id 会话目录时报错返回,不覆盖、不合并。
- 导入不执行任何东西:纯文件落位,包内脚本一律不运行。
- v1 限制:导入后需重启 dsh web 才会出现在对话列表(宿主启动时扫描会话目录)。

已知限制 (Known limitations)

- 导出/导入的 zip 由系统 tar -a 生成:Windows(tar.exe)与 macOS(bsdtar)开箱可用;Linux 的 GNU tar 不支持 -a,需要 bsdtar 或预装 zip/unzip(v1 未内置 zip 库)。
- 附件不入包(manifest 只记 attachmentRefs),跨机迁移后附件引用会缺失。

Mailbox protocol / 信箱协议

一个总信箱 + 一个心跳。 所有来信投到同一个目录;信箱守卫(gatekeeper)负责拦截垃圾、按名字/沿用/模型分派,插件用 500 ms 轮询(心跳)把信送到目标会话,再把回执写回 outbox/。不需要为每个会话单设信箱,也不需要常驻服务或端口。

最小配置(总信箱 + 心跳):

- id: dsh-session-suite
name: "dsh-session-suite"
config:
dir: "" # 总信箱;空 = <DSH_HOME 或 ~/.dsh>/mailbox pollMs: 500 # 心跳:扫 inbox 的间隔 heartbeatMs: 1000 # 心跳:状态刷新间隔
allowTargets: [] # 建议显式填白名单(或用 <dir>/allow.json)
secret: "" # 共享目录建议设置一个投递密钥

往 <dir>/inbox/ 里丢一个 JSON 文件;插件会把它移到 processed/,再往 <dir>/outbox/ 写一条回执。

{ "target": "<session name or id>", "message": "hello", "from": "my-app", "id": "req-0001" }

信里写了会话名(to / sessionName / targetName)时可以省略 target;否则由信箱守卫决定。回执:

{ "target": "session-name", "seq": 42, "at": "2026-01-01T00:00:00.000Z",
"text": "reply text", "requestId": "req-0001", "from": "my-app",
"status": "ok", "reason": "completed" }

status 取值为 ok · partial · no-reply · aborted-by-target · error · deduped · blocked · target_queue_timeout。重复的 id/requestId 会去重。

Configuration / 配置

| Key | Default | Meaning |
| writeEnabled | false | 跨会话写入路径的总开关。 |
| maxHops | 5 | 交接链最大深度。 |
| syncTimeoutMs | 120000 | sync 投递等待对端文本的时长。 |
| pollIntervalMs | 500 | 轮询聊天回复的间隔。 |
| maxReplyChars | 200000 | 回拷回复文本的上限(也是 outbox 上限)。 |
| maxMessageBytes | 65536 | 单次投递的上限。 |
| dir | "" | 信箱根目录;空 = <DSH_HOME 或 ~/.dsh>/mailbox。 |
| pollMs | 500 | 扫描 inbox 的间隔。 |
| heartbeatMs | 1000 | 心跳间隔(客户端超过 30 s 视为失联)。 |
| replyTimeoutMs | 600000 | 等待一轮回复的最长时间,超时写 partial/no-reply。 |
| queueTimeoutMs | 660000 | 每个目标在途队列的释放阈值。 |
| allowTargets | [] | 目标会话 id 白名单(allow.json 不存在时使用)。 |
| secret | "" | 可选的共享密钥,每封信都要带上(空 = 不校验)。 |
| stateDir | "" | Fleet 表目录(fleet.json);留空 = <DSH_HOME>/.dsh/state。 |
| gatekeeper. | 见代码 | 可选的 LLM 分诊:服务商 / 模型 / 推理强度、快速通道、通行码、回执与催促规则。 |

allow.json(放在 dir 内)优先于 allowTargets,2 秒内重新读取,并且是失败即拒绝:文件损坏时拒绝一切,而不是悄悄全部放行。

安全说明 / 安全边界

- 写入需显式开启:writeEnabled: false 时,插件不会改动任何会话。
- 不执行 shell,不运行任意代码:信箱只读写 dir 下的 JSON 文件;会话按各自的权限运行。信件正文作为数据传入(绝不作为指令),gate 模型拿不到任何工具。
- 提示词注入加固:gate 调用锁定单一服务商 / 模型 / 推理强度,且不携带工具列表。
- 失败即拒绝的允许列表、可选的共享密钥,以及针对共享目录的通行码校验。
- 面板以只读为主:破坏性操作要么软删除,要么需显式确认。

环境要求 / 环境

- DSH >=0.2.1-0 <0.3.0(桌面宿主,需提供 agents / sessions / tools / llm 服务)。
- 内置工具需要 Node.js >=22;支持 Windows、macOS 和 Linux(路径从环境解析,绝不硬编码)。

开发 / 开发

npm run bundle # build the client half (tsdown + scope wrapper)
npm run smoke # core smoke suite
npm run smoke-ui # panel / wakeability suite
npm run smoke-ops # operations + archive suite
npm run smoke-gate # gatekeeper suite

宿主侧(lib/index.js)是手写的 ESM,不是生成的;构建只把 src/client/.ts 编译成 lib/client.js。

许可证

MIT —— 见 LICENSE。
预览分享卡片长什么样 ↓chc-1986/dsh-session-suite
分享 · DeepSeek Harness Hub
chc-1986/dsh-session-suite

跨会话收发消息,统一信箱分发并唤醒未归档会话

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部