/** * Thinking templates — chat-bubble surface (separate from commentary). * * Audience split: * • COMMENTARY (`commentaryTemplates`) — third-person, every moment, * shown in Lens panel. Audience: * developer / observer. * • THINKING (this file) — first-person, mid-call only, * shown in chat bubble. Audience: * end user chatting with the agent. * * The thinking surface is a tiny finite state machine driven purely by * the event log: * * ┌──────────┐ llm.start, no tools yet * ────┤ idle ├────────────────────────────► "Thinking…" * └──────────┘ * * ┌──────────┐ stream.token chunks accumulate * ────┤streaming ├────────────────────────────► "{{partial}}" * └──────────┘ * * ┌──────────┐ tool.start, no tool.end yet * ────┤ tool ├────────────────────────────► "Working on `weather`…" * └──────────┘ (or per-tool override) * * ┌──────────┐ pause.request, no resume yet * ────┤ paused ├────────────────────────────► "Waiting on you: …" * └──────────┘ * * (null) run done / between calls → bubble hidden * * The selector returns the CURRENT state by walking the event log; * the renderer maps state → final string by looking up the template. * * Per-tool templates: consumers can ship `tool.` keys * (e.g. `tool.weather: 'Looking up the weather…'`) which the renderer * prefers over the generic `tool` template. Lets each tool have its * own first-person status without per-tool plumbing. */ import type { AgentfootprintEvent } from '../../../events/registry.js'; /** The four mid-call states a chat bubble might render. */ export type StatusKind = 'idle' | 'tool' | 'streaming' | 'paused'; /** * What the selector returns. The chat-bubble consumer feeds this into * the renderer to get the final string. */ export interface StatusState { readonly state: StatusKind; /** Vars for `{{name}}` substitution in the matched template. */ readonly vars: Readonly>; /** When `state === 'tool'`, the resolving toolName. The renderer * uses this to look up `tool.` before the generic `tool`. */ readonly toolName?: string; } /** Flat template map. Keys: state kinds + per-tool overrides. */ export type StatusTemplates = Readonly>; /** Render context — what the consumer's app config injects. */ export interface StatusContext { /** Active actor's name. Substituted as `{{appName}}` in templates. */ readonly appName: string; } /** * Bundled English defaults. Override in the agent config via * `.thinkingTemplates({...})`. Per-tool overrides go via * `tool.` keys. */ export declare const defaultStatusTemplates: StatusTemplates; /** * Derive the current thinking state from the event log. * * Single forward walk that tracks "active" state for each domain: * • pause — set on pause.request, cleared on pause.resume * • tool — set on tool.start, cleared on matching tool.end * (matched by `toolCallId` for parallel-tool safety) * • llm — set on llm.start, cleared on llm.end * * Priority order (highest first): * * 1. ACTIVE PAUSE wins. When the agent is waiting on the human, * that's what the chat should show — not the underlying tool * that triggered the pause. * 2. ACTIVE TOOL — the LLM said "use a tool" and the tool is * running. Show "Working on ``…". * 3. ACTIVE LLM — call in flight. Show streaming tokens if any * arrived, otherwise "Thinking…". * 4. Otherwise null (bubble hidden). * * Pure projection. Forward walk is O(n); a closing event correctly * cancels its matching opener so a completed tool.start/tool.end * pair leaves the state quiescent. */ export declare function selectStatus(events: readonly AgentfootprintEvent[]): StatusState | null; /** * Resolve the matched template + substitute vars. * * • `state === null` → null (chat bubble renders nothing) * • `state === 'tool'` → tries `tool.` first, then * generic `tool` * • Other states → looks up the state's name as the key * * Missing template keys return null rather than the empty string — * keeps the contract honest (consumer can detect "no template" and * fall back to its own default). */ export declare function renderStatusLine(state: StatusState | null, ctx: StatusContext, templates?: StatusTemplates): string | null;