cloving 0.3.19 → 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/.DS_Store +0 -0
- package/.aider.chat.history.md +0 -16978
- package/.aider.input.history +0 -15
- package/.aider.tags.cache.v3/cache.db +0 -0
- package/.aider.tags.cache.v3/cache.db-shm +0 -0
- package/.aider.tags.cache.v3/cache.db-wal +0 -0
- package/.cursorrules +0 -77
- package/.github/workflows/auto-release.yml +0 -83
- package/.github/workflows/ci.yml +0 -32
- package/.github/workflows/npm-publish.yml +0 -34
- package/.gitignore +0 -67
- package/.husky/_/.gitignore +0 -1
- package/.husky/_/applypatch-msg +0 -2
- package/.husky/_/commit-msg +0 -2
- package/.husky/_/h +0 -22
- package/.husky/_/husky.sh +0 -9
- package/.husky/_/post-applypatch +0 -2
- package/.husky/_/post-checkout +0 -2
- package/.husky/_/post-commit +0 -2
- package/.husky/_/post-merge +0 -2
- package/.husky/_/post-rewrite +0 -2
- package/.husky/_/pre-applypatch +0 -2
- package/.husky/_/pre-auto-gc +0 -2
- package/.husky/_/pre-commit +0 -2
- package/.husky/_/pre-merge-commit +0 -2
- package/.husky/_/pre-push +0 -2
- package/.husky/_/pre-rebase +0 -2
- package/.husky/_/prepare-commit-msg +0 -2
- package/.husky/pre-commit +0 -1
- package/.husky/pre-push +0 -1
- package/.prettierrc.json +0 -7
- package/.tool-versions +0 -2
- package/SECURITY.md +0 -15
- package/cloving.json +0 -67
- 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 -134
- 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 -64
- 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
- package/jest.config.js +0 -11
- package/src/cloving_gpt/adapters/azureopenai.ts +0 -83
- package/src/cloving_gpt/adapters/claude.ts +0 -140
- package/src/cloving_gpt/adapters/gemini.ts +0 -146
- package/src/cloving_gpt/adapters/index.ts +0 -43
- package/src/cloving_gpt/adapters/mistral.ts +0 -142
- package/src/cloving_gpt/adapters/ollama.ts +0 -136
- package/src/cloving_gpt/adapters/openai.ts +0 -113
- package/src/cloving_gpt/index.ts +0 -229
- package/src/commands/chat.ts +0 -12
- package/src/commands/config.ts +0 -192
- package/src/commands/generate/code.ts +0 -18
- package/src/commands/generate/commit.ts +0 -9
- package/src/commands/generate/context.ts +0 -93
- package/src/commands/generate/docs.ts +0 -9
- package/src/commands/generate/review.ts +0 -9
- package/src/commands/generate/shell.ts +0 -9
- package/src/commands/generate/unit_tests.ts +0 -9
- package/src/commands/init.ts +0 -9
- package/src/commands/models.ts +0 -21
- package/src/commands/proxy.ts +0 -9
- package/src/commands/tokens.ts +0 -82
- package/src/index.ts +0 -197
- package/src/managers/BlockManager.ts +0 -126
- package/src/managers/ChatManager.ts +0 -755
- package/src/managers/ChunkManager.ts +0 -31
- package/src/managers/CodeManager.ts +0 -226
- package/src/managers/CommitManager.ts +0 -71
- package/src/managers/DocsManager.ts +0 -101
- package/src/managers/InitManager.ts +0 -263
- package/src/managers/ProxyManager.ts +0 -240
- package/src/managers/ReviewManager.ts +0 -154
- package/src/managers/ShellManager.ts +0 -172
- package/src/managers/StreamManager.ts +0 -353
- package/src/managers/UnitTestManager.ts +0 -293
- package/src/utils/config_utils.ts +0 -271
- package/src/utils/git_utils.ts +0 -230
- package/src/utils/model_utils.ts +0 -3
- package/src/utils/prompt_utils.ts +0 -375
- package/src/utils/prompts/CODEGEN_COULDNT_APPLY.md +0 -5
- package/src/utils/prompts/CODEGEN_EXAMPLES.md +0 -82
- package/src/utils/prompts/CODEGEN_INSTRUCTIONS.md +0 -43
- package/src/utils/prompts/DOCS_INSTRUCTIONS.md +0 -9
- package/src/utils/prompts/INIT_INSTRUCTIONS.md +0 -132
- package/src/utils/prompts/REVIEW_INSTRUCTIONS.md +0 -49
- package/src/utils/prompts/SHELL_INSTRUCTIONS.md +0 -15
- package/src/utils/prompts/SPECIAL_FILES.md +0 -66
- package/src/utils/prompts/index.ts +0 -37
- package/src/utils/string_utils.ts +0 -552
- package/src/utils/types.ts +0 -127
- package/tests/commands/generate/unit_tests.test.ts +0 -27
- package/tests/utils/git_utils.test.ts +0 -116
- package/tests/utils/model_utils.test.ts +0 -27
- package/tests/utils/prompt_utils.test.ts +0 -33
- package/tests/utils/string_utils.test.ts +0 -560
- package/tsconfig.json +0 -14
- package/yarn.lock +0 -5823
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const component = /^[A-Za-z0-9._:/-]{1,128}$/;
|
|
2
|
+
export function operationIdentity(value) {
|
|
3
|
+
const scope = fields(value);
|
|
4
|
+
const round = scope["round"];
|
|
5
|
+
const stage = optionalStage(scope["stage"]);
|
|
6
|
+
const key = scope["key"];
|
|
7
|
+
const required = [scope["run"], scope["phase"], scope["operation"]];
|
|
8
|
+
if (typeof round !== "number" ||
|
|
9
|
+
!Number.isSafeInteger(round) ||
|
|
10
|
+
round < 0 ||
|
|
11
|
+
stage === undefined ||
|
|
12
|
+
!required.every(isComponent) ||
|
|
13
|
+
(key !== undefined && !isComponent(key)))
|
|
14
|
+
return { kind: "invalid", reason: "invalid-operation-scope" };
|
|
15
|
+
return {
|
|
16
|
+
kind: "valid",
|
|
17
|
+
value: JSON.stringify([
|
|
18
|
+
"cloving-operation",
|
|
19
|
+
round,
|
|
20
|
+
...required,
|
|
21
|
+
stage,
|
|
22
|
+
key ?? null,
|
|
23
|
+
]),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function optionalStage(value) {
|
|
27
|
+
if (value === undefined)
|
|
28
|
+
return null;
|
|
29
|
+
const stage = fields(value);
|
|
30
|
+
const [id, visit, branch] = [stage["id"], stage["visit"], stage["branch"]];
|
|
31
|
+
if (!isComponent(id) || !isComponent(visit) || !isComponent(branch))
|
|
32
|
+
return undefined;
|
|
33
|
+
return [id, visit, branch];
|
|
34
|
+
}
|
|
35
|
+
function isComponent(value) {
|
|
36
|
+
return typeof value === "string" && component.test(value);
|
|
37
|
+
}
|
|
38
|
+
function fields(value) {
|
|
39
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
40
|
+
return {};
|
|
41
|
+
return Object.fromEntries(Object.entries(value));
|
|
42
|
+
}
|
|
43
|
+
export function operationScope(operationId) {
|
|
44
|
+
const [marker, , run, , operation] = parsedList(operationId);
|
|
45
|
+
if (marker !== "cloving-operation")
|
|
46
|
+
return null;
|
|
47
|
+
if (!isComponent(run) || !isComponent(operation))
|
|
48
|
+
return null;
|
|
49
|
+
return { run, operation };
|
|
50
|
+
}
|
|
51
|
+
function parsedList(text) {
|
|
52
|
+
try {
|
|
53
|
+
const value = JSON.parse(text);
|
|
54
|
+
return Array.isArray(value) ? value : [];
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export declare const protocolVersion = 1;
|
|
2
|
+
export declare const maximumFrameBytes = 1048576;
|
|
3
|
+
export type Fields = Readonly<Record<string, unknown>>;
|
|
4
|
+
export interface ServiceRequest {
|
|
5
|
+
readonly operation: string;
|
|
6
|
+
readonly parameters: Fields;
|
|
7
|
+
}
|
|
8
|
+
export interface ServiceError extends Fields {
|
|
9
|
+
readonly code: string;
|
|
10
|
+
readonly detail: string;
|
|
11
|
+
}
|
|
12
|
+
export type Reply = {
|
|
13
|
+
readonly kind: "result";
|
|
14
|
+
readonly result: Fields;
|
|
15
|
+
} | {
|
|
16
|
+
readonly kind: "error";
|
|
17
|
+
readonly error: ServiceError;
|
|
18
|
+
};
|
|
19
|
+
export type ParsedRequest = {
|
|
20
|
+
readonly kind: "request";
|
|
21
|
+
readonly request: ServiceRequest;
|
|
22
|
+
} | {
|
|
23
|
+
readonly kind: "error";
|
|
24
|
+
readonly error: ServiceError;
|
|
25
|
+
};
|
|
26
|
+
export type ReplyLine = Reply | {
|
|
27
|
+
readonly kind: "event";
|
|
28
|
+
readonly event: Fields;
|
|
29
|
+
};
|
|
30
|
+
export declare function record(value: unknown): Fields | undefined;
|
|
31
|
+
export declare function parseRequest(line: string): ParsedRequest;
|
|
32
|
+
export declare function requestLine(request: ServiceRequest): string;
|
|
33
|
+
export declare function replyLine(reply: Reply): string;
|
|
34
|
+
export declare function eventLine(event: Fields): string;
|
|
35
|
+
export declare function parseReplyLine(line: string): ReplyLine | undefined;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export const protocolVersion = 1;
|
|
2
|
+
export const maximumFrameBytes = 1_048_576;
|
|
3
|
+
export function record(value) {
|
|
4
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
5
|
+
return undefined;
|
|
6
|
+
return Object.fromEntries(Object.entries(value));
|
|
7
|
+
}
|
|
8
|
+
function decoded(line) {
|
|
9
|
+
try {
|
|
10
|
+
return JSON.parse(line);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function invalid(detail) {
|
|
17
|
+
return { kind: "error", error: { code: "invalid-request", detail } };
|
|
18
|
+
}
|
|
19
|
+
export function parseRequest(line) {
|
|
20
|
+
const fields = record(decoded(line));
|
|
21
|
+
if (fields === undefined)
|
|
22
|
+
return invalid("The request is not a JSON object.");
|
|
23
|
+
if (fields["protocol"] !== protocolVersion)
|
|
24
|
+
return {
|
|
25
|
+
kind: "error",
|
|
26
|
+
error: {
|
|
27
|
+
code: "service-incompatible",
|
|
28
|
+
detail: `The service uses protocol ${String(protocolVersion)}.`,
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
const { operation } = fields;
|
|
32
|
+
const parameters = record(fields["parameters"]);
|
|
33
|
+
if (typeof operation !== "string" || parameters === undefined)
|
|
34
|
+
return invalid("The request needs an operation and a parameters object.");
|
|
35
|
+
return { kind: "request", request: { operation, parameters } };
|
|
36
|
+
}
|
|
37
|
+
export function requestLine(request) {
|
|
38
|
+
return `${JSON.stringify({ protocol: protocolVersion, ...request })}\n`;
|
|
39
|
+
}
|
|
40
|
+
export function replyLine(reply) {
|
|
41
|
+
return reply.kind === "result"
|
|
42
|
+
? `${JSON.stringify({ ok: true, result: reply.result })}\n`
|
|
43
|
+
: `${JSON.stringify({ ok: false, error: reply.error })}\n`;
|
|
44
|
+
}
|
|
45
|
+
export function eventLine(event) {
|
|
46
|
+
return `${JSON.stringify({ event })}\n`;
|
|
47
|
+
}
|
|
48
|
+
export function parseReplyLine(line) {
|
|
49
|
+
const fields = record(decoded(line));
|
|
50
|
+
if (fields === undefined)
|
|
51
|
+
return undefined;
|
|
52
|
+
const event = record(fields["event"]);
|
|
53
|
+
if (event !== undefined)
|
|
54
|
+
return { kind: "event", event };
|
|
55
|
+
const result = record(fields["result"]);
|
|
56
|
+
if (fields["ok"] === true && result !== undefined)
|
|
57
|
+
return { kind: "result", result };
|
|
58
|
+
const error = record(fields["error"]);
|
|
59
|
+
const code = error?.["code"];
|
|
60
|
+
const detail = error?.["detail"];
|
|
61
|
+
if (typeof code !== "string" || typeof detail !== "string")
|
|
62
|
+
return undefined;
|
|
63
|
+
return { kind: "error", error: { ...error, code, detail } };
|
|
64
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function collectResources(root: string, paths: readonly string[]): Promise<Readonly<Record<string, string>>>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { lstat, readFile, realpath } from "node:fs/promises";
|
|
3
|
+
import { isAbsolute, join, relative, sep } from "node:path";
|
|
4
|
+
export async function collectResources(root, paths) {
|
|
5
|
+
const base = await realpath(root);
|
|
6
|
+
const entries = [];
|
|
7
|
+
for (const path of paths) {
|
|
8
|
+
const digest = await resourceDigest(base, path);
|
|
9
|
+
if (digest !== null)
|
|
10
|
+
entries.push([path, digest]);
|
|
11
|
+
}
|
|
12
|
+
return Object.fromEntries(entries);
|
|
13
|
+
}
|
|
14
|
+
async function resourceDigest(base, path) {
|
|
15
|
+
if (isAbsolute(path))
|
|
16
|
+
return null;
|
|
17
|
+
const file = await realpath(join(base, path)).catch(() => null);
|
|
18
|
+
if (file === null)
|
|
19
|
+
return null;
|
|
20
|
+
const inside = relative(base, file);
|
|
21
|
+
if (inside === ".." || inside.startsWith(`..${sep}`) || isAbsolute(inside))
|
|
22
|
+
return null;
|
|
23
|
+
if (!(await lstat(file)).isFile())
|
|
24
|
+
return null;
|
|
25
|
+
const bytes = await readFile(file).catch(() => null);
|
|
26
|
+
if (bytes === null)
|
|
27
|
+
return null;
|
|
28
|
+
return createHash("sha256").update(bytes).digest("hex");
|
|
29
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface ChangeWait {
|
|
2
|
+
readonly after: number;
|
|
3
|
+
readonly milliseconds: number;
|
|
4
|
+
}
|
|
5
|
+
export interface ChangeSignal {
|
|
6
|
+
readonly next: (wait: ChangeWait) => Promise<void>;
|
|
7
|
+
readonly close: () => void;
|
|
8
|
+
}
|
|
9
|
+
type Subscribe = (listener: (sequence: number) => void) => () => void;
|
|
10
|
+
export declare function changeSignal(subscribe: Subscribe): ChangeSignal;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export function changeSignal(subscribe) {
|
|
2
|
+
const waiting = new Set();
|
|
3
|
+
const seen = { latest: -1, closed: false };
|
|
4
|
+
const wake = () => {
|
|
5
|
+
for (const settle of [...waiting])
|
|
6
|
+
settle();
|
|
7
|
+
};
|
|
8
|
+
const unsubscribe = subscribe((sequence) => {
|
|
9
|
+
seen.latest = Math.max(seen.latest, sequence);
|
|
10
|
+
wake();
|
|
11
|
+
});
|
|
12
|
+
return {
|
|
13
|
+
next: ({ after, milliseconds }) => {
|
|
14
|
+
if (seen.closed || seen.latest > after)
|
|
15
|
+
return Promise.resolve();
|
|
16
|
+
return new Promise((settle) => {
|
|
17
|
+
const done = () => {
|
|
18
|
+
clearTimeout(timer);
|
|
19
|
+
waiting.delete(done);
|
|
20
|
+
settle();
|
|
21
|
+
};
|
|
22
|
+
const timer = setTimeout(done, milliseconds);
|
|
23
|
+
waiting.add(done);
|
|
24
|
+
});
|
|
25
|
+
},
|
|
26
|
+
close: () => {
|
|
27
|
+
seen.closed = true;
|
|
28
|
+
unsubscribe();
|
|
29
|
+
wake();
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { StoredState } from "../broker/actor/authority.ts";
|
|
2
|
+
import type { Fields, Reply } from "../protocol.ts";
|
|
3
|
+
import { type ServiceContext } from "./replies.ts";
|
|
4
|
+
export declare function feedbackOf(context: ServiceContext, scope: {
|
|
5
|
+
readonly state: StoredState;
|
|
6
|
+
readonly runId: string;
|
|
7
|
+
}): Promise<readonly Fields[]>;
|
|
8
|
+
export declare function questions(context: ServiceContext, parameters: Fields): Promise<Reply>;
|
|
9
|
+
export declare function decision(context: ServiceContext, parameters: Fields): Promise<Reply>;
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { continues, gateKey } from "../authority/gates.js";
|
|
2
|
+
import { gateContinuation } from "../authority/reduction.js";
|
|
3
|
+
import { documentDigest } from "../broker/decision-restore.js";
|
|
4
|
+
import { committed, failed, invalidRequest, isIdentifier, publicReceipt, rejection, result, wholeNumber, } from "./replies.js";
|
|
5
|
+
const decisions = {
|
|
6
|
+
answer: "answered",
|
|
7
|
+
approve: "approved",
|
|
8
|
+
deny: "denied",
|
|
9
|
+
};
|
|
10
|
+
const feedbackBytes = 8_000;
|
|
11
|
+
const commands = {
|
|
12
|
+
question: ["answer"],
|
|
13
|
+
approval: ["approve", "deny"],
|
|
14
|
+
};
|
|
15
|
+
function decisionId(gate) {
|
|
16
|
+
return `${gate.runId}/${gate.gateId}`;
|
|
17
|
+
}
|
|
18
|
+
function label(gate) {
|
|
19
|
+
return gate.label === null ? null : `Q${String(gate.label)}`;
|
|
20
|
+
}
|
|
21
|
+
function typed(state) {
|
|
22
|
+
return Object.values(state.gates)
|
|
23
|
+
.filter((gate) => gate.kind !== "untyped")
|
|
24
|
+
.sort((left, right) => left.openedSequence - right.openedSequence);
|
|
25
|
+
}
|
|
26
|
+
function pending(state) {
|
|
27
|
+
return typed(state).filter((gate) => gate.outcome === null &&
|
|
28
|
+
["waiting_gate", "paused"].includes(state.runs[gate.runId]?.status ?? ""));
|
|
29
|
+
}
|
|
30
|
+
export async function feedbackOf(context, scope) {
|
|
31
|
+
const denied = Object.values(scope.state.gates)
|
|
32
|
+
.filter((gate) => gate.runId === scope.runId &&
|
|
33
|
+
gate.outcome?.decision === "denied" &&
|
|
34
|
+
gate.outcome.answer !== null)
|
|
35
|
+
.sort((left, right) => left.openedSequence - right.openedSequence);
|
|
36
|
+
const shown = [];
|
|
37
|
+
for (const gate of denied) {
|
|
38
|
+
const text = await context.authority.queries.document(gate.outcome?.answer ?? "");
|
|
39
|
+
shown.push({
|
|
40
|
+
decisionId: `${gate.runId}/${gate.gateId}`,
|
|
41
|
+
text: text ?? "",
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return shown;
|
|
45
|
+
}
|
|
46
|
+
async function described(context, shown) {
|
|
47
|
+
const { state, gate } = shown;
|
|
48
|
+
const { queries } = context.authority;
|
|
49
|
+
const opened = await queries.eventsAfter({
|
|
50
|
+
after: gate.openedSequence - 1,
|
|
51
|
+
limit: 1,
|
|
52
|
+
});
|
|
53
|
+
return {
|
|
54
|
+
decisionId: decisionId(gate),
|
|
55
|
+
label: label(gate),
|
|
56
|
+
type: gate.kind,
|
|
57
|
+
runId: gate.runId,
|
|
58
|
+
gateId: gate.gateId,
|
|
59
|
+
prompt: (await queries.document(gate.prompt ?? "")) ?? "",
|
|
60
|
+
allowed: commands[gate.kind] ?? [],
|
|
61
|
+
revision: gate.revision,
|
|
62
|
+
generation: gate.generation,
|
|
63
|
+
subjectDigest: gate.subject,
|
|
64
|
+
openedAt: opened.events[0]?.recordedAt ?? "",
|
|
65
|
+
expiresAt: gate.expiresAt,
|
|
66
|
+
context: [],
|
|
67
|
+
feedback: await feedbackOf(context, { state, runId: gate.runId }),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export async function questions(context, parameters) {
|
|
71
|
+
const { runId } = parameters;
|
|
72
|
+
const state = await context.authority.state();
|
|
73
|
+
const listed = pending(state).filter((gate) => runId === undefined || gate.runId === runId);
|
|
74
|
+
const views = [];
|
|
75
|
+
for (const gate of listed)
|
|
76
|
+
views.push(await described(context, { state, gate }));
|
|
77
|
+
return result("decision-list", { decisions: views });
|
|
78
|
+
}
|
|
79
|
+
function referenced(gates, reference) {
|
|
80
|
+
const matches = [
|
|
81
|
+
(gate) => decisionId(gate) === reference,
|
|
82
|
+
(gate) => label(gate) === reference,
|
|
83
|
+
(gate) => gate.runId === reference,
|
|
84
|
+
].map((matcher) => gates.filter(matcher));
|
|
85
|
+
return matches.find((found) => found.length > 0) ?? [];
|
|
86
|
+
}
|
|
87
|
+
function refusedTarget(code, extra) {
|
|
88
|
+
return { kind: "refused", reply: failed(code, extra) };
|
|
89
|
+
}
|
|
90
|
+
function target(state, request) {
|
|
91
|
+
const { reference, command } = request;
|
|
92
|
+
const open = referenced(pending(state), reference);
|
|
93
|
+
if (open.length === 0)
|
|
94
|
+
return refusedTarget(referenced(typed(state), reference).length > 0
|
|
95
|
+
? "decision-not-pending"
|
|
96
|
+
: "unknown-decision", { detail: `No pending decision matches ${reference}.` });
|
|
97
|
+
const allowing = open.filter((gate) => commands[gate.kind]?.includes(command));
|
|
98
|
+
const [gate] = allowing;
|
|
99
|
+
if (gate === undefined)
|
|
100
|
+
return refusedTarget("decision-not-allowed", {
|
|
101
|
+
detail: `The decision does not allow the command ${command}.`,
|
|
102
|
+
});
|
|
103
|
+
if (allowing.length > 1)
|
|
104
|
+
return refusedTarget("ambiguous-decision", {
|
|
105
|
+
detail: "The reference matches more than one pending decision.",
|
|
106
|
+
candidates: allowing.map(decisionId),
|
|
107
|
+
});
|
|
108
|
+
return { kind: "gate", gate };
|
|
109
|
+
}
|
|
110
|
+
function validText(command, text) {
|
|
111
|
+
const given = typeof text === "string" && text.trim().length > 0;
|
|
112
|
+
if (command === "answer")
|
|
113
|
+
return given;
|
|
114
|
+
if (command === "deny")
|
|
115
|
+
return given || text === undefined || text === null;
|
|
116
|
+
return text === undefined || text === null;
|
|
117
|
+
}
|
|
118
|
+
function textLimit(context, command) {
|
|
119
|
+
return command === "deny"
|
|
120
|
+
? { bytes: feedbackBytes, name: "A feedback text" }
|
|
121
|
+
: { bytes: context.textBytes, name: "An answer" };
|
|
122
|
+
}
|
|
123
|
+
function decisionRequest(parameters) {
|
|
124
|
+
const { command, reference, expectedRevision, generation } = parameters;
|
|
125
|
+
const { subjectDigest, commandId } = parameters;
|
|
126
|
+
const text = parameters["text"] ?? null;
|
|
127
|
+
if (typeof command !== "string" ||
|
|
128
|
+
!Object.hasOwn(decisions, command) ||
|
|
129
|
+
typeof reference !== "string" ||
|
|
130
|
+
!wholeNumber(expectedRevision, 1) ||
|
|
131
|
+
!wholeNumber(generation, 1) ||
|
|
132
|
+
!isIdentifier(subjectDigest) ||
|
|
133
|
+
!isIdentifier(commandId) ||
|
|
134
|
+
!validText(command, text))
|
|
135
|
+
return undefined;
|
|
136
|
+
return {
|
|
137
|
+
command,
|
|
138
|
+
reference,
|
|
139
|
+
text,
|
|
140
|
+
expectedRevision,
|
|
141
|
+
generation,
|
|
142
|
+
subjectDigest,
|
|
143
|
+
commandId,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
async function located(context, request) {
|
|
147
|
+
const { commandId, text } = request;
|
|
148
|
+
const limit = textLimit(context, request.command);
|
|
149
|
+
if (text !== null && Buffer.byteLength(text) > limit.bytes)
|
|
150
|
+
return refusedTarget("input-too-large", {
|
|
151
|
+
commandId,
|
|
152
|
+
detail: `${limit.name} has at most ${String(limit.bytes)} bytes.`,
|
|
153
|
+
});
|
|
154
|
+
const existing = await context.authority.queries.receipt(commandId);
|
|
155
|
+
if (existing === undefined)
|
|
156
|
+
return target(await context.authority.state(), request);
|
|
157
|
+
const { gateId } = existing.command;
|
|
158
|
+
if (existing.command.kind !== "decide-gate" || gateId === undefined)
|
|
159
|
+
return refusedTarget("conflicting-command", {
|
|
160
|
+
commandId,
|
|
161
|
+
detail: "The command ID is known with a different request.",
|
|
162
|
+
});
|
|
163
|
+
return { kind: "known", runId: existing.runId, gateId };
|
|
164
|
+
}
|
|
165
|
+
export async function decision(context, parameters) {
|
|
166
|
+
const request = decisionRequest(parameters);
|
|
167
|
+
if (request === undefined)
|
|
168
|
+
return invalidRequest("The decision request is not valid.");
|
|
169
|
+
const found = await located(context, request);
|
|
170
|
+
if (found.kind === "refused")
|
|
171
|
+
return found.reply;
|
|
172
|
+
const { runId, gateId } = found.kind === "gate" ? found.gate : found;
|
|
173
|
+
const { commandId, text } = request;
|
|
174
|
+
const receipt = await context.gateway.execute({
|
|
175
|
+
principal: "operator",
|
|
176
|
+
command: {
|
|
177
|
+
kind: "decide-gate",
|
|
178
|
+
commandId,
|
|
179
|
+
runId,
|
|
180
|
+
gateId,
|
|
181
|
+
decision: decisions[request.command],
|
|
182
|
+
expectedRevision: request.expectedRevision,
|
|
183
|
+
generation: request.generation,
|
|
184
|
+
subject: request.subjectDigest,
|
|
185
|
+
...(text === null ? {} : { answer: documentDigest(text) }),
|
|
186
|
+
},
|
|
187
|
+
documents: text === null ? [] : [text],
|
|
188
|
+
});
|
|
189
|
+
if (!committed(receipt)) {
|
|
190
|
+
const state = await context.authority.state();
|
|
191
|
+
return rejection(receipt, {
|
|
192
|
+
commandId,
|
|
193
|
+
runId,
|
|
194
|
+
currentRevision: state.gates[gateKey(runId, gateId)]?.revision ?? null,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
return recorded(context, {
|
|
198
|
+
commandId,
|
|
199
|
+
runId,
|
|
200
|
+
gateId,
|
|
201
|
+
replayed: receipt.kind === "duplicate",
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
async function continuationState(context, decided) {
|
|
205
|
+
const { gate, run } = decided;
|
|
206
|
+
if (!continues(gate))
|
|
207
|
+
return "held";
|
|
208
|
+
const { operationId } = gateContinuation(gate);
|
|
209
|
+
const operation = (await context.authority.operations()).find((item) => item.operationId === operationId);
|
|
210
|
+
if (operation?.deliveries.some((delivery) => delivery.outcome === "sent"))
|
|
211
|
+
return "admitted";
|
|
212
|
+
const deliverable = operation?.releasedSequence === null && run.status === "running";
|
|
213
|
+
return deliverable ? "admitted" : "held";
|
|
214
|
+
}
|
|
215
|
+
async function recorded(context, outcome) {
|
|
216
|
+
const { commandId, runId, gateId } = outcome;
|
|
217
|
+
const stored = await context.authority.queries.receipt(commandId);
|
|
218
|
+
const state = await context.authority.state();
|
|
219
|
+
const gate = state.gates[gateKey(runId, gateId)];
|
|
220
|
+
const run = state.runs[runId];
|
|
221
|
+
if (stored === undefined || gate === undefined || run === undefined)
|
|
222
|
+
return failed("authority-unavailable", { commandId, runId });
|
|
223
|
+
return result("decision-recorded", {
|
|
224
|
+
decisionId: decisionId(gate),
|
|
225
|
+
runId,
|
|
226
|
+
decision: gate.outcome?.decision ?? null,
|
|
227
|
+
commandId,
|
|
228
|
+
replayed: outcome.replayed,
|
|
229
|
+
receipt: publicReceipt(stored),
|
|
230
|
+
run: { state: run.status, revision: run.revision },
|
|
231
|
+
continuation: await continuationState(context, { gate, run }),
|
|
232
|
+
});
|
|
233
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Fields, Reply } from "../protocol.ts";
|
|
2
|
+
import { type ServiceContext } from "./replies.ts";
|
|
3
|
+
export interface Connection {
|
|
4
|
+
readonly send: (events: readonly Fields[]) => Promise<boolean>;
|
|
5
|
+
readonly closed: () => boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function events(context: ServiceContext, request: {
|
|
8
|
+
readonly parameters: Fields;
|
|
9
|
+
readonly connection: Connection;
|
|
10
|
+
}): Promise<Reply | undefined>;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
2
|
+
import { failed, invalidRequest, isIdentifier, result, wholeNumber, } from "./replies.js";
|
|
3
|
+
function cursor(parameters) {
|
|
4
|
+
const { runId } = parameters;
|
|
5
|
+
const after = parameters["after"] ?? 0;
|
|
6
|
+
const limit = parameters["limit"] ?? 100;
|
|
7
|
+
if (!wholeNumber(after, 0) ||
|
|
8
|
+
!wholeNumber(limit, 1) ||
|
|
9
|
+
limit > 1000 ||
|
|
10
|
+
(runId !== undefined && typeof runId !== "string"))
|
|
11
|
+
return undefined;
|
|
12
|
+
return { after, limit, ...(runId === undefined ? {} : { runId }) };
|
|
13
|
+
}
|
|
14
|
+
function published(page) {
|
|
15
|
+
return page.events.map((event) => ({ schemaVersion: 1, ...event }));
|
|
16
|
+
}
|
|
17
|
+
function gap(after, page) {
|
|
18
|
+
return failed("event-gap", {
|
|
19
|
+
detail: `The service has no events after sequence ${String(after)}.`,
|
|
20
|
+
after,
|
|
21
|
+
earliestAvailable: page.earliest,
|
|
22
|
+
latestSequence: page.latest,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
async function followed(context, stream) {
|
|
26
|
+
const { connection } = stream;
|
|
27
|
+
let { after } = stream.start;
|
|
28
|
+
while (!connection.closed()) {
|
|
29
|
+
const page = await context.authority.queries.eventsAfter({
|
|
30
|
+
...stream.start,
|
|
31
|
+
after,
|
|
32
|
+
});
|
|
33
|
+
if (!(await connection.send(published(page))))
|
|
34
|
+
return undefined;
|
|
35
|
+
after = page.events.at(-1)?.sequence ?? after;
|
|
36
|
+
if (page.events.length === 0)
|
|
37
|
+
await changed(context, page.latest);
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
function changed(context, latest) {
|
|
42
|
+
const milliseconds = context.followMilliseconds;
|
|
43
|
+
return context.changed === undefined
|
|
44
|
+
? delay(milliseconds)
|
|
45
|
+
: context.changed({ after: latest, milliseconds });
|
|
46
|
+
}
|
|
47
|
+
async function known(context, runId) {
|
|
48
|
+
if (!isIdentifier(runId))
|
|
49
|
+
return false;
|
|
50
|
+
return (await context.authority.state()).runs[runId] !== undefined;
|
|
51
|
+
}
|
|
52
|
+
export async function events(context, request) {
|
|
53
|
+
const start = cursor(request.parameters);
|
|
54
|
+
if (start === undefined)
|
|
55
|
+
return invalidRequest("The events request is not valid.");
|
|
56
|
+
if (start.runId !== undefined && !(await known(context, start.runId)))
|
|
57
|
+
return failed("unknown-run", {
|
|
58
|
+
runId: start.runId,
|
|
59
|
+
detail: `No run has the ID ${start.runId}.`,
|
|
60
|
+
});
|
|
61
|
+
const page = await context.authority.queries.eventsAfter(start);
|
|
62
|
+
if (start.after > page.latest)
|
|
63
|
+
return gap(start.after, page);
|
|
64
|
+
if (request.parameters["follow"] === true)
|
|
65
|
+
return followed(context, { start, connection: request.connection });
|
|
66
|
+
return result("event-page", {
|
|
67
|
+
events: published(page),
|
|
68
|
+
latestSequence: page.latest,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Authority } from "../broker/actor/authority.ts";
|
|
2
|
+
import type { Gateway } from "./gateway.ts";
|
|
3
|
+
export interface ExpiryScan {
|
|
4
|
+
readonly stop: () => Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
interface ScanParts {
|
|
7
|
+
readonly authority: Authority;
|
|
8
|
+
readonly gateway: Gateway;
|
|
9
|
+
readonly clock: () => string;
|
|
10
|
+
readonly intervalMilliseconds: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function expiryScan(parts: ScanParts): ExpiryScan;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
3
|
+
import { notBefore } from "../authority/instants.js";
|
|
4
|
+
import { operationDigest } from "../broker/operation-digest.js";
|
|
5
|
+
function expiryIdentity(runId, gateId) {
|
|
6
|
+
return `expire:${createHash("sha256").update(`${runId} ${gateId}`).digest("hex").slice(0, 32)}`;
|
|
7
|
+
}
|
|
8
|
+
async function scanned(parts) {
|
|
9
|
+
const { authority, gateway, clock } = parts;
|
|
10
|
+
const state = await authority.state();
|
|
11
|
+
const now = clock();
|
|
12
|
+
const due = Object.values(state.gates).filter((gate) => gate.outcome === null &&
|
|
13
|
+
gate.expiresAt !== null &&
|
|
14
|
+
notBefore(now, gate.expiresAt) &&
|
|
15
|
+
state.runs[gate.runId]?.status === "waiting_gate");
|
|
16
|
+
for (const gate of due)
|
|
17
|
+
await gateway.execute({
|
|
18
|
+
principal: "controller",
|
|
19
|
+
command: {
|
|
20
|
+
kind: "expire-gate",
|
|
21
|
+
commandId: expiryIdentity(gate.runId, gate.gateId),
|
|
22
|
+
runId: gate.runId,
|
|
23
|
+
gateId: gate.gateId,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
for (const lease of await authority.effects.dueLeases(now))
|
|
27
|
+
await gateway.execute({
|
|
28
|
+
principal: "controller",
|
|
29
|
+
command: {
|
|
30
|
+
kind: "expire-lease",
|
|
31
|
+
commandId: `expire-lease:${operationDigest(lease.operationId)}:${String(lease.generation)}`,
|
|
32
|
+
runId: lease.runId,
|
|
33
|
+
operationId: lease.operationId,
|
|
34
|
+
leaseGeneration: lease.generation,
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
async function cycle(parts, signal) {
|
|
39
|
+
while (!signal.aborted) {
|
|
40
|
+
await scanned(parts).catch(() => undefined);
|
|
41
|
+
await delay(parts.intervalMilliseconds, undefined, { signal }).catch(() => undefined);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export function expiryScan(parts) {
|
|
45
|
+
const stopping = new AbortController();
|
|
46
|
+
const running = cycle(parts, stopping.signal);
|
|
47
|
+
return {
|
|
48
|
+
stop: async () => {
|
|
49
|
+
stopping.abort();
|
|
50
|
+
await running;
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Authority, StoreReceipt } from "../broker/actor/authority.ts";
|
|
2
|
+
import type { Registry } from "./registry.ts";
|
|
3
|
+
export type Principal = "operator" | "worker" | "controller";
|
|
4
|
+
export type Command = Readonly<Record<string, unknown>>;
|
|
5
|
+
export interface Submission {
|
|
6
|
+
readonly principal: Principal;
|
|
7
|
+
readonly command: Command;
|
|
8
|
+
readonly documents?: readonly string[];
|
|
9
|
+
readonly epoch?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare const workerCommandBound = 1000;
|
|
12
|
+
export interface Gateway {
|
|
13
|
+
readonly execute: (submission: Submission) => Promise<StoreReceipt>;
|
|
14
|
+
}
|
|
15
|
+
export declare function commandGateway(parts: {
|
|
16
|
+
readonly authority: Authority;
|
|
17
|
+
readonly registry: Registry;
|
|
18
|
+
readonly clock: () => string;
|
|
19
|
+
readonly textBytes: number;
|
|
20
|
+
readonly pendingWorkerCommands?: number;
|
|
21
|
+
}): Gateway;
|