@sunshaobei/dsh-workflow 0.0.0-stage → 2.1.2

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 (386) hide show
  1. package/README.md +43 -2
  2. package/cordis.patch.yml +17 -0
  3. package/lib/client.js +14708 -0
  4. package/lib/core.js +137 -0
  5. package/lib/engine-adapter.js +1387 -0
  6. package/lib/host-driver.js +298 -0
  7. package/lib/index.js +536 -0
  8. package/lib/projection.js +159 -0
  9. package/lib/registry.js +218 -0
  10. package/lib/session-records.js +54 -0
  11. package/lib/submission-commit.js +34 -0
  12. package/lib/world-driver.js +275 -0
  13. package/package.json +67 -4
  14. package/vendor/PROVENANCE.md +9 -0
  15. package/vendor/dynamic-workflow/analysis/actor-graph.d.ts +47 -0
  16. package/vendor/dynamic-workflow/analysis/actor-graph.d.ts.map +1 -0
  17. package/vendor/dynamic-workflow/analysis/actor-graph.js +95 -0
  18. package/vendor/dynamic-workflow/analysis/actor-models.d.ts +60 -0
  19. package/vendor/dynamic-workflow/analysis/actor-models.d.ts.map +1 -0
  20. package/vendor/dynamic-workflow/analysis/actor-models.js +208 -0
  21. package/vendor/dynamic-workflow/analysis/actor-names.d.ts +56 -0
  22. package/vendor/dynamic-workflow/analysis/actor-names.d.ts.map +1 -0
  23. package/vendor/dynamic-workflow/analysis/actor-names.js +155 -0
  24. package/vendor/dynamic-workflow/analysis/analyze.d.ts +63 -0
  25. package/vendor/dynamic-workflow/analysis/analyze.d.ts.map +1 -0
  26. package/vendor/dynamic-workflow/analysis/analyze.js +92 -0
  27. package/vendor/dynamic-workflow/analysis/array-methods.d.ts +21 -0
  28. package/vendor/dynamic-workflow/analysis/array-methods.d.ts.map +1 -0
  29. package/vendor/dynamic-workflow/analysis/array-methods.js +132 -0
  30. package/vendor/dynamic-workflow/analysis/artifact-types.d.ts +39 -0
  31. package/vendor/dynamic-workflow/analysis/artifact-types.d.ts.map +1 -0
  32. package/vendor/dynamic-workflow/analysis/artifact-types.js +114 -0
  33. package/vendor/dynamic-workflow/analysis/artifacts.d.ts +67 -0
  34. package/vendor/dynamic-workflow/analysis/artifacts.d.ts.map +1 -0
  35. package/vendor/dynamic-workflow/analysis/artifacts.js +263 -0
  36. package/vendor/dynamic-workflow/analysis/assign.d.ts +42 -0
  37. package/vendor/dynamic-workflow/analysis/assign.d.ts.map +1 -0
  38. package/vendor/dynamic-workflow/analysis/assign.js +287 -0
  39. package/vendor/dynamic-workflow/analysis/callbacks.d.ts +71 -0
  40. package/vendor/dynamic-workflow/analysis/callbacks.d.ts.map +1 -0
  41. package/vendor/dynamic-workflow/analysis/callbacks.js +133 -0
  42. package/vendor/dynamic-workflow/analysis/calls.d.ts +40 -0
  43. package/vendor/dynamic-workflow/analysis/calls.d.ts.map +1 -0
  44. package/vendor/dynamic-workflow/analysis/calls.js +495 -0
  45. package/vendor/dynamic-workflow/analysis/causality-graph-lanes.d.ts +25 -0
  46. package/vendor/dynamic-workflow/analysis/causality-graph-lanes.d.ts.map +1 -0
  47. package/vendor/dynamic-workflow/analysis/causality-graph-lanes.js +161 -0
  48. package/vendor/dynamic-workflow/analysis/causality-graph-types.d.ts +163 -0
  49. package/vendor/dynamic-workflow/analysis/causality-graph-types.d.ts.map +1 -0
  50. package/vendor/dynamic-workflow/analysis/causality-graph-types.js +8 -0
  51. package/vendor/dynamic-workflow/analysis/causality-graph.d.ts +39 -0
  52. package/vendor/dynamic-workflow/analysis/causality-graph.d.ts.map +1 -0
  53. package/vendor/dynamic-workflow/analysis/causality-graph.js +530 -0
  54. package/vendor/dynamic-workflow/analysis/causality-order-calls.d.ts +29 -0
  55. package/vendor/dynamic-workflow/analysis/causality-order-calls.d.ts.map +1 -0
  56. package/vendor/dynamic-workflow/analysis/causality-order-calls.js +266 -0
  57. package/vendor/dynamic-workflow/analysis/causality-order-functions.d.ts +26 -0
  58. package/vendor/dynamic-workflow/analysis/causality-order-functions.d.ts.map +1 -0
  59. package/vendor/dynamic-workflow/analysis/causality-order-functions.js +116 -0
  60. package/vendor/dynamic-workflow/analysis/causality-order-loops.d.ts +5 -0
  61. package/vendor/dynamic-workflow/analysis/causality-order-loops.d.ts.map +1 -0
  62. package/vendor/dynamic-workflow/analysis/causality-order-loops.js +148 -0
  63. package/vendor/dynamic-workflow/analysis/causality-order-settle.d.ts +39 -0
  64. package/vendor/dynamic-workflow/analysis/causality-order-settle.d.ts.map +1 -0
  65. package/vendor/dynamic-workflow/analysis/causality-order-settle.js +263 -0
  66. package/vendor/dynamic-workflow/analysis/causality-order-state.d.ts +110 -0
  67. package/vendor/dynamic-workflow/analysis/causality-order-state.d.ts.map +1 -0
  68. package/vendor/dynamic-workflow/analysis/causality-order-state.js +162 -0
  69. package/vendor/dynamic-workflow/analysis/causality-order-strands.d.ts +79 -0
  70. package/vendor/dynamic-workflow/analysis/causality-order-strands.d.ts.map +1 -0
  71. package/vendor/dynamic-workflow/analysis/causality-order-strands.js +154 -0
  72. package/vendor/dynamic-workflow/analysis/causality-order-types.d.ts +174 -0
  73. package/vendor/dynamic-workflow/analysis/causality-order-types.d.ts.map +1 -0
  74. package/vendor/dynamic-workflow/analysis/causality-order-types.js +1 -0
  75. package/vendor/dynamic-workflow/analysis/causality-order-walk.d.ts +17 -0
  76. package/vendor/dynamic-workflow/analysis/causality-order-walk.d.ts.map +1 -0
  77. package/vendor/dynamic-workflow/analysis/causality-order-walk.js +282 -0
  78. package/vendor/dynamic-workflow/analysis/causality-order.d.ts +60 -0
  79. package/vendor/dynamic-workflow/analysis/causality-order.d.ts.map +1 -0
  80. package/vendor/dynamic-workflow/analysis/causality-order.js +110 -0
  81. package/vendor/dynamic-workflow/analysis/causality-reduce.d.ts +60 -0
  82. package/vendor/dynamic-workflow/analysis/causality-reduce.d.ts.map +1 -0
  83. package/vendor/dynamic-workflow/analysis/causality-reduce.js +198 -0
  84. package/vendor/dynamic-workflow/analysis/classes.d.ts +47 -0
  85. package/vendor/dynamic-workflow/analysis/classes.d.ts.map +1 -0
  86. package/vendor/dynamic-workflow/analysis/classes.js +264 -0
  87. package/vendor/dynamic-workflow/analysis/constants.d.ts +35 -0
  88. package/vendor/dynamic-workflow/analysis/constants.d.ts.map +1 -0
  89. package/vendor/dynamic-workflow/analysis/constants.js +23 -0
  90. package/vendor/dynamic-workflow/analysis/control-flow.d.ts +26 -0
  91. package/vendor/dynamic-workflow/analysis/control-flow.d.ts.map +1 -0
  92. package/vendor/dynamic-workflow/analysis/control-flow.js +132 -0
  93. package/vendor/dynamic-workflow/analysis/core-json.d.ts +45 -0
  94. package/vendor/dynamic-workflow/analysis/core-json.d.ts.map +1 -0
  95. package/vendor/dynamic-workflow/analysis/core-json.js +49 -0
  96. package/vendor/dynamic-workflow/analysis/core.d.ts +194 -0
  97. package/vendor/dynamic-workflow/analysis/core.d.ts.map +1 -0
  98. package/vendor/dynamic-workflow/analysis/core.js +204 -0
  99. package/vendor/dynamic-workflow/analysis/domain.d.ts +269 -0
  100. package/vendor/dynamic-workflow/analysis/domain.d.ts.map +1 -0
  101. package/vendor/dynamic-workflow/analysis/domain.js +523 -0
  102. package/vendor/dynamic-workflow/analysis/facade-misuse.d.ts +56 -0
  103. package/vendor/dynamic-workflow/analysis/facade-misuse.d.ts.map +1 -0
  104. package/vendor/dynamic-workflow/analysis/facade-misuse.js +350 -0
  105. package/vendor/dynamic-workflow/analysis/fanout-cardinality.d.ts +11 -0
  106. package/vendor/dynamic-workflow/analysis/fanout-cardinality.d.ts.map +1 -0
  107. package/vendor/dynamic-workflow/analysis/fanout-cardinality.js +121 -0
  108. package/vendor/dynamic-workflow/analysis/flow-graph.d.ts +113 -0
  109. package/vendor/dynamic-workflow/analysis/flow-graph.d.ts.map +1 -0
  110. package/vendor/dynamic-workflow/analysis/flow-graph.js +411 -0
  111. package/vendor/dynamic-workflow/analysis/flow-phase.d.ts +28 -0
  112. package/vendor/dynamic-workflow/analysis/flow-phase.d.ts.map +1 -0
  113. package/vendor/dynamic-workflow/analysis/flow-phase.js +104 -0
  114. package/vendor/dynamic-workflow/analysis/flow-strands.d.ts +39 -0
  115. package/vendor/dynamic-workflow/analysis/flow-strands.d.ts.map +1 -0
  116. package/vendor/dynamic-workflow/analysis/flow-strands.js +47 -0
  117. package/vendor/dynamic-workflow/analysis/flow-tree.d.ts +35 -0
  118. package/vendor/dynamic-workflow/analysis/flow-tree.d.ts.map +1 -0
  119. package/vendor/dynamic-workflow/analysis/flow-tree.js +33 -0
  120. package/vendor/dynamic-workflow/analysis/graph.d.ts +5 -0
  121. package/vendor/dynamic-workflow/analysis/graph.d.ts.map +1 -0
  122. package/vendor/dynamic-workflow/analysis/graph.js +199 -0
  123. package/vendor/dynamic-workflow/analysis/handoff-graph.d.ts +48 -0
  124. package/vendor/dynamic-workflow/analysis/handoff-graph.d.ts.map +1 -0
  125. package/vendor/dynamic-workflow/analysis/handoff-graph.js +0 -0
  126. package/vendor/dynamic-workflow/analysis/heap-ops.d.ts +14 -0
  127. package/vendor/dynamic-workflow/analysis/heap-ops.d.ts.map +1 -0
  128. package/vendor/dynamic-workflow/analysis/heap-ops.js +70 -0
  129. package/vendor/dynamic-workflow/analysis/hole-id.d.ts +28 -0
  130. package/vendor/dynamic-workflow/analysis/hole-id.d.ts.map +1 -0
  131. package/vendor/dynamic-workflow/analysis/hole-id.js +41 -0
  132. package/vendor/dynamic-workflow/analysis/hole-sites.d.ts +32 -0
  133. package/vendor/dynamic-workflow/analysis/hole-sites.d.ts.map +1 -0
  134. package/vendor/dynamic-workflow/analysis/hole-sites.js +215 -0
  135. package/vendor/dynamic-workflow/analysis/hole-splice.d.ts +45 -0
  136. package/vendor/dynamic-workflow/analysis/hole-splice.d.ts.map +1 -0
  137. package/vendor/dynamic-workflow/analysis/hole-splice.js +100 -0
  138. package/vendor/dynamic-workflow/analysis/interpret.d.ts +26 -0
  139. package/vendor/dynamic-workflow/analysis/interpret.d.ts.map +1 -0
  140. package/vendor/dynamic-workflow/analysis/interpret.js +200 -0
  141. package/vendor/dynamic-workflow/analysis/literals.d.ts +18 -0
  142. package/vendor/dynamic-workflow/analysis/literals.d.ts.map +1 -0
  143. package/vendor/dynamic-workflow/analysis/literals.js +125 -0
  144. package/vendor/dynamic-workflow/analysis/mermaid.d.ts +60 -0
  145. package/vendor/dynamic-workflow/analysis/mermaid.d.ts.map +1 -0
  146. package/vendor/dynamic-workflow/analysis/mermaid.js +477 -0
  147. package/vendor/dynamic-workflow/analysis/patterns.d.ts +31 -0
  148. package/vendor/dynamic-workflow/analysis/patterns.d.ts.map +1 -0
  149. package/vendor/dynamic-workflow/analysis/patterns.js +94 -0
  150. package/vendor/dynamic-workflow/analysis/phase-graph.d.ts +47 -0
  151. package/vendor/dynamic-workflow/analysis/phase-graph.d.ts.map +1 -0
  152. package/vendor/dynamic-workflow/analysis/phase-graph.js +334 -0
  153. package/vendor/dynamic-workflow/analysis/phases.d.ts +24 -0
  154. package/vendor/dynamic-workflow/analysis/phases.d.ts.map +1 -0
  155. package/vendor/dynamic-workflow/analysis/phases.js +54 -0
  156. package/vendor/dynamic-workflow/analysis/promise-ops.d.ts +52 -0
  157. package/vendor/dynamic-workflow/analysis/promise-ops.d.ts.map +1 -0
  158. package/vendor/dynamic-workflow/analysis/promise-ops.js +123 -0
  159. package/vendor/dynamic-workflow/analysis/relays.d.ts +12 -0
  160. package/vendor/dynamic-workflow/analysis/relays.d.ts.map +1 -0
  161. package/vendor/dynamic-workflow/analysis/relays.js +78 -0
  162. package/vendor/dynamic-workflow/analysis/serialize.d.ts +125 -0
  163. package/vendor/dynamic-workflow/analysis/serialize.d.ts.map +1 -0
  164. package/vendor/dynamic-workflow/analysis/serialize.js +321 -0
  165. package/vendor/dynamic-workflow/analysis/site-phases.d.ts +32 -0
  166. package/vendor/dynamic-workflow/analysis/site-phases.d.ts.map +1 -0
  167. package/vendor/dynamic-workflow/analysis/site-phases.js +69 -0
  168. package/vendor/dynamic-workflow/analysis/sites-labels.d.ts +71 -0
  169. package/vendor/dynamic-workflow/analysis/sites-labels.d.ts.map +1 -0
  170. package/vendor/dynamic-workflow/analysis/sites-labels.js +189 -0
  171. package/vendor/dynamic-workflow/analysis/sites.d.ts +267 -0
  172. package/vendor/dynamic-workflow/analysis/sites.d.ts.map +1 -0
  173. package/vendor/dynamic-workflow/analysis/sites.js +225 -0
  174. package/vendor/dynamic-workflow/analysis/state.d.ts +254 -0
  175. package/vendor/dynamic-workflow/analysis/state.d.ts.map +1 -0
  176. package/vendor/dynamic-workflow/analysis/state.js +569 -0
  177. package/vendor/dynamic-workflow/analysis/taint.d.ts +97 -0
  178. package/vendor/dynamic-workflow/analysis/taint.d.ts.map +1 -0
  179. package/vendor/dynamic-workflow/analysis/taint.js +649 -0
  180. package/vendor/dynamic-workflow/analysis/types.d.ts +100 -0
  181. package/vendor/dynamic-workflow/analysis/types.d.ts.map +1 -0
  182. package/vendor/dynamic-workflow/analysis/types.js +1 -0
  183. package/vendor/dynamic-workflow/analysis/world-run.d.ts +27 -0
  184. package/vendor/dynamic-workflow/analysis/world-run.d.ts.map +1 -0
  185. package/vendor/dynamic-workflow/analysis/world-run.js +44 -0
  186. package/vendor/dynamic-workflow/compiler/compile.d.ts +59 -0
  187. package/vendor/dynamic-workflow/compiler/compile.d.ts.map +1 -0
  188. package/vendor/dynamic-workflow/compiler/compile.js +159 -0
  189. package/vendor/dynamic-workflow/compiler/libs.generated.d.ts +3 -0
  190. package/vendor/dynamic-workflow/compiler/libs.generated.d.ts.map +1 -0
  191. package/vendor/dynamic-workflow/compiler/libs.generated.js +64 -0
  192. package/vendor/dynamic-workflow/engine/artifact-spec.d.ts +26 -0
  193. package/vendor/dynamic-workflow/engine/artifact-spec.d.ts.map +1 -0
  194. package/vendor/dynamic-workflow/engine/artifact-spec.js +173 -0
  195. package/vendor/dynamic-workflow/engine/ask-observation-types.d.ts +54 -0
  196. package/vendor/dynamic-workflow/engine/ask-observation-types.d.ts.map +1 -0
  197. package/vendor/dynamic-workflow/engine/ask-observation-types.js +19 -0
  198. package/vendor/dynamic-workflow/engine/cached-ask-facts.d.ts +28 -0
  199. package/vendor/dynamic-workflow/engine/cached-ask-facts.d.ts.map +1 -0
  200. package/vendor/dynamic-workflow/engine/cached-ask-facts.js +35 -0
  201. package/vendor/dynamic-workflow/engine/concurrency.d.ts +151 -0
  202. package/vendor/dynamic-workflow/engine/concurrency.d.ts.map +1 -0
  203. package/vendor/dynamic-workflow/engine/concurrency.js +282 -0
  204. package/vendor/dynamic-workflow/engine/engine-artifacts-primary.d.ts +17 -0
  205. package/vendor/dynamic-workflow/engine/engine-artifacts-primary.d.ts.map +1 -0
  206. package/vendor/dynamic-workflow/engine/engine-artifacts-primary.js +29 -0
  207. package/vendor/dynamic-workflow/engine/engine-artifacts.d.ts +55 -0
  208. package/vendor/dynamic-workflow/engine/engine-artifacts.d.ts.map +1 -0
  209. package/vendor/dynamic-workflow/engine/engine-artifacts.js +367 -0
  210. package/vendor/dynamic-workflow/engine/engine-config.d.ts +90 -0
  211. package/vendor/dynamic-workflow/engine/engine-config.d.ts.map +1 -0
  212. package/vendor/dynamic-workflow/engine/engine-config.js +6 -0
  213. package/vendor/dynamic-workflow/engine/engine-holes.d.ts +116 -0
  214. package/vendor/dynamic-workflow/engine/engine-holes.d.ts.map +1 -0
  215. package/vendor/dynamic-workflow/engine/engine-holes.js +142 -0
  216. package/vendor/dynamic-workflow/engine/engine-launch.d.ts +34 -0
  217. package/vendor/dynamic-workflow/engine/engine-launch.d.ts.map +1 -0
  218. package/vendor/dynamic-workflow/engine/engine-launch.js +26 -0
  219. package/vendor/dynamic-workflow/engine/engine-phase-stamp.d.ts +35 -0
  220. package/vendor/dynamic-workflow/engine/engine-phase-stamp.d.ts.map +1 -0
  221. package/vendor/dynamic-workflow/engine/engine-phase-stamp.js +74 -0
  222. package/vendor/dynamic-workflow/engine/engine-report.d.ts +27 -0
  223. package/vendor/dynamic-workflow/engine/engine-report.d.ts.map +1 -0
  224. package/vendor/dynamic-workflow/engine/engine-report.js +151 -0
  225. package/vendor/dynamic-workflow/engine/engine-resume.d.ts +18 -0
  226. package/vendor/dynamic-workflow/engine/engine-resume.d.ts.map +1 -0
  227. package/vendor/dynamic-workflow/engine/engine-resume.js +38 -0
  228. package/vendor/dynamic-workflow/engine/engine-settlement.d.ts +30 -0
  229. package/vendor/dynamic-workflow/engine/engine-settlement.d.ts.map +1 -0
  230. package/vendor/dynamic-workflow/engine/engine-settlement.js +79 -0
  231. package/vendor/dynamic-workflow/engine/engine-state.d.ts +99 -0
  232. package/vendor/dynamic-workflow/engine/engine-state.d.ts.map +1 -0
  233. package/vendor/dynamic-workflow/engine/engine-state.js +13 -0
  234. package/vendor/dynamic-workflow/engine/engine-world.d.ts +36 -0
  235. package/vendor/dynamic-workflow/engine/engine-world.d.ts.map +1 -0
  236. package/vendor/dynamic-workflow/engine/engine-world.js +189 -0
  237. package/vendor/dynamic-workflow/engine/engine.d.ts +263 -0
  238. package/vendor/dynamic-workflow/engine/engine.d.ts.map +1 -0
  239. package/vendor/dynamic-workflow/engine/engine.js +602 -0
  240. package/vendor/dynamic-workflow/engine/errors.d.ts +87 -0
  241. package/vendor/dynamic-workflow/engine/errors.d.ts.map +1 -0
  242. package/vendor/dynamic-workflow/engine/errors.js +56 -0
  243. package/vendor/dynamic-workflow/engine/hash-mismatch.d.ts +10 -0
  244. package/vendor/dynamic-workflow/engine/hash-mismatch.d.ts.map +1 -0
  245. package/vendor/dynamic-workflow/engine/hash-mismatch.js +15 -0
  246. package/vendor/dynamic-workflow/engine/hash.d.ts +16 -0
  247. package/vendor/dynamic-workflow/engine/hash.d.ts.map +1 -0
  248. package/vendor/dynamic-workflow/engine/hash.js +48 -0
  249. package/vendor/dynamic-workflow/engine/imported-cache-types.d.ts +96 -0
  250. package/vendor/dynamic-workflow/engine/imported-cache-types.d.ts.map +1 -0
  251. package/vendor/dynamic-workflow/engine/imported-cache-types.js +6 -0
  252. package/vendor/dynamic-workflow/engine/imported-cache.d.ts +127 -0
  253. package/vendor/dynamic-workflow/engine/imported-cache.d.ts.map +1 -0
  254. package/vendor/dynamic-workflow/engine/imported-cache.js +244 -0
  255. package/vendor/dynamic-workflow/engine/index.d.ts +11 -0
  256. package/vendor/dynamic-workflow/engine/index.d.ts.map +1 -0
  257. package/vendor/dynamic-workflow/engine/index.js +10 -0
  258. package/vendor/dynamic-workflow/engine/journal-memory.d.ts +32 -0
  259. package/vendor/dynamic-workflow/engine/journal-memory.d.ts.map +1 -0
  260. package/vendor/dynamic-workflow/engine/journal-memory.js +243 -0
  261. package/vendor/dynamic-workflow/engine/journal-read-types.d.ts +72 -0
  262. package/vendor/dynamic-workflow/engine/journal-read-types.d.ts.map +1 -0
  263. package/vendor/dynamic-workflow/engine/journal-read-types.js +28 -0
  264. package/vendor/dynamic-workflow/engine/persona.d.ts +20 -0
  265. package/vendor/dynamic-workflow/engine/persona.d.ts.map +1 -0
  266. package/vendor/dynamic-workflow/engine/persona.js +43 -0
  267. package/vendor/dynamic-workflow/engine/replay-order.d.ts +96 -0
  268. package/vendor/dynamic-workflow/engine/replay-order.d.ts.map +1 -0
  269. package/vendor/dynamic-workflow/engine/replay-order.js +229 -0
  270. package/vendor/dynamic-workflow/engine/run-terminal.d.ts +35 -0
  271. package/vendor/dynamic-workflow/engine/run-terminal.d.ts.map +1 -0
  272. package/vendor/dynamic-workflow/engine/run-terminal.js +7 -0
  273. package/vendor/dynamic-workflow/engine/scheduler-submit.d.ts +22 -0
  274. package/vendor/dynamic-workflow/engine/scheduler-submit.d.ts.map +1 -0
  275. package/vendor/dynamic-workflow/engine/scheduler-submit.js +84 -0
  276. package/vendor/dynamic-workflow/engine/scheduler-types.d.ts +105 -0
  277. package/vendor/dynamic-workflow/engine/scheduler-types.d.ts.map +1 -0
  278. package/vendor/dynamic-workflow/engine/scheduler-types.js +17 -0
  279. package/vendor/dynamic-workflow/engine/scheduler.d.ts +113 -0
  280. package/vendor/dynamic-workflow/engine/scheduler.d.ts.map +1 -0
  281. package/vendor/dynamic-workflow/engine/scheduler.js +484 -0
  282. package/vendor/dynamic-workflow/engine/types.d.ts +979 -0
  283. package/vendor/dynamic-workflow/engine/types.d.ts.map +1 -0
  284. package/vendor/dynamic-workflow/engine/types.js +26 -0
  285. package/vendor/dynamic-workflow/engine/world-read-input.d.ts +10 -0
  286. package/vendor/dynamic-workflow/engine/world-read-input.d.ts.map +1 -0
  287. package/vendor/dynamic-workflow/engine/world-read-input.js +55 -0
  288. package/vendor/dynamic-workflow/facade/artifact-caps.d.ts +48 -0
  289. package/vendor/dynamic-workflow/facade/artifact-caps.d.ts.map +1 -0
  290. package/vendor/dynamic-workflow/facade/artifact-caps.js +47 -0
  291. package/vendor/dynamic-workflow/facade/dts-hole.d.ts +16 -0
  292. package/vendor/dynamic-workflow/facade/dts-hole.d.ts.map +1 -0
  293. package/vendor/dynamic-workflow/facade/dts-hole.js +26 -0
  294. package/vendor/dynamic-workflow/facade/dts-model.d.ts +11 -0
  295. package/vendor/dynamic-workflow/facade/dts-model.d.ts.map +1 -0
  296. package/vendor/dynamic-workflow/facade/dts-model.js +18 -0
  297. package/vendor/dynamic-workflow/facade/dts-stream.d.ts +15 -0
  298. package/vendor/dynamic-workflow/facade/dts-stream.d.ts.map +1 -0
  299. package/vendor/dynamic-workflow/facade/dts-stream.js +41 -0
  300. package/vendor/dynamic-workflow/facade/dts.d.ts +29 -0
  301. package/vendor/dynamic-workflow/facade/dts.d.ts.map +1 -0
  302. package/vendor/dynamic-workflow/facade/dts.js +324 -0
  303. package/vendor/dynamic-workflow/facade/registry.d.ts +218 -0
  304. package/vendor/dynamic-workflow/facade/registry.d.ts.map +1 -0
  305. package/vendor/dynamic-workflow/facade/registry.js +203 -0
  306. package/vendor/dynamic-workflow/facade/report-caps.d.ts +40 -0
  307. package/vendor/dynamic-workflow/facade/report-caps.d.ts.map +1 -0
  308. package/vendor/dynamic-workflow/facade/report-caps.js +39 -0
  309. package/vendor/dynamic-workflow/facade/world-read-caps.d.ts +37 -0
  310. package/vendor/dynamic-workflow/facade/world-read-caps.d.ts.map +1 -0
  311. package/vendor/dynamic-workflow/facade/world-read-caps.js +36 -0
  312. package/vendor/dynamic-workflow/index.d.ts +41 -0
  313. package/vendor/dynamic-workflow/index.d.ts.map +1 -0
  314. package/vendor/dynamic-workflow/index.js +51 -0
  315. package/vendor/dynamic-workflow/lowering/index.d.ts +2 -0
  316. package/vendor/dynamic-workflow/lowering/index.d.ts.map +1 -0
  317. package/vendor/dynamic-workflow/lowering/index.js +1 -0
  318. package/vendor/dynamic-workflow/lowering/lower-hole.d.ts +16 -0
  319. package/vendor/dynamic-workflow/lowering/lower-hole.d.ts.map +1 -0
  320. package/vendor/dynamic-workflow/lowering/lower-hole.js +63 -0
  321. package/vendor/dynamic-workflow/lowering/lower.d.ts +82 -0
  322. package/vendor/dynamic-workflow/lowering/lower.d.ts.map +1 -0
  323. package/vendor/dynamic-workflow/lowering/lower.js +333 -0
  324. package/vendor/dynamic-workflow/projections.d.ts +26 -0
  325. package/vendor/dynamic-workflow/projections.d.ts.map +1 -0
  326. package/vendor/dynamic-workflow/projections.js +23 -0
  327. package/vendor/dynamic-workflow/schema/actor-submit-profiles.d.ts +49 -0
  328. package/vendor/dynamic-workflow/schema/actor-submit-profiles.d.ts.map +1 -0
  329. package/vendor/dynamic-workflow/schema/actor-submit-profiles.js +69 -0
  330. package/vendor/dynamic-workflow/schema/emit.d.ts +55 -0
  331. package/vendor/dynamic-workflow/schema/emit.d.ts.map +1 -0
  332. package/vendor/dynamic-workflow/schema/emit.js +325 -0
  333. package/vendor/dynamic-workflow/schema/jsdoc.d.ts +10 -0
  334. package/vendor/dynamic-workflow/schema/jsdoc.d.ts.map +1 -0
  335. package/vendor/dynamic-workflow/schema/jsdoc.js +83 -0
  336. package/vendor/dynamic-workflow/schema/serialize.d.ts +8 -0
  337. package/vendor/dynamic-workflow/schema/serialize.d.ts.map +1 -0
  338. package/vendor/dynamic-workflow/schema/serialize.js +20 -0
  339. package/vendor/dynamic-workflow/schema/synthesize.d.ts +48 -0
  340. package/vendor/dynamic-workflow/schema/synthesize.d.ts.map +1 -0
  341. package/vendor/dynamic-workflow/schema/synthesize.js +138 -0
  342. package/vendor/dynamic-workflow/schema/types.d.ts +67 -0
  343. package/vendor/dynamic-workflow/schema/types.d.ts.map +1 -0
  344. package/vendor/dynamic-workflow/schema/types.js +18 -0
  345. package/vendor/dynamic-workflow/schema/validate.d.ts +15 -0
  346. package/vendor/dynamic-workflow/schema/validate.d.ts.map +1 -0
  347. package/vendor/dynamic-workflow/schema/validate.js +213 -0
  348. package/vendor/dynamic-workflow/testing/index.d.ts +6 -0
  349. package/vendor/dynamic-workflow/testing/index.d.ts.map +1 -0
  350. package/vendor/dynamic-workflow/testing/index.js +5 -0
  351. package/vendor/dynamic-workflow/testing/journal-contract-artifacts.d.ts +9 -0
  352. package/vendor/dynamic-workflow/testing/journal-contract-artifacts.d.ts.map +1 -0
  353. package/vendor/dynamic-workflow/testing/journal-contract-artifacts.js +195 -0
  354. package/vendor/dynamic-workflow/testing/journal-contract-events.d.ts +9 -0
  355. package/vendor/dynamic-workflow/testing/journal-contract-events.d.ts.map +1 -0
  356. package/vendor/dynamic-workflow/testing/journal-contract-events.js +163 -0
  357. package/vendor/dynamic-workflow/testing/journal-contract-helpers.d.ts +9 -0
  358. package/vendor/dynamic-workflow/testing/journal-contract-helpers.d.ts.map +1 -0
  359. package/vendor/dynamic-workflow/testing/journal-contract-helpers.js +12 -0
  360. package/vendor/dynamic-workflow/testing/journal-contract-isolation.d.ts +9 -0
  361. package/vendor/dynamic-workflow/testing/journal-contract-isolation.d.ts.map +1 -0
  362. package/vendor/dynamic-workflow/testing/journal-contract-isolation.js +46 -0
  363. package/vendor/dynamic-workflow/testing/journal-contract-nodes.d.ts +9 -0
  364. package/vendor/dynamic-workflow/testing/journal-contract-nodes.d.ts.map +1 -0
  365. package/vendor/dynamic-workflow/testing/journal-contract-nodes.js +234 -0
  366. package/vendor/dynamic-workflow/testing/journal-contract-reads.d.ts +11 -0
  367. package/vendor/dynamic-workflow/testing/journal-contract-reads.d.ts.map +1 -0
  368. package/vendor/dynamic-workflow/testing/journal-contract-reads.js +281 -0
  369. package/vendor/dynamic-workflow/testing/journal-contract-runs.d.ts +9 -0
  370. package/vendor/dynamic-workflow/testing/journal-contract-runs.d.ts.map +1 -0
  371. package/vendor/dynamic-workflow/testing/journal-contract-runs.js +396 -0
  372. package/vendor/dynamic-workflow/testing/journal-contract-script.d.ts +12 -0
  373. package/vendor/dynamic-workflow/testing/journal-contract-script.d.ts.map +1 -0
  374. package/vendor/dynamic-workflow/testing/journal-contract-script.js +82 -0
  375. package/vendor/dynamic-workflow/testing/journal-contract.d.ts +15 -0
  376. package/vendor/dynamic-workflow/testing/journal-contract.d.ts.map +1 -0
  377. package/vendor/dynamic-workflow/testing/journal-contract.js +31 -0
  378. package/vendor/dynamic-workflow-runtime/child-cell-streams.js +128 -0
  379. package/vendor/dynamic-workflow-runtime/child-entry-file.js +43 -0
  380. package/vendor/dynamic-workflow-runtime/child-source.js +299 -0
  381. package/vendor/dynamic-workflow-runtime/harness.js +302 -0
  382. package/vendor/dynamic-workflow-runtime/index.js +4 -0
  383. package/vendor/dynamic-workflow-runtime/protocol.js +2 -0
  384. package/vendor/mcode-host/dynamic-workflow-import.js +269 -0
  385. package/vendor/mcode-host/workflow-git-world-read.js +183 -0
  386. package/vendor/mcode-host/workflow-world-read.js +282 -0
