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,12 @@
|
|
|
1
|
+
import { persistDecisions } from "../storage/domain-changes.js";
|
|
2
|
+
import { decidedVersion, upgradeSchema } from "../storage/domain-schema.js";
|
|
3
|
+
import { decisionRows } from "./decision-restore.js";
|
|
4
|
+
export async function upgradeDecisions(database, state) {
|
|
5
|
+
await database.transaction(async (connection) => {
|
|
6
|
+
await upgradeSchema(connection, decidedVersion);
|
|
7
|
+
await persistDecisions(connection, {
|
|
8
|
+
...decisionRows(state),
|
|
9
|
+
documents: [],
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type EffectState, type Evidence, type RunBudget } from "../authority/operations.ts";
|
|
2
|
+
import type { BudgetRow, EffectRows } from "../storage/effect-rows.ts";
|
|
3
|
+
export interface EffectInput {
|
|
4
|
+
readonly capability: string;
|
|
5
|
+
readonly method: string;
|
|
6
|
+
readonly target: string;
|
|
7
|
+
readonly payload: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function effectInputDigest(effect: EffectInput): string;
|
|
10
|
+
export declare function effectRows(effects: EffectState, evidence: readonly Evidence[]): EffectRows;
|
|
11
|
+
export declare function storedBudget(row: BudgetRow): RunBudget;
|
|
12
|
+
export type StoredEffects = Pick<EffectRows, "budgets" | "operations" | "leases" | "stops"> & {
|
|
13
|
+
readonly holding: number;
|
|
14
|
+
};
|
|
15
|
+
export declare function storedEffects(rows: StoredEffects): EffectState;
|
|
16
|
+
export declare function effectDigests(effects: EffectState): readonly string[];
|
|
17
|
+
export declare function effectChecks(rows: EffectRows, replay: {
|
|
18
|
+
readonly effects: EffectState;
|
|
19
|
+
readonly evidence: readonly Evidence[];
|
|
20
|
+
}): readonly (readonly [string, boolean])[];
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { isDeepStrictEqual } from "node:util";
|
|
3
|
+
import { isHolding, } from "../authority/operations.js";
|
|
4
|
+
export function effectInputDigest(effect) {
|
|
5
|
+
const text = JSON.stringify([
|
|
6
|
+
"cloving-effect-input",
|
|
7
|
+
1,
|
|
8
|
+
effect.capability,
|
|
9
|
+
effect.method,
|
|
10
|
+
effect.target,
|
|
11
|
+
effect.payload,
|
|
12
|
+
]);
|
|
13
|
+
return `sha256:${createHash("sha256").update(text).digest("hex")}`;
|
|
14
|
+
}
|
|
15
|
+
function budgetRecord(budget) {
|
|
16
|
+
return {
|
|
17
|
+
runId: budget.runId,
|
|
18
|
+
effectLimit: budget.limit,
|
|
19
|
+
spent: budget.spent,
|
|
20
|
+
capabilities: JSON.stringify(budget.capabilities),
|
|
21
|
+
exhaustedSequence: budget.exhaustedSequence,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function byText(key) {
|
|
25
|
+
return (left, right) => (key(left) < key(right) ? -1 : 1);
|
|
26
|
+
}
|
|
27
|
+
export function effectRows(effects, evidence) {
|
|
28
|
+
return {
|
|
29
|
+
budgets: Object.values(effects.budgets)
|
|
30
|
+
.map(budgetRecord)
|
|
31
|
+
.sort(byText((row) => row.runId)),
|
|
32
|
+
operations: Object.values(effects.operations).sort((left, right) => left.requestedSequence - right.requestedSequence),
|
|
33
|
+
leases: Object.values(effects.leases).sort(byText((row) => row.resourceKey)),
|
|
34
|
+
evidence,
|
|
35
|
+
stops: Object.entries(effects.stops)
|
|
36
|
+
.map(([operationId, stop]) => ({ operationId, ...stop }))
|
|
37
|
+
.sort(byText((row) => row.operationId)),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
const statuses = [
|
|
41
|
+
"refused",
|
|
42
|
+
"waiting",
|
|
43
|
+
"dispatch-pending",
|
|
44
|
+
"running",
|
|
45
|
+
"recovering",
|
|
46
|
+
"blocked",
|
|
47
|
+
"completed",
|
|
48
|
+
"failed",
|
|
49
|
+
"stopped",
|
|
50
|
+
"cancelled",
|
|
51
|
+
];
|
|
52
|
+
const leaseStates = ["held", "expired", "released"];
|
|
53
|
+
function storedOperation(row) {
|
|
54
|
+
const status = statuses.find((candidate) => candidate === row.status);
|
|
55
|
+
if (status === undefined)
|
|
56
|
+
throw new Error("invalid-operation-row");
|
|
57
|
+
return { ...row, status };
|
|
58
|
+
}
|
|
59
|
+
function storedLease(row) {
|
|
60
|
+
const state = leaseStates.find((candidate) => candidate === row.state);
|
|
61
|
+
if (state === undefined)
|
|
62
|
+
throw new Error("invalid-lease-row");
|
|
63
|
+
return { ...row, state };
|
|
64
|
+
}
|
|
65
|
+
export function storedBudget(row) {
|
|
66
|
+
const capabilities = JSON.parse(row.capabilities);
|
|
67
|
+
if (!Array.isArray(capabilities))
|
|
68
|
+
throw new Error("invalid-budget-row");
|
|
69
|
+
return {
|
|
70
|
+
runId: row.runId,
|
|
71
|
+
limit: row.effectLimit,
|
|
72
|
+
spent: row.spent,
|
|
73
|
+
capabilities: capabilities.map(String),
|
|
74
|
+
exhaustedSequence: row.exhaustedSequence,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
export function storedEffects(rows) {
|
|
78
|
+
return {
|
|
79
|
+
budgets: Object.fromEntries(rows.budgets.map((row) => [row.runId, storedBudget(row)])),
|
|
80
|
+
operations: Object.fromEntries(rows.operations.map((row) => [row.operationId, storedOperation(row)])),
|
|
81
|
+
leases: Object.fromEntries(rows.leases.map((row) => [row.resourceKey, storedLease(row)])),
|
|
82
|
+
holding: rows.holding,
|
|
83
|
+
stops: Object.fromEntries(rows.stops.map((row) => [
|
|
84
|
+
row.operationId,
|
|
85
|
+
{ runId: row.runId, sequence: row.sequence },
|
|
86
|
+
])),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
export function effectDigests(effects) {
|
|
90
|
+
return Object.values(effects.operations)
|
|
91
|
+
.flatMap((operation) => [operation.payload, operation.result])
|
|
92
|
+
.filter((digest) => digest !== null);
|
|
93
|
+
}
|
|
94
|
+
export function effectChecks(rows, replay) {
|
|
95
|
+
const expected = effectRows(replay.effects, replay.evidence);
|
|
96
|
+
return [
|
|
97
|
+
["budgets", isDeepStrictEqual(rows.budgets, expected.budgets)],
|
|
98
|
+
["operations", isDeepStrictEqual(rows.operations, expected.operations)],
|
|
99
|
+
["leases", isDeepStrictEqual(rows.leases, expected.leases)],
|
|
100
|
+
["effect-evidence", isDeepStrictEqual(rows.evidence, expected.evidence)],
|
|
101
|
+
["stopped-operations", isDeepStrictEqual(rows.stops, expected.stops)],
|
|
102
|
+
[
|
|
103
|
+
"holding",
|
|
104
|
+
rows.operations.filter(isHolding).length === replay.effects.holding,
|
|
105
|
+
],
|
|
106
|
+
[
|
|
107
|
+
"input-digests",
|
|
108
|
+
rows.operations.every((row) => effectInputDigest(row) === row.inputDigest),
|
|
109
|
+
],
|
|
110
|
+
];
|
|
111
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { currentVersion, upgradeSchema } from "../storage/domain-schema.js";
|
|
2
|
+
import { persistEffects } from "../storage/effect-changes.js";
|
|
3
|
+
import { effectRows } from "./effect-restore.js";
|
|
4
|
+
export async function upgradeEffects(database, state) {
|
|
5
|
+
await database.transaction(async (connection) => {
|
|
6
|
+
await upgradeSchema(connection, currentVersion);
|
|
7
|
+
await persistEffects(connection, effectRows(state.effects, []));
|
|
8
|
+
});
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function operationDigest(operationId: string): string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type SocketAddress = {
|
|
2
|
+
readonly kind: "address";
|
|
3
|
+
readonly path: string;
|
|
4
|
+
} | {
|
|
5
|
+
readonly kind: "refused";
|
|
6
|
+
readonly reason: "runtime-path-too-long";
|
|
7
|
+
readonly detail: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function socketAddress(path: string): SocketAddress;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { relative } from "node:path";
|
|
2
|
+
const maximumBytes = 103;
|
|
3
|
+
export function socketAddress(path) {
|
|
4
|
+
const [shortest] = [path, relative(process.cwd(), path)]
|
|
5
|
+
.filter((candidate) => candidate.length > 0)
|
|
6
|
+
.sort((left, right) => Buffer.byteLength(left) - Buffer.byteLength(right));
|
|
7
|
+
if (shortest === undefined || Buffer.byteLength(shortest) > maximumBytes)
|
|
8
|
+
return {
|
|
9
|
+
kind: "refused",
|
|
10
|
+
reason: "runtime-path-too-long",
|
|
11
|
+
detail: `The socket path ${path} is longer than ${String(maximumBytes)} bytes.`,
|
|
12
|
+
};
|
|
13
|
+
return { kind: "address", path: shortest };
|
|
14
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type FileHandle } from "node:fs/promises";
|
|
2
|
+
export declare function importDirectory(runtime: string, importId: string): Promise<string>;
|
|
3
|
+
export declare function validateDestination(directory: string): Promise<void>;
|
|
4
|
+
export declare function createPrivateFile(path: string): Promise<FileHandle>;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { lstat, mkdir, open, realpath, } from "node:fs/promises";
|
|
3
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
4
|
+
function missing(error) {
|
|
5
|
+
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
6
|
+
}
|
|
7
|
+
async function canonical(path) {
|
|
8
|
+
try {
|
|
9
|
+
await lstat(path);
|
|
10
|
+
}
|
|
11
|
+
catch (error) {
|
|
12
|
+
if (!missing(error))
|
|
13
|
+
throw error;
|
|
14
|
+
return join(await canonical(dirname(path)), basename(path));
|
|
15
|
+
}
|
|
16
|
+
return realpath(path);
|
|
17
|
+
}
|
|
18
|
+
async function outsideRepository(path) {
|
|
19
|
+
let ancestor = path;
|
|
20
|
+
for (;;) {
|
|
21
|
+
try {
|
|
22
|
+
await lstat(join(ancestor, ".git"));
|
|
23
|
+
throw new Error("destination-refused");
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (!missing(error))
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
const parent = dirname(ancestor);
|
|
30
|
+
if (parent === ancestor)
|
|
31
|
+
return;
|
|
32
|
+
ancestor = parent;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async function privateDirectory(path) {
|
|
36
|
+
try {
|
|
37
|
+
const stats = await lstat(path);
|
|
38
|
+
if (!stats.isDirectory())
|
|
39
|
+
throw new Error("destination-refused");
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
if (!missing(error))
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
await privateDirectory(dirname(path));
|
|
47
|
+
try {
|
|
48
|
+
await mkdir(path, { mode: 0o700 });
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
if (!(error instanceof Error && "code" in error && error.code === "EEXIST"))
|
|
52
|
+
throw error;
|
|
53
|
+
if (!(await lstat(path)).isDirectory())
|
|
54
|
+
throw new Error("destination-refused", { cause: error });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export async function importDirectory(runtime, importId) {
|
|
58
|
+
if (process.platform !== "darwin")
|
|
59
|
+
throw new Error("destination-refused");
|
|
60
|
+
let chats;
|
|
61
|
+
try {
|
|
62
|
+
chats = await canonical(join(resolve(runtime), "chats"));
|
|
63
|
+
await outsideRepository(chats);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
throw new Error("destination-refused");
|
|
67
|
+
}
|
|
68
|
+
await privateDirectory(chats);
|
|
69
|
+
await validateDestination(chats);
|
|
70
|
+
const directory = join(chats, importId);
|
|
71
|
+
await mkdir(directory, { mode: 0o700 });
|
|
72
|
+
await validateDestination(directory);
|
|
73
|
+
return directory;
|
|
74
|
+
}
|
|
75
|
+
export async function validateDestination(directory) {
|
|
76
|
+
if ((await realpath(directory)) !== directory)
|
|
77
|
+
throw new Error("destination-refused");
|
|
78
|
+
await outsideRepository(directory);
|
|
79
|
+
}
|
|
80
|
+
export async function createPrivateFile(path) {
|
|
81
|
+
await validateDestination(dirname(path));
|
|
82
|
+
const darwinNoFollowAny = 0x20000000;
|
|
83
|
+
try {
|
|
84
|
+
return await open(path, constants.O_WRONLY |
|
|
85
|
+
constants.O_CREAT |
|
|
86
|
+
constants.O_EXCL |
|
|
87
|
+
darwinNoFollowAny, 0o600);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
if (error instanceof Error && "code" in error && error.code === "ELOOP")
|
|
91
|
+
throw new Error("destination-refused", { cause: error });
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface ImportRequest {
|
|
2
|
+
readonly paths: readonly string[];
|
|
3
|
+
readonly workingDirectory: string;
|
|
4
|
+
readonly runtimeDirectory: string | undefined;
|
|
5
|
+
}
|
|
6
|
+
export interface ImportSummary {
|
|
7
|
+
readonly code: "import-complete" | "import-partial" | "runtime-directory-unknown" | "destination-refused" | "output-failed";
|
|
8
|
+
readonly importId: string | null;
|
|
9
|
+
readonly included: number;
|
|
10
|
+
readonly refused: number;
|
|
11
|
+
readonly records: number;
|
|
12
|
+
}
|
|
13
|
+
export declare function importChats(request: ImportRequest): Promise<ImportSummary>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { rm } from "node:fs/promises";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
import { createPrivateFile, importDirectory, validateDestination, } from "./destination.js";
|
|
5
|
+
import { readTranscript } from "./reader.js";
|
|
6
|
+
async function writeImport(directory, request) {
|
|
7
|
+
const files = [];
|
|
8
|
+
const corpus = await createPrivateFile(join(directory, "corpus.jsonl"));
|
|
9
|
+
try {
|
|
10
|
+
for (const selected of request.paths) {
|
|
11
|
+
const result = await readTranscript(resolve(request.workingDirectory, selected));
|
|
12
|
+
files.push(result.coverage);
|
|
13
|
+
for (const record of result.records)
|
|
14
|
+
await corpus.writeFile(`${JSON.stringify(record)}\n`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
finally {
|
|
18
|
+
await corpus.close();
|
|
19
|
+
}
|
|
20
|
+
return files;
|
|
21
|
+
}
|
|
22
|
+
async function writeCoverage(directory, coverage) {
|
|
23
|
+
const manifest = join(directory, "coverage.json");
|
|
24
|
+
let created = false;
|
|
25
|
+
try {
|
|
26
|
+
const handle = await createPrivateFile(manifest);
|
|
27
|
+
created = true;
|
|
28
|
+
try {
|
|
29
|
+
await handle.writeFile(`${JSON.stringify(coverage, null, 2)}\n`);
|
|
30
|
+
}
|
|
31
|
+
finally {
|
|
32
|
+
await handle.close();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
if (created) {
|
|
37
|
+
await validateDestination(directory);
|
|
38
|
+
await rm(manifest, { force: true });
|
|
39
|
+
}
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export async function importChats(request) {
|
|
44
|
+
const empty = { importId: null, included: 0, refused: 0, records: 0 };
|
|
45
|
+
if (request.runtimeDirectory === undefined)
|
|
46
|
+
return { ...empty, code: "runtime-directory-unknown" };
|
|
47
|
+
try {
|
|
48
|
+
const importId = randomUUID();
|
|
49
|
+
const directory = await importDirectory(resolve(request.workingDirectory, request.runtimeDirectory), importId);
|
|
50
|
+
const files = await writeImport(directory, request);
|
|
51
|
+
const included = files.filter((file) => file.status === "included").length;
|
|
52
|
+
const records = files.reduce((count, file) => count + file.recordCount, 0);
|
|
53
|
+
const refused = files.length - included;
|
|
54
|
+
await writeCoverage(directory, { schemaVersion: 1, importId, files });
|
|
55
|
+
return {
|
|
56
|
+
code: refused === 0 ? "import-complete" : "import-partial",
|
|
57
|
+
importId,
|
|
58
|
+
included,
|
|
59
|
+
refused,
|
|
60
|
+
records,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
return {
|
|
65
|
+
...empty,
|
|
66
|
+
code: error instanceof Error && error.message === "destination-refused"
|
|
67
|
+
? "destination-refused"
|
|
68
|
+
: "output-failed",
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface Omissions {
|
|
2
|
+
metadataRecords: number;
|
|
3
|
+
thinkingBlocks: number;
|
|
4
|
+
}
|
|
5
|
+
export interface MessageRecord {
|
|
6
|
+
readonly schemaVersion: 1;
|
|
7
|
+
readonly sourceId: string;
|
|
8
|
+
readonly role: "user" | "assistant";
|
|
9
|
+
readonly timestamp: string | null;
|
|
10
|
+
readonly sessionId: string | null;
|
|
11
|
+
readonly text: string;
|
|
12
|
+
readonly blocks: readonly Record<string, unknown>[];
|
|
13
|
+
}
|
|
14
|
+
export interface NormalizedTranscript {
|
|
15
|
+
readonly status: "included" | "unsupported";
|
|
16
|
+
readonly reason: string;
|
|
17
|
+
readonly records: readonly MessageRecord[];
|
|
18
|
+
readonly omissions: Omissions;
|
|
19
|
+
}
|
|
20
|
+
export declare function normalizeTranscript(text: string, digest: string): NormalizedTranscript;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
function object(value) {
|
|
2
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3
|
+
}
|
|
4
|
+
function supportedBlock(block) {
|
|
5
|
+
const type = block["type"];
|
|
6
|
+
if (type === "text" && typeof block["text"] === "string")
|
|
7
|
+
return { type, text: block["text"] };
|
|
8
|
+
if (type === "tool_use" &&
|
|
9
|
+
typeof block["id"] === "string" &&
|
|
10
|
+
typeof block["name"] === "string" &&
|
|
11
|
+
Object.hasOwn(block, "input")) {
|
|
12
|
+
return {
|
|
13
|
+
type,
|
|
14
|
+
id: block["id"],
|
|
15
|
+
name: block["name"],
|
|
16
|
+
input: block["input"],
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
if (type === "tool_result")
|
|
20
|
+
return toolResult(block);
|
|
21
|
+
throw new Error("unsupported-block");
|
|
22
|
+
}
|
|
23
|
+
function toolResult(block) {
|
|
24
|
+
if (typeof block["tool_use_id"] !== "string" ||
|
|
25
|
+
!Object.hasOwn(block, "content"))
|
|
26
|
+
throw new Error("unsupported-block");
|
|
27
|
+
if (Object.hasOwn(block, "is_error") &&
|
|
28
|
+
typeof block["is_error"] !== "boolean")
|
|
29
|
+
throw new Error("unsupported-block");
|
|
30
|
+
return {
|
|
31
|
+
type: "tool_result",
|
|
32
|
+
tool_use_id: block["tool_use_id"],
|
|
33
|
+
content: block["content"],
|
|
34
|
+
...(Object.hasOwn(block, "is_error")
|
|
35
|
+
? { is_error: block["is_error"] }
|
|
36
|
+
: {}),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function optionalText(value) {
|
|
40
|
+
if (value === undefined || value === null)
|
|
41
|
+
return null;
|
|
42
|
+
if (typeof value !== "string")
|
|
43
|
+
throw new Error("unsupported-message");
|
|
44
|
+
return value;
|
|
45
|
+
}
|
|
46
|
+
function rawJsonApi(value) {
|
|
47
|
+
return "rawJSON" in value && typeof value.rawJSON === "function";
|
|
48
|
+
}
|
|
49
|
+
function preserveJson(...argumentsList) {
|
|
50
|
+
const [, value, context] = argumentsList;
|
|
51
|
+
if (typeof value !== "number")
|
|
52
|
+
return value;
|
|
53
|
+
if (!object(context) || typeof context["source"] !== "string")
|
|
54
|
+
throw new Error("unsupported-record");
|
|
55
|
+
if (JSON.stringify(value) === context["source"])
|
|
56
|
+
return value;
|
|
57
|
+
if (!rawJsonApi(JSON))
|
|
58
|
+
throw new Error("unsupported-record");
|
|
59
|
+
return JSON.rawJSON(context["source"]);
|
|
60
|
+
}
|
|
61
|
+
function blocks(content, omissions) {
|
|
62
|
+
if (typeof content === "string")
|
|
63
|
+
return [{ position: 0, type: "text", text: content }];
|
|
64
|
+
if (!Array.isArray(content))
|
|
65
|
+
throw new Error("unsupported-message");
|
|
66
|
+
return content.flatMap((block, position) => {
|
|
67
|
+
if (!object(block))
|
|
68
|
+
throw new Error("unsupported-block");
|
|
69
|
+
if (block["type"] === "thinking") {
|
|
70
|
+
omissions.thinkingBlocks++;
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
return [{ ...supportedBlock(block), position }];
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function message(value, context) {
|
|
77
|
+
if (!object(value) || typeof value["type"] !== "string")
|
|
78
|
+
throw new Error("unsupported-record");
|
|
79
|
+
if (value["type"] !== "user" &&
|
|
80
|
+
value["type"] !== "assistant" &&
|
|
81
|
+
Object.hasOwn(value, "message"))
|
|
82
|
+
throw new Error("unsupported-message");
|
|
83
|
+
if (value["type"] !== "user" && value["type"] !== "assistant") {
|
|
84
|
+
context.omissions.metadataRecords++;
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
const envelope = value["message"];
|
|
88
|
+
if (!object(envelope) || envelope["role"] !== value["type"])
|
|
89
|
+
throw new Error("unsupported-message");
|
|
90
|
+
const normalized = blocks(envelope["content"], context.omissions);
|
|
91
|
+
return {
|
|
92
|
+
schemaVersion: 1,
|
|
93
|
+
sourceId: context.sourceId,
|
|
94
|
+
role: value["type"],
|
|
95
|
+
timestamp: optionalText(value["timestamp"]),
|
|
96
|
+
sessionId: optionalText(value["sessionId"]),
|
|
97
|
+
text: normalized
|
|
98
|
+
.filter((block) => block["type"] === "text")
|
|
99
|
+
.map((block) => block["text"])
|
|
100
|
+
.join("\n"),
|
|
101
|
+
blocks: normalized,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
export function normalizeTranscript(text, digest) {
|
|
105
|
+
const omissions = { metadataRecords: 0, thinkingBlocks: 0 };
|
|
106
|
+
const records = [];
|
|
107
|
+
if (text === "")
|
|
108
|
+
return { status: "unsupported", reason: "empty-file", records, omissions };
|
|
109
|
+
let offset = 0;
|
|
110
|
+
const lines = text.split("\n");
|
|
111
|
+
if (lines.at(-1) === "")
|
|
112
|
+
lines.pop();
|
|
113
|
+
try {
|
|
114
|
+
for (const line of lines) {
|
|
115
|
+
const parsed = JSON.parse(line, preserveJson);
|
|
116
|
+
const record = message(parsed, {
|
|
117
|
+
sourceId: `${digest}:${String(offset)}`,
|
|
118
|
+
omissions,
|
|
119
|
+
});
|
|
120
|
+
if (record !== null)
|
|
121
|
+
records.push(record);
|
|
122
|
+
offset += new TextEncoder().encode(line).length + 1;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
let reason = "unsupported-record";
|
|
127
|
+
if (error instanceof Error)
|
|
128
|
+
reason = error.message;
|
|
129
|
+
if (error instanceof SyntaxError)
|
|
130
|
+
reason = "invalid-json";
|
|
131
|
+
return {
|
|
132
|
+
status: "unsupported",
|
|
133
|
+
reason,
|
|
134
|
+
records: [],
|
|
135
|
+
omissions,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
return { status: "included", reason: "supported", records, omissions };
|
|
139
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type MessageRecord, type Omissions } from "./normalize.ts";
|
|
2
|
+
export declare const transcriptLimit = 10485760;
|
|
3
|
+
export interface SelectedTranscript {
|
|
4
|
+
readonly path: string;
|
|
5
|
+
readonly status: "included" | "unreadable" | "unsupported" | "too-large";
|
|
6
|
+
readonly reason: string;
|
|
7
|
+
readonly digest: string | null;
|
|
8
|
+
readonly recordCount: number;
|
|
9
|
+
readonly omissions: Omissions;
|
|
10
|
+
}
|
|
11
|
+
export interface ReadTranscript {
|
|
12
|
+
readonly coverage: SelectedTranscript;
|
|
13
|
+
readonly records: readonly MessageRecord[];
|
|
14
|
+
}
|
|
15
|
+
export declare function readTranscript(path: string): Promise<ReadTranscript>;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { constants } from "node:fs";
|
|
3
|
+
import { lstat, open } from "node:fs/promises";
|
|
4
|
+
import { normalizeTranscript, } from "./normalize.js";
|
|
5
|
+
export const transcriptLimit = 10_485_760;
|
|
6
|
+
function refused(path, reason) {
|
|
7
|
+
const status = reason === "source-unreadable" ? "unreadable" : "unsupported";
|
|
8
|
+
return {
|
|
9
|
+
coverage: {
|
|
10
|
+
path,
|
|
11
|
+
status: reason === "file-too-large" ? "too-large" : status,
|
|
12
|
+
reason,
|
|
13
|
+
digest: null,
|
|
14
|
+
recordCount: 0,
|
|
15
|
+
omissions: { metadataRecords: 0, thinkingBlocks: 0 },
|
|
16
|
+
},
|
|
17
|
+
records: [],
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
async function boundedBytes(handle) {
|
|
21
|
+
const stats = await handle.stat();
|
|
22
|
+
if (!stats.isFile())
|
|
23
|
+
return "nonregular-file";
|
|
24
|
+
if (stats.size > transcriptLimit)
|
|
25
|
+
return "file-too-large";
|
|
26
|
+
const chunks = [];
|
|
27
|
+
let total = 0;
|
|
28
|
+
while (total <= transcriptLimit) {
|
|
29
|
+
const buffer = Buffer.alloc(Math.min(65_536, transcriptLimit + 1 - total));
|
|
30
|
+
const { bytesRead } = await handle.read(buffer, 0, buffer.length, total);
|
|
31
|
+
if (bytesRead === 0)
|
|
32
|
+
break;
|
|
33
|
+
total += bytesRead;
|
|
34
|
+
chunks.push(buffer.subarray(0, bytesRead));
|
|
35
|
+
}
|
|
36
|
+
if (total > transcriptLimit || (await handle.stat()).size > transcriptLimit)
|
|
37
|
+
return "file-too-large";
|
|
38
|
+
return Buffer.concat(chunks, total);
|
|
39
|
+
}
|
|
40
|
+
function normalizeBytes(path, bytes) {
|
|
41
|
+
const digest = `sha256:${createHash("sha256").update(bytes).digest("hex")}`;
|
|
42
|
+
let text;
|
|
43
|
+
try {
|
|
44
|
+
text = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
const result = refused(path, "invalid-utf8");
|
|
48
|
+
return { ...result, coverage: { ...result.coverage, digest } };
|
|
49
|
+
}
|
|
50
|
+
const result = normalizeTranscript(text, digest);
|
|
51
|
+
return {
|
|
52
|
+
coverage: {
|
|
53
|
+
path,
|
|
54
|
+
status: result.status,
|
|
55
|
+
reason: result.reason,
|
|
56
|
+
digest,
|
|
57
|
+
recordCount: result.records.length,
|
|
58
|
+
omissions: result.omissions,
|
|
59
|
+
},
|
|
60
|
+
records: result.records,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export async function readTranscript(path) {
|
|
64
|
+
try {
|
|
65
|
+
const stats = await lstat(path);
|
|
66
|
+
if (stats.isSymbolicLink())
|
|
67
|
+
return refused(path, "symbolic-link");
|
|
68
|
+
if (!stats.isFile())
|
|
69
|
+
return refused(path, "nonregular-file");
|
|
70
|
+
const handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
71
|
+
let bytes;
|
|
72
|
+
try {
|
|
73
|
+
bytes = await boundedBytes(handle);
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
await handle.close();
|
|
77
|
+
}
|
|
78
|
+
return typeof bytes === "string"
|
|
79
|
+
? refused(path, bytes)
|
|
80
|
+
: normalizeBytes(path, bytes);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
if (error instanceof Error && "code" in error && error.code === "ELOOP")
|
|
84
|
+
return refused(path, "symbolic-link");
|
|
85
|
+
return refused(path, "source-unreadable");
|
|
86
|
+
}
|
|
87
|
+
}
|