create-walle 0.10.2 → 0.10.3

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 (488) hide show
  1. package/README.md +3 -1
  2. package/lib/release-schema.json +2 -2
  3. package/lib/runtime-closure-policy.json +8 -7
  4. package/package.json +1 -1
  5. package/template/coding-task-manager/api-prompts.js +45 -7
  6. package/template/coding-task-manager/bin/claude-hook.js +55 -1
  7. package/template/coding-task-manager/bin/ctm-relay-client.js +35 -12
  8. package/template/coding-task-manager/bin/land.js +2069 -0
  9. package/template/coding-task-manager/bin/memory-census.js +4 -2
  10. package/template/coding-task-manager/bin/memory-sync-verify.js +151 -0
  11. package/template/coding-task-manager/bin/probe-refusal-scope.js +530 -0
  12. package/template/coding-task-manager/db.js +156 -32
  13. package/template/coding-task-manager/lib/acp/acp-client.js +383 -0
  14. package/template/coding-task-manager/lib/acp/dsh-context-truth.js +176 -0
  15. package/template/coding-task-manager/lib/acp/dsh-launch-model.js +302 -0
  16. package/template/coding-task-manager/lib/acp/dsh-mcp-servers.js +194 -0
  17. package/template/coding-task-manager/lib/acp/dsh-prompt-lane.js +616 -0
  18. package/template/coding-task-manager/lib/acp/dsh-route-patch.js +308 -0
  19. package/template/coding-task-manager/lib/acp/dsh-session-runtime.js +522 -0
  20. package/template/coding-task-manager/lib/acp/dsh-transcript.js +395 -0
  21. package/template/coding-task-manager/lib/acp/dsh-usage-log.js +162 -0
  22. package/template/coding-task-manager/lib/acp/ndjson-stdio-transport.js +225 -0
  23. package/template/coding-task-manager/lib/adopted-host-redial.js +47 -11
  24. package/template/coding-task-manager/lib/adopted-launch-environment.js +123 -0
  25. package/template/coding-task-manager/lib/agent-auto-update-runtime.js +0 -3
  26. package/template/coding-task-manager/lib/agent-auto-update.js +26 -10
  27. package/template/coding-task-manager/lib/agent-bundle/build.js +657 -0
  28. package/template/coding-task-manager/lib/agent-bundle/codex-install.js +558 -0
  29. package/template/coding-task-manager/lib/agent-bundle/drift.js +120 -0
  30. package/template/coding-task-manager/lib/agent-bundle/gc.js +522 -0
  31. package/template/coding-task-manager/lib/agent-bundle/inventory.js +346 -0
  32. package/template/coding-task-manager/lib/agent-bundle/push.js +717 -0
  33. package/template/coding-task-manager/lib/agent-bundle/skill-transfer.js +724 -0
  34. package/template/coding-task-manager/lib/agent-bundle/spawn.js +119 -0
  35. package/template/coding-task-manager/lib/agent-bundle/store.js +568 -0
  36. package/template/coding-task-manager/lib/agent-capabilities.js +142 -12
  37. package/template/coding-task-manager/lib/agent-cli-cache.js +30 -5
  38. package/template/coding-task-manager/lib/agent-definitions.js +19 -0
  39. package/template/coding-task-manager/lib/agent-hooks-codex-toml.js +28 -16
  40. package/template/coding-task-manager/lib/agent-hooks-codex-workspace.js +9 -1
  41. package/template/coding-task-manager/lib/agent-hooks-installer.js +23 -8
  42. package/template/coding-task-manager/lib/agent-hooks-prune.js +37 -11
  43. package/template/coding-task-manager/lib/agent-hooks-shim.js +105 -0
  44. package/template/coding-task-manager/lib/agent-presets.js +84 -1
  45. package/template/coding-task-manager/lib/agent-upgrade-jobs.js +12 -1
  46. package/template/coding-task-manager/lib/agent-version-service.js +74 -11
  47. package/template/coding-task-manager/lib/all-sessions-query.js +6 -2
  48. package/template/coding-task-manager/lib/api/agent-bundles.js +436 -0
  49. package/template/coding-task-manager/lib/api/backup-retention.js +83 -0
  50. package/template/coding-task-manager/lib/api/conversation-sync-routes.js +124 -0
  51. package/template/coding-task-manager/lib/api/diagnostics.js +549 -69
  52. package/template/coding-task-manager/lib/api/fleet.js +118 -0
  53. package/template/coding-task-manager/lib/api/hub-bridge.js +243 -0
  54. package/template/coding-task-manager/lib/api/ingress.js +9 -1
  55. package/template/coding-task-manager/lib/api/landing.js +403 -0
  56. package/template/coding-task-manager/lib/api/machines.js +691 -2
  57. package/template/coding-task-manager/lib/api/memory-sync-routes.js +335 -0
  58. package/template/coding-task-manager/lib/api/misc-ops.js +8 -3
  59. package/template/coding-task-manager/lib/api/remote-sessions.js +1326 -0
  60. package/template/coding-task-manager/lib/api/session-attach.js +623 -0
  61. package/template/coding-task-manager/lib/api/session-messages.js +1384 -0
  62. package/template/coding-task-manager/lib/api/sessions.js +77 -51
  63. package/template/coding-task-manager/lib/api/setup-network.js +544 -16
  64. package/template/coding-task-manager/lib/api/setup-wizard-handlers.js +884 -0
  65. package/template/coding-task-manager/lib/api/setup.js +829 -10
  66. package/template/coding-task-manager/lib/api/walle-bridge.js +9 -1
  67. package/template/coding-task-manager/lib/attachment-reconciler-wiring.js +5 -2
  68. package/template/coding-task-manager/lib/auth-rate-limit.js +23 -0
  69. package/template/coding-task-manager/lib/auth-rules.js +292 -21
  70. package/template/coding-task-manager/lib/background-stop.js +369 -0
  71. package/template/coding-task-manager/lib/best-of-attempts.js +4 -1
  72. package/template/coding-task-manager/lib/best-of-launch-plan.js +52 -0
  73. package/template/coding-task-manager/lib/box-keep-awake.js +89 -0
  74. package/template/coding-task-manager/lib/broadcast-reason-stats.js +152 -0
  75. package/template/coding-task-manager/lib/broadcast-serialize.js +5 -0
  76. package/template/coding-task-manager/lib/build-info.js +4 -2
  77. package/template/coding-task-manager/lib/claude-model-truth.js +13 -2
  78. package/template/coding-task-manager/lib/claude-transcript-terminal-renderer.js +17 -13
  79. package/template/coding-task-manager/lib/client-diag-handler.js +64 -2
  80. package/template/coding-task-manager/lib/codex-app-server-client.js +14 -16
  81. package/template/coding-task-manager/lib/codex-configuration-history.js +55 -0
  82. package/template/coding-task-manager/lib/codex-harness-qualification.js +43 -20
  83. package/template/coding-task-manager/lib/codex-rollout-history.js +743 -0
  84. package/template/coding-task-manager/lib/coding-agent-models.js +27 -12
  85. package/template/coding-task-manager/lib/coding-cli-skill-installer.js +44 -14
  86. package/template/coding-task-manager/lib/coding-session-model-adapters.js +43 -2
  87. package/template/coding-task-manager/lib/coding-session-model-owner.js +1 -1
  88. package/template/coding-task-manager/lib/coding-session-model-public.js +7 -1
  89. package/template/coding-task-manager/lib/coding-session-model-runtime.js +23 -4
  90. package/template/coding-task-manager/lib/coding-session-model-scan.js +31 -0
  91. package/template/coding-task-manager/lib/coding-session-model-state.js +7 -0
  92. package/template/coding-task-manager/lib/conversation-freshness-diagnostics.js +280 -0
  93. package/template/coding-task-manager/lib/conversation-item-clock.js +261 -0
  94. package/template/coding-task-manager/lib/conversation-source-registry.js +5 -0
  95. package/template/coding-task-manager/lib/conversation-store-v2.js +44 -0
  96. package/template/coding-task-manager/lib/conversation-sync.js +355 -0
  97. package/template/coding-task-manager/lib/create/resolve-launch-params.js +96 -12
  98. package/template/coding-task-manager/lib/create/worker-role-profile.js +4 -4
  99. package/template/coding-task-manager/lib/create-intent-lease.js +51 -0
  100. package/template/coding-task-manager/lib/ctm-session-context-api.js +97 -6
  101. package/template/coding-task-manager/lib/db-domain-tables.js +1 -0
  102. package/template/coding-task-manager/lib/db-domains.js +1 -0
  103. package/template/coding-task-manager/lib/db-owner-dispatch-probe.js +32 -0
  104. package/template/coding-task-manager/lib/db-owner-request-counts.js +178 -0
  105. package/template/coding-task-manager/lib/db-owner-worker-client.js +68 -14
  106. package/template/coding-task-manager/lib/db-schema-source-files.js +5 -0
  107. package/template/coding-task-manager/lib/deferred-restore-attempt.js +6 -2
  108. package/template/coding-task-manager/lib/feature-manifest.js +4 -0
  109. package/template/coding-task-manager/lib/fleet-conversation-route.js +97 -0
  110. package/template/coding-task-manager/lib/fleet-fanout.js +78 -0
  111. package/template/coding-task-manager/lib/fleet-hub.js +762 -0
  112. package/template/coding-task-manager/lib/fleet-origin-follower.js +252 -0
  113. package/template/coding-task-manager/lib/fleet-resolver-effects.js +147 -0
  114. package/template/coding-task-manager/lib/fleet-resolver-tick.js +148 -0
  115. package/template/coding-task-manager/lib/fleet-resolver.js +454 -0
  116. package/template/coding-task-manager/lib/fleet-session-list-routes.js +114 -0
  117. package/template/coding-task-manager/lib/fleet-session-lists.js +672 -0
  118. package/template/coding-task-manager/lib/fleet-update.js +798 -0
  119. package/template/coding-task-manager/lib/fs-watcher-root-watch.js +141 -0
  120. package/template/coding-task-manager/lib/fs-watcher.js +58 -42
  121. package/template/coding-task-manager/lib/harness-history-transition.js +50 -9
  122. package/template/coding-task-manager/lib/headless-term-service.js +84 -8
  123. package/template/coding-task-manager/lib/hermetic-agent-launch-guard.js +10 -0
  124. package/template/coding-task-manager/lib/history-transition-read-op.js +175 -8
  125. package/template/coding-task-manager/lib/host-cpu-categories.js +310 -0
  126. package/template/coding-task-manager/lib/host-fseventsd-sampler.js +399 -0
  127. package/template/coding-task-manager/lib/host-handoff.js +16 -19
  128. package/template/coding-task-manager/lib/host-stats.js +150 -3
  129. package/template/coding-task-manager/lib/hosted-sync-worker.js +43 -320
  130. package/template/coding-task-manager/lib/hub-bridge-access.js +798 -0
  131. package/template/coding-task-manager/lib/hub-bridge-box.js +409 -0
  132. package/template/coding-task-manager/lib/hub-bridge-mcp.js +380 -0
  133. package/template/coding-task-manager/lib/hub-bridge-mesh.js +313 -0
  134. package/template/coding-task-manager/lib/hub-bridge-ops.js +721 -0
  135. package/template/coding-task-manager/lib/hub-bridge.js +398 -0
  136. package/template/coding-task-manager/lib/idle-notify.js +491 -0
  137. package/template/coding-task-manager/lib/instance-id-ownership-manifest.js +8 -0
  138. package/template/coding-task-manager/lib/instance-manifest.js +5 -1
  139. package/template/coding-task-manager/lib/instance-sync-status.js +18 -8
  140. package/template/coding-task-manager/lib/landing/agent-rule.txt +1 -0
  141. package/template/coding-task-manager/lib/landing/batch-runner.js +366 -0
  142. package/template/coding-task-manager/lib/landing/config.js +536 -0
  143. package/template/coding-task-manager/lib/landing/ctm-view.js +256 -0
  144. package/template/coding-task-manager/lib/landing/gate.js +360 -0
  145. package/template/coding-task-manager/lib/landing/git.js +344 -0
  146. package/template/coding-task-manager/lib/landing/lease.js +247 -0
  147. package/template/coding-task-manager/lib/landing/merge-delta.js +380 -0
  148. package/template/coding-task-manager/lib/landing/proof.js +223 -0
  149. package/template/coding-task-manager/lib/landing/queue.js +998 -0
  150. package/template/coding-task-manager/lib/landing/radar.js +489 -0
  151. package/template/coding-task-manager/lib/landing/resolve-cli.js +424 -0
  152. package/template/coding-task-manager/lib/landing/state.js +263 -0
  153. package/template/coding-task-manager/lib/landing/stop.js +49 -0
  154. package/template/coding-task-manager/lib/landing/sync-cli.js +475 -0
  155. package/template/coding-task-manager/lib/landing/sync.js +456 -0
  156. package/template/coding-task-manager/lib/landing/train.js +885 -0
  157. package/template/coding-task-manager/lib/landing/window.js +57 -0
  158. package/template/coding-task-manager/lib/launch-environment.js +121 -0
  159. package/template/coding-task-manager/lib/launch-model-override.js +36 -10
  160. package/template/coding-task-manager/lib/launch-plan-pool.js +2 -1
  161. package/template/coding-task-manager/lib/launch-plan-warm-cache.js +6 -0
  162. package/template/coding-task-manager/lib/lead-model-observer.js +57 -1
  163. package/template/coding-task-manager/lib/lead-model-options.js +160 -3
  164. package/template/coding-task-manager/lib/lead-model-restore-reconciliation.js +106 -24
  165. package/template/coding-task-manager/lib/lead-model-switch-runtime.js +352 -68
  166. package/template/coding-task-manager/lib/lead-model-switch.js +114 -10
  167. package/template/coding-task-manager/lib/lead-model-transition-runtime.js +14 -2
  168. package/template/coding-task-manager/lib/lead-model-transition-store.js +24 -6
  169. package/template/coding-task-manager/lib/lead-route-preflight.js +179 -0
  170. package/template/coding-task-manager/lib/lead-switch-history-mode.js +110 -0
  171. package/template/coding-task-manager/lib/lead-wire-agent.js +7 -0
  172. package/template/coding-task-manager/lib/lifecycle-wake-experiment.js +9 -2
  173. package/template/coding-task-manager/lib/live-defer-announce.js +45 -0
  174. package/template/coding-task-manager/lib/machine-registry.js +750 -5
  175. package/template/coding-task-manager/lib/macos-capabilities.js +32 -15
  176. package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +433 -53
  177. package/template/coding-task-manager/lib/mainloop-observability.js +14 -9
  178. package/template/coding-task-manager/lib/media-draft-owner.js +16 -3
  179. package/template/coding-task-manager/lib/memory-join.js +337 -0
  180. package/template/coding-task-manager/lib/memory-sync-verify.js +393 -0
  181. package/template/coding-task-manager/lib/memory-sync.js +565 -0
  182. package/template/coding-task-manager/lib/migrations/v57-delegate-pref-mirror-opencode.js +68 -0
  183. package/template/coding-task-manager/lib/migrations/v58-subagent-launch-native-subagents.js +42 -0
  184. package/template/coding-task-manager/lib/migrations/v59-coding-session-model-state-dsh.js +73 -0
  185. package/template/coding-task-manager/lib/migrations/v60-delegate-pref-mirror-dsh.js +78 -0
  186. package/template/coding-task-manager/lib/migrations/v61-conversation-item-clock.js +71 -0
  187. package/template/coding-task-manager/lib/model-availability.js +727 -0
  188. package/template/coding-task-manager/lib/model-execution-recipe-metadata.js +4 -6
  189. package/template/coding-task-manager/lib/model-host-receipt.js +6 -3
  190. package/template/coding-task-manager/lib/model-id-rule.js +19 -0
  191. package/template/coding-task-manager/lib/model-proxy/anthropic-face.js +4 -0
  192. package/template/coding-task-manager/lib/model-proxy/auto-mode-review.js +110 -23
  193. package/template/coding-task-manager/lib/model-proxy/chat-response-translators.js +3 -0
  194. package/template/coding-task-manager/lib/model-proxy/generation-probe.js +60 -17
  195. package/template/coding-task-manager/lib/model-proxy/historical-tool-declarations.js +37 -0
  196. package/template/coding-task-manager/lib/model-proxy/lead-request-validation.js +1 -0
  197. package/template/coding-task-manager/lib/model-proxy/lead-token-admin.js +130 -0
  198. package/template/coding-task-manager/lib/model-proxy/refusal-scope.js +151 -0
  199. package/template/coding-task-manager/lib/model-proxy/request-budget-store.js +11 -2
  200. package/template/coding-task-manager/lib/model-proxy/tokens.js +69 -5
  201. package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +9 -0
  202. package/template/coding-task-manager/lib/native-agent-model-args.js +25 -22
  203. package/template/coding-task-manager/lib/native-history-control.js +6 -4
  204. package/template/coding-task-manager/lib/native-lead-settings-client.js +44 -4
  205. package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +173 -36
  206. package/template/coding-task-manager/lib/online-backup-worker-client.js +2 -0
  207. package/template/coding-task-manager/lib/opencode-cli.js +480 -0
  208. package/template/coding-task-manager/lib/opencode-launch-model.js +471 -0
  209. package/template/coding-task-manager/lib/opencode-v1-plugin/model-carrier.mjs +35 -0
  210. package/template/coding-task-manager/lib/opencode-v2-plugin/server.js +118 -0
  211. package/template/coding-task-manager/lib/owner-action-manifest-data.json +1 -1
  212. package/template/coding-task-manager/lib/park-composer-draft.js +54 -0
  213. package/template/coding-task-manager/lib/park-fresh-relaunch.js +41 -10
  214. package/template/coding-task-manager/lib/perf-phase-trace.js +72 -0
  215. package/template/coding-task-manager/lib/perf-summary.js +7 -0
  216. package/template/coding-task-manager/lib/perf-tracker.js +63 -2
  217. package/template/coding-task-manager/lib/project-config.js +7 -0
  218. package/template/coding-task-manager/lib/prompt-purge-v2.js +52 -1
  219. package/template/coding-task-manager/lib/provider-login-broker.js +72 -15
  220. package/template/coding-task-manager/lib/provider-login-tab.js +10 -2
  221. package/template/coding-task-manager/lib/read-pool-client.js +89 -2
  222. package/template/coding-task-manager/lib/read-pool-worker-handle.js +29 -4
  223. package/template/coding-task-manager/lib/recent-catalog-query.js +15 -0
  224. package/template/coding-task-manager/lib/recent-session-catalog-response.js +67 -10
  225. package/template/coding-task-manager/lib/recovery-evidence.js +26 -11
  226. package/template/coding-task-manager/lib/relay-client.js +57 -3
  227. package/template/coding-task-manager/lib/relink-audit.js +34 -5
  228. package/template/coding-task-manager/lib/remote-machine-catalog.js +321 -26
  229. package/template/coding-task-manager/lib/remote-machine-create.js +576 -36
  230. package/template/coding-task-manager/lib/remote-machine-link.js +546 -59
  231. package/template/coding-task-manager/lib/remote-machine-proxy.js +143 -9
  232. package/template/coding-task-manager/lib/remote-session-forward.js +65 -7
  233. package/template/coding-task-manager/lib/remote-terminal-target.js +9 -2
  234. package/template/coding-task-manager/lib/restart-guard.js +18 -6
  235. package/template/coding-task-manager/lib/restore-seed-modes.js +87 -0
  236. package/template/coding-task-manager/lib/restored-scrollback-hydration-runtime.js +22 -2
  237. package/template/coding-task-manager/lib/resume-admission.js +17 -3
  238. package/template/coding-task-manager/lib/review-repo-registry.js +58 -19
  239. package/template/coding-task-manager/lib/root-delivery-runtime.js +2 -2
  240. package/template/coding-task-manager/lib/root-prompt-flow.js +1 -1
  241. package/template/coding-task-manager/lib/runtime-contract.js +3 -1
  242. package/template/coding-task-manager/lib/schema-indexes.js +1 -0
  243. package/template/coding-task-manager/lib/session-context-locator.js +742 -0
  244. package/template/coding-task-manager/lib/session-create/attachment.js +2 -2
  245. package/template/coding-task-manager/lib/session-create/create-phases.js +118 -0
  246. package/template/coding-task-manager/lib/session-create/delegate-worker.js +86 -16
  247. package/template/coding-task-manager/lib/session-create/dsh-session.js +930 -0
  248. package/template/coding-task-manager/lib/session-create/lead-route-launch.js +186 -13
  249. package/template/coding-task-manager/lib/session-create/native-lead-lifetime.js +55 -3
  250. package/template/coding-task-manager/lib/session-create/opencode-lead-provider.js +50 -0
  251. package/template/coding-task-manager/lib/session-create/prepared.js +162 -38
  252. package/template/coding-task-manager/lib/session-create/provider-process.js +160 -28
  253. package/template/coding-task-manager/lib/session-create/response.js +7 -7
  254. package/template/coding-task-manager/lib/session-create/structured-session.js +27 -0
  255. package/template/coding-task-manager/lib/session-create/subagent-pick-table.js +3 -1
  256. package/template/coding-task-manager/lib/session-create/subagent-pick.js +458 -9
  257. package/template/coding-task-manager/lib/session-create/transcript.js +1 -1
  258. package/template/coding-task-manager/lib/session-create/worker-budget-setup.js +21 -2
  259. package/template/coding-task-manager/lib/session-create/worker-continuation.js +7 -1
  260. package/template/coding-task-manager/lib/session-create/worker-launch-sandbox.js +39 -10
  261. package/template/coding-task-manager/lib/session-create/worker-observability.js +2 -2
  262. package/template/coding-task-manager/lib/session-empty.js +13 -10
  263. package/template/coding-task-manager/lib/session-host-manager.js +60 -0
  264. package/template/coding-task-manager/lib/session-jobs.js +3 -1
  265. package/template/coding-task-manager/lib/session-lifecycle.js +10 -4
  266. package/template/coding-task-manager/lib/session-model-action-preconditions.js +6 -2
  267. package/template/coding-task-manager/lib/session-model-intent-contract.js +11 -8
  268. package/template/coding-task-manager/lib/session-park.js +738 -0
  269. package/template/coding-task-manager/lib/session-path-grant.js +13 -4
  270. package/template/coding-task-manager/lib/session-status-ledger.js +106 -4
  271. package/template/coding-task-manager/lib/session-transport.js +17 -0
  272. package/template/coding-task-manager/lib/session-workspace-projection.js +54 -5
  273. package/template/coding-task-manager/lib/session-workspace-tracking-runtime.js +213 -1
  274. package/template/coding-task-manager/lib/skill-autocomplete-query.js +120 -3
  275. package/template/coding-task-manager/lib/skill-autocomplete.js +15 -1
  276. package/template/coding-task-manager/lib/sqlite-file-set.js +39 -0
  277. package/template/coding-task-manager/lib/standup-search-adapter.js +16 -2
  278. package/template/coding-task-manager/lib/state-sync/client-ledger.js +12 -0
  279. package/template/coding-task-manager/lib/state-sync/frame-emitter.js +319 -100
  280. package/template/coding-task-manager/lib/storage/coding-session-model-store.js +4 -1
  281. package/template/coding-task-manager/lib/storage/delegate-pref-mirror-store.js +32 -9
  282. package/template/coding-task-manager/lib/structured-session-boot-sweep.js +235 -0
  283. package/template/coding-task-manager/lib/submission-ack.js +90 -2
  284. package/template/coding-task-manager/lib/systemd-scope.js +115 -0
  285. package/template/coding-task-manager/lib/telemetry-receiver.js +39 -0
  286. package/template/coding-task-manager/lib/terminal-attach-geometry.js +985 -0
  287. package/template/coding-task-manager/lib/terminal-bootstrap.js +30 -0
  288. package/template/coding-task-manager/lib/terminal-draft-operation.js +357 -0
  289. package/template/coding-task-manager/lib/terminal-input-admission.js +17 -1
  290. package/template/coding-task-manager/lib/terminal-input-prepared.js +563 -0
  291. package/template/coding-task-manager/lib/transcript-cache-temps.js +171 -0
  292. package/template/coding-task-manager/lib/transcript-frame-cache.js +8 -3
  293. package/template/coding-task-manager/lib/transcript-source.js +36 -4
  294. package/template/coding-task-manager/lib/transcript-store.js +9 -0
  295. package/template/coding-task-manager/lib/typing-interaction-trace.js +106 -3
  296. package/template/coding-task-manager/lib/usage-ledger/backfill.js +40 -5
  297. package/template/coding-task-manager/lib/usage-ledger/client.js +4 -1
  298. package/template/coding-task-manager/lib/usage-ledger/dsh-parse.js +152 -0
  299. package/template/coding-task-manager/lib/usage-ledger/dsh-read.js +73 -0
  300. package/template/coding-task-manager/lib/usage-ledger/ingest.js +34 -6
  301. package/template/coding-task-manager/lib/usage-ledger/live.js +35 -8
  302. package/template/coding-task-manager/lib/usage-ledger/read.js +29 -20
  303. package/template/coding-task-manager/lib/usage-ledger/schema.js +61 -1
  304. package/template/coding-task-manager/lib/usage-ledger/task-coordinator.js +4 -2
  305. package/template/coding-task-manager/lib/wake-skip-reasons.js +1 -0
  306. package/template/coding-task-manager/lib/walle/turn.js +1 -1
  307. package/template/coding-task-manager/lib/walle-history-serve.js +838 -0
  308. package/template/coding-task-manager/lib/walle-kill-authority.js +2 -2
  309. package/template/coding-task-manager/lib/walle-log-rotation.js +164 -1
  310. package/template/coding-task-manager/lib/walle-mcp-auto-config.js +56 -2
  311. package/template/coding-task-manager/lib/walle-row-history.js +495 -0
  312. package/template/coding-task-manager/lib/walle-supervisor.js +33 -14
  313. package/template/coding-task-manager/lib/watch-worker-client.js +203 -0
  314. package/template/coding-task-manager/lib/worker-terminal-output.js +5 -2
  315. package/template/coding-task-manager/lib/ws/hub-bridge.js +35 -0
  316. package/template/coding-task-manager/lib/ws/lifecycle.js +6 -11
  317. package/template/coding-task-manager/lib/ws/misc.js +1 -1
  318. package/template/coding-task-manager/lib/ws/state-sync.js +106 -4
  319. package/template/coding-task-manager/lib/ws/terminal-attach.js +91 -0
  320. package/template/coding-task-manager/oauth-proxy.js +112 -115
  321. package/template/coding-task-manager/package-lock.json +10 -94
  322. package/template/coding-task-manager/package.json +4 -3
  323. package/template/coding-task-manager/protocol/message-table.json +10 -0
  324. package/template/coding-task-manager/protocol/messages.js +10 -0
  325. package/template/coding-task-manager/protocol/ws-schema.json +20 -0
  326. package/template/coding-task-manager/protocol/ws-schema.md +2 -0
  327. package/template/coding-task-manager/public/css/app.css +170 -0
  328. package/template/coding-task-manager/public/css/walle-session.css +4 -0
  329. package/template/coding-task-manager/public/index.html +473 -243
  330. package/template/coding-task-manager/public/js/agent-command.js +86 -0
  331. package/template/coding-task-manager/public/js/app/backups-panel.js +111 -5
  332. package/template/coding-task-manager/public/js/app/coding-agent-upgrade.js +103 -4
  333. package/template/coding-task-manager/public/js/app/machines-page.js +1328 -8
  334. package/template/coding-task-manager/public/js/app/models-tab.js +113 -38
  335. package/template/coding-task-manager/public/js/app/restart-banner.js +53 -0
  336. package/template/coding-task-manager/public/js/app/worktrees-panel.js +184 -2
  337. package/template/coding-task-manager/public/js/background-work.js +196 -27
  338. package/template/coding-task-manager/public/js/coding-session-model-presentation.js +138 -10
  339. package/template/coding-task-manager/public/js/core/active-session-groups.js +179 -0
  340. package/template/coding-task-manager/public/js/core/pending-create.js +238 -0
  341. package/template/coding-task-manager/public/js/core/recent-machine-source.js +228 -0
  342. package/template/coding-task-manager/public/js/core/session-commands.js +180 -14
  343. package/template/coding-task-manager/public/js/dashboard-client-function-order.json +8 -0
  344. package/template/coding-task-manager/public/js/document-review-links.js +9 -1
  345. package/template/coding-task-manager/public/js/file-resolution-client.js +52 -1
  346. package/template/coding-task-manager/public/js/history-app-seam.js +22 -2
  347. package/template/coding-task-manager/public/js/machine-pool-shared.js +558 -3
  348. package/template/coding-task-manager/public/js/message-renderer.js +4 -3
  349. package/template/coding-task-manager/public/js/model-picker.js +3 -1
  350. package/template/coding-task-manager/public/js/native-subagent-review.js +15 -2
  351. package/template/coding-task-manager/public/js/new-session-agent-grid.js +346 -0
  352. package/template/coding-task-manager/public/js/pasted-content.js +236 -0
  353. package/template/coding-task-manager/public/js/pe-private-content-lifetime.js +39 -7
  354. package/template/coding-task-manager/public/js/private-model-lifetime.js +6 -2
  355. package/template/coding-task-manager/public/js/prompts.js +11 -10
  356. package/template/coding-task-manager/public/js/protocol.js +10 -0
  357. package/template/coding-task-manager/public/js/restart-banner-policy.js +29 -1
  358. package/template/coding-task-manager/public/js/session-model-picker.js +447 -57
  359. package/template/coding-task-manager/public/js/session-search-utils.js +18 -2
  360. package/template/coding-task-manager/public/js/session-usage-view.js +2 -1
  361. package/template/coding-task-manager/public/js/session-workspace-tracking.js +51 -1
  362. package/template/coding-task-manager/public/js/state-sync-client.js +10 -1
  363. package/template/coding-task-manager/public/js/stream-view.js +6 -5
  364. package/template/coding-task-manager/public/js/terminal/conv-only-session.js +287 -0
  365. package/template/coding-task-manager/public/js/terminal/runtime-09.js +2 -0
  366. package/template/coding-task-manager/public/js/terminal/runtime-10.js +5 -5
  367. package/template/coding-task-manager/public/js/terminal/runtime-12.js +8 -1
  368. package/template/coding-task-manager/public/js/terminal/runtime-16.js +4 -0
  369. package/template/coding-task-manager/public/js/terminal/runtime-20.js +1 -1
  370. package/template/coding-task-manager/public/js/terminal-attachment-draft.js +67 -13
  371. package/template/coding-task-manager/public/js/terminal-image-orchestration.js +52 -6
  372. package/template/coding-task-manager/public/js/terminal-wheel.js +23 -3
  373. package/template/coding-task-manager/public/js/walle/chat-conversation.js +4 -4
  374. package/template/coding-task-manager/public/js/walle.js +6 -0
  375. package/template/coding-task-manager/public/js/ws/live-dispatch.js +10 -0
  376. package/template/coding-task-manager/public/m/app.css +140 -0
  377. package/template/coding-task-manager/public/m/app.js +507 -68
  378. package/template/coding-task-manager/public/m/index.html +17 -0
  379. package/template/coding-task-manager/public/m/machines.js +838 -4
  380. package/template/coding-task-manager/public/m/private-api.js +31 -1
  381. package/template/coding-task-manager/public/usage.html +1 -0
  382. package/template/coding-task-manager/scripts/dev-route-fixture/synthetic-route-upstream.js +104 -0
  383. package/template/coding-task-manager/scripts/dev-route-fixture.js +339 -0
  384. package/template/coding-task-manager/scripts/opencode-lead-route-probe.js +195 -0
  385. package/template/coding-task-manager/scripts/opencode-v2-contract-probe/fake-anthropic.js +168 -0
  386. package/template/coding-task-manager/scripts/opencode-v2-contract-probe/probe-plugin/server.js +95 -0
  387. package/template/coding-task-manager/scripts/opencode-v2-contract-probe.js +673 -0
  388. package/template/coding-task-manager/server.js +1950 -11679
  389. package/template/coding-task-manager/session-integrity.js +64 -4
  390. package/template/coding-task-manager/workers/db-owner-worker.js +19 -2
  391. package/template/coding-task-manager/workers/online-backup-worker.js +1 -0
  392. package/template/coding-task-manager/workers/read-pool-model-collector.js +51 -3
  393. package/template/coding-task-manager/workers/read-pool-worker.js +76 -6
  394. package/template/coding-task-manager/workers/session-host-pool-process.js +6 -6
  395. package/template/coding-task-manager/workers/session-host-process.js +5 -5
  396. package/template/coding-task-manager/workers/watch-worker.js +105 -0
  397. package/template/coding-task-manager/workers/worktree-worker.js +168 -33
  398. package/template/ctm-relay/lib/protocol.js +14 -1
  399. package/template/package-lock.json +2 -2
  400. package/template/package.json +1 -1
  401. package/template/shared/backup-retention.js +82 -0
  402. package/template/shared/conversation-admission.js +2 -0
  403. package/template/shared/conversation-provenance.js +3 -7
  404. package/template/shared/conversation-storage-v2-contract.js +5 -0
  405. package/template/shared/linked-worktree.js +51 -0
  406. package/template/shared/macos-fda-target.js +57 -0
  407. package/template/shared/orphan-parents.js +55 -0
  408. package/template/shared/release-schema.json +2 -2
  409. package/template/shared/storage/contract.js +3 -0
  410. package/template/wall-e/adapters/imessage.js +12 -0
  411. package/template/wall-e/agent.js +71 -4
  412. package/template/wall-e/api-walle.js +21 -1
  413. package/template/wall-e/bin/train-gemma-e4b-tooluse.js +2 -2
  414. package/template/wall-e/bin/walle-mcp-stdio.js +5 -5
  415. package/template/wall-e/brain/brain-join.js +859 -0
  416. package/template/wall-e/brain/brain-sync-membership.js +20 -0
  417. package/template/wall-e/brain/brain-sync-store.js +131 -77
  418. package/template/wall-e/brain/brain-sync-v2-schema.js +203 -0
  419. package/template/wall-e/brain/brain-sync-v2.js +578 -0
  420. package/template/wall-e/brain/delegate-model-prefs-store.js +13 -4
  421. package/template/wall-e/brain/deterministic-id.js +51 -0
  422. package/template/wall-e/brain/memories.js +2 -2
  423. package/template/wall-e/brain/migrations.js +40 -6
  424. package/template/wall-e/brain/model-identity-migration.js +1 -1
  425. package/template/wall-e/brain/owner-call-whitelist.js +23 -7
  426. package/template/wall-e/brain/schema.js +45 -85
  427. package/template/wall-e/brain.js +171 -35
  428. package/template/wall-e/chat.js +3 -3
  429. package/template/wall-e/coding/agent-shell-env.js +7 -2
  430. package/template/wall-e/coding/prompt-bundle.js +66 -21
  431. package/template/wall-e/config/main-loop-exemptions.json +2 -2
  432. package/template/wall-e/http/admin-api.js +37 -0
  433. package/template/wall-e/http/gws-api.js +4 -0
  434. package/template/wall-e/http/helper-rules-api.js +7 -1
  435. package/template/wall-e/http/model-admin.js +8 -1
  436. package/template/wall-e/http/model-delegate-pref-admin.js +3 -3
  437. package/template/wall-e/http/model-proxy-providers.js +174 -1
  438. package/template/wall-e/http/model-route-health.js +157 -0
  439. package/template/wall-e/http/sync-api.js +278 -464
  440. package/template/wall-e/jobs/job-runner.js +28 -1
  441. package/template/wall-e/lib/brain-owner-op-priority.js +9 -1
  442. package/template/wall-e/lib/ctm-data-dir.js +26 -0
  443. package/template/wall-e/lib/derivation-home.js +147 -0
  444. package/template/wall-e/lib/helper-rules/evaluate.js +50 -9
  445. package/template/wall-e/lib/helper-rules/grade.js +51 -8
  446. package/template/wall-e/lib/helper-rules/lead-call-hook.js +38 -5
  447. package/template/wall-e/lib/helper-rules/store.js +4 -2
  448. package/template/wall-e/lib/landing-mcp-tools.js +170 -0
  449. package/template/wall-e/lib/mcp-client-config.js +133 -14
  450. package/template/wall-e/lib/mcp-gateway-migrate.js +28 -64
  451. package/template/wall-e/lib/mcp-integration.js +58 -13
  452. package/template/wall-e/lib/parent-death.js +7 -1
  453. package/template/wall-e/lib/scheduler-worker-jobs.js +6 -4
  454. package/template/wall-e/llm/delegate-lead-prefs.js +16 -1
  455. package/template/wall-e/llm/delegate-vendor-default.js +12 -5
  456. package/template/wall-e/llm/model-roles.js +1 -1
  457. package/template/wall-e/llm/native-delegate-selection.js +56 -8
  458. package/template/wall-e/llm/worker-delegate-args.js +72 -7
  459. package/template/wall-e/llm/worker-mcp-routing.js +66 -17
  460. package/template/wall-e/loops/brain-custom-writes.js +19 -0
  461. package/template/wall-e/loops/ingest.js +17 -1
  462. package/template/wall-e/loops/think.js +19 -4
  463. package/template/wall-e/mcp-contract.js +222 -6
  464. package/template/wall-e/mcp-protocol-contract.js +40 -5
  465. package/template/wall-e/mcp-server.js +128 -29
  466. package/template/wall-e/mcp-worker-schemas.js +5 -5
  467. package/template/wall-e/memory/ctm-context-client.js +85 -0
  468. package/template/wall-e/memory/ctm-session-context.js +9 -3
  469. package/template/wall-e/memory/hub-bridge-client.js +388 -0
  470. package/template/wall-e/memory/replica-origin.js +56 -0
  471. package/template/wall-e/memory/session-pool.js +135 -0
  472. package/template/wall-e/runtime/live-capabilities.js +8 -3
  473. package/template/wall-e/server.js +4 -2
  474. package/template/wall-e/shared/release-schema.json +2 -2
  475. package/template/wall-e/shared/sqlite-file-set.js +39 -0
  476. package/template/wall-e/shared/storage/contract.js +3 -0
  477. package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
  478. package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +7 -1
  479. package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +4 -4
  480. package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +6 -6
  481. package/template/wall-e/skills/_templates/fleet-sync/VERSION +1 -0
  482. package/template/wall-e/skills/_templates/fleet-sync/released-sha256.json +16 -0
  483. package/template/wall-e/skills/_templates/fleet-sync/templates/claude/SKILL.md +64 -0
  484. package/template/wall-e/skills/_templates/fleet-sync/templates/codex/SKILL.md +64 -0
  485. package/template/wall-e/tools/chrome-automation.js +6 -0
  486. package/template/wall-e/training/setup-cuda-train-env.sh +2 -2
  487. package/template/wall-e/workers/brain-owner-worker.js +18 -4
  488. package/template/wall-e/workers/mcp-gateway-process.js +5 -5
