cloving 0.3.20 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{LICENSE.md → LICENSE} +1 -1
- package/README.md +475 -182
- package/dist/src/authority/budgets.d.ts +12 -0
- package/dist/src/authority/budgets.js +42 -0
- package/dist/src/authority/commands.d.ts +7 -0
- package/dist/src/authority/commands.js +263 -0
- package/dist/src/authority/details.d.ts +28 -0
- package/dist/src/authority/details.js +33 -0
- package/dist/src/authority/dispatch-decision.d.ts +40 -0
- package/dist/src/authority/dispatch-decision.js +47 -0
- package/dist/src/authority/effect-requests.d.ts +2 -0
- package/dist/src/authority/effect-requests.js +139 -0
- package/dist/src/authority/effect-results.d.ts +4 -0
- package/dist/src/authority/effect-results.js +236 -0
- package/dist/src/authority/events.d.ts +2 -0
- package/dist/src/authority/events.js +45 -0
- package/dist/src/authority/gate-reduction.d.ts +8 -0
- package/dist/src/authority/gate-reduction.js +109 -0
- package/dist/src/authority/gates.d.ts +48 -0
- package/dist/src/authority/gates.js +77 -0
- package/dist/src/authority/history-state.d.ts +15 -0
- package/dist/src/authority/history-state.js +61 -0
- package/dist/src/authority/history.d.ts +13 -0
- package/dist/src/authority/history.js +37 -0
- package/dist/src/authority/instants.d.ts +3 -0
- package/dist/src/authority/instants.js +38 -0
- package/dist/src/authority/leases.d.ts +15 -0
- package/dist/src/authority/leases.js +113 -0
- package/dist/src/authority/operations.d.ts +101 -0
- package/dist/src/authority/operations.js +75 -0
- package/dist/src/authority/reconciliation.d.ts +27 -0
- package/dist/src/authority/reconciliation.js +147 -0
- package/dist/src/authority/reducer.d.ts +41 -0
- package/dist/src/authority/reducer.js +139 -0
- package/dist/src/authority/reduction-state.d.ts +36 -0
- package/dist/src/authority/reduction-state.js +68 -0
- package/dist/src/authority/reduction.d.ts +6 -0
- package/dist/src/authority/reduction.js +160 -0
- package/dist/src/authority/status-closure.d.ts +4 -0
- package/dist/src/authority/status-closure.js +57 -0
- package/dist/src/authority/status-effects.d.ts +17 -0
- package/dist/src/authority/status-effects.js +43 -0
- package/dist/src/authority/status-input.d.ts +45 -0
- package/dist/src/authority/status-input.js +9 -0
- package/dist/src/authority/status.d.ts +32 -0
- package/dist/src/authority/status.js +256 -0
- package/dist/src/authority/stop-sequence.d.ts +37 -0
- package/dist/src/authority/stop-sequence.js +91 -0
- package/dist/src/authority/transitions.d.ts +63 -0
- package/dist/src/authority/transitions.js +122 -0
- package/dist/src/broker/actor/adapter-calls.d.ts +13 -0
- package/dist/src/broker/actor/adapter-calls.js +34 -0
- package/dist/src/broker/actor/adapter-outcomes.d.ts +28 -0
- package/dist/src/broker/actor/adapter-outcomes.js +80 -0
- package/dist/src/broker/actor/authority-actor.d.ts +25 -0
- package/dist/src/broker/actor/authority-actor.js +169 -0
- package/dist/src/broker/actor/authority-changes.d.ts +31 -0
- package/dist/src/broker/actor/authority-changes.js +46 -0
- package/dist/src/broker/actor/authority-connection.d.ts +15 -0
- package/dist/src/broker/actor/authority-connection.js +44 -0
- package/dist/src/broker/actor/authority-conversion.d.ts +10 -0
- package/dist/src/broker/actor/authority-conversion.js +72 -0
- package/dist/src/broker/actor/authority-delivery.d.ts +13 -0
- package/dist/src/broker/actor/authority-delivery.js +162 -0
- package/dist/src/broker/actor/authority-logger.d.ts +2 -0
- package/dist/src/broker/actor/authority-logger.js +19 -0
- package/dist/src/broker/actor/authority-policy.d.ts +9 -0
- package/dist/src/broker/actor/authority-policy.js +11 -0
- package/dist/src/broker/actor/authority-queries.d.ts +45 -0
- package/dist/src/broker/actor/authority-queries.js +85 -0
- package/dist/src/broker/actor/authority-receipts.d.ts +28 -0
- package/dist/src/broker/actor/authority-receipts.js +84 -0
- package/dist/src/broker/actor/authority-release.d.ts +13 -0
- package/dist/src/broker/actor/authority-release.js +69 -0
- package/dist/src/broker/actor/authority-runtime.d.ts +60 -0
- package/dist/src/broker/actor/authority-runtime.js +204 -0
- package/dist/src/broker/actor/authority-session.d.ts +65 -0
- package/dist/src/broker/actor/authority-session.js +252 -0
- package/dist/src/broker/actor/authority-settings.d.ts +33 -0
- package/dist/src/broker/actor/authority-settings.js +63 -0
- package/dist/src/broker/actor/authority-upgrades.d.ts +16 -0
- package/dist/src/broker/actor/authority-upgrades.js +12 -0
- package/dist/src/broker/actor/authority-watchdog.d.ts +14 -0
- package/dist/src/broker/actor/authority-watchdog.js +41 -0
- package/dist/src/broker/actor/authority.d.ts +14 -0
- package/dist/src/broker/actor/authority.js +115 -0
- package/dist/src/broker/actor/delivery-intents.d.ts +68 -0
- package/dist/src/broker/actor/delivery-intents.js +77 -0
- package/dist/src/broker/actor/delivery-plan.d.ts +2 -0
- package/dist/src/broker/actor/delivery-plan.js +109 -0
- package/dist/src/broker/actor/delivery-results.d.ts +11 -0
- package/dist/src/broker/actor/delivery-results.js +63 -0
- package/dist/src/broker/actor/effect-delivery.d.ts +19 -0
- package/dist/src/broker/actor/effect-delivery.js +118 -0
- package/dist/src/broker/actor/effect-plan.d.ts +41 -0
- package/dist/src/broker/actor/effect-plan.js +173 -0
- package/dist/src/broker/actor/effect-queries.d.ts +27 -0
- package/dist/src/broker/actor/effect-queries.js +80 -0
- package/dist/src/broker/actor/effect-turn.d.ts +25 -0
- package/dist/src/broker/actor/effect-turn.js +84 -0
- package/dist/src/broker/actor/pin-check.d.ts +6 -0
- package/dist/src/broker/actor/pin-check.js +12 -0
- package/dist/src/broker/actor/runtime-parts.d.ts +23 -0
- package/dist/src/broker/actor/runtime-parts.js +34 -0
- package/dist/src/broker/actor/stop-plan.d.ts +20 -0
- package/dist/src/broker/actor/stop-plan.js +46 -0
- package/dist/src/broker/actor/stop-turn.d.ts +17 -0
- package/dist/src/broker/actor/stop-turn.js +42 -0
- package/dist/src/broker/actor/turn-draft.d.ts +31 -0
- package/dist/src/broker/actor/turn-draft.js +138 -0
- package/dist/src/broker/actor/turn-plan.d.ts +17 -0
- package/dist/src/broker/actor/turn-plan.js +136 -0
- package/dist/src/broker/actor/turn-refusals.d.ts +8 -0
- package/dist/src/broker/actor/turn-refusals.js +35 -0
- package/dist/src/broker/actor/turn-staging.d.ts +78 -0
- package/dist/src/broker/actor/turn-staging.js +34 -0
- package/dist/src/broker/actor/turn-state.d.ts +34 -0
- package/dist/src/broker/actor/turn-state.js +208 -0
- package/dist/src/broker/authority-admission.d.ts +21 -0
- package/dist/src/broker/authority-admission.js +70 -0
- package/dist/src/broker/authority-restore.d.ts +30 -0
- package/dist/src/broker/authority-restore.js +165 -0
- package/dist/src/broker/decision-restore.d.ts +16 -0
- package/dist/src/broker/decision-restore.js +158 -0
- package/dist/src/broker/decision-upgrade.d.ts +3 -0
- package/dist/src/broker/decision-upgrade.js +12 -0
- package/dist/src/broker/effect-restore.d.ts +20 -0
- package/dist/src/broker/effect-restore.js +111 -0
- package/dist/src/broker/effect-upgrade.d.ts +3 -0
- package/dist/src/broker/effect-upgrade.js +9 -0
- package/dist/src/broker/operation-digest.d.ts +1 -0
- package/dist/src/broker/operation-digest.js +4 -0
- package/dist/src/broker/socket-address.d.ts +9 -0
- package/dist/src/broker/socket-address.js +14 -0
- package/dist/src/broker/workflow-pin.d.ts +2 -0
- package/dist/src/broker/workflow-pin.js +5 -0
- package/dist/src/chats/destination.d.ts +4 -0
- package/dist/src/chats/destination.js +94 -0
- package/dist/src/chats/import.d.ts +13 -0
- package/dist/src/chats/import.js +71 -0
- package/dist/src/chats/normalize.d.ts +20 -0
- package/dist/src/chats/normalize.js +139 -0
- package/dist/src/chats/reader.d.ts +15 -0
- package/dist/src/chats/reader.js +87 -0
- package/dist/src/cli/arguments.d.ts +23 -0
- package/dist/src/cli/arguments.js +154 -0
- package/dist/src/cli/client.d.ts +15 -0
- package/dist/src/cli/client.js +122 -0
- package/dist/src/cli/commands.d.ts +14 -0
- package/dist/src/cli/commands.js +253 -0
- package/dist/src/cli/main.d.ts +1 -0
- package/dist/src/cli/main.js +80 -0
- package/dist/src/cli/render.d.ts +8 -0
- package/dist/src/cli/render.js +186 -0
- package/dist/src/cli/runtime-arguments.d.ts +73 -0
- package/dist/src/cli/runtime-arguments.js +248 -0
- package/dist/src/cli/runtime-directory.d.ts +4 -0
- package/dist/src/cli/runtime-directory.js +25 -0
- package/dist/src/cli/toolchain.d.ts +3 -0
- package/dist/src/cli/toolchain.js +74 -0
- package/dist/src/cli/usage.d.ts +4 -0
- package/dist/src/cli/usage.js +124 -0
- package/dist/src/cli/validate.d.ts +38 -0
- package/dist/src/cli/validate.js +116 -0
- package/dist/src/cli/watch-board-view.d.ts +22 -0
- package/dist/src/cli/watch-board-view.js +128 -0
- package/dist/src/cli/watch-board.d.ts +15 -0
- package/dist/src/cli/watch-board.js +174 -0
- package/dist/src/cli/watch-element.d.ts +11 -0
- package/dist/src/cli/watch-element.js +6 -0
- package/dist/src/cli/watch-model.d.ts +29 -0
- package/dist/src/cli/watch-model.js +261 -0
- package/dist/src/cli/watch-navigation.d.ts +9 -0
- package/dist/src/cli/watch-navigation.js +40 -0
- package/dist/src/cli/watch-page.d.ts +1 -0
- package/dist/src/cli/watch-page.js +272 -0
- package/dist/src/cli/watch-paths.d.ts +2 -0
- package/dist/src/cli/watch-paths.js +52 -0
- package/dist/src/cli/watch-phases.d.ts +7 -0
- package/dist/src/cli/watch-phases.js +148 -0
- package/dist/src/cli/watch-reads.d.ts +28 -0
- package/dist/src/cli/watch-reads.js +244 -0
- package/dist/src/cli/watch-render.d.ts +139 -0
- package/dist/src/cli/watch-render.js +95 -0
- package/dist/src/cli/watch-server.d.ts +10 -0
- package/dist/src/cli/watch-server.js +176 -0
- package/dist/src/cli/watch-stream.d.ts +11 -0
- package/dist/src/cli/watch-stream.js +128 -0
- package/dist/src/cli/watch-turn.d.ts +29 -0
- package/dist/src/cli/watch-turn.js +130 -0
- package/dist/src/cli/watch-view.d.ts +39 -0
- package/dist/src/cli/watch-view.js +223 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +62 -0
- package/dist/src/daemon/claude-turn.d.ts +28 -0
- package/dist/src/daemon/claude-turn.js +135 -0
- package/dist/src/daemon/claude-worker.d.ts +26 -0
- package/dist/src/daemon/claude-worker.js +224 -0
- package/dist/src/daemon/codex-stream.d.ts +4 -0
- package/dist/src/daemon/codex-stream.js +113 -0
- package/dist/src/daemon/daemon.d.ts +46 -0
- package/dist/src/daemon/daemon.js +186 -0
- package/dist/src/daemon/delivery-router.d.ts +10 -0
- package/dist/src/daemon/delivery-router.js +34 -0
- package/dist/src/daemon/github-calls.d.ts +29 -0
- package/dist/src/daemon/github-calls.js +127 -0
- package/dist/src/daemon/github-issue-methods.d.ts +3 -0
- package/dist/src/daemon/github-issue-methods.js +99 -0
- package/dist/src/daemon/github-issue-privacy.d.ts +6 -0
- package/dist/src/daemon/github-issue-privacy.js +131 -0
- package/dist/src/daemon/github-merge.d.ts +18 -0
- package/dist/src/daemon/github-merge.js +259 -0
- package/dist/src/daemon/github-methods.d.ts +5 -0
- package/dist/src/daemon/github-methods.js +198 -0
- package/dist/src/daemon/github-operation.d.ts +38 -0
- package/dist/src/daemon/github-operation.js +57 -0
- package/dist/src/daemon/github-worker.d.ts +17 -0
- package/dist/src/daemon/github-worker.js +281 -0
- package/dist/src/daemon/host-environment.d.ts +8 -0
- package/dist/src/daemon/host-environment.js +14 -0
- package/dist/src/daemon/issue-queue.d.ts +9 -0
- package/dist/src/daemon/issue-queue.js +163 -0
- package/dist/src/daemon/notify-message.d.ts +14 -0
- package/dist/src/daemon/notify-message.js +48 -0
- package/dist/src/daemon/notify.d.ts +12 -0
- package/dist/src/daemon/notify.js +161 -0
- package/dist/src/daemon/operation-journal.d.ts +42 -0
- package/dist/src/daemon/operation-journal.js +53 -0
- package/dist/src/daemon/ticket-registration.d.ts +33 -0
- package/dist/src/daemon/ticket-registration.js +177 -0
- package/dist/src/daemon/ticket-source.d.ts +17 -0
- package/dist/src/daemon/ticket-source.js +36 -0
- package/dist/src/daemon/work-tree.d.ts +26 -0
- package/dist/src/daemon/work-tree.js +206 -0
- package/dist/src/effect-authorization.d.ts +21 -0
- package/dist/src/effect-authorization.js +14 -0
- package/dist/src/execution-pin.d.ts +4 -0
- package/dist/src/execution-pin.js +68 -0
- package/dist/src/host/start-delivery.d.ts +41 -0
- package/dist/src/host/start-delivery.js +68 -0
- package/dist/src/host/step-bridge-host.d.ts +79 -0
- package/dist/src/host/step-bridge-host.js +205 -0
- package/dist/src/host/step-claims.d.ts +31 -0
- package/dist/src/host/step-claims.js +85 -0
- package/dist/src/host/world-host.d.ts +21 -0
- package/dist/src/host/world-host.js +51 -0
- package/dist/src/host/world-reconciliation.d.ts +37 -0
- package/dist/src/host/world-reconciliation.js +75 -0
- package/dist/src/host/world-runs.d.ts +14 -0
- package/dist/src/host/world-runs.js +61 -0
- package/dist/src/operation-identity.d.ts +7 -0
- package/dist/src/operation-identity.js +59 -0
- package/dist/src/protocol.d.ts +35 -0
- package/dist/src/protocol.js +64 -0
- package/dist/src/resource-files.d.ts +1 -0
- package/dist/src/resource-files.js +29 -0
- package/dist/src/service/changes.d.ts +11 -0
- package/dist/src/service/changes.js +32 -0
- package/dist/src/service/decision-handler.d.ts +9 -0
- package/dist/src/service/decision-handler.js +233 -0
- package/dist/src/service/event-handler.d.ts +10 -0
- package/dist/src/service/event-handler.js +70 -0
- package/dist/src/service/expiry.d.ts +13 -0
- package/dist/src/service/expiry.js +53 -0
- package/dist/src/service/gateway.d.ts +21 -0
- package/dist/src/service/gateway.js +120 -0
- package/dist/src/service/registry.d.ts +40 -0
- package/dist/src/service/registry.js +13 -0
- package/dist/src/service/replies.d.ts +26 -0
- package/dist/src/service/replies.js +56 -0
- package/dist/src/service/run-handlers.d.ts +4 -0
- package/dist/src/service/run-handlers.js +271 -0
- package/dist/src/service/service.d.ts +58 -0
- package/dist/src/service/service.js +212 -0
- package/dist/src/service/submission-handler.d.ts +4 -0
- package/dist/src/service/submission-handler.js +206 -0
- package/dist/src/service/transport.d.ts +16 -0
- package/dist/src/service/transport.js +141 -0
- package/dist/src/service/worker-port.d.ts +85 -0
- package/dist/src/service/worker-port.js +126 -0
- package/dist/src/step-bridge.d.ts +57 -0
- package/dist/src/step-bridge.js +4 -0
- package/dist/src/steps/decision-gate.d.ts +2 -0
- package/dist/src/steps/decision-gate.js +8 -0
- package/dist/src/steps/load-cycle.d.ts +10 -0
- package/dist/src/steps/load-cycle.js +11 -0
- package/dist/src/steps/protected-effect.d.ts +2 -0
- package/dist/src/steps/protected-effect.js +8 -0
- package/dist/src/storage/decision-rows.d.ts +54 -0
- package/dist/src/storage/decision-rows.js +72 -0
- package/dist/src/storage/decision-snapshots.d.ts +17 -0
- package/dist/src/storage/decision-snapshots.js +25 -0
- package/dist/src/storage/domain-changes.d.ts +48 -0
- package/dist/src/storage/domain-changes.js +213 -0
- package/dist/src/storage/domain-rows.d.ts +85 -0
- package/dist/src/storage/domain-rows.js +129 -0
- package/dist/src/storage/domain-schema.d.ts +32 -0
- package/dist/src/storage/domain-schema.js +193 -0
- package/dist/src/storage/effect-changes.d.ts +5 -0
- package/dist/src/storage/effect-changes.js +105 -0
- package/dist/src/storage/effect-rows.d.ts +67 -0
- package/dist/src/storage/effect-rows.js +74 -0
- package/dist/src/storage/effect-schema.d.ts +1 -0
- package/dist/src/storage/effect-schema.js +59 -0
- package/dist/src/storage/statements.d.ts +9 -0
- package/dist/src/storage/statements.js +8 -0
- package/dist/src/submission.d.ts +42 -0
- package/dist/src/submission.js +71 -0
- package/dist/src/turn-profile.d.ts +13 -0
- package/dist/src/turn-profile.js +100 -0
- package/dist/src/workflow-admission.d.ts +45 -0
- package/dist/src/workflow-admission.js +151 -0
- package/dist/src/workflow-contracts.d.ts +27 -0
- package/dist/src/workflow-contracts.js +88 -0
- package/dist/src/workflow-declaration.d.ts +11 -0
- package/dist/src/workflow-declaration.js +57 -0
- package/dist/src/workflow-resources.d.ts +8 -0
- package/dist/src/workflow-resources.js +14 -0
- package/dist/src/workflows.d.ts +5 -0
- package/dist/src/workflows.js +3 -0
- package/dist/tools/compile-workflows.d.ts +1 -0
- package/dist/tools/compile-workflows.js +33 -0
- package/dist/tools/self-host-processes.d.ts +10 -0
- package/dist/tools/self-host-processes.js +151 -0
- package/dist/tools/self-host-workflows.d.ts +15 -0
- package/dist/tools/self-host-workflows.js +78 -0
- package/dist/tools/self-host.d.ts +1 -0
- package/dist/tools/self-host.js +261 -0
- package/dist/tools/self-update-host.d.ts +6 -0
- package/dist/tools/self-update-host.js +41 -0
- package/dist/tools/self-update.d.ts +10 -0
- package/dist/tools/self-update.js +105 -0
- package/dist/tools/workflow-manifest.d.ts +3 -0
- package/dist/tools/workflow-manifest.js +34 -0
- package/dist/workflows/develop-prd.d.ts +7 -0
- package/dist/workflows/develop-prd.js +97 -0
- package/dist/workflows/develop-ticket.d.ts +15 -0
- package/dist/workflows/develop-ticket.js +301 -0
- package/dist/workflows/issue-labels.d.ts +14 -0
- package/dist/workflows/issue-labels.js +36 -0
- package/package.json +82 -75
- package/dist/abstract_gpt/index.js +0 -55
- package/dist/cloving_gpt/adapters/Adapter.js +0 -2
- package/dist/cloving_gpt/adapters/azureopenai.js +0 -69
- package/dist/cloving_gpt/adapters/claude.js +0 -128
- package/dist/cloving_gpt/adapters/gemini.js +0 -135
- package/dist/cloving_gpt/adapters/gpt4all.js +0 -29
- package/dist/cloving_gpt/adapters/index.js +0 -2
- package/dist/cloving_gpt/adapters/mistral.js +0 -128
- package/dist/cloving_gpt/adapters/ollama.js +0 -128
- package/dist/cloving_gpt/adapters/openai.js +0 -100
- package/dist/cloving_gpt/index.js +0 -192
- package/dist/commands/analyze.js +0 -47
- package/dist/commands/chat.js +0 -14
- package/dist/commands/check.js +0 -7
- package/dist/commands/commit.js +0 -44
- package/dist/commands/config.js +0 -167
- package/dist/commands/describe.js +0 -235
- package/dist/commands/generate/code.js +0 -21
- package/dist/commands/generate/commit.js +0 -11
- package/dist/commands/generate/context.js +0 -82
- package/dist/commands/generate/docs.js +0 -11
- package/dist/commands/generate/documentation.js +0 -11
- package/dist/commands/generate/fizzbuzz.js +0 -35
- package/dist/commands/generate/init.js +0 -15
- package/dist/commands/generate/review.js +0 -11
- package/dist/commands/generate/sh.js +0 -95
- package/dist/commands/generate/shell.js +0 -11
- package/dist/commands/generate/unit_tests.js +0 -11
- package/dist/commands/init.js +0 -13
- package/dist/commands/models.js +0 -22
- package/dist/commands/project/build.js +0 -88
- package/dist/commands/project/complete.js +0 -12
- package/dist/commands/project/init.js +0 -82
- package/dist/commands/project/plan.js +0 -108
- package/dist/commands/proxy.js +0 -11
- package/dist/commands/review.js +0 -50
- package/dist/commands/tokens.js +0 -75
- package/dist/commands/unit_tests.js +0 -150
- package/dist/commands/update.js +0 -7
- package/dist/file2.js +0 -4
- package/dist/index.js +0 -136
- package/dist/managers/BlockManager.js +0 -120
- package/dist/managers/ChatManager.js +0 -653
- package/dist/managers/ChunkManager.js +0 -32
- package/dist/managers/CodeManager.js +0 -185
- package/dist/managers/CommitManager.js +0 -78
- package/dist/managers/DocsManager.js +0 -88
- package/dist/managers/DocumentationManager.js +0 -114
- package/dist/managers/InitManager.js +0 -230
- package/dist/managers/ProxyManager.js +0 -210
- package/dist/managers/ReviewManager.js +0 -131
- package/dist/managers/ShellManager.js +0 -163
- package/dist/managers/StreamManager.js +0 -308
- package/dist/managers/UnitTestManager.js +0 -243
- package/dist/managers/src/managers/ProxyManager.js +0 -1
- package/dist/newfile.js +0 -2
- package/dist/package.json +0 -86
- package/dist/utils/command_utils.js +0 -384
- package/dist/utils/config_utils.js +0 -249
- package/dist/utils/gitUtils.js +0 -42
- package/dist/utils/git_utils.js +0 -217
- package/dist/utils/modelUtils.js +0 -7
- package/dist/utils/model_utils.js +0 -7
- package/dist/utils/prompt_utils.js +0 -333
- package/dist/utils/prompts/CODEGEN_COULDNT_APPLY.md +0 -5
- package/dist/utils/prompts/CODEGEN_EXAMPLES.md +0 -82
- package/dist/utils/prompts/CODEGEN_INSTRUCTIONS.md +0 -43
- package/dist/utils/prompts/DOCS_INSTRUCTIONS.md +0 -9
- package/dist/utils/prompts/INIT_INSTRUCTIONS.md +0 -132
- package/dist/utils/prompts/REVIEW_INSTRUCTIONS.md +0 -49
- package/dist/utils/prompts/SHELL_INSTRUCTIONS.md +0 -15
- package/dist/utils/prompts/SPECIAL_FILES.md +0 -66
- package/dist/utils/prompts/index.js +0 -27
- package/dist/utils/string_utils.js +0 -505
- package/dist/utils/types.js +0 -2
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { type ProtectedRequest, type StepBridge } from "../step-bridge.ts";
|
|
2
|
+
export interface StepCall {
|
|
3
|
+
readonly worldRunId: string;
|
|
4
|
+
readonly stepId: string;
|
|
5
|
+
readonly attempt: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function sdkStepCall(): StepCall;
|
|
8
|
+
export interface OperationRead {
|
|
9
|
+
readonly operationId: string;
|
|
10
|
+
readonly status: string;
|
|
11
|
+
readonly reason: string | null;
|
|
12
|
+
readonly receipt: string | null;
|
|
13
|
+
readonly result: string | null;
|
|
14
|
+
}
|
|
15
|
+
export interface BridgeReply {
|
|
16
|
+
readonly receipt: {
|
|
17
|
+
readonly kind: string;
|
|
18
|
+
readonly reason?: string;
|
|
19
|
+
};
|
|
20
|
+
readonly disposition: {
|
|
21
|
+
readonly disposition: string;
|
|
22
|
+
readonly reason: string | null;
|
|
23
|
+
} | null;
|
|
24
|
+
readonly operation: OperationRead | null;
|
|
25
|
+
}
|
|
26
|
+
interface BridgeIdentity {
|
|
27
|
+
readonly commandId: string;
|
|
28
|
+
readonly transport: string;
|
|
29
|
+
}
|
|
30
|
+
export interface BridgeRequest extends ProtectedRequest, BridgeIdentity {
|
|
31
|
+
readonly runId: string;
|
|
32
|
+
}
|
|
33
|
+
export interface GateReceipt {
|
|
34
|
+
readonly kind: string;
|
|
35
|
+
readonly reason?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface GateOpening {
|
|
38
|
+
readonly runId: string;
|
|
39
|
+
readonly commandId: string;
|
|
40
|
+
readonly expectedRevision: number;
|
|
41
|
+
readonly gateId: string;
|
|
42
|
+
readonly kind: "question" | "approval";
|
|
43
|
+
readonly prompt: string;
|
|
44
|
+
readonly subject: string;
|
|
45
|
+
}
|
|
46
|
+
export interface WaitRegistration {
|
|
47
|
+
readonly runId: string;
|
|
48
|
+
readonly commandId: string;
|
|
49
|
+
readonly gateId: string;
|
|
50
|
+
}
|
|
51
|
+
export interface BridgeTiming {
|
|
52
|
+
readonly lookupTries: number;
|
|
53
|
+
readonly pollMilliseconds: number;
|
|
54
|
+
readonly retryMilliseconds: number;
|
|
55
|
+
}
|
|
56
|
+
export declare const bridgeTiming: BridgeTiming;
|
|
57
|
+
export interface BridgePorts {
|
|
58
|
+
readonly call: () => StepCall;
|
|
59
|
+
readonly run: (worldRunId: string) => Promise<{
|
|
60
|
+
readonly runId: string;
|
|
61
|
+
} | undefined>;
|
|
62
|
+
readonly timing?: BridgeTiming;
|
|
63
|
+
readonly stopped: AbortSignal;
|
|
64
|
+
readonly state: () => Promise<{
|
|
65
|
+
readonly runs: Readonly<Record<string, {
|
|
66
|
+
readonly status: string;
|
|
67
|
+
readonly revision: number;
|
|
68
|
+
} | undefined>>;
|
|
69
|
+
readonly gates: Readonly<Record<string, unknown>>;
|
|
70
|
+
}>;
|
|
71
|
+
readonly openGate: (opening: GateOpening) => Promise<GateReceipt>;
|
|
72
|
+
readonly registerWait: (wait: WaitRegistration) => Promise<GateReceipt>;
|
|
73
|
+
readonly requestEffect: (request: BridgeRequest) => Promise<BridgeReply>;
|
|
74
|
+
readonly operation: (operationId: string) => Promise<OperationRead | undefined>;
|
|
75
|
+
readonly document: (digest: string) => Promise<string | undefined>;
|
|
76
|
+
}
|
|
77
|
+
export declare function stepBridge(ports: BridgePorts): StepBridge;
|
|
78
|
+
export declare function registerStepBridge(bridge: StepBridge): () => void;
|
|
79
|
+
export {};
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
3
|
+
import { getStepMetadata, getWorkflowMetadata } from "workflow";
|
|
4
|
+
import { gateKey } from "../authority/gates.js";
|
|
5
|
+
import { stepBridgeKey, } from "../step-bridge.js";
|
|
6
|
+
export function sdkStepCall() {
|
|
7
|
+
const { stepId, attempt } = getStepMetadata();
|
|
8
|
+
return { worldRunId: getWorkflowMetadata().workflowRunId, stepId, attempt };
|
|
9
|
+
}
|
|
10
|
+
export const bridgeTiming = {
|
|
11
|
+
lookupTries: 250,
|
|
12
|
+
pollMilliseconds: 20,
|
|
13
|
+
retryMilliseconds: 1000,
|
|
14
|
+
};
|
|
15
|
+
const committed = ["accepted", "duplicate"];
|
|
16
|
+
const ended = ["failed", "stopped", "blocked", "cancelled"];
|
|
17
|
+
async function paused(hold, milliseconds) {
|
|
18
|
+
const { stopped } = hold.ports;
|
|
19
|
+
await delay(milliseconds, undefined, { signal: stopped }).catch(() => undefined);
|
|
20
|
+
if (stopped.aborted)
|
|
21
|
+
await new Promise(() => undefined);
|
|
22
|
+
}
|
|
23
|
+
function answered(reply) {
|
|
24
|
+
const { receipt, disposition, operation } = reply;
|
|
25
|
+
const busy = receipt.kind === "rejected" && receipt.reason === "service-busy";
|
|
26
|
+
if (receipt.kind === "failed" || busy)
|
|
27
|
+
return undefined;
|
|
28
|
+
if (!committed.includes(receipt.kind))
|
|
29
|
+
return { kind: "refused", reason: receipt.reason ?? receipt.kind };
|
|
30
|
+
if (disposition?.disposition === "refused")
|
|
31
|
+
return { kind: "refused", reason: disposition.reason ?? "refused" };
|
|
32
|
+
if (operation === null)
|
|
33
|
+
return undefined;
|
|
34
|
+
return { kind: "admitted", operationId: operation.operationId };
|
|
35
|
+
}
|
|
36
|
+
async function requested(hold, request) {
|
|
37
|
+
for (;;) {
|
|
38
|
+
await paused(hold, 0);
|
|
39
|
+
const answer = await hold.ports
|
|
40
|
+
.requestEffect(request)
|
|
41
|
+
.then(answered, () => undefined);
|
|
42
|
+
if (answer !== undefined)
|
|
43
|
+
return answer;
|
|
44
|
+
await paused(hold, hold.timing.retryMilliseconds);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function text(hold, digest) {
|
|
48
|
+
if (digest === null)
|
|
49
|
+
return null;
|
|
50
|
+
for (;;) {
|
|
51
|
+
const read = await hold.ports.document(digest).then((value) => ({ value: value ?? null }), () => undefined);
|
|
52
|
+
if (read !== undefined)
|
|
53
|
+
return read.value;
|
|
54
|
+
await paused(hold, hold.timing.retryMilliseconds);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async function outcome(hold, operation) {
|
|
58
|
+
const { operationId, status, reason, receipt, result } = operation;
|
|
59
|
+
if (status === "refused")
|
|
60
|
+
return { kind: "refused", reason: reason ?? "refused" };
|
|
61
|
+
const end = ended.find((kind) => kind === status);
|
|
62
|
+
if (end !== undefined)
|
|
63
|
+
return { kind: end, operationId, reason };
|
|
64
|
+
if (status !== "completed")
|
|
65
|
+
return undefined;
|
|
66
|
+
return {
|
|
67
|
+
kind: "completed",
|
|
68
|
+
operationId,
|
|
69
|
+
receipt,
|
|
70
|
+
result: await text(hold, result),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
async function settled(hold, operationId) {
|
|
74
|
+
for (;;) {
|
|
75
|
+
const operation = await hold.ports
|
|
76
|
+
.operation(operationId)
|
|
77
|
+
.catch(() => undefined);
|
|
78
|
+
const result = operation === undefined ? undefined : await outcome(hold, operation);
|
|
79
|
+
if (result !== undefined)
|
|
80
|
+
return result;
|
|
81
|
+
await paused(hold, operation === undefined
|
|
82
|
+
? hold.timing.retryMilliseconds
|
|
83
|
+
: hold.timing.pollMilliseconds);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async function located(hold, worldRunId) {
|
|
87
|
+
const tries = hold.timing.lookupTries;
|
|
88
|
+
for (let attempt = 1; attempt <= tries; attempt += 1) {
|
|
89
|
+
const world = await hold.ports.run(worldRunId);
|
|
90
|
+
if (world !== undefined || attempt === tries)
|
|
91
|
+
return world;
|
|
92
|
+
await paused(hold, hold.timing.pollMilliseconds);
|
|
93
|
+
}
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
async function inWork(hold, runId) {
|
|
97
|
+
for (;;) {
|
|
98
|
+
const state = await hold.ports.state().catch(() => undefined);
|
|
99
|
+
if (state !== undefined && state.runs[runId]?.status !== "queued")
|
|
100
|
+
return;
|
|
101
|
+
await paused(hold, state === undefined
|
|
102
|
+
? hold.timing.retryMilliseconds
|
|
103
|
+
: hold.timing.pollMilliseconds);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function transportOf(call) {
|
|
107
|
+
return `sdk:${call.stepId}`.replace(/[^A-Za-z0-9._:/-]/g, "-");
|
|
108
|
+
}
|
|
109
|
+
function identity(call, request) {
|
|
110
|
+
const transport = transportOf(call);
|
|
111
|
+
const scope = createHash("sha256")
|
|
112
|
+
.update(JSON.stringify(request.scope))
|
|
113
|
+
.digest("hex")
|
|
114
|
+
.slice(0, 16);
|
|
115
|
+
return { transport, commandId: `${transport}:${scope}` };
|
|
116
|
+
}
|
|
117
|
+
async function effect(hold, request) {
|
|
118
|
+
const call = hold.ports.call();
|
|
119
|
+
const world = await located(hold, call.worldRunId);
|
|
120
|
+
if (world === undefined)
|
|
121
|
+
return { kind: "unavailable", reason: "unknown-world-run" };
|
|
122
|
+
await inWork(hold, world.runId);
|
|
123
|
+
const answer = await requested(hold, {
|
|
124
|
+
...request,
|
|
125
|
+
...identity(call, request),
|
|
126
|
+
runId: world.runId,
|
|
127
|
+
});
|
|
128
|
+
if (answer.kind !== "admitted")
|
|
129
|
+
return answer;
|
|
130
|
+
return await settled(hold, answer.operationId);
|
|
131
|
+
}
|
|
132
|
+
function verdict(hold, receipt) {
|
|
133
|
+
if (receipt === undefined || receipt.kind === "failed")
|
|
134
|
+
return hold.timing.retryMilliseconds;
|
|
135
|
+
if (committed.includes(receipt.kind))
|
|
136
|
+
return "committed";
|
|
137
|
+
if (receipt.reason === "service-busy")
|
|
138
|
+
return hold.timing.retryMilliseconds;
|
|
139
|
+
if (receipt.reason === "stale-revision")
|
|
140
|
+
return hold.timing.pollMilliseconds;
|
|
141
|
+
return { kind: "refused", reason: receipt.reason ?? receipt.kind };
|
|
142
|
+
}
|
|
143
|
+
async function gateCommand(hold, send) {
|
|
144
|
+
for (;;) {
|
|
145
|
+
await paused(hold, 0);
|
|
146
|
+
const result = verdict(hold, await send().catch(() => undefined));
|
|
147
|
+
if (result === "committed")
|
|
148
|
+
return undefined;
|
|
149
|
+
if (typeof result !== "number")
|
|
150
|
+
return result;
|
|
151
|
+
await paused(hold, result);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
async function opening(hold, subject) {
|
|
155
|
+
const { runId, transport, request } = subject;
|
|
156
|
+
const { gateId, kind, prompt } = request;
|
|
157
|
+
const state = await hold.ports.state();
|
|
158
|
+
const run = state.runs[runId];
|
|
159
|
+
if (run === undefined)
|
|
160
|
+
return { kind: "rejected", reason: "unknown-run" };
|
|
161
|
+
if (Object.hasOwn(state.gates, gateKey(runId, gateId)))
|
|
162
|
+
return { kind: "duplicate" };
|
|
163
|
+
return await hold.ports.openGate({
|
|
164
|
+
runId,
|
|
165
|
+
commandId: `${transport}:open:${gateId}`,
|
|
166
|
+
expectedRevision: run.revision,
|
|
167
|
+
gateId,
|
|
168
|
+
kind,
|
|
169
|
+
prompt,
|
|
170
|
+
subject: `sha256:${createHash("sha256").update(prompt).digest("hex")}`,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
async function gate(hold, request) {
|
|
174
|
+
const call = hold.ports.call();
|
|
175
|
+
const world = await located(hold, call.worldRunId);
|
|
176
|
+
if (world === undefined)
|
|
177
|
+
return { kind: "unavailable", reason: "unknown-world-run" };
|
|
178
|
+
await inWork(hold, world.runId);
|
|
179
|
+
const subject = {
|
|
180
|
+
runId: world.runId,
|
|
181
|
+
transport: transportOf(call),
|
|
182
|
+
request,
|
|
183
|
+
};
|
|
184
|
+
const refusal = (await gateCommand(hold, () => opening(hold, subject))) ??
|
|
185
|
+
(await gateCommand(hold, () => hold.ports.registerWait({
|
|
186
|
+
runId: subject.runId,
|
|
187
|
+
commandId: `${subject.transport}:wait:${request.gateId}`,
|
|
188
|
+
gateId: request.gateId,
|
|
189
|
+
})));
|
|
190
|
+
return refusal ?? { kind: "opened", decisionId: request.gateId };
|
|
191
|
+
}
|
|
192
|
+
export function stepBridge(ports) {
|
|
193
|
+
const hold = { ports, timing: ports.timing ?? bridgeTiming };
|
|
194
|
+
return {
|
|
195
|
+
effect: (request) => effect(hold, request),
|
|
196
|
+
gate: (request) => gate(hold, request),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
export function registerStepBridge(bridge) {
|
|
200
|
+
const key = Symbol.for(stepBridgeKey);
|
|
201
|
+
Reflect.set(globalThis, key, bridge);
|
|
202
|
+
return () => {
|
|
203
|
+
Reflect.deleteProperty(globalThis, key);
|
|
204
|
+
};
|
|
205
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
interface ClaimEvent {
|
|
2
|
+
readonly eventType: string;
|
|
3
|
+
readonly correlationId?: string | undefined;
|
|
4
|
+
}
|
|
5
|
+
interface EventPage {
|
|
6
|
+
readonly data: readonly ClaimEvent[];
|
|
7
|
+
readonly cursor: string | null;
|
|
8
|
+
readonly hasMore: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface ClaimWorld {
|
|
11
|
+
readonly runs: {
|
|
12
|
+
readonly get: (runId: string, parameters: {
|
|
13
|
+
readonly resolveData: "none";
|
|
14
|
+
}) => Promise<{
|
|
15
|
+
readonly status: string;
|
|
16
|
+
}>;
|
|
17
|
+
};
|
|
18
|
+
readonly events: {
|
|
19
|
+
readonly list: (parameters: {
|
|
20
|
+
readonly runId: string;
|
|
21
|
+
readonly resolveData: "none";
|
|
22
|
+
readonly pagination: {
|
|
23
|
+
readonly limit: number;
|
|
24
|
+
readonly sortOrder: "asc";
|
|
25
|
+
readonly cursor?: string;
|
|
26
|
+
};
|
|
27
|
+
}) => Promise<EventPage>;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export declare function releaseStepClaims(dataDirectory: string, world: ClaimWorld): Promise<readonly string[]>;
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { readFile, readdir, rename, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
const claimName = /^(wrun_[0-9A-Z]+)-(step_[0-9A-Z]+)\.(created|terminal)$/;
|
|
4
|
+
const runEnds = ["completed", "failed", "cancelled"];
|
|
5
|
+
const stepEnds = ["step_completed", "step_failed"];
|
|
6
|
+
const endFields = ["output", "error", "completedAt"];
|
|
7
|
+
function claimOf(name) {
|
|
8
|
+
const [, runId, stepId, kind] = claimName.exec(name) ?? [];
|
|
9
|
+
if (runId === undefined || stepId === undefined)
|
|
10
|
+
return [];
|
|
11
|
+
return [
|
|
12
|
+
{ name, runId, stepId, kind: kind === "terminal" ? kind : "created" },
|
|
13
|
+
];
|
|
14
|
+
}
|
|
15
|
+
async function recorded(world, page) {
|
|
16
|
+
const { runId, cursor } = page;
|
|
17
|
+
const listed = await world.events.list({
|
|
18
|
+
runId,
|
|
19
|
+
resolveData: "none",
|
|
20
|
+
pagination: {
|
|
21
|
+
limit: 1000,
|
|
22
|
+
sortOrder: "asc",
|
|
23
|
+
...(cursor === null ? {} : { cursor }),
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
if (!listed.hasMore || listed.cursor === null)
|
|
27
|
+
return listed.data;
|
|
28
|
+
return [
|
|
29
|
+
...listed.data,
|
|
30
|
+
...(await recorded(world, { runId, cursor: listed.cursor })),
|
|
31
|
+
];
|
|
32
|
+
}
|
|
33
|
+
function proven(claim, events) {
|
|
34
|
+
const own = events
|
|
35
|
+
.filter((event) => event.correlationId === claim.stepId)
|
|
36
|
+
.map((event) => event.eventType);
|
|
37
|
+
if (claim.kind === "created")
|
|
38
|
+
return own.length > 0;
|
|
39
|
+
return own.some((type) => stepEnds.includes(type));
|
|
40
|
+
}
|
|
41
|
+
async function orphans(world, held) {
|
|
42
|
+
const run = await world.runs
|
|
43
|
+
.get(held.runId, { resolveData: "none" })
|
|
44
|
+
.catch(() => undefined);
|
|
45
|
+
if (run === undefined || runEnds.includes(run.status))
|
|
46
|
+
return [];
|
|
47
|
+
const events = await recorded(world, { runId: held.runId, cursor: null });
|
|
48
|
+
return held.claims.filter((claim) => !proven(claim, events));
|
|
49
|
+
}
|
|
50
|
+
function records(value) {
|
|
51
|
+
return typeof value === "object" && value !== null ? { ...value } : {};
|
|
52
|
+
}
|
|
53
|
+
async function reopened(path) {
|
|
54
|
+
const text = await readFile(path, "utf8").catch(() => undefined);
|
|
55
|
+
if (text === undefined)
|
|
56
|
+
return;
|
|
57
|
+
const parsed = JSON.parse(text);
|
|
58
|
+
const step = records(parsed);
|
|
59
|
+
if (step["status"] !== "completed" && step["status"] !== "failed")
|
|
60
|
+
return;
|
|
61
|
+
const kept = Object.entries(step).filter(([field]) => !endFields.includes(field));
|
|
62
|
+
const staged = `${path}.reopened`;
|
|
63
|
+
await writeFile(staged, JSON.stringify({ ...Object.fromEntries(kept), status: "running" }, null, 2));
|
|
64
|
+
await rename(staged, path);
|
|
65
|
+
}
|
|
66
|
+
async function reverted(dataDirectory, claim) {
|
|
67
|
+
const path = join(dataDirectory, "steps", `${claim.runId}-${claim.stepId}.json`);
|
|
68
|
+
if (claim.kind === "created")
|
|
69
|
+
await rm(path, { force: true });
|
|
70
|
+
if (claim.kind === "terminal")
|
|
71
|
+
await reopened(path);
|
|
72
|
+
}
|
|
73
|
+
export async function releaseStepClaims(dataDirectory, world) {
|
|
74
|
+
const folder = join(dataDirectory, ".locks", "steps");
|
|
75
|
+
const names = await readdir(folder).catch(() => []);
|
|
76
|
+
const held = Map.groupBy(names.flatMap(claimOf), (claim) => claim.runId);
|
|
77
|
+
const released = [];
|
|
78
|
+
for (const [runId, claims] of held)
|
|
79
|
+
for (const claim of await orphans(world, { runId, claims })) {
|
|
80
|
+
await reverted(dataDirectory, claim);
|
|
81
|
+
await rm(join(folder, claim.name), { force: true });
|
|
82
|
+
released.push(claim.name);
|
|
83
|
+
}
|
|
84
|
+
return released;
|
|
85
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type WorkflowHandler = (request: Request) => Promise<Response>;
|
|
2
|
+
export interface HostSettings {
|
|
3
|
+
readonly dataDirectory: string;
|
|
4
|
+
readonly concurrency: number;
|
|
5
|
+
readonly handler: WorkflowHandler;
|
|
6
|
+
}
|
|
7
|
+
export interface WorkflowHost {
|
|
8
|
+
readonly released: readonly string[];
|
|
9
|
+
readonly close: () => Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
export interface HostRefusal {
|
|
12
|
+
readonly kind: "refused";
|
|
13
|
+
readonly reason: string;
|
|
14
|
+
readonly detail: string;
|
|
15
|
+
}
|
|
16
|
+
export type HostOpening = {
|
|
17
|
+
readonly kind: "started";
|
|
18
|
+
readonly host: WorkflowHost;
|
|
19
|
+
} | HostRefusal;
|
|
20
|
+
export declare const hostBoundLimit = 64;
|
|
21
|
+
export declare function startHost(settings: HostSettings): Promise<HostOpening>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { getWorld } from "workflow/runtime";
|
|
2
|
+
import { releaseStepClaims } from "./step-claims.js";
|
|
3
|
+
const workflowQueue = "__wkf_workflow_";
|
|
4
|
+
export const hostBoundLimit = 64;
|
|
5
|
+
function direct(world) {
|
|
6
|
+
return ("registerHandler" in world && typeof world.registerHandler === "function");
|
|
7
|
+
}
|
|
8
|
+
function refused(reason, detail) {
|
|
9
|
+
return { kind: "refused", reason, detail };
|
|
10
|
+
}
|
|
11
|
+
function unsuitable(settings) {
|
|
12
|
+
const { concurrency, dataDirectory } = settings;
|
|
13
|
+
const bounded = Number.isSafeInteger(concurrency) &&
|
|
14
|
+
concurrency >= 1 &&
|
|
15
|
+
concurrency <= hostBoundLimit;
|
|
16
|
+
if (!bounded)
|
|
17
|
+
return refused("invalid-host-bound", String(concurrency));
|
|
18
|
+
if (process.env["WORKFLOW_TARGET_WORLD"] !== "local")
|
|
19
|
+
return refused("host-world", "WORKFLOW_TARGET_WORLD is not local");
|
|
20
|
+
if (process.env["WORKFLOW_LOCAL_DATA_DIR"] !== dataDirectory)
|
|
21
|
+
return refused("host-world", "WORKFLOW_LOCAL_DATA_DIR is not the setting");
|
|
22
|
+
if (process.env["WORKFLOW_LOCAL_QUEUE_CONCURRENCY"] !== String(concurrency))
|
|
23
|
+
return refused("host-bound", "WORKFLOW_LOCAL_QUEUE_CONCURRENCY is not the setting");
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
export async function startHost(settings) {
|
|
27
|
+
const refusal = unsuitable(settings);
|
|
28
|
+
if (refusal)
|
|
29
|
+
return refusal;
|
|
30
|
+
const world = await getWorld();
|
|
31
|
+
if (!direct(world))
|
|
32
|
+
return refused("host-world", "the World takes no handler in its process");
|
|
33
|
+
const released = await releaseStepClaims(settings.dataDirectory, world);
|
|
34
|
+
world.registerHandler(workflowQueue, settings.handler);
|
|
35
|
+
try {
|
|
36
|
+
await world.start?.();
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
await world.close?.();
|
|
40
|
+
return refused("host-start-failed", String(Reflect.get(Object(error), "message")));
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
kind: "started",
|
|
44
|
+
host: {
|
|
45
|
+
released,
|
|
46
|
+
close: async () => {
|
|
47
|
+
await world.close?.();
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type WorldReport, type WorldRun } from "../authority/reconciliation.ts";
|
|
2
|
+
import type { AuthorityState } from "../authority/transitions.ts";
|
|
3
|
+
export type ReconciledState = Pick<AuthorityState, "runs" | "intents" | "details" | "gates" | "commands">;
|
|
4
|
+
export interface WorkflowOutcome {
|
|
5
|
+
readonly kind: string;
|
|
6
|
+
readonly reason?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface ReconciliationPorts {
|
|
9
|
+
readonly state: () => Promise<ReconciledState>;
|
|
10
|
+
readonly submit: (command: Readonly<Record<string, unknown>>) => Promise<{
|
|
11
|
+
readonly kind: "accepted" | "duplicate" | "rejected" | "failed";
|
|
12
|
+
}>;
|
|
13
|
+
readonly runs: () => Promise<readonly WorldRun[]>;
|
|
14
|
+
readonly outcome: (receipt: string) => Promise<WorkflowOutcome | undefined>;
|
|
15
|
+
}
|
|
16
|
+
export interface Pass {
|
|
17
|
+
readonly sent: readonly string[];
|
|
18
|
+
readonly interrupted: boolean;
|
|
19
|
+
readonly reports: readonly WorldReport[];
|
|
20
|
+
readonly conflicts: readonly string[];
|
|
21
|
+
}
|
|
22
|
+
export declare function reconcileWorld(ports: ReconciliationPorts): Promise<Pass>;
|
|
23
|
+
export type LoopReport = WorldReport | {
|
|
24
|
+
readonly kind: "world-run-conflict";
|
|
25
|
+
readonly runId: string;
|
|
26
|
+
} | {
|
|
27
|
+
readonly kind: "world-reconciliation-failed";
|
|
28
|
+
readonly passes: number;
|
|
29
|
+
};
|
|
30
|
+
export declare const passFailureLimit = 3;
|
|
31
|
+
export interface WorldLoop {
|
|
32
|
+
readonly stop: () => Promise<void>;
|
|
33
|
+
readonly reports: () => readonly LoopReport[];
|
|
34
|
+
}
|
|
35
|
+
export declare function worldLoop(parts: ReconciliationPorts & {
|
|
36
|
+
readonly intervalMilliseconds: number;
|
|
37
|
+
}): WorldLoop;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
2
|
+
import { reconcile, } from "../authority/reconciliation.js";
|
|
3
|
+
async function withOutcome(ports, observed) {
|
|
4
|
+
const { state, world } = observed;
|
|
5
|
+
const ended = world.status === "completed" &&
|
|
6
|
+
state.runs[world.runId]?.status === "running";
|
|
7
|
+
if (!ended)
|
|
8
|
+
return world;
|
|
9
|
+
const read = await ports.outcome(world.receipt).then((outcome) => ({ outcome }), () => undefined);
|
|
10
|
+
if (read === undefined)
|
|
11
|
+
return { ...world, status: "unreadable" };
|
|
12
|
+
return read.outcome === undefined
|
|
13
|
+
? world
|
|
14
|
+
: {
|
|
15
|
+
...world,
|
|
16
|
+
outcome: read.outcome.kind,
|
|
17
|
+
...(read.outcome.reason === undefined
|
|
18
|
+
? {}
|
|
19
|
+
: { outcomeReason: read.outcome.reason }),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export async function reconcileWorld(ports) {
|
|
23
|
+
const listed = await ports.runs();
|
|
24
|
+
const state = await ports.state();
|
|
25
|
+
const runs = [];
|
|
26
|
+
for (const world of listed)
|
|
27
|
+
runs.push(await withOutcome(ports, { state, world }));
|
|
28
|
+
const { commands, reports, conflicts } = reconcile(state, runs);
|
|
29
|
+
const sent = [];
|
|
30
|
+
for (const command of commands) {
|
|
31
|
+
const receipt = await ports.submit(command);
|
|
32
|
+
sent.push(`${String(command["commandId"])} ${receipt.kind}`);
|
|
33
|
+
if (receipt.kind === "failed")
|
|
34
|
+
return { sent, interrupted: true, reports, conflicts };
|
|
35
|
+
}
|
|
36
|
+
return { sent, interrupted: false, reports, conflicts };
|
|
37
|
+
}
|
|
38
|
+
export const passFailureLimit = 3;
|
|
39
|
+
function reported(pass) {
|
|
40
|
+
return [
|
|
41
|
+
...pass.reports,
|
|
42
|
+
...pass.conflicts.map((runId) => ({
|
|
43
|
+
kind: "world-run-conflict",
|
|
44
|
+
runId,
|
|
45
|
+
})),
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
export function worldLoop(parts) {
|
|
49
|
+
const stopping = new AbortController();
|
|
50
|
+
let reports = [];
|
|
51
|
+
let failures = 0;
|
|
52
|
+
const cycle = async () => {
|
|
53
|
+
while (!stopping.signal.aborted) {
|
|
54
|
+
const pass = await reconcileWorld(parts).catch(() => undefined);
|
|
55
|
+
reports = pass === undefined ? reports : reported(pass);
|
|
56
|
+
failures = pass?.interrupted === false ? 0 : failures + 1;
|
|
57
|
+
await delay(parts.intervalMilliseconds, undefined, {
|
|
58
|
+
signal: stopping.signal,
|
|
59
|
+
}).catch(() => undefined);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
const running = cycle();
|
|
63
|
+
return {
|
|
64
|
+
stop: async () => {
|
|
65
|
+
stopping.abort();
|
|
66
|
+
await running;
|
|
67
|
+
},
|
|
68
|
+
reports: () => failures < passFailureLimit
|
|
69
|
+
? reports
|
|
70
|
+
: [
|
|
71
|
+
...reports,
|
|
72
|
+
{ kind: "world-reconciliation-failed", passes: failures },
|
|
73
|
+
],
|
|
74
|
+
};
|
|
75
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { WorldRun } from "../authority/reconciliation.ts";
|
|
2
|
+
import type { WorkflowOutcome } from "./world-reconciliation.ts";
|
|
3
|
+
export declare const runTag = "cloving.run";
|
|
4
|
+
export declare const operationTag = "cloving.operation";
|
|
5
|
+
export interface TaggedRun extends WorldRun {
|
|
6
|
+
readonly operationId: string | null;
|
|
7
|
+
readonly createdAt: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function taggedRuns(pageSize?: number): Promise<TaggedRun[]>;
|
|
10
|
+
export declare function workflowOutcome(receipt: string): Promise<WorkflowOutcome | undefined>;
|
|
11
|
+
export declare function cancelled(receipt: string): Promise<string>;
|
|
12
|
+
export declare function taggedRun(receipt: string): Promise<{
|
|
13
|
+
readonly runId: string;
|
|
14
|
+
} | undefined>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { getRun } from "workflow/api";
|
|
2
|
+
import { getWorld } from "workflow/runtime";
|
|
3
|
+
export const runTag = "cloving.run";
|
|
4
|
+
export const operationTag = "cloving.operation";
|
|
5
|
+
function tag(attributes, name) {
|
|
6
|
+
const value = Reflect.get(Object(attributes), name);
|
|
7
|
+
return typeof value === "string" ? value : null;
|
|
8
|
+
}
|
|
9
|
+
async function collected(world, page) {
|
|
10
|
+
const listed = await world.runs.list({
|
|
11
|
+
resolveData: "none",
|
|
12
|
+
pagination: {
|
|
13
|
+
limit: page.limit,
|
|
14
|
+
...(page.cursor === null ? {} : { cursor: page.cursor }),
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
const found = listed.data.flatMap((item) => {
|
|
18
|
+
const runId = tag(item.attributes, runTag);
|
|
19
|
+
if (runId === null)
|
|
20
|
+
return [];
|
|
21
|
+
return [
|
|
22
|
+
{
|
|
23
|
+
runId,
|
|
24
|
+
operationId: tag(item.attributes, operationTag),
|
|
25
|
+
receipt: item.runId,
|
|
26
|
+
status: item.status,
|
|
27
|
+
createdAt: item.createdAt.toISOString(),
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
});
|
|
31
|
+
if (!listed.hasMore || listed.cursor === null)
|
|
32
|
+
return found;
|
|
33
|
+
return [
|
|
34
|
+
...found,
|
|
35
|
+
...(await collected(world, { limit: page.limit, cursor: listed.cursor })),
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
export async function taggedRuns(pageSize = 200) {
|
|
39
|
+
return await collected(await getWorld(), { limit: pageSize, cursor: null });
|
|
40
|
+
}
|
|
41
|
+
export async function workflowOutcome(receipt) {
|
|
42
|
+
const value = await getRun(receipt).returnValue;
|
|
43
|
+
const kind = Reflect.get(Object(value), "kind");
|
|
44
|
+
if (typeof kind !== "string")
|
|
45
|
+
return undefined;
|
|
46
|
+
const reason = Reflect.get(Object(value), "reason");
|
|
47
|
+
return { kind, ...(typeof reason === "string" ? { reason } : {}) };
|
|
48
|
+
}
|
|
49
|
+
export async function cancelled(receipt) {
|
|
50
|
+
const run = getRun(receipt);
|
|
51
|
+
await run.cancel().catch(() => undefined);
|
|
52
|
+
return await run.status;
|
|
53
|
+
}
|
|
54
|
+
export async function taggedRun(receipt) {
|
|
55
|
+
const world = await getWorld();
|
|
56
|
+
const run = await world.runs
|
|
57
|
+
.get(receipt, { resolveData: "none" })
|
|
58
|
+
.catch(() => undefined);
|
|
59
|
+
const runId = tag(run?.attributes, runTag);
|
|
60
|
+
return runId === null ? undefined : { runId };
|
|
61
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Validation } from "./workflow-contracts.ts";
|
|
2
|
+
export declare function operationIdentity(value: unknown): Validation<string>;
|
|
3
|
+
export interface OperationScope {
|
|
4
|
+
readonly run: string;
|
|
5
|
+
readonly operation: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function operationScope(operationId: string): OperationScope | null;
|