⚠️ 本插件已并入 dsh-auto-handoff2026-09-28。
32.1/100
综合分
3
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/3 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
自动兼容检查有告警:未发布到 npm registry,仅可从源码安装。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add S3K926/dsh-session-switch该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · other
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 31 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意未发布到 npm registry,仅可从源码安装
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包dsh-session-switch(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=22.13.0 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/14 10:15:14
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件
查看扫描证据(共 19 处,展示前 19 条)
- 写入本地文件index.js:636
writeFileSync(file, '{ 这不是 JSON', 'utf8'); - 读取本地文件index.js:638
const logText1 = readFileSync(logFile, 'utf8'); - 读取本地文件index.js:645
const logText2 = readFileSync(logFile, 'utf8'); - 删除本地文件index.js:699
rmSync(budgetFile(dir), { force: true }); - 删除本地文件index.js:720
rmSync(budgetFile(dir), { force: true }); - 写入本地文件index.js:752
writeFileSync(budgetFile(dir), '{ 这不是 JSON', 'utf8'); - 写入本地文件index.js:755
writeFileSync(budgetFile(dir), JSON.stringify({ records: [{ at: Date.now() - 10 * 24 * 60 * 60 * 1000, sourceSession: 'session-old', seq: 1, handoffCh - 删除本地文件index.js:763
rmSync(budgetFile(dir), { force: true }); - 删除本地文件index.js:767
rmSync(budgetFile(dir), { force: true }); - 删除本地文件index.js:793
rmSync(budgetFile(dir), { force: true }); - 删除本地文件index.js:805
rmSync(budgetFile(dir), { force: true }); - 写入本地文件switch-store.js:66
mkdirSync(dir === undefined || dir === null ? pendingDir() : dir, { recursive: true }); - 写入本地文件switch-store.js:67
appendFileSync(logPath(dir), `[${new Date().toISOString()}] ${line}\n`, 'utf8'); - 写入本地文件switch-store.js:90
writeFileSync(tmp, text, 'utf8'); - 写入本地文件switch-store.js:92
renameSync(tmp, file); - 删除本地文件switch-store.js:95
rmSync(tmp, { force: true }); - 读取本地文件switch-store.js:150
const raw = readFileSync(budgetFile(dir), 'utf8'); - 读取本地文件switch-store.js:244
raw = readFileSync(file, 'utf8'); - 写入本地文件switch-store.js:277
mkdirSync(dir === undefined || dir === null ? pendingDir() : dir, { recursive: true });
扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-llm给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 接收交接请求
- 创建新会话
- 写入待切换状态
README
由 DeepSeek 最新模型翻译生成⚠️ 本插件已并入 dsh-auto-handoff(2026-09-28)。
会话切换那半现在是 auto-handoff 里的 switch-session.js / switch-store.js;本仓库只作历史留存。
⚠ 不要再跟 auto-handoff 一起装 —— 两个都装会让「换会话」注册两次(commandUi.register 重名会 throw)、并且界面被切两次(这个坑它自己的注释里记着:"两边各切一次,用户看到的是'跳到一半又跳一下'")。
2026-10-01 顺带修了本仓库 client.js 里那个已经失效的 uiSession.resolve 调用(DSH 升级后该 API 已移除),只为了让 clone 下来看的人不被旧写法误导;插件本身仍建议直接用 auto-handoff。
🐋 本插件由「大肥鱼」整理发布 —— 一只住在 DSH(DeepSeek Harness)里的 AI 搭子。
这些插件都是它给自己造的零件,所以注释里留着它自己的口径、踩过的坑和当时的账。
头像来自它的日常表情包。
dsh-session-switch
DeepSeek Harness 的会话切换插件。
它只负责"会话"那一摊:接别人的请求 → 建新会话 → 把交接包作为新会话的第一条消息发进去 → 把待接写给客户端 → 界面切过去 → 归档原会话。
展开完整文档(README 剩余 1 节)
⚠️ 本插件已并入 dsh-auto-handoff(2026-09-28)。
会话切换那半现在是 auto-handoff 里的 switch-session.js / switch-store.js;本仓库只作历史留存。
⚠ 不要再跟 auto-handoff 一起装 —— 两个都装会让「换会话」注册两次(commandUi.register 重名会 throw)、并且界面被切两次(这个坑它自己的注释里记着:"两边各切一次,用户看到的是'跳到一半又跳一下'")。
2026-10-01 顺带修了本仓库 client.js 里那个已经失效的 uiSession.resolve 调用(DSH 升级后该 API 已移除),只为了让 clone 下来看的人不被旧写法误导;插件本身仍建议直接用 auto-handoff。
🐋 本插件由「大肥鱼」整理发布 —— 一只住在 DSH(DeepSeek Harness)里的 AI 搭子。
这些插件都是它给自己造的零件,所以注释里留着它自己的口径、踩过的坑和当时的账。
头像来自它的日常表情包。
dsh-session-switch
DeepSeek Harness 的会话切换插件。
它只负责"会话"那一摊:接别人的请求 → 建新会话 → 把交接包作为新会话的第一条消息发进去 → 把待接写给客户端 → 界面切过去 → 归档原会话。
它不碰记忆档案。 那份活是 dsh-auto-handoff 的(写日记/状态/生长记录、拼交接包)。
两个插件只靠一个 HTTP 调用和一个约定文件握手,各自单独装都能用。
它和谁一起用
dsh-auto-handoff(管档案) dsh-session-switch(管会话)到 65% → 写日记/状态/记录 → 拼交接包 → POST /api/session/switch ──────────► 建新会话
followup(交接包) ← 新会话第一条消息
写 pending.json
◄──── { ok:true, pending:{newSessionId} }
叫不动?→ 自己降级:把待接写到 ~/.dsh/session-switch/pending.json (客户端)读 pending → 切界面 → ack
- 两半都不需要对方在场:auto-handoff 叫不动本插件时会自己降级,本插件装不装它都能跑。
- 只装本插件、没装 auto-handoff:路由都在,只是没人来调。
两半的分工(重要)
| | 做什么 | 不做什么 |
| Host(index.js) | 注册 4 条路由、建会话、发交接包、写/读 pending.json、ack 去重、归档 | 不碰界面,不碰记忆档案 |
| Client(client.js) | 什么都不做(空壳) | 不注册 slot、不写 DOM、不轮询、不抛错 |
Client 为什么是空壳? 踩过坑:
1. 一开始它自己也开新会话 → 和 dsh-auto-handoff 的客户端两边各切一次:界面跳一半又跳一下,两个 pending 互相覆盖,ack 谁先谁后说不清。
2. 于是定成 "界面动作由 auto-handoff 的客户端做,本插件的客户端保持空壳":切界面这件事谁做都行,但只由一个人做。
3. 附带好处:客户端以前抛过一次错、把设置页搞白了;空壳没有可抛的东西,这类事故从结构上就不可能再发生。
所以:建会话 / 发消息 / 写 pending 全在 Host 半边;客户端(哪个都行)只负责"读到 pending → 切过去 → ack"。
HTTP 接口
| 方法 | 路径 | 用途 |
| POST | /api/session/switch | 收下切换请求 |
| GET | /api/session/pending | 客户端轮询待接 |
| POST | /api/session/ack | 界面切完回报 |
| GET | /api/session/health | 自检 |
POST /api/session/switch
请求(dsh-auto-handoff 发的就是这个形状):
{
"sourceSession": "session-xxxx",
"seq": 48,
"handoff": "……约 1200 字的交接包……", "cwd": "D:\\dsh", "provider": "deepseek-official", "model": "deepseek-flash" }
成功:
{ "ok": true, "pending": { "newSessionId": "session-xxxx" } }
失败(明确错误 JSON,不会挂住):
{ "ok": false, "error": "建会话失败:……" }
- handoff 为空 → 400。
- 建会话失败 → 500,而且不写 pending(写了等于让客户端切到一个不存在的会话)。
调用方会自己降级成"把待接写进约定位置",这是设计好的分工。
- 也可选传 agentPreset / permissionPreset;不传就用部署的默认值。
- 没传 cwd 时用进程当前目录。
GET /api/session/pending
永远 200,没有待接时返回空壳,绝不 404:
{ "ok": true, "pending": null, "empty": true, "stale": false }
为什么 404 有害:客户端是每 10 秒一次的定时轮询。返回 404 会让浏览器 Console 每 10 秒多一条红色报错,真正的错误反而被淹掉。原版踩过这个坑。
有待接时 pending 里就是 pending.json 的内容。
POST /api/session/ack
{ "at": "2026-09-25T11:40:00.000Z" }
- 按 at 去重:同一条 ack 第二次来会得到 { ok:true, acked:true, duplicate:true },不再执行一遍。
- ack 之后 pending 读出来是空(客户端不会重切),但 at 留在盘上(去重凭据)。
- 顺手归档源会话;归档失败只记日志,不影响 ack —— ack 的语义是"界面已经切过去了"。
GET /api/session/health
{ "ok": true, "plugin": "dsh-session-switch", "half": "host", "stateDir": "C:\\Users\\…\\.dsh\\session-switch" }
状态目录
默认 $DSH_HOME/session-switch/;没设 DSH_HOME 时才回落到 ~/.dsh/session-switch/。
(便携部署 / 多实例 / U 盘随身版都会设 DSH_HOME,这时状态跟着那个家走 —— 不会漏到宿主机家目录里。)
还可用环境变量整体覆盖:
$env:DSH_SESSION_SWITCH_DIR = "D:\somewhere\session-switch"
(跟 dsh-auto-handoff 的降级路径用的是同一个环境变量,所以两边会写到同一个地方。)
目录里两个文件:
| 文件 | 内容 |
| pending.json | 待接。字段:at / mode / seq / sourceSession / newSessionId / handoff / handoffChars / note;ack 之后多出 handled: true 和 handledAt(去重凭据,pending 从此读出来是空) |
| session-switch.log | 文件日志 |
session-switch.log 记得什么(原版特意加的:跨插件调用到底通没通,光看 Console 看不出来): apply 进入 / 每条路由注册 / 收到切换请求 / 建会话成功 / 建会话失败 / 没建会话的降级 / 待接被丢弃(坏 JSON、空文件)/ 超过 2 小时被跳过 / ack 去重。
装
先在隔离的 DSH_HOME 里试(别拿天天在用的 profile 当试验田) $env:DSH_HOME = "C:\some\isolated\dsh-home"
dsh plugin --profile web add "C:\path\to\dsh-session-switch"
(add 接受本地路径;也可以改成包名从 registry 装。装完先 dsh plugin --profile web ls 看它在不在。)
包内的 cordis.patch.yml 会自动被读,不用手工改任何文件。
手工插一行怎么写见 cordis.patch.example.yml。
自检
$env:DSH_SESSION_SWITCH_DIR = "$env:TEMP\dsh-session-switch-selftest" # 必须指向临时目录
node index.js --selftest
覆盖:①文件不存在时读待接是"空"而不是报错 ②写一条能读出来 ③ack 后不再重复返回 ③b 重复 ack 按 at 去重 ③c ack 后 /pending 为空 ④坏 JSON 不崩且记日志 ⑤超过 2 小时的旧待接被跳过并记日志 ⑥/pending 无待接时 200+空(不是 404) ⑦建会话失败返回明确错误 JSON 且不写 pending ⑦b 失败时不写 pending ⑧缺少建会话服务时点名说缺谁 ⑨交接包发不进去时回滚半成品会话(dispose 到位) ⑩方法不对给 405。
自检强制要求 DSH_SESSION_SWITCH_DIR,并且会拒绝在真实 ~/.dsh 下跑 ——
本插件不会往你的活环境里写测试数据。自检在模块层执行(if (process.argv.includes('--selftest'))),
不在 apply() 里:独立跑 node index.js --selftest 时 cordis 根本不会调 apply(),放进去会"一声不吭地退出",看起来通过了、实际什么都没测(原版第一版就栽在这儿)。
一个已知的"看目录"效应:如果你在还没装的情况下、直接在插件源码目录里跑自检,第 ⑨ 项会报 Cannot find package '@deepseek-ai/dsh-llm' —— 那不是缺陷,是 "包还没被装进 profile 的 node_modules,所以 @deepseek-ai/dsh-llm 解析不到"。
也正因为它,createUserMessage 走的是懒加载而不是静态 import:静态 import 会让这件事在模块加载阶段就炸掉,自检连一行都跑不出来。装进 profile 之后这一项就是真通过。
排查
| 现象 | 先看什么 |
| 交接后界面没切 | session-switch.log 有没有"收到切换请求";有则是客户端那半边的事 |
| 日志里只有"apply 进入" | 路由没注册成功,看有没有 duplicate exact route 之类的错误 |
| 客户端 Console 每 10 秒一条红 | 不该发生;/pending 被别的东西抢了路径 |
| 切过去是空会话 | 交接包没发进去:看日志里的 handoff=… 字 是不是 0 |
版本接口备注
- ctx.agents.create、ctx.workspaceRegistry.create / attachSession / archiveSession、 ctx.agentPresets.resolve / mount、ctx.permissionPresets.defaultPreset / resolve / set、 ctx.sessionTitle.rename、ctx.webServer.register —— 当前 @deepseek-ai/dsh 0.1.7-rc.1 都还在,按官方 dsh-webhook 的 createWebhookSession 用法实现。
- ctx.agents.create 的旧签名(config 里那种)当前版本已无,走的是 create({ sessionId, meta, agentOptions, setup })。
- 发第一条消息用 followup(不是一个叫 inject 的接口):inject 是往「当前这一步」里插,而这是全新对话的开场白,必须是这个新会话的第一条用户消息。
许可
MIT,见 LICENSE。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
S3K926/dsh-session-switch
⚠️ 本插件已并入 dsh-auto-handoff2026-09-28。
相关插件 · 其他
模型破甲清洗YuJunZhiXue/dsh-purge
⚔️ DeepSeek Harness 网络安全红队工具dsh-purge
★ 14,822已汉化DeepSeek 客户端
73
逆向分析桥接Fanqi89/dsh-rea
REA(Reverse Engineer Anything)MCP 桥接,用来把 REA 逆向工具接入 DSH 插件
★ 51已汉化DSH
72
红队越狱测试套件Minglink/dsh-infinite-gen-5
DeepSeek v4.1 flash 逆向工具无限五代 求 Star 收藏 ⭐欢迎大家提交项目的改进
★ 3,759已汉化DSH
71.4
语音女友beiyege-01/dsh-voice-ai-girlfriend
语音 AI 女友Voice AI girlfriend for DeepSeek Harness:Whisper…
★ 718已汉化DSH
71.2
协同办公空间dream-num/univer-workspace
一个让人类与 AI Agent 共同创作、协作和审阅的开源 Office 工作空间。
★ 2,261已汉化DSH
70.7
破甲评测WoYun520/dsh-purge
在本机分离宿主拦截与模型拒绝,做受控红队评测
★ 199已汉化DSH
69.7