@ljwei-stak/dsh-model-route-bot 0.66.4 → 0.67.0

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 (271) hide show
  1. package/.dsh-plugin/bot-product.mjs +81 -5
  2. package/.dsh-plugin/client.js +17490 -1791
  3. package/README.i18n.yaml +4 -4
  4. package/README.md +409 -364
  5. package/README.zh.md +409 -364
  6. package/apps/integration-client/README.md +31 -7
  7. package/apps/integration-client/api.mjs +14 -3
  8. package/apps/integration-client/binding-editor.jsx +308 -109
  9. package/apps/integration-client/binding-model.mjs +262 -0
  10. package/apps/integration-client/binding.css +144 -0
  11. package/apps/integration-client/bot-model-status.mjs +18 -0
  12. package/apps/integration-client/bot-profile-identity.jsx +197 -0
  13. package/apps/integration-client/bot-profile.css +57 -0
  14. package/apps/integration-client/bot-profile.mjs +97 -0
  15. package/apps/integration-client/bot-settings-dialog.css +18 -0
  16. package/apps/integration-client/bot-settings-dialog.jsx +111 -0
  17. package/apps/integration-client/bot-thread-header-bridge.css +20 -0
  18. package/apps/integration-client/bot-thread-header.jsx +278 -0
  19. package/apps/integration-client/bot-threads-panel.jsx +378 -0
  20. package/apps/integration-client/bot-threads.css +169 -0
  21. package/apps/integration-client/chat-design.mjs +250 -0
  22. package/apps/integration-client/chat-ui.jsx +175 -0
  23. package/apps/integration-client/chat.css +477 -0
  24. package/apps/integration-client/composer-draft-binding.mjs +50 -0
  25. package/apps/integration-client/composer-draft-bound.jsx +14 -0
  26. package/apps/integration-client/composer-draft-host.jsx +142 -0
  27. package/apps/integration-client/composer-draft-session.jsx +287 -0
  28. package/apps/integration-client/composer-draft-witness.mjs +115 -0
  29. package/apps/integration-client/composer-draft.css +4 -0
  30. package/apps/integration-client/composer-draft.mjs +322 -0
  31. package/apps/integration-client/contact-attention.jsx +54 -0
  32. package/apps/integration-client/data-panel.jsx +439 -0
  33. package/apps/integration-client/data.css +69 -0
  34. package/apps/integration-client/desktop-bridge.mjs +1 -0
  35. package/apps/integration-client/desktop-http-socket.mjs +49 -0
  36. package/apps/integration-client/desktop-keyboard.mjs +32 -0
  37. package/apps/integration-client/desktop-pane.jsx +99 -30
  38. package/apps/integration-client/desktop-stream.mjs +13 -3
  39. package/apps/integration-client/desktop-tools.jsx +19 -0
  40. package/apps/integration-client/desktop-touch.mjs +27 -0
  41. package/apps/integration-client/desktop.css +41 -0
  42. package/apps/integration-client/independent-chat-controller.mjs +224 -0
  43. package/apps/integration-client/independent-chat-entry.jsx +61 -0
  44. package/apps/integration-client/independent-chat-navigation.mjs +21 -0
  45. package/apps/integration-client/independent-chat-page.jsx +148 -0
  46. package/apps/integration-client/independent-chat-rich.jsx +64 -0
  47. package/apps/integration-client/independent-chat-rich.mjs +30 -0
  48. package/apps/integration-client/independent-chat.css +73 -0
  49. package/apps/integration-client/index.jsx +24 -16
  50. package/apps/integration-client/library-panel.jsx +4 -1
  51. package/apps/integration-client/licenses/jsqr-1.4.0-LICENSE.txt +202 -0
  52. package/apps/integration-client/main-route-editor.jsx +94 -0
  53. package/apps/integration-client/main-route-model.mjs +100 -0
  54. package/apps/integration-client/model-picker.css +37 -0
  55. package/apps/integration-client/model-picker.jsx +83 -0
  56. package/apps/integration-client/native-activity.css +141 -0
  57. package/apps/integration-client/native-activity.jsx +276 -0
  58. package/apps/integration-client/native-activity.mjs +384 -0
  59. package/apps/integration-client/notifications-panel.jsx +186 -0
  60. package/apps/integration-client/notifications.css +126 -0
  61. package/apps/integration-client/pairing-qr.jsx +79 -0
  62. package/apps/integration-client/panels.jsx +126 -115
  63. package/apps/integration-client/product-slots.jsx +46 -0
  64. package/apps/integration-client/routine-recorder.mjs +23 -2
  65. package/apps/integration-client/secure-pairing.jsx +84 -0
  66. package/apps/integration-client/tasks-panel.jsx +32 -10
  67. package/apps/integration-client/ui-icons.jsx +17 -0
  68. package/apps/integration-client/usage-explorer.jsx +43 -0
  69. package/apps/integration-client/usage-report.mjs +71 -0
  70. package/apps/integration-client/usage.css +34 -0
  71. package/apps/integration-client/web-panel-model.mjs +140 -0
  72. package/apps/integration-client/web-panel-page.jsx +221 -0
  73. package/apps/integration-client/web-panel-pins-live.jsx +28 -0
  74. package/apps/integration-client/web-panel.css +139 -0
  75. package/apps/integration-client/workspace-model.mjs +67 -0
  76. package/apps/integration-client/workspace-navigation.mjs +56 -0
  77. package/apps/integration-client/workspace-ui.jsx +173 -0
  78. package/apps/integration-client/workspace.css +332 -0
  79. package/modules/bot-runtime/SOURCE.json +176 -50
  80. package/modules/bot-runtime/index.mjs +169 -13
  81. package/modules/bot-runtime/product-overlay/OVERLAY.json +128 -2
  82. package/modules/bot-runtime/product-overlay/base/src/client/header.js +244 -0
  83. package/modules/bot-runtime/product-overlay/base/src/client/learning-card.js +202 -0
  84. package/modules/bot-runtime/product-overlay/base/src/client/model-menu.js +371 -0
  85. package/modules/bot-runtime/product-overlay/base/src/client/secret-card.js +363 -0
  86. package/modules/bot-runtime/product-overlay/base/src/client/sources.js +68 -0
  87. package/modules/bot-runtime/product-overlay/base/src/client/turn-error.js +260 -0
  88. package/modules/bot-runtime/product-overlay/base/src/host/channel.js +647 -0
  89. package/modules/bot-runtime/product-overlay/base/src/host/memory.js +2050 -0
  90. package/modules/bot-runtime/product-overlay/base/src/host/models.js +314 -0
  91. package/modules/bot-runtime/product-overlay/base/src/host/parts.js +1473 -0
  92. package/modules/bot-runtime/product-overlay/base/src/host/privacy.js +368 -0
  93. package/modules/bot-runtime/product-overlay/base/src/host/roster.js +776 -0
  94. package/modules/bot-runtime/product-overlay/base/src/host/store.js +512 -0
  95. package/modules/bot-runtime/product-overlay/base/src/host/usage.js +653 -0
  96. package/modules/bot-runtime/product-overlay/patches/src/client/details-drawer.js.patch +48 -2
  97. package/modules/bot-runtime/product-overlay/patches/src/client/header.js.patch +41 -0
  98. package/modules/bot-runtime/product-overlay/patches/src/client/index.js.patch +33 -1
  99. package/modules/bot-runtime/product-overlay/patches/src/client/learning-card.js.patch +20 -0
  100. package/modules/bot-runtime/product-overlay/patches/src/client/model-menu.js.patch +24 -0
  101. package/modules/bot-runtime/product-overlay/patches/src/client/secret-card.js.patch +25 -0
  102. package/modules/bot-runtime/product-overlay/patches/src/client/sources.js.patch +52 -0
  103. package/modules/bot-runtime/product-overlay/patches/src/client/turn-error.js.patch +23 -0
  104. package/modules/bot-runtime/product-overlay/patches/src/host/channel.js.patch +46 -0
  105. package/modules/bot-runtime/product-overlay/patches/src/host/memory.js.patch +11 -0
  106. package/modules/bot-runtime/product-overlay/patches/src/host/models.js.patch +16 -0
  107. package/modules/bot-runtime/product-overlay/patches/src/host/parts.js.patch +95 -0
  108. package/modules/bot-runtime/product-overlay/patches/src/host/privacy.js.patch +11 -0
  109. package/modules/bot-runtime/product-overlay/patches/src/host/roster.js.patch +145 -0
  110. package/modules/bot-runtime/product-overlay/patches/src/host/store.js.patch +68 -0
  111. package/modules/bot-runtime/product-overlay/patches/src/host/usage.js.patch +11 -0
  112. package/modules/bot-runtime/read-model.mjs +19 -4
  113. package/modules/bot-runtime/vendor/ds-bot/src/client/details-drawer.js +15 -5
  114. package/modules/bot-runtime/vendor/ds-bot/src/client/header.js +9 -2
  115. package/modules/bot-runtime/vendor/ds-bot/src/client/index.js +9 -2
  116. package/modules/bot-runtime/vendor/ds-bot/src/client/learning-card.js +2 -2
  117. package/modules/bot-runtime/vendor/ds-bot/src/client/model-menu.js +5 -3
  118. package/modules/bot-runtime/vendor/ds-bot/src/client/secret-card.js +3 -3
  119. package/modules/bot-runtime/vendor/ds-bot/src/client/sources.js +25 -2
  120. package/modules/bot-runtime/vendor/ds-bot/src/client/turn-error.js +3 -2
  121. package/modules/bot-runtime/vendor/ds-bot/src/host/channel.js +14 -2
  122. package/modules/bot-runtime/vendor/ds-bot/src/host/memory.js +1 -1
  123. package/modules/bot-runtime/vendor/ds-bot/src/host/models.js +7 -0
  124. package/modules/bot-runtime/vendor/ds-bot/src/host/parts.js +26 -9
  125. package/modules/bot-runtime/vendor/ds-bot/src/host/privacy.js +1 -1
  126. package/modules/bot-runtime/vendor/ds-bot/src/host/roster.js +112 -3
  127. package/modules/bot-runtime/vendor/ds-bot/src/host/store.js +34 -1
  128. package/modules/bot-runtime/vendor/ds-bot/src/host/usage.js +1 -1
  129. package/modules/independent-runtime/index.mjs +152 -62
  130. package/modules/independent-runtime/remote-tools.mjs +8 -5
  131. package/modules/openmaus-protocol/NOTICE +10 -0
  132. package/modules/openmaus-protocol/README.md +15 -0
  133. package/modules/openmaus-protocol/SOURCE.json +68 -0
  134. package/modules/openmaus-protocol/dist/protocol.mjs +1203 -0
  135. package/modules/openmaus-protocol/index.mjs +1 -0
  136. package/modules/openmaus-protocol/transport.mjs +77 -0
  137. package/modules/openmaus-protocol/vendor/LICENSE +202 -0
  138. package/modules/openmaus-protocol/vendor/companion/src/e2e/README.md +405 -0
  139. package/modules/openmaus-protocol/vendor/companion/src/e2e/credentials.ts +128 -0
  140. package/modules/openmaus-protocol/vendor/companion/src/e2e/descriptor.ts +84 -0
  141. package/modules/openmaus-protocol/vendor/companion/src/e2e/noise.ts +456 -0
  142. package/modules/openmaus-protocol/vendor/companion/src/e2e/phone.ts +104 -0
  143. package/modules/openmaus-protocol/vendor/companion/src/e2e/session.ts +417 -0
  144. package/modules/openmaus-protocol/vendor/companion/src/e2e/vectors/v1.json +2565 -0
  145. package/modules/openmaus-protocol/vendor/companion/src/e2e/vectors/v1.sha256 +1 -0
  146. package/modules/openmaus-protocol/vendor/companion/src/e2e/yamux.ts +335 -0
  147. package/package.json +18 -6
  148. package/packages/bot-acp/README.md +156 -0
  149. package/packages/bot-acp/licenses/LICENSE-OpenMausBot +202 -0
  150. package/packages/bot-acp/licenses/NOTICE.md +27 -0
  151. package/packages/bot-acp/src/acp-adapter.mjs +795 -0
  152. package/packages/bot-acp/src/acp-host.mjs +148 -0
  153. package/packages/bot-acp/src/native-launch.mjs +121 -0
  154. package/packages/bot-acp/src/permission-policy.mjs +283 -0
  155. package/packages/bot-acp/src/rpc-codec.mjs +265 -0
  156. package/packages/bot-acp/src/session-core.mjs +581 -0
  157. package/packages/bot-acp/src/stdio-rpc.mjs +329 -0
  158. package/packages/bot-engines/README.md +281 -0
  159. package/packages/bot-engines/licenses/LICENSE-OpenMausBot +202 -0
  160. package/packages/bot-engines/licenses/NOTICE.md +32 -0
  161. package/packages/bot-engines/src/claude-engine.mjs +772 -0
  162. package/packages/bot-engines/src/claude-llm-adapter.mjs +797 -0
  163. package/packages/bot-engines/src/claude-llm-turn.mjs +292 -0
  164. package/packages/bot-engines/src/claude-permission-broker.mjs +130 -0
  165. package/packages/bot-engines/src/claude-permission-proxy.mjs +87 -0
  166. package/packages/bot-engines/src/claude-protocol.mjs +177 -0
  167. package/packages/bot-engines/src/driver-catalog.mjs +334 -0
  168. package/packages/bot-engines/src/host-loop-request.mjs +95 -0
  169. package/packages/bot-engines/src/host-registrations.mjs +105 -0
  170. package/packages/capability-broker/src/cli-bootstrap.mjs +86 -16
  171. package/packages/capability-broker/src/cli-bridge-response.mjs +80 -0
  172. package/packages/capability-broker/src/cli-stdio-bridge.mjs +21 -8
  173. package/packages/cli-runtime/src/codex-session-core.mjs +4 -0
  174. package/packages/cli-runtime/src/native-cli-output.mjs +57 -0
  175. package/packages/cli-runtime/src/native-peer.ps1 +51 -3
  176. package/packages/cli-runtime/src/native-process.mjs +77 -14
  177. package/packages/model-router-plugin/package.json +1 -1
  178. package/packages/orchestration/src/binding-product.mjs +19 -0
  179. package/packages/orchestration/src/bot-data-actions.mjs +45 -0
  180. package/packages/orchestration/src/bot-data-chart.mjs +109 -0
  181. package/packages/orchestration/src/bot-data-context.mjs +44 -0
  182. package/packages/orchestration/src/bot-data-engine.mjs +809 -0
  183. package/packages/orchestration/src/bot-data-io.mjs +186 -0
  184. package/packages/orchestration/src/bot-data-sql.mjs +195 -0
  185. package/packages/orchestration/src/bot-data-surface.mjs +144 -0
  186. package/packages/orchestration/src/bot-data-tools.mjs +68 -0
  187. package/packages/orchestration/src/bot-data-worker.mjs +228 -0
  188. package/packages/orchestration/src/bot-independent-execution.mjs +195 -0
  189. package/packages/orchestration/src/bot-independent-stream.mjs +74 -0
  190. package/packages/orchestration/src/bot-loop.mjs +152 -19
  191. package/packages/orchestration/src/bot-notifications.mjs +159 -0
  192. package/packages/orchestration/src/bot-policy.mjs +43 -4
  193. package/packages/orchestration/src/bot-profile.mjs +171 -0
  194. package/packages/orchestration/src/bot-routine.mjs +4 -4
  195. package/packages/orchestration/src/bot-runtime-assembly.mjs +255 -8
  196. package/packages/orchestration/src/bot-runtime-switch.mjs +13 -2
  197. package/packages/orchestration/src/bot-serving.mjs +164 -0
  198. package/packages/orchestration/src/bot-session-store.mjs +105 -9
  199. package/packages/orchestration/src/bot-settings.mjs +50 -11
  200. package/packages/orchestration/src/bot-thread-admission.mjs +84 -0
  201. package/packages/orchestration/src/bot-thread-host.mjs +187 -0
  202. package/packages/orchestration/src/bot-threads.mjs +790 -0
  203. package/packages/orchestration/src/data-product-access.mjs +37 -0
  204. package/packages/orchestration/src/data-tool-contract.mjs +291 -0
  205. package/packages/orchestration/src/desktop-http-carrier.mjs +120 -0
  206. package/packages/orchestration/src/desktop-proxy.mjs +311 -0
  207. package/packages/orchestration/src/desktop-sessions.mjs +43 -9
  208. package/packages/orchestration/src/ds-lifecycle.mjs +31 -4
  209. package/packages/orchestration/src/grant-refresh-queue.mjs +17 -0
  210. package/packages/orchestration/src/independent-chat-page.mjs +39 -0
  211. package/packages/orchestration/src/independent-chat-service.mjs +308 -0
  212. package/packages/orchestration/src/independent-context-state.mjs +44 -0
  213. package/packages/orchestration/src/independent-message-wire.mjs +84 -0
  214. package/packages/orchestration/src/independent-tool-catalog.mjs +175 -0
  215. package/packages/orchestration/src/independent-tool-families.mjs +73 -0
  216. package/packages/orchestration/src/independent-tool-host.mjs +344 -0
  217. package/packages/orchestration/src/main-bot-grant.mjs +15 -0
  218. package/packages/orchestration/src/main-model-routes.mjs +208 -0
  219. package/packages/orchestration/src/model-accounting.mjs +99 -35
  220. package/packages/orchestration/src/model-auxiliary-dispatch.mjs +187 -0
  221. package/packages/orchestration/src/model-loop-frame.mjs +179 -0
  222. package/packages/orchestration/src/model-prepared-generation.mjs +175 -0
  223. package/packages/orchestration/src/model-request-bounds.mjs +111 -0
  224. package/packages/orchestration/src/native-activity-contract.mjs +491 -0
  225. package/packages/orchestration/src/native-activity-service.mjs +102 -0
  226. package/packages/orchestration/src/native-activity-store.mjs +249 -0
  227. package/packages/orchestration/src/native-conversation-tools.mjs +78 -0
  228. package/packages/orchestration/src/native-data-tools.mjs +100 -0
  229. package/packages/orchestration/src/native-remote-actions.mjs +742 -0
  230. package/packages/orchestration/src/native-team-tools.mjs +73 -0
  231. package/packages/orchestration/src/pairing-invite.mjs +37 -0
  232. package/packages/orchestration/src/product-composition.mjs +1559 -1001
  233. package/packages/orchestration/src/remote-machines.mjs +82 -14
  234. package/packages/orchestration/src/routine-execution.mjs +5 -3
  235. package/packages/orchestration/src/routine-session.mjs +19 -13
  236. package/packages/orchestration/src/secure-pairing-host.mjs +112 -0
  237. package/packages/orchestration/src/task-journal.mjs +29 -0
  238. package/packages/orchestration/src/task-product.mjs +17 -0
  239. package/packages/orchestration/src/team-assignment-store.mjs +120 -0
  240. package/packages/orchestration/src/team-bridge.mjs +282 -0
  241. package/packages/orchestration/src/team-scheduler.mjs +83 -0
  242. package/packages/orchestration/src/team-sdk-tools.mjs +84 -0
  243. package/packages/orchestration/src/team-tool-contract.mjs +284 -0
  244. package/packages/orchestration/src/ui-host-namespace.mjs +23 -0
  245. package/packages/orchestration/src/web-panel-actions.mjs +103 -0
  246. package/packages/orchestration/src/web-panel-framing.mjs +227 -0
  247. package/packages/orchestration/src/web-panel-store.mjs +206 -0
  248. package/remote-computer-agent/README.md +39 -29
  249. package/remote-computer-agent/build.mjs +3 -0
  250. package/remote-computer-agent/dist/OPENMAUSBOT_LICENSE +202 -0
  251. package/remote-computer-agent/dist/OPENMAUSBOT_NOTICE +10 -0
  252. package/remote-computer-agent/dist/OPENMAUSBOT_SOURCE.json +68 -0
  253. package/remote-computer-agent/dist/cli-stdio-bridge.mjs +215 -25
  254. package/remote-computer-agent/dist/cli-stdio-bridge.mjs.map +4 -4
  255. package/remote-computer-agent/dist/cli.mjs +1688 -168
  256. package/remote-computer-agent/dist/cli.mjs.map +4 -4
  257. package/remote-computer-agent/dist/index.mjs +1579 -122
  258. package/remote-computer-agent/dist/index.mjs.map +4 -4
  259. package/remote-computer-agent/dist/native-peer.ps1 +51 -3
  260. package/remote-computer-agent/package-lock.json +308 -2
  261. package/remote-computer-agent/package.json +2 -1
  262. package/remote-computer-agent/pair-device.ps1 +20 -0
  263. package/remote-computer-agent/setup.ps1 +38 -16
  264. package/remote-computer-agent/src/cli.ts +24 -3
  265. package/remote-computer-agent/src/desktop-session.ts +11 -3
  266. package/remote-computer-agent/src/e2e-server.ts +81 -0
  267. package/remote-computer-agent/src/pairing-page.ts +35 -0
  268. package/remote-computer-agent/src/protocol.ts +25 -25
  269. package/remote-computer-agent/src/secure-pairing.ts +105 -0
  270. package/remote-computer-agent/src/store.ts +20 -5
  271. package/remote-computer-agent/src/transport.ts +39 -15
