pi-mono/packages/coding-agent/test/model-search.test.ts
Petr Houška 8c03fef4d3 fix(tui,coding-agent): rank contiguous fuzzy matches and search session fields separately
fuzzyMatch scored only the greedy leftmost alignment, so a query could be
scattered over an earlier unrelated part of the text (opus via "openrouter",
astra via "radius radius/gpt") and the real match ranked last. It now also
scores every contiguous occurrence and keeps the best alignment.

/resume matched one concatenated id/name/messages/cwd string. Scattered
matches in megabytes of message text or in UUIDs were noise, and the
position penalty buried real hits deep in a transcript. Fields are now
matched separately: name and cwd fuzzy, id and messages exact only, with no
position penalty. Ranking is name text, then id/message/cwd text, then
scattered name/cwd matches. Lowercased message text is cached per session.

closes #11220
2026-10-22 21:39:17 +02:00

33 lines
1.5 KiB
TypeScript

import { fuzzyFilter } from "@earendil-works/pi-tui";
import { describe, expect, it } from "vitest";
import { getModelSelectorSearchText } from "../src/modes/interactive/model-search.ts";
describe("model selector search ranking", () => {
// #11220
it("ranks models containing the query above scattered matches", () => {
const models = [
{ provider: "openrouter", id: "openai/gpt-oss-120b", name: "OpenAI: gpt-oss-120b" },
{ provider: "openrouter", id: "anthropic/claude-sonnet-4.5", name: "Anthropic: Claude Sonnet 4.5" },
{ provider: "openrouter", id: "anthropic/claude-opus-4.1", name: "Anthropic: Claude Opus 4.1" },
{ provider: "anthropic", id: "claude-sonnet-4-5", name: "Claude Sonnet 4.5" },
{ provider: "anthropic", id: "claude-opus-4-1", name: "Claude Opus 4.1" },
];
const result = fuzzyFilter(models, "opus", getModelSelectorSearchText).map((m) => m.id);
expect(result.slice(0, 2).sort()).toEqual(["anthropic/claude-opus-4.1", "claude-opus-4-1"]);
});
// #10065
it("ranks the typed model above models sharing a long provider prefix", () => {
const models = [
{ provider: "fireworks", id: "accounts/fireworks/models/deepseek-v4-flash-0731" },
{ provider: "fireworks", id: "accounts/fireworks/models/kimi-k3" },
{ provider: "fireworks", id: "accounts/fireworks/routers/firerouter", name: "FireRouter" },
];
const result = fuzzyFilter(models, "firerouter", getModelSelectorSearchText);
expect(result[0]?.id).toBe("accounts/fireworks/routers/firerouter");
});
});