Files
pi_harness/packages/coding-agent/test/radius.test.ts
T
2026-07-14 11:01:21 +02:00

147 lines
4.9 KiB
TypeScript

import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { getOAuthProvider, resetOAuthProviders } from "@earendil-works/pi-ai/oauth";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { AuthStorage } from "../src/core/auth-storage.ts";
import { ModelRegistry } from "../src/core/model-registry.ts";
import { RADIUS_PROVIDER_ID } from "../src/core/radius.ts";
function radiusOAuthCredential(gatewayBaseUrl: string) {
return {
type: "oauth" as const,
access: "access-token",
refresh: "refresh-token",
expires: Date.now() + 60 * 60 * 1000,
gatewayConfig: {
baseUrl: gatewayBaseUrl,
models: [
{
id: "auto",
name: "Radius Auto",
reasoning: false,
input: ["text"],
cost: { input: 1, output: 2, cacheRead: 0.1, cacheWrite: 0.2 },
contextWindow: 128000,
maxTokens: 16384,
},
{
id: "byok/gpt-5.5",
name: "GPT-5.5 (BYOK)",
reasoning: true,
input: ["text", "image"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 256000,
maxTokens: 32000,
},
],
},
};
}
let tempDir: string;
beforeEach(() => {
tempDir = join(tmpdir(), `pi-test-radius-${Date.now()}-${Math.random().toString(36).slice(2)}`);
mkdirSync(tempDir, { recursive: true });
resetOAuthProviders();
});
afterEach(() => {
if (tempDir && existsSync(tempDir)) {
rmSync(tempDir, { recursive: true });
}
resetOAuthProviders();
});
describe("radius oauth provider", () => {
it("is registered as a built-in OAuth provider", () => {
expect(getOAuthProvider(RADIUS_PROVIDER_ID)?.name).toBe("Radius");
});
});
describe("radius models via ModelRegistry", () => {
it("injects catalog models from the stored credential", () => {
const registry = ModelRegistry.inMemory(
AuthStorage.inMemory({ radius: radiusOAuthCredential("https://radius.example.com/v1") }),
);
const auto = registry.find(RADIUS_PROVIDER_ID, "auto");
expect(auto).toBeDefined();
expect(auto?.api).toBe("pi-messages");
expect(auto?.baseUrl).toBe("https://radius.example.com/v1");
expect(auto?.name).toBe("Radius Auto");
// byok ids are registered verbatim
const byok = registry.find(RADIUS_PROVIDER_ID, "byok/gpt-5.5");
expect(byok).toBeDefined();
expect(byok?.contextWindow).toBe(256000);
expect(registry.hasConfiguredAuth(auto!)).toBe(true);
expect(registry.getProviderDisplayName(RADIUS_PROVIDER_ID)).toBe("Radius");
});
it("exposes no radius models without credentials", () => {
const registry = ModelRegistry.inMemory(AuthStorage.inMemory());
expect(registry.getAll().filter((model) => model.provider === RADIUS_PROVIDER_ID)).toHaveLength(0);
expect(getOAuthProvider(RADIUS_PROVIDER_ID)).toBeDefined();
});
it("keeps radius models across registry refresh", () => {
const registry = ModelRegistry.inMemory(
AuthStorage.inMemory({ radius: radiusOAuthCredential("https://radius.example.com/v1") }),
);
registry.refresh();
expect(registry.find(RADIUS_PROVIDER_ID, "auto")).toBeDefined();
});
});
describe("custom radius gateways via models.json", () => {
function createRegistry(providers: Record<string, unknown>, authStorage: AuthStorage): ModelRegistry {
const modelsJsonPath = join(tempDir, "models.json");
writeFileSync(modelsJsonPath, JSON.stringify({ providers }));
return ModelRegistry.create(authStorage, modelsJsonPath);
}
it("registers an independent radius-style provider", () => {
const registry = createRegistry(
{ "radius-dev": { name: "Radius (dev)", baseUrl: "http://localhost:8788", oauth: "radius" } },
AuthStorage.inMemory({ "radius-dev": radiusOAuthCredential("http://localhost:8788/v1") }),
);
expect(registry.getError()).toBeUndefined();
expect(getOAuthProvider("radius-dev")?.name).toBe("Radius (dev)");
expect(getOAuthProvider(RADIUS_PROVIDER_ID)?.name).toBe("Radius");
// Dev gateway models are injected under the custom provider id only.
const devAuto = registry.find("radius-dev", "auto");
expect(devAuto).toBeDefined();
expect(devAuto?.api).toBe("pi-messages");
expect(devAuto?.baseUrl).toBe("http://localhost:8788/v1");
expect(registry.find(RADIUS_PROVIDER_ID, "auto")).toBeUndefined();
expect(registry.getProviderDisplayName("radius-dev")).toBe("Radius (dev)");
});
it("survives registry refresh", () => {
const registry = createRegistry(
{ "radius-dev": { baseUrl: "http://localhost:8788", oauth: "radius" } },
AuthStorage.inMemory({ "radius-dev": radiusOAuthCredential("http://localhost:8788/v1") }),
);
registry.refresh();
expect(getOAuthProvider("radius-dev")).toBeDefined();
expect(registry.find("radius-dev", "auto")).toBeDefined();
});
it("requires baseUrl when oauth is set", () => {
const registry = createRegistry({ "radius-dev": { oauth: "radius" } }, AuthStorage.inMemory());
expect(registry.getError()).toContain('"baseUrl" is required when "oauth" is set');
});
});