@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
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
CODEX_APP_SERVER_ARGS,
|
|
4
4
|
parseUsage,
|
|
5
5
|
probeCodexCapacity,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from "../../capacity/
|
|
6
|
+
} from "../../capacity/sources/codex.js";
|
|
7
|
+
import { resolveCodexAuthPath } from "../../harnesses/codex/credentials.js";
|
|
8
|
+
import { toRateWindow } from "../../capacity/providers/openai-subscription.js";
|
|
9
9
|
|
|
10
10
|
const checkedAt = "2026-08-20T10:00:00.000Z";
|
|
11
11
|
const context = { installed: true, checkedAt };
|
|
@@ -52,9 +52,7 @@ describe("Codex auth resolution", () => {
|
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
it("falls back to ~/.codex/auth.json", () => {
|
|
55
|
-
expect(resolveCodexAuthPath({ HOME: "/users/test" })).toBe(
|
|
56
|
-
"/users/test/.codex/auth.json",
|
|
57
|
-
);
|
|
55
|
+
expect(resolveCodexAuthPath({ HOME: "/users/test" })).toBe("/users/test/.codex/auth.json");
|
|
58
56
|
});
|
|
59
57
|
});
|
|
60
58
|
|
|
@@ -108,9 +106,7 @@ describe("tiered Codex probing", () => {
|
|
|
108
106
|
status: 200,
|
|
109
107
|
}),
|
|
110
108
|
)
|
|
111
|
-
.mockResolvedValueOnce(
|
|
112
|
-
new Response(JSON.stringify(apiUsage()), { status: 200 }),
|
|
113
|
-
);
|
|
109
|
+
.mockResolvedValueOnce(new Response(JSON.stringify(apiUsage()), { status: 200 }));
|
|
114
110
|
const rpc = vi.fn();
|
|
115
111
|
const result = await probeCodexCapacity({
|
|
116
112
|
...context,
|
|
@@ -129,9 +125,7 @@ describe("tiered Codex probing", () => {
|
|
|
129
125
|
expect(fetch.mock.calls[0][0]).toBe(
|
|
130
126
|
"https://auth.openai.com/api/accounts/v1/user-auth-credential/whoami",
|
|
131
127
|
);
|
|
132
|
-
expect(fetch.mock.calls[1][0]).toBe(
|
|
133
|
-
"https://chatgpt.com/backend-api/wham/usage",
|
|
134
|
-
);
|
|
128
|
+
expect(fetch.mock.calls[1][0]).toBe("https://chatgpt.com/backend-api/wham/usage");
|
|
135
129
|
expect(fetch.mock.calls[1][1].headers).toMatchObject({
|
|
136
130
|
Authorization: "Bearer pat-secret",
|
|
137
131
|
"ChatGPT-Account-Id": "acct-1",
|
|
@@ -154,9 +148,7 @@ describe("tiered Codex probing", () => {
|
|
|
154
148
|
it("selects a fresh OAuth token without calling whoami", async () => {
|
|
155
149
|
const fetch = vi
|
|
156
150
|
.fn()
|
|
157
|
-
.mockResolvedValue(
|
|
158
|
-
new Response(JSON.stringify(apiUsage()), { status: 200 }),
|
|
159
|
-
);
|
|
151
|
+
.mockResolvedValue(new Response(JSON.stringify(apiUsage()), { status: 200 }));
|
|
160
152
|
const result = await probeCodexCapacity({
|
|
161
153
|
...context,
|
|
162
154
|
readFile: async () =>
|
|
@@ -210,9 +202,7 @@ describe("tiered Codex probing", () => {
|
|
|
210
202
|
])("falls back to the CLI for %s", async (name, readFile) => {
|
|
211
203
|
const fetch = vi
|
|
212
204
|
.fn()
|
|
213
|
-
.mockResolvedValue(
|
|
214
|
-
new Response("", { status: name === "OAuth 401" ? 401 : 200 }),
|
|
215
|
-
);
|
|
205
|
+
.mockResolvedValue(new Response("", { status: name === "OAuth 401" ? 401 : 200 }));
|
|
216
206
|
const rpc = vi.fn(async () => ({
|
|
217
207
|
rateLimits: {
|
|
218
208
|
rateLimits: {
|
|
@@ -239,8 +229,7 @@ describe("tiered Codex probing", () => {
|
|
|
239
229
|
}));
|
|
240
230
|
const result = await probeCodexCapacity({
|
|
241
231
|
...context,
|
|
242
|
-
readFile: async () =>
|
|
243
|
-
JSON.stringify({ personal_access_token: "pat-secret" }),
|
|
232
|
+
readFile: async () => JSON.stringify({ personal_access_token: "pat-secret" }),
|
|
244
233
|
fetch: vi.fn().mockRejectedValue(new Error("network failure pat-secret")),
|
|
245
234
|
rpc,
|
|
246
235
|
});
|
|
@@ -252,9 +241,7 @@ describe("tiered Codex probing", () => {
|
|
|
252
241
|
const fetch = vi
|
|
253
242
|
.fn()
|
|
254
243
|
.mockRejectedValueOnce(new Error("PAT failed"))
|
|
255
|
-
.mockResolvedValueOnce(
|
|
256
|
-
new Response(JSON.stringify(apiUsage()), { status: 200 }),
|
|
257
|
-
);
|
|
244
|
+
.mockResolvedValueOnce(new Response(JSON.stringify(apiUsage()), { status: 200 }));
|
|
258
245
|
const rpc = vi.fn();
|
|
259
246
|
const result = await probeCodexCapacity({
|
|
260
247
|
...context,
|
|
@@ -294,13 +281,7 @@ describe("tiered Codex probing", () => {
|
|
|
294
281
|
"account/read",
|
|
295
282
|
]);
|
|
296
283
|
expect(JSON.stringify(messages)).not.toMatch(/prompt|turn\/start/);
|
|
297
|
-
expect(CODEX_APP_SERVER_ARGS).toEqual([
|
|
298
|
-
"-s",
|
|
299
|
-
"read-only",
|
|
300
|
-
"-a",
|
|
301
|
-
"untrusted",
|
|
302
|
-
"app-server",
|
|
303
|
-
]);
|
|
284
|
+
expect(CODEX_APP_SERVER_ARGS).toEqual(["-s", "read-only", "-a", "untrusted", "app-server"]);
|
|
304
285
|
});
|
|
305
286
|
|
|
306
287
|
it("uses account/read to distinguish logged-out CLI state", async () => {
|
|
@@ -316,11 +297,7 @@ describe("tiered Codex probing", () => {
|
|
|
316
297
|
});
|
|
317
298
|
|
|
318
299
|
it("never exposes tokens or raw auth content through failures", async () => {
|
|
319
|
-
const secrets = [
|
|
320
|
-
"pat-secret-value",
|
|
321
|
-
"oauth-secret-value",
|
|
322
|
-
"refresh-secret-value",
|
|
323
|
-
];
|
|
300
|
+
const secrets = ["pat-secret-value", "oauth-secret-value", "refresh-secret-value"];
|
|
324
301
|
const result = await probeCodexCapacity({
|
|
325
302
|
...context,
|
|
326
303
|
readFile: async () =>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"openai-codex": {
|
|
3
3
|
"type": "oauth",
|
|
4
|
-
"access": "
|
|
4
|
+
"access": "sample access value for tests",
|
|
5
5
|
"refresh": "fixture-refresh-token",
|
|
6
6
|
"expires": 1793000000000,
|
|
7
7
|
"accountId": "fixture-chatgpt-account-id"
|
|
@@ -2,14 +2,17 @@ import { readFile } from "node:fs/promises";
|
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { probeOpenAiCapacity } from "../../capacity/sources/pi.js";
|
|
5
6
|
import {
|
|
6
|
-
|
|
7
|
+
buildOpenAiPlatformCapacity,
|
|
7
8
|
parseOpenAiUsage,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} from "../../capacity/openai.js";
|
|
9
|
+
} from "../../capacity/providers/openai-platform.js";
|
|
10
|
+
import { resolvePiOpenAiCredential as resolveOpenAiCredential } from "../../harnesses/pi/credentials.js";
|
|
11
11
|
|
|
12
12
|
const checkedAt = "2026-09-26T10:00:00.000Z";
|
|
13
|
+
const fixtureOauthAccess = "sample access value for tests";
|
|
14
|
+
const fakeJwt = (payload: string) =>
|
|
15
|
+
["test", Buffer.from(payload).toString("base64url"), "test"].join(".");
|
|
13
16
|
const fixture = (name: string) =>
|
|
14
17
|
readFile(fileURLToPath(new URL(`./fixtures/${name}`, import.meta.url)), "utf8");
|
|
15
18
|
const fixtureString = (name: string) =>
|
|
@@ -59,7 +62,7 @@ describe("OpenAI tiered credential resolution", () => {
|
|
|
59
62
|
openai: { type: "api_key", key: "pi-openai-test-key" },
|
|
60
63
|
"openai-codex": {
|
|
61
64
|
type: "oauth",
|
|
62
|
-
access:
|
|
65
|
+
access: fixtureOauthAccess,
|
|
63
66
|
refresh: "fixture-refresh-token",
|
|
64
67
|
expires: 1793000000000,
|
|
65
68
|
accountId: "fixture-chatgpt-account-id",
|
|
@@ -83,7 +86,7 @@ describe("OpenAI tiered credential resolution", () => {
|
|
|
83
86
|
}),
|
|
84
87
|
).resolves.toEqual({
|
|
85
88
|
kind: "oauth",
|
|
86
|
-
access:
|
|
89
|
+
access: fixtureOauthAccess,
|
|
87
90
|
accountId: "fixture-chatgpt-account-id",
|
|
88
91
|
expiresMs: 1793000000000,
|
|
89
92
|
});
|
|
@@ -148,7 +151,7 @@ describe("OpenAI OAuth capacity probe", () => {
|
|
|
148
151
|
expect.objectContaining({
|
|
149
152
|
method: "GET",
|
|
150
153
|
headers: {
|
|
151
|
-
Authorization:
|
|
154
|
+
Authorization: `Bearer ${fixtureOauthAccess}`,
|
|
152
155
|
"ChatGPT-Account-Id": "fixture-chatgpt-account-id",
|
|
153
156
|
},
|
|
154
157
|
}),
|
|
@@ -217,7 +220,7 @@ describe("OpenAI OAuth capacity probe", () => {
|
|
|
217
220
|
const expiredJwtAuth = JSON.stringify({
|
|
218
221
|
"openai-codex": {
|
|
219
222
|
type: "oauth",
|
|
220
|
-
access:
|
|
223
|
+
access: fakeJwt(JSON.stringify({ exp: 1789000000 })),
|
|
221
224
|
accountId: "fixture-chatgpt-account-id",
|
|
222
225
|
},
|
|
223
226
|
});
|
|
@@ -235,7 +238,7 @@ describe("OpenAI OAuth capacity probe", () => {
|
|
|
235
238
|
const futureJwtAuth = JSON.stringify({
|
|
236
239
|
"openai-codex": {
|
|
237
240
|
type: "oauth",
|
|
238
|
-
access:
|
|
241
|
+
access: fakeJwt(JSON.stringify({ exp: 1793000000 })),
|
|
239
242
|
accountId: "fixture-chatgpt-account-id",
|
|
240
243
|
},
|
|
241
244
|
});
|
|
@@ -255,7 +258,7 @@ describe("OpenAI OAuth capacity probe", () => {
|
|
|
255
258
|
const auth = JSON.stringify({
|
|
256
259
|
"openai-codex": {
|
|
257
260
|
type: "oauth",
|
|
258
|
-
access: "
|
|
261
|
+
access: fakeJwt("not-json"),
|
|
259
262
|
accountId: "fixture-chatgpt-account-id",
|
|
260
263
|
},
|
|
261
264
|
});
|
|
@@ -391,11 +394,8 @@ describe("OpenAI usage mapping", () => {
|
|
|
391
394
|
...parseOpenAiUsage(JSON.parse(await fixture("openai-usage-completions.json"))),
|
|
392
395
|
...parseOpenAiUsage(JSON.parse(await fixture("openai-usage-responses.json"))),
|
|
393
396
|
];
|
|
394
|
-
const report =
|
|
397
|
+
const report = buildOpenAiPlatformCapacity(buckets, checkedAt);
|
|
395
398
|
expect(report).toMatchObject({
|
|
396
|
-
harness: "pi",
|
|
397
|
-
provider: "openai",
|
|
398
|
-
generatedAt: checkedAt,
|
|
399
399
|
authenticated: true,
|
|
400
400
|
available: "yes",
|
|
401
401
|
creditsRemaining: null,
|
|
@@ -427,7 +427,7 @@ describe("OpenAI usage mapping", () => {
|
|
|
427
427
|
});
|
|
428
428
|
|
|
429
429
|
it("reports zero usage for days without buckets", () => {
|
|
430
|
-
const report =
|
|
430
|
+
const report = buildOpenAiPlatformCapacity([], checkedAt);
|
|
431
431
|
expect(report.windows.map((window) => window.current)).toEqual([0, 0]);
|
|
432
432
|
expect(report.windows[0].resetsAt).toBe("2026-09-27T00:00:00.000Z");
|
|
433
433
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
3
|
import { describe, expect, it } from "vitest";
|
|
4
|
-
import { parseWhamUsage, toRateWindow } from "../../capacity/
|
|
4
|
+
import { parseWhamUsage, toRateWindow } from "../../capacity/providers/openai-subscription.js";
|
|
5
5
|
|
|
6
6
|
const fixture = (name: string) =>
|
|
7
7
|
readFile(fileURLToPath(new URL(`./fixtures/${name}`, import.meta.url)), "utf8");
|
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
3
|
import { describe, expect, it, vi } from "vitest";
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
resolveZaiApiKey,
|
|
8
|
-
} from "../../capacity/zai.js";
|
|
4
|
+
import { parseZaiCapacity } from "../../capacity/providers/zai.js";
|
|
5
|
+
import { probeZaiCapacity } from "../../capacity/sources/pi.js";
|
|
6
|
+
import { resolvePiZaiApiKey as resolveZaiApiKey } from "../../harnesses/pi/credentials.js";
|
|
9
7
|
|
|
10
8
|
const checkedAt = "2026-08-20T10:00:00.000Z";
|
|
11
9
|
const fixture = (name: string) =>
|
|
12
|
-
readFile(
|
|
13
|
-
fileURLToPath(new URL(`./fixtures/${name}`, import.meta.url)),
|
|
14
|
-
"utf8",
|
|
15
|
-
);
|
|
10
|
+
readFile(fileURLToPath(new URL(`./fixtures/${name}`, import.meta.url)), "utf8");
|
|
16
11
|
|
|
17
12
|
describe("z.ai credential resolution", () => {
|
|
18
13
|
it("prefers Z_AI_API_KEY without reading Pi auth", async () => {
|
|
@@ -31,44 +26,28 @@ describe("z.ai credential resolution", () => {
|
|
|
31
26
|
await expect(
|
|
32
27
|
resolveZaiApiKey({ env: { HOME: "/users/test" }, readFile: readAuth }),
|
|
33
28
|
).resolves.toBe("pi-zai-test-key");
|
|
34
|
-
expect(readAuth).toHaveBeenCalledWith(
|
|
35
|
-
"/users/test/.pi/agent/auth.json",
|
|
36
|
-
"utf8",
|
|
37
|
-
);
|
|
29
|
+
expect(readAuth).toHaveBeenCalledWith("/users/test/.pi/agent/auth.json", "utf8");
|
|
38
30
|
});
|
|
39
31
|
|
|
40
32
|
it.each([
|
|
41
33
|
[
|
|
42
34
|
"missing",
|
|
43
|
-
async () =>
|
|
44
|
-
Promise.reject(Object.assign(new Error("missing"), { code: "ENOENT" })),
|
|
35
|
+
async () => Promise.reject(Object.assign(new Error("missing"), { code: "ENOENT" })),
|
|
45
36
|
],
|
|
46
37
|
["invalid JSON", async () => "{"],
|
|
47
|
-
[
|
|
48
|
-
"wrong credential type",
|
|
49
|
-
async () => JSON.stringify({ zai: { type: "oauth", key: "x" } }),
|
|
50
|
-
],
|
|
38
|
+
["wrong credential type", async () => JSON.stringify({ zai: { type: "oauth", key: "x" } })],
|
|
51
39
|
["missing key", async () => JSON.stringify({ zai: { type: "api_key" } })],
|
|
52
|
-
])(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
).rejects.toThrow(/z\.ai API key|z\.ai Pi auth file/);
|
|
58
|
-
},
|
|
59
|
-
);
|
|
40
|
+
])("fails clearly for %s credentials without exposing file content", async (_name, readAuth) => {
|
|
41
|
+
await expect(
|
|
42
|
+
resolveZaiApiKey({ env: { HOME: "/users/test" }, readFile: readAuth }),
|
|
43
|
+
).rejects.toThrow(/z\.ai API key|z\.ai Pi auth file/);
|
|
44
|
+
});
|
|
60
45
|
});
|
|
61
46
|
|
|
62
47
|
describe("z.ai quota mapping", () => {
|
|
63
48
|
it("maps token, credit, and monthly MCP windows with recomputed usage", async () => {
|
|
64
|
-
const report =
|
|
65
|
-
JSON.parse(await fixture("zai-quota.json")),
|
|
66
|
-
checkedAt,
|
|
67
|
-
);
|
|
49
|
+
const report = parseZaiCapacity(JSON.parse(await fixture("zai-quota.json")));
|
|
68
50
|
expect(report).toMatchObject({
|
|
69
|
-
harness: "pi",
|
|
70
|
-
provider: "zai",
|
|
71
|
-
generatedAt: checkedAt,
|
|
72
51
|
authenticated: true,
|
|
73
52
|
available: "yes",
|
|
74
53
|
creditsRemaining: null,
|
|
@@ -111,40 +90,26 @@ describe("z.ai quota mapping", () => {
|
|
|
111
90
|
});
|
|
112
91
|
|
|
113
92
|
it("uses and clamps the server percentage when quota amounts are unavailable", () => {
|
|
114
|
-
const report =
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
],
|
|
123
|
-
},
|
|
93
|
+
const report = parseZaiCapacity({
|
|
94
|
+
success: true,
|
|
95
|
+
code: 200,
|
|
96
|
+
data: {
|
|
97
|
+
limits: [
|
|
98
|
+
{ type: "TOKENS_LIMIT", unit: 1, number: 1, percentage: 120 },
|
|
99
|
+
{ type: "CREDIT_LIMIT", unit: 5, number: 30, percentage: -5 },
|
|
100
|
+
],
|
|
124
101
|
},
|
|
125
|
-
|
|
126
|
-
);
|
|
127
|
-
expect(report.windows.map((window) => window.usedPercent)).toEqual([
|
|
128
|
-
100, 0,
|
|
129
|
-
]);
|
|
102
|
+
});
|
|
103
|
+
expect(report.windows.map((window) => window.usedPercent)).toEqual([100, 0]);
|
|
130
104
|
});
|
|
131
105
|
|
|
132
106
|
it.each([
|
|
133
|
-
[
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
],
|
|
137
|
-
[
|
|
138
|
-
"unsuccessful envelope",
|
|
139
|
-
async () => ({ success: false, code: 401, data: { limits: [] } }),
|
|
140
|
-
],
|
|
141
|
-
[
|
|
142
|
-
"invalid entry",
|
|
143
|
-
async () => ({ success: true, code: 200, data: { limits: [{}] } }),
|
|
144
|
-
],
|
|
107
|
+
["invalid fixture", async () => JSON.parse(await fixture("zai-quota-invalid.json"))],
|
|
108
|
+
["unsuccessful envelope", async () => ({ success: false, code: 401, data: { limits: [] } })],
|
|
109
|
+
["invalid entry", async () => ({ success: true, code: 200, data: { limits: [{}] } })],
|
|
145
110
|
])("rejects %s", async (_name, input) => {
|
|
146
111
|
const value = await input();
|
|
147
|
-
expect(() =>
|
|
112
|
+
expect(() => parseZaiCapacity(value)).toThrow(/z\.ai quota/);
|
|
148
113
|
});
|
|
149
114
|
});
|
|
150
115
|
|
|
@@ -3,10 +3,10 @@ import os from "node:os";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
5
5
|
import {
|
|
6
|
-
ClaudePrintAgentService,
|
|
7
6
|
DurableAgentRepository,
|
|
8
7
|
type ProcessInspector,
|
|
9
|
-
} from "../../../../
|
|
8
|
+
} from "../../../../durable/DurableAgentRepository.js";
|
|
9
|
+
import { ClaudePrintAgentService } from "../../../../harnesses/claude/durable/ClaudePrintAgentService.js";
|
|
10
10
|
|
|
11
11
|
const roots: string[] = [];
|
|
12
12
|
|
|
@@ -1,7 +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 type { DurableAgent } from "../../../../
|
|
4
|
+
import type { DurableAgent } from "../../../../durable/DurableAgent.js";
|
|
5
5
|
import { ClaudePrintRunner } from "../../../../harnesses/claude/durable/ClaudePrintRunner.js";
|
|
6
6
|
|
|
7
7
|
function agent(): DurableAgent {
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { CodexCliProbe } from "../../../../harnesses/codex/durable/CodexCliProbe.js";
|
|
2
3
|
|
|
3
4
|
describe("CodexCliProbe", () => {
|
|
4
5
|
it("validates version, exec JSON/stdin, and resume capabilities without a model call", async () => {
|
|
5
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
6
|
-
expect(api).toHaveProperty("CodexCliProbe");
|
|
7
6
|
const exec = vi
|
|
8
7
|
.fn()
|
|
9
8
|
.mockResolvedValueOnce({ stdout: "codex-cli 0.147.0", stderr: "" })
|
|
@@ -15,12 +14,12 @@ describe("CodexCliProbe", () => {
|
|
|
15
14
|
stdout: "Usage: codex exec resume [SESSION_ID] [PROMPT]\n--json\n- stdin",
|
|
16
15
|
stderr: "",
|
|
17
16
|
});
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
await expect(new CodexCliProbe({ executable: "fake-codex", exec }).validate()).resolves.toEqual(
|
|
18
|
+
{
|
|
19
|
+
executable: "fake-codex",
|
|
20
|
+
version: "codex-cli 0.147.0",
|
|
21
|
+
},
|
|
22
|
+
);
|
|
24
23
|
expect(exec.mock.calls).toEqual([
|
|
25
24
|
["fake-codex", ["--version"]],
|
|
26
25
|
["fake-codex", ["exec", "--help"]],
|
|
@@ -29,9 +28,7 @@ describe("CodexCliProbe", () => {
|
|
|
29
28
|
});
|
|
30
29
|
|
|
31
30
|
it("rejects unsupported and unavailable CLIs with bounded sanitized errors", async () => {
|
|
32
|
-
const
|
|
33
|
-
const Probe = api.CodexCliProbe as new (options: unknown) => any;
|
|
34
|
-
const unsupported = new Probe({
|
|
31
|
+
const unsupported = new CodexCliProbe({
|
|
35
32
|
exec: vi
|
|
36
33
|
.fn()
|
|
37
34
|
.mockResolvedValueOnce({ stdout: "version", stderr: "" })
|
|
@@ -39,7 +36,7 @@ describe("CodexCliProbe", () => {
|
|
|
39
36
|
.mockResolvedValueOnce({ stdout: "resume", stderr: "" }),
|
|
40
37
|
});
|
|
41
38
|
await expect(unsupported.validate()).rejects.toMatchObject({ code: "CODEX_CLI_UNSUPPORTED" });
|
|
42
|
-
const missingCommands = new
|
|
39
|
+
const missingCommands = new CodexCliProbe({
|
|
43
40
|
exec: vi
|
|
44
41
|
.fn()
|
|
45
42
|
.mockResolvedValueOnce({ stdout: "version", stderr: "" })
|
|
@@ -50,7 +47,7 @@ describe("CodexCliProbe", () => {
|
|
|
50
47
|
code: "CODEX_CLI_UNSUPPORTED",
|
|
51
48
|
});
|
|
52
49
|
|
|
53
|
-
const unavailable = new
|
|
50
|
+
const unavailable = new CodexCliProbe({
|
|
54
51
|
exec: vi.fn().mockRejectedValue(new Error(`bad\0${"x".repeat(1000)}`)),
|
|
55
52
|
});
|
|
56
53
|
const error = await unavailable.validate().catch((value: Error & { code: string }) => value);
|
|
@@ -60,25 +57,23 @@ describe("CodexCliProbe", () => {
|
|
|
60
57
|
});
|
|
61
58
|
|
|
62
59
|
it("reports an empty version response as unknown", async () => {
|
|
63
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
64
|
-
const Probe = api.CodexCliProbe as new (options: unknown) => any;
|
|
65
60
|
const exec = vi
|
|
66
61
|
.fn()
|
|
67
62
|
.mockResolvedValueOnce({ stdout: " \n", stderr: "" })
|
|
68
63
|
.mockResolvedValueOnce({ stdout: "exec --json -", stderr: "" })
|
|
69
64
|
.mockResolvedValueOnce({ stdout: "resume --json -", stderr: "" });
|
|
70
|
-
await expect(new
|
|
65
|
+
await expect(new CodexCliProbe({ exec }).validate()).resolves.toMatchObject({
|
|
66
|
+
version: "unknown",
|
|
67
|
+
});
|
|
71
68
|
});
|
|
72
69
|
|
|
73
70
|
it("requires a standalone stdin dash rather than accepting flag hyphens", async () => {
|
|
74
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
75
|
-
const Probe = api.CodexCliProbe as new (options: unknown) => any;
|
|
76
71
|
const exec = vi
|
|
77
72
|
.fn()
|
|
78
73
|
.mockResolvedValueOnce({ stdout: "version", stderr: "" })
|
|
79
74
|
.mockResolvedValueOnce({ stdout: "exec --json", stderr: "" })
|
|
80
75
|
.mockResolvedValueOnce({ stdout: "resume --json", stderr: "" });
|
|
81
|
-
await expect(new
|
|
76
|
+
await expect(new CodexCliProbe({ exec }).validate()).rejects.toMatchObject({
|
|
82
77
|
code: "CODEX_CLI_UNSUPPORTED",
|
|
83
78
|
});
|
|
84
79
|
});
|
|
@@ -2,12 +2,12 @@ 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 } from "../../../../durable/DurableAgent.js";
|
|
5
6
|
import {
|
|
6
|
-
CodexPrintError,
|
|
7
|
-
CodexPrintAgentService,
|
|
8
7
|
DurableAgentRepository,
|
|
9
8
|
type ProcessInspector,
|
|
10
|
-
} from "../../../../
|
|
9
|
+
} from "../../../../durable/DurableAgentRepository.js";
|
|
10
|
+
import { CodexPrintAgentService } from "../../../../harnesses/codex/durable/CodexPrintAgentService.js";
|
|
11
11
|
|
|
12
12
|
const SESSION = "22222222-2222-4222-8222-222222222222";
|
|
13
13
|
const roots: string[] = [];
|
|
@@ -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
|
|
|
3
5
|
const SESSION = "22222222-2222-4222-8222-222222222222";
|
|
4
6
|
const base = {
|
|
@@ -11,15 +13,15 @@ const base = {
|
|
|
11
13
|
|
|
12
14
|
describe("CodexPrintAgentService", () => {
|
|
13
15
|
it("validates before provider-aware create and never runs Codex", async () => {
|
|
14
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
15
|
-
expect(api).toHaveProperty("CodexPrintAgentService");
|
|
16
16
|
const probe = {
|
|
17
17
|
validate: vi.fn().mockResolvedValue({ executable: "codex", version: "0.147.0" }),
|
|
18
18
|
};
|
|
19
19
|
const repository = { create: vi.fn().mockResolvedValue(base) };
|
|
20
20
|
const runner = { run: vi.fn() };
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
await new CodexPrintAgentService({ repository, probe, runner }).create({
|
|
22
|
+
name: "reviewer",
|
|
23
|
+
cwd: "/project",
|
|
24
|
+
});
|
|
23
25
|
expect(repository.create).toHaveBeenCalledWith({
|
|
24
26
|
name: "reviewer",
|
|
25
27
|
cwd: "/project",
|
|
@@ -29,7 +31,6 @@ describe("CodexPrintAgentService", () => {
|
|
|
29
31
|
});
|
|
30
32
|
|
|
31
33
|
it("binds during first send and explicitly resumes later sends", async () => {
|
|
32
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
33
34
|
const repository = {
|
|
34
35
|
resolve: vi.fn().mockResolvedValue(base),
|
|
35
36
|
acquireRun: vi
|
|
@@ -50,8 +51,7 @@ describe("CodexPrintAgentService", () => {
|
|
|
50
51
|
return { sessionId: SESSION, result: "answer", messages: ["answer"], exitCode: 0 };
|
|
51
52
|
}),
|
|
52
53
|
};
|
|
53
|
-
const
|
|
54
|
-
const service = new Service({
|
|
54
|
+
const service = new CodexPrintAgentService({
|
|
55
55
|
repository,
|
|
56
56
|
probe: { validate: vi.fn() },
|
|
57
57
|
runner,
|
|
@@ -74,8 +74,6 @@ describe("CodexPrintAgentService", () => {
|
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
it("records mismatch separately from unknown failures", async () => {
|
|
77
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
78
|
-
const ErrorType = api.CodexPrintError as new (message: string, code: string) => Error;
|
|
79
77
|
const completeRun = vi.fn();
|
|
80
78
|
const repository = {
|
|
81
79
|
resolve: vi.fn().mockResolvedValue(base),
|
|
@@ -84,12 +82,11 @@ describe("CodexPrintAgentService", () => {
|
|
|
84
82
|
bindProviderSession: vi.fn(),
|
|
85
83
|
completeRun,
|
|
86
84
|
};
|
|
87
|
-
const
|
|
88
|
-
const service = new Service({
|
|
85
|
+
const service = new CodexPrintAgentService({
|
|
89
86
|
repository,
|
|
90
87
|
probe: { validate: vi.fn() },
|
|
91
88
|
runner: {
|
|
92
|
-
run: vi.fn().mockRejectedValue(new
|
|
89
|
+
run: vi.fn().mockRejectedValue(new CodexPrintError("mismatch", "CODEX_SESSION_MISMATCH")),
|
|
93
90
|
},
|
|
94
91
|
});
|
|
95
92
|
await expect(service.send("reviewer", "x")).rejects.toMatchObject({
|
|
@@ -103,8 +100,6 @@ describe("CodexPrintAgentService", () => {
|
|
|
103
100
|
});
|
|
104
101
|
|
|
105
102
|
it("rejects a non-Codex target without acquiring or mutating it", async () => {
|
|
106
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
107
|
-
const Service = api.CodexPrintAgentService as new (options: unknown) => any;
|
|
108
103
|
const repository = {
|
|
109
104
|
resolve: vi.fn().mockResolvedValue({ ...base, provider: "claude" }),
|
|
110
105
|
acquireRun: vi.fn(),
|
|
@@ -114,18 +109,17 @@ describe("CodexPrintAgentService", () => {
|
|
|
114
109
|
};
|
|
115
110
|
|
|
116
111
|
await expect(
|
|
117
|
-
new
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
112
|
+
new CodexPrintAgentService({
|
|
113
|
+
repository,
|
|
114
|
+
probe: { validate: vi.fn() },
|
|
115
|
+
runner: { run: vi.fn() },
|
|
116
|
+
}).send("reviewer", "x"),
|
|
121
117
|
).rejects.toMatchObject({ code: "CODEX_UNSUPPORTED" });
|
|
122
118
|
expect(repository.acquireRun).not.toHaveBeenCalled();
|
|
123
119
|
expect(repository.completeRun).not.toHaveBeenCalled();
|
|
124
120
|
});
|
|
125
121
|
|
|
126
122
|
it("does not turn a successful completion write failure into a second completion", async () => {
|
|
127
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
128
|
-
const Service = api.CodexPrintAgentService as new (options: unknown) => any;
|
|
129
123
|
const completionFailure = new Error("completion failed");
|
|
130
124
|
const repository = {
|
|
131
125
|
resolve: vi.fn().mockResolvedValue(base),
|
|
@@ -144,14 +138,15 @@ describe("CodexPrintAgentService", () => {
|
|
|
144
138
|
};
|
|
145
139
|
|
|
146
140
|
await expect(
|
|
147
|
-
new
|
|
141
|
+
new CodexPrintAgentService({ repository, probe: { validate: vi.fn() }, runner }).send(
|
|
142
|
+
"reviewer",
|
|
143
|
+
"x",
|
|
144
|
+
),
|
|
148
145
|
).rejects.toBe(completionFailure);
|
|
149
146
|
expect(repository.completeRun).toHaveBeenCalledOnce();
|
|
150
147
|
});
|
|
151
148
|
|
|
152
149
|
it("records a repository binding conflict as a session mismatch", async () => {
|
|
153
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
154
|
-
const BindingError = api.CodexPrintError as new (message: string, code: string) => Error;
|
|
155
150
|
const completeRun = vi.fn();
|
|
156
151
|
const repository = {
|
|
157
152
|
resolve: vi.fn().mockResolvedValue(base),
|
|
@@ -159,7 +154,7 @@ describe("CodexPrintAgentService", () => {
|
|
|
159
154
|
recordProviderProcess: vi.fn(),
|
|
160
155
|
bindProviderSession: vi
|
|
161
156
|
.fn()
|
|
162
|
-
.mockRejectedValue(new
|
|
157
|
+
.mockRejectedValue(new CodexPrintError("binding mismatch", "CODEX_SESSION_MISMATCH")),
|
|
163
158
|
completeRun,
|
|
164
159
|
};
|
|
165
160
|
const runner = {
|
|
@@ -168,10 +163,11 @@ describe("CodexPrintAgentService", () => {
|
|
|
168
163
|
return { sessionId: SESSION, result: "x", messages: ["x"], exitCode: 0 };
|
|
169
164
|
}),
|
|
170
165
|
};
|
|
171
|
-
const Service = api.CodexPrintAgentService as new (options: unknown) => any;
|
|
172
|
-
|
|
173
166
|
await expect(
|
|
174
|
-
new
|
|
167
|
+
new CodexPrintAgentService({ repository, probe: { validate: vi.fn() }, runner }).send(
|
|
168
|
+
"reviewer",
|
|
169
|
+
"x",
|
|
170
|
+
),
|
|
175
171
|
).rejects.toMatchObject({ code: "CODEX_SESSION_MISMATCH" });
|
|
176
172
|
expect(completeRun).toHaveBeenCalledWith(
|
|
177
173
|
"id",
|
|
@@ -181,8 +177,6 @@ describe("CodexPrintAgentService", () => {
|
|
|
181
177
|
});
|
|
182
178
|
|
|
183
179
|
it("rejects missing and ambiguous records before acquiring a run", async () => {
|
|
184
|
-
const api = (await import("../../../../index.js")) as Record<string, unknown>;
|
|
185
|
-
const Service = api.CodexPrintAgentService as new (options: unknown) => any;
|
|
186
180
|
const repository = {
|
|
187
181
|
create: vi.fn(),
|
|
188
182
|
resolve: vi.fn().mockResolvedValueOnce(null).mockResolvedValueOnce([base, base]),
|
|
@@ -191,7 +185,7 @@ describe("CodexPrintAgentService", () => {
|
|
|
191
185
|
bindProviderSession: vi.fn(),
|
|
192
186
|
completeRun: vi.fn(),
|
|
193
187
|
};
|
|
194
|
-
const service = new
|
|
188
|
+
const service = new CodexPrintAgentService({
|
|
195
189
|
repository,
|
|
196
190
|
probe: { validate: vi.fn() },
|
|
197
191
|
runner: { run: vi.fn() },
|