161 lines
4.2 KiB
TypeScript
161 lines
4.2 KiB
TypeScript
import { assertEquals, assertRejects } from "jsr:@std/assert@1";
|
|
import {
|
|
agentEnvironment,
|
|
runProfiles,
|
|
sanitizedEnvironment,
|
|
} from "./profiles.ts";
|
|
|
|
Deno.test("falls through only after usage exhaustion", async () => {
|
|
const visited: string[] = [];
|
|
const result = await runProfiles(
|
|
[
|
|
{ type: "claude", model: "claude-sonnet-5", token: "first" },
|
|
{ type: "codex", model: "gpt-5.6-terra" },
|
|
],
|
|
(profile) => {
|
|
visited.push(profile.type);
|
|
if (profile.type === "claude") {
|
|
throw new Error("You've hit your usage limit");
|
|
}
|
|
return Promise.resolve("done");
|
|
},
|
|
);
|
|
|
|
assertEquals(result, "done");
|
|
assertEquals(visited, ["claude", "codex"]);
|
|
});
|
|
|
|
Deno.test("recognizes Claude's weekly limit message", async () => {
|
|
const result = await runProfiles(
|
|
[
|
|
{ type: "claude", model: "claude-sonnet-5", token: "first" },
|
|
{ type: "codex", model: "gpt-5.6-terra" },
|
|
],
|
|
(profile) => {
|
|
if (profile.type === "claude") {
|
|
throw new Error("You've hit your limit · resets Monday");
|
|
}
|
|
return Promise.resolve("fallback");
|
|
},
|
|
);
|
|
|
|
assertEquals(result, "fallback");
|
|
});
|
|
|
|
Deno.test("recognizes provider API exhaustion status", async () => {
|
|
const results = await Promise.all(
|
|
["API Error: 402 Insufficient funds", "HTTP error: 429"]
|
|
.map((message) =>
|
|
runProfiles(
|
|
[
|
|
{ type: "claude", model: "claude-sonnet-5", token: "first" },
|
|
{ type: "codex", model: "gpt-5.6-terra" },
|
|
],
|
|
(profile) => {
|
|
if (profile.type === "claude") throw new Error(message);
|
|
return Promise.resolve("fallback");
|
|
},
|
|
)
|
|
),
|
|
);
|
|
|
|
assertEquals(results, ["fallback", "fallback"]);
|
|
});
|
|
|
|
Deno.test("preserves an ordinary agent failure", async () => {
|
|
const visited: string[] = [];
|
|
await assertRejects(
|
|
() =>
|
|
runProfiles(
|
|
[
|
|
{ type: "claude", model: "claude-sonnet-5", token: "first" },
|
|
{ type: "codex", model: "gpt-5.6-terra" },
|
|
],
|
|
(profile) => {
|
|
visited.push(profile.type);
|
|
throw new Error("tests failed");
|
|
},
|
|
),
|
|
Error,
|
|
"tests failed",
|
|
);
|
|
assertEquals(visited, ["claude"]);
|
|
});
|
|
|
|
Deno.test("does not mistake incidental quota text for exhaustion", async () => {
|
|
const visited: string[] = [];
|
|
await assertRejects(
|
|
() =>
|
|
runProfiles(
|
|
[
|
|
{ type: "claude", model: "claude-sonnet-5", token: "first" },
|
|
{ type: "codex", model: "gpt-5.6-terra" },
|
|
],
|
|
(profile) => {
|
|
visited.push(profile.type);
|
|
throw new Error("quota parser test failed at line 429");
|
|
},
|
|
),
|
|
Error,
|
|
"quota parser test failed",
|
|
);
|
|
assertEquals(visited, ["claude"]);
|
|
});
|
|
|
|
Deno.test("exposes only the selected profile credential to the agent", () => {
|
|
const base = {
|
|
PATH: "/usr/bin",
|
|
HOME: "/home/bot",
|
|
UNRELATED_SECRET: "must-not-reach-agent",
|
|
BOT_AGENTS_MASTER_KEY: "master",
|
|
PROFILES: "contains every secret",
|
|
REVIEWER_TOKEN: "reviewer",
|
|
CLAUDE_CODE_OAUTH_TOKEN: "old-claude",
|
|
ANTHROPIC_API_KEY: "old-anthropic-key",
|
|
ANTHROPIC_AUTH_TOKEN: "old-anthropic-token",
|
|
OPENAI_API_KEY: "old-openai",
|
|
CODEX_API_KEY: "old-codex-key",
|
|
CODEX_ACCESS_TOKEN: "old-codex-token",
|
|
};
|
|
const profile = {
|
|
index: 0,
|
|
type: "claude" as const,
|
|
model: "claude-sonnet-5",
|
|
uid: 20_000,
|
|
gid: 20_000,
|
|
home: "/runtime/profile-0",
|
|
tokenFile: "/runtime/profile-0/token",
|
|
};
|
|
|
|
assertEquals(
|
|
agentEnvironment(base, profile, "selected"),
|
|
{
|
|
PATH: "/usr/bin",
|
|
HOME: "/runtime/profile-0",
|
|
CLAUDE_CODE_OAUTH_TOKEN: "selected",
|
|
},
|
|
);
|
|
assertEquals(sanitizedEnvironment(base), {
|
|
PATH: "/usr/bin",
|
|
HOME: "/home/bot",
|
|
});
|
|
});
|
|
|
|
Deno.test("uses a private Codex home without inventing an API credential", () => {
|
|
const profile = {
|
|
index: 1,
|
|
type: "codex" as const,
|
|
model: "gpt-5.6-terra",
|
|
uid: 20_001,
|
|
gid: 20_001,
|
|
home: "/runtime/profile-1",
|
|
tokenFile: null,
|
|
};
|
|
|
|
assertEquals(agentEnvironment({ PATH: "/bin" }, profile), {
|
|
PATH: "/bin",
|
|
HOME: "/runtime/profile-1",
|
|
CODEX_HOME: "/runtime/profile-1/.codex",
|
|
});
|
|
});
|