/** * Commentary templates — bundled English prose for narrating an * agentfootprint run, plus the small engine that picks the right * template per event and substitutes payload values. * * Audience split (load-bearing): * • COMMENTARY — pure prose for the bottom panel of any viewer * (Lens, CLI tail, log file). NO technical numbers, * NO field dumps, NO library terms. * • DETAILS — token counts, durations, args, IDs. The right * panel / DevTools / structured-log territory. * * Architecture (3 pieces): * 1. `defaultCommentaryTemplates` — flat `key → string` map. * i18n-ready: ship a Spanish/Japanese/etc. version with the same * keys, pass via `commentaryTemplates` on the renderer. * 2. `selectCommentaryKey(event)` — per-event-type routing fn. * Returns `string` (render this key), `null` (skip — too * low-signal for prose), or `undefined` (fall through to a * caller-supplied default humanizer). * 3. `extractCommentaryVars(event, ctx)` — builds the * `{ appName, userPrompt, toolName, descClause, ... }` bag the * template will be rendered with. * * Plus a tiny non-recursive `renderCommentary(template, vars)`. * * Why this lives in agentfootprint (not Lens): * The keys ARE agentfootprint event types. The prose teaches * agentfootprint concepts (slot composition, ReAct, tool-calling). * Consumers building agentfootprint Agents ship their voice / locale * alongside their system prompt and tool registry. Lens (or any * other viewer) is just a renderer that consumes this surface. * * Verb discipline (encoded in the prose): * • `{{appName}}` (active actor) — called, dispatched, returned, * decided, read, built * • LLM (passive actor) — suggested, responded, produced, * asked for, gave * The split reflects the architectural truth: LLMs don't act, the * orchestrating system does. */ import type { AgentfootprintEvent } from '../../../events/registry.js'; /** Flat map of template keys to template strings. Keys use a dotted * hierarchy mirroring event types + payload branches * (`'stream.llm_start.iter1'`, `'context.injected.rag'`). Values may * contain `{{name}}` placeholders that `renderCommentary` substitutes. */ export type CommentaryTemplates = Readonly>; /** * The bundled English templates. Override per-key via the renderer's * `templates` option — partial overrides are spread on top of these * defaults so consumers only ship what they want to change. */ export declare const defaultCommentaryTemplates: CommentaryTemplates; /** Context the var-extractor reads from. Anything that's NOT in the * event payload (consumer-supplied appName, tool registry lookup) goes * here. Pure data — no closures, no I/O. */ export interface CommentaryContext { /** The system that orchestrates the LLM. Substituted as the active * actor in every line ("Acme called the LLM"). Default: `'Chatbot'`. */ readonly appName: string; /** Resolves a tool name to its registered description ("Get current * weather for a city"). Used to compose the optional `descClause` * for `stream.tool_start`. Sync — Lens-style consumers precompute * the lookup map from `context.injected source='registry'` events. */ readonly getToolDescription?: (toolName: string) => string | undefined; } /** * Pick the template key for an event. Branches encoded in the key * suffix (no conditional logic in the templates themselves). * * `null` → explicit skip (baseline injections, low-signal events) * `undefined` → fall through to caller's default humanizer * `string` → render `templates[key]` with `extractCommentaryVars` */ export declare function selectCommentaryKey(event: AgentfootprintEvent): string | null | undefined; /** * Build the variable bag for a given event. Flat `name → string` map; * `renderCommentary` substitutes by name. Templates use whatever names * this function produces. * * Two-step composition for `stream.tool_start`: the optional * `descClause` is a rendered sub-template. We pre-render it here so * the outer template stays a single non-recursive substitution pass. */ export declare function extractCommentaryVars(event: AgentfootprintEvent, ctx: CommentaryContext, templates?: CommentaryTemplates): Record; /** * Resolve the agent name from an event's `meta.subflowPath`. * * Walks the path right-to-left, skipping library-internal segments * (slot subflows, agent-routing subflows, thinking handlers), and * returns the FIRST meaningful segment with the optional `step-` * Sequence prefix stripped. For events with no meaningful path * (single-Agent runners, top-level events), falls back to `appName`. */ export declare function extractAgentName(event: AgentfootprintEvent, ctx: CommentaryContext): string; /** * Render a template by substituting `{{name}}` placeholders from the * vars bag. Missing keys render as empty string — keeps prose * forgiving when an optional field isn't present. * * Non-recursive: a substituted value is NOT itself processed for * placeholders. Compose sub-templates upstream (see * `extractCommentaryVars`). */ export declare function renderCommentary(template: string, vars: Record): string;