release: WRNexusJS 0.8.0
Quality / quality (ubuntu-latest) (push) Failing after 21s
Quality / quality (windows-latest) (push) Canceled after 0s

This commit is contained in:
2026-08-02 23:18:51 +05:30
parent 87507edf59
commit 586a6db8ff
625 changed files with 243608 additions and 11210 deletions
+80 -1
View File
@@ -1,5 +1,11 @@
import { afterEach, expect, test } from "bun:test";
import { AIError, createAI } from "../src/index.ts";
import {
AIError,
createAI,
createAIClient,
deterministicAIProvider,
type AIProvider,
} from "../src/index.ts";
const originalFetch = globalThis.fetch;
afterEach(() => {
@@ -54,3 +60,76 @@ test("streams fragmented SSE and keeps a final event without a newline", async (
for await (const chunk of createAI({ apiKey: "secret" }).stream("Hi")) chunks.push(chunk);
expect(chunks).toEqual(["A", "B"]);
});
test("generates and validates structured output with an offline provider", async () => {
const client = createAIClient({
providers: [deterministicAIProvider({ responses: ['```json\n{"ok":true}\n```'] })],
});
const result = await client.generateObject<{ ok: boolean }>("ignored", {
validate: (value): value is { ok: boolean } =>
typeof value === "object" && value !== null && "ok" in value,
});
expect(result.value).toEqual({ ok: true });
expect(client.capabilities().deterministic?.structuredOutput).toBe(true);
});
test("retries transient failures and reports redacted metadata", async () => {
let calls = 0;
const events: unknown[] = [];
const provider: AIProvider = {
name: "retrying",
async generate() {
calls++;
if (calls === 1) throw new AIError("temporary secret-token", 503, "overloaded");
return { value: "done", provider: "retrying", usage: { totalTokens: 3, costUsd: 0.01 } };
},
};
const result = await createAIClient({
providers: [provider],
retry: { attempts: 2, baseDelayMs: 0 },
onAttempt: (event) => {
events.push(event);
},
}).generate("private prompt");
expect(result.value).toBe("done");
expect(calls).toBe(2);
expect(JSON.stringify(events)).not.toContain("private prompt");
expect(JSON.stringify(events)).not.toContain("raw");
});
test("opens a provider circuit and falls back", async () => {
let failedCalls = 0;
const failing: AIProvider = {
name: "failing",
async generate() {
failedCalls++;
throw new AIError("down", 503);
},
};
const client = createAIClient({
providers: [failing, deterministicAIProvider({ responses: ["one", "two"] })],
retry: { attempts: 1 },
circuitBreaker: { failureThreshold: 1, resetAfterMs: 60_000 },
});
expect((await client.generate("first")).value).toBe("one");
expect((await client.generate("second")).value).toBe("two");
expect(failedCalls).toBe(1);
});
test("executes validated tool calls and forwards cancellation", async () => {
const client = createAIClient({ providers: [deterministicAIProvider({ responses: ["ok"] })] });
const result = {
value: "",
provider: "deterministic",
toolCalls: [{ id: "1", name: "double", arguments: { value: 4 } }],
};
const output = await client.executeTools(result, [
{
name: "double",
validate: (value): value is { value: number } =>
typeof value === "object" && value !== null && "value" in value,
execute: ({ value }) => value * 2,
},
]);
expect(output[0]?.value).toBe(8);
});