@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.
Files changed (300) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/adapters/agents/claude-diagnostics.d.ts +1 -0
  3. package/dist/adapters/agents/claude-diagnostics.js +7 -0
  4. package/dist/adapters/agents/claude-diagnostics.js.map +1 -0
  5. package/dist/adapters/agents/cli-diagnostics.constants.d.ts +12 -0
  6. package/dist/adapters/agents/cli-diagnostics.constants.js +24 -0
  7. package/dist/adapters/agents/cli-diagnostics.constants.js.map +1 -0
  8. package/dist/adapters/agents/cli-diagnostics.d.ts +4 -0
  9. package/dist/adapters/agents/cli-diagnostics.js +14 -0
  10. package/dist/adapters/agents/cli-diagnostics.js.map +1 -0
  11. package/dist/adapters/agents/cli-diagnostics.types.d.ts +13 -0
  12. package/dist/adapters/agents/cli-diagnostics.types.js +2 -0
  13. package/dist/adapters/agents/cli-diagnostics.types.js.map +1 -0
  14. package/dist/adapters/agents/codex-diagnostics.d.ts +1 -0
  15. package/dist/adapters/agents/codex-diagnostics.js +7 -0
  16. package/dist/adapters/agents/codex-diagnostics.js.map +1 -0
  17. package/dist/adapters/agents/protocol-fixtures.constants.d.ts +2 -0
  18. package/dist/adapters/agents/protocol-fixtures.constants.js +68 -0
  19. package/dist/adapters/agents/protocol-fixtures.constants.js.map +1 -0
  20. package/dist/adapters/agents/protocol-fixtures.types.d.ts +6 -0
  21. package/dist/adapters/agents/protocol-fixtures.types.js +2 -0
  22. package/dist/adapters/agents/protocol-fixtures.types.js.map +1 -0
  23. package/dist/application/diagnostic-probe.d.ts +3 -0
  24. package/dist/application/diagnostic-probe.js +55 -0
  25. package/dist/application/diagnostic-probe.js.map +1 -0
  26. package/dist/application/doctor-agent.constants.d.ts +9 -0
  27. package/dist/application/doctor-agent.constants.js +8 -0
  28. package/dist/application/doctor-agent.constants.js.map +1 -0
  29. package/dist/application/doctor-agent.d.ts +3 -0
  30. package/dist/application/doctor-agent.js +53 -0
  31. package/dist/application/doctor-agent.js.map +1 -0
  32. package/dist/application/doctor-image.d.ts +3 -0
  33. package/dist/application/doctor-image.js +133 -0
  34. package/dist/application/doctor-image.js.map +1 -0
  35. package/dist/application/doctor-protocol.d.ts +3 -0
  36. package/dist/application/doctor-protocol.js +29 -0
  37. package/dist/application/doctor-protocol.js.map +1 -0
  38. package/dist/application/doctor-protocol.types.d.ts +10 -0
  39. package/dist/application/doctor-protocol.types.js +2 -0
  40. package/dist/application/doctor-protocol.types.js.map +1 -0
  41. package/dist/application/doctor-sandbox.constants.d.ts +5 -0
  42. package/dist/application/doctor-sandbox.constants.js +6 -0
  43. package/dist/application/doctor-sandbox.constants.js.map +1 -0
  44. package/dist/application/doctor-sandbox.d.ts +4 -0
  45. package/dist/application/doctor-sandbox.js +133 -0
  46. package/dist/application/doctor-sandbox.js.map +1 -0
  47. package/dist/application/doctor-sandbox.types.d.ts +23 -0
  48. package/dist/application/doctor-sandbox.types.js +2 -0
  49. package/dist/application/doctor-sandbox.types.js.map +1 -0
  50. package/dist/application/doctor-transfers.constants.d.ts +6 -0
  51. package/dist/application/doctor-transfers.constants.js +7 -0
  52. package/dist/application/doctor-transfers.constants.js.map +1 -0
  53. package/dist/application/doctor-transfers.d.ts +4 -0
  54. package/dist/application/doctor-transfers.js +88 -0
  55. package/dist/application/doctor-transfers.js.map +1 -0
  56. package/dist/application/doctor.constants.d.ts +9 -0
  57. package/dist/application/doctor.constants.js +15 -0
  58. package/dist/application/doctor.constants.js.map +1 -0
  59. package/dist/application/doctor.d.ts +3 -0
  60. package/dist/application/doctor.js +106 -0
  61. package/dist/application/doctor.js.map +1 -0
  62. package/dist/application/doctor.types.d.ts +39 -0
  63. package/dist/application/doctor.types.js +2 -0
  64. package/dist/application/doctor.types.js.map +1 -0
  65. package/dist/application/execution.js +1 -0
  66. package/dist/application/execution.js.map +1 -1
  67. package/dist/application/outpost.types.d.ts +2 -0
  68. package/dist/application/outpost.types.js.map +1 -1
  69. package/dist/application/recovery-checksum-capture.d.ts +2 -0
  70. package/dist/application/recovery-checksum-capture.js +32 -0
  71. package/dist/application/recovery-checksum-capture.js.map +1 -0
  72. package/dist/application/recovery-checksum-paths.d.ts +2 -0
  73. package/dist/application/recovery-checksum-paths.js +11 -0
  74. package/dist/application/recovery-checksum-paths.js.map +1 -0
  75. package/dist/application/recovery-checksums.constants.d.ts +5 -0
  76. package/dist/application/recovery-checksums.constants.js +6 -0
  77. package/dist/application/recovery-checksums.constants.js.map +1 -0
  78. package/dist/application/recovery-checksums.d.ts +3 -0
  79. package/dist/application/recovery-checksums.js +94 -0
  80. package/dist/application/recovery-checksums.js.map +1 -0
  81. package/dist/application/recovery-checksums.types.d.ts +17 -0
  82. package/dist/application/recovery-checksums.types.js +2 -0
  83. package/dist/application/recovery-checksums.types.js.map +1 -0
  84. package/dist/application/recovery-inspection.d.ts +2 -0
  85. package/dist/application/recovery-inspection.js +27 -0
  86. package/dist/application/recovery-inspection.js.map +1 -0
  87. package/dist/application/recovery-inspection.types.d.ts +15 -0
  88. package/dist/application/recovery-inspection.types.js +2 -0
  89. package/dist/application/recovery-inspection.types.js.map +1 -0
  90. package/dist/application/recovery-restorability.d.ts +2 -0
  91. package/dist/application/recovery-restorability.js +137 -0
  92. package/dist/application/recovery-restorability.js.map +1 -0
  93. package/dist/application/recovery-retention-policy.d.ts +2 -0
  94. package/dist/application/recovery-retention-policy.js +21 -0
  95. package/dist/application/recovery-retention-policy.js.map +1 -0
  96. package/dist/application/recovery-retention.constants.d.ts +3 -0
  97. package/dist/application/recovery-retention.constants.js +2 -0
  98. package/dist/application/recovery-retention.constants.js.map +1 -0
  99. package/dist/application/recovery-retention.d.ts +4 -0
  100. package/dist/application/recovery-retention.js +202 -0
  101. package/dist/application/recovery-retention.js.map +1 -0
  102. package/dist/application/recovery-retention.types.d.ts +52 -0
  103. package/dist/application/recovery-retention.types.js +2 -0
  104. package/dist/application/recovery-retention.types.js.map +1 -0
  105. package/dist/application/recovery-verification.constants.d.ts +5 -0
  106. package/dist/application/recovery-verification.constants.js +10 -0
  107. package/dist/application/recovery-verification.constants.js.map +1 -0
  108. package/dist/application/recovery-verification.d.ts +2 -0
  109. package/dist/application/recovery-verification.js +107 -0
  110. package/dist/application/recovery-verification.js.map +1 -0
  111. package/dist/application/recovery-verification.types.d.ts +26 -0
  112. package/dist/application/recovery-verification.types.js +2 -0
  113. package/dist/application/recovery-verification.types.js.map +1 -0
  114. package/dist/application/remote-apply.js +24 -6
  115. package/dist/application/remote-apply.js.map +1 -1
  116. package/dist/application/remote-backup.js +6 -2
  117. package/dist/application/remote-backup.js.map +1 -1
  118. package/dist/application/remote-download.js +36 -4
  119. package/dist/application/remote-download.js.map +1 -1
  120. package/dist/application/remote-validation.js +19 -0
  121. package/dist/application/remote-validation.js.map +1 -1
  122. package/dist/application/remote-workspace.constants.d.ts +3 -0
  123. package/dist/application/remote-workspace.constants.js +2 -0
  124. package/dist/application/remote-workspace.constants.js.map +1 -0
  125. package/dist/application/remote-workspace.js +6 -0
  126. package/dist/application/remote-workspace.js.map +1 -1
  127. package/dist/application/remote-workspace.types.d.ts +3 -1
  128. package/dist/application/remote-workspace.types.js.map +1 -1
  129. package/dist/application/sandbox.js +11 -0
  130. package/dist/application/sandbox.js.map +1 -1
  131. package/dist/application/task-usage.d.ts +4 -0
  132. package/dist/application/task-usage.js +41 -0
  133. package/dist/application/task-usage.js.map +1 -0
  134. package/dist/application/task-usage.types.d.ts +5 -0
  135. package/dist/application/task-usage.types.js +2 -0
  136. package/dist/application/task-usage.types.js.map +1 -0
  137. package/dist/application/tasks.js +23 -2
  138. package/dist/application/tasks.js.map +1 -1
  139. package/dist/cli/commands.js +4 -0
  140. package/dist/cli/commands.js.map +1 -1
  141. package/dist/cli/doctor-command.d.ts +3 -0
  142. package/dist/cli/doctor-command.js +38 -0
  143. package/dist/cli/doctor-command.js.map +1 -0
  144. package/dist/cli/main.constants.d.ts +28 -1
  145. package/dist/cli/main.constants.js +15 -0
  146. package/dist/cli/main.constants.js.map +1 -1
  147. package/dist/cli/recovery-command.d.ts +2 -0
  148. package/dist/cli/recovery-command.js +69 -0
  149. package/dist/cli/recovery-command.js.map +1 -0
  150. package/dist/cli/recovery-prune-command.d.ts +2 -0
  151. package/dist/cli/recovery-prune-command.js +34 -0
  152. package/dist/cli/recovery-prune-command.js.map +1 -0
  153. package/dist/cli/recovery-verify-command.d.ts +2 -0
  154. package/dist/cli/recovery-verify-command.js +43 -0
  155. package/dist/cli/recovery-verify-command.js.map +1 -0
  156. package/dist/domain/ports.d.ts +1 -1
  157. package/dist/domain/ports.js.map +1 -1
  158. package/dist/domain/sandbox.types.d.ts +12 -0
  159. package/dist/domain/sandbox.types.js.map +1 -1
  160. package/dist/domain/workflow/budget.constants.d.ts +1 -0
  161. package/dist/domain/workflow/budget.constants.js +7 -0
  162. package/dist/domain/workflow/budget.constants.js.map +1 -0
  163. package/dist/domain/workflow/budget.d.ts +9 -0
  164. package/dist/domain/workflow/budget.js +67 -0
  165. package/dist/domain/workflow/budget.js.map +1 -0
  166. package/dist/domain/workflow/budget.types.d.ts +15 -0
  167. package/dist/domain/workflow/budget.types.js +2 -0
  168. package/dist/domain/workflow/budget.types.js.map +1 -0
  169. package/dist/domain/workflow/task-runner.js +8 -1
  170. package/dist/domain/workflow/task-runner.js.map +1 -1
  171. package/dist/domain/workflow/workflow-scheduler.js +4 -2
  172. package/dist/domain/workflow/workflow-scheduler.js.map +1 -1
  173. package/dist/domain/workflow/workflow-state.js +29 -0
  174. package/dist/domain/workflow/workflow-state.js.map +1 -1
  175. package/dist/domain/workflow.d.ts +2 -0
  176. package/dist/domain/workflow.js +1 -0
  177. package/dist/domain/workflow.js.map +1 -1
  178. package/dist/domain/workflow.types.d.ts +10 -1
  179. package/dist/domain/workflow.types.js.map +1 -1
  180. package/dist/index.d.ts +12 -3
  181. package/dist/index.js +5 -1
  182. package/dist/index.js.map +1 -1
  183. package/dist/infrastructure/file-manifest.d.ts +6 -0
  184. package/dist/infrastructure/file-manifest.js +91 -0
  185. package/dist/infrastructure/file-manifest.js.map +1 -0
  186. package/dist/infrastructure/git/lock-inspection.constants.d.ts +4 -0
  187. package/dist/infrastructure/git/lock-inspection.constants.js +5 -0
  188. package/dist/infrastructure/git/lock-inspection.constants.js.map +1 -0
  189. package/dist/infrastructure/git/lock-inspection.d.ts +3 -0
  190. package/dist/infrastructure/git/lock-inspection.js +64 -0
  191. package/dist/infrastructure/git/lock-inspection.js.map +1 -0
  192. package/dist/infrastructure/git/lock-inspection.types.d.ts +27 -0
  193. package/dist/infrastructure/git/lock-inspection.types.js +2 -0
  194. package/dist/infrastructure/git/lock-inspection.types.js.map +1 -0
  195. package/dist/infrastructure/git/lock.d.ts +1 -0
  196. package/dist/infrastructure/git/lock.js +70 -29
  197. package/dist/infrastructure/git/lock.js.map +1 -1
  198. package/dist/infrastructure/git/process-identity.d.ts +3 -0
  199. package/dist/infrastructure/git/process-identity.js +73 -0
  200. package/dist/infrastructure/git/process-identity.js.map +1 -0
  201. package/dist/infrastructure/git/process-identity.types.d.ts +10 -0
  202. package/dist/infrastructure/git/process-identity.types.js +2 -0
  203. package/dist/infrastructure/git/process-identity.types.js.map +1 -0
  204. package/dist/infrastructure/git/verification-command.d.ts +1 -0
  205. package/dist/infrastructure/git/verification-command.js +36 -0
  206. package/dist/infrastructure/git/verification-command.js.map +1 -0
  207. package/dist/infrastructure/git/workspace-lease.js +1 -0
  208. package/dist/infrastructure/git/workspace-lease.js.map +1 -1
  209. package/dist/infrastructure/git/workspace.js +5 -1
  210. package/dist/infrastructure/git/workspace.js.map +1 -1
  211. package/dist/infrastructure/git/worktree-inspection.constants.d.ts +5 -0
  212. package/dist/infrastructure/git/worktree-inspection.constants.js +16 -0
  213. package/dist/infrastructure/git/worktree-inspection.constants.js.map +1 -0
  214. package/dist/infrastructure/git/worktree-inspection.d.ts +3 -0
  215. package/dist/infrastructure/git/worktree-inspection.js +120 -0
  216. package/dist/infrastructure/git/worktree-inspection.js.map +1 -0
  217. package/dist/infrastructure/git/worktree-inspection.types.d.ts +19 -0
  218. package/dist/infrastructure/git/worktree-inspection.types.js +2 -0
  219. package/dist/infrastructure/git/worktree-inspection.types.js.map +1 -0
  220. package/dist/infrastructure/inspection-file.constants.d.ts +1 -0
  221. package/dist/infrastructure/inspection-file.constants.js +5 -0
  222. package/dist/infrastructure/inspection-file.constants.js.map +1 -0
  223. package/dist/infrastructure/inspection-file.d.ts +1 -0
  224. package/dist/infrastructure/inspection-file.js +43 -0
  225. package/dist/infrastructure/inspection-file.js.map +1 -0
  226. package/dist/infrastructure/inspection-hash.constants.d.ts +1 -0
  227. package/dist/infrastructure/inspection-hash.constants.js +2 -0
  228. package/dist/infrastructure/inspection-hash.constants.js.map +1 -0
  229. package/dist/infrastructure/inspection-hash.d.ts +2 -0
  230. package/dist/infrastructure/inspection-hash.js +62 -0
  231. package/dist/infrastructure/inspection-hash.js.map +1 -0
  232. package/dist/infrastructure/inspection-hash.types.d.ts +5 -0
  233. package/dist/infrastructure/inspection-hash.types.js +2 -0
  234. package/dist/infrastructure/inspection-hash.types.js.map +1 -0
  235. package/dist/infrastructure/journal-retention.constants.d.ts +4 -0
  236. package/dist/infrastructure/journal-retention.constants.js +5 -0
  237. package/dist/infrastructure/journal-retention.constants.js.map +1 -0
  238. package/dist/infrastructure/journal-retention.d.ts +2 -0
  239. package/dist/infrastructure/journal-retention.js +51 -0
  240. package/dist/infrastructure/journal-retention.js.map +1 -0
  241. package/dist/infrastructure/journal.js +37 -13
  242. package/dist/infrastructure/journal.js.map +1 -1
  243. package/dist/infrastructure/opentelemetry.constants.d.ts +10 -0
  244. package/dist/infrastructure/opentelemetry.constants.js +11 -0
  245. package/dist/infrastructure/opentelemetry.constants.js.map +1 -0
  246. package/dist/infrastructure/opentelemetry.d.ts +3 -0
  247. package/dist/infrastructure/opentelemetry.js +131 -0
  248. package/dist/infrastructure/opentelemetry.js.map +1 -0
  249. package/dist/infrastructure/opentelemetry.types.d.ts +21 -0
  250. package/dist/infrastructure/opentelemetry.types.js +2 -0
  251. package/dist/infrastructure/opentelemetry.types.js.map +1 -0
  252. package/dist/infrastructure/storage-inventory.constants.d.ts +6 -0
  253. package/dist/infrastructure/storage-inventory.constants.js +11 -0
  254. package/dist/infrastructure/storage-inventory.constants.js.map +1 -0
  255. package/dist/infrastructure/storage-inventory.d.ts +2 -0
  256. package/dist/infrastructure/storage-inventory.js +123 -0
  257. package/dist/infrastructure/storage-inventory.js.map +1 -0
  258. package/dist/infrastructure/storage-inventory.types.d.ts +38 -0
  259. package/dist/infrastructure/storage-inventory.types.js +2 -0
  260. package/dist/infrastructure/storage-inventory.types.js.map +1 -0
  261. package/dist/infrastructure/transfer.js +12 -0
  262. package/dist/infrastructure/transfer.js.map +1 -1
  263. package/dist/providers/cloud.constants.d.ts +1 -0
  264. package/dist/providers/cloud.constants.js +1 -0
  265. package/dist/providers/cloud.constants.js.map +1 -1
  266. package/dist/providers/container-cache.constants.d.ts +11 -0
  267. package/dist/providers/container-cache.constants.js +9 -0
  268. package/dist/providers/container-cache.constants.js.map +1 -0
  269. package/dist/providers/container-cache.d.ts +4 -0
  270. package/dist/providers/container-cache.js +48 -0
  271. package/dist/providers/container-cache.js.map +1 -0
  272. package/dist/providers/container-cache.types.d.ts +8 -0
  273. package/dist/providers/container-cache.types.js +2 -0
  274. package/dist/providers/container-cache.types.js.map +1 -0
  275. package/dist/providers/container-plan.js +3 -1
  276. package/dist/providers/container-plan.js.map +1 -1
  277. package/dist/providers/container.js +31 -1
  278. package/dist/providers/container.js.map +1 -1
  279. package/dist/providers/container.types.d.ts +2 -0
  280. package/dist/providers/container.types.js.map +1 -1
  281. package/dist/providers/daytona-command.js +7 -4
  282. package/dist/providers/daytona-command.js.map +1 -1
  283. package/dist/providers/daytona.js +13 -4
  284. package/dist/providers/daytona.js.map +1 -1
  285. package/dist/providers/diagnostic-container.d.ts +4 -0
  286. package/dist/providers/diagnostic-container.js +15 -0
  287. package/dist/providers/diagnostic-container.js.map +1 -0
  288. package/dist/providers/docker.d.ts +1 -0
  289. package/dist/providers/docker.js.map +1 -1
  290. package/dist/providers/file-batches.constants.d.ts +10 -0
  291. package/dist/providers/file-batches.constants.js +57 -0
  292. package/dist/providers/file-batches.constants.js.map +1 -0
  293. package/dist/providers/file-batches.d.ts +2 -0
  294. package/dist/providers/file-batches.js +151 -0
  295. package/dist/providers/file-batches.js.map +1 -0
  296. package/dist/providers/podman.d.ts +1 -0
  297. package/dist/providers/podman.js.map +1 -1
  298. package/dist/providers/vercel.js +3 -1
  299. package/dist/providers/vercel.js.map +1 -1
  300. package/package.json +12 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.0.0
