dsh-plugin-mobile-gateway 0.10.4 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/PROTOCOL.md CHANGED
@@ -866,6 +866,38 @@ DSH `present` 工具成功后持久化 `deliverables/presented`,移动端根
866
866
  - 默认每块为 512 KiB、同时最多 4 个下载、单个文件最多 512 MiB。部署方可用 `fileDownloadChunkBytes`、`fileDownloadMaxTransfers`、`fileDownloadMaxBytes`、`fileDownloadIdleMs` 调整;`fileDownloadsEnabled: false` 会关闭该能力,且 `hello.capabilities` 不再包含 `file-downloads`。
867
867
  - 绝对路径、空路径(`file-download-open`)、`..` 路径段、NUL 字符、工作目录外的符号链接、目录和其他非普通文件都会被拒绝。`file-list` 不返回符号链接,避免客户端误认为其可下载。
868
868
 
869
+ ### 普通文件上传
870
+
871
+ 已配对连接在启用 `fileUploadsEnabled` 时公布 `file-upload-v1`。上传请求走 control 连接(兼容 legacy),消息走 conversation 连接(兼容 legacy)。普通文件按原始字节进入官方附件存储,取得会话专属 `receiptId`,不接受客户端指定的主机路径。自定义 Host 未组合官方文件上传服务时返回 `file-upload-unavailable`。
872
+
873
+ | type | 必填参数 | 成功 kind |
874
+ |---|---|---|
875
+ | `file-upload-open` | `requestId`, `sessionId`, `name`, `size`, `sha256` | `file-upload-opened` |
876
+ | `file-upload-chunk` | `requestId`, `uploadId`, `offset`, `data` | `file-upload-chunk-accepted` |
877
+ | `file-upload-finish` | `requestId`, `uploadId` | `file-upload-completed` |
878
+ | `file-upload-cancel` | `requestId`, `uploadId` | `file-upload-cancelled` |
879
+
880
+ `requestId` 为 1 至 128 字符的非空字符串,所有上传响应和错误均回显。`sessionId` 必须是已有普通会话;新草稿先使用 `session-create`,子智能体暂不支持文件附件。`name` 只允许不带目录和控制字符的 1 至 255 字符文件名。`size` 为非负安全整数,`sha256` 是完整原始字节的 64 位十六进制摘要,允许空文件。
881
+
882
+ `file-upload-opened` 返回 `uploadId/sessionId/name/size/chunkBytes/maxBytes/idleTimeoutMs`。chunk 使用标准 Base64,`offset` 按解码字节计数,必须等于当前已确认位置;每次等待 `file-upload-chunk-accepted.nextOffset` 后再发下一块,不支持分块流水线或跨连接续传。finish 校验长度和 SHA-256 后通过官方流式接口提交:
883
+
884
+ ```json
885
+ { "kind": "file-upload-completed", "requestId": "finish-1", "uploadId": "upload-uuid", "sessionId": "s1",
886
+ "receiptId": "host-receipt-uuid", "sha256": "<64 位十六进制摘要>",
887
+ "file": { "attachmentId": "opaque-file-id", "name": "报告.pdf", "bytes": 1234 } }
888
+
889
+ { "type": "message", "requestId": "submission-uuid", "sessionId": "s1", "text": "分析这个报告",
890
+ "files": [{ "receiptId": "host-receipt-uuid" }], "mode": "queue" }
891
+ ```
892
+
893
+ 含文件消息必须有 `requestId`,会原样传给 Host 用于相同提交的重试去重。`files` 最多 20 项,不允许重复凭证;可以纯文件发送或与已有图片、文字混合。Host 校验凭证所属的准确 Session,并将其转换为原生 file 内容块;上传完成不会自动发送消息。
894
+
895
+ 实时 `user/message` 新增 `event.files: [{attachmentId,name,bytes}]`;历史 `data.content[]` 保留 `{type:"file",attachment:{attachmentId,name,bytes}}`。附件 ID 不等于工作区路径,现有图片 `attachment` 和工作区 `file-download-*` 不能用于按此 ID 下载文件。
896
+
897
+ 默认单文件 512 MiB、每块 256 KiB、全网关最多 4 个活动上传、空闲 2 分钟、Host 提交超时 180 秒。可配置 `fileUploadMaxBytes/fileUploadChunkBytes/fileUploadMaxTransfers/fileUploadIdleMs/fileUploadCommitTimeoutMs`,实际分块上限还受 `maxPayloadBytes` 限制。上传开关独立于下载开关。
898
+
899
+ uploadId 仅归属创建它的 socket;取消、断线、空闲超时和网关停止会清理网关暂存并中止活动提交。原连接可在短期完成缓存内重试 finish 取得同一结果,缓存最多 128 条、默认保留 2 分钟;不提供断点续传或 Host 附件回滚删除。更完整的官方 WebUI 源码对应关系、JSON 示例、错误表、App 状态机和验收步骤见 [移动端普通文件上传对接指南](docs/file-upload-app-integration.md)。
900
+
869
901
  ### `session-stats` 详细(输入框统计条)
