@lvce-editor/chat-debug-view 8.0.0 → 10.0.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.
@@ -1117,11 +1117,17 @@ const create$2 = rpcId => {
1117
1117
  };
1118
1118
  };
1119
1119
 
1120
+ const ListBox = 'listbox';
1121
+ const Option = 'option';
1122
+ const Tab = 'tab';
1123
+
1120
1124
  const Button$1 = 1;
1125
+ const Col = 2;
1126
+ const ColGroup = 3;
1121
1127
  const Div = 4;
1122
1128
  const Input = 6;
1123
1129
  const Span = 8;
1124
- const Table = 9;
1130
+ const Table$1 = 9;
1125
1131
  const TBody = 10;
1126
1132
  const Td = 11;
1127
1133
  const Text = 12;
@@ -1129,9 +1135,9 @@ const Th = 13;
1129
1135
  const THead = 14;
1130
1136
  const Tr = 15;
1131
1137
  const Img = 17;
1132
- const H2 = 22;
1133
1138
  const Section = 41;
1134
1139
  const Search = 42;
1140
+ const TextArea = 62;
1135
1141
  const Reference = 100;
1136
1142
 
1137
1143
  const Button = 'event.button';
@@ -1147,8 +1153,10 @@ const Unchecked = 3;
1147
1153
  const ChatStorageWorker = 6003;
1148
1154
  const RendererWorker = 1;
1149
1155
 
1156
+ const FocusSelector = 'Viewlet.focusSelector';
1150
1157
  const SetCss = 'Viewlet.setCss';
1151
1158
  const SetDom2 = 'Viewlet.setDom2';
1159
+ const SetFocusContext = 'Viewlet.setFocusContext';
1152
1160
  const SetPatches = 'Viewlet.setPatches';
1153
1161
 
