@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.
- package/dist/AgentManager.d.ts +0 -4
- package/dist/AgentManager.d.ts.map +1 -1
- package/dist/AgentManager.js +2 -2
- package/dist/AgentManager.js.map +1 -1
- package/dist/__tests__/capacity/anthropic.test.js +115 -0
- package/dist/__tests__/capacity/anthropic.test.js.map +1 -0
- package/dist/__tests__/capacity/boundaries.test.js +45 -0
- package/dist/__tests__/capacity/boundaries.test.js.map +1 -0
- package/dist/__tests__/capacity/claude.test.js +3 -3
- package/dist/__tests__/capacity/claude.test.js.map +1 -1
- package/dist/__tests__/capacity/codex.test.js +3 -1
- package/dist/__tests__/capacity/codex.test.js.map +1 -1
- package/dist/__tests__/capacity/openai.test.js +21 -12
- package/dist/__tests__/capacity/openai.test.js.map +1 -1
- package/dist/__tests__/capacity/wham.test.js +1 -1
- package/dist/__tests__/capacity/wham.test.js.map +1 -1
- package/dist/__tests__/capacity/zai.test.js +7 -8
- package/dist/__tests__/capacity/zai.test.js.map +1 -1
- package/dist/__tests__/harnesses/claude/durable/ClaudePrintAgent.integration.test.js +2 -1
- package/dist/__tests__/harnesses/claude/durable/ClaudePrintAgent.integration.test.js.map +1 -1
- package/dist/__tests__/harnesses/claude/durable/ClaudePrintRunner.test.js.map +1 -1
- package/dist/__tests__/harnesses/codex/durable/CodexCliProbe.test.js +7 -15
- package/dist/__tests__/harnesses/codex/durable/CodexCliProbe.test.js.map +1 -1
- package/dist/__tests__/harnesses/codex/durable/CodexPrintAgent.integration.test.js +3 -1
- package/dist/__tests__/harnesses/codex/durable/CodexPrintAgent.integration.test.js.map +1 -1
- package/dist/__tests__/harnesses/codex/durable/CodexPrintAgentService.test.js +11 -26
- package/dist/__tests__/harnesses/codex/durable/CodexPrintAgentService.test.js.map +1 -1
- package/dist/__tests__/harnesses/codex/durable/CodexPrintRunner.test.js +3 -7
- package/dist/__tests__/harnesses/codex/durable/CodexPrintRunner.test.js.map +1 -1
- package/dist/__tests__/harnesses/pi/durable/PiCliProbe.test.js +5 -11
- package/dist/__tests__/harnesses/pi/durable/PiCliProbe.test.js.map +1 -1
- package/dist/__tests__/harnesses/pi/durable/PiPrintAgentService.test.js +9 -19
- package/dist/__tests__/harnesses/pi/durable/PiPrintAgentService.test.js.map +1 -1
- package/dist/__tests__/harnesses/pi/durable/PiPrintRunner.test.js +3 -7
- package/dist/__tests__/harnesses/pi/durable/PiPrintRunner.test.js.map +1 -1
- package/dist/__tests__/{readiness → harnesses/readiness}/AgentReadiness.test.js +31 -10
- package/dist/__tests__/harnesses/readiness/AgentReadiness.test.js.map +1 -0
- package/dist/__tests__/harnesses/runtimeProfiles.test.js +89 -0
- package/dist/__tests__/harnesses/runtimeProfiles.test.js.map +1 -0
- package/dist/__tests__/print/DurableAgent.test.js +4 -6
- package/dist/__tests__/print/DurableAgent.test.js.map +1 -1
- package/dist/__tests__/print/DurableAgentRepository.test.js +1 -12
- package/dist/__tests__/print/DurableAgentRepository.test.js.map +1 -1
- package/dist/__tests__/runtime/ManagedAgentRuntime.test.js.map +1 -1
- package/dist/__tests__/terminal/TmuxManager.test.js +1 -1
- package/dist/__tests__/terminal/TmuxManager.test.js.map +1 -1
- package/dist/capacity/index.d.ts +9 -19
- package/dist/capacity/index.d.ts.map +1 -1
- package/dist/capacity/index.js +11 -4
- package/dist/capacity/index.js.map +1 -1
- package/dist/capacity/providers/anthropic.d.ts +9 -0
- package/dist/capacity/providers/anthropic.d.ts.map +1 -0
- package/dist/capacity/{claude.js → providers/anthropic.js} +10 -128
- package/dist/capacity/providers/anthropic.js.map +1 -0
- package/dist/capacity/providers/openai-platform.d.ts +14 -0
- package/dist/capacity/providers/openai-platform.d.ts.map +1 -0
- package/dist/capacity/providers/openai-platform.js +120 -0
- package/dist/capacity/providers/openai-platform.js.map +1 -0
- package/dist/capacity/providers/openai-subscription.d.ts +20 -0
- package/dist/capacity/providers/openai-subscription.d.ts.map +1 -0
- package/dist/capacity/providers/openai-subscription.js +129 -0
- package/dist/capacity/providers/openai-subscription.js.map +1 -0
- package/dist/capacity/providers/zai.d.ts +8 -0
- package/dist/capacity/providers/zai.d.ts.map +1 -0
- package/dist/capacity/{zai.js → providers/zai.js} +17 -62
- package/dist/capacity/providers/zai.js.map +1 -0
- package/dist/capacity/sources/claude.d.ts +9 -0
- package/dist/capacity/sources/claude.d.ts.map +1 -0
- package/dist/capacity/sources/claude.js +17 -0
- package/dist/capacity/sources/claude.js.map +1 -0
- package/dist/capacity/{codex.d.ts → sources/codex.d.ts} +5 -9
- package/dist/capacity/sources/codex.d.ts.map +1 -0
- package/dist/capacity/{codex.js → sources/codex.js} +31 -84
- package/dist/capacity/sources/codex.js.map +1 -0
- package/dist/capacity/sources/pi.d.ts +30 -0
- package/dist/capacity/sources/pi.d.ts.map +1 -0
- package/dist/capacity/sources/pi.js +81 -0
- package/dist/capacity/sources/pi.js.map +1 -0
- package/dist/capacity/types.d.ts +2 -0
- package/dist/capacity/types.d.ts.map +1 -1
- package/dist/capacity/types.js +1 -1
- package/dist/capacity/types.js.map +1 -1
- package/dist/harnesses/claude/credentials.d.ts +10 -0
- package/dist/harnesses/claude/credentials.d.ts.map +1 -0
- package/dist/harnesses/claude/credentials.js +112 -0
- package/dist/harnesses/claude/credentials.js.map +1 -0
- package/dist/harnesses/claude/readiness.d.ts +3 -0
- package/dist/harnesses/claude/readiness.d.ts.map +1 -0
- package/dist/harnesses/claude/readiness.js +63 -0
- package/dist/harnesses/claude/readiness.js.map +1 -0
- package/dist/harnesses/codex/credentials.d.ts +15 -0
- package/dist/harnesses/codex/credentials.d.ts.map +1 -0
- package/dist/harnesses/codex/credentials.js +58 -0
- package/dist/harnesses/codex/credentials.js.map +1 -0
- package/dist/harnesses/codex/readiness.d.ts +3 -0
- package/dist/harnesses/codex/readiness.d.ts.map +1 -0
- package/dist/harnesses/codex/readiness.js +60 -0
- package/dist/harnesses/codex/readiness.js.map +1 -0
- package/dist/harnesses/copilot/readiness.d.ts +3 -0
- package/dist/harnesses/copilot/readiness.d.ts.map +1 -0
- package/dist/harnesses/copilot/readiness.js +39 -0
- package/dist/harnesses/copilot/readiness.js.map +1 -0
- package/dist/harnesses/opencode/readiness.d.ts +3 -0
- package/dist/harnesses/opencode/readiness.d.ts.map +1 -0
- package/dist/harnesses/opencode/readiness.js +50 -0
- package/dist/harnesses/opencode/readiness.js.map +1 -0
- package/dist/harnesses/pi/credentials.d.ts +22 -0
- package/dist/harnesses/pi/credentials.d.ts.map +1 -0
- package/dist/harnesses/pi/credentials.js +98 -0
- package/dist/harnesses/pi/credentials.js.map +1 -0
- package/dist/harnesses/pi/readiness.d.ts +3 -0
- package/dist/harnesses/pi/readiness.d.ts.map +1 -0
- package/dist/harnesses/pi/readiness.js +96 -0
- package/dist/harnesses/pi/readiness.js.map +1 -0
- package/dist/harnesses/readiness/AgentReadiness.d.ts +6 -0
- package/dist/harnesses/readiness/AgentReadiness.d.ts.map +1 -0
- package/dist/harnesses/readiness/AgentReadiness.js +68 -0
- package/dist/harnesses/readiness/AgentReadiness.js.map +1 -0
- package/dist/harnesses/readiness/checks.d.ts +31 -0
- package/dist/harnesses/readiness/checks.d.ts.map +1 -0
- package/dist/harnesses/readiness/checks.js +270 -0
- package/dist/harnesses/readiness/checks.js.map +1 -0
- package/dist/{readiness/AgentReadiness.d.ts → harnesses/readiness/types.d.ts} +19 -10
- package/dist/harnesses/readiness/types.d.ts.map +1 -0
- package/dist/harnesses/readiness/types.js +4 -0
- package/dist/harnesses/readiness/types.js.map +1 -0
- package/dist/harnesses/runtimeProfiles.d.ts +11 -0
- package/dist/harnesses/runtimeProfiles.d.ts.map +1 -0
- package/dist/harnesses/runtimeProfiles.js +99 -0
- package/dist/harnesses/runtimeProfiles.js.map +1 -0
- package/dist/index.d.ts +16 -42
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -23
- package/dist/index.js.map +1 -1
- package/dist/runtime/ManagedAgentRuntime.d.ts +3 -3
- package/dist/runtime/ManagedAgentRuntime.d.ts.map +1 -1
- package/dist/runtime/ManagedAgentRuntime.js +6 -20
- package/dist/runtime/ManagedAgentRuntime.js.map +1 -1
- package/dist/runtime/herdr/HerdrAgentDiscovery.d.ts.map +1 -1
- package/dist/runtime/herdr/HerdrAgentDiscovery.js +2 -43
- package/dist/runtime/herdr/HerdrAgentDiscovery.js.map +1 -1
- package/dist/runtime/tmux/PidPolling.d.ts +1 -1
- package/dist/runtime/tmux/PidPolling.d.ts.map +1 -1
- package/dist/runtime/tmux/PidPolling.js.map +1 -1
- package/dist/runtime/tmux/TmuxAgentRuntime.d.ts +1 -1
- package/dist/runtime/tmux/TmuxAgentRuntime.d.ts.map +1 -1
- package/dist/runtime/tmux/TmuxAgentRuntime.js +1 -1
- package/dist/runtime/tmux/TmuxAgentRuntime.js.map +1 -1
- package/dist/runtime/tmux/TmuxManager.d.ts +12 -0
- package/dist/runtime/tmux/TmuxManager.d.ts.map +1 -0
- package/dist/{terminal → runtime/tmux}/TmuxManager.js +9 -28
- package/dist/runtime/tmux/TmuxManager.js.map +1 -0
- package/dist/runtime/types.d.ts +1 -1
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js.map +1 -1
- package/dist/terminal/TerminalFocusManager.d.ts +4 -32
- package/dist/terminal/TerminalFocusManager.d.ts.map +1 -1
- package/dist/terminal/TerminalFocusManager.js +17 -267
- package/dist/terminal/TerminalFocusManager.js.map +1 -1
- package/dist/terminal/TtyWriter.d.ts +1 -44
- package/dist/terminal/TtyWriter.d.ts.map +1 -1
- package/dist/terminal/TtyWriter.js +11 -347
- package/dist/terminal/TtyWriter.js.map +1 -1
- package/dist/terminal/backends/index.d.ts +5 -0
- package/dist/terminal/backends/index.d.ts.map +1 -0
- package/dist/terminal/backends/index.js +19 -0
- package/dist/terminal/backends/index.js.map +1 -0
- package/dist/terminal/backends/iterm2.d.ts +3 -0
- package/dist/terminal/backends/iterm2.d.ts.map +1 -0
- package/dist/terminal/backends/iterm2.js +135 -0
- package/dist/terminal/backends/iterm2.js.map +1 -0
- package/dist/terminal/backends/shared.d.ts +7 -0
- package/dist/terminal/backends/shared.d.ts.map +1 -0
- package/dist/terminal/backends/shared.js +35 -0
- package/dist/terminal/backends/shared.js.map +1 -0
- package/dist/terminal/backends/terminal-app.d.ts +3 -0
- package/dist/terminal/backends/terminal-app.d.ts.map +1 -0
- package/dist/terminal/backends/terminal-app.js +129 -0
- package/dist/terminal/backends/terminal-app.js.map +1 -0
- package/dist/terminal/backends/tmux.d.ts +3 -0
- package/dist/terminal/backends/tmux.d.ts.map +1 -0
- package/dist/terminal/backends/tmux.js +76 -0
- package/dist/terminal/backends/tmux.js.map +1 -0
- package/dist/terminal/backends/wezterm.d.ts +3 -0
- package/dist/terminal/backends/wezterm.d.ts.map +1 -0
- package/dist/terminal/backends/wezterm.js +71 -0
- package/dist/terminal/backends/wezterm.js.map +1 -0
- package/dist/terminal/types.d.ts +21 -0
- package/dist/terminal/types.d.ts.map +1 -0
- package/dist/terminal/types.js +10 -0
- package/dist/terminal/types.js.map +1 -0
- package/package.json +1 -1
- package/src/AgentManager.ts +1 -1
- package/src/__tests__/capacity/anthropic.test.ts +105 -0
- package/src/__tests__/capacity/boundaries.test.ts +36 -0
- package/src/__tests__/capacity/claude.test.ts +3 -8
- package/src/__tests__/capacity/codex.test.ts +12 -35
- package/src/__tests__/capacity/fixtures/openai-codex-auth.json +1 -1
- package/src/__tests__/capacity/openai.test.ts +15 -15
- package/src/__tests__/capacity/wham.test.ts +1 -1
- package/src/__tests__/capacity/zai.test.ts +27 -62
- package/src/__tests__/harnesses/claude/durable/ClaudePrintAgent.integration.test.ts +2 -2
- package/src/__tests__/harnesses/claude/durable/ClaudePrintRunner.test.ts +1 -1
- package/src/__tests__/harnesses/codex/durable/CodexCliProbe.test.ts +14 -19
- package/src/__tests__/harnesses/codex/durable/CodexPrintAgent.integration.test.ts +3 -3
- package/src/__tests__/harnesses/codex/durable/CodexPrintAgentService.test.ts +24 -30
- package/src/__tests__/harnesses/codex/durable/CodexPrintRunner.test.ts +4 -8
- package/src/__tests__/harnesses/pi/durable/PiCliProbe.test.ts +7 -11
- package/src/__tests__/harnesses/pi/durable/PiPrintAgentService.test.ts +19 -22
- package/src/__tests__/harnesses/pi/durable/PiPrintRunner.test.ts +7 -8
- package/src/__tests__/{readiness → harnesses/readiness}/AgentReadiness.test.ts +36 -9
- package/src/__tests__/harnesses/runtimeProfiles.test.ts +110 -0
- package/src/__tests__/print/DurableAgent.test.ts +4 -13
- package/src/__tests__/print/DurableAgentRepository.test.ts +1 -13
- package/src/__tests__/runtime/ManagedAgentRuntime.test.ts +1 -1
- package/src/__tests__/terminal/TmuxManager.test.ts +1 -1
- package/src/capacity/index.ts +29 -23
- package/src/capacity/{claude.ts → providers/anthropic.ts} +16 -131
- package/src/capacity/providers/openai-platform.ts +150 -0
- package/src/capacity/{wham.ts → providers/openai-subscription.ts} +86 -8
- package/src/capacity/{zai.ts → providers/zai.ts} +29 -111
- package/src/capacity/sources/claude.ts +30 -0
- package/src/capacity/{codex.ts → sources/codex.ts} +54 -124
- package/src/capacity/sources/pi.ts +131 -0
- package/src/capacity/types.ts +3 -0
- package/src/harnesses/claude/credentials.ts +122 -0
- package/src/harnesses/claude/readiness.ts +69 -0
- package/src/harnesses/codex/credentials.ts +81 -0
- package/src/harnesses/codex/readiness.ts +72 -0
- package/src/harnesses/copilot/readiness.ts +33 -0
- package/src/harnesses/opencode/readiness.ts +48 -0
- package/src/harnesses/pi/credentials.ts +129 -0
- package/src/harnesses/pi/readiness.ts +104 -0
- package/src/harnesses/readiness/AgentReadiness.ts +87 -0
- package/src/harnesses/readiness/checks.ts +336 -0
- package/src/harnesses/readiness/types.ts +90 -0
- package/src/{utils/agents.ts → harnesses/runtimeProfiles.ts} +34 -38
- package/src/index.ts +15 -128
- package/src/runtime/ManagedAgentRuntime.ts +7 -22
- package/src/runtime/herdr/HerdrAgentDiscovery.ts +3 -19
- package/src/runtime/tmux/PidPolling.ts +1 -1
- package/src/runtime/tmux/TmuxAgentRuntime.ts +1 -1
- package/src/{terminal → runtime/tmux}/TmuxManager.ts +9 -30
- package/src/runtime/types.ts +1 -1
- package/src/terminal/TerminalFocusManager.ts +19 -292
- package/src/terminal/TtyWriter.ts +16 -336
- package/src/terminal/backends/index.ts +21 -0
- package/src/terminal/backends/iterm2.ts +126 -0
- package/src/terminal/backends/shared.ts +42 -0
- package/src/terminal/backends/terminal-app.ts +122 -0
- package/src/terminal/backends/tmux.ts +62 -0
- package/src/terminal/backends/wezterm.ts +65 -0
- package/src/terminal/types.ts +22 -0
- package/dist/__tests__/readiness/AgentReadiness.test.js.map +0 -1
- package/dist/__tests__/utils/agents.test.js +0 -93
- package/dist/__tests__/utils/agents.test.js.map +0 -1
- package/dist/capacity/claude.d.ts +0 -17
- package/dist/capacity/claude.d.ts.map +0 -1
- package/dist/capacity/claude.js.map +0 -1
- package/dist/capacity/codex.d.ts.map +0 -1
- package/dist/capacity/codex.js.map +0 -1
- package/dist/capacity/openai.d.ts +0 -47
- package/dist/capacity/openai.d.ts.map +0 -1
- package/dist/capacity/openai.js +0 -307
- package/dist/capacity/openai.js.map +0 -1
- package/dist/capacity/wham.d.ts +0 -16
- package/dist/capacity/wham.d.ts.map +0 -1
- package/dist/capacity/wham.js +0 -66
- package/dist/capacity/wham.js.map +0 -1
- package/dist/capacity/zai.d.ts +0 -14
- package/dist/capacity/zai.d.ts.map +0 -1
- package/dist/capacity/zai.js.map +0 -1
- package/dist/readiness/AgentReadiness.d.ts.map +0 -1
- package/dist/readiness/AgentReadiness.js +0 -614
- package/dist/readiness/AgentReadiness.js.map +0 -1
- package/dist/terminal/TmuxManager.d.ts +0 -28
- package/dist/terminal/TmuxManager.d.ts.map +0 -1
- package/dist/terminal/TmuxManager.js.map +0 -1
- package/dist/terminal/index.d.ts +0 -5
- package/dist/terminal/index.d.ts.map +0 -1
- package/dist/terminal/index.js +0 -5
- package/dist/terminal/index.js.map +0 -1
- package/dist/utils/agents.d.ts +0 -16
- package/dist/utils/agents.d.ts.map +0 -1
- package/dist/utils/agents.js +0 -117
- package/dist/utils/agents.js.map +0 -1
- package/dist/utils/index.d.ts +0 -8
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -6
- package/dist/utils/index.js.map +0 -1
- package/src/__tests__/utils/agents.test.ts +0 -105
- package/src/capacity/openai.ts +0 -355
- package/src/readiness/AgentReadiness.ts +0 -730
- package/src/terminal/index.ts +0 -4
- package/src/utils/index.ts +0 -14
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/__tests__/harnesses/claude/durable/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 \"../../../../
|
|
1
|
+
{"version":3,"sources":["../../../../../src/__tests__/harnesses/claude/durable/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 \"../../../../durable/DurableAgent.js\";\nimport { ClaudePrintRunner } from \"../../../../harnesses/claude/durable/ClaudePrintRunner.js\";\n\nfunction agent(): DurableAgent {\n return {\n id: \"11111111-1111-4111-8111-111111111111\",\n name: \"reviewer\",\n provider: \"claude\",\n mode: \"durable\",\n cwd: \"/project\",\n providerSessionId: \"22222222-2222-4222-8222-222222222222\",\n state: \"running\",\n sessionHealth: \"uninitialized\",\n createdAt: \"\",\n updatedAt: \"\",\n lastActiveAt: null,\n 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) {\n promptChunks.push(Buffer.from(chunk));\n callback();\n },\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[]) => {\n calls.push(args);\n return child;\n });\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({\n spawn: fixture.spawn,\n processInspector: {\n getIdentity: () => ({ pid: 4242, startedAt: \"provider-start\" }),\n },\n });\n\n const result = await runner.run({\n agent: agent(),\n prompt: \"secret prompt\",\n executable: \"claude-test\",\n firstRun: true,\n onSpawn: async () => {\n expect(fixture.promptChunks).toHaveLength(0);\n persisted = true;\n },\n });\n\n expect(persisted).toBe(true);\n expect(fixture.calls[0]).toEqual([\n \"claude-test\",\n [\n \"-p\",\n \"--session-id\",\n agent().providerSessionId,\n \"--output-format\",\n \"stream-json\",\n \"--verbose\",\n ],\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({\n spawn: fixture.spawn,\n processInspector: {\n getIdentity: () => ({ pid: 4242, startedAt: \"provider-start\" }),\n },\n });\n\n await expect(\n runner.run({\n agent: agent(),\n prompt: \"followup\",\n executable: \"claude\",\n firstRun: false,\n onSpawn: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"CLAUDE_SESSION_MISMATCH\" });\n expect(fixture.calls[0]![1]).toEqual([\n \"-p\",\n \"--resume\",\n agent().providerSessionId,\n \"--output-format\",\n \"stream-json\",\n \"--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({\n spawn: fixture.spawn,\n processInspector: {\n getIdentity: () => ({ pid: 4242, startedAt: \"provider-start\" }),\n },\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(\n runner.run({\n agent: agent(),\n prompt: \"secret prompt\",\n firstRun: true,\n onSpawn: vi.fn(),\n }),\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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"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { CodexCliProbe } from "../../../../harnesses/codex/durable/CodexCliProbe.js";
|
|
2
3
|
describe("CodexCliProbe", ()=>{
|
|
3
4
|
it("validates version, exec JSON/stdin, and resume capabilities without a model call", async ()=>{
|
|
4
|
-
const api = await import("../../../../index.js");
|
|
5
|
-
expect(api).toHaveProperty("CodexCliProbe");
|
|
6
5
|
const exec = vi.fn().mockResolvedValueOnce({
|
|
7
6
|
stdout: "codex-cli 0.147.0",
|
|
8
7
|
stderr: ""
|
|
@@ -13,8 +12,7 @@ describe("CodexCliProbe", ()=>{
|
|
|
13
12
|
stdout: "Usage: codex exec resume [SESSION_ID] [PROMPT]\n--json\n- stdin",
|
|
14
13
|
stderr: ""
|
|
15
14
|
});
|
|
16
|
-
|
|
17
|
-
await expect(new Probe({
|
|
15
|
+
await expect(new CodexCliProbe({
|
|
18
16
|
executable: "fake-codex",
|
|
19
17
|
exec
|
|
20
18
|
}).validate()).resolves.toEqual({
|
|
@@ -46,9 +44,7 @@ describe("CodexCliProbe", ()=>{
|
|
|
46
44
|
]);
|
|
47
45
|
});
|
|
48
46
|
it("rejects unsupported and unavailable CLIs with bounded sanitized errors", async ()=>{
|
|
49
|
-
const
|
|
50
|
-
const Probe = api.CodexCliProbe;
|
|
51
|
-
const unsupported = new Probe({
|
|
47
|
+
const unsupported = new CodexCliProbe({
|
|
52
48
|
exec: vi.fn().mockResolvedValueOnce({
|
|
53
49
|
stdout: "version",
|
|
54
50
|
stderr: ""
|
|
@@ -63,7 +59,7 @@ describe("CodexCliProbe", ()=>{
|
|
|
63
59
|
await expect(unsupported.validate()).rejects.toMatchObject({
|
|
64
60
|
code: "CODEX_CLI_UNSUPPORTED"
|
|
65
61
|
});
|
|
66
|
-
const missingCommands = new
|
|
62
|
+
const missingCommands = new CodexCliProbe({
|
|
67
63
|
exec: vi.fn().mockResolvedValueOnce({
|
|
68
64
|
stdout: "version",
|
|
69
65
|
stderr: ""
|
|
@@ -78,7 +74,7 @@ describe("CodexCliProbe", ()=>{
|
|
|
78
74
|
await expect(missingCommands.validate()).rejects.toMatchObject({
|
|
79
75
|
code: "CODEX_CLI_UNSUPPORTED"
|
|
80
76
|
});
|
|
81
|
-
const unavailable = new
|
|
77
|
+
const unavailable = new CodexCliProbe({
|
|
82
78
|
exec: vi.fn().mockRejectedValue(new Error(`bad\0${"x".repeat(1000)}`))
|
|
83
79
|
});
|
|
84
80
|
const error = await unavailable.validate().catch((value)=>value);
|
|
@@ -87,8 +83,6 @@ describe("CodexCliProbe", ()=>{
|
|
|
87
83
|
expect(error.message.length).toBeLessThan(600);
|
|
88
84
|
});
|
|
89
85
|
it("reports an empty version response as unknown", async ()=>{
|
|
90
|
-
const api = await import("../../../../index.js");
|
|
91
|
-
const Probe = api.CodexCliProbe;
|
|
92
86
|
const exec = vi.fn().mockResolvedValueOnce({
|
|
93
87
|
stdout: " \n",
|
|
94
88
|
stderr: ""
|
|
@@ -99,15 +93,13 @@ describe("CodexCliProbe", ()=>{
|
|
|
99
93
|
stdout: "resume --json -",
|
|
100
94
|
stderr: ""
|
|
101
95
|
});
|
|
102
|
-
await expect(new
|
|
96
|
+
await expect(new CodexCliProbe({
|
|
103
97
|
exec
|
|
104
98
|
}).validate()).resolves.toMatchObject({
|
|
105
99
|
version: "unknown"
|
|
106
100
|
});
|
|
107
101
|
});
|
|
108
102
|
it("requires a standalone stdin dash rather than accepting flag hyphens", async ()=>{
|
|
109
|
-
const api = await import("../../../../index.js");
|
|
110
|
-
const Probe = api.CodexCliProbe;
|
|
111
103
|
const exec = vi.fn().mockResolvedValueOnce({
|
|
112
104
|
stdout: "version",
|
|
113
105
|
stderr: ""
|
|
@@ -118,7 +110,7 @@ describe("CodexCliProbe", ()=>{
|
|
|
118
110
|
stdout: "resume --json",
|
|
119
111
|
stderr: ""
|
|
120
112
|
});
|
|
121
|
-
await expect(new
|
|
113
|
+
await expect(new CodexCliProbe({
|
|
122
114
|
exec
|
|
123
115
|
}).validate()).rejects.toMatchObject({
|
|
124
116
|
code: "CODEX_CLI_UNSUPPORTED"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/__tests__/harnesses/codex/durable/CodexCliProbe.test.ts"],"sourcesContent":["import { describe, expect, it, vi } from \"vitest\";\n\ndescribe(\"CodexCliProbe\", () => {\n it(\"validates version, exec JSON/stdin, and resume capabilities without a model call\", async () => {\n const
|
|
1
|
+
{"version":3,"sources":["../../../../../src/__tests__/harnesses/codex/durable/CodexCliProbe.test.ts"],"sourcesContent":["import { describe, expect, it, vi } from \"vitest\";\nimport { CodexCliProbe } from \"../../../../harnesses/codex/durable/CodexCliProbe.js\";\n\ndescribe(\"CodexCliProbe\", () => {\n it(\"validates version, exec JSON/stdin, and resume capabilities without a model call\", async () => {\n const exec = vi\n .fn()\n .mockResolvedValueOnce({ stdout: \"codex-cli 0.147.0\", stderr: \"\" })\n .mockResolvedValueOnce({\n stdout: \"Usage: codex exec [PROMPT]\\n--json\\n- read from stdin\\nresume\",\n stderr: \"\",\n })\n .mockResolvedValueOnce({\n stdout: \"Usage: codex exec resume [SESSION_ID] [PROMPT]\\n--json\\n- stdin\",\n stderr: \"\",\n });\n await expect(new CodexCliProbe({ executable: \"fake-codex\", exec }).validate()).resolves.toEqual(\n {\n executable: \"fake-codex\",\n version: \"codex-cli 0.147.0\",\n },\n );\n expect(exec.mock.calls).toEqual([\n [\"fake-codex\", [\"--version\"]],\n [\"fake-codex\", [\"exec\", \"--help\"]],\n [\"fake-codex\", [\"exec\", \"resume\", \"--help\"]],\n ]);\n });\n\n it(\"rejects unsupported and unavailable CLIs with bounded sanitized errors\", async () => {\n const unsupported = new CodexCliProbe({\n exec: vi\n .fn()\n .mockResolvedValueOnce({ stdout: \"version\", stderr: \"\" })\n .mockResolvedValueOnce({ stdout: \"exec\", stderr: \"\" })\n .mockResolvedValueOnce({ stdout: \"resume\", stderr: \"\" }),\n });\n await expect(unsupported.validate()).rejects.toMatchObject({ code: \"CODEX_CLI_UNSUPPORTED\" });\n const missingCommands = new CodexCliProbe({\n exec: vi\n .fn()\n .mockResolvedValueOnce({ stdout: \"version\", stderr: \"\" })\n .mockResolvedValueOnce({ stdout: \"\", stderr: \"\" })\n .mockResolvedValueOnce({ stdout: \"\", stderr: \"\" }),\n });\n await expect(missingCommands.validate()).rejects.toMatchObject({\n code: \"CODEX_CLI_UNSUPPORTED\",\n });\n\n const unavailable = new CodexCliProbe({\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(\"CODEX_CLI_UNAVAILABLE\");\n expect(error.message).not.toContain(\"\\0\");\n expect(error.message.length).toBeLessThan(600);\n });\n\n it(\"reports an empty version response as unknown\", async () => {\n const exec = vi\n .fn()\n .mockResolvedValueOnce({ stdout: \" \\n\", stderr: \"\" })\n .mockResolvedValueOnce({ stdout: \"exec --json -\", stderr: \"\" })\n .mockResolvedValueOnce({ stdout: \"resume --json -\", stderr: \"\" });\n await expect(new CodexCliProbe({ exec }).validate()).resolves.toMatchObject({\n version: \"unknown\",\n });\n });\n\n it(\"requires a standalone stdin dash rather than accepting flag hyphens\", async () => {\n const exec = vi\n .fn()\n .mockResolvedValueOnce({ stdout: \"version\", stderr: \"\" })\n .mockResolvedValueOnce({ stdout: \"exec --json\", stderr: \"\" })\n .mockResolvedValueOnce({ stdout: \"resume --json\", stderr: \"\" });\n await expect(new CodexCliProbe({ exec }).validate()).rejects.toMatchObject({\n code: \"CODEX_CLI_UNSUPPORTED\",\n });\n });\n});\n"],"names":["describe","expect","it","vi","CodexCliProbe","exec","fn","mockResolvedValueOnce","stdout","stderr","executable","validate","resolves","toEqual","version","mock","calls","unsupported","rejects","toMatchObject","code","missingCommands","unavailable","mockRejectedValue","Error","repeat","error","catch","value","toBe","message","not","toContain","length","toBeLessThan"],"mappings":"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"}
|
|
@@ -2,7 +2,9 @@ import fs from "node:fs";
|
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
5
|
-
import { CodexPrintError
|
|
5
|
+
import { CodexPrintError } from "../../../../durable/DurableAgent.js";
|
|
6
|
+
import { DurableAgentRepository } from "../../../../durable/DurableAgentRepository.js";
|
|
7
|
+
import { CodexPrintAgentService } from "../../../../harnesses/codex/durable/CodexPrintAgentService.js";
|
|
6
8
|
const SESSION = "22222222-2222-4222-8222-222222222222";
|
|
7
9
|
const roots = [];
|
|
8
10
|
afterEach(()=>{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/__tests__/harnesses/codex/durable/CodexPrintAgent.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
|
|
1
|
+
{"version":3,"sources":["../../../../../src/__tests__/harnesses/codex/durable/CodexPrintAgent.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 { CodexPrintError } from \"../../../../durable/DurableAgent.js\";\nimport {\n DurableAgentRepository,\n type ProcessInspector,\n} from \"../../../../durable/DurableAgentRepository.js\";\nimport { CodexPrintAgentService } from \"../../../../harnesses/codex/durable/CodexPrintAgentService.js\";\n\nconst SESSION = \"22222222-2222-4222-8222-222222222222\";\nconst roots: string[] = [];\n\nafterEach(() => {\n for (const root of roots.splice(0)) fs.rmSync(root, { recursive: true, force: true });\n});\n\ndescribe(\"Codex print-agent fake-provider journey\", () => {\n it(\"creates unbound, then binds and explicitly resumes the provider-minted session\", async () => {\n const root = fs.mkdtempSync(path.join(os.tmpdir(), \"codex-print-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, \"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 await request.onSession(SESSION);\n return {\n sessionId: SESSION,\n result: `answer:${request.prompt}`,\n messages: [`answer:${request.prompt}`],\n exitCode: 0,\n };\n }),\n };\n const service = new CodexPrintAgentService({\n repository,\n probe: { validate: vi.fn() },\n runner,\n });\n\n const created = await service.create({ name: \"reviewer\", cwd });\n expect(created).toMatchObject({\n provider: \"codex\",\n providerSessionId: null,\n sessionHealth: \"uninitialized\",\n });\n\n const first = await service.send(created.id, \"first secret\");\n expect(first).toMatchObject({ result: \"answer:first secret\" });\n const bound = await repository.getById(created.id);\n expect(bound?.providerSessionId).toBe(first.sessionId);\n await expect(service.send(created.id, \"follow up\")).resolves.toMatchObject({\n result: \"answer:follow up\",\n });\n\n expect(runner.run.mock.calls[0][0].agent).toMatchObject({ providerSessionId: null });\n expect(runner.run.mock.calls[1][0].agent).toMatchObject({ providerSessionId: SESSION });\n });\n\n it(\"retains a first-run binding when the provider fails after thread start\", async () => {\n const root = fs.mkdtempSync(path.join(os.tmpdir(), \"codex-print-bind-failure-\"));\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, \"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 await request.onSession(SESSION);\n throw new CodexPrintError(\"Codex print run failed.\", \"CODEX_PROCESS\");\n }),\n };\n const service = new CodexPrintAgentService({\n repository,\n probe: { validate: vi.fn() },\n runner,\n });\n const created = await service.create({ name: \"reviewer\", cwd });\n\n await expect(service.send(created.id, \"secret\")).rejects.toMatchObject({\n code: \"CODEX_PROCESS\",\n });\n expect(await repository.getById(created.id)).toMatchObject({\n providerSessionId: SESSION,\n state: \"degraded\",\n sessionHealth: \"unknown\",\n });\n });\n});\n"],"names":["fs","os","path","afterEach","describe","expect","it","vi","CodexPrintError","DurableAgentRepository","CodexPrintAgentService","SESSION","roots","root","splice","rmSync","recursive","force","mkdtempSync","join","tmpdir","push","cwd","mkdirSync","processInspector","getIdentity","pid","startedAt","repository","dbPath","runner","run","fn","mockImplementation","request","onSpawn","onSession","sessionId","result","prompt","messages","exitCode","service","probe","validate","created","create","name","toMatchObject","provider","providerSessionId","sessionHealth","first","send","id","bound","getById","toBe","resolves","mock","calls","agent","rejects","code","state"],"mappings":"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"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { CodexPrintError } from "../../../../durable/DurableAgent.js";
|
|
3
|
+
import { CodexPrintAgentService } from "../../../../harnesses/codex/durable/CodexPrintAgentService.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("CodexPrintAgentService", ()=>{
|
|
11
13
|
it("validates before provider-aware create and never runs Codex", async ()=>{
|
|
12
|
-
const api = await import("../../../../index.js");
|
|
13
|
-
expect(api).toHaveProperty("CodexPrintAgentService");
|
|
14
14
|
const probe = {
|
|
15
15
|
validate: vi.fn().mockResolvedValue({
|
|
16
16
|
executable: "codex",
|
|
@@ -23,8 +23,7 @@ describe("CodexPrintAgentService", ()=>{
|
|
|
23
23
|
const runner = {
|
|
24
24
|
run: vi.fn()
|
|
25
25
|
};
|
|
26
|
-
|
|
27
|
-
await new Service({
|
|
26
|
+
await new CodexPrintAgentService({
|
|
28
27
|
repository,
|
|
29
28
|
probe,
|
|
30
29
|
runner
|
|
@@ -40,7 +39,6 @@ describe("CodexPrintAgentService", ()=>{
|
|
|
40
39
|
expect(runner.run).not.toHaveBeenCalled();
|
|
41
40
|
});
|
|
42
41
|
it("binds during first send and explicitly resumes later sends", async ()=>{
|
|
43
|
-
const api = await import("../../../../index.js");
|
|
44
42
|
const repository = {
|
|
45
43
|
resolve: vi.fn().mockResolvedValue(base),
|
|
46
44
|
acquireRun: vi.fn().mockResolvedValueOnce({
|
|
@@ -75,8 +73,7 @@ describe("CodexPrintAgentService", ()=>{
|
|
|
75
73
|
};
|
|
76
74
|
})
|
|
77
75
|
};
|
|
78
|
-
const
|
|
79
|
-
const service = new Service({
|
|
76
|
+
const service = new CodexPrintAgentService({
|
|
80
77
|
repository,
|
|
81
78
|
probe: {
|
|
82
79
|
validate: vi.fn()
|
|
@@ -94,8 +91,6 @@ describe("CodexPrintAgentService", ()=>{
|
|
|
94
91
|
}));
|
|
95
92
|
});
|
|
96
93
|
it("records mismatch separately from unknown failures", async ()=>{
|
|
97
|
-
const api = await import("../../../../index.js");
|
|
98
|
-
const ErrorType = api.CodexPrintError;
|
|
99
94
|
const completeRun = vi.fn();
|
|
100
95
|
const repository = {
|
|
101
96
|
resolve: vi.fn().mockResolvedValue(base),
|
|
@@ -107,14 +102,13 @@ describe("CodexPrintAgentService", ()=>{
|
|
|
107
102
|
bindProviderSession: vi.fn(),
|
|
108
103
|
completeRun
|
|
109
104
|
};
|
|
110
|
-
const
|
|
111
|
-
const service = new Service({
|
|
105
|
+
const service = new CodexPrintAgentService({
|
|
112
106
|
repository,
|
|
113
107
|
probe: {
|
|
114
108
|
validate: vi.fn()
|
|
115
109
|
},
|
|
116
110
|
runner: {
|
|
117
|
-
run: vi.fn().mockRejectedValue(new
|
|
111
|
+
run: vi.fn().mockRejectedValue(new CodexPrintError("mismatch", "CODEX_SESSION_MISMATCH"))
|
|
118
112
|
}
|
|
119
113
|
});
|
|
120
114
|
await expect(service.send("reviewer", "x")).rejects.toMatchObject({
|
|
@@ -125,8 +119,6 @@ describe("CodexPrintAgentService", ()=>{
|
|
|
125
119
|
}));
|
|
126
120
|
});
|
|
127
121
|
it("rejects a non-Codex target without acquiring or mutating it", async ()=>{
|
|
128
|
-
const api = await import("../../../../index.js");
|
|
129
|
-
const Service = api.CodexPrintAgentService;
|
|
130
122
|
const repository = {
|
|
131
123
|
resolve: vi.fn().mockResolvedValue({
|
|
132
124
|
...base,
|
|
@@ -137,7 +129,7 @@ describe("CodexPrintAgentService", ()=>{
|
|
|
137
129
|
bindProviderSession: vi.fn(),
|
|
138
130
|
completeRun: vi.fn()
|
|
139
131
|
};
|
|
140
|
-
await expect(new
|
|
132
|
+
await expect(new CodexPrintAgentService({
|
|
141
133
|
repository,
|
|
142
134
|
probe: {
|
|
143
135
|
validate: vi.fn()
|
|
@@ -152,8 +144,6 @@ describe("CodexPrintAgentService", ()=>{
|
|
|
152
144
|
expect(repository.completeRun).not.toHaveBeenCalled();
|
|
153
145
|
});
|
|
154
146
|
it("does not turn a successful completion write failure into a second completion", async ()=>{
|
|
155
|
-
const api = await import("../../../../index.js");
|
|
156
|
-
const Service = api.CodexPrintAgentService;
|
|
157
147
|
const completionFailure = new Error("completion failed");
|
|
158
148
|
const repository = {
|
|
159
149
|
resolve: vi.fn().mockResolvedValue(base),
|
|
@@ -175,7 +165,7 @@ describe("CodexPrintAgentService", ()=>{
|
|
|
175
165
|
exitCode: 0
|
|
176
166
|
})
|
|
177
167
|
};
|
|
178
|
-
await expect(new
|
|
168
|
+
await expect(new CodexPrintAgentService({
|
|
179
169
|
repository,
|
|
180
170
|
probe: {
|
|
181
171
|
validate: vi.fn()
|
|
@@ -185,8 +175,6 @@ describe("CodexPrintAgentService", ()=>{
|
|
|
185
175
|
expect(repository.completeRun).toHaveBeenCalledOnce();
|
|
186
176
|
});
|
|
187
177
|
it("records a repository binding conflict as a session mismatch", async ()=>{
|
|
188
|
-
const api = await import("../../../../index.js");
|
|
189
|
-
const BindingError = api.CodexPrintError;
|
|
190
178
|
const completeRun = vi.fn();
|
|
191
179
|
const repository = {
|
|
192
180
|
resolve: vi.fn().mockResolvedValue(base),
|
|
@@ -195,7 +183,7 @@ describe("CodexPrintAgentService", ()=>{
|
|
|
195
183
|
token: "one"
|
|
196
184
|
}),
|
|
197
185
|
recordProviderProcess: vi.fn(),
|
|
198
|
-
bindProviderSession: vi.fn().mockRejectedValue(new
|
|
186
|
+
bindProviderSession: vi.fn().mockRejectedValue(new CodexPrintError("binding mismatch", "CODEX_SESSION_MISMATCH")),
|
|
199
187
|
completeRun
|
|
200
188
|
};
|
|
201
189
|
const runner = {
|
|
@@ -211,8 +199,7 @@ describe("CodexPrintAgentService", ()=>{
|
|
|
211
199
|
};
|
|
212
200
|
})
|
|
213
201
|
};
|
|
214
|
-
|
|
215
|
-
await expect(new Service({
|
|
202
|
+
await expect(new CodexPrintAgentService({
|
|
216
203
|
repository,
|
|
217
204
|
probe: {
|
|
218
205
|
validate: vi.fn()
|
|
@@ -226,8 +213,6 @@ describe("CodexPrintAgentService", ()=>{
|
|
|
226
213
|
}));
|
|
227
214
|
});
|
|
228
215
|
it("rejects missing and ambiguous records before acquiring a run", async ()=>{
|
|
229
|
-
const api = await import("../../../../index.js");
|
|
230
|
-
const Service = api.CodexPrintAgentService;
|
|
231
216
|
const repository = {
|
|
232
217
|
create: vi.fn(),
|
|
233
218
|
resolve: vi.fn().mockResolvedValueOnce(null).mockResolvedValueOnce([
|
|
@@ -239,7 +224,7 @@ describe("CodexPrintAgentService", ()=>{
|
|
|
239
224
|
bindProviderSession: vi.fn(),
|
|
240
225
|
completeRun: vi.fn()
|
|
241
226
|
};
|
|
242
|
-
const service = new
|
|
227
|
+
const service = new CodexPrintAgentService({
|
|
243
228
|
repository,
|
|
244
229
|
probe: {
|
|
245
230
|
validate: vi.fn()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/__tests__/harnesses/codex/durable/CodexPrintAgentService.test.ts"],"sourcesContent":["import { describe, expect, it, vi } from \"vitest\";\n\nconst SESSION = \"22222222-2222-4222-8222-222222222222\";\nconst base = {\n id: \"id\",\n name: \"reviewer\",\n provider: \"codex\",\n providerSessionId: null,\n sessionHealth: \"uninitialized\",\n};\n\ndescribe(\"CodexPrintAgentService\", () => {\n it(\"validates before provider-aware create and never runs Codex\", async () => {\n const api = (await import(\"../../../../index.js\")) as Record<string, unknown>;\n expect(api).toHaveProperty(\"CodexPrintAgentService\");\n const probe = {\n validate: vi.fn().mockResolvedValue({ executable: \"codex\", version: \"0.147.0\" }),\n };\n const repository = { create: vi.fn().mockResolvedValue(base) };\n const runner = { run: vi.fn() };\n const Service = api.CodexPrintAgentService as new (options: unknown) => any;\n await new Service({ repository, probe, runner }).create({ name: \"reviewer\", cwd: \"/project\" });\n expect(repository.create).toHaveBeenCalledWith({\n name: \"reviewer\",\n cwd: \"/project\",\n provider: \"codex\",\n });\n expect(runner.run).not.toHaveBeenCalled();\n });\n\n it(\"binds during first send and explicitly resumes later sends\", async () => {\n const api = (await import(\"../../../../index.js\")) as Record<string, unknown>;\n const repository = {\n resolve: vi.fn().mockResolvedValue(base),\n acquireRun: vi\n .fn()\n .mockResolvedValueOnce({ agent: base, token: \"one\" })\n .mockResolvedValueOnce({\n agent: { ...base, providerSessionId: SESSION, sessionHealth: \"healthy\" },\n token: \"two\",\n }),\n recordProviderProcess: vi.fn(),\n bindProviderSession: vi.fn(),\n completeRun: vi.fn(),\n };\n const runner = {\n run: vi.fn().mockImplementation(async (request) => {\n await request.onSpawn({ pid: 42, startedAt: \"start\" });\n await request.onSession(SESSION);\n return { sessionId: SESSION, result: \"answer\", messages: [\"answer\"], exitCode: 0 };\n }),\n };\n const Service = api.CodexPrintAgentService as new (options: unknown) => any;\n const service = new Service({\n repository,\n probe: { validate: vi.fn() },\n runner,\n executable: \"fake-codex\",\n });\n\n await service.send(\"reviewer\", \"first\");\n await service.send(\"reviewer\", \"later\");\n\n expect(repository.bindProviderSession).toHaveBeenNthCalledWith(1, \"id\", \"one\", SESSION);\n expect(repository.bindProviderSession).toHaveBeenNthCalledWith(2, \"id\", \"two\", SESSION);\n expect(repository.completeRun).toHaveBeenCalledWith(\n \"id\",\n \"one\",\n expect.objectContaining({\n status: \"succeeded\",\n sessionHealth: \"healthy\",\n }),\n );\n });\n\n it(\"records mismatch separately from unknown failures\", async () => {\n const api = (await import(\"../../../../index.js\")) as Record<string, unknown>;\n const ErrorType = api.CodexPrintError as new (message: string, code: string) => Error;\n const completeRun = vi.fn();\n const repository = {\n resolve: vi.fn().mockResolvedValue(base),\n acquireRun: vi.fn().mockResolvedValue({ agent: base, token: \"one\" }),\n recordProviderProcess: vi.fn(),\n bindProviderSession: vi.fn(),\n completeRun,\n };\n const Service = api.CodexPrintAgentService as new (options: unknown) => any;\n const service = new Service({\n repository,\n probe: { validate: vi.fn() },\n runner: {\n run: vi.fn().mockRejectedValue(new ErrorType(\"mismatch\", \"CODEX_SESSION_MISMATCH\")),\n },\n });\n await expect(service.send(\"reviewer\", \"x\")).rejects.toMatchObject({\n code: \"CODEX_SESSION_MISMATCH\",\n });\n expect(completeRun).toHaveBeenCalledWith(\n \"id\",\n \"one\",\n expect.objectContaining({ sessionHealth: \"mismatch\" }),\n );\n });\n\n it(\"rejects a non-Codex target without acquiring or mutating it\", async () => {\n const api = (await import(\"../../../../index.js\")) as Record<string, unknown>;\n const Service = api.CodexPrintAgentService 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 bindProviderSession: 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: \"CODEX_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.CodexPrintAgentService 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 bindProviderSession: 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 it(\"records a repository binding conflict as a session mismatch\", async () => {\n const api = (await import(\"../../../../index.js\")) as Record<string, unknown>;\n const BindingError = api.CodexPrintError as new (message: string, code: string) => Error;\n const completeRun = vi.fn();\n const repository = {\n resolve: vi.fn().mockResolvedValue(base),\n acquireRun: vi.fn().mockResolvedValue({ agent: base, token: \"one\" }),\n recordProviderProcess: vi.fn(),\n bindProviderSession: vi\n .fn()\n .mockRejectedValue(new BindingError(\"binding mismatch\", \"CODEX_SESSION_MISMATCH\")),\n completeRun,\n };\n const runner = {\n run: vi.fn().mockImplementation(async (request) => {\n await request.onSession(SESSION);\n return { sessionId: SESSION, result: \"x\", messages: [\"x\"], exitCode: 0 };\n }),\n };\n const Service = api.CodexPrintAgentService as new (options: unknown) => any;\n\n await expect(\n new Service({ repository, probe: { validate: vi.fn() }, runner }).send(\"reviewer\", \"x\"),\n ).rejects.toMatchObject({ code: \"CODEX_SESSION_MISMATCH\" });\n expect(completeRun).toHaveBeenCalledWith(\n \"id\",\n \"one\",\n expect.objectContaining({ sessionHealth: \"mismatch\" }),\n );\n });\n\n it(\"rejects missing and ambiguous records before acquiring a run\", async () => {\n const api = (await import(\"../../../../index.js\")) as Record<string, unknown>;\n const Service = api.CodexPrintAgentService as new (options: unknown) => any;\n const repository = {\n create: vi.fn(),\n resolve: vi.fn().mockResolvedValueOnce(null).mockResolvedValueOnce([base, base]),\n acquireRun: vi.fn(),\n recordProviderProcess: vi.fn(),\n bindProviderSession: vi.fn(),\n completeRun: vi.fn(),\n };\n const service = new Service({\n repository,\n probe: { validate: vi.fn() },\n runner: { run: vi.fn() },\n });\n await expect(service.send(\"missing\", \"x\")).rejects.toMatchObject({\n code: \"DURABLE_AGENT_NOT_FOUND\",\n });\n await expect(service.send(\"ambiguous\", \"x\")).rejects.toMatchObject({\n code: \"CODEX_UNSUPPORTED\",\n });\n expect(repository.acquireRun).not.toHaveBeenCalled();\n });\n});\n"],"names":["describe","expect","it","vi","SESSION","base","id","name","provider","providerSessionId","sessionHealth","api","toHaveProperty","probe","validate","fn","mockResolvedValue","executable","version","repository","create","runner","run","Service","CodexPrintAgentService","cwd","toHaveBeenCalledWith","not","toHaveBeenCalled","resolve","acquireRun","mockResolvedValueOnce","agent","token","recordProviderProcess","bindProviderSession","completeRun","mockImplementation","request","onSpawn","pid","startedAt","onSession","sessionId","result","messages","exitCode","service","send","toHaveBeenNthCalledWith","objectContaining","status","ErrorType","CodexPrintError","mockRejectedValue","rejects","toMatchObject","code","completionFailure","Error","toBe","toHaveBeenCalledOnce","BindingError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/__tests__/harnesses/codex/durable/CodexPrintAgentService.test.ts"],"sourcesContent":["import { describe, expect, it, vi } from \"vitest\";\nimport { CodexPrintError } from \"../../../../durable/DurableAgent.js\";\nimport { CodexPrintAgentService } from \"../../../../harnesses/codex/durable/CodexPrintAgentService.js\";\n\nconst SESSION = \"22222222-2222-4222-8222-222222222222\";\nconst base = {\n id: \"id\",\n name: \"reviewer\",\n provider: \"codex\",\n providerSessionId: null,\n sessionHealth: \"uninitialized\",\n};\n\ndescribe(\"CodexPrintAgentService\", () => {\n it(\"validates before provider-aware create and never runs Codex\", async () => {\n const probe = {\n validate: vi.fn().mockResolvedValue({ executable: \"codex\", version: \"0.147.0\" }),\n };\n const repository = { create: vi.fn().mockResolvedValue(base) };\n const runner = { run: vi.fn() };\n await new CodexPrintAgentService({ repository, probe, runner }).create({\n name: \"reviewer\",\n cwd: \"/project\",\n });\n expect(repository.create).toHaveBeenCalledWith({\n name: \"reviewer\",\n cwd: \"/project\",\n provider: \"codex\",\n });\n expect(runner.run).not.toHaveBeenCalled();\n });\n\n it(\"binds during first send and explicitly resumes later sends\", async () => {\n const repository = {\n resolve: vi.fn().mockResolvedValue(base),\n acquireRun: vi\n .fn()\n .mockResolvedValueOnce({ agent: base, token: \"one\" })\n .mockResolvedValueOnce({\n agent: { ...base, providerSessionId: SESSION, sessionHealth: \"healthy\" },\n token: \"two\",\n }),\n recordProviderProcess: vi.fn(),\n bindProviderSession: vi.fn(),\n completeRun: vi.fn(),\n };\n const runner = {\n run: vi.fn().mockImplementation(async (request) => {\n await request.onSpawn({ pid: 42, startedAt: \"start\" });\n await request.onSession(SESSION);\n return { sessionId: SESSION, result: \"answer\", messages: [\"answer\"], exitCode: 0 };\n }),\n };\n const service = new CodexPrintAgentService({\n repository,\n probe: { validate: vi.fn() },\n runner,\n executable: \"fake-codex\",\n });\n\n await service.send(\"reviewer\", \"first\");\n await service.send(\"reviewer\", \"later\");\n\n expect(repository.bindProviderSession).toHaveBeenNthCalledWith(1, \"id\", \"one\", SESSION);\n expect(repository.bindProviderSession).toHaveBeenNthCalledWith(2, \"id\", \"two\", SESSION);\n expect(repository.completeRun).toHaveBeenCalledWith(\n \"id\",\n \"one\",\n expect.objectContaining({\n status: \"succeeded\",\n sessionHealth: \"healthy\",\n }),\n );\n });\n\n it(\"records mismatch separately from unknown failures\", async () => {\n const completeRun = vi.fn();\n const repository = {\n resolve: vi.fn().mockResolvedValue(base),\n acquireRun: vi.fn().mockResolvedValue({ agent: base, token: \"one\" }),\n recordProviderProcess: vi.fn(),\n bindProviderSession: vi.fn(),\n completeRun,\n };\n const service = new CodexPrintAgentService({\n repository,\n probe: { validate: vi.fn() },\n runner: {\n run: vi.fn().mockRejectedValue(new CodexPrintError(\"mismatch\", \"CODEX_SESSION_MISMATCH\")),\n },\n });\n await expect(service.send(\"reviewer\", \"x\")).rejects.toMatchObject({\n code: \"CODEX_SESSION_MISMATCH\",\n });\n expect(completeRun).toHaveBeenCalledWith(\n \"id\",\n \"one\",\n expect.objectContaining({ sessionHealth: \"mismatch\" }),\n );\n });\n\n it(\"rejects a non-Codex 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 bindProviderSession: vi.fn(),\n completeRun: vi.fn(),\n };\n\n await expect(\n new CodexPrintAgentService({\n repository,\n probe: { validate: vi.fn() },\n runner: { run: vi.fn() },\n }).send(\"reviewer\", \"x\"),\n ).rejects.toMatchObject({ code: \"CODEX_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 bindProviderSession: 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 CodexPrintAgentService({ repository, probe: { validate: vi.fn() }, runner }).send(\n \"reviewer\",\n \"x\",\n ),\n ).rejects.toBe(completionFailure);\n expect(repository.completeRun).toHaveBeenCalledOnce();\n });\n\n it(\"records a repository binding conflict as a session mismatch\", async () => {\n const completeRun = vi.fn();\n const repository = {\n resolve: vi.fn().mockResolvedValue(base),\n acquireRun: vi.fn().mockResolvedValue({ agent: base, token: \"one\" }),\n recordProviderProcess: vi.fn(),\n bindProviderSession: vi\n .fn()\n .mockRejectedValue(new CodexPrintError(\"binding mismatch\", \"CODEX_SESSION_MISMATCH\")),\n completeRun,\n };\n const runner = {\n run: vi.fn().mockImplementation(async (request) => {\n await request.onSession(SESSION);\n return { sessionId: SESSION, result: \"x\", messages: [\"x\"], exitCode: 0 };\n }),\n };\n await expect(\n new CodexPrintAgentService({ repository, probe: { validate: vi.fn() }, runner }).send(\n \"reviewer\",\n \"x\",\n ),\n ).rejects.toMatchObject({ code: \"CODEX_SESSION_MISMATCH\" });\n expect(completeRun).toHaveBeenCalledWith(\n \"id\",\n \"one\",\n expect.objectContaining({ sessionHealth: \"mismatch\" }),\n );\n });\n\n it(\"rejects missing and ambiguous records before acquiring a run\", async () => {\n const repository = {\n create: vi.fn(),\n resolve: vi.fn().mockResolvedValueOnce(null).mockResolvedValueOnce([base, base]),\n acquireRun: vi.fn(),\n recordProviderProcess: vi.fn(),\n bindProviderSession: vi.fn(),\n completeRun: vi.fn(),\n };\n const service = new CodexPrintAgentService({\n repository,\n probe: { validate: vi.fn() },\n runner: { run: vi.fn() },\n });\n await expect(service.send(\"missing\", \"x\")).rejects.toMatchObject({\n code: \"DURABLE_AGENT_NOT_FOUND\",\n });\n await expect(service.send(\"ambiguous\", \"x\")).rejects.toMatchObject({\n code: \"CODEX_UNSUPPORTED\",\n });\n expect(repository.acquireRun).not.toHaveBeenCalled();\n });\n});\n"],"names":["describe","expect","it","vi","CodexPrintError","CodexPrintAgentService","SESSION","base","id","name","provider","providerSessionId","sessionHealth","probe","validate","fn","mockResolvedValue","executable","version","repository","create","runner","run","cwd","toHaveBeenCalledWith","not","toHaveBeenCalled","resolve","acquireRun","mockResolvedValueOnce","agent","token","recordProviderProcess","bindProviderSession","completeRun","mockImplementation","request","onSpawn","pid","startedAt","onSession","sessionId","result","messages","exitCode","service","send","toHaveBeenNthCalledWith","objectContaining","status","mockRejectedValue","rejects","toMatchObject","code","completionFailure","Error","toBe","toHaveBeenCalledOnce"],"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 { CodexPrintRunner } from "../../../../harnesses/codex/durable/CodexPrintRunner.js";
|
|
4
5
|
const SESSION = "22222222-2222-4222-8222-222222222222";
|
|
5
6
|
function agent(providerSessionId = null) {
|
|
6
7
|
return {
|
|
@@ -84,10 +85,7 @@ function events(session = SESSION) {
|
|
|
84
85
|
];
|
|
85
86
|
}
|
|
86
87
|
async function runner(fixture, maxLineBytes) {
|
|
87
|
-
|
|
88
|
-
expect(api).toHaveProperty("CodexPrintRunner");
|
|
89
|
-
const Runner = api.CodexPrintRunner;
|
|
90
|
-
return new Runner({
|
|
88
|
+
return new CodexPrintRunner({
|
|
91
89
|
spawn: fixture.spawn,
|
|
92
90
|
maxLineBytes,
|
|
93
91
|
processInspector: {
|
|
@@ -344,10 +342,8 @@ describe("CodexPrintRunner", ()=>{
|
|
|
344
342
|
expect(spawnFailure.child.kill).toHaveBeenCalledOnce();
|
|
345
343
|
});
|
|
346
344
|
it("rejects an unverifiable positive PID", async ()=>{
|
|
347
|
-
const api = await import("../../../../index.js");
|
|
348
345
|
const fixture = fakeSpawn([]);
|
|
349
|
-
const
|
|
350
|
-
const instance = new Runner({
|
|
346
|
+
const instance = new CodexPrintRunner({
|
|
351
347
|
spawn: fixture.spawn,
|
|
352
348
|
processInspector: {
|
|
353
349
|
getIdentity: ()=>null
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/__tests__/harnesses/codex/durable/CodexPrintRunner.test.ts"],"sourcesContent":["import { EventEmitter } from \"node:events\";\nimport { PassThrough, Writable } from \"node:stream\";\nimport { describe, expect, it, vi } from \"vitest\";\nimport type { CodexDurableAgent } from \"../../../../index.js\";\n\nconst SESSION = \"22222222-2222-4222-8222-222222222222\";\n\nfunction agent(providerSessionId: string | null = null): CodexDurableAgent {\n return {\n id: \"11111111-1111-4111-8111-111111111111\",\n name: \"reviewer\",\n provider: \"codex\",\n mode: \"durable\",\n cwd: \"/project\",\n providerSessionId,\n state: \"running\",\n sessionHealth: \"uninitialized\",\n createdAt: \"\",\n updatedAt: \"\",\n lastActiveAt: null,\n lastResult: null,\n activeRun: null,\n };\n}\n\nfunction fakeSpawn(lines: string[], exitCode = 0, chunks = false) {\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 const output = lines.join(\"\\n\");\n if (chunks) {\n const bytes = Buffer.from(output);\n child.stdout.write(bytes.subarray(0, 7));\n child.stdout.write(bytes.subarray(7));\n } else child.stdout.write(output);\n child.stdout.end();\n queueMicrotask(() => child.emit(\"close\", exitCode, null));\n callback();\n },\n });\n const spawn = vi.fn(() => child);\n return { child, spawn, promptChunks };\n}\n\nfunction events(session = SESSION): string[] {\n return [\n JSON.stringify({ type: \"thread.started\", thread_id: session }),\n JSON.stringify({ type: \"turn.started\" }),\n JSON.stringify({ type: \"future.event\", anything: true }),\n JSON.stringify({ type: \"item.completed\", item: { type: \"agent_message\", text: \"first\" } }),\n JSON.stringify({ type: \"item.completed\", item: { type: \"agent_message\", text: \"final\" } }),\n JSON.stringify({ type: \"turn.completed\" }),\n \"\",\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(\"CodexPrintRunner\");\n const Runner = api.CodexPrintRunner as new (options: unknown) => any;\n return new Runner({\n spawn: fixture.spawn,\n maxLineBytes,\n processInspector: {\n getIdentity: () => ({ pid: 4242, startedAt: \"provider-start\" }),\n },\n });\n}\n\ndescribe(\"CodexPrintRunner\", () => {\n it(\"binds an initial thread before returning ordered assistant output\", async () => {\n const fixture = fakeSpawn(events(), 0, true);\n const instance = await runner(fixture);\n const order: string[] = [];\n const result = await instance.run({\n agent: agent(),\n prompt: \"secret prompt\",\n executable: \"fake-codex\",\n onSpawn: async () => {\n expect(fixture.promptChunks).toHaveLength(0);\n order.push(\"spawn\");\n },\n onSession: async (id: string) => {\n expect(id).toBe(SESSION);\n order.push(\"session\");\n },\n });\n\n expect(order).toEqual([\"spawn\", \"session\"]);\n expect(fixture.spawn).toHaveBeenCalledWith(\n \"fake-codex\",\n [\"exec\", \"--json\", \"-\"],\n expect.objectContaining({\n cwd: \"/project\",\n shell: false,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n }),\n );\n expect(JSON.stringify(fixture.spawn.mock.calls)).not.toContain(\"secret prompt\");\n expect(Buffer.concat(fixture.promptChunks).toString()).toBe(\"secret prompt\");\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 UUID and rejects a mismatch\", async () => {\n const mismatch = \"33333333-3333-4333-8333-333333333333\";\n const fixture = fakeSpawn(events(mismatch));\n const instance = await runner(fixture);\n await expect(\n instance.run({\n agent: agent(SESSION),\n prompt: \"later\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"CODEX_SESSION_MISMATCH\" });\n expect(fixture.spawn.mock.calls[0]![1]).toEqual([\"exec\", \"resume\", \"--json\", SESSION, \"-\"]);\n });\n\n it.each([\n [\"malformed JSON\", [\"{bad\\n\"], \"CODEX_PROTOCOL\"],\n [\"non-object JSON\", [\"[]\\n\"], \"CODEX_PROTOCOL\"],\n [\"truncated JSON\", [\"{}\"], \"CODEX_PROTOCOL\"],\n [\n \"missing thread\",\n [\n JSON.stringify({ type: \"item.completed\", item: { type: \"agent_message\", text: \"x\" } }),\n JSON.stringify({ type: \"turn.completed\" }),\n \"\",\n ],\n \"CODEX_PROTOCOL\",\n ],\n [\n \"missing assistant\",\n [\n JSON.stringify({ type: \"thread.started\", thread_id: SESSION }),\n JSON.stringify({ type: \"turn.completed\" }),\n \"\",\n ],\n \"CODEX_RESULT_MISSING\",\n ],\n [\n \"missing completion\",\n [\n JSON.stringify({ type: \"thread.started\", thread_id: SESSION }),\n JSON.stringify({ type: \"item.completed\", item: { type: \"agent_message\", text: \"x\" } }),\n \"\",\n ],\n \"CODEX_PROTOCOL\",\n ],\n ])(\"rejects %s\", async (_name, lines, code) => {\n const fixture = fakeSpawn(lines as string[]);\n await expect(\n (await runner(fixture)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code });\n });\n\n it(\"rejects oversized output, non-zero exit, and missing process identity without leaking stderr\", async () => {\n const oversized = fakeSpawn([`${\"x\".repeat(20)}\\n`]);\n await expect(\n (await runner(oversized, 10)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"CODEX_PROTOCOL\" });\n const oversizedWithoutNewline = fakeSpawn([\"x\".repeat(20)]);\n await expect(\n (await runner(oversizedWithoutNewline, 10)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"CODEX_PROTOCOL\" });\n\n const failed = fakeSpawn(events(), 1);\n failed.child.stderr.end(\"secret-looking provider diagnostic\");\n await expect(\n (await runner(failed)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"CODEX_PROCESS\" });\n\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: \"CODEX_PROCESS\" });\n });\n\n it(\"rejects invalid or duplicate thread identities\", async () => {\n for (const lines of [\n [JSON.stringify({ type: \"thread.started\", thread_id: \"bad\" }), \"\"],\n [\n JSON.stringify({ type: \"thread.started\", thread_id: SESSION }),\n JSON.stringify({ type: \"thread.started\", thread_id: SESSION }),\n \"\",\n ],\n ]) {\n const fixture = fakeSpawn(lines);\n await expect(\n (await runner(fixture)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"CODEX_PROTOCOL\" });\n }\n });\n\n it(\"classifies callback processing failure and kills when spawn persistence fails\", async () => {\n const callbackFailure = fakeSpawn(events());\n await expect(\n (await runner(callbackFailure)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn().mockRejectedValue(new Error(\"storage unavailable\")),\n }),\n ).rejects.toMatchObject({ code: \"CODEX_PROTOCOL\" });\n\n const spawnFailure = fakeSpawn([]);\n const failure = new Error(\"cannot persist process\");\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(\"rejects an unverifiable positive PID\", async () => {\n const api = (await import(\"../../../../index.js\")) as Record<string, unknown>;\n const fixture = fakeSpawn([]);\n const Runner = api.CodexPrintRunner as new (options: unknown) => any;\n const instance = new Runner({\n spawn: fixture.spawn,\n processInspector: { getIdentity: () => null },\n });\n await expect(\n instance.run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"CODEX_PROCESS\" });\n expect(fixture.child.kill).toHaveBeenCalledOnce();\n });\n\n it(\"classifies a child spawn error as a process failure\", async () => {\n const fixture = fakeSpawn([]);\n fixture.child.stdin = new Writable({\n write(_chunk, _encoding, callback) {\n callback();\n },\n final(callback) {\n queueMicrotask(() => fixture.child.emit(\"error\", new Error(\"spawn failed\")));\n callback();\n },\n });\n await expect(\n (await runner(fixture)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"CODEX_PROCESS\" });\n });\n});\n"],"names":["EventEmitter","PassThrough","Writable","describe","expect","it","vi","SESSION","agent","providerSessionId","id","name","provider","mode","cwd","state","sessionHealth","createdAt","updatedAt","lastActiveAt","lastResult","activeRun","fakeSpawn","lines","exitCode","chunks","promptChunks","child","pid","stdout","stderr","kill","fn","stdin","write","chunk","_encoding","callback","push","Buffer","from","final","output","join","bytes","subarray","end","queueMicrotask","emit","spawn","events","session","JSON","stringify","type","thread_id","anything","item","text","runner","fixture","maxLineBytes","api","toHaveProperty","Runner","CodexPrintRunner","processInspector","getIdentity","startedAt","instance","order","result","run","prompt","executable","onSpawn","toHaveLength","onSession","toBe","toEqual","toHaveBeenCalledWith","objectContaining","shell","stdio","mock","calls","not","toContain","concat","toString","sessionId","messages","mismatch","rejects","toMatchObject","code","each","_name","oversized","repeat","oversizedWithoutNewline","failed","missing","undefined","callbackFailure","mockRejectedValue","Error","spawnFailure","failure","toHaveBeenCalledOnce","_chunk"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/__tests__/harnesses/codex/durable/CodexPrintRunner.test.ts"],"sourcesContent":["import { EventEmitter } from \"node:events\";\nimport { PassThrough, Writable } from \"node:stream\";\nimport { describe, expect, it, vi } from \"vitest\";\nimport type { CodexDurableAgent } from \"../../../../durable/DurableAgent.js\";\nimport { CodexPrintRunner } from \"../../../../harnesses/codex/durable/CodexPrintRunner.js\";\n\nconst SESSION = \"22222222-2222-4222-8222-222222222222\";\n\nfunction agent(providerSessionId: string | null = null): CodexDurableAgent {\n return {\n id: \"11111111-1111-4111-8111-111111111111\",\n name: \"reviewer\",\n provider: \"codex\",\n mode: \"durable\",\n cwd: \"/project\",\n providerSessionId,\n state: \"running\",\n sessionHealth: \"uninitialized\",\n createdAt: \"\",\n updatedAt: \"\",\n lastActiveAt: null,\n lastResult: null,\n activeRun: null,\n };\n}\n\nfunction fakeSpawn(lines: string[], exitCode = 0, chunks = false) {\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 const output = lines.join(\"\\n\");\n if (chunks) {\n const bytes = Buffer.from(output);\n child.stdout.write(bytes.subarray(0, 7));\n child.stdout.write(bytes.subarray(7));\n } else child.stdout.write(output);\n child.stdout.end();\n queueMicrotask(() => child.emit(\"close\", exitCode, null));\n callback();\n },\n });\n const spawn = vi.fn(() => child);\n return { child, spawn, promptChunks };\n}\n\nfunction events(session = SESSION): string[] {\n return [\n JSON.stringify({ type: \"thread.started\", thread_id: session }),\n JSON.stringify({ type: \"turn.started\" }),\n JSON.stringify({ type: \"future.event\", anything: true }),\n JSON.stringify({ type: \"item.completed\", item: { type: \"agent_message\", text: \"first\" } }),\n JSON.stringify({ type: \"item.completed\", item: { type: \"agent_message\", text: \"final\" } }),\n JSON.stringify({ type: \"turn.completed\" }),\n \"\",\n ];\n}\n\nasync function runner(fixture: ReturnType<typeof fakeSpawn>, maxLineBytes?: number) {\n return new CodexPrintRunner({\n spawn: fixture.spawn,\n maxLineBytes,\n processInspector: {\n getIdentity: () => ({ pid: 4242, startedAt: \"provider-start\" }),\n },\n });\n}\n\ndescribe(\"CodexPrintRunner\", () => {\n it(\"binds an initial thread before returning ordered assistant output\", async () => {\n const fixture = fakeSpawn(events(), 0, true);\n const instance = await runner(fixture);\n const order: string[] = [];\n const result = await instance.run({\n agent: agent(),\n prompt: \"secret prompt\",\n executable: \"fake-codex\",\n onSpawn: async () => {\n expect(fixture.promptChunks).toHaveLength(0);\n order.push(\"spawn\");\n },\n onSession: async (id: string) => {\n expect(id).toBe(SESSION);\n order.push(\"session\");\n },\n });\n\n expect(order).toEqual([\"spawn\", \"session\"]);\n expect(fixture.spawn).toHaveBeenCalledWith(\n \"fake-codex\",\n [\"exec\", \"--json\", \"-\"],\n expect.objectContaining({\n cwd: \"/project\",\n shell: false,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n }),\n );\n expect(JSON.stringify(fixture.spawn.mock.calls)).not.toContain(\"secret prompt\");\n expect(Buffer.concat(fixture.promptChunks).toString()).toBe(\"secret prompt\");\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 UUID and rejects a mismatch\", async () => {\n const mismatch = \"33333333-3333-4333-8333-333333333333\";\n const fixture = fakeSpawn(events(mismatch));\n const instance = await runner(fixture);\n await expect(\n instance.run({\n agent: agent(SESSION),\n prompt: \"later\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"CODEX_SESSION_MISMATCH\" });\n expect(fixture.spawn.mock.calls[0]![1]).toEqual([\"exec\", \"resume\", \"--json\", SESSION, \"-\"]);\n });\n\n it.each([\n [\"malformed JSON\", [\"{bad\\n\"], \"CODEX_PROTOCOL\"],\n [\"non-object JSON\", [\"[]\\n\"], \"CODEX_PROTOCOL\"],\n [\"truncated JSON\", [\"{}\"], \"CODEX_PROTOCOL\"],\n [\n \"missing thread\",\n [\n JSON.stringify({ type: \"item.completed\", item: { type: \"agent_message\", text: \"x\" } }),\n JSON.stringify({ type: \"turn.completed\" }),\n \"\",\n ],\n \"CODEX_PROTOCOL\",\n ],\n [\n \"missing assistant\",\n [\n JSON.stringify({ type: \"thread.started\", thread_id: SESSION }),\n JSON.stringify({ type: \"turn.completed\" }),\n \"\",\n ],\n \"CODEX_RESULT_MISSING\",\n ],\n [\n \"missing completion\",\n [\n JSON.stringify({ type: \"thread.started\", thread_id: SESSION }),\n JSON.stringify({ type: \"item.completed\", item: { type: \"agent_message\", text: \"x\" } }),\n \"\",\n ],\n \"CODEX_PROTOCOL\",\n ],\n ])(\"rejects %s\", async (_name, lines, code) => {\n const fixture = fakeSpawn(lines as string[]);\n await expect(\n (await runner(fixture)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code });\n });\n\n it(\"rejects oversized output, non-zero exit, and missing process identity without leaking stderr\", async () => {\n const oversized = fakeSpawn([`${\"x\".repeat(20)}\\n`]);\n await expect(\n (await runner(oversized, 10)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"CODEX_PROTOCOL\" });\n const oversizedWithoutNewline = fakeSpawn([\"x\".repeat(20)]);\n await expect(\n (await runner(oversizedWithoutNewline, 10)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"CODEX_PROTOCOL\" });\n\n const failed = fakeSpawn(events(), 1);\n failed.child.stderr.end(\"secret-looking provider diagnostic\");\n await expect(\n (await runner(failed)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"CODEX_PROCESS\" });\n\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: \"CODEX_PROCESS\" });\n });\n\n it(\"rejects invalid or duplicate thread identities\", async () => {\n for (const lines of [\n [JSON.stringify({ type: \"thread.started\", thread_id: \"bad\" }), \"\"],\n [\n JSON.stringify({ type: \"thread.started\", thread_id: SESSION }),\n JSON.stringify({ type: \"thread.started\", thread_id: SESSION }),\n \"\",\n ],\n ]) {\n const fixture = fakeSpawn(lines);\n await expect(\n (await runner(fixture)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"CODEX_PROTOCOL\" });\n }\n });\n\n it(\"classifies callback processing failure and kills when spawn persistence fails\", async () => {\n const callbackFailure = fakeSpawn(events());\n await expect(\n (await runner(callbackFailure)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn().mockRejectedValue(new Error(\"storage unavailable\")),\n }),\n ).rejects.toMatchObject({ code: \"CODEX_PROTOCOL\" });\n\n const spawnFailure = fakeSpawn([]);\n const failure = new Error(\"cannot persist process\");\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(\"rejects an unverifiable positive PID\", async () => {\n const fixture = fakeSpawn([]);\n const instance = new CodexPrintRunner({\n spawn: fixture.spawn,\n processInspector: { getIdentity: () => null },\n });\n await expect(\n instance.run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"CODEX_PROCESS\" });\n expect(fixture.child.kill).toHaveBeenCalledOnce();\n });\n\n it(\"classifies a child spawn error as a process failure\", async () => {\n const fixture = fakeSpawn([]);\n fixture.child.stdin = new Writable({\n write(_chunk, _encoding, callback) {\n callback();\n },\n final(callback) {\n queueMicrotask(() => fixture.child.emit(\"error\", new Error(\"spawn failed\")));\n callback();\n },\n });\n await expect(\n (await runner(fixture)).run({\n agent: agent(),\n prompt: \"x\",\n onSpawn: vi.fn(),\n onSession: vi.fn(),\n }),\n ).rejects.toMatchObject({ code: \"CODEX_PROCESS\" });\n });\n});\n"],"names":["EventEmitter","PassThrough","Writable","describe","expect","it","vi","CodexPrintRunner","SESSION","agent","providerSessionId","id","name","provider","mode","cwd","state","sessionHealth","createdAt","updatedAt","lastActiveAt","lastResult","activeRun","fakeSpawn","lines","exitCode","chunks","promptChunks","child","pid","stdout","stderr","kill","fn","stdin","write","chunk","_encoding","callback","push","Buffer","from","final","output","join","bytes","subarray","end","queueMicrotask","emit","spawn","events","session","JSON","stringify","type","thread_id","anything","item","text","runner","fixture","maxLineBytes","processInspector","getIdentity","startedAt","instance","order","result","run","prompt","executable","onSpawn","toHaveLength","onSession","toBe","toEqual","toHaveBeenCalledWith","objectContaining","shell","stdio","mock","calls","not","toContain","concat","toString","sessionId","messages","mismatch","rejects","toMatchObject","code","each","_name","oversized","repeat","oversizedWithoutNewline","failed","missing","undefined","callbackFailure","mockRejectedValue","Error","spawnFailure","failure","toHaveBeenCalledOnce","_chunk"],"mappings":"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"}
|