4
+
5
+ - Canonicalize temporary recovery verification directories across platforms and reuse existing Podman cache volumes without recreation.
6
+ - Breaking: custom implementations of `Sandbox`, `TaskContext` and `WorkflowResult` must provide `diagnose`, `reportUsage` and `usage`, respectively; exhaustive workflow observers must handle the new `attempt` and `usage` events. Factory-created objects provide these members automatically.
7
+ - Treat uncertain or legacy lock ownership conservatively; simultaneous writers to the same configured journal now conflict instead of sharing the file.
8
+ - Add shared workflow attempt and observed usage budgets, including retries and agent repairs, with graceful admission draining and cooperative token-limit cancellation.
9
+ - Add structured workflow usage/lifecycle events and an optional OpenTelemetry entry point with injected tracer/meter, fixed span names, counters and duration histograms without task contents or identifiers.
10
+ - Diagnose caller-owned sandboxes through an exclusive operation, with optional binary transfer probes and cleanup; report observed capabilities separately from advertised contracts and bundled agent protocol fixture checks.
11
+ - Add credential-free cloud contract fixtures and explicitly enabled scheduled Vercel/Daytona checks with sanitized reports, independent cleanup and optional live CLI syntax probes; authenticated model turns remain outside this suite.
12
+ - Wait for Daytona command exit status after output closes, and register allocation cleanup before discovering the sandbox home.
13
+ - Add explicit recovery retention plans, revalidated cleanup and quota admission; protect recovery artifacts, uncertain logs and workspaces containing ignored files.
14
+ - Observe lock ownership using Linux host, boot, namespace and process-start identity; serialize stale-lock reclamation and refuse uncertain owners.
15
+ - Verify retained Git bundles, objects and patch applicability in an isolated copy without inherited Git filters or changes to the source repository.
16
+ - Add opt-in Docker/Podman dependency caches with explicit invalidation keys and repository, image and user scoping; add pinned agent-image build tooling and a gated publication workflow with signed provenance verification.
17
+ - Download changed untracked files from Vercel/Daytona using SHA-256 manifests and bounded gzip batches; reuse verified unchanged files while retaining complete recovery payloads and protecting ignored host files.
18
+ - Record atomic SHA-256 manifests for new remote transfer backups before host apply; add opt-in `recovery verify --checksums` with bounded streaming verification, explicit missing/mismatched results and preserved host state on capture failure.
19
+ - Add read-only `recovery verify --directory` checks for retained transfer metadata and required backup files, with bounded state parsing and explicit separation from content integrity or restoration validation.
20
+ - Add optional `recovery inspect --locks` with bounded lock metadata reads and local PID observations; report invalid or unverifiable records explicitly without claiming ownership or deleting locks.
21
+ - Add optional `recovery inspect --git` workspace reports with branch/detached HEAD, clean/dirty status, Git locks and explicit unregistered/unavailable states, without refreshing indexes or pruning registrations.
22
+ - Add read-only `outpost recovery inspect` reports for recovery files, logs, locks and managed workspaces, with metadata-only logical sizes, symlink protection and explicit partial results when traversal limits or filesystem errors prevent a complete inventory.
23
+ - Check default agent start/resume/fork CLI help inside diagnostic images, verifying command usage and declared options instead of trusting a successful help exit; keep real execution and protocol compatibility explicitly unverified.
24
+ - Extend `doctor --image` to check a local Docker/Podman image in a temporary sandbox, without image downloads or networking; report image agent versions and cleanup failures separately from host checks.
25
+ - Add `outpost doctor` with bounded host prerequisite checks, Docker/Podman connectivity, host agent version comparison, explicit unchecked capabilities and JSON reports.
26
+
3
27
  ## 2.0.0
