@opendash-ai/cli 0.1.0-beta.1 → 0.1.0-beta.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 (1213) hide show
  1. package/{src/skill/compose/LICENSE-superpowers → LICENSE} +2 -6
  2. package/README.md +53 -8
  3. package/bin/opendash +3 -4
  4. package/package.json +9 -191
  5. package/postinstall.mjs +124 -0
  6. package/Dockerfile +0 -18
  7. package/analysis.py +0 -171
  8. package/bunfig.toml +0 -7
  9. package/drizzle.config.ts +0 -10
  10. package/git +0 -0
  11. package/migration/20260127222353_familiar_lady_ursula/migration.sql +0 -90
  12. package/migration/20260127222353_familiar_lady_ursula/snapshot.json +0 -796
  13. package/migration/20260211171708_add_project_commands/migration.sql +0 -1
  14. package/migration/20260211171708_add_project_commands/snapshot.json +0 -806
  15. package/migration/20260213144116_wakeful_the_professor/migration.sql +0 -11
  16. package/migration/20260213144116_wakeful_the_professor/snapshot.json +0 -897
  17. package/migration/20260225215848_workspace/migration.sql +0 -7
  18. package/migration/20260225215848_workspace/snapshot.json +0 -959
  19. package/migration/20260227213759_add_session_workspace_id/migration.sql +0 -2
  20. package/migration/20260227213759_add_session_workspace_id/snapshot.json +0 -983
  21. package/migration/20260228203230_blue_harpoon/migration.sql +0 -17
  22. package/migration/20260228203230_blue_harpoon/snapshot.json +0 -1102
  23. package/migration/20260303231226_add_workspace_fields/migration.sql +0 -5
  24. package/migration/20260303231226_add_workspace_fields/snapshot.json +0 -1013
  25. package/migration/20260309230000_move_org_to_state/migration.sql +0 -3
  26. package/migration/20260309230000_move_org_to_state/snapshot.json +0 -1156
  27. package/migration/20260312043431_session_message_cursor/migration.sql +0 -4
  28. package/migration/20260312043431_session_message_cursor/snapshot.json +0 -1168
  29. package/migration/20260323234822_events/migration.sql +0 -13
  30. package/migration/20260323234822_events/snapshot.json +0 -1271
  31. package/migration/20260410174513_workspace-name/migration.sql +0 -16
  32. package/migration/20260410174513_workspace-name/snapshot.json +0 -1271
  33. package/migration/20260413175956_chief_energizer/migration.sql +0 -13
  34. package/migration/20260413175956_chief_energizer/snapshot.json +0 -1399
  35. package/migration/20260422160000_context_inheritance/migration.sql +0 -3
  36. package/migration/20260422170000_task_registry/migration.sql +0 -18
  37. package/migration/20260423145421_remove_session_entry/migration.sql +0 -4
  38. package/migration/20260515000000_actor_rename/migration.sql +0 -7
  39. package/migration/20260515010000_memory_fts/migration.sql +0 -33
  40. package/migration/20260515020000_user_task/migration.sql +0 -29
  41. package/migration/20260519000000_last_checkpoint_message_id/migration.sql +0 -1
  42. package/migration/20260521000000_message_agent_id/migration.sql +0 -2
  43. package/migration/20260521000100_actor_registry_v6/migration.sql +0 -25
  44. package/migration/20260521010000_memory_fts_v6/migration.sql +0 -33
  45. package/migration/20260521020000_memory_fts_triggers/migration.sql +0 -17
  46. package/migration/20260526000000_agent_id_main/migration.sql +0 -14
  47. package/migration/20260527000000_actor_lifecycle/migration.sql +0 -8
  48. package/migration/20260527000100_inbox/migration.sql +0 -12
  49. package/migration/20260529000000_task_todo_redesign/migration.sql +0 -16
  50. package/migration/20260603000000_task_in_progress_owner/migration.sql +0 -1
  51. package/migration/20260603000000_workflow_run/migration.sql +0 -17
  52. package/migration/20260604000000_workflow_script_sha/migration.sql +0 -1
  53. package/migration/20260608000000_claude_import/migration.sql +0 -7
  54. package/migration/20260608010000_claude_import_message_ids/migration.sql +0 -1
  55. package/migration/20260609000000_history_fts/migration.sql +0 -29
  56. package/migration/20260609230000_workflow_agent_timeout/migration.sql +0 -1
  57. package/migration/20260612000000_external_import/migration.sql +0 -16
  58. package/parsers-config.ts +0 -290
  59. package/script/build.ts +0 -337
  60. package/script/build_noinstall.ts +0 -337
  61. package/script/check-migrations.ts +0 -16
  62. package/script/dev.ts +0 -38
  63. package/script/fds-upload.ts +0 -170
  64. package/script/fix-node-pty.ts +0 -28
  65. package/script/generate.ts +0 -23
  66. package/script/postinstall.mjs +0 -102
  67. package/script/publish.ts +0 -75
  68. package/script/run-workspace-server +0 -106
  69. package/script/schema.ts +0 -63
  70. package/script/time.ts +0 -6
  71. package/script/trace-imports.ts +0 -153
  72. package/script/upgrade-opentui.ts +0 -64
  73. package/src/account/account.sql.ts +0 -39
  74. package/src/account/account.ts +0 -456
  75. package/src/account/repo.ts +0 -166
  76. package/src/account/schema.ts +0 -99
  77. package/src/account/url.ts +0 -8
  78. package/src/acp/README.md +0 -174
  79. package/src/acp/agent.ts +0 -1787
  80. package/src/acp/session.ts +0 -116
  81. package/src/acp/types.ts +0 -24
  82. package/src/actor/actor.sql.ts +0 -38
  83. package/src/actor/events.ts +0 -67
  84. package/src/actor/index.ts +0 -2
  85. package/src/actor/registry.ts +0 -412
  86. package/src/actor/return-header.ts +0 -24
  87. package/src/actor/schema.ts +0 -47
  88. package/src/actor/spawn-ref.ts +0 -16
  89. package/src/actor/spawn.ts +0 -756
  90. package/src/actor/turn.ts +0 -49
  91. package/src/actor/waiter.ts +0 -166
  92. package/src/agent/agent.ts +0 -574
  93. package/src/agent/config.ts +0 -5
  94. package/src/agent/generate.txt +0 -75
  95. package/src/agent/prompt/checkpoint-writer.txt +0 -167
  96. package/src/agent/prompt/compaction.txt +0 -9
  97. package/src/agent/prompt/distill.txt +0 -199
  98. package/src/agent/prompt/dream.txt +0 -155
  99. package/src/agent/prompt/explore.txt +0 -18
  100. package/src/agent/prompt/summary.txt +0 -11
  101. package/src/agent/prompt/title.txt +0 -44
  102. package/src/audio.d.ts +0 -9
  103. package/src/auth/index.ts +0 -97
  104. package/src/bus/bus-event.ts +0 -33
  105. package/src/bus/global.ts +0 -12
  106. package/src/bus/index.ts +0 -193
  107. package/src/cli/bootstrap.ts +0 -33
  108. package/src/cli/cmd/account.ts +0 -258
  109. package/src/cli/cmd/acp.ts +0 -70
  110. package/src/cli/cmd/agent.ts +0 -248
  111. package/src/cli/cmd/cmd.ts +0 -7
  112. package/src/cli/cmd/db.ts +0 -120
  113. package/src/cli/cmd/debug/agent.ts +0 -192
  114. package/src/cli/cmd/debug/config.ts +0 -17
  115. package/src/cli/cmd/debug/file.ts +0 -100
  116. package/src/cli/cmd/debug/index.ts +0 -48
  117. package/src/cli/cmd/debug/lsp.ts +0 -61
  118. package/src/cli/cmd/debug/ripgrep.ts +0 -105
  119. package/src/cli/cmd/debug/scrap.ts +0 -16
  120. package/src/cli/cmd/debug/skill.ts +0 -23
  121. package/src/cli/cmd/debug/snapshot.ts +0 -53
  122. package/src/cli/cmd/export.ts +0 -306
  123. package/src/cli/cmd/generate.ts +0 -50
  124. package/src/cli/cmd/github.ts +0 -1647
  125. package/src/cli/cmd/import.ts +0 -208
  126. package/src/cli/cmd/mcp.ts +0 -812
  127. package/src/cli/cmd/models.ts +0 -88
  128. package/src/cli/cmd/plug.ts +0 -233
  129. package/src/cli/cmd/pr.ts +0 -138
  130. package/src/cli/cmd/providers.ts +0 -713
  131. package/src/cli/cmd/run-completion.ts +0 -77
  132. package/src/cli/cmd/run.ts +0 -694
  133. package/src/cli/cmd/serve.ts +0 -30
  134. package/src/cli/cmd/session.ts +0 -181
  135. package/src/cli/cmd/stats.ts +0 -413
  136. package/src/cli/cmd/tui/app.tsx +0 -1140
  137. package/src/cli/cmd/tui/asset/TEN_VAD_LICENSE +0 -12
  138. package/src/cli/cmd/tui/asset/charge.wav +0 -0
  139. package/src/cli/cmd/tui/asset/pulse-a.wav +0 -0
  140. package/src/cli/cmd/tui/asset/pulse-b.wav +0 -0
  141. package/src/cli/cmd/tui/asset/pulse-c.wav +0 -0
  142. package/src/cli/cmd/tui/asset/ten_vad.wasm +0 -0
  143. package/src/cli/cmd/tui/asset/ten_vad_loader.js +0 -30
  144. package/src/cli/cmd/tui/attach.ts +0 -84
  145. package/src/cli/cmd/tui/component/background-image.tsx +0 -150
  146. package/src/cli/cmd/tui/component/bg-pulse.tsx +0 -130
  147. package/src/cli/cmd/tui/component/border.tsx +0 -21
  148. package/src/cli/cmd/tui/component/dialog-agent.tsx +0 -31
  149. package/src/cli/cmd/tui/component/dialog-agreement.tsx +0 -111
  150. package/src/cli/cmd/tui/component/dialog-command.tsx +0 -219
  151. package/src/cli/cmd/tui/component/dialog-console-org.tsx +0 -103
  152. package/src/cli/cmd/tui/component/dialog-go-upsell.tsx +0 -157
  153. package/src/cli/cmd/tui/component/dialog-image-list.tsx +0 -111
  154. package/src/cli/cmd/tui/component/dialog-logo-design.tsx +0 -37
  155. package/src/cli/cmd/tui/component/dialog-mcp.tsx +0 -86
  156. package/src/cli/cmd/tui/component/dialog-mimo-login.tsx +0 -165
  157. package/src/cli/cmd/tui/component/dialog-model.tsx +0 -335
  158. package/src/cli/cmd/tui/component/dialog-provider.tsx +0 -449
  159. package/src/cli/cmd/tui/component/dialog-session-delete-failed.tsx +0 -101
  160. package/src/cli/cmd/tui/component/dialog-session-list.tsx +0 -269
  161. package/src/cli/cmd/tui/component/dialog-session-rename.tsx +0 -31
  162. package/src/cli/cmd/tui/component/dialog-skill.tsx +0 -42
  163. package/src/cli/cmd/tui/component/dialog-stash.tsx +0 -87
  164. package/src/cli/cmd/tui/component/dialog-status.tsx +0 -170
  165. package/src/cli/cmd/tui/component/dialog-tag.tsx +0 -44
  166. package/src/cli/cmd/tui/component/dialog-theme-list.tsx +0 -50
  167. package/src/cli/cmd/tui/component/dialog-token-plan.tsx +0 -77
  168. package/src/cli/cmd/tui/component/dialog-variant.tsx +0 -39
  169. package/src/cli/cmd/tui/component/dialog-workflows.tsx +0 -51
  170. package/src/cli/cmd/tui/component/dialog-workspace-create.tsx +0 -289
  171. package/src/cli/cmd/tui/component/dialog-workspace-unavailable.tsx +0 -81
  172. package/src/cli/cmd/tui/component/dialog-worktree.tsx +0 -90
  173. package/src/cli/cmd/tui/component/error-component.tsx +0 -92
  174. package/src/cli/cmd/tui/component/logo.tsx +0 -961
  175. package/src/cli/cmd/tui/component/plugin-route-missing.tsx +0 -14
  176. package/src/cli/cmd/tui/component/prompt/autocomplete-detect.ts +0 -34
  177. package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +0 -668
  178. package/src/cli/cmd/tui/component/prompt/cwd.ts +0 -0
  179. package/src/cli/cmd/tui/component/prompt/frecency.tsx +0 -90
  180. package/src/cli/cmd/tui/component/prompt/history.tsx +0 -108
  181. package/src/cli/cmd/tui/component/prompt/index.tsx +0 -1917
  182. package/src/cli/cmd/tui/component/prompt/offset.ts +0 -45
  183. package/src/cli/cmd/tui/component/prompt/part.ts +0 -36
  184. package/src/cli/cmd/tui/component/prompt/shimmer.ts +0 -62
  185. package/src/cli/cmd/tui/component/prompt/stash.tsx +0 -101
  186. package/src/cli/cmd/tui/component/spinner.tsx +0 -24
  187. package/src/cli/cmd/tui/component/starry-background.tsx +0 -305
  188. package/src/cli/cmd/tui/component/startup-loading.tsx +0 -67
  189. package/src/cli/cmd/tui/component/task-item.tsx +0 -63
  190. package/src/cli/cmd/tui/component/textarea-keybindings.ts +0 -73
  191. package/src/cli/cmd/tui/component/todo-item.tsx +0 -32
  192. package/src/cli/cmd/tui/component/workflow-tree.tsx +0 -177
  193. package/src/cli/cmd/tui/config/cwd.ts +0 -5
  194. package/src/cli/cmd/tui/config/tui-migrate.ts +0 -151
  195. package/src/cli/cmd/tui/config/tui-schema.ts +0 -38
  196. package/src/cli/cmd/tui/config/tui.ts +0 -219
  197. package/src/cli/cmd/tui/context/args.tsx +0 -16
  198. package/src/cli/cmd/tui/context/directory.ts +0 -15
  199. package/src/cli/cmd/tui/context/event.ts +0 -45
  200. package/src/cli/cmd/tui/context/exit.tsx +0 -65
  201. package/src/cli/cmd/tui/context/helper.tsx +0 -25
  202. package/src/cli/cmd/tui/context/keybind.tsx +0 -105
  203. package/src/cli/cmd/tui/context/kv.tsx +0 -86
  204. package/src/cli/cmd/tui/context/language.tsx +0 -91
  205. package/src/cli/cmd/tui/context/local.tsx +0 -469
  206. package/src/cli/cmd/tui/context/plugin-keybinds.ts +0 -41
  207. package/src/cli/cmd/tui/context/project.tsx +0 -109
  208. package/src/cli/cmd/tui/context/prompt.tsx +0 -18
  209. package/src/cli/cmd/tui/context/route.tsx +0 -68
  210. package/src/cli/cmd/tui/context/sdk.tsx +0 -150
  211. package/src/cli/cmd/tui/context/sync.tsx +0 -884
  212. package/src/cli/cmd/tui/context/theme/aura.json +0 -69
  213. package/src/cli/cmd/tui/context/theme/ayu.json +0 -80
  214. package/src/cli/cmd/tui/context/theme/carbonfox.json +0 -248
  215. package/src/cli/cmd/tui/context/theme/catppuccin-frappe.json +0 -230
  216. package/src/cli/cmd/tui/context/theme/catppuccin-macchiato.json +0 -230
  217. package/src/cli/cmd/tui/context/theme/catppuccin.json +0 -112
  218. package/src/cli/cmd/tui/context/theme/cobalt2.json +0 -225
  219. package/src/cli/cmd/tui/context/theme/cursor.json +0 -249
  220. package/src/cli/cmd/tui/context/theme/dracula.json +0 -219
  221. package/src/cli/cmd/tui/context/theme/everforest.json +0 -241
  222. package/src/cli/cmd/tui/context/theme/flexoki.json +0 -237
  223. package/src/cli/cmd/tui/context/theme/github.json +0 -233
  224. package/src/cli/cmd/tui/context/theme/gruvbox.json +0 -242
  225. package/src/cli/cmd/tui/context/theme/kanagawa.json +0 -77
  226. package/src/cli/cmd/tui/context/theme/lucent-orng.json +0 -234
  227. package/src/cli/cmd/tui/context/theme/material.json +0 -235
  228. package/src/cli/cmd/tui/context/theme/matrix.json +0 -77
  229. package/src/cli/cmd/tui/context/theme/mercury.json +0 -252
  230. package/src/cli/cmd/tui/context/theme/monokai.json +0 -221
  231. package/src/cli/cmd/tui/context/theme/nightowl.json +0 -221
  232. package/src/cli/cmd/tui/context/theme/nord.json +0 -223
  233. package/src/cli/cmd/tui/context/theme/one-dark.json +0 -84
  234. package/src/cli/cmd/tui/context/theme/opendash.json +0 -243
  235. package/src/cli/cmd/tui/context/theme/orng.json +0 -249
  236. package/src/cli/cmd/tui/context/theme/osaka-jade.json +0 -93
  237. package/src/cli/cmd/tui/context/theme/palenight.json +0 -222
  238. package/src/cli/cmd/tui/context/theme/rosepine.json +0 -234
  239. package/src/cli/cmd/tui/context/theme/solarized.json +0 -223
  240. package/src/cli/cmd/tui/context/theme/synthwave84.json +0 -226
  241. package/src/cli/cmd/tui/context/theme/tokyonight.json +0 -243
  242. package/src/cli/cmd/tui/context/theme/vercel.json +0 -245
  243. package/src/cli/cmd/tui/context/theme/vesper.json +0 -218
  244. package/src/cli/cmd/tui/context/theme/zenburn.json +0 -223
  245. package/src/cli/cmd/tui/context/theme.tsx +0 -1299
  246. package/src/cli/cmd/tui/context/thinking.ts +0 -48
  247. package/src/cli/cmd/tui/context/tui-config.tsx +0 -9
  248. package/src/cli/cmd/tui/event.ts +0 -56
  249. package/src/cli/cmd/tui/feature-plugins/home/footer.tsx +0 -93
  250. package/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx +0 -194
  251. package/src/cli/cmd/tui/feature-plugins/home/tips.tsx +0 -54
  252. package/src/cli/cmd/tui/feature-plugins/sidebar/context.tsx +0 -114
  253. package/src/cli/cmd/tui/feature-plugins/sidebar/cwd.tsx +0 -45
  254. package/src/cli/cmd/tui/feature-plugins/sidebar/files.tsx +0 -62
  255. package/src/cli/cmd/tui/feature-plugins/sidebar/footer.tsx +0 -93
  256. package/src/cli/cmd/tui/feature-plugins/sidebar/goal.tsx +0 -84
  257. package/src/cli/cmd/tui/feature-plugins/sidebar/instructions.tsx +0 -54
  258. package/src/cli/cmd/tui/feature-plugins/sidebar/lsp.tsx +0 -66
  259. package/src/cli/cmd/tui/feature-plugins/sidebar/mcp.tsx +0 -98
  260. package/src/cli/cmd/tui/feature-plugins/sidebar/task.tsx +0 -95
  261. package/src/cli/cmd/tui/feature-plugins/sidebar/todo.tsx +0 -51
  262. package/src/cli/cmd/tui/feature-plugins/sidebar/tps.ts +0 -31
  263. package/src/cli/cmd/tui/feature-plugins/system/plugins.tsx +0 -274
  264. package/src/cli/cmd/tui/i18n/en.ts +0 -470
  265. package/src/cli/cmd/tui/i18n/es.ts +0 -508
  266. package/src/cli/cmd/tui/i18n/fr.ts +0 -515
  267. package/src/cli/cmd/tui/i18n/ja.ts +0 -463
  268. package/src/cli/cmd/tui/i18n/locales.ts +0 -82
  269. package/src/cli/cmd/tui/i18n/ru.ts +0 -527
  270. package/src/cli/cmd/tui/i18n/slash-command.ts +0 -11
  271. package/src/cli/cmd/tui/i18n/zh.ts +0 -459
  272. package/src/cli/cmd/tui/i18n/zht.ts +0 -430
  273. package/src/cli/cmd/tui/layer.ts +0 -6
  274. package/src/cli/cmd/tui/plugin/api.tsx +0 -402
  275. package/src/cli/cmd/tui/plugin/index.ts +0 -3
  276. package/src/cli/cmd/tui/plugin/internal.ts +0 -35
  277. package/src/cli/cmd/tui/plugin/runtime.ts +0 -1057
  278. package/src/cli/cmd/tui/plugin/slots.tsx +0 -60
  279. package/src/cli/cmd/tui/routes/home.tsx +0 -172
  280. package/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +0 -76
  281. package/src/cli/cmd/tui/routes/session/dialog-message.tsx +0 -116
  282. package/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +0 -47
  283. package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +0 -47
  284. package/src/cli/cmd/tui/routes/session/footer.tsx +0 -91
  285. package/src/cli/cmd/tui/routes/session/index.tsx +0 -3087
  286. package/src/cli/cmd/tui/routes/session/permission.tsx +0 -697
  287. package/src/cli/cmd/tui/routes/session/question.tsx +0 -488
  288. package/src/cli/cmd/tui/routes/session/sidebar.tsx +0 -109
  289. package/src/cli/cmd/tui/routes/session/subagent-footer.tsx +0 -143
  290. package/src/cli/cmd/tui/thread.ts +0 -323
  291. package/src/cli/cmd/tui/ui/dialog-alert.tsx +0 -61
  292. package/src/cli/cmd/tui/ui/dialog-confirm.tsx +0 -95
  293. package/src/cli/cmd/tui/ui/dialog-export-options.tsx +0 -223
  294. package/src/cli/cmd/tui/ui/dialog-help.tsx +0 -42
  295. package/src/cli/cmd/tui/ui/dialog-prompt.tsx +0 -123
  296. package/src/cli/cmd/tui/ui/dialog-select.tsx +0 -467
  297. package/src/cli/cmd/tui/ui/dialog.tsx +0 -207
  298. package/src/cli/cmd/tui/ui/link.tsx +0 -28
  299. package/src/cli/cmd/tui/ui/spinner.ts +0 -386
  300. package/src/cli/cmd/tui/ui/toast.tsx +0 -102
  301. package/src/cli/cmd/tui/util/clipboard.ts +0 -203
  302. package/src/cli/cmd/tui/util/editor.ts +0 -36
  303. package/src/cli/cmd/tui/util/image-protocol.ts +0 -35
  304. package/src/cli/cmd/tui/util/index.ts +0 -6
  305. package/src/cli/cmd/tui/util/model.ts +0 -23
  306. package/src/cli/cmd/tui/util/pinyin.ts +0 -20
  307. package/src/cli/cmd/tui/util/provider-origin.ts +0 -7
  308. package/src/cli/cmd/tui/util/revert-diff.ts +0 -18
  309. package/src/cli/cmd/tui/util/scroll.ts +0 -23
  310. package/src/cli/cmd/tui/util/selection.ts +0 -23
  311. package/src/cli/cmd/tui/util/signal.ts +0 -71
  312. package/src/cli/cmd/tui/util/sound.ts +0 -154
  313. package/src/cli/cmd/tui/util/system-locale.ts +0 -209
  314. package/src/cli/cmd/tui/util/terminal.ts +0 -110
  315. package/src/cli/cmd/tui/util/transcript.ts +0 -112
  316. package/src/cli/cmd/tui/util/vad.ts +0 -229
  317. package/src/cli/cmd/tui/util/voice.ts +0 -595
  318. package/src/cli/cmd/tui/win32.ts +0 -130
  319. package/src/cli/cmd/tui/worker.ts +0 -104
  320. package/src/cli/cmd/uninstall.ts +0 -351
  321. package/src/cli/cmd/upgrade.ts +0 -79
  322. package/src/cli/cmd/web.ts +0 -96
  323. package/src/cli/effect/prompt.ts +0 -25
  324. package/src/cli/error.ts +0 -82
  325. package/src/cli/heap.ts +0 -59
  326. package/src/cli/i18n.ts +0 -15
  327. package/src/cli/logo.ts +0 -52
  328. package/src/cli/network.ts +0 -68
  329. package/src/cli/ui.ts +0 -133
  330. package/src/cli/upgrade.ts +0 -41
  331. package/src/command/index.ts +0 -276
  332. package/src/command/template/initialize.txt +0 -66
  333. package/src/command/template/review.txt +0 -101
  334. package/src/config/agent.ts +0 -197
  335. package/src/config/command.ts +0 -69
  336. package/src/config/compose.ts +0 -26
  337. package/src/config/config.ts +0 -1052
  338. package/src/config/console-state.ts +0 -16
  339. package/src/config/entry-name.ts +0 -16
  340. package/src/config/error.ts +0 -21
  341. package/src/config/formatter.ts +0 -17
  342. package/src/config/history.ts +0 -21
  343. package/src/config/index.ts +0 -17
  344. package/src/config/keybinds.ts +0 -127
  345. package/src/config/layout.ts +0 -10
  346. package/src/config/lsp.ts +0 -45
  347. package/src/config/managed.ts +0 -70
  348. package/src/config/markdown.ts +0 -97
  349. package/src/config/mcp.ts +0 -172
  350. package/src/config/model-id.ts +0 -14
  351. package/src/config/parse.ts +0 -44
  352. package/src/config/paths.ts +0 -73
  353. package/src/config/permission.ts +0 -76
  354. package/src/config/plugin.ts +0 -88
  355. package/src/config/provider.ts +0 -118
  356. package/src/config/server.ts +0 -20
  357. package/src/config/skills.ts +0 -16
  358. package/src/config/variable.ts +0 -90
  359. package/src/control-plane/adaptors/index.ts +0 -52
  360. package/src/control-plane/adaptors/worktree.ts +0 -47
  361. package/src/control-plane/dev/debug-workspace-plugin.ts +0 -73
  362. package/src/control-plane/schema.ts +0 -19
  363. package/src/control-plane/sse.ts +0 -66
  364. package/src/control-plane/types.ts +0 -34
  365. package/src/control-plane/util.ts +0 -37
  366. package/src/control-plane/workspace-context.ts +0 -26
  367. package/src/control-plane/workspace.sql.ts +0 -17
  368. package/src/control-plane/workspace.ts +0 -615
  369. package/src/effect/app-runtime.ts +0 -146
  370. package/src/effect/bootstrap-runtime.ts +0 -33
  371. package/src/effect/bridge.ts +0 -48
  372. package/src/effect/cross-spawn-spawner.ts +0 -514
  373. package/src/effect/index.ts +0 -5
  374. package/src/effect/instance-ref.ts +0 -11
  375. package/src/effect/instance-registry.ts +0 -12
  376. package/src/effect/instance-state.ts +0 -81
  377. package/src/effect/logger.ts +0 -73
  378. package/src/effect/memo-map.ts +0 -3
  379. package/src/effect/observability.ts +0 -107
  380. package/src/effect/run-service.ts +0 -52
  381. package/src/effect/runner.ts +0 -210
  382. package/src/effect/runtime.ts +0 -19
  383. package/src/env/index.ts +0 -37
  384. package/src/file/ignore.ts +0 -81
  385. package/src/file/index.ts +0 -664
  386. package/src/file/protected.ts +0 -59
  387. package/src/file/ripgrep.ts +0 -485
  388. package/src/file/watcher.ts +0 -163
  389. package/src/flag/flag.ts +0 -212
  390. package/src/format/formatter.ts +0 -403
  391. package/src/format/index.ts +0 -203
  392. package/src/git/index.ts +0 -260
  393. package/src/global/index.ts +0 -54
  394. package/src/history/backfill.ts +0 -162
  395. package/src/history/extract.ts +0 -67
  396. package/src/history/fts-query.ts +0 -15
  397. package/src/history/fts.sql.ts +0 -20
  398. package/src/history/index.ts +0 -10
  399. package/src/history/resolve.ts +0 -65
  400. package/src/history/service.ts +0 -258
  401. package/src/history/writer.ts +0 -112
  402. package/src/id/id.ts +0 -87
  403. package/src/ide/index.ts +0 -73
  404. package/src/inbox/inbox-ref.ts +0 -38
  405. package/src/inbox/inbox.sql.ts +0 -26
  406. package/src/inbox/inbox.ts +0 -223
  407. package/src/inbox/index.ts +0 -3
  408. package/src/inbox/render.ts +0 -40
  409. package/src/index.ts +0 -261
  410. package/src/installation/index.ts +0 -362
  411. package/src/installation/version.ts +0 -32
  412. package/src/intelligence/AUDIT.md +0 -292
  413. package/src/intelligence/ENTERPRISE-CAPABILITIES.md +0 -317
  414. package/src/intelligence/ENTERPRISE-REVIEW.md +0 -284
  415. package/src/intelligence/IMPLEMENTATION.md +0 -214
  416. package/src/intelligence/PHASE1.md +0 -178
  417. package/src/intelligence/PHASE2.5.md +0 -162
  418. package/src/intelligence/PHASE2.md +0 -150
  419. package/src/intelligence/PHASE3-REFINED.md +0 -257
  420. package/src/intelligence/PHASE3.md +0 -188
  421. package/src/intelligence/README.md +0 -260
  422. package/src/intelligence/analytics/SKILL.md +0 -369
  423. package/src/intelligence/analytics/adapters/index.ts +0 -77
  424. package/src/intelligence/analytics/benchmarks/observable-runner.ts +0 -575
  425. package/src/intelligence/analytics/benchmarks/runner.ts +0 -758
  426. package/src/intelligence/analytics/engine/index.ts +0 -152
  427. package/src/intelligence/analytics/hook.ts +0 -154
  428. package/src/intelligence/analytics/index.ts +0 -194
  429. package/src/intelligence/analytics/loader/index.ts +0 -502
  430. package/src/intelligence/analytics/memory/index.ts +0 -455
  431. package/src/intelligence/analytics/orchestrator/index.ts +0 -329
  432. package/src/intelligence/analytics/planner/index.ts +0 -188
  433. package/src/intelligence/analytics/prompt/index.ts +0 -449
  434. package/src/intelligence/analytics/reasoning/enterprise-capabilities.ts +0 -534
  435. package/src/intelligence/analytics/reasoning/enterprise-prompt.ts +0 -321
  436. package/src/intelligence/analytics/reasoning/index.ts +0 -267
  437. package/src/intelligence/analytics/reasoning/test.ts +0 -166
  438. package/src/intelligence/analytics/reasoning/visible-reasoning.ts +0 -609
  439. package/src/intelligence/analytics/registry/index.ts +0 -176
  440. package/src/intelligence/analytics/router/index.ts +0 -352
  441. package/src/intelligence/analytics/test.ts +0 -127
  442. package/src/intelligence/analytics/workflow/index.ts +0 -375
  443. package/src/intelligence/index.ts +0 -50
  444. package/src/lsp/client.ts +0 -249
  445. package/src/lsp/diagnostic.ts +0 -29
  446. package/src/lsp/index.ts +0 -3
  447. package/src/lsp/language.ts +0 -120
  448. package/src/lsp/launch.ts +0 -21
  449. package/src/lsp/lsp.ts +0 -519
  450. package/src/lsp/server.ts +0 -1956
  451. package/src/mcp/auth.ts +0 -144
  452. package/src/mcp/index.ts +0 -939
  453. package/src/mcp/oauth-callback.ts +0 -236
  454. package/src/mcp/oauth-provider.ts +0 -214
  455. package/src/memory/fts-query.ts +0 -37
  456. package/src/memory/fts.sql.ts +0 -19
  457. package/src/memory/index.ts +0 -1
  458. package/src/memory/paths.ts +0 -116
  459. package/src/memory/reconcile.ts +0 -144
  460. package/src/memory/service.ts +0 -144
  461. package/src/metrics/client.ts +0 -40
  462. package/src/metrics/event.ts +0 -43
  463. package/src/metrics/index.ts +0 -5
  464. package/src/metrics/installation.ts +0 -18
  465. package/src/metrics/subscriber.ts +0 -58
  466. package/src/metrics/util.ts +0 -9
  467. package/src/node.ts +0 -6
  468. package/src/npm/config.ts +0 -0
  469. package/src/npm/index.ts +0 -293
  470. package/src/npmcli-config.d.ts +0 -43
  471. package/src/patch/index.ts +0 -680
  472. package/src/permission/arity.ts +0 -163
  473. package/src/permission/evaluate.ts +0 -15
  474. package/src/permission/index.ts +0 -382
  475. package/src/permission/schema.ts +0 -17
  476. package/src/plugin/checkpoint-splitover.ts +0 -60
  477. package/src/plugin/cloudflare.ts +0 -76
  478. package/src/plugin/codex.ts +0 -611
  479. package/src/plugin/github-copilot/copilot.ts +0 -368
  480. package/src/plugin/github-copilot/models.ts +0 -153
  481. package/src/plugin/index.ts +0 -637
  482. package/src/plugin/install.ts +0 -439
  483. package/src/plugin/loader.ts +0 -216
  484. package/src/plugin/matcher.ts +0 -33
  485. package/src/plugin/meta.ts +0 -188
  486. package/src/plugin/mimo.ts +0 -296
  487. package/src/plugin/shared.ts +0 -323
  488. package/src/plugin/subagent-progress-checker.ts +0 -147
  489. package/src/project/bootstrap.ts +0 -59
  490. package/src/project/index.ts +0 -2
  491. package/src/project/instance.ts +0 -215
  492. package/src/project/project-id.ts +0 -48
  493. package/src/project/project.sql.ts +0 -16
  494. package/src/project/project.ts +0 -522
  495. package/src/project/schema.ts +0 -15
  496. package/src/project/vcs.ts +0 -227
  497. package/src/project/workspace-trust.ts +0 -67
  498. package/src/provider/auth.ts +0 -234
  499. package/src/provider/error.ts +0 -216
  500. package/src/provider/index.ts +0 -5
  501. package/src/provider/models.ts +0 -180
  502. package/src/provider/provider.ts +0 -1788
  503. package/src/provider/schema.ts +0 -36
  504. package/src/provider/sdk/copilot/README.md +0 -5
  505. package/src/provider/sdk/copilot/chat/convert-to-openai-compatible-chat-messages.ts +0 -170
  506. package/src/provider/sdk/copilot/chat/get-response-metadata.ts +0 -15
  507. package/src/provider/sdk/copilot/chat/map-openai-compatible-finish-reason.ts +0 -19
  508. package/src/provider/sdk/copilot/chat/openai-compatible-api-types.ts +0 -64
  509. package/src/provider/sdk/copilot/chat/openai-compatible-chat-language-model.ts +0 -815
  510. package/src/provider/sdk/copilot/chat/openai-compatible-chat-options.ts +0 -28
  511. package/src/provider/sdk/copilot/chat/openai-compatible-metadata-extractor.ts +0 -44
  512. package/src/provider/sdk/copilot/chat/openai-compatible-prepare-tools.ts +0 -83
  513. package/src/provider/sdk/copilot/copilot-provider.ts +0 -100
  514. package/src/provider/sdk/copilot/index.ts +0 -2
  515. package/src/provider/sdk/copilot/openai-compatible-error.ts +0 -27
  516. package/src/provider/sdk/copilot/responses/convert-to-openai-responses-input.ts +0 -335
  517. package/src/provider/sdk/copilot/responses/map-openai-responses-finish-reason.ts +0 -22
  518. package/src/provider/sdk/copilot/responses/openai-config.ts +0 -18
  519. package/src/provider/sdk/copilot/responses/openai-error.ts +0 -22
  520. package/src/provider/sdk/copilot/responses/openai-responses-api-types.ts +0 -214
  521. package/src/provider/sdk/copilot/responses/openai-responses-language-model.ts +0 -1770
  522. package/src/provider/sdk/copilot/responses/openai-responses-prepare-tools.ts +0 -173
  523. package/src/provider/sdk/copilot/responses/openai-responses-settings.ts +0 -1
  524. package/src/provider/sdk/copilot/responses/tool/code-interpreter.ts +0 -87
  525. package/src/provider/sdk/copilot/responses/tool/file-search.ts +0 -127
  526. package/src/provider/sdk/copilot/responses/tool/image-generation.ts +0 -114
  527. package/src/provider/sdk/copilot/responses/tool/local-shell.ts +0 -64
  528. package/src/provider/sdk/copilot/responses/tool/web-search-preview.ts +0 -103
  529. package/src/provider/sdk/copilot/responses/tool/web-search.ts +0 -102
  530. package/src/provider/transform.ts +0 -1376
  531. package/src/pty/index.ts +0 -364
  532. package/src/pty/pty.bun.ts +0 -26
  533. package/src/pty/pty.node.ts +0 -27
  534. package/src/pty/pty.ts +0 -25
  535. package/src/pty/schema.ts +0 -17
  536. package/src/question/index.ts +0 -252
  537. package/src/question/schema.ts +0 -17
  538. package/src/server/adapter.bun.ts +0 -40
  539. package/src/server/adapter.node.ts +0 -66
  540. package/src/server/adapter.ts +0 -21
  541. package/src/server/auth.ts +0 -16
  542. package/src/server/error.ts +0 -53
  543. package/src/server/event.ts +0 -7
  544. package/src/server/fence.ts +0 -81
  545. package/src/server/mdns.ts +0 -60
  546. package/src/server/middleware.ts +0 -94
  547. package/src/server/projectors.ts +0 -28
  548. package/src/server/proxy.ts +0 -171
  549. package/src/server/pty-ticket.ts +0 -42
  550. package/src/server/rate-limit.ts +0 -38
  551. package/src/server/routes/control/index.ts +0 -160
  552. package/src/server/routes/control/workspace.ts +0 -203
  553. package/src/server/routes/global.ts +0 -367
  554. package/src/server/routes/instance/bash-interactive.ts +0 -82
  555. package/src/server/routes/instance/config.ts +0 -89
  556. package/src/server/routes/instance/event.ts +0 -108
  557. package/src/server/routes/instance/experimental.ts +0 -408
  558. package/src/server/routes/instance/file.ts +0 -190
  559. package/src/server/routes/instance/httpapi/config.ts +0 -51
  560. package/src/server/routes/instance/httpapi/permission.ts +0 -72
  561. package/src/server/routes/instance/httpapi/project.ts +0 -62
  562. package/src/server/routes/instance/httpapi/provider.ts +0 -142
  563. package/src/server/routes/instance/httpapi/question.ts +0 -121
  564. package/src/server/routes/instance/httpapi/server.ts +0 -153
  565. package/src/server/routes/instance/index.ts +0 -301
  566. package/src/server/routes/instance/mcp.ts +0 -260
  567. package/src/server/routes/instance/middleware.ts +0 -44
  568. package/src/server/routes/instance/permission.ts +0 -73
  569. package/src/server/routes/instance/project.ts +0 -122
  570. package/src/server/routes/instance/provider.ts +0 -158
  571. package/src/server/routes/instance/pty.ts +0 -302
  572. package/src/server/routes/instance/question.ts +0 -162
  573. package/src/server/routes/instance/session.ts +0 -1328
  574. package/src/server/routes/instance/sync.ts +0 -143
  575. package/src/server/routes/instance/trace.ts +0 -59
  576. package/src/server/routes/instance/tui.ts +0 -384
  577. package/src/server/routes/instance/workflows.ts +0 -142
  578. package/src/server/routes/ui.ts +0 -37
  579. package/src/server/server.ts +0 -146
  580. package/src/server/workspace.ts +0 -122
  581. package/src/session/auto-dream.ts +0 -123
  582. package/src/session/boundary.ts +0 -77
  583. package/src/session/budgeted-read.ts +0 -118
  584. package/src/session/checkpoint-align.ts +0 -29
  585. package/src/session/checkpoint-context.ts +0 -36
  586. package/src/session/checkpoint-paths.ts +0 -86
  587. package/src/session/checkpoint-progress-reconcile.ts +0 -111
  588. package/src/session/checkpoint-retry.ts +0 -192
  589. package/src/session/checkpoint-templates.ts +0 -114
  590. package/src/session/checkpoint-validator.ts +0 -259
  591. package/src/session/checkpoint.ts +0 -1560
  592. package/src/session/classify.ts +0 -117
  593. package/src/session/claude-import.ts +0 -381
  594. package/src/session/codex-import.ts +0 -416
  595. package/src/session/compaction.ts +0 -545
  596. package/src/session/external-import.sql.ts +0 -18
  597. package/src/session/external-import.ts +0 -136
  598. package/src/session/goal.ts +0 -232
  599. package/src/session/index.ts +0 -1
  600. package/src/session/instruction.ts +0 -276
  601. package/src/session/last-message-info.ts +0 -32
  602. package/src/session/llm-request-prefix.ts +0 -82
  603. package/src/session/llm.ts +0 -734
  604. package/src/session/max-mode.ts +0 -410
  605. package/src/session/message-v2.ts +0 -1138
  606. package/src/session/message.ts +0 -191
  607. package/src/session/opendash-import.ts +0 -281
  608. package/src/session/overflow.ts +0 -53
  609. package/src/session/prefix-capture-ref.ts +0 -48
  610. package/src/session/processor.ts +0 -983
  611. package/src/session/projectors.ts +0 -137
  612. package/src/session/prompt/anthropic.txt +0 -177
  613. package/src/session/prompt/beast.txt +0 -186
  614. package/src/session/prompt/build-switch.txt +0 -5
  615. package/src/session/prompt/codex.txt +0 -108
  616. package/src/session/prompt/compose.txt +0 -119
  617. package/src/session/prompt/copilot-gpt-5.txt +0 -173
  618. package/src/session/prompt/deepseek.txt +0 -156
  619. package/src/session/prompt/default.old.txt +0 -151
  620. package/src/session/prompt/default.txt +0 -209
  621. package/src/session/prompt/gemini.txt +0 -186
  622. package/src/session/prompt/glm.txt +0 -73
  623. package/src/session/prompt/gpt.txt +0 -134
  624. package/src/session/prompt/kimi.txt +0 -117
  625. package/src/session/prompt/max-steps.txt +0 -16
  626. package/src/session/prompt/minimax.txt +0 -165
  627. package/src/session/prompt/text-loop-recovery.ts +0 -40
  628. package/src/session/prompt/text-ngram-detection.ts +0 -116
  629. package/src/session/prompt/trinity.txt +0 -128
  630. package/src/session/prompt.ts +0 -3878
  631. package/src/session/prune.ts +0 -481
  632. package/src/session/retry.ts +0 -178
  633. package/src/session/revert.ts +0 -161
  634. package/src/session/run-state.ts +0 -135
  635. package/src/session/schema.ts +0 -36
  636. package/src/session/session.sql.ts +0 -110
  637. package/src/session/session.ts +0 -908
  638. package/src/session/status.ts +0 -89
  639. package/src/session/summary.ts +0 -163
  640. package/src/session/system.ts +0 -97
  641. package/src/session/todo.ts +0 -77
  642. package/src/session/trajectory.ts +0 -98
  643. package/src/share/index.ts +0 -2
  644. package/src/share/session.ts +0 -57
  645. package/src/share/share-next.ts +0 -381
  646. package/src/share/share.sql.ts +0 -13
  647. package/src/shell/shell.ts +0 -124
  648. package/src/skill/builtin/.bundle/self-extend/SKILL.md +0 -131
  649. package/src/skill/builtin/.bundle/self-extend/reference/hook-api.md +0 -242
  650. package/src/skill/builtin/.bundle/self-extend/reference/skill-api.md +0 -114
  651. package/src/skill/builtin/.bundle/self-extend/reference/tool-api.md +0 -115
  652. package/src/skill/builtin/.bundle/self-extend/reference/tui-api.md +0 -258
  653. package/src/skill/builtin/bundle.macro.ts +0 -30
  654. package/src/skill/builtin/extract.ts +0 -41
  655. package/src/skill/compose/.bundle/ask/SKILL.md +0 -58
  656. package/src/skill/compose/.bundle/brainstorm/SKILL.md +0 -200
  657. package/src/skill/compose/.bundle/brainstorm/scripts/frame-template.html +0 -214
  658. package/src/skill/compose/.bundle/brainstorm/scripts/helper.js +0 -88
  659. package/src/skill/compose/.bundle/brainstorm/scripts/server.cjs +0 -354
  660. package/src/skill/compose/.bundle/brainstorm/scripts/start-server.sh +0 -148
  661. package/src/skill/compose/.bundle/brainstorm/scripts/stop-server.sh +0 -56
  662. package/src/skill/compose/.bundle/brainstorm/spec-document-reviewer-prompt.md +0 -50
  663. package/src/skill/compose/.bundle/brainstorm/visual-companion.md +0 -258
  664. package/src/skill/compose/.bundle/debug/CREATION-LOG.md +0 -119
  665. package/src/skill/compose/.bundle/debug/SKILL.md +0 -297
  666. package/src/skill/compose/.bundle/debug/condition-based-waiting-example.ts +0 -158
  667. package/src/skill/compose/.bundle/debug/condition-based-waiting.md +0 -106
  668. package/src/skill/compose/.bundle/debug/defense-in-depth.md +0 -122
  669. package/src/skill/compose/.bundle/debug/find-polluter.sh +0 -63
  670. package/src/skill/compose/.bundle/debug/root-cause-tracing.md +0 -144
  671. package/src/skill/compose/.bundle/debug/test-academic.md +0 -14
  672. package/src/skill/compose/.bundle/debug/test-pressure-1.md +0 -58
  673. package/src/skill/compose/.bundle/debug/test-pressure-2.md +0 -68
  674. package/src/skill/compose/.bundle/debug/test-pressure-3.md +0 -69
  675. package/src/skill/compose/.bundle/execute/SKILL.md +0 -71
  676. package/src/skill/compose/.bundle/feedback/SKILL.md +0 -214
  677. package/src/skill/compose/.bundle/merge/SKILL.md +0 -252
  678. package/src/skill/compose/.bundle/new-skill/SKILL.md +0 -211
  679. package/src/skill/compose/.bundle/parallel/SKILL.md +0 -168
  680. package/src/skill/compose/.bundle/plan/SKILL.md +0 -183
  681. package/src/skill/compose/.bundle/plan/plan-document-reviewer-prompt.md +0 -50
  682. package/src/skill/compose/.bundle/report/SKILL.md +0 -180
  683. package/src/skill/compose/.bundle/review/SKILL.md +0 -104
  684. package/src/skill/compose/.bundle/review/code-reviewer.md +0 -178
  685. package/src/skill/compose/.bundle/subagent/SKILL.md +0 -325
  686. package/src/skill/compose/.bundle/subagent/code-quality-reviewer-prompt.md +0 -26
  687. package/src/skill/compose/.bundle/subagent/implementer-prompt.md +0 -128
  688. package/src/skill/compose/.bundle/subagent/spec-reviewer-prompt.md +0 -118
  689. package/src/skill/compose/.bundle/tdd/SKILL.md +0 -360
  690. package/src/skill/compose/.bundle/tdd/testing-anti-patterns.md +0 -299
  691. package/src/skill/compose/.bundle/verify/SKILL.md +0 -140
  692. package/src/skill/compose/.bundle/worktree/SKILL.md +0 -234
  693. package/src/skill/compose/LICENSE-karpathy +0 -28
  694. package/src/skill/compose/bundle.macro.ts +0 -30
  695. package/src/skill/compose/extract.ts +0 -85
  696. package/src/skill/discovery.ts +0 -116
  697. package/src/skill/index.ts +0 -328
  698. package/src/snapshot/index.ts +0 -777
  699. package/src/sql.d.ts +0 -4
  700. package/src/storage/db.bun.ts +0 -8
  701. package/src/storage/db.node.ts +0 -8
  702. package/src/storage/db.ts +0 -172
  703. package/src/storage/index.ts +0 -26
  704. package/src/storage/json-migration.ts +0 -426
  705. package/src/storage/read-sqlite.bun.ts +0 -11
  706. package/src/storage/read-sqlite.node.ts +0 -13
  707. package/src/storage/read-sqlite.ts +0 -10
  708. package/src/storage/schema.sql.ts +0 -10
  709. package/src/storage/schema.ts +0 -7
  710. package/src/storage/storage.ts +0 -331
  711. package/src/sync/README.md +0 -179
  712. package/src/sync/event.sql.ts +0 -16
  713. package/src/sync/index.ts +0 -278
  714. package/src/sync/schema.ts +0 -14
  715. package/src/task/events.ts +0 -28
  716. package/src/task/gate-state.ts +0 -54
  717. package/src/task/gate.ts +0 -116
  718. package/src/task/index.ts +0 -1
  719. package/src/task/registry.ts +0 -394
  720. package/src/task/schema.ts +0 -43
  721. package/src/task/task.sql.ts +0 -50
  722. package/src/team/events.ts +0 -22
  723. package/src/team/index.ts +0 -113
  724. package/src/team/schema.ts +0 -31
  725. package/src/temporary.ts +0 -33
  726. package/src/tool/actor.shell.txt +0 -72
  727. package/src/tool/actor.ts +0 -804
  728. package/src/tool/actor.txt +0 -103
  729. package/src/tool/apply_patch.ts +0 -308
  730. package/src/tool/apply_patch.txt +0 -33
  731. package/src/tool/bash-interactive.ts +0 -183
  732. package/src/tool/bash.ts +0 -722
  733. package/src/tool/bash.txt +0 -123
  734. package/src/tool/bash_token_efficient_pipeline.ts +0 -189
  735. package/src/tool/change-directory.ts +0 -91
  736. package/src/tool/codesearch.ts +0 -63
  737. package/src/tool/codesearch.txt +0 -12
  738. package/src/tool/edit.ts +0 -752
  739. package/src/tool/edit.txt +0 -10
  740. package/src/tool/external-directory.ts +0 -132
  741. package/src/tool/glob.ts +0 -100
  742. package/src/tool/glob.txt +0 -6
  743. package/src/tool/grep.ts +0 -145
  744. package/src/tool/grep.txt +0 -8
  745. package/src/tool/history.ts +0 -146
  746. package/src/tool/history.txt +0 -17
  747. package/src/tool/index.ts +0 -4
  748. package/src/tool/invalid.ts +0 -20
  749. package/src/tool/invocation-style.ts +0 -17
  750. package/src/tool/lsp.ts +0 -91
  751. package/src/tool/lsp.txt +0 -19
  752. package/src/tool/mcp-exa.ts +0 -78
  753. package/src/tool/memory-path-guard.ts +0 -162
  754. package/src/tool/memory.ts +0 -81
  755. package/src/tool/memory.txt +0 -69
  756. package/src/tool/multiedit.ts +0 -54
  757. package/src/tool/multiedit.txt +0 -41
  758. package/src/tool/notebook-edit.ts +0 -225
  759. package/src/tool/notebook-edit.txt +0 -10
  760. package/src/tool/plan-enter.txt +0 -16
  761. package/src/tool/plan-exit.txt +0 -14
  762. package/src/tool/plan.ts +0 -179
  763. package/src/tool/question.ts +0 -67
  764. package/src/tool/question.txt +0 -10
  765. package/src/tool/read-state.ts +0 -44
  766. package/src/tool/read.ts +0 -327
  767. package/src/tool/read.txt +0 -14
  768. package/src/tool/recoverable.ts +0 -35
  769. package/src/tool/registry.ts +0 -429
  770. package/src/tool/schema.ts +0 -17
  771. package/src/tool/session-cwd.ts +0 -35
  772. package/src/tool/shell-tokenize.ts +0 -374
  773. package/src/tool/shell-wrap.ts +0 -235
  774. package/src/tool/skill.ts +0 -76
  775. package/src/tool/skill.txt +0 -5
  776. package/src/tool/task.shell.txt +0 -57
  777. package/src/tool/task.ts +0 -456
  778. package/src/tool/task.txt +0 -56
  779. package/src/tool/tool.ts +0 -166
  780. package/src/tool/truncate.ts +0 -201
  781. package/src/tool/truncation-dir.ts +0 -4
  782. package/src/tool/webfetch.ts +0 -208
  783. package/src/tool/webfetch.txt +0 -13
  784. package/src/tool/websearch/index.ts +0 -104
  785. package/src/tool/websearch/mimo.ts +0 -118
  786. package/src/tool/websearch/websearch.txt +0 -14
  787. package/src/tool/workflow.ts +0 -357
  788. package/src/tool/workflow.txt +0 -25
  789. package/src/tool/write.ts +0 -88
  790. package/src/tool/write.txt +0 -10
  791. package/src/util/abort.ts +0 -35
  792. package/src/util/archive.ts +0 -15
  793. package/src/util/color.ts +0 -17
  794. package/src/util/data-url.ts +0 -9
  795. package/src/util/defer.ts +0 -10
  796. package/src/util/effect-http-client.ts +0 -11
  797. package/src/util/effect-zod.ts +0 -367
  798. package/src/util/env-info.ts +0 -62
  799. package/src/util/error.ts +0 -78
  800. package/src/util/filesystem.ts +0 -243
  801. package/src/util/fn.ts +0 -21
  802. package/src/util/format.ts +0 -20
  803. package/src/util/iife.ts +0 -3
  804. package/src/util/index.ts +0 -14
  805. package/src/util/keybind.ts +0 -101
  806. package/src/util/lazy.ts +0 -18
  807. package/src/util/local-context.ts +0 -23
  808. package/src/util/locale.ts +0 -79
  809. package/src/util/lock.ts +0 -96
  810. package/src/util/log.ts +0 -234
  811. package/src/util/media.ts +0 -26
  812. package/src/util/network.ts +0 -9
  813. package/src/util/opendash-process.ts +0 -24
  814. package/src/util/process.ts +0 -174
  815. package/src/util/provider-priority.ts +0 -48
  816. package/src/util/queue.ts +0 -60
  817. package/src/util/record.ts +0 -3
  818. package/src/util/rpc.ts +0 -64
  819. package/src/util/schema.ts +0 -53
  820. package/src/util/scrap.ts +0 -10
  821. package/src/util/signal.ts +0 -12
  822. package/src/util/ssrf.ts +0 -116
  823. package/src/util/timeout.ts +0 -14
  824. package/src/util/token.ts +0 -5
  825. package/src/util/tool-compat.ts +0 -144
  826. package/src/util/update-schema.ts +0 -13
  827. package/src/util/which.ts +0 -14
  828. package/src/util/wildcard.ts +0 -57
  829. package/src/workflow/builtin/compose.js +0 -749
  830. package/src/workflow/builtin/deep-research.js +0 -398
  831. package/src/workflow/builtin.ts +0 -59
  832. package/src/workflow/events.ts +0 -72
  833. package/src/workflow/meta.ts +0 -335
  834. package/src/workflow/persistence.ts +0 -312
  835. package/src/workflow/resolve.ts +0 -45
  836. package/src/workflow/runtime-ref.ts +0 -18
  837. package/src/workflow/runtime.ts +0 -1447
  838. package/src/workflow/sandbox.ts +0 -286
  839. package/src/workflow/workflow.sql.ts +0 -31
  840. package/src/workflow/workspace.ts +0 -69
  841. package/src/worktree/index.ts +0 -629
  842. package/sst-env.d.ts +0 -10
  843. package/test/AGENTS.md +0 -133
  844. package/test/account/repo.test.ts +0 -352
  845. package/test/account/service.test.ts +0 -456
  846. package/test/acp/agent-interface.test.ts +0 -51
  847. package/test/acp/event-subscription.test.ts +0 -725
  848. package/test/actor/cancel-cascade.test.ts +0 -432
  849. package/test/actor/no-completion-listener.test.ts +0 -41
  850. package/test/actor/poststop-progress-write-permission.repro.test.ts +0 -414
  851. package/test/actor/registry-render.test.ts +0 -113
  852. package/test/actor/registry-status.test.ts +0 -111
  853. package/test/actor/registry.test.ts +0 -619
  854. package/test/actor/return-header.test.ts +0 -40
  855. package/test/actor/spawn-lifecycle.test.ts +0 -346
  856. package/test/actor/spawn-no-deadlock.test.ts +0 -340
  857. package/test/actor/spawn-notification.test.ts +0 -393
  858. package/test/actor/spawn-task-autostart.test.ts +0 -530
  859. package/test/actor/spawn.test.ts +0 -1106
  860. package/test/actor/status-event-payload.test.ts +0 -132
  861. package/test/actor/terminology.test.ts +0 -39
  862. package/test/actor/turn.test.ts +0 -125
  863. package/test/actor/waiter.test.ts +0 -246
  864. package/test/agent/agent.test.ts +0 -935
  865. package/test/agent/allowlist.test.ts +0 -45
  866. package/test/auth/auth.test.ts +0 -86
  867. package/test/bus/bus-effect.test.ts +0 -162
  868. package/test/bus/bus-integration.test.ts +0 -87
  869. package/test/bus/bus.test.ts +0 -219
  870. package/test/cli/account.test.ts +0 -26
  871. package/test/cli/cmd/tui/autocomplete-detect.test.ts +0 -55
  872. package/test/cli/cmd/tui/extmark-cjk.test.ts +0 -96
  873. package/test/cli/cmd/tui/offset.test.ts +0 -101
  874. package/test/cli/cmd/tui/prompt-part.test.ts +0 -97
  875. package/test/cli/error.test.ts +0 -18
  876. package/test/cli/github-action.test.ts +0 -198
  877. package/test/cli/github-remote.test.ts +0 -80
  878. package/test/cli/import.test.ts +0 -54
  879. package/test/cli/plugin-auth-picker.test.ts +0 -120
  880. package/test/cli/run-completion.test.ts +0 -131
  881. package/test/cli/tui/keybind-plugin.test.ts +0 -90
  882. package/test/cli/tui/plugin-add.test.ts +0 -111
  883. package/test/cli/tui/plugin-install.test.ts +0 -87
  884. package/test/cli/tui/plugin-lifecycle.test.ts +0 -224
  885. package/test/cli/tui/plugin-loader-entrypoint.test.ts +0 -484
  886. package/test/cli/tui/plugin-loader-pure.test.ts +0 -71
  887. package/test/cli/tui/plugin-loader.test.ts +0 -816
  888. package/test/cli/tui/plugin-toggle.test.ts +0 -157
  889. package/test/cli/tui/revert-diff.test.ts +0 -35
  890. package/test/cli/tui/route-agent-id.test.ts +0 -26
  891. package/test/cli/tui/sidebar-tps.test.ts +0 -63
  892. package/test/cli/tui/slot-replace.test.tsx +0 -47
  893. package/test/cli/tui/sync-bucket.test.ts +0 -29
  894. package/test/cli/tui/theme-store.test.ts +0 -51
  895. package/test/cli/tui/thread.test.ts +0 -125
  896. package/test/cli/tui/transcript.test.ts +0 -426
  897. package/test/cli/tui/use-event.test.tsx +0 -175
  898. package/test/cli/tui/voice.test.ts +0 -443
  899. package/test/command/deep-research-command.test.ts +0 -16
  900. package/test/config/agent-color.test.ts +0 -77
  901. package/test/config/checkpoint-fork.test.ts +0 -21
  902. package/test/config/config.test.ts +0 -2577
  903. package/test/config/fixtures/empty-frontmatter.md +0 -4
  904. package/test/config/fixtures/frontmatter.md +0 -28
  905. package/test/config/fixtures/markdown-header.md +0 -11
  906. package/test/config/fixtures/no-frontmatter.md +0 -1
  907. package/test/config/fixtures/weird-model-id.md +0 -13
  908. package/test/config/lsp.test.ts +0 -87
  909. package/test/config/markdown.test.ts +0 -228
  910. package/test/config/plugin.test.ts +0 -0
  911. package/test/config/tui.test.ts +0 -627
  912. package/test/control-plane/adaptors.test.ts +0 -71
  913. package/test/control-plane/sse.test.ts +0 -56
  914. package/test/effect/app-runtime-logger.test.ts +0 -92
  915. package/test/effect/cross-spawn-spawner.test.ts +0 -411
  916. package/test/effect/instance-state.test.ts +0 -482
  917. package/test/effect/observability.test.ts +0 -46
  918. package/test/effect/run-service.test.ts +0 -46
  919. package/test/effect/runner-warn-log.test.ts +0 -111
  920. package/test/effect/runner.test.ts +0 -494
  921. package/test/fake/provider.ts +0 -90
  922. package/test/file/fsmonitor.test.ts +0 -68
  923. package/test/file/ignore.test.ts +0 -10
  924. package/test/file/index.test.ts +0 -963
  925. package/test/file/path-traversal.test.ts +0 -243
  926. package/test/file/ripgrep.test.ts +0 -218
  927. package/test/file/watcher.test.ts +0 -249
  928. package/test/filesystem/filesystem.test.ts +0 -319
  929. package/test/fixture/db.ts +0 -11
  930. package/test/fixture/fixture.test.ts +0 -58
  931. package/test/fixture/fixture.ts +0 -223
  932. package/test/fixture/flock-worker.ts +0 -72
  933. package/test/fixture/lsp/fake-lsp-server.js +0 -75
  934. package/test/fixture/plug-worker.ts +0 -93
  935. package/test/fixture/plugin-meta-worker.ts +0 -19
  936. package/test/fixture/skills/agents-sdk/SKILL.md +0 -152
  937. package/test/fixture/skills/agents-sdk/references/callable.md +0 -92
  938. package/test/fixture/skills/cloudflare/SKILL.md +0 -211
  939. package/test/fixture/skills/index.json +0 -6
  940. package/test/fixture/tui-plugin.ts +0 -328
  941. package/test/fixture/tui-runtime.ts +0 -31
  942. package/test/format/format.test.ts +0 -244
  943. package/test/git/git.test.ts +0 -128
  944. package/test/global/fixture/global-paths-worker.ts +0 -17
  945. package/test/global/mimocode-home.test.ts +0 -143
  946. package/test/history/backfill.test.ts +0 -160
  947. package/test/history/extract.test.ts +0 -106
  948. package/test/history/fts-query.test.ts +0 -30
  949. package/test/history/resolve.test.ts +0 -130
  950. package/test/history/service.test.ts +0 -210
  951. package/test/history/writer.test.ts +0 -163
  952. package/test/ide/ide.test.ts +0 -82
  953. package/test/inbox/drain-in-loop.test.ts +0 -230
  954. package/test/inbox/fork-agent-compat.test.ts +0 -387
  955. package/test/inbox/gc-on-init.test.ts +0 -167
  956. package/test/inbox/send-no-block.test.ts +0 -120
  957. package/test/inbox/sender-cancel-independence.test.ts +0 -160
  958. package/test/inbox/wake-matrix.test.ts +0 -141
  959. package/test/installation/installation.test.ts +0 -255
  960. package/test/keybind.test.ts +0 -421
  961. package/test/lib/effect.ts +0 -53
  962. package/test/lib/filesystem.ts +0 -10
  963. package/test/lib/llm-server.ts +0 -770
  964. package/test/lib/mock-llm.ts +0 -159
  965. package/test/lib/scripted-llm-server.ts +0 -245
  966. package/test/lsp/client.test.ts +0 -98
  967. package/test/lsp/index.test.ts +0 -109
  968. package/test/lsp/launch.test.ts +0 -22
  969. package/test/lsp/lifecycle.test.ts +0 -184
  970. package/test/mcp/headers.test.ts +0 -178
  971. package/test/mcp/lifecycle.test.ts +0 -786
  972. package/test/mcp/oauth-auto-connect.test.ts +0 -281
  973. package/test/mcp/oauth-browser.test.ts +0 -268
  974. package/test/mcp/oauth-callback.test.ts +0 -34
  975. package/test/memory/abort-leak-webfetch.ts +0 -49
  976. package/test/memory/abort-leak.test.ts +0 -127
  977. package/test/memory/cc-frontmatter.test.ts +0 -85
  978. package/test/memory/cc-paths.test.ts +0 -60
  979. package/test/memory/cc-reconcile.test.ts +0 -239
  980. package/test/memory/cc-search.test.ts +0 -151
  981. package/test/memory/fts-query.test.ts +0 -48
  982. package/test/memory/fts-rowid-stability.test.ts +0 -271
  983. package/test/memory/paths.test.ts +0 -210
  984. package/test/memory/reconcile.test.ts +0 -115
  985. package/test/memory/service.test.ts +0 -169
  986. package/test/npm.test.ts +0 -18
  987. package/test/patch/patch.test.ts +0 -348
  988. package/test/permission/abort.test.ts +0 -116
  989. package/test/permission/arity.test.ts +0 -33
  990. package/test/permission/disabled.test.ts +0 -68
  991. package/test/permission/next.test.ts +0 -1116
  992. package/test/permission/non-interactive.test.ts +0 -55
  993. package/test/permission-task.test.ts +0 -326
  994. package/test/plugin/actor-hooks.test.ts +0 -1471
  995. package/test/plugin/auth-override.test.ts +0 -79
  996. package/test/plugin/checkpoint-splitover.test.ts +0 -434
  997. package/test/plugin/cloudflare.test.ts +0 -68
  998. package/test/plugin/codex.test.ts +0 -123
  999. package/test/plugin/github-copilot-models.test.ts +0 -163
  1000. package/test/plugin/install-concurrency.test.ts +0 -140
  1001. package/test/plugin/install.test.ts +0 -570
  1002. package/test/plugin/loader-shared.test.ts +0 -1169
  1003. package/test/plugin/matcher.test.ts +0 -97
  1004. package/test/plugin/meta.test.ts +0 -137
  1005. package/test/plugin/mimo.test.ts +0 -259
  1006. package/test/plugin/session-loop-hooks.test.ts +0 -159
  1007. package/test/plugin/shared.test.ts +0 -88
  1008. package/test/plugin/subagent-progress-checker.test.ts +0 -227
  1009. package/test/plugin/trigger.test.ts +0 -116
  1010. package/test/plugin/workspace-adaptor.test.ts +0 -109
  1011. package/test/preload.ts +0 -102
  1012. package/test/project/migrate-global.test.ts +0 -152
  1013. package/test/project/project-id.test.ts +0 -64
  1014. package/test/project/project.test.ts +0 -504
  1015. package/test/project/vcs.test.ts +0 -286
  1016. package/test/project/worktree-remove.test.ts +0 -126
  1017. package/test/project/worktree.test.ts +0 -222
  1018. package/test/provider/amazon-bedrock.test.ts +0 -462
  1019. package/test/provider/copilot/convert-to-copilot-messages.test.ts +0 -523
  1020. package/test/provider/copilot/copilot-chat-model.test.ts +0 -592
  1021. package/test/provider/error.test.ts +0 -160
  1022. package/test/provider/gitlab-duo.test.ts +0 -413
  1023. package/test/provider/model-groups.test.ts +0 -389
  1024. package/test/provider/provider-chunk-timeout.test.ts +0 -23
  1025. package/test/provider/provider.test.ts +0 -2610
  1026. package/test/provider/transform.test.ts +0 -3523
  1027. package/test/pty/pty-output-isolation.test.ts +0 -146
  1028. package/test/pty/pty-session.test.ts +0 -102
  1029. package/test/pty/pty-shell.test.ts +0 -69
  1030. package/test/question/question.test.ts +0 -464
  1031. package/test/server/global-session-list.test.ts +0 -105
  1032. package/test/server/project-init-git.test.ts +0 -137
  1033. package/test/server/rate-limit.test.ts +0 -66
  1034. package/test/server/session-actions.test.ts +0 -49
  1035. package/test/server/session-list.test.ts +0 -110
  1036. package/test/server/session-messages.test.ts +0 -220
  1037. package/test/server/session-prompt-busy.test.ts +0 -146
  1038. package/test/server/session-prompt-heartbeat.test.ts +0 -131
  1039. package/test/server/session-select.test.ts +0 -100
  1040. package/test/server/session-task-route.test.ts +0 -165
  1041. package/test/server/summarize-route-main-slice.test.ts +0 -99
  1042. package/test/server/trace-attributes.test.ts +0 -76
  1043. package/test/server/workflows-route.test.ts +0 -363
  1044. package/test/session/bootstrap-skip-system.test.ts +0 -121
  1045. package/test/session/boundary.test.ts +0 -33
  1046. package/test/session/budgeted-read.test.ts +0 -74
  1047. package/test/session/checkpoint-align.test.ts +0 -58
  1048. package/test/session/checkpoint-boundary.test.ts +0 -186
  1049. package/test/session/checkpoint-child-session.test.ts +0 -509
  1050. package/test/session/checkpoint-context.test.ts +0 -141
  1051. package/test/session/checkpoint-drain.test.ts +0 -189
  1052. package/test/session/checkpoint-extract-titles.test.ts +0 -58
  1053. package/test/session/checkpoint-fork-mode.test.ts +0 -577
  1054. package/test/session/checkpoint-main-slice.test.ts +0 -261
  1055. package/test/session/checkpoint-paths.test.ts +0 -87
  1056. package/test/session/checkpoint-permission.test.ts +0 -136
  1057. package/test/session/checkpoint-progress-reconcile.test.ts +0 -219
  1058. package/test/session/checkpoint-rebuild-unify.test.ts +0 -158
  1059. package/test/session/checkpoint-rebuild-v3.test.ts +0 -259
  1060. package/test/session/checkpoint-render-verify.test.ts +0 -512
  1061. package/test/session/checkpoint-retry.test.ts +0 -150
  1062. package/test/session/checkpoint-splitover-integration.test.ts +0 -533
  1063. package/test/session/checkpoint-templates.test.ts +0 -51
  1064. package/test/session/checkpoint-thresholds.test.ts +0 -120
  1065. package/test/session/checkpoint-validator.test.ts +0 -189
  1066. package/test/session/classify-integration.test.ts +0 -476
  1067. package/test/session/classify.test.ts +0 -390
  1068. package/test/session/codex-import.test.ts +0 -331
  1069. package/test/session/compaction-agent-scope.test.ts +0 -209
  1070. package/test/session/context-inheritance.test.ts +0 -46
  1071. package/test/session/external-import.test.ts +0 -17
  1072. package/test/session/fork-prefix-invariant.test.ts +0 -116
  1073. package/test/session/goal.test.ts +0 -106
  1074. package/test/session/instruction.test.ts +0 -388
  1075. package/test/session/invalid-output-continuation.test.ts +0 -150
  1076. package/test/session/last-message-info.test.ts +0 -47
  1077. package/test/session/length-tool-safety.test.ts +0 -125
  1078. package/test/session/llm-request-prefix.test.ts +0 -197
  1079. package/test/session/llm-retry.test.ts +0 -59
  1080. package/test/session/llm-system-prompt.test.ts +0 -479
  1081. package/test/session/llm.test.ts +0 -1268
  1082. package/test/session/main-lifecycle.test.ts +0 -51
  1083. package/test/session/main-runloop-history-invariant.test.ts +0 -182
  1084. package/test/session/max-mode-econnreset.test.ts +0 -232
  1085. package/test/session/max-mode.test.ts +0 -54
  1086. package/test/session/message-v2-filter.test.ts +0 -197
  1087. package/test/session/message-v2.test.ts +0 -1119
  1088. package/test/session/messages-default-main.test.ts +0 -105
  1089. package/test/session/messages-pagination.test.ts +0 -888
  1090. package/test/session/overflow.test.ts +0 -576
  1091. package/test/session/processor-effect.test.ts +0 -853
  1092. package/test/session/prompt-effect.test.ts +0 -1534
  1093. package/test/session/prompt-rebuild-loop.test.ts +0 -108
  1094. package/test/session/prompt-rebuild-reset.test.ts +0 -67
  1095. package/test/session/prompt-sweep.test.ts +0 -145
  1096. package/test/session/prompt-task-gate.test.ts +0 -127
  1097. package/test/session/prompt.test.ts +0 -827
  1098. package/test/session/prune-main-slice.test.ts +0 -272
  1099. package/test/session/prune-skip-system.test.ts +0 -346
  1100. package/test/session/prune.test.ts +0 -419
  1101. package/test/session/rebuild-microcompact.test.ts +0 -318
  1102. package/test/session/recall-reminder.test.ts +0 -37
  1103. package/test/session/recent-user-msg.test.ts +0 -219
  1104. package/test/session/retry.test.ts +0 -410
  1105. package/test/session/revert-compact.test.ts +0 -639
  1106. package/test/session/run-state-tuple-key.test.ts +0 -152
  1107. package/test/session/session-create-registers-main.test.ts +0 -70
  1108. package/test/session/session.test.ts +0 -181
  1109. package/test/session/snapshot-tool-race.test.ts +0 -301
  1110. package/test/session/structured-output-integration.test.ts +0 -264
  1111. package/test/session/structured-output-retry.test.ts +0 -127
  1112. package/test/session/structured-output.test.ts +0 -397
  1113. package/test/session/summary-main-slice.test.ts +0 -170
  1114. package/test/session/system.test.ts +0 -72
  1115. package/test/session/text-loop-detection.test.ts +0 -185
  1116. package/test/session/text-loop-integration.test.ts +0 -448
  1117. package/test/session/text-ngram-detection.test.ts +0 -169
  1118. package/test/session/trajectory.test.ts +0 -236
  1119. package/test/share/share-next.test.ts +0 -332
  1120. package/test/shell/shell.test.ts +0 -73
  1121. package/test/skill/compose-review.test.ts +0 -174
  1122. package/test/skill/discovery.test.ts +0 -116
  1123. package/test/skill/skill.test.ts +0 -466
  1124. package/test/snapshot/snapshot.test.ts +0 -1531
  1125. package/test/storage/db.test.ts +0 -16
  1126. package/test/storage/json-migration.test.ts +0 -831
  1127. package/test/storage/storage.test.ts +0 -293
  1128. package/test/sync/index.test.ts +0 -237
  1129. package/test/task/gate-state.test.ts +0 -66
  1130. package/test/task/gate.test.ts +0 -167
  1131. package/test/task/registry.test.ts +0 -171
  1132. package/test/task/state-machine.test.ts +0 -292
  1133. package/test/team/migrate-to-inbox.test.ts +0 -124
  1134. package/test/team/team.test.ts +0 -75
  1135. package/test/tool/__snapshots__/tool.test.ts.snap +0 -9
  1136. package/test/tool/actor-cancel.test.ts +0 -211
  1137. package/test/tool/actor-recover.test.ts +0 -50
  1138. package/test/tool/actor-send.test.ts +0 -200
  1139. package/test/tool/actor-status.test.ts +0 -296
  1140. package/test/tool/actor-wait.test.ts +0 -193
  1141. package/test/tool/actor.shell.test.ts +0 -266
  1142. package/test/tool/actor.test.ts +0 -753
  1143. package/test/tool/apply_patch.test.ts +0 -626
  1144. package/test/tool/bash.test.ts +0 -1232
  1145. package/test/tool/bash_token_efficient_pipeline.test.ts +0 -329
  1146. package/test/tool/describe-workflow.test.ts +0 -12
  1147. package/test/tool/edit.test.ts +0 -730
  1148. package/test/tool/external-directory.test.ts +0 -207
  1149. package/test/tool/fixtures/large-image.png +0 -0
  1150. package/test/tool/fixtures/models-api.json +0 -65179
  1151. package/test/tool/glob.test.ts +0 -81
  1152. package/test/tool/grep.test.ts +0 -114
  1153. package/test/tool/history.test.ts +0 -144
  1154. package/test/tool/invocation-style.test.ts +0 -30
  1155. package/test/tool/memory-edit-ask-skip.test.ts +0 -62
  1156. package/test/tool/memory-path-guard.test.ts +0 -594
  1157. package/test/tool/memory.test.ts +0 -71
  1158. package/test/tool/question.test.ts +0 -167
  1159. package/test/tool/read.test.ts +0 -483
  1160. package/test/tool/recoverable.test.ts +0 -36
  1161. package/test/tool/registry-invocation-style.test.ts +0 -121
  1162. package/test/tool/registry.test.ts +0 -164
  1163. package/test/tool/shell-tokenize.test.ts +0 -309
  1164. package/test/tool/shell-wrap-missing-script.test.ts +0 -128
  1165. package/test/tool/shell-wrap.test.ts +0 -345
  1166. package/test/tool/skill.test.ts +0 -99
  1167. package/test/tool/task-recover.test.ts +0 -36
  1168. package/test/tool/task.shell.test.ts +0 -234
  1169. package/test/tool/task.test.ts +0 -296
  1170. package/test/tool/tool-def-shell-shape.test.ts +0 -23
  1171. package/test/tool/tool-define.test.ts +0 -59
  1172. package/test/tool/tool-validation-error.test.ts +0 -25
  1173. package/test/tool/truncation.test.ts +0 -253
  1174. package/test/tool/webfetch.test.ts +0 -103
  1175. package/test/tool/whitelist.test.ts +0 -377
  1176. package/test/tool/write.test.ts +0 -244
  1177. package/test/util/data-url.test.ts +0 -14
  1178. package/test/util/effect-zod.test.ts +0 -869
  1179. package/test/util/env-info.test.ts +0 -26
  1180. package/test/util/error.test.ts +0 -38
  1181. package/test/util/filesystem.test.ts +0 -656
  1182. package/test/util/format.test.ts +0 -59
  1183. package/test/util/glob.test.ts +0 -164
  1184. package/test/util/iife.test.ts +0 -36
  1185. package/test/util/lazy.test.ts +0 -50
  1186. package/test/util/lock.test.ts +0 -72
  1187. package/test/util/log.test.ts +0 -69
  1188. package/test/util/module.test.ts +0 -59
  1189. package/test/util/process.test.ts +0 -128
  1190. package/test/util/queue.test.ts +0 -64
  1191. package/test/util/ssrf.test.ts +0 -115
  1192. package/test/util/timeout.test.ts +0 -21
  1193. package/test/util/tool-compat.test.ts +0 -189
  1194. package/test/util/which.test.ts +0 -100
  1195. package/test/util/wildcard.test.ts +0 -90
  1196. package/test/workflow/builtin.test.ts +0 -36
  1197. package/test/workflow/compose.test.ts +0 -668
  1198. package/test/workflow/deep-research-cluster.test.ts +0 -47
  1199. package/test/workflow/lib.ts +0 -243
  1200. package/test/workflow/meta.test.ts +0 -142
  1201. package/test/workflow/model-routing.test.ts +0 -68
  1202. package/test/workflow/persistence.test.ts +0 -229
  1203. package/test/workflow/resolve.test.ts +0 -37
  1204. package/test/workflow/runtime-nested.test.ts +0 -419
  1205. package/test/workflow/runtime-worktree.test.ts +0 -261
  1206. package/test/workflow/runtime.test.ts +0 -1142
  1207. package/test/workflow/sandbox.test.ts +0 -259
  1208. package/test/workflow/tool.test.ts +0 -487
  1209. package/test/workflow/verify-wow.test.ts +0 -144
  1210. package/test/workflow/workspace.test.ts +0 -88
  1211. package/test/workspace/workspace-restore.test.ts +0 -281
  1212. package/test/worktree/index.test.ts +0 -30
  1213. package/tsconfig.json +0 -24
@@ -1,1447 +0,0 @@
1
- import { Context, Deferred, Effect, Exit, Fiber, Layer, Scope } from "effect"
2
- import os from "node:os"
3
- import { createHash } from "node:crypto"
4
- import { spawnRef } from "@/actor/spawn-ref"
5
- import { workflowRef } from "./runtime-ref"
6
- import { Config } from "@/config"
7
- import { EffectBridge } from "@/effect"
8
- import { Bus } from "@/bus"
9
- import { Inbox } from "@/inbox"
10
- import { Worktree } from "@/worktree"
11
- import { Provider } from "@/provider"
12
- import { InstanceRef } from "@/effect/instance-ref"
13
- import { Instance } from "@/project/instance"
14
- import { Identifier } from "@/id/id"
15
- import type { SessionID } from "@/session/schema"
16
- import type { ProviderID, ModelID } from "@/provider/schema"
17
- import { parseMeta } from "./meta"
18
- import { evalScript, type HostFn } from "./sandbox"
19
- import { makeFileHooks, resolveInWorkspace } from "./workspace"
20
- import { isInlineScript, resolveWorkflowScript } from "./resolve"
21
- import { WorkflowAgentFailed, WorkflowChildFailed, WorkflowFinished, WorkflowLog, WorkflowPhase, WorkflowStarted } from "./events"
22
- import { WorkflowPersistence, journalKeyBase } from "./persistence"
23
- import type { RunSummary } from "./persistence"
24
- import { Log, Lock } from "@/util"
25
-
26
- const log = Log.create({ service: "workflow.runtime" })
27
-
28
- /** Default wall-clock budget for a whole workflow script (12h research default). */
29
- const SCRIPT_DEADLINE_MS = 12 * 60 * 60 * 1000
30
- /** Unique sentinel for the per-agent timeout race: a timeout winner can never
31
- * collide with an agent deliverable (those are object | string | null). */
32
- const STRAGGLER_TIMEOUT = Symbol("straggler-timeout")
33
- /** Hard ceiling on total agents a single run may spawn (lifecycle cap). */
34
- const MAX_LIFECYCLE_AGENTS = 1000
35
- /** Default soft cap on concurrent agents when the caller does not specify one. */
36
- const DEFAULT_MAX_CONCURRENT = 16
37
- /** Marker prefix on errors from STRUCTURAL workflow faults (cycle, over-depth,
38
- * unknown name) — workflow-wiring bugs that must fail the whole tree loud rather
39
- * than degrade to the never-throw null that a child's RUNTIME failure yields. The
40
- * workflow() hook re-propagates any child outcome whose error carries this marker,
41
- * so the fault surfaces at the root run the user launched. */
42
- const WORKFLOW_STRUCTURAL_ERROR = "WorkflowStructuralError"
43
-
44
- type RunStatus = "running" | "completed" | "failed" | "cancelled"
45
-
46
- export type RunOutcome =
47
- | { status: "completed"; result: unknown }
48
- | { status: "failed"; error: string }
49
- | { status: "cancelled" }
50
-
51
- /** One ordered transcript line. The runtime appends these synchronously from the
52
- * guest's phase()/log() hooks (in-process QuickJS, same thread), so the array is
53
- * the authoritative program-order record — no bus delivery race, no cross-event
54
- * reordering. Consumers (the workflow tool's sync path) read it instead of
55
- * subscribing to WorkflowPhase/WorkflowLog. */
56
- export type WorkflowTranscriptEntry = { kind: "phase" | "log"; text: string }
57
-
58
- // Observability-only structure tree for one run, recorded in the agent()/phase()/
59
- // workflow() host hooks. Each agent/workflow node is attributed to the phase
60
- // current at call time (known synchronously inside the hook — no timing guess).
61
- // This NEVER touches journal keys / occ counts / resume: adding or removing it
62
- // changes no run outcome. parallel/pipeline batch grouping is intentionally not
63
- // recorded (pure-guest helpers, no AsyncLocalStorage in QuickJS) — agents are
64
- // siblings under their phase.
65
- export type WorkflowNode =
66
- | { type: "phase"; id: string; title: string }
67
- | {
68
- type: "agent"
69
- id: string
70
- phaseId?: string
71
- label?: string
72
- agentType: string
73
- /** The prompt the guest passed to agent() — the call's primary parameter. */
74
- prompt: string
75
- /** Resolved-ref model the call requested (undefined = run default). */
76
- model?: string
77
- /** Tool allowlist the call passed, if any. */
78
- tools?: string[]
79
- /** Whether the call requested structured output (a schema was passed). */
80
- schema?: boolean
81
- /** Whether the call ran in an isolated worktree. */
82
- isolation?: boolean
83
- /** The spawned child actor id (filled once spawned; absent for cache hits / over-cap). */
84
- actorID?: string
85
- /** Wall-clock duration in ms (filled when the call settles). */
86
- durationMs?: number
87
- /** Short summary of the agent's deliverable (the value agent() resolved to),
88
- * so the tree shows what it actually produced — not just that it finished. */
89
- resultSummary?: string
90
- status: "running" | "succeeded" | "failed"
91
- }
92
- | {
93
- type: "workflow"
94
- id: string
95
- phaseId?: string
96
- childRunID: string
97
- name: string
98
- /** The args the guest passed to workflow() (JSON), for parity with agent params. */
99
- args?: unknown
100
- status: "running" | "completed" | "failed" | "cancelled"
101
- }
102
- export type WorkflowStructure = { nodes: WorkflowNode[] }
103
-
104
- // Short, display-only summary of an agent's deliverable for the structure tree.
105
- // A deliverable is a string (prose finalText) or a structured object; a worktree
106
- // deliverable is wrapped as { _worktree, result }. We flatten to one line and cap
107
- // length — purely observability, never fed to the model. Capped generously so the
108
- // card shows a substantial chunk of the response (the full trace is one ↗ away).
109
- const RESULT_SUMMARY_MAX = 600
110
- function summarizeAgentResult(result: unknown): string | undefined {
111
- if (result === null || result === undefined) return undefined
112
- const unwrapped =
113
- typeof result === "object" && result !== null && "_worktree" in result
114
- ? (result as { result?: unknown }).result ?? result
115
- : result
116
- // JSON.stringify can throw (cycles, BigInt). This runs on the host settle path
117
- // inside markAgentNode, so a throw would escape into the run — guard it: a result
118
- // we can't summarize just yields no summary, never breaks the agent.
119
- let text: string
120
- try {
121
- text = typeof unwrapped === "string" ? unwrapped : JSON.stringify(unwrapped, null, 2)
122
- } catch {
123
- return undefined
124
- }
125
- if (!text) return undefined
126
- // Preserve line breaks (collapse only runs of spaces/tabs) so a multi-paragraph
127
- // response renders as readable text in the card, then cap total length.
128
- const trimmed = text.replace(/[ \t]+/g, " ").replace(/\n{3,}/g, "\n\n").trim()
129
- if (!trimmed) return undefined
130
- return trimmed.length > RESULT_SUMMARY_MAX ? trimmed.slice(0, RESULT_SUMMARY_MAX - 1) + "…" : trimmed
131
- }
132
-
133
- interface RunEntry {
134
- runID: string
135
- sessionID: SessionID
136
- status: RunStatus
137
- deferred: Deferred.Deferred<RunOutcome>
138
- fiber: Fiber.Fiber<void> | undefined
139
- childActorIDs: Set<string>
140
- worktrees: Set<string> // worktree directories pending disposition, for cancel cleanup
141
- childRunIDs: Set<string> // child workflow runIDs, for recursive cancel/reclaim
142
- name: string
143
- running: number
144
- succeeded: number
145
- failed: number
146
- agentCount: number
147
- capWarned: boolean
148
- // Model refs already warned about this run, so an unresolvable ref (e.g. a
149
- // workflow using "lite" with no model_groups.lite configured) logs ONCE per
150
- // run instead of once per agent spawn. Per-run, not layer-global, so a later
151
- // run re-warns. See resolveAgentModel.
152
- warnedModelRefs: Set<string>
153
- currentPhase: string | undefined
154
- // Ordered phase/log transcript, appended synchronously by the guest hooks. The
155
- // sync workflow-tool path reads this (via the `transcript` accessor) rather than
156
- // subscribing to the bus, which removes the subscribe-after-start head race, the
157
- // two-PubSub reordering, the post-wait tail race, and the subscription leak.
158
- transcript: WorkflowTranscriptEntry[]
159
- // Observability-only structure nodes (phase/agent/workflow), program-ordered.
160
- structure: WorkflowNode[]
161
- // Id of the phase node current at the time of the next agent()/workflow() call.
162
- currentPhaseId: string | undefined
163
- }
164
-
165
- interface StartInput {
166
- script: string
167
- sessionID: SessionID
168
- parentActorID: string
169
- args?: unknown
170
- model?: { providerID: ProviderID; modelID: ModelID }
171
- maxConcurrentAgents?: number
172
- // Hard ceiling on total agents this run may spawn (lifecycle cap). Defaults to
173
- // MAX_LIFECYCLE_AGENTS (1000). Over-cap agent() calls return null (graceful
174
- // degradation, never-throw), NOT throw — so a fan-out that wants more agents
175
- // than the cap degrades to the cap-limited subset instead of aborting the run.
176
- // Lowerable for tests; tunable in prod.
177
- maxLifecycleAgents?: number
178
- /** Per-agent wall-clock timeout (ms). When an individual agent() call's spawned
179
- * child produces no terminal outcome within this window, it is gracefully
180
- * cancelled and agent() resolves to null (the never-throw failure sentinel), so
181
- * one hung agent (e.g. an LLM TTFT wall) cannot stall a parallel/pipeline barrier
182
- * indefinitely. Default undefined = OFF (only the global scriptDeadlineMs bounds a
183
- * run). A per-call agent(prompt,{timeoutMs}) overrides this. */
184
- agentTimeoutMs?: number
185
- scriptDeadlineMs?: number
186
- // Internal (resume-only): when true, launch ignores any persisted journal and
187
- // truncates the stale `.jsonl` before the run appends. resume() sets this on the
188
- // script-change path (stored script_sha != current script's sha, MR104 P1-2) so
189
- // an EDITED script never replays results journaled against the OLD body. start()
190
- // never sets it (a fresh runID has no prior journal — nothing to invalidate).
191
- freshJournal?: boolean
192
- /** Root dir the guest's file primitives (readFile/writeFile/glob/exists) are
193
- * jailed to. Defaults to the caller's worktree. A child workflow inherits the
194
- * parent's workspace unless its workflow() opts override it. */
195
- workspace?: string
196
- /** Resolved names of ancestor workflows (root = empty). A workflow() whose
197
- * resolved child name is already here is a cycle → throw. */
198
- lineage?: readonly string[]
199
- /** Current nesting depth (root run = 0). */
200
- depth?: number
201
- /** Max nesting depth before workflow() throws. Defaults to config (8). */
202
- maxDepth?: number
203
- /** When the run reaches a terminal state, send an actor_notification to the
204
- * parent's inbox (the legacy fire-and-forget contract). Defaults to true. The
205
- * workflow tool's SYNC path sets this false: it blocks on wait() and returns the
206
- * result as its own tool output, so a parent inbox notification would surface a
207
- * DUPLICATE completion (and duplicate error text) on the next turn. */
208
- notifyOnTerminal?: boolean
209
- }
210
-
211
- /** Options the guest may pass to `agent(prompt, opts?)`. */
212
- interface AgentOpts {
213
- agentType?: string
214
- tools?: readonly string[]
215
- /** A model reference resolved host-side via Provider.resolveModelRef: either a
216
- * "provider/model" literal or a configured tier/group name (e.g. "lite").
217
- * Omitted → the run's default model. Unknown group → falls back to the run
218
- * default (never throws to the guest). */
219
- model?: string
220
- schema?: Record<string, unknown>
221
- isolation?: "worktree"
222
- label?: string
223
- phase?: string
224
- /** Per-call override of the run's agentTimeoutMs (ms). */
225
- timeoutMs?: number
226
- }
227
-
228
- export interface Interface {
229
- readonly start: (input: StartInput) => Effect.Effect<{ runID: string }>
230
- readonly status: (input: {
231
- runID: string
232
- }) => Effect.Effect<{
233
- status: RunStatus | "unknown"
234
- agentCount: number
235
- running: number
236
- succeeded: number
237
- failed: number
238
- currentPhase?: string
239
- }>
240
- readonly wait: (input: { runID: string; timeoutMs?: number }) => Effect.Effect<RunOutcome>
241
- readonly transcript: (input: { runID: string }) => Effect.Effect<readonly WorkflowTranscriptEntry[]>
242
- readonly structure: (input: { runID: string }) => Effect.Effect<WorkflowStructure>
243
- readonly cancel: (input: { runID: string }) => Effect.Effect<void>
244
- readonly list: (input?: { sessionID?: SessionID }) => Effect.Effect<RunSummary[]>
245
- readonly resume: (input: { runID: string; agentTimeoutMs?: number }) => Effect.Effect<{ runID: string; resumed: boolean }>
246
- }
247
-
248
- export class Service extends Context.Service<Service, Interface>()("@opendash/WorkflowRuntime") {}
249
-
250
- /** A plain promise-based semaphore: at most `max` concurrent `run` callbacks. */
251
- function makeSemaphore(max: number) {
252
- let active = 0
253
- const queue: Array<() => void> = []
254
- const release = () => {
255
- active--
256
- const next = queue.shift()
257
- if (next) next()
258
- }
259
- return {
260
- run<T>(fn: () => Promise<T>): Promise<T> {
261
- return new Promise<T>((resolve, reject) => {
262
- const attempt = () => {
263
- active++
264
- fn().then(
265
- (value) => {
266
- release()
267
- resolve(value)
268
- },
269
- (err) => {
270
- release()
271
- reject(err)
272
- },
273
- )
274
- }
275
- if (active < max) attempt()
276
- else queue.push(attempt)
277
- })
278
- },
279
- }
280
- }
281
-
282
- function cpuCount(): number {
283
- const n = os.cpus().length
284
- return n > 0 ? n : 4
285
- }
286
-
287
- export const layer = Layer.effect(
288
- Service,
289
- Effect.gen(function* () {
290
- const bus = yield* Bus.Service
291
- const inbox = yield* Inbox.Service
292
- const worktree = yield* Worktree.Service
293
- const provider = yield* Provider.Service
294
- // Resolve the Config service handle at layer scope (a legitimate layer dep,
295
- // satisfied by Config.defaultLayer) so the requirement is discharged here and
296
- // does NOT leak into start/resume's effect signatures. Only config.get() runs
297
- // lazily below — it reads the per-instance ALS context and returns Effect<Info>
298
- // with no requirement, so it stays out of the public method types.
299
- const config = yield* Config.Service
300
- const scope = yield* Scope.Scope
301
- const runs = new Map<string, RunEntry>()
302
-
303
- // Resolve a guest-supplied model ref (a "provider/model" literal OR a
304
- // tier/group name like "lite") to a concrete {providerID, modelID} via the
305
- // Provider service — host-side, inside the runtime's own Layer scope (so it
306
- // survives resume(), which re-reads the script with no fresh StartInput).
307
- // NEVER throws to the guest: an unknown group (resolveModelRef throwing
308
- // ModelGroupNotFoundError) falls back to the run default, matching agent()'s
309
- // never-throw contract. undefined ref → the run default unchanged.
310
- const resolveAgentModel = (
311
- ref: string | undefined,
312
- fallback: { providerID: ProviderID; modelID: ModelID } | undefined,
313
- warned: Set<string>,
314
- ): Effect.Effect<{ providerID: ProviderID; modelID: ModelID } | undefined> =>
315
- ref === undefined
316
- ? Effect.succeed(fallback)
317
- : provider.resolveModelRef(ref).pipe(
318
- Effect.map((m) => ({ providerID: m.providerID, modelID: m.id })),
319
- Effect.catchCause(() =>
320
- Effect.sync(() => {
321
- // Leave a breadcrumb so a bad ref isn't pure silence: an unknown
322
- // group/tier, a typo, or an out-of-tree script passing the old
323
- // {providerID, modelID} object (not a string) all land here and
324
- // silently use the run default. Warn ONCE per unique ref per run
325
- // (a fan-out like deep-research would otherwise log on every
326
- // agent spawn). For a non-string ref, log its sorted keys (e.g.
327
- // "modelID,providerID") so the operator sees it's the legacy
328
- // object shape — keys are schema names, no user data.
329
- const shown =
330
- typeof ref === "string"
331
- ? ref
332
- : `{${Object.keys(ref as object)
333
- .sort()
334
- .join(",")}}`
335
- if (!warned.has(shown)) {
336
- warned.add(shown)
337
- log.warn("workflow agent model ref did not resolve — using run default", { ref: shown })
338
- }
339
- return fallback
340
- }),
341
- ),
342
- )
343
-
344
- // Process-wide concurrency ceiling: ONE semaphore shared by every run
345
- // (including nested children), so tree-wide concurrent agents can never
346
- // exceed it regardless of nesting depth. It is a PURE process/config property,
347
- // sized SOLELY from config.workflow.maxConcurrentAgents (falling back to the
348
- // min(16, 2×cores) default) — NEVER seeded or raised by any per-launch
349
- // maxConcurrentAgents input. A per-run input only ever NARROWS that run's own
350
- // semaphore (clamped ≤ global, below); it can neither raise the global nor bind
351
- // a later run to an earlier run's cap. Resolved LAZILY on the first launch
352
- // (config.get reads the per-instance ALS context, live inside launch but NOT at
353
- // layer-build time) and memoized at service scope so every subsequent launch() —
354
- // including nested children — shares the same semaphore. `cfg`/`globalMax`/
355
- // `globalSem` are reused by later tasks (T12 maxDepth, T14 maxLifecycleAgents).
356
- let cfg: Config.Info | undefined
357
- let globalMax = 0
358
- let globalSem: ReturnType<typeof makeSemaphore> | undefined
359
- const ensureGlobal = Effect.fn("WorkflowRuntime.ensureGlobal")(function* () {
360
- if (globalSem) return globalSem
361
- // Resolve config once (this is the only suspension point). Cached on `cfg`
362
- // for reuse by later per-run reads (maxDepth, maxLifecycleAgents).
363
- cfg ??= yield* config.get()
364
- globalMax = Math.max(
365
- 1,
366
- cfg.workflow?.maxConcurrentAgents ?? Math.min(DEFAULT_MAX_CONCURRENT, 2 * Math.max(1, cpuCount())),
367
- )
368
- // Assign synchronously with ??= so two concurrent first-launches that both
369
- // passed the guard above (the `config.get()` await is a suspension point)
370
- // converge on ONE semaphore instead of transiently doubling the ceiling.
371
- // Frozen for the process lifetime: a later config change to
372
- // maxConcurrentAgents does NOT rebuild it (acceptable while workflow is
373
- // experimental — the global ceiling is a process/config property).
374
- globalSem ??= makeSemaphore(globalMax)
375
- return globalSem
376
- })
377
-
378
- // Debounced counter flush: coalesce high-rate running/succeeded/failed updates
379
- // to at most one DB write per ~250ms per run. flushNow is the synchronous final
380
- // flush on terminal. All best-effort.
381
- const flushTimers = new Map<string, ReturnType<typeof setTimeout>>()
382
- const flushNow = (entry: RunEntry) => {
383
- const t = flushTimers.get(entry.runID)
384
- if (t) {
385
- clearTimeout(t)
386
- flushTimers.delete(entry.runID)
387
- }
388
- return WorkflowPersistence.flushCounters({
389
- runID: entry.runID,
390
- running: entry.running,
391
- succeeded: entry.succeeded,
392
- failed: entry.failed,
393
- }).pipe(Effect.ignore)
394
- }
395
- const scheduleFlush = (entry: RunEntry) => {
396
- if (flushTimers.has(entry.runID)) return
397
- flushTimers.set(
398
- entry.runID,
399
- setTimeout(() => {
400
- flushTimers.delete(entry.runID)
401
- Effect.runFork(
402
- WorkflowPersistence.flushCounters({
403
- runID: entry.runID,
404
- running: entry.running,
405
- succeeded: entry.succeeded,
406
- failed: entry.failed,
407
- }).pipe(Effect.ignore),
408
- )
409
- }, 250),
410
- )
411
- }
412
-
413
- // Best-effort cleanup for a NON-SUCCESS terminal (cancel, deadline, script
414
- // failure): graceful-cancel any in-flight child agents and remove every
415
- // worktree the run still owns, then clear the set. NEVER throws — a reclaim
416
- // failure must not mask the original terminal cause. NOT called on success:
417
- // kept (success+changed) worktrees are the deliverable and must survive.
418
- const reclaim = (entry: RunEntry) =>
419
- Effect.gen(function* () {
420
- const actor = spawnRef.current
421
- if (actor) {
422
- yield* Effect.forEach(
423
- [...entry.childActorIDs],
424
- (childID) => actor.cancel(entry.sessionID, childID, "graceful").pipe(Effect.ignore),
425
- { concurrency: "unbounded", discard: true },
426
- )
427
- }
428
- yield* Effect.forEach(
429
- [...entry.worktrees],
430
- (directory) => worktree.remove({ directory }).pipe(Effect.ignore),
431
- { concurrency: "unbounded", discard: true },
432
- )
433
- entry.worktrees.clear()
434
- // Recurse into child workflow RUNS (populated by workflow()). Cancelling the
435
- // orchestrator tears down the whole tree — a child still "running" here is
436
- // cancelled via cancelEntry (mutually recursive with reclaim).
437
- // SAFETY: childRunIDs edges are parent→child only (added solely at the
438
- // workflow() call site with a freshly-minted child runID), so the graph is a
439
- // tree and this recursion is finite. The status-flip guard alone does NOT stop
440
- // a cycle (a node's flip is post-order, after its reclaim returns), so
441
- // acyclicity is load-bearing — the workflow() cycle guard (Task 12) is what
442
- // keeps it true as the call graph grows.
443
- yield* Effect.forEach(
444
- [...entry.childRunIDs],
445
- (childRunID) =>
446
- Effect.gen(function* () {
447
- const child = runs.get(childRunID)
448
- if (child && child.status === "running") yield* cancelEntry(child)
449
- }).pipe(Effect.ignore),
450
- { concurrency: "unbounded", discard: true },
451
- )
452
- })
453
-
454
- const cancelEntry = (entry: RunEntry): Effect.Effect<void> =>
455
- Effect.gen(function* () {
456
- if (entry.status !== "running") return
457
- yield* reclaim(entry)
458
- yield* flushNow(entry)
459
- yield* WorkflowPersistence.recordTerminal({ runID: entry.runID, status: "cancelled" }).pipe(Effect.ignore)
460
- if (entry.fiber) yield* Fiber.interrupt(entry.fiber)
461
- entry.status = "cancelled"
462
- yield* Deferred.succeed(entry.deferred, { status: "cancelled" })
463
- yield* bus.publish(WorkflowFinished, { sessionID: entry.sessionID, runID: entry.runID, status: "cancelled" })
464
- })
465
-
466
- const waitFor = (childRunID: string) =>
467
- Effect.gen(function* () {
468
- const child = runs.get(childRunID)
469
- if (!child) return { status: "failed" as const, error: "child run missing" }
470
- return yield* Deferred.await(child.deferred)
471
- })
472
-
473
- const launch = Effect.fn("WorkflowRuntime.launch")(function* (input: StartInput, runID: string, name: string) {
474
- // The guest body is the script with the `meta` literal blanked out (parseMeta
475
- // preserves line numbers). start already validated meta and resume only loads
476
- // a previously-validated script, so this parse is purely to extract the body;
477
- // it never gates here. Fall back to the raw script if parse somehow fails.
478
- const parsed = parseMeta(input.script)
479
- const body = parsed.ok ? parsed.body : input.script
480
- // Resolve the workspace root ONCE at launch (the Instance ALS context is
481
- // live here — the bridge below captures it). Default = the caller's
482
- // worktree. Captured in the closure so the file hooks read it synchronously
483
- // and never touch ALS from inside the forked work fiber.
484
- const workspaceRoot = input.workspace ?? Instance.worktree
485
- const fileHooks = makeFileHooks(workspaceRoot)
486
- const deferred = yield* Deferred.make<RunOutcome>()
487
- const entry: RunEntry = {
488
- runID,
489
- sessionID: input.sessionID,
490
- status: "running",
491
- deferred,
492
- fiber: undefined,
493
- childActorIDs: new Set<string>(),
494
- worktrees: new Set<string>(),
495
- childRunIDs: new Set<string>(),
496
- name,
497
- running: 0,
498
- succeeded: 0,
499
- failed: 0,
500
- agentCount: 0,
501
- capWarned: false,
502
- warnedModelRefs: new Set<string>(),
503
- currentPhase: undefined,
504
- transcript: [],
505
- structure: [],
506
- currentPhaseId: undefined,
507
- }
508
- runs.set(runID, entry)
509
- // Stamp a sha256 of the FULL script body (the exact bytes writeScript persists
510
- // and resume's readScript reads back), so resume can detect a between-cycle
511
- // edit by comparing this to the current file's sha — apples-to-apples, MR104
512
- // P1-2. recordStart re-stamps it on every (re)launch, so a changed-script
513
- // relaunch overwrites the stale sha and a subsequent resume replays correctly.
514
- const scriptSha = createHash("sha256").update(input.script).digest("hex")
515
- yield* WorkflowPersistence.recordStart({
516
- runID,
517
- sessionID: input.sessionID,
518
- name,
519
- parentActorID: input.parentActorID,
520
- args: input.args,
521
- scriptSha,
522
- agentTimeoutMs: input.agentTimeoutMs,
523
- }).pipe(Effect.ignore)
524
- yield* WorkflowPersistence.writeScript(runID, input.script).pipe(Effect.ignore)
525
-
526
- // Replay journal: prior agent() results (empty on a fresh run). On resume,
527
- // a cache hit returns instantly with no spawn; misses spawn + append. The
528
- // occ counter disambiguates byte-identical calls into distinct slots.
529
- // freshJournal (resume's script-change path) truncates the stale `.jsonl`
530
- // FIRST so loadJournal returns empty AND the run's appends don't interleave
531
- // with results journaled against the old script body — a later resume would
532
- // otherwise read both and replay the wrong results.
533
- if (input.freshJournal) yield* WorkflowPersistence.clearJournal(runID).pipe(Effect.ignore)
534
- const journal = yield* WorkflowPersistence.loadJournal(runID)
535
- const occ = new Map<string, number>()
536
- const pass = journal.pass
537
-
538
- // Capture the bridge BEFORE forking so it snapshots the caller's
539
- // Instance/Workspace context — the quickjs Promise boundary in agent()
540
- // would otherwise lose it.
541
- const bridge = yield* EffectBridge.make()
542
-
543
- // Resolve the process-wide ceiling NOW (under the live Instance context) so
544
- // its semaphore object exists before any spawn site closes over it. Sized
545
- // PURELY from config (memoized after the first launch); a per-launch
546
- // maxConcurrentAgents never seeds or raises it — it only narrows this run's
547
- // own semaphore below.
548
- const globalSemLocal = yield* ensureGlobal()
549
- // Nesting safety (T12): carried through every run. lineage = resolved names of
550
- // ancestor workflows (root = empty); depth = this run's level (root = 0). A
551
- // workflow() whose child name is already in lineage is a cycle, and a child
552
- // beyond maxDepth is over-deep — both throw at the call site (workflowHook).
553
- // maxDepth precedence: explicit per-run input > config > module default 8.
554
- const lineage = input.lineage ?? []
555
- const depth = input.depth ?? 0
556
- const maxDepth = input.maxDepth ?? cfg?.workflow?.maxDepth ?? 8
557
- // Per-run soft cap: defaults to the global ceiling, clamped to ≤ global so a
558
- // child can shrink its own concurrency but never exceed the process ceiling.
559
- // The 2×cores clamp is GONE — the global semaphore is the real throttle.
560
- const requested = input.maxConcurrentAgents ?? globalMax
561
- const max = Math.max(1, Math.min(requested, globalMax))
562
- const sem = makeSemaphore(max)
563
- // Lifecycle cap (total agents over the run's life). Resolved once here so
564
- // both spawn paths (shared + isolated) share it; over-cap calls return null.
565
- const lifecycleCap = input.maxLifecycleAgents ?? cfg?.workflow?.maxLifecycleAgents ?? MAX_LIFECYCLE_AGENTS
566
- // Over-cap → null (see maxLifecycleAgents doc): warn ONCE per run so the
567
- // dropped work is visible without spamming a log line per over-cap call.
568
- const warnCapOnce = () => {
569
- if (entry.capWarned) return
570
- entry.capWarned = true
571
- log.warn("workflow lifecycle agent cap reached — over-cap agents return null", {
572
- runID,
573
- cap: lifecycleCap,
574
- })
575
- }
576
- // Per-agent wall-clock timeout. Run-level default (OFF unless set); a per-call
577
- // opts.timeoutMs overrides it. Resolved per agent() call since opts is per-call.
578
- const runAgentTimeoutMs = input.agentTimeoutMs
579
- // Race a child's outcome-await against the effective per-agent timeout. On a
580
- // TRUE timeout: gracefully cancel that one child (the lever reclaim uses) and
581
- // yield null — the never-throw sentinel the guest already tolerates, so a hung
582
- // agent can't stall a parallel/pipeline barrier. A genuine null deliverable
583
- // (agent failed fast) is NOT a timeout → no cancel. No timeout configured
584
- // (undefined / <=0) ⇒ await unbounded (current behavior, only scriptDeadline bounds).
585
- const awaitWithTimeout = <A>(
586
- actorID: string,
587
- opts: AgentOpts,
588
- await_: Effect.Effect<A | null>,
589
- // Optional side-channel: set when the timeout branch wins, so the caller
590
- // can distinguish a TRUE timeout (reason="timeout") from a fast actor-error
591
- // null. Never throws; called once at most. Pure observability.
592
- onTimeout?: () => void,
593
- ) => {
594
- const ms = opts.timeoutMs ?? runAgentTimeoutMs
595
- if (!ms || ms <= 0) return await_
596
- return Effect.raceFirst(
597
- await_,
598
- Effect.sleep(`${ms} millis`).pipe(Effect.as(STRAGGLER_TIMEOUT as unknown as A | null)),
599
- ).pipe(
600
- Effect.flatMap((r) =>
601
- r === (STRAGGLER_TIMEOUT as unknown)
602
- ? (spawnRef.current
603
- ? spawnRef.current.cancel(input.sessionID, actorID, "graceful").pipe(Effect.ignore)
604
- : Effect.void
605
- ).pipe(
606
- Effect.tap(() =>
607
- Effect.sync(() => {
608
- try {
609
- onTimeout?.()
610
- } catch {
611
- /* observability must never escape */
612
- }
613
- }),
614
- ),
615
- Effect.as(null),
616
- )
617
- : Effect.succeed(r),
618
- ),
619
- )
620
- }
621
-
622
- // Publish a WorkflowAgentFailed event for an agent() call that resolved to
623
- // null. Pure observability — counters and the agent() return value are
624
- // unaffected. Wrapped in try/catch so a bus problem can never break a run.
625
- type FailReason = "over-cap" | "spawn-reject" | "timeout" | "actor-error" | "no-deliverable"
626
- const publishAgentFailed = (
627
- o: AgentOpts,
628
- reason: FailReason,
629
- info: { actorID?: string; errorMessage?: string } = {},
630
- ) => {
631
- try {
632
- Effect.runFork(
633
- bus
634
- .publish(WorkflowAgentFailed, {
635
- sessionID: input.sessionID,
636
- runID,
637
- actorID: info.actorID,
638
- agentType: o.agentType ?? "general",
639
- label: o.label,
640
- phase: o.phase ?? entry.currentPhase,
641
- reason,
642
- errorMessage: info.errorMessage,
643
- })
644
- .pipe(Effect.ignore),
645
- )
646
- } catch {
647
- /* observability must never escape */
648
- }
649
- }
650
-
651
- yield* bus.publish(WorkflowStarted, { sessionID: input.sessionID, runID, name })
652
-
653
- // Observability-only spawn description from label/phase: "[Phase] label",
654
- // or just one of them, or undefined (then spawn falls back to agentType —
655
- // see spawn.ts `input.description ?? input.agentType`). label/phase NEVER
656
- // touch currentPhase/counters/schema — they are purely the per-agent tag
657
- // the actor registry stores and the /workflows view surfaces.
658
- const spawnDescription = (o: AgentOpts) =>
659
- o.label ? (o.phase ? `[${o.phase}] ${o.label}` : o.label) : o.phase ? `[${o.phase}]` : undefined
660
-
661
- // Shared-tree spawn (default): the existing behavior. SUBAGENT mode — the
662
- // worker shares the run's parent session (cheaper, no per-agent session).
663
- // Safe since lastAssistant is agent-scoped (fix 59597264): each subagent's
664
- // result is extracted by its own agentID, so concurrent same-session
665
- // subagents don't cross-contaminate. context:"none" keeps each worker free
666
- // of parent history (parallel fan-out is the use case). NEVER throw to the
667
- // guest for spawn/turn failures — resolve to null so the script continues.
668
- const spawnShared = async (
669
- actor: NonNullable<typeof spawnRef.current>,
670
- prompt: string,
671
- o: AgentOpts,
672
- resolvedModel: { providerID: ProviderID; modelID: ModelID } | undefined,
673
- onActorID?: (id: string) => void,
674
- ) => {
675
- // COUNTER INVARIANT: running++ exactly once BEFORE the spawn attempt, and
676
- // running-- + (succeeded XOR failed)++ exactly once AFTER it settles. The
677
- // bookkeeping lives OUTSIDE the bridge so it still runs when the bridge
678
- // result is the spawn-reject sentinel (null). Counters settle on whether a
679
- // DELIVERABLE was produced (value !== null) — the exact thing the guest
680
- // observes. An agent whose turn errored finishes with status:"success" but
681
- // no finalText/structured, so its deliverable is null and the guest sees a
682
- // failure; the counter must agree. A spawn reject also yields null → failed.
683
- entry.running++
684
- scheduleFlush(entry)
685
- // Failure-reason refs: defaults to "actor-error" (the broad catch-all) and
686
- // is narrowed at known branch points. Read once at the end, on null return,
687
- // to publish WorkflowAgentFailed. agent()'s null contract is unchanged.
688
- let reason: FailReason = "actor-error"
689
- let actorID: string | undefined
690
- let errorMessage: string | undefined
691
- const value = await bridge
692
- .promise(
693
- Effect.gen(function* () {
694
- const spawned = yield* actor.spawn({
695
- mode: "subagent",
696
- sessionID: input.sessionID,
697
- agentType: o.agentType ?? "general",
698
- description: spawnDescription(o),
699
- task: prompt,
700
- context: "none",
701
- tools: o.tools ? [...o.tools] : "INHERIT",
702
- background: true,
703
- parentActorID: input.parentActorID,
704
- model: resolvedModel,
705
- // Register the child in the reclaim set the instant the actor
706
- // exists — synchronously inside the spawn Effect, BEFORE its work
707
- // fiber detaches. A cancel racing this spawn would otherwise miss
708
- // it (the child runs detached in the actor scope, so interrupting
709
- // the workflow fiber can't stop it) and leak an orphan. MR104 #2.
710
- onActorID: (id) => {
711
- entry.childActorIDs.add(id)
712
- onActorID?.(id)
713
- },
714
- ...(o.schema ? { format: { type: "json_schema" as const, schema: o.schema, retryCount: 2 } } : {}),
715
- })
716
- actorID = spawned.actorID
717
- // Bound the outcome-await by the per-agent timeout: a hung child times
718
- // out to null (and is cancelled) rather than stalling the barrier. The
719
- // deliverable is computed inside the awaited Effect so the timeout wraps
720
- // the whole await→extract. schema requested ⇒ structured ?? null (never
721
- // prose finalText: prose breaks `r.fields`-style scripts + our pipeline).
722
- const deliverable = yield* awaitWithTimeout(
723
- spawned.actorID,
724
- o,
725
- Deferred.await(spawned.outcome).pipe(
726
- Effect.map((outcome) => {
727
- if (outcome.status !== "success") {
728
- reason = "actor-error"
729
- errorMessage = (outcome as { error?: string }).error
730
- return null
731
- }
732
- const v = o.schema
733
- ? (outcome.structured ?? null)
734
- : (outcome.structured ?? outcome.finalText ?? null)
735
- if (v === null) reason = "no-deliverable"
736
- return v
737
- }),
738
- ),
739
- () => {
740
- reason = "timeout"
741
- },
742
- )
743
- entry.childActorIDs.delete(spawned.actorID)
744
- return deliverable
745
- }),
746
- )
747
- .catch((e) => {
748
- reason = "spawn-reject"
749
- errorMessage = e instanceof Error ? e.message : String(e)
750
- return null
751
- })
752
- entry.running--
753
- if (value !== null) entry.succeeded++
754
- else {
755
- entry.failed++
756
- publishAgentFailed(o, reason, { actorID, errorMessage })
757
- }
758
- scheduleFlush(entry)
759
- return value
760
- }
761
-
762
- // Isolated spawn: fresh worktree, file tools rebound to it via Instance.provide.
763
- const spawnIsolated = async (
764
- actor: NonNullable<typeof spawnRef.current>,
765
- prompt: string,
766
- o: AgentOpts,
767
- resolvedModel: { providerID: ProviderID; modelID: ModelID } | undefined,
768
- onActorID?: (id: string) => void,
769
- ) => {
770
- // Failure-reason refs (parallel to spawnShared); see there for rationale.
771
- let reason: FailReason = "actor-error"
772
- let actorIDOut: string | undefined
773
- let errorMessage: string | undefined
774
- // 1) Create + fully populate a worktree (createFromInfo awaits boot).
775
- const info = await bridge
776
- .promise(
777
- Effect.gen(function* () {
778
- const i = yield* worktree.makeWorktreeInfo()
779
- yield* worktree.createFromInfo(i)
780
- return i
781
- }),
782
- )
783
- .catch((e) => {
784
- errorMessage = e instanceof Error ? e.message : String(e)
785
- return null
786
- })
787
- if (!info) {
788
- publishAgentFailed(o, "spawn-reject", { errorMessage })
789
- return null
790
- }
791
- // Register the worktree for cleanup the moment it exists on disk — BEFORE
792
- // the spawn attempt. If spawn rejects or the agent fails, cancel-cleanup
793
- // (and the disposition below) can still reclaim it; nothing orphans.
794
- entry.worktrees.add(info.directory)
795
- const base = await bridge.promise(worktree.head(info.directory)).catch(() => "")
796
- // 2) A bridge bound to the worktree's InstanceContext: provide InstanceRef =
797
- // worktree ctx so Effect-side reads resolve there; the Instance.provide
798
- // wrap below covers raw-ALS tool reads (the load-bearing part). The outer
799
- // Instance.provide is what reroutes the agent's file tools; wtBridge is
800
- // defense-in-depth for any Effect-side InstanceRef read during dispatch.
801
- const wtCtx = await Instance.provide({
802
- directory: info.directory,
803
- fn: () => Promise.resolve(Instance.current),
804
- })
805
- const wtBridge = await bridge.promise(EffectBridge.make().pipe(Effect.provideService(InstanceRef, wtCtx)))
806
- // 3) Spawn + await INSIDE Instance.provide({worktree}) — AsyncLocalStorage
807
- // propagates the worktree dir across the actor's forked work fiber, so the
808
- // agent's read/write/bash resolve to the worktree, not the parent tree.
809
- // COUNTER INVARIANT (isolated path): running++ here, BEFORE the spawn
810
- // attempt, so it pairs with the settle below regardless of spawn-reject
811
- // (spawned === null). The settle (running-- + succeeded/failed++) runs once
812
- // on every disposition path after `succeeded` is known.
813
- entry.running++
814
- scheduleFlush(entry)
815
- const spawned = await Instance.provide({
816
- directory: info.directory,
817
- fn: () =>
818
- wtBridge
819
- .promise(
820
- Effect.gen(function* () {
821
- const s = yield* actor.spawn({
822
- mode: "subagent",
823
- sessionID: input.sessionID,
824
- agentType: o.agentType ?? "general",
825
- description: spawnDescription(o),
826
- task: prompt,
827
- context: "none",
828
- tools: o.tools ? [...o.tools] : "INHERIT",
829
- background: true,
830
- parentActorID: input.parentActorID,
831
- model: resolvedModel,
832
- // Same MR104 #2 fix as spawnShared: register the child in the
833
- // reclaim set synchronously inside the spawn Effect, before its
834
- // work fiber detaches, so a racing cancel never orphans it.
835
- onActorID: (id) => {
836
- entry.childActorIDs.add(id)
837
- onActorID?.(id)
838
- },
839
- ...(o.schema ? { format: { type: "json_schema" as const, schema: o.schema, retryCount: 2 } } : {}),
840
- })
841
- actorIDOut = s.actorID
842
- // Bound the await by the per-agent timeout. On timeout the helper
843
- // cancels the child and yields null; we surface that as a null
844
- // `spawned` so the disposition below takes the same path as a
845
- // spawn-reject/failure (worktree reclaimed, value null, failed++) —
846
- // a hung isolated agent can't stall the barrier or leak a worktree.
847
- const outcome = yield* awaitWithTimeout(s.actorID, o, Deferred.await(s.outcome), () => {
848
- reason = "timeout"
849
- })
850
- entry.childActorIDs.delete(s.actorID)
851
- if (outcome === null) return null
852
- if (outcome.status !== "success") {
853
- reason = "actor-error"
854
- errorMessage = (outcome as { error?: string }).error
855
- }
856
- return { actorID: s.actorID, outcome }
857
- }),
858
- )
859
- .catch((e) => {
860
- reason = "spawn-reject"
861
- errorMessage = e instanceof Error ? e.message : String(e)
862
- return null
863
- }),
864
- }).catch((e) => {
865
- reason = "spawn-reject"
866
- errorMessage = e instanceof Error ? e.message : String(e)
867
- return null
868
- })
869
- // 4) Disposition. KEEP the worktree only when the agent SUCCEEDED and left
870
- // changes (the deliverable, surfaced via _worktree). In every other case
871
- // — pristine (untouched), spawn rejected, or agent failed/cancelled —
872
- // remove it so nothing leaks on disk. Guard: an empty base means head()
873
- // failed at create time; treat as CHANGED (never trust an unreliable
874
- // pristine check to authorize a delete).
875
- const succeeded = !!spawned && spawned.outcome.status === "success"
876
- // Settle the counter once here — after `succeeded` is known and before any
877
- // disposition branch — so it runs exactly once on every path (spawn-reject
878
- // → spawned===null → failed++, keep, remove). Pairs with the running++ above.
879
- // We REUSE the existing `succeeded` discriminant (read-only; the worktree
880
- // disposition below owns it) rather than the returned deliverable: in the
881
- // isolated path a successful agent's work is its worktree, so a status
882
- // success is a success even when it returned no text.
883
- entry.running--
884
- if (succeeded) entry.succeeded++
885
- else {
886
- entry.failed++
887
- publishAgentFailed(o, reason, { actorID: actorIDOut, errorMessage })
888
- }
889
- scheduleFlush(entry)
890
- // The success deliverable. When a schema was requested it MUST be the
891
- // validated structured object — never prose finalText (see the shared-spawn
892
- // path above for why: prose breaks `r.fields`-style scripts + our pipeline
893
- // null-injection). schema requested ⇒ structured ?? null.
894
- const value =
895
- spawned && spawned.outcome.status === "success"
896
- ? o.schema
897
- ? (spawned.outcome.structured ?? null)
898
- : (spawned.outcome.structured ?? spawned.outcome.finalText ?? null)
899
- : null
900
- const pristine =
901
- base !== "" && (await bridge.promise(worktree.isPristine(info.directory, base)).catch(() => false))
902
- const keep = succeeded && !pristine
903
- if (!keep) {
904
- await bridge.promise(worktree.remove({ directory: info.directory })).catch(() => undefined)
905
- entry.worktrees.delete(info.directory)
906
- return succeeded ? value : null
907
- }
908
- // keep: the worktree stays on disk and tracked until an integrate step or
909
- // cancel reclaims it; surface its branch so the script can act on it.
910
- const wt = { branch: info.branch, directory: info.directory, changed: true }
911
- if (value && typeof value === "object" && !Array.isArray(value)) return { ...(value as object), _worktree: wt }
912
- return { _worktree: wt, result: value }
913
- }
914
-
915
- // Per-call start times (host wall-clock) for the observability nodes' durationMs.
916
- // Host-side only — never read by the guest, so it doesn't affect determinism/replay.
917
- const nodeStart = new Map<string, number>()
918
- const agentImpl = (prompt: unknown, opts?: unknown, nodeId?: string) => {
919
- const o = (opts ?? {}) as AgentOpts
920
- const promptStr = String(prompt)
921
- // Flip the observability node (if any) recorded by the `agent` wrapper for
922
- // THIS call. Called at the same points that bump succeeded/failed counters.
923
- // `result` is the agent's deliverable (string / structured object / null);
924
- // we stash a short summary on the node so the tree shows what it produced.
925
- const markAgentNode = (status: "succeeded" | "failed", result?: unknown, actorID?: string) => {
926
- if (!nodeId) return
927
- const node = entry.structure.find((n) => n.id === nodeId)
928
- if (node && node.type === "agent") {
929
- node.status = status
930
- const start = nodeStart.get(nodeId)
931
- if (start !== undefined) node.durationMs = Date.now() - start
932
- if (actorID && node.actorID === undefined) node.actorID = actorID
933
- const summary = summarizeAgentResult(result)
934
- if (summary !== undefined) node.resultSummary = summary
935
- }
936
- }
937
- // Fill the node's actorID the instant the child actor is minted (BEFORE it
938
- // settles), so the TUI can offer "open this agent" while it's still running.
939
- const setActorID = (actorID: string) => {
940
- if (!nodeId) return
941
- const node = entry.structure.find((n) => n.id === nodeId)
942
- if (node && node.type === "agent" && node.actorID === undefined) node.actorID = actorID
943
- }
944
- // Isolated agents are never journaled in v1 (their deliverable is a
945
- // worktree the journal can't reconstruct) — always spawn.
946
- if (o.isolation !== "worktree") {
947
- const base = journalKeyBase(promptStr, {
948
- agentType: o.agentType,
949
- model: o.model,
950
- schema: o.schema,
951
- phase: o.phase,
952
- })
953
- const n = occ.get(base) ?? 0
954
- occ.set(base, n + 1)
955
- const key = base + ":" + n
956
- if (journal.results.has(key)) {
957
- // Cache hit: no spawn, no agentCount increment (would hit the 1000
958
- // cap on replays alone). Outcome counter DOES climb so the live view
959
- // reflects reality as replay proceeds.
960
- entry.succeeded++
961
- markAgentNode("succeeded", journal.results.get(key))
962
- scheduleFlush(entry)
963
- return Promise.resolve(journal.results.get(key))
964
- }
965
- return (async () => {
966
- // Spawn UNDER the semaphore (governs concurrency). The journal append
967
- // happens AFTER the slot is released, so file IO never holds a slot.
968
- const result = await sem.run(async () =>
969
- globalSemLocal.run(async () => {
970
- if (entry.agentCount >= lifecycleCap) {
971
- warnCapOnce()
972
- publishAgentFailed(o, "over-cap")
973
- return null
974
- }
975
- entry.agentCount++
976
- const actor = spawnRef.current
977
- if (!actor) throw new Error("Actor service unavailable")
978
- // Resolve the guest's model ref host-side AFTER the journal key was
979
- // computed above (the key hashes the raw `o.model` ref, NOT the
980
- // resolved struct, so resume keys stay stable across config changes).
981
- // Never-throws: an unknown group falls back to input.model.
982
- const resolvedModel = await bridge.promise(resolveAgentModel(o.model, input.model, entry.warnedModelRefs))
983
- return spawnShared(actor, promptStr, o, resolvedModel, setActorID)
984
- }),
985
- )
986
- markAgentNode(result === null ? "failed" : "succeeded", result)
987
- // Cache successful results only (null = failure/spawn-reject/killed →
988
- // not journaled → re-runs on resume, self-heal). SYNCHRONOUS append so
989
- // the result is durable the instant it resolves: a mid-run process exit
990
- // / SIGKILL / deadline leaves a journal with every completed agent, which
991
- // is the whole point of resume. A sync write (unlike an awaited async
992
- // Effect.promise(fs)) does NOT starve the quickjs sandbox pump — verified.
993
- // Effect.ignore'd so a write failure can't break the agent.
994
- if (result !== null) {
995
- await Effect.runPromise(
996
- WorkflowPersistence.appendJournalSync(runID, [{ t: "agent", key, result, pass }]).pipe(Effect.ignore),
997
- )
998
- }
999
- return result
1000
- })()
1001
- }
1002
- return sem.run(async () =>
1003
- globalSemLocal.run(async () => {
1004
- if (entry.agentCount >= lifecycleCap) {
1005
- warnCapOnce()
1006
- publishAgentFailed(o, "over-cap")
1007
- markAgentNode("failed")
1008
- return null
1009
- }
1010
- entry.agentCount++
1011
- const actor = spawnRef.current
1012
- if (!actor) throw new Error("Actor service unavailable")
1013
- // Resolve the guest's model ref host-side (isolated agents aren't
1014
- // journaled, so there's no key to keep stable here). Never-throws.
1015
- const resolvedModel = await bridge.promise(resolveAgentModel(o.model, input.model, entry.warnedModelRefs))
1016
- const value = await spawnIsolated(actor, promptStr, o, resolvedModel, setActorID)
1017
- markAgentNode(value === null ? "failed" : "succeeded", value)
1018
- return value
1019
- }),
1020
- )
1021
- }
1022
-
1023
- // Observability: record a structure node at agent() call time, attributed to
1024
- // the current phase. Status starts "running" and is flipped to succeeded/failed
1025
- // at the SAME sites that bump the succeeded/failed counters (markAgentNode),
1026
- // keyed by this node id. We deliberately do NOT wrap or tap the returned host
1027
- // promise: the sandbox's asyncify-free sync-promise bridge counts pending jobs
1028
- // to drive its pump, so an extra Promise.resolve().then() perturbs settle timing
1029
- // and corrupts counters. The hook returns the host promise untouched.
1030
- const agent: HostFn = (prompt: unknown, opts?: unknown) => {
1031
- const o = (opts ?? {}) as AgentOpts
1032
- const nodeId = "a" + entry.structure.length
1033
- entry.structure.push({
1034
- type: "agent",
1035
- id: nodeId,
1036
- phaseId: entry.currentPhaseId,
1037
- label: o.label,
1038
- agentType: o.agentType ?? "general",
1039
- prompt: String(prompt),
1040
- ...(o.model !== undefined ? { model: o.model } : {}),
1041
- ...(o.tools ? { tools: [...o.tools] } : {}),
1042
- ...(o.schema ? { schema: true } : {}),
1043
- ...(o.isolation === "worktree" ? { isolation: true } : {}),
1044
- status: "running",
1045
- })
1046
- nodeStart.set(nodeId, Date.now())
1047
- return agentImpl(prompt, opts, nodeId)
1048
- }
1049
-
1050
- const phase: HostFn = (title: unknown) => {
1051
- entry.currentPhase = String(title)
1052
- entry.transcript.push({ kind: "phase", text: String(title) })
1053
- const phaseId = "p" + entry.structure.length
1054
- entry.structure.push({ type: "phase", id: phaseId, title: String(title) })
1055
- entry.currentPhaseId = phaseId
1056
- Effect.runFork(WorkflowPersistence.recordPhase({ runID, phase: String(title) }).pipe(Effect.ignore))
1057
- Effect.runFork(WorkflowPersistence.appendJournal(runID, { t: "phase", title: String(title), pass }).pipe(Effect.ignore))
1058
- Effect.runFork(bus.publish(WorkflowPhase, { sessionID: input.sessionID, runID, title: String(title) }))
1059
- return undefined
1060
- }
1061
-
1062
- const logHook: HostFn = (message: unknown) => {
1063
- entry.transcript.push({ kind: "log", text: String(message) })
1064
- Effect.runFork(WorkflowPersistence.appendJournal(runID, { t: "log", msg: String(message), pass }).pipe(Effect.ignore))
1065
- Effect.runFork(bus.publish(WorkflowLog, { sessionID: input.sessionID, runID, message: String(message) }))
1066
- return undefined
1067
- }
1068
-
1069
- // workflow(nameOrScript, args?, opts?) — schedule a CHILD workflow as its
1070
- // own independent sub-run, awaited inline. Mirrors agent()→Actor.spawn one
1071
- // level up: mint a deterministic child runID (stable across resume so the
1072
- // parent journal can find the child), resolve name→script, launch it, await
1073
- // its RunOutcome. A child that fails resolves to null (never-throw, like
1074
- // agent()) so parallel/pipeline over children degrade gracefully. An unknown
1075
- // name THROWS (Effect.die → the guest call rejects → the run fails loud).
1076
- const workflowOcc = new Map<string, number>()
1077
- const workflowHook: HostFn = (nameOrScript: unknown, childArgs?: unknown, opts?: unknown) => {
1078
- const spec = String(nameOrScript)
1079
- const o = (opts ?? {}) as { workspace?: string; maxConcurrentAgents?: number }
1080
- // Content key over the SEMANTIC inputs that reach the child (spec + args).
1081
- // occ disambiguates byte-identical workflow() calls into distinct slots.
1082
- const base = createHash("sha256")
1083
- .update(JSON.stringify({ spec, args: childArgs ?? null }))
1084
- .digest("hex")
1085
- const n = workflowOcc.get(base) ?? 0
1086
- workflowOcc.set(base, n + 1)
1087
- const key = base + ":" + n
1088
- // Parent-journal hit: a completed child replays its result with NO relaunch
1089
- // (the two-level resume short-circuit — parent journal skips the whole child
1090
- // sub-run; the child's own journal would handle agent-level skip if it were
1091
- // re-run). Counts as a succeeded outcome so the live view reflects replay
1092
- // progress. The "wf:" prefix keeps this slot namespace disjoint from agent() keys.
1093
- if (journal.results.has("wf:" + key)) {
1094
- entry.succeeded++
1095
- scheduleFlush(entry)
1096
- return Promise.resolve(journal.results.get("wf:" + key))
1097
- }
1098
- const childRunID = "wf_" + createHash("sha256").update(runID + key).digest("hex")
1099
- return bridge.promise(
1100
- Effect.gen(function* () {
1101
- const childScript = isInlineScript(spec)
1102
- ? spec
1103
- : yield* Effect.promise(() => resolveWorkflowScript(spec, workspaceRoot, Instance.worktree))
1104
- if (childScript === null)
1105
- return yield* Effect.die(new Error(`${WORKFLOW_STRUCTURAL_ERROR}: unknown workflow: ${JSON.stringify(spec)}`))
1106
- // Nesting guards (T12) — LAUNCH path only (a journal HIT early-returned
1107
- // above without deriving childName/childRunID, and a cached child already
1108
- // completed in a prior pass, so re-validating would be wrong). The child's
1109
- // lineage name is its resolved saved name, or a content-hash label for an
1110
- // inline body so distinct inline children don't collide AND an inline body
1111
- // that re-invokes itself is still caught as a cycle. Over-depth and cycle
1112
- // are SCRIPT-LOGIC errors → Effect.die (fail loud), same posture as the
1113
- // unknown-name die above. The guest await rejects → the orchestrator script
1114
- // throws → the parent run fails with this message.
1115
- // NOTE: saved names key on the name alone (args-independent), so saved
1116
- // A→A with different args IS a cycle; an inline body keys on its content
1117
- // hash WHICH INCLUDES args, so inline A→A with different args is NOT a
1118
- // cycle and is bounded only by maxDepth.
1119
- const childName = isInlineScript(spec) ? "inline:" + base.slice(0, 12) : spec
1120
- if (depth + 1 > maxDepth) {
1121
- return yield* Effect.die(new Error(`${WORKFLOW_STRUCTURAL_ERROR}: workflow nesting exceeds maxDepth (${maxDepth})`))
1122
- }
1123
- if (lineage.includes(childName)) {
1124
- return yield* Effect.die(
1125
- new Error(`${WORKFLOW_STRUCTURAL_ERROR}: workflow cycle detected: ${childName} is already an ancestor`),
1126
- )
1127
- }
1128
- entry.childRunIDs.add(childRunID)
1129
- const wfNodeId = "w" + entry.structure.length
1130
- entry.structure.push({
1131
- type: "workflow",
1132
- id: wfNodeId,
1133
- phaseId: entry.currentPhaseId,
1134
- childRunID,
1135
- name: isInlineScript(spec) ? "inline" : spec,
1136
- ...(childArgs !== undefined ? { args: childArgs } : {}),
1137
- status: "running",
1138
- })
1139
- // The child is an independent sub-run: it gets its own per-run lifecycle
1140
- // cap + per-agent timeout (defaults), deliberately NOT inherited from the
1141
- // parent. Tree-wide concurrency is bounded by the global semaphore,
1142
- // not by propagating these per-run knobs.
1143
- yield* launch(
1144
- {
1145
- script: childScript,
1146
- sessionID: input.sessionID,
1147
- parentActorID: input.parentActorID,
1148
- args: childArgs,
1149
- model: input.model,
1150
- // A child may narrow its workspace to a subdir but never widen it
1151
- // beyond the parent's root — resolveInWorkspace throws on escape
1152
- // (a script-logic error → fail loud), same posture as the jail itself.
1153
- workspace: o.workspace ? resolveInWorkspace(workspaceRoot, String(o.workspace)) : workspaceRoot,
1154
- maxConcurrentAgents: o.maxConcurrentAgents,
1155
- scriptDeadlineMs: input.scriptDeadlineMs,
1156
- // Extend the nesting context for the child (T12): append this child to
1157
- // the ancestor lineage, increment depth, carry the same cap down.
1158
- lineage: [...lineage, childName],
1159
- depth: depth + 1,
1160
- maxDepth,
1161
- // A child is awaited inline here (waitFor below) and its outcome is
1162
- // consumed by the parent script — never deliver a separate inbox
1163
- // notification to the parent actor, regardless of the root run's
1164
- // sync/async mode. Only top-level async runs notify.
1165
- notifyOnTerminal: false,
1166
- },
1167
- childRunID,
1168
- isInlineScript(spec) ? "inline" : spec,
1169
- )
1170
- const childOutcome = yield* waitFor(childRunID)
1171
- const wfNode = entry.structure.find((n) => n.id === wfNodeId)
1172
- if (wfNode && wfNode.type === "workflow") wfNode.status = childOutcome.status
1173
- // Structural faults (cycle / depth / unknown-name) are workflow-wiring
1174
- // BUGS, not runtime conditions — propagate them loud instead of degrading
1175
- // to null like a child's runtime failure, so the fault surfaces at the root
1176
- // run. Each ancestor re-dies in turn; slice from the marker so the message
1177
- // doesn't accrete a "workflow script rejected:" prefix at every level.
1178
- if (childOutcome.status === "failed" && childOutcome.error.includes(WORKFLOW_STRUCTURAL_ERROR)) {
1179
- const idx = childOutcome.error.indexOf(WORKFLOW_STRUCTURAL_ERROR)
1180
- return yield* Effect.die(new Error(childOutcome.error.slice(idx)))
1181
- }
1182
- // Runtime failure (NOT structural — that path re-died above): the child's
1183
- // agents failed, it hit its deadline, or it was cancelled. workflow() still
1184
- // returns null (never-throw); this event records WHY for triage. Mirrors
1185
- // WorkflowAgentFailed. Fire-and-forget so a bus problem can't break the run.
1186
- if (childOutcome.status !== "completed") {
1187
- yield* bus
1188
- .publish(WorkflowChildFailed, {
1189
- sessionID: input.sessionID,
1190
- runID,
1191
- childRunID,
1192
- name: isInlineScript(spec) ? "inline" : spec,
1193
- status: childOutcome.status, // "failed" | "cancelled"
1194
- ...(childOutcome.status === "failed" ? { error: childOutcome.error } : {}),
1195
- })
1196
- .pipe(Effect.ignore)
1197
- }
1198
- const value = childOutcome.status === "completed" ? (childOutcome.result ?? null) : null
1199
- // Journal ONLY a successful child (null = failure → not cached → re-runs
1200
- // on resume, self-heal — same contract as agent()). Synchronous append so
1201
- // it survives a mid-run kill.
1202
- if (value !== null) {
1203
- yield* WorkflowPersistence.appendJournalSync(runID, [
1204
- { t: "agent", key: "wf:" + key, result: value, pass },
1205
- ]).pipe(Effect.ignore)
1206
- }
1207
- return value
1208
- }),
1209
- )
1210
- }
1211
-
1212
- const hooks: Record<string, HostFn> = {
1213
- agent,
1214
- phase,
1215
- log: logHook,
1216
- workflow: workflowHook,
1217
- readFile: fileHooks.readFile,
1218
- writeFile: fileHooks.writeFile,
1219
- glob: fileHooks.glob,
1220
- exists: fileHooks.exists,
1221
- }
1222
-
1223
- const work = Effect.gen(function* () {
1224
- // Object-form tryPromise: bare tryPromise wraps any rejection as an
1225
- // UnknownError whose .message is the useless "An error occurred in
1226
- // Effect.tryPromise" (the real error lands in .cause), so the failed-run
1227
- // error field / WorkflowFinished.error below would be opaque. Catching to
1228
- // the raw Error makes result.failure the sandbox Error itself, whose
1229
- // .message already carries the guest {name,message,stack} (vm.dump
1230
- // preserves it through the sandbox throw site) — a script-logic crash is
1231
- // then diagnosable from the run's error alone, no repro needed.
1232
- // Per-run PRNG seed = first 4 bytes of sha1(runID). runID is unique-per-run
1233
- // and persisted, so resume of the SAME run derives the SAME seed → guest
1234
- // Math.random replays identically (the replay invariant). Two UNRELATED runs
1235
- // of the same script get DIFFERENT runIDs → different seeds → different
1236
- // sequences, so sampling-style scripts get fresh coverage instead of
1237
- // repeating the same picks. Bun's lifetime-classify verification sample
1238
- // is the motivating use case.
1239
- const seed = createHash("sha1").update(runID).digest().readUInt32BE(0)
1240
- const result = yield* Effect.tryPromise({
1241
- try: () => evalScript(body, hooks, { deadlineMs: input.scriptDeadlineMs ?? SCRIPT_DEADLINE_MS, args: input.args, seed }),
1242
- catch: (e) => (e instanceof Error ? e : new Error(String(e))),
1243
- }).pipe(Effect.result)
1244
-
1245
- if (result._tag === "Success") {
1246
- entry.status = "completed"
1247
- yield* flushNow(entry)
1248
- yield* WorkflowPersistence.recordTerminal({ runID, status: "completed" }).pipe(Effect.ignore)
1249
- yield* Deferred.succeed(deferred, { status: "completed", result: result.success })
1250
- yield* bus.publish(WorkflowFinished, { sessionID: input.sessionID, runID, status: "completed" })
1251
- // Notify the parent so its next turn drains a completion message, the
1252
- // same way background actors notify on terminal (see actor/spawn.ts
1253
- // forkWork.notify). Fire-and-forget: a notify failure (e.g. parent row
1254
- // gone) must never fail the run, and wait-ers are already unblocked
1255
- // above by Deferred.succeed. Skipped when notifyOnTerminal === false (the
1256
- // tool's sync path returns the result inline; a notify would duplicate it).
1257
- if (input.notifyOnTerminal !== false)
1258
- yield* inbox
1259
- .send({
1260
- receiverSessionID: input.sessionID,
1261
- receiverActorID: input.parentActorID,
1262
- senderSessionID: input.sessionID,
1263
- senderActorID: "workflow",
1264
- type: "actor_notification",
1265
- content: `Workflow completed. run_id: ${runID}\n` + JSON.stringify(result.success ?? null).slice(0, 4000),
1266
- })
1267
- .pipe(Effect.ignore)
1268
- return
1269
- }
1270
- // Non-success terminal: reclaim in-flight agents + worktrees so a
1271
- // deadline-fire / script throw leaves a clean slate for a convergent
1272
- // re-run. Success path does NOT reclaim — kept worktrees are the deliverable.
1273
- yield* reclaim(entry)
1274
- const error = result.failure instanceof Error ? result.failure.message : String(result.failure)
1275
- entry.status = "failed"
1276
- log.warn("workflow run failed", { runID, error })
1277
- yield* flushNow(entry)
1278
- yield* WorkflowPersistence.recordTerminal({ runID, status: "failed", error }).pipe(Effect.ignore)
1279
- yield* Deferred.succeed(deferred, { status: "failed", error })
1280
- yield* bus.publish(WorkflowFinished, { sessionID: input.sessionID, runID, status: "failed", error })
1281
- if (input.notifyOnTerminal !== false)
1282
- yield* inbox
1283
- .send({
1284
- receiverSessionID: input.sessionID,
1285
- receiverActorID: input.parentActorID,
1286
- senderSessionID: input.sessionID,
1287
- senderActorID: "workflow",
1288
- type: "actor_notification",
1289
- content: `Workflow failed. run_id: ${runID}\nerror: ${error}`,
1290
- })
1291
- .pipe(Effect.ignore)
1292
- })
1293
-
1294
- entry.fiber = yield* work.pipe(Effect.forkIn(scope))
1295
- return { runID }
1296
- })
1297
-
1298
- const start = Effect.fn("WorkflowRuntime.start")(function* (input: StartInput) {
1299
- const parsed = parseMeta(input.script)
1300
- if (!parsed.ok) return yield* Effect.die(parsed.error)
1301
- const runID = Identifier.descending("workflow")
1302
- return yield* launch(input, runID, parsed.meta.name)
1303
- })
1304
-
1305
- const status = Effect.fn("WorkflowRuntime.status")(function* (input: { runID: string }) {
1306
- const entry = runs.get(input.runID)
1307
- if (!entry) return { status: "unknown" as const, agentCount: 0, running: 0, succeeded: 0, failed: 0 }
1308
- return {
1309
- status: entry.status,
1310
- agentCount: entry.agentCount,
1311
- running: entry.running,
1312
- succeeded: entry.succeeded,
1313
- failed: entry.failed,
1314
- ...(entry.currentPhase !== undefined ? { currentPhase: entry.currentPhase } : {}),
1315
- }
1316
- })
1317
-
1318
- const transcript = Effect.fn("WorkflowRuntime.transcript")(function* (input: { runID: string }) {
1319
- const entry = runs.get(input.runID)
1320
- return entry ? entry.transcript.slice() : []
1321
- })
1322
-
1323
- const structure = Effect.fn("WorkflowRuntime.structure")(function* (input: { runID: string }) {
1324
- const entry = runs.get(input.runID)
1325
- return { nodes: entry ? entry.structure.slice() : [] } satisfies WorkflowStructure
1326
- })
1327
-
1328
- const wait = Effect.fn("WorkflowRuntime.wait")(function* (input: { runID: string; timeoutMs?: number }) {
1329
- const entry = runs.get(input.runID)
1330
- if (!entry) return { status: "failed" as const, error: `unknown runID ${input.runID}` }
1331
- if (input.timeoutMs === undefined) return yield* Deferred.await(entry.deferred)
1332
- const raced = yield* Deferred.await(entry.deferred).pipe(
1333
- Effect.timeout(input.timeoutMs),
1334
- Effect.catchTag("TimeoutError", () => Effect.succeed(null)),
1335
- )
1336
- if (raced === null) return { status: "failed" as const, error: "workflow wait timed out" }
1337
- return raced
1338
- })
1339
-
1340
- const cancel = Effect.fn("WorkflowRuntime.cancel")(function* (input: { runID: string }) {
1341
- const entry = runs.get(input.runID)
1342
- if (!entry) return
1343
- yield* cancelEntry(entry)
1344
- })
1345
-
1346
- const list = Effect.fn("WorkflowRuntime.list")(function* (input?: { sessionID?: SessionID }) {
1347
- return yield* WorkflowPersistence.list(input)
1348
- })
1349
-
1350
- // Re-launch a persisted run under the SAME runID via the shared launch path.
1351
- // recordStart's onConflictDoUpdate flips the existing row back to "running" and
1352
- // runs.set overwrites the stale terminal entry (its old fiber is already done).
1353
- // model/concurrency/deadline are not persisted in v1 — launch applies defaults.
1354
- const resume = Effect.fn("WorkflowRuntime.resume")(function* (input: { runID: string; agentTimeoutMs?: number }) {
1355
- // SERIALIZE same-runID resume with the repo's in-process reader/writer lock
1356
- // (util/lock.ts: a module-global Map mutex). The live-guard below is a
1357
- // check-then-act (read runs.get → decide → launch) and is NOT atomic on its
1358
- // own: two concurrent resume(sameRunID) of a completed run would BOTH read
1359
- // status !== "running", BOTH pass the guard, and BOTH launch() — and launch
1360
- // does runs.set(runID, entry), so the second clobbers the first (orphaned
1361
- // fiber, raced counter flush) and both append to the same .jsonl journal.
1362
- // Holding the write lock across the guard THROUGH launch closes that window:
1363
- // the first waiter launches and flips the entry to "running" before releasing,
1364
- // so the second waiter sees status "running" at the guard and bails. We do NOT
1365
- // hold it for the whole run (launch forks the work fiber and returns once the
1366
- // entry is "running") — only the resume decision + entry creation is serialized.
1367
- // LIMITATION: this is in-process only. Two SEPARATE processes resuming the same
1368
- // runID against the same DB (e.g. two server instances) are NOT covered — there
1369
- // is no shared/file-lock infra in this repo to reuse, and cross-process resume
1370
- // is out of scope for MR104 P2-1.
1371
- // Acquire as a JS Promise<Disposable> (Lock.write is promise-based; there is no
1372
- // existing Effect-context consumer to mirror, so we bridge via Effect.promise),
1373
- // and release in Effect.ensuring so it ALWAYS releases — even if load /
1374
- // readScript / launch throws — otherwise a failed resume would deadlock every
1375
- // future resume of this runID.
1376
- const lock = yield* Effect.promise(() => Lock.write("workflow-resume:" + input.runID))
1377
- return yield* Effect.gen(function* () {
1378
- // Refuse to resume a run that is still LIVE in this process: launch would
1379
- // runs.set() over the live entry, orphaning the running fiber (double parent
1380
- // notify, raced counter flush, unreclaimable by cancel). The DB row is NOT the
1381
- // signal — a process-exited run still reads "running" there and IS resumable;
1382
- // a live `runs` entry means a fiber is actually executing here.
1383
- const live = runs.get(input.runID)
1384
- if (live && live.status === "running") return { runID: input.runID, resumed: false }
1385
- const row = yield* WorkflowPersistence.load(input.runID)
1386
- if (!row) return { runID: input.runID, resumed: false }
1387
- // readScript is Effect.promise — a missing file rejects as a DEFECT, which
1388
- // Effect.exit captures (Effect.result/option/catchAll do not catch defects in
1389
- // this effect version). Treat a missing or empty script as not-resumable.
1390
- const read = yield* WorkflowPersistence.readScript(input.runID).pipe(Effect.exit)
1391
- const script = Exit.isSuccess(read) ? read.value : ""
1392
- if (!script) return { runID: input.runID, resumed: false }
1393
- // Script-change invalidation (MR104 P1-2): the journal keys results by
1394
- // {prompt,agentType,model,schema,phase}+occ, NOT by the script body — so a
1395
- // between-cycle edit would replay OLD results onto NEW code paths (silent
1396
- // divergence). Compare the persisted sha (stamped at the prior launch) to the
1397
- // CURRENT script's sha; on any mismatch — including a null stored sha (a run
1398
- // recorded before this column existed → "unknown" → treat as changed) — pass
1399
- // freshJournal so launch truncates the stale journal and runs from scratch,
1400
- // re-stamping the new sha for the next resume. A match → normal replay.
1401
- const currentSha = createHash("sha256").update(script).digest("hex")
1402
- const freshJournal = row.scriptSha !== currentSha
1403
- yield* launch(
1404
- {
1405
- script,
1406
- sessionID: row.sessionID,
1407
- parentActorID: row.parentActorID ?? "main",
1408
- args: row.args,
1409
- freshJournal,
1410
- // Per-agent timeout: caller's explicit override > persisted value > undefined (off).
1411
- // The row's agent_timeout_ms was stamped at the original launch (or last resume
1412
- // that supplied an explicit override), so a UI-side resume that doesn't know
1413
- // the original launch params (e.g. TUI's /workflows resume) inherits the
1414
- // original timeout instead of silently dropping to unbounded — which used to
1415
- // let a wedged mimo TTFT stall the resumed run forever.
1416
- agentTimeoutMs: input.agentTimeoutMs ?? row.agentTimeoutMs,
1417
- },
1418
- input.runID,
1419
- row.name,
1420
- )
1421
- return { runID: input.runID, resumed: true }
1422
- }).pipe(Effect.ensuring(Effect.sync(() => lock[Symbol.dispose]())))
1423
- })
1424
-
1425
- const impl = Service.of({ start, status, wait, transcript, structure, cancel, list, resume })
1426
- // Late-bind the impl so the `workflow` tool can resolve it without forcing a
1427
- // WorkflowRuntime.Service requirement onto ToolRegistry.layer. See
1428
- // runtime-ref.ts for rationale.
1429
- workflowRef.current = impl
1430
- yield* Effect.addFinalizer(() =>
1431
- Effect.sync(() => {
1432
- if (workflowRef.current === impl) workflowRef.current = undefined
1433
- }),
1434
- )
1435
- return impl
1436
- }),
1437
- )
1438
-
1439
- export const defaultLayer = layer.pipe(
1440
- Layer.provide(Bus.defaultLayer),
1441
- Layer.provide(Inbox.defaultLayer),
1442
- Layer.provide(Worktree.defaultLayer),
1443
- Layer.provide(Provider.defaultLayer),
1444
- Layer.provide(Config.defaultLayer),
1445
- )
1446
-
1447
- export * as WorkflowRuntime from "./runtime"