Stats-bar catalog join + dock numerator consistency (context-meter close-out)

Platform's context-meter pair (04e336d, 18cc493) left two client seams
in my band; this closes the arc:

1. STATS-BAR CATALOG JOIN: contextWindow's denominator resolves ONLY
   from pi's live catalog — stats-bar now builds the provider:id ->
   contextWindow index client-side (catalogLimits in model-picker.tsx,
   the client twin of the server's catalogContextLimits join) over the
   picker's existing /api/models fetch/cache (useModelCatalog exported;
   module-level dedupe, one fetch feeds both ModelControl and the
   meter). Catalog pending or failed -> undefined index -> limit null ->
   USAGE-ONLY (Platform's interim render IS the null path; the
   honest-render precedent, never a fake window).

2. DOCK NUMERATOR CONSISTENCY: toBlobs' context fold was still
   last-step input+output only — now the same cache-inclusive footprint
   the session meter uses (all four directions; provider "input"
   EXCLUDES cacheRead/cacheWrite, so the old fold read wildly low on
   cache-heavy jobs). Same metric everywhere.

Review of Platform's interim edits in this band: verified as-shipped —
stats-bar's usage-only render (summary + popover), FeedJob.contextLimit
with the line-hides null treatment, and the render-test rewrites all
fit. Only fix needed: none beyond the above.

Tests: catalogLimits pinned pure (index shape, provider:id keying,
missing-model absence); toBlobs pinned on the cache-inclusive
numerator (10k+0.5k+120k+30k = 160.5k against a 200k feed limit).
889/889.

Live-verified on :3001: seedplan's bar reads "18.7k / 1M" (footprint
18725, catalog 1048576); a nope/unknown-model chat renders "12.8k"
usage-only with cost "-"; the popover detail matches; the dock blob's
context line renders "946 / 1M" from a server-joined feed (an
unintentionally real runner-adopted job — the full chain, live).
This commit is contained in:
amosblomqvist
2026-09-24 02:15:23 +03:00
parent 4ded547cb5
commit 81709afd22
5 changed files with 108 additions and 6 deletions
+48 -1
View File
@@ -2,6 +2,8 @@ import { renderToStaticMarkup } from "react-dom/server";
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import { StatsBar } from "../components/stats-bar.tsx";
import { catalogLimits } from "../components/model-picker.tsx";
import type { ModelCatalogEntry, ModelCatalogResponse } from "../src/core/contracts.ts";
import { prettyModel } from "../components/usage-format.ts";
import type { ChatSettings, TurnUsage } from "../src/core/contracts.ts";
@@ -90,4 +92,49 @@ describe("stats bar", () => {
// qualified on a bare id: no suffix invented
assert.equal(prettyModel("z-ai/glm-5.3-flash", true), "Glm 5.3 Flash");
});
});
});
describe("catalogLimits (the stats-bar live-limits join, pure)", () => {
// The client-side twin of the server's catalogContextLimits join:
// provider:id → contextWindow straight from the cached /api/models
// payload. A static render holds no catalog (the fetch is a live
// concern — Playwright verifies the wiring), so the pure index shape
// is pinned here: one entry per model, the exact key contextWindow()
// looks up, missing models absent (→ limit null → usage-only).
const entry = (over: Pick<ModelCatalogEntry, "id" | "provider" | "contextWindow">): ModelCatalogEntry => ({
name: over.id,
reasoning: false,
input: ["text"],
supportedLevels: [],
cost: { input: 1, output: 2, cacheRead: 0, cacheWrite: 0 },
maxTokens: 32_768,
...over,
});
const catalog: Pick<ModelCatalogResponse, "models"> = {
models: [
entry({ id: "z-ai/glm-5.3-flash", provider: "openrouter", contextWindow: 1_048_576 }),
entry({ id: "gpt-x", provider: "openai", contextWindow: 400_000 }),
],
};
it("builds provider:id → contextWindow over every catalog model", () => {
const limits = catalogLimits(catalog);
assert.equal(limits.get("openrouter:z-ai/glm-5.3-flash"), 1_048_576);
assert.equal(limits.get("openai:gpt-x"), 400_000);
assert.equal(limits.size, 2);
});
it("a model missing from the index is absent — limit null, usage-only (never a fallback)", () => {
const limits = catalogLimits(catalog);
assert.equal(limits.has("nope/unknown"), false);
});
it("same provider+model on different providers keys apart", () => {
const twin: Pick<ModelCatalogResponse, "models"> = {
models: [...catalog.models, entry({ id: "z-ai/glm-5.3-flash", provider: "zai", contextWindow: 200_000 })],
};
const limits = catalogLimits(twin);
assert.equal(limits.get("openrouter:z-ai/glm-5.3-flash"), 1_048_576);
assert.equal(limits.get("zai:z-ai/glm-5.3-flash"), 200_000);
});
});