@elie-laloum/outpost 1.1.4 → 3.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 +35 -0
- package/README.md +12 -6
- 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/protocol-fixtures.constants.d.ts +2 -0
- package/dist/adapters/agents/protocol-fixtures.constants.js +68 -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/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/doctor-agent.constants.d.ts +9 -0
- package/dist/application/doctor-agent.constants.js +8 -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 +29 -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 +2 -0
- package/dist/application/outpost.types.js.map +1 -1
- 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 +27 -0
- package/dist/application/recovery-inspection.js.map +1 -0
- package/dist/application/recovery-inspection.types.d.ts +15 -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-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 +202 -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 +2 -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 +24 -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 +36 -4
- package/dist/application/remote-download.js.map +1 -1
- package/dist/application/remote-validation.js +19 -0
- 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 +6 -0
- 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.js +11 -0
- package/dist/application/sandbox.js.map +1 -1
- 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/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/image.js +1 -1
- package/dist/cli/image.js.map +1 -1
- package/dist/cli/init-command.js +4 -3
- package/dist/cli/init-command.js.map +1 -1
- package/dist/cli/main.constants.d.ts +29 -8
- package/dist/cli/main.constants.js +19 -7
- package/dist/cli/main.constants.js.map +1 -1
- package/dist/cli/project-settings.js +8 -2
- package/dist/cli/project-settings.js.map +1 -1
- package/dist/cli/recovery-command.d.ts +2 -0
- package/dist/cli/recovery-command.js +69 -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-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.d.ts +1 -1
- package/dist/cli/scaffold-files.js +26 -20
- package/dist/cli/scaffold-files.js.map +1 -1
- package/dist/cli/scaffold-validation.js +2 -5
- package/dist/cli/scaffold-validation.js.map +1 -1
- package/dist/cli/scaffold.constants.d.ts +0 -2
- package/dist/cli/scaffold.constants.js +1 -13
- package/dist/cli/scaffold.constants.js.map +1 -1
- package/dist/cli/scaffold.d.ts +1 -1
- package/dist/cli/scaffold.js +37 -29
- package/dist/cli/scaffold.js.map +1 -1
- package/dist/cli/scaffold.types.d.ts +3 -5
- package/dist/cli/scaffold.types.js.map +1 -1
- package/dist/cli/starters.d.ts +1 -2
- package/dist/cli/starters.js +42 -30
- package/dist/cli/starters.js.map +1 -1
- package/dist/domain/ports.d.ts +1 -1
- package/dist/domain/ports.js.map +1 -1
- package/dist/domain/sandbox.types.d.ts +12 -0
- package/dist/domain/sandbox.types.js.map +1 -1
- 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 +67 -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/task-runner.js +8 -1
- package/dist/domain/workflow/task-runner.js.map +1 -1
- package/dist/domain/workflow/workflow-scheduler.js +4 -2
- package/dist/domain/workflow/workflow-scheduler.js.map +1 -1
- package/dist/domain/workflow/workflow-state.js +29 -0
- 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 +10 -1
- package/dist/domain/workflow.types.js.map +1 -1
- package/dist/index.d.ts +12 -8
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/file-manifest.d.ts +6 -0
- package/dist/infrastructure/file-manifest.js +91 -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 +36 -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/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/transfer.js +12 -0
- package/dist/infrastructure/transfer.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-plan.js +3 -1
- package/dist/providers/container-plan.js.map +1 -1
- package/dist/providers/container.js +31 -1
- package/dist/providers/container.js.map +1 -1
- package/dist/providers/container.types.d.ts +2 -0
- package/dist/providers/container.types.js.map +1 -1
- package/dist/providers/daytona-command.js +7 -4
- package/dist/providers/daytona-command.js.map +1 -1
- package/dist/providers/daytona.js +13 -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 +1 -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 +151 -0
- package/dist/providers/file-batches.js.map +1 -0
- package/dist/providers/podman.d.ts +1 -0
- package/dist/providers/podman.js.map +1 -1
- package/dist/providers/vercel.js +3 -1
- package/dist/providers/vercel.js.map +1 -1
- package/package.json +12 -1
- package/dist/adapters/backlogs/backlog.constants.d.ts +0 -4
- package/dist/adapters/backlogs/backlog.constants.js +0 -5
- package/dist/adapters/backlogs/backlog.constants.js.map +0 -1
- package/dist/adapters/backlogs/beads-adapter.d.ts +0 -4
- package/dist/adapters/backlogs/beads-adapter.js +0 -31
- package/dist/adapters/backlogs/beads-adapter.js.map +0 -1
- package/dist/adapters/backlogs/cli.d.ts +0 -3
- package/dist/adapters/backlogs/cli.js +0 -20
- package/dist/adapters/backlogs/cli.js.map +0 -1
- package/dist/adapters/backlogs/github-adapter.d.ts +0 -4
- package/dist/adapters/backlogs/github-adapter.js +0 -28
- package/dist/adapters/backlogs/github-adapter.js.map +0 -1
- package/dist/adapters/backlogs/issue.d.ts +0 -2
- package/dist/adapters/backlogs/issue.js +0 -13
- package/dist/adapters/backlogs/issue.js.map +0 -1
- package/dist/adapters/backlogs/settings.types.d.ts +0 -5
- package/dist/adapters/backlogs/settings.types.js +0 -2
- package/dist/adapters/backlogs/settings.types.js.map +0 -1
- package/dist/application/campaign-integration.d.ts +0 -2
- package/dist/application/campaign-integration.js +0 -44
- package/dist/application/campaign-integration.js.map +0 -1
- package/dist/application/campaign-planner.d.ts +0 -3
- package/dist/application/campaign-planner.js +0 -35
- package/dist/application/campaign-planner.js.map +0 -1
- package/dist/application/campaign-worker.d.ts +0 -3
- package/dist/application/campaign-worker.js +0 -54
- package/dist/application/campaign-worker.js.map +0 -1
- package/dist/application/campaign.constants.d.ts +0 -7
- package/dist/application/campaign.constants.js +0 -8
- package/dist/application/campaign.constants.js.map +0 -1
- package/dist/application/campaign.d.ts +0 -3
- package/dist/application/campaign.js +0 -96
- package/dist/application/campaign.js.map +0 -1
- package/dist/application/campaign.types.d.ts +0 -43
- package/dist/application/campaign.types.js +0 -2
- package/dist/application/campaign.types.js.map +0 -1
- package/dist/domain/backlog.d.ts +0 -3
- package/dist/domain/backlog.js +0 -23
- package/dist/domain/backlog.js.map +0 -1
- package/dist/domain/backlog.types.d.ts +0 -15
- package/dist/domain/backlog.types.js +0 -2
- package/dist/domain/backlog.types.js.map +0 -1
- package/dist/providers/backlogs.d.ts +0 -3
- package/dist/providers/backlogs.js +0 -3
- package/dist/providers/backlogs.js.map +0 -1
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { OutpostError } from "../domain/errors.js";
|
|
5
|
+
import { executeProcess } from "../infrastructure/process.js";
|
|
6
|
+
import { registerCleanup } from "../infrastructure/shutdown.js";
|
|
7
|
+
import { diagnosticContainer } from "../providers/diagnostic-container.js";
|
|
8
|
+
import { agentVersions } from "../providers/versions.constants.js";
|
|
9
|
+
import { diagnoseAgentCli } from "./doctor-agent.js";
|
|
10
|
+
import { diagnosticProbe } from "./diagnostic-probe.js";
|
|
11
|
+
import { doctorDefaults } from "./doctor.constants.js";
|
|
12
|
+
export async function diagnoseImage(options, execute = executeProcess) {
|
|
13
|
+
const stop = new AbortController();
|
|
14
|
+
const pending = inspectImage(options, execute, stop.signal);
|
|
15
|
+
const unregister = registerCleanup(async () => {
|
|
16
|
+
stop.abort(new OutpostError("aborted", "Image diagnostics interrupted"));
|
|
17
|
+
await pending;
|
|
18
|
+
});
|
|
19
|
+
try {
|
|
20
|
+
return await pending;
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
unregister();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async function inspectImage({ provider, agent, image }, execute, signal) {
|
|
27
|
+
const directory = await mkdtemp(join(tmpdir(), "outpost-doctor-"));
|
|
28
|
+
const checks = [];
|
|
29
|
+
let lease;
|
|
30
|
+
let retained = false;
|
|
31
|
+
let container;
|
|
32
|
+
const tracked = (command) => {
|
|
33
|
+
if (command.arguments?.[0] === "create") {
|
|
34
|
+
const index = command.arguments.indexOf("--name");
|
|
35
|
+
container = command.arguments[index + 1];
|
|
36
|
+
}
|
|
37
|
+
return execute(command);
|
|
38
|
+
};
|
|
39
|
+
try {
|
|
40
|
+
lease = await diagnosticContainer(provider, image, doctorDefaults.deadlineMs, tracked).acquire({
|
|
41
|
+
repository: directory,
|
|
42
|
+
directory,
|
|
43
|
+
gitDirectories: [],
|
|
44
|
+
variables: {},
|
|
45
|
+
signal,
|
|
46
|
+
});
|
|
47
|
+
checks.push({
|
|
48
|
+
id: "image.runtime",
|
|
49
|
+
status: "pass",
|
|
50
|
+
message: "Temporary sandbox started with network disabled and an empty workspace.",
|
|
51
|
+
});
|
|
52
|
+
const sandbox = lease;
|
|
53
|
+
const invoke = (command) => sandbox.invoke({ ...command, signal });
|
|
54
|
+
for (const executable of ["node", "git"]) {
|
|
55
|
+
checks.push(await diagnosticProbe({
|
|
56
|
+
id: `image.${executable}`,
|
|
57
|
+
command: { executable, arguments: ["--version"] },
|
|
58
|
+
failureStatus: "fail",
|
|
59
|
+
readVersion: true,
|
|
60
|
+
remedy: `Install ${executable} in the image and rebuild it.`,
|
|
61
|
+
}, invoke));
|
|
62
|
+
}
|
|
63
|
+
checks.push(await diagnosticProbe({
|
|
64
|
+
id: "image.home",
|
|
65
|
+
command: {
|
|
66
|
+
executable: "sh",
|
|
67
|
+
arguments: ["-c", 'test -d "$HOME" && test -w "$HOME"'],
|
|
68
|
+
},
|
|
69
|
+
failureStatus: "fail",
|
|
70
|
+
remedy: "Check the image user and permissions of the private agent home.",
|
|
71
|
+
}, invoke));
|
|
72
|
+
const agentVersion = await diagnosticProbe({
|
|
73
|
+
id: "agent.sandbox",
|
|
74
|
+
command: { executable: agent, arguments: ["--version"] },
|
|
75
|
+
failureStatus: "fail",
|
|
76
|
+
readVersion: true,
|
|
77
|
+
referenceVersion: agentVersions[agent],
|
|
78
|
+
remedy: `Install ${agent} in the image and rebuild it. This check does not bootstrap agents.`,
|
|
79
|
+
}, invoke);
|
|
80
|
+
checks.push(agentVersion);
|
|
81
|
+
if (agentVersion.status === "fail")
|
|
82
|
+
checks.push({
|
|
83
|
+
id: "agent.cli",
|
|
84
|
+
status: "skipped",
|
|
85
|
+
message: "CLI help checks require a successful agent version probe.",
|
|
86
|
+
});
|
|
87
|
+
else
|
|
88
|
+
checks.push(...(await diagnoseAgentCli(agent, invoke)));
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
retained = error instanceof AggregateError;
|
|
92
|
+
checks.push({
|
|
93
|
+
id: "image.runtime",
|
|
94
|
+
status: "fail",
|
|
95
|
+
message: "Image diagnostics could not start. Check that the image exists locally, its UID matches the host, and sh, sleep, setsid, kill, tar and cp are installed. No image is downloaded.",
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
if (lease) {
|
|
100
|
+
try {
|
|
101
|
+
await lease.release();
|
|
102
|
+
checks.push({
|
|
103
|
+
id: "image.cleanup",
|
|
104
|
+
status: "pass",
|
|
105
|
+
message: "Diagnostic container removed.",
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
retained = true;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (retained)
|
|
113
|
+
checks.push({
|
|
114
|
+
id: "image.cleanup",
|
|
115
|
+
status: "fail",
|
|
116
|
+
message: `Cleanup could not be confirmed. Inspect container ${container ?? "creation state"} with ${provider}; temporary workspace retained at ${directory}.`,
|
|
117
|
+
});
|
|
118
|
+
if (!retained) {
|
|
119
|
+
try {
|
|
120
|
+
await rm(directory, { recursive: true, force: true });
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
checks.push({
|
|
124
|
+
id: "image.workspace",
|
|
125
|
+
status: "fail",
|
|
126
|
+
message: `Could not remove temporary workspace ${directory}.`,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return checks;
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=doctor-image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-image.js","sourceRoot":"","sources":["../../src/application/doctor-image.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdtemp, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { OutpostError } from \"../domain/errors.ts\";\nimport type { SandboxLease } from \"../domain/sandbox.types.ts\";\nimport { executeProcess } from \"../infrastructure/process.ts\";\nimport type { Executor } from \"../infrastructure/process.types.ts\";\nimport { registerCleanup } from \"../infrastructure/shutdown.ts\";\nimport { diagnosticContainer } from \"../providers/diagnostic-container.ts\";\nimport { agentVersions } from \"../providers/versions.constants.ts\";\nimport { diagnoseAgentCli } from \"./doctor-agent.ts\";\nimport { diagnosticProbe } from \"./diagnostic-probe.ts\";\nimport { doctorDefaults } from \"./doctor.constants.ts\";\nimport type { DiagnosticCheck, DoctorImageOptions } from \"./doctor.types.ts\";\n\nexport async function diagnoseImage(\n options: DoctorImageOptions,\n execute: Executor = executeProcess,\n): Promise<readonly DiagnosticCheck[]> {\n const stop = new AbortController();\n const pending = inspectImage(options, execute, stop.signal);\n const unregister = registerCleanup(async () => {\n stop.abort(new OutpostError(\"aborted\", \"Image diagnostics interrupted\"));\n await pending;\n });\n try {\n return await pending;\n } finally {\n unregister();\n }\n}\n\nasync function inspectImage(\n { provider, agent, image }: DoctorImageOptions,\n execute: Executor,\n signal: AbortSignal,\n): Promise<readonly DiagnosticCheck[]> {\n const directory = await mkdtemp(join(tmpdir(), \"outpost-doctor-\"));\n const checks: DiagnosticCheck[] = [];\n let lease: SandboxLease | undefined;\n let retained = false;\n let container: string | undefined;\n const tracked: Executor = (command) => {\n if (command.arguments?.[0] === \"create\") {\n const index = command.arguments.indexOf(\"--name\");\n container = command.arguments[index + 1];\n }\n return execute(command);\n };\n try {\n lease = await diagnosticContainer(\n provider,\n image,\n doctorDefaults.deadlineMs,\n tracked,\n ).acquire({\n repository: directory,\n directory,\n gitDirectories: [],\n variables: {},\n signal,\n });\n checks.push({\n id: \"image.runtime\",\n status: \"pass\",\n message:\n \"Temporary sandbox started with network disabled and an empty workspace.\",\n });\n const sandbox = lease;\n const invoke: Executor = (command) =>\n sandbox.invoke({ ...command, signal });\n for (const executable of [\"node\", \"git\"]) {\n checks.push(\n await diagnosticProbe(\n {\n id: `image.${executable}`,\n command: { executable, arguments: [\"--version\"] },\n failureStatus: \"fail\",\n readVersion: true,\n remedy: `Install ${executable} in the image and rebuild it.`,\n },\n invoke,\n ),\n );\n }\n checks.push(\n await diagnosticProbe(\n {\n id: \"image.home\",\n command: {\n executable: \"sh\",\n arguments: [\"-c\", 'test -d \"$HOME\" && test -w \"$HOME\"'],\n },\n failureStatus: \"fail\",\n remedy:\n \"Check the image user and permissions of the private agent home.\",\n },\n invoke,\n ),\n );\n const agentVersion = await diagnosticProbe(\n {\n id: \"agent.sandbox\",\n command: { executable: agent, arguments: [\"--version\"] },\n failureStatus: \"fail\",\n readVersion: true,\n referenceVersion: agentVersions[agent],\n remedy: `Install ${agent} in the image and rebuild it. This check does not bootstrap agents.`,\n },\n invoke,\n );\n checks.push(agentVersion);\n if (agentVersion.status === \"fail\")\n checks.push({\n id: \"agent.cli\",\n status: \"skipped\",\n message: \"CLI help checks require a successful agent version probe.\",\n });\n else checks.push(...(await diagnoseAgentCli(agent, invoke)));\n } catch (error) {\n retained = error instanceof AggregateError;\n checks.push({\n id: \"image.runtime\",\n status: \"fail\",\n message:\n \"Image diagnostics could not start. Check that the image exists locally, its UID matches the host, and sh, sleep, setsid, kill, tar and cp are installed. No image is downloaded.\",\n });\n } finally {\n if (lease) {\n try {\n await lease.release();\n checks.push({\n id: \"image.cleanup\",\n status: \"pass\",\n message: \"Diagnostic container removed.\",\n });\n } catch {\n retained = true;\n }\n }\n if (retained)\n checks.push({\n id: \"image.cleanup\",\n status: \"fail\",\n message: `Cleanup could not be confirmed. Inspect container ${container ?? \"creation state\"} with ${provider}; temporary workspace retained at ${directory}.`,\n });\n if (!retained) {\n try {\n await rm(directory, { recursive: true, force: true });\n } catch {\n checks.push({\n id: \"image.workspace\",\n status: \"fail\",\n message: `Could not remove temporary workspace ${directory}.`,\n });\n }\n }\n }\n return checks;\n}\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { isDeepStrictEqual } from "node:util";
|
|
2
|
+
import { claude } from "../adapters/agents/claude-adapter.js";
|
|
3
|
+
import { codex } from "../adapters/agents/codex-adapter.js";
|
|
4
|
+
import { protocolFixtures } from "../adapters/agents/protocol-fixtures.constants.js";
|
|
5
|
+
import { agentVersions } from "../providers/versions.constants.js";
|
|
6
|
+
export function diagnoseAgentProtocol(agent) {
|
|
7
|
+
const adapter = { claude, codex }[agent]();
|
|
8
|
+
const checks = protocolFixtures[agent].map((fixture) => {
|
|
9
|
+
const events = fixture.lines.flatMap((line) => adapter.events(line));
|
|
10
|
+
const passed = isDeepStrictEqual(events, fixture.expected);
|
|
11
|
+
return {
|
|
12
|
+
id: `protocol.fixture.${fixture.name}`,
|
|
13
|
+
status: passed ? "pass" : "fail",
|
|
14
|
+
message: passed
|
|
15
|
+
? "Bundled synthetic events decode to the expected structural observations. No installed CLI or model was invoked."
|
|
16
|
+
: "Bundled synthetic events do not match the expected structural observations.",
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
return {
|
|
20
|
+
scope: "bundled-protocol-fixtures",
|
|
21
|
+
agent,
|
|
22
|
+
referenceVersion: agentVersions[agent],
|
|
23
|
+
installedCli: "unverified",
|
|
24
|
+
modelCompatibility: "unverified",
|
|
25
|
+
checks,
|
|
26
|
+
hasFailures: checks.some((check) => check.status === "fail"),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=doctor-protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-protocol.js","sourceRoot":"","sources":["../../src/application/doctor-protocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,sCAAsC,CAAC;AAC9D,OAAO,EAAE,KAAK,EAAE,MAAM,qCAAqC,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mDAAmD,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAInE,MAAM,UAAU,qBAAqB,CAAC,KAAkB;IACtD,MAAM,OAAO,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;IAC3C,MAAM,MAAM,GAAsB,gBAAgB,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QACxE,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QACrE,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC3D,OAAO;YACL,EAAE,EAAE,oBAAoB,OAAO,CAAC,IAAI,EAAE;YACtC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;YAChC,OAAO,EAAE,MAAM;gBACb,CAAC,CAAC,iHAAiH;gBACnH,CAAC,CAAC,6EAA6E;SAClF,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,OAAO;QACL,KAAK,EAAE,2BAA2B;QAClC,KAAK;QACL,gBAAgB,EAAE,aAAa,CAAC,KAAK,CAAC;QACtC,YAAY,EAAE,YAAY;QAC1B,kBAAkB,EAAE,YAAY;QAChC,MAAM;QACN,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC;KAC7D,CAAC;AACJ,CAAC","sourcesContent":["import { isDeepStrictEqual } from \"node:util\";\nimport { claude } from \"../adapters/agents/claude-adapter.ts\";\nimport { codex } from \"../adapters/agents/codex-adapter.ts\";\nimport { protocolFixtures } from \"../adapters/agents/protocol-fixtures.constants.ts\";\nimport { agentVersions } from \"../providers/versions.constants.ts\";\nimport type { AgentProtocolReport } from \"./doctor-protocol.types.ts\";\nimport type { DiagnosticCheck, DoctorAgent } from \"./doctor.types.ts\";\n\nexport function diagnoseAgentProtocol(agent: DoctorAgent): AgentProtocolReport {\n const adapter = { claude, codex }[agent]();\n const checks: DiagnosticCheck[] = protocolFixtures[agent].map((fixture) => {\n const events = fixture.lines.flatMap((line) => adapter.events(line));\n const passed = isDeepStrictEqual(events, fixture.expected);\n return {\n id: `protocol.fixture.${fixture.name}`,\n status: passed ? \"pass\" : \"fail\",\n message: passed\n ? \"Bundled synthetic events decode to the expected structural observations. No installed CLI or model was invoked.\"\n : \"Bundled synthetic events do not match the expected structural observations.\",\n };\n });\n return {\n scope: \"bundled-protocol-fixtures\",\n agent,\n referenceVersion: agentVersions[agent],\n installedCli: \"unverified\",\n modelCompatibility: \"unverified\",\n checks,\n hasFailures: checks.some((check) => check.status === \"fail\"),\n };\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DiagnosticCheck, DoctorAgent } from "./doctor.types.ts";
|
|
2
|
+
export interface AgentProtocolReport {
|
|
3
|
+
readonly scope: "bundled-protocol-fixtures";
|
|
4
|
+
readonly agent: DoctorAgent;
|
|
5
|
+
readonly referenceVersion: string;
|
|
6
|
+
readonly installedCli: "unverified";
|
|
7
|
+
readonly modelCompatibility: "unverified";
|
|
8
|
+
readonly checks: readonly DiagnosticCheck[];
|
|
9
|
+
readonly hasFailures: boolean;
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-protocol.types.js","sourceRoot":"","sources":["../../src/application/doctor-protocol.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { DiagnosticCheck, DoctorAgent } from \"./doctor.types.ts\";\n\nexport interface AgentProtocolReport {\n readonly scope: \"bundled-protocol-fixtures\";\n readonly agent: DoctorAgent;\n readonly referenceVersion: string;\n readonly installedCli: \"unverified\";\n readonly modelCompatibility: \"unverified\";\n readonly checks: readonly DiagnosticCheck[];\n readonly hasFailures: boolean;\n}\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const sandboxDiagnosticDefaults: Readonly<{
|
|
2
|
+
maximumDeadlineMs: 60000;
|
|
3
|
+
command: "process.stdout.write('outpost-stdout'); process.stderr.write('outpost-stderr'); process.exitCode = 7";
|
|
4
|
+
home: "const fs = require('node:fs'); fs.accessSync(process.argv[1], fs.constants.R_OK | fs.constants.W_OK); if (!fs.statSync(process.argv[1]).isDirectory()) process.exit(1)";
|
|
5
|
+
}>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const sandboxDiagnosticDefaults = Object.freeze({
|
|
2
|
+
maximumDeadlineMs: 60_000,
|
|
3
|
+
command: "process.stdout.write('outpost-stdout'); process.stderr.write('outpost-stderr'); process.exitCode = 7",
|
|
4
|
+
home: "const fs = require('node:fs'); fs.accessSync(process.argv[1], fs.constants.R_OK | fs.constants.W_OK); if (!fs.statSync(process.argv[1]).isDirectory()) process.exit(1)",
|
|
5
|
+
});
|
|
6
|
+
//# sourceMappingURL=doctor-sandbox.constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-sandbox.constants.js","sourceRoot":"","sources":["../../src/application/doctor-sandbox.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC,MAAM,CAAC;IACrD,iBAAiB,EAAE,MAAM;IACzB,OAAO,EACL,sGAAsG;IACxG,IAAI,EAAE,wKAAwK;CAC/K,CAAC,CAAC","sourcesContent":["export const sandboxDiagnosticDefaults = Object.freeze({\n maximumDeadlineMs: 60_000,\n command:\n \"process.stdout.write('outpost-stdout'); process.stderr.write('outpost-stderr'); process.exitCode = 7\",\n home: \"const fs = require('node:fs'); fs.accessSync(process.argv[1], fs.constants.R_OK | fs.constants.W_OK); if (!fs.statSync(process.argv[1]).isDirectory()) process.exit(1)\",\n});\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SandboxLease } from "../domain/sandbox.types.ts";
|
|
2
|
+
import type { SandboxDiagnosticOptions, SandboxDiagnosticReport } from "./doctor-sandbox.types.ts";
|
|
3
|
+
import type { Sandbox } from "./outpost.types.ts";
|
|
4
|
+
export declare function diagnoseSandbox(target: Sandbox | SandboxLease, options?: SandboxDiagnosticOptions): Promise<SandboxDiagnosticReport>;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { invariant } from "../domain/errors.js";
|
|
2
|
+
import { agentVersions } from "../providers/versions.constants.js";
|
|
3
|
+
import { diagnoseAgentCli } from "./doctor-agent.js";
|
|
4
|
+
import { diagnosticProbe } from "./diagnostic-probe.js";
|
|
5
|
+
import { doctorDefaults } from "./doctor.constants.js";
|
|
6
|
+
import { diagnoseTransfers } from "./doctor-transfers.js";
|
|
7
|
+
import { sandboxDiagnosticDefaults } from "./doctor-sandbox.constants.js";
|
|
8
|
+
export async function diagnoseSandbox(target, options = {}) {
|
|
9
|
+
if ("diagnose" in target)
|
|
10
|
+
return target.diagnose(options);
|
|
11
|
+
const deadlineMs = options.deadlineMs ?? doctorDefaults.deadlineMs;
|
|
12
|
+
invariant(Number.isInteger(deadlineMs) &&
|
|
13
|
+
deadlineMs > 0 &&
|
|
14
|
+
deadlineMs <= sandboxDiagnosticDefaults.maximumDeadlineMs, "Diagnostic deadlineMs must be an integer from 1 to 60000");
|
|
15
|
+
options.signal?.throwIfAborted();
|
|
16
|
+
const invoke = (command) => {
|
|
17
|
+
options.signal?.throwIfAborted();
|
|
18
|
+
return target.invoke({
|
|
19
|
+
...command,
|
|
20
|
+
deadlineMs,
|
|
21
|
+
retain: command.retain ?? doctorDefaults.retain,
|
|
22
|
+
signal: options.signal
|
|
23
|
+
? AbortSignal.any([options.signal, AbortSignal.timeout(deadlineMs)])
|
|
24
|
+
: AbortSignal.timeout(deadlineMs),
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
const checks = [];
|
|
28
|
+
for (const executable of ["node", "git"]) {
|
|
29
|
+
checks.push(await diagnosticProbe({
|
|
30
|
+
id: `sandbox.${executable}`,
|
|
31
|
+
command: { executable, arguments: ["--version"] },
|
|
32
|
+
readVersion: true,
|
|
33
|
+
failureStatus: "fail",
|
|
34
|
+
remedy: `Install ${executable} in this sandbox.`,
|
|
35
|
+
}, invoke));
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const result = await invoke({
|
|
39
|
+
executable: "node",
|
|
40
|
+
arguments: ["-e", sandboxDiagnosticDefaults.command],
|
|
41
|
+
});
|
|
42
|
+
const passed = result.status === 7 &&
|
|
43
|
+
result.stdout === "outpost-stdout" &&
|
|
44
|
+
result.stderr === "outpost-stderr";
|
|
45
|
+
checks.push({
|
|
46
|
+
id: "sandbox.command",
|
|
47
|
+
status: passed ? "pass" : "fail",
|
|
48
|
+
message: passed
|
|
49
|
+
? "Observed separate output streams and nonzero process exit status."
|
|
50
|
+
: "Command output or exit status did not match the diagnostic sentinel.",
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
checks.push({
|
|
55
|
+
id: "sandbox.command",
|
|
56
|
+
status: "fail",
|
|
57
|
+
message: "Bounded command probe failed or was interrupted.",
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
checks.push(await diagnosticProbe({
|
|
61
|
+
id: "sandbox.home",
|
|
62
|
+
command: {
|
|
63
|
+
executable: "node",
|
|
64
|
+
arguments: ["-e", sandboxDiagnosticDefaults.home, target.home],
|
|
65
|
+
},
|
|
66
|
+
failureStatus: "fail",
|
|
67
|
+
remedy: "Check the lease home directory and its permissions.",
|
|
68
|
+
}, invoke));
|
|
69
|
+
if (options.agent) {
|
|
70
|
+
const version = await diagnosticProbe({
|
|
71
|
+
id: "agent.sandbox",
|
|
72
|
+
command: { executable: options.agent, arguments: ["--version"] },
|
|
73
|
+
readVersion: true,
|
|
74
|
+
referenceVersion: agentVersions[options.agent],
|
|
75
|
+
failureStatus: "fail",
|
|
76
|
+
remedy: "Install the agent explicitly; diagnostics never bootstrap it.",
|
|
77
|
+
}, invoke);
|
|
78
|
+
checks.push(version);
|
|
79
|
+
if (version.status !== "fail")
|
|
80
|
+
checks.push(...(await diagnoseAgentCli(options.agent, invoke)));
|
|
81
|
+
}
|
|
82
|
+
if (options.transfers === true)
|
|
83
|
+
checks.push(...(await diagnoseTransfers(target, { deadlineMs, ...(options.signal ? { signal: options.signal } : {}) }, invoke)));
|
|
84
|
+
checks.push({
|
|
85
|
+
id: "model",
|
|
86
|
+
status: "skipped",
|
|
87
|
+
message: "Authentication, model access and installed agent protocol compatibility are unverified. No model request was made.",
|
|
88
|
+
});
|
|
89
|
+
const observed = (id) => {
|
|
90
|
+
const check = checks.find((check) => check.id === id);
|
|
91
|
+
if (!check)
|
|
92
|
+
return "unverified";
|
|
93
|
+
return check.status === "pass" ? "pass" : "fail";
|
|
94
|
+
};
|
|
95
|
+
return {
|
|
96
|
+
scope: "owned-sandbox",
|
|
97
|
+
ownership: "caller",
|
|
98
|
+
...(options.provider
|
|
99
|
+
? {
|
|
100
|
+
provider: {
|
|
101
|
+
name: options.provider.name,
|
|
102
|
+
placement: options.provider.placement,
|
|
103
|
+
},
|
|
104
|
+
}
|
|
105
|
+
: {}),
|
|
106
|
+
capabilities: [
|
|
107
|
+
{
|
|
108
|
+
id: "command",
|
|
109
|
+
advertised: true,
|
|
110
|
+
observed: observed("sandbox.command"),
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
id: "transfers",
|
|
114
|
+
advertised: true,
|
|
115
|
+
observed: observed("sandbox.transfers"),
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
id: "batchTransfers",
|
|
119
|
+
advertised: target.fileTransfers !== undefined,
|
|
120
|
+
observed: "unverified",
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
id: "interactiveTerminal",
|
|
124
|
+
advertised: "unknown",
|
|
125
|
+
observed: "unverified",
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
checks,
|
|
129
|
+
modelCompatibility: "unverified",
|
|
130
|
+
hasFailures: checks.some((check) => check.status === "fail"),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=doctor-sandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-sandbox.js","sourceRoot":"","sources":["../../src/application/doctor-sandbox.ts"],"names":[],"mappings":"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","sourcesContent":["import { invariant } from \"../domain/errors.ts\";\nimport type { SandboxLease } from \"../domain/sandbox.types.ts\";\nimport type { Executor } from \"../infrastructure/process.types.ts\";\nimport { agentVersions } from \"../providers/versions.constants.ts\";\nimport { diagnoseAgentCli } from \"./doctor-agent.ts\";\nimport { diagnosticProbe } from \"./diagnostic-probe.ts\";\nimport { doctorDefaults } from \"./doctor.constants.ts\";\nimport type { DiagnosticCheck } from \"./doctor.types.ts\";\nimport { diagnoseTransfers } from \"./doctor-transfers.ts\";\nimport { sandboxDiagnosticDefaults } from \"./doctor-sandbox.constants.ts\";\nimport type {\n SandboxDiagnosticOptions,\n SandboxDiagnosticReport,\n} from \"./doctor-sandbox.types.ts\";\nimport type { Sandbox } from \"./outpost.types.ts\";\n\nexport async function diagnoseSandbox(\n target: Sandbox | SandboxLease,\n options: SandboxDiagnosticOptions = {},\n): Promise<SandboxDiagnosticReport> {\n if (\"diagnose\" in target) return target.diagnose(options);\n const deadlineMs = options.deadlineMs ?? doctorDefaults.deadlineMs;\n invariant(\n Number.isInteger(deadlineMs) &&\n deadlineMs > 0 &&\n deadlineMs <= sandboxDiagnosticDefaults.maximumDeadlineMs,\n \"Diagnostic deadlineMs must be an integer from 1 to 60000\",\n );\n options.signal?.throwIfAborted();\n const invoke: Executor = (command) => {\n options.signal?.throwIfAborted();\n return target.invoke({\n ...command,\n deadlineMs,\n retain: command.retain ?? doctorDefaults.retain,\n signal: options.signal\n ? AbortSignal.any([options.signal, AbortSignal.timeout(deadlineMs)])\n : AbortSignal.timeout(deadlineMs),\n });\n };\n const checks: DiagnosticCheck[] = [];\n for (const executable of [\"node\", \"git\"]) {\n checks.push(\n await diagnosticProbe(\n {\n id: `sandbox.${executable}`,\n command: { executable, arguments: [\"--version\"] },\n readVersion: true,\n failureStatus: \"fail\",\n remedy: `Install ${executable} in this sandbox.`,\n },\n invoke,\n ),\n );\n }\n try {\n const result = await invoke({\n executable: \"node\",\n arguments: [\"-e\", sandboxDiagnosticDefaults.command],\n });\n const passed =\n result.status === 7 &&\n result.stdout === \"outpost-stdout\" &&\n result.stderr === \"outpost-stderr\";\n checks.push({\n id: \"sandbox.command\",\n status: passed ? \"pass\" : \"fail\",\n message: passed\n ? \"Observed separate output streams and nonzero process exit status.\"\n : \"Command output or exit status did not match the diagnostic sentinel.\",\n });\n } catch {\n checks.push({\n id: \"sandbox.command\",\n status: \"fail\",\n message: \"Bounded command probe failed or was interrupted.\",\n });\n }\n checks.push(\n await diagnosticProbe(\n {\n id: \"sandbox.home\",\n command: {\n executable: \"node\",\n arguments: [\"-e\", sandboxDiagnosticDefaults.home, target.home],\n },\n failureStatus: \"fail\",\n remedy: \"Check the lease home directory and its permissions.\",\n },\n invoke,\n ),\n );\n if (options.agent) {\n const version = await diagnosticProbe(\n {\n id: \"agent.sandbox\",\n command: { executable: options.agent, arguments: [\"--version\"] },\n readVersion: true,\n referenceVersion: agentVersions[options.agent],\n failureStatus: \"fail\",\n remedy: \"Install the agent explicitly; diagnostics never bootstrap it.\",\n },\n invoke,\n );\n checks.push(version);\n if (version.status !== \"fail\")\n checks.push(...(await diagnoseAgentCli(options.agent, invoke)));\n }\n if (options.transfers === true)\n checks.push(\n ...(await diagnoseTransfers(\n target,\n { deadlineMs, ...(options.signal ? { signal: options.signal } : {}) },\n invoke,\n )),\n );\n checks.push({\n id: \"model\",\n status: \"skipped\",\n message:\n \"Authentication, model access and installed agent protocol compatibility are unverified. No model request was made.\",\n });\n const observed = (id: string) => {\n const check = checks.find((check) => check.id === id);\n if (!check) return \"unverified\" as const;\n return check.status === \"pass\" ? (\"pass\" as const) : (\"fail\" as const);\n };\n return {\n scope: \"owned-sandbox\",\n ownership: \"caller\",\n ...(options.provider\n ? {\n provider: {\n name: options.provider.name,\n placement: options.provider.placement,\n },\n }\n : {}),\n capabilities: [\n {\n id: \"command\",\n advertised: true,\n observed: observed(\"sandbox.command\"),\n },\n {\n id: \"transfers\",\n advertised: true,\n observed: observed(\"sandbox.transfers\"),\n },\n {\n id: \"batchTransfers\",\n advertised: target.fileTransfers !== undefined,\n observed: \"unverified\",\n },\n {\n id: \"interactiveTerminal\",\n advertised: \"unknown\",\n observed: \"unverified\",\n },\n ],\n checks,\n modelCompatibility: \"unverified\",\n hasFailures: checks.some((check) => check.status === \"fail\"),\n };\n}\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { SandboxProvider } from "../domain/sandbox.types.ts";
|
|
2
|
+
import type { DiagnosticCheck, DoctorAgent } from "./doctor.types.ts";
|
|
3
|
+
export interface SandboxDiagnosticOptions {
|
|
4
|
+
readonly agent?: DoctorAgent;
|
|
5
|
+
readonly deadlineMs?: number;
|
|
6
|
+
readonly signal?: AbortSignal;
|
|
7
|
+
readonly transfers?: boolean;
|
|
8
|
+
readonly provider?: Pick<SandboxProvider, "name" | "placement">;
|
|
9
|
+
}
|
|
10
|
+
export interface DiagnosticCapability {
|
|
11
|
+
readonly id: "command" | "transfers" | "batchTransfers" | "interactiveTerminal";
|
|
12
|
+
readonly advertised: boolean | "unknown";
|
|
13
|
+
readonly observed: "pass" | "fail" | "unverified";
|
|
14
|
+
}
|
|
15
|
+
export interface SandboxDiagnosticReport {
|
|
16
|
+
readonly scope: "owned-sandbox";
|
|
17
|
+
readonly ownership: "caller";
|
|
18
|
+
readonly provider?: Pick<SandboxProvider, "name" | "placement">;
|
|
19
|
+
readonly capabilities: readonly DiagnosticCapability[];
|
|
20
|
+
readonly checks: readonly DiagnosticCheck[];
|
|
21
|
+
readonly modelCompatibility: "unverified";
|
|
22
|
+
readonly hasFailures: boolean;
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-sandbox.types.js","sourceRoot":"","sources":["../../src/application/doctor-sandbox.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { SandboxProvider } from \"../domain/sandbox.types.ts\";\nimport type { DiagnosticCheck, DoctorAgent } from \"./doctor.types.ts\";\n\nexport interface SandboxDiagnosticOptions {\n readonly agent?: DoctorAgent;\n readonly deadlineMs?: number;\n readonly signal?: AbortSignal;\n readonly transfers?: boolean;\n readonly provider?: Pick<SandboxProvider, \"name\" | \"placement\">;\n}\n\nexport interface DiagnosticCapability {\n readonly id:\n \"command\" | \"transfers\" | \"batchTransfers\" | \"interactiveTerminal\";\n readonly advertised: boolean | \"unknown\";\n readonly observed: \"pass\" | \"fail\" | \"unverified\";\n}\n\nexport interface SandboxDiagnosticReport {\n readonly scope: \"owned-sandbox\";\n readonly ownership: \"caller\";\n readonly provider?: Pick<SandboxProvider, \"name\" | \"placement\">;\n readonly capabilities: readonly DiagnosticCapability[];\n readonly checks: readonly DiagnosticCheck[];\n readonly modelCompatibility: \"unverified\";\n readonly hasFailures: boolean;\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const transferDiagnosticRecipe: Readonly<{
|
|
2
|
+
base64: "AAECA/7/AG91dHBvc3QK";
|
|
3
|
+
create: "require('node:fs').mkdirSync(process.argv[1])";
|
|
4
|
+
verify: "const fs = require('node:fs'); if (fs.readFileSync(process.argv[1]).toString('base64') !== process.argv[2]) process.exit(1)";
|
|
5
|
+
cleanup: "require('node:fs').rmSync(process.argv[1], { recursive: true, force: true })";
|
|
6
|
+
}>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const transferDiagnosticRecipe = Object.freeze({
|
|
2
|
+
base64: "AAECA/7/AG91dHBvc3QK",
|
|
3
|
+
create: "require('node:fs').mkdirSync(process.argv[1])",
|
|
4
|
+
verify: "const fs = require('node:fs'); if (fs.readFileSync(process.argv[1]).toString('base64') !== process.argv[2]) process.exit(1)",
|
|
5
|
+
cleanup: "require('node:fs').rmSync(process.argv[1], { recursive: true, force: true })",
|
|
6
|
+
});
|
|
7
|
+
//# sourceMappingURL=doctor-transfers.constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-transfers.constants.js","sourceRoot":"","sources":["../../src/application/doctor-transfers.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC,MAAM,CAAC;IACpD,MAAM,EAAE,sBAAsB;IAC9B,MAAM,EAAE,+CAA+C;IACvD,MAAM,EACJ,6HAA6H;IAC/H,OAAO,EACL,8EAA8E;CACjF,CAAC,CAAC","sourcesContent":["export const transferDiagnosticRecipe = Object.freeze({\n base64: \"AAECA/7/AG91dHBvc3QK\",\n create: \"require('node:fs').mkdirSync(process.argv[1])\",\n verify:\n \"const fs = require('node:fs'); if (fs.readFileSync(process.argv[1]).toString('base64') !== process.argv[2]) process.exit(1)\",\n cleanup:\n \"require('node:fs').rmSync(process.argv[1], { recursive: true, force: true })\",\n});\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SandboxLease, TransferOptions } from "../domain/sandbox.types.ts";
|
|
2
|
+
import type { Executor } from "../infrastructure/process.types.ts";
|
|
3
|
+
import type { DiagnosticCheck } from "./doctor.types.ts";
|
|
4
|
+
export declare function diagnoseTransfers(lease: SandboxLease, options: TransferOptions, invoke: Executor): Promise<DiagnosticCheck[]>;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { doctorDefaults } from "./doctor.constants.js";
|
|
6
|
+
import { transferDiagnosticRecipe as recipe } from "./doctor-transfers.constants.js";
|
|
7
|
+
export async function diagnoseTransfers(lease, options, invoke) {
|
|
8
|
+
const checks = [];
|
|
9
|
+
const directory = await mkdtemp(join(tmpdir(), "outpost-probe-"));
|
|
10
|
+
const remote = `${lease.root.replace(/[\\/]$/, "")}/.outpost-probe-${randomUUID()}`;
|
|
11
|
+
const source = join(directory, "source");
|
|
12
|
+
let cleanupNeeded = false;
|
|
13
|
+
try {
|
|
14
|
+
cleanupNeeded = true;
|
|
15
|
+
const result = await invoke({
|
|
16
|
+
executable: "node",
|
|
17
|
+
arguments: ["-e", recipe.create, remote],
|
|
18
|
+
});
|
|
19
|
+
if (result.status !== 0) {
|
|
20
|
+
cleanupNeeded = false;
|
|
21
|
+
throw new Error("create");
|
|
22
|
+
}
|
|
23
|
+
const payload = Buffer.from(recipe.base64, "base64");
|
|
24
|
+
await writeFile(source, payload, { mode: 0o600 });
|
|
25
|
+
const bounded = () => ({
|
|
26
|
+
...options,
|
|
27
|
+
signal: options.signal
|
|
28
|
+
? AbortSignal.any([
|
|
29
|
+
options.signal,
|
|
30
|
+
AbortSignal.timeout(options.deadlineMs ?? doctorDefaults.deadlineMs),
|
|
31
|
+
])
|
|
32
|
+
: AbortSignal.timeout(options.deadlineMs ?? doctorDefaults.deadlineMs),
|
|
33
|
+
});
|
|
34
|
+
await lease.upload(source, `${remote}/payload`, bounded());
|
|
35
|
+
const verified = await invoke({
|
|
36
|
+
executable: "node",
|
|
37
|
+
arguments: ["-e", recipe.verify, `${remote}/payload`, recipe.base64],
|
|
38
|
+
});
|
|
39
|
+
if (verified.status !== 0)
|
|
40
|
+
throw new Error("verify");
|
|
41
|
+
const destination = join(directory, "download");
|
|
42
|
+
await lease.download(`${remote}/payload`, destination, bounded());
|
|
43
|
+
if (!(await readFile(destination)).equals(payload))
|
|
44
|
+
throw new Error("download");
|
|
45
|
+
checks.push({
|
|
46
|
+
id: "sandbox.transfers",
|
|
47
|
+
status: "pass",
|
|
48
|
+
message: "Binary upload verified by a sandbox process; downloaded bytes match. Symlinks, permissions, directories and batch transfers remain unverified.",
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
checks.push({
|
|
53
|
+
id: "sandbox.transfers",
|
|
54
|
+
status: "fail",
|
|
55
|
+
message: "Bounded binary transfer probe failed or was interrupted.",
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
if (cleanupNeeded) {
|
|
60
|
+
try {
|
|
61
|
+
const result = await lease.invoke({
|
|
62
|
+
executable: "node",
|
|
63
|
+
arguments: ["-e", recipe.cleanup, remote],
|
|
64
|
+
deadlineMs: options.deadlineMs ?? doctorDefaults.deadlineMs,
|
|
65
|
+
signal: AbortSignal.timeout(options.deadlineMs ?? doctorDefaults.deadlineMs),
|
|
66
|
+
retain: doctorDefaults.retain,
|
|
67
|
+
});
|
|
68
|
+
if (result.status !== 0)
|
|
69
|
+
throw new Error("cleanup");
|
|
70
|
+
checks.push({
|
|
71
|
+
id: "sandbox.transfers.cleanup",
|
|
72
|
+
status: "pass",
|
|
73
|
+
message: "Temporary sandbox probe directory removed.",
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
checks.push({
|
|
78
|
+
id: "sandbox.transfers.cleanup",
|
|
79
|
+
status: "fail",
|
|
80
|
+
message: `Temporary probe cleanup could not be confirmed; inspect ${remote}. The caller still owns the sandbox.`,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
await rm(directory, { recursive: true, force: true });
|
|
85
|
+
}
|
|
86
|
+
return checks;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=doctor-transfers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-transfers.js","sourceRoot":"","sources":["../../src/application/doctor-transfers.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { mkdtemp, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { SandboxLease, TransferOptions } from \"../domain/sandbox.types.ts\";\nimport type { Executor } from \"../infrastructure/process.types.ts\";\nimport { doctorDefaults } from \"./doctor.constants.ts\";\nimport type { DiagnosticCheck } from \"./doctor.types.ts\";\nimport { transferDiagnosticRecipe as recipe } from \"./doctor-transfers.constants.ts\";\n\nexport async function diagnoseTransfers(\n lease: SandboxLease,\n options: TransferOptions,\n invoke: Executor,\n): Promise<DiagnosticCheck[]> {\n const checks: DiagnosticCheck[] = [];\n const directory = await mkdtemp(join(tmpdir(), \"outpost-probe-\"));\n const remote = `${lease.root.replace(/[\\\\/]$/, \"\")}/.outpost-probe-${randomUUID()}`;\n const source = join(directory, \"source\");\n let cleanupNeeded = false;\n try {\n cleanupNeeded = true;\n const result = await invoke({\n executable: \"node\",\n arguments: [\"-e\", recipe.create, remote],\n });\n if (result.status !== 0) {\n cleanupNeeded = false;\n throw new Error(\"create\");\n }\n const payload = Buffer.from(recipe.base64, \"base64\");\n await writeFile(source, payload, { mode: 0o600 });\n const bounded = () => ({\n ...options,\n signal: options.signal\n ? AbortSignal.any([\n options.signal,\n AbortSignal.timeout(\n options.deadlineMs ?? doctorDefaults.deadlineMs,\n ),\n ])\n : AbortSignal.timeout(options.deadlineMs ?? doctorDefaults.deadlineMs),\n });\n await lease.upload(source, `${remote}/payload`, bounded());\n const verified = await invoke({\n executable: \"node\",\n arguments: [\"-e\", recipe.verify, `${remote}/payload`, recipe.base64],\n });\n if (verified.status !== 0) throw new Error(\"verify\");\n const destination = join(directory, \"download\");\n await lease.download(`${remote}/payload`, destination, bounded());\n if (!(await readFile(destination)).equals(payload))\n throw new Error(\"download\");\n checks.push({\n id: \"sandbox.transfers\",\n status: \"pass\",\n message:\n \"Binary upload verified by a sandbox process; downloaded bytes match. Symlinks, permissions, directories and batch transfers remain unverified.\",\n });\n } catch {\n checks.push({\n id: \"sandbox.transfers\",\n status: \"fail\",\n message: \"Bounded binary transfer probe failed or was interrupted.\",\n });\n } finally {\n if (cleanupNeeded) {\n try {\n const result = await lease.invoke({\n executable: \"node\",\n arguments: [\"-e\", recipe.cleanup, remote],\n deadlineMs: options.deadlineMs ?? doctorDefaults.deadlineMs,\n signal: AbortSignal.timeout(\n options.deadlineMs ?? doctorDefaults.deadlineMs,\n ),\n retain: doctorDefaults.retain,\n });\n if (result.status !== 0) throw new Error(\"cleanup\");\n checks.push({\n id: \"sandbox.transfers.cleanup\",\n status: \"pass\",\n message: \"Temporary sandbox probe directory removed.\",\n });\n } catch {\n checks.push({\n id: \"sandbox.transfers.cleanup\",\n status: \"fail\",\n message: `Temporary probe cleanup could not be confirmed; inspect ${remote}. The caller still owns the sandbox.`,\n });\n }\n }\n await rm(directory, { recursive: true, force: true });\n }\n return checks;\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DoctorProvider, DoctorReport } from "./doctor.types.ts";
|
|
2
|
+
export declare const doctorDefaults: Readonly<{
|
|
3
|
+
readonly provider: "docker";
|
|
4
|
+
readonly agent: "codex";
|
|
5
|
+
readonly deadlineMs: 5000;
|
|
6
|
+
readonly retain: 4096;
|
|
7
|
+
readonly minimumNodeMajor: 24;
|
|
8
|
+
}>;
|
|
9
|
+
export declare const providerDiagnostics: Readonly<Record<DoctorProvider, Pick<DoctorReport, "placement" | "interactiveTerminal">>>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const doctorDefaults = Object.freeze({
|
|
2
|
+
provider: "docker",
|
|
3
|
+
agent: "codex",
|
|
4
|
+
deadlineMs: 5_000,
|
|
5
|
+
retain: 4_096,
|
|
6
|
+
minimumNodeMajor: 24,
|
|
7
|
+
});
|
|
8
|
+
export const providerDiagnostics = {
|
|
9
|
+
docker: { placement: "mounted", interactiveTerminal: true },
|
|
10
|
+
podman: { placement: "mounted", interactiveTerminal: true },
|
|
11
|
+
local: { placement: "host", interactiveTerminal: true },
|
|
12
|
+
vercel: { placement: "remote", interactiveTerminal: false },
|
|
13
|
+
daytona: { placement: "remote", interactiveTerminal: false },
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=doctor.constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.constants.js","sourceRoot":"","sources":["../../src/application/doctor.constants.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC;IAC1C,QAAQ,EAAE,QAAQ;IAClB,KAAK,EAAE,OAAO;IACd,UAAU,EAAE,KAAK;IACjB,MAAM,EAAE,KAAK;IACb,gBAAgB,EAAE,EAAE;CACZ,CAAC,CAAC;AACZ,MAAM,CAAC,MAAM,mBAAmB,GAK5B;IACF,MAAM,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,mBAAmB,EAAE,IAAI,EAAE;IAC3D,MAAM,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,mBAAmB,EAAE,IAAI,EAAE;IAC3D,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,mBAAmB,EAAE,IAAI,EAAE;IACvD,MAAM,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,mBAAmB,EAAE,KAAK,EAAE;IAC3D,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,mBAAmB,EAAE,KAAK,EAAE;CAC7D,CAAC","sourcesContent":["import type { DoctorProvider, DoctorReport } from \"./doctor.types.ts\";\nexport const doctorDefaults = Object.freeze({\n provider: \"docker\",\n agent: \"codex\",\n deadlineMs: 5_000,\n retain: 4_096,\n minimumNodeMajor: 24,\n} as const);\nexport const providerDiagnostics: Readonly<\n Record<\n DoctorProvider,\n Pick<DoctorReport, \"placement\" | \"interactiveTerminal\">\n >\n> = {\n docker: { placement: \"mounted\", interactiveTerminal: true },\n podman: { placement: \"mounted\", interactiveTerminal: true },\n local: { placement: \"host\", interactiveTerminal: true },\n vercel: { placement: \"remote\", interactiveTerminal: false },\n daytona: { placement: \"remote\", interactiveTerminal: false },\n};\n"]}
|