@dsh-edge/dsh-edge-agent 0.0.0-stage → 0.1.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.
Files changed (238) hide show
  1. package/CHANGELOG.md +142 -0
  2. package/LICENSE +21 -0
  3. package/README.md +372 -2
  4. package/config/edge.example.json +179 -0
  5. package/config/privacy-policy.json +202 -0
  6. package/cordis.desktop-safe.patch.yml +129 -0
  7. package/cordis.patch.yml +382 -0
  8. package/cordis.yml +374 -0
  9. package/lib/attestation.d.ts +2 -0
  10. package/lib/attestation.d.ts.map +1 -0
  11. package/lib/attestation.js +2 -0
  12. package/lib/audit-log.d.ts +2 -0
  13. package/lib/audit-log.d.ts.map +1 -0
  14. package/lib/audit-log.js +2 -0
  15. package/lib/client.js +87 -0
  16. package/lib/cloud-llm-adapter.d.ts +2 -0
  17. package/lib/cloud-llm-adapter.d.ts.map +1 -0
  18. package/lib/cloud-llm-adapter.js +2 -0
  19. package/lib/dsh-adapter/attestation.d.ts +42 -0
  20. package/lib/dsh-adapter/attestation.d.ts.map +1 -0
  21. package/lib/dsh-adapter/attestation.js +40 -0
  22. package/lib/dsh-adapter/audit-log.d.ts +139 -0
  23. package/lib/dsh-adapter/audit-log.d.ts.map +1 -0
  24. package/lib/dsh-adapter/audit-log.js +376 -0
  25. package/lib/dsh-adapter/cloud-egress.d.ts +181 -0
  26. package/lib/dsh-adapter/cloud-egress.d.ts.map +1 -0
  27. package/lib/dsh-adapter/cloud-egress.js +257 -0
  28. package/lib/dsh-adapter/cloud-llm-adapter.d.ts +416 -0
  29. package/lib/dsh-adapter/cloud-llm-adapter.d.ts.map +1 -0
  30. package/lib/dsh-adapter/cloud-llm-adapter.js +1472 -0
  31. package/lib/dsh-adapter/contract.d.ts +80 -0
  32. package/lib/dsh-adapter/contract.d.ts.map +1 -0
  33. package/lib/dsh-adapter/contract.js +194 -0
  34. package/lib/dsh-adapter/desktop-cookie-janitor.d.ts +214 -0
  35. package/lib/dsh-adapter/desktop-cookie-janitor.d.ts.map +1 -0
  36. package/lib/dsh-adapter/desktop-cookie-janitor.js +409 -0
  37. package/lib/dsh-adapter/dsh-edge-agent.d.ts +48 -0
  38. package/lib/dsh-adapter/dsh-edge-agent.d.ts.map +1 -0
  39. package/lib/dsh-adapter/dsh-edge-agent.js +64 -0
  40. package/lib/dsh-adapter/edge-config.d.ts +484 -0
  41. package/lib/dsh-adapter/edge-config.d.ts.map +1 -0
  42. package/lib/dsh-adapter/edge-config.js +898 -0
  43. package/lib/dsh-adapter/edge-context-view.d.ts +184 -0
  44. package/lib/dsh-adapter/edge-context-view.d.ts.map +1 -0
  45. package/lib/dsh-adapter/edge-context-view.js +483 -0
  46. package/lib/dsh-adapter/effective-model.d.ts +85 -0
  47. package/lib/dsh-adapter/effective-model.d.ts.map +1 -0
  48. package/lib/dsh-adapter/effective-model.js +171 -0
  49. package/lib/dsh-adapter/etscli-shell-guard.d.ts +244 -0
  50. package/lib/dsh-adapter/etscli-shell-guard.d.ts.map +1 -0
  51. package/lib/dsh-adapter/etscli-shell-guard.js +420 -0
  52. package/lib/dsh-adapter/etscli-tools.d.ts +112 -0
  53. package/lib/dsh-adapter/etscli-tools.d.ts.map +1 -0
  54. package/lib/dsh-adapter/etscli-tools.js +393 -0
  55. package/lib/dsh-adapter/file-logger.d.ts +294 -0
  56. package/lib/dsh-adapter/file-logger.d.ts.map +1 -0
  57. package/lib/dsh-adapter/file-logger.js +564 -0
  58. package/lib/dsh-adapter/function-call-external.d.ts +357 -0
  59. package/lib/dsh-adapter/function-call-external.d.ts.map +1 -0
  60. package/lib/dsh-adapter/function-call-external.js +1005 -0
  61. package/lib/dsh-adapter/host-egress-guard.d.ts +161 -0
  62. package/lib/dsh-adapter/host-egress-guard.d.ts.map +1 -0
  63. package/lib/dsh-adapter/host-egress-guard.js +213 -0
  64. package/lib/dsh-adapter/host-llm-trace.d.ts +198 -0
  65. package/lib/dsh-adapter/host-llm-trace.d.ts.map +1 -0
  66. package/lib/dsh-adapter/host-llm-trace.js +344 -0
  67. package/lib/dsh-adapter/http-api-routes.d.ts +61 -0
  68. package/lib/dsh-adapter/http-api-routes.d.ts.map +1 -0
  69. package/lib/dsh-adapter/http-api-routes.js +79 -0
  70. package/lib/dsh-adapter/http-api-sessions.d.ts +105 -0
  71. package/lib/dsh-adapter/http-api-sessions.d.ts.map +1 -0
  72. package/lib/dsh-adapter/http-api-sessions.js +173 -0
  73. package/lib/dsh-adapter/http-api.d.ts +221 -0
  74. package/lib/dsh-adapter/http-api.d.ts.map +1 -0
  75. package/lib/dsh-adapter/http-api.js +1811 -0
  76. package/lib/dsh-adapter/index.d.ts +62 -0
  77. package/lib/dsh-adapter/index.d.ts.map +1 -0
  78. package/lib/dsh-adapter/index.js +97 -0
  79. package/lib/dsh-adapter/input-guard-messages.d.ts +56 -0
  80. package/lib/dsh-adapter/input-guard-messages.d.ts.map +1 -0
  81. package/lib/dsh-adapter/input-guard-messages.js +136 -0
  82. package/lib/dsh-adapter/input-guard.d.ts +508 -0
  83. package/lib/dsh-adapter/input-guard.d.ts.map +1 -0
  84. package/lib/dsh-adapter/input-guard.js +2174 -0
  85. package/lib/dsh-adapter/intent-prompts.d.ts +77 -0
  86. package/lib/dsh-adapter/intent-prompts.d.ts.map +1 -0
  87. package/lib/dsh-adapter/intent-prompts.js +97 -0
  88. package/lib/dsh-adapter/intent-router.d.ts +710 -0
  89. package/lib/dsh-adapter/intent-router.d.ts.map +1 -0
  90. package/lib/dsh-adapter/intent-router.js +2802 -0
  91. package/lib/dsh-adapter/intent-signals.d.ts +208 -0
  92. package/lib/dsh-adapter/intent-signals.d.ts.map +1 -0
  93. package/lib/dsh-adapter/intent-signals.js +391 -0
  94. package/lib/dsh-adapter/invariant-install.d.ts +16 -0
  95. package/lib/dsh-adapter/invariant-install.d.ts.map +1 -0
  96. package/lib/dsh-adapter/invariant-install.js +15 -0
  97. package/lib/dsh-adapter/invariant.d.ts +16 -0
  98. package/lib/dsh-adapter/invariant.d.ts.map +1 -0
  99. package/lib/dsh-adapter/invariant.js +22 -0
  100. package/lib/dsh-adapter/llm-adapters.d.ts +19 -0
  101. package/lib/dsh-adapter/llm-adapters.d.ts.map +1 -0
  102. package/lib/dsh-adapter/llm-adapters.js +16 -0
  103. package/lib/dsh-adapter/llm-internal-caller.d.ts +92 -0
  104. package/lib/dsh-adapter/llm-internal-caller.d.ts.map +1 -0
  105. package/lib/dsh-adapter/llm-internal-caller.js +100 -0
  106. package/lib/dsh-adapter/llm-max-turns.d.ts +55 -0
  107. package/lib/dsh-adapter/llm-max-turns.d.ts.map +1 -0
  108. package/lib/dsh-adapter/llm-max-turns.js +127 -0
  109. package/lib/dsh-adapter/llm-trace-store.d.ts +131 -0
  110. package/lib/dsh-adapter/llm-trace-store.d.ts.map +1 -0
  111. package/lib/dsh-adapter/llm-trace-store.js +205 -0
  112. package/lib/dsh-adapter/llm-trace.d.ts +450 -0
  113. package/lib/dsh-adapter/llm-trace.d.ts.map +1 -0
  114. package/lib/dsh-adapter/llm-trace.js +463 -0
  115. package/lib/dsh-adapter/local-llm-adapter.d.ts +141 -0
  116. package/lib/dsh-adapter/local-llm-adapter.d.ts.map +1 -0
  117. package/lib/dsh-adapter/local-llm-adapter.js +787 -0
  118. package/lib/dsh-adapter/local-storage.d.ts +96 -0
  119. package/lib/dsh-adapter/local-storage.d.ts.map +1 -0
  120. package/lib/dsh-adapter/local-storage.js +198 -0
  121. package/lib/dsh-adapter/model-router.d.ts +79 -0
  122. package/lib/dsh-adapter/model-router.d.ts.map +1 -0
  123. package/lib/dsh-adapter/model-router.js +107 -0
  124. package/lib/dsh-adapter/ohttp-gateway.d.ts +49 -0
  125. package/lib/dsh-adapter/ohttp-gateway.d.ts.map +1 -0
  126. package/lib/dsh-adapter/ohttp-gateway.js +32 -0
  127. package/lib/dsh-adapter/openai-sse.d.ts +85 -0
  128. package/lib/dsh-adapter/openai-sse.d.ts.map +1 -0
  129. package/lib/dsh-adapter/openai-sse.js +462 -0
  130. package/lib/dsh-adapter/pii-utils.d.ts +96 -0
  131. package/lib/dsh-adapter/pii-utils.d.ts.map +1 -0
  132. package/lib/dsh-adapter/pii-utils.js +324 -0
  133. package/lib/dsh-adapter/plugin-host.d.ts +38 -0
  134. package/lib/dsh-adapter/plugin-host.d.ts.map +1 -0
  135. package/lib/dsh-adapter/plugin-host.js +38 -0
  136. package/lib/dsh-adapter/plugin.d.ts +46 -0
  137. package/lib/dsh-adapter/plugin.d.ts.map +1 -0
  138. package/lib/dsh-adapter/plugin.js +100 -0
  139. package/lib/dsh-adapter/privacy-policy.d.ts +237 -0
  140. package/lib/dsh-adapter/privacy-policy.d.ts.map +1 -0
  141. package/lib/dsh-adapter/privacy-policy.js +391 -0
  142. package/lib/dsh-adapter/prompt-guard.d.ts +152 -0
  143. package/lib/dsh-adapter/prompt-guard.d.ts.map +1 -0
  144. package/lib/dsh-adapter/prompt-guard.js +872 -0
  145. package/lib/dsh-adapter/realm-skill-bridge.d.ts +365 -0
  146. package/lib/dsh-adapter/realm-skill-bridge.d.ts.map +1 -0
  147. package/lib/dsh-adapter/realm-skill-bridge.js +1180 -0
  148. package/lib/dsh-adapter/sanitizer-pipeline.d.ts +140 -0
  149. package/lib/dsh-adapter/sanitizer-pipeline.d.ts.map +1 -0
  150. package/lib/dsh-adapter/sanitizer-pipeline.js +431 -0
  151. package/lib/dsh-adapter/secure-bridge.d.ts +47 -0
  152. package/lib/dsh-adapter/secure-bridge.d.ts.map +1 -0
  153. package/lib/dsh-adapter/secure-bridge.js +35 -0
  154. package/lib/dsh-adapter/session-attribution.d.ts +70 -0
  155. package/lib/dsh-adapter/session-attribution.d.ts.map +1 -0
  156. package/lib/dsh-adapter/session-attribution.js +76 -0
  157. package/lib/dsh-adapter/sessions.d.ts +86 -0
  158. package/lib/dsh-adapter/sessions.d.ts.map +1 -0
  159. package/lib/dsh-adapter/sessions.js +179 -0
  160. package/lib/dsh-adapter/tcm.d.ts +55 -0
  161. package/lib/dsh-adapter/tcm.d.ts.map +1 -0
  162. package/lib/dsh-adapter/tcm.js +94 -0
  163. package/lib/dsh-adapter/td-bus.d.ts +87 -0
  164. package/lib/dsh-adapter/td-bus.d.ts.map +1 -0
  165. package/lib/dsh-adapter/td-bus.js +196 -0
  166. package/lib/dsh-adapter/tool-runner.d.ts +185 -0
  167. package/lib/dsh-adapter/tool-runner.d.ts.map +1 -0
  168. package/lib/dsh-adapter/tool-runner.js +271 -0
  169. package/lib/dsh-adapter/tools.d.ts +118 -0
  170. package/lib/dsh-adapter/tools.d.ts.map +1 -0
  171. package/lib/dsh-adapter/tools.js +292 -0
  172. package/lib/dsh-adapter/types.d.ts +23 -0
  173. package/lib/dsh-adapter/types.d.ts.map +1 -0
  174. package/lib/dsh-adapter/types.js +16 -0
  175. package/lib/dsh-adapter/voice-input.d.ts +30 -0
  176. package/lib/dsh-adapter/voice-input.d.ts.map +1 -0
  177. package/lib/dsh-adapter/voice-input.js +34 -0
  178. package/lib/dsh-adapter/web-search-tavily-bocha.d.ts +152 -0
  179. package/lib/dsh-adapter/web-search-tavily-bocha.d.ts.map +1 -0
  180. package/lib/dsh-adapter/web-search-tavily-bocha.js +289 -0
  181. package/lib/http-api.d.ts +2 -0
  182. package/lib/http-api.d.ts.map +1 -0
  183. package/lib/http-api.js +2 -0
  184. package/lib/index.d.ts +48 -0
  185. package/lib/index.d.ts.map +1 -0
  186. package/lib/index.js +49 -0
  187. package/lib/intent-router.d.ts +2 -0
  188. package/lib/intent-router.d.ts.map +1 -0
  189. package/lib/intent-router.js +2 -0
  190. package/lib/llm-adapters.d.ts +2 -0
  191. package/lib/llm-adapters.d.ts.map +1 -0
  192. package/lib/llm-adapters.js +2 -0
  193. package/lib/local-llm-adapter.d.ts +2 -0
  194. package/lib/local-llm-adapter.d.ts.map +1 -0
  195. package/lib/local-llm-adapter.js +2 -0
  196. package/lib/local-storage.d.ts +2 -0
  197. package/lib/local-storage.d.ts.map +1 -0
  198. package/lib/local-storage.js +2 -0
  199. package/lib/model-router.d.ts +2 -0
  200. package/lib/model-router.d.ts.map +1 -0
  201. package/lib/model-router.js +2 -0
  202. package/lib/ohttp-gateway.d.ts +2 -0
  203. package/lib/ohttp-gateway.d.ts.map +1 -0
  204. package/lib/ohttp-gateway.js +2 -0
  205. package/lib/plugin-host.d.ts +2 -0
  206. package/lib/plugin-host.d.ts.map +1 -0
  207. package/lib/plugin-host.js +2 -0
  208. package/lib/privacy-policy.d.ts +2 -0
  209. package/lib/privacy-policy.d.ts.map +1 -0
  210. package/lib/privacy-policy.js +2 -0
  211. package/lib/prompt-guard.d.ts +2 -0
  212. package/lib/prompt-guard.d.ts.map +1 -0
  213. package/lib/prompt-guard.js +2 -0
  214. package/lib/sanitizer-pipeline.d.ts +2 -0
  215. package/lib/sanitizer-pipeline.d.ts.map +1 -0
  216. package/lib/sanitizer-pipeline.js +2 -0
  217. package/lib/secure-bridge.d.ts +2 -0
  218. package/lib/secure-bridge.d.ts.map +1 -0
  219. package/lib/secure-bridge.js +2 -0
  220. package/lib/sessions.d.ts +2 -0
  221. package/lib/sessions.d.ts.map +1 -0
  222. package/lib/sessions.js +2 -0
  223. package/lib/tcm.d.ts +2 -0
  224. package/lib/tcm.d.ts.map +1 -0
  225. package/lib/tcm.js +2 -0
  226. package/lib/td-bus.d.ts +2 -0
  227. package/lib/td-bus.d.ts.map +1 -0
  228. package/lib/td-bus.js +2 -0
  229. package/lib/tools.d.ts +2 -0
  230. package/lib/tools.d.ts.map +1 -0
  231. package/lib/tools.js +2 -0
  232. package/lib/voice-input.d.ts +2 -0
  233. package/lib/voice-input.d.ts.map +1 -0
  234. package/lib/voice-input.js +2 -0
  235. package/package.json +341 -3
  236. package/presets/agent-preset-edge.json +50 -0
  237. package/presets/edge.desktop-safe.patch.yml +503 -0
  238. package/presets/edge.patch.yml +557 -0
