@n8n/instance-ai 1.7.1 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (363) hide show
  1. package/dist/agent/instance-agent.d.ts +1 -1
  2. package/dist/agent/instance-agent.js +88 -75
  3. package/dist/agent/instance-agent.js.map +1 -1
  4. package/dist/agent/mcp-tool-name-validation.d.ts +4 -2
  5. package/dist/agent/mcp-tool-name-validation.js +2 -2
  6. package/dist/agent/mcp-tool-name-validation.js.map +1 -1
  7. package/dist/agent/runtime-workspace.d.ts +6 -0
  8. package/dist/agent/runtime-workspace.js +14 -0
  9. package/dist/agent/runtime-workspace.js.map +1 -0
  10. package/dist/agent/sanitize-mcp-schemas.d.ts +4 -3
  11. package/dist/agent/sanitize-mcp-schemas.js +53 -24
  12. package/dist/agent/sanitize-mcp-schemas.js.map +1 -1
  13. package/dist/agent/sub-agent-debriefing.d.ts +2 -2
  14. package/dist/agent/sub-agent-factory.d.ts +7 -4
  15. package/dist/agent/sub-agent-factory.js +24 -13
  16. package/dist/agent/sub-agent-factory.js.map +1 -1
  17. package/dist/agent/system-prompt.js +18 -15
  18. package/dist/agent/system-prompt.js.map +1 -1
  19. package/dist/build.tsbuildinfo +1 -1
  20. package/dist/constants/max-steps.d.ts +1 -1
  21. package/dist/constants/max-steps.js +1 -1
  22. package/dist/constants/max-steps.js.map +1 -1
  23. package/dist/domain-access/domain-gating.d.ts +2 -2
  24. package/dist/error-formatting.d.ts +1 -0
  25. package/dist/error-formatting.js +159 -0
  26. package/dist/error-formatting.js.map +1 -0
  27. package/dist/index.d.ts +65 -24
  28. package/dist/index.js +96 -52
  29. package/dist/index.js.map +1 -1
  30. package/dist/mcp/mcp-client-manager.d.ts +5 -4
  31. package/dist/mcp/mcp-client-manager.js +42 -17
  32. package/dist/mcp/mcp-client-manager.js.map +1 -1
  33. package/dist/memory/title-utils.d.ts +4 -1
  34. package/dist/memory/title-utils.js +10 -2
  35. package/dist/memory/title-utils.js.map +1 -1
  36. package/dist/parsers/structured-file-parser.d.ts +5 -2
  37. package/dist/parsers/structured-file-parser.js +9 -2
  38. package/dist/parsers/structured-file-parser.js.map +1 -1
  39. package/dist/planned-tasks/planned-task-permissions.js +3 -5
  40. package/dist/planned-tasks/planned-task-permissions.js.map +1 -1
  41. package/dist/planned-tasks/planned-task-service.d.ts +1 -0
  42. package/dist/planned-tasks/planned-task-service.js +8 -0
  43. package/dist/planned-tasks/planned-task-service.js.map +1 -1
  44. package/dist/runtime/background-task-manager.d.ts +9 -2
  45. package/dist/runtime/background-task-manager.js +7 -2
  46. package/dist/runtime/background-task-manager.js.map +1 -1
  47. package/dist/runtime/liveness-policy.js +4 -3
  48. package/dist/runtime/liveness-policy.js.map +1 -1
  49. package/dist/runtime/resumable-stream-executor.d.ts +4 -24
  50. package/dist/runtime/resumable-stream-executor.js +103 -1318
  51. package/dist/runtime/resumable-stream-executor.js.map +1 -1
  52. package/dist/runtime/run-state-registry.d.ts +8 -2
  53. package/dist/runtime/run-state-registry.js +19 -1
  54. package/dist/runtime/run-state-registry.js.map +1 -1
  55. package/dist/runtime/stream-runner.d.ts +4 -4
  56. package/dist/runtime/stream-runner.js +11 -25
  57. package/dist/runtime/stream-runner.js.map +1 -1
  58. package/dist/skills/materialize-runtime-skills.d.ts +62 -0
  59. package/dist/skills/materialize-runtime-skills.js +465 -0
  60. package/dist/skills/materialize-runtime-skills.js.map +1 -0
  61. package/dist/skills/runtime-skills.d.ts +4 -0
  62. package/dist/skills/runtime-skills.js +17 -0
  63. package/dist/skills/runtime-skills.js.map +1 -0
  64. package/dist/source-map-filter.d.ts +17 -0
  65. package/dist/source-map-filter.js +39 -0
  66. package/dist/source-map-filter.js.map +1 -0
  67. package/dist/storage/agent-tree-snapshot.d.ts +2 -0
  68. package/dist/storage/index.d.ts +3 -3
  69. package/dist/storage/index.js +8 -7
  70. package/dist/storage/index.js.map +1 -1
  71. package/dist/storage/planned-task-storage.d.ts +3 -3
  72. package/dist/storage/planned-task-storage.js +3 -8
  73. package/dist/storage/planned-task-storage.js.map +1 -1
  74. package/dist/storage/terminal-outcome-storage.d.ts +4 -4
  75. package/dist/storage/terminal-outcome-storage.js +1 -1
  76. package/dist/storage/terminal-outcome-storage.js.map +1 -1
  77. package/dist/storage/{mastra-iteration-log-storage.d.ts → thread-iteration-log-storage.d.ts} +3 -3
  78. package/dist/storage/{mastra-iteration-log-storage.js → thread-iteration-log-storage.js} +5 -5
  79. package/dist/storage/thread-iteration-log-storage.js.map +1 -0
  80. package/dist/storage/thread-patch.d.ts +16 -10
  81. package/dist/storage/thread-patch.js +37 -36
  82. package/dist/storage/thread-patch.js.map +1 -1
  83. package/dist/storage/{mastra-task-storage.d.ts → thread-task-storage.d.ts} +3 -3
  84. package/dist/storage/{mastra-task-storage.js → thread-task-storage.js} +5 -5
  85. package/dist/storage/thread-task-storage.js.map +1 -0
  86. package/dist/storage/workflow-loop-storage.d.ts +28 -28
  87. package/dist/storage/workflow-loop-storage.js +1 -1
  88. package/dist/storage/workflow-loop-storage.js.map +1 -1
  89. package/dist/stream/consume-with-hitl.d.ts +11 -11
  90. package/dist/stream/consume-with-hitl.js +27 -15
  91. package/dist/stream/consume-with-hitl.js.map +1 -1
  92. package/dist/stream/map-chunk.d.ts +1 -1
  93. package/dist/stream/map-chunk.js +153 -36
  94. package/dist/stream/map-chunk.js.map +1 -1
  95. package/dist/tool-registry.d.ts +8 -0
  96. package/dist/tool-registry.js +45 -0
  97. package/dist/tool-registry.js.map +1 -0
  98. package/dist/tools/attachments/parse-file.tool.d.ts +42 -45
  99. package/dist/tools/attachments/parse-file.tool.js +140 -97
  100. package/dist/tools/attachments/parse-file.tool.js.map +1 -1
  101. package/dist/tools/credentials.tool.d.ts +5 -5
  102. package/dist/tools/credentials.tool.js +31 -34
  103. package/dist/tools/credentials.tool.js.map +1 -1
  104. package/dist/tools/data-tables.tool.d.ts +3 -2
  105. package/dist/tools/data-tables.tool.js +99 -100
  106. package/dist/tools/data-tables.tool.js.map +1 -1
  107. package/dist/tools/evals/apply-pin-data.service.d.ts +3 -0
  108. package/dist/tools/evals/apply-pin-data.service.js +19 -0
  109. package/dist/tools/evals/apply-pin-data.service.js.map +1 -0
  110. package/dist/tools/evals/column-ref-utils.d.ts +3 -0
  111. package/dist/tools/evals/column-ref-utils.js +205 -48
  112. package/dist/tools/evals/column-ref-utils.js.map +1 -1
  113. package/dist/tools/evals/detect-agent-named-refs.service.js +20 -4
  114. package/dist/tools/evals/detect-agent-named-refs.service.js.map +1 -1
  115. package/dist/tools/evals/ensure-eval-data-table.service.d.ts +15 -0
  116. package/dist/tools/evals/ensure-eval-data-table.service.js +83 -0
  117. package/dist/tools/evals/ensure-eval-data-table.service.js.map +1 -0
  118. package/dist/tools/evals/eval-data-requirements.service.d.ts +1 -0
  119. package/dist/tools/evals/eval-data-requirements.service.js +23 -4
  120. package/dist/tools/evals/eval-data-requirements.service.js.map +1 -1
  121. package/dist/tools/evals/evals.tool.d.ts +2 -0
  122. package/dist/tools/evals/evals.tool.js +452 -0
  123. package/dist/tools/evals/evals.tool.js.map +1 -0
  124. package/dist/tools/evals/extract-rows-from-history.service.d.ts +17 -0
  125. package/dist/tools/evals/extract-rows-from-history.service.js +103 -0
  126. package/dist/tools/evals/extract-rows-from-history.service.js.map +1 -0
  127. package/dist/tools/evals/format-eval-setup-task.d.ts +16 -0
  128. package/dist/tools/evals/format-eval-setup-task.js +167 -0
  129. package/dist/tools/evals/format-eval-setup-task.js.map +1 -0
  130. package/dist/tools/evals/generate-sample-rows.service.d.ts +35 -0
  131. package/dist/tools/evals/generate-sample-rows.service.js +278 -0
  132. package/dist/tools/evals/generate-sample-rows.service.js.map +1 -0
  133. package/dist/tools/evals/generate-tool-ref-pin-data.service.d.ts +11 -0
  134. package/dist/tools/evals/generate-tool-ref-pin-data.service.js +125 -0
  135. package/dist/tools/evals/generate-tool-ref-pin-data.service.js.map +1 -0
  136. package/dist/tools/evals/metric-catalog.d.ts +10 -4
  137. package/dist/tools/evals/metric-catalog.js.map +1 -1
  138. package/dist/tools/executions.tool.d.ts +1 -1
  139. package/dist/tools/executions.tool.js +25 -34
  140. package/dist/tools/executions.tool.js.map +1 -1
  141. package/dist/tools/filesystem/create-tools-from-mcp-server.d.ts +2 -3
  142. package/dist/tools/filesystem/create-tools-from-mcp-server.js +129 -67
  143. package/dist/tools/filesystem/create-tools-from-mcp-server.js.map +1 -1
  144. package/dist/tools/index.d.ts +4 -16
  145. package/dist/tools/index.js +102 -92
  146. package/dist/tools/index.js.map +1 -1
  147. package/dist/tools/nodes.tool.d.ts +1 -1
  148. package/dist/tools/nodes.tool.js +31 -33
  149. package/dist/tools/nodes.tool.js.map +1 -1
  150. package/dist/tools/orchestration/add-plan-item.tool.d.ts +2 -2
  151. package/dist/tools/orchestration/add-plan-item.tool.js +45 -49
  152. package/dist/tools/orchestration/add-plan-item.tool.js.map +1 -1
  153. package/dist/tools/orchestration/agent-persistence.d.ts +14 -0
  154. package/dist/tools/orchestration/agent-persistence.js +43 -0
  155. package/dist/tools/orchestration/agent-persistence.js.map +1 -0
  156. package/dist/tools/orchestration/blueprint-accumulator.d.ts +4 -8
  157. package/dist/tools/orchestration/blueprint-accumulator.js +11 -78
  158. package/dist/tools/orchestration/blueprint-accumulator.js.map +1 -1
  159. package/dist/tools/orchestration/blueprint.schema.d.ts +13 -147
  160. package/dist/tools/orchestration/blueprint.schema.js +4 -23
  161. package/dist/tools/orchestration/blueprint.schema.js.map +1 -1
  162. package/dist/tools/orchestration/browser-credential-setup.nudge.d.ts +2 -4
  163. package/dist/tools/orchestration/browser-credential-setup.nudge.js +1 -1
  164. package/dist/tools/orchestration/browser-credential-setup.nudge.js.map +1 -1
  165. package/dist/tools/orchestration/browser-credential-setup.tool.d.ts +10 -2
  166. package/dist/tools/orchestration/browser-credential-setup.tool.js +299 -270
  167. package/dist/tools/orchestration/browser-credential-setup.tool.js.map +1 -1
  168. package/dist/tools/orchestration/build-workflow-agent.prompt.d.ts +7 -1
  169. package/dist/tools/orchestration/build-workflow-agent.prompt.js +46 -20
  170. package/dist/tools/orchestration/build-workflow-agent.prompt.js.map +1 -1
  171. package/dist/tools/orchestration/build-workflow-agent.tool.d.ts +50 -5
  172. package/dist/tools/orchestration/build-workflow-agent.tool.js +748 -605
  173. package/dist/tools/orchestration/build-workflow-agent.tool.js.map +1 -1
  174. package/dist/tools/orchestration/builder-memory-compaction.d.ts +6 -2
  175. package/dist/tools/orchestration/builder-memory-compaction.js +32 -46
  176. package/dist/tools/orchestration/builder-memory-compaction.js.map +1 -1
  177. package/dist/tools/orchestration/complete-checkpoint.tool.d.ts +1 -1
  178. package/dist/tools/orchestration/complete-checkpoint.tool.js +46 -47
  179. package/dist/tools/orchestration/complete-checkpoint.tool.js.map +1 -1
  180. package/dist/tools/orchestration/delegate.tool.d.ts +1 -1
  181. package/dist/tools/orchestration/delegate.tool.js +170 -166
  182. package/dist/tools/orchestration/delegate.tool.js.map +1 -1
  183. package/dist/tools/orchestration/eval-data-agent.tool.d.ts +2 -0
  184. package/dist/tools/orchestration/eval-data-agent.tool.js +183 -0
  185. package/dist/tools/orchestration/eval-data-agent.tool.js.map +1 -0
  186. package/dist/tools/orchestration/eval-setup-agent.prompt.d.ts +1 -0
  187. package/dist/tools/orchestration/eval-setup-agent.prompt.js +238 -0
  188. package/dist/tools/orchestration/eval-setup-agent.prompt.js.map +1 -0
  189. package/dist/tools/orchestration/eval-setup-agent.tool.d.ts +31 -0
  190. package/dist/tools/orchestration/eval-setup-agent.tool.js +204 -0
  191. package/dist/tools/orchestration/eval-setup-agent.tool.js.map +1 -0
  192. package/dist/tools/orchestration/plan-agent-prompt.d.ts +1 -1
  193. package/dist/tools/orchestration/plan-agent-prompt.js +9 -9
  194. package/dist/tools/orchestration/plan-with-agent.tool.d.ts +1 -1
  195. package/dist/tools/orchestration/plan-with-agent.tool.js +210 -179
  196. package/dist/tools/orchestration/plan-with-agent.tool.js.map +1 -1
  197. package/dist/tools/orchestration/plan.tool.d.ts +5 -2
  198. package/dist/tools/orchestration/plan.tool.js +125 -105
  199. package/dist/tools/orchestration/plan.tool.js.map +1 -1
  200. package/dist/tools/orchestration/report-verification-verdict.tool.d.ts +3 -3
  201. package/dist/tools/orchestration/report-verification-verdict.tool.js +65 -66
  202. package/dist/tools/orchestration/report-verification-verdict.tool.js.map +1 -1
  203. package/dist/tools/orchestration/submit-plan.tool.d.ts +1 -1
  204. package/dist/tools/orchestration/submit-plan.tool.js +83 -66
  205. package/dist/tools/orchestration/submit-plan.tool.js.map +1 -1
  206. package/dist/tools/orchestration/tracing-utils.d.ts +3 -2
  207. package/dist/tools/orchestration/tracing-utils.js +58 -39
  208. package/dist/tools/orchestration/tracing-utils.js.map +1 -1
  209. package/dist/tools/orchestration/verify-built-workflow.tool.d.ts +5 -5
  210. package/dist/tools/orchestration/verify-built-workflow.tool.js +166 -166
  211. package/dist/tools/orchestration/verify-built-workflow.tool.js.map +1 -1
  212. package/dist/tools/research.tool.d.ts +1 -1
  213. package/dist/tools/research.tool.js +59 -27
  214. package/dist/tools/research.tool.js.map +1 -1
  215. package/dist/tools/shared/ask-user.tool.d.ts +3 -2
  216. package/dist/tools/shared/ask-user.tool.js +61 -63
  217. package/dist/tools/shared/ask-user.tool.js.map +1 -1
  218. package/dist/tools/task-control.tool.d.ts +1 -1
  219. package/dist/tools/task-control.tool.js +15 -16
  220. package/dist/tools/task-control.tool.js.map +1 -1
  221. package/dist/tools/templates.tool.d.ts +1 -1
  222. package/dist/tools/templates.tool.js +6 -7
  223. package/dist/tools/templates.tool.js.map +1 -1
  224. package/dist/tools/tool-ids.d.ts +40 -0
  225. package/dist/tools/tool-ids.js +62 -0
  226. package/dist/tools/tool-ids.js.map +1 -0
  227. package/dist/tools/workflows/apply-workflow-credentials.tool.d.ts +3 -3
  228. package/dist/tools/workflows/apply-workflow-credentials.tool.js +72 -73
  229. package/dist/tools/workflows/apply-workflow-credentials.tool.js.map +1 -1
  230. package/dist/tools/workflows/build-workflow.tool.d.ts +3 -3
  231. package/dist/tools/workflows/build-workflow.tool.js +113 -114
  232. package/dist/tools/workflows/build-workflow.tool.js.map +1 -1
  233. package/dist/tools/workflows/materialize-node-type.tool.d.ts +6 -6
  234. package/dist/tools/workflows/materialize-node-type.tool.js +64 -65
  235. package/dist/tools/workflows/materialize-node-type.tool.js.map +1 -1
  236. package/dist/tools/workflows/resolve-credentials.d.ts +3 -5
  237. package/dist/tools/workflows/resolve-credentials.js +15 -6
  238. package/dist/tools/workflows/resolve-credentials.js.map +1 -1
  239. package/dist/tools/workflows/setup-workflow.schema.d.ts +2 -2
  240. package/dist/tools/workflows/submit-workflow-identity.d.ts +8 -9
  241. package/dist/tools/workflows/submit-workflow-identity.js +41 -27
  242. package/dist/tools/workflows/submit-workflow-identity.js.map +1 -1
  243. package/dist/tools/workflows/submit-workflow.tool.d.ts +10 -7
  244. package/dist/tools/workflows/submit-workflow.tool.js +224 -191
  245. package/dist/tools/workflows/submit-workflow.tool.js.map +1 -1
  246. package/dist/tools/workflows/validate-workflow.service.d.ts +15 -0
  247. package/dist/tools/workflows/validate-workflow.service.js +289 -0
  248. package/dist/tools/workflows/validate-workflow.service.js.map +1 -0
  249. package/dist/tools/workflows/write-sandbox-file.tool.d.ts +2 -2
  250. package/dist/tools/workflows/write-sandbox-file.tool.js +29 -30
  251. package/dist/tools/workflows/write-sandbox-file.tool.js.map +1 -1
  252. package/dist/tools/workflows.tool.d.ts +5 -2
  253. package/dist/tools/workflows.tool.js +184 -85
  254. package/dist/tools/workflows.tool.js.map +1 -1
  255. package/dist/tools/workspace.tool.d.ts +1 -1
  256. package/dist/tools/workspace.tool.js +49 -65
  257. package/dist/tools/workspace.tool.js.map +1 -1
  258. package/dist/tracing/langsmith-tracing.d.ts +17 -18
  259. package/dist/tracing/langsmith-tracing.js +941 -677
  260. package/dist/tracing/langsmith-tracing.js.map +1 -1
  261. package/dist/tracing/trace-labels.d.ts +5 -0
  262. package/dist/tracing/trace-labels.js +36 -0
  263. package/dist/tracing/trace-labels.js.map +1 -0
  264. package/dist/tracing/trace-payloads.d.ts +23 -0
  265. package/dist/tracing/trace-payloads.js +1008 -0
  266. package/dist/tracing/trace-payloads.js.map +1 -0
  267. package/dist/types.d.ts +57 -25
  268. package/dist/types.js +3 -0
  269. package/dist/types.js.map +1 -1
  270. package/dist/utils/eval-agents.js +1 -1
  271. package/dist/utils/eval-agents.js.map +1 -1
  272. package/dist/utils/scrub-secrets.js +1 -1
  273. package/dist/utils/scrub-secrets.js.map +1 -1
  274. package/dist/utils/stream-helpers.d.ts +2 -5
  275. package/dist/utils/stream-helpers.js +12 -1
  276. package/dist/utils/stream-helpers.js.map +1 -1
  277. package/dist/workflow-loop/workflow-loop-state.d.ts +18 -18
  278. package/dist/workspace/builder-templates-service.d.ts +54 -0
  279. package/dist/workspace/builder-templates-service.js +442 -0
  280. package/dist/workspace/builder-templates-service.js.map +1 -0
  281. package/dist/workspace/create-workspace.d.ts +16 -3
  282. package/dist/workspace/create-workspace.js +45 -21
  283. package/dist/workspace/create-workspace.js.map +1 -1
  284. package/dist/workspace/daytona-auth-manager.d.ts +26 -0
  285. package/dist/workspace/daytona-auth-manager.js +90 -0
  286. package/dist/workspace/daytona-auth-manager.js.map +1 -0
  287. package/dist/workspace/daytona-filesystem.d.ts +5 -4
  288. package/dist/workspace/daytona-filesystem.js +25 -15
  289. package/dist/workspace/daytona-filesystem.js.map +1 -1
  290. package/dist/workspace/daytona-sandbox.d.ts +65 -0
  291. package/dist/workspace/daytona-sandbox.js +314 -0
  292. package/dist/workspace/daytona-sandbox.js.map +1 -0
  293. package/dist/workspace/lazy-daytona.d.ts +2 -0
  294. package/dist/workspace/lazy-daytona.js +12 -0
  295. package/dist/workspace/lazy-daytona.js.map +1 -0
  296. package/dist/workspace/lazy-runtime-workspace.d.ts +8 -0
  297. package/dist/workspace/lazy-runtime-workspace.js +246 -0
  298. package/dist/workspace/lazy-runtime-workspace.js.map +1 -0
  299. package/dist/workspace/local-filesystem.d.ts +48 -0
  300. package/dist/workspace/local-filesystem.js +250 -0
  301. package/dist/workspace/local-filesystem.js.map +1 -0
  302. package/dist/workspace/local-sandbox.d.ts +28 -0
  303. package/dist/workspace/local-sandbox.js +121 -0
  304. package/dist/workspace/local-sandbox.js.map +1 -0
  305. package/dist/workspace/n8n-sandbox-filesystem.d.ts +3 -3
  306. package/dist/workspace/n8n-sandbox-filesystem.js +3 -3
  307. package/dist/workspace/n8n-sandbox-filesystem.js.map +1 -1
  308. package/dist/workspace/n8n-sandbox-sandbox.d.ts +12 -3
  309. package/dist/workspace/n8n-sandbox-sandbox.js +54 -10
  310. package/dist/workspace/n8n-sandbox-sandbox.js.map +1 -1
  311. package/dist/workspace/sandbox-fs.d.ts +35 -4
  312. package/dist/workspace/sandbox-fs.js +1 -1
  313. package/dist/workspace/sandbox-fs.js.map +1 -1
  314. package/dist/workspace/sandbox-setup.d.ts +13 -4
  315. package/dist/workspace/sandbox-setup.js +250 -36
  316. package/dist/workspace/sandbox-setup.js.map +1 -1
  317. package/dist/workspace/scoped-workspace.d.ts +2 -0
  318. package/dist/workspace/scoped-workspace.js +141 -0
  319. package/dist/workspace/scoped-workspace.js.map +1 -0
  320. package/dist/workspace/snapshot-manager.d.ts +11 -5
  321. package/dist/workspace/snapshot-manager.js +74 -17
  322. package/dist/workspace/snapshot-manager.js.map +1 -1
  323. package/dist/workspace/template-telemetry.d.ts +4 -4
  324. package/dist/workspace/template-telemetry.js +18 -6
  325. package/dist/workspace/template-telemetry.js.map +1 -1
  326. package/package.json +13 -16
  327. package/skills/data-table-manager/SKILL.md +119 -0
  328. package/skills/data-table-manager/references/data-table-playbook.md +212 -0
  329. package/dist/agent/register-with-mastra.d.ts +0 -3
  330. package/dist/agent/register-with-mastra.js +0 -15
  331. package/dist/agent/register-with-mastra.js.map +0 -1
  332. package/dist/compaction/compaction-helper.d.ts +0 -9
  333. package/dist/compaction/compaction-helper.js +0 -58
  334. package/dist/compaction/compaction-helper.js.map +0 -1
  335. package/dist/compaction/index.d.ts +0 -2
  336. package/dist/compaction/index.js +0 -6
  337. package/dist/compaction/index.js.map +0 -1
  338. package/dist/memory/memory-config.d.ts +0 -3
  339. package/dist/memory/memory-config.js +0 -27
  340. package/dist/memory/memory-config.js.map +0 -1
  341. package/dist/runtime/builder-sandbox-session-registry.d.ts +0 -47
  342. package/dist/runtime/builder-sandbox-session-registry.js +0 -166
  343. package/dist/runtime/builder-sandbox-session-registry.js.map +0 -1
  344. package/dist/storage/mastra-iteration-log-storage.js.map +0 -1
  345. package/dist/storage/mastra-task-storage.js.map +0 -1
  346. package/dist/tools/orchestration/data-table-agent.prompt.d.ts +0 -1
  347. package/dist/tools/orchestration/data-table-agent.prompt.js +0 -47
  348. package/dist/tools/orchestration/data-table-agent.prompt.js.map +0 -1
  349. package/dist/tools/orchestration/data-table-agent.tool.d.ts +0 -26
  350. package/dist/tools/orchestration/data-table-agent.tool.js +0 -174
  351. package/dist/tools/orchestration/data-table-agent.tool.js.map +0 -1
  352. package/dist/tools/orchestration/research-agent-prompt.d.ts +0 -1
  353. package/dist/tools/orchestration/research-agent-prompt.js +0 -26
  354. package/dist/tools/orchestration/research-agent-prompt.js.map +0 -1
  355. package/dist/tools/orchestration/research-with-agent.tool.d.ts +0 -30
  356. package/dist/tools/orchestration/research-with-agent.tool.js +0 -179
  357. package/dist/tools/orchestration/research-with-agent.tool.js.map +0 -1
  358. package/dist/workspace/builder-sandbox-factory.d.ts +0 -30
  359. package/dist/workspace/builder-sandbox-factory.js +0 -289
  360. package/dist/workspace/builder-sandbox-factory.js.map +0 -1
  361. package/dist/workspace/guarded-filesystem.d.ts +0 -10
  362. package/dist/workspace/guarded-filesystem.js +0 -136
  363. package/dist/workspace/guarded-filesystem.js.map +0 -1
