@ai-devkit/agent-manager 0.28.1 → 0.30.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 (219) hide show
  1. package/dist/__tests__/adapters/ClaudeCodeAdapter.test.js +1 -342
  2. package/dist/__tests__/adapters/ClaudeCodeAdapter.test.js.map +1 -1
  3. package/dist/__tests__/capacity/codex.test.js +343 -0
  4. package/dist/__tests__/capacity/codex.test.js.map +1 -0
  5. package/dist/__tests__/capacity/index.test.js +50 -0
  6. package/dist/__tests__/capacity/index.test.js.map +1 -0
  7. package/dist/__tests__/database/DurableAgentsDatabase.test.js +31 -3
  8. package/dist/__tests__/database/DurableAgentsDatabase.test.js.map +1 -1
  9. package/dist/__tests__/durable/CodexCliProbe.test.js +129 -0
  10. package/dist/__tests__/durable/CodexCliProbe.test.js.map +1 -0
  11. package/dist/__tests__/durable/CodexDurableAgentRepository.test.js +84 -0
  12. package/dist/__tests__/durable/CodexDurableAgentRepository.test.js.map +1 -0
  13. package/dist/__tests__/durable/CodexPrintAgent.integration.test.js +126 -0
  14. package/dist/__tests__/durable/CodexPrintAgent.integration.test.js.map +1 -0
  15. package/dist/__tests__/durable/CodexPrintAgentService.test.js +271 -0
  16. package/dist/__tests__/durable/CodexPrintAgentService.test.js.map +1 -0
  17. package/dist/__tests__/durable/CodexPrintRunner.test.js +393 -0
  18. package/dist/__tests__/durable/CodexPrintRunner.test.js.map +1 -0
  19. package/dist/__tests__/print/ClaudeCliProbe.test.js +3 -7
  20. package/dist/__tests__/print/ClaudeCliProbe.test.js.map +1 -1
  21. package/dist/__tests__/print/ClaudePrintAgent.integration.test.js +33 -27
  22. package/dist/__tests__/print/ClaudePrintAgent.integration.test.js.map +1 -1
  23. package/dist/__tests__/print/ClaudePrintAgentService.test.js +65 -0
  24. package/dist/__tests__/print/ClaudePrintAgentService.test.js.map +1 -1
  25. package/dist/__tests__/print/ClaudePrintRunner.test.js +4 -10
  26. package/dist/__tests__/print/ClaudePrintRunner.test.js.map +1 -1
  27. package/dist/__tests__/providers/claude/ClaudeAgentMapper.test.js +79 -0
  28. package/dist/__tests__/providers/claude/ClaudeAgentMapper.test.js.map +1 -0
  29. package/dist/__tests__/providers/claude/ClaudeSessionLocator.test.js +436 -0
  30. package/dist/__tests__/providers/claude/ClaudeSessionLocator.test.js.map +1 -0
  31. package/dist/__tests__/providers/pi/durable/PiCliProbe.test.js +76 -0
  32. package/dist/__tests__/providers/pi/durable/PiCliProbe.test.js.map +1 -0
  33. package/dist/__tests__/providers/pi/durable/PiDurableAgentRepository.test.js +43 -0
  34. package/dist/__tests__/providers/pi/durable/PiDurableAgentRepository.test.js.map +1 -0
  35. package/dist/__tests__/providers/pi/durable/PiPrintAgentService.test.js +202 -0
  36. package/dist/__tests__/providers/pi/durable/PiPrintAgentService.test.js.map +1 -0
  37. package/dist/__tests__/providers/pi/durable/PiPrintProtocol.test.js +119 -0
  38. package/dist/__tests__/providers/pi/durable/PiPrintProtocol.test.js.map +1 -0
  39. package/dist/__tests__/providers/pi/durable/PiPrintRunner.test.js +386 -0
  40. package/dist/__tests__/providers/pi/durable/PiPrintRunner.test.js.map +1 -0
  41. package/dist/__tests__/providers/pi/durable/PiStreamParser.test.js +34 -0
  42. package/dist/__tests__/providers/pi/durable/PiStreamParser.test.js.map +1 -0
  43. package/dist/__tests__/utils/ClaudeSessionParser.test.js +2 -2
  44. package/dist/__tests__/utils/ClaudeSessionParser.test.js.map +1 -1
  45. package/dist/adapters/index.d.ts +1 -1
  46. package/dist/adapters/index.d.ts.map +1 -1
  47. package/dist/adapters/index.js +1 -1
  48. package/dist/adapters/index.js.map +1 -1
  49. package/dist/capacity/codex.d.ts +36 -0
  50. package/dist/capacity/codex.d.ts.map +1 -0
  51. package/dist/capacity/codex.js +317 -0
  52. package/dist/capacity/codex.js.map +1 -0
  53. package/dist/capacity/index.d.ts +11 -0
  54. package/dist/capacity/index.d.ts.map +1 -0
  55. package/dist/capacity/index.js +49 -0
  56. package/dist/capacity/index.js.map +1 -0
  57. package/dist/capacity/types.d.ts +17 -0
  58. package/dist/capacity/types.d.ts.map +1 -0
  59. package/dist/capacity/types.js +3 -0
  60. package/dist/capacity/types.js.map +1 -0
  61. package/dist/database/migrations/004_codex_durable_sessions.sql +1 -0
  62. package/dist/durable/DurableAgent.d.ts +23 -3
  63. package/dist/durable/DurableAgent.d.ts.map +1 -1
  64. package/dist/durable/DurableAgent.js +12 -0
  65. package/dist/durable/DurableAgent.js.map +1 -1
  66. package/dist/durable/DurableAgentRepository.d.ts +6 -7
  67. package/dist/durable/DurableAgentRepository.d.ts.map +1 -1
  68. package/dist/durable/DurableAgentRepository.js +73 -42
  69. package/dist/durable/DurableAgentRepository.js.map +1 -1
  70. package/dist/durable/process.d.ts +8 -0
  71. package/dist/durable/process.d.ts.map +1 -0
  72. package/dist/durable/process.js +40 -0
  73. package/dist/durable/process.js.map +1 -0
  74. package/dist/durable/run.d.ts +32 -0
  75. package/dist/durable/run.d.ts.map +1 -0
  76. package/dist/durable/run.js +46 -0
  77. package/dist/durable/run.js.map +1 -0
  78. package/dist/durable/utils.d.ts +19 -0
  79. package/dist/durable/utils.d.ts.map +1 -0
  80. package/dist/durable/utils.js +52 -0
  81. package/dist/durable/utils.js.map +1 -0
  82. package/dist/index.d.ts +19 -13
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +10 -8
  85. package/dist/index.js.map +1 -1
  86. package/dist/providers/claude/ClaudeAgentMapper.d.ts +21 -0
  87. package/dist/providers/claude/ClaudeAgentMapper.d.ts.map +1 -0
  88. package/dist/providers/claude/ClaudeAgentMapper.js +42 -0
  89. package/dist/providers/claude/ClaudeAgentMapper.js.map +1 -0
  90. package/dist/providers/claude/ClaudeCodeAdapter.d.ts +29 -0
  91. package/dist/providers/claude/ClaudeCodeAdapter.d.ts.map +1 -0
  92. package/dist/providers/claude/ClaudeCodeAdapter.js +129 -0
  93. package/dist/providers/claude/ClaudeCodeAdapter.js.map +1 -0
  94. package/dist/{adapters/ClaudeCodeAdapter.d.ts → providers/claude/ClaudeSessionLocator.d.ts} +68 -52
  95. package/dist/providers/claude/ClaudeSessionLocator.d.ts.map +1 -0
  96. package/dist/{adapters/ClaudeCodeAdapter.js → providers/claude/ClaudeSessionLocator.js} +71 -189
  97. package/dist/providers/claude/ClaudeSessionLocator.js.map +1 -0
  98. package/dist/{utils → providers/claude}/ClaudeSessionParser.d.ts +2 -2
  99. package/dist/providers/claude/ClaudeSessionParser.d.ts.map +1 -0
  100. package/dist/{utils → providers/claude}/ClaudeSessionParser.js +1 -1
  101. package/dist/providers/claude/ClaudeSessionParser.js.map +1 -0
  102. package/dist/providers/claude/durable/ClaudeCliProbe.d.ts.map +1 -0
  103. package/dist/{durable → providers/claude/durable}/ClaudeCliProbe.js +4 -9
  104. package/dist/providers/claude/durable/ClaudeCliProbe.js.map +1 -0
  105. package/dist/{durable → providers/claude/durable}/ClaudePrintAgentService.d.ts +4 -9
  106. package/dist/providers/claude/durable/ClaudePrintAgentService.d.ts.map +1 -0
  107. package/dist/providers/claude/durable/ClaudePrintAgentService.js +45 -0
  108. package/dist/providers/claude/durable/ClaudePrintAgentService.js.map +1 -0
  109. package/dist/{durable → providers/claude/durable}/ClaudePrintRunner.d.ts +3 -3
  110. package/dist/providers/claude/durable/ClaudePrintRunner.d.ts.map +1 -0
  111. package/dist/providers/claude/durable/ClaudePrintRunner.js +75 -0
  112. package/dist/providers/claude/durable/ClaudePrintRunner.js.map +1 -0
  113. package/dist/providers/claude/durable/ClaudeStreamParser.d.ts +17 -0
  114. package/dist/providers/claude/durable/ClaudeStreamParser.d.ts.map +1 -0
  115. package/dist/providers/claude/durable/ClaudeStreamParser.js +69 -0
  116. package/dist/providers/claude/durable/ClaudeStreamParser.js.map +1 -0
  117. package/dist/providers/codex/durable/CodexCliProbe.d.ts +20 -0
  118. package/dist/providers/codex/durable/CodexCliProbe.d.ts.map +1 -0
  119. package/dist/providers/codex/durable/CodexCliProbe.js +61 -0
  120. package/dist/providers/codex/durable/CodexCliProbe.js.map +1 -0
  121. package/dist/providers/codex/durable/CodexPrintAgentService.d.ts +40 -0
  122. package/dist/providers/codex/durable/CodexPrintAgentService.d.ts.map +1 -0
  123. package/dist/providers/codex/durable/CodexPrintAgentService.js +50 -0
  124. package/dist/providers/codex/durable/CodexPrintAgentService.js.map +1 -0
  125. package/dist/providers/codex/durable/CodexPrintRunner.d.ts +34 -0
  126. package/dist/providers/codex/durable/CodexPrintRunner.d.ts.map +1 -0
  127. package/dist/providers/codex/durable/CodexPrintRunner.js +78 -0
  128. package/dist/providers/codex/durable/CodexPrintRunner.js.map +1 -0
  129. package/dist/providers/codex/durable/CodexStreamParser.d.ts +21 -0
  130. package/dist/providers/codex/durable/CodexStreamParser.d.ts.map +1 -0
  131. package/dist/providers/codex/durable/CodexStreamParser.js +86 -0
  132. package/dist/providers/codex/durable/CodexStreamParser.js.map +1 -0
  133. package/dist/providers/pi/durable/PiCliProbe.d.ts +20 -0
  134. package/dist/providers/pi/durable/PiCliProbe.d.ts.map +1 -0
  135. package/dist/providers/pi/durable/PiCliProbe.js +51 -0
  136. package/dist/providers/pi/durable/PiCliProbe.js.map +1 -0
  137. package/dist/providers/pi/durable/PiPrintAgentService.d.ts +39 -0
  138. package/dist/providers/pi/durable/PiPrintAgentService.d.ts.map +1 -0
  139. package/dist/providers/pi/durable/PiPrintAgentService.js +47 -0
  140. package/dist/providers/pi/durable/PiPrintAgentService.js.map +1 -0
  141. package/dist/providers/pi/durable/PiPrintProtocol.d.ts +4 -0
  142. package/dist/providers/pi/durable/PiPrintProtocol.d.ts.map +1 -0
  143. package/dist/providers/pi/durable/PiPrintProtocol.js +44 -0
  144. package/dist/providers/pi/durable/PiPrintProtocol.js.map +1 -0
  145. package/dist/providers/pi/durable/PiPrintRunner.d.ts +32 -0
  146. package/dist/providers/pi/durable/PiPrintRunner.d.ts.map +1 -0
  147. package/dist/providers/pi/durable/PiPrintRunner.js +61 -0
  148. package/dist/providers/pi/durable/PiPrintRunner.js.map +1 -0
  149. package/dist/providers/pi/durable/PiStreamParser.d.ts +21 -0
  150. package/dist/providers/pi/durable/PiStreamParser.d.ts.map +1 -0
  151. package/dist/providers/pi/durable/PiStreamParser.js +71 -0
  152. package/dist/providers/pi/durable/PiStreamParser.js.map +1 -0
  153. package/package.json +1 -1
  154. package/src/__tests__/adapters/ClaudeCodeAdapter.test.ts +1 -307
  155. package/src/__tests__/capacity/codex.test.ts +184 -0
  156. package/src/__tests__/capacity/index.test.ts +38 -0
  157. package/src/__tests__/database/DurableAgentsDatabase.test.ts +28 -3
  158. package/src/__tests__/durable/CodexCliProbe.test.ts +63 -0
  159. package/src/__tests__/durable/CodexDurableAgentRepository.test.ts +54 -0
  160. package/src/__tests__/durable/CodexPrintAgent.integration.test.ts +79 -0
  161. package/src/__tests__/durable/CodexPrintAgentService.test.ts +139 -0
  162. package/src/__tests__/durable/CodexPrintRunner.test.ts +189 -0
  163. package/src/__tests__/fixtures/fake-codex.cjs +45 -0
  164. package/src/__tests__/print/ClaudeCliProbe.test.ts +3 -7
  165. package/src/__tests__/print/ClaudePrintAgent.integration.test.ts +19 -22
  166. package/src/__tests__/print/ClaudePrintAgentService.test.ts +33 -1
  167. package/src/__tests__/print/ClaudePrintRunner.test.ts +4 -10
  168. package/src/__tests__/providers/claude/ClaudeAgentMapper.test.ts +84 -0
  169. package/src/__tests__/providers/claude/ClaudeSessionLocator.test.ts +411 -0
  170. package/src/__tests__/providers/pi/durable/PiCliProbe.test.ts +38 -0
  171. package/src/__tests__/providers/pi/durable/PiDurableAgentRepository.test.ts +32 -0
  172. package/src/__tests__/providers/pi/durable/PiPrintAgentService.test.ts +69 -0
  173. package/src/__tests__/providers/pi/durable/PiPrintProtocol.test.ts +33 -0
  174. package/src/__tests__/providers/pi/durable/PiPrintRunner.test.ts +107 -0
  175. package/src/__tests__/providers/pi/durable/PiStreamParser.test.ts +24 -0
  176. package/src/__tests__/utils/ClaudeSessionParser.test.ts +2 -2
  177. package/src/adapters/index.ts +1 -1
  178. package/src/capacity/codex.ts +320 -0
  179. package/src/capacity/index.ts +57 -0
  180. package/src/capacity/types.ts +18 -0
  181. package/src/database/migrations/004_codex_durable_sessions.sql +1 -0
  182. package/src/durable/DurableAgent.ts +51 -3
  183. package/src/durable/DurableAgentRepository.ts +60 -31
  184. package/src/durable/process.ts +28 -0
  185. package/src/durable/run.ts +74 -0
  186. package/src/durable/utils.ts +61 -0
  187. package/src/index.ts +37 -15
  188. package/src/providers/claude/ClaudeAgentMapper.ts +62 -0
  189. package/src/providers/claude/ClaudeCodeAdapter.ts +160 -0
  190. package/src/{adapters/ClaudeCodeAdapter.ts → providers/claude/ClaudeSessionLocator.ts} +97 -239
  191. package/src/{utils → providers/claude}/ClaudeSessionParser.ts +2 -2
  192. package/src/{durable → providers/claude/durable}/ClaudeCliProbe.ts +4 -10
  193. package/src/providers/claude/durable/ClaudePrintAgentService.ts +66 -0
  194. package/src/providers/claude/durable/ClaudePrintRunner.ts +92 -0
  195. package/src/providers/claude/durable/ClaudeStreamParser.ts +79 -0
  196. package/src/providers/codex/durable/CodexCliProbe.ts +60 -0
  197. package/src/providers/codex/durable/CodexPrintAgentService.ts +65 -0
  198. package/src/providers/codex/durable/CodexPrintRunner.ts +94 -0
  199. package/src/providers/codex/durable/CodexStreamParser.ts +104 -0
  200. package/src/providers/pi/durable/PiCliProbe.ts +48 -0
  201. package/src/providers/pi/durable/PiPrintAgentService.ts +69 -0
  202. package/src/providers/pi/durable/PiPrintProtocol.ts +39 -0
  203. package/src/providers/pi/durable/PiPrintRunner.ts +88 -0
  204. package/src/providers/pi/durable/PiStreamParser.ts +84 -0
  205. package/dist/adapters/ClaudeCodeAdapter.d.ts.map +0 -1
  206. package/dist/adapters/ClaudeCodeAdapter.js.map +0 -1
  207. package/dist/durable/ClaudeCliProbe.d.ts.map +0 -1
  208. package/dist/durable/ClaudeCliProbe.js.map +0 -1
  209. package/dist/durable/ClaudePrintAgentService.d.ts.map +0 -1
  210. package/dist/durable/ClaudePrintAgentService.js +0 -66
  211. package/dist/durable/ClaudePrintAgentService.js.map +0 -1
  212. package/dist/durable/ClaudePrintRunner.d.ts.map +0 -1
  213. package/dist/durable/ClaudePrintRunner.js +0 -128
  214. package/dist/durable/ClaudePrintRunner.js.map +0 -1
  215. package/dist/utils/ClaudeSessionParser.d.ts.map +0 -1
  216. package/dist/utils/ClaudeSessionParser.js.map +0 -1
  217. package/src/durable/ClaudePrintAgentService.ts +0 -94
  218. package/src/durable/ClaudePrintRunner.ts +0 -139
  219. /package/dist/{durable → providers/claude/durable}/ClaudeCliProbe.d.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/__tests__/print/ClaudePrintAgent.integration.test.ts"],"sourcesContent":["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { afterEach, describe, expect, it } from 'vitest';\nimport {\n ClaudeCliProbe,\n ClaudePrintAgentService,\n ClaudePrintRunner,\n DurableAgentRepository,\n} from '../../index.js';\n\nconst roots: string[] = [];\nconst originalCapture = process.env.AI_DEVKIT_FAKE_CLAUDE_CAPTURE;\n\nafterEach(() => {\n if (originalCapture === undefined) delete process.env.AI_DEVKIT_FAKE_CLAUDE_CAPTURE;\n else process.env.AI_DEVKIT_FAKE_CLAUDE_CAPTURE = originalCapture;\n for (const root of roots.splice(0)) fs.rmSync(root, { recursive: true, force: true });\n});\n\ndescribe('Claude durable-agent fake-provider journey', () => {\n it('creates without invocation, then starts and resumes the same session through stdin', async () => {\n const root = fs.mkdtempSync(path.join(os.tmpdir(), 'durable-agent-integration-'));\n roots.push(root);\n const cwd = path.join(root, 'project');\n fs.mkdirSync(cwd);\n const capture = path.join(root, 'capture.jsonl');\n process.env.AI_DEVKIT_FAKE_CLAUDE_CAPTURE = capture;\n const executable = fileURLToPath(new URL('../fixtures/fake-claude.cjs', import.meta.url));\n const repository = new DurableAgentRepository({ dbPath: path.join(root, 'state', 'agents.db') });\n const service = new ClaudePrintAgentService({\n repository,\n probe: new ClaudeCliProbe({ executable }),\n runner: new ClaudePrintRunner(),\n executable,\n });\n\n const created = await service.create({ name: 'reviewer', cwd });\n expect(fs.existsSync(capture)).toBe(false);\n\n await expect(service.send(created.id, 'first secret')).resolves.toMatchObject({ result: 'answer:first secret' });\n await expect(service.send(created.id, 'follow up')).resolves.toMatchObject({ result: 'answer:follow up' });\n\n const invocations = fs.readFileSync(capture, 'utf8').trim().split('\\n').map((line) => JSON.parse(line));\n expect(invocations[0]).toMatchObject({ prompt: 'first secret', cwd: fs.realpathSync(cwd) });\n expect(invocations[0].args).toContain('--session-id');\n expect(invocations[0].args).not.toContain('first secret');\n expect(invocations[1]).toMatchObject({ prompt: 'follow up', cwd: fs.realpathSync(cwd) });\n expect(invocations[1].args).toContain('--resume');\n expect(invocations[1].args[invocations[1].args.indexOf('--resume') + 1]).toBe(created.providerSessionId);\n\n const persisted = await repository.getById(created.id);\n expect(persisted).toMatchObject({ state: 'ready', sessionHealth: 'healthy' });\n });\n});\n"],"names":["fs","os","path","fileURLToPath","afterEach","describe","expect","it","ClaudeCliProbe","ClaudePrintAgentService","ClaudePrintRunner","DurableAgentRepository","roots","originalCapture","process","env","AI_DEVKIT_FAKE_CLAUDE_CAPTURE","undefined","root","splice","rmSync","recursive","force","mkdtempSync","join","tmpdir","push","cwd","mkdirSync","capture","executable","URL","url","repository","dbPath","service","probe","runner","created","create","name","existsSync","toBe","send","id","resolves","toMatchObject","result","invocations","readFileSync","trim","split","map","line","JSON","parse","prompt","realpathSync","args","toContain","not","indexOf","providerSessionId","persisted","getById","state","sessionHealth"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/__tests__/print/ClaudePrintAgent.integration.test.ts"],"sourcesContent":["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport {\n ClaudePrintAgentService,\n DurableAgentRepository,\n type ProcessInspector,\n} from '../../index.js';\n\nconst roots: string[] = [];\n\nafterEach(() => {\n for (const root of roots.splice(0)) fs.rmSync(root, { recursive: true, force: true });\n});\n\ndescribe('Claude durable-agent fake-provider journey', () => {\n it('creates without invocation, then starts and resumes the same session through stdin', async () => {\n const root = fs.mkdtempSync(path.join(os.tmpdir(), 'durable-agent-integration-'));\n roots.push(root);\n const cwd = path.join(root, 'project');\n fs.mkdirSync(cwd);\n const processInspector: ProcessInspector = {\n getIdentity: (pid) => ({ pid, startedAt: `process-${pid}` }),\n };\n const repository = new DurableAgentRepository({\n dbPath: path.join(root, 'state', 'agents.db'),\n processInspector,\n });\n const runner = {\n run: vi.fn().mockImplementation(async (request) => {\n await request.onSpawn({ pid: 42, startedAt: 'process-42' });\n return { sessionId: request.agent.providerSessionId, result: `answer:${request.prompt}`, exitCode: 0 };\n }),\n };\n const service = new ClaudePrintAgentService({\n repository,\n probe: { validate: vi.fn() },\n runner,\n });\n\n const created = await service.create({ name: 'reviewer', cwd });\n\n await expect(service.send(created.id, 'first secret')).resolves.toMatchObject({ result: 'answer:first secret' });\n await expect(service.send(created.id, 'follow up')).resolves.toMatchObject({ result: 'answer:follow up' });\n\n expect(runner.run.mock.calls[0][0]).toMatchObject({ firstRun: true, prompt: 'first secret' });\n expect(runner.run.mock.calls[1][0]).toMatchObject({ firstRun: false, prompt: 'follow up' });\n\n const persisted = await repository.getById(created.id);\n expect(persisted).toMatchObject({ state: 'ready', sessionHealth: 'healthy' });\n });\n});\n"],"names":["fs","os","path","afterEach","describe","expect","it","vi","ClaudePrintAgentService","DurableAgentRepository","roots","root","splice","rmSync","recursive","force","mkdtempSync","join","tmpdir","push","cwd","mkdirSync","processInspector","getIdentity","pid","startedAt","repository","dbPath","runner","run","fn","mockImplementation","request","onSpawn","sessionId","agent","providerSessionId","result","prompt","exitCode","service","probe","validate","created","create","name","send","id","resolves","toMatchObject","mock","calls","firstRun","persisted","getById","state","sessionHealth"],"mappings":"AAAA,OAAOA,QAAQ,UAAU;AACzB,OAAOC,QAAQ,UAAU;AACzB,OAAOC,UAAU,YAAY;AAC7B,SAASC,SAAS,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ,SAAS;AAC7D,SACIC,uBAAuB,EACvBC,sBAAsB,QAEnB,iBAAiB;AAExB,MAAMC,QAAkB,EAAE;AAE1BP,UAAU;IACN,KAAK,MAAMQ,QAAQD,MAAME,MAAM,CAAC,GAAIZ,GAAGa,MAAM,CAACF,MAAM;QAAEG,WAAW;QAAMC,OAAO;IAAK;AACvF;AAEAX,SAAS,8CAA8C;IACnDE,GAAG,sFAAsF;QACrF,MAAMK,OAAOX,GAAGgB,WAAW,CAACd,KAAKe,IAAI,CAAChB,GAAGiB,MAAM,IAAI;QACnDR,MAAMS,IAAI,CAACR;QACX,MAAMS,MAAMlB,KAAKe,IAAI,CAACN,MAAM;QAC5BX,GAAGqB,SAAS,CAACD;QACb,MAAME,mBAAqC;YACvCC,aAAa,CAACC,MAAS,CAAA;oBAAEA;oBAAKC,WAAW,CAAC,QAAQ,EAAED,KAAK;gBAAC,CAAA;QAC9D;QACA,MAAME,aAAa,IAAIjB,uBAAuB;YAC1CkB,QAAQzB,KAAKe,IAAI,CAACN,MAAM,SAAS;YACjCW;QACJ;QACA,MAAMM,SAAS;YACXC,KAAKtB,GAAGuB,EAAE,GAAGC,kBAAkB,CAAC,OAAOC;gBACnC,MAAMA,QAAQC,OAAO,CAAC;oBAAET,KAAK;oBAAIC,WAAW;gBAAa;gBACzD,OAAO;oBAAES,WAAWF,QAAQG,KAAK,CAACC,iBAAiB;oBAAEC,QAAQ,CAAC,OAAO,EAAEL,QAAQM,MAAM,EAAE;oBAAEC,UAAU;gBAAE;YACzG;QACJ;QACA,MAAMC,UAAU,IAAIhC,wBAAwB;YACxCkB;YACAe,OAAO;gBAAEC,UAAUnC,GAAGuB,EAAE;YAAG;YAC3BF;QACJ;QAEA,MAAMe,UAAU,MAAMH,QAAQI,MAAM,CAAC;YAAEC,MAAM;YAAYzB;QAAI;QAE7D,MAAMf,OAAOmC,QAAQM,IAAI,CAACH,QAAQI,EAAE,EAAE,iBAAiBC,QAAQ,CAACC,aAAa,CAAC;YAAEZ,QAAQ;QAAsB;QAC9G,MAAMhC,OAAOmC,QAAQM,IAAI,CAACH,QAAQI,EAAE,EAAE,cAAcC,QAAQ,CAACC,aAAa,CAAC;YAAEZ,QAAQ;QAAmB;QAExGhC,OAAOuB,OAAOC,GAAG,CAACqB,IAAI,CAACC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAEF,aAAa,CAAC;YAAEG,UAAU;YAAMd,QAAQ;QAAe;QAC3FjC,OAAOuB,OAAOC,GAAG,CAACqB,IAAI,CAACC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAEF,aAAa,CAAC;YAAEG,UAAU;YAAOd,QAAQ;QAAY;QAEzF,MAAMe,YAAY,MAAM3B,WAAW4B,OAAO,CAACX,QAAQI,EAAE;QACrD1C,OAAOgD,WAAWJ,aAAa,CAAC;YAAEM,OAAO;YAASC,eAAe;QAAU;IAC/E;AACJ"}
