@ai-devkit/agent-manager 0.37.0 → 0.38.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 (295) hide show
  1. package/dist/AgentManager.d.ts +0 -4
  2. package/dist/AgentManager.d.ts.map +1 -1
  3. package/dist/AgentManager.js +2 -2
  4. package/dist/AgentManager.js.map +1 -1
  5. package/dist/__tests__/capacity/anthropic.test.js +115 -0
  6. package/dist/__tests__/capacity/anthropic.test.js.map +1 -0
  7. package/dist/__tests__/capacity/boundaries.test.js +45 -0
  8. package/dist/__tests__/capacity/boundaries.test.js.map +1 -0
  9. package/dist/__tests__/capacity/claude.test.js +3 -3
  10. package/dist/__tests__/capacity/claude.test.js.map +1 -1
  11. package/dist/__tests__/capacity/codex.test.js +3 -1
  12. package/dist/__tests__/capacity/codex.test.js.map +1 -1
  13. package/dist/__tests__/capacity/openai.test.js +21 -12
  14. package/dist/__tests__/capacity/openai.test.js.map +1 -1
  15. package/dist/__tests__/capacity/wham.test.js +1 -1
  16. package/dist/__tests__/capacity/wham.test.js.map +1 -1
  17. package/dist/__tests__/capacity/zai.test.js +7 -8
  18. package/dist/__tests__/capacity/zai.test.js.map +1 -1
  19. package/dist/__tests__/harnesses/claude/durable/ClaudePrintAgent.integration.test.js +2 -1
  20. package/dist/__tests__/harnesses/claude/durable/ClaudePrintAgent.integration.test.js.map +1 -1
  21. package/dist/__tests__/harnesses/claude/durable/ClaudePrintRunner.test.js.map +1 -1
  22. package/dist/__tests__/harnesses/codex/durable/CodexCliProbe.test.js +7 -15
  23. package/dist/__tests__/harnesses/codex/durable/CodexCliProbe.test.js.map +1 -1
  24. package/dist/__tests__/harnesses/codex/durable/CodexPrintAgent.integration.test.js +3 -1
  25. package/dist/__tests__/harnesses/codex/durable/CodexPrintAgent.integration.test.js.map +1 -1
  26. package/dist/__tests__/harnesses/codex/durable/CodexPrintAgentService.test.js +11 -26
  27. package/dist/__tests__/harnesses/codex/durable/CodexPrintAgentService.test.js.map +1 -1
  28. package/dist/__tests__/harnesses/codex/durable/CodexPrintRunner.test.js +3 -7
  29. package/dist/__tests__/harnesses/codex/durable/CodexPrintRunner.test.js.map +1 -1
  30. package/dist/__tests__/harnesses/pi/durable/PiCliProbe.test.js +5 -11
  31. package/dist/__tests__/harnesses/pi/durable/PiCliProbe.test.js.map +1 -1
  32. package/dist/__tests__/harnesses/pi/durable/PiPrintAgentService.test.js +9 -19
  33. package/dist/__tests__/harnesses/pi/durable/PiPrintAgentService.test.js.map +1 -1
  34. package/dist/__tests__/harnesses/pi/durable/PiPrintRunner.test.js +3 -7
  35. package/dist/__tests__/harnesses/pi/durable/PiPrintRunner.test.js.map +1 -1
  36. package/dist/__tests__/{readiness → harnesses/readiness}/AgentReadiness.test.js +31 -10
  37. package/dist/__tests__/harnesses/readiness/AgentReadiness.test.js.map +1 -0
  38. package/dist/__tests__/harnesses/runtimeProfiles.test.js +89 -0
  39. package/dist/__tests__/harnesses/runtimeProfiles.test.js.map +1 -0
  40. package/dist/__tests__/print/DurableAgent.test.js +4 -6
  41. package/dist/__tests__/print/DurableAgent.test.js.map +1 -1
  42. package/dist/__tests__/print/DurableAgentRepository.test.js +1 -12
  43. package/dist/__tests__/print/DurableAgentRepository.test.js.map +1 -1
  44. package/dist/__tests__/runtime/ManagedAgentRuntime.test.js.map +1 -1
  45. package/dist/__tests__/terminal/TmuxManager.test.js +1 -1
  46. package/dist/__tests__/terminal/TmuxManager.test.js.map +1 -1
  47. package/dist/capacity/index.d.ts +9 -19
  48. package/dist/capacity/index.d.ts.map +1 -1
  49. package/dist/capacity/index.js +11 -4
  50. package/dist/capacity/index.js.map +1 -1
  51. package/dist/capacity/providers/anthropic.d.ts +9 -0
  52. package/dist/capacity/providers/anthropic.d.ts.map +1 -0
  53. package/dist/capacity/{claude.js → providers/anthropic.js} +10 -128
  54. package/dist/capacity/providers/anthropic.js.map +1 -0
  55. package/dist/capacity/providers/openai-platform.d.ts +14 -0
  56. package/dist/capacity/providers/openai-platform.d.ts.map +1 -0
  57. package/dist/capacity/providers/openai-platform.js +120 -0
  58. package/dist/capacity/providers/openai-platform.js.map +1 -0
  59. package/dist/capacity/providers/openai-subscription.d.ts +20 -0
  60. package/dist/capacity/providers/openai-subscription.d.ts.map +1 -0
  61. package/dist/capacity/providers/openai-subscription.js +129 -0
  62. package/dist/capacity/providers/openai-subscription.js.map +1 -0
  63. package/dist/capacity/providers/zai.d.ts +8 -0
  64. package/dist/capacity/providers/zai.d.ts.map +1 -0
  65. package/dist/capacity/{zai.js → providers/zai.js} +17 -62
  66. package/dist/capacity/providers/zai.js.map +1 -0
  67. package/dist/capacity/sources/claude.d.ts +9 -0
  68. package/dist/capacity/sources/claude.d.ts.map +1 -0
  69. package/dist/capacity/sources/claude.js +17 -0
  70. package/dist/capacity/sources/claude.js.map +1 -0
  71. package/dist/capacity/{codex.d.ts → sources/codex.d.ts} +5 -9
  72. package/dist/capacity/sources/codex.d.ts.map +1 -0
  73. package/dist/capacity/{codex.js → sources/codex.js} +31 -84
  74. package/dist/capacity/sources/codex.js.map +1 -0
  75. package/dist/capacity/sources/pi.d.ts +30 -0
  76. package/dist/capacity/sources/pi.d.ts.map +1 -0
  77. package/dist/capacity/sources/pi.js +81 -0
  78. package/dist/capacity/sources/pi.js.map +1 -0
  79. package/dist/capacity/types.d.ts +2 -0
  80. package/dist/capacity/types.d.ts.map +1 -1
  81. package/dist/capacity/types.js +1 -1
  82. package/dist/capacity/types.js.map +1 -1
  83. package/dist/harnesses/claude/credentials.d.ts +10 -0
  84. package/dist/harnesses/claude/credentials.d.ts.map +1 -0
  85. package/dist/harnesses/claude/credentials.js +112 -0
  86. package/dist/harnesses/claude/credentials.js.map +1 -0
  87. package/dist/harnesses/claude/readiness.d.ts +3 -0
  88. package/dist/harnesses/claude/readiness.d.ts.map +1 -0
  89. package/dist/harnesses/claude/readiness.js +63 -0
  90. package/dist/harnesses/claude/readiness.js.map +1 -0
  91. package/dist/harnesses/codex/credentials.d.ts +15 -0
  92. package/dist/harnesses/codex/credentials.d.ts.map +1 -0
  93. package/dist/harnesses/codex/credentials.js +58 -0
  94. package/dist/harnesses/codex/credentials.js.map +1 -0
  95. package/dist/harnesses/codex/readiness.d.ts +3 -0
  96. package/dist/harnesses/codex/readiness.d.ts.map +1 -0
  97. package/dist/harnesses/codex/readiness.js +60 -0
  98. package/dist/harnesses/codex/readiness.js.map +1 -0
  99. package/dist/harnesses/copilot/readiness.d.ts +3 -0
  100. package/dist/harnesses/copilot/readiness.d.ts.map +1 -0
  101. package/dist/harnesses/copilot/readiness.js +39 -0
  102. package/dist/harnesses/copilot/readiness.js.map +1 -0
  103. package/dist/harnesses/opencode/readiness.d.ts +3 -0
  104. package/dist/harnesses/opencode/readiness.d.ts.map +1 -0
  105. package/dist/harnesses/opencode/readiness.js +50 -0
  106. package/dist/harnesses/opencode/readiness.js.map +1 -0
  107. package/dist/harnesses/pi/credentials.d.ts +22 -0
  108. package/dist/harnesses/pi/credentials.d.ts.map +1 -0
  109. package/dist/harnesses/pi/credentials.js +98 -0
  110. package/dist/harnesses/pi/credentials.js.map +1 -0
  111. package/dist/harnesses/pi/readiness.d.ts +3 -0
  112. package/dist/harnesses/pi/readiness.d.ts.map +1 -0
  113. package/dist/harnesses/pi/readiness.js +96 -0
  114. package/dist/harnesses/pi/readiness.js.map +1 -0
  115. package/dist/harnesses/readiness/AgentReadiness.d.ts +6 -0
  116. package/dist/harnesses/readiness/AgentReadiness.d.ts.map +1 -0
  117. package/dist/harnesses/readiness/AgentReadiness.js +68 -0
  118. package/dist/harnesses/readiness/AgentReadiness.js.map +1 -0
  119. package/dist/harnesses/readiness/checks.d.ts +31 -0
  120. package/dist/harnesses/readiness/checks.d.ts.map +1 -0
  121. package/dist/harnesses/readiness/checks.js +270 -0
  122. package/dist/harnesses/readiness/checks.js.map +1 -0
  123. package/dist/{readiness/AgentReadiness.d.ts → harnesses/readiness/types.d.ts} +19 -10
  124. package/dist/harnesses/readiness/types.d.ts.map +1 -0
  125. package/dist/harnesses/readiness/types.js +4 -0
  126. package/dist/harnesses/readiness/types.js.map +1 -0
  127. package/dist/harnesses/runtimeProfiles.d.ts +11 -0
  128. package/dist/harnesses/runtimeProfiles.d.ts.map +1 -0
  129. package/dist/harnesses/runtimeProfiles.js +99 -0
  130. package/dist/harnesses/runtimeProfiles.js.map +1 -0
  131. package/dist/index.d.ts +16 -42
  132. package/dist/index.d.ts.map +1 -1
  133. package/dist/index.js +9 -23
  134. package/dist/index.js.map +1 -1
  135. package/dist/runtime/ManagedAgentRuntime.d.ts +3 -3
  136. package/dist/runtime/ManagedAgentRuntime.d.ts.map +1 -1
  137. package/dist/runtime/ManagedAgentRuntime.js +6 -20
  138. package/dist/runtime/ManagedAgentRuntime.js.map +1 -1
  139. package/dist/runtime/herdr/HerdrAgentDiscovery.d.ts.map +1 -1
  140. package/dist/runtime/herdr/HerdrAgentDiscovery.js +2 -43
  141. package/dist/runtime/herdr/HerdrAgentDiscovery.js.map +1 -1
  142. package/dist/runtime/tmux/PidPolling.d.ts +1 -1
  143. package/dist/runtime/tmux/PidPolling.d.ts.map +1 -1
  144. package/dist/runtime/tmux/PidPolling.js.map +1 -1
  145. package/dist/runtime/tmux/TmuxAgentRuntime.d.ts +1 -1
  146. package/dist/runtime/tmux/TmuxAgentRuntime.d.ts.map +1 -1
  147. package/dist/runtime/tmux/TmuxAgentRuntime.js +1 -1
  148. package/dist/runtime/tmux/TmuxAgentRuntime.js.map +1 -1
  149. package/dist/runtime/tmux/TmuxManager.d.ts +12 -0
  150. package/dist/runtime/tmux/TmuxManager.d.ts.map +1 -0
  151. package/dist/{terminal → runtime/tmux}/TmuxManager.js +9 -28
  152. package/dist/runtime/tmux/TmuxManager.js.map +1 -0
  153. package/dist/runtime/types.d.ts +1 -1
  154. package/dist/runtime/types.d.ts.map +1 -1
  155. package/dist/runtime/types.js.map +1 -1
  156. package/dist/terminal/TerminalFocusManager.d.ts +4 -32
  157. package/dist/terminal/TerminalFocusManager.d.ts.map +1 -1
  158. package/dist/terminal/TerminalFocusManager.js +17 -267
  159. package/dist/terminal/TerminalFocusManager.js.map +1 -1
  160. package/dist/terminal/TtyWriter.d.ts +1 -44
  161. package/dist/terminal/TtyWriter.d.ts.map +1 -1
  162. package/dist/terminal/TtyWriter.js +11 -347
  163. package/dist/terminal/TtyWriter.js.map +1 -1
  164. package/dist/terminal/backends/index.d.ts +5 -0
  165. package/dist/terminal/backends/index.d.ts.map +1 -0
  166. package/dist/terminal/backends/index.js +19 -0
  167. package/dist/terminal/backends/index.js.map +1 -0
  168. package/dist/terminal/backends/iterm2.d.ts +3 -0
  169. package/dist/terminal/backends/iterm2.d.ts.map +1 -0
  170. package/dist/terminal/backends/iterm2.js +135 -0
  171. package/dist/terminal/backends/iterm2.js.map +1 -0
  172. package/dist/terminal/backends/shared.d.ts +7 -0
  173. package/dist/terminal/backends/shared.d.ts.map +1 -0
  174. package/dist/terminal/backends/shared.js +35 -0
  175. package/dist/terminal/backends/shared.js.map +1 -0
  176. package/dist/terminal/backends/terminal-app.d.ts +3 -0
  177. package/dist/terminal/backends/terminal-app.d.ts.map +1 -0
  178. package/dist/terminal/backends/terminal-app.js +129 -0
  179. package/dist/terminal/backends/terminal-app.js.map +1 -0
  180. package/dist/terminal/backends/tmux.d.ts +3 -0
  181. package/dist/terminal/backends/tmux.d.ts.map +1 -0
  182. package/dist/terminal/backends/tmux.js +76 -0
  183. package/dist/terminal/backends/tmux.js.map +1 -0
  184. package/dist/terminal/backends/wezterm.d.ts +3 -0
  185. package/dist/terminal/backends/wezterm.d.ts.map +1 -0
  186. package/dist/terminal/backends/wezterm.js +71 -0
  187. package/dist/terminal/backends/wezterm.js.map +1 -0
  188. package/dist/terminal/types.d.ts +21 -0
  189. package/dist/terminal/types.d.ts.map +1 -0
  190. package/dist/terminal/types.js +10 -0
  191. package/dist/terminal/types.js.map +1 -0
  192. package/package.json +1 -1
  193. package/src/AgentManager.ts +1 -1
  194. package/src/__tests__/capacity/anthropic.test.ts +105 -0
  195. package/src/__tests__/capacity/boundaries.test.ts +36 -0
  196. package/src/__tests__/capacity/claude.test.ts +3 -8
  197. package/src/__tests__/capacity/codex.test.ts +12 -35
  198. package/src/__tests__/capacity/fixtures/openai-codex-auth.json +1 -1
  199. package/src/__tests__/capacity/openai.test.ts +15 -15
  200. package/src/__tests__/capacity/wham.test.ts +1 -1
  201. package/src/__tests__/capacity/zai.test.ts +27 -62
  202. package/src/__tests__/harnesses/claude/durable/ClaudePrintAgent.integration.test.ts +2 -2
  203. package/src/__tests__/harnesses/claude/durable/ClaudePrintRunner.test.ts +1 -1
  204. package/src/__tests__/harnesses/codex/durable/CodexCliProbe.test.ts +14 -19
  205. package/src/__tests__/harnesses/codex/durable/CodexPrintAgent.integration.test.ts +3 -3
  206. package/src/__tests__/harnesses/codex/durable/CodexPrintAgentService.test.ts +24 -30
  207. package/src/__tests__/harnesses/codex/durable/CodexPrintRunner.test.ts +4 -8
  208. package/src/__tests__/harnesses/pi/durable/PiCliProbe.test.ts +7 -11
  209. package/src/__tests__/harnesses/pi/durable/PiPrintAgentService.test.ts +19 -22
  210. package/src/__tests__/harnesses/pi/durable/PiPrintRunner.test.ts +7 -8
  211. package/src/__tests__/{readiness → harnesses/readiness}/AgentReadiness.test.ts +36 -9
  212. package/src/__tests__/harnesses/runtimeProfiles.test.ts +110 -0
  213. package/src/__tests__/print/DurableAgent.test.ts +4 -13
  214. package/src/__tests__/print/DurableAgentRepository.test.ts +1 -13
  215. package/src/__tests__/runtime/ManagedAgentRuntime.test.ts +1 -1
  216. package/src/__tests__/terminal/TmuxManager.test.ts +1 -1
  217. package/src/capacity/index.ts +29 -23
  218. package/src/capacity/{claude.ts → providers/anthropic.ts} +16 -131
  219. package/src/capacity/providers/openai-platform.ts +150 -0
  220. package/src/capacity/{wham.ts → providers/openai-subscription.ts} +86 -8
  221. package/src/capacity/{zai.ts → providers/zai.ts} +29 -111
  222. package/src/capacity/sources/claude.ts +30 -0
  223. package/src/capacity/{codex.ts → sources/codex.ts} +54 -124
  224. package/src/capacity/sources/pi.ts +131 -0
  225. package/src/capacity/types.ts +3 -0
  226. package/src/harnesses/claude/credentials.ts +122 -0
  227. package/src/harnesses/claude/readiness.ts +69 -0
  228. package/src/harnesses/codex/credentials.ts +81 -0
  229. package/src/harnesses/codex/readiness.ts +72 -0
  230. package/src/harnesses/copilot/readiness.ts +33 -0
  231. package/src/harnesses/opencode/readiness.ts +48 -0
  232. package/src/harnesses/pi/credentials.ts +129 -0
  233. package/src/harnesses/pi/readiness.ts +104 -0
  234. package/src/harnesses/readiness/AgentReadiness.ts +87 -0
  235. package/src/harnesses/readiness/checks.ts +336 -0
  236. package/src/harnesses/readiness/types.ts +90 -0
  237. package/src/{utils/agents.ts → harnesses/runtimeProfiles.ts} +34 -38
  238. package/src/index.ts +15 -128
  239. package/src/runtime/ManagedAgentRuntime.ts +7 -22
  240. package/src/runtime/herdr/HerdrAgentDiscovery.ts +3 -19
  241. package/src/runtime/tmux/PidPolling.ts +1 -1
  242. package/src/runtime/tmux/TmuxAgentRuntime.ts +1 -1
  243. package/src/{terminal → runtime/tmux}/TmuxManager.ts +9 -30
  244. package/src/runtime/types.ts +1 -1
  245. package/src/terminal/TerminalFocusManager.ts +19 -292
  246. package/src/terminal/TtyWriter.ts +16 -336
  247. package/src/terminal/backends/index.ts +21 -0
  248. package/src/terminal/backends/iterm2.ts +126 -0
  249. package/src/terminal/backends/shared.ts +42 -0
  250. package/src/terminal/backends/terminal-app.ts +122 -0
  251. package/src/terminal/backends/tmux.ts +62 -0
  252. package/src/terminal/backends/wezterm.ts +65 -0
  253. package/src/terminal/types.ts +22 -0
  254. package/dist/__tests__/readiness/AgentReadiness.test.js.map +0 -1
  255. package/dist/__tests__/utils/agents.test.js +0 -93
  256. package/dist/__tests__/utils/agents.test.js.map +0 -1
  257. package/dist/capacity/claude.d.ts +0 -17
  258. package/dist/capacity/claude.d.ts.map +0 -1
  259. package/dist/capacity/claude.js.map +0 -1
  260. package/dist/capacity/codex.d.ts.map +0 -1
  261. package/dist/capacity/codex.js.map +0 -1
  262. package/dist/capacity/openai.d.ts +0 -47
  263. package/dist/capacity/openai.d.ts.map +0 -1
  264. package/dist/capacity/openai.js +0 -307
  265. package/dist/capacity/openai.js.map +0 -1
  266. package/dist/capacity/wham.d.ts +0 -16
  267. package/dist/capacity/wham.d.ts.map +0 -1
  268. package/dist/capacity/wham.js +0 -66
  269. package/dist/capacity/wham.js.map +0 -1
  270. package/dist/capacity/zai.d.ts +0 -14
  271. package/dist/capacity/zai.d.ts.map +0 -1
  272. package/dist/capacity/zai.js.map +0 -1
  273. package/dist/readiness/AgentReadiness.d.ts.map +0 -1
  274. package/dist/readiness/AgentReadiness.js +0 -614
  275. package/dist/readiness/AgentReadiness.js.map +0 -1
  276. package/dist/terminal/TmuxManager.d.ts +0 -28
  277. package/dist/terminal/TmuxManager.d.ts.map +0 -1
  278. package/dist/terminal/TmuxManager.js.map +0 -1
  279. package/dist/terminal/index.d.ts +0 -5
  280. package/dist/terminal/index.d.ts.map +0 -1
  281. package/dist/terminal/index.js +0 -5
  282. package/dist/terminal/index.js.map +0 -1
  283. package/dist/utils/agents.d.ts +0 -16
  284. package/dist/utils/agents.d.ts.map +0 -1
  285. package/dist/utils/agents.js +0 -117
  286. package/dist/utils/agents.js.map +0 -1
  287. package/dist/utils/index.d.ts +0 -8
  288. package/dist/utils/index.d.ts.map +0 -1
  289. package/dist/utils/index.js +0 -6
  290. package/dist/utils/index.js.map +0 -1
  291. package/src/__tests__/utils/agents.test.ts +0 -105
  292. package/src/capacity/openai.ts +0 -355
  293. package/src/readiness/AgentReadiness.ts +0 -730
  294. package/src/terminal/index.ts +0 -4
  295. package/src/utils/index.ts +0 -14
