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

会话指挥台 EIGHTfs/dsh-session-conductor

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

集中管理会话,支持归档、回收站与自动续跑

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

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

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

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么
dsh 原生插件 · other
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 1 天前
档位由哪些信号合成

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

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

读写/删除本地文件发起外部网络请求
查看扫描证据(共 122 处,展示前 107 条)
  • 删除本地文件递归
    lib/features/session-ops.js:157
    await rm(sessionDir, { recursive: true, force: true });
  • 删除本地文件递归
    lib/features/session-ops.js:161
    if ((await readdir(projectDir)).length === 0) await rm(projectDir, { recursive: true, force: true });
  • 读取本地文件
    lib/features/session-ops.js:161
    if ((await readdir(projectDir)).length === 0) await rm(projectDir, { recursive: true, force: true });
  • 读取本地文件
    lib/features/session-ops.js:323
    text = await decodeAllFrames(readFileSync(filePath));
  • 写入本地文件
    lib/features/session-ops.js:388
    mkdirSync(backupDir, { recursive: true });
  • 写入本地文件
    lib/features/session-ops.js:390
    copyFileSync(filePath, bak);
  • 读取本地文件
    lib/core/config.js:86
    try { if (statSync(ws).isDirectory()) return ws; } catch { }
  • 读取本地文件
    lib/core/config.js:120
    const parsed = JSON.parse(await readFile(file, "utf8"));
  • 写入本地文件
    lib/core/config.js:147
    await mkdir(path.dirname(file), { recursive: true });
  • 写入本地文件
    lib/core/config.js:150
    await writeFile(tmpPath, JSON.stringify({
  • 写入本地文件
    lib/core/config.js:155
    await rename(tmpPath, file);
  • 读取本地文件
    lib/sessions/events.js:143
    for (const group of readdirSync(root)) {
  • 读取本地文件
    lib/sessions/events.js:145
    if (!existsSync(dir)) continue;
  • 读取本地文件
    lib/sessions/events.js:178
    const buf = await readFile(file);
  • 读取本地文件
    lib/sessions/events.js:280
    const buf = await readFile(file);
  • 写入本地文件
    lib/shared/atomic-file.js:21
    writeFileSync(tmpPath, data);
  • 写入本地文件
    lib/shared/atomic-file.js:23
    chmodSync(tmpPath, statSync(targetPath).mode);
  • 读取本地文件
    lib/shared/atomic-file.js:23
    chmodSync(tmpPath, statSync(targetPath).mode);
  • 写入本地文件
    lib/shared/atomic-file.js:27
    renameSync(tmpPath, targetPath);
  • 读取本地文件
    lib/shared/atomic-file.js:36
    if (!existsSync(backupPath)) copyFileSync(srcPath, backupPath);
  • 写入本地文件
    lib/shared/atomic-file.js:36
    if (!existsSync(backupPath)) copyFileSync(srcPath, backupPath);
  • 发起网络请求
    lib/template-inject.js:113
    res = await fetch(raw, {
  • 读取本地文件
    lib/template-inject.js:152
    if (!existsSync(file)) return '';
  • 读取本地文件
    lib/template-inject.js:153
    const text = readFileSync(file, 'utf8');
  • 读取本地文件
    lib/template-inject.js:169
    const raw = readFileSync(url, 'utf8');
  • 读取本地文件
    lib/template-inject.js:253
    try { st = statSync(full); } catch (error) {
  • 读取本地文件
    lib/template-inject.js:258
    const content = readFileSync(full, 'utf8');
  • 发起网络请求
    lib/group.js:231
    const raw = await fetch(`http://127.0.0.1:${hostPort}/api/session/create`, {
  • 发起网络请求
    lib/group.js:268
    const prompt = await fetch(`http://127.0.0.1:${hostPort}/api/session.prompt`, {
  • 读取本地文件
    lib/features/base-routes.js:29
    zh: JSON.parse(readFileSync(new URL("../i18n/zh.json", import.meta.url), "utf8")),
  • 读取本地文件
    lib/features/base-routes.js:30
    en: JSON.parse(readFileSync(new URL("../i18n/en.json", import.meta.url), "utf8")),
  • 读取本地文件
    lib/core/index-store.js:102
    if (!existsSync(legacyPath)) continue;
  • 读取本地文件
    lib/features/member-model/locate.js:40
    for (const group of readdirSync(root)) {
  • 读取本地文件
    lib/features/member-model/locate.js:43
    names = readdirSync(join(root, group));
  • 读取本地文件
    lib/features/member-model/switch.js:66
    text = await decodeAllFrames(await readFile(filePath));
  • 写入本地文件
    lib/features/member-model/switch.js:87
    mkdirSync(backupDir, { recursive: true });
  • 写入本地文件
    lib/features/member-model/switch.js:89
    copyFileSync(filePath, file);
  • 写入本地文件
    lib/features/member-model/switch.js:100
    copyFileSync(backup.file, filePath);
  • 读取本地文件
    lib/features/member-model/switch.js:125
    const buf = await readFile(filePath);
  • 读取本地文件
    lib/features/member-model/switch.js:161
    buf = await readFile(filePath);
  • 读取本地文件
    lib/features/member-model/switch.js:287
    freshTail = await readTailEvents(await readFile(filePath), { tailFrames: 3 });
  • 读取本地文件
    lib/features/member-model/switch.js:315
    const after = await readTailEvents(await readFile(filePath), { tailFrames: 3 });
  • 读取本地文件
    lib/features/member-model/switch.js:642
    const buf = await readFile(file);
  • 读取本地文件
    lib/features/member-model/clone-member.js:55
    const text = await decodeAllFrames(readFileSync(targetFile));
  • 读取本地文件
    lib/features/member-model/clone-member.js:65
    const text = await decodeAllFrames(readFileSync(sourceFile));
  • 写入本地文件
    lib/features/member-model/clone-member.js:128
    copyFileSync(targetFile, backup);
  • 写入本地文件
    lib/features/member-model/clone-member.js:133
    writeFileSync(tmp, encoded, { mode: 0o600 });
  • 写入本地文件
    lib/features/member-model/clone-member.js:134
    renameSync(tmp, targetFile);
  • 读取本地文件
    lib/features/member-model/clone-member.js:136
    return { ok: true, events: sourceEvents.length, backup, size: statSync(targetFile).size };
  • 读取本地文件
    lib/zstd-frames.js:152
    const origBuf = readFileSync(path);
  • 写入本地文件
    lib/zstd-frames.js:185
    mkdirSync(backupDir, { recursive: true });
  • 写入本地文件
    lib/zstd-frames.js:236
    mkdirSync(backupDir, { recursive: true });
  • 读取本地文件
    lib/zstd-frames.js:262
    if (!sessionsRoot || !existsSync(sessionsRoot)) return { ok: true, corrupt: [], healthy: 0, total: 0, error: 'sessions 目录不存在' };
  • 读取本地文件
    lib/zstd-frames.js:265
    for (const proj of readdirSync(sessionsRoot)) {
  • 读取本地文件
    lib/zstd-frames.js:267
    if (!statSync(pp).isDirectory()) continue;
  • 读取本地文件
    lib/zstd-frames.js:268
    for (const sess of readdirSync(pp)) {
  • 读取本地文件
    lib/zstd-frames.js:273
    const r = await validateHeaderFrame(readFileSync(f));
  • 读取本地文件
    lib/sessions/log-stream.js:67
    return await streamSessionEvents(await readFile(file), onEvent);
  • 读取本地文件
    lib/session-log.js:24
    if (existsSync(p)) return p;
  • 读取本地文件
    lib/session-log.js:28
    const hit = readdirSync(sessionDir)
  • 读取本地文件
    lib/sessions/resolve.js:29
    try { return (await stat(p)).isDirectory(); } catch { return false; }
  • 读取本地文件
    lib/sessions/resolve.js:32
    for (const group of await readdir(root)) {
  • 读取本地文件
    lib/sessions/resolve.js:35
    for (const dir of await readdir(groupPath)) {
  • 写入本地文件
    lib/shared/json-store.js:22
    mkdirSync(path.dirname(file), { recursive: true });
  • 写入本地文件
    lib/shared/json-store.js:24
    writeFileSync(tmpPath, JSON.stringify(data), "utf8");
  • 写入本地文件
    lib/shared/json-store.js:25
    renameSync(tmpPath, file);
  • 写入本地文件
    lib/shared/json-store.js:30
    await mkdir(path.dirname(file), { recursive: true });
  • 写入本地文件
    lib/shared/json-store.js:32
    await writeFile(tmpPath, JSON.stringify(data), "utf8");
  • 写入本地文件
    lib/shared/json-store.js:33
    await rename(tmpPath, file);
  • 读取本地文件
    lib/shared/json-store.js:39
    const parsed = JSON.parse(readFileSync(file, "utf8"));
  • 读取本地文件
    lib/shared/json-store.js:49
    const parsed = JSON.parse(await readFile(file, "utf8"));
  • 读取本地文件
    lib/sessions/export-restore.js:97
    if (!existsSync(exportDir)) return { entries: [], error: `导出目录不存在:${exportDir}` };
  • 读取本地文件
    lib/sessions/export-restore.js:105
    const firstLine = readFileSync(plainPath, 'utf8').split('\n', 1)[0];
  • 读取本地文件
    lib/sessions/export-restore.js:115
    if (existsSync(parentPlain)) {
  • 读取本地文件
    lib/sessions/export-restore.js:134
    if (existsSync(subsDir)) {
  • 读取本地文件
    lib/sessions/export-restore.js:135
    for (const name of readdirSync(subsDir)) {
  • 读取本地文件
    lib/sessions/export-restore.js:137
    if (!existsSync(plainPath)) continue;
  • 写入本地文件
    lib/sessions/export-restore.js:218
    mkdirSync(join(objRoot, hash.slice(0, 2)), { recursive: true, mode: 0o700 });
  • 写入本地文件
    lib/sessions/export-restore.js:219
    writeFileSync(target, buf, { mode: 0o600 });
  • 删除本地文件
    lib/sessions/export-restore.js:253
    unlinkSync(cacheFile);
  • 写入本地文件
    lib/sessions/export-restore.js:338
    mkdirSync(entry.targetDir, { recursive: true, mode: 0o700 });
  • 写入本地文件
    lib/sessions/export-restore.js:343
    writeFileSync(tmp, encoded.buffer, { mode: 0o600 });
  • 写入本地文件
    lib/sessions/export-restore.js:344
    renameSync(tmp, target);
  • 读取本地文件
    lib/sessions/member-trace.js:117
    const buf = await readFile(file);
  • 读取本地文件
    build.cjs:95
    src += fs.readFileSync(path.join(partsDir, name), "utf8");
  • 读取本地文件
    build.cjs:103
    const cur = fs.existsSync(clientPath) ? fs.readFileSync(clientPath, "utf8") : "";
  • 写入本地文件
    build.cjs:112
    fs.writeFileSync(clientPath, src);
  • 读取本地文件
    lib/eio-repair.js:42
    const size = statSync(filePath).size;
  • 读取本地文件
    lib/eio-repair.js:72
    if (!sessionsRoot || !existsSync(sessionsRoot)) {
  • 读取本地文件
    lib/eio-repair.js:77
    for (const proj of readdirSync(sessionsRoot)) {
  • 读取本地文件
    lib/eio-repair.js:79
    if (!statSync(pp).isDirectory()) continue;
  • 读取本地文件
    lib/eio-repair.js:80
    for (const sess of readdirSync(pp)) {
  • 写入本地文件
    lib/eio-repair.js:126
    mkdirSync(bk, { recursive: true });
  • 写入本地文件
    lib/eio-repair.js:129
    copyFileSync(filePath, backup, fs.constants.COPYFILE_EXCL);
  • 写入本地文件
    lib/eio-repair.js:157
    renameSync(eioTmpPath, filePath);
  • 读取本地文件
    lib/repair.js:306
    try { return existsSync(sessionsRootOf()); } catch { return false; }
  • 读取本地文件
    lib/repair.js:377
    if (!root || !existsSync(root)) return { ...report, error: `sessions 目录不存在: ${root}` };
  • 读取本地文件
    lib/repair.js:378
    for (const proj of readdirSync(root)) {
  • 读取本地文件
    lib/repair.js:381
    try { st = statSync(projectDir); } catch { continue; }
  • 读取本地文件
    lib/repair.js:384
    try { sessions = readdirSync(projectDir); } catch { continue; }
  • 读取本地文件
    lib/repair.js:388
    try { sst = statSync(sessionDir); } catch { continue; }
  • 写入本地文件
    lib/repair.js:429
    mkdirSync(backupDir, { recursive: true });
  • 写入本地文件
    lib/repair.js:445
    renameSync(join(entry.dir, "session.jsonl"), target);
  • 读取本地文件
    lib/seq-gap-repair.js:27
    const orig = await readFile(path);
  • 写入本地文件
    lib/seq-gap-repair.js:188
    mkdirSync(bakDir, { recursive: true });
  • 写入本地文件
    lib/seq-gap-repair.js:190
    writeFileSync(bakPath, orig);
  • 读取本地文件
    lib/sessions/tail-io.js:100
    buf = await readFile(filePath);
扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

DSH 会话功能增强插件(重命名/分支/归档)

README

由 DeepSeek 最新模型翻译生成
dsh-session-conductor DSH 会话管理增强插件:面板管理会话、批量删除与回收站、损坏修复、自动续跑、模板注入,以及成员(子代理)的模型/权限/换名管理。 功能 | 功能 | 做什么 | 入口 | | 会话管理面板 | 五视图(全部/已归档/活跃/回收站/说明);归档、删除、撤回、置不活跃、释放空闲 | 侧边栏「会话管理」 | | 回收站 | 删除只打标记,可单条/多选/按批次还原;到期或一键清空才真删盘 | 面板「回收站」 | | 自动重命名 | 回合后分析内容,主题偏离时生成新标题 | 面板逐会话开关 | | 自动续跑 | 识别非人为中断并继续原任务,失败 30s 重试 | 面板逐会话开关 | | 会话分组 | 按工作区分组显示;分组下新建会话 | 设置 → 插件 → 会话分组 | | 撤回最后一条消息 | 删除最后一条用户消息及整轮回复(预览 + 二次确认 + 备份) | 面板按钮 | | 损坏修复 | seq-gap / EIO 坏块 / 双格式 / zstd 帧级损坏 四类 | 面板「说明」页 + /repair 系列 | | 价值分析 | LLM 给会话分类(已完成/未完成/久未活跃/活跃中) | 面板按钮 | | 全文搜索 | FTS5 优先,内置 zstd 扫描兜底 | 面板搜索框 |
展开完整文档(README 剩余 1 节)
dsh-session-conductor

DSH 会话管理增强插件:面板管理会话、批量删除与回收站、损坏修复、自动续跑、模板注入,以及成员(子代理)的模型/权限/换名管理。

功能

| 功能 | 做什么 | 入口 |
| 会话管理面板 | 五视图(全部/已归档/活跃/回收站/说明);归档、删除、撤回、置不活跃、释放空闲 | 侧边栏「会话管理」 |
| 回收站 | 删除只打标记,可单条/多选/按批次还原;到期或一键清空才真删盘 | 面板「回收站」 |
| 自动重命名 | 回合后分析内容,主题偏离时生成新标题 | 面板逐会话开关 |
| 自动续跑 | 识别非人为中断并继续原任务,失败 30s 重试 | 面板逐会话开关 |
| 会话分组 | 按工作区分组显示;分组下新建会话 | 设置 → 插件 → 会话分组 |
| 撤回最后一条消息 | 删除最后一条用户消息及整轮回复(预览 + 二次确认 + 备份) | 面板按钮 |
| 损坏修复 | seq-gap / EIO 坏块 / 双格式 / zstd 帧级损坏 四类 | 面板「说明」页 + /repair 系列 |
| 价值分析 | LLM 给会话分类(已完成/未完成/久未活跃/活跃中) | 面板按钮 |
| 全文搜索 | FTS5 优先,内置 zstd 扫描兜底 | 面板搜索框 |
| 压缩模型 | 上下文自动压缩使用独立模型 | 设置 → 插件 → 压缩模型 |
| 模板注入 | 方案/收尾模板;本地文件、在线网址、目录浏览三种导入 | 设置 → 会话管理 |
| 自动重命名模型 | 指定标题分析用的模型 | 设置 → 会话管理 |
| 成员模型切换 | 切单个或全部成员的模型,可跟随主代理 | /model-switch、set_member_model |
| 成员权限预设 | 查看/切换成员权限预设,支持批量与跟随 | /perm-switch、set_member_permission |
| 成员换名 | 新建成员并把原会话内容搬进去 | clone_member_as |
| 创建成员并选模型 | 创建时即指定模型,首轮就用它 | create_teammate_with_model |
| 指定模型新建会话 | 新建会话并直接指定 provider/model | create_session |
| 记忆取回 | 上下文用量骤降时自动回注最近几轮对话 | 自动注入 + recall_memory |
| 上下文用量 | 查自己会话的占用与构成 | context_usage |
| 跨会话消息 | 给另一个会话发消息,空闲时自动唤醒 | list_sessions、send_to_session |
| 成员轨迹 | 读子代理的完整执行过程:思考、正文、工具调用与结果 | read_member_trace |

环境要求

| 项 | 要求 |
| DSH | 0.2.1 及以上(更早版本功能可用,但列表缓存不生效,会话多时列表构建变慢) |
| Node | 与宿主自带的 Node 一致 |
| 平台 | Linux(群晖 DSM / fnOS 等);纯 Node 实现,无原生依赖 |

用法

面板与设置页

- 面板:侧边栏底部「会话管理」展开。五个视图分别是全部、已归档、活跃、回收站、说明。
行内可归档、删除、撤回最后一条消息、开关自动重命名/自动续跑;顶部可搜索、价值分析、释放全部空闲。
- 设置页:左侧栏「会话管理」独立页。模板注入(方案/收尾两个槽位,可上传本地 md、填在线网址、浏览 DSH 目录导入,导入后可再编辑)与自动重命名模型选择。

聊天框指令

/model-switch —— 查看/切换成员模型:

/model-switch # 无参:列出成员与各自模型 /model-switch writer # 只给成员:查它实际在用的模型 /model-switch writer sa6400/deepseek-v4.1-flash # 成员 + 模型:切换 /model-switch * auto # 成员写 * = 全部;模型写 auto = 跟随我

/perm-switch —— 查看/切换成员权限预设:

/perm-switch # 无参:列出成员与各自预设 /perm-switch writer # 只给成员:查 preset / sandbox / approval /perm-switch writer danger-full-access # 成员 + 预设:切换 /perm-switch * auto # 成员写 * = 全部;预设写 auto = 跟随我

两条指令都支持:成员位置可填成员名、唯一子串或 sessionId; 表示全部成员(不含自己); auto 表示跟随主代理当前值。切换后回执会带上「实际生效」的查证结果。

AI 工具

list_models({}) // 列出可用 provider 与模型 id
set_member_model({ target, provider, model }) // 三者都可空:target 空=全部成员;provider/model 空=跟随我
set_member_permission({ target, preset }) // 两者都可空:target 空=全部成员;preset 空=跟随我
list_permission_presets({}) // 列出可选权限预设
clone_member_as({ source, name, description, withHistory, provider, model, subagentProvider })
// source/name 必填;withHistory 默认 true(false=只建空成员)
create_teammate_with_model({ name, description, prompt, provider, model, subagentProvider, context })
// name/description/prompt/provider/model 必填
create_session({ cwd, workspaceId, provider, model, text, dryRun, sessionId })
// 全可空:cwd 缺省=调用方 cwd;dryRun=true 只预览
list_sessions({ query, limit, offset, fromIndex }) // 全可空:fromIndex=true 直接读索引(秒回)
send_to_session({ sessionId, text, mode, dryRun }) // sessionId/text 必填;mode=queue|steer
recall_memory({ rounds, session }) // 都可空:rounds 默认取配置、上限 50;session 空=自己
context_usage({}) // 无参
read_member_trace({ session, rounds, detail, include, maxCharsPerItem })
// session 空=自己(可填成员名/id/前缀/标题);rounds 默认 1(上限 20) // detail=summary(每条一行)|full(完整文本);include 可裁 reasoning,text,tool // maxCharsPerItem 单条截断(默认 800)

典型调用:

// 全部子代理都换成我现在用的模型
set_member_model({})

// 只把 writer 切到指定模型
set_member_model({ target: "writer", provider: "sa6400", model: "cn:deepseek-v4.1-flash" })

// 把 probe1 克隆成 rename1(换名用)
clone_member_as({ source: "probe1", name: "rename1" })

// 给另一个会话发消息(dryRun 先预览目标状态与限流余量)
send_to_session({ sessionId: "session-xxxx", text: "继续刚才的任务", dryRun: true })

// 看子代理最近一轮的执行过程(子代理只有最后一条回复会被自动发回,中间的思考靠这里读)
read_member_trace({ session: "writer" })

// 看最近 3 轮,只要思考与工具调用
read_member_trace({ session: "writer", rounds: 3, include: "reasoning,tool" })

// 要完整文本(默认 summary 每条压成一行)
read_member_trace({ session: "writer", detail: "full" })

API

插件以 /api/session-conductor/ 前缀注册宿主路由:

| 端点 | 方法 | 用途 |
| /list | GET | 会话列表;?fromIndex=true 读落盘索引秒回,?job=1 交给后台 job |
| /archive /restore | POST | 归档 / 恢复会话 |
| /delete | POST | 删除会话(拒绝运行中) |
| /undo | POST | 撤回最后一条消息 |
| /auto-rename /auto-continue | POST | 两个逐会话开关 |
| /auto-continue-gate | GET/POST | 全局续跑闸门 |
| /release | POST | 释放空闲会话 |
| /value-analysis | POST | 价值分析 |
| /repair /repair-eio /repair-dual | POST | 三类损坏修复 |
| /search | GET | 全文搜索 |
| /compaction-model /auto-rename-model | GET/POST | 两个模型设置 |
| /templates /templates/dir | GET/POST | 模板注入与目录浏览 |
| /i18n | GET | 语言包(zh/en) |

curl http://<host>/api/session-conductor/list
→ { "ok": true, "sessions": [ { "id": "...", "title": "...", "cwd": "...", "updatedAt": 172... } ], "total": N }

curl -X POST http://<host>/api/session-conductor/archive \
-H "Content-Type: application/json" -d '{"id":"<sessionId>"}'
→ { "ok": true, "archived": true }

文档索引

- 文件目录结构 — 目录树与文件作用
- 版本列表 — 按 git 提交聚合的版本记录
- 函数列表 — lib/ 导出函数的名称/位置/签名
- 模型与权限切换机制 — 子代理切换的实现依据与内部机制
预览分享卡片长什么样 ↓EIGHTfs/dsh-session-conductor
分享 · DeepSeek Harness Hub
EIGHTfs/dsh-session-conductor

集中管理会话,支持归档、回收站与自动续跑

回到顶部