@@ -41,6 +41,7 @@ describe('ClaudePrintAgentService', ()=>{
41
41
  const base = {
42
42
  id: 'id',
43
43
  name: 'reviewer',
44
+ provider: 'claude',
44
45
  providerSessionId: 'session',
45
46
  sessionHealth: 'uninitialized'
46
47
  };
@@ -103,6 +104,70 @@ describe('ClaudePrintAgentService', ()=>{
103
104
  sessionHealth: 'healthy'
104
105
  }));
105
106
  });
107
+ it('rejects a non-Claude target without acquiring or mutating it', async ()=>{
108
+ const api = await import('../../index.js');
109
+ const Service = api.ClaudePrintAgentService;
110
+ const target = {
111
+ id: 'id',
112
+ name: 'reviewer',
113
+ provider: 'pi'
114
+ };
115
+ const repository = {
116
+ resolve: vi.fn().mockResolvedValue(target),
117
+ acquireRun: vi.fn(),
118
+ recordProviderProcess: vi.fn(),
119
+ completeRun: vi.fn()
120
+ };
121
+ await expect(new Service({
122
+ repository,
123
+ probe: {
124
+ validate: vi.fn()
125
+ },
126
+ runner: {
127
+ run: vi.fn()
128
+ }
129
+ }).send('reviewer', 'x')).rejects.toMatchObject({
130
+ code: 'CLAUDE_PRINT_UNSUPPORTED'
131
+ });
132
+ expect(repository.acquireRun).not.toHaveBeenCalled();
133
+ expect(repository.completeRun).not.toHaveBeenCalled();
134
+ });
135
+ it('does not turn a successful completion write failure into a second completion', async ()=>{
136
+ const api = await import('../../index.js');
137
+ const Service = api.ClaudePrintAgentService;
138
+ const target = {
139
+ id: 'id',
140
+ name: 'reviewer',
141
+ provider: 'claude',
142
+ providerSessionId: 'session',
143
+ sessionHealth: 'healthy'
144
+ };
145
+ const completionFailure = new Error('completion failed');
146
+ const repository = {
147
+ resolve: vi.fn().mockResolvedValue(target),
148
+ acquireRun: vi.fn().mockResolvedValue({
149
+ agent: target,
150
+ token: 'one'
151
+ }),
152
+ recordProviderProcess: vi.fn(),
153
+ completeRun: vi.fn().mockRejectedValue(completionFailure)
154
+ };
155
+ const runner = {
156
+ run: vi.fn().mockResolvedValue({
157
+ sessionId: 'session',
158
+ result: 'answer',
159
+ exitCode: 0
160
+ })
161
+ };
162
+ await expect(new Service({
163
+ repository,
164
+ probe: {
165
+ validate: vi.fn()
166
+ },
167
+ runner
168
+ }).send('reviewer', 'x')).rejects.toBe(completionFailure);
169
+ expect(repository.completeRun).toHaveBeenCalledOnce();
170
+ });
106
171
  });
