@vercel/factory 0.0.14 → 0.0.16
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/CHANGELOG.md +356 -0
- package/README.md +96 -2
- package/dist/agent-routes.d.mts +113 -0
- package/dist/agent-routes.mjs +91 -0
- package/dist/agent-routes.mjs.map +1 -0
- package/dist/api-contracts.d.mts +1768 -0
- package/dist/api-contracts.mjs +119 -0
- package/dist/api-contracts.mjs.map +1 -0
- package/dist/api-images.d.mts +30 -0
- package/dist/api-images.mjs +28 -0
- package/dist/api-images.mjs.map +1 -0
- package/dist/api-task-graph.mjs +57 -0
- package/dist/api-task-graph.mjs.map +1 -0
- package/dist/api.d.mts +111 -216
- package/dist/api.mjs +1063 -99
- package/dist/api.mjs.map +1 -1
- package/dist/approval-access.d.mts +39 -0
- package/dist/approval-access.mjs +62 -0
- package/dist/approval-access.mjs.map +1 -0
- package/dist/approval-contracts.d.mts +698 -0
- package/dist/approval-contracts.mjs +27 -0
- package/dist/approval-contracts.mjs.map +1 -0
- package/dist/approval.d.mts +49 -0
- package/dist/approval.mjs +39 -0
- package/dist/approval.mjs.map +1 -0
- package/dist/blob/artifacts.d.mts +37 -0
- package/dist/blob/artifacts.mjs +45 -0
- package/dist/blob/artifacts.mjs.map +1 -0
- package/dist/blob/index.d.mts +84 -12
- package/dist/blob/index.mjs +179 -45
- package/dist/blob/index.mjs.map +1 -1
- package/dist/budget.d.mts +115 -0
- package/dist/budget.mjs +147 -0
- package/dist/budget.mjs.map +1 -0
- package/dist/budgets.d.mts +4 -0
- package/dist/budgets.mjs +4 -0
- package/dist/build-factory.d.mts +7 -4
- package/dist/build-factory.mjs +2 -1
- package/dist/build-factory.mjs.map +1 -1
- package/dist/change-verification/brief.d.mts +9 -0
- package/dist/change-verification/brief.mjs +13 -0
- package/dist/change-verification/brief.mjs.map +1 -0
- package/dist/change-verification/dispatch.d.mts +37 -0
- package/dist/change-verification/dispatch.mjs +83 -0
- package/dist/change-verification/dispatch.mjs.map +1 -0
- package/dist/change-verification/eve-tool.d.mts +61 -0
- package/dist/change-verification/eve-tool.mjs +89 -0
- package/dist/change-verification/eve-tool.mjs.map +1 -0
- package/dist/change-verification/result.mjs +130 -0
- package/dist/change-verification/result.mjs.map +1 -0
- package/dist/changes/eve-record-change.d.mts +56 -0
- package/dist/changes/eve-record-change.mjs +131 -0
- package/dist/changes/eve-record-change.mjs.map +1 -0
- package/dist/changes/presentation.d.mts +14 -0
- package/dist/changes.d.mts +24 -0
- package/dist/changes.mjs +29 -0
- package/dist/changes.mjs.map +1 -0
- package/dist/client-events.d.mts +25 -0
- package/dist/client-events.mjs +45 -0
- package/dist/client-events.mjs.map +1 -0
- package/dist/client-stream.d.mts +28 -0
- package/dist/client-stream.mjs +210 -0
- package/dist/client-stream.mjs.map +1 -0
- package/dist/client-transcript.d.mts +41 -0
- package/dist/client-transcript.mjs +233 -0
- package/dist/client-transcript.mjs.map +1 -0
- package/dist/client.d.mts +343 -0
- package/dist/client.mjs +366 -0
- package/dist/client.mjs.map +1 -0
- package/dist/code-review/contracts.d.mts +27 -0
- package/dist/code-review/eve-post-review.d.mts +70 -0
- package/dist/code-review/eve-post-review.mjs +195 -0
- package/dist/code-review/eve-post-review.mjs.map +1 -0
- package/dist/code-review/eve-review-comments.d.mts +75 -0
- package/dist/code-review/eve-review-comments.mjs +193 -0
- package/dist/code-review/eve-review-comments.mjs.map +1 -0
- package/dist/code-review/github-contracts.d.mts +10 -0
- package/dist/code-review/github-reporter.d.mts +46 -0
- package/dist/code-review/github-reporter.mjs +262 -0
- package/dist/code-review/github-reporter.mjs.map +1 -0
- package/dist/code-review/preparation.d.mts +34 -0
- package/dist/code-review/preparation.mjs +23 -0
- package/dist/code-review/preparation.mjs.map +1 -0
- package/dist/code-review/stall.d.mts +17 -0
- package/dist/code-review/stall.mjs +30 -0
- package/dist/code-review/stall.mjs.map +1 -0
- package/dist/code-review.d.mts +7 -0
- package/dist/code-review.mjs +5 -0
- package/dist/communication.d.mts +9 -0
- package/dist/communication.mjs +9 -0
- package/dist/connectors/github.d.mts +26 -0
- package/dist/connectors/github.mjs +55 -0
- package/dist/connectors/github.mjs.map +1 -0
- package/dist/connectors/index.d.mts +35 -3
- package/dist/connectors/index.mjs +3 -52
- package/dist/connectors/index.mjs.map +1 -1
- package/dist/connectors/outbox.d.mts +34 -0
- package/dist/connectors/outbox.mjs +50 -0
- package/dist/connectors/outbox.mjs.map +1 -0
- package/dist/connectors/slack-approval-blocks.mjs +136 -0
- package/dist/connectors/slack-approval-blocks.mjs.map +1 -0
- package/dist/connectors/slack-approvals.d.mts +29 -0
- package/dist/connectors/slack-approvals.mjs +346 -0
- package/dist/connectors/slack-approvals.mjs.map +1 -0
- package/dist/connectors/slack.d.mts +35 -52
- package/dist/connectors/slack.mjs +13 -85
- package/dist/connectors/slack.mjs.map +1 -1
- package/dist/deepsec/eve-tool.d.mts +110 -0
- package/dist/deepsec/eve-tool.mjs +166 -0
- package/dist/deepsec/eve-tool.mjs.map +1 -0
- package/dist/deepsec/finding.d.mts +84 -0
- package/dist/deepsec/finding.mjs +56 -0
- package/dist/deepsec/finding.mjs.map +1 -0
- package/dist/deepsec.d.mts +3 -0
- package/dist/delivery-metrics/metrics.d.mts +93 -0
- package/dist/delivery-metrics/metrics.mjs +200 -0
- package/dist/delivery-metrics/metrics.mjs.map +1 -0
- package/dist/delivery-metrics.d.mts +2 -0
- package/dist/delivery-metrics.mjs +2 -0
- package/dist/dispatch.d.mts +152 -0
- package/dist/dispatch.mjs +199 -0
- package/dist/dispatch.mjs.map +1 -0
- package/dist/errors.d.mts +15 -0
- package/dist/errors.mjs +38 -0
- package/dist/errors.mjs.map +1 -0
- package/dist/eve/index.d.mts +209 -1277
- package/dist/eve/index.mjs +312 -1073
- package/dist/eve/index.mjs.map +1 -1
- package/dist/eve/invoke.d.mts +144 -0
- package/dist/eve/invoke.mjs +254 -0
- package/dist/eve/invoke.mjs.map +1 -0
- package/dist/eve/session-client.d.mts +186 -0
- package/dist/eve/session-client.mjs +245 -0
- package/dist/eve/session-client.mjs.map +1 -0
- package/dist/eve/task-execution.d.mts +380 -0
- package/dist/eve/task-execution.mjs +73 -0
- package/dist/eve/task-execution.mjs.map +1 -0
- package/dist/eve/task-session.d.mts +129 -0
- package/dist/eve/task-session.mjs +245 -0
- package/dist/eve/task-session.mjs.map +1 -0
- package/dist/eve/transcript.d.mts +37 -0
- package/dist/eve/transcript.mjs +69 -0
- package/dist/eve/transcript.mjs.map +1 -0
- package/dist/execution-public.d.mts +8 -0
- package/dist/execution-public.mjs +7 -0
- package/dist/execution.d.mts +183 -0
- package/dist/execution.mjs +223 -0
- package/dist/execution.mjs.map +1 -0
- package/dist/finding-remediation/admission.d.mts +53 -0
- package/dist/finding-remediation/admission.mjs +90 -0
- package/dist/finding-remediation/admission.mjs.map +1 -0
- package/dist/finding-remediation/brief.d.mts +14 -0
- package/dist/finding-remediation/brief.mjs +25 -0
- package/dist/finding-remediation/brief.mjs.map +1 -0
- package/dist/finding-remediation/eve-tool.d.mts +29 -0
- package/dist/finding-remediation/eve-tool.mjs +34 -0
- package/dist/finding-remediation/eve-tool.mjs.map +1 -0
- package/dist/findings/fingerprint.d.mts +14 -0
- package/dist/findings/fingerprint.mjs +28 -0
- package/dist/findings/fingerprint.mjs.map +1 -0
- package/dist/findings.d.mts +7 -0
- package/dist/findings.mjs +6 -0
- package/dist/github-app.d.mts +54 -0
- package/dist/github-app.mjs +121 -0
- package/dist/github-app.mjs.map +1 -0
- package/dist/github-publication.d.mts +199 -0
- package/dist/github-publication.mjs +442 -0
- package/dist/github-publication.mjs.map +1 -0
- package/dist/github-transfer.d.mts +81 -0
- package/dist/github-transfer.mjs +273 -0
- package/dist/github-transfer.mjs.map +1 -0
- package/dist/github.d.mts +446 -2
- package/dist/github.mjs +357 -56
- package/dist/github.mjs.map +1 -1
- package/dist/image-input.d.mts +51 -0
- package/dist/image-input.mjs +63 -0
- package/dist/image-input.mjs.map +1 -0
- package/dist/inbox-activity.d.mts +53 -0
- package/dist/inbox-activity.mjs +41 -0
- package/dist/inbox-activity.mjs.map +1 -0
- package/dist/index.d.mts +16 -484
- package/dist/index.mjs +15 -522
- package/dist/intake-contracts.d.mts +55 -0
- package/dist/intake-contracts.mjs +33 -0
- package/dist/intake-contracts.mjs.map +1 -0
- package/dist/integrations/deepsec.d.mts +5 -0
- package/dist/integrations/deepsec.mjs +3 -0
- package/dist/integrations/github.d.mts +11 -0
- package/dist/integrations/github.mjs +9 -0
- package/dist/integrations/slack.d.mts +5 -0
- package/dist/integrations/slack.mjs +5 -0
- package/dist/integrations/vercel.d.mts +5 -0
- package/dist/integrations/vercel.mjs +4 -0
- package/dist/merge-resolution/contracts.d.mts +17 -0
- package/dist/merge-resolution/contracts.mjs +19 -0
- package/dist/merge-resolution/contracts.mjs.map +1 -0
- package/dist/merge-resolution/eve-tools.d.mts +47 -0
- package/dist/merge-resolution/eve-tools.mjs +122 -0
- package/dist/merge-resolution/eve-tools.mjs.map +1 -0
- package/dist/model-settings.d.mts +41 -0
- package/dist/model-settings.mjs +35 -0
- package/dist/model-settings.mjs.map +1 -0
- package/dist/multi-repository-changes/coordination.d.mts +49 -0
- package/dist/multi-repository-changes/coordination.mjs +115 -0
- package/dist/multi-repository-changes/coordination.mjs.map +1 -0
- package/dist/planning/cancellation.mjs +82 -0
- package/dist/planning/cancellation.mjs.map +1 -0
- package/dist/planning/configuration.d.mts +23 -0
- package/dist/planning/configuration.mjs +56 -0
- package/dist/planning/configuration.mjs.map +1 -0
- package/dist/planning/contracts.d.mts +136 -0
- package/dist/planning/contracts.mjs +42 -0
- package/dist/planning/contracts.mjs.map +1 -0
- package/dist/planning/dependencies.mjs +44 -0
- package/dist/planning/dependencies.mjs.map +1 -0
- package/dist/planning/effects.mjs +122 -0
- package/dist/planning/effects.mjs.map +1 -0
- package/dist/planning/reconcile.mjs +279 -0
- package/dist/planning/reconcile.mjs.map +1 -0
- package/dist/planning/runtime.d.mts +27 -0
- package/dist/planning/runtime.mjs +25 -0
- package/dist/planning/runtime.mjs.map +1 -0
- package/dist/planning/state.mjs +92 -0
- package/dist/planning/state.mjs.map +1 -0
- package/dist/planning/turns.mjs +262 -0
- package/dist/planning/turns.mjs.map +1 -0
- package/dist/planning/validation.mjs +106 -0
- package/dist/planning/validation.mjs.map +1 -0
- package/dist/postgres/index.d.mts +48 -1
- package/dist/postgres/index.mjs +45 -3
- package/dist/postgres/index.mjs.map +1 -1
- package/dist/presets/software-development/approval.d.mts +14 -0
- package/dist/presets/software-development/approval.mjs +21 -0
- package/dist/presets/software-development/approval.mjs.map +1 -0
- package/dist/presets/software-development/deepsec-brief.d.mts +8 -0
- package/dist/presets/software-development/deepsec-brief.mjs +14 -0
- package/dist/presets/software-development/deepsec-brief.mjs.map +1 -0
- package/dist/presets/software-development/dispatch.d.mts +56 -0
- package/dist/presets/software-development/dispatch.mjs +67 -0
- package/dist/presets/software-development/dispatch.mjs.map +1 -0
- package/dist/presets/software-development/eve-delegation-policy.d.mts +7 -0
- package/dist/presets/software-development/eve-delegation-policy.mjs +34 -0
- package/dist/presets/software-development/eve-delegation-policy.mjs.map +1 -0
- package/dist/presets/software-development/eve.d.mts +18 -0
- package/dist/presets/software-development/eve.mjs +19 -0
- package/dist/presets/software-development/eve.mjs.map +1 -0
- package/dist/presets/software-development/finish-task-policy.d.mts +7 -0
- package/dist/presets/software-development/finish-task-policy.mjs +9 -0
- package/dist/presets/software-development/finish-task-policy.mjs.map +1 -0
- package/dist/presets/software-development/recovery.d.mts +32 -0
- package/dist/presets/software-development/recovery.mjs +120 -0
- package/dist/presets/software-development/recovery.mjs.map +1 -0
- package/dist/presets/software-development/task-communication.d.mts +24 -0
- package/dist/presets/software-development/task-communication.mjs +157 -0
- package/dist/presets/software-development/task-communication.mjs.map +1 -0
- package/dist/presets/software-development.d.mts +10 -0
- package/dist/presets/software-development.mjs +9 -0
- package/dist/pull-requests/contracts.d.mts +72 -0
- package/dist/pull-requests/eve-fetch.d.mts +57 -0
- package/dist/pull-requests/eve-fetch.mjs +151 -0
- package/dist/pull-requests/eve-fetch.mjs.map +1 -0
- package/dist/pull-requests/github-label-manager.d.mts +27 -0
- package/dist/pull-requests/github-label-manager.mjs +40 -0
- package/dist/pull-requests/github-label-manager.mjs.map +1 -0
- package/dist/pull-requests/github-publisher.d.mts +67 -0
- package/dist/pull-requests/github-publisher.mjs +405 -0
- package/dist/pull-requests/github-publisher.mjs.map +1 -0
- package/dist/pull-requests.d.mts +6 -0
- package/dist/pull-requests.mjs +4 -0
- package/dist/receipts.d.mts +4 -0
- package/dist/receipts.mjs +3 -0
- package/dist/repositories.d.mts +18 -0
- package/dist/repositories.mjs +33 -0
- package/dist/repositories.mjs.map +1 -0
- package/dist/sandbox/command.d.mts +18 -0
- package/dist/sandbox/execution-abort.d.mts +16 -0
- package/dist/sandbox/execution-abort.mjs +49 -0
- package/dist/sandbox/execution-abort.mjs.map +1 -0
- package/dist/sandbox/execution-environment.d.mts +25 -0
- package/dist/sandbox/execution-run-ledger.d.mts +115 -0
- package/dist/sandbox/execution-run-ledger.mjs +209 -0
- package/dist/sandbox/execution-run-ledger.mjs.map +1 -0
- package/dist/sandbox/execution.d.mts +54 -0
- package/dist/sandbox/execution.mjs +228 -0
- package/dist/sandbox/execution.mjs.map +1 -0
- package/dist/sandbox/harness-runner.d.mts +79 -0
- package/dist/sandbox/harness-runner.mjs +162 -0
- package/dist/sandbox/harness-runner.mjs.map +1 -0
- package/dist/sandbox/index.d.mts +10 -0
- package/dist/sandbox/index.mjs +7 -0
- package/dist/sandbox/task-environment.d.mts +50 -0
- package/dist/sandbox/task-environment.mjs +140 -0
- package/dist/sandbox/task-environment.mjs.map +1 -0
- package/dist/sandbox/workspace.d.mts +29 -0
- package/dist/sandbox/workspace.mjs +28 -0
- package/dist/sandbox/workspace.mjs.map +1 -0
- package/dist/schema/agent-route.d.mts +40 -0
- package/dist/schema/agent-route.mjs +33 -0
- package/dist/schema/agent-route.mjs.map +1 -0
- package/dist/schema/answer.d.mts +23 -0
- package/dist/schema/answer.mjs +21 -0
- package/dist/schema/answer.mjs.map +1 -0
- package/dist/schema/budget.d.mts +38 -0
- package/dist/schema/budget.mjs +30 -0
- package/dist/schema/budget.mjs.map +1 -0
- package/dist/schema/catalog.mjs +72 -0
- package/dist/schema/catalog.mjs.map +1 -0
- package/dist/schema/change.d.mts +117 -0
- package/dist/schema/change.mjs +68 -0
- package/dist/schema/change.mjs.map +1 -0
- package/dist/schema/common.d.mts +33 -0
- package/dist/{id-BLIkCVue.mjs → schema/common.mjs} +7 -16
- package/dist/schema/common.mjs.map +1 -0
- package/dist/schema/communication.d.mts +52 -0
- package/dist/{communication-Kd9nU5RP.mjs → schema/communication.mjs} +8 -3
- package/dist/schema/communication.mjs.map +1 -0
- package/dist/schema/execution.d.mts +101 -0
- package/dist/schema/execution.mjs +86 -0
- package/dist/schema/execution.mjs.map +1 -0
- package/dist/schema/factory-config.d.mts +122 -0
- package/dist/schema/factory-config.mjs +90 -0
- package/dist/schema/factory-config.mjs.map +1 -0
- package/dist/schema/finding.d.mts +125 -0
- package/dist/schema/finding.mjs +67 -0
- package/dist/schema/finding.mjs.map +1 -0
- package/dist/schema/id.d.mts +43 -0
- package/dist/schema/id.mjs +32 -0
- package/dist/schema/id.mjs.map +1 -0
- package/dist/schema/outbox.d.mts +240 -0
- package/dist/schema/outbox.mjs +53 -0
- package/dist/schema/outbox.mjs.map +1 -0
- package/dist/schema/question-route.mjs +16 -0
- package/dist/schema/question-route.mjs.map +1 -0
- package/dist/schema/receipt.d.mts +81 -0
- package/dist/schema/receipt.mjs +94 -0
- package/dist/schema/receipt.mjs.map +1 -0
- package/dist/schema/repository.d.mts +30 -0
- package/dist/schema/repository.mjs +29 -0
- package/dist/schema/repository.mjs.map +1 -0
- package/dist/schema/session.d.mts +136 -0
- package/dist/schema/session.mjs +54 -0
- package/dist/schema/session.mjs.map +1 -0
- package/dist/schema/signal.d.mts +105 -0
- package/dist/schema/signal.mjs +81 -0
- package/dist/schema/signal.mjs.map +1 -0
- package/dist/schema/slack-pr-notifications.d.mts +12 -0
- package/dist/schema/slack-pr-notifications.mjs +11 -0
- package/dist/schema/slack-pr-notifications.mjs.map +1 -0
- package/dist/schema/stored-session.mjs +10 -0
- package/dist/schema/stored-session.mjs.map +1 -0
- package/dist/schema/stored-task.mjs +20 -0
- package/dist/schema/stored-task.mjs.map +1 -0
- package/dist/schema/task-effect.d.mts +39 -0
- package/dist/schema/task-effect.mjs +29 -0
- package/dist/schema/task-effect.mjs.map +1 -0
- package/dist/schema/task-graph.d.mts +3173 -0
- package/dist/schema/task-graph.mjs +97 -0
- package/dist/schema/task-graph.mjs.map +1 -0
- package/dist/schema/task-message.d.mts +254 -0
- package/dist/schema/task-message.mjs +189 -0
- package/dist/schema/task-message.mjs.map +1 -0
- package/dist/schema/task.d.mts +273 -0
- package/dist/schema/task.mjs +200 -0
- package/dist/schema/task.mjs.map +1 -0
- package/dist/schema/transcript.d.mts +176 -0
- package/dist/schema/transcript.mjs +87 -0
- package/dist/schema/transcript.mjs.map +1 -0
- package/dist/schema/transitions.d.mts +50 -0
- package/dist/schema/transitions.mjs +303 -0
- package/dist/schema/transitions.mjs.map +1 -0
- package/dist/schema/work.d.mts +150 -0
- package/dist/schema/work.mjs +102 -0
- package/dist/schema/work.mjs.map +1 -0
- package/dist/session-previews.d.mts +76 -0
- package/dist/session-previews.mjs +55 -0
- package/dist/session-previews.mjs.map +1 -0
- package/dist/session-review.d.mts +120 -0
- package/dist/session-review.mjs +79 -0
- package/dist/session-review.mjs.map +1 -0
- package/dist/signal-triage.d.mts +20 -0
- package/dist/signal-triage.mjs +85 -0
- package/dist/signal-triage.mjs.map +1 -0
- package/dist/signals.d.mts +20 -0
- package/dist/signals.mjs +19 -0
- package/dist/signals.mjs.map +1 -0
- package/dist/stall.d.mts +41 -0
- package/dist/stall.mjs +83 -0
- package/dist/stall.mjs.map +1 -0
- package/dist/storage.d.mts +4 -0
- package/dist/storage.mjs +4 -0
- package/dist/store/driver.d.mts +65 -0
- package/dist/store/driver.mjs +42 -0
- package/dist/store/driver.mjs.map +1 -0
- package/dist/store/engine.d.mts +683 -0
- package/dist/store/engine.mjs +2309 -0
- package/dist/store/engine.mjs.map +1 -0
- package/dist/store/memory.d.mts +24 -0
- package/dist/store/memory.mjs +69 -0
- package/dist/store/memory.mjs.map +1 -0
- package/dist/store/slack-pr-notifications.d.mts +44 -0
- package/dist/store/slack-pr-notifications.mjs +121 -0
- package/dist/store/slack-pr-notifications.mjs.map +1 -0
- package/dist/store/task-effects.d.mts +38 -0
- package/dist/store/task-effects.mjs +118 -0
- package/dist/store/task-effects.mjs.map +1 -0
- package/dist/store/task-graphs.d.mts +60 -0
- package/dist/store/task-graphs.mjs +212 -0
- package/dist/store/task-graphs.mjs.map +1 -0
- package/dist/store/task-messages.d.mts +136 -0
- package/dist/store/task-messages.mjs +475 -0
- package/dist/store/task-messages.mjs.map +1 -0
- package/dist/store/task-work.d.mts +180 -0
- package/dist/store/task-work.mjs +137 -0
- package/dist/store/task-work.mjs.map +1 -0
- package/dist/store/work-notifications.d.mts +19 -0
- package/dist/store/work-notifications.mjs +48 -0
- package/dist/store/work-notifications.mjs.map +1 -0
- package/dist/sweep.d.mts +79 -0
- package/dist/sweep.mjs +171 -0
- package/dist/sweep.mjs.map +1 -0
- package/dist/task-communication.d.mts +35 -0
- package/dist/task-communication.mjs +47 -0
- package/dist/task-communication.mjs.map +1 -0
- package/dist/task-graph-view.d.mts +267 -0
- package/dist/task-graph-view.mjs +17 -0
- package/dist/task-graph-view.mjs.map +1 -0
- package/dist/task-message-processing.d.mts +60 -0
- package/dist/task-message-processing.mjs +200 -0
- package/dist/task-message-processing.mjs.map +1 -0
- package/dist/task-protocols.d.mts +80 -0
- package/dist/task-protocols.mjs +47 -0
- package/dist/task-protocols.mjs.map +1 -0
- package/dist/tasks.d.mts +17 -0
- package/dist/tasks.mjs +17 -0
- package/dist/vercel-git.d.mts +53 -0
- package/dist/vercel-git.mjs +344 -0
- package/dist/vercel-git.mjs.map +1 -0
- package/dist/vercel-github-api.d.mts +103 -0
- package/dist/vercel-github-api.mjs +363 -0
- package/dist/vercel-github-api.mjs.map +1 -0
- package/dist/vercel.d.mts +34 -2
- package/dist/vercel.mjs +49 -3
- package/dist/vercel.mjs.map +1 -1
- package/dist/work-triage/eve-tool.d.mts +29 -0
- package/dist/work-triage/eve-tool.mjs +32 -0
- package/dist/work-triage/eve-tool.mjs.map +1 -0
- package/dist/work-triage/find-existing-work.d.mts +32 -0
- package/dist/work-triage/find-existing-work.mjs +31 -0
- package/dist/work-triage/find-existing-work.mjs.map +1 -0
- package/dist/work-triage/github.d.mts +15 -0
- package/dist/work-triage/github.mjs +14 -0
- package/dist/work-triage/github.mjs.map +1 -0
- package/dist/work-triage.d.mts +4 -0
- package/dist/work-triage.mjs +3 -0
- package/dist/workflows.d.mts +146 -0
- package/dist/workflows.mjs +139 -0
- package/dist/workflows.mjs.map +1 -0
- package/dist/workspace-diff-assembly.d.mts +33 -0
- package/dist/workspace-diff-assembly.mjs +95 -0
- package/dist/workspace-diff-assembly.mjs.map +1 -0
- package/dist/workspace-diff.d.mts +90 -0
- package/dist/workspace-diff.mjs +61 -0
- package/dist/workspace-diff.mjs.map +1 -0
- package/dist/workspace-files-git.d.mts +15 -0
- package/dist/workspace-files-git.mjs +61 -0
- package/dist/workspace-files-git.mjs.map +1 -0
- package/dist/workspace-files.d.mts +107 -0
- package/dist/workspace-files.mjs +74 -0
- package/dist/workspace-files.mjs.map +1 -0
- package/dist/workspace-snapshot.d.mts +26 -0
- package/dist/workspace-snapshot.mjs +80 -0
- package/dist/workspace-snapshot.mjs.map +1 -0
- package/docs/getting-started.md +104 -0
- package/docs/index.md +100 -0
- package/docs/recipes/cancellation.md +215 -0
- package/docs/recipes/custom-workflow.md +153 -0
- package/docs/recipes/dependent-tasks.md +207 -0
- package/docs/recipes/eve-agent.md +277 -0
- package/docs/recipes/human-input.md +204 -0
- package/docs/recipes/persistence-recovery.md +268 -0
- package/docs/recipes/retry-recovery.md +241 -0
- package/docs/recipes/task-messaging.md +215 -0
- package/docs/recipes/typed-eve-result.md +161 -0
- package/docs/runtime-integration.md +137 -0
- package/package.json +142 -46
- package/dist/approval-JX2Px9IC.mjs +0 -132
- package/dist/approval-JX2Px9IC.mjs.map +0 -1
- package/dist/budget-DzSiIA4t.mjs +0 -42
- package/dist/budget-DzSiIA4t.mjs.map +0 -1
- package/dist/change-D2U6v7Ek.mjs +0 -554
- package/dist/change-D2U6v7Ek.mjs.map +0 -1
- package/dist/communication-Kd9nU5RP.mjs.map +0 -1
- package/dist/coordination-Cq08hb1l.mjs +0 -76
- package/dist/coordination-Cq08hb1l.mjs.map +0 -1
- package/dist/dispatch-BaZS3PT8.d.mts +0 -76
- package/dist/driver-BC0Mt5KG.d.mts +0 -34
- package/dist/driver-Bbd25rNM.mjs +0 -23
- package/dist/driver-Bbd25rNM.mjs.map +0 -1
- package/dist/engine-DFHU2Pe-.d.mts +0 -781
- package/dist/engine-WaUM2cGA.mjs +0 -1068
- package/dist/engine-WaUM2cGA.mjs.map +0 -1
- package/dist/factory-config-BoRXOw43.mjs +0 -50
- package/dist/factory-config-BoRXOw43.mjs.map +0 -1
- package/dist/factory-config-D2yU3G0c.d.mts +0 -58
- package/dist/github-C5HNBN6p.d.mts +0 -279
- package/dist/id-BLIkCVue.mjs.map +0 -1
- package/dist/index-Bw6hggoH.d.mts +0 -40
- package/dist/index.mjs.map +0 -1
- package/dist/task-CcOyOJ3k.mjs +0 -154
- package/dist/task-CcOyOJ3k.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-review.mjs","names":[],"sources":["../src/session-review.ts"],"sourcesContent":["import { z } from \"zod\";\n\nconst text = z.string().min(1);\nconst source = {\n source: text.describe(\"Human-readable origin of the evidence, including attempt when known.\"),\n revision: text.nullable().describe(\"Exact provider-owned revision, or null when not recorded.\"),\n};\n\n/** Validates one recorded check without inferring success from a completed Task. */\nexport const sessionReviewCheckSchema = z.strictObject({\n id: text.describe(\"Stable check identity within this review.\"),\n title: text.describe(\"Check name.\"),\n status: z\n .enum([\"passed\", \"failed\", \"skipped\", \"running\", \"unknown\"])\n .describe(\"Recorded outcome.\"),\n command: text.optional().describe(\"Exact command, when recorded.\"),\n details: text.optional().describe(\"Recorded output or explanation, rendered as Markdown.\"),\n ...source,\n});\n\nconst imageUrl = z.string().refine((value) => {\n if (/[\\s\\\\]/u.test(value)) return false;\n if (value.startsWith(\"/\") && !value.startsWith(\"//\")) return true;\n try {\n const url = new URL(value);\n return [\"https:\", \"http:\"].includes(url.protocol) && !url.username && !url.password;\n } catch {\n return false;\n }\n}, \"Use an HTTP(S) image URL or an absolute same-origin path\");\n\n/** Validates a screenshot supplied by the application's authorized review reader. */\nexport const sessionReviewScreenshotSchema = z.strictObject({\n id: text.describe(\"Stable image identity within this review.\"),\n url: imageUrl.describe(\"Browser-readable image URL; the application owns access and expiry.\"),\n caption: text.describe(\"Description of what the screenshot demonstrates.\"),\n state: z.enum([\"before\", \"after\"]).optional().describe(\"Side of a before/after comparison.\"),\n comparisonId: text.optional().describe(\"Groups before and after images of the same scenario.\"),\n width: z.number().int().positive().optional().describe(\"Captured pixel width.\"),\n height: z.number().int().positive().optional().describe(\"Captured pixel height.\"),\n ...source,\n});\n\n/** Validates a reported issue and the evidence or uncertainty behind it. */\nexport const sessionReviewIssueSchema = z.strictObject({\n id: text.describe(\"Stable issue identity within this review.\"),\n title: text.describe(\"Short problem description.\"),\n body: text.describe(\"Impact and explanation, rendered as Markdown.\"),\n status: z\n .enum([\"open\", \"resolved\"])\n .describe(\"Recorded resolution state, not inferred from Task success.\"),\n path: text.optional().describe(\"Repository-relative affected file.\"),\n line: z.number().int().positive().optional().describe(\"Affected line in the recorded revision.\"),\n priority: text.optional().describe(\"Application-defined urgency label.\"),\n evidence: text.optional().describe(\"What was checked and what it showed.\"),\n limitations: text.optional().describe(\"What remains uncertain or unchecked.\"),\n ...source,\n});\n\nconst common = {\n executionId: text.nullable().describe(\"Observed session execution, or null before execution.\"),\n capturedAt: z.iso.datetime().describe(\"When this evidence projection was read.\"),\n};\n\n/** Validates a review projection with explicit distinctions between missing and empty evidence. */\nexport const sessionReviewSchema = z.discriminatedUnion(\"state\", [\n z.strictObject({\n ...common,\n state: z.literal(\"ready\").describe(\"The configured review reader completed.\"),\n summary: text.optional().describe(\"Application-provided summary of the work.\"),\n checks: z\n .array(sessionReviewCheckSchema)\n .readonly()\n .nullable()\n .describe(\"Recorded checks; null means not recorded, not passing.\"),\n screenshots: z\n .array(sessionReviewScreenshotSchema)\n .readonly()\n .nullable()\n .describe(\"Recorded screenshots; null means no capture report is available.\"),\n issues: z\n .array(sessionReviewIssueSchema)\n .readonly()\n .nullable()\n .describe(\"Reported issues; null means no issue report is available.\"),\n limitations: z\n .array(text)\n .readonly()\n .describe(\"Missing evidence, unsupported sources, or other review limitations.\"),\n truncated: z\n .boolean()\n .describe(\"The reader omitted evidence because of its configured limits.\"),\n }),\n z.strictObject({\n ...common,\n state: z.literal(\"unavailable\").describe(\"Review evidence could not be read.\"),\n reason: text.describe(\"Why review evidence is unavailable.\"),\n }),\n]);\n\n/** Recorded check displayed in the operator review screen. */\nexport type SessionReviewCheck = z.infer<typeof sessionReviewCheckSchema>;\n/** Screenshot and optional before/after grouping supplied by an application. */\nexport type SessionReviewScreenshot = z.infer<typeof sessionReviewScreenshotSchema>;\n/** Reported issue with its recorded resolution state and supporting evidence. */\nexport type SessionReviewIssue = z.infer<typeof sessionReviewIssueSchema>;\n/** Provider-neutral evidence for reviewing an operator session. */\nexport type SessionReview = z.infer<typeof sessionReviewSchema>;\n"],"mappings":";;AAEA,MAAM,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;AAC7B,MAAM,SAAS;CACb,QAAQ,KAAK,SAAS,sEAAsE;CAC5F,UAAU,KAAK,SAAS,CAAC,CAAC,SAAS,2DAA2D;AAChG;;AAGA,MAAa,2BAA2B,EAAE,aAAa;CACrD,IAAI,KAAK,SAAS,2CAA2C;CAC7D,OAAO,KAAK,SAAS,aAAa;CAClC,QAAQ,EACL,KAAK;EAAC;EAAU;EAAU;EAAW;EAAW;CAAS,CAAC,CAAC,CAC3D,SAAS,mBAAmB;CAC/B,SAAS,KAAK,SAAS,CAAC,CAAC,SAAS,+BAA+B;CACjE,SAAS,KAAK,SAAS,CAAC,CAAC,SAAS,uDAAuD;CACzF,GAAG;AACL,CAAC;AAED,MAAM,WAAW,EAAE,OAAO,CAAC,CAAC,QAAQ,UAAU;CAC5C,IAAI,UAAU,KAAK,KAAK,GAAG,OAAO;CAClC,IAAI,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,WAAW,IAAI,GAAG,OAAO;CAC7D,IAAI;EACF,MAAM,MAAM,IAAI,IAAI,KAAK;EACzB,OAAO,CAAC,UAAU,OAAO,CAAC,CAAC,SAAS,IAAI,QAAQ,KAAK,CAAC,IAAI,YAAY,CAAC,IAAI;CAC7E,QAAQ;EACN,OAAO;CACT;AACF,GAAG,0DAA0D;;AAG7D,MAAa,gCAAgC,EAAE,aAAa;CAC1D,IAAI,KAAK,SAAS,2CAA2C;CAC7D,KAAK,SAAS,SAAS,qEAAqE;CAC5F,SAAS,KAAK,SAAS,kDAAkD;CACzE,OAAO,EAAE,KAAK,CAAC,UAAU,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,oCAAoC;CAC3F,cAAc,KAAK,SAAS,CAAC,CAAC,SAAS,sDAAsD;CAC7F,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,uBAAuB;CAC9E,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,wBAAwB;CAChF,GAAG;AACL,CAAC;;AAGD,MAAa,2BAA2B,EAAE,aAAa;CACrD,IAAI,KAAK,SAAS,2CAA2C;CAC7D,OAAO,KAAK,SAAS,4BAA4B;CACjD,MAAM,KAAK,SAAS,+CAA+C;CACnE,QAAQ,EACL,KAAK,CAAC,QAAQ,UAAU,CAAC,CAAC,CAC1B,SAAS,4DAA4D;CACxE,MAAM,KAAK,SAAS,CAAC,CAAC,SAAS,oCAAoC;CACnE,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,yCAAyC;CAC/F,UAAU,KAAK,SAAS,CAAC,CAAC,SAAS,oCAAoC;CACvE,UAAU,KAAK,SAAS,CAAC,CAAC,SAAS,sCAAsC;CACzE,aAAa,KAAK,SAAS,CAAC,CAAC,SAAS,sCAAsC;CAC5E,GAAG;AACL,CAAC;AAED,MAAM,SAAS;CACb,aAAa,KAAK,SAAS,CAAC,CAAC,SAAS,uDAAuD;CAC7F,YAAY,EAAE,IAAI,SAAS,CAAC,CAAC,SAAS,yCAAyC;AACjF;;AAGA,MAAa,sBAAsB,EAAE,mBAAmB,SAAS,CAC/D,EAAE,aAAa;CACb,GAAG;CACH,OAAO,EAAE,QAAQ,OAAO,CAAC,CAAC,SAAS,yCAAyC;CAC5E,SAAS,KAAK,SAAS,CAAC,CAAC,SAAS,2CAA2C;CAC7E,QAAQ,EACL,MAAM,wBAAwB,CAAC,CAC/B,SAAS,CAAC,CACV,SAAS,CAAC,CACV,SAAS,wDAAwD;CACpE,aAAa,EACV,MAAM,6BAA6B,CAAC,CACpC,SAAS,CAAC,CACV,SAAS,CAAC,CACV,SAAS,kEAAkE;CAC9E,QAAQ,EACL,MAAM,wBAAwB,CAAC,CAC/B,SAAS,CAAC,CACV,SAAS,CAAC,CACV,SAAS,2DAA2D;CACvE,aAAa,EACV,MAAM,IAAI,CAAC,CACX,SAAS,CAAC,CACV,SAAS,qEAAqE;CACjF,WAAW,EACR,QAAQ,CAAC,CACT,SAAS,+DAA+D;AAC7E,CAAC,GACD,EAAE,aAAa;CACb,GAAG;CACH,OAAO,EAAE,QAAQ,aAAa,CAAC,CAAC,SAAS,oCAAoC;CAC7E,QAAQ,KAAK,SAAS,qCAAqC;AAC7D,CAAC,CACH,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Signal } from "./schema/signal.mjs";
|
|
2
|
+
import { FactoryStores } from "./store/engine.mjs";
|
|
3
|
+
import { AuthFn } from "eve/channels/auth";
|
|
4
|
+
//#region src/signal-triage.d.ts
|
|
5
|
+
/** Bind optional signal attempt headers only after the underlying caller authenticates. */
|
|
6
|
+
declare function withSignalTriage(authenticate: AuthFn<Request>): AuthFn<Request>;
|
|
7
|
+
/** Encode the admitted Signal attempt for a trusted Foreman launch. */
|
|
8
|
+
declare function signalTriageHeaders(signal: Signal): Record<string, string>;
|
|
9
|
+
/** Persist admission before launching; an ambiguous launch stays visible and cannot be retried blindly. */
|
|
10
|
+
declare function runSignalTriage(stores: Pick<FactoryStores, "signals">, signal: Signal, options: {
|
|
11
|
+
expectedAttempt: number;
|
|
12
|
+
by: string;
|
|
13
|
+
}, launch: (admitted: Signal, operationId: string) => Promise<{
|
|
14
|
+
sessionId: string;
|
|
15
|
+
} | void>): Promise<Signal>;
|
|
16
|
+
/** Record taskless Foreman failures from authenticated, repository-scoped Eve lifecycle events. */
|
|
17
|
+
declare function createSignalTriageHook(stores: Pick<FactoryStores, "signals">): import("eve/hooks").HookDefinition<"session.failed" | "turn.cancelled" | "turn.completed" | "turn.failed">;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { createSignalTriageHook, runSignalTriage, signalTriageHeaders, withSignalTriage };
|
|
20
|
+
//# sourceMappingURL=signal-triage.d.mts.map
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { signalIdSchema } from "./schema/id.mjs";
|
|
2
|
+
import { repositoryIdsForSession } from "./eve/task-session.mjs";
|
|
3
|
+
import { ForbiddenError } from "eve/channels/auth";
|
|
4
|
+
import { defineHook } from "eve/hooks";
|
|
5
|
+
//#region src/signal-triage.ts
|
|
6
|
+
const signalHeader = "x-factory-signal-id";
|
|
7
|
+
const attemptHeader = "x-factory-signal-attempt";
|
|
8
|
+
/** Bind optional signal attempt headers only after the underlying caller authenticates. */
|
|
9
|
+
function withSignalTriage(authenticate) {
|
|
10
|
+
return async (request) => {
|
|
11
|
+
const auth = await authenticate(request);
|
|
12
|
+
if (auth == null) return auth;
|
|
13
|
+
const id = request.headers.get(signalHeader);
|
|
14
|
+
const attempt = request.headers.get(attemptHeader);
|
|
15
|
+
if (id === null && attempt === null) return auth;
|
|
16
|
+
if (!signalIdSchema.safeParse(id).success || !attempt || !/^[1-9]\d*$/u.test(attempt) || !Number.isSafeInteger(Number(attempt))) throw new ForbiddenError();
|
|
17
|
+
return {
|
|
18
|
+
...auth,
|
|
19
|
+
attributes: {
|
|
20
|
+
...auth.attributes,
|
|
21
|
+
factorySignalId: id,
|
|
22
|
+
factorySignalAttempt: attempt
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** Encode the admitted Signal attempt for a trusted Foreman launch. */
|
|
28
|
+
function signalTriageHeaders(signal) {
|
|
29
|
+
if (!signal.triage) throw new Error("Signal has no admitted triage attempt");
|
|
30
|
+
return {
|
|
31
|
+
[signalHeader]: signal.id,
|
|
32
|
+
[attemptHeader]: String(signal.triage.attempt)
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** Persist admission before launching; an ambiguous launch stays visible and cannot be retried blindly. */
|
|
36
|
+
async function runSignalTriage(stores, signal, options, launch) {
|
|
37
|
+
const admitted = await stores.signals.beginTriage(signal.id, options);
|
|
38
|
+
const attempt = admitted.triage.attempt;
|
|
39
|
+
let execution;
|
|
40
|
+
try {
|
|
41
|
+
execution = await launch(admitted, attempt === 1 ? `factory-signal:${signal.id}` : `factory-signal:${signal.id}:${attempt}`);
|
|
42
|
+
} catch {
|
|
43
|
+
return stores.signals.updateTriage(signal.id, attempt, {
|
|
44
|
+
state: "uncertain",
|
|
45
|
+
failure: "launch_unconfirmed"
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if (!execution) return stores.signals.updateTriage(signal.id, attempt, {
|
|
49
|
+
state: "uncertain",
|
|
50
|
+
failure: "launch_unconfirmed"
|
|
51
|
+
});
|
|
52
|
+
return stores.signals.updateTriage(signal.id, attempt, {
|
|
53
|
+
state: "running",
|
|
54
|
+
sessionId: execution.sessionId
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/** Record taskless Foreman failures from authenticated, repository-scoped Eve lifecycle events. */
|
|
58
|
+
function createSignalTriageHook(stores) {
|
|
59
|
+
async function stopped(ctx, failure) {
|
|
60
|
+
const auth = ctx.session.auth.initiator;
|
|
61
|
+
const id = signalIdSchema.safeParse(auth?.attributes.factorySignalId);
|
|
62
|
+
const attempt = Number(auth?.attributes.factorySignalAttempt);
|
|
63
|
+
if (!id.success || !Number.isSafeInteger(attempt) || attempt < 1) return;
|
|
64
|
+
const signal = await stores.signals.get(id.data);
|
|
65
|
+
if (!signal || !repositoryIdsForSession(auth)?.includes(signal.repositoryId)) return;
|
|
66
|
+
await stores.signals.updateTriage(id.data, attempt, {
|
|
67
|
+
state: "blocked",
|
|
68
|
+
failure,
|
|
69
|
+
sessionId: ctx.session.id
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
function category(code, message) {
|
|
73
|
+
return `${code} ${message}`.includes("customer_verification_required") ? "billing_verification_required" : "provider_failed";
|
|
74
|
+
}
|
|
75
|
+
return defineHook({ events: {
|
|
76
|
+
"turn.failed": (event, ctx) => stopped(ctx, category(event.data.code, event.data.message)),
|
|
77
|
+
"session.failed": (event, ctx) => stopped(ctx, category(event.data.code, event.data.message)),
|
|
78
|
+
"turn.cancelled": (_event, ctx) => stopped(ctx, "cancelled"),
|
|
79
|
+
"turn.completed": (_event, ctx) => stopped(ctx, "no_decision")
|
|
80
|
+
} });
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
83
|
+
export { createSignalTriageHook, runSignalTriage, signalTriageHeaders, withSignalTriage };
|
|
84
|
+
|
|
85
|
+
//# sourceMappingURL=signal-triage.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signal-triage.mjs","names":[],"sources":["../src/signal-triage.ts"],"sourcesContent":["import { ForbiddenError, type AuthFn } from \"eve/channels/auth\";\nimport type { SessionContext } from \"eve/context\";\nimport { defineHook } from \"eve/hooks\";\nimport { signalIdSchema } from \"./schema/id\";\nimport type { Signal, SignalTriage } from \"./schema/signal\";\nimport type { FactoryStores } from \"./store/engine\";\nimport { repositoryIdsForSession } from \"./eve/task-session\";\n\nconst signalHeader = \"x-factory-signal-id\";\nconst attemptHeader = \"x-factory-signal-attempt\";\n\n/** Bind optional signal attempt headers only after the underlying caller authenticates. */\nexport function withSignalTriage(authenticate: AuthFn<Request>): AuthFn<Request> {\n return async (request) => {\n const auth = await authenticate(request);\n if (auth == null) return auth;\n const id = request.headers.get(signalHeader);\n const attempt = request.headers.get(attemptHeader);\n if (id === null && attempt === null) return auth;\n if (\n !signalIdSchema.safeParse(id).success ||\n !attempt ||\n !/^[1-9]\\d*$/u.test(attempt) ||\n !Number.isSafeInteger(Number(attempt))\n )\n throw new ForbiddenError();\n return {\n ...auth,\n attributes: { ...auth.attributes, factorySignalId: id!, factorySignalAttempt: attempt },\n };\n };\n}\n\n/** Encode the admitted Signal attempt for a trusted Foreman launch. */\nexport function signalTriageHeaders(signal: Signal): Record<string, string> {\n if (!signal.triage) throw new Error(\"Signal has no admitted triage attempt\");\n return { [signalHeader]: signal.id, [attemptHeader]: String(signal.triage.attempt) };\n}\n\n/** Persist admission before launching; an ambiguous launch stays visible and cannot be retried blindly. */\nexport async function runSignalTriage(\n stores: Pick<FactoryStores, \"signals\">,\n signal: Signal,\n options: { expectedAttempt: number; by: string },\n launch: (admitted: Signal, operationId: string) => Promise<{ sessionId: string } | void>,\n): Promise<Signal> {\n const admitted = await stores.signals.beginTriage(signal.id, options);\n const attempt = admitted.triage!.attempt;\n let execution: { sessionId: string } | void;\n try {\n execution = await launch(\n admitted,\n attempt === 1 ? `factory-signal:${signal.id}` : `factory-signal:${signal.id}:${attempt}`,\n );\n } catch {\n return stores.signals.updateTriage(signal.id, attempt, {\n state: \"uncertain\",\n failure: \"launch_unconfirmed\",\n });\n }\n if (!execution)\n return stores.signals.updateTriage(signal.id, attempt, {\n state: \"uncertain\",\n failure: \"launch_unconfirmed\",\n });\n return stores.signals.updateTriage(signal.id, attempt, {\n state: \"running\",\n sessionId: execution.sessionId,\n });\n}\n\n/** Record taskless Foreman failures from authenticated, repository-scoped Eve lifecycle events. */\nexport function createSignalTriageHook(stores: Pick<FactoryStores, \"signals\">) {\n async function stopped(ctx: Pick<SessionContext, \"session\">, failure: SignalTriage[\"failure\"]) {\n const auth = ctx.session.auth.initiator;\n const id = signalIdSchema.safeParse(auth?.attributes.factorySignalId);\n const attempt = Number(auth?.attributes.factorySignalAttempt);\n if (!id.success || !Number.isSafeInteger(attempt) || attempt < 1) return;\n const signal = await stores.signals.get(id.data);\n if (!signal || !repositoryIdsForSession(auth)?.includes(signal.repositoryId)) return;\n await stores.signals.updateTriage(id.data, attempt, {\n state: \"blocked\",\n failure,\n sessionId: ctx.session.id,\n });\n }\n function category(code: string, message: string): SignalTriage[\"failure\"] {\n return `${code} ${message}`.includes(\"customer_verification_required\")\n ? \"billing_verification_required\"\n : \"provider_failed\";\n }\n return defineHook({\n events: {\n \"turn.failed\": (event, ctx) => stopped(ctx, category(event.data.code, event.data.message)),\n \"session.failed\": (event, ctx) => stopped(ctx, category(event.data.code, event.data.message)),\n \"turn.cancelled\": (_event, ctx) => stopped(ctx, \"cancelled\"),\n \"turn.completed\": (_event, ctx) => stopped(ctx, \"no_decision\"),\n },\n });\n}\n"],"mappings":";;;;;AAQA,MAAM,eAAe;AACrB,MAAM,gBAAgB;;AAGtB,SAAgB,iBAAiB,cAAgD;CAC/E,OAAO,OAAO,YAAY;EACxB,MAAM,OAAO,MAAM,aAAa,OAAO;EACvC,IAAI,QAAQ,MAAM,OAAO;EACzB,MAAM,KAAK,QAAQ,QAAQ,IAAI,YAAY;EAC3C,MAAM,UAAU,QAAQ,QAAQ,IAAI,aAAa;EACjD,IAAI,OAAO,QAAQ,YAAY,MAAM,OAAO;EAC5C,IACE,CAAC,eAAe,UAAU,EAAE,CAAC,CAAC,WAC9B,CAAC,WACD,CAAC,cAAc,KAAK,OAAO,KAC3B,CAAC,OAAO,cAAc,OAAO,OAAO,CAAC,GAErC,MAAM,IAAI,eAAe;EAC3B,OAAO;GACL,GAAG;GACH,YAAY;IAAE,GAAG,KAAK;IAAY,iBAAiB;IAAK,sBAAsB;GAAQ;EACxF;CACF;AACF;;AAGA,SAAgB,oBAAoB,QAAwC;CAC1E,IAAI,CAAC,OAAO,QAAQ,MAAM,IAAI,MAAM,uCAAuC;CAC3E,OAAO;GAAG,eAAe,OAAO;GAAK,gBAAgB,OAAO,OAAO,OAAO,OAAO;CAAE;AACrF;;AAGA,eAAsB,gBACpB,QACA,QACA,SACA,QACiB;CACjB,MAAM,WAAW,MAAM,OAAO,QAAQ,YAAY,OAAO,IAAI,OAAO;CACpE,MAAM,UAAU,SAAS,OAAQ;CACjC,IAAI;CACJ,IAAI;EACF,YAAY,MAAM,OAChB,UACA,YAAY,IAAI,kBAAkB,OAAO,OAAO,kBAAkB,OAAO,GAAG,GAAG,SACjF;CACF,QAAQ;EACN,OAAO,OAAO,QAAQ,aAAa,OAAO,IAAI,SAAS;GACrD,OAAO;GACP,SAAS;EACX,CAAC;CACH;CACA,IAAI,CAAC,WACH,OAAO,OAAO,QAAQ,aAAa,OAAO,IAAI,SAAS;EACrD,OAAO;EACP,SAAS;CACX,CAAC;CACH,OAAO,OAAO,QAAQ,aAAa,OAAO,IAAI,SAAS;EACrD,OAAO;EACP,WAAW,UAAU;CACvB,CAAC;AACH;;AAGA,SAAgB,uBAAuB,QAAwC;CAC7E,eAAe,QAAQ,KAAsC,SAAkC;EAC7F,MAAM,OAAO,IAAI,QAAQ,KAAK;EAC9B,MAAM,KAAK,eAAe,UAAU,MAAM,WAAW,eAAe;EACpE,MAAM,UAAU,OAAO,MAAM,WAAW,oBAAoB;EAC5D,IAAI,CAAC,GAAG,WAAW,CAAC,OAAO,cAAc,OAAO,KAAK,UAAU,GAAG;EAClE,MAAM,SAAS,MAAM,OAAO,QAAQ,IAAI,GAAG,IAAI;EAC/C,IAAI,CAAC,UAAU,CAAC,wBAAwB,IAAI,CAAC,EAAE,SAAS,OAAO,YAAY,GAAG;EAC9E,MAAM,OAAO,QAAQ,aAAa,GAAG,MAAM,SAAS;GAClD,OAAO;GACP;GACA,WAAW,IAAI,QAAQ;EACzB,CAAC;CACH;CACA,SAAS,SAAS,MAAc,SAA0C;EACxE,OAAO,GAAG,KAAK,GAAG,UAAU,SAAS,gCAAgC,IACjE,kCACA;CACN;CACA,OAAO,WAAW,EAChB,QAAQ;EACN,gBAAgB,OAAO,QAAQ,QAAQ,KAAK,SAAS,MAAM,KAAK,MAAM,MAAM,KAAK,OAAO,CAAC;EACzF,mBAAmB,OAAO,QAAQ,QAAQ,KAAK,SAAS,MAAM,KAAK,MAAM,MAAM,KAAK,OAAO,CAAC;EAC5F,mBAAmB,QAAQ,QAAQ,QAAQ,KAAK,WAAW;EAC3D,mBAAmB,QAAQ,QAAQ,QAAQ,KAAK,aAAa;CAC/D,EACF,CAAC;AACH"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { DecidedSignal, PendingSignal, Signal, SignalOutcome, SignalSource, SignalTriage, signalOutcomeSchema, signalSchema, signalSourceSchema, signalTriageSchema, standardSignalSources } from "./schema/signal.mjs";
|
|
3
|
+
import { SignalId, signalIdSchema } from "./schema/id.mjs";
|
|
4
|
+
import { CreateSignalInput, DecideSignalInput, FactoryStores } from "./store/engine.mjs";
|
|
5
|
+
import { signalInitialOutcome, signalOutcomeTransitions, signalTriageTransitions } from "./schema/transitions.mjs";
|
|
6
|
+
import { createSignalTriageHook, runSignalTriage, signalTriageHeaders, withSignalTriage } from "./signal-triage.mjs";
|
|
7
|
+
//#region src/signals.d.ts
|
|
8
|
+
/** Narrow intake boundary that persists normalized Signals without starting workflow work. */
|
|
9
|
+
interface SignalCreator {
|
|
10
|
+
create(input: CreateSignalInput): Promise<Signal>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Bind normalized intake to signal creation alone. Connectors and API routes
|
|
14
|
+
* own authentication and normalization; configured workflows own what happens
|
|
15
|
+
* next.
|
|
16
|
+
*/
|
|
17
|
+
declare function createSignalCreator(stores: Pick<FactoryStores, "signals">): SignalCreator;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { type CreateSignalInput, type DecideSignalInput, type DecidedSignal, type PendingSignal, type Signal, SignalCreator, type SignalId, type SignalOutcome, type SignalSource, type SignalTriage, createSignalCreator, createSignalTriageHook, runSignalTriage, signalIdSchema, signalInitialOutcome, signalOutcomeSchema, signalOutcomeTransitions, signalSchema, signalSourceSchema, signalTriageHeaders, signalTriageSchema, signalTriageTransitions, standardSignalSources, withSignalTriage };
|
|
20
|
+
//# sourceMappingURL=signals.d.mts.map
|
package/dist/signals.mjs
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { signalIdSchema } from "./schema/id.mjs";
|
|
2
|
+
import { signalInitialOutcome, signalOutcomeTransitions, signalTriageTransitions } from "./schema/transitions.mjs";
|
|
3
|
+
import { signalOutcomeSchema, signalSchema, signalSourceSchema, signalTriageSchema, standardSignalSources } from "./schema/signal.mjs";
|
|
4
|
+
import { createSignalTriageHook, runSignalTriage, signalTriageHeaders, withSignalTriage } from "./signal-triage.mjs";
|
|
5
|
+
//#region src/signals.ts
|
|
6
|
+
/**
|
|
7
|
+
* Bind normalized intake to signal creation alone. Connectors and API routes
|
|
8
|
+
* own authentication and normalization; configured workflows own what happens
|
|
9
|
+
* next.
|
|
10
|
+
*/
|
|
11
|
+
function createSignalCreator(stores) {
|
|
12
|
+
return { create(input) {
|
|
13
|
+
return stores.signals.create(input);
|
|
14
|
+
} };
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { createSignalCreator, createSignalTriageHook, runSignalTriage, signalIdSchema, signalInitialOutcome, signalOutcomeSchema, signalOutcomeTransitions, signalSchema, signalSourceSchema, signalTriageHeaders, signalTriageSchema, signalTriageTransitions, standardSignalSources, withSignalTriage };
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=signals.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signals.mjs","names":[],"sources":["../src/signals.ts"],"sourcesContent":["import type { Signal } from \"./schema/signal\";\nimport type { CreateSignalInput, FactoryStores } from \"./store/engine\";\n\nexport { signalIdSchema, type SignalId } from \"./schema/id\";\nexport {\n signalOutcomeSchema,\n signalTriageSchema,\n type SignalTriage,\n signalSchema,\n signalSourceSchema,\n standardSignalSources,\n type DecidedSignal,\n type PendingSignal,\n type Signal,\n type SignalOutcome,\n type SignalSource,\n} from \"./schema/signal\";\nexport {\n signalInitialOutcome,\n signalOutcomeTransitions,\n signalTriageTransitions,\n} from \"./schema/transitions\";\nexport { type CreateSignalInput, type DecideSignalInput } from \"./store/engine\";\n\n/** Narrow intake boundary that persists normalized Signals without starting workflow work. */\nexport interface SignalCreator {\n create(input: CreateSignalInput): Promise<Signal>;\n}\n\n/**\n * Bind normalized intake to signal creation alone. Connectors and API routes\n * own authentication and normalization; configured workflows own what happens\n * next.\n */\nexport function createSignalCreator(stores: Pick<FactoryStores, \"signals\">): SignalCreator {\n return {\n create(input) {\n return stores.signals.create(input);\n },\n };\n}\n\nexport {\n createSignalTriageHook,\n withSignalTriage,\n signalTriageHeaders,\n runSignalTriage,\n} from \"./signal-triage\";\n"],"mappings":";;;;;;;;;;AAkCA,SAAgB,oBAAoB,QAAuD;CACzF,OAAO,EACL,OAAO,OAAO;EACZ,OAAO,OAAO,QAAQ,OAAO,KAAK;CACpC,EACF;AACF"}
|
package/dist/stall.d.mts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { TaskId } from "./schema/id.mjs";
|
|
2
|
+
import { Task } from "./schema/task.mjs";
|
|
3
|
+
import { DateClock, MaybePromise } from "./schema/common.mjs";
|
|
4
|
+
import { FactoryStores } from "./store/engine.mjs";
|
|
5
|
+
import { ExecutionPolicy } from "./schema/factory-config.mjs";
|
|
6
|
+
//#region src/stall.d.ts
|
|
7
|
+
/** Execution policy, clock, snapshot, and optional workflow cancellation hook for stall recovery. */
|
|
8
|
+
interface StallSweepOptions {
|
|
9
|
+
policy: ExecutionPolicy;
|
|
10
|
+
now?: DateClock;
|
|
11
|
+
/** A dispatcher-wide snapshot avoids another complete task read. */
|
|
12
|
+
tasks?: readonly Task[];
|
|
13
|
+
/** Recover a saved result before marking work stalled; a throw defers stall recovery. */
|
|
14
|
+
recoverResult?: (task: Task) => Promise<boolean>;
|
|
15
|
+
/** Optional workflow policy that cancels a stalled task instead of retrying it. */
|
|
16
|
+
cancelStalled?: (task: Task, tasks: readonly Task[]) => MaybePromise<string | null>;
|
|
17
|
+
}
|
|
18
|
+
/** Task IDs transitioned at each stage of one stall-recovery pass. */
|
|
19
|
+
interface TaskStallSweepResult {
|
|
20
|
+
readonly stalled: readonly TaskId[];
|
|
21
|
+
readonly requeued: readonly TaskId[];
|
|
22
|
+
readonly failed: readonly TaskId[];
|
|
23
|
+
readonly cancelled: readonly TaskId[];
|
|
24
|
+
}
|
|
25
|
+
/** Task capability required to detect and recover stalled work. */
|
|
26
|
+
type TaskStallSweepStores = Pick<FactoryStores, "tasks">;
|
|
27
|
+
/** Resolve the progress timeout for a Task kind from the configured execution policy. */
|
|
28
|
+
declare function stallWindowMinutes(policy: ExecutionPolicy, kind: Task["kind"]): number;
|
|
29
|
+
/**
|
|
30
|
+
* The reconciler's stall pass. A running task whose execution has not
|
|
31
|
+
* progressed within its stall window is marked stalled; a stalled task is
|
|
32
|
+
* re-queued for a replacement attempt while attempts remain, and failed once
|
|
33
|
+
* they are exhausted. Only `running` tasks can stall: a task whose result has
|
|
34
|
+
* already been recorded (verifying, or terminal) is never retried by this
|
|
35
|
+
* pass. Workflows explicitly waiting for messages are skipped. Configured result recovery
|
|
36
|
+
* runs before marking a Task stalled; an error defers that attempt to a later pass.
|
|
37
|
+
*/
|
|
38
|
+
declare function sweepTaskStalls(stores: TaskStallSweepStores, options: StallSweepOptions): Promise<TaskStallSweepResult>;
|
|
39
|
+
//#endregion
|
|
40
|
+
export { StallSweepOptions, TaskStallSweepResult, TaskStallSweepStores, stallWindowMinutes, sweepTaskStalls };
|
|
41
|
+
//# sourceMappingURL=stall.d.mts.map
|
package/dist/stall.mjs
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
//#region src/stall.ts
|
|
2
|
+
/** Resolve the progress timeout for a Task kind from the configured execution policy. */
|
|
3
|
+
function stallWindowMinutes(policy, kind) {
|
|
4
|
+
return policy.stallMinutesByKind[kind] ?? policy.stallMinutes;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* The reconciler's stall pass. A running task whose execution has not
|
|
8
|
+
* progressed within its stall window is marked stalled; a stalled task is
|
|
9
|
+
* re-queued for a replacement attempt while attempts remain, and failed once
|
|
10
|
+
* they are exhausted. Only `running` tasks can stall: a task whose result has
|
|
11
|
+
* already been recorded (verifying, or terminal) is never retried by this
|
|
12
|
+
* pass. Workflows explicitly waiting for messages are skipped. Configured result recovery
|
|
13
|
+
* runs before marking a Task stalled; an error defers that attempt to a later pass.
|
|
14
|
+
*/
|
|
15
|
+
async function sweepTaskStalls(stores, options) {
|
|
16
|
+
const nowMs = (options.now ?? (() => /* @__PURE__ */ new Date()))().getTime();
|
|
17
|
+
const result = {
|
|
18
|
+
stalled: [],
|
|
19
|
+
requeued: [],
|
|
20
|
+
failed: [],
|
|
21
|
+
cancelled: []
|
|
22
|
+
};
|
|
23
|
+
const tasks = options.tasks ?? await stores.tasks.list();
|
|
24
|
+
const newlyStalled = [];
|
|
25
|
+
for (const task of tasks) {
|
|
26
|
+
if (task.waitingForMessages || task.state !== "running") continue;
|
|
27
|
+
const minutes = stallWindowMinutes(options.policy, task.kind);
|
|
28
|
+
const sinceProgress = nowMs - Date.parse(task.lastProgressAt ?? task.updatedAt);
|
|
29
|
+
if (sinceProgress < minutes * 6e4) continue;
|
|
30
|
+
try {
|
|
31
|
+
if (await options.recoverResult?.(task)) continue;
|
|
32
|
+
const stalled = await stores.tasks.transition(task.id, "stalled", {
|
|
33
|
+
reason: `no progress for ${Math.floor(sinceProgress / 6e4)} minutes (window ${minutes})`,
|
|
34
|
+
expectFrom: "running",
|
|
35
|
+
expectAttempt: task.attempt,
|
|
36
|
+
expectExecution: task.execution
|
|
37
|
+
});
|
|
38
|
+
result.stalled.push(task.id);
|
|
39
|
+
newlyStalled.push(stalled);
|
|
40
|
+
} catch {
|
|
41
|
+
if (options.tasks !== void 0) {
|
|
42
|
+
const current = await stores.tasks.get(task.id).catch(() => null);
|
|
43
|
+
if (current?.state === "stalled") newlyStalled.push(current);
|
|
44
|
+
}
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const stalledCandidates = options.tasks === void 0 ? await stores.tasks.list() : [...tasks.filter((task) => task.state === "stalled"), ...newlyStalled];
|
|
49
|
+
for (const task of stalledCandidates) {
|
|
50
|
+
if (task.waitingForMessages || task.state !== "stalled") continue;
|
|
51
|
+
const cancellationReason = await options.cancelStalled?.(task, tasks) ?? null;
|
|
52
|
+
try {
|
|
53
|
+
if (cancellationReason !== null) {
|
|
54
|
+
await stores.tasks.transition(task.id, "cancelled", {
|
|
55
|
+
reason: cancellationReason,
|
|
56
|
+
expectFrom: "stalled"
|
|
57
|
+
});
|
|
58
|
+
result.cancelled.push(task.id);
|
|
59
|
+
} else if (task.attempt < options.policy.maxAttempts) {
|
|
60
|
+
await stores.tasks.transition(task.id, "queued", {
|
|
61
|
+
reason: `stalled on attempt ${task.attempt} of ${options.policy.maxAttempts}; replacing`,
|
|
62
|
+
phase: "retry",
|
|
63
|
+
expectFrom: "stalled"
|
|
64
|
+
});
|
|
65
|
+
result.requeued.push(task.id);
|
|
66
|
+
} else {
|
|
67
|
+
await stores.tasks.transition(task.id, "failed", {
|
|
68
|
+
reason: `stalled on attempt ${task.attempt} of ${options.policy.maxAttempts}; attempts exhausted`,
|
|
69
|
+
phase: "retry",
|
|
70
|
+
expectFrom: "stalled"
|
|
71
|
+
});
|
|
72
|
+
result.failed.push(task.id);
|
|
73
|
+
}
|
|
74
|
+
} catch {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
export { stallWindowMinutes, sweepTaskStalls };
|
|
82
|
+
|
|
83
|
+
//# sourceMappingURL=stall.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stall.mjs","names":[],"sources":["../src/stall.ts"],"sourcesContent":["import type { ExecutionPolicy } from \"./schema/factory-config\";\nimport type { DateClock, MaybePromise } from \"./schema/common\";\nimport type { TaskId } from \"./schema/id\";\nimport type { Task } from \"./schema/task\";\nimport type { FactoryStores } from \"./store/engine\";\n\n/** Execution policy, clock, snapshot, and optional workflow cancellation hook for stall recovery. */\nexport interface StallSweepOptions {\n policy: ExecutionPolicy;\n now?: DateClock;\n /** A dispatcher-wide snapshot avoids another complete task read. */\n tasks?: readonly Task[];\n /** Recover a saved result before marking work stalled; a throw defers stall recovery. */\n recoverResult?: (task: Task) => Promise<boolean>;\n /** Optional workflow policy that cancels a stalled task instead of retrying it. */\n cancelStalled?: (task: Task, tasks: readonly Task[]) => MaybePromise<string | null>;\n}\n\n/** Task IDs transitioned at each stage of one stall-recovery pass. */\nexport interface TaskStallSweepResult {\n readonly stalled: readonly TaskId[];\n readonly requeued: readonly TaskId[];\n readonly failed: readonly TaskId[];\n readonly cancelled: readonly TaskId[];\n}\n\n/** Task capability required to detect and recover stalled work. */\nexport type TaskStallSweepStores = Pick<FactoryStores, \"tasks\">;\n\n/** Resolve the progress timeout for a Task kind from the configured execution policy. */\nexport function stallWindowMinutes(policy: ExecutionPolicy, kind: Task[\"kind\"]): number {\n return policy.stallMinutesByKind[kind] ?? policy.stallMinutes;\n}\n\n/**\n * The reconciler's stall pass. A running task whose execution has not\n * progressed within its stall window is marked stalled; a stalled task is\n * re-queued for a replacement attempt while attempts remain, and failed once\n * they are exhausted. Only `running` tasks can stall: a task whose result has\n * already been recorded (verifying, or terminal) is never retried by this\n * pass. Workflows explicitly waiting for messages are skipped. Configured result recovery\n * runs before marking a Task stalled; an error defers that attempt to a later pass.\n */\nexport async function sweepTaskStalls(\n stores: TaskStallSweepStores,\n options: StallSweepOptions,\n): Promise<TaskStallSweepResult> {\n const nowMs = (options.now ?? (() => new Date()))().getTime();\n const result: {\n stalled: TaskId[];\n requeued: TaskId[];\n failed: TaskId[];\n cancelled: TaskId[];\n } = {\n stalled: [],\n requeued: [],\n failed: [],\n cancelled: [],\n };\n const tasks = options.tasks ?? (await stores.tasks.list());\n const newlyStalled: Task[] = [];\n\n for (const task of tasks) {\n if (task.waitingForMessages || task.state !== \"running\") {\n continue;\n }\n const minutes = stallWindowMinutes(options.policy, task.kind);\n const sinceProgress = nowMs - Date.parse(task.lastProgressAt ?? task.updatedAt);\n if (sinceProgress < minutes * 60_000) {\n continue;\n }\n // A concurrent writer may have moved the task; skip rather than abort.\n try {\n if (await options.recoverResult?.(task)) continue;\n const stalled = await stores.tasks.transition(task.id, \"stalled\", {\n reason: `no progress for ${Math.floor(sinceProgress / 60_000)} minutes (window ${minutes})`,\n expectFrom: \"running\",\n expectAttempt: task.attempt,\n expectExecution: task.execution,\n });\n result.stalled.push(task.id);\n newlyStalled.push(stalled);\n } catch {\n if (options.tasks !== undefined) {\n const current = await stores.tasks.get(task.id).catch(() => null);\n if (current?.state === \"stalled\") newlyStalled.push(current);\n }\n continue;\n }\n }\n\n // Resolve every stalled task, including ones stalled by an earlier pass that\n // crashed before reaching this step.\n const stalledCandidates =\n options.tasks === undefined\n ? await stores.tasks.list()\n : [...tasks.filter((task) => task.state === \"stalled\"), ...newlyStalled];\n for (const task of stalledCandidates) {\n if (task.waitingForMessages || task.state !== \"stalled\") {\n continue;\n }\n const cancellationReason = (await options.cancelStalled?.(task, tasks)) ?? null;\n try {\n if (cancellationReason !== null) {\n await stores.tasks.transition(task.id, \"cancelled\", {\n reason: cancellationReason,\n expectFrom: \"stalled\",\n });\n result.cancelled.push(task.id);\n } else if (task.attempt < options.policy.maxAttempts) {\n await stores.tasks.transition(task.id, \"queued\", {\n reason: `stalled on attempt ${task.attempt} of ${options.policy.maxAttempts}; replacing`,\n phase: \"retry\",\n expectFrom: \"stalled\",\n });\n result.requeued.push(task.id);\n } else {\n await stores.tasks.transition(task.id, \"failed\", {\n reason: `stalled on attempt ${task.attempt} of ${options.policy.maxAttempts}; attempts exhausted`,\n phase: \"retry\",\n expectFrom: \"stalled\",\n });\n result.failed.push(task.id);\n }\n } catch {\n continue;\n }\n }\n return result;\n}\n"],"mappings":";;AA8BA,SAAgB,mBAAmB,QAAyB,MAA4B;CACtF,OAAO,OAAO,mBAAmB,SAAS,OAAO;AACnD;;;;;;;;;;AAWA,eAAsB,gBACpB,QACA,SAC+B;CAC/B,MAAM,SAAS,QAAQ,8BAAc,IAAI,KAAK,GAAA,CAAI,CAAC,CAAC,QAAQ;CAC5D,MAAM,SAKF;EACF,SAAS,CAAC;EACV,UAAU,CAAC;EACX,QAAQ,CAAC;EACT,WAAW,CAAC;CACd;CACA,MAAM,QAAQ,QAAQ,SAAU,MAAM,OAAO,MAAM,KAAK;CACxD,MAAM,eAAuB,CAAC;CAE9B,KAAK,MAAM,QAAQ,OAAO;EACxB,IAAI,KAAK,sBAAsB,KAAK,UAAU,WAC5C;EAEF,MAAM,UAAU,mBAAmB,QAAQ,QAAQ,KAAK,IAAI;EAC5D,MAAM,gBAAgB,QAAQ,KAAK,MAAM,KAAK,kBAAkB,KAAK,SAAS;EAC9E,IAAI,gBAAgB,UAAU,KAC5B;EAGF,IAAI;GACF,IAAI,MAAM,QAAQ,gBAAgB,IAAI,GAAG;GACzC,MAAM,UAAU,MAAM,OAAO,MAAM,WAAW,KAAK,IAAI,WAAW;IAChE,QAAQ,mBAAmB,KAAK,MAAM,gBAAgB,GAAM,EAAE,mBAAmB,QAAQ;IACzF,YAAY;IACZ,eAAe,KAAK;IACpB,iBAAiB,KAAK;GACxB,CAAC;GACD,OAAO,QAAQ,KAAK,KAAK,EAAE;GAC3B,aAAa,KAAK,OAAO;EAC3B,QAAQ;GACN,IAAI,QAAQ,UAAU,KAAA,GAAW;IAC/B,MAAM,UAAU,MAAM,OAAO,MAAM,IAAI,KAAK,EAAE,CAAC,CAAC,YAAY,IAAI;IAChE,IAAI,SAAS,UAAU,WAAW,aAAa,KAAK,OAAO;GAC7D;GACA;EACF;CACF;CAIA,MAAM,oBACJ,QAAQ,UAAU,KAAA,IACd,MAAM,OAAO,MAAM,KAAK,IACxB,CAAC,GAAG,MAAM,QAAQ,SAAS,KAAK,UAAU,SAAS,GAAG,GAAG,YAAY;CAC3E,KAAK,MAAM,QAAQ,mBAAmB;EACpC,IAAI,KAAK,sBAAsB,KAAK,UAAU,WAC5C;EAEF,MAAM,qBAAsB,MAAM,QAAQ,gBAAgB,MAAM,KAAK,KAAM;EAC3E,IAAI;GACF,IAAI,uBAAuB,MAAM;IAC/B,MAAM,OAAO,MAAM,WAAW,KAAK,IAAI,aAAa;KAClD,QAAQ;KACR,YAAY;IACd,CAAC;IACD,OAAO,UAAU,KAAK,KAAK,EAAE;GAC/B,OAAO,IAAI,KAAK,UAAU,QAAQ,OAAO,aAAa;IACpD,MAAM,OAAO,MAAM,WAAW,KAAK,IAAI,UAAU;KAC/C,QAAQ,sBAAsB,KAAK,QAAQ,MAAM,QAAQ,OAAO,YAAY;KAC5E,OAAO;KACP,YAAY;IACd,CAAC;IACD,OAAO,SAAS,KAAK,KAAK,EAAE;GAC9B,OAAO;IACL,MAAM,OAAO,MAAM,WAAW,KAAK,IAAI,UAAU;KAC/C,QAAQ,sBAAsB,KAAK,QAAQ,MAAM,QAAQ,OAAO,YAAY;KAC5E,OAAO;KACP,YAAY;IACd,CAAC;IACD,OAAO,OAAO,KAAK,KAAK,EAAE;GAC5B;EACF,QAAQ;GACN;EACF;CACF;CACA,OAAO;AACT"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { CollectionName, InsertStoreRecordInput, RecordExistsError, RecordNotFoundError, StoreDriver, StoredEntry, StoredRecord, TransientStoreError, UpdateStoreRecordInput, VersionConflictError } from "./store/driver.mjs";
|
|
2
|
+
import { CacheContinuationContextInput, CreateStoresOptions, FactoryStores, createStores } from "./store/engine.mjs";
|
|
3
|
+
import { createInMemoryDriver } from "./store/memory.mjs";
|
|
4
|
+
export { type CacheContinuationContextInput, type CollectionName, type CreateStoresOptions, type FactoryStores, type InsertStoreRecordInput, RecordExistsError, RecordNotFoundError, type StoreDriver, type StoredEntry, type StoredRecord, TransientStoreError, type UpdateStoreRecordInput, VersionConflictError, createInMemoryDriver, createStores };
|
package/dist/storage.mjs
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { RecordExistsError, RecordNotFoundError, TransientStoreError, VersionConflictError } from "./store/driver.mjs";
|
|
2
|
+
import { createStores } from "./store/engine.mjs";
|
|
3
|
+
import { createInMemoryDriver } from "./store/memory.mjs";
|
|
4
|
+
export { RecordExistsError, RecordNotFoundError, TransientStoreError, VersionConflictError, createInMemoryDriver, createStores };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
//#region src/store/driver.d.ts
|
|
2
|
+
/** Closed set of persistence collections understood by Factory store drivers. */
|
|
3
|
+
type CollectionName = "repositories" | "signals" | "tasks" | "changes" | "receipts" | "budgets" | "answers" | "sessions" | "externalSessions" | "transcripts" | "images" | "questionRoutes" | "taskCatalogs" | "changeCatalogs" | "sessionCatalogs" | "externalSessionCatalogs" | "taskRoutes" | "outboxQueues" | "outboxDeliveries" | "communicationSettings" | "taskGraphs" | "taskMessages" | "taskEffects" | "taskInboxes" | "taskMessageProcessing" | "taskMessageDecisions" | "taskMessageDiscards" | "plannerActivations" | "plannerCancellations";
|
|
4
|
+
/** Opaque persisted value paired with its compare-and-swap version. */
|
|
5
|
+
interface StoredRecord {
|
|
6
|
+
readonly value: unknown;
|
|
7
|
+
readonly version: number;
|
|
8
|
+
}
|
|
9
|
+
/** Collection-listing entry containing its storage key and versioned record. */
|
|
10
|
+
interface StoredEntry {
|
|
11
|
+
readonly id: string;
|
|
12
|
+
readonly record: StoredRecord;
|
|
13
|
+
}
|
|
14
|
+
/** Collection, storage key, and opaque value for one insert-only write. */
|
|
15
|
+
interface InsertStoreRecordInput {
|
|
16
|
+
readonly collection: CollectionName;
|
|
17
|
+
readonly id: string;
|
|
18
|
+
readonly value: unknown;
|
|
19
|
+
}
|
|
20
|
+
/** Collection, storage key, opaque value, and compare-and-swap version for one update. */
|
|
21
|
+
interface UpdateStoreRecordInput extends InsertStoreRecordInput {
|
|
22
|
+
readonly expectedVersion: number;
|
|
23
|
+
}
|
|
24
|
+
/** Error raised when an insert targets an already occupied storage key. */
|
|
25
|
+
declare class RecordExistsError extends Error {
|
|
26
|
+
constructor(collection: CollectionName, id: string);
|
|
27
|
+
}
|
|
28
|
+
/** Error raised when an operation requires a storage record that does not exist. */
|
|
29
|
+
declare class RecordNotFoundError extends Error {
|
|
30
|
+
constructor(collection: CollectionName, id: string);
|
|
31
|
+
}
|
|
32
|
+
/** Error raised when atomic update loses its expected-version comparison. */
|
|
33
|
+
declare class VersionConflictError extends Error {
|
|
34
|
+
constructor(collection: CollectionName, id: string, expectedVersion: number);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A transient infrastructure failure (network error, 5xx/429 response) that
|
|
38
|
+
* a driver's own bounded, backed-off low-level retries could not resolve.
|
|
39
|
+
* Distinct from VersionConflictError (a concurrent writer legitimately won)
|
|
40
|
+
* and from validation or "already exists" errors (the request itself is
|
|
41
|
+
* rejected): the same operation may still succeed if retried again later,
|
|
42
|
+
* but every caller retrying on this error must keep its own bound so a real
|
|
43
|
+
* outage surfaces as a failure instead of hanging a dispatch cycle.
|
|
44
|
+
*/
|
|
45
|
+
declare class TransientStoreError extends Error {
|
|
46
|
+
constructor(collection: CollectionName, id: string, cause: unknown);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Raw persistence contract. Drivers store opaque values and enforce nothing
|
|
50
|
+
* about their content; every invariant lives in the engine above. `update`
|
|
51
|
+
* must be an atomic compare-and-swap on `expectedVersion`. A driver may
|
|
52
|
+
* throw TransientStoreError for a read or write that failed only because of
|
|
53
|
+
* infrastructure trouble (network errors, 5xx/429 responses); it must not
|
|
54
|
+
* use TransientStoreError for version conflicts or malformed input.
|
|
55
|
+
*/
|
|
56
|
+
interface StoreDriver {
|
|
57
|
+
readonly name: string;
|
|
58
|
+
get(collection: CollectionName, id: string): Promise<StoredRecord | null>;
|
|
59
|
+
insert(input: InsertStoreRecordInput): Promise<void>;
|
|
60
|
+
update(input: UpdateStoreRecordInput): Promise<void>;
|
|
61
|
+
list(collection: CollectionName): Promise<readonly StoredEntry[]>;
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
export { CollectionName, InsertStoreRecordInput, RecordExistsError, RecordNotFoundError, StoreDriver, StoredEntry, StoredRecord, TransientStoreError, UpdateStoreRecordInput, VersionConflictError };
|
|
65
|
+
//# sourceMappingURL=driver.d.mts.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
//#region src/store/driver.ts
|
|
2
|
+
/** Error raised when an insert targets an already occupied storage key. */
|
|
3
|
+
var RecordExistsError = class extends Error {
|
|
4
|
+
constructor(collection, id) {
|
|
5
|
+
super(`record "${id}" already exists in "${collection}"`);
|
|
6
|
+
this.name = "RecordExistsError";
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
/** Error raised when an operation requires a storage record that does not exist. */
|
|
10
|
+
var RecordNotFoundError = class extends Error {
|
|
11
|
+
constructor(collection, id) {
|
|
12
|
+
super(`record "${id}" not found in "${collection}"`);
|
|
13
|
+
this.name = "RecordNotFoundError";
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
/** Error raised when atomic update loses its expected-version comparison. */
|
|
17
|
+
var VersionConflictError = class extends Error {
|
|
18
|
+
constructor(collection, id, expectedVersion) {
|
|
19
|
+
super(`record "${id}" in "${collection}" changed since version ${expectedVersion} was read`);
|
|
20
|
+
this.name = "VersionConflictError";
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* A transient infrastructure failure (network error, 5xx/429 response) that
|
|
25
|
+
* a driver's own bounded, backed-off low-level retries could not resolve.
|
|
26
|
+
* Distinct from VersionConflictError (a concurrent writer legitimately won)
|
|
27
|
+
* and from validation or "already exists" errors (the request itself is
|
|
28
|
+
* rejected): the same operation may still succeed if retried again later,
|
|
29
|
+
* but every caller retrying on this error must keep its own bound so a real
|
|
30
|
+
* outage surfaces as a failure instead of hanging a dispatch cycle.
|
|
31
|
+
*/
|
|
32
|
+
var TransientStoreError = class extends Error {
|
|
33
|
+
constructor(collection, id, cause) {
|
|
34
|
+
const reason = cause instanceof Error ? cause.message : String(cause);
|
|
35
|
+
super(`record "${id}" in "${collection}" failed after transient retries were exhausted: ${reason}`, { cause: cause instanceof Error ? cause : void 0 });
|
|
36
|
+
this.name = "TransientStoreError";
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
//#endregion
|
|
40
|
+
export { RecordExistsError, RecordNotFoundError, TransientStoreError, VersionConflictError };
|
|
41
|
+
|
|
42
|
+
//# sourceMappingURL=driver.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.mjs","names":[],"sources":["../../src/store/driver.ts"],"sourcesContent":["/** Closed set of persistence collections understood by Factory store drivers. */\nexport type CollectionName =\n | \"repositories\"\n | \"signals\"\n | \"tasks\"\n | \"changes\"\n | \"receipts\"\n | \"budgets\"\n | \"answers\"\n | \"sessions\"\n | \"externalSessions\"\n | \"transcripts\"\n | \"images\"\n | \"questionRoutes\"\n | \"taskCatalogs\"\n | \"changeCatalogs\"\n | \"sessionCatalogs\"\n | \"externalSessionCatalogs\"\n | \"taskRoutes\"\n | \"outboxQueues\"\n | \"outboxDeliveries\"\n | \"communicationSettings\"\n | \"taskGraphs\"\n | \"taskMessages\"\n | \"taskEffects\"\n | \"taskInboxes\"\n | \"taskMessageProcessing\"\n | \"taskMessageDecisions\"\n | \"taskMessageDiscards\"\n | \"plannerActivations\"\n | \"plannerCancellations\";\n\n/** Opaque persisted value paired with its compare-and-swap version. */\nexport interface StoredRecord {\n readonly value: unknown;\n readonly version: number;\n}\n\n/** Collection-listing entry containing its storage key and versioned record. */\nexport interface StoredEntry {\n readonly id: string;\n readonly record: StoredRecord;\n}\n\n/** Collection, storage key, and opaque value for one insert-only write. */\nexport interface InsertStoreRecordInput {\n readonly collection: CollectionName;\n readonly id: string;\n readonly value: unknown;\n}\n\n/** Collection, storage key, opaque value, and compare-and-swap version for one update. */\nexport interface UpdateStoreRecordInput extends InsertStoreRecordInput {\n readonly expectedVersion: number;\n}\n\n/** Error raised when an insert targets an already occupied storage key. */\nexport class RecordExistsError extends Error {\n constructor(collection: CollectionName, id: string) {\n super(`record \"${id}\" already exists in \"${collection}\"`);\n this.name = \"RecordExistsError\";\n }\n}\n\n/** Error raised when an operation requires a storage record that does not exist. */\nexport class RecordNotFoundError extends Error {\n constructor(collection: CollectionName, id: string) {\n super(`record \"${id}\" not found in \"${collection}\"`);\n this.name = \"RecordNotFoundError\";\n }\n}\n\n/** Error raised when atomic update loses its expected-version comparison. */\nexport class VersionConflictError extends Error {\n constructor(collection: CollectionName, id: string, expectedVersion: number) {\n super(`record \"${id}\" in \"${collection}\" changed since version ${expectedVersion} was read`);\n this.name = \"VersionConflictError\";\n }\n}\n\n/**\n * A transient infrastructure failure (network error, 5xx/429 response) that\n * a driver's own bounded, backed-off low-level retries could not resolve.\n * Distinct from VersionConflictError (a concurrent writer legitimately won)\n * and from validation or \"already exists\" errors (the request itself is\n * rejected): the same operation may still succeed if retried again later,\n * but every caller retrying on this error must keep its own bound so a real\n * outage surfaces as a failure instead of hanging a dispatch cycle.\n */\nexport class TransientStoreError extends Error {\n constructor(collection: CollectionName, id: string, cause: unknown) {\n const reason = cause instanceof Error ? cause.message : String(cause);\n super(\n `record \"${id}\" in \"${collection}\" failed after transient retries were exhausted: ${reason}`,\n { cause: cause instanceof Error ? cause : undefined },\n );\n this.name = \"TransientStoreError\";\n }\n}\n\n/**\n * Raw persistence contract. Drivers store opaque values and enforce nothing\n * about their content; every invariant lives in the engine above. `update`\n * must be an atomic compare-and-swap on `expectedVersion`. A driver may\n * throw TransientStoreError for a read or write that failed only because of\n * infrastructure trouble (network errors, 5xx/429 responses); it must not\n * use TransientStoreError for version conflicts or malformed input.\n */\nexport interface StoreDriver {\n readonly name: string;\n get(collection: CollectionName, id: string): Promise<StoredRecord | null>;\n insert(input: InsertStoreRecordInput): Promise<void>;\n update(input: UpdateStoreRecordInput): Promise<void>;\n list(collection: CollectionName): Promise<readonly StoredEntry[]>;\n}\n"],"mappings":";;AAyDA,IAAa,oBAAb,cAAuC,MAAM;CAC3C,YAAY,YAA4B,IAAY;EAClD,MAAM,WAAW,GAAG,uBAAuB,WAAW,EAAE;EACxD,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,sBAAb,cAAyC,MAAM;CAC7C,YAAY,YAA4B,IAAY;EAClD,MAAM,WAAW,GAAG,kBAAkB,WAAW,EAAE;EACnD,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,uBAAb,cAA0C,MAAM;CAC9C,YAAY,YAA4B,IAAY,iBAAyB;EAC3E,MAAM,WAAW,GAAG,QAAQ,WAAW,0BAA0B,gBAAgB,UAAU;EAC3F,KAAK,OAAO;CACd;AACF;;;;;;;;;;AAWA,IAAa,sBAAb,cAAyC,MAAM;CAC7C,YAAY,YAA4B,IAAY,OAAgB;EAClE,MAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACpE,MACE,WAAW,GAAG,QAAQ,WAAW,mDAAmD,UACpF,EAAE,OAAO,iBAAiB,QAAQ,QAAQ,KAAA,EAAU,CACtD;EACA,KAAK,OAAO;CACd;AACF"}
|