@elie-laloum/outpost 3.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 +18 -0
- package/README.md +3 -1
- package/SECURITY.md +3 -1
- 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 +1 -1
- package/dist/adapters/agents/protocol-fixtures.constants.js +37 -0
- package/dist/adapters/agents/protocol-fixtures.constants.js.map +1 -1
- 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/dispatch-validation.js +2 -0
- package/dist/application/dispatch-validation.js.map +1 -1
- package/dist/application/doctor-agent.constants.d.ts +2 -0
- package/dist/application/doctor-agent.constants.js +2 -0
- package/dist/application/doctor-agent.constants.js.map +1 -1
- package/dist/application/doctor-agent.js +1 -1
- package/dist/application/doctor-agent.js.map +1 -1
- package/dist/application/doctor-protocol.js +2 -1
- package/dist/application/doctor-protocol.js.map +1 -1
- package/dist/application/doctor.constants.js +1 -1
- package/dist/application/doctor.constants.js.map +1 -1
- package/dist/application/doctor.types.d.ts +1 -1
- package/dist/application/doctor.types.js.map +1 -1
- package/dist/application/outpost.types.d.ts +2 -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-inspection.js +5 -0
- package/dist/application/recovery-inspection.js.map +1 -1
- package/dist/application/recovery-inspection.types.d.ts +3 -0
- package/dist/application/recovery-inspection.types.js.map +1 -1
- 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.js +5 -0
- package/dist/application/recovery-retention.js.map +1 -1
- package/dist/application/recovery-verification.d.ts +2 -1
- package/dist/application/recovery-verification.js +1 -1
- package/dist/application/recovery-verification.js.map +1 -1
- package/dist/application/remote-apply.js +6 -0
- package/dist/application/remote-apply.js.map +1 -1
- package/dist/application/remote-download.js +2 -2
- 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 +20 -28
- package/dist/application/remote-validation.js.map +1 -1
- package/dist/application/remote-workspace.js +4 -10
- package/dist/application/remote-workspace.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 +23 -11
- 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 +1 -1
- package/dist/application/task-usage.js.map +1 -1
- package/dist/application/tasks.js +1 -1
- 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/doctor-command.js +1 -1
- package/dist/cli/doctor-command.js.map +1 -1
- package/dist/cli/main.constants.d.ts +11 -2
- package/dist/cli/main.constants.js +8 -4
- package/dist/cli/main.constants.js.map +1 -1
- package/dist/cli/recovery-command.js +28 -4
- package/dist/cli/recovery-command.js.map +1 -1
- 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/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/sandbox.types.d.ts +1 -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.d.ts +2 -2
- package/dist/domain/workflow/budget.js +5 -3
- package/dist/domain/workflow/budget.js.map +1 -1
- 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 +14 -2
- 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 +65 -32
- 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 +91 -16
- package/dist/domain/workflow/workflow-state.js.map +1 -1
- package/dist/domain/workflow.types.d.ts +13 -2
- package/dist/domain/workflow.types.js.map +1 -1
- package/dist/index.d.ts +32 -2
- package/dist/index.js +14 -1
- 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 +1 -1
- package/dist/infrastructure/file-manifest.js +3 -2
- package/dist/infrastructure/file-manifest.js.map +1 -1
- package/dist/infrastructure/git/verification-command.d.ts +1 -1
- package/dist/infrastructure/git/verification-command.js +3 -2
- package/dist/infrastructure/git/verification-command.js.map +1 -1
- package/dist/infrastructure/opentelemetry.js +1 -1
- package/dist/infrastructure/opentelemetry.js.map +1 -1
- 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-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 +5 -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/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 +4 -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 +19 -2
- package/dist/providers/container.js.map +1 -1
- package/dist/providers/container.types.d.ts +3 -0
- package/dist/providers/container.types.js.map +1 -1
- package/dist/providers/daytona-command.js +3 -2
- 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 +2 -0
- package/dist/providers/daytona.js.map +1 -1
- package/dist/providers/docker.d.ts +1 -0
- package/dist/providers/docker.js.map +1 -1
- package/dist/providers/file-batches.d.ts +1 -1
- package/dist/providers/file-batches.js +9 -0
- package/dist/providers/file-batches.js.map +1 -1
- 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 +1 -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 +5 -1
- 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 +5 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox-provision.js","sourceRoot":"","sources":["../../src/application/sandbox-provision.ts"],"names":[],"mappings":"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","sourcesContent":["import { stat } from \"node:fs/promises\";\nimport { join, posix } from \"node:path\";\nimport type { AgentAdapter } from \"../domain/agent.types.ts\";\nimport { invariant } from \"../domain/errors.ts\";\nimport type { SandboxLease } from \"../domain/sandbox.types.ts\";\nimport { git } from \"../infrastructure/git/command.ts\";\nimport { executeProcess } from \"../infrastructure/process.ts\";\nimport { resolveVariables } from \"../infrastructure/settings.ts\";\nimport { boundedTransfers } from \"../infrastructure/transfer.ts\";\nimport { docker } from \"../providers/docker.ts\";\nimport { prepareAdapter } from \"./agent-bootstrap.ts\";\nimport { hooks } from \"./lifecycle-hooks.ts\";\nimport type { SandboxOptions } from \"./outpost.types.ts\";\nimport { seedRemote } from \"./remote-workspace.ts\";\nimport type { RemoteSync } from \"./remote-workspace.types.ts\";\nimport type { ProvisionedSandbox } from \"./sandbox-session.types.ts\";\nimport { startupFailure } from \"./startup-recovery.ts\";\nimport { workspaces } from \"./workspace-registry.ts\";\nimport { openWorkspace } from \"./workspace.ts\";\n\nexport async function provisionSandbox(\n options: SandboxOptions,\n): Promise<ProvisionedSandbox> {\n options.signal?.throwIfAborted();\n const provider = options.provider ?? docker();\n if (provider.placement === \"remote\" && !options.workspace && !options.branch)\n options = { ...options, branch: { mode: \"integrate\" } };\n invariant(\n !options.workspace ||\n (!options.repository && !options.branch && !options.copies),\n \"A supplied workspace owns its repository, branch and copied inputs\",\n );\n const owned = !options.workspace;\n invariant(\n provider.placement !== \"remote\" ||\n ((options.workspace?.policy ?? options.branch)?.mode !== \"current\" &&\n (options.workspace || options.branch)),\n \"Remote providers require a named or integration workspace\",\n );\n const workspace = options.workspace ?? (await openWorkspace(options));\n const state = workspaces.get(workspace);\n invariant(\n state && !state.closed && !state.active,\n \"Workspace must be open and cannot belong to another sandbox\",\n );\n state.active = true;\n const lifecycle = options.hooks ?? state.hooks;\n const stop = new AbortController();\n const setupSignal = options.signal\n ? AbortSignal.any([options.signal, stop.signal])\n : stop.signal;\n let lease: SandboxLease | undefined, sync: RemoteSync | undefined;\n const prepared = new Map<AgentAdapter, AgentAdapter>();\n const staging = join(\n workspace.repository,\n \".outpost\",\n \"recovery\",\n \"conversations\",\n );\n try {\n const configured = await resolveVariables(\n workspace.repository,\n {},\n provider.variables,\n );\n const name = (\n await git(workspace.repository, [\"config\", \"--get\", \"user.name\"]).catch(\n () => \"Outpost\",\n )\n ).trim();\n const email = (\n await git(workspace.repository, [\"config\", \"--get\", \"user.email\"]).catch(\n () => \"outpost@localhost\",\n )\n ).trim();\n const variables = {\n GIT_AUTHOR_NAME: name,\n GIT_COMMITTER_NAME: name,\n GIT_AUTHOR_EMAIL: email,\n GIT_COMMITTER_EMAIL: email,\n ...configured,\n };\n lease = boundedTransfers(\n await provider.acquire({\n repository: workspace.repository,\n directory: workspace.directory,\n gitDirectories: workspace.gitDirectories,\n variables,\n signal: setupSignal,\n }),\n {\n ...(options.limits?.copyMs\n ? { deadlineMs: options.limits.copyMs }\n : {}),\n },\n );\n if (provider.placement === \"remote\") {\n sync = await seedRemote(workspace, lease, {\n ...(options.includeUncommitted ? { includeUncommitted: true } : {}),\n ...(options.limits ? { limits: options.limits } : {}),\n signal: setupSignal,\n });\n for (const path of options.copies ?? [])\n if (\n await stat(join(workspace.directory, path)).catch((error) => {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\")\n return undefined;\n throw error;\n })\n )\n await lease.upload(\n join(workspace.directory, path),\n posix.join(lease.root, path.replaceAll(\"\\\\\", \"/\")),\n );\n if (options.bootstrap !== false && options.agent)\n prepared.set(\n options.agent,\n await prepareAdapter(options.agent, lease, setupSignal),\n );\n }\n const initialized = await Promise.allSettled(\n [\n hooks(\n lifecycle?.hostReady ?? [],\n workspace.directory,\n executeProcess,\n setupSignal,\n ),\n hooks(\n lifecycle?.sandboxReady ?? [],\n lease.root,\n lease.invoke.bind(lease),\n setupSignal,\n true,\n ),\n ].map((pending) =>\n pending.catch((cause) => {\n stop.abort(cause);\n throw cause;\n }),\n ),\n );\n const failure = initialized.find((item) => item.status === \"rejected\");\n if (failure?.status === \"rejected\") throw failure.reason;\n } catch (cause) {\n await startupFailure(workspace, cause, options);\n await lease?.release().catch(() => undefined);\n state.active = false;\n if (owned) await workspace.close();\n throw cause;\n }\n\n return {\n options,\n provider,\n workspace,\n state,\n owned,\n stop,\n runtime: lease,\n sync,\n prepared,\n staging,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sandbox-provision.js","sourceRoot":"","sources":["../../src/application/sandbox-provision.ts"],"names":[],"mappings":"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","sourcesContent":["import { lstat } from \"node:fs/promises\";\nimport { join, posix } from \"node:path\";\nimport type { AgentAdapter } from \"../domain/agent.types.ts\";\nimport { invariant } from \"../domain/errors.ts\";\nimport type { SandboxLease } from \"../domain/sandbox.types.ts\";\nimport { git } from \"../infrastructure/git/command.ts\";\nimport { executeProcess } from \"../infrastructure/process.ts\";\nimport { resolveVariables } from \"../infrastructure/settings.ts\";\nimport { registerResourceActivity } from \"../infrastructure/resource-activity.ts\";\nimport type { ResourceActivity } from \"../infrastructure/resource-activity.types.ts\";\nimport { trackedSandboxLease } from \"./sandbox-activity.ts\";\nimport { boundedTransfers } from \"../infrastructure/transfer.ts\";\nimport { docker } from \"../providers/docker.ts\";\nimport { prepareAdapter } from \"./agent-bootstrap.ts\";\nimport { hooks } from \"./lifecycle-hooks.ts\";\nimport type { SandboxOptions } from \"./outpost.types.ts\";\nimport { uploadFiles } from \"./remote-upload.ts\";\nimport { seedRemote } from \"./remote-workspace.ts\";\nimport type { RemoteSync } from \"./remote-workspace.types.ts\";\nimport type { ProvisionedSandbox } from \"./sandbox-session.types.ts\";\nimport { startupFailure } from \"./startup-recovery.ts\";\nimport { workspaces } from \"./workspace-registry.ts\";\nimport { openWorkspace } from \"./workspace.ts\";\n\nexport async function provisionSandbox(\n options: SandboxOptions,\n): Promise<ProvisionedSandbox> {\n options.signal?.throwIfAborted();\n const provider = options.provider ?? docker();\n if (provider.placement === \"remote\" && !options.workspace && !options.branch)\n options = { ...options, branch: { mode: \"integrate\" } };\n invariant(\n !options.workspace ||\n (!options.repository &&\n !options.branch &&\n !options.copies &&\n !options.storageQuota),\n \"A supplied workspace owns its repository, branch, copied inputs and storage quota\",\n );\n const owned = !options.workspace;\n invariant(\n provider.placement !== \"remote\" ||\n ((options.workspace?.policy ?? options.branch)?.mode !== \"current\" &&\n (options.workspace || options.branch)),\n \"Remote providers require a named or integration workspace\",\n );\n const workspace = options.workspace ?? (await openWorkspace(options));\n const state = workspaces.get(workspace);\n invariant(\n state && !state.closed && !state.active,\n \"Workspace must be open and cannot belong to another sandbox\",\n );\n state.active = true;\n const lifecycle = options.hooks ?? state.hooks;\n const stop = new AbortController();\n const setupSignal = options.signal\n ? AbortSignal.any([options.signal, stop.signal])\n : stop.signal;\n let lease: SandboxLease | undefined, sync: RemoteSync | undefined;\n let activity: ResourceActivity | undefined;\n let acquisitionStarted = false;\n const prepared = new Map<AgentAdapter, AgentAdapter>();\n const staging = join(\n workspace.repository,\n \".outpost\",\n \"recovery\",\n \"conversations\",\n );\n try {\n activity = await registerResourceActivity({\n repository: workspace.repository,\n workspace: workspace.directory,\n provider: provider.name,\n placement: provider.placement,\n });\n const configured = await resolveVariables(\n workspace.repository,\n {},\n provider.variables,\n );\n const name = (\n await git(workspace.repository, [\"config\", \"--get\", \"user.name\"]).catch(\n () => \"Outpost\",\n )\n ).trim();\n const email = (\n await git(workspace.repository, [\"config\", \"--get\", \"user.email\"]).catch(\n () => \"outpost@localhost\",\n )\n ).trim();\n const variables = {\n GIT_AUTHOR_NAME: name,\n GIT_COMMITTER_NAME: name,\n GIT_AUTHOR_EMAIL: email,\n GIT_COMMITTER_EMAIL: email,\n ...configured,\n };\n acquisitionStarted = true;\n lease = boundedTransfers(\n trackedSandboxLease(\n await provider.acquire({\n repository: workspace.repository,\n directory: workspace.directory,\n gitDirectories: workspace.gitDirectories,\n variables,\n signal: setupSignal,\n }),\n activity,\n ),\n {\n ...(options.limits?.copyMs\n ? { deadlineMs: options.limits.copyMs }\n : {}),\n },\n );\n if (provider.placement === \"remote\") {\n sync = await seedRemote(workspace, lease, {\n ...(options.includeUncommitted ? { includeUncommitted: true } : {}),\n ...(options.limits ? { limits: options.limits } : {}),\n signal: setupSignal,\n });\n const copiedFiles: string[] = [];\n for (const path of options.copies ?? []) {\n const info = await lstat(join(workspace.directory, path)).catch(\n (error) => {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\")\n return undefined;\n throw error;\n },\n );\n if (!info) continue;\n if (info.isFile() || info.isSymbolicLink()) {\n copiedFiles.push(path.replaceAll(\"\\\\\", \"/\"));\n continue;\n }\n await lease.upload(\n join(workspace.directory, path),\n posix.join(lease.root, path.replaceAll(\"\\\\\", \"/\")),\n { signal: setupSignal },\n );\n }\n await uploadFiles(lease, workspace.directory, [...new Set(copiedFiles)], {\n signal: setupSignal,\n });\n if (options.bootstrap !== false && options.agent)\n prepared.set(\n options.agent,\n await prepareAdapter(options.agent, lease, setupSignal),\n );\n }\n const initialized = await Promise.allSettled(\n [\n hooks(\n lifecycle?.hostReady ?? [],\n workspace.directory,\n executeProcess,\n setupSignal,\n ),\n hooks(\n lifecycle?.sandboxReady ?? [],\n lease.root,\n lease.invoke.bind(lease),\n setupSignal,\n true,\n ),\n ].map((pending) =>\n pending.catch((cause) => {\n stop.abort(cause);\n throw cause;\n }),\n ),\n );\n const failure = initialized.find((item) => item.status === \"rejected\");\n if (failure?.status === \"rejected\") throw failure.reason;\n await activity.phase(\"ready\");\n } catch (cause) {\n await startupFailure(workspace, cause, options);\n const allocationUncertain = acquisitionStarted && !lease;\n let cleanupFailed = allocationUncertain;\n await activity?.phase(\"closing\").catch(() => {\n cleanupFailed = true;\n });\n await lease?.release().catch(() => {\n cleanupFailed = true;\n });\n if (activity && !(await activity.idle())) cleanupFailed = true;\n state.active = false;\n if (owned)\n await workspace.close({ preserve: cleanupFailed }).catch(() => {\n cleanupFailed = true;\n });\n if (cleanupFailed)\n await activity\n ?.phase(allocationUncertain ? \"allocation-uncertain\" : \"cleanup-failed\")\n .catch(() => undefined);\n if (!cleanupFailed) await activity?.remove().catch(() => undefined);\n throw cause;\n }\n\n return {\n options,\n provider,\n workspace,\n state,\n owned,\n stop,\n runtime: lease,\n activity,\n sync,\n prepared,\n staging,\n };\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ResourceActivity } from "../infrastructure/resource-activity.types.ts";
|
|
1
2
|
import type { AgentAdapter } from "../domain/agent.types.ts";
|
|
2
3
|
import type { SandboxLease, SandboxProvider } from "../domain/sandbox.types.ts";
|
|
3
4
|
import type { LifecycleHooks } from "../domain/workspace.types.ts";
|
|
@@ -18,6 +19,7 @@ export interface ProvisionedSandbox {
|
|
|
18
19
|
readonly owned: boolean;
|
|
19
20
|
readonly stop: AbortController;
|
|
20
21
|
readonly runtime: SandboxLease;
|
|
22
|
+
readonly activity: ResourceActivity;
|
|
21
23
|
readonly sync: RemoteSync | undefined;
|
|
22
24
|
readonly prepared: Map<AgentAdapter, AgentAdapter>;
|
|
23
25
|
readonly staging: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox-session.types.js","sourceRoot":"","sources":["../../src/application/sandbox-session.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AgentAdapter } from \"../domain/agent.types.ts\";\nimport type { SandboxLease, SandboxProvider } from \"../domain/sandbox.types.ts\";\nimport type { LifecycleHooks } from \"../domain/workspace.types.ts\";\nimport type { WorkspaceLease } from \"../infrastructure/git/workspace.types.ts\";\nimport type { SandboxOptions, Workspace } from \"./outpost.types.ts\";\nimport type { RemoteSync } from \"./remote-workspace.types.ts\";\n\nexport interface WorkspaceState {\n lease: WorkspaceLease;\n active: boolean;\n closed: boolean;\n hooks?: LifecycleHooks;\n}\n\nexport interface ProvisionedSandbox {\n readonly options: SandboxOptions;\n readonly provider: SandboxProvider;\n readonly workspace: Workspace;\n readonly state: WorkspaceState;\n readonly owned: boolean;\n readonly stop: AbortController;\n readonly runtime: SandboxLease;\n readonly sync: RemoteSync | undefined;\n readonly prepared: Map<AgentAdapter, AgentAdapter>;\n readonly staging: string;\n}\n\nexport interface SelectedAgent {\n readonly selected: AgentAdapter;\n readonly adapter: AgentAdapter;\n readonly executionLease: SandboxLease;\n}\n\nexport interface SandboxAgents {\n selectAgent(\n agent: AgentAdapter | undefined,\n signal: AbortSignal,\n ): Promise<SelectedAgent>;\n restore(id: string, agent: AgentAdapter): Promise<void>;\n remember(agent: AgentAdapter, id: string): void;\n}\n\nexport interface OperationGate {\n run<T>(action: () => Promise<T>): Promise<T>;\n close(): Promise<void>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sandbox-session.types.js","sourceRoot":"","sources":["../../src/application/sandbox-session.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ResourceActivity } from \"../infrastructure/resource-activity.types.ts\";\nimport type { AgentAdapter } from \"../domain/agent.types.ts\";\nimport type { SandboxLease, SandboxProvider } from \"../domain/sandbox.types.ts\";\nimport type { LifecycleHooks } from \"../domain/workspace.types.ts\";\nimport type { WorkspaceLease } from \"../infrastructure/git/workspace.types.ts\";\nimport type { SandboxOptions, Workspace } from \"./outpost.types.ts\";\nimport type { RemoteSync } from \"./remote-workspace.types.ts\";\n\nexport interface WorkspaceState {\n lease: WorkspaceLease;\n active: boolean;\n closed: boolean;\n hooks?: LifecycleHooks;\n}\n\nexport interface ProvisionedSandbox {\n readonly options: SandboxOptions;\n readonly provider: SandboxProvider;\n readonly workspace: Workspace;\n readonly state: WorkspaceState;\n readonly owned: boolean;\n readonly stop: AbortController;\n readonly runtime: SandboxLease;\n readonly activity: ResourceActivity;\n readonly sync: RemoteSync | undefined;\n readonly prepared: Map<AgentAdapter, AgentAdapter>;\n readonly staging: string;\n}\n\nexport interface SelectedAgent {\n readonly selected: AgentAdapter;\n readonly adapter: AgentAdapter;\n readonly executionLease: SandboxLease;\n}\n\nexport interface SandboxAgents {\n selectAgent(\n agent: AgentAdapter | undefined,\n signal: AbortSignal,\n ): Promise<SelectedAgent>;\n restore(id: string, agent: AgentAdapter): Promise<void>;\n remember(agent: AgentAdapter, id: string): void;\n}\n\nexport interface OperationGate {\n run<T>(action: () => Promise<T>): Promise<T>;\n close(): Promise<void>;\n}\n"]}
|
|
@@ -13,14 +13,14 @@ export async function createSandbox(options = {}) {
|
|
|
13
13
|
const { workspace, runtime, sync, stop, state, owned } = context;
|
|
14
14
|
const agents = sandboxAgents(context);
|
|
15
15
|
const gate = operationGate();
|
|
16
|
-
const exclusive = gate.run;
|
|
16
|
+
const exclusive = (kind, action) => gate.run(() => context.activity.run(kind, action));
|
|
17
17
|
let closing;
|
|
18
18
|
const result = {
|
|
19
19
|
workspace,
|
|
20
20
|
root: runtime.root,
|
|
21
21
|
dispatch(settings) {
|
|
22
22
|
validateDispatch(settings);
|
|
23
|
-
return exclusive(() => dispatchInSandbox(context, agents, result, settings));
|
|
23
|
+
return exclusive("dispatch", () => dispatchInSandbox(context, agents, result, settings));
|
|
24
24
|
},
|
|
25
25
|
resume(id, settings) {
|
|
26
26
|
return result.dispatch({ ...settings, continuation: { id } });
|
|
@@ -31,11 +31,11 @@ export async function createSandbox(options = {}) {
|
|
|
31
31
|
attach(settings = {}) {
|
|
32
32
|
settings.signal?.throwIfAborted();
|
|
33
33
|
validateBrief(settings.brief, true);
|
|
34
|
-
return exclusive(() => attachInSandbox(context, agents, settings));
|
|
34
|
+
return exclusive("attach", () => attachInSandbox(context, agents, settings));
|
|
35
35
|
},
|
|
36
36
|
diagnose(settings = {}) {
|
|
37
37
|
settings.signal?.throwIfAborted();
|
|
38
|
-
return exclusive(() => diagnoseSandbox(runtime, {
|
|
38
|
+
return exclusive("diagnose", () => diagnoseSandbox(runtime, {
|
|
39
39
|
...settings,
|
|
40
40
|
provider: context.provider,
|
|
41
41
|
signal: settings.signal
|
|
@@ -45,7 +45,7 @@ export async function createSandbox(options = {}) {
|
|
|
45
45
|
},
|
|
46
46
|
command(command) {
|
|
47
47
|
command.signal?.throwIfAborted();
|
|
48
|
-
return exclusive(async () => {
|
|
48
|
+
return exclusive("command", async () => {
|
|
49
49
|
try {
|
|
50
50
|
return await runtime.invoke({
|
|
51
51
|
...command,
|
|
@@ -66,21 +66,33 @@ export async function createSandbox(options = {}) {
|
|
|
66
66
|
stop.abort(new OutpostError("aborted", "Sandbox closed"));
|
|
67
67
|
await gate.close();
|
|
68
68
|
let failure;
|
|
69
|
+
await context.activity.phase("closing").catch(() => undefined);
|
|
69
70
|
try {
|
|
70
71
|
await runtime.release();
|
|
71
72
|
await sync?.close();
|
|
73
|
+
if (!(await context.activity.idle()))
|
|
74
|
+
throw new OutpostError("provider", "Sandbox operations remain unsettled after release");
|
|
72
75
|
}
|
|
73
76
|
catch (cause) {
|
|
74
77
|
failure = cause;
|
|
75
78
|
}
|
|
76
79
|
state.active = false;
|
|
77
80
|
unregister();
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
let disposal = {};
|
|
82
|
+
try {
|
|
83
|
+
if (owned)
|
|
84
|
+
disposal = await workspace.close({
|
|
85
|
+
preserve: settings.preserve || !!failure,
|
|
86
|
+
});
|
|
87
|
+
if (failure)
|
|
88
|
+
throw failure;
|
|
89
|
+
await context.activity.remove();
|
|
90
|
+
return disposal;
|
|
91
|
+
}
|
|
92
|
+
catch (cause) {
|
|
93
|
+
await context.activity.phase("cleanup-failed").catch(() => undefined);
|
|
94
|
+
throw cause;
|
|
95
|
+
}
|
|
84
96
|
})();
|
|
85
97
|
return closing;
|
|
86
98
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/application/sandbox.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/application/sandbox.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ResourceOperationKind } from \"../infrastructure/resource-activity.types.ts\";\nimport { OutpostError } from \"../domain/errors.ts\";\nimport { validateBrief } from \"../domain/prompts.ts\";\nimport type { Disposal } from \"../domain/workspace.types.ts\";\nimport { registerCleanup } from \"../infrastructure/shutdown.ts\";\nimport { validateDispatch } from \"./dispatch-validation.ts\";\nimport { diagnoseSandbox } from \"./doctor-sandbox.ts\";\nimport { operationGate } from \"./operation-gate.ts\";\nimport type { Sandbox, SandboxOptions } from \"./outpost.types.ts\";\nimport { sandboxAgents } from \"./sandbox-agents.ts\";\nimport { attachInSandbox } from \"./sandbox-attach.ts\";\nimport { dispatchInSandbox } from \"./sandbox-dispatch.ts\";\nimport { provisionSandbox } from \"./sandbox-provision.ts\";\n\nexport async function createSandbox(\n options: SandboxOptions = {},\n): Promise<Sandbox> {\n const context = await provisionSandbox(options);\n const { workspace, runtime, sync, stop, state, owned } = context;\n const agents = sandboxAgents(context);\n const gate = operationGate();\n const exclusive = <T>(\n kind: ResourceOperationKind,\n action: () => Promise<T>,\n ) => gate.run(() => context.activity.run(kind, action));\n let closing: Promise<Disposal> | undefined;\n const result: Sandbox = {\n workspace,\n root: runtime.root,\n dispatch(settings) {\n validateDispatch(settings);\n return exclusive(\"dispatch\", () =>\n dispatchInSandbox(context, agents, result, settings),\n );\n },\n resume(id, settings) {\n return result.dispatch({ ...settings, continuation: { id } });\n },\n fork(id, settings) {\n return result.dispatch({ ...settings, continuation: { id, fork: true } });\n },\n attach(settings = {}) {\n settings.signal?.throwIfAborted();\n validateBrief(settings.brief, true);\n return exclusive(\"attach\", () =>\n attachInSandbox(context, agents, settings),\n );\n },\n diagnose(settings = {}) {\n settings.signal?.throwIfAborted();\n return exclusive(\"diagnose\", () =>\n diagnoseSandbox(runtime, {\n ...settings,\n provider: context.provider,\n signal: settings.signal\n ? AbortSignal.any([settings.signal, stop.signal])\n : stop.signal,\n }),\n );\n },\n command(command) {\n command.signal?.throwIfAborted();\n return exclusive(\"command\", async () => {\n try {\n return await runtime.invoke({\n ...command,\n signal: command.signal\n ? AbortSignal.any([command.signal, stop.signal])\n : stop.signal,\n });\n } finally {\n await sync?.pull();\n }\n });\n },\n close(settings = {}) {\n if (closing) return closing;\n closing = (async () => {\n stop.abort(new OutpostError(\"aborted\", \"Sandbox closed\"));\n await gate.close();\n let failure: unknown;\n await context.activity.phase(\"closing\").catch(() => undefined);\n try {\n await runtime.release();\n await sync?.close();\n if (!(await context.activity.idle()))\n throw new OutpostError(\n \"provider\",\n \"Sandbox operations remain unsettled after release\",\n );\n } catch (cause) {\n failure = cause;\n }\n state.active = false;\n\n unregister();\n let disposal: Disposal = {};\n try {\n if (owned)\n disposal = await workspace.close({\n preserve: settings.preserve || !!failure,\n });\n if (failure) throw failure;\n await context.activity.remove();\n return disposal;\n } catch (cause) {\n await context.activity.phase(\"cleanup-failed\").catch(() => undefined);\n throw cause;\n }\n })();\n return closing;\n },\n async [Symbol.asyncDispose]() {\n await result.close();\n },\n };\n const unregister = registerCleanup(() => result.close({ preserve: true }));\n return result;\n}\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { git } from "../infrastructure/git/command.js";
|
|
5
|
+
import { digest } from "./workspace-fingerprint.js";
|
|
6
|
+
export async function speculativeHostSnapshot(repository) {
|
|
7
|
+
const temporary = await mkdtemp(join(tmpdir(), "outpost-speculation-"));
|
|
8
|
+
try {
|
|
9
|
+
const head = (await git(repository, ["rev-parse", "--verify", "HEAD^{commit}"])).trim();
|
|
10
|
+
const branch = (await git(repository, ["rev-parse", "--abbrev-ref", "HEAD"])).trim();
|
|
11
|
+
const status = await git(repository, [
|
|
12
|
+
"status",
|
|
13
|
+
"--porcelain",
|
|
14
|
+
"--untracked-files=all",
|
|
15
|
+
"--",
|
|
16
|
+
".",
|
|
17
|
+
":(exclude).outpost",
|
|
18
|
+
]);
|
|
19
|
+
return {
|
|
20
|
+
head,
|
|
21
|
+
branch,
|
|
22
|
+
dirty: !!status.trim(),
|
|
23
|
+
fingerprint: await digest(repository, temporary),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
await rm(temporary, { recursive: true, force: true });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=speculation-host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"speculation-host.js","sourceRoot":"","sources":["../../src/application/speculation-host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,GAAG,EAAE,MAAM,kCAAkC,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAGpD,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,UAAkB;IAElB,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC,CAAC;IACxE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,CACX,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC,CAClE,CAAC,IAAI,EAAE,CAAC;QACT,MAAM,MAAM,GAAG,CACb,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAC7D,CAAC,IAAI,EAAE,CAAC;QACT,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,UAAU,EAAE;YACnC,QAAQ;YACR,aAAa;YACb,uBAAuB;YACvB,IAAI;YACJ,GAAG;YACH,oBAAoB;SACrB,CAAC,CAAC;QACH,OAAO;YACL,IAAI;YACJ,MAAM;YACN,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE;YACtB,WAAW,EAAE,MAAM,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC;SACjD,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;AACH,CAAC","sourcesContent":["import { mkdtemp, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { git } from \"../infrastructure/git/command.ts\";\nimport { digest } from \"./workspace-fingerprint.ts\";\nimport type { SpeculativeHostSnapshot } from \"./speculation.types.ts\";\n\nexport async function speculativeHostSnapshot(\n repository: string,\n): Promise<SpeculativeHostSnapshot> {\n const temporary = await mkdtemp(join(tmpdir(), \"outpost-speculation-\"));\n try {\n const head = (\n await git(repository, [\"rev-parse\", \"--verify\", \"HEAD^{commit}\"])\n ).trim();\n const branch = (\n await git(repository, [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"])\n ).trim();\n const status = await git(repository, [\n \"status\",\n \"--porcelain\",\n \"--untracked-files=all\",\n \"--\",\n \".\",\n \":(exclude).outpost\",\n ]);\n return {\n head,\n branch,\n dirty: !!status.trim(),\n fingerprint: await digest(repository, temporary),\n };\n } finally {\n await rm(temporary, { recursive: true, force: true });\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"speculation.constants.js","sourceRoot":"","sources":["../../src/application/speculation.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAW,CAAC","sourcesContent":["export const speculationLimits = { candidates: 8, concurrency: 2 } as const;\n"]}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { invariant, recoveryDetails } from "../domain/errors.js";
|
|
3
|
+
import { workflowAccounting } from "../domain/workflow/budget.js";
|
|
4
|
+
import { speculativeHostSnapshot } from "./speculation-host.js";
|
|
5
|
+
import { createSandbox } from "./sandbox.js";
|
|
6
|
+
import { speculationLimits } from "./speculation.constants.js";
|
|
7
|
+
import { taskUsage } from "./task-usage.js";
|
|
8
|
+
export async function speculate(options) {
|
|
9
|
+
const { candidates } = options;
|
|
10
|
+
invariant(candidates.length > 0 && candidates.length <= speculationLimits.candidates, `Speculation requires 1 to ${speculationLimits.candidates} candidates`);
|
|
11
|
+
invariant(new Set(candidates.map((candidate) => candidate.key)).size ===
|
|
12
|
+
candidates.length &&
|
|
13
|
+
candidates.every((candidate) => /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/.test(candidate.key)), "Speculative candidate keys must be unique simple names of 1 to 64 characters");
|
|
14
|
+
const concurrency = options.concurrency ?? speculationLimits.concurrency;
|
|
15
|
+
invariant(Number.isSafeInteger(concurrency) &&
|
|
16
|
+
concurrency > 0 &&
|
|
17
|
+
concurrency <= speculationLimits.candidates, `Speculation concurrency must be 1 to ${speculationLimits.candidates}`);
|
|
18
|
+
const stop = new AbortController();
|
|
19
|
+
const signal = options.signal
|
|
20
|
+
? AbortSignal.any([options.signal, stop.signal])
|
|
21
|
+
: stop.signal;
|
|
22
|
+
let budgetError;
|
|
23
|
+
const accounting = workflowAccounting(options.budget, (error) => {
|
|
24
|
+
budgetError = error;
|
|
25
|
+
// Attempt limits stop admissions; already admitted candidates may finish.
|
|
26
|
+
if (error.dimension !== "attempts")
|
|
27
|
+
stop.abort(error);
|
|
28
|
+
});
|
|
29
|
+
const before = await speculativeHostSnapshot(options.repository);
|
|
30
|
+
const baseline = before.head;
|
|
31
|
+
const id = randomUUID();
|
|
32
|
+
const records = candidates.map((candidate) => ({
|
|
33
|
+
key: candidate.key,
|
|
34
|
+
branch: `outpost/speculation/${id}/${candidate.key}`,
|
|
35
|
+
status: "skipped",
|
|
36
|
+
}));
|
|
37
|
+
let winner;
|
|
38
|
+
let next = 0;
|
|
39
|
+
async function worker() {
|
|
40
|
+
while (!signal.aborted && !winner && !accounting.exhausted) {
|
|
41
|
+
const index = next++;
|
|
42
|
+
const candidate = candidates[index];
|
|
43
|
+
if (!candidate)
|
|
44
|
+
return;
|
|
45
|
+
try {
|
|
46
|
+
accounting.admit();
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const initial = records[index];
|
|
52
|
+
let sandbox;
|
|
53
|
+
let result;
|
|
54
|
+
let error;
|
|
55
|
+
let accepted = false;
|
|
56
|
+
let cleanupFailed = false;
|
|
57
|
+
let retainedDirectory;
|
|
58
|
+
const usage = taskUsage({ reportUsage: (value) => accounting.report(value) }, candidate.request.observe);
|
|
59
|
+
try {
|
|
60
|
+
sandbox = await createSandbox({
|
|
61
|
+
...options.sandbox,
|
|
62
|
+
repository: options.repository,
|
|
63
|
+
provider: options.provider,
|
|
64
|
+
branch: { mode: "named", name: initial.branch, from: baseline },
|
|
65
|
+
agent: candidate.agent,
|
|
66
|
+
signal,
|
|
67
|
+
});
|
|
68
|
+
signal.throwIfAborted();
|
|
69
|
+
invariant(sandbox.workspace.baseline === baseline, "Speculative workspace does not match the pinned baseline");
|
|
70
|
+
const { resume: _resume, fork: _fork, ...output } = await sandbox.dispatch({
|
|
71
|
+
...candidate.request,
|
|
72
|
+
signal,
|
|
73
|
+
observe: usage.observe,
|
|
74
|
+
});
|
|
75
|
+
result = output;
|
|
76
|
+
usage.reconcile(output.usage);
|
|
77
|
+
signal.throwIfAborted();
|
|
78
|
+
accepted = await options.validate({
|
|
79
|
+
key: candidate.key,
|
|
80
|
+
result,
|
|
81
|
+
sandbox,
|
|
82
|
+
signal,
|
|
83
|
+
});
|
|
84
|
+
signal.throwIfAborted();
|
|
85
|
+
}
|
|
86
|
+
catch (cause) {
|
|
87
|
+
error = cause;
|
|
88
|
+
}
|
|
89
|
+
if (sandbox) {
|
|
90
|
+
try {
|
|
91
|
+
const disposal = await sandbox.close({
|
|
92
|
+
preserve: error !== undefined,
|
|
93
|
+
});
|
|
94
|
+
retainedDirectory = disposal.retainedDirectory;
|
|
95
|
+
}
|
|
96
|
+
catch (cause) {
|
|
97
|
+
cleanupFailed = true;
|
|
98
|
+
error =
|
|
99
|
+
error === undefined
|
|
100
|
+
? cause
|
|
101
|
+
: new AggregateError([error, cause], "Speculative execution and cleanup failed");
|
|
102
|
+
retainedDirectory = sandbox.workspace.directory;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const recovery = recoveryDetails(error);
|
|
106
|
+
const recoveredDirectory = typeof recovery?.directory === "string"
|
|
107
|
+
? recovery.directory
|
|
108
|
+
: undefined;
|
|
109
|
+
const directory = sandbox?.workspace.directory ?? recoveredDirectory;
|
|
110
|
+
retainedDirectory ??= recoveredDirectory;
|
|
111
|
+
function candidateStatus() {
|
|
112
|
+
if (cleanupFailed)
|
|
113
|
+
return "failed";
|
|
114
|
+
if (signal.aborted)
|
|
115
|
+
return "cancelled";
|
|
116
|
+
if (error !== undefined)
|
|
117
|
+
return "failed";
|
|
118
|
+
if (accepted && !winner)
|
|
119
|
+
return "winner";
|
|
120
|
+
return "rejected";
|
|
121
|
+
}
|
|
122
|
+
const status = candidateStatus();
|
|
123
|
+
const record = {
|
|
124
|
+
...initial,
|
|
125
|
+
status,
|
|
126
|
+
...(directory ? { directory } : {}),
|
|
127
|
+
...(retainedDirectory ? { retainedDirectory } : {}),
|
|
128
|
+
...(result ? { result } : {}),
|
|
129
|
+
...(error !== undefined ? { error } : {}),
|
|
130
|
+
};
|
|
131
|
+
records[index] = record;
|
|
132
|
+
if (status === "winner") {
|
|
133
|
+
winner = record;
|
|
134
|
+
stop.abort(new Error(`Speculative candidate ${candidate.key} selected`));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, candidates.length) }, worker));
|
|
139
|
+
function outcome() {
|
|
140
|
+
if (winner)
|
|
141
|
+
return "winner";
|
|
142
|
+
if (options.signal?.aborted)
|
|
143
|
+
return "aborted";
|
|
144
|
+
if (budgetError !== undefined)
|
|
145
|
+
return "budget-exhausted";
|
|
146
|
+
return "no-winner";
|
|
147
|
+
}
|
|
148
|
+
const status = outcome();
|
|
149
|
+
const host = await speculativeHostSnapshot(options.repository).then((after) => ({
|
|
150
|
+
before,
|
|
151
|
+
after,
|
|
152
|
+
changed: before.fingerprint !== after.fingerprint ||
|
|
153
|
+
before.branch !== after.branch,
|
|
154
|
+
}), (error) => ({ before, changed: true, error }));
|
|
155
|
+
return {
|
|
156
|
+
id,
|
|
157
|
+
baseline,
|
|
158
|
+
host,
|
|
159
|
+
status,
|
|
160
|
+
candidates: records,
|
|
161
|
+
usage: accounting.snapshot(),
|
|
162
|
+
...(winner ? { winner } : {}),
|
|
163
|
+
...(budgetError !== undefined ? { error: budgetError } : {}),
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=speculation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"speculation.js","sourceRoot":"","sources":["../../src/application/speculation.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { invariant, recoveryDetails } from \"../domain/errors.ts\";\nimport { workflowAccounting } from \"../domain/workflow/budget.ts\";\nimport { speculativeHostSnapshot } from \"./speculation-host.ts\";\nimport type { Sandbox } from \"./outpost.types.ts\";\nimport { createSandbox } from \"./sandbox.ts\";\nimport { speculationLimits } from \"./speculation.constants.ts\";\nimport type {\n SpeculationOptions,\n SpeculationResult,\n SpeculativeCandidateResult,\n SpeculativeOutput,\n} from \"./speculation.types.ts\";\nimport { taskUsage } from \"./task-usage.ts\";\n\nexport async function speculate<T = undefined>(\n options: SpeculationOptions<T>,\n): Promise<SpeculationResult<T>> {\n const { candidates } = options;\n invariant(\n candidates.length > 0 && candidates.length <= speculationLimits.candidates,\n `Speculation requires 1 to ${speculationLimits.candidates} candidates`,\n );\n invariant(\n new Set(candidates.map((candidate) => candidate.key)).size ===\n candidates.length &&\n candidates.every((candidate) =>\n /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/.test(candidate.key),\n ),\n \"Speculative candidate keys must be unique simple names of 1 to 64 characters\",\n );\n const concurrency = options.concurrency ?? speculationLimits.concurrency;\n invariant(\n Number.isSafeInteger(concurrency) &&\n concurrency > 0 &&\n concurrency <= speculationLimits.candidates,\n `Speculation concurrency must be 1 to ${speculationLimits.candidates}`,\n );\n const stop = new AbortController();\n const signal = options.signal\n ? AbortSignal.any([options.signal, stop.signal])\n : stop.signal;\n let budgetError: unknown;\n const accounting = workflowAccounting(options.budget, (error) => {\n budgetError = error;\n // Attempt limits stop admissions; already admitted candidates may finish.\n if (error.dimension !== \"attempts\") stop.abort(error);\n });\n const before = await speculativeHostSnapshot(options.repository);\n const baseline = before.head;\n const id = randomUUID();\n const records: SpeculativeCandidateResult<T>[] = candidates.map(\n (candidate) => ({\n key: candidate.key,\n branch: `outpost/speculation/${id}/${candidate.key}`,\n status: \"skipped\",\n }),\n );\n let winner: SpeculativeCandidateResult<T> | undefined;\n let next = 0;\n async function worker(): Promise<void> {\n while (!signal.aborted && !winner && !accounting.exhausted) {\n const index = next++;\n const candidate = candidates[index];\n if (!candidate) return;\n try {\n accounting.admit();\n } catch {\n return;\n }\n const initial = records[index]!;\n let sandbox: Sandbox | undefined;\n let result: SpeculativeOutput<T> | undefined;\n let error: unknown;\n let accepted = false;\n let cleanupFailed = false;\n let retainedDirectory: string | undefined;\n const usage = taskUsage(\n { reportUsage: (value) => accounting.report(value) },\n candidate.request.observe,\n );\n try {\n sandbox = await createSandbox({\n ...options.sandbox,\n repository: options.repository,\n provider: options.provider,\n branch: { mode: \"named\", name: initial.branch, from: baseline },\n agent: candidate.agent,\n signal,\n });\n signal.throwIfAborted();\n invariant(\n sandbox.workspace.baseline === baseline,\n \"Speculative workspace does not match the pinned baseline\",\n );\n const {\n resume: _resume,\n fork: _fork,\n ...output\n } = await sandbox.dispatch({\n ...candidate.request,\n signal,\n observe: usage.observe,\n });\n result = output;\n usage.reconcile(output.usage);\n signal.throwIfAborted();\n accepted = await options.validate({\n key: candidate.key,\n result,\n sandbox,\n signal,\n });\n signal.throwIfAborted();\n } catch (cause) {\n error = cause;\n }\n if (sandbox) {\n try {\n const disposal = await sandbox.close({\n preserve: error !== undefined,\n });\n retainedDirectory = disposal.retainedDirectory;\n } catch (cause) {\n cleanupFailed = true;\n error =\n error === undefined\n ? cause\n : new AggregateError(\n [error, cause],\n \"Speculative execution and cleanup failed\",\n );\n retainedDirectory = sandbox.workspace.directory;\n }\n }\n const recovery = recoveryDetails(error);\n const recoveredDirectory =\n typeof recovery?.directory === \"string\"\n ? recovery.directory\n : undefined;\n const directory = sandbox?.workspace.directory ?? recoveredDirectory;\n retainedDirectory ??= recoveredDirectory;\n function candidateStatus(): SpeculativeCandidateResult<T>[\"status\"] {\n if (cleanupFailed) return \"failed\";\n if (signal.aborted) return \"cancelled\";\n if (error !== undefined) return \"failed\";\n if (accepted && !winner) return \"winner\";\n return \"rejected\";\n }\n const status = candidateStatus();\n const record: SpeculativeCandidateResult<T> = {\n ...initial,\n status,\n ...(directory ? { directory } : {}),\n ...(retainedDirectory ? { retainedDirectory } : {}),\n ...(result ? { result } : {}),\n ...(error !== undefined ? { error } : {}),\n };\n records[index] = record;\n if (status === \"winner\") {\n winner = record;\n stop.abort(\n new Error(`Speculative candidate ${candidate.key} selected`),\n );\n }\n }\n }\n await Promise.all(\n Array.from({ length: Math.min(concurrency, candidates.length) }, worker),\n );\n function outcome(): SpeculationResult<T>[\"status\"] {\n if (winner) return \"winner\";\n if (options.signal?.aborted) return \"aborted\";\n if (budgetError !== undefined) return \"budget-exhausted\";\n return \"no-winner\";\n }\n const status = outcome();\n const host = await speculativeHostSnapshot(options.repository).then(\n (after) => ({\n before,\n after,\n changed:\n before.fingerprint !== after.fingerprint ||\n before.branch !== after.branch,\n }),\n (error: unknown) => ({ before, changed: true, error }),\n );\n return {\n id,\n baseline,\n host,\n status,\n candidates: records,\n usage: accounting.snapshot(),\n ...(winner ? { winner } : {}),\n ...(budgetError !== undefined ? { error: budgetError } : {}),\n };\n}\n"]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { AgentAdapter } from "../domain/agent.types.ts";
|
|
2
|
+
import type { WorkflowBudget, WorkflowUsage } from "../domain/workflow/budget.types.ts";
|
|
3
|
+
import type { DispatchOptions } from "./execution.types.ts";
|
|
4
|
+
import type { Sandbox, SandboxOptions, WarmDispatchResult } from "./outpost.types.ts";
|
|
5
|
+
export interface SpeculativeCandidate<T = undefined> {
|
|
6
|
+
readonly key: string;
|
|
7
|
+
readonly agent: AgentAdapter;
|
|
8
|
+
readonly request: Omit<DispatchOptions<T>, "agent" | "signal" | "continuation">;
|
|
9
|
+
}
|
|
10
|
+
export type SpeculativeOutput<T> = Omit<WarmDispatchResult<T>, "resume" | "fork">;
|
|
11
|
+
export interface SpeculativeValidation<T> {
|
|
12
|
+
readonly key: string;
|
|
13
|
+
readonly result: SpeculativeOutput<T>;
|
|
14
|
+
readonly sandbox: Sandbox;
|
|
15
|
+
readonly signal: AbortSignal;
|
|
16
|
+
}
|
|
17
|
+
export interface SpeculationOptions<T = undefined> {
|
|
18
|
+
readonly repository: string;
|
|
19
|
+
readonly provider: NonNullable<SandboxOptions["provider"]>;
|
|
20
|
+
readonly candidates: readonly SpeculativeCandidate<T>[];
|
|
21
|
+
readonly concurrency?: number;
|
|
22
|
+
readonly budget: WorkflowBudget;
|
|
23
|
+
readonly signal?: AbortSignal;
|
|
24
|
+
readonly sandbox?: Pick<SandboxOptions, "hooks" | "bootstrap" | "logging" | "limits" | "storageQuota" | "conversationHome">;
|
|
25
|
+
readonly validate: (candidate: SpeculativeValidation<T>) => boolean | Promise<boolean>;
|
|
26
|
+
}
|
|
27
|
+
export interface SpeculativeCandidateResult<T = undefined> {
|
|
28
|
+
readonly key: string;
|
|
29
|
+
readonly branch: string;
|
|
30
|
+
readonly status: "winner" | "rejected" | "failed" | "cancelled" | "skipped";
|
|
31
|
+
readonly directory?: string;
|
|
32
|
+
readonly retainedDirectory?: string;
|
|
33
|
+
readonly result?: SpeculativeOutput<T>;
|
|
34
|
+
readonly error?: unknown;
|
|
35
|
+
}
|
|
36
|
+
export interface SpeculationResult<T = undefined> {
|
|
37
|
+
readonly id: string;
|
|
38
|
+
readonly baseline: string;
|
|
39
|
+
readonly host: {
|
|
40
|
+
readonly before: SpeculativeHostSnapshot;
|
|
41
|
+
readonly after?: SpeculativeHostSnapshot;
|
|
42
|
+
readonly changed: boolean;
|
|
43
|
+
readonly error?: unknown;
|
|
44
|
+
};
|
|
45
|
+
readonly status: "winner" | "no-winner" | "aborted" | "budget-exhausted";
|
|
46
|
+
readonly winner?: SpeculativeCandidateResult<T>;
|
|
47
|
+
readonly candidates: readonly SpeculativeCandidateResult<T>[];
|
|
48
|
+
readonly usage: WorkflowUsage;
|
|
49
|
+
readonly error?: unknown;
|
|
50
|
+
}
|
|
51
|
+
export interface SpeculativeHostSnapshot {
|
|
52
|
+
readonly head: string;
|
|
53
|
+
readonly branch: string;
|
|
54
|
+
readonly fingerprint: string;
|
|
55
|
+
readonly dirty: boolean;
|
|
56
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"speculation.types.js","sourceRoot":"","sources":["../../src/application/speculation.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AgentAdapter } from \"../domain/agent.types.ts\";\nimport type {\n WorkflowBudget,\n WorkflowUsage,\n} from \"../domain/workflow/budget.types.ts\";\nimport type { DispatchOptions } from \"./execution.types.ts\";\nimport type {\n Sandbox,\n SandboxOptions,\n WarmDispatchResult,\n} from \"./outpost.types.ts\";\n\nexport interface SpeculativeCandidate<T = undefined> {\n readonly key: string;\n readonly agent: AgentAdapter;\n readonly request: Omit<\n DispatchOptions<T>,\n \"agent\" | \"signal\" | \"continuation\"\n >;\n}\n\nexport type SpeculativeOutput<T> = Omit<\n WarmDispatchResult<T>,\n \"resume\" | \"fork\"\n>;\n\nexport interface SpeculativeValidation<T> {\n readonly key: string;\n readonly result: SpeculativeOutput<T>;\n readonly sandbox: Sandbox;\n readonly signal: AbortSignal;\n}\n\nexport interface SpeculationOptions<T = undefined> {\n readonly repository: string;\n readonly provider: NonNullable<SandboxOptions[\"provider\"]>;\n readonly candidates: readonly SpeculativeCandidate<T>[];\n readonly concurrency?: number;\n readonly budget: WorkflowBudget;\n readonly signal?: AbortSignal;\n readonly sandbox?: Pick<\n SandboxOptions,\n | \"hooks\"\n | \"bootstrap\"\n | \"logging\"\n | \"limits\"\n | \"storageQuota\"\n | \"conversationHome\"\n >;\n readonly validate: (\n candidate: SpeculativeValidation<T>,\n ) => boolean | Promise<boolean>;\n}\n\nexport interface SpeculativeCandidateResult<T = undefined> {\n readonly key: string;\n readonly branch: string;\n readonly status: \"winner\" | \"rejected\" | \"failed\" | \"cancelled\" | \"skipped\";\n readonly directory?: string;\n readonly retainedDirectory?: string;\n readonly result?: SpeculativeOutput<T>;\n readonly error?: unknown;\n}\n\nexport interface SpeculationResult<T = undefined> {\n readonly id: string;\n readonly baseline: string;\n readonly host: {\n readonly before: SpeculativeHostSnapshot;\n readonly after?: SpeculativeHostSnapshot;\n readonly changed: boolean;\n readonly error?: unknown;\n };\n readonly status: \"winner\" | \"no-winner\" | \"aborted\" | \"budget-exhausted\";\n readonly winner?: SpeculativeCandidateResult<T>;\n readonly candidates: readonly SpeculativeCandidateResult<T>[];\n readonly usage: WorkflowUsage;\n readonly error?: unknown;\n}\n\nexport interface SpeculativeHostSnapshot {\n readonly head: string;\n readonly branch: string;\n readonly fingerprint: string;\n readonly dirty: boolean;\n}\n"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { StorageReservation } from "../infrastructure/storage-reservations.types.ts";
|
|
2
|
+
import type { RecoveryStorageReservationOptions } from "./storage-reservation.types.ts";
|
|
3
|
+
export declare function reserveRecoveryStorage(options: RecoveryStorageReservationOptions): Promise<StorageReservation>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { directory } from "../infrastructure/files.js";
|
|
2
|
+
import { git } from "../infrastructure/git/command.js";
|
|
3
|
+
import { reserveStorage } from "../infrastructure/storage-reservations.js";
|
|
4
|
+
export async function reserveRecoveryStorage(options) {
|
|
5
|
+
options.signal?.throwIfAborted();
|
|
6
|
+
const requested = await directory(options.repository);
|
|
7
|
+
const root = await directory((await git(requested, ["rev-parse", "--show-toplevel"])).trim());
|
|
8
|
+
return reserveStorage(root, options);
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=storage-reservation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-reservation.js","sourceRoot":"","sources":["../../src/application/storage-reservation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,GAAG,EAAE,MAAM,kCAAkC,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAC;AAI3E,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,OAA0C;IAE1C,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC;IACjC,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,MAAM,SAAS,CAC1B,CAAC,MAAM,GAAG,CAAC,SAAS,EAAE,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAChE,CAAC;IACF,OAAO,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACvC,CAAC","sourcesContent":["import { directory } from \"../infrastructure/files.ts\";\nimport { git } from \"../infrastructure/git/command.ts\";\nimport { reserveStorage } from \"../infrastructure/storage-reservations.ts\";\nimport type { StorageReservation } from \"../infrastructure/storage-reservations.types.ts\";\nimport type { RecoveryStorageReservationOptions } from \"./storage-reservation.types.ts\";\n\nexport async function reserveRecoveryStorage(\n options: RecoveryStorageReservationOptions,\n): Promise<StorageReservation> {\n options.signal?.throwIfAborted();\n const requested = await directory(options.repository);\n const root = await directory(\n (await git(requested, [\"rev-parse\", \"--show-toplevel\"])).trim(),\n );\n return reserveStorage(root, options);\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-reservation.types.js","sourceRoot":"","sources":["../../src/application/storage-reservation.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { StorageReservationOptions } from \"../infrastructure/storage-reservations.types.ts\";\n\nexport interface RecoveryStorageReservationOptions extends StorageReservationOptions {\n readonly repository?: string;\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { AgentObservation } from "../domain/agent.types.ts";
|
|
2
2
|
import type { TaskContext } from "../domain/workflow.types.ts";
|
|
3
3
|
import type { TaskUsageObserver } from "./task-usage.types.ts";
|
|
4
|
-
export declare function taskUsage(context: TaskContext, observer: ((event: AgentObservation) => void) | undefined): TaskUsageObserver;
|
|
4
|
+
export declare function taskUsage(context: Pick<TaskContext, "reportUsage">, observer: ((event: AgentObservation) => void) | undefined): TaskUsageObserver;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-usage.js","sourceRoot":"","sources":["../../src/application/task-usage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG1C,MAAM,UAAU,SAAS,CACvB,
|
|
1
|
+
{"version":3,"file":"task-usage.js","sourceRoot":"","sources":["../../src/application/task-usage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG1C,MAAM,UAAU,SAAS,CACvB,OAAyC,EACzC,QAAyD;IAEzD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAiB,CAAC;IACxC,IAAI,KAAK,GAAU,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IACtD,SAAS,UAAU,CAAC,IAAW,EAAE,QAAe;QAC9C,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;YAC/C,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;YAClD,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;YAClD,YAAY,EAAE,IAAI,CAAC,GAAG,CACpB,CAAC,EACD,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,IAAI,CAAC,CAAC,CACxD;SACF,CAAC;IACJ,CAAC;IACD,SAAS,MAAM,CAAC,KAAY;QAC1B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC;YAAE,OAAO;QAC7D,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC/B,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO;QACL,OAAO,CAAC,KAAK;YACX,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvD,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI;oBACzC,KAAK,EAAE,CAAC;oBACR,MAAM,EAAE,CAAC;oBACT,MAAM,EAAE,CAAC;iBACV,CAAC;gBACF,MAAM,KAAK,GACT,KAAK,CAAC,IAAI,KAAK,OAAO;oBACpB,CAAC,CAAC,KAAK,CAAC,MAAM;oBACd,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;gBACzC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;gBAClD,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC;YACD,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC1B,CAAC;QACD,SAAS,CAAC,KAAK;YACb,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;QACnC,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { AgentObservation, Usage } from \"../domain/agent.types.ts\";\nimport { addUsage } from \"../domain/usage.ts\";\nimport type { TaskContext } from \"../domain/workflow.types.ts\";\nimport { notify } from \"./observation.ts\";\nimport type { TaskUsageObserver } from \"./task-usage.types.ts\";\n\nexport function taskUsage(\n context: Pick<TaskContext, \"reportUsage\">,\n observer: ((event: AgentObservation) => void) | undefined,\n): TaskUsageObserver {\n const passes = new Map<number, Usage>();\n let total: Usage = { input: 0, cached: 0, output: 0 };\n function difference(next: Usage, previous: Usage): Usage {\n return {\n input: Math.max(0, next.input - previous.input),\n cached: Math.max(0, next.cached - previous.cached),\n output: Math.max(0, next.output - previous.output),\n cacheCreated: Math.max(\n 0,\n (next.cacheCreated ?? 0) - (previous.cacheCreated ?? 0),\n ),\n };\n }\n function report(usage: Usage): void {\n if (!Object.values(usage).some((value) => value > 0)) return;\n total = addUsage(total, usage);\n context.reportUsage(usage);\n }\n return {\n observe(event) {\n if (event.kind === \"usage\" || event.kind === \"summary\") {\n const previous = passes.get(event.pass) ?? {\n input: 0,\n cached: 0,\n output: 0,\n };\n const delta =\n event.kind === \"usage\"\n ? event.tokens\n : difference(event.tokens, previous);\n passes.set(event.pass, addUsage(previous, delta));\n report(delta);\n }\n notify(observer, event);\n },\n reconcile(usage) {\n report(difference(usage, total));\n },\n };\n}\n"]}
|
|
@@ -24,7 +24,7 @@ export function isolatedTask(options) {
|
|
|
24
24
|
return task({
|
|
25
25
|
...definition,
|
|
26
26
|
async perform(context) {
|
|
27
|
-
const options = request(context);
|
|
27
|
+
const options = await request(context);
|
|
28
28
|
const usage = taskUsage(context, options.observe);
|
|
29
29
|
const result = await dispatch({
|
|
30
30
|
...options,
|