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,148 @@
|
|
|
1
|
+
const endings = [
|
|
2
|
+
{ type: "run.completed", name: "Completed", state: "done" },
|
|
3
|
+
{ type: "run.failed", name: "Failed", state: "failed" },
|
|
4
|
+
{ type: "run.cancelled", name: "Dropped", state: "failed" },
|
|
5
|
+
];
|
|
6
|
+
const review = { open: "gate.opened", close: "gate.decided" };
|
|
7
|
+
const effect = { open: "effect.requested", close: "effect.reported" };
|
|
8
|
+
const issueWorkflow = "develop-issue";
|
|
9
|
+
export const issueSteps = [
|
|
10
|
+
{ name: "Work tree", operation: "github-prepare" },
|
|
11
|
+
{ name: "Claude turn", operation: "claude-turn" },
|
|
12
|
+
{ name: "Pull request", operation: "github-open-pr" },
|
|
13
|
+
{ name: "Greptile review", operation: "github-wait-review" },
|
|
14
|
+
{ name: "Merge", operation: "github-merge" },
|
|
15
|
+
];
|
|
16
|
+
const verdicts = {
|
|
17
|
+
approved: "Approved",
|
|
18
|
+
denied: "Denied",
|
|
19
|
+
};
|
|
20
|
+
const unfinished = ["failed", "stopped"];
|
|
21
|
+
const roundOperations = ["claude-turn", "github-open-pr", "github-wait-review"];
|
|
22
|
+
function record(value) {
|
|
23
|
+
return typeof value === "object" && value !== null ? { ...value } : {};
|
|
24
|
+
}
|
|
25
|
+
function timeOf(event) {
|
|
26
|
+
const recordedAt = event?.["recordedAt"];
|
|
27
|
+
return typeof recordedAt === "string" ? recordedAt : null;
|
|
28
|
+
}
|
|
29
|
+
function firstAt(events, type) {
|
|
30
|
+
return timeOf(events.find((event) => event["type"] === type));
|
|
31
|
+
}
|
|
32
|
+
function closedAt(events, pair) {
|
|
33
|
+
const types = events.map((event) => event["type"]);
|
|
34
|
+
const closed = types.lastIndexOf(pair.close);
|
|
35
|
+
return closed > types.lastIndexOf(pair.open) ? timeOf(events[closed]) : null;
|
|
36
|
+
}
|
|
37
|
+
export function decisionOf(events) {
|
|
38
|
+
const known = events.map(record);
|
|
39
|
+
const types = known.map((event) => event["type"]);
|
|
40
|
+
const closed = types.lastIndexOf(review.close);
|
|
41
|
+
if (closed <= types.lastIndexOf(review.open))
|
|
42
|
+
return "";
|
|
43
|
+
const decision = record(known[closed]?.["payload"])["decision"];
|
|
44
|
+
return typeof decision === "string" ? decision : "";
|
|
45
|
+
}
|
|
46
|
+
function admission(events) {
|
|
47
|
+
const created = firstAt(events, "run.created");
|
|
48
|
+
const started = firstAt(events, "run.started");
|
|
49
|
+
return [
|
|
50
|
+
{ name: "Admitted", startedAt: created, endedAt: created, ending: "done" },
|
|
51
|
+
{ name: "Started", startedAt: started, endedAt: started, ending: "done" },
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
function ticketSpans(events) {
|
|
55
|
+
const decision = decisionOf(events);
|
|
56
|
+
return [
|
|
57
|
+
...admission(events),
|
|
58
|
+
{
|
|
59
|
+
name: "Claude turn",
|
|
60
|
+
startedAt: firstAt(events, effect.open),
|
|
61
|
+
endedAt: closedAt(events, effect),
|
|
62
|
+
ending: "done",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: verdicts[decision] ?? "Your review",
|
|
66
|
+
startedAt: firstAt(events, review.open),
|
|
67
|
+
endedAt: closedAt(events, review),
|
|
68
|
+
ending: decision === "denied" ? "failed" : "done",
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
function operationOf(event) {
|
|
73
|
+
const operationId = record(event?.["payload"])["operationId"];
|
|
74
|
+
try {
|
|
75
|
+
const scope = JSON.parse(String(operationId));
|
|
76
|
+
return Array.isArray(scope) ? scope : [];
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function currentRound(events) {
|
|
83
|
+
const requested = events.findLast((event) => event["type"] === effect.open && operationOf(event)[4] === "claude-turn");
|
|
84
|
+
const round = operationOf(requested)[1];
|
|
85
|
+
return typeof round === "number" ? round : 1;
|
|
86
|
+
}
|
|
87
|
+
function spans(events, workflowId) {
|
|
88
|
+
if (workflowId !== issueWorkflow)
|
|
89
|
+
return ticketSpans(events);
|
|
90
|
+
const effects = events.filter((event) => [effect.open, effect.close].includes(String(event["type"])));
|
|
91
|
+
const round = currentRound(effects);
|
|
92
|
+
return [
|
|
93
|
+
...admission(events),
|
|
94
|
+
...issueSteps.map((step) => {
|
|
95
|
+
const repeated = roundOperations.includes(step.operation);
|
|
96
|
+
const own = effects.filter((event) => {
|
|
97
|
+
const scope = operationOf(event);
|
|
98
|
+
return scope[4] === step.operation && (!repeated || scope[1] === round);
|
|
99
|
+
});
|
|
100
|
+
const last = own.findLast((event) => event["type"] === effect.close);
|
|
101
|
+
const outcome = String(record(last?.["payload"])["outcome"]);
|
|
102
|
+
return {
|
|
103
|
+
name: repeated && round > 1
|
|
104
|
+
? `${step.name}, round ${String(round)}`
|
|
105
|
+
: step.name,
|
|
106
|
+
startedAt: firstAt(own, effect.open),
|
|
107
|
+
endedAt: closedAt(own, effect),
|
|
108
|
+
ending: unfinished.includes(outcome) ? "failed" : "done",
|
|
109
|
+
};
|
|
110
|
+
}),
|
|
111
|
+
];
|
|
112
|
+
}
|
|
113
|
+
function phase(span, open) {
|
|
114
|
+
const { ending, ...shown } = span;
|
|
115
|
+
if (span.endedAt !== null)
|
|
116
|
+
return { ...shown, state: ending };
|
|
117
|
+
return { ...shown, state: span.startedAt === null ? "pending" : open };
|
|
118
|
+
}
|
|
119
|
+
function ends(events) {
|
|
120
|
+
return endings.flatMap(({ type, name, state }) => {
|
|
121
|
+
const event = events.findLast((item) => item["type"] === type);
|
|
122
|
+
if (event === undefined)
|
|
123
|
+
return [];
|
|
124
|
+
const recordedAt = timeOf(event);
|
|
125
|
+
return [{ name, state, startedAt: recordedAt, endedAt: recordedAt }];
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
function advanced(phases) {
|
|
129
|
+
const next = phases.findLastIndex((item) => item.state === "done") + 1;
|
|
130
|
+
const idle = phases.every((item) => item.state !== "active");
|
|
131
|
+
return phases.map((item, index) => idle && next > 0 && index === next && item.state === "pending"
|
|
132
|
+
? { ...item, state: "active" }
|
|
133
|
+
: item);
|
|
134
|
+
}
|
|
135
|
+
export function phasesOf(events, workflowId = "") {
|
|
136
|
+
const known = events.map(record);
|
|
137
|
+
const steps = spans(known, workflowId);
|
|
138
|
+
const [end] = ends(known);
|
|
139
|
+
if (end !== undefined)
|
|
140
|
+
return [...steps.map((span) => phase(span, "failed")), end];
|
|
141
|
+
const open = {
|
|
142
|
+
name: "Completed",
|
|
143
|
+
startedAt: null,
|
|
144
|
+
endedAt: null,
|
|
145
|
+
ending: "done",
|
|
146
|
+
};
|
|
147
|
+
return advanced([...steps, open].map((span) => phase(span, "active")));
|
|
148
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type Fields } from "../protocol.ts";
|
|
2
|
+
interface ReadStatus extends Fields {
|
|
3
|
+
readonly runId: string;
|
|
4
|
+
readonly latestSequence: number;
|
|
5
|
+
readonly state: string;
|
|
6
|
+
readonly latestAt: string | null;
|
|
7
|
+
}
|
|
8
|
+
interface ReadEvent extends Fields {
|
|
9
|
+
readonly sequence: number;
|
|
10
|
+
}
|
|
11
|
+
interface ReadRun {
|
|
12
|
+
readonly status: ReadStatus;
|
|
13
|
+
readonly events: readonly ReadEvent[];
|
|
14
|
+
}
|
|
15
|
+
export interface WatchRead {
|
|
16
|
+
readonly service: string;
|
|
17
|
+
readonly workflows: readonly string[];
|
|
18
|
+
readonly summaries: readonly ReadStatus[];
|
|
19
|
+
readonly runs: readonly ReadRun[];
|
|
20
|
+
readonly completionCandidates: readonly ReadRun[];
|
|
21
|
+
readonly decisions: readonly unknown[];
|
|
22
|
+
}
|
|
23
|
+
export interface WatchReader {
|
|
24
|
+
readonly read: (now: string) => Promise<WatchRead>;
|
|
25
|
+
readonly run: (runId: string) => Promise<WatchRead>;
|
|
26
|
+
}
|
|
27
|
+
export declare function watchReader(runtimeDirectory: string): WatchReader;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { record } from "../protocol.js";
|
|
2
|
+
import { send } from "./client.js";
|
|
3
|
+
import { activeRun, recentRun } from "./watch-board.js";
|
|
4
|
+
const unavailable = {
|
|
5
|
+
service: "down",
|
|
6
|
+
workflows: [],
|
|
7
|
+
summaries: [],
|
|
8
|
+
runs: [],
|
|
9
|
+
completionCandidates: [],
|
|
10
|
+
decisions: [],
|
|
11
|
+
};
|
|
12
|
+
function list(value) {
|
|
13
|
+
return Array.isArray(value) ? value.map((item) => item) : [];
|
|
14
|
+
}
|
|
15
|
+
function statusOf(value) {
|
|
16
|
+
const fields = record(value);
|
|
17
|
+
const runId = fields?.["runId"];
|
|
18
|
+
const latestSequence = fields?.["latestSequence"];
|
|
19
|
+
const state = fields?.["state"];
|
|
20
|
+
const latestAt = fields?.["latestAt"];
|
|
21
|
+
if (typeof runId !== "string" ||
|
|
22
|
+
typeof latestSequence !== "number" ||
|
|
23
|
+
typeof state !== "string")
|
|
24
|
+
throw new Error("invalid-run-status");
|
|
25
|
+
return {
|
|
26
|
+
...fields,
|
|
27
|
+
runId,
|
|
28
|
+
latestSequence,
|
|
29
|
+
state,
|
|
30
|
+
latestAt: typeof latestAt === "string" ? latestAt : null,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function eventOf(value) {
|
|
34
|
+
const fields = record(value);
|
|
35
|
+
const sequence = fields?.["sequence"];
|
|
36
|
+
if (typeof sequence !== "number")
|
|
37
|
+
throw new Error("invalid-event-page");
|
|
38
|
+
return { ...fields, sequence };
|
|
39
|
+
}
|
|
40
|
+
async function asked(reader, request) {
|
|
41
|
+
const reply = await send(reader.runtimeDirectory, request);
|
|
42
|
+
if (reply.kind === "error")
|
|
43
|
+
throw new Error(reply.error.code);
|
|
44
|
+
return reply.result;
|
|
45
|
+
}
|
|
46
|
+
async function* eventPages(reader, cursor) {
|
|
47
|
+
let after = 0;
|
|
48
|
+
for (;;) {
|
|
49
|
+
const limit = after === 0 ? (cursor.firstLimit ?? 1000) : 1000;
|
|
50
|
+
const page = await asked(reader, {
|
|
51
|
+
operation: "events",
|
|
52
|
+
parameters: { runId: cursor.runId, after, limit },
|
|
53
|
+
});
|
|
54
|
+
const batch = list(page["events"]).map(eventOf);
|
|
55
|
+
yield batch;
|
|
56
|
+
if (batch.length < limit)
|
|
57
|
+
return;
|
|
58
|
+
const next = batch.at(-1)?.sequence;
|
|
59
|
+
if (next === undefined || next <= after)
|
|
60
|
+
throw new Error("invalid-event-page");
|
|
61
|
+
after = next;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async function eventsOf(reader, runId) {
|
|
65
|
+
const events = [];
|
|
66
|
+
for await (const batch of eventPages(reader, { runId }))
|
|
67
|
+
events.push(...batch);
|
|
68
|
+
return events;
|
|
69
|
+
}
|
|
70
|
+
async function creationOf(reader, runId) {
|
|
71
|
+
for await (const batch of eventPages(reader, { runId, firstLimit: 1 })) {
|
|
72
|
+
const event = batch.find((value) => value["type"] === "run.created");
|
|
73
|
+
if (event !== undefined)
|
|
74
|
+
return {
|
|
75
|
+
sequence: event.sequence,
|
|
76
|
+
type: event["type"],
|
|
77
|
+
recordedAt: event["recordedAt"],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
function matchingCompletion(status, ticketIds) {
|
|
83
|
+
const ticketId = status["ticketId"];
|
|
84
|
+
return (status.state === "completed" &&
|
|
85
|
+
status["workflowId"] === "develop-issue" &&
|
|
86
|
+
record(status["outcome"])?.["kind"] === "handoff_requested" &&
|
|
87
|
+
typeof ticketId === "string" &&
|
|
88
|
+
ticketIds.has(ticketId));
|
|
89
|
+
}
|
|
90
|
+
async function completionOf(reader, search) {
|
|
91
|
+
const { runId, latestSequence } = search.summary;
|
|
92
|
+
let known = reader.completions.get(runId);
|
|
93
|
+
if (known?.status.latestSequence !== latestSequence) {
|
|
94
|
+
const shown = await asked(reader, {
|
|
95
|
+
operation: "status",
|
|
96
|
+
parameters: { runId },
|
|
97
|
+
});
|
|
98
|
+
const status = statusOf(shown["run"]);
|
|
99
|
+
known = {
|
|
100
|
+
status: {
|
|
101
|
+
runId,
|
|
102
|
+
latestSequence: status.latestSequence,
|
|
103
|
+
latestAt: status.latestAt,
|
|
104
|
+
state: status.state,
|
|
105
|
+
workflowId: status["workflowId"],
|
|
106
|
+
ticketId: status["ticketId"],
|
|
107
|
+
outcome: status["outcome"],
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
reader.completions.set(runId, known);
|
|
111
|
+
}
|
|
112
|
+
if (!matchingCompletion(known.status, search.ticketIds))
|
|
113
|
+
return null;
|
|
114
|
+
const creation = known.creation === undefined
|
|
115
|
+
? await creationOf(reader, runId)
|
|
116
|
+
: known.creation;
|
|
117
|
+
reader.completions.set(runId, { ...known, creation });
|
|
118
|
+
return { status: known.status, events: creation === null ? [] : [creation] };
|
|
119
|
+
}
|
|
120
|
+
async function detailed(reader, summary) {
|
|
121
|
+
const { runId, latestSequence: sequence } = summary;
|
|
122
|
+
const known = reader.details.get(runId);
|
|
123
|
+
if (known !== undefined && known.sequence === sequence)
|
|
124
|
+
return known.value;
|
|
125
|
+
const shown = await asked(reader, {
|
|
126
|
+
operation: "status",
|
|
127
|
+
parameters: { runId },
|
|
128
|
+
});
|
|
129
|
+
return remember(reader, statusOf(shown["run"]));
|
|
130
|
+
}
|
|
131
|
+
async function remember(reader, status) {
|
|
132
|
+
const { runId, latestSequence: sequence } = status;
|
|
133
|
+
const value = { status, events: await eventsOf(reader, runId) };
|
|
134
|
+
reader.details.set(runId, { sequence, value });
|
|
135
|
+
return value;
|
|
136
|
+
}
|
|
137
|
+
async function allRuns(reader, first) {
|
|
138
|
+
const runs = list(first["runs"]).map(statusOf);
|
|
139
|
+
let next = first["next"];
|
|
140
|
+
const visited = new Set();
|
|
141
|
+
while (typeof next === "string") {
|
|
142
|
+
if (visited.has(next))
|
|
143
|
+
throw new Error("invalid-run-page");
|
|
144
|
+
visited.add(next);
|
|
145
|
+
const page = await asked(reader, {
|
|
146
|
+
operation: "status",
|
|
147
|
+
parameters: { after: next },
|
|
148
|
+
});
|
|
149
|
+
runs.push(...list(page["runs"]).map(statusOf));
|
|
150
|
+
next = page["next"];
|
|
151
|
+
}
|
|
152
|
+
return runs;
|
|
153
|
+
}
|
|
154
|
+
async function decisionsOf(reader) {
|
|
155
|
+
const questions = await asked(reader, {
|
|
156
|
+
operation: "questions",
|
|
157
|
+
parameters: {},
|
|
158
|
+
});
|
|
159
|
+
return list(questions["decisions"]);
|
|
160
|
+
}
|
|
161
|
+
function stoppedTicketIds(runs, now) {
|
|
162
|
+
const stopped = runs
|
|
163
|
+
.map((run) => run.status)
|
|
164
|
+
.filter((status) => recentRun(status.latestAt, now) &&
|
|
165
|
+
status["workflowId"] === "develop-issue" &&
|
|
166
|
+
(["failed", "cancelled"].includes(status.state) ||
|
|
167
|
+
(status.state === "completed" &&
|
|
168
|
+
record(status["outcome"])?.["kind"] === "blocked")))
|
|
169
|
+
.toSorted((first, second) => Date.parse(second.latestAt ?? "") - Date.parse(first.latestAt ?? ""))
|
|
170
|
+
.slice(0, 20);
|
|
171
|
+
return new Set(stopped.flatMap((status) => {
|
|
172
|
+
const ticketId = status["ticketId"];
|
|
173
|
+
return status.state === "completed" &&
|
|
174
|
+
typeof ticketId === "string" &&
|
|
175
|
+
ticketId !== ""
|
|
176
|
+
? [ticketId]
|
|
177
|
+
: [];
|
|
178
|
+
}));
|
|
179
|
+
}
|
|
180
|
+
async function service(reader, now) {
|
|
181
|
+
const status = await asked(reader, {
|
|
182
|
+
operation: "status",
|
|
183
|
+
parameters: {},
|
|
184
|
+
}).catch(() => null);
|
|
185
|
+
if (status === null || !Array.isArray(status["runs"]))
|
|
186
|
+
return unavailable;
|
|
187
|
+
const summaries = await allRuns(reader, status);
|
|
188
|
+
const runs = [];
|
|
189
|
+
const completionCandidates = [];
|
|
190
|
+
const current = summaries.filter((summary) => activeRun(summary.state) || recentRun(summary.latestAt, now));
|
|
191
|
+
for (const summary of current)
|
|
192
|
+
runs.push(await detailed(reader, summary));
|
|
193
|
+
const ticketIds = stoppedTicketIds(runs, now);
|
|
194
|
+
const older = ticketIds.size === 0
|
|
195
|
+
? []
|
|
196
|
+
: summaries.filter((summary) => !recentRun(summary.latestAt, now) &&
|
|
197
|
+
summary["workflowId"] === "develop-issue" &&
|
|
198
|
+
summary.state === "completed");
|
|
199
|
+
for (const summary of older) {
|
|
200
|
+
const candidate = await completionOf(reader, { summary, ticketIds });
|
|
201
|
+
if (candidate !== null)
|
|
202
|
+
completionCandidates.push(candidate);
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
service: "up",
|
|
206
|
+
workflows: list(status["workflows"]).filter((value) => typeof value === "string"),
|
|
207
|
+
summaries,
|
|
208
|
+
runs,
|
|
209
|
+
completionCandidates,
|
|
210
|
+
decisions: await decisionsOf(reader),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
async function singleRun(reader, runId) {
|
|
214
|
+
const reply = await send(reader.runtimeDirectory, {
|
|
215
|
+
operation: "status",
|
|
216
|
+
parameters: { runId },
|
|
217
|
+
});
|
|
218
|
+
if (reply.kind === "error" && reply.error.code === "unknown-run")
|
|
219
|
+
return unavailable;
|
|
220
|
+
if (reply.kind === "error")
|
|
221
|
+
throw new Error(reply.error.code);
|
|
222
|
+
const status = statusOf(reply.result["run"]);
|
|
223
|
+
const known = reader.details.get(runId);
|
|
224
|
+
const value = known !== undefined && known.sequence === status.latestSequence
|
|
225
|
+
? known.value
|
|
226
|
+
: await remember(reader, status);
|
|
227
|
+
return {
|
|
228
|
+
...unavailable,
|
|
229
|
+
service: "up",
|
|
230
|
+
runs: [value],
|
|
231
|
+
decisions: await decisionsOf(reader),
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
export function watchReader(runtimeDirectory) {
|
|
235
|
+
const reader = {
|
|
236
|
+
runtimeDirectory,
|
|
237
|
+
details: new Map(),
|
|
238
|
+
completions: new Map(),
|
|
239
|
+
};
|
|
240
|
+
return {
|
|
241
|
+
read: (now) => service(reader, now),
|
|
242
|
+
run: (runId) => singleRun(reader, runId),
|
|
243
|
+
};
|
|
244
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
export interface WatchItem {
|
|
2
|
+
readonly kind: string;
|
|
3
|
+
readonly text: string;
|
|
4
|
+
readonly costUsd?: number;
|
|
5
|
+
}
|
|
6
|
+
export interface WatchTurn {
|
|
7
|
+
readonly key: string;
|
|
8
|
+
readonly runId: string;
|
|
9
|
+
readonly target: string;
|
|
10
|
+
readonly branch: string;
|
|
11
|
+
readonly worktree: string;
|
|
12
|
+
readonly startedAt: string;
|
|
13
|
+
readonly endedAt: string | null;
|
|
14
|
+
readonly activeAt: string | null;
|
|
15
|
+
readonly outcome: string;
|
|
16
|
+
readonly costUsd: number | null;
|
|
17
|
+
readonly activity: readonly WatchItem[];
|
|
18
|
+
readonly commits: readonly string[];
|
|
19
|
+
readonly files: readonly string[];
|
|
20
|
+
readonly uncommitted: readonly string[];
|
|
21
|
+
readonly summary: string;
|
|
22
|
+
}
|
|
23
|
+
export interface WatchDecision {
|
|
24
|
+
readonly decisionId: string;
|
|
25
|
+
readonly type: string;
|
|
26
|
+
readonly prompt: string;
|
|
27
|
+
readonly approve: string;
|
|
28
|
+
readonly deny: string;
|
|
29
|
+
}
|
|
30
|
+
export interface WatchEvent {
|
|
31
|
+
readonly sequence: number;
|
|
32
|
+
readonly recordedAt: string;
|
|
33
|
+
readonly type: string;
|
|
34
|
+
}
|
|
35
|
+
export interface WatchPhase {
|
|
36
|
+
readonly name: string;
|
|
37
|
+
readonly state: string;
|
|
38
|
+
readonly startedAt: string | null;
|
|
39
|
+
readonly endedAt: string | null;
|
|
40
|
+
}
|
|
41
|
+
export interface WatchFeedback {
|
|
42
|
+
readonly decisionId: string;
|
|
43
|
+
readonly text: string;
|
|
44
|
+
}
|
|
45
|
+
export interface WatchPullRequest {
|
|
46
|
+
readonly number: number;
|
|
47
|
+
readonly url: string;
|
|
48
|
+
}
|
|
49
|
+
export interface WatchReview {
|
|
50
|
+
readonly round: number;
|
|
51
|
+
readonly commit: string;
|
|
52
|
+
readonly score: number;
|
|
53
|
+
}
|
|
54
|
+
export interface WatchStep {
|
|
55
|
+
readonly name: string;
|
|
56
|
+
readonly startedAt: string | null;
|
|
57
|
+
}
|
|
58
|
+
export interface WatchCard {
|
|
59
|
+
readonly runId: string;
|
|
60
|
+
readonly title: string | null;
|
|
61
|
+
readonly claudeCostUsd: number;
|
|
62
|
+
readonly currentStep: WatchStep | null;
|
|
63
|
+
readonly endedAt: string | null;
|
|
64
|
+
readonly decisionWaiting: boolean;
|
|
65
|
+
readonly round: number | null;
|
|
66
|
+
readonly greptileScore: number | null;
|
|
67
|
+
readonly pullRequestNumber: number | null;
|
|
68
|
+
readonly completionMark: WatchCompletionMark | null;
|
|
69
|
+
}
|
|
70
|
+
export interface WatchCompletionMark {
|
|
71
|
+
readonly text: string;
|
|
72
|
+
readonly laterRunId: string | null;
|
|
73
|
+
}
|
|
74
|
+
export interface WatchColumn {
|
|
75
|
+
readonly name: string;
|
|
76
|
+
readonly cards: readonly WatchCard[];
|
|
77
|
+
}
|
|
78
|
+
export interface WatchWorkflow {
|
|
79
|
+
readonly workflowId: string;
|
|
80
|
+
readonly activeCount: number;
|
|
81
|
+
readonly waitingCount: number;
|
|
82
|
+
readonly latestAt: string | null;
|
|
83
|
+
readonly columns: readonly WatchColumn[];
|
|
84
|
+
}
|
|
85
|
+
export interface WatchRun {
|
|
86
|
+
readonly ticketId: string | null;
|
|
87
|
+
readonly title: string | null;
|
|
88
|
+
readonly outcome: string | null;
|
|
89
|
+
readonly latestAt: string | null;
|
|
90
|
+
readonly claudeCostUsd: number;
|
|
91
|
+
readonly currentStep: WatchStep;
|
|
92
|
+
readonly round: number;
|
|
93
|
+
readonly runId: string;
|
|
94
|
+
readonly workflowId: string;
|
|
95
|
+
readonly state: string;
|
|
96
|
+
readonly code: string;
|
|
97
|
+
readonly detail: string;
|
|
98
|
+
readonly spent: number | null;
|
|
99
|
+
readonly limit: number | null;
|
|
100
|
+
readonly decisions: readonly WatchDecision[];
|
|
101
|
+
readonly events: readonly WatchEvent[];
|
|
102
|
+
readonly turns: readonly WatchTurn[];
|
|
103
|
+
readonly phases: readonly WatchPhase[];
|
|
104
|
+
readonly decision: string;
|
|
105
|
+
readonly feedback: readonly WatchFeedback[];
|
|
106
|
+
readonly pullRequest: WatchPullRequest | null;
|
|
107
|
+
readonly reviews: readonly WatchReview[];
|
|
108
|
+
readonly mergeCommit: string | null;
|
|
109
|
+
}
|
|
110
|
+
export interface WatchModel {
|
|
111
|
+
readonly workflows: readonly WatchWorkflow[];
|
|
112
|
+
readonly startWorkflowId: string | null;
|
|
113
|
+
readonly updatedAt: string;
|
|
114
|
+
readonly service: string;
|
|
115
|
+
readonly runs: readonly WatchRun[];
|
|
116
|
+
}
|
|
117
|
+
export interface WatchTone {
|
|
118
|
+
readonly tone: string;
|
|
119
|
+
readonly icon: string;
|
|
120
|
+
readonly label: string;
|
|
121
|
+
}
|
|
122
|
+
export interface Copying {
|
|
123
|
+
readonly command: string;
|
|
124
|
+
readonly label: string;
|
|
125
|
+
readonly onCopy: (command: string) => void;
|
|
126
|
+
}
|
|
127
|
+
export declare function counted(count: number, noun: string): string;
|
|
128
|
+
export declare function elapsed(from: string, to: string): string;
|
|
129
|
+
export declare function clockTime(time: string): string;
|
|
130
|
+
export declare function groupActivity(activity: readonly WatchItem[]): WatchItem[][];
|
|
131
|
+
export declare function turnTime(turn: WatchTurn, now: string): string;
|
|
132
|
+
export declare function toneOf(state: string): WatchTone;
|
|
133
|
+
export declare function runTone(run: WatchRun): WatchTone;
|
|
134
|
+
export declare function runName(run: WatchRun): string;
|
|
135
|
+
export declare function waitingDetail(run: WatchRun, now: string): string;
|
|
136
|
+
export declare function completedDetail(run: WatchRun): string;
|
|
137
|
+
export declare function phaseTime(phase: WatchPhase, now: string): string;
|
|
138
|
+
export declare function selectedRun(model: WatchModel, selected: string): WatchRun | undefined;
|
|
139
|
+
export declare function pageTitle(model: WatchModel, selected: string): string;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
export function counted(count, noun) {
|
|
2
|
+
return `${String(count)} ${noun}${count === 1 ? "" : "s"}`;
|
|
3
|
+
}
|
|
4
|
+
export function elapsed(from, to) {
|
|
5
|
+
const span = Math.round((Date.parse(to) - Date.parse(from)) / 1000);
|
|
6
|
+
if (Number.isNaN(span))
|
|
7
|
+
return "";
|
|
8
|
+
const seconds = Math.max(0, span);
|
|
9
|
+
const minutes = Math.floor(seconds / 60);
|
|
10
|
+
if (minutes === 0)
|
|
11
|
+
return `${String(seconds)} s`;
|
|
12
|
+
if (minutes < 60)
|
|
13
|
+
return `${String(minutes)} min ${String(seconds % 60)} s`;
|
|
14
|
+
return `${String(Math.floor(minutes / 60))} h ${String(minutes % 60)} min`;
|
|
15
|
+
}
|
|
16
|
+
export function clockTime(time) {
|
|
17
|
+
const moment = new Date(time);
|
|
18
|
+
return Number.isNaN(moment.getTime()) ? "" : moment.toLocaleTimeString();
|
|
19
|
+
}
|
|
20
|
+
export function groupActivity(activity) {
|
|
21
|
+
const routine = (item) => item?.kind === "tool" || item?.kind === "error";
|
|
22
|
+
return activity.reduce((groups, item) => {
|
|
23
|
+
const last = groups.at(-1) ?? [];
|
|
24
|
+
if (routine(item) && routine(last[0]))
|
|
25
|
+
return [...groups.slice(0, -1), [...last, item]];
|
|
26
|
+
return [...groups, [item]];
|
|
27
|
+
}, []);
|
|
28
|
+
}
|
|
29
|
+
export function turnTime(turn, now) {
|
|
30
|
+
if (turn.outcome === "in work")
|
|
31
|
+
return elapsed(turn.startedAt, now);
|
|
32
|
+
return turn.endedAt === null ? "" : elapsed(turn.startedAt, turn.endedAt);
|
|
33
|
+
}
|
|
34
|
+
export function toneOf(state) {
|
|
35
|
+
const tones = {
|
|
36
|
+
waiting_gate: ["attention", "!", "Needs your decision"],
|
|
37
|
+
running: ["working", "●", "In work"],
|
|
38
|
+
paused: ["attention", "Ⅱ", "Paused"],
|
|
39
|
+
completed: ["good", "✓", "Completed"],
|
|
40
|
+
failed: ["bad", "✕", "Failed"],
|
|
41
|
+
cancelled: ["bad", "✕", "Dropped"],
|
|
42
|
+
};
|
|
43
|
+
const [tone, icon, label] = tones[state] ?? ["idle", "○", state];
|
|
44
|
+
return { tone, icon, label };
|
|
45
|
+
}
|
|
46
|
+
export function runTone(run) {
|
|
47
|
+
if (run.state === "completed" && run.decision === "denied")
|
|
48
|
+
return { tone: "idle", icon: "✕", label: "Denied" };
|
|
49
|
+
return toneOf(run.state);
|
|
50
|
+
}
|
|
51
|
+
export function runName(run) {
|
|
52
|
+
return run.turns[0]?.target ?? run.runId.slice(0, 12);
|
|
53
|
+
}
|
|
54
|
+
export function waitingDetail(run, now) {
|
|
55
|
+
const opened = run.phases.find((phase) => phase.state === "active");
|
|
56
|
+
const since = opened?.startedAt ?? null;
|
|
57
|
+
const waited = since === null ? "" : ` for ${elapsed(since, now)}`;
|
|
58
|
+
return `A decision waits for you${waited}. Examine the work, then approve or deny.`;
|
|
59
|
+
}
|
|
60
|
+
export function completedDetail(run) {
|
|
61
|
+
const [first] = run.events;
|
|
62
|
+
const last = run.events.at(-1);
|
|
63
|
+
const cost = run.turns.reduce((sum, turn) => sum + (turn.costUsd ?? 0), 0);
|
|
64
|
+
const time = first === undefined || last === undefined
|
|
65
|
+
? ""
|
|
66
|
+
: ` in ${elapsed(first.recordedAt, last.recordedAt)}`;
|
|
67
|
+
const verdicts = {
|
|
68
|
+
approved: "You approved the work. ",
|
|
69
|
+
denied: "You denied the work. ",
|
|
70
|
+
};
|
|
71
|
+
return `${verdicts[run.decision] ?? ""}The run completed${time} · cost ${cost.toFixed(2)} USD.`;
|
|
72
|
+
}
|
|
73
|
+
export function phaseTime(phase, now) {
|
|
74
|
+
if (phase.startedAt === null)
|
|
75
|
+
return "";
|
|
76
|
+
if (phase.endedAt === null)
|
|
77
|
+
return phase.state === "active" ? elapsed(phase.startedAt, now) : "";
|
|
78
|
+
return phase.startedAt === phase.endedAt
|
|
79
|
+
? clockTime(phase.startedAt)
|
|
80
|
+
: elapsed(phase.startedAt, phase.endedAt);
|
|
81
|
+
}
|
|
82
|
+
export function selectedRun(model, selected) {
|
|
83
|
+
if (selected === "")
|
|
84
|
+
return model.runs[0];
|
|
85
|
+
return model.runs.find((run) => run.runId === selected);
|
|
86
|
+
}
|
|
87
|
+
export function pageTitle(model, selected) {
|
|
88
|
+
const run = selectedRun(model, selected);
|
|
89
|
+
if (run === undefined)
|
|
90
|
+
return "Cloving";
|
|
91
|
+
const waiting = model.runs.filter((item) => item.state === "waiting_gate");
|
|
92
|
+
const count = waiting.length === 0 ? "" : `(${String(waiting.length)}) `;
|
|
93
|
+
const { icon, label } = runTone(run);
|
|
94
|
+
return `${count}${icon} ${label} · ${runName(run)} · Cloving`;
|
|
95
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const defaultWatchPort = 3663;
|
|
2
|
+
export interface WatchSettings {
|
|
3
|
+
readonly runtimeDirectory: string;
|
|
4
|
+
readonly port: number;
|
|
5
|
+
readonly client: string;
|
|
6
|
+
readonly announce: (text: string) => void;
|
|
7
|
+
readonly complain: (text: string) => void;
|
|
8
|
+
readonly stopped: Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export declare function watchServer(settings: WatchSettings): Promise<number>;
|