dsh-plugins/sessions

44Star4Fork1Issue0Watching

为 DeepSeek Harness 增加会话管理工具与侧边聊天:列出/读取/创建/发送会话,并能开一个挂载在主会话旁、保持可继续对话的子会话面板。

语言
Python
License
MIT
分支
main
dsh-plugindsh-plugin-marketdsh-plugins

安装

$ dsh plugin --profile web add github:Ephemeral-AI-Lab/dsh-plugins/sessions

在终端中运行以上命令,通过 dsh CLI 安装此插件。可在右上角切换 Profile。 第一次用 dsh?看这篇新手教程

落地页对应的仓库子路径是 sessions,仓库中的承载目录也叫 sessions,npm 包名 dsh-sessionspackage.json:3),是 Ephemeral-AI-Lab/dsh-plugins monorepo 下的子包之一。本百科聚焦 sessions 路径对应的能力。

一句话定位

为 DeepSeek Harness 增加"会话管理"与"侧边聊天"能力:让 agent 和用户能够列出历史会话、按窗口读取对话内容、创建新会话、把消息投给已有会话(steer 或 followup),以及在不离开主会话的情况下开一个挂载在旁的、可继续对话的子会话面板。

核心能力

  • 列出最近会话或查看单个会话状态:session_status({ session_id?, recent_n? }) 默认按最近更新时间倒序返回 50 条,状态分 running / idle / cold / missing(src/service.ts:22-60SPEC §2 session_status)。
  • 按窗口读取会话历史:session_read({ session_id, offset?, limit? }) 只读、不恢复、不重启生成,跳过 token 流、生命周期事件等 trace-only 数据(src/service.ts:85-102)。
  • 创建新会话并排队初始 prompt:session_create({ prompt, preset?, model?, cwd? }) 返回新 session_id 和 status: "queued",不等待生成结束(src/creation-service.ts:26-68)。
  • 向已有会话投递消息:session_send({ session_id, message, mode? }) 支持 steer(唤醒/插入下一个步骤)和 followup(排队成下一轮),冷会话会被本插件恢复后投消息(src/send-service.ts:18-61)。
  • 开启一个真实可继续的子会话:session_open_sidechat({ prompt }) 返回 subagent_id(不是另造的 ID),复用 DSH 现有的 send_message 继续对话(src/sidechat/sidechat-service.ts:29-49SIDE_CHAT_SPEC §2)。
  • 等价的用户命令 /sessions 加 Web 可视化:命令覆盖 status / read / create / send / sidechat 五个动作(/sessions create 支持 --preset/--provider/--model/--effort/--cwd 与 JSON 两种形式,src/commands.ts:11,72-118,212-325);Web 端把侧边聊天渲染成标签化、状态/常驻分离、关闭再打开恢复标签的独立 panel,并把 /sessions 命令结果以浮层 popup 形式呈现(src/ui/SideChatPanel.tsxsrc/ui/index.ts:42-91)。