107
172
 
108
173
  //# sourceMappingURL=ClaudePrintAgentService.test.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/__tests__/print/ClaudePrintAgentService.test.ts"],"sourcesContent":["import { describe, expect, it, vi } from 'vitest';\n\ndescribe('ClaudePrintAgentService', () => {\n it('validates before create and does not run Claude', async () => {\n const api = await import('../../index.js') as Record<string, unknown>;\n expect(api).toHaveProperty('ClaudePrintAgentService');\n const probe = { validate: vi.fn().mockResolvedValue({ executable: 'claude', version: '2.1.220' }) };\n const repository = { create: vi.fn().mockResolvedValue({ id: 'agent-id', name: 'reviewer' }) };\n const runner = { run: vi.fn() };\n const Service = api.ClaudePrintAgentService as new (options: unknown) => any;\n\n await expect(new Service({ repository, probe, runner }).create({ name: 'reviewer', cwd: '/project' }))\n .resolves.toMatchObject({ id: 'agent-id' });\n expect(probe.validate).toHaveBeenCalledOnce();\n expect(repository.create).toHaveBeenCalledWith({ name: 'reviewer', cwd: '/project' });\n expect(runner.run).not.toHaveBeenCalled();\n });\n\n it('runs first and resumed sends and records provider identity/results', async () => {\n const api = await import('../../index.js') as Record<string, unknown>;\n const base = { id: 'id', name: 'reviewer', providerSessionId: 'session', sessionHealth: 'uninitialized' };\n const repository = {\n resolve: vi.fn().mockResolvedValue(base),\n acquireRun: vi.fn()\n .mockResolvedValueOnce({ agent: base, token: 'one' })\n .mockResolvedValueOnce({ agent: { ...base, sessionHealth: 'healthy' }, token: 'two' }),\n recordProviderProcess: vi.fn(), completeRun: vi.fn().mockResolvedValue({}),\n };\n const runner = { run: vi.fn().mockImplementation(async (request) => {\n await request.onSpawn({ pid: 42, startedAt: 'start' });\n return { sessionId: 'session', result: 'answer', exitCode: 0 };\n }) };\n const Service = api.ClaudePrintAgentService as new (options: unknown) => any;\n const service = new Service({ repository, probe: { validate: vi.fn() }, runner, executable: 'fake-claude' });\n\n await service.send('reviewer', 'first');\n await service.send('id', 'later');\n\n expect(runner.run.mock.calls[0][0]).toMatchObject({ prompt: 'first', firstRun: true, executable: 'fake-claude' });\n expect(runner.run.mock.calls[1][0]).toMatchObject({ prompt: 'later', firstRun: false, executable: 'fake-claude' });\n expect(repository.recordProviderProcess).toHaveBeenCalledWith('id', 'one', { pid: 42, startedAt: 'start' });\n expect(repository.completeRun).toHaveBeenCalledWith('id', 'one', expect.objectContaining({\n status: 'succeeded', exitCode: 0, sessionHealth: 'healthy',\n }));\n });\n});\n"],"names":["describe","expect","it","vi","api","toHaveProperty","probe","validate","fn","mockResolvedValue","executable","version","repository","create","id","name","runner","run","Service","ClaudePrintAgentService","cwd","resolves","toMatchObject","toHaveBeenCalledOnce","toHaveBeenCalledWith","not","toHaveBeenCalled","base","providerSessionId","sessionHealth","resolve","acquireRun","mockResolvedValueOnce","agent","token","recordProviderProcess","completeRun","mockImplementation","request","onSpawn","pid","startedAt","sessionId","result","exitCode","service","send","mock","calls","prompt","firstRun","objectContaining","status"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ,SAAS;AAElDH,SAAS,2BAA2B;IAChCE,GAAG,mDAAmD;QAClD,MAAME,MAAM,MAAM,MAAM,CAAC;QACzBH,OAAOG,KAAKC,cAAc,CAAC;QAC3B,MAAMC,QAAQ;YAAEC,UAAUJ,GAAGK,EAAE,GAAGC,iBAAiB,CAAC;gBAAEC,YAAY;gBAAUC,SAAS;YAAU;QAAG;QAClG,MAAMC,aAAa;YAAEC,QAAQV,GAAGK,EAAE,GAAGC,iBAAiB,CAAC;gBAAEK,IAAI;gBAAYC,MAAM;YAAW;QAAG;QAC7F,MAAMC,SAAS;YAAEC,KAAKd,GAAGK,EAAE;QAAG;QAC9B,MAAMU,UAAUd,IAAIe,uBAAuB;QAE3C,MAAMlB,OAAO,IAAIiB,QAAQ;YAAEN;YAAYN;YAAOU;QAAO,GAAGH,MAAM,CAAC;YAAEE,MAAM;YAAYK,KAAK;QAAW,IAC9FC,QAAQ,CAACC,aAAa,CAAC;YAAER,IAAI;QAAW;QAC7Cb,OAAOK,MAAMC,QAAQ,EAAEgB,oBAAoB;QAC3CtB,OAAOW,WAAWC,MAAM,EAAEW,oBAAoB,CAAC;YAAET,MAAM;YAAYK,KAAK;QAAW;QACnFnB,OAAOe,OAAOC,GAAG,EAAEQ,GAAG,CAACC,gBAAgB;IAC3C;IAEAxB,GAAG,sEAAsE;QACrE,MAAME,MAAM,MAAM,MAAM,CAAC;QACzB,MAAMuB,OAAO;YAAEb,IAAI;YAAMC,MAAM;YAAYa,mBAAmB;YAAWC,eAAe;QAAgB;QACxG,MAAMjB,aAAa;YACfkB,SAAS3B,GAAGK,EAAE,GAAGC,iBAAiB,CAACkB;YACnCI,YAAY5B,GAAGK,EAAE,GACZwB,qBAAqB,CAAC;gBAAEC,OAAON;gBAAMO,OAAO;YAAM,GAClDF,qBAAqB,CAAC;gBAAEC,OAAO;oBAAE,GAAGN,IAAI;oBAAEE,eAAe;gBAAU;gBAAGK,OAAO;YAAM;YACxFC,uBAAuBhC,GAAGK,EAAE;YAAI4B,aAAajC,GAAGK,EAAE,GAAGC,iBAAiB,CAAC,CAAC;QAC5E;QACA,MAAMO,SAAS;YAAEC,KAAKd,GAAGK,EAAE,GAAG6B,kBAAkB,CAAC,OAAOC;gBACpD,MAAMA,QAAQC,OAAO,CAAC;oBAAEC,KAAK;oBAAIC,WAAW;gBAAQ;gBACpD,OAAO;oBAAEC,WAAW;oBAAWC,QAAQ;oBAAUC,UAAU;gBAAE;YACjE;QAAG;QACH,MAAM1B,UAAUd,IAAIe,uBAAuB;QAC3C,MAAM0B,UAAU,IAAI3B,QAAQ;YAAEN;YAAYN,OAAO;gBAAEC,UAAUJ,GAAGK,EAAE;YAAG;YAAGQ;YAAQN,YAAY;QAAc;QAE1G,MAAMmC,QAAQC,IAAI,CAAC,YAAY;QAC/B,MAAMD,QAAQC,IAAI,CAAC,MAAM;QAEzB7C,OAAOe,OAAOC,GAAG,CAAC8B,IAAI,CAACC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE1B,aAAa,CAAC;YAAE2B,QAAQ;YAASC,UAAU;YAAMxC,YAAY;QAAc;QAC/GT,OAAOe,OAAOC,GAAG,CAAC8B,IAAI,CAACC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE1B,aAAa,CAAC;YAAE2B,QAAQ;YAASC,UAAU;YAAOxC,YAAY;QAAc;QAChHT,OAAOW,WAAWuB,qBAAqB,EAAEX,oBAAoB,CAAC,MAAM,OAAO;YAAEgB,KAAK;YAAIC,WAAW;QAAQ;QACzGxC,OAAOW,WAAWwB,WAAW,EAAEZ,oBAAoB,CAAC,MAAM,OAAOvB,OAAOkD,gBAAgB,CAAC;YACrFC,QAAQ;YAAaR,UAAU;YAAGf,eAAe;QACrD;IACJ;AACJ"}
