108 lines
3.1 KiB
TypeScript
108 lines
3.1 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
buildDebugRoutesFromRoute,
|
|
buildExecutionPlanFromRoute,
|
|
buildFragmentTextById
|
|
} from "../src/services/assistantQueryPlanning";
|
|
|
|
describe("assistant query planning module", () => {
|
|
it("builds fragment text map with account hints enrichment", () => {
|
|
const map = buildFragmentTextById([
|
|
{
|
|
fragment_id: "F1",
|
|
raw_fragment_text: "проверить хвосты",
|
|
normalized_fragment_text: "",
|
|
account_hints: ["60.01", "60.02"]
|
|
},
|
|
{
|
|
fragment_id: "F2",
|
|
raw_fragment_text: "проверить 60.01 по поставщику",
|
|
normalized_fragment_text: "",
|
|
account_hints: ["60.01"]
|
|
}
|
|
]);
|
|
|
|
expect(map.get("F1")).toBe("проверить хвосты, по счету 60.01, 60.02");
|
|
expect(map.get("F2")).toBe("проверить 60.01 по поставщику");
|
|
});
|
|
|
|
it("builds deterministic execution plan from route summary", () => {
|
|
const executionPlan = buildExecutionPlanFromRoute({
|
|
routeSummary: {
|
|
mode: "deterministic_v2",
|
|
message_in_scope: true,
|
|
scope_confidence: "high",
|
|
planner: {
|
|
total_fragments: 2,
|
|
in_scope_fragments: 2,
|
|
out_of_scope_fragments: 0,
|
|
discarded_fragments: 0,
|
|
contains_multiple_tasks: false
|
|
},
|
|
decisions: [
|
|
{
|
|
fragment_id: "F1",
|
|
route: "no_route",
|
|
no_route_reason: "insufficient_specificity",
|
|
clarification_reason: "missing anchor",
|
|
reason: "needs clarification"
|
|
},
|
|
{
|
|
fragment_id: "F2",
|
|
route: "hybrid_store_plus_live",
|
|
reason: "route selected"
|
|
}
|
|
],
|
|
fallback: {
|
|
type: "none",
|
|
message: null
|
|
}
|
|
} as any,
|
|
userMessage: "base question",
|
|
fragmentTextById: new Map([
|
|
["F1", "уточни период"],
|
|
["F2", "проверь по 60.01"]
|
|
]),
|
|
requirementByFragment: new Map([
|
|
["F1", ["R1"]],
|
|
["F2", ["R2"]]
|
|
])
|
|
});
|
|
|
|
expect(executionPlan).toHaveLength(2);
|
|
expect(executionPlan[0]).toMatchObject({
|
|
fragment_id: "F1",
|
|
route: "no_route",
|
|
should_execute: false,
|
|
no_route_reason: "insufficient_specificity",
|
|
clarification_reason: "missing anchor"
|
|
});
|
|
expect(executionPlan[1]).toMatchObject({
|
|
fragment_id: "F2",
|
|
route: "hybrid_store_plus_live",
|
|
should_execute: true,
|
|
no_route_reason: null
|
|
});
|
|
});
|
|
|
|
it("builds legacy debug routes via resolver", () => {
|
|
const routes = buildDebugRoutesFromRoute({
|
|
routeSummary: {
|
|
mode: "legacy_v1",
|
|
intent_class: "partner_reconciliation",
|
|
route_hint: "store_canonical",
|
|
confidence: "medium"
|
|
} as any,
|
|
resolveLegacyRouteReason: (route) => `legacy:${route}`
|
|
});
|
|
|
|
expect(routes).toHaveLength(1);
|
|
expect(routes[0]).toMatchObject({
|
|
fragment_id: "F1",
|
|
route: "store_canonical",
|
|
reason: "legacy:store_canonical",
|
|
confidence: "medium"
|
|
});
|
|
});
|
|
});
|