870
902
  ```json
871
903
  { "type": "session-stats", "sessionId": "session-abc" }
@@ -1155,7 +1187,7 @@ Control/旧单连接接收全局模式状态增量,不受所订阅会话过滤
1155
1187
  "event": { "type": "assistant/message", "turn": 1, "step": 0, "text": "已完成", "reasoning": "", "toolCalls": [] } }
1156
1188
  ```
1157
1189
  `event.type` 覆盖(精炼字段):
1158
- - `user/message` → `{text, source, images?: ImageAttachmentRef[]}`
1190
+ - `user/message` → `{text, source, images?: ImageAttachmentRef[], files?: [{attachmentId,name,bytes}]}`
1159
1191
  - 实时 token 使用独立 `assistant-stream`,不是带持久 seq 的 `assistant/chunk`;详见 [rc.2 接入说明](docs/dsh-rc2-mobile-integration.md)。
1160
1192
  - `assistant/attempt` → `{turn, step, stream[], finish?: {kind, failure?}}`
1161
1193
  - `assistant/message` → `{turn, step, text, reasoning, toolCalls[], interrupted?, usage?, finish?: {kind, failure?}}`
@@ -1395,3 +1427,41 @@ history. Older gateways without the capability continue using one connection.
1395
1427
  取消回执只表示已发出取消信号;原转写随后返回 `speech/cancelled`,资源清理完成前仍占并发名额。断线、网关停止会中止该连接的活动转写和状态订阅。其他连接不能取消这个转写,即使属于同一设备。客户端上滑取消、切换页面或替换草稿后必须忽略旧请求的迟到结果。
1396
1428
 
1397
1429
  错误统一为 `kind:error`,包含 `requestType`, `requestId`, `code`, `message`。网关错误包括 `authentication-required`, `wrong-channel`, `bad-request`, `speech/unavailable`, `speech/busy`, `speech/request-in-progress`, `speech/request-not-found`, `speech/invalid-audio`, `speech/cancelled`, `speech/timeout`, `speech/invalid-response`, `speech/stream-ended`;官方插件的 `speech/transcription-failed` 等错误代码保留。
