import { assertEquals, assertRejects, assertThrows } from "jsr:@std/assert@1"; import { agentEnvironment, parseProfiles, runProfiles, sanitizedEnvironment, } from "./profiles.ts"; Deno.test("parses profiles in fallback order with model defaults", () => { assertEquals( parseProfiles(` - type: claude token: claude-token - type: codex model: gpt-custom `), [ { type: "claude", model: "claude-sonnet-5", token: "claude-token" }, { type: "codex", model: "gpt-custom" }, ], ); }); Deno.test("rejects an empty profile list", () => { assertThrows(() => parseProfiles("[]"), Error, "at least one profile"); }); Deno.test("rejects a Claude profile without its setup token", () => { assertThrows( () => parseProfiles("- type: claude"), Error, "profiles[0].token", ); }); 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 = { HOME: "/home/bot", PROFILES: "contains every secret", REVIEWER_TOKEN: "reviewer", BOT_TOKEN: "legacy", 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", }; assertEquals( agentEnvironment(base, { type: "claude", model: "claude-sonnet-5", token: "selected", }), { HOME: "/home/bot", CLAUDE_CODE_OAUTH_TOKEN: "selected" }, ); assertEquals(sanitizedEnvironment(base), { HOME: "/home/bot" }); });