@@ -0,0 +1,503 @@
1
+ # ── 边缘模式 preset(§7.135)──────────────────────────────────────────
2
+ #
3
+ # 宿主 DSH 的「Agent Preset」机制:preset 是一份 cordis insert patch,声明
4
+ # 一行 `@deepseek-ai/dsh-agent-preset`,其 `config.plugins` 是该工作方式
5
+ # 的**完整**插件行列表。宿主内置四种工作方式,都由 bundle 的 patch 文件
6
+ # 声明(@deepseek-ai/dsh-web-app/presets/*.patch.yml):
7
+ #
8
+ # standard —— 标准模式:persona / 工具 / plan-mode / compaction /
9
+ # delegation / subagent …
10
+ # ptc / minimal / cordis —— 另外三种
11
+ #
12
+ # 本文件声明**边缘模式**:标准模式的插件列表 **+ 本项目的功能**(隐私护栏、
13
+ # 意图判定、路由决策、PII 脱敏、两个 LLM adapter、Realm 闸门、威胁总线、
14
+ # Edge 面板)。主人裁决(2026-10-28):
15
+ #
16
+ # 「我需要在 dsh 桌面上出一新的 agent 工作时间,叫做边缘模式,功能是在
17
+ # 标准模式之上增加本项目的功能」
18
+ # 「只有选择 边缘模式 才会出现 edge tab」
19
+ #
20
+ # ## 本项目的插件行在哪(§7.136 修正)
21
+ #
22
+ # 行为面(护栏 / 判定 / 路由 / 脱敏 / Realm / Edge 面板)**在这里**,并且整体
23
+ # 关进一个 `cordis:group` + `isolate` 隔离 realm —— 宿主规则(dsh-agent-preset-
24
+ # registry README):「preset 的服务提供方及其消费方必须共享同一个 cordis:group
25
+ # 隔离 realm」。挂载审计(lib/types/mount.js)会把「挂在 preset 子树里却把服务
26
+ # 存进 root realm」的行判为泄漏 ⇒ 整个 preset 挂载失败 ⇒ 设置页那张卡显示
27
+ # 「加载失败」。这正是 §7.135 那版预设加载失败的原因。
28
+ #
29
+ # **三行必须留在宿主树**(bundle 顶层 insert 段)—— 宿主机制的限制,不是偏好:
30
+ #
31
+ # dsh-edge-agent(裸包名行)—— 宿主的 client-modules 只扫**宿主 Loader 的
32
+ # entries**(dsh-client-modules/lib/index.js:「scans the host Loader's
33
+ # entries」;processOne() 遍历 `this.ctx.loader.entries()`),preset 的插件树
34
+ # 是独立的 EntryTree、不在其中 ⇒ Edge tab 的浏览器半边只有从宿主树里的裸
35
+ # 包名行才能被发现。
36
+ # audit-log / file-logger —— 裸包名行 inject ['auditLog'],且它 apply() 里的
37
+ # installFileLogger 会先占住 `fileLogger` 服务名 ⇒ 两者必须在 root realm,
38
+ # 且 file-logger 行必须比裸包名行更早装载(否则桌面 ops log 的文件名会从
39
+ # `dsh-edge-agent-desktop.log` 退回 `dsh-edge-agent.log`)。
40
+ #
41
+ # ## 「切回标准模式会怎样」(§7.136 实测结论)
42
+ #
43
+ # 宿主的 preset 是**启动即挂载**的(dsh-agent-preset README:「声明会提前加载」):
44
+ # 声明过的 preset 在启动时都建好插件树,选哪个只决定 **Agent 绑到哪个 scope**
45
+ # (可见的工具 / 提示词 / 服务)。所以:
46
+ #
47
+ # * 本项目的插件在任何工作方式下都已挂载 —— 切回标准模式**不会**卸载它们;
48
+ # 让标准模式变「纯宿主」的是**事件作用域**,不是卸载:
49
+ # * 我们的 hook(agent/pre-step / agent/request / system-prompt/assemble /
50
+ # tools/pre-execute / tools/result)**不再带 `{ global: true }`**。宿主的
51
+ # 事件过滤(cordis EventsService.dispatch:
52
+ # `hook.global || !filter || filter.call(thisArg, hook.ctx)`)按 scope 链
53
+ # 判定 —— 监听器自己的 scope 必须是派发 scope 或其祖先;Agent 的 scope 父
54
+ # 链接到所选 preset 的代际 scope(dsh-agent-preset-registry 的
55
+ # `bindScopeParent`),事件沿 scope 链向上流、不向下 ⇒ 标准模式的 Agent
56
+ # 收不到边缘模式 preset 里的 hook ⇒ 标准模式不经过本项目的护栏;
57
+ # * `llm/stream` 保留 `{ global: true }`:该事件不带 scope 载体(去掉也不
58
+ # 生效),且无 pre-step state 时恒直通;
59
+ # * Edge tab 的浏览器半边是全局的(客户端只有一张全局 boot 图,tab 类型是
60
+ # 全局注册表),所以「只有边缘模式才有 edge tab」由**客户端按 roster 的
61
+ # 默认 preset 注册/注销 tab 类型**实现(src/client/index.ts,5s 轮询
62
+ # `agentPresets.list()` 的 `isDefault`)。
63
+ #
64
+ # ## 为什么标准模式的行是抄来的
65
+ #
66
+ # 注册表**不合并**:preset 的 plugins 是完整列表,覆盖式(宿主原文:「用户覆盖
67
+ # 替换完整子插件列表,不自动合并内置列表的未来更新」)。所以边缘模式要
68
+ # 「在标准模式之上增加」,就必须把标准模式的行**整份抄进来**。
69
+ #
70
+ # 代价要说清楚:**宿主升级后标准模式的插件列表若变了,边缘模式不会自动跟随**
71
+ # —— 需要人把宿主的
72
+ # @deepseek-ai/dsh-web-app/presets/standard.patch.yml
73
+ # 重新对齐到本文件。生成器 scripts/_gen-edge-preset.mjs 就是干这件事的。
74
+ #
75
+ # ## 主机 row 的覆盖留在顶层
76
+ #
77
+ # 本 bundle 顶层对宿主行的覆盖(tool-web / web / web-search-deepseek)是
78
+ # **patch 层**语义 —— preset 只能声明插件行,不能覆盖宿主行。所以这些覆盖
79
+ # 在任何工作方式下都生效。这是 preset 机制的边界,如实记录在此。
80
+
81
+ - insert:
82
+ - id: preset-edge
83
+ name: '@deepseek-ai/dsh-agent-preset'
84
+ config:
85
+ id: edge
86
+ name: 边缘模式
87
+ description: 标准模式 + 本项目的端侧隐私能力(意图判定 / 路由决策 / PII 脱敏 / Realm 闸门)
88
+ order: 5
89
+ plugins:
90
+ # §7.175(2026-11-11):这里**故意没有** `agent-default-model` 行;
91
+ # §7.176(2026-11-11)起,本地模型默认值改由**本 preset 内的
92
+ # input-guard** 给出(见下面 edge-stack 组里的 input-guard 行)。
93
+ #
94
+ # 实测(桌面 App 日志 2026-11-11 10:24 / 10:26,两次启动一致):
95
+ # WARN [agent-preset-registry] agent preset edge:
96
+ # agent-default-model (@deepseek-ai/dsh-agent-default-model):
97
+ # service "agentDefaultModel" has been registered at <AgentDefaultModelConfig>
98
+ # ⇒ 加了这一行,**整个边缘模式 preset 挂载失败**(设置页那张卡显示
99
+ # 「加载失败」),Edge 模式用不了。
100
+ #
101
+ # 根因:宿主 dsh-base/cordis.patch.yml L90-94 已经在 **host scope** 声明了
102
+ # 同一个插件(provider: deepseek-official / model: deepseek-flash);该插件
103
+ # 用 `super(ownerContext, "agentDefaultModel")` 注册 cordis service,
104
+ # 而这个 service 名**跨 scope 唯一** ⇒ preset scope 再声明一次 ⇒ 撞名。
105
+ #
106
+ # ⚠️ 本文件此前写的理由(「service 注册在插件所在 scope,scope 查找就近 ⇒
107
+ # preset 内就近拿到这一行、遮蔽 host scope 的全局默认」)是**推断,实测证伪**
108
+ # —— 真正的读取方是 host scope 的那份:
109
+ # `dsh-api-session-controller` 的 `agentOptions()` 读 `this.ctx.agentDefaultModel`,
110
+ # preset scope 里那份即使不撞名也**没有读者**。
111
+ #
112
+ # §7.176:为什么由 input-guard 给默认值,而不是这一行:
113
+ # 1. 宿主 0.2.2-rc.1 起,路由只由**会话级** modelSelection 决定
114
+ # (`agent/request` 里改写会被 prepareRequest() 判非法并抛错);
115
+ # 2. 桌面 GUI 建的 agent,其 agentOptions 来自 host scope 的
116
+ # agentDefaultModel(宿主自带的云端模型)⇒ 边缘模式默认会跑云端;
117
+ # 3. 本地路由 local-llm 在模型目录里隐身(§7.106 Option A:它是管线
118
+ # 内部件,不是用户可选项)⇒ GUI 里**选不到**它,用户没法手动纠正;
119
+ # ⇒ 只能由 preset 侧把会话选择钉成 local-llm。input-guard 用的是宿主
120
+ # 自己的合规入口 `agent.model.select()`(agent-loop 的
121
+ # applyConfiguredRoute() 也是这么写的),**不动**宿主的全局默认 ——
122
+ # `sessionController.selectModel()` 会顺手 `saveSelection()` 改全局,
123
+ # 那样会波及同 profile 的标准模式。
124
+ #
125
+ # 主人裁决(2026-11-11):**npm 包里不会带本地模型配置**(config/edge.json
126
+ # 被 `files` 白名单排除)⇒ local-llm 走 DELEGATE(§7.171)转发宿主
127
+ # provider ⇒ 装上就能用(先用 dsh 自带的云端模型),而 provider 身份仍是
128
+ # local-llm ⇒ §7.175 的 fail-closed 闸门照样放行。
129
+ # 实测记录见 docs/PROGRESS.md §7.175 / §7.176。
130
+ - id: persona
131
+ name: '@deepseek-ai/dsh-persona'
132
+ config:
133
+ prefix: You are a coding agent powered by the {{model}} model.
134
+ - id: agent-instructions
135
+ name: '@deepseek-ai/dsh-agent-instructions'
136
+ config:
137
+ maxBytes: 65536
138
+ - id: time-context
139
+ name: '@deepseek-ai/dsh-time-context'
140
+ - id: tool-bash
141
+ name: '@deepseek-ai/dsh-tool-bash'
142
+ disabled: !!js process.platform === 'win32'
143
+ - id: tool-pwsh
144
+ name: '@deepseek-ai/dsh-tool-pwsh'
145
+ disabled: !!js process.platform !== 'win32'
146
+ - id: tool-fs
147
+ name: '@deepseek-ai/dsh-tool-fs'
148
+ config:
149
+ # §7.174:随宿主 0.2.2-rc.1 的 standard preset 对齐 ——
150
+ # Set false to drop the apply_patch tool beside edit.
151
+ applyPatch: false
152
+ - id: tool-fs-search
153
+ name: '@deepseek-ai/dsh-tool-fs-search'
154
+ config:
155
+ sampleOverCapGlobResults: false
156
+ - id: tool-jobs
157
+ name: '@deepseek-ai/dsh-tool-jobs'
158
+ - id: tool-schedule
159
+ name: '@deepseek-ai/dsh-tool-schedule'
160
+ - id: skill-filesystem
161
+ name: '@deepseek-ai/dsh-skill-filesystem'
162
+ - id: tool-skill
163
+ name: '@deepseek-ai/dsh-tool-skill'
164
+ - id: command-goal
165
+ name: '@deepseek-ai/dsh-command-goal'
166
+ - id: tool-goal
167
+ name: '@deepseek-ai/dsh-tool-goal'
168
+ - id: planning
169
+ name: cordis:group
170
+ group: true
171
+ isolate:
172
+ planMode: true
173
+ config:
174
+ - id: plan-mode
175
+ name: '@deepseek-ai/dsh-plan-mode'
176
+ config:
177
+ section: |
178
+ You are in plan mode. Stay in plan mode until the user approves your plan through exit_plan_mode or switches the session mode. Imperative language to implement changes means plan the implementation, not execute it. A user's conversational agreement — including an answer confirming something you asked — approves nothing and does not end plan mode; fold the confirmed decision into the plan and submit it through exit_plan_mode.
179
+
180
+ Explore first. Use non-mutating reads, searches, static analysis, and checks to ground the plan in the actual repository. Do not edit or write files, change configuration, run formatters or code generation that rewrites tracked files, commit, or otherwise carry out the plan. Prefer existing functions and patterns over new machinery.
181
+
182
+ The tool catalog stays the same across modes for request-cache stability. These plan-mode rules override any later tool description or guidance that suggests using mutation tools; those tools remain listed to keep the tool catalog unchanged. Do not use todo_write to track this planning phase: it tracks implementation after an approved plan, while the plan itself belongs in exit_plan_mode.
183
+
184
+ Resolve discoverable facts by inspection. Use ask_user_question only for user-owned choices or material ambiguity that inspection cannot answer. Do not ask the user where code lives or how current behavior works when you can find out.
185
+
186
+ Make the plan decision-complete: state the goal and success criteria; group implementation changes by subsystem; identify public API, schema, and data-flow changes; cover edge cases, failure modes, tests, acceptance criteria, and explicit assumptions. Keep it concise enough to review but detailed enough that another engineer can implement it without making design decisions.
187
+
188
+ When ready, call exit_plan_mode with the complete plan markdown, starting with a # title. Make exit_plan_mode the only and final tool call in that assistant response: it presents the plan for approval, and implementation begins only in a later step after approval. Do not paste the final plan as a plain reply or ask "should I proceed?" through prose or ask_user_question. If review rejects it, incorporate the feedback and present again. If the review channel is unavailable or aborted, stay in plan mode and ask the user to switch modes manually; do not proceed with implementation.
189
+ - id: compaction
190
+ name: cordis:group
191
+ group: true
192
+ isolate:
193
+ compaction: true
194
+ toolResultPruner: true
195
+ config:
196
+ - id: compaction-basic
197
+ name: '@deepseek-ai/dsh-compaction-basic'
198
+ - id: command-compact
199
+ name: '@deepseek-ai/dsh-command-compact'
200
+ - id: tool-result-pruner
201
+ name: '@deepseek-ai/dsh-compaction-tool-result-pruner'
202
+ config:
203
+ thresholdChars: 8192
204
+ headChars: 4096
205
+ tailChars: 1024
206
+ - id: delegation
207
+ name: cordis:group
208
+ group: true
209
+ isolate:
210
+ workflowEngine: true
211
+ config:
212
+ - id: tool-subagent-control
213
+ name: '@deepseek-ai/dsh-tool-subagent-control'
214
+ # §7.174:宿主 0.2.2-rc.1 的 dsh-tool-subagent-control **不再导出**
215
+ # './list-agents' 子路径(exports 只剩 . / ./src/* / ./package.json /
216
+ # ./locale/*.json)⇒ 保留这行会在 preset 挂载时抛
217
+ # ERR_PACKAGE_PATH_NOT_EXPORTED ⇒ 整个 edge preset 被判 broken
218
+ # ⇒ 设置页「边缘模式」消失。宿主四个内置 preset(standard/ptc/
219
+ # minimal/cordis)**都没有这一行** ⇒ 按宿主现状删除。
220
+ - id: tool-subagent
221
+ name: '@deepseek-ai/dsh-tool-subagent'
222
+ config:
223
+ provider: spawn
224
+ toolName: subagent
225
+ # §7.136 曾经**故意不写** modelSelection(那时宿主键名是
226
+ # `modelSelectionSettings`):旧宿主的 per-agent 安装路径在
227
+ # tools/change 重投时会二次 install() ⇒ 同一 scope 重复注册
228
+ # 'subagent'。上游已改为「挂载时注册一次」,且宿主现在的
229
+ # standard/ptc/cordis preset 都写着这两项 ⇒ §7.174 对齐,
230
+ # 边缘模式恢复「子 Agent 选模型」参数。
231
+ modelSelection: true
232
+ modelDiscovery: true
233
+ - id: tool-subagent-fork
234
+ name: '@deepseek-ai/dsh-tool-subagent'
235
+ config:
236
+ provider: fork
237
+ toolName: subagent_fork
238
+ - id: workflow-ptc
239
+ name: '@deepseek-ai/dsh-workflow-ptc'
240
+ config:
241
+ provider: spawn
242
+ - id: tool-workflow
243
+ name: '@deepseek-ai/dsh-tool-workflow'
244
+ - id: tool-ask-user
245
+ name: '@deepseek-ai/dsh-tool-ask-user'
246
+ - id: tool-todo
247
+ name: '@deepseek-ai/dsh-tool-todo'
248
+ config:
249
+ allowParallelInProgress: true
250
+ - id: tool-web
251
+ name: '@deepseek-ai/dsh-tool-web'
252
+ config:
253
+ fetch: true
254
+ searchTimeoutMs: 60000
255
+ - id: present
256
+ name: '@deepseek-ai/dsh-tool-present'
257
+ - id: tool-plugin-manager
258
+ name: '@deepseek-ai/dsh-plugin-manager/tools'
259
+ disabled: true
260
+ - id: tool-plugin-market
261
+ name: '@deepseek-ai/dsh-plugin-market/tools'
262
+ disabled: true
263
+
264
+ # ── 边缘模式:本项目的功能(§7.135 + §7.136)──────────────────────
265
+ #
266
+ # 宿主规则(dsh-agent-preset-registry README):
267
+ # 「preset 的服务提供方及其消费方必须共享同一个 cordis:group 隔离 realm」
268
+ # 挂载审计(lib/types/mount.js):preset 子树里的服务如果存进 root realm
269
+ # ⇒ 泄漏 ⇒ 整个 preset 挂载失败(设置页那张卡显示「加载失败」)。
270
+ # 所以本组用 cordis:group + isolate 把组内每一行提供的服务关进组内 realm:
271
+ # 组内互相可见,组外(宿主)看不见 ⇒ 不泄漏。
272
+ #
273
+ # isolate 名单由 scripts/_isolate-edge-group.mjs 从源码推导
274
+ # (super(ctx,'<svc>')),门禁 scripts/verify-preset-isolate.ts 复核 ——
275
+ # 改源码后必须重跑本脚本。
276
+ - id: edge-stack
277
+ name: cordis:group
278
+ group: true
279
+ isolate:
280
+ edgeContextView: true
281
+ edgeTools: true
282
+ functionCallExternal: true
283
+ inputGuard: true
284
+ intentRouter: true
285
+ modelRouter: true
286
+ privacyPolicy: true
287
+ promptGuard: true
288
+ realmSkillBridge: true
289
+ sanitizer: true
290
+ tcm: true
291
+ tdBus: true
292
+ config:
293
+ # Stub TCM. Real crypto remains future work; keep shape stable.
294
+ - id: tcm
295
+ name: '@dsh-edge/dsh-edge-agent/tcm'
296
+ # §7.102 "one config file": teeType / keyStorePath come from
297
+ # config/edge.json (tee.*) inside the plugin — no row config.
298
+
299
+ # Privacy policy engine. Missing file falls back to built-in v1.6 policy.
300
+ - id: privacy-policy
301
+ name: '@dsh-edge/dsh-edge-agent/privacy-policy'
302
+ inject: [auditLog]
303
+ # §7.102 "one config file": policyPath / hot-reload knobs come from
304
+ # config/edge.json (privacy.*).
305
+
306
+ # Threat bus. Thresholds come from config/edge.json (threat.*) — §7.102.
307
+ # Desktop-safe keeps the looser default threshold.
308
+ - id: td-bus
309
+ name: '@dsh-edge/dsh-edge-agent/td-bus'
310
+ inject: [auditLog, privacyPolicy]
311
+ config:
312
+ windowSeconds: 60
313
+ thresholds:
314
+ failedSanitizationStreak: 3
315
+ permissionDeniedStreak: 5
316
+
317
+ # Edge tool registry. Do not isolate tools by default in desktop mode.
318
+ - id: edge-tools-registry
319
+ name: '@dsh-edge/dsh-edge-agent/tools'
320
+ inject: [auditLog, tools]
321
+ config:
322
+ defaultRateLimitPerMinute: 60
323
+ enableToolIsolation: false
324
+ presentationMode: native
325
+
326
+ # §7.120: 封堵「bash 里直接调 etscli 写子命令」这条逃逸口。
327
+ #
328
+ # 独立行(不挂 etscli-tools)⇒ 桌面**只多一道闸**,不新增那 14 个
329
+ # 只读 etscli 工具。监听器挂在 `tools/pre-execute` waterfall 上,
330
+ # 按 scope 链派发 ⇒ 只有边缘模式会话够得着它,标准模式不受影响
331
+ # (§7.140 的「标准模式零 edge 事件」不变式)。
332
+ - id: etscli-shell-guard
333
+ name: '@dsh-edge/dsh-edge-agent/etscli-shell-guard'
334
+
335
+ # Realm-aware skill/tool filtering. Uses the shared realm config file.
336
+ - id: realm-skill-bridge
337
+ name: '@dsh-edge/dsh-edge-agent/realm-skill-bridge'
338
+ inject: [auditLog, skills, edgeTools, tools]
339
+ # §7.102 "one config file": configPath / hot-reload knobs come from
340
+ # config/edge.json (privacy.realm*).
341
+
342
+ # Input guard. Model-assisted detection config comes from
343
+ # config/edge.json (stages.guard.*) — §7.102.
344
+ - id: prompt-guard
345
+ name: '@dsh-edge/dsh-edge-agent/prompt-guard'
346
+ inject: [privacyPolicy, auditLog, llm]
347
+ config:
348
+ maxInputLength: 10000
349
+ maxRequestsPerMinute: 20
350
+ enablePIIRedaction: true
351
+ enableInjectionDetection: true
352
+ enableRateLimit: true
353
+
354
+ # Reversible PII sanitizer. Session limits come from
355
+ # config/edge.json (privacy.*) — §7.102.
356
+ - id: sanitizer-pipeline
357
+ name: '@dsh-edge/dsh-edge-agent/sanitizer-pipeline'
358
+ inject: [privacyPolicy, auditLog]
359
+ config:
360
+ enableAutoDetection: true
361
+ maxReplacementsPerSession: 1024
362
+
363
+ # Intent router. Classifier config comes from config/edge.json
364
+ # (stages.intent.*) — §7.102. Classifier provider may be absent;
365
+ # fail-open to keywords.
366
+ - id: intent-router
367
+ name: '@dsh-edge/dsh-edge-agent/intent-router'
368
+ inject: [llm, auditLog, privacyPolicy]
369
+
370
+ # §7.100 cloud-llm = DELEGATE route. baseUrl deliberately absent →
371
+ # Schema default '' → every CLOUD/SANITIZED turn is forwarded to the
372
+ # host profile's own configured model provider (GUI picker wins; probe
373
+ # falls back to live host routes). Credential resolution stays entirely
374
+ # on the host side — this bundle reads no secrets.
375
+ # §7.102: the pool + delegate knobs come from config/edge.json
376
+ # (llm.cloud.*) — the patch row no longer reads process.env.
377
+ - id: cloud-llm-adapter
378
+ name: '@dsh-edge/dsh-edge-agent/cloud-llm-adapter'
379
+ inject: [llm, auditLog]
380
+ config:
381
+ providers: [cloud-llm]
382
+
383
+ # §7.102 (2026-10-21): local-LLM configuration moved OUT of the cordis
384
+ # patch and into config/edge.json (llm.local.*). The patch row no
385
+ # longer reads process.env — the desktop GUI starts the bundle without
386
+ # sourcing any .env.sh, so every `process.env.DSH_EDGE_LOCAL_LLM_*`
387
+ # lookup here resolved to undefined and the adapter fell back to a
388
+ # hard-coded 127.0.0.1:8080 that collided with unrelated daemons.
389
+ #
390
+ # The adapter now reads the pool from config/edge.json itself:
391
+ # - baseUrl set → DIRECT: the local-LLM route talks to that
392
+ # OpenAI-compatible endpoint with the key named by
393
+ # `llm.local.keyRef` (omit keyRef when the endpoint is open).
394
+ # - baseUrl unset → §7.171 DELEGATE: the route IS registered, but
395
+ # forwards to the host profile's provider (symmetric with
396
+ # cloud-llm). `llm.local.delegate=false` is the kill switch
397
+ # that leaves the route unregistered.
398
+ # - Internal LLM stages (intent classification / guard model-detect)
399
+ # point here EXCLUSIVELY per the 2026-10-18 privacy ruling; they
400
+ # never target cloud-llm. Note: with DELEGATE they run on the
401
+ # host's model — configure a local endpoint to keep them on
402
+ # device.
403
+ - id: local-llm-adapter
404
+ name: '@dsh-edge/dsh-edge-agent/local-llm-adapter'
405
+ inject: [llm, auditLog]
406
+ config:
407
+ providers: [local-llm]
408
+
409
+ # Route catalog so /v1-style enumeration & intent-router soft-dep see
410
+ # both routes with registry truth (§7.100 isAvailable).
411
+ - id: model-router
412
+ name: '@dsh-edge/dsh-edge-agent/model-router'
413
+ inject: [llm]
414
+ config:
415
+ localModels: [local-llm]
416
+ cloudModels: [cloud-llm]
417
+
418
+ # Optional external tool caller; disabled by default. Knobs come from
419
+ # config/edge.json (functionCallExternal.*) — §7.102.
420
+ - id: function-call-external
421
+ name: '@dsh-edge/dsh-edge-agent/function-call-external'
422
+ inject: [auditLog, realmSkillBridge, tools]
423
+
424
+ # Orchestrator. This is the actual global hook installer.
425
+ - id: input-guard
426
+ name: '@dsh-edge/dsh-edge-agent/input-guard'
427
+ # §7.176 (2026-11-11): 本行是**边缘模式本地模型默认值的给出点** ——
428
+ # input-guard 监听 `agent/created`,用宿主的合规入口
429
+ # `agent.model.select()` 把会话级 modelSelection 钉成 local-llm
430
+ # (宿主 0.2.2-rc.1 起路由只由会话级选择决定,而 GUI 里选不到
431
+ # local-llm —— §7.106 Option A 它在模型目录里隐身)。
432
+ # 详见 docs/PROGRESS.md §7.176。
433
+ inject: [promptGuard, privacyPolicy, intentRouter, sanitizer, auditLog, realmSkillBridge]
434
+ config:
435
+ sanitizeLocalTraffic: false
436
+ # §7.179 (2026-11-11): 本 preset 的 id。`agent-preset/selected`
437
+ # 是**全局**事件(宿主 registry 直接 ctx.emit,不带 scope 载体)
438
+ # ⇒ input-guard 必须自己按 presetId 过滤,否则会把标准模式的
439
+ # 会话也钉成 local-llm。必须与上面 `config.id` 一致 ——
440
+ # scripts/verify-preset-isolate.ts 复核这一点。
441
+ presetId: edge
442
+
443
+ # §7.101 Edge tab host half: folds the audit stream into the four panel
444
+ # row-lists + session summary and serves them on /api/dsh-edge/context.
445
+ # Hard dep is auditLog only (the sole live data source — see
446
+ # docs/notes/dsh-context-walkthrough.md ruling E); `connection` arms
447
+ # deferred, so headless profiles mount the plugin without the route.
448
+ #
449
+ # §7.101.x (2026-10-20, fix #2, SUPERSEDED by fix #4 below): BARE
450
+ # package name was tried after v7's ERR_PACKAGE_PATH_NOT_EXPORTED,
451
+ # but the bare name makes the loader mount the MAIN entry plugin
452
+ # (`dsh-edge-agent` host half) under this `edge-context-view` entry
453
+ # id — and the host half's apply() (via plugin.ts) touched the
454
+ # undeclared `ctx.event` service, so cordis reported:
455
+ # "1 entry did not activate edge-context-view:
456
+ # Error: cannot get property 'event' without inject"
457
+ # (live evidence: desktop plugin-manager reload, 2026-10-20).
458
+ #
459
+ # §7.101.x (2026-10-20, fix #4): the REAL v7 bug was exports pointing
460
+ # at the removed dotted layout (lib/types/dsh-adapter/*). With the
461
+ # flat-layout move (tsconfig outDir -> lib, exports -> lib/dsh-adapter/*,
462
+ # package.json#main -> lib/index.js matching dsh-context), the subpath
463
+ # name resolves cleanly through exports['./edge-context-view'] to
464
+ # lib/dsh-adapter/edge-context-view.js (import-proven on this host).
465
+ # This row now mounts the ACTUAL view plugin (src declares
466
+ # inject = ['auditLog'] + deferred `connection` inside apply());
467
+ # plugin.ts's ctx.event emit is also best-effort-wrapped so the host
468
+ # half can never again poison this entry.
469
+ #
470
+ # §7.101.x (2026-10-20, fix #1, still active): no `inject:` / `config:`
471
+ # fields — cordis 0.2.1-rc.2 patch loader SILENTLY SKIPS both (Bug 1,
472
+ # docs/dev-notes/cordis-rc021-patch-loader.md). The plugin declares
473
+ # its deps in src; runtime knobs come from process.env inside apply().
474
+ - id: edge-context-view
475
+ name: '@dsh-edge/dsh-edge-agent/edge-context-view'
476
+
477
+ # §7.107 (2026-10-23): web search aggregator — Tavily → 博查 AI →
478
+ # DeepSeek(三级链,§7.82)。它的 Tier-3 DeepSeek 用
479
+ # `web_search_20250305` server tool 打 DeepSeek Messages API,凭据读
480
+ # config/edge.json 的 secrets.deepseekApiKey —— 不依赖环境变量,所以
481
+ # CLI 起的 profile(dsh-http)也能用。
482
+ - id: web-search-tavily-bocha
483
+ name: '@dsh-edge/dsh-edge-agent/web-search-tavily-bocha'
484
+
485
+ # ── web capability: DEEPSEEK Search + Fetch(§7.107)──────────────────────
486
+ #
487
+ # §7.107 的路由规则把「需要检索公网上的信息」定为唯一允许出网的操作 ——
488
+ # 那这条路径就得真的能搜公网、真的能抓网页,否则规则没有意义。
489
+ #
490
+ # - search → 本仓的 aggregator(Tavily → 博查 → DeepSeek);DeepSeek 是
491
+ # 链上的兜底也是唯一不依赖环境变量的后端。
492
+ # - fetch → 宿主的 'http' provider(dsh-web-fetch-http,dsh-base 自带,
493
+ # 匿名公共 HTTP(S) 抓取,自带目的地校验)。
494
+ #
495
+ # dsh-web-app 层把 tool-web 禁掉了(桌面版默认不带网工具);这里重新启用。
496
+ # realm 桥仍然管着:web_search / web_fetch 是 CLOUD realm 的工具
497
+ # (tools.ts 的 DSH_NATIVE_REALM_MAP),LOCAL realm 下不可见 —— 也就是只有
498
+ # §7.107 允许出网的那些轮次能用它们。
499
+ #
500
+ # 注意:这些是宿主 row 的覆盖(disabled / config),不是 insert。上游
501
+ # 'deepseek-official' search provider 必须禁掉 —— aggregator 内部私有一份
502
+ # DeepSeekSearchProvider,两个都注册会让 seam 报 WEB_PROVIDER_AMBIGUOUS
503
+ # (与 cordis.patch.yml 的 web 段同因同解)。