@@ -1,12 +1,69 @@
1
1
  import { spawn } from 'node:child_process'
2
2
  import { EventEmitter } from 'node:events'
3
3
  import { StringDecoder } from 'node:string_decoder'
4
- import { access, realpath } from 'node:fs/promises'
5
- import { isAbsolute, join } from 'node:path'
4
+ import { access, lstat, readFile, readdir, realpath, rmdir, unlink } from 'node:fs/promises'
5
+ import { lstatSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, writeFileSync } from 'node:fs'
6
+ import { randomBytes } from 'node:crypto'
7
+ import { tmpdir } from 'node:os'
8
+ import { basename, dirname, isAbsolute, join } from 'node:path'
6
9
  import { fileURLToPath } from 'node:url'
10
+ import { NativeCliOutput } from './native-cli-output.mjs'
7
11
 
8
12
  const HERE = fileURLToPath(new URL('.', import.meta.url))
9
13
  const MAX_FRAME = 262_144
14
+ const COMPILER_ROOT = 'DSH_NATIVE_COMPILER_ROOT'
15
+ const COMPILER_SCRATCH = 'DSH_NATIVE_COMPILER_SCRATCH'
16
+ // Capture only the trusted Host launch environment, never a model's spec or an
17
+ // env argument. A packaged bridge inherits this one non-secret root hint so its
18
+ // compiler does not start a new root beneath an ever-deeper private TEMP.
19
+ const inheritedCompilerRoot = process.platform === 'win32' ? process.env[COMPILER_ROOT] : undefined
20
+ const hostTemp = process.platform === 'win32' ? tmpdir() : null
21
+ let compilerRoot = null
22
+ const compilerFailure = () => Object.assign(new Error('NATIVE_COMPILER_SCRATCH_UNAVAILABLE'), { code: 'NATIVE_COMPILER_SCRATCH_UNAVAILABLE' })
23
+ const sameDirectory = (info, expected) => info.isDirectory() && !info.isSymbolicLink() && info.dev === expected.dev && info.ino === expected.ino
24
+ const rootStamp = path => `dsh-native-compiler-v1:${basename(path)}\n`
25
+
26
+ function compilerDirectory() {
27
+ try {
28
+ if (!compilerRoot) {
29
+ if (inheritedCompilerRoot !== undefined) {
30
+ if (!isAbsolute(inheritedCompilerRoot) || inheritedCompilerRoot.length > 140 || !/^dshc-[a-f0-9]{16}$/.test(basename(inheritedCompilerRoot))) throw compilerFailure()
31
+ const info = lstatSync(inheritedCompilerRoot, { bigint: true })
32
+ if (!info.isDirectory() || info.isSymbolicLink() || realpathSync(inheritedCompilerRoot) !== inheritedCompilerRoot || readFileSync(join(inheritedCompilerRoot, '.dsh-root'), 'utf8') !== rootStamp(inheritedCompilerRoot)) throw compilerFailure()
33
+ compilerRoot = { path: inheritedCompilerRoot, info }
34
+ } else {
35
+ const parent = realpathSync(hostTemp)
36
+ const path = join(parent, `dshc-${randomBytes(8).toString('hex')}`)
37
+ if (path.length > 140) throw compilerFailure()
38
+ mkdirSync(path)
39
+ writeFileSync(join(path, '.dsh-root'), rootStamp(path), { flag: 'wx' })
40
+ compilerRoot = { path, info: lstatSync(path, { bigint: true }) }
41
+ }
42
+ }
43
+ if (!sameDirectory(lstatSync(compilerRoot.path, { bigint: true }), compilerRoot.info) || realpathSync(compilerRoot.path) !== compilerRoot.path) throw compilerFailure()
44
+ const path = mkdtempSync(join(compilerRoot.path, 'c-'))
45
+ const info = lstatSync(path, { bigint: true }), owner = randomBytes(16).toString('hex')
46
+ writeFileSync(join(path, '.dsh-owner'), owner, { flag: 'wx' })
47
+ const root = compilerRoot
48
+ // Never recursively remove a path obtained from the environment. Only this
49
+ // allocated child, after confirmed helper exit, with unchanged filesystem
50
+ // identity and no links/subdirectories, is eligible for flat cleanup.
51
+ const cleanup = async () => {
52
+ try {
53
+ if (dirname(path) !== root.path || !/^c-[A-Za-z0-9]{6}$/.test(basename(path))) return false
54
+ if (!sameDirectory(await lstat(root.path, { bigint: true }), root.info) || await realpath(root.path) !== root.path) return false
55
+ if (!sameDirectory(await lstat(path, { bigint: true }), info) || await realpath(path) !== path || await readFile(join(path, '.dsh-owner'), 'utf8') !== owner) return false
56
+ const names = await readdir(path)
57
+ if (names.length > 128) return false
58
+ for (const name of names) { const entry = await lstat(join(path, name)); if (!entry.isFile() || entry.isSymbolicLink()) return false }
59
+ for (const name of names) await unlink(join(path, name))
60
+ await rmdir(path)
61
+ return true
62
+ } catch { return false } // Busy, replaced or unknown resources remain.
63
+ }
64
+ return { root: root.path, path, cleanup }
65
+ } catch { throw compilerFailure() }
66
+ }
10
67
 
