@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.
- package/dist/agent/instance-agent.d.ts +1 -1
- package/dist/agent/instance-agent.js +88 -75
- package/dist/agent/instance-agent.js.map +1 -1
- package/dist/agent/mcp-tool-name-validation.d.ts +4 -2
- package/dist/agent/mcp-tool-name-validation.js +2 -2
- package/dist/agent/mcp-tool-name-validation.js.map +1 -1
- package/dist/agent/runtime-workspace.d.ts +6 -0
- package/dist/agent/runtime-workspace.js +14 -0
- package/dist/agent/runtime-workspace.js.map +1 -0
- package/dist/agent/sanitize-mcp-schemas.d.ts +4 -3
- package/dist/agent/sanitize-mcp-schemas.js +53 -24
- package/dist/agent/sanitize-mcp-schemas.js.map +1 -1
- package/dist/agent/sub-agent-debriefing.d.ts +2 -2
- package/dist/agent/sub-agent-factory.d.ts +7 -4
- package/dist/agent/sub-agent-factory.js +24 -13
- package/dist/agent/sub-agent-factory.js.map +1 -1
- package/dist/agent/system-prompt.js +18 -15
- package/dist/agent/system-prompt.js.map +1 -1
- package/dist/build.tsbuildinfo +1 -1
- package/dist/constants/max-steps.d.ts +1 -1
- package/dist/constants/max-steps.js +1 -1
- package/dist/constants/max-steps.js.map +1 -1
- package/dist/domain-access/domain-gating.d.ts +2 -2
- package/dist/error-formatting.d.ts +1 -0
- package/dist/error-formatting.js +159 -0
- package/dist/error-formatting.js.map +1 -0
- package/dist/index.d.ts +65 -24
- package/dist/index.js +96 -52
- package/dist/index.js.map +1 -1
- package/dist/mcp/mcp-client-manager.d.ts +5 -4
- package/dist/mcp/mcp-client-manager.js +42 -17
- package/dist/mcp/mcp-client-manager.js.map +1 -1
- package/dist/memory/title-utils.d.ts +4 -1
- package/dist/memory/title-utils.js +10 -2
- package/dist/memory/title-utils.js.map +1 -1
- package/dist/parsers/structured-file-parser.d.ts +5 -2
- package/dist/parsers/structured-file-parser.js +9 -2
- package/dist/parsers/structured-file-parser.js.map +1 -1
- package/dist/planned-tasks/planned-task-permissions.js +3 -5
- package/dist/planned-tasks/planned-task-permissions.js.map +1 -1
- package/dist/planned-tasks/planned-task-service.d.ts +1 -0
- package/dist/planned-tasks/planned-task-service.js +8 -0
- package/dist/planned-tasks/planned-task-service.js.map +1 -1
- package/dist/runtime/background-task-manager.d.ts +9 -2
- package/dist/runtime/background-task-manager.js +7 -2
- package/dist/runtime/background-task-manager.js.map +1 -1
- package/dist/runtime/liveness-policy.js +4 -3
- package/dist/runtime/liveness-policy.js.map +1 -1
- package/dist/runtime/resumable-stream-executor.d.ts +4 -24
- package/dist/runtime/resumable-stream-executor.js +103 -1318
- package/dist/runtime/resumable-stream-executor.js.map +1 -1
- package/dist/runtime/run-state-registry.d.ts +8 -2
- package/dist/runtime/run-state-registry.js +19 -1
- package/dist/runtime/run-state-registry.js.map +1 -1
- package/dist/runtime/stream-runner.d.ts +4 -4
- package/dist/runtime/stream-runner.js +11 -25
- package/dist/runtime/stream-runner.js.map +1 -1
- package/dist/skills/materialize-runtime-skills.d.ts +62 -0
- package/dist/skills/materialize-runtime-skills.js +465 -0
- package/dist/skills/materialize-runtime-skills.js.map +1 -0
- package/dist/skills/runtime-skills.d.ts +4 -0
- package/dist/skills/runtime-skills.js +17 -0
- package/dist/skills/runtime-skills.js.map +1 -0
- package/dist/source-map-filter.d.ts +17 -0
- package/dist/source-map-filter.js +39 -0
- package/dist/source-map-filter.js.map +1 -0
- package/dist/storage/agent-tree-snapshot.d.ts +2 -0
- package/dist/storage/index.d.ts +3 -3
- package/dist/storage/index.js +8 -7
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/planned-task-storage.d.ts +3 -3
- package/dist/storage/planned-task-storage.js +3 -8
- package/dist/storage/planned-task-storage.js.map +1 -1
- package/dist/storage/terminal-outcome-storage.d.ts +4 -4
- package/dist/storage/terminal-outcome-storage.js +1 -1
- package/dist/storage/terminal-outcome-storage.js.map +1 -1
- package/dist/storage/{mastra-iteration-log-storage.d.ts → thread-iteration-log-storage.d.ts} +3 -3
- package/dist/storage/{mastra-iteration-log-storage.js → thread-iteration-log-storage.js} +5 -5
- package/dist/storage/thread-iteration-log-storage.js.map +1 -0
- package/dist/storage/thread-patch.d.ts +16 -10
- package/dist/storage/thread-patch.js +37 -36
- package/dist/storage/thread-patch.js.map +1 -1
- package/dist/storage/{mastra-task-storage.d.ts → thread-task-storage.d.ts} +3 -3
- package/dist/storage/{mastra-task-storage.js → thread-task-storage.js} +5 -5
- package/dist/storage/thread-task-storage.js.map +1 -0
- package/dist/storage/workflow-loop-storage.d.ts +28 -28
- package/dist/storage/workflow-loop-storage.js +1 -1
- package/dist/storage/workflow-loop-storage.js.map +1 -1
- package/dist/stream/consume-with-hitl.d.ts +11 -11
- package/dist/stream/consume-with-hitl.js +27 -15
- package/dist/stream/consume-with-hitl.js.map +1 -1
- package/dist/stream/map-chunk.d.ts +1 -1
- package/dist/stream/map-chunk.js +153 -36
- package/dist/stream/map-chunk.js.map +1 -1
- package/dist/tool-registry.d.ts +8 -0
- package/dist/tool-registry.js +45 -0
- package/dist/tool-registry.js.map +1 -0
- package/dist/tools/attachments/parse-file.tool.d.ts +42 -45
- package/dist/tools/attachments/parse-file.tool.js +140 -97
- package/dist/tools/attachments/parse-file.tool.js.map +1 -1
- package/dist/tools/credentials.tool.d.ts +5 -5
- package/dist/tools/credentials.tool.js +31 -34
- package/dist/tools/credentials.tool.js.map +1 -1
- package/dist/tools/data-tables.tool.d.ts +3 -2
- package/dist/tools/data-tables.tool.js +99 -100
- package/dist/tools/data-tables.tool.js.map +1 -1
- package/dist/tools/evals/apply-pin-data.service.d.ts +3 -0
- package/dist/tools/evals/apply-pin-data.service.js +19 -0
- package/dist/tools/evals/apply-pin-data.service.js.map +1 -0
- package/dist/tools/evals/column-ref-utils.d.ts +3 -0
- package/dist/tools/evals/column-ref-utils.js +205 -48
- package/dist/tools/evals/column-ref-utils.js.map +1 -1
- package/dist/tools/evals/detect-agent-named-refs.service.js +20 -4
- package/dist/tools/evals/detect-agent-named-refs.service.js.map +1 -1
- package/dist/tools/evals/ensure-eval-data-table.service.d.ts +15 -0
- package/dist/tools/evals/ensure-eval-data-table.service.js +83 -0
- package/dist/tools/evals/ensure-eval-data-table.service.js.map +1 -0
- package/dist/tools/evals/eval-data-requirements.service.d.ts +1 -0
- package/dist/tools/evals/eval-data-requirements.service.js +23 -4
- package/dist/tools/evals/eval-data-requirements.service.js.map +1 -1
- package/dist/tools/evals/evals.tool.d.ts +2 -0
- package/dist/tools/evals/evals.tool.js +452 -0
- package/dist/tools/evals/evals.tool.js.map +1 -0
- package/dist/tools/evals/extract-rows-from-history.service.d.ts +17 -0
- package/dist/tools/evals/extract-rows-from-history.service.js +103 -0
- package/dist/tools/evals/extract-rows-from-history.service.js.map +1 -0
- package/dist/tools/evals/format-eval-setup-task.d.ts +16 -0
- package/dist/tools/evals/format-eval-setup-task.js +167 -0
- package/dist/tools/evals/format-eval-setup-task.js.map +1 -0
- package/dist/tools/evals/generate-sample-rows.service.d.ts +35 -0
- package/dist/tools/evals/generate-sample-rows.service.js +278 -0
- package/dist/tools/evals/generate-sample-rows.service.js.map +1 -0
- package/dist/tools/evals/generate-tool-ref-pin-data.service.d.ts +11 -0
- package/dist/tools/evals/generate-tool-ref-pin-data.service.js +125 -0
- package/dist/tools/evals/generate-tool-ref-pin-data.service.js.map +1 -0
- package/dist/tools/evals/metric-catalog.d.ts +10 -4
- package/dist/tools/evals/metric-catalog.js.map +1 -1
- package/dist/tools/executions.tool.d.ts +1 -1
- package/dist/tools/executions.tool.js +25 -34
- package/dist/tools/executions.tool.js.map +1 -1
- package/dist/tools/filesystem/create-tools-from-mcp-server.d.ts +2 -3
- package/dist/tools/filesystem/create-tools-from-mcp-server.js +129 -67
- package/dist/tools/filesystem/create-tools-from-mcp-server.js.map +1 -1
- package/dist/tools/index.d.ts +4 -16
- package/dist/tools/index.js +102 -92
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/nodes.tool.d.ts +1 -1
- package/dist/tools/nodes.tool.js +31 -33
- package/dist/tools/nodes.tool.js.map +1 -1
- package/dist/tools/orchestration/add-plan-item.tool.d.ts +2 -2
- package/dist/tools/orchestration/add-plan-item.tool.js +45 -49
- package/dist/tools/orchestration/add-plan-item.tool.js.map +1 -1
- package/dist/tools/orchestration/agent-persistence.d.ts +14 -0
- package/dist/tools/orchestration/agent-persistence.js +43 -0
- package/dist/tools/orchestration/agent-persistence.js.map +1 -0
- package/dist/tools/orchestration/blueprint-accumulator.d.ts +4 -8
- package/dist/tools/orchestration/blueprint-accumulator.js +11 -78
- package/dist/tools/orchestration/blueprint-accumulator.js.map +1 -1
- package/dist/tools/orchestration/blueprint.schema.d.ts +13 -147
- package/dist/tools/orchestration/blueprint.schema.js +4 -23
- package/dist/tools/orchestration/blueprint.schema.js.map +1 -1
- package/dist/tools/orchestration/browser-credential-setup.nudge.d.ts +2 -4
- package/dist/tools/orchestration/browser-credential-setup.nudge.js +1 -1
- package/dist/tools/orchestration/browser-credential-setup.nudge.js.map +1 -1
- package/dist/tools/orchestration/browser-credential-setup.tool.d.ts +10 -2
- package/dist/tools/orchestration/browser-credential-setup.tool.js +299 -270
- package/dist/tools/orchestration/browser-credential-setup.tool.js.map +1 -1
- package/dist/tools/orchestration/build-workflow-agent.prompt.d.ts +7 -1
- package/dist/tools/orchestration/build-workflow-agent.prompt.js +46 -20
- package/dist/tools/orchestration/build-workflow-agent.prompt.js.map +1 -1
- package/dist/tools/orchestration/build-workflow-agent.tool.d.ts +50 -5
- package/dist/tools/orchestration/build-workflow-agent.tool.js +748 -605
- package/dist/tools/orchestration/build-workflow-agent.tool.js.map +1 -1
- package/dist/tools/orchestration/builder-memory-compaction.d.ts +6 -2
- package/dist/tools/orchestration/builder-memory-compaction.js +32 -46
- package/dist/tools/orchestration/builder-memory-compaction.js.map +1 -1
- package/dist/tools/orchestration/complete-checkpoint.tool.d.ts +1 -1
- package/dist/tools/orchestration/complete-checkpoint.tool.js +46 -47
- package/dist/tools/orchestration/complete-checkpoint.tool.js.map +1 -1
- package/dist/tools/orchestration/delegate.tool.d.ts +1 -1
- package/dist/tools/orchestration/delegate.tool.js +170 -166
- package/dist/tools/orchestration/delegate.tool.js.map +1 -1
- package/dist/tools/orchestration/eval-data-agent.tool.d.ts +2 -0
- package/dist/tools/orchestration/eval-data-agent.tool.js +183 -0
- package/dist/tools/orchestration/eval-data-agent.tool.js.map +1 -0
- package/dist/tools/orchestration/eval-setup-agent.prompt.d.ts +1 -0
- package/dist/tools/orchestration/eval-setup-agent.prompt.js +238 -0
- package/dist/tools/orchestration/eval-setup-agent.prompt.js.map +1 -0
- package/dist/tools/orchestration/eval-setup-agent.tool.d.ts +31 -0
- package/dist/tools/orchestration/eval-setup-agent.tool.js +204 -0
- package/dist/tools/orchestration/eval-setup-agent.tool.js.map +1 -0
- package/dist/tools/orchestration/plan-agent-prompt.d.ts +1 -1
- package/dist/tools/orchestration/plan-agent-prompt.js +9 -9
- package/dist/tools/orchestration/plan-with-agent.tool.d.ts +1 -1
- package/dist/tools/orchestration/plan-with-agent.tool.js +210 -179
- package/dist/tools/orchestration/plan-with-agent.tool.js.map +1 -1
- package/dist/tools/orchestration/plan.tool.d.ts +5 -2
- package/dist/tools/orchestration/plan.tool.js +125 -105
- package/dist/tools/orchestration/plan.tool.js.map +1 -1
- package/dist/tools/orchestration/report-verification-verdict.tool.d.ts +3 -3
- package/dist/tools/orchestration/report-verification-verdict.tool.js +65 -66
- package/dist/tools/orchestration/report-verification-verdict.tool.js.map +1 -1
- package/dist/tools/orchestration/submit-plan.tool.d.ts +1 -1
- package/dist/tools/orchestration/submit-plan.tool.js +83 -66
- package/dist/tools/orchestration/submit-plan.tool.js.map +1 -1
- package/dist/tools/orchestration/tracing-utils.d.ts +3 -2
- package/dist/tools/orchestration/tracing-utils.js +58 -39
- package/dist/tools/orchestration/tracing-utils.js.map +1 -1
- package/dist/tools/orchestration/verify-built-workflow.tool.d.ts +5 -5
- package/dist/tools/orchestration/verify-built-workflow.tool.js +166 -166
- package/dist/tools/orchestration/verify-built-workflow.tool.js.map +1 -1
- package/dist/tools/research.tool.d.ts +1 -1
- package/dist/tools/research.tool.js +59 -27
- package/dist/tools/research.tool.js.map +1 -1
- package/dist/tools/shared/ask-user.tool.d.ts +3 -2
- package/dist/tools/shared/ask-user.tool.js +61 -63
- package/dist/tools/shared/ask-user.tool.js.map +1 -1
- package/dist/tools/task-control.tool.d.ts +1 -1
- package/dist/tools/task-control.tool.js +15 -16
- package/dist/tools/task-control.tool.js.map +1 -1
- package/dist/tools/templates.tool.d.ts +1 -1
- package/dist/tools/templates.tool.js +6 -7
- package/dist/tools/templates.tool.js.map +1 -1
- package/dist/tools/tool-ids.d.ts +40 -0
- package/dist/tools/tool-ids.js +62 -0
- package/dist/tools/tool-ids.js.map +1 -0
- package/dist/tools/workflows/apply-workflow-credentials.tool.d.ts +3 -3
- package/dist/tools/workflows/apply-workflow-credentials.tool.js +72 -73
- package/dist/tools/workflows/apply-workflow-credentials.tool.js.map +1 -1
- package/dist/tools/workflows/build-workflow.tool.d.ts +3 -3
- package/dist/tools/workflows/build-workflow.tool.js +113 -114
- package/dist/tools/workflows/build-workflow.tool.js.map +1 -1
- package/dist/tools/workflows/materialize-node-type.tool.d.ts +6 -6
- package/dist/tools/workflows/materialize-node-type.tool.js +64 -65
- package/dist/tools/workflows/materialize-node-type.tool.js.map +1 -1
- package/dist/tools/workflows/resolve-credentials.d.ts +3 -5
- package/dist/tools/workflows/resolve-credentials.js +15 -6
- package/dist/tools/workflows/resolve-credentials.js.map +1 -1
- package/dist/tools/workflows/setup-workflow.schema.d.ts +2 -2
- package/dist/tools/workflows/submit-workflow-identity.d.ts +8 -9
- package/dist/tools/workflows/submit-workflow-identity.js +41 -27
- package/dist/tools/workflows/submit-workflow-identity.js.map +1 -1
- package/dist/tools/workflows/submit-workflow.tool.d.ts +10 -7
- package/dist/tools/workflows/submit-workflow.tool.js +224 -191
- package/dist/tools/workflows/submit-workflow.tool.js.map +1 -1
- package/dist/tools/workflows/validate-workflow.service.d.ts +15 -0
- package/dist/tools/workflows/validate-workflow.service.js +289 -0
- package/dist/tools/workflows/validate-workflow.service.js.map +1 -0
- package/dist/tools/workflows/write-sandbox-file.tool.d.ts +2 -2
- package/dist/tools/workflows/write-sandbox-file.tool.js +29 -30
- package/dist/tools/workflows/write-sandbox-file.tool.js.map +1 -1
- package/dist/tools/workflows.tool.d.ts +5 -2
- package/dist/tools/workflows.tool.js +184 -85
- package/dist/tools/workflows.tool.js.map +1 -1
- package/dist/tools/workspace.tool.d.ts +1 -1
- package/dist/tools/workspace.tool.js +49 -65
- package/dist/tools/workspace.tool.js.map +1 -1
- package/dist/tracing/langsmith-tracing.d.ts +17 -18
- package/dist/tracing/langsmith-tracing.js +941 -677
- package/dist/tracing/langsmith-tracing.js.map +1 -1
- package/dist/tracing/trace-labels.d.ts +5 -0
- package/dist/tracing/trace-labels.js +36 -0
- package/dist/tracing/trace-labels.js.map +1 -0
- package/dist/tracing/trace-payloads.d.ts +23 -0
- package/dist/tracing/trace-payloads.js +1008 -0
- package/dist/tracing/trace-payloads.js.map +1 -0
- package/dist/types.d.ts +57 -25
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -1
- package/dist/utils/eval-agents.js +1 -1
- package/dist/utils/eval-agents.js.map +1 -1
- package/dist/utils/scrub-secrets.js +1 -1
- package/dist/utils/scrub-secrets.js.map +1 -1
- package/dist/utils/stream-helpers.d.ts +2 -5
- package/dist/utils/stream-helpers.js +12 -1
- package/dist/utils/stream-helpers.js.map +1 -1
- package/dist/workflow-loop/workflow-loop-state.d.ts +18 -18
- package/dist/workspace/builder-templates-service.d.ts +54 -0
- package/dist/workspace/builder-templates-service.js +442 -0
- package/dist/workspace/builder-templates-service.js.map +1 -0
- package/dist/workspace/create-workspace.d.ts +16 -3
- package/dist/workspace/create-workspace.js +45 -21
- package/dist/workspace/create-workspace.js.map +1 -1
- package/dist/workspace/daytona-auth-manager.d.ts +26 -0
- package/dist/workspace/daytona-auth-manager.js +90 -0
- package/dist/workspace/daytona-auth-manager.js.map +1 -0
- package/dist/workspace/daytona-filesystem.d.ts +5 -4
- package/dist/workspace/daytona-filesystem.js +25 -15
- package/dist/workspace/daytona-filesystem.js.map +1 -1
- package/dist/workspace/daytona-sandbox.d.ts +65 -0
- package/dist/workspace/daytona-sandbox.js +314 -0
- package/dist/workspace/daytona-sandbox.js.map +1 -0
- package/dist/workspace/lazy-daytona.d.ts +2 -0
- package/dist/workspace/lazy-daytona.js +12 -0
- package/dist/workspace/lazy-daytona.js.map +1 -0
- package/dist/workspace/lazy-runtime-workspace.d.ts +8 -0
- package/dist/workspace/lazy-runtime-workspace.js +246 -0
- package/dist/workspace/lazy-runtime-workspace.js.map +1 -0
- package/dist/workspace/local-filesystem.d.ts +48 -0
- package/dist/workspace/local-filesystem.js +250 -0
- package/dist/workspace/local-filesystem.js.map +1 -0
- package/dist/workspace/local-sandbox.d.ts +28 -0
- package/dist/workspace/local-sandbox.js +121 -0
- package/dist/workspace/local-sandbox.js.map +1 -0
- package/dist/workspace/n8n-sandbox-filesystem.d.ts +3 -3
- package/dist/workspace/n8n-sandbox-filesystem.js +3 -3
- package/dist/workspace/n8n-sandbox-filesystem.js.map +1 -1
- package/dist/workspace/n8n-sandbox-sandbox.d.ts +12 -3
- package/dist/workspace/n8n-sandbox-sandbox.js +54 -10
- package/dist/workspace/n8n-sandbox-sandbox.js.map +1 -1
- package/dist/workspace/sandbox-fs.d.ts +35 -4
- package/dist/workspace/sandbox-fs.js +1 -1
- package/dist/workspace/sandbox-fs.js.map +1 -1
- package/dist/workspace/sandbox-setup.d.ts +13 -4
- package/dist/workspace/sandbox-setup.js +250 -36
- package/dist/workspace/sandbox-setup.js.map +1 -1
- package/dist/workspace/scoped-workspace.d.ts +2 -0
- package/dist/workspace/scoped-workspace.js +141 -0
- package/dist/workspace/scoped-workspace.js.map +1 -0
- package/dist/workspace/snapshot-manager.d.ts +11 -5
- package/dist/workspace/snapshot-manager.js +74 -17
- package/dist/workspace/snapshot-manager.js.map +1 -1
- package/dist/workspace/template-telemetry.d.ts +4 -4
- package/dist/workspace/template-telemetry.js +18 -6
- package/dist/workspace/template-telemetry.js.map +1 -1
- package/package.json +13 -16
- package/skills/data-table-manager/SKILL.md +119 -0
- package/skills/data-table-manager/references/data-table-playbook.md +212 -0
- package/dist/agent/register-with-mastra.d.ts +0 -3
- package/dist/agent/register-with-mastra.js +0 -15
- package/dist/agent/register-with-mastra.js.map +0 -1
- package/dist/compaction/compaction-helper.d.ts +0 -9
- package/dist/compaction/compaction-helper.js +0 -58
- package/dist/compaction/compaction-helper.js.map +0 -1
- package/dist/compaction/index.d.ts +0 -2
- package/dist/compaction/index.js +0 -6
- package/dist/compaction/index.js.map +0 -1
- package/dist/memory/memory-config.d.ts +0 -3
- package/dist/memory/memory-config.js +0 -27
- package/dist/memory/memory-config.js.map +0 -1
- package/dist/runtime/builder-sandbox-session-registry.d.ts +0 -47
- package/dist/runtime/builder-sandbox-session-registry.js +0 -166
- package/dist/runtime/builder-sandbox-session-registry.js.map +0 -1
- package/dist/storage/mastra-iteration-log-storage.js.map +0 -1
- package/dist/storage/mastra-task-storage.js.map +0 -1
- package/dist/tools/orchestration/data-table-agent.prompt.d.ts +0 -1
- package/dist/tools/orchestration/data-table-agent.prompt.js +0 -47
- package/dist/tools/orchestration/data-table-agent.prompt.js.map +0 -1
- package/dist/tools/orchestration/data-table-agent.tool.d.ts +0 -26
- package/dist/tools/orchestration/data-table-agent.tool.js +0 -174
- package/dist/tools/orchestration/data-table-agent.tool.js.map +0 -1
- package/dist/tools/orchestration/research-agent-prompt.d.ts +0 -1
- package/dist/tools/orchestration/research-agent-prompt.js +0 -26
- package/dist/tools/orchestration/research-agent-prompt.js.map +0 -1
- package/dist/tools/orchestration/research-with-agent.tool.d.ts +0 -30
- package/dist/tools/orchestration/research-with-agent.tool.js +0 -179
- package/dist/tools/orchestration/research-with-agent.tool.js.map +0 -1
- package/dist/workspace/builder-sandbox-factory.d.ts +0 -30
- package/dist/workspace/builder-sandbox-factory.js +0 -289
- package/dist/workspace/builder-sandbox-factory.js.map +0 -1
- package/dist/workspace/guarded-filesystem.d.ts +0 -10
- package/dist/workspace/guarded-filesystem.js +0 -136
- 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
|
|
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
|
|
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
|
|
35
|
-
const
|
|
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
|
-
|
|
49
|
-
|
|
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
|
-
|
|
68
|
-
'
|
|
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
|
-
|
|
76
|
-
'
|
|
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 (!
|
|
208
|
+
if (!tool?.handler)
|
|
148
209
|
return;
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
const result = await
|
|
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** —
|
|
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
|
|
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
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
controller.abort(parentSignal.reason);
|
|
395
|
-
return controller;
|
|
461
|
+
function createMainWorkflowSnapshot(content) {
|
|
462
|
+
if (content === null) {
|
|
463
|
+
return { exists: false };
|
|
396
464
|
}
|
|
397
|
-
|
|
398
|
-
|
|
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
|
|
824
|
+
const sharedWorkspace = context.workspace;
|
|
602
825
|
const domainContext = context.domainContext;
|
|
603
|
-
const useSandbox = !!
|
|
826
|
+
const useSandbox = !!sharedWorkspace && !!domainContext;
|
|
604
827
|
let builderTools;
|
|
605
828
|
let prompt = build_workflow_agent_prompt_1.BUILDER_AGENT_PROMPT;
|
|
606
|
-
let
|
|
829
|
+
let credMap;
|
|
607
830
|
if (useSandbox) {
|
|
608
|
-
|
|
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
|
-
|
|
615
|
-
|
|
836
|
+
const tool = context.domainTools.get(name);
|
|
837
|
+
if (tool) {
|
|
838
|
+
builderTools.set(name, tool);
|
|
616
839
|
}
|
|
617
840
|
}
|
|
618
|
-
builderTools.workflows
|
|
619
|
-
builderTools.
|
|
841
|
+
builderTools.set('workflows', builderWorkflowsTool);
|
|
842
|
+
builderTools.set(credentials_tool_1.CREDENTIALS_TOOL_ID, builderCredentialsTool);
|
|
620
843
|
if (context.workflowTaskService && context.domainContext) {
|
|
621
|
-
builderTools
|
|
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
|
-
|
|
628
|
-
|
|
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
|
|
633
|
-
builderTools.
|
|
856
|
+
builderTools.set('workflows', createBuilderWorkflowsTool(domainContext));
|
|
857
|
+
builderTools.set(credentials_tool_1.CREDENTIALS_TOOL_ID, createBuilderCredentialsTool(domainContext));
|
|
634
858
|
}
|
|
635
|
-
if (!builderTools
|
|
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
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
const
|
|
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 (
|
|
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 =
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
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
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
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
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
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
|
|
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
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
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
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
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
|
|
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
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
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
|
-
|
|
983
|
-
|
|
984
|
-
|
|
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
|
-
|
|
987
|
-
|
|
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
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
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
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
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
|
-
|
|
1088
|
-
|
|
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
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
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
|
-
|
|
1062
|
+
maxIterations: max_steps_1.MAX_STEPS.BUILDER,
|
|
1107
1063
|
abortSignal: signal,
|
|
1108
|
-
|
|
1064
|
+
persistence,
|
|
1109
1065
|
providerOptions: {
|
|
1110
1066
|
anthropic: { cacheControl: { type: 'ephemeral' } },
|
|
1111
1067
|
},
|
|
1112
|
-
...(llmStepTraceHooks?.executionOptions ?? {}),
|
|
1113
1068
|
});
|
|
1114
|
-
|
|
1069
|
+
const hitlResult = await (0, consume_with_hitl_1.consumeStreamWithHitl)({
|
|
1115
1070
|
agent: subAgent,
|
|
1116
|
-
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
|
-
|
|
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
|
|
1133
|
-
|
|
1134
|
-
|
|
1230
|
+
const outcome = await buildOutcomeWithLatestVerification(context, workItemId, taskId, mainWorkflowAttempt, finalText);
|
|
1231
|
+
return {
|
|
1232
|
+
text: finalText,
|
|
1233
|
+
outcome,
|
|
1234
|
+
};
|
|
1135
1235
|
}
|
|
1136
1236
|
finally {
|
|
1137
|
-
|
|
1237
|
+
unsubscribeTelemetry?.();
|
|
1238
|
+
if (telemetrySession) {
|
|
1138
1239
|
try {
|
|
1139
1240
|
telemetrySession.flush();
|
|
1140
|
-
(0, template_telemetry_1.detachTemplateTelemetrySession)(
|
|
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
|
-
|
|
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
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
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:
|
|
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
|
|
1277
|
-
const
|
|
1278
|
-
|
|
1279
|
-
if (
|
|
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:
|
|
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
|
|
1424
|
+
return { result, taskId: '' };
|
|
1287
1425
|
};
|
|
1288
|
-
return
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
if (
|
|
1305
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
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
|
-
|
|
1330
|
-
|
|
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
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
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
|