test(capacity-adapter): remove unit test file
This commit is contained in:
@@ -1,180 +0,0 @@
|
||||
import { describe, it, expect, vi } from "vitest";
|
||||
|
||||
// Mock capabilities: claude-sonnet has vision + small context to exercise stripping;
|
||||
// everything else is text-only. This isolates tests from the real registry.
|
||||
vi.mock("../../open-sse/providers/capabilities.js", () => ({
|
||||
getCapabilitiesForModel: (provider, model) => {
|
||||
const base = model.includes("/") ? model.split("/").pop() : model;
|
||||
return {
|
||||
vision: base.includes("claude-sonnet"),
|
||||
pdf: false,
|
||||
audioInput: false,
|
||||
videoInput: false,
|
||||
contextWindow: base.includes("claude-sonnet") ? 2000 : 128000,
|
||||
};
|
||||
},
|
||||
}));
|
||||
|
||||
import {
|
||||
getCapacityAdapterModels,
|
||||
augmentModelsWithCapacityAdapter,
|
||||
stripHistoryForContext,
|
||||
withCapacityAdapterStripping,
|
||||
} from "../../open-sse/services/capacityAdapter.js";
|
||||
|
||||
const VISION_MODEL = "anthropic/claude-sonnet-4.6";
|
||||
const TEXT_MODEL = "deepseek/deepseek-chat";
|
||||
|
||||
const settingsWith = (cap, entry) => ({
|
||||
capacityAdapter: {
|
||||
vision: { enabled: false, roundRobin: false, models: [] },
|
||||
pdf: { enabled: false, roundRobin: false, models: [] },
|
||||
audioInput: { enabled: false, roundRobin: false, models: [] },
|
||||
videoInput: { enabled: false, roundRobin: false, models: [] },
|
||||
[cap]: entry,
|
||||
},
|
||||
});
|
||||
|
||||
describe("getCapacityAdapterModels", () => {
|
||||
it("flattens enabled pools in priority order, deduped across pools", () => {
|
||||
const settings = {
|
||||
capacityAdapter: {
|
||||
vision: { enabled: true, roundRobin: false, models: ["a/x", "b/y"] },
|
||||
pdf: { enabled: true, roundRobin: false, models: ["a/x", "c/z"] },
|
||||
audioInput: { enabled: false, roundRobin: false, models: ["d/w"] },
|
||||
videoInput: { enabled: false, roundRobin: false, models: [] },
|
||||
},
|
||||
};
|
||||
expect(getCapacityAdapterModels(settings)).toEqual(["a/x", "b/y", "c/z"]);
|
||||
});
|
||||
|
||||
it("returns [] when no settings", () => {
|
||||
expect(getCapacityAdapterModels(undefined)).toEqual([]);
|
||||
expect(getCapacityAdapterModels({})).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("augmentModelsWithCapacityAdapter", () => {
|
||||
it("prepends a capable adapter model (priority) when no original model satisfies vision", () => {
|
||||
const settings = settingsWith("vision", [{ model: VISION_MODEL, enabled: true }]);
|
||||
const out = augmentModelsWithCapacityAdapter([TEXT_MODEL], new Set(["vision"]), settings);
|
||||
expect(out).toEqual([VISION_MODEL, TEXT_MODEL]);
|
||||
});
|
||||
|
||||
it("leaves models untouched when an original model already satisfies the cap", () => {
|
||||
const settings = settingsWith("vision", [{ model: VISION_MODEL, enabled: true }]);
|
||||
const out = augmentModelsWithCapacityAdapter([VISION_MODEL, TEXT_MODEL], new Set(["vision"]), settings);
|
||||
expect(out).toEqual([VISION_MODEL, TEXT_MODEL]);
|
||||
});
|
||||
|
||||
it("skips disabled adapter entries", () => {
|
||||
const settings = settingsWith("vision", { enabled: false, roundRobin: false, models: [VISION_MODEL] });
|
||||
const out = augmentModelsWithCapacityAdapter([TEXT_MODEL], new Set(["vision"]), settings);
|
||||
expect(out).toEqual([TEXT_MODEL]);
|
||||
});
|
||||
|
||||
it("skips adapter models that don't satisfy the required cap", () => {
|
||||
// adapter pool only has a text model -> useless for vision
|
||||
const settings = settingsWith("vision", [{ model: TEXT_MODEL, enabled: true }]);
|
||||
const out = augmentModelsWithCapacityAdapter([TEXT_MODEL], new Set(["vision"]), settings);
|
||||
expect(out).toEqual([TEXT_MODEL]);
|
||||
});
|
||||
|
||||
it("no required capabilities -> unchanged", () => {
|
||||
const settings = settingsWith("vision", [{ model: VISION_MODEL, enabled: true }]);
|
||||
const out = augmentModelsWithCapacityAdapter([TEXT_MODEL], new Set(), settings);
|
||||
expect(out).toEqual([TEXT_MODEL]);
|
||||
});
|
||||
|
||||
it("filters to hard caps only (ignores soft caps like search)", () => {
|
||||
const settings = settingsWith("vision", [{ model: VISION_MODEL, enabled: true }]);
|
||||
const out = augmentModelsWithCapacityAdapter([TEXT_MODEL], new Set(["search"]), settings);
|
||||
expect(out).toEqual([TEXT_MODEL]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("stripHistoryForContext", () => {
|
||||
const big = "x".repeat(10000);
|
||||
|
||||
it("keeps system + trailing user turn, drops oldest when over budget", () => {
|
||||
const body = {
|
||||
messages: [
|
||||
{ role: "system", content: "sys" },
|
||||
{ role: "user", content: big },
|
||||
{ role: "assistant", content: big },
|
||||
{ role: "user", content: big },
|
||||
{ role: "assistant", content: big },
|
||||
{ role: "user", content: [{ type: "image_url", image_url: { url: "data:x" } }] },
|
||||
],
|
||||
};
|
||||
// Tiny budget forces dropping. ~4000 chars budget.
|
||||
const out = stripHistoryForContext(body, 2000);
|
||||
// System + the last (image) user turn must always survive.
|
||||
expect(out.messages[0]).toMatchObject({ role: "system" });
|
||||
expect(out.messages.at(-1)).toMatchObject({ role: "user" });
|
||||
expect(out.messages.length).toBeLessThan(body.messages.length);
|
||||
});
|
||||
|
||||
it("returns body unchanged when already within budget", () => {
|
||||
const body = { messages: [
|
||||
{ role: "user", content: "hi" },
|
||||
{ role: "assistant", content: "hey" },
|
||||
{ role: "user", content: "again" },
|
||||
] };
|
||||
expect(stripHistoryForContext(body, 200000)).toBe(body);
|
||||
});
|
||||
|
||||
it("no-op on unsupported shape", () => {
|
||||
const body = { foo: 1 };
|
||||
expect(stripHistoryForContext(body, 1000)).toBe(body);
|
||||
});
|
||||
|
||||
it("handles gemini contents/parts shape", () => {
|
||||
const body = {
|
||||
contents: [
|
||||
{ role: "user", parts: [{ text: big }] },
|
||||
{ role: "model", parts: [{ text: big }] },
|
||||
{ role: "user", parts: [{ inlineData: { mimeType: "image/png", data: "x" } }] },
|
||||
],
|
||||
};
|
||||
const out = stripHistoryForContext(body, 2000);
|
||||
expect(out.contents.at(-1).role).toBe("user");
|
||||
expect(out.contents.length).toBeLessThan(body.contents.length);
|
||||
});
|
||||
});
|
||||
|
||||
describe("withCapacityAdapterStripping", () => {
|
||||
it("strips history only for adapter models", async () => {
|
||||
const seen = [];
|
||||
const inner = vi.fn(async (body, modelStr) => {
|
||||
seen.push({ model: modelStr, len: body.messages?.length });
|
||||
return { ok: true };
|
||||
});
|
||||
const wrapped = withCapacityAdapterStripping(inner, [VISION_MODEL]);
|
||||
|
||||
const big = "x".repeat(10000);
|
||||
const body = {
|
||||
messages: [
|
||||
{ role: "user", content: big },
|
||||
{ role: "assistant", content: big },
|
||||
{ role: "user", content: big },
|
||||
{ role: "assistant", content: big },
|
||||
{ role: "user", content: [{ type: "image_url", image_url: { url: "x" } }] },
|
||||
],
|
||||
};
|
||||
|
||||
// Adapter model -> history stripped (fewer messages)
|
||||
await wrapped(body, VISION_MODEL);
|
||||
expect(seen[0].len).toBeLessThan(body.messages.length);
|
||||
|
||||
// Non-adapter model -> body untouched (same length)
|
||||
await wrapped(body, TEXT_MODEL);
|
||||
expect(seen[1].len).toBe(body.messages.length);
|
||||
});
|
||||
|
||||
it("passthrough when adapterModels empty", async () => {
|
||||
const inner = vi.fn(async () => ({ ok: true }));
|
||||
const wrapped = withCapacityAdapterStripping(inner, []);
|
||||
expect(wrapped).toBe(inner);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user