技术实现

  • 语言: TypeScript(tsc -p tsconfig.json 编译到 lib/package.json:11 声明 "type": "module"
  • 关键依赖:
    • @deepseek-ai/cordis(>=4.0.0):宿主插件框架,apply(ctx) 走标准 Cordis effect
    • @deepseek-ai/dsh-tools / @deepseek-ai/dsh-commands:用 defineTool 注册五个工具、用 ctx.commands.register 注册 /sessions 命令
    • @deepseek-ai/dsh-agent + @deepseek-ai/dsh-subagent + @deepseek-ai/dsh-session-persistence + @deepseek-ai/dsh-session-query + @deepseek-ai/dsh-workspace + @deepseek-ai/dsh-llm:分别负责创建/恢复 Agent、subagent 启动、会话存储/恢复、标题快照、workspace 解析、消息构造
    • @deepseek-ai/dsh-client-ui-* + @deepseek-ai/dsh-client-runtime + react(>=18.2.0):Web 端把侧边聊天 panel 注入 shell.overlay 槽位、命令结果浮层注入 conversation.input.overlay 槽位
  • 架构模式: 双端 Cordis 插件。Server 端 apply(ctx)sessions/src/index.ts:15-29 注入 tools / commands / agents / subagents / llm / sessionPersistence / sessionQuery / workspaceRegistry 八个服务,组合四个 Service(SessionsServiceSessionCreationServiceSessionSendServiceSideChatService)并通过 registerSessionTools + registerSessionsCommand 暴露能力;Client 端 apply(ctx)src/ui/index.ts:18-102 监听 command/executed 事件、把侧边聊天注入 shell.overlay 槽位、把 /sessions 命令的瞬态结果用 conversation.input.overlay 槽位渲染成浮层 popup。cordis.patch.yml 给宿主注入一个名为 dsh-sessions 的 bundle patch,让宿主在加载时挂载这个插件。
  • 入口文件: sessions/src/index.ts(服务端)+ sessions/src/ui/index.ts(客户端),均通过 package.json#dsh 字段 bundle.patch + client.inject 注入 DSH。

适用场景

当用户希望 agent 把"管多个会话"这件事做得正式一些——比如在长项目里随时跳回 3 天前的会话读上下文、临时拉一个并行 agent 出去查资料而不打断当前主任务、在不离开当前聊天窗口的情况下并排看两个子任务的进度——这个插件提供标准化的工具/命令和 Web 面板,让"会话列表、读取、创建、发送、并行子会话"成为 agent 可以直接调用的能力。

前置依赖与兼容性

依赖最低版本说明
@deepseek-ai/dsh-tools>=0.1.0-rc.5peerDependencies,注册五个 agent 工具依赖
@deepseek-ai/dsh-commands>=0.1.0-rc.5peerDependencies,注册 /sessions 命令依赖
@deepseek-ai/dsh-agent>=0.1.0-rc.5peerDependencies,SessionCreationService / SessionSendService 直接持有 Agent
@deepseek-ai/dsh-subagent>=0.1.0-rc.7peerDependencies,侧边聊天走 ctx.subagents.startContinuable
@deepseek-ai/dsh-session-persistence>=0.1.0-rc.5peerDependencies,session_status 列举冷会话、session_send 恢复冷会话都依赖
@deepseek-ai/dsh-session-query>=0.1.0-rc.5peerDependencies,标题快照通过 readTitleSnapshots
@deepseek-ai/dsh-workspace>=0.1.0-rc.7peerDependencies,cwd 通过 workspaceRegistry.resolveByPath 解析
@deepseek-ai/dsh-agent-presets>=0.1.0-rc.7peerDependencies,session_create 解析 preset 依赖
@deepseek-ai/dsh-agent-default-model>=0.1.0-rc.7peerDependencies,根调用无显式 model 时回落部署默认依赖
@deepseek-ai/dsh-llm>=0.1.0-rc.5peerDependencies,createUserMessage + ReasoningEffortId 来源
@deepseek-ai/dsh-client-runtime + @deepseek-ai/dsh-client-ui-commands + @deepseek-ai/dsh-client-ui-conversation + @deepseek-ai/dsh-client-ui-primitives + @deepseek-ai/dsh-client-ui-tool + @deepseek-ai/dsh-client-ui-slots + @deepseek-ai/dsh-api-remotes + @deepseek-ai/dsh-client-connection>=0.1.0-rc.5peerDependencies,Web 端侧边聊天 panel 与浮层 popup 必需;package.json:19-26 列入 dsh.client.inject,缺一加载不到 Web UI
@deepseek-ai/cordis>=4.0.0peerDependencies,宿主插件框架
react>=18.2.0peerDependencies,侧边聊天 panel 是 React 组件
平台DSH Webpackage.json:27 显式声明 dsh.client.platform: "web",命令行/桌面端未声明
Node.js未声明package.json 没有 engines 字段;只有 devDependencies 里有 @types/node ^22.20.0
原生模块全部是纯 JS 依赖,无 node-gyp 构建项;插件本身只用到 node:crypto / node:fs/promises / node:path 这些 Node 内置模块

安装方式

dsh plugin --profile web add github:Ephemeral-AI-Lab/dsh-plugins/sessions

配置项

本插件无需额外配置。安装后重启 DSH 并新建会话即可使用,会话相关参数(prompt、session_id、cwd、model、preset、reasoningEffort、recent_n、offset、limit、mode、subagent_id 等)全部在运行时通过工具调用或 /sessions 命令传递,源码中无 .env / settings 配置文件读取逻辑(grep 全文未发现 process.env / config.get / Schema 等运行时配置入口)。

唯一会被校验的字段是工具/命令入参的硬约束:session_id/message/prompt/provider/model/preset/reasoningEffort/cwd 都必须是非空字符串、recent_n/offset/limit 必须是正整数、limit 上限 200(src/service.ts:16,134-151src/creation-service.ts:267-274src/sidechat/sidechat-service.ts:79-83),这些是入参校验,不算可配置项。

常见问题

Q: 装完之后怎么用?

A: 重启 DSH 并新建会话即可。Agent 可在自然语言里调用 session_status / session_read / session_create / session_send / session_open_sidechat 五个工具;用户也可直接在输入框打 /sessions status/sessions read <ID>/sessions create <prompt>/sessions send <ID> <msg>/sessions sidechat "PROMPT" 这几条命令,操作的是同一套后端(src/commands.ts:21-70)。无需新建 preset 或开关任何宿主配置。

Q: session_create 会等模型生成完才返回吗?

A: 不会。README §5SPEC §2 session_create 都明确说明它只创建新会话并把初始 prompt 投到收件箱就立即返回,返回的 status: "queued" 表示"已入队、未完成";想看生成结果请用 session_status 查当前状态,或 session_read 读窗口消息。followup() 在失败时会回滚 handle 并重新抛错(src/creation-service.ts:52-60),所以要么拿到 session_id 要么抛错,不会留下半成品。

Q: session_send 的 steer 和 followup 有什么区别?

A: steer(默认)会唤醒空闲 agent,并对运行中 agent 投到最近一个步骤边界;followup 则排队成普通的下一轮(src/send-service.ts:50-51SPEC §2 session_send)。两者都不会打断 agent 当前正在跑的步骤,返回的 message_id 只是收件箱里的接受凭证,不代表模型已处理完。

Q: 侧边聊天 / sessions sidechatsession_create 是一回事吗?

A: 不是。session_open_sidechat 走 Harness 自带的 continuable subagent 服务(ctx.subagents.startContinuablesrc/sidechat/sidechat-service.ts:33-49),返回的是真实可继续的 subagent_id,跟 list_agents({ scope: "children" }) 看到的子 agent 是同一套;session_create 返回的是新的顶层 session_id。侧边聊天在 Web 端有专门的标签化 panel(src/ui/SideChatPanel.tsx),关闭再打开标签保留,主会话不会被导航走;普通 session_create 出来的子会话没有这个 panel。

Q: 怎么选择 session_create 的模型或工作目录?

A: 在创建时显式传 model: { provider, model, reasoningEffort? }presetcwd 即可。模型解析顺序:显式 > 调用方 agent 路由 > 部署默认;preset 解析顺序:显式 > 调用方 preset > 部署默认;cwd 缺省时子会话继承调用方 cwd,根调用则不绑工作区(SPEC §2 session_create 的解析表)。cwd 必须是已存在的绝对目录,会被 realpath canonicalize,否则抛 cwd must be an absolute path / cwd 'X' is not a directorysrc/creation-service.ts:267-274)。