@@ -1,8 +1,7 @@
1
1
  import { describe, expect, it, vi } from "vitest";
2
+ import { PiCliProbe } from "../../../../harnesses/pi/durable/PiCliProbe.js";
2
3
  describe("PiCliProbe", ()=>{
3
4
  it("validates documented JSON mode and session capabilities", async ()=>{
4
- const api = await import("../../../../index.js");
5
- expect(api).toHaveProperty("PiCliProbe");
6
5
  const exec = vi.fn().mockResolvedValueOnce({
7
6
  stdout: "pi 0.52.8",
8
7
  stderr: ""
@@ -10,8 +9,7 @@ describe("PiCliProbe", ()=>{
10
9
  stdout: "--mode json\n--session-id <uuid>\n--session <path|id>",
11
10
  stderr: ""
12
11
  });
13
- const Probe = api.PiCliProbe;
14
- await expect(new Probe({
12
+ await expect(new PiCliProbe({
15
13
  executable: "fake-pi",
16
14
  exec
17
15
  }).validate()).resolves.toEqual({
@@ -34,9 +32,7 @@ describe("PiCliProbe", ()=>{
34
32
  ]);
35
33
  });
36
34
  it("rejects unsupported and unavailable CLIs with sanitized errors", async ()=>{
37
- const api = await import("../../../../index.js");
38
- const Probe = api.PiCliProbe;
39
- await expect(new Probe({
35
+ await expect(new PiCliProbe({
40
36
  exec: vi.fn().mockResolvedValueOnce({
41
37
  stdout: "",
42
38
  stderr: ""
@@ -47,7 +43,7 @@ describe("PiCliProbe", ()=>{
47
43
  }).validate()).rejects.toMatchObject({
48
44
  code: "PI_CLI_UNSUPPORTED"
49
45
  });
50
- const unavailable = new Probe({
46
+ const unavailable = new PiCliProbe({
51
47
  exec: vi.fn().mockRejectedValue(new Error(`bad\0${"x".repeat(1000)}`))
52
48
  });
53
49
  const error = await unavailable.validate().catch((value)=>value);
@@ -56,8 +52,6 @@ describe("PiCliProbe", ()=>{
56
52
  expect(error.message.length).toBeLessThan(600);
57
53
  });
58
54
  it("reports an empty version as unknown", async ()=>{
59
- const api = await import("../../../../index.js");
60
- const Probe = api.PiCliProbe;
61
55
  const exec = vi.fn().mockResolvedValueOnce({
62
56
  stdout: " \n",
63
57
  stderr: ""
@@ -65,7 +59,7 @@ describe("PiCliProbe", ()=>{
65
59
  stdout: "--mode json --session-id --session",
66
60
  stderr: ""
67
61
  });
68
- await expect(new Probe({
62
+ await expect(new PiCliProbe({
69
63
  exec
70
64
  }).validate()).resolves.toMatchObject({
71
65
  version: "unknown"
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/__tests__/harnesses/pi/durable/PiCliProbe.test.ts"],"sourcesContent":["import { describe, expect, it, vi } from \"vitest\";\n\ndescribe(\"PiCliProbe\", () => {\n it(\"validates documented JSON mode and session capabilities\", async () => {\n const api = (await import(\"../../../../index.js\")) as Record<string, unknown>;\n expect(api).toHaveProperty(\"PiCliProbe\");\n const exec = vi\n .fn()\n .mockResolvedValueOnce({ stdout: \"pi 0.52.8\", stderr: \"\" })\n .mockResolvedValueOnce({\n stdout: \"--mode json\\n--session-id <uuid>\\n--session <path|id>\",\n stderr: \"\",\n });\n const Probe = api.PiCliProbe as new (options: unknown) => any;\n await expect(new Probe({ executable: \"fake-pi\", exec }).validate()).resolves.toEqual({\n executable: \"fake-pi\",\n version: \"pi 0.52.8\",\n });\n expect(exec.mock.calls).toEqual([\n [\"fake-pi\", [\"--version\"]],\n [\"fake-pi\", [\"--help\"]],\n ]);\n });\n\n it(\"rejects unsupported and unavailable CLIs with sanitized errors\", async () => {\n const api = (await import(\"../../../../index.js\")) as Record<string, unknown>;\n const Probe = api.PiCliProbe as new (options: unknown) => any;\n await expect(\n new Probe({\n exec: vi\n .fn()\n .mockResolvedValueOnce({ stdout: \"\", stderr: \"\" })\n .mockResolvedValueOnce({ stdout: \"--print only\", stderr: \"\" }),\n }).validate(),\n ).rejects.toMatchObject({ code: \"PI_CLI_UNSUPPORTED\" });\n const unavailable = new Probe({\n exec: vi.fn().mockRejectedValue(new Error(`bad\\0${\"x\".repeat(1000)}`)),\n });\n const error = await unavailable.validate().catch((value: Error & { code: string }) => value);\n expect(error.code).toBe(\"PI_CLI_UNAVAILABLE\");\n expect(error.message).not.toContain(\"\\0\");\n expect(error.message.length).toBeLessThan(600);\n });\n\n it(\"reports an empty version as unknown\", async () => {\n const api = (await import(\"../../../../index.js\")) as Record<string, unknown>;\n const Probe = api.PiCliProbe as new (options: unknown) => any;\n const exec = vi\n .fn()\n .mockResolvedValueOnce({ stdout: \" \\n\", stderr: \"\" })\n .mockResolvedValueOnce({ stdout: \"--mode json --session-id --session\", stderr: \"\" });\n await expect(new Probe({ exec }).validate()).resolves.toMatchObject({ version: \"unknown\" });\n });\n});\n"],"names":["describe","expect","it","vi","api","toHaveProperty","exec","fn","mockResolvedValueOnce","stdout","stderr","Probe","PiCliProbe","executable","validate","resolves","toEqual","version","mock","calls","rejects","toMatchObject","code","unavailable","mockRejectedValue","Error","repeat","error","catch","value","toBe","message","not","toContain","length","toBeLessThan"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ,SAAS;AAElDH,SAAS,cAAc;IACrBE,GAAG,2DAA2D;QAC5D,MAAME,MAAO,MAAM,MAAM,CAAC;QAC1BH,OAAOG,KAAKC,cAAc,CAAC;QAC3B,MAAMC,OAAOH,GACVI,EAAE,GACFC,qBAAqB,CAAC;YAAEC,QAAQ;YAAaC,QAAQ;QAAG,GACxDF,qBAAqB,CAAC;YACrBC,QAAQ;YACRC,QAAQ;QACV;QACF,MAAMC,QAAQP,IAAIQ,UAAU;QAC5B,MAAMX,OAAO,IAAIU,MAAM;YAAEE,YAAY;YAAWP;QAAK,GAAGQ,QAAQ,IAAIC,QAAQ,CAACC,OAAO,CAAC;YACnFH,YAAY;YACZI,SAAS;QACX;QACAhB,OAAOK,KAAKY,IAAI,CAACC,KAAK,EAAEH,OAAO,CAAC;YAC9B;gBAAC;gBAAW;oBAAC;iBAAY;aAAC;YAC1B;gBAAC;gBAAW;oBAAC;iBAAS;aAAC;SACxB;IACH;IAEAd,GAAG,kEAAkE;QACnE,MAAME,MAAO,MAAM,MAAM,CAAC;QAC1B,MAAMO,QAAQP,IAAIQ,UAAU;QAC5B,MAAMX,OACJ,IAAIU,MAAM;YACRL,MAAMH,GACHI,EAAE,GACFC,qBAAqB,CAAC;gBAAEC,QAAQ;gBAAIC,QAAQ;YAAG,GAC/CF,qBAAqB,CAAC;gBAAEC,QAAQ;gBAAgBC,QAAQ;YAAG;QAChE,GAAGI,QAAQ,IACXM,OAAO,CAACC,aAAa,CAAC;YAAEC,MAAM;QAAqB;QACrD,MAAMC,cAAc,IAAIZ,MAAM;YAC5BL,MAAMH,GAAGI,EAAE,GAAGiB,iBAAiB,CAAC,IAAIC,MAAM,CAAC,KAAK,EAAE,IAAIC,MAAM,CAAC,OAAO;QACtE;QACA,MAAMC,QAAQ,MAAMJ,YAAYT,QAAQ,GAAGc,KAAK,CAAC,CAACC,QAAoCA;QACtF5B,OAAO0B,MAAML,IAAI,EAAEQ,IAAI,CAAC;QACxB7B,OAAO0B,MAAMI,OAAO,EAAEC,GAAG,CAACC,SAAS,CAAC;QACpChC,OAAO0B,MAAMI,OAAO,CAACG,MAAM,EAAEC,YAAY,CAAC;IAC5C;IAEAjC,GAAG,uCAAuC;QACxC,MAAME,MAAO,MAAM,MAAM,CAAC;QAC1B,MAAMO,QAAQP,IAAIQ,UAAU;QAC5B,MAAMN,OAAOH,GACVI,EAAE,GACFC,qBAAqB,CAAC;YAAEC,QAAQ;YAAOC,QAAQ;QAAG,GAClDF,qBAAqB,CAAC;YAAEC,QAAQ;YAAsCC,QAAQ;QAAG;QACpF,MAAMT,OAAO,IAAIU,MAAM;YAAEL;QAAK,GAAGQ,QAAQ,IAAIC,QAAQ,CAACM,aAAa,CAAC;YAAEJ,SAAS;QAAU;IAC3F;AACF"}
1
+ {"version":3,"sources":["../../../../../src/__tests__/harnesses/pi/durable/PiCliProbe.test.ts"],"sourcesContent":["import { describe, expect, it, vi } from \"vitest\";\nimport { PiCliProbe } from \"../../../../harnesses/pi/durable/PiCliProbe.js\";\n\ndescribe(\"PiCliProbe\", () => {\n it(\"validates documented JSON mode and session capabilities\", async () => {\n const exec = vi\n .fn()\n .mockResolvedValueOnce({ stdout: \"pi 0.52.8\", stderr: \"\" })\n .mockResolvedValueOnce({\n stdout: \"--mode json\\n--session-id <uuid>\\n--session <path|id>\",\n stderr: \"\",\n });\n await expect(new PiCliProbe({ executable: \"fake-pi\", exec }).validate()).resolves.toEqual({\n executable: \"fake-pi\",\n version: \"pi 0.52.8\",\n });\n expect(exec.mock.calls).toEqual([\n [\"fake-pi\", [\"--version\"]],\n [\"fake-pi\", [\"--help\"]],\n ]);\n });\n\n it(\"rejects unsupported and unavailable CLIs with sanitized errors\", async () => {\n await expect(\n new PiCliProbe({\n exec: vi\n .fn()\n .mockResolvedValueOnce({ stdout: \"\", stderr: \"\" })\n .mockResolvedValueOnce({ stdout: \"--print only\", stderr: \"\" }),\n }).validate(),\n ).rejects.toMatchObject({ code: \"PI_CLI_UNSUPPORTED\" });\n const unavailable = new PiCliProbe({\n exec: vi.fn().mockRejectedValue(new Error(`bad\\0${\"x\".repeat(1000)}`)),\n });\n const error = await unavailable.validate().catch((value: Error & { code: string }) => value);\n expect(error.code).toBe(\"PI_CLI_UNAVAILABLE\");\n expect(error.message).not.toContain(\"\\0\");\n expect(error.message.length).toBeLessThan(600);\n });\n\n it(\"reports an empty version as unknown\", async () => {\n const exec = vi\n .fn()\n .mockResolvedValueOnce({ stdout: \" \\n\", stderr: \"\" })\n .mockResolvedValueOnce({ stdout: \"--mode json --session-id --session\", stderr: \"\" });\n await expect(new PiCliProbe({ exec }).validate()).resolves.toMatchObject({\n version: \"unknown\",\n });\n });\n});\n"],"names":["describe","expect","it","vi","PiCliProbe","exec","fn","mockResolvedValueOnce","stdout","stderr","executable","validate","resolves","toEqual","version","mock","calls","rejects","toMatchObject","code","unavailable","mockRejectedValue","Error","repeat","error","catch","value","toBe","message","not","toContain","length","toBeLessThan"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ,SAAS;AAClD,SAASC,UAAU,QAAQ,iDAAiD;AAE5EJ,SAAS,cAAc;IACrBE,GAAG,2DAA2D;QAC5D,MAAMG,OAAOF,GACVG,EAAE,GACFC,qBAAqB,CAAC;YAAEC,QAAQ;YAAaC,QAAQ;QAAG,GACxDF,qBAAqB,CAAC;YACrBC,QAAQ;YACRC,QAAQ;QACV;QACF,MAAMR,OAAO,IAAIG,WAAW;YAAEM,YAAY;YAAWL;QAAK,GAAGM,QAAQ,IAAIC,QAAQ,CAACC,OAAO,CAAC;YACxFH,YAAY;YACZI,SAAS;QACX;QACAb,OAAOI,KAAKU,IAAI,CAACC,KAAK,EAAEH,OAAO,CAAC;YAC9B;gBAAC;gBAAW;oBAAC;iBAAY;aAAC;YAC1B;gBAAC;gBAAW;oBAAC;iBAAS;aAAC;SACxB;IACH;IAEAX,GAAG,kEAAkE;QACnE,MAAMD,OACJ,IAAIG,WAAW;YACbC,MAAMF,GACHG,EAAE,GACFC,qBAAqB,CAAC;gBAAEC,QAAQ;gBAAIC,QAAQ;YAAG,GAC/CF,qBAAqB,CAAC;gBAAEC,QAAQ;gBAAgBC,QAAQ;YAAG;QAChE,GAAGE,QAAQ,IACXM,OAAO,CAACC,aAAa,CAAC;YAAEC,MAAM;QAAqB;QACrD,MAAMC,cAAc,IAAIhB,WAAW;YACjCC,MAAMF,GAAGG,EAAE,GAAGe,iBAAiB,CAAC,IAAIC,MAAM,CAAC,KAAK,EAAE,IAAIC,MAAM,CAAC,OAAO;QACtE;QACA,MAAMC,QAAQ,MAAMJ,YAAYT,QAAQ,GAAGc,KAAK,CAAC,CAACC,QAAoCA;QACtFzB,OAAOuB,MAAML,IAAI,EAAEQ,IAAI,CAAC;QACxB1B,OAAOuB,MAAMI,OAAO,EAAEC,GAAG,CAACC,SAAS,CAAC;QACpC7B,OAAOuB,MAAMI,OAAO,CAACG,MAAM,EAAEC,YAAY,CAAC;IAC5C;IAEA9B,GAAG,uCAAuC;QACxC,MAAMG,OAAOF,GACVG,EAAE,GACFC,qBAAqB,CAAC;YAAEC,QAAQ;YAAOC,QAAQ;QAAG,GAClDF,qBAAqB,CAAC;YAAEC,QAAQ;YAAsCC,QAAQ;QAAG;QACpF,MAAMR,OAAO,IAAIG,WAAW;YAAEC;QAAK,GAAGM,QAAQ,IAAIC,QAAQ,CAACM,aAAa,CAAC;YACvEJ,SAAS;QACX;IACF;AACF"}
@@ -1,4 +1,6 @@
1
1
  import { describe, expect, it, vi } from "vitest";
2
+ import { PiPrintError } from "../../../../durable/DurableAgent.js";
3
+ import { PiPrintAgentService } from "../../../../harnesses/pi/durable/PiPrintAgentService.js";
2
4
  const SESSION = "22222222-2222-4222-8222-222222222222";
3
5
  const base = {
4
6
  id: "id",
@@ -9,8 +11,6 @@ const base = {
9
11
  };
10
12
  describe("PiPrintAgentService", ()=>{
11
13
  it("probes before provider-aware create", async ()=>{
12
- const api = await import("../../../../index.js");
13
- expect(api).toHaveProperty("PiPrintAgentService");
14
14
  const probe = {
15
15
  validate: vi.fn()
16
16
  };
@@ -21,8 +21,7 @@ describe("PiPrintAgentService", ()=>{
21
21
  const runner = {
22
22
  run: vi.fn()
23
23
  };
24
- const Service = api.PiPrintAgentService;
25
- await new Service({
24
+ await new PiPrintAgentService({
26
25
  repository,
27
26
  probe,
28
27
  runner
@@ -38,7 +37,6 @@ describe("PiPrintAgentService", ()=>{
38
37
  });
39
38
  });
40
39
  it("records successful first and resumed sends", async ()=>{
41
- const api = await import("../../../../index.js");
42
40
  const repository = {
43
41
  list: vi.fn(),
44
42
  resolve: vi.fn().mockResolvedValue(base),
@@ -71,8 +69,7 @@ describe("PiPrintAgentService", ()=>{
71
69
  };
72
70
  })
73
71
  };
74
- const Service = api.PiPrintAgentService;
75
- const service = new Service({
72
+ const service = new PiPrintAgentService({
76
73
  repository,
77
74
  probe: {
78
75
  validate: vi.fn()
@@ -87,8 +84,6 @@ describe("PiPrintAgentService", ()=>{
87
84
  }));
88
85
  });
89
86
  it("records mismatches and rejects missing and ambiguous records", async ()=>{
90
- const api = await import("../../../../index.js");
91
- const ErrorType = api.PiPrintError;
92
87
  const completeRun = vi.fn();
93
88
  const repository = {
94
89
  list: vi.fn(),
@@ -100,14 +95,13 @@ describe("PiPrintAgentService", ()=>{
100
95
  recordProviderProcess: vi.fn(),
101
96
  completeRun
102
97
  };
103
- const Service = api.PiPrintAgentService;
104
- await expect(new Service({
98
+ await expect(new PiPrintAgentService({
105
99
  repository,
106
100
  probe: {
107
101
  validate: vi.fn()
108
102
  },
109
103
  runner: {
110
- run: vi.fn().mockRejectedValue(new ErrorType("bad", "PI_SESSION_MISMATCH"))
104
+ run: vi.fn().mockRejectedValue(new PiPrintError("bad", "PI_SESSION_MISMATCH"))
111
105
  }
112
106
  }).send("reviewer", "x")).rejects.toMatchObject({
113
107
  code: "PI_SESSION_MISMATCH"
@@ -123,7 +117,7 @@ describe("PiPrintAgentService", ()=>{
123
117
  ]),
124
118
  acquireRun: vi.fn()
125
119
  };
126
- const early = new Service({
120
+ const early = new PiPrintAgentService({
127
121
  repository: earlyRepository,
128
122
  probe: {
129
123
  validate: vi.fn()
@@ -140,8 +134,6 @@ describe("PiPrintAgentService", ()=>{
140
134
  });
141
135
  });
142
136
  it("rejects a non-Pi target without acquiring or mutating it", async ()=>{
143
- const api = await import("../../../../index.js");
144
- const Service = api.PiPrintAgentService;
145
137
  const repository = {
146
138
  resolve: vi.fn().mockResolvedValue({
147
139
  ...base,
@@ -151,7 +143,7 @@ describe("PiPrintAgentService", ()=>{
151
143
  recordProviderProcess: vi.fn(),
152
144
  completeRun: vi.fn()
153
145
  };
154
- await expect(new Service({
146
+ await expect(new PiPrintAgentService({
155
147
  repository,
156
148
  probe: {
157
149
  validate: vi.fn()
@@ -166,8 +158,6 @@ describe("PiPrintAgentService", ()=>{
166
158
  expect(repository.completeRun).not.toHaveBeenCalled();
167
159
  });
168
160
  it("does not turn a successful completion write failure into a second completion", async ()=>{
169
- const api = await import("../../../../index.js");
170
- const Service = api.PiPrintAgentService;
171
161
  const completionFailure = new Error("completion failed");
172
162
  const repository = {
173
163
  resolve: vi.fn().mockResolvedValue(base),
@@ -188,7 +178,7 @@ describe("PiPrintAgentService", ()=>{
188
178
  exitCode: 0
189
179
  })
190
180
  };
191
- await expect(new Service({
181
+ await expect(new PiPrintAgentService({
192
182
  repository,
193
183
  probe: {
194
184
  validate: vi.fn()
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/__tests__/harnesses/pi/durable/PiPrintAgentService.test.ts"],"sourcesContent":["import { describe, expect, it, vi } from \"vitest\";\nconst SESSION = \"22222222-2222-4222-8222-222222222222\";\nconst base = {\n id: \"id\",\n name: \"reviewer\",\n provider: \"pi\",\n providerSessionId: SESSION,\n sessionHealth: \"uninitialized\",\n};\n\ndescribe(\"PiPrintAgentService\", () => {\n it(\"probes before provider-aware create\", async () => {\n const api = (await import(\"../../../../index.js\")) as Record<string, unknown>;\n expect(api).toHaveProperty(\"PiPrintAgentService\");\n const probe = { validate: vi.fn() };\n const repository = { create: vi.fn().mockResolvedValue(base), list: vi.fn() };\n const runner = { run: vi.fn() };\n const Service = api.PiPrintAgentService as new (options: unknown) => any;\n await new Service({ repository, probe, runner }).create({ name: \"reviewer\", cwd: \"/project\" });\n expect(probe.validate).toHaveBeenCalledOnce();\n expect(repository.create).toHaveBeenCalledWith({\n name: \"reviewer\",\n cwd: \"/project\",\n provider: \"pi\",\n });\n });\n\n it(\"records successful first and resumed sends\", async () => {\n const api = (await import(\"../../../../index.js\")) as Record<string, unknown>;\n const repository = {\n list: vi.fn(),\n resolve: vi.fn().mockResolvedValue(base),\n acquireRun: vi\n .fn()\n .mockResolvedValueOnce({ agent: base, token: \"one\" })\n .mockResolvedValueOnce({ agent: { ...base, sessionHealth: \"healthy\" }, token: \"two\" }),\n recordProviderProcess: vi.fn(),\n completeRun: vi.fn(),\n };\n const runner = {\n run: vi.fn(async (request) => {\n await request.onSpawn({ pid: 42, startedAt: \"start\" });\n return { sessionId: SESSION, result: \"answer\", messages: [\"answer\"], exitCode: 0 };\n }),\n };\n const Service = api.PiPrintAgentService as new (options: unknown) => any;\n const service = new Service({ repository, probe: { validate: vi.fn() }, runner });\n await service.send(\"reviewer\", \"first\");\n await service.send(\"reviewer\", \"later\");\n expect(repository.completeRun).toHaveBeenCalledWith(\n \"id\",\n \"one\",\n expect.objectContaining({ status: \"succeeded\", sessionHealth: \"healthy\" }),\n );\n });\n\n it(\"records mismatches and rejects missing and ambiguous records\", async () => {\n const api = (await import(\"../../../../index.js\")) as Record<string, unknown>;\n const ErrorType = api.PiPrintError as new (message: string, code: string) => Error;\n const completeRun = vi.fn();\n const repository = {\n list: vi.fn(),\n resolve: vi.fn().mockResolvedValue(base),\n acquireRun: vi.fn().mockResolvedValue({ agent: base, token: \"one\" }),\n recordProviderProcess: vi.fn(),\n completeRun,\n };\n const Service = api.PiPrintAgentService as new (options: unknown) => any;\n await expect(\n new Service({\n repository,\n probe: { validate: vi.fn() },\n runner: { run: vi.fn().mockRejectedValue(new ErrorType(\"bad\", \"PI_SESSION_MISMATCH\")) },\n }).send(\"reviewer\", \"x\"),\n ).rejects.toMatchObject({ code: \"PI_SESSION_MISMATCH\" });\n expect(completeRun).toHaveBeenCalledWith(\n \"id\",\n \"one\",\n expect.objectContaining({ sessionHealth: \"mismatch\" }),\n );\n const earlyRepository = {\n ...repository,\n resolve: vi.fn().mockResolvedValueOnce(null).mockResolvedValueOnce([base, base]),\n acquireRun: vi.fn(),\n };\n const early = new Service({\n repository: earlyRepository,\n probe: { validate: vi.fn() },\n runner: { run: vi.fn() },\n });\n await expect(early.send(\"missing\", \"x\")).rejects.toMatchObject({\n code: \"DURABLE_AGENT_NOT_FOUND\",\n });\n await expect(early.send(\"many\", \"x\")).rejects.toMatchObject({ code: \"PI_UNSUPPORTED\" });\n });\n\n it(\"rejects a non-Pi target without acquiring or mutating it\", async () => {\n const api = (await import(\"../../../../index.js\")) as Record<string, unknown>;\n const Service = api.PiPrintAgentService as new (options: unknown) => any;\n const repository = {\n resolve: vi.fn().mockResolvedValue({ ...base, provider: \"claude\" }),\n acquireRun: vi.fn(),\n recordProviderProcess: vi.fn(),\n completeRun: vi.fn(),\n };\n\n await expect(\n new Service({ repository, probe: { validate: vi.fn() }, runner: { run: vi.fn() } }).send(\n \"reviewer\",\n \"x\",\n ),\n ).rejects.toMatchObject({ code: \"PI_UNSUPPORTED\" });\n expect(repository.acquireRun).not.toHaveBeenCalled();\n expect(repository.completeRun).not.toHaveBeenCalled();\n });\n\n it(\"does not turn a successful completion write failure into a second completion\", async () => {\n const api = (await import(\"../../../../index.js\")) as Record<string, unknown>;\n const Service = api.PiPrintAgentService as new (options: unknown) => any;\n const completionFailure = new Error(\"completion failed\");\n const repository = {\n resolve: vi.fn().mockResolvedValue(base),\n acquireRun: vi.fn().mockResolvedValue({ agent: base, token: \"one\" }),\n recordProviderProcess: vi.fn(),\n completeRun: vi.fn().mockRejectedValue(completionFailure),\n };\n const runner = {\n run: vi.fn().mockResolvedValue({\n sessionId: SESSION,\n result: \"answer\",\n messages: [\"answer\"],\n exitCode: 0,\n }),\n };\n\n await expect(\n new Service({ repository, probe: { validate: vi.fn() }, runner }).send(\"reviewer\", \"x\"),\n ).rejects.toBe(completionFailure);\n expect(repository.completeRun).toHaveBeenCalledOnce();\n });\n});\n"],"names":["describe","expect","it","vi","SESSION","base","id","name","provider","providerSessionId","sessionHealth","api","toHaveProperty","probe","validate","fn","repository","create","mockResolvedValue","list","runner","run","Service","PiPrintAgentService","cwd","toHaveBeenCalledOnce","toHaveBeenCalledWith","resolve","acquireRun","mockResolvedValueOnce","agent","token","recordProviderProcess","completeRun","request","onSpawn","pid","startedAt","sessionId","result","messages","exitCode","service","send","objectContaining","status","ErrorType","PiPrintError","mockRejectedValue","rejects","toMatchObject","code","earlyRepository","early","not","toHaveBeenCalled","completionFailure","Error","toBe"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/__tests__/harnesses/pi/durable/PiPrintAgentService.test.ts"],"sourcesContent":["import { describe, expect, it, vi } from \"vitest\";\nimport { PiPrintError } from \"../../../../durable/DurableAgent.js\";\nimport { PiPrintAgentService } from \"../../../../harnesses/pi/durable/PiPrintAgentService.js\";\nconst SESSION = \"22222222-2222-4222-8222-222222222222\";\nconst base = {\n id: \"id\",\n name: \"reviewer\",\n provider: \"pi\",\n providerSessionId: SESSION,\n sessionHealth: \"uninitialized\",\n};\n\ndescribe(\"PiPrintAgentService\", () => {\n it(\"probes before provider-aware create\", async () => {\n const probe = { validate: vi.fn() };\n const repository = { create: vi.fn().mockResolvedValue(base), list: vi.fn() };\n const runner = { run: vi.fn() };\n await new PiPrintAgentService({ repository, probe, runner }).create({\n name: \"reviewer\",\n cwd: \"/project\",\n });\n expect(probe.validate).toHaveBeenCalledOnce();\n expect(repository.create).toHaveBeenCalledWith({\n name: \"reviewer\",\n cwd: \"/project\",\n provider: \"pi\",\n });\n });\n\n it(\"records successful first and resumed sends\", async () => {\n const repository = {\n list: vi.fn(),\n resolve: vi.fn().mockResolvedValue(base),\n acquireRun: vi\n .fn()\n .mockResolvedValueOnce({ agent: base, token: \"one\" })\n .mockResolvedValueOnce({ agent: { ...base, sessionHealth: \"healthy\" }, token: \"two\" }),\n recordProviderProcess: vi.fn(),\n completeRun: vi.fn(),\n };\n const runner = {\n run: vi.fn(async (request) => {\n await request.onSpawn({ pid: 42, startedAt: \"start\" });\n return { sessionId: SESSION, result: \"answer\", messages: [\"answer\"], exitCode: 0 };\n }),\n };\n const service = new PiPrintAgentService({ repository, probe: { validate: vi.fn() }, runner });\n await service.send(\"reviewer\", \"first\");\n await service.send(\"reviewer\", \"later\");\n expect(repository.completeRun).toHaveBeenCalledWith(\n \"id\",\n \"one\",\n expect.objectContaining({ status: \"succeeded\", sessionHealth: \"healthy\" }),\n );\n });\n\n it(\"records mismatches and rejects missing and ambiguous records\", async () => {\n const completeRun = vi.fn();\n const repository = {\n list: vi.fn(),\n resolve: vi.fn().mockResolvedValue(base),\n acquireRun: vi.fn().mockResolvedValue({ agent: base, token: \"one\" }),\n recordProviderProcess: vi.fn(),\n completeRun,\n };\n await expect(\n new PiPrintAgentService({\n repository,\n probe: { validate: vi.fn() },\n runner: { run: vi.fn().mockRejectedValue(new PiPrintError(\"bad\", \"PI_SESSION_MISMATCH\")) },\n }).send(\"reviewer\", \"x\"),\n ).rejects.toMatchObject({ code: \"PI_SESSION_MISMATCH\" });\n expect(completeRun).toHaveBeenCalledWith(\n \"id\",\n \"one\",\n expect.objectContaining({ sessionHealth: \"mismatch\" }),\n );\n const earlyRepository = {\n ...repository,\n resolve: vi.fn().mockResolvedValueOnce(null).mockResolvedValueOnce([base, base]),\n acquireRun: vi.fn(),\n };\n const early = new PiPrintAgentService({\n repository: earlyRepository,\n probe: { validate: vi.fn() },\n runner: { run: vi.fn() },\n });\n await expect(early.send(\"missing\", \"x\")).rejects.toMatchObject({\n code: \"DURABLE_AGENT_NOT_FOUND\",\n });\n await expect(early.send(\"many\", \"x\")).rejects.toMatchObject({ code: \"PI_UNSUPPORTED\" });\n });\n\n it(\"rejects a non-Pi target without acquiring or mutating it\", async () => {\n const repository = {\n resolve: vi.fn().mockResolvedValue({ ...base, provider: \"claude\" }),\n acquireRun: vi.fn(),\n recordProviderProcess: vi.fn(),\n completeRun: vi.fn(),\n };\n\n await expect(\n new PiPrintAgentService({\n repository,\n probe: { validate: vi.fn() },\n runner: { run: vi.fn() },\n }).send(\"reviewer\", \"x\"),\n ).rejects.toMatchObject({ code: \"PI_UNSUPPORTED\" });\n expect(repository.acquireRun).not.toHaveBeenCalled();\n expect(repository.completeRun).not.toHaveBeenCalled();\n });\n\n it(\"does not turn a successful completion write failure into a second completion\", async () => {\n const completionFailure = new Error(\"completion failed\");\n const repository = {\n resolve: vi.fn().mockResolvedValue(base),\n acquireRun: vi.fn().mockResolvedValue({ agent: base, token: \"one\" }),\n recordProviderProcess: vi.fn(),\n completeRun: vi.fn().mockRejectedValue(completionFailure),\n };\n const runner = {\n run: vi.fn().mockResolvedValue({\n sessionId: SESSION,\n result: \"answer\",\n messages: [\"answer\"],\n exitCode: 0,\n }),\n };\n\n await expect(\n new PiPrintAgentService({ repository, probe: { validate: vi.fn() }, runner }).send(\n \"reviewer\",\n \"x\",\n ),\n ).rejects.toBe(completionFailure);\n expect(repository.completeRun).toHaveBeenCalledOnce();\n });\n});\n"],"names":["describe","expect","it","vi","PiPrintError","PiPrintAgentService","SESSION","base","id","name","provider","providerSessionId","sessionHealth","probe","validate","fn","repository","create","mockResolvedValue","list","runner","run","cwd","toHaveBeenCalledOnce","toHaveBeenCalledWith","resolve","acquireRun","mockResolvedValueOnce","agent","token","recordProviderProcess","completeRun","request","onSpawn","pid","startedAt","sessionId","result","messages","exitCode","service","send","objectContaining","status","mockRejectedValue","rejects","toMatchObject","code","earlyRepository","early","not","toHaveBeenCalled","completionFailure","Error","toBe"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ,SAAS;AAClD,SAASC,YAAY,QAAQ,sCAAsC;AACnE,SAASC,mBAAmB,QAAQ,0DAA0D;AAC9F,MAAMC,UAAU;AAChB,MAAMC,OAAO;IACXC,IAAI;IACJC,MAAM;IACNC,UAAU;IACVC,mBAAmBL;IACnBM,eAAe;AACjB;AAEAZ,SAAS,uBAAuB;IAC9BE,GAAG,uCAAuC;QACxC,MAAMW,QAAQ;YAAEC,UAAUX,GAAGY,EAAE;QAAG;QAClC,MAAMC,aAAa;YAAEC,QAAQd,GAAGY,EAAE,GAAGG,iBAAiB,CAACX;YAAOY,MAAMhB,GAAGY,EAAE;QAAG;QAC5E,MAAMK,SAAS;YAAEC,KAAKlB,GAAGY,EAAE;QAAG;QAC9B,MAAM,IAAIV,oBAAoB;YAAEW;YAAYH;YAAOO;QAAO,GAAGH,MAAM,CAAC;YAClER,MAAM;YACNa,KAAK;QACP;QACArB,OAAOY,MAAMC,QAAQ,EAAES,oBAAoB;QAC3CtB,OAAOe,WAAWC,MAAM,EAAEO,oBAAoB,CAAC;YAC7Cf,MAAM;YACNa,KAAK;YACLZ,UAAU;QACZ;IACF;IAEAR,GAAG,8CAA8C;QAC/C,MAAMc,aAAa;YACjBG,MAAMhB,GAAGY,EAAE;YACXU,SAAStB,GAAGY,EAAE,GAAGG,iBAAiB,CAACX;YACnCmB,YAAYvB,GACTY,EAAE,GACFY,qBAAqB,CAAC;gBAAEC,OAAOrB;gBAAMsB,OAAO;YAAM,GAClDF,qBAAqB,CAAC;gBAAEC,OAAO;oBAAE,GAAGrB,IAAI;oBAAEK,eAAe;gBAAU;gBAAGiB,OAAO;YAAM;YACtFC,uBAAuB3B,GAAGY,EAAE;YAC5BgB,aAAa5B,GAAGY,EAAE;QACpB;QACA,MAAMK,SAAS;YACbC,KAAKlB,GAAGY,EAAE,CAAC,OAAOiB;gBAChB,MAAMA,QAAQC,OAAO,CAAC;oBAAEC,KAAK;oBAAIC,WAAW;gBAAQ;gBACpD,OAAO;oBAAEC,WAAW9B;oBAAS+B,QAAQ;oBAAUC,UAAU;wBAAC;qBAAS;oBAAEC,UAAU;gBAAE;YACnF;QACF;QACA,MAAMC,UAAU,IAAInC,oBAAoB;YAAEW;YAAYH,OAAO;gBAAEC,UAAUX,GAAGY,EAAE;YAAG;YAAGK;QAAO;QAC3F,MAAMoB,QAAQC,IAAI,CAAC,YAAY;QAC/B,MAAMD,QAAQC,IAAI,CAAC,YAAY;QAC/BxC,OAAOe,WAAWe,WAAW,EAAEP,oBAAoB,CACjD,MACA,OACAvB,OAAOyC,gBAAgB,CAAC;YAAEC,QAAQ;YAAa/B,eAAe;QAAU;IAE5E;IAEAV,GAAG,gEAAgE;QACjE,MAAM6B,cAAc5B,GAAGY,EAAE;QACzB,MAAMC,aAAa;YACjBG,MAAMhB,GAAGY,EAAE;YACXU,SAAStB,GAAGY,EAAE,GAAGG,iBAAiB,CAACX;YACnCmB,YAAYvB,GAAGY,EAAE,GAAGG,iBAAiB,CAAC;gBAAEU,OAAOrB;gBAAMsB,OAAO;YAAM;YAClEC,uBAAuB3B,GAAGY,EAAE;YAC5BgB;QACF;QACA,MAAM9B,OACJ,IAAII,oBAAoB;YACtBW;YACAH,OAAO;gBAAEC,UAAUX,GAAGY,EAAE;YAAG;YAC3BK,QAAQ;gBAAEC,KAAKlB,GAAGY,EAAE,GAAG6B,iBAAiB,CAAC,IAAIxC,aAAa,OAAO;YAAwB;QAC3F,GAAGqC,IAAI,CAAC,YAAY,MACpBI,OAAO,CAACC,aAAa,CAAC;YAAEC,MAAM;QAAsB;QACtD9C,OAAO8B,aAAaP,oBAAoB,CACtC,MACA,OACAvB,OAAOyC,gBAAgB,CAAC;YAAE9B,eAAe;QAAW;QAEtD,MAAMoC,kBAAkB;YACtB,GAAGhC,UAAU;YACbS,SAAStB,GAAGY,EAAE,GAAGY,qBAAqB,CAAC,MAAMA,qBAAqB,CAAC;gBAACpB;gBAAMA;aAAK;YAC/EmB,YAAYvB,GAAGY,EAAE;QACnB;QACA,MAAMkC,QAAQ,IAAI5C,oBAAoB;YACpCW,YAAYgC;YACZnC,OAAO;gBAAEC,UAAUX,GAAGY,EAAE;YAAG;YAC3BK,QAAQ;gBAAEC,KAAKlB,GAAGY,EAAE;YAAG;QACzB;QACA,MAAMd,OAAOgD,MAAMR,IAAI,CAAC,WAAW,MAAMI,OAAO,CAACC,aAAa,CAAC;YAC7DC,MAAM;QACR;QACA,MAAM9C,OAAOgD,MAAMR,IAAI,CAAC,QAAQ,MAAMI,OAAO,CAACC,aAAa,CAAC;YAAEC,MAAM;QAAiB;IACvF;IAEA7C,GAAG,4DAA4D;QAC7D,MAAMc,aAAa;YACjBS,SAAStB,GAAGY,EAAE,GAAGG,iBAAiB,CAAC;gBAAE,GAAGX,IAAI;gBAAEG,UAAU;YAAS;YACjEgB,YAAYvB,GAAGY,EAAE;YACjBe,uBAAuB3B,GAAGY,EAAE;YAC5BgB,aAAa5B,GAAGY,EAAE;QACpB;QAEA,MAAMd,OACJ,IAAII,oBAAoB;YACtBW;YACAH,OAAO;gBAAEC,UAAUX,GAAGY,EAAE;YAAG;YAC3BK,QAAQ;gBAAEC,KAAKlB,GAAGY,EAAE;YAAG;QACzB,GAAG0B,IAAI,CAAC,YAAY,MACpBI,OAAO,CAACC,aAAa,CAAC;YAAEC,MAAM;QAAiB;QACjD9C,OAAOe,WAAWU,UAAU,EAAEwB,GAAG,CAACC,gBAAgB;QAClDlD,OAAOe,WAAWe,WAAW,EAAEmB,GAAG,CAACC,gBAAgB;IACrD;IAEAjD,GAAG,gFAAgF;QACjF,MAAMkD,oBAAoB,IAAIC,MAAM;QACpC,MAAMrC,aAAa;YACjBS,SAAStB,GAAGY,EAAE,GAAGG,iBAAiB,CAACX;YACnCmB,YAAYvB,GAAGY,EAAE,GAAGG,iBAAiB,CAAC;gBAAEU,OAAOrB;gBAAMsB,OAAO;YAAM;YAClEC,uBAAuB3B,GAAGY,EAAE;YAC5BgB,aAAa5B,GAAGY,EAAE,GAAG6B,iBAAiB,CAACQ;QACzC;QACA,MAAMhC,SAAS;YACbC,KAAKlB,GAAGY,EAAE,GAAGG,iBAAiB,CAAC;gBAC7BkB,WAAW9B;gBACX+B,QAAQ;gBACRC,UAAU;oBAAC;iBAAS;gBACpBC,UAAU;YACZ;QACF;QAEA,MAAMtC,OACJ,IAAII,oBAAoB;YAAEW;YAAYH,OAAO;gBAAEC,UAAUX,GAAGY,EAAE;YAAG;YAAGK;QAAO,GAAGqB,IAAI,CAChF,YACA,MAEFI,OAAO,CAACS,IAAI,CAACF;QACfnD,OAAOe,WAAWe,WAAW,EAAER,oBAAoB;IACrD;AACF"}
@@ -1,6 +1,7 @@
1
1
  import { EventEmitter } from "node:events";
2
2
  import { PassThrough, Writable } from "node:stream";
3
3
  import { describe, expect, it, vi } from "vitest";
4
+ import { PiPrintRunner } from "../../../../harnesses/pi/durable/PiPrintRunner.js";
4
5
  const SESSION = "22222222-2222-4222-8222-222222222222";
5
6
  function agent(sessionHealth = "uninitialized") {
6
7
  return {
@@ -87,10 +88,7 @@ function events(session = SESSION) {
87
88
  ];
88
89
  }
89
90
  async function runner(fixture, maxLineBytes) {
90
- const api = await import("../../../../index.js");
91
- expect(api).toHaveProperty("PiPrintRunner");
92
- const Runner = api.PiPrintRunner;
93
- return new Runner({
91
+ return new PiPrintRunner({
94
92
  spawn: fixture.spawn,
95
93
  maxLineBytes,
96
94
  processInspector: {
@@ -250,9 +248,7 @@ describe("PiPrintRunner", ()=>{
250
248
  code: "PI_PROCESS"
251
249
  });
252
250
  const fixture = fakeSpawn([]);
253
- const api = await import("../../../../index.js");
254
- const Runner = api.PiPrintRunner;
255
- await expect(new Runner({
251
+ await expect(new PiPrintRunner({
256
252
  spawn: fixture.spawn,
257
253
  processInspector: {
258
254
  getIdentity: ()=>null
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/__tests__/harnesses/pi/durable/PiPrintRunner.test.ts"],"sourcesContent":["import { EventEmitter } from \"node:events\";\nimport { PassThrough, Writable } from \"node:stream\";\nimport { describe, expect, it, vi } from \"vitest\";\nimport type { PiDurableAgent } from \"../../../../index.js\";\n\nconst SESSION = \"22222222-2222-4222-8222-222222222222\";\nfunction agent(sessionHealth: PiDurableAgent[\"sessionHealth\"] = \"uninitialized\"): PiDurableAgent {\n return {\n id: \"11111111-1111-4111-8111-111111111111\",\n name: \"reviewer\",\n provider: \"pi\",\n mode: \"durable\",\n cwd: \"/project\",\n providerSessionId: SESSION,\n state: \"running\",\n sessionHealth,\n createdAt: \"\",\n updatedAt: \"\",\n lastActiveAt: null,\n lastResult: null,\n activeRun: null,\n };\n}\nfunction fakeSpawn(lines: string[], exitCode = 0) {\n const promptChunks: Buffer[] = [];\n const child = new EventEmitter() as any;\n child.pid = 4242;\n child.stdout = new PassThrough();\n child.stderr = new PassThrough();\n child.kill = vi.fn();\n child.stdin = new Writable({\n write(chunk, _encoding, callback) {\n promptChunks.push(Buffer.from(chunk));\n callback();\n },\n final(callback) {\n child.stdout.end(lines.join(\"\\n\"));\n queueMicrotask(() => child.emit(\"close\", exitCode, null));\n callback();\n },\n });\n return { child, spawn: vi.fn(() => child), promptChunks };\n}\nfunction events(session = SESSION): string[] {\n return [\n JSON.stringify({ type: \"session\", version: 3, id: session, cwd: \"/project\" }),\n JSON.stringify({\n type: \"message_end\",\n message: { role: \"assistant\", content: [{ type: \"text\", text: \"first\" }] },\n }),\n JSON.stringify({\n type: \"message_end\",\n message: {\n role: \"assistant\",\n content: [\n { type: \"thinking\", thinking: \"hidden\" },\n { type: \"text\", text: \"final\" },\n ],\n },\n }),\n JSON.stringify({ type: \"agent_end\", messages: [] }),\n \"\",\n ];\n}\nasync function runner(fixture: ReturnType<typeof fakeSpawn>, maxLineBytes?: number) {\n const api = (await import(\"../../../../index.js\")) as Record<string, unknown>;\n expect(api).toHaveProperty(\"PiPrintRunner\");\n const Runner = api.PiPrintRunner as new (options: unknown) => any;\n return new Runner({\n spawn: fixture.spawn,\n maxLineBytes,\n processInspector: { getIdentity: () => ({ pid: 4242, startedAt: \"start\" }) },\n });\n}\n\ndescribe(\"PiPrintRunner\", () => {\n it(\"binds a first session and returns the last completed assistant text\", async () => {\n const fixture = fakeSpawn(events());\n const instance = await runner(fixture);\n const order: string[] = [];\n const result = await instance.run({\n agent: agent(),\n prompt: \"secret\",\n executable: \"fake-pi\",\n onSpawn: async () => {\n expect(fixture.promptChunks).toHaveLength(0);\n order.push(\"spawn\");\n },\n });\n expect(order).toEqual([\"spawn\"]);\n expect(fixture.spawn).toHaveBeenCalledWith(\n \"fake-pi\",\n [\"--mode\", \"json\", \"--session-id\", SESSION],\n expect.objectContaining({ cwd: \"/project\", shell: false }),\n );\n expect(Buffer.concat(fixture.promptChunks).toString()).toBe(\"secret\");\n expect(result).toEqual({\n sessionId: SESSION,\n result: \"final\",\n messages: [\"first\", \"final\"],\n exitCode: 0,\n });\n });\n\n it(\"resumes the exact stored session and rejects mismatch\", async () => {\n const fixture = fakeSpawn(events(\"33333333-3333-4333-8333-333333333333\"));\n await expect(\n (await runner(fixture)).run({ agent: agent(\"healthy\"), prompt: \"later\", onSpawn: vi.fn() }),\n ).rejects.toMatchObject({ code: \"PI_SESSION_MISMATCH\" });\n expect(fixture.spawn.mock.calls[0]![1]).toEqual([\"--mode\", \"json\", \"--session\", SESSION]);\n });\n\n it.each([\n [\"malformed\", [\"{bad\\n\"], \"PI_PROTOCOL\"],\n [\"non-object\", [\"[]\\n\"], \"PI_PROTOCOL\"],\n [\"truncated\", [\"{}\"], \"PI_PROTOCOL\"],\n [\"missing session\", [JSON.stringify({ type: \"agent_end\" }), \"\"], \"PI_PROTOCOL\"],\n [\n \"missing result\",\n [JSON.stringify({ type: \"session\", id: SESSION }), JSON.stringify({ type: \"agent_end\" }), \"\"],\n \"PI_RESULT_MISSING\",\n ],\n [\n \"missing end\",\n [\n JSON.stringify({ type: \"session\", id: SESSION }),\n JSON.stringify({\n type: \"message_end\",\n message: { role: \"assistant\", content: [{ type: \"text\", text: \"x\" }] },\n }),\n \"\",\n ],\n \"PI_PROTOCOL\",\n ],\n ])(\"rejects %s output\", async (_name, lines, code) => {\n await expect(\n (await runner(fakeSpawn(lines as string[]))).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n }),\n ).rejects.toMatchObject({ code });\n });\n\n it(\"rejects oversized output, failed processes, and unverifiable identities\", async () => {\n await expect(\n (await runner(fakeSpawn([\"x\".repeat(20)]), 10)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"PI_PROTOCOL\" });\n await expect(\n (await runner(fakeSpawn(events(), 1))).run({ agent: agent(), prompt: \"x\", onSpawn: vi.fn() }),\n ).rejects.toMatchObject({ code: \"PI_PROCESS\" });\n const fixture = fakeSpawn([]);\n const api = (await import(\"../../../../index.js\")) as Record<string, unknown>;\n const Runner = api.PiPrintRunner as new (options: unknown) => any;\n await expect(\n new Runner({ spawn: fixture.spawn, processInspector: { getIdentity: () => null } }).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"PI_PROCESS\" });\n expect(fixture.child.kill).toHaveBeenCalledOnce();\n });\n\n it(\"rejects invalid and duplicate session identities\", async () => {\n for (const lines of [\n [JSON.stringify({ type: \"session\", id: \"bad\" }), \"\"],\n [\n JSON.stringify({ type: \"session\", id: SESSION }),\n JSON.stringify({ type: \"session\", id: SESSION }),\n \"\",\n ],\n ])\n await expect(\n (await runner(fakeSpawn(lines))).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"PI_PROTOCOL\" });\n });\n\n it(\"kills on spawn persistence failure\", async () => {\n const spawnFailure = fakeSpawn([]);\n const failure = new Error(\"cannot persist\");\n await expect(\n (await runner(spawnFailure)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn().mockRejectedValue(failure),\n onSession: vi.fn(),\n }),\n ).rejects.toBe(failure);\n expect(spawnFailure.child.kill).toHaveBeenCalledOnce();\n });\n\n it(\"classifies spawn errors and a missing PID as process failures\", async () => {\n const errored = fakeSpawn([]);\n errored.child.stdin = new Writable({\n write(_chunk, _encoding, callback) {\n callback();\n },\n final(callback) {\n queueMicrotask(() => errored.child.emit(\"error\", new Error(\"spawn\")));\n callback();\n },\n });\n await expect(\n (await runner(errored)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"PI_PROCESS\" });\n const missing = fakeSpawn([]);\n missing.child.pid = undefined;\n await expect(\n (await runner(missing)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"PI_PROCESS\" });\n expect(missing.child.kill).toHaveBeenCalledOnce();\n });\n\n it(\"accepts string assistant content and ignores empty or unrelated messages\", async () => {\n const lines = [\n JSON.stringify({ type: \"session\", id: SESSION }),\n JSON.stringify({ type: \"future\" }),\n JSON.stringify({ type: \"message_end\", message: { role: \"user\", content: \"ignored\" } }),\n JSON.stringify({ type: \"message_end\", message: { role: \"assistant\", content: \" \" } }),\n JSON.stringify({ type: \"message_end\", message: { role: \"assistant\", content: \"answer\" } }),\n JSON.stringify({ type: \"agent_end\" }),\n \"\",\n ];\n await expect(\n (await runner(fakeSpawn(lines))).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).resolves.toMatchObject({ result: \"answer\" });\n });\n});\n"],"names":["EventEmitter","PassThrough","Writable","describe","expect","it","vi","SESSION","agent","sessionHealth","id","name","provider","mode","cwd","providerSessionId","state","createdAt","updatedAt","lastActiveAt","lastResult","activeRun","fakeSpawn","lines","exitCode","promptChunks","child","pid","stdout","stderr","kill","fn","stdin","write","chunk","_encoding","callback","push","Buffer","from","final","end","join","queueMicrotask","emit","spawn","events","session","JSON","stringify","type","version","message","role","content","text","thinking","messages","runner","fixture","maxLineBytes","api","toHaveProperty","Runner","PiPrintRunner","processInspector","getIdentity","startedAt","instance","order","result","run","prompt","executable","onSpawn","toHaveLength","toEqual","toHaveBeenCalledWith","objectContaining","shell","concat","toString","toBe","sessionId","rejects","toMatchObject","code","mock","calls","each","_name","repeat","toHaveBeenCalledOnce","onSession","spawnFailure","failure","Error","mockRejectedValue","errored","_chunk","missing","undefined","resolves"],"mappings":"AAAA,SAASA,YAAY,QAAQ,cAAc;AAC3C,SAASC,WAAW,EAAEC,QAAQ,QAAQ,cAAc;AACpD,SAASC,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ,SAAS;AAGlD,MAAMC,UAAU;AAChB,SAASC,MAAMC,gBAAiD,eAAe;IAC7E,OAAO;QACLC,IAAI;QACJC,MAAM;QACNC,UAAU;QACVC,MAAM;QACNC,KAAK;QACLC,mBAAmBR;QACnBS,OAAO;QACPP;QACAQ,WAAW;QACXC,WAAW;QACXC,cAAc;QACdC,YAAY;QACZC,WAAW;IACb;AACF;AACA,SAASC,UAAUC,KAAe,EAAEC,WAAW,CAAC;IAC9C,MAAMC,eAAyB,EAAE;IACjC,MAAMC,QAAQ,IAAI1B;IAClB0B,MAAMC,GAAG,GAAG;IACZD,MAAME,MAAM,GAAG,IAAI3B;IACnByB,MAAMG,MAAM,GAAG,IAAI5B;IACnByB,MAAMI,IAAI,GAAGxB,GAAGyB,EAAE;IAClBL,MAAMM,KAAK,GAAG,IAAI9B,SAAS;QACzB+B,OAAMC,KAAK,EAAEC,SAAS,EAAEC,QAAQ;YAC9BX,aAAaY,IAAI,CAACC,OAAOC,IAAI,CAACL;YAC9BE;QACF;QACAI,OAAMJ,QAAQ;YACZV,MAAME,MAAM,CAACa,GAAG,CAAClB,MAAMmB,IAAI,CAAC;YAC5BC,eAAe,IAAMjB,MAAMkB,IAAI,CAAC,SAASpB,UAAU;YACnDY;QACF;IACF;IACA,OAAO;QAAEV;QAAOmB,OAAOvC,GAAGyB,EAAE,CAAC,IAAML;QAAQD;IAAa;AAC1D;AACA,SAASqB,OAAOC,UAAUxC,OAAO;IAC/B,OAAO;QACLyC,KAAKC,SAAS,CAAC;YAAEC,MAAM;YAAWC,SAAS;YAAGzC,IAAIqC;YAASjC,KAAK;QAAW;QAC3EkC,KAAKC,SAAS,CAAC;YACbC,MAAM;YACNE,SAAS;gBAAEC,MAAM;gBAAaC,SAAS;oBAAC;wBAAEJ,MAAM;wBAAQK,MAAM;oBAAQ;iBAAE;YAAC;QAC3E;QACAP,KAAKC,SAAS,CAAC;YACbC,MAAM;YACNE,SAAS;gBACPC,MAAM;gBACNC,SAAS;oBACP;wBAAEJ,MAAM;wBAAYM,UAAU;oBAAS;oBACvC;wBAAEN,MAAM;wBAAQK,MAAM;oBAAQ;iBAC/B;YACH;QACF;QACAP,KAAKC,SAAS,CAAC;YAAEC,MAAM;YAAaO,UAAU,EAAE;QAAC;QACjD;KACD;AACH;AACA,eAAeC,OAAOC,OAAqC,EAAEC,YAAqB;IAChF,MAAMC,MAAO,MAAM,MAAM,CAAC;IAC1BzD,OAAOyD,KAAKC,cAAc,CAAC;IAC3B,MAAMC,SAASF,IAAIG,aAAa;IAChC,OAAO,IAAID,OAAO;QAChBlB,OAAOc,QAAQd,KAAK;QACpBe;QACAK,kBAAkB;YAAEC,aAAa,IAAO,CAAA;oBAAEvC,KAAK;oBAAMwC,WAAW;gBAAQ,CAAA;QAAG;IAC7E;AACF;AAEAhE,SAAS,iBAAiB;IACxBE,GAAG,uEAAuE;QACxE,MAAMsD,UAAUrC,UAAUwB;QAC1B,MAAMsB,WAAW,MAAMV,OAAOC;QAC9B,MAAMU,QAAkB,EAAE;QAC1B,MAAMC,SAAS,MAAMF,SAASG,GAAG,CAAC;YAChC/D,OAAOA;YACPgE,QAAQ;YACRC,YAAY;YACZC,SAAS;gBACPtE,OAAOuD,QAAQlC,YAAY,EAAEkD,YAAY,CAAC;gBAC1CN,MAAMhC,IAAI,CAAC;YACb;QACF;QACAjC,OAAOiE,OAAOO,OAAO,CAAC;YAAC;SAAQ;QAC/BxE,OAAOuD,QAAQd,KAAK,EAAEgC,oBAAoB,CACxC,WACA;YAAC;YAAU;YAAQ;YAAgBtE;SAAQ,EAC3CH,OAAO0E,gBAAgB,CAAC;YAAEhE,KAAK;YAAYiE,OAAO;QAAM;QAE1D3E,OAAOkC,OAAO0C,MAAM,CAACrB,QAAQlC,YAAY,EAAEwD,QAAQ,IAAIC,IAAI,CAAC;QAC5D9E,OAAOkE,QAAQM,OAAO,CAAC;YACrBO,WAAW5E;YACX+D,QAAQ;YACRb,UAAU;gBAAC;gBAAS;aAAQ;YAC5BjC,UAAU;QACZ;IACF;IAEAnB,GAAG,yDAAyD;QAC1D,MAAMsD,UAAUrC,UAAUwB,OAAO;QACjC,MAAM1C,OACJ,AAAC,CAAA,MAAMsD,OAAOC,QAAO,EAAGY,GAAG,CAAC;YAAE/D,OAAOA,MAAM;YAAYgE,QAAQ;YAASE,SAASpE,GAAGyB,EAAE;QAAG,IACzFqD,OAAO,CAACC,aAAa,CAAC;YAAEC,MAAM;QAAsB;QACtDlF,OAAOuD,QAAQd,KAAK,CAAC0C,IAAI,CAACC,KAAK,CAAC,EAAE,AAAC,CAAC,EAAE,EAAEZ,OAAO,CAAC;YAAC;YAAU;YAAQ;YAAarE;SAAQ;IAC1F;IAEAF,GAAGoF,IAAI,CAAC;QACN;YAAC;YAAa;gBAAC;aAAS;YAAE;SAAc;QACxC;YAAC;YAAc;gBAAC;aAAO;YAAE;SAAc;QACvC;YAAC;YAAa;gBAAC;aAAK;YAAE;SAAc;QACpC;YAAC;YAAmB;gBAACzC,KAAKC,SAAS,CAAC;oBAAEC,MAAM;gBAAY;gBAAI;aAAG;YAAE;SAAc;QAC/E;YACE;YACA;gBAACF,KAAKC,SAAS,CAAC;oBAAEC,MAAM;oBAAWxC,IAAIH;gBAAQ;gBAAIyC,KAAKC,SAAS,CAAC;oBAAEC,MAAM;gBAAY;gBAAI;aAAG;YAC7F;SACD;QACD;YACE;YACA;gBACEF,KAAKC,SAAS,CAAC;oBAAEC,MAAM;oBAAWxC,IAAIH;gBAAQ;gBAC9CyC,KAAKC,SAAS,CAAC;oBACbC,MAAM;oBACNE,SAAS;wBAAEC,MAAM;wBAAaC,SAAS;4BAAC;gCAAEJ,MAAM;gCAAQK,MAAM;4BAAI;yBAAE;oBAAC;gBACvE;gBACA;aACD;YACD;SACD;KACF,EAAE,qBAAqB,OAAOmC,OAAOnE,OAAO+D;QAC3C,MAAMlF,OACJ,AAAC,CAAA,MAAMsD,OAAOpC,UAAUC,OAAkB,EAAGgD,GAAG,CAAC;YAC/C/D,OAAOA;YACPgE,QAAQ;YACRE,SAASpE,GAAGyB,EAAE;QAChB,IACAqD,OAAO,CAACC,aAAa,CAAC;YAAEC;QAAK;IACjC;IAEAjF,GAAG,2EAA2E;QAC5E,MAAMD,OACJ,AAAC,CAAA,MAAMsD,OAAOpC,UAAU;YAAC,IAAIqE,MAAM,CAAC;SAAI,GAAG,GAAE,EAAGpB,GAAG,CAAC;YAClD/D,OAAOA;YACPgE,QAAQ;YACRE,SAASpE,GAAGyB,EAAE;QAChB,IACAqD,OAAO,CAACC,aAAa,CAAC;YAAEC,MAAM;QAAc;QAC9C,MAAMlF,OACJ,AAAC,CAAA,MAAMsD,OAAOpC,UAAUwB,UAAU,GAAE,EAAGyB,GAAG,CAAC;YAAE/D,OAAOA;YAASgE,QAAQ;YAAKE,SAASpE,GAAGyB,EAAE;QAAG,IAC3FqD,OAAO,CAACC,aAAa,CAAC;YAAEC,MAAM;QAAa;QAC7C,MAAM3B,UAAUrC,UAAU,EAAE;QAC5B,MAAMuC,MAAO,MAAM,MAAM,CAAC;QAC1B,MAAME,SAASF,IAAIG,aAAa;QAChC,MAAM5D,OACJ,IAAI2D,OAAO;YAAElB,OAAOc,QAAQd,KAAK;YAAEoB,kBAAkB;gBAAEC,aAAa,IAAM;YAAK;QAAE,GAAGK,GAAG,CAAC;YACtF/D,OAAOA;YACPgE,QAAQ;YACRE,SAASpE,GAAGyB,EAAE;QAChB,IACAqD,OAAO,CAACC,aAAa,CAAC;YAAEC,MAAM;QAAa;QAC7ClF,OAAOuD,QAAQjC,KAAK,CAACI,IAAI,EAAE8D,oBAAoB;IACjD;IAEAvF,GAAG,oDAAoD;QACrD,KAAK,MAAMkB,SAAS;YAClB;gBAACyB,KAAKC,SAAS,CAAC;oBAAEC,MAAM;oBAAWxC,IAAI;gBAAM;gBAAI;aAAG;YACpD;gBACEsC,KAAKC,SAAS,CAAC;oBAAEC,MAAM;oBAAWxC,IAAIH;gBAAQ;gBAC9CyC,KAAKC,SAAS,CAAC;oBAAEC,MAAM;oBAAWxC,IAAIH;gBAAQ;gBAC9C;aACD;SACF,CACC,MAAMH,OACJ,AAAC,CAAA,MAAMsD,OAAOpC,UAAUC,OAAM,EAAGgD,GAAG,CAAC;YACnC/D,OAAOA;YACPgE,QAAQ;YACRE,SAASpE,GAAGyB,EAAE;YACd8D,WAAWvF,GAAGyB,EAAE;QAClB,IACAqD,OAAO,CAACC,aAAa,CAAC;YAAEC,MAAM;QAAc;IAClD;IAEAjF,GAAG,sCAAsC;QACvC,MAAMyF,eAAexE,UAAU,EAAE;QACjC,MAAMyE,UAAU,IAAIC,MAAM;QAC1B,MAAM5F,OACJ,AAAC,CAAA,MAAMsD,OAAOoC,aAAY,EAAGvB,GAAG,CAAC;YAC/B/D,OAAOA;YACPgE,QAAQ;YACRE,SAASpE,GAAGyB,EAAE,GAAGkE,iBAAiB,CAACF;YACnCF,WAAWvF,GAAGyB,EAAE;QAClB,IACAqD,OAAO,CAACF,IAAI,CAACa;QACf3F,OAAO0F,aAAapE,KAAK,CAACI,IAAI,EAAE8D,oBAAoB;IACtD;IAEAvF,GAAG,iEAAiE;QAClE,MAAM6F,UAAU5E,UAAU,EAAE;QAC5B4E,QAAQxE,KAAK,CAACM,KAAK,GAAG,IAAI9B,SAAS;YACjC+B,OAAMkE,MAAM,EAAEhE,SAAS,EAAEC,QAAQ;gBAC/BA;YACF;YACAI,OAAMJ,QAAQ;gBACZO,eAAe,IAAMuD,QAAQxE,KAAK,CAACkB,IAAI,CAAC,SAAS,IAAIoD,MAAM;gBAC3D5D;YACF;QACF;QACA,MAAMhC,OACJ,AAAC,CAAA,MAAMsD,OAAOwC,QAAO,EAAG3B,GAAG,CAAC;YAC1B/D,OAAOA;YACPgE,QAAQ;YACRE,SAASpE,GAAGyB,EAAE;YACd8D,WAAWvF,GAAGyB,EAAE;QAClB,IACAqD,OAAO,CAACC,aAAa,CAAC;YAAEC,MAAM;QAAa;QAC7C,MAAMc,UAAU9E,UAAU,EAAE;QAC5B8E,QAAQ1E,KAAK,CAACC,GAAG,GAAG0E;QACpB,MAAMjG,OACJ,AAAC,CAAA,MAAMsD,OAAO0C,QAAO,EAAG7B,GAAG,CAAC;YAC1B/D,OAAOA;YACPgE,QAAQ;YACRE,SAASpE,GAAGyB,EAAE;YACd8D,WAAWvF,GAAGyB,EAAE;QAClB,IACAqD,OAAO,CAACC,aAAa,CAAC;YAAEC,MAAM;QAAa;QAC7ClF,OAAOgG,QAAQ1E,KAAK,CAACI,IAAI,EAAE8D,oBAAoB;IACjD;IAEAvF,GAAG,4EAA4E;QAC7E,MAAMkB,QAAQ;YACZyB,KAAKC,SAAS,CAAC;gBAAEC,MAAM;gBAAWxC,IAAIH;YAAQ;YAC9CyC,KAAKC,SAAS,CAAC;gBAAEC,MAAM;YAAS;YAChCF,KAAKC,SAAS,CAAC;gBAAEC,MAAM;gBAAeE,SAAS;oBAAEC,MAAM;oBAAQC,SAAS;gBAAU;YAAE;YACpFN,KAAKC,SAAS,CAAC;gBAAEC,MAAM;gBAAeE,SAAS;oBAAEC,MAAM;oBAAaC,SAAS;gBAAI;YAAE;YACnFN,KAAKC,SAAS,CAAC;gBAAEC,MAAM;gBAAeE,SAAS;oBAAEC,MAAM;oBAAaC,SAAS;gBAAS;YAAE;YACxFN,KAAKC,SAAS,CAAC;gBAAEC,MAAM;YAAY;YACnC;SACD;QACD,MAAM9C,OACJ,AAAC,CAAA,MAAMsD,OAAOpC,UAAUC,OAAM,EAAGgD,GAAG,CAAC;YACnC/D,OAAOA;YACPgE,QAAQ;YACRE,SAASpE,GAAGyB,EAAE;YACd8D,WAAWvF,GAAGyB,EAAE;QAClB,IACAuE,QAAQ,CAACjB,aAAa,CAAC;YAAEf,QAAQ;QAAS;IAC9C;AACF"}
1
+ {"version":3,"sources":["../../../../../src/__tests__/harnesses/pi/durable/PiPrintRunner.test.ts"],"sourcesContent":["import { EventEmitter } from \"node:events\";\nimport { PassThrough, Writable } from \"node:stream\";\nimport { describe, expect, it, vi } from \"vitest\";\nimport type { PiDurableAgent } from \"../../../../durable/DurableAgent.js\";\nimport { PiPrintRunner } from \"../../../../harnesses/pi/durable/PiPrintRunner.js\";\n\nconst SESSION = \"22222222-2222-4222-8222-222222222222\";\nfunction agent(sessionHealth: PiDurableAgent[\"sessionHealth\"] = \"uninitialized\"): PiDurableAgent {\n return {\n id: \"11111111-1111-4111-8111-111111111111\",\n name: \"reviewer\",\n provider: \"pi\",\n mode: \"durable\",\n cwd: \"/project\",\n providerSessionId: SESSION,\n state: \"running\",\n sessionHealth,\n createdAt: \"\",\n updatedAt: \"\",\n lastActiveAt: null,\n lastResult: null,\n activeRun: null,\n };\n}\nfunction fakeSpawn(lines: string[], exitCode = 0) {\n const promptChunks: Buffer[] = [];\n const child = new EventEmitter() as any;\n child.pid = 4242;\n child.stdout = new PassThrough();\n child.stderr = new PassThrough();\n child.kill = vi.fn();\n child.stdin = new Writable({\n write(chunk, _encoding, callback) {\n promptChunks.push(Buffer.from(chunk));\n callback();\n },\n final(callback) {\n child.stdout.end(lines.join(\"\\n\"));\n queueMicrotask(() => child.emit(\"close\", exitCode, null));\n callback();\n },\n });\n return { child, spawn: vi.fn(() => child), promptChunks };\n}\nfunction events(session = SESSION): string[] {\n return [\n JSON.stringify({ type: \"session\", version: 3, id: session, cwd: \"/project\" }),\n JSON.stringify({\n type: \"message_end\",\n message: { role: \"assistant\", content: [{ type: \"text\", text: \"first\" }] },\n }),\n JSON.stringify({\n type: \"message_end\",\n message: {\n role: \"assistant\",\n content: [\n { type: \"thinking\", thinking: \"hidden\" },\n { type: \"text\", text: \"final\" },\n ],\n },\n }),\n JSON.stringify({ type: \"agent_end\", messages: [] }),\n \"\",\n ];\n}\nasync function runner(fixture: ReturnType<typeof fakeSpawn>, maxLineBytes?: number) {\n return new PiPrintRunner({\n spawn: fixture.spawn,\n maxLineBytes,\n processInspector: { getIdentity: () => ({ pid: 4242, startedAt: \"start\" }) },\n });\n}\n\ndescribe(\"PiPrintRunner\", () => {\n it(\"binds a first session and returns the last completed assistant text\", async () => {\n const fixture = fakeSpawn(events());\n const instance = await runner(fixture);\n const order: string[] = [];\n const result = await instance.run({\n agent: agent(),\n prompt: \"secret\",\n executable: \"fake-pi\",\n onSpawn: async () => {\n expect(fixture.promptChunks).toHaveLength(0);\n order.push(\"spawn\");\n },\n });\n expect(order).toEqual([\"spawn\"]);\n expect(fixture.spawn).toHaveBeenCalledWith(\n \"fake-pi\",\n [\"--mode\", \"json\", \"--session-id\", SESSION],\n expect.objectContaining({ cwd: \"/project\", shell: false }),\n );\n expect(Buffer.concat(fixture.promptChunks).toString()).toBe(\"secret\");\n expect(result).toEqual({\n sessionId: SESSION,\n result: \"final\",\n messages: [\"first\", \"final\"],\n exitCode: 0,\n });\n });\n\n it(\"resumes the exact stored session and rejects mismatch\", async () => {\n const fixture = fakeSpawn(events(\"33333333-3333-4333-8333-333333333333\"));\n await expect(\n (await runner(fixture)).run({ agent: agent(\"healthy\"), prompt: \"later\", onSpawn: vi.fn() }),\n ).rejects.toMatchObject({ code: \"PI_SESSION_MISMATCH\" });\n expect(fixture.spawn.mock.calls[0]![1]).toEqual([\"--mode\", \"json\", \"--session\", SESSION]);\n });\n\n it.each([\n [\"malformed\", [\"{bad\\n\"], \"PI_PROTOCOL\"],\n [\"non-object\", [\"[]\\n\"], \"PI_PROTOCOL\"],\n [\"truncated\", [\"{}\"], \"PI_PROTOCOL\"],\n [\"missing session\", [JSON.stringify({ type: \"agent_end\" }), \"\"], \"PI_PROTOCOL\"],\n [\n \"missing result\",\n [JSON.stringify({ type: \"session\", id: SESSION }), JSON.stringify({ type: \"agent_end\" }), \"\"],\n \"PI_RESULT_MISSING\",\n ],\n [\n \"missing end\",\n [\n JSON.stringify({ type: \"session\", id: SESSION }),\n JSON.stringify({\n type: \"message_end\",\n message: { role: \"assistant\", content: [{ type: \"text\", text: \"x\" }] },\n }),\n \"\",\n ],\n \"PI_PROTOCOL\",\n ],\n ])(\"rejects %s output\", async (_name, lines, code) => {\n await expect(\n (await runner(fakeSpawn(lines as string[]))).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n }),\n ).rejects.toMatchObject({ code });\n });\n\n it(\"rejects oversized output, failed processes, and unverifiable identities\", async () => {\n await expect(\n (await runner(fakeSpawn([\"x\".repeat(20)]), 10)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"PI_PROTOCOL\" });\n await expect(\n (await runner(fakeSpawn(events(), 1))).run({ agent: agent(), prompt: \"x\", onSpawn: vi.fn() }),\n ).rejects.toMatchObject({ code: \"PI_PROCESS\" });\n const fixture = fakeSpawn([]);\n await expect(\n new PiPrintRunner({\n spawn: fixture.spawn,\n processInspector: { getIdentity: () => null },\n }).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"PI_PROCESS\" });\n expect(fixture.child.kill).toHaveBeenCalledOnce();\n });\n\n it(\"rejects invalid and duplicate session identities\", async () => {\n for (const lines of [\n [JSON.stringify({ type: \"session\", id: \"bad\" }), \"\"],\n [\n JSON.stringify({ type: \"session\", id: SESSION }),\n JSON.stringify({ type: \"session\", id: SESSION }),\n \"\",\n ],\n ])\n await expect(\n (await runner(fakeSpawn(lines))).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"PI_PROTOCOL\" });\n });\n\n it(\"kills on spawn persistence failure\", async () => {\n const spawnFailure = fakeSpawn([]);\n const failure = new Error(\"cannot persist\");\n await expect(\n (await runner(spawnFailure)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn().mockRejectedValue(failure),\n onSession: vi.fn(),\n }),\n ).rejects.toBe(failure);\n expect(spawnFailure.child.kill).toHaveBeenCalledOnce();\n });\n\n it(\"classifies spawn errors and a missing PID as process failures\", async () => {\n const errored = fakeSpawn([]);\n errored.child.stdin = new Writable({\n write(_chunk, _encoding, callback) {\n callback();\n },\n final(callback) {\n queueMicrotask(() => errored.child.emit(\"error\", new Error(\"spawn\")));\n callback();\n },\n });\n await expect(\n (await runner(errored)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"PI_PROCESS\" });\n const missing = fakeSpawn([]);\n missing.child.pid = undefined;\n await expect(\n (await runner(missing)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"PI_PROCESS\" });\n expect(missing.child.kill).toHaveBeenCalledOnce();\n });\n\n it(\"accepts string assistant content and ignores empty or unrelated messages\", async () => {\n const lines = [\n JSON.stringify({ type: \"session\", id: SESSION }),\n JSON.stringify({ type: \"future\" }),\n JSON.stringify({ type: \"message_end\", message: { role: \"user\", content: \"ignored\" } }),\n JSON.stringify({ type: \"message_end\", message: { role: \"assistant\", content: \" \" } }),\n JSON.stringify({ type: \"message_end\", message: { role: \"assistant\", content: \"answer\" } }),\n JSON.stringify({ type: \"agent_end\" }),\n \"\",\n ];\n await expect(\n (await runner(fakeSpawn(lines))).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).resolves.toMatchObject({ result: \"answer\" });\n });\n});\n"],"names":["EventEmitter","PassThrough","Writable","describe","expect","it","vi","PiPrintRunner","SESSION","agent","sessionHealth","id","name","provider","mode","cwd","providerSessionId","state","createdAt","updatedAt","lastActiveAt","lastResult","activeRun","fakeSpawn","lines","exitCode","promptChunks","child","pid","stdout","stderr","kill","fn","stdin","write","chunk","_encoding","callback","push","Buffer","from","final","end","join","queueMicrotask","emit","spawn","events","session","JSON","stringify","type","version","message","role","content","text","thinking","messages","runner","fixture","maxLineBytes","processInspector","getIdentity","startedAt","instance","order","result","run","prompt","executable","onSpawn","toHaveLength","toEqual","toHaveBeenCalledWith","objectContaining","shell","concat","toString","toBe","sessionId","rejects","toMatchObject","code","mock","calls","each","_name","repeat","toHaveBeenCalledOnce","onSession","spawnFailure","failure","Error","mockRejectedValue","errored","_chunk","missing","undefined","resolves"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import path from "node:path";
2
2
  import { describe, expect, it, vi } from "vitest";
3
- import { AGENTS, getAgentReadinessReport, getAgentReadinessReports } from "../../index.js";
3
+ import { getAgentReadinessReport, getAgentReadinessReports } from "../../../harnesses/readiness/AgentReadiness.js";
4
+ import { HARNESS_RUNTIME_PROFILES } from "../../../harnesses/runtimeProfiles.js";
4
5
  const builtInSkillNames = [
5
6
  "agent-management",
6
7
  "memory",
@@ -10,7 +11,9 @@ const skillRoots = {
10
11
  claude: ".claude/skills",
11
12
  codex: ".codex/skills",
12
13
  copilot: ".copilot/skills",
14
+ gemini_cli: ".gemini/skills",
13
15
  grok_cli: ".grok/skills",
16
+ antigravity_cli: ".gemini/config/skills",
14
17
  opencode: ".config/opencode/skill",
15
18
  pi: ".pi/agent/skills"
16
19
  };
@@ -74,7 +77,10 @@ function fixture(overrides = {}) {
74
77
  ".claude",
75
78
  ".codex",
76
79
  ".copilot",
80
+ ".gemini",
77
81
  ".grok",
82
+ ".kiro",
83
+ ".gemini/antigravity-cli",
78
84
  ".config/opencode",
79
85
  ".pi"
80
86
  ]){
@@ -85,7 +91,7 @@ function fixture(overrides = {}) {
85
91
  files[path.join(homeDir, root, skill, "SKILL.md")] = "# skill";
86
92
  }
87
93
  }
88
- const executablePaths = Object.values(AGENTS).map((agent)=>path.join("/bin", agent.command));
94
+ const executablePaths = Object.values(HARNESS_RUNTIME_PROFILES).map((agent)=>path.join("/bin", agent.command));
89
95
  const options = {
90
96
  homeDir,
91
97
  path: "/bin",
@@ -136,22 +142,34 @@ describe("agent readiness", ()=>{
136
142
  expect(Object.keys(reports)).toEqual([
137
143
  "claude",
138
144
  "codex",
139
- "copilot",
145
+ "gemini_cli",
140
146
  "grok_cli",
147
+ "kiro",
148
+ "antigravity_cli",
141
149
  "opencode",
150
+ "copilot",
142
151
  "pi"
143
152
  ]);
144
- expect(reports).not.toHaveProperty("gemini_cli");
145
153
  for (const [agent, report] of Object.entries(reports)){
146
154
  expect(report.type).toBe(agent);
147
155
  expect(report.executable.status).toBe("pass");
148
156
  expect(report.globalConfig.status).toBe("pass");
149
- expect(report.builtInSkills).toMatchObject({
150
- status: "info",
151
- present: 3,
152
- required: 3
153
- });
157
+ expect(report.builtInSkills.status).toBe("info");
154
158
  }
159
+ expect(reports.gemini_cli.builtInSkills).toMatchObject({
160
+ present: 3,
161
+ required: 3
162
+ });
163
+ expect(reports.antigravity_cli.builtInSkills).toMatchObject({
164
+ present: 3,
165
+ required: 3
166
+ });
167
+ expect(reports.kiro.builtInSkills).toMatchObject({
168
+ path: null,
169
+ present: 0,
170
+ required: 3,
171
+ missing: builtInSkillNames
172
+ });
155
173
  expect(reports.codex.integration).toMatchObject({
156
174
  label: "ai-devkit hook",
157
175
  installed: true,
@@ -168,12 +186,15 @@ describe("agent readiness", ()=>{
168
186
  status: "pass"
169
187
  });
170
188
  expect(reports.copilot.integration).toBeUndefined();
189
+ expect(reports.gemini_cli.integration).toBeUndefined();
171
190
  expect(reports.grok_cli.integration).toBeUndefined();
191
+ expect(reports.kiro.integration).toBeUndefined();
192
+ expect(reports.antigravity_cli.integration).toBeUndefined();
172
193
  expect(reports.opencode.integration).toBeUndefined();
173
194
  });
174
195
  it("resolves agent executables from PATH directories containing spaces", async ()=>{
175
196
  const spacedBin = "/Applications/Some App.app/Contents/Resources";
176
- const codexPath = path.join(spacedBin, AGENTS.codex.command);
197
+ const codexPath = path.join(spacedBin, HARNESS_RUNTIME_PROFILES.codex.command);
177
198
  const { options } = fixture({
178
199
  path: [
179
200
  spacedBin,
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/__tests__/harnesses/readiness/AgentReadiness.test.ts"],"sourcesContent":["import path from \"node:path\";\nimport { describe, expect, it, vi } from \"vitest\";\nimport {\n getAgentReadinessReport,\n getAgentReadinessReports,\n type AgentReadinessOptions,\n type ReadinessAgentType,\n} from \"../../../harnesses/readiness/AgentReadiness.js\";\nimport { HARNESS_RUNTIME_PROFILES } from \"../../../harnesses/runtimeProfiles.js\";\n\ntype Files = Record<string, string>;\n\nconst builtInSkillNames = [\"agent-management\", \"memory\", \"verify\"];\nconst skillRoots: Record<string, string> = {\n claude: \".claude/skills\",\n codex: \".codex/skills\",\n copilot: \".copilot/skills\",\n gemini_cli: \".gemini/skills\",\n grok_cli: \".grok/skills\",\n antigravity_cli: \".gemini/config/skills\",\n opencode: \".config/opencode/skill\",\n pi: \".pi/agent/skills\",\n};\n\nfunction fixture(overrides: Partial<AgentReadinessOptions> = {}) {\n const homeDir = \"/home/test\";\n const assetRoot = \"/assets\";\n const files: Files = {\n [path.join(homeDir, \".codex\", \"hooks\", \"codex-session-mapping.cjs\")]: \"codex-hook\",\n [path.join(assetRoot, \"codex\", \"codex-session-mapping.cjs\")]: \"codex-hook\",\n [path.join(homeDir, \".codex\", \"hooks.json\")]: JSON.stringify({\n hooks: {\n SessionStart: [\n {\n hooks: [{ type: \"command\", command: \"node ~/.codex/hooks/codex-session-mapping.cjs\" }],\n },\n ],\n },\n }),\n [path.join(homeDir, \".codex\", \"ai-devkit\", \"sessions.json\")]: JSON.stringify({\n \"123\": \"/sessions/codex.jsonl\",\n }),\n \"/sessions/codex.jsonl\": \"\",\n [path.join(homeDir, \".claude\", \"hooks\", \"claude-prompt-hook.js\")]: \"claude-hook\",\n [path.join(assetRoot, \"claude\", \"claude-prompt-hook.js\")]: \"claude-hook\",\n [path.join(homeDir, \".claude\", \"settings.json\")]: JSON.stringify({\n hooks: {\n PreToolUse: [\n { hooks: [{ type: \"command\", command: \"node ~/.claude/hooks/claude-prompt-hook.js\" }] },\n ],\n },\n }),\n [path.join(homeDir, \".pi\", \"agent\", \"sessions.json\")]: JSON.stringify({\n \"456\": \"/sessions/missing-pi.jsonl\",\n }),\n [path.join(homeDir, \".pi\", \"agent\", \"auth.json\")]: JSON.stringify({\n anthropic: { access: \"access-secret\", refresh: \"refresh-secret\" },\n litellm: { key: \"litellm-secret\", env: { LITELLM_BASE_URL: \"https://litellm.example.test\" } },\n }),\n };\n for (const directory of [\n \".claude\",\n \".codex\",\n \".copilot\",\n \".gemini\",\n \".grok\",\n \".kiro\",\n \".gemini/antigravity-cli\",\n \".config/opencode\",\n \".pi\",\n ]) {\n files[path.join(homeDir, directory)] = \"<dir>\";\n }\n for (const root of Object.values(skillRoots)) {\n for (const skill of builtInSkillNames) {\n files[path.join(homeDir, root, skill, \"SKILL.md\")] = \"# skill\";\n }\n }\n const executablePaths = Object.values(HARNESS_RUNTIME_PROFILES).map((agent) =>\n path.join(\"/bin\", agent.command),\n );\n const options: AgentReadinessOptions = {\n homeDir,\n path: \"/bin\",\n assetRoot,\n builtInSkillNames,\n skillRoots,\n readFile: async (target) => {\n if (!(target in files)) throw new Error(\"missing\");\n return files[target];\n },\n access: async (target) => {\n if (executablePaths.includes(target) || target in files) return;\n throw new Error(\"missing\");\n },\n runCommand: vi.fn(async (command) => {\n if (command === \"pi\") return { stdout: \"npm:@ai-devkit/pi-session-tracker\\n\", stderr: \"\" };\n if (command === \"claude\") return { stdout: JSON.stringify({ loggedIn: true }), stderr: \"\" };\n if (command === \"gh\")\n return { stdout: \"github.com\\n Logged in to github.com account test-user\\n\", stderr: \"\" };\n if (command === \"opencode\")\n return { stdout: \"● litellm api\\n● OpenAI oauth\\n\", stderr: \"\" };\n throw new Error(`unexpected command ${command}`);\n }),\n codexAuth: async () => true,\n ...overrides,\n };\n return { options, files };\n}\n\ndescribe(\"agent readiness\", () => {\n it(\"reports every readiness-supported adapter with generic checks and only real integrations\", async () => {\n const { options } = fixture();\n\n const reports = await getAgentReadinessReports(options);\n\n expect(Object.keys(reports)).toEqual([\n \"claude\",\n \"codex\",\n \"gemini_cli\",\n \"grok_cli\",\n \"kiro\",\n \"antigravity_cli\",\n \"opencode\",\n \"copilot\",\n \"pi\",\n ]);\n for (const [agent, report] of Object.entries(reports) as Array<\n [ReadinessAgentType, (typeof reports)[ReadinessAgentType]]\n >) {\n expect(report.type).toBe(agent);\n expect(report.executable.status).toBe(\"pass\");\n expect(report.globalConfig.status).toBe(\"pass\");\n expect(report.builtInSkills.status).toBe(\"info\");\n }\n expect(reports.gemini_cli.builtInSkills).toMatchObject({ present: 3, required: 3 });\n expect(reports.antigravity_cli.builtInSkills).toMatchObject({ present: 3, required: 3 });\n expect(reports.kiro.builtInSkills).toMatchObject({\n path: null,\n present: 0,\n required: 3,\n missing: builtInSkillNames,\n });\n expect(reports.codex.integration).toMatchObject({\n label: \"ai-devkit hook\",\n installed: true,\n status: \"pass\",\n });\n expect(reports.claude.integration).toMatchObject({\n label: \"ai-devkit hook\",\n installed: true,\n status: \"pass\",\n });\n expect(reports.pi.integration).toMatchObject({\n label: \"ai-devkit plugin\",\n installed: true,\n status: \"pass\",\n });\n expect(reports.copilot.integration).toBeUndefined();\n expect(reports.gemini_cli.integration).toBeUndefined();\n expect(reports.grok_cli.integration).toBeUndefined();\n expect(reports.kiro.integration).toBeUndefined();\n expect(reports.antigravity_cli.integration).toBeUndefined();\n expect(reports.opencode.integration).toBeUndefined();\n });\n\n it(\"resolves agent executables from PATH directories containing spaces\", async () => {\n const spacedBin = \"/Applications/Some App.app/Contents/Resources\";\n const codexPath = path.join(spacedBin, HARNESS_RUNTIME_PROFILES.codex.command);\n const { options } = fixture({\n path: [spacedBin, \"/usr/local/bin\"].join(path.delimiter),\n access: async (target) => {\n if (target === codexPath || target.startsWith(\"/home/test\")) return;\n throw new Error(\"missing\");\n },\n });\n\n const report = await getAgentReadinessReport(\"codex\", options);\n\n expect(report.executable).toMatchObject({ command: \"codex\", path: codexPath, status: \"pass\" });\n });\n\n it(\"parses Pi provider names without returning credential values\", async () => {\n const { options } = fixture();\n\n const report = await getAgentReadinessReport(\"pi\", options);\n const serialized = JSON.stringify(report);\n\n expect(report.auth).toMatchObject({\n state: \"authenticated\",\n provider: null,\n availableProviders: [\"anthropic\", \"litellm\"],\n status: \"pass\",\n });\n expect(serialized).not.toContain(\"access-secret\");\n expect(serialized).not.toContain(\"refresh-secret\");\n expect(serialized).not.toContain(\"litellm-secret\");\n expect(serialized).not.toContain(\"litellm.example.test\");\n });\n\n it(\"accepts Pi session tracker display names from pi list output\", async () => {\n const { options } = fixture({\n runCommand: vi.fn(async (command) => {\n if (command === \"pi\") return { stdout: \"session tracker\\n\", stderr: \"\" };\n if (command === \"claude\") return { stdout: JSON.stringify({ loggedIn: true }), stderr: \"\" };\n throw new Error(`unexpected command ${command}`);\n }),\n });\n\n const report = await getAgentReadinessReport(\"pi\", options);\n\n expect(report.integration).toMatchObject({\n label: \"ai-devkit plugin\",\n installed: true,\n status: \"pass\",\n });\n });\n\n it(\"reports missing built-in skills as informational readiness\", async () => {\n const { options, files } = fixture();\n delete files[path.join(options.homeDir!, skillRoots.codex, \"verify\", \"SKILL.md\")];\n\n const report = await getAgentReadinessReport(\"codex\", options);\n\n expect(report.builtInSkills).toMatchObject({\n status: \"info\",\n present: 2,\n required: 3,\n missing: [\"verify\"],\n });\n expect(report.status).toBe(\"pass\");\n });\n\n it(\"checks OpenCode auth from auth list output\", async () => {\n const { options } = fixture({\n runCommand: vi.fn(async (command) => {\n if (command === \"opencode\") {\n return {\n stdout: \"\\x1B[32m●\\x1B[0m litellm api\\n● OpenAI oauth\\n● GitLab Duo GITLAB_TOKEN\\n\",\n stderr: \"\",\n };\n }\n if (command === \"pi\") return { stdout: \"npm:@ai-devkit/pi-session-tracker\\n\", stderr: \"\" };\n if (command === \"claude\") return { stdout: JSON.stringify({ loggedIn: true }), stderr: \"\" };\n throw new Error(`unexpected command ${command}`);\n }),\n });\n\n const report = await getAgentReadinessReport(\"opencode\", options);\n\n expect(report.auth).toMatchObject({\n state: \"authenticated\",\n source: \"opencode auth list\",\n provider: null,\n availableProviders: [\"GitLab Duo\", \"OpenAI\", \"litellm\"],\n status: \"pass\",\n });\n });\n\n it(\"checks Copilot auth through GitHub CLI authentication\", async () => {\n const { options } = fixture({\n runCommand: vi.fn(async (command) => {\n if (command === \"gh\")\n return {\n stdout: \"github.com\\n Logged in to github.com account test-user\\n\",\n stderr: \"\",\n };\n if (command === \"pi\") return { stdout: \"npm:@ai-devkit/pi-session-tracker\\n\", stderr: \"\" };\n if (command === \"claude\") return { stdout: JSON.stringify({ loggedIn: true }), stderr: \"\" };\n if (command === \"opencode\") return { stdout: \"● litellm api\\n\", stderr: \"\" };\n throw new Error(`unexpected command ${command}`);\n }),\n });\n\n const report = await getAgentReadinessReport(\"copilot\", options);\n\n expect(report.auth).toMatchObject({\n state: \"authenticated\",\n source: \"gh auth status --hostname github.com\",\n provider: \"github\",\n availableProviders: [\"GitHub\"],\n status: \"pass\",\n });\n });\n});\n"],"names":["path","describe","expect","it","vi","getAgentReadinessReport","getAgentReadinessReports","HARNESS_RUNTIME_PROFILES","builtInSkillNames","skillRoots","claude","codex","copilot","gemini_cli","grok_cli","antigravity_cli","opencode","pi","fixture","overrides","homeDir","assetRoot","files","join","JSON","stringify","hooks","SessionStart","type","command","PreToolUse","anthropic","access","refresh","litellm","key","env","LITELLM_BASE_URL","directory","root","Object","values","skill","executablePaths","map","agent","options","readFile","target","Error","includes","runCommand","fn","stdout","stderr","loggedIn","codexAuth","reports","keys","toEqual","report","entries","toBe","executable","status","globalConfig","builtInSkills","toMatchObject","present","required","kiro","missing","integration","label","installed","toBeUndefined","spacedBin","codexPath","delimiter","startsWith","serialized","auth","state","provider","availableProviders","not","toContain","source"],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
5
+ import { HARNESS_RUNTIME_PROFILES, runtimeAgentMatchesHarness } from "../../harnesses/runtimeProfiles.js";
6
+ describe("harness runtime profiles", ()=>{
7
+ it("keeps launch and runtime identity metadata together", ()=>{
8
+ expect(HARNESS_RUNTIME_PROFILES.antigravity_cli).toMatchObject({
9
+ command: "agy",
10
+ runtimeKind: "agy",
11
+ discoveryAliases: [
12
+ "agy",
13
+ "antigravity",
14
+ "antigravity_cli"
15
+ ]
16
+ });
17
+ expect(HARNESS_RUNTIME_PROFILES.antigravity_cli.matches("/usr/local/bin/agy")).toBe(true);
18
+ });
19
+ it("recognizes agent commands without matching similar argument text", ()=>{
20
+ expect(HARNESS_RUNTIME_PROFILES.copilot.matches("/opt/copilot-cli/1.0/copilot")).toBe(true);
21
+ expect(HARNESS_RUNTIME_PROFILES.copilot.matches("node /repo/copilot-cli/script.js")).toBe(false);
22
+ expect(HARNESS_RUNTIME_PROFILES.grok_cli.matches("/Users/dev/.grok/bin/grok --approve")).toBe(true);
23
+ expect(HARNESS_RUNTIME_PROFILES.grok_cli.matches("node /repo/grok-cli/script.js")).toBe(false);
24
+ expect(HARNESS_RUNTIME_PROFILES.gemini_cli.matches("node --no-warnings /usr/local/bin/gemini")).toBe(true);
25
+ });
26
+ it("matches runtime discovery names through the owning harness profile", ()=>{
27
+ expect(runtimeAgentMatchesHarness("kiro-cli", "kiro")).toBe(true);
28
+ expect(runtimeAgentMatchesHarness("gemini", "gemini_cli")).toBe(true);
29
+ expect(runtimeAgentMatchesHarness("codex", "claude")).toBe(false);
30
+ });
31
+ });
32
+ describe("harness matchers with executables under paths containing spaces", ()=>{
33
+ let root;
34
+ function install(relativePath) {
35
+ const fullPath = path.join(root, relativePath);
36
+ fs.mkdirSync(path.dirname(fullPath), {
37
+ recursive: true
38
+ });
39
+ fs.writeFileSync(fullPath, "");
40
+ return fullPath;
41
+ }
42
+ beforeEach(()=>{
43
+ root = fs.mkdtempSync(path.join(os.tmpdir(), "runtime-profiles-spaces-"));
44
+ });
45
+ afterEach(()=>{
46
+ fs.rmSync(root, {
47
+ recursive: true,
48
+ force: true
49
+ });
50
+ });
51
+ it("recognizes argv[0] under a spaced directory", ()=>{
52
+ const codex = install("Applications/Some App.app/Contents/Resources/codex");
53
+ const claude = install("Users/dev/My Tools/bin/claude");
54
+ expect(HARNESS_RUNTIME_PROFILES.codex.matches(`${codex} --sandbox workspace-write`)).toBe(true);
55
+ expect(HARNESS_RUNTIME_PROFILES.codex.matches(codex)).toBe(true);
56
+ expect(HARNESS_RUNTIME_PROFILES.claude.matches(`${claude} --continue`)).toBe(true);
57
+ expect(HARNESS_RUNTIME_PROFILES.claude.matches(`${codex} exec --cd /repo`)).toBe(false);
58
+ });
59
+ it("recognizes argv[0] by distribution name under a spaced directory", ()=>{
60
+ const copilot = install("opt/Home Brew/Caskroom/copilot-cli/1.0.60/copilot");
61
+ expect(HARNESS_RUNTIME_PROFILES.copilot.matches(`${copilot} --allow-all-tools`)).toBe(true);
62
+ });
63
+ it("does not treat arguments containing spaces as the executable", ()=>{
64
+ const vim = install("usr/bin/vim");
65
+ const codex = install("Applications/Some App.app/Contents/Resources/codex");
66
+ expect(HARNESS_RUNTIME_PROFILES.claude.matches(`${vim} My Notes/claude`)).toBe(false);
67
+ expect(HARNESS_RUNTIME_PROFILES.claude.matches(`${codex} exec review the Other Dir/claude`)).toBe(false);
68
+ expect(HARNESS_RUNTIME_PROFILES.copilot.matches(`${vim} Some Dir/copilot-cli/notes.md`)).toBe(false);
69
+ expect(HARNESS_RUNTIME_PROFILES.claude.matches("/usr/bin/vim My Notes/claude")).toBe(false);
70
+ });
71
+ it("recognizes spaced argv[0] in script-aware matchers", ()=>{
72
+ const pi = install("Users/dev/Node Tools/bin/pi");
73
+ const kiro = install("Applications/Kiro CLI.app/Contents/MacOS/kiro-cli");
74
+ const node = install("Applications/Dev Tools/node/bin/node");
75
+ expect(HARNESS_RUNTIME_PROFILES.pi.matches(`${pi} --model x`)).toBe(true);
76
+ expect(HARNESS_RUNTIME_PROFILES.kiro.matches(`${kiro} chat`)).toBe(true);
77
+ expect(HARNESS_RUNTIME_PROFILES.gemini_cli.matches(`${node} /Users/dev/.npm/bin/gemini --yolo`)).toBe(true);
78
+ expect(HARNESS_RUNTIME_PROFILES.pi.matches(`${node} /opt/pi-tools/script.js`)).toBe(false);
79
+ });
80
+ it("does not match agent words inside an executable directory", ()=>{
81
+ const node = install("opt/Dev pi gemini/bin/node");
82
+ expect(HARNESS_RUNTIME_PROFILES.pi.matches(`${node} /repo/script.js`)).toBe(false);
83
+ expect(HARNESS_RUNTIME_PROFILES.gemini_cli.matches(`${node} /repo/script.js`)).toBe(false);
84
+ expect(HARNESS_RUNTIME_PROFILES.gemini_cli.matches(`${node} /repo/bin/gemini`)).toBe(true);
85
+ expect(HARNESS_RUNTIME_PROFILES.pi.matches(`${node} --title pi`)).toBe(true);
86
+ });
87
+ });
88
+
89
+ //# sourceMappingURL=runtimeProfiles.test.js.map