kimi-code / apps /vis /web /src /components /wire /renderers.tsx
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
7c5ed63 verified
Raw History Blame Contribute Delete
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];
}