@elie-laloum/outpost 2.0.0 → 4.0.0
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/CHANGELOG.md +42 -0
- package/README.md +3 -1
- package/SECURITY.md +3 -1
- package/dist/adapters/agents/claude-diagnostics.d.ts +1 -0
- package/dist/adapters/agents/claude-diagnostics.js +7 -0
- package/dist/adapters/agents/claude-diagnostics.js.map +1 -0
- package/dist/adapters/agents/cli-diagnostics.constants.d.ts +12 -0
- package/dist/adapters/agents/cli-diagnostics.constants.js +24 -0
- package/dist/adapters/agents/cli-diagnostics.constants.js.map +1 -0
- package/dist/adapters/agents/cli-diagnostics.d.ts +4 -0
- package/dist/adapters/agents/cli-diagnostics.js +14 -0
- package/dist/adapters/agents/cli-diagnostics.js.map +1 -0
- package/dist/adapters/agents/cli-diagnostics.types.d.ts +13 -0
- package/dist/adapters/agents/cli-diagnostics.types.js +2 -0
- package/dist/adapters/agents/cli-diagnostics.types.js.map +1 -0
- package/dist/adapters/agents/codex-diagnostics.d.ts +1 -0
- package/dist/adapters/agents/codex-diagnostics.js +7 -0
- package/dist/adapters/agents/codex-diagnostics.js.map +1 -0
- package/dist/adapters/agents/gemini-adapter.d.ts +3 -0
- package/dist/adapters/agents/gemini-adapter.js +15 -0
- package/dist/adapters/agents/gemini-adapter.js.map +1 -0
- package/dist/adapters/agents/gemini-diagnostics.d.ts +2 -0
- package/dist/adapters/agents/gemini-diagnostics.js +15 -0
- package/dist/adapters/agents/gemini-diagnostics.js.map +1 -0
- package/dist/adapters/agents/gemini-events.d.ts +2 -0
- package/dist/adapters/agents/gemini-events.js +50 -0
- package/dist/adapters/agents/gemini-events.js.map +1 -0
- package/dist/adapters/agents/gemini-request.d.ts +4 -0
- package/dist/adapters/agents/gemini-request.js +21 -0
- package/dist/adapters/agents/gemini-request.js.map +1 -0
- package/dist/adapters/agents/gemini.types.d.ts +6 -0
- package/dist/adapters/agents/gemini.types.js +2 -0
- package/dist/adapters/agents/gemini.types.js.map +1 -0
- package/dist/adapters/agents/protocol-fixtures.constants.d.ts +2 -0
- package/dist/adapters/agents/protocol-fixtures.constants.js +105 -0
- package/dist/adapters/agents/protocol-fixtures.constants.js.map +1 -0
- package/dist/adapters/agents/protocol-fixtures.types.d.ts +6 -0
- package/dist/adapters/agents/protocol-fixtures.types.js +2 -0
- package/dist/adapters/agents/protocol-fixtures.types.js.map +1 -0
- package/dist/application/agent-bootstrap.constants.d.ts +1 -0
- package/dist/application/agent-bootstrap.constants.js +1 -0
- package/dist/application/agent-bootstrap.constants.js.map +1 -1
- package/dist/application/agent-bootstrap.js +6 -2
- package/dist/application/agent-bootstrap.js.map +1 -1
- package/dist/application/agent-output.js +9 -2
- package/dist/application/agent-output.js.map +1 -1
- package/dist/application/artifact-tasks.d.ts +5 -0
- package/dist/application/artifact-tasks.js +31 -0
- package/dist/application/artifact-tasks.js.map +1 -0
- package/dist/application/artifact-tasks.types.d.ts +8 -0
- package/dist/application/artifact-tasks.types.js +2 -0
- package/dist/application/artifact-tasks.types.js.map +1 -0
- package/dist/application/diagnostic-probe.d.ts +3 -0
- package/dist/application/diagnostic-probe.js +55 -0
- package/dist/application/diagnostic-probe.js.map +1 -0
- package/dist/application/dispatch-validation.js +2 -0
- package/dist/application/dispatch-validation.js.map +1 -1
- package/dist/application/doctor-agent.constants.d.ts +11 -0
- package/dist/application/doctor-agent.constants.js +10 -0
- package/dist/application/doctor-agent.constants.js.map +1 -0
- package/dist/application/doctor-agent.d.ts +3 -0
- package/dist/application/doctor-agent.js +53 -0
- package/dist/application/doctor-agent.js.map +1 -0
- package/dist/application/doctor-image.d.ts +3 -0
- package/dist/application/doctor-image.js +133 -0
- package/dist/application/doctor-image.js.map +1 -0
- package/dist/application/doctor-protocol.d.ts +3 -0
- package/dist/application/doctor-protocol.js +30 -0
- package/dist/application/doctor-protocol.js.map +1 -0
- package/dist/application/doctor-protocol.types.d.ts +10 -0
- package/dist/application/doctor-protocol.types.js +2 -0
- package/dist/application/doctor-protocol.types.js.map +1 -0
- package/dist/application/doctor-sandbox.constants.d.ts +5 -0
- package/dist/application/doctor-sandbox.constants.js +6 -0
- package/dist/application/doctor-sandbox.constants.js.map +1 -0
- package/dist/application/doctor-sandbox.d.ts +4 -0
- package/dist/application/doctor-sandbox.js +133 -0
- package/dist/application/doctor-sandbox.js.map +1 -0
- package/dist/application/doctor-sandbox.types.d.ts +23 -0
- package/dist/application/doctor-sandbox.types.js +2 -0
- package/dist/application/doctor-sandbox.types.js.map +1 -0
- package/dist/application/doctor-transfers.constants.d.ts +6 -0
- package/dist/application/doctor-transfers.constants.js +7 -0
- package/dist/application/doctor-transfers.constants.js.map +1 -0
- package/dist/application/doctor-transfers.d.ts +4 -0
- package/dist/application/doctor-transfers.js +88 -0
- package/dist/application/doctor-transfers.js.map +1 -0
- package/dist/application/doctor.constants.d.ts +9 -0
- package/dist/application/doctor.constants.js +15 -0
- package/dist/application/doctor.constants.js.map +1 -0
- package/dist/application/doctor.d.ts +3 -0
- package/dist/application/doctor.js +106 -0
- package/dist/application/doctor.js.map +1 -0
- package/dist/application/doctor.types.d.ts +39 -0
- package/dist/application/doctor.types.js +2 -0
- package/dist/application/doctor.types.js.map +1 -0
- package/dist/application/execution.js +1 -0
- package/dist/application/execution.js.map +1 -1
- package/dist/application/outpost.types.d.ts +4 -0
- package/dist/application/outpost.types.js.map +1 -1
- package/dist/application/queue-worker.d.ts +2 -0
- package/dist/application/queue-worker.js +75 -0
- package/dist/application/queue-worker.js.map +1 -0
- package/dist/application/queue-worker.types.d.ts +15 -0
- package/dist/application/queue-worker.types.js +2 -0
- package/dist/application/queue-worker.types.js.map +1 -0
- package/dist/application/queued-task.d.ts +3 -0
- package/dist/application/queued-task.js +56 -0
- package/dist/application/queued-task.js.map +1 -0
- package/dist/application/queued-task.types.d.ts +11 -0
- package/dist/application/queued-task.types.js +2 -0
- package/dist/application/queued-task.types.js.map +1 -0
- package/dist/application/recovery-checksum-capture.d.ts +2 -0
- package/dist/application/recovery-checksum-capture.js +32 -0
- package/dist/application/recovery-checksum-capture.js.map +1 -0
- package/dist/application/recovery-checksum-paths.d.ts +2 -0
- package/dist/application/recovery-checksum-paths.js +11 -0
- package/dist/application/recovery-checksum-paths.js.map +1 -0
- package/dist/application/recovery-checksums.constants.d.ts +5 -0
- package/dist/application/recovery-checksums.constants.js +6 -0
- package/dist/application/recovery-checksums.constants.js.map +1 -0
- package/dist/application/recovery-checksums.d.ts +3 -0
- package/dist/application/recovery-checksums.js +94 -0
- package/dist/application/recovery-checksums.js.map +1 -0
- package/dist/application/recovery-checksums.types.d.ts +17 -0
- package/dist/application/recovery-checksums.types.js +2 -0
- package/dist/application/recovery-checksums.types.js.map +1 -0
- package/dist/application/recovery-inspection.d.ts +2 -0
- package/dist/application/recovery-inspection.js +32 -0
- package/dist/application/recovery-inspection.js.map +1 -0
- package/dist/application/recovery-inspection.types.d.ts +18 -0
- package/dist/application/recovery-inspection.types.js +2 -0
- package/dist/application/recovery-inspection.types.js.map +1 -0
- package/dist/application/recovery-restorability.d.ts +2 -0
- package/dist/application/recovery-restorability.js +137 -0
- package/dist/application/recovery-restorability.js.map +1 -0
- package/dist/application/recovery-restore-snapshot.d.ts +2 -0
- package/dist/application/recovery-restore-snapshot.js +57 -0
- package/dist/application/recovery-restore-snapshot.js.map +1 -0
- package/dist/application/recovery-restore.d.ts +3 -0
- package/dist/application/recovery-restore.js +161 -0
- package/dist/application/recovery-restore.js.map +1 -0
- package/dist/application/recovery-restore.types.d.ts +28 -0
- package/dist/application/recovery-restore.types.js +2 -0
- package/dist/application/recovery-restore.types.js.map +1 -0
- package/dist/application/recovery-retention-policy.d.ts +2 -0
- package/dist/application/recovery-retention-policy.js +21 -0
- package/dist/application/recovery-retention-policy.js.map +1 -0
- package/dist/application/recovery-retention.constants.d.ts +3 -0
- package/dist/application/recovery-retention.constants.js +2 -0
- package/dist/application/recovery-retention.constants.js.map +1 -0
- package/dist/application/recovery-retention.d.ts +4 -0
- package/dist/application/recovery-retention.js +207 -0
- package/dist/application/recovery-retention.js.map +1 -0
- package/dist/application/recovery-retention.types.d.ts +52 -0
- package/dist/application/recovery-retention.types.js +2 -0
- package/dist/application/recovery-retention.types.js.map +1 -0
- package/dist/application/recovery-verification.constants.d.ts +5 -0
- package/dist/application/recovery-verification.constants.js +10 -0
- package/dist/application/recovery-verification.constants.js.map +1 -0
- package/dist/application/recovery-verification.d.ts +3 -0
- package/dist/application/recovery-verification.js +107 -0
- package/dist/application/recovery-verification.js.map +1 -0
- package/dist/application/recovery-verification.types.d.ts +26 -0
- package/dist/application/recovery-verification.types.js +2 -0
- package/dist/application/recovery-verification.types.js.map +1 -0
- package/dist/application/remote-apply.js +30 -6
- package/dist/application/remote-apply.js.map +1 -1
- package/dist/application/remote-backup.js +6 -2
- package/dist/application/remote-backup.js.map +1 -1
- package/dist/application/remote-download.js +38 -6
- package/dist/application/remote-download.js.map +1 -1
- package/dist/application/remote-history.d.ts +6 -0
- package/dist/application/remote-history.js +114 -0
- package/dist/application/remote-history.js.map +1 -0
- package/dist/application/remote-upload.d.ts +2 -0
- package/dist/application/remote-upload.js +17 -0
- package/dist/application/remote-upload.js.map +1 -0
- package/dist/application/remote-validation.js +39 -28
- package/dist/application/remote-validation.js.map +1 -1
- package/dist/application/remote-workspace.constants.d.ts +3 -0
- package/dist/application/remote-workspace.constants.js +2 -0
- package/dist/application/remote-workspace.constants.js.map +1 -0
- package/dist/application/remote-workspace.js +10 -10
- package/dist/application/remote-workspace.js.map +1 -1
- package/dist/application/remote-workspace.types.d.ts +3 -1
- package/dist/application/remote-workspace.types.js.map +1 -1
- package/dist/application/sandbox-activity.d.ts +3 -0
- package/dist/application/sandbox-activity.js +25 -0
- package/dist/application/sandbox-activity.js.map +1 -0
- package/dist/application/sandbox-provision.js +55 -10
- package/dist/application/sandbox-provision.js.map +1 -1
- package/dist/application/sandbox-session.types.d.ts +2 -0
- package/dist/application/sandbox-session.types.js.map +1 -1
- package/dist/application/sandbox.js +33 -10
- package/dist/application/sandbox.js.map +1 -1
- package/dist/application/speculation-host.d.ts +2 -0
- package/dist/application/speculation-host.js +30 -0
- package/dist/application/speculation-host.js.map +1 -0
- package/dist/application/speculation.constants.d.ts +4 -0
- package/dist/application/speculation.constants.js +2 -0
- package/dist/application/speculation.constants.js.map +1 -0
- package/dist/application/speculation.d.ts +2 -0
- package/dist/application/speculation.js +166 -0
- package/dist/application/speculation.js.map +1 -0
- package/dist/application/speculation.types.d.ts +56 -0
- package/dist/application/speculation.types.js +2 -0
- package/dist/application/speculation.types.js.map +1 -0
- package/dist/application/storage-reservation.d.ts +3 -0
- package/dist/application/storage-reservation.js +10 -0
- package/dist/application/storage-reservation.js.map +1 -0
- package/dist/application/storage-reservation.types.d.ts +4 -0
- package/dist/application/storage-reservation.types.js +2 -0
- package/dist/application/storage-reservation.types.js.map +1 -0
- package/dist/application/task-usage.d.ts +4 -0
- package/dist/application/task-usage.js +41 -0
- package/dist/application/task-usage.js.map +1 -0
- package/dist/application/task-usage.types.d.ts +5 -0
- package/dist/application/task-usage.types.js +2 -0
- package/dist/application/task-usage.types.js.map +1 -0
- package/dist/application/tasks.js +23 -2
- package/dist/application/tasks.js.map +1 -1
- package/dist/application/tasks.types.d.ts +4 -3
- package/dist/application/tasks.types.js.map +1 -1
- package/dist/application/workspace-allocation.d.ts +3 -0
- package/dist/application/workspace-allocation.js +34 -0
- package/dist/application/workspace-allocation.js.map +1 -0
- package/dist/application/workspace.js +2 -2
- package/dist/application/workspace.js.map +1 -1
- package/dist/cli/commands.js +4 -0
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli/doctor-command.d.ts +3 -0
- package/dist/cli/doctor-command.js +38 -0
- package/dist/cli/doctor-command.js.map +1 -0
- package/dist/cli/main.constants.d.ts +38 -2
- package/dist/cli/main.constants.js +21 -2
- package/dist/cli/main.constants.js.map +1 -1
- package/dist/cli/recovery-command.d.ts +2 -0
- package/dist/cli/recovery-command.js +93 -0
- package/dist/cli/recovery-command.js.map +1 -0
- package/dist/cli/recovery-prune-command.d.ts +2 -0
- package/dist/cli/recovery-prune-command.js +34 -0
- package/dist/cli/recovery-prune-command.js.map +1 -0
- package/dist/cli/recovery-restore-command.d.ts +2 -0
- package/dist/cli/recovery-restore-command.js +34 -0
- package/dist/cli/recovery-restore-command.js.map +1 -0
- package/dist/cli/recovery-verify-command.d.ts +2 -0
- package/dist/cli/recovery-verify-command.js +43 -0
- package/dist/cli/recovery-verify-command.js.map +1 -0
- package/dist/cli/scaffold-files.js +2 -2
- package/dist/cli/scaffold-files.js.map +1 -1
- package/dist/cli/scaffold-validation.js +1 -1
- package/dist/cli/scaffold-validation.js.map +1 -1
- package/dist/cli/scaffold.constants.d.ts +5 -0
- package/dist/cli/scaffold.constants.js +7 -2
- package/dist/cli/scaffold.constants.js.map +1 -1
- package/dist/cli/scaffold.types.d.ts +1 -1
- package/dist/cli/scaffold.types.js.map +1 -1
- package/dist/domain/agent.types.d.ts +2 -0
- package/dist/domain/agent.types.js.map +1 -1
- package/dist/domain/artifact-reference.d.ts +4 -0
- package/dist/domain/artifact-reference.js +90 -0
- package/dist/domain/artifact-reference.js.map +1 -0
- package/dist/domain/artifact.constants.d.ts +2 -0
- package/dist/domain/artifact.constants.js +3 -0
- package/dist/domain/artifact.constants.js.map +1 -0
- package/dist/domain/artifact.d.ts +7 -0
- package/dist/domain/artifact.js +104 -0
- package/dist/domain/artifact.js.map +1 -0
- package/dist/domain/artifact.types.d.ts +44 -0
- package/dist/domain/artifact.types.js +2 -0
- package/dist/domain/artifact.types.js.map +1 -0
- package/dist/domain/egress.constants.d.ts +1 -0
- package/dist/domain/egress.constants.js +7 -0
- package/dist/domain/egress.constants.js.map +1 -0
- package/dist/domain/egress.d.ts +2 -0
- package/dist/domain/egress.js +48 -0
- package/dist/domain/egress.js.map +1 -0
- package/dist/domain/egress.types.d.ts +8 -0
- package/dist/domain/egress.types.js +2 -0
- package/dist/domain/egress.types.js.map +1 -0
- package/dist/domain/ports.d.ts +1 -1
- package/dist/domain/ports.js.map +1 -1
- package/dist/domain/sandbox.types.d.ts +13 -0
- package/dist/domain/sandbox.types.js.map +1 -1
- package/dist/domain/task-queue.constants.d.ts +8 -0
- package/dist/domain/task-queue.constants.js +9 -0
- package/dist/domain/task-queue.constants.js.map +1 -0
- package/dist/domain/task-queue.d.ts +11 -0
- package/dist/domain/task-queue.js +105 -0
- package/dist/domain/task-queue.js.map +1 -0
- package/dist/domain/task-queue.types.d.ts +41 -0
- package/dist/domain/task-queue.types.js +2 -0
- package/dist/domain/task-queue.types.js.map +1 -0
- package/dist/domain/workflow/budget.constants.d.ts +1 -0
- package/dist/domain/workflow/budget.constants.js +7 -0
- package/dist/domain/workflow/budget.constants.js.map +1 -0
- package/dist/domain/workflow/budget.d.ts +9 -0
- package/dist/domain/workflow/budget.js +69 -0
- package/dist/domain/workflow/budget.js.map +1 -0
- package/dist/domain/workflow/budget.types.d.ts +15 -0
- package/dist/domain/workflow/budget.types.js +2 -0
- package/dist/domain/workflow/budget.types.js.map +1 -0
- package/dist/domain/workflow/checkpoint-validation.d.ts +3 -0
- package/dist/domain/workflow/checkpoint-validation.js +81 -0
- package/dist/domain/workflow/checkpoint-validation.js.map +1 -0
- package/dist/domain/workflow/checkpoint-value.d.ts +2 -0
- package/dist/domain/workflow/checkpoint-value.js +49 -0
- package/dist/domain/workflow/checkpoint-value.js.map +1 -0
- package/dist/domain/workflow/checkpoint.d.ts +3 -0
- package/dist/domain/workflow/checkpoint.js +70 -0
- package/dist/domain/workflow/checkpoint.js.map +1 -0
- package/dist/domain/workflow/checkpoint.types.d.ts +40 -0
- package/dist/domain/workflow/checkpoint.types.js +2 -0
- package/dist/domain/workflow/checkpoint.types.js.map +1 -0
- package/dist/domain/workflow/gate-validation.d.ts +4 -0
- package/dist/domain/workflow/gate-validation.js +71 -0
- package/dist/domain/workflow/gate-validation.js.map +1 -0
- package/dist/domain/workflow/gates.constants.d.ts +4 -0
- package/dist/domain/workflow/gates.constants.js +5 -0
- package/dist/domain/workflow/gates.constants.js.map +1 -0
- package/dist/domain/workflow/gates.d.ts +7 -0
- package/dist/domain/workflow/gates.js +85 -0
- package/dist/domain/workflow/gates.js.map +1 -0
- package/dist/domain/workflow/gates.types.d.ts +27 -0
- package/dist/domain/workflow/gates.types.js +2 -0
- package/dist/domain/workflow/gates.types.js.map +1 -0
- package/dist/domain/workflow/task-runner.js +22 -3
- package/dist/domain/workflow/task-runner.js.map +1 -1
- package/dist/domain/workflow/usage-receipt.constants.d.ts +2 -0
- package/dist/domain/workflow/usage-receipt.constants.js +3 -0
- package/dist/domain/workflow/usage-receipt.constants.js.map +1 -0
- package/dist/domain/workflow/usage-receipt.d.ts +2 -0
- package/dist/domain/workflow/usage-receipt.js +18 -0
- package/dist/domain/workflow/usage-receipt.js.map +1 -0
- package/dist/domain/workflow/validation.js +6 -0
- package/dist/domain/workflow/validation.js.map +1 -1
- package/dist/domain/workflow/workflow-scheduler.js +68 -33
- package/dist/domain/workflow/workflow-scheduler.js.map +1 -1
- package/dist/domain/workflow/workflow-state.d.ts +2 -1
- package/dist/domain/workflow/workflow-state.js +107 -3
- package/dist/domain/workflow/workflow-state.js.map +1 -1
- package/dist/domain/workflow.d.ts +2 -0
- package/dist/domain/workflow.js +1 -0
- package/dist/domain/workflow.js.map +1 -1
- package/dist/domain/workflow.types.d.ts +23 -3
- package/dist/domain/workflow.types.js.map +1 -1
- package/dist/index.d.ts +44 -5
- package/dist/index.js +19 -2
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/artifact-store.constants.d.ts +1 -0
- package/dist/infrastructure/artifact-store.constants.js +2 -0
- package/dist/infrastructure/artifact-store.constants.js.map +1 -0
- package/dist/infrastructure/artifact-store.d.ts +3 -0
- package/dist/infrastructure/artifact-store.js +100 -0
- package/dist/infrastructure/artifact-store.js.map +1 -0
- package/dist/infrastructure/artifact-store.types.d.ts +4 -0
- package/dist/infrastructure/artifact-store.types.js +2 -0
- package/dist/infrastructure/artifact-store.types.js.map +1 -0
- package/dist/infrastructure/file-manifest.d.ts +6 -0
- package/dist/infrastructure/file-manifest.js +92 -0
- package/dist/infrastructure/file-manifest.js.map +1 -0
- package/dist/infrastructure/git/lock-inspection.constants.d.ts +4 -0
- package/dist/infrastructure/git/lock-inspection.constants.js +5 -0
- package/dist/infrastructure/git/lock-inspection.constants.js.map +1 -0
- package/dist/infrastructure/git/lock-inspection.d.ts +3 -0
- package/dist/infrastructure/git/lock-inspection.js +64 -0
- package/dist/infrastructure/git/lock-inspection.js.map +1 -0
- package/dist/infrastructure/git/lock-inspection.types.d.ts +27 -0
- package/dist/infrastructure/git/lock-inspection.types.js +2 -0
- package/dist/infrastructure/git/lock-inspection.types.js.map +1 -0
- package/dist/infrastructure/git/lock.d.ts +1 -0
- package/dist/infrastructure/git/lock.js +70 -29
- package/dist/infrastructure/git/lock.js.map +1 -1
- package/dist/infrastructure/git/process-identity.d.ts +3 -0
- package/dist/infrastructure/git/process-identity.js +73 -0
- package/dist/infrastructure/git/process-identity.js.map +1 -0
- package/dist/infrastructure/git/process-identity.types.d.ts +10 -0
- package/dist/infrastructure/git/process-identity.types.js +2 -0
- package/dist/infrastructure/git/process-identity.types.js.map +1 -0
- package/dist/infrastructure/git/verification-command.d.ts +1 -0
- package/dist/infrastructure/git/verification-command.js +37 -0
- package/dist/infrastructure/git/verification-command.js.map +1 -0
- package/dist/infrastructure/git/workspace-lease.js +1 -0
- package/dist/infrastructure/git/workspace-lease.js.map +1 -1
- package/dist/infrastructure/git/workspace.js +5 -1
- package/dist/infrastructure/git/workspace.js.map +1 -1
- package/dist/infrastructure/git/worktree-inspection.constants.d.ts +5 -0
- package/dist/infrastructure/git/worktree-inspection.constants.js +16 -0
- package/dist/infrastructure/git/worktree-inspection.constants.js.map +1 -0
- package/dist/infrastructure/git/worktree-inspection.d.ts +3 -0
- package/dist/infrastructure/git/worktree-inspection.js +120 -0
- package/dist/infrastructure/git/worktree-inspection.js.map +1 -0
- package/dist/infrastructure/git/worktree-inspection.types.d.ts +19 -0
- package/dist/infrastructure/git/worktree-inspection.types.js +2 -0
- package/dist/infrastructure/git/worktree-inspection.types.js.map +1 -0
- package/dist/infrastructure/inspection-file.constants.d.ts +1 -0
- package/dist/infrastructure/inspection-file.constants.js +5 -0
- package/dist/infrastructure/inspection-file.constants.js.map +1 -0
- package/dist/infrastructure/inspection-file.d.ts +1 -0
- package/dist/infrastructure/inspection-file.js +43 -0
- package/dist/infrastructure/inspection-file.js.map +1 -0
- package/dist/infrastructure/inspection-hash.constants.d.ts +1 -0
- package/dist/infrastructure/inspection-hash.constants.js +2 -0
- package/dist/infrastructure/inspection-hash.constants.js.map +1 -0
- package/dist/infrastructure/inspection-hash.d.ts +2 -0
- package/dist/infrastructure/inspection-hash.js +62 -0
- package/dist/infrastructure/inspection-hash.js.map +1 -0
- package/dist/infrastructure/inspection-hash.types.d.ts +5 -0
- package/dist/infrastructure/inspection-hash.types.js +2 -0
- package/dist/infrastructure/inspection-hash.types.js.map +1 -0
- package/dist/infrastructure/journal-retention.constants.d.ts +4 -0
- package/dist/infrastructure/journal-retention.constants.js +5 -0
- package/dist/infrastructure/journal-retention.constants.js.map +1 -0
- package/dist/infrastructure/journal-retention.d.ts +2 -0
- package/dist/infrastructure/journal-retention.js +51 -0
- package/dist/infrastructure/journal-retention.js.map +1 -0
- package/dist/infrastructure/journal.js +37 -13
- package/dist/infrastructure/journal.js.map +1 -1
- package/dist/infrastructure/opentelemetry.constants.d.ts +10 -0
- package/dist/infrastructure/opentelemetry.constants.js +11 -0
- package/dist/infrastructure/opentelemetry.constants.js.map +1 -0
- package/dist/infrastructure/opentelemetry.d.ts +3 -0
- package/dist/infrastructure/opentelemetry.js +131 -0
- package/dist/infrastructure/opentelemetry.js.map +1 -0
- package/dist/infrastructure/opentelemetry.types.d.ts +21 -0
- package/dist/infrastructure/opentelemetry.types.js +2 -0
- package/dist/infrastructure/opentelemetry.types.js.map +1 -0
- package/dist/infrastructure/resource-activity-inspection.d.ts +2 -0
- package/dist/infrastructure/resource-activity-inspection.js +152 -0
- package/dist/infrastructure/resource-activity-inspection.js.map +1 -0
- package/dist/infrastructure/resource-activity.constants.d.ts +8 -0
- package/dist/infrastructure/resource-activity.constants.js +26 -0
- package/dist/infrastructure/resource-activity.constants.js.map +1 -0
- package/dist/infrastructure/resource-activity.d.ts +2 -0
- package/dist/infrastructure/resource-activity.js +166 -0
- package/dist/infrastructure/resource-activity.js.map +1 -0
- package/dist/infrastructure/resource-activity.types.d.ts +53 -0
- package/dist/infrastructure/resource-activity.types.js +2 -0
- package/dist/infrastructure/resource-activity.types.js.map +1 -0
- package/dist/infrastructure/storage-inventory.constants.d.ts +6 -0
- package/dist/infrastructure/storage-inventory.constants.js +11 -0
- package/dist/infrastructure/storage-inventory.constants.js.map +1 -0
- package/dist/infrastructure/storage-inventory.d.ts +2 -0
- package/dist/infrastructure/storage-inventory.js +123 -0
- package/dist/infrastructure/storage-inventory.js.map +1 -0
- package/dist/infrastructure/storage-inventory.types.d.ts +38 -0
- package/dist/infrastructure/storage-inventory.types.js +2 -0
- package/dist/infrastructure/storage-inventory.types.js.map +1 -0
- package/dist/infrastructure/storage-mutation-lock.constants.d.ts +5 -0
- package/dist/infrastructure/storage-mutation-lock.constants.js +6 -0
- package/dist/infrastructure/storage-mutation-lock.constants.js.map +1 -0
- package/dist/infrastructure/storage-mutation-lock.d.ts +1 -0
- package/dist/infrastructure/storage-mutation-lock.js +21 -0
- package/dist/infrastructure/storage-mutation-lock.js.map +1 -0
- package/dist/infrastructure/storage-reservations.constants.d.ts +4 -0
- package/dist/infrastructure/storage-reservations.constants.js +5 -0
- package/dist/infrastructure/storage-reservations.constants.js.map +1 -0
- package/dist/infrastructure/storage-reservations.d.ts +2 -0
- package/dist/infrastructure/storage-reservations.js +150 -0
- package/dist/infrastructure/storage-reservations.js.map +1 -0
- package/dist/infrastructure/storage-reservations.types.d.ts +21 -0
- package/dist/infrastructure/storage-reservations.types.js +2 -0
- package/dist/infrastructure/storage-reservations.types.js.map +1 -0
- package/dist/infrastructure/task-queue-http.constants.d.ts +2 -0
- package/dist/infrastructure/task-queue-http.constants.js +3 -0
- package/dist/infrastructure/task-queue-http.constants.js.map +1 -0
- package/dist/infrastructure/task-queue-http.d.ts +4 -0
- package/dist/infrastructure/task-queue-http.js +158 -0
- package/dist/infrastructure/task-queue-http.js.map +1 -0
- package/dist/infrastructure/task-queue-http.types.d.ts +16 -0
- package/dist/infrastructure/task-queue-http.types.js +2 -0
- package/dist/infrastructure/task-queue-http.types.js.map +1 -0
- package/dist/infrastructure/task-queue.d.ts +2 -0
- package/dist/infrastructure/task-queue.js +134 -0
- package/dist/infrastructure/task-queue.js.map +1 -0
- package/dist/infrastructure/transfer.js +17 -0
- package/dist/infrastructure/transfer.js.map +1 -1
- package/dist/infrastructure/workflow-checkpoint.constants.d.ts +1 -0
- package/dist/infrastructure/workflow-checkpoint.constants.js +2 -0
- package/dist/infrastructure/workflow-checkpoint.constants.js.map +1 -0
- package/dist/infrastructure/workflow-checkpoint.d.ts +3 -0
- package/dist/infrastructure/workflow-checkpoint.js +77 -0
- package/dist/infrastructure/workflow-checkpoint.js.map +1 -0
- package/dist/infrastructure/workflow-checkpoint.types.d.ts +4 -0
- package/dist/infrastructure/workflow-checkpoint.types.js +2 -0
- package/dist/infrastructure/workflow-checkpoint.types.js.map +1 -0
- package/dist/providers/agents.d.ts +2 -0
- package/dist/providers/agents.js +1 -0
- package/dist/providers/agents.js.map +1 -1
- package/dist/providers/cloud.constants.d.ts +1 -0
- package/dist/providers/cloud.constants.js +1 -0
- package/dist/providers/cloud.constants.js.map +1 -1
- package/dist/providers/container-cache.constants.d.ts +11 -0
- package/dist/providers/container-cache.constants.js +9 -0
- package/dist/providers/container-cache.constants.js.map +1 -0
- package/dist/providers/container-cache.d.ts +4 -0
- package/dist/providers/container-cache.js +48 -0
- package/dist/providers/container-cache.js.map +1 -0
- package/dist/providers/container-cache.types.d.ts +8 -0
- package/dist/providers/container-cache.types.js +2 -0
- package/dist/providers/container-cache.types.js.map +1 -0
- package/dist/providers/container-isolation.d.ts +2 -0
- package/dist/providers/container-isolation.js +29 -0
- package/dist/providers/container-isolation.js.map +1 -0
- package/dist/providers/container-mounts.js +7 -2
- package/dist/providers/container-mounts.js.map +1 -1
- package/dist/providers/container-network.d.ts +2 -0
- package/dist/providers/container-network.js +14 -0
- package/dist/providers/container-network.js.map +1 -0
- package/dist/providers/container-plan.js +6 -2
- package/dist/providers/container-plan.js.map +1 -1
- package/dist/providers/container.constants.d.ts +1 -0
- package/dist/providers/container.constants.js +1 -0
- package/dist/providers/container.constants.js.map +1 -1
- package/dist/providers/container.js +50 -3
- package/dist/providers/container.js.map +1 -1
- package/dist/providers/container.types.d.ts +5 -0
- package/dist/providers/container.types.js.map +1 -1
- package/dist/providers/daytona-command.js +10 -6
- package/dist/providers/daytona-command.js.map +1 -1
- package/dist/providers/daytona-terminal.d.ts +3 -0
- package/dist/providers/daytona-terminal.js +128 -0
- package/dist/providers/daytona-terminal.js.map +1 -0
- package/dist/providers/daytona.js +15 -4
- package/dist/providers/daytona.js.map +1 -1
- package/dist/providers/diagnostic-container.d.ts +4 -0
- package/dist/providers/diagnostic-container.js +15 -0
- package/dist/providers/diagnostic-container.js.map +1 -0
- package/dist/providers/docker.d.ts +2 -0
- package/dist/providers/docker.js.map +1 -1
- package/dist/providers/file-batches.constants.d.ts +10 -0
- package/dist/providers/file-batches.constants.js +57 -0
- package/dist/providers/file-batches.constants.js.map +1 -0
- package/dist/providers/file-batches.d.ts +2 -0
- package/dist/providers/file-batches.js +160 -0
- package/dist/providers/file-batches.js.map +1 -0
- package/dist/providers/file-upload.constants.d.ts +1 -0
- package/dist/providers/file-upload.constants.js +68 -0
- package/dist/providers/file-upload.constants.js.map +1 -0
- package/dist/providers/file-upload.d.ts +2 -0
- package/dist/providers/file-upload.js +146 -0
- package/dist/providers/file-upload.js.map +1 -0
- package/dist/providers/firecracker-command.d.ts +5 -0
- package/dist/providers/firecracker-command.js +114 -0
- package/dist/providers/firecracker-command.js.map +1 -0
- package/dist/providers/firecracker-files.constants.d.ts +1 -0
- package/dist/providers/firecracker-files.constants.js +21 -0
- package/dist/providers/firecracker-files.constants.js.map +1 -0
- package/dist/providers/firecracker-files.d.ts +3 -0
- package/dist/providers/firecracker-files.js +110 -0
- package/dist/providers/firecracker-files.js.map +1 -0
- package/dist/providers/firecracker-machine.d.ts +3 -0
- package/dist/providers/firecracker-machine.js +155 -0
- package/dist/providers/firecracker-machine.js.map +1 -0
- package/dist/providers/firecracker.constants.d.ts +10 -0
- package/dist/providers/firecracker.constants.js +11 -0
- package/dist/providers/firecracker.constants.js.map +1 -0
- package/dist/providers/firecracker.d.ts +4 -0
- package/dist/providers/firecracker.js +103 -0
- package/dist/providers/firecracker.js.map +1 -0
- package/dist/providers/firecracker.types.d.ts +36 -0
- package/dist/providers/firecracker.types.js +2 -0
- package/dist/providers/firecracker.types.js.map +1 -0
- package/dist/providers/local.js +2 -1
- package/dist/providers/local.js.map +1 -1
- package/dist/providers/podman.d.ts +2 -0
- package/dist/providers/podman.js.map +1 -1
- package/dist/providers/terminal-bridge.d.ts +14 -0
- package/dist/providers/terminal-bridge.js +100 -0
- package/dist/providers/terminal-bridge.js.map +1 -0
- package/dist/providers/vercel-directory.d.ts +2 -0
- package/dist/providers/vercel-directory.js +7 -0
- package/dist/providers/vercel-directory.js.map +1 -0
- package/dist/providers/vercel-files.js +3 -2
- package/dist/providers/vercel-files.js.map +1 -1
- package/dist/providers/vercel-network.d.ts +2 -0
- package/dist/providers/vercel-network.js +18 -0
- package/dist/providers/vercel-network.js.map +1 -0
- package/dist/providers/vercel.d.ts +1 -0
- package/dist/providers/vercel.js +8 -2
- package/dist/providers/vercel.js.map +1 -1
- package/dist/providers/vercel.types.d.ts +2 -0
- package/dist/providers/vercel.types.js.map +1 -1
- package/dist/providers/versions.constants.d.ts +1 -0
- package/dist/providers/versions.constants.js +1 -0
- package/dist/providers/versions.constants.js.map +1 -1
- package/package.json +16 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outpost.types.js","sourceRoot":"","sources":["../../src/application/outpost.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AgentAdapter } from \"../domain/agent.types.ts\";\nimport type { Command, CommandResult } from \"../domain/command.types.ts\";\nimport type { Brief } from \"../domain/prompts.types.ts\";\nimport type { SandboxProvider } from \"../domain/sandbox.types.ts\";\nimport type {\n BranchPolicy,\n Commit,\n Disposal,\n LifecycleHooks,\n StageLimits,\n WorkspaceRecord,\n} from \"../domain/workspace.types.ts\";\nimport type { Logging } from \"../infrastructure/journal.types.ts\";\nimport type { DispatchOptions, Execution } from \"./execution.types.ts\";\nimport type { VariableQuestion } from \"./interactive-brief.types.ts\";\n\nexport interface WorkspaceOptions {\n readonly signal?: AbortSignal;\n readonly repository?: string;\n readonly branch?: BranchPolicy;\n readonly copies?: readonly string[];\n readonly limits?: StageLimits;\n readonly label?: string;\n readonly hooks?: LifecycleHooks;\n}\n\nexport interface Workspace extends WorkspaceRecord {\n dispatch<T = undefined>(\n options: Omit<\n SandboxOptions,\n Exclude<keyof WorkspaceOptions, \"hooks\" | \"label\"> | \"workspace\"\n > &\n DispatchOptions<T> & { readonly agent: AgentAdapter },\n ): Promise<DispatchResult<T>>;\n sandbox(\n options?: Omit<\n SandboxOptions,\n Exclude<keyof WorkspaceOptions, \"hooks\" | \"label\"> | \"workspace\"\n >,\n ): Promise<Sandbox>;\n attach(\n options: Omit<\n SandboxOptions,\n Exclude<keyof WorkspaceOptions, \"hooks\" | \"label\"> | \"workspace\"\n > &\n AttachOptions & { readonly agent: AgentAdapter },\n ): Promise<AttachResult>;\n close(options?: { readonly preserve?: boolean }): Promise<Disposal>;\n integrate(): Promise<void>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n\nexport interface SandboxOptions extends WorkspaceOptions {\n readonly includeUncommitted?: boolean;\n readonly agent?: AgentAdapter;\n readonly provider?: SandboxProvider;\n readonly workspace?: Workspace;\n readonly hooks?: LifecycleHooks;\n readonly signal?: AbortSignal;\n readonly logging?: Logging;\n readonly bootstrap?: boolean;\n readonly conversationHome?: string;\n}\n\nexport interface AttachOptions {\n readonly ask?: VariableQuestion;\n readonly agent?: AgentAdapter;\n readonly brief?: Brief;\n readonly continuation?: { readonly id: string; readonly fork?: boolean };\n readonly signal?: AbortSignal;\n readonly terminal?: Command[\"terminal\"];\n}\n\nexport interface AttachResult extends CommandResult, Disposal {\n readonly commits: readonly Commit[];\n readonly branch: string;\n readonly directory: string;\n}\n\nexport interface DispatchResult<T> extends Execution<T> {\n readonly branch: string;\n readonly directory: string;\n readonly commits: readonly Commit[];\n readonly transcript?: string;\n readonly log?: string;\n readonly retainedDirectory?: string;\n resume<U = undefined>(\n options: ContinuationOptions<U>,\n ): Promise<DispatchResult<U>>;\n fork<U = undefined>(\n options: ContinuationOptions<U>,\n ): Promise<DispatchResult<U>>;\n}\n\nexport type ContinuationOptions<T = undefined> = DispatchOptions<T> &\n Omit<SandboxOptions, \"agent\">;\n\nexport interface WarmDispatchResult<T> extends Omit<\n DispatchResult<T>,\n \"resume\" | \"fork\"\n> {\n resume<U = undefined>(\n options: DispatchOptions<U>,\n ): Promise<WarmDispatchResult<U>>;\n fork<U = undefined>(\n options: DispatchOptions<U>,\n ): Promise<WarmDispatchResult<U>>;\n}\n\nexport interface Sandbox {\n readonly workspace: Workspace;\n readonly root: string;\n dispatch<T = undefined>(\n options: DispatchOptions<T>,\n ): Promise<WarmDispatchResult<T>>;\n resume<T = undefined>(\n id: string,\n options: DispatchOptions<T>,\n ): Promise<WarmDispatchResult<T>>;\n fork<T = undefined>(\n id: string,\n options: DispatchOptions<T>,\n ): Promise<WarmDispatchResult<T>>;\n attach(options?: AttachOptions): Promise<AttachResult>;\n command(command: Command): Promise<CommandResult>;\n close(options?: { readonly preserve?: boolean }): Promise<Disposal>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"outpost.types.js","sourceRoot":"","sources":["../../src/application/outpost.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AgentAdapter } from \"../domain/agent.types.ts\";\nimport type { Command, CommandResult } from \"../domain/command.types.ts\";\nimport type { Brief } from \"../domain/prompts.types.ts\";\nimport type { SandboxProvider } from \"../domain/sandbox.types.ts\";\nimport type {\n BranchPolicy,\n Commit,\n Disposal,\n LifecycleHooks,\n StageLimits,\n WorkspaceRecord,\n} from \"../domain/workspace.types.ts\";\nimport type { StorageReservationOptions } from \"../infrastructure/storage-reservations.types.ts\";\nimport type { Logging } from \"../infrastructure/journal.types.ts\";\nimport type {\n SandboxDiagnosticOptions,\n SandboxDiagnosticReport,\n} from \"./doctor-sandbox.types.ts\";\nimport type { DispatchOptions, Execution } from \"./execution.types.ts\";\nimport type { VariableQuestion } from \"./interactive-brief.types.ts\";\n\nexport interface WorkspaceOptions {\n readonly storageQuota?: Omit<StorageReservationOptions, \"signal\">;\n readonly signal?: AbortSignal;\n readonly repository?: string;\n readonly branch?: BranchPolicy;\n readonly copies?: readonly string[];\n readonly limits?: StageLimits;\n readonly label?: string;\n readonly hooks?: LifecycleHooks;\n}\n\nexport interface Workspace extends WorkspaceRecord {\n dispatch<T = undefined>(\n options: Omit<\n SandboxOptions,\n Exclude<keyof WorkspaceOptions, \"hooks\" | \"label\"> | \"workspace\"\n > &\n DispatchOptions<T> & { readonly agent: AgentAdapter },\n ): Promise<DispatchResult<T>>;\n sandbox(\n options?: Omit<\n SandboxOptions,\n Exclude<keyof WorkspaceOptions, \"hooks\" | \"label\"> | \"workspace\"\n >,\n ): Promise<Sandbox>;\n attach(\n options: Omit<\n SandboxOptions,\n Exclude<keyof WorkspaceOptions, \"hooks\" | \"label\"> | \"workspace\"\n > &\n AttachOptions & { readonly agent: AgentAdapter },\n ): Promise<AttachResult>;\n close(options?: { readonly preserve?: boolean }): Promise<Disposal>;\n integrate(): Promise<void>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n\nexport interface SandboxOptions extends WorkspaceOptions {\n readonly includeUncommitted?: boolean;\n readonly agent?: AgentAdapter;\n readonly provider?: SandboxProvider;\n readonly workspace?: Workspace;\n readonly hooks?: LifecycleHooks;\n readonly signal?: AbortSignal;\n readonly logging?: Logging;\n readonly bootstrap?: boolean;\n readonly conversationHome?: string;\n}\n\nexport interface AttachOptions {\n readonly ask?: VariableQuestion;\n readonly agent?: AgentAdapter;\n readonly brief?: Brief;\n readonly continuation?: { readonly id: string; readonly fork?: boolean };\n readonly signal?: AbortSignal;\n readonly terminal?: Command[\"terminal\"];\n}\n\nexport interface AttachResult extends CommandResult, Disposal {\n readonly commits: readonly Commit[];\n readonly branch: string;\n readonly directory: string;\n}\n\nexport interface DispatchResult<T> extends Execution<T> {\n readonly branch: string;\n readonly directory: string;\n readonly commits: readonly Commit[];\n readonly transcript?: string;\n readonly log?: string;\n readonly retainedDirectory?: string;\n resume<U = undefined>(\n options: ContinuationOptions<U>,\n ): Promise<DispatchResult<U>>;\n fork<U = undefined>(\n options: ContinuationOptions<U>,\n ): Promise<DispatchResult<U>>;\n}\n\nexport type ContinuationOptions<T = undefined> = DispatchOptions<T> &\n Omit<SandboxOptions, \"agent\">;\n\nexport interface WarmDispatchResult<T> extends Omit<\n DispatchResult<T>,\n \"resume\" | \"fork\"\n> {\n resume<U = undefined>(\n options: DispatchOptions<U>,\n ): Promise<WarmDispatchResult<U>>;\n fork<U = undefined>(\n options: DispatchOptions<U>,\n ): Promise<WarmDispatchResult<U>>;\n}\n\nexport interface Sandbox {\n diagnose(\n options?: SandboxDiagnosticOptions,\n ): Promise<SandboxDiagnosticReport>;\n readonly workspace: Workspace;\n readonly root: string;\n dispatch<T = undefined>(\n options: DispatchOptions<T>,\n ): Promise<WarmDispatchResult<T>>;\n resume<T = undefined>(\n id: string,\n options: DispatchOptions<T>,\n ): Promise<WarmDispatchResult<T>>;\n fork<T = undefined>(\n id: string,\n options: DispatchOptions<T>,\n ): Promise<WarmDispatchResult<T>>;\n attach(options?: AttachOptions): Promise<AttachResult>;\n command(command: Command): Promise<CommandResult>;\n close(options?: { readonly preserve?: boolean }): Promise<Disposal>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n"]}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
2
|
+
import { queueMaxStringLength, queueDefaultLeaseMs, queueDefaultPollMs, } from "../domain/task-queue.constants.js";
|
|
3
|
+
import { queueLeaseMs, queueNumber, queueString, queueResult, } from "../domain/task-queue.js";
|
|
4
|
+
export async function runQueueWorker(options) {
|
|
5
|
+
const leaseMs = queueLeaseMs(options.leaseMs ?? queueDefaultLeaseMs);
|
|
6
|
+
const pollMs = queueNumber(options.pollMs ?? queueDefaultPollMs);
|
|
7
|
+
if (!pollMs)
|
|
8
|
+
throw new Error("Worker poll interval must be positive");
|
|
9
|
+
const handlers = new Map(Object.entries(options.handlers));
|
|
10
|
+
if (!handlers.size ||
|
|
11
|
+
[...handlers.values()].some((handler) => typeof handler !== "function"))
|
|
12
|
+
throw new Error("Worker requires trusted handlers");
|
|
13
|
+
const worker = queueString(options.worker);
|
|
14
|
+
async function execute(job) {
|
|
15
|
+
if (options.signal.aborted)
|
|
16
|
+
return;
|
|
17
|
+
const stop = new AbortController();
|
|
18
|
+
const signal = AbortSignal.any([options.signal, stop.signal]);
|
|
19
|
+
const lease = { id: job.id, worker, fence: job.fence };
|
|
20
|
+
const heartbeat = (async () => {
|
|
21
|
+
try {
|
|
22
|
+
while (!signal.aborted) {
|
|
23
|
+
await delay(Math.max(10, Math.floor(leaseMs / 3)), undefined, {
|
|
24
|
+
signal,
|
|
25
|
+
});
|
|
26
|
+
await options.queue.renew(lease, leaseMs);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
if (!signal.aborted)
|
|
31
|
+
stop.abort(error);
|
|
32
|
+
}
|
|
33
|
+
})();
|
|
34
|
+
try {
|
|
35
|
+
const handler = handlers.get(job.handler);
|
|
36
|
+
if (!handler)
|
|
37
|
+
throw new Error("Worker handler unavailable");
|
|
38
|
+
let result;
|
|
39
|
+
try {
|
|
40
|
+
result = queueResult(await handler(job.input, { signal, job }));
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
result = {
|
|
44
|
+
value: null,
|
|
45
|
+
error: (error instanceof Error ? error.message : String(error)).slice(0, queueMaxStringLength) || "Queue handler failed",
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (!signal.aborted)
|
|
49
|
+
await options.queue.complete(lease, result);
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
stop.abort();
|
|
53
|
+
await heartbeat;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
while (!options.signal.aborted) {
|
|
58
|
+
const job = await options.queue.claim({
|
|
59
|
+
worker,
|
|
60
|
+
handlers: [...handlers.keys()],
|
|
61
|
+
leaseMs,
|
|
62
|
+
});
|
|
63
|
+
if (job) {
|
|
64
|
+
await execute(job);
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
await delay(pollMs, undefined, { signal: options.signal });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
if (!options.signal.aborted)
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=queue-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue-worker.js","sourceRoot":"","sources":["../../src/application/queue-worker.ts"],"names":[],"mappings":"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","sourcesContent":["import { setTimeout as delay } from \"node:timers/promises\";\nimport {\n queueMaxStringLength,\n queueDefaultLeaseMs,\n queueDefaultPollMs,\n} from \"../domain/task-queue.constants.ts\";\nimport {\n queueLeaseMs,\n queueNumber,\n queueString,\n queueResult,\n} from \"../domain/task-queue.ts\";\nimport type { QueueWorkerOptions } from \"./queue-worker.types.ts\";\nimport type { QueueJob, QueueResult } from \"../domain/task-queue.types.ts\";\n\nexport async function runQueueWorker(\n options: QueueWorkerOptions,\n): Promise<void> {\n const leaseMs = queueLeaseMs(options.leaseMs ?? queueDefaultLeaseMs);\n const pollMs = queueNumber(options.pollMs ?? queueDefaultPollMs);\n if (!pollMs) throw new Error(\"Worker poll interval must be positive\");\n const handlers = new Map(Object.entries(options.handlers));\n if (\n !handlers.size ||\n [...handlers.values()].some((handler) => typeof handler !== \"function\")\n )\n throw new Error(\"Worker requires trusted handlers\");\n const worker = queueString(options.worker);\n async function execute(job: QueueJob) {\n if (options.signal.aborted) return;\n const stop = new AbortController();\n const signal = AbortSignal.any([options.signal, stop.signal]);\n const lease = { id: job.id, worker, fence: job.fence };\n const heartbeat = (async () => {\n try {\n while (!signal.aborted) {\n await delay(Math.max(10, Math.floor(leaseMs / 3)), undefined, {\n signal,\n });\n await options.queue.renew(lease, leaseMs);\n }\n } catch (error) {\n if (!signal.aborted) stop.abort(error);\n }\n })();\n try {\n const handler = handlers.get(job.handler);\n if (!handler) throw new Error(\"Worker handler unavailable\");\n let result: QueueResult;\n try {\n result = queueResult(await handler(job.input, { signal, job }));\n } catch (error) {\n result = {\n value: null,\n error:\n (error instanceof Error ? error.message : String(error)).slice(\n 0,\n queueMaxStringLength,\n ) || \"Queue handler failed\",\n };\n }\n if (!signal.aborted) await options.queue.complete(lease, result);\n } finally {\n stop.abort();\n await heartbeat;\n }\n }\n try {\n while (!options.signal.aborted) {\n const job = await options.queue.claim({\n worker,\n handlers: [...handlers.keys()],\n leaseMs,\n });\n if (job) {\n await execute(job);\n continue;\n }\n await delay(pollMs, undefined, { signal: options.signal });\n }\n } catch (error) {\n if (!options.signal.aborted) throw error;\n }\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { QueueJob, QueueResult, TaskQueue } from "../domain/task-queue.types.ts";
|
|
2
|
+
import type { WorkflowJson } from "../domain/workflow/checkpoint.types.ts";
|
|
3
|
+
export interface QueueHandlerContext {
|
|
4
|
+
readonly signal: AbortSignal;
|
|
5
|
+
readonly job: QueueJob;
|
|
6
|
+
}
|
|
7
|
+
export type QueueHandler = (input: WorkflowJson, context: QueueHandlerContext) => Promise<QueueResult> | QueueResult;
|
|
8
|
+
export interface QueueWorkerOptions {
|
|
9
|
+
readonly queue: TaskQueue;
|
|
10
|
+
readonly worker: string;
|
|
11
|
+
readonly handlers: Readonly<Record<string, QueueHandler>>;
|
|
12
|
+
readonly signal: AbortSignal;
|
|
13
|
+
readonly leaseMs?: number;
|
|
14
|
+
readonly pollMs?: number;
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue-worker.types.js","sourceRoot":"","sources":["../../src/application/queue-worker.types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n QueueJob,\n QueueResult,\n TaskQueue,\n} from \"../domain/task-queue.types.ts\";\nimport type { WorkflowJson } from \"../domain/workflow/checkpoint.types.ts\";\nexport interface QueueHandlerContext {\n readonly signal: AbortSignal;\n readonly job: QueueJob;\n}\nexport type QueueHandler = (\n input: WorkflowJson,\n context: QueueHandlerContext,\n) => Promise<QueueResult> | QueueResult;\nexport interface QueueWorkerOptions {\n readonly queue: TaskQueue;\n readonly worker: string;\n readonly handlers: Readonly<Record<string, QueueHandler>>;\n readonly signal: AbortSignal;\n readonly leaseMs?: number;\n readonly pollMs?: number;\n}\n"]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
3
|
+
import { task } from "../domain/workflow.js";
|
|
4
|
+
import { queueDefaultPollMs } from "../domain/task-queue.constants.js";
|
|
5
|
+
import { queueNumber, queueString } from "../domain/task-queue.js";
|
|
6
|
+
export function queuedTask(options) {
|
|
7
|
+
const { queue, handler, input, decode, deadline, pollMs = queueDefaultPollMs, ...definition } = options;
|
|
8
|
+
queueString(handler);
|
|
9
|
+
if (!queueNumber(pollMs))
|
|
10
|
+
throw new Error("Queue poll interval must be positive");
|
|
11
|
+
if (deadline !== undefined)
|
|
12
|
+
queueNumber(deadline);
|
|
13
|
+
return task({
|
|
14
|
+
...definition,
|
|
15
|
+
async perform(context) {
|
|
16
|
+
context.signal.throwIfAborted();
|
|
17
|
+
const id = createHash("sha256")
|
|
18
|
+
.update(JSON.stringify([context.executionId, definition.key]))
|
|
19
|
+
.digest("hex");
|
|
20
|
+
let job = await queue.enqueue({
|
|
21
|
+
id,
|
|
22
|
+
handler,
|
|
23
|
+
input: input(context),
|
|
24
|
+
...(deadline === undefined ? {} : { deadline }),
|
|
25
|
+
});
|
|
26
|
+
try {
|
|
27
|
+
while (job.status === "pending" || job.status === "active") {
|
|
28
|
+
await delay(pollMs, undefined, { signal: context.signal });
|
|
29
|
+
const latest = await queue.get(id);
|
|
30
|
+
if (!latest)
|
|
31
|
+
throw new Error("Queued workflow job disappeared");
|
|
32
|
+
job = latest;
|
|
33
|
+
}
|
|
34
|
+
if (job.result?.usage) {
|
|
35
|
+
if (context.reportUsageOnce)
|
|
36
|
+
context.reportUsageOnce(`queue:${id}`, job.result.usage);
|
|
37
|
+
else
|
|
38
|
+
context.reportUsage(job.result.usage);
|
|
39
|
+
}
|
|
40
|
+
if (job.status !== "done" || !job.result)
|
|
41
|
+
throw new Error(job.result?.error ?? "Queued workflow job cancelled");
|
|
42
|
+
context.signal.throwIfAborted();
|
|
43
|
+
return decode(job.result.value);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
if (context.signal.aborted) {
|
|
47
|
+
const latest = await queue.get(id);
|
|
48
|
+
if (latest)
|
|
49
|
+
await queue.cancel(id, latest.fence);
|
|
50
|
+
}
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=queued-task.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queued-task.js","sourceRoot":"","sources":["../../src/application/queued-task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAInE,MAAM,UAAU,UAAU,CAAI,OAA6B;IACzD,MAAM,EACJ,KAAK,EACL,OAAO,EACP,KAAK,EACL,MAAM,EACN,QAAQ,EACR,MAAM,GAAG,kBAAkB,EAC3B,GAAG,UAAU,EACd,GAAG,OAAO,CAAC;IACZ,WAAW,CAAC,OAAO,CAAC,CAAC;IACrB,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,IAAI,QAAQ,KAAK,SAAS;QAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IAClD,OAAO,IAAI,CAAC;QACV,GAAG,UAAU;QACb,KAAK,CAAC,OAAO,CAAC,OAAO;YACnB,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;YAChC,MAAM,EAAE,GAAG,UAAU,CAAC,QAAQ,CAAC;iBAC5B,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;iBAC7D,MAAM,CAAC,KAAK,CAAC,CAAC;YACjB,IAAI,GAAG,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC;gBAC5B,EAAE;gBACF,OAAO;gBACP,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;gBACrB,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;aAChD,CAAC,CAAC;YACH,IAAI,CAAC;gBACH,OAAO,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;oBAC3D,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;oBAC3D,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;oBACnC,IAAI,CAAC,MAAM;wBAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;oBAChE,GAAG,GAAG,MAAM,CAAC;gBACf,CAAC;gBACD,IAAI,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;oBACtB,IAAI,OAAO,CAAC,eAAe;wBACzB,OAAO,CAAC,eAAe,CAAC,SAAS,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;;wBACtD,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC7C,CAAC;gBACD,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM;oBACtC,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,IAAI,+BAA+B,CAAC,CAAC;gBACxE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;gBAChC,OAAO,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAClC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;oBAC3B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;oBACnC,IAAI,MAAM;wBAAE,MAAM,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;gBACnD,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { task } from \"../domain/workflow.ts\";\nimport { queueDefaultPollMs } from \"../domain/task-queue.constants.ts\";\nimport { queueNumber, queueString } from \"../domain/task-queue.ts\";\nimport type { Task } from \"../domain/workflow.types.ts\";\nimport type { QueuedTaskOptions } from \"./queued-task.types.ts\";\n\nexport function queuedTask<T>(options: QueuedTaskOptions<T>): Task<T> {\n const {\n queue,\n handler,\n input,\n decode,\n deadline,\n pollMs = queueDefaultPollMs,\n ...definition\n } = options;\n queueString(handler);\n if (!queueNumber(pollMs))\n throw new Error(\"Queue poll interval must be positive\");\n if (deadline !== undefined) queueNumber(deadline);\n return task({\n ...definition,\n async perform(context) {\n context.signal.throwIfAborted();\n const id = createHash(\"sha256\")\n .update(JSON.stringify([context.executionId, definition.key]))\n .digest(\"hex\");\n let job = await queue.enqueue({\n id,\n handler,\n input: input(context),\n ...(deadline === undefined ? {} : { deadline }),\n });\n try {\n while (job.status === \"pending\" || job.status === \"active\") {\n await delay(pollMs, undefined, { signal: context.signal });\n const latest = await queue.get(id);\n if (!latest) throw new Error(\"Queued workflow job disappeared\");\n job = latest;\n }\n if (job.result?.usage) {\n if (context.reportUsageOnce)\n context.reportUsageOnce(`queue:${id}`, job.result.usage);\n else context.reportUsage(job.result.usage);\n }\n if (job.status !== \"done\" || !job.result)\n throw new Error(job.result?.error ?? \"Queued workflow job cancelled\");\n context.signal.throwIfAborted();\n return decode(job.result.value);\n } catch (error) {\n if (context.signal.aborted) {\n const latest = await queue.get(id);\n if (latest) await queue.cancel(id, latest.fence);\n }\n throw error;\n }\n },\n });\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TaskContext, TaskOptions } from "../domain/workflow.types.ts";
|
|
2
|
+
import type { WorkflowJson } from "../domain/workflow/checkpoint.types.ts";
|
|
3
|
+
import type { TaskQueue } from "../domain/task-queue.types.ts";
|
|
4
|
+
export type QueuedTaskOptions<T> = Omit<TaskOptions<T>, "perform"> & {
|
|
5
|
+
readonly queue: TaskQueue;
|
|
6
|
+
readonly handler: string;
|
|
7
|
+
readonly input: (context: TaskContext) => WorkflowJson;
|
|
8
|
+
readonly decode: (value: WorkflowJson) => T;
|
|
9
|
+
readonly deadline?: number;
|
|
10
|
+
readonly pollMs?: number;
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queued-task.types.js","sourceRoot":"","sources":["../../src/application/queued-task.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { TaskContext, TaskOptions } from \"../domain/workflow.types.ts\";\nimport type { WorkflowJson } from \"../domain/workflow/checkpoint.types.ts\";\nimport type { TaskQueue } from \"../domain/task-queue.types.ts\";\nexport type QueuedTaskOptions<T> = Omit<TaskOptions<T>, \"perform\"> & {\n readonly queue: TaskQueue;\n readonly handler: string;\n readonly input: (context: TaskContext) => WorkflowJson;\n readonly decode: (value: WorkflowJson) => T;\n readonly deadline?: number;\n readonly pollMs?: number;\n};\n"]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { rename, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { safeDestination } from "../infrastructure/files.js";
|
|
5
|
+
import { hashInspectionEntry } from "../infrastructure/inspection-hash.js";
|
|
6
|
+
import { recoveryChecksumDefaults } from "./recovery-checksums.constants.js";
|
|
7
|
+
import { recoveryChecksumPaths } from "./recovery-checksum-paths.js";
|
|
8
|
+
export async function captureRecoveryChecksums(root, state) {
|
|
9
|
+
const entries = [];
|
|
10
|
+
for (const path of recoveryChecksumPaths(state))
|
|
11
|
+
entries.push({
|
|
12
|
+
path,
|
|
13
|
+
...(await hashInspectionEntry(await safeDestination(root, path))),
|
|
14
|
+
});
|
|
15
|
+
const manifest = {
|
|
16
|
+
version: 1,
|
|
17
|
+
algorithm: "sha256",
|
|
18
|
+
entries,
|
|
19
|
+
};
|
|
20
|
+
const temporary = join(root, `.checksums-${randomUUID()}.tmp`);
|
|
21
|
+
try {
|
|
22
|
+
await writeFile(temporary, JSON.stringify(manifest), {
|
|
23
|
+
flag: "wx",
|
|
24
|
+
mode: 0o600,
|
|
25
|
+
});
|
|
26
|
+
await rename(temporary, join(root, recoveryChecksumDefaults.filename));
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
await rm(temporary, { force: true });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=recovery-checksum-capture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery-checksum-capture.js","sourceRoot":"","sources":["../../src/application/recovery-checksum-capture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AAK7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAGrE,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,IAAY,EACZ,KAA4B;IAE5B,MAAM,OAAO,GAA4B,EAAE,CAAC;IAC5C,KAAK,MAAM,IAAI,IAAI,qBAAqB,CAAC,KAAK,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC;YACX,IAAI;YACJ,GAAG,CAAC,MAAM,mBAAmB,CAAC,MAAM,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;SAClE,CAAC,CAAC;IACL,MAAM,QAAQ,GAA6B;QACzC,OAAO,EAAE,CAAC;QACV,SAAS,EAAE,QAAQ;QACnB,OAAO;KACR,CAAC;IACF,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,UAAU,EAAE,MAAM,CAAC,CAAC;IAC/D,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE;YACnD,IAAI,EAAE,IAAI;YACV,IAAI,EAAE,KAAK;SACZ,CAAC,CAAC;QACH,MAAM,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,wBAAwB,CAAC,QAAQ,CAAC,CAAC,CAAC;IACzE,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,CAAC;AACH,CAAC","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { rename, rm, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { safeDestination } from \"../infrastructure/files.ts\";\nimport { hashInspectionEntry } from \"../infrastructure/inspection-hash.ts\";\nimport { recoveryChecksumDefaults } from \"./recovery-checksums.constants.ts\";\nimport type {\n RecoveryChecksumEntry,\n RecoveryChecksumManifest,\n} from \"./recovery-checksums.types.ts\";\nimport { recoveryChecksumPaths } from \"./recovery-checksum-paths.ts\";\nimport type { RecoveryTransferState } from \"./recovery-verification.types.ts\";\n\nexport async function captureRecoveryChecksums(\n root: string,\n state: RecoveryTransferState,\n): Promise<void> {\n const entries: RecoveryChecksumEntry[] = [];\n for (const path of recoveryChecksumPaths(state))\n entries.push({\n path,\n ...(await hashInspectionEntry(await safeDestination(root, path))),\n });\n const manifest: RecoveryChecksumManifest = {\n version: 1,\n algorithm: \"sha256\",\n entries,\n };\n const temporary = join(root, `.checksums-${randomUUID()}.tmp`);\n try {\n await writeFile(temporary, JSON.stringify(manifest), {\n flag: \"wx\",\n mode: 0o600,\n });\n await rename(temporary, join(root, recoveryChecksumDefaults.filename));\n } finally {\n await rm(temporary, { force: true });\n }\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { recoveryTransferPatches } from "./recovery-verification.constants.js";
|
|
2
|
+
export function recoveryChecksumPaths(state) {
|
|
3
|
+
return [
|
|
4
|
+
"state.json",
|
|
5
|
+
...recoveryTransferPatches,
|
|
6
|
+
...(state.previous !== state.next ? ["commits.bundle"] : []),
|
|
7
|
+
...state.previousExtras.map((path) => `previous-files/${path}`),
|
|
8
|
+
...state.incoming.map((path) => `incoming/${path}`),
|
|
9
|
+
];
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=recovery-checksum-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery-checksum-paths.js","sourceRoot":"","sources":["../../src/application/recovery-checksum-paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAG/E,MAAM,UAAU,qBAAqB,CAAC,KAA4B;IAChE,OAAO;QACL,YAAY;QACZ,GAAG,uBAAuB;QAC1B,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5D,GAAG,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,kBAAkB,IAAI,EAAE,CAAC;QAC/D,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,IAAI,EAAE,CAAC;KACpD,CAAC;AACJ,CAAC","sourcesContent":["import { recoveryTransferPatches } from \"./recovery-verification.constants.ts\";\nimport type { RecoveryTransferState } from \"./recovery-verification.types.ts\";\n\nexport function recoveryChecksumPaths(state: RecoveryTransferState): string[] {\n return [\n \"state.json\",\n ...recoveryTransferPatches,\n ...(state.previous !== state.next ? [\"commits.bundle\"] : []),\n ...state.previousExtras.map((path) => `previous-files/${path}`),\n ...state.incoming.map((path) => `incoming/${path}`),\n ];\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery-checksums.constants.js","sourceRoot":"","sources":["../../src/application/recovery-checksums.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,QAAQ,EAAE,gBAAgB;IAC1B,gBAAgB,EAAE,SAAS;IAC3B,QAAQ,EAAE,aAAa;CACf,CAAC","sourcesContent":["export const recoveryChecksumDefaults = {\n filename: \"checksums.json\",\n maxManifestBytes: 1_048_576,\n maxBytes: 1_073_741_824,\n} as const;\n"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { RecoveryChecksumResult } from "./recovery-checksums.types.ts";
|
|
2
|
+
import type { RecoveryTransferState } from "./recovery-verification.types.ts";
|
|
3
|
+
export declare function verifyRecoveryChecksums(root: string, state: RecoveryTransferState, maxBytes?: number): Promise<RecoveryChecksumResult>;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { OutpostError, positive } from "../domain/errors.js";
|
|
3
|
+
import { safeDestination } from "../infrastructure/files.js";
|
|
4
|
+
import { hashInspectionEntry } from "../infrastructure/inspection-hash.js";
|
|
5
|
+
import { readInspectionFile } from "../infrastructure/inspection-file.js";
|
|
6
|
+
import { recoveryChecksumPaths } from "./recovery-checksum-paths.js";
|
|
7
|
+
import { recoveryChecksumDefaults } from "./recovery-checksums.constants.js";
|
|
8
|
+
function validManifest(value, expected) {
|
|
9
|
+
if (!value ||
|
|
10
|
+
typeof value !== "object" ||
|
|
11
|
+
!("version" in value) ||
|
|
12
|
+
value.version !== 1 ||
|
|
13
|
+
!("algorithm" in value) ||
|
|
14
|
+
value.algorithm !== "sha256" ||
|
|
15
|
+
!("entries" in value) ||
|
|
16
|
+
!Array.isArray(value.entries) ||
|
|
17
|
+
value.entries.length !== expected.length)
|
|
18
|
+
return false;
|
|
19
|
+
const remaining = new Set(expected);
|
|
20
|
+
if (remaining.size !== expected.length)
|
|
21
|
+
return false;
|
|
22
|
+
const entries = value.entries;
|
|
23
|
+
for (const entry of entries) {
|
|
24
|
+
if (!entry ||
|
|
25
|
+
typeof entry !== "object" ||
|
|
26
|
+
!("path" in entry) ||
|
|
27
|
+
typeof entry.path !== "string" ||
|
|
28
|
+
!remaining.delete(entry.path) ||
|
|
29
|
+
!("kind" in entry) ||
|
|
30
|
+
(entry.kind !== "file" && entry.kind !== "symlink") ||
|
|
31
|
+
!("bytes" in entry) ||
|
|
32
|
+
typeof entry.bytes !== "number" ||
|
|
33
|
+
!Number.isSafeInteger(entry.bytes) ||
|
|
34
|
+
entry.bytes < 0 ||
|
|
35
|
+
!("sha256" in entry) ||
|
|
36
|
+
typeof entry.sha256 !== "string" ||
|
|
37
|
+
!/^[a-f0-9]{64}$/.test(entry.sha256))
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
return remaining.size === 0;
|
|
41
|
+
}
|
|
42
|
+
export async function verifyRecoveryChecksums(root, state, maxBytes = recoveryChecksumDefaults.maxBytes) {
|
|
43
|
+
positive(maxBytes, "maxBytes");
|
|
44
|
+
const checks = [];
|
|
45
|
+
let bytesChecked = 0;
|
|
46
|
+
const manifestPath = join(root, recoveryChecksumDefaults.filename);
|
|
47
|
+
const unavailable = (code) => ({
|
|
48
|
+
integrity: "unverified",
|
|
49
|
+
bytesChecked,
|
|
50
|
+
maxBytes,
|
|
51
|
+
checks: [{ path: manifestPath, status: "fail", code }],
|
|
52
|
+
});
|
|
53
|
+
let manifest;
|
|
54
|
+
try {
|
|
55
|
+
manifest = JSON.parse((await readInspectionFile(manifestPath, recoveryChecksumDefaults.maxManifestBytes)).toString("utf8"));
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return unavailable("CHECKSUMS_UNAVAILABLE");
|
|
59
|
+
}
|
|
60
|
+
if (!validManifest(manifest, recoveryChecksumPaths(state)))
|
|
61
|
+
return unavailable("INVALID_CHECKSUM_MANIFEST");
|
|
62
|
+
for (const entry of manifest.entries) {
|
|
63
|
+
const path = join(root, entry.path);
|
|
64
|
+
try {
|
|
65
|
+
const actual = await hashInspectionEntry(await safeDestination(root, entry.path), maxBytes - bytesChecked);
|
|
66
|
+
bytesChecked += actual.bytes;
|
|
67
|
+
const matches = actual.kind === entry.kind &&
|
|
68
|
+
actual.bytes === entry.bytes &&
|
|
69
|
+
actual.sha256 === entry.sha256;
|
|
70
|
+
checks.push({
|
|
71
|
+
path,
|
|
72
|
+
status: matches ? "pass" : "fail",
|
|
73
|
+
code: matches ? "CHECKSUM_MATCH" : "CHECKSUM_MISMATCH",
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
const code = error instanceof OutpostError &&
|
|
78
|
+
error.details.reason === "CHECKSUM_LIMIT"
|
|
79
|
+
? "CHECKSUM_LIMIT"
|
|
80
|
+
: "CHECKSUM_UNAVAILABLE";
|
|
81
|
+
checks.push({ path, status: "fail", code });
|
|
82
|
+
return { integrity: "unverified", bytesChecked, maxBytes, checks };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
integrity: checks.every((check) => check.status === "pass")
|
|
87
|
+
? "checksums-match"
|
|
88
|
+
: "checksums-mismatch",
|
|
89
|
+
bytesChecked,
|
|
90
|
+
maxBytes,
|
|
91
|
+
checks,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=recovery-checksums.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery-checksums.js","sourceRoot":"","sources":["../../src/application/recovery-checksums.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport { OutpostError, positive } from \"../domain/errors.ts\";\nimport { safeDestination } from \"../infrastructure/files.ts\";\nimport { hashInspectionEntry } from \"../infrastructure/inspection-hash.ts\";\nimport { readInspectionFile } from \"../infrastructure/inspection-file.ts\";\nimport { recoveryChecksumPaths } from \"./recovery-checksum-paths.ts\";\nimport { recoveryChecksumDefaults } from \"./recovery-checksums.constants.ts\";\nimport type {\n RecoveryChecksumManifest,\n RecoveryChecksumResult,\n} from \"./recovery-checksums.types.ts\";\nimport type {\n RecoveryStructureCheck,\n RecoveryTransferState,\n} from \"./recovery-verification.types.ts\";\n\nfunction validManifest(\n value: unknown,\n expected: readonly string[],\n): value is RecoveryChecksumManifest {\n if (\n !value ||\n typeof value !== \"object\" ||\n !(\"version\" in value) ||\n value.version !== 1 ||\n !(\"algorithm\" in value) ||\n value.algorithm !== \"sha256\" ||\n !(\"entries\" in value) ||\n !Array.isArray(value.entries) ||\n value.entries.length !== expected.length\n )\n return false;\n const remaining = new Set(expected);\n if (remaining.size !== expected.length) return false;\n const entries: readonly unknown[] = value.entries;\n for (const entry of entries) {\n if (\n !entry ||\n typeof entry !== \"object\" ||\n !(\"path\" in entry) ||\n typeof entry.path !== \"string\" ||\n !remaining.delete(entry.path) ||\n !(\"kind\" in entry) ||\n (entry.kind !== \"file\" && entry.kind !== \"symlink\") ||\n !(\"bytes\" in entry) ||\n typeof entry.bytes !== \"number\" ||\n !Number.isSafeInteger(entry.bytes) ||\n entry.bytes < 0 ||\n !(\"sha256\" in entry) ||\n typeof entry.sha256 !== \"string\" ||\n !/^[a-f0-9]{64}$/.test(entry.sha256)\n )\n return false;\n }\n return remaining.size === 0;\n}\n\nexport async function verifyRecoveryChecksums(\n root: string,\n state: RecoveryTransferState,\n maxBytes: number = recoveryChecksumDefaults.maxBytes,\n): Promise<RecoveryChecksumResult> {\n positive(maxBytes, \"maxBytes\");\n const checks: RecoveryStructureCheck[] = [];\n let bytesChecked = 0;\n const manifestPath = join(root, recoveryChecksumDefaults.filename);\n const unavailable = (code: string): RecoveryChecksumResult => ({\n integrity: \"unverified\",\n bytesChecked,\n maxBytes,\n checks: [{ path: manifestPath, status: \"fail\", code }],\n });\n let manifest: unknown;\n try {\n manifest = JSON.parse(\n (\n await readInspectionFile(\n manifestPath,\n recoveryChecksumDefaults.maxManifestBytes,\n )\n ).toString(\"utf8\"),\n );\n } catch {\n return unavailable(\"CHECKSUMS_UNAVAILABLE\");\n }\n if (!validManifest(manifest, recoveryChecksumPaths(state)))\n return unavailable(\"INVALID_CHECKSUM_MANIFEST\");\n for (const entry of manifest.entries) {\n const path = join(root, entry.path);\n try {\n const actual = await hashInspectionEntry(\n await safeDestination(root, entry.path),\n maxBytes - bytesChecked,\n );\n bytesChecked += actual.bytes;\n const matches =\n actual.kind === entry.kind &&\n actual.bytes === entry.bytes &&\n actual.sha256 === entry.sha256;\n checks.push({\n path,\n status: matches ? \"pass\" : \"fail\",\n code: matches ? \"CHECKSUM_MATCH\" : \"CHECKSUM_MISMATCH\",\n });\n } catch (error) {\n const code =\n error instanceof OutpostError &&\n error.details.reason === \"CHECKSUM_LIMIT\"\n ? \"CHECKSUM_LIMIT\"\n : \"CHECKSUM_UNAVAILABLE\";\n checks.push({ path, status: \"fail\", code });\n return { integrity: \"unverified\", bytesChecked, maxBytes, checks };\n }\n }\n return {\n integrity: checks.every((check) => check.status === \"pass\")\n ? \"checksums-match\"\n : \"checksums-mismatch\",\n bytesChecked,\n maxBytes,\n checks,\n };\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { InspectionHash } from "../infrastructure/inspection-hash.types.ts";
|
|
2
|
+
import type { RecoveryStructureCheck } from "./recovery-verification.types.ts";
|
|
3
|
+
export interface RecoveryChecksumEntry extends InspectionHash {
|
|
4
|
+
readonly path: string;
|
|
5
|
+
}
|
|
6
|
+
export interface RecoveryChecksumManifest {
|
|
7
|
+
readonly version: 1;
|
|
8
|
+
readonly algorithm: "sha256";
|
|
9
|
+
readonly entries: readonly RecoveryChecksumEntry[];
|
|
10
|
+
}
|
|
11
|
+
export type RecoveryIntegrity = "unverified" | "checksums-match" | "checksums-mismatch";
|
|
12
|
+
export interface RecoveryChecksumResult {
|
|
13
|
+
readonly integrity: RecoveryIntegrity;
|
|
14
|
+
readonly bytesChecked: number;
|
|
15
|
+
readonly maxBytes: number;
|
|
16
|
+
readonly checks: readonly RecoveryStructureCheck[];
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery-checksums.types.js","sourceRoot":"","sources":["../../src/application/recovery-checksums.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { InspectionHash } from \"../infrastructure/inspection-hash.types.ts\";\nimport type { RecoveryStructureCheck } from \"./recovery-verification.types.ts\";\n\nexport interface RecoveryChecksumEntry extends InspectionHash {\n readonly path: string;\n}\nexport interface RecoveryChecksumManifest {\n readonly version: 1;\n readonly algorithm: \"sha256\";\n readonly entries: readonly RecoveryChecksumEntry[];\n}\nexport type RecoveryIntegrity =\n \"unverified\" | \"checksums-match\" | \"checksums-mismatch\";\nexport interface RecoveryChecksumResult {\n readonly integrity: RecoveryIntegrity;\n readonly bytesChecked: number;\n readonly maxBytes: number;\n readonly checks: readonly RecoveryStructureCheck[];\n}\n"]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { inspectResourceActivity } from "../infrastructure/resource-activity-inspection.js";
|
|
2
|
+
import { inspectLocks } from "../infrastructure/git/lock-inspection.js";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { directory } from "../infrastructure/files.js";
|
|
5
|
+
import { git } from "../infrastructure/git/command.js";
|
|
6
|
+
import { inspectWorktreeGit } from "../infrastructure/git/worktree-inspection.js";
|
|
7
|
+
import { storageInventory } from "../infrastructure/storage-inventory.js";
|
|
8
|
+
export async function inspectRecovery(options = {}) {
|
|
9
|
+
const requested = await directory(options.repository);
|
|
10
|
+
const repository = await directory((await git(requested, ["rev-parse", "--show-toplevel"])).trim());
|
|
11
|
+
const inventory = await storageInventory(join(repository, ".outpost"), options.maxEntries);
|
|
12
|
+
const gitReport = options.git
|
|
13
|
+
? await inspectWorktreeGit(repository, inventory.categories.find((category) => category.name === "workspaces")
|
|
14
|
+
?.entries ?? [])
|
|
15
|
+
: undefined;
|
|
16
|
+
const lockReport = options.locks
|
|
17
|
+
? await inspectLocks(inventory.categories.find((category) => category.name === "locks")
|
|
18
|
+
?.entries ?? [])
|
|
19
|
+
: undefined;
|
|
20
|
+
const resources = options.resources
|
|
21
|
+
? await inspectResourceActivity(repository, options.maxEntries)
|
|
22
|
+
: undefined;
|
|
23
|
+
return {
|
|
24
|
+
repository,
|
|
25
|
+
activity: "unverified",
|
|
26
|
+
...inventory,
|
|
27
|
+
...(resources ? { resources } : {}),
|
|
28
|
+
...(gitReport ? { git: gitReport } : {}),
|
|
29
|
+
...(lockReport ? { locks: lockReport } : {}),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=recovery-inspection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery-inspection.js","sourceRoot":"","sources":["../../src/application/recovery-inspection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,mDAAmD,CAAC;AAC5F,OAAO,EAAE,YAAY,EAAE,MAAM,0CAA0C,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,GAAG,EAAE,MAAM,kCAAkC,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAC;AAClF,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAM1E,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,UAAqC,EAAE;IAEvC,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACtD,MAAM,UAAU,GAAG,MAAM,SAAS,CAChC,CAAC,MAAM,GAAG,CAAC,SAAS,EAAE,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAChE,CAAC;IACF,MAAM,SAAS,GAAG,MAAM,gBAAgB,CACtC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,EAC5B,OAAO,CAAC,UAAU,CACnB,CAAC;IACF,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG;QAC3B,CAAC,CAAC,MAAM,kBAAkB,CACtB,UAAU,EACV,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC;YACrE,EAAE,OAAO,IAAI,EAAE,CAClB;QACH,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK;QAC9B,CAAC,CAAC,MAAM,YAAY,CAChB,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,OAAO,CAAC;YAChE,EAAE,OAAO,IAAI,EAAE,CAClB;QACH,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS;QACjC,CAAC,CAAC,MAAM,uBAAuB,CAAC,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC;QAC/D,CAAC,CAAC,SAAS,CAAC;IACd,OAAO;QACL,UAAU;QACV,QAAQ,EAAE,YAAY;QACtB,GAAG,SAAS;QACZ,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7C,CAAC;AACJ,CAAC","sourcesContent":["import { inspectResourceActivity } from \"../infrastructure/resource-activity-inspection.ts\";\nimport { inspectLocks } from \"../infrastructure/git/lock-inspection.ts\";\nimport { join } from \"node:path\";\nimport { directory } from \"../infrastructure/files.ts\";\nimport { git } from \"../infrastructure/git/command.ts\";\nimport { inspectWorktreeGit } from \"../infrastructure/git/worktree-inspection.ts\";\nimport { storageInventory } from \"../infrastructure/storage-inventory.ts\";\nimport type {\n RecoveryInspection,\n RecoveryInspectionOptions,\n} from \"./recovery-inspection.types.ts\";\n\nexport async function inspectRecovery(\n options: RecoveryInspectionOptions = {},\n): Promise<RecoveryInspection> {\n const requested = await directory(options.repository);\n const repository = await directory(\n (await git(requested, [\"rev-parse\", \"--show-toplevel\"])).trim(),\n );\n const inventory = await storageInventory(\n join(repository, \".outpost\"),\n options.maxEntries,\n );\n const gitReport = options.git\n ? await inspectWorktreeGit(\n repository,\n inventory.categories.find((category) => category.name === \"workspaces\")\n ?.entries ?? [],\n )\n : undefined;\n const lockReport = options.locks\n ? await inspectLocks(\n inventory.categories.find((category) => category.name === \"locks\")\n ?.entries ?? [],\n )\n : undefined;\n const resources = options.resources\n ? await inspectResourceActivity(repository, options.maxEntries)\n : undefined;\n return {\n repository,\n activity: \"unverified\",\n ...inventory,\n ...(resources ? { resources } : {}),\n ...(gitReport ? { git: gitReport } : {}),\n ...(lockReport ? { locks: lockReport } : {}),\n };\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ResourceInspection } from "../infrastructure/resource-activity.types.ts";
|
|
2
|
+
import type { LockInspection } from "../infrastructure/git/lock-inspection.types.ts";
|
|
3
|
+
import type { WorkspaceGitInspection } from "../infrastructure/git/worktree-inspection.types.ts";
|
|
4
|
+
import type { StorageInventory } from "../infrastructure/storage-inventory.types.ts";
|
|
5
|
+
export interface RecoveryInspectionOptions {
|
|
6
|
+
readonly repository?: string;
|
|
7
|
+
readonly maxEntries?: number;
|
|
8
|
+
readonly git?: boolean;
|
|
9
|
+
readonly locks?: boolean;
|
|
10
|
+
readonly resources?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface RecoveryInspection extends StorageInventory {
|
|
13
|
+
readonly repository: string;
|
|
14
|
+
readonly activity: "unverified";
|
|
15
|
+
readonly git?: WorkspaceGitInspection;
|
|
16
|
+
readonly locks?: LockInspection;
|
|
17
|
+
readonly resources?: ResourceInspection;
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery-inspection.types.js","sourceRoot":"","sources":["../../src/application/recovery-inspection.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ResourceInspection } from \"../infrastructure/resource-activity.types.ts\";\nimport type { LockInspection } from \"../infrastructure/git/lock-inspection.types.ts\";\nimport type { WorkspaceGitInspection } from \"../infrastructure/git/worktree-inspection.types.ts\";\nimport type { StorageInventory } from \"../infrastructure/storage-inventory.types.ts\";\n\nexport interface RecoveryInspectionOptions {\n readonly repository?: string;\n readonly maxEntries?: number;\n readonly git?: boolean;\n readonly locks?: boolean;\n readonly resources?: boolean;\n}\nexport interface RecoveryInspection extends StorageInventory {\n readonly repository: string;\n readonly activity: \"unverified\";\n readonly git?: WorkspaceGitInspection;\n readonly locks?: LockInspection;\n readonly resources?: ResourceInspection;\n}\n"]}
|