1
+ {"version":3,"sources":["../../../src/__tests__/print/ClaudePrintAgentService.test.ts"],"sourcesContent":["import { describe, expect, it, vi } from 'vitest';\n\ndescribe('ClaudePrintAgentService', () => {\n it('validates before create and does not run Claude', async () => {\n const api = await import('../../index.js') as Record<string, unknown>;\n expect(api).toHaveProperty('ClaudePrintAgentService');\n const probe = { validate: vi.fn().mockResolvedValue({ executable: 'claude', version: '2.1.220' }) };\n const repository = { create: vi.fn().mockResolvedValue({ id: 'agent-id', name: 'reviewer' }) };\n const runner = { run: vi.fn() };\n const Service = api.ClaudePrintAgentService as new (options: unknown) => any;\n\n await expect(new Service({ repository, probe, runner }).create({ name: 'reviewer', cwd: '/project' }))\n .resolves.toMatchObject({ id: 'agent-id' });\n expect(probe.validate).toHaveBeenCalledOnce();\n expect(repository.create).toHaveBeenCalledWith({ name: 'reviewer', cwd: '/project' });\n expect(runner.run).not.toHaveBeenCalled();\n });\n\n it('runs first and resumed sends and records provider identity/results', async () => {\n const api = await import('../../index.js') as Record<string, unknown>;\n const base = { id: 'id', name: 'reviewer', provider: 'claude', providerSessionId: 'session', sessionHealth: 'uninitialized' };\n const repository = {\n resolve: vi.fn().mockResolvedValue(base),\n acquireRun: vi.fn()\n .mockResolvedValueOnce({ agent: base, token: 'one' })\n .mockResolvedValueOnce({ agent: { ...base, sessionHealth: 'healthy' }, token: 'two' }),\n recordProviderProcess: vi.fn(), completeRun: vi.fn().mockResolvedValue({}),\n };\n const runner = { run: vi.fn().mockImplementation(async (request) => {\n await request.onSpawn({ pid: 42, startedAt: 'start' });\n return { sessionId: 'session', result: 'answer', exitCode: 0 };\n }) };\n const Service = api.ClaudePrintAgentService as new (options: unknown) => any;\n const service = new Service({ repository, probe: { validate: vi.fn() }, runner, executable: 'fake-claude' });\n\n await service.send('reviewer', 'first');\n await service.send('id', 'later');\n\n expect(runner.run.mock.calls[0][0]).toMatchObject({ prompt: 'first', firstRun: true, executable: 'fake-claude' });\n expect(runner.run.mock.calls[1][0]).toMatchObject({ prompt: 'later', firstRun: false, executable: 'fake-claude' });\n expect(repository.recordProviderProcess).toHaveBeenCalledWith('id', 'one', { pid: 42, startedAt: 'start' });\n expect(repository.completeRun).toHaveBeenCalledWith('id', 'one', expect.objectContaining({\n status: 'succeeded', exitCode: 0, sessionHealth: 'healthy',\n }));\n });\n\n it('rejects a non-Claude target without acquiring or mutating it', async () => {\n const api = await import('../../index.js') as Record<string, unknown>;\n const Service = api.ClaudePrintAgentService as new (options: unknown) => any;\n const target = { id: 'id', name: 'reviewer', provider: 'pi' };\n const repository = {\n resolve: vi.fn().mockResolvedValue(target),\n acquireRun: vi.fn(), recordProviderProcess: vi.fn(), completeRun: vi.fn(),\n };\n\n await expect(new Service({ repository, probe: { validate: vi.fn() }, runner: { run: vi.fn() } })\n .send('reviewer', 'x')).rejects.toMatchObject({ code: 'CLAUDE_PRINT_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.ClaudePrintAgentService as new (options: unknown) => any;\n const target = { id: 'id', name: 'reviewer', provider: 'claude', providerSessionId: 'session', sessionHealth: 'healthy' };\n const completionFailure = new Error('completion failed');\n const repository = {\n resolve: vi.fn().mockResolvedValue(target),\n acquireRun: vi.fn().mockResolvedValue({ agent: target, token: 'one' }),\n recordProviderProcess: vi.fn(), completeRun: vi.fn().mockRejectedValue(completionFailure),\n };\n const runner = { run: vi.fn().mockResolvedValue({ sessionId: 'session', result: 'answer', exitCode: 0 }) };\n\n await expect(new Service({ repository, probe: { validate: vi.fn() }, runner })\n .send('reviewer', 'x')).rejects.toBe(completionFailure);\n expect(repository.completeRun).toHaveBeenCalledOnce();\n });\n});\n"],"names":["describe","expect","it","vi","api","toHaveProperty","probe","validate","fn","mockResolvedValue","executable","version","repository","create","id","name","runner","run","Service","ClaudePrintAgentService","cwd","resolves","toMatchObject","toHaveBeenCalledOnce","toHaveBeenCalledWith","not","toHaveBeenCalled","base","provider","providerSessionId","sessionHealth","resolve","acquireRun","mockResolvedValueOnce","agent","token","recordProviderProcess","completeRun","mockImplementation","request","onSpawn","pid","startedAt","sessionId","result","exitCode","service","send","mock","calls","prompt","firstRun","objectContaining","status","target","rejects","code","completionFailure","Error","mockRejectedValue","toBe"],"mappings":"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"}
@@ -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 { ClaudePrintRunner } from '../../providers/claude/durable/ClaudePrintRunner.js';
4
5
  function agent() {
5
6
  return {
6
7
  id: '11111111-1111-4111-8111-111111111111',
@@ -49,8 +50,6 @@ function fakeSpawn(events, exitCode = 0) {
49
50
  }
50
51
  describe('ClaudePrintRunner', ()=>{
51
52
  it('starts a caller-assigned session and persists provider identity before stdin', async ()=>{
52
- const api = await import('../../index.js');
53
- expect(api).toHaveProperty('ClaudePrintRunner');
54
53
  const fixture = fakeSpawn([
55
54
  {
56
55
  type: 'system',
@@ -64,8 +63,7 @@ describe('ClaudePrintRunner', ()=>{
64
63
  }
65
64
  ]);
66
65
  let persisted = false;
67
- const Runner = api.ClaudePrintRunner;
68
- const runner = new Runner({
66
+ const runner = new ClaudePrintRunner({
69
67
  spawn: fixture.spawn,
70
68
  processInspector: {
71
69
  getIdentity: ()=>({
@@ -114,7 +112,6 @@ describe('ClaudePrintRunner', ()=>{
114
112
  });
115
113
  });
116
114
  it('uses exact resume and rejects a mismatched result session', async ()=>{
117
- const api = await import('../../index.js');
118
115
  const fixture = fakeSpawn([
119
116
  {
120
117
  type: 'result',
@@ -122,8 +119,7 @@ describe('ClaudePrintRunner', ()=>{
122
119
  result: 'nope'
123
120
  }
124
121
  ]);
125
- const Runner = api.ClaudePrintRunner;
126
- const runner = new Runner({
122
+ const runner = new ClaudePrintRunner({
127
123
  spawn: fixture.spawn,
128
124
  processInspector: {
129
125
  getIdentity: ()=>({
@@ -151,10 +147,8 @@ describe('ClaudePrintRunner', ()=>{
151
147
  ]);
152
148
  });
153
149
  it('does not disclose provider stderr in a failed-run error', async ()=>{
154
- const api = await import('../../index.js');
155
150
  const fixture = fakeSpawn([], 1);
156
- const Runner = api.ClaudePrintRunner;
157
- const runner = new Runner({
151
+ const runner = new ClaudePrintRunner({
158
152
  spawn: fixture.spawn,
159
153
  processInspector: {
160
154
  getIdentity: ()=>({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/__tests__/print/ClaudePrintRunner.test.ts"],"sourcesContent":["import { EventEmitter } from 'node:events';\nimport { PassThrough, Writable } from 'node:stream';\nimport { describe, expect, it, vi } from 'vitest';\nimport type { DurableAgent } from '../../index.js';\n\nfunction agent(): DurableAgent {\n return {\n id: '11111111-1111-4111-8111-111111111111', name: 'reviewer', provider: 'claude', mode: 'durable',\n cwd: '/project', providerSessionId: '22222222-2222-4222-8222-222222222222', state: 'running',\n sessionHealth: 'uninitialized', createdAt: '', updatedAt: '', lastActiveAt: null, lastResult: null,\n activeRun: null,\n };\n}\n\nfunction fakeSpawn(events: object[], exitCode = 0) {\n const calls: unknown[][] = [];\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.stdin = new Writable({\n write(chunk, _encoding, callback) { promptChunks.push(Buffer.from(chunk)); callback(); },\n final(callback) {\n for (const event of events) child.stdout.write(`${JSON.stringify(event)}\\n`);\n child.stdout.end();\n queueMicrotask(() => child.emit('close', exitCode, null));\n callback();\n },\n });\n const spawn = vi.fn((...args: unknown[]) => { calls.push(args); return child; });\n return { spawn, calls, promptChunks };\n}\n\ndescribe('ClaudePrintRunner', () => {\n it('starts a caller-assigned session and persists provider identity before stdin', async () => {\n const api = await import('../../index.js') as Record<string, unknown>;\n expect(api).toHaveProperty('ClaudePrintRunner');\n const fixture = fakeSpawn([\n { type: 'system', subtype: 'init', session_id: agent().providerSessionId },\n { type: 'result', session_id: agent().providerSessionId, result: 'done' },\n ]);\n let persisted = false;\n const Runner = api.ClaudePrintRunner as new (options: unknown) => any;\n const runner = new Runner({ spawn: fixture.spawn, processInspector: {\n getIdentity: () => ({ pid: 4242, startedAt: 'provider-start' }),\n } });\n\n const result = await runner.run({\n agent: agent(), prompt: 'secret prompt', executable: 'claude-test', firstRun: true,\n onSpawn: async () => { expect(fixture.promptChunks).toHaveLength(0); persisted = true; },\n });\n\n expect(persisted).toBe(true);\n expect(fixture.calls[0]).toEqual([\n 'claude-test',\n ['-p', '--session-id', agent().providerSessionId, '--output-format', 'stream-json', '--verbose'],\n expect.objectContaining({ cwd: '/project', shell: false, stdio: ['pipe', 'pipe', 'pipe'] }),\n ]);\n expect(JSON.stringify(fixture.calls)).not.toContain('secret prompt');\n expect(Buffer.concat(fixture.promptChunks).toString()).toBe('secret prompt');\n expect(result).toEqual({ sessionId: agent().providerSessionId, result: 'done', exitCode: 0 });\n });\n\n it('uses exact resume and rejects a mismatched result session', async () => {\n const api = await import('../../index.js') as Record<string, unknown>;\n const fixture = fakeSpawn([{ type: 'result', session_id: 'wrong', result: 'nope' }]);\n const Runner = api.ClaudePrintRunner as new (options: unknown) => any;\n const runner = new Runner({ spawn: fixture.spawn, processInspector: {\n getIdentity: () => ({ pid: 4242, startedAt: 'provider-start' }),\n } });\n\n await expect(runner.run({\n agent: agent(), prompt: 'followup', executable: 'claude', firstRun: false, onSpawn: vi.fn(),\n })).rejects.toMatchObject({ code: 'CLAUDE_SESSION_MISMATCH' });\n expect(fixture.calls[0]![1]).toEqual([\n '-p', '--resume', agent().providerSessionId, '--output-format', 'stream-json', '--verbose',\n ]);\n });\n\n it('does not disclose provider stderr in a failed-run error', async () => {\n const api = await import('../../index.js') as Record<string, unknown>;\n const fixture = fakeSpawn([], 1);\n const Runner = api.ClaudePrintRunner as new (options: unknown) => any;\n const runner = new Runner({ spawn: fixture.spawn, processInspector: {\n getIdentity: () => ({ pid: 4242, startedAt: 'provider-start' }),\n } });\n fixture.spawn.mockImplementationOnce((...args: unknown[]) => {\n const child = (fakeSpawn([], 1).spawn as any)(...args);\n child.stdin = new Writable({\n final(callback) {\n child.stderr.write('secret prompt echoed by provider');\n child.stderr.end();\n queueMicrotask(() => child.emit('close', 1, null));\n callback();\n },\n });\n return child;\n });\n\n await expect(runner.run({\n agent: agent(), prompt: 'secret prompt', firstRun: true, onSpawn: vi.fn(),\n })).rejects.not.toThrow(/secret prompt/);\n });\n});\n"],"names":["EventEmitter","PassThrough","Writable","describe","expect","it","vi","agent","id","name","provider","mode","cwd","providerSessionId","state","sessionHealth","createdAt","updatedAt","lastActiveAt","lastResult","activeRun","fakeSpawn","events","exitCode","calls","promptChunks","child","pid","stdout","stderr","stdin","write","chunk","_encoding","callback","push","Buffer","from","final","event","JSON","stringify","end","queueMicrotask","emit","spawn","fn","args","api","toHaveProperty","fixture","type","subtype","session_id","result","persisted","Runner","ClaudePrintRunner","runner","processInspector","getIdentity","startedAt","run","prompt","executable","firstRun","onSpawn","toHaveLength","toBe","toEqual","objectContaining","shell","stdio","not","toContain","concat","toString","sessionId","rejects","toMatchObject","code","mockImplementationOnce","toThrow"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/__tests__/print/ClaudePrintRunner.test.ts"],"sourcesContent":["import { EventEmitter } from 'node:events';\nimport { PassThrough, Writable } from 'node:stream';\nimport { describe, expect, it, vi } from 'vitest';\nimport type { DurableAgent } from '../../index.js';\nimport { ClaudePrintRunner } from '../../providers/claude/durable/ClaudePrintRunner.js';\n\nfunction agent(): DurableAgent {\n return {\n id: '11111111-1111-4111-8111-111111111111', name: 'reviewer', provider: 'claude', mode: 'durable',\n cwd: '/project', providerSessionId: '22222222-2222-4222-8222-222222222222', state: 'running',\n sessionHealth: 'uninitialized', createdAt: '', updatedAt: '', lastActiveAt: null, lastResult: null,\n activeRun: null,\n };\n}\n\nfunction fakeSpawn(events: object[], exitCode = 0) {\n const calls: unknown[][] = [];\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.stdin = new Writable({\n write(chunk, _encoding, callback) { promptChunks.push(Buffer.from(chunk)); callback(); },\n final(callback) {\n for (const event of events) child.stdout.write(`${JSON.stringify(event)}\\n`);\n child.stdout.end();\n queueMicrotask(() => child.emit('close', exitCode, null));\n callback();\n },\n });\n const spawn = vi.fn((...args: unknown[]) => { calls.push(args); return child; });\n return { spawn, calls, promptChunks };\n}\n\ndescribe('ClaudePrintRunner', () => {\n it('starts a caller-assigned session and persists provider identity before stdin', async () => {\n const fixture = fakeSpawn([\n { type: 'system', subtype: 'init', session_id: agent().providerSessionId },\n { type: 'result', session_id: agent().providerSessionId, result: 'done' },\n ]);\n let persisted = false;\n const runner = new ClaudePrintRunner({ spawn: fixture.spawn, processInspector: {\n getIdentity: () => ({ pid: 4242, startedAt: 'provider-start' }),\n } });\n\n const result = await runner.run({\n agent: agent(), prompt: 'secret prompt', executable: 'claude-test', firstRun: true,\n onSpawn: async () => { expect(fixture.promptChunks).toHaveLength(0); persisted = true; },\n });\n\n expect(persisted).toBe(true);\n expect(fixture.calls[0]).toEqual([\n 'claude-test',\n ['-p', '--session-id', agent().providerSessionId, '--output-format', 'stream-json', '--verbose'],\n expect.objectContaining({ cwd: '/project', shell: false, stdio: ['pipe', 'pipe', 'pipe'] }),\n ]);\n expect(JSON.stringify(fixture.calls)).not.toContain('secret prompt');\n expect(Buffer.concat(fixture.promptChunks).toString()).toBe('secret prompt');\n expect(result).toEqual({ sessionId: agent().providerSessionId, result: 'done', exitCode: 0 });\n });\n\n it('uses exact resume and rejects a mismatched result session', async () => {\n const fixture = fakeSpawn([{ type: 'result', session_id: 'wrong', result: 'nope' }]);\n const runner = new ClaudePrintRunner({ spawn: fixture.spawn, processInspector: {\n getIdentity: () => ({ pid: 4242, startedAt: 'provider-start' }),\n } });\n\n await expect(runner.run({\n agent: agent(), prompt: 'followup', executable: 'claude', firstRun: false, onSpawn: vi.fn(),\n })).rejects.toMatchObject({ code: 'CLAUDE_SESSION_MISMATCH' });\n expect(fixture.calls[0]![1]).toEqual([\n '-p', '--resume', agent().providerSessionId, '--output-format', 'stream-json', '--verbose',\n ]);\n });\n\n it('does not disclose provider stderr in a failed-run error', async () => {\n const fixture = fakeSpawn([], 1);\n const runner = new ClaudePrintRunner({ spawn: fixture.spawn, processInspector: {\n getIdentity: () => ({ pid: 4242, startedAt: 'provider-start' }),\n } });\n fixture.spawn.mockImplementationOnce((...args: unknown[]) => {\n const child = (fakeSpawn([], 1).spawn as any)(...args);\n child.stdin = new Writable({\n final(callback) {\n child.stderr.write('secret prompt echoed by provider');\n child.stderr.end();\n queueMicrotask(() => child.emit('close', 1, null));\n callback();\n },\n });\n return child;\n });\n\n await expect(runner.run({\n agent: agent(), prompt: 'secret prompt', firstRun: true, onSpawn: vi.fn(),\n })).rejects.not.toThrow(/secret prompt/);\n });\n});\n"],"names":["EventEmitter","PassThrough","Writable","describe","expect","it","vi","ClaudePrintRunner","agent","id","name","provider","mode","cwd","providerSessionId","state","sessionHealth","createdAt","updatedAt","lastActiveAt","lastResult","activeRun","fakeSpawn","events","exitCode","calls","promptChunks","child","pid","stdout","stderr","stdin","write","chunk","_encoding","callback","push","Buffer","from","final","event","JSON","stringify","end","queueMicrotask","emit","spawn","fn","args","fixture","type","subtype","session_id","result","persisted","runner","processInspector","getIdentity","startedAt","run","prompt","executable","firstRun","onSpawn","toHaveLength","toBe","toEqual","objectContaining","shell","stdio","not","toContain","concat","toString","sessionId","rejects","toMatchObject","code","mockImplementationOnce","toThrow"],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { AgentStatus } from '../../../adapters/AgentAdapter.js';
3
+ import { ClaudeAgentMapper } from '../../../providers/claude/ClaudeAgentMapper.js';
4
+ function makeProcess(overrides = {}) {
5
+ return {
6
+ pid: 123,
7
+ command: 'claude',
8
+ cwd: '/repo/my-app',
9
+ tty: 'ttys001',
10
+ ...overrides
11
+ };
12
+ }
13
+ function makeSession(overrides = {}) {
14
+ return {
15
+ sessionId: 'session-1',
16
+ projectPath: '/repo/my-app',
17
+ sessionStart: new Date('2026-08-23T10:00:00.000Z'),
18
+ lastActive: new Date('2026-08-23T10:05:00.000Z'),
19
+ lastEntryType: 'assistant',
20
+ isInterrupted: false,
21
+ lastUserMessage: 'Review this change',
22
+ ...overrides
23
+ };
24
+ }
25
+ function makeSessionFile(overrides = {}) {
26
+ return {
27
+ sessionId: 'session-1',
28
+ filePath: '/home/.claude/projects/-repo-my-app/session-1.jsonl',
29
+ projectDir: '/home/.claude/projects/-repo-my-app',
30
+ birthtimeMs: new Date('2026-08-23T10:00:00.000Z').getTime(),
31
+ resolvedCwd: '/repo/my-app',
32
+ ...overrides
33
+ };
34
+ }
35
+ describe('ClaudeAgentMapper', ()=>{
36
+ it('prefers live PID-file status and waiting reason over JSONL-derived status', ()=>{
37
+ const mapper = new ClaudeAgentMapper();
38
+ const agent = mapper.mapSessionToAgent({
39
+ session: makeSession({
40
+ lastEntryType: 'assistant'
41
+ }),
42
+ processInfo: makeProcess(),
43
+ sessionFile: makeSessionFile(),
44
+ liveInfo: {
45
+ pidStatus: AgentStatus.WAITING,
46
+ waitingFor: 'approve Read'
47
+ }
48
+ });
49
+ expect(agent).toMatchObject({
50
+ name: 'my-app-123',
51
+ type: 'claude',
52
+ status: AgentStatus.WAITING,
53
+ summary: 'Review this change — waiting for approve Read',
54
+ pid: 123,
55
+ projectPath: '/repo/my-app',
56
+ sessionId: 'session-1',
57
+ sessionFilePath: '/home/.claude/projects/-repo-my-app/session-1.jsonl'
58
+ });
59
+ });
60
+ it('maps unmatched processes to the existing process-only fallback shape', ()=>{
61
+ const mapper = new ClaudeAgentMapper();
62
+ const agent = mapper.mapProcessOnlyAgent(makeProcess({
63
+ pid: 456,
64
+ cwd: '/repo/tooling'
65
+ }));
66
+ expect(agent).toMatchObject({
67
+ name: 'tooling-456',
68
+ type: 'claude',
69
+ status: AgentStatus.IDLE,
70
+ summary: 'Unknown',
71
+ pid: 456,
72
+ projectPath: '/repo/tooling',
73
+ sessionId: 'pid-456'
74
+ });
75
+ expect(agent.lastActive).toBeInstanceOf(Date);
76
+ });
77
+ });
78
+
79
+ //# sourceMappingURL=ClaudeAgentMapper.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/__tests__/providers/claude/ClaudeAgentMapper.test.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest';\n\nimport { AgentStatus, type ProcessInfo } from '../../../adapters/AgentAdapter.js';\nimport { ClaudeAgentMapper } from '../../../providers/claude/ClaudeAgentMapper.js';\nimport type { ClaudeSession } from '../../../providers/claude/ClaudeSessionParser.js';\nimport type { SessionFile } from '../../../utils/session.js';\n\nfunction makeProcess(overrides: Partial<ProcessInfo> = {}): ProcessInfo {\n return {\n pid: 123,\n command: 'claude',\n cwd: '/repo/my-app',\n tty: 'ttys001',\n ...overrides,\n };\n}\n\nfunction makeSession(overrides: Partial<ClaudeSession> = {}): ClaudeSession {\n return {\n sessionId: 'session-1',\n projectPath: '/repo/my-app',\n sessionStart: new Date('2026-08-23T10:00:00.000Z'),\n lastActive: new Date('2026-08-23T10:05:00.000Z'),\n lastEntryType: 'assistant',\n isInterrupted: false,\n lastUserMessage: 'Review this change',\n ...overrides,\n };\n}\n\nfunction makeSessionFile(overrides: Partial<SessionFile> = {}): SessionFile {\n return {\n sessionId: 'session-1',\n filePath: '/home/.claude/projects/-repo-my-app/session-1.jsonl',\n projectDir: '/home/.claude/projects/-repo-my-app',\n birthtimeMs: new Date('2026-08-23T10:00:00.000Z').getTime(),\n resolvedCwd: '/repo/my-app',\n ...overrides,\n };\n}\n\ndescribe('ClaudeAgentMapper', () => {\n it('prefers live PID-file status and waiting reason over JSONL-derived status', () => {\n const mapper = new ClaudeAgentMapper();\n\n const agent = mapper.mapSessionToAgent({\n session: makeSession({ lastEntryType: 'assistant' }),\n processInfo: makeProcess(),\n sessionFile: makeSessionFile(),\n liveInfo: {\n pidStatus: AgentStatus.WAITING,\n waitingFor: 'approve Read',\n },\n });\n\n expect(agent).toMatchObject({\n name: 'my-app-123',\n type: 'claude',\n status: AgentStatus.WAITING,\n summary: 'Review this change — waiting for approve Read',\n pid: 123,\n projectPath: '/repo/my-app',\n sessionId: 'session-1',\n sessionFilePath: '/home/.claude/projects/-repo-my-app/session-1.jsonl',\n });\n });\n\n it('maps unmatched processes to the existing process-only fallback shape', () => {\n const mapper = new ClaudeAgentMapper();\n\n const agent = mapper.mapProcessOnlyAgent(makeProcess({ pid: 456, cwd: '/repo/tooling' }));\n\n expect(agent).toMatchObject({\n name: 'tooling-456',\n type: 'claude',\n status: AgentStatus.IDLE,\n summary: 'Unknown',\n pid: 456,\n projectPath: '/repo/tooling',\n sessionId: 'pid-456',\n });\n expect(agent.lastActive).toBeInstanceOf(Date);\n });\n});\n"],"names":["describe","expect","it","AgentStatus","ClaudeAgentMapper","makeProcess","overrides","pid","command","cwd","tty","makeSession","sessionId","projectPath","sessionStart","Date","lastActive","lastEntryType","isInterrupted","lastUserMessage","makeSessionFile","filePath","projectDir","birthtimeMs","getTime","resolvedCwd","mapper","agent","mapSessionToAgent","session","processInfo","sessionFile","liveInfo","pidStatus","WAITING","waitingFor","toMatchObject","name","type","status","summary","sessionFilePath","mapProcessOnlyAgent","IDLE","toBeInstanceOf"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAS;AAE9C,SAASC,WAAW,QAA0B,oCAAoC;AAClF,SAASC,iBAAiB,QAAQ,iDAAiD;AAInF,SAASC,YAAYC,YAAkC,CAAC,CAAC;IACrD,OAAO;QACHC,KAAK;QACLC,SAAS;QACTC,KAAK;QACLC,KAAK;QACL,GAAGJ,SAAS;IAChB;AACJ;AAEA,SAASK,YAAYL,YAAoC,CAAC,CAAC;IACvD,OAAO;QACHM,WAAW;QACXC,aAAa;QACbC,cAAc,IAAIC,KAAK;QACvBC,YAAY,IAAID,KAAK;QACrBE,eAAe;QACfC,eAAe;QACfC,iBAAiB;QACjB,GAAGb,SAAS;IAChB;AACJ;AAEA,SAASc,gBAAgBd,YAAkC,CAAC,CAAC;IACzD,OAAO;QACHM,WAAW;QACXS,UAAU;QACVC,YAAY;QACZC,aAAa,IAAIR,KAAK,4BAA4BS,OAAO;QACzDC,aAAa;QACb,GAAGnB,SAAS;IAChB;AACJ;AAEAN,SAAS,qBAAqB;IAC1BE,GAAG,6EAA6E;QAC5E,MAAMwB,SAAS,IAAItB;QAEnB,MAAMuB,QAAQD,OAAOE,iBAAiB,CAAC;YACnCC,SAASlB,YAAY;gBAAEM,eAAe;YAAY;YAClDa,aAAazB;YACb0B,aAAaX;YACbY,UAAU;gBACNC,WAAW9B,YAAY+B,OAAO;gBAC9BC,YAAY;YAChB;QACJ;QAEAlC,OAAO0B,OAAOS,aAAa,CAAC;YACxBC,MAAM;YACNC,MAAM;YACNC,QAAQpC,YAAY+B,OAAO;YAC3BM,SAAS;YACTjC,KAAK;YACLM,aAAa;YACbD,WAAW;YACX6B,iBAAiB;QACrB;IACJ;IAEAvC,GAAG,wEAAwE;QACvE,MAAMwB,SAAS,IAAItB;QAEnB,MAAMuB,QAAQD,OAAOgB,mBAAmB,CAACrC,YAAY;YAAEE,KAAK;YAAKE,KAAK;QAAgB;QAEtFR,OAAO0B,OAAOS,aAAa,CAAC;YACxBC,MAAM;YACNC,MAAM;YACNC,QAAQpC,YAAYwC,IAAI;YACxBH,SAAS;YACTjC,KAAK;YACLM,aAAa;YACbD,WAAW;QACf;QACAX,OAAO0B,MAAMX,UAAU,EAAE4B,cAAc,CAAC7B;IAC5C;AACJ"}