@herdctl/core 0.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/.turbo/turbo-build.log +4 -0
- package/.turbo/turbo-test.log +219 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/coverage-final.json +51 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +251 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +210 -0
- package/coverage/src/config/index.html +191 -0
- package/coverage/src/config/index.ts.html +442 -0
- package/coverage/src/config/interpolate.ts.html +652 -0
- package/coverage/src/config/loader.ts.html +1501 -0
- package/coverage/src/config/merge.ts.html +823 -0
- package/coverage/src/config/parser.ts.html +1213 -0
- package/coverage/src/config/schema.ts.html +1123 -0
- package/coverage/src/fleet-manager/errors.ts.html +2326 -0
- package/coverage/src/fleet-manager/event-types.ts.html +1219 -0
- package/coverage/src/fleet-manager/fleet-manager.ts.html +7030 -0
- package/coverage/src/fleet-manager/index.html +206 -0
- package/coverage/src/fleet-manager/index.ts.html +469 -0
- package/coverage/src/fleet-manager/job-manager.ts.html +2074 -0
- package/coverage/src/fleet-manager/job-queue.ts.html +2479 -0
- package/coverage/src/fleet-manager/types.ts.html +2602 -0
- package/coverage/src/index.html +116 -0
- package/coverage/src/index.ts.html +181 -0
- package/coverage/src/runner/errors.ts.html +1006 -0
- package/coverage/src/runner/index.html +191 -0
- package/coverage/src/runner/index.ts.html +256 -0
- package/coverage/src/runner/job-executor.ts.html +1429 -0
- package/coverage/src/runner/message-processor.ts.html +1150 -0
- package/coverage/src/runner/sdk-adapter.ts.html +658 -0
- package/coverage/src/runner/types.ts.html +559 -0
- package/coverage/src/scheduler/errors.ts.html +388 -0
- package/coverage/src/scheduler/index.html +206 -0
- package/coverage/src/scheduler/index.ts.html +244 -0
- package/coverage/src/scheduler/interval.ts.html +652 -0
- package/coverage/src/scheduler/schedule-runner.ts.html +1411 -0
- package/coverage/src/scheduler/schedule-state.ts.html +718 -0
- package/coverage/src/scheduler/scheduler.ts.html +1795 -0
- package/coverage/src/scheduler/types.ts.html +733 -0
- package/coverage/src/state/directory.ts.html +736 -0
- package/coverage/src/state/errors.ts.html +376 -0
- package/coverage/src/state/fleet-state.ts.html +937 -0
- package/coverage/src/state/index.html +221 -0
- package/coverage/src/state/index.ts.html +322 -0
- package/coverage/src/state/job-metadata.ts.html +1420 -0
- package/coverage/src/state/job-output.ts.html +1033 -0
- package/coverage/src/state/schemas/fleet-state.ts.html +445 -0
- package/coverage/src/state/schemas/index.html +176 -0
- package/coverage/src/state/schemas/index.ts.html +286 -0
- package/coverage/src/state/schemas/job-metadata.ts.html +628 -0
- package/coverage/src/state/schemas/job-output.ts.html +616 -0
- package/coverage/src/state/schemas/session-info.ts.html +361 -0
- package/coverage/src/state/session.ts.html +844 -0
- package/coverage/src/state/types.ts.html +262 -0
- package/coverage/src/state/utils/atomic.ts.html +748 -0
- package/coverage/src/state/utils/index.html +146 -0
- package/coverage/src/state/utils/index.ts.html +103 -0
- package/coverage/src/state/utils/reads.ts.html +1621 -0
- package/coverage/src/work-sources/adapters/github.ts.html +3583 -0
- package/coverage/src/work-sources/adapters/index.html +131 -0
- package/coverage/src/work-sources/adapters/index.ts.html +277 -0
- package/coverage/src/work-sources/errors.ts.html +298 -0
- package/coverage/src/work-sources/index.html +176 -0
- package/coverage/src/work-sources/index.ts.html +529 -0
- package/coverage/src/work-sources/manager.ts.html +1324 -0
- package/coverage/src/work-sources/registry.ts.html +619 -0
- package/coverage/src/work-sources/types.ts.html +568 -0
- package/dist/config/__tests__/agent.test.d.ts +2 -0
- package/dist/config/__tests__/agent.test.d.ts.map +1 -0
- package/dist/config/__tests__/agent.test.js +752 -0
- package/dist/config/__tests__/agent.test.js.map +1 -0
- package/dist/config/__tests__/interpolate.test.d.ts +2 -0
- package/dist/config/__tests__/interpolate.test.d.ts.map +1 -0
- package/dist/config/__tests__/interpolate.test.js +509 -0
- package/dist/config/__tests__/interpolate.test.js.map +1 -0
- package/dist/config/__tests__/loader.test.d.ts +2 -0
- package/dist/config/__tests__/loader.test.d.ts.map +1 -0
- package/dist/config/__tests__/loader.test.js +631 -0
- package/dist/config/__tests__/loader.test.js.map +1 -0
- package/dist/config/__tests__/merge.test.d.ts +2 -0
- package/dist/config/__tests__/merge.test.d.ts.map +1 -0
- package/dist/config/__tests__/merge.test.js +672 -0
- package/dist/config/__tests__/merge.test.js.map +1 -0
- package/dist/config/__tests__/parser.test.d.ts +2 -0
- package/dist/config/__tests__/parser.test.d.ts.map +1 -0
- package/dist/config/__tests__/parser.test.js +476 -0
- package/dist/config/__tests__/parser.test.js.map +1 -0
- package/dist/config/__tests__/schema.test.d.ts +2 -0
- package/dist/config/__tests__/schema.test.d.ts.map +1 -0
- package/dist/config/__tests__/schema.test.js +776 -0
- package/dist/config/__tests__/schema.test.js.map +1 -0
- package/dist/config/index.d.ts +11 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +26 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/interpolate.d.ts +76 -0
- package/dist/config/interpolate.d.ts.map +1 -0
- package/dist/config/interpolate.js +143 -0
- package/dist/config/interpolate.js.map +1 -0
- package/dist/config/loader.d.ts +147 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +336 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/merge.d.ts +84 -0
- package/dist/config/merge.d.ts.map +1 -0
- package/dist/config/merge.js +138 -0
- package/dist/config/merge.js.map +1 -0
- package/dist/config/parser.d.ts +143 -0
- package/dist/config/parser.d.ts.map +1 -0
- package/dist/config/parser.js +316 -0
- package/dist/config/parser.js.map +1 -0
- package/dist/config/schema.d.ts +1906 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +268 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/fleet-manager/__tests__/coverage.test.d.ts +13 -0
- package/dist/fleet-manager/__tests__/coverage.test.d.ts.map +1 -0
- package/dist/fleet-manager/__tests__/coverage.test.js +2282 -0
- package/dist/fleet-manager/__tests__/coverage.test.js.map +1 -0
- package/dist/fleet-manager/__tests__/errors.test.d.ts +7 -0
- package/dist/fleet-manager/__tests__/errors.test.d.ts.map +1 -0
- package/dist/fleet-manager/__tests__/errors.test.js +557 -0
- package/dist/fleet-manager/__tests__/errors.test.js.map +1 -0
- package/dist/fleet-manager/__tests__/event-helpers.test.d.ts +7 -0
- package/dist/fleet-manager/__tests__/event-helpers.test.d.ts.map +1 -0
- package/dist/fleet-manager/__tests__/event-helpers.test.js +368 -0
- package/dist/fleet-manager/__tests__/event-helpers.test.js.map +1 -0
- package/dist/fleet-manager/__tests__/integration.test.d.ts +11 -0
- package/dist/fleet-manager/__tests__/integration.test.d.ts.map +1 -0
- package/dist/fleet-manager/__tests__/integration.test.js +949 -0
- package/dist/fleet-manager/__tests__/integration.test.js.map +1 -0
- package/dist/fleet-manager/__tests__/job-control.test.d.ts +7 -0
- package/dist/fleet-manager/__tests__/job-control.test.d.ts.map +1 -0
- package/dist/fleet-manager/__tests__/job-control.test.js +215 -0
- package/dist/fleet-manager/__tests__/job-control.test.js.map +1 -0
- package/dist/fleet-manager/__tests__/job-manager.test.d.ts +7 -0
- package/dist/fleet-manager/__tests__/job-manager.test.d.ts.map +1 -0
- package/dist/fleet-manager/__tests__/job-manager.test.js +659 -0
- package/dist/fleet-manager/__tests__/job-manager.test.js.map +1 -0
- package/dist/fleet-manager/__tests__/job-queue.test.d.ts +5 -0
- package/dist/fleet-manager/__tests__/job-queue.test.d.ts.map +1 -0
- package/dist/fleet-manager/__tests__/job-queue.test.js +315 -0
- package/dist/fleet-manager/__tests__/job-queue.test.js.map +1 -0
- package/dist/fleet-manager/__tests__/reload.test.d.ts +7 -0
- package/dist/fleet-manager/__tests__/reload.test.d.ts.map +1 -0
- package/dist/fleet-manager/__tests__/reload.test.js +609 -0
- package/dist/fleet-manager/__tests__/reload.test.js.map +1 -0
- package/dist/fleet-manager/__tests__/status-queries.test.d.ts +7 -0
- package/dist/fleet-manager/__tests__/status-queries.test.d.ts.map +1 -0
- package/dist/fleet-manager/__tests__/status-queries.test.js +488 -0
- package/dist/fleet-manager/__tests__/status-queries.test.js.map +1 -0
- package/dist/fleet-manager/__tests__/trigger.test.d.ts +7 -0
- package/dist/fleet-manager/__tests__/trigger.test.d.ts.map +1 -0
- package/dist/fleet-manager/__tests__/trigger.test.js +471 -0
- package/dist/fleet-manager/__tests__/trigger.test.js.map +1 -0
- package/dist/fleet-manager/errors.d.ts +407 -0
- package/dist/fleet-manager/errors.d.ts.map +1 -0
- package/dist/fleet-manager/errors.js +569 -0
- package/dist/fleet-manager/errors.js.map +1 -0
- package/dist/fleet-manager/event-types.d.ts +302 -0
- package/dist/fleet-manager/event-types.d.ts.map +1 -0
- package/dist/fleet-manager/event-types.js +9 -0
- package/dist/fleet-manager/event-types.js.map +1 -0
- package/dist/fleet-manager/fleet-manager.d.ts +699 -0
- package/dist/fleet-manager/fleet-manager.d.ts.map +1 -0
- package/dist/fleet-manager/fleet-manager.js +1906 -0
- package/dist/fleet-manager/fleet-manager.js.map +1 -0
- package/dist/fleet-manager/index.d.ts +17 -0
- package/dist/fleet-manager/index.d.ts.map +1 -0
- package/dist/fleet-manager/index.js +29 -0
- package/dist/fleet-manager/index.js.map +1 -0
- package/dist/fleet-manager/job-manager.d.ts +271 -0
- package/dist/fleet-manager/job-manager.d.ts.map +1 -0
- package/dist/fleet-manager/job-manager.js +443 -0
- package/dist/fleet-manager/job-manager.js.map +1 -0
- package/dist/fleet-manager/job-queue.d.ts +422 -0
- package/dist/fleet-manager/job-queue.d.ts.map +1 -0
- package/dist/fleet-manager/job-queue.js +448 -0
- package/dist/fleet-manager/job-queue.js.map +1 -0
- package/dist/fleet-manager/types.d.ts +680 -0
- package/dist/fleet-manager/types.d.ts.map +1 -0
- package/dist/fleet-manager/types.js +8 -0
- package/dist/fleet-manager/types.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/runner/__tests__/errors.test.d.ts +2 -0
- package/dist/runner/__tests__/errors.test.d.ts.map +1 -0
- package/dist/runner/__tests__/errors.test.js +264 -0
- package/dist/runner/__tests__/errors.test.js.map +1 -0
- package/dist/runner/__tests__/job-executor.test.d.ts +2 -0
- package/dist/runner/__tests__/job-executor.test.d.ts.map +1 -0
- package/dist/runner/__tests__/job-executor.test.js +1345 -0
- package/dist/runner/__tests__/job-executor.test.js.map +1 -0
- package/dist/runner/__tests__/message-processor.test.d.ts +2 -0
- package/dist/runner/__tests__/message-processor.test.d.ts.map +1 -0
- package/dist/runner/__tests__/message-processor.test.js +768 -0
- package/dist/runner/__tests__/message-processor.test.js.map +1 -0
- package/dist/runner/__tests__/sdk-adapter.test.d.ts +2 -0
- package/dist/runner/__tests__/sdk-adapter.test.d.ts.map +1 -0
- package/dist/runner/__tests__/sdk-adapter.test.js +554 -0
- package/dist/runner/__tests__/sdk-adapter.test.js.map +1 -0
- package/dist/runner/errors.d.ts +121 -0
- package/dist/runner/errors.d.ts.map +1 -0
- package/dist/runner/errors.js +212 -0
- package/dist/runner/errors.js.map +1 -0
- package/dist/runner/index.d.ts +12 -0
- package/dist/runner/index.d.ts.map +1 -0
- package/dist/runner/index.js +15 -0
- package/dist/runner/index.js.map +1 -0
- package/dist/runner/job-executor.d.ts +98 -0
- package/dist/runner/job-executor.d.ts.map +1 -0
- package/dist/runner/job-executor.js +333 -0
- package/dist/runner/job-executor.js.map +1 -0
- package/dist/runner/message-processor.d.ts +45 -0
- package/dist/runner/message-processor.d.ts.map +1 -0
- package/dist/runner/message-processor.js +294 -0
- package/dist/runner/message-processor.js.map +1 -0
- package/dist/runner/sdk-adapter.d.ts +60 -0
- package/dist/runner/sdk-adapter.d.ts.map +1 -0
- package/dist/runner/sdk-adapter.js +138 -0
- package/dist/runner/sdk-adapter.js.map +1 -0
- package/dist/runner/types.d.ts +135 -0
- package/dist/runner/types.d.ts.map +1 -0
- package/dist/runner/types.js +7 -0
- package/dist/runner/types.js.map +1 -0
- package/dist/scheduler/__tests__/errors.test.d.ts +2 -0
- package/dist/scheduler/__tests__/errors.test.d.ts.map +1 -0
- package/dist/scheduler/__tests__/errors.test.js +101 -0
- package/dist/scheduler/__tests__/errors.test.js.map +1 -0
- package/dist/scheduler/__tests__/interval.test.d.ts +2 -0
- package/dist/scheduler/__tests__/interval.test.d.ts.map +1 -0
- package/dist/scheduler/__tests__/interval.test.js +419 -0
- package/dist/scheduler/__tests__/interval.test.js.map +1 -0
- package/dist/scheduler/__tests__/schedule-runner.test.d.ts +2 -0
- package/dist/scheduler/__tests__/schedule-runner.test.d.ts.map +1 -0
- package/dist/scheduler/__tests__/schedule-runner.test.js +634 -0
- package/dist/scheduler/__tests__/schedule-runner.test.js.map +1 -0
- package/dist/scheduler/__tests__/schedule-state.test.d.ts +2 -0
- package/dist/scheduler/__tests__/schedule-state.test.d.ts.map +1 -0
- package/dist/scheduler/__tests__/schedule-state.test.js +572 -0
- package/dist/scheduler/__tests__/schedule-state.test.js.map +1 -0
- package/dist/scheduler/__tests__/scheduler.test.d.ts +2 -0
- package/dist/scheduler/__tests__/scheduler.test.d.ts.map +1 -0
- package/dist/scheduler/__tests__/scheduler.test.js +987 -0
- package/dist/scheduler/__tests__/scheduler.test.js.map +1 -0
- package/dist/scheduler/errors.d.ts +61 -0
- package/dist/scheduler/errors.d.ts.map +1 -0
- package/dist/scheduler/errors.js +81 -0
- package/dist/scheduler/errors.js.map +1 -0
- package/dist/scheduler/index.d.ts +13 -0
- package/dist/scheduler/index.d.ts.map +1 -0
- package/dist/scheduler/index.js +17 -0
- package/dist/scheduler/index.js.map +1 -0
- package/dist/scheduler/interval.d.ts +64 -0
- package/dist/scheduler/interval.d.ts.map +1 -0
- package/dist/scheduler/interval.js +139 -0
- package/dist/scheduler/interval.js.map +1 -0
- package/dist/scheduler/schedule-runner.d.ts +149 -0
- package/dist/scheduler/schedule-runner.d.ts.map +1 -0
- package/dist/scheduler/schedule-runner.js +277 -0
- package/dist/scheduler/schedule-runner.js.map +1 -0
- package/dist/scheduler/schedule-state.d.ts +105 -0
- package/dist/scheduler/schedule-state.d.ts.map +1 -0
- package/dist/scheduler/schedule-state.js +151 -0
- package/dist/scheduler/schedule-state.js.map +1 -0
- package/dist/scheduler/scheduler.d.ts +138 -0
- package/dist/scheduler/scheduler.d.ts.map +1 -0
- package/dist/scheduler/scheduler.js +423 -0
- package/dist/scheduler/scheduler.js.map +1 -0
- package/dist/scheduler/types.d.ts +160 -0
- package/dist/scheduler/types.d.ts.map +1 -0
- package/dist/scheduler/types.js +8 -0
- package/dist/scheduler/types.js.map +1 -0
- package/dist/state/__tests__/directory.test.d.ts +2 -0
- package/dist/state/__tests__/directory.test.d.ts.map +1 -0
- package/dist/state/__tests__/directory.test.js +414 -0
- package/dist/state/__tests__/directory.test.js.map +1 -0
- package/dist/state/__tests__/fleet-state.test.d.ts +2 -0
- package/dist/state/__tests__/fleet-state.test.d.ts.map +1 -0
- package/dist/state/__tests__/fleet-state.test.js +696 -0
- package/dist/state/__tests__/fleet-state.test.js.map +1 -0
- package/dist/state/__tests__/job-metadata-schema.test.d.ts +2 -0
- package/dist/state/__tests__/job-metadata-schema.test.d.ts.map +1 -0
- package/dist/state/__tests__/job-metadata-schema.test.js +329 -0
- package/dist/state/__tests__/job-metadata-schema.test.js.map +1 -0
- package/dist/state/__tests__/job-metadata.test.d.ts +2 -0
- package/dist/state/__tests__/job-metadata.test.d.ts.map +1 -0
- package/dist/state/__tests__/job-metadata.test.js +667 -0
- package/dist/state/__tests__/job-metadata.test.js.map +1 -0
- package/dist/state/__tests__/job-output.test.d.ts +2 -0
- package/dist/state/__tests__/job-output.test.d.ts.map +1 -0
- package/dist/state/__tests__/job-output.test.js +672 -0
- package/dist/state/__tests__/job-output.test.js.map +1 -0
- package/dist/state/__tests__/session-schema.test.d.ts +2 -0
- package/dist/state/__tests__/session-schema.test.d.ts.map +1 -0
- package/dist/state/__tests__/session-schema.test.js +323 -0
- package/dist/state/__tests__/session-schema.test.js.map +1 -0
- package/dist/state/__tests__/session.test.d.ts +2 -0
- package/dist/state/__tests__/session.test.d.ts.map +1 -0
- package/dist/state/__tests__/session.test.js +468 -0
- package/dist/state/__tests__/session.test.js.map +1 -0
- package/dist/state/directory.d.ts +42 -0
- package/dist/state/directory.d.ts.map +1 -0
- package/dist/state/directory.js +170 -0
- package/dist/state/directory.js.map +1 -0
- package/dist/state/errors.d.ts +44 -0
- package/dist/state/errors.d.ts.map +1 -0
- package/dist/state/errors.js +82 -0
- package/dist/state/errors.js.map +1 -0
- package/dist/state/fleet-state.d.ts +126 -0
- package/dist/state/fleet-state.d.ts.map +1 -0
- package/dist/state/fleet-state.js +196 -0
- package/dist/state/fleet-state.js.map +1 -0
- package/dist/state/index.d.ts +21 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +30 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/job-metadata.d.ts +151 -0
- package/dist/state/job-metadata.d.ts.map +1 -0
- package/dist/state/job-metadata.js +287 -0
- package/dist/state/job-metadata.js.map +1 -0
- package/dist/state/job-output.d.ts +116 -0
- package/dist/state/job-output.d.ts.map +1 -0
- package/dist/state/job-output.js +218 -0
- package/dist/state/job-output.js.map +1 -0
- package/dist/state/schemas/__tests__/job-output.test.d.ts +2 -0
- package/dist/state/schemas/__tests__/job-output.test.d.ts.map +1 -0
- package/dist/state/schemas/__tests__/job-output.test.js +279 -0
- package/dist/state/schemas/__tests__/job-output.test.js.map +1 -0
- package/dist/state/schemas/fleet-state.d.ts +249 -0
- package/dist/state/schemas/fleet-state.d.ts.map +1 -0
- package/dist/state/schemas/fleet-state.js +97 -0
- package/dist/state/schemas/fleet-state.js.map +1 -0
- package/dist/state/schemas/index.d.ts +10 -0
- package/dist/state/schemas/index.d.ts.map +1 -0
- package/dist/state/schemas/index.js +10 -0
- package/dist/state/schemas/index.js.map +1 -0
- package/dist/state/schemas/job-metadata.d.ts +118 -0
- package/dist/state/schemas/job-metadata.d.ts.map +1 -0
- package/dist/state/schemas/job-metadata.js +123 -0
- package/dist/state/schemas/job-metadata.js.map +1 -0
- package/dist/state/schemas/job-output.d.ts +291 -0
- package/dist/state/schemas/job-output.d.ts.map +1 -0
- package/dist/state/schemas/job-output.js +132 -0
- package/dist/state/schemas/job-output.js.map +1 -0
- package/dist/state/schemas/session-info.d.ts +65 -0
- package/dist/state/schemas/session-info.d.ts.map +1 -0
- package/dist/state/schemas/session-info.js +58 -0
- package/dist/state/schemas/session-info.js.map +1 -0
- package/dist/state/session.d.ts +92 -0
- package/dist/state/session.d.ts.map +1 -0
- package/dist/state/session.js +173 -0
- package/dist/state/session.js.map +1 -0
- package/dist/state/types.d.ts +54 -0
- package/dist/state/types.d.ts.map +1 -0
- package/dist/state/types.js +18 -0
- package/dist/state/types.js.map +1 -0
- package/dist/state/utils/__tests__/atomic.test.d.ts +2 -0
- package/dist/state/utils/__tests__/atomic.test.d.ts.map +1 -0
- package/dist/state/utils/__tests__/atomic.test.js +537 -0
- package/dist/state/utils/__tests__/atomic.test.js.map +1 -0
- package/dist/state/utils/__tests__/reads.test.d.ts +2 -0
- package/dist/state/utils/__tests__/reads.test.d.ts.map +1 -0
- package/dist/state/utils/__tests__/reads.test.js +792 -0
- package/dist/state/utils/__tests__/reads.test.js.map +1 -0
- package/dist/state/utils/atomic.d.ts +89 -0
- package/dist/state/utils/atomic.d.ts.map +1 -0
- package/dist/state/utils/atomic.js +157 -0
- package/dist/state/utils/atomic.js.map +1 -0
- package/dist/state/utils/index.d.ts +6 -0
- package/dist/state/utils/index.d.ts.map +1 -0
- package/dist/state/utils/index.js +6 -0
- package/dist/state/utils/index.js.map +1 -0
- package/dist/state/utils/reads.d.ts +196 -0
- package/dist/state/utils/reads.d.ts.map +1 -0
- package/dist/state/utils/reads.js +346 -0
- package/dist/state/utils/reads.js.map +1 -0
- package/dist/work-sources/__tests__/github.test.d.ts +2 -0
- package/dist/work-sources/__tests__/github.test.d.ts.map +1 -0
- package/dist/work-sources/__tests__/github.test.js +1334 -0
- package/dist/work-sources/__tests__/github.test.js.map +1 -0
- package/dist/work-sources/__tests__/manager.test.d.ts +2 -0
- package/dist/work-sources/__tests__/manager.test.d.ts.map +1 -0
- package/dist/work-sources/__tests__/manager.test.js +424 -0
- package/dist/work-sources/__tests__/manager.test.js.map +1 -0
- package/dist/work-sources/__tests__/registry.test.d.ts +2 -0
- package/dist/work-sources/__tests__/registry.test.d.ts.map +1 -0
- package/dist/work-sources/__tests__/registry.test.js +381 -0
- package/dist/work-sources/__tests__/registry.test.js.map +1 -0
- package/dist/work-sources/__tests__/types.test.d.ts +2 -0
- package/dist/work-sources/__tests__/types.test.d.ts.map +1 -0
- package/dist/work-sources/__tests__/types.test.js +406 -0
- package/dist/work-sources/__tests__/types.test.js.map +1 -0
- package/dist/work-sources/adapters/github.d.ts +290 -0
- package/dist/work-sources/adapters/github.d.ts.map +1 -0
- package/dist/work-sources/adapters/github.js +803 -0
- package/dist/work-sources/adapters/github.js.map +1 -0
- package/dist/work-sources/adapters/index.d.ts +10 -0
- package/dist/work-sources/adapters/index.d.ts.map +1 -0
- package/dist/work-sources/adapters/index.js +31 -0
- package/dist/work-sources/adapters/index.js.map +1 -0
- package/dist/work-sources/errors.d.ts +40 -0
- package/dist/work-sources/errors.d.ts.map +1 -0
- package/dist/work-sources/errors.js +54 -0
- package/dist/work-sources/errors.js.map +1 -0
- package/dist/work-sources/index.d.ts +105 -0
- package/dist/work-sources/index.d.ts.map +1 -0
- package/dist/work-sources/index.js +24 -0
- package/dist/work-sources/index.js.map +1 -0
- package/dist/work-sources/manager.d.ts +370 -0
- package/dist/work-sources/manager.d.ts.map +1 -0
- package/dist/work-sources/manager.js +61 -0
- package/dist/work-sources/manager.js.map +1 -0
- package/dist/work-sources/registry.d.ts +128 -0
- package/dist/work-sources/registry.d.ts.map +1 -0
- package/dist/work-sources/registry.js +132 -0
- package/dist/work-sources/registry.js.map +1 -0
- package/dist/work-sources/types.d.ts +127 -0
- package/dist/work-sources/types.d.ts.map +1 -0
- package/dist/work-sources/types.js +8 -0
- package/dist/work-sources/types.js.map +1 -0
- package/package.json +23 -0
- package/src/config/__tests__/agent.test.ts +864 -0
- package/src/config/__tests__/interpolate.test.ts +644 -0
- package/src/config/__tests__/loader.test.ts +784 -0
- package/src/config/__tests__/merge.test.ts +751 -0
- package/src/config/__tests__/parser.test.ts +533 -0
- package/src/config/__tests__/schema.test.ts +873 -0
- package/src/config/index.ts +119 -0
- package/src/config/interpolate.ts +189 -0
- package/src/config/loader.ts +472 -0
- package/src/config/merge.ts +246 -0
- package/src/config/parser.ts +376 -0
- package/src/config/schema.ts +346 -0
- package/src/fleet-manager/__tests__/coverage.test.ts +2869 -0
- package/src/fleet-manager/__tests__/errors.test.ts +660 -0
- package/src/fleet-manager/__tests__/event-helpers.test.ts +448 -0
- package/src/fleet-manager/__tests__/integration.test.ts +1209 -0
- package/src/fleet-manager/__tests__/job-control.test.ts +283 -0
- package/src/fleet-manager/__tests__/job-manager.test.ts +869 -0
- package/src/fleet-manager/__tests__/job-queue.test.ts +401 -0
- package/src/fleet-manager/__tests__/reload.test.ts +751 -0
- package/src/fleet-manager/__tests__/status-queries.test.ts +595 -0
- package/src/fleet-manager/__tests__/trigger.test.ts +601 -0
- package/src/fleet-manager/errors.ts +747 -0
- package/src/fleet-manager/event-types.ts +378 -0
- package/src/fleet-manager/fleet-manager.ts +2315 -0
- package/src/fleet-manager/index.ts +128 -0
- package/src/fleet-manager/job-manager.ts +663 -0
- package/src/fleet-manager/job-queue.ts +798 -0
- package/src/fleet-manager/types.ts +839 -0
- package/src/index.ts +32 -0
- package/src/runner/__tests__/errors.test.ts +382 -0
- package/src/runner/__tests__/job-executor.test.ts +1708 -0
- package/src/runner/__tests__/message-processor.test.ts +960 -0
- package/src/runner/__tests__/sdk-adapter.test.ts +626 -0
- package/src/runner/errors.ts +307 -0
- package/src/runner/index.ts +57 -0
- package/src/runner/job-executor.ts +448 -0
- package/src/runner/message-processor.ts +355 -0
- package/src/runner/sdk-adapter.ts +191 -0
- package/src/runner/types.ts +158 -0
- package/src/scheduler/__tests__/errors.test.ts +159 -0
- package/src/scheduler/__tests__/interval.test.ts +515 -0
- package/src/scheduler/__tests__/schedule-runner.test.ts +798 -0
- package/src/scheduler/__tests__/schedule-state.test.ts +671 -0
- package/src/scheduler/__tests__/scheduler.test.ts +1280 -0
- package/src/scheduler/errors.ts +101 -0
- package/src/scheduler/index.ts +53 -0
- package/src/scheduler/interval.ts +189 -0
- package/src/scheduler/schedule-runner.ts +442 -0
- package/src/scheduler/schedule-state.ts +211 -0
- package/src/scheduler/scheduler.ts +570 -0
- package/src/scheduler/types.ts +216 -0
- package/src/state/__tests__/directory.test.ts +595 -0
- package/src/state/__tests__/fleet-state.test.ts +868 -0
- package/src/state/__tests__/job-metadata-schema.test.ts +414 -0
- package/src/state/__tests__/job-metadata.test.ts +831 -0
- package/src/state/__tests__/job-output.test.ts +856 -0
- package/src/state/__tests__/session-schema.test.ts +378 -0
- package/src/state/__tests__/session.test.ts +604 -0
- package/src/state/directory.ts +217 -0
- package/src/state/errors.ts +97 -0
- package/src/state/fleet-state.ts +284 -0
- package/src/state/index.ts +79 -0
- package/src/state/job-metadata.ts +445 -0
- package/src/state/job-output.ts +316 -0
- package/src/state/schemas/__tests__/job-output.test.ts +338 -0
- package/src/state/schemas/fleet-state.ts +120 -0
- package/src/state/schemas/index.ts +67 -0
- package/src/state/schemas/job-metadata.ts +181 -0
- package/src/state/schemas/job-output.ts +177 -0
- package/src/state/schemas/session-info.ts +92 -0
- package/src/state/session.ts +253 -0
- package/src/state/types.ts +59 -0
- package/src/state/utils/__tests__/atomic.test.ts +723 -0
- package/src/state/utils/__tests__/reads.test.ts +1071 -0
- package/src/state/utils/atomic.ts +221 -0
- package/src/state/utils/index.ts +6 -0
- package/src/state/utils/reads.ts +512 -0
- package/src/work-sources/__tests__/github.test.ts +1800 -0
- package/src/work-sources/__tests__/manager.test.ts +529 -0
- package/src/work-sources/__tests__/registry.test.ts +477 -0
- package/src/work-sources/__tests__/types.test.ts +479 -0
- package/src/work-sources/adapters/github.ts +1166 -0
- package/src/work-sources/adapters/index.ts +64 -0
- package/src/work-sources/errors.ts +71 -0
- package/src/work-sources/index.ts +148 -0
- package/src/work-sources/manager.ts +413 -0
- package/src/work-sources/registry.ts +178 -0
- package/src/work-sources/types.ts +161 -0
- package/tsconfig.json +9 -0
- package/vitest.config.ts +19 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State directory management
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to initialize and access the .herdctl/ state directory
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { mkdir, stat, access, constants } from "node:fs/promises";
|
|
8
|
+
import { join, resolve } from "node:path";
|
|
9
|
+
import {
|
|
10
|
+
type StateDirectory,
|
|
11
|
+
type InitStateDirectoryOptions,
|
|
12
|
+
type StateDirectoryValidation,
|
|
13
|
+
STATE_SUBDIRECTORIES,
|
|
14
|
+
DEFAULT_STATE_DIR_NAME,
|
|
15
|
+
STATE_FILE_NAME,
|
|
16
|
+
} from "./types.js";
|
|
17
|
+
import {
|
|
18
|
+
StateDirectoryCreateError,
|
|
19
|
+
StateDirectoryValidationError,
|
|
20
|
+
StateFileError,
|
|
21
|
+
getPermissionErrorMessage,
|
|
22
|
+
} from "./errors.js";
|
|
23
|
+
import { createInitialFleetState, FleetStateSchema } from "./schemas/index.js";
|
|
24
|
+
import { atomicWriteYaml } from "./utils/index.js";
|
|
25
|
+
import { safeReadYaml } from "./utils/reads.js";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get the paths for all state directory components
|
|
29
|
+
*
|
|
30
|
+
* @param rootPath - Root path to the state directory (e.g., /path/to/.herdctl)
|
|
31
|
+
* @returns StateDirectory object with paths to all subdirectories and files
|
|
32
|
+
*/
|
|
33
|
+
export function getStateDirectory(rootPath?: string): StateDirectory {
|
|
34
|
+
const root = rootPath
|
|
35
|
+
? resolve(rootPath)
|
|
36
|
+
: resolve(process.cwd(), DEFAULT_STATE_DIR_NAME);
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
root,
|
|
40
|
+
jobs: join(root, "jobs"),
|
|
41
|
+
sessions: join(root, "sessions"),
|
|
42
|
+
logs: join(root, "logs"),
|
|
43
|
+
stateFile: join(root, STATE_FILE_NAME),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Check if a path exists and is a directory
|
|
49
|
+
*/
|
|
50
|
+
async function isDirectory(path: string): Promise<boolean> {
|
|
51
|
+
try {
|
|
52
|
+
const stats = await stat(path);
|
|
53
|
+
return stats.isDirectory();
|
|
54
|
+
} catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Check if a path exists (file or directory)
|
|
61
|
+
*/
|
|
62
|
+
async function pathExists(path: string): Promise<boolean> {
|
|
63
|
+
try {
|
|
64
|
+
await access(path, constants.F_OK);
|
|
65
|
+
return true;
|
|
66
|
+
} catch {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Validate that the state directory structure exists and is accessible
|
|
73
|
+
*
|
|
74
|
+
* @param stateDir - StateDirectory object to validate
|
|
75
|
+
* @returns Validation result with any missing paths or errors
|
|
76
|
+
*/
|
|
77
|
+
export async function validateStateDirectory(
|
|
78
|
+
stateDir: StateDirectory
|
|
79
|
+
): Promise<StateDirectoryValidation> {
|
|
80
|
+
const missing: string[] = [];
|
|
81
|
+
const errors: string[] = [];
|
|
82
|
+
|
|
83
|
+
// Check root directory
|
|
84
|
+
if (!(await isDirectory(stateDir.root))) {
|
|
85
|
+
const exists = await pathExists(stateDir.root);
|
|
86
|
+
if (exists) {
|
|
87
|
+
errors.push(`'${stateDir.root}' exists but is not a directory`);
|
|
88
|
+
} else {
|
|
89
|
+
missing.push(stateDir.root);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Check subdirectories
|
|
94
|
+
for (const subdir of STATE_SUBDIRECTORIES) {
|
|
95
|
+
const subdirPath = stateDir[subdir];
|
|
96
|
+
if (!(await isDirectory(subdirPath))) {
|
|
97
|
+
const exists = await pathExists(subdirPath);
|
|
98
|
+
if (exists) {
|
|
99
|
+
errors.push(`'${subdirPath}' exists but is not a directory`);
|
|
100
|
+
} else {
|
|
101
|
+
missing.push(subdirPath);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Check state file (should exist, can be file)
|
|
107
|
+
if (!(await pathExists(stateDir.stateFile))) {
|
|
108
|
+
missing.push(stateDir.stateFile);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
valid: missing.length === 0 && errors.length === 0,
|
|
113
|
+
missing,
|
|
114
|
+
errors,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Create a single directory with descriptive error handling
|
|
120
|
+
*/
|
|
121
|
+
async function createDirectory(path: string): Promise<void> {
|
|
122
|
+
try {
|
|
123
|
+
await mkdir(path, { recursive: true });
|
|
124
|
+
} catch (error) {
|
|
125
|
+
const code = (error as NodeJS.ErrnoException).code;
|
|
126
|
+
throw new StateDirectoryCreateError(
|
|
127
|
+
getPermissionErrorMessage(code, path),
|
|
128
|
+
path,
|
|
129
|
+
error as Error
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Initialize the state directory structure
|
|
136
|
+
*
|
|
137
|
+
* Creates the .herdctl/ directory and its subdirectories (jobs/, sessions/, logs/)
|
|
138
|
+
* if they don't exist. Also creates an initial state.yaml file with empty fleet state.
|
|
139
|
+
*
|
|
140
|
+
* @param options - Options for initialization
|
|
141
|
+
* @returns StateDirectory object with paths to all subdirectories
|
|
142
|
+
* @throws {StateDirectoryCreateError} If directories cannot be created
|
|
143
|
+
* @throws {StateFileError} If state.yaml cannot be created
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* // Initialize in current directory
|
|
148
|
+
* const stateDir = await initStateDirectory();
|
|
149
|
+
*
|
|
150
|
+
* // Initialize in custom location
|
|
151
|
+
* const stateDir = await initStateDirectory({ path: '/custom/path/.herdctl' });
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
export async function initStateDirectory(
|
|
155
|
+
options: InitStateDirectoryOptions = {}
|
|
156
|
+
): Promise<StateDirectory> {
|
|
157
|
+
const stateDir = getStateDirectory(options.path);
|
|
158
|
+
|
|
159
|
+
// Create root directory
|
|
160
|
+
await createDirectory(stateDir.root);
|
|
161
|
+
|
|
162
|
+
// Create subdirectories
|
|
163
|
+
for (const subdir of STATE_SUBDIRECTORIES) {
|
|
164
|
+
await createDirectory(stateDir[subdir]);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Create state.yaml if it doesn't exist
|
|
168
|
+
if (!(await pathExists(stateDir.stateFile))) {
|
|
169
|
+
try {
|
|
170
|
+
const initialState = createInitialFleetState();
|
|
171
|
+
await atomicWriteYaml(stateDir.stateFile, initialState);
|
|
172
|
+
} catch (error) {
|
|
173
|
+
throw new StateFileError(
|
|
174
|
+
`Failed to create initial state file: ${(error as Error).message}`,
|
|
175
|
+
stateDir.stateFile,
|
|
176
|
+
"write",
|
|
177
|
+
error as Error
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
// Validate existing state.yaml is readable and valid
|
|
182
|
+
const result = await safeReadYaml(stateDir.stateFile);
|
|
183
|
+
if (!result.success) {
|
|
184
|
+
throw new StateFileError(
|
|
185
|
+
`Existing state file is corrupted or unreadable: ${result.error.message}`,
|
|
186
|
+
stateDir.stateFile,
|
|
187
|
+
"read",
|
|
188
|
+
result.error
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Validate against schema
|
|
193
|
+
const parseResult = FleetStateSchema.safeParse(result.data);
|
|
194
|
+
if (!parseResult.success) {
|
|
195
|
+
const issues = parseResult.error.issues
|
|
196
|
+
.map((i) => `${i.path.join(".")}: ${i.message}`)
|
|
197
|
+
.join("; ");
|
|
198
|
+
throw new StateFileError(
|
|
199
|
+
`Existing state file has invalid schema: ${issues}`,
|
|
200
|
+
stateDir.stateFile,
|
|
201
|
+
"read"
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Final validation
|
|
207
|
+
const validation = await validateStateDirectory(stateDir);
|
|
208
|
+
if (!validation.valid) {
|
|
209
|
+
const allIssues = [...validation.missing, ...validation.errors];
|
|
210
|
+
throw new StateDirectoryValidationError(
|
|
211
|
+
`State directory validation failed: ${allIssues.join(", ")}`,
|
|
212
|
+
validation.missing
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return stateDir;
|
|
217
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error classes for state management operations
|
|
3
|
+
*
|
|
4
|
+
* Provides typed errors with descriptive messages for state-related failures
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Base error class for state management errors
|
|
9
|
+
*/
|
|
10
|
+
export class StateError extends Error {
|
|
11
|
+
constructor(message: string) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = "StateError";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Error thrown when the state directory cannot be created
|
|
19
|
+
*/
|
|
20
|
+
export class StateDirectoryCreateError extends StateError {
|
|
21
|
+
/** Path that could not be created */
|
|
22
|
+
public readonly path: string;
|
|
23
|
+
/** System error code if available (e.g., EACCES, ENOENT) */
|
|
24
|
+
public readonly code?: string;
|
|
25
|
+
|
|
26
|
+
constructor(message: string, path: string, cause?: Error) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.name = "StateDirectoryCreateError";
|
|
29
|
+
this.path = path;
|
|
30
|
+
this.cause = cause;
|
|
31
|
+
this.code = (cause as NodeJS.ErrnoException | undefined)?.code;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Error thrown when the state directory validation fails
|
|
37
|
+
*/
|
|
38
|
+
export class StateDirectoryValidationError extends StateError {
|
|
39
|
+
/** Paths that failed validation */
|
|
40
|
+
public readonly missingPaths: string[];
|
|
41
|
+
|
|
42
|
+
constructor(message: string, missingPaths: string[]) {
|
|
43
|
+
super(message);
|
|
44
|
+
this.name = "StateDirectoryValidationError";
|
|
45
|
+
this.missingPaths = missingPaths;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Error thrown when the state file cannot be read or written
|
|
51
|
+
*/
|
|
52
|
+
export class StateFileError extends StateError {
|
|
53
|
+
/** Path to the state file */
|
|
54
|
+
public readonly path: string;
|
|
55
|
+
/** The operation that failed */
|
|
56
|
+
public readonly operation: "read" | "write";
|
|
57
|
+
|
|
58
|
+
constructor(
|
|
59
|
+
message: string,
|
|
60
|
+
path: string,
|
|
61
|
+
operation: "read" | "write",
|
|
62
|
+
cause?: Error
|
|
63
|
+
) {
|
|
64
|
+
super(message);
|
|
65
|
+
this.name = "StateFileError";
|
|
66
|
+
this.path = path;
|
|
67
|
+
this.operation = operation;
|
|
68
|
+
this.cause = cause;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Get a descriptive error message for common permission errors
|
|
74
|
+
*/
|
|
75
|
+
export function getPermissionErrorMessage(
|
|
76
|
+
code: string | undefined,
|
|
77
|
+
path: string
|
|
78
|
+
): string {
|
|
79
|
+
switch (code) {
|
|
80
|
+
case "EACCES":
|
|
81
|
+
return `Permission denied: Cannot access '${path}'. Check file permissions.`;
|
|
82
|
+
case "EPERM":
|
|
83
|
+
return `Operation not permitted: Cannot modify '${path}'. This may require elevated privileges.`;
|
|
84
|
+
case "EROFS":
|
|
85
|
+
return `Read-only filesystem: Cannot write to '${path}'.`;
|
|
86
|
+
case "ENOSPC":
|
|
87
|
+
return `No space left on device: Cannot create '${path}'.`;
|
|
88
|
+
case "ENOENT":
|
|
89
|
+
return `Path does not exist: '${path}' or one of its parent directories is missing.`;
|
|
90
|
+
case "ENOTDIR":
|
|
91
|
+
return `Not a directory: A component of '${path}' is not a directory.`;
|
|
92
|
+
case "EEXIST":
|
|
93
|
+
return `Path already exists: '${path}' already exists as a file but should be a directory.`;
|
|
94
|
+
default:
|
|
95
|
+
return `Failed to access '${path}'${code ? ` (${code})` : ""}.`;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fleet state management (state.yaml)
|
|
3
|
+
*
|
|
4
|
+
* Provides functions for reading, writing, and updating fleet state.
|
|
5
|
+
* Handles missing files gracefully and corrupted files with warnings.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { ZodError } from "zod";
|
|
9
|
+
import {
|
|
10
|
+
FleetStateSchema,
|
|
11
|
+
createInitialFleetState,
|
|
12
|
+
type FleetState,
|
|
13
|
+
type AgentState,
|
|
14
|
+
} from "./schemas/fleet-state.js";
|
|
15
|
+
import { safeReadYaml } from "./utils/reads.js";
|
|
16
|
+
import { atomicWriteYaml } from "./utils/atomic.js";
|
|
17
|
+
import { StateFileError } from "./errors.js";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Logger interface for warning messages
|
|
21
|
+
*/
|
|
22
|
+
export interface StateLogger {
|
|
23
|
+
warn: (message: string) => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Default console logger
|
|
28
|
+
*/
|
|
29
|
+
const defaultLogger: StateLogger = {
|
|
30
|
+
warn: (message: string) => console.warn(`[herdctl] ${message}`),
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Options for reading fleet state
|
|
35
|
+
*/
|
|
36
|
+
export interface ReadFleetStateOptions {
|
|
37
|
+
/**
|
|
38
|
+
* Logger for warning messages (e.g., corrupted file warnings)
|
|
39
|
+
* Default: console.warn
|
|
40
|
+
*/
|
|
41
|
+
logger?: StateLogger;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Options for writing fleet state
|
|
46
|
+
*/
|
|
47
|
+
export interface WriteFleetStateOptions {
|
|
48
|
+
/**
|
|
49
|
+
* YAML indent level
|
|
50
|
+
* Default: 2
|
|
51
|
+
*/
|
|
52
|
+
indent?: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Read and validate fleet state from state.yaml
|
|
57
|
+
*
|
|
58
|
+
* Handles:
|
|
59
|
+
* - Missing file: Returns default empty state
|
|
60
|
+
* - Corrupted file: Logs warning, returns default empty state
|
|
61
|
+
* - Valid file: Returns validated FleetState
|
|
62
|
+
*
|
|
63
|
+
* @param stateFilePath - Path to state.yaml file
|
|
64
|
+
* @param options - Read options including logger
|
|
65
|
+
* @returns Validated FleetState object
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* const state = await readFleetState('.herdctl/state.yaml');
|
|
70
|
+
* console.log(state.fleet.started_at);
|
|
71
|
+
* console.log(state.agents);
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export async function readFleetState(
|
|
75
|
+
stateFilePath: string,
|
|
76
|
+
options: ReadFleetStateOptions = {}
|
|
77
|
+
): Promise<FleetState> {
|
|
78
|
+
const logger = options.logger ?? defaultLogger;
|
|
79
|
+
|
|
80
|
+
// Attempt to read the file
|
|
81
|
+
const readResult = await safeReadYaml<unknown>(stateFilePath);
|
|
82
|
+
|
|
83
|
+
// Handle file not found - return default state
|
|
84
|
+
if (!readResult.success) {
|
|
85
|
+
if (readResult.error.code === "ENOENT") {
|
|
86
|
+
return createInitialFleetState();
|
|
87
|
+
}
|
|
88
|
+
// For other read errors, log and return default
|
|
89
|
+
logger.warn(
|
|
90
|
+
`Failed to read state file '${stateFilePath}': ${readResult.error.message}. Using default state.`
|
|
91
|
+
);
|
|
92
|
+
return createInitialFleetState();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Handle empty file - return default state
|
|
96
|
+
if (readResult.data === null || readResult.data === undefined) {
|
|
97
|
+
return createInitialFleetState();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Validate against schema
|
|
101
|
+
try {
|
|
102
|
+
return FleetStateSchema.parse(readResult.data);
|
|
103
|
+
} catch (error) {
|
|
104
|
+
if (error instanceof ZodError) {
|
|
105
|
+
const issues = error.issues
|
|
106
|
+
.map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`)
|
|
107
|
+
.join(", ");
|
|
108
|
+
logger.warn(
|
|
109
|
+
`Corrupted state file '${stateFilePath}': ${issues}. Using default state.`
|
|
110
|
+
);
|
|
111
|
+
return createInitialFleetState();
|
|
112
|
+
}
|
|
113
|
+
// Unexpected error - log and return default
|
|
114
|
+
logger.warn(
|
|
115
|
+
`Unexpected error parsing state file '${stateFilePath}': ${(error as Error).message}. Using default state.`
|
|
116
|
+
);
|
|
117
|
+
return createInitialFleetState();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Write fleet state to state.yaml atomically
|
|
123
|
+
*
|
|
124
|
+
* Uses atomic write (write to temp file, then rename) to prevent corruption.
|
|
125
|
+
*
|
|
126
|
+
* @param stateFilePath - Path to state.yaml file
|
|
127
|
+
* @param state - FleetState object to write
|
|
128
|
+
* @param options - Write options
|
|
129
|
+
* @throws {StateFileError} If write fails
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* const state = await readFleetState('.herdctl/state.yaml');
|
|
134
|
+
* state.fleet.started_at = new Date().toISOString();
|
|
135
|
+
* await writeFleetState('.herdctl/state.yaml', state);
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
export async function writeFleetState(
|
|
139
|
+
stateFilePath: string,
|
|
140
|
+
state: FleetState,
|
|
141
|
+
options: WriteFleetStateOptions = {}
|
|
142
|
+
): Promise<void> {
|
|
143
|
+
// Validate before writing
|
|
144
|
+
const validatedState = FleetStateSchema.parse(state);
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
await atomicWriteYaml(stateFilePath, validatedState, {
|
|
148
|
+
indent: options.indent ?? 2,
|
|
149
|
+
});
|
|
150
|
+
} catch (error) {
|
|
151
|
+
throw new StateFileError(
|
|
152
|
+
`Failed to write state file '${stateFilePath}': ${(error as Error).message}`,
|
|
153
|
+
stateFilePath,
|
|
154
|
+
"write",
|
|
155
|
+
error as Error
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Partial updates for agent state
|
|
162
|
+
*/
|
|
163
|
+
export type AgentStateUpdates = Partial<AgentState>;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Update a single agent's state within the fleet state
|
|
167
|
+
*
|
|
168
|
+
* This is a convenience function that:
|
|
169
|
+
* 1. Reads current state
|
|
170
|
+
* 2. Applies partial updates to the specified agent
|
|
171
|
+
* 3. Writes the updated state back atomically
|
|
172
|
+
*
|
|
173
|
+
* If the agent doesn't exist, it will be created with the provided updates.
|
|
174
|
+
*
|
|
175
|
+
* @param stateFilePath - Path to state.yaml file
|
|
176
|
+
* @param agentName - Name of the agent to update
|
|
177
|
+
* @param updates - Partial AgentState updates to apply
|
|
178
|
+
* @param options - Options for read/write operations
|
|
179
|
+
* @returns The updated FleetState
|
|
180
|
+
* @throws {StateFileError} If write fails
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```typescript
|
|
184
|
+
* // Mark agent as running with a job
|
|
185
|
+
* await updateAgentState('.herdctl/state.yaml', 'my-agent', {
|
|
186
|
+
* status: 'running',
|
|
187
|
+
* current_job: 'job-123',
|
|
188
|
+
* });
|
|
189
|
+
*
|
|
190
|
+
* // Clear error state
|
|
191
|
+
* await updateAgentState('.herdctl/state.yaml', 'my-agent', {
|
|
192
|
+
* status: 'idle',
|
|
193
|
+
* error_message: null,
|
|
194
|
+
* });
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
197
|
+
export async function updateAgentState(
|
|
198
|
+
stateFilePath: string,
|
|
199
|
+
agentName: string,
|
|
200
|
+
updates: AgentStateUpdates,
|
|
201
|
+
options: ReadFleetStateOptions & WriteFleetStateOptions = {}
|
|
202
|
+
): Promise<FleetState> {
|
|
203
|
+
// Read current state
|
|
204
|
+
const currentState = await readFleetState(stateFilePath, options);
|
|
205
|
+
|
|
206
|
+
// Get current agent state or create new one
|
|
207
|
+
const currentAgentState = currentState.agents[agentName] ?? { status: "idle" };
|
|
208
|
+
|
|
209
|
+
// Merge updates
|
|
210
|
+
const updatedAgentState: AgentState = {
|
|
211
|
+
...currentAgentState,
|
|
212
|
+
...updates,
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// Update the state
|
|
216
|
+
const updatedState: FleetState = {
|
|
217
|
+
...currentState,
|
|
218
|
+
agents: {
|
|
219
|
+
...currentState.agents,
|
|
220
|
+
[agentName]: updatedAgentState,
|
|
221
|
+
},
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
// Write back
|
|
225
|
+
await writeFleetState(stateFilePath, updatedState, options);
|
|
226
|
+
|
|
227
|
+
return updatedState;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Initialize fleet state with started_at timestamp if not already set
|
|
232
|
+
*
|
|
233
|
+
* @param stateFilePath - Path to state.yaml file
|
|
234
|
+
* @param options - Options for read/write operations
|
|
235
|
+
* @returns The initialized FleetState
|
|
236
|
+
*/
|
|
237
|
+
export async function initializeFleetState(
|
|
238
|
+
stateFilePath: string,
|
|
239
|
+
options: ReadFleetStateOptions & WriteFleetStateOptions = {}
|
|
240
|
+
): Promise<FleetState> {
|
|
241
|
+
const currentState = await readFleetState(stateFilePath, options);
|
|
242
|
+
|
|
243
|
+
// Only set started_at if not already set
|
|
244
|
+
if (!currentState.fleet.started_at) {
|
|
245
|
+
const updatedState: FleetState = {
|
|
246
|
+
...currentState,
|
|
247
|
+
fleet: {
|
|
248
|
+
...currentState.fleet,
|
|
249
|
+
started_at: new Date().toISOString(),
|
|
250
|
+
},
|
|
251
|
+
};
|
|
252
|
+
await writeFleetState(stateFilePath, updatedState, options);
|
|
253
|
+
return updatedState;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return currentState;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Remove an agent from the fleet state
|
|
261
|
+
*
|
|
262
|
+
* @param stateFilePath - Path to state.yaml file
|
|
263
|
+
* @param agentName - Name of the agent to remove
|
|
264
|
+
* @param options - Options for read/write operations
|
|
265
|
+
* @returns The updated FleetState
|
|
266
|
+
*/
|
|
267
|
+
export async function removeAgentState(
|
|
268
|
+
stateFilePath: string,
|
|
269
|
+
agentName: string,
|
|
270
|
+
options: ReadFleetStateOptions & WriteFleetStateOptions = {}
|
|
271
|
+
): Promise<FleetState> {
|
|
272
|
+
const currentState = await readFleetState(stateFilePath, options);
|
|
273
|
+
|
|
274
|
+
// Create new agents map without the specified agent
|
|
275
|
+
const { [agentName]: _, ...remainingAgents } = currentState.agents;
|
|
276
|
+
|
|
277
|
+
const updatedState: FleetState = {
|
|
278
|
+
...currentState,
|
|
279
|
+
agents: remainingAgents,
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
await writeFleetState(stateFilePath, updatedState, options);
|
|
283
|
+
return updatedState;
|
|
284
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State management module
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for managing herdctl state files including:
|
|
5
|
+
* - State directory initialization and management
|
|
6
|
+
* - Atomic file writes to prevent corruption
|
|
7
|
+
* - YAML and JSONL file operations
|
|
8
|
+
* - Safe reads with validation
|
|
9
|
+
* - Fleet state (state.yaml) management
|
|
10
|
+
* - Job metadata (job-<id>.yaml) management
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// Re-export types
|
|
14
|
+
export * from "./types.js";
|
|
15
|
+
|
|
16
|
+
// Re-export errors
|
|
17
|
+
export * from "./errors.js";
|
|
18
|
+
|
|
19
|
+
// Re-export schemas
|
|
20
|
+
export * from "./schemas/index.js";
|
|
21
|
+
|
|
22
|
+
// Re-export directory functions
|
|
23
|
+
export {
|
|
24
|
+
initStateDirectory,
|
|
25
|
+
getStateDirectory,
|
|
26
|
+
validateStateDirectory,
|
|
27
|
+
} from "./directory.js";
|
|
28
|
+
|
|
29
|
+
// Re-export file utilities
|
|
30
|
+
export * from "./utils/index.js";
|
|
31
|
+
|
|
32
|
+
// Re-export fleet state functions
|
|
33
|
+
export {
|
|
34
|
+
readFleetState,
|
|
35
|
+
writeFleetState,
|
|
36
|
+
updateAgentState,
|
|
37
|
+
initializeFleetState,
|
|
38
|
+
removeAgentState,
|
|
39
|
+
type StateLogger,
|
|
40
|
+
type ReadFleetStateOptions,
|
|
41
|
+
type WriteFleetStateOptions,
|
|
42
|
+
type AgentStateUpdates,
|
|
43
|
+
} from "./fleet-state.js";
|
|
44
|
+
|
|
45
|
+
// Re-export job metadata functions
|
|
46
|
+
export {
|
|
47
|
+
createJob,
|
|
48
|
+
updateJob,
|
|
49
|
+
getJob,
|
|
50
|
+
listJobs,
|
|
51
|
+
deleteJob,
|
|
52
|
+
type JobMetadataOptions,
|
|
53
|
+
type JobLogger,
|
|
54
|
+
type JobMetadataUpdates,
|
|
55
|
+
type ListJobsFilter,
|
|
56
|
+
type ListJobsResult,
|
|
57
|
+
} from "./job-metadata.js";
|
|
58
|
+
|
|
59
|
+
// Re-export job output functions
|
|
60
|
+
export {
|
|
61
|
+
getJobOutputPath,
|
|
62
|
+
appendJobOutput,
|
|
63
|
+
appendJobOutputBatch,
|
|
64
|
+
readJobOutput,
|
|
65
|
+
readJobOutputAll,
|
|
66
|
+
type JobOutputLogger,
|
|
67
|
+
type JobOutputOptions,
|
|
68
|
+
type ReadJobOutputOptions,
|
|
69
|
+
} from "./job-output.js";
|
|
70
|
+
|
|
71
|
+
// Re-export session functions
|
|
72
|
+
export {
|
|
73
|
+
getSessionInfo,
|
|
74
|
+
updateSessionInfo,
|
|
75
|
+
clearSession,
|
|
76
|
+
type SessionOptions,
|
|
77
|
+
type SessionLogger,
|
|
78
|
+
type SessionInfoUpdates,
|
|
79
|
+
} from "./session.js";
|