@@ -0,0 +1,1387 @@
1
+ // dsh-workflow engine adapter.
2
+ //
3
+ // Executes the MCode engine with native DSH child sessions and durable journals.
4
+
5
+ import {
6
+ buildImportedCache,
7
+ preflightAmendImport,
8
+ } from "../vendor/mcode-host/dynamic-workflow-import.js";
9
+ import { runWorkflowScript } from "../vendor/dynamic-workflow-runtime/index.js";
10
+ import {
11
+ existsSync,
12
+ mkdirSync,
13
+ readFileSync,
14
+ readdirSync,
15
+ rmSync,
16
+ statSync,
17
+ realpathSync,
18
+ writeFileSync,
19
+ appendFileSync,
20
+ symlinkSync,
21
+ } from "node:fs";
22
+ import { homedir } from "node:os";
23
+ import path from "node:path";
24
+ import { fileURLToPath, pathToFileURL } from "node:url";
25
+ import { ARTIFACT_CAPS } from "../vendor/dynamic-workflow/index.js";
26
+ import { createWorldDriver } from "./world-driver.js";
27
+ import { projectRun } from "./projection.js";
28
+ import { collectSessionStats } from "./host-driver.js";
29
+ import { randomUUID } from "node:crypto";
30
+
31
+ const PLUGIN_ROOT = path.resolve(
32
+ path.dirname(fileURLToPath(import.meta.url)),
33
+ "..",
34
+ );
35
+ const VENDOR_URL = pathToFileURL(
36
+ path.join(PLUGIN_ROOT, "vendor", "dynamic-workflow", "index.js"),
37
+ ).href;
38
+
39
+ // ---------------------------------------------------------------------------
40
+ // Configuration
41
+ // ---------------------------------------------------------------------------
42
+
43
+ /** Default workflows dir; overridable via configure({ dir }). */
44
+ export let WORKFLOWS_DIR = path.join(homedir(), ".dsh", "workflows");
45
+
46
+ const config = {
47
+ onChange: () => {},
48
+ driverFactory: undefined,
49
+ /** Path to a typescript installation, used only when bare `import "typescript"` fails. */
50
+ typescriptPath: undefined,
51
+ /** Default max concurrency for new runs. */
52
+ maxConcurrency: 4,
53
+ };
54
+
55
+ /** configure({ dir?, typescriptPath?, maxConcurrency? }) */
56
+ export function configure(opts = {}) {
57
+ if (opts.transcripts) config.transcripts = opts.transcripts;
58
+ if (opts.onSettled) config.onSettled = opts.onSettled;
59
+ if (opts.onChange) config.onChange = opts.onChange;
60
+ if (opts.driverFactory) config.driverFactory = opts.driverFactory;
61
+ if (opts.dir !== undefined) WORKFLOWS_DIR = path.resolve(opts.dir);
62
+ if (opts.typescriptPath !== undefined)
63
+ config.typescriptPath = path.resolve(opts.typescriptPath);
64
+ if (opts.maxConcurrency !== undefined)
65
+ config.maxConcurrency = Math.max(1, Math.floor(opts.maxConcurrency));
66
+ }
67
+
68
+ function runsRoot() {
69
+ return path.join(WORKFLOWS_DIR, "runs");
70
+ }
71
+
72
+ // ---------------------------------------------------------------------------
73
+ // Lazy vendor + typescript loading
74
+ // ---------------------------------------------------------------------------
75
+
76
+ async function ensureTypescript() {
77
+ try {
78
+ await import("typescript");
79
+ return;
80
+ } catch {
81
+ /* fall through */
82
+ }
83
+ const target = config.typescriptPath;
84
+ if (!target)
85
+ throw new Error(
86
+ "缺少 TypeScript 依赖,请在 dsh-workflow 中运行 npm install",
87
+ );
88
+ const link = path.join(PLUGIN_ROOT, "node_modules", "typescript");
89
+ if (!existsSync(link)) {
90
+ if (!existsSync(target)) {
91
+ throw new Error(
92
+ `dsh-workflow: typescript is required by vendor/dynamic-workflow but is not resolvable. ` +
93
+ `Either add typescript@^5 to the plugin's package.json, or call configure({ typescriptPath: "<dir with typescript/package.json>" }). ` +
94
+ `(Tried bare import and path: ${target})`,
95
+ );
96
+ }
97
+ mkdirSync(path.dirname(link), { recursive: true });
98
+ symlinkSync(target, link, "dir");
99
+ }
100
+ await import("typescript");
101
+ }
102
+
103
+ let vendorPromise = undefined;
104
+ /** Set once vendor() resolves; used to mint engine-shaped errors. */
105
+ let WorkflowErrorCtor = undefined;
106
+
107
+ async function vendor() {
108
+ if (!vendorPromise) {
109
+ vendorPromise = (async () => {
110
+ await ensureTypescript();
111
+ const mod = await import(VENDOR_URL);
112
+ WorkflowErrorCtor = mod.WorkflowError;
113
+ return mod;
114
+ })();
115
+ }
116
+ return vendorPromise;
117
+ }
118
+
119
+ // ---------------------------------------------------------------------------
120
+ // Journal: JournalStorePort as flat files under runs/<runId>/
121
+ // script.dwf.ts — the author's script text (written once at createRun)
122
+ // journal.jsonl — append-only log of run/actor/node record writes
123
+ // events.jsonl — append-only event log with per-run sequences
124
+ // state.json — checkpoint (run row snapshot + pending asks + live flags)
125
+ // Loading = replaying journal.jsonl + events.jsonl into the in-memory maps,
126
+ // which is exactly the engine's documented resume-by-replay substrate.
127
+ // ---------------------------------------------------------------------------
128
+
129
+ class FileJournalStore {
130
+ constructor(dir, runId, scriptText) {
131
+ this.dir = dir;
132
+ this.runId = runId;
133
+ this.runs = new Map(); // runId -> RunRecord (mutable copy)
134
+ this.actors = new Map(); // `${siteId}#${ordinal}` -> ActorRecord
135
+ this.nodes = new Map(); // `${siteId}#${ordinal}` -> NodeRecord
136
+ this.events = []; // StoredEvent[]
137
+ if (scriptText !== undefined) {
138
+ mkdirSync(dir, { recursive: true });
139
+ writeFileSync(path.join(dir, "script.dwf.ts"), scriptText, "utf8");
140
+ }
141
+ this.load();
142
+ }
143
+
144
+ load() {
145
+ const jl = path.join(this.dir, "journal.jsonl");
146
+ if (existsSync(jl)) {
147
+ for (const line of readFileSync(jl, "utf8").split("\n")) {
148
+ if (!line.trim()) continue;
149
+ const { op, record } = JSON.parse(line);
150
+ if (op === "createRun") this.runs.set(record.runId, record);
151
+ else if (op === "putActor")
152
+ this.actors.set(actorKey(record), { ...record });
153
+ else if (op === "putNode")
154
+ this.nodes.set(nodeKey(record), { ...record });
155
+ else if (op === "run")
156
+ this.runs.set(record.runId, {
157
+ ...this.runs.get(record.runId),
158
+ ...record,
159
+ });
160
+ }
161
+ }
162
+ const el = path.join(this.dir, "events.jsonl");
163
+ if (existsSync(el)) {
164
+ for (const line of readFileSync(el, "utf8").split("\n")) {
165
+ if (line.trim()) this.events.push(JSON.parse(line));
166
+ }
167
+ }
168
+ }
169
+
170
+ appendJournal(op, record) {
171
+ appendFileSync(
172
+ path.join(this.dir, "journal.jsonl"),
173
+ JSON.stringify({ op, record }) + "\n",
174
+ );
175
+ }
176
+
177
+ persistState(extra = {}) {
178
+ try {
179
+ const run = this.runs.get(this.runId);
180
+ writeFileSync(
181
+ path.join(this.dir, "state.json"),
182
+ JSON.stringify(
183
+ {
184
+ runId: this.runId,
185
+ run,
186
+ ...extra,
187
+ updatedAt: new Date().toISOString(),
188
+ },
189
+ null,
190
+ 2,
191
+ ),
192
+ );
193
+ } catch {
194
+ /* best-effort checkpoint */
195
+ }
196
+ }
197
+
198
+ persistRecoveredUsage() {
199
+ let extra = {};
200
+ try {
201
+ const { runId, run, updatedAt, ...previous } = JSON.parse(
202
+ readFileSync(path.join(this.dir, "state.json"), "utf8"),
203
+ );
204
+ extra = previous;
205
+ } catch {
206
+ /* no prior checkpoint */
207
+ }
208
+ this.persistState(extra);
209
+ }
210
+
211
+ // --- JournalStorePort ---
212
+ createRun(record) {
213
+ if (this.runs.has(record.runId)) {
214
+ throw new Error(`duplicate run: ${record.runId}`);
215
+ }
216
+ this.runs.set(record.runId, { ...record });
217
+ this.appendJournal("createRun", record);
218
+ }
219
+ getRun(runId) {
220
+ const run = this.runs.get(runId);
221
+ return run === undefined ? undefined : { ...run };
222
+ }
223
+ updateRunStatus(runId, status, settlement) {
224
+ const run = this.runs.get(runId);
225
+ if (!run) return;
226
+ const next = { ...run, status };
227
+ if (status === "running") {
228
+ // non-terminal flip clears the settlement fields
229
+ delete next.result;
230
+ delete next.failure;
231
+ delete next.stopReason;
232
+ delete next.supersededBy;
233
+ } else if (status === "completed") {
234
+ if (settlement?.result !== undefined) next.result = settlement.result;
235
+ delete next.failure;
236
+ delete next.stopReason;
237
+ delete next.supersededBy;
238
+ } else if (status === "errored") {
239
+ if (settlement?.failure !== undefined) next.failure = settlement.failure;
240
+ delete next.result;
241
+ delete next.stopReason;
242
+ delete next.supersededBy;
243
+ } else if (status === "stopped") {
244
+ next.stopReason = settlement?.stopReason ?? "user";
245
+ if (settlement?.supersededBy !== undefined)
246
+ next.supersededBy = settlement.supersededBy;
247
+ if (settlement?.failure !== undefined) next.failure = settlement.failure;
248
+ delete next.result;
249
+ }
250
+ this.runs.set(runId, next);
251
+ this.appendJournal("run", next);
252
+ }
253
+ updateRunUsage(runId, spentTokens) {
254
+ const run = this.runs.get(runId);
255
+ if (!run) return;
256
+ const next = { ...run, spentTokens };
257
+ this.runs.set(runId, next);
258
+ this.appendJournal("run", next);
259
+ }
260
+ updateRunCaps(runId, caps) {
261
+ const run = this.runs.get(runId);
262
+ if (!run) return;
263
+ const next = { ...run, caps: { ...caps } };
264
+ this.runs.set(runId, next);
265
+ this.appendJournal("run", next);
266
+ }
267
+ updateRunScript(runId, scriptText, scriptHash) {
268
+ const run = this.runs.get(runId);
269
+ if (!run) return;
270
+ const next = { ...run, scriptText, scriptHash };
271
+ this.runs.set(runId, next);
272
+ this.appendJournal("run", next);
273
+ writeFileSync(path.join(this.dir, "script.dwf.ts"), scriptText, "utf8");
274
+ }
275
+ putActor(record) {
276
+ const key = actorKey(record);
277
+ const existing = this.actors.get(key);
278
+ // carry driver-owned fields forward on a re-put (same contract as production)
279
+ const merged = { ...(existing ?? {}), ...record };
280
+ if (record.sessionId === undefined && existing?.sessionId !== undefined)
281
+ merged.sessionId = existing.sessionId;
282
+ if (existing?.resolvedModel !== undefined)
283
+ merged.resolvedModel = existing.resolvedModel;
284
+ this.actors.set(key, merged);
285
+ this.appendJournal("putActor", merged);
286
+ }
287
+ getActor(runId, siteId, ordinal) {
288
+ const a = this.actors.get(`${siteId}#${ordinal}`);
289
+ return a && a.runId === runId ? { ...a } : undefined;
290
+ }
291
+ listActors(runId, opts) {
292
+ return [...this.actors.values()]
293
+ .filter((a) => a.runId === runId)
294
+ .filter((a) => opts.name === undefined || a.name === opts.name)
295
+ .map((a) =>
296
+ opts.withPersona ? { ...a } : (({ persona, ...rest }) => rest)(a),
297
+ );
298
+ }
299
+ putNode(record) {
300
+ const key = nodeKey(record);
301
+ const existing = this.nodes.get(key);
302
+ const merged = { ...(existing ?? {}), ...record };
303
+ this.nodes.set(key, merged);
304
+ this.appendJournal("putNode", merged);
305
+ }
306
+ getNode(runId, siteId, ordinal, opts) {
307
+ const n = this.nodes.get(`${siteId}#${ordinal}`);
308
+ if (!n || n.runId !== runId) return undefined;
309
+ return opts?.withResult === false
310
+ ? (({ result, ...rest }) => rest)(n)
311
+ : { ...n };
312
+ }
313
+ listNodes(runId, opts) {
314
+ const kinds = opts.kinds === "all" ? null : new Set(opts.kinds);
315
+ const rows = [...this.nodes.values()]
316
+ .filter((n) => n.runId === runId)
317
+ .filter((n) => kinds === null || kinds.has(n.kind))
318
+ .map((n) =>
319
+ opts.withResult ? { ...n } : (({ result, ...rest }) => rest)(n),
320
+ );
321
+ if (opts.limit !== undefined) return rows.slice(0, opts.limit);
322
+ return rows;
323
+ }
324
+ countNodes(runId, kind) {
325
+ let c = 0;
326
+ for (const n of this.nodes.values())
327
+ if (n.runId === runId && n.kind === kind) c++;
328
+ return c;
329
+ }
330
+ sumResultBytes(runId, kind) {
331
+ let s = 0;
332
+ for (const n of this.nodes.values()) {
333
+ if (n.runId === runId && n.kind === kind && n.result !== undefined) {
334
+ s += Buffer.byteLength(JSON.stringify(n.result) ?? "", "utf8");
335
+ }
336
+ }
337
+ return s;
338
+ }
339
+ appendEvent(runId, event) {
340
+ const sequence =
341
+ this.events.length === 0
342
+ ? 0
343
+ : this.events[this.events.length - 1].sequence + 1;
344
+ const stored = { sequence, event, timeCreated: Date.now() };
345
+ this.events.push(stored);
346
+ appendFileSync(
347
+ path.join(this.dir, "events.jsonl"),
348
+ JSON.stringify(stored) + "\n",
349
+ );
350
+ config.onChange({ runId, event });
351
+ return { sequence, event };
352
+ }
353
+ listEvents(runId, opts) {
354
+ const types = opts.types === "all" ? null : new Set(opts.types);
355
+ const after = opts.afterSequence ?? -1;
356
+ const limit =
357
+ opts.limit === undefined || opts.limit === -1 ? Infinity : opts.limit;
358
+ let reportSeen = 0;
359
+ const reportLimit =
360
+ opts.reportItems === "all" ? Infinity : opts.reportItems.limit;
361
+ const out = [];
362
+ for (const stored of this.events) {
363
+ if (stored.sequence <= after) continue;
364
+ if (types !== null && !types.has(stored.event.type)) continue;
365
+ if (out.length >= limit) break;
366
+ let e = stored.event;
367
+ if (e.type === "report") {
368
+ if (reportSeen >= reportLimit) e = { ...e, item: undefined };
369
+ reportSeen++;
370
+ }
371
+ out.push({ ...stored, event: e });
372
+ }
373
+ return out;
374
+ }
375
+ }
376
+
377
+ function actorKey(r) {
378
+ return `${r.siteId}#${r.ordinal}`;
379
+ }
380
+ function nodeKey(r) {
381
+ return `${r.siteId}#${r.ordinal}`;
382
+ }
383
+
384
+ // ---------------------------------------------------------------------------
385
+ // LocalDriver (Boundary B) — agent-driven, no LLM in-process.
386
+ // startAsk records the pending ask and returns WITHOUT blocking; the ask promise
387
+ // inside the engine stays pending until submitAsk() feeds the sink.
388
+ // ---------------------------------------------------------------------------
389
+
390
+ class LocalDriver {
391
+ constructor(runId, journal, workspaceRoot, hooks) {
392
+ this.runId = runId;
393
+ this.journal = journal;
394
+ this.workspaceRoot = workspaceRoot;
395
+ this.hooks = hooks; // { onPendingChange }
396
+ this.pending = new Map(); // instanceKey -> { instance, key, instructions, typed, schema, actorRef, actorName, sessionId }
397
+ this.actorsBySession = new Map(); // sessionId -> { actor, persona }
398
+ this.submitWaiters = new Map(); // instanceKey -> deferred verdict
399
+ this.disposed = false;
400
+ this.runtime = hooks.runtime;
401
+ this.world = createWorldDriver(workspaceRoot);
402
+ }
403
+
404
+ async createActorSession(actor, persona, seed) {
405
+ if (!seed && this.runtime) {
406
+ const previousActor = this.journal.getActor(
407
+ this.runId,
408
+ actor.siteId,
409
+ actor.ordinal,
410
+ );
411
+ const previous = previousActor?.sessionId;
412
+ const events = previous && config.transcripts?.read(previous);
413
+ if (events?.length)
414
+ seed = {
415
+ sourceSessionId: previous,
416
+ messageCount: events.length,
417
+ resolvedModel: previousActor.resolvedModel,
418
+ };
419
+ }
420
+ const sessionId = this.runtime
421
+ ? await this.runtime.createActor(
422
+ actor,
423
+ persona,
424
+ seed,
425
+ (resolvedModel) => {
426
+ const record = this.journal.getActor(
427
+ this.runId,
428
+ actor.siteId,
429
+ actor.ordinal,
430
+ );
431
+ if (record) {
432
+ this.journal.actors.set(actorKey(record), {
433
+ ...record,
434
+ resolvedModel,
435
+ });
436
+ this.journal.appendJournal("putActor", {
437
+ ...record,
438
+ resolvedModel,
439
+ });
440
+ }
441
+ },
442
+ )
443
+ : `dwf-${randomUUID()}`;
444
+ this.actorsBySession.set(sessionId, { actor, persona });
445
+ return { id: sessionId };
446
+ }
447
+
448
+ startAsk(session, instance, message) {
449
+ const key = ref(instance);
450
+ const info = this.actorsBySession.get(session.id);
451
+ this.pending.set(key, {
452
+ key,
453
+ instance: { ...instance },
454
+ sessionId: session.id,
455
+ actor: info?.actor ? { ...info.actor } : undefined,
456
+ actorName:
457
+ (info?.persona?.name ?? info?.persona?.name === "")
458
+ ? info?.persona?.name
459
+ : info?.persona?.name || undefined,
460
+ instructions: message.instructions,
461
+ typed: message.typed,
462
+ schema: message.schema ?? null,
463
+ });
464
+ this.journal.persistState({ pendingAsks: [...this.pending.keys()] });
465
+ this.hooks.onPendingChange?.();
466
+ if (this.runtime)
467
+ void this.runtime.ask(
468
+ { ...this.pending.get(key), instance: key },
469
+ (error) => {
470
+ const run = live.get(this.runId);
471
+ if (run && this.pending.has(key))
472
+ run.engine.askFailed(
473
+ instance,
474
+ new WorkflowErrorCtor("DriverError", error.message),
475
+ );
476
+ },
477
+ {
478
+ mutating: () => live.get(this.runId)?.engine.askMutating(instance),
479
+ ended: async (finalText) => {
480
+ const run = live.get(this.runId);
481
+ if (!run || !this.pending.has(key)) return;
482
+ await finishSubmission(
483
+ run,
484
+ this.pending.get(key),
485
+ instance,
486
+ key,
487
+ false,
488
+ );
489
+ run.engine.askTurnEnded(instance, finalText);
490
+ if (!message.typed) {
491
+ this.pending.delete(key);
492
+ this.journal.persistState({
493
+ pendingAsks: [...this.pending.keys()],
494
+ });
495
+ }
496
+ },
497
+ },
498
+ );
499
+ }
500
+
501
+ respondToSubmit(instance, verdict) {
502
+ const key = ref(instance);
503
+ if (verdict.kind === "nudge") {
504
+ const pending = this.pending.get(key);
505
+ if (pending) void this.runtime?.nudge?.(pending.sessionId);
506
+ }
507
+ const waiter = this.submitWaiters.get(key);
508
+ if (waiter) {
509
+ this.submitWaiters.delete(key);
510
+ waiter(verdict);
511
+ }
512
+ }
513
+
514
+ cancelAsk(instance) {
515
+ const key = ref(instance);
516
+ const waiter = this.submitWaiters.get(key);
517
+ if (waiter) {
518
+ this.submitWaiters.delete(key);
519
+ waiter({ kind: "cancel" });
520
+ }
521
+ const pending = this.pending.get(key);
522
+ if (pending) this.runtime?.cancel(pending.sessionId);
523
+ if (this.pending.delete(key)) {
524
+ this.journal.persistState({ pendingAsks: [...this.pending.keys()] });
525
+ this.hooks.onPendingChange?.();
526
+ }
527
+ }
528
+
529
+ async executeWorldRead(op, args) {
530
+ return this.world.execute(op, args);
531
+ }
532
+
533
+ async executeArtifactPublish(request) {
534
+ const dir = path.join(runsRoot(), this.runId, "artifacts");
535
+ mkdirSync(dir, { recursive: true });
536
+ const filename = `${encodeURIComponent(request.id)}-${request.version}`;
537
+ const maxBytes =
538
+ request.op === "markdown"
539
+ ? ARTIFACT_CAPS.maxMarkdownBytes
540
+ : ARTIFACT_CAPS.maxFileBytes;
541
+ if (
542
+ request.op === "file" &&
543
+ statSync(resolveWithin(this.workspaceRoot, request.path)).size > maxBytes
544
+ )
545
+ throw new WorkflowErrorCtor("ArtifactTooLarge", "产物超过 20MB 限制");
546
+ const content =
547
+ request.op === "markdown"
548
+ ? Buffer.from(request.content ?? "")
549
+ : readFileSync(resolveWithin(this.workspaceRoot, request.path));
550
+ if (content.length > maxBytes)
551
+ throw new WorkflowErrorCtor("ArtifactTooLarge", "产物内容超过大小限制");
552
+ const ext = path.extname(request.path ?? "").toLowerCase();
553
+ const contentType =
554
+ request.opts?.contentType ??
555
+ (request.op === "markdown" || ext === ".md"
556
+ ? "text/markdown"
557
+ : ({
558
+ ".html": "text/html",
559
+ ".json": "application/json",
560
+ ".png": "image/png",
561
+ ".jpg": "image/jpeg",
562
+ ".svg": "image/svg+xml",
563
+ ".pdf": "application/pdf",
564
+ }[ext] ?? "application/octet-stream"));
565
+ if (!/^[\w.+-]+\/[\w.+-]+$/.test(contentType))
566
+ throw new Error("contentType 必须是有效 MIME 类型");
567
+ writeFileSync(path.join(dir, filename), content);
568
+ return {
569
+ id: request.id,
570
+ kind: request.op,
571
+ version: request.version ?? 1,
572
+ title: request.opts?.title ?? request.id,
573
+ description: request.opts?.description,
574
+ contentType,
575
+ bytes: content.length,
576
+ uri: `dsh-workflow://${this.runId}/${filename}`,
577
+ publishedAt: Date.now(),
578
+ };
579
+ }
580
+
581
+ emit(_event) {
582
+ /* events are already in the journal; the host reads them from there */
583
+ }
584
+
585
+ dispose() {
586
+ if (this.disposed) return;
587
+ this.disposed = true;
588
+ this.world.dispose();
589
+ this.runtime?.dispose(
590
+ this.journal.getRun(this.runId)?.status === "completed",
591
+ );
592
+ }
593
+ }
594
+
595
+ function ref(instance) {
596
+ return `${instance.siteId}@${instance.ordinal}`;
597
+ }
598
+
599
+ export function parseInstance(instance) {
600
+ if (typeof instance === "string") {
601
+ const at = instance.lastIndexOf("@");
602
+ if (at < 0)
603
+ throw new Error(
604
+ `bad instance "${instance}" — expected "<siteId>@<ordinal>"`,
605
+ );
606
+ return {
607
+ siteId: instance.slice(0, at),
608
+ ordinal: Number(instance.slice(at + 1)),
609
+ };
610
+ }
611
+ if (
612
+ instance &&
613
+ typeof instance === "object" &&
614
+ typeof instance.siteId === "string"
615
+ ) {
616
+ return { siteId: instance.siteId, ordinal: Number(instance.ordinal) };
617
+ }
618
+ throw new Error(`bad instance ${JSON.stringify(instance)}`);
619
+ }
620
+
621
+ // ---------------------------------------------------------------------------
622
+ // World operations use the upstream MCode ports over native files and processes.
623
+ // Run registry
624
+ // ---------------------------------------------------------------------------
625
+
626
+ const live = new Map(); // runId -> { runId, engine, driver, journal, scriptText, askSpecs, sitePhases, phaseNames, holeBodies, lowered, settlement? }
627
+
628
+ async function compileProduct(code) {
629
+ const v = await vendor();
630
+ const analysis = v.analyzeWorkflowScript(code);
631
+ if (!analysis.ok) {
632
+ const err = new Error(
633
+ `workflow script failed analysis:\n${analysis.diagnostics.map((d) => `${d.line}:${d.column} ${d.code} ${d.message}`).join("\n")}`,
634
+ );
635
+ err.diagnostics = analysis.diagnostics;
636
+ throw err;
637
+ }
638
+ const loweredResult = v.lowerWorkflowScript(code);
639
+ if (!loweredResult.ok || !loweredResult.lowered) {
640
+ throw new Error("workflow script could not be lowered");
641
+ }
642
+ const program = v.createWorkflowProgram(code);
643
+ const table = v.collectSites(program);
644
+ const schemas = v.synthesizeAskSchemas(program, table);
645
+ const askSpecs = v.buildAskSpecs(table, schemas.schemas);
646
+ const sitePhases = v.collectSitePhases(analysis.core);
647
+ const { phaseNames, holes } = v.collectPhaseNames(analysis.flow);
648
+ return {
649
+ v,
650
+ analysis,
651
+ lowered: loweredResult.lowered,
652
+ askSpecs,
653
+ sitePhases,
654
+ phaseNames,
655
+ holes,
656
+ };
657
+ }
658
+
659
+ /**
660
+ * createRun({ name, code, args? }) -> { runId }
661
+ * Lowers, constructs WorkflowEngine with a LocalDriver, persists everything and
662
+ * starts execution. Facade calls that don't need the agent (phase/log/report/
663
+ * worldRead file ops) run through; asks block until submitAsk().
664
+ */
665
+ export async function createRun({
666
+ name,
667
+ code,
668
+ args,
669
+ cwd,
670
+ parentSessionId,
671
+ toolCallId,
672
+ groupId,
673
+ savedName,
674
+ maxConcurrency,
675
+ runtime,
676
+ createdSeq,
677
+ resumedFrom,
678
+ importedCache,
679
+ inheritedTokens,
680
+ model,
681
+ reasoningEffort,
682
+ } = {}) {
683
+ if (typeof code !== "string" || !code.trim())
684
+ throw new Error("createRun: code (workflow script source) is required");
685
+ const product = await compileProduct(code);
686
+ const { v } = product;
687
+ const runId = `dwfrun-${randomUUID()}`;
688
+ const dir = path.join(runsRoot(), runId);
689
+ const workspaceRoot = path.resolve(cwd ?? process.cwd());
690
+ const journal = new FileJournalStore(dir, runId, code);
691
+ const driver = new LocalDriver(runId, journal, workspaceRoot, {
692
+ runtime:
693
+ runtime ??
694
+ config.driverFactory?.({
695
+ runId,
696
+ parentSessionId,
697
+ cwd: workspaceRoot,
698
+ model,
699
+ reasoningEffort,
700
+ }),
701
+ });
702
+ const scriptHash = v.fnv1a(v.canonicalJson(code));
703
+ const engineOptions = {
704
+ runId,
705
+
706
+ caps: { maxConcurrency: maxConcurrency ?? config.maxConcurrency },
707
+ parentSessionId,
708
+ toolCallId,
709
+ resumedFrom,
710
+ importedCache,
711
+ inheritedTokens,
712
+ askSpecs: product.askSpecs,
713
+ validate: v.validate,
714
+ sitePhases: product.sitePhases,
715
+ scriptText: code,
716
+ scriptHash,
717
+ name,
718
+ args: args ?? {},
719
+ cwd: workspaceRoot,
720
+ };
721
+ const run = {
722
+ runId,
723
+ engineOptions,
724
+ driver,
725
+ journal,
726
+ scriptText: code,
727
+ scriptHash,
728
+ askSpecs: product.askSpecs,
729
+ sitePhases: product.sitePhases,
730
+ phaseNames: product.phaseNames,
731
+ holeBodies: product.lowered.holeBodies,
732
+ loweredCode: product.lowered.code,
733
+ dir,
734
+ workspaceRoot,
735
+ name,
736
+ // MCode 在子进程沙箱里把实参冻结成 `__host.args` 全局(child-source.ts);引擎本体不
737
+ // 暴露 args。进程内执行的 host 对象必须补上同一形状,否则脚本读 `args.x` 直接 TypeError。
738
+ args: Object.freeze(JSON.parse(JSON.stringify(args ?? {}))),
739
+ };
740
+ writeFileSync(
741
+ path.join(dir, "plan.json"),
742
+ JSON.stringify(v.encodeAnalysisCore(product.analysis.core)),
743
+ );
744
+ writeFileSync(
745
+ path.join(dir, "meta.json"),
746
+ JSON.stringify({
747
+ groupId,
748
+ savedName,
749
+ parentSessionId,
750
+ toolCallId,
751
+ createdSeq,
752
+ cwd: workspaceRoot,
753
+ model,
754
+ reasoningEffort,
755
+ }),
756
+ );
757
+ live.set(runId, run);
758
+ startExecution(run);
759
+ return { runId };
760
+ }
761
+
762
+ function startExecution(run) {
763
+ run.settled = runWorkflowScript({
764
+ ...run.engineOptions,
765
+ lowered: run.loweredCode,
766
+ args: run.args,
767
+ cwd: run.workspaceRoot,
768
+ makeDriver: () => run.driver,
769
+ control: {
770
+ bind(engine) {
771
+ run.engine = engine;
772
+ },
773
+ },
774
+ })
775
+ .then(async (settlement) => {
776
+ await run.driver.runtime?.closed?.();
777
+ run.settlement = settlement;
778
+ run.journal.persistState({
779
+ pendingAsks: [...run.driver.pending.keys()],
780
+ settlement,
781
+ });
782
+ live.delete(run.runId);
783
+ config.onChange();
784
+ void Promise.resolve(config.onSettled?.(run.runId)).catch(() => {});
785
+ return settlement;
786
+ })
787
+ .catch((error) => {
788
+ live.delete(run.runId);
789
+ run.driver.dispose();
790
+ config.onChange();
791
+ throw error;
792
+ });
793
+ }
794
+
795
+ /** resumeRun(runId): replay per the engine's documented resume path. */
796
+ export async function resumeRun(runId, { runtime } = {}) {
797
+ const existing = live.get(runId);
798
+ if (existing) return { runId, alreadyRunning: true };
799
+ const dir = path.join(runsRoot(), runId);
800
+ const scriptPath = path.join(dir, "script.dwf.ts");
801
+ if (!existsSync(scriptPath))
802
+ throw new Error(`resumeRun: no such run "${runId}" under ${runsRoot()}`);
803
+ const code = readFileSync(scriptPath, "utf8");
804
+ const product = await compileProduct(code);
805
+ const { v } = product;
806
+ const journal = new FileJournalStore(dir, runId);
807
+ const record = journal.getRun(runId);
808
+ if (!record)
809
+ throw new Error(`resumeRun: journal has no run record for ${runId}`);
810
+ if (
811
+ record.status === "completed" ||
812
+ record.status === "errored" ||
813
+ record.stopReason === "superseded"
814
+ ) {
815
+ throw new Error(
816
+ `resumeRun: run ${runId} is ${record.status}; only stopped runs resume (amend instead)`,
817
+ );
818
+ }
819
+ const meta = existsSync(path.join(dir, "meta.json"))
820
+ ? JSON.parse(readFileSync(path.join(dir, "meta.json"), "utf8"))
821
+ : {};
822
+ const importedCache = record.resumedFrom
823
+ ? (await buildImportedCache(importDeps(), record.resumedFrom)).cache
824
+ : undefined;
825
+ const workspaceRoot = record.cwd ?? process.cwd();
826
+ const driver = new LocalDriver(runId, journal, workspaceRoot, {
827
+ runtime:
828
+ runtime ??
829
+ config.driverFactory?.({
830
+ runId,
831
+ parentSessionId: record.parentSessionId,
832
+ cwd: workspaceRoot,
833
+ model: meta.model,
834
+ reasoningEffort: meta.reasoningEffort,
835
+ }),
836
+ });
837
+ const engineOptions = {
838
+ runId,
839
+
840
+ caps: record.caps,
841
+ importedCache,
842
+ askSpecs: product.askSpecs,
843
+ validate: v.validate,
844
+ sitePhases: product.sitePhases,
845
+ scriptHash: record.scriptHash ?? v.fnv1a(v.canonicalJson(code)),
846
+ };
847
+ const run = {
848
+ runId,
849
+ engineOptions,
850
+ driver,
851
+ journal,
852
+ scriptText: code,
853
+ askSpecs: product.askSpecs,
854
+ sitePhases: product.sitePhases,
855
+ phaseNames: product.phaseNames,
856
+ holeBodies: product.lowered.holeBodies,
857
+ loweredCode: product.lowered.code,
858
+ dir,
859
+ workspaceRoot,
860
+ name: record.name,
861
+ // resume 同 createRun:args 从 journal 的 run 行读回(record.args),冻结后给 host。
862
+ args: Object.freeze(JSON.parse(JSON.stringify(record.args ?? {}))),
863
+ };
864
+ live.set(runId, run);
865
+ startExecution(run);
866
+ return { runId };
867
+ }
868
+
869
+ /** stopRun(runId, reason?): stop("user"|"model"|"interrupted"). */
870
+ export async function stopRun(runId, reason = "user") {
871
+ const run = live.get(runId);
872
+ if (!run) {
873
+ const current = await status(runId);
874
+ return {
875
+ ok: false,
876
+ reason: `run ${runId} is not live (status: ${current.status})`,
877
+ };
878
+ }
879
+ run.engine.stop(
880
+ reason === "model"
881
+ ? "model"
882
+ : reason === "interrupted"
883
+ ? "interrupted"
884
+ : "user",
885
+ );
886
+ await run.settled.catch(() => {});
887
+ return { ok: true, runId };
888
+ }
889
+
890
+ function importDeps() {
891
+ const journal = (id) => new FileJournalStore(path.join(runsRoot(), id), id);
892
+ return {
893
+ journal: {
894
+ getRun: (id) => journal(id).getRun(id),
895
+ listActors: (id, opts) => journal(id).listActors(id, opts),
896
+ listNodes: (id, opts) => journal(id).listNodes(id, opts),
897
+ },
898
+ ...(config.transcripts
899
+ ? {
900
+ actorTranscriptStore: {
901
+ messages: async ({ sessionID }) => {
902
+ const events = config.transcripts.read(sessionID);
903
+ if (!events) throw new Error("Missing transcript");
904
+ return events;
905
+ },
906
+ },
907
+ }
908
+ : {}),
909
+ };
910
+ }
911
+ export async function amendRun(runId, { code, notes } = {}) {
912
+ const deps = importDeps();
913
+ const check = preflightAmendImport(deps.journal, runId);
914
+ if (!check.ok) throw new Error(`无法修订续跑:${check.reason}`);
915
+ const record = check.run,
916
+ dir = path.join(runsRoot(), runId);
917
+ const newCode = code ?? readFileSync(path.join(dir, "script.dwf.ts"), "utf8");
918
+ await compileProduct(newCode); // Reject invalid edits before stopping the predecessor.
919
+ const meta = JSON.parse(readFileSync(path.join(dir, "meta.json"), "utf8"));
920
+ const predecessor = live.get(runId);
921
+ if (predecessor) {
922
+ predecessor.engine.stop("superseded");
923
+ await predecessor.settled;
924
+ }
925
+ const imported = await buildImportedCache(deps, runId);
926
+ if (!imported.ok) throw new Error(`无法修订续跑:${imported.reason}`);
927
+ const result = await createRun({
928
+ ...meta,
929
+ code: newCode,
930
+ name: record.name,
931
+ args: record.args,
932
+ cwd: record.cwd,
933
+ parentSessionId: record.parentSessionId,
934
+ maxConcurrency: record.caps.maxConcurrency,
935
+ resumedFrom: runId,
936
+ inheritedTokens: record.spentTokens,
937
+ importedCache: imported.cache,
938
+ });
939
+ if (notes)
940
+ writeFileSync(
941
+ path.join(runsRoot(), result.runId, "amend-notes.txt"),
942
+ notes,
943
+ );
944
+ return { newRunId: result.runId };
945
+ }
946
+
947
+ /** status(runId) -> { status, ... } */
948
+ export async function status(runId) {
949
+ const run = live.get(runId);
950
+ if (run) return { runId, status: run.engine.status() };
951
+ return readStatusFromDisk(runId);
952
+ }
953
+
954
+ function readStatusFromDisk(runId) {
955
+ const dir = path.join(runsRoot(), runId);
956
+ const jl = path.join(dir, "journal.jsonl");
957
+ if (!existsSync(jl)) throw new Error(`status: no such run "${runId}"`);
958
+ const j = new FileJournalStore(dir, runId);
959
+ const record = j.getRun(runId);
960
+ return {
961
+ runId,
962
+ status:
963
+ record?.status === "running" && !live.has(runId)
964
+ ? "stopped"
965
+ : (record?.status ?? "unknown"),
966
+ stopReason:
967
+ record?.status === "running" && !live.has(runId)
968
+ ? "interrupted"
969
+ : record?.stopReason,
970
+ failure: record?.failure,
971
+ spentTokens: record?.spentTokens,
972
+ };
973
+ }
974
+
975
+ /**
976
+ * listPendingAsks(runId) -> [{ instance, actor, actorName, instructions, schema }]
977
+ * instance is the "<siteId>@<ordinal>" string; pass it back to submitAsk.
978
+ */
979
+ export async function listPendingAsks(runId) {
980
+ const run = live.get(runId);
981
+ if (!run) return [];
982
+ const out = [];
983
+ for (const p of run.driver.pending.values()) {
984
+ const spec = run.askSpecs.get(p.instance.siteId);
985
+ const a = p.actor;
986
+ out.push({
987
+ instance: p.key,
988
+ actor: a ? `${a.siteId}@${a.ordinal}` : undefined,
989
+ actorName: run.driver.actorsBySession.get(p.sessionId)?.persona?.name,
990
+ instructions: p.instructions,
991
+ schema: p.typed ? p.schema : null,
992
+ });
993
+ void spec;
994
+ }
995
+ return out;
996
+ }
997
+
998
+ /**
999
+ * submitAsk(runId, instance, value) -> { ok, violation? }
1000
+ * Validates against the ask schema (typed asks), then drives
1001
+ * engine.askSubmitAttempted + engine.askTurnEnded.
1002
+ */
1003
+ export async function submitAsk(runId, instance, value) {
1004
+ const run = live.get(runId);
1005
+ if (!run) return { ok: false, violation: `run ${runId} is not live` };
1006
+ const v = await vendor();
1007
+ const inst = parseInstance(instance);
1008
+ const key = ref(inst);
1009
+ const pending = run.driver.pending.get(key);
1010
+ if (!pending)
1011
+ return { ok: false, violation: `no pending ask ${key} on run ${runId}` };
1012
+ const spec = run.askSpecs.get(inst.siteId);
1013
+ if (!spec)
1014
+ return { ok: false, violation: `no ask spec for site ${inst.siteId}` };
1015
+
1016
+ if (spec.typed) {
1017
+ const { candidate, violations } = normalizeSubmission(
1018
+ v,
1019
+ spec.schema,
1020
+ value,
1021
+ );
1022
+ if (violations.length > 0) {
1023
+ run.engine.askSubmitAttempted(inst, value);
1024
+ return { ok: false, violation: v.formatViolations(violations) };
1025
+ }
1026
+ await finishSubmission(run, pending, inst, instance);
1027
+ // accepted: engine validates again (lenient decode) and settles the ask at submit
1028
+ run.engine.askSubmitAttempted(inst, candidate);
1029
+ await flush();
1030
+ run.engine.askTurnEnded(inst, "");
1031
+ await flush();
1032
+ run.driver.pending.delete(key);
1033
+ run.journal.persistState({ pendingAsks: [...run.driver.pending.keys()] });
1034
+ return { ok: true };
1035
+ }
1036
+
1037
+ await finishSubmission(run, pending, inst, instance);
1038
+ // untyped ask: the result is the final text; engine ignores submit attempts
1039
+ const finalText =
1040
+ typeof value === "string"
1041
+ ? value
1042
+ : (JSON.stringify(value) ?? String(value));
1043
+ run.engine.askTurnEnded(inst, finalText);
1044
+ await flush();
1045
+ run.driver.pending.delete(key);
1046
+ run.journal.persistState({ pendingAsks: [...run.driver.pending.keys()] });
1047
+ return { ok: true };
1048
+ }
1049
+
1050
+ async function finishSubmission(run, pending, inst, instance, accepted = true) {
1051
+ if (accepted) run.driver.runtime?.accepted(instance);
1052
+ const observed = await run.driver.runtime?.finish?.(pending.sessionId);
1053
+ if (observed?.stats) {
1054
+ run.engine.askProgress(inst, {
1055
+ turn: observed.stats.turns,
1056
+ toolCalls: observed.stats.toolCalls,
1057
+ });
1058
+ run.engine.askStats(inst, observed.stats);
1059
+ }
1060
+ if (observed?.messageBoundary !== undefined) {
1061
+ const node = run.journal.getNode(run.runId, inst.siteId, inst.ordinal);
1062
+ if (node)
1063
+ run.journal.putNode({
1064
+ ...node,
1065
+ messageBoundary: observed.messageBoundary,
1066
+ });
1067
+ }
1068
+ }
1069
+
1070
+ async function flush(rounds = 12) {
1071
+ for (let i = 0; i < rounds; i++) await Promise.resolve();
1072
+ }
1073
+
1074
+ /**
1075
+ * fillHole(runId, siteId, code): release a branch parked at an open hole.
1076
+ * `code` is the hole body source as written by the agent; we lower it through
1077
+ * the same hole-splice machinery by handing the engine the lowered body text.
1078
+ */
1079
+ export async function fillHole(runId, siteId, code) {
1080
+ const run = live.get(runId);
1081
+ if (!run) return { ok: false, reason: "not_live" };
1082
+ const v = await vendor();
1083
+ // The effective-script body for a fill must be the lowered hole body text.
1084
+ // We lower a scratch script whose hole body is the agent's code so the text
1085
+ // goes through the exact same transform as a compile-time filled hole.
1086
+ const bodyResult = v.lowerWorkflowScript(
1087
+ `await hole<unknown>("__scratch__", async () => {\n ${code}\n });`,
1088
+ );
1089
+ let bodyText = run.holeBodies[siteId];
1090
+ const scratchBodies = bodyResult.ok
1091
+ ? Object.values(bodyResult.lowered.holeBodies)
1092
+ : [];
1093
+ if (scratchBodies.length > 0) bodyText = scratchBodies[0];
1094
+ if (!bodyText) {
1095
+ return {
1096
+ ok: false,
1097
+ reason: "not_waiting",
1098
+ detail: `could not lower the hole body: ${(bodyResult.diagnostics ?? []).map((d) => `${d.line}:${d.column} ${d.message}`).join("; ") || "no body produced"}`,
1099
+ };
1100
+ }
1101
+ const result = run.engine.fillHole({
1102
+ siteId,
1103
+ code: bodyText,
1104
+ script: { text: run.scriptText, hash: run.scriptHash },
1105
+ askSpecs: run.askSpecs,
1106
+ sitePhases: run.sitePhases,
1107
+ phaseNames: run.phaseNames,
1108
+ });
1109
+ await flush();
1110
+ return result;
1111
+ }
1112
+
1113
+ /** openHoles(runId) -> OpenHole[] */
1114
+ export async function openHoles(runId) {
1115
+ const run = live.get(runId);
1116
+ if (!run) return [];
1117
+ return run.engine.openHoles();
1118
+ }
1119
+
1120
+ /** listRuns() -> [{ runId, name, status, updatedAt }] */
1121
+ export async function listRuns() {
1122
+ const root = runsRoot();
1123
+ if (!existsSync(root)) return [];
1124
+ const out = [];
1125
+ for (const entry of readdirSync(root)) {
1126
+ const dir = path.join(root, entry);
1127
+ if (!statSync(dir).isDirectory()) continue;
1128
+ try {
1129
+ const s = readStatusFromDisk(entry);
1130
+ const journal = new FileJournalStore(dir, entry);
1131
+ const record = journal.getRun(entry);
1132
+ let meta = {};
1133
+ try {
1134
+ meta = JSON.parse(readFileSync(path.join(dir, "meta.json"), "utf8"));
1135
+ } catch {}
1136
+ out.push({
1137
+ ...record,
1138
+ scriptText: undefined,
1139
+ ...meta,
1140
+ runId: entry,
1141
+ status:
1142
+ s.status === "running" && !live.has(entry) ? "stopped" : s.status,
1143
+ startedAt: journal.events[0]?.timeCreated,
1144
+ finishedAt:
1145
+ s.status === "running"
1146
+ ? undefined
1147
+ : journal.events.at(-1)?.timeCreated,
1148
+ });
1149
+ } catch {
1150
+ /* skip partial runs */
1151
+ }
1152
+ }
1153
+ return out.sort((a, b) => (b.startedAt ?? 0) - (a.startedAt ?? 0));
1154
+ }
1155
+
1156
+ /** getRun(runId) -> { status, phases, actors, nodes, events, reports, artifacts, counts } */
1157
+ export async function getRun(runId) {
1158
+ const run = live.get(runId);
1159
+ let journal;
1160
+ let engineStatus;
1161
+ let settlement;
1162
+ if (run) {
1163
+ journal = run.journal;
1164
+ engineStatus = run.engine.status();
1165
+ settlement = run.settlement;
1166
+ } else {
1167
+ const dir = path.join(runsRoot(), runId);
1168
+ if (!existsSync(path.join(dir, "journal.jsonl")))
1169
+ throw new Error(`getRun: no such run "${runId}"`);
1170
+ journal = new FileJournalStore(dir, runId);
1171
+ }
1172
+ const record = journal.getRun(runId);
1173
+ const events = journal.listEvents(runId, {
1174
+ types: "all",
1175
+ reportItems: { limit: 64 },
1176
+ });
1177
+ const actors = journal.listActors(runId, { withPersona: true });
1178
+ const nodes = journal.listNodes(runId, { kinds: "all", withResult: true });
1179
+ // Earlier DSH versions recorded child usage in transcripts but did not transfer
1180
+ // it to the run. Recover terminal runs once, from each unique child session.
1181
+ if (
1182
+ record.status !== "running" &&
1183
+ !(record.spentTokens > 0) &&
1184
+ !nodes.some((node) => node.stats?.tokens > 0) &&
1185
+ config.transcripts?.read
1186
+ ) {
1187
+ const sessionIds = new Set(actors.map((actor) => actor.sessionId).filter(Boolean));
1188
+ const recovered = [...sessionIds].reduce(
1189
+ (sum, id) => sum + (collectSessionStats(config.transcripts.read(id) ?? [])?.tokens ?? 0),
1190
+ 0,
1191
+ );
1192
+ if (recovered > 0) {
1193
+ journal.updateRunUsage(runId, recovered);
1194
+ journal.persistRecoveredUsage();
1195
+ record.spentTokens = recovered;
1196
+ }
1197
+ }
1198
+ const askNodes = journal.listNodes(runId, {
1199
+ kinds: ["ask"],
1200
+ withResult: true,
1201
+ });
1202
+ const worldNodes = journal.listNodes(runId, {
1203
+ kinds: ["world-read", "world-run"],
1204
+ withResult: true,
1205
+ });
1206
+ const reportRows = journal.listNodes(runId, {
1207
+ kinds: ["report"],
1208
+ withResult: true,
1209
+ });
1210
+ const artifactRows = journal.listNodes(runId, {
1211
+ kinds: ["artifact"],
1212
+ withResult: true,
1213
+ });
1214
+ let core = {},
1215
+ meta = {};
1216
+ const dir = path.join(runsRoot(), runId);
1217
+ try {
1218
+ core = JSON.parse(readFileSync(path.join(dir, "plan.json"), "utf8"));
1219
+ } catch {
1220
+ const analysis = await analyzeScript(
1221
+ record.scriptText ??
1222
+ readFileSync(path.join(dir, "script.dwf.ts"), "utf8"),
1223
+ );
1224
+ core = analysis.coreJson ?? {};
1225
+ }
1226
+ try {
1227
+ meta = JSON.parse(readFileSync(path.join(dir, "meta.json"), "utf8"));
1228
+ } catch {}
1229
+ const actualStatus =
1230
+ engineStatus ?? (record.status === "running" ? "stopped" : record.status);
1231
+ return {
1232
+ ...projectRun(
1233
+ {
1234
+ ...record,
1235
+ status: actualStatus,
1236
+ ...(record.status === "running" && !run
1237
+ ? { stopReason: "interrupted" }
1238
+ : {}),
1239
+ },
1240
+ nodes,
1241
+ actors,
1242
+ events,
1243
+ core,
1244
+ meta,
1245
+ ),
1246
+ asks: askNodes.map((n) => ({
1247
+ instance: ref(n),
1248
+ status: n.status,
1249
+ actor: `${n.actorSiteId}@${n.actorOrdinal}`,
1250
+ result: n.result,
1251
+ error: n.error,
1252
+ })),
1253
+ events: events.slice(-100),
1254
+ settlement,
1255
+ counts: {
1256
+ asks: askNodes.length,
1257
+ worldReads: worldNodes.length,
1258
+ reports: reportRows.length,
1259
+ artifacts: artifactRows.length,
1260
+ events: events.length,
1261
+ },
1262
+ };
1263
+ }
1264
+
1265
+ // ---------------------------------------------------------------------------
1266
+ // Convenience wrappers the plugin can expose directly
1267
+ // ---------------------------------------------------------------------------
1268
+ export async function compileScript(code) {
1269
+ const v = await vendor();
1270
+ const result = v.compileWorkflowScript(code);
1271
+ return {
1272
+ ok: result.ok,
1273
+ program: result.ok ? v.createWorkflowProgram(code) : undefined,
1274
+ diagnostics: result.diagnostics,
1275
+ dts: undefined, // the vendored compiler does not emit .d.ts for scripts
1276
+ };
1277
+ }
1278
+
1279
+ /** analyzeScript(code) -> { ok, coreJson, mermaid: {site,causality,controlFlow,handoff,phase}, diagnostics } */
1280
+ export async function analyzeScript(code) {
1281
+ const v = await vendor();
1282
+ const r = v.analyzeWorkflowScript(code);
1283
+ const mermaid = {
1284
+ site: r.graph ? v.siteGraphToMermaid(r.graph) : undefined,
1285
+ causality: r.causality ? v.causalityGraphToMermaid(r.causality) : undefined,
1286
+ controlFlow: r.flow ? v.controlFlowToMermaid(r.flow) : undefined,
1287
+ handoff: r.handoff ? v.handoffGraphToMermaid(r.handoff) : undefined,
1288
+ phase: r.flow ? v.phaseFlowToMermaid(r.flow) : undefined,
1289
+ };
1290
+ return {
1291
+ ok: r.ok,
1292
+ coreJson: r.core ? v.encodeAnalysisCore(r.core) : undefined,
1293
+ mermaid,
1294
+ diagnostics: r.diagnostics,
1295
+ };
1296
+ }
1297
+
1298
+ export async function updateSettings(runId, settings) {
1299
+ const n = Number(settings.maxConcurrency);
1300
+ if (!Number.isInteger(n) || n < 1 || n > 64)
1301
+ throw new Error("并发上限必须是 1–64 的整数");
1302
+ const run = live.get(runId);
1303
+ if (!run) throw new Error("只能调整正在运行的工作流");
1304
+ run.engine.setMaxConcurrency(n);
1305
+ run.driver.runtime?.updateSettings({
1306
+ model: settings.model,
1307
+ reasoningEffort: settings.reasoningEffort,
1308
+ });
1309
+ const file = path.join(run.dir, "meta.json");
1310
+ const meta = JSON.parse(readFileSync(file, "utf8"));
1311
+ writeFileSync(
1312
+ file,
1313
+ JSON.stringify({
1314
+ ...meta,
1315
+ model: settings.model,
1316
+ reasoningEffort: settings.reasoningEffort,
1317
+ }),
1318
+ );
1319
+ return getRun(runId);
1320
+ }
1321
+ export function pendingOwner(runId, instance) {
1322
+ return live.get(runId)?.driver.pending.get(instance)?.sessionId;
1323
+ }
1324
+ export async function readArtifact(runId, artifactId) {
1325
+ const run = await getRun(runId);
1326
+ const item = run.artifacts.find((a) => a.id === artifactId);
1327
+ if (!item) throw new Error("产物不存在");
1328
+ if (!item.uri)
1329
+ return {
1330
+ ...item,
1331
+ items: run.reports
1332
+ .filter((r) => r.artifactId === artifactId)
1333
+ .map((r) => r.item),
1334
+ };
1335
+ const filename = item.uri.split("/").at(-1);
1336
+ if (!filename || filename.includes("..")) throw new Error("产物地址无效");
1337
+ const data = readFileSync(
1338
+ path.join(runsRoot(), runId, "artifacts", filename),
1339
+ );
1340
+ return {
1341
+ ...item,
1342
+ content: /^(text\/|application\/json)/.test(item.contentType)
1343
+ ? data.toString("utf8")
1344
+ : undefined,
1345
+ base64: data.toString("base64"),
1346
+ };
1347
+ }
1348
+
1349
+ function resolveWithin(root, relative) {
1350
+ const file = path.resolve(root, String(relative ?? ""));
1351
+ if (file !== root && !file.startsWith(root + path.sep))
1352
+ throw new Error("文件不在工作目录内");
1353
+ const realRoot = realpathSync(root),
1354
+ realFile = realpathSync(file);
1355
+ if (realFile !== realRoot && !realFile.startsWith(realRoot + path.sep))
1356
+ throw new Error("产物符号链接指向工作目录之外");
1357
+ return realFile;
1358
+ }
1359
+
1360
+ export async function validateSubmission(runId, instance, value) {
1361
+ const run = live.get(runId),
1362
+ pending = run?.driver.pending.get(instance);
1363
+ if (!pending) return { ok: false, violation: "任务已经结束或不存在" };
1364
+ const spec = run.askSpecs.get(parseInstance(instance).siteId);
1365
+ if (!spec?.typed) return { ok: true };
1366
+ const v = await vendor();
1367
+ const { violations } = normalizeSubmission(v, spec.schema, value);
1368
+ return violations.length
1369
+ ? { ok: false, violation: v.formatViolations(violations) }
1370
+ : { ok: true };
1371
+ }
1372
+
1373
+ export function stopAll() {
1374
+ for (const run of live.values()) run.engine.stop("interrupted");
1375
+ }
1376
+
1377
+ function normalizeSubmission(v, schema, value) {
1378
+ const direct = v.validate(schema, value);
1379
+ if (!direct.length || typeof value !== "string")
1380
+ return { candidate: value, violations: direct };
1381
+ try {
1382
+ const candidate = JSON.parse(value);
1383
+ return { candidate, violations: v.validate(schema, candidate) };
1384
+ } catch {
1385
+ return { candidate: value, violations: direct };
1386
+ }
1387
+ }