feat(radar): build guided combo suggestions

This commit is contained in:
diegosouzapw
2026-08-08 20:33:48 -03:00
committed by Xiangzhe
parent 2ebab9c686
commit 86caa94baa
4 changed files with 339 additions and 0 deletions

View File

@@ -27,6 +27,8 @@ export interface MergedEntry {
provider: string;
modelId: string;
displayName: string;
/** Curated cross-provider model family used for Radar combo suggestions. */
familyId?: string | null;
monthlyTokens: number;
creditTokens: number;
freeType:
@@ -259,6 +261,9 @@ function mergeOne(
if (!overriddenKeys.has("displayName")) {
result.displayName = feed.displayName;
}
if (!overriddenKeys.has("familyId")) {
result.familyId = feed.familyId;
}
if (!overriddenKeys.has("monthlyTokens")) {
result.monthlyTokens = feedBudgetToMonthlyTokens(feed.budget);
}
@@ -293,6 +298,7 @@ function mergeOne(
// Apply local overrides (rule 1: they win)
if (overrides) {
if (overrides.displayName !== undefined) result.displayName = overrides.displayName;
if (overrides.familyId !== undefined) result.familyId = overrides.familyId;
if (overrides.monthlyTokens !== undefined) result.monthlyTokens = overrides.monthlyTokens;
if (overrides.creditTokens !== undefined) result.creditTokens = overrides.creditTokens;
if (overrides.freeType !== undefined) result.freeType = overrides.freeType;
@@ -330,6 +336,7 @@ function feedModelToMerged(
provider: feed.provider,
modelId: feed.modelId,
displayName: overrides?.displayName ?? feed.displayName,
familyId: overrides?.familyId ?? feed.familyId,
monthlyTokens: overrides?.monthlyTokens ?? feedBudgetToMonthlyTokens(feed.budget),
creditTokens: overrides?.creditTokens ?? 0,
freeType: overrides?.freeType ?? feed.freeType,

View File

@@ -0,0 +1,164 @@
import type { ComboBuilderProviderOption } from "../combos/builderOptions";
import type { MergedEntry } from "./applyFeed";
export interface RadarComboSuggestionModel {
providerId: string;
providerName: string;
modelId: string;
qualifiedModel: string;
displayName: string;
monthlyTokens: number;
}
export interface RadarComboSuggestionPayload {
name: string;
strategy: "priority";
models: Array<{
kind: "model";
providerId: string;
model: string;
weight: 0;
}>;
}
export interface RadarComboSuggestion {
familyId: string;
name: string;
alreadyExists: boolean;
models: RadarComboSuggestionModel[];
payload: RadarComboSuggestionPayload;
}
export interface BuildRadarComboSuggestionsInput {
entries: readonly MergedEntry[];
providers: readonly ComboBuilderProviderOption[];
existingComboNames: Iterable<string>;
}
function compareText(left: string, right: string): number {
if (left < right) return -1;
if (left > right) return 1;
return 0;
}
function normalizedIdentity(value: string | null | undefined): string {
return value?.trim().toLowerCase() ?? "";
}
function resolveProvider(
providerIdentity: string,
providers: readonly ComboBuilderProviderOption[]
): ComboBuilderProviderOption | null {
const identity = normalizedIdentity(providerIdentity);
if (!identity) return null;
const active = providers.filter((provider) => provider.activeConnectionCount > 0);
const selectors: Array<(provider: ComboBuilderProviderOption) => string | null | undefined> = [
(provider) => provider.providerId,
(provider) => provider.alias,
(provider) => provider.prefix,
];
for (const select of selectors) {
const matches = active.filter((provider) => normalizedIdentity(select(provider)) === identity);
if (matches.length === 1) return matches[0];
if (matches.length > 1) return null;
}
return null;
}
function stableHash(value: string): string {
let hash = 0x811c9dc5;
for (let index = 0; index < value.length; index += 1) {
hash ^= value.charCodeAt(index);
hash = Math.imul(hash, 0x01000193);
}
return (hash >>> 0).toString(16).padStart(8, "0");
}
function comboNameForFamily(familyId: string): string {
const safeFamily =
familyId
.trim()
.toLowerCase()
.replace(/[^a-z0-9._-]+/g, "-")
.replace(/^-+|-+$/g, "") || "family";
const fullName = `radar-${safeFamily}`;
if (fullName.length <= 100) return fullName;
const hash = stableHash(familyId);
const availableFamilyLength = 100 - "radar-".length - 1 - hash.length;
return `radar-${safeFamily.slice(0, availableFamilyLength)}-${hash}`;
}
function compareModels(left: RadarComboSuggestionModel, right: RadarComboSuggestionModel): number {
return (
right.monthlyTokens - left.monthlyTokens ||
compareText(left.providerId, right.providerId) ||
compareText(left.modelId, right.modelId)
);
}
/** Build pure, deterministic combo proposals from curated Radar families and live provider options. */
export function buildRadarComboSuggestions(
input: BuildRadarComboSuggestionsInput
): RadarComboSuggestion[] {
const families = new Map<string, Map<string, RadarComboSuggestionModel>>();
for (const entry of input.entries) {
const familyId = entry.familyId?.trim();
if (!familyId || entry.enabled === false) continue;
const provider = resolveProvider(entry.provider, input.providers);
if (!provider) continue;
const model = provider.models.find((candidate) => candidate.id === entry.modelId);
if (!model) continue;
const candidate: RadarComboSuggestionModel = {
providerId: provider.providerId,
providerName: provider.displayName,
modelId: entry.modelId,
qualifiedModel: model.qualifiedModel,
displayName: entry.displayName,
monthlyTokens: entry.monthlyTokens,
};
const byProvider = families.get(familyId) ?? new Map<string, RadarComboSuggestionModel>();
const current = byProvider.get(provider.providerId);
if (!current || compareModels(candidate, current) < 0) {
byProvider.set(provider.providerId, candidate);
}
families.set(familyId, byProvider);
}
const existingNames = new Set(
[...input.existingComboNames].map((name) => normalizedIdentity(name)).filter(Boolean)
);
const suggestions: RadarComboSuggestion[] = [];
for (const familyId of [...families.keys()].sort(compareText)) {
const models = [...(families.get(familyId)?.values() ?? [])].sort(compareModels);
if (models.length < 2) continue;
const name = comboNameForFamily(familyId);
suggestions.push({
familyId,
name,
alreadyExists: existingNames.has(normalizedIdentity(name)),
models,
payload: {
name,
strategy: "priority",
models: models.map((model) => ({
kind: "model",
providerId: model.providerId,
model: model.qualifiedModel,
weight: 0,
})),
},
});
}
return suggestions;
}

View File

@@ -746,6 +746,40 @@ test("FIX2 feedModelToMerged path: contextWindow/capabilities/limits/setup survi
});
});
test("F3 mergeOne path: familyId survives the feed merge over a baseline entry", () => {
const result = applyFeed({
baseline: makeBaseline(),
feed: [
makeFeedModel({
provider: "groq",
modelId: "llama-3.3-70b-versatile",
familyId: "llama-3.3-70b",
}),
],
localOverrides: new Map(),
tombstones: new Set(),
});
assert.equal(result.find((entry) => entry.provider === "groq")?.familyId, "llama-3.3-70b");
});
test("F3 feedModelToMerged path: familyId survives for a feed-only entry", () => {
const result = applyFeed({
baseline: [],
feed: [
makeFeedModel({
provider: "new-provider",
modelId: "shared-model",
familyId: "shared-family",
}),
],
localOverrides: new Map(),
tombstones: new Set(),
});
assert.equal(result[0]?.familyId, "shared-family");
});
// ===========================================================================
// Feed `enabled:false` is the safety exception to local override precedence:
// a model confirmed dead upstream must not be resurrected locally.

View File

@@ -0,0 +1,134 @@
import assert from "node:assert/strict";
import test from "node:test";
import type { ComboBuilderProviderOption } from "../../src/lib/combos/builderOptions.ts";
import type { MergedEntry } from "../../src/lib/radar/applyFeed.ts";
import { buildRadarComboSuggestions } from "../../src/lib/radar/comboSuggestions.ts";
function entry(
overrides: Partial<MergedEntry> & Pick<MergedEntry, "provider" | "modelId">
): MergedEntry {
return {
provider: overrides.provider,
modelId: overrides.modelId,
displayName: overrides.displayName ?? overrides.modelId,
monthlyTokens: overrides.monthlyTokens ?? 100,
creditTokens: 0,
freeType: "recurring-daily",
poolKey: null,
tos: "ok",
enabled: true,
origin: "radar",
familyId: "shared-family",
...overrides,
};
}
function provider(
providerId: string,
modelId: string,
overrides: Partial<ComboBuilderProviderOption> = {}
): ComboBuilderProviderOption {
return {
providerId,
providerType: providerId,
displayName: providerId.toUpperCase(),
alias: providerId,
icon: "api",
color: "#000000",
source: "system",
acceptsArbitraryModel: false,
connectionCount: 1,
activeConnectionCount: 1,
modelCount: 1,
connections: [],
models: [
{
id: modelId,
qualifiedModel: `${providerId}/${modelId}`,
name: modelId,
source: "system",
sources: ["system"],
},
],
...overrides,
};
}
test("two active providers in one family create one deterministic priority suggestion", () => {
const suggestions = buildRadarComboSuggestions({
entries: [
entry({ provider: "groq", modelId: "llama", monthlyTokens: 200 }),
entry({ provider: "cerebras", modelId: "llama", monthlyTokens: 300 }),
],
providers: [provider("groq", "llama"), provider("cerebras", "llama")],
existingComboNames: [],
});
assert.equal(suggestions.length, 1);
assert.equal(suggestions[0].familyId, "shared-family");
assert.equal(suggestions[0].name, "radar-shared-family");
assert.equal(suggestions[0].alreadyExists, false);
assert.deepEqual(suggestions[0].payload, {
name: "radar-shared-family",
strategy: "priority",
models: [
{ kind: "model", providerId: "cerebras", model: "cerebras/llama", weight: 0 },
{ kind: "model", providerId: "groq", model: "groq/llama", weight: 0 },
],
});
});
test("ineligible entries fail closed while alias and prefix match exact provider models", () => {
const suggestions = buildRadarComboSuggestions({
entries: [
entry({ provider: "gq", modelId: "llama", monthlyTokens: 500 }),
entry({ provider: "cb", modelId: "llama", monthlyTokens: 400 }),
entry({ provider: "inactive", modelId: "llama", monthlyTokens: 900 }),
entry({ provider: "disabled", modelId: "llama", enabled: false }),
entry({ provider: "missing-model", modelId: "other" }),
entry({ provider: "singleton", modelId: "solo", familyId: "solo-family" }),
],
providers: [
provider("groq", "llama", { alias: "gq" }),
provider("cerebras", "llama", { prefix: "cb" }),
provider("inactive", "llama", { activeConnectionCount: 0 }),
provider("disabled", "llama"),
provider("missing-model", "llama"),
provider("singleton", "solo"),
],
existingComboNames: new Set(["RADAR-SHARED-FAMILY"]),
});
assert.equal(suggestions.length, 1);
assert.equal(suggestions[0].alreadyExists, true);
assert.deepEqual(
suggestions[0].models.map((model) => model.providerId),
["groq", "cerebras"]
);
});
test("ambiguous provider aliases, duplicate providers, empty families and unsafe names are closed", () => {
const longFamily = `Family / ${"x".repeat(120)}`;
const suggestions = buildRadarComboSuggestions({
entries: [
entry({ provider: "ambiguous", modelId: "m", familyId: "ambiguous-family" }),
entry({ provider: "one", modelId: "m", familyId: longFamily, monthlyTokens: 200 }),
entry({ provider: "two", modelId: "m", familyId: longFamily, monthlyTokens: 100 }),
entry({ provider: "one", modelId: "m", familyId: longFamily, monthlyTokens: 50 }),
entry({ provider: "one", modelId: "blank", familyId: " " }),
],
providers: [
provider("ambiguous-a", "m", { alias: "ambiguous" }),
provider("ambiguous-b", "m", { alias: "ambiguous" }),
provider("one", "m"),
provider("two", "m"),
],
existingComboNames: [],
});
assert.equal(suggestions.length, 1);
assert.ok(suggestions[0].name.length <= 100);
assert.match(suggestions[0].name, /^[a-zA-Z0-9_/.\-\[\] ]+$/);
assert.equal(new Set(suggestions[0].models.map((model) => model.providerId)).size, 2);
});