@vercel/factory 0.0.13 → 0.0.15
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/README.md +307 -1
- package/dist/agent-routes.d.mts +69 -0
- package/dist/agent-routes.mjs +64 -0
- package/dist/agent-routes.mjs.map +1 -0
- package/dist/api-contracts.d.mts +1749 -0
- package/dist/api-contracts.mjs +118 -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 +77 -0
- package/dist/api.mjs +1087 -0
- package/dist/api.mjs.map +1 -0
- 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 +692 -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 +44 -8
- package/dist/blob/index.mjs +159 -35
- package/dist/blob/index.mjs.map +1 -1
- package/dist/budget.d.mts +108 -0
- package/dist/budget.mjs +141 -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 +6 -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 +24 -0
- package/dist/change-verification/dispatch.mjs +45 -0
- package/dist/change-verification/dispatch.mjs.map +1 -0
- package/dist/change-verification/eve-tool.d.mts +60 -0
- package/dist/change-verification/eve-tool.mjs +101 -0
- package/dist/change-verification/eve-tool.mjs.map +1 -0
- package/dist/changes/eve-record-change.d.mts +56 -0
- package/dist/changes/eve-record-change.mjs +97 -0
- package/dist/changes/eve-record-change.mjs.map +1 -0
- package/dist/changes/presentation.d.mts +14 -0
- package/dist/changes.d.mts +23 -0
- package/dist/changes.mjs +29 -0
- package/dist/changes.mjs.map +1 -0
- package/dist/client-events.d.mts +18 -0
- package/dist/client-events.mjs +41 -0
- package/dist/client-events.mjs.map +1 -0
- package/dist/client-stream.d.mts +28 -0
- package/dist/client-stream.mjs +204 -0
- package/dist/client-stream.mjs.map +1 -0
- package/dist/client-transcript.d.mts +41 -0
- package/dist/client-transcript.mjs +229 -0
- package/dist/client-transcript.mjs.map +1 -0
- package/dist/client.d.mts +234 -0
- package/dist/client.mjs +258 -0
- package/dist/client.mjs.map +1 -0
- package/dist/code-review/contracts.d.mts +26 -0
- package/dist/code-review/eve-post-review.d.mts +70 -0
- package/dist/code-review/eve-post-review.mjs +183 -0
- package/dist/code-review/eve-post-review.mjs.map +1 -0
- package/dist/code-review/eve-review-comments.d.mts +64 -0
- package/dist/code-review/eve-review-comments.mjs +159 -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 +44 -0
- package/dist/code-review/github-reporter.mjs +260 -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 +6 -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 -2
- package/dist/connectors/index.mjs +4 -26
- 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 -41
- package/dist/connectors/slack.mjs +13 -69
- package/dist/connectors/slack.mjs.map +1 -1
- package/dist/deepsec/eve-tool.d.mts +110 -0
- package/dist/deepsec/eve-tool.mjs +164 -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 +81 -0
- package/dist/dispatch.mjs +140 -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 +143 -1561
- package/dist/eve/index.mjs +244 -1063
- package/dist/eve/index.mjs.map +1 -1
- package/dist/eve/invoke.d.mts +144 -0
- package/dist/eve/invoke.mjs +241 -0
- package/dist/eve/invoke.mjs.map +1 -0
- package/dist/eve/session-client.d.mts +68 -0
- package/dist/eve/session-client.mjs +131 -0
- package/dist/eve/session-client.mjs.map +1 -0
- package/dist/eve/task-execution.mjs +18 -0
- package/dist/eve/task-execution.mjs.map +1 -0
- package/dist/eve/task-session.d.mts +87 -0
- package/dist/eve/task-session.mjs +203 -0
- package/dist/eve/task-session.mjs.map +1 -0
- package/dist/eve/transcript.d.mts +37 -0
- package/dist/eve/transcript.mjs +65 -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 +75 -0
- package/dist/execution.mjs +153 -0
- package/dist/execution.mjs.map +1 -0
- package/dist/finding-remediation/admission.d.mts +51 -0
- package/dist/finding-remediation/admission.mjs +87 -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 +6 -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 +198 -0
- package/dist/github-publication.mjs +429 -0
- package/dist/github-publication.mjs.map +1 -0
- package/dist/github-transfer.d.mts +72 -0
- package/dist/github-transfer.mjs +125 -0
- package/dist/github-transfer.mjs.map +1 -0
- package/dist/github.d.mts +406 -2
- package/dist/github.mjs +250 -37
- 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/index.d.mts +14 -314
- package/dist/index.mjs +14 -1124
- package/dist/intake-contracts.d.mts +56 -0
- package/dist/intake-contracts.mjs +33 -0
- package/dist/intake-contracts.mjs.map +1 -0
- package/dist/integrations/deepsec.d.mts +4 -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 +3 -0
- package/dist/integrations/slack.mjs +3 -0
- package/dist/integrations/vercel.d.mts +3 -0
- package/dist/integrations/vercel.mjs +3 -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 +46 -0
- package/dist/merge-resolution/eve-tools.mjs +117 -0
- package/dist/merge-resolution/eve-tools.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 +273 -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 +7 -1
- package/dist/postgres/index.mjs +7 -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 +53 -0
- package/dist/presets/software-development/dispatch.mjs +66 -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 +23 -0
- package/dist/presets/software-development/task-communication.mjs +120 -0
- package/dist/presets/software-development/task-communication.mjs.map +1 -0
- package/dist/presets/software-development.d.mts +9 -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 +53 -0
- package/dist/pull-requests/github-publisher.mjs +345 -0
- package/dist/pull-requests/github-publisher.mjs.map +1 -0
- package/dist/pull-requests.d.mts +5 -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 +9 -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 +22 -0
- package/dist/schema/agent-route.mjs +15 -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-DwCihQr4.mjs → schema/common.mjs} +7 -14
- package/dist/schema/common.mjs.map +1 -0
- package/dist/schema/communication.d.mts +52 -0
- package/dist/schema/communication.mjs +35 -0
- 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 +95 -0
- package/dist/schema/factory-config.mjs +60 -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 +26 -0
- package/dist/schema/repository.mjs +25 -0
- package/dist/schema/repository.mjs.map +1 -0
- package/dist/schema/session.d.mts +135 -0
- package/dist/schema/session.mjs +53 -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/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 +3134 -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 +272 -0
- package/dist/schema/task.mjs +199 -0
- package/dist/schema/task.mjs.map +1 -0
- package/dist/schema/transcript.d.mts +170 -0
- package/dist/schema/transcript.mjs +86 -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 +101 -0
- package/dist/schema/work.mjs +102 -0
- package/dist/schema/work.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 +19 -0
- package/dist/signals.mjs +19 -0
- package/dist/signals.mjs.map +1 -0
- package/dist/stall.d.mts +38 -0
- package/dist/stall.mjs +79 -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 +485 -0
- package/dist/store/engine.mjs +2175 -0
- package/dist/store/engine.mjs.map +1 -0
- package/dist/store/memory.d.mts +7 -0
- package/dist/store/memory.mjs +52 -0
- package/dist/store/memory.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 +65 -0
- package/dist/store/task-work.mjs +134 -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 +57 -0
- package/dist/sweep.mjs +143 -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 +264 -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 +21 -0
- package/dist/vercel-git.mjs +112 -0
- package/dist/vercel-git.mjs.map +1 -0
- package/dist/vercel.d.mts +33 -2
- package/dist/vercel.mjs +48 -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 +3 -0
- package/dist/work-triage.mjs +3 -0
- package/dist/workflows.d.mts +48 -0
- package/dist/workflows.mjs +86 -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-snapshot.d.mts +26 -0
- package/dist/workspace-snapshot.mjs +80 -0
- package/dist/workspace-snapshot.mjs.map +1 -0
- package/package.json +129 -40
- package/dist/approval-CwhTP1XB.mjs +0 -269
- package/dist/approval-CwhTP1XB.mjs.map +0 -1
- package/dist/change-CzEAoFVE.mjs +0 -620
- package/dist/change-CzEAoFVE.mjs.map +0 -1
- package/dist/dispatch-B77cuPxh.d.mts +0 -713
- package/dist/driver-BJutB0PE.d.mts +0 -34
- package/dist/driver-Bbd25rNM.mjs +0 -23
- package/dist/driver-Bbd25rNM.mjs.map +0 -1
- package/dist/factory-config-BJcjsPKl.mjs +0 -86
- package/dist/factory-config-BJcjsPKl.mjs.map +0 -1
- package/dist/factory-config-D2yU3G0c.d.mts +0 -58
- package/dist/github-DXsxboUL.d.mts +0 -271
- package/dist/id-DwCihQr4.mjs.map +0 -1
- package/dist/index-Cy4jfXh5.d.mts +0 -67
- package/dist/index.mjs.map +0 -1
- package/dist/signal-CHVEmzvI.d.mts +0 -59
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { taskIdSchema } from "./schema/id.mjs";
|
|
2
|
+
import { repositorySlugSchema } from "./schema/repository.mjs";
|
|
3
|
+
import { taskSchema } from "./schema/task.mjs";
|
|
4
|
+
import { receiptSchema } from "./schema/receipt.mjs";
|
|
5
|
+
import { findingSchema } from "./schema/finding.mjs";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
//#region src/approval-contracts.ts
|
|
8
|
+
/** Validates the stable human reason attached to an approval decision. */
|
|
9
|
+
const approvalRequestSchema = z.strictObject({ reason: z.string().trim().min(1).max(2e3).optional().describe("Reason for the decision; required for rejection. Retain unchanged for retries.") });
|
|
10
|
+
/** Validates one authorized approval proposal and its immutable decision state. */
|
|
11
|
+
const approvalViewSchema = z.object({
|
|
12
|
+
task: taskSchema.describe("Task requiring or carrying a human decision."),
|
|
13
|
+
repositories: z.array(repositorySlugSchema).readonly().describe("Configured repository names for this Task."),
|
|
14
|
+
finding: findingSchema.nullable().describe("Finding that prompted the Task, when available."),
|
|
15
|
+
decision: receiptSchema.nullable().describe("Immutable decision receipt, or null before a decision.")
|
|
16
|
+
});
|
|
17
|
+
/** Validates a filtered, cursor-paginated page of approval proposals. */
|
|
18
|
+
const approvalPageSchema = z.object({
|
|
19
|
+
actor: z.string().describe("Authenticated actor used for decision attribution."),
|
|
20
|
+
items: z.array(approvalViewSchema).readonly().describe("Authorized approvals in the requested order."),
|
|
21
|
+
totalCount: z.number().int().nonnegative().optional().describe("Number of authorized approvals matching all filters, before pagination."),
|
|
22
|
+
nextCursor: taskIdSchema.nullable().describe("Continue this filtered listing after this Task ID.")
|
|
23
|
+
});
|
|
24
|
+
//#endregion
|
|
25
|
+
export { approvalPageSchema, approvalRequestSchema, approvalViewSchema };
|
|
26
|
+
|
|
27
|
+
//# sourceMappingURL=approval-contracts.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-contracts.mjs","names":[],"sources":["../src/approval-contracts.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { taskIdSchema, type TaskId } from \"./schema/id\";\nimport { taskSchema } from \"./schema/task\";\nimport { receiptSchema } from \"./schema/receipt\";\nimport { findingSchema } from \"./schema/finding\";\nimport { repositorySlugSchema, type RepositorySlug } from \"./schema/repository\";\n\n/** Workspace owner and optional individually authenticated actor at the approval boundary. */\nexport interface ApiPrincipal {\n /** Workspace identity used for existing conversation ownership. */\n readonly id: string;\n /** Individually authenticated, provider-qualified actor; absent for anonymous/workload access. */\n readonly actor?: string;\n}\n\n/** Validates the stable human reason attached to an approval decision. */\nexport const approvalRequestSchema = z.strictObject({\n reason: z\n .string()\n .trim()\n .min(1)\n .max(2000)\n .optional()\n .describe(\"Reason for the decision; required for rejection. Retain unchanged for retries.\"),\n});\n/** Validates one authorized approval proposal and its immutable decision state. */\nexport const approvalViewSchema = z.object({\n task: taskSchema.describe(\"Task requiring or carrying a human decision.\"),\n repositories: z\n .array(repositorySlugSchema)\n .readonly()\n .describe(\"Configured repository names for this Task.\"),\n finding: findingSchema.nullable().describe(\"Finding that prompted the Task, when available.\"),\n decision: receiptSchema\n .nullable()\n .describe(\"Immutable decision receipt, or null before a decision.\"),\n});\n/** Validates a filtered, cursor-paginated page of approval proposals. */\nexport const approvalPageSchema = z.object({\n actor: z.string().describe(\"Authenticated actor used for decision attribution.\"),\n items: z\n .array(approvalViewSchema)\n .readonly()\n .describe(\"Authorized approvals in the requested order.\"),\n totalCount: z\n .number()\n .int()\n .nonnegative()\n .optional()\n .describe(\"Number of authorized approvals matching all filters, before pagination.\"),\n nextCursor: taskIdSchema\n .nullable()\n .describe(\"Continue this filtered listing after this Task ID.\"),\n});\n/** Authorized Task proposal with repository, finding, and decision context. */\nexport type ApprovalView = z.infer<typeof approvalViewSchema>;\n/** Filtered, cursor-paginated approval proposals for one authorized actor. */\nexport type ApprovalPage = z.infer<typeof approvalPageSchema>;\n/** Filters, ordering, and cursor controls for approval discovery. */\nexport interface ApprovalListOptions {\n readonly repository?: RepositorySlug;\n readonly status?: \"pending\" | \"decided\" | \"all\";\n readonly query?: string;\n readonly sort?: \"created\" | \"priority\" | \"decided\";\n readonly limit?: number;\n readonly cursor?: TaskId;\n}\n"],"mappings":";;;;;;;;AAgBA,MAAa,wBAAwB,EAAE,aAAa,EAClD,QAAQ,EACL,OAAO,CAAC,CACR,KAAK,CAAC,CACN,IAAI,CAAC,CAAC,CACN,IAAI,GAAI,CAAC,CACT,SAAS,CAAC,CACV,SAAS,gFAAgF,EAC9F,CAAC;;AAED,MAAa,qBAAqB,EAAE,OAAO;CACzC,MAAM,WAAW,SAAS,8CAA8C;CACxE,cAAc,EACX,MAAM,oBAAoB,CAAC,CAC3B,SAAS,CAAC,CACV,SAAS,4CAA4C;CACxD,SAAS,cAAc,SAAS,CAAC,CAAC,SAAS,iDAAiD;CAC5F,UAAU,cACP,SAAS,CAAC,CACV,SAAS,wDAAwD;AACtE,CAAC;;AAED,MAAa,qBAAqB,EAAE,OAAO;CACzC,OAAO,EAAE,OAAO,CAAC,CAAC,SAAS,oDAAoD;CAC/E,OAAO,EACJ,MAAM,kBAAkB,CAAC,CACzB,SAAS,CAAC,CACV,SAAS,8CAA8C;CAC1D,YAAY,EACT,OAAO,CAAC,CACR,IAAI,CAAC,CACL,YAAY,CAAC,CACb,SAAS,CAAC,CACV,SAAS,yEAAyE;CACrF,YAAY,aACT,SAAS,CAAC,CACV,SAAS,oDAAoD;AAClE,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
//#region src/approval.d.ts
|
|
3
|
+
/** Validates an open priority label used to match admission policy subjects. */
|
|
4
|
+
declare const approvalPrioritySchema: z.ZodString;
|
|
5
|
+
/**
|
|
6
|
+
* One approval rule. Every listed field must match for the rule to apply;
|
|
7
|
+
* absent fields match anything. Rules are evaluated first-match.
|
|
8
|
+
*/
|
|
9
|
+
declare const approvalRuleSchema: z.ZodReadonly<z.ZodObject<{
|
|
10
|
+
source: z.ZodOptional<z.ZodString>;
|
|
11
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
12
|
+
priority: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
13
|
+
require: z.ZodBoolean;
|
|
14
|
+
}, z.core.$strict>>;
|
|
15
|
+
/** Validates an ordered, first-match set of Task approval rules. */
|
|
16
|
+
declare const approvalPolicySchema: z.ZodReadonly<z.ZodArray<z.ZodReadonly<z.ZodObject<{
|
|
17
|
+
source: z.ZodOptional<z.ZodString>;
|
|
18
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
19
|
+
priority: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
20
|
+
require: z.ZodBoolean;
|
|
21
|
+
}, z.core.$strict>>>>;
|
|
22
|
+
/** One first-match condition that decides whether admitted work requires approval. */
|
|
23
|
+
type ApprovalRule = z.infer<typeof approvalRuleSchema>;
|
|
24
|
+
/** Ordered admission policy that stamps a Task's approval requirement once. */
|
|
25
|
+
type ApprovalPolicy = z.infer<typeof approvalPolicySchema>;
|
|
26
|
+
/** Open priority label compared exactly by approval policy. */
|
|
27
|
+
type ApprovalPriority = z.infer<typeof approvalPrioritySchema>;
|
|
28
|
+
/** Neutral framework default when an application does not select an approval policy. */
|
|
29
|
+
declare const allowByDefaultApprovalPolicy: readonly Readonly<{
|
|
30
|
+
require: boolean;
|
|
31
|
+
source?: string | undefined;
|
|
32
|
+
kind?: string | undefined;
|
|
33
|
+
priority?: readonly string[] | undefined;
|
|
34
|
+
}>[];
|
|
35
|
+
/** Immutable intake attributes evaluated against an approval policy. */
|
|
36
|
+
interface ApprovalSubject {
|
|
37
|
+
source?: string;
|
|
38
|
+
kind: string;
|
|
39
|
+
priority?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Decide at task-creation time whether a task needs approval. Pure: the answer
|
|
43
|
+
* is stamped on the task and never re-evaluated, so a later policy change
|
|
44
|
+
* cannot silently release work a human was expecting to see.
|
|
45
|
+
*/
|
|
46
|
+
declare function requiresApproval(policy: ApprovalPolicy, subject: ApprovalSubject): boolean;
|
|
47
|
+
//#endregion
|
|
48
|
+
export { ApprovalPolicy, ApprovalPriority, ApprovalRule, ApprovalSubject, allowByDefaultApprovalPolicy, approvalPolicySchema, approvalPrioritySchema, approvalRuleSchema, requiresApproval };
|
|
49
|
+
//# sourceMappingURL=approval.d.mts.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { vocabularySchema } from "./schema/common.mjs";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
//#region src/approval.ts
|
|
4
|
+
/** Validates an open priority label used to match admission policy subjects. */
|
|
5
|
+
const approvalPrioritySchema = z.string().min(1).max(64).describe("Priority label compared exactly, e.g. P0, P1, urgent, or a custom domain value.");
|
|
6
|
+
/**
|
|
7
|
+
* One approval rule. Every listed field must match for the rule to apply;
|
|
8
|
+
* absent fields match anything. Rules are evaluated first-match.
|
|
9
|
+
*/
|
|
10
|
+
const approvalRuleSchema = z.strictObject({
|
|
11
|
+
source: vocabularySchema.optional().describe("Signal source, e.g. security_scan or github_issue."),
|
|
12
|
+
kind: vocabularySchema.optional().describe("Task kind, e.g. code_change."),
|
|
13
|
+
priority: z.array(approvalPrioritySchema).min(1).readonly().optional().describe("Finding priorities the rule applies to."),
|
|
14
|
+
require: z.boolean().describe("Whether matching tasks wait for a human before dispatch.")
|
|
15
|
+
}).readonly();
|
|
16
|
+
/** Validates an ordered, first-match set of Task approval rules. */
|
|
17
|
+
const approvalPolicySchema = z.array(approvalRuleSchema).readonly().describe("First-match rules deciding which tasks need a human before they run.");
|
|
18
|
+
/** Neutral framework default when an application does not select an approval policy. */
|
|
19
|
+
const allowByDefaultApprovalPolicy = approvalPolicySchema.parse([{ require: false }]);
|
|
20
|
+
/**
|
|
21
|
+
* Decide at task-creation time whether a task needs approval. Pure: the answer
|
|
22
|
+
* is stamped on the task and never re-evaluated, so a later policy change
|
|
23
|
+
* cannot silently release work a human was expecting to see.
|
|
24
|
+
*/
|
|
25
|
+
function requiresApproval(policy, subject) {
|
|
26
|
+
for (const rule of policy) {
|
|
27
|
+
if (rule.source !== void 0 && rule.source !== subject.source) continue;
|
|
28
|
+
if (rule.kind !== void 0 && rule.kind !== subject.kind) continue;
|
|
29
|
+
if (rule.priority !== void 0) {
|
|
30
|
+
if (subject.priority === void 0 || !rule.priority.includes(subject.priority)) continue;
|
|
31
|
+
}
|
|
32
|
+
return rule.require;
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { allowByDefaultApprovalPolicy, approvalPolicySchema, approvalPrioritySchema, approvalRuleSchema, requiresApproval };
|
|
38
|
+
|
|
39
|
+
//# sourceMappingURL=approval.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval.mjs","names":[],"sources":["../src/approval.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { vocabularySchema } from \"./schema/common\";\n\n/** Validates an open priority label used to match admission policy subjects. */\nexport const approvalPrioritySchema = z\n .string()\n .min(1)\n .max(64)\n .describe(\"Priority label compared exactly, e.g. P0, P1, urgent, or a custom domain value.\");\n\n/**\n * One approval rule. Every listed field must match for the rule to apply;\n * absent fields match anything. Rules are evaluated first-match.\n */\nexport const approvalRuleSchema = z\n .strictObject({\n source: vocabularySchema\n .optional()\n .describe(\"Signal source, e.g. security_scan or github_issue.\"),\n kind: vocabularySchema.optional().describe(\"Task kind, e.g. code_change.\"),\n priority: z\n .array(approvalPrioritySchema)\n .min(1)\n .readonly()\n .optional()\n .describe(\"Finding priorities the rule applies to.\"),\n require: z.boolean().describe(\"Whether matching tasks wait for a human before dispatch.\"),\n })\n .readonly();\n\n/** Validates an ordered, first-match set of Task approval rules. */\nexport const approvalPolicySchema = z\n .array(approvalRuleSchema)\n .readonly()\n .describe(\"First-match rules deciding which tasks need a human before they run.\");\n\n/** One first-match condition that decides whether admitted work requires approval. */\nexport type ApprovalRule = z.infer<typeof approvalRuleSchema>;\n/** Ordered admission policy that stamps a Task's approval requirement once. */\nexport type ApprovalPolicy = z.infer<typeof approvalPolicySchema>;\n/** Open priority label compared exactly by approval policy. */\nexport type ApprovalPriority = z.infer<typeof approvalPrioritySchema>;\n\n/** Neutral framework default when an application does not select an approval policy. */\nexport const allowByDefaultApprovalPolicy = approvalPolicySchema.parse([{ require: false }]);\n\n/** Immutable intake attributes evaluated against an approval policy. */\nexport interface ApprovalSubject {\n source?: string;\n kind: string;\n priority?: string;\n}\n\n/**\n * Decide at task-creation time whether a task needs approval. Pure: the answer\n * is stamped on the task and never re-evaluated, so a later policy change\n * cannot silently release work a human was expecting to see.\n */\nexport function requiresApproval(policy: ApprovalPolicy, subject: ApprovalSubject): boolean {\n for (const rule of policy) {\n if (rule.source !== undefined && rule.source !== subject.source) continue;\n if (rule.kind !== undefined && rule.kind !== subject.kind) continue;\n if (rule.priority !== undefined) {\n if (subject.priority === undefined || !rule.priority.includes(subject.priority)) continue;\n }\n return rule.require;\n }\n return false;\n}\n"],"mappings":";;;;AAIA,MAAa,yBAAyB,EACnC,OAAO,CAAC,CACR,IAAI,CAAC,CAAC,CACN,IAAI,EAAE,CAAC,CACP,SAAS,iFAAiF;;;;;AAM7F,MAAa,qBAAqB,EAC/B,aAAa;CACZ,QAAQ,iBACL,SAAS,CAAC,CACV,SAAS,oDAAoD;CAChE,MAAM,iBAAiB,SAAS,CAAC,CAAC,SAAS,8BAA8B;CACzE,UAAU,EACP,MAAM,sBAAsB,CAAC,CAC7B,IAAI,CAAC,CAAC,CACN,SAAS,CAAC,CACV,SAAS,CAAC,CACV,SAAS,yCAAyC;CACrD,SAAS,EAAE,QAAQ,CAAC,CAAC,SAAS,0DAA0D;AAC1F,CAAC,CAAC,CACD,SAAS;;AAGZ,MAAa,uBAAuB,EACjC,MAAM,kBAAkB,CAAC,CACzB,SAAS,CAAC,CACV,SAAS,sEAAsE;;AAUlF,MAAa,+BAA+B,qBAAqB,MAAM,CAAC,EAAE,SAAS,MAAM,CAAC,CAAC;;;;;;AAc3F,SAAgB,iBAAiB,QAAwB,SAAmC;CAC1F,KAAK,MAAM,QAAQ,QAAQ;EACzB,IAAI,KAAK,WAAW,KAAA,KAAa,KAAK,WAAW,QAAQ,QAAQ;EACjE,IAAI,KAAK,SAAS,KAAA,KAAa,KAAK,SAAS,QAAQ,MAAM;EAC3D,IAAI,KAAK,aAAa,KAAA,GAChB;OAAA,QAAQ,aAAa,KAAA,KAAa,CAAC,KAAK,SAAS,SAAS,QAAQ,QAAQ,GAAG;EAAA;EAEnF,OAAO,KAAK;CACd;CACA,OAAO;AACT"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { TaskId } from "../schema/id.mjs";
|
|
2
|
+
import { TaskAttemptRef } from "../schema/execution.mjs";
|
|
3
|
+
import { BlobClient } from "./index.mjs";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
//#region src/blob/artifacts.d.ts
|
|
6
|
+
declare const artifactRefSchema: z.core.$ZodBranded<z.ZodString, "ArtifactRef", "out">;
|
|
7
|
+
/** A content-addressed reference that binds an artifact to its owning Task attempt and kind. */
|
|
8
|
+
type ArtifactRef = z.infer<typeof artifactRefSchema>;
|
|
9
|
+
/** Valid syntax grants neither read authority nor proof that an artifact exists. */
|
|
10
|
+
declare function parseArtifactRef(value: unknown): ArtifactRef;
|
|
11
|
+
/** Artifact kinds accepted by the Task-bound content-addressed store. */
|
|
12
|
+
type ArtifactKind = "patch" | "report" | "log";
|
|
13
|
+
/** Task attempt, kind, and encoded body used to derive or persist an artifact. */
|
|
14
|
+
interface ArtifactInput extends TaskAttemptRef {
|
|
15
|
+
kind: ArtifactKind;
|
|
16
|
+
/** Binary artifacts use base64. */
|
|
17
|
+
body: string;
|
|
18
|
+
}
|
|
19
|
+
/** Artifact reference and authorized owning Task used for one verified read. */
|
|
20
|
+
interface ReadArtifactInput {
|
|
21
|
+
ref: ArtifactRef;
|
|
22
|
+
taskId: TaskId;
|
|
23
|
+
}
|
|
24
|
+
/** Persists and retrieves content-addressed artifacts within a Task authorization boundary. */
|
|
25
|
+
interface ArtifactStore {
|
|
26
|
+
/** Content-addressed and therefore idempotent; returns the durable reference. */
|
|
27
|
+
put(artifact: ArtifactInput): Promise<ArtifactRef>;
|
|
28
|
+
/** Reads require the owning Task and re-verify the content digest. */
|
|
29
|
+
read(input: ReadArtifactInput): Promise<string>;
|
|
30
|
+
}
|
|
31
|
+
/** Derive a validated, content-addressed reference for an artifact without writing it. */
|
|
32
|
+
declare function artifactReference(artifact: ArtifactInput): ArtifactRef;
|
|
33
|
+
/** Create a Task-bound artifact store that verifies ownership and content digests on reads. */
|
|
34
|
+
declare function createArtifactStore(client: BlobClient): ArtifactStore;
|
|
35
|
+
//#endregion
|
|
36
|
+
export { ArtifactInput, ArtifactKind, ArtifactRef, ArtifactStore, ReadArtifactInput, artifactReference, createArtifactStore, parseArtifactRef };
|
|
37
|
+
//# sourceMappingURL=artifacts.d.mts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
//#region src/blob/artifacts.ts
|
|
4
|
+
const artifactRefPattern = /^factory-artifacts\/(task_[a-z0-9]{6,64})\/([1-9]\d{0,8})\/(patch|report|log)\/([0-9a-f]{64})$/u;
|
|
5
|
+
const artifactRefSchema = z.string().regex(artifactRefPattern, "Unrecognized artifact reference").brand();
|
|
6
|
+
/** Valid syntax grants neither read authority nor proof that an artifact exists. */
|
|
7
|
+
function parseArtifactRef(value) {
|
|
8
|
+
return artifactRefSchema.parse(value);
|
|
9
|
+
}
|
|
10
|
+
const sha256 = (body) => createHash("sha256").update(body).digest("hex");
|
|
11
|
+
/** Derive a validated, content-addressed reference for an artifact without writing it. */
|
|
12
|
+
function artifactReference(artifact) {
|
|
13
|
+
const ref = `factory-artifacts/${artifact.taskId}/${artifact.attempt}/${artifact.kind}/${sha256(artifact.body)}`;
|
|
14
|
+
if (!artifactRefPattern.test(ref)) throw new Error("Artifact reference requires a valid Task ID, attempt, and kind");
|
|
15
|
+
return parseArtifactRef(ref);
|
|
16
|
+
}
|
|
17
|
+
/** Create a Task-bound artifact store that verifies ownership and content digests on reads. */
|
|
18
|
+
function createArtifactStore(client) {
|
|
19
|
+
return {
|
|
20
|
+
async put(artifact) {
|
|
21
|
+
const ref = artifactReference(artifact);
|
|
22
|
+
await client.write({
|
|
23
|
+
pathname: ref,
|
|
24
|
+
body: artifact.body,
|
|
25
|
+
overwrite: true
|
|
26
|
+
});
|
|
27
|
+
return ref;
|
|
28
|
+
},
|
|
29
|
+
async read({ ref, taskId: authorizedTaskId }) {
|
|
30
|
+
const parsed = parseArtifactRef(ref);
|
|
31
|
+
const match = artifactRefPattern.exec(parsed);
|
|
32
|
+
if (!match) throw new Error("Unrecognized artifact reference");
|
|
33
|
+
const [, taskId, , , digest] = match;
|
|
34
|
+
if (taskId !== authorizedTaskId) throw new Error(`Artifact belongs to ${taskId}, not to the authorized Task ${authorizedTaskId}`);
|
|
35
|
+
const stored = await client.read({ pathname: parsed });
|
|
36
|
+
if (!stored) throw new Error(`Artifact ${ref} is unavailable`);
|
|
37
|
+
if (sha256(stored.body) !== digest) throw new Error(`Artifact ${ref} content does not match its digest`);
|
|
38
|
+
return stored.body;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { artifactReference, createArtifactStore, parseArtifactRef };
|
|
44
|
+
|
|
45
|
+
//# sourceMappingURL=artifacts.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifacts.mjs","names":[],"sources":["../../src/blob/artifacts.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { BlobClient } from \"./index\";\nimport type { TaskAttemptRef } from \"../schema/execution\";\nimport type { TaskId } from \"../schema/id\";\nimport { z } from \"zod\";\n\nconst artifactRefPattern =\n /^factory-artifacts\\/(task_[a-z0-9]{6,64})\\/([1-9]\\d{0,8})\\/(patch|report|log)\\/([0-9a-f]{64})$/u;\nconst artifactRefSchema = z\n .string()\n .regex(artifactRefPattern, \"Unrecognized artifact reference\")\n .brand<\"ArtifactRef\">();\n\n/** A content-addressed reference that binds an artifact to its owning Task attempt and kind. */\nexport type ArtifactRef = z.infer<typeof artifactRefSchema>;\n\n/** Valid syntax grants neither read authority nor proof that an artifact exists. */\nexport function parseArtifactRef(value: unknown): ArtifactRef {\n return artifactRefSchema.parse(value);\n}\n\n/** Artifact kinds accepted by the Task-bound content-addressed store. */\nexport type ArtifactKind = \"patch\" | \"report\" | \"log\";\n\n/** Task attempt, kind, and encoded body used to derive or persist an artifact. */\nexport interface ArtifactInput extends TaskAttemptRef {\n kind: ArtifactKind;\n /** Binary artifacts use base64. */\n body: string;\n}\n\n/** Artifact reference and authorized owning Task used for one verified read. */\nexport interface ReadArtifactInput {\n ref: ArtifactRef;\n taskId: TaskId;\n}\n\n/** Persists and retrieves content-addressed artifacts within a Task authorization boundary. */\nexport interface ArtifactStore {\n /** Content-addressed and therefore idempotent; returns the durable reference. */\n put(artifact: ArtifactInput): Promise<ArtifactRef>;\n /** Reads require the owning Task and re-verify the content digest. */\n read(input: ReadArtifactInput): Promise<string>;\n}\n\nconst sha256 = (body: string) => createHash(\"sha256\").update(body).digest(\"hex\");\n\n/** Derive a validated, content-addressed reference for an artifact without writing it. */\nexport function artifactReference(artifact: ArtifactInput): ArtifactRef {\n const ref = `factory-artifacts/${artifact.taskId}/${artifact.attempt}/${artifact.kind}/${sha256(artifact.body)}`;\n if (!artifactRefPattern.test(ref)) {\n throw new Error(\"Artifact reference requires a valid Task ID, attempt, and kind\");\n }\n return parseArtifactRef(ref);\n}\n\n/** Create a Task-bound artifact store that verifies ownership and content digests on reads. */\nexport function createArtifactStore(client: BlobClient): ArtifactStore {\n return {\n async put(artifact) {\n const ref = artifactReference(artifact);\n // Same path implies same content, so overwriting is safe and retryable.\n await client.write({ pathname: ref, body: artifact.body, overwrite: true });\n return ref;\n },\n async read({ ref, taskId: authorizedTaskId }) {\n const parsed = parseArtifactRef(ref);\n const match = artifactRefPattern.exec(parsed);\n if (!match) throw new Error(\"Unrecognized artifact reference\");\n const [, taskId, , , digest] = match;\n if (taskId !== authorizedTaskId) {\n throw new Error(\n `Artifact belongs to ${taskId}, not to the authorized Task ${authorizedTaskId}`,\n );\n }\n const stored = await client.read({ pathname: parsed });\n if (!stored) throw new Error(`Artifact ${ref} is unavailable`);\n if (sha256(stored.body) !== digest) {\n throw new Error(`Artifact ${ref} content does not match its digest`);\n }\n return stored.body;\n },\n };\n}\n"],"mappings":";;;AAMA,MAAM,qBACJ;AACF,MAAM,oBAAoB,EACvB,OAAO,CAAC,CACR,MAAM,oBAAoB,iCAAiC,CAAC,CAC5D,MAAqB;;AAMxB,SAAgB,iBAAiB,OAA6B;CAC5D,OAAO,kBAAkB,MAAM,KAAK;AACtC;AA0BA,MAAM,UAAU,SAAiB,WAAW,QAAQ,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,KAAK;;AAG/E,SAAgB,kBAAkB,UAAsC;CACtE,MAAM,MAAM,qBAAqB,SAAS,OAAO,GAAG,SAAS,QAAQ,GAAG,SAAS,KAAK,GAAG,OAAO,SAAS,IAAI;CAC7G,IAAI,CAAC,mBAAmB,KAAK,GAAG,GAC9B,MAAM,IAAI,MAAM,gEAAgE;CAElF,OAAO,iBAAiB,GAAG;AAC7B;;AAGA,SAAgB,oBAAoB,QAAmC;CACrE,OAAO;EACL,MAAM,IAAI,UAAU;GAClB,MAAM,MAAM,kBAAkB,QAAQ;GAEtC,MAAM,OAAO,MAAM;IAAE,UAAU;IAAK,MAAM,SAAS;IAAM,WAAW;GAAK,CAAC;GAC1E,OAAO;EACT;EACA,MAAM,KAAK,EAAE,KAAK,QAAQ,oBAAoB;GAC5C,MAAM,SAAS,iBAAiB,GAAG;GACnC,MAAM,QAAQ,mBAAmB,KAAK,MAAM;GAC5C,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,iCAAiC;GAC7D,MAAM,GAAG,YAAY,UAAU;GAC/B,IAAI,WAAW,kBACb,MAAM,IAAI,MACR,uBAAuB,OAAO,+BAA+B,kBAC/D;GAEF,MAAM,SAAS,MAAM,OAAO,KAAK,EAAE,UAAU,OAAO,CAAC;GACrD,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,YAAY,IAAI,gBAAgB;GAC7D,IAAI,OAAO,OAAO,IAAI,MAAM,QAC1B,MAAM,IAAI,MAAM,YAAY,IAAI,mCAAmC;GAErE,OAAO,OAAO;EAChB;CACF;AACF"}
|
package/dist/blob/index.d.mts
CHANGED
|
@@ -1,32 +1,68 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MillisecondClock } from "../schema/common.mjs";
|
|
2
|
+
import { StoreDriver } from "../store/driver.mjs";
|
|
3
|
+
import { ArtifactInput, ArtifactKind, ArtifactRef, ArtifactStore, ReadArtifactInput, artifactReference, createArtifactStore, parseArtifactRef } from "./artifacts.mjs";
|
|
2
4
|
//#region src/blob/index.d.ts
|
|
5
|
+
/** Blob content paired with the ETag required for compare-and-swap persistence. */
|
|
3
6
|
interface BlobObject {
|
|
4
7
|
body: string;
|
|
5
8
|
etag: string;
|
|
6
9
|
}
|
|
10
|
+
/** Exact blob pathname requested from storage. */
|
|
11
|
+
interface ReadBlobInput {
|
|
12
|
+
pathname: string;
|
|
13
|
+
}
|
|
14
|
+
/** Blob body and conditional-write policy used for one storage write. */
|
|
15
|
+
interface WriteBlobInput extends ReadBlobInput {
|
|
16
|
+
body: string;
|
|
17
|
+
overwrite: boolean;
|
|
18
|
+
ifMatch?: string;
|
|
19
|
+
}
|
|
20
|
+
/** Path prefix used to list matching blobs. */
|
|
21
|
+
interface ListBlobPathsInput {
|
|
22
|
+
prefix: string;
|
|
23
|
+
}
|
|
7
24
|
/** The narrow blob operations the driver needs; injectable for tests. */
|
|
8
25
|
interface BlobClient {
|
|
9
26
|
/** Must return the latest content, never a cached copy. */
|
|
10
|
-
read(
|
|
27
|
+
read(input: ReadBlobInput): Promise<BlobObject | null>;
|
|
11
28
|
/** Must reject if overwrite is false and the path exists, or if ifMatch is given and the ETag differs. */
|
|
12
|
-
write(
|
|
13
|
-
listPaths(
|
|
29
|
+
write(input: WriteBlobInput): Promise<void>;
|
|
30
|
+
listPaths(input: ListBlobPathsInput): Promise<readonly string[]>;
|
|
14
31
|
}
|
|
32
|
+
/** Default private Vercel Blob client used by the durable Factory store driver. */
|
|
15
33
|
declare const vercelBlobClient: BlobClient;
|
|
34
|
+
/** Bounds retries and exponential backoff for transient Blob operations. */
|
|
35
|
+
interface BlobRetryOptions {
|
|
36
|
+
/** Maximum attempts of a single read or write, including the first. Default 3. */
|
|
37
|
+
attempts?: number;
|
|
38
|
+
/** Backoff base in milliseconds; doubles each retry. Default 250. */
|
|
39
|
+
baseDelayMs?: number;
|
|
40
|
+
/** Ceiling on total elapsed retry time so a real outage still surfaces as a failure. Default 5000. */
|
|
41
|
+
maxTotalMs?: number;
|
|
42
|
+
}
|
|
43
|
+
/** Configures the Blob client, namespace, read concurrency, and transient retries. */
|
|
16
44
|
interface BlobDriverOptions {
|
|
17
45
|
client?: BlobClient;
|
|
18
46
|
/** Path prefix inside the blob store; defaults to "factory". */
|
|
19
47
|
prefix?: string;
|
|
48
|
+
/** Maximum Blob downloads in flight while listing a collection. Default 32. */
|
|
49
|
+
readConcurrency?: number;
|
|
50
|
+
/** Bounds retry of transient (5xx/429/network) Blob failures on reads and writes. */
|
|
51
|
+
retry?: BlobRetryOptions;
|
|
52
|
+
/** Millisecond clock used to bound total retry time. */
|
|
53
|
+
now?: MillisecondClock;
|
|
20
54
|
}
|
|
21
55
|
/**
|
|
22
56
|
* Store driver on Vercel Blob: durable and dependency-free (one Blob store on
|
|
23
|
-
* the project, no database). Inserts
|
|
24
|
-
* Postgres (create-if-absent is atomic). Updates read the latest content,
|
|
57
|
+
* the project, no database). Inserts are create-if-absent. Updates read the latest content,
|
|
25
58
|
* bypassing Blob's CDN cache, and write with an ETag precondition, so a
|
|
26
59
|
* writer that lost a race gets a VersionConflictError rather than
|
|
27
|
-
* overwriting the winner.
|
|
60
|
+
* overwriting the winner. Reads and writes retry with backoff on transient
|
|
61
|
+
* (5xx/429/network) failures, bounded by attempts and total elapsed time;
|
|
62
|
+
* once exhausted, the failure surfaces as TransientStoreError so a real
|
|
63
|
+
* outage does not hang a caller retrying forever.
|
|
28
64
|
*/
|
|
29
65
|
declare function createBlobDriver(options?: BlobDriverOptions): StoreDriver;
|
|
30
66
|
//#endregion
|
|
31
|
-
export { BlobClient, BlobDriverOptions, BlobObject, createBlobDriver, vercelBlobClient };
|
|
67
|
+
export { type ArtifactInput, type ArtifactKind, type ArtifactRef, type ArtifactStore, BlobClient, BlobDriverOptions, BlobObject, BlobRetryOptions, ListBlobPathsInput, type ReadArtifactInput, ReadBlobInput, WriteBlobInput, artifactReference, createArtifactStore, createBlobDriver, parseArtifactRef, vercelBlobClient };
|
|
32
68
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/blob/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RecordExistsError, RecordNotFoundError, TransientStoreError, VersionConflictError } from "../store/driver.mjs";
|
|
2
|
+
import { artifactReference, createArtifactStore, parseArtifactRef } from "./artifacts.mjs";
|
|
2
3
|
import { get, list, put } from "@vercel/blob";
|
|
3
4
|
//#region src/blob/index.ts
|
|
4
5
|
function isNotFoundError(error) {
|
|
@@ -10,8 +11,44 @@ function isAlreadyExistsError(error) {
|
|
|
10
11
|
function isPreconditionError(error) {
|
|
11
12
|
return error instanceof Error && (error.name === "BlobPreconditionFailedError" || /precondition|etag|412/iu.test(error.message));
|
|
12
13
|
}
|
|
14
|
+
const TRANSIENT_NETWORK_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
15
|
+
"ECONNRESET",
|
|
16
|
+
"ECONNREFUSED",
|
|
17
|
+
"ETIMEDOUT",
|
|
18
|
+
"ENOTFOUND",
|
|
19
|
+
"EAI_AGAIN",
|
|
20
|
+
"EPIPE",
|
|
21
|
+
"EHOSTUNREACH",
|
|
22
|
+
"ENETUNREACH",
|
|
23
|
+
"UND_ERR_CONNECT_TIMEOUT",
|
|
24
|
+
"UND_ERR_SOCKET",
|
|
25
|
+
"UND_ERR_HEADERS_TIMEOUT"
|
|
26
|
+
]);
|
|
27
|
+
function isTransientBlobError(error) {
|
|
28
|
+
if (!(error instanceof Error)) return false;
|
|
29
|
+
if (isAlreadyExistsError(error) || isPreconditionError(error) || isNotFoundError(error)) return false;
|
|
30
|
+
const code = error.code;
|
|
31
|
+
if (code !== void 0 && TRANSIENT_NETWORK_ERROR_CODES.has(code)) return true;
|
|
32
|
+
if (error.name === "AbortError") return true;
|
|
33
|
+
if (/fetch failed|network|socket hang up|timed? ?out|ECONNRESET|ECONNREFUSED|ETIMEDOUT|ENOTFOUND|EAI_AGAIN/iu.test(error.message)) return true;
|
|
34
|
+
return /(?:^|[^0-9])(?:429|5\d{2})(?:[^0-9]|$)/u.test(error.message);
|
|
35
|
+
}
|
|
36
|
+
function jsonValuesEqual(a, b) {
|
|
37
|
+
if (a === b) return true;
|
|
38
|
+
if (typeof a !== typeof b) return false;
|
|
39
|
+
if (a === null || b === null || typeof a !== "object" || typeof b !== "object") return false;
|
|
40
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
41
|
+
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
|
|
42
|
+
return a.every((item, index) => jsonValuesEqual(item, b[index]));
|
|
43
|
+
}
|
|
44
|
+
const aKeys = Object.keys(a);
|
|
45
|
+
const bKeys = Object.keys(b);
|
|
46
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
47
|
+
return aKeys.every((key) => Object.hasOwn(b, key) && jsonValuesEqual(a[key], b[key]));
|
|
48
|
+
}
|
|
49
|
+
/** Default private Vercel Blob client used by the durable Factory store driver. */
|
|
13
50
|
const vercelBlobClient = {
|
|
14
|
-
async read(pathname) {
|
|
51
|
+
async read({ pathname }) {
|
|
15
52
|
let result;
|
|
16
53
|
try {
|
|
17
54
|
result = await get(pathname, {
|
|
@@ -28,15 +65,15 @@ const vercelBlobClient = {
|
|
|
28
65
|
etag: result.blob.etag
|
|
29
66
|
};
|
|
30
67
|
},
|
|
31
|
-
async write(pathname, body, overwrite, ifMatch) {
|
|
32
|
-
await put(pathname, body, {
|
|
68
|
+
async write({ pathname, body, overwrite, ifMatch }) {
|
|
69
|
+
await put(pathname, body === "" ? Buffer.alloc(0) : body, {
|
|
33
70
|
access: "private",
|
|
34
71
|
allowOverwrite: overwrite,
|
|
35
72
|
contentType: "application/json",
|
|
36
|
-
...ifMatch === void 0 ? {} : { ifMatch }
|
|
73
|
+
...ifMatch === void 0 ? {} : { ifMatch: ifMatch.replace(/^W\//u, "") }
|
|
37
74
|
});
|
|
38
75
|
},
|
|
39
|
-
async listPaths(prefix) {
|
|
76
|
+
async listPaths({ prefix }) {
|
|
40
77
|
const paths = [];
|
|
41
78
|
let cursor;
|
|
42
79
|
do {
|
|
@@ -53,22 +90,57 @@ const vercelBlobClient = {
|
|
|
53
90
|
};
|
|
54
91
|
/**
|
|
55
92
|
* Store driver on Vercel Blob: durable and dependency-free (one Blob store on
|
|
56
|
-
* the project, no database). Inserts
|
|
57
|
-
* Postgres (create-if-absent is atomic). Updates read the latest content,
|
|
93
|
+
* the project, no database). Inserts are create-if-absent. Updates read the latest content,
|
|
58
94
|
* bypassing Blob's CDN cache, and write with an ETag precondition, so a
|
|
59
95
|
* writer that lost a race gets a VersionConflictError rather than
|
|
60
|
-
* overwriting the winner.
|
|
96
|
+
* overwriting the winner. Reads and writes retry with backoff on transient
|
|
97
|
+
* (5xx/429/network) failures, bounded by attempts and total elapsed time;
|
|
98
|
+
* once exhausted, the failure surfaces as TransientStoreError so a real
|
|
99
|
+
* outage does not hang a caller retrying forever.
|
|
61
100
|
*/
|
|
62
101
|
function createBlobDriver(options = {}) {
|
|
63
102
|
const client = options.client ?? vercelBlobClient;
|
|
103
|
+
const now = options.now ?? Date.now;
|
|
64
104
|
const prefix = options.prefix ?? "factory";
|
|
105
|
+
const readConcurrency = options.readConcurrency ?? 32;
|
|
106
|
+
if (!Number.isInteger(readConcurrency) || readConcurrency < 1) throw new Error("Blob read concurrency must be a positive integer");
|
|
107
|
+
const retry = {
|
|
108
|
+
attempts: options.retry?.attempts ?? 3,
|
|
109
|
+
baseDelayMs: options.retry?.baseDelayMs ?? 250,
|
|
110
|
+
maxTotalMs: options.retry?.maxTotalMs ?? 5e3
|
|
111
|
+
};
|
|
112
|
+
let activeReads = 0;
|
|
113
|
+
const readWaiters = [];
|
|
114
|
+
const activeLists = /* @__PURE__ */ new Map();
|
|
115
|
+
async function withTransientRetry(collection, id, operation) {
|
|
116
|
+
const start = now();
|
|
117
|
+
for (let attempt = 0;; attempt += 1) try {
|
|
118
|
+
return await operation();
|
|
119
|
+
} catch (error) {
|
|
120
|
+
if (!isTransientBlobError(error)) throw error;
|
|
121
|
+
const nextDelayMs = retry.baseDelayMs * 2 ** attempt;
|
|
122
|
+
if (attempt >= retry.attempts - 1 || now() - start + nextDelayMs > retry.maxTotalMs) throw new TransientStoreError(collection, id, error);
|
|
123
|
+
await new Promise((resolve) => setTimeout(resolve, nextDelayMs));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async function limitedRead(pathname) {
|
|
127
|
+
if (activeReads < readConcurrency) activeReads += 1;
|
|
128
|
+
else await new Promise((resolve) => readWaiters.push(resolve));
|
|
129
|
+
try {
|
|
130
|
+
return await client.read({ pathname });
|
|
131
|
+
} finally {
|
|
132
|
+
const waiter = readWaiters.shift();
|
|
133
|
+
if (waiter === void 0) activeReads -= 1;
|
|
134
|
+
else waiter();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
65
137
|
function pathFor(collection, id) {
|
|
66
138
|
return `${prefix}/${collection}/${id}.json`;
|
|
67
139
|
}
|
|
68
140
|
async function readRecord(collection, id) {
|
|
69
141
|
let object;
|
|
70
142
|
try {
|
|
71
|
-
object = await
|
|
143
|
+
object = await withTransientRetry(collection, id, () => limitedRead(pathFor(collection, id)));
|
|
72
144
|
} catch (error) {
|
|
73
145
|
if (isNotFoundError(error)) return null;
|
|
74
146
|
throw error;
|
|
@@ -82,6 +154,14 @@ function createBlobDriver(options = {}) {
|
|
|
82
154
|
etag: object.etag
|
|
83
155
|
};
|
|
84
156
|
}
|
|
157
|
+
async function wroteThisInsert(collection, id, value) {
|
|
158
|
+
const after = await readRecord(collection, id);
|
|
159
|
+
return after !== null && after.version === 1 && jsonValuesEqual(after.value, value);
|
|
160
|
+
}
|
|
161
|
+
async function wroteThisUpdate(collection, id, value, expectedNewVersion) {
|
|
162
|
+
const after = await readRecord(collection, id);
|
|
163
|
+
return after !== null && after.version === expectedNewVersion && jsonValuesEqual(after.value, value);
|
|
164
|
+
}
|
|
85
165
|
return {
|
|
86
166
|
name: "blob",
|
|
87
167
|
async get(collection, id) {
|
|
@@ -91,51 +171,95 @@ function createBlobDriver(options = {}) {
|
|
|
91
171
|
version: record.version
|
|
92
172
|
};
|
|
93
173
|
},
|
|
94
|
-
async insert(collection, id, value) {
|
|
174
|
+
async insert({ collection, id, value }) {
|
|
175
|
+
let attempts = 0;
|
|
95
176
|
try {
|
|
96
|
-
await
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
177
|
+
await withTransientRetry(collection, id, () => {
|
|
178
|
+
attempts += 1;
|
|
179
|
+
return client.write({
|
|
180
|
+
pathname: pathFor(collection, id),
|
|
181
|
+
body: JSON.stringify({
|
|
182
|
+
value,
|
|
183
|
+
version: 1
|
|
184
|
+
}),
|
|
185
|
+
overwrite: false
|
|
186
|
+
});
|
|
187
|
+
});
|
|
100
188
|
} catch (error) {
|
|
101
|
-
if (isAlreadyExistsError(error))
|
|
189
|
+
if (isAlreadyExistsError(error)) {
|
|
190
|
+
if (attempts > 1 && await wroteThisInsert(collection, id, value)) return;
|
|
191
|
+
throw new RecordExistsError(collection, id);
|
|
192
|
+
}
|
|
102
193
|
throw error;
|
|
103
194
|
}
|
|
104
195
|
},
|
|
105
|
-
async update(collection, id, value, expectedVersion) {
|
|
196
|
+
async update({ collection, id, value, expectedVersion }) {
|
|
106
197
|
const existing = await readRecord(collection, id);
|
|
107
198
|
if (existing === null) throw new RecordNotFoundError(collection, id);
|
|
108
199
|
if (existing.version !== expectedVersion) throw new VersionConflictError(collection, id, expectedVersion);
|
|
200
|
+
let attempts = 0;
|
|
109
201
|
try {
|
|
110
|
-
await
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
202
|
+
await withTransientRetry(collection, id, () => {
|
|
203
|
+
attempts += 1;
|
|
204
|
+
return client.write({
|
|
205
|
+
pathname: pathFor(collection, id),
|
|
206
|
+
body: JSON.stringify({
|
|
207
|
+
value,
|
|
208
|
+
version: expectedVersion + 1
|
|
209
|
+
}),
|
|
210
|
+
overwrite: true,
|
|
211
|
+
ifMatch: existing.etag.replace(/^W\//u, "")
|
|
212
|
+
});
|
|
213
|
+
});
|
|
114
214
|
} catch (error) {
|
|
115
|
-
if (isPreconditionError(error))
|
|
215
|
+
if (isPreconditionError(error)) {
|
|
216
|
+
if (attempts > 1 && await wroteThisUpdate(collection, id, value, expectedVersion + 1)) return;
|
|
217
|
+
throw new VersionConflictError(collection, id, expectedVersion);
|
|
218
|
+
}
|
|
116
219
|
throw error;
|
|
117
220
|
}
|
|
118
221
|
},
|
|
119
222
|
async list(collection) {
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
const
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
223
|
+
const active = activeLists.get(collection);
|
|
224
|
+
if (active !== void 0) return active;
|
|
225
|
+
const listing = (async () => {
|
|
226
|
+
const dir = `${prefix}/${collection}/`;
|
|
227
|
+
const paths = await client.listPaths({ prefix: dir });
|
|
228
|
+
const entries = new Array(paths.length);
|
|
229
|
+
let next = 0;
|
|
230
|
+
let failure;
|
|
231
|
+
const workers = Array.from({ length: Math.min(readConcurrency, paths.length) }, async () => {
|
|
232
|
+
while (next < paths.length && failure === void 0) {
|
|
233
|
+
const index = next++;
|
|
234
|
+
const id = paths[index].slice(dir.length).replace(/\.json$/u, "");
|
|
235
|
+
try {
|
|
236
|
+
const record = await readRecord(collection, id);
|
|
237
|
+
entries[index] = record === null ? null : {
|
|
238
|
+
id,
|
|
239
|
+
record: {
|
|
240
|
+
value: record.value,
|
|
241
|
+
version: record.version
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
} catch (error) {
|
|
245
|
+
failure ??= error;
|
|
246
|
+
}
|
|
131
247
|
}
|
|
132
248
|
});
|
|
249
|
+
await Promise.all(workers);
|
|
250
|
+
if (failure !== void 0) throw failure;
|
|
251
|
+
return entries.filter((entry) => entry !== null);
|
|
252
|
+
})();
|
|
253
|
+
activeLists.set(collection, listing);
|
|
254
|
+
try {
|
|
255
|
+
return await listing;
|
|
256
|
+
} finally {
|
|
257
|
+
if (activeLists.get(collection) === listing) activeLists.delete(collection);
|
|
133
258
|
}
|
|
134
|
-
return entries;
|
|
135
259
|
}
|
|
136
260
|
};
|
|
137
261
|
}
|
|
138
262
|
//#endregion
|
|
139
|
-
export { createBlobDriver, vercelBlobClient };
|
|
263
|
+
export { artifactReference, createArtifactStore, createBlobDriver, parseArtifactRef, vercelBlobClient };
|
|
140
264
|
|
|
141
265
|
//# sourceMappingURL=index.mjs.map
|