1154
1162
  const {
@@ -1174,6 +1182,9 @@ const sendMessagePortToChatStorageWorker$1 = async port => {
1174
1182
  const writeClipBoardText = async text => {
1175
1183
  await invoke('ClipBoard.writeText', /* text */text);
1176
1184
  };
1185
+ const getPreference = async key => {
1186
+ return await invoke('Preferences.get', key);
1187
+ };
1177
1188
 
1178
1189
  const toCommandId = key => {
1179
1190
  const dotIndex = key.indexOf('.');
@@ -1310,6 +1321,54 @@ const appendStoredEventForTest = async (state, event) => {
1310
1321
  return state;
1311
1322
  };
1312
1323
 
1324
+ const decodeBase64$1 = value => {
1325
+ const decoded = atob(value);
1326
+ const bytes = new Uint8Array(decoded.length);
1327
+ for (let i = 0; i < decoded.length; i++) {
1328
+ bytes[i] = decoded.codePointAt(i) || 0;
1329
+ }
1330
+ return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
1331
+ };
1332
+ const createCanvasBlob$1 = async mimeType => {
1333
+ const canvas = new OffscreenCanvas(2, 2);
1334
+ const context = canvas.getContext('2d');
1335
+ if (!context) {
1336
+ throw new Error('2d canvas context is not available');
1337
+ }
1338
+ context.fillStyle = '#0b6';
1339
+ context.fillRect(0, 0, 2, 2);
1340
+ return canvas.convertToBlob({
1341
+ type: mimeType
1342
+ });
1343
+ };
1344
+ const createBlob$1 = async (mimeType, contentKind, content) => {
1345
+ if (contentKind === 'canvas') {
1346
+ return createCanvasBlob$1(mimeType);
1347
+ }
1348
+ if (contentKind === 'base64') {
1349
+ return new Blob([decodeBase64$1(content)], {
1350
+ type: mimeType
1351
+ });
1352
+ }
1353
+ return new Blob([content], {
1354
+ type: mimeType
1355
+ });
1356
+ };
1357
+ const appendStoredImageAttachmentForTest = async (state, sessionId, eventId, mimeType, name, contentKind, content, timestamp) => {
1358
+ const blob = await createBlob$1(mimeType, contentKind, content);
1359
+ await appendEvent({
1360
+ attachmentId: `attachment-${eventId}`,
1361
+ blob,
1362
+ eventId,
1363
+ mimeType,
1364
+ name,
1365
+ sessionId,
1366
+ timestamp,
1367
+ type: 'chat-attachment-added'
1368
+ });
1369
+ return state;
1370
+ };
1371
+
1313
1372
  const decodeBase64 = value => {
1314
1373
  const decoded = atob(value);
1315
1374
  const bytes = new Uint8Array(decoded.length);
@@ -1343,7 +1402,7 @@ const createBlob = async (mimeType, contentKind, content) => {
1343
1402
  type: mimeType
1344
1403
  });
1345
1404
  };
1346
- const appendStoredImageAttachmentForTest = async (state, sessionId, eventId, mimeType, name, contentKind, content, timestamp) => {
1405
+ const appendStoredRemovedImageAttachmentForTest = async (state, sessionId, eventId, mimeType, name, contentKind, content, timestamp) => {
1347
1406
  const blob = await createBlob(mimeType, contentKind, content);
1348
1407
  await appendEvent({
1349
1408
  attachmentId: `attachment-${eventId}`,
@@ -1353,7 +1412,7 @@ const appendStoredImageAttachmentForTest = async (state, sessionId, eventId, mim
1353
1412
  name,
1354
1413
  sessionId,
1355
1414
  timestamp,
1356
- type: 'chat-attachment-added'
1415
+ type: 'chat-attachment-removed'
1357
1416
  });
1358
1417
  return state;
1359
1418
  };
@@ -1374,7 +1433,7 @@ const All$1 = 'All';
1374
1433
  const CloseDetails$1 = 'Close details';
1375
1434
  const Copy = 'Copy';
1376
1435
  const DetailSections = 'Detail sections';
1377
- const Duration$1 = 'Duration';
1436
+ const Duration$1 = 'Time';
1378
1437
  const Ended = 'Ended';
1379
1438
  const FailedToLoadChatDebugSession = 'Failed to load chat debug session "{PH1}". Please try again.';
1380
1439
  const FailedToLoadChatDebugSessionWithError = 'Failed to load chat debug session "{PH1}": {PH2}';
@@ -1398,8 +1457,10 @@ const ResetColumns = 'Reset columns';
1398
1457
  const Response$1 = 'Response';
1399
1458
  const SecondsRange = '{PH1}s-{PH2}s';
1400
1459
  const Started = 'Started';
1401
- const Status$1 = 'Status';
1460
+ const Status$2 = 'Status';
1402
1461
  const Stream$1 = 'Stream';
1462
+ const TableSummaryPlural = '{PH1} events, {PH2} from start to finish';
1463
+ const TableSummarySingular = '{PH1} event, {PH2} from start to finish';
1403
1464
  const Timing$1 = 'Timing';
1404
1465
  const ToSeconds = 'to {PH1}s';
1405
1466
  const Tools$1 = 'Tools';
@@ -1413,7 +1474,7 @@ const copy = () => {
1413
1474
  return i18nString(Copy);
1414
1475
  };
1415
1476
  const status = () => {
1416
- return i18nString(Status$1);
1477
+ return i18nString(Status$2);
1417
1478
  };
1418
1479
  const all = () => {
1419
1480
  return i18nString(All$1);
@@ -1516,6 +1577,12 @@ const stream = () => {
1516
1577
  const timing = () => {
1517
1578
  return i18nString(Timing$1);
1518
1579
  };
1580
+ const tableSummary = (eventCount, duration) => {
1581
+ return i18nString(eventCount === 1 ? TableSummarySingular : TableSummaryPlural, {
1582
+ PH1: String(eventCount),
1583
+ PH2: duration
1584
+ });
1585
+ };
1519
1586
  const toSeconds = seconds => {
1520
1587
  return i18nString(ToSeconds, {
1521
1588
  PH1: seconds
@@ -1632,13 +1699,9 @@ const selectDetailTab$1 = (detailTabs, selectedDetailTab) => {
1632
1699
  return detailTabs;
1633
1700
  }
1634
1701
  return detailTabs.map(detailTab => {
1635
- const isSelectedProperty = detailTab.name === selectedDetailTab;
1636
- if (detailTab.isSelected === isSelectedProperty) {
1637
- return detailTab;
1638
- }
1639
1702
  return {
1640
1703
  ...detailTab,
1641
- isSelected: isSelectedProperty
1704
+ isSelected: detailTab.name === selectedDetailTab
1642
1705
  };
1643
1706
  });
1644
1707
  };
@@ -1765,30 +1828,43 @@ const parseFilterValue = filterValue => {
1765
1828
 
1766
1829
  const Type = 'type';
1767
1830
  const Duration = 'duration';
1768
- const Status = 'status';
1769
- const tableColumnNames = [Type, Duration, Status];
1831
+ const Status$1 = 'status';
1832
+ const tableColumnNames = [Type, Status$1, Duration];
1770
1833
  const createTableColumns = () => {
1771
1834
  return [{
1835
+ isVisible: true,
1772
1836
  label: type(),
1773
1837
  name: Type
1774
1838
  }, {
1839
+ isVisible: true,
1840
+ label: status(),
1841
+ name: Status$1
1842
+ }, {
1843
+ isVisible: true,
1775
1844
  label: duration(),
1776
1845
  name: Duration
1777
- }, {
1778
- label: status(),
1779
- name: Status
1780
1846
  }];
1781
1847
  };
1782
1848
  const defaultVisibleTableColumns = tableColumnNames;
1783
1849
  const isTableColumn = value => {
1784
1850
  return tableColumnNames.includes(value);
1785
1851
  };
1852
+ const getVisibleTableColumns = tableColumns => {
1853
+ return tableColumns.filter(column => column.isVisible).map(column => column.name);
1854
+ };
1855
+ const getTableColumnsWithVisibility = (tableColumns, visibleTableColumns) => {
1856
+ const visibleColumns = new Set(visibleTableColumns.filter(isTableColumn));
1857
+ return tableColumns.map(column => ({
1858
+ ...column,
1859
+ isVisible: visibleColumns.has(column.name)
1860
+ }));
1861
+ };
1786
1862
  const getOrderedVisibleTableColumns = (values, tableColumns = createTableColumns()) => {
1787
1863
  const visibleColumns = new Set(values.filter(isTableColumn));
1788
1864
  return tableColumns.map(column => column.name).filter(column => visibleColumns.has(column));
1789
1865
  };
1790
- const isVisibleTableColumn = (visibleTableColumns, column) => {
1791
- return visibleTableColumns.includes(column);
1866
+ const isVisibleTableColumn = (tableColumns, column) => {
1867
+ return tableColumns.some(tableColumn => tableColumn.name === column && tableColumn.isVisible);
1792
1868
  };
1793
1869
  const getTableColumnLabel = (tableColumns, name) => {
1794
1870
  const match = tableColumns.find(column => column.name === name);
@@ -1798,7 +1874,7 @@ const getTableColumnLabel = (tableColumns, name) => {
1798
1874
  switch (name) {
1799
1875
  case Duration:
1800
1876
  return duration();
1801
- case Status:
1877
+ case Status$1:
1802
1878
  return status();
1803
1879
  case Type:
1804
1880
  return type();
@@ -1840,7 +1916,14 @@ const getTableWidthFromClientX = (viewX, width, clientX) => {
1840
1916
  return clampTableWidth(width, nextTableWidth);
1841
1917
  };
1842
1918
 
1843
- const minimumTableColumnWidth = 80;
1919
+ const minimumTableColumnWidths = {
1920
+ [Duration]: 80,
1921
+ [Status$1]: 56,
1922
+ [Type]: 80
1923
+ };
1924
+ const getMinimumTableColumnWidth = column => {
1925
+ return minimumTableColumnWidths[column];
1926
+ };
1844
1927
 
1845
1928
  const getTableColumnLayout = (tableWidth, visibleTableColumns, tableColumnWidths) => {
1846
1929
  const visibleColumns = getOrderedVisibleTableColumns(visibleTableColumns);
@@ -1854,19 +1937,19 @@ const getTableColumnLayout = (tableWidth, visibleTableColumns, tableColumnWidths
1854
1937
  }
1855
1938
  const visibleColumnWidths = [];
1856
1939
  let remainingWidth = tableWidth;
1857
- let remainingColumnCount = visibleColumns.length;
1858
1940
  for (let index = 0; index < visibleColumns.length; index++) {
1859
1941
  const column = visibleColumns[index];
1860
1942
  if (index === visibleColumns.length - 1) {
1861
1943
  visibleColumnWidths.push(Math.max(0, remainingWidth));
1862
1944
  continue;
1863
1945
  }
1864
- const maxWidth = Math.max(minimumTableColumnWidth, remainingWidth - minimumTableColumnWidth * (remainingColumnCount - 1));
1946
+ const minimumWidth = getMinimumTableColumnWidth(column);
1947
+ const minimumRemainingWidth = visibleColumns.slice(index + 1).reduce((total, remainingColumn) => total + getMinimumTableColumnWidth(remainingColumn), 0);
1948
+ const maxWidth = Math.max(minimumWidth, remainingWidth - minimumRemainingWidth);
1865
1949
  const preferredWidth = tableColumnWidths[column];
1866
- const clampedWidth = Math.max(minimumTableColumnWidth, Math.min(preferredWidth, maxWidth));
1950
+ const clampedWidth = Math.max(minimumWidth, Math.min(preferredWidth, maxWidth));
1867
1951
  visibleColumnWidths.push(clampedWidth);
1868
1952
  remainingWidth -= clampedWidth;
1869
- remainingColumnCount -= 1;
1870
1953
  }
1871
1954
  const resizerLefts = [];
1872
1955
  let cumulativeWidth = 0;
@@ -1890,11 +1973,12 @@ const getResizedTableColumnWidths = (width, tableWidth, visibleTableColumns, tab
1890
1973
  }
1891
1974
  const boundaryIndex = resizerDownId - 1;
1892
1975
  const precedingWidth = layout.visibleColumnWidths.slice(0, boundaryIndex).reduce((total, current) => total + current, 0);
1893
- const remainingVisibleColumnCount = layout.visibleColumns.length - boundaryIndex - 1;
1894
- const maxWidth = Math.max(minimumTableColumnWidth, clampedTableWidth - precedingWidth - minimumTableColumnWidth * remainingVisibleColumnCount);
1895
- const nextWidth = clientX - viewX - leftPadding - precedingWidth;
1896
- const clampedWidth = Math.max(minimumTableColumnWidth, Math.min(nextWidth, maxWidth));
1897
1976
  const resizedColumn = layout.visibleColumns[boundaryIndex];
1977
+ const minimumWidth = getMinimumTableColumnWidth(resizedColumn);
1978
+ const minimumRemainingWidth = layout.visibleColumns.slice(boundaryIndex + 1).reduce((total, column) => total + getMinimumTableColumnWidth(column), 0);
1979
+ const maxWidth = Math.max(minimumWidth, clampedTableWidth - precedingWidth - minimumRemainingWidth);
1980
+ const nextWidth = clientX - viewX - leftPadding - precedingWidth;
1981
+ const clampedWidth = Math.max(minimumWidth, Math.min(nextWidth, maxWidth));
1898
1982
  return {
1899
1983
  ...tableColumnWidths,
1900
1984
  [resizedColumn]: clampedWidth
@@ -1948,12 +2032,12 @@ const restoreTimelineEndSeconds = (savedState, currentTimelineEndSeconds) => {
1948
2032
  const restoreTimelineStartSeconds = (savedState, currentTimelineStartSeconds) => {
1949
2033
  return typeof savedState.timelineStartSeconds === 'string' ? savedState.timelineStartSeconds : currentTimelineStartSeconds;
1950
2034
  };
1951
- const restoreVisibleTableColumns = (savedState, currentVisibleTableColumns) => {
2035
+ const restoreVisibleTableColumns = (savedState, currentTableColumns) => {
1952
2036
  if (!Array.isArray(savedState.visibleTableColumns)) {
1953
- return currentVisibleTableColumns;
2037
+ return currentTableColumns;
1954
2038
  }
1955
2039
  const visibleTableColumns = savedState.visibleTableColumns.filter(value => typeof value === 'string');
1956
- return getOrderedVisibleTableColumns(visibleTableColumns);
2040
+ return getTableColumnsWithVisibility(currentTableColumns, visibleTableColumns);
1957
2041
  };
1958
2042
  const restoreTableColumnWidths = (savedState, currentTableColumnWidths) => {
1959
2043
  return isTableColumnWidths(savedState.tableColumnWidths) ? savedState.tableColumnWidths : currentTableColumnWidths;
@@ -1968,10 +2052,10 @@ const restoreSavedState = (state, savedState) => {
1968
2052
  detailTabs: restoreDetailTabs(savedState, state.detailTabs),
1969
2053
  filterValue: restoreFilterValue(savedState, state.filterValue),
1970
2054
  selectedEventId: restoreSelectedEventId(savedState, state.selectedEventId),
2055
+ tableColumns: restoreVisibleTableColumns(savedState, state.tableColumns),
1971
2056
  tableColumnWidths: restoreTableColumnWidths(savedState, state.tableColumnWidths),
1972
2057
  timelineEndSeconds: restoreTimelineEndSeconds(savedState, state.timelineEndSeconds),
1973
- timelineStartSeconds: restoreTimelineStartSeconds(savedState, state.timelineStartSeconds),
1974
- visibleTableColumns: restoreVisibleTableColumns(savedState, state.visibleTableColumns)
2058
+ timelineStartSeconds: restoreTimelineStartSeconds(savedState, state.timelineStartSeconds)
1975
2059
  };
1976
2060
  };
1977
2061
 
@@ -2127,8 +2211,11 @@ const createDefaultState = () => {
2127
2211
  events: [],
2128
2212
  eventStoreName: 'chat-view-events',
2129
2213
  filterValue: '',
2214
+ focus: 0,
2130
2215
  height: 0,
2131
2216
  initial: false,
2217
+ largeBreakpoint: 900,
2218
+ mediumBreakpoint: 600,
2132
2219
  platform: 0,
2133
2220
  sashPointerActive: false,
2134
2221
  selectedEvent: null,
@@ -2139,12 +2226,17 @@ const createDefaultState = () => {
2139
2226
  showEventStreamFinishedEvents: false,
2140
2227
  showInputEvents: false,
2141
2228
  showResponsePartEvents: false,
2142
- tableColumns: [],
2229
+ sortColumn: '',
2230
+ sortDescending: false,
2231
+ tableColumns: createTableColumns(),
2143
2232
  tableColumnWidths: defaultTableColumnWidths,
2144
2233
  tableResizerDownId: 0,
2145
2234
  tableWidth: defaultTableWidth,
2146
2235
  timelineEndSeconds: '',
2147
2236
  timelineEvents: [],
2237
+ timelineFilterDescription: '',
2238
+ timelineHoverPercent: null,
2239
+ timelineHoverSeconds: '',
2148
2240
  timelineInfo: emptyTimelineInfo,
2149
2241
  timelineSelectionActive: false,
2150
2242
  timelineSelectionAnchorSeconds: '',
@@ -2153,7 +2245,6 @@ const createDefaultState = () => {
2153
2245
  uid: 0,
2154
2246
  uri: '',
2155
2247
  useDevtoolsLayout: true,
2156
- visibleTableColumns: defaultVisibleTableColumns,
2157
2248
  width: 0,
2158
2249
  x: 0,
2159
2250
  y: 0
@@ -2168,6 +2259,7 @@ const create = (uid, uri, x, y, width, height, platform, assetDir, sessionId = '
2168
2259
  databaseName,
2169
2260
  dataBaseVersion,
2170
2261
  eventStoreName,
2262
+ focus: 0,
2171
2263
  height,
2172
2264
  initial: true,
2173
2265
  platform,
@@ -2186,9 +2278,11 @@ const create = (uid, uri, x, y, width, height, platform, assetDir, sessionId = '
2186
2278
  const RenderItems = 1;
2187
2279
  const RenderCss = 2;
2188
2280
  const RenderIncremental = 3;
2281
+ const RenderFocusContext = 4;
2282
+ const RenderFocus = 5;
2189
2283
 
2190
2284
  const diff = (oldState, newState) => {
2191
- if (oldState.categoryFilters !== newState.categoryFilters || oldState.detailTabs !== newState.detailTabs || oldState.errorMessage !== newState.errorMessage || 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.selectedEvent !== newState.selectedEvent || oldState.selectedEventIndex !== newState.selectedEventIndex || oldState.width !== newState.width || oldState.uid !== newState.uid) {
2285
+ if (oldState.categoryFilters !== newState.categoryFilters || oldState.detailTabs !== newState.detailTabs || oldState.errorMessage !== newState.errorMessage || 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.sortColumn !== newState.sortColumn || oldState.sortDescending !== newState.sortDescending || oldState.tableColumnWidths !== newState.tableColumnWidths || oldState.tableWidth !== newState.tableWidth || oldState.timelineEndSeconds !== newState.timelineEndSeconds || oldState.timelineHoverPercent !== newState.timelineHoverPercent || oldState.timelineHoverSeconds !== newState.timelineHoverSeconds || oldState.timelineSelectionActive !== newState.timelineSelectionActive || oldState.timelineSelectionAnchorSeconds !== newState.timelineSelectionAnchorSeconds || oldState.timelineSelectionFocusSeconds !== newState.timelineSelectionFocusSeconds || oldState.timelineStartSeconds !== newState.timelineStartSeconds || oldState.useDevtoolsLayout !== newState.useDevtoolsLayout || oldState.tableColumns !== newState.tableColumns || oldState.selectedEvent !== newState.selectedEvent || oldState.selectedEventIndex !== newState.selectedEventIndex || oldState.focus !== newState.focus || oldState.width !== newState.width || oldState.uid !== newState.uid) {
2192
2286
  return [RenderIncremental, RenderCss];
2193
2287
  }
2194
2288
  return [];
@@ -2202,26 +2296,6 @@ const diff2 = uid => {
2202
2296
  return diff(oldState, newState);
2203
2297
  };
2204
2298
 
2205
- const getColumnVisibilityFlags = (state, column) => {
2206
- return isVisibleTableColumn(state.visibleTableColumns, column) ? Checked : Unchecked;
2207
- };
2208
-
2209
- const MenuChatDebugTableHeader = 2189;
2210
- const handleHeaderContextMenu = async (state, eventX, eventY) => {
2211
- await showContextMenu2(state.uid, MenuChatDebugTableHeader, eventX, eventY, {
2212
- menuId: MenuChatDebugTableHeader
2213
- });
2214
- return state;
2215
- };
2216
-
2217
- const devtoolsRootGap = 4;
2218
- const devtoolsTopHeight = 28;
2219
- const devtoolsTimelineHeight = 88;
2220
- const devtoolsTableHeaderHeight = 24;
2221
- const getTableBodyY = (state, hasTimeline) => {
2222
- return state.y + viewPadding + devtoolsTopHeight + devtoolsRootGap + (hasTimeline ? devtoolsTimelineHeight : 0) + devtoolsTableHeaderHeight;
2223
- };
2224
-
2225
2299
  const filterEventsByTimelineRange = (events, startValue, endValue) => {
2226
2300
  const eventsWithTime = getEventsWithTime(events);
2227
2301
  if (eventsWithTime.length === 0) {
@@ -2239,6 +2313,12 @@ const filterEventsByTimelineRange = (events, startValue, endValue) => {
2239
2313
  return eventsWithTime.filter(item => item.time >= startTime && item.time <= endTime).map(item => item.event);
2240
2314
  };
2241
2315
 
2316
+ const startedEventType = 'tool-execution-started';
2317
+ const finishedEventType = 'tool-execution-finished';
2318
+ const mergedEventType = 'tool-execution';
2319
+ const handleSubmitEventType = 'handle-submit';
2320
+ const sseResponseCompletedEventType = 'sse-response-completed';
2321
+
2242
2322
  const hasMatchingToolName = (startedEvent, finishedEvent) => {
2243
2323
  if (typeof startedEvent.toolName === 'string' && typeof finishedEvent.toolName === 'string') {
2244
2324
  return startedEvent.toolName === finishedEvent.toolName;
@@ -2250,10 +2330,6 @@ const isMatchingToolExecutionPair = (startedEvent, finishedEvent) => {
2250
2330
  return startedEvent.sessionId === finishedEvent.sessionId && hasMatchingToolName(startedEvent, finishedEvent);
2251
2331
  };
2252
2332
 
2253
- const startedEventType = 'tool-execution-started';
2254
- const finishedEventType = 'tool-execution-finished';
2255
- const mergedEventType = 'tool-execution';
2256
-
2257
2333
  const isToolExecutionFinishedEvent = event => {
2258
2334
  return event.type === finishedEventType;
2259
2335
  };
@@ -2274,7 +2350,7 @@ const getStartedTimestamp = event => {
2274
2350
  return getTimestamp(event.started) ?? getTimestamp(event.startTime) ?? getTimestamp(event.startTimestamp) ?? getTimestamp(event.timestamp);
2275
2351
  };
2276
2352
 
2277
- const mergeToolExecutionEvents = (startedEvent, finishedEvent) => {
2353
+ const mergeToolExecutionEvents = (startedEvent, finishedEvent, type = mergedEventType) => {
2278
2354
  const ended = getEndedTimestamp(finishedEvent);
2279
2355
  const {
2280
2356
  eventId
@@ -2292,22 +2368,28 @@ const mergeToolExecutionEvents = (startedEvent, finishedEvent) => {
2292
2368
  ...(started === undefined ? {} : {
2293
2369
  started
2294
2370
  }),
2295
- type: mergedEventType
2371
+ type
2296
2372
  };
2297
2373
  return mergedEvent;
2298
2374
  };
2299
2375
 
2376
+ const isMatchingHandleSubmitPair = (startedEvent, finishedEvent) => {
2377
+ return startedEvent.type === handleSubmitEventType && finishedEvent.type === sseResponseCompletedEventType && startedEvent.sessionId === finishedEvent.sessionId;
2378
+ };
2300
2379
  const collapseToolExecutionEvents = events => {
2301
2380
  const collapsedEvents = [];
2302
2381
  for (let i = 0; i < events.length; i++) {
2303
2382
  const event = events[i];
2304
- if (isToolExecutionStartedEvent(event)) {
2305
- const nextEvent = events[i + 1];
2306
- if (nextEvent && isToolExecutionFinishedEvent(nextEvent) && isMatchingToolExecutionPair(event, nextEvent)) {
2307
- collapsedEvents.push(mergeToolExecutionEvents(event, nextEvent));
2308
- i++;
2309
- continue;
2310
- }
2383
+ const nextEvent = events[i + 1];
2384
+ if (nextEvent && isToolExecutionStartedEvent(event) && isToolExecutionFinishedEvent(nextEvent) && isMatchingToolExecutionPair(event, nextEvent)) {
2385
+ collapsedEvents.push(mergeToolExecutionEvents(event, nextEvent));
2386
+ i++;
2387
+ continue;
2388
+ }
2389
+ if (nextEvent && isMatchingHandleSubmitPair(event, nextEvent)) {
2390
+ collapsedEvents.push(mergeToolExecutionEvents(event, nextEvent, handleSubmitEventType));
2391
+ i++;
2392
+ continue;
2311
2393
  }
2312
2394
  collapsedEvents.push(event);
2313
2395
  }
@@ -2387,10 +2469,171 @@ const getFilteredEvents = (events, filterValue, eventCategoryFilters, showInputE
2387
2469
  return filteredByCategory.filter(event => JSON.stringify(event).toLowerCase().includes(filterText));
2388
2470
  };
2389
2471
 
2472
+ const getDurationText = event => {
2473
+ const explicitDuration = event.durationMs ?? event.duration;
2474
+ if (typeof explicitDuration === 'number' && Number.isFinite(explicitDuration)) {
2475
+ return `${explicitDuration}ms`;
2476
+ }
2477
+ const start = toTimeNumber(event.started ?? event.startTime ?? event.startTimestamp ?? event.timestamp);
2478
+ const end = toTimeNumber(event.ended ?? event.endTime ?? event.endTimestamp ?? event.timestamp);
2479
+ if (start === undefined || end === undefined || end < start) {
2480
+ return '-';
2481
+ }
2482
+ return `${end - start}ms`;
2483
+ };
2484
+
2485
+ const getEventTableDurationText = event => {
2486
+ const durationText = getDurationText(event);
2487
+ if (!durationText.endsWith('ms')) {
2488
+ return durationText;
2489
+ }
2490
+ return `${durationText.slice(0, -2)} ms`;
2491
+ };
2492
+
2493
+ const toolExecutionTypePrefix = 'tool-execution';
2494
+ const getToolName = event => {
2495
+ if (typeof event.toolName === 'string' && event.toolName) {
2496
+ return event.toolName;
2497
+ }
2498
+ if (typeof event.name === 'string' && event.name) {
2499
+ return event.name;
2500
+ }
2501
+ const {
2502
+ arguments: toolArguments
2503
+ } = event;
2504
+ if (!toolArguments || typeof toolArguments !== 'object') {
2505
+ return undefined;
2506
+ }
2507
+ const {
2508
+ name
2509
+ } = toolArguments;
2510
+ if (typeof name !== 'string' || !name) {
2511
+ return undefined;
2512
+ }
2513
+ return name;
2514
+ };
2515
+ const getEventTypeLabel = event => {
2516
+ if (!event.type.startsWith(toolExecutionTypePrefix)) {
2517
+ return event.type;
2518
+ }
2519
+ const toolName = getToolName(event);
2520
+ if (!toolName) {
2521
+ return event.type;
2522
+ }
2523
+ return `${event.type}, ${toolName}`;
2524
+ };
2525
+
2526
+ const getEventTableTypeLabel = event => {
2527
+ if (event.name === 'list_files') {
2528
+ return event.name;
2529
+ }
2530
+ return getEventTypeLabel(event);
2531
+ };
2532
+
2533
+ const isErrorStatusCode = value => {
2534
+ if (typeof value === 'number') {
2535
+ return value >= 400;
2536
+ }
2537
+ if (typeof value === 'string') {
2538
+ const parsedStatus = Number(value);
2539
+ return Number.isFinite(parsedStatus) && parsedStatus >= 400;
2540
+ }
2541
+ return false;
2542
+ };
2543
+
2544
+ const isRecord = value => {
2545
+ return typeof value === 'object' && value !== null;
2546
+ };
2547
+
2548
+ const hasErrorStatus = event => {
2549
+ if (event.type === 'error') {
2550
+ return true;
2551
+ }
2552
+ if (event.success === false || event.ok === false) {
2553
+ return true;
2554
+ }
2555
+ const {
2556
+ status
2557
+ } = event;
2558
+ if (isErrorStatusCode(status)) {
2559
+ return true;
2560
+ }
2561
+ const {
2562
+ result
2563
+ } = event;
2564
+ if (isRecord(result)) {
2565
+ if (isErrorStatusCode(result.status)) {
2566
+ return true;
2567
+ }
2568
+ if (isToolEvent(event) && 'error' in result && result.error !== undefined) {
2569
+ return true;
2570
+ }
2571
+ if (typeof result.error === 'string' || typeof result.errorMessage === 'string' || typeof result.exception === 'string') {
2572
+ return true;
2573
+ }
2574
+ }
2575
+ return typeof event.error === 'string' || typeof event.errorMessage === 'string' || typeof event.exception === 'string';
2576
+ };
2577
+
2578
+ const getStatusText = event => {
2579
+ return hasErrorStatus(event) ? '400' : '200';
2580
+ };
2581
+
2582
+ const getEventTableColumnValue = (event, column) => {
2583
+ switch (column) {
2584
+ case Duration:
2585
+ return getEventTableDurationText(event);
2586
+ case Status$1:
2587
+ return getStatusText(event);
2588
+ case Type:
2589
+ return getEventTableTypeLabel(event);
2590
+ default:
2591
+ return '';
2592
+ }
2593
+ };
2594
+
2595
+ const compareValues = (a, b, descending) => {
2596
+ const result = a.localeCompare(b, undefined, {
2597
+ sensitivity: 'base'
2598
+ });
2599
+ return descending ? -result : result;
2600
+ };
2601
+ const compareSortableEventEntries = (a, b, sortDescending) => {
2602
+ const compared = compareValues(a.value, b.value, sortDescending);
2603
+ if (compared !== 0) {
2604
+ return compared;
2605
+ }
2606
+ return a.index - b.index;
2607
+ };
2608
+ const sortEventsByTableColumn = (events, sortColumn, sortDescending) => {
2609
+ if (!sortColumn || !isTableColumn(sortColumn)) {
2610
+ return events;
2611
+ }
2612
+ const sortableEvents = events.map((event, index) => ({
2613
+ event,
2614
+ index,
2615
+ value: getEventTableColumnValue(event, sortColumn)
2616
+ }));
2617
+ const compareEntries = (a, b) => {
2618
+ return compareSortableEventEntries(a, b, sortDescending);
2619
+ };
2620
+ return sortableEvents.toSorted(compareEntries).map(item => item.event);
2621
+ };
2622
+
2623
+ const getCurrentEvents$2 = state => {
2624
+ const eventCategoryFilters = getSelectedEventCategoryFilters(state.categoryFilters);
2625
+ const filteredEvents = getFilteredEvents(state.events, state.filterValue, eventCategoryFilters, state.showInputEvents, state.showResponsePartEvents, state.showEventStreamFinishedEvents);
2626
+ const timelineEvents = filterEventsByTimelineRange(filteredEvents, state.timelineStartSeconds, state.timelineEndSeconds);
2627
+ return sortEventsByTableColumn(timelineEvents, state.sortColumn, state.sortDescending);
2628
+ };
2629
+
2390
2630
  const loadSelectedEvent = async (_databaseName, _dataBaseVersion, _eventStoreName, sessionId, _sessionIdIndexName, eventId, type) => {
2391
2631
  return loadSelectedEvent$1(sessionId, eventId, type);
2392
2632
  };
2393
2633
 
2634
+ const svgWidthRegex = /\bwidth=["']([\d.]+)(?:px)?["']/i;
2635
+ const svgHeightRegex = /\bheight=["']([\d.]+)(?:px)?["']/i;
2636
+ const svgViewBoxRegex = /\bviewBox=["'][^"']*?([\d.]+)\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)["']/i;
2394
2637
  const getBlob = event => {
2395
2638
  const {
2396
2639
  blob
@@ -2409,8 +2652,27 @@ const getAltText = event => {
2409
2652
  const isImageMimeType = mimeType => {
2410
2653
  return typeof mimeType === 'string' && mimeType.startsWith('image/');
2411
2654
  };
2412
- const shouldValidateImage = mimeType => {
2413
- return mimeType !== 'image/svg+xml';
2655
+ const formatImageSize = size => {
2656
+ if (size < 1024) {
2657
+ return `${size} B`;
2658
+ }
2659
+ return `${(size / 1024).toFixed(1)} kB`;
2660
+ };
2661
+ const formatImageStats = (width, height, size) => {
2662
+ return `${width} × ${height} px · ${formatImageSize(size)}`;
2663
+ };
2664
+ const getSvgImageStats = async blob => {
2665
+ const text = await blob.text();
2666
+ const widthMatch = text.match(svgWidthRegex);
2667
+ const heightMatch = text.match(svgHeightRegex);
2668
+ if (widthMatch && heightMatch) {
2669
+ return formatImageStats(Number(widthMatch[1]), Number(heightMatch[1]), blob.size);
2670
+ }
2671
+ const viewBoxMatch = text.match(svgViewBoxRegex);
2672
+ if (viewBoxMatch) {
2673
+ return formatImageStats(Number(viewBoxMatch[3]), Number(viewBoxMatch[4]), blob.size);
2674
+ }
2675
+ return undefined;
2414
2676
  };
2415
2677
  const readBlobAsPreviewUrl = blob => {
2416
2678
  if (typeof FileReaderSync === 'function') {
@@ -2422,15 +2684,29 @@ const readBlobAsPreviewUrl = blob => {
2422
2684
  }
2423
2685
  throw new Error('image preview reader is not available');
2424
2686
  };
2425
- const validateImage = async blob => {
2687
+ const getRasterImageStats = async blob => {
2426
2688
  if (typeof createImageBitmap !== 'function') {
2427
- return;
2689
+ throw new TypeError('image bitmap decoder is not available');
2428
2690
  }
2429
2691
  const bitmap = await createImageBitmap(blob);
2430
- bitmap.close?.();
2692
+ try {
2693
+ return formatImageStats(bitmap.width, bitmap.height, blob.size);
2694
+ } finally {
2695
+ bitmap.close?.();
2696
+ }
2697
+ };
2698
+ const getImageStats = async (blob, mimeType) => {
2699
+ if (mimeType === 'image/svg+xml') {
2700
+ const svgStats = await getSvgImageStats(blob);
2701
+ if (svgStats === undefined) {
2702
+ throw new TypeError('image stats are not available');
2703
+ }
2704
+ return svgStats;
2705
+ }
2706
+ return getRasterImageStats(blob);
2431
2707
  };
2432
2708
  const getAttachmentImagePreview = async event => {
2433
- if (event.type !== 'chat-attachment-added') {
2709
+ if (event.type !== 'chat-attachment-added' && event.type !== 'chat-attachment-removed') {
2434
2710
  return undefined;
2435
2711
  }
2436
2712
  const blob = getBlob(event);
@@ -2439,13 +2715,12 @@ const getAttachmentImagePreview = async event => {
2439
2715
  return undefined;
2440
2716
  }
2441
2717
  try {
2442
- if (shouldValidateImage(mimeType)) {
2443
- await validateImage(blob);
2444
- }
2718
+ const stats = await getImageStats(blob, mimeType);
2445
2719
  return {
2446
2720
  alt: getAltText(event),
2447
2721
  previewType: 'image',
2448
- src: readBlobAsPreviewUrl(blob)
2722
+ src: readBlobAsPreviewUrl(blob),
2723
+ stats
2449
2724
  };
2450
2725
  } catch {
2451
2726
  return imageCouldNotBeLoaded();
@@ -2477,23 +2752,10 @@ const withPreparedSelectedEventPreview = async event => {
2477
2752
  const selectEventAtIndexDependencies = {
2478
2753
  loadSelectedEvent: loadSelectedEvent
2479
2754
  };
2480
- const getCurrentEvents$3 = state => {
2481
- const {
2482
- events,
2483
- filterValue,
2484
- showEventStreamFinishedEvents,
2485
- showInputEvents,
2486
- showResponsePartEvents,
2487
- timelineEndSeconds,
2488
- timelineStartSeconds
2489
- } = state;
2490
- const eventCategoryFilters = getSelectedEventCategoryFilters(state.categoryFilters);
2491
- const filteredEvents = getFilteredEvents(events, filterValue, eventCategoryFilters, showInputEvents, showResponsePartEvents, showEventStreamFinishedEvents);
2492
- return filterEventsByTimelineRange(filteredEvents, timelineStartSeconds, timelineEndSeconds);
2493
- };
2755
+ const getCurrentEvents$1 = state => getCurrentEvents$2(state);
2494
2756
  const selectEventAtIndex = async (state, selectedEventIndex, dependencies = selectEventAtIndexDependencies) => {
2495
2757
  const selectedDetailTab = getSelectedDetailTab(state.detailTabs);
2496
- const currentEvents = getCurrentEvents$3(state);
2758
+ const currentEvents = getCurrentEvents$1(state);
2497
2759
  const selectedEvent = currentEvents[selectedEventIndex];
2498
2760
  if (!selectedEvent) {
2499
2761
  return {
@@ -2522,60 +2784,80 @@ const selectEventAtIndex = async (state, selectedEventIndex, dependencies = sele
2522
2784
  };
2523
2785
  };
2524
2786
 
2525
- const devtoolsTableRowHeight = 24;
2526
- const getTableBodyEventIndex = (state, eventX, eventY) => {
2527
- if (!state.useDevtoolsLayout) {
2528
- return -1;
2787
+ const focusIndex = async (state, index) => {
2788
+ const currentEvents = getCurrentEvents$1(state);
2789
+ if (currentEvents.length === 0 || state.selectedEventIndex === index) {
2790
+ return state;
2529
2791
  }
2530
- const currentEvents = getCurrentEvents$3(state);
2792
+ return selectEventAtIndex(state, index);
2793
+ };
2794
+
2795
+ const focusFirst = async state => {
2796
+ return focusIndex(state, 0);
2797
+ };
2798
+
2799
+ const focusLast = async state => {
2800
+ const currentEvents = getCurrentEvents$1(state);
2531
2801
  if (currentEvents.length === 0) {
2532
- return -1;
2802
+ return state;
2533
2803
  }
2534
- const tableX = state.x + leftPadding;
2535
- const tableWidth = clampTableWidth(state.width, state.tableWidth);
2536
- const hasTimeline = currentEvents.length > 0;
2537
- const tableBodyY = getTableBodyY(state, hasTimeline);
2538
- const relativeX = eventX - tableX;
2539
- const relativeY = eventY - tableBodyY;
2540
- if (relativeX < 0 || relativeX >= tableWidth || relativeY < 0) {
2541
- return -1;
2804
+ const lastIndex = currentEvents.length - 1;
2805
+ return focusIndex(state, lastIndex);
2806
+ };
2807
+
2808
+ const focusNext = async state => {
2809
+ const currentEvents = getCurrentEvents$1(state);
2810
+ if (currentEvents.length === 0) {
2811
+ return state;
2542
2812
  }
2543
- const eventIndex = Math.floor(relativeY / devtoolsTableRowHeight);
2544
- if (eventIndex < 0 || eventIndex >= currentEvents.length) {
2545
- return -1;
2813
+ const currentIndex = state.selectedEventIndex === null || state.selectedEventIndex < 0 ? -1 : state.selectedEventIndex;
2814
+ const nextIndex = Math.min(currentEvents.length - 1, currentIndex + 1);
2815
+ return focusIndex(state, nextIndex);
2816
+ };
2817
+
2818
+ const focusPrevious = async state => {
2819
+ const currentEvents = getCurrentEvents$1(state);
2820
+ if (currentEvents.length === 0) {
2821
+ return state;
2546
2822
  }
2547
- return eventIndex;
2823
+ const currentIndex = state.selectedEventIndex === null || state.selectedEventIndex >= currentEvents.length ? currentEvents.length : state.selectedEventIndex;
2824
+ const nextIndex = Math.max(0, currentIndex - 1);
2825
+ return focusIndex(state, nextIndex);
2548
2826
  };
2549
2827
 
2550
- const MenuChatDebugTableBody = 2190;
2551
- const handleTableBodyContextMenu = async (state, eventX, eventY) => {
2552
- const eventIndex = getTableBodyEventIndex(state, eventX, eventY);
2553
- await showContextMenu2(state.uid, MenuChatDebugTableBody, eventX, eventY, {
2554
- eventIndex,
2555
- menuId: MenuChatDebugTableBody
2556
- });
2557
- return state;
2828
+ const getMenuEntriesTableBody = props => {
2829
+ return [{
2830
+ args: [props.eventIndex],
2831
+ command: 'ChatDebug.handleTableRowCopy',
2832
+ flags: None$1,
2833
+ id: 'copy',
2834
+ label: copy()
2835
+ }];
2836
+ };
2837
+
2838
+ const getColumnVisibilityFlags = (tableColumns, column) => {
2839
+ return isVisibleTableColumn(tableColumns, column) ? Checked : Unchecked;
2558
2840
  };
2559
2841
 
2560
2842
  const getMenuEntriesTableHeader = state => {
2561
2843
  return [{
2562
2844
  args: [Type],
2563
2845
  command: 'ChatDebug.toggleTableColumnVisibility',
2564
- flags: getColumnVisibilityFlags(state, Type),
2846
+ flags: getColumnVisibilityFlags(state.tableColumns, Type),
2565
2847
  id: 'type',
2566
2848
  label: type()
2849
+ }, {
2850
+ args: [Status$1],
2851
+ command: 'ChatDebug.toggleTableColumnVisibility',
2852
+ flags: getColumnVisibilityFlags(state.tableColumns, Status$1),
2853
+ id: 'status',
2854
+ label: status()
2567
2855
  }, {
2568
2856
  args: [Duration],
2569
2857
  command: 'ChatDebug.toggleTableColumnVisibility',
2570
- flags: getColumnVisibilityFlags(state, Duration),
2858
+ flags: getColumnVisibilityFlags(state.tableColumns, Duration),
2571
2859
  id: 'duration',
2572
2860
  label: duration()
2573
- }, {
2574
- args: [Status],
2575
- command: 'ChatDebug.toggleTableColumnVisibility',
2576
- flags: getColumnVisibilityFlags(state, Status),
2577
- id: 'status',
2578
- label: status()
2579
2861
  }, {
2580
2862
  args: [],
2581
2863
  command: 'ChatDebug.resetTableColumns',
@@ -2584,15 +2866,63 @@ const getMenuEntriesTableHeader = state => {
2584
2866
  label: resetColumns()
2585
2867
  }];
2586
2868
  };
2587
- const getMenuEntriesTableBody = props => {
2588
- return [{
2589
- args: [props.eventIndex],
2590
- command: 'ChatDebug.handleTableRowCopy',
2591
- flags: None$1,
2592
- id: 'copy',
2593
- label: copy()
2594
- }];
2869
+
2870
+ const MenuChatDebugTableHeader = 2189;
2871
+ const handleHeaderContextMenu = async (state, eventX, eventY) => {
2872
+ await showContextMenu2(state.uid, MenuChatDebugTableHeader, eventX, eventY, {
2873
+ menuId: MenuChatDebugTableHeader
2874
+ });
2875
+ return state;
2876
+ };
2877
+
2878
+ const show2 = async (uid, menuId, x, y, args) => {
2879
+ await showContextMenu2(uid, menuId, x, y, args);
2880
+ };
2881
+
2882
+ const devtoolsTableHeaderHeight = 24;
2883
+ const devtoolsTableRowHeight = 24;
2884
+
2885
+ const devtoolsRootGap = 4;
2886
+ const devtoolsTopHeight = 28;
2887
+ const devtoolsTimelineHeight = 88;
2888
+ const getTableBodyY = (state, hasTimeline) => {
2889
+ return state.y + viewPadding + devtoolsTopHeight + devtoolsRootGap + (hasTimeline ? devtoolsTimelineHeight : 0) + devtoolsTableHeaderHeight;
2890
+ };
2891
+
2892
+ const getTableBodyEventIndex = (state, eventX, eventY) => {
2893
+ if (!state.useDevtoolsLayout) {
2894
+ return -1;
2895
+ }
2896
+ const currentEvents = getCurrentEvents$1(state);
2897
+ if (currentEvents.length === 0) {
2898
+ return -1;
2899
+ }
2900
+ const tableX = state.x + leftPadding;
2901
+ const tableWidth = clampTableWidth(state.width, state.tableWidth);
2902
+ const hasTimeline = currentEvents.length > 0;
2903
+ const tableBodyY = getTableBodyY(state, hasTimeline);
2904
+ const relativeX = eventX - tableX;
2905
+ const relativeY = eventY - tableBodyY;
2906
+ if (relativeX < 0 || relativeX >= tableWidth || relativeY < 0) {
2907
+ return -1;
2908
+ }
2909
+ const eventIndex = Math.floor(relativeY / devtoolsTableRowHeight);
2910
+ if (eventIndex < 0 || eventIndex >= currentEvents.length) {
2911
+ return -1;
2912
+ }
2913
+ return eventIndex;
2914
+ };
2915
+
2916
+ const MenuChatDebugTableBody = 2190;
2917
+ const handleTableBodyContextMenu = async (state, eventX, eventY) => {
2918
+ const eventIndex = getTableBodyEventIndex(state, eventX, eventY);
2919
+ await show2(state.uid, MenuChatDebugTableBody, eventX, eventY, {
2920
+ eventIndex,
2921
+ menuId: MenuChatDebugTableBody
2922
+ });
2923
+ return state;
2595
2924
  };
2925
+
2596
2926
  const getMenuEntries2 = (state, props) => {
2597
2927
  if (props.menuId === MenuChatDebugTableHeader) {
2598
2928
  return getMenuEntriesTableHeader(state);
@@ -2717,13 +3047,30 @@ const getTimelineEvents = state => {
2717
3047
  return getFilteredEvents(events, filterValue, eventCategoryFilters, showInputEvents, showResponsePartEvents, showEventStreamFinishedEvents);
2718
3048
  };
2719
3049
 
3050
+ const getTimelineFilterDescription = (timelineStartSeconds, timelineEndSeconds) => {
3051
+ const trimmedStart = timelineStartSeconds.trim();
3052
+ const trimmedEnd = timelineEndSeconds.trim();
3053
+ if (trimmedStart && trimmedEnd) {
3054
+ return secondsRange(trimmedStart, trimmedEnd);
3055
+ }
3056
+ if (trimmedStart) {
3057
+ return fromSeconds(trimmedStart);
3058
+ }
3059
+ if (trimmedEnd) {
3060
+ return toSeconds(trimmedEnd);
3061
+ }
3062
+ return '';
3063
+ };
3064
+
2720
3065
  const getStateWithTimelineInfo = state => {
2721
3066
  const timelineEvents = getTimelineEvents(state);
2722
3067
  const effectiveRange = getEffectiveTimelineRange(state.timelineStartSeconds, state.timelineEndSeconds, state.timelineSelectionActive, state.timelineSelectionAnchorSeconds, state.timelineSelectionFocusSeconds);
2723
3068
  const timelineInfo = getTimelineInfo(timelineEvents, effectiveRange.startSeconds, effectiveRange.endSeconds);
3069
+ const timelineFilterDescription = getTimelineFilterDescription(state.timelineStartSeconds, state.timelineEndSeconds);
2724
3070
  return {
2725
3071
  ...state,
2726
3072
  timelineEvents,
3073
+ timelineFilterDescription,
2727
3074
  timelineInfo
2728
3075
  };
2729
3076
  };
@@ -2769,12 +3116,6 @@ const getSessionNotFoundMessage = sessionId => {
2769
3116
  return noChatSessionFound(sessionId);
2770
3117
  };
2771
3118
 
2772
- const getCurrentEvents$2 = state => {
2773
- const eventCategoryFilters = getSelectedEventCategoryFilters(state.categoryFilters);
2774
- const filteredEvents = getFilteredEvents(state.events, state.filterValue, eventCategoryFilters, state.showInputEvents, state.showResponsePartEvents, state.showEventStreamFinishedEvents);
2775
- return filterEventsByTimelineRange(filteredEvents, state.timelineStartSeconds, state.timelineEndSeconds);
2776
- };
2777
-
2778
3119
  const restoreSelectedEvent = async state => {
2779
3120
  if (state.selectedEventId === null) {
2780
3121
  return {
@@ -2914,13 +3255,16 @@ const selectDetailTab = (state, value) => {
2914
3255
  detailTabs
2915
3256
  };
2916
3257
  };
3258
+ const handleDetailTabsFocus = (state, value) => {
3259
+ return selectDetailTab(state, value);
3260
+ };
2917
3261
 
2918
- const getCurrentEvents$1 = state => {
2919
- const eventCategoryFilters = getSelectedEventCategoryFilters(state.categoryFilters);
2920
- const filteredEvents = getFilteredEvents(state.events, state.filterValue, eventCategoryFilters, state.showInputEvents, state.showResponsePartEvents, state.showEventStreamFinishedEvents);
2921
- return filterEventsByTimelineRange(filteredEvents, state.timelineStartSeconds, state.timelineEndSeconds);
3262
+ const handleEscape = state => {
3263
+ return state;
2922
3264
  };
2923
3265
 
3266
+ const getCurrentEvents = state => getCurrentEvents$2(state);
3267
+
2924
3268
  const getEventIndexByStableId$1 = (events, event) => {
2925
3269
  return events.findIndex(candidate => candidate.eventId === event.eventId);
2926
3270
  };
@@ -2932,7 +3276,7 @@ const getSelectedEventIndex$1 = state => {
2932
3276
  if (selectedEventIndex === null) {
2933
3277
  return null;
2934
3278
  }
2935
- const filteredEvents = getCurrentEvents$1(state);
3279
+ const filteredEvents = getCurrentEvents(state);
2936
3280
  const selectedEvent = filteredEvents[selectedEventIndex];
2937
3281
  if (!selectedEvent) {
2938
3282
  return null;
@@ -2951,12 +3295,12 @@ const getPreservedSelectedEventIndex$1 = (oldState, newState) => {
2951
3295
  if (selectedEventIndex === null) {
2952
3296
  return null;
2953
3297
  }
2954
- const oldFilteredEvents = getCurrentEvents$1(oldState);
3298
+ const oldFilteredEvents = getCurrentEvents(oldState);
2955
3299
  const selectedEvent = oldFilteredEvents[selectedEventIndex];
2956
3300
  if (!selectedEvent) {
2957
3301
  return null;
2958
3302
  }
2959
- const newFilteredEvents = getCurrentEvents$1(newState);
3303
+ const newFilteredEvents = getCurrentEvents(newState);
2960
3304
  const newIndex = getEventIndexByStableId$1(newFilteredEvents, selectedEvent);
2961
3305
  if (newIndex === -1) {
2962
3306
  return null;
@@ -2976,51 +3320,46 @@ const withPreservedSelection$1 = (state, nextState) => {
2976
3320
  };
2977
3321
 
2978
3322
  const handleEventCategoryFilter = (state, value, ctrlKey = false, metaKey = false) => {
2979
- const categoryFilters = selectCategoryFilter(state.categoryFilters, value || All, ctrlKey || metaKey);
2980
- if (categoryFilters === state.categoryFilters) {
3323
+ const {
3324
+ categoryFilters
3325
+ } = state;
3326
+ const newCategoryFilters = selectCategoryFilter(categoryFilters, value || All, ctrlKey || metaKey);
3327
+ if (newCategoryFilters === categoryFilters) {
2981
3328
  return state;
2982
3329
  }
2983
3330
  const nextState = {
2984
3331
  ...state,
2985
- categoryFilters
3332
+ categoryFilters: newCategoryFilters
2986
3333
  };
2987
3334
  return withPreservedSelection$1(state, nextState);
2988
3335
  };
2989
3336
 
2990
- const parseSelectedEventIndex$1 = value => {
2991
- const parsed = Number.parseInt(value, 10);
2992
- if (Number.isNaN(parsed) || parsed < 0) {
2993
- return null;
2994
- }
2995
- return parsed;
2996
- };
2997
-
2998
3337
  const handleEventRowClickDependencies = {
2999
3338
  loadSelectedEvent: loadSelectedEvent
3000
3339
  };
3001
3340
  const isPrimaryButton = button => {
3002
3341
  return button === 0;
3003
3342
  };
3004
- const handleEventRowClick = async (state, value, button = 0) => {
3343
+ const handleEventRowClick = async (state, index, button = 0) => {
3344
+ const actual = typeof index === 'string' ? Number.parseInt(index, 10) : index;
3005
3345
  if (!isPrimaryButton(button)) {
3006
3346
  return state;
3007
3347
  }
3008
- const selectedEventIndex = parseSelectedEventIndex$1(value);
3009
- if (selectedEventIndex === null) {
3348
+ if (actual === -1) {
3010
3349
  return state;
3011
3350
  }
3012
- return selectEventAtIndex(state, selectedEventIndex, handleEventRowClickDependencies);
3351
+ return selectEventAtIndex(state, actual, handleEventRowClickDependencies);
3352
+ };
3353
+
3354
+ const handleEventRowClickAt = async (state, eventX, eventY, button = 0) => {
3355
+ const selectedEventIndex = getTableBodyEventIndex(state, eventX, eventY);
3356
+ return handleEventRowClick(state, selectedEventIndex, button);
3013
3357
  };
3014
3358
 
3015
3359
  const getBoolean = value => {
3016
3360
  return value === true || value === 'true' || value === 'on' || value === '1';
3017
3361
  };
3018
3362
 
3019
- const getCurrentEvents = state => {
3020
- const eventCategoryFilters = getSelectedEventCategoryFilters(state.categoryFilters);
3021
- const filteredEvents = getFilteredEvents(state.events, state.filterValue, eventCategoryFilters, state.showInputEvents, state.showResponsePartEvents, state.showEventStreamFinishedEvents);
3022
- return filterEventsByTimelineRange(filteredEvents, state.timelineStartSeconds, state.timelineEndSeconds);
3023
- };
3024
3363
  const parseTimelineRangePreset$1 = value => {
3025
3364
  if (!value) {
3026
3365
  return {
@@ -3044,7 +3383,7 @@ const getSelectedEventIndex = state => {
3044
3383
  if (selectedEventIndex === null) {
3045
3384
  return null;
3046
3385
  }
3047
- const filteredEvents = getCurrentEvents(state);
3386
+ const filteredEvents = getCurrentEvents$2(state);
3048
3387
  const selectedEvent = filteredEvents[selectedEventIndex];
3049
3388
  if (!selectedEvent) {
3050
3389
  return null;
@@ -3062,12 +3401,12 @@ const getPreservedSelectedEventIndex = (oldState, newState) => {
3062
3401
  if (selectedEventIndex === null) {
3063
3402
  return null;
3064
3403
  }
3065
- const oldFilteredEvents = getCurrentEvents(oldState);
3404
+ const oldFilteredEvents = getCurrentEvents$2(oldState);
3066
3405
  const selectedEvent = oldFilteredEvents[selectedEventIndex];
3067
3406
  if (!selectedEvent) {
3068
3407
  return null;
3069
3408
  }
3070
- const newFilteredEvents = getCurrentEvents(newState);
3409
+ const newFilteredEvents = getCurrentEvents$2(newState);
3071
3410
  const newIndex = getEventIndexByStableId(newFilteredEvents, selectedEvent);
3072
3411
  if (newIndex === -1) {
3073
3412
  return null;
@@ -3226,6 +3565,28 @@ const handleSashPointerUp = (state, eventX, eventY) => {
3226
3565
  };
3227
3566
  };
3228
3567
 
3568
+ const FocusChatDebugTable = 221_139;
3569
+
3570
+ const handleTableFocus = state => {
3571
+ return {
3572
+ ...state,
3573
+ focus: FocusChatDebugTable
3574
+ };
3575
+ };
3576
+
3577
+ const handleTableHeaderClick = (state, value) => {
3578
+ if (!isTableColumn(value)) {
3579
+ return state;
3580
+ }
3581
+ const sortDescending = state.sortColumn === value ? !state.sortDescending : false;
3582
+ const nextState = {
3583
+ ...state,
3584
+ sortColumn: value,
3585
+ sortDescending
3586
+ };
3587
+ return withPreservedSelection$1(state, nextState);
3588
+ };
3589
+
3229
3590
  const getTableResizerId = name => {
3230
3591
  switch (name) {
3231
3592
  case 'ResizerOne':
@@ -3249,7 +3610,7 @@ const handleTableResizerPointerMove = (state, clientX) => {
3249
3610
  }
3250
3611
  return {
3251
3612
  ...state,
3252
- tableColumnWidths: getResizedTableColumnWidths(state.width, state.tableWidth, state.visibleTableColumns, state.tableColumnWidths, state.x, clientX, state.tableResizerDownId)
3613
+ tableColumnWidths: getResizedTableColumnWidths(state.width, state.tableWidth, getVisibleTableColumns(state.tableColumns), state.tableColumnWidths, state.x, clientX, state.tableResizerDownId)
3253
3614
  };
3254
3615
  };
3255
3616
 
@@ -3264,7 +3625,7 @@ const handleTableResizerPointerUp = state => {
3264
3625
  };
3265
3626
 
3266
3627
  const handleTableRowCopy = async (state, eventIndex) => {
3267
- const currentEvents = getCurrentEvents$3(state);
3628
+ const currentEvents = getCurrentEvents$1(state);
3268
3629
  const event = currentEvents[eventIndex];
3269
3630
  if (!event) {
3270
3631
  return state;
@@ -3333,6 +3694,10 @@ const formatTimelinePresetValue = value => {
3333
3694
  return value.toFixed(3).replace(trailingZeroFractionRegex, '').replace(trailingFractionZeroRegex, '$1');
3334
3695
  };
3335
3696
 
3697
+ const getTimelineEventX = (state, eventX) => {
3698
+ return state.x + eventX;
3699
+ };
3700
+
3336
3701
  const getTimelineLeft = state => {
3337
3702
  return state.x + viewPadding + timelineHorizontalPadding;
3338
3703
  };
@@ -3392,32 +3757,53 @@ const handleTimelinePointerDown = (state, name, eventX) => {
3392
3757
  }
3393
3758
  const timelineLeft = getTimelineLeft(state);
3394
3759
  const timelineWidth = getTimelineWidth(state);
3395
- const clientX = state.x + eventX;
3760
+ const clientX = getTimelineEventX(state, eventX);
3396
3761
  const seconds = getTimelineSecondsFromClientX(state.timelineEvents, clientX, timelineLeft, timelineWidth);
3397
3762
  if (seconds === undefined) {
3398
3763
  return state;
3399
3764
  }
3765
+ const timelineHoverPercent = getSelectionPercent(Number.parseFloat(seconds), state.timelineInfo.durationSeconds);
3400
3766
  return getStateWithTimelineInfo({
3401
3767
  ...state,
3768
+ timelineHoverPercent,
3769
+ timelineHoverSeconds: seconds,
3402
3770
  timelineSelectionActive: true,
3403
3771
  timelineSelectionAnchorSeconds: seconds,
3404
3772
  timelineSelectionFocusSeconds: seconds
3405
3773
  });
3406
3774
  };
3407
3775
 
3408
- const handleTimelinePointerMove = (state, eventX) => {
3409
- if (!state.timelineSelectionActive) {
3776
+ const handleTimelinePointerLeave = state => {
3777
+ if (state.timelineHoverPercent === null && state.timelineHoverSeconds === '') {
3410
3778
  return state;
3411
3779
  }
3780
+ return {
3781
+ ...state,
3782
+ timelineHoverPercent: null,
3783
+ timelineHoverSeconds: ''
3784
+ };
3785
+ };
3786
+
3787
+ const handleTimelinePointerMove = (state, eventX) => {
3412
3788
  const timelineLeft = getTimelineLeft(state);
3413
3789
  const timelineWidth = getTimelineWidth(state);
3414
- const clientX = state.x + eventX;
3790
+ const clientX = getTimelineEventX(state, eventX);
3415
3791
  const seconds = getTimelineSecondsFromClientX(state.timelineEvents, clientX, timelineLeft, timelineWidth);
3416
3792
  if (seconds === undefined) {
3417
3793
  return state;
3418
3794
  }
3795
+ const timelineHoverPercent = getSelectionPercent(Number.parseFloat(seconds), state.timelineInfo.durationSeconds);
3796
+ if (!state.timelineSelectionActive) {
3797
+ return {
3798
+ ...state,
3799
+ timelineHoverPercent,
3800
+ timelineHoverSeconds: seconds
3801
+ };
3802
+ }
3419
3803
  return getStateWithTimelineInfo({
3420
3804
  ...state,
3805
+ timelineHoverPercent,
3806
+ timelineHoverSeconds: seconds,
3421
3807
  timelineSelectionFocusSeconds: seconds
3422
3808
  });
3423
3809
  };
@@ -3428,17 +3814,22 @@ const handleTimelinePointerUp = (state, eventX) => {
3428
3814
  }
3429
3815
  const timelineLeft = getTimelineLeft(state);
3430
3816
  const timelineWidth = getTimelineWidth(state);
3431
- const clientX = state.x + eventX;
3817
+ const clientX = getTimelineEventX(state, eventX);
3432
3818
  const focusSeconds = getTimelineSecondsFromClientX(state.timelineEvents, clientX, timelineLeft, timelineWidth);
3433
3819
  if (focusSeconds === undefined) {
3434
3820
  return clearTimelineSelectionState(state);
3435
3821
  }
3822
+ const timelineHoverPercent = getSelectionPercent(Number.parseFloat(focusSeconds), state.timelineInfo.durationSeconds);
3436
3823
  const anchor = Number.parseFloat(state.timelineSelectionAnchorSeconds);
3437
3824
  const focus = Number.parseFloat(focusSeconds);
3438
3825
  const startSeconds = formatTimelinePresetValue(Math.min(anchor, focus));
3439
3826
  const endSeconds = formatTimelinePresetValue(Math.max(anchor, focus));
3440
3827
  const nextState = handleTimelineRangePreset(state, `${startSeconds}:${endSeconds}`);
3441
- return clearTimelineSelectionState(nextState);
3828
+ return clearTimelineSelectionState({
3829
+ ...nextState,
3830
+ timelineHoverPercent,
3831
+ timelineHoverSeconds: focusSeconds
3832
+ });
3442
3833
  };
3443
3834
 
3444
3835
  const setUseDevtoolsLayout = (state, checked) => {
@@ -3476,6 +3867,7 @@ const handleShowResponsePartEvents = (state, checked) => {
3476
3867
  };
3477
3868
 
3478
3869
  const loadContent = async (state, savedState) => {
3870
+ await getPreference('chatDebug.autoRefresh');
3479
3871
  const nextState = await loadEventsFromUri(restoreSavedState(state, savedState));
3480
3872
  return {
3481
3873
  ...nextState,
@@ -3485,412 +3877,81 @@ const loadContent = async (state, savedState) => {
3485
3877
  };
3486
3878
  };
3487
3879
 
3880
+ // cspell:ignore liga calt
3881
+
3488
3882
  const getCss = state => {
3489
3883
  const hasSelectedEvent = !!state.selectedEvent;
3490
3884
  const tableWidth = hasSelectedEvent ? clampTableWidth(state.width, state.tableWidth) : getMainWidth(state.width);
3491
3885
  const detailsWidth = hasSelectedEvent ? getDetailsWidth(state.width, state.tableWidth) : 0;
3492
- const tableColumnLayout = getTableColumnLayout(tableWidth, state.visibleTableColumns, state.tableColumnWidths);
3493
- const resizerOneLeft = tableColumnLayout.resizerLefts[0] || 0;
3494
- const resizerTwoLeft = tableColumnLayout.resizerLefts[1] || 0;
3886
+ const topSize = state.width >= state.largeBreakpoint ? 30 : state.width >= state.mediumBreakpoint ? 60 : 60;
3887
+ const tableColumnLayout = getTableColumnLayout(tableWidth, getVisibleTableColumns(state.tableColumns), state.tableColumnWidths);
3888
+ const [tableColZeroWidth = 0, tableColOneWidth = 0, tableColTwoWidth = 0] = tableColumnLayout.visibleColumnWidths;
3889
+ const resizerOneLeft = tableColumnLayout.resizerLefts[0] ?? 0;
3890
+ const resizerTwoLeft = tableColumnLayout.resizerLefts[1] ?? 0;
3891
+ const {
3892
+ selectionEndPercent,
3893
+ selectionStartPercent
3894
+ } = state.timelineInfo;
3495
3895
  return `
3496
3896
  .ChatDebugView {
3897
+ --ChatDebugViewTableHeaderHeight: ${devtoolsTableHeaderHeight}px;
3898
+ --ChatDebugViewTableColZeroWidth: ${tableColZeroWidth}px;
3899
+ --ChatDebugViewTableColOneWidth: ${tableColOneWidth}px;
3900
+ --ChatDebugViewTableColTwoWidth: ${tableColTwoWidth}px;
3497
3901
  --ChatDebugViewDetailsWidth: ${detailsWidth}px;
3498
3902
  --ChatDebugViewDurationColumnWidth: ${state.tableColumnWidths.duration}px;
3499
- --ChatDebugViewResizerOneLeft: ${resizerOneLeft}px;
3500
- --ChatDebugViewResizerTwoLeft: ${resizerTwoLeft}px;
3903
+ --ChatDebugViewTableRowHeight: ${devtoolsTableRowHeight}px;
3904
+ --ResizerOneLeft: ${resizerOneLeft}px;
3905
+ --ResizerTwoLeft: ${resizerTwoLeft}px;
3501
3906
  --ChatDebugViewSashWidth: ${sashWidth}px;
3502
3907
  --ChatDebugViewTableWidth: ${tableWidth}px;
3908
+ --ChatDebugViewTimelineCursorGuideLeft: ${state.timelineHoverPercent ?? 0}%;
3909
+ --ChatDebugViewTimelineSelectionEndLeft: ${selectionEndPercent ?? 0}%;
3910
+ --ChatDebugViewTimelineSelectionStartLeft: ${selectionStartPercent ?? 0}%;
3911
+ --ChatDebugViewTopSize: ${topSize}px;
3503
3912
  --ChatDebugViewTypeColumnWidth: ${state.tableColumnWidths.type}px;
3504
3913
  padding: ${viewPadding}px;
3505
3914
  }
3506
3915
 
3507
- .ChatDebugViewTop {
3508
- display: flex;
3509
- align-items: center;
3510
- gap: 8px;
3511
- min-width: 0;
3512
- }
3513
-
3514
- .ChatDebugViewFilterInput {
3515
- flex: 1;
3516
- min-width: 0;
3517
- }
3518
-
3519
- .ChatDebugViewFilterInput--devtools {
3520
- flex: 1 1 220px;
3521
- min-width: 180px;
3522
- }
3523
-
3524
- .ChatDebugViewTableWrapper {
3525
- position: relative;
3526
- width: min(100%, var(--ChatDebugViewTableWidth));
3527
- max-width: 100%;
3528
- flex:1;
3529
- display:flex
3530
- }
3531
-
3532
- .ChatDebugViewTable {
3533
- width: 100%;
3534
- table-layout: fixed;
3535
- border-collapse: collapse;
3536
- flex: 1;
3537
- }
3538
-
3539
- .ChatDebugViewHeaderCell,
3540
- .ChatDebugViewCell {
3541
- overflow: hidden;
3542
- text-overflow: ellipsis;
3543
- white-space: nowrap;
3544
- }
3545
-
3546
- .ChatDebugViewHeaderCellType.ChatDebugViewColumnFixed,
3547
- .ChatDebugViewCellType.ChatDebugViewColumnFixed {
3548
- width: var(--ChatDebugViewTypeColumnWidth);
3549
- max-width: var(--ChatDebugViewTypeColumnWidth);
3550
- }
3551
-
3552
- .ChatDebugViewHeaderCellDuration.ChatDebugViewColumnFixed,
3553
- .ChatDebugViewCellDuration.ChatDebugViewColumnFixed {
3554
- width: var(--ChatDebugViewDurationColumnWidth);
3555
- max-width: var(--ChatDebugViewDurationColumnWidth);
3556
- }
3557
-
3558
- .ChatDebugViewResizers {
3559
- position: absolute;
3560
- inset: 0;
3561
- pointer-events: none;
3562
- }
3563
-
3564
- .ChatDebugViewResizer {
3565
- position: absolute;
3566
- top: 0;
3567
- bottom: 0;
3568
- width: 12px;
3569
- margin: 0;
3570
- padding: 0;
3571
- border: 0;
3572
- background: transparent;
3573
- pointer-events: auto;
3574
- cursor: col-resize;
3575
- }
3576
-
3577
- .ChatDebugViewResizerOne {
3578
- left: var(--ChatDebugViewResizerOneLeft);
3579
- transform: translateX(-50%);
3580
- }
3581
-
3582
- .ChatDebugViewResizerTwo {
3583
- left: var(--ChatDebugViewResizerTwoLeft);
3584
- transform: translateX(-50%);
3585
- }
3586
-
3587
- .ChatDebugViewResizerInner {
3588
- position: absolute;
3589
- top: 0;
3590
- bottom: 0;
3591
- left: 50%;
3592
- width: 1px;
3593
- transform: translateX(-50%);
3594
- background: var(--vscode-widget-border, rgba(255, 255, 255, 0.18));
3595
- }
3596
-
3916
+ `;
3917
+ };
3597
3918
 
3598
- .ChatDebugViewDetails {
3599
- margin-left: auto;
3600
- min-height: 26px;
3601
- }
3602
- border: 1px solid transparent;
3603
- border-radius: 4px;
3604
- background: transparent;
3605
- color: var(--vscode-descriptionForeground, inherit);
3606
- }
3607
- font-size: 11px;
3608
- font-weight: 600;
3609
- letter-spacing: 0.02em;
3610
- display: flex;
3611
- contain: strict;
3612
- flex:1;
3613
- transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease, transform 120ms ease;
3919
+ const renderCss = (oldState, newState) => {
3920
+ const css = getCss(newState);
3921
+ return [SetCss, newState.uid, css];
3922
+ };
3614
3923
 
3615
- }
3616
- .ChatDebugViewEvent {
3617
- border-color: var(--vscode-widget-border, rgba(255, 255, 255, 0.14));
3618
- background: var(--vscode-toolbar-hoverBackground, rgba(255, 255, 255, 0.06));
3619
- color: var(--vscode-foreground, inherit);
3620
-
3621
- .ChatDebugViewEventLineContent {
3622
- flex: 1;
3623
- background: var(--vscode-toolbar-activeBackground, rgba(255, 255, 255, 0.1));
3624
- min-width: 0;
3625
- overflow-wrap: anywhere;
3626
- white-space: pre-wrap;
3627
- word-break: break-word;
3628
- outline: 1px solid var(--vscode-focusBorder, rgba(255, 255, 255, 0.4));
3629
-
3630
- .ChatDebugViewEventLineNumber {
3631
- flex: none;
3632
- }
3924
+ const mergeClassNames = (...classNames) => {
3925
+ return classNames.filter(Boolean).join(' ');
3926
+ };
3633
3927
 
3634
- .row {
3635
- flex-shrink: 0;
3636
- min-width: 0;
3637
- }
3928
+ const text = data => {
3929
+ return {
3930
+ childCount: 0,
3931
+ text: data,
3932
+ type: Text
3933
+ };
3934
+ };
3638
3935
 
3639
- .ChatDebugViewRefreshButton {
3640
- display: inline-flex;
3641
- align-items: center;
3642
- justify-content: center;
3643
- flex: none;
3644
- margin-left: auto;
3645
- min-height: 28px;
3646
- padding: 0 10px;
3647
- border: 1px solid rgba(255, 255, 255, 0.16);
3648
- border-radius: 6px;
3649
- background: linear-gradient(180deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.04));
3650
- color: inherit;
3651
- font: inherit;
3652
- font-size: 12px;
3653
- font-weight: 500;
3654
- line-height: 1;
3655
- white-space: nowrap;
3656
- cursor: pointer;
3657
- transition: background-color 120ms ease, border-color 120ms ease, transform 120ms ease;
3658
- }
3936
+ const SetText = 1;
3937
+ const Replace = 2;
3938
+ const SetAttribute = 3;
3939
+ const RemoveAttribute = 4;
3940
+ const Add = 6;
3941
+ const NavigateChild = 7;
3942
+ const NavigateParent = 8;
3943
+ const RemoveChild = 9;
3944
+ const NavigateSibling = 10;
3945
+ const SetReferenceNodeUid = 11;
3659
3946
 
3660
- .ChatDebugViewRefreshButton:hover {
3661
- background: linear-gradient(180deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0.08));
3662
- border-color: rgba(255, 255, 255, 0.24);
3663
- }
3947
+ const isKey = key => {
3948
+ return key !== 'type' && key !== 'childCount';
3949
+ };
3664
3950
 
3665
- .ChatDebugViewRefreshButton:active {
3666
- transform: translateY(1px);
3667
- }
3668
-
3669
- .ChatDebugViewRefreshButton:focus-visible {
3670
- outline: 2px solid rgba(255, 255, 255, 0.4);
3671
- outline-offset: 1px;
3672
- }
3673
-
3674
- .ChatDebugViewEventRow:hover {
3675
- background: var(--ListHoverBackground);
3676
- color: var(--ListHoverForeground);
3677
- }
3678
-
3679
- .ChatDebugViewImagePreview {
3680
- display: flex;
3681
- flex-direction: column;
3682
- align-items: flex-start;
3683
- gap: 8px;
3684
- max-width: 100%;
3685
- }
3686
-
3687
- .ChatDebugViewImagePreviewImage {
3688
- display: block;
3689
- max-width: 100%;
3690
- max-height: 320px;
3691
- border: 1px solid var(--vscode-widget-border, rgba(255, 255, 255, 0.14));
3692
- border-radius: 6px;
3693
- object-fit: contain;
3694
- }
3695
-
3696
- .ChatDebugViewImagePreviewLabel {
3697
- color: var(--vscode-descriptionForeground, inherit);
3698
- }
3699
-
3700
- .ChatDebugViewTimeline {
3701
- display: flex;
3702
- flex-direction: column;
3703
- gap: 8px;
3704
- }
3705
-
3706
- .ChatDebugViewTimelineTop {
3707
- display: flex;
3708
- align-items: center;
3709
- min-width: 0;
3710
- }
3711
-
3712
- .ChatDebugViewTimelineSummary {
3713
- margin: 0;
3714
- color: var(--vscode-descriptionForeground, inherit);
3715
- font-size: 11px;
3716
- font-weight: 600;
3717
- }
3718
-
3719
- .ChatDebugViewTimelineInteractive {
3720
- position: relative;
3721
- height: 54px;
3722
- overflow: hidden;
3723
- border: 1px solid var(--vscode-widget-border, rgba(255, 255, 255, 0.14));
3724
- border-radius: 8px;
3725
- background: linear-gradient(180deg, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0.02));
3726
- contain: strict;
3727
- user-select: none;
3728
- }
3729
-
3730
- .ChatDebugViewTimelineBuckets {
3731
- position: absolute;
3732
- inset: 18px 8px 8px;
3733
- display: flex;
3734
- align-items: flex-end;
3735
- gap: 2px;
3736
- }
3737
-
3738
- .ChatDebugViewTimelineBucket {
3739
- display: flex;
3740
- flex: 1;
3741
- align-items: flex-end;
3742
- height: 100%;
3743
- min-width: 0;
3744
- cursor: pointer;
3745
- }
3746
-
3747
- .ChatDebugViewTimelineBucketBar {
3748
- display: flex;
3749
- flex: 1;
3750
- flex-direction: column;
3751
- justify-content: flex-end;
3752
- gap: 2px;
3753
- height: 100%;
3754
- }
3755
-
3756
- .ChatDebugViewTimelineBucketUnit {
3757
- flex: none;
3758
- height: 4px;
3759
- border-radius: 999px;
3760
- background: var(--vscode-charts-blue, rgba(91, 151, 255, 0.9));
3761
- }
3762
-
3763
- .ChatDebugViewTimelineBucketUnitEmpty {
3764
- opacity: 0.18;
3765
- }
3766
-
3767
- .ChatDebugViewTimelineBucketSelected .ChatDebugViewTimelineBucketUnit,
3768
- .ChatDebugViewTimelineBucketBarSelected .ChatDebugViewTimelineBucketUnit {
3769
- background: var(--vscode-charts-orange, rgba(255, 174, 0, 0.95));
3770
- }
3771
-
3772
- .ChatDebugViewTimelineSelectionOverlay {
3773
- position: absolute;
3774
- inset: 0;
3775
- pointer-events: none;
3776
- }
3777
-
3778
- .ChatDebugViewTimelineSelectionRange {
3779
- position: absolute;
3780
- top: 18px;
3781
- bottom: 8px;
3782
- border-radius: 6px;
3783
- background: color-mix(in srgb, var(--vscode-charts-orange, rgba(255, 174, 0, 0.95)) 18%, transparent);
3784
- outline: 1px solid color-mix(in srgb, var(--vscode-charts-orange, rgba(255, 174, 0, 0.95)) 55%, transparent);
3785
- }
3786
-
3787
- .ChatDebugViewTimelineSelectionMarker {
3788
- position: absolute;
3789
- top: 0;
3790
- bottom: 0;
3791
- width: 14px;
3792
- margin-left: -7px;
3793
- padding: 0;
3794
- border: 0;
3795
- background: linear-gradient(
3796
- 90deg,
3797
- transparent calc(50% - 1px),
3798
- var(--vscode-charts-orange, rgba(255, 174, 0, 0.95)) calc(50% - 1px),
3799
- var(--vscode-charts-orange, rgba(255, 174, 0, 0.95)) calc(50% + 1px),
3800
- transparent calc(50% + 1px)
3801
- );
3802
- }
3803
-
3804
- .ChatDebugViewTimelineSelectionHandle {
3805
- pointer-events: auto;
3806
- cursor: ew-resize;
3807
- }
3808
-
3809
- .ChatDebugViewTimelineSelectionHandle::before {
3810
- content: '';
3811
- position: absolute;
3812
- top: 0;
3813
- left: 50%;
3814
- width: 14px;
3815
- height: 16px;
3816
- transform: translateX(-50%);
3817
- border: 1px solid var(--vscode-widget-border, rgba(255, 255, 255, 0.22));
3818
- border-radius: 4px;
3819
- background: linear-gradient(180deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.08));
3820
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
3821
- }
3822
-
3823
- .ChatDebugViewTimelineSelectionHandle::after {
3824
- content: '';
3825
- position: absolute;
3826
- top: 5px;
3827
- left: 50%;
3828
- width: 7px;
3829
- height: 6px;
3830
- transform: translateX(-50%);
3831
- background: linear-gradient(
3832
- 90deg,
3833
- transparent 0,
3834
- transparent 1px,
3835
- var(--vscode-foreground, rgba(255, 255, 255, 0.88)) 1px,
3836
- var(--vscode-foreground, rgba(255, 255, 255, 0.88)) 2px,
3837
- transparent 2px,
3838
- transparent 4px,
3839
- var(--vscode-foreground, rgba(255, 255, 255, 0.88)) 4px,
3840
- var(--vscode-foreground, rgba(255, 255, 255, 0.88)) 5px,
3841
- transparent 5px,
3842
- transparent 100%
3843
- );
3844
- opacity: 0.8;
3845
- }
3846
-
3847
- .ChatDebugViewTimelineSelectionHandle:hover::before {
3848
- background: linear-gradient(180deg, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0.12));
3849
- }
3850
-
3851
- .ChatDebugViewTimelineSelectionHandle:focus-visible {
3852
- outline: 2px solid var(--vscode-focusBorder, rgba(255, 255, 255, 0.45));
3853
- outline-offset: 1px;
3854
- }
3855
- `;
3856
- };
3857
-
3858
- const renderCss = (oldState, newState) => {
3859
- const css = getCss(newState);
3860
- return [SetCss, newState.uid, css];
3861
- };
3862
-
3863
- const mergeClassNames = (...classNames) => {
3864
- return classNames.filter(Boolean).join(' ');
3865
- };
3866
-
3867
- const text = data => {
3868
- return {
3869
- childCount: 0,
3870
- text: data,
3871
- type: Text
3872
- };
3873
- };
3874
-
3875
- const SetText = 1;
3876
- const Replace = 2;
3877
- const SetAttribute = 3;
3878
- const RemoveAttribute = 4;
3879
- const Add = 6;
3880
- const NavigateChild = 7;
3881
- const NavigateParent = 8;
3882
- const RemoveChild = 9;
3883
- const NavigateSibling = 10;
3884
- const SetReferenceNodeUid = 11;
3885
-
3886
- const isKey = key => {
3887
- return key !== 'type' && key !== 'childCount';
3888
- };
3889
-
3890
- const getKeys = node => {
3891
- const keys = Object.keys(node).filter(isKey);
3892
- return keys;
3893
- };
3951
+ const getKeys = node => {
3952
+ const keys = Object.keys(node).filter(isKey);
3953
+ return keys;
3954
+ };
3894
3955
 
3895
3956
  const arrayToTree = nodes => {
3896
3957
  const result = [];
@@ -4165,48 +4226,59 @@ const ChatDebugViewDevtools = 'ChatDebugView--devtools';
4165
4226
  const ChatDebugViewDetails = 'ChatDebugViewDetails';
4166
4227
  const ChatDebugViewDetailsBottom = 'ChatDebugViewDetailsBottom';
4167
4228
  const ChatDebugViewDetailsClose = 'ChatDebugViewDetailsClose';
4168
- const ChatDebugViewDetailsTab = 'ChatDebugViewDetailsTab';
4169
- const ChatDebugViewDetailsTabSelected = 'ChatDebugViewDetailsTabSelected';
4229
+ const EditorContainer = 'EditorContainer';
4230
+ const PanelTab = 'PanelTab';
4231
+ const PanelTabSelected = 'PanelTabSelected';
4170
4232
  const ChatDebugViewDetailsTabs = 'ChatDebugViewDetailsTabs';
4171
4233
  const ChatDebugViewDetailsTop = 'ChatDebugViewDetailsTop';
4172
- const ChatDebugViewDevtoolsMain = 'ChatDebugViewDevtoolsMain';
4173
4234
  const ChatDebugViewDevtoolsSplit = 'ChatDebugViewDevtoolsSplit';
4174
4235
  const ChatDebugViewEmpty = 'ChatDebugViewEmpty';
4175
4236
  const ChatDebugViewError = 'ChatDebugViewError';
4176
- const ChatDebugViewEvent = 'ChatDebugViewEvent';
4177
- const ChatDebugViewEventLineContent = 'ChatDebugViewEventLineContent';
4237
+ const EditorContent = 'EditorContent';
4238
+ const EditorInput = 'EditorInput';
4239
+ const EditorLayers = 'EditorLayers';
4240
+ const EditorRow = 'EditorRow';
4241
+ const EditorRows = 'EditorRows';
4242
+ const EditorSelection = 'EditorSelection';
4243
+ const EditorSelections = 'Selections';
4244
+ const EditorViewlet = 'Viewlet Editor';
4178
4245
  const ChatDebugViewEventLineNumber = 'ChatDebugViewEventLineNumber';
4179
- const ChatDebugViewEventRow = 'ChatDebugViewEventRow';
4180
- const ChatDebugViewEventRowSelected = 'ChatDebugViewEventRowSelected';
4246
+ const Gutter = 'Gutter';
4247
+ const TableRowSelected = 'TableRowSelected';
4181
4248
  const ChatDebugViewEvents = 'ChatDebugViewEvents';
4182
4249
  const ChatDebugViewEventsFullWidth = 'ChatDebugViewEventsFullWidth';
4183
4250
  const ChatDebugViewFilterInput = 'ChatDebugViewFilterInput';
4184
4251
  const ChatDebugViewFilterInputDevtools = 'ChatDebugViewFilterInput--devtools';
4185
- const ChatDebugViewHeaderCell = 'ChatDebugViewHeaderCell';
4186
- const ChatDebugViewHeaderCellDuration = 'ChatDebugViewHeaderCellDuration';
4187
- const ChatDebugViewHeaderCellStatus = 'ChatDebugViewHeaderCellStatus';
4188
- const ChatDebugViewHeaderCellType = 'ChatDebugViewHeaderCellType';
4252
+ const ChatDebugViewHeaderCell = 'TableCell';
4189
4253
  const ChatDebugViewImagePreview = 'ChatDebugViewImagePreview';
4254
+ const ChatDebugViewImagePreviewImageWrapper = 'ChatDebugViewImagePreviewImageWrapper';
4190
4255
  const ChatDebugViewImagePreviewImage = 'ChatDebugViewImagePreviewImage';
4191
4256
  const ChatDebugViewImagePreviewLabel = 'ChatDebugViewImagePreviewLabel';
4192
4257
  const ChatDebugViewRefreshButton = 'ChatDebugViewRefreshButton';
4193
4258
  const ChatDebugViewQuickFilterPill = 'ChatDebugViewQuickFilterPill';
4194
4259
  const ChatDebugViewQuickFilterPillSelected = 'ChatDebugViewQuickFilterPillSelected';
4195
4260
  const ChatDebugViewQuickFilters = 'ChatDebugViewQuickFilters';
4196
- const ChatDebugViewSash = 'ChatDebugViewSash';
4261
+ const Sash = 'Sash';
4197
4262
  const ChatDebugViewSashLine = 'ChatDebugViewSashLine';
4198
- const ChatDebugViewTable = 'ChatDebugViewTable';
4199
- const ChatDebugViewTableBody = 'ChatDebugViewTableBody';
4200
- const ChatDebugViewTableHeader = 'ChatDebugViewTableHeader';
4201
- const ChatDebugViewTableHeaderRow = 'ChatDebugViewTableHeaderRow';
4202
- const ChatDebugViewTableWrapper = 'ChatDebugViewTableWrapper';
4203
- const ChatDebugViewResizer = 'ChatDebugViewResizer';
4204
- const ChatDebugViewResizerInner = 'ChatDebugViewResizerInner';
4205
- const ChatDebugViewResizerOne = 'ChatDebugViewResizerOne';
4206
- const ChatDebugViewResizerTwo = 'ChatDebugViewResizerTwo';
4207
- const ChatDebugViewResizers = 'ChatDebugViewResizers';
4263
+ const Table = 'Table';
4264
+ const TableBody = 'TableBody';
4265
+ const TableSummary = 'TableSummary';
4266
+ const TableWrapper = 'TableWrapper';
4267
+ const TableWrapperWrapper = 'TableWrapperWrapper';
4268
+ const FocusOutline = 'FocusOutline';
4269
+ const Resizer = 'Resizer';
4270
+ const ResizerInner = 'ResizerInner';
4271
+ const ResizerOne = 'ResizerOne';
4272
+ const ResizerTwo = 'ResizerTwo';
4273
+ const TableHead = 'TableHead';
4274
+ const Resizers = 'Resizers';
4275
+ const TableCol = 'TableCol';
4276
+ const TableRow = 'TableRow';
4277
+ const TableRowOdd = 'TableRowOdd';
4208
4278
  const TableRowEven = 'TableRowEven';
4209
4279
  const ChatDebugViewTimeline = 'ChatDebugViewTimeline';
4280
+ const ChatDebugViewTimelineBadge = 'ChatDebugViewTimelineBadge';
4281
+ const ChatDebugViewTimelineBadges = 'ChatDebugViewTimelineBadges';
4210
4282
  const ChatDebugViewTimelineBucket = 'ChatDebugViewTimelineBucket';
4211
4283
  const ChatDebugViewTimelineBucketBar = 'ChatDebugViewTimelineBucketBar';
4212
4284
  const ChatDebugViewTimelineBucketBarSelected = 'ChatDebugViewTimelineBucketBarSelected';
@@ -4214,29 +4286,37 @@ const ChatDebugViewTimelineBucketSelected = 'ChatDebugViewTimelineBucketSelected
4214
4286
  const ChatDebugViewTimelineBucketUnit = 'ChatDebugViewTimelineBucketUnit';
4215
4287
  const ChatDebugViewTimelineBucketUnitEmpty = 'ChatDebugViewTimelineBucketUnitEmpty';
4216
4288
  const ChatDebugViewTimelineBuckets = 'ChatDebugViewTimelineBuckets';
4289
+ const ChatDebugViewTimelineCursorGuide = 'ChatDebugViewTimelineCursorGuide';
4290
+ const ChatDebugViewTimelineCursorGuideVisible = 'ChatDebugViewTimelineCursorGuideVisible';
4217
4291
  const ChatDebugViewTimelineInteractive = 'ChatDebugViewTimelineInteractive';
4218
4292
  const ChatDebugViewTimelineSelectionHandle = 'ChatDebugViewTimelineSelectionHandle';
4293
+ const ChatDebugViewTimelineSelectionHandleEnd = 'ChatDebugViewTimelineSelectionHandleEnd';
4294
+ const ChatDebugViewTimelineSelectionHandleStart = 'ChatDebugViewTimelineSelectionHandleStart';
4219
4295
  const ChatDebugViewTimelineSelectionMarker = 'ChatDebugViewTimelineSelectionMarker';
4220
4296
  const ChatDebugViewTimelineSelectionMarkerEnd = 'ChatDebugViewTimelineSelectionMarkerEnd';
4221
4297
  const ChatDebugViewTimelineSelectionMarkerStart = 'ChatDebugViewTimelineSelectionMarkerStart';
4222
4298
  const ChatDebugViewTimelineSelectionOverlay = 'ChatDebugViewTimelineSelectionOverlay';
4223
4299
  const ChatDebugViewTimelineSelectionRange = 'ChatDebugViewTimelineSelectionRange';
4224
- const ChatDebugViewTimelineSummary = 'ChatDebugViewTimelineSummary';
4225
4300
  const ChatDebugViewTimelineTop = 'ChatDebugViewTimelineTop';
4226
4301
  const ChatDebugViewTiming = 'ChatDebugViewTiming';
4227
4302
  const ChatDebugViewTimingLabel = 'ChatDebugViewTimingLabel';
4303
+ const ChatDebugViewTimingPreview = 'ChatDebugViewTimingPreview';
4304
+ const ChatDebugViewTimingPreviewMarker = 'ChatDebugViewTimingPreviewMarker';
4305
+ const ChatDebugViewTimingPreviewMarkerEnd = 'ChatDebugViewTimingPreviewMarkerEnd';
4306
+ const ChatDebugViewTimingPreviewMarkerStart = 'ChatDebugViewTimingPreviewMarkerStart';
4307
+ const ChatDebugViewTimingPreviewRail = 'ChatDebugViewTimingPreviewRail';
4308
+ const ChatDebugViewTimingPreviewSegment = 'ChatDebugViewTimingPreviewSegment';
4309
+ const ChatDebugViewTimingPreviewTrack = 'ChatDebugViewTimingPreviewTrack';
4310
+ const ChatDebugViewTimingPreviewTrackOverlay = 'ChatDebugViewTimingPreviewTrackOverlay';
4228
4311
  const ChatDebugViewTimingRow = 'ChatDebugViewTimingRow';
4229
4312
  const ChatDebugViewTimingValue = 'ChatDebugViewTimingValue';
4230
4313
  const ChatDebugViewTop = 'ChatDebugViewTop';
4231
4314
  const ChatDebugViewTopDevtools = 'ChatDebugViewTop--devtools';
4232
- const ChatDebugViewCell = 'ChatDebugViewCell';
4315
+ const TableCell = 'TableCell';
4233
4316
  const ChatDebugViewColumnFixed = 'ChatDebugViewColumnFixed';
4234
4317
  const ChatDebugViewCellDuration = 'ChatDebugViewCellDuration';
4235
- const ChatDebugViewCellStatus = 'ChatDebugViewCellStatus';
4236
4318
  const ChatDebugViewCellStatusError = 'ChatDebugViewCellStatusError';
4237
- const ChatDebugViewCellType = 'ChatDebugViewCellType';
4238
4319
  const InputBox = 'InputBox';
4239
- const Row = 'row';
4240
4320
  const TokenBoolean = 'Token TokenBoolean';
4241
4321
  const TokenKey = 'Token TokenKey';
4242
4322
  const TokenNumeric = 'Token TokenNumeric';
@@ -4260,7 +4340,7 @@ const getDebugErrorDom = errorMessage => {
4260
4340
  const HandleEventCategoryFilter = 4;
4261
4341
  const HandleFilterInput = 5;
4262
4342
  const SelectDetailTab = 6;
4263
- const HandleEventRowClick = 7;
4343
+ const HandleEventRowClickAt = 7;
4264
4344
  const HandleHeaderContextMenu = 8;
4265
4345
  const HandleSashPointerDown = 9;
4266
4346
  const HandleSashPointerMove = 10;
@@ -4274,11 +4354,59 @@ const HandleTimelinePointerDown = 17;
4274
4354
  const HandleTimelinePointerMove = 18;
4275
4355
  const HandleTimelinePointerUp = 19;
4276
4356
  const HandleTimelineDoubleClick = 20;
4357
+ const HandleTableHeaderClick = 21;
4277
4358
  const HandleTimelineRangePreset = 22;
4278
4359
  const HandleCloseDetails = 23;
4279
4360
  const HandleClickRefresh = 24;
4280
4361
  const HandleDetailsTopContextMenu = 25;
4281
4362
  const HandleTimelineContextMenu = 26;
4363
+ const HandleTimelinePointerLeave = 27;
4364
+ const HandleEventRowClick = 28;
4365
+ const HandleTableFocus = 29;
4366
+ const HandleDetailTabsFocus = 30;
4367
+
4368
+ const getFilterInputDom = (filterValue, useDevtoolsLayout) => {
4369
+ return {
4370
+ autocomplete: 'off',
4371
+ childCount: 0,
4372
+ className: useDevtoolsLayout ? mergeClassNames(InputBox, ChatDebugViewFilterInput, ChatDebugViewFilterInputDevtools) : mergeClassNames(InputBox, ChatDebugViewFilterInput),
4373
+ inputType: 'search',
4374
+ name: Filter,
4375
+ onInput: HandleFilterInput,
4376
+ placeholder: filterEvents(),
4377
+ type: Input,
4378
+ value: filterValue
4379
+ };
4380
+ };
4381
+
4382
+ const getQuickFilterDom = categoryFilter => {
4383
+ const {
4384
+ isSelected,
4385
+ label,
4386
+ name
4387
+ } = categoryFilter;
4388
+ return [{
4389
+ ariaSelected: isSelected,
4390
+ childCount: 1,
4391
+ className: mergeClassNames(ChatDebugViewQuickFilterPill, isSelected ? ChatDebugViewQuickFilterPillSelected : ''),
4392
+ name,
4393
+ onClick: HandleEventCategoryFilter,
4394
+ role: Option,
4395
+ type: Button$1
4396
+ }, text(label)];
4397
+ };
4398
+
4399
+ // cspell:ignore multiselectable
4400
+ const getQuickFilterNodes = categoryFilters => {
4401
+ return [{
4402
+ 'aria-multiselectable': true,
4403
+ childCount: categoryFilters.length,
4404
+ className: ChatDebugViewQuickFilters,
4405
+ onClick: HandleEventCategoryFilter,
4406
+ role: ListBox,
4407
+ type: Div
4408
+ }, ...categoryFilters.flatMap(getQuickFilterDom)];
4409
+ };
4282
4410
 
4283
4411
  const refreshButtonDom = [{
4284
4412
  'aria-label': refreshEvents$1(),
@@ -4293,360 +4421,116 @@ const getRefreshButtonDom = () => {
4293
4421
  return refreshButtonDom;
4294
4422
  };
4295
4423
 
4296
- const getDebugViewTopDom = (filterValue, useDevtoolsLayout, quickFilterNodes) => {
4424
+ const getDebugViewTopDom = (filterValue, useDevtoolsLayout, categoryFilters) => {
4297
4425
  const refreshButtonDom = getRefreshButtonDom();
4298
4426
  if (useDevtoolsLayout) {
4427
+ const quickFilterNodes = getQuickFilterNodes(categoryFilters);
4299
4428
  return [{
4300
4429
  childCount: 2 + (quickFilterNodes.length > 0 ? 1 : 0),
4301
4430
  className: mergeClassNames(ChatDebugViewTop, ChatDebugViewTopDevtools),
4302
4431
  onContextMenu: HandleHeaderContextMenu,
4303
4432
  type: Search
4304
- }, {
4305
- autocomplete: 'off',
4306
- childCount: 0,
4307
- className: mergeClassNames(InputBox, ChatDebugViewFilterInput, ChatDebugViewFilterInputDevtools),
4308
- inputType: 'search',
4309
- name: Filter,
4310
- onInput: HandleFilterInput,
4311
- placeholder: filterEvents(),
4312
- type: Input,
4313
- value: filterValue
4314
- }, ...quickFilterNodes, ...refreshButtonDom];
4433
+ }, getFilterInputDom(filterValue, true), ...quickFilterNodes, ...refreshButtonDom];
4315
4434
  }
4316
4435
  return [{
4317
4436
  childCount: 2,
4318
4437
  className: ChatDebugViewTop,
4319
4438
  onContextMenu: HandleHeaderContextMenu,
4320
4439
  type: Search
4321
- }, {
4322
- autocomplete: 'off',
4323
- childCount: 0,
4324
- className: mergeClassNames(InputBox, ChatDebugViewFilterInput),
4325
- inputType: 'search',
4326
- name: Filter,
4327
- onInput: HandleFilterInput,
4328
- placeholder: filterEvents(),
4329
- type: Input,
4330
- value: filterValue
4331
- }, ...refreshButtonDom];
4332
- };
4333
-
4334
- const None = 'none';
4335
-
4336
- const getPanelId = detailTab => {
4337
- return `ChatDebugViewDetailsPanel-${detailTab}`;
4440
+ }, getFilterInputDom(filterValue, false), ...refreshButtonDom];
4338
4441
  };
4339
4442
 
4340
- const getTabId = detailTab => {
4341
- return `ChatDebugViewDetailsTab-${detailTab}`;
4443
+ const detailsCloseButtonDom = [{
4444
+ 'aria-label': closeDetails(),
4445
+ childCount: 1,
4446
+ className: ChatDebugViewDetailsClose,
4447
+ name: CloseDetails,
4448
+ onChange: HandleCloseDetails,
4449
+ onClick: HandleCloseDetails,
4450
+ type: Button$1,
4451
+ value: 'close'
4452
+ }, {
4453
+ childCount: 0,
4454
+ className: 'MaskIcon MaskIconClose',
4455
+ type: Div
4456
+ }];
4457
+ const getDetailsCloseButtonDom = () => {
4458
+ return detailsCloseButtonDom;
4342
4459
  };
4343
4460
 
4344
- const getDetailTabDom = detailTab => {
4345
- const {
4346
- isSelected
4347
- } = detailTab;
4461
+ const getEditorSelectionDom = () => {
4348
4462
  return [{
4349
- 'aria-controls': getPanelId(detailTab.name),
4350
- 'aria-selected': isSelected,
4351
4463
  childCount: 1,
4352
- className: mergeClassNames(ChatDebugViewDetailsTab, isSelected ? ChatDebugViewDetailsTabSelected : ''),
4353
- id: getTabId(detailTab.name),
4354
- name: DetailTab,
4355
- onChange: SelectDetailTab,
4356
- onClick: SelectDetailTab,
4357
- role: 'tab',
4358
- tabIndex: isSelected ? 0 : -1,
4359
- type: Button$1,
4360
- value: detailTab.name
4361
- }, text(detailTab.label)];
4464
+ className: EditorSelections,
4465
+ type: Div
4466
+ }, {
4467
+ childCount: 0,
4468
+ className: EditorSelection,
4469
+ style: 'height: 20px; left: 0px; top: 20px; width: 0px;',
4470
+ type: Div
4471
+ }];
4362
4472
  };
4363
-
4364
- const getTabNodes = detailTabs => {
4473
+ const getGutterDom = (lineData, showLineNumbers) => {
4474
+ const gutterNodes = showLineNumbers ? lineData.flatMap((_, index) => {
4475
+ return [{
4476
+ childCount: 1,
4477
+ className: ChatDebugViewEventLineNumber,
4478
+ type: Span
4479
+ }, text(String(index + 1))];
4480
+ }) : [];
4365
4481
  return [{
4366
- 'aria-label': detailSections(),
4367
- childCount: detailTabs.length,
4368
- className: ChatDebugViewDetailsTabs,
4369
- role: 'tablist',
4482
+ childCount: showLineNumbers ? lineData.length : 0,
4483
+ className: Gutter,
4370
4484
  type: Div
4371
- }, ...detailTabs.flatMap(getDetailTabDom)];
4372
- };
4373
-
4374
- const getDurationText = event => {
4375
- const explicitDuration = event.durationMs ?? event.duration;
4376
- if (typeof explicitDuration === 'number' && Number.isFinite(explicitDuration)) {
4377
- return `${explicitDuration}ms`;
4378
- }
4379
- const start = toTimeNumber(event.started ?? event.startTime ?? event.startTimestamp ?? event.timestamp);
4380
- const end = toTimeNumber(event.ended ?? event.endTime ?? event.endTimestamp ?? event.timestamp);
4381
- if (start === undefined || end === undefined || end < start) {
4382
- return '-';
4383
- }
4384
- return `${end - start}ms`;
4385
- };
4386
-
4387
- const timestampFormatter = new Intl.DateTimeFormat('en-US', {
4388
- day: '2-digit',
4389
- fractionalSecondDigits: 3,
4390
- hour: '2-digit',
4391
- hourCycle: 'h23',
4392
- minute: '2-digit',
4393
- month: 'short',
4394
- second: '2-digit',
4395
- timeZone: 'UTC',
4396
- year: 'numeric'
4397
- });
4398
- const formatTimestamp = date => {
4399
- return `${timestampFormatter.format(date)} UTC`;
4400
- };
4401
-
4402
- const getTimestampText = value => {
4403
- if (typeof value === 'string') {
4404
- const timestamp = Date.parse(value);
4405
- if (!Number.isNaN(timestamp)) {
4406
- return formatTimestamp(new Date(timestamp));
4407
- }
4408
- return value;
4409
- }
4410
- if (typeof value === 'number' && Number.isFinite(value)) {
4411
- return formatTimestamp(new Date(value));
4412
- }
4413
- return '-';
4414
- };
4415
-
4416
- const getEndText = event => {
4417
- return getTimestampText(event.ended ?? event.endTime ?? event.endTimestamp ?? event.timestamp);
4418
- };
4419
-
4420
- const getStartText = event => {
4421
- return getTimestampText(event.started ?? event.startTime ?? event.startTimestamp ?? event.timestamp);
4422
- };
4423
-
4424
- const timingRowNode = {
4425
- childCount: 2,
4426
- className: ChatDebugViewTimingRow,
4427
- type: Div
4428
- };
4429
- const timingLabelNode = {
4430
- childCount: 1,
4431
- className: ChatDebugViewTimingLabel,
4432
- type: Span
4433
- };
4434
- const timingValueNode = {
4435
- childCount: 1,
4436
- className: ChatDebugViewTimingValue,
4437
- type: Span
4438
- };
4439
- const getTimingRowDom = (label, value) => {
4440
- return [timingRowNode, timingLabelNode, text(label), timingValueNode, text(value)];
4485
+ }, ...gutterNodes];
4441
4486
  };
4442
-
4443
- const getTimingDetailsDom = event => {
4487
+ const getEditorRowDom = line => {
4444
4488
  return [{
4445
- childCount: 3,
4446
- className: ChatDebugViewTiming,
4489
+ childCount: line.childCount,
4490
+ className: EditorRow,
4447
4491
  type: Div
4448
- }, ...getTimingRowDom(started(), getStartText(event)), ...getTimingRowDom(ended(), getEndText(event)), ...getTimingRowDom(duration(), getDurationText(event))];
4492
+ }, ...line.nodes];
4449
4493
  };
4450
-
4451
- const getContentNode = (previewEventNodes, payloadEventNodes, responseEventNodes, selectedEvent, detailTabs) => {
4452
- const safeSelectedDetailTab = getSelectedDetailTab(detailTabs);
4453
- const contentNodes = safeSelectedDetailTab === Timing && selectedEvent ? getTimingDetailsDom(selectedEvent) : safeSelectedDetailTab === Preview ? previewEventNodes : safeSelectedDetailTab === Payload ? payloadEventNodes : responseEventNodes;
4454
- return {
4455
- contentNodes,
4456
- safeSelectedDetailTab
4457
- };
4494
+ const getEditorRowsDom = lineData => {
4495
+ return [{
4496
+ childCount: lineData.length,
4497
+ className: EditorRows,
4498
+ type: Div
4499
+ }, ...lineData.flatMap(getEditorRowDom)];
4458
4500
  };
4459
- const getDetailsDom = (previewEventNodes, payloadEventNodes = previewEventNodes, responseEventNodes = payloadEventNodes, selectedEvent = null, detailTabs = createDetailTabs()) => {
4460
- if (previewEventNodes.length === 0 && payloadEventNodes.length === 0 && responseEventNodes.length === 0) {
4461
- return [];
4462
- }
4463
- const normalizedDetailTabs = selectedEvent ? createDetailTabs(getSelectedDetailTab(detailTabs), selectedEvent) : detailTabs;
4464
- const {
4465
- contentNodes,
4466
- safeSelectedDetailTab
4467
- } = getContentNode(previewEventNodes, payloadEventNodes, responseEventNodes, selectedEvent, normalizedDetailTabs);
4501
+ const getEditorDom = (lineData, showLineNumbers = true) => {
4468
4502
  return [{
4469
- childCount: 2,
4470
- className: ChatDebugViewDetails,
4471
- type: Section
4503
+ childCount: 1,
4504
+ className: EditorContainer,
4505
+ type: Div
4472
4506
  }, {
4473
4507
  childCount: 2,
4474
- className: ChatDebugViewDetailsTop,
4475
- onContextMenu: HandleDetailsTopContextMenu,
4508
+ className: EditorViewlet,
4509
+ role: 'code',
4510
+ type: Div
4511
+ }, ...getGutterDom(lineData, showLineNumbers), {
4512
+ childCount: 2,
4513
+ className: EditorContent,
4476
4514
  type: Div
4477
4515
  }, {
4478
- 'aria-label': closeDetails(),
4516
+ 'aria-autocomplete': 'list',
4517
+ 'aria-multiline': true,
4518
+ 'aria-roledescription': 'editor',
4519
+ autocapitalize: 'off',
4520
+ autocomplete: 'off',
4521
+ autocorrect: 'off',
4479
4522
  childCount: 0,
4480
- className: ChatDebugViewDetailsClose,
4481
- name: CloseDetails,
4482
- onChange: HandleCloseDetails,
4483
- onClick: HandleCloseDetails,
4484
- type: Button$1,
4485
- value: 'close'
4486
- }, ...getTabNodes(normalizedDetailTabs), {
4487
- 'aria-labelledby': getTabId(safeSelectedDetailTab),
4488
- childCount: 1,
4489
- className: ChatDebugViewDetailsBottom,
4490
- id: getPanelId(safeSelectedDetailTab),
4491
- onContextMenu: HandleDetailsContextMenu,
4492
- role: 'tabpanel',
4493
- type: Div
4494
- }, ...contentNodes];
4495
- };
4496
-
4497
- const toolExecutionTypePrefix = 'tool-execution';
4498
- const getToolName = event => {
4499
- if (typeof event.toolName === 'string' && event.toolName) {
4500
- return event.toolName;
4501
- }
4502
- if (typeof event.name === 'string' && event.name) {
4503
- return event.name;
4504
- }
4505
- const {
4506
- arguments: toolArguments
4507
- } = event;
4508
- if (!toolArguments || typeof toolArguments !== 'object') {
4509
- return undefined;
4510
- }
4511
- const {
4512
- name
4513
- } = toolArguments;
4514
- if (typeof name !== 'string' || !name) {
4515
- return undefined;
4516
- }
4517
- return name;
4518
- };
4519
- const getEventTypeLabel = event => {
4520
- if (!event.type.startsWith(toolExecutionTypePrefix)) {
4521
- return event.type;
4522
- }
4523
- const toolName = getToolName(event);
4524
- if (!toolName) {
4525
- return event.type;
4526
- }
4527
- return `${event.type}, ${toolName}`;
4528
- };
4529
-
4530
- const isErrorStatusCode = value => {
4531
- if (typeof value === 'number') {
4532
- return value >= 400;
4533
- }
4534
- if (typeof value === 'string') {
4535
- const parsedStatus = Number(value);
4536
- return Number.isFinite(parsedStatus) && parsedStatus >= 400;
4537
- }
4538
- return false;
4539
- };
4540
-
4541
- const isRecord = value => {
4542
- return typeof value === 'object' && value !== null;
4543
- };
4544
-
4545
- const hasErrorStatus = event => {
4546
- if (event.type === 'error') {
4547
- return true;
4548
- }
4549
- if (event.success === false || event.ok === false) {
4550
- return true;
4551
- }
4552
- const {
4553
- status
4554
- } = event;
4555
- if (isErrorStatusCode(status)) {
4556
- return true;
4557
- }
4558
- const {
4559
- result
4560
- } = event;
4561
- if (isRecord(result)) {
4562
- if (isErrorStatusCode(result.status)) {
4563
- return true;
4564
- }
4565
- if (isToolEvent(event) && 'error' in result && result.error !== undefined) {
4566
- return true;
4567
- }
4568
- if (typeof result.error === 'string' || typeof result.errorMessage === 'string' || typeof result.exception === 'string') {
4569
- return true;
4570
- }
4571
- }
4572
- return typeof event.error === 'string' || typeof event.errorMessage === 'string' || typeof event.exception === 'string';
4573
- };
4574
-
4575
- const getStatusText = event => {
4576
- return hasErrorStatus(event) ? '400' : '200';
4577
- };
4578
-
4579
- const getRowCellNodes = (event, isErrorStatus, visibleTableColumns) => {
4580
- const orderedVisibleTableColumns = getOrderedVisibleTableColumns(visibleTableColumns);
4581
- return orderedVisibleTableColumns.flatMap((column, index) => {
4582
- const isFixed = index < orderedVisibleTableColumns.length - 1;
4583
- switch (column) {
4584
- case Duration:
4585
- return [{
4586
- childCount: 1,
4587
- className: mergeClassNames(ChatDebugViewCell, ChatDebugViewCellDuration, isFixed ? ChatDebugViewColumnFixed : ''),
4588
- type: Td
4589
- }, text(getDurationText(event))];
4590
- case Status:
4591
- return [{
4592
- childCount: 1,
4593
- className: mergeClassNames(ChatDebugViewCell, ChatDebugViewCellStatus, isErrorStatus ? ChatDebugViewCellStatusError : '', isFixed ? ChatDebugViewColumnFixed : ''),
4594
- type: Td
4595
- }, text(getStatusText(event))];
4596
- case Type:
4597
- return [{
4598
- childCount: 1,
4599
- className: mergeClassNames(ChatDebugViewCell, ChatDebugViewCellType, isFixed ? ChatDebugViewColumnFixed : ''),
4600
- type: Td
4601
- }, text(getEventTypeLabel(event))];
4602
- default:
4603
- return [];
4604
- }
4605
- });
4606
- };
4607
-
4608
- const getDevtoolsRows = (events, selectedEventIndex, visibleTableColumns = defaultVisibleTableColumns) => {
4609
- return events.flatMap((event, i) => {
4610
- const isEvenRow = i % 2 === 1;
4611
- const isSelected = selectedEventIndex === i;
4612
- const isErrorStatus = hasErrorStatus(event);
4613
- const rowIndex = String(i);
4614
- const rowCellNodes = getRowCellNodes(event, isErrorStatus, visibleTableColumns);
4615
- return [{
4616
- childCount: visibleTableColumns.length,
4617
- className: mergeClassNames(ChatDebugViewEventRow, isEvenRow ? TableRowEven : '', isSelected ? ChatDebugViewEventRowSelected : ''),
4618
- 'data-index': rowIndex,
4619
- type: Tr
4620
- }, ...rowCellNodes];
4621
- });
4622
- };
4623
-
4624
- const emptyStateNode = {
4625
- childCount: 1,
4626
- className: ChatDebugViewEmpty,
4627
- type: Div
4628
- };
4629
- const getEmptyStateDom = emptyMessage => {
4630
- return [emptyStateNode, text(emptyMessage)];
4631
- };
4632
-
4633
- const getLineNodeDom = (line, index) => {
4634
- return [{
4523
+ className: EditorInput,
4524
+ name: 'editor',
4525
+ role: 'textbox',
4526
+ spellcheck: false,
4527
+ type: TextArea,
4528
+ wrap: 'off'
4529
+ }, {
4635
4530
  childCount: 2,
4636
- className: Row,
4531
+ className: EditorLayers,
4637
4532
  type: Div
4638
- }, {
4639
- childCount: 1,
4640
- className: ChatDebugViewEventLineNumber,
4641
- type: Span
4642
- }, text(String(index + 1)), {
4643
- childCount: line.childCount,
4644
- className: ChatDebugViewEventLineContent,
4645
- type: Span
4646
- }, ...line.nodes];
4647
- };
4648
- const getLineNodes = lines => {
4649
- return lines.flatMap(getLineNodeDom);
4533
+ }, ...getEditorSelectionDom(), ...getEditorRowsDom(lineData)];
4650
4534
  };
4651
4535
 
4652
4536
  const isDigit = character => {
@@ -4805,23 +4689,18 @@ const getEventNode = value => {
4805
4689
  type: getEventTypeLabel(value)
4806
4690
  } : value;
4807
4691
  const lines = getJsonLines(renderedValue);
4808
- const lineNodes = getLineNodes(lines.map(line => {
4692
+ const lineData = lines.map(line => {
4809
4693
  const lineContentNodes = getLineContentNodes(line);
4810
4694
  return {
4811
4695
  childCount: lineContentNodes.length / 2,
4812
4696
  nodes: lineContentNodes
4813
4697
  };
4814
- }));
4815
- return [{
4816
- childCount: lines.length,
4817
- className: ChatDebugViewEvent,
4818
- type: Div
4819
- }, ...lineNodes];
4698
+ });
4699
+ return getEditorDom(lineData);
4820
4700
  };
4821
4701
 
4822
- const getEventsClassName = hasSelectedEvent => {
4823
- const widthClassName = mergeClassNames(ChatDebugViewEvents, hasSelectedEvent ? '' : ChatDebugViewEventsFullWidth);
4824
- return widthClassName;
4702
+ const getPanelId = detailTab => {
4703
+ return `ChatDebugViewDetailsPanel-${detailTab}`;
4825
4704
  };
4826
4705
 
4827
4706
  const getPreviewName = event => {
@@ -4850,6 +4729,9 @@ const shouldIncludeArguments = (event, name) => {
4850
4729
 
4851
4730
  const getPayloadEvent = event => {
4852
4731
  const name = getPreviewName(event);
4732
+ if (name === 'list_files' && hasOwn(event, 'arguments')) {
4733
+ return event.arguments;
4734
+ }
4853
4735
  const payloadEvent = {
4854
4736
  ...(name === undefined ? {} : {
4855
4737
  name
@@ -4867,6 +4749,26 @@ const getPayloadEvent = event => {
4867
4749
  return event;
4868
4750
  };
4869
4751
 
4752
+ const getListFilesPreviewEvent = (event, name) => {
4753
+ if (name !== 'list_files') {
4754
+ return undefined;
4755
+ }
4756
+ const {
4757
+ result
4758
+ } = event;
4759
+ if (typeof result !== 'object' || result === null) {
4760
+ return undefined;
4761
+ }
4762
+ const {
4763
+ entries,
4764
+ error
4765
+ } = result;
4766
+ if (entries !== undefined) {
4767
+ return entries;
4768
+ }
4769
+ return error;
4770
+ };
4771
+
4870
4772
  const isChatMessageAddedEvent = event => {
4871
4773
  return event.type === 'chat-message-added';
4872
4774
  };
@@ -4875,10 +4777,64 @@ const isChatMessageUpdatedEvent = event => {
4875
4777
  return event.type === 'chat-message-updated';
4876
4778
  };
4877
4779
 
4780
+ const getResponseContentText = content => {
4781
+ if (!content || typeof content !== 'object') {
4782
+ return undefined;
4783
+ }
4784
+ if (Array.isArray(content)) {
4785
+ const [firstContentItem] = content;
4786
+ if (!firstContentItem || typeof firstContentItem !== 'object') {
4787
+ return undefined;
4788
+ }
4789
+ const {
4790
+ text
4791
+ } = firstContentItem;
4792
+ return typeof text === 'string' ? text : undefined;
4793
+ }
4794
+ const {
4795
+ text
4796
+ } = content;
4797
+ return typeof text === 'string' ? text : undefined;
4798
+ };
4799
+ const getSseResponseCompletedPreviewText = event => {
4800
+ if (event.type !== 'sse-response-completed') {
4801
+ return undefined;
4802
+ }
4803
+ const {
4804
+ value
4805
+ } = event;
4806
+ if (!value || typeof value !== 'object') {
4807
+ return undefined;
4808
+ }
4809
+ const {
4810
+ response
4811
+ } = value;
4812
+ if (!response || typeof response !== 'object') {
4813
+ return undefined;
4814
+ }
4815
+ const {
4816
+ output
4817
+ } = response;
4818
+ if (!Array.isArray(output) || output.length === 0) {
4819
+ return undefined;
4820
+ }
4821
+ const [firstOutput] = output;
4822
+ if (!firstOutput || typeof firstOutput !== 'object') {
4823
+ return undefined;
4824
+ }
4825
+ const {
4826
+ content
4827
+ } = firstOutput;
4828
+ return getResponseContentText(content);
4829
+ };
4878
4830
  const getPreviewMessageText = event => {
4879
4831
  if (isChatMessageUpdatedEvent(event) && typeof event.text === 'string') {
4880
4832
  return event.text;
4881
4833
  }
4834
+ const sseResponseCompletedPreviewText = getSseResponseCompletedPreviewText(event);
4835
+ if (sseResponseCompletedPreviewText !== undefined) {
4836
+ return sseResponseCompletedPreviewText;
4837
+ }
4882
4838
  if (!isChatMessageAddedEvent(event)) {
4883
4839
  return undefined;
4884
4840
  }
@@ -4900,6 +4856,19 @@ const getPreviewMessageText = event => {
4900
4856
  return text;
4901
4857
  };
4902
4858
 
4859
+ const getReadFilePreviewText = (event, name) => {
4860
+ if (name !== 'read_file') {
4861
+ return undefined;
4862
+ }
4863
+ const {
4864
+ result
4865
+ } = event;
4866
+ if (typeof result !== 'string') {
4867
+ return undefined;
4868
+ }
4869
+ return result;
4870
+ };
4871
+
4903
4872
  const getWriteFilePreviewText = (event, name) => {
4904
4873
  if (name !== 'write_file') {
4905
4874
  return undefined;
@@ -4919,152 +4888,569 @@ const getWriteFilePreviewText = (event, name) => {
4919
4888
  return content;
4920
4889
  };
4921
4890
 
4922
- const getPreviewEvent = event => {
4923
- const selectedEventPreview = getSelectedEventPreview(event);
4924
- if (selectedEventPreview !== undefined) {
4925
- return selectedEventPreview;
4926
- }
4927
- const previewMessageText = getPreviewMessageText(event);
4928
- if (previewMessageText !== undefined) {
4929
- return previewMessageText;
4930
- }
4931
- const name = getPreviewName(event);
4932
- const writeFilePreviewText = getWriteFilePreviewText(event, name);
4933
- if (writeFilePreviewText !== undefined) {
4934
- return writeFilePreviewText;
4891
+ const getPreviewEvent = event => {
4892
+ const selectedEventPreview = getSelectedEventPreview(event);
4893
+ if (selectedEventPreview !== undefined) {
4894
+ return selectedEventPreview;
4895
+ }
4896
+ const previewMessageText = getPreviewMessageText(event);
4897
+ if (previewMessageText !== undefined) {
4898
+ return previewMessageText;
4899
+ }
4900
+ const name = getPreviewName(event);
4901
+ const writeFilePreviewText = getWriteFilePreviewText(event, name);
4902
+ if (writeFilePreviewText !== undefined) {
4903
+ return writeFilePreviewText;
4904
+ }
4905
+ const readFilePreviewText = getReadFilePreviewText(event, name);
4906
+ if (readFilePreviewText !== undefined) {
4907
+ return readFilePreviewText;
4908
+ }
4909
+ const listFilesPreviewEvent = getListFilesPreviewEvent(event, name);
4910
+ if (listFilesPreviewEvent !== undefined) {
4911
+ return listFilesPreviewEvent;
4912
+ }
4913
+ return getPayloadEvent(event);
4914
+ };
4915
+
4916
+ const isAttachmentImagePreview = value => {
4917
+ return typeof value === 'object' && value !== null && value.previewType === 'image';
4918
+ };
4919
+
4920
+ const getImagePreviewLabelDom = preview => {
4921
+ if (preview.stats === undefined) {
4922
+ return [{
4923
+ childCount: 1,
4924
+ className: ChatDebugViewImagePreviewLabel,
4925
+ type: Span
4926
+ }, text(preview.alt)];
4927
+ }
4928
+ return [{
4929
+ childCount: 2,
4930
+ className: ChatDebugViewImagePreviewLabel,
4931
+ type: Span
4932
+ }, {
4933
+ childCount: 1,
4934
+ type: Span
4935
+ }, text(preview.stats), {
4936
+ childCount: 1,
4937
+ type: Span
4938
+ }, text(preview.alt)];
4939
+ };
4940
+ const getImagePreviewDom = preview => {
4941
+ return [{
4942
+ childCount: 2,
4943
+ className: ChatDebugViewImagePreview,
4944
+ type: Div
4945
+ }, {
4946
+ childCount: 1,
4947
+ className: ChatDebugViewImagePreviewImageWrapper,
4948
+ type: Div
4949
+ }, {
4950
+ alt: preview.alt,
4951
+ childCount: 0,
4952
+ className: ChatDebugViewImagePreviewImage,
4953
+ src: preview.src,
4954
+ type: Img
4955
+ }, ...getImagePreviewLabelDom(preview)];
4956
+ };
4957
+
4958
+ const getTextNode = (value, showLineNumbers = true) => {
4959
+ const lines = value.split('\n');
4960
+ const lineData = lines.map(line => {
4961
+ return {
4962
+ childCount: 2,
4963
+ nodes: [{
4964
+ childCount: 1,
4965
+ className: TokenText,
4966
+ type: Span
4967
+ }, text(line)]
4968
+ };
4969
+ });
4970
+ return getEditorDom(lineData, showLineNumbers);
4971
+ };
4972
+
4973
+ const getPreviewEventNodes = (previewEvent, selectedEvent) => {
4974
+ if (typeof previewEvent === 'string') {
4975
+ const isInvalidImageMessage = previewEvent === ImageCouldNotBeLoaded;
4976
+ const isChatMessageUpdatedPreview = !!selectedEvent && isChatMessageUpdatedEvent(selectedEvent);
4977
+ const showLineNumbers = !isInvalidImageMessage && !isChatMessageUpdatedPreview;
4978
+ return getTextNode(previewEvent, showLineNumbers);
4979
+ }
4980
+ if (previewEvent === undefined) {
4981
+ return [];
4982
+ }
4983
+ if (isAttachmentImagePreview(previewEvent)) {
4984
+ return getImagePreviewDom(previewEvent);
4985
+ }
4986
+ return getEventNode(previewEvent);
4987
+ };
4988
+
4989
+ const getDetailTabDom = detailTab => {
4990
+ const {
4991
+ isSelected
4992
+ } = detailTab;
4993
+ return [{
4994
+ 'aria-controls': getPanelId(detailTab.name),
4995
+ ariaSelected: isSelected,
4996
+ childCount: 1,
4997
+ className: mergeClassNames(PanelTab, isSelected ? PanelTabSelected : ''),
4998
+ name: detailTab.name,
4999
+ onChange: SelectDetailTab,
5000
+ onClick: SelectDetailTab,
5001
+ onFocus: HandleDetailTabsFocus,
5002
+ role: Tab,
5003
+ tabIndex: isSelected ? 0 : -1,
5004
+ type: Button$1
5005
+ }, text(detailTab.label)];
5006
+ };
5007
+
5008
+ const getTabNodes = detailTabs => {
5009
+ return [{
5010
+ 'aria-label': detailSections(),
5011
+ childCount: detailTabs.length,
5012
+ className: ChatDebugViewDetailsTabs,
5013
+ role: 'tablist',
5014
+ type: Div
5015
+ }, ...detailTabs.flatMap(getDetailTabDom)];
5016
+ };
5017
+
5018
+ const timestampFormatter = new Intl.DateTimeFormat('en-US', {
5019
+ day: '2-digit',
5020
+ fractionalSecondDigits: 3,
5021
+ hour: '2-digit',
5022
+ hourCycle: 'h23',
5023
+ minute: '2-digit',
5024
+ month: 'short',
5025
+ second: '2-digit',
5026
+ timeZone: 'UTC',
5027
+ year: 'numeric'
5028
+ });
5029
+ const formatTimestamp = date => {
5030
+ return `${timestampFormatter.format(date)} UTC`;
5031
+ };
5032
+
5033
+ const getTimestampText = value => {
5034
+ if (typeof value === 'string') {
5035
+ const timestamp = Date.parse(value);
5036
+ if (!Number.isNaN(timestamp)) {
5037
+ return formatTimestamp(new Date(timestamp));
5038
+ }
5039
+ return value;
5040
+ }
5041
+ if (typeof value === 'number' && Number.isFinite(value)) {
5042
+ return formatTimestamp(new Date(value));
5043
+ }
5044
+ return '-';
5045
+ };
5046
+
5047
+ const getEndText = event => {
5048
+ return getTimestampText(event.ended ?? event.endTime ?? event.endTimestamp ?? event.timestamp);
5049
+ };
5050
+
5051
+ const getStartText = event => {
5052
+ return getTimestampText(event.started ?? event.startTime ?? event.startTimestamp ?? event.timestamp);
5053
+ };
5054
+
5055
+ const getTimingPreviewSegments = event => {
5056
+ return [{
5057
+ endPercent: 100,
5058
+ label: getDurationText(event),
5059
+ startPercent: 0
5060
+ }];
5061
+ };
5062
+ const getTimingPreviewSegmentNodes = segments => {
5063
+ return [{
5064
+ childCount: segments.length,
5065
+ className: ChatDebugViewTimingPreviewTrackOverlay,
5066
+ type: Div
5067
+ }, ...segments.flatMap(segment => {
5068
+ const widthPercent = Math.max(0, segment.endPercent - segment.startPercent);
5069
+ return [{
5070
+ childCount: 1,
5071
+ className: ChatDebugViewTimingPreviewSegment,
5072
+ style: `left:${segment.startPercent}%;width:${widthPercent}%;min-width:2px;`,
5073
+ type: Div
5074
+ }, text(segment.label)];
5075
+ })];
5076
+ };
5077
+ const getTimingPreviewDom = event => {
5078
+ const segments = getTimingPreviewSegments(event);
5079
+ return [{
5080
+ childCount: 1,
5081
+ className: ChatDebugViewTimingPreview,
5082
+ type: Div
5083
+ }, {
5084
+ childCount: 4,
5085
+ className: ChatDebugViewTimingPreviewTrack,
5086
+ type: Div
5087
+ }, {
5088
+ childCount: 0,
5089
+ className: ChatDebugViewTimingPreviewRail,
5090
+ type: Div
5091
+ }, ...getTimingPreviewSegmentNodes(segments), {
5092
+ childCount: 0,
5093
+ className: `${ChatDebugViewTimingPreviewMarker} ${ChatDebugViewTimingPreviewMarkerStart}`,
5094
+ style: 'left:12px;',
5095
+ type: Div
5096
+ }, {
5097
+ childCount: 0,
5098
+ className: `${ChatDebugViewTimingPreviewMarker} ${ChatDebugViewTimingPreviewMarkerEnd}`,
5099
+ style: 'right:12px;',
5100
+ type: Div
5101
+ }];
5102
+ };
5103
+
5104
+ const timingRowNode = {
5105
+ childCount: 2,
5106
+ className: ChatDebugViewTimingRow,
5107
+ type: Div
5108
+ };
5109
+ const timingLabelNode = {
5110
+ childCount: 1,
5111
+ className: ChatDebugViewTimingLabel,
5112
+ type: Span
5113
+ };
5114
+ const timingValueNode = {
5115
+ childCount: 1,
5116
+ className: ChatDebugViewTimingValue,
5117
+ type: Span
5118
+ };
5119
+ const getTimingRowDom = (label, value) => {
5120
+ return [timingRowNode, timingLabelNode, text(label), timingValueNode, text(value)];
5121
+ };
5122
+
5123
+ const getTimingDetailsDom = event => {
5124
+ return [{
5125
+ childCount: 4,
5126
+ className: ChatDebugViewTiming,
5127
+ type: Div
5128
+ }, ...getTimingPreviewDom(event), ...getTimingRowDom(started(), getStartText(event)), ...getTimingRowDom(ended(), getEndText(event)), ...getTimingRowDom(duration(), getDurationText(event))];
5129
+ };
5130
+
5131
+ const getNextSiblingIndex$2 = (nodes, index) => {
5132
+ let nextSiblingIndex = index + 1;
5133
+ const childCount = nodes[index]?.childCount || 0;
5134
+ for (let i = 0; i < childCount; i++) {
5135
+ nextSiblingIndex = getNextSiblingIndex$2(nodes, nextSiblingIndex);
5136
+ }
5137
+ return nextSiblingIndex;
5138
+ };
5139
+ const getDirectChildCount$1 = nodes => {
5140
+ let count = 0;
5141
+ let index = 0;
5142
+ while (index < nodes.length) {
5143
+ count++;
5144
+ index = getNextSiblingIndex$2(nodes, index);
5145
+ }
5146
+ return count;
5147
+ };
5148
+ const getNormalizedDetailTabs = (selectedEvent, detailTabs) => {
5149
+ if (selectedEvent === null) {
5150
+ return detailTabs;
5151
+ }
5152
+ return createDetailTabs(getSelectedDetailTab(detailTabs), selectedEvent);
5153
+ };
5154
+ const getDetailsDom = (previewEventNodes, payloadEventNodes = previewEventNodes, responseEventNodes = payloadEventNodes, selectedEvent = null, detailTabs = createDetailTabs()) => {
5155
+ if (previewEventNodes.length === 0 && payloadEventNodes.length === 0 && responseEventNodes.length === 0) {
5156
+ return [];
5157
+ }
5158
+ const normalizedDetailTabs = getNormalizedDetailTabs(selectedEvent, detailTabs);
5159
+ const safeSelectedDetailTab = getSelectedDetailTab(normalizedDetailTabs);
5160
+ const selectedDetailTab = normalizedDetailTabs.find(detailTab => detailTab.name === safeSelectedDetailTab) ?? normalizedDetailTabs[0];
5161
+ const getDetailContentDom = () => {
5162
+ const getDetailContentDomTiming = () => {
5163
+ if (selectedEvent === null) {
5164
+ return responseEventNodes;
5165
+ }
5166
+ return getTimingDetailsDom(selectedEvent);
5167
+ };
5168
+ const getDetailContentDomPreview = () => {
5169
+ if (previewEventNodes.length > 0) {
5170
+ return previewEventNodes;
5171
+ }
5172
+ if (selectedEvent === null) {
5173
+ return [];
5174
+ }
5175
+ return getPreviewEventNodes(getPreviewEvent(selectedEvent), selectedEvent);
5176
+ };
5177
+ const getDetailContentDomPayload = () => {
5178
+ if (payloadEventNodes.length > 0) {
5179
+ return payloadEventNodes;
5180
+ }
5181
+ if (selectedEvent === null) {
5182
+ return [];
5183
+ }
5184
+ return getEventNode(getPayloadEvent(selectedEvent));
5185
+ };
5186
+ const getDetailContentDomResponse = () => {
5187
+ if (responseEventNodes.length > 0) {
5188
+ return responseEventNodes;
5189
+ }
5190
+ if (selectedEvent === null) {
5191
+ return [];
5192
+ }
5193
+ return getEventNode(selectedEvent);
5194
+ };
5195
+ const contentNodes = safeSelectedDetailTab === Timing ? getDetailContentDomTiming() : safeSelectedDetailTab === Preview ? getDetailContentDomPreview() : safeSelectedDetailTab === Payload ? getDetailContentDomPayload() : getDetailContentDomResponse();
5196
+ return [{
5197
+ 'aria-label': selectedDetailTab.label,
5198
+ childCount: getDirectChildCount$1(contentNodes),
5199
+ className: ChatDebugViewDetailsBottom,
5200
+ id: getPanelId(safeSelectedDetailTab),
5201
+ onContextMenu: HandleDetailsContextMenu,
5202
+ role: 'tabpanel',
5203
+ type: Div
5204
+ }, ...contentNodes];
5205
+ };
5206
+ return [{
5207
+ childCount: 2,
5208
+ className: ChatDebugViewDetails,
5209
+ type: Section
5210
+ }, {
5211
+ childCount: 2,
5212
+ className: ChatDebugViewDetailsTop,
5213
+ onContextMenu: HandleDetailsTopContextMenu,
5214
+ type: Div
5215
+ }, ...getDetailsCloseButtonDom(), ...getTabNodes(normalizedDetailTabs), ...getDetailContentDom()];
5216
+ };
5217
+
5218
+ const getRowCellNodes = (event, isErrorStatus, visibleTableColumns) => {
5219
+ const orderedVisibleTableColumns = getOrderedVisibleTableColumns(visibleTableColumns);
5220
+ return orderedVisibleTableColumns.flatMap((column, index) => {
5221
+ const isFixed = index < orderedVisibleTableColumns.length - 1;
5222
+ switch (column) {
5223
+ case Duration:
5224
+ return [{
5225
+ childCount: 1,
5226
+ className: mergeClassNames(TableCell, ChatDebugViewCellDuration),
5227
+ type: Td
5228
+ }, text(getEventTableDurationText(event))];
5229
+ case Status$1:
5230
+ return [{
5231
+ childCount: 1,
5232
+ className: mergeClassNames(TableCell, isErrorStatus ? ChatDebugViewCellStatusError : '', isFixed ? ChatDebugViewColumnFixed : ''),
5233
+ type: Td
5234
+ }, text(getStatusText(event))];
5235
+ case Type:
5236
+ return [{
5237
+ childCount: 1,
5238
+ className: TableCell,
5239
+ type: Td
5240
+ }, text(getEventTableTypeLabel(event))];
5241
+ default:
5242
+ return [];
5243
+ }
5244
+ });
5245
+ };
5246
+
5247
+ const getDevtoolsRows = (events, selectedEventIndex, visibleTableColumns = defaultVisibleTableColumns) => {
5248
+ return events.flatMap((event, i) => {
5249
+ const isEvenRow = i % 2 === 1;
5250
+ const rowClassName = isEvenRow ? TableRowEven : TableRowOdd;
5251
+ const isSelected = selectedEventIndex === i;
5252
+ const isErrorStatus = hasErrorStatus(event);
5253
+ const rowCellNodes = getRowCellNodes(event, isErrorStatus, visibleTableColumns);
5254
+ return [{
5255
+ childCount: visibleTableColumns.length,
5256
+ className: mergeClassNames(TableRow, rowClassName, isSelected ? TableRowSelected : ''),
5257
+ type: Tr
5258
+ }, ...rowCellNodes];
5259
+ });
5260
+ };
5261
+
5262
+ const emptyStateNode = {
5263
+ childCount: 1,
5264
+ className: ChatDebugViewEmpty,
5265
+ type: Div
5266
+ };
5267
+ const getEmptyStateDom = emptyMessage => {
5268
+ return [emptyStateNode, text(emptyMessage)];
5269
+ };
5270
+
5271
+ const getEventsClassName = hasSelectedEvent => {
5272
+ const widthClassName = mergeClassNames(ChatDebugViewEvents, hasSelectedEvent ? '' : ChatDebugViewEventsFullWidth);
5273
+ return widthClassName;
5274
+ };
5275
+
5276
+ const sashNodesDom = [{
5277
+ childCount: 1,
5278
+ className: Sash,
5279
+ onPointerDown: HandleSashPointerDown,
5280
+ type: Button$1
5281
+ }, {
5282
+ childCount: 0,
5283
+ className: ChatDebugViewSashLine,
5284
+ type: Div
5285
+ }];
5286
+ const getSashNodesDom = hasSelectedEvent => {
5287
+ if (!hasSelectedEvent) {
5288
+ return [];
4935
5289
  }
4936
- return getPayloadEvent(event);
5290
+ return sashNodesDom;
4937
5291
  };
4938
5292
 
4939
- const isAttachmentImagePreview = value => {
4940
- return typeof value === 'object' && value !== null && value.previewType === 'image';
4941
- };
5293
+ const None = 'none';
5294
+ const Status = 'status';
4942
5295
 
4943
- const getImagePreviewDom = preview => {
5296
+ const getNextSiblingIndex$1 = (nodes, index) => {
5297
+ let nextSiblingIndex = index + 1;
5298
+ const childCount = nodes[index]?.childCount || 0;
5299
+ for (let i = 0; i < childCount; i++) {
5300
+ nextSiblingIndex = getNextSiblingIndex$1(nodes, nextSiblingIndex);
5301
+ }
5302
+ return nextSiblingIndex;
5303
+ };
5304
+ const getDirectChildCount = nodes => {
5305
+ let count = 0;
5306
+ let index = 0;
5307
+ while (index < nodes.length) {
5308
+ count++;
5309
+ index = getNextSiblingIndex$1(nodes, index);
5310
+ }
5311
+ return count;
5312
+ };
5313
+ const getSplitViewDom = (splitChildCount, eventsClassName, tableNodes, sashNodes, detailsNodes) => {
5314
+ const eventsChildCount = getDirectChildCount(tableNodes);
5315
+ if (splitChildCount === 1) {
5316
+ return [{
5317
+ childCount: eventsChildCount,
5318
+ className: eventsClassName,
5319
+ role: 'application',
5320
+ type: Div
5321
+ }, ...tableNodes];
5322
+ }
4944
5323
  return [{
4945
- childCount: 2,
4946
- className: ChatDebugViewImagePreview,
5324
+ childCount: splitChildCount,
5325
+ className: ChatDebugViewDevtoolsSplit,
5326
+ role: None,
4947
5327
  type: Div
4948
5328
  }, {
4949
- alt: preview.alt,
4950
- childCount: 0,
4951
- className: ChatDebugViewImagePreviewImage,
4952
- src: preview.src,
4953
- type: Img
4954
- }, {
4955
- childCount: 1,
4956
- className: ChatDebugViewImagePreviewLabel,
4957
- type: Span
4958
- }, text(preview.alt)];
5329
+ childCount: eventsChildCount,
5330
+ className: eventsClassName,
5331
+ role: 'application',
5332
+ type: Div
5333
+ }, ...tableNodes, ...sashNodes, ...detailsNodes];
4959
5334
  };
4960
5335
 
4961
- const getTextNode = value => {
4962
- const lines = value.split('\n');
4963
- const lineNodes = getLineNodes(lines.map(line => {
4964
- return {
4965
- childCount: 1,
4966
- nodes: [{
4967
- childCount: 1,
4968
- className: TokenText,
4969
- type: Span
4970
- }, text(line)]
4971
- };
4972
- }));
4973
- return [{
4974
- childCount: lines.length,
4975
- className: ChatDebugViewEvent,
4976
- type: Div
4977
- }, ...lineNodes];
5336
+ const formatTimelineMilliseconds = value => {
5337
+ return `${Math.round(value * 1000)}ms`;
4978
5338
  };
4979
5339
 
4980
- const getPreviewEventNodes = previewEvent => {
4981
- if (typeof previewEvent === 'string') {
4982
- return getTextNode(previewEvent);
5340
+ const formatTimelineSeconds = value => {
5341
+ if (Number.isInteger(value)) {
5342
+ return `${value}s`;
4983
5343
  }
4984
- if (previewEvent === undefined) {
4985
- return [];
5344
+ return `${Number(value.toFixed(1))}s`;
5345
+ };
5346
+
5347
+ const getEndTime = event => {
5348
+ return event.ended ?? event.endTime ?? event.timestamp;
5349
+ };
5350
+
5351
+ const getStartTime = event => {
5352
+ return event.started ?? event.startTime ?? event.timestamp;
5353
+ };
5354
+
5355
+ const formatTableSummaryDuration = durationMs => {
5356
+ if (durationMs < 1000) {
5357
+ return formatTimelineMilliseconds(durationMs / 1000);
4986
5358
  }
4987
- if (isAttachmentImagePreview(previewEvent)) {
4988
- return getImagePreviewDom(previewEvent);
5359
+ return formatTimelineSeconds(durationMs / 1000);
5360
+ };
5361
+ const getTableSummary = events => {
5362
+ let minStart = Number.POSITIVE_INFINITY;
5363
+ let maxEnd = Number.NEGATIVE_INFINITY;
5364
+ for (const event of events) {
5365
+ const startTime = toTimeNumber(getStartTime(event));
5366
+ const endTime = toTimeNumber(getEndTime(event));
5367
+ if (typeof startTime === 'number' && Number.isFinite(startTime)) {
5368
+ minStart = Math.min(minStart, startTime);
5369
+ }
5370
+ if (typeof endTime === 'number' && Number.isFinite(endTime)) {
5371
+ maxEnd = Math.max(maxEnd, endTime);
5372
+ }
4989
5373
  }
4990
- return getEventNode(previewEvent);
5374
+ const durationMs = Number.isFinite(minStart) && Number.isFinite(maxEnd) ? Math.max(0, maxEnd - minStart) : 0;
5375
+ return tableSummary(events.length, formatTableSummaryDuration(durationMs));
4991
5376
  };
4992
5377
 
4993
- const sashNodesDom = [{
5378
+ const tableSummaryNode = {
4994
5379
  childCount: 1,
4995
- className: ChatDebugViewSash,
4996
- onPointerDown: HandleSashPointerDown,
4997
- type: Div
4998
- }, {
4999
- childCount: 0,
5000
- className: ChatDebugViewSashLine,
5380
+ className: TableSummary,
5381
+ role: Status,
5001
5382
  type: Div
5002
- }];
5003
- const getSashNodesDom = hasSelectedEvent => {
5004
- if (!hasSelectedEvent) {
5383
+ };
5384
+ const getTableSummaryDom = summary => {
5385
+ if (!summary) {
5005
5386
  return [];
5006
5387
  }
5007
- return sashNodesDom;
5388
+ return [tableSummaryNode, text(summary)];
5008
5389
  };
5009
5390
 
5010
5391
  const getTableBodyDom = (rowNodes, eventCount) => {
5011
5392
  return [{
5012
5393
  childCount: eventCount === 0 ? 1 : eventCount,
5013
- className: ChatDebugViewTableBody,
5394
+ className: TableBody,
5014
5395
  onContextMenu: HandleTableBodyContextMenu,
5015
- onPointerDown: HandleEventRowClick,
5396
+ onPointerDown: HandleEventRowClickAt,
5016
5397
  type: TBody
5017
5398
  }, ...rowNodes];
5018
5399
  };
5019
5400
 
5401
+ const tableColClassNames = ['TableColZero', 'TableColOne', 'TableColTwo'];
5402
+ const getTableColumnGroupDom = visibleTableColumns => {
5403
+ const orderedVisibleTableColumns = getOrderedVisibleTableColumns(visibleTableColumns);
5404
+ return [{
5405
+ childCount: orderedVisibleTableColumns.length,
5406
+ className: 'ColGroup',
5407
+ type: ColGroup
5408
+ }, ...orderedVisibleTableColumns.map((_, index) => ({
5409
+ childCount: 0,
5410
+ className: `${TableCol} ${tableColClassNames[index]}`,
5411
+ type: Col
5412
+ }))];
5413
+ };
5414
+
5415
+ const getHeaderCellNode = (column, tableColumns) => {
5416
+ return [{
5417
+ childCount: 1,
5418
+ className: ChatDebugViewHeaderCell,
5419
+ name: column,
5420
+ onClick: HandleTableHeaderClick,
5421
+ type: Th
5422
+ }, text(getTableColumnLabel(tableColumns, column))];
5423
+ };
5020
5424
  const getHeaderCellNodes = (visibleTableColumns, tableColumns = createTableColumns()) => {
5021
5425
  const orderedVisibleTableColumns = getOrderedVisibleTableColumns(visibleTableColumns, tableColumns);
5022
- return orderedVisibleTableColumns.flatMap((column, index) => {
5023
- const isFixed = index < orderedVisibleTableColumns.length - 1;
5024
- switch (column) {
5025
- case Duration:
5026
- return [{
5027
- childCount: 1,
5028
- className: mergeClassNames(ChatDebugViewHeaderCell, ChatDebugViewHeaderCellDuration, isFixed ? ChatDebugViewColumnFixed : ''),
5029
- scope: 'col',
5030
- type: Th
5031
- }, text(getTableColumnLabel(tableColumns, column))];
5032
- case Status:
5033
- return [{
5034
- childCount: 1,
5035
- className: mergeClassNames(ChatDebugViewHeaderCell, ChatDebugViewHeaderCellStatus, isFixed ? ChatDebugViewColumnFixed : ''),
5036
- scope: 'col',
5037
- type: Th
5038
- }, text(getTableColumnLabel(tableColumns, column))];
5039
- case Type:
5040
- return [{
5041
- childCount: 1,
5042
- className: mergeClassNames(ChatDebugViewHeaderCell, ChatDebugViewHeaderCellType, isFixed ? ChatDebugViewColumnFixed : ''),
5043
- scope: 'col',
5044
- type: Th
5045
- }, text(getTableColumnLabel(tableColumns, column))];
5046
- default:
5047
- return [];
5048
- }
5049
- });
5426
+ return orderedVisibleTableColumns.flatMap(column => getHeaderCellNode(column, tableColumns));
5050
5427
  };
5051
5428
 
5052
5429
  const getTableHeaderDom = (visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns()) => {
5053
- const headerCellNodes = getHeaderCellNodes(visibleTableColumns, tableColumns);
5054
5430
  return [{
5055
5431
  childCount: 1,
5056
- className: ChatDebugViewTableHeader,
5432
+ className: TableHead,
5057
5433
  onContextMenu: HandleHeaderContextMenu,
5058
5434
  type: THead
5059
5435
  }, {
5060
5436
  childCount: visibleTableColumns.length,
5061
- className: ChatDebugViewTableHeaderRow,
5437
+ className: TableRow,
5062
5438
  type: Tr
5063
- }, ...headerCellNodes];
5439
+ }, ...getHeaderCellNodes(visibleTableColumns, tableColumns)];
5440
+ };
5441
+
5442
+ const getTableDom = (rowNodes, eventCount, visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns(), summary = '', focus = 0) => {
5443
+ return [{
5444
+ childCount: 3,
5445
+ className: Table,
5446
+ onFocus: HandleTableFocus,
5447
+ tabIndex: 0,
5448
+ type: Table$1
5449
+ }, ...getTableColumnGroupDom(visibleTableColumns), ...getTableHeaderDom(visibleTableColumns, tableColumns), ...getTableBodyDom(rowNodes, eventCount)];
5064
5450
  };
5065
5451
 
5066
5452
  const resizerNames = ['ResizerOne', 'ResizerTwo'];
5067
- const resizerClassNames = [ChatDebugViewResizerOne, ChatDebugViewResizerTwo];
5453
+ const resizerClassNames = [ResizerOne, ResizerTwo];
5068
5454
  const getTableResizersDom = visibleTableColumns => {
5069
5455
  const visibleColumnCount = getOrderedVisibleTableColumns(visibleTableColumns).length;
5070
5456
  const resizerCount = Math.max(0, visibleColumnCount - 1);
@@ -5074,34 +5460,45 @@ const getTableResizersDom = visibleTableColumns => {
5074
5460
  const visibleResizerClassNames = resizerClassNames.slice(0, resizerCount);
5075
5461
  const resizerNodes = visibleResizerClassNames.flatMap((resizerClassName, index) => [{
5076
5462
  childCount: 1,
5077
- className: `${ChatDebugViewResizer} ${resizerClassName}`,
5463
+ className: mergeClassNames(Resizer, resizerClassName),
5078
5464
  name: resizerNames[index],
5079
5465
  onPointerDown: HandleTableResizerPointerDown,
5080
5466
  role: None,
5467
+ tabIndex: -1,
5081
5468
  type: Button$1
5082
5469
  }, {
5083
5470
  childCount: 0,
5084
- className: ChatDebugViewResizerInner,
5471
+ className: ResizerInner,
5472
+ role: None,
5085
5473
  type: Div
5086
5474
  }]);
5087
5475
  return [{
5088
5476
  childCount: resizerCount,
5089
- className: ChatDebugViewResizers,
5477
+ className: Resizers,
5090
5478
  type: Div
5091
5479
  }, ...resizerNodes];
5092
5480
  };
5093
5481
 
5094
- const getTableDom = (rowNodes, eventCount, visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns()) => {
5095
- const resizerNodes = getTableResizersDom(visibleTableColumns);
5482
+ const getTableWrapperDom = (rowNodes, eventCount, visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns(), summary = '', focus = 0, className = '', role = '') => {
5483
+ const tableWrapperClassName = mergeClassNames(TableWrapper, focus === FocusChatDebugTable ? FocusOutline : '', className);
5484
+ const tableWrapperNode = {
5485
+ childCount: 2,
5486
+ className: tableWrapperClassName,
5487
+ type: Div,
5488
+ ...(role ? {
5489
+ role
5490
+ } : {})
5491
+ };
5492
+ return [tableWrapperNode, ...getTableDom(rowNodes, eventCount, visibleTableColumns, tableColumns, summary, focus), ...getTableResizersDom(visibleTableColumns)];
5493
+ };
5494
+
5495
+ const getTableWrapperWrapperDom = (rowNodes, eventCount, visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns(), summary = '', focus = 0, className = '', role = '') => {
5496
+ const tableSummaryNodes = getTableSummaryDom(summary);
5096
5497
  return [{
5097
- childCount: 1 + (resizerNodes.length > 0 ? 1 : 0),
5098
- className: ChatDebugViewTableWrapper,
5498
+ childCount: tableSummaryNodes.length === 0 ? 1 : 2,
5499
+ className: TableWrapperWrapper,
5099
5500
  type: Div
5100
- }, {
5101
- childCount: 2,
5102
- className: ChatDebugViewTable,
5103
- type: Table
5104
- }, ...getTableHeaderDom(visibleTableColumns, tableColumns), ...getTableBodyDom(rowNodes, eventCount), ...resizerNodes];
5501
+ }, ...getTableWrapperDom(rowNodes, eventCount, visibleTableColumns, tableColumns, summary, focus, className, role), ...tableSummaryNodes];
5105
5502
  };
5106
5503
 
5107
5504
  const getBucketUnitDom = (unitCount, presetValue) => {
@@ -5143,6 +5540,23 @@ const getBucketDom = bucket => {
5143
5540
  }, ...getBucketUnitDom(bucket.unitCount, presetValue)];
5144
5541
  };
5145
5542
 
5543
+ const getBucketsDom = buckets => {
5544
+ return [{
5545
+ childCount: buckets.length,
5546
+ className: ChatDebugViewTimelineBuckets,
5547
+ type: Div
5548
+ }, ...buckets.flatMap(getBucketDom)];
5549
+ };
5550
+
5551
+ const getCursorGuideNodes = hoverPercent => {
5552
+ return hoverPercent === null ? [] : [{
5553
+ childCount: 0,
5554
+ className: mergeClassNames(ChatDebugViewTimelineCursorGuide, ChatDebugViewTimelineCursorGuideVisible),
5555
+ style: `left:${hoverPercent}%;`,
5556
+ type: Div
5557
+ }];
5558
+ };
5559
+
5146
5560
  const formatPercent = value => {
5147
5561
  return `${Number(value.toFixed(3))}%`;
5148
5562
  };
@@ -5158,26 +5572,55 @@ const getSelectionNodesDom = (hasSelection, selectionStartPercent, selectionEndP
5158
5572
  type: Div
5159
5573
  }, {
5160
5574
  childCount: 0,
5161
- className: mergeClassNames(ChatDebugViewTimelineSelectionHandle, ChatDebugViewTimelineSelectionMarker, ChatDebugViewTimelineSelectionMarkerStart),
5575
+ className: mergeClassNames(ChatDebugViewTimelineSelectionHandle, ChatDebugViewTimelineSelectionHandleStart, ChatDebugViewTimelineSelectionMarker, ChatDebugViewTimelineSelectionMarkerStart),
5162
5576
  name: Start,
5163
5577
  role: None,
5164
- style: `left:${formatPercent(selectionStartPercent)};`,
5165
5578
  type: Button$1
5166
5579
  }, {
5167
5580
  childCount: 0,
5168
- className: mergeClassNames(ChatDebugViewTimelineSelectionHandle, ChatDebugViewTimelineSelectionMarker, ChatDebugViewTimelineSelectionMarkerEnd),
5581
+ className: mergeClassNames(ChatDebugViewTimelineSelectionHandle, ChatDebugViewTimelineSelectionHandleEnd, ChatDebugViewTimelineSelectionMarker, ChatDebugViewTimelineSelectionMarkerEnd),
5169
5582
  name: End,
5170
5583
  role: None,
5171
- style: `left:${formatPercent(selectionEndPercent)};`,
5172
5584
  type: Button$1
5173
5585
  }];
5174
5586
  };
5175
5587
 
5176
- const formatTimelineSeconds = value => {
5177
- if (Number.isInteger(value)) {
5178
- return `${value}s`;
5588
+ const getTimelineBadgeValues = durationSeconds => {
5589
+ if (durationSeconds <= 0) {
5590
+ return [0];
5179
5591
  }
5180
- return `${Number(value.toFixed(1))}s`;
5592
+ const segmentCount = durationSeconds < 1 ? 2 : Math.min(5, Math.max(1, Math.ceil(durationSeconds)));
5593
+ return Array.from({
5594
+ length: segmentCount + 1
5595
+ }, (_, index) => {
5596
+ if (index === segmentCount) {
5597
+ return durationSeconds;
5598
+ }
5599
+ return roundSeconds(durationSeconds / segmentCount * index);
5600
+ });
5601
+ };
5602
+ const getTimelineBadgeStyle = (index, lastIndex) => {
5603
+ if (index === 0 || lastIndex === 0) {
5604
+ return 'left:0;transform:translateX(0);';
5605
+ }
5606
+ if (index === lastIndex) {
5607
+ return 'left:100%;transform:translateX(-100%);';
5608
+ }
5609
+ return `left:${roundSeconds(index / lastIndex * 100)}%;transform:translateX(-50%);`;
5610
+ };
5611
+ const getTimelineBadgeNodes = timelineInfo => {
5612
+ const badgeValues = getTimelineBadgeValues(timelineInfo.durationSeconds);
5613
+ const lastIndex = badgeValues.length - 1;
5614
+ return [{
5615
+ childCount: badgeValues.length,
5616
+ className: ChatDebugViewTimelineBadges,
5617
+ type: Div
5618
+ }, ...badgeValues.flatMap((value, index) => [{
5619
+ childCount: 1,
5620
+ className: ChatDebugViewTimelineBadge,
5621
+ style: getTimelineBadgeStyle(index, lastIndex),
5622
+ type: Span
5623
+ }, text(formatTimelineMilliseconds(value))])];
5181
5624
  };
5182
5625
 
5183
5626
  const getTimelineSummary = timelineInfo => {
@@ -5187,74 +5630,72 @@ const getTimelineSummary = timelineInfo => {
5187
5630
  return windowSummary('0s', formatTimelineSeconds(timelineInfo.durationSeconds), formatTimelineSeconds(timelineInfo.durationSeconds));
5188
5631
  };
5189
5632
 
5190
- const getTimelineNodes = timelineInfo => {
5633
+ const getTimelineTopDom = timelineInfo => {
5634
+ return [{
5635
+ childCount: 1,
5636
+ className: ChatDebugViewTimelineTop,
5637
+ type: Div
5638
+ }, text(getTimelineSummary(timelineInfo))];
5639
+ };
5640
+
5641
+ // cspell:ignore gettimelinedom
5642
+ const getTimelineDom = (timelineInfo, hoverPercent = null) => {
5191
5643
  if (timelineInfo.buckets.length === 0) {
5192
5644
  return [];
5193
5645
  }
5646
+ const badgeNodes = getTimelineBadgeNodes(timelineInfo);
5647
+ const bucketNodes = getBucketsDom(timelineInfo.buckets);
5194
5648
  const selectionNodes = getSelectionNodesDom(timelineInfo.hasSelection, timelineInfo.selectionStartPercent, timelineInfo.selectionEndPercent);
5649
+ const cursorGuideNodes = getCursorGuideNodes(hoverPercent);
5650
+ const timelineTopDom = getTimelineTopDom(timelineInfo);
5195
5651
  return [{
5196
5652
  childCount: 2,
5197
5653
  className: ChatDebugViewTimeline,
5198
5654
  onContextMenu: HandleTimelineContextMenu,
5199
5655
  type: Section
5200
- }, {
5201
- childCount: 1,
5202
- className: ChatDebugViewTimelineTop,
5203
- type: Div
5204
- }, {
5205
- childCount: 1,
5206
- className: ChatDebugViewTimelineSummary,
5207
- type: H2
5208
- }, text(getTimelineSummary(timelineInfo)), {
5209
- childCount: 2,
5656
+ }, ...timelineTopDom, {
5657
+ childCount: 3,
5210
5658
  className: ChatDebugViewTimelineInteractive,
5211
- onDoubleClick: HandleTimelineDoubleClick,
5659
+ onDblClick: HandleTimelineDoubleClick,
5212
5660
  onPointerDown: HandleTimelinePointerDown,
5661
+ onPointerLeave: HandleTimelinePointerLeave,
5662
+ onPointerMove: HandleTimelinePointerMove,
5663
+ type: Div
5664
+ }, ...badgeNodes, ...bucketNodes, {
5665
+ childCount: 2,
5666
+ className: ChatDebugViewTimelineSelectionOverlay,
5213
5667
  type: Div
5214
5668
  }, {
5215
- childCount: timelineInfo.buckets.length,
5216
- className: ChatDebugViewTimelineBuckets,
5669
+ childCount: cursorGuideNodes.length,
5217
5670
  type: Div
5218
- }, ...timelineInfo.buckets.flatMap(getBucketDom), {
5671
+ }, ...cursorGuideNodes, {
5219
5672
  childCount: selectionNodes.length,
5220
- className: ChatDebugViewTimelineSelectionOverlay,
5221
5673
  type: Div
5222
5674
  }, ...selectionNodes];
5223
5675
  };
5224
5676
 
5225
- const getDevtoolsDom = (events, selectedEvent, selectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage = noEventsFound(), timelineSelectionActive = false, timelineSelectionAnchorSeconds = '', timelineSelectionFocusSeconds = '', visibleTableColumns = defaultVisibleTableColumns, detailTabs = createDetailTabs(), tableColumns = createTableColumns(), timelineInfo) => {
5677
+ const getDevtoolsDom = (events, selectedEvent, selectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage = noEventsFound(), timelineSelectionActive = false, timelineSelectionAnchorSeconds = '', timelineSelectionFocusSeconds = '', detailTabs = createDetailTabs(), visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns(), timelineInfo, timelineHoverPercent = null, focus = 0) => {
5226
5678
  const rowNodes = getDevtoolsRows(events, selectedEventIndex, visibleTableColumns);
5227
5679
  const effectiveRange = getEffectiveTimelineRange(timelineStartSeconds, timelineEndSeconds, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds);
5228
5680
  const resolvedTimelineInfo = timelineInfo || getTimelineInfo(timelineEvents, effectiveRange.startSeconds, effectiveRange.endSeconds);
5229
- const timelineNodes = getTimelineNodes(resolvedTimelineInfo);
5681
+ const timelineNodes = getTimelineDom(resolvedTimelineInfo, timelineHoverPercent);
5230
5682
  const previewEvent = selectedEvent ? getPreviewEvent(selectedEvent) : undefined;
5231
- const previewEventNodes = getPreviewEventNodes(previewEvent);
5683
+ const previewEventNodes = getPreviewEventNodes(previewEvent, selectedEvent);
5232
5684
  const payloadEventNodes = selectedEvent ? getEventNode(getPayloadEvent(selectedEvent)) : [];
5233
5685
  const responseEventNodes = selectedEvent ? getEventNode(selectedEvent) : [];
5234
5686
  const hasSelectedEvent = responseEventNodes.length > 0;
5235
- const tableNodes = events.length === 0 ? getEmptyStateDom(emptyMessage) : getTableDom(rowNodes, events.length, visibleTableColumns, tableColumns);
5236
5687
  const eventsClassName = getEventsClassName(hasSelectedEvent);
5688
+ const summary = getTableSummary(events);
5689
+ const tableNodes = events.length === 0 ? getEmptyStateDom(emptyMessage) : getTableWrapperWrapperDom(rowNodes, events.length, visibleTableColumns, tableColumns, summary, focus);
5237
5690
  const detailsNodes = getDetailsDom(previewEventNodes, payloadEventNodes, responseEventNodes, selectedEvent, detailTabs);
5238
5691
  const sashNodes = getSashNodesDom(hasSelectedEvent);
5239
5692
  const splitChildCount = hasSelectedEvent ? 3 : 1;
5240
- const mainChildCount = 1 + (timelineNodes.length > 0 ? 1 : 0);
5693
+ const rootChildCount = 3;
5241
5694
  return [{
5242
- childCount: mainChildCount,
5243
- className: ChatDebugViewDevtoolsMain,
5244
- role: None,
5245
- type: Div
5246
- }, ...timelineNodes, {
5247
- childCount: splitChildCount,
5248
- className: ChatDebugViewDevtoolsSplit,
5249
- role: None,
5250
- type: Div
5251
- }, {
5252
- childCount: 1,
5253
- className: eventsClassName,
5254
- role: 'application',
5255
- tabIndex: 0,
5695
+ childCount: rootChildCount,
5696
+ className: mergeClassNames(ChatDebugView, ChatDebugViewDevtools),
5256
5697
  type: Div
5257
- }, ...tableNodes, ...sashNodes, ...detailsNodes];
5698
+ }, ...timelineNodes, ...getSplitViewDom(splitChildCount, eventsClassName, tableNodes, sashNodes, detailsNodes)];
5258
5699
  };
5259
5700
 
5260
5701
  const getEmptyMessage = (eventCount, hasFilterValue, useNoToolCallEventsMessage, noFilteredEventsMessage) => {
@@ -5269,7 +5710,6 @@ const getLegacyEventsDom = (errorMessage, emptyMessage, eventNodes) => {
5269
5710
  childCount: eventNodes.length === 0 ? 1 : eventNodes.length,
5270
5711
  className: ChatDebugViewEvents,
5271
5712
  role: 'application',
5272
- tabIndex: 0,
5273
5713
  type: Div
5274
5714
  }, ...(eventNodes.length === 0 ? [{
5275
5715
  childCount: 1,
@@ -5278,55 +5718,30 @@ const getLegacyEventsDom = (errorMessage, emptyMessage, eventNodes) => {
5278
5718
  }, text(errorMessage || emptyMessage)] : eventNodes)];
5279
5719
  };
5280
5720
 
5281
- // cspell:ignore multiselectable
5282
- const getQuickFilterNodes = categoryFilters => {
5283
- return [{
5284
- 'aria-multiselectable': true,
5285
- childCount: categoryFilters.length,
5286
- className: ChatDebugViewQuickFilters,
5287
- onClick: HandleEventCategoryFilter,
5288
- role: 'listbox',
5289
- type: Div
5290
- }, ...categoryFilters.flatMap(categoryFilter => {
5291
- const {
5292
- isSelected,
5293
- label,
5294
- name
5295
- } = categoryFilter;
5296
- return [{
5297
- 'aria-selected': isSelected,
5298
- childCount: 1,
5299
- className: mergeClassNames(ChatDebugViewQuickFilterPill, isSelected ? ChatDebugViewQuickFilterPillSelected : ''),
5300
- 'data-value': name,
5301
- onClick: HandleEventCategoryFilter,
5302
- role: 'option',
5303
- type: Div
5304
- }, text(label)];
5305
- })];
5306
- };
5307
-
5308
- const getTimelineFilterDescription = (timelineStartSeconds, timelineEndSeconds) => {
5309
- const trimmedStart = timelineStartSeconds.trim();
5310
- const trimmedEnd = timelineEndSeconds.trim();
5311
- if (trimmedStart && trimmedEnd) {
5312
- return secondsRange(trimmedStart, trimmedEnd);
5313
- }
5314
- if (trimmedStart) {
5315
- return fromSeconds(trimmedStart);
5721
+ const getNextSiblingIndex = (nodes, index) => {
5722
+ let nextSiblingIndex = index + 1;
5723
+ const childCount = nodes[index]?.childCount || 0;
5724
+ for (let i = 0; i < childCount; i++) {
5725
+ nextSiblingIndex = getNextSiblingIndex(nodes, nextSiblingIndex);
5316
5726
  }
5317
- if (trimmedEnd) {
5318
- return toSeconds(trimmedEnd);
5727
+ return nextSiblingIndex;
5728
+ };
5729
+ const getTopLevelChildCount = nodes => {
5730
+ let count = 0;
5731
+ let index = 0;
5732
+ while (index < nodes.length) {
5733
+ count++;
5734
+ index = getNextSiblingIndex(nodes, index);
5319
5735
  }
5320
- return '';
5736
+ return count;
5321
5737
  };
5322
-
5323
5738
  const getEventCategoryFilterDescription = eventCategoryFilters => {
5324
5739
  if (eventCategoryFilters.length === 0 || eventCategoryFilters.includes(All)) {
5325
5740
  return '';
5326
5741
  }
5327
5742
  return eventCategoryFilters.map(eventCategoryFilter => getEventCategoryFilterLabel(eventCategoryFilter).toLowerCase()).join(', ');
5328
5743
  };
5329
- const getChatDebugViewDom = (errorMessage, filterValue, eventCategoryFilters, categoryFilters, _showEventStreamFinishedEvents, _showInputEvents, _showResponsePartEvents, useDevtoolsLayout, selectedEvent, selectedEventIndex, timelineStartSeconds, timelineEndSeconds, timelineEvents, events, timelineSelectionActive = false, timelineSelectionAnchorSeconds = '', timelineSelectionFocusSeconds = '', visibleTableColumns = defaultVisibleTableColumns, detailTabs = createDetailTabs(), tableColumns = createTableColumns(), timelineInfo) => {
5744
+ const getChatDebugViewDom = (errorMessage, filterValue, eventCategoryFilters, categoryFilters, _showEventStreamFinishedEvents, _showInputEvents, _showResponsePartEvents, useDevtoolsLayout, selectedEvent, selectedEventIndex, timelineStartSeconds, timelineEndSeconds, timelineFilterDescription, timelineEvents, events, timelineSelectionActive = false, timelineSelectionAnchorSeconds = '', timelineSelectionFocusSeconds = '', visibleTableColumns = defaultVisibleTableColumns, detailTabs = createDetailTabs(), tableColumns = createTableColumns(), timelineInfo, timelineHoverPercent = null, focus = 0) => {
5330
5745
  if (errorMessage) {
5331
5746
  return getDebugErrorDom(errorMessage);
5332
5747
  }
@@ -5339,7 +5754,6 @@ const getChatDebugViewDom = (errorMessage, filterValue, eventCategoryFilters, ca
5339
5754
  if (trimmedFilterValue) {
5340
5755
  filterDescriptionParts.push(trimmedFilterValue);
5341
5756
  }
5342
- const timelineFilterDescription = getTimelineFilterDescription(timelineStartSeconds, timelineEndSeconds);
5343
5757
  if (timelineFilterDescription) {
5344
5758
  filterDescriptionParts.push(timelineFilterDescription);
5345
5759
  }
@@ -5350,10 +5764,20 @@ const getChatDebugViewDom = (errorMessage, filterValue, eventCategoryFilters, ca
5350
5764
  const useNoToolCallEventsMessage = eventCategoryFilters.length === 1 && eventCategoryFilters[0] === Tools && !trimmedFilterValue && !hasTimelineFilter;
5351
5765
  const emptyMessage = getEmptyMessage(events.length, hasFilterValue, useNoToolCallEventsMessage, noFilteredEventsMessage);
5352
5766
  const safeSelectedEventIndex = selectedEventIndex === null || selectedEventIndex < 0 || selectedEventIndex >= events.length ? null : selectedEventIndex;
5353
- const contentNodes = useDevtoolsLayout ? getDevtoolsDom(events, selectedEvent, safeSelectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds, visibleTableColumns, detailTabs, tableColumns, timelineInfo) : getLegacyEventsDom(errorMessage, emptyMessage, events.flatMap(getEventNode));
5354
- const quickFilterNodes = useDevtoolsLayout ? getQuickFilterNodes(categoryFilters) : [];
5355
- const debugViewTopDom = getDebugViewTopDom(filterValue, useDevtoolsLayout, quickFilterNodes);
5356
- const rootChildCount = 2;
5767
+ if (useDevtoolsLayout) {
5768
+ const devtoolsDom = getDevtoolsDom(events, selectedEvent, safeSelectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds, detailTabs, visibleTableColumns, tableColumns, timelineInfo, timelineHoverPercent, focus);
5769
+ const devtoolsContentNodes = devtoolsDom.slice(1);
5770
+ const topLevelNodes = [...getDebugViewTopDom(filterValue, useDevtoolsLayout, categoryFilters), ...devtoolsContentNodes];
5771
+ const rootChildCount = getTopLevelChildCount(topLevelNodes);
5772
+ return [{
5773
+ childCount: rootChildCount,
5774
+ className: mergeClassNames(ChatDebugView, ChatDebugViewDevtools),
5775
+ type: Div
5776
+ }, ...topLevelNodes];
5777
+ }
5778
+ const contentNodes = getLegacyEventsDom(errorMessage, emptyMessage, events.flatMap(getEventNode));
5779
+ const debugViewTopDom = getDebugViewTopDom(filterValue, useDevtoolsLayout, categoryFilters);
5780
+ const rootChildCount = 1 + getTopLevelChildCount(contentNodes);
5357
5781
  return [{
5358
5782
  childCount: rootChildCount,
5359
5783
  className: mergeClassNames(ChatDebugView, useDevtoolsLayout ? ChatDebugViewDevtools : ''),
@@ -5374,7 +5798,7 @@ const renderItems = (oldState, newState) => {
5374
5798
  return [SetDom2, newState.uid, []];
5375
5799
  }
5376
5800
  const filteredEvents = filterEventsByTimelineRange(newState.timelineEvents, newState.timelineStartSeconds, newState.timelineEndSeconds);
5377
- const dom = getChatDebugViewDom(newState.errorMessage, newState.filterValue, getSelectedEventCategoryFilters(newState.categoryFilters), newState.categoryFilters, newState.showEventStreamFinishedEvents, newState.showInputEvents, newState.showResponsePartEvents, newState.useDevtoolsLayout, newState.selectedEvent, newState.selectedEventIndex, newState.timelineStartSeconds, newState.timelineEndSeconds, withSessionEventIds(newState.timelineEvents), withSessionEventIds(filteredEvents), newState.timelineSelectionActive, newState.timelineSelectionAnchorSeconds, newState.timelineSelectionFocusSeconds, newState.visibleTableColumns, newState.detailTabs, newState.tableColumns, newState.timelineInfo);
5801
+ const dom = getChatDebugViewDom(newState.errorMessage, newState.filterValue, getSelectedEventCategoryFilters(newState.categoryFilters), newState.categoryFilters, newState.showEventStreamFinishedEvents, newState.showInputEvents, newState.showResponsePartEvents, newState.useDevtoolsLayout, newState.selectedEvent, newState.selectedEventIndex, newState.timelineStartSeconds, newState.timelineEndSeconds, newState.timelineFilterDescription, withSessionEventIds(newState.timelineEvents), withSessionEventIds(filteredEvents), newState.timelineSelectionActive, newState.timelineSelectionAnchorSeconds, newState.timelineSelectionFocusSeconds, getVisibleTableColumns(newState.tableColumns), newState.detailTabs, newState.tableColumns, newState.timelineInfo, newState.timelineHoverPercent, newState.focus);
5378
5802
  return [SetDom2, newState.uid, dom];
5379
5803
  };
5380
5804
 
@@ -5385,10 +5809,35 @@ const renderIncremental = (oldState, newState) => {
5385
5809
  return [SetPatches, newState.uid, patches];
5386
5810
  };
5387
5811
 
5812
+ const getSelector = focus => {
5813
+ if (focus === 0) {
5814
+ return '.Table';
5815
+ }
5816
+ return '';
5817
+ };
5818
+ const renderFocus = (oldState, newState) => {
5819
+ const {
5820
+ uid
5821
+ } = newState;
5822
+ const selector = getSelector(newState.focus);
5823
+ return [FocusSelector, uid, selector];
5824
+ };
5825
+
5826
+ const renderFocusContext = (oldState, newState) => {
5827
+ const {
5828
+ uid
5829
+ } = newState;
5830
+ return [SetFocusContext, uid, FocusChatDebugTable];
5831
+ };
5832
+
5388
5833
  const getRenderer = diffType => {
5389
5834
  switch (diffType) {
5390
5835
  case RenderCss:
5391
5836
  return renderCss;
5837
+ case RenderFocus:
5838
+ return renderFocus;
5839
+ case RenderFocusContext:
5840
+ return renderFocusContext;
5392
5841
  case RenderIncremental:
5393
5842
  return renderIncremental;
5394
5843
  case RenderItems:
@@ -5426,11 +5875,17 @@ const renderEventListeners = () => {
5426
5875
  preventDefault: true
5427
5876
  }, {
5428
5877
  name: HandleEventRowClick,
5429
- params: ['handleEventRowClick', 'event.target.dataset.index', Button]
5878
+ params: ['handleEventRowClick', '0', Button]
5879
+ }, {
5880
+ name: HandleEventRowClickAt,
5881
+ params: ['handleEventRowClickAt', ClientX, ClientY, Button]
5430
5882
  }, {
5431
5883
  name: HandleTableBodyContextMenu,
5432
5884
  params: ['handleTableBodyContextMenu', ClientX, ClientY],
5433
5885
  preventDefault: true
5886
+ }, {
5887
+ name: HandleTableFocus,
5888
+ params: ['handleTableFocus']
5434
5889
  }, {
5435
5890
  name: HandleDetailsContextMenu,
5436
5891
  params: ['handleDetailsContextMenu'],
@@ -5448,10 +5903,16 @@ const renderEventListeners = () => {
5448
5903
  params: ['handleInput', TargetName, TargetValue]
5449
5904
  }, {
5450
5905
  name: HandleEventCategoryFilter,
5451
- params: ['handleEventCategoryFilter', 'event.target.dataset.value', 'event.ctrlKey', 'event.metaKey']
5906
+ params: ['handleEventCategoryFilter', TargetName, 'event.ctrlKey']
5907
+ }, {
5908
+ name: HandleTableHeaderClick,
5909
+ params: ['handleTableHeaderClick', TargetName]
5452
5910
  }, {
5453
5911
  name: SelectDetailTab,
5454
- params: ['selectDetailTab', TargetValue]
5912
+ params: ['selectDetailTab', TargetName]
5913
+ }, {
5914
+ name: HandleDetailTabsFocus,
5915
+ params: ['handleDetailTabsFocus', TargetName]
5455
5916
  }, {
5456
5917
  name: HandleTimelineRangePreset,
5457
5918
  params: ['handleTimelineRangePreset', 'event.target.dataset.value']
@@ -5488,6 +5949,9 @@ const renderEventListeners = () => {
5488
5949
  }, {
5489
5950
  name: HandleTimelinePointerMove,
5490
5951
  params: ['handleTimelinePointerMove', ClientX]
5952
+ }, {
5953
+ name: HandleTimelinePointerLeave,
5954
+ params: ['handleTimelinePointerLeave']
5491
5955
  }, {
5492
5956
  name: HandleTimelinePointerUp,
5493
5957
  params: ['handleTimelinePointerUp', ClientX]
@@ -5501,18 +5965,14 @@ const rerender = state => {
5501
5965
  return structuredClone(state);
5502
5966
  };
5503
5967
 
5504
- const isSameVisibleTableColumns = (a, b) => {
5505
- return a.length === b.length && a.every((value, index) => value === b[index]);
5506
- };
5507
-
5508
5968
  const resetTableColumns = state => {
5509
- if (isSameVisibleTableColumns(state.visibleTableColumns, defaultVisibleTableColumns) && isSameTableColumnWidths(state.tableColumnWidths, defaultTableColumnWidths)) {
5969
+ if (getVisibleTableColumns(state.tableColumns).join(',') === defaultVisibleTableColumns.join(',') && isSameTableColumnWidths(state.tableColumnWidths, defaultTableColumnWidths)) {
5510
5970
  return state;
5511
5971
  }
5512
5972
  return {
5513
5973
  ...state,
5514
- tableColumnWidths: defaultTableColumnWidths,
5515
- visibleTableColumns: defaultVisibleTableColumns
5974
+ tableColumns: createTableColumns(),
5975
+ tableColumnWidths: defaultTableColumnWidths
5516
5976
  };
5517
5977
  };
5518
5978
 
@@ -5544,10 +6004,10 @@ const saveState = state => {
5544
6004
  filterValue,
5545
6005
  selectedEventId,
5546
6006
  sessionId,
6007
+ tableColumns,
5547
6008
  tableColumnWidths,
5548
6009
  timelineEndSeconds,
5549
- timelineStartSeconds,
5550
- visibleTableColumns
6010
+ timelineStartSeconds
5551
6011
  } = state;
5552
6012
  return {
5553
6013
  eventCategoryFilter: getSelectedEventCategoryFilter(categoryFilters),
@@ -5559,10 +6019,19 @@ const saveState = state => {
5559
6019
  tableColumnWidths,
5560
6020
  timelineEndSeconds,
5561
6021
  timelineStartSeconds,
5562
- visibleTableColumns
6022
+ visibleTableColumns: getVisibleTableColumns(tableColumns)
5563
6023
  };
5564
6024
  };
5565
6025
 
6026
+ const selectCurrent = async state => {
6027
+ const currentEvents = getCurrentEvents$1(state);
6028
+ if (currentEvents.length === 0) {
6029
+ return state;
6030
+ }
6031
+ const selectedEventIndex = state.selectedEventIndex === null ? 0 : state.selectedEventIndex;
6032
+ return focusIndex(state, selectedEventIndex);
6033
+ };
6034
+
5566
6035
  const setEvents = (state, events) => {
5567
6036
  return getStateWithTimelineInfo({
5568
6037
  ...state,
@@ -5617,18 +6086,30 @@ const toggleTableColumnVisibility = (state, column) => {
5617
6086
  if (!isTableColumn(column)) {
5618
6087
  return state;
5619
6088
  }
5620
- const nextVisibleColumns = state.visibleTableColumns.includes(column) ? state.visibleTableColumns.filter(visibleColumn => visibleColumn !== column) : [...state.visibleTableColumns, column];
5621
6089
  return {
5622
6090
  ...state,
5623
- visibleTableColumns: getOrderedVisibleTableColumns(nextVisibleColumns)
6091
+ tableColumns: state.tableColumns.map(tableColumn => {
6092
+ if (tableColumn.name !== column) {
6093
+ return tableColumn;
6094
+ }
6095
+ return {
6096
+ ...tableColumn,
6097
+ isVisible: !tableColumn.isVisible
6098
+ };
6099
+ })
5624
6100
  };
5625
6101
  };
5626
6102
 
5627
6103
  const commandMap = {
5628
6104
  'ChatDebug.appendStoredEventForTest': wrapCommand(appendStoredEventForTest),
5629
6105
  'ChatDebug.appendStoredImageAttachmentForTest': wrapCommand(appendStoredImageAttachmentForTest),
6106
+ 'ChatDebug.appendStoredRemovedImageAttachmentForTest': wrapCommand(appendStoredRemovedImageAttachmentForTest),
5630
6107
  'ChatDebug.create': create,
5631
6108
  'ChatDebug.diff2': diff2,
6109
+ 'ChatDebug.focusFirst': wrapCommand(focusFirst),
6110
+ 'ChatDebug.focusLast': wrapCommand(focusLast),
6111
+ 'ChatDebug.focusNext': wrapCommand(focusNext),
6112
+ 'ChatDebug.focusPrevious': wrapCommand(focusPrevious),
5632
6113
  'ChatDebug.getCommandIds': getCommandIds,
5633
6114
  'ChatDebug.getMenuEntries': wrapGetter(getMenuEntries2),
5634
6115
  'ChatDebug.getMenuIds': getMenuIds,
@@ -5636,8 +6117,11 @@ const commandMap = {
5636
6117
  'ChatDebug.handleCloseDetails': wrapCommand(handleCloseDetails),
5637
6118
  'ChatDebug.handleDetailsContextMenu': wrapCommand(handleDetailsContextMenu),
5638
6119
  'ChatDebug.handleDetailsTopContextMenu': wrapCommand(handleDetailsTopContextMenu),
6120
+ 'ChatDebug.handleDetailTabsFocus': wrapCommand(handleDetailTabsFocus),
6121
+ 'ChatDebug.handleEscape': wrapCommand(handleEscape),
5639
6122
  'ChatDebug.handleEventCategoryFilter': wrapCommand(handleEventCategoryFilter),
5640
6123
  'ChatDebug.handleEventRowClick': wrapCommand(handleEventRowClick),
6124
+ 'ChatDebug.handleEventRowClickAt': wrapCommand(handleEventRowClickAt),
5641
6125
  'ChatDebug.handleHeaderContextMenu': wrapCommand(handleHeaderContextMenu),
5642
6126
  'ChatDebug.handleInput': wrapCommand(handleInput),
5643
6127
  'ChatDebug.handleSashPointerDown': wrapCommand(handleSashPointerDown),
@@ -5647,6 +6131,8 @@ const commandMap = {
5647
6131
  'ChatDebug.handleShowInputEvents': wrapCommand(handleShowInputEvents),
5648
6132
  'ChatDebug.handleShowResponsePartEvents': wrapCommand(handleShowResponsePartEvents),
5649
6133
  'ChatDebug.handleTableBodyContextMenu': wrapCommand(handleTableBodyContextMenu),
6134
+ 'ChatDebug.handleTableFocus': wrapCommand(handleTableFocus),
6135
+ 'ChatDebug.handleTableHeaderClick': wrapCommand(handleTableHeaderClick),
5650
6136
  'ChatDebug.handleTableResizerPointerDown': wrapCommand(handleTableResizerPointerDown),
5651
6137
  'ChatDebug.handleTableResizerPointerMove': wrapCommand(handleTableResizerPointerMove),
5652
6138
  'ChatDebug.handleTableResizerPointerUp': wrapCommand(handleTableResizerPointerUp),
@@ -5655,6 +6141,7 @@ const commandMap = {
5655
6141
  'ChatDebug.handleTimelineDoubleClick': wrapCommand(handleTimelineDoubleClick),
5656
6142
  'ChatDebug.handleTimelineEndSeconds': wrapCommand(handleTimelineEndSeconds),
5657
6143
  'ChatDebug.handleTimelinePointerDown': wrapCommand(handleTimelinePointerDown),
6144
+ 'ChatDebug.handleTimelinePointerLeave': wrapCommand(handleTimelinePointerLeave),
5658
6145
  'ChatDebug.handleTimelinePointerMove': wrapCommand(handleTimelinePointerMove),
5659
6146
  'ChatDebug.handleTimelinePointerUp': wrapCommand(handleTimelinePointerUp),
5660
6147
  'ChatDebug.handleTimelineRangePreset': wrapCommand(handleTimelineRangePreset),
@@ -5669,6 +6156,7 @@ const commandMap = {
5669
6156
  'ChatDebug.resetTableColumns': wrapCommand(resetTableColumns),
5670
6157
  'ChatDebug.resize': wrapCommand(resize),
5671
6158
  'ChatDebug.saveState': wrapGetter(saveState),
6159
+ 'ChatDebug.selectCurrent': wrapCommand(selectCurrent),
5672
6160
  'ChatDebug.selectDetailTab': wrapCommand(selectDetailTab),
5673
6161
  'ChatDebug.setEvents': wrapCommand(setEvents),
5674
6162
  'ChatDebug.setSessionId': wrapCommand(setSessionId),
@@ -5701,3 +6189,5 @@ const main = async () => {
5701
6189
  };
5702
6190
 
5703
6191
  main();
6192
+
6193
+ // console.log('hi3')