Q: session_read 能读整段历史吗?

A: 不能,是有界读取。limit 默认且上限 200 条 message block(src/service.ts:16 READ_SESSION_LIMIT = 200src/service.ts:144 校验),offset 是 1-based,超出会被 offset X is out of range 拒掉。读冷会话走 sessionPersistence.inspect 不恢复、不重启生成(src/service.ts:88-90);只投影会话规范消息块,跳过原始 stream chunk、token delta、lifecycle 等 trace-only 事件(src/service.ts:153-162SPEC §2 session_read)。

Q: 跟 dsh-loop 是什么关系?

A: 职责互补。dsh-sessions 拥有跨会话的发现/读取/创建/发送(SPEC §1);dsh-loop 拥有当前会话内的循环闹钟(详见 _wiki/Ephemeral-AI-Lab_dsh-plugins_loop.md)。dsh-loop 用本插件的会话列表能力填它面板上的"已有会话"选项(SPEC §5),两者不会重复实现同一份会话状态。

Q: 怎么卸载?

A: 用 dsh plugin --profile web remove 对应的安装源即可。卸载后这五个工具名(session_status / session_read / session_create / session_send / session_open_sidechat)和 /sessions 命令从新会话的工具表中消失(src/index.ts:23-28 提供的 dispose 会撤销注册);已创建/已发送的会话和侧边聊天仍保留在 DSH 会话存储里,不会被删除。

上手难度

入门 — 装好就能用,没有配置文件、没有原生模块、没有特殊 preset 要建;最快 30 秒就能在输入框打 /sessions status 看到最近会话列表,或 /sessions sidechat "帮我查一下" 开一个侧边聊天面板。

已知问题与限制

  • v1 没有"会话修改/删除/重命名"工具:session_status 是只读的,session_send 只投递消息,session_create 只创建新会话,没有提供 delete / rename / archive 这一类操作(README §5SPEC §1 把"create + send + inspect"明确列为职责边界)。
  • session_create 不等待模型生成结束:返回 status: "queued" 后调用方需要自己用 session_status 轮询或 session_read 拉窗口(README §5 / SPEC §2 session_create);想在同一次工具调用里拿到完整回复做不到。
  • session_send 不会创建新会话:传入一个不存在的 session_id 会抛 missing,不会自动建(SPEC §2 session_send);冷会话会被本插件恢复(src/send-service.ts:30-42),但不会补建不存在的会话。
  • session_read 窗口上限 200:limit 超过 READ_SESSION_LIMIT = 200 直接抛 limit must be less than or equal to 200src/service.ts:144),要分段读只能多次调用。
  • session_open_sidechat 必须有 calling agent:在没有当前 agent 的工具调用上下文里会抛 session_open_sidechat requires a calling agentsrc/sidechat/sidechat-service.ts:31);这是因为它要复用 subagent 框架的 parent 关系。
  • 侧边聊天仅 Web 端可见:底层 session_open_sidechat 工具在命令端也能跑,但没有 panel,只返回 JSON;UI 端的标签化和状态/常驻分离体验是 DSH Web 专属(src/ui/SideChatPanel.tsxpackage.json:27 dsh.client.platform: "web")。
  • 命令行/桌面端是否可用未声明:package.json:27 只声明 dsh.client.platform: "web",CLI / TUI / Desktop bundle 是否会自动挂载这个插件源码中未明确(同样适用于 dsh-loop,见 _wiki/..._loop.md 的同条限制)。
  • 不修改 DeepSeek Harness 宿主代码,全部走 Cordis effect 和 DSH 公共 API(README §5 / SPEC §1);这意味着宿主一旦变更 dsh-session / dsh-subagent / dsh-llm 等公开 API 形状,插件需要同步升级 peerDependencies(当前要求 dsh-agent-presets / dsh-agent-default-model / dsh-workspace / dsh-subagent>=0.1.0-rc.7)。
  • 侧边聊天 subagent_idsession_id 是同一类 ID:它是真实 child Session ID,跟 list_agents({ scope: "children" }) 列出来的一致(SIDE_CHAT_SPEC §2),但也意味着 session_send({ session_id: <subagent_id>, message }) 走的是普通会话投递而不是 subagent 的 send_message,如果你想用 send_message 的"按 subagent ID 投递"语义需要直接调宿主工具,不要被本插件的 session_send 替代(README §6 明确警告)。