@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,7 +1,8 @@
|
|
|
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 type { CodexDurableAgent } from "../../../../
|
|
4
|
+
import type { CodexDurableAgent } from "../../../../durable/DurableAgent.js";
|
|
5
|
+
import { CodexPrintRunner } from "../../../../harnesses/codex/durable/CodexPrintRunner.js";
|
|
5
6
|
|
|
6
7
|
const SESSION = "22222222-2222-4222-8222-222222222222";
|
|
7
8
|
|
|
@@ -64,10 +65,7 @@ function events(session = SESSION): string[] {
|
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
async function runner(fixture: ReturnType<typeof fakeSpawn>, maxLineBytes?: number) {
|
|
67
|
-
|
|
68
|
-
expect(api).toHaveProperty("CodexPrintRunner");
|
|
69
|
-
const Runner = api.CodexPrintRunner as new (options: unknown) => any;
|
|
70
|
-
return new Runner({
|
|
68
|
+
return new CodexPrintRunner({
|
|
71
69
|
spawn: fixture.spawn,
|
|
72
70
|
maxLineBytes,
|
|
73
71
|
processInspector: {
|
|
@@ -262,10 +260,8 @@ describe("CodexPrintRunner", () => {
|
|
|
262
260
|
});
|
|
263
261
|
|
|
264
262
|
it("rejects an unverifiable positive PID", async () => {
|
|
265
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
266
263
|
const fixture = fakeSpawn([]);
|
|
267
|
-
const
|
|
268
|
-
const instance = new Runner({
|
|
264
|
+
const instance = new CodexPrintRunner({
|
|
269
265
|
spawn: fixture.spawn,
|
|
270
266
|
processInspector: { getIdentity: () => null },
|
|
271
267
|
});
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { PiCliProbe } from "../../../../harnesses/pi/durable/PiCliProbe.js";
|
|
2
3
|
|
|
3
4
|
describe("PiCliProbe", () => {
|
|
4
5
|
it("validates documented JSON mode and session capabilities", async () => {
|
|
5
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
6
|
-
expect(api).toHaveProperty("PiCliProbe");
|
|
7
6
|
const exec = vi
|
|
8
7
|
.fn()
|
|
9
8
|
.mockResolvedValueOnce({ stdout: "pi 0.52.8", stderr: "" })
|
|
@@ -11,8 +10,7 @@ describe("PiCliProbe", () => {
|
|
|
11
10
|
stdout: "--mode json\n--session-id <uuid>\n--session <path|id>",
|
|
12
11
|
stderr: "",
|
|
13
12
|
});
|
|
14
|
-
|
|
15
|
-
await expect(new Probe({ executable: "fake-pi", exec }).validate()).resolves.toEqual({
|
|
13
|
+
await expect(new PiCliProbe({ executable: "fake-pi", exec }).validate()).resolves.toEqual({
|
|
16
14
|
executable: "fake-pi",
|
|
17
15
|
version: "pi 0.52.8",
|
|
18
16
|
});
|
|
@@ -23,17 +21,15 @@ describe("PiCliProbe", () => {
|
|
|
23
21
|
});
|
|
24
22
|
|
|
25
23
|
it("rejects unsupported and unavailable CLIs with sanitized errors", async () => {
|
|
26
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
27
|
-
const Probe = api.PiCliProbe as new (options: unknown) => any;
|
|
28
24
|
await expect(
|
|
29
|
-
new
|
|
25
|
+
new PiCliProbe({
|
|
30
26
|
exec: vi
|
|
31
27
|
.fn()
|
|
32
28
|
.mockResolvedValueOnce({ stdout: "", stderr: "" })
|
|
33
29
|
.mockResolvedValueOnce({ stdout: "--print only", stderr: "" }),
|
|
34
30
|
}).validate(),
|
|
35
31
|
).rejects.toMatchObject({ code: "PI_CLI_UNSUPPORTED" });
|
|
36
|
-
const unavailable = new
|
|
32
|
+
const unavailable = new PiCliProbe({
|
|
37
33
|
exec: vi.fn().mockRejectedValue(new Error(`bad\0${"x".repeat(1000)}`)),
|
|
38
34
|
});
|
|
39
35
|
const error = await unavailable.validate().catch((value: Error & { code: string }) => value);
|
|
@@ -43,12 +39,12 @@ describe("PiCliProbe", () => {
|
|
|
43
39
|
});
|
|
44
40
|
|
|
45
41
|
it("reports an empty version as unknown", async () => {
|
|
46
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
47
|
-
const Probe = api.PiCliProbe as new (options: unknown) => any;
|
|
48
42
|
const exec = vi
|
|
49
43
|
.fn()
|
|
50
44
|
.mockResolvedValueOnce({ stdout: " \n", stderr: "" })
|
|
51
45
|
.mockResolvedValueOnce({ stdout: "--mode json --session-id --session", stderr: "" });
|
|
52
|
-
await expect(new
|
|
46
|
+
await expect(new PiCliProbe({ exec }).validate()).resolves.toMatchObject({
|
|
47
|
+
version: "unknown",
|
|
48
|
+
});
|
|
53
49
|
});
|
|
54
50
|
});
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { PiPrintError } from "../../../../durable/DurableAgent.js";
|
|
3
|
+
import { PiPrintAgentService } from "../../../../harnesses/pi/durable/PiPrintAgentService.js";
|
|
2
4
|
const SESSION = "22222222-2222-4222-8222-222222222222";
|
|
3
5
|
const base = {
|
|
4
6
|
id: "id",
|
|
@@ -10,13 +12,13 @@ const base = {
|
|
|
10
12
|
|
|
11
13
|
describe("PiPrintAgentService", () => {
|
|
12
14
|
it("probes before provider-aware create", async () => {
|
|
13
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
14
|
-
expect(api).toHaveProperty("PiPrintAgentService");
|
|
15
15
|
const probe = { validate: vi.fn() };
|
|
16
16
|
const repository = { create: vi.fn().mockResolvedValue(base), list: vi.fn() };
|
|
17
17
|
const runner = { run: vi.fn() };
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
await new PiPrintAgentService({ repository, probe, runner }).create({
|
|
19
|
+
name: "reviewer",
|
|
20
|
+
cwd: "/project",
|
|
21
|
+
});
|
|
20
22
|
expect(probe.validate).toHaveBeenCalledOnce();
|
|
21
23
|
expect(repository.create).toHaveBeenCalledWith({
|
|
22
24
|
name: "reviewer",
|
|
@@ -26,7 +28,6 @@ describe("PiPrintAgentService", () => {
|
|
|
26
28
|
});
|
|
27
29
|
|
|
28
30
|
it("records successful first and resumed sends", async () => {
|
|
29
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
30
31
|
const repository = {
|
|
31
32
|
list: vi.fn(),
|
|
32
33
|
resolve: vi.fn().mockResolvedValue(base),
|
|
@@ -43,8 +44,7 @@ describe("PiPrintAgentService", () => {
|
|
|
43
44
|
return { sessionId: SESSION, result: "answer", messages: ["answer"], exitCode: 0 };
|
|
44
45
|
}),
|
|
45
46
|
};
|
|
46
|
-
const
|
|
47
|
-
const service = new Service({ repository, probe: { validate: vi.fn() }, runner });
|
|
47
|
+
const service = new PiPrintAgentService({ repository, probe: { validate: vi.fn() }, runner });
|
|
48
48
|
await service.send("reviewer", "first");
|
|
49
49
|
await service.send("reviewer", "later");
|
|
50
50
|
expect(repository.completeRun).toHaveBeenCalledWith(
|
|
@@ -55,8 +55,6 @@ describe("PiPrintAgentService", () => {
|
|
|
55
55
|
});
|
|
56
56
|
|
|
57
57
|
it("records mismatches and rejects missing and ambiguous records", async () => {
|
|
58
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
59
|
-
const ErrorType = api.PiPrintError as new (message: string, code: string) => Error;
|
|
60
58
|
const completeRun = vi.fn();
|
|
61
59
|
const repository = {
|
|
62
60
|
list: vi.fn(),
|
|
@@ -65,12 +63,11 @@ describe("PiPrintAgentService", () => {
|
|
|
65
63
|
recordProviderProcess: vi.fn(),
|
|
66
64
|
completeRun,
|
|
67
65
|
};
|
|
68
|
-
const Service = api.PiPrintAgentService as new (options: unknown) => any;
|
|
69
66
|
await expect(
|
|
70
|
-
new
|
|
67
|
+
new PiPrintAgentService({
|
|
71
68
|
repository,
|
|
72
69
|
probe: { validate: vi.fn() },
|
|
73
|
-
runner: { run: vi.fn().mockRejectedValue(new
|
|
70
|
+
runner: { run: vi.fn().mockRejectedValue(new PiPrintError("bad", "PI_SESSION_MISMATCH")) },
|
|
74
71
|
}).send("reviewer", "x"),
|
|
75
72
|
).rejects.toMatchObject({ code: "PI_SESSION_MISMATCH" });
|
|
76
73
|
expect(completeRun).toHaveBeenCalledWith(
|
|
@@ -83,7 +80,7 @@ describe("PiPrintAgentService", () => {
|
|
|
83
80
|
resolve: vi.fn().mockResolvedValueOnce(null).mockResolvedValueOnce([base, base]),
|
|
84
81
|
acquireRun: vi.fn(),
|
|
85
82
|
};
|
|
86
|
-
const early = new
|
|
83
|
+
const early = new PiPrintAgentService({
|
|
87
84
|
repository: earlyRepository,
|
|
88
85
|
probe: { validate: vi.fn() },
|
|
89
86
|
runner: { run: vi.fn() },
|
|
@@ -95,8 +92,6 @@ describe("PiPrintAgentService", () => {
|
|
|
95
92
|
});
|
|
96
93
|
|
|
97
94
|
it("rejects a non-Pi target without acquiring or mutating it", async () => {
|
|
98
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
99
|
-
const Service = api.PiPrintAgentService as new (options: unknown) => any;
|
|
100
95
|
const repository = {
|
|
101
96
|
resolve: vi.fn().mockResolvedValue({ ...base, provider: "claude" }),
|
|
102
97
|
acquireRun: vi.fn(),
|
|
@@ -105,18 +100,17 @@ describe("PiPrintAgentService", () => {
|
|
|
105
100
|
};
|
|
106
101
|
|
|
107
102
|
await expect(
|
|
108
|
-
new
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
103
|
+
new PiPrintAgentService({
|
|
104
|
+
repository,
|
|
105
|
+
probe: { validate: vi.fn() },
|
|
106
|
+
runner: { run: vi.fn() },
|
|
107
|
+
}).send("reviewer", "x"),
|
|
112
108
|
).rejects.toMatchObject({ code: "PI_UNSUPPORTED" });
|
|
113
109
|
expect(repository.acquireRun).not.toHaveBeenCalled();
|
|
114
110
|
expect(repository.completeRun).not.toHaveBeenCalled();
|
|
115
111
|
});
|
|
116
112
|
|
|
117
113
|
it("does not turn a successful completion write failure into a second completion", async () => {
|
|
118
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
119
|
-
const Service = api.PiPrintAgentService as new (options: unknown) => any;
|
|
120
114
|
const completionFailure = new Error("completion failed");
|
|
121
115
|
const repository = {
|
|
122
116
|
resolve: vi.fn().mockResolvedValue(base),
|
|
@@ -134,7 +128,10 @@ describe("PiPrintAgentService", () => {
|
|
|
134
128
|
};
|
|
135
129
|
|
|
136
130
|
await expect(
|
|
137
|
-
new
|
|
131
|
+
new PiPrintAgentService({ repository, probe: { validate: vi.fn() }, runner }).send(
|
|
132
|
+
"reviewer",
|
|
133
|
+
"x",
|
|
134
|
+
),
|
|
138
135
|
).rejects.toBe(completionFailure);
|
|
139
136
|
expect(repository.completeRun).toHaveBeenCalledOnce();
|
|
140
137
|
});
|
|
@@ -1,7 +1,8 @@
|
|
|
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 type { PiDurableAgent } from "../../../../
|
|
4
|
+
import type { PiDurableAgent } from "../../../../durable/DurableAgent.js";
|
|
5
|
+
import { PiPrintRunner } from "../../../../harnesses/pi/durable/PiPrintRunner.js";
|
|
5
6
|
|
|
6
7
|
const SESSION = "22222222-2222-4222-8222-222222222222";
|
|
7
8
|
function agent(sessionHealth: PiDurableAgent["sessionHealth"] = "uninitialized"): PiDurableAgent {
|
|
@@ -63,10 +64,7 @@ function events(session = SESSION): string[] {
|
|
|
63
64
|
];
|
|
64
65
|
}
|
|
65
66
|
async function runner(fixture: ReturnType<typeof fakeSpawn>, maxLineBytes?: number) {
|
|
66
|
-
|
|
67
|
-
expect(api).toHaveProperty("PiPrintRunner");
|
|
68
|
-
const Runner = api.PiPrintRunner as new (options: unknown) => any;
|
|
69
|
-
return new Runner({
|
|
67
|
+
return new PiPrintRunner({
|
|
70
68
|
spawn: fixture.spawn,
|
|
71
69
|
maxLineBytes,
|
|
72
70
|
processInspector: { getIdentity: () => ({ pid: 4242, startedAt: "start" }) },
|
|
@@ -154,10 +152,11 @@ describe("PiPrintRunner", () => {
|
|
|
154
152
|
(await runner(fakeSpawn(events(), 1))).run({ agent: agent(), prompt: "x", onSpawn: vi.fn() }),
|
|
155
153
|
).rejects.toMatchObject({ code: "PI_PROCESS" });
|
|
156
154
|
const fixture = fakeSpawn([]);
|
|
157
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
158
|
-
const Runner = api.PiPrintRunner as new (options: unknown) => any;
|
|
159
155
|
await expect(
|
|
160
|
-
new
|
|
156
|
+
new PiPrintRunner({
|
|
157
|
+
spawn: fixture.spawn,
|
|
158
|
+
processInspector: { getIdentity: () => null },
|
|
159
|
+
}).run({
|
|
161
160
|
agent: agent(),
|
|
162
161
|
prompt: "x",
|
|
163
162
|
onSpawn: vi.fn(),
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { describe, expect, it, vi } from "vitest";
|
|
3
3
|
import {
|
|
4
|
-
AGENTS,
|
|
5
4
|
getAgentReadinessReport,
|
|
6
5
|
getAgentReadinessReports,
|
|
7
6
|
type AgentReadinessOptions,
|
|
8
7
|
type ReadinessAgentType,
|
|
9
|
-
} from "
|
|
8
|
+
} from "../../../harnesses/readiness/AgentReadiness.js";
|
|
9
|
+
import { HARNESS_RUNTIME_PROFILES } from "../../../harnesses/runtimeProfiles.js";
|
|
10
10
|
|
|
11
11
|
type Files = Record<string, string>;
|
|
12
12
|
|
|
13
13
|
const builtInSkillNames = ["agent-management", "memory", "verify"];
|
|
14
|
-
const skillRoots: Record<
|
|
14
|
+
const skillRoots: Record<string, string> = {
|
|
15
15
|
claude: ".claude/skills",
|
|
16
16
|
codex: ".codex/skills",
|
|
17
17
|
copilot: ".copilot/skills",
|
|
18
|
+
gemini_cli: ".gemini/skills",
|
|
18
19
|
grok_cli: ".grok/skills",
|
|
20
|
+
antigravity_cli: ".gemini/config/skills",
|
|
19
21
|
opencode: ".config/opencode/skill",
|
|
20
22
|
pi: ".pi/agent/skills",
|
|
21
23
|
};
|
|
@@ -56,7 +58,17 @@ function fixture(overrides: Partial<AgentReadinessOptions> = {}) {
|
|
|
56
58
|
litellm: { key: "litellm-secret", env: { LITELLM_BASE_URL: "https://litellm.example.test" } },
|
|
57
59
|
}),
|
|
58
60
|
};
|
|
59
|
-
for (const directory of [
|
|
61
|
+
for (const directory of [
|
|
62
|
+
".claude",
|
|
63
|
+
".codex",
|
|
64
|
+
".copilot",
|
|
65
|
+
".gemini",
|
|
66
|
+
".grok",
|
|
67
|
+
".kiro",
|
|
68
|
+
".gemini/antigravity-cli",
|
|
69
|
+
".config/opencode",
|
|
70
|
+
".pi",
|
|
71
|
+
]) {
|
|
60
72
|
files[path.join(homeDir, directory)] = "<dir>";
|
|
61
73
|
}
|
|
62
74
|
for (const root of Object.values(skillRoots)) {
|
|
@@ -64,7 +76,9 @@ function fixture(overrides: Partial<AgentReadinessOptions> = {}) {
|
|
|
64
76
|
files[path.join(homeDir, root, skill, "SKILL.md")] = "# skill";
|
|
65
77
|
}
|
|
66
78
|
}
|
|
67
|
-
const executablePaths = Object.values(
|
|
79
|
+
const executablePaths = Object.values(HARNESS_RUNTIME_PROFILES).map((agent) =>
|
|
80
|
+
path.join("/bin", agent.command),
|
|
81
|
+
);
|
|
68
82
|
const options: AgentReadinessOptions = {
|
|
69
83
|
homeDir,
|
|
70
84
|
path: "/bin",
|
|
@@ -103,20 +117,30 @@ describe("agent readiness", () => {
|
|
|
103
117
|
expect(Object.keys(reports)).toEqual([
|
|
104
118
|
"claude",
|
|
105
119
|
"codex",
|
|
106
|
-
"
|
|
120
|
+
"gemini_cli",
|
|
107
121
|
"grok_cli",
|
|
122
|
+
"kiro",
|
|
123
|
+
"antigravity_cli",
|
|
108
124
|
"opencode",
|
|
125
|
+
"copilot",
|
|
109
126
|
"pi",
|
|
110
127
|
]);
|
|
111
|
-
expect(reports).not.toHaveProperty("gemini_cli");
|
|
112
128
|
for (const [agent, report] of Object.entries(reports) as Array<
|
|
113
129
|
[ReadinessAgentType, (typeof reports)[ReadinessAgentType]]
|
|
114
130
|
>) {
|
|
115
131
|
expect(report.type).toBe(agent);
|
|
116
132
|
expect(report.executable.status).toBe("pass");
|
|
117
133
|
expect(report.globalConfig.status).toBe("pass");
|
|
118
|
-
expect(report.builtInSkills).
|
|
134
|
+
expect(report.builtInSkills.status).toBe("info");
|
|
119
135
|
}
|
|
136
|
+
expect(reports.gemini_cli.builtInSkills).toMatchObject({ present: 3, required: 3 });
|
|
137
|
+
expect(reports.antigravity_cli.builtInSkills).toMatchObject({ present: 3, required: 3 });
|
|
138
|
+
expect(reports.kiro.builtInSkills).toMatchObject({
|
|
139
|
+
path: null,
|
|
140
|
+
present: 0,
|
|
141
|
+
required: 3,
|
|
142
|
+
missing: builtInSkillNames,
|
|
143
|
+
});
|
|
120
144
|
expect(reports.codex.integration).toMatchObject({
|
|
121
145
|
label: "ai-devkit hook",
|
|
122
146
|
installed: true,
|
|
@@ -133,13 +157,16 @@ describe("agent readiness", () => {
|
|
|
133
157
|
status: "pass",
|
|
134
158
|
});
|
|
135
159
|
expect(reports.copilot.integration).toBeUndefined();
|
|
160
|
+
expect(reports.gemini_cli.integration).toBeUndefined();
|
|
136
161
|
expect(reports.grok_cli.integration).toBeUndefined();
|
|
162
|
+
expect(reports.kiro.integration).toBeUndefined();
|
|
163
|
+
expect(reports.antigravity_cli.integration).toBeUndefined();
|
|
137
164
|
expect(reports.opencode.integration).toBeUndefined();
|
|
138
165
|
});
|
|
139
166
|
|
|
140
167
|
it("resolves agent executables from PATH directories containing spaces", async () => {
|
|
141
168
|
const spacedBin = "/Applications/Some App.app/Contents/Resources";
|
|
142
|
-
const codexPath = path.join(spacedBin,
|
|
169
|
+
const codexPath = path.join(spacedBin, HARNESS_RUNTIME_PROFILES.codex.command);
|
|
143
170
|
const { options } = fixture({
|
|
144
171
|
path: [spacedBin, "/usr/local/bin"].join(path.delimiter),
|
|
145
172
|
access: async (target) => {
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
5
|
+
import {
|
|
6
|
+
HARNESS_RUNTIME_PROFILES,
|
|
7
|
+
runtimeAgentMatchesHarness,
|
|
8
|
+
} from "../../harnesses/runtimeProfiles.js";
|
|
9
|
+
|
|
10
|
+
describe("harness runtime profiles", () => {
|
|
11
|
+
it("keeps launch and runtime identity metadata together", () => {
|
|
12
|
+
expect(HARNESS_RUNTIME_PROFILES.antigravity_cli).toMatchObject({
|
|
13
|
+
command: "agy",
|
|
14
|
+
runtimeKind: "agy",
|
|
15
|
+
discoveryAliases: ["agy", "antigravity", "antigravity_cli"],
|
|
16
|
+
});
|
|
17
|
+
expect(HARNESS_RUNTIME_PROFILES.antigravity_cli.matches("/usr/local/bin/agy")).toBe(true);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("recognizes agent commands without matching similar argument text", () => {
|
|
21
|
+
expect(HARNESS_RUNTIME_PROFILES.copilot.matches("/opt/copilot-cli/1.0/copilot")).toBe(true);
|
|
22
|
+
expect(HARNESS_RUNTIME_PROFILES.copilot.matches("node /repo/copilot-cli/script.js")).toBe(
|
|
23
|
+
false,
|
|
24
|
+
);
|
|
25
|
+
expect(HARNESS_RUNTIME_PROFILES.grok_cli.matches("/Users/dev/.grok/bin/grok --approve")).toBe(
|
|
26
|
+
true,
|
|
27
|
+
);
|
|
28
|
+
expect(HARNESS_RUNTIME_PROFILES.grok_cli.matches("node /repo/grok-cli/script.js")).toBe(false);
|
|
29
|
+
expect(
|
|
30
|
+
HARNESS_RUNTIME_PROFILES.gemini_cli.matches("node --no-warnings /usr/local/bin/gemini"),
|
|
31
|
+
).toBe(true);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("matches runtime discovery names through the owning harness profile", () => {
|
|
35
|
+
expect(runtimeAgentMatchesHarness("kiro-cli", "kiro")).toBe(true);
|
|
36
|
+
expect(runtimeAgentMatchesHarness("gemini", "gemini_cli")).toBe(true);
|
|
37
|
+
expect(runtimeAgentMatchesHarness("codex", "claude")).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe("harness matchers with executables under paths containing spaces", () => {
|
|
42
|
+
let root: string;
|
|
43
|
+
|
|
44
|
+
function install(relativePath: string): string {
|
|
45
|
+
const fullPath = path.join(root, relativePath);
|
|
46
|
+
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
47
|
+
fs.writeFileSync(fullPath, "");
|
|
48
|
+
return fullPath;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
beforeEach(() => {
|
|
52
|
+
root = fs.mkdtempSync(path.join(os.tmpdir(), "runtime-profiles-spaces-"));
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
afterEach(() => {
|
|
56
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("recognizes argv[0] under a spaced directory", () => {
|
|
60
|
+
const codex = install("Applications/Some App.app/Contents/Resources/codex");
|
|
61
|
+
const claude = install("Users/dev/My Tools/bin/claude");
|
|
62
|
+
|
|
63
|
+
expect(HARNESS_RUNTIME_PROFILES.codex.matches(`${codex} --sandbox workspace-write`)).toBe(true);
|
|
64
|
+
expect(HARNESS_RUNTIME_PROFILES.codex.matches(codex)).toBe(true);
|
|
65
|
+
expect(HARNESS_RUNTIME_PROFILES.claude.matches(`${claude} --continue`)).toBe(true);
|
|
66
|
+
expect(HARNESS_RUNTIME_PROFILES.claude.matches(`${codex} exec --cd /repo`)).toBe(false);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("recognizes argv[0] by distribution name under a spaced directory", () => {
|
|
70
|
+
const copilot = install("opt/Home Brew/Caskroom/copilot-cli/1.0.60/copilot");
|
|
71
|
+
|
|
72
|
+
expect(HARNESS_RUNTIME_PROFILES.copilot.matches(`${copilot} --allow-all-tools`)).toBe(true);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("does not treat arguments containing spaces as the executable", () => {
|
|
76
|
+
const vim = install("usr/bin/vim");
|
|
77
|
+
const codex = install("Applications/Some App.app/Contents/Resources/codex");
|
|
78
|
+
|
|
79
|
+
expect(HARNESS_RUNTIME_PROFILES.claude.matches(`${vim} My Notes/claude`)).toBe(false);
|
|
80
|
+
expect(
|
|
81
|
+
HARNESS_RUNTIME_PROFILES.claude.matches(`${codex} exec review the Other Dir/claude`),
|
|
82
|
+
).toBe(false);
|
|
83
|
+
expect(HARNESS_RUNTIME_PROFILES.copilot.matches(`${vim} Some Dir/copilot-cli/notes.md`)).toBe(
|
|
84
|
+
false,
|
|
85
|
+
);
|
|
86
|
+
expect(HARNESS_RUNTIME_PROFILES.claude.matches("/usr/bin/vim My Notes/claude")).toBe(false);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("recognizes spaced argv[0] in script-aware matchers", () => {
|
|
90
|
+
const pi = install("Users/dev/Node Tools/bin/pi");
|
|
91
|
+
const kiro = install("Applications/Kiro CLI.app/Contents/MacOS/kiro-cli");
|
|
92
|
+
const node = install("Applications/Dev Tools/node/bin/node");
|
|
93
|
+
|
|
94
|
+
expect(HARNESS_RUNTIME_PROFILES.pi.matches(`${pi} --model x`)).toBe(true);
|
|
95
|
+
expect(HARNESS_RUNTIME_PROFILES.kiro.matches(`${kiro} chat`)).toBe(true);
|
|
96
|
+
expect(
|
|
97
|
+
HARNESS_RUNTIME_PROFILES.gemini_cli.matches(`${node} /Users/dev/.npm/bin/gemini --yolo`),
|
|
98
|
+
).toBe(true);
|
|
99
|
+
expect(HARNESS_RUNTIME_PROFILES.pi.matches(`${node} /opt/pi-tools/script.js`)).toBe(false);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it("does not match agent words inside an executable directory", () => {
|
|
103
|
+
const node = install("opt/Dev pi gemini/bin/node");
|
|
104
|
+
|
|
105
|
+
expect(HARNESS_RUNTIME_PROFILES.pi.matches(`${node} /repo/script.js`)).toBe(false);
|
|
106
|
+
expect(HARNESS_RUNTIME_PROFILES.gemini_cli.matches(`${node} /repo/script.js`)).toBe(false);
|
|
107
|
+
expect(HARNESS_RUNTIME_PROFILES.gemini_cli.matches(`${node} /repo/bin/gemini`)).toBe(true);
|
|
108
|
+
expect(HARNESS_RUNTIME_PROFILES.pi.matches(`${node} --title pi`)).toBe(true);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
@@ -1,18 +1,9 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { DurableAgentBusyError } from "../../durable/DurableAgent.js";
|
|
2
3
|
|
|
3
|
-
describe("durable-agent
|
|
4
|
-
it("
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
expect(api).toHaveProperty("DurableAgentBusyError");
|
|
8
|
-
const ErrorType = api.DurableAgentBusyError as new (
|
|
9
|
-
agentId: string,
|
|
10
|
-
name: string,
|
|
11
|
-
) => Error & {
|
|
12
|
-
code: string;
|
|
13
|
-
agentId: string;
|
|
14
|
-
};
|
|
15
|
-
const error = new ErrorType("agent-id", "reviewer");
|
|
4
|
+
describe("durable-agent errors", () => {
|
|
5
|
+
it("classifies a busy error without exposing prompt data", () => {
|
|
6
|
+
const error = new DurableAgentBusyError("agent-id", "reviewer");
|
|
16
7
|
|
|
17
8
|
expect(error).toMatchObject({
|
|
18
9
|
name: "DurableAgentBusyError",
|
|
@@ -2,6 +2,7 @@ import fs from "fs";
|
|
|
2
2
|
import os from "os";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { afterEach, describe, expect, it } from "vitest";
|
|
5
|
+
import { DurableAgentRepository } from "../../durable/DurableAgentRepository.js";
|
|
5
6
|
|
|
6
7
|
const tempDirs: string[] = [];
|
|
7
8
|
|
|
@@ -9,12 +10,6 @@ afterEach(() => {
|
|
|
9
10
|
for (const dir of tempDirs.splice(0)) fs.rmSync(dir, { recursive: true, force: true });
|
|
10
11
|
});
|
|
11
12
|
|
|
12
|
-
async function loadStore(): Promise<any> {
|
|
13
|
-
const api = (await import("../../index.js")) as Record<string, unknown>;
|
|
14
|
-
expect(api).toHaveProperty("DurableAgentRepository");
|
|
15
|
-
return api.DurableAgentRepository;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
13
|
function fixture(): { root: string; cwd: string; dbPath: string } {
|
|
19
14
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), "durable-agent-store-"));
|
|
20
15
|
tempDirs.push(root);
|
|
@@ -25,7 +20,6 @@ function fixture(): { root: string; cwd: string; dbPath: string } {
|
|
|
25
20
|
|
|
26
21
|
describe("DurableAgentRepository create/list/resolve", () => {
|
|
27
22
|
it("creates distinct durable identities with a canonical cwd and lists them", async () => {
|
|
28
|
-
const DurableAgentRepository = await loadStore();
|
|
29
23
|
const { cwd, dbPath } = fixture();
|
|
30
24
|
const repository = new DurableAgentRepository({
|
|
31
25
|
dbPath,
|
|
@@ -51,7 +45,6 @@ describe("DurableAgentRepository create/list/resolve", () => {
|
|
|
51
45
|
});
|
|
52
46
|
|
|
53
47
|
it("resolves exact ids and names and rejects duplicate names", async () => {
|
|
54
|
-
const DurableAgentRepository = await loadStore();
|
|
55
48
|
const { cwd, dbPath } = fixture();
|
|
56
49
|
const repository = new DurableAgentRepository({ dbPath });
|
|
57
50
|
const agent = await repository.create({ name: "Reviewer", cwd });
|
|
@@ -65,7 +58,6 @@ describe("DurableAgentRepository create/list/resolve", () => {
|
|
|
65
58
|
});
|
|
66
59
|
|
|
67
60
|
it("rejects a missing cwd", async () => {
|
|
68
|
-
const DurableAgentRepository = await loadStore();
|
|
69
61
|
const { root, dbPath } = fixture();
|
|
70
62
|
const repository = new DurableAgentRepository({ dbPath });
|
|
71
63
|
|
|
@@ -77,7 +69,6 @@ describe("DurableAgentRepository create/list/resolve", () => {
|
|
|
77
69
|
|
|
78
70
|
describe("DurableAgentRepository run ownership", () => {
|
|
79
71
|
it("fails fast when another exact owner is live and completes only for its token", async () => {
|
|
80
|
-
const DurableAgentRepository = await loadStore();
|
|
81
72
|
const { cwd, dbPath } = fixture();
|
|
82
73
|
const live = new Map<number, string>([[process.pid, "owner-start"]]);
|
|
83
74
|
const processInspector = {
|
|
@@ -112,7 +103,6 @@ describe("DurableAgentRepository run ownership", () => {
|
|
|
112
103
|
});
|
|
113
104
|
|
|
114
105
|
it("retains busy for a live provider then recovers a dead run without signaling it", async () => {
|
|
115
|
-
const DurableAgentRepository = await loadStore();
|
|
116
106
|
const { cwd, dbPath } = fixture();
|
|
117
107
|
const live = new Map<number, string>([
|
|
118
108
|
[process.pid, "owner-start"],
|
|
@@ -151,7 +141,6 @@ describe("DurableAgentRepository run ownership", () => {
|
|
|
151
141
|
});
|
|
152
142
|
|
|
153
143
|
it("reconciles an interrupted run to degraded during list", async () => {
|
|
154
|
-
const DurableAgentRepository = await loadStore();
|
|
155
144
|
const { cwd, dbPath } = fixture();
|
|
156
145
|
const live = new Map<number, string>([[process.pid, "owner-start"]]);
|
|
157
146
|
const repository = new DurableAgentRepository({
|
|
@@ -179,7 +168,6 @@ describe("DurableAgentRepository run ownership", () => {
|
|
|
179
168
|
});
|
|
180
169
|
|
|
181
170
|
it("rejects send acquisition when the bound cwd is replaced by a symlink", async () => {
|
|
182
|
-
const DurableAgentRepository = await loadStore();
|
|
183
171
|
const { root, cwd, dbPath } = fixture();
|
|
184
172
|
const repository = new DurableAgentRepository({ dbPath });
|
|
185
173
|
const agent = await repository.create({ name: "bound", cwd });
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from "../../runtime/ManagedAgentRuntime.js";
|
|
16
16
|
import type { AgentInfo } from "../../adapters/AgentAdapter.js";
|
|
17
17
|
import type { AgentRegistry, RegistryEntry } from "../../utils/AgentRegistry.js";
|
|
18
|
-
import type { TmuxManager } from "../../
|
|
18
|
+
import type { TmuxManager } from "../../runtime/tmux/TmuxManager.js";
|
|
19
19
|
import type { InteractiveAgentRuntime } from "../../runtime/types.js";
|
|
20
20
|
|
|
21
21
|
function makeAgent(overrides: Partial<AgentInfo> = {}): AgentInfo {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { execFile } from "child_process";
|
|
2
2
|
import type { MockedFunction } from "vitest";
|
|
3
|
-
import { TmuxManager } from "../../
|
|
3
|
+
import { TmuxManager } from "../../runtime/tmux/TmuxManager.js";
|
|
4
4
|
|
|
5
5
|
vi.mock("child_process", () => ({
|
|
6
6
|
execFile: vi.fn(),
|
package/src/capacity/index.ts
CHANGED
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
import { constants } from "node:fs";
|
|
2
2
|
import { access as fsAccess } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { codexUnavailableReport, probeCodexCapacity } from "./codex.js";
|
|
5
|
-
import { probeClaudeCapacity, type ClaudeCapacityOptions } from "./claude.js";
|
|
6
|
-
import {
|
|
7
|
-
|
|
4
|
+
import { codexUnavailableReport, probeCodexCapacity } from "./sources/codex.js";
|
|
5
|
+
import { probeClaudeCapacity, type ClaudeCapacityOptions } from "./sources/claude.js";
|
|
6
|
+
import {
|
|
7
|
+
probeOpenAiCapacity,
|
|
8
|
+
probePiAnthropicCapacity,
|
|
9
|
+
probeZaiCapacity,
|
|
10
|
+
type PiAnthropicCapacityOptions,
|
|
11
|
+
type PiOpenAiCapacityOptions,
|
|
12
|
+
type PiZaiCapacityOptions,
|
|
13
|
+
} from "./sources/pi.js";
|
|
8
14
|
import type { CapacityReport } from "./types.js";
|
|
9
15
|
|
|
10
16
|
export type { CapacityReport, CapacityWindow } from "./types.js";
|
|
11
|
-
export type { ClaudeCapacityOptions } from "./claude.js";
|
|
17
|
+
export type { ClaudeCapacityOptions } from "./sources/claude.js";
|
|
18
|
+
export type { PiAnthropicCapacityOptions as AnthropicCapacityOptions } from "./sources/pi.js";
|
|
19
|
+
export type {
|
|
20
|
+
PiOpenAiCapacityOptions as OpenAiCapacityOptions,
|
|
21
|
+
PiZaiCapacityOptions as ZaiCapacityOptions,
|
|
22
|
+
} from "./sources/pi.js";
|
|
12
23
|
|
|
13
24
|
export type CapacityProbeOptions = {
|
|
14
25
|
now?: () => Date;
|
|
@@ -17,22 +28,6 @@ export type CapacityProbeOptions = {
|
|
|
17
28
|
probe?: typeof probeCodexCapacity;
|
|
18
29
|
};
|
|
19
30
|
|
|
20
|
-
export type ZaiCapacityOptions = {
|
|
21
|
-
now?: () => Date;
|
|
22
|
-
env?: NodeJS.ProcessEnv;
|
|
23
|
-
readFile?: (path: string, encoding: BufferEncoding) => Promise<string>;
|
|
24
|
-
fetch?: typeof globalThis.fetch;
|
|
25
|
-
timeoutMs?: number;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export type OpenAiCapacityOptions = {
|
|
29
|
-
now?: () => Date;
|
|
30
|
-
env?: NodeJS.ProcessEnv;
|
|
31
|
-
readFile?: (path: string, encoding: BufferEncoding) => Promise<string>;
|
|
32
|
-
fetch?: typeof globalThis.fetch;
|
|
33
|
-
timeoutMs?: number;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
31
|
async function canAccess(target: string, mode: number): Promise<boolean> {
|
|
37
32
|
try {
|
|
38
33
|
await fsAccess(target, mode);
|
|
@@ -78,7 +73,7 @@ export async function getCodexCapacityReport(
|
|
|
78
73
|
}
|
|
79
74
|
|
|
80
75
|
export async function getZaiCapacityReport(
|
|
81
|
-
options:
|
|
76
|
+
options: PiZaiCapacityOptions = {},
|
|
82
77
|
): Promise<CapacityReport> {
|
|
83
78
|
const { now, ...probeOptions } = options;
|
|
84
79
|
return probeZaiCapacity({
|
|
@@ -88,7 +83,7 @@ export async function getZaiCapacityReport(
|
|
|
88
83
|
}
|
|
89
84
|
|
|
90
85
|
export async function getOpenAiCapacityReport(
|
|
91
|
-
options:
|
|
86
|
+
options: PiOpenAiCapacityOptions = {},
|
|
92
87
|
): Promise<CapacityReport> {
|
|
93
88
|
const { now, ...probeOptions } = options;
|
|
94
89
|
return probeOpenAiCapacity({
|
|
@@ -107,3 +102,14 @@ export async function getClaudeCapacityReport(
|
|
|
107
102
|
now,
|
|
108
103
|
});
|
|
109
104
|
}
|
|
105
|
+
|
|
106
|
+
export async function getAnthropicCapacityReport(
|
|
107
|
+
options: PiAnthropicCapacityOptions = {},
|
|
108
|
+
): Promise<CapacityReport> {
|
|
109
|
+
const { now, ...probeOptions } = options;
|
|
110
|
+
return probePiAnthropicCapacity({
|
|
111
|
+
...probeOptions,
|
|
112
|
+
checkedAt: (now?.() ?? new Date()).toISOString(),
|
|
113
|
+
now,
|
|
114
|
+
});
|
|
115
|
+
}
|