@principal-ai/principal-view-react 0.15.9 → 0.16.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,656 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * SessionEventFeed — a three-column diagnostic feed over one agent session's
4
+ * events, showing the raw V1 event → repo-normalized → accumulated (UI) pipeline
5
+ * for every row.
6
+ *
7
+ * Input rows match the trail-viewer's `SessionEventRow` wire shape:
8
+ * { seq, type, raw, normalized, accumulated }
9
+ * `raw` is the raw V1 event payload, `normalized` its repo-normalized form, and
10
+ * `accumulated` the AgentSessionEvent the File City UI actually renders (null
11
+ * when the accumulator drops the event).
12
+ *
13
+ * Dark diagnostic palette — intentionally self-contained rather than themed.
14
+ */
15
+ import { useCallback, useMemo, useState } from 'react';
16
+ /** Shared collapse state keyed by row seq. */
17
+ function useCollapse(seqs, defaultCollapsed = false) {
18
+ const [collapsed, setCollapsed] = useState(() => (defaultCollapsed ? new Set(seqs) : new Set()));
19
+ const toggle = useCallback((seq) => {
20
+ setCollapsed((prev) => {
21
+ const next = new Set(prev);
22
+ if (next.has(seq))
23
+ next.delete(seq);
24
+ else
25
+ next.add(seq);
26
+ return next;
27
+ });
28
+ }, []);
29
+ const setAll = useCallback((value) => setCollapsed(value ? new Set(seqs) : new Set()), [seqs]);
30
+ return { collapsed, toggle, setAll };
31
+ }
32
+ function toRaw(raw) {
33
+ return raw;
34
+ }
35
+ function toNormalized(normalized) {
36
+ return normalized;
37
+ }
38
+ // =============================================================================
39
+ // Raw event → presentable pieces
40
+ // =============================================================================
41
+ function dataOf(e) {
42
+ return (e.data ?? {});
43
+ }
44
+ function partOf(e) {
45
+ return dataOf(e).part;
46
+ }
47
+ function eventTimestamp(e) {
48
+ const d = dataOf(e);
49
+ if (typeof d.time === 'number')
50
+ return d.time;
51
+ const info = d.info;
52
+ const infoTime = info?.time;
53
+ if (typeof infoTime?.created === 'number')
54
+ return infoTime.created;
55
+ const part = partOf(e);
56
+ if (typeof part?.time === 'number')
57
+ return part.time;
58
+ const state = part?.state;
59
+ const stateTime = state?.time;
60
+ if (typeof stateTime?.start === 'number')
61
+ return stateTime.start;
62
+ if (typeof stateTime?.end === 'number')
63
+ return stateTime.end;
64
+ return 0;
65
+ }
66
+ const ALL_CATEGORIES = [
67
+ 'session',
68
+ 'conversation',
69
+ 'tool',
70
+ 'step',
71
+ 'patch',
72
+ 'compaction',
73
+ ];
74
+ function eventCategory(e) {
75
+ switch (e.type) {
76
+ case 'session.created.1':
77
+ case 'session.updated.1':
78
+ return 'session';
79
+ case 'message.updated.1':
80
+ case 'message.removed.1':
81
+ case 'message.part.updated.1': {
82
+ const partType = partOf(e)?.type;
83
+ switch (partType) {
84
+ case 'text':
85
+ case 'reasoning':
86
+ return 'conversation';
87
+ case 'tool':
88
+ return 'tool';
89
+ case 'step-start':
90
+ case 'step-finish':
91
+ return 'step';
92
+ case 'patch':
93
+ return 'patch';
94
+ case 'compaction':
95
+ return 'compaction';
96
+ default:
97
+ return 'conversation';
98
+ }
99
+ }
100
+ default:
101
+ return 'conversation';
102
+ }
103
+ }
104
+ const PRESETS = [
105
+ { id: 'all', label: 'All', include: ALL_CATEGORIES },
106
+ { id: 'activity', label: 'Activity', include: ['conversation', 'tool', 'patch'] },
107
+ { id: 'conversation', label: 'Conversation', include: ['conversation'] },
108
+ { id: 'tools', label: 'Tools', include: ['tool'] },
109
+ { id: 'noise', label: 'Session & steps', include: ['session', 'step', 'compaction'] },
110
+ ];
111
+ /** Granular key for a card (raw event type, or part type for parts). */
112
+ function eventKind(e) {
113
+ if (e.type === 'message.part.updated.1') {
114
+ return `part:${partOf(e)?.type ?? 'unknown'}`;
115
+ }
116
+ return e.type;
117
+ }
118
+ function kindLabel(kind) {
119
+ if (kind.startsWith('part:'))
120
+ return `part · ${kind.slice(5)}`;
121
+ return kind;
122
+ }
123
+ const KIND_COLORS = {
124
+ 'session.created.1': '#64748b',
125
+ 'session.updated.1': '#94a3b8',
126
+ 'message.updated.1': '#06b6d4',
127
+ 'message.removed.1': '#ef4444',
128
+ 'part:text': '#10b981',
129
+ 'part:reasoning': '#8b5cf6',
130
+ 'part:tool': '#3b82f6',
131
+ 'part:step-start': '#f59e0b',
132
+ 'part:step-finish': '#f59e0b',
133
+ 'part:patch': '#ef4444',
134
+ 'part:compaction': '#ec4899',
135
+ 'part:unknown': '#6b7280',
136
+ };
137
+ function kindColor(kind) {
138
+ return KIND_COLORS[kind] ?? '#6b7280';
139
+ }
140
+ function describe(e) {
141
+ const d = dataOf(e);
142
+ const info = d.info;
143
+ const part = partOf(e);
144
+ const state = part?.state;
145
+ switch (e.type) {
146
+ case 'session.created.1':
147
+ return info?.title ?? 'Session created';
148
+ case 'session.updated.1': {
149
+ const bits = [];
150
+ const tokens = info?.tokens;
151
+ if (typeof info?.cost === 'number')
152
+ bits.push(`$${info.cost.toFixed(4)}`);
153
+ if (typeof tokens?.input === 'number')
154
+ bits.push(`${tokens.input} in`);
155
+ if (typeof tokens?.output === 'number')
156
+ bits.push(`${tokens.output} out`);
157
+ return bits.length > 0 ? `Session updated · ${bits.join(' · ')}` : 'Session updated';
158
+ }
159
+ case 'message.updated.1': {
160
+ const role = info?.role ?? 'message';
161
+ const model = info?.model?.modelID;
162
+ return model ? `${role} message · ${model}` : `${role} message`;
163
+ }
164
+ case 'message.removed.1':
165
+ return `Removed ${d.messageID}`;
166
+ case 'message.part.updated.1': {
167
+ const partType = part?.type;
168
+ const toolName = part?.tool;
169
+ const status = state?.status;
170
+ switch (partType) {
171
+ case 'text':
172
+ return part?.text ?? 'Text';
173
+ case 'reasoning':
174
+ return part?.text || 'Reasoning';
175
+ case 'tool':
176
+ return [toolName, status].filter(Boolean).join(' · ') || 'Tool';
177
+ case 'step-start':
178
+ return 'Step start';
179
+ case 'step-finish':
180
+ return part?.reason ? `Step finish · ${part.reason}` : 'Step finish';
181
+ case 'patch': {
182
+ const files = part?.files;
183
+ return `Patch · ${files?.length ?? 0} file${(files?.length ?? 0) === 1 ? '' : 's'}`;
184
+ }
185
+ case 'compaction':
186
+ return `Compaction${part?.auto ? ' · auto' : ''}`;
187
+ default:
188
+ return partType ?? 'Part';
189
+ }
190
+ }
191
+ default:
192
+ return e.type;
193
+ }
194
+ }
195
+ function toolSummary(input) {
196
+ if (input === null || input === undefined)
197
+ return '';
198
+ if (typeof input === 'string')
199
+ return input;
200
+ if (Array.isArray(input))
201
+ return JSON.stringify(input).slice(0, 120);
202
+ const obj = input;
203
+ for (const key of ['command', 'filePath', 'file_path', 'path', 'pattern', 'include', 'tool']) {
204
+ if (typeof obj[key] === 'string' && obj[key] !== '')
205
+ return obj[key];
206
+ }
207
+ return JSON.stringify(input).slice(0, 120);
208
+ }
209
+ // =============================================================================
210
+ // Cards
211
+ // =============================================================================
212
+ function formatTime(ts) {
213
+ if (!ts)
214
+ return '';
215
+ return new Date(ts).toLocaleTimeString([], {
216
+ hour: '2-digit',
217
+ minute: '2-digit',
218
+ second: '2-digit',
219
+ });
220
+ }
221
+ function RawEventCard({ event, expanded, onToggle, }) {
222
+ const kind = eventKind(event);
223
+ const d = dataOf(event);
224
+ const part = partOf(event);
225
+ const state = part?.state;
226
+ const color = kindColor(kind);
227
+ const body = useMemo(() => (() => {
228
+ switch (event.type) {
229
+ case 'session.created.1': {
230
+ const info = d.info;
231
+ return (_jsx(MetaRows, { rows: [
232
+ ['agent', info?.agent],
233
+ ['model', info?.model?.id ?? info?.model?.modelID],
234
+ ['directory', info?.directory],
235
+ ['version', info?.version],
236
+ ['slug', info?.slug],
237
+ ] }));
238
+ }
239
+ case 'session.updated.1': {
240
+ const info = d.info;
241
+ return (_jsx(MetaRows, { rows: [
242
+ ['cost', typeof info?.cost === 'number' ? `$${info.cost.toFixed(4)}` : undefined],
243
+ ['tokens', info?.tokens],
244
+ ['title', info?.title],
245
+ ] }));
246
+ }
247
+ case 'message.updated.1': {
248
+ const info = d.info;
249
+ return (_jsx(MetaRows, { rows: [
250
+ ['role', info?.role],
251
+ ['agent', info?.agent],
252
+ ['model', info?.model],
253
+ ['tokens', info?.tokens],
254
+ ['messageID', info?.id],
255
+ ] }));
256
+ }
257
+ case 'message.removed.1':
258
+ return _jsx(MetaRows, { rows: [['messageID', d.messageID]] });
259
+ case 'message.part.updated.1': {
260
+ switch (part?.type) {
261
+ case 'text':
262
+ case 'reasoning':
263
+ return _jsx(TextView, { text: part?.text });
264
+ case 'tool':
265
+ return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 8 }, children: [_jsxs("div", { style: { fontSize: 12, color: '#9ca3af' }, children: ["callID ", String(part?.callID ?? ''), " \u00B7 ", String(state?.status ?? '')] }), _jsx(ToolIO, { input: state?.input, output: state?.status === 'error' ? state?.error : state?.output })] }));
266
+ case 'step-start':
267
+ return _jsx(MetaRows, { rows: [['snapshot', part?.snapshot]] });
268
+ case 'step-finish':
269
+ return (_jsx(MetaRows, { rows: [
270
+ ['reason', part?.reason],
271
+ ['cost', typeof part?.cost === 'number' ? `$${part.cost.toFixed(4)}` : undefined],
272
+ ['tokens', part?.tokens],
273
+ ] }));
274
+ case 'patch':
275
+ return (_jsx(MetaRows, { rows: [
276
+ ['files', part?.files],
277
+ ['hash', part?.hash],
278
+ ] }));
279
+ case 'compaction':
280
+ return (_jsx(MetaRows, { rows: [
281
+ ['auto', typeof part?.auto === 'boolean' ? String(part.auto) : undefined],
282
+ ['overflow', typeof part?.overflow === 'boolean' ? String(part.overflow) : undefined],
283
+ ] }));
284
+ default:
285
+ return _jsx(JsonView, { value: d });
286
+ }
287
+ }
288
+ default:
289
+ return _jsx(JsonView, { value: d });
290
+ }
291
+ })(), [event]);
292
+ return (_jsxs("div", { style: {
293
+ display: 'flex',
294
+ flexDirection: 'column',
295
+ gap: expanded ? 8 : 0,
296
+ padding: '10px 14px',
297
+ borderRadius: 0,
298
+ minWidth: 0,
299
+ overflow: 'hidden',
300
+ backgroundColor: expanded ? '#111827' : '#161b26',
301
+ fontFamily: 'system-ui, sans-serif',
302
+ fontSize: 13,
303
+ }, children: [_jsxs("button", { onClick: onToggle, "aria-expanded": expanded, style: {
304
+ display: 'flex',
305
+ alignItems: 'center',
306
+ gap: 8,
307
+ width: '100%',
308
+ border: 'none',
309
+ background: 'none',
310
+ padding: 0,
311
+ cursor: 'pointer',
312
+ fontFamily: 'inherit',
313
+ textAlign: 'left',
314
+ }, children: [_jsxs("span", { style: { color: '#6b7280', fontSize: 11, whiteSpace: 'nowrap' }, children: ["#", event.seq] }), _jsx("span", { style: {
315
+ fontSize: 11,
316
+ fontWeight: 600,
317
+ textTransform: 'uppercase',
318
+ letterSpacing: 0.5,
319
+ color,
320
+ whiteSpace: 'nowrap',
321
+ }, children: kindLabel(kind) }), _jsx("span", { style: {
322
+ flex: 1,
323
+ overflow: 'hidden',
324
+ textOverflow: 'ellipsis',
325
+ whiteSpace: 'nowrap',
326
+ color: '#e5e7eb',
327
+ }, children: describe(event) }), _jsx("span", { style: { color: '#6b7280', fontSize: 11, whiteSpace: 'nowrap' }, children: formatTime(eventTimestamp(event)) })] }), expanded ? body : null] }));
328
+ }
329
+ function prettifyEventType(t) {
330
+ return t.replace(/-/g, ' ');
331
+ }
332
+ function normalizedDescribe(n) {
333
+ if (n.toolName)
334
+ return [n.toolName, n.operation].filter(Boolean).join(' · ');
335
+ if (n.operation)
336
+ return n.operation;
337
+ const d = n.data;
338
+ if (typeof d?.message === 'string')
339
+ return d.message.slice(0, 90);
340
+ return prettifyEventType(n.eventType);
341
+ }
342
+ function repoLabel(repo) {
343
+ const identity = repo.owner && repo.repo ? `${repo.owner}/${repo.repo}` : repo.repo ?? '';
344
+ return identity && repo.root ? `${identity} @ ${repo.root}` : repo.root ?? '';
345
+ }
346
+ function NormalizedEventCard({ event, seq, color, expanded, onToggle, }) {
347
+ return (_jsxs("div", { style: {
348
+ display: 'flex',
349
+ flexDirection: 'column',
350
+ gap: expanded ? 8 : 0,
351
+ padding: '10px 14px',
352
+ borderRadius: 0,
353
+ minWidth: 0,
354
+ overflow: 'hidden',
355
+ backgroundColor: expanded ? '#0d1520' : '#101722',
356
+ fontFamily: 'system-ui, sans-serif',
357
+ fontSize: 13,
358
+ }, children: [_jsxs("button", { onClick: onToggle, "aria-expanded": expanded, style: {
359
+ display: 'flex',
360
+ alignItems: 'center',
361
+ gap: 8,
362
+ width: '100%',
363
+ border: 'none',
364
+ background: 'none',
365
+ padding: 0,
366
+ cursor: 'pointer',
367
+ fontFamily: 'inherit',
368
+ textAlign: 'left',
369
+ }, children: [_jsxs("span", { style: { color: '#6b7280', fontSize: 11, whiteSpace: 'nowrap' }, children: ["#", seq] }), _jsx("span", { style: {
370
+ fontSize: 11,
371
+ fontWeight: 600,
372
+ textTransform: 'uppercase',
373
+ letterSpacing: 0.5,
374
+ color,
375
+ whiteSpace: 'nowrap',
376
+ }, children: prettifyEventType(event.eventType) }), _jsx("span", { style: {
377
+ flex: 1,
378
+ overflow: 'hidden',
379
+ textOverflow: 'ellipsis',
380
+ whiteSpace: 'nowrap',
381
+ color: '#e5e7eb',
382
+ }, children: normalizedDescribe(event) }), _jsx("span", { style: { color: '#6b7280', fontSize: 11, whiteSpace: 'nowrap' }, children: formatTime(event.timestamp) })] }), expanded ? (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 8 }, children: [_jsx(MetaRows, { rows: [
383
+ ['eventType', event.eventType],
384
+ ['operation', event.operation],
385
+ ['toolName', event.toolName],
386
+ ['sessionId', event.sessionId],
387
+ ['workingDir', event.normalizedWorkingDirectory],
388
+ ['repository', event.repository ? repoLabel(event.repository) : undefined],
389
+ ] }), event.files && event.files.length > 0 ? (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 3 }, children: [_jsxs("div", { style: { fontSize: 11, color: '#6b7280' }, children: ["files (", event.files.length, ")"] }), event.files.map((file, i) => (_jsx(FileRow, { file: file }, i)))] })) : null, event.toolInput !== undefined ? (_jsx(ToolIO, { input: event.toolInput, output: event.toolOutput })) : null] })) : null] }));
390
+ }
391
+ function FileRow({ file }) {
392
+ return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 1 }, children: [_jsx("div", { style: {
393
+ color: '#93c5fd',
394
+ fontSize: 12,
395
+ wordBreak: 'break-word',
396
+ fontFamily: 'monospace',
397
+ }, children: file.displayPath }), _jsxs("div", { style: { color: '#6b7280', fontSize: 11, wordBreak: 'break-word' }, children: [file.context, file.repository
398
+ ? ` · ${file.repository.gitRoot} → ${file.repository.relativePath}`
399
+ : ` · ${file.absolutePath}`] })] }));
400
+ }
401
+ const OPERATION_COLORS = {
402
+ starting: '#6b7280',
403
+ prompting: '#a78bfa',
404
+ reading: '#a855f7',
405
+ grepping: '#e879f9',
406
+ editing: '#22c55e',
407
+ tool: '#3b82f6',
408
+ errored: '#ef4444',
409
+ waiting: '#9ca3af',
410
+ finished: '#10b981',
411
+ compacting: '#ec4899',
412
+ subagent: '#f59e0b',
413
+ };
414
+ function AccumulatedEventCard({ event, seq, expanded, onToggle, }) {
415
+ if (!event) {
416
+ return (_jsxs("div", { style: {
417
+ display: 'flex',
418
+ alignItems: 'center',
419
+ gap: 8,
420
+ padding: '10px 14px',
421
+ borderRadius: 0,
422
+ minWidth: 0,
423
+ overflow: 'hidden',
424
+ border: '1px dashed #1f2937',
425
+ backgroundColor: '#0d1117',
426
+ fontFamily: 'system-ui, sans-serif',
427
+ fontSize: 12,
428
+ }, children: [_jsxs("span", { style: { color: '#374151', whiteSpace: 'nowrap' }, children: ["#", seq] }), _jsx("span", { style: { color: '#4b5563', fontStyle: 'italic' }, children: "no UI event (accumulator dropped)" })] }));
429
+ }
430
+ const opColor = OPERATION_COLORS[event.operation] ?? '#6b7280';
431
+ return (_jsxs("div", { style: {
432
+ display: 'flex',
433
+ flexDirection: 'column',
434
+ gap: expanded ? 8 : 0,
435
+ padding: '10px 14px',
436
+ borderRadius: 0,
437
+ minWidth: 0,
438
+ overflow: 'hidden',
439
+ backgroundColor: expanded ? '#121a13' : '#141b16',
440
+ fontFamily: 'system-ui, sans-serif',
441
+ fontSize: 13,
442
+ }, children: [_jsxs("button", { onClick: onToggle, "aria-expanded": expanded, style: {
443
+ display: 'flex',
444
+ alignItems: 'center',
445
+ gap: 8,
446
+ width: '100%',
447
+ border: 'none',
448
+ background: 'none',
449
+ padding: 0,
450
+ cursor: 'pointer',
451
+ fontFamily: 'inherit',
452
+ textAlign: 'left',
453
+ }, children: [_jsx("span", { style: {
454
+ width: 8,
455
+ height: 8,
456
+ borderRadius: '50%',
457
+ flexShrink: 0,
458
+ backgroundColor: event.sessionColor,
459
+ } }), _jsxs("span", { style: { color: '#6b7280', fontSize: 11, whiteSpace: 'nowrap' }, children: ["#", seq] }), _jsx("span", { style: {
460
+ fontSize: 11,
461
+ fontWeight: 600,
462
+ textTransform: 'uppercase',
463
+ letterSpacing: 0.5,
464
+ color: opColor,
465
+ whiteSpace: 'nowrap',
466
+ }, children: event.operation }), _jsx("span", { style: {
467
+ flex: 1,
468
+ overflow: 'hidden',
469
+ textOverflow: 'ellipsis',
470
+ whiteSpace: 'nowrap',
471
+ color: '#e5e7eb',
472
+ }, children: event.description }), _jsx("span", { style: { color: '#6b7280', fontSize: 11, whiteSpace: 'nowrap' }, children: formatTime(event.timestamp) })] }), expanded ? (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 8 }, children: [_jsx(MetaRows, { rows: [
473
+ ['operation', event.operation],
474
+ ['session', event.sessionName],
475
+ ['contextTokens', event.contextTokens],
476
+ ['toolName', event.toolName],
477
+ ['subagent', event.subagentType],
478
+ ['childSessionId', event.childSessionId],
479
+ ] }), _jsx("div", { style: { fontSize: 12, color: '#6b7280' }, children: event.description }), event.files.length > 0 ? _jsx(PathList, { label: "files", paths: event.files }) : null, event.dependencies.length > 0 ? (_jsx(PathList, { label: "dependencies", paths: event.dependencies })) : null, event.layers.length > 0 ? (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsx("div", { style: { fontSize: 11, color: '#6b7280' }, children: "layers" }), event.layers.map((layer) => (_jsxs("div", { style: { display: 'flex', gap: 6, alignItems: 'center', fontSize: 12 }, children: [_jsx("span", { style: {
480
+ width: 8,
481
+ height: 8,
482
+ borderRadius: '50%',
483
+ backgroundColor: layer.color,
484
+ opacity: 0.8,
485
+ } }), _jsxs("span", { style: { color: '#d1d5db' }, children: [layer.name, " (", layer.items.length, ")"] })] }, layer.id)))] })) : null] })) : null] }));
486
+ }
487
+ function PathList({ label, paths }) {
488
+ return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsx("div", { style: { fontSize: 11, color: '#6b7280' }, children: label }), paths.map((p, i) => (_jsx("div", { style: { color: '#93c5fd', fontSize: 11.5, fontFamily: 'monospace', wordBreak: 'break-word' }, children: p.displayPath }, i)))] }));
489
+ }
490
+ function TextView({ text }) {
491
+ if (!text)
492
+ return _jsx("div", { style: { color: '#6b7280', fontSize: 12 }, children: "(empty)" });
493
+ return (_jsx("div", { style: {
494
+ color: '#d1d5db',
495
+ fontSize: 12.5,
496
+ lineHeight: 1.5,
497
+ maxHeight: 120,
498
+ overflowY: 'auto',
499
+ whiteSpace: 'pre-wrap',
500
+ wordBreak: 'break-word',
501
+ }, children: text }));
502
+ }
503
+ function ToolIO({ input, output }) {
504
+ const summary = toolSummary(input);
505
+ return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 6 }, children: [summary ? (_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8 }, children: [_jsx("span", { style: { fontSize: 11, color: '#60a5fa', fontWeight: 600 }, children: "IN" }), _jsx("code", { style: { color: '#93c5fd', fontSize: 12, wordBreak: 'break-word' }, children: summary })] })) : null, input !== undefined && input !== null && typeof input === 'object' ? (_jsx(CodeBlock, { value: JSON.stringify(input, null, 2) })) : null, output !== undefined && output !== null ? (_jsxs(_Fragment, { children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8 }, children: [_jsx("span", { style: { fontSize: 11, color: '#34d399', fontWeight: 600 }, children: "OUT" }), _jsx("span", { style: { fontSize: 11, color: '#6b7280' }, children: typeof output === 'string' ? `${output.length.toLocaleString()} chars` : 'object' })] }), _jsx(CodeBlock, { value: typeof output === 'string' ? output : JSON.stringify(output, null, 2) })] })) : null] }));
506
+ }
507
+ function CodeBlock({ value }) {
508
+ return (_jsx("pre", { style: {
509
+ margin: 0,
510
+ padding: 8,
511
+ borderRadius: 6,
512
+ backgroundColor: '#0b1220',
513
+ color: '#9ca3af',
514
+ fontSize: 11.5,
515
+ lineHeight: 1.45,
516
+ maxHeight: 180,
517
+ overflow: 'auto',
518
+ whiteSpace: 'pre-wrap',
519
+ wordBreak: 'break-word',
520
+ }, children: value }));
521
+ }
522
+ function MetaRows({ rows }) {
523
+ const present = rows.filter(([, v]) => v !== undefined && v !== null && v !== '');
524
+ if (present.length === 0)
525
+ return null;
526
+ return (_jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: 3 }, children: present.map(([label, value]) => (_jsxs("div", { style: { display: 'flex', gap: 8, fontSize: 12 }, children: [_jsx("span", { style: { color: '#6b7280', minWidth: 76, whiteSpace: 'nowrap' }, children: label }), _jsx("span", { style: {
527
+ color: '#d1d5db',
528
+ wordBreak: 'break-word',
529
+ whiteSpace: typeof value === 'string' ? 'pre-wrap' : 'nowrap',
530
+ }, children: typeof value === 'string'
531
+ ? value
532
+ : Array.isArray(value)
533
+ ? value.join(', ')
534
+ : JSON.stringify(value) })] }, label))) }));
535
+ }
536
+ function JsonView({ value }) {
537
+ return _jsx(CodeBlock, { value: JSON.stringify(value, null, 2) });
538
+ }
539
+ // =============================================================================
540
+ // Feed
541
+ // =============================================================================
542
+ export function SessionEventFeed({ title, rows }) {
543
+ const items = useMemo(() => [...rows].sort((a, b) => a.seq - b.seq), [rows]);
544
+ const seqs = useMemo(() => items.map((r) => r.seq), [items]);
545
+ const { collapsed, toggle, setAll } = useCollapse(seqs, true);
546
+ const [active, setActive] = useState('activity');
547
+ const activePreset = PRESETS.find((p) => p.id === active) ?? PRESETS[0];
548
+ const isVisible = (raw) => activePreset.include.includes(eventCategory(raw));
549
+ const visibleEvents = items.filter((r) => isVisible(toRaw(r.raw)));
550
+ const presetCounts = useMemo(() => {
551
+ const map = new Map();
552
+ for (const preset of PRESETS) {
553
+ map.set(preset.id, items.filter((r) => preset.include.includes(eventCategory(toRaw(r.raw)))).length);
554
+ }
555
+ return map;
556
+ }, [items]);
557
+ const expandedCount = visibleEvents.filter((r) => !collapsed.has(r.seq)).length;
558
+ return (_jsxs("div", { style: { padding: 24, backgroundColor: '#0d1117', minHeight: '100vh' }, children: [_jsxs("div", { style: {
559
+ display: 'flex',
560
+ alignItems: 'baseline',
561
+ gap: 12,
562
+ marginBottom: 4,
563
+ fontFamily: 'system-ui, sans-serif',
564
+ }, children: [_jsx("h1", { style: { margin: 0, color: '#f3f4f6', fontSize: 18, fontWeight: 600 }, children: title }), _jsxs("span", { style: { color: '#6b7280', fontSize: 12 }, children: [items.length, " raw events \u00B7 ", visibleEvents.length, " visible \u00B7 ", expandedCount, " expanded"] })] }), _jsxs("div", { style: {
565
+ display: 'flex',
566
+ gap: 6,
567
+ flexWrap: 'wrap',
568
+ marginBottom: 16,
569
+ fontFamily: 'system-ui, sans-serif',
570
+ }, children: [_jsx(FilterChip, { label: "all", active: active === 'all', onClick: () => setActive('all') }), PRESETS.filter((p) => p.id !== 'all').map((preset) => (_jsx(FilterChip, { label: `${preset.label} (${presetCounts.get(preset.id) ?? 0})`, active: active === preset.id, onClick: () => setActive(preset.id) }, preset.id))), _jsx("span", { style: { flex: 1 } }), _jsx(FilterChip, { label: "Expand all", active: false, onClick: () => setAll(false) }), _jsx(FilterChip, { label: "Collapse all", active: false, onClick: () => setAll(true) })] }), _jsx(ColumnHeaders, {}), _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: 8, maxWidth: 1300 }, children: items.map((r) => (_jsx(EventRow, { row: r, visible: isVisible(toRaw(r.raw)), expanded: !collapsed.has(r.seq), onToggle: () => toggle(r.seq) }, r.seq))) })] }));
571
+ }
572
+ export function SessionEventFeedGrouped({ title, rows }) {
573
+ const items = useMemo(() => [...rows].sort((a, b) => a.seq - b.seq), [rows]);
574
+ const byKind = useMemo(() => {
575
+ const map = new Map();
576
+ for (const r of items) {
577
+ const kind = eventKind(toRaw(r.raw));
578
+ map.set(kind, [...(map.get(kind) ?? []), r]);
579
+ }
580
+ return map;
581
+ }, [items]);
582
+ return (_jsxs("div", { style: { padding: 24, backgroundColor: '#0d1117', minHeight: '100vh' }, children: [title ? (_jsx("h1", { style: { margin: '0 0 12px', color: '#f3f4f6', fontSize: 18, fontWeight: 600, fontFamily: 'system-ui, sans-serif' }, children: title })) : null, _jsx(ColumnHeaders, {}), Array.from(byKind.entries())
583
+ .sort((a, b) => b[1].length - a[1].length)
584
+ .map(([kind, group]) => (_jsx(GroupSection, { kind: kind, group: group }, kind)))] }));
585
+ }
586
+ function GroupSection({ kind, group }) {
587
+ const seqs = useMemo(() => group.map((r) => r.seq), [group]);
588
+ const { collapsed, toggle, setAll } = useCollapse(seqs, true);
589
+ return (_jsxs("div", { style: { marginBottom: 20 }, children: [_jsxs("div", { style: {
590
+ display: 'flex',
591
+ alignItems: 'center',
592
+ gap: 8,
593
+ marginBottom: 8,
594
+ fontFamily: 'system-ui, sans-serif',
595
+ }, children: [_jsx("span", { style: { color: kindColor(kind), fontWeight: 600, fontSize: 13 }, children: kindLabel(kind) }), _jsx("span", { style: { color: '#6b7280', fontSize: 12 }, children: group.length }), _jsx("span", { style: { flex: 1 } }), _jsx(FilterChip, { label: "Expand all", active: false, onClick: () => setAll(false) }), _jsx(FilterChip, { label: "Collapse all", active: false, onClick: () => setAll(true) })] }), _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: 6, maxWidth: 1300 }, children: group.map((r) => (_jsx(EventRow, { row: r, visible: true, expanded: !collapsed.has(r.seq), onToggle: () => toggle(r.seq) }, r.seq))) })] }));
596
+ }
597
+ function ColumnHeaders() {
598
+ return (_jsxs("div", { style: {
599
+ position: 'sticky',
600
+ top: 0,
601
+ zIndex: 10,
602
+ display: 'grid',
603
+ gridTemplateColumns: '3px 1fr 1fr 1fr',
604
+ gap: 8,
605
+ maxWidth: 1300,
606
+ padding: '8px 14px',
607
+ marginBottom: 8,
608
+ backgroundColor: '#0d1117',
609
+ borderBottom: '1px solid #1f2937',
610
+ fontFamily: 'system-ui, sans-serif',
611
+ }, children: [_jsx("span", {}), _jsx(HeaderLabel, { children: "Raw event" }), _jsx(HeaderLabel, { children: "Repo-normalized" }), _jsx(HeaderLabel, { children: "UI event (accumulated)" })] }));
612
+ }
613
+ function HeaderLabel({ children }) {
614
+ return (_jsx("span", { style: {
615
+ fontSize: 11,
616
+ fontWeight: 600,
617
+ textTransform: 'uppercase',
618
+ letterSpacing: 0.5,
619
+ color: '#9ca3af',
620
+ }, children: children }));
621
+ }
622
+ function EventRow({ row, visible, expanded, onToggle, }) {
623
+ const raw = toRaw(row.raw);
624
+ const normalized = toNormalized(row.normalized);
625
+ if (!visible)
626
+ return _jsx(FilteredOutLine, { raw: raw });
627
+ const color = kindColor(eventKind(raw));
628
+ const files = normalized?.files;
629
+ const hasPaths = !!files && files.length > 0;
630
+ return (_jsxs("div", { style: { display: 'grid', gridTemplateColumns: '3px 1fr 1fr 1fr', gap: 8 }, children: [_jsx("div", { title: hasPaths ? `${files.length} normalized path(s)` : 'no paths to normalize', style: {
631
+ backgroundColor: hasPaths ? '#10b981' : '#232c39',
632
+ minHeight: '100%',
633
+ } }), _jsx(RawEventCard, { event: raw, expanded: expanded, onToggle: onToggle }), normalized ? (_jsx(NormalizedEventCard, { event: normalized, seq: row.seq, color: color, expanded: expanded, onToggle: onToggle })) : null, _jsx(AccumulatedEventCard, { event: row.accumulated, seq: row.seq, expanded: expanded, onToggle: onToggle })] }));
634
+ }
635
+ function FilteredOutLine({ raw }) {
636
+ const color = kindColor(eventKind(raw));
637
+ return (_jsx("div", { title: describe(raw), style: {
638
+ height: 2,
639
+ backgroundColor: color,
640
+ opacity: 0.16,
641
+ cursor: 'default',
642
+ } }));
643
+ }
644
+ function FilterChip({ label, active, color, onClick, }) {
645
+ return (_jsx("button", { onClick: onClick, style: {
646
+ padding: '4px 10px',
647
+ borderRadius: 999,
648
+ border: `1px solid ${active ? color ?? '#3b82f6' : '#1f2937'}`,
649
+ backgroundColor: active ? (color ?? '#3b82f6') + '22' : 'transparent',
650
+ color: active ? '#f3f4f6' : '#9ca3af',
651
+ fontSize: 11.5,
652
+ cursor: 'pointer',
653
+ fontFamily: 'inherit',
654
+ }, children: label }));
655
+ }
656
+ //# sourceMappingURL=SessionEventFeed.js.map