@tangle-network/agent-app 0.43.4 → 0.43.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/web-react/index.tsx","../src/web-react/smooth-text.ts","../src/web-react/controls.tsx","../src/web-react/provider-logo.tsx","../src/web-react/brand-mark.tsx","../src/web-react/chat-stream.ts","../src/web-react/chat-composer.tsx","../src/web-react/mission-activity.tsx","../src/web-react/seat-paywall.tsx","../src/web-react/agent-session-controls.tsx"],"sourcesContent":["/**\n * `@tangle-network/agent-app/web-react` — the shared chat-shell components\n * every agent app's web UI hand-rolls: a model picker over the runtime's\n * model catalogue, a reasoning-effort selector, and a message thread with\n * User/Agent identity, per-message model + cost + tokens/sec metrics, tool\n * chips, and a collapsible thinking section.\n *\n * Works for BOTH chat shapes: router-backed copilots (LoopEvents from\n * `runtime/openai-stream`) and sandbox-backed chats — the thread renders\n * `ChatUiMessage`s; how they're produced is the app's business.\n *\n * Styling contract: Tailwind classes against the shared design tokens\n * (`bg-card`, `border-border`, `text-muted-foreground`, `bg-primary`, …) that\n * Tangle app shells define. No icon library — the few glyphs are inline SVGs.\n * Markdown and provider logos are injected (`renderMarkdown`,\n * `renderProviderBadge`) so this package stays dependency-free beyond React.\n */\n\nimport { useEffect, useMemo, useRef, useState, memo, type ReactNode } from 'react'\nimport { useSmoothText } from './smooth-text'\nimport { ChevronDown, POPOVER_OPTION_FOCUS, usePending } from './controls'\nimport { BrandMark } from './brand-mark'\n\nexport * from './chat-stream'\nexport * from './chat-composer'\nexport * from './provider-logo'\nexport * from './smooth-text'\nexport * from './mission-activity'\nexport * from './sandbox-terminal'\nexport * from './seat-paywall'\nexport {\n usePopover,\n usePending,\n ModelPicker,\n EffortPicker,\n DEFAULT_EFFORT_LEVELS,\n type ModelPickerProps,\n type EffortPickerProps,\n type EffortLevel,\n} from './controls'\nexport {\n AgentSessionControls,\n type AgentSessionControlsProps,\n} from './agent-session-controls'\nimport type { CatalogModel } from '../runtime/model-catalog'\n// Re-export the model type the chat components consume, so a web-react consumer\n// imports it from here rather than the package root.\nexport type { CatalogModel } from '../runtime/model-catalog'\n\n// ── metrics helpers ───────────────────────────────────────────────────────\n\nexport interface ChatMessageMetrics {\n modelUsed?: string\n promptTokens?: number\n completionTokens?: number\n durationMs?: number\n}\n\n/** \"$0.0042\" from token counts × catalogue per-token pricing; null when unknown. */\nexport function formatModelCost(msg: ChatMessageMetrics, models: CatalogModel[]): string | null {\n if (msg.promptTokens == null && msg.completionTokens == null) return null\n const pricing = models.find((m) => m.id === msg.modelUsed)?.pricing\n if (!pricing) return null\n const cost =\n (msg.promptTokens ?? 0) * Number(pricing.prompt ?? 0) +\n (msg.completionTokens ?? 0) * Number(pricing.completion ?? 0)\n if (!isFinite(cost) || cost <= 0) return null\n return cost < 0.01 ? `$${cost.toFixed(4)}` : `$${cost.toFixed(2)}`\n}\n\n/** \"38 tok/s\" from completion tokens over first-token→end duration; null when unknown. */\nexport function formatTokensPerSecond(msg: ChatMessageMetrics): string | null {\n if (msg.completionTokens == null || !msg.durationMs) return null\n return `${Math.round(msg.completionTokens / (msg.durationMs / 1000))} tok/s`\n}\n\n// ── Tool run drill-in (retained runs) ─────────────────────────────────────\n\n/** One step of a retained tool run (e.g. a sandbox command + its output). */\nexport interface ToolRunStep {\n at: string\n label: string\n detail?: string\n status?: 'ok' | 'error'\n}\n\n/** A retained tool run keyed by the parent message's toolCallId. The product\n * persists these server-side (fail-closed: only ids its own loop created)\n * and serves them to the drill-in panel. */\nexport interface ToolRunRecord {\n toolCallId: string\n toolName: string\n title: string\n status: 'running' | 'complete' | 'error'\n steps: ToolRunStep[]\n}\n\nexport interface RunDrillInProps {\n run: ToolRunRecord\n onClose: () => void\n}\n\n/**\n * Readonly side panel showing a retained tool run's transcript — the\n * \"drill into what the sandbox actually did\" view. Follow-ups happen in the\n * main chat, never here.\n */\nexport function RunDrillIn({ run, onClose }: RunDrillInProps) {\n return (\n <div className=\"fixed inset-y-0 right-0 z-50 flex w-[480px] max-w-full flex-col border-l border-border bg-card shadow-xl\">\n <div className=\"flex items-center gap-2 border-b border-border px-4 py-3\">\n <span\n className={`h-2 w-2 shrink-0 rounded-full ${\n run.status === 'running' ? 'bg-warning' : run.status === 'error' ? 'bg-destructive' : 'bg-success'\n }`}\n />\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-semibold\">{run.title}</p>\n <p className=\"truncate font-mono text-[11px] text-muted-foreground\">{run.toolName}</p>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n aria-label=\"Close\"\n className=\"rounded-md p-1.5 text-muted-foreground transition hover:bg-accent/30 hover:text-foreground\"\n >\n <svg className=\"h-4 w-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden>\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n </button>\n </div>\n <div className=\"flex-1 space-y-3 overflow-y-auto p-4\">\n {run.steps.length === 0 && (\n <p className=\"text-sm text-muted-foreground\">No steps recorded yet.</p>\n )}\n {run.steps.map((step, i) => (\n <div key={i} className=\"rounded-lg border border-border/60 bg-background\">\n <div className=\"flex items-baseline gap-2 border-b border-border/40 px-3 py-1.5\">\n <span className={`font-mono text-[11px] ${step.status === 'error' ? 'text-destructive' : 'text-muted-foreground'}`}>\n {step.status === 'error' ? '✗' : '$'}\n </span>\n <code className=\"min-w-0 flex-1 truncate font-mono text-xs\">{step.label}</code>\n <span className=\"shrink-0 text-[10px] text-muted-foreground\">\n {new Date(step.at).toLocaleTimeString()}\n </span>\n </div>\n {step.detail && (\n <pre className=\"max-h-48 overflow-auto whitespace-pre-wrap px-3 py-2 font-mono text-[11px] leading-relaxed text-muted-foreground\">\n {step.detail}\n </pre>\n )}\n </div>\n ))}\n </div>\n <p className=\"border-t border-border px-4 py-2 text-[11px] text-muted-foreground\">\n Readonly drill-in. Follow up in the main chat.\n </p>\n </div>\n )\n}\n\n// ── ChatMessages ──────────────────────────────────────────────────────────\n\nexport interface ChatToolCallInfo {\n id: string\n name: string\n status: 'running' | 'done' | 'error'\n /** The call arguments, captured from the tool_call event — shown in the\n * expanded card so users see exactly what the agent invoked. */\n args?: Record<string, unknown>\n /** The tool outcome (`{ok, result}` shape). When `result.status` is\n * 'queued_for_approval' the card renders the approval state. */\n result?: unknown\n}\n\n/** Extract `{proposalId, status}` from a tool outcome when it is a proposal\n * awaiting human approval; null otherwise. */\nexport function pendingApprovalOf(call: ChatToolCallInfo): { proposalId: string } | null {\n const outcome = call.result as { ok?: boolean; result?: { status?: string; proposalId?: string } } | undefined\n if (!outcome?.ok || outcome.result?.status !== 'queued_for_approval' || !outcome.result.proposalId) return null\n return { proposalId: outcome.result.proposalId }\n}\n\n/** One ordered piece of an assistant turn: a run of answer text, or a tool\n * call, in the sequence the agent emitted them. A message carrying `segments`\n * is rendered in order — interleaving text and tool chips — so the agent's\n * pre- and post-tool reasoning reads chronologically instead of as one text\n * blob with the tool chips collected after it. */\nexport type ChatMessageSegment =\n | { kind: 'text'; content: string }\n | { kind: 'tool'; call: ChatToolCallInfo }\n\nexport interface ChatUiMessage extends ChatMessageMetrics {\n id: string\n role: 'user' | 'assistant' | 'system'\n content: string\n reasoning?: string\n toolCalls?: ChatToolCallInfo[]\n /** Ordered text/tool sequence for true chronological interleaving. When\n * present and non-empty it is rendered in place of `content` + `toolCalls`;\n * both remain the fallback for producers that don't segment a turn. */\n segments?: ChatMessageSegment[]\n}\n\nexport interface ChatMessagesProps {\n messages: ChatUiMessage[]\n /** Catalogue models, for per-message cost from pricing. Pass [] to skip cost. */\n models?: CatalogModel[]\n /** Markdown renderer for assistant content; default renders pre-wrapped text. */\n renderMarkdown?: (content: string) => ReactNode\n /** Extra per-message content (artifacts, custom panels) appended after the body. */\n renderExtras?: (message: ChatUiMessage) => ReactNode\n userLabel?: string\n agentLabel?: string\n /** Render the trailing \"agent is thinking\" row. */\n loading?: boolean\n /** Approve/Reject handlers for proposals awaiting approval. When omitted the\n * chip still shows \"awaiting approval\" but without action buttons. */\n approval?: ProposalApprovalHandlers\n /** Open a full-transcript view (e.g. {@link RunDrillIn}) from a tool card. */\n onToolCallClick?: (call: ChatToolCallInfo, message: ChatUiMessage) => void\n /** Per-tool custom detail renderers for expanded tool cards. */\n toolRenderers?: ToolDetailRenderers\n /** Stream-error affordance: when the turn failed (a thrown transport error or\n * a loop-level `onErrorEvent`), pass the message here to render an error row.\n * A failed turn otherwise just stops with no UI signal. */\n error?: string | null\n /** Retry control shown on the error row; omit to render the error without a\n * retry button (e.g. when the product retries automatically). */\n onRetry?: () => void\n /** Zero-state renderer, shown when there are no messages and the turn is\n * neither loading nor errored. When omitted, a branded first-run state is\n * shown ({@link ChatEmptyState}); pass `() => null` to render nothing. */\n renderEmpty?: () => ReactNode\n /** First-run state config used when `renderEmpty` is not supplied. Lets a\n * product set the headline and the \"doors\" (e.g. start from a template, ask\n * the agent) without replacing the whole zero-state. */\n emptyState?: ChatEmptyStateProps\n /** Optional branded header slot rendered above the thread. Off by default to\n * preserve the current layout; pass `{ title }` (or your own node via\n * `header`) to show the Tangle mark + product title in the chat shell. */\n header?: ReactNode\n}\n\n/** One starting \"door\" in the chat first-run state — a concrete, labeled action\n * (start from a template, do it by hand, ask the agent), not a placeholder. */\nexport interface ChatEmptyDoor {\n label: string\n description?: string\n onSelect: () => void\n}\n\nexport interface ChatEmptyStateProps {\n /** Product name shown next to the Tangle mark. Default \"Agent\". */\n productName?: string\n /** Headline. Default frames delegation, not messaging. */\n headline?: string\n /** Subline under the headline. */\n subline?: string\n /** Up to three concrete starting doors. Omit for a mark-and-prompt-only state. */\n doors?: ChatEmptyDoor[]\n}\n\n/**\n * Branded chat first-run state: the Tangle mark, a delegation-framed prompt, and\n * up to three concrete doors. Replaces the blank thread that read as \"empty or\n * broken\". Concrete + actionable — never a \"coming soon\" placeholder.\n */\nexport function ChatEmptyState({\n productName = 'Agent',\n headline = 'Ask the agent to do something',\n subline = 'Describe the outcome you want. The agent works through it step by step, and pauses for your approval before anything irreversible.',\n doors,\n}: ChatEmptyStateProps) {\n return (\n <div className=\"mx-auto flex w-full max-w-2xl flex-col items-center px-6 py-12 text-center sm:py-20\">\n <span className=\"mb-5 inline-flex h-14 w-14 items-center justify-center rounded-2xl bg-primary/10 ring-1 ring-primary/15\">\n <BrandMark size={32} className=\"shrink-0\" />\n </span>\n <p className=\"text-[11px] font-semibold uppercase tracking-[0.18em] text-muted-foreground\">{productName}</p>\n <h2 className=\"mt-1.5 text-balance text-2xl font-semibold leading-tight text-foreground sm:text-[28px]\">\n {headline}\n </h2>\n {subline && <p className=\"mt-3 max-w-md text-[15px] leading-relaxed text-muted-foreground\">{subline}</p>}\n {doors && doors.length > 0 && (\n <div className=\"mt-7 grid w-full gap-2.5 sm:grid-cols-3\">\n {doors.slice(0, 3).map((door, i) => (\n <button\n key={i}\n type=\"button\"\n onClick={door.onSelect}\n className=\"group flex min-h-[44px] flex-col items-start rounded-xl border border-border bg-card px-4 py-3 text-left transition hover:border-primary/40 hover:bg-accent/30 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\"\n >\n <span className=\"text-sm font-semibold text-foreground\">{door.label}</span>\n {door.description && (\n <span className=\"mt-0.5 text-[12px] leading-snug text-muted-foreground\">{door.description}</span>\n )}\n </button>\n ))}\n </div>\n )}\n </div>\n )\n}\n\nexport interface ProposalApprovalHandlers {\n onApprove: (proposalId: string, toolCallId: string) => void | Promise<void>\n onReject: (proposalId: string, toolCallId: string) => void | Promise<void>\n}\n\n/** Per-tool custom detail renderers for the expanded card body — keyed by\n * tool name. Return null to fall back to the generic detail view. */\nexport type ToolDetailRenderers = Record<\n string,\n (call: ChatToolCallInfo, message: ChatUiMessage) => ReactNode\n>\n\nfunction ToolGlyph({ name, className }: { name: string; className?: string }) {\n if (name.startsWith('sandbox_')) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <polyline points=\"4 17 10 11 4 5\" />\n <line x1=\"12\" y1=\"19\" x2=\"20\" y2=\"19\" />\n </svg>\n )\n }\n if (name === 'submit_proposal') {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" />\n <path d=\"M14 2v6h6M9 15l2 2 4-4\" />\n </svg>\n )\n }\n if (name === 'schedule_followup') {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"M12 7v5l3 3\" />\n </svg>\n )\n }\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M12 3v3m0 12v3M3 12h3m12 0h3\" />\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n </svg>\n )\n}\n\nfunction toolOutcomeOf(call: ChatToolCallInfo): { ok?: boolean; result?: Record<string, unknown>; message?: string } | undefined {\n return call.result as { ok?: boolean; result?: Record<string, unknown>; message?: string } | undefined\n}\n\n/** The four visual kinds a tool call presents as. They are *different kinds of\n * thing* (audit chat finding #3/#4) and must read differently: a command is a\n * past-tense action, a proposal is a pending decision, a follow-up is a\n * scheduled intent, everything else is a generic tool step. Derived from the\n * tool name + outcome, never from baked domain values. */\ntype BlockKind = 'command' | 'proposal' | 'followup' | 'generic'\n\nfunction blockKindOf(call: ChatToolCallInfo): BlockKind {\n if (call.name === 'submit_proposal') return 'proposal'\n if (call.name === 'schedule_followup') return 'followup'\n if (call.name.startsWith('sandbox_')) return 'command'\n return 'generic'\n}\n\n/** Humanize an otherwise-unmapped tool name for display: `get_credit_balance`\n * → \"Get credit balance\". Splits on separators and camelCase, then sentence-\n * cases — domain-agnostic, so a host's tool reads as a label without this\n * shared renderer knowing that host's tool taxonomy. Falls back to the raw name\n * when there's nothing to humanize. */\nfunction humanizeToolName(name: string): string {\n const words = name\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .trim()\n if (!words) return name\n return words.charAt(0).toUpperCase() + words.slice(1)\n}\n\n/** Human title for a call, derived from its real arguments. Proposals lead with\n * the decision verb (docs/product-surfaces.md) rather than the internal tool\n * taxonomy, so the user reads \"Approve: publish …?\" not \"submit_proposal\". An\n * unmapped tool falls back to its humanized name rather than the raw slug. */\nfunction friendlyToolTitle(call: ChatToolCallInfo): string {\n const a = call.args ?? {}\n switch (call.name) {\n case 'submit_proposal':\n return a.title ? `Approve: ${String(a.title)}?` : 'Approve this action?'\n case 'sandbox_create':\n return `Created sandbox (${String(a.environment ?? 'universal')})`\n case 'sandbox_run_command':\n return `Ran ${String(a.command ?? 'command')}`\n case 'sandbox_destroy':\n return `Destroyed sandbox ${String(a.sandbox_id ?? '')}`\n case 'schedule_followup':\n return `Scheduled: ${String(a.title ?? 'follow-up')}`\n case 'render_ui':\n return `Rendered view · ${String(a.title ?? '')}`\n case 'add_citation':\n return `Cited ${String(a.path ?? '')}`\n default:\n return humanizeToolName(call.name)\n }\n}\n\n/** A one-line, plain-English preview of WHAT a proposal will do, assembled from\n * the proposal's real arguments (audit chat finding #2 — \"approving a black box\n * is the fastest way to lose trust\"). Domain stays a parameter: we only read\n * conventional fields (destinations/targets/channels, cost, reach) when present\n * — nothing here is baked to a specific product's proposal type. Returns null\n * when there's nothing meaningful to preview. */\nfunction proposalPreview(call: ChatToolCallInfo): { summary: string | null; meta: string[] } {\n const a = (call.args ?? {}) as Record<string, unknown>\n const asString = (v: unknown): string | null =>\n typeof v === 'string' && v.trim() ? v.trim() : null\n const asList = (v: unknown): string[] =>\n Array.isArray(v)\n ? v.map((x) => (typeof x === 'string' ? x : null)).filter((x): x is string => !!x)\n : asString(v)\n ? [asString(v) as string]\n : []\n\n // The verb: a free-form summary the agent wrote, else derive from type.\n const verbPhrase =\n asString(a.summary) ??\n asString(a.description) ??\n (asString(a.type)\n ? `${String(a.type).replace(/_/g, ' ')}${asString(a.title) ? `: ${asString(a.title)}` : ''}`\n : null)\n\n const destinations = [\n ...asList(a.destinations),\n ...asList(a.channels),\n ...asList(a.targets),\n ...asList(a.platforms),\n ]\n const dest = destinations.length ? ` to ${destinations.join(' and ')}` : ''\n const summary = verbPhrase ? `${verbPhrase}${dest}` : destinations.length ? `Publish to ${destinations.join(' and ')}` : null\n\n // Cost / reach: surfaced when the data carries it, formatted lightly.\n const meta: string[] = []\n const cost = a.cost ?? a.price ?? a.estimatedCost\n if (typeof cost === 'number' && cost > 0) meta.push(`~$${cost < 0.01 ? cost.toFixed(4) : cost.toFixed(2)}`)\n else if (asString(cost)) meta.push(asString(cost) as string)\n const reach = a.reach ?? a.audience ?? a.estimatedReach\n if (typeof reach === 'number' && reach > 0) meta.push(`reaches ~${reach.toLocaleString()}`)\n else if (asString(reach)) meta.push(asString(reach) as string)\n\n return { summary, meta }\n}\n\nfunction truncate(v: unknown, max = 240): string {\n const s = typeof v === 'string' ? v : JSON.stringify(v)\n return s.length > max ? `${s.slice(0, max)}…` : s\n}\n\nfunction KvRows({ data }: { data: Record<string, unknown> }) {\n const entries = Object.entries(data).filter(([, v]) => v !== undefined && v !== null && v !== '')\n if (!entries.length) return null\n return (\n <dl className=\"grid grid-cols-[auto_1fr] gap-x-3 gap-y-1\">\n {entries.map(([k, v]) => (\n <div key={k} className=\"contents\">\n <dt className=\"font-mono text-[11px] text-muted-foreground\">{k}</dt>\n <dd className=\"min-w-0 whitespace-pre-wrap break-words font-mono text-[11px] text-muted-foreground\">\n {truncate(v)}\n </dd>\n </div>\n ))}\n </dl>\n )\n}\n\n/** Terminal-styled rendering for shell executions. */\nfunction ShellDetail({ call }: { call: ChatToolCallInfo }) {\n const outcome = toolOutcomeOf(call)\n const r = (outcome?.result ?? {}) as { stdout?: string; stderr?: string; exitCode?: number }\n return (\n <div className=\"overflow-hidden rounded-md bg-zinc-900 font-mono text-[11px] leading-relaxed\">\n <div className=\"flex items-center gap-2 px-3 pt-2 text-zinc-400\">\n <span className=\"select-none text-zinc-500\">$</span>\n <span className=\"min-w-0 flex-1 truncate text-zinc-200\">{String(call.args?.command ?? '')}</span>\n {r.exitCode != null && (\n <span className={r.exitCode === 0 ? 'text-success' : 'text-destructive'}>exit {r.exitCode}</span>\n )}\n </div>\n <pre className=\"max-h-56 overflow-auto whitespace-pre-wrap px-3 pb-2.5 pt-1.5 text-zinc-300\">\n {outcome?.ok === false ? (outcome.message ?? 'failed') : [r.stdout, r.stderr].filter(Boolean).join('\\n') || '(no output)'}\n </pre>\n </div>\n )\n}\n\n/** Generic expanded detail: what was called, and what actually happened. */\nfunction DefaultToolDetail({ call }: { call: ChatToolCallInfo }) {\n const outcome = toolOutcomeOf(call)\n return (\n <div className=\"space-y-2\">\n {call.args && Object.keys(call.args).length > 0 && (\n <div>\n <p className=\"mb-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground\">Called with</p>\n <KvRows data={call.args} />\n </div>\n )}\n {outcome && (\n <div>\n <p className=\"mb-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground\">\n {outcome.ok === false ? 'Failed' : 'Result'}\n </p>\n {outcome.ok === false ? (\n <p className=\"text-xs text-destructive\">{outcome.message ?? 'Tool failed'}</p>\n ) : outcome.result && typeof outcome.result === 'object' ? (\n <KvRows data={outcome.result} />\n ) : (\n <p className=\"font-mono text-[11px] text-muted-foreground\">{truncate(outcome.result)}</p>\n )}\n </div>\n )}\n </div>\n )\n}\n\n/** The pending-decision card. The single highest-leverage surface in the repo\n * (audit chat finding #1, critical): Approve is the affirmative path — filled,\n * brand-colored, primary — and Reject is quiet/outline, so a user never reads\n * both labels twice to know the safe action. Carries a plain-English preview of\n * WHAT it will do (#2). `onApprove`/`onReject` are unchanged. */\nfunction ProposalCard({\n call,\n message,\n pending,\n approval,\n renderers,\n}: {\n call: ChatToolCallInfo\n message: ChatUiMessage\n pending: { proposalId: string }\n approval?: ProposalApprovalHandlers\n renderers?: ToolDetailRenderers\n}) {\n const [expanded, setExpanded] = useState(false)\n const { summary, meta } = proposalPreview(call)\n const custom = renderers?.[call.name]?.(call, message)\n const { pending: deciding, run: decide } = usePending()\n\n return (\n <div className=\"w-full max-w-full rounded-xl border border-warning/50 bg-warning/[0.06] text-sm shadow-sm ring-1 ring-warning/10\">\n <div className=\"flex items-start gap-2.5 px-4 pt-3.5\">\n <span className=\"mt-0.5 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-warning/15 text-warning\">\n <ToolGlyph name={call.name} className=\"h-3.5 w-3.5\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-[10px] font-semibold uppercase tracking-wider text-warning-foreground\">Needs your approval</p>\n <p className=\"mt-0.5 text-[15px] font-semibold leading-snug text-foreground\">{friendlyToolTitle(call)}</p>\n {summary && <p className=\"mt-1 text-[13px] leading-relaxed text-muted-foreground\">{summary}</p>}\n {meta.length > 0 && (\n <div className=\"mt-1.5 flex flex-wrap items-center gap-1.5\">\n {meta.map((m, i) => (\n <span key={i} className=\"rounded-full bg-muted/60 px-2 py-0.5 text-[11px] font-medium text-muted-foreground\">\n {m}\n </span>\n ))}\n </div>\n )}\n </div>\n </div>\n <div className=\"flex flex-wrap items-center gap-2 px-4 pb-3.5 pt-3\">\n {approval ? (\n <>\n <button\n type=\"button\"\n disabled={deciding}\n onClick={() => decide(() => approval.onApprove(pending.proposalId, call.id))}\n className=\"inline-flex min-h-[40px] flex-1 items-center justify-center rounded-lg bg-primary px-4 py-2 text-sm font-semibold text-primary-foreground shadow-sm transition hover:bg-primary/90 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-card disabled:cursor-not-allowed disabled:opacity-60 sm:flex-none sm:min-w-[160px]\"\n >\n Approve &amp; run\n </button>\n <button\n type=\"button\"\n disabled={deciding}\n onClick={() => decide(() => approval.onReject(pending.proposalId, call.id))}\n className=\"inline-flex min-h-[40px] items-center justify-center rounded-lg border border-border bg-transparent px-4 py-2 text-sm font-medium text-muted-foreground transition hover:bg-accent/30 hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-card disabled:cursor-not-allowed disabled:opacity-60\"\n >\n Reject\n </button>\n </>\n ) : (\n <span className=\"text-[12px] font-medium text-muted-foreground\">Awaiting approval…</span>\n )}\n <button\n type=\"button\"\n onClick={() => setExpanded((v) => !v)}\n aria-expanded={expanded}\n className=\"ml-auto inline-flex items-center gap-1 rounded text-[12px] font-medium text-muted-foreground transition hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n {expanded ? 'Hide details' : 'View details'}\n <ChevronDown className={`h-3 w-3 transition-transform ${expanded ? 'rotate-180' : ''}`} />\n </button>\n </div>\n {expanded && (\n <div className=\"border-t border-warning/20 px-4 py-3 text-xs\">\n {custom ?? <DefaultToolDetail call={call} />}\n </div>\n )}\n </div>\n )\n}\n\n/** A scheduled follow-up — a pending, time-based intent, not a decision and not\n * a completed action (audit finding #5). Quiet left-rule card with a clock. */\nfunction FollowupCard({ call }: { call: ChatToolCallInfo }) {\n const a = (call.args ?? {}) as Record<string, unknown>\n const when = typeof a.when === 'string' ? a.when : typeof a.at === 'string' ? a.at : typeof a.schedule === 'string' ? a.schedule : null\n return (\n <div className=\"w-fit min-w-[260px] max-w-full rounded-lg border border-border/60 border-l-2 border-l-primary/60 bg-muted/20 px-3 py-2 text-sm\">\n <div className=\"flex items-center gap-2\">\n <ToolGlyph name={call.name} className=\"h-3.5 w-3.5 shrink-0 text-primary/80\" />\n <span className=\"min-w-0 flex-1 truncate font-medium text-foreground\">{friendlyToolTitle(call)}</span>\n </div>\n {when && <p className=\"mt-0.5 pl-[22px] text-[12px] text-muted-foreground\">{when}</p>}\n </div>\n )\n}\n\nfunction ToolCallCard({\n call,\n message,\n approval,\n onOpenRun,\n renderers,\n}: {\n call: ChatToolCallInfo\n message: ChatUiMessage\n approval?: ProposalApprovalHandlers\n onOpenRun?: (call: ChatToolCallInfo, message: ChatUiMessage) => void\n renderers?: ToolDetailRenderers\n}) {\n const [expanded, setExpanded] = useState(false)\n const pending = call.status === 'done' ? pendingApprovalOf(call) : null\n const kind = blockKindOf(call)\n const failed = call.status === 'error' || toolOutcomeOf(call)?.ok === false\n const custom = renderers?.[call.name]?.(call, message)\n\n // A proposal awaiting approval is a pending DECISION, not a tool chip — it\n // gets its own prominent card with primary Approve / quiet Reject.\n if (pending) {\n return (\n <ProposalCard\n call={call}\n message={message}\n pending={pending}\n approval={approval}\n renderers={renderers}\n />\n )\n }\n // A scheduled follow-up is a time-based intent — distinct from a tool chip.\n if (kind === 'followup' && !failed) {\n return <FollowupCard call={call} />\n }\n\n // A command chip reads as a past-tense action; its command text is monospace\n // (audit finding #1 minor). Everything else is a generic tool step. Both share\n // one card shape so the transcript reads as a worklog, not a flat list.\n const isCommand = kind === 'command'\n return (\n <div\n className={`w-fit min-w-[280px] max-w-full rounded-lg border text-xs transition ${\n failed ? 'border-destructive/40 bg-destructive/5' : 'border-border/60 bg-muted/20'\n }`}\n >\n {/* Header is a flex row, NOT a button, so any controls are siblings of the\n expand toggle rather than nested inside it (axe: nested-interactive). */}\n <div className=\"flex w-full items-center gap-2 px-3 py-2\">\n <button\n type=\"button\"\n onClick={() => setExpanded((v) => !v)}\n aria-expanded={expanded}\n className=\"flex min-w-0 flex-1 items-center gap-2 rounded text-left focus:outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <span\n className={`h-2 w-2 shrink-0 rounded-full ${\n call.status === 'running' ? 'animate-pulse bg-warning' : failed ? 'bg-destructive' : 'bg-success'\n }`}\n />\n <ToolGlyph name={call.name} className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span\n className={`min-w-0 flex-1 truncate ${\n isCommand ? 'font-mono text-[12px] tracking-tight text-foreground/90' : 'font-medium'\n }`}\n >\n {friendlyToolTitle(call)}\n </span>\n </button>\n <span className=\"shrink-0 text-[11px] text-muted-foreground\">\n {call.status === 'running' ? 'running…' : failed ? 'failed' : 'done'}\n </span>\n <button\n type=\"button\"\n onClick={() => setExpanded((v) => !v)}\n aria-label={expanded ? 'Collapse details' : 'Expand details'}\n aria-expanded={expanded}\n className=\"shrink-0 rounded p-0.5 focus:outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <ChevronDown className={`h-3 w-3 text-muted-foreground transition-transform ${expanded ? 'rotate-180' : ''}`} />\n </button>\n </div>\n {expanded && (\n <div className=\"border-t border-border/40 px-3 py-2.5\">\n {custom ?? (call.name === 'sandbox_run_command' ? <ShellDetail call={call} /> : <DefaultToolDetail call={call} />)}\n {onOpenRun && call.name.startsWith('sandbox_') && (\n <button\n type=\"button\"\n onClick={() => onOpenRun(call, message)}\n className=\"mt-2 rounded border border-border bg-card px-2 py-1 text-[11px] font-medium transition hover:bg-accent/30\"\n >\n Open full transcript →\n </button>\n )}\n </div>\n )}\n </div>\n )\n}\n\n/** The blinking insertion caret shown at the end of streaming answer text.\n * Shared by the segmented and legacy branches so their streaming cue can't\n * visually diverge. */\nfunction StreamingCaret() {\n return (\n <span\n className=\"ml-0.5 inline-block h-[1.1em] w-[3px] translate-y-[2px] animate-pulse rounded-sm bg-foreground/70\"\n aria-hidden\n />\n )\n}\n\n/** One text run inside a segmented turn. Smooths its own text so only the\n * actively-streaming trailing run types out; finalized runs render at once.\n * A child component (not an inline map) so its `useSmoothText` state is stable\n * across the parent's per-frame stream re-renders. */\nfunction SegmentText({\n content,\n streaming,\n showCaret,\n renderBody,\n}: {\n content: string\n streaming: boolean\n showCaret: boolean\n renderBody: (content: string) => ReactNode\n}) {\n const text = useSmoothText(content, streaming)\n const body = useMemo(() => renderBody(text), [renderBody, text])\n // An empty / whitespace-only run paints a blank line-height gap — render\n // nothing, UNLESS it's the live trailing run (showCaret), where it still\n // carries the caret so the turn doesn't look frozen. (Hooks run first, so\n // this stays rules-of-hooks safe.)\n if (!content.trim() && !showCaret) return null\n return (\n <div className=\"text-base leading-[1.75]\">\n {body}\n {/* Gate on showCaret (not the smoothed `text`, which is '' on the first\n frame) so the caret is steady from the start instead of flickering. */}\n {showCaret && <StreamingCaret />}\n </div>\n )\n}\n\n/** Renders a turn's ordered text/tool segments interleaved. The trailing text\n * run carries the streaming caret; if the last segment is instead a tool, a\n * trailing caret keeps the gap before the next run from looking frozen. Any\n * `toolCalls` not represented in `segments` (a partially-migrated producer that\n * set both) still render, so a tool chip is never silently dropped. */\nfunction SegmentedBody({\n segments,\n msg,\n streaming,\n renderBody,\n approval,\n onToolCallClick,\n toolRenderers,\n}: {\n segments: ChatMessageSegment[]\n msg: ChatUiMessage\n streaming: boolean\n renderBody: (content: string) => ReactNode\n approval?: ProposalApprovalHandlers\n onToolCallClick?: (call: ChatToolCallInfo, message: ChatUiMessage) => void\n toolRenderers?: ToolDetailRenderers\n}) {\n const lastIndex = segments.length - 1\n const segmentToolIds = new Set(\n segments.flatMap((s) => (s.kind === 'tool' ? [s.call.id] : [])),\n )\n const leftoverToolCalls = (msg.toolCalls ?? []).filter(\n (tc) => !segmentToolIds.has(tc.id),\n )\n const renderToolCard = (call: ChatToolCallInfo) => (\n <ToolCallCard\n key={`tool-${call.id}`}\n call={call}\n message={msg}\n approval={approval}\n onOpenRun={onToolCallClick}\n renderers={toolRenderers}\n />\n )\n return (\n <div className=\"flex flex-col gap-2\">\n {segments.map((seg, i) =>\n seg.kind === 'text' ? (\n <SegmentText\n // Segments only ever append within a turn, so the index is a stable\n // key — a finalized run keeps its slot as later runs/tools are added,\n // so its smooth-text state isn't reset.\n key={`text-${i}`}\n content={seg.content}\n // Only the trailing run of the live turn types out + shows the caret.\n streaming={streaming && i === lastIndex}\n showCaret={streaming && i === lastIndex}\n renderBody={renderBody}\n />\n ) : (\n renderToolCard(seg.call)\n ),\n )}\n {leftoverToolCalls.map(renderToolCard)}\n {streaming && segments[lastIndex]?.kind === 'tool' && <StreamingCaret />}\n </div>\n )\n}\n\nfunction AssistantMessageImpl({\n msg,\n streaming,\n models,\n agentLabel,\n renderBody,\n approval,\n onToolCallClick,\n toolRenderers,\n renderExtras,\n}: {\n msg: ChatUiMessage\n streaming: boolean\n models: CatalogModel[]\n agentLabel: string\n renderBody: (content: string) => ReactNode\n approval?: ProposalApprovalHandlers\n onToolCallClick?: (call: ChatToolCallInfo, message: ChatUiMessage) => void\n toolRenderers?: ToolDetailRenderers\n renderExtras?: (message: ChatUiMessage) => ReactNode\n}) {\n // Smooth reveal: chunky network slabs (model bursts, flush windows, replay\n // polls) paint as a continuous typewriter. Reasoning often arrives as one\n // burst right before the answer — smoothing makes it visibly type out in\n // the open thinking box instead of popping in and collapsing.\n const content = useSmoothText(msg.content, streaming)\n const reasoning = useSmoothText(msg.reasoning ?? '', streaming)\n // The smooth reveal re-renders on every rAF frame while streaming, but the\n // FLOORED visible length only advances every few frames — re-parsing markdown\n // each frame is wasted work on the hot path. Memo on (renderBody, content) so\n // the parse runs only when the visible text actually changes.\n const body = useMemo(() => renderBody(content), [renderBody, content])\n // When a turn is segmented, render the ordered text/tool runs interleaved;\n // otherwise fall back to the single content body + trailing tool group.\n const segments = msg.segments\n // \"Has the answer started?\" — true once any answer text exists, whether the\n // producer puts it in `content` (legacy) or in a text `segment`. Drives the\n // reasoning box (open while still thinking, the thinking timer, the summary\n // label), so a segmented message with `content: ''` doesn't read as\n // perpetually \"Thinking…\" after its answer segments are visible.\n const hasAnswerText =\n content !== '' ||\n (segments?.some((s) => s.kind === 'text' && s.content.trim() !== '') ??\n false)\n const reasoningScrollRef = useRef<HTMLDivElement>(null)\n // Measure visible thinking time: first reasoning reveal → first answer text.\n const thinkStartRef = useRef<number | null>(null)\n const thinkMsRef = useRef<number | null>(null)\n if (streaming && reasoning && !hasAnswerText && thinkStartRef.current === null) {\n thinkStartRef.current = performance.now()\n }\n if (\n hasAnswerText &&\n thinkStartRef.current !== null &&\n thinkMsRef.current === null\n ) {\n thinkMsRef.current = performance.now() - thinkStartRef.current\n }\n useEffect(() => {\n const el = reasoningScrollRef.current\n if (el && streaming && !hasAnswerText) el.scrollTop = el.scrollHeight\n }, [reasoning, streaming, hasAnswerText])\n // Live seconds while the model is reasoning before its answer starts, so a\n // long thinking gap shows progress rather than a static \"Thinking…\".\n const thinkingSeconds = useThinkingSeconds(\n streaming && !!reasoning && !hasAnswerText,\n )\n\n return (\n <div className=\"mx-auto w-full max-w-3xl px-6 py-3\">\n <div className=\"mb-1 flex items-baseline gap-2 text-[11px] tracking-wide text-muted-foreground\">\n <span className=\"font-semibold uppercase\">{agentLabel}</span>\n {msg.modelUsed && <span className=\"font-mono normal-case\">{msg.modelUsed}</span>}\n {formatTokensPerSecond(msg) && <span>{formatTokensPerSecond(msg)}</span>}\n {formatModelCost(msg, models) && <span>{formatModelCost(msg, models)}</span>}\n </div>\n {reasoning && (\n <details className=\"mb-2 rounded-lg border-l-2 border-border/70 bg-muted/20 px-3 py-2\" open={!hasAnswerText}>\n <summary className=\"cursor-pointer select-none text-xs font-medium text-muted-foreground\">\n {!hasAnswerText ? (\n <span className=\"animate-pulse\">\n Thinking{thinkingSeconds >= 3 ? ` · ${thinkingSeconds}s` : '…'}\n </span>\n ) : thinkMsRef.current != null ? (\n `Thought for ${Math.max(1, Math.round(thinkMsRef.current / 1000))}s`\n ) : (\n 'Thought process'\n )}\n </summary>\n <div ref={reasoningScrollRef} className=\"mt-2 max-h-48 overflow-y-auto whitespace-pre-wrap text-[13px] leading-relaxed text-muted-foreground\">\n {reasoning}\n </div>\n </details>\n )}\n {segments && segments.length > 0 ? (\n <SegmentedBody\n segments={segments}\n msg={msg}\n streaming={streaming}\n renderBody={renderBody}\n approval={approval}\n onToolCallClick={onToolCallClick}\n toolRenderers={toolRenderers}\n />\n ) : (\n <>\n <div className=\"text-base leading-[1.75]\">\n {body}\n {streaming && content && !msg.toolCalls?.length && <StreamingCaret />}\n </div>\n {msg.toolCalls && msg.toolCalls.length > 0 && (\n <div className=\"mt-2 flex flex-col gap-1.5\">\n {msg.toolCalls.map((tc) => (\n <ToolCallCard\n key={tc.id}\n call={tc}\n message={msg}\n approval={approval}\n onOpenRun={onToolCallClick}\n renderers={toolRenderers}\n />\n ))}\n </div>\n )}\n </>\n )}\n {renderExtras?.(msg)}\n </div>\n )\n}\n\n/**\n * Only the actively-streaming message changes per frame; historical messages\n * are referentially stable. `memo` keeps a stable `AssistantMessage` from\n * re-rendering (and re-running its markdown parse) when a sibling streams —\n * default shallow-equal prop comparison is exactly right here since every prop\n * is referentially stable except the one being streamed.\n */\nconst AssistantMessage = memo(AssistantMessageImpl)\n\n/** Whole seconds elapsed while `active`, ticking once a second. Powers the live\n * \"thinking\" timers (the pre-first-token row and the reasoning box) so a long\n * thinking gap shows progress instead of a frozen label. Counts from when\n * `active` first turns true; freezes when it clears. */\nexport function useThinkingSeconds(active: boolean): number {\n const [seconds, setSeconds] = useState(0)\n useEffect(() => {\n if (!active) return\n // Reset on each (re)activation so a reused component resuming \"thinking\"\n // counts from 0 rather than showing the prior phase's stale elapsed time.\n setSeconds(0)\n const id = setInterval(() => setSeconds((s) => s + 1), 1000)\n return () => clearInterval(id)\n }, [active])\n return seconds\n}\n\nfunction ThinkingRow({ agentLabel }: { agentLabel: string }) {\n const seconds = useThinkingSeconds(true)\n return (\n <div className=\"mx-auto w-full max-w-3xl px-6 py-3\">\n <p className=\"mb-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground\">{agentLabel}</p>\n <div className=\"flex items-center gap-2 text-base text-muted-foreground\">\n <svg className=\"h-4 w-4 animate-spin\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" aria-hidden>\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" strokeLinecap=\"round\" />\n </svg>\n Thinking{seconds >= 3 ? ` · ${seconds}s` : '...'}\n </div>\n </div>\n )\n}\n\n/** Top-level turn-failure row with an optional Retry — the affordance a failed\n * stream otherwise lacks (the turn just stopped). */\nfunction StreamErrorRow({ message, onRetry }: { message: string; onRetry?: () => void }) {\n return (\n <div className=\"mx-auto w-full max-w-3xl px-6 py-3\">\n <div role=\"alert\" className=\"flex items-start gap-2.5 rounded-lg border border-destructive/40 bg-destructive/5 px-3 py-2.5 text-sm text-destructive\">\n <svg className=\"mt-0.5 h-4 w-4 shrink-0\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"M12 8v4m0 4h.01\" />\n </svg>\n <span className=\"min-w-0 flex-1 break-words\">{message}</span>\n {onRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n className={`shrink-0 rounded border border-destructive/40 bg-card px-2 py-0.5 text-[11px] font-medium text-destructive transition hover:bg-destructive/10 ${POPOVER_OPTION_FOCUS}`}\n >\n Retry\n </button>\n )}\n </div>\n </div>\n )\n}\n\n/**\n * The message thread: one centered column; user messages are right-aligned\n * bubbles with a User label; agent messages carry an Agent meta line with\n * model id, tokens/sec, and cost, plus a collapsible thinking section and\n * tool-call chips.\n */\nexport function ChatMessages({\n messages,\n models = [],\n renderMarkdown,\n renderExtras,\n userLabel = 'User',\n agentLabel = 'Agent',\n loading,\n approval,\n onToolCallClick,\n toolRenderers,\n error,\n onRetry,\n renderEmpty,\n emptyState,\n header,\n}: ChatMessagesProps) {\n // Stabilize the fallback renderer's identity so it doesn't change every\n // render — otherwise the memoized `AssistantMessage` (and its per-frame body\n // memo) would invalidate on every parent render when no `renderMarkdown` is\n // supplied.\n const renderBody = useMemo(\n () => renderMarkdown ?? ((content: string) => <p className=\"whitespace-pre-wrap\">{content}</p>),\n [renderMarkdown],\n )\n const lastIsUser = messages[messages.length - 1]?.role === 'user'\n if (messages.length === 0 && !loading && !error) {\n // Explicit renderEmpty wins (incl. `() => null` to opt out); otherwise show\n // the branded first-run state instead of a blank thread.\n const empty = renderEmpty ? renderEmpty() : <ChatEmptyState {...emptyState} />\n return (\n <>\n {header}\n {empty}\n </>\n )\n }\n return (\n <>\n {header}\n {messages.map((msg) =>\n msg.role === 'user' ? (\n <div key={msg.id} className=\"mx-auto w-full max-w-3xl px-6 py-3\">\n <div className=\"ml-auto w-fit max-w-[85%]\">\n <p className=\"mb-1 text-right text-[11px] font-semibold uppercase tracking-wide text-muted-foreground\">\n {userLabel}\n </p>\n <div className=\"rounded-2xl rounded-tr-md bg-primary/10 px-4 py-2.5 text-base leading-relaxed\">\n <p className=\"whitespace-pre-wrap\">{msg.content}</p>\n </div>\n </div>\n </div>\n ) : (\n <AssistantMessage\n key={msg.id}\n msg={msg}\n streaming={!!loading && msg.id === messages[messages.length - 1]?.id}\n models={models}\n agentLabel={agentLabel}\n renderBody={renderBody}\n approval={approval}\n onToolCallClick={onToolCallClick}\n toolRenderers={toolRenderers}\n renderExtras={renderExtras}\n />\n ),\n )}\n {loading && lastIsUser && <ThinkingRow agentLabel={agentLabel} />}\n {error && !loading && <StreamErrorRow message={error} onRetry={onRetry} />}\n </>\n )\n}\n","/**\n * Smooth text reveal — turns chunky network deltas into a continuous\n * typewriter paint. Streamed turns arrive in 100-500ms slabs (model burst,\n * flush windows, replay polls); revealing characters at an adaptive rate\n * makes the same bytes read as top-tier streaming. The rate scales with the\n * backlog so the reveal never falls behind the stream — it crawls when caught\n * up and sprints when a burst lands (e.g. a reasoning summary arriving all at\n * once still *types out* instead of popping in).\n */\n\nimport { useEffect, useRef, useState } from 'react'\n\nexport interface SmoothRevealOptions {\n /** Baseline reveal rate when nearly caught up. Default 90 chars/s. */\n baseCharsPerSecond?: number\n /** Extra chars/s per backlog character — the catch-up pressure. Default 5. */\n catchUpPerChar?: number\n /** Hard ceiling so giant bursts still animate. Default 2400 chars/s. */\n maxCharsPerSecond?: number\n}\n\n/** Pure reveal step: how many characters should be visible after `dtMs`.\n * Exposed for tests; the hook is a thin rAF wrapper around it. */\nexport function nextRevealCount(\n shown: number,\n targetLength: number,\n dtMs: number,\n opts: SmoothRevealOptions = {},\n): number {\n if (shown >= targetLength) return targetLength\n const base = opts.baseCharsPerSecond ?? 90\n const catchUp = opts.catchUpPerChar ?? 5\n const max = opts.maxCharsPerSecond ?? 2400\n const backlog = targetLength - shown\n const rate = Math.min(max, base + backlog * catchUp)\n return Math.min(targetLength, shown + (rate * dtMs) / 1000)\n}\n\n/**\n * Animate `target` text into view. While `enabled`, the returned string grows\n * smoothly toward `target` (which may itself keep growing); when `enabled` is\n * false the full text returns immediately (history, completed turns). A\n * target that is not an extension of the revealed prefix (new message) resets\n * the reveal.\n */\nexport function useSmoothText(target: string, enabled: boolean, opts?: SmoothRevealOptions): string {\n const [, force] = useState(0)\n const shownRef = useRef(0)\n const lastTargetRef = useRef('')\n\n // New message / rewritten prefix → restart the reveal from zero.\n if (!target.startsWith(lastTargetRef.current.slice(0, Math.floor(shownRef.current)))) {\n shownRef.current = 0\n }\n lastTargetRef.current = target\n if (!enabled) shownRef.current = target.length\n\n useEffect(() => {\n if (!enabled) return\n let raf = 0\n let last: number | null = null\n const tick = (t: number) => {\n const dt = last == null ? 16 : Math.min(t - last, 100)\n last = t\n const targetLen = lastTargetRef.current.length\n if (shownRef.current < targetLen) {\n shownRef.current = nextRevealCount(shownRef.current, targetLen, dt, opts)\n force((n) => n + 1)\n // Keep painting while there is still backlog to reveal.\n raf = requestAnimationFrame(tick)\n }\n // Caught up: stop the loop. A later `target` growth re-renders this hook\n // (target is read fresh below), and the next render's effect — re-run\n // because `target` is a dep — restarts the loop. Idle messages spawn no\n // rAF, so a full thread of completed turns is dormant.\n }\n raf = requestAnimationFrame(tick)\n return () => cancelAnimationFrame(raf)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, target])\n\n return target.slice(0, Math.floor(shownRef.current))\n}\n","/**\n * Shared chat-shell control primitives — the LEAF that both the web-react barrel\n * (`./index`) and the composer children (`./agent-session-controls`,\n * `./seat-paywall`) import directly, so neither child has to reach back through\n * the barrel (which would re-create an import cycle). The barrel re-exports the\n * public names (`usePopover`, `usePending`, `ModelPicker`, `EffortPicker`, …)\n * unchanged, so the published export surface is identical.\n *\n * Styling contract matches the rest of `web-react`: Tailwind classes against the\n * shared design tokens; the glyphs are inline SVGs, no icon-library dependency.\n */\n\nimport { useEffect, useMemo, useRef, useState, type ReactNode } from 'react'\nimport { ProviderLogo } from './provider-logo'\nimport type { CatalogModel } from '../runtime/model-catalog'\n\n// ── shared glyphs (no icon-library dependency) ────────────────────────────\n\nexport function ChevronDown({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n )\n}\n\nexport function SearchGlyph({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.3-4.3\" />\n </svg>\n )\n}\n\nexport function SparkleGlyph({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M12 3v3m0 12v3M3 12h3m12 0h3M5.6 5.6l2.1 2.1m8.6 8.6 2.1 2.1m0-12.8-2.1 2.1M7.7 16.3l-2.1 2.1\" />\n </svg>\n )\n}\n\n/**\n * Keyboard + pointer model for a trigger-and-popover pair, dependency-free.\n * Outside-mousedown and Escape both close; Escape also returns focus to the\n * trigger so keyboard users aren't dropped at the top of the document. The\n * returned `triggerProps` carry the ARIA contract (`aria-haspopup`/\n * `aria-expanded`); spread them onto the trigger button.\n */\nexport function usePopover(open: boolean, setOpen: (open: boolean) => void) {\n const containerRef = useRef<HTMLDivElement>(null)\n const triggerRef = useRef<HTMLButtonElement>(null)\n\n useEffect(() => {\n if (!open) return\n function onMouseDown(e: MouseEvent) {\n if (containerRef.current && !containerRef.current.contains(e.target as Node)) setOpen(false)\n }\n function onKeyDown(e: KeyboardEvent) {\n if (e.key === 'Escape') {\n setOpen(false)\n triggerRef.current?.focus()\n }\n }\n document.addEventListener('mousedown', onMouseDown)\n document.addEventListener('keydown', onKeyDown)\n return () => {\n document.removeEventListener('mousedown', onMouseDown)\n document.removeEventListener('keydown', onKeyDown)\n }\n }, [open, setOpen])\n\n return {\n containerRef,\n triggerRef,\n triggerProps: {\n ref: triggerRef,\n 'aria-haspopup': true as const,\n 'aria-expanded': open,\n },\n }\n}\n\n/** Tailwind utilities applied to every popover option so keyboard focus is\n * visible (the prior buttons had no focus ring). */\nexport const POPOVER_OPTION_FOCUS =\n 'focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-card'\n\n/**\n * Guard an async action against double-submit. `run` ignores re-entrant calls\n * while a promise is in flight and flips `pending` so the caller can disable\n * the control — the fix for double-charge / double-approve on a slow network.\n * Settles (success or throw) before clearing, and no-ops state updates after\n * unmount.\n */\nexport function usePending(): { pending: boolean; run: (action: () => void | Promise<void>) => void } {\n const [pending, setPending] = useState(false)\n const inFlight = useRef(false)\n const mounted = useRef(true)\n useEffect(() => {\n mounted.current = true\n return () => {\n mounted.current = false\n }\n }, [])\n const run = (action: () => void | Promise<void>) => {\n if (inFlight.current) return\n let result: void | Promise<void>\n try {\n result = action()\n } catch {\n return\n }\n if (!(result instanceof Promise)) return\n inFlight.current = true\n setPending(true)\n void result.finally(() => {\n inFlight.current = false\n if (mounted.current) setPending(false)\n })\n }\n return { pending, run }\n}\n\n// ── ModelPicker ───────────────────────────────────────────────────────────\n\nexport interface ModelPickerProps {\n value: string\n onChange: (id: string) => void\n /** Catalogue models — from `GET`ing the app's catalogue route (see\n * `runtime/model-catalog`), plus any product-specific entries appended. */\n models: CatalogModel[]\n loading?: boolean\n /** Render a provider logo/badge; default is a generic sparkle. */\n renderProviderBadge?: (provider: string) => ReactNode\n /** Section label for `featured` models. */\n recommendedLabel?: string\n /** Pin a labeled section to the TOP of the list (above Recommended) for the\n * models a product wants surfaced first — e.g. a tuner app's own fine-tuned\n * models (`{ label: 'Your Fine-Tuned Models', match: (m) => m.provider === 'tuner' }`).\n * Matching models are shown only in this section, not duplicated below. */\n priorityGroup?: {\n label: string\n match: (model: CatalogModel) => boolean\n }\n}\n\nfunction formatPrice(p?: string): string | undefined {\n if (!p) return undefined\n const n = Number(p)\n if (isNaN(n) || n === 0) return undefined\n const perM = n * 1_000_000\n return perM >= 1 ? `$${perM.toFixed(0)}/M` : `$${perM.toFixed(2)}/M`\n}\n\nfunction formatContext(len?: number): string | undefined {\n if (!len) return undefined\n if (len >= 1_000_000) return `${(len / 1_000_000).toFixed(1)}M ctx`\n if (len >= 1_000) return `${Math.round(len / 1_000)}K ctx`\n return `${len} ctx`\n}\n\nfunction SectionHeader({ children }: { children: ReactNode }) {\n return (\n <div className=\"px-3 pb-1 pt-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground\">\n {children}\n </div>\n )\n}\n\nfunction ModelRow({\n model,\n selected,\n onSelect,\n renderProviderBadge,\n}: {\n model: CatalogModel\n selected: boolean\n onSelect: () => void\n renderProviderBadge?: (provider: string) => ReactNode\n}) {\n const price = formatPrice(model.pricing?.prompt)\n const ctx = formatContext(model.contextLength)\n return (\n <button\n type=\"button\"\n onClick={onSelect}\n className={`flex w-full items-center gap-2.5 rounded-md px-3 py-2.5 text-left text-sm transition ${POPOVER_OPTION_FOCUS} ${\n selected ? 'bg-primary/10 font-medium' : 'hover:bg-accent/30'\n }`}\n >\n {renderProviderBadge ? renderProviderBadge(model.provider) : <ProviderLogo provider={model.provider} size={16} />}\n <span className=\"truncate\">{model.name}</span>\n {!model.supportsTools && (\n <span className=\"shrink-0 rounded bg-muted/60 px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground\">\n no tools\n </span>\n )}\n <span className=\"ml-auto flex shrink-0 items-center gap-2 text-xs text-muted-foreground\">\n {ctx && <span>{ctx}</span>}\n {price && <span>{price}</span>}\n </span>\n </button>\n )\n}\n\n/**\n * Searchable model picker pill + popover: a featured/recommended section\n * first, then per-provider groups in catalogue order (the server already\n * sorts providers by tier).\n */\nexport function ModelPicker({ value, onChange, models, loading, renderProviderBadge, recommendedLabel = 'Recommended', priorityGroup }: ModelPickerProps) {\n const [open, setOpen] = useState(false)\n const [query, setQuery] = useState('')\n const { containerRef, triggerProps } = usePopover(open, setOpen)\n const inputRef = useRef<HTMLInputElement>(null)\n\n useEffect(() => {\n if (open) inputRef.current?.focus()\n }, [open])\n\n const selected = models.find((m) => m.id === value)\n\n const filtered = useMemo(() => {\n const q = query.trim().toLowerCase()\n if (!q) return null\n return models.filter(\n (m) =>\n m.id.toLowerCase().includes(q) ||\n m.name.toLowerCase().includes(q) ||\n (m.description?.toLowerCase() ?? '').includes(q) ||\n m.provider.toLowerCase().includes(q),\n )\n }, [models, query])\n\n const sections = useMemo(() => {\n const isPriority = priorityGroup ? (m: CatalogModel) => priorityGroup.match(m) : () => false\n const priority = priorityGroup ? models.filter(isPriority) : []\n const recommended = models.filter((m) => m.featured && !isPriority(m))\n const byProvider: Array<{ provider: string; items: CatalogModel[] }> = []\n for (const m of models) {\n if (m.featured || isPriority(m)) continue\n const last = byProvider[byProvider.length - 1]\n if (last && last.provider === m.provider) last.items.push(m)\n else byProvider.push({ provider: m.provider, items: [m] })\n }\n return { priority, recommended, byProvider }\n }, [models, priorityGroup])\n\n const select = (id: string) => {\n onChange(id)\n setOpen(false)\n setQuery('')\n }\n\n return (\n <div ref={containerRef} className=\"relative inline-flex\">\n <button\n type=\"button\"\n {...triggerProps}\n onClick={() => setOpen(!open)}\n className=\"inline-flex items-center gap-1.5 rounded-full border border-border bg-card px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-accent/30 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background\"\n >\n {selected ? (renderProviderBadge ? renderProviderBadge(selected.provider) : <ProviderLogo provider={selected.provider} size={16} />) : <SparkleGlyph className=\"h-3.5 w-3.5 text-muted-foreground\" />}\n <span className=\"max-w-[160px] truncate\">{selected?.name ?? value}</span>\n <ChevronDown className=\"h-3.5 w-3.5 text-muted-foreground\" />\n </button>\n\n {open && (\n <div className=\"absolute bottom-full left-0 z-50 mb-2 w-[420px] max-w-[calc(100vw-2rem)] overflow-hidden rounded-xl border border-border bg-card shadow-lg\">\n <div className=\"border-b border-border px-3 py-2\">\n <div className=\"flex items-center gap-2 rounded-lg border border-border bg-background px-3 py-2\">\n <SearchGlyph className=\"h-3.5 w-3.5 text-muted-foreground\" />\n <input\n ref={inputRef}\n type=\"text\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder=\"Search models...\"\n className=\"flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground\"\n />\n </div>\n </div>\n <div className=\"max-h-[400px] overflow-y-auto p-1 pb-2\">\n {loading && <div className=\"px-3 py-4 text-center text-sm text-muted-foreground\">Loading models...</div>}\n {!loading && filtered && (\n <>\n {filtered.length === 0 && (\n <div className=\"px-3 py-4 text-center text-sm text-muted-foreground\">No models match your search</div>\n )}\n {filtered.map((m) => (\n <ModelRow key={m.id} model={m} selected={m.id === value} onSelect={() => select(m.id)} renderProviderBadge={renderProviderBadge} />\n ))}\n </>\n )}\n {!loading && !filtered && (\n <>\n {priorityGroup && sections.priority.length > 0 && (\n <>\n <SectionHeader>{priorityGroup.label}</SectionHeader>\n {sections.priority.map((m) => (\n <ModelRow key={m.id} model={m} selected={m.id === value} onSelect={() => select(m.id)} renderProviderBadge={renderProviderBadge} />\n ))}\n </>\n )}\n {sections.recommended.length > 0 && (\n <>\n <SectionHeader>{recommendedLabel}</SectionHeader>\n {sections.recommended.map((m) => (\n <ModelRow key={m.id} model={m} selected={m.id === value} onSelect={() => select(m.id)} renderProviderBadge={renderProviderBadge} />\n ))}\n </>\n )}\n {sections.byProvider.map((g) => (\n <div key={g.provider}>\n <SectionHeader>{g.provider}</SectionHeader>\n {g.items.map((m) => (\n <ModelRow key={m.id} model={m} selected={m.id === value} onSelect={() => select(m.id)} renderProviderBadge={renderProviderBadge} />\n ))}\n </div>\n ))}\n </>\n )}\n </div>\n </div>\n )}\n </div>\n )\n}\n\n// ── EffortPicker ──────────────────────────────────────────────────────────\n\n/** One reasoning-budget level: the engine `id` is unchanged (the value the\n * product sends to the loop); only the user-facing `label` is renamed to the\n * plainer \"how hard should it think\" vocabulary from docs/product-surfaces.md.\n * `low`→Quick, `medium`→Standard, `high`→Extended. The mapping is overridable\n * via `EffortPickerProps.levels`, so a product can relabel without losing the\n * ids the runtime expects. */\nexport interface EffortLevel {\n id: string\n label: string\n}\n\nexport const DEFAULT_EFFORT_LEVELS: readonly EffortLevel[] = [\n { id: 'off', label: 'Off' },\n { id: 'low', label: 'Quick' },\n { id: 'medium', label: 'Standard' },\n { id: 'high', label: 'Extended' },\n]\n\nexport interface EffortPickerProps {\n value: string\n onChange: (id: string) => void\n /** Selectable levels (engine id + user-facing label). Defaults to the plain\n * \"Thinking\" vocabulary; override to relabel without changing the ids the\n * runtime receives. */\n levels?: readonly EffortLevel[]\n /** Prefix shown before the active level on the pill — the \"what is this\"\n * context the bare value lacked. Default \"Thinking\". Pass '' to hide it. */\n label?: string\n}\n\n/** Thinking-budget selector pill, styled to match {@link ModelPicker}. Show\n * it only when the selected model `supportsReasoning`. \"Thinking\" is the\n * plain-English name for what was internally called \"effort\". */\nexport function EffortPicker({ value, onChange, levels = DEFAULT_EFFORT_LEVELS, label = 'Thinking' }: EffortPickerProps) {\n const [open, setOpen] = useState(false)\n const { containerRef, triggerProps } = usePopover(open, setOpen)\n const selected = levels.find((l) => l.id === value) ?? levels[2] ?? levels[0]\n\n return (\n <div ref={containerRef} className=\"relative inline-flex\">\n <button\n type=\"button\"\n {...triggerProps}\n onClick={() => setOpen(!open)}\n title={label ? `${label} — how hard the agent reasons before answering` : 'Reasoning effort'}\n className=\"inline-flex min-h-[36px] items-center gap-1.5 rounded-full border border-border bg-card px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-accent/30 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background\"\n >\n <SparkleGlyph className=\"h-3.5 w-3.5 text-muted-foreground\" />\n <span>\n {label ? <span className=\"text-muted-foreground\">{label}: </span> : null}\n {selected?.label}\n </span>\n <ChevronDown className=\"h-3.5 w-3.5 text-muted-foreground\" />\n </button>\n {open && (\n <div role=\"menu\" className=\"absolute bottom-full left-0 z-50 mb-2 w-40 overflow-hidden rounded-xl border border-border bg-card p-1 shadow-lg\">\n {levels.map((l) => (\n <button\n key={l.id}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={l.id === value}\n onClick={() => {\n onChange(l.id)\n setOpen(false)\n }}\n className={`flex min-h-[40px] w-full items-center rounded-md px-3 py-2 text-left text-sm transition ${POPOVER_OPTION_FOCUS} ${\n l.id === value ? 'bg-primary/10 font-medium' : 'hover:bg-accent/30'\n }`}\n >\n {l.label}\n </button>\n ))}\n </div>\n )}\n </div>\n )\n}\n","/**\n * Provider brand marks — real logo path data (simple-icons / SVG Logos, both\n * CC0) inlined so the picker shows actual provider identity instead of\n * colored-initial monograms. Providers without a usable mark fall back to a\n * tinted monogram chip. Aliases (z-ai/zai, moonshot/moonshotai, deepseek_ai)\n * normalize to one entry.\n */\n\nimport type { ReactNode } from 'react'\n\ninterface LogoDef {\n viewBox: string\n fill: string\n paths: string[]\n}\n\nconst LOGOS: Record<string, LogoDef> = {\n anthropic: { viewBox: '0 0 24 24', fill: '#D97757', paths: [\"M17.3041 3.541h-3.6718l6.696 16.918H24Zm-10.6082 0L0 20.459h3.7442l1.3693-3.5527h7.0052l1.3693 3.5528h3.7442L10.5363 3.5409Zm-.3712 10.2232 2.2914-5.9456 2.2914 5.9456Z\"] },\n google: { viewBox: '0 0 24 24', fill: '#8E75B2', paths: [\"M11.04 19.32Q12 21.51 12 24q0-2.49.93-4.68.96-2.19 2.58-3.81t3.81-2.55Q21.51 12 24 12q-2.49 0-4.68-.93a12.3 12.3 0 0 1-3.81-2.58 12.3 12.3 0 0 1-2.58-3.81Q12 2.49 12 0q0 2.49-.96 4.68-.93 2.19-2.55 3.81a12.3 12.3 0 0 1-3.81 2.58Q2.49 12 0 12q2.49 0 4.68.96 2.19.93 3.81 2.55t2.55 3.81\"] },\n deepseek: { viewBox: '0 0 24 24', fill: '#4D6BFE', paths: [\"M23.748 4.651c-.254-.124-.364.113-.512.233-.051.04-.094.09-.137.137-.372.397-.806.657-1.373.626-.829-.046-1.537.214-2.163.848-.133-.782-.575-1.248-1.247-1.548-.352-.155-.708-.311-.955-.65-.172-.24-.219-.509-.305-.774-.055-.16-.11-.323-.293-.35-.2-.031-.278.136-.356.276-.313.572-.434 1.202-.422 1.84.027 1.436.633 2.58 1.838 3.393.137.094.172.187.129.323-.082.28-.18.553-.266.833-.055.179-.137.218-.328.14a5.5 5.5 0 0 1-1.737-1.179c-.857-.828-1.631-1.743-2.597-2.46a12 12 0 0 0-.689-.47c-.985-.957.13-1.743.387-1.836.27-.098.094-.433-.778-.428-.872.003-1.67.295-2.687.685a3 3 0 0 1-.465.136 9.6 9.6 0 0 0-2.883-.101c-1.885.21-3.39 1.1-4.497 2.622C.082 8.776-.231 10.854.152 13.02c.403 2.284 1.568 4.175 3.36 5.653 1.857 1.533 3.997 2.284 6.438 2.14 1.482-.085 3.132-.284 4.994-1.86.47.234.962.328 1.78.398.629.058 1.235-.031 1.705-.129.735-.155.684-.836.418-.961-2.155-1.004-1.682-.595-2.112-.926 1.095-1.295 2.768-3.598 3.284-6.733.05-.346.115-.834.108-1.114-.004-.171.035-.238.23-.257a4.2 4.2 0 0 0 1.545-.475c1.397-.763 1.96-2.016 2.093-3.517.02-.23-.004-.467-.247-.588M11.58 18.168c-2.088-1.642-3.101-2.183-3.52-2.16-.39.024-.32.472-.234.763.09.288.207.487.371.74.114.167.192.416-.113.603-.673.416-1.842-.14-1.897-.168-1.361-.801-2.5-1.86-3.301-3.306-.775-1.393-1.225-2.888-1.299-4.482-.02-.385.094-.522.477-.592a4.7 4.7 0 0 1 1.53-.038c2.131.311 3.946 1.264 5.467 2.774.868.86 1.525 1.887 2.202 2.89.72 1.066 1.494 2.082 2.48 2.915.348.291.626.513.892.677-.802.09-2.14.109-3.055-.615zm1.001-6.44a.306.306 0 0 1 .415-.287.3.3 0 0 1 .113.074.3.3 0 0 1 .086.214c0 .17-.136.307-.308.307a.303.303 0 0 1-.306-.307m3.11 1.596c-.2.081-.4.151-.591.16a1.25 1.25 0 0 1-.798-.254c-.274-.23-.47-.358-.551-.758a1.7 1.7 0 0 1 .015-.588c.07-.327-.007-.537-.238-.727-.188-.156-.426-.199-.689-.199a.6.6 0 0 1-.254-.078.253.253 0 0 1-.114-.358 1 1 0 0 1 .192-.21c.356-.202.767-.136 1.146.016.352.144.618.408 1.001.782.392.451.462.576.685.915.176.264.336.536.446.848.066.194-.02.353-.25.45\"] },\n mistral: { viewBox: '0 0 24 24', fill: '#FA520F', paths: [\"M17.143 3.429v3.428h-3.429v3.429h-3.428V6.857H6.857V3.43H3.43v13.714H0v3.428h10.286v-3.428H6.857v-3.429h3.429v3.429h3.429v-3.429h3.428v3.429h-3.428v3.428H24v-3.428h-3.43V3.429z\"] },\n xai: { viewBox: '0 0 24 24', fill: '#000000', paths: [\"M14.234 10.162 22.977 0h-2.072l-7.591 8.824L7.251 0H.258l9.168 13.343L.258 24H2.33l8.016-9.318L16.749 24h6.993zm-2.837 3.299-.929-1.329L3.076 1.56h3.182l5.965 8.532.929 1.329 7.754 11.09h-3.182z\"] },\n nvidia: { viewBox: '0 0 24 24', fill: '#76B900', paths: [\"M8.948 8.798v-1.43a6.7 6.7 0 0 1 .424-.018c3.922-.124 6.493 3.374 6.493 3.374s-2.774 3.851-5.75 3.851c-.398 0-.787-.062-1.158-.185v-4.346c1.528.185 1.837.857 2.747 2.385l2.04-1.714s-1.492-1.952-4-1.952a6.016 6.016 0 0 0-.796.035m0-4.735v2.138l.424-.027c5.45-.185 9.01 4.47 9.01 4.47s-4.08 4.964-8.33 4.964c-.37 0-.733-.035-1.095-.097v1.325c.3.035.61.062.91.062 3.957 0 6.82-2.023 9.593-4.408.459.371 2.34 1.263 2.73 1.652-2.633 2.208-8.772 3.984-12.253 3.984-.335 0-.653-.018-.971-.053v1.864H24V4.063zm0 10.326v1.131c-3.657-.654-4.673-4.46-4.673-4.46s1.758-1.944 4.673-2.262v1.237H8.94c-1.528-.186-2.73 1.245-2.73 1.245s.68 2.412 2.739 3.11M2.456 10.9s2.164-3.197 6.5-3.533V6.201C4.153 6.59 0 10.653 0 10.653s2.35 6.802 8.948 7.42v-1.237c-4.84-.6-6.492-5.936-6.492-5.936z\"] },\n meta: { viewBox: '0 0 24 24', fill: '#0467DF', paths: [\"M6.915 4.03c-1.968 0-3.683 1.28-4.871 3.113C.704 9.208 0 11.883 0 14.449c0 .706.07 1.369.21 1.973a6.624 6.624 0 0 0 .265.86 5.297 5.297 0 0 0 .371.761c.696 1.159 1.818 1.927 3.593 1.927 1.497 0 2.633-.671 3.965-2.444.76-1.012 1.144-1.626 2.663-4.32l.756-1.339.186-.325c.061.1.121.196.183.3l2.152 3.595c.724 1.21 1.665 2.556 2.47 3.314 1.046.987 1.992 1.22 3.06 1.22 1.075 0 1.876-.355 2.455-.843a3.743 3.743 0 0 0 .81-.973c.542-.939.861-2.127.861-3.745 0-2.72-.681-5.357-2.084-7.45-1.282-1.912-2.957-2.93-4.716-2.93-1.047 0-2.088.467-3.053 1.308-.652.57-1.257 1.29-1.82 2.05-.69-.875-1.335-1.547-1.958-2.056-1.182-.966-2.315-1.303-3.454-1.303zm10.16 2.053c1.147 0 2.188.758 2.992 1.999 1.132 1.748 1.647 4.195 1.647 6.4 0 1.548-.368 2.9-1.839 2.9-.58 0-1.027-.23-1.664-1.004-.496-.601-1.343-1.878-2.832-4.358l-.617-1.028a44.908 44.908 0 0 0-1.255-1.98c.07-.109.141-.224.211-.327 1.12-1.667 2.118-2.602 3.358-2.602zm-10.201.553c1.265 0 2.058.791 2.675 1.446.307.327.737.871 1.234 1.579l-1.02 1.566c-.757 1.163-1.882 3.017-2.837 4.338-1.191 1.649-1.81 1.817-2.486 1.817-.524 0-1.038-.237-1.383-.794-.263-.426-.464-1.13-.464-2.046 0-2.221.63-4.535 1.66-6.088.454-.687.964-1.226 1.533-1.533a2.264 2.264 0 0 1 1.088-.285z\"] },\n moonshotai: { viewBox: '0 0 24 24', fill: '#16191E', paths: [\"m1.053 16.91 9.538 2.55a21 20.981 0 0 0 .06 2.031l5.956 1.592a12 11.99 0 0 1-15.554-6.172m-1.02-5.79 11.352 3.035a21 20.981 0 0 0-.469 2.01l10.817 2.89a12 11.99 0 0 1-1.845 2.004L.658 15.918a12 11.99 0 0 1-.625-4.796m1.593-5.146L13.573 9.17a21 20.981 0 0 0-1.01 1.874l11.297 3.02a21 20.981 0 0 1-.67 2.362l-11.55-3.087L.125 10.26a12 11.99 0 0 1 1.499-4.285ZM6.067 1.58l11.285 3.016a21 20.981 0 0 0-1.688 1.719l7.824 2.091a21 20.981 0 0 1 .513 2.664L2.107 5.218a12 11.99 0 0 1 3.96-3.638M21.68 4.866 7.222 1.003A12 11.99 0 0 1 21.68 4.866\"] },\n openai: { viewBox: '0 0 256 260', fill: '#10A37F', paths: [\"M239.184 106.203a64.72 64.72 0 0 0-5.576-53.103C219.452 28.459 191 15.784 163.213 21.74A65.586 65.586 0 0 0 52.096 45.22a64.72 64.72 0 0 0-43.23 31.36c-14.31 24.602-11.061 55.634 8.033 76.74a64.67 64.67 0 0 0 5.525 53.102c14.174 24.65 42.644 37.324 70.446 31.36a64.72 64.72 0 0 0 48.754 21.744c28.481.025 53.714-18.361 62.414-45.481a64.77 64.77 0 0 0 43.229-31.36c14.137-24.558 10.875-55.423-8.083-76.483m-97.56 136.338a48.4 48.4 0 0 1-31.105-11.255l1.535-.87l51.67-29.825a8.6 8.6 0 0 0 4.247-7.367v-72.85l21.845 12.636c.218.111.37.32.409.563v60.367c-.056 26.818-21.783 48.545-48.601 48.601M37.158 197.93a48.35 48.35 0 0 1-5.781-32.589l1.534.921l51.722 29.826a8.34 8.34 0 0 0 8.441 0l63.181-36.425v25.221a.87.87 0 0 1-.358.665l-52.335 30.184c-23.257 13.398-52.97 5.431-66.404-17.803M23.549 85.38a48.5 48.5 0 0 1 25.58-21.333v61.39a8.29 8.29 0 0 0 4.195 7.316l62.874 36.272l-21.845 12.636a.82.82 0 0 1-.767 0L41.353 151.53c-23.211-13.454-31.171-43.144-17.804-66.405zm179.466 41.695l-63.08-36.63L161.73 77.86a.82.82 0 0 1 .768 0l52.233 30.184a48.6 48.6 0 0 1-7.316 87.635v-61.391a8.54 8.54 0 0 0-4.4-7.213m21.742-32.69l-1.535-.922l-51.619-30.081a8.39 8.39 0 0 0-8.492 0L99.98 99.808V74.587a.72.72 0 0 1 .307-.665l52.233-30.133a48.652 48.652 0 0 1 72.236 50.391zM88.061 139.097l-21.845-12.585a.87.87 0 0 1-.41-.614V65.685a48.652 48.652 0 0 1 79.757-37.346l-1.535.87l-51.67 29.825a8.6 8.6 0 0 0-4.246 7.367zm11.868-25.58L128.067 97.3l28.188 16.218v32.434l-28.086 16.218l-28.188-16.218z\"] },\n}\n\nconst ALIASES: Record<string, string> = {\n moonshot: 'moonshotai',\n deepseek_ai: 'deepseek',\n 'x-ai': 'xai',\n 'meta-llama': 'meta',\n}\n\nconst MONOGRAM: Record<string, { bg: string; fg: string }> = {\n cohere: { bg: '#fae8ff', fg: '#c026d3' },\n groq: { bg: '#fce7f3', fg: '#db2777' },\n cerebras: { bg: '#ccfbf1', fg: '#0d9488' },\n zai: { bg: '#ede9fe', fg: '#7c3aed' },\n 'z-ai': { bg: '#ede9fe', fg: '#7c3aed' },\n tuner: { bg: '#dbeafe', fg: '#2563eb' },\n}\n\nexport interface ProviderLogoProps {\n provider?: string\n size?: number\n}\n\n/** Real brand mark when we have one; tinted monogram otherwise. */\nexport function ProviderLogo({ provider, size = 16 }: ProviderLogoProps): ReactNode {\n const key = ALIASES[provider ?? ''] ?? provider ?? ''\n const logo = LOGOS[key]\n if (logo) {\n return (\n <svg width={size} height={size} viewBox={logo.viewBox} role=\"img\" aria-label={key}>\n {logo.paths.map((d, i) => (\n <path key={i} d={d} fill={logo.fill} />\n ))}\n </svg>\n )\n }\n const mono = MONOGRAM[key] ?? { bg: '#f3f4f6', fg: '#6b7280' }\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" role=\"img\" aria-label={key || 'model'}>\n <rect width=\"16\" height=\"16\" rx=\"4\" fill={mono.bg} />\n <text x=\"8\" y=\"11.6\" textAnchor=\"middle\" fill={mono.fg} fontSize=\"9\" fontWeight=\"700\" fontFamily=\"system-ui, sans-serif\">\n {(key || '?').charAt(0).toUpperCase()}\n </text>\n </svg>\n )\n}\n","/**\n * Lazy boundary around the Tangle knot from `../brand`.\n *\n * `/brand` re-exports the mark from `@tangle-network/sandbox-ui`, an OPT-IN\n * peer. Static-importing it here would pull that peer into the eagerly-evaluated\n * `web-react` graph — breaking the dependency-light contract this module relies\n * on (it must import cleanly in environments, and tests, that haven't installed\n * the peer). Code-splitting keeps the peer out of the static graph: the knot\n * streams in only when a branded surface actually renders, and a missing peer\n * degrades to reserved space rather than crashing the chat shell.\n */\n\nimport { lazy, Suspense } from 'react'\nimport type { ComponentType } from 'react'\n\nexport interface BrandMarkProps {\n size?: number\n className?: string\n}\n\n/** Reserve the mark's footprint so its async arrival doesn't shift layout, and\n * serve as the graceful fallback when the opt-in peer isn't installed. */\nfunction MarkSpacer({ size = 24, className }: BrandMarkProps) {\n return <span aria-hidden style={{ display: 'inline-block', width: size, height: size }} className={className} />\n}\n\nconst LazyKnot = lazy(async () => {\n try {\n const mod = await import('../brand')\n return { default: mod.TangleKnot as ComponentType<BrandMarkProps> }\n } catch {\n return { default: MarkSpacer as ComponentType<BrandMarkProps> }\n }\n})\n\nexport function BrandMark({ size = 24, className }: BrandMarkProps) {\n return (\n <Suspense fallback={<MarkSpacer size={size} className={className} />}>\n <LazyKnot size={size} className={className} />\n </Suspense>\n )\n}\n","/**\n * Client-side chat-stream consumption — the NDJSON parse loop every agent\n * app's chat UI hand-rolls (and breaks). Normalizes the three line shapes the\n * agent-app chat routes emit:\n *\n * {kind:'event', event:{type:'text'|'reasoning'|'tool_call'|'usage', ...}}\n * {kind:'tool_result', toolCallId, toolName, label, outcome}\n * {type:'turn'|'metadata'|'error'|'turn_status', ...} (route-level)\n *\n * Replayed lines carry an extra `seq` — transparently ignored. Works for\n * router-backed and sandbox-backed chats alike: anything producing these\n * lines (live pump, queued follow, resume replay) feeds the same callbacks.\n */\n\nexport interface ChatStreamToolCall {\n toolCallId?: string\n toolName: string\n args: Record<string, unknown>\n}\n\nexport interface ChatStreamToolResult {\n toolCallId?: string\n toolName?: string\n label?: string\n outcome: { ok: boolean; result?: unknown; code?: string; message?: string }\n}\n\nexport interface ChatStreamCallbacks {\n onTurnId?: (turnId: string) => void\n onText?: (delta: string) => void\n onReasoning?: (delta: string) => void\n onToolCall?: (call: ChatStreamToolCall) => void\n onToolResult?: (result: ChatStreamToolResult) => void\n onUsage?: (usage: { promptTokens: number; completionTokens: number }) => void\n onMetadata?: (data: Record<string, unknown>) => void\n /** A loop-level error event (the turn failed server-side). */\n onErrorEvent?: (message: string) => void\n}\n\nexport interface ConsumeChatStreamResult {\n turnId: string | null\n /** True when any text/reasoning/tool activity was received. */\n receivedContent: boolean\n}\n\n/** Parse one NDJSON line into the callbacks. Exposed for tests. */\nexport function dispatchChatStreamLine(line: string, cb: ChatStreamCallbacks): {\n turnId?: string\n receivedContent: boolean\n} {\n let receivedContent = false\n let turnId: string | undefined\n if (!line.trim()) return { receivedContent }\n let parsed: Record<string, unknown>\n try {\n parsed = JSON.parse(line) as Record<string, unknown>\n } catch {\n return { receivedContent } // tolerate a torn line\n }\n\n if (parsed.kind === 'tool_result') {\n cb.onToolResult?.({\n toolCallId: parsed.toolCallId as string | undefined,\n toolName: parsed.toolName as string | undefined,\n label: parsed.label as string | undefined,\n outcome: (parsed.outcome ?? parsed.result) as ChatStreamToolResult['outcome'],\n })\n return { receivedContent: true }\n }\n\n const evt = (parsed.kind === 'event' ? parsed.event : parsed) as Record<string, unknown>\n if (!evt || typeof evt !== 'object') return { receivedContent }\n\n switch (evt.type) {\n case 'turn':\n if (typeof evt.turnId === 'string') turnId = evt.turnId\n break\n case 'text':\n if (typeof evt.text === 'string') {\n cb.onText?.(evt.text)\n receivedContent = true\n }\n break\n case 'reasoning':\n if (typeof evt.text === 'string') {\n cb.onReasoning?.(evt.text)\n receivedContent = true\n }\n break\n case 'tool_call': {\n const call = (evt.call ?? evt) as Record<string, unknown>\n cb.onToolCall?.({\n toolCallId: (call.toolCallId ?? call.id) as string | undefined,\n toolName: String(call.toolName ?? call.name ?? 'unknown'),\n args: (call.args ?? {}) as Record<string, unknown>,\n })\n receivedContent = true\n break\n }\n case 'tool_result':\n cb.onToolResult?.({\n toolCallId: evt.toolCallId as string | undefined,\n toolName: evt.toolName as string | undefined,\n label: evt.label as string | undefined,\n outcome: (evt.outcome ?? evt.result) as ChatStreamToolResult['outcome'],\n })\n receivedContent = true\n break\n case 'usage': {\n const u = evt.usage as { promptTokens?: number; completionTokens?: number } | undefined\n if (u) cb.onUsage?.({ promptTokens: u.promptTokens ?? 0, completionTokens: u.completionTokens ?? 0 })\n break\n }\n case 'metadata':\n cb.onMetadata?.((evt.data ?? {}) as Record<string, unknown>)\n break\n case 'error':\n cb.onErrorEvent?.(String(evt.details ?? evt.error ?? 'Unknown stream error'))\n break\n default:\n break // turn_status and unknown line types are non-content\n }\n return { turnId, receivedContent }\n}\n\n/** Drain one NDJSON body into the callbacks. Throws on transport failure\n * (caller decides whether to resume). */\nexport async function consumeChatStream(\n body: ReadableStream<Uint8Array>,\n cb: ChatStreamCallbacks,\n): Promise<ConsumeChatStreamResult> {\n const reader = body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n let turnId: string | null = null\n let receivedContent = false\n\n const handle = (line: string) => {\n const r = dispatchChatStreamLine(line, cb)\n if (r.turnId) {\n turnId = r.turnId\n cb.onTurnId?.(r.turnId)\n }\n if (r.receivedContent) receivedContent = true\n }\n\n for (;;) {\n const { done, value } = await reader.read()\n if (done) {\n if (buffer.trim()) handle(buffer)\n break\n }\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n for (const line of lines) handle(line)\n }\n return { turnId, receivedContent }\n}\n\nexport interface StreamChatOptions {\n /** Start the turn (POST the chat request); must return a streaming Response. */\n start: () => Promise<Response>\n /** Re-attach to a turn after a transport drop (GET the resume route). */\n resume?: (turnId: string, fromSeq: number) => Promise<Response>\n callbacks: ChatStreamCallbacks\n /** Called before a resume replays from 0 so the UI can reset accumulated\n * turn state (text, reasoning, tool chips). */\n onResetForResume?: () => void\n}\n\n/**\n * Run one chat turn with automatic single-shot resume: if the transport drops\n * mid-turn and the server announced a turnId, reset and replay the buffered\n * turn. Server-side the turn keeps running either way (queued runner).\n */\nexport async function streamChatTurn(opts: StreamChatOptions): Promise<ConsumeChatStreamResult> {\n const res = await opts.start()\n if (!res.ok || !res.body) {\n const err = await res.json().catch(() => ({ error: `HTTP ${res.status}` })) as { error?: string }\n throw new Error(err.error ?? `HTTP ${res.status}`)\n }\n let turnId: string | null = null\n const cb: ChatStreamCallbacks = {\n ...opts.callbacks,\n onTurnId: (id) => {\n turnId = id\n opts.callbacks.onTurnId?.(id)\n },\n }\n try {\n return await consumeChatStream(res.body, cb)\n } catch (transportErr) {\n if (!turnId || !opts.resume) throw transportErr\n opts.onResetForResume?.()\n const resumed = await opts.resume(turnId, 0)\n if (!resumed.ok || !resumed.body) throw transportErr\n return await consumeChatStream(resumed.body, cb)\n }\n}\n","/**\n * ChatComposer — the shared message input every agent app used to hand-roll:\n * an auto-resizing textarea (Enter sends, Shift+Enter inserts a newline), an\n * opt-in attach + drag-and-drop surface with pending-file chips, a streaming\n * Stop/Send toggle, a slot for inline controls (model picker, reasoning\n * effort), and a Cmd/Ctrl+L focus shortcut.\n *\n * Styling contract matches the rest of `web-react`: Tailwind over the shared\n * design tokens (`bg-card`, `border-border`, `text-foreground`, `bg-primary`, …)\n * and inline-SVG glyphs. It defines NO `--chat-*` / `--brand-*` custom\n * properties, so it themes correctly in any shell that provides the standard\n * tokens — the input renders on-palette instead of collapsing to unstyled\n * fallbacks when a host hasn't defined a private chat-token set.\n */\n\nimport {\n useCallback,\n useEffect,\n useRef,\n useState,\n type ChangeEvent,\n type DragEvent,\n type KeyboardEvent,\n type ReactNode,\n} from 'react'\n\n// ── glyphs (no icon-library dependency) ───────────────────────────────────\n\nfunction SendGlyph({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M22 2 11 13M22 2l-7 20-4-9-9-4 20-7z\" />\n </svg>\n )\n}\n\nfunction StopGlyph({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden>\n <rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2\" />\n </svg>\n )\n}\n\nfunction PaperclipGlyph({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48\" />\n </svg>\n )\n}\n\nfunction FolderGlyph({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M4 20h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.93a2 2 0 0 1-1.66-.9l-.82-1.2A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13c0 1.1.9 2 2 2Z\" />\n <path d=\"M12 10v6m-3-3h6\" />\n </svg>\n )\n}\n\nfunction CloseGlyph({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden>\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n )\n}\n\nfunction UploadGlyph({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12\" />\n </svg>\n )\n}\n\n// ── component ──────────────────────────────────────────────────────────────\n\nexport interface ComposerFile {\n id: string\n name: string\n size?: number\n kind: 'file' | 'folder'\n /** Number of files inside, for a folder chip. */\n fileCount?: number\n status: 'pending' | 'uploading' | 'ready' | 'error'\n}\n\nexport interface ChatComposerProps {\n /** Send the trimmed, non-empty message. Attached files travel separately via\n * `onAttach` + `pendingFiles` (the host consumes and clears them on send). */\n onSend: (message: string) => void\n /** Stop the in-flight turn; shown in place of Send while `isStreaming`. */\n onCancel?: () => void\n isStreaming?: boolean\n /** Block input + send (e.g. while restoring). Distinct from `isStreaming`,\n * which keeps the textarea editable so the next turn can be composed. */\n disabled?: boolean\n placeholder?: string\n\n /** Controlled value. Omit for self-managed internal state (cleared on send). */\n value?: string\n onValueChange?: (value: string) => void\n /** Initial text in uncontrolled mode; ignored when `value` is provided. */\n initialValue?: string\n\n /** Inline controls (e.g. `<ModelPicker/>` + `<EffortPicker/>` or\n * `<AgentSessionControls/>`). Rendered in a row above the input by default. */\n controls?: ReactNode\n controlsPlacement?: 'above' | 'footer'\n\n /** Attachments are opt-in: pass `onAttach` to show the attach button, accept\n * drag-and-drop onto the input, and render `pendingFiles` chips. */\n onAttach?: (files: FileList) => void\n onAttachFolder?: (files: FileList) => void\n pendingFiles?: ComposerFile[]\n onRemoveFile?: (id: string) => void\n accept?: string\n dropTitle?: string\n dropDescription?: string\n\n /** Cmd/Ctrl+L focuses the input and shows the hint. Default true. */\n focusShortcut?: boolean\n /** Send button label. Default \"Send\". */\n sendLabel?: string\n className?: string\n}\n\nconst MAX_HEIGHT = 168\n\nexport function ChatComposer({\n onSend,\n onCancel,\n isStreaming = false,\n disabled = false,\n placeholder = 'Message the agent…',\n value,\n onValueChange,\n initialValue,\n controls,\n controlsPlacement = 'above',\n onAttach,\n onAttachFolder,\n pendingFiles = [],\n onRemoveFile,\n accept,\n dropTitle = 'Drop files to add context',\n dropDescription = 'They attach to your next message.',\n focusShortcut = true,\n sendLabel = 'Send',\n className,\n}: ChatComposerProps) {\n const isControlled = value !== undefined\n const [internal, setInternal] = useState(initialValue ?? '')\n const text = isControlled ? value : internal\n\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n const fileInputRef = useRef<HTMLInputElement>(null)\n const folderInputRef = useRef<HTMLInputElement>(null)\n const [dragOver, setDragOver] = useState(false)\n const dragDepth = useRef(0)\n\n const setText = useCallback(\n (next: string) => {\n if (!isControlled) setInternal(next)\n onValueChange?.(next)\n },\n [isControlled, onValueChange],\n )\n\n // Keep the textarea height in sync with the content for BOTH typed and\n // external (controlled) value changes — one effect covers both paths.\n useEffect(() => {\n const el = textareaRef.current\n if (!el) return\n el.style.height = 'auto'\n el.style.height = `${Math.min(el.scrollHeight, MAX_HEIGHT)}px`\n }, [text])\n\n // Cmd/Ctrl+L focuses the composer from anywhere — the shortcut the hint\n // advertises. Scoped to when the shortcut is enabled and not disabled.\n useEffect(() => {\n if (!focusShortcut || disabled) return\n function onKeyDown(e: globalThis.KeyboardEvent) {\n if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'l') {\n e.preventDefault()\n textareaRef.current?.focus()\n }\n }\n document.addEventListener('keydown', onKeyDown)\n return () => document.removeEventListener('keydown', onKeyDown)\n }, [focusShortcut, disabled])\n\n const canSend = text.trim().length > 0 && !isStreaming && !disabled\n\n const send = useCallback(() => {\n const trimmed = text.trim()\n if (!trimmed || isStreaming || disabled) return\n onSend(trimmed)\n setText('')\n }, [text, isStreaming, disabled, onSend, setText])\n\n const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n // Respect IME composition — Enter commits the candidate, it doesn't send.\n if (e.nativeEvent.isComposing) return\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n send()\n }\n }\n\n const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => {\n if (e.target.files?.length) onAttach?.(e.target.files)\n e.target.value = ''\n }\n\n const handleFolderChange = (e: ChangeEvent<HTMLInputElement>) => {\n if (e.target.files?.length) (onAttachFolder ?? onAttach)?.(e.target.files)\n e.target.value = ''\n }\n\n const handleDragEnter = useCallback((e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n dragDepth.current++\n if (e.dataTransfer?.types.includes('Files')) setDragOver(true)\n }, [])\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n dragDepth.current--\n if (dragDepth.current <= 0) {\n dragDepth.current = 0\n setDragOver(false)\n }\n }, [])\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n if (e.dataTransfer) e.dataTransfer.dropEffect = 'copy'\n }, [])\n\n const handleDrop = useCallback(\n (e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n dragDepth.current = 0\n setDragOver(false)\n const files = e.dataTransfer?.files\n if (files?.length) onAttach?.(files)\n },\n [onAttach],\n )\n\n const folderChips = pendingFiles.filter((f) => f.kind === 'folder')\n const fileChips = pendingFiles.filter((f) => f.kind !== 'folder')\n const showFooter = controls != null && controlsPlacement === 'footer'\n const showAbove = controls != null && controlsPlacement === 'above'\n\n return (\n <div\n className={`relative ${className ?? ''}`}\n onDragEnter={onAttach ? handleDragEnter : undefined}\n onDragLeave={onAttach ? handleDragLeave : undefined}\n onDragOver={onAttach ? handleDragOver : undefined}\n onDrop={onAttach ? handleDrop : undefined}\n >\n {dragOver && (\n <div className=\"pointer-events-none absolute inset-0 z-10 flex items-center justify-center rounded-2xl border-2 border-dashed border-primary/50 bg-card/95\">\n <div className=\"text-center\">\n <span className=\"mx-auto mb-2 flex h-11 w-11 items-center justify-center rounded-xl bg-primary/10 text-primary\">\n <UploadGlyph className=\"h-5 w-5\" />\n </span>\n <p className=\"text-sm font-semibold text-foreground\">{dropTitle}</p>\n <p className=\"mt-0.5 text-xs text-muted-foreground\">{dropDescription}</p>\n </div>\n </div>\n )}\n\n {showAbove && <div className=\"mb-1.5 flex flex-wrap items-center gap-1.5 px-1\">{controls}</div>}\n\n {pendingFiles.length > 0 && (\n <div className=\"mb-2 flex flex-wrap gap-1.5\">\n {[...folderChips, ...fileChips].map((f) => (\n <span\n key={f.id}\n className={`inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-xs ${\n f.status === 'error'\n ? 'border-destructive/40 text-destructive'\n : 'border-border bg-muted/50 text-foreground'\n }`}\n >\n {f.kind === 'folder' ? <FolderGlyph className=\"h-3 w-3 shrink-0\" /> : <PaperclipGlyph className=\"h-3 w-3 shrink-0\" />}\n <span className=\"max-w-[150px] truncate\">{f.name}</span>\n {f.fileCount !== undefined && <span className=\"text-muted-foreground\">({f.fileCount})</span>}\n {f.status === 'uploading' && (\n <span className=\"h-3 w-3 animate-spin rounded-full border-2 border-primary border-t-transparent\" />\n )}\n {onRemoveFile && (\n <button\n type=\"button\"\n aria-label={`Remove ${f.name}`}\n onClick={() => onRemoveFile(f.id)}\n className=\"rounded p-0.5 text-muted-foreground transition hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <CloseGlyph className=\"h-3 w-3\" />\n </button>\n )}\n </span>\n ))}\n </div>\n )}\n\n <div className=\"flex items-end gap-2 rounded-2xl border border-border bg-card px-2.5 py-2 transition focus-within:border-primary/40 focus-within:ring-2 focus-within:ring-primary/15\">\n {onAttach && (\n <>\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n disabled={disabled}\n aria-label=\"Attach files\"\n title=\"Attach files\"\n className=\"mb-0.5 shrink-0 rounded-lg p-2 text-muted-foreground transition hover:bg-accent/40 hover:text-foreground disabled:opacity-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <PaperclipGlyph className=\"h-4 w-4\" />\n </button>\n <input ref={fileInputRef} type=\"file\" multiple className=\"hidden\" accept={accept} onChange={handleFileChange} />\n </>\n )}\n {onAttachFolder && (\n <>\n <button\n type=\"button\"\n onClick={() => folderInputRef.current?.click()}\n disabled={disabled}\n aria-label=\"Attach folder\"\n title=\"Attach folder\"\n className=\"mb-0.5 shrink-0 rounded-lg p-2 text-muted-foreground transition hover:bg-accent/40 hover:text-foreground disabled:opacity-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <FolderGlyph className=\"h-4 w-4\" />\n </button>\n {/* webkitdirectory is non-standard but widely supported for folder picks. */}\n <input\n ref={folderInputRef}\n type=\"file\"\n multiple\n className=\"hidden\"\n onChange={handleFolderChange}\n {...({ webkitdirectory: '' } as Record<string, string>)}\n />\n </>\n )}\n\n <textarea\n ref={textareaRef}\n value={text}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={disabled}\n rows={1}\n aria-label=\"Message input\"\n className=\"max-h-[168px] min-h-[40px] flex-1 resize-none bg-transparent px-1.5 py-2 text-[15px] leading-6 text-foreground outline-none placeholder:text-muted-foreground disabled:opacity-50\"\n />\n\n {showFooter && <div className=\"mb-0.5 flex shrink-0 items-center gap-1.5\">{controls}</div>}\n\n {isStreaming ? (\n <button\n type=\"button\"\n onClick={onCancel}\n aria-label=\"Stop response\"\n className=\"mb-0.5 inline-flex shrink-0 items-center gap-1.5 rounded-full bg-destructive/15 px-3.5 py-2 text-sm font-medium text-destructive transition hover:bg-destructive/25 focus:outline-none focus-visible:ring-2 focus-visible:ring-destructive/50\"\n >\n <StopGlyph className=\"h-3.5 w-3.5\" />\n <span>Stop</span>\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={send}\n disabled={!canSend}\n aria-label={sendLabel}\n className=\"mb-0.5 inline-flex shrink-0 items-center gap-1.5 rounded-full bg-primary px-3.5 py-2 text-sm font-medium text-primary-foreground shadow-sm transition hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-40 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-card\"\n >\n <SendGlyph className=\"h-3.5 w-3.5\" />\n <span>{sendLabel}</span>\n </button>\n )}\n </div>\n\n {focusShortcut && (\n <div className=\"mt-1.5 flex justify-end px-1\">\n <span className=\"text-xs text-muted-foreground\">\n <kbd className=\"rounded border border-border bg-background px-1 py-0.5 text-[10px]\">Cmd</kbd>\n <kbd className=\"ml-0.5 rounded border border-border bg-background px-1 py-0.5 text-[10px]\">L</kbd>\n <span className=\"ml-1\">to focus</span>\n </span>\n </div>\n )}\n </div>\n )\n}\n","/**\n * Mission + delegation observability surfaces — different nouns, one trace\n * tree:\n *\n * - {@link MissionActivityLane}: the collapsed sub-rows under a mission step\n * (what the step's agent is actually doing), expanding to a compact web\n * waterfall rendered from the `/trace` converters.\n * - {@link AgentActivityPanel}: the standalone cross-context surface — every\n * delegation a workspace ran, regardless of which mission (if any) spawned\n * it — behind a `fetchActivity` data port with cursor + refresh.\n * - {@link FlowWaterfall}: the web counterpart of `/trace`'s ASCII\n * `renderWaterfall` (which stays CLI) — proportional bars over a FlowTrace.\n *\n * Same styling contract as the rest of `/web-react`: Tailwind classes against\n * the shared design tokens, inline SVG glyphs, no icon library. The pure\n * layout/merge/format helpers are exported for tests and reuse.\n */\n\nimport { useCallback, useEffect, useState, type ReactNode } from 'react'\n\nimport type { StepAgentActivity } from '../missions/agent-activity'\nimport type { FlowTrace } from '../trace/index'\nimport { stepActivityFlowTrace } from '../trace/mission-flow'\n\n// ── pure helpers ──────────────────────────────────────────────────────────\n\nexport type ActivityTone = 'live' | 'ok' | 'error' | 'neutral'\n\nconst LIVE_STATUSES = new Set(['pending', 'running'])\nconst OK_STATUSES = new Set(['completed', 'done', 'succeeded'])\nconst ERROR_STATUSES = new Set(['failed', 'error', 'cancelled', 'aborted'])\n\n/** Map a delegation status (free-form string on the wire) to a render tone. */\nexport function activityTone(status: string): ActivityTone {\n const s = status.toLowerCase()\n if (LIVE_STATUSES.has(s)) return 'live'\n if (OK_STATUSES.has(s)) return 'ok'\n if (ERROR_STATUSES.has(s)) return 'error'\n return 'neutral'\n}\n\n/** \"$0.4000\" under a cent shows 4 decimals; null when unknown/zero. */\nexport function formatActivityCost(costUsd?: number): string | null {\n if (costUsd === undefined || !isFinite(costUsd) || costUsd <= 0) return null\n return costUsd < 0.01 ? `$${costUsd.toFixed(4)}` : `$${costUsd.toFixed(2)}`\n}\n\n/** \"8s\" / \"2m 05s\" / \"1h 12m\"; null when unknown. */\nexport function formatActivityDuration(durationMs?: number): string | null {\n if (durationMs === undefined || !isFinite(durationMs) || durationMs < 0) return null\n const totalSeconds = Math.round(durationMs / 1000)\n if (totalSeconds < 60) return `${totalSeconds}s`\n const minutes = Math.floor(totalSeconds / 60)\n const seconds = totalSeconds % 60\n if (minutes < 60) return `${minutes}m ${String(seconds).padStart(2, '0')}s`\n return `${Math.floor(minutes / 60)}h ${String(minutes % 60).padStart(2, '0')}m`\n}\n\n/** A delegation record on the cross-context surface; `missionRef` links a\n * promoted delegation back to the mission/step that spawned it. */\nexport interface AgentActivityRecord extends StepAgentActivity {\n missionRef?: { missionId: string; stepId?: string; label?: string }\n}\n\nexport interface AgentActivityPage {\n items: AgentActivityRecord[]\n /** Opaque continuation token; absent ⇒ no further pages. */\n nextCursor?: string\n}\n\n/**\n * Fold a fetched page into the held rows: dedupe by `taskId` with the\n * incoming row winning (a refresh re-fetches the head page, so newer\n * snapshots of in-flight runs replace stale ones), newest `startedAt` first.\n */\nexport function mergeActivityPages(\n existing: AgentActivityRecord[],\n incoming: AgentActivityRecord[],\n): AgentActivityRecord[] {\n const byTask = new Map<string, AgentActivityRecord>()\n for (const row of existing) byTask.set(row.taskId, row)\n for (const row of incoming) byTask.set(row.taskId, row)\n return [...byTask.values()].sort((a, b) => Date.parse(b.startedAt) - Date.parse(a.startedAt))\n}\n\nexport interface WaterfallRow {\n name: string\n kind: 'pipeline' | 'model' | 'tool'\n /** Bar geometry as percentages of the trace's total span. */\n offsetPct: number\n widthPct: number\n durationLabel: string\n approx: boolean\n /** False only when the span's meta carries an explicit failure. */\n ok: boolean\n}\n\n/** Project a FlowTrace into proportional bar geometry for {@link FlowWaterfall}. */\nexport function waterfallLayout(trace: FlowTrace): WaterfallRow[] {\n const total = trace.totalMs > 0 ? trace.totalMs : 1\n return [...trace.spans]\n .sort((a, b) => a.startMs - b.startMs)\n .map((span) => {\n const meta = span.meta ?? {}\n const failed =\n meta.ok === false || (typeof meta.status === 'string' && activityTone(meta.status) === 'error')\n return {\n name: span.name,\n kind: span.kind,\n offsetPct: Math.max(0, Math.min(100, (span.startMs / total) * 100)),\n widthPct: Math.max(0.5, Math.min(100, ((span.endMs - span.startMs) / total) * 100)),\n durationLabel: `${((span.endMs - span.startMs) / 1000).toFixed(1)}s${span.approx ? '~' : ''}`,\n approx: span.approx === true,\n ok: !failed,\n }\n })\n}\n\n// ── glyphs ────────────────────────────────────────────────────────────────\n\nfunction ChevronGlyph({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n )\n}\n\nfunction RefreshGlyph({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M21 12a9 9 0 1 1-2.64-6.36M21 3v6h-6\" />\n </svg>\n )\n}\n\nfunction CopyGlyph({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" />\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\" />\n </svg>\n )\n}\n\n/** Copy a trace id to the clipboard — the drill-in's actionable handle instead\n * of a bare, dead-end string. Falls back silently when the Clipboard API is\n * unavailable (insecure context / older browser). */\nfunction TraceIdCopy({ traceId }: { traceId: string }) {\n const [copied, setCopied] = useState(false)\n const copy = useCallback(() => {\n void navigator.clipboard?.writeText(traceId).then(\n () => {\n setCopied(true)\n setTimeout(() => setCopied(false), 1200)\n },\n () => {},\n )\n }, [traceId])\n return (\n <button\n type=\"button\"\n onClick={copy}\n title=\"Copy trace id\"\n aria-label=\"Copy trace id\"\n className=\"inline-flex min-w-0 items-center gap-1.5 rounded text-left font-mono text-muted-foreground transition hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-card\"\n >\n <span className=\"truncate\">{traceId}</span>\n <CopyGlyph className=\"h-3 w-3 shrink-0\" />\n {copied && <span className=\"shrink-0 not-italic text-success\">copied</span>}\n </button>\n )\n}\n\nfunction StatusDot({ tone }: { tone: ActivityTone }) {\n return (\n <span className=\"inline-flex items-center\">\n <span\n aria-hidden\n className={`h-2 w-2 shrink-0 rounded-full ${\n tone === 'live' ? 'animate-pulse bg-warning' : tone === 'ok' ? 'bg-success' : tone === 'error' ? 'bg-destructive' : 'bg-muted-foreground/40'\n }`}\n />\n <span className=\"sr-only\">{tone}</span>\n </span>\n )\n}\n\n// ── FlowWaterfall ─────────────────────────────────────────────────────────\n\nconst BAR_CLASS: Record<WaterfallRow['kind'], string> = {\n pipeline: 'bg-muted-foreground/30',\n model: 'bg-primary/60',\n tool: 'bg-primary',\n}\n\nexport interface FlowWaterfallProps {\n trace: FlowTrace\n}\n\n/** Compact proportional waterfall over a FlowTrace — span name, bar, duration\n * per row; total + cost in the footer. */\nexport function FlowWaterfall({ trace }: FlowWaterfallProps) {\n const rows = waterfallLayout(trace)\n if (rows.length === 0) return null\n const cost = formatActivityCost(trace.costUsd)\n return (\n <div className=\"space-y-1\">\n {rows.map((row, i) => (\n <div key={i} className=\"grid grid-cols-[minmax(0,2fr)_minmax(0,3fr)_auto] items-center gap-2\">\n <span className=\"truncate font-mono text-[11px] text-muted-foreground\" title={row.name}>\n {row.name}\n </span>\n <div className=\"relative h-2 rounded-sm bg-muted/40\">\n <div\n className={`absolute inset-y-0 rounded-sm ${row.ok ? BAR_CLASS[row.kind] : 'bg-destructive/80'} ${row.approx ? 'opacity-70' : ''}`}\n style={{ left: `${row.offsetPct}%`, width: `${row.widthPct}%` }}\n />\n </div>\n <span className=\"shrink-0 font-mono text-[10px] tabular-nums text-muted-foreground/70\">{row.durationLabel}</span>\n </div>\n ))}\n <p className=\"pt-0.5 text-right font-mono text-[10px] tabular-nums text-muted-foreground/60\">\n {(trace.totalMs / 1000).toFixed(1)}s{cost ? ` · ${cost}` : ''}\n </p>\n </div>\n )\n}\n\n// ── MissionActivityLane ───────────────────────────────────────────────────\n\nexport interface MissionActivityLaneProps {\n /** The step's delegated-run snapshot (`MissionStepState.agentActivity`). */\n activity: StepAgentActivity[]\n /** Epoch ms origin for the expanded waterfall — usually the step start. */\n startedAt?: number\n /** Wall clock for extending in-flight runs on the waterfall. */\n nowMs?: number\n}\n\n/**\n * Collapsed sub-rows under a mission step — one row per delegated run —\n * expanding to the step's waterfall. Renders nothing for an empty lane.\n */\nexport function MissionActivityLane({ activity, startedAt, nowMs }: MissionActivityLaneProps) {\n const [expanded, setExpanded] = useState(false)\n if (activity.length === 0) return null\n\n return (\n <div className=\"mt-1 border-l border-border/50 pl-3\">\n {activity.map((run) => {\n const tone = activityTone(run.status)\n const cost = formatActivityCost(run.costUsd)\n const duration = formatActivityDuration(run.durationMs)\n return (\n <div key={run.taskId} className=\"flex items-center gap-2 py-1 text-xs\">\n <StatusDot tone={tone} />\n <span className=\"min-w-0 flex-1 truncate\">\n <span className=\"font-medium\">{run.tool}</span>\n <span className=\"text-muted-foreground\"> — {run.detail}</span>\n </span>\n {tone === 'live' && (run.iteration !== undefined || run.phase !== undefined) && (\n <span className=\"shrink-0 rounded-full bg-warning/10 px-1.5 py-0.5 font-mono text-[10px] text-warning\">\n {[run.iteration !== undefined ? `iter ${run.iteration}` : null, run.phase ?? null]\n .filter(Boolean)\n .join(' · ')}\n </span>\n )}\n <span className=\"flex shrink-0 items-center gap-1.5 font-mono text-[10px] tabular-nums text-muted-foreground/70\">\n {tone !== 'live' && tone !== 'ok' && <span>{run.status}</span>}\n {cost && <span>{cost}</span>}\n {duration && <span>{duration}</span>}\n </span>\n </div>\n )\n })}\n <button\n type=\"button\"\n onClick={() => setExpanded((v) => !v)}\n className=\"flex items-center gap-1 py-0.5 text-[10px] font-medium text-muted-foreground/70 transition hover:text-foreground\"\n >\n <ChevronGlyph className={`h-3 w-3 transition-transform ${expanded ? 'rotate-180' : ''}`} />\n timeline\n </button>\n {expanded && (\n <div className=\"rounded-md border border-border/50 bg-muted/10 p-2\">\n <FlowWaterfall\n trace={stepActivityFlowTrace(activity, {\n ...(startedAt !== undefined ? { startedAt } : {}),\n ...(nowMs !== undefined ? { nowMs } : {}),\n })}\n />\n </div>\n )}\n </div>\n )\n}\n\n// ── AgentActivityPanel ────────────────────────────────────────────────────\n\nexport interface AgentActivityPanelProps {\n /** Data port — page through the product's delegation records. Called with\n * no cursor on mount/refresh, with `nextCursor` for older pages. */\n fetchActivity: (cursor?: string) => Promise<AgentActivityPage>\n /** Render the mission link for a promoted delegation (chip, anchor, router\n * Link — the product's routing, not ours). */\n renderMissionRef?: (ref: NonNullable<AgentActivityRecord['missionRef']>, record: AgentActivityRecord) => ReactNode\n title?: string\n emptyLabel?: string\n}\n\nfunction ActivityRow({\n record,\n renderMissionRef,\n}: {\n record: AgentActivityRecord\n renderMissionRef?: AgentActivityPanelProps['renderMissionRef']\n}) {\n const [open, setOpen] = useState(false)\n const tone = activityTone(record.status)\n const cost = formatActivityCost(record.costUsd)\n const duration = formatActivityDuration(record.durationMs)\n\n return (\n <div className=\"rounded-lg border border-border/60 bg-card\">\n <button type=\"button\" onClick={() => setOpen((v) => !v)} className=\"flex w-full items-center gap-2.5 px-3 py-2 text-left text-sm\">\n <StatusDot tone={tone} />\n <span className=\"min-w-0 flex-1 truncate\">\n <span className=\"font-medium\">{record.tool}</span>\n <span className=\"text-muted-foreground\"> — {record.detail}</span>\n </span>\n {tone === 'live' && (record.iteration !== undefined || record.phase !== undefined) && (\n <span className=\"shrink-0 rounded-full bg-warning/10 px-2 py-0.5 font-mono text-[10px] text-warning\">\n {[record.iteration !== undefined ? `iter ${record.iteration}` : null, record.phase ?? null]\n .filter(Boolean)\n .join(' · ')}\n </span>\n )}\n <span\n className={`shrink-0 rounded-full px-2 py-0.5 text-[10px] font-medium ${\n tone === 'ok'\n ? 'bg-success/10 text-success'\n : tone === 'error'\n ? 'bg-destructive/10 text-destructive'\n : tone === 'live'\n ? 'bg-warning/10 text-warning'\n : 'bg-muted/60 text-muted-foreground'\n }`}\n >\n {record.status}\n </span>\n {cost && <span className=\"shrink-0 font-mono text-[11px] tabular-nums text-muted-foreground\">{cost}</span>}\n <ChevronGlyph className={`h-3 w-3 shrink-0 text-muted-foreground transition-transform ${open ? 'rotate-180' : ''}`} />\n </button>\n {open && (\n <div className=\"space-y-2.5 border-t border-border/40 px-3 py-2.5\">\n {record.durationMs !== undefined && (\n <div className=\"rounded-md border border-border/50 bg-muted/10 p-2\">\n <FlowWaterfall trace={stepActivityFlowTrace([record])} />\n </div>\n )}\n <dl className=\"grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 font-mono text-[11px]\">\n <dt className=\"text-muted-foreground/60\">task</dt>\n <dd className=\"truncate text-muted-foreground\">{record.taskId}</dd>\n <dt className=\"text-muted-foreground/60\">started</dt>\n <dd className=\"text-muted-foreground\">{new Date(record.startedAt).toLocaleString()}</dd>\n {duration && (\n <>\n <dt className=\"text-muted-foreground/60\">duration</dt>\n <dd className=\"text-muted-foreground\">{duration}</dd>\n </>\n )}\n {record.traceId && (\n <>\n <dt className=\"text-muted-foreground/60\">trace</dt>\n <dd className=\"min-w-0\">\n <TraceIdCopy traceId={record.traceId} />\n </dd>\n </>\n )}\n </dl>\n {record.missionRef && renderMissionRef?.(record.missionRef, record)}\n </div>\n )}\n </div>\n )\n}\n\n/**\n * The standalone cross-context delegation surface: every agent run the\n * product journaled, mission-spawned or not, with status, cost, drill-in, and\n * a mission link slot for promoted delegations.\n */\nexport function AgentActivityPanel({ fetchActivity, renderMissionRef, title = 'Agent activity', emptyLabel = 'No agent runs yet.' }: AgentActivityPanelProps) {\n const [rows, setRows] = useState<AgentActivityRecord[]>([])\n const [cursor, setCursor] = useState<string | undefined>(undefined)\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const load = useCallback(\n async (from?: string) => {\n setLoading(true)\n setError(null)\n try {\n const page = await fetchActivity(from)\n setRows((prev) => mergeActivityPages(from === undefined ? [] : prev, page.items))\n setCursor(page.nextCursor)\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e))\n } finally {\n setLoading(false)\n }\n },\n [fetchActivity],\n )\n\n useEffect(() => {\n void load()\n }, [load])\n\n return (\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-2\">\n <h2 className=\"flex-1 text-sm font-semibold\">{title}</h2>\n <button\n type=\"button\"\n onClick={() => void load()}\n disabled={loading}\n aria-label=\"Refresh\"\n className=\"rounded-md p-1.5 text-muted-foreground transition hover:bg-accent/30 hover:text-foreground disabled:opacity-50\"\n >\n <RefreshGlyph className={`h-3.5 w-3.5 ${loading ? 'animate-spin' : ''}`} />\n </button>\n </div>\n {error && <p role=\"alert\" className=\"rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-xs text-destructive\">{error}</p>}\n {!error && rows.length === 0 && !loading && <p className=\"px-1 text-sm text-muted-foreground\">{emptyLabel}</p>}\n <div className=\"space-y-1.5\">\n {rows.map((record) => (\n <ActivityRow key={record.taskId} record={record} renderMissionRef={renderMissionRef} />\n ))}\n </div>\n {cursor && (\n <button\n type=\"button\"\n onClick={() => void load(cursor)}\n disabled={loading}\n className=\"w-full rounded-md border border-border bg-card px-3 py-1.5 text-xs font-medium text-muted-foreground transition hover:bg-accent/30 disabled:opacity-50\"\n >\n Older runs\n </button>\n )}\n </div>\n )\n}\n","/**\n * `SeatPaywall` — the shared \"unlock this product\" screen every agent app\n * shows when a user has no active seat and has spent past the free tier. One\n * component, adopted by all five products (gtm / creative / tax / legal /\n * insurance) in ~2 lines.\n *\n * Copy contract (design §6.8): the included monthly AI usage is framed as a\n * BENEFIT the buyer receives — never the ratio, never the word \"margin\", never\n * \"we debit 50%\". Surface the allowance, hide the economics.\n *\n * Styling contract matches the rest of `web-react`: Tailwind classes over the\n * shared design tokens (`bg-card`, `border-border`, `text-muted-foreground`,\n * `bg-primary`, …); glyphs are inline SVGs; no icon or UI library.\n */\n\nimport type { ReactNode } from 'react'\n\nimport { usePending } from './controls'\n\nexport interface SeatPaywallProps {\n /** Human product name shown in the headline, e.g. \"Creative\". */\n product: string\n /** Fired when the user clicks the unlock CTA — route them to checkout. When\n * it returns a promise the button shows a pending state and ignores repeat\n * clicks until it settles (no double-charge on a slow checkout open). */\n onCheckout: () => void | Promise<void>\n /** Monthly seat price in whole dollars. Default 100. */\n priceUsd?: number\n /** Included monthly AI usage in whole dollars. Default 50. */\n includedUsageUsd?: number\n /** Optional one-line value prop under the headline. */\n tagline?: string\n /** CTA label. Default \"Unlock {product}\". */\n ctaLabel?: string\n /** Value-prop bullets. Default = product/usage-derived only; pass your own to\n * supply product-specific value props (the shell bakes no GTM copy). */\n benefits?: ReactNode[]\n /** Optional fine print under the CTA (e.g. \"Cancel anytime.\"). Omitted by default. */\n footnote?: ReactNode\n}\n\nfunction CheckGlyph(): ReactNode {\n return (\n <svg\n className=\"h-4 w-4 shrink-0 text-primary\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n >\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n )\n}\n\nfunction Benefit({ children }: { children: ReactNode }): ReactNode {\n return (\n <li className=\"flex items-start gap-2.5 text-sm text-foreground\">\n <span className=\"mt-0.5\">\n <CheckGlyph />\n </span>\n <span>{children}</span>\n </li>\n )\n}\n\n/**\n * Centered card paywall. The price line reads\n * \"$100/mo · includes $50/mo of AI usage\" so the included allowance anchors the\n * value without ever exposing the ratio.\n */\nexport function SeatPaywall({\n product,\n onCheckout,\n priceUsd = 100,\n includedUsageUsd = 50,\n tagline,\n ctaLabel,\n benefits,\n footnote,\n}: SeatPaywallProps): ReactNode {\n const { pending, run } = usePending()\n return (\n <div className=\"flex min-h-[60vh] w-full items-center justify-center p-6\">\n <div className=\"w-full max-w-md rounded-2xl border border-border bg-card p-8 shadow-sm\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n {product}\n </p>\n <h1 className=\"mt-2 text-2xl font-semibold tracking-tight text-foreground\">\n Unlock {product}\n </h1>\n {tagline && <p className=\"mt-2 text-sm text-muted-foreground\">{tagline}</p>}\n\n <div className=\"mt-6 flex items-baseline gap-1.5\">\n <span className=\"text-3xl font-semibold text-foreground\">${priceUsd}</span>\n <span className=\"text-sm text-muted-foreground\">/mo</span>\n </div>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n Includes ${includedUsageUsd}/mo of AI usage\n </p>\n\n <ul className=\"mt-6 space-y-2.5\">\n {(benefits ?? [\n `Full access to ${product}`,\n `$${includedUsageUsd}/mo of AI usage included, every month`,\n ]).map((benefit, i) => (\n <Benefit key={i}>{benefit}</Benefit>\n ))}\n </ul>\n\n <button\n type=\"button\"\n disabled={pending}\n onClick={() => run(onCheckout)}\n className=\"mt-7 inline-flex w-full items-center justify-center rounded-xl bg-primary px-4 py-2.5 text-sm font-medium text-primary-foreground transition hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-70\"\n >\n {pending ? 'Opening checkout…' : ctaLabel ?? `Unlock ${product}`}\n </button>\n {footnote && (\n <p className=\"mt-3 text-center text-xs text-muted-foreground/70\">\n {footnote}\n </p>\n )}\n </div>\n </div>\n )\n}\n","/**\n * `AgentSessionControls` — the model + harness + reasoning-effort cluster a chat\n * composer docks. One component so every product's two composers (and every\n * product) share the same control surface and harness↔model coherence policy.\n *\n * Two layouts, additive — the default preserves the prior hand-rolled behavior:\n * - `layout=\"inline\"` (default): model, harness, and effort sit side by side as\n * pills. This is the original arrangement; existing call sites that mounted\n * `ModelPicker` + a harness picker + `EffortPicker` in a row get the same UI.\n * - `layout=\"compact\"`: the model picker stays inline and visible; the agent\n * backend (\"harness\") and reasoning-effort controls — internal jargon a user\n * rarely needs — tuck behind a single gear popover with plain-English copy.\n *\n * Harness ↔ model coherence is identical in both layouts, via the substrate's\n * snap helpers (`@tangle-network/agent-app/harness`): changing the harness snaps\n * an incompatible model to that harness's best catalog option; changing the\n * model switches to the model's native harness. Catalog model ids are canonical\n * (\"provider/model\"), which is exactly what the snap helpers expect — no id\n * translation is needed here.\n *\n * Dependency-free beyond React: inline SVG glyphs, CSS-var / Tailwind tokens the\n * app shell defines. The harness picker is rendered inline so this needs no\n * sandbox-ui dependency.\n */\n\nimport { useMemo, useState, type ReactNode } from 'react'\nimport {\n snapHarnessToModel,\n snapModelToHarness,\n type Harness,\n} from '../harness'\nimport type { CatalogModel } from '../runtime/model-catalog'\nimport { ModelPicker, EffortPicker, usePopover } from './controls'\n\n/** Plain-English labels for the harnesses a product is likely to expose. Unknown\n * ids fall back to the raw value so a new backend still renders a usable label. */\nconst HARNESS_LABELS: Partial<Record<Harness, string>> = {\n opencode: 'OpenCode (any model)',\n 'claude-code': 'Claude Code (Anthropic)',\n codex: 'Codex (OpenAI)',\n 'kimi-code': 'Kimi (Moonshot)',\n amp: 'Amp',\n 'factory-droids': 'Factory Droids',\n cursor: 'Cursor',\n hermes: 'Hermes',\n forge: 'Forge',\n pi: 'Pi',\n openclaw: 'OpenClaw',\n acp: 'ACP',\n 'cli-base': 'CLI',\n}\n\nfunction harnessLabel(h: Harness): string {\n return HARNESS_LABELS[h] ?? h\n}\n\nfunction ChevronDown({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n )\n}\n\nfunction GearGlyph({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n <path d=\"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z\" />\n </svg>\n )\n}\n\n/** Tailwind utilities for keyboard-visible focus on popover options + triggers. */\nconst FOCUS_RING =\n 'focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background'\n\n/** Pill-styled harness picker — inline, no sandbox-ui dependency. */\nfunction HarnessPicker({\n value,\n onChange,\n available,\n}: {\n value: Harness\n onChange: (h: Harness) => void\n available?: ReadonlyArray<Harness>\n}) {\n const [open, setOpen] = useState(false)\n const { containerRef, triggerProps } = usePopover(open, setOpen)\n const options = available ?? (Object.keys(HARNESS_LABELS) as Harness[])\n return (\n <div ref={containerRef} className=\"relative inline-flex\">\n <button\n type=\"button\"\n {...triggerProps}\n onClick={() => setOpen(!open)}\n title=\"Agent backend\"\n className={`inline-flex w-full items-center justify-between gap-1.5 rounded-lg border border-border bg-card px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-accent/30 ${FOCUS_RING}`}\n >\n <span className=\"truncate\">{harnessLabel(value)}</span>\n <ChevronDown className=\"h-3.5 w-3.5 text-muted-foreground\" />\n </button>\n {open && (\n <div role=\"menu\" className=\"absolute bottom-full left-0 z-50 mb-2 max-h-64 w-full min-w-[220px] overflow-y-auto rounded-xl border border-border bg-card p-1 shadow-lg\">\n {options.map((h) => (\n <button\n key={h}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={h === value}\n onClick={() => {\n onChange(h)\n setOpen(false)\n }}\n className={`flex w-full items-center rounded-md px-3 py-2 text-left text-sm transition ${FOCUS_RING} ${\n h === value ? 'bg-primary/10 font-medium' : 'hover:bg-accent/30'\n }`}\n >\n {harnessLabel(h)}\n </button>\n ))}\n </div>\n )}\n </div>\n )\n}\n\nexport interface AgentSessionControlsProps {\n /** Catalog models — canonical provider-prefixed ids. */\n models: CatalogModel[]\n modelsLoading?: boolean\n /** Selected canonical model id. */\n model: string\n onModelChange(modelId: string): void\n /** Current harness; harness↔model coherence is enforced on every change. */\n harness: Harness\n onHarnessChange(harness: Harness): void\n /** Harnesses to offer; defaults to the labeled set. */\n availableHarnesses?: ReadonlyArray<Harness>\n /** Reasoning-effort value + setter. Shown only when the selected model\n * `supportsReasoning`, matching `EffortPicker`'s guidance. */\n effort: string\n onEffortChange(effort: string): void\n /**\n * `inline` (default): model, harness, effort side by side — the prior\n * behavior. `compact`: model inline, harness + effort behind a gear popover.\n */\n layout?: 'inline' | 'compact'\n /** Hide the harness control entirely (single-harness products). */\n showHarness?: boolean\n renderProviderBadge?: (provider: string) => ReactNode\n className?: string\n}\n\n/**\n * Apply the harness↔model coherence policy and emit the resulting change(s).\n * Returned from a hook-free helper so both layouts share one implementation.\n */\nfunction useCoherentHandlers(props: AgentSessionControlsProps) {\n const { model, models, harness, onModelChange, onHarnessChange } = props\n const canonicalIds = useMemo(() => models.map((m) => m.id), [models])\n\n const onModel = (next: string) => {\n onModelChange(next)\n const nextHarness = snapHarnessToModel(harness, next)\n if (nextHarness !== harness) onHarnessChange(nextHarness)\n }\n\n const onHarness = (next: Harness) => {\n onHarnessChange(next)\n const snapped = snapModelToHarness(next, model, canonicalIds)\n if (snapped !== model) onModelChange(snapped)\n }\n\n return { onModel, onHarness }\n}\n\nexport function AgentSessionControls(props: AgentSessionControlsProps) {\n const {\n models,\n modelsLoading,\n model,\n harness,\n availableHarnesses,\n effort,\n onEffortChange,\n layout = 'inline',\n showHarness = true,\n renderProviderBadge,\n className,\n } = props\n const { onModel, onHarness } = useCoherentHandlers(props)\n const [open, setOpen] = useState(false)\n const { containerRef: popoverRef, triggerProps } = usePopover(open, setOpen)\n\n const selectedModel = models.find((m) => m.id === model)\n const showEffort = selectedModel?.supportsReasoning ?? true\n\n const modelPicker = (\n <ModelPicker\n value={model}\n onChange={onModel}\n models={models}\n loading={modelsLoading}\n renderProviderBadge={renderProviderBadge}\n />\n )\n\n if (layout === 'inline') {\n return (\n <div className={`flex items-center gap-1.5 ${className ?? ''}`}>\n {modelPicker}\n {showHarness && (\n <HarnessPicker value={harness} onChange={onHarness} available={availableHarnesses} />\n )}\n {showEffort && <EffortPicker value={effort} onChange={onEffortChange} />}\n </div>\n )\n }\n\n // compact: model inline; harness + effort behind a gear popover.\n const hasAdvanced = showHarness || showEffort\n return (\n <div className={`flex items-center gap-1.5 ${className ?? ''}`}>\n {modelPicker}\n {hasAdvanced && (\n <div ref={popoverRef} className=\"relative inline-flex\">\n <button\n type=\"button\"\n {...triggerProps}\n onClick={() => setOpen(!open)}\n title=\"Model settings — pick the agent backend and how hard it thinks\"\n className={`flex h-8 w-8 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-muted hover:text-foreground data-[state=open]:bg-muted ${FOCUS_RING}`}\n data-state={open ? 'open' : 'closed'}\n >\n <GearGlyph className=\"h-4 w-4\" />\n </button>\n {open && (\n <div className=\"absolute bottom-full left-0 z-50 mb-2 w-72 space-y-3 rounded-xl border border-border bg-card p-3 shadow-lg\">\n {showHarness && (\n <div className=\"space-y-1.5\">\n <p className=\"text-xs font-medium text-foreground\">Agent backend</p>\n <HarnessPicker value={harness} onChange={onHarness} available={availableHarnesses} />\n <p className=\"text-[11px] leading-snug text-muted-foreground\">\n The engine that runs the agent. Switching it keeps your model choice compatible.\n </p>\n </div>\n )}\n {showEffort && (\n <div className=\"space-y-1.5\">\n <p className=\"text-xs font-medium text-foreground\">Thinking</p>\n <EffortPicker value={effort} onChange={onEffortChange} label=\"\" />\n <p className=\"text-[11px] leading-snug text-muted-foreground\">\n How hard the agent thinks before answering. Higher is slower but more thorough.\n </p>\n </div>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n )\n}\n"],"mappings":"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","names":["useEffect","useMemo","useRef","useState","useEffect","useRef","useState","jsx","jsxs","useRef","useEffect","useState","jsx","useEffect","useRef","useState","Fragment","jsx","jsxs","useCallback","useEffect","useState","Fragment","jsx","jsxs","useState","useCallback","useEffect","jsx","jsxs","useMemo","useState","jsx","jsxs","ChevronDown","useState","useMemo","Fragment","jsx","jsxs","useState","useMemo","useRef","useEffect"]}