11
68
  /** Deliberately small environment: profiles, credentials and proxy secrets are never inherited. */
12
69
  export function privateEnvironment(home, source = process.env) {
@@ -17,6 +74,7 @@ export function privateEnvironment(home, source = process.env) {
17
74
  for (const key of ['SystemRoot', 'windir', 'ComSpec', 'LANG', 'LC_ALL']) if (source[key]) env[key] = source[key]
18
75
  // Fixed executable paths remove PATH lookup from both supervisor and bridge.
19
76
  env.PATH = process.platform === 'win32' ? join(source.SystemRoot ?? 'C:\\Windows', 'System32') : '/usr/bin:/bin'
77
+ if (process.platform === 'win32' && (compilerRoot?.path ?? inheritedCompilerRoot)) env[COMPILER_ROOT] = compilerRoot?.path ?? inheritedCompilerRoot
20
78
  return env
21
79
  }
22
80
 
@@ -35,30 +93,35 @@ export async function resolveNativeHelper({ python = '/usr/bin/python3' } = {})
35
93
  export function nativeProcess(helper, mode, spec, { home, env = privateEnvironment(home) } = {}) {
36
94
  const events = new EventEmitter()
37
95
  const args = helper.platform === 'win32' ? [...helper.prefix, '-Mode', mode] : [...helper.prefix, mode]
38
- const child = spawn(helper.executable, args, { cwd: home, env, windowsHide: true, shell: false, stdio: ['pipe', 'pipe', 'pipe'] })
39
- let tail = '', buffer = '', bytes = 0, closed = false
96
+ const compiler = helper.platform === 'win32' ? compilerDirectory() : null
97
+ const helperEnv = compiler ? Object.fromEntries(Object.entries(env).filter(([key]) => ![COMPILER_ROOT, COMPILER_SCRATCH].includes(key.toUpperCase()))) : env
98
+ if (compiler) { helperEnv[COMPILER_ROOT] = compiler.root; helperEnv[COMPILER_SCRATCH] = compiler.path }
99
+ const child = spawn(helper.executable, args, { cwd: home, env: helperEnv, windowsHide: true, shell: false, stdio: ['pipe', 'pipe', 'pipe'] })
100
+ let tail = '', buffer = '', bytes = 0, closed = false, treeStopped = false
40
101
  const decoder = new StringDecoder('utf8'), cliDecoder = new StringDecoder('utf8')
41
- let cliBuffer = ''
102
+ const cliOutput = new NativeCliOutput()
42
103
  const frame = value => {
104
+ if (mode === 'supervise' && value.control === 'stopped' && value.treeStopped === true) treeStopped = true
43
105
  if (mode === 'supervise' && value.type === 'cli-output') {
44
106
  if (typeof value.data !== 'string' || value.data.length > MAX_FRAME * 2) throw new Error('INVALID_CLI_FRAME')
45
- cliBuffer += cliDecoder.write(Buffer.from(value.data, 'base64'))
46
- if (Buffer.byteLength(cliBuffer) > MAX_FRAME) throw new Error('CLI_FRAME_LIMIT')
47
- let end
48
- while ((end = cliBuffer.indexOf('\n')) >= 0) {
49
- const line = cliBuffer.slice(0, end); cliBuffer = cliBuffer.slice(end + 1)
50
- if (line.trim()) events.emit('message', JSON.parse(line))
51
- }
107
+ for (const message of cliOutput.push(cliDecoder.write(Buffer.from(value.data, 'base64')))) events.emit('message', message)
52
108
  } else events.emit(value.control ? 'control' : 'message', value)
53
109
  }
54
- const exit = new Promise(resolve => child.once('close', (code, signal) => { closed = true; events.emit('closed', { code, signal }); resolve({ code, signal }) }))
110
+ const exit = new Promise(resolve => child.once('close', async (code, signal) => {
111
+ closed = true
112
+ if (compiler && code === 0 && signal === null && (mode !== 'supervise' || treeStopped)) await compiler.cleanup()
113
+ events.emit('closed', { code, signal }); resolve({ code, signal })
114
+ }))
55
115
  child.on('error', error => events.emit('failure', error))
56
116
  child.stdin.on('error', () => {})
57
117
  child.stderr.on('data', data => { tail = (tail + data.toString('utf8')).slice(-4096) })
58
118
  child.stdout.on('data', chunk => {
59
119
  bytes += chunk.length
60
120
  buffer += decoder.write(chunk)
61
- if (bytes > 8 * 1024 * 1024 || Buffer.byteLength(buffer) > MAX_FRAME) { events.emit('failure', new Error('OUTPUT_LIMIT')); child.stdin.end(); return }
121
+ // MCP responses and CLI image echoes have their own bounded readers. Their
122
+ // retained connections can carry several screenshots without a raw lifetime cap.
123
+ const boundedStream = mode === 'client' || mode === 'server' || mode === 'supervise'
124
+ if (!boundedStream && bytes > 8 * 1024 * 1024 || Buffer.byteLength(buffer) > MAX_FRAME) { events.emit('failure', new Error('OUTPUT_LIMIT')); child.stdin.end(); return }
62
125
  let end
63
126
  while ((end = buffer.indexOf('\n')) >= 0) {
64
127
  const line = buffer.slice(0, end); buffer = buffer.slice(end + 1)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ljwei-stak/dsh-model-router",
3
- "version": "0.66.4",
3
+ "version": "0.67.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -0,0 +1,19 @@
1
+ const invalid = () => { throw Object.assign(new Error('请选择当前团队中的 Bot。'), { code: 'INVALID_BINDING_OWNER' }) }
2
+
3
+ /** A bounded owner view for chat settings; it never reads task inputs or receipts. */
4
+ export async function inspectProductBinding({ runtime, lifecycle, botSettings, fundingAccounts, signal }, payload) {
5
+ if (!payload || typeof payload !== 'object' || Array.isArray(payload) || Object.keys(payload).some(key => key !== 'botId') || typeof payload.botId !== 'string') invalid()
6
+ signal?.throwIfAborted()
7
+ await runtime.load()
8
+ signal?.throwIfAborted()
9
+ const bot = lifecycle.committedBot(payload.botId)
10
+ if (!bot) invalid()
11
+ const main = lifecycle.committedMainBotIds?.().includes(bot.id) === true
12
+ const record=botSettings.get(bot.id)
13
+ const grant=main?lifecycle.committedGrant?.(bot.id):null
14
+ return { schemaVersion: 1, bot: { id: bot.id, name: bot.name, role: bot.role ?? '', model: bot.model ?? null,
15
+ main, permissions: main ? 'full-control' : 'scoped',
16
+ appliedModel: typeof bot.appliedModel === 'string' ? bot.appliedModel : null },
17
+ record: grant?{...record,grant}:record, accounts: { status: 'available', items: fundingAccounts?.catalog() ?? [] },
18
+ availableActions: ['binding.save', 'funding.account.save'] }
19
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * The panel-facing data actions. The human signs in as owner and picks which
3
+ * Bot's data to view; the read-model's dispatch already requires an
4
+ * authenticated owner and an allow-listed action, so these handlers only map
5
+ * payloads onto the engine. A Bot id is still validated by the engine (never a
6
+ * path, another service or an endpoint), and every failure is a structured
7
+ * DataError the panel can render instead of a silent empty state.
8
+ *
9
+ * Wire these into product-composition's `actions` and add their names to the
10
+ * read-model ACTIONS allow-list — see data-wiring.patch.
11
+ *
12
+ * Interface notes for the panel:
13
+ * - `data.show` takes `{ kind, table|sql, cardId? }`. With `cardId` it re-opens
14
+ * a SAVED card: the chart is re-rendered from its saved spec and the table
15
+ * from its saved result, so a chart card can be reopened (its id is a card
16
+ * id, never a table name).
17
+ * - `data.export` fails loudly: a library write that fails returns a structured
18
+ * error (output_too_large for the library's single-file limit) and NO path,
19
+ * so the panel must not report a completed export.
20
+ * - `data.cancel` reaches the Host and SIGKILLs the Bot's worker; it is a stop
21
+ * REQUEST, and the in-flight call fails with `cancelled`.
22
+ */
23
+
24
+ import { DataFailure } from './bot-data-surface.mjs'
25
+
26
+ const errorOf = error => (error instanceof DataFailure ? error.error : { code: 'engine_unavailable', message: String(error?.message ?? error) })
27
+
28
+ /** @param {{ engine: object }} source */
29
+ export function createDataActions({ engine } = {}) {
30
+ if (!engine || typeof engine.forBot !== 'function') throw new TypeError('DATA_ACTIONS_REQUIRE_ENGINE')
31
+ const wrap = run => async payload => { try { return await run(payload) } catch (error) { return { error: errorOf(error) } } }
32
+ const bot = payload => engine.forBot(payload?.botId)
33
+
34
+ return Object.freeze({
35
+ 'data.catalog': wrap(payload => bot(payload).catalog()),
36
+ 'data.load': wrap(payload => bot(payload).load(payload)),
37
+ 'data.describe': wrap(payload => bot(payload).describe(payload?.target)),
38
+ 'data.sql': wrap(payload => bot(payload).sql(payload)),
39
+ 'data.show': wrap(payload => bot(payload).show(payload)),
40
+ 'data.page': wrap(payload => bot(payload).page(payload)),
41
+ 'data.export': wrap(payload => bot(payload).exportCsv(payload)),
42
+ 'data.remove': wrap(payload => bot(payload).remove(payload)),
43
+ 'data.cancel': wrap(payload => bot(payload).cancel()),
44
+ })
45
+ }
@@ -0,0 +1,109 @@
1
+ /**
2
+ * The chart compiler: a tiny, safe spec the model can ask for, compiled to a
3
+ * bounded SQL aggregation and then shaped into a declarative result the panel
4
+ * renders as inline SVG. The model never writes a chart grammar and never
5
+ * writes raw SQL for a chart — only {type,x,y,color,agg,…} with column names
6
+ * that must already exist. Identifiers are quoted; values are never
7
+ * concatenated into the SQL.
8
+ *
9
+ * Supported marks: bar, line, area (the required minimum). scatter, histogram,
10
+ * pie and heatmap are intentionally refused for now rather than faked — see
11
+ * data-report.md. Aggregations count/sum/avg/min/max are supported; median is
12
+ * refused (SQLite has no median aggregate) rather than approximated silently.
13
+ *
14
+ * Ported and narrowed from OpenMausBot server/data/chart-compiler.ts (1bc4749).
15
+ */
16
+
17
+ import { DATA_LIMITS, DataFailure, dataError, quoteIdent } from './bot-data-surface.mjs'
18
+
19
+ const fail = (code, message, extra = {}) => { throw new DataFailure(dataError(code, message, extra)) }
20
+
21
+ const MARKS = new Set(['bar', 'line', 'area'])
22
+ const AGGS = new Set(['count', 'sum', 'avg', 'min', 'max'])
23
+ const SORTS = new Set(['x', '-x', 'y', '-y'])
24
+ const TIME_FORMAT = { year: '%Y', quarter: null, month: '%Y-%m', week: '%Y-W%W', day: '%Y-%m-%d', hour: '%Y-%m-%d %H' }
25
+
26
+ /** Validate the spec against the table's real columns; throw spec_invalid otherwise. */
27
+ function validate(spec, columns) {
28
+ if (!spec || typeof spec !== 'object') fail('spec_invalid', 'A chart spec object is required.')
29
+ if (!MARKS.has(spec.type)) fail('spec_invalid', `Chart type ${JSON.stringify(spec.type)} is not supported yet. Supported: bar, line, area.`)
30
+ if (typeof spec.x !== 'string' || !columns.includes(spec.x)) fail('spec_invalid', `Unknown x column ${JSON.stringify(spec.x)}. Use data_describe to list columns.`)
31
+ if (spec.y !== undefined && (typeof spec.y !== 'string' || !columns.includes(spec.y))) fail('spec_invalid', `Unknown y column ${JSON.stringify(spec.y)}. Use data_describe to list columns.`)
32
+ if (spec.color !== undefined && (typeof spec.color !== 'string' || !columns.includes(spec.color))) fail('spec_invalid', `Unknown color column ${JSON.stringify(spec.color)}.`)
33
+ const agg = spec.agg ?? (spec.y ? 'sum' : 'count')
34
+ if (!AGGS.has(agg)) fail('spec_invalid', `Aggregation ${JSON.stringify(agg)} is not supported. Supported: ${[...AGGS].join(', ')}.`)
35
+ if (spec.sort !== undefined && !SORTS.has(spec.sort)) fail('spec_invalid', `Unknown sort ${JSON.stringify(spec.sort)}.`)
36
+ if (spec.timeUnit !== undefined && !(spec.timeUnit in TIME_FORMAT)) fail('spec_invalid', `Unknown timeUnit ${JSON.stringify(spec.timeUnit)}.`)
37
+ if (spec.timeUnit === 'quarter' && !spec.y) fail('spec_invalid', 'A quarter bucket needs an aggregation (set y and agg).')
38
+ return { agg }
39
+ }
40
+
41
+ /** Build the aggregation SQL and a reduction description. `from` is the final SQL relation (a quoted identifier or a parenthesised subquery); spec columns are quoted here, never concatenated raw. */
42
+ export function compileChart(spec, columns, from) {
43
+ const { agg } = validate(spec, columns)
44
+ const limit = Math.min(Math.max(1, Math.trunc(spec.limit ?? 20)), 1000)
45
+ const hasColor = spec.color !== undefined
46
+ const groupParts = []
47
+ const selectParts = []
48
+
49
+ // x expression: raw column, or a time bucket when timeUnit is set.
50
+ let xExpr
51
+ if (spec.timeUnit) {
52
+ const format = TIME_FORMAT[spec.timeUnit]
53
+ xExpr = spec.timeUnit === 'quarter'
54
+ ? `(strftime('%Y', ${quoteIdent(spec.x)}) || '-Q' || ((CAST(strftime('%m', ${quoteIdent(spec.x)}) AS INTEGER) + 2) / 3))`
55
+ : `strftime(${`'${format}'`}, ${quoteIdent(spec.x)})`
56
+ groupParts.push(xExpr)
57
+ selectParts.push(`${xExpr} AS x`)
58
+ } else {
59
+ groupParts.push(quoteIdent(spec.x))
60
+ selectParts.push(`${quoteIdent(spec.x)} AS x`)
61
+ }
62
+
63
+ // y expression: COUNT(*) or AGG(y).
64
+ const yExpr = agg === 'count' || !spec.y ? 'COUNT(*)' : `${agg.toUpperCase()}(${quoteIdent(spec.y)})`
65
+ selectParts.push(`${yExpr} AS y`)
66
+
67
+ if (hasColor) { groupParts.push(quoteIdent(spec.color)); selectParts.push(`${quoteIdent(spec.color)} AS series`) }
68
+
69
+ let orderBy
70
+ switch (spec.sort) {
71
+ case '-x': orderBy = 'x DESC'; break
72
+ case 'y': orderBy = 'y ASC'; break
73
+ case '-y': orderBy = 'y DESC'; break
74
+ default: orderBy = 'x ASC'
75
+ }
76
+ const sql = `SELECT ${selectParts.join(', ')} FROM ${from} GROUP BY ${groupParts.join(', ')} ORDER BY ${orderBy} LIMIT ${limit}`
77
+ const reduction = {
78
+ method: spec.timeUnit ? 'timeBucket' : 'group',
79
+ inputRows: null,
80
+ outputRows: null,
81
+ note: spec.timeUnit ? `Bucketed by ${spec.timeUnit}.` : `Grouped by ${spec.x}${hasColor ? ` and ${spec.color}` : ''}, ${agg}${spec.y ? ` of ${spec.y}` : ''}. Top ${limit} by ${orderBy}.`,
82
+ }
83
+ return { sql, xLabel: spec.x, yLabel: spec.y ?? 'count', reduction, hasColor }
84
+ }
85
+
86
+ /** Shape a bounded result (columns + rows) into a declarative chart the panel renders. */
87
+ export function shapeChart(result, spec) {
88
+ const hasColor = result.columns.some(column => column.name === 'series')
89
+ const seriesMap = new Map()
90
+ let maxMarks = DATA_LIMITS.chartMaxMarks
91
+ for (const row of result.rows) {
92
+ if (maxMarks-- <= 0) break
93
+ const x = row[0]
94
+ const y = row[1]
95
+ const key = hasColor ? String(row[2]) : 'series'
96
+ if (!seriesMap.has(key)) seriesMap.set(key, [])
97
+ seriesMap.get(key).push({ x: x === null ? null : String(x), y: typeof y === 'number' ? y : Number(y) || 0 })
98
+ }
99
+ const series = [...seriesMap.entries()].map(([key, points]) => ({ key, points }))
100
+ return {
101
+ kind: 'chart',
102
+ type: spec.type,
103
+ xLabel: spec.x,
104
+ yLabel: spec.y ?? 'count',
105
+ stacked: spec.stack === true,
106
+ series,
107
+ truncated: result.truncated || maxMarks < 0,
108
+ }
109
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * The data context envelope (apps.data-context, P2): a metadata-only summary
3
+ * the Host can inject into a Bot's prompt so it knows what it can query,
4
+ * WITHOUT ever leaking row data. It lists table names, columns, types and row
5
+ * counts, plus saved card titles — never a single cell value.
6
+ *
7
+ * This is a pure function of the engine's catalog; the composition decides
8
+ * where to inject it (see data-wiring.patch). It is bounded so a Bot with many
9
+ * tables cannot bloat the prompt.
10
+ */
11
+
12
+ import { DATA_LIMITS } from './bot-data-surface.mjs'
13
+
14
+ const TABLES_MAX = 25
15
+ const COLUMNS_MAX = 20
16
+
17
+ /**
18
+ * @param {object} engine
19
+ * @param {string} botId
20
+ * @returns {Promise<{ tables: Array<{name:string,rowCount?:number,columns:string[]}>, cards: Array<{id:string,title:string,kind:string}> }>}
21
+ */
22
+ export async function buildDataContext(engine, botId) {
23
+ const catalog = await engine.forBot(botId).catalog()
24
+ return {
25
+ tables: catalog.tables.slice(0, TABLES_MAX).map(table => ({
26
+ name: table.name,
27
+ columns: table.columns.slice(0, COLUMNS_MAX).map(column => `${column.name} ${column.type}`.trim()),
28
+ columnCount: table.columns.length,
29
+ })),
30
+ cards: catalog.cards.slice(0, DATA_LIMITS.sheetCardsMax).map(card => ({ id: card.id, title: card.title, kind: card.kind })),
31
+ }
32
+ }
33
+
34
+ /** Render the envelope as compact prompt text. Metadata only — no cell values. */
35
+ export function renderDataContext(context) {
36
+ if (!context || !context.tables?.length) return ''
37
+ const lines = ['You have data tables you can query with data_describe, data_sql, data_show and data_export (metadata only; no rows are shown here):']
38
+ for (const table of context.tables) {
39
+ const columns = table.columns.length ? `: ${table.columns.join(', ')}` : ''
40
+ lines.push(`- ${table.name}${columns}`)
41
+ }
42
+ for (const card of context.cards ?? []) lines.push(`- saved ${card.kind} card "${card.title}" (${card.id})`)
43
+ return lines.join('\n')
44
+ }