@@ -0,0 +1,522 @@
1
+ 'use strict';
2
+
3
+ // WP-2 of docs/deepseek-harness-acp-agent-2026-10-28.html (§6.3; decisions D-1, D-2, D-5, D-6, D-9, D-10).
4
+ //
5
+ // One CTM dsh session owns exactly ONE child process (D-2) driven over the Agent Client Protocol on
6
+ // pipes — never node-pty (D-1). This module owns the child, the ACP client and the stop sequence; it
7
+ // renders nothing, writes no transcript (that is WP-3) and knows nothing about WebSockets (the caller
8
+ // injects `onUpdate`/`onRequestPermission`/`onExit`). Prompts, approvals and status are WP-4; restore
9
+ // after a CTM restart is WP-5 and spawns through `start({ resumeAcpSessionId })`.
10
+ //
11
+ // Everything that touches the outside world is a dep so a test never spawns the real binary (D-14):
12
+ // `resolveCliCommand` (the CLI cache), `realpath`, `execPath` (CTM's pinned Node), `spawnFn` (the
13
+ // ND-JSON transport's), the log sink and the timers.
14
+
15
+ const { spawnNdjsonTransport } = require('./ndjson-stdio-transport');
16
+ const { createAcpClient, AcpError } = require('./acp-client');
17
+ const { AGENT_DEFINITIONS } = require('../agent-definitions');
18
+
19
+ // WP-12: the name `dsh` is not unique (homebrew's `dsh` is the unrelated "Dancer's shell"), so a
20
+ // resolved binary is spawned only when its REALPATH is inside the @deepseek-ai/dsh package -- the
21
+ // same installIdentity rule the version service applies (lib/agent-version-service.js).
22
+ const DSH_INSTALL_IDENTITY = AGENT_DEFINITIONS.dsh.installIdentity;
23
+
24
+ const DSH_STOP_GRACE_MS = 5000; // SIGTERM this long after stdin end
25
+ const DSH_KILL_GRACE_MS = 1000; // SIGKILL this long after SIGTERM
26
+ const DSH_CLOSE_TIMEOUT_MS = 3000; // session/close budget before stdin end
27
+ const STDERR_TAIL_BYTES = 64 * 1024;
28
+ // WP-14: the bounded assistant text a completed turn leaves behind (see accumulateFinalText). Well
29
+ // above any real report, and small next to the 64 KB stderr ring.
30
+ const FINAL_TEXT_MAX_CHARS = 256 * 1024;
31
+ // A start failure names the child's exit in ONE line, so the tail it quotes is bounded well below the
32
+ // 64 KB ring it is cut from.
33
+ const STDERR_MESSAGE_CHARS = 400;
34
+ // D-1: a `.js`/`.cjs`/`.mjs` realpath is an npm entrypoint, not an executable — spawn it under the
35
+ // interpreter CTM pins (dsh needs Node >= 24.9) rather than whatever `node` PATH resolves to.
36
+ const JS_ENTRYPOINT_RE = /\.(?:js|cjs|mjs)$/i;
37
+ // WP-6 (§6.6, D-11): a ROUTED child talks to CTM's loopback proxy and carries the session token as
38
+ // its only credential, so every other provider credential or base URL inherited from the launch env
39
+ // is removed — otherwise pi-ai's own provider resolution (or a stale DEEPSEEK_API_KEY the user still
40
+ // has exported) could quietly win over the `--patch`.
41
+ const DSH_ROUTE_ENV_KEYS = Object.freeze([
42
+ 'DEEPSEEK_API_KEY',
43
+ 'ANTHROPIC_API_KEY',
44
+ 'ANTHROPIC_BASE_URL',
45
+ 'ANTHROPIC_OAUTH_TOKEN',
46
+ ]);
47
+
48
+ /**
49
+ * @param {object} deps
50
+ * @param {(cmd: string) => string} deps.resolveCliCommand // lib/agent-cli-cache.js's resolver
51
+ * @param {(p: string) => Promise<string>|string} deps.realpath // async in production (no sync fs on the main loop)
52
+ * @param {string} deps.execPath // process.execPath
53
+ * @param {Function} [deps.spawnFn] // child_process.spawn stand-in for tests
54
+ * @param {Function} [deps.now]
55
+ * @param {Function} [deps.log] // ({level, msg}) => void
56
+ * @param {(ctmSessionId: string, update: object) => void} [deps.onUpdate]
57
+ * @param {(ctmSessionId: string, configOptions: Array<object>|null) => void} [deps.onConfigOptions]
58
+ * @param {(ctmSessionId: string, params: object) => Promise<object>} [deps.onRequestPermission]
59
+ * @param {(ctmSessionId: string, info: object) => void} [deps.onExit]
60
+ * @param {Function} [deps.setTimeout]
61
+ * @param {Function} [deps.clearTimeout]
62
+ */
63
+ function createDshSessionRuntime(deps = {}) {
64
+ const {
65
+ resolveCliCommand = (cmd) => cmd,
66
+ realpath = (p) => p,
67
+ execPath = process.execPath,
68
+ spawnFn,
69
+ log = () => {},
70
+ } = deps;
71
+ const setTimeoutFn = deps.setTimeout || setTimeout;
72
+ const clearTimeoutFn = deps.clearTimeout || clearTimeout;
73
+
74
+ const entries = new Map(); // ctmSessionId → entry (ONE per id, D-2)
75
+
76
+ function logLine(level, msg) {
77
+ try {
78
+ log({ level, msg });
79
+ } catch (error) {
80
+ // expected: a broken log sink must never take down a session's start/stop path.
81
+ void error;
82
+ }
83
+ }
84
+
85
+ // The bounded stderr tail (D-5). Byte-trimmed so a chatty child cannot grow it without limit; the
86
+ // tail is diagnostic only and is NEVER logged at info (it can carry the child's own error text).
87
+ function trimTail(text) {
88
+ if (Buffer.byteLength(text, 'utf8') <= STDERR_TAIL_BYTES) return text;
89
+ return Buffer.from(text, 'utf8').subarray(-STDERR_TAIL_BYTES).toString('utf8');
90
+ }
91
+
92
+ function appendTail(state, line) {
93
+ state.stderrTail = trimTail(state.stderrTail ? `${state.stderrTail}\n${line}` : String(line));
94
+ }
95
+
96
+ function describeExit(info, tail) {
97
+ const code = info && info.code !== undefined && info.code !== null ? info.code : null;
98
+ const signal = info && info.signal ? info.signal : null;
99
+ const detail = code === null && !signal
100
+ ? 'dsh exited during startup'
101
+ : `dsh exited during startup (code ${code}${signal ? `, signal ${signal}` : ''})`;
102
+ const quoted = String(tail || '').slice(-STDERR_MESSAGE_CHARS);
103
+ return quoted ? `${detail}: ${quoted}` : detail;
104
+ }
105
+
106
+ function scheduleSigkillEscalation(entry) {
107
+ const timer = setTimeoutFn(() => {
108
+ if (!entry.exited) entry.transport.kill('SIGKILL');
109
+ }, DSH_KILL_GRACE_MS);
110
+ if (timer && typeof timer.unref === 'function') timer.unref();
111
+ return timer;
112
+ }
113
+
114
+ // The child is gone: drop the registry row, release anyone waiting on the stop, and report the exit
115
+ // to the caller exactly once. An exit this runtime caused itself (stop, or a failed start) is
116
+ // either reported as intentional or not reported at all — never both.
117
+ function onChildExit(ctmSessionId, entry, info) {
118
+ if (entry.exited) return;
119
+ entry.exited = true;
120
+ entry.exitInfo = info || null;
121
+ if (entries.get(ctmSessionId) === entry) entries.delete(ctmSessionId);
122
+ if (typeof entry.resolveExit === 'function') entry.resolveExit();
123
+ // Before the handshake completes the child belongs to start(), which reports the failure itself.
124
+ if (!entry.started) return;
125
+ // WP-6: the routed token is released exactly ONCE per started child, on whichever path the child
126
+ // died (a stop, or a crash): `entry.exited` above already makes this a one-shot, and clearing the
127
+ // hook means a later re-entry can never fire it a second time.
128
+ if (typeof entry.onStopped === 'function') {
129
+ const release = entry.onStopped;
130
+ entry.onStopped = null;
131
+ try {
132
+ release();
133
+ } catch (error) {
134
+ // expected: a release observer must never break the transport's own teardown.
135
+ void error;
136
+ }
137
+ }
138
+ const report = deps.onExit;
139
+ if (typeof report !== 'function') return;
140
+ try {
141
+ report(ctmSessionId, {
142
+ code: info && info.code !== undefined ? info.code : null,
143
+ signal: info && info.signal !== undefined ? info.signal : null,
144
+ stderrTail: entry.stderrTail,
145
+ intentional: entry.stopping === true,
146
+ });
147
+ } catch (error) {
148
+ // expected: an exit observer must never break the transport's own teardown.
149
+ void error;
150
+ }
151
+ }
152
+
153
+ // WP-8 (§9b M-16, D-12/D-13): a `config_option_update` notification carries the bridge's WHOLE
154
+ // `configOptions` list — the same shape `session/new`/`session/resume` returned — so it replaces the
155
+ // entry's copy (which `get()` serves) and is handed to the caller's observer, which records the
156
+ // model-owner row. Any other update kind is passed through untouched, and a throwing observer can
157
+ // never break the ACP read loop that called it.
158
+ function acceptConfigOptions(ctmSessionId, entry, update) {
159
+ if (!update || update.sessionUpdate !== 'config_option_update') return;
160
+ const next = Array.isArray(update.configOptions) ? update.configOptions
161
+ : (update.configOption && typeof update.configOption === 'object' ? [update.configOption] : null);
162
+ if (next) entry.configOptions = next;
163
+ if (typeof entry.onConfigOptions !== 'function') return;
164
+ try {
165
+ entry.onConfigOptions(ctmSessionId, entry.configOptions);
166
+ } catch (error) {
167
+ logLine('warn', `dsh-runtime: config-option observer failed for ${ctmSessionId} (${(error && error.message) || 'error'})`);
168
+ }
169
+ }
170
+
171
+ // WP-14 (docs/deepseek-harness-acp-agent-2026-10-28.html §9b W-3, §6.4): the LAST assistant text the
172
+ // child produced, which is what a delegated dsh worker's report IS (its brief turn's final answer;
173
+ // the transcript writer appends the same chunks). The ACP wire has no "final message" field — the
174
+ // text arrives as `agent_message_chunk` updates — so this accumulates them per `messageId` and keeps
175
+ // the last id seen: a new id starts a new assistant message, exactly the grouping
176
+ // lib/acp/dsh-transcript.js's chunk writer uses (`pending.messageId`). Bounded, so a runaway child
177
+ // cannot grow the entry without limit; only text chunks count (thinking chunks are not an answer).
178
+ function accumulateFinalText(entry, update) {
179
+ if (!update || update.sessionUpdate !== 'agent_message_chunk') return;
180
+ const messageId = typeof update.messageId === 'string' && update.messageId ? update.messageId : entry.finalTextMessageId;
181
+ const content = update.content;
182
+ const text = typeof content === 'string' ? content
183
+ : content && typeof content.text === 'string' ? content.text : '';
184
+ if (!text) return;
185
+ if (messageId !== entry.finalTextMessageId) {
186
+ entry.finalTextMessageId = messageId;
187
+ entry.finalText = '';
188
+ }
189
+ entry.finalText = `${entry.finalText}${text}`.slice(-FINAL_TEXT_MAX_CHARS);
190
+ }
191
+
192
+ // WP-10 step A (C-6/D-16): `mcpServers` are the ACP entries the child mounts for THIS session
193
+ // (lib/acp/dsh-mcp-servers.js converts CTM's normalized map into them). They ride the
194
+ // `session/new`/`session/resume` JSON-RPC request -- never argv, never the child's process env --
195
+ // and an absent list is an empty one, so a session with no MCP profile is byte-for-byte what it
196
+ // was before WP-10.
197
+ async function start({ ctmSessionId, cwd, env, resumeAcpSessionId = null, patchPath = null, mcpServers = [], onStopped = null, onConfigOptions = null } = {}) {
198
+ if (entries.has(ctmSessionId)) {
199
+ return {
200
+ ok: false,
201
+ code: 'dsh_already_running',
202
+ message: `A DeepSeek Harness process is already running for session ${ctmSessionId}.`,
203
+ };
204
+ }
205
+ const bin = resolveCliCommand('dsh');
206
+ // `resolveCliCommand` returns its input unchanged when the CLI is not on this host (an absolute
207
+ // path it cannot find also comes back bare).
208
+ if (!bin || bin === 'dsh') {
209
+ return { ok: false, code: 'dsh_not_found', message: 'DeepSeek Harness (dsh) was not found on PATH' };
210
+ }
211
+ let real = bin;
212
+ try {
213
+ real = (await realpath(bin)) || bin;
214
+ } catch (error) {
215
+ // expected: the CLI cache can point at a path that has since been removed; spawn reports that
216
+ // as a start failure through the transport's exit channel, so no throw is needed here.
217
+ void error;
218
+ }
219
+ if (!DSH_INSTALL_IDENTITY.test(String(real))) {
220
+ return { ok: false, code: 'dsh_not_found', message: 'The dsh on PATH is not the DeepSeek Harness (@deepseek-ai/dsh)' };
221
+ }
222
+ const args = ['--profile', 'acp'];
223
+ if (patchPath) args.push('--patch', patchPath);
224
+ const isJsEntrypoint = JS_ENTRYPOINT_RE.test(real);
225
+ const command = isJsEntrypoint ? execPath : real;
226
+ const spawnArgs = isJsEntrypoint ? [real, ...args] : args;
227
+ const childEnv = { ...(env || {}) };
228
+ // WP-6 (§6.6): a routed child's provider comes from the patch and its credential is the session
229
+ // token; every other provider key/base URL in the launch env is dropped (see DSH_ROUTE_ENV_KEYS).
230
+ if (patchPath) for (const key of DSH_ROUTE_ENV_KEYS) delete childEnv[key];
231
+ // The bridge's own permission mode. Passed THROUGH to the child; never read back by CTM and never
232
+ // logged (it is launch context, not a CTM flag).
233
+ if (childEnv.DSH_PERMISSION_MODE === undefined) childEnv.DSH_PERMISSION_MODE = 'workspace-write';
234
+
235
+ const entry = {
236
+ acpSessionId: null,
237
+ client: null,
238
+ transport: null,
239
+ pid: undefined,
240
+ configOptions: null,
241
+ agentInfo: null,
242
+ // WP-11 (D-20): the child's LIVE image capability, read from the ACP `initialize` result
243
+ // (`agentCapabilities.promptCapabilities.image`). Absent/false means the bridge cannot accept
244
+ // an image content block, and the prompt lane refuses such a prompt rather than sending one.
245
+ imageInput: false,
246
+ // WP-14: the last assistant text seen for this child (accumulateFinalText above), and the
247
+ // messageId that text belongs to.
248
+ finalText: '',
249
+ finalTextMessageId: null,
250
+ stderrTail: '',
251
+ started: false,
252
+ startFailed: false,
253
+ stopping: false,
254
+ stopReason: '',
255
+ stopPromise: null,
256
+ exited: false,
257
+ exitInfo: null,
258
+ resolveExit: null,
259
+ exitPromise: null,
260
+ // WP-6: the caller's one-shot release hook (see onChildExit). Never called for a child whose
261
+ // start failed -- that child belongs to start(), which releases its own token.
262
+ onStopped: typeof onStopped === 'function' ? onStopped : null,
263
+ // WP-8: the caller's model-owner observer (see acceptConfigOptions). Fires for every
264
+ // `config_option_update` the child emits, including ones that arrive before the handshake ends.
265
+ onConfigOptions: typeof onConfigOptions === 'function' ? onConfigOptions : null,
266
+ };
267
+ entry.exitPromise = new Promise((resolve) => { entry.resolveExit = resolve; });
268
+
269
+ const transport = spawnNdjsonTransport({
270
+ command,
271
+ args: spawnArgs,
272
+ cwd,
273
+ env: childEnv,
274
+ ...(spawnFn ? { spawnFn } : {}),
275
+ onStderrLine: (line) => appendTail(entry, line),
276
+ });
277
+ entry.transport = transport;
278
+ entry.pid = transport.pid;
279
+ transport.onExit((info) => onChildExit(ctmSessionId, entry, info));
280
+
281
+ const client = createAcpClient({
282
+ transport,
283
+ onSessionUpdate: (sessionId, update) => {
284
+ acceptConfigOptions(ctmSessionId, entry, update);
285
+ accumulateFinalText(entry, update);
286
+ if (typeof deps.onUpdate === 'function') deps.onUpdate(ctmSessionId, update);
287
+ else logLine('info', `dsh-runtime: session update for ${sessionId} dropped (no observer)`);
288
+ },
289
+ onRequestPermission: (params) => (typeof deps.onRequestPermission === 'function'
290
+ ? deps.onRequestPermission(ctmSessionId, params)
291
+ : Promise.resolve({ outcome: 'cancelled' })),
292
+ log: (entryLog) => logLine(entryLog.level, entryLog.msg),
293
+ });
294
+ entry.client = client;
295
+
296
+ try {
297
+ const initResult = await client.initialize();
298
+ const acpMcpServers = Array.isArray(mcpServers) ? mcpServers : [];
299
+ const sessionResult = resumeAcpSessionId
300
+ ? await client.resumeSession({ sessionId: resumeAcpSessionId, cwd, mcpServers: acpMcpServers })
301
+ : await client.newSession({ cwd, mcpServers: acpMcpServers });
302
+ const acpSessionId = (sessionResult && (sessionResult.sessionId || sessionResult.session_id))
303
+ || resumeAcpSessionId
304
+ || null;
305
+ entry.acpSessionId = acpSessionId;
306
+ entry.configOptions = (sessionResult && sessionResult.configOptions) || null;
307
+ entry.agentInfo = (initResult && initResult.agentInfo) || null;
308
+ // WP-11 (D-20): the child's own answer to "can you take an image?". Read from the SAME
309
+ // initialize result the handshake gate above already validated; an absent or non-`true` value
310
+ // is false (a bridge that does not advertise image prompts cannot be given one).
311
+ entry.imageInput = !!(
312
+ initResult
313
+ && initResult.agentCapabilities
314
+ && initResult.agentCapabilities.promptCapabilities
315
+ && initResult.agentCapabilities.promptCapabilities.image === true
316
+ );
317
+ entry.started = true;
318
+ entries.set(ctmSessionId, entry);
319
+ return {
320
+ ok: true,
321
+ acpSessionId,
322
+ configOptions: entry.configOptions,
323
+ agentInfo: entry.agentInfo,
324
+ imageInput: entry.imageInput,
325
+ };
326
+ } catch (error) {
327
+ // Nothing was registered, so the child must not outlive this call.
328
+ entry.startFailed = true;
329
+ transport.kill('SIGTERM');
330
+ entry.sigkillTimer = scheduleSigkillEscalation(entry);
331
+ if (error instanceof AcpError && error.code === 'dsh_acp_incompatible') {
332
+ return { ok: false, code: 'dsh_acp_incompatible', message: error.message };
333
+ }
334
+ if (entry.exited || (error instanceof AcpError && error.code === 'acp_child_exited')) {
335
+ return { ok: false, code: 'dsh_start_failed', message: describeExit(entry.exitInfo, entry.stderrTail) };
336
+ }
337
+ return {
338
+ ok: false,
339
+ code: 'dsh_start_failed',
340
+ message: error && error.message ? String(error.message) : 'DeepSeek Harness failed to start',
341
+ };
342
+ }
343
+ }
344
+
345
+ // D-10: session/close (bounded), stdin end, SIGTERM after DSH_STOP_GRACE_MS, SIGKILL
346
+ // DSH_KILL_GRACE_MS later if the child is still alive. Files are never touched.
347
+ // `closeAcpSession:false` (§6.7 cross-route relaunch) skips session/close: the SAME ACP session is
348
+ // resumed by the next child, so it must stay open.
349
+ async function stop(ctmSessionId, { reason, closeAcpSession = true } = {}) {
350
+ const entry = entries.get(ctmSessionId);
351
+ if (!entry) return { ok: true, alreadyStopped: true };
352
+ if (entry.stopPromise) return entry.stopPromise;
353
+ entry.stopping = true;
354
+ entry.stopReason = reason || '';
355
+ entry.stopPromise = (async () => {
356
+ if (closeAcpSession) {
357
+ try {
358
+ await Promise.race([
359
+ entry.client.closeSession({ sessionId: entry.acpSessionId }),
360
+ new Promise((resolve) => {
361
+ const timer = setTimeoutFn(resolve, DSH_CLOSE_TIMEOUT_MS);
362
+ if (timer && typeof timer.unref === 'function') timer.unref();
363
+ }),
364
+ ]);
365
+ } catch (error) {
366
+ // The child may already be gone, or the bridge may not implement session/close (its
367
+ // capability is optional); the SIGTERM ladder below is the real guarantee.
368
+ logLine('warn', `dsh-runtime: session/close failed for ${ctmSessionId} (${(error && error.code) || 'error'})`);
369
+ }
370
+ }
371
+ entry.transport.endInput();
372
+ const termTimer = setTimeoutFn(() => {
373
+ if (!entry.exited) entry.transport.kill('SIGTERM');
374
+ }, DSH_STOP_GRACE_MS);
375
+ const killTimer = setTimeoutFn(() => {
376
+ if (!entry.exited) entry.transport.kill('SIGKILL');
377
+ }, DSH_STOP_GRACE_MS + DSH_KILL_GRACE_MS);
378
+ if (termTimer && typeof termTimer.unref === 'function') termTimer.unref();
379
+ if (killTimer && typeof killTimer.unref === 'function') killTimer.unref();
380
+ await entry.exitPromise;
381
+ clearTimeoutFn(termTimer);
382
+ clearTimeoutFn(killTimer);
383
+ return { ok: true };
384
+ })();
385
+ return entry.stopPromise;
386
+ }
387
+
388
+ function isRunning(ctmSessionId) {
389
+ const entry = entries.get(ctmSessionId);
390
+ return !!entry && !entry.exited;
391
+ }
392
+
393
+ // WP-8 step 3 (§6.7): the bridge admits ONE in-flight prompt per session, so a config-option write
394
+ // that arrived while a turn is open must be REFUSED, never queued (the caller's pick is a
395
+ // point-in-time choice, and a queued write would silently apply to a later turn). The predicate is
396
+ // injected (the prompt lane owns the turn registry) — absent a predicate nothing is ever in flight.
397
+ function isTurnInFlight(ctmSessionId) {
398
+ if (typeof deps.isTurnInFlight !== 'function') return false;
399
+ try {
400
+ return deps.isTurnInFlight(ctmSessionId) === true;
401
+ } catch (error) {
402
+ logLine('warn', `dsh-runtime: turn-in-flight probe failed for ${ctmSessionId} (${(error && error.message) || 'error'})`);
403
+ return false;
404
+ }
405
+ }
406
+
407
+ // The ONE config-option write (§6.7). `value` is the OPAQUE option value the bridge itself
408
+ // advertised — never a hand-built string — so the caller must have found it in the entry's own
409
+ // `configOptions`. On success the returned list replaces the entry's copy and the SAME observer
410
+ // path `acceptConfigOptions` uses is invoked, so the model-owner row re-binds from one place.
411
+ async function applyConfigOption(ctmSessionId, configId, value) {
412
+ const entry = entries.get(ctmSessionId);
413
+ if (!entry || entry.exited) return { ok: false, code: 'acp_child_exited' };
414
+ if (!configId || typeof value !== 'string' || !value) return { ok: false, code: 'dsh_option_unavailable' };
415
+ if (isTurnInFlight(ctmSessionId)) return { ok: false, code: 'dsh_turn_in_flight' };
416
+ if (typeof entry.client?.setConfigOption !== 'function') return { ok: false, code: 'dsh_option_unavailable' };
417
+ let result;
418
+ try {
419
+ result = await entry.client.setConfigOption({
420
+ sessionId: entry.acpSessionId, configId, value,
421
+ });
422
+ } catch (error) {
423
+ // A child that died mid-write is reported as exited; anything else is the bridge refusing the
424
+ // option, which is exactly the `dsh_option_unavailable` the caller shows the user.
425
+ if (entry.exited) return { ok: false, code: 'acp_child_exited' };
426
+ logLine('warn', `dsh-runtime: set_config_option ${configId} failed for ${ctmSessionId} (${(error && error.code) || 'error'})`);
427
+ return { ok: false, code: 'dsh_option_unavailable' };
428
+ }
429
+ const next = result && Array.isArray(result.configOptions) ? result.configOptions : null;
430
+ if (next) {
431
+ entry.configOptions = next;
432
+ if (typeof entry.onConfigOptions === 'function') {
433
+ try {
434
+ entry.onConfigOptions(ctmSessionId, entry.configOptions);
435
+ } catch (error) {
436
+ logLine('warn', `dsh-runtime: config-option observer failed for ${ctmSessionId} (${(error && error.message) || 'error'})`);
437
+ }
438
+ }
439
+ }
440
+ return { ok: true, configOptions: entry.configOptions };
441
+ }
442
+
443
+ /**
444
+ * §6.7: switch the ACP `model` option. `value` is the OPAQUE value from the entry's `configOptions`
445
+ * (the caller unwraps the entry's JSON pair; this layer never builds one).
446
+ */
447
+ async function setModel(ctmSessionId, { value } = {}) {
448
+ return applyConfigOption(ctmSessionId, 'model', value);
449
+ }
450
+
451
+ /** §6.7: switch the bridge-declared effort option (`reasoning_effort`), same contract as setModel. */
452
+ async function setEffort(ctmSessionId, level, { configId = 'reasoning_effort', value = null } = {}) {
453
+ return applyConfigOption(ctmSessionId, configId, value == null ? level : value);
454
+ }
455
+
456
+ function get(ctmSessionId) {
457
+ const entry = entries.get(ctmSessionId);
458
+ if (!entry) return null;
459
+ return {
460
+ acpSessionId: entry.acpSessionId,
461
+ client: entry.client,
462
+ pid: entry.pid,
463
+ configOptions: entry.configOptions,
464
+ // WP-11 (D-20): the live image capability of THIS child (`initialize`'s
465
+ // `agentCapabilities.promptCapabilities.image`). Absent reads false — a gone child reads
466
+ // `null` for the whole entry, which the prompt lane already treats as "not running".
467
+ imageInput: entry.imageInput === true,
468
+ stderrTail: () => entry.stderrTail,
469
+ // WP-14 (§9b W-3): the report source for a delegated dsh worker — `observer?.finalText ||
470
+ // runtime?.finalText` in delegate-worker.js's getWorkerStatus reads this through
471
+ // lib/session-create/dsh-session.js's `_dshFinalText` accessor. Empty until the child has
472
+ // produced assistant text; '' (never null) so a caller never has to type-check it.
473
+ finalText: entry.finalText || '',
474
+ };
475
+ }
476
+
477
+ /**
478
+ * WP-14 (§9b W-2): put ONE prompt on the wire for a caller that is not the interactive prompt lane
479
+ * — the delegated dsh worker's brief, which has no argv to ride. Returns the ACP prompt promise
480
+ * (the turn's own settle/status/cancel behaviour stays the prompt lane's business, exactly as it is
481
+ * for an interactive turn); a session with no live child is refused rather than throwing.
482
+ * `resetFinalText` starts the report's text from THIS turn: without it a run whose first turn was
483
+ * empty would report the previous turn's answer.
484
+ *
485
+ * @param {string} ctmSessionId
486
+ * @param {{text: string}} prompt
487
+ * @returns {Promise<{ok: true, prompt: Promise<any>}|{ok: false, code: string, message: string}>}
488
+ */
489
+ function prompt(ctmSessionId, { text = '' } = {}) {
490
+ const entry = entries.get(ctmSessionId);
491
+ if (!entry || !entry.client || typeof entry.client.prompt !== 'function' || !entry.acpSessionId) {
492
+ return Promise.resolve({
493
+ ok: false,
494
+ code: 'dsh_not_running',
495
+ message: `No DeepSeek Harness process is running for session ${ctmSessionId}.`,
496
+ });
497
+ }
498
+ entry.finalText = '';
499
+ entry.finalTextMessageId = null;
500
+ let pending;
501
+ try {
502
+ pending = entry.client.prompt({ sessionId: entry.acpSessionId, text: String(text) });
503
+ } catch (error) {
504
+ return Promise.resolve({
505
+ ok: false,
506
+ code: 'dsh_prompt_failed',
507
+ message: (error && error.message) ? String(error.message) : 'DeepSeek Harness refused the prompt',
508
+ });
509
+ }
510
+ return Promise.resolve({ ok: true, prompt: Promise.resolve(pending) });
511
+ }
512
+
513
+ return { start, stop, isRunning, get, prompt, setModel, setEffort, isTurnInFlight };
514
+ }
515
+
516
+ module.exports = {
517
+ createDshSessionRuntime,
518
+ DSH_STOP_GRACE_MS,
519
+ DSH_KILL_GRACE_MS,
520
+ DSH_CLOSE_TIMEOUT_MS,
521
+ DSH_ROUTE_ENV_KEYS,
522
+ };