@pgege/kaboo-react 0.1.0

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.
@@ -0,0 +1,557 @@
1
+ import { a as KabooInterruptHandlerProps, I as InterruptReason, A as ActivityState, D as DrillState, S as StreamGroup, T as ToolCall, b as InterruptRendererProps, c as TimelineEntry } from './KabooInterruptHandler-BO2Uv3gS.cjs';
2
+ export { d as ApprovalReason, F as FormQuestion, e as FormReason, f as InterruptData } from './KabooInterruptHandler-BO2Uv3gS.cjs';
3
+ import * as react from 'react';
4
+ import { ReactElement, ReactNode } from 'react';
5
+ import { CopilotKitProps } from '@copilotkit/react-core/v2';
6
+
7
+ /**
8
+ * A map of custom renderers for structured agent output, keyed by the output
9
+ * schema name. When a group carries `structuredOutput` and a matching
10
+ * `outputSchemaName`, its renderer is used instead of the default JSON view.
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * import type { StructuredRenderers } from "@pgege/kaboo-react";
15
+ *
16
+ * const renderers: StructuredRenderers = {
17
+ * WeatherReport: (data) => <div>{String(data.summary)}</div>,
18
+ * };
19
+ * ```
20
+ */
21
+ type StructuredRenderers = Record<string, (data: Record<string, unknown>) => ReactElement>;
22
+ /** React context carrying the {@link StructuredRenderers} map for structured output. */
23
+ declare const StructuredRenderersContext: react.Context<StructuredRenderers>;
24
+ /** Props for {@link KabooActivityProvider}. */
25
+ interface KabooActivityProviderProps {
26
+ /**
27
+ * CopilotKit agent id whose activity snapshots to consume. Omit to use the
28
+ * provider's default agent. Agent and thread scoping come from CopilotKit.
29
+ */
30
+ agentId?: string;
31
+ /** Renderers for structured agent outputs, keyed by output schema name. */
32
+ structuredRenderers?: StructuredRenderers;
33
+ /** The subtree that reads activity via {@link useActivity}. */
34
+ children: ReactNode;
35
+ }
36
+ /**
37
+ * Reads kaboo's hierarchical activity from the AG-UI run stream. The backend
38
+ * emits it as `ACTIVITY_SNAPSHOT` events interleaved on `/invocations`, so we
39
+ * subscribe to the CopilotKit agent instead of a separate SSE endpoint.
40
+ *
41
+ * Included automatically by {@link KabooProvider}; mount it yourself only when
42
+ * composing providers by hand under an existing `<CopilotKit>`.
43
+ *
44
+ * @example
45
+ * ```tsx
46
+ * import { KabooActivityProvider, ActivityPanel } from "@pgege/kaboo-react";
47
+ *
48
+ * function Activity({ agent }: { agent: string }) {
49
+ * return (
50
+ * <KabooActivityProvider agentId={agent}>
51
+ * <ActivityPanel />
52
+ * </KabooActivityProvider>
53
+ * );
54
+ * }
55
+ * ```
56
+ */
57
+ declare function KabooActivityProvider({ agentId, structuredRenderers, children }: KabooActivityProviderProps): react.JSX.Element;
58
+
59
+ /**
60
+ * Provides drill-down navigation state ({@link DrillState}) to the activity
61
+ * components below it. Included automatically by {@link KabooProvider}; only
62
+ * mount it yourself if you compose the providers by hand.
63
+ *
64
+ * @example
65
+ * ```tsx
66
+ * import { DrillProvider, GlassTabs, DrillDetailView } from "@pgege/kaboo-react";
67
+ *
68
+ * function Panel() {
69
+ * return (
70
+ * <DrillProvider>
71
+ * <GlassTabs />
72
+ * <DrillDetailView />
73
+ * </DrillProvider>
74
+ * );
75
+ * }
76
+ * ```
77
+ */
78
+ declare function DrillProvider({ children }: {
79
+ children: ReactNode;
80
+ }): react.JSX.Element;
81
+
82
+ /** Props for {@link KabooProvider}. */
83
+ interface KabooProviderProps {
84
+ /** URL of the CopilotKit runtime endpoint (e.g. `/api/copilotkit`). */
85
+ runtimeUrl: string;
86
+ /** CopilotKit agent id to run (the workflow entry agent). */
87
+ agent: string;
88
+ /** Conversation id. Scopes both the run and its activity. */
89
+ threadId?: string;
90
+ /** Renderers for structured agent outputs, keyed by output schema name. */
91
+ structuredRenderers?: StructuredRenderers;
92
+ /** Per-interrupt-type renderer overrides for the built-in HITL handler. */
93
+ interruptRenderers?: KabooInterruptHandlerProps["renderers"];
94
+ /** Skip auto-mounting the built-in {@link KabooInterruptHandler}. */
95
+ disableInterruptHandler?: boolean;
96
+ /** Skip auto-mounting the built-in {@link KabooInlineCards}. */
97
+ disableInlineCards?: boolean;
98
+ /** Extra props forwarded to the underlying `<CopilotKit>`. */
99
+ copilotKitProps?: Partial<Omit<CopilotKitProps, "children" | "runtimeUrl" | "agent" | "threadId">>;
100
+ /** Your app subtree, rendered inside all kaboo contexts. */
101
+ children: ReactNode;
102
+ }
103
+ /**
104
+ * Batteries-included CopilotKit plugin. Renders `<CopilotKit>` and nests every
105
+ * kaboo context (activity -> drill -> interrupt bridge) plus the built-in HITL
106
+ * and inline-card handlers, so integrators drop this once near the root and use
107
+ * only kaboo-react. Activity rides the AG-UI run stream, so there is no separate
108
+ * activity endpoint to configure.
109
+ *
110
+ * @example
111
+ * ```tsx
112
+ * import { CopilotChat } from "@copilotkit/react-core/v2";
113
+ * import { KabooProvider, GlassTabs, DrillDetailView } from "@pgege/kaboo-react";
114
+ * import { KabooMessageView } from "@pgege/kaboo-react/copilotkit";
115
+ * import "@pgege/kaboo-react/styles.css";
116
+ *
117
+ * function App({ agent, threadId }: { agent: string; threadId: string }) {
118
+ * return (
119
+ * <KabooProvider runtimeUrl="/api/copilotkit" agent={agent} threadId={threadId}>
120
+ * <GlassTabs />
121
+ * <CopilotChat messageView={KabooMessageView} />
122
+ * <DrillDetailView />
123
+ * </KabooProvider>
124
+ * );
125
+ * }
126
+ * ```
127
+ */
128
+ declare function KabooProvider({ runtimeUrl, agent, threadId, structuredRenderers, interruptRenderers, disableInterruptHandler, disableInlineCards, copilotKitProps, children, }: KabooProviderProps): react.JSX.Element;
129
+
130
+ /**
131
+ * An open interrupt published onto the InterruptBridge so an owning agent card
132
+ * can render its prompt inline (rather than only in the chat slot). Carries the
133
+ * reason plus resolve/cancel callbacks bound to this specific interrupt id.
134
+ */
135
+ interface ActiveInterrupt {
136
+ /**
137
+ * Unique interrupt id (from the AG-UI interrupt). Distinguishes concurrent
138
+ * gates that may share a single tool-call id (e.g. two parallel sub-agent
139
+ * gates re-keyed onto one delegating call), so each resolves independently.
140
+ */
141
+ id: string;
142
+ /** Why the run paused, and what input it needs. */
143
+ reason: InterruptReason;
144
+ /** Resume the run with the user's answer/approval payload. */
145
+ onResolve: (payload: unknown) => void;
146
+ /** Cancel/reject this gate, resuming the run without a positive answer. */
147
+ onCancel: () => void;
148
+ /**
149
+ * The originating tool-call id, when the interrupt was raised by a tool (e.g.
150
+ * `ask_user` or a gated tool). Lets the owning agent card render the live
151
+ * prompt inline at its tool-call position, so the prompt sits in chronological
152
+ * order rather than in a separate top-level slot.
153
+ */
154
+ toolCallId?: string;
155
+ }
156
+ /**
157
+ * Holds the set of currently open interrupts so any tool row can claim and
158
+ * render its own gate inline (see {@link useInterruptFor}). Included
159
+ * automatically by {@link KabooProvider}.
160
+ *
161
+ * @example
162
+ * ```tsx
163
+ * import { InterruptBridgeProvider } from "@pgege/kaboo-react";
164
+ *
165
+ * function Providers({ children }: { children: React.ReactNode }) {
166
+ * return <InterruptBridgeProvider>{children}</InterruptBridgeProvider>;
167
+ * }
168
+ * ```
169
+ */
170
+ declare function InterruptBridgeProvider({ children }: {
171
+ children: ReactNode;
172
+ }): react.JSX.Element;
173
+ /**
174
+ * Reads the InterruptBridge: the list of open interrupts plus `publish`. Most
175
+ * consumers want {@link useInterruptFor} instead; use this to inspect or drive
176
+ * the whole set.
177
+ *
178
+ * @example
179
+ * ```tsx
180
+ * import { useInterruptBridge } from "@pgege/kaboo-react";
181
+ *
182
+ * function OpenGateCount() {
183
+ * const { active } = useInterruptBridge();
184
+ * return <span>{active.length} open</span>;
185
+ * }
186
+ * ```
187
+ */
188
+ declare function useInterruptBridge(): {
189
+ /** Every open interrupt from the current run, in emission order. */
190
+ active: ActiveInterrupt[];
191
+ /** Replace the set of interrupts published to the bridge. */
192
+ publish: (interrupts: ActiveInterrupt[]) => void;
193
+ };
194
+ /**
195
+ * The first open interrupt anchored to a given tool-call id, or `undefined`.
196
+ * Lets a tool row claim and render its own gate inline while N concurrent gates
197
+ * are open, each anchored to a distinct tool call.
198
+ */
199
+ declare function useInterruptFor(toolCallId: string | undefined): ActiveInterrupt | undefined;
200
+ /**
201
+ * Publishes the current set of open interrupts to the bridge so each owning
202
+ * agent card can render its prompt inline at the matching tool-call position.
203
+ * CopilotKit surfaces every open interrupt at once, so this takes the full list
204
+ * and keeps the latest resolve/cancel callbacks in a ref — their per-render
205
+ * identity churn must not re-publish (only the interrupt set should).
206
+ */
207
+ declare function InterruptBridgePublisher({ interrupts, }: {
208
+ interrupts: ActiveInterrupt[];
209
+ }): null;
210
+
211
+ /**
212
+ * Reads the current {@link ActivityState} (all activity groups for the thread)
213
+ * from the nearest {@link KabooActivityProvider}. Re-renders on each new
214
+ * `ACTIVITY_SNAPSHOT`.
215
+ *
216
+ * @example
217
+ * ```tsx
218
+ * import { useActivity } from "@pgege/kaboo-react";
219
+ *
220
+ * function GroupCount() {
221
+ * const { groups } = useActivity();
222
+ * return <span>{Object.keys(groups).length} agents</span>;
223
+ * }
224
+ * ```
225
+ */
226
+ declare function useActivity(): ActivityState;
227
+
228
+ /**
229
+ * Reads the drill-down navigation state ({@link DrillState}) from the nearest
230
+ * {@link DrillProvider}: the current path plus `drillIn`/`drillUp`/`drillToRoot`/
231
+ * `drillToLevel`.
232
+ *
233
+ * @example
234
+ * ```tsx
235
+ * import { useDrill } from "@pgege/kaboo-react";
236
+ *
237
+ * function BackButton() {
238
+ * const { drillUp, activeDrill } = useDrill();
239
+ * if (!activeDrill) return null;
240
+ * return <button onClick={drillUp}>Back</button>;
241
+ * }
242
+ * ```
243
+ */
244
+ declare function useDrill(): DrillState;
245
+
246
+ /** A `[groupId, group]` pair, as returned by the group-hierarchy helpers. */
247
+ type GroupEntry = [string, StreamGroup];
248
+ /**
249
+ * Top-level groups are those without a parent. Uses the explicit
250
+ * `parentGroup` field rather than parsing dot-paths out of the group id, so
251
+ * group names are free to contain any characters.
252
+ *
253
+ * @example
254
+ * ```ts
255
+ * import { topLevelGroups } from "@pgege/kaboo-react";
256
+ *
257
+ * function rootCount(groups: Parameters<typeof topLevelGroups>[0]) {
258
+ * return topLevelGroups(groups).length;
259
+ * }
260
+ * ```
261
+ */
262
+ declare function topLevelGroups(groups: Record<string, StreamGroup>): GroupEntry[];
263
+ /**
264
+ * Direct children of `parentId` (one level deep) via the `parentGroup` field.
265
+ *
266
+ * @example
267
+ * ```ts
268
+ * import { directChildren } from "@pgege/kaboo-react";
269
+ *
270
+ * function childCount(
271
+ * groups: Parameters<typeof directChildren>[0],
272
+ * parentId: string,
273
+ * ) {
274
+ * return directChildren(groups, parentId).length;
275
+ * }
276
+ * ```
277
+ */
278
+ declare function directChildren(groups: Record<string, StreamGroup>, parentId: string): GroupEntry[];
279
+
280
+ /**
281
+ * Standalone panel that renders the current activity tree as a list of
282
+ * {@link AgentCard}s — top-level groups at the root, or the drilled-in group's
283
+ * children. Use it when you want the hierarchical activity view outside the chat
284
+ * transcript (the in-chat view is handled by `KabooMessageView`). Renders
285
+ * nothing when there is no activity.
286
+ *
287
+ * @example
288
+ * ```tsx
289
+ * import { ActivityPanel } from "@pgege/kaboo-react";
290
+ *
291
+ * function Sidebar() {
292
+ * return (
293
+ * <aside>
294
+ * <ActivityPanel />
295
+ * </aside>
296
+ * );
297
+ * }
298
+ * ```
299
+ */
300
+ declare function ActivityPanel(): react.JSX.Element | null;
301
+
302
+ /** Props for {@link AgentCard}. */
303
+ interface AgentCardProps {
304
+ /** Id of the group this card renders. */
305
+ groupId: string;
306
+ /** The activity group to render. */
307
+ group: StreamGroup;
308
+ /** Task/input text to show, overriding the group's own `task`. */
309
+ input?: string;
310
+ /** Raw tool result to render as the card's answer, when provided by the host. */
311
+ result?: string;
312
+ /** Host-provided action status (e.g. `"complete"`) used to mark the card done. */
313
+ actionStatus?: string;
314
+ /**
315
+ * When true, the card renders its `directChildren` inline as nested
316
+ * {@link AgentCard}s (recursively). Used by the first-class swarm/graph inline
317
+ * renderer to show the whole member tree without the drill navigation. Left
318
+ * off (default) for the delegate path and the drill views, which surface
319
+ * children through their own navigation.
320
+ */
321
+ showChildren?: boolean;
322
+ }
323
+ /**
324
+ * Card for a single agent run: title, status badge, task, chronological timeline
325
+ * (text + tool rows), result/structured output, and a "View details" drill
326
+ * button. Delegated sub-agents are interleaved at their tool-call position; with
327
+ * `showChildren` the card renders its whole child tree inline.
328
+ *
329
+ * @example
330
+ * ```tsx
331
+ * import { AgentCard, useActivity } from "@pgege/kaboo-react";
332
+ *
333
+ * function FirstCard() {
334
+ * const { groups } = useActivity();
335
+ * const [id, group] = Object.entries(groups)[0] ?? [];
336
+ * return id ? <AgentCard groupId={id} group={group} /> : null;
337
+ * }
338
+ * ```
339
+ */
340
+ declare function AgentCard({ groupId, group, input, result, actionStatus, showChildren }: AgentCardProps): react.JSX.Element;
341
+
342
+ /**
343
+ * Renders a single {@link ToolCall} as a collapsible row: status icon, label, an
344
+ * input summary, and — when expanded — the formatted result (a {@link MiniTable}
345
+ * for tabular JSON, otherwise text). Used inside the {@link Timeline}.
346
+ *
347
+ * @example
348
+ * ```tsx
349
+ * import { ToolRow } from "@pgege/kaboo-react";
350
+ * import type { ToolCall } from "@pgege/kaboo-react";
351
+ *
352
+ * const tool: ToolCall = {
353
+ * toolUseId: "t1",
354
+ * toolName: "run_sql",
355
+ * toolInput: { query: "select 1" },
356
+ * status: "done",
357
+ * };
358
+ *
359
+ * function Example() {
360
+ * return <ToolRow tool={tool} />;
361
+ * }
362
+ * ```
363
+ */
364
+ declare function ToolRow({ tool }: {
365
+ tool: ToolCall;
366
+ }): react.JSX.Element;
367
+
368
+ /**
369
+ * Compact table for row-shaped tool results. Columns are inferred from the first
370
+ * row's keys; underscores in headers become spaces. Renders at most `maxRows`
371
+ * rows with a "+N more" footer, and nothing at all for an empty list.
372
+ *
373
+ * @example
374
+ * ```tsx
375
+ * import { MiniTable } from "@pgege/kaboo-react";
376
+ *
377
+ * function Example() {
378
+ * return <MiniTable rows={[{ id: "1", name: "Ada" }]} maxRows={5} />;
379
+ * }
380
+ * ```
381
+ */
382
+ declare function MiniTable({ rows, maxRows }: {
383
+ rows: Record<string, string>[];
384
+ maxRows?: number;
385
+ }): react.JSX.Element | null;
386
+
387
+ /**
388
+ * Breadcrumb navigation for the drill-down path: a "Chat" root followed by one
389
+ * crumb per drilled-in group. Clicking a crumb jumps to that level; the current
390
+ * (last) crumb is disabled. Renders nothing at the root. Pair with
391
+ * {@link DrillDetailView}.
392
+ *
393
+ * @example
394
+ * ```tsx
395
+ * import { GlassTabs, DrillDetailView } from "@pgege/kaboo-react";
396
+ *
397
+ * function DrillArea() {
398
+ * return (
399
+ * <>
400
+ * <GlassTabs />
401
+ * <DrillDetailView />
402
+ * </>
403
+ * );
404
+ * }
405
+ * ```
406
+ */
407
+ declare function GlassTabs(): react.JSX.Element | null;
408
+
409
+ /**
410
+ * Detail pane for the currently drilled-in group: its task, full timeline
411
+ * (with delegated sub-agents interleaved at their tool-call position), any
412
+ * unanchored interrupt prompts, and a "Sub-agents" section for swarm/graph
413
+ * members. Renders a hidden placeholder at the root. Pair with {@link GlassTabs}.
414
+ *
415
+ * @example
416
+ * ```tsx
417
+ * import { GlassTabs, DrillDetailView } from "@pgege/kaboo-react";
418
+ *
419
+ * function DrillArea() {
420
+ * return (
421
+ * <>
422
+ * <GlassTabs />
423
+ * <DrillDetailView />
424
+ * </>
425
+ * );
426
+ * }
427
+ * ```
428
+ */
429
+ declare function DrillDetailView(): react.JSX.Element;
430
+
431
+ /**
432
+ * Minimal, dependency-free markdown renderer used for agent text: supports
433
+ * `#`/`##`/`###` headings, `-`/`*` list items, `**bold**` inline, and blank-line
434
+ * spacing. Intentionally small — it is not a full CommonMark implementation.
435
+ *
436
+ * @example
437
+ * ```tsx
438
+ * import { MarkdownContent } from "@pgege/kaboo-react";
439
+ *
440
+ * function Example() {
441
+ * return <MarkdownContent text={"# Title\n\nSome **bold** text."} />;
442
+ * }
443
+ * ```
444
+ */
445
+ declare function MarkdownContent({ text }: {
446
+ text: string;
447
+ }): react.JSX.Element;
448
+
449
+ /**
450
+ * Default human-in-the-loop interrupt UI. Renders an Approve/Reject panel for an
451
+ * {@link ApprovalReason} and a (optionally multi-step) form with radio/checkbox/
452
+ * text inputs for a {@link FormReason}, calling `onResolve`/`onCancel` with the
453
+ * answer payload. Override per type via `interruptRenderers` on
454
+ * {@link KabooProvider}.
455
+ *
456
+ * @example
457
+ * ```tsx
458
+ * import { InterruptRenderer } from "@pgege/kaboo-react";
459
+ * import type { InterruptReason } from "@pgege/kaboo-react";
460
+ *
461
+ * const reason: InterruptReason = {
462
+ * type: "approval",
463
+ * message: "Run this query?",
464
+ * tool_name: "run_sql",
465
+ * };
466
+ *
467
+ * function Example() {
468
+ * return (
469
+ * <InterruptRenderer
470
+ * reason={reason}
471
+ * onResolve={() => {}}
472
+ * onCancel={() => {}}
473
+ * />
474
+ * );
475
+ * }
476
+ * ```
477
+ */
478
+ declare function InterruptRenderer(props: InterruptRendererProps): ReactElement;
479
+
480
+ /** Props for {@link Timeline}. */
481
+ interface TimelineProps {
482
+ /** The interleaved text/tool entries to render, in order. */
483
+ timeline: TimelineEntry[];
484
+ /** When true, a blinking cursor is shown after the last text segment. */
485
+ active: boolean;
486
+ /** Visual variant selecting the text container class. */
487
+ variant?: "card" | "drill";
488
+ /**
489
+ * Optional hook to render a delegating tool call as its spawned sub-agent
490
+ * card, interleaved at its chronological position. Returns the card node for a
491
+ * given tool-call id, or `null`/`undefined` to fall back to the tool row. Keeps
492
+ * a delegated agent's work in order relative to the parent's surrounding text.
493
+ */
494
+ renderToolCard?: (toolUseId: string) => ReactNode | null | undefined;
495
+ }
496
+ /**
497
+ * Chronological render of interleaved text segments and tool calls. Shared by
498
+ * {@link AgentCard} and {@link DrillDetailView} so the two stay in sync.
499
+ */
500
+ declare function Timeline({ timeline, active, variant, renderToolCard }: TimelineProps): react.JSX.Element;
501
+
502
+ /**
503
+ * Condenses arbitrary tool input into a short one-line `summary` for a tool row.
504
+ * Prefers well-known fields (`query`/`table_name`/`url`), unwraps single-key
505
+ * objects, and otherwise joins `key: value` pairs. `detail` is reserved for
506
+ * future expansion and is currently always `null`.
507
+ *
508
+ * @example
509
+ * ```ts
510
+ * import { formatToolInput } from "@pgege/kaboo-react";
511
+ *
512
+ * const { summary } = formatToolInput({ query: "select 1" });
513
+ * // summary === "select 1"
514
+ * ```
515
+ */
516
+ declare function formatToolInput(input: unknown): {
517
+ /** One-line summary suitable for a tool row. */
518
+ summary: string;
519
+ /** Reserved for future detail expansion; currently always `null`. */
520
+ detail: string | null;
521
+ };
522
+
523
+ /**
524
+ * Parses a raw tool result into a renderable shape: `rows` (for tabular JSON —
525
+ * either `{ rows: [...] }` or a top-level array of objects) or `text` (a
526
+ * `key: value` rendering of an object, or the raw string when it isn't JSON).
527
+ *
528
+ * @example
529
+ * ```ts
530
+ * import { formatToolResult } from "@pgege/kaboo-react";
531
+ *
532
+ * const { rows } = formatToolResult('{"rows":[{"id":"1"}]}');
533
+ * // rows?.length === 1
534
+ * ```
535
+ */
536
+ declare function formatToolResult(raw: string): {
537
+ /** Row-shaped result for a table view, or `null` when not tabular. */
538
+ rows: Record<string, string>[] | null;
539
+ /** Text rendering of the result when it is not tabular. */
540
+ text: string;
541
+ };
542
+ /**
543
+ * Normalizes a raw result string for display: unwraps one layer of JSON string
544
+ * encoding, converts escaped `\n` into real newlines, and returns `null` for
545
+ * empty/undefined input.
546
+ *
547
+ * @example
548
+ * ```ts
549
+ * import { normalizeResult } from "@pgege/kaboo-react";
550
+ *
551
+ * normalizeResult('"line one\\nline two"');
552
+ * // "line one\nline two"
553
+ * ```
554
+ */
555
+ declare function normalizeResult(result: string | undefined): string | null;
556
+
557
+ export { type ActiveInterrupt, ActivityPanel, ActivityState, AgentCard, type AgentCardProps, DrillDetailView, DrillProvider, DrillState, GlassTabs, type GroupEntry, InterruptBridgeProvider, InterruptBridgePublisher, InterruptReason, InterruptRenderer, InterruptRendererProps, KabooActivityProvider, type KabooActivityProviderProps, KabooProvider, type KabooProviderProps, MarkdownContent, MiniTable, StreamGroup, type StructuredRenderers, StructuredRenderersContext, Timeline, TimelineEntry, type TimelineProps, ToolCall, ToolRow, directChildren, formatToolInput, formatToolResult, normalizeResult, topLevelGroups, useActivity, useDrill, useInterruptBridge, useInterruptFor };