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:
@@ -1,9 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef, useState, type ReactNode } from "react";
|
||||
import { useEffect, useMemo, useRef, useState, type ReactNode } from "react";
|
||||
import { contextWindow, sessionCost, turnCost, type ChatSettings, type TurnUsage } from "@/src/core";
|
||||
import { formatTokens, formatUsd, prettyModel } from "@/components/usage-format";
|
||||
import { ModelControl } from "@/components/model-picker";
|
||||
import { ModelControl, catalogLimits, useModelCatalog } from "@/components/model-picker";
|
||||
|
||||
/**
|
||||
* The below-composer stats bar (wave 4 observability): the session's
|
||||
@@ -56,7 +56,16 @@ export function StatsBar({
|
||||
document.removeEventListener("keydown", onKeyDown);
|
||||
};
|
||||
}, [open]);
|
||||
const ctx = contextWindow({ turns });
|
||||
// The live-limits join (context-meter amendment, owner 2026-09-23):
|
||||
// contextWindow's denominator resolves ONLY from pi's live catalog —
|
||||
// built client-side over the picker's cached /api/models fetch (the
|
||||
// same fetch ModelControl below rides; module-level dedupe). Catalog
|
||||
// pending or failed → undefined index → limit null → USAGE-ONLY (the
|
||||
// honest-render precedent, never a fake window); the usage-only render
|
||||
// IS the null path.
|
||||
const { catalog } = useModelCatalog();
|
||||
const limits = useMemo(() => (catalog ? catalogLimits(catalog) : undefined), [catalog]);
|
||||
const ctx = contextWindow({ turns }, limits);
|
||||
const { cost, unpriced } = sessionCost({ turns });
|
||||
// Honest cost: show dollars only when at least one turn priced;
|
||||
// otherwise "—" (never a fake $0.0000).
|
||||
|
||||
Reference in New Issue
Block a user