Files
OmniRoute/tests/unit/request-timeline-lane-allocation.test.ts
Praveen K Palaniswamy 65e81158ab fix(ollama): route models by advertised capability (#11088)
Landed with the design call resolved per the owner's pick — **option 1**: the synced store is now endpoint-agnostic (persistDiscoveredModels and managedModelImport no longer drop non-chat models at write time), and chat selectability moved to read time (auto-pool expansion in autoStrategy applies filterChatSelectableModels; the models-route projection already had its chatOnly filter). Your discovery test now passes end-to-end (3/3): /api/show capabilities persist per connection and image/embedding requests route through the advertising host.

Reconciliation notes: conflicted areas merged onto the current tip (adobe discovery import, requestedModel preflight signature, resolvedProvider fast-path coexists with the synced-route override — explicit resolution wins); carried base-red drains (#10055 memoization, #11071 test variants) dropped as already-landed; the managed-model-import exclusion test was propagated to the new contract (image/video models persist; the read filter still hides them from chat pickers — pinned by a new assertion). Full battery: 205/206 focused (the one red is a confirmed periodic-timer timing flake on the loaded devbox — 20/20 isolated), autoCombo vitest 30/30, combo suites 46/46, gates + typecheck clean.

Thank you @yourspraveen — the capability probe + routing design was right; it just needed the store contract opened up. Fixes #11087.
2026-08-23 11:45:01 -03:00

77 lines
3.0 KiB
TypeScript

/**
* Unit tests for RequestTimeline's allocateLanes conversation-aware lane
* reuse (agentic conversation tracking / X-ConversationId).
*/
import test from "node:test";
import assert from "node:assert/strict";
import { allocateLanes, type TimelineLog } from "../../src/shared/components/RequestTimeline.tsx";
function log(
id: string,
timestampMs: number,
durationMs: number,
sessionTag: string | null = null
): TimelineLog {
return {
id,
timestamp: new Date(timestampMs).toISOString(),
status: 200,
model: "test-model",
provider: "test-provider",
account: null,
duration: durationMs,
tokens: { in: 0, out: 0 },
completed: true,
sessionTag,
};
}
const BASE = 1_800_000_000_000; // arbitrary fixed epoch ms
test("allocateLanes: unrelated non-overlapping bars share a lane as before (no regression)", () => {
const items = [log("a", BASE, 1000), log("b", BASE + 5000, 1000)];
const lanes = allocateLanes(items, BASE + 10_000);
assert.equal(lanes.get("a"), lanes.get("b"));
});
test("allocateLanes: same conversation id reuses the same lane within the reuse window", () => {
const items = [
log("a", BASE, 1000, "conv-1"),
// Overlapping in time with "a" would normally force a different lane —
// but sharing conv-1 within the reuse window should force it onto a's lane.
log("b", BASE + 500, 1000, "conv-1"),
];
const lanes = allocateLanes(items, BASE + 10_000, 2 * 60 * 1000);
assert.equal(lanes.get("a"), lanes.get("b"));
});
test("allocateLanes: same conversation id falls back to normal packing outside the reuse window", () => {
const reuseWindowMs = 2 * 60 * 1000;
const items = [
log("a", BASE, 1000, "conv-2"),
// Same conversation id, but arrives long after the reuse window lapsed —
// must NOT be forced onto a's lane if that lane is still busy with
// something else (falls back to the ordinary overlap-avoidance packer).
log("b", BASE + reuseWindowMs + 60_000, 1000, "conv-2"),
// Occupies a's lane again right after "a" finishes, before "b" arrives —
// forces "b" to pack elsewhere via the normal greedy logic.
log("c", BASE + 2000, 1000, null),
];
const lanes = allocateLanes(items, BASE + reuseWindowMs + 65_000, reuseWindowMs);
// "a" and "c" share a's lane (c starts after a ends); "b" arrives far later
// and long after the reuse window, so it is free to reuse that same lane
// once it's genuinely free again — the key assertion is that "b" was NOT
// force-placed via conversation reuse logic (which only applies within the
// window), i.e. this is ordinary greedy packing, not identity-based.
assert.equal(lanes.get("a"), lanes.get("c"));
assert.ok(lanes.get("b") !== undefined);
});
test("allocateLanes: different conversation ids never share a lane just for overlapping in time", () => {
const items = [log("a", BASE, 5000, "conv-x"), log("b", BASE + 1000, 5000, "conv-y")];
const lanes = allocateLanes(items, BASE + 10_000);
assert.notEqual(lanes.get("a"), lanes.get("b"));
});