4
28
 
5
29
  - Normalize the workflow test directory before computing relative repository paths, fixing macOS CI with symlinked temporary directories.
@@ -0,0 +1 @@
1
+ export declare function claudeDiagnostics(): readonly import("./cli-diagnostics.types.ts").AgentCliDiagnostic[];
@@ -0,0 +1,7 @@
1
+ import { claudeDiagnosticUsage } from "./cli-diagnostics.constants.js";
2
+ import { cliDiagnostics } from "./cli-diagnostics.js";
3
+ import { claudeRequest } from "./claude-request.js";
4
+ export function claudeDiagnostics() {
5
+ return cliDiagnostics((input) => claudeRequest({}, input), claudeDiagnosticUsage);
6
+ }
7
+ //# sourceMappingURL=claude-diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-diagnostics.js","sourceRoot":"","sources":["../../../src/adapters/agents/claude-diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,UAAU,iBAAiB;IAC/B,OAAO,cAAc,CACnB,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC,EACnC,qBAAqB,CACtB,CAAC;AACJ,CAAC","sourcesContent":["import { claudeDiagnosticUsage } from \"./cli-diagnostics.constants.ts\";\nimport { cliDiagnostics } from \"./cli-diagnostics.ts\";\nimport { claudeRequest } from \"./claude-request.ts\";\n\nexport function claudeDiagnostics() {\n return cliDiagnostics(\n (input) => claudeRequest({}, input),\n claudeDiagnosticUsage,\n );\n}\n"]}
@@ -0,0 +1,12 @@
1
+ import type { AgentCliScenario } from "./cli-diagnostics.types.ts";
2
+ export declare const cliDiagnosticScenarios: readonly AgentCliScenario[];
3
+ export declare const codexDiagnosticUsage: {
4
+ readonly start: "codex exec";
5
+ readonly resume: "codex exec resume";
6
+ readonly fork: "codex exec fork";
7
+ };
8
+ export declare const claudeDiagnosticUsage: {
9
+ readonly start: "claude";
10
+ readonly resume: "claude";
11
+ readonly fork: "claude";
12
+ };
@@ -0,0 +1,24 @@
1
+ export const cliDiagnosticScenarios = [
2
+ { mode: "start", input: {} },
3
+ {
4
+ mode: "resume",
5
+ input: { continuation: { id: "00000000-0000-0000-0000-000000000000" } },
6
+ },
7
+ {
8
+ mode: "fork",
9
+ input: {
10
+ continuation: { id: "00000000-0000-0000-0000-000000000000", fork: true },
11
+ },
12
+ },
13
+ ];
14
+ export const codexDiagnosticUsage = {
15
+ start: "codex exec",
16
+ resume: "codex exec resume",
17
+ fork: "codex exec fork",
18
+ };
19
+ export const claudeDiagnosticUsage = {
20
+ start: "claude",
21
+ resume: "claude",
22
+ fork: "claude",
23
+ };
24
+ //# sourceMappingURL=cli-diagnostics.constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-diagnostics.constants.js","sourceRoot":"","sources":["../../../src/adapters/agents/cli-diagnostics.constants.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,sBAAsB,GAAgC;IACjE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;IAC5B;QACE,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,EAAE,sCAAsC,EAAE,EAAE;KACxE;IACD;QACE,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE;YACL,YAAY,EAAE,EAAE,EAAE,EAAE,sCAAsC,EAAE,IAAI,EAAE,IAAI,EAAE;SACzE;KACF;CACF,CAAC;AACF,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,mBAAmB;IAC3B,IAAI,EAAE,iBAAiB;CACf,CAAC;AACX,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,QAAQ;CACN,CAAC","sourcesContent":["import type { AgentCliScenario } from \"./cli-diagnostics.types.ts\";\n\nexport const cliDiagnosticScenarios: readonly AgentCliScenario[] = [\n { mode: \"start\", input: {} },\n {\n mode: \"resume\",\n input: { continuation: { id: \"00000000-0000-0000-0000-000000000000\" } },\n },\n {\n mode: \"fork\",\n input: {\n continuation: { id: \"00000000-0000-0000-0000-000000000000\", fork: true },\n },\n },\n];\nexport const codexDiagnosticUsage = {\n start: \"codex exec\",\n resume: \"codex exec resume\",\n fork: \"codex exec fork\",\n} as const;\nexport const claudeDiagnosticUsage = {\n start: \"claude\",\n resume: \"claude\",\n fork: \"claude\",\n} as const;\n"]}
@@ -0,0 +1,4 @@
1
+ import type { AgentInput } from "../../domain/agent.types.ts";
2
+ import type { Command } from "../../domain/command.types.ts";
3
+ import type { AgentCliDiagnostic, AgentCliMode } from "./cli-diagnostics.types.ts";
4
+ export declare function cliDiagnostics(request: (input: AgentInput) => Command, usage: Readonly<Record<AgentCliMode, string>>): readonly AgentCliDiagnostic[];
@@ -0,0 +1,14 @@
1
+ import { cliDiagnosticScenarios } from "./cli-diagnostics.constants.js";
2
+ export function cliDiagnostics(request, usage) {
3
+ return cliDiagnosticScenarios.map(({ mode, input }) => {
4
+ const command = request(input);
5
+ const args = command.arguments ?? [];
6
+ return {
7
+ mode,
8
+ usage: usage[mode],
9
+ options: args.filter((argument) => argument.startsWith("--")),
10
+ command: { ...command, arguments: [...args, "--help"] },
11
+ };
12
+ });
13
+ }
14
+ //# sourceMappingURL=cli-diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-diagnostics.js","sourceRoot":"","sources":["../../../src/adapters/agents/cli-diagnostics.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAMxE,MAAM,UAAU,cAAc,CAC5B,OAAuC,EACvC,KAA6C;IAE7C,OAAO,sBAAsB,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE;QACpD,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC;QACrC,OAAO;YACL,IAAI;YACJ,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC;YAClB,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAC7D,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,CAAC,GAAG,IAAI,EAAE,QAAQ,CAAC,EAAE;SACxD,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { AgentInput } from \"../../domain/agent.types.ts\";\nimport type { Command } from \"../../domain/command.types.ts\";\nimport { cliDiagnosticScenarios } from \"./cli-diagnostics.constants.ts\";\nimport type {\n AgentCliDiagnostic,\n AgentCliMode,\n} from \"./cli-diagnostics.types.ts\";\n\nexport function cliDiagnostics(\n request: (input: AgentInput) => Command,\n usage: Readonly<Record<AgentCliMode, string>>,\n): readonly AgentCliDiagnostic[] {\n return cliDiagnosticScenarios.map(({ mode, input }) => {\n const command = request(input);\n const args = command.arguments ?? [];\n return {\n mode,\n usage: usage[mode],\n options: args.filter((argument) => argument.startsWith(\"--\")),\n command: { ...command, arguments: [...args, \"--help\"] },\n };\n });\n}\n"]}
@@ -0,0 +1,13 @@
1
+ import type { AgentInput } from "../../domain/agent.types.ts";
2
+ import type { Command } from "../../domain/command.types.ts";
3
+ export type AgentCliMode = "start" | "resume" | "fork";
4
+ export interface AgentCliScenario {
5
+ readonly mode: AgentCliMode;
6
+ readonly input: AgentInput;
7
+ }
8
+ export interface AgentCliDiagnostic {
9
+ readonly mode: AgentCliMode;
10
+ readonly command: Command;
11
+ readonly usage: string;
12
+ readonly options: readonly string[];
13
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cli-diagnostics.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-diagnostics.types.js","sourceRoot":"","sources":["../../../src/adapters/agents/cli-diagnostics.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AgentInput } from \"../../domain/agent.types.ts\";\nimport type { Command } from \"../../domain/command.types.ts\";\n\nexport type AgentCliMode = \"start\" | \"resume\" | \"fork\";\nexport interface AgentCliScenario {\n readonly mode: AgentCliMode;\n readonly input: AgentInput;\n}\nexport interface AgentCliDiagnostic {\n readonly mode: AgentCliMode;\n readonly command: Command;\n readonly usage: string;\n readonly options: readonly string[];\n}\n"]}
@@ -0,0 +1 @@
1
+ export declare function codexDiagnostics(): readonly import("./cli-diagnostics.types.ts").AgentCliDiagnostic[];
@@ -0,0 +1,7 @@
1
+ import { codexDiagnosticUsage } from "./cli-diagnostics.constants.js";
2
+ import { cliDiagnostics } from "./cli-diagnostics.js";
3
+ import { codexRequest } from "./codex-request.js";
4
+ export function codexDiagnostics() {
5
+ return cliDiagnostics((input) => codexRequest({}, input), codexDiagnosticUsage);
6
+ }
7
+ //# sourceMappingURL=codex-diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-diagnostics.js","sourceRoot":"","sources":["../../../src/adapters/agents/codex-diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,UAAU,gBAAgB;IAC9B,OAAO,cAAc,CACnB,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,EAAE,KAAK,CAAC,EAClC,oBAAoB,CACrB,CAAC;AACJ,CAAC","sourcesContent":["import { codexDiagnosticUsage } from \"./cli-diagnostics.constants.ts\";\nimport { cliDiagnostics } from \"./cli-diagnostics.ts\";\nimport { codexRequest } from \"./codex-request.ts\";\n\nexport function codexDiagnostics() {\n return cliDiagnostics(\n (input) => codexRequest({}, input),\n codexDiagnosticUsage,\n );\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import type { AgentProtocolFixture } from "./protocol-fixtures.types.ts";
2
+ export declare const protocolFixtures: Readonly<Record<"claude" | "codex", readonly AgentProtocolFixture[]>>;
@@ -0,0 +1,68 @@
1
+ export const protocolFixtures = {
2
+ codex: [
3
+ {
4
+ name: "turn",
5
+ lines: [
6
+ '{"type":"thread.started","thread_id":"fixture-conversation"}',
7
+ '{"type":"item.started","item":{"type":"command_execution","command":"fixture-command"}}',
8
+ '{"type":"item.completed","item":{"type":"agent_message","text":"fixture-result"}}',
9
+ '{"type":"turn.completed","usage":{"input_tokens":10,"cached_input_tokens":2,"output_tokens":3}}',
10
+ ],
11
+ expected: [
12
+ { kind: "conversation", id: "fixture-conversation" },
13
+ { kind: "tool", name: "command", input: "fixture-command" },
14
+ { kind: "text", text: "fixture-result" },
15
+ { kind: "usage", tokens: { input: 10, cached: 2, output: 3 } },
16
+ { kind: "finished" },
17
+ ],
18
+ },
19
+ {
20
+ name: "failure",
21
+ lines: ['{"type":"turn.failed","error":{"message":"fixture-failure"}}'],
22
+ expected: [{ kind: "failure", message: "fixture-failure" }],
23
+ },
24
+ {
25
+ name: "unknown",
26
+ lines: ['{"type":"future.event"}', "invalid-json"],
27
+ expected: [
28
+ { kind: "raw", value: { type: "future.event" } },
29
+ { kind: "raw", value: "invalid-json" },
30
+ ],
31
+ },
32
+ ],
33
+ claude: [
34
+ {
35
+ name: "turn",
36
+ lines: [
37
+ '{"type":"system","session_id":"fixture-conversation"}',
38
+ '{"type":"assistant","message":{"content":[{"type":"tool_use","name":"command","input":"fixture-command"},{"type":"text","text":"fixture-result"}]}}',
39
+ '{"type":"result","result":"fixture-result","usage":{"input_tokens":10,"cache_creation_input_tokens":1,"cache_read_input_tokens":2,"output_tokens":3}}',
40
+ ],
41
+ expected: [
42
+ { kind: "conversation", id: "fixture-conversation" },
43
+ { kind: "tool", name: "command", input: "fixture-command" },
44
+ { kind: "text", text: "fixture-result" },
45
+ { kind: "result", text: "fixture-result" },
46
+ {
47
+ kind: "usage",
48
+ tokens: { input: 10, cached: 2, cacheCreated: 1, output: 3 },
49
+ },
50
+ { kind: "finished" },
51
+ ],
52
+ },
53
+ {
54
+ name: "failure",
55
+ lines: ['{"type":"result","is_error":true,"result":"fixture-failure"}'],
56
+ expected: [{ kind: "failure", message: "fixture-failure" }],
57
+ },
58
+ {
59
+ name: "unknown",
60
+ lines: ['{"type":"future.event"}', "invalid-json"],
61
+ expected: [
62
+ { kind: "raw", value: { type: "future.event" } },
63
+ { kind: "raw", value: "invalid-json" },
64
+ ],
65
+ },
66
+ ],
67
+ };
68
+ //# sourceMappingURL=protocol-fixtures.constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol-fixtures.constants.js","sourceRoot":"","sources":["../../../src/adapters/agents/protocol-fixtures.constants.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,gBAAgB,GAEzB;IACF,KAAK,EAAE;QACL;YACE,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE;gBACL,8DAA8D;gBAC9D,yFAAyF;gBACzF,mFAAmF;gBACnF,iGAAiG;aAClG;YACD,QAAQ,EAAE;gBACR,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,sBAAsB,EAAE;gBACpD,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,iBAAiB,EAAE;gBAC3D,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE;gBACxC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE;gBAC9D,EAAE,IAAI,EAAE,UAAU,EAAE;aACrB;SACF;QACD;YACE,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,CAAC,8DAA8D,CAAC;YACvE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC;SAC5D;QACD;YACE,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,CAAC,yBAAyB,EAAE,cAAc,CAAC;YAClD,QAAQ,EAAE;gBACR,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE;gBAChD,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE;aACvC;SACF;KACF;IACD,MAAM,EAAE;QACN;YACE,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE;gBACL,uDAAuD;gBACvD,qJAAqJ;gBACrJ,uJAAuJ;aACxJ;YACD,QAAQ,EAAE;gBACR,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,sBAAsB,EAAE;gBACpD,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,iBAAiB,EAAE;gBAC3D,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE;gBACxC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,gBAAgB,EAAE;gBAC1C;oBACE,IAAI,EAAE,OAAO;oBACb,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;iBAC7D;gBACD,EAAE,IAAI,EAAE,UAAU,EAAE;aACrB;SACF;QACD;YACE,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,CAAC,8DAA8D,CAAC;YACvE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC;SAC5D;QACD;YACE,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,CAAC,yBAAyB,EAAE,cAAc,CAAC;YAClD,QAAQ,EAAE;gBACR,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE;gBAChD,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE;aACvC;SACF;KACF;CACF,CAAC","sourcesContent":["import type { AgentProtocolFixture } from \"./protocol-fixtures.types.ts\";\n\nexport const protocolFixtures: Readonly<\n Record<\"claude\" | \"codex\", readonly AgentProtocolFixture[]>\n> = {\n codex: [\n {\n name: \"turn\",\n lines: [\n '{\"type\":\"thread.started\",\"thread_id\":\"fixture-conversation\"}',\n '{\"type\":\"item.started\",\"item\":{\"type\":\"command_execution\",\"command\":\"fixture-command\"}}',\n '{\"type\":\"item.completed\",\"item\":{\"type\":\"agent_message\",\"text\":\"fixture-result\"}}',\n '{\"type\":\"turn.completed\",\"usage\":{\"input_tokens\":10,\"cached_input_tokens\":2,\"output_tokens\":3}}',\n ],\n expected: [\n { kind: \"conversation\", id: \"fixture-conversation\" },\n { kind: \"tool\", name: \"command\", input: \"fixture-command\" },\n { kind: \"text\", text: \"fixture-result\" },\n { kind: \"usage\", tokens: { input: 10, cached: 2, output: 3 } },\n { kind: \"finished\" },\n ],\n },\n {\n name: \"failure\",\n lines: ['{\"type\":\"turn.failed\",\"error\":{\"message\":\"fixture-failure\"}}'],\n expected: [{ kind: \"failure\", message: \"fixture-failure\" }],\n },\n {\n name: \"unknown\",\n lines: ['{\"type\":\"future.event\"}', \"invalid-json\"],\n expected: [\n { kind: \"raw\", value: { type: \"future.event\" } },\n { kind: \"raw\", value: \"invalid-json\" },\n ],\n },\n ],\n claude: [\n {\n name: \"turn\",\n lines: [\n '{\"type\":\"system\",\"session_id\":\"fixture-conversation\"}',\n '{\"type\":\"assistant\",\"message\":{\"content\":[{\"type\":\"tool_use\",\"name\":\"command\",\"input\":\"fixture-command\"},{\"type\":\"text\",\"text\":\"fixture-result\"}]}}',\n '{\"type\":\"result\",\"result\":\"fixture-result\",\"usage\":{\"input_tokens\":10,\"cache_creation_input_tokens\":1,\"cache_read_input_tokens\":2,\"output_tokens\":3}}',\n ],\n expected: [\n { kind: \"conversation\", id: \"fixture-conversation\" },\n { kind: \"tool\", name: \"command\", input: \"fixture-command\" },\n { kind: \"text\", text: \"fixture-result\" },\n { kind: \"result\", text: \"fixture-result\" },\n {\n kind: \"usage\",\n tokens: { input: 10, cached: 2, cacheCreated: 1, output: 3 },\n },\n { kind: \"finished\" },\n ],\n },\n {\n name: \"failure\",\n lines: ['{\"type\":\"result\",\"is_error\":true,\"result\":\"fixture-failure\"}'],\n expected: [{ kind: \"failure\", message: \"fixture-failure\" }],\n },\n {\n name: \"unknown\",\n lines: ['{\"type\":\"future.event\"}', \"invalid-json\"],\n expected: [\n { kind: \"raw\", value: { type: \"future.event\" } },\n { kind: \"raw\", value: \"invalid-json\" },\n ],\n },\n ],\n};\n"]}
@@ -0,0 +1,6 @@
1
+ import type { AgentEvent } from "../../domain/agent.types.ts";
2
+ export interface AgentProtocolFixture {
3
+ readonly name: string;
4
+ readonly lines: readonly string[];
5
+ readonly expected: readonly AgentEvent[];
6
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=protocol-fixtures.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol-fixtures.types.js","sourceRoot":"","sources":["../../../src/adapters/agents/protocol-fixtures.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AgentEvent } from \"../../domain/agent.types.ts\";\n\nexport interface AgentProtocolFixture {\n readonly name: string;\n readonly lines: readonly string[];\n readonly expected: readonly AgentEvent[];\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { Executor } from "../infrastructure/process.types.ts";
2
+ import type { DiagnosticCheck, DiagnosticProbe } from "./doctor.types.ts";
3
+ export declare function diagnosticProbe(probe: DiagnosticProbe, execute?: Executor): Promise<DiagnosticCheck>;
@@ -0,0 +1,55 @@
1
+ import { OutpostError } from "../domain/errors.js";
2
+ import { executeProcess } from "../infrastructure/process.js";
3
+ import { doctorDefaults } from "./doctor.constants.js";
4
+ export async function diagnosticProbe(probe, execute = executeProcess) {
5
+ const failure = (reason) => ({
6
+ id: probe.id,
7
+ status: probe.failureStatus,
8
+ message: `${reason}. ${probe.remedy}`,
9
+ });
10
+ try {
11
+ const result = await execute({
12
+ ...probe.command,
13
+ deadlineMs: doctorDefaults.deadlineMs,
14
+ retain: probe.command.retain ?? doctorDefaults.retain,
15
+ });
16
+ if (result.status !== 0)
17
+ return failure(`Exited with status ${result.status}`);
18
+ if (!probe.readVersion)
19
+ return {
20
+ id: probe.id,
21
+ status: "pass",
22
+ message: "Check succeeded.",
23
+ };
24
+ const version = /\bv?(\d+\.\d+\.\d+(?:-[\w.-]+)?(?:\+[\w.-]+)?)\b/.exec(result.stdout || result.stderr)?.[1];
25
+ if (!version)
26
+ return failure("Version could not be identified");
27
+ if (probe.referenceVersion)
28
+ return {
29
+ id: probe.id,
30
+ status: version === probe.referenceVersion ? "pass" : "warn",
31
+ version,
32
+ referenceVersion: probe.referenceVersion,
33
+ message: version === probe.referenceVersion
34
+ ? "Matches the version pinned by Outpost; protocol and authentication are not tested."
35
+ : "Differs from the version pinned by Outpost; compatibility is unverified.",
36
+ };
37
+ return {
38
+ id: probe.id,
39
+ status: "pass",
40
+ version,
41
+ message: "Version identified.",
42
+ };
43
+ }
44
+ catch (error) {
45
+ if (error instanceof OutpostError && error.code === "timeout")
46
+ return failure("Check timed out");
47
+ if (error &&
48
+ typeof error === "object" &&
49
+ "code" in error &&
50
+ error.code === "ENOENT")
51
+ return failure("Executable not found on PATH");
52
+ return failure("Command could not be executed");
53
+ }
54
+ }
55
+ //# sourceMappingURL=diagnostic-probe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostic-probe.js","sourceRoot":"","sources":["../../src/application/diagnostic-probe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGvD,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAsB,EACtB,UAAoB,cAAc;IAElC,MAAM,OAAO,GAAG,CAAC,MAAc,EAAmB,EAAE,CAAC,CAAC;QACpD,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,MAAM,EAAE,KAAK,CAAC,aAAa;QAC3B,OAAO,EAAE,GAAG,MAAM,KAAK,KAAK,CAAC,MAAM,EAAE;KACtC,CAAC,CAAC;IACH,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC;YAC3B,GAAG,KAAK,CAAC,OAAO;YAChB,UAAU,EAAE,cAAc,CAAC,UAAU;YACrC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC,MAAM;SACtD,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YACrB,OAAO,OAAO,CAAC,sBAAsB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACxD,IAAI,CAAC,KAAK,CAAC,WAAW;YACpB,OAAO;gBACL,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,kBAAkB;aAC5B,CAAC;QACJ,MAAM,OAAO,GAAG,kDAAkD,CAAC,IAAI,CACrE,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAC/B,EAAE,CAAC,CAAC,CAAC,CAAC;QACP,IAAI,CAAC,OAAO;YAAE,OAAO,OAAO,CAAC,iCAAiC,CAAC,CAAC;QAChE,IAAI,KAAK,CAAC,gBAAgB;YACxB,OAAO;gBACL,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,MAAM,EAAE,OAAO,KAAK,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;gBAC5D,OAAO;gBACP,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;gBACxC,OAAO,EACL,OAAO,KAAK,KAAK,CAAC,gBAAgB;oBAChC,CAAC,CAAC,oFAAoF;oBACtF,CAAC,CAAC,0EAA0E;aACjF,CAAC;QACJ,OAAO;YACL,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,MAAM,EAAE,MAAM;YACd,OAAO;YACP,OAAO,EAAE,qBAAqB;SAC/B,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;YAC3D,OAAO,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACpC,IACE,KAAK;YACL,OAAO,KAAK,KAAK,QAAQ;YACzB,MAAM,IAAI,KAAK;YACf,KAAK,CAAC,IAAI,KAAK,QAAQ;YAEvB,OAAO,OAAO,CAAC,8BAA8B,CAAC,CAAC;QACjD,OAAO,OAAO,CAAC,+BAA+B,CAAC,CAAC;IAClD,CAAC;AACH,CAAC","sourcesContent":["import { OutpostError } from \"../domain/errors.ts\";\nimport { executeProcess } from \"../infrastructure/process.ts\";\nimport type { Executor } from \"../infrastructure/process.types.ts\";\nimport { doctorDefaults } from \"./doctor.constants.ts\";\nimport type { DiagnosticCheck, DiagnosticProbe } from \"./doctor.types.ts\";\n\nexport async function diagnosticProbe(\n probe: DiagnosticProbe,\n execute: Executor = executeProcess,\n): Promise<DiagnosticCheck> {\n const failure = (reason: string): DiagnosticCheck => ({\n id: probe.id,\n status: probe.failureStatus,\n message: `${reason}. ${probe.remedy}`,\n });\n try {\n const result = await execute({\n ...probe.command,\n deadlineMs: doctorDefaults.deadlineMs,\n retain: probe.command.retain ?? doctorDefaults.retain,\n });\n if (result.status !== 0)\n return failure(`Exited with status ${result.status}`);\n if (!probe.readVersion)\n return {\n id: probe.id,\n status: \"pass\",\n message: \"Check succeeded.\",\n };\n const version = /\\bv?(\\d+\\.\\d+\\.\\d+(?:-[\\w.-]+)?(?:\\+[\\w.-]+)?)\\b/.exec(\n result.stdout || result.stderr,\n )?.[1];\n if (!version) return failure(\"Version could not be identified\");\n if (probe.referenceVersion)\n return {\n id: probe.id,\n status: version === probe.referenceVersion ? \"pass\" : \"warn\",\n version,\n referenceVersion: probe.referenceVersion,\n message:\n version === probe.referenceVersion\n ? \"Matches the version pinned by Outpost; protocol and authentication are not tested.\"\n : \"Differs from the version pinned by Outpost; compatibility is unverified.\",\n };\n return {\n id: probe.id,\n status: \"pass\",\n version,\n message: \"Version identified.\",\n };\n } catch (error) {\n if (error instanceof OutpostError && error.code === \"timeout\")\n return failure(\"Check timed out\");\n if (\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n )\n return failure(\"Executable not found on PATH\");\n return failure(\"Command could not be executed\");\n }\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import { claudeDiagnostics } from "../adapters/agents/claude-diagnostics.ts";
2
+ import { codexDiagnostics } from "../adapters/agents/codex-diagnostics.ts";
3
+ export declare const agentDiagnosticPlans: {
4
+ readonly claude: typeof claudeDiagnostics;
5
+ readonly codex: typeof codexDiagnostics;
6
+ };
7
+ export declare const agentDiagnosticDefaults: Readonly<{
8
+ retain: 65536;
9
+ }>;
@@ -0,0 +1,8 @@
1
+ import { claudeDiagnostics } from "../adapters/agents/claude-diagnostics.js";
2
+ import { codexDiagnostics } from "../adapters/agents/codex-diagnostics.js";
3
+ export const agentDiagnosticPlans = {
4
+ claude: claudeDiagnostics,
5
+ codex: codexDiagnostics,
6
+ };
7
+ export const agentDiagnosticDefaults = Object.freeze({ retain: 65_536 });
8
+ //# sourceMappingURL=doctor-agent.constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor-agent.constants.js","sourceRoot":"","sources":["../../src/application/doctor-agent.constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAE3E,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,MAAM,EAAE,iBAAiB;IACzB,KAAK,EAAE,gBAAgB;CACf,CAAC;AACX,MAAM,CAAC,MAAM,uBAAuB,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC","sourcesContent":["import { claudeDiagnostics } from \"../adapters/agents/claude-diagnostics.ts\";\nimport { codexDiagnostics } from \"../adapters/agents/codex-diagnostics.ts\";\n\nexport const agentDiagnosticPlans = {\n claude: claudeDiagnostics,\n codex: codexDiagnostics,\n} as const;\nexport const agentDiagnosticDefaults = Object.freeze({ retain: 65_536 });\n"]}
@@ -0,0 +1,3 @@
1
+ import type { Executor } from "../infrastructure/process.types.ts";
2
+ import type { DiagnosticCheck, DoctorAgent } from "./doctor.types.ts";
3
+ export declare function diagnoseAgentCli(agent: DoctorAgent, execute: Executor): Promise<readonly DiagnosticCheck[]>;
@@ -0,0 +1,53 @@
1
+ import { stripVTControlCharacters } from "node:util";
2
+ import { diagnosticProbe } from "./diagnostic-probe.js";
3
+ import { agentDiagnosticDefaults, agentDiagnosticPlans, } from "./doctor-agent.constants.js";
4
+ export async function diagnoseAgentCli(agent, execute) {
5
+ const checks = [];
6
+ for (const plan of agentDiagnosticPlans[agent]()) {
7
+ let help = "";
8
+ const check = await diagnosticProbe({
9
+ id: `agent.cli.${plan.mode}`,
10
+ command: { ...plan.command, retain: agentDiagnosticDefaults.retain },
11
+ failureStatus: "fail",
12
+ remedy: "The default Outpost invocation with --help failed. Check the agent CLI in this image and rebuild it if needed.",
13
+ }, async (command) => {
14
+ const result = await execute(command);
15
+ help = stripVTControlCharacters(`${result.stdout}\n${result.stderr}`);
16
+ return result;
17
+ });
18
+ if (check.status !== "pass") {
19
+ checks.push(check);
20
+ continue;
21
+ }
22
+ const usage = help
23
+ .split(/\r?\n/)
24
+ .some((line) => line.trim().startsWith(`Usage: ${plan.usage} [`));
25
+ if (!usage) {
26
+ checks.push({
27
+ id: check.id,
28
+ status: "warn",
29
+ message: "Command exited successfully but the expected help could not be identified; CLI support is unverified.",
30
+ });
31
+ continue;
32
+ }
33
+ const declared = new Set([
34
+ ...help.matchAll(/^\s*(?:-[A-Za-z0-9?],?\s+)?(--[A-Za-z][\w-]*)\b/gm),
35
+ ].map((match) => match[1]));
36
+ const missing = plan.options.filter((option) => !declared.has(option));
37
+ if (missing.length) {
38
+ checks.push({
39
+ id: check.id,
40
+ status: "fail",
41
+ message: `Help does not declare required options: ${missing.join(", ")}. Rebuild the image with a CLI supporting Outpost's default invocation.`,
42
+ });
43
+ continue;
44
+ }
45
+ checks.push({
46
+ id: check.id,
47
+ status: "pass",
48
+ message: "Help identifies the command and declares the options used by Outpost's default invocation. Conversation execution and event decoding are not tested.",
49
+ });
50
+ }
51
+ return checks;
52
+ }
53
+ //# sourceMappingURL=doctor-agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor-agent.js","sourceRoot":"","sources":["../../src/application/doctor-agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAErD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EACL,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,6BAA6B,CAAC;AAGrC,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAAkB,EAClB,OAAiB;IAEjB,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,oBAAoB,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QACjD,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,MAAM,KAAK,GAAG,MAAM,eAAe,CACjC;YACE,EAAE,EAAE,aAAa,IAAI,CAAC,IAAI,EAAE;YAC5B,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,uBAAuB,CAAC,MAAM,EAAE;YACpE,aAAa,EAAE,MAAM;YACrB,MAAM,EACJ,gHAAgH;SACnH,EACD,KAAK,EAAE,OAAO,EAAE,EAAE;YAChB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;YACtC,IAAI,GAAG,wBAAwB,CAAC,GAAG,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;YACtE,OAAO,MAAM,CAAC;QAChB,CAAC,CACF,CAAC;QACF,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC5B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,IAAI;aACf,KAAK,CAAC,OAAO,CAAC;aACd,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC;QACpE,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,CAAC;gBACV,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,MAAM,EAAE,MAAM;gBACd,OAAO,EACL,uGAAuG;aAC1G,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,GAAG,CACtB;YACE,GAAG,IAAI,CAAC,QAAQ,CAAC,mDAAmD,CAAC;SACtE,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAC3B,CAAC;QACF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QACvE,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,CAAC,IAAI,CAAC;gBACV,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,2CAA2C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,yEAAyE;aAChJ,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,MAAM,CAAC,IAAI,CAAC;YACV,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,MAAM,EAAE,MAAM;YACd,OAAO,EACL,sJAAsJ;SACzJ,CAAC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import { stripVTControlCharacters } from \"node:util\";\nimport type { Executor } from \"../infrastructure/process.types.ts\";\nimport { diagnosticProbe } from \"./diagnostic-probe.ts\";\nimport {\n agentDiagnosticDefaults,\n agentDiagnosticPlans,\n} from \"./doctor-agent.constants.ts\";\nimport type { DiagnosticCheck, DoctorAgent } from \"./doctor.types.ts\";\n\nexport async function diagnoseAgentCli(\n agent: DoctorAgent,\n execute: Executor,\n): Promise<readonly DiagnosticCheck[]> {\n const checks: DiagnosticCheck[] = [];\n for (const plan of agentDiagnosticPlans[agent]()) {\n let help = \"\";\n const check = await diagnosticProbe(\n {\n id: `agent.cli.${plan.mode}`,\n command: { ...plan.command, retain: agentDiagnosticDefaults.retain },\n failureStatus: \"fail\",\n remedy:\n \"The default Outpost invocation with --help failed. Check the agent CLI in this image and rebuild it if needed.\",\n },\n async (command) => {\n const result = await execute(command);\n help = stripVTControlCharacters(`${result.stdout}\\n${result.stderr}`);\n return result;\n },\n );\n if (check.status !== \"pass\") {\n checks.push(check);\n continue;\n }\n const usage = help\n .split(/\\r?\\n/)\n .some((line) => line.trim().startsWith(`Usage: ${plan.usage} [`));\n if (!usage) {\n checks.push({\n id: check.id,\n status: \"warn\",\n message:\n \"Command exited successfully but the expected help could not be identified; CLI support is unverified.\",\n });\n continue;\n }\n const declared = new Set(\n [\n ...help.matchAll(/^\\s*(?:-[A-Za-z0-9?],?\\s+)?(--[A-Za-z][\\w-]*)\\b/gm),\n ].map((match) => match[1]),\n );\n const missing = plan.options.filter((option) => !declared.has(option));\n if (missing.length) {\n checks.push({\n id: check.id,\n status: \"fail\",\n message: `Help does not declare required options: ${missing.join(\", \")}. Rebuild the image with a CLI supporting Outpost's default invocation.`,\n });\n continue;\n }\n checks.push({\n id: check.id,\n status: \"pass\",\n message:\n \"Help identifies the command and declares the options used by Outpost's default invocation. Conversation execution and event decoding are not tested.\",\n });\n }\n return checks;\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { Executor } from "../infrastructure/process.types.ts";
2
+ import type { DiagnosticCheck, DoctorImageOptions } from "./doctor.types.ts";
3
+ export declare function diagnoseImage(options: DoctorImageOptions, execute?: Executor): Promise<readonly DiagnosticCheck[]>;
@@ -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":"AAAA,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9D,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3E,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;AAGvD,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAA2B,EAC3B,UAAoB,cAAc;IAElC,MAAM,IAAI,GAAG,IAAI,eAAe,EAAE,CAAC;IACnC,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,eAAe,CAAC,KAAK,IAAI,EAAE;QAC5C,IAAI,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,SAAS,EAAE,+BAA+B,CAAC,CAAC,CAAC;QACzE,MAAM,OAAO,CAAC;IAChB,CAAC,CAAC,CAAC;IACH,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC;IACvB,CAAC;YAAS,CAAC;QACT,UAAU,EAAE,CAAC;IACf,CAAC;AACH,CAAC;AAED,KAAK,UAAU,YAAY,CACzB,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAsB,EAC9C,OAAiB,EACjB,MAAmB;IAEnB,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;IACnE,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,IAAI,KAA+B,CAAC;IACpC,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,SAA6B,CAAC;IAClC,MAAM,OAAO,GAAa,CAAC,OAAO,EAAE,EAAE;QACpC,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;YACxC,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAClD,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC,CAAC;IACF,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,mBAAmB,CAC/B,QAAQ,EACR,KAAK,EACL,cAAc,CAAC,UAAU,EACzB,OAAO,CACR,CAAC,OAAO,CAAC;YACR,UAAU,EAAE,SAAS;YACrB,SAAS;YACT,cAAc,EAAE,EAAE;YAClB,SAAS,EAAE,EAAE;YACb,MAAM;SACP,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC;YACV,EAAE,EAAE,eAAe;YACnB,MAAM,EAAE,MAAM;YACd,OAAO,EACL,yEAAyE;SAC5E,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,KAAK,CAAC;QACtB,MAAM,MAAM,GAAa,CAAC,OAAO,EAAE,EAAE,CACnC,OAAO,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACzC,KAAK,MAAM,UAAU,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;YACzC,MAAM,CAAC,IAAI,CACT,MAAM,eAAe,CACnB;gBACE,EAAE,EAAE,SAAS,UAAU,EAAE;gBACzB,OAAO,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,WAAW,CAAC,EAAE;gBACjD,aAAa,EAAE,MAAM;gBACrB,WAAW,EAAE,IAAI;gBACjB,MAAM,EAAE,WAAW,UAAU,+BAA+B;aAC7D,EACD,MAAM,CACP,CACF,CAAC;QACJ,CAAC;QACD,MAAM,CAAC,IAAI,CACT,MAAM,eAAe,CACnB;YACE,EAAE,EAAE,YAAY;YAChB,OAAO,EAAE;gBACP,UAAU,EAAE,IAAI;gBAChB,SAAS,EAAE,CAAC,IAAI,EAAE,oCAAoC,CAAC;aACxD;YACD,aAAa,EAAE,MAAM;YACrB,MAAM,EACJ,iEAAiE;SACpE,EACD,MAAM,CACP,CACF,CAAC;QACF,MAAM,YAAY,GAAG,MAAM,eAAe,CACxC;YACE,EAAE,EAAE,eAAe;YACnB,OAAO,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,WAAW,CAAC,EAAE;YACxD,aAAa,EAAE,MAAM;YACrB,WAAW,EAAE,IAAI;YACjB,gBAAgB,EAAE,aAAa,CAAC,KAAK,CAAC;YACtC,MAAM,EAAE,WAAW,KAAK,qEAAqE;SAC9F,EACD,MAAM,CACP,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC1B,IAAI,YAAY,CAAC,MAAM,KAAK,MAAM;YAChC,MAAM,CAAC,IAAI,CAAC;gBACV,EAAE,EAAE,WAAW;gBACf,MAAM,EAAE,SAAS;gBACjB,OAAO,EAAE,2DAA2D;aACrE,CAAC,CAAC;;YACA,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IAC/D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,QAAQ,GAAG,KAAK,YAAY,cAAc,CAAC;QAC3C,MAAM,CAAC,IAAI,CAAC;YACV,EAAE,EAAE,eAAe;YACnB,MAAM,EAAE,MAAM;YACd,OAAO,EACL,kLAAkL;SACrL,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC;gBACH,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;gBACtB,MAAM,CAAC,IAAI,CAAC;oBACV,EAAE,EAAE,eAAe;oBACnB,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,+BAA+B;iBACzC,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,QAAQ,GAAG,IAAI,CAAC;YAClB,CAAC;QACH,CAAC;QACD,IAAI,QAAQ;YACV,MAAM,CAAC,IAAI,CAAC;gBACV,EAAE,EAAE,eAAe;gBACnB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,qDAAqD,SAAS,IAAI,gBAAgB,SAAS,QAAQ,qCAAqC,SAAS,GAAG;aAC9J,CAAC,CAAC;QACL,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACxD,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,CAAC,IAAI,CAAC;oBACV,EAAE,EAAE,iBAAiB;oBACrB,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,wCAAwC,SAAS,GAAG;iBAC9D,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC","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,3 @@
1
+ import type { AgentProtocolReport } from "./doctor-protocol.types.ts";
2
+ import type { DoctorAgent } from "./doctor.types.ts";
3
+ export declare function diagnoseAgentProtocol(agent: DoctorAgent): AgentProtocolReport;