Download apps/vis/web/src/components/wire/renderers.tsx from SaylorTwift/kimi-code: direct link, hf CLI and curl.
- Browser
- Download file 43.9 kB
-
https://huggingface.co/SaylorTwift/kimi-code/resolve/main/apps/vis/web/src/components/wire/renderers.tsx
- Command line
-
hf download hf://SaylorTwift/kimi-code/apps/vis/web/src/components/wire/renderers.tsx
-
curl -L -o renderers.tsx https://huggingface.co/SaylorTwift/kimi-code/resolve/main/apps/vis/web/src/components/wire/renderers.tsx
43.9 kB
| // The single wire-renderer registry. Co-locates tone + label + headline + | |
| // detail for every record kind. Because `WIRE_RENDERERS` is typed as a mapped | |
| // type over the FULL `RecordType` union, TypeScript REQUIRES an entry for each | |
| // kind: adding a kind upstream in agent-core-v2 fails | |
| // `pnpm --filter @moonshot-ai/vis-web typecheck` here until a renderer is | |
| // added. This is the anti-rot guarantee that keeps vis from silently falling | |
| // behind the wire protocol. | |
| import type { ReactNode } from 'react'; | |
| import type { AgentRecord, AgentRecordOf } from '../../types'; | |
| import type { PillTone } from '../shared/Pill'; | |
| import { Pill } from '../shared/Pill'; | |
| import { | |
| Dim, | |
| type HeadlineRender, | |
| LoopEventDetail, | |
| MessageDetail, | |
| Mono, | |
| ContentPartView, | |
| FieldRow, | |
| firstText, | |
| truncate, | |
| loopEventSummary, | |
| } from './parts'; | |
| import { SizePreview } from '../shared/SizePreview'; | |
| import { JsonViewer } from '../shared/JsonViewer'; | |
| export type RecordType = AgentRecord['type']; | |
| export interface WireRenderer<K extends RecordType> { | |
| tone: PillTone; | |
| /** Compact badge label. */ | |
| label: string; | |
| /** One-line collapsed summary. */ | |
| headline: (r: AgentRecordOf<K>) => HeadlineRender; | |
| /** Expanded detail. Omit to fall back to a full structured JSON dump. */ | |
| detail?: (r: AgentRecordOf<K>) => ReactNode; | |
| } | |
| /** A registry entry for every record kind. The value type is a mapped type | |
| * over the full `RecordType` union, so TypeScript forces an entry per kind. */ | |
| type RendererMap = { [K in RecordType]: WireRenderer<K> }; | |
| interface CompactionSummaryView { | |
| label: 'summary' | 'contextSummary'; | |
| text: string; | |
| contextSummary?: string; | |
| message?: UnknownObject; | |
| } | |
| /** Normalize all three `context.apply_compaction` summary variants without | |
| * trusting imported wire payloads. */ | |
| function compactionSummaryView( | |
| r: AgentRecordOf<'context.apply_compaction'>, | |
| ): CompactionSummaryView { | |
| const record = r as unknown as UnknownObject; | |
| const summary = record.summary; | |
| const contextSummary = | |
| typeof record.contextSummary === 'string' ? record.contextSummary : undefined; | |
| if (typeof summary === 'string') { | |
| return { | |
| label: 'summary', | |
| text: summary, | |
| contextSummary: contextSummary === summary ? undefined : contextSummary, | |
| }; | |
| } | |
| const message = asObject(summary); | |
| const content = message?.content; | |
| if (Array.isArray(content)) { | |
| let text = ''; | |
| for (const part of content) { | |
| const candidate = asObject(part); | |
| if (candidate?.type === 'text' && typeof candidate.text === 'string') { | |
| text += candidate.text; | |
| } | |
| } | |
| return { | |
| label: 'summary', | |
| text, | |
| contextSummary: contextSummary === text ? undefined : contextSummary, | |
| message, | |
| }; | |
| } | |
| if (summary === undefined && contextSummary !== undefined) { | |
| return { label: 'contextSummary', text: contextSummary }; | |
| } | |
| return { | |
| label: 'summary', | |
| text: invalidValue(summary), | |
| contextSummary, | |
| }; | |
| } | |
| type UnknownObject = Record<string, unknown>; | |
| function asObject(value: unknown): UnknownObject | undefined { | |
| return typeof value === 'object' && value !== null && !Array.isArray(value) | |
| ? (value as UnknownObject) | |
| : undefined; | |
| } | |
| function wireLineRange(value: unknown): { start: number; end: number } | undefined { | |
| const range = asObject(value); | |
| if (range === undefined) return undefined; | |
| const { start, end } = range; | |
| if ( | |
| typeof start !== 'number' || | |
| !Number.isFinite(start) || | |
| !Number.isInteger(start) || | |
| start < 0 || | |
| typeof end !== 'number' || | |
| !Number.isFinite(end) || | |
| !Number.isInteger(end) || | |
| end < 0 | |
| ) { | |
| return undefined; | |
| } | |
| return { start, end }; | |
| } | |
| function valuePreview(value: unknown): string { | |
| if (value === null) return 'null'; | |
| if (typeof value === 'string') return JSON.stringify(value); | |
| if ( | |
| typeof value === 'number' || | |
| typeof value === 'boolean' || | |
| typeof value === 'bigint' | |
| ) { | |
| return String(value); | |
| } | |
| if (value === undefined) return 'undefined'; | |
| try { | |
| const serialized = JSON.stringify(value); | |
| return serialized === undefined ? `[${typeof value}]` : truncate(serialized, 80); | |
| } catch { | |
| return '[unserializable]'; | |
| } | |
| } | |
| function invalidValue(value: unknown): string { | |
| return value === undefined ? '(missing)' : `(invalid: ${valuePreview(value)})`; | |
| } | |
| function stringValue(value: unknown): string { | |
| return typeof value === 'string' ? value : invalidValue(value); | |
| } | |
| function numberValue(value: unknown): string { | |
| return typeof value === 'number' && Number.isFinite(value) | |
| ? String(value) | |
| : invalidValue(value); | |
| } | |
| function checkpointPhase(value: unknown): { label: string; tone: PillTone } { | |
| if (value === undefined || value === 'start') return { label: 'start', tone: 'lifecycle' }; | |
| if (value === 'end') return { label: 'end', tone: 'success' }; | |
| return { label: invalidValue(value), tone: 'warning' }; | |
| } | |
| function trackedStatus(value: unknown): { label: string; tone: PillTone } { | |
| const entry = asObject(value); | |
| if (entry === undefined) return { label: 'entry unavailable', tone: 'warning' }; | |
| if (entry.oversize === true) return { label: 'oversize', tone: 'warning' }; | |
| if (entry.oversize !== undefined && typeof entry.oversize !== 'boolean') { | |
| return { label: 'invalid entry', tone: 'warning' }; | |
| } | |
| if (entry.key === null) return { label: 'new', tone: 'info' }; | |
| if (typeof entry.key !== 'string') return { label: 'invalid entry', tone: 'warning' }; | |
| if (typeof entry.version !== 'number' || !Number.isFinite(entry.version)) { | |
| return { label: 'invalid version', tone: 'warning' }; | |
| } | |
| return { label: `v${entry.version}`, tone: 'tools' }; | |
| } | |
| function snapshotKey(entry: UnknownObject | undefined): { label: string; dim: boolean } { | |
| if (entry === undefined) return { label: '(entry unavailable)', dim: true }; | |
| if (entry.oversize === true) return { label: '(not captured: oversized)', dim: true }; | |
| if (entry.key === null) return { label: '(file did not exist)', dim: true }; | |
| if (typeof entry.key === 'string') return { label: entry.key, dim: false }; | |
| return { label: invalidValue(entry.key), dim: true }; | |
| } | |
| function sizeValue(value: unknown): string { | |
| return typeof value === 'number' && Number.isFinite(value) | |
| ? `${value}b` | |
| : invalidValue(value); | |
| } | |
| function timestampValue(value: unknown): string { | |
| if (typeof value !== 'number' || !Number.isFinite(value)) return invalidValue(value); | |
| return new Date(value).toLocaleString(); | |
| } | |
| function optionalNumberValue(value: unknown, fallback: string): string { | |
| return value === undefined ? fallback : numberValue(value); | |
| } | |
| function compactionCount(record: UnknownObject): { label: 'compactedCount' | 'count'; value: string } { | |
| if (record.compactedCount !== undefined) { | |
| return { label: 'compactedCount', value: numberValue(record.compactedCount) }; | |
| } | |
| if (record.count !== undefined) { | |
| return { label: 'count', value: numberValue(record.count) }; | |
| } | |
| return { label: 'compactedCount', value: '(missing)' }; | |
| } | |
| export const WIRE_RENDERERS: RendererMap = { | |
| metadata: { | |
| tone: 'meta', | |
| label: 'meta', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Mono>protocol v{r.protocol_version}</Mono> | |
| <Dim>·</Dim> | |
| <Mono>created {new Date(r.created_at).toLocaleString()}</Mono> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'file_history.checkpoint': { | |
| tone: 'lifecycle', | |
| label: 'files·checkpoint', | |
| headline: (r) => { | |
| const record = r as unknown as UnknownObject; | |
| const phase = checkpointPhase(record.phase); | |
| const entries = asObject(record.entries); | |
| const count = entries === undefined ? undefined : Object.keys(entries).length; | |
| return { | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Mono>turn {numberValue(record.turnId)}</Mono> | |
| <Dim> | |
| {count === undefined | |
| ? 'entries unavailable' | |
| : `${count} file${count === 1 ? '' : 's'}`} | |
| </Dim> | |
| </span> | |
| ), | |
| right: ( | |
| <Pill tone={phase.tone} variant="outline"> | |
| {phase.label} | |
| </Pill> | |
| ), | |
| }; | |
| }, | |
| detail: (r) => { | |
| const record = r as unknown as UnknownObject; | |
| const phase = checkpointPhase(record.phase); | |
| return ( | |
| <div className="grid grid-cols-[140px_1fr] gap-x-3 gap-y-[2px]"> | |
| <FieldRow label="turnId"> | |
| <span className="text-[var(--color-sev-info)]">{numberValue(record.turnId)}</span> | |
| </FieldRow> | |
| <FieldRow label="phase"> | |
| <Mono>{phase.label}</Mono> | |
| </FieldRow> | |
| <FieldRow label="entries" wide> | |
| <JsonViewer value={record.entries} defaultOpenDepth={2} /> | |
| </FieldRow> | |
| </div> | |
| ); | |
| }, | |
| }, | |
| 'file_history.tracked': { | |
| tone: 'tools', | |
| label: 'file·tracked', | |
| headline: (r) => { | |
| const record = r as unknown as UnknownObject; | |
| const status = trackedStatus(record.entry); | |
| return { | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Mono>turn {numberValue(record.turnId)}</Mono> | |
| <Dim className="truncate">{stringValue(record.path)}</Dim> | |
| </span> | |
| ), | |
| right: ( | |
| <Pill tone={status.tone} variant="outline"> | |
| {status.label} | |
| </Pill> | |
| ), | |
| }; | |
| }, | |
| detail: (r) => { | |
| const record = r as unknown as UnknownObject; | |
| const entry = asObject(record.entry); | |
| const key = snapshotKey(entry); | |
| const malformedOversize = | |
| entry !== undefined && | |
| entry.oversize !== undefined && | |
| typeof entry.oversize !== 'boolean'; | |
| return ( | |
| <div className="grid grid-cols-[140px_1fr] gap-x-3 gap-y-[2px]"> | |
| <FieldRow label="turnId"> | |
| <span className="text-[var(--color-sev-info)]">{numberValue(record.turnId)}</span> | |
| </FieldRow> | |
| <FieldRow label="path" wide> | |
| <Mono className="break-all">{stringValue(record.path)}</Mono> | |
| </FieldRow> | |
| <FieldRow label="version"> | |
| <span className="text-[var(--color-sev-info)]"> | |
| {entry === undefined ? '(entry unavailable)' : numberValue(entry.version)} | |
| </span> | |
| </FieldRow> | |
| <FieldRow label="snapshotKey" wide> | |
| {key.dim ? <Dim>{key.label}</Dim> : <Mono>{key.label}</Mono>} | |
| </FieldRow> | |
| {entry !== undefined && entry.contentHash !== undefined ? ( | |
| <FieldRow label="contentHash" wide> | |
| <Mono className="break-all">{stringValue(entry.contentHash)}</Mono> | |
| </FieldRow> | |
| ) : null} | |
| {entry !== undefined && entry.size !== undefined ? ( | |
| <FieldRow label="size"> | |
| <span className="text-[var(--color-sev-info)]">{sizeValue(entry.size)}</span> | |
| </FieldRow> | |
| ) : null} | |
| {entry !== undefined && entry.mtimeMs !== undefined ? ( | |
| <FieldRow label="mtime"> | |
| <Mono>{timestampValue(entry.mtimeMs)}</Mono> | |
| </FieldRow> | |
| ) : null} | |
| {entry?.oversize === true ? ( | |
| <FieldRow label="oversize"> | |
| <Pill tone="warning" variant="outline"> | |
| true | |
| </Pill> | |
| </FieldRow> | |
| ) : malformedOversize ? ( | |
| <FieldRow label="oversize"> | |
| <Dim>{invalidValue(entry.oversize)}</Dim> | |
| </FieldRow> | |
| ) : null} | |
| </div> | |
| ); | |
| }, | |
| }, | |
| forked: { | |
| tone: 'lifecycle', | |
| label: 'fork', | |
| headline: () => ({ main: <Dim>session forked</Dim> }), | |
| }, | |
| 'config.update': { | |
| tone: 'config', | |
| label: 'config', | |
| headline: (r) => { | |
| const cwd = r.environmentDisclosure?.cwd; | |
| const effort = r.thinkingEffort ?? r.thinkingLevel; | |
| const parts: string[] = []; | |
| if (r.profileName !== undefined) parts.push(`profile=${r.profileName}`); | |
| if (r.modelAlias !== undefined) parts.push(`model=${r.modelAlias}`); | |
| if (cwd !== undefined) parts.push(`cwd=${cwd}`); | |
| if (effort !== undefined) parts.push(`thinking=${effort}`); | |
| if (r.systemPrompt !== undefined) parts.push(`system(${r.systemPrompt.length}b)`); | |
| return { | |
| main: ( | |
| <span className="truncate text-fg-0"> | |
| {parts.length === 0 ? <Dim>(no fields)</Dim> : parts.join(' · ')} | |
| </span> | |
| ), | |
| }; | |
| }, | |
| }, | |
| 'profile.bind': { | |
| tone: 'config', | |
| label: 'profile', | |
| headline: (r) => { | |
| const parts: string[] = []; | |
| if (r.profileName !== undefined) parts.push(`profile=${r.profileName}`); | |
| if (r.modelAlias !== undefined) parts.push(`model=${r.modelAlias}`); | |
| if (r.thinkingEffort !== undefined) parts.push(`thinking=${r.thinkingEffort}`); | |
| if (r.activeToolNames !== undefined) { | |
| parts.push(`${r.activeToolNames.length} tools`); | |
| } else { | |
| parts.push('all tools'); | |
| } | |
| return { | |
| main: ( | |
| <span className="truncate text-fg-0"> | |
| {parts.length === 0 ? <Dim>(no fields)</Dim> : parts.join(' · ')} | |
| </span> | |
| ), | |
| }; | |
| }, | |
| }, | |
| 'turn.prompt': { | |
| tone: 'turn', | |
| label: 'prompt', | |
| headline: (r) => { | |
| const text = firstText(r.input); | |
| return { | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Pill tone="turn" variant="soft"> | |
| {r.origin.kind} | |
| </Pill> | |
| <span className="truncate text-fg-1">→ {truncate(text, 80)}</span> | |
| </span> | |
| ), | |
| }; | |
| }, | |
| detail: (r) => ( | |
| <div className="space-y-2"> | |
| <div className="grid grid-cols-[140px_1fr] gap-x-3 gap-y-[2px]"> | |
| <FieldRow label="origin" wide> | |
| <JsonViewer value={r.origin} defaultOpenDepth={2} /> | |
| </FieldRow> | |
| </div> | |
| <div> | |
| <div className="mb-1 text-fg-2"> | |
| input ({r.input.length} part{r.input.length === 1 ? '' : 's'}) | |
| </div> | |
| <div className="space-y-1"> | |
| {r.input.map((part, i) => ( | |
| <ContentPartView key={i} part={part} /> | |
| ))} | |
| </div> | |
| </div> | |
| </div> | |
| ), | |
| }, | |
| 'turn.steer': { | |
| tone: 'turn', | |
| label: 'steer', | |
| headline: (r) => { | |
| const text = firstText(r.input); | |
| return { | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Pill tone="turn" variant="soft"> | |
| {r.origin.kind} | |
| </Pill> | |
| <span className="truncate text-fg-1">→ {truncate(text, 80)}</span> | |
| </span> | |
| ), | |
| }; | |
| }, | |
| detail: (r) => ( | |
| <div className="space-y-2"> | |
| <div className="grid grid-cols-[140px_1fr] gap-x-3 gap-y-[2px]"> | |
| <FieldRow label="origin" wide> | |
| <JsonViewer value={r.origin} defaultOpenDepth={2} /> | |
| </FieldRow> | |
| </div> | |
| <div> | |
| <div className="mb-1 text-fg-2"> | |
| input ({r.input.length} part{r.input.length === 1 ? '' : 's'}) | |
| </div> | |
| <div className="space-y-1"> | |
| {r.input.map((part, i) => ( | |
| <ContentPartView key={i} part={part} /> | |
| ))} | |
| </div> | |
| </div> | |
| </div> | |
| ), | |
| }, | |
| 'turn.cancel': { | |
| tone: 'warning', | |
| label: 'cancel', | |
| headline: (r) => ({ | |
| main: <Mono>{r.turnId !== undefined ? `turn ${r.turnId}` : '(latest)'}</Mono>, | |
| }), | |
| }, | |
| 'context.append_message': { | |
| tone: 'assistant', | |
| label: 'message', | |
| headline: (r) => { | |
| const m = r.message; | |
| const tc = m.toolCalls.length > 0 ? `${m.toolCalls.length} tool_call(s)` : ''; | |
| return { | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Pill | |
| tone={ | |
| m.role === 'user' | |
| ? 'user' | |
| : m.role === 'assistant' | |
| ? 'assistant' | |
| : m.role === 'tool' | |
| ? 'tool' | |
| : 'meta' | |
| } | |
| variant="soft" | |
| > | |
| {m.role} | |
| </Pill> | |
| <Dim>({m.content.length} part{m.content.length === 1 ? '' : 's'})</Dim> | |
| {tc ? <Dim>· {tc}</Dim> : null} | |
| {m.origin?.kind ? <Dim>· origin={m.origin.kind}</Dim> : null} | |
| </span> | |
| ), | |
| right: m.isError === true ? ( | |
| <Pill tone="error" variant="solid"> | |
| error | |
| </Pill> | |
| ) : undefined, | |
| }; | |
| }, | |
| detail: (r) => <MessageDetail message={r.message} />, | |
| }, | |
| 'context.append_loop_event': { | |
| tone: 'meta', | |
| label: 'loop', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Mono>{r.event.type}</Mono> | |
| <Dim className="truncate">{loopEventSummary(r.event)}</Dim> | |
| </span> | |
| ), | |
| }), | |
| detail: (r) => <LoopEventDetail event={r.event} />, | |
| }, | |
| 'context.update_token_count': { | |
| tone: 'meta', | |
| label: 'tokens', | |
| headline: (r) => ({ main: <Dim>context {r.tokenCount} tok</Dim> }), | |
| }, | |
| 'context.clear': { | |
| tone: 'warning', | |
| label: 'clear', | |
| headline: () => ({ main: <Dim>context cleared</Dim> }), | |
| }, | |
| 'context.apply_compaction': { | |
| tone: 'compaction', | |
| label: 'compacted', | |
| headline: (r) => { | |
| // v2 payload variants: `summary` is a string on current records, a | |
| // ContextMessage on the legacy variant (which uses `count` instead of | |
| // `compactedCount`); `tokensBefore`/`tokensAfter` are optional. | |
| const record = r as unknown as UnknownObject; | |
| const summary = compactionSummaryView(r); | |
| const compactedCount = compactionCount(record); | |
| const wireLines = wireLineRange(record.wireLines); | |
| return { | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Pill tone="compaction" variant="soft"> | |
| compacted | |
| </Pill> | |
| <Dim> | |
| {summary.label} {summary.text.length}b · {optionalNumberValue(record.tokensBefore, '?')}→ | |
| {optionalNumberValue(record.tokensAfter, '?')} tok ·{' '} | |
| {compactedCount.value} msgs | |
| </Dim> | |
| </span> | |
| ), | |
| right: | |
| wireLines === undefined ? undefined : ( | |
| <Mono> | |
| L{wireLines.start}–{wireLines.end} | |
| </Mono> | |
| ), | |
| }; | |
| }, | |
| detail: (r) => { | |
| const record = r as unknown as UnknownObject; | |
| const summary = compactionSummaryView(r); | |
| const compactedCount = compactionCount(record); | |
| const wireLines = wireLineRange(record.wireLines); | |
| return ( | |
| <div className="grid grid-cols-[140px_1fr] gap-x-3 gap-y-[2px]"> | |
| <FieldRow label={summary.label} wide> | |
| <SizePreview | |
| label={summary.label} | |
| sizeBytes={summary.text.length} | |
| preview={summary.text} | |
| > | |
| <pre className="whitespace-pre-wrap break-words text-fg-1">{summary.text}</pre> | |
| </SizePreview> | |
| </FieldRow> | |
| {summary.message !== undefined ? ( | |
| <FieldRow label="summaryMessage" wide> | |
| <JsonViewer value={summary.message} defaultOpenDepth={2} /> | |
| </FieldRow> | |
| ) : null} | |
| {summary.contextSummary !== undefined ? ( | |
| <FieldRow label="contextSummary" wide> | |
| <SizePreview | |
| label="contextSummary" | |
| sizeBytes={summary.contextSummary.length} | |
| preview={summary.contextSummary} | |
| > | |
| <pre className="whitespace-pre-wrap break-words text-fg-1"> | |
| {summary.contextSummary} | |
| </pre> | |
| </SizePreview> | |
| </FieldRow> | |
| ) : null} | |
| <FieldRow label={compactedCount.label}> | |
| <span className="text-[var(--color-sev-info)]">{compactedCount.value}</span> | |
| </FieldRow> | |
| <FieldRow label="tokensBefore"> | |
| <span className="text-[var(--color-sev-info)]"> | |
| {optionalNumberValue(record.tokensBefore, '(n/a)')} | |
| </span> | |
| </FieldRow> | |
| <FieldRow label="tokensAfter"> | |
| <span className="text-[var(--color-sev-info)]"> | |
| {optionalNumberValue(record.tokensAfter, '(n/a)')} | |
| </span> | |
| </FieldRow> | |
| {record.summaryOutputTokens !== undefined ? ( | |
| <FieldRow label="summaryOutputTokens"> | |
| <span className="text-[var(--color-sev-info)]"> | |
| {numberValue(record.summaryOutputTokens)} | |
| </span> | |
| </FieldRow> | |
| ) : null} | |
| {record.keptUserMessageCount !== undefined ? ( | |
| <FieldRow label="keptUserMessages"> | |
| <span className="text-[var(--color-sev-info)]"> | |
| {numberValue(record.keptUserMessageCount)} | |
| </span> | |
| </FieldRow> | |
| ) : null} | |
| {record.keptHeadUserMessageCount !== undefined ? ( | |
| <FieldRow label="keptHeadMessages"> | |
| <span className="text-[var(--color-sev-info)]"> | |
| {numberValue(record.keptHeadUserMessageCount)} | |
| </span> | |
| </FieldRow> | |
| ) : null} | |
| {record.droppedCount !== undefined ? ( | |
| <FieldRow label="droppedCount"> | |
| <span className="text-[var(--color-sev-info)]"> | |
| {numberValue(record.droppedCount)} | |
| </span> | |
| </FieldRow> | |
| ) : null} | |
| {record.legacyTail !== undefined ? ( | |
| <FieldRow label="legacyTail"> | |
| <Mono> | |
| {typeof record.legacyTail === 'boolean' | |
| ? String(record.legacyTail) | |
| : invalidValue(record.legacyTail)} | |
| </Mono> | |
| </FieldRow> | |
| ) : null} | |
| {wireLines !== undefined ? ( | |
| <FieldRow label="wireLines"> | |
| <Mono> | |
| {wireLines.start}–{wireLines.end} | |
| </Mono> | |
| </FieldRow> | |
| ) : null} | |
| </div> | |
| ); | |
| }, | |
| }, | |
| 'context.undo': { | |
| tone: 'warning', | |
| label: 'undo', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2"> | |
| <Pill tone="warning" variant="soft"> | |
| undo | |
| </Pill> | |
| <Dim> | |
| {r.count} prompt{r.count === 1 ? '' : 's'} | |
| </Dim> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'tools.register_user_tool': { | |
| tone: 'tools', | |
| label: 'tool+', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2"> | |
| <Mono className="text-[var(--color-cat-tools)]">+ {r.name}</Mono> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'tools.unregister_user_tool': { | |
| tone: 'tools', | |
| label: 'tool-', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2"> | |
| <Mono className="text-[var(--color-sev-warning)]">- {r.name}</Mono> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'tools.set_active_tools': { | |
| tone: 'tools', | |
| label: 'tools', | |
| headline: (r) => { | |
| const head = r.names.slice(0, 3).join(', '); | |
| const rest = r.names.length > 3 ? ` +${r.names.length - 3} more` : ''; | |
| return { | |
| main: ( | |
| <Mono className="truncate"> | |
| {head} | |
| {rest} | |
| </Mono> | |
| ), | |
| right: <Dim>{r.names.length} tools</Dim>, | |
| }; | |
| }, | |
| }, | |
| 'tools.reset_active_tools': { | |
| tone: 'tools', | |
| label: 'reset', | |
| headline: () => ({ | |
| main: <Mono>all tools active</Mono>, | |
| }), | |
| }, | |
| 'tools.update_store': { | |
| tone: 'meta', | |
| label: 'store', | |
| headline: (r) => { | |
| const valuePreview = | |
| typeof r.value === 'object' && r.value !== null | |
| ? '(object)' | |
| : truncate(String(r.value), 60); | |
| return { | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Mono>{r.key}</Mono> | |
| <Dim>= {valuePreview}</Dim> | |
| </span> | |
| ), | |
| }; | |
| }, | |
| }, | |
| 'permission.set_mode': { | |
| tone: 'approval', | |
| label: 'perm', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2"> | |
| <Dim>mode →</Dim> | |
| <Pill tone="approval" variant="soft"> | |
| {r.mode} | |
| </Pill> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'permission.record_approval_result': { | |
| tone: 'approval', | |
| label: 'approval', | |
| headline: (r) => { | |
| const tone = | |
| r.result.decision === 'approved' | |
| ? 'success' | |
| : r.result.decision === 'rejected' | |
| ? 'error' | |
| : 'neutral'; | |
| return { | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Mono> | |
| {r.toolName}#{r.toolCallId.slice(-8)} | |
| </Mono> | |
| <Pill tone={tone} variant="soft"> | |
| {r.result.decision} | |
| </Pill> | |
| {r.result.scope ? <Dim>({r.result.scope})</Dim> : null} | |
| </span> | |
| ), | |
| }; | |
| }, | |
| detail: (r) => ( | |
| <div className="grid grid-cols-[140px_1fr] gap-x-3 gap-y-[2px]"> | |
| <FieldRow label="toolName"> | |
| <Mono>{r.toolName}</Mono> | |
| </FieldRow> | |
| <FieldRow label="toolCallId"> | |
| <Mono>{r.toolCallId}</Mono> | |
| </FieldRow> | |
| <FieldRow label="action"> | |
| <Mono>{r.action}</Mono> | |
| </FieldRow> | |
| <FieldRow label="turnId"> | |
| <span className="text-[var(--color-sev-info)]">{r.turnId}</span> | |
| </FieldRow> | |
| <FieldRow label="decision"> | |
| <span className="text-fg-0">{r.result.decision}</span> | |
| </FieldRow> | |
| {r.result.scope !== undefined ? ( | |
| <FieldRow label="scope"> | |
| <Mono>{r.result.scope}</Mono> | |
| </FieldRow> | |
| ) : null} | |
| {r.sessionApprovalRule !== undefined ? ( | |
| <FieldRow label="sessionApprovalRule" wide> | |
| <Mono className="break-all">{r.sessionApprovalRule}</Mono> | |
| </FieldRow> | |
| ) : null} | |
| {r.result.selectedLabel !== undefined ? ( | |
| <FieldRow label="selectedLabel" wide> | |
| <Mono className="break-all">{r.result.selectedLabel}</Mono> | |
| </FieldRow> | |
| ) : null} | |
| {r.result.feedback !== undefined ? ( | |
| <FieldRow label="feedback" wide> | |
| <pre className="whitespace-pre-wrap break-words text-fg-1">{r.result.feedback}</pre> | |
| </FieldRow> | |
| ) : null} | |
| </div> | |
| ), | |
| }, | |
| 'usage.record': { | |
| tone: 'meta', | |
| label: 'usage', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Mono>{r.model}</Mono> | |
| <Dim> | |
| in {r.usage.inputOther} / out {r.usage.output} / cache r{r.usage.inputCacheRead} w | |
| {r.usage.inputCacheCreation} | |
| </Dim> | |
| </span> | |
| ), | |
| right: r.usageScope ? ( | |
| <Pill tone="meta" variant="outline"> | |
| {r.usageScope} | |
| </Pill> | |
| ) : undefined, | |
| }), | |
| }, | |
| 'full_compaction.begin': { | |
| tone: 'compaction', | |
| label: 'compact↻', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Pill tone="compaction" variant="soft"> | |
| {r.source} | |
| </Pill> | |
| {r.instruction ? ( | |
| <Dim className="truncate">"{truncate(r.instruction, 40)}"</Dim> | |
| ) : null} | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'full_compaction.cancel': { | |
| tone: 'warning', | |
| label: 'compact×', | |
| headline: () => ({ main: <Dim>cancelled</Dim> }), | |
| }, | |
| // `full_compaction.complete` has an EMPTY payload (`{}`). The previous code | |
| // read `r.summary` / `r.compactedCount` / `r.tokensBefore` / `r.tokensAfter`, | |
| // none of which exist on this record — a runtime crash. Those fields belong | |
| // to `context.apply_compaction` (its own entry above). This is a static, | |
| // payload-free renderer; the generic JSON dump shows type + time only. | |
| 'full_compaction.complete': { | |
| tone: 'success', | |
| label: 'compact✓', | |
| headline: () => ({ main: <Dim>compaction complete</Dim> }), | |
| }, | |
| 'micro_compaction.apply': { | |
| tone: 'compaction', | |
| label: 'µcompact', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Pill tone="compaction" variant="soft"> | |
| micro | |
| </Pill> | |
| <Dim>cutoff {r.cutoff}</Dim> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'plan_mode.enter': { | |
| tone: 'lifecycle', | |
| label: 'plan↻', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2"> | |
| <Pill tone="lifecycle" variant="soft"> | |
| enter | |
| </Pill> | |
| <Mono>{r.id}</Mono> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'plan_mode.cancel': { | |
| tone: 'warning', | |
| label: 'plan×', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2"> | |
| <Pill tone="warning" variant="soft"> | |
| cancel | |
| </Pill> | |
| <Mono>{r.id ?? '(latest)'}</Mono> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'plan_mode.exit': { | |
| tone: 'success', | |
| label: 'plan✓', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2"> | |
| <Pill tone="success" variant="soft"> | |
| exit | |
| </Pill> | |
| <Mono>{r.id ?? '(latest)'}</Mono> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'swarm_mode.enter': { | |
| tone: 'subagent', | |
| label: 'swarm↻', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2"> | |
| <Pill tone="subagent" variant="soft"> | |
| enter | |
| </Pill> | |
| <Mono>{r.trigger}</Mono> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'swarm_mode.exit': { | |
| tone: 'subagent', | |
| label: 'swarm✓', | |
| headline: () => ({ main: <Dim>swarm mode exited</Dim> }), | |
| }, | |
| 'tower_mode.enter': { | |
| tone: 'subagent', | |
| label: 'tower↻', | |
| headline: () => ({ main: <Dim>tower mode entered</Dim> }), | |
| }, | |
| 'tower_mode.exit': { | |
| tone: 'subagent', | |
| label: 'tower✓', | |
| headline: () => ({ main: <Dim>tower mode exited</Dim> }), | |
| }, | |
| 'goal.create': { | |
| tone: 'lifecycle', | |
| label: 'goal+', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Pill tone="lifecycle" variant="soft"> | |
| goal | |
| </Pill> | |
| <span className="truncate text-fg-1">{r.objective}</span> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'goal.update': { | |
| tone: 'lifecycle', | |
| label: 'goal', | |
| headline: (r) => { | |
| const parts: string[] = []; | |
| if (r.status !== undefined) parts.push(`status=${r.status}`); | |
| if (r.actor !== undefined) parts.push(`by=${r.actor}`); | |
| if (r.turnsUsed !== undefined) parts.push(`turns=${r.turnsUsed}`); | |
| if (r.tokensUsed !== undefined) parts.push(`tok=${r.tokensUsed}`); | |
| return { | |
| main: ( | |
| <span className="truncate text-fg-1"> | |
| {parts.length === 0 ? <Dim>(no change)</Dim> : parts.join(' · ')} | |
| </span> | |
| ), | |
| }; | |
| }, | |
| }, | |
| 'goal.clear': { | |
| tone: 'warning', | |
| label: 'goal×', | |
| headline: () => ({ main: <Dim>goal cleared</Dim> }), | |
| }, | |
| // Observability records — the request trace (see the v2 wire manifest). | |
| 'llm.tools_snapshot': { | |
| tone: 'tools', | |
| label: 'req·tools', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Mono> | |
| {r.tools.length} tool{r.tools.length === 1 ? '' : 's'} | |
| </Mono> | |
| <Dim className="truncate"> | |
| {r.tools | |
| .slice(0, 4) | |
| .map((tool) => tool.name) | |
| .join(', ')} | |
| {r.tools.length > 4 ? ` +${r.tools.length - 4} more` : ''} | |
| </Dim> | |
| </span> | |
| ), | |
| right: <Mono>#{r.hash.slice(0, 8)}</Mono>, | |
| }), | |
| }, | |
| 'llm.request': { | |
| tone: 'meta', | |
| label: 'llm→', | |
| headline: (r) => { | |
| const parts: string[] = []; | |
| if (r.turnStep !== undefined) parts.push(`step ${r.turnStep}`); | |
| if (r.attempt !== undefined) parts.push(`attempt ${r.attempt}`); | |
| parts.push(`${r.messageCount} msgs`); | |
| if (r.maxTokens !== undefined) parts.push(`max ${r.maxTokens} tok`); | |
| return { | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Pill tone={r.kind === 'compaction' ? 'compaction' : 'turn'} variant="soft"> | |
| {r.kind} | |
| </Pill> | |
| <Mono>{r.model}</Mono> | |
| <Dim className="truncate">{parts.join(' · ')}</Dim> | |
| </span> | |
| ), | |
| right: | |
| r.projection !== undefined ? ( | |
| <Pill tone="warning" variant="soft"> | |
| {r.projection} | |
| </Pill> | |
| ) : undefined, | |
| }; | |
| }, | |
| detail: (r) => ( | |
| <div className="grid grid-cols-[140px_1fr] gap-x-3 gap-y-[2px]"> | |
| <FieldRow label="provider"> | |
| <Mono>{r.provider}</Mono> | |
| </FieldRow> | |
| <FieldRow label="model"> | |
| <Mono>{r.model}</Mono> | |
| </FieldRow> | |
| {r.modelAlias !== undefined ? ( | |
| <FieldRow label="modelAlias"> | |
| <Mono>{r.modelAlias}</Mono> | |
| </FieldRow> | |
| ) : null} | |
| {r.thinkingEffort !== undefined ? ( | |
| <FieldRow label="thinkingEffort"> | |
| <Mono>{r.thinkingEffort}</Mono> | |
| </FieldRow> | |
| ) : null} | |
| {r.thinkingKeep !== undefined ? ( | |
| <FieldRow label="thinkingKeep"> | |
| <Mono>{r.thinkingKeep}</Mono> | |
| </FieldRow> | |
| ) : null} | |
| {r.temperature !== undefined ? ( | |
| <FieldRow label="temperature"> | |
| <span className="text-[var(--color-sev-info)]">{r.temperature}</span> | |
| </FieldRow> | |
| ) : null} | |
| {r.topP !== undefined ? ( | |
| <FieldRow label="topP"> | |
| <span className="text-[var(--color-sev-info)]">{r.topP}</span> | |
| </FieldRow> | |
| ) : null} | |
| {r.maxTokens !== undefined ? ( | |
| <FieldRow label="maxTokens"> | |
| <span className="text-[var(--color-sev-info)]">{r.maxTokens}</span> | |
| </FieldRow> | |
| ) : null} | |
| {r.betaApi !== undefined ? ( | |
| <FieldRow label="betaApi"> | |
| <Mono>{String(r.betaApi)}</Mono> | |
| </FieldRow> | |
| ) : null} | |
| <FieldRow label="toolSelect"> | |
| <Mono>{String(r.toolSelect)}</Mono> | |
| </FieldRow> | |
| <FieldRow label="toolsHash" wide> | |
| <Mono className="break-all">{r.toolsHash}</Mono> | |
| </FieldRow> | |
| <FieldRow label="systemPromptHash" wide> | |
| <Mono className="break-all">{r.systemPromptHash}</Mono> | |
| </FieldRow> | |
| {r.systemPrompt !== undefined ? ( | |
| <FieldRow label="systemPrompt" wide> | |
| <SizePreview | |
| label="systemPrompt" | |
| sizeBytes={r.systemPrompt.length} | |
| preview={r.systemPrompt} | |
| > | |
| <pre className="whitespace-pre-wrap break-words text-fg-1">{r.systemPrompt}</pre> | |
| </SizePreview> | |
| </FieldRow> | |
| ) : null} | |
| {r.droppedCount !== undefined ? ( | |
| <FieldRow label="droppedCount"> | |
| <span className="text-[var(--color-sev-info)]">{r.droppedCount}</span> | |
| </FieldRow> | |
| ) : null} | |
| </div> | |
| ), | |
| }, | |
| 'mcp.tools_discovered': { | |
| tone: 'tools', | |
| label: 'mcp·list', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Mono>{r.serverName}</Mono> | |
| <Dim> | |
| {r.tools.length} tool{r.tools.length === 1 ? '' : 's'} · {r.enabledNames.length}{' '} | |
| enabled | |
| </Dim> | |
| </span> | |
| ), | |
| right: | |
| r.collisions !== undefined && r.collisions.length > 0 ? ( | |
| <Pill tone="warning" variant="soft"> | |
| {r.collisions.length} collision{r.collisions.length === 1 ? '' : 's'} | |
| </Pill> | |
| ) : ( | |
| <Mono>#{r.hash.slice(0, 8)}</Mono> | |
| ), | |
| }), | |
| }, | |
| 'turn.ended': { | |
| tone: 'turn', | |
| label: 'turn✓', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Mono>turn {r.turnId}</Mono> | |
| <Pill | |
| tone={r.reason === 'completed' ? 'success' : r.reason === 'failed' ? 'error' : 'warning'} | |
| variant="soft" | |
| > | |
| {r.reason} | |
| </Pill> | |
| {r.durationMs !== undefined ? <Dim>{r.durationMs}ms</Dim> : null} | |
| {r.stopReason !== undefined ? ( | |
| <span className="truncate text-fg-3" title={r.stopReason}> | |
| {truncate(r.stopReason, 80)} | |
| </span> | |
| ) : null} | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'turn.step.interrupted': { | |
| tone: 'warning', | |
| label: 'step×', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Mono> | |
| turn {r.turnId} · step {r.step} | |
| </Mono> | |
| <Dim className="truncate">{r.reason}</Dim> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'turn.step.retrying': { | |
| tone: 'warning', | |
| label: 'retry↻', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Mono> | |
| turn {r.turnId} · step {r.step} | |
| </Mono> | |
| <Pill tone="warning" variant="soft"> | |
| attempt {r.nextAttempt}/{r.maxAttempts} | |
| </Pill> | |
| <Dim className="truncate"> | |
| {r.errorName}: {truncate(r.errorMessage, 60)} | |
| </Dim> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'prompt.accepted': { | |
| tone: 'turn', | |
| label: 'prompt+', | |
| headline: (r) => ({ main: <Mono>{r.promptId}</Mono> }), | |
| }, | |
| 'prompt.aborted': { | |
| tone: 'warning', | |
| label: 'prompt×', | |
| headline: (r) => ({ main: <Mono>{r.promptId}</Mono> }), | |
| }, | |
| 'prompt.completed': { | |
| tone: 'turn', | |
| label: 'prompt✓', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2"> | |
| <Mono>{r.promptId}</Mono> | |
| <Pill tone={r.reason === 'completed' ? 'success' : 'warning'} variant="soft"> | |
| {r.reason} | |
| </Pill> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'prompt.steered': { | |
| tone: 'turn', | |
| label: 'steer→', | |
| headline: (r) => ({ | |
| main: <span className="truncate text-fg-1">→ {truncate(firstText(r.content), 80)}</span>, | |
| }), | |
| }, | |
| 'interaction.request': { | |
| tone: 'approval', | |
| label: 'ask→', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2"> | |
| <Pill tone="approval" variant="soft"> | |
| {r.kind} | |
| </Pill> | |
| <Mono>{r.id}</Mono> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'interaction.resolved': { | |
| tone: 'approval', | |
| label: 'ask✓', | |
| headline: (r) => ({ main: <Mono>{r.id}</Mono> }), | |
| }, | |
| 'task.started': { | |
| tone: 'subagent', | |
| label: 'task↻', | |
| headline: (r) => ({ main: <Mono>{r.info.taskId}</Mono> }), | |
| }, | |
| 'task.terminated': { | |
| tone: 'subagent', | |
| label: 'task✓', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2"> | |
| <Mono>{r.info.taskId}</Mono> | |
| <Dim>{r.info.status}</Dim> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'task.waitDelivered': { | |
| tone: 'subagent', | |
| label: 'task⇢', | |
| headline: (r) => ({ | |
| main: ( | |
| <Dim> | |
| wait delivered · {r.keys.length} task{r.keys.length === 1 ? '' : 's'} | |
| </Dim> | |
| ), | |
| }), | |
| }, | |
| 'token_counting.measured': { | |
| tone: 'meta', | |
| label: 'tokens', | |
| headline: (r) => ({ main: <Dim>context {r.tokens} tok (measured)</Dim> }), | |
| }, | |
| 'token_counting.truncated': { | |
| tone: 'meta', | |
| label: 'tokens', | |
| headline: (r) => ({ main: <Dim>context {r.tokens} tok (truncated @ {r.length})</Dim> }), | |
| }, | |
| 'token_counting.rebased': { | |
| tone: 'meta', | |
| label: 'tokens', | |
| headline: (r) => ({ | |
| main: ( | |
| <Dim> | |
| context {r.tokens} tok (rebased{r.measured ? ', measured' : ''}) | |
| </Dim> | |
| ), | |
| }), | |
| }, | |
| 'token_counting.turn_recorded': { | |
| tone: 'meta', | |
| label: 'tokens', | |
| headline: (r) => ({ main: <Dim>context {r.tokens} tok (turn {r.turnId})</Dim> }), | |
| }, | |
| 'cron.add': { | |
| tone: 'lifecycle', | |
| label: 'cron+', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Mono>{r.task.cron}</Mono> | |
| <Dim className="truncate">{truncate(r.task.prompt, 60)}</Dim> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'cron.delete': { | |
| tone: 'warning', | |
| label: 'cron−', | |
| headline: (r) => ({ | |
| main: ( | |
| <Dim> | |
| {r.ids.length} task{r.ids.length === 1 ? '' : 's'} deleted | |
| </Dim> | |
| ), | |
| }), | |
| }, | |
| 'cron.cursor': { | |
| tone: 'lifecycle', | |
| label: 'cron·fired', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Mono>{r.id}</Mono> | |
| <Dim>fired {new Date(r.lastFiredAt).toLocaleString()}</Dim> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'plan.revision': { | |
| tone: 'lifecycle', | |
| label: 'plan·rev', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Mono> | |
| plan {r.id} · v{r.version} | |
| </Mono> | |
| <Dim>{r.bytes}b</Dim> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'plugin.session_start': { | |
| tone: 'meta', | |
| label: 'plugin', | |
| headline: (r) => ({ | |
| main: ( | |
| <Dim className="truncate"> | |
| session start{r.content !== null ? `: ${truncate(r.content, 60)}` : ''} | |
| </Dim> | |
| ), | |
| }), | |
| }, | |
| 'runtime.set_binding': { | |
| tone: 'meta', | |
| label: 'runtime', | |
| headline: (r) => ({ | |
| main: ( | |
| <span className="flex items-center gap-2 min-w-0"> | |
| <Mono>{r.runtimeId}</Mono> | |
| <Dim className="truncate">workspace {r.workspaceId}</Dim> | |
| </span> | |
| ), | |
| }), | |
| }, | |
| 'staleGuard.recorded': { | |
| tone: 'meta', | |
| label: 'stale', | |
| headline: (r) => ({ main: <Dim className="truncate">{r.path}</Dim> }), | |
| }, | |
| 'staleGuard.cleared': { | |
| tone: 'meta', | |
| label: 'stale✓', | |
| headline: () => ({ main: <Dim>stale guard cleared</Dim> }), | |
| }, | |
| 'interruptionReminder.recorded': { | |
| tone: 'meta', | |
| label: 'interrupted', | |
| headline: (r) => ({ main: <Dim>interruption reminder · turn {r.turnId}</Dim> }), | |
| }, | |
| }; | |
| /** Look up a renderer by a runtime `type` string. Returns `undefined` for kinds | |
| * outside the known union (best-effort parse of a future/legacy/foreign | |
| * protocol), which the callers render via the generic fallback. | |
| * | |
| * Legacy/foreign runtime-only kinds (e.g. `goal.account_usage`, | |
| * `goal.continuation`, `background.stop`) are intentionally NOT given registry | |
| * entries: they sit outside the typed `AgentRecord` union, so this returns | |
| * `undefined` and they fall back to a readable generic render — `TypeBadge` | |
| * shows the raw `type` string (neutral tone, `title` tooltip), the headline | |
| * shows `(unknown record type: …)`, and the detail shows the full JSON. That is | |
| * legible enough; no friendly-label map is warranted. | |
| * | |
| * The `as unknown as` widening is the one place we sidestep TypeScript's | |
| * correlated-union limitation: each entry's `headline`/`detail` is narrowed to | |
| * its own kind, but at dispatch time we only have the union, so we widen the | |
| * value to `WireRenderer<RecordType>` (callable with any `AgentRecord`). Safe | |
| * because we only ever call it with the matching record. */ | |
| export function rendererFor(type: string): WireRenderer<RecordType> | undefined { | |
| return (WIRE_RENDERERS as unknown as Record<string, WireRenderer<RecordType>>)[type]; | |
| } | |