1430
+
1431
+ ## 智能体团队与子会话(agent-team-v1 / subagent-conversations-v1)
1432
+
1433
+ 当前源码新增两个协议 3 可选能力,Host 适配基线为 DSH 0.2.1-rc.2、Session format 4。完整 APP 实施规范见 [智能体团队 APP 详细接入指南](docs/agent-team-app-integration.md),包含成员与任务完整字段、目录树、视图切换、消息和停止、投影缓存、恢复流程及验收清单。
1434
+
1435
+ | 连接 | 请求/推送 | 说明 |
1436
+ |---|---|---|
1437
+ | control | `agent-team` | 请求 `sessionId` 为 Lead ID,`requestId?` 回显;响应 `agentTeam` 完整值及 `projectionState`、精确值的 `asOfSeq` |
1438
+ | control | `subagents` | 请求 `sessionId` 为父节点 ID,`requestId?` 回显;响应 `subagentCatalog` 直接子节点数组及相同投影状态字段 |
1439
+ | control | `agent-team-updated` | `{sessionId,asOfSeq,agentTeam}`,团队完整值替换,null 表示失效 |
1440
+ | control | `subagents-updated` | `{sessionId,asOfSeq,subagentCatalog}`,父节点直接子目录完整替换,null 表示失效 |
1441
+ | control | `subagent-identity-updated` | `{sessionId,asOfSeq,subagent}`,该子会话身份完整值或 null |
1442
+ | control | `subagent-timing-updated` | `{sessionId,asOfSeq,subagentTiming}`,该子会话耗时完整值或 null |
1443
+ | control | `session-status` | `{sessionId,running}`,全局进程内运行状态;初始/重连用 sessions 刷新 |
1444
+
1445
+ 两个查询都返回 `projectionState: ready | unavailable | migration-required`。没有投影是 null,空目录是 `[]`,空任务板是团队对象中的 `tasks:[]`;迁移提示没有 `asOfSeq`,不能当作精确基线。未找到会话返回 `session/not-found`。查询不激活 Agent、不调用模型。capability 仅表示网关理解协议,不保证 Host 已启用实验性团队插件。
1446
+
1447
+ 新增投影键 `agentTeam/subagentCatalog/subagent/subagentTiming` 同时出现在 `projection-baseline`。上述更新与运行状态不受当前聊天 subscribe 过滤,仅发往 control/legacy。Host control 重建会发送替换基线及失效通知;基线未包含冷会话不表示会话删除。各投影按 `(gatewayId, sessionId, projectionKey)` 管理水位,不能跨会话或跨键比较 seq。初始运行状态从 sessions 查询取得,实时状态不具备持久 seq。
1448
+
1449
+ 子会话沿用现有 `sessionId` 为当前视图 ID,增加 `parentSessionId`(直接父会话)和 `subagentMode`(`continuable | one-shot | unknown`);这两个字段必须一起提供。普通会话不带它们,external 节点没有本地子会话地址。
1450
+
1451
+ ```json
1452
+ {"type":"subscribe","sessionId":"child","parentSessionId":"lead","subagentMode":"continuable","assistantStream":true}
1453
+ {"type":"history","sessionId":"child","parentSessionId":"lead","subagentMode":"continuable","requestId":"h1","beforeSeq":20,"historyFormatVersion":4}
1454
+ {"type":"message","sessionId":"child","parentSessionId":"lead","subagentMode":"continuable","requestId":"m1","mode":"queue","text":"继续处理当前任务"}
1455
+ {"type":"session-cancel","sessionId":"child","parentSessionId":"lead","subagentMode":"continuable","requestId":"stop1"}
1456
+ {"type":"tasks","sessionId":"child","parentSessionId":"lead","subagentMode":"continuable","requestId":"todos1"}
1457
+ ```
1458
+
1459
+ - conversation:`history/subscribe/message`;control:`session-cancel/tasks/goal`。`goal` 同样支持子地址。其他操作不能仅凭此能力推定支持子地址。
1460
+ - `subscribed`、follower 的 snapshot/event/assistant-stream/reset 回显父子地址;切换使用新 `subscriptionId/streamId`。旧 legacy 持久事件可能只有 sessionId。
1461
+ - history、tasks、goal、session-cancel 的正常响应及查询失败回显原请求 requestId(如果提供)。`sent` 对子消息额外返回 `messageId`、父子地址以及原 requestId。
1462
+ - 子消息内部使用官方专用 continuation 接口;`message.mode` 仍是 queue/steer,不表示生命周期。只有 continuable 能发送与停止。
1463
+ - 共享任务来自 Lead 的 `agentTeam.tasks`,负责人字段是 `ownerName`;成员 `todos` 仍是独立内部待办。
1464
+ - 普通子目录包含 continuable/one-shot/external/unknown;按父节点逐级读取,不自动递归。
1465
+ - 子会话父子关系由 Host 校验,非法关系返回 `subagent/unauthorized` 等错误;无法继续的模式返回 `subagent/not-resumable`。
1466
+ - 发送回执只表示 inbox 接受,不保证执行完成,也不提供自动重试去重保证。断线无回执应核对历史/队列,不能盲目重发。
1467
+ - 本次不提供直接创建成员或变更共享任务的移动 RPC;由用户在 Lead 对话中提出要求,Host 团队工具执行,APP 等待权威投影更新。
package/README.md CHANGED
@@ -10,7 +10,11 @@ DeepSeek Harness 的设备鉴权移动网关,支持会话与实时事件、排
10
10
  >
