@elie-laloum/outpost 2.0.0 → 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 +24 -0
- 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/main.constants.d.ts +28 -1
- package/dist/cli/main.constants.js +15 -0
- package/dist/cli/main.constants.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/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 -3
- package/dist/index.js +5 -1
- 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
|
@@ -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":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAO1E,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAA8B,EAC9B,UAAoC,EAAE;IAEtC,IAAI,UAAU,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC1D,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,cAAc,CAAC,UAAU,CAAC;IACnE,SAAS,CACP,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC;QAC1B,UAAU,GAAG,CAAC;QACd,UAAU,IAAI,yBAAyB,CAAC,iBAAiB,EAC3D,0DAA0D,CAC3D,CAAC;IACF,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC;IACjC,MAAM,MAAM,GAAa,CAAC,OAAO,EAAE,EAAE;QACnC,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC;QACjC,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,GAAG,OAAO;YACV,UAAU;YACV,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC,MAAM;YAC/C,MAAM,EAAE,OAAO,CAAC,MAAM;gBACpB,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;gBACpE,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC;SACpC,CAAC,CAAC;IACL,CAAC,CAAC;IACF,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,KAAK,MAAM,UAAU,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;QACzC,MAAM,CAAC,IAAI,CACT,MAAM,eAAe,CACnB;YACE,EAAE,EAAE,WAAW,UAAU,EAAE;YAC3B,OAAO,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,WAAW,CAAC,EAAE;YACjD,WAAW,EAAE,IAAI;YACjB,aAAa,EAAE,MAAM;YACrB,MAAM,EAAE,WAAW,UAAU,mBAAmB;SACjD,EACD,MAAM,CACP,CACF,CAAC;IACJ,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC;YAC1B,UAAU,EAAE,MAAM;YAClB,SAAS,EAAE,CAAC,IAAI,EAAE,yBAAyB,CAAC,OAAO,CAAC;SACrD,CAAC,CAAC;QACH,MAAM,MAAM,GACV,MAAM,CAAC,MAAM,KAAK,CAAC;YACnB,MAAM,CAAC,MAAM,KAAK,gBAAgB;YAClC,MAAM,CAAC,MAAM,KAAK,gBAAgB,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC;YACV,EAAE,EAAE,iBAAiB;YACrB,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;YAChC,OAAO,EAAE,MAAM;gBACb,CAAC,CAAC,mEAAmE;gBACrE,CAAC,CAAC,sEAAsE;SAC3E,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,CAAC,IAAI,CAAC;YACV,EAAE,EAAE,iBAAiB;YACrB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,kDAAkD;SAC5D,CAAC,CAAC;IACL,CAAC;IACD,MAAM,CAAC,IAAI,CACT,MAAM,eAAe,CACnB;QACE,EAAE,EAAE,cAAc;QAClB,OAAO,EAAE;YACP,UAAU,EAAE,MAAM;YAClB,SAAS,EAAE,CAAC,IAAI,EAAE,yBAAyB,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC;SAC/D;QACD,aAAa,EAAE,MAAM;QACrB,MAAM,EAAE,qDAAqD;KAC9D,EACD,MAAM,CACP,CACF,CAAC;IACF,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,OAAO,GAAG,MAAM,eAAe,CACnC;YACE,EAAE,EAAE,eAAe;YACnB,OAAO,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,WAAW,CAAC,EAAE;YAChE,WAAW,EAAE,IAAI;YACjB,gBAAgB,EAAE,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC;YAC9C,aAAa,EAAE,MAAM;YACrB,MAAM,EAAE,+DAA+D;SACxE,EACD,MAAM,CACP,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrB,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM;YAC3B,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,gBAAgB,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,OAAO,CAAC,SAAS,KAAK,IAAI;QAC5B,MAAM,CAAC,IAAI,CACT,GAAG,CAAC,MAAM,iBAAiB,CACzB,MAAM,EACN,EAAE,UAAU,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EACrE,MAAM,CACP,CAAC,CACH,CAAC;IACJ,MAAM,CAAC,IAAI,CAAC;QACV,EAAE,EAAE,OAAO;QACX,MAAM,EAAE,SAAS;QACjB,OAAO,EACL,oHAAoH;KACvH,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,CAAC,EAAU,EAAE,EAAE;QAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACtD,IAAI,CAAC,KAAK;YAAE,OAAO,YAAqB,CAAC;QACzC,OAAO,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAE,MAAgB,CAAC,CAAC,CAAE,MAAgB,CAAC;IACzE,CAAC,CAAC;IACF,OAAO;QACL,KAAK,EAAE,eAAe;QACtB,SAAS,EAAE,QAAQ;QACnB,GAAG,CAAC,OAAO,CAAC,QAAQ;YAClB,CAAC,CAAC;gBACE,QAAQ,EAAE;oBACR,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI;oBAC3B,SAAS,EAAE,OAAO,CAAC,QAAQ,CAAC,SAAS;iBACtC;aACF;YACH,CAAC,CAAC,EAAE,CAAC;QACP,YAAY,EAAE;YACZ;gBACE,EAAE,EAAE,SAAS;gBACb,UAAU,EAAE,IAAI;gBAChB,QAAQ,EAAE,QAAQ,CAAC,iBAAiB,CAAC;aACtC;YACD;gBACE,EAAE,EAAE,WAAW;gBACf,UAAU,EAAE,IAAI;gBAChB,QAAQ,EAAE,QAAQ,CAAC,mBAAmB,CAAC;aACxC;YACD;gBACE,EAAE,EAAE,gBAAgB;gBACpB,UAAU,EAAE,MAAM,CAAC,aAAa,KAAK,SAAS;gBAC9C,QAAQ,EAAE,YAAY;aACvB;YACD;gBACE,EAAE,EAAE,qBAAqB;gBACzB,UAAU,EAAE,SAAS;gBACrB,QAAQ,EAAE,YAAY;aACvB;SACF;QACD,MAAM;QACN,kBAAkB,EAAE,YAAY;QAChC,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC;KAC7D,CAAC;AACJ,CAAC","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"]}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { invariant } from "../domain/errors.js";
|
|
2
|
+
import { executeProcess } from "../infrastructure/process.js";
|
|
3
|
+
import { agentVersions } from "../providers/versions.constants.js";
|
|
4
|
+
import { diagnoseImage } from "./doctor-image.js";
|
|
5
|
+
import { diagnosticProbe } from "./diagnostic-probe.js";
|
|
6
|
+
import { doctorDefaults, providerDiagnostics } from "./doctor.constants.js";
|
|
7
|
+
export async function diagnose(options, execute = executeProcess) {
|
|
8
|
+
const { provider, agent, image } = options;
|
|
9
|
+
if (image !== undefined) {
|
|
10
|
+
invariant(provider === "docker" || provider === "podman", "--image requires docker or podman.");
|
|
11
|
+
invariant(image.length > 0 &&
|
|
12
|
+
!image.startsWith("-") &&
|
|
13
|
+
!/[\x00-\x20\x7f]/.test(image), "Invalid diagnostic image name.");
|
|
14
|
+
}
|
|
15
|
+
const capabilities = providerDiagnostics[provider];
|
|
16
|
+
const checks = [
|
|
17
|
+
{
|
|
18
|
+
id: "host.node",
|
|
19
|
+
status: Number(process.versions.node.split(".")[0]) >=
|
|
20
|
+
doctorDefaults.minimumNodeMajor
|
|
21
|
+
? "pass"
|
|
22
|
+
: "fail",
|
|
23
|
+
version: process.versions.node,
|
|
24
|
+
message: `Outpost requires Node.js ${doctorDefaults.minimumNodeMajor}+.`,
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
checks.push(await diagnosticProbe({
|
|
28
|
+
id: "host.git",
|
|
29
|
+
command: { executable: "git", arguments: ["--version"] },
|
|
30
|
+
failureStatus: "fail",
|
|
31
|
+
remedy: "Install Git and make it available on PATH.",
|
|
32
|
+
readVersion: true,
|
|
33
|
+
}, execute));
|
|
34
|
+
if (capabilities.placement === "mounted") {
|
|
35
|
+
const engine = await diagnosticProbe({
|
|
36
|
+
id: "provider.cli",
|
|
37
|
+
command: { executable: provider, arguments: ["--version"] },
|
|
38
|
+
failureStatus: "fail",
|
|
39
|
+
remedy: `Install ${provider} and make it available on PATH.`,
|
|
40
|
+
readVersion: true,
|
|
41
|
+
}, execute);
|
|
42
|
+
checks.push(engine);
|
|
43
|
+
if (engine.status === "pass")
|
|
44
|
+
checks.push(await diagnosticProbe({
|
|
45
|
+
id: "provider.connection",
|
|
46
|
+
command: {
|
|
47
|
+
executable: provider,
|
|
48
|
+
arguments: ["info"],
|
|
49
|
+
},
|
|
50
|
+
failureStatus: "fail",
|
|
51
|
+
remedy: `Check ${provider} is running and accessible to this user; on macOS, start its virtual machine.`,
|
|
52
|
+
}, execute));
|
|
53
|
+
checks.push(await diagnosticProbe({
|
|
54
|
+
id: "host.tar",
|
|
55
|
+
command: { executable: "tar", arguments: ["--version"] },
|
|
56
|
+
failureStatus: "fail",
|
|
57
|
+
remedy: "Install GNU tar or bsdtar for container transfers.",
|
|
58
|
+
}, execute));
|
|
59
|
+
}
|
|
60
|
+
if (capabilities.placement === "remote")
|
|
61
|
+
checks.push({
|
|
62
|
+
id: "provider.cloud",
|
|
63
|
+
status: "skipped",
|
|
64
|
+
message: "Cloud SDK, credentials, account access and allocation are not checked.",
|
|
65
|
+
});
|
|
66
|
+
checks.push(await diagnosticProbe({
|
|
67
|
+
id: "agent.host",
|
|
68
|
+
command: { executable: agent, arguments: ["--version"] },
|
|
69
|
+
failureStatus: "warn",
|
|
70
|
+
remedy: "Host CLI is unavailable or unverified. A sandbox may have its own CLI; dispatch can bootstrap a missing agent.",
|
|
71
|
+
readVersion: true,
|
|
72
|
+
referenceVersion: agentVersions[agent],
|
|
73
|
+
}, execute));
|
|
74
|
+
if (image !== undefined && (provider === "docker" || provider === "podman")) {
|
|
75
|
+
const connected = checks.some((check) => check.id === "provider.connection" && check.status === "pass");
|
|
76
|
+
if (connected)
|
|
77
|
+
checks.push(...(await diagnoseImage({ provider, agent, image }, execute)));
|
|
78
|
+
else
|
|
79
|
+
checks.push({
|
|
80
|
+
id: "image.runtime",
|
|
81
|
+
status: "skipped",
|
|
82
|
+
message: "Image checks require a reachable container engine.",
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
if (capabilities.placement !== "host" && image === undefined)
|
|
86
|
+
checks.push({
|
|
87
|
+
id: "agent.sandbox",
|
|
88
|
+
status: "skipped",
|
|
89
|
+
message: "Agent version inside the sandbox is not checked; the host version does not describe the sandbox.",
|
|
90
|
+
});
|
|
91
|
+
checks.push({
|
|
92
|
+
id: "execution",
|
|
93
|
+
status: "skipped",
|
|
94
|
+
message: image === undefined
|
|
95
|
+
? "Images, mounts, repository state, authentication and model access are not tested. No sandbox is allocated."
|
|
96
|
+
: "Workflow mounts, repository state, authentication and model access are not tested. Image checks use a separate temporary sandbox.",
|
|
97
|
+
});
|
|
98
|
+
return {
|
|
99
|
+
...options,
|
|
100
|
+
scope: image === undefined ? "host" : "host-and-image",
|
|
101
|
+
...capabilities,
|
|
102
|
+
checks,
|
|
103
|
+
hasFailures: checks.some((check) => check.status === "fail"),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/application/doctor.ts"],"names":[],"mappings":"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","sourcesContent":["import { invariant } from \"../domain/errors.ts\";\nimport { executeProcess } from \"../infrastructure/process.ts\";\nimport type { Executor } from \"../infrastructure/process.types.ts\";\nimport { agentVersions } from \"../providers/versions.constants.ts\";\nimport { diagnoseImage } from \"./doctor-image.ts\";\nimport { diagnosticProbe } from \"./diagnostic-probe.ts\";\nimport { doctorDefaults, providerDiagnostics } from \"./doctor.constants.ts\";\nimport type {\n DiagnosticCheck,\n DoctorOptions,\n DoctorReport,\n} from \"./doctor.types.ts\";\n\nexport async function diagnose(\n options: DoctorOptions,\n execute: Executor = executeProcess,\n): Promise<DoctorReport> {\n const { provider, agent, image } = options;\n if (image !== undefined) {\n invariant(\n provider === \"docker\" || provider === \"podman\",\n \"--image requires docker or podman.\",\n );\n invariant(\n image.length > 0 &&\n !image.startsWith(\"-\") &&\n !/[\\x00-\\x20\\x7f]/.test(image),\n \"Invalid diagnostic image name.\",\n );\n }\n const capabilities = providerDiagnostics[provider];\n const checks: DiagnosticCheck[] = [\n {\n id: \"host.node\",\n status:\n Number(process.versions.node.split(\".\")[0]) >=\n doctorDefaults.minimumNodeMajor\n ? \"pass\"\n : \"fail\",\n version: process.versions.node,\n message: `Outpost requires Node.js ${doctorDefaults.minimumNodeMajor}+.`,\n },\n ];\n checks.push(\n await diagnosticProbe(\n {\n id: \"host.git\",\n command: { executable: \"git\", arguments: [\"--version\"] },\n failureStatus: \"fail\",\n remedy: \"Install Git and make it available on PATH.\",\n readVersion: true,\n },\n execute,\n ),\n );\n if (capabilities.placement === \"mounted\") {\n const engine = await diagnosticProbe(\n {\n id: \"provider.cli\",\n command: { executable: provider, arguments: [\"--version\"] },\n failureStatus: \"fail\",\n remedy: `Install ${provider} and make it available on PATH.`,\n readVersion: true,\n },\n execute,\n );\n checks.push(engine);\n if (engine.status === \"pass\")\n checks.push(\n await diagnosticProbe(\n {\n id: \"provider.connection\",\n command: {\n executable: provider,\n arguments: [\"info\"],\n },\n failureStatus: \"fail\",\n remedy: `Check ${provider} is running and accessible to this user; on macOS, start its virtual machine.`,\n },\n execute,\n ),\n );\n checks.push(\n await diagnosticProbe(\n {\n id: \"host.tar\",\n command: { executable: \"tar\", arguments: [\"--version\"] },\n failureStatus: \"fail\",\n remedy: \"Install GNU tar or bsdtar for container transfers.\",\n },\n execute,\n ),\n );\n }\n if (capabilities.placement === \"remote\")\n checks.push({\n id: \"provider.cloud\",\n status: \"skipped\",\n message:\n \"Cloud SDK, credentials, account access and allocation are not checked.\",\n });\n checks.push(\n await diagnosticProbe(\n {\n id: \"agent.host\",\n command: { executable: agent, arguments: [\"--version\"] },\n failureStatus: \"warn\",\n remedy:\n \"Host CLI is unavailable or unverified. A sandbox may have its own CLI; dispatch can bootstrap a missing agent.\",\n readVersion: true,\n referenceVersion: agentVersions[agent],\n },\n execute,\n ),\n );\n if (image !== undefined && (provider === \"docker\" || provider === \"podman\")) {\n const connected = checks.some(\n (check) => check.id === \"provider.connection\" && check.status === \"pass\",\n );\n if (connected)\n checks.push(\n ...(await diagnoseImage({ provider, agent, image }, execute)),\n );\n else\n checks.push({\n id: \"image.runtime\",\n status: \"skipped\",\n message: \"Image checks require a reachable container engine.\",\n });\n }\n if (capabilities.placement !== \"host\" && image === undefined)\n checks.push({\n id: \"agent.sandbox\",\n status: \"skipped\",\n message:\n \"Agent version inside the sandbox is not checked; the host version does not describe the sandbox.\",\n });\n checks.push({\n id: \"execution\",\n status: \"skipped\",\n message:\n image === undefined\n ? \"Images, mounts, repository state, authentication and model access are not tested. No sandbox is allocated.\"\n : \"Workflow mounts, repository state, authentication and model access are not tested. Image checks use a separate temporary sandbox.\",\n });\n return {\n ...options,\n scope: image === undefined ? \"host\" : \"host-and-image\",\n ...capabilities,\n checks,\n hasFailures: checks.some((check) => check.status === \"fail\"),\n };\n}\n"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Command } from "../domain/command.types.ts";
|
|
2
|
+
export type DoctorProvider = "docker" | "podman" | "local" | "vercel" | "daytona";
|
|
3
|
+
export type DoctorAgent = "codex" | "claude";
|
|
4
|
+
export type DiagnosticStatus = "pass" | "warn" | "fail" | "skipped";
|
|
5
|
+
export interface DiagnosticCheck {
|
|
6
|
+
readonly id: string;
|
|
7
|
+
readonly status: DiagnosticStatus;
|
|
8
|
+
readonly message: string;
|
|
9
|
+
readonly version?: string;
|
|
10
|
+
readonly referenceVersion?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface DoctorOptions {
|
|
13
|
+
readonly image?: string;
|
|
14
|
+
readonly provider: DoctorProvider;
|
|
15
|
+
readonly agent: DoctorAgent;
|
|
16
|
+
}
|
|
17
|
+
export interface DoctorImageOptions {
|
|
18
|
+
readonly provider: "docker" | "podman";
|
|
19
|
+
readonly agent: DoctorAgent;
|
|
20
|
+
readonly image: string;
|
|
21
|
+
}
|
|
22
|
+
export interface DoctorReport {
|
|
23
|
+
readonly provider: DoctorProvider;
|
|
24
|
+
readonly agent: DoctorAgent;
|
|
25
|
+
readonly scope: "host" | "host-and-image";
|
|
26
|
+
readonly image?: string;
|
|
27
|
+
readonly placement: "mounted" | "host" | "remote";
|
|
28
|
+
readonly interactiveTerminal: boolean;
|
|
29
|
+
readonly checks: readonly DiagnosticCheck[];
|
|
30
|
+
readonly hasFailures: boolean;
|
|
31
|
+
}
|
|
32
|
+
export interface DiagnosticProbe {
|
|
33
|
+
readonly id: string;
|
|
34
|
+
readonly command: Command;
|
|
35
|
+
readonly failureStatus: "fail" | "warn";
|
|
36
|
+
readonly remedy: string;
|
|
37
|
+
readonly readVersion?: boolean;
|
|
38
|
+
readonly referenceVersion?: string;
|
|
39
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.types.js","sourceRoot":"","sources":["../../src/application/doctor.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Command } from \"../domain/command.types.ts\";\nexport type DoctorProvider =\n \"docker\" | \"podman\" | \"local\" | \"vercel\" | \"daytona\";\nexport type DoctorAgent = \"codex\" | \"claude\";\nexport type DiagnosticStatus = \"pass\" | \"warn\" | \"fail\" | \"skipped\";\nexport interface DiagnosticCheck {\n readonly id: string;\n readonly status: DiagnosticStatus;\n readonly message: string;\n readonly version?: string;\n readonly referenceVersion?: string;\n}\nexport interface DoctorOptions {\n readonly image?: string;\n readonly provider: DoctorProvider;\n readonly agent: DoctorAgent;\n}\nexport interface DoctorImageOptions {\n readonly provider: \"docker\" | \"podman\";\n readonly agent: DoctorAgent;\n readonly image: string;\n}\nexport interface DoctorReport {\n readonly provider: DoctorProvider;\n readonly agent: DoctorAgent;\n readonly scope: \"host\" | \"host-and-image\";\n readonly image?: string;\n readonly placement: \"mounted\" | \"host\" | \"remote\";\n readonly interactiveTerminal: boolean;\n readonly checks: readonly DiagnosticCheck[];\n readonly hasFailures: boolean;\n}\nexport interface DiagnosticProbe {\n readonly id: string;\n readonly command: Command;\n readonly failureStatus: \"fail\" | \"warn\";\n readonly remedy: string;\n readonly readVersion?: boolean;\n readonly referenceVersion?: string;\n}\n"]}
|