mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-11 17:52:31 +03:00
* fix(radar): preserve extended feed fields and honor local enable override
applyFeed()'s MergedEntry shape omitted contextWindow/capabilities/limits/
setup even though FeedModel always carries them, so the dashboard's setup
link, Context column, and capability badges never rendered and the setup
page's provider lookup always failed. Both merge paths (mergeOne and
feedModelToMerged) now copy the four fields through, respecting rule 1
(local override wins) same as every other field.
feedModelToMerged() also unconditionally forced enabled:false when the feed
disabled a feed-only entry, even when the operator had locally overridden
enabled:true — mergeOne() already applies overrides after the disable rule
and got this right. feedModelToMerged() now only force-disables when there
is no local `enabled` override, matching mergeOne()'s semantics.
* fix(radar): cap feed sync response body at 10MB
syncRadar() buffered the entire feed response via
Buffer.from(await res.arrayBuffer()) with no size limit, so a
misconfigured or hostile RADAR_FEED_URL (or an upstream serving garbage)
could force an unbounded in-memory buffer. Enforcement is two-layered: a
Content-Length preflight skips reading an already-oversized body entirely,
and a running-total check while reading the stream enforces the cap even
when Content-Length is absent or understates the real size — concatenating
the accumulated chunks preserves the exact bytes the signature check needs.
Exceeding the cap returns a new { status: "too_large" } SyncStatus and
leaves the cache untouched, following the same non-destructive pattern as
every other sync failure (invalid_signature/invalid_schema/stale).
* fix(radar): gate the sidebar radar item behind RADAR_ENABLED
The "radar" sidebar item was registered unconditionally in
sidebarVisibility/sections.ts, but Sidebar.tsx has no feature-flag
awareness (it's a client component), so the link stayed visible and
clickable with RADAR_ENABLED off, landing on a 404 dashboard page.
Sidebar items gain an opt-in `featureFlagKey` field plus a pure
isSidebarItemVisibleForFlags() filter (fails open when a flag isn't in the
map, so a missing/not-yet-loaded key never hides an unrelated item). The
resolved flag value piggy-backs on the /api/settings response the sidebar
already fetches on mount (new `radarEnabled` field) rather than adding a
dedicated round trip.
* fix(radar): require auth on management routes, add GET settings
GET /api/radar/catalog, POST /api/radar/sync, and POST /api/radar/settings
had zero authentication — any client that could reach the local server
could read the merged catalog, trigger a sync, or flip the opt-in/set the
supporter key. All three (plus the new GET below) now call
isAuthenticated() from the shared apiAuth guard, same gate as the rest of
/api/settings/*. The RADAR_ENABLED flag-off 404 check keeps running FIRST
so flag-off inertia stays byte-identical (no auth prompt just to learn the
surface doesn't exist); auth runs after it, before any DB access.
Adds GET /api/radar/settings, returning { optIn, hasSupporterKey,
supporterKeyMasked } — the raw key never leaves the server on either verb.
The dashboard page's fetchSettings() now calls this endpoint instead of
inferring opt-in state from the catalog response (which always defaulted
to unknown/null), so an already-activated operator no longer sees the
activation screen on every reload. handleSync() also handles the new
too_large sync status introduced by the response-cap fix, reusing the
existing generic sync-failed copy (no new UI strings).
* docs(radar): fix stale feed URL, document tier header/auth/size cap
- RADAR_FEED_URL default was documented as radar.omniroute.dev in
ENVIRONMENT.md; the actual default (src/lib/radar/sync.ts) and every
other reference use radar.omniroute.online — fix the one stale spot.
- Correct the FREE_MODEL_BUDGETS source path: it's declared in
freeModelCatalog.data.ts, not freeModelCatalog.ts (which only
re-exports it).
- Document that the signed feed body's `tier` is always "live" (one
signed artifact per version) and the actually-served tier comes from
the `x-omniroute-feed-tier` response header, resolved with a Zod parse
+ fallback to the body field.
- Document that all four /api/radar/* routes now require auth
(isAuthenticated(), same gate as /api/settings/*), the new
GET /api/radar/settings route, and the new too_large sync status from
the 10MB response cap.
* feat(radar): daily sync scheduler + auto-sync on page open
Spec asks for a 1x/day sync while opted in and fresh data on every page
open. The scheduler only arms itself when RADAR_ENABLED AND the opt-in are
already on (boot) or right after the user opts in (settings route) — a
flag-off install never creates the timer, preserving the inertia contract.
The page auto-syncs once per mount when the cached feed is older than 6h.
---------
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
820 lines
25 KiB
TypeScript
820 lines
25 KiB
TypeScript
/**
|
|
* tests/unit/radar-apply-feed.test.ts
|
|
*
|
|
* TDD regression guard for the Radar read-time overlay merge rules.
|
|
*
|
|
* Tests cover:
|
|
* - 4 merge rules (local override, feed disable, user-added, tombstone)
|
|
* - flag off => baseline passthrough
|
|
* - no cache => baseline
|
|
* - corrupt cache => baseline (defensive)
|
|
* - feed-only entry gets added
|
|
* - feed fields merge over baseline when no local override
|
|
* - getRadarCatalog() accessor
|
|
*/
|
|
|
|
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import {
|
|
applyFeed,
|
|
type MergedEntry,
|
|
type FeedModel,
|
|
} from "../../src/lib/radar/applyFeed.ts";
|
|
import {
|
|
getRadarCatalog,
|
|
baselineToMergedEntries,
|
|
type RadarCatalogResult,
|
|
} from "../../src/lib/radar/index.ts";
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Minimal fixtures — shape-matched to real types
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/** Slimmed-down baseline entries (the static free catalog shape). */
|
|
function makeBaseline(): MergedEntry[] {
|
|
return [
|
|
{
|
|
provider: "groq",
|
|
modelId: "llama-3.3-70b-versatile",
|
|
displayName: "Llama 3.3 70B Versatile",
|
|
monthlyTokens: 1_000_000,
|
|
creditTokens: 0,
|
|
freeType: "recurring-daily",
|
|
poolKey: null,
|
|
tos: "ok",
|
|
trainsOnPrompts: false,
|
|
origin: "baseline",
|
|
},
|
|
{
|
|
provider: "gemini",
|
|
modelId: "gemini-2.5-flash",
|
|
displayName: "Gemini 2.5 Flash",
|
|
monthlyTokens: 500_000,
|
|
creditTokens: 0,
|
|
freeType: "recurring-daily",
|
|
poolKey: "gemini-free-pool",
|
|
tos: "ok",
|
|
origin: "baseline",
|
|
},
|
|
{
|
|
provider: "openrouter",
|
|
modelId: "mistral-small-3.1-24b-instruct:free",
|
|
displayName: "Mistral Small 3.1 24B",
|
|
monthlyTokens: 200_000,
|
|
creditTokens: 0,
|
|
freeType: "recurring-daily",
|
|
poolKey: null,
|
|
tos: "caution",
|
|
origin: "baseline",
|
|
},
|
|
];
|
|
}
|
|
|
|
function makeFeedModel(overrides: Partial<FeedModel> & { provider: string; modelId: string }): FeedModel {
|
|
return {
|
|
displayName: overrides.displayName ?? overrides.modelId,
|
|
familyId: null,
|
|
freeType: overrides.freeType ?? "recurring-daily",
|
|
budget: overrides.budget ?? { kind: "per_model", tokensPerMonth: 1_000_000 },
|
|
limits: { rpm: null, rpd: null, tpm: null, tpd: null },
|
|
contextWindow: 131072,
|
|
capabilities: { tools: true, vision: false, thinking: false },
|
|
trainsOnPrompts: null,
|
|
tosRisk: overrides.tosRisk ?? "ok",
|
|
setup: null,
|
|
enabled: overrides.enabled ?? true,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Rule 1: Feed never overwrites a local override
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("rule 1: feed does NOT overwrite a local override field", () => {
|
|
const baseline = makeBaseline();
|
|
const feed: FeedModel[] = [
|
|
makeFeedModel({
|
|
provider: "groq",
|
|
modelId: "llama-3.3-70b-versatile",
|
|
displayName: "Feed Updated Name",
|
|
tosRisk: "avoid",
|
|
budget: { kind: "per_model", tokensPerMonth: 9_999_999 },
|
|
}),
|
|
];
|
|
|
|
// User has locally overridden displayName and tos for this entry
|
|
const localOverrides = new Map<string, Partial<MergedEntry>>([
|
|
["groq:llama-3.3-70b-versatile", { displayName: "My Custom Name", tos: "ok" }],
|
|
]);
|
|
|
|
const result = applyFeed({
|
|
baseline,
|
|
feed,
|
|
localOverrides,
|
|
tombstones: new Set(),
|
|
});
|
|
|
|
const groq = result.find(
|
|
(e) => e.provider === "groq" && e.modelId === "llama-3.3-70b-versatile",
|
|
)!;
|
|
|
|
// Local override fields must survive
|
|
assert.equal(groq.displayName, "My Custom Name");
|
|
assert.equal(groq.tos, "ok");
|
|
|
|
// Feed fields that the user did NOT override should still merge
|
|
assert.equal(groq.monthlyTokens, 9_999_999);
|
|
assert.equal(groq.origin, "local");
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Rule 2: enabled:false in the feed disables the entry with provenance
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("rule 2: feed enabled:false disables entry and carries disabledBy provenance", () => {
|
|
const baseline = makeBaseline();
|
|
const feed: FeedModel[] = [
|
|
makeFeedModel({
|
|
provider: "groq",
|
|
modelId: "llama-3.3-70b-versatile",
|
|
enabled: false,
|
|
}),
|
|
];
|
|
|
|
const result = applyFeed({
|
|
baseline,
|
|
feed,
|
|
localOverrides: new Map(),
|
|
tombstones: new Set(),
|
|
});
|
|
|
|
const groq = result.find(
|
|
(e) => e.provider === "groq" && e.modelId === "llama-3.3-70b-versatile",
|
|
)!;
|
|
|
|
assert.equal(groq.enabled, false);
|
|
assert.equal(groq.disabledBy, "radar");
|
|
assert.equal(groq.origin, "radar");
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Rule 3: User-added entry NOT in the feed survives untouched
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("rule 3: user-added entry not in feed survives untouched", () => {
|
|
// Add a user-created entry to baseline
|
|
const baseline = [
|
|
...makeBaseline(),
|
|
{
|
|
provider: "custom",
|
|
modelId: "my-local-model",
|
|
displayName: "My Local Model",
|
|
monthlyTokens: 50_000,
|
|
creditTokens: 0,
|
|
freeType: "recurring-daily" as const,
|
|
poolKey: null,
|
|
tos: "ok" as const,
|
|
origin: "local" as const,
|
|
},
|
|
];
|
|
|
|
// Feed does NOT mention custom:my-local-model
|
|
const feed: FeedModel[] = [
|
|
makeFeedModel({ provider: "groq", modelId: "llama-3.3-70b-versatile" }),
|
|
];
|
|
|
|
const result = applyFeed({
|
|
baseline,
|
|
feed,
|
|
localOverrides: new Map(),
|
|
tombstones: new Set(),
|
|
});
|
|
|
|
const custom = result.find(
|
|
(e) => e.provider === "custom" && e.modelId === "my-local-model",
|
|
)!;
|
|
|
|
assert.equal(custom.displayName, "My Local Model");
|
|
assert.equal(custom.monthlyTokens, 50_000);
|
|
assert.equal(custom.origin, "local");
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Rule 3b: User-added entry that IS in the feed => rule 1 applies (merge)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("rule 3b: user-added entry that IS in the feed merges with rule 1", () => {
|
|
const baseline = [
|
|
...makeBaseline(),
|
|
{
|
|
provider: "groq",
|
|
modelId: "llama-3.3-70b-versatile",
|
|
displayName: "My Custom Groq",
|
|
monthlyTokens: 999_000,
|
|
creditTokens: 0,
|
|
freeType: "recurring-daily" as const,
|
|
poolKey: null,
|
|
tos: "ok" as const,
|
|
origin: "local" as const,
|
|
},
|
|
];
|
|
|
|
const feed: FeedModel[] = [
|
|
makeFeedModel({
|
|
provider: "groq",
|
|
modelId: "llama-3.3-70b-versatile",
|
|
displayName: "Feed Name",
|
|
budget: { kind: "per_model", tokensPerMonth: 2_000_000 },
|
|
}),
|
|
];
|
|
|
|
// User has overridden displayName locally
|
|
const localOverrides = new Map<string, Partial<MergedEntry>>([
|
|
["groq:llama-3.3-70b-versatile", { displayName: "My Custom Groq" }],
|
|
]);
|
|
|
|
const result = applyFeed({
|
|
baseline,
|
|
feed,
|
|
localOverrides,
|
|
tombstones: new Set(),
|
|
});
|
|
|
|
const groq = result.filter(
|
|
(e) => e.provider === "groq" && e.modelId === "llama-3.3-70b-versatile",
|
|
);
|
|
|
|
// Should be deduplicated to ONE entry
|
|
assert.equal(groq.length, 1);
|
|
|
|
// Local override preserved
|
|
assert.equal(groq[0].displayName, "My Custom Groq");
|
|
|
|
// Feed field that user did not override merges through
|
|
assert.equal(groq[0].monthlyTokens, 2_000_000);
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Rule 4: Tombstone prevents feed from resurrecting a deleted entry
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("rule 4: tombstone prevents feed from resurrecting a deleted entry", () => {
|
|
// Baseline has an entry for gemini, but user deleted it
|
|
const baseline = makeBaseline().filter(
|
|
(e) => !(e.provider === "gemini" && e.modelId === "gemini-2.5-flash"),
|
|
);
|
|
|
|
const feed: FeedModel[] = [
|
|
makeFeedModel({
|
|
provider: "gemini",
|
|
modelId: "gemini-2.5-flash",
|
|
displayName: "Gemini 2.5 Flash",
|
|
}),
|
|
];
|
|
|
|
// Tombstone marks this key as deleted by the user
|
|
const tombstones = new Set<string>(["gemini:gemini-2.5-flash"]);
|
|
|
|
const result = applyFeed({
|
|
baseline,
|
|
feed,
|
|
localOverrides: new Map(),
|
|
tombstones,
|
|
});
|
|
|
|
const gemini = result.find(
|
|
(e) => e.provider === "gemini" && e.modelId === "gemini-2.5-flash",
|
|
);
|
|
|
|
// Must NOT be resurrected
|
|
assert.equal(gemini, undefined);
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Flag off => accessor returns baseline byte-for-byte equivalent
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("getRadarCatalog: flag off returns baseline unchanged", async () => {
|
|
// We test applyFeed directly: when called with empty feed, result = baseline
|
|
const baseline = makeBaseline();
|
|
const result = applyFeed({
|
|
baseline,
|
|
feed: [],
|
|
localOverrides: new Map(),
|
|
tombstones: new Set(),
|
|
});
|
|
|
|
assert.equal(result.length, baseline.length);
|
|
for (let i = 0; i < result.length; i++) {
|
|
assert.equal(result[i].provider, baseline[i].provider);
|
|
assert.equal(result[i].modelId, baseline[i].modelId);
|
|
assert.equal(result[i].displayName, baseline[i].displayName);
|
|
assert.equal(result[i].monthlyTokens, baseline[i].monthlyTokens);
|
|
assert.equal(result[i].origin, baseline[i].origin);
|
|
}
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// No feed (empty) => baseline passthrough
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("applyFeed: empty feed returns baseline unchanged", () => {
|
|
const baseline = makeBaseline();
|
|
const result = applyFeed({
|
|
baseline,
|
|
feed: [],
|
|
localOverrides: new Map(),
|
|
tombstones: new Set(),
|
|
});
|
|
|
|
assert.deepEqual(result, baseline);
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Feed entry NOT in baseline is ADDED with origin "radar"
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("applyFeed: feed-only entry is added with origin 'radar'", () => {
|
|
const baseline = makeBaseline();
|
|
const feed: FeedModel[] = [
|
|
makeFeedModel({
|
|
provider: "new-provider",
|
|
modelId: "new-model",
|
|
displayName: "Brand New Model",
|
|
budget: { kind: "per_model", tokensPerMonth: 3_000_000 },
|
|
}),
|
|
];
|
|
|
|
const result = applyFeed({
|
|
baseline,
|
|
feed,
|
|
localOverrides: new Map(),
|
|
tombstones: new Set(),
|
|
});
|
|
|
|
const added = result.find(
|
|
(e) => e.provider === "new-provider" && e.modelId === "new-model",
|
|
);
|
|
|
|
assert.ok(added, "feed-only entry should be present");
|
|
assert.equal(added.displayName, "Brand New Model");
|
|
assert.equal(added.monthlyTokens, 3_000_000);
|
|
assert.equal(added.origin, "radar");
|
|
assert.equal(added.enabled, true);
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Feed merges over baseline where no local override exists
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("applyFeed: feed fields merge over baseline where no local override", () => {
|
|
const baseline = makeBaseline();
|
|
const feed: FeedModel[] = [
|
|
makeFeedModel({
|
|
provider: "groq",
|
|
modelId: "llama-3.3-70b-versatile",
|
|
displayName: "Feed Updated Name",
|
|
tosRisk: "avoid",
|
|
budget: { kind: "per_model", tokensPerMonth: 5_000_000 },
|
|
}),
|
|
];
|
|
|
|
const result = applyFeed({
|
|
baseline,
|
|
feed,
|
|
localOverrides: new Map(),
|
|
tombstones: new Set(),
|
|
});
|
|
|
|
const groq = result.find(
|
|
(e) => e.provider === "groq" && e.modelId === "llama-3.3-70b-versatile",
|
|
)!;
|
|
|
|
// Feed values win when no local override
|
|
assert.equal(groq.displayName, "Feed Updated Name");
|
|
assert.equal(groq.tos, "avoid");
|
|
assert.equal(groq.monthlyTokens, 5_000_000);
|
|
assert.equal(groq.origin, "radar");
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Corrupt feed payload => baseline passthrough (defensive)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("applyFeed: returns baseline when feed is empty (defensive corrupt scenario)", () => {
|
|
const baseline = makeBaseline();
|
|
|
|
// Simulate a corrupt/invalid feed by passing an empty array
|
|
// (the real accessor would catch JSON.parse failures before calling applyFeed)
|
|
const result = applyFeed({
|
|
baseline,
|
|
feed: [],
|
|
localOverrides: new Map(),
|
|
tombstones: new Set(),
|
|
});
|
|
|
|
assert.deepEqual(result, baseline);
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Deduplication: baseline + feed with same key produces one entry
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("applyFeed: duplicate key (baseline + feed) produces single merged entry", () => {
|
|
const baseline = makeBaseline();
|
|
const feed: FeedModel[] = [
|
|
makeFeedModel({
|
|
provider: "groq",
|
|
modelId: "llama-3.3-70b-versatile",
|
|
displayName: "Feed Groq",
|
|
budget: { kind: "per_model", tokensPerMonth: 7_000_000 },
|
|
}),
|
|
];
|
|
|
|
const result = applyFeed({
|
|
baseline,
|
|
feed,
|
|
localOverrides: new Map(),
|
|
tombstones: new Set(),
|
|
});
|
|
|
|
const groqEntries = result.filter(
|
|
(e) => e.provider === "groq" && e.modelId === "llama-3.3-70b-versatile",
|
|
);
|
|
|
|
assert.equal(groqEntries.length, 1, "should be deduplicated to one entry");
|
|
assert.equal(groqEntries[0].displayName, "Feed Groq");
|
|
assert.equal(groqEntries[0].monthlyTokens, 7_000_000);
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Tombstone: feed entry is tombstoned even when baseline also has it
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("rule 4b: tombstoned entry removed even when baseline has it", () => {
|
|
const baseline = makeBaseline();
|
|
const feed: FeedModel[] = [];
|
|
|
|
const tombstones = new Set<string>(["groq:llama-3.3-70b-versatile"]);
|
|
|
|
const result = applyFeed({
|
|
baseline,
|
|
feed,
|
|
localOverrides: new Map(),
|
|
tombstones,
|
|
});
|
|
|
|
const groq = result.find(
|
|
(e) => e.provider === "groq" && e.modelId === "llama-3.3-70b-versatile",
|
|
);
|
|
|
|
assert.equal(groq, undefined, "tombstoned entry should be excluded");
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Entry with origin "baseline" that feed updates gets origin "radar"
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("origin switches to 'radar' when feed updates a baseline entry", () => {
|
|
const baseline = makeBaseline();
|
|
const feed: FeedModel[] = [
|
|
makeFeedModel({
|
|
provider: "gemini",
|
|
modelId: "gemini-2.5-flash",
|
|
displayName: "Updated Gemini",
|
|
budget: { kind: "per_model", tokensPerMonth: 800_000 },
|
|
}),
|
|
];
|
|
|
|
const result = applyFeed({
|
|
baseline,
|
|
feed,
|
|
localOverrides: new Map(),
|
|
tombstones: new Set(),
|
|
});
|
|
|
|
const gemini = result.find(
|
|
(e) => e.provider === "gemini" && e.modelId === "gemini-2.5-flash",
|
|
)!;
|
|
|
|
assert.equal(gemini.origin, "radar");
|
|
assert.equal(gemini.displayName, "Updated Gemini");
|
|
});
|
|
|
|
// ===========================================================================
|
|
// getRadarCatalog() accessor tests
|
|
// ===========================================================================
|
|
|
|
/** Minimal valid RadarFeed payload (passes RadarFeedSchema.parse). */
|
|
const VALID_FEED_JSON = JSON.stringify({
|
|
feed: "omniroute-radar",
|
|
schemaVersion: 1,
|
|
version: "2026.08.01.1",
|
|
generatedAt: "2026-08-01T12:00:00Z",
|
|
tier: "community",
|
|
counts: { providers: 1, models: 1 },
|
|
providers: [{ id: "groq", name: "Groq" }],
|
|
models: [
|
|
{
|
|
provider: "groq",
|
|
modelId: "llama-3.3-70b-versatile",
|
|
displayName: "Feed Groq Name",
|
|
familyId: "llama-3.3-70b",
|
|
freeType: "recurring-daily",
|
|
budget: { kind: "per_model", tokensPerMonth: 5_000_000 },
|
|
limits: { rpm: 30, rpd: 14400, tpm: 6000, tpd: null },
|
|
contextWindow: 131072,
|
|
capabilities: { tools: true, vision: false, thinking: false },
|
|
trainsOnPrompts: null,
|
|
tosRisk: "ok",
|
|
setup: { keyUrl: "https://console.groq.com/keys", steps: ["Step 1"] },
|
|
enabled: true,
|
|
},
|
|
],
|
|
quirks: [],
|
|
totals: { dedupedTokensPerMonth: 5_000_000, modelCount: 1, poolCount: 0 },
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Accessor: flag off => baseline passthrough, no cache read
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("getRadarCatalog: flag off returns baseline and does NOT read cache", () => {
|
|
let cacheRead = false;
|
|
|
|
const result = getRadarCatalog({
|
|
getFlag: () => false,
|
|
getCache: () => {
|
|
cacheRead = true;
|
|
return null;
|
|
},
|
|
baseline: makeBaseline(),
|
|
});
|
|
|
|
assert.equal(result.entries.length, 3, "baseline entries returned");
|
|
assert.equal(result.meta, null, "no meta when flag off");
|
|
assert.equal(cacheRead, false, "cache should not be read when flag is off");
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Accessor: no cache => baseline
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("getRadarCatalog: no cache returns baseline", () => {
|
|
const result = getRadarCatalog({
|
|
getFlag: () => true,
|
|
getCache: () => null,
|
|
baseline: makeBaseline(),
|
|
});
|
|
|
|
assert.equal(result.entries.length, 3);
|
|
assert.equal(result.meta, null);
|
|
assert.equal(result.entries[0].origin, "baseline");
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Accessor: corrupt cached payload => baseline (defensive), no throw
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("getRadarCatalog: corrupt payload returns baseline without throwing", () => {
|
|
const result = getRadarCatalog({
|
|
getFlag: () => true,
|
|
getCache: () => ({
|
|
version: "2026.08.01.1",
|
|
tier: "community",
|
|
payload: "{invalid json!!!",
|
|
fetchedAt: "2026-08-01T12:00:00Z",
|
|
}),
|
|
baseline: makeBaseline(),
|
|
});
|
|
|
|
assert.equal(result.entries.length, 3);
|
|
assert.equal(result.meta, null);
|
|
assert.equal(result.entries[0].origin, "baseline");
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Accessor: valid cache => applyFeed output + meta
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("getRadarCatalog: valid cache returns merged entries with meta", () => {
|
|
const result = getRadarCatalog({
|
|
getFlag: () => true,
|
|
getCache: () => ({
|
|
version: "2026.08.01.1",
|
|
tier: "community",
|
|
payload: VALID_FEED_JSON,
|
|
fetchedAt: "2026-08-01T12:00:00Z",
|
|
}),
|
|
baseline: makeBaseline(),
|
|
});
|
|
|
|
// The feed has groq:llama-3.3-70b-versatile, which merges over baseline
|
|
const groq = result.entries.find(
|
|
(e) => e.provider === "groq" && e.modelId === "llama-3.3-70b-versatile",
|
|
)!;
|
|
|
|
assert.equal(groq.displayName, "Feed Groq Name");
|
|
assert.equal(groq.monthlyTokens, 5_000_000);
|
|
assert.equal(groq.origin, "radar");
|
|
|
|
// Meta is present
|
|
assert.ok(result.meta);
|
|
assert.equal(result.meta.version, "2026.08.01.1");
|
|
assert.equal(result.meta.tier, "community");
|
|
assert.equal(result.meta.fetchedAt, "2026-08-01T12:00:00Z");
|
|
|
|
// Other baseline entries survive
|
|
assert.equal(result.entries.length, 3);
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Accessor: schema-valid but wrong feed name => falls back to baseline
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("getRadarCatalog: wrong feed literal falls back to baseline", () => {
|
|
const badPayload = JSON.stringify({
|
|
feed: "wrong-feed-name",
|
|
schemaVersion: 1,
|
|
version: "2026.08.01.1",
|
|
generatedAt: "2026-08-01T12:00:00Z",
|
|
tier: "community",
|
|
counts: { providers: 0, models: 0 },
|
|
providers: [],
|
|
models: [],
|
|
quirks: [],
|
|
totals: { dedupedTokensPerMonth: 0, modelCount: 0, poolCount: 0 },
|
|
});
|
|
|
|
const result = getRadarCatalog({
|
|
getFlag: () => true,
|
|
getCache: () => ({
|
|
version: "2026.08.01.1",
|
|
tier: "community",
|
|
payload: badPayload,
|
|
fetchedAt: "2026-08-01T12:00:00Z",
|
|
}),
|
|
baseline: makeBaseline(),
|
|
});
|
|
|
|
assert.equal(result.entries.length, 3, "baseline returned for bad feed literal");
|
|
assert.equal(result.meta, null);
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// baselineToMergedEntries converter
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("baselineToMergedEntries: converts FreeModelBudget shape to MergedEntry", () => {
|
|
const budgets = [
|
|
{
|
|
provider: "test",
|
|
modelId: "model-1",
|
|
displayName: "Test Model",
|
|
monthlyTokens: 100_000,
|
|
creditTokens: 0,
|
|
freeType: "recurring-daily" as const,
|
|
poolKey: null,
|
|
tos: "ok" as const,
|
|
},
|
|
];
|
|
|
|
const entries = baselineToMergedEntries(budgets);
|
|
|
|
assert.equal(entries.length, 1);
|
|
assert.equal(entries[0].provider, "test");
|
|
assert.equal(entries[0].origin, "baseline");
|
|
assert.equal(entries[0].enabled, true);
|
|
});
|
|
|
|
// ===========================================================================
|
|
// FIX 2 — extended feed fields (contextWindow/capabilities/limits/setup)
|
|
// must survive the merge on BOTH code paths (mergeOne + feedModelToMerged).
|
|
// ===========================================================================
|
|
|
|
test("FIX2 mergeOne path: contextWindow/capabilities/limits/setup survive merge over a baseline entry", () => {
|
|
const baseline = makeBaseline();
|
|
const feed: FeedModel[] = [
|
|
makeFeedModel({
|
|
provider: "groq",
|
|
modelId: "llama-3.3-70b-versatile",
|
|
contextWindow: 131072,
|
|
capabilities: { tools: true, vision: true, thinking: false },
|
|
limits: { rpm: 30, rpd: 14400, tpm: 6000, tpd: null },
|
|
setup: { keyUrl: "https://console.groq.com/keys", steps: ["Sign up", "Create key"] },
|
|
}),
|
|
];
|
|
|
|
const result = applyFeed({
|
|
baseline,
|
|
feed,
|
|
localOverrides: new Map(),
|
|
tombstones: new Set(),
|
|
});
|
|
|
|
const groq = result.find(
|
|
(e) => e.provider === "groq" && e.modelId === "llama-3.3-70b-versatile",
|
|
)!;
|
|
|
|
assert.equal(groq.contextWindow, 131072);
|
|
assert.deepEqual(groq.capabilities, { tools: true, vision: true, thinking: false });
|
|
assert.deepEqual(groq.limits, { rpm: 30, rpd: 14400, tpm: 6000, tpd: null });
|
|
assert.deepEqual(groq.setup, {
|
|
keyUrl: "https://console.groq.com/keys",
|
|
steps: ["Sign up", "Create key"],
|
|
});
|
|
});
|
|
|
|
test("FIX2 feedModelToMerged path: contextWindow/capabilities/limits/setup survive for a feed-only entry", () => {
|
|
const baseline = makeBaseline();
|
|
const feed: FeedModel[] = [
|
|
makeFeedModel({
|
|
provider: "new-provider",
|
|
modelId: "new-model",
|
|
contextWindow: 65536,
|
|
capabilities: { tools: false, vision: true, thinking: true },
|
|
limits: { rpm: null, rpd: 100, tpm: null, tpd: null },
|
|
setup: { keyUrl: "https://new-provider.example/keys", steps: ["Step A"] },
|
|
}),
|
|
];
|
|
|
|
const result = applyFeed({
|
|
baseline,
|
|
feed,
|
|
localOverrides: new Map(),
|
|
tombstones: new Set(),
|
|
});
|
|
|
|
const added = result.find((e) => e.provider === "new-provider" && e.modelId === "new-model")!;
|
|
|
|
assert.equal(added.contextWindow, 65536);
|
|
assert.deepEqual(added.capabilities, { tools: false, vision: true, thinking: true });
|
|
assert.deepEqual(added.limits, { rpm: null, rpd: 100, tpm: null, tpd: null });
|
|
assert.deepEqual(added.setup, {
|
|
keyUrl: "https://new-provider.example/keys",
|
|
steps: ["Step A"],
|
|
});
|
|
});
|
|
|
|
// ===========================================================================
|
|
// FIX 4 — feedModelToMerged() must honor an `enabled` local override instead
|
|
// of unconditionally forcing `enabled:false` when the feed disables the model.
|
|
// mergeOne() already gets this right (overrides applied AFTER rule 2); this
|
|
// pins the same semantics on the feed-only path.
|
|
// ===========================================================================
|
|
|
|
test("FIX4: feed-only entry with local override enabled:true wins over feed enabled:false", () => {
|
|
const baseline = makeBaseline();
|
|
const feed: FeedModel[] = [
|
|
makeFeedModel({
|
|
provider: "new-provider",
|
|
modelId: "disabled-model",
|
|
enabled: false,
|
|
}),
|
|
];
|
|
|
|
const localOverrides = new Map<string, Partial<MergedEntry>>([
|
|
["new-provider:disabled-model", { enabled: true }],
|
|
]);
|
|
|
|
const result = applyFeed({
|
|
baseline,
|
|
feed,
|
|
localOverrides,
|
|
tombstones: new Set(),
|
|
});
|
|
|
|
const entry = result.find(
|
|
(e) => e.provider === "new-provider" && e.modelId === "disabled-model",
|
|
)!;
|
|
|
|
assert.equal(entry.enabled, true, "local override must win over feed disable");
|
|
assert.equal(entry.disabledBy, undefined, "must not carry radar disabledBy when overridden on");
|
|
});
|
|
|
|
test("FIX4: feed-only entry with NO override still gets disabled with disabledBy provenance", () => {
|
|
const baseline = makeBaseline();
|
|
const feed: FeedModel[] = [
|
|
makeFeedModel({
|
|
provider: "new-provider",
|
|
modelId: "disabled-model-2",
|
|
enabled: false,
|
|
}),
|
|
];
|
|
|
|
const result = applyFeed({
|
|
baseline,
|
|
feed,
|
|
localOverrides: new Map(),
|
|
tombstones: new Set(),
|
|
});
|
|
|
|
const entry = result.find(
|
|
(e) => e.provider === "new-provider" && e.modelId === "disabled-model-2",
|
|
)!;
|
|
|
|
assert.equal(entry.enabled, false);
|
|
assert.equal(entry.disabledBy, "radar");
|
|
});
|