11
11
  > 实时流已改为独立 `assistant-stream` 帧,移动端需要按 [rc.2 接入说明](docs/dsh-rc2-mobile-integration.md) 更新订阅、缓存与分页处理。当前修改尚未发布。
12
12
  >
13
- > v0.10.4(当前源码):精简会话列表投影,仅保留标题与投影切点,修复大量会话通过公网隧道传输时超时的问题;保留会话元信息和历史完整投影,现有移动客户端无需配套修改。
13
+ > v0.11.1(当前源码,尚未发布):新增普通文件分块上传,支持 SHA-256 校验、进度确认、取消与断线清理,复用 DSH 官方附件存储和会话专属凭证,支持文件随消息发送及实时和历史文件引用。App 需按 `file-upload-v1` 能力接入,详见 [移动端普通文件上传对接指南](docs/file-upload-app-integration.md)。
14
+ >
15
+ > v0.11.0:新增智能体团队与子会话协议,支持团队成员、共享任务看板、多层子智能体目录和运行状态实时同步,以及子智能体独立历史、视图切换、继续对话、图片输入与停止执行。APP 需按能力发现接入,详见 [智能体团队 APP 详细接入指南](docs/agent-team-app-integration.md)。
16
+ >
17
+ > v0.10.4:精简会话列表投影,仅保留标题与投影切点,修复大量会话通过公网隧道传输时超时的问题;保留会话元信息和历史完整投影,现有移动客户端无需配套修改。
14
18
  >
15
19
  > v0.10.3:适配 DSH 0.2.1-rc.2,为 Remote 请求及实时订阅补齐 Connection Peer,修复 `Cannot read properties of undefined (reading 'signal')` 报错,并在网关停止时释放 Peer。移动端协议保持不变。
16
20
  >
@@ -52,6 +56,10 @@ DSH_INSTALL_ROOT=/absolute/path/to/@deepseek-ai/dsh node test/host-official.test
52
56
 
53
57
  当前源码新增 `turn-outline-v1`:透传 WebUI 使用的完整轮次大纲及实时更新,支持 App 在未加载全部正文时展示会话刻度、问答预览并按需分页跳转。控制连接重建和新设备连接会恢复大纲基线;Host 未提供大纲时可降级为已加载轮次导航。详见 [App 会话轮次导航接入指南](docs/turn-outline-app-integration.md)。App 界面需单独接入,本次源码尚未发布。
54
58
 
59
+ 当前源码新增 `file-upload-v1`:已配对移动端可通过控制连接分块上传 PDF、Office、压缩包、音频等普通文件,校验 SHA-256 后存入 DSH 官方附件存储,再以会话专属凭证随消息发送。支持进度确认、取消、断线清理及实时/历史文件引用;复用官方 WebUI 的附件准入,不写入客户端指定的主机路径。帧示例、App 状态机、限制及验收见 [移动端普通文件上传对接指南](docs/file-upload-app-integration.md)。App 页面需单独接入,本次源码尚未发布。
60
+
61
+ 当前源码新增 `agent-team-v1`、`subagent-conversations-v1`:支持团队成员与共享任务板查询、各层子智能体目录、团队投影和成员运行状态实时同步,以及子会话独立历史、订阅、继续对话与停止执行。APP 的目标地址、完整 JSON 示例、看板规则、切换与重连状态机、错误处理和验收清单见 [智能体团队 APP 详细接入指南](docs/agent-team-app-integration.md)。本次只提供网关能力,APP 页面需单独接入,源码尚未发布。
62
+
55
63
  ## 多网关第一阶段(当前源码)
56
64
 
57
65
  插件提供稳定 `gatewayId`、可配置 `gatewayName`、配对候选地址列表,以及可持久化的“关闭 / 临时开启 / 常驻开启”运行模式。一个 App 可以分别配对不同机器上的网关;客户端多网关管理仍需按 [App 对接说明](docs/multi-gateway-app-integration.md) 实现。本次源码尚未发布新的 npm 版本。