@mastra/factory 0.0.0-aggregate-trace-20261015182851
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/LICENSE.md +32 -0
- package/README.md +671 -0
- package/dist/auth.d.ts +201 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +623 -0
- package/dist/auth.js.map +1 -0
- package/dist/boards/define-board.d.ts +111 -0
- package/dist/boards/define-board.d.ts.map +1 -0
- package/dist/boards/define-board.js +156 -0
- package/dist/boards/define-board.js.map +1 -0
- package/dist/boards/index.d.ts +14 -0
- package/dist/boards/index.d.ts.map +1 -0
- package/dist/boards/index.js +21 -0
- package/dist/boards/index.js.map +1 -0
- package/dist/boards/registry.d.ts +16 -0
- package/dist/boards/registry.d.ts.map +1 -0
- package/dist/boards/registry.js +25 -0
- package/dist/boards/registry.js.map +1 -0
- package/dist/boards/relocate.d.ts +21 -0
- package/dist/boards/relocate.d.ts.map +1 -0
- package/dist/boards/relocate.js +58 -0
- package/dist/boards/relocate.js.map +1 -0
- package/dist/boards/review.d.ts +6 -0
- package/dist/boards/review.d.ts.map +1 -0
- package/dist/boards/review.js +104 -0
- package/dist/boards/review.js.map +1 -0
- package/dist/boards/semantics.d.ts +68 -0
- package/dist/boards/semantics.d.ts.map +1 -0
- package/dist/boards/semantics.js +119 -0
- package/dist/boards/semantics.js.map +1 -0
- package/dist/boards/transition-policy.d.ts +67 -0
- package/dist/boards/transition-policy.d.ts.map +1 -0
- package/dist/boards/transition-policy.js +36 -0
- package/dist/boards/transition-policy.js.map +1 -0
- package/dist/boards/work-tool-rules.d.ts +8 -0
- package/dist/boards/work-tool-rules.d.ts.map +1 -0
- package/dist/boards/work-tool-rules.js +20 -0
- package/dist/boards/work-tool-rules.js.map +1 -0
- package/dist/boards/work-transition-policy.d.ts +3 -0
- package/dist/boards/work-transition-policy.d.ts.map +1 -0
- package/dist/boards/work-transition-policy.js +46 -0
- package/dist/boards/work-transition-policy.js.map +1 -0
- package/dist/boards/work.d.ts +4 -0
- package/dist/boards/work.d.ts.map +1 -0
- package/dist/boards/work.js +222 -0
- package/dist/boards/work.js.map +1 -0
- package/dist/capabilities/connection.d.ts +9 -0
- package/dist/capabilities/connection.d.ts.map +1 -0
- package/dist/capabilities/connection.js +1 -0
- package/dist/capabilities/intake.d.ts +153 -0
- package/dist/capabilities/intake.d.ts.map +1 -0
- package/dist/capabilities/intake.js +1 -0
- package/dist/capabilities/version-control.d.ts +268 -0
- package/dist/capabilities/version-control.d.ts.map +1 -0
- package/dist/capabilities/version-control.js +1 -0
- package/dist/environment/build-runner.d.ts +72 -0
- package/dist/environment/build-runner.d.ts.map +1 -0
- package/dist/environment/build-runner.js +131 -0
- package/dist/environment/build-runner.js.map +1 -0
- package/dist/environment/build-schedule.d.ts +40 -0
- package/dist/environment/build-schedule.d.ts.map +1 -0
- package/dist/environment/build-schedule.js +94 -0
- package/dist/environment/build-schedule.js.map +1 -0
- package/dist/environment/build-workflow.d.ts +62 -0
- package/dist/environment/build-workflow.d.ts.map +1 -0
- package/dist/environment/build-workflow.js +149 -0
- package/dist/environment/build-workflow.js.map +1 -0
- package/dist/environment/build.d.ts +111 -0
- package/dist/environment/build.d.ts.map +1 -0
- package/dist/environment/build.js +344 -0
- package/dist/environment/build.js.map +1 -0
- package/dist/environment/heads.d.ts +36 -0
- package/dist/environment/heads.d.ts.map +1 -0
- package/dist/environment/heads.js +60 -0
- package/dist/environment/heads.js.map +1 -0
- package/dist/factory.d.ts +225 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/factory.js +1006 -0
- package/dist/factory.js.map +1 -0
- package/dist/feed-events.d.ts +13 -0
- package/dist/feed-events.d.ts.map +1 -0
- package/dist/feed-events.js +25 -0
- package/dist/feed-events.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/integrations/base.d.ts +302 -0
- package/dist/integrations/base.d.ts.map +1 -0
- package/dist/integrations/base.js +1 -0
- package/dist/integrations/github/acceptance-labels.d.ts +16 -0
- package/dist/integrations/github/acceptance-labels.d.ts.map +1 -0
- package/dist/integrations/github/acceptance-labels.js +55 -0
- package/dist/integrations/github/acceptance-labels.js.map +1 -0
- package/dist/integrations/github/app-identity.d.ts +43 -0
- package/dist/integrations/github/app-identity.d.ts.map +1 -0
- package/dist/integrations/github/app-identity.js +62 -0
- package/dist/integrations/github/app-identity.js.map +1 -0
- package/dist/integrations/github/commits.d.ts +40 -0
- package/dist/integrations/github/commits.d.ts.map +1 -0
- package/dist/integrations/github/commits.js +48 -0
- package/dist/integrations/github/commits.js.map +1 -0
- package/dist/integrations/github/config.d.ts +60 -0
- package/dist/integrations/github/config.d.ts.map +1 -0
- package/dist/integrations/github/config.js +42 -0
- package/dist/integrations/github/config.js.map +1 -0
- package/dist/integrations/github/default-rules.d.ts +218 -0
- package/dist/integrations/github/default-rules.d.ts.map +1 -0
- package/dist/integrations/github/default-rules.js +296 -0
- package/dist/integrations/github/default-rules.js.map +1 -0
- package/dist/integrations/github/integration.d.ts +270 -0
- package/dist/integrations/github/integration.d.ts.map +1 -0
- package/dist/integrations/github/integration.js +1375 -0
- package/dist/integrations/github/integration.js.map +1 -0
- package/dist/integrations/github/issue-reconciler.d.ts +28 -0
- package/dist/integrations/github/issue-reconciler.d.ts.map +1 -0
- package/dist/integrations/github/issue-reconciler.js +138 -0
- package/dist/integrations/github/issue-reconciler.js.map +1 -0
- package/dist/integrations/github/pat.d.ts +38 -0
- package/dist/integrations/github/pat.d.ts.map +1 -0
- package/dist/integrations/github/pat.js +59 -0
- package/dist/integrations/github/pat.js.map +1 -0
- package/dist/integrations/github/provenance.d.ts +34 -0
- package/dist/integrations/github/provenance.d.ts.map +1 -0
- package/dist/integrations/github/provenance.js +91 -0
- package/dist/integrations/github/provenance.js.map +1 -0
- package/dist/integrations/github/reconcile-worker.d.ts +45 -0
- package/dist/integrations/github/reconcile-worker.d.ts.map +1 -0
- package/dist/integrations/github/reconcile-worker.js +189 -0
- package/dist/integrations/github/reconcile-worker.js.map +1 -0
- package/dist/integrations/github/reconciliation-config.d.ts +3 -0
- package/dist/integrations/github/reconciliation-config.d.ts.map +1 -0
- package/dist/integrations/github/reconciliation-config.js +19 -0
- package/dist/integrations/github/reconciliation-config.js.map +1 -0
- package/dist/integrations/github/routes.d.ts +90 -0
- package/dist/integrations/github/routes.d.ts.map +1 -0
- package/dist/integrations/github/routes.js +1362 -0
- package/dist/integrations/github/routes.js.map +1 -0
- package/dist/integrations/github/rules.d.ts +173 -0
- package/dist/integrations/github/rules.d.ts.map +1 -0
- package/dist/integrations/github/rules.js +1021 -0
- package/dist/integrations/github/rules.js.map +1 -0
- package/dist/integrations/github/sandbox-release.d.ts +25 -0
- package/dist/integrations/github/sandbox-release.d.ts.map +1 -0
- package/dist/integrations/github/sandbox-release.js +38 -0
- package/dist/integrations/github/sandbox-release.js.map +1 -0
- package/dist/integrations/github/sandbox.d.ts +234 -0
- package/dist/integrations/github/sandbox.d.ts.map +1 -0
- package/dist/integrations/github/sandbox.js +947 -0
- package/dist/integrations/github/sandbox.js.map +1 -0
- package/dist/integrations/github/session-subscriptions.d.ts +28 -0
- package/dist/integrations/github/session-subscriptions.d.ts.map +1 -0
- package/dist/integrations/github/session-subscriptions.js +283 -0
- package/dist/integrations/github/session-subscriptions.js.map +1 -0
- package/dist/integrations/github/settle-or-abort.d.ts +7 -0
- package/dist/integrations/github/settle-or-abort.d.ts.map +1 -0
- package/dist/integrations/github/settle-or-abort.js +25 -0
- package/dist/integrations/github/settle-or-abort.js.map +1 -0
- package/dist/integrations/github/stale-reviews.d.ts +22 -0
- package/dist/integrations/github/stale-reviews.d.ts.map +1 -0
- package/dist/integrations/github/stale-reviews.js +70 -0
- package/dist/integrations/github/stale-reviews.js.map +1 -0
- package/dist/integrations/github/subscriptions.d.ts +54 -0
- package/dist/integrations/github/subscriptions.d.ts.map +1 -0
- package/dist/integrations/github/subscriptions.js +64 -0
- package/dist/integrations/github/subscriptions.js.map +1 -0
- package/dist/integrations/github/token-refresh.d.ts +31 -0
- package/dist/integrations/github/token-refresh.d.ts.map +1 -0
- package/dist/integrations/github/token-refresh.js +42 -0
- package/dist/integrations/github/token-refresh.js.map +1 -0
- package/dist/integrations/github/webhook.d.ts +139 -0
- package/dist/integrations/github/webhook.d.ts.map +1 -0
- package/dist/integrations/github/webhook.js +432 -0
- package/dist/integrations/github/webhook.js.map +1 -0
- package/dist/integrations/gitlab/agent-tools.d.ts +14 -0
- package/dist/integrations/gitlab/agent-tools.d.ts.map +1 -0
- package/dist/integrations/gitlab/agent-tools.js +42 -0
- package/dist/integrations/gitlab/agent-tools.js.map +1 -0
- package/dist/integrations/gitlab/api.d.ts +222 -0
- package/dist/integrations/gitlab/api.d.ts.map +1 -0
- package/dist/integrations/gitlab/api.js +274 -0
- package/dist/integrations/gitlab/api.js.map +1 -0
- package/dist/integrations/gitlab/default-rules.d.ts +125 -0
- package/dist/integrations/gitlab/default-rules.d.ts.map +1 -0
- package/dist/integrations/gitlab/default-rules.js +180 -0
- package/dist/integrations/gitlab/default-rules.js.map +1 -0
- package/dist/integrations/gitlab/integration.d.ts +138 -0
- package/dist/integrations/gitlab/integration.d.ts.map +1 -0
- package/dist/integrations/gitlab/integration.js +705 -0
- package/dist/integrations/gitlab/integration.js.map +1 -0
- package/dist/integrations/gitlab/issue-reconciler.d.ts +6 -0
- package/dist/integrations/gitlab/issue-reconciler.d.ts.map +1 -0
- package/dist/integrations/gitlab/issue-reconciler.js +123 -0
- package/dist/integrations/gitlab/issue-reconciler.js.map +1 -0
- package/dist/integrations/gitlab/merge-request-reconciler.d.ts +6 -0
- package/dist/integrations/gitlab/merge-request-reconciler.d.ts.map +1 -0
- package/dist/integrations/gitlab/merge-request-reconciler.js +267 -0
- package/dist/integrations/gitlab/merge-request-reconciler.js.map +1 -0
- package/dist/integrations/gitlab/reconciler.d.ts +5 -0
- package/dist/integrations/gitlab/reconciler.d.ts.map +1 -0
- package/dist/integrations/gitlab/reconciler.js +31 -0
- package/dist/integrations/gitlab/reconciler.js.map +1 -0
- package/dist/integrations/gitlab/reconciliation-config.d.ts +3 -0
- package/dist/integrations/gitlab/reconciliation-config.d.ts.map +1 -0
- package/dist/integrations/gitlab/reconciliation-config.js +17 -0
- package/dist/integrations/gitlab/reconciliation-config.js.map +1 -0
- package/dist/integrations/gitlab/routes.d.ts +20 -0
- package/dist/integrations/gitlab/routes.d.ts.map +1 -0
- package/dist/integrations/gitlab/routes.js +474 -0
- package/dist/integrations/gitlab/routes.js.map +1 -0
- package/dist/integrations/gitlab/rules.d.ts +35 -0
- package/dist/integrations/gitlab/rules.d.ts.map +1 -0
- package/dist/integrations/gitlab/rules.js +502 -0
- package/dist/integrations/gitlab/rules.js.map +1 -0
- package/dist/integrations/gitlab/session-subscriptions.d.ts +32 -0
- package/dist/integrations/gitlab/session-subscriptions.d.ts.map +1 -0
- package/dist/integrations/gitlab/session-subscriptions.js +193 -0
- package/dist/integrations/gitlab/session-subscriptions.js.map +1 -0
- package/dist/integrations/gitlab/subscriptions.d.ts +70 -0
- package/dist/integrations/gitlab/subscriptions.d.ts.map +1 -0
- package/dist/integrations/gitlab/subscriptions.js +76 -0
- package/dist/integrations/gitlab/subscriptions.js.map +1 -0
- package/dist/integrations/gitlab/version-control.d.ts +16 -0
- package/dist/integrations/gitlab/version-control.d.ts.map +1 -0
- package/dist/integrations/gitlab/version-control.js +621 -0
- package/dist/integrations/gitlab/version-control.js.map +1 -0
- package/dist/integrations/gitlab/webhook-dispatch.d.ts +75 -0
- package/dist/integrations/gitlab/webhook-dispatch.d.ts.map +1 -0
- package/dist/integrations/gitlab/webhook-dispatch.js +235 -0
- package/dist/integrations/gitlab/webhook-dispatch.js.map +1 -0
- package/dist/integrations/gitlab/webhook.d.ts +72 -0
- package/dist/integrations/gitlab/webhook.d.ts.map +1 -0
- package/dist/integrations/gitlab/webhook.js +201 -0
- package/dist/integrations/gitlab/webhook.js.map +1 -0
- package/dist/integrations/incidentio/agent-tools.d.ts +49 -0
- package/dist/integrations/incidentio/agent-tools.d.ts.map +1 -0
- package/dist/integrations/incidentio/agent-tools.js +90 -0
- package/dist/integrations/incidentio/agent-tools.js.map +1 -0
- package/dist/integrations/incidentio/api.d.ts +400 -0
- package/dist/integrations/incidentio/api.d.ts.map +1 -0
- package/dist/integrations/incidentio/api.js +192 -0
- package/dist/integrations/incidentio/api.js.map +1 -0
- package/dist/integrations/incidentio/claim.d.ts +8 -0
- package/dist/integrations/incidentio/claim.d.ts.map +1 -0
- package/dist/integrations/incidentio/claim.js +14 -0
- package/dist/integrations/incidentio/claim.js.map +1 -0
- package/dist/integrations/incidentio/default-rules.d.ts +46 -0
- package/dist/integrations/incidentio/default-rules.d.ts.map +1 -0
- package/dist/integrations/incidentio/default-rules.js +68 -0
- package/dist/integrations/incidentio/default-rules.js.map +1 -0
- package/dist/integrations/incidentio/intake.d.ts +10 -0
- package/dist/integrations/incidentio/intake.d.ts.map +1 -0
- package/dist/integrations/incidentio/intake.js +307 -0
- package/dist/integrations/incidentio/intake.js.map +1 -0
- package/dist/integrations/incidentio/integration.d.ts +63 -0
- package/dist/integrations/incidentio/integration.d.ts.map +1 -0
- package/dist/integrations/incidentio/integration.js +141 -0
- package/dist/integrations/incidentio/integration.js.map +1 -0
- package/dist/integrations/incidentio/issue-reconciler.d.ts +10 -0
- package/dist/integrations/incidentio/issue-reconciler.d.ts.map +1 -0
- package/dist/integrations/incidentio/issue-reconciler.js +75 -0
- package/dist/integrations/incidentio/issue-reconciler.js.map +1 -0
- package/dist/integrations/incidentio/reconciliation-config.d.ts +3 -0
- package/dist/integrations/incidentio/reconciliation-config.d.ts.map +1 -0
- package/dist/integrations/incidentio/reconciliation-config.js +17 -0
- package/dist/integrations/incidentio/reconciliation-config.js.map +1 -0
- package/dist/integrations/incidentio/routes.d.ts +76 -0
- package/dist/integrations/incidentio/routes.d.ts.map +1 -0
- package/dist/integrations/incidentio/routes.js +249 -0
- package/dist/integrations/incidentio/routes.js.map +1 -0
- package/dist/integrations/incidentio/rules.d.ts +55 -0
- package/dist/integrations/incidentio/rules.d.ts.map +1 -0
- package/dist/integrations/incidentio/rules.js +189 -0
- package/dist/integrations/incidentio/rules.js.map +1 -0
- package/dist/integrations/issue-reconcile-worker.d.ts +19 -0
- package/dist/integrations/issue-reconcile-worker.d.ts.map +1 -0
- package/dist/integrations/issue-reconcile-worker.js +97 -0
- package/dist/integrations/issue-reconcile-worker.js.map +1 -0
- package/dist/integrations/issue-reconciler.d.ts +51 -0
- package/dist/integrations/issue-reconciler.d.ts.map +1 -0
- package/dist/integrations/issue-reconciler.js +158 -0
- package/dist/integrations/issue-reconciler.js.map +1 -0
- package/dist/integrations/jira/adf.d.ts +26 -0
- package/dist/integrations/jira/adf.d.ts.map +1 -0
- package/dist/integrations/jira/adf.js +73 -0
- package/dist/integrations/jira/adf.js.map +1 -0
- package/dist/integrations/jira/agent-tools.d.ts +45 -0
- package/dist/integrations/jira/agent-tools.d.ts.map +1 -0
- package/dist/integrations/jira/agent-tools.js +87 -0
- package/dist/integrations/jira/agent-tools.js.map +1 -0
- package/dist/integrations/jira/api.d.ts +157 -0
- package/dist/integrations/jira/api.d.ts.map +1 -0
- package/dist/integrations/jira/api.js +141 -0
- package/dist/integrations/jira/api.js.map +1 -0
- package/dist/integrations/jira/claim.d.ts +9 -0
- package/dist/integrations/jira/claim.d.ts.map +1 -0
- package/dist/integrations/jira/claim.js +15 -0
- package/dist/integrations/jira/claim.js.map +1 -0
- package/dist/integrations/jira/default-rules.d.ts +47 -0
- package/dist/integrations/jira/default-rules.d.ts.map +1 -0
- package/dist/integrations/jira/default-rules.js +69 -0
- package/dist/integrations/jira/default-rules.js.map +1 -0
- package/dist/integrations/jira/integration.d.ts +114 -0
- package/dist/integrations/jira/integration.d.ts.map +1 -0
- package/dist/integrations/jira/integration.js +407 -0
- package/dist/integrations/jira/integration.js.map +1 -0
- package/dist/integrations/jira/issue-reconciler.d.ts +10 -0
- package/dist/integrations/jira/issue-reconciler.d.ts.map +1 -0
- package/dist/integrations/jira/issue-reconciler.js +70 -0
- package/dist/integrations/jira/issue-reconciler.js.map +1 -0
- package/dist/integrations/jira/reconciliation-config.d.ts +3 -0
- package/dist/integrations/jira/reconciliation-config.d.ts.map +1 -0
- package/dist/integrations/jira/reconciliation-config.js +17 -0
- package/dist/integrations/jira/reconciliation-config.js.map +1 -0
- package/dist/integrations/jira/routes.d.ts +54 -0
- package/dist/integrations/jira/routes.d.ts.map +1 -0
- package/dist/integrations/jira/routes.js +260 -0
- package/dist/integrations/jira/routes.js.map +1 -0
- package/dist/integrations/jira/rules.d.ts +57 -0
- package/dist/integrations/jira/rules.d.ts.map +1 -0
- package/dist/integrations/jira/rules.js +189 -0
- package/dist/integrations/jira/rules.js.map +1 -0
- package/dist/integrations/linear/agent-tools.d.ts +34 -0
- package/dist/integrations/linear/agent-tools.d.ts.map +1 -0
- package/dist/integrations/linear/agent-tools.js +87 -0
- package/dist/integrations/linear/agent-tools.js.map +1 -0
- package/dist/integrations/linear/claim.d.ts +8 -0
- package/dist/integrations/linear/claim.d.ts.map +1 -0
- package/dist/integrations/linear/claim.js +14 -0
- package/dist/integrations/linear/claim.js.map +1 -0
- package/dist/integrations/linear/default-rules.d.ts +46 -0
- package/dist/integrations/linear/default-rules.d.ts.map +1 -0
- package/dist/integrations/linear/default-rules.js +70 -0
- package/dist/integrations/linear/default-rules.js.map +1 -0
- package/dist/integrations/linear/integration.d.ts +260 -0
- package/dist/integrations/linear/integration.d.ts.map +1 -0
- package/dist/integrations/linear/integration.js +900 -0
- package/dist/integrations/linear/integration.js.map +1 -0
- package/dist/integrations/linear/issue-reconciler.d.ts +8 -0
- package/dist/integrations/linear/issue-reconciler.d.ts.map +1 -0
- package/dist/integrations/linear/issue-reconciler.js +73 -0
- package/dist/integrations/linear/issue-reconciler.js.map +1 -0
- package/dist/integrations/linear/reconciliation-config.d.ts +3 -0
- package/dist/integrations/linear/reconciliation-config.d.ts.map +1 -0
- package/dist/integrations/linear/reconciliation-config.js +21 -0
- package/dist/integrations/linear/reconciliation-config.js.map +1 -0
- package/dist/integrations/linear/routes.d.ts +81 -0
- package/dist/integrations/linear/routes.d.ts.map +1 -0
- package/dist/integrations/linear/routes.js +380 -0
- package/dist/integrations/linear/routes.js.map +1 -0
- package/dist/integrations/linear/rules.d.ts +54 -0
- package/dist/integrations/linear/rules.d.ts.map +1 -0
- package/dist/integrations/linear/rules.js +189 -0
- package/dist/integrations/linear/rules.js.map +1 -0
- package/dist/integrations/linear/storage.d.ts +65 -0
- package/dist/integrations/linear/storage.d.ts.map +1 -0
- package/dist/integrations/linear/storage.js +1 -0
- package/dist/integrations/platform/api-client.d.ts +26 -0
- package/dist/integrations/platform/api-client.d.ts.map +1 -0
- package/dist/integrations/platform/api-client.js +177 -0
- package/dist/integrations/platform/api-client.js.map +1 -0
- package/dist/integrations/platform/connect/routes.d.ts +39 -0
- package/dist/integrations/platform/connect/routes.d.ts.map +1 -0
- package/dist/integrations/platform/connect/routes.js +133 -0
- package/dist/integrations/platform/connect/routes.js.map +1 -0
- package/dist/integrations/platform/github/event-worker.d.ts +58 -0
- package/dist/integrations/platform/github/event-worker.d.ts.map +1 -0
- package/dist/integrations/platform/github/event-worker.js +449 -0
- package/dist/integrations/platform/github/event-worker.js.map +1 -0
- package/dist/integrations/platform/github/integration.d.ts +89 -0
- package/dist/integrations/platform/github/integration.d.ts.map +1 -0
- package/dist/integrations/platform/github/integration.js +1266 -0
- package/dist/integrations/platform/github/integration.js.map +1 -0
- package/dist/integrations/platform/gitlab/event-worker.d.ts +64 -0
- package/dist/integrations/platform/gitlab/event-worker.d.ts.map +1 -0
- package/dist/integrations/platform/gitlab/event-worker.js +305 -0
- package/dist/integrations/platform/gitlab/event-worker.js.map +1 -0
- package/dist/integrations/platform/gitlab/integration.d.ts +57 -0
- package/dist/integrations/platform/gitlab/integration.d.ts.map +1 -0
- package/dist/integrations/platform/gitlab/integration.js +113 -0
- package/dist/integrations/platform/gitlab/integration.js.map +1 -0
- package/dist/integrations/platform/incidentio/integration.d.ts +74 -0
- package/dist/integrations/platform/incidentio/integration.d.ts.map +1 -0
- package/dist/integrations/platform/incidentio/integration.js +406 -0
- package/dist/integrations/platform/incidentio/integration.js.map +1 -0
- package/dist/integrations/platform/jira/agent-tools.d.ts +36 -0
- package/dist/integrations/platform/jira/agent-tools.d.ts.map +1 -0
- package/dist/integrations/platform/jira/agent-tools.js +85 -0
- package/dist/integrations/platform/jira/agent-tools.js.map +1 -0
- package/dist/integrations/platform/jira/integration.d.ts +65 -0
- package/dist/integrations/platform/jira/integration.d.ts.map +1 -0
- package/dist/integrations/platform/jira/integration.js +546 -0
- package/dist/integrations/platform/jira/integration.js.map +1 -0
- package/dist/integrations/platform/jira/routes.d.ts +55 -0
- package/dist/integrations/platform/jira/routes.d.ts.map +1 -0
- package/dist/integrations/platform/jira/routes.js +274 -0
- package/dist/integrations/platform/jira/routes.js.map +1 -0
- package/dist/integrations/platform/linear/event-worker.d.ts +105 -0
- package/dist/integrations/platform/linear/event-worker.d.ts.map +1 -0
- package/dist/integrations/platform/linear/event-worker.js +379 -0
- package/dist/integrations/platform/linear/event-worker.js.map +1 -0
- package/dist/integrations/platform/linear/integration.d.ts +92 -0
- package/dist/integrations/platform/linear/integration.d.ts.map +1 -0
- package/dist/integrations/platform/linear/integration.js +754 -0
- package/dist/integrations/platform/linear/integration.js.map +1 -0
- package/dist/integrations/pull-request-head.d.ts +18 -0
- package/dist/integrations/pull-request-head.d.ts.map +1 -0
- package/dist/integrations/pull-request-head.js +45 -0
- package/dist/integrations/pull-request-head.js.map +1 -0
- package/dist/integrations/reconciliation-config.d.ts +3 -0
- package/dist/integrations/reconciliation-config.d.ts.map +1 -0
- package/dist/integrations/reconciliation-config.js +16 -0
- package/dist/integrations/reconciliation-config.js.map +1 -0
- package/dist/integrations/slack/connect-route.d.ts +46 -0
- package/dist/integrations/slack/connect-route.d.ts.map +1 -0
- package/dist/integrations/slack/connect-route.js +186 -0
- package/dist/integrations/slack/connect-route.js.map +1 -0
- package/dist/integrations/slack/emoji-shortcodes.generated.d.ts +8 -0
- package/dist/integrations/slack/emoji-shortcodes.generated.d.ts.map +1 -0
- package/dist/integrations/slack/emoji-shortcodes.generated.js +1985 -0
- package/dist/integrations/slack/emoji-shortcodes.generated.js.map +1 -0
- package/dist/integrations/slack/emoji.d.ts +3 -0
- package/dist/integrations/slack/emoji.d.ts.map +1 -0
- package/dist/integrations/slack/emoji.js +12 -0
- package/dist/integrations/slack/emoji.js.map +1 -0
- package/dist/integrations/slack/feed-publisher.d.ts +26 -0
- package/dist/integrations/slack/feed-publisher.d.ts.map +1 -0
- package/dist/integrations/slack/feed-publisher.js +44 -0
- package/dist/integrations/slack/feed-publisher.js.map +1 -0
- package/dist/integrations/slack/integration.d.ts +80 -0
- package/dist/integrations/slack/integration.d.ts.map +1 -0
- package/dist/integrations/slack/integration.js +93 -0
- package/dist/integrations/slack/integration.js.map +1 -0
- package/dist/integrations/slack/slack.d.ts +205 -0
- package/dist/integrations/slack/slack.d.ts.map +1 -0
- package/dist/integrations/slack/slack.js +653 -0
- package/dist/integrations/slack/slack.js.map +1 -0
- package/dist/integrations/subscription-session.d.ts +49 -0
- package/dist/integrations/subscription-session.d.ts.map +1 -0
- package/dist/integrations/subscription-session.js +103 -0
- package/dist/integrations/subscription-session.js.map +1 -0
- package/dist/integrations/workos/integration.d.ts +39 -0
- package/dist/integrations/workos/integration.d.ts.map +1 -0
- package/dist/integrations/workos/integration.js +91 -0
- package/dist/integrations/workos/integration.js.map +1 -0
- package/dist/packages/_internals/workspace/dist/index.js +48 -0
- package/dist/packages/_internals/workspace/dist/index.js.map +1 -0
- package/dist/platform-auth-host.d.ts +4 -0
- package/dist/platform-auth-host.d.ts.map +1 -0
- package/dist/platform-auth-host.js +18 -0
- package/dist/platform-auth-host.js.map +1 -0
- package/dist/review-verdict.d.ts +6 -0
- package/dist/review-verdict.d.ts.map +1 -0
- package/dist/review-verdict.js +14 -0
- package/dist/review-verdict.js.map +1 -0
- package/dist/routes/attention-activity.d.ts +23 -0
- package/dist/routes/attention-activity.d.ts.map +1 -0
- package/dist/routes/attention-activity.js +152 -0
- package/dist/routes/attention-activity.js.map +1 -0
- package/dist/routes/attention-parked.d.ts +22 -0
- package/dist/routes/attention-parked.d.ts.map +1 -0
- package/dist/routes/attention-parked.js +136 -0
- package/dist/routes/attention-parked.js.map +1 -0
- package/dist/routes/attention-proposed.d.ts +3 -0
- package/dist/routes/attention-proposed.d.ts.map +1 -0
- package/dist/routes/attention-proposed.js +21 -0
- package/dist/routes/attention-proposed.js.map +1 -0
- package/dist/routes/attention-providers.d.ts +159 -0
- package/dist/routes/attention-providers.d.ts.map +1 -0
- package/dist/routes/attention-providers.js +524 -0
- package/dist/routes/attention-providers.js.map +1 -0
- package/dist/routes/attention.d.ts +23 -0
- package/dist/routes/attention.d.ts.map +1 -0
- package/dist/routes/attention.js +219 -0
- package/dist/routes/attention.js.map +1 -0
- package/dist/routes/automation-runs.d.ts +37 -0
- package/dist/routes/automation-runs.d.ts.map +1 -0
- package/dist/routes/automation-runs.js +196 -0
- package/dist/routes/automation-runs.js.map +1 -0
- package/dist/routes/config.d.ts +238 -0
- package/dist/routes/config.d.ts.map +1 -0
- package/dist/routes/config.js +1011 -0
- package/dist/routes/config.js.map +1 -0
- package/dist/routes/contracts.d.ts +1080 -0
- package/dist/routes/contracts.d.ts.map +1 -0
- package/dist/routes/contracts.js +673 -0
- package/dist/routes/contracts.js.map +1 -0
- package/dist/routes/custom-provider-source.d.ts +52 -0
- package/dist/routes/custom-provider-source.d.ts.map +1 -0
- package/dist/routes/custom-provider-source.js +124 -0
- package/dist/routes/custom-provider-source.js.map +1 -0
- package/dist/routes/fs.d.ts +189 -0
- package/dist/routes/fs.d.ts.map +1 -0
- package/dist/routes/fs.js +916 -0
- package/dist/routes/fs.js.map +1 -0
- package/dist/routes/intake.d.ts +64 -0
- package/dist/routes/intake.d.ts.map +1 -0
- package/dist/routes/intake.js +627 -0
- package/dist/routes/intake.js.map +1 -0
- package/dist/routes/knowledge.d.ts +247 -0
- package/dist/routes/knowledge.d.ts.map +1 -0
- package/dist/routes/knowledge.js +1128 -0
- package/dist/routes/knowledge.js.map +1 -0
- package/dist/routes/oauth.d.ts +43 -0
- package/dist/routes/oauth.d.ts.map +1 -0
- package/dist/routes/oauth.js +477 -0
- package/dist/routes/oauth.js.map +1 -0
- package/dist/routes/projects.d.ts +68 -0
- package/dist/routes/projects.d.ts.map +1 -0
- package/dist/routes/projects.js +919 -0
- package/dist/routes/projects.js.map +1 -0
- package/dist/routes/provider-credentials.d.ts +82 -0
- package/dist/routes/provider-credentials.d.ts.map +1 -0
- package/dist/routes/provider-credentials.js +80 -0
- package/dist/routes/provider-credentials.js.map +1 -0
- package/dist/routes/route.d.ts +48 -0
- package/dist/routes/route.d.ts.map +1 -0
- package/dist/routes/route.js +15 -0
- package/dist/routes/route.js.map +1 -0
- package/dist/routes/skills.d.ts +30 -0
- package/dist/routes/skills.d.ts.map +1 -0
- package/dist/routes/skills.js +198 -0
- package/dist/routes/skills.js.map +1 -0
- package/dist/routes/source-control-sessions.d.ts +22 -0
- package/dist/routes/source-control-sessions.d.ts.map +1 -0
- package/dist/routes/source-control-sessions.js +356 -0
- package/dist/routes/source-control-sessions.js.map +1 -0
- package/dist/routes/source-control-settings.d.ts +10 -0
- package/dist/routes/source-control-settings.d.ts.map +1 -0
- package/dist/routes/source-control-settings.js +87 -0
- package/dist/routes/source-control-settings.js.map +1 -0
- package/dist/routes/supervisor.d.ts +25 -0
- package/dist/routes/supervisor.d.ts.map +1 -0
- package/dist/routes/supervisor.js +35 -0
- package/dist/routes/supervisor.js.map +1 -0
- package/dist/routes/surface.d.ts +133 -0
- package/dist/routes/surface.d.ts.map +1 -0
- package/dist/routes/surface.js +518 -0
- package/dist/routes/surface.js.map +1 -0
- package/dist/routes/telemetry.d.ts +13 -0
- package/dist/routes/telemetry.d.ts.map +1 -0
- package/dist/routes/telemetry.js +60 -0
- package/dist/routes/telemetry.js.map +1 -0
- package/dist/routes/tenant-credentials.d.ts +87 -0
- package/dist/routes/tenant-credentials.d.ts.map +1 -0
- package/dist/routes/tenant-credentials.js +219 -0
- package/dist/routes/tenant-credentials.js.map +1 -0
- package/dist/routes/work-items.d.ts +49 -0
- package/dist/routes/work-items.d.ts.map +1 -0
- package/dist/routes/work-items.js +633 -0
- package/dist/routes/work-items.js.map +1 -0
- package/dist/rules/binding-context.d.ts +59 -0
- package/dist/rules/binding-context.d.ts.map +1 -0
- package/dist/rules/binding-context.js +134 -0
- package/dist/rules/binding-context.js.map +1 -0
- package/dist/rules/decision-applicability.d.ts +32 -0
- package/dist/rules/decision-applicability.d.ts.map +1 -0
- package/dist/rules/decision-applicability.js +56 -0
- package/dist/rules/decision-applicability.js.map +1 -0
- package/dist/rules/dispatch-errors.d.ts +13 -0
- package/dist/rules/dispatch-errors.d.ts.map +1 -0
- package/dist/rules/dispatch-errors.js +105 -0
- package/dist/rules/dispatch-errors.js.map +1 -0
- package/dist/rules/dispatcher.d.ts +86 -0
- package/dist/rules/dispatcher.d.ts.map +1 -0
- package/dist/rules/dispatcher.js +1159 -0
- package/dist/rules/dispatcher.js.map +1 -0
- package/dist/rules/event-rules.d.ts +23 -0
- package/dist/rules/event-rules.d.ts.map +1 -0
- package/dist/rules/event-rules.js +46 -0
- package/dist/rules/event-rules.js.map +1 -0
- package/dist/rules/index.d.ts +6 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +4 -0
- package/dist/rules/processor.d.ts +90 -0
- package/dist/rules/processor.d.ts.map +1 -0
- package/dist/rules/processor.js +486 -0
- package/dist/rules/processor.js.map +1 -0
- package/dist/rules/resolve.d.ts +15 -0
- package/dist/rules/resolve.d.ts.map +1 -0
- package/dist/rules/resolve.js +23 -0
- package/dist/rules/resolve.js.map +1 -0
- package/dist/rules/review-source-tool.d.ts +105 -0
- package/dist/rules/review-source-tool.d.ts.map +1 -0
- package/dist/rules/review-source-tool.js +109 -0
- package/dist/rules/review-source-tool.js.map +1 -0
- package/dist/rules/start-coordinator.d.ts +64 -0
- package/dist/rules/start-coordinator.d.ts.map +1 -0
- package/dist/rules/start-coordinator.js +246 -0
- package/dist/rules/start-coordinator.js.map +1 -0
- package/dist/rules/terminal-cleanup.d.ts +38 -0
- package/dist/rules/terminal-cleanup.d.ts.map +1 -0
- package/dist/rules/terminal-cleanup.js +68 -0
- package/dist/rules/terminal-cleanup.js.map +1 -0
- package/dist/rules/tools.d.ts +15 -0
- package/dist/rules/tools.d.ts.map +1 -0
- package/dist/rules/tools.js +185 -0
- package/dist/rules/tools.js.map +1 -0
- package/dist/rules/transition-service.d.ts +93 -0
- package/dist/rules/transition-service.d.ts.map +1 -0
- package/dist/rules/transition-service.js +402 -0
- package/dist/rules/transition-service.js.map +1 -0
- package/dist/rules/types.d.ts +553 -0
- package/dist/rules/types.d.ts.map +1 -0
- package/dist/rules/types.js +154 -0
- package/dist/rules/types.js.map +1 -0
- package/dist/rules/validation.d.ts +21 -0
- package/dist/rules/validation.d.ts.map +1 -0
- package/dist/rules/validation.js +327 -0
- package/dist/rules/validation.js.map +1 -0
- package/dist/sandbox/callback-factory-sandbox.d.ts +15 -0
- package/dist/sandbox/callback-factory-sandbox.d.ts.map +1 -0
- package/dist/sandbox/callback-factory-sandbox.js +22 -0
- package/dist/sandbox/callback-factory-sandbox.js.map +1 -0
- package/dist/sandbox/git-ref.d.ts +7 -0
- package/dist/sandbox/git-ref.d.ts.map +1 -0
- package/dist/sandbox/git-ref.js +15 -0
- package/dist/sandbox/git-ref.js.map +1 -0
- package/dist/sandbox/local-factory-sandbox.d.ts +20 -0
- package/dist/sandbox/local-factory-sandbox.d.ts.map +1 -0
- package/dist/sandbox/local-factory-sandbox.js +27 -0
- package/dist/sandbox/local-factory-sandbox.js.map +1 -0
- package/dist/sandbox/materialization.d.ts +41 -0
- package/dist/sandbox/materialization.d.ts.map +1 -0
- package/dist/sandbox/materialization.js +18 -0
- package/dist/sandbox/materialization.js.map +1 -0
- package/dist/sandbox/session-retirement.d.ts +45 -0
- package/dist/sandbox/session-retirement.d.ts.map +1 -0
- package/dist/sandbox/session-retirement.js +153 -0
- package/dist/sandbox/session-retirement.js.map +1 -0
- package/dist/sandbox/session-sandbox.d.ts +185 -0
- package/dist/sandbox/session-sandbox.d.ts.map +1 -0
- package/dist/sandbox/session-sandbox.js +248 -0
- package/dist/sandbox/session-sandbox.js.map +1 -0
- package/dist/sandbox/workdir.d.ts +45 -0
- package/dist/sandbox/workdir.d.ts.map +1 -0
- package/dist/sandbox/workdir.js +64 -0
- package/dist/sandbox/workdir.js.map +1 -0
- package/dist/secret-encryption.d.ts +25 -0
- package/dist/secret-encryption.d.ts.map +1 -0
- package/dist/secret-encryption.js +107 -0
- package/dist/secret-encryption.js.map +1 -0
- package/dist/server-error.d.ts +12 -0
- package/dist/server-error.d.ts.map +1 -0
- package/dist/server-error.js +16 -0
- package/dist/server-error.js.map +1 -0
- package/dist/session/credential-policy.d.ts +20 -0
- package/dist/session/credential-policy.d.ts.map +1 -0
- package/dist/session/credential-policy.js +70 -0
- package/dist/session/credential-policy.js.map +1 -0
- package/dist/session/default-model-hydration.d.ts +46 -0
- package/dist/session/default-model-hydration.d.ts.map +1 -0
- package/dist/session/default-model-hydration.js +85 -0
- package/dist/session/default-model-hydration.js.map +1 -0
- package/dist/session/environment-repositories.d.ts +31 -0
- package/dist/session/environment-repositories.d.ts.map +1 -0
- package/dist/session/environment-repositories.js +89 -0
- package/dist/session/environment-repositories.js.map +1 -0
- package/dist/session/environment-state-processor.d.ts +59 -0
- package/dist/session/environment-state-processor.d.ts.map +1 -0
- package/dist/session/environment-state-processor.js +105 -0
- package/dist/session/environment-state-processor.js.map +1 -0
- package/dist/session/factory-session.d.ts +159 -0
- package/dist/session/factory-session.d.ts.map +1 -0
- package/dist/session/factory-session.js +226 -0
- package/dist/session/factory-session.js.map +1 -0
- package/dist/session/filesystem-capture.d.ts +50 -0
- package/dist/session/filesystem-capture.d.ts.map +1 -0
- package/dist/session/filesystem-capture.js +231 -0
- package/dist/session/filesystem-capture.js.map +1 -0
- package/dist/session/first-exec-capture.d.ts +38 -0
- package/dist/session/first-exec-capture.d.ts.map +1 -0
- package/dist/session/first-exec-capture.js +91 -0
- package/dist/session/first-exec-capture.js.map +1 -0
- package/dist/session/first-message-capture.d.ts +33 -0
- package/dist/session/first-message-capture.d.ts.map +1 -0
- package/dist/session/first-message-capture.js +35 -0
- package/dist/session/first-message-capture.js.map +1 -0
- package/dist/session/live-sessions.d.ts +63 -0
- package/dist/session/live-sessions.d.ts.map +1 -0
- package/dist/session/live-sessions.js +90 -0
- package/dist/session/live-sessions.js.map +1 -0
- package/dist/session/memory-settings-hydration.d.ts +36 -0
- package/dist/session/memory-settings-hydration.d.ts.map +1 -0
- package/dist/session/memory-settings-hydration.js +43 -0
- package/dist/session/memory-settings-hydration.js.map +1 -0
- package/dist/session/org-seed.d.ts +67 -0
- package/dist/session/org-seed.d.ts.map +1 -0
- package/dist/session/org-seed.js +53 -0
- package/dist/session/org-seed.js.map +1 -0
- package/dist/session/run-audit.d.ts +54 -0
- package/dist/session/run-audit.d.ts.map +1 -0
- package/dist/session/run-audit.js +124 -0
- package/dist/session/run-audit.js.map +1 -0
- package/dist/session/session-title.d.ts +7 -0
- package/dist/session/session-title.d.ts.map +1 -0
- package/dist/session/session-title.js +14 -0
- package/dist/session/session-title.js.map +1 -0
- package/dist/session/shell-commands.d.ts +5 -0
- package/dist/session/shell-commands.d.ts.map +1 -0
- package/dist/session/shell-commands.js +25 -0
- package/dist/session/shell-commands.js.map +1 -0
- package/dist/session/source-control-tools.d.ts +25 -0
- package/dist/session/source-control-tools.d.ts.map +1 -0
- package/dist/session/source-control-tools.js +594 -0
- package/dist/session/source-control-tools.js.map +1 -0
- package/dist/session/thread-title-mirror.d.ts +35 -0
- package/dist/session/thread-title-mirror.d.ts.map +1 -0
- package/dist/session/thread-title-mirror.js +51 -0
- package/dist/session/thread-title-mirror.js.map +1 -0
- package/dist/session/work-item-repository.d.ts +21 -0
- package/dist/session/work-item-repository.d.ts.map +1 -0
- package/dist/session/work-item-repository.js +113 -0
- package/dist/session/work-item-repository.js.map +1 -0
- package/dist/skills/catalog.d.ts +14 -0
- package/dist/skills/catalog.d.ts.map +1 -0
- package/dist/skills/catalog.js +62 -0
- package/dist/skills/catalog.js.map +1 -0
- package/dist/skills/service.d.ts +70 -0
- package/dist/skills/service.d.ts.map +1 -0
- package/dist/skills/service.js +88 -0
- package/dist/skills/service.js.map +1 -0
- package/dist/spa-static.d.ts +33 -0
- package/dist/spa-static.d.ts.map +1 -0
- package/dist/spa-static.js +104 -0
- package/dist/spa-static.js.map +1 -0
- package/dist/state-signing.d.ts +59 -0
- package/dist/state-signing.d.ts.map +1 -0
- package/dist/state-signing.js +83 -0
- package/dist/state-signing.js.map +1 -0
- package/dist/storage/domains/audit/actions.d.ts +24 -0
- package/dist/storage/domains/audit/actions.d.ts.map +1 -0
- package/dist/storage/domains/audit/actions.js +69 -0
- package/dist/storage/domains/audit/actions.js.map +1 -0
- package/dist/storage/domains/audit/actors.d.ts +5 -0
- package/dist/storage/domains/audit/actors.d.ts.map +1 -0
- package/dist/storage/domains/audit/actors.js +25 -0
- package/dist/storage/domains/audit/actors.js.map +1 -0
- package/dist/storage/domains/audit/agent-audit.d.ts +30 -0
- package/dist/storage/domains/audit/agent-audit.d.ts.map +1 -0
- package/dist/storage/domains/audit/agent-audit.js +93 -0
- package/dist/storage/domains/audit/agent-audit.js.map +1 -0
- package/dist/storage/domains/audit/base.d.ts +133 -0
- package/dist/storage/domains/audit/base.d.ts.map +1 -0
- package/dist/storage/domains/audit/base.js +206 -0
- package/dist/storage/domains/audit/base.js.map +1 -0
- package/dist/storage/domains/audit/domain.d.ts +79 -0
- package/dist/storage/domains/audit/domain.d.ts.map +1 -0
- package/dist/storage/domains/audit/domain.js +248 -0
- package/dist/storage/domains/audit/domain.js.map +1 -0
- package/dist/storage/domains/audit/wire.d.ts +24 -0
- package/dist/storage/domains/audit/wire.d.ts.map +1 -0
- package/dist/storage/domains/audit/wire.js +16 -0
- package/dist/storage/domains/audit/wire.js.map +1 -0
- package/dist/storage/domains/channel-identity/base.d.ts +100 -0
- package/dist/storage/domains/channel-identity/base.d.ts.map +1 -0
- package/dist/storage/domains/channel-identity/base.js +164 -0
- package/dist/storage/domains/channel-identity/base.js.map +1 -0
- package/dist/storage/domains/comments/activity.d.ts +40 -0
- package/dist/storage/domains/comments/activity.d.ts.map +1 -0
- package/dist/storage/domains/comments/activity.js +94 -0
- package/dist/storage/domains/comments/activity.js.map +1 -0
- package/dist/storage/domains/comments/actor.d.ts +51 -0
- package/dist/storage/domains/comments/actor.d.ts.map +1 -0
- package/dist/storage/domains/comments/actor.js +38 -0
- package/dist/storage/domains/comments/actor.js.map +1 -0
- package/dist/storage/domains/comments/base.d.ts +245 -0
- package/dist/storage/domains/comments/base.d.ts.map +1 -0
- package/dist/storage/domains/comments/base.js +533 -0
- package/dist/storage/domains/comments/base.js.map +1 -0
- package/dist/storage/domains/comments/domain.d.ts +135 -0
- package/dist/storage/domains/comments/domain.d.ts.map +1 -0
- package/dist/storage/domains/comments/domain.js +285 -0
- package/dist/storage/domains/comments/domain.js.map +1 -0
- package/dist/storage/domains/comments/feed-context.d.ts +22 -0
- package/dist/storage/domains/comments/feed-context.d.ts.map +1 -0
- package/dist/storage/domains/comments/feed-context.js +89 -0
- package/dist/storage/domains/comments/feed-context.js.map +1 -0
- package/dist/storage/domains/comments/feed-sync.d.ts +21 -0
- package/dist/storage/domains/comments/feed-sync.d.ts.map +1 -0
- package/dist/storage/domains/comments/feed-sync.js +1 -0
- package/dist/storage/domains/comments/parse.d.ts +23 -0
- package/dist/storage/domains/comments/parse.d.ts.map +1 -0
- package/dist/storage/domains/comments/parse.js +90 -0
- package/dist/storage/domains/comments/parse.js.map +1 -0
- package/dist/storage/domains/comments/routes.d.ts +24 -0
- package/dist/storage/domains/comments/routes.d.ts.map +1 -0
- package/dist/storage/domains/comments/routes.js +302 -0
- package/dist/storage/domains/comments/routes.js.map +1 -0
- package/dist/storage/domains/comments/schema.d.ts +5 -0
- package/dist/storage/domains/comments/schema.d.ts.map +1 -0
- package/dist/storage/domains/comments/schema.js +179 -0
- package/dist/storage/domains/comments/schema.js.map +1 -0
- package/dist/storage/domains/comments/wire.d.ts +40 -0
- package/dist/storage/domains/comments/wire.d.ts.map +1 -0
- package/dist/storage/domains/comments/wire.js +37 -0
- package/dist/storage/domains/comments/wire.js.map +1 -0
- package/dist/storage/domains/credentials/base.d.ts +136 -0
- package/dist/storage/domains/credentials/base.d.ts.map +1 -0
- package/dist/storage/domains/credentials/base.js +294 -0
- package/dist/storage/domains/credentials/base.js.map +1 -0
- package/dist/storage/domains/custom-providers/base.d.ts +59 -0
- package/dist/storage/domains/custom-providers/base.d.ts.map +1 -0
- package/dist/storage/domains/custom-providers/base.js +176 -0
- package/dist/storage/domains/custom-providers/base.js.map +1 -0
- package/dist/storage/domains/filesystem/base.d.ts +26 -0
- package/dist/storage/domains/filesystem/base.d.ts.map +1 -0
- package/dist/storage/domains/filesystem/base.js +74 -0
- package/dist/storage/domains/filesystem/base.js.map +1 -0
- package/dist/storage/domains/intake/base.d.ts +150 -0
- package/dist/storage/domains/intake/base.d.ts.map +1 -0
- package/dist/storage/domains/intake/base.js +431 -0
- package/dist/storage/domains/intake/base.js.map +1 -0
- package/dist/storage/domains/integrations/base.d.ts +128 -0
- package/dist/storage/domains/integrations/base.d.ts.map +1 -0
- package/dist/storage/domains/integrations/base.js +333 -0
- package/dist/storage/domains/integrations/base.js.map +1 -0
- package/dist/storage/domains/memory-settings/base.d.ts +58 -0
- package/dist/storage/domains/memory-settings/base.d.ts.map +1 -0
- package/dist/storage/domains/memory-settings/base.js +129 -0
- package/dist/storage/domains/memory-settings/base.js.map +1 -0
- package/dist/storage/domains/model-defaults/base.d.ts +29 -0
- package/dist/storage/domains/model-defaults/base.d.ts.map +1 -0
- package/dist/storage/domains/model-defaults/base.js +79 -0
- package/dist/storage/domains/model-defaults/base.js.map +1 -0
- package/dist/storage/domains/projects/base.d.ts +191 -0
- package/dist/storage/domains/projects/base.d.ts.map +1 -0
- package/dist/storage/domains/projects/base.js +352 -0
- package/dist/storage/domains/projects/base.js.map +1 -0
- package/dist/storage/domains/queue-health/base.d.ts +52 -0
- package/dist/storage/domains/queue-health/base.d.ts.map +1 -0
- package/dist/storage/domains/queue-health/base.js +122 -0
- package/dist/storage/domains/queue-health/base.js.map +1 -0
- package/dist/storage/domains/source-control/base.d.ts +422 -0
- package/dist/storage/domains/source-control/base.d.ts.map +1 -0
- package/dist/storage/domains/source-control/base.js +1114 -0
- package/dist/storage/domains/source-control/base.js.map +1 -0
- package/dist/storage/domains/source-control/inmemory.d.ts +147 -0
- package/dist/storage/domains/source-control/inmemory.d.ts.map +1 -0
- package/dist/storage/domains/source-control/inmemory.js +416 -0
- package/dist/storage/domains/source-control/inmemory.js.map +1 -0
- package/dist/storage/domains/work-items/base.d.ts +794 -0
- package/dist/storage/domains/work-items/base.d.ts.map +1 -0
- package/dist/storage/domains/work-items/base.js +2747 -0
- package/dist/storage/domains/work-items/base.js.map +1 -0
- package/dist/storage/domains/work-items/board-version.d.ts +26 -0
- package/dist/storage/domains/work-items/board-version.d.ts.map +1 -0
- package/dist/storage/domains/work-items/board-version.js +110 -0
- package/dist/storage/domains/work-items/board-version.js.map +1 -0
- package/dist/storage/domains/work-items/metrics.d.ts +97 -0
- package/dist/storage/domains/work-items/metrics.d.ts.map +1 -0
- package/dist/storage/domains/work-items/metrics.js +226 -0
- package/dist/storage/domains/work-items/metrics.js.map +1 -0
- package/dist/supervisor/health-worker.d.ts +19 -0
- package/dist/supervisor/health-worker.d.ts.map +1 -0
- package/dist/supervisor/health-worker.js +74 -0
- package/dist/supervisor/health-worker.js.map +1 -0
- package/dist/supervisor/health.d.ts +79 -0
- package/dist/supervisor/health.d.ts.map +1 -0
- package/dist/supervisor/health.js +228 -0
- package/dist/supervisor/health.js.map +1 -0
- package/dist/supervisor/instructions.d.ts +6 -0
- package/dist/supervisor/instructions.d.ts.map +1 -0
- package/dist/supervisor/instructions.js +66 -0
- package/dist/supervisor/instructions.js.map +1 -0
- package/dist/supervisor/read-tools.d.ts +43 -0
- package/dist/supervisor/read-tools.d.ts.map +1 -0
- package/dist/supervisor/read-tools.js +343 -0
- package/dist/supervisor/read-tools.js.map +1 -0
- package/dist/supervisor/session-messaging.d.ts +26 -0
- package/dist/supervisor/session-messaging.d.ts.map +1 -0
- package/dist/supervisor/session-messaging.js +21 -0
- package/dist/supervisor/session-messaging.js.map +1 -0
- package/dist/supervisor/session.d.ts +38 -0
- package/dist/supervisor/session.d.ts.map +1 -0
- package/dist/supervisor/session.js +79 -0
- package/dist/supervisor/session.js.map +1 -0
- package/dist/supervisor/write-tools.d.ts +30 -0
- package/dist/supervisor/write-tools.d.ts.map +1 -0
- package/dist/supervisor/write-tools.js +231 -0
- package/dist/supervisor/write-tools.js.map +1 -0
- package/dist/telemetry-types.d.ts +7 -0
- package/dist/telemetry-types.d.ts.map +1 -0
- package/dist/telemetry-types.js +24 -0
- package/dist/telemetry-types.js.map +1 -0
- package/dist/telemetry.d.ts +9 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +47 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/timing.d.ts +15 -0
- package/dist/timing.d.ts.map +1 -0
- package/dist/timing.js +34 -0
- package/dist/timing.js.map +1 -0
- package/dist/work-item-branch.d.ts +33 -0
- package/dist/work-item-branch.d.ts.map +1 -0
- package/dist/work-item-branch.js +70 -0
- package/dist/work-item-branch.js.map +1 -0
- package/dist/workspace.d.ts +131 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +995 -0
- package/dist/workspace.js.map +1 -0
- package/factory-skills/configure-factory-rules/SKILL.md +122 -0
- package/factory-skills/factory-complete-issue/SKILL.md +24 -0
- package/factory-skills/factory-gitlab-rereview/SKILL.md +22 -0
- package/factory-skills/factory-gitlab-review/SKILL.md +48 -0
- package/factory-skills/factory-plan/SKILL.md +72 -0
- package/factory-skills/factory-rereview/SKILL.md +225 -0
- package/factory-skills/factory-review/SKILL.md +214 -0
- package/factory-skills/factory-review/references/archaeology.md +225 -0
- package/factory-skills/factory-review/references/categories/README.md +34 -0
- package/factory-skills/factory-review/references/categories/behavior-change.md +36 -0
- package/factory-skills/factory-review/references/categories/bug-fix.md +37 -0
- package/factory-skills/factory-review/references/categories/docs.md +32 -0
- package/factory-skills/factory-review/references/categories/experimental-flagged.md +34 -0
- package/factory-skills/factory-review/references/categories/infra-tooling.md +37 -0
- package/factory-skills/factory-review/references/categories/internal-capability.md +35 -0
- package/factory-skills/factory-review/references/categories/large-cross-cutting.md +35 -0
- package/factory-skills/factory-review/references/categories/mechanical.md +36 -0
- package/factory-skills/factory-review/references/categories/performance.md +33 -0
- package/factory-skills/factory-review/references/categories/public-api.md +38 -0
- package/factory-skills/factory-review/references/categories/refactor.md +35 -0
- package/factory-skills/factory-review/references/categories/revert.md +31 -0
- package/factory-skills/factory-review/references/categories/schema-storage.md +39 -0
- package/factory-skills/factory-review/references/categories/security.md +35 -0
- package/factory-skills/factory-review/references/categories/tests-only.md +38 -0
- package/factory-skills/factory-triage/SKILL.md +197 -0
- package/package.json +92 -0
|
@@ -0,0 +1,1159 @@
|
|
|
1
|
+
import { FACTORY_RULE_STAGES, externalSourceForWorkItem, externallyAuthoredWorkItem } from "./types.js";
|
|
2
|
+
import { assertFactoryDecisionTarget, validateFactoryRuleDecision } from "./validation.js";
|
|
3
|
+
import { boardForWorkItem, resolvePhaseSemantics, workItemPhaseSemantics } from "../boards/semantics.js";
|
|
4
|
+
import { createBoardRegistry } from "../boards/registry.js";
|
|
5
|
+
import "../boards/index.js";
|
|
6
|
+
import { FactoryDispatchError, factoryDispatchFailureCode, factoryDispatchFailureMetadata } from "./dispatch-errors.js";
|
|
7
|
+
import { FACTORY_RULE_MATERIALIZATION_KEY, WorkItemClaimConflictError } from "../storage/domains/work-items/base.js";
|
|
8
|
+
import { moveCardToBoard } from "../boards/relocate.js";
|
|
9
|
+
import { isHumanActorId } from "../storage/domains/audit/actors.js";
|
|
10
|
+
import { resolvePromptInvocation, resolveSkillInvocation, resolveSkillResumeInvocation } from "../skills/service.js";
|
|
11
|
+
import { decisionOvertaken } from "./decision-applicability.js";
|
|
12
|
+
import { FACTORY_OPEN_RUN_STALE_MS, heartbeatSessionOpenRun, isOpenRunLiveElsewhere, listSessionOpenRuns, recordSessionRunStart, waitForSessionRunAudit } from "../session/run-audit.js";
|
|
13
|
+
import { withWorkItemFeed } from "../storage/domains/comments/feed-context.js";
|
|
14
|
+
import { RequestContext } from "@mastra/core/request-context";
|
|
15
|
+
//#region src/rules/dispatcher.ts
|
|
16
|
+
const LEASE_MS = 3e4;
|
|
17
|
+
const POLL_MS = 1e3;
|
|
18
|
+
const BATCH_SIZE = 10;
|
|
19
|
+
const MAX_ATTEMPTS = 5;
|
|
20
|
+
const MAX_PLAN_APPROVALS = 3;
|
|
21
|
+
const MAX_ERROR_LENGTH = 512;
|
|
22
|
+
const MAX_BACKOFF_MS = 6e4;
|
|
23
|
+
const RUN_REGISTRY_HEARTBEAT_MS = 10 * 6e4;
|
|
24
|
+
const SKILL_COMPLETION_OBSERVATION_TIMEOUT_MS = 360 * 6e4;
|
|
25
|
+
const MAX_IN_FLIGHT = 25;
|
|
26
|
+
/**
|
|
27
|
+
* Decisions that may start or wake an agent run and so hold a run slot. A
|
|
28
|
+
* transition's message is queued as a separate sendMessage, so the transition
|
|
29
|
+
* itself stays bookkeeping.
|
|
30
|
+
*/
|
|
31
|
+
const isRunBearingDecision = (decision) => decision.type === "invokeSkill" || decision.type === "sendMessage";
|
|
32
|
+
const isBookkeepingDecision = (decision) => !isRunBearingDecision(decision);
|
|
33
|
+
const BOOKKEEPING_MAX_IN_FLIGHT = 4;
|
|
34
|
+
const STALE_BINDING_SWEEP_INTERVAL_MS = 10 * 6e4;
|
|
35
|
+
const STALE_BINDING_TTL_MS = 1440 * 6e4;
|
|
36
|
+
const RECONCILE_INTERVAL_MS = 3e4;
|
|
37
|
+
/** The card moved on before this run could act; it settles as superseded, not succeeded. */
|
|
38
|
+
var FactoryDecisionSuperseded = class extends Error {};
|
|
39
|
+
function isTerminalFailure(attempts, failureCode) {
|
|
40
|
+
return attempts >= MAX_ATTEMPTS || !factoryDispatchFailureMetadata(failureCode).canRetry;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Conservative check for observational-memory failures that a retry cannot fix:
|
|
44
|
+
* a provider rejecting the request outright (HTTP 400 / model unsupported /
|
|
45
|
+
* authentication). Anything ambiguous (timeouts, 5xx, rate limits, network
|
|
46
|
+
* blips) is intentionally left retryable to avoid dead-ending a card that would
|
|
47
|
+
* have recovered on its own.
|
|
48
|
+
*/
|
|
49
|
+
function isPermanentProviderRejection(error) {
|
|
50
|
+
const normalized = error.toLowerCase();
|
|
51
|
+
return /\bhttp(?:\/\d(?:\.\d)?)?\s*400\b/.test(normalized) || /\bstatus(?:\s*code)?\s*[:=]?\s*400\b/.test(normalized) || /\b400\s*(?:bad request|status)\b/.test(normalized) || normalized.includes("model not supported") || normalized.includes("model is not supported") || normalized.includes("unsupported model") || normalized.includes("not supported with") || normalized.includes("unauthorized") || normalized.includes("authentication") || normalized.includes("invalid") && normalized.includes("model");
|
|
52
|
+
}
|
|
53
|
+
function watchRun(session, { timeoutMs, approvePlans, onAgentEnd, label, runStillActive }) {
|
|
54
|
+
let resolveAgentEnd;
|
|
55
|
+
let agentEnd;
|
|
56
|
+
let endReason;
|
|
57
|
+
let supersededAtEnd;
|
|
58
|
+
let parked;
|
|
59
|
+
let omFailure;
|
|
60
|
+
const arm = () => {
|
|
61
|
+
endReason = void 0;
|
|
62
|
+
supersededAtEnd = void 0;
|
|
63
|
+
omFailure = void 0;
|
|
64
|
+
agentEnd = new Promise((resolve) => {
|
|
65
|
+
resolveAgentEnd = resolve;
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
arm();
|
|
69
|
+
const unsubscribe = session.subscribe((event) => {
|
|
70
|
+
if (event.type === "agent_end") {
|
|
71
|
+
endReason = event.reason;
|
|
72
|
+
supersededAtEnd = onAgentEnd?.();
|
|
73
|
+
resolveAgentEnd();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (event.type === "om_observation_failed" || event.type === "om_buffering_failed") {
|
|
77
|
+
if (event.error) omFailure = event.error;
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (event.type === "tool_suspended") {
|
|
81
|
+
parked = {
|
|
82
|
+
toolName: event.toolName,
|
|
83
|
+
toolCallId: event.toolCallId
|
|
84
|
+
};
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (event.type === "tool_suspension_cancelled" && parked?.toolCallId === event.toolCallId) parked = void 0;
|
|
88
|
+
});
|
|
89
|
+
const wait = async () => {
|
|
90
|
+
const deadline = Date.now() + timeoutMs;
|
|
91
|
+
while (Date.now() < deadline) {
|
|
92
|
+
const heartbeatMs = Math.min(RUN_REGISTRY_HEARTBEAT_MS, deadline - Date.now());
|
|
93
|
+
if (await waitForAgentEndOrTimeout(agentEnd, heartbeatMs)) return true;
|
|
94
|
+
if (!runStillActive()) return false;
|
|
95
|
+
}
|
|
96
|
+
throw new FactoryDispatchError("run_overdue", `${label} is still in flight after ${Math.round(timeoutMs / 36e5)} hours and needs a person.`);
|
|
97
|
+
};
|
|
98
|
+
return {
|
|
99
|
+
arm,
|
|
100
|
+
wait,
|
|
101
|
+
supersededAtEnd: () => supersededAtEnd,
|
|
102
|
+
endReason: () => endReason,
|
|
103
|
+
close: unsubscribe,
|
|
104
|
+
/** The run's own verdict, thrown as what the dispatcher should record. */
|
|
105
|
+
async settle() {
|
|
106
|
+
let observed = await wait();
|
|
107
|
+
if (approvePlans) for (let approvals = 0; parked?.toolName === "submit_plan" && approvals < MAX_PLAN_APPROVALS; approvals += 1) {
|
|
108
|
+
const { toolCallId } = parked;
|
|
109
|
+
parked = void 0;
|
|
110
|
+
arm();
|
|
111
|
+
await session.respondToToolSuspension({
|
|
112
|
+
resumeData: { action: "approved" },
|
|
113
|
+
toolCallId
|
|
114
|
+
});
|
|
115
|
+
observed = await wait();
|
|
116
|
+
}
|
|
117
|
+
if (!observed) throw new FactoryDispatchError("run_terminal_event_missing", `${label} terminal event was not observed before timeout.`);
|
|
118
|
+
if (endReason === "error") throw new Error(`${label} ended in error.`);
|
|
119
|
+
if (endReason === "aborted") {
|
|
120
|
+
if (omFailure) {
|
|
121
|
+
if (isPermanentProviderRejection(omFailure)) throw new FactoryDispatchError("run_configuration_invalid", `${label} was aborted by an observational-memory failure that will not succeed on retry: ${omFailure}`);
|
|
122
|
+
throw new Error(`${label} was aborted after an observational-memory failure: ${omFailure}`);
|
|
123
|
+
}
|
|
124
|
+
throw new Error(`${label} was aborted before it finished.`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function waitForAgentEndOrTimeout(agentEnd, timeoutMs) {
|
|
130
|
+
return new Promise((resolve) => {
|
|
131
|
+
const timeout = setTimeout(() => resolve(false), timeoutMs);
|
|
132
|
+
timeout.unref?.();
|
|
133
|
+
agentEnd.then(() => {
|
|
134
|
+
clearTimeout(timeout);
|
|
135
|
+
resolve(true);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
function factoryRequestContext(input) {
|
|
140
|
+
const { session, binding, userId, orgId } = input;
|
|
141
|
+
const requestContext = new RequestContext();
|
|
142
|
+
requestContext.set("user", {
|
|
143
|
+
workosId: userId,
|
|
144
|
+
organizationId: orgId
|
|
145
|
+
});
|
|
146
|
+
requestContext.set("controller", {
|
|
147
|
+
state: session.state.get(),
|
|
148
|
+
getState: () => session.state.get(),
|
|
149
|
+
threadId: binding.threadId,
|
|
150
|
+
resourceId: binding.resourceId,
|
|
151
|
+
session: {
|
|
152
|
+
id: session.identity.getId(),
|
|
153
|
+
ownerId: session.identity.getOwnerId(),
|
|
154
|
+
modelId: session.model.get() ?? ""
|
|
155
|
+
},
|
|
156
|
+
workspace: session.getWorkspace()
|
|
157
|
+
});
|
|
158
|
+
return requestContext;
|
|
159
|
+
}
|
|
160
|
+
function positiveMs(value, fallback) {
|
|
161
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
|
|
162
|
+
}
|
|
163
|
+
function sanitizeDispatchError(error) {
|
|
164
|
+
return (error instanceof Error ? error.message : String(error)).replace(/\b(?:bearer|token|api[-_ ]?key|authorization)\s*[:=]?\s*[^\s,;]+/gi, "[redacted]").slice(0, MAX_ERROR_LENGTH);
|
|
165
|
+
}
|
|
166
|
+
function retryAt(now, attempts) {
|
|
167
|
+
return new Date(now.getTime() + Math.min(1e3 * 2 ** Math.max(0, attempts - 1), MAX_BACKOFF_MS));
|
|
168
|
+
}
|
|
169
|
+
function externalSourceForDecision(decision) {
|
|
170
|
+
return externalSourceForWorkItem(decision.source, decision.sourceKey, decision.url ?? void 0);
|
|
171
|
+
}
|
|
172
|
+
function deferredActor(record) {
|
|
173
|
+
const actor = record.actor;
|
|
174
|
+
if (actor?.type === "github" && typeof actor.login === "string" && typeof actor.trusted === "boolean" && typeof actor.factoryAuthored === "boolean") return {
|
|
175
|
+
type: "github",
|
|
176
|
+
login: actor.login,
|
|
177
|
+
trusted: actor.trusted,
|
|
178
|
+
factoryAuthored: actor.factoryAuthored
|
|
179
|
+
};
|
|
180
|
+
if (actor?.type === "gitlab" && typeof actor.username === "string" && typeof actor.trusted === "boolean" && typeof actor.factoryAuthored === "boolean") return {
|
|
181
|
+
type: "gitlab",
|
|
182
|
+
username: actor.username,
|
|
183
|
+
trusted: actor.trusted,
|
|
184
|
+
factoryAuthored: actor.factoryAuthored
|
|
185
|
+
};
|
|
186
|
+
return {
|
|
187
|
+
type: "system",
|
|
188
|
+
id: "factory-rule-dispatcher"
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function externalActor(actor) {
|
|
192
|
+
return actor !== null && actor.type !== "human" && actor.type !== "agent" && actor.type !== "system";
|
|
193
|
+
}
|
|
194
|
+
/** A run start asks for consent; an external event asks before pulling a card back into a working lane. */
|
|
195
|
+
function requestsConsent(boards, record, decision) {
|
|
196
|
+
if (decision.type === "invokeSkill") return true;
|
|
197
|
+
if (decision.type !== "transition" || !externalActor(record.actor)) return false;
|
|
198
|
+
return (resolvePhaseSemantics(boards, decision.board, decision.stage)?.kind ?? "working") === "working";
|
|
199
|
+
}
|
|
200
|
+
function reviewsFactoryAuthoredCode(item, decision) {
|
|
201
|
+
if (item.metadata?.factoryAuthored !== true) return false;
|
|
202
|
+
if (decision.type === "transition") return decision.board === "review" && decision.stage === "review";
|
|
203
|
+
return decision.type === "invokeSkill" && decision.role === "review";
|
|
204
|
+
}
|
|
205
|
+
function leaseIdentity(record, ownerId) {
|
|
206
|
+
return {
|
|
207
|
+
id: record.id,
|
|
208
|
+
orgId: record.orgId,
|
|
209
|
+
factoryProjectId: record.factoryProjectId,
|
|
210
|
+
ownerId
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
async function awaitNotification(send, requireDelivery = false) {
|
|
214
|
+
try {
|
|
215
|
+
const notification = await send();
|
|
216
|
+
const [, accepted] = await Promise.all([notification.persisted, notification.accepted]);
|
|
217
|
+
if (!accepted) {
|
|
218
|
+
if (requireDelivery) throw new FactoryDispatchError("notification_delivery_failed", "Factory notification was persisted without agent delivery.");
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if (!requireDelivery) return accepted;
|
|
222
|
+
if (accepted.action === "wake") {
|
|
223
|
+
if (!accepted.output) throw new FactoryDispatchError("notification_delivery_failed", "Factory notification wake had no output.");
|
|
224
|
+
await accepted.output.consumeStream();
|
|
225
|
+
return accepted;
|
|
226
|
+
}
|
|
227
|
+
if (accepted.action !== "deliver") throw new FactoryDispatchError("notification_delivery_failed", `Factory notification did not reach the agent (${String(accepted.action)}).`);
|
|
228
|
+
return accepted;
|
|
229
|
+
} catch (error) {
|
|
230
|
+
if (error instanceof FactoryDispatchError) throw error;
|
|
231
|
+
throw new FactoryDispatchError("notification_delivery_failed", `Factory notification delivery failed: ${sanitizeDispatchError(error)}`, { cause: error });
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
var FactoryDecisionDispatcher = class {
|
|
235
|
+
#audit;
|
|
236
|
+
#controller;
|
|
237
|
+
#transitionService;
|
|
238
|
+
#boards;
|
|
239
|
+
#storage;
|
|
240
|
+
#ownerId;
|
|
241
|
+
#isAutoRunEnabled;
|
|
242
|
+
#autoApprovePlans;
|
|
243
|
+
#reconcileToolResults;
|
|
244
|
+
#prepareBinding;
|
|
245
|
+
#primeCredentials;
|
|
246
|
+
#feedReader;
|
|
247
|
+
#dismissStaleReviews;
|
|
248
|
+
#resolveLinkedWorkItemParentId;
|
|
249
|
+
#maxInFlight;
|
|
250
|
+
#staleBindingSweepIntervalMs;
|
|
251
|
+
#staleBindingTtlMs;
|
|
252
|
+
#lastStaleBindingSweepAt;
|
|
253
|
+
#reconcileIntervalMs;
|
|
254
|
+
#skillCompletionObservationTimeoutMs;
|
|
255
|
+
#lastReconcileAt;
|
|
256
|
+
#reconcileInFlight;
|
|
257
|
+
#timer;
|
|
258
|
+
#activeClaim;
|
|
259
|
+
/** Starts and run-bearing decisions; capped by `maxInFlight`. */
|
|
260
|
+
#runInFlight = /* @__PURE__ */ new Set();
|
|
261
|
+
/** Fast board bookkeeping (transitions, linked-card upserts); its own small cap. */
|
|
262
|
+
#bookkeepingInFlight = /* @__PURE__ */ new Set();
|
|
263
|
+
/** Background work awaited on stop but outside both caps. */
|
|
264
|
+
#backgroundInFlight = /* @__PURE__ */ new Set();
|
|
265
|
+
#bindingSkillRuns = /* @__PURE__ */ new Map();
|
|
266
|
+
constructor(options) {
|
|
267
|
+
this.#audit = options.audit;
|
|
268
|
+
this.#controller = options.controller;
|
|
269
|
+
this.#transitionService = options.transitionService;
|
|
270
|
+
this.#boards = options.boards ?? createBoardRegistry();
|
|
271
|
+
this.#storage = options.storage;
|
|
272
|
+
this.#ownerId = options.ownerId ?? `factory-dispatcher:${globalThis.crypto.randomUUID()}`;
|
|
273
|
+
this.#isAutoRunEnabled = options.isAutoRunEnabled;
|
|
274
|
+
this.#autoApprovePlans = options.autoApprovePlans;
|
|
275
|
+
this.#reconcileToolResults = options.reconcileToolResults;
|
|
276
|
+
this.#prepareBinding = options.prepareBinding;
|
|
277
|
+
this.#primeCredentials = options.primeCredentials;
|
|
278
|
+
this.#feedReader = options.feedReader;
|
|
279
|
+
this.#dismissStaleReviews = options.dismissStaleReviews;
|
|
280
|
+
this.#resolveLinkedWorkItemParentId = options.resolveLinkedWorkItemParentId;
|
|
281
|
+
const maxInFlight = options.maxInFlight ?? MAX_IN_FLIGHT;
|
|
282
|
+
this.#maxInFlight = Number.isFinite(maxInFlight) && maxInFlight > 0 ? Math.floor(maxInFlight) : MAX_IN_FLIGHT;
|
|
283
|
+
this.#staleBindingSweepIntervalMs = positiveMs(options.staleBindingSweepIntervalMs, STALE_BINDING_SWEEP_INTERVAL_MS);
|
|
284
|
+
this.#staleBindingTtlMs = positiveMs(options.staleBindingTtlMs, STALE_BINDING_TTL_MS);
|
|
285
|
+
this.#reconcileIntervalMs = positiveMs(options.reconcileIntervalMs, RECONCILE_INTERVAL_MS);
|
|
286
|
+
this.#skillCompletionObservationTimeoutMs = positiveMs(options.skillCompletionObservationTimeoutMs, SKILL_COMPLETION_OBSERVATION_TIMEOUT_MS);
|
|
287
|
+
}
|
|
288
|
+
start() {
|
|
289
|
+
if (this.#timer) return;
|
|
290
|
+
this.#tick();
|
|
291
|
+
this.#timer = setInterval(() => void this.#tick(), POLL_MS);
|
|
292
|
+
this.#timer.unref?.();
|
|
293
|
+
}
|
|
294
|
+
async stop() {
|
|
295
|
+
if (this.#timer) clearInterval(this.#timer);
|
|
296
|
+
this.#timer = void 0;
|
|
297
|
+
await this.#activeClaim;
|
|
298
|
+
await Promise.allSettled([
|
|
299
|
+
...this.#runInFlight,
|
|
300
|
+
...this.#bookkeepingInFlight,
|
|
301
|
+
...this.#backgroundInFlight
|
|
302
|
+
]);
|
|
303
|
+
}
|
|
304
|
+
async runOnce(now = /* @__PURE__ */ new Date()) {
|
|
305
|
+
await Promise.all(await this.#claimAndStart(now));
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Claims a batch and starts dispatches without awaiting their completion.
|
|
309
|
+
* Dispatches can legitimately take minutes (skill kickoffs consume the
|
|
310
|
+
* agent's run stream; binding preparation provisions sandboxes), so awaiting
|
|
311
|
+
* them here would freeze the poll loop and starve every other queued
|
|
312
|
+
* decision. In-flight records stay protected from re-claim by lease renewal.
|
|
313
|
+
*/
|
|
314
|
+
async #claimAndStart(now) {
|
|
315
|
+
this.#maybeSweepStaleBindings(now);
|
|
316
|
+
this.#maybeReconcileToolResults(now);
|
|
317
|
+
const leaseExpiresAt = new Date(now.getTime() + LEASE_MS);
|
|
318
|
+
const dispatches = [];
|
|
319
|
+
const runCapacity = this.#maxInFlight - this.#runInFlight.size;
|
|
320
|
+
if (runCapacity > 0) {
|
|
321
|
+
const limit = Math.min(BATCH_SIZE, runCapacity);
|
|
322
|
+
const starts = await this.#storage.claimPendingStarts({
|
|
323
|
+
ownerId: this.#ownerId,
|
|
324
|
+
now,
|
|
325
|
+
leaseExpiresAt,
|
|
326
|
+
limit
|
|
327
|
+
});
|
|
328
|
+
const decisionsLimit = limit - starts.length;
|
|
329
|
+
const decisions = decisionsLimit > 0 ? await this.#storage.claimDeferredDecisions({
|
|
330
|
+
ownerId: this.#ownerId,
|
|
331
|
+
now,
|
|
332
|
+
leaseExpiresAt,
|
|
333
|
+
limit: decisionsLimit,
|
|
334
|
+
decisionFilter: isRunBearingDecision
|
|
335
|
+
}) : [];
|
|
336
|
+
dispatches.push(...starts.map((start) => this.#track(this.#runInFlight, this.#dispatchPendingStart(start, now))), ...decisions.map((decision) => this.#track(this.#runInFlight, this.#dispatchDecision(decision, now))));
|
|
337
|
+
}
|
|
338
|
+
const bookkeepingCapacity = BOOKKEEPING_MAX_IN_FLIGHT - this.#bookkeepingInFlight.size;
|
|
339
|
+
if (bookkeepingCapacity > 0) {
|
|
340
|
+
const decisions = await this.#storage.claimDeferredDecisions({
|
|
341
|
+
ownerId: this.#ownerId,
|
|
342
|
+
now,
|
|
343
|
+
leaseExpiresAt,
|
|
344
|
+
limit: Math.min(BATCH_SIZE, bookkeepingCapacity),
|
|
345
|
+
decisionFilter: isBookkeepingDecision
|
|
346
|
+
});
|
|
347
|
+
dispatches.push(...decisions.map((decision) => this.#track(this.#bookkeepingInFlight, this.#dispatchDecision(decision, now))));
|
|
348
|
+
}
|
|
349
|
+
return dispatches;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Throttled, coalesced, non-blocking bound-thread reconcile: dispatch
|
|
353
|
+
* claiming never waits behind cursor + message reads, and overlapping runs
|
|
354
|
+
* are skipped while one is still in flight.
|
|
355
|
+
*/
|
|
356
|
+
#maybeReconcileToolResults(now) {
|
|
357
|
+
if (!this.#reconcileToolResults || this.#reconcileInFlight) return;
|
|
358
|
+
if (this.#lastReconcileAt && now.getTime() - this.#lastReconcileAt.getTime() < this.#reconcileIntervalMs) return;
|
|
359
|
+
this.#lastReconcileAt = now;
|
|
360
|
+
const run = this.#reconcileToolResults().catch((error) => {
|
|
361
|
+
console.error("Factory tool-result reconcile failed", sanitizeDispatchError(error));
|
|
362
|
+
}).finally(() => {
|
|
363
|
+
this.#reconcileInFlight = void 0;
|
|
364
|
+
});
|
|
365
|
+
this.#reconcileInFlight = run;
|
|
366
|
+
this.#track(this.#backgroundInFlight, run);
|
|
367
|
+
}
|
|
368
|
+
/** Slow-cadence revocation of leaked/legacy bindings; failures never block the claim path. */
|
|
369
|
+
async #maybeSweepStaleBindings(now) {
|
|
370
|
+
if (!this.#lastStaleBindingSweepAt) {
|
|
371
|
+
this.#lastStaleBindingSweepAt = now;
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
if (now.getTime() - this.#lastStaleBindingSweepAt.getTime() < this.#staleBindingSweepIntervalMs) return;
|
|
375
|
+
this.#lastStaleBindingSweepAt = now;
|
|
376
|
+
try {
|
|
377
|
+
const revoked = await this.#storage.revokeStaleRunBindings({
|
|
378
|
+
olderThan: new Date(now.getTime() - this.#staleBindingTtlMs),
|
|
379
|
+
now
|
|
380
|
+
});
|
|
381
|
+
if (revoked > 0) console.info(`Factory stale-binding sweep revoked ${revoked} binding(s)`);
|
|
382
|
+
} catch (error) {
|
|
383
|
+
console.error("Factory stale-binding sweep failed", sanitizeDispatchError(error));
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
#track(pool, dispatch) {
|
|
387
|
+
pool.add(dispatch);
|
|
388
|
+
dispatch.catch(() => {}).then(() => pool.delete(dispatch));
|
|
389
|
+
return dispatch;
|
|
390
|
+
}
|
|
391
|
+
async #tick() {
|
|
392
|
+
if (this.#activeClaim) return;
|
|
393
|
+
this.#activeClaim = this.#claimAndStart(/* @__PURE__ */ new Date()).then((dispatches) => {
|
|
394
|
+
for (const dispatch of dispatches) dispatch.catch((error) => {
|
|
395
|
+
console.error("Factory decision dispatch failed", sanitizeDispatchError(error));
|
|
396
|
+
});
|
|
397
|
+
}, (error) => {
|
|
398
|
+
console.error("Factory decision dispatch cycle failed", sanitizeDispatchError(error));
|
|
399
|
+
});
|
|
400
|
+
try {
|
|
401
|
+
await this.#activeClaim;
|
|
402
|
+
} finally {
|
|
403
|
+
this.#activeClaim = void 0;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
async #dispatchDecision(record, now) {
|
|
407
|
+
let executionCompleted = false;
|
|
408
|
+
try {
|
|
409
|
+
const decision = validateFactoryRuleDecision(record.decision, record.causalChain.length);
|
|
410
|
+
if (decision.type === "reject") throw new Error("Deferred Factory decisions cannot reject.");
|
|
411
|
+
if (await this.#needsApproval(record, decision)) {
|
|
412
|
+
if (!await this.#storage.proposeDeferredDecision(leaseIdentity(record, this.#ownerId), /* @__PURE__ */ new Date())) throw new Error("Factory decision lease was lost before approval could be requested.");
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
await this.#supersedeProposals(record, decision);
|
|
416
|
+
await this.#withLease(async (leaseExpiresAt) => this.#storage.renewDeferredDecisionLease(leaseIdentity(record, this.#ownerId), leaseExpiresAt), async () => this.#executeDecision(record, decision));
|
|
417
|
+
executionCompleted = true;
|
|
418
|
+
if (!await this.#storage.completeDeferredDecision(leaseIdentity(record, this.#ownerId), /* @__PURE__ */ new Date())) throw new Error("Factory decision lease was lost before completion.");
|
|
419
|
+
} catch (error) {
|
|
420
|
+
if (error instanceof FactoryDecisionSuperseded) {
|
|
421
|
+
await this.#storage.supersedeLeasedDecision(leaseIdentity(record, this.#ownerId), /* @__PURE__ */ new Date());
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
const failureCode = factoryDispatchFailureCode(error);
|
|
425
|
+
const terminal = isTerminalFailure(record.attempts, failureCode);
|
|
426
|
+
const failed = await this.#storage.failDeferredDecision({
|
|
427
|
+
...leaseIdentity(record, this.#ownerId),
|
|
428
|
+
now: /* @__PURE__ */ new Date(),
|
|
429
|
+
availableAt: retryAt(now, record.attempts),
|
|
430
|
+
lastError: sanitizeDispatchError(error),
|
|
431
|
+
failureCode,
|
|
432
|
+
terminal,
|
|
433
|
+
advanceDeliveryGeneration: !executionCompleted
|
|
434
|
+
});
|
|
435
|
+
if (terminal && failed) await this.#supersedeFailureOnSettledCard(failed);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Startup repair and terminal cleanup already settle a failed effect on a done or canceled
|
|
440
|
+
* card as superseded; a failure landing after the card settled would otherwise page a person
|
|
441
|
+
* until the next restart.
|
|
442
|
+
*/
|
|
443
|
+
async #supersedeFailureOnSettledCard(record) {
|
|
444
|
+
if (!record.workItemId) return;
|
|
445
|
+
try {
|
|
446
|
+
const item = await this.#storage.get({
|
|
447
|
+
orgId: record.orgId,
|
|
448
|
+
id: record.workItemId
|
|
449
|
+
});
|
|
450
|
+
if (!item || workItemPhaseSemantics(this.#boards, item)?.kind !== "terminal") return;
|
|
451
|
+
await this.#storage.supersedeDecisionsForWorkItem({
|
|
452
|
+
orgId: record.orgId,
|
|
453
|
+
factoryProjectId: record.factoryProjectId,
|
|
454
|
+
workItemId: record.workItemId,
|
|
455
|
+
supersededAt: /* @__PURE__ */ new Date()
|
|
456
|
+
});
|
|
457
|
+
} catch (error) {
|
|
458
|
+
console.error("Factory settled-card supersede failed", sanitizeDispatchError(error));
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* A proposal is a question: "should this run start?" Once that run is
|
|
463
|
+
* starting anyway — because a person approved a later copy, or armed the item
|
|
464
|
+
* — the question has been answered and the card must stop asking it. Left
|
|
465
|
+
* alone the badge outlives the work it describes, and the one affordance that
|
|
466
|
+
* means "the loop is stopped, answer this" cries wolf.
|
|
467
|
+
*/
|
|
468
|
+
async #supersedeProposals(record, decision) {
|
|
469
|
+
if (decision.type !== "invokeSkill" || !record.workItemId) return;
|
|
470
|
+
try {
|
|
471
|
+
await this.#storage.supersedeDecisionsForWorkItem({
|
|
472
|
+
orgId: record.orgId,
|
|
473
|
+
factoryProjectId: record.factoryProjectId,
|
|
474
|
+
workItemId: record.workItemId,
|
|
475
|
+
role: decision.role,
|
|
476
|
+
supersededAt: /* @__PURE__ */ new Date()
|
|
477
|
+
});
|
|
478
|
+
} catch (error) {
|
|
479
|
+
console.error("Factory proposal supersede failed", sanitizeDispatchError(error));
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
async #needsApproval(record, decision) {
|
|
483
|
+
if (record.approvedAt !== null || !requestsConsent(this.#boards, record, decision)) return false;
|
|
484
|
+
const item = record.workItemId ? await this.#storage.get({
|
|
485
|
+
orgId: record.orgId,
|
|
486
|
+
id: record.workItemId
|
|
487
|
+
}) : null;
|
|
488
|
+
if (item && externallyAuthoredWorkItem(item)) return true;
|
|
489
|
+
if (item?.autonomyArmedAt != null) return false;
|
|
490
|
+
if (item && reviewsFactoryAuthoredCode(item, decision)) return false;
|
|
491
|
+
return !await this.#isAutoRunEnabled({
|
|
492
|
+
orgId: record.orgId,
|
|
493
|
+
factoryProjectId: record.factoryProjectId
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
async #executeDecision(record, decision) {
|
|
497
|
+
const nextChain = [...record.causalChain, {
|
|
498
|
+
ingressId: record.idempotencyKey,
|
|
499
|
+
decisionType: decision.type
|
|
500
|
+
}];
|
|
501
|
+
if (nextChain.length > 8) throw new Error("Factory rule causal depth exceeded.");
|
|
502
|
+
switch (decision.type) {
|
|
503
|
+
case "transition": {
|
|
504
|
+
const item = await this.#requireItem(record);
|
|
505
|
+
if (!await this.#storage.getTransitionResultByIngress(record.orgId, record.factoryProjectId, `decision:${record.idempotencyKey}`)) assertFactoryDecisionTarget(decision, this.#boards, item.board ?? void 0);
|
|
506
|
+
const result = await this.#transitionService.transition({
|
|
507
|
+
orgId: record.orgId,
|
|
508
|
+
factoryProjectId: record.factoryProjectId,
|
|
509
|
+
workItemId: item.id,
|
|
510
|
+
board: decision.board,
|
|
511
|
+
stage: decision.stage,
|
|
512
|
+
expectedRevision: item.revision,
|
|
513
|
+
actor: record.approvedBy ? {
|
|
514
|
+
type: "human",
|
|
515
|
+
id: record.approvedBy
|
|
516
|
+
} : {
|
|
517
|
+
type: "system",
|
|
518
|
+
id: "factory-rule-dispatcher"
|
|
519
|
+
},
|
|
520
|
+
ingress: {
|
|
521
|
+
type: "rule",
|
|
522
|
+
identity: `decision:${record.idempotencyKey}`
|
|
523
|
+
},
|
|
524
|
+
cause: "rule_decision",
|
|
525
|
+
causalChain: nextChain,
|
|
526
|
+
...decision.reenter ? { reenter: true } : {}
|
|
527
|
+
});
|
|
528
|
+
if (result.status === "rejected") throw new Error(`${result.code}: ${result.reason}`);
|
|
529
|
+
const transitionMessage = decision.message;
|
|
530
|
+
if (!transitionMessage) return;
|
|
531
|
+
const moved = await this.#storage.get({
|
|
532
|
+
orgId: record.orgId,
|
|
533
|
+
id: item.id
|
|
534
|
+
});
|
|
535
|
+
if (!moved) return;
|
|
536
|
+
const messageKey = `${record.idempotencyKey}:message`;
|
|
537
|
+
const queued = await this.#storage.commitRuleEvaluation({
|
|
538
|
+
orgId: record.orgId,
|
|
539
|
+
factoryProjectId: record.factoryProjectId,
|
|
540
|
+
workItemId: item.id,
|
|
541
|
+
ingress: {
|
|
542
|
+
identity: `decision:${messageKey}@${moved.revision}`,
|
|
543
|
+
triggerType: "transition.message"
|
|
544
|
+
},
|
|
545
|
+
configVersion: this.#transitionService.configVersion,
|
|
546
|
+
expectedRevision: moved.revision,
|
|
547
|
+
actor: record.actor ?? {
|
|
548
|
+
type: "system",
|
|
549
|
+
id: "factory-rule-dispatcher"
|
|
550
|
+
},
|
|
551
|
+
outcome: { status: "accepted" },
|
|
552
|
+
decisions: [{
|
|
553
|
+
type: "sendMessage",
|
|
554
|
+
idempotencyKey: messageKey,
|
|
555
|
+
message: transitionMessage.text,
|
|
556
|
+
priority: "high",
|
|
557
|
+
idleBehavior: "wake",
|
|
558
|
+
...transitionMessage.role !== void 0 ? { role: transitionMessage.role } : {}
|
|
559
|
+
}],
|
|
560
|
+
causalChain: nextChain,
|
|
561
|
+
now: /* @__PURE__ */ new Date()
|
|
562
|
+
});
|
|
563
|
+
if (queued.status === "missing") return;
|
|
564
|
+
if (queued.status === "stale") throw new Error("Factory transition message was not queued: the work item changed concurrently.");
|
|
565
|
+
const queuedStatus = queued.result.status;
|
|
566
|
+
if (queuedStatus !== "accepted") throw new Error(`Factory transition message was not queued: ${queuedStatus ?? "unknown"}.`);
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
case "upsertLinkedWorkItem":
|
|
570
|
+
await this.#upsertLinkedItem(record, decision, nextChain);
|
|
571
|
+
return;
|
|
572
|
+
case "invokeSkill": {
|
|
573
|
+
if (await this.#roleSuperseded(record, decision.role) || await this.#decisionOvertaken(record, decision.role)) throw new FactoryDecisionSuperseded();
|
|
574
|
+
const binding = await this.#requireOrPrepareBinding(record, decision.role);
|
|
575
|
+
await this.#withBindingSkillRun(binding.id, async () => {
|
|
576
|
+
const item = record.workItemId ? await this.#storage.get({
|
|
577
|
+
orgId: record.orgId,
|
|
578
|
+
id: record.workItemId
|
|
579
|
+
}) : null;
|
|
580
|
+
const startedBy = item?.sessions[binding.role]?.startedBy;
|
|
581
|
+
if (!startedBy) throw new Error(`Factory binding ${binding.id} has no authenticated session owner.`);
|
|
582
|
+
await this.#primeCredentials?.({
|
|
583
|
+
orgId: record.orgId,
|
|
584
|
+
userId: startedBy
|
|
585
|
+
});
|
|
586
|
+
const session = await this.#requireSession(binding);
|
|
587
|
+
const requestContext = factoryRequestContext({
|
|
588
|
+
session,
|
|
589
|
+
binding,
|
|
590
|
+
userId: startedBy,
|
|
591
|
+
orgId: record.orgId
|
|
592
|
+
});
|
|
593
|
+
const resolved = decision.skillName === void 0 ? await resolvePromptInvocation(this.#controller, {
|
|
594
|
+
resourceId: binding.resourceId,
|
|
595
|
+
prompt: decision.prompt
|
|
596
|
+
}) : decision.resume === true ? await resolveSkillResumeInvocation(this.#controller, {
|
|
597
|
+
resourceId: binding.resourceId,
|
|
598
|
+
name: decision.skillName,
|
|
599
|
+
arguments: decision.arguments
|
|
600
|
+
}) : await resolveSkillInvocation(this.#controller, {
|
|
601
|
+
resourceId: binding.resourceId,
|
|
602
|
+
name: decision.skillName,
|
|
603
|
+
arguments: decision.arguments
|
|
604
|
+
});
|
|
605
|
+
await this.#switchThread(session, binding);
|
|
606
|
+
const deliveryId = record.deliveryGeneration === 0 ? record.id : `${record.id}:retry:${record.deliveryGeneration}`;
|
|
607
|
+
const kickoffLanded = async () => (await session.thread.listActiveMessages()).some((message) => message.id === deliveryId);
|
|
608
|
+
const kickoffStale = async () => await this.#roleSuperseded(record, decision.role) || (await this.#findBinding(record, decision.role))?.id !== binding.id || await this.#decisionOvertaken(record, decision.role);
|
|
609
|
+
const runStillActive = () => this.#controller.listActiveThreadRuns().some((active) => active.threadId === binding.threadId);
|
|
610
|
+
while (true) {
|
|
611
|
+
const openRun = watchRun(session, {
|
|
612
|
+
timeoutMs: this.#skillCompletionObservationTimeoutMs,
|
|
613
|
+
approvePlans: false,
|
|
614
|
+
label: "Factory skill run",
|
|
615
|
+
runStillActive
|
|
616
|
+
});
|
|
617
|
+
try {
|
|
618
|
+
const open = (await listSessionOpenRuns(session)).filter((entry) => entry.bindingId === binding.id);
|
|
619
|
+
if (open.length === 0) break;
|
|
620
|
+
if (open.some((entry) => isOpenRunLiveElsewhere(entry, this.#ownerId))) throw new FactoryDispatchError("session_unavailable", `Factory binding ${binding.id} has a run in flight on another dispatcher.`);
|
|
621
|
+
if (!runStillActive()) break;
|
|
622
|
+
if (!await openRun.wait()) break;
|
|
623
|
+
} finally {
|
|
624
|
+
openRun.close();
|
|
625
|
+
}
|
|
626
|
+
await waitForSessionRunAudit(session);
|
|
627
|
+
}
|
|
628
|
+
if (await this.#roleSuperseded(record, decision.role)) throw new FactoryDecisionSuperseded();
|
|
629
|
+
if ((await this.#requireBinding(record, decision.role)).id !== binding.id) throw new FactoryDispatchError("session_unavailable", `Factory binding ${binding.id} changed while waiting for its open run to end.`);
|
|
630
|
+
if (await kickoffLanded()) return;
|
|
631
|
+
if (await kickoffStale()) throw new FactoryDecisionSuperseded();
|
|
632
|
+
const kickoffContents = await withWorkItemFeed(this.#feedReader, {
|
|
633
|
+
orgId: record.orgId,
|
|
634
|
+
factoryProjectId: record.factoryProjectId,
|
|
635
|
+
workItemId: record.workItemId
|
|
636
|
+
}, resolved.message);
|
|
637
|
+
if (await kickoffLanded()) return;
|
|
638
|
+
if (await kickoffStale()) throw new FactoryDecisionSuperseded();
|
|
639
|
+
if (decision.cancelInFlight && session.stream.isActive()) session.abort();
|
|
640
|
+
const precedingMessage = decision.precedingMessage;
|
|
641
|
+
if (precedingMessage) {
|
|
642
|
+
await awaitNotification(() => session.sendNotificationSignal({
|
|
643
|
+
source: "factory",
|
|
644
|
+
kind: "stage-transition",
|
|
645
|
+
summary: precedingMessage,
|
|
646
|
+
priority: "medium",
|
|
647
|
+
payload: { message: precedingMessage },
|
|
648
|
+
sourceId: `${record.id}:stage-transition`,
|
|
649
|
+
dedupeKey: `${record.idempotencyKey}:stage-transition`
|
|
650
|
+
}, {
|
|
651
|
+
ifActive: { behavior: "deliver" },
|
|
652
|
+
ifIdle: { behavior: "persist" },
|
|
653
|
+
requestContext
|
|
654
|
+
}));
|
|
655
|
+
if (await kickoffStale()) throw new FactoryDecisionSuperseded();
|
|
656
|
+
}
|
|
657
|
+
const run = watchRun(session, {
|
|
658
|
+
timeoutMs: this.#skillCompletionObservationTimeoutMs,
|
|
659
|
+
approvePlans: await this.#plansAreAutoApproved(record),
|
|
660
|
+
onAgentEnd: () => this.#roleSuperseded(record, decision.role),
|
|
661
|
+
label: "Factory skill run",
|
|
662
|
+
runStillActive
|
|
663
|
+
});
|
|
664
|
+
const sendKickoff = async () => {
|
|
665
|
+
const settled = await session.sendSignal({
|
|
666
|
+
id: deliveryId,
|
|
667
|
+
type: "user",
|
|
668
|
+
tagName: "user",
|
|
669
|
+
contents: kickoffContents
|
|
670
|
+
}, {
|
|
671
|
+
requestContext,
|
|
672
|
+
requireDelivery: true
|
|
673
|
+
}).accepted;
|
|
674
|
+
if (settled.action !== "wake" && settled.action !== "deliver") throw new FactoryDispatchError(settled.action ? "notification_delivery_failed" : "skill_delivery_ambiguous", `Factory skill invocation signal did not reach the agent (${String(settled.action)}).`);
|
|
675
|
+
return settled;
|
|
676
|
+
};
|
|
677
|
+
try {
|
|
678
|
+
let settled = await sendKickoff();
|
|
679
|
+
while (settled.action === "deliver") {
|
|
680
|
+
if (await kickoffLanded()) break;
|
|
681
|
+
if (!await run.wait()) throw new FactoryDispatchError("run_terminal_event_missing", "Factory skill invocation is waiting on a run whose terminal event was not observed.");
|
|
682
|
+
if (await kickoffLanded()) break;
|
|
683
|
+
if (await kickoffStale()) throw new FactoryDecisionSuperseded();
|
|
684
|
+
run.arm();
|
|
685
|
+
settled = await sendKickoff();
|
|
686
|
+
}
|
|
687
|
+
await this.#recordRunStart(session, binding, deliveryId, record.approvedBy ?? void 0, run.endReason, item?.title);
|
|
688
|
+
try {
|
|
689
|
+
await this.#withOpenRunHeartbeat(session, deliveryId, () => run.settle());
|
|
690
|
+
} catch (error) {
|
|
691
|
+
if (!(await run.supersededAtEnd() ?? await this.#roleSuperseded(record, decision.role))) throw error;
|
|
692
|
+
}
|
|
693
|
+
} finally {
|
|
694
|
+
run.close();
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
case "sendMessage": {
|
|
700
|
+
const binding = await this.#messageBinding(record, decision);
|
|
701
|
+
if (!binding) return;
|
|
702
|
+
const startedBy = (record.workItemId ? await this.#storage.get({
|
|
703
|
+
orgId: record.orgId,
|
|
704
|
+
id: record.workItemId
|
|
705
|
+
}) : null)?.sessions[binding.role]?.startedBy;
|
|
706
|
+
if (!startedBy) throw new Error(`Factory binding ${binding.id} has no authenticated session owner.`);
|
|
707
|
+
await this.#primeCredentials?.({
|
|
708
|
+
orgId: record.orgId,
|
|
709
|
+
userId: startedBy
|
|
710
|
+
});
|
|
711
|
+
const session = await this.#requireSession(binding);
|
|
712
|
+
const requestContext = factoryRequestContext({
|
|
713
|
+
session,
|
|
714
|
+
binding,
|
|
715
|
+
userId: startedBy,
|
|
716
|
+
orgId: record.orgId
|
|
717
|
+
});
|
|
718
|
+
await awaitNotification(() => session.sendNotificationSignal({
|
|
719
|
+
source: "factory",
|
|
720
|
+
kind: "rule-message",
|
|
721
|
+
summary: decision.message,
|
|
722
|
+
priority: decision.priority ?? "high",
|
|
723
|
+
payload: { message: decision.message },
|
|
724
|
+
sourceId: record.id,
|
|
725
|
+
dedupeKey: record.idempotencyKey
|
|
726
|
+
}, {
|
|
727
|
+
ifActive: { behavior: "deliver" },
|
|
728
|
+
ifIdle: { behavior: decision.idleBehavior ?? "wake" },
|
|
729
|
+
requestContext
|
|
730
|
+
}), true);
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
case "dismissStaleReviews":
|
|
734
|
+
if (!this.#dismissStaleReviews) throw new Error("GitHub review dismissal is not configured.");
|
|
735
|
+
await this.#dismissStaleReviews(decision);
|
|
736
|
+
return;
|
|
737
|
+
case "notify": {
|
|
738
|
+
const binding = await this.#requireBinding(record);
|
|
739
|
+
const session = await this.#requireSession(binding);
|
|
740
|
+
await awaitNotification(() => session.sendNotificationSignal({
|
|
741
|
+
source: "factory",
|
|
742
|
+
kind: "rule-notification",
|
|
743
|
+
summary: decision.title,
|
|
744
|
+
payload: {
|
|
745
|
+
body: decision.body,
|
|
746
|
+
level: decision.level
|
|
747
|
+
},
|
|
748
|
+
sourceId: record.id,
|
|
749
|
+
dedupeKey: record.idempotencyKey
|
|
750
|
+
}));
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
async #upsertLinkedItem(record, decision, causalChain) {
|
|
755
|
+
const existing = await this.#storage.getByProjectSource({
|
|
756
|
+
orgId: record.orgId,
|
|
757
|
+
factoryProjectId: record.factoryProjectId,
|
|
758
|
+
source: externalSourceForDecision(decision)
|
|
759
|
+
});
|
|
760
|
+
if (existing?.metadata?.["factoryRuleMaterializationKey"] === record.idempotencyKey) {
|
|
761
|
+
if (decision.skipRules === true) return;
|
|
762
|
+
for (const suffix of ["destination", "initial-entry"]) {
|
|
763
|
+
const replay = await this.#storage.getTransitionResultByIngress(record.orgId, record.factoryProjectId, `decision:${record.idempotencyKey}:${existing.id}:${suffix}`);
|
|
764
|
+
if (replay?.status === "accepted" && replay.stage === decision.stage) return;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
assertFactoryDecisionTarget(decision, this.#boards);
|
|
768
|
+
const definition = this.#boards.get(decision.board);
|
|
769
|
+
if (!definition) throw new Error("Factory decision target board is not installed.");
|
|
770
|
+
const initialPhase = definition.initialPhase;
|
|
771
|
+
const skipRules = decision.skipRules === true;
|
|
772
|
+
const entryStage = skipRules ? decision.stage : initialPhase;
|
|
773
|
+
const parentWorkItemId = record.workItemId ?? await this.#resolveLinkedWorkItemParentId?.({
|
|
774
|
+
orgId: record.orgId,
|
|
775
|
+
factoryProjectId: record.factoryProjectId,
|
|
776
|
+
decision
|
|
777
|
+
}) ?? null;
|
|
778
|
+
let result;
|
|
779
|
+
try {
|
|
780
|
+
result = await this.#storage.upsert({
|
|
781
|
+
orgId: record.orgId,
|
|
782
|
+
userId: "factory-rule-dispatcher",
|
|
783
|
+
factoryProjectId: record.factoryProjectId,
|
|
784
|
+
input: {
|
|
785
|
+
externalSource: externalSourceForDecision(decision),
|
|
786
|
+
...decision.claimKey ? { claimKey: decision.claimKey } : {},
|
|
787
|
+
parentWorkItemId,
|
|
788
|
+
title: decision.title,
|
|
789
|
+
board: decision.board,
|
|
790
|
+
stages: [entryStage],
|
|
791
|
+
sessions: {},
|
|
792
|
+
metadata: {
|
|
793
|
+
...decision.metadata,
|
|
794
|
+
[FACTORY_RULE_MATERIALIZATION_KEY]: record.idempotencyKey
|
|
795
|
+
}
|
|
796
|
+
},
|
|
797
|
+
reuseMode: "preserve"
|
|
798
|
+
});
|
|
799
|
+
} catch (error) {
|
|
800
|
+
if (error instanceof WorkItemClaimConflictError) return;
|
|
801
|
+
throw error;
|
|
802
|
+
}
|
|
803
|
+
if (!result.created && decision.claimKey && !result.item.claimKey) {
|
|
804
|
+
const claimed = await this.#storage.claimWorkItem({
|
|
805
|
+
orgId: record.orgId,
|
|
806
|
+
id: result.item.id,
|
|
807
|
+
claimKey: decision.claimKey
|
|
808
|
+
});
|
|
809
|
+
if (claimed) result = {
|
|
810
|
+
...result,
|
|
811
|
+
item: claimed
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
const itemBoard = boardForWorkItem(result.item);
|
|
815
|
+
if (!skipRules && itemBoard !== decision.board) throw new Error(`The work item belongs to board "${itemBoard}", not "${decision.board}".`);
|
|
816
|
+
if (!result.item.parentWorkItemId && parentWorkItemId && parentWorkItemId !== result.item.id) {
|
|
817
|
+
const item = await this.#storage.setParentWorkItemIfMissing({
|
|
818
|
+
orgId: record.orgId,
|
|
819
|
+
id: result.item.id,
|
|
820
|
+
userId: "factory-rule-dispatcher",
|
|
821
|
+
parentWorkItemId
|
|
822
|
+
});
|
|
823
|
+
if (item) result = {
|
|
824
|
+
...result,
|
|
825
|
+
item
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
if (!result.created && !skipRules) {
|
|
829
|
+
const missing = Object.fromEntries(Object.entries(decision.metadata ?? {}).filter(([key]) => key !== "factoryRuleMaterializationKey" && result.item.metadata?.[key] === void 0));
|
|
830
|
+
if (Object.keys(missing).length > 0) {
|
|
831
|
+
const filled = await this.#storage.update({
|
|
832
|
+
orgId: record.orgId,
|
|
833
|
+
id: result.item.id,
|
|
834
|
+
userId: "factory-rule-dispatcher",
|
|
835
|
+
patch: { metadata: missing }
|
|
836
|
+
});
|
|
837
|
+
if (filled) result = {
|
|
838
|
+
...result,
|
|
839
|
+
item: filled.item
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
if (skipRules) {
|
|
844
|
+
if (!result.created) await moveCardToBoard({
|
|
845
|
+
workItems: this.#storage,
|
|
846
|
+
boardRegistry: this.#boards,
|
|
847
|
+
userId: "factory-rule-dispatcher",
|
|
848
|
+
item: result.item,
|
|
849
|
+
targetBoard: decision.board,
|
|
850
|
+
targetStage: decision.stage
|
|
851
|
+
});
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
const materializedByDecision = result.item.metadata?.[FACTORY_RULE_MATERIALIZATION_KEY] === record.idempotencyKey;
|
|
855
|
+
if (!materializedByDecision && (decision.stage === initialPhase || !result.item.stages.includes(initialPhase))) return;
|
|
856
|
+
const board = decision.board;
|
|
857
|
+
let expectedRevision = result.item.revision;
|
|
858
|
+
if (materializedByDecision) {
|
|
859
|
+
const initial = await this.#transitionService.transition({
|
|
860
|
+
orgId: record.orgId,
|
|
861
|
+
factoryProjectId: record.factoryProjectId,
|
|
862
|
+
workItemId: result.item.id,
|
|
863
|
+
board,
|
|
864
|
+
stage: initialPhase,
|
|
865
|
+
expectedRevision,
|
|
866
|
+
actor: deferredActor(record),
|
|
867
|
+
ingress: {
|
|
868
|
+
type: "rule",
|
|
869
|
+
identity: `decision:${record.idempotencyKey}:${result.item.id}:initial-entry`
|
|
870
|
+
},
|
|
871
|
+
cause: "linked_item_materialized",
|
|
872
|
+
causalChain,
|
|
873
|
+
initialEntry: true
|
|
874
|
+
});
|
|
875
|
+
if (initial.status === "rejected") {
|
|
876
|
+
if (result.created) await this.#storage.delete({
|
|
877
|
+
orgId: record.orgId,
|
|
878
|
+
id: result.item.id,
|
|
879
|
+
purgeRuleState: false
|
|
880
|
+
});
|
|
881
|
+
throw new Error(`${initial.code}: ${initial.reason}`);
|
|
882
|
+
}
|
|
883
|
+
expectedRevision = initial.revision;
|
|
884
|
+
}
|
|
885
|
+
if (decision.stage === initialPhase) return;
|
|
886
|
+
const moved = await this.#transitionService.transition({
|
|
887
|
+
orgId: record.orgId,
|
|
888
|
+
factoryProjectId: record.factoryProjectId,
|
|
889
|
+
workItemId: result.item.id,
|
|
890
|
+
board,
|
|
891
|
+
stage: decision.stage,
|
|
892
|
+
expectedRevision,
|
|
893
|
+
actor: {
|
|
894
|
+
type: "system",
|
|
895
|
+
id: "factory-rule-dispatcher"
|
|
896
|
+
},
|
|
897
|
+
ingress: {
|
|
898
|
+
type: "rule",
|
|
899
|
+
identity: `decision:${record.idempotencyKey}:${result.item.id}:destination`
|
|
900
|
+
},
|
|
901
|
+
cause: materializedByDecision ? "linked_item_materialized" : "linked_item_reconciled",
|
|
902
|
+
causalChain
|
|
903
|
+
});
|
|
904
|
+
if (moved.status === "rejected") throw new Error(`${moved.code}: ${moved.reason}`);
|
|
905
|
+
}
|
|
906
|
+
async #requireItem(record) {
|
|
907
|
+
if (!record.workItemId) throw new Error("Factory decision is not linked to a work item.");
|
|
908
|
+
const item = await this.#storage.get({
|
|
909
|
+
orgId: record.orgId,
|
|
910
|
+
id: record.workItemId
|
|
911
|
+
});
|
|
912
|
+
if (!item) throw new Error("Factory work item not found.");
|
|
913
|
+
return item;
|
|
914
|
+
}
|
|
915
|
+
async #findBinding(record, role) {
|
|
916
|
+
if (!record.workItemId) throw new Error("Factory decision is not linked to a work item.");
|
|
917
|
+
return (await this.#storage.listRunBindings(record.orgId, record.factoryProjectId, record.workItemId)).filter((candidate) => candidate.status === "active" && (role === void 0 || candidate.role === role)).sort((left, right) => {
|
|
918
|
+
if (role === void 0 && left.role === "work" && right.role !== "work") return -1;
|
|
919
|
+
if (role === void 0 && right.role === "work" && left.role !== "work") return 1;
|
|
920
|
+
return right.createdAt.getTime() - left.createdAt.getTime() || left.id.localeCompare(right.id);
|
|
921
|
+
})[0];
|
|
922
|
+
}
|
|
923
|
+
async #requireBinding(record, role) {
|
|
924
|
+
const binding = await this.#findBinding(record, role);
|
|
925
|
+
if (!binding) throw new FactoryDispatchError("session_unavailable", role ? `No active Factory binding for role ${role}.` : "No active Factory binding.");
|
|
926
|
+
return binding;
|
|
927
|
+
}
|
|
928
|
+
async #messageBinding(record, decision) {
|
|
929
|
+
if (decision.prepareBinding && decision.role !== void 0) return this.#requireOrPrepareBinding(record, decision.role);
|
|
930
|
+
return this.#findBinding(record, decision.role);
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* A role is superseded when its binding was revoked by a later role taking
|
|
934
|
+
* the same session (`prepareRunBinding` revokes every other active binding on
|
|
935
|
+
* that session). Only a hand-on — the running agent or a person moving the
|
|
936
|
+
* card — produces that shape, so the role's job is done: its decision is not
|
|
937
|
+
* owed a retry, and whatever ends the shared turn afterwards belongs to the
|
|
938
|
+
* successor's decision. A revoke with no successor (terminal cleanup, an
|
|
939
|
+
* operator pulling the seat) is not supersession and still fails as before.
|
|
940
|
+
* Only a hand-on that happened after this decision was queued counts: a
|
|
941
|
+
* fresh decision for the role (the card came back to it) must still dispatch
|
|
942
|
+
* even though an older revoked binding for that role is on record.
|
|
943
|
+
*/
|
|
944
|
+
async #decisionOvertaken(record, role) {
|
|
945
|
+
if (!record.workItemId) return false;
|
|
946
|
+
const [item, siblings] = await Promise.all([this.#storage.get({
|
|
947
|
+
orgId: record.orgId,
|
|
948
|
+
id: record.workItemId
|
|
949
|
+
}), this.#storage.listDecisionsForEvaluations(record.orgId, record.factoryProjectId, [record.evaluationId])]);
|
|
950
|
+
return decisionOvertaken({
|
|
951
|
+
boards: this.#boards,
|
|
952
|
+
item,
|
|
953
|
+
record,
|
|
954
|
+
role,
|
|
955
|
+
siblings
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
async #roleSuperseded(record, role) {
|
|
959
|
+
if (!record.workItemId) return false;
|
|
960
|
+
const bindings = await this.#storage.listRunBindings(record.orgId, record.factoryProjectId, record.workItemId);
|
|
961
|
+
const own = bindings.filter((candidate) => candidate.role === role);
|
|
962
|
+
if (own.some((candidate) => candidate.status === "active")) return false;
|
|
963
|
+
const item = await this.#storage.get({
|
|
964
|
+
orgId: record.orgId,
|
|
965
|
+
id: record.workItemId
|
|
966
|
+
}).catch(() => null);
|
|
967
|
+
if (item && workItemPhaseSemantics(this.#boards, item)?.kind === "terminal") return true;
|
|
968
|
+
return own.some((revoked) => revoked.revokedAt !== null && revoked.revokedAt.getTime() >= record.createdAt.getTime() && bindings.some((successor) => successor.role !== role && successor.status === "active" && successor.resourceId === revoked.resourceId && successor.sessionId === revoked.sessionId && successor.threadId === revoked.threadId && successor.createdAt.getTime() >= revoked.revokedAt.getTime()));
|
|
969
|
+
}
|
|
970
|
+
async #requireOrPrepareBinding(record, role) {
|
|
971
|
+
const binding = await this.#findBinding(record, role);
|
|
972
|
+
if (binding) {
|
|
973
|
+
if (await this.#controller.getSessionByResource(binding.resourceId)) return binding;
|
|
974
|
+
}
|
|
975
|
+
if (!this.#prepareBinding) throw new FactoryDispatchError("session_unavailable", binding ? "Bound Factory session not found." : `No active Factory binding for role ${role}.`);
|
|
976
|
+
const item = await this.#requireItem(record);
|
|
977
|
+
await this.#prepareBinding({
|
|
978
|
+
record,
|
|
979
|
+
item,
|
|
980
|
+
role
|
|
981
|
+
});
|
|
982
|
+
return this.#requireBinding(record, role);
|
|
983
|
+
}
|
|
984
|
+
async #findSession(binding) {
|
|
985
|
+
const session = await this.#controller.getSessionByResource(binding.resourceId);
|
|
986
|
+
if (!session) return void 0;
|
|
987
|
+
await this.#switchThread(session, binding);
|
|
988
|
+
return session;
|
|
989
|
+
}
|
|
990
|
+
/** Unset means off: a plan nobody asked us to answer is a plan someone should see. */
|
|
991
|
+
async #plansAreAutoApproved({ orgId, factoryProjectId }) {
|
|
992
|
+
return this.#autoApprovePlans ? await this.#autoApprovePlans({
|
|
993
|
+
orgId,
|
|
994
|
+
factoryProjectId
|
|
995
|
+
}) : false;
|
|
996
|
+
}
|
|
997
|
+
async #requireSession(binding) {
|
|
998
|
+
const session = await this.#findSession(binding);
|
|
999
|
+
if (!session) throw new FactoryDispatchError("session_unavailable", "Bound Factory session not found.");
|
|
1000
|
+
return session;
|
|
1001
|
+
}
|
|
1002
|
+
async #switchThread(session, binding) {
|
|
1003
|
+
if (session.thread.requireId() === binding.threadId) return;
|
|
1004
|
+
await session.thread.switch({ threadId: binding.threadId });
|
|
1005
|
+
}
|
|
1006
|
+
async #withBindingSkillRun(bindingId, effect) {
|
|
1007
|
+
const run = (this.#bindingSkillRuns.get(bindingId) ?? Promise.resolve()).catch(() => {}).then(effect);
|
|
1008
|
+
this.#bindingSkillRuns.set(bindingId, run);
|
|
1009
|
+
try {
|
|
1010
|
+
await run;
|
|
1011
|
+
} finally {
|
|
1012
|
+
if (this.#bindingSkillRuns.get(bindingId) === run) this.#bindingSkillRuns.delete(bindingId);
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
async #withLease(renew, effect) {
|
|
1016
|
+
let renewalFailure;
|
|
1017
|
+
let renewal = Promise.resolve();
|
|
1018
|
+
const timer = setInterval(() => {
|
|
1019
|
+
renewal = renewal.then(async () => {
|
|
1020
|
+
try {
|
|
1021
|
+
if (!await renew(new Date(Date.now() + LEASE_MS))) renewalFailure = /* @__PURE__ */ new Error("Factory dispatch lease was lost during execution.");
|
|
1022
|
+
} catch (error) {
|
|
1023
|
+
renewalFailure = error;
|
|
1024
|
+
}
|
|
1025
|
+
});
|
|
1026
|
+
}, Math.floor(LEASE_MS / 3));
|
|
1027
|
+
timer.unref?.();
|
|
1028
|
+
try {
|
|
1029
|
+
await effect();
|
|
1030
|
+
await renewal;
|
|
1031
|
+
if (renewalFailure) throw renewalFailure;
|
|
1032
|
+
} finally {
|
|
1033
|
+
clearInterval(timer);
|
|
1034
|
+
await renewal;
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
/** Keep this process's claim on an open run fresh for as long as it is watching the run. */
|
|
1038
|
+
async #withOpenRunHeartbeat(session, kickoffId, effect) {
|
|
1039
|
+
if (!this.#audit) return effect();
|
|
1040
|
+
const timer = setInterval(() => void heartbeatSessionOpenRun(session, kickoffId), Math.floor(FACTORY_OPEN_RUN_STALE_MS / 3));
|
|
1041
|
+
timer.unref?.();
|
|
1042
|
+
try {
|
|
1043
|
+
return await effect();
|
|
1044
|
+
} finally {
|
|
1045
|
+
clearInterval(timer);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
async #recordRunStart(session, binding, kickoffId, approvedBy, observedEnd, workItemName) {
|
|
1049
|
+
if (!this.#audit) return;
|
|
1050
|
+
const humanApproved = isHumanActorId(approvedBy);
|
|
1051
|
+
await recordSessionRunStart(session, {
|
|
1052
|
+
audit: this.#audit,
|
|
1053
|
+
actorType: humanApproved ? "human" : "system",
|
|
1054
|
+
observedEnd,
|
|
1055
|
+
run: {
|
|
1056
|
+
kickoffId,
|
|
1057
|
+
ownerId: this.#ownerId,
|
|
1058
|
+
heartbeatAt: Date.now(),
|
|
1059
|
+
bindingId: binding.id,
|
|
1060
|
+
role: binding.role,
|
|
1061
|
+
startedBy: humanApproved ? approvedBy : "factory-rule-dispatcher",
|
|
1062
|
+
orgId: binding.orgId,
|
|
1063
|
+
factoryProjectId: binding.factoryProjectId,
|
|
1064
|
+
workItemId: binding.workItemId,
|
|
1065
|
+
workItemName,
|
|
1066
|
+
sessionId: binding.sessionId,
|
|
1067
|
+
threadId: binding.threadId,
|
|
1068
|
+
branch: binding.branch
|
|
1069
|
+
}
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
async #dispatchPendingStart(record, now) {
|
|
1073
|
+
try {
|
|
1074
|
+
await this.#withLease(async (leaseExpiresAt) => this.#storage.renewPendingStartLease(leaseIdentity(record, this.#ownerId), leaseExpiresAt), async () => {
|
|
1075
|
+
if (record.message === null) return;
|
|
1076
|
+
const binding = (await this.#storage.listRunBindings(record.orgId, record.factoryProjectId)).find((candidate) => candidate.id === record.bindingId && candidate.status === "active");
|
|
1077
|
+
if (!binding) throw new FactoryDispatchError("session_unavailable", "Prepared Factory binding is unavailable or revoked.");
|
|
1078
|
+
const item = await this.#storage.get({
|
|
1079
|
+
orgId: record.orgId,
|
|
1080
|
+
id: binding.workItemId
|
|
1081
|
+
});
|
|
1082
|
+
const startedBy = item?.sessions[binding.role]?.startedBy;
|
|
1083
|
+
if (!startedBy) throw new Error(`Factory binding ${binding.id} has no authenticated session owner.`);
|
|
1084
|
+
await this.#primeCredentials?.({
|
|
1085
|
+
orgId: record.orgId,
|
|
1086
|
+
userId: startedBy
|
|
1087
|
+
});
|
|
1088
|
+
const session = await this.#requireSession(binding);
|
|
1089
|
+
const requestContext = factoryRequestContext({
|
|
1090
|
+
session,
|
|
1091
|
+
binding,
|
|
1092
|
+
userId: startedBy,
|
|
1093
|
+
orgId: record.orgId
|
|
1094
|
+
});
|
|
1095
|
+
const run = watchRun(session, {
|
|
1096
|
+
timeoutMs: this.#skillCompletionObservationTimeoutMs,
|
|
1097
|
+
approvePlans: await this.#plansAreAutoApproved(record),
|
|
1098
|
+
label: "Factory kickoff run",
|
|
1099
|
+
runStillActive: () => this.#controller.listActiveThreadRuns().some((active) => active.threadId === binding.threadId)
|
|
1100
|
+
});
|
|
1101
|
+
const sendKickoff = (dedupeKey) => awaitNotification(() => session.sendNotificationSignal({
|
|
1102
|
+
source: "factory",
|
|
1103
|
+
kind: "run-kickoff",
|
|
1104
|
+
summary: record.message,
|
|
1105
|
+
priority: "high",
|
|
1106
|
+
payload: { message: record.message },
|
|
1107
|
+
sourceId: record.id,
|
|
1108
|
+
dedupeKey
|
|
1109
|
+
}, {
|
|
1110
|
+
ifActive: { behavior: "deliver" },
|
|
1111
|
+
ifIdle: { behavior: "wake" },
|
|
1112
|
+
requestContext
|
|
1113
|
+
}), true);
|
|
1114
|
+
try {
|
|
1115
|
+
let settled = await sendKickoff(`factory-kickoff:${record.kickoffKey}`);
|
|
1116
|
+
let deliveryGeneration = 0;
|
|
1117
|
+
while (settled?.action === "deliver") {
|
|
1118
|
+
if (!await run.wait()) throw new Error("Factory kickoff is waiting on a run that has not ended.");
|
|
1119
|
+
run.arm();
|
|
1120
|
+
deliveryGeneration += 1;
|
|
1121
|
+
settled = await sendKickoff(`factory-kickoff:${record.kickoffKey}:retry:${record.attempts}:${deliveryGeneration}`);
|
|
1122
|
+
}
|
|
1123
|
+
await this.#recordRunStart(session, binding, `factory-kickoff:${record.kickoffKey}:${record.attempts}`, startedBy, run.endReason, item?.title);
|
|
1124
|
+
await run.settle();
|
|
1125
|
+
} finally {
|
|
1126
|
+
run.close();
|
|
1127
|
+
}
|
|
1128
|
+
});
|
|
1129
|
+
if (!await this.#storage.completePendingStart(leaseIdentity(record, this.#ownerId), /* @__PURE__ */ new Date())) throw new Error("Factory kickoff lease was lost before completion.");
|
|
1130
|
+
} catch (error) {
|
|
1131
|
+
const failureCode = factoryDispatchFailureCode(error);
|
|
1132
|
+
await this.#storage.failPendingStart({
|
|
1133
|
+
...leaseIdentity(record, this.#ownerId),
|
|
1134
|
+
now: /* @__PURE__ */ new Date(),
|
|
1135
|
+
availableAt: retryAt(now, record.attempts),
|
|
1136
|
+
lastError: sanitizeDispatchError(error),
|
|
1137
|
+
failureCode,
|
|
1138
|
+
terminal: isTerminalFailure(record.attempts, failureCode)
|
|
1139
|
+
});
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
};
|
|
1143
|
+
const FACTORY_DISPATCH_CONSTANTS = {
|
|
1144
|
+
leaseMs: LEASE_MS,
|
|
1145
|
+
pollMs: POLL_MS,
|
|
1146
|
+
batchSize: BATCH_SIZE,
|
|
1147
|
+
maxAttempts: MAX_ATTEMPTS,
|
|
1148
|
+
maxErrorLength: MAX_ERROR_LENGTH,
|
|
1149
|
+
maxBackoffMs: MAX_BACKOFF_MS,
|
|
1150
|
+
skillCompletionObservationTimeoutMs: SKILL_COMPLETION_OBSERVATION_TIMEOUT_MS,
|
|
1151
|
+
runRegistryHeartbeatMs: RUN_REGISTRY_HEARTBEAT_MS,
|
|
1152
|
+
openRunStaleMs: FACTORY_OPEN_RUN_STALE_MS,
|
|
1153
|
+
maxInFlight: MAX_IN_FLIGHT,
|
|
1154
|
+
stages: FACTORY_RULE_STAGES
|
|
1155
|
+
};
|
|
1156
|
+
//#endregion
|
|
1157
|
+
export { FACTORY_DISPATCH_CONSTANTS, FactoryDecisionDispatcher };
|
|
1158
|
+
|
|
1159
|
+
//# sourceMappingURL=dispatcher.js.map
|