fix: the knowledge-context slider lives in the stats bar's left slot — the session-data spot — with a "tok" readout

The original vision, restored (owner, 2026-09-15): pre-chat the session-
data side of the under-composer stats bar is free real estate ("—" only),
so the budget slider mounts exactly where session data will sit once a
session exists — via a new StatsBar leftSlot — vertically centered with
the model + thinking pills by the row's own geometry. Short 96px slider
instead of a full-width one; readout abbreviates "1k tok" so >1k budgets
stay on one line ("4.1k tokens" wrapped). Home and /chat/new both.
This commit is contained in:
amosblomqvist
2026-09-15 08:00:04 +03:00
parent 1d45d77303
commit 4c7ad48c73
5 changed files with 69 additions and 43 deletions
+15 -1
View File
@@ -1,6 +1,6 @@
"use client";
import { useEffect, useRef, useState } from "react";
import { useEffect, 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";
@@ -11,6 +11,12 @@ import { ModelControl } from "@/components/model-picker";
* LEFT-aligned: context window + session cost; RIGHT-aligned: model +
* thinking level. Clicking the left side opens the per-turn detail popover.
*
* Pre-chat views (home, /chat/new) pass `leftSlot`: with no session there
* IS no session data (the summary would just read "—"), so that left side
* is free real estate — the knowledge-context budget slider lives there
* (vision-context-injection.md), vertically centered beside the model +
* thinking pills by the row's own geometry.
*
* All folds come from core/prices.ts (sessionCost, contextWindow, turnCost)
* — no cost math lives here. Absent data renders "—", never zero (the
* doctrine): no turns yet → every figure is "—"; turns the price table
@@ -26,11 +32,15 @@ export function StatsBar({
chatId,
settings,
onSettingsSaved,
leftSlot,
}: {
turns: TurnUsage[];
chatId: string;
settings?: ChatSettings;
onSettingsSaved: (settings: ChatSettings) => void;
/** Pre-chat only: replaces the (empty) session-data summary — home and
* the /chat/new draft mount the knowledge-context slider here. */
leftSlot?: ReactNode;
}) {
const [open, setOpen] = useState(false);
// Same dropdown discipline as the model control (owner, df4433f treatment,
@@ -74,6 +84,9 @@ export function StatsBar({
outside-close ref anchors HERE too (owner, round 3): on the whole
bar it wrapped the model control, so clicking model/thinking never
counted as outside — the asymmetry the owner observed. */}
{/* The left side: the session-data summary, or — pre-chat — the
caller's slot (the knowledge-context slider) in its place. */}
{leftSlot ?? (
<div ref={barRef} className="relative">
<button
type="button"
@@ -141,6 +154,7 @@ export function StatsBar({
</div>
)}
</div>
)}
{/* The model + thinking control — one controller for the conversation
agents (prober/teacher); the record's `turns` above still folds
the ACTUAL models billed, regardless of what the picker says. */}