@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,35 @@
|
|
|
1
|
+
import { execFile } from "child_process";
|
|
2
|
+
import { promisify } from "util";
|
|
3
|
+
import { escapeAppleScript } from "../../utils/applescript.js";
|
|
4
|
+
export const CARRIAGE_RETURN = "\x0d";
|
|
5
|
+
export const ESCAPE_BYTE = "\x1b";
|
|
6
|
+
const execFileAsync = promisify(execFile);
|
|
7
|
+
export function sleep(ms) {
|
|
8
|
+
return new Promise((resolve)=>setTimeout(resolve, ms));
|
|
9
|
+
}
|
|
10
|
+
export async function execFileWithInput(command, args, input) {
|
|
11
|
+
await new Promise((resolve, reject)=>{
|
|
12
|
+
const child = execFile(command, args, (error)=>{
|
|
13
|
+
if (error) reject(error);
|
|
14
|
+
else resolve();
|
|
15
|
+
});
|
|
16
|
+
if (!child.stdin) {
|
|
17
|
+
reject(new Error(`Cannot write stdin to ${command}`));
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
child.stdin.end(input);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
export function appleScriptKeyAction(key) {
|
|
24
|
+
if (key === ESCAPE_BYTE) return "key code 53";
|
|
25
|
+
return `keystroke "${escapeAppleScript(key)}"`;
|
|
26
|
+
}
|
|
27
|
+
export async function isProcessRunning(name) {
|
|
28
|
+
const { stdout } = await execFileAsync("ps", [
|
|
29
|
+
"-Axo",
|
|
30
|
+
"comm"
|
|
31
|
+
]);
|
|
32
|
+
return stdout.split("\n").map((line)=>line.trim()).some((command)=>command === name || command.endsWith(`/${name}`));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/terminal/backends/shared.ts"],"sourcesContent":["import { execFile } from \"child_process\";\nimport { promisify } from \"util\";\nimport { escapeAppleScript } from \"../../utils/applescript.js\";\n\nexport const CARRIAGE_RETURN = \"\\x0d\";\nexport const ESCAPE_BYTE = \"\\x1b\";\nconst execFileAsync = promisify(execFile);\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function execFileWithInput(\n command: string,\n args: string[],\n input: string,\n): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const child = execFile(command, args, (error) => {\n if (error) reject(error);\n else resolve();\n });\n if (!child.stdin) {\n reject(new Error(`Cannot write stdin to ${command}`));\n return;\n }\n child.stdin.end(input);\n });\n}\n\nexport function appleScriptKeyAction(key: string): string {\n if (key === ESCAPE_BYTE) return \"key code 53\";\n return `keystroke \"${escapeAppleScript(key)}\"`;\n}\n\nexport async function isProcessRunning(name: string): Promise<boolean> {\n const { stdout } = await execFileAsync(\"ps\", [\"-Axo\", \"comm\"]);\n return stdout\n .split(\"\\n\")\n .map((line) => line.trim())\n .some((command) => command === name || command.endsWith(`/${name}`));\n}\n"],"names":["execFile","promisify","escapeAppleScript","CARRIAGE_RETURN","ESCAPE_BYTE","execFileAsync","sleep","ms","Promise","resolve","setTimeout","execFileWithInput","command","args","input","reject","child","error","stdin","Error","end","appleScriptKeyAction","key","isProcessRunning","name","stdout","split","map","line","trim","some","endsWith"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,gBAAgB;AACzC,SAASC,SAAS,QAAQ,OAAO;AACjC,SAASC,iBAAiB,QAAQ,6BAA6B;AAE/D,OAAO,MAAMC,kBAAkB,OAAO;AACtC,OAAO,MAAMC,cAAc,OAAO;AAClC,MAAMC,gBAAgBJ,UAAUD;AAEhC,OAAO,SAASM,MAAMC,EAAU;IAC9B,OAAO,IAAIC,QAAQ,CAACC,UAAYC,WAAWD,SAASF;AACtD;AAEA,OAAO,eAAeI,kBACpBC,OAAe,EACfC,IAAc,EACdC,KAAa;IAEb,MAAM,IAAIN,QAAc,CAACC,SAASM;QAChC,MAAMC,QAAQhB,SAASY,SAASC,MAAM,CAACI;YACrC,IAAIA,OAAOF,OAAOE;iBACbR;QACP;QACA,IAAI,CAACO,MAAME,KAAK,EAAE;YAChBH,OAAO,IAAII,MAAM,CAAC,sBAAsB,EAAEP,SAAS;YACnD;QACF;QACAI,MAAME,KAAK,CAACE,GAAG,CAACN;IAClB;AACF;AAEA,OAAO,SAASO,qBAAqBC,GAAW;IAC9C,IAAIA,QAAQlB,aAAa,OAAO;IAChC,OAAO,CAAC,WAAW,EAAEF,kBAAkBoB,KAAK,CAAC,CAAC;AAChD;AAEA,OAAO,eAAeC,iBAAiBC,IAAY;IACjD,MAAM,EAAEC,MAAM,EAAE,GAAG,MAAMpB,cAAc,MAAM;QAAC;QAAQ;KAAO;IAC7D,OAAOoB,OACJC,KAAK,CAAC,MACNC,GAAG,CAAC,CAACC,OAASA,KAAKC,IAAI,IACvBC,IAAI,CAAC,CAAClB,UAAYA,YAAYY,QAAQZ,QAAQmB,QAAQ,CAAC,CAAC,CAAC,EAAEP,MAAM;AACtE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-app.d.ts","sourceRoot":"","sources":["../../../src/terminal/backends/terminal-app.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAyBjE,eAAO,MAAM,kBAAkB,EAAE,eA6FhC,CAAC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { execFile } from "child_process";
|
|
2
|
+
import { promisify } from "util";
|
|
3
|
+
import { escapeAppleScript } from "../../utils/applescript.js";
|
|
4
|
+
import { TerminalType } from "../types.js";
|
|
5
|
+
import { appleScriptKeyAction, isProcessRunning, sleep } from "./shared.js";
|
|
6
|
+
const execFileAsync = promisify(execFile);
|
|
7
|
+
function tabScript(tty, command) {
|
|
8
|
+
return `
|
|
9
|
+
tell application "Terminal"
|
|
10
|
+
set targetTab to missing value
|
|
11
|
+
repeat with w in windows
|
|
12
|
+
repeat with i from 1 to count of tabs of w
|
|
13
|
+
set t to tab i of w
|
|
14
|
+
if tty of t is "${escapeAppleScript(tty)}" then
|
|
15
|
+
set targetTab to t
|
|
16
|
+
exit repeat
|
|
17
|
+
end if
|
|
18
|
+
end repeat
|
|
19
|
+
if targetTab is not missing value then exit repeat
|
|
20
|
+
end repeat
|
|
21
|
+
if targetTab is missing value then return "not_found"
|
|
22
|
+
${command}
|
|
23
|
+
end tell
|
|
24
|
+
return "ok"`;
|
|
25
|
+
}
|
|
26
|
+
export const terminalAppBackend = {
|
|
27
|
+
type: TerminalType.TERMINAL_APP,
|
|
28
|
+
label: "Terminal.app",
|
|
29
|
+
async find (tty) {
|
|
30
|
+
try {
|
|
31
|
+
if (!await isProcessRunning("Terminal")) return null;
|
|
32
|
+
const script = `
|
|
33
|
+
tell application "Terminal"
|
|
34
|
+
repeat with w in windows
|
|
35
|
+
repeat with t in tabs of w
|
|
36
|
+
if tty of t is "${escapeAppleScript(tty)}" then
|
|
37
|
+
return "found"
|
|
38
|
+
end if
|
|
39
|
+
end repeat
|
|
40
|
+
end repeat
|
|
41
|
+
end tell
|
|
42
|
+
`;
|
|
43
|
+
const { stdout } = await execFileAsync("osascript", [
|
|
44
|
+
"-e",
|
|
45
|
+
script
|
|
46
|
+
]);
|
|
47
|
+
return stdout.trim() === "found" ? {
|
|
48
|
+
type: TerminalType.TERMINAL_APP,
|
|
49
|
+
identifier: tty,
|
|
50
|
+
tty
|
|
51
|
+
} : null;
|
|
52
|
+
} catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
async focus (location) {
|
|
57
|
+
const script = `
|
|
58
|
+
tell application "Terminal"
|
|
59
|
+
activate
|
|
60
|
+
repeat with w in windows
|
|
61
|
+
repeat with t in tabs of w
|
|
62
|
+
if tty of t is "${escapeAppleScript(location.tty)}" then
|
|
63
|
+
set index of w to 1
|
|
64
|
+
set selected tab of w to t
|
|
65
|
+
return "true"
|
|
66
|
+
end if
|
|
67
|
+
end repeat
|
|
68
|
+
end repeat
|
|
69
|
+
end tell
|
|
70
|
+
`;
|
|
71
|
+
const { stdout } = await execFileAsync("osascript", [
|
|
72
|
+
"-e",
|
|
73
|
+
script
|
|
74
|
+
]);
|
|
75
|
+
return stdout.trim() === "true";
|
|
76
|
+
},
|
|
77
|
+
async send (location, message) {
|
|
78
|
+
const textScript = tabScript(location.tty, `do script "${escapeAppleScript(message)}" in targetTab`);
|
|
79
|
+
const { stdout: textResult } = await execFileAsync("osascript", [
|
|
80
|
+
"-e",
|
|
81
|
+
textScript
|
|
82
|
+
]);
|
|
83
|
+
if (textResult.trim() !== "ok") {
|
|
84
|
+
throw new Error(`Terminal.app tab not found for TTY ${location.tty}`);
|
|
85
|
+
}
|
|
86
|
+
await sleep(150);
|
|
87
|
+
const enterScript = tabScript(location.tty, 'do script "" in targetTab');
|
|
88
|
+
const { stdout: enterResult } = await execFileAsync("osascript", [
|
|
89
|
+
"-e",
|
|
90
|
+
enterScript
|
|
91
|
+
]);
|
|
92
|
+
if (enterResult.trim() !== "ok") {
|
|
93
|
+
throw new Error(`Terminal.app tab disappeared before Enter could be sent for TTY ${location.tty}`);
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
async sendKey (location, key) {
|
|
97
|
+
const script = `
|
|
98
|
+
tell application "Terminal"
|
|
99
|
+
set targetTab to missing value
|
|
100
|
+
set targetWindow to missing value
|
|
101
|
+
repeat with w in windows
|
|
102
|
+
repeat with i from 1 to count of tabs of w
|
|
103
|
+
set t to tab i of w
|
|
104
|
+
if tty of t is "${escapeAppleScript(location.tty)}" then
|
|
105
|
+
set targetTab to t
|
|
106
|
+
set targetWindow to w
|
|
107
|
+
exit repeat
|
|
108
|
+
end if
|
|
109
|
+
end repeat
|
|
110
|
+
if targetTab is not missing value then exit repeat
|
|
111
|
+
end repeat
|
|
112
|
+
if targetTab is missing value then return "not_found"
|
|
113
|
+
set selected of targetTab to true
|
|
114
|
+
set frontmost of targetWindow to true
|
|
115
|
+
activate
|
|
116
|
+
end tell
|
|
117
|
+
tell application "System Events" to ${appleScriptKeyAction(key)}
|
|
118
|
+
return "ok"`;
|
|
119
|
+
const { stdout } = await execFileAsync("osascript", [
|
|
120
|
+
"-e",
|
|
121
|
+
script
|
|
122
|
+
]);
|
|
123
|
+
if (stdout.trim() !== "ok") {
|
|
124
|
+
throw new Error(`Terminal.app tab not found for TTY ${location.tty}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
//# sourceMappingURL=terminal-app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/terminal/backends/terminal-app.ts"],"sourcesContent":["import { execFile } from \"child_process\";\nimport { promisify } from \"util\";\nimport { escapeAppleScript } from \"../../utils/applescript.js\";\nimport { TerminalType, type TerminalBackend } from \"../types.js\";\nimport { appleScriptKeyAction, isProcessRunning, sleep } from \"./shared.js\";\n\nconst execFileAsync = promisify(execFile);\n\nfunction tabScript(tty: string, command: string): string {\n return `\ntell application \"Terminal\"\n set targetTab to missing value\n repeat with w in windows\n repeat with i from 1 to count of tabs of w\n set t to tab i of w\n if tty of t is \"${escapeAppleScript(tty)}\" then\n set targetTab to t\n exit repeat\n end if\n end repeat\n if targetTab is not missing value then exit repeat\n end repeat\n if targetTab is missing value then return \"not_found\"\n ${command}\nend tell\nreturn \"ok\"`;\n}\n\nexport const terminalAppBackend: TerminalBackend = {\n type: TerminalType.TERMINAL_APP,\n label: \"Terminal.app\",\n\n async find(tty) {\n try {\n if (!(await isProcessRunning(\"Terminal\"))) return null;\n const script = `\n tell application \"Terminal\"\n repeat with w in windows\n repeat with t in tabs of w\n if tty of t is \"${escapeAppleScript(tty)}\" then\n return \"found\"\n end if\n end repeat\n end repeat\n end tell\n `;\n const { stdout } = await execFileAsync(\"osascript\", [\"-e\", script]);\n return stdout.trim() === \"found\"\n ? { type: TerminalType.TERMINAL_APP, identifier: tty, tty }\n : null;\n } catch {\n return null;\n }\n },\n\n async focus(location) {\n const script = `\n tell application \"Terminal\"\n activate\n repeat with w in windows\n repeat with t in tabs of w\n if tty of t is \"${escapeAppleScript(location.tty)}\" then\n set index of w to 1\n set selected tab of w to t\n return \"true\"\n end if\n end repeat\n end repeat\n end tell\n `;\n const { stdout } = await execFileAsync(\"osascript\", [\"-e\", script]);\n return stdout.trim() === \"true\";\n },\n\n async send(location, message) {\n const textScript = tabScript(\n location.tty,\n `do script \"${escapeAppleScript(message)}\" in targetTab`,\n );\n const { stdout: textResult } = await execFileAsync(\"osascript\", [\"-e\", textScript]);\n if (textResult.trim() !== \"ok\") {\n throw new Error(`Terminal.app tab not found for TTY ${location.tty}`);\n }\n await sleep(150);\n const enterScript = tabScript(location.tty, 'do script \"\" in targetTab');\n const { stdout: enterResult } = await execFileAsync(\"osascript\", [\"-e\", enterScript]);\n if (enterResult.trim() !== \"ok\") {\n throw new Error(\n `Terminal.app tab disappeared before Enter could be sent for TTY ${location.tty}`,\n );\n }\n },\n\n async sendKey(location, key) {\n const script = `\ntell application \"Terminal\"\n set targetTab to missing value\n set targetWindow to missing value\n repeat with w in windows\n repeat with i from 1 to count of tabs of w\n set t to tab i of w\n if tty of t is \"${escapeAppleScript(location.tty)}\" then\n set targetTab to t\n set targetWindow to w\n exit repeat\n end if\n end repeat\n if targetTab is not missing value then exit repeat\n end repeat\n if targetTab is missing value then return \"not_found\"\n set selected of targetTab to true\n set frontmost of targetWindow to true\n activate\nend tell\ntell application \"System Events\" to ${appleScriptKeyAction(key)}\nreturn \"ok\"`;\n const { stdout } = await execFileAsync(\"osascript\", [\"-e\", script]);\n if (stdout.trim() !== \"ok\") {\n throw new Error(`Terminal.app tab not found for TTY ${location.tty}`);\n }\n },\n};\n"],"names":["execFile","promisify","escapeAppleScript","TerminalType","appleScriptKeyAction","isProcessRunning","sleep","execFileAsync","tabScript","tty","command","terminalAppBackend","type","TERMINAL_APP","label","find","script","stdout","trim","identifier","focus","location","send","message","textScript","textResult","Error","enterScript","enterResult","sendKey","key"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,gBAAgB;AACzC,SAASC,SAAS,QAAQ,OAAO;AACjC,SAASC,iBAAiB,QAAQ,6BAA6B;AAC/D,SAASC,YAAY,QAA8B,cAAc;AACjE,SAASC,oBAAoB,EAAEC,gBAAgB,EAAEC,KAAK,QAAQ,cAAc;AAE5E,MAAMC,gBAAgBN,UAAUD;AAEhC,SAASQ,UAAUC,GAAW,EAAEC,OAAe;IAC7C,OAAO,CAAC;;;;;;sBAMY,EAAER,kBAAkBO,KAAK;;;;;;;;EAQ7C,EAAEC,QAAQ;;WAED,CAAC;AACZ;AAEA,OAAO,MAAMC,qBAAsC;IACjDC,MAAMT,aAAaU,YAAY;IAC/BC,OAAO;IAEP,MAAMC,MAAKN,GAAG;QACZ,IAAI;YACF,IAAI,CAAE,MAAMJ,iBAAiB,aAAc,OAAO;YAClD,MAAMW,SAAS,CAAC;;;;8BAIQ,EAAEd,kBAAkBO,KAAK;;;;;;MAMjD,CAAC;YACD,MAAM,EAAEQ,MAAM,EAAE,GAAG,MAAMV,cAAc,aAAa;gBAAC;gBAAMS;aAAO;YAClE,OAAOC,OAAOC,IAAI,OAAO,UACrB;gBAAEN,MAAMT,aAAaU,YAAY;gBAAEM,YAAYV;gBAAKA;YAAI,IACxD;QACN,EAAE,OAAM;YACN,OAAO;QACT;IACF;IAEA,MAAMW,OAAMC,QAAQ;QAClB,MAAML,SAAS,CAAC;;;;;6BAKS,EAAEd,kBAAkBmB,SAASZ,GAAG,EAAE;;;;;;;;IAQ3D,CAAC;QACD,MAAM,EAAEQ,MAAM,EAAE,GAAG,MAAMV,cAAc,aAAa;YAAC;YAAMS;SAAO;QAClE,OAAOC,OAAOC,IAAI,OAAO;IAC3B;IAEA,MAAMI,MAAKD,QAAQ,EAAEE,OAAO;QAC1B,MAAMC,aAAahB,UACjBa,SAASZ,GAAG,EACZ,CAAC,WAAW,EAAEP,kBAAkBqB,SAAS,cAAc,CAAC;QAE1D,MAAM,EAAEN,QAAQQ,UAAU,EAAE,GAAG,MAAMlB,cAAc,aAAa;YAAC;YAAMiB;SAAW;QAClF,IAAIC,WAAWP,IAAI,OAAO,MAAM;YAC9B,MAAM,IAAIQ,MAAM,CAAC,mCAAmC,EAAEL,SAASZ,GAAG,EAAE;QACtE;QACA,MAAMH,MAAM;QACZ,MAAMqB,cAAcnB,UAAUa,SAASZ,GAAG,EAAE;QAC5C,MAAM,EAAEQ,QAAQW,WAAW,EAAE,GAAG,MAAMrB,cAAc,aAAa;YAAC;YAAMoB;SAAY;QACpF,IAAIC,YAAYV,IAAI,OAAO,MAAM;YAC/B,MAAM,IAAIQ,MACR,CAAC,gEAAgE,EAAEL,SAASZ,GAAG,EAAE;QAErF;IACF;IAEA,MAAMoB,SAAQR,QAAQ,EAAES,GAAG;QACzB,MAAMd,SAAS,CAAC;;;;;;;sBAOE,EAAEd,kBAAkBmB,SAASZ,GAAG,EAAE;;;;;;;;;;;;;oCAapB,EAAEL,qBAAqB0B,KAAK;WACrD,CAAC;QACR,MAAM,EAAEb,MAAM,EAAE,GAAG,MAAMV,cAAc,aAAa;YAAC;YAAMS;SAAO;QAClE,IAAIC,OAAOC,IAAI,OAAO,MAAM;YAC1B,MAAM,IAAIQ,MAAM,CAAC,mCAAmC,EAAEL,SAASZ,GAAG,EAAE;QACtE;IACF;AACF,EAAE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tmux.d.ts","sourceRoot":"","sources":["../../../src/terminal/backends/tmux.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAKjE,eAAO,MAAM,WAAW,EAAE,eAsDzB,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { execFile } from "child_process";
|
|
2
|
+
import { promisify } from "util";
|
|
3
|
+
import { TerminalType } from "../types.js";
|
|
4
|
+
import { ESCAPE_BYTE, execFileWithInput, sleep } from "./shared.js";
|
|
5
|
+
const execFileAsync = promisify(execFile);
|
|
6
|
+
export const tmuxBackend = {
|
|
7
|
+
type: TerminalType.TMUX,
|
|
8
|
+
label: "tmux",
|
|
9
|
+
async find (tty) {
|
|
10
|
+
try {
|
|
11
|
+
const { stdout } = await execFileAsync("tmux", [
|
|
12
|
+
"list-panes",
|
|
13
|
+
"-a",
|
|
14
|
+
"-F",
|
|
15
|
+
"#{pane_tty}|#{session_name}:#{window_index}.#{pane_index}"
|
|
16
|
+
]);
|
|
17
|
+
for (const line of stdout.trim().split("\n")){
|
|
18
|
+
if (!line.trim()) continue;
|
|
19
|
+
const [paneTty, identifier] = line.split("|");
|
|
20
|
+
if (paneTty === tty && identifier) {
|
|
21
|
+
return {
|
|
22
|
+
type: TerminalType.TMUX,
|
|
23
|
+
identifier,
|
|
24
|
+
tty
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
} catch {
|
|
29
|
+
// tmux might not be installed or running
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
},
|
|
33
|
+
async focus (location) {
|
|
34
|
+
await execFileAsync("tmux", [
|
|
35
|
+
"switch-client",
|
|
36
|
+
"-t",
|
|
37
|
+
location.identifier
|
|
38
|
+
]);
|
|
39
|
+
return true;
|
|
40
|
+
},
|
|
41
|
+
async send (location, message) {
|
|
42
|
+
const bufferName = `ai-devkit-send-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
43
|
+
await execFileWithInput("tmux", [
|
|
44
|
+
"load-buffer",
|
|
45
|
+
"-b",
|
|
46
|
+
bufferName,
|
|
47
|
+
"-"
|
|
48
|
+
], message);
|
|
49
|
+
await execFileAsync("tmux", [
|
|
50
|
+
"paste-buffer",
|
|
51
|
+
"-t",
|
|
52
|
+
location.identifier,
|
|
53
|
+
"-b",
|
|
54
|
+
bufferName,
|
|
55
|
+
"-p",
|
|
56
|
+
"-d"
|
|
57
|
+
]);
|
|
58
|
+
await sleep(150);
|
|
59
|
+
await execFileAsync("tmux", [
|
|
60
|
+
"send-keys",
|
|
61
|
+
"-t",
|
|
62
|
+
location.identifier,
|
|
63
|
+
"Enter"
|
|
64
|
+
]);
|
|
65
|
+
},
|
|
66
|
+
async sendKey (location, key) {
|
|
67
|
+
await execFileAsync("tmux", [
|
|
68
|
+
"send-keys",
|
|
69
|
+
"-t",
|
|
70
|
+
location.identifier,
|
|
71
|
+
key === ESCAPE_BYTE ? "Escape" : key
|
|
72
|
+
]);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
//# sourceMappingURL=tmux.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/terminal/backends/tmux.ts"],"sourcesContent":["import { execFile } from \"child_process\";\nimport { promisify } from \"util\";\nimport { TerminalType, type TerminalBackend } from \"../types.js\";\nimport { ESCAPE_BYTE, execFileWithInput, sleep } from \"./shared.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport const tmuxBackend: TerminalBackend = {\n type: TerminalType.TMUX,\n label: \"tmux\",\n\n async find(tty) {\n try {\n const { stdout } = await execFileAsync(\"tmux\", [\n \"list-panes\",\n \"-a\",\n \"-F\",\n \"#{pane_tty}|#{session_name}:#{window_index}.#{pane_index}\",\n ]);\n for (const line of stdout.trim().split(\"\\n\")) {\n if (!line.trim()) continue;\n const [paneTty, identifier] = line.split(\"|\");\n if (paneTty === tty && identifier) {\n return { type: TerminalType.TMUX, identifier, tty };\n }\n }\n } catch {\n // tmux might not be installed or running\n }\n return null;\n },\n\n async focus(location) {\n await execFileAsync(\"tmux\", [\"switch-client\", \"-t\", location.identifier]);\n return true;\n },\n\n async send(location, message) {\n const bufferName = `ai-devkit-send-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n await execFileWithInput(\"tmux\", [\"load-buffer\", \"-b\", bufferName, \"-\"], message);\n await execFileAsync(\"tmux\", [\n \"paste-buffer\",\n \"-t\",\n location.identifier,\n \"-b\",\n bufferName,\n \"-p\",\n \"-d\",\n ]);\n await sleep(150);\n await execFileAsync(\"tmux\", [\"send-keys\", \"-t\", location.identifier, \"Enter\"]);\n },\n\n async sendKey(location, key) {\n await execFileAsync(\"tmux\", [\n \"send-keys\",\n \"-t\",\n location.identifier,\n key === ESCAPE_BYTE ? \"Escape\" : key,\n ]);\n },\n};\n"],"names":["execFile","promisify","TerminalType","ESCAPE_BYTE","execFileWithInput","sleep","execFileAsync","tmuxBackend","type","TMUX","label","find","tty","stdout","line","trim","split","paneTty","identifier","focus","location","send","message","bufferName","process","pid","Date","now","Math","random","toString","slice","sendKey","key"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,gBAAgB;AACzC,SAASC,SAAS,QAAQ,OAAO;AACjC,SAASC,YAAY,QAA8B,cAAc;AACjE,SAASC,WAAW,EAAEC,iBAAiB,EAAEC,KAAK,QAAQ,cAAc;AAEpE,MAAMC,gBAAgBL,UAAUD;AAEhC,OAAO,MAAMO,cAA+B;IAC1CC,MAAMN,aAAaO,IAAI;IACvBC,OAAO;IAEP,MAAMC,MAAKC,GAAG;QACZ,IAAI;YACF,MAAM,EAAEC,MAAM,EAAE,GAAG,MAAMP,cAAc,QAAQ;gBAC7C;gBACA;gBACA;gBACA;aACD;YACD,KAAK,MAAMQ,QAAQD,OAAOE,IAAI,GAAGC,KAAK,CAAC,MAAO;gBAC5C,IAAI,CAACF,KAAKC,IAAI,IAAI;gBAClB,MAAM,CAACE,SAASC,WAAW,GAAGJ,KAAKE,KAAK,CAAC;gBACzC,IAAIC,YAAYL,OAAOM,YAAY;oBACjC,OAAO;wBAAEV,MAAMN,aAAaO,IAAI;wBAAES;wBAAYN;oBAAI;gBACpD;YACF;QACF,EAAE,OAAM;QACN,yCAAyC;QAC3C;QACA,OAAO;IACT;IAEA,MAAMO,OAAMC,QAAQ;QAClB,MAAMd,cAAc,QAAQ;YAAC;YAAiB;YAAMc,SAASF,UAAU;SAAC;QACxE,OAAO;IACT;IAEA,MAAMG,MAAKD,QAAQ,EAAEE,OAAO;QAC1B,MAAMC,aAAa,CAAC,eAAe,EAAEC,QAAQC,GAAG,CAAC,CAAC,EAAEC,KAAKC,GAAG,GAAG,CAAC,EAAEC,KAAKC,MAAM,GAAGC,QAAQ,CAAC,IAAIC,KAAK,CAAC,IAAI;QACvG,MAAM3B,kBAAkB,QAAQ;YAAC;YAAe;YAAMmB;YAAY;SAAI,EAAED;QACxE,MAAMhB,cAAc,QAAQ;YAC1B;YACA;YACAc,SAASF,UAAU;YACnB;YACAK;YACA;YACA;SACD;QACD,MAAMlB,MAAM;QACZ,MAAMC,cAAc,QAAQ;YAAC;YAAa;YAAMc,SAASF,UAAU;YAAE;SAAQ;IAC/E;IAEA,MAAMc,SAAQZ,QAAQ,EAAEa,GAAG;QACzB,MAAM3B,cAAc,QAAQ;YAC1B;YACA;YACAc,SAASF,UAAU;YACnBe,QAAQ9B,cAAc,WAAW8B;SAClC;IACH;AACF,EAAE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wezterm.d.ts","sourceRoot":"","sources":["../../../src/terminal/backends/wezterm.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAUjE,eAAO,MAAM,cAAc,EAAE,eAoD5B,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { execFile } from "child_process";
|
|
2
|
+
import { promisify } from "util";
|
|
3
|
+
import { TerminalType } from "../types.js";
|
|
4
|
+
import { CARRIAGE_RETURN, execFileWithInput, sleep } from "./shared.js";
|
|
5
|
+
const execFileAsync = promisify(execFile);
|
|
6
|
+
export const weztermBackend = {
|
|
7
|
+
type: TerminalType.WEZTERM,
|
|
8
|
+
label: "wezterm",
|
|
9
|
+
async find (tty) {
|
|
10
|
+
try {
|
|
11
|
+
const { stdout } = await execFileAsync("wezterm", [
|
|
12
|
+
"cli",
|
|
13
|
+
"list",
|
|
14
|
+
"--format",
|
|
15
|
+
"json"
|
|
16
|
+
]);
|
|
17
|
+
const panes = JSON.parse(stdout);
|
|
18
|
+
if (!Array.isArray(panes)) return null;
|
|
19
|
+
for (const pane of panes){
|
|
20
|
+
if (pane?.tty_name === tty && pane.pane_id != null) {
|
|
21
|
+
return {
|
|
22
|
+
type: TerminalType.WEZTERM,
|
|
23
|
+
identifier: String(pane.pane_id),
|
|
24
|
+
tty
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
} catch {
|
|
29
|
+
// wezterm might not be installed, running, or returning valid JSON
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
},
|
|
33
|
+
async focus (location) {
|
|
34
|
+
await execFileAsync("wezterm", [
|
|
35
|
+
"cli",
|
|
36
|
+
"activate-pane",
|
|
37
|
+
"--pane-id",
|
|
38
|
+
location.identifier
|
|
39
|
+
]);
|
|
40
|
+
return true;
|
|
41
|
+
},
|
|
42
|
+
async send (location, message) {
|
|
43
|
+
await execFileWithInput("wezterm", [
|
|
44
|
+
"cli",
|
|
45
|
+
"send-text",
|
|
46
|
+
"--pane-id",
|
|
47
|
+
location.identifier
|
|
48
|
+
], message);
|
|
49
|
+
await sleep(150);
|
|
50
|
+
await execFileAsync("wezterm", [
|
|
51
|
+
"cli",
|
|
52
|
+
"send-text",
|
|
53
|
+
"--pane-id",
|
|
54
|
+
location.identifier,
|
|
55
|
+
"--no-paste",
|
|
56
|
+
CARRIAGE_RETURN
|
|
57
|
+
]);
|
|
58
|
+
},
|
|
59
|
+
async sendKey (location, key) {
|
|
60
|
+
await execFileAsync("wezterm", [
|
|
61
|
+
"cli",
|
|
62
|
+
"send-text",
|
|
63
|
+
"--pane-id",
|
|
64
|
+
location.identifier,
|
|
65
|
+
"--no-paste",
|
|
66
|
+
key
|
|
67
|
+
]);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
//# sourceMappingURL=wezterm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/terminal/backends/wezterm.ts"],"sourcesContent":["import { execFile } from \"child_process\";\nimport { promisify } from \"util\";\nimport { TerminalType, type TerminalBackend } from \"../types.js\";\nimport { CARRIAGE_RETURN, execFileWithInput, sleep } from \"./shared.js\";\n\nconst execFileAsync = promisify(execFile);\n\ninterface WeztermPaneEntry {\n pane_id?: number;\n tty_name?: string | null;\n}\n\nexport const weztermBackend: TerminalBackend = {\n type: TerminalType.WEZTERM,\n label: \"wezterm\",\n\n async find(tty) {\n try {\n const { stdout } = await execFileAsync(\"wezterm\", [\"cli\", \"list\", \"--format\", \"json\"]);\n const panes = JSON.parse(stdout) as WeztermPaneEntry[];\n if (!Array.isArray(panes)) return null;\n for (const pane of panes) {\n if (pane?.tty_name === tty && pane.pane_id != null) {\n return { type: TerminalType.WEZTERM, identifier: String(pane.pane_id), tty };\n }\n }\n } catch {\n // wezterm might not be installed, running, or returning valid JSON\n }\n return null;\n },\n\n async focus(location) {\n await execFileAsync(\"wezterm\", [\"cli\", \"activate-pane\", \"--pane-id\", location.identifier]);\n return true;\n },\n\n async send(location, message) {\n await execFileWithInput(\n \"wezterm\",\n [\"cli\", \"send-text\", \"--pane-id\", location.identifier],\n message,\n );\n await sleep(150);\n await execFileAsync(\"wezterm\", [\n \"cli\",\n \"send-text\",\n \"--pane-id\",\n location.identifier,\n \"--no-paste\",\n CARRIAGE_RETURN,\n ]);\n },\n\n async sendKey(location, key) {\n await execFileAsync(\"wezterm\", [\n \"cli\",\n \"send-text\",\n \"--pane-id\",\n location.identifier,\n \"--no-paste\",\n key,\n ]);\n },\n};\n"],"names":["execFile","promisify","TerminalType","CARRIAGE_RETURN","execFileWithInput","sleep","execFileAsync","weztermBackend","type","WEZTERM","label","find","tty","stdout","panes","JSON","parse","Array","isArray","pane","tty_name","pane_id","identifier","String","focus","location","send","message","sendKey","key"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,gBAAgB;AACzC,SAASC,SAAS,QAAQ,OAAO;AACjC,SAASC,YAAY,QAA8B,cAAc;AACjE,SAASC,eAAe,EAAEC,iBAAiB,EAAEC,KAAK,QAAQ,cAAc;AAExE,MAAMC,gBAAgBL,UAAUD;AAOhC,OAAO,MAAMO,iBAAkC;IAC7CC,MAAMN,aAAaO,OAAO;IAC1BC,OAAO;IAEP,MAAMC,MAAKC,GAAG;QACZ,IAAI;YACF,MAAM,EAAEC,MAAM,EAAE,GAAG,MAAMP,cAAc,WAAW;gBAAC;gBAAO;gBAAQ;gBAAY;aAAO;YACrF,MAAMQ,QAAQC,KAAKC,KAAK,CAACH;YACzB,IAAI,CAACI,MAAMC,OAAO,CAACJ,QAAQ,OAAO;YAClC,KAAK,MAAMK,QAAQL,MAAO;gBACxB,IAAIK,MAAMC,aAAaR,OAAOO,KAAKE,OAAO,IAAI,MAAM;oBAClD,OAAO;wBAAEb,MAAMN,aAAaO,OAAO;wBAAEa,YAAYC,OAAOJ,KAAKE,OAAO;wBAAGT;oBAAI;gBAC7E;YACF;QACF,EAAE,OAAM;QACN,mEAAmE;QACrE;QACA,OAAO;IACT;IAEA,MAAMY,OAAMC,QAAQ;QAClB,MAAMnB,cAAc,WAAW;YAAC;YAAO;YAAiB;YAAamB,SAASH,UAAU;SAAC;QACzF,OAAO;IACT;IAEA,MAAMI,MAAKD,QAAQ,EAAEE,OAAO;QAC1B,MAAMvB,kBACJ,WACA;YAAC;YAAO;YAAa;YAAaqB,SAASH,UAAU;SAAC,EACtDK;QAEF,MAAMtB,MAAM;QACZ,MAAMC,cAAc,WAAW;YAC7B;YACA;YACA;YACAmB,SAASH,UAAU;YACnB;YACAnB;SACD;IACH;IAEA,MAAMyB,SAAQH,QAAQ,EAAEI,GAAG;QACzB,MAAMvB,cAAc,WAAW;YAC7B;YACA;YACA;YACAmB,SAASH,UAAU;YACnB;YACAO;SACD;IACH;AACF,EAAE"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare enum TerminalType {
|
|
2
|
+
TMUX = "tmux",
|
|
3
|
+
WEZTERM = "wezterm",
|
|
4
|
+
ITERM2 = "iterm2",
|
|
5
|
+
TERMINAL_APP = "terminal-app",
|
|
6
|
+
UNKNOWN = "unknown"
|
|
7
|
+
}
|
|
8
|
+
export interface TerminalLocation {
|
|
9
|
+
type: TerminalType;
|
|
10
|
+
identifier: string;
|
|
11
|
+
tty: string;
|
|
12
|
+
}
|
|
13
|
+
export interface TerminalBackend {
|
|
14
|
+
readonly type: Exclude<TerminalType, TerminalType.UNKNOWN>;
|
|
15
|
+
readonly label: string;
|
|
16
|
+
find(tty: string): Promise<TerminalLocation | null>;
|
|
17
|
+
focus(location: TerminalLocation): Promise<boolean>;
|
|
18
|
+
send(location: TerminalLocation, message: string): Promise<void>;
|
|
19
|
+
sendKey(location: TerminalLocation, key: string): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/terminal/types.ts"],"names":[],"mappings":"AAAA,oBAAY,YAAY;IACtB,IAAI,SAAS;IACb,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,YAAY,iBAAiB;IAC7B,OAAO,YAAY;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,YAAY,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACpD,KAAK,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpD,IAAI,CAAC,QAAQ,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,OAAO,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjE"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export var TerminalType = /*#__PURE__*/ function(TerminalType) {
|
|
2
|
+
TerminalType["TMUX"] = "tmux";
|
|
3
|
+
TerminalType["WEZTERM"] = "wezterm";
|
|
4
|
+
TerminalType["ITERM2"] = "iterm2";
|
|
5
|
+
TerminalType["TERMINAL_APP"] = "terminal-app";
|
|
6
|
+
TerminalType["UNKNOWN"] = "unknown";
|
|
7
|
+
return TerminalType;
|
|
8
|
+
}({});
|
|
9
|
+
|
|
10
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/terminal/types.ts"],"sourcesContent":["export enum TerminalType {\n TMUX = \"tmux\",\n WEZTERM = \"wezterm\",\n ITERM2 = \"iterm2\",\n TERMINAL_APP = \"terminal-app\",\n UNKNOWN = \"unknown\",\n}\n\nexport interface TerminalLocation {\n type: TerminalType;\n identifier: string;\n tty: string;\n}\n\nexport interface TerminalBackend {\n readonly type: Exclude<TerminalType, TerminalType.UNKNOWN>;\n readonly label: string;\n find(tty: string): Promise<TerminalLocation | null>;\n focus(location: TerminalLocation): Promise<boolean>;\n send(location: TerminalLocation, message: string): Promise<void>;\n sendKey(location: TerminalLocation, key: string): Promise<void>;\n}\n"],"names":["TerminalType"],"mappings":"AAAA,OAAO,IAAA,AAAKA,sCAAAA;;;;;;WAAAA;MAMX"}
|
package/package.json
CHANGED
package/src/AgentManager.ts
CHANGED
|
@@ -47,7 +47,7 @@ export interface AgentManagerOptions {
|
|
|
47
47
|
onRuntimeDiscoveryError?: (error: unknown) => void;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
class AgentNotRunningError extends Error {
|
|
51
51
|
constructor(public agentName: string) {
|
|
52
52
|
super(`Agent "${agentName}" is no longer running.`);
|
|
53
53
|
this.name = "AgentNotRunningError";
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import * as capacity from "../../capacity/index.js";
|
|
3
|
+
import * as agentManager from "../../index.js";
|
|
4
|
+
|
|
5
|
+
const checkedAt = "2026-09-30T12:00:00.000Z";
|
|
6
|
+
const freshAuth = JSON.stringify({
|
|
7
|
+
anthropic: {
|
|
8
|
+
type: "oauth",
|
|
9
|
+
access: "fake-pi-anthropic-token",
|
|
10
|
+
refresh: "fake-pi-anthropic-refresh",
|
|
11
|
+
expires: Date.parse("2026-10-01T12:00:00.000Z"),
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
describe("Pi Anthropic capacity", () => {
|
|
16
|
+
it("exports a Pi Anthropic capacity report reader", () => {
|
|
17
|
+
expect(capacity).toHaveProperty("getAnthropicCapacityReport");
|
|
18
|
+
expect(agentManager).toHaveProperty("getAnthropicCapacityReport");
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("reads Pi's Anthropic OAuth credential and reports the Pi harness", async () => {
|
|
22
|
+
const readFile = vi.fn(async () => freshAuth);
|
|
23
|
+
const fetch = vi.fn(
|
|
24
|
+
async () =>
|
|
25
|
+
new Response(JSON.stringify({ five_hour: { utilization: 20 } }), {
|
|
26
|
+
status: 200,
|
|
27
|
+
}),
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
const report = await capacity.getAnthropicCapacityReport({
|
|
31
|
+
now: () => new Date(checkedAt),
|
|
32
|
+
env: { HOME: "/users/test" },
|
|
33
|
+
readFile,
|
|
34
|
+
fetch,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
expect(readFile).toHaveBeenCalledWith("/users/test/.pi/agent/auth.json", "utf8");
|
|
38
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
39
|
+
"https://api.anthropic.com/api/oauth/usage",
|
|
40
|
+
expect.objectContaining({
|
|
41
|
+
headers: expect.objectContaining({
|
|
42
|
+
Authorization: "Bearer fake-pi-anthropic-token",
|
|
43
|
+
}),
|
|
44
|
+
}),
|
|
45
|
+
);
|
|
46
|
+
expect(report).toMatchObject({
|
|
47
|
+
harness: "pi",
|
|
48
|
+
provider: "anthropic",
|
|
49
|
+
generatedAt: checkedAt,
|
|
50
|
+
authenticated: true,
|
|
51
|
+
available: "yes",
|
|
52
|
+
});
|
|
53
|
+
expect(JSON.stringify(report)).not.toContain("fake-pi-anthropic-token");
|
|
54
|
+
expect(JSON.stringify(report)).not.toContain("fake-pi-anthropic-refresh");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("does not fetch for an expired Pi login and returns a stale report", async () => {
|
|
58
|
+
const fetch = vi.fn();
|
|
59
|
+
const report = await capacity.getAnthropicCapacityReport({
|
|
60
|
+
now: () => new Date(checkedAt),
|
|
61
|
+
env: { HOME: "/users/test" },
|
|
62
|
+
readFile: async () =>
|
|
63
|
+
JSON.stringify({
|
|
64
|
+
anthropic: {
|
|
65
|
+
type: "oauth",
|
|
66
|
+
access: "fake-expired-token",
|
|
67
|
+
expires: 1,
|
|
68
|
+
},
|
|
69
|
+
}),
|
|
70
|
+
fetch,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
expect(fetch).not.toHaveBeenCalled();
|
|
74
|
+
expect(report).toEqual({
|
|
75
|
+
harness: "pi",
|
|
76
|
+
provider: "anthropic",
|
|
77
|
+
generatedAt: checkedAt,
|
|
78
|
+
authenticated: true,
|
|
79
|
+
available: "unknown",
|
|
80
|
+
windows: [],
|
|
81
|
+
creditsRemaining: null,
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it.each([
|
|
86
|
+
[
|
|
87
|
+
"missing file",
|
|
88
|
+
async () => Promise.reject(Object.assign(new Error("missing"), { code: "ENOENT" })),
|
|
89
|
+
],
|
|
90
|
+
["malformed file", async () => "{"],
|
|
91
|
+
["missing credential", async () => "{}"],
|
|
92
|
+
["malformed credential", async () => JSON.stringify({ anthropic: { type: "oauth" } })],
|
|
93
|
+
])("rejects a %s without fetching", async (_name, readFile) => {
|
|
94
|
+
const fetch = vi.fn();
|
|
95
|
+
await expect(
|
|
96
|
+
capacity.getAnthropicCapacityReport({
|
|
97
|
+
now: () => new Date(checkedAt),
|
|
98
|
+
env: { HOME: "/users/test" },
|
|
99
|
+
readFile,
|
|
100
|
+
fetch,
|
|
101
|
+
}),
|
|
102
|
+
).rejects.toThrow(/Pi Anthropic/);
|
|
103
|
+
expect(fetch).not.toHaveBeenCalled();
|
|
104
|
+
});
|
|
105
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { parseAnthropicCapacity } from "../../capacity/providers/anthropic.js";
|
|
3
|
+
import { resolvePiAnthropicCredential } from "../../harnesses/pi/credentials.js";
|
|
4
|
+
|
|
5
|
+
describe("capacity boundaries", () => {
|
|
6
|
+
it("keeps Pi credential extraction separate from Anthropic quota parsing", async () => {
|
|
7
|
+
const credential = await resolvePiAnthropicCredential({
|
|
8
|
+
env: { HOME: "/users/test" },
|
|
9
|
+
readFile: async () =>
|
|
10
|
+
JSON.stringify({
|
|
11
|
+
anthropic: {
|
|
12
|
+
type: "oauth",
|
|
13
|
+
access: "fake-boundary-token",
|
|
14
|
+
expires: Date.parse("2026-10-01T00:00:00.000Z"),
|
|
15
|
+
},
|
|
16
|
+
}),
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const snapshot = parseAnthropicCapacity({ five_hour: { utilization: 25 } });
|
|
20
|
+
|
|
21
|
+
expect(credential).toEqual({
|
|
22
|
+
kind: "oauth",
|
|
23
|
+
access: "fake-boundary-token",
|
|
24
|
+
expiresMs: Date.parse("2026-10-01T00:00:00.000Z"),
|
|
25
|
+
});
|
|
26
|
+
expect(snapshot).toMatchObject({
|
|
27
|
+
authenticated: true,
|
|
28
|
+
available: "yes",
|
|
29
|
+
windows: [{ id: "session", usedPercent: 25 }],
|
|
30
|
+
creditsRemaining: null,
|
|
31
|
+
});
|
|
32
|
+
expect(snapshot).not.toHaveProperty("harness");
|
|
33
|
+
expect(snapshot).not.toHaveProperty("provider");
|
|
34
|
+
expect(snapshot).not.toHaveProperty("generatedAt");
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -2,7 +2,7 @@ import { readFile } from "node:fs/promises";
|
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
3
|
import { describe, expect, it, vi } from "vitest";
|
|
4
4
|
import * as capacity from "../../capacity/index.js";
|
|
5
|
-
import {
|
|
5
|
+
import { parseAnthropicCapacity } from "../../capacity/providers/anthropic.js";
|
|
6
6
|
import * as agentManager from "../../index.js";
|
|
7
7
|
|
|
8
8
|
const fixture = (name: string) =>
|
|
@@ -226,10 +226,7 @@ describe("Claude capacity", () => {
|
|
|
226
226
|
});
|
|
227
227
|
|
|
228
228
|
it("preserves valid windows in a partial payload", async () => {
|
|
229
|
-
const report =
|
|
230
|
-
JSON.parse(await fixture("claude-usage-partial.json")),
|
|
231
|
-
"2026-09-25T18:00:00.000Z",
|
|
232
|
-
);
|
|
229
|
+
const report = parseAnthropicCapacity(JSON.parse(await fixture("claude-usage-partial.json")));
|
|
233
230
|
expect(report.available).toBe("yes");
|
|
234
231
|
expect(report.windows).toEqual([
|
|
235
232
|
{
|
|
@@ -251,9 +248,7 @@ describe("Claude capacity", () => {
|
|
|
251
248
|
|
|
252
249
|
it("rejects a non-object usage payload", async () => {
|
|
253
250
|
const raw = JSON.parse(await fixture("claude-usage-malformed.json"));
|
|
254
|
-
expect(() =>
|
|
255
|
-
"Claude usage response is malformed",
|
|
256
|
-
);
|
|
251
|
+
expect(() => parseAnthropicCapacity(raw)).toThrow("Claude usage response is malformed");
|
|
257
252
|
});
|
|
258
253
|
|
|
259
254
|
it.each([
|