@@ -1,6 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildWorkflowAgentInputSchema = exports.DETACHED_BUILDER_REQUIREMENTS = void 0;
4
+ exports.getBuilderSessionMemory = getBuilderSessionMemory;
5
+ exports.builderWorkflowWorkspaceLayout = builderWorkflowWorkspaceLayout;
6
+ exports.materializeBuilderRuntimeSkills = materializeBuilderRuntimeSkills;
4
7
  exports.buildWarmBuilderFollowUp = buildWarmBuilderFollowUp;
5
8
  exports.recordSuccessfulWorkflowBuilds = recordSuccessfulWorkflowBuilds;
6
9
  exports.determineVerificationReadiness = determineVerificationReadiness;
@@ -8,45 +11,129 @@ exports.determineSetupRequirement = determineSetupRequirement;
8
11
  exports.mergeLatestVerificationIntoOutcome = mergeLatestVerificationIntoOutcome;
9
12
  exports.withTerminalLoopState = withTerminalLoopState;
10
13
  exports.finalizeBuildResult = finalizeBuildResult;
14
+ exports.createMainWorkflowSnapshot = createMainWorkflowSnapshot;
15
+ exports.shouldFinalSubmitMainWorkflow = shouldFinalSubmitMainWorkflow;
11
16
  exports.supportingWorkflowIdsFromSubmitAttempts = supportingWorkflowIdsFromSubmitAttempts;
12
17
  exports.resultFromPostStreamError = resultFromPostStreamError;
13
18
  exports.resultFromTerminalRemediation = resultFromTerminalRemediation;
14
19
  exports.resultFromLaterFailedMainSubmit = resultFromLaterFailedMainSubmit;
