127 lines
2.8 KiB
TypeScript
127 lines
2.8 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import {
|
|
collectExtractionBusinessIssues,
|
|
repairExtractionParams,
|
|
selectExtractionModel,
|
|
} from "../src/answer-extraction.ts";
|
|
|
|
function model(provider: string, id: string) {
|
|
return { provider, id } as never;
|
|
}
|
|
|
|
test("selectExtractionModel uses first configured model with auth", async () => {
|
|
const first = model("missing", "a");
|
|
const second = model("ok", "b");
|
|
const result = await selectExtractionModel(
|
|
{
|
|
model: model("fallback", "c"),
|
|
modelRegistry: {
|
|
find(provider: string, _id: string) {
|
|
if (provider === "missing") {
|
|
return first;
|
|
}
|
|
if (provider === "ok") {
|
|
return second;
|
|
}
|
|
},
|
|
getApiKeyAndHeaders(candidate: { provider: string }) {
|
|
if (candidate.provider === "ok") {
|
|
return Promise.resolve({ ok: true, apiKey: "key" });
|
|
}
|
|
return Promise.resolve({ ok: false, error: "no" });
|
|
},
|
|
},
|
|
} as never,
|
|
[
|
|
{ provider: "missing", id: "a" },
|
|
{ provider: "ok", id: "b" },
|
|
]
|
|
);
|
|
|
|
assert.deepEqual(result, {
|
|
model: second,
|
|
auth: { ok: true, apiKey: "key" },
|
|
usedFallback: false,
|
|
});
|
|
});
|
|
|
|
test("extraction business rules flag option spam", () => {
|
|
const issues = collectExtractionBusinessIssues({
|
|
questions: [
|
|
{
|
|
id: "q",
|
|
prompt: "Pick one",
|
|
options: [
|
|
{ value: "a", label: "A" },
|
|
{ value: "b", label: "B" },
|
|
{ value: "c", label: "C" },
|
|
{ value: "d", label: "D" },
|
|
{ value: "e", label: "E" },
|
|
],
|
|
},
|
|
],
|
|
});
|
|
|
|
assert.deepEqual(issues, ["questions[0].options has 5 items; max is 4"]);
|
|
});
|
|
|
|
test("repairExtractionParams caps options while preserving other", () => {
|
|
const repaired = repairExtractionParams({
|
|
questions: [
|
|
{
|
|
id: "q",
|
|
prompt: "Pick one",
|
|
options: [
|
|
{ value: "a", label: "A" },
|
|
{ value: "b", label: "B" },
|
|
{ value: "c", label: "C" },
|
|
{ value: "d", label: "D" },
|
|
{ value: "other", label: "Other" },
|
|
],
|
|
},
|
|
],
|
|
});
|
|
|
|
assert.deepEqual(
|
|
repaired.questions[0]?.options.map((option) => option.value),
|
|
["a", "b", "c", "other"]
|
|
);
|
|
});
|
|
|
|
test("repairExtractionParams drops generic conversational prompts", () => {
|
|
const repaired = repairExtractionParams({
|
|
questions: [
|
|
{
|
|
id: "generic",
|
|
prompt: "How can I help you today?",
|
|
options: [{ value: "help", label: "Help me" }],
|
|
},
|
|
],
|
|
});
|
|
|
|
assert.deepEqual(repaired.questions, []);
|
|
});
|
|
|
|
test("selectExtractionModel validates fallback model auth", async () => {
|
|
const fallback = model("fallback", "c");
|
|
const result = await selectExtractionModel(
|
|
{
|
|
model: fallback,
|
|
modelRegistry: {
|
|
find() {
|
|
return;
|
|
},
|
|
getApiKeyAndHeaders() {
|
|
return Promise.resolve({ ok: false, error: "no auth" });
|
|
},
|
|
},
|
|
} as never,
|
|
[]
|
|
);
|
|
|
|
assert.deepEqual(result, {
|
|
error: "No auth for fallback chat model: fallback/c.",
|
|
});
|
|
});
|