@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
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { execFile } from "child_process";
|
|
2
|
+
import { promisify } from "util";
|
|
3
|
+
import { TerminalType, type TerminalBackend } from "../types.js";
|
|
4
|
+
import { ESCAPE_BYTE, execFileWithInput, sleep } from "./shared.js";
|
|
5
|
+
|
|
6
|
+
const execFileAsync = promisify(execFile);
|
|
7
|
+
|
|
8
|
+
export const tmuxBackend: TerminalBackend = {
|
|
9
|
+
type: TerminalType.TMUX,
|
|
10
|
+
label: "tmux",
|
|
11
|
+
|
|
12
|
+
async find(tty) {
|
|
13
|
+
try {
|
|
14
|
+
const { stdout } = await execFileAsync("tmux", [
|
|
15
|
+
"list-panes",
|
|
16
|
+
"-a",
|
|
17
|
+
"-F",
|
|
18
|
+
"#{pane_tty}|#{session_name}:#{window_index}.#{pane_index}",
|
|
19
|
+
]);
|
|
20
|
+
for (const line of stdout.trim().split("\n")) {
|
|
21
|
+
if (!line.trim()) continue;
|
|
22
|
+
const [paneTty, identifier] = line.split("|");
|
|
23
|
+
if (paneTty === tty && identifier) {
|
|
24
|
+
return { type: TerminalType.TMUX, identifier, tty };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
} catch {
|
|
28
|
+
// tmux might not be installed or running
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
async focus(location) {
|
|
34
|
+
await execFileAsync("tmux", ["switch-client", "-t", location.identifier]);
|
|
35
|
+
return true;
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
async send(location, message) {
|
|
39
|
+
const bufferName = `ai-devkit-send-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
40
|
+
await execFileWithInput("tmux", ["load-buffer", "-b", bufferName, "-"], message);
|
|
41
|
+
await execFileAsync("tmux", [
|
|
42
|
+
"paste-buffer",
|
|
43
|
+
"-t",
|
|
44
|
+
location.identifier,
|
|
45
|
+
"-b",
|
|
46
|
+
bufferName,
|
|
47
|
+
"-p",
|
|
48
|
+
"-d",
|
|
49
|
+
]);
|
|
50
|
+
await sleep(150);
|
|
51
|
+
await execFileAsync("tmux", ["send-keys", "-t", location.identifier, "Enter"]);
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
async sendKey(location, key) {
|
|
55
|
+
await execFileAsync("tmux", [
|
|
56
|
+
"send-keys",
|
|
57
|
+
"-t",
|
|
58
|
+
location.identifier,
|
|
59
|
+
key === ESCAPE_BYTE ? "Escape" : key,
|
|
60
|
+
]);
|
|
61
|
+
},
|
|
62
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { execFile } from "child_process";
|
|
2
|
+
import { promisify } from "util";
|
|
3
|
+
import { TerminalType, type TerminalBackend } from "../types.js";
|
|
4
|
+
import { CARRIAGE_RETURN, execFileWithInput, sleep } from "./shared.js";
|
|
5
|
+
|
|
6
|
+
const execFileAsync = promisify(execFile);
|
|
7
|
+
|
|
8
|
+
interface WeztermPaneEntry {
|
|
9
|
+
pane_id?: number;
|
|
10
|
+
tty_name?: string | null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const weztermBackend: TerminalBackend = {
|
|
14
|
+
type: TerminalType.WEZTERM,
|
|
15
|
+
label: "wezterm",
|
|
16
|
+
|
|
17
|
+
async find(tty) {
|
|
18
|
+
try {
|
|
19
|
+
const { stdout } = await execFileAsync("wezterm", ["cli", "list", "--format", "json"]);
|
|
20
|
+
const panes = JSON.parse(stdout) as WeztermPaneEntry[];
|
|
21
|
+
if (!Array.isArray(panes)) return null;
|
|
22
|
+
for (const pane of panes) {
|
|
23
|
+
if (pane?.tty_name === tty && pane.pane_id != null) {
|
|
24
|
+
return { type: TerminalType.WEZTERM, identifier: String(pane.pane_id), tty };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
} catch {
|
|
28
|
+
// wezterm might not be installed, running, or returning valid JSON
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
async focus(location) {
|
|
34
|
+
await execFileAsync("wezterm", ["cli", "activate-pane", "--pane-id", location.identifier]);
|
|
35
|
+
return true;
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
async send(location, message) {
|
|
39
|
+
await execFileWithInput(
|
|
40
|
+
"wezterm",
|
|
41
|
+
["cli", "send-text", "--pane-id", location.identifier],
|
|
42
|
+
message,
|
|
43
|
+
);
|
|
44
|
+
await sleep(150);
|
|
45
|
+
await execFileAsync("wezterm", [
|
|
46
|
+
"cli",
|
|
47
|
+
"send-text",
|
|
48
|
+
"--pane-id",
|
|
49
|
+
location.identifier,
|
|
50
|
+
"--no-paste",
|
|
51
|
+
CARRIAGE_RETURN,
|
|
52
|
+
]);
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
async sendKey(location, key) {
|
|
56
|
+
await execFileAsync("wezterm", [
|
|
57
|
+
"cli",
|
|
58
|
+
"send-text",
|
|
59
|
+
"--pane-id",
|
|
60
|
+
location.identifier,
|
|
61
|
+
"--no-paste",
|
|
62
|
+
key,
|
|
63
|
+
]);
|
|
64
|
+
},
|
|
65
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export enum TerminalType {
|
|
2
|
+
TMUX = "tmux",
|
|
3
|
+
WEZTERM = "wezterm",
|
|
4
|
+
ITERM2 = "iterm2",
|
|
5
|
+
TERMINAL_APP = "terminal-app",
|
|
6
|
+
UNKNOWN = "unknown",
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface TerminalLocation {
|
|
10
|
+
type: TerminalType;
|
|
11
|
+
identifier: string;
|
|
12
|
+
tty: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface TerminalBackend {
|
|
16
|
+
readonly type: Exclude<TerminalType, TerminalType.UNKNOWN>;
|
|
17
|
+
readonly label: string;
|
|
18
|
+
find(tty: string): Promise<TerminalLocation | null>;
|
|
19
|
+
focus(location: TerminalLocation): Promise<boolean>;
|
|
20
|
+
send(location: TerminalLocation, message: string): Promise<void>;
|
|
21
|
+
sendKey(location: TerminalLocation, key: string): Promise<void>;
|
|
22
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/__tests__/readiness/AgentReadiness.test.ts"],"sourcesContent":["import path from \"node:path\";\nimport { describe, expect, it, vi } from \"vitest\";\nimport {\n AGENTS,\n getAgentReadinessReport,\n getAgentReadinessReports,\n type AgentReadinessOptions,\n type ReadinessAgentType,\n} from \"../../index.js\";\n\ntype Files = Record<string, string>;\n\nconst builtInSkillNames = [\"agent-management\", \"memory\", \"verify\"];\nconst skillRoots: Record<ReadinessAgentType, string> = {\n claude: \".claude/skills\",\n codex: \".codex/skills\",\n copilot: \".copilot/skills\",\n grok_cli: \".grok/skills\",\n opencode: \".config/opencode/skill\",\n pi: \".pi/agent/skills\",\n};\n\nfunction fixture(overrides: Partial<AgentReadinessOptions> = {}) {\n const homeDir = \"/home/test\";\n const assetRoot = \"/assets\";\n const files: Files = {\n [path.join(homeDir, \".codex\", \"hooks\", \"codex-session-mapping.cjs\")]: \"codex-hook\",\n [path.join(assetRoot, \"codex\", \"codex-session-mapping.cjs\")]: \"codex-hook\",\n [path.join(homeDir, \".codex\", \"hooks.json\")]: JSON.stringify({\n hooks: {\n SessionStart: [\n {\n hooks: [{ type: \"command\", command: \"node ~/.codex/hooks/codex-session-mapping.cjs\" }],\n },\n ],\n },\n }),\n [path.join(homeDir, \".codex\", \"ai-devkit\", \"sessions.json\")]: JSON.stringify({\n \"123\": \"/sessions/codex.jsonl\",\n }),\n \"/sessions/codex.jsonl\": \"\",\n [path.join(homeDir, \".claude\", \"hooks\", \"claude-prompt-hook.js\")]: \"claude-hook\",\n [path.join(assetRoot, \"claude\", \"claude-prompt-hook.js\")]: \"claude-hook\",\n [path.join(homeDir, \".claude\", \"settings.json\")]: JSON.stringify({\n hooks: {\n PreToolUse: [\n { hooks: [{ type: \"command\", command: \"node ~/.claude/hooks/claude-prompt-hook.js\" }] },\n ],\n },\n }),\n [path.join(homeDir, \".pi\", \"agent\", \"sessions.json\")]: JSON.stringify({\n \"456\": \"/sessions/missing-pi.jsonl\",\n }),\n [path.join(homeDir, \".pi\", \"agent\", \"auth.json\")]: JSON.stringify({\n anthropic: { access: \"access-secret\", refresh: \"refresh-secret\" },\n litellm: { key: \"litellm-secret\", env: { LITELLM_BASE_URL: \"https://litellm.example.test\" } },\n }),\n };\n for (const directory of [\".claude\", \".codex\", \".copilot\", \".grok\", \".config/opencode\", \".pi\"]) {\n files[path.join(homeDir, directory)] = \"<dir>\";\n }\n for (const root of Object.values(skillRoots)) {\n for (const skill of builtInSkillNames) {\n files[path.join(homeDir, root, skill, \"SKILL.md\")] = \"# skill\";\n }\n }\n const executablePaths = Object.values(AGENTS).map((agent) => path.join(\"/bin\", agent.command));\n const options: AgentReadinessOptions = {\n homeDir,\n path: \"/bin\",\n assetRoot,\n builtInSkillNames,\n skillRoots,\n readFile: async (target) => {\n if (!(target in files)) throw new Error(\"missing\");\n return files[target];\n },\n access: async (target) => {\n if (executablePaths.includes(target) || target in files) return;\n throw new Error(\"missing\");\n },\n runCommand: vi.fn(async (command) => {\n if (command === \"pi\") return { stdout: \"npm:@ai-devkit/pi-session-tracker\\n\", stderr: \"\" };\n if (command === \"claude\") return { stdout: JSON.stringify({ loggedIn: true }), stderr: \"\" };\n if (command === \"gh\")\n return { stdout: \"github.com\\n Logged in to github.com account test-user\\n\", stderr: \"\" };\n if (command === \"opencode\")\n return { stdout: \"● litellm api\\n● OpenAI oauth\\n\", stderr: \"\" };\n throw new Error(`unexpected command ${command}`);\n }),\n codexAuth: async () => true,\n ...overrides,\n };\n return { options, files };\n}\n\ndescribe(\"agent readiness\", () => {\n it(\"reports every readiness-supported adapter with generic checks and only real integrations\", async () => {\n const { options } = fixture();\n\n const reports = await getAgentReadinessReports(options);\n\n expect(Object.keys(reports)).toEqual([\n \"claude\",\n \"codex\",\n \"copilot\",\n \"grok_cli\",\n \"opencode\",\n \"pi\",\n ]);\n expect(reports).not.toHaveProperty(\"gemini_cli\");\n for (const [agent, report] of Object.entries(reports) as Array<\n [ReadinessAgentType, (typeof reports)[ReadinessAgentType]]\n >) {\n expect(report.type).toBe(agent);\n expect(report.executable.status).toBe(\"pass\");\n expect(report.globalConfig.status).toBe(\"pass\");\n expect(report.builtInSkills).toMatchObject({ status: \"info\", present: 3, required: 3 });\n }\n expect(reports.codex.integration).toMatchObject({\n label: \"ai-devkit hook\",\n installed: true,\n status: \"pass\",\n });\n expect(reports.claude.integration).toMatchObject({\n label: \"ai-devkit hook\",\n installed: true,\n status: \"pass\",\n });\n expect(reports.pi.integration).toMatchObject({\n label: \"ai-devkit plugin\",\n installed: true,\n status: \"pass\",\n });\n expect(reports.copilot.integration).toBeUndefined();\n expect(reports.grok_cli.integration).toBeUndefined();\n expect(reports.opencode.integration).toBeUndefined();\n });\n\n it(\"resolves agent executables from PATH directories containing spaces\", async () => {\n const spacedBin = \"/Applications/Some App.app/Contents/Resources\";\n const codexPath = path.join(spacedBin, AGENTS.codex.command);\n const { options } = fixture({\n path: [spacedBin, \"/usr/local/bin\"].join(path.delimiter),\n access: async (target) => {\n if (target === codexPath || target.startsWith(\"/home/test\")) return;\n throw new Error(\"missing\");\n },\n });\n\n const report = await getAgentReadinessReport(\"codex\", options);\n\n expect(report.executable).toMatchObject({ command: \"codex\", path: codexPath, status: \"pass\" });\n });\n\n it(\"parses Pi provider names without returning credential values\", async () => {\n const { options } = fixture();\n\n const report = await getAgentReadinessReport(\"pi\", options);\n const serialized = JSON.stringify(report);\n\n expect(report.auth).toMatchObject({\n state: \"authenticated\",\n provider: null,\n availableProviders: [\"anthropic\", \"litellm\"],\n status: \"pass\",\n });\n expect(serialized).not.toContain(\"access-secret\");\n expect(serialized).not.toContain(\"refresh-secret\");\n expect(serialized).not.toContain(\"litellm-secret\");\n expect(serialized).not.toContain(\"litellm.example.test\");\n });\n\n it(\"accepts Pi session tracker display names from pi list output\", async () => {\n const { options } = fixture({\n runCommand: vi.fn(async (command) => {\n if (command === \"pi\") return { stdout: \"session tracker\\n\", stderr: \"\" };\n if (command === \"claude\") return { stdout: JSON.stringify({ loggedIn: true }), stderr: \"\" };\n throw new Error(`unexpected command ${command}`);\n }),\n });\n\n const report = await getAgentReadinessReport(\"pi\", options);\n\n expect(report.integration).toMatchObject({\n label: \"ai-devkit plugin\",\n installed: true,\n status: \"pass\",\n });\n });\n\n it(\"reports missing built-in skills as informational readiness\", async () => {\n const { options, files } = fixture();\n delete files[path.join(options.homeDir!, skillRoots.codex, \"verify\", \"SKILL.md\")];\n\n const report = await getAgentReadinessReport(\"codex\", options);\n\n expect(report.builtInSkills).toMatchObject({\n status: \"info\",\n present: 2,\n required: 3,\n missing: [\"verify\"],\n });\n expect(report.status).toBe(\"pass\");\n });\n\n it(\"checks OpenCode auth from auth list output\", async () => {\n const { options } = fixture({\n runCommand: vi.fn(async (command) => {\n if (command === \"opencode\") {\n return {\n stdout: \"\\x1B[32m●\\x1B[0m litellm api\\n● OpenAI oauth\\n● GitLab Duo GITLAB_TOKEN\\n\",\n stderr: \"\",\n };\n }\n if (command === \"pi\") return { stdout: \"npm:@ai-devkit/pi-session-tracker\\n\", stderr: \"\" };\n if (command === \"claude\") return { stdout: JSON.stringify({ loggedIn: true }), stderr: \"\" };\n throw new Error(`unexpected command ${command}`);\n }),\n });\n\n const report = await getAgentReadinessReport(\"opencode\", options);\n\n expect(report.auth).toMatchObject({\n state: \"authenticated\",\n source: \"opencode auth list\",\n provider: null,\n availableProviders: [\"GitLab Duo\", \"OpenAI\", \"litellm\"],\n status: \"pass\",\n });\n });\n\n it(\"checks Copilot auth through GitHub CLI authentication\", async () => {\n const { options } = fixture({\n runCommand: vi.fn(async (command) => {\n if (command === \"gh\")\n return {\n stdout: \"github.com\\n Logged in to github.com account test-user\\n\",\n stderr: \"\",\n };\n if (command === \"pi\") return { stdout: \"npm:@ai-devkit/pi-session-tracker\\n\", stderr: \"\" };\n if (command === \"claude\") return { stdout: JSON.stringify({ loggedIn: true }), stderr: \"\" };\n if (command === \"opencode\") return { stdout: \"● litellm api\\n\", stderr: \"\" };\n throw new Error(`unexpected command ${command}`);\n }),\n });\n\n const report = await getAgentReadinessReport(\"copilot\", options);\n\n expect(report.auth).toMatchObject({\n state: \"authenticated\",\n source: \"gh auth status --hostname github.com\",\n provider: \"github\",\n availableProviders: [\"GitHub\"],\n status: \"pass\",\n });\n });\n});\n"],"names":["path","describe","expect","it","vi","AGENTS","getAgentReadinessReport","getAgentReadinessReports","builtInSkillNames","skillRoots","claude","codex","copilot","grok_cli","opencode","pi","fixture","overrides","homeDir","assetRoot","files","join","JSON","stringify","hooks","SessionStart","type","command","PreToolUse","anthropic","access","refresh","litellm","key","env","LITELLM_BASE_URL","directory","root","Object","values","skill","executablePaths","map","agent","options","readFile","target","Error","includes","runCommand","fn","stdout","stderr","loggedIn","codexAuth","reports","keys","toEqual","not","toHaveProperty","report","entries","toBe","executable","status","globalConfig","builtInSkills","toMatchObject","present","required","integration","label","installed","toBeUndefined","spacedBin","codexPath","delimiter","startsWith","serialized","auth","state","provider","availableProviders","toContain","missing","source"],"mappings":"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"}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import * as fs from "fs";
|
|
2
|
-
import * as os from "os";
|
|
3
|
-
import * as path from "path";
|
|
4
|
-
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
5
|
-
import { AGENTS } from "../../utils/agents.js";
|
|
6
|
-
describe("AGENTS", ()=>{
|
|
7
|
-
it("includes Copilot as a startable agent", ()=>{
|
|
8
|
-
expect(AGENTS.copilot.command).toBe("copilot");
|
|
9
|
-
expect(AGENTS.copilot.matches("/opt/homebrew/Caskroom/copilot-cli/1.0.60/copilot")).toBe(true);
|
|
10
|
-
expect(AGENTS.copilot.matches("node /repo/feature-cli-copilot-cli/script.js")).toBe(false);
|
|
11
|
-
});
|
|
12
|
-
it("includes Pi as a startable agent", ()=>{
|
|
13
|
-
expect(AGENTS.pi.command).toBe("pi");
|
|
14
|
-
expect(AGENTS.pi.matches("pi")).toBe(true);
|
|
15
|
-
expect(AGENTS.pi.matches("/usr/local/bin/pi --model x")).toBe(true);
|
|
16
|
-
expect(AGENTS.pi.matches("node /repo/feature-pi-adapter/script.js")).toBe(false);
|
|
17
|
-
});
|
|
18
|
-
it("includes Grok as a startable agent", ()=>{
|
|
19
|
-
expect(AGENTS.grok_cli.command).toBe("grok");
|
|
20
|
-
expect(AGENTS.grok_cli.matches("grok")).toBe(true);
|
|
21
|
-
expect(AGENTS.grok_cli.matches("/Users/dev/.grok/bin/grok --always-approve")).toBe(true);
|
|
22
|
-
expect(AGENTS.grok_cli.matches("node /repo/feature-grok-cli/script.js")).toBe(false);
|
|
23
|
-
});
|
|
24
|
-
it("includes Kiro as a startable agent", ()=>{
|
|
25
|
-
expect(AGENTS.kiro.command).toBe("kiro-cli");
|
|
26
|
-
expect(AGENTS.kiro.matches("kiro-cli")).toBe(true);
|
|
27
|
-
expect(AGENTS.kiro.matches("/usr/local/bin/kiro --model x")).toBe(true);
|
|
28
|
-
expect(AGENTS.kiro.matches("node /repo/feature-kiro-adapter/script.js")).toBe(false);
|
|
29
|
-
});
|
|
30
|
-
it("matches Gemini as argv[0] or as a script argument", ()=>{
|
|
31
|
-
expect(AGENTS.gemini_cli.matches("gemini --yolo")).toBe(true);
|
|
32
|
-
expect(AGENTS.gemini_cli.matches("node --no-warnings /usr/local/bin/gemini")).toBe(true);
|
|
33
|
-
expect(AGENTS.gemini_cli.matches("node /repo/gemini-tools/script.js")).toBe(false);
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
describe("AGENTS matchers with executables under paths containing spaces", ()=>{
|
|
37
|
-
let root;
|
|
38
|
-
function install(relativePath) {
|
|
39
|
-
const fullPath = path.join(root, relativePath);
|
|
40
|
-
fs.mkdirSync(path.dirname(fullPath), {
|
|
41
|
-
recursive: true
|
|
42
|
-
});
|
|
43
|
-
fs.writeFileSync(fullPath, "");
|
|
44
|
-
return fullPath;
|
|
45
|
-
}
|
|
46
|
-
beforeEach(()=>{
|
|
47
|
-
root = fs.mkdtempSync(path.join(os.tmpdir(), "agents-spaces-"));
|
|
48
|
-
});
|
|
49
|
-
afterEach(()=>{
|
|
50
|
-
fs.rmSync(root, {
|
|
51
|
-
recursive: true,
|
|
52
|
-
force: true
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
it("recognises argv[0] under a spaced directory (matchArgv0)", ()=>{
|
|
56
|
-
const codex = install("Applications/Some App.app/Contents/Resources/codex");
|
|
57
|
-
const claude = install("Users/dev/My Tools/bin/claude");
|
|
58
|
-
expect(AGENTS.codex.matches(`${codex} --sandbox workspace-write`)).toBe(true);
|
|
59
|
-
expect(AGENTS.codex.matches(codex)).toBe(true);
|
|
60
|
-
expect(AGENTS.claude.matches(`${claude} --continue`)).toBe(true);
|
|
61
|
-
expect(AGENTS.claude.matches(`${codex} exec --cd /repo`)).toBe(false);
|
|
62
|
-
});
|
|
63
|
-
it("recognises argv[0] under a spaced directory by name (matchArgv0Name)", ()=>{
|
|
64
|
-
const copilot = install("opt/Home Brew/Caskroom/copilot-cli/1.0.60/copilot");
|
|
65
|
-
expect(AGENTS.copilot.matches(`${copilot} --allow-all-tools`)).toBe(true);
|
|
66
|
-
});
|
|
67
|
-
it("does not treat arguments containing spaces as the executable", ()=>{
|
|
68
|
-
const vim = install("usr/bin/vim");
|
|
69
|
-
const codex = install("Applications/Some App.app/Contents/Resources/codex");
|
|
70
|
-
expect(AGENTS.claude.matches(`${vim} My Notes/claude`)).toBe(false);
|
|
71
|
-
expect(AGENTS.claude.matches(`${codex} exec review the Other Dir/claude`)).toBe(false);
|
|
72
|
-
expect(AGENTS.copilot.matches(`${vim} Some Dir/copilot-cli/notes.md`)).toBe(false);
|
|
73
|
-
expect(AGENTS.claude.matches("/usr/bin/vim My Notes/claude")).toBe(false);
|
|
74
|
-
});
|
|
75
|
-
it("recognises a spaced argv[0] in the any-token matchers", ()=>{
|
|
76
|
-
const pi = install("Users/dev/Node Tools/bin/pi");
|
|
77
|
-
const kiro = install("Applications/Kiro CLI.app/Contents/MacOS/kiro-cli");
|
|
78
|
-
const node = install("Applications/Dev Tools/node/bin/node");
|
|
79
|
-
expect(AGENTS.pi.matches(`${pi} --model x`)).toBe(true);
|
|
80
|
-
expect(AGENTS.kiro.matches(`${kiro} chat`)).toBe(true);
|
|
81
|
-
expect(AGENTS.gemini_cli.matches(`${node} /Users/dev/.npm/bin/gemini --yolo`)).toBe(true);
|
|
82
|
-
expect(AGENTS.pi.matches(`${node} /opt/pi-tools/script.js`)).toBe(false);
|
|
83
|
-
});
|
|
84
|
-
it("does not match words inside a spaced argv[0] directory in the any-token matchers", ()=>{
|
|
85
|
-
const node = install("opt/Dev pi gemini/bin/node");
|
|
86
|
-
expect(AGENTS.pi.matches(`${node} /repo/script.js`)).toBe(false);
|
|
87
|
-
expect(AGENTS.gemini_cli.matches(`${node} /repo/script.js`)).toBe(false);
|
|
88
|
-
expect(AGENTS.gemini_cli.matches(`${node} /repo/bin/gemini`)).toBe(true);
|
|
89
|
-
expect(AGENTS.pi.matches(`${node} --title pi`)).toBe(true);
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
//# sourceMappingURL=agents.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/__tests__/utils/agents.test.ts"],"sourcesContent":["import * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\nimport { afterEach, beforeEach, describe, expect, it } from \"vitest\";\nimport { AGENTS } from \"../../utils/agents.js\";\n\ndescribe(\"AGENTS\", () => {\n it(\"includes Copilot as a startable agent\", () => {\n expect(AGENTS.copilot.command).toBe(\"copilot\");\n expect(AGENTS.copilot.matches(\"/opt/homebrew/Caskroom/copilot-cli/1.0.60/copilot\")).toBe(true);\n expect(AGENTS.copilot.matches(\"node /repo/feature-cli-copilot-cli/script.js\")).toBe(false);\n });\n\n it(\"includes Pi as a startable agent\", () => {\n expect(AGENTS.pi.command).toBe(\"pi\");\n expect(AGENTS.pi.matches(\"pi\")).toBe(true);\n expect(AGENTS.pi.matches(\"/usr/local/bin/pi --model x\")).toBe(true);\n expect(AGENTS.pi.matches(\"node /repo/feature-pi-adapter/script.js\")).toBe(false);\n });\n\n it(\"includes Grok as a startable agent\", () => {\n expect(AGENTS.grok_cli.command).toBe(\"grok\");\n expect(AGENTS.grok_cli.matches(\"grok\")).toBe(true);\n expect(AGENTS.grok_cli.matches(\"/Users/dev/.grok/bin/grok --always-approve\")).toBe(true);\n expect(AGENTS.grok_cli.matches(\"node /repo/feature-grok-cli/script.js\")).toBe(false);\n });\n\n it(\"includes Kiro as a startable agent\", () => {\n expect(AGENTS.kiro.command).toBe(\"kiro-cli\");\n expect(AGENTS.kiro.matches(\"kiro-cli\")).toBe(true);\n expect(AGENTS.kiro.matches(\"/usr/local/bin/kiro --model x\")).toBe(true);\n expect(AGENTS.kiro.matches(\"node /repo/feature-kiro-adapter/script.js\")).toBe(false);\n });\n\n it(\"matches Gemini as argv[0] or as a script argument\", () => {\n expect(AGENTS.gemini_cli.matches(\"gemini --yolo\")).toBe(true);\n expect(AGENTS.gemini_cli.matches(\"node --no-warnings /usr/local/bin/gemini\")).toBe(true);\n expect(AGENTS.gemini_cli.matches(\"node /repo/gemini-tools/script.js\")).toBe(false);\n });\n});\n\ndescribe(\"AGENTS matchers with executables under paths containing spaces\", () => {\n let root: string;\n\n function install(relativePath: string): string {\n const fullPath = path.join(root, relativePath);\n fs.mkdirSync(path.dirname(fullPath), { recursive: true });\n fs.writeFileSync(fullPath, \"\");\n return fullPath;\n }\n\n beforeEach(() => {\n root = fs.mkdtempSync(path.join(os.tmpdir(), \"agents-spaces-\"));\n });\n\n afterEach(() => {\n fs.rmSync(root, { recursive: true, force: true });\n });\n\n it(\"recognises argv[0] under a spaced directory (matchArgv0)\", () => {\n const codex = install(\"Applications/Some App.app/Contents/Resources/codex\");\n const claude = install(\"Users/dev/My Tools/bin/claude\");\n\n expect(AGENTS.codex.matches(`${codex} --sandbox workspace-write`)).toBe(true);\n expect(AGENTS.codex.matches(codex)).toBe(true);\n expect(AGENTS.claude.matches(`${claude} --continue`)).toBe(true);\n expect(AGENTS.claude.matches(`${codex} exec --cd /repo`)).toBe(false);\n });\n\n it(\"recognises argv[0] under a spaced directory by name (matchArgv0Name)\", () => {\n const copilot = install(\"opt/Home Brew/Caskroom/copilot-cli/1.0.60/copilot\");\n\n expect(AGENTS.copilot.matches(`${copilot} --allow-all-tools`)).toBe(true);\n });\n\n it(\"does not treat arguments containing spaces as the executable\", () => {\n const vim = install(\"usr/bin/vim\");\n const codex = install(\"Applications/Some App.app/Contents/Resources/codex\");\n\n expect(AGENTS.claude.matches(`${vim} My Notes/claude`)).toBe(false);\n expect(AGENTS.claude.matches(`${codex} exec review the Other Dir/claude`)).toBe(false);\n expect(AGENTS.copilot.matches(`${vim} Some Dir/copilot-cli/notes.md`)).toBe(false);\n expect(AGENTS.claude.matches(\"/usr/bin/vim My Notes/claude\")).toBe(false);\n });\n\n it(\"recognises a spaced argv[0] in the any-token matchers\", () => {\n const pi = install(\"Users/dev/Node Tools/bin/pi\");\n const kiro = install(\"Applications/Kiro CLI.app/Contents/MacOS/kiro-cli\");\n const node = install(\"Applications/Dev Tools/node/bin/node\");\n\n expect(AGENTS.pi.matches(`${pi} --model x`)).toBe(true);\n expect(AGENTS.kiro.matches(`${kiro} chat`)).toBe(true);\n expect(AGENTS.gemini_cli.matches(`${node} /Users/dev/.npm/bin/gemini --yolo`)).toBe(true);\n expect(AGENTS.pi.matches(`${node} /opt/pi-tools/script.js`)).toBe(false);\n });\n\n it(\"does not match words inside a spaced argv[0] directory in the any-token matchers\", () => {\n const node = install(\"opt/Dev pi gemini/bin/node\");\n\n expect(AGENTS.pi.matches(`${node} /repo/script.js`)).toBe(false);\n expect(AGENTS.gemini_cli.matches(`${node} /repo/script.js`)).toBe(false);\n expect(AGENTS.gemini_cli.matches(`${node} /repo/bin/gemini`)).toBe(true);\n expect(AGENTS.pi.matches(`${node} --title pi`)).toBe(true);\n });\n});\n"],"names":["fs","os","path","afterEach","beforeEach","describe","expect","it","AGENTS","copilot","command","toBe","matches","pi","grok_cli","kiro","gemini_cli","root","install","relativePath","fullPath","join","mkdirSync","dirname","recursive","writeFileSync","mkdtempSync","tmpdir","rmSync","force","codex","claude","vim","node"],"mappings":"AAAA,YAAYA,QAAQ,KAAK;AACzB,YAAYC,QAAQ,KAAK;AACzB,YAAYC,UAAU,OAAO;AAC7B,SAASC,SAAS,EAAEC,UAAU,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAS;AACrE,SAASC,MAAM,QAAQ,wBAAwB;AAE/CH,SAAS,UAAU;IACjBE,GAAG,yCAAyC;QAC1CD,OAAOE,OAAOC,OAAO,CAACC,OAAO,EAAEC,IAAI,CAAC;QACpCL,OAAOE,OAAOC,OAAO,CAACG,OAAO,CAAC,sDAAsDD,IAAI,CAAC;QACzFL,OAAOE,OAAOC,OAAO,CAACG,OAAO,CAAC,iDAAiDD,IAAI,CAAC;IACtF;IAEAJ,GAAG,oCAAoC;QACrCD,OAAOE,OAAOK,EAAE,CAACH,OAAO,EAAEC,IAAI,CAAC;QAC/BL,OAAOE,OAAOK,EAAE,CAACD,OAAO,CAAC,OAAOD,IAAI,CAAC;QACrCL,OAAOE,OAAOK,EAAE,CAACD,OAAO,CAAC,gCAAgCD,IAAI,CAAC;QAC9DL,OAAOE,OAAOK,EAAE,CAACD,OAAO,CAAC,4CAA4CD,IAAI,CAAC;IAC5E;IAEAJ,GAAG,sCAAsC;QACvCD,OAAOE,OAAOM,QAAQ,CAACJ,OAAO,EAAEC,IAAI,CAAC;QACrCL,OAAOE,OAAOM,QAAQ,CAACF,OAAO,CAAC,SAASD,IAAI,CAAC;QAC7CL,OAAOE,OAAOM,QAAQ,CAACF,OAAO,CAAC,+CAA+CD,IAAI,CAAC;QACnFL,OAAOE,OAAOM,QAAQ,CAACF,OAAO,CAAC,0CAA0CD,IAAI,CAAC;IAChF;IAEAJ,GAAG,sCAAsC;QACvCD,OAAOE,OAAOO,IAAI,CAACL,OAAO,EAAEC,IAAI,CAAC;QACjCL,OAAOE,OAAOO,IAAI,CAACH,OAAO,CAAC,aAAaD,IAAI,CAAC;QAC7CL,OAAOE,OAAOO,IAAI,CAACH,OAAO,CAAC,kCAAkCD,IAAI,CAAC;QAClEL,OAAOE,OAAOO,IAAI,CAACH,OAAO,CAAC,8CAA8CD,IAAI,CAAC;IAChF;IAEAJ,GAAG,qDAAqD;QACtDD,OAAOE,OAAOQ,UAAU,CAACJ,OAAO,CAAC,kBAAkBD,IAAI,CAAC;QACxDL,OAAOE,OAAOQ,UAAU,CAACJ,OAAO,CAAC,6CAA6CD,IAAI,CAAC;QACnFL,OAAOE,OAAOQ,UAAU,CAACJ,OAAO,CAAC,sCAAsCD,IAAI,CAAC;IAC9E;AACF;AAEAN,SAAS,kEAAkE;IACzE,IAAIY;IAEJ,SAASC,QAAQC,YAAoB;QACnC,MAAMC,WAAWlB,KAAKmB,IAAI,CAACJ,MAAME;QACjCnB,GAAGsB,SAAS,CAACpB,KAAKqB,OAAO,CAACH,WAAW;YAAEI,WAAW;QAAK;QACvDxB,GAAGyB,aAAa,CAACL,UAAU;QAC3B,OAAOA;IACT;IAEAhB,WAAW;QACTa,OAAOjB,GAAG0B,WAAW,CAACxB,KAAKmB,IAAI,CAACpB,GAAG0B,MAAM,IAAI;IAC/C;IAEAxB,UAAU;QACRH,GAAG4B,MAAM,CAACX,MAAM;YAAEO,WAAW;YAAMK,OAAO;QAAK;IACjD;IAEAtB,GAAG,4DAA4D;QAC7D,MAAMuB,QAAQZ,QAAQ;QACtB,MAAMa,SAASb,QAAQ;QAEvBZ,OAAOE,OAAOsB,KAAK,CAAClB,OAAO,CAAC,GAAGkB,MAAM,0BAA0B,CAAC,GAAGnB,IAAI,CAAC;QACxEL,OAAOE,OAAOsB,KAAK,CAAClB,OAAO,CAACkB,QAAQnB,IAAI,CAAC;QACzCL,OAAOE,OAAOuB,MAAM,CAACnB,OAAO,CAAC,GAAGmB,OAAO,WAAW,CAAC,GAAGpB,IAAI,CAAC;QAC3DL,OAAOE,OAAOuB,MAAM,CAACnB,OAAO,CAAC,GAAGkB,MAAM,gBAAgB,CAAC,GAAGnB,IAAI,CAAC;IACjE;IAEAJ,GAAG,wEAAwE;QACzE,MAAME,UAAUS,QAAQ;QAExBZ,OAAOE,OAAOC,OAAO,CAACG,OAAO,CAAC,GAAGH,QAAQ,kBAAkB,CAAC,GAAGE,IAAI,CAAC;IACtE;IAEAJ,GAAG,gEAAgE;QACjE,MAAMyB,MAAMd,QAAQ;QACpB,MAAMY,QAAQZ,QAAQ;QAEtBZ,OAAOE,OAAOuB,MAAM,CAACnB,OAAO,CAAC,GAAGoB,IAAI,gBAAgB,CAAC,GAAGrB,IAAI,CAAC;QAC7DL,OAAOE,OAAOuB,MAAM,CAACnB,OAAO,CAAC,GAAGkB,MAAM,iCAAiC,CAAC,GAAGnB,IAAI,CAAC;QAChFL,OAAOE,OAAOC,OAAO,CAACG,OAAO,CAAC,GAAGoB,IAAI,8BAA8B,CAAC,GAAGrB,IAAI,CAAC;QAC5EL,OAAOE,OAAOuB,MAAM,CAACnB,OAAO,CAAC,iCAAiCD,IAAI,CAAC;IACrE;IAEAJ,GAAG,yDAAyD;QAC1D,MAAMM,KAAKK,QAAQ;QACnB,MAAMH,OAAOG,QAAQ;QACrB,MAAMe,OAAOf,QAAQ;QAErBZ,OAAOE,OAAOK,EAAE,CAACD,OAAO,CAAC,GAAGC,GAAG,UAAU,CAAC,GAAGF,IAAI,CAAC;QAClDL,OAAOE,OAAOO,IAAI,CAACH,OAAO,CAAC,GAAGG,KAAK,KAAK,CAAC,GAAGJ,IAAI,CAAC;QACjDL,OAAOE,OAAOQ,UAAU,CAACJ,OAAO,CAAC,GAAGqB,KAAK,kCAAkC,CAAC,GAAGtB,IAAI,CAAC;QACpFL,OAAOE,OAAOK,EAAE,CAACD,OAAO,CAAC,GAAGqB,KAAK,wBAAwB,CAAC,GAAGtB,IAAI,CAAC;IACpE;IAEAJ,GAAG,oFAAoF;QACrF,MAAM0B,OAAOf,QAAQ;QAErBZ,OAAOE,OAAOK,EAAE,CAACD,OAAO,CAAC,GAAGqB,KAAK,gBAAgB,CAAC,GAAGtB,IAAI,CAAC;QAC1DL,OAAOE,OAAOQ,UAAU,CAACJ,OAAO,CAAC,GAAGqB,KAAK,gBAAgB,CAAC,GAAGtB,IAAI,CAAC;QAClEL,OAAOE,OAAOQ,UAAU,CAACJ,OAAO,CAAC,GAAGqB,KAAK,iBAAiB,CAAC,GAAGtB,IAAI,CAAC;QACnEL,OAAOE,OAAOK,EAAE,CAACD,OAAO,CAAC,GAAGqB,KAAK,WAAW,CAAC,GAAGtB,IAAI,CAAC;IACvD;AACF"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { CapacityReport } from "./types.js";
|
|
2
|
-
export type ClaudeCapacityOptions = {
|
|
3
|
-
env?: NodeJS.ProcessEnv;
|
|
4
|
-
readFile?: (path: string, encoding: BufferEncoding) => Promise<string>;
|
|
5
|
-
fetch?: typeof globalThis.fetch;
|
|
6
|
-
timeoutMs?: number;
|
|
7
|
-
now?: () => Date;
|
|
8
|
-
cwd?: string;
|
|
9
|
-
platform?: NodeJS.Platform;
|
|
10
|
-
keychainRead?: (service: string) => Promise<string | null>;
|
|
11
|
-
};
|
|
12
|
-
export type ClaudeProbeOptions = ClaudeCapacityOptions & {
|
|
13
|
-
checkedAt: string;
|
|
14
|
-
};
|
|
15
|
-
export declare function parseClaudeUsage(raw: unknown, checkedAt: string): CapacityReport;
|
|
16
|
-
export declare function probeClaudeCapacity(options: ClaudeProbeOptions): Promise<CapacityReport>;
|
|
17
|
-
//# sourceMappingURL=claude.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/capacity/claude.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAgB,cAAc,EAAkB,MAAM,YAAY,CAAC;AAI/E,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACvE,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC5D,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,qBAAqB,GAAG;IACvD,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAyNF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,cAAc,CAyBhF;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,cAAc,CAAC,CA8C9F"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/capacity/claude.ts"],"sourcesContent":["import { execFile } from \"node:child_process\";\nimport { readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { isAbsolute, join, resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport type { Availability, CapacityReport, CapacityWindow } from \"./types.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport type ClaudeCapacityOptions = {\n env?: NodeJS.ProcessEnv;\n readFile?: (path: string, encoding: BufferEncoding) => Promise<string>;\n fetch?: typeof globalThis.fetch;\n timeoutMs?: number;\n now?: () => Date;\n cwd?: string;\n platform?: NodeJS.Platform;\n keychainRead?: (service: string) => Promise<string | null>;\n};\n\nexport type ClaudeProbeOptions = ClaudeCapacityOptions & {\n checkedAt: string;\n};\n\nconst CLAUDE_USAGE_URL = \"https://api.anthropic.com/api/oauth/usage\";\nconst CLAUDE_KEYCHAIN_SERVICE = \"Claude Code-credentials\";\nconst SESSION_DURATION_MINUTES = 5 * 60;\nconst WEEK_DURATION_MINUTES = 7 * 24 * 60;\n\ntype Credential = { token: string | null; expired: boolean };\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction percent(value: unknown): number | null {\n return typeof value === \"number\" && Number.isFinite(value) && value >= 0 && value <= 100\n ? value\n : null;\n}\n\nfunction nonEmptyText(value: unknown): string | null {\n return typeof value === \"string\" && value.trim() ? value.trim() : null;\n}\n\nfunction credentialsPath(options: ClaudeProbeOptions): string {\n const env = options.env ?? process.env;\n const configured = nonEmptyText(env.CLAUDE_CONFIG_DIR);\n if (configured) {\n const profileRoot = isAbsolute(configured)\n ? configured\n : resolve(options.cwd ?? process.cwd(), configured);\n return join(profileRoot, \".credentials.json\");\n }\n return join(env.HOME || homedir(), \".claude\", \".credentials.json\");\n}\n\nfunction credentialFromPayload(payload: string | null, now: Date): Credential {\n if (!payload) return { token: null, expired: false };\n try {\n return credentialFromRoot(record(JSON.parse(payload)), now);\n } catch {\n return { token: null, expired: false };\n }\n}\n\nasync function readProfileCredential(options: ClaudeProbeOptions, now: Date): Promise<Credential> {\n try {\n const payload = await (options.readFile ?? readFile)(credentialsPath(options), \"utf8\");\n return credentialFromPayload(payload, now);\n } catch {\n return { token: null, expired: false };\n }\n}\n\nasync function readKeychainCredential(options: ClaudeProbeOptions, now: Date): Promise<Credential> {\n const env = options.env ?? process.env;\n const usesDefaultProfile = !nonEmptyText(env.CLAUDE_CONFIG_DIR);\n if (!usesDefaultProfile || (options.platform ?? process.platform) !== \"darwin\") {\n return { token: null, expired: false };\n }\n try {\n const payload = await (options.keychainRead ?? readClaudeKeychain)(CLAUDE_KEYCHAIN_SERVICE);\n return credentialFromPayload(payload, now);\n } catch {\n return { token: null, expired: false };\n }\n}\n\nasync function resolveToken(options: ClaudeProbeOptions): Promise<string> {\n const env = options.env ?? process.env;\n const environmentToken = nonEmptyText(env.CLAUDE_CODE_OAUTH_TOKEN);\n if (environmentToken) return environmentToken;\n\n const now = options.now?.() ?? new Date();\n const profileCredential = await readProfileCredential(options, now);\n if (profileCredential.token) return profileCredential.token;\n\n const keychainCredential = await readKeychainCredential(options, now);\n if (keychainCredential.token) return keychainCredential.token;\n if (profileCredential.expired || keychainCredential.expired) {\n throw new Error(\"Claude OAuth credentials expired\");\n }\n throw new Error(\"Claude OAuth credentials not found or malformed\");\n}\n\nfunction credentialFromRoot(root: Record<string, unknown> | null, now: Date): Credential {\n const oauth = record(root?.claudeAiOauth);\n const token = nonEmptyText(oauth?.accessToken);\n if (!token) return { token: null, expired: false };\n const expired =\n typeof oauth?.expiresAt === \"number\" &&\n Number.isFinite(oauth.expiresAt) &&\n oauth.expiresAt <= now.getTime();\n return { token: expired ? null : token, expired };\n}\n\nasync function readClaudeKeychain(service: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\n \"/usr/bin/security\",\n [\"find-generic-password\", \"-s\", service, \"-w\"],\n { encoding: \"utf8\", timeout: 1500, maxBuffer: 1024 * 1024 },\n );\n return nonEmptyText(stdout);\n } catch {\n return null;\n }\n}\n\nfunction resetTime(value: unknown): string | null {\n if (typeof value !== \"string\") return null;\n const milliseconds = Date.parse(value);\n return Number.isNaN(milliseconds) ? null : new Date(milliseconds).toISOString();\n}\n\nfunction usageWindow(\n value: unknown,\n id: string,\n label: string,\n durationMinutes: number,\n): CapacityWindow | null {\n const input = record(value);\n if (!input) return null;\n return {\n id,\n label,\n durationMinutes,\n usedPercent: percent(input.utilization),\n resetsAt: resetTime(input.resets_at),\n };\n}\n\nfunction slug(value: string): string {\n return value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n}\n\nfunction scopedWindows(value: unknown): CapacityWindow[] {\n if (!Array.isArray(value)) return [];\n const seen = new Set<string>();\n const windows: CapacityWindow[] = [];\n for (const entry of value) {\n const limit = record(entry);\n const model = record(record(limit?.scope)?.model);\n const name = nonEmptyText(model?.display_name);\n const identity = nonEmptyText(model?.id) ?? name;\n if (limit?.kind !== \"weekly_scoped\" || limit.group !== \"weekly\" || !name || !identity) {\n continue;\n }\n const modelSlug = slug(identity);\n if (!modelSlug || modelSlug === \"all-models\" || modelSlug.endsWith(\"-all-models\")) {\n continue;\n }\n const id = `claude:weekly:${modelSlug}`;\n if (seen.has(id)) continue;\n seen.add(id);\n windows.push({\n id,\n label: `${name} weekly`,\n durationMinutes: WEEK_DURATION_MINUTES,\n usedPercent: percent(limit.percent),\n resetsAt: resetTime(limit.resets_at),\n });\n }\n return windows;\n}\n\nfunction finiteNumber(value: unknown): number | null {\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\n\nfunction extraUsageWindow(value: unknown): CapacityWindow | null {\n const extra = record(value);\n if (!extra || extra.is_enabled !== true) return null;\n const limitMinor = finiteNumber(extra.monthly_limit);\n const usedMinor = finiteNumber(extra.used_credits);\n if (limitMinor === null || usedMinor === null) return null;\n const total = limitMinor / 100;\n const current = usedMinor / 100;\n const currency = nonEmptyText(extra.currency)?.toUpperCase() ?? \"USD\";\n return {\n id: \"claude:extra-usage\",\n label: `Extra usage · ${currency}`,\n limitType: \"CREDIT_LIMIT\",\n durationMinutes: null,\n usedPercent:\n percent(extra.utilization) ??\n (total > 0 ? Math.max(0, Math.min(100, (current / total) * 100)) : null),\n resetsAt: null,\n total,\n current,\n remaining: Math.max(0, total - current),\n };\n}\n\nfunction availability(windows: CapacityWindow[]): Availability {\n const known = windows.flatMap((window) =>\n window.usedPercent === null ? [] : [window.usedPercent],\n );\n if (known.length === 0) return \"unknown\";\n return known.some((used) => used < 100) ? \"yes\" : \"no\";\n}\n\nfunction retryAfterTime(response: Response, now: Date): string | null {\n const raw = response.headers.get(\"Retry-After\")?.trim();\n if (!raw) return null;\n const seconds = Number(raw);\n if (Number.isFinite(seconds) && seconds >= 0) {\n return new Date(now.getTime() + seconds * 1000).toISOString();\n }\n const milliseconds = Date.parse(raw);\n return Number.isNaN(milliseconds) ? null : new Date(milliseconds).toISOString();\n}\n\nexport function parseClaudeUsage(raw: unknown, checkedAt: string): CapacityReport {\n const input = record(raw);\n if (!input) throw new Error(\"Claude usage response is malformed\");\n const windows = [\n usageWindow(input.five_hour, \"session\", \"Session\", SESSION_DURATION_MINUTES),\n usageWindow(input.seven_day, \"weekly\", \"Weekly\", WEEK_DURATION_MINUTES),\n usageWindow(\n input.seven_day_sonnet,\n \"claude:sonnet:weekly\",\n \"Sonnet weekly\",\n WEEK_DURATION_MINUTES,\n ),\n usageWindow(input.seven_day_opus, \"claude:opus:weekly\", \"Opus weekly\", WEEK_DURATION_MINUTES),\n ...scopedWindows(input.limits),\n extraUsageWindow(input.extra_usage),\n ].filter((window): window is CapacityWindow => window !== null);\n return {\n harness: \"claude\",\n provider: \"anthropic\",\n generatedAt: checkedAt,\n authenticated: true,\n available: availability(windows),\n windows,\n creditsRemaining: null,\n };\n}\n\nexport async function probeClaudeCapacity(options: ClaudeProbeOptions): Promise<CapacityReport> {\n const token = await resolveToken(options);\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), options.timeoutMs ?? 5000);\n let response: Response;\n try {\n response = await (options.fetch ?? globalThis.fetch)(CLAUDE_USAGE_URL, {\n method: \"GET\",\n headers: {\n Accept: \"application/json\",\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"claude-code/2.1.0\",\n \"anthropic-beta\": \"oauth-2025-04-20\",\n },\n signal: controller.signal,\n });\n } catch {\n throw new Error(\"Claude OAuth usage request failed\");\n } finally {\n clearTimeout(timer);\n }\n if (response.status === 401) {\n throw new Error(\"Claude OAuth request unauthorized (HTTP 401)\");\n }\n if (response.status === 403) {\n throw new Error(\"Claude OAuth request forbidden (HTTP 403)\");\n }\n if (response.status === 429) {\n const retryAt = retryAfterTime(response, options.now?.() ?? new Date());\n throw new Error(\n retryAt\n ? `Claude OAuth usage rate limited until ${retryAt}`\n : \"Claude OAuth usage rate limited (HTTP 429)\",\n );\n }\n if (!response.ok) {\n throw new Error(`Claude OAuth usage request failed (HTTP ${response.status})`);\n }\n let raw: unknown;\n try {\n raw = await response.json();\n } catch {\n throw new Error(\"Claude usage response is malformed\");\n }\n return parseClaudeUsage(raw, options.checkedAt);\n}\n"],"names":["execFile","readFile","homedir","isAbsolute","join","resolve","promisify","execFileAsync","CLAUDE_USAGE_URL","CLAUDE_KEYCHAIN_SERVICE","SESSION_DURATION_MINUTES","WEEK_DURATION_MINUTES","record","value","Array","isArray","percent","Number","isFinite","nonEmptyText","trim","credentialsPath","options","env","process","configured","CLAUDE_CONFIG_DIR","profileRoot","cwd","HOME","credentialFromPayload","payload","now","token","expired","credentialFromRoot","JSON","parse","readProfileCredential","readKeychainCredential","usesDefaultProfile","platform","keychainRead","readClaudeKeychain","resolveToken","environmentToken","CLAUDE_CODE_OAUTH_TOKEN","Date","profileCredential","keychainCredential","Error","root","oauth","claudeAiOauth","accessToken","expiresAt","getTime","service","stdout","encoding","timeout","maxBuffer","resetTime","milliseconds","isNaN","toISOString","usageWindow","id","label","durationMinutes","input","usedPercent","utilization","resetsAt","resets_at","slug","toLowerCase","replace","scopedWindows","seen","Set","windows","entry","limit","model","scope","name","display_name","identity","kind","group","modelSlug","endsWith","has","add","push","finiteNumber","extraUsageWindow","extra","is_enabled","limitMinor","monthly_limit","usedMinor","used_credits","total","current","currency","toUpperCase","limitType","Math","max","min","remaining","availability","known","flatMap","window","length","some","used","retryAfterTime","response","raw","headers","get","seconds","parseClaudeUsage","checkedAt","five_hour","seven_day","seven_day_sonnet","seven_day_opus","limits","extra_usage","filter","harness","provider","generatedAt","authenticated","available","creditsRemaining","probeClaudeCapacity","controller","AbortController","timer","setTimeout","abort","timeoutMs","fetch","globalThis","method","Accept","Authorization","signal","clearTimeout","status","retryAt","ok","json"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/capacity/codex.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjE,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,KAAK,gBAAgB,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,CAAC;AAChD,KAAK,aAAa,GAAG;IACnB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,gBAAgB,CAAC;CAC1B,CAAC;AAEF,KAAK,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC7C,KAAK,UAAU,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,aAAa,CAAA;CAAE,CAAC;AAC1E,KAAK,YAAY,GAAG;IAAE,UAAU,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAC9D,KAAK,QAAQ,GAAG,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;AAElE,eAAO,MAAM,qBAAqB,+DAAgE,CAAC;AAEnG,KAAK,iBAAiB,GAAG;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACvE,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB,CAAC;AAgBF,wBAAgB,oBAAoB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAGjF;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,GAAG,OAAO,GAAG,aAAa,CAG/E;AAwBD,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,aAAa,CAWzD;AAuID,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAUxE;AA4CD,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,CAoD5F"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/capacity/codex.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { parseWhamUsage, resetTime, safeIdentifier } from \"./wham.js\";\nimport type { CapacityReport, CapacityWindow } from \"./types.js\";\n\nexport { toRateWindow } from \"./wham.js\";\n\ntype CodexUsageSource = \"pat\" | \"oauth\" | \"cli\";\ntype UsageSnapshot = {\n windows: CapacityWindow[];\n creditsRemaining: number | null;\n source: CodexUsageSource;\n};\n\ntype UnknownRecord = Record<string, unknown>;\ntype RpcMessage = { id?: number; method: string; params?: UnknownRecord };\ntype CliResponses = { rateLimits: unknown; account: unknown };\ntype CodexRpc = (messages: RpcMessage[]) => Promise<CliResponses>;\n\nexport const CODEX_APP_SERVER_ARGS = [\"-s\", \"read-only\", \"-a\", \"untrusted\", \"app-server\"] as const;\n\ntype CodexProbeOptions = {\n installed: boolean;\n checkedAt: string;\n readFile?: (path: string, encoding: BufferEncoding) => Promise<string>;\n fetch?: typeof globalThis.fetch;\n rpc?: CodexRpc;\n timeoutMs?: number;\n env?: NodeJS.ProcessEnv;\n now?: () => Date;\n};\n\nfunction record(value: unknown): UnknownRecord | null {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? (value as UnknownRecord)\n : null;\n}\n\nfunction finiteNumber(value: unknown): number | null {\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\n\nfunction nonEmptyText(value: unknown): string | null {\n return typeof value === \"string\" && value.length > 0 ? value : null;\n}\n\nexport function resolveCodexAuthPath(env: NodeJS.ProcessEnv = process.env): string {\n const root = env.CODEX_HOME || join(env.HOME || \"\", \".codex\");\n return join(root, \"auth.json\");\n}\n\nexport function parseUsage(raw: unknown, source: \"pat\" | \"oauth\"): UsageSnapshot {\n const { windows, creditsRemaining } = parseWhamUsage(raw);\n return { windows, creditsRemaining, source };\n}\n\nfunction cliWindow(value: unknown, id: string, label: string): CapacityWindow | null {\n const input = record(value);\n if (!input) return null;\n return {\n id,\n label,\n durationMinutes: finiteNumber(input.windowDurationMins),\n usedPercent: finiteNumber(input.usedPercent),\n resetsAt: resetTime(input.resetsAt),\n };\n}\n\nfunction cliSnapshotWindows(value: unknown, fallbackId: string): CapacityWindow[] {\n const snapshot = record(value);\n if (!snapshot) return [];\n const scope = safeIdentifier(snapshot.limitId) ?? safeIdentifier(fallbackId) ?? \"codex\";\n return [\n cliWindow(snapshot.primary, `${scope}:primary`, `${scope} primary`),\n cliWindow(snapshot.secondary, `${scope}:secondary`, `${scope} secondary`),\n ].filter((item): item is CapacityWindow => item !== null);\n}\n\nexport function parseCliUsage(raw: unknown): UsageSnapshot {\n const response = record(raw) ?? {};\n const primary = record(response.rateLimits);\n const windows = primary ? cliSnapshotWindows(primary, \"codex\") : [];\n const buckets = record(response.rateLimitsByLimitId);\n if (buckets) {\n for (const [id, snapshot] of Object.entries(buckets))\n windows.push(...cliSnapshotWindows(snapshot, id));\n }\n const unique = [...new Map(windows.map((window) => [window.id, window])).values()];\n return { windows: unique, creditsRemaining: null, source: \"cli\" };\n}\n\nfunction capacityFromSnapshot(\n snapshot: UsageSnapshot,\n context: CodexProbeOptions,\n raw?: unknown,\n): CapacityReport {\n const hasUsage = snapshot.windows.some((window) => window.usedPercent !== null);\n const rateLimits = record(record(raw)?.rateLimits);\n const reached = nonEmptyText(rateLimits?.rateLimitReachedType);\n const resetCredits =\n record(record(raw)?.rateLimitResetCredits) ?? record(record(raw)?.usageLimitResetCredits);\n return {\n harness: \"codex\",\n provider: \"openai\",\n generatedAt: context.checkedAt,\n authenticated: true,\n available: reached ? \"no\" : hasUsage ? \"yes\" : \"unknown\",\n windows: snapshot.windows,\n creditsRemaining: snapshot.creditsRemaining ?? finiteNumber(resetCredits?.availableCount),\n };\n}\n\nfunction jwtExpiry(token: string): number | null {\n const part = token.split(\".\")[1];\n if (!part) return null;\n try {\n return finiteNumber(record(JSON.parse(Buffer.from(part, \"base64url\").toString(\"utf8\")))?.exp);\n } catch {\n return null;\n }\n}\n\nfunction staleOAuth(tokens: UnknownRecord, token: string, now: Date): boolean {\n const metadata = tokens.expires_at ?? tokens.expiresAt ?? tokens.expiry;\n let expiry: number | null = finiteNumber(metadata);\n if (typeof metadata === \"string\") {\n const parsed = Date.parse(metadata);\n expiry = Number.isNaN(parsed) ? null : parsed / 1000;\n }\n expiry ??= jwtExpiry(token);\n return expiry !== null && expiry <= now.getTime() / 1000;\n}\n\nasync function fetchJson(\n fetcher: typeof globalThis.fetch,\n url: string,\n init: RequestInit,\n timeoutMs: number,\n): Promise<unknown> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const response = await fetcher(url, { ...init, signal: controller.signal });\n if (!response.ok) throw new Error(response.status === 401 ? \"unauthorized\" : \"request failed\");\n return await response.json();\n } finally {\n clearTimeout(timer);\n }\n}\n\nasync function apiSnapshot(\n token: string,\n accountId: string,\n source: \"pat\" | \"oauth\",\n options: CodexProbeOptions,\n): Promise<UsageSnapshot> {\n const fetcher = options.fetch ?? globalThis.fetch;\n const raw = await fetchJson(\n fetcher,\n \"https://chatgpt.com/backend-api/wham/usage\",\n {\n headers: {\n Authorization: `Bearer ${token}`,\n \"ChatGPT-Account-Id\": accountId,\n },\n },\n options.timeoutMs ?? 5000,\n );\n return parseUsage(raw, source);\n}\n\nfunction appServerRpc(messages: RpcMessage[], timeoutMs = 5000): Promise<CliResponses> {\n return new Promise((resolve, reject) => {\n const child = spawn(\"codex\", CODEX_APP_SERVER_ARGS, {\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n });\n const results: Partial<CliResponses> = {};\n let buffer = \"\";\n let settled = false;\n const finish = (error?: Error) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n child.kill();\n if (error) reject(error);\n else resolve(results as CliResponses);\n };\n const timer = setTimeout(() => finish(new Error(\"codex probe timed out\")), timeoutMs);\n child.once(\"error\", () => finish(new Error(\"codex app-server unavailable\")));\n child.once(\"exit\", () => {\n if (!settled) finish(new Error(\"codex app-server exited\"));\n });\n child.stdout.setEncoding(\"utf8\");\n child.stdout.on(\"data\", (chunk: string) => {\n buffer += chunk;\n for (;;) {\n const newline = buffer.indexOf(\"\\n\");\n if (newline < 0) break;\n const line = buffer.slice(0, newline).trim();\n buffer = buffer.slice(newline + 1);\n if (!line) continue;\n let message: UnknownRecord;\n try {\n message = JSON.parse(line) as UnknownRecord;\n } catch {\n continue;\n }\n if (message.id === 1) {\n for (const request of messages.slice(1))\n child.stdin.write(`${JSON.stringify(request)}\\n`);\n } else if (message.id === 2) {\n if (message.error) finish(new Error(\"codex rate-limit method failed\"));\n else results.rateLimits = message.result;\n } else if (message.id === 3) {\n if (message.error) finish(new Error(\"codex account method failed\"));\n else results.account = message.result;\n }\n if (\"rateLimits\" in results && \"account\" in results) finish();\n }\n });\n child.stdin.write(`${JSON.stringify(messages[0])}\\n`);\n });\n}\n\nexport function codexUnavailableReport(checkedAt: string): CapacityReport {\n return {\n harness: \"codex\",\n provider: \"openai\",\n generatedAt: checkedAt,\n authenticated: null,\n available: \"unknown\",\n windows: [],\n creditsRemaining: null,\n };\n}\n\nfunction unavailable(options: CodexProbeOptions): CapacityReport {\n return codexUnavailableReport(options.checkedAt);\n}\n\nasync function cliFallback(options: CodexProbeOptions): Promise<CapacityReport> {\n if (!options.installed) return unavailable(options);\n const messages: RpcMessage[] = [\n {\n id: 1,\n method: \"initialize\",\n params: {\n clientInfo: { name: \"ai-devkit\", title: null, version: \"1\" },\n capabilities: null,\n },\n },\n { method: \"initialized\" },\n { id: 2, method: \"account/rateLimits/read\" },\n { id: 3, method: \"account/read\" },\n ];\n try {\n const rpc = options.rpc ?? ((requests) => appServerRpc(requests, options.timeoutMs));\n const response = await rpc(messages);\n const result = capacityFromSnapshot(\n parseCliUsage(response.rateLimits),\n options,\n response.rateLimits,\n );\n const accountEnvelope = record(response.account);\n if (\n accountEnvelope &&\n Object.hasOwn(accountEnvelope, \"account\") &&\n !record(accountEnvelope.account)\n ) {\n result.authenticated = false;\n result.available = \"unknown\";\n }\n return result;\n } catch {\n return unavailable(options);\n }\n}\n\nexport async function probeCodexCapacity(options: CodexProbeOptions): Promise<CapacityReport> {\n let parsed: UnknownRecord | null = null;\n try {\n const contents = await (options.readFile ?? readFile)(\n resolveCodexAuthPath(options.env),\n \"utf8\",\n );\n parsed = record(JSON.parse(contents));\n } catch {\n return cliFallback(options);\n }\n\n const auth = parsed ?? {};\n const pat = nonEmptyText(auth.personal_access_token);\n if (pat) {\n try {\n const fetcher = options.fetch ?? globalThis.fetch;\n const whoami = record(\n await fetchJson(\n fetcher,\n \"https://auth.openai.com/api/accounts/v1/user-auth-credential/whoami\",\n { headers: { Authorization: `Bearer ${pat}` } },\n options.timeoutMs ?? 5000,\n ),\n );\n const accountId = nonEmptyText(whoami?.chatgpt_account_id);\n if (!accountId) throw new Error(\"account unavailable\");\n return capacityFromSnapshot(await apiSnapshot(pat, accountId, \"pat\", options), options);\n } catch {\n // Continue to a separately available OAuth credential before using the CLI.\n }\n }\n\n const tokens = record(auth.tokens);\n const accessToken = nonEmptyText(tokens?.access_token);\n const accountId = nonEmptyText(tokens?.account_id);\n if (\n tokens &&\n accessToken &&\n accountId &&\n !staleOAuth(tokens, accessToken, (options.now ?? (() => new Date()))())\n ) {\n try {\n return capacityFromSnapshot(\n await apiSnapshot(accessToken, accountId, \"oauth\", options),\n options,\n );\n } catch {\n return cliFallback(options);\n }\n }\n return cliFallback(options);\n}\n"],"names":["spawn","readFile","join","parseWhamUsage","resetTime","safeIdentifier","toRateWindow","CODEX_APP_SERVER_ARGS","record","value","Array","isArray","finiteNumber","Number","isFinite","nonEmptyText","length","resolveCodexAuthPath","env","process","root","CODEX_HOME","HOME","parseUsage","raw","source","windows","creditsRemaining","cliWindow","id","label","input","durationMinutes","windowDurationMins","usedPercent","resetsAt","cliSnapshotWindows","fallbackId","snapshot","scope","limitId","primary","secondary","filter","item","parseCliUsage","response","rateLimits","buckets","rateLimitsByLimitId","Object","entries","push","unique","Map","map","window","values","capacityFromSnapshot","context","hasUsage","some","reached","rateLimitReachedType","resetCredits","rateLimitResetCredits","usageLimitResetCredits","harness","provider","generatedAt","checkedAt","authenticated","available","availableCount","jwtExpiry","token","part","split","JSON","parse","Buffer","from","toString","exp","staleOAuth","tokens","now","metadata","expires_at","expiresAt","expiry","parsed","Date","isNaN","getTime","fetchJson","fetcher","url","init","timeoutMs","controller","AbortController","timer","setTimeout","abort","signal","ok","Error","status","json","clearTimeout","apiSnapshot","accountId","options","fetch","globalThis","headers","Authorization","appServerRpc","messages","Promise","resolve","reject","child","stdio","results","buffer","settled","finish","error","kill","once","stdout","setEncoding","on","chunk","newline","indexOf","line","slice","trim","message","request","stdin","write","stringify","result","account","codexUnavailableReport","unavailable","cliFallback","installed","method","params","clientInfo","name","title","version","capabilities","rpc","requests","accountEnvelope","hasOwn","probeCodexCapacity","contents","auth","pat","personal_access_token","whoami","chatgpt_account_id","accessToken","access_token","account_id"],"mappings":"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"}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import type { CapacityReport } from "./types.js";
|
|
2
|
-
export type OpenAiUsageBucket = {
|
|
3
|
-
startMs: number;
|
|
4
|
-
tokens: number;
|
|
5
|
-
};
|
|
6
|
-
/**
|
|
7
|
-
* Resolved OpenAI credential: a platform API key (env or Pi `openai` entry)
|
|
8
|
-
* or the OAuth login Pi stores as `openai-codex` for ChatGPT-backed access.
|
|
9
|
-
*/
|
|
10
|
-
export type OpenAiCredential = {
|
|
11
|
-
kind: "platform";
|
|
12
|
-
key: string;
|
|
13
|
-
} | {
|
|
14
|
-
kind: "oauth";
|
|
15
|
-
access: string;
|
|
16
|
-
accountId: string;
|
|
17
|
-
expiresMs: number | null;
|
|
18
|
-
};
|
|
19
|
-
export type OpenAiCredentialOptions = {
|
|
20
|
-
env?: NodeJS.ProcessEnv;
|
|
21
|
-
readFile?: (path: string, encoding: BufferEncoding) => Promise<string>;
|
|
22
|
-
};
|
|
23
|
-
export type OpenAiProbeOptions = OpenAiCredentialOptions & {
|
|
24
|
-
checkedAt: string;
|
|
25
|
-
fetch?: typeof globalThis.fetch;
|
|
26
|
-
timeoutMs?: number;
|
|
27
|
-
};
|
|
28
|
-
/**
|
|
29
|
-
* Resolves the OpenAI credential in priority order: `OPENAI_API_KEY` env,
|
|
30
|
-
* then the Pi `openai` platform-key entry, then the Pi `openai-codex` OAuth
|
|
31
|
-
* login written by `pi login` (no manual setup required).
|
|
32
|
-
*/
|
|
33
|
-
export declare function resolveOpenAiCredential(options?: OpenAiCredentialOptions): Promise<OpenAiCredential>;
|
|
34
|
-
/**
|
|
35
|
-
* Maps one OpenAI Usage API payload (day buckets of per-model token counts)
|
|
36
|
-
* into summed UTC-day buckets. Entries without a numeric
|
|
37
|
-
* aggregation_timestamp are skipped because they cannot be placed in time.
|
|
38
|
-
*/
|
|
39
|
-
export declare function parseOpenAiUsage(raw: unknown): OpenAiUsageBucket[];
|
|
40
|
-
/**
|
|
41
|
-
* Builds the capacity report from merged day buckets: trailing-7-day and
|
|
42
|
-
* current-UTC-day token usage. The platform is pay-as-you-go and exposes no
|
|
43
|
-
* queryable limit, so windows report consumption only — no faked percentages.
|
|
44
|
-
*/
|
|
45
|
-
export declare function buildOpenAiReport(buckets: OpenAiUsageBucket[], checkedAt: string): CapacityReport;
|
|
46
|
-
export declare function probeOpenAiCapacity(options: OpenAiProbeOptions): Promise<CapacityReport>;
|
|
47
|
-
//# sourceMappingURL=openai.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/capacity/openai.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,YAAY,CAAC;AAYjE,MAAM,MAAM,iBAAiB,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAGpE;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAEnF,MAAM,MAAM,uBAAuB,GAAG;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACxE,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,uBAAuB,GAAG;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AA2CF;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,gBAAgB,CAAC,CAuB3B;AAaD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,iBAAiB,EAAE,CAUlE;AAkBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,cAAc,CAmCjG;AAyDD,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,cAAc,CAAC,CAgB9F"}
|