# 架构与协议边界 DSH Desktop Agent Bridge 是安装在现有 DSH desktop profile 中的宿主插件及客户端 UI。外部 agent 通过 MCP 分派工作,DSH 宿主拥有模型调用、工具执行、原生会话与审批。 ```text 本机 MCP 客户端 ── stdio 适配器 ───────────────────┐ │ 远程 MCP 客户端 ── HTTPS 通道 ── HTTP MCP 适配器 ──┤ ▼ 本机 RPC → 身份与授权检查 → 任务队列 │ ▼ 现有 DSH 桌面宿主 │ 原生会话 / 工具 / 审批 │ ▼ 原生聊天 + Agent 协作 UI ``` HTTPS 终止和隧道由部署方负责,不由插件自动创建。远程接入方式见 [remote.md](remote.md)。 ## 代码职责 | 文件 | 职责 | | --- | --- | | `src/protocol.mjs` | 严格请求结构、客户端授权结构及宿主/UI 远程服务描述 | | `src/host.mjs` | 插件生命周期、状态目录锁、本机端点和 UI 服务注册 | | `src/host-adapter.mjs` | 对接 DSH 的会话、模型、权限、历史、队列及原生交互 | | `src/broker.mjs` | 凭据身份、资源授权、会话归属、任务去重、调度和审计 | | `src/http.mjs` | 仅回环监听的 RPC 入口,固定路由与请求边界 | | `src/mcp-server.mjs` | 本机与远程共用的十个 MCP 工具 | | `src/mcp.mjs` | 本机 stdio 传输与健康心跳 | | `src/remote-mcp.mjs` | 远程接入的 Streamable HTTP 适配器,转发到固定本机身份 | | `src/client.jsx` / `src/client.css` | 左侧协作区和用户授权设置 | 内部包名 `dsh-agent-collaboration`、插件 ID `agent-collaboration`、服务 `agentCollaboration` 及原有工具名保留兼容。品牌名不参与身份鉴权。 ## 身份、授权与会话 每个客户端创建时获得独立随机令牌,状态中保存令牌摘要,连接文件保存供适配器使用的令牌。RPC 根据令牌解析身份,不接受调用者自报身份覆盖结果。 客户端授权只包含已有工作区、能力包、模型及可选父交互开关。新客户端的资源列表为空,父交互默认关闭。`dsh_catalog` 先过滤资源,任务创建时再次校验;排队任务提交前也重新检查,避免使用已撤销授权。 一个身份可以拥有多条协作会话。一条会话固定一个身份、工作区和能力包;后续空闲轮次可以选择已授权模型及受支持的思考强度。外部工具不能列出其他身份或用户的普通会话。用户可通过桌面设置明确交接普通会话,已有归属的会话不能再转给另一身份。 这些检查限制本插件接口。DSH 宿主、用户本人和持有同一操作系统账号权限的程序仍处于更高信任层。 ## 提交、去重与结果 `requestId` 在客户端身份内标识一次请求。相同 ID 和相同参数返回原任务;相同 ID 配不同参数被拒绝。提交状态在发出原生消息前持久化,以便区分尚未提交和提交结果不确定的任务。 任务按规范化后的项目目录排队,同一目录同时只派发一个本插件任务。它不是全局文件锁,不限制普通 DSH 会话、其他插件或独立进程。 本轮结果由原生日志事件边界确定,避免继续会话后把下一轮回复混入旧结果。MCP 只输出助手文本,不把推理块当作公开结果;输出超过 60,000 字符时返回末尾并标记 `truncated`。 主要状态为: ```text preparing → queued → running → completed / failed / cancelled / blocked ↕ waiting_approval / waiting_input 提交或恢复无法确定结果 → unknown → 用户检查原生会话 ``` `completed` 表示原生轮次完成,不是对产物正确性的保证。`unknown` 不自动重发;只有原生日志确认消费了本任务的消息,插件才会认领对应结果,避免把之后的人工消息结果误归到旧任务。停止未知任务也必须等待原生执行停止后才能释放项目队列。外部 MCP 断线不会撤销已经派发的任务,DSH 宿主退出则可能中断工作。 ## 用户控制 接管先撤销外部写入控制权,再移除尚未消费且属于该身份的外部消息;用户输入保留,当前已开始工作继续。交还不重放撤回的消息。停止使用 DSH 原生取消,不回滚文件改动。 资源撤销与停止不同:撤销阻止后续指挥及队列提交,正在执行的模型或工具不会因此自动回滚。 ## 原生审批与父 Agent 转交 普通控制连接创建 `interactions: 'none'` 的 DSH Peer,不能回答审批。可选交互连接单独建立,仅为用户开启转交、仍归外部 agent 控制且正在运行的会话接收原生请求。 父 Agent 流程为:列出请求 → 完整展示给用户 → 等待实际答复 → 回传一次 → 读取结果。回传只允许一次批准、拒绝或合法问题答案。请求 ID 同时绑定当前任务、控制权代次和授权代次;接管、停止、修改授权或关闭开关会使旧 ID 失效。 原生网关标识不直接暴露给外部客户端。回复在提交前记录,传输结果不确定时不自动重放批准。两处同时回答由 DSH 原生交互流程决定哪个有效答复先完成。 这不是独立的人类身份认证:父 Agent 仍能填写 `userReply`。启用此功能表示用户信任父 Agent 不会伪造其答复。默认关闭和请求校验不能替代这一信任前提。 ## 持久化与版本约束 默认状态目录位于用户目录下的 `.dsh/agent-collaboration`,可配置: - `state.json`:身份授权、会话归属、任务文本、请求记录和交互回复审计。 - `client-.json`:该身份的本机连接凭据。 - `endpoint.json`:当前宿主端点和运行信息。 - `host.lock`:同一状态目录的宿主占用记录。 DSH 自己管理完整原生会话。插件状态使用临时文件加替换写入;这不构成加密存储,也不是跨账号隔离。卸载保留状态与 DSH 会话。 已验证宿主为 Windows 上的 DSH `0.2.1-rc.2`。模型选择使用 `selectForNextRequest`,父交互依赖该版原生事件通道,UI 使用 `sidebar.footer.action` 插槽。这些版本相关接口集中在适配器和 UI 中;不兼容时应明确报错,不回退到修改全局模型、关闭审批或启动另一个 DSH。