@lvce-editor/chat-debug-view 7.3.0 → 7.5.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.
@@ -1128,6 +1128,7 @@ const Text = 12;
1128
1128
  const Th = 13;
1129
1129
  const THead = 14;
1130
1130
  const Tr = 15;
1131
+ const H2 = 22;
1131
1132
  const Section = 41;
1132
1133
  const Search = 42;
1133
1134
  const Label = 66;
@@ -1139,6 +1140,10 @@ const ClientY = 'event.clientY';
1139
1140
  const TargetName = 'event.target.name';
1140
1141
  const TargetValue = 'event.target.value';
1141
1142
 
1143
+ const None$1 = 0;
1144
+ const Checked = 2;
1145
+ const Unchecked = 3;
1146
+
1142
1147
  const ChatStorageWorker = 6003;
1143
1148
  const RendererWorker = 1;
1144
1149
 
@@ -1166,6 +1171,9 @@ const showContextMenu2 = async (uid, menuId, x, y, args) => {
1166
1171
  const sendMessagePortToChatStorageWorker$1 = async port => {
1167
1172
  await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToChatStorageWorker', port, 'HandleMessagePort.handleMessagePort');
1168
1173
  };
1174
+ const writeClipBoardText = async text => {
1175
+ await invoke('ClipBoard.writeText', /* text */text);
1176
+ };
1169
1177
 
1170
1178
  const toCommandId = key => {
1171
1179
  const dotIndex = key.indexOf('.');
@@ -1297,71 +1305,284 @@ const loadSelectedEvent$1 = async (sessionId, eventId, type) => {
1297
1305
  return invoke$1('ChatStorage.loadSelectedEvent', sessionId, eventId, type);
1298
1306
  };
1299
1307
 
1300
- const appendStoredEventForTestDependencies = {
1301
- appendEvent: appendEvent
1302
- };
1303
1308
  const appendStoredEventForTest = async (state, event) => {
1304
- await appendStoredEventForTestDependencies.appendEvent(event);
1309
+ await appendEvent(event);
1305
1310
  return state;
1306
1311
  };
1307
1312
 
1313
+ const emptyObject = {};
1314
+ const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
1315
+ const i18nString = (key, placeholders = emptyObject) => {
1316
+ if (placeholders === emptyObject) {
1317
+ return key;
1318
+ }
1319
+ const replacer = (match, rest) => {
1320
+ return placeholders[rest];
1321
+ };
1322
+ return key.replaceAll(RE_PLACEHOLDER, replacer);
1323
+ };
1324
+
1325
+ const All$1 = 'All';
1326
+ const CloseDetails$1 = 'Close details';
1327
+ const Copy = 'Copy';
1328
+ const DetailSections = 'Detail sections';
1329
+ const Duration$1 = 'Duration';
1330
+ const Ended = 'Ended';
1331
+ const FailedToLoadChatDebugSession = 'Failed to load chat debug session "{PH1}". Please try again.';
1332
+ const FailedToLoadChatDebugSessionWithError = 'Failed to load chat debug session "{PH1}": {PH2}';
1333
+ const FilterEvents = 'Filter events';
1334
+ const FromSeconds = 'from {PH1}s';
1335
+ const InvalidSessionId = 'Invalid session id';
1336
+ const InvalidUriEncoding = 'Invalid URI encoding';
1337
+ const InvalidUriFormat = 'Invalid URI format';
1338
+ const MissingUri = 'Missing URI';
1339
+ const Network$1 = 'Network';
1340
+ const NoChatSessionFound = 'No chat session found for sessionId "{PH1}".';
1341
+ const NoEventsFound = 'No events have been found';
1342
+ const NoEventsFoundMatching = 'No events found matching {PH1}';
1343
+ const NoToolCallEvents = 'No tool call events.';
1344
+ const Payload$1 = 'Payload';
1345
+ const Preview$1 = 'Preview';
1346
+ const Refresh$1 = 'Refresh';
1347
+ const RefreshEvents = 'Refresh events';
1348
+ const ResetColumns = 'Reset columns';
1349
+ const Response$1 = 'Response';
1350
+ const SecondsRange = '{PH1}s-{PH2}s';
1351
+ const Started = 'Started';
1352
+ const Status$1 = 'Status';
1353
+ const Stream$1 = 'Stream';
1354
+ const Timing$1 = 'Timing';
1355
+ const ToSeconds = 'to {PH1}s';
1356
+ const Tools$1 = 'Tools';
1357
+ const Type$1 = 'Type';
1358
+ const Ui$1 = 'UI';
1359
+ const UnableToLoadDebugSessionInvalidUri = 'Unable to load debug session: invalid URI "{PH1}". Expected format: chat-debug://<sessionId>.';
1360
+ const UnableToLoadDebugSessionMissingUri = 'Unable to load debug session: missing URI. Expected format: chat-debug://<sessionId>.';
1361
+ const WindowSummary = 'Window {PH1}-{PH2} of {PH3}';
1362
+
1363
+ const copy = () => {
1364
+ return i18nString(Copy);
1365
+ };
1366
+ const status = () => {
1367
+ return i18nString(Status$1);
1368
+ };
1369
+ const all = () => {
1370
+ return i18nString(All$1);
1371
+ };
1372
+ const closeDetails = () => {
1373
+ return i18nString(CloseDetails$1);
1374
+ };
1375
+ const detailSections = () => {
1376
+ return i18nString(DetailSections);
1377
+ };
1378
+ const duration = () => {
1379
+ return i18nString(Duration$1);
1380
+ };
1381
+ const ended = () => {
1382
+ return i18nString(Ended);
1383
+ };
1384
+ const failedToLoadChatDebugSession = sessionId => {
1385
+ return i18nString(FailedToLoadChatDebugSession, {
1386
+ PH1: sessionId
1387
+ });
1388
+ };
1389
+ const failedToLoadChatDebugSessionWithError = (sessionId, errorMessage) => {
1390
+ return i18nString(FailedToLoadChatDebugSessionWithError, {
1391
+ PH1: sessionId,
1392
+ PH2: errorMessage
1393
+ });
1394
+ };
1395
+ const filterEvents = () => {
1396
+ return i18nString(FilterEvents);
1397
+ };
1398
+ const fromSeconds = seconds => {
1399
+ return i18nString(FromSeconds, {
1400
+ PH1: seconds
1401
+ });
1402
+ };
1403
+ const invalidSessionId = () => {
1404
+ return i18nString(InvalidSessionId);
1405
+ };
1406
+ const invalidUriEncoding = () => {
1407
+ return i18nString(InvalidUriEncoding);
1408
+ };
1409
+ const invalidUriFormat = () => {
1410
+ return i18nString(InvalidUriFormat);
1411
+ };
1412
+ const missingUri = () => {
1413
+ return i18nString(MissingUri);
1414
+ };
1415
+ const network = () => {
1416
+ return i18nString(Network$1);
1417
+ };
1418
+ const noChatSessionFound = sessionId => {
1419
+ return i18nString(NoChatSessionFound, {
1420
+ PH1: sessionId
1421
+ });
1422
+ };
1423
+ const noEventsFound = () => {
1424
+ return i18nString(NoEventsFound);
1425
+ };
1426
+ const noEventsFoundMatching = filterDescription => {
1427
+ return i18nString(NoEventsFoundMatching, {
1428
+ PH1: filterDescription
1429
+ });
1430
+ };
1431
+ const noToolCallEvents = () => {
1432
+ return i18nString(NoToolCallEvents);
1433
+ };
1434
+ const preview = () => {
1435
+ return i18nString(Preview$1);
1436
+ };
1437
+ const payload = () => {
1438
+ return i18nString(Payload$1);
1439
+ };
1440
+ const refresh$1 = () => {
1441
+ return i18nString(Refresh$1);
1442
+ };
1443
+ const refreshEvents$1 = () => {
1444
+ return i18nString(RefreshEvents);
1445
+ };
1446
+ const resetColumns = () => {
1447
+ return i18nString(ResetColumns);
1448
+ };
1449
+ const response = () => {
1450
+ return i18nString(Response$1);
1451
+ };
1452
+ const secondsRange = (start, end) => {
1453
+ return i18nString(SecondsRange, {
1454
+ PH1: start,
1455
+ PH2: end
1456
+ });
1457
+ };
1458
+ const started = () => {
1459
+ return i18nString(Started);
1460
+ };
1461
+ const stream = () => {
1462
+ return i18nString(Stream$1);
1463
+ };
1464
+ const timing = () => {
1465
+ return i18nString(Timing$1);
1466
+ };
1467
+ const toSeconds = seconds => {
1468
+ return i18nString(ToSeconds, {
1469
+ PH1: seconds
1470
+ });
1471
+ };
1472
+ const tools = () => {
1473
+ return i18nString(Tools$1);
1474
+ };
1475
+ const type = () => {
1476
+ return i18nString(Type$1);
1477
+ };
1478
+ const ui = () => {
1479
+ return i18nString(Ui$1);
1480
+ };
1481
+ const unableToLoadDebugSessionInvalidUri = uri => {
1482
+ return i18nString(UnableToLoadDebugSessionInvalidUri, {
1483
+ PH1: uri
1484
+ });
1485
+ };
1486
+ const unableToLoadDebugSessionMissingUri = () => {
1487
+ return i18nString(UnableToLoadDebugSessionMissingUri);
1488
+ };
1489
+ const windowSummary = (start, end, duration) => {
1490
+ return i18nString(WindowSummary, {
1491
+ PH1: start,
1492
+ PH2: end,
1493
+ PH3: duration
1494
+ });
1495
+ };
1496
+
1497
+ const Filter = 'filter';
1498
+ const EventCategoryFilter = 'eventCategoryFilter';
1499
+ const ShowEventStreamFinishedEvents = 'showEventStreamFinishedEvents';
1500
+ const ShowInputEvents = 'showInputEvents';
1501
+ const ShowResponsePartEvents = 'showResponsePartEvents';
1502
+ const UseDevtoolsLayout = 'useDevtoolsLayout';
1503
+ const SelectedEventIndex = 'selectedEventIndex';
1504
+ const CloseDetails = 'closeDetails';
1505
+ const DetailTab = 'detailTab';
1506
+ const TimelineStartSeconds = 'timelineStartSeconds';
1507
+ const TimelineEndSeconds = 'timelineEndSeconds';
1508
+ const TimelineRangePreset = 'timelineRangePreset';
1509
+ const Refresh = 'refresh';
1510
+ const All = 'all';
1511
+ const Tools = 'tools';
1512
+ const Network = 'network';
1513
+ const Ui = 'ui';
1514
+ const Stream = 'stream';
1308
1515
  const Response = 'response';
1309
1516
  const Preview = 'preview';
1517
+ const Payload = 'payload';
1310
1518
  const Timing = 'timing';
1311
- const detailTabs = [Preview, Response, Timing];
1519
+
1520
+ const createDetailTabs = () => {
1521
+ return [{
1522
+ label: preview(),
1523
+ name: Preview
1524
+ }, {
1525
+ label: payload(),
1526
+ name: Payload
1527
+ }, {
1528
+ label: response(),
1529
+ name: Response
1530
+ }, {
1531
+ label: timing(),
1532
+ name: Timing
1533
+ }];
1534
+ };
1312
1535
  const isDetailTab = value => {
1313
- return value === Response || value === Preview || value === Timing;
1536
+ return value === Response || value === Preview || value === Payload || value === Timing;
1537
+ };
1538
+ const hasDetailTab = (detailTabs, value) => {
1539
+ return detailTabs.some(detailTab => detailTab.name === value);
1314
1540
  };
1315
- const getDetailTabLabel = value => {
1316
- if (value === Preview) {
1317
- return 'Preview';
1541
+ const getSelectedDetailTab = (detailTabs, selectedDetailTab) => {
1542
+ if (hasDetailTab(detailTabs, selectedDetailTab)) {
1543
+ return selectedDetailTab;
1318
1544
  }
1319
- if (value === Timing) {
1320
- return 'Timing';
1545
+ const responseTab = detailTabs.find(detailTab => detailTab.name === Response);
1546
+ if (responseTab) {
1547
+ return responseTab.name;
1321
1548
  }
1322
- return 'Response';
1549
+ return detailTabs[0]?.name ?? selectedDetailTab;
1323
1550
  };
1324
1551
 
1325
- const createEventCategoryFilterOptions = () => {
1552
+ const createCategoryFilters = () => {
1326
1553
  return [{
1327
- label: 'All',
1328
- value: All
1554
+ label: all(),
1555
+ name: All
1329
1556
  }, {
1330
- label: 'Tools',
1331
- value: Tools
1557
+ label: tools(),
1558
+ name: Tools
1332
1559
  }, {
1333
- label: 'Network',
1334
- value: Network
1560
+ label: network(),
1561
+ name: Network
1335
1562
  }, {
1336
- label: 'UI',
1337
- value: Ui
1563
+ label: ui(),
1564
+ name: Ui
1338
1565
  }, {
1339
- label: 'Stream',
1340
- value: Stream
1566
+ label: stream(),
1567
+ name: Stream
1341
1568
  }];
1342
1569
  };
1343
1570
 
1344
1571
  const getEventCategoryFilterLabel = eventCategoryFilter => {
1345
1572
  switch (eventCategoryFilter) {
1346
1573
  case Network:
1347
- return 'Network';
1574
+ return network();
1348
1575
  case Stream:
1349
- return 'Stream';
1576
+ return stream();
1350
1577
  case Tools:
1351
- return 'Tools';
1578
+ return tools();
1352
1579
  case Ui:
1353
- return 'UI';
1580
+ return ui();
1354
1581
  default:
1355
- return 'All';
1582
+ return all();
1356
1583
  }
1357
1584
  };
1358
1585
 
1359
- const All = 'all';
1360
- const Tools = 'tools';
1361
- const Network = 'network';
1362
- const Ui = 'ui';
1363
- const Stream = 'stream';
1364
-
1365
1586
  const RE_SPACE = /\s+/;
1366
1587
  const tokenToEventCategoryFilter = new Map([['@tools', Tools], ['@network', Network], ['@ui', Ui], ['@stream', Stream]]);
1367
1588
  const parseFilterValue = filterValue => {
@@ -1381,42 +1602,27 @@ const parseFilterValue = filterValue => {
1381
1602
  };
1382
1603
  };
1383
1604
 
1384
- const validEventCategoryFilters = new Set([All, Network, Stream, Tools, Ui]);
1385
- const isSavedState = value => {
1386
- return typeof value === 'object' && value !== null;
1605
+ const Type = 'type';
1606
+ const Duration = 'duration';
1607
+ const Status = 'status';
1608
+ const tableColumns = [Type, Duration, Status];
1609
+ const defaultVisibleTableColumns = tableColumns;
1610
+ const isTableColumn = value => {
1611
+ return tableColumns.includes(value);
1387
1612
  };
1388
- const getRestoredEventCategoryFilter = (savedState, currentEventCategoryFilter) => {
1389
- if (typeof savedState.eventCategoryFilter === 'string' && validEventCategoryFilters.has(savedState.eventCategoryFilter)) {
1390
- return savedState.eventCategoryFilter;
1391
- }
1392
- if (typeof savedState.filterValue === 'string') {
1393
- return parseFilterValue(savedState.filterValue).eventCategoryFilter;
1394
- }
1395
- return currentEventCategoryFilter;
1613
+ const getOrderedVisibleTableColumns = values => {
1614
+ const visibleColumns = new Set(values.filter(isTableColumn));
1615
+ return tableColumns.filter(column => visibleColumns.has(column));
1396
1616
  };
1397
- const restoreSavedState = (state, savedState) => {
1398
- if (!isSavedState(savedState)) {
1399
- return state;
1400
- }
1401
- return {
1402
- ...state,
1403
- eventCategoryFilter: getRestoredEventCategoryFilter(savedState, state.eventCategoryFilter),
1404
- filterValue: typeof savedState.filterValue === 'string' ? savedState.filterValue : state.filterValue,
1405
- selectedDetailTab: typeof savedState.selectedDetailTab === 'string' && isDetailTab(savedState.selectedDetailTab) ? savedState.selectedDetailTab : state.selectedDetailTab,
1406
- selectedEventId: typeof savedState.selectedEventId === 'number' || savedState.selectedEventId === null ? savedState.selectedEventId : state.selectedEventId,
1407
- timelineEndSeconds: typeof savedState.timelineEndSeconds === 'string' ? savedState.timelineEndSeconds : state.timelineEndSeconds,
1408
- timelineStartSeconds: typeof savedState.timelineStartSeconds === 'string' ? savedState.timelineStartSeconds : state.timelineStartSeconds
1409
- };
1617
+ const isVisibleTableColumn = (visibleTableColumns, column) => {
1618
+ return visibleTableColumns.includes(column);
1410
1619
  };
1411
1620
 
1412
- const {
1413
- get,
1414
- getCommandIds,
1415
- registerCommands,
1416
- set,
1417
- wrapCommand,
1418
- wrapGetter
1419
- } = create$1();
1621
+ const defaultTableColumnWidths = {
1622
+ duration: 110,
1623
+ status: 110,
1624
+ type: 260
1625
+ };
1420
1626
 
1421
1627
  const defaultTableWidth = 480;
1422
1628
  const minTableWidth = 240;
@@ -1445,14 +1651,156 @@ const getTableWidthFromClientX = (viewX, width, clientX) => {
1445
1651
  return clampTableWidth(width, nextTableWidth);
1446
1652
  };
1447
1653
 
1654
+ const minimumTableColumnWidth = 80;
1655
+
1656
+ const getTableColumnLayout = (tableWidth, visibleTableColumns, tableColumnWidths) => {
1657
+ const visibleColumns = getOrderedVisibleTableColumns(visibleTableColumns);
1658
+ if (visibleColumns.length === 0) {
1659
+ return {
1660
+ fixedColumns: [],
1661
+ resizerLefts: [],
1662
+ visibleColumns,
1663
+ visibleColumnWidths: []
1664
+ };
1665
+ }
1666
+ const visibleColumnWidths = [];
1667
+ let remainingWidth = tableWidth;
1668
+ let remainingColumnCount = visibleColumns.length;
1669
+ for (let index = 0; index < visibleColumns.length; index++) {
1670
+ const column = visibleColumns[index];
1671
+ if (index === visibleColumns.length - 1) {
1672
+ visibleColumnWidths.push(Math.max(0, remainingWidth));
1673
+ continue;
1674
+ }
1675
+ const maxWidth = Math.max(minimumTableColumnWidth, remainingWidth - minimumTableColumnWidth * (remainingColumnCount - 1));
1676
+ const preferredWidth = tableColumnWidths[column];
1677
+ const clampedWidth = Math.max(minimumTableColumnWidth, Math.min(preferredWidth, maxWidth));
1678
+ visibleColumnWidths.push(clampedWidth);
1679
+ remainingWidth -= clampedWidth;
1680
+ remainingColumnCount -= 1;
1681
+ }
1682
+ const resizerLefts = [];
1683
+ let cumulativeWidth = 0;
1684
+ for (let index = 0; index < visibleColumnWidths.length - 1; index++) {
1685
+ cumulativeWidth += visibleColumnWidths[index];
1686
+ resizerLefts.push(cumulativeWidth);
1687
+ }
1688
+ return {
1689
+ fixedColumns: visibleColumns.slice(0, -1),
1690
+ resizerLefts,
1691
+ visibleColumns,
1692
+ visibleColumnWidths
1693
+ };
1694
+ };
1695
+
1696
+ const getResizedTableColumnWidths = (width, tableWidth, visibleTableColumns, tableColumnWidths, viewX, clientX, resizerDownId) => {
1697
+ const clampedTableWidth = clampTableWidth(width, tableWidth);
1698
+ const layout = getTableColumnLayout(clampedTableWidth, visibleTableColumns, tableColumnWidths);
1699
+ if (resizerDownId < 1 || resizerDownId >= layout.visibleColumns.length) {
1700
+ return tableColumnWidths;
1701
+ }
1702
+ const boundaryIndex = resizerDownId - 1;
1703
+ const precedingWidth = layout.visibleColumnWidths.slice(0, boundaryIndex).reduce((total, current) => total + current, 0);
1704
+ const remainingVisibleColumnCount = layout.visibleColumns.length - boundaryIndex - 1;
1705
+ const maxWidth = Math.max(minimumTableColumnWidth, clampedTableWidth - precedingWidth - minimumTableColumnWidth * remainingVisibleColumnCount);
1706
+ const nextWidth = clientX - viewX - leftPadding - precedingWidth;
1707
+ const clampedWidth = Math.max(minimumTableColumnWidth, Math.min(nextWidth, maxWidth));
1708
+ const resizedColumn = layout.visibleColumns[boundaryIndex];
1709
+ return {
1710
+ ...tableColumnWidths,
1711
+ [resizedColumn]: clampedWidth
1712
+ };
1713
+ };
1714
+
1715
+ const isSameTableColumnWidths = (first, second) => {
1716
+ return first.type === second.type && first.duration === second.duration && first.status === second.status;
1717
+ };
1718
+
1719
+ const isFiniteNumber = value => {
1720
+ return typeof value === 'number' && Number.isFinite(value);
1721
+ };
1722
+
1723
+ const isTableColumnWidths = value => {
1724
+ if (typeof value !== 'object' || value === null) {
1725
+ return false;
1726
+ }
1727
+ const record = value;
1728
+ return isFiniteNumber(record.type) && isFiniteNumber(record.duration) && isFiniteNumber(record.status);
1729
+ };
1730
+
1731
+ const validEventCategoryFilters = new Set([All, Network, Stream, Tools, Ui]);
1732
+ const isSavedState = value => {
1733
+ return typeof value === 'object' && value !== null;
1734
+ };
1735
+ const restoreEventCategoryFilter = (savedState, currentEventCategoryFilter) => {
1736
+ if (typeof savedState.eventCategoryFilter === 'string' && validEventCategoryFilters.has(savedState.eventCategoryFilter)) {
1737
+ return savedState.eventCategoryFilter;
1738
+ }
1739
+ if (typeof savedState.filterValue === 'string') {
1740
+ return parseFilterValue(savedState.filterValue).eventCategoryFilter;
1741
+ }
1742
+ return currentEventCategoryFilter;
1743
+ };
1744
+ const restoreFilterValue = (savedState, currentFilterValue) => {
1745
+ return typeof savedState.filterValue === 'string' ? savedState.filterValue : currentFilterValue;
1746
+ };
1747
+ const restoreSelectedDetailTab = (savedState, currentSelectedDetailTab) => {
1748
+ return typeof savedState.selectedDetailTab === 'string' && isDetailTab(savedState.selectedDetailTab) ? savedState.selectedDetailTab : currentSelectedDetailTab;
1749
+ };
1750
+ const restoreSelectedEventId = (savedState, currentSelectedEventId) => {
1751
+ return typeof savedState.selectedEventId === 'number' || savedState.selectedEventId === null ? savedState.selectedEventId : currentSelectedEventId;
1752
+ };
1753
+ const restoreTimelineEndSeconds = (savedState, currentTimelineEndSeconds) => {
1754
+ return typeof savedState.timelineEndSeconds === 'string' ? savedState.timelineEndSeconds : currentTimelineEndSeconds;
1755
+ };
1756
+ const restoreTimelineStartSeconds = (savedState, currentTimelineStartSeconds) => {
1757
+ return typeof savedState.timelineStartSeconds === 'string' ? savedState.timelineStartSeconds : currentTimelineStartSeconds;
1758
+ };
1759
+ const restoreVisibleTableColumns = (savedState, currentVisibleTableColumns) => {
1760
+ if (!Array.isArray(savedState.visibleTableColumns)) {
1761
+ return currentVisibleTableColumns;
1762
+ }
1763
+ const visibleTableColumns = savedState.visibleTableColumns.filter(value => typeof value === 'string');
1764
+ return getOrderedVisibleTableColumns(visibleTableColumns);
1765
+ };
1766
+ const restoreTableColumnWidths = (savedState, currentTableColumnWidths) => {
1767
+ return isTableColumnWidths(savedState.tableColumnWidths) ? savedState.tableColumnWidths : currentTableColumnWidths;
1768
+ };
1769
+ const restoreSavedState = (state, savedState) => {
1770
+ if (!isSavedState(savedState)) {
1771
+ return state;
1772
+ }
1773
+ return {
1774
+ ...state,
1775
+ eventCategoryFilter: restoreEventCategoryFilter(savedState, state.eventCategoryFilter),
1776
+ filterValue: restoreFilterValue(savedState, state.filterValue),
1777
+ selectedDetailTab: restoreSelectedDetailTab(savedState, state.selectedDetailTab),
1778
+ selectedEventId: restoreSelectedEventId(savedState, state.selectedEventId),
1779
+ tableColumnWidths: restoreTableColumnWidths(savedState, state.tableColumnWidths),
1780
+ timelineEndSeconds: restoreTimelineEndSeconds(savedState, state.timelineEndSeconds),
1781
+ timelineStartSeconds: restoreTimelineStartSeconds(savedState, state.timelineStartSeconds),
1782
+ visibleTableColumns: restoreVisibleTableColumns(savedState, state.visibleTableColumns)
1783
+ };
1784
+ };
1785
+
1786
+ const {
1787
+ get,
1788
+ getCommandIds,
1789
+ registerCommands,
1790
+ set,
1791
+ wrapCommand,
1792
+ wrapGetter
1793
+ } = create$1();
1794
+
1448
1795
  const createDefaultState = () => {
1449
1796
  return {
1450
1797
  assetDir: '',
1798
+ categoryFilters: [],
1451
1799
  databaseName: 'lvce-chat-view-sessions',
1452
1800
  dataBaseVersion: 2,
1801
+ detailTabs: [],
1453
1802
  errorMessage: '',
1454
1803
  eventCategoryFilter: All,
1455
- eventCategoryFilterOptions: createEventCategoryFilterOptions(),
1456
1804
  events: [],
1457
1805
  eventStoreName: 'chat-view-events',
1458
1806
  filterValue: '',
@@ -1468,6 +1816,8 @@ const createDefaultState = () => {
1468
1816
  showEventStreamFinishedEvents: false,
1469
1817
  showInputEvents: false,
1470
1818
  showResponsePartEvents: false,
1819
+ tableColumnWidths: defaultTableColumnWidths,
1820
+ tableResizerDownId: 0,
1471
1821
  tableWidth: defaultTableWidth,
1472
1822
  timelineEndSeconds: '',
1473
1823
  timelineSelectionActive: false,
@@ -1477,6 +1827,7 @@ const createDefaultState = () => {
1477
1827
  uid: 0,
1478
1828
  uri: '',
1479
1829
  useDevtoolsLayout: true,
1830
+ visibleTableColumns: defaultVisibleTableColumns,
1480
1831
  width: 0,
1481
1832
  x: 0,
1482
1833
  y: 0
@@ -1510,7 +1861,7 @@ const RenderCss = 2;
1510
1861
  const RenderIncremental = 3;
1511
1862
 
1512
1863
  const diff = (oldState, newState) => {
1513
- if (oldState.errorMessage !== newState.errorMessage || oldState.eventCategoryFilter !== newState.eventCategoryFilter || oldState.events !== newState.events || oldState.filterValue !== newState.filterValue || oldState.sessionId !== newState.sessionId || oldState.showEventStreamFinishedEvents !== newState.showEventStreamFinishedEvents || oldState.showInputEvents !== newState.showInputEvents || oldState.showResponsePartEvents !== newState.showResponsePartEvents || oldState.tableWidth !== newState.tableWidth || oldState.timelineEndSeconds !== newState.timelineEndSeconds || oldState.timelineSelectionActive !== newState.timelineSelectionActive || oldState.timelineSelectionAnchorSeconds !== newState.timelineSelectionAnchorSeconds || oldState.timelineSelectionFocusSeconds !== newState.timelineSelectionFocusSeconds || oldState.timelineStartSeconds !== newState.timelineStartSeconds || oldState.useDevtoolsLayout !== newState.useDevtoolsLayout || oldState.selectedDetailTab !== newState.selectedDetailTab || oldState.selectedEvent !== newState.selectedEvent || oldState.selectedEventIndex !== newState.selectedEventIndex || oldState.width !== newState.width || oldState.uid !== newState.uid) {
1864
+ if (oldState.categoryFilters !== newState.categoryFilters || oldState.detailTabs !== newState.detailTabs || oldState.errorMessage !== newState.errorMessage || oldState.eventCategoryFilter !== newState.eventCategoryFilter || oldState.events !== newState.events || oldState.filterValue !== newState.filterValue || oldState.sessionId !== newState.sessionId || oldState.showEventStreamFinishedEvents !== newState.showEventStreamFinishedEvents || oldState.showInputEvents !== newState.showInputEvents || oldState.showResponsePartEvents !== newState.showResponsePartEvents || oldState.tableColumnWidths !== newState.tableColumnWidths || oldState.tableWidth !== newState.tableWidth || oldState.timelineEndSeconds !== newState.timelineEndSeconds || oldState.timelineSelectionActive !== newState.timelineSelectionActive || oldState.timelineSelectionAnchorSeconds !== newState.timelineSelectionAnchorSeconds || oldState.timelineSelectionFocusSeconds !== newState.timelineSelectionFocusSeconds || oldState.timelineStartSeconds !== newState.timelineStartSeconds || oldState.useDevtoolsLayout !== newState.useDevtoolsLayout || oldState.visibleTableColumns !== newState.visibleTableColumns || oldState.selectedDetailTab !== newState.selectedDetailTab || oldState.selectedEvent !== newState.selectedEvent || oldState.selectedEventIndex !== newState.selectedEventIndex || oldState.width !== newState.width || oldState.uid !== newState.uid) {
1514
1865
  return [RenderIncremental, RenderCss];
1515
1866
  }
1516
1867
  return [];
@@ -1524,6 +1875,102 @@ const diff2 = uid => {
1524
1875
  return diff(oldState, newState);
1525
1876
  };
1526
1877
 
1878
+ const getColumnVisibilityFlags = (state, column) => {
1879
+ return isVisibleTableColumn(state.visibleTableColumns, column) ? Checked : Unchecked;
1880
+ };
1881
+
1882
+ const MenuChatDebugTableHeader = 2189;
1883
+ const handleHeaderContextMenu = async (state, eventX, eventY) => {
1884
+ await showContextMenu2(state.uid, MenuChatDebugTableHeader, eventX, eventY, {
1885
+ menuId: MenuChatDebugTableHeader
1886
+ });
1887
+ return state;
1888
+ };
1889
+
1890
+ const toTimeNumber = value => {
1891
+ if (typeof value === 'number' && Number.isFinite(value)) {
1892
+ return value;
1893
+ }
1894
+ if (typeof value === 'string') {
1895
+ const timestamp = Date.parse(value);
1896
+ if (!Number.isNaN(timestamp)) {
1897
+ return timestamp;
1898
+ }
1899
+ }
1900
+ return undefined;
1901
+ };
1902
+
1903
+ const getEventTime = event => {
1904
+ return toTimeNumber(event.started ?? event.startTime ?? event.startTimestamp ?? event.timestamp);
1905
+ };
1906
+
1907
+ const getEventsWithTime = events => {
1908
+ return events.flatMap(event => {
1909
+ const time = getEventTime(event);
1910
+ if (time === undefined) {
1911
+ return [];
1912
+ }
1913
+ return [{
1914
+ event,
1915
+ time
1916
+ }];
1917
+ });
1918
+ };
1919
+
1920
+ const parseTimelineSeconds = value => {
1921
+ const trimmed = value.trim();
1922
+ if (!trimmed) {
1923
+ return undefined;
1924
+ }
1925
+ const parsed = Number.parseFloat(trimmed);
1926
+ if (!Number.isFinite(parsed) || parsed < 0) {
1927
+ return undefined;
1928
+ }
1929
+ return parsed;
1930
+ };
1931
+
1932
+ const roundSeconds = value => {
1933
+ return Number(value.toFixed(3));
1934
+ };
1935
+
1936
+ const getNormalizedRange = (durationSeconds, startValue, endValue) => {
1937
+ const parsedStart = parseTimelineSeconds(startValue);
1938
+ const parsedEnd = parseTimelineSeconds(endValue);
1939
+ if (parsedStart === undefined && parsedEnd === undefined) {
1940
+ return {
1941
+ endSeconds: null,
1942
+ hasSelection: false,
1943
+ startSeconds: null
1944
+ };
1945
+ }
1946
+ const rawStart = parsedStart ?? 0;
1947
+ const rawEnd = parsedEnd ?? durationSeconds;
1948
+ const normalizedStart = Math.max(0, Math.min(durationSeconds, Math.min(rawStart, rawEnd)));
1949
+ const normalizedEnd = Math.max(0, Math.min(durationSeconds, Math.max(rawStart, rawEnd)));
1950
+ return {
1951
+ endSeconds: roundSeconds(normalizedEnd),
1952
+ hasSelection: true,
1953
+ startSeconds: roundSeconds(normalizedStart)
1954
+ };
1955
+ };
1956
+
1957
+ const filterEventsByTimelineRange = (events, startValue, endValue) => {
1958
+ const eventsWithTime = getEventsWithTime(events);
1959
+ if (eventsWithTime.length === 0) {
1960
+ return events;
1961
+ }
1962
+ const baseTime = eventsWithTime[0].time;
1963
+ const lastTime = eventsWithTime.at(-1)?.time ?? baseTime;
1964
+ const durationSeconds = roundSeconds(Math.max(0, lastTime - baseTime) / 1000);
1965
+ const range = getNormalizedRange(durationSeconds, startValue, endValue);
1966
+ if (!range.hasSelection || range.startSeconds === null || range.endSeconds === null) {
1967
+ return events;
1968
+ }
1969
+ const startTime = baseTime + range.startSeconds * 1000;
1970
+ const endTime = baseTime + range.endSeconds * 1000;
1971
+ return eventsWithTime.filter(item => item.time >= startTime && item.time <= endTime).map(item => item.event);
1972
+ };
1973
+
1527
1974
  const hasMatchingToolName = (startedEvent, finishedEvent) => {
1528
1975
  if (typeof startedEvent.toolName === 'string' && typeof finishedEvent.toolName === 'string') {
1529
1976
  return startedEvent.toolName === finishedEvent.toolName;
@@ -1666,162 +2113,18 @@ const getFilteredEvents = (events, filterValue, eventCategoryFilter, showInputEv
1666
2113
  return filteredByCategory.filter(event => JSON.stringify(event).toLowerCase().includes(filterText));
1667
2114
  };
1668
2115
 
1669
- const toTimeNumber = value => {
1670
- if (typeof value === 'number' && Number.isFinite(value)) {
1671
- return value;
1672
- }
1673
- if (typeof value === 'string') {
1674
- const timestamp = Date.parse(value);
1675
- if (!Number.isNaN(timestamp)) {
1676
- return timestamp;
1677
- }
1678
- }
1679
- return undefined;
1680
- };
1681
-
1682
- const getEventTime = event => {
1683
- return toTimeNumber(event.started ?? event.startTime ?? event.startTimestamp ?? event.timestamp);
2116
+ const loadSelectedEvent = async (_databaseName, _dataBaseVersion, _eventStoreName, sessionId, _sessionIdIndexName, eventId, type) => {
2117
+ return loadSelectedEvent$1(sessionId, eventId, type);
1684
2118
  };
1685
2119
 
1686
- const maxBarUnits = 8;
1687
- const parseTimelineSeconds = value => {
1688
- const trimmed = value.trim();
1689
- if (!trimmed) {
1690
- return undefined;
1691
- }
1692
- const parsed = Number.parseFloat(trimmed);
1693
- if (!Number.isFinite(parsed) || parsed < 0) {
1694
- return undefined;
1695
- }
1696
- return parsed;
1697
- };
1698
- const roundSeconds = value => {
1699
- return Number(value.toFixed(3));
1700
- };
1701
- const getEventsWithTime = events => {
1702
- return events.flatMap(event => {
1703
- const time = getEventTime(event);
1704
- if (time === undefined) {
1705
- return [];
1706
- }
1707
- return [{
1708
- event,
1709
- time
1710
- }];
1711
- });
1712
- };
1713
- const getTimelineDurationSeconds = events => {
1714
- const eventsWithTime = getEventsWithTime(events);
1715
- if (eventsWithTime.length === 0) {
1716
- return 0;
1717
- }
1718
- const baseTime = eventsWithTime[0].time;
1719
- const lastTime = eventsWithTime.at(-1)?.time ?? baseTime;
1720
- return roundSeconds(Math.max(0, lastTime - baseTime) / 1000);
1721
- };
1722
- const getSelectionPercent = (value, durationSeconds) => {
1723
- if (durationSeconds <= 0) {
1724
- return 0;
1725
- }
1726
- return Number((value / durationSeconds * 100).toFixed(3));
1727
- };
1728
- const getNormalizedRange = (durationSeconds, startValue, endValue) => {
1729
- const parsedStart = parseTimelineSeconds(startValue);
1730
- const parsedEnd = parseTimelineSeconds(endValue);
1731
- if (parsedStart === undefined && parsedEnd === undefined) {
1732
- return {
1733
- endSeconds: null,
1734
- hasSelection: false,
1735
- startSeconds: null
1736
- };
1737
- }
1738
- const rawStart = parsedStart ?? 0;
1739
- const rawEnd = parsedEnd ?? durationSeconds;
1740
- const normalizedStart = Math.max(0, Math.min(durationSeconds, Math.min(rawStart, rawEnd)));
1741
- const normalizedEnd = Math.max(0, Math.min(durationSeconds, Math.max(rawStart, rawEnd)));
1742
- return {
1743
- endSeconds: roundSeconds(normalizedEnd),
1744
- hasSelection: true,
1745
- startSeconds: roundSeconds(normalizedStart)
1746
- };
1747
- };
1748
- const filterEventsByTimelineRange = (events, startValue, endValue) => {
1749
- const eventsWithTime = getEventsWithTime(events);
1750
- if (eventsWithTime.length === 0) {
1751
- return events;
1752
- }
1753
- const baseTime = eventsWithTime[0].time;
1754
- const lastTime = eventsWithTime.at(-1)?.time ?? baseTime;
1755
- const durationSeconds = roundSeconds(Math.max(0, lastTime - baseTime) / 1000);
1756
- const range = getNormalizedRange(durationSeconds, startValue, endValue);
1757
- if (!range.hasSelection || range.startSeconds === null || range.endSeconds === null) {
1758
- return events;
1759
- }
1760
- const startTime = baseTime + range.startSeconds * 1000;
1761
- const endTime = baseTime + range.endSeconds * 1000;
1762
- return eventsWithTime.filter(item => item.time >= startTime && item.time <= endTime).map(item => item.event);
1763
- };
1764
- const getTimelineInfo = (events, startValue, endValue) => {
1765
- const eventsWithTime = getEventsWithTime(events);
1766
- if (eventsWithTime.length === 0) {
1767
- return {
1768
- buckets: [],
1769
- durationSeconds: 0,
1770
- endSeconds: null,
1771
- hasSelection: false,
1772
- selectionEndPercent: null,
1773
- selectionStartPercent: null,
1774
- startSeconds: null
1775
- };
1776
- }
1777
- const baseTime = eventsWithTime[0].time;
1778
- const lastTime = eventsWithTime.at(-1)?.time ?? baseTime;
1779
- const durationMs = Math.max(0, lastTime - baseTime);
1780
- const durationSeconds = roundSeconds(durationMs / 1000);
1781
- const range = getNormalizedRange(durationSeconds, startValue, endValue);
1782
- const bucketCount = durationSeconds === 0 ? 1 : Math.max(12, Math.min(48, Math.ceil(durationSeconds)));
1783
- const bucketDurationMs = durationMs === 0 ? 1000 : durationMs / bucketCount;
1784
- const counts = Array.from({
1785
- length: bucketCount
1786
- }).fill(0);
1787
- for (const item of eventsWithTime) {
1788
- const offsetMs = item.time - baseTime;
1789
- const index = durationMs === 0 ? 0 : Math.min(bucketCount - 1, Math.floor(offsetMs / durationMs * bucketCount));
1790
- counts[index] += 1;
1791
- }
1792
- const maxCount = Math.max(...counts);
1793
- const selectionStartPercent = range.hasSelection && range.startSeconds !== null ? getSelectionPercent(range.startSeconds, durationSeconds) : null;
1794
- const selectionEndPercent = range.hasSelection && range.endSeconds !== null ? getSelectionPercent(range.endSeconds, durationSeconds) : null;
1795
- const buckets = counts.map((count, index) => {
1796
- const bucketStartMs = index * bucketDurationMs;
1797
- const bucketEndMs = index === bucketCount - 1 ? durationMs : (index + 1) * bucketDurationMs;
1798
- const hasSelection = range.hasSelection && range.startSeconds !== null && range.endSeconds !== null;
1799
- const selectionStartMs = hasSelection ? range.startSeconds * 1000 : 0;
1800
- const selectionEndMs = hasSelection ? range.endSeconds * 1000 : 0;
1801
- return {
1802
- count,
1803
- endSeconds: roundSeconds(bucketEndMs / 1000),
1804
- isSelected: hasSelection && bucketEndMs >= selectionStartMs && bucketStartMs <= selectionEndMs,
1805
- startSeconds: roundSeconds(bucketStartMs / 1000),
1806
- unitCount: count === 0 ? 0 : Math.max(1, Math.round(count / maxCount * maxBarUnits))
1807
- };
1808
- });
1809
- return {
1810
- buckets,
1811
- durationSeconds,
1812
- endSeconds: range.endSeconds,
1813
- hasSelection: range.hasSelection,
1814
- selectionEndPercent,
1815
- selectionStartPercent,
1816
- startSeconds: range.startSeconds
1817
- };
2120
+ const selectEventAtIndexDependencies = {
2121
+ loadSelectedEvent: loadSelectedEvent
1818
2122
  };
1819
-
1820
2123
  const getCurrentEvents$3 = state => {
1821
2124
  const filteredEvents = getFilteredEvents(state.events, state.filterValue, state.eventCategoryFilter, state.showInputEvents, state.showResponsePartEvents, state.showEventStreamFinishedEvents);
1822
2125
  return filterEventsByTimelineRange(filteredEvents, state.timelineStartSeconds, state.timelineEndSeconds);
1823
2126
  };
1824
- const selectEventAtIndex = async (state, selectedEventIndex, dependencies) => {
2127
+ const selectEventAtIndex = async (state, selectedEventIndex, dependencies = selectEventAtIndexDependencies) => {
1825
2128
  const currentEvents = getCurrentEvents$3(state);
1826
2129
  const selectedEvent = currentEvents[selectedEventIndex];
1827
2130
  if (!selectedEvent) {
@@ -1891,54 +2194,53 @@ const handleTableBodyContextMenu = async (state, eventX, eventY) => {
1891
2194
  return state;
1892
2195
  };
1893
2196
 
1894
- const getMenuIds = () => {
1895
- return [MenuChatDebugTableBody, 556, 557];
1896
- };
1897
-
1898
- const getErrorMessage = error => {
1899
- if (error instanceof Error) {
1900
- return error.message;
1901
- }
1902
- if (typeof error === 'string') {
1903
- return error;
1904
- }
1905
- if (error && typeof error === 'object' && 'message' in error && typeof error.message === 'string') {
1906
- return error.message;
1907
- }
1908
- return undefined;
1909
- };
1910
- const getFailedToLoadMessage = (sessionId, error) => {
1911
- const errorMessage = getErrorMessage(error);
1912
- if (errorMessage) {
1913
- return `Failed to load chat debug session "${sessionId}": ${errorMessage}`;
2197
+ const getMenuEntries2 = (state, props) => {
2198
+ if (props.menuId === MenuChatDebugTableHeader) {
2199
+ return [{
2200
+ args: [Type],
2201
+ command: 'ChatDebug.toggleTableColumnVisibility',
2202
+ flags: getColumnVisibilityFlags(state, Type),
2203
+ id: 'type',
2204
+ label: type()
2205
+ }, {
2206
+ args: [Duration],
2207
+ command: 'ChatDebug.toggleTableColumnVisibility',
2208
+ flags: getColumnVisibilityFlags(state, Duration),
2209
+ id: 'duration',
2210
+ label: duration()
2211
+ }, {
2212
+ args: [Status],
2213
+ command: 'ChatDebug.toggleTableColumnVisibility',
2214
+ flags: getColumnVisibilityFlags(state, Status),
2215
+ id: 'status',
2216
+ label: status()
2217
+ }, {
2218
+ args: [],
2219
+ command: 'ChatDebug.resetTableColumns',
2220
+ flags: None$1,
2221
+ id: 'reset-columns',
2222
+ label: resetColumns()
2223
+ }];
1914
2224
  }
1915
- return `Failed to load chat debug session "${sessionId}". Please try again.`;
1916
- };
1917
-
1918
- const ParseChatDebugUriErrorCode = {
1919
- InvalidSessionId: 'invalid-session-id',
1920
- InvalidUriEncoding: 'invalid-uri-encoding',
1921
- InvalidUriFormat: 'invalid-uri-format',
1922
- MissingUri: 'missing-uri'
1923
- };
1924
-
1925
- const getInvalidUriMessage = (uri, code) => {
1926
- if (code === ParseChatDebugUriErrorCode.MissingUri) {
1927
- return 'Unable to load debug session: missing URI. Expected format: chat-debug://<sessionId>.';
2225
+ if (props.menuId === MenuChatDebugTableBody) {
2226
+ return [{
2227
+ args: [props.eventIndex],
2228
+ command: 'ChatDebug.handleTableRowCopy',
2229
+ flags: None$1,
2230
+ id: 'copy',
2231
+ label: copy()
2232
+ }];
1928
2233
  }
1929
- return `Unable to load debug session: invalid URI "${uri}". Expected format: chat-debug://<sessionId>.`;
2234
+ return [];
1930
2235
  };
1931
2236
 
1932
- const getSessionNotFoundMessage = sessionId => {
1933
- return `No chat session found for sessionId "${sessionId}".`;
2237
+ const getMenuIds = () => {
2238
+ return [MenuChatDebugTableHeader, MenuChatDebugTableBody, 556, 557];
1934
2239
  };
1935
2240
 
1936
- const listChatViewEventsDependencies = {
1937
- listChatViewEventsFromWorker: listChatViewEvents$1
1938
- };
1939
2241
  const listChatViewEvents = async (sessionId, _databaseName, _dataBaseVersion, _eventStoreName, _sessionIdIndexName) => {
1940
2242
  try {
1941
- return await listChatViewEventsDependencies.listChatViewEventsFromWorker(sessionId);
2243
+ return await listChatViewEvents$1(sessionId);
1942
2244
  } catch (error) {
1943
2245
  return {
1944
2246
  error,
@@ -1947,11 +2249,21 @@ const listChatViewEvents = async (sessionId, _databaseName, _dataBaseVersion, _e
1947
2249
  }
1948
2250
  };
1949
2251
 
1950
- const loadSelectedEventDependencies = {
1951
- loadSelectedEventFromWorker: loadSelectedEvent$1
1952
- };
1953
- const loadSelectedEvent = async (_databaseName, _dataBaseVersion, _eventStoreName, sessionId, _sessionIdIndexName, eventId, type) => {
1954
- return loadSelectedEventDependencies.loadSelectedEventFromWorker(sessionId, eventId, type);
2252
+ const loadEventsDependencies = {
2253
+ listChatViewEvents: listChatViewEvents,
2254
+ loadSelectedEvent: loadSelectedEvent
2255
+ };
2256
+
2257
+ const ParseChatDebugUriErrorCode = {
2258
+ InvalidSessionId: 'invalid-session-id',
2259
+ InvalidUriEncoding: 'invalid-uri-encoding',
2260
+ InvalidUriFormat: 'invalid-uri-format',
2261
+ MissingUri: 'missing-uri'
2262
+ };
2263
+
2264
+ const ParseChatDebugUriResultType = {
2265
+ Error: 2,
2266
+ Success: 1
1955
2267
  };
1956
2268
 
1957
2269
  const chatDebugUriPattern = /^chat-debug:\/\/([^/?#]+)$/;
@@ -1960,16 +2272,16 @@ const parseChatDebugUri = uri => {
1960
2272
  if (!uri) {
1961
2273
  return {
1962
2274
  code: ParseChatDebugUriErrorCode.MissingUri,
1963
- message: 'Missing URI',
1964
- type: 'error'
2275
+ message: missingUri(),
2276
+ type: ParseChatDebugUriResultType.Error
1965
2277
  };
1966
2278
  }
1967
2279
  const match = uri.match(chatDebugUriPattern);
1968
2280
  if (!match) {
1969
2281
  return {
1970
2282
  code: ParseChatDebugUriErrorCode.InvalidUriFormat,
1971
- message: 'Invalid URI format',
1972
- type: 'error'
2283
+ message: invalidUriFormat(),
2284
+ type: ParseChatDebugUriResultType.Error
1973
2285
  };
1974
2286
  }
1975
2287
  const encodedSessionId = match[1];
@@ -1979,31 +2291,84 @@ const parseChatDebugUri = uri => {
1979
2291
  } catch {
1980
2292
  return {
1981
2293
  code: ParseChatDebugUriErrorCode.InvalidUriEncoding,
1982
- message: 'Invalid URI encoding',
1983
- type: 'error'
2294
+ message: invalidUriEncoding(),
2295
+ type: ParseChatDebugUriResultType.Error
1984
2296
  };
1985
2297
  }
1986
2298
  if (!sessionId || invalidSessionIdPattern.test(sessionId)) {
1987
2299
  return {
1988
2300
  code: ParseChatDebugUriErrorCode.InvalidSessionId,
1989
- message: 'Invalid session id',
1990
- type: 'error'
2301
+ message: invalidSessionId(),
2302
+ type: ParseChatDebugUriResultType.Error
1991
2303
  };
1992
2304
  }
1993
2305
  return {
1994
2306
  sessionId,
1995
- type: 'success'
2307
+ type: ParseChatDebugUriResultType.Success
1996
2308
  };
1997
2309
  };
1998
2310
 
1999
- const loadEventsDependencies = {
2000
- listChatViewEvents: listChatViewEvents,
2001
- loadSelectedEvent: loadSelectedEvent
2311
+ const getSessionIdFromUri = state => {
2312
+ const parsed = parseChatDebugUri(state.uri);
2313
+ if (parsed.type === ParseChatDebugUriResultType.Error) {
2314
+ return undefined;
2315
+ }
2316
+ return parsed.sessionId;
2317
+ };
2318
+
2319
+ const getInvalidUriMessage = (uri, code) => {
2320
+ if (code === ParseChatDebugUriErrorCode.MissingUri) {
2321
+ return unableToLoadDebugSessionMissingUri();
2322
+ }
2323
+ return unableToLoadDebugSessionInvalidUri(uri);
2324
+ };
2325
+
2326
+ const getStateWithInvalidUri = state => {
2327
+ const parsed = parseChatDebugUri(state.uri);
2328
+ if (parsed.type !== ParseChatDebugUriResultType.Error) {
2329
+ return state;
2330
+ }
2331
+ return {
2332
+ ...state,
2333
+ errorMessage: getInvalidUriMessage(state.uri, parsed.code),
2334
+ events: [],
2335
+ initial: false,
2336
+ selectedEvent: null,
2337
+ selectedEventId: null,
2338
+ selectedEventIndex: null,
2339
+ sessionId: ''
2340
+ };
2341
+ };
2342
+
2343
+ const getErrorMessage = error => {
2344
+ if (error instanceof Error) {
2345
+ return error.message;
2346
+ }
2347
+ if (typeof error === 'string') {
2348
+ return error;
2349
+ }
2350
+ if (error && typeof error === 'object' && 'message' in error && typeof error.message === 'string') {
2351
+ return error.message;
2352
+ }
2353
+ return undefined;
2354
+ };
2355
+ const getFailedToLoadMessage = (sessionId, error) => {
2356
+ const errorMessage = getErrorMessage(error);
2357
+ if (errorMessage) {
2358
+ return failedToLoadChatDebugSessionWithError(sessionId, errorMessage);
2359
+ }
2360
+ return failedToLoadChatDebugSession(sessionId);
2361
+ };
2362
+
2363
+ const getSessionNotFoundMessage = sessionId => {
2364
+ return noChatSessionFound(sessionId);
2002
2365
  };
2366
+
2003
2367
  const getCurrentEvents$2 = state => {
2004
2368
  const filteredEvents = getFilteredEvents(state.events, state.filterValue, state.eventCategoryFilter, state.showInputEvents, state.showResponsePartEvents, state.showEventStreamFinishedEvents);
2005
2369
  return filterEventsByTimelineRange(filteredEvents, state.timelineStartSeconds, state.timelineEndSeconds);
2006
2370
  };
2371
+
2007
2372
  const restoreSelectedEvent = async state => {
2008
2373
  if (state.selectedEventId === null) {
2009
2374
  return {
@@ -2039,29 +2404,7 @@ const restoreSelectedEvent = async state => {
2039
2404
  selectedEventIndex
2040
2405
  };
2041
2406
  };
2042
- const getStateWithInvalidUri = state => {
2043
- const parsed = parseChatDebugUri(state.uri);
2044
- if (parsed.type !== 'error') {
2045
- return state;
2046
- }
2047
- return {
2048
- ...state,
2049
- errorMessage: getInvalidUriMessage(state.uri, parsed.code),
2050
- events: [],
2051
- initial: false,
2052
- selectedEvent: null,
2053
- selectedEventId: null,
2054
- selectedEventIndex: null,
2055
- sessionId: ''
2056
- };
2057
- };
2058
- const getSessionIdFromUri = state => {
2059
- const parsed = parseChatDebugUri(state.uri);
2060
- if (parsed.type === 'error') {
2061
- return undefined;
2062
- }
2063
- return parsed.sessionId;
2064
- };
2407
+
2065
2408
  const loadEventsForSessionId = async (state, sessionId) => {
2066
2409
  const {
2067
2410
  databaseName,
@@ -2106,6 +2449,7 @@ const loadEventsForSessionId = async (state, sessionId) => {
2106
2449
  };
2107
2450
  return restoreSelectedEvent(nextState);
2108
2451
  };
2452
+
2109
2453
  const loadEventsFromUri = async state => {
2110
2454
  const sessionId = getSessionIdFromUri(state);
2111
2455
  if (!sessionId) {
@@ -2113,6 +2457,7 @@ const loadEventsFromUri = async state => {
2113
2457
  }
2114
2458
  return loadEventsForSessionId(state, sessionId);
2115
2459
  };
2460
+
2116
2461
  const refreshEvents = async state => {
2117
2462
  const sessionId = state.sessionId || getSessionIdFromUri(state);
2118
2463
  if (!sessionId) {
@@ -2145,7 +2490,11 @@ const handleDetailsContextMenu = state => {
2145
2490
  return state;
2146
2491
  };
2147
2492
 
2148
- const handleDetailTab = (state, value) => {
2493
+ const handleDetailsTopContextMenu = state => {
2494
+ return state;
2495
+ };
2496
+
2497
+ const selectDetailTab = (state, value) => {
2149
2498
  if (!isDetailTab(value)) {
2150
2499
  return state;
2151
2500
  }
@@ -2159,9 +2508,11 @@ const getCurrentEvents$1 = state => {
2159
2508
  const filteredEvents = getFilteredEvents(state.events, state.filterValue, state.eventCategoryFilter, state.showInputEvents, state.showResponsePartEvents, state.showEventStreamFinishedEvents);
2160
2509
  return filterEventsByTimelineRange(filteredEvents, state.timelineStartSeconds, state.timelineEndSeconds);
2161
2510
  };
2511
+
2162
2512
  const getEventIndexByStableId$1 = (events, event) => {
2163
2513
  return events.findIndex(candidate => candidate.eventId === event.eventId);
2164
2514
  };
2515
+
2165
2516
  const getSelectedEventIndex$1 = state => {
2166
2517
  const {
2167
2518
  selectedEventIndex
@@ -2180,6 +2531,7 @@ const getSelectedEventIndex$1 = state => {
2180
2531
  }
2181
2532
  return newIndex;
2182
2533
  };
2534
+
2183
2535
  const getPreservedSelectedEventIndex$1 = (oldState, newState) => {
2184
2536
  const {
2185
2537
  selectedEventIndex
@@ -2199,6 +2551,7 @@ const getPreservedSelectedEventIndex$1 = (oldState, newState) => {
2199
2551
  }
2200
2552
  return newIndex;
2201
2553
  };
2554
+
2202
2555
  const withPreservedSelection$1 = (state, nextState) => {
2203
2556
  const selectedEventIndex = getPreservedSelectedEventIndex$1(state, nextState);
2204
2557
  return {
@@ -2217,12 +2570,6 @@ const handleEventCategoryFilter = (state, value) => {
2217
2570
  return withPreservedSelection$1(state, nextState);
2218
2571
  };
2219
2572
 
2220
- const handleEventRowClickDependencies = {
2221
- loadSelectedEvent: loadSelectedEvent
2222
- };
2223
- const isPrimaryButton = button => {
2224
- return button === 0;
2225
- };
2226
2573
  const parseSelectedEventIndex$1 = value => {
2227
2574
  const parsed = Number.parseInt(value, 10);
2228
2575
  if (Number.isNaN(parsed) || parsed < 0) {
@@ -2230,6 +2577,13 @@ const parseSelectedEventIndex$1 = value => {
2230
2577
  }
2231
2578
  return parsed;
2232
2579
  };
2580
+
2581
+ const handleEventRowClickDependencies = {
2582
+ loadSelectedEvent: loadSelectedEvent
2583
+ };
2584
+ const isPrimaryButton = button => {
2585
+ return button === 0;
2586
+ };
2233
2587
  const handleEventRowClick = async (state, value, button = 0) => {
2234
2588
  if (!isPrimaryButton(button)) {
2235
2589
  return state;
@@ -2241,28 +2595,10 @@ const handleEventRowClick = async (state, value, button = 0) => {
2241
2595
  return selectEventAtIndex(state, selectedEventIndex, handleEventRowClickDependencies);
2242
2596
  };
2243
2597
 
2244
- const handleHeaderContextMenu = state => {
2245
- return state;
2246
- };
2247
-
2248
2598
  const getBoolean = value => {
2249
2599
  return value === true || value === 'true' || value === 'on' || value === '1';
2250
2600
  };
2251
2601
 
2252
- const Filter = 'filter';
2253
- const EventCategoryFilter = 'eventCategoryFilter';
2254
- const ShowEventStreamFinishedEvents = 'showEventStreamFinishedEvents';
2255
- const ShowInputEvents = 'showInputEvents';
2256
- const ShowResponsePartEvents = 'showResponsePartEvents';
2257
- const UseDevtoolsLayout = 'useDevtoolsLayout';
2258
- const SelectedEventIndex = 'selectedEventIndex';
2259
- const CloseDetails = 'closeDetails';
2260
- const DetailTab = 'detailTab';
2261
- const TimelineStartSeconds = 'timelineStartSeconds';
2262
- const TimelineEndSeconds = 'timelineEndSeconds';
2263
- const TimelineRangePreset = 'timelineRangePreset';
2264
- const Refresh = 'refresh';
2265
-
2266
2602
  const getCurrentEvents = state => {
2267
2603
  const filteredEvents = getFilteredEvents(state.events, state.filterValue, state.eventCategoryFilter, state.showInputEvents, state.showResponsePartEvents, state.showEventStreamFinishedEvents);
2268
2604
  return filterEventsByTimelineRange(filteredEvents, state.timelineStartSeconds, state.timelineEndSeconds);
@@ -2448,6 +2784,58 @@ const handleSashPointerUp = (state, eventX, eventY) => {
2448
2784
  return state;
2449
2785
  };
2450
2786
 
2787
+ const getTableResizerId = name => {
2788
+ switch (name) {
2789
+ case 'ResizerOne':
2790
+ return 1;
2791
+ case 'ResizerTwo':
2792
+ return 2;
2793
+ default:
2794
+ return 0;
2795
+ }
2796
+ };
2797
+ const handleTableResizerPointerDown = (state, name, clientX) => {
2798
+ return {
2799
+ ...state,
2800
+ tableResizerDownId: getTableResizerId(name)
2801
+ };
2802
+ };
2803
+
2804
+ const handleTableResizerPointerMove = (state, clientX) => {
2805
+ if (!state.tableResizerDownId) {
2806
+ return state;
2807
+ }
2808
+ return {
2809
+ ...state,
2810
+ tableColumnWidths: getResizedTableColumnWidths(state.width, state.tableWidth, state.visibleTableColumns, state.tableColumnWidths, state.x, clientX, state.tableResizerDownId)
2811
+ };
2812
+ };
2813
+
2814
+ const handleTableResizerPointerUp = state => {
2815
+ if (!state.tableResizerDownId) {
2816
+ return state;
2817
+ }
2818
+ return {
2819
+ ...state,
2820
+ tableResizerDownId: 0
2821
+ };
2822
+ };
2823
+
2824
+ const handleTableRowCopy = async (state, eventIndex) => {
2825
+ const currentEvents = getCurrentEvents$3(state);
2826
+ const event = currentEvents[eventIndex];
2827
+ if (!event) {
2828
+ return state;
2829
+ }
2830
+ const text = JSON.stringify(event, null, 2);
2831
+ await writeClipBoardText(text);
2832
+ return state;
2833
+ };
2834
+
2835
+ const handleTimelineContextMenu = state => {
2836
+ return state;
2837
+ };
2838
+
2451
2839
  const clearTimelineSelectionState = state => {
2452
2840
  return {
2453
2841
  ...state,
@@ -2522,6 +2910,16 @@ const formatTimelinePresetValue = value => {
2522
2910
  return value.toFixed(3).replace(trailingZeroFractionRegex, '').replace(trailingFractionZeroRegex, '$1');
2523
2911
  };
2524
2912
 
2913
+ const getTimelineDurationSeconds = events => {
2914
+ const eventsWithTime = getEventsWithTime(events);
2915
+ if (eventsWithTime.length === 0) {
2916
+ return 0;
2917
+ }
2918
+ const baseTime = eventsWithTime[0].time;
2919
+ const lastTime = eventsWithTime.at(-1)?.time ?? baseTime;
2920
+ return roundSeconds(Math.max(0, lastTime - baseTime) / 1000);
2921
+ };
2922
+
2525
2923
  const getTimelineSecondsFromClientX = (events, eventX, timelineLeft, timelineWidth) => {
2526
2924
  if (timelineWidth <= 0) {
2527
2925
  return undefined;
@@ -2587,7 +2985,7 @@ const handleTimelinePointerUp = (state, eventX) => {
2587
2985
  return clearTimelineSelectionState(nextState);
2588
2986
  };
2589
2987
 
2590
- const handleUseDevtoolsLayout = (state, checked) => {
2988
+ const setUseDevtoolsLayout = (state, checked) => {
2591
2989
  const useDevtoolsLayout = getBoolean(checked);
2592
2990
  const selectedEventIndex = useDevtoolsLayout ? getSelectedEventIndex$1(state) : null;
2593
2991
  return {
@@ -2622,42 +3020,157 @@ const handleShowResponsePartEvents = (state, checked) => {
2622
3020
  };
2623
3021
 
2624
3022
  const loadContent = async (state, savedState) => {
2625
- return loadEventsFromUri(restoreSavedState(state, savedState));
3023
+ const nextState = await loadEventsFromUri(restoreSavedState(state, savedState));
3024
+ return {
3025
+ ...nextState,
3026
+ categoryFilters: createCategoryFilters(),
3027
+ detailTabs: createDetailTabs()
3028
+ };
2626
3029
  };
2627
3030
 
2628
3031
  const getCss = state => {
2629
3032
  const tableWidth = clampTableWidth(state.width, state.tableWidth);
2630
3033
  const detailsWidth = getDetailsWidth(state.width, state.tableWidth);
3034
+ const tableColumnLayout = getTableColumnLayout(tableWidth, state.visibleTableColumns, state.tableColumnWidths);
3035
+ const resizerOneLeft = tableColumnLayout.resizerLefts[0] || 0;
3036
+ const resizerTwoLeft = tableColumnLayout.resizerLefts[1] || 0;
2631
3037
  return `
2632
3038
  .ChatDebugView {
2633
3039
  --ChatDebugViewDetailsWidth: ${detailsWidth}px;
3040
+ --ChatDebugViewDurationColumnWidth: ${state.tableColumnWidths.duration}px;
3041
+ --ChatDebugViewResizerOneLeft: ${resizerOneLeft}px;
3042
+ --ChatDebugViewResizerTwoLeft: ${resizerTwoLeft}px;
2634
3043
  --ChatDebugViewSashWidth: ${sashWidth}px;
2635
3044
  --ChatDebugViewTableWidth: ${tableWidth}px;
3045
+ --ChatDebugViewTypeColumnWidth: ${state.tableColumnWidths.type}px;
2636
3046
  padding: ${viewPadding}px;
2637
3047
  }
2638
3048
 
3049
+ .ChatDebugViewTop {
3050
+ display: flex;
3051
+ align-items: center;
3052
+ gap: 8px;
3053
+ min-width: 0;
3054
+ }
3055
+
3056
+ .ChatDebugViewFilterInput {
3057
+ flex: 1;
3058
+ min-width: 0;
3059
+ }
2639
3060
 
2640
- .ChatDebugViewDetails {
2641
- contain: strict;
3061
+ .ChatDebugViewTableWrapper {
3062
+ position: relative;
3063
+ width: min(100%, var(--ChatDebugViewTableWidth));
3064
+ max-width: 100%;
3065
+ flex:1;
3066
+ display:flex
2642
3067
  }
2643
3068
 
2644
- .ChatDebugViewDetailsTop {
2645
- height: 33px;
2646
- contain: strict;
3069
+ .ChatDebugViewTable {
3070
+ width: 100%;
3071
+ table-layout: fixed;
3072
+ border-collapse: collapse;
3073
+ flex: 1;
3074
+ }
3075
+
3076
+ .ChatDebugViewHeaderCell,
3077
+ .ChatDebugViewCell {
3078
+ overflow: hidden;
3079
+ text-overflow: ellipsis;
3080
+ white-space: nowrap;
3081
+ }
3082
+
3083
+ .ChatDebugViewHeaderCellType.ChatDebugViewColumnFixed,
3084
+ .ChatDebugViewCellType.ChatDebugViewColumnFixed {
3085
+ width: var(--ChatDebugViewTypeColumnWidth);
3086
+ max-width: var(--ChatDebugViewTypeColumnWidth);
3087
+ }
3088
+
3089
+ .ChatDebugViewHeaderCellDuration.ChatDebugViewColumnFixed,
3090
+ .ChatDebugViewCellDuration.ChatDebugViewColumnFixed {
3091
+ width: var(--ChatDebugViewDurationColumnWidth);
3092
+ max-width: var(--ChatDebugViewDurationColumnWidth);
3093
+ }
3094
+
3095
+ .ChatDebugViewResizers {
3096
+ position: absolute;
3097
+ inset: 0;
3098
+ pointer-events: none;
3099
+ }
3100
+
3101
+ .ChatDebugViewResizer {
3102
+ position: absolute;
3103
+ top: 0;
3104
+ bottom: 0;
3105
+ width: 12px;
3106
+ margin: 0;
3107
+ padding: 0;
3108
+ border: 0;
3109
+ background: transparent;
3110
+ pointer-events: auto;
3111
+ cursor: col-resize;
3112
+ }
3113
+
3114
+ .ChatDebugViewResizerOne {
3115
+ left: var(--ChatDebugViewResizerOneLeft);
3116
+ transform: translateX(-50%);
3117
+ }
3118
+
3119
+ .ChatDebugViewResizerTwo {
3120
+ left: var(--ChatDebugViewResizerTwoLeft);
3121
+ transform: translateX(-50%);
3122
+ }
3123
+
3124
+ .ChatDebugViewResizerInner {
3125
+ position: absolute;
3126
+ top: 0;
3127
+ bottom: 0;
3128
+ left: 50%;
3129
+ width: 1px;
3130
+ transform: translateX(-50%);
3131
+ background: var(--vscode-widget-border, rgba(255, 255, 255, 0.18));
2647
3132
  }
2648
3133
 
2649
- .ChatDebugViewDetailsBottom {
3134
+
3135
+ .ChatDebugViewDetails {
3136
+ margin-left: auto;
3137
+ min-height: 26px;
3138
+ }
3139
+ border: 1px solid transparent;
3140
+ border-radius: 4px;
3141
+ background: transparent;
3142
+ color: var(--vscode-descriptionForeground, inherit);
3143
+ }
3144
+ font-size: 11px;
3145
+ font-weight: 600;
3146
+ letter-spacing: 0.02em;
2650
3147
  display: flex;
2651
3148
  contain: strict;
2652
- flex:1
3149
+ flex:1;
3150
+ transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease, transform 120ms ease;
2653
3151
 
2654
3152
  }
2655
3153
  .ChatDebugViewEvent {
2656
- contain: content
3154
+ border-color: var(--vscode-widget-border, rgba(255, 255, 255, 0.14));
3155
+ background: var(--vscode-toolbar-hoverBackground, rgba(255, 255, 255, 0.06));
3156
+ color: var(--vscode-foreground, inherit);
3157
+
3158
+ .ChatDebugViewEventLineContent {
3159
+ flex: 1;
3160
+ background: var(--vscode-toolbar-activeBackground, rgba(255, 255, 255, 0.1));
3161
+ min-width: 0;
3162
+ overflow-wrap: anywhere;
3163
+ white-space: pre-wrap;
3164
+ word-break: break-word;
3165
+ outline: 1px solid var(--vscode-focusBorder, rgba(255, 255, 255, 0.4));
3166
+
3167
+ .ChatDebugViewEventLineNumber {
3168
+ flex: none;
2657
3169
  }
2658
3170
 
2659
3171
  .row {
2660
3172
  flex-shrink: 0;
3173
+ min-width: 0;
2661
3174
  }
2662
3175
 
2663
3176
  .ChatDebugViewRefreshButton {
@@ -2665,6 +3178,7 @@ const getCss = state => {
2665
3178
  align-items: center;
2666
3179
  justify-content: center;
2667
3180
  flex: none;
3181
+ margin-left: auto;
2668
3182
  min-height: 28px;
2669
3183
  padding: 0 10px;
2670
3184
  border: 1px solid rgba(255, 255, 255, 0.16);
@@ -2706,6 +3220,10 @@ const renderCss = (oldState, newState) => {
2706
3220
  return [SetCss, newState.uid, css];
2707
3221
  };
2708
3222
 
3223
+ const mergeClassNames = (...classNames) => {
3224
+ return classNames.filter(Boolean).join(' ');
3225
+ };
3226
+
2709
3227
  const text = data => {
2710
3228
  return {
2711
3229
  childCount: 0,
@@ -3025,6 +3543,9 @@ const ChatDebugViewEventsFullWidth = 'ChatDebugViewEventsFullWidth';
3025
3543
  const ChatDebugViewFilterInput = 'ChatDebugViewFilterInput';
3026
3544
  const ChatDebugViewFilterInputDevtools = 'ChatDebugViewFilterInput--devtools';
3027
3545
  const ChatDebugViewHeaderCell = 'ChatDebugViewHeaderCell';
3546
+ const ChatDebugViewHeaderCellDuration = 'ChatDebugViewHeaderCellDuration';
3547
+ const ChatDebugViewHeaderCellStatus = 'ChatDebugViewHeaderCellStatus';
3548
+ const ChatDebugViewHeaderCellType = 'ChatDebugViewHeaderCellType';
3028
3549
  const ChatDebugViewRefreshButton = 'ChatDebugViewRefreshButton';
3029
3550
  const ChatDebugViewQuickFilterInput = 'ChatDebugViewQuickFilterInput';
3030
3551
  const ChatDebugViewQuickFilterPill = 'ChatDebugViewQuickFilterPill';
@@ -3036,6 +3557,12 @@ const ChatDebugViewTable = 'ChatDebugViewTable';
3036
3557
  const ChatDebugViewTableBody = 'ChatDebugViewTableBody';
3037
3558
  const ChatDebugViewTableHeader = 'ChatDebugViewTableHeader';
3038
3559
  const ChatDebugViewTableHeaderRow = 'ChatDebugViewTableHeaderRow';
3560
+ const ChatDebugViewTableWrapper = 'ChatDebugViewTableWrapper';
3561
+ const ChatDebugViewResizer = 'ChatDebugViewResizer';
3562
+ const ChatDebugViewResizerInner = 'ChatDebugViewResizerInner';
3563
+ const ChatDebugViewResizerOne = 'ChatDebugViewResizerOne';
3564
+ const ChatDebugViewResizerTwo = 'ChatDebugViewResizerTwo';
3565
+ const ChatDebugViewResizers = 'ChatDebugViewResizers';
3039
3566
  const TableRowEven = 'TableRowEven';
3040
3567
  const ChatDebugViewTimeline = 'ChatDebugViewTimeline';
3041
3568
  const ChatDebugViewTimelineBucket = 'ChatDebugViewTimelineBucket';
@@ -3060,6 +3587,7 @@ const ChatDebugViewTimingValue = 'ChatDebugViewTimingValue';
3060
3587
  const ChatDebugViewTop = 'ChatDebugViewTop';
3061
3588
  const ChatDebugViewTopDevtools = 'ChatDebugViewTop--devtools';
3062
3589
  const ChatDebugViewCell = 'ChatDebugViewCell';
3590
+ const ChatDebugViewColumnFixed = 'ChatDebugViewColumnFixed';
3063
3591
  const ChatDebugViewCellDuration = 'ChatDebugViewCellDuration';
3064
3592
  const ChatDebugViewCellStatus = 'ChatDebugViewCellStatus';
3065
3593
  const ChatDebugViewCellStatusError = 'ChatDebugViewCellStatusError';
@@ -3071,9 +3599,6 @@ const TokenKey = 'Token TokenKey';
3071
3599
  const TokenNumeric = 'Token TokenNumeric';
3072
3600
  const TokenString = 'Token TokenString';
3073
3601
  const TokenText = 'Token TokenText';
3074
- const joinClassNames = (...classNames) => {
3075
- return classNames.filter(Boolean).join(' ');
3076
- };
3077
3602
 
3078
3603
  const getDebugErrorDom = errorMessage => {
3079
3604
  return [{
@@ -3089,50 +3614,56 @@ const getDebugErrorDom = errorMessage => {
3089
3614
 
3090
3615
  const HandleEventCategoryFilter = 4;
3091
3616
  const HandleFilterInput = 5;
3092
- const HandleDetailTab = 6;
3617
+ const SelectDetailTab = 6;
3093
3618
  const HandleEventRowClick = 7;
3094
3619
  const HandleHeaderContextMenu = 8;
3095
3620
  const HandleSashPointerDown = 9;
3096
3621
  const HandleSashPointerMove = 10;
3097
3622
  const HandleSashPointerUp = 11;
3098
- const HandleTableBodyContextMenu = 12;
3099
- const HandleDetailsContextMenu = 13;
3100
- const HandleTimelinePointerDown = 14;
3101
- const HandleTimelinePointerMove = 15;
3102
- const HandleTimelinePointerUp = 16;
3103
- const HandleTimelineDoubleClick = 17;
3104
- const HandleTableKeyDown = 18;
3105
- const HandleTimelineRangePreset = 19;
3106
- const HandleCloseDetails = 20;
3107
- const HandleClickRefresh = 21;
3623
+ const HandleTableResizerPointerDown = 12;
3624
+ const HandleTableResizerPointerMove = 13;
3625
+ const HandleTableResizerPointerUp = 14;
3626
+ const HandleTableBodyContextMenu = 15;
3627
+ const HandleDetailsContextMenu = 16;
3628
+ const HandleTimelinePointerDown = 17;
3629
+ const HandleTimelinePointerMove = 18;
3630
+ const HandleTimelinePointerUp = 19;
3631
+ const HandleTimelineDoubleClick = 20;
3632
+ const HandleTableKeyDown = 21;
3633
+ const HandleTimelineRangePreset = 22;
3634
+ const HandleCloseDetails = 23;
3635
+ const HandleClickRefresh = 24;
3636
+ const HandleDetailsTopContextMenu = 25;
3637
+ const HandleTimelineContextMenu = 26;
3108
3638
 
3109
3639
  const getRefreshButtonDom = () => {
3110
3640
  return [{
3111
- 'aria-label': 'Refresh events',
3641
+ 'aria-label': refreshEvents$1(),
3112
3642
  childCount: 1,
3113
3643
  className: ChatDebugViewRefreshButton,
3114
3644
  name: Refresh,
3115
3645
  onClick: HandleClickRefresh,
3116
3646
  type: Button$1,
3117
3647
  value: Refresh
3118
- }, text('Refresh')];
3648
+ }, text(refresh$1())];
3119
3649
  };
3650
+
3120
3651
  const getDebugViewTopDom = (filterValue, useDevtoolsLayout, quickFilterNodes) => {
3121
3652
  const refreshButtonDom = getRefreshButtonDom();
3122
3653
  if (useDevtoolsLayout) {
3123
3654
  return [{
3124
3655
  childCount: 2 + (quickFilterNodes.length > 0 ? 1 : 0),
3125
- className: joinClassNames(ChatDebugViewTop, ChatDebugViewTopDevtools),
3656
+ className: mergeClassNames(ChatDebugViewTop, ChatDebugViewTopDevtools),
3126
3657
  onContextMenu: HandleHeaderContextMenu,
3127
3658
  type: Search
3128
3659
  }, {
3129
3660
  autocomplete: 'off',
3130
3661
  childCount: 0,
3131
- className: joinClassNames(InputBox, ChatDebugViewFilterInput, ChatDebugViewFilterInputDevtools),
3662
+ className: mergeClassNames(InputBox, ChatDebugViewFilterInput, ChatDebugViewFilterInputDevtools),
3132
3663
  inputType: 'search',
3133
3664
  name: Filter,
3134
3665
  onInput: HandleFilterInput,
3135
- placeholder: 'Filter events',
3666
+ placeholder: filterEvents(),
3136
3667
  type: Input,
3137
3668
  value: filterValue
3138
3669
  }, ...quickFilterNodes, ...refreshButtonDom];
@@ -3145,16 +3676,49 @@ const getDebugViewTopDom = (filterValue, useDevtoolsLayout, quickFilterNodes) =>
3145
3676
  }, {
3146
3677
  autocomplete: 'off',
3147
3678
  childCount: 0,
3148
- className: joinClassNames(InputBox, ChatDebugViewFilterInput),
3679
+ className: mergeClassNames(InputBox, ChatDebugViewFilterInput),
3149
3680
  inputType: 'search',
3150
3681
  name: Filter,
3151
3682
  onInput: HandleFilterInput,
3152
- placeholder: 'Filter events',
3683
+ placeholder: filterEvents(),
3153
3684
  type: Input,
3154
3685
  value: filterValue
3155
3686
  }, ...refreshButtonDom];
3156
3687
  };
3157
3688
 
3689
+ const None = 'none';
3690
+
3691
+ const getPanelId = detailTab => {
3692
+ return `ChatDebugViewDetailsPanel-${detailTab}`;
3693
+ };
3694
+
3695
+ const getTabId = detailTab => {
3696
+ return `ChatDebugViewDetailsTab-${detailTab}`;
3697
+ };
3698
+
3699
+ const getDetailTabDom = (detailTab, selectedDetailTab) => {
3700
+ const isSelected = detailTab.name === selectedDetailTab;
3701
+ return [{
3702
+ 'aria-controls': getPanelId(detailTab.name),
3703
+ 'aria-selected': isSelected,
3704
+ childCount: 1,
3705
+ className: mergeClassNames(ChatDebugViewDetailsTab, isSelected ? ChatDebugViewDetailsTabSelected : ''),
3706
+ id: getTabId(detailTab.name),
3707
+ name: DetailTab,
3708
+ onChange: SelectDetailTab,
3709
+ onClick: SelectDetailTab,
3710
+ role: 'tab',
3711
+ tabIndex: isSelected ? 0 : -1,
3712
+ type: Button$1,
3713
+ value: detailTab.name
3714
+ }, text(detailTab.label)];
3715
+ };
3716
+ const getTabNodes = (detailTabs, selectedDetailTab) => {
3717
+ return detailTabs.flatMap(detailTab => {
3718
+ return getDetailTabDom(detailTab, selectedDetailTab);
3719
+ });
3720
+ };
3721
+
3158
3722
  const getDurationText = event => {
3159
3723
  const explicitDuration = event.durationMs ?? event.duration;
3160
3724
  if (typeof explicitDuration === 'number' && Number.isFinite(explicitDuration)) {
@@ -3220,44 +3784,21 @@ const getTimingRowDom = (label, value) => {
3220
3784
  type: Span
3221
3785
  }, text(value)];
3222
3786
  };
3787
+
3223
3788
  const getTimingDetailsDom = event => {
3224
3789
  return [{
3225
3790
  childCount: 3,
3226
3791
  className: ChatDebugViewTiming,
3227
3792
  type: Div
3228
- }, ...getTimingRowDom('Started', getStartText(event)), ...getTimingRowDom('Ended', getEndText(event)), ...getTimingRowDom('Duration', getDurationText(event))];
3793
+ }, ...getTimingRowDom(started(), getStartText(event)), ...getTimingRowDom(ended(), getEndText(event)), ...getTimingRowDom(duration(), getDurationText(event))];
3229
3794
  };
3230
3795
 
3231
- const getTabId = detailTab => {
3232
- return `ChatDebugViewDetailsTab-${detailTab}`;
3233
- };
3234
- const getPanelId = detailTab => {
3235
- return `ChatDebugViewDetailsPanel-${detailTab}`;
3236
- };
3237
- const getTabNodes = selectedDetailTab => {
3238
- return detailTabs.flatMap(detailTab => {
3239
- const isSelected = detailTab === selectedDetailTab;
3240
- return [{
3241
- 'aria-controls': getPanelId(detailTab),
3242
- 'aria-selected': isSelected,
3243
- childCount: 1,
3244
- className: joinClassNames(ChatDebugViewDetailsTab, isSelected && ChatDebugViewDetailsTabSelected),
3245
- id: getTabId(detailTab),
3246
- name: DetailTab,
3247
- onChange: HandleDetailTab,
3248
- onClick: HandleDetailTab,
3249
- role: 'tab',
3250
- tabIndex: isSelected ? 0 : -1,
3251
- type: Button$1,
3252
- value: detailTab
3253
- }, text(getDetailTabLabel(detailTab))];
3254
- });
3255
- };
3256
- const getDetailsDom = (previewEventNodes, responseEventNodes = previewEventNodes, selectedEvent = null, selectedDetailTab = Response) => {
3257
- if (previewEventNodes.length === 0 && responseEventNodes.length === 0) {
3796
+ const getDetailsDom = (previewEventNodes, payloadEventNodes = previewEventNodes, responseEventNodes = payloadEventNodes, selectedEvent = null, detailTabs = createDetailTabs(), selectedDetailTab = Response) => {
3797
+ if (previewEventNodes.length === 0 && payloadEventNodes.length === 0 && responseEventNodes.length === 0) {
3258
3798
  return [];
3259
3799
  }
3260
- const contentNodes = selectedDetailTab === Timing && selectedEvent ? getTimingDetailsDom(selectedEvent) : selectedDetailTab === Preview ? previewEventNodes : responseEventNodes;
3800
+ const safeSelectedDetailTab = getSelectedDetailTab(detailTabs, selectedDetailTab);
3801
+ const contentNodes = safeSelectedDetailTab === Timing && selectedEvent ? getTimingDetailsDom(selectedEvent) : safeSelectedDetailTab === Preview ? previewEventNodes : safeSelectedDetailTab === Payload ? payloadEventNodes : responseEventNodes;
3261
3802
  return [{
3262
3803
  childCount: 2,
3263
3804
  className: ChatDebugViewDetails,
@@ -3265,9 +3806,10 @@ const getDetailsDom = (previewEventNodes, responseEventNodes = previewEventNodes
3265
3806
  }, {
3266
3807
  childCount: 2,
3267
3808
  className: ChatDebugViewDetailsTop,
3809
+ onContextMenu: HandleDetailsTopContextMenu,
3268
3810
  type: Div
3269
3811
  }, {
3270
- 'aria-label': 'Close details',
3812
+ 'aria-label': closeDetails(),
3271
3813
  childCount: 0,
3272
3814
  className: ChatDebugViewDetailsClose,
3273
3815
  name: CloseDetails,
@@ -3276,16 +3818,16 @@ const getDetailsDom = (previewEventNodes, responseEventNodes = previewEventNodes
3276
3818
  type: Button$1,
3277
3819
  value: 'close'
3278
3820
  }, {
3279
- 'aria-label': 'Detail sections',
3821
+ 'aria-label': detailSections(),
3280
3822
  childCount: detailTabs.length,
3281
3823
  className: ChatDebugViewDetailsTabs,
3282
3824
  role: 'tablist',
3283
3825
  type: Div
3284
- }, ...getTabNodes(selectedDetailTab), {
3285
- 'aria-labelledby': getTabId(selectedDetailTab),
3826
+ }, ...getTabNodes(detailTabs, safeSelectedDetailTab), {
3827
+ 'aria-labelledby': getTabId(safeSelectedDetailTab),
3286
3828
  childCount: 1,
3287
3829
  className: ChatDebugViewDetailsBottom,
3288
- id: getPanelId(selectedDetailTab),
3830
+ id: getPanelId(safeSelectedDetailTab),
3289
3831
  onContextMenu: HandleDetailsContextMenu,
3290
3832
  role: 'tabpanel',
3291
3833
  type: Div
@@ -3325,9 +3867,6 @@ const getEventTypeLabel = event => {
3325
3867
  return `${event.type}, ${toolName}`;
3326
3868
  };
3327
3869
 
3328
- const isRecord = value => {
3329
- return typeof value === 'object' && value !== null;
3330
- };
3331
3870
  const isErrorStatusCode = value => {
3332
3871
  if (typeof value === 'number') {
3333
3872
  return value >= 400;
@@ -3338,6 +3877,11 @@ const isErrorStatusCode = value => {
3338
3877
  }
3339
3878
  return false;
3340
3879
  };
3880
+
3881
+ const isRecord = value => {
3882
+ return typeof value === 'object' && value !== null;
3883
+ };
3884
+
3341
3885
  const hasErrorStatus = event => {
3342
3886
  if (event.type === 'error') {
3343
3887
  return true;
@@ -3372,30 +3916,48 @@ const getStatusText = event => {
3372
3916
  return hasErrorStatus(event) ? '400' : '200';
3373
3917
  };
3374
3918
 
3375
- const getDevtoolsRows = (events, selectedEventIndex) => {
3919
+ const getRowCellNodes = (event, isErrorStatus, visibleTableColumns) => {
3920
+ const orderedVisibleTableColumns = getOrderedVisibleTableColumns(visibleTableColumns);
3921
+ return orderedVisibleTableColumns.flatMap((column, index) => {
3922
+ const isFixed = index < orderedVisibleTableColumns.length - 1;
3923
+ switch (column) {
3924
+ case Duration:
3925
+ return [{
3926
+ childCount: 1,
3927
+ className: mergeClassNames(ChatDebugViewCell, ChatDebugViewCellDuration, isFixed ? ChatDebugViewColumnFixed : ''),
3928
+ type: Td
3929
+ }, text(getDurationText(event))];
3930
+ case Status:
3931
+ return [{
3932
+ childCount: 1,
3933
+ className: mergeClassNames(ChatDebugViewCell, ChatDebugViewCellStatus, isErrorStatus ? ChatDebugViewCellStatusError : '', isFixed ? ChatDebugViewColumnFixed : ''),
3934
+ type: Td
3935
+ }, text(getStatusText(event))];
3936
+ case Type:
3937
+ return [{
3938
+ childCount: 1,
3939
+ className: mergeClassNames(ChatDebugViewCell, ChatDebugViewCellType, isFixed ? ChatDebugViewColumnFixed : ''),
3940
+ type: Td
3941
+ }, text(getEventTypeLabel(event))];
3942
+ default:
3943
+ return [];
3944
+ }
3945
+ });
3946
+ };
3947
+
3948
+ const getDevtoolsRows = (events, selectedEventIndex, visibleTableColumns = defaultVisibleTableColumns) => {
3376
3949
  return events.flatMap((event, i) => {
3377
3950
  const isEvenRow = i % 2 === 1;
3378
3951
  const isSelected = selectedEventIndex === i;
3379
3952
  const isErrorStatus = hasErrorStatus(event);
3380
3953
  const rowIndex = String(i);
3954
+ const rowCellNodes = getRowCellNodes(event, isErrorStatus, visibleTableColumns);
3381
3955
  return [{
3382
- childCount: 3,
3383
- className: joinClassNames(ChatDebugViewEventRow, isEvenRow && TableRowEven, isSelected && ChatDebugViewEventRowSelected),
3956
+ childCount: visibleTableColumns.length,
3957
+ className: mergeClassNames(ChatDebugViewEventRow, isEvenRow ? TableRowEven : '', isSelected ? ChatDebugViewEventRowSelected : ''),
3384
3958
  'data-index': rowIndex,
3385
3959
  type: Tr
3386
- }, {
3387
- childCount: 1,
3388
- className: joinClassNames(ChatDebugViewCell, ChatDebugViewCellType),
3389
- type: Td
3390
- }, text(getEventTypeLabel(event)), {
3391
- childCount: 1,
3392
- className: joinClassNames(ChatDebugViewCell, ChatDebugViewCellDuration),
3393
- type: Td
3394
- }, text(getDurationText(event)), {
3395
- childCount: 1,
3396
- className: joinClassNames(ChatDebugViewCell, ChatDebugViewCellStatus, isErrorStatus && ChatDebugViewCellStatusError),
3397
- type: Td
3398
- }, text(getStatusText(event))];
3960
+ }, ...rowCellNodes];
3399
3961
  });
3400
3962
  };
3401
3963
 
@@ -3407,6 +3969,25 @@ const getEmptyStateDom = emptyMessage => {
3407
3969
  }, text(emptyMessage)];
3408
3970
  };
3409
3971
 
3972
+ const getLineNodeDom = (line, index) => {
3973
+ return [{
3974
+ childCount: 2,
3975
+ className: Row,
3976
+ type: Div
3977
+ }, {
3978
+ childCount: 1,
3979
+ className: ChatDebugViewEventLineNumber,
3980
+ type: Span
3981
+ }, text(String(index + 1)), {
3982
+ childCount: line.childCount,
3983
+ className: ChatDebugViewEventLineContent,
3984
+ type: Span
3985
+ }, ...line.nodes];
3986
+ };
3987
+ const getLineNodes = lines => {
3988
+ return lines.flatMap(getLineNodeDom);
3989
+ };
3990
+
3410
3991
  const isDigit = character => {
3411
3992
  return character !== undefined && character >= '0' && character <= '9';
3412
3993
  };
@@ -3554,24 +4135,6 @@ const getLineContentNodes = line => {
3554
4135
  }, text(segment.value)];
3555
4136
  });
3556
4137
  };
3557
- const getLineNodes = lines => {
3558
- return lines.flatMap((line, index) => {
3559
- const lineContentNodes = getLineContentNodes(line);
3560
- return [{
3561
- childCount: 2,
3562
- className: Row,
3563
- type: Div
3564
- }, {
3565
- childCount: 1,
3566
- className: ChatDebugViewEventLineNumber,
3567
- type: Span
3568
- }, text(String(index + 1)), {
3569
- childCount: lineContentNodes.length / 2,
3570
- className: ChatDebugViewEventLineContent,
3571
- type: Span
3572
- }, ...lineContentNodes];
3573
- });
3574
- };
3575
4138
  const isChatViewEvent = value => {
3576
4139
  return typeof value === 'object' && value !== null && typeof value.type === 'string';
3577
4140
  };
@@ -3581,7 +4144,13 @@ const getEventNode = value => {
3581
4144
  type: getEventTypeLabel(value)
3582
4145
  } : value;
3583
4146
  const lines = getJsonLines(renderedValue);
3584
- const lineNodes = getLineNodes(lines);
4147
+ const lineNodes = getLineNodes(lines.map(line => {
4148
+ const lineContentNodes = getLineContentNodes(line);
4149
+ return {
4150
+ childCount: lineContentNodes.length / 2,
4151
+ nodes: lineContentNodes
4152
+ };
4153
+ }));
3585
4154
  return [{
3586
4155
  childCount: lines.length,
3587
4156
  className: ChatDebugViewEvent,
@@ -3590,19 +4159,61 @@ const getEventNode = value => {
3590
4159
  };
3591
4160
 
3592
4161
  const getEventsClassName = hasSelectedEvent => {
3593
- const widthClassName = joinClassNames(ChatDebugViewEvents, !hasSelectedEvent && ChatDebugViewEventsFullWidth);
4162
+ const widthClassName = mergeClassNames(ChatDebugViewEvents, hasSelectedEvent ? '' : ChatDebugViewEventsFullWidth);
3594
4163
  return widthClassName;
3595
4164
  };
3596
4165
 
4166
+ const getPreviewName = event => {
4167
+ if (typeof event.name === 'string' && event.name) {
4168
+ return event.name;
4169
+ }
4170
+ if (typeof event.toolName === 'string' && event.toolName) {
4171
+ return event.toolName;
4172
+ }
4173
+ return undefined;
4174
+ };
4175
+
3597
4176
  const hasOwn = (event, key) => {
3598
4177
  return Object.hasOwn(event, key);
3599
4178
  };
3600
- const isChatMessageUpdatedEvent = event => {
3601
- return event.type === 'chat-message-updated';
4179
+
4180
+ const shouldIncludeArguments = (event, name) => {
4181
+ if (!hasOwn(event, 'arguments')) {
4182
+ return false;
4183
+ }
4184
+ if (name === 'getWorkspaceUri') {
4185
+ return false;
4186
+ }
4187
+ return true;
4188
+ };
4189
+
4190
+ const getPayloadEvent = event => {
4191
+ const name = getPreviewName(event);
4192
+ const payloadEvent = {
4193
+ ...(name === undefined ? {} : {
4194
+ name
4195
+ }),
4196
+ ...(shouldIncludeArguments(event, name) ? {
4197
+ arguments: event.arguments
4198
+ } : {}),
4199
+ ...(hasOwn(event, 'result') ? {
4200
+ result: event.result
4201
+ } : {})
4202
+ };
4203
+ if (Object.keys(payloadEvent).length > 0) {
4204
+ return payloadEvent;
4205
+ }
4206
+ return event;
3602
4207
  };
4208
+
3603
4209
  const isChatMessageAddedEvent = event => {
3604
4210
  return event.type === 'chat-message-added';
3605
4211
  };
4212
+
4213
+ const isChatMessageUpdatedEvent = event => {
4214
+ return event.type === 'chat-message-updated';
4215
+ };
4216
+
3606
4217
  const getPreviewMessageText = event => {
3607
4218
  if (isChatMessageUpdatedEvent(event) && typeof event.text === 'string') {
3608
4219
  return event.text;
@@ -3627,23 +4238,24 @@ const getPreviewMessageText = event => {
3627
4238
  }
3628
4239
  return text;
3629
4240
  };
3630
- const getPreviewName = event => {
3631
- if (typeof event.name === 'string' && event.name) {
3632
- return event.name;
3633
- }
3634
- if (typeof event.toolName === 'string' && event.toolName) {
3635
- return event.toolName;
4241
+
4242
+ const getWriteFilePreviewText = (event, name) => {
4243
+ if (name !== 'write_file') {
4244
+ return undefined;
3636
4245
  }
3637
- return undefined;
3638
- };
3639
- const shouldIncludeArguments = (event, name) => {
3640
- if (!hasOwn(event, 'arguments')) {
3641
- return false;
4246
+ const {
4247
+ arguments: toolArguments
4248
+ } = event;
4249
+ if (typeof toolArguments !== 'object' || toolArguments === null || !Object.hasOwn(toolArguments, 'content')) {
4250
+ return undefined;
3642
4251
  }
3643
- if (name === 'getWorkspaceUri') {
3644
- return false;
4252
+ const {
4253
+ content
4254
+ } = toolArguments;
4255
+ if (typeof content !== 'string') {
4256
+ return undefined;
3645
4257
  }
3646
- return true;
4258
+ return content;
3647
4259
  };
3648
4260
  const getPreviewEvent = event => {
3649
4261
  const previewMessageText = getPreviewMessageText(event);
@@ -3651,21 +4263,11 @@ const getPreviewEvent = event => {
3651
4263
  return previewMessageText;
3652
4264
  }
3653
4265
  const name = getPreviewName(event);
3654
- const previewEvent = {
3655
- ...(name === undefined ? {} : {
3656
- name
3657
- }),
3658
- ...(shouldIncludeArguments(event, name) ? {
3659
- arguments: event.arguments
3660
- } : {}),
3661
- ...(hasOwn(event, 'result') ? {
3662
- result: event.result
3663
- } : {})
3664
- };
3665
- if (Object.keys(previewEvent).length > 0) {
3666
- return previewEvent;
4266
+ const writeFilePreviewText = getWriteFilePreviewText(event, name);
4267
+ if (writeFilePreviewText !== undefined) {
4268
+ return writeFilePreviewText;
3667
4269
  }
3668
- return event;
4270
+ return getPayloadEvent(event);
3669
4271
  };
3670
4272
 
3671
4273
  const getSashNodesDom = hasSelectedEvent => {
@@ -3694,43 +4296,110 @@ const getTableBodyDom = (rowNodes, eventCount) => {
3694
4296
  }, ...rowNodes];
3695
4297
  };
3696
4298
 
3697
- const getTableHeaderDom = () => {
4299
+ const getHeaderCellNodes = visibleTableColumns => {
4300
+ const orderedVisibleTableColumns = getOrderedVisibleTableColumns(visibleTableColumns);
4301
+ return orderedVisibleTableColumns.flatMap((column, index) => {
4302
+ const isFixed = index < orderedVisibleTableColumns.length - 1;
4303
+ switch (column) {
4304
+ case Duration:
4305
+ return [{
4306
+ childCount: 1,
4307
+ className: mergeClassNames(ChatDebugViewHeaderCell, ChatDebugViewHeaderCellDuration, isFixed ? ChatDebugViewColumnFixed : ''),
4308
+ scope: 'col',
4309
+ type: Th
4310
+ }, text(duration())];
4311
+ case Status:
4312
+ return [{
4313
+ childCount: 1,
4314
+ className: mergeClassNames(ChatDebugViewHeaderCell, ChatDebugViewHeaderCellStatus, isFixed ? ChatDebugViewColumnFixed : ''),
4315
+ scope: 'col',
4316
+ type: Th
4317
+ }, text(status())];
4318
+ case Type:
4319
+ return [{
4320
+ childCount: 1,
4321
+ className: mergeClassNames(ChatDebugViewHeaderCell, ChatDebugViewHeaderCellType, isFixed ? ChatDebugViewColumnFixed : ''),
4322
+ scope: 'col',
4323
+ type: Th
4324
+ }, text(type())];
4325
+ default:
4326
+ return [];
4327
+ }
4328
+ });
4329
+ };
4330
+
4331
+ const getTableHeaderDom = (visibleTableColumns = defaultVisibleTableColumns) => {
4332
+ const headerCellNodes = getHeaderCellNodes(visibleTableColumns);
3698
4333
  return [{
3699
4334
  childCount: 1,
3700
4335
  className: ChatDebugViewTableHeader,
4336
+ onContextMenu: HandleHeaderContextMenu,
3701
4337
  type: THead
3702
4338
  }, {
3703
- childCount: 3,
4339
+ childCount: visibleTableColumns.length,
3704
4340
  className: ChatDebugViewTableHeaderRow,
3705
4341
  type: Tr
3706
- }, {
3707
- childCount: 1,
3708
- className: ChatDebugViewHeaderCell,
3709
- scope: 'col',
3710
- type: Th
3711
- }, text('Type'), {
3712
- childCount: 1,
3713
- className: ChatDebugViewHeaderCell,
3714
- scope: 'col',
3715
- type: Th
3716
- }, text('Duration'), {
4342
+ }, ...headerCellNodes];
4343
+ };
4344
+
4345
+ const resizerNames = ['ResizerOne', 'ResizerTwo'];
4346
+ const resizerClassNames = [ChatDebugViewResizerOne, ChatDebugViewResizerTwo];
4347
+ const getTableResizersDom = visibleTableColumns => {
4348
+ const visibleColumnCount = getOrderedVisibleTableColumns(visibleTableColumns).length;
4349
+ const resizerCount = Math.max(0, visibleColumnCount - 1);
4350
+ if (resizerCount === 0) {
4351
+ return [];
4352
+ }
4353
+ const visibleResizerClassNames = resizerClassNames.slice(0, resizerCount);
4354
+ const resizerNodes = visibleResizerClassNames.flatMap((resizerClassName, index) => [{
3717
4355
  childCount: 1,
3718
- className: ChatDebugViewHeaderCell,
3719
- scope: 'col',
3720
- type: Th
3721
- }, text('Status')];
4356
+ className: `${ChatDebugViewResizer} ${resizerClassName}`,
4357
+ name: resizerNames[index],
4358
+ onPointerDown: HandleTableResizerPointerDown,
4359
+ role: None,
4360
+ type: Button$1
4361
+ }, {
4362
+ childCount: 0,
4363
+ className: ChatDebugViewResizerInner,
4364
+ type: Div
4365
+ }]);
4366
+ return [{
4367
+ childCount: resizerCount,
4368
+ className: ChatDebugViewResizers,
4369
+ type: Div
4370
+ }, ...resizerNodes];
3722
4371
  };
3723
4372
 
3724
- const getTableDom = (rowNodes, eventCount) => {
4373
+ const getTableDom = (rowNodes, eventCount, visibleTableColumns = defaultVisibleTableColumns) => {
4374
+ const resizerNodes = getTableResizersDom(visibleTableColumns);
3725
4375
  return [{
4376
+ childCount: 1 + (resizerNodes.length > 0 ? 1 : 0),
4377
+ className: ChatDebugViewTableWrapper,
4378
+ type: Div
4379
+ }, {
3726
4380
  childCount: 2,
3727
4381
  className: ChatDebugViewTable,
3728
4382
  type: Table
3729
- }, ...getTableHeaderDom(), ...getTableBodyDom(rowNodes, eventCount)];
4383
+ }, ...getTableHeaderDom(visibleTableColumns), ...getTableBodyDom(rowNodes, eventCount), ...resizerNodes];
3730
4384
  };
3731
4385
 
3732
- const formatPercent = value => {
3733
- return `${Number(value.toFixed(3))}%`;
4386
+ const getTextNode = value => {
4387
+ const lines = value.split('\n');
4388
+ const lineNodes = getLineNodes(lines.map(line => {
4389
+ return {
4390
+ childCount: 1,
4391
+ nodes: [{
4392
+ childCount: 1,
4393
+ className: TokenText,
4394
+ type: Span
4395
+ }, text(line)]
4396
+ };
4397
+ }));
4398
+ return [{
4399
+ childCount: lines.length,
4400
+ className: ChatDebugViewEvent,
4401
+ type: Div
4402
+ }, ...lineNodes];
3734
4403
  };
3735
4404
 
3736
4405
  const getBucketUnitDom = (unitCount, presetValue) => {
@@ -3740,7 +4409,7 @@ const getBucketUnitDom = (unitCount, presetValue) => {
3740
4409
  'data-value': presetValue
3741
4410
  } : {}),
3742
4411
  childCount: 0,
3743
- className: joinClassNames(ChatDebugViewTimelineBucketUnit, ChatDebugViewTimelineBucketUnitEmpty),
4412
+ className: mergeClassNames(ChatDebugViewTimelineBucketUnit, ChatDebugViewTimelineBucketUnitEmpty),
3744
4413
  type: Div
3745
4414
  }];
3746
4415
  }
@@ -3760,13 +4429,13 @@ const getBucketDom = bucket => {
3760
4429
  const presetValue = `${formatTimelinePresetValue(bucket.startSeconds)}:${formatTimelinePresetValue(bucket.endSeconds)}`;
3761
4430
  return [{
3762
4431
  childCount: 1,
3763
- className: joinClassNames(ChatDebugViewTimelineBucket, bucket.isSelected && ChatDebugViewTimelineBucketSelected),
4432
+ className: mergeClassNames(ChatDebugViewTimelineBucket, bucket.isSelected ? ChatDebugViewTimelineBucketSelected : ''),
3764
4433
  'data-value': presetValue,
3765
4434
  onClick: HandleTimelineRangePreset,
3766
4435
  type: Div
3767
4436
  }, {
3768
4437
  childCount: bucket.unitCount === 0 ? 1 : bucket.unitCount,
3769
- className: joinClassNames(ChatDebugViewTimelineBucketBar, bucket.isSelected && ChatDebugViewTimelineBucketBarSelected),
4438
+ className: mergeClassNames(ChatDebugViewTimelineBucketBar, bucket.isSelected ? ChatDebugViewTimelineBucketBarSelected : ''),
3770
4439
  'data-value': presetValue,
3771
4440
  type: Div
3772
4441
  }, ...getBucketUnitDom(bucket.unitCount, presetValue)];
@@ -3785,6 +4454,96 @@ const getEffectiveTimelineRange = (timelineStartSeconds, timelineEndSeconds, tim
3785
4454
  };
3786
4455
  };
3787
4456
 
4457
+ const formatPercent = value => {
4458
+ return `${Number(value.toFixed(3))}%`;
4459
+ };
4460
+
4461
+ const getSelectionNodesDom = (hasSelection, selectionStartPercent, selectionEndPercent) => {
4462
+ if (!hasSelection || selectionStartPercent === null || selectionEndPercent === null) {
4463
+ return [];
4464
+ }
4465
+ return [{
4466
+ childCount: 0,
4467
+ className: ChatDebugViewTimelineSelectionRange,
4468
+ style: `left:${formatPercent(selectionStartPercent)};width:${formatPercent(selectionEndPercent - selectionStartPercent)};`,
4469
+ type: Div
4470
+ }, {
4471
+ childCount: 0,
4472
+ className: mergeClassNames(ChatDebugViewTimelineSelectionMarker, ChatDebugViewTimelineSelectionMarkerStart),
4473
+ style: `left:${formatPercent(selectionStartPercent)};`,
4474
+ type: Div
4475
+ }, {
4476
+ childCount: 0,
4477
+ className: mergeClassNames(ChatDebugViewTimelineSelectionMarker, ChatDebugViewTimelineSelectionMarkerEnd),
4478
+ style: `left:${formatPercent(selectionEndPercent)};`,
4479
+ type: Div
4480
+ }];
4481
+ };
4482
+
4483
+ const getSelectionPercent = (value, durationSeconds) => {
4484
+ if (durationSeconds <= 0) {
4485
+ return 0;
4486
+ }
4487
+ return Number((value / durationSeconds * 100).toFixed(3));
4488
+ };
4489
+
4490
+ const maxBarUnits = 8;
4491
+ const getTimelineInfo = (events, startValue, endValue) => {
4492
+ const eventsWithTime = getEventsWithTime(events);
4493
+ if (eventsWithTime.length === 0) {
4494
+ return {
4495
+ buckets: [],
4496
+ durationSeconds: 0,
4497
+ endSeconds: null,
4498
+ hasSelection: false,
4499
+ selectionEndPercent: null,
4500
+ selectionStartPercent: null,
4501
+ startSeconds: null
4502
+ };
4503
+ }
4504
+ const baseTime = eventsWithTime[0].time;
4505
+ const lastTime = eventsWithTime.at(-1)?.time ?? baseTime;
4506
+ const durationMs = Math.max(0, lastTime - baseTime);
4507
+ const durationSeconds = roundSeconds(durationMs / 1000);
4508
+ const range = getNormalizedRange(durationSeconds, startValue, endValue);
4509
+ const bucketCount = durationSeconds === 0 ? 1 : Math.max(12, Math.min(48, Math.ceil(durationSeconds)));
4510
+ const bucketDurationMs = durationMs === 0 ? 1000 : durationMs / bucketCount;
4511
+ const counts = Array.from({
4512
+ length: bucketCount
4513
+ }).fill(0);
4514
+ for (const item of eventsWithTime) {
4515
+ const offsetMs = item.time - baseTime;
4516
+ const index = durationMs === 0 ? 0 : Math.min(bucketCount - 1, Math.floor(offsetMs / durationMs * bucketCount));
4517
+ counts[index] += 1;
4518
+ }
4519
+ const maxCount = Math.max(...counts);
4520
+ const selectionStartPercent = range.hasSelection && range.startSeconds !== null ? getSelectionPercent(range.startSeconds, durationSeconds) : null;
4521
+ const selectionEndPercent = range.hasSelection && range.endSeconds !== null ? getSelectionPercent(range.endSeconds, durationSeconds) : null;
4522
+ const buckets = counts.map((count, index) => {
4523
+ const bucketStartMs = index * bucketDurationMs;
4524
+ const bucketEndMs = index === bucketCount - 1 ? durationMs : (index + 1) * bucketDurationMs;
4525
+ const hasSelection = range.hasSelection && range.startSeconds !== null && range.endSeconds !== null;
4526
+ const selectionStartMs = hasSelection ? range.startSeconds * 1000 : 0;
4527
+ const selectionEndMs = hasSelection ? range.endSeconds * 1000 : 0;
4528
+ return {
4529
+ count,
4530
+ endSeconds: roundSeconds(bucketEndMs / 1000),
4531
+ isSelected: hasSelection && bucketEndMs >= selectionStartMs && bucketStartMs <= selectionEndMs,
4532
+ startSeconds: roundSeconds(bucketStartMs / 1000),
4533
+ unitCount: count === 0 ? 0 : Math.max(1, Math.round(count / maxCount * maxBarUnits))
4534
+ };
4535
+ });
4536
+ return {
4537
+ buckets,
4538
+ durationSeconds,
4539
+ endSeconds: range.endSeconds,
4540
+ hasSelection: range.hasSelection,
4541
+ selectionEndPercent,
4542
+ selectionStartPercent,
4543
+ startSeconds: range.startSeconds
4544
+ };
4545
+ };
4546
+
3788
4547
  const formatTimelineSeconds = value => {
3789
4548
  if (Number.isInteger(value)) {
3790
4549
  return `${value}s`;
@@ -3795,9 +4554,9 @@ const formatTimelineSeconds = value => {
3795
4554
  const getTimelineSummary = (timelineEvents, timelineStartSeconds, timelineEndSeconds) => {
3796
4555
  const timelineInfo = getTimelineInfo(timelineEvents, timelineStartSeconds, timelineEndSeconds);
3797
4556
  if (timelineInfo.hasSelection && timelineInfo.startSeconds !== null && timelineInfo.endSeconds !== null) {
3798
- return `Window ${formatTimelineSeconds(timelineInfo.startSeconds)}-${formatTimelineSeconds(timelineInfo.endSeconds)} of ${formatTimelineSeconds(timelineInfo.durationSeconds)}`;
4557
+ return windowSummary(formatTimelineSeconds(timelineInfo.startSeconds), formatTimelineSeconds(timelineInfo.endSeconds), formatTimelineSeconds(timelineInfo.durationSeconds));
3799
4558
  }
3800
- return `Window 0s-${formatTimelineSeconds(timelineInfo.durationSeconds)} of ${formatTimelineSeconds(timelineInfo.durationSeconds)}`;
4559
+ return windowSummary('0s', formatTimelineSeconds(timelineInfo.durationSeconds), formatTimelineSeconds(timelineInfo.durationSeconds));
3801
4560
  };
3802
4561
 
3803
4562
  const getTimelineNodes = (timelineEvents, timelineStartSeconds, timelineEndSeconds, timelineSelectionActive = false, timelineSelectionAnchorSeconds = '', timelineSelectionFocusSeconds = '') => {
@@ -3806,25 +4565,11 @@ const getTimelineNodes = (timelineEvents, timelineStartSeconds, timelineEndSecon
3806
4565
  if (timelineInfo.buckets.length === 0) {
3807
4566
  return [];
3808
4567
  }
3809
- const selectionNodes = timelineInfo.hasSelection && timelineInfo.selectionStartPercent !== null && timelineInfo.selectionEndPercent !== null ? [{
3810
- childCount: 0,
3811
- className: ChatDebugViewTimelineSelectionRange,
3812
- style: `left:${formatPercent(timelineInfo.selectionStartPercent)};width:${formatPercent(timelineInfo.selectionEndPercent - timelineInfo.selectionStartPercent)};`,
3813
- type: Div
3814
- }, {
3815
- childCount: 0,
3816
- className: joinClassNames(ChatDebugViewTimelineSelectionMarker, ChatDebugViewTimelineSelectionMarkerStart),
3817
- style: `left:${formatPercent(timelineInfo.selectionStartPercent)};`,
3818
- type: Div
3819
- }, {
3820
- childCount: 0,
3821
- className: joinClassNames(ChatDebugViewTimelineSelectionMarker, ChatDebugViewTimelineSelectionMarkerEnd),
3822
- style: `left:${formatPercent(timelineInfo.selectionEndPercent)};`,
3823
- type: Div
3824
- }] : [];
4568
+ const selectionNodes = getSelectionNodesDom(timelineInfo.hasSelection, timelineInfo.selectionStartPercent, timelineInfo.selectionEndPercent);
3825
4569
  return [{
3826
4570
  childCount: 2,
3827
4571
  className: ChatDebugViewTimeline,
4572
+ onContextMenu: HandleTimelineContextMenu,
3828
4573
  type: Section
3829
4574
  }, {
3830
4575
  childCount: 1,
@@ -3833,7 +4578,7 @@ const getTimelineNodes = (timelineEvents, timelineStartSeconds, timelineEndSecon
3833
4578
  }, {
3834
4579
  childCount: 1,
3835
4580
  className: ChatDebugViewTimelineSummary,
3836
- type: Div
4581
+ type: H2
3837
4582
  }, text(getTimelineSummary(timelineEvents, effectiveRange.startSeconds, effectiveRange.endSeconds)), {
3838
4583
  childCount: 2,
3839
4584
  className: ChatDebugViewTimelineInteractive,
@@ -3851,27 +4596,30 @@ const getTimelineNodes = (timelineEvents, timelineStartSeconds, timelineEndSecon
3851
4596
  }, ...selectionNodes];
3852
4597
  };
3853
4598
 
3854
- const getDevtoolsDom = (events, selectedEvent, selectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage = 'No events have been found', timelineSelectionActive = false, timelineSelectionAnchorSeconds = '', timelineSelectionFocusSeconds = '', selectedDetailTab = Response) => {
3855
- const rowNodes = getDevtoolsRows(events, selectedEventIndex);
4599
+ const getDevtoolsDom = (events, selectedEvent, selectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage = noEventsFound(), timelineSelectionActive = false, timelineSelectionAnchorSeconds = '', timelineSelectionFocusSeconds = '', selectedDetailTab = Response, visibleTableColumns = defaultVisibleTableColumns, detailTabs = createDetailTabs()) => {
4600
+ const rowNodes = getDevtoolsRows(events, selectedEventIndex, visibleTableColumns);
3856
4601
  const timelineNodes = getTimelineNodes(timelineEvents, timelineStartSeconds, timelineEndSeconds, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds);
3857
- const previewEventNodes = selectedEvent ? getEventNode(getPreviewEvent(selectedEvent)) : [];
4602
+ const previewEvent = selectedEvent ? getPreviewEvent(selectedEvent) : undefined;
4603
+ const previewEventNodes = typeof previewEvent === 'string' ? getTextNode(previewEvent) : previewEvent === undefined ? [] : getEventNode(previewEvent);
4604
+ const payloadEventNodes = selectedEvent ? getEventNode(getPayloadEvent(selectedEvent)) : [];
3858
4605
  const responseEventNodes = selectedEvent ? getEventNode(selectedEvent) : [];
3859
4606
  const hasSelectedEvent = responseEventNodes.length > 0;
3860
- const tableNodes = events.length === 0 ? getEmptyStateDom(emptyMessage) : getTableDom(rowNodes, events.length);
4607
+ const tableNodes = events.length === 0 ? getEmptyStateDom(emptyMessage) : getTableDom(rowNodes, events.length, visibleTableColumns);
3861
4608
  const eventsClassName = getEventsClassName(hasSelectedEvent);
3862
- const detailsNodes = getDetailsDom(previewEventNodes, responseEventNodes, selectedEvent, isDetailTab(selectedDetailTab) ? selectedDetailTab : Response);
4609
+ const safeSelectedDetailTab = getSelectedDetailTab(detailTabs, selectedDetailTab);
4610
+ const detailsNodes = getDetailsDom(previewEventNodes, payloadEventNodes, responseEventNodes, selectedEvent, detailTabs, safeSelectedDetailTab);
3863
4611
  const sashNodes = getSashNodesDom(hasSelectedEvent);
3864
4612
  const splitChildCount = hasSelectedEvent ? 3 : 1;
3865
4613
  const mainChildCount = 1 + (timelineNodes.length > 0 ? 1 : 0);
3866
4614
  return [{
3867
4615
  childCount: mainChildCount,
3868
4616
  className: ChatDebugViewDevtoolsMain,
3869
- role: 'none',
4617
+ role: None,
3870
4618
  type: Div
3871
4619
  }, ...timelineNodes, {
3872
4620
  childCount: splitChildCount,
3873
4621
  className: ChatDebugViewDevtoolsSplit,
3874
- role: 'none',
4622
+ role: None,
3875
4623
  type: Div
3876
4624
  }, {
3877
4625
  childCount: 1,
@@ -3883,6 +4631,13 @@ const getDevtoolsDom = (events, selectedEvent, selectedEventIndex, timelineEvent
3883
4631
  }, ...tableNodes, ...sashNodes, ...detailsNodes];
3884
4632
  };
3885
4633
 
4634
+ const getEmptyMessage = (eventCount, hasFilterValue, useNoToolCallEventsMessage, noFilteredEventsMessage) => {
4635
+ if (eventCount === 0 && hasFilterValue) {
4636
+ return useNoToolCallEventsMessage ? noToolCallEvents() : noFilteredEventsMessage;
4637
+ }
4638
+ return noEventsFound();
4639
+ };
4640
+
3886
4641
  const getLegacyEventsDom = (errorMessage, emptyMessage, eventNodes) => {
3887
4642
  return [{
3888
4643
  childCount: eventNodes.length === 0 ? 1 : eventNodes.length,
@@ -3897,16 +4652,16 @@ const getLegacyEventsDom = (errorMessage, emptyMessage, eventNodes) => {
3897
4652
  }, text(errorMessage || emptyMessage)] : eventNodes)];
3898
4653
  };
3899
4654
 
3900
- const getQuickFilterNodes = (eventCategoryFilter, eventCategoryFilterOptions) => {
4655
+ const getQuickFilterNodes = (eventCategoryFilter, categoryFilters) => {
3901
4656
  return [{
3902
- childCount: eventCategoryFilterOptions.length,
4657
+ childCount: categoryFilters.length,
3903
4658
  className: ChatDebugViewQuickFilters,
3904
4659
  type: Div
3905
- }, ...eventCategoryFilterOptions.flatMap(option => {
3906
- const isSelected = option.value === eventCategoryFilter;
4660
+ }, ...categoryFilters.flatMap(categoryFilter => {
4661
+ const isSelected = categoryFilter.name === eventCategoryFilter;
3907
4662
  return [{
3908
4663
  childCount: 2,
3909
- className: joinClassNames(ChatDebugViewQuickFilterPill, isSelected && ChatDebugViewQuickFilterPillSelected),
4664
+ className: mergeClassNames(ChatDebugViewQuickFilterPill, isSelected ? ChatDebugViewQuickFilterPillSelected : ''),
3910
4665
  type: Label
3911
4666
  }, {
3912
4667
  checked: isSelected,
@@ -3916,8 +4671,8 @@ const getQuickFilterNodes = (eventCategoryFilter, eventCategoryFilterOptions) =>
3916
4671
  name: EventCategoryFilter,
3917
4672
  onChange: HandleEventCategoryFilter,
3918
4673
  type: Input,
3919
- value: option.value
3920
- }, text(option.label)];
4674
+ value: categoryFilter.name
4675
+ }, text(categoryFilter.label)];
3921
4676
  })];
3922
4677
  };
3923
4678
 
@@ -3925,18 +4680,18 @@ const getTimelineFilterDescription = (timelineStartSeconds, timelineEndSeconds)
3925
4680
  const trimmedStart = timelineStartSeconds.trim();
3926
4681
  const trimmedEnd = timelineEndSeconds.trim();
3927
4682
  if (trimmedStart && trimmedEnd) {
3928
- return `${trimmedStart}s-${trimmedEnd}s`;
4683
+ return secondsRange(trimmedStart, trimmedEnd);
3929
4684
  }
3930
4685
  if (trimmedStart) {
3931
- return `from ${trimmedStart}s`;
4686
+ return fromSeconds(trimmedStart);
3932
4687
  }
3933
4688
  if (trimmedEnd) {
3934
- return `to ${trimmedEnd}s`;
4689
+ return toSeconds(trimmedEnd);
3935
4690
  }
3936
4691
  return '';
3937
4692
  };
3938
4693
 
3939
- const getChatDebugViewDom = (errorMessage, filterValue, eventCategoryFilter, eventCategoryFilterOptions, _showEventStreamFinishedEvents, _showInputEvents, _showResponsePartEvents, useDevtoolsLayout, selectedEvent, selectedEventIndex, timelineStartSeconds, timelineEndSeconds, timelineEvents, events, timelineSelectionActive = false, timelineSelectionAnchorSeconds = '', timelineSelectionFocusSeconds = '', selectedDetailTab = Response) => {
4694
+ const getChatDebugViewDom = (errorMessage, filterValue, eventCategoryFilter, categoryFilters, _showEventStreamFinishedEvents, _showInputEvents, _showResponsePartEvents, useDevtoolsLayout, selectedEvent, selectedEventIndex, timelineStartSeconds, timelineEndSeconds, timelineEvents, events, timelineSelectionActive = false, timelineSelectionAnchorSeconds = '', timelineSelectionFocusSeconds = '', selectedDetailTab = Response, visibleTableColumns = defaultVisibleTableColumns, detailTabs = createDetailTabs()) => {
3940
4695
  if (errorMessage) {
3941
4696
  return getDebugErrorDom(errorMessage);
3942
4697
  }
@@ -3955,17 +4710,17 @@ const getChatDebugViewDom = (errorMessage, filterValue, eventCategoryFilter, eve
3955
4710
  const hasTimelineFilter = Boolean(timelineFilterDescription);
3956
4711
  const hasFilterValue = filterDescriptionParts.length > 0;
3957
4712
  const filterDescription = filterDescriptionParts.join(' ');
3958
- const noFilteredEventsMessage = `no events found matching ${filterDescription}`;
4713
+ const noFilteredEventsMessage = noEventsFoundMatching(filterDescription);
3959
4714
  const useNoToolCallEventsMessage = eventCategoryFilter === Tools && !trimmedFilterValue && !hasTimelineFilter;
3960
- const emptyMessage = events.length === 0 && hasFilterValue ? useNoToolCallEventsMessage ? 'No tool call events.' : noFilteredEventsMessage : 'No events have been found';
4715
+ const emptyMessage = getEmptyMessage(events.length, hasFilterValue, useNoToolCallEventsMessage, noFilteredEventsMessage);
3961
4716
  const safeSelectedEventIndex = selectedEventIndex === null || selectedEventIndex < 0 || selectedEventIndex >= events.length ? null : selectedEventIndex;
3962
- const contentNodes = useDevtoolsLayout ? getDevtoolsDom(events, selectedEvent, safeSelectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds, isDetailTab(selectedDetailTab) ? selectedDetailTab : Response) : getLegacyEventsDom(errorMessage, emptyMessage, events.flatMap(getEventNode));
3963
- const quickFilterNodes = useDevtoolsLayout ? getQuickFilterNodes(eventCategoryFilter, eventCategoryFilterOptions) : [];
4717
+ const contentNodes = useDevtoolsLayout ? getDevtoolsDom(events, selectedEvent, safeSelectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds, getSelectedDetailTab(detailTabs, selectedDetailTab), visibleTableColumns, detailTabs) : getLegacyEventsDom(errorMessage, emptyMessage, events.flatMap(getEventNode));
4718
+ const quickFilterNodes = useDevtoolsLayout ? getQuickFilterNodes(eventCategoryFilter, categoryFilters) : [];
3964
4719
  const debugViewTopDom = getDebugViewTopDom(filterValue, useDevtoolsLayout, quickFilterNodes);
3965
4720
  const rootChildCount = 2;
3966
4721
  return [{
3967
4722
  childCount: rootChildCount,
3968
- className: joinClassNames(ChatDebugView, useDevtoolsLayout && ChatDebugViewDevtools),
4723
+ className: mergeClassNames(ChatDebugView, useDevtoolsLayout ? ChatDebugViewDevtools : ''),
3969
4724
  type: Div
3970
4725
  }, ...debugViewTopDom, ...contentNodes];
3971
4726
  };
@@ -3984,7 +4739,7 @@ const renderItems = (oldState, newState) => {
3984
4739
  }
3985
4740
  const timelineEvents = getTimelineEvents(newState);
3986
4741
  const filteredEvents = filterEventsByTimelineRange(timelineEvents, newState.timelineStartSeconds, newState.timelineEndSeconds);
3987
- const dom = getChatDebugViewDom(newState.errorMessage, newState.filterValue, newState.eventCategoryFilter, newState.eventCategoryFilterOptions, newState.showEventStreamFinishedEvents, newState.showInputEvents, newState.showResponsePartEvents, newState.useDevtoolsLayout, newState.selectedEvent, newState.selectedEventIndex, newState.timelineStartSeconds, newState.timelineEndSeconds, withSessionEventIds(timelineEvents), withSessionEventIds(filteredEvents), newState.timelineSelectionActive, newState.timelineSelectionAnchorSeconds, newState.timelineSelectionFocusSeconds, newState.selectedDetailTab);
4742
+ const dom = getChatDebugViewDom(newState.errorMessage, newState.filterValue, newState.eventCategoryFilter, newState.categoryFilters, newState.showEventStreamFinishedEvents, newState.showInputEvents, newState.showResponsePartEvents, newState.useDevtoolsLayout, newState.selectedEvent, newState.selectedEventIndex, newState.timelineStartSeconds, newState.timelineEndSeconds, withSessionEventIds(timelineEvents), withSessionEventIds(filteredEvents), newState.timelineSelectionActive, newState.timelineSelectionAnchorSeconds, newState.timelineSelectionFocusSeconds, newState.selectedDetailTab, newState.visibleTableColumns, newState.detailTabs);
3988
4743
  return [SetDom2, newState.uid, dom];
3989
4744
  };
3990
4745
 
@@ -4032,7 +4787,7 @@ const render2 = (uid, diffResult) => {
4032
4787
  const renderEventListeners = () => {
4033
4788
  return [{
4034
4789
  name: HandleHeaderContextMenu,
4035
- params: ['handleHeaderContextMenu'],
4790
+ params: ['handleHeaderContextMenu', ClientX, ClientY],
4036
4791
  preventDefault: true
4037
4792
  }, {
4038
4793
  name: HandleEventRowClick,
@@ -4045,6 +4800,14 @@ const renderEventListeners = () => {
4045
4800
  name: HandleDetailsContextMenu,
4046
4801
  params: ['handleDetailsContextMenu'],
4047
4802
  preventDefault: true
4803
+ }, {
4804
+ name: HandleDetailsTopContextMenu,
4805
+ params: ['handleDetailsTopContextMenu'],
4806
+ preventDefault: true
4807
+ }, {
4808
+ name: HandleTimelineContextMenu,
4809
+ params: ['handleTimelineContextMenu'],
4810
+ preventDefault: true
4048
4811
  }, {
4049
4812
  name: HandleFilterInput,
4050
4813
  params: ['handleInput', TargetName, TargetValue]
@@ -4052,8 +4815,8 @@ const renderEventListeners = () => {
4052
4815
  name: HandleEventCategoryFilter,
4053
4816
  params: ['handleEventCategoryFilter', TargetValue]
4054
4817
  }, {
4055
- name: HandleDetailTab,
4056
- params: ['handleDetailTab', TargetValue]
4818
+ name: SelectDetailTab,
4819
+ params: ['selectDetailTab', TargetValue]
4057
4820
  }, {
4058
4821
  name: HandleTimelineRangePreset,
4059
4822
  params: ['handleTimelineRangePreset', 'event.target.dataset.value']
@@ -4076,6 +4839,16 @@ const renderEventListeners = () => {
4076
4839
  }, {
4077
4840
  name: HandleSashPointerUp,
4078
4841
  params: ['handleSashPointerUp', ClientX, ClientY]
4842
+ }, {
4843
+ name: HandleTableResizerPointerDown,
4844
+ params: ['handleTableResizerPointerDown', TargetName, ClientX],
4845
+ trackPointerEvents: [HandleTableResizerPointerMove, HandleTableResizerPointerUp]
4846
+ }, {
4847
+ name: HandleTableResizerPointerMove,
4848
+ params: ['handleTableResizerPointerMove', ClientX]
4849
+ }, {
4850
+ name: HandleTableResizerPointerUp,
4851
+ params: ['handleTableResizerPointerUp']
4079
4852
  }, {
4080
4853
  name: HandleTimelinePointerDown,
4081
4854
  params: ['handleTimelinePointerDown', ClientX],
@@ -4096,6 +4869,21 @@ const rerender = state => {
4096
4869
  return structuredClone(state);
4097
4870
  };
4098
4871
 
4872
+ const isSameVisibleTableColumns = (a, b) => {
4873
+ return a.length === b.length && a.every((value, index) => value === b[index]);
4874
+ };
4875
+
4876
+ const resetTableColumns = state => {
4877
+ if (isSameVisibleTableColumns(state.visibleTableColumns, defaultVisibleTableColumns) && isSameTableColumnWidths(state.tableColumnWidths, defaultTableColumnWidths)) {
4878
+ return state;
4879
+ }
4880
+ return {
4881
+ ...state,
4882
+ tableColumnWidths: defaultTableColumnWidths,
4883
+ visibleTableColumns: defaultVisibleTableColumns
4884
+ };
4885
+ };
4886
+
4099
4887
  const handleResize = (state, dimensions) => {
4100
4888
  const nextState = {
4101
4889
  ...state,
@@ -4124,8 +4912,10 @@ const saveState = state => {
4124
4912
  selectedDetailTab,
4125
4913
  selectedEventId,
4126
4914
  sessionId,
4915
+ tableColumnWidths,
4127
4916
  timelineEndSeconds,
4128
- timelineStartSeconds
4917
+ timelineStartSeconds,
4918
+ visibleTableColumns
4129
4919
  } = state;
4130
4920
  return {
4131
4921
  eventCategoryFilter,
@@ -4133,8 +4923,10 @@ const saveState = state => {
4133
4923
  selectedDetailTab,
4134
4924
  selectedEventId,
4135
4925
  sessionId,
4926
+ tableColumnWidths,
4136
4927
  timelineEndSeconds,
4137
- timelineStartSeconds
4928
+ timelineStartSeconds,
4929
+ visibleTableColumns
4138
4930
  };
4139
4931
  };
4140
4932
 
@@ -4154,7 +4946,13 @@ const setSessionIdDependencies = {
4154
4946
  listChatViewEvents: listChatViewEvents
4155
4947
  };
4156
4948
  const setSessionId = async (state, sessionId) => {
4157
- const result = await setSessionIdDependencies.listChatViewEvents(sessionId, state.databaseName, state.dataBaseVersion, state.eventStoreName, state.sessionIdIndexName);
4949
+ const {
4950
+ databaseName,
4951
+ dataBaseVersion,
4952
+ eventStoreName,
4953
+ sessionIdIndexName
4954
+ } = state;
4955
+ const result = await setSessionIdDependencies.listChatViewEvents(sessionId, databaseName, dataBaseVersion, eventStoreName, sessionIdIndexName);
4158
4956
  if (result.type === 'error') {
4159
4957
  return {
4160
4958
  ...state,
@@ -4182,16 +4980,33 @@ const setSessionId = async (state, sessionId) => {
4182
4980
  };
4183
4981
  };
4184
4982
 
4983
+ const toggleTableColumnVisibility = (state, column) => {
4984
+ if (!isTableColumn(column)) {
4985
+ return state;
4986
+ }
4987
+ const nextVisibleColumns = new Set(state.visibleTableColumns);
4988
+ if (nextVisibleColumns.has(column)) {
4989
+ nextVisibleColumns.delete(column);
4990
+ } else {
4991
+ nextVisibleColumns.add(column);
4992
+ }
4993
+ return {
4994
+ ...state,
4995
+ visibleTableColumns: getOrderedVisibleTableColumns([...nextVisibleColumns])
4996
+ };
4997
+ };
4998
+
4185
4999
  const commandMap = {
4186
5000
  'ChatDebug.appendStoredEventForTest': wrapCommand(appendStoredEventForTest),
4187
5001
  'ChatDebug.create': create,
4188
5002
  'ChatDebug.diff2': diff2,
4189
5003
  'ChatDebug.getCommandIds': getCommandIds,
5004
+ 'ChatDebug.getMenuEntries': wrapGetter(getMenuEntries2),
4190
5005
  'ChatDebug.getMenuIds': getMenuIds,
4191
5006
  'ChatDebug.handleClickRefresh': wrapCommand(handleClickRefresh),
4192
5007
  'ChatDebug.handleCloseDetails': wrapCommand(handleCloseDetails),
4193
5008
  'ChatDebug.handleDetailsContextMenu': wrapCommand(handleDetailsContextMenu),
4194
- 'ChatDebug.handleDetailTab': wrapCommand(handleDetailTab),
5009
+ 'ChatDebug.handleDetailsTopContextMenu': wrapCommand(handleDetailsTopContextMenu),
4195
5010
  'ChatDebug.handleEventCategoryFilter': wrapCommand(handleEventCategoryFilter),
4196
5011
  'ChatDebug.handleEventRowClick': wrapCommand(handleEventRowClick),
4197
5012
  'ChatDebug.handleHeaderContextMenu': wrapCommand(handleHeaderContextMenu),
@@ -4203,6 +5018,11 @@ const commandMap = {
4203
5018
  'ChatDebug.handleShowInputEvents': wrapCommand(handleShowInputEvents),
4204
5019
  'ChatDebug.handleShowResponsePartEvents': wrapCommand(handleShowResponsePartEvents),
4205
5020
  'ChatDebug.handleTableBodyContextMenu': wrapCommand(handleTableBodyContextMenu),
5021
+ 'ChatDebug.handleTableResizerPointerDown': wrapCommand(handleTableResizerPointerDown),
5022
+ 'ChatDebug.handleTableResizerPointerMove': wrapCommand(handleTableResizerPointerMove),
5023
+ 'ChatDebug.handleTableResizerPointerUp': wrapCommand(handleTableResizerPointerUp),
5024
+ 'ChatDebug.handleTableRowCopy': wrapCommand(handleTableRowCopy),
5025
+ 'ChatDebug.handleTimelineContextMenu': wrapCommand(handleTimelineContextMenu),
4206
5026
  'ChatDebug.handleTimelineDoubleClick': wrapCommand(handleTimelineDoubleClick),
4207
5027
  'ChatDebug.handleTimelineEndSeconds': wrapCommand(handleTimelineEndSeconds),
4208
5028
  'ChatDebug.handleTimelinePointerDown': wrapCommand(handleTimelinePointerDown),
@@ -4210,18 +5030,21 @@ const commandMap = {
4210
5030
  'ChatDebug.handleTimelinePointerUp': wrapCommand(handleTimelinePointerUp),
4211
5031
  'ChatDebug.handleTimelineRangePreset': wrapCommand(handleTimelineRangePreset),
4212
5032
  'ChatDebug.handleTimelineStartSeconds': wrapCommand(handleTimelineStartSeconds),
4213
- 'ChatDebug.handleUseDevtoolsLayout': wrapCommand(handleUseDevtoolsLayout),
5033
+ 'ChatDebug.handleUseDevtoolsLayout': wrapCommand(setUseDevtoolsLayout),
4214
5034
  'ChatDebug.loadContent': wrapCommand(loadContent),
4215
5035
  'ChatDebug.loadContent2': wrapCommand(loadContent),
4216
5036
  'ChatDebug.refresh': wrapCommand(refresh),
4217
5037
  'ChatDebug.render2': render2,
4218
5038
  'ChatDebug.renderEventListeners': renderEventListeners,
4219
5039
  'ChatDebug.rerender': wrapCommand(rerender),
5040
+ 'ChatDebug.resetTableColumns': wrapCommand(resetTableColumns),
4220
5041
  'ChatDebug.resize': wrapCommand(resize),
4221
5042
  'ChatDebug.saveState': wrapGetter(saveState),
5043
+ 'ChatDebug.selectDetailTab': wrapCommand(selectDetailTab),
4222
5044
  'ChatDebug.setEvents': wrapCommand(setEvents),
4223
5045
  'ChatDebug.setSessionId': wrapCommand(setSessionId),
4224
- 'ChatDebug.terminate': terminate
5046
+ 'ChatDebug.terminate': terminate,
5047
+ 'ChatDebug.toggleTableColumnVisibility': wrapCommand(toggleTableColumnVisibility)
4225
5048
  };
4226
5049
 
4227
5050
  const sendMessagePortToChatStorageWorker = async port => {