Files
PubScript/packages/ai/src/discover.test.ts
T
Schwitzz 4c4b83bb68 feat(ai): add packages/ai provider layer (Chunk #8)
Self-contained SSE-based provider layer for OpenAI-compatible endpoints
(Ollama/llama.cpp/LM Studio/vLLM), Anthropic, Gemini, and OpenRouter.

- budget.ts: re-export core token-budget engine (countTokens,
  allocateBudget, DEFAULT_BUDGET)
- client.ts: streamCompletion/collectStream/complete with budget
  enforcement via enforceBudget + measureBudget
- discover.ts: auto-detect local providers by probing common /v1/models
- adapters.ts: per-provider param mapping + streaming adapters + factory
- thinking.ts: thinking/reasoning-param normalization per provider
- http.ts: SSE parsing + 429 retry
- errors.ts: BudgetExceededError

35 unit/integration tests pass; typecheck and lint clean.
2026-10-28 18:59:54 -05:00

82 lines
2.4 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { discoverLocalProviders } from "./index.js";
/** Build a mock fetch that returns a models catalog for a given URL. */
function mockFetch(
catalog: Record<string, unknown>,
): typeof fetch {
return ((url: string) => {
if (catalog[url]) {
return Promise.resolve(
new Response(JSON.stringify(catalog[url]), {
status: 200,
headers: { "content-type": "application/json" },
}),
);
}
return Promise.reject(new Error("not found"));
}) as unknown as typeof fetch;
}
describe("discoverLocalProviders", () => {
it("detects a running Ollama server", async () => {
const results = await discoverLocalProviders({
timeoutMs: 200,
fetchImpl: mockFetch({
"http://localhost:11434/v1/models": {
object: "list",
data: [
{ id: "llama3.1", owned_by: "ollama" },
{ id: "mistral", owned_by: "ollama" },
],
},
}),
});
expect(results).toHaveLength(1);
expect(results[0]!.endpoint).toBe("http://localhost:11434/v1/models");
expect(results[0]!.kind).toBe("openai-compatible");
expect(results[0]!.models.map((m) => m.id)).toEqual(["llama3.1", "mistral"]);
});
it("returns an empty array when no endpoints respond", async () => {
const results = await discoverLocalProviders({
timeoutMs: 100,
fetchImpl: mockFetch({}),
});
expect(results).toEqual([]);
});
it("ignores endpoints that return no models", async () => {
const results = await discoverLocalProviders({
timeoutMs: 200,
fetchImpl: mockFetch({
"http://localhost:1234/v1/models": { object: "list", data: [] },
}),
});
expect(results).toEqual([]);
});
it("probes multiple endpoints and collects all responders", async () => {
const results = await discoverLocalProviders({
timeoutMs: 200,
fetchImpl: mockFetch({
"http://localhost:11434/v1/models": {
object: "list",
data: [{ id: "llama3.1" }],
},
"http://localhost:1234/v1/models": {
object: "list",
data: [{ id: "qwen2.5" }],
},
}),
});
expect(results).toHaveLength(2);
const ids = results.flatMap((r) => r.models.map((m) => m.id));
expect(ids).toContain("llama3.1");
expect(ids).toContain("qwen2.5");
});
});