15
20
  exports.attemptFromAutoResubmit = attemptFromAutoResubmit;
16
21
  exports.shouldRecoverSavedWorkflowAfterFailedSubmit = shouldRecoverSavedWorkflowAfterFailedSubmit;
22
+ exports.settleMissingMainWorkflowSubmit = settleMissingMainWorkflowSubmit;
17
23
  exports.startBuildWorkflowAgentTask = startBuildWorkflowAgentTask;
18
24
  exports.createBuildWorkflowAgentTool = createBuildWorkflowAgentTool;
19
- const agent_1 = require("@mastra/core/agent");
20
- const tools_1 = require("@mastra/core/tools");
25
+ const agents_1 = require("@n8n/agents");
21
26
  const workflow_sdk_1 = require("@n8n/workflow-sdk");
22
27
  const n8n_workflow_1 = require("n8n-workflow");
23
28
  const nanoid_1 = require("nanoid");
24
29
  const node_crypto_1 = require("node:crypto");
25
30
  const zod_1 = require("zod");
31
+ const agent_persistence_1 = require("./agent-persistence");
26
32
  const build_workflow_agent_prompt_1 = require("./build-workflow-agent.prompt");
27
33
  const builder_memory_compaction_1 = require("./builder-memory-compaction");
28
34
  const display_utils_1 = require("./display-utils");
29
35
  const tracing_utils_1 = require("./tracing-utils");
30
36
  const verify_built_workflow_tool_1 = require("./verify-built-workflow.tool");
31
- const register_with_mastra_1 = require("../../agent/register-with-mastra");
37
+ const runtime_workspace_1 = require("../../agent/runtime-workspace");
32
38
  const sub_agent_briefing_1 = require("../../agent/sub-agent-briefing");
33
39
  const max_steps_1 = require("../../constants/max-steps");
34
- const model_settings_1 = require("../../constants/model-settings");
35
- const resumable_stream_executor_1 = require("../../runtime/resumable-stream-executor");
40
+ const materialize_runtime_skills_1 = require("../../skills/materialize-runtime-skills");
41
+ const runtime_skills_1 = require("../../skills/runtime-skills");
36
42
  const consume_with_hitl_1 = require("../../stream/consume-with-hitl");
43
+ const tool_registry_1 = require("../../tool-registry");
37
44
  const langsmith_tracing_1 = require("../../tracing/langsmith-tracing");
38
45
  const extract_code_1 = require("../../workflow-builder/extract-code");
39
46
  const workflow_loop_1 = require("../../workflow-loop");
40
47
  const sandbox_fs_1 = require("../../workspace/sandbox-fs");
41
48
  const sandbox_setup_1 = require("../../workspace/sandbox-setup");
49
+ const scoped_workspace_1 = require("../../workspace/scoped-workspace");
42
50
  const template_telemetry_1 = require("../../workspace/template-telemetry");
43
51
  const credentials_tool_1 = require("../credentials.tool");
52
+ const data_tables_tool_1 = require("../data-tables.tool");
53
+ const ask_user_tool_1 = require("../shared/ask-user.tool");
44
54
  const resolve_credentials_1 = require("../workflows/resolve-credentials");
45
55
  const submit_workflow_identity_1 = require("../workflows/submit-workflow-identity");
46
56
  const workflow_json_utils_1 = require("../workflows/workflow-json-utils");
47
57
  const workflows_tool_1 = require("../workflows.tool");
48
- function createBuilderResourceId(userId) {
49
- return `${userId}:workflow-builder`;
58
+ const WORKFLOW_NOT_SUBMITTED_FAILURE_SIGNATURE = 'workflow:not_submitted';
59
+ const WORKFLOW_FINAL_SUBMIT_FAILED_FAILURE_SIGNATURE = 'workflow:final_submit_failed';
60
+ function getBuilderSessionMemory(context, useSharedWorkspace) {
61
+ return useSharedWorkspace ? context.memory : undefined;
62
+ }
63
+ const BUILDER_WORK_ITEMS_DIR = 'builder-work-items';
64
+ function safeWorkItemPathSegment(workItemId) {
65
+ const slug = workItemId
66
+ .replace(/[^A-Za-z0-9_-]+/g, '-')
67
+ .replace(/^-+|-+$/g, '')
68
+ .slice(0, 48);
69
+ const hash = (0, node_crypto_1.createHash)('sha256').update(workItemId).digest('hex').slice(0, 8);
70
+ return `${slug || 'work-item'}-${hash}`;
71
+ }
72
+ function builderWorkflowWorkspaceLayout(root, workItemId) {
73
+ const relativeWorkItemRoot = `${BUILDER_WORK_ITEMS_DIR}/${safeWorkItemPathSegment(workItemId)}`;
74
+ const workItemRoot = `${root}/${relativeWorkItemRoot}`;
75
+ return {
76
+ workItemRoot,
77
+ sourceDir: `${workItemRoot}/src`,
78
+ chunksDir: `${workItemRoot}/chunks`,
79
+ mainWorkflowPath: `${workItemRoot}/src/workflow.ts`,
80
+ tsconfigPath: `${workItemRoot}/tsconfig.json`,
81
+ relativeMainWorkflowPath: `${relativeWorkItemRoot}/src/workflow.ts`,
82
+ };
83
+ }
84
+ function renderBuilderTaskTsconfig() {
85
+ return `${JSON.stringify({
86
+ extends: '../../tsconfig.json',
87
+ include: ['src/**/*.ts', 'chunks/**/*.ts'],
88
+ }, null, 2)}\n`;
89
+ }
90
+ async function writeBuilderWorkspaceFile(workspace, filePath, content) {
91
+ if (workspace.filesystem) {
92
+ await workspace.filesystem.writeFile(filePath, content, { recursive: true });
93
+ return;
94
+ }
95
+ await (0, sandbox_fs_1.writeFileViaSandbox)(workspace, filePath, content);
96
+ }
97
+ async function materializeBuilderRuntimeSkills(context, workspace, root) {
98
+ const source = context.runtimeSkillCatalog ?? context.runtimeSkills;
99
+ if (!(0, runtime_skills_1.hasRuntimeSkills)(source)) {
100
+ return { workspace, source };
101
+ }
102
+ let materialized;
103
+ try {
104
+ const workspaceRoot = await (0, sandbox_setup_1.getWorkspaceRoot)(workspace);
105
+ materialized = await (0, materialize_runtime_skills_1.createPrebakedRuntimeSkillsFromWorkspace)({
106
+ source,
107
+ workspace,
108
+ root: workspaceRoot,
109
+ workspaceRoot: root,
110
+ logger: context.logger,
111
+ });
112
+ }
113
+ catch (error) {
114
+ context.logger.debug('Could not inspect prebaked runtime skills; materializing live', {
115
+ error: error instanceof Error ? error.message : String(error),
116
+ });
117
+ }
118
+ materialized ??= await (0, materialize_runtime_skills_1.materializeRuntimeSkillsIntoWorkspace)({
119
+ source,
120
+ workspace,
121
+ root,
122
+ logger: context.logger,
123
+ });
124
+ if (!materialized)
125
+ return { workspace, source };
126
+ return {
127
+ workspace: (0, scoped_workspace_1.createScopedWorkspace)(workspace, root, materialized.env),
128
+ source: materialized.source,
129
+ };
130
+ }
131
+ function toToolRegistry(tools) {
132
+ const registry = (0, tool_registry_1.createToolRegistry)();
133
+ for (const tool of tools) {
134
+ registry.set(tool.name, tool);
135
+ }
136
+ return registry;
50
137
  }
51
138
  const BUILDER_WORKFLOW_ACTIONS = [
52
139
  'list',
@@ -61,19 +148,19 @@ const BUILDER_CREDENTIAL_ACTIONS = [
61
148
  ];
62
149
  const BUILDER_SANDBOX_TOOL_NAMES = [
63
150
  'nodes',
64
- 'workflows',
65
- 'credentials',
66
151
  'executions',
67
- 'data-tables',
68
- 'ask-user',
152
+ data_tables_tool_1.DATA_TABLES_TOOL_ID,
153
+ 'parse-file',
154
+ ask_user_tool_1.ASK_USER_TOOL_ID,
69
155
  'research',
70
156
  ];
71
157
  const BUILDER_TOOL_MODE_TOOL_NAMES = [
72
158
  'build-workflow',
73
159
  'nodes',
74
160
  'workflows',
75
- 'data-tables',
76
- 'ask-user',
161
+ data_tables_tool_1.DATA_TABLES_TOOL_ID,
162
+ 'parse-file',
163
+ ask_user_tool_1.ASK_USER_TOOL_ID,
77
164
  'research',
78
165
  ];
79
166
  function createBuilderWorkflowsTool(context) {
@@ -104,29 +191,6 @@ function buildWarmBuilderFollowUp(input) {
104
191
  parts.push('', '<requested-change>', input.task, '</requested-change>', '</builder-follow-up>');
105
192
  return parts.join('\n');
106
193
  }
107
- async function ensureBuilderMemoryThread(context, binding) {
108
- if (!context.memory)
109
- return false;
110
- try {
111
- const existingThread = await context.memory.getThreadById({ threadId: binding.thread });
112
- if (existingThread)
113
- return true;
114
- const now = new Date();
115
- await context.memory.saveThread({
116
- thread: {
117
- id: binding.thread,
118
- resourceId: binding.resource,
119
- title: 'Workflow Builder',
120
- createdAt: now,
121
- updatedAt: now,
122
- },
123
- });
124
- return true;
125
- }
126
- catch {
127
- return false;
128
- }
129
- }
130
194
  async function promoteMainWorkflow(context, logger, workflowId) {
131
195
  if (!workflowId || !context)
132
196
  return;
@@ -140,20 +204,18 @@ async function promoteMainWorkflow(context, logger, workflowId) {
140
204
  function isRecord(value) {
141
205
  return typeof value === 'object' && value !== null;
142
206
  }
143
- function isExecutableTool(tool) {
144
- return isRecord(tool) && typeof tool.execute === 'function';
145
- }
146
207
  function recordSuccessfulWorkflowBuilds(tool, onWorkflowId) {
147
- if (!isExecutableTool(tool))
208
+ if (!tool?.handler)
148
209
  return;
149
- const execute = tool.execute.bind(tool);
150
- tool.execute = async (...args) => {
151
- const result = await execute(...args);
210
+ const original = tool.handler;
211
+ const wrapped = async (input, ctx) => {
212
+ const result = await original(input, ctx);
152
213
  if (isRecord(result) && result.success === true && typeof result.workflowId === 'string') {
153
214
  onWorkflowId(result.workflowId);
154
215
  }
155
216
  return result;
156
217
  };
218
+ Object.assign(tool, { handler: wrapped });
157
219
  }
158
220
  function detectTriggerType(_attempt) {
159
221
  return 'manual_or_testable';
@@ -337,6 +399,10 @@ async function finalizeBuildResult(context, workItemId, result) {
337
399
  outcome: await finalBuildOutcome(context, workItemId, result.outcome),
338
400
  };
339
401
  }
402
+ async function reportAndFinalizeBuildResult(context, workItemId, result) {
403
+ await context.workflowTaskService?.reportBuildOutcome(result.outcome);
404
+ return await finalizeBuildResult(context, workItemId, result);
405
+ }
340
406
  async function buildOutcomeWithLatestVerification(context, workItemId, taskId, attempt, finalText, supportingWorkflowIds = []) {
341
407
  const outcome = buildOutcome(workItemId, context.runId, taskId, attempt, finalText, supportingWorkflowIds);
342
408
  return await finalBuildOutcome(context, workItemId, outcome);
@@ -359,14 +425,14 @@ payload. The pin-data adapter injects it as the trigger node's output.
359
425
  ### Submit discipline
360
426
 
361
427
  **Every file edit MUST be followed by submit-workflow before you do anything else.**
362
- The system tracks file hashes. If you edit the code and then call \`executions(action="run")\` or finish without re-submitting, your work is discarded. The sequence is always: edit → submit → then verify/run.
428
+ The system tracks file hashes. If you edit the code and then call \`executions(action="run")\`, \`verify-built-workflow\`, or finish without re-submitting, your work is discarded. The sequence is always: edit → submit → then verify/run.
363
429
 
364
430
  ### Verification
365
431
 
366
- - If submit-workflow returned mocked credentials, call \`verify-built-workflow\` with the workItemId.
432
+ - If submit-workflow returned mocked credentials, call \`verify-built-workflow\` with the workItemId and workflowId from this task.
367
433
  - Otherwise pick based on trigger type:
368
434
  - **Manual / Schedule** — \`executions(action="run")\`.
369
- - **Form Trigger** — \`verify-built-workflow\` with \`inputData\` as a flat field map, e.g. \`{name: "Alice", email: "a@b.c"}\`. Do NOT wrap in \`formFields\` — production Form Trigger emits fields directly on \`$json\`, and the adapter rejects wrapped payloads.
435
+ - **Form Trigger** — pass \`inputData\` as a flat field map, e.g. \`{name: "Alice", email: "a@b.c"}\`. Do NOT wrap in \`formFields\` — production Form Trigger emits fields directly on \`$json\`, and the adapter rejects wrapped payloads.
370
436
  - **Webhook** — \`verify-built-workflow\` with \`inputData\` as the body payload, e.g. \`{event: "signup", userId: "..."}\`. Adapter wraps it under \`body\`; downstream expressions use \`$json.body.<field>\`.
371
437
  - **Chat Trigger** — \`verify-built-workflow\` with \`{chatInput: "user message"}\`.
372
438
  - **Other event triggers (Linear, GitHub, Slack, MCP, etc.)** — \`verify-built-workflow\` with \`inputData\` matching the trigger's expected payload shape.
@@ -378,26 +444,44 @@ The system tracks file hashes. If you edit the code and then call \`executions(a
378
444
  ### Resource discovery
379
445
 
380
446
  Before writing code that uses external services, **resolve real resource IDs**:
381
- - Call \`nodes(action="explore-resources")\` for any parameter with searchListMethod when a matching explicit credential is attached (calendars, spreadsheets, channels, models, etc.)
447
+ - Call \`nodes(action="explore-resources")\` for any parameter with searchListMethod (calendars, spreadsheets, channels, models, etc.)
382
448
  - Do NOT use "primary", "default", or any assumed identifier — look up the actual value
383
449
  - Call \`nodes(action="suggested")\` early if the workflow fits a known category (web_app, form_input, data_persistence, etc.) — the pattern hints prevent common mistakes
384
450
  - Check @builderHint annotations in node type definitions for critical configuration guidance
451
+
452
+ ### Publishing
453
+
454
+ Do NOT call \`workflows(action="publish")\` for the main workflow. Publishing is the user's decision after testing. Your job ends at a successful submit. The only exception is sub-workflows in the compositional pattern — those must be published so the parent workflow can reference them.
385
455
  `;
386
456
  function hashContent(content) {
387
457
  return (0, node_crypto_1.createHash)('sha256')
388
458
  .update(content ?? '', 'utf8')
389
459
  .digest('hex');
390
460
  }
391
- function createLinkedAbortController(parentSignal) {
392
- const controller = new AbortController();
393
- if (parentSignal.aborted) {
394
- controller.abort(parentSignal.reason);
395
- return controller;
461
+ function createMainWorkflowSnapshot(content) {
462
+ if (content === null) {
463
+ return { exists: false };
396
464
  }
397
- parentSignal.addEventListener('abort', () => controller.abort(parentSignal.reason), {
398
- once: true,
465
+ return {
466
+ exists: true,
467
+ sourceHash: hashContent(content),
468
+ };
469
+ }
470
+ function shouldFinalSubmitMainWorkflow(input) {
471
+ return (input.current.exists &&
472
+ (!input.initial.exists || input.initial.sourceHash !== input.current.sourceHash));
473
+ }
474
+ function buildNotSubmittedOutcome(workItemId, runId, taskId, finalText, failureSignature = WORKFLOW_NOT_SUBMITTED_FAILURE_SIGNATURE) {
475
+ return withDeterministicRouting({
476
+ workItemId,
477
+ runId,
478
+ taskId,
479
+ submitted: false,
480
+ triggerType: 'manual_or_testable',
481
+ needsUserInput: false,
482
+ failureSignature,
483
+ summary: finalText,
399
484
  });
400
- return controller;
401
485
  }
402
486
  function deterministicSuffix(seed, label, length) {
403
487
  return (0, node_crypto_1.createHash)('sha256')
@@ -534,7 +618,6 @@ async function compactSuccessfulBuilderMemory(input) {
534
618
  await (0, builder_memory_compaction_1.compactBuilderMemoryThread)({
535
619
  context: input.context,
536
620
  binding: input.binding,
537
- sessionId: input.activeBuilderSession?.sessionId,
538
621
  workflowId: input.workflowId,
539
622
  workItemId: input.workItemId,
540
623
  sourceFilePath: input.mainWorkflowPath,
@@ -551,6 +634,26 @@ async function compactSuccessfulBuilderMemory(input) {
551
634
  catch {
552
635
  }
553
636
  }
637
+ async function finalizeSuccessfulMainWorkflowSubmit(input) {
638
+ await promoteMainWorkflow(input.domainContext, input.context.logger, input.mainWorkflowAttempt.workflowId);
639
+ await compactSuccessfulBuilderMemory({
640
+ context: input.context,
641
+ binding: input.binding,
642
+ domainContext: input.domainContext,
643
+ workflowId: input.mainWorkflowAttempt.workflowId,
644
+ workItemId: input.workItemId,
645
+ mainWorkflowPath: input.mainWorkflowPath,
646
+ mainWorkflowAttempt: input.mainWorkflowAttempt,
647
+ lastRequestedChange: input.lastRequestedChange,
648
+ finalText: input.finalText,
649
+ shouldUseBuilderMemory: input.shouldUseBuilderMemory,
650
+ });
651
+ const outcome = await buildOutcomeWithLatestVerification(input.context, input.workItemId, input.taskId, input.mainWorkflowAttempt, input.finalText, supportingWorkflowIdsFromSubmitAttempts(input.submitAttemptHistory, input.mainWorkflowPath, input.mainWorkflowAttempt.workflowId, input.mainWorkflowAttempt.referencedWorkflowIds));
652
+ return {
653
+ text: input.finalText,
654
+ outcome,
655
+ };
656
+ }
554
657
  function resultFromLaterFailedMainSubmit(input) {
555
658
  if (!shouldRecoverSavedWorkflowAfterFailedSubmit(input.failedAttempt))
556
659
  return undefined;
@@ -589,6 +692,126 @@ function formatSubmitWorkflowErrors(output, fallback) {
589
692
  const errors = output.errors?.join(' ') ?? '';
590
693
  return errors.length > 0 ? errors : fallback;
591
694
  }
695
+ async function settleMissingMainWorkflowSubmit(input) {
696
+ const currentSnapshot = createMainWorkflowSnapshot(input.currentMainWorkflow);
697
+ const shouldFinalSubmit = shouldFinalSubmitMainWorkflow({
698
+ initial: input.initialMainWorkflowSnapshot,
699
+ current: currentSnapshot,
700
+ });
701
+ input.context.trackTelemetry?.('Builder finished without submit', {
702
+ thread_id: input.context.threadId,
703
+ run_id: input.runId,
704
+ work_item_id: input.workItemId,
705
+ ...(input.workflowId ? { workflow_id: input.workflowId } : {}),
706
+ has_main_workflow_file: currentSnapshot.exists,
707
+ main_workflow_changed: shouldFinalSubmit,
708
+ final_settlement: shouldFinalSubmit
709
+ ? 'final_submit'
710
+ : input.currentMainWorkflow === null
711
+ ? 'missing_file'
712
+ : 'unchanged_file',
713
+ });
714
+ if (!shouldFinalSubmit) {
715
+ const text = input.currentMainWorkflow === null
716
+ ? 'Error: workflow builder finished without creating or submitting /src/workflow.ts.'
717
+ : 'Error: workflow builder finished without submitting /src/workflow.ts; the file was unchanged from the start of the run.';
718
+ return await reportAndFinalizeBuildResult(input.context, input.workItemId, {
719
+ text,
720
+ outcome: buildNotSubmittedOutcome(input.workItemId, input.runId, input.taskId, text),
721
+ });
722
+ }
723
+ if (!input.submitTool?.handler) {
724
+ const text = 'Error: workflow builder wrote /src/workflow.ts, but submit-workflow was unavailable for final settlement.';
725
+ return await reportAndFinalizeBuildResult(input.context, input.workItemId, {
726
+ text,
727
+ outcome: buildNotSubmittedOutcome(input.workItemId, input.runId, input.taskId, text, WORKFLOW_FINAL_SUBMIT_FAILED_FAILURE_SIGNATURE),
728
+ });
729
+ }
730
+ const attemptsBeforeFinalSubmit = input.submitAttemptHistory.length;
731
+ let finalSubmit;
732
+ try {
733
+ const submitInput = { filePath: input.mainWorkflowPath };
734
+ if (input.workflowId) {
735
+ submitInput.workflowId = input.workflowId;
736
+ }
737
+ finalSubmit = (await input.submitTool.handler(submitInput, {}));
738
+ }
739
+ catch (error) {
740
+ const message = error instanceof Error ? error.message : String(error);
741
+ const recordedAttempt = input.submitAttempts.get(input.mainWorkflowPath);
742
+ if (isFreshAttemptForHash(recordedAttempt, input.currentMainWorkflowHash)) {
743
+ if (recordedAttempt.success) {
744
+ return await input.onSuccessfulSubmit(recordedAttempt);
745
+ }
746
+ if (shouldRecoverSavedWorkflowAfterFailedSubmit(recordedAttempt)) {
747
+ const recovered = resultFromLaterFailedMainSubmit({
748
+ failedAttempt: recordedAttempt,
749
+ submitAttempts: input.submitAttemptHistory,
750
+ mainWorkflowPath: input.mainWorkflowPath,
751
+ workItemId: input.workItemId,
752
+ runId: input.runId,
753
+ taskId: input.taskId,
754
+ });
755
+ if (recovered) {
756
+ return await input.onRecoveredSubmit(recovered);
757
+ }
758
+ }
759
+ const recordedErrors = recordedAttempt.errors?.join(' ') ?? message;
760
+ const text = `Error: final submit of /src/workflow.ts failed. ${recordedErrors}`;
761
+ return await finalizeBuildResult(input.context, input.workItemId, {
762
+ text,
763
+ outcome: buildOutcome(input.workItemId, input.runId, input.taskId, recordedAttempt, text),
764
+ });
765
+ }
766
+ const text = `Error: final submit of /src/workflow.ts failed before recording an attempt. ${message}`;
767
+ const result = {
768
+ text,
769
+ outcome: buildNotSubmittedOutcome(input.workItemId, input.runId, input.taskId, text, WORKFLOW_FINAL_SUBMIT_FAILED_FAILURE_SIGNATURE),
770
+ };
771
+ if (input.submitAttemptHistory.length === attemptsBeforeFinalSubmit) {
772
+ return await reportAndFinalizeBuildResult(input.context, input.workItemId, result);
773
+ }
774
+ return await finalizeBuildResult(input.context, input.workItemId, result);
775
+ }
776
+ const refreshedAttempt = attemptFromAutoResubmit({
777
+ latestAttempt: input.submitAttempts.get(input.mainWorkflowPath),
778
+ resubmit: finalSubmit,
779
+ filePath: input.mainWorkflowPath,
780
+ sourceHash: input.currentMainWorkflowHash,
781
+ });
782
+ if (finalSubmit.success && refreshedAttempt?.success) {
783
+ return await input.onSuccessfulSubmit(refreshedAttempt);
784
+ }
785
+ if (refreshedAttempt &&
786
+ !refreshedAttempt.success &&
787
+ shouldRecoverSavedWorkflowAfterFailedSubmit(refreshedAttempt)) {
788
+ const recovered = resultFromLaterFailedMainSubmit({
789
+ failedAttempt: refreshedAttempt,
790
+ submitAttempts: input.submitAttemptHistory,
791
+ mainWorkflowPath: input.mainWorkflowPath,
792
+ workItemId: input.workItemId,
793
+ runId: input.runId,
794
+ taskId: input.taskId,
795
+ });
796
+ if (recovered) {
797
+ return await input.onRecoveredSubmit(recovered);
798
+ }
799
+ }
800
+ const finalSubmitErrors = refreshedAttempt?.errors?.join(' ') ??
801
+ formatSubmitWorkflowErrors(finalSubmit, 'Final submit did not record a main workflow attempt.');
802
+ const text = `Error: final submit of /src/workflow.ts failed. ${finalSubmitErrors}`;
803
+ const result = {
804
+ text,
805
+ outcome: refreshedAttempt
806
+ ? buildOutcome(input.workItemId, input.runId, input.taskId, refreshedAttempt, text)
807
+ : buildNotSubmittedOutcome(input.workItemId, input.runId, input.taskId, text, WORKFLOW_FINAL_SUBMIT_FAILED_FAILURE_SIGNATURE),
808
+ };
809
+ const reportedMainAttempt = input.submitAttempts.get(input.mainWorkflowPath);
810
+ if (!refreshedAttempt || refreshedAttempt !== reportedMainAttempt) {
811
+ return await reportAndFinalizeBuildResult(input.context, input.workItemId, result);
812
+ }
813
+ return await finalizeBuildResult(input.context, input.workItemId, result);
814
+ }
592
815
  async function startBuildWorkflowAgentTask(context, input) {
593
816
  if (!context.spawnBackgroundTask) {
594
817
  return {
@@ -598,41 +821,42 @@ async function startBuildWorkflowAgentTask(context, input) {
598
821
  };
599
822
  }
600
823
  const spawnBackgroundTask = context.spawnBackgroundTask;
601
- const factory = context.builderSandboxFactory;
824
+ const sharedWorkspace = context.workspace;
602
825
  const domainContext = context.domainContext;
603
- const useSandbox = !!factory && !!domainContext;
826
+ const useSandbox = !!sharedWorkspace && !!domainContext;
604
827
  let builderTools;
605
828
  let prompt = build_workflow_agent_prompt_1.BUILDER_AGENT_PROMPT;
606
- let availableCredentials;
829
+ let credMap;
607
830
  if (useSandbox) {
608
- const credentialSnapshot = await (0, resolve_credentials_1.buildCredentialSnapshot)(domainContext.credentialService);
609
- availableCredentials = credentialSnapshot.list;
831
+ credMap = await (0, resolve_credentials_1.buildCredentialMap)(domainContext.credentialService);
610
832
  const builderWorkflowsTool = createBuilderWorkflowsTool(domainContext);
611
833
  const builderCredentialsTool = createBuilderCredentialsTool(domainContext);
612
- builderTools = {};
834
+ builderTools = (0, tool_registry_1.createToolRegistry)();
613
835
  for (const name of BUILDER_SANDBOX_TOOL_NAMES) {
614
- if (context.domainTools[name]) {
615
- builderTools[name] = context.domainTools[name];
836
+ const tool = context.domainTools.get(name);
837
+ if (tool) {
838
+ builderTools.set(name, tool);
616
839
  }
617
840
  }
618
- builderTools.workflows = builderWorkflowsTool;
619
- builderTools.credentials = builderCredentialsTool;
841
+ builderTools.set('workflows', builderWorkflowsTool);
842
+ builderTools.set(credentials_tool_1.CREDENTIALS_TOOL_ID, builderCredentialsTool);
620
843
  if (context.workflowTaskService && context.domainContext) {
621
- builderTools['verify-built-workflow'] = (0, verify_built_workflow_tool_1.createVerifyBuiltWorkflowTool)(context);
844
+ builderTools.set('verify-built-workflow', (0, verify_built_workflow_tool_1.createVerifyBuiltWorkflowTool)(context));
622
845
  }
623
846
  }
624
847
  else {
625
- builderTools = {};
848
+ builderTools = (0, tool_registry_1.createToolRegistry)();
626
849
  for (const name of BUILDER_TOOL_MODE_TOOL_NAMES) {
627
- if (name in context.domainTools) {
628
- builderTools[name] = context.domainTools[name];
850
+ const tool = context.domainTools.get(name);
851
+ if (tool) {
852
+ builderTools.set(name, tool);
629
853
  }
630
854
  }
631
855
  if (domainContext) {
632
- builderTools.workflows = createBuilderWorkflowsTool(domainContext);
633
- builderTools.credentials = createBuilderCredentialsTool(domainContext);
856
+ builderTools.set('workflows', createBuilderWorkflowsTool(domainContext));
857
+ builderTools.set(credentials_tool_1.CREDENTIALS_TOOL_ID, createBuilderCredentialsTool(domainContext));
634
858
  }
635
- if (!builderTools['build-workflow']) {
859
+ if (!builderTools.has('build-workflow')) {
636
860
  return { result: 'Error: build-workflow tool not available.', taskId: '', agentId: '' };
637
861
  }
638
862
  }
@@ -645,22 +869,17 @@ async function startBuildWorkflowAgentTask(context, input) {
645
869
  deterministicIds?.workItemId ??
646
870
  (input.workflowId ? `${context.runId}:default` : `wi_${(0, nanoid_1.nanoid)(8)}`);
647
871
  const { workflowId } = input;
648
- const reusedBuilderSession = useSandbox && workflowId
649
- ? context.builderSandboxSessionRegistry?.acquireByWorkflowId(context.threadId, workflowId)
650
- : undefined;
651
- const workItemId = reusedBuilderSession?.workItemId ?? baseWorkItemId;
652
- const builderThreadId = reusedBuilderSession?.builderThreadId ?? (0, node_crypto_1.randomUUID)();
653
- const builderResourceId = reusedBuilderSession?.builderResourceId ?? createBuilderResourceId(context.userId);
872
+ const workItemId = baseWorkItemId;
873
+ const relativeMainWorkflowPath = builderWorkflowWorkspaceLayout('', workItemId).relativeMainWorkflowPath;
874
+ const builderThreadId = (0, node_crypto_1.randomUUID)();
875
+ const builderResourceId = (0, agent_persistence_1.createSubAgentResourceId)(context.threadId, 'workflow-builder');
654
876
  const builderMemoryBinding = {
655
877
  resource: builderResourceId,
656
878
  thread: builderThreadId,
657
879
  };
658
880
  let additionalContext = '';
659
- if (reusedBuilderSession && workflowId) {
660
- additionalContext = '';
661
- }
662
- else if (useSandbox && workflowId) {
663
- additionalContext = `[CONTEXT: Modifying existing workflow ${workflowId}. The current code is pre-loaded in ~/workspace/src/workflow.ts — read it first, then edit. Use workflowId "${workflowId}" when calling submit-workflow.]\n\n[WORK ITEM ID: ${workItemId}]`;
881
+ if (useSandbox && workflowId) {
882
+ additionalContext = `[CONTEXT: Modifying existing workflow ${workflowId}. The current code is pre-loaded in ${relativeMainWorkflowPath} — read it first, then edit. Use workflowId "${workflowId}" when calling submit-workflow.]\n\n[WORK ITEM ID: ${workItemId}]`;
664
883
  }
665
884
  else if (useSandbox) {
666
885
  additionalContext = `[WORK ITEM ID: ${workItemId}]`;
@@ -669,451 +888,187 @@ async function startBuildWorkflowAgentTask(context, input) {
669
888
  additionalContext = `[CONTEXT: Modifying existing workflow ${workflowId}. Use workflowId "${workflowId}" when calling build-workflow.]`;
670
889
  }
671
890
  const runningTaskSummaries = context.getRunningTaskSummaries?.();
672
- const briefing = reusedBuilderSession && workflowId
673
- ? buildWarmBuilderFollowUp({
674
- task: input.task,
675
- conversationContext: input.conversationContext,
676
- workflowId,
677
- workItemId,
678
- })
679
- : await (0, sub_agent_briefing_1.buildSubAgentBriefing)({
891
+ const briefing = await (0, sub_agent_briefing_1.buildSubAgentBriefing)({
892
+ task: input.task,
893
+ conversationContext: input.conversationContext,
894
+ additionalContext: additionalContext || undefined,
895
+ requirements: useSandbox ? exports.DETACHED_BUILDER_REQUIREMENTS : undefined,
896
+ iteration: context.iterationLog
897
+ ? {
898
+ log: context.iterationLog,
899
+ threadId: context.threadId,
900
+ taskKey: `build:${workflowId ?? 'new'}`,
901
+ }
902
+ : undefined,
903
+ runningTasks: runningTaskSummaries,
904
+ });
905
+ const detachedTraceFactory = (0, tracing_utils_1.createDetachedSubAgentTraceFactory)(context, {
906
+ agentId: subAgentId,
907
+ role: 'workflow-builder',
908
+ kind: 'builder',
909
+ taskId,
910
+ plannedTaskId: input.plannedTaskId,
911
+ workItemId,
912
+ inputs: {
680
913
  task: input.task,
914
+ workflowId: input.workflowId,
681
915
  conversationContext: input.conversationContext,
682
- additionalContext: additionalContext || undefined,
683
- requirements: useSandbox ? exports.DETACHED_BUILDER_REQUIREMENTS : undefined,
684
- iteration: context.iterationLog
685
- ? {
686
- log: context.iterationLog,
687
- threadId: context.threadId,
688
- taskKey: `build:${workflowId ?? 'new'}`,
689
- }
690
- : undefined,
691
- runningTasks: runningTaskSummaries,
692
- });
693
- let traceContext;
694
- try {
695
- traceContext = await (0, tracing_utils_1.createDetachedSubAgentTracing)(context, {
696
- agentId: subAgentId,
697
- role: 'workflow-builder',
698
- kind: 'builder',
699
- taskId,
700
- plannedTaskId: input.plannedTaskId,
701
- workItemId,
702
- inputs: {
703
- task: input.task,
704
- workflowId: input.workflowId,
705
- conversationContext: input.conversationContext,
706
- },
707
- });
708
- }
709
- catch (error) {
710
- if (reusedBuilderSession) {
711
- void context.builderSandboxSessionRegistry?.release(reusedBuilderSession.sessionId, {
712
- keep: true,
713
- reason: 'trace_setup_failed',
714
- });
715
- }
716
- throw error;
717
- }
718
- let spawnOutcome;
719
- try {
720
- spawnOutcome = spawnBackgroundTask({
721
- taskId,
722
- threadId: context.threadId,
723
- agentId: subAgentId,
916
+ },
917
+ });
918
+ const createTraceContext = async () => await detachedTraceFactory();
919
+ const spawnOutcome = spawnBackgroundTask({
920
+ taskId,
921
+ threadId: context.threadId,
922
+ agentId: subAgentId,
923
+ role: 'workflow-builder',
924
+ createTraceContext,
925
+ plannedTaskId: input.plannedTaskId,
926
+ workItemId,
927
+ dedupeKey: {
724
928
  role: 'workflow-builder',
725
- traceContext,
726
929
  plannedTaskId: input.plannedTaskId,
727
- workItemId,
728
- dedupeKey: {
729
- role: 'workflow-builder',
730
- plannedTaskId: input.plannedTaskId,
731
- workflowId: input.workflowId,
732
- },
733
- parentCheckpointId: context.isCheckpointFollowUp === true ? context.checkpointTaskId : undefined,
734
- run: async (signal, drainCorrections, waitForCorrection) => await (0, tracing_utils_1.withTraceContextActor)(traceContext, async () => {
735
- let builderWs;
736
- let activeBuilderSession = reusedBuilderSession;
930
+ workflowId: input.workflowId,
931
+ },
932
+ parentCheckpointId: context.isCheckpointFollowUp === true ? context.checkpointTaskId : undefined,
933
+ run: async (signal, drainCorrections, waitForCorrection, { traceContext }) => await (0, tracing_utils_1.withTraceContextActor)(traceContext, async () => {
934
+ const submitAttempts = new Map();
935
+ const submitAttemptHistory = [];
936
+ if (useSandbox && sharedWorkspace && domainContext) {
937
+ let workspace = sharedWorkspace;
938
+ const root = await (0, sandbox_setup_1.getWorkspaceRoot)(workspace);
939
+ const materializedRuntimeSkills = await materializeBuilderRuntimeSkills(context, workspace, root);
940
+ workspace = materializedRuntimeSkills.workspace;
941
+ const runtimeSkills = materializedRuntimeSkills.source;
942
+ const builderLayout = builderWorkflowWorkspaceLayout(root, workItemId);
737
943
  let telemetrySession;
738
- let telemetryWorkspace;
739
- const submitAttempts = new Map();
740
- const submitAttemptHistory = [];
741
- const builderAbortController = createLinkedAbortController(signal);
742
- const terminalRemediationGuard = (0, workflow_loop_1.createTerminalRemediationGuard)((remediation) => {
743
- context.trackTelemetry?.('Builder terminal remediation reached', {
744
- thread_id: context.threadId,
745
- run_id: context.runId,
746
- work_item_id: workItemId,
747
- category: remediation.category,
748
- attempt_count: remediation.attemptCount,
749
- reason: remediation.reason,
750
- });
751
- builderAbortController.abort(new Error(remediation.guidance));
752
- });
753
- let clearFilesystemMutationGuard;
944
+ let unsubscribeTelemetry;
754
945
  try {
755
- if (useSandbox) {
756
- let workspace;
757
- let root;
758
- if (activeBuilderSession) {
759
- workspace = activeBuilderSession.workspace;
760
- root = activeBuilderSession.root;
761
- }
762
- else {
763
- builderWs = await factory.create(subAgentId, domainContext);
764
- workspace = builderWs.workspace;
765
- root = await (0, sandbox_setup_1.getWorkspaceRoot)(workspace);
766
- }
767
- telemetrySession = (0, template_telemetry_1.createTemplateTelemetrySession)({
768
- context,
769
- threadId: context.threadId,
770
- runId: context.runId,
771
- workItemId,
772
- userRequestExcerpt: input.task,
773
- });
774
- telemetryWorkspace = workspace;
775
- (0, template_telemetry_1.attachTemplateTelemetrySession)(workspace, telemetrySession);
776
- const templateToolObserver = (0, template_telemetry_1.createTypedToolObserver)(telemetrySession);
777
- prompt = (0, build_workflow_agent_prompt_1.createSandboxBuilderAgentPrompt)(root);
778
- if (!activeBuilderSession && builderWs) {
779
- activeBuilderSession = context.builderSandboxSessionRegistry?.create({
780
- threadId: context.threadId,
781
- workflowId,
782
- workItemId,
783
- builderThreadId,
784
- builderResourceId,
785
- builderWorkspace: builderWs,
786
- root,
787
- });
788
- }
789
- if (!reusedBuilderSession && workflowId && domainContext) {
790
- try {
791
- const json = await domainContext.workflowService.getAsWorkflowJSON(workflowId);
792
- const rawCode = (0, workflow_sdk_1.generateWorkflowCode)(json);
793
- const code = `${extract_code_1.SDK_IMPORT_STATEMENT}\n\n${rawCode}`;
794
- if (workspace.filesystem) {
795
- await workspace.filesystem.writeFile(`${root}/src/workflow.ts`, code, {
796
- recursive: true,
797
- });
798
- }
799
- }
800
- catch {
801
- }
802
- }
803
- const mainWorkflowPath = `${root}/src/workflow.ts`;
804
- const setFilesystemMutationGuard = activeBuilderSession?.setFilesystemMutationGuard ??
805
- builderWs?.setFilesystemMutationGuard;
806
- if (setFilesystemMutationGuard) {
807
- setFilesystemMutationGuard(() => terminalRemediationGuard.get());
808
- clearFilesystemMutationGuard = () => setFilesystemMutationGuard(undefined);
809
- }
810
- const finishTerminalRemediation = async (remediation) => {
811
- const terminalResult = resultFromTerminalRemediation({
812
- remediation,
813
- submitAttempts: submitAttemptHistory,
814
- mainWorkflowPath,
815
- workItemId,
816
- runId: context.runId,
817
- taskId,
818
- });
819
- if (terminalResult.outcome.submitted && terminalResult.outcome.workflowId) {
820
- await promoteMainWorkflow(domainContext, context.logger, terminalResult.outcome.workflowId);
821
- }
822
- return await finalizeBuildResult(context, workItemId, terminalResult);
823
- };
824
- builderTools['submit-workflow'] = (0, submit_workflow_identity_1.createIdentityEnforcedSubmitWorkflowTool)({
825
- context: domainContext,
826
- workspace,
827
- availableCredentials,
828
- root,
829
- currentRunId: context.runId,
830
- tracingRoot: traceContext?.rootRun,
831
- getWorkflowLoopState: async () => await context.workflowTaskService?.getWorkflowLoopState(workItemId),
832
- getTerminalRemediation: () => terminalRemediationGuard.get(),
833
- onGuardFired: (event) => {
834
- context.trackTelemetry?.('Builder remediation guard fired', {
835
- thread_id: context.threadId,
836
- run_id: context.runId,
837
- work_item_id: workItemId,
838
- workflow_id: event.workflowId,
839
- category: event.category,
840
- attempt_count: event.attemptCount,
841
- reason: event.reason,
842
- });
843
- },
844
- onTerminalRemediation: (remediation) => {
845
- terminalRemediationGuard.record(remediation);
846
- },
847
- onAttempt: async (attempt) => {
848
- submitAttempts.set(attempt.filePath, attempt);
849
- submitAttemptHistory.push(attempt);
850
- if (attempt.filePath !== mainWorkflowPath) {
851
- return;
852
- }
853
- if (attempt.success && attempt.workflowId && activeBuilderSession) {
854
- context.builderSandboxSessionRegistry?.aliasWorkflowId(activeBuilderSession.sessionId, attempt.workflowId);
855
- }
856
- if (!context.workflowTaskService) {
857
- return;
858
- }
859
- await context.workflowTaskService.reportBuildOutcome(buildOutcome(workItemId, context.runId, taskId, attempt, attempt.success
860
- ? 'Workflow submitted and ready for verification.'
861
- : (attempt.errors?.join(' ') ?? 'Workflow submission failed.'), supportingWorkflowIdsFromSubmitAttempts(submitAttemptHistory, mainWorkflowPath, attempt.workflowId, attempt.referencedWorkflowIds)));
862
- },
863
- });
864
- const tracedBuilderTools = (0, tracing_utils_1.traceSubAgentTools)(context, builderTools, 'workflow-builder');
865
- const shouldUseBuilderMemory = activeBuilderSession
866
- ? await ensureBuilderMemoryThread(context, builderMemoryBinding)
867
- : false;
868
- const subAgent = new agent_1.Agent({
869
- id: subAgentId,
870
- name: 'Workflow Builder Agent',
871
- instructions: {
872
- role: 'system',
873
- content: prompt,
874
- providerOptions: {
875
- anthropic: { cacheControl: { type: 'ephemeral' } },
876
- },
877
- },
878
- model: context.modelId,
879
- tools: tracedBuilderTools,
880
- workspace,
881
- memory: shouldUseBuilderMemory ? context.memory : undefined,
882
- });
883
- (0, langsmith_tracing_1.mergeTraceRunInputs)(traceContext?.actorRun, (0, langsmith_tracing_1.buildAgentTraceInputs)({
884
- systemPrompt: prompt,
885
- tools: tracedBuilderTools,
886
- modelId: context.modelId,
887
- }));
888
- (0, register_with_mastra_1.registerWithMastra)(subAgentId, subAgent, context.storage);
889
- const traceParent = (0, langsmith_tracing_1.getTraceParentRun)();
890
- let finalText;
946
+ telemetrySession = (0, template_telemetry_1.createTemplateTelemetrySession)({
947
+ context,
948
+ threadId: context.threadId,
949
+ runId: context.runId,
950
+ workItemId,
951
+ userRequestExcerpt: input.task,
952
+ templatesVersion: domainContext.templatesService?.getVersion() ?? null,
953
+ });
954
+ (0, template_telemetry_1.attachTemplateTelemetrySession)(workspace, telemetrySession);
955
+ const templateToolObserver = (0, template_telemetry_1.createTypedToolObserver)(telemetrySession);
956
+ unsubscribeTelemetry = context.eventBus.subscribe(context.threadId, (stored) => {
957
+ if (stored.event.agentId !== subAgentId)
958
+ return;
959
+ templateToolObserver(stored.event);
960
+ });
961
+ prompt = (0, build_workflow_agent_prompt_1.createSandboxBuilderAgentPrompt)(root, {
962
+ mainWorkflowPath: builderLayout.mainWorkflowPath,
963
+ sourceDir: builderLayout.sourceDir,
964
+ chunksDir: builderLayout.chunksDir,
965
+ tsconfigPath: builderLayout.tsconfigPath,
966
+ });
967
+ await writeBuilderWorkspaceFile(workspace, builderLayout.tsconfigPath, renderBuilderTaskTsconfig());
968
+ if (workflowId) {
891
969
  try {
892
- const hitlResult = await (0, langsmith_tracing_1.withTraceParentContext)(traceParent, async () => {
893
- const llmStepTraceHooks = (0, resumable_stream_executor_1.createLlmStepTraceHooks)(traceParent);
894
- const resumeOptions = {
895
- modelSettings: { temperature: model_settings_1.TEMPERATURE.BUILDER },
896
- providerOptions: {
897
- anthropic: { cacheControl: { type: 'ephemeral' } },
898
- },
899
- ...(shouldUseBuilderMemory
900
- ? { memory: builderMemoryBinding, savePerStep: true }
901
- : {}),
902
- };
903
- const stream = await subAgent.stream(briefing, {
904
- maxSteps: max_steps_1.MAX_STEPS.BUILDER,
905
- abortSignal: builderAbortController.signal,
906
- modelSettings: { temperature: model_settings_1.TEMPERATURE.BUILDER },
907
- providerOptions: {
908
- anthropic: { cacheControl: { type: 'ephemeral' } },
909
- },
910
- ...(shouldUseBuilderMemory
911
- ? { memory: builderMemoryBinding, savePerStep: true }
912
- : {}),
913
- ...(llmStepTraceHooks?.executionOptions ?? {}),
914
- });
915
- return await (0, consume_with_hitl_1.consumeStreamWithHitl)({
916
- agent: subAgent,
917
- stream: stream,
918
- runId: context.runId,
919
- agentId: subAgentId,
920
- eventBus: context.eventBus,
921
- logger: context.logger,
922
- threadId: context.threadId,
923
- abortSignal: builderAbortController.signal,
924
- waitForConfirmation: context.waitForConfirmation,
925
- drainCorrections,
926
- waitForCorrection,
927
- onActivity: () => context.touchBackgroundTask?.(taskId),
928
- llmStepTraceHooks,
929
- maxSteps: max_steps_1.MAX_STEPS.BUILDER,
930
- resumeOptions,
931
- onStreamEvent: templateToolObserver,
932
- });
933
- });
934
- const terminalRemediation = terminalRemediationGuard.get();
935
- if (terminalRemediation) {
936
- return await finishTerminalRemediation(terminalRemediation);
937
- }
938
- finalText = await hitlResult.text;
970
+ const json = await domainContext.workflowService.getAsWorkflowJSON(workflowId);
971
+ const rawCode = (0, workflow_sdk_1.generateWorkflowCode)(json);
972
+ const code = `${extract_code_1.SDK_IMPORT_STATEMENT}\n\n${rawCode}`;
973
+ await writeBuilderWorkspaceFile(workspace, builderLayout.mainWorkflowPath, code);
939
974
  }
940
- catch (error) {
941
- const terminalRemediation = terminalRemediationGuard.get();
942
- if (terminalRemediation) {
943
- return await finishTerminalRemediation(terminalRemediation);
944
- }
945
- const recovered = resultFromPostStreamError({
946
- error,
947
- submitAttempts: submitAttemptHistory,
948
- mainWorkflowPath,
949
- workItemId,
950
- runId: context.runId,
951
- taskId,
952
- });
953
- if (recovered) {
954
- await promoteMainWorkflow(domainContext, context.logger, recovered.outcome.workflowId);
955
- return await finalizeBuildResult(context, workItemId, recovered);
956
- }
957
- throw error;
958
- }
959
- const terminalRemediation = terminalRemediationGuard.get();
960
- if (terminalRemediation) {
961
- return await finishTerminalRemediation(terminalRemediation);
975
+ catch {
962
976
  }
963
- const mainWorkflowAttempt = submitAttempts.get(mainWorkflowPath);
964
- const currentMainWorkflow = await (0, sandbox_fs_1.readFileViaSandbox)(workspace, mainWorkflowPath);
965
- const currentMainWorkflowHash = hashContent(currentMainWorkflow);
966
- if (!mainWorkflowAttempt) {
967
- const text = 'Error: workflow builder finished without submitting /src/workflow.ts.';
968
- return {
969
- text,
970
- outcome: buildOutcome(workItemId, context.runId, taskId, undefined, text),
971
- };
972
- }
973
- if (!mainWorkflowAttempt.success) {
974
- const recovered = resultFromLaterFailedMainSubmit({
975
- failedAttempt: mainWorkflowAttempt,
976
- submitAttempts: submitAttemptHistory,
977
- mainWorkflowPath,
978
- workItemId,
979
- runId: context.runId,
980
- taskId,
977
+ }
978
+ else {
979
+ await writeBuilderWorkspaceFile(workspace, builderLayout.mainWorkflowPath, `${extract_code_1.SDK_IMPORT_STATEMENT}\n\n`);
980
+ }
981
+ const mainWorkflowPath = builderLayout.mainWorkflowPath;
982
+ const initialMainWorkflowSnapshot = createMainWorkflowSnapshot(await (0, sandbox_fs_1.readFileViaSandbox)(workspace, mainWorkflowPath));
983
+ builderTools.set('submit-workflow', (0, submit_workflow_identity_1.createIdentityEnforcedSubmitWorkflowTool)({
984
+ context: domainContext,
985
+ workspace,
986
+ credentialMap: credMap,
987
+ root,
988
+ defaultFilePath: mainWorkflowPath,
989
+ currentRunId: context.runId,
990
+ getWorkflowLoopState: async () => await context.workflowTaskService?.getWorkflowLoopState(workItemId),
991
+ onGuardFired: (event) => {
992
+ context.trackTelemetry?.('Builder remediation guard fired', {
993
+ thread_id: context.threadId,
994
+ run_id: context.runId,
995
+ work_item_id: workItemId,
996
+ workflow_id: event.workflowId,
997
+ category: event.category,
998
+ attempt_count: event.attemptCount,
999
+ reason: event.reason,
981
1000
  });
982
- if (recovered) {
983
- await promoteMainWorkflow(domainContext, context.logger, recovered.outcome.workflowId);
984
- return await finalizeBuildResult(context, workItemId, recovered);
1001
+ },
1002
+ onAttempt: async (attempt) => {
1003
+ submitAttempts.set(attempt.filePath, attempt);
1004
+ submitAttemptHistory.push(attempt);
1005
+ if (attempt.filePath !== mainWorkflowPath) {
1006
+ return;
985
1007
  }
986
- const errorText = mainWorkflowAttempt.errors?.join(' ') ?? 'Unknown submit-workflow failure.';
987
- const text = `Error: workflow builder stopped after a failed submit-workflow for /src/workflow.ts. ${errorText}`;
988
- return {
989
- text,
990
- outcome: buildOutcome(workItemId, context.runId, taskId, mainWorkflowAttempt, text),
991
- };
992
- }
993
- if (mainWorkflowAttempt.sourceHash !== currentMainWorkflowHash) {
994
- const submitTool = tracedBuilderTools['submit-workflow'];
995
- if (submitTool && 'execute' in submitTool) {
996
- const resubmit = await submitTool.execute({
997
- filePath: mainWorkflowPath,
998
- workflowId: mainWorkflowAttempt.workflowId,
999
- });
1000
- const refreshedAttempt = attemptFromAutoResubmit({
1001
- latestAttempt: submitAttempts.get(mainWorkflowPath),
1002
- resubmit,
1003
- filePath: mainWorkflowPath,
1004
- sourceHash: currentMainWorkflowHash,
1005
- });
1006
- if (resubmit.success && refreshedAttempt?.success) {
1007
- await promoteMainWorkflow(domainContext, context.logger, refreshedAttempt.workflowId);
1008
- await compactSuccessfulBuilderMemory({
1009
- context,
1010
- binding: builderMemoryBinding,
1011
- activeBuilderSession,
1012
- domainContext,
1013
- workflowId: refreshedAttempt.workflowId,
1014
- workItemId,
1015
- mainWorkflowPath,
1016
- mainWorkflowAttempt: refreshedAttempt,
1017
- lastRequestedChange: input.task,
1018
- finalText,
1019
- shouldUseBuilderMemory,
1020
- });
1021
- const outcome = await buildOutcomeWithLatestVerification(context, workItemId, taskId, refreshedAttempt, finalText, supportingWorkflowIdsFromSubmitAttempts(submitAttemptHistory, mainWorkflowPath, refreshedAttempt.workflowId, refreshedAttempt.referencedWorkflowIds));
1022
- return {
1023
- text: finalText,
1024
- outcome,
1025
- };
1026
- }
1027
- const resubmitErrors = refreshedAttempt?.errors?.join(' ') ??
1028
- formatSubmitWorkflowErrors(resubmit, 'Auto-re-submit failed.');
1029
- if (refreshedAttempt &&
1030
- !refreshedAttempt.success &&
1031
- shouldRecoverSavedWorkflowAfterFailedSubmit(refreshedAttempt)) {
1032
- const recovered = resultFromLaterFailedMainSubmit({
1033
- failedAttempt: refreshedAttempt,
1034
- submitAttempts: submitAttemptHistory,
1035
- mainWorkflowPath,
1036
- workItemId,
1037
- runId: context.runId,
1038
- taskId,
1039
- });
1040
- if (recovered) {
1041
- await promoteMainWorkflow(domainContext, context.logger, recovered.outcome.workflowId);
1042
- return await finalizeBuildResult(context, workItemId, recovered);
1043
- }
1044
- }
1045
- const text = `Error: auto-re-submit of edited /src/workflow.ts failed. ${resubmitErrors}`;
1046
- return {
1047
- text,
1048
- outcome: buildOutcome(workItemId, context.runId, taskId, refreshedAttempt ?? undefined, text),
1049
- };
1008
+ if (!context.workflowTaskService) {
1009
+ return;
1050
1010
  }
1051
- }
1052
- await promoteMainWorkflow(domainContext, context.logger, mainWorkflowAttempt.workflowId);
1053
- await compactSuccessfulBuilderMemory({
1054
- context,
1055
- binding: builderMemoryBinding,
1056
- activeBuilderSession,
1057
- domainContext,
1058
- workflowId: mainWorkflowAttempt.workflowId,
1059
- workItemId,
1060
- mainWorkflowPath,
1061
- mainWorkflowAttempt,
1062
- lastRequestedChange: input.task,
1063
- finalText,
1064
- shouldUseBuilderMemory,
1065
- });
1066
- const outcome = await buildOutcomeWithLatestVerification(context, workItemId, taskId, mainWorkflowAttempt, finalText, supportingWorkflowIdsFromSubmitAttempts(submitAttemptHistory, mainWorkflowPath, mainWorkflowAttempt.workflowId, mainWorkflowAttempt.referencedWorkflowIds));
1067
- return {
1068
- text: finalText,
1069
- outcome,
1070
- };
1071
- }
1072
- let fallbackMainWorkflowId;
1073
- recordSuccessfulWorkflowBuilds(builderTools['build-workflow'], (workflowId) => {
1074
- fallbackMainWorkflowId = workflowId;
1075
- });
1011
+ await context.workflowTaskService.reportBuildOutcome(buildOutcome(workItemId, context.runId, taskId, attempt, attempt.success
1012
+ ? 'Workflow submitted and ready for verification.'
1013
+ : (attempt.errors?.join(' ') ?? 'Workflow submission failed.')));
1014
+ },
1015
+ }));
1076
1016
  const tracedBuilderTools = (0, tracing_utils_1.traceSubAgentTools)(context, builderTools, 'workflow-builder');
1077
- const subAgent = new agent_1.Agent({
1078
- id: subAgentId,
1079
- name: 'Workflow Builder Agent',
1080
- instructions: {
1081
- role: 'system',
1082
- content: prompt,
1083
- providerOptions: {
1084
- anthropic: { cacheControl: { type: 'ephemeral' } },
1085
- },
1017
+ const runtimeWorkspaceTools = toToolRegistry(workspace.getTools());
1018
+ const builderMemory = getBuilderSessionMemory(context, true);
1019
+ const shouldUseBuilderMemory = Boolean(builderMemory);
1020
+ const subAgent = new agents_1.Agent('Workflow Builder Agent')
1021
+ .model(context.modelId)
1022
+ .instructions(prompt, {
1023
+ providerOptions: {
1024
+ anthropic: { cacheControl: { type: 'ephemeral' } },
1086
1025
  },
1087
- model: context.modelId,
1088
- tools: tracedBuilderTools,
1026
+ })
1027
+ .tool((0, tool_registry_1.toolRegistryValues)(tracedBuilderTools))
1028
+ .checkpoint(context.checkpointStore ?? 'memory');
1029
+ (0, runtime_workspace_1.attachRuntimeWorkspaceCapabilities)(subAgent, { workspace, runtimeSkills });
1030
+ if (builderMemory) {
1031
+ subAgent.memory(builderMemory);
1032
+ }
1033
+ const telemetry = traceContext?.getTelemetry?.({
1034
+ agentRole: 'workflow-builder',
1035
+ functionId: 'instance-ai.subagent.workflow-builder',
1036
+ executionMode: 'background_subagent',
1037
+ metadata: { agent_id: subAgentId, task_id: taskId },
1089
1038
  });
1039
+ if (telemetry) {
1040
+ subAgent.telemetry(telemetry);
1041
+ }
1090
1042
  (0, langsmith_tracing_1.mergeTraceRunInputs)(traceContext?.actorRun, (0, langsmith_tracing_1.buildAgentTraceInputs)({
1091
1043
  systemPrompt: prompt,
1092
1044
  tools: tracedBuilderTools,
1045
+ runtimeTools: runtimeWorkspaceTools,
1046
+ runtimeSkills: runtimeSkills?.registry,
1093
1047
  modelId: context.modelId,
1094
1048
  }));
1095
- (0, register_with_mastra_1.registerWithMastra)(subAgentId, subAgent, context.storage);
1096
- const traceParent = (0, langsmith_tracing_1.getTraceParentRun)();
1097
- const hitlResult = await (0, langsmith_tracing_1.withTraceParentContext)(traceParent, async () => {
1098
- const llmStepTraceHooks = (0, resumable_stream_executor_1.createLlmStepTraceHooks)(traceParent);
1049
+ let finalText;
1050
+ try {
1051
+ const persistence = await (0, agent_persistence_1.createSubAgentPersistence)(context, {
1052
+ agentKind: 'workflow-builder',
1053
+ threadId: builderThreadId,
1054
+ resourceId: builderResourceId,
1055
+ });
1099
1056
  const resumeOptions = {
1100
- modelSettings: { temperature: model_settings_1.TEMPERATURE.BUILDER },
1101
1057
  providerOptions: {
1102
1058
  anthropic: { cacheControl: { type: 'ephemeral' } },
1103
1059
  },
1104
1060
  };
1105
1061
  const stream = await subAgent.stream(briefing, {
1106
- maxSteps: max_steps_1.MAX_STEPS.BUILDER,
1062
+ maxIterations: max_steps_1.MAX_STEPS.BUILDER,
1107
1063
  abortSignal: signal,
1108
- modelSettings: { temperature: model_settings_1.TEMPERATURE.BUILDER },
1064
+ persistence,
1109
1065
  providerOptions: {
1110
1066
  anthropic: { cacheControl: { type: 'ephemeral' } },
1111
1067
  },
1112
- ...(llmStepTraceHooks?.executionOptions ?? {}),
1113
1068
  });
1114
- return await (0, consume_with_hitl_1.consumeStreamWithHitl)({
1069
+ const hitlResult = await (0, consume_with_hitl_1.consumeStreamWithHitl)({
1115
1070
  agent: subAgent,
1116
- stream: stream,
1071
+ stream,
1117
1072
  runId: context.runId,
1118
1073
  agentId: subAgentId,
1119
1074
  eventBus: context.eventBus,
@@ -1123,21 +1078,167 @@ async function startBuildWorkflowAgentTask(context, input) {
1123
1078
  waitForConfirmation: context.waitForConfirmation,
1124
1079
  drainCorrections,
1125
1080
  waitForCorrection,
1126
- onActivity: () => context.touchBackgroundTask?.(taskId),
1127
- llmStepTraceHooks,
1128
- maxSteps: max_steps_1.MAX_STEPS.BUILDER,
1081
+ maxIterations: max_steps_1.MAX_STEPS.BUILDER,
1129
1082
  resumeOptions,
1083
+ persistence,
1084
+ });
1085
+ finalText = await (0, consume_with_hitl_1.requireCompletedHitlText)(hitlResult, 'Workflow builder sub-agent');
1086
+ }
1087
+ catch (error) {
1088
+ const recovered = resultFromPostStreamError({
1089
+ error,
1090
+ submitAttempts: submitAttemptHistory,
1091
+ mainWorkflowPath,
1092
+ workItemId,
1093
+ runId: context.runId,
1094
+ taskId,
1130
1095
  });
1096
+ if (recovered) {
1097
+ await promoteMainWorkflow(domainContext, context.logger, recovered.outcome.workflowId);
1098
+ return await finalizeBuildResult(context, workItemId, recovered);
1099
+ }
1100
+ throw error;
1101
+ }
1102
+ const mainWorkflowAttempt = submitAttempts.get(mainWorkflowPath);
1103
+ const currentMainWorkflow = await (0, sandbox_fs_1.readFileViaSandbox)(workspace, mainWorkflowPath);
1104
+ const currentMainWorkflowHash = hashContent(currentMainWorkflow);
1105
+ if (!mainWorkflowAttempt) {
1106
+ return await settleMissingMainWorkflowSubmit({
1107
+ context,
1108
+ workItemId,
1109
+ runId: context.runId,
1110
+ taskId,
1111
+ workflowId,
1112
+ mainWorkflowPath,
1113
+ initialMainWorkflowSnapshot,
1114
+ currentMainWorkflow,
1115
+ currentMainWorkflowHash,
1116
+ submitTool: tracedBuilderTools.get('submit-workflow'),
1117
+ submitAttempts,
1118
+ submitAttemptHistory,
1119
+ finalText,
1120
+ onSuccessfulSubmit: async (attempt) => await finalizeSuccessfulMainWorkflowSubmit({
1121
+ context,
1122
+ binding: builderMemoryBinding,
1123
+ domainContext,
1124
+ workItemId,
1125
+ taskId,
1126
+ mainWorkflowPath,
1127
+ mainWorkflowAttempt: attempt,
1128
+ submitAttemptHistory,
1129
+ lastRequestedChange: input.task,
1130
+ finalText,
1131
+ shouldUseBuilderMemory,
1132
+ }),
1133
+ onRecoveredSubmit: async (recovered) => {
1134
+ await promoteMainWorkflow(domainContext, context.logger, recovered.outcome.workflowId);
1135
+ return await finalizeBuildResult(context, workItemId, recovered);
1136
+ },
1137
+ });
1138
+ }
1139
+ if (!mainWorkflowAttempt.success) {
1140
+ const recovered = resultFromLaterFailedMainSubmit({
1141
+ failedAttempt: mainWorkflowAttempt,
1142
+ submitAttempts: submitAttemptHistory,
1143
+ mainWorkflowPath,
1144
+ workItemId,
1145
+ runId: context.runId,
1146
+ taskId,
1147
+ });
1148
+ if (recovered) {
1149
+ await promoteMainWorkflow(domainContext, context.logger, recovered.outcome.workflowId);
1150
+ return await finalizeBuildResult(context, workItemId, recovered);
1151
+ }
1152
+ const errorText = mainWorkflowAttempt.errors?.join(' ') ?? 'Unknown submit-workflow failure.';
1153
+ const text = `Error: workflow builder stopped after a failed submit-workflow for ${mainWorkflowPath}. ${errorText}`;
1154
+ return {
1155
+ text,
1156
+ outcome: buildOutcome(workItemId, context.runId, taskId, mainWorkflowAttempt, text),
1157
+ };
1158
+ }
1159
+ if (mainWorkflowAttempt.sourceHash !== currentMainWorkflowHash) {
1160
+ const submitTool = tracedBuilderTools.get('submit-workflow');
1161
+ if (submitTool?.handler) {
1162
+ const resubmit = (await submitTool.handler({
1163
+ filePath: mainWorkflowPath,
1164
+ workflowId: mainWorkflowAttempt.workflowId,
1165
+ }, {}));
1166
+ const refreshedAttempt = attemptFromAutoResubmit({
1167
+ latestAttempt: submitAttempts.get(mainWorkflowPath),
1168
+ resubmit,
1169
+ filePath: mainWorkflowPath,
1170
+ sourceHash: currentMainWorkflowHash,
1171
+ });
1172
+ if (resubmit.success && refreshedAttempt?.success) {
1173
+ await promoteMainWorkflow(domainContext, context.logger, refreshedAttempt.workflowId);
1174
+ await compactSuccessfulBuilderMemory({
1175
+ context,
1176
+ binding: builderMemoryBinding,
1177
+ domainContext,
1178
+ workflowId: refreshedAttempt.workflowId,
1179
+ workItemId,
1180
+ mainWorkflowPath,
1181
+ mainWorkflowAttempt: refreshedAttempt,
1182
+ lastRequestedChange: input.task,
1183
+ finalText,
1184
+ shouldUseBuilderMemory,
1185
+ });
1186
+ const outcome = await buildOutcomeWithLatestVerification(context, workItemId, taskId, refreshedAttempt, finalText);
1187
+ return {
1188
+ text: finalText,
1189
+ outcome,
1190
+ };
1191
+ }
1192
+ const resubmitErrors = refreshedAttempt?.errors?.join(' ') ??
1193
+ formatSubmitWorkflowErrors(resubmit, 'Auto-re-submit failed.');
1194
+ if (refreshedAttempt &&
1195
+ !refreshedAttempt.success &&
1196
+ shouldRecoverSavedWorkflowAfterFailedSubmit(refreshedAttempt)) {
1197
+ const recovered = resultFromLaterFailedMainSubmit({
1198
+ failedAttempt: refreshedAttempt,
1199
+ submitAttempts: submitAttemptHistory,
1200
+ mainWorkflowPath,
1201
+ workItemId,
1202
+ runId: context.runId,
1203
+ taskId,
1204
+ });
1205
+ if (recovered) {
1206
+ await promoteMainWorkflow(domainContext, context.logger, recovered.outcome.workflowId);
1207
+ return await finalizeBuildResult(context, workItemId, recovered);
1208
+ }
1209
+ }
1210
+ const text = `Error: auto-re-submit of edited ${mainWorkflowPath} failed. ${resubmitErrors}`;
1211
+ return {
1212
+ text,
1213
+ outcome: buildOutcome(workItemId, context.runId, taskId, refreshedAttempt ?? undefined, text),
1214
+ };
1215
+ }
1216
+ }
1217
+ await promoteMainWorkflow(domainContext, context.logger, mainWorkflowAttempt.workflowId);
1218
+ await compactSuccessfulBuilderMemory({
1219
+ context,
1220
+ binding: builderMemoryBinding,
1221
+ domainContext,
1222
+ workflowId: mainWorkflowAttempt.workflowId,
1223
+ workItemId,
1224
+ mainWorkflowPath,
1225
+ mainWorkflowAttempt,
1226
+ lastRequestedChange: input.task,
1227
+ finalText,
1228
+ shouldUseBuilderMemory,
1131
1229
  });
1132
- const toolFinalText = await hitlResult.text;
1133
- await promoteMainWorkflow(domainContext, context.logger, fallbackMainWorkflowId);
1134
- return { text: toolFinalText };
1230
+ const outcome = await buildOutcomeWithLatestVerification(context, workItemId, taskId, mainWorkflowAttempt, finalText);
1231
+ return {
1232
+ text: finalText,
1233
+ outcome,
1234
+ };
1135
1235
  }
1136
1236
  finally {
1137
- if (telemetrySession && telemetryWorkspace) {
1237
+ unsubscribeTelemetry?.();
1238
+ if (telemetrySession) {
1138
1239
  try {
1139
1240
  telemetrySession.flush();
1140
- (0, template_telemetry_1.detachTemplateTelemetrySession)(telemetryWorkspace);
1241
+ (0, template_telemetry_1.detachTemplateTelemetrySession)(workspace);
1141
1242
  }
1142
1243
  catch (error) {
1143
1244
  context.logger.warn('build-workflow-agent: failed to flush template telemetry', {
@@ -1145,36 +1246,79 @@ async function startBuildWorkflowAgentTask(context, input) {
1145
1246
  });
1146
1247
  }
1147
1248
  }
1148
- clearFilesystemMutationGuard?.();
1149
- if (activeBuilderSession && context.builderSandboxSessionRegistry) {
1150
- await context.builderSandboxSessionRegistry.release(activeBuilderSession.sessionId, {
1151
- keep: !signal.aborted,
1152
- reason: signal.aborted ? 'aborted' : 'builder_run_finished',
1153
- });
1154
- }
1155
- else {
1156
- await builderWs?.cleanup();
1157
- }
1158
1249
  }
1159
- }),
1160
- });
1161
- }
1162
- catch (error) {
1163
- if (reusedBuilderSession) {
1164
- void context.builderSandboxSessionRegistry?.release(reusedBuilderSession.sessionId, {
1165
- keep: true,
1166
- reason: 'spawn_failed',
1250
+ }
1251
+ let fallbackMainWorkflowId;
1252
+ recordSuccessfulWorkflowBuilds(builderTools.get('build-workflow'), (workflowId) => {
1253
+ fallbackMainWorkflowId = workflowId;
1167
1254
  });
1168
- }
1169
- throw error;
1170
- }
1171
- if (spawnOutcome.status === 'duplicate') {
1172
- if (reusedBuilderSession) {
1173
- void context.builderSandboxSessionRegistry?.release(reusedBuilderSession.sessionId, {
1174
- keep: true,
1175
- reason: 'spawn_duplicate',
1255
+ const tracedBuilderTools = (0, tracing_utils_1.traceSubAgentTools)(context, builderTools, 'workflow-builder');
1256
+ const runtimeSkills = context.runtimeSkills;
1257
+ const subAgent = new agents_1.Agent('Workflow Builder Agent')
1258
+ .model(context.modelId)
1259
+ .instructions(prompt, {
1260
+ providerOptions: {
1261
+ anthropic: { cacheControl: { type: 'ephemeral' } },
1262
+ },
1263
+ })
1264
+ .tool((0, tool_registry_1.toolRegistryValues)(tracedBuilderTools))
1265
+ .checkpoint(context.checkpointStore ?? 'memory');
1266
+ (0, runtime_workspace_1.attachRuntimeWorkspaceCapabilities)(subAgent, { runtimeSkills });
1267
+ const telemetry = traceContext?.getTelemetry?.({
1268
+ agentRole: 'workflow-builder',
1269
+ functionId: 'instance-ai.subagent.workflow-builder',
1270
+ executionMode: 'background_subagent',
1271
+ metadata: { agent_id: subAgentId, task_id: taskId },
1176
1272
  });
1177
- }
1273
+ if (telemetry) {
1274
+ subAgent.telemetry(telemetry);
1275
+ }
1276
+ (0, langsmith_tracing_1.mergeTraceRunInputs)(traceContext?.actorRun, (0, langsmith_tracing_1.buildAgentTraceInputs)({
1277
+ systemPrompt: prompt,
1278
+ tools: tracedBuilderTools,
1279
+ runtimeSkills: runtimeSkills?.registry,
1280
+ modelId: context.modelId,
1281
+ }));
1282
+ const resumeOptions = {
1283
+ providerOptions: {
1284
+ anthropic: { cacheControl: { type: 'ephemeral' } },
1285
+ },
1286
+ };
1287
+ const persistence = await (0, agent_persistence_1.createSubAgentPersistence)(context, {
1288
+ agentKind: 'workflow-builder',
1289
+ threadId: builderThreadId,
1290
+ resourceId: builderResourceId,
1291
+ });
1292
+ const stream = await subAgent.stream(briefing, {
1293
+ maxIterations: max_steps_1.MAX_STEPS.BUILDER,
1294
+ abortSignal: signal,
1295
+ persistence,
1296
+ providerOptions: {
1297
+ anthropic: { cacheControl: { type: 'ephemeral' } },
1298
+ },
1299
+ });
1300
+ const hitlResult = await (0, consume_with_hitl_1.consumeStreamWithHitl)({
1301
+ agent: subAgent,
1302
+ stream,
1303
+ runId: context.runId,
1304
+ agentId: subAgentId,
1305
+ eventBus: context.eventBus,
1306
+ logger: context.logger,
1307
+ threadId: context.threadId,
1308
+ abortSignal: signal,
1309
+ waitForConfirmation: context.waitForConfirmation,
1310
+ drainCorrections,
1311
+ waitForCorrection,
1312
+ maxIterations: max_steps_1.MAX_STEPS.BUILDER,
1313
+ resumeOptions,
1314
+ persistence,
1315
+ });
1316
+ const toolFinalText = await (0, consume_with_hitl_1.requireCompletedHitlText)(hitlResult, 'Workflow builder sub-agent');
1317
+ await promoteMainWorkflow(domainContext, context.logger, fallbackMainWorkflowId);
1318
+ return { text: toolFinalText };
1319
+ }),
1320
+ });
1321
+ if (spawnOutcome.status === 'duplicate') {
1178
1322
  return {
1179
1323
  result: `Workflow build already in progress (task: ${spawnOutcome.existing.taskId}). Acknowledge and wait for the planned-task-follow-up — do not dispatch again.`,
1180
1324
  taskId: spawnOutcome.existing.taskId,
@@ -1182,12 +1326,6 @@ async function startBuildWorkflowAgentTask(context, input) {
1182
1326
  };
1183
1327
  }
1184
1328
  if (spawnOutcome.status === 'limit-reached') {
1185
- if (reusedBuilderSession) {
1186
- void context.builderSandboxSessionRegistry?.release(reusedBuilderSession.sessionId, {
1187
- keep: true,
1188
- reason: 'spawn_limit_reached',
1189
- });
1190
- }
1191
1329
  return {
1192
1330
  result: 'Could not start build: concurrent background-task limit reached. Wait for an existing task to finish and try again.',
1193
1331
  taskId: '',
@@ -1201,7 +1339,7 @@ async function startBuildWorkflowAgentTask(context, input) {
1201
1339
  payload: {
1202
1340
  parentId: context.orchestratorAgentId,
1203
1341
  role: 'workflow-builder',
1204
- tools: Object.keys(builderTools),
1342
+ tools: (0, tool_registry_1.toolRegistryKeys)(builderTools),
1205
1343
  taskId,
1206
1344
  kind: 'builder',
1207
1345
  title: 'Building workflow',
@@ -1273,83 +1411,88 @@ async function resolveWorkflowNameForEditConfirmation(context, workflowId) {
1273
1411
  }
1274
1412
  }
1275
1413
  function createBuildWorkflowAgentTool(context) {
1276
- let consecutivePlanGuardRejections = 0;
1277
- const rejectWithGuard = (message) => {
1278
- consecutivePlanGuardRejections += 1;
1279
- if (consecutivePlanGuardRejections >= PLAN_GUARD_REJECTION_LIMIT) {
1414
+ let planGuardRejectionCount = 0;
1415
+ const rejectPlanGuardCall = (result) => {
1416
+ planGuardRejectionCount++;
1417
+ if (planGuardRejectionCount >= PLAN_GUARD_REJECTION_LIMIT) {
1280
1418
  context.logger.warn('build-workflow-with-agent plan-guard rejection limit reached — aborting run', {
1281
1419
  threadId: context.threadId,
1282
- rejectionCount: consecutivePlanGuardRejections,
1420
+ rejectionCount: planGuardRejectionCount,
1283
1421
  });
1284
1422
  throw new n8n_workflow_1.UserError('Stopped: the agent looped on `build-workflow-with-agent` rejections without correcting them. Try again or rephrase the request.');
1285
1423
  }
1286
- return { result: message, taskId: '' };
1424
+ return { result, taskId: '' };
1287
1425
  };
1288
- return (0, tools_1.createTool)({
1289
- id: 'build-workflow-with-agent',
1290
- description: 'Build or modify an n8n workflow using a specialized builder agent. ' +
1291
- 'The agent handles node discovery, schema lookups, code generation, and validation internally. ' +
1292
- 'For edits to an existing workflow, call directly with `bypassPlan: true`, the existing `workflowId`, and a one-sentence `reason`the orchestrator runs a lightweight verify afterwards. ' +
1293
- 'For new workflows, multi-workflow builds, or data-table schema changes, go through `plan` ' +
1294
- 'a runtime guard rejects direct calls without `bypassPlan: true` outside replan/checkpoint follow-ups, because those paths need the orchestrator-run checkpoint for end-to-end verification.',
1295
- inputSchema: exports.buildWorkflowAgentInputSchema,
1296
- outputSchema: zod_1.z.object({
1297
- result: zod_1.z.string(),
1298
- taskId: zod_1.z.string(),
1299
- }),
1300
- suspendSchema: buildWorkflowAgentSuspendSchema,
1301
- resumeSchema: buildWorkflowAgentResumeSchema,
1302
- execute: async (input, ctx) => {
1303
- const isPostPlanFollowUpRun = isPostPlanFollowUp(context);
1304
- if (isBuildViaPlanGuardEnabled() && !isPostPlanFollowUpRun) {
1305
- if (!input.bypassPlan) {
1306
- context.logger.warn('build-workflow-with-agent called outside plan/replan context — rejecting', {
1307
- threadId: context.threadId,
1308
- hasWorkflowId: Boolean(input.workflowId),
1309
- });
1310
- return rejectWithGuard('STOP. Call `plan` with a `build-workflow` task — do NOT retry this tool. Direct builder calls outside a plan are only allowed for edits to an existing workflow (`bypassPlan: true` + `workflowId` + one-sentence `reason`).');
1311
- }
1312
- if (!input.workflowId) {
1313
- return rejectWithGuard('STOP. `bypassPlan: true` is for edits to an EXISTING workflow only. For new workflows call `plan` with a `build-workflow` task — do NOT retry this tool without a `workflowId`.');
1314
- }
1315
- if (!input.reason || input.reason.trim().length === 0) {
1316
- return rejectWithGuard('STOP. `bypassPlan: true` requires a one-sentence `reason` (e.g. "swap Slack channel"). Retry once with `reason` set; do not retry without it.');
1317
- }
1318
- context.logger.warn('build-workflow-with-agent bypassing plan with bypassPlan=true', {
1426
+ return new agents_1.Tool('build-workflow-with-agent')
1427
+ .description('Build or modify an n8n workflow using a specialized builder agent. ' +
1428
+ 'The agent handles node discovery, schema lookups, code generation, and validation internally. ' +
1429
+ 'For edits to an existing workflow, call directly with `bypassPlan: true`, the existing `workflowId`, and a one-sentence `reason` — the orchestrator runs a lightweight verify afterwards. ' +
1430
+ 'For new workflows, multi-workflow builds, or data-table schema changes, go through `plan` — ' +
1431
+ 'a runtime guard rejects direct calls without `bypassPlan: true` outside replan/checkpoint follow-ups, because those paths need the orchestrator-run checkpoint for end-to-end verification.')
1432
+ .input(exports.buildWorkflowAgentInputSchema)
1433
+ .output(zod_1.z.object({
1434
+ result: zod_1.z.string(),
1435
+ taskId: zod_1.z.string(),
1436
+ }))
1437
+ .suspend(buildWorkflowAgentSuspendSchema)
1438
+ .resume(buildWorkflowAgentResumeSchema)
1439
+ .handler(async (input, ctx) => {
1440
+ const isPostPlanFollowUpRun = isPostPlanFollowUp(context);
1441
+ if (isBuildViaPlanGuardEnabled() && !isPostPlanFollowUpRun) {
1442
+ if (!input.bypassPlan) {
1443
+ context.logger.warn('build-workflow-with-agent called outside plan/replan context — rejecting', {
1319
1444
  threadId: context.threadId,
1320
- workflowId: input.workflowId,
1321
- reason: input.reason,
1445
+ hasWorkflowId: Boolean(input.workflowId),
1322
1446
  });
1447
+ return rejectPlanGuardCall('STOP. Direct builder calls require `bypassPlan: true` + an existing ' +
1448
+ '`workflowId` + a one-sentence `reason`. Use that combination for any edit to ' +
1449
+ 'an existing workflow. For new workflows, multi-workflow builds, or data-table ' +
1450
+ 'schema changes, call `plan` with a `build-workflow` task instead — the planner ' +
1451
+ 'discovers credentials, data tables, and best practices, and schedules an ' +
1452
+ 'orchestrator-run verification checkpoint.');
1453
+ }
1454
+ if (!input.workflowId) {
1455
+ return rejectPlanGuardCall('STOP. `bypassPlan: true` is for edits to an EXISTING workflow and requires a ' +
1456
+ '`workflowId`. New workflow builds must go through `plan` so an orchestrator-run ' +
1457
+ 'verification checkpoint is scheduled. Call `plan` with a `build-workflow` task ' +
1458
+ 'instead.');
1459
+ }
1460
+ if (!input.reason || input.reason.trim().length === 0) {
1461
+ return rejectPlanGuardCall('STOP. `bypassPlan: true` requires a one-sentence `reason` describing the edit ' +
1462
+ '(e.g. "swap Slack channel", "fix Code node shape issue").');
1463
+ }
1464
+ context.logger.warn('build-workflow-with-agent bypassing plan with bypassPlan=true', {
1465
+ threadId: context.threadId,
1466
+ workflowId: input.workflowId,
1467
+ reason: input.reason,
1468
+ });
1469
+ }
1470
+ planGuardRejectionCount = 0;
1471
+ if (input.workflowId && !isPostPlanFollowUpRun && context.domainContext) {
1472
+ const updateWorkflowPermission = context.domainContext.permissions?.updateWorkflow ?? 'require_approval';
1473
+ if (updateWorkflowPermission === 'blocked') {
1474
+ return { result: 'Action blocked by admin', taskId: '' };
1323
1475
  }
1324
- if (input.workflowId && !isPostPlanFollowUpRun && context.domainContext) {
1325
- const updateWorkflowPermission = context.domainContext.permissions?.updateWorkflow ?? 'require_approval';
1326
- if (updateWorkflowPermission === 'blocked') {
1327
- return { result: 'Action blocked by admin', taskId: '' };
1476
+ const isOwnInFlightWorkflow = context.domainContext.aiCreatedWorkflowIds?.has(input.workflowId) ?? false;
1477
+ if (!isOwnInFlightWorkflow) {
1478
+ const resumeData = ctx.resumeData;
1479
+ const needsApproval = updateWorkflowPermission !== 'always_allow';
1480
+ if (needsApproval && (resumeData === undefined || resumeData === null)) {
1481
+ const workflowName = await resolveWorkflowNameForEditConfirmation(context, input.workflowId);
1482
+ return await ctx.suspend({
1483
+ requestId: (0, nanoid_1.nanoid)(),
1484
+ message: `Edit ${workflowName} (ID: ${input.workflowId})`,
1485
+ severity: 'warning',
1486
+ });
1328
1487
  }
1329
- const isOwnInFlightWorkflow = context.domainContext.aiCreatedWorkflowIds?.has(input.workflowId) ?? false;
1330
- if (!isOwnInFlightWorkflow) {
1331
- const resumeData = ctx?.agent?.resumeData;
1332
- const suspend = ctx?.agent?.suspend;
1333
- const needsApproval = updateWorkflowPermission !== 'always_allow';
1334
- if (needsApproval && (resumeData === undefined || resumeData === null)) {
1335
- const workflowName = await resolveWorkflowNameForEditConfirmation(context, input.workflowId);
1336
- const reason = input.reason?.trim();
1337
- await suspend?.({
1338
- requestId: (0, nanoid_1.nanoid)(),
1339
- message: `Edit existing workflow "${workflowName}" (ID: ${input.workflowId})?${reason ? ` Reason: ${reason}` : ''}`,
1340
- severity: 'warning',
1341
- });
1342
- return { result: '', taskId: '' };
1343
- }
1344
- if (resumeData !== undefined && resumeData !== null && !resumeData.approved) {
1345
- return { result: 'User declined the workflow edit.', taskId: '' };
1346
- }
1488
+ if (resumeData !== undefined && resumeData !== null && !resumeData.approved) {
1489
+ return { result: 'User declined the workflow edit.', taskId: '' };
1347
1490
  }
1348
1491
  }
1349
- consecutivePlanGuardRejections = 0;
1350
- const result = await startBuildWorkflowAgentTask(context, input);
1351
- return { result: result.result, taskId: result.taskId };
1352
- },
1353
- });
1492
+ }
1493
+ const result = await startBuildWorkflowAgentTask(context, input);
1494
+ return { result: result.result, taskId: result.taskId };
1495
+ })
1496
+ .build();
1354
1497
  }
1355
1498
  //# sourceMappingURL=build-workflow-agent.tool.js.map