dsh-cross-session-approval
Cross-session task delegation for DeepSeek Harness: spawn durable top-level sessions and send them tasks, read or steer them by base62 session alias, and approve their sandbox escalation requests through an approval bridge that refuses destructive deletes.
Install
dsh plugin --profile web add dsh-cross-session-approval
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✓ |
| 2 list | ✓ |
| 3 mount | ✓ |
| 4 boot | — |
Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
dsh-cross-session-approval(0.3.10)
DeepSeek Harness(DSH)0.2.x 的跨会话任务派发插件(bundle),提供 10 个工具:创建顶层持久会话、发送任务、回传结果、查询状态与消息、列出会话、批量投递、改名、归档及跨会话审批。
插件包含跨会话审批桥、子会话权限夹紧(A:发布前三维;F:派生入口),以及用于会话寻址的 cs_ base62 别名。创建任务后即可继续当前会话,任务结果通过回信返回。
派活登记保存在 <工作区>/.cross-session/registry.json,以临时文件加原子重命名写入。它包含任务正文和回复摘要,可能涉及敏感信息,应作为工作区本地数据保管。登记读取失败会阻止依赖该读取的操作;写入失败会告警,已完成的投递不会因此撤回。
安装与加载
需要 Node.js 18 或以上,以及已配置可用模型的 DeepSeek Harness 0.2.x profile。宿主 peer 依赖要求为 >=0.2.0-rc.2 <0.3.0;具体依赖见 package.json。本插件是宿主 bundle,不是独立运行的 MCP 服务。
以下以名为 dev 的 profile 为例;请替换为实际 profile 名。克隆需要具备该 GitHub 仓库的读取权限。
$profileName = 'dev' $profileDir = Join-Path $HOME ".dsh/profiles/$profileName" $bundleDir = Join-Path $profileDir 'node_modules/dsh-cross-session-approval' git clone https://github.com/zsjs110110-cpu/dsh-cross-session-approval.git $bundleDir
在该 profile 的 package.json 中,将 dsh-cross-session-approval 追加到 dsh.profile.bundles。以下仅展示相关字段,保留已有配置与其他 bundle:
{
"dsh": {
"profile": {
"bundles": ["dsh-cross-session-approval"]
}
}
}
校验组合配置,再启动宿主加载插件:
dsh --profile $profileName --dump-config dsh --profile $profileName --no-open --port 0
配置输出应包含 cross-session-approval,且无该 bundle 的 skipping;启动时应无该插件的 failed to import。进入该 profile 的会话后,确认可用工具包含下列 10 项。配置校验成功不代表审批桥已启用;还需检查启动告警及下文的服务要求。
快速使用
下面是 DSH 会话内的工具调用示例,不是 PowerShell 命令或可直接导入的 JavaScript API。cs_XXXXXXXXXX 表示工具实际返回的别名,使用时必须替换。
cross_session_spawn({ name: "检查文档", task: "阅读 README,列出安装步骤中的歧义;完成后回复结果。" })
// 保存返回的 session_id(cs_ 别名);spawn 返回后任务仍可能在执行。
cross_session_status({ session_id: "cs_XXXXXXXXXX" })
cross_session_read({ session_id: "cs_XXXXXXXXXX", tail: 10 })
cross_session_send({ session_id: "cs_XXXXXXXXXX", message: "请再核对配置示例。", interrupt: false })
默认继承调用者的模型、推理程度与 agent preset(自定义模式)。spawn 会在任务消息中自动附上回信目标;任务会话应按指引调用 cross_session_reply({ to: "<回信目标别名>", text: "结果摘要或失败原因" })。回信按用户消息投递,并唤醒目标。投递成功与任务完成是两个不同状态,请结合回信及 read 判断结果。
建议先不传 permission 和 cwd,使用默认权限夹紧与当前工作区。显式权限、跨工作区寻址和审批桥的限制见下文。
工具一览
工具 · 必填参数 · 可选参数与行为
cross_session_spawn · name, task · reply_to, provider, model, reasoning_effort, permission, agent_preset, cwd, tags;创建顶层持久会话并投递任务,不等待完成
cross_session_send · session_id, message · wake、interrupt 默认 true;reply_to 指定回信目标;未打开的顶层会话自动恢复
cross_session_reply · to, text · 向指定会话回信并唤醒,目标未打开时自动恢复
cross_session_status · 无 · session_id 筛选当前工作区的派活登记,省略则查看登记总览
cross_session_read · session_id · tail 默认 10、最大 50;include_attempts 附带诊断事件;读取不唤醒目标
cross_session_list · 无 · limit 默认 20;include_archived, cwd, all_workspaces, tag;默认列当前工作区的顶层会话
cross_session_broadcast · targets · 最多 20 项,每项为 { session_id, message, wake?, interrupt?, reply_to? };逐项报告成功或失败
cross_session_rename · session_id, name · 标题长度为 1–60 字符
cross_session_archive · session_id · 归档会话
cross_session_approve · key, decision · decision 为 allow 或 reject;note 为可选备注;仅请求会话的创建者可处理
send 默认在目标当前步骤结束后插入消息;interrupt: false 等当前整轮结束;wake: false 只投递、不唤醒。所有会话标识优先使用工具返回的 cs_ 别名;参数名仍为 session_id、to 或 reply_to。
单条任务或消息正文按 32 KiB UTF-8 配额截断。登记表最多保留 200 条任务记录,超出时淘汰最久未活动的登记;登记表不是完整会话历史。读取与广播可能涉及其他会话的任务内容,请按实际授权范围选择目标。
会话 ID 与短别名
部分宿主或上游显示链路会将模型可见文本中的 32 位十六进制串或 UUID 替换为占位符,例如 session-00000000-0000-4000-8000-000000000000。这不改变内存或磁盘中的真实会话 ID,但从显示文本复制占位符无法正确寻址。
插件用 FNV-1a 确定性派生 cs_ 加 10 位 base62 字符的别名(总长 13),例如 cs_xwx698M4Wa。cross_session_list 和 cross_session_status 返回 alias,文本列表使用该别名。别名不单独落盘,同一版本下由真实 ID 按需重算,重启不改变结果;0.3.8 的别名迁移见版本记录。
输入 · 解析行为
被遮蔽的占位符,含 session- 前缀形式 · 拒绝,并提示使用别名
cs_ 别名 · 在登记表与宿主当前工作区可见会话中匹配;找不到则报错
其他字符串 · 作为真实 ID 原样交给宿主处理
session_id、to 等参数名保持不变,没有单独的 alias 参数。别名用于寻址,不是授权凭据,也不构成权限隔离;解析后仍按真实会话 ID 做身份与权限判断。短哈希不保证数学上无碰撞。
子会话权限夹紧(发布前三维 + 派生入口,0.3.0)
权限夹紧同时检查沙箱档位、审批策略和工作区。沙箱档位从窄到宽为 read-only、workspace-write、danger-full-access;审批策略中 never 比 ask 更严格:它会拒绝需要提权审批的请求。
A:发布前三维夹紧
默认 spawnPermission: cap。cross_session_spawn 的可选参数:
permission:宿主权限预设名。省略时,档位取调用者与部署默认预设中较窄者,审批取更严格者;显式预设的任一维比调用者更宽则拒绝,不静默降级。agent_preset:宿主提供的 agent preset(自定义模式)ID。默认继承调用者;显式指定不存在的模式会报错并附可用列表。它影响工具和提示词,沙箱权限及模型路由由各自配置控制。cwd:已存在的绝对目录,默认取调用者解析出的工作区根目录。非最高档调用者只能选择其工作区根目录或内部目录,按 realpath 校验,指向外部的 junction 不算包含;最高档调用者可指定任意已存在绝对目录。选择不同目录会另开工作区,见下文已知边界。
插件在 session/created 的同步前置监听器中重新解析调用者当前策略,写入沙箱档位与审批策略,再逐项精确读回复核。工作区须与创建意图一致;预设名仅在实际权限值与所选预设匹配时写入。任一步失败则拒绝创建,不投递任务。派发期间调用者权限发生变化也会拒绝,调用者需重试;投递前还须核对绑定该 Session 实例的夹紧凭证。
以部署默认 workspace-write/ask 为例(省略 permission、cwd):
调用者档位 / 审批 · 子会话档位 / 审批
workspace-write/ask · workspace-write/ask
danger-full-access/ask · workspace-write/ask
danger-full-access/never · workspace-write/never
read-only/ask · read-only/ask
read-only/never · read-only/never
上述子会话工作区均为调用者工作区。spawnPermission: off 关闭 A,恢复宿主默认创建行为,可能使低权限调用者创建出更高权限的会话;启用审批桥必须使用 cap。
显式同档权限的边界
显式 permission 只拒绝比调用者更宽的权限,允许与调用者相同的权限。例如部署配置了 full-ask(danger-full-access/ask)时,同档调用者显式指定 permission: "full-ask" 可以创建同档子会话;省略该参数则仍按部署默认值夹紧。
这是当前契约的结果。插件没有独立的子会话最高预设配置,无法保证子会话始终严格低于创建者。非必要时省略 permission;确需最高档权限时,应先向用户说明并取得授权。使用约定与界面提示不能替代权限限制。
F:派生入口夹紧
同一监听器处理非 A、带 parentSession 的会话创建通知,包括 fork 和恢复派生会话。默认 forkPermission: cap:
- 源会话活跃:按源当前策略限制三维权限。工作区必须在源工作区内,源为最高档时跳过此包含检查。
- 源会话未加载:
cap按部署默认预设与部署根目录限制;越界或 realpath 解析失败则拒绝。此上限不代表源会话的当前权限。strict直接拒绝未加载源的派生。 off:关闭 F,不访问 F 的可选权限服务。
F 只修改需要收窄的沙箱档位和审批策略,不写 permission/preset,写后读回复核。权限服务缺失时,启用的 A/F 对应创建路径拒绝。A/F 独立于审批桥:关闭桥不关闭 A/F,关闭 F 不影响 A。恢复派生会话也可能被收窄或拒绝。
跨会话审批桥(0.3.0)
由 cross_session_spawn 创建的任务会话,在 pwsh 或 run_code 请求沙箱提权时,可将审批交给其创建者会话(下称 owner)。owner 必须在同一宿主中保持活跃;本版不会为审批恢复未加载的 owner。
桥在宿主根上下文中优先处理 approval/request,处理链如下:
1. 身份与所有者:用 carrierKeyOf(this) === request.agent 校验请求载体。所有者只在 spawn 时按真实调用者写入内存;send、`broad
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::2,最后更新 2026-10-18