@lvce-editor/chat-debug-view 9.0.0 → 10.2.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.
@@ -1135,10 +1135,9 @@ const Th = 13;
1135
1135
  const THead = 14;
1136
1136
  const Tr = 15;
1137
1137
  const Img = 17;
1138
- const H2 = 22;
1139
1138
  const Section = 41;
1140
1139
  const Search = 42;
1141
- const P = 50;
1140
+ const TextArea = 62;
1142
1141
  const Reference = 100;
1143
1142
 
1144
1143
  const Button = 'event.button';
@@ -1183,6 +1182,9 @@ const sendMessagePortToChatStorageWorker$1 = async port => {
1183
1182
  const writeClipBoardText = async text => {
1184
1183
  await invoke('ClipBoard.writeText', /* text */text);
1185
1184
  };
1185
+ const getPreference = async key => {
1186
+ return await invoke('Preferences.get', key);
1187
+ };
1186
1188
 
1187
1189
  const toCommandId = key => {
1188
1190
  const dotIndex = key.indexOf('.');
@@ -1313,12 +1315,63 @@ const listChatViewEvents$1 = async sessionId => {
1313
1315
  const loadSelectedEvent$1 = async (sessionId, eventId, type) => {
1314
1316
  return invoke$1('ChatStorage.loadSelectedEvent', sessionId, eventId, type);
1315
1317
  };
1318
+ const registerUpdateListener = async (sessionId, rpcId, uid) => {
1319
+ return invoke$1('ChatStorage.registerUpdateListener', sessionId, rpcId, uid);
1320
+ };
1316
1321
 
1317
1322
  const appendStoredEventForTest = async (state, event) => {
1318
1323
  await appendEvent(event);
1319
1324
  return state;
1320
1325
  };
1321
1326
 
1327
+ const decodeBase64$1 = value => {
1328
+ const decoded = atob(value);
1329
+ const bytes = new Uint8Array(decoded.length);
1330
+ for (let i = 0; i < decoded.length; i++) {
1331
+ bytes[i] = decoded.codePointAt(i) || 0;
1332
+ }
1333
+ return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
1334
+ };
1335
+ const createCanvasBlob$1 = async mimeType => {
1336
+ const canvas = new OffscreenCanvas(2, 2);
1337
+ const context = canvas.getContext('2d');
1338
+ if (!context) {
1339
+ throw new Error('2d canvas context is not available');
1340
+ }
1341
+ context.fillStyle = '#0b6';
1342
+ context.fillRect(0, 0, 2, 2);
1343
+ return canvas.convertToBlob({
1344
+ type: mimeType
1345
+ });
1346
+ };
1347
+ const createBlob$1 = async (mimeType, contentKind, content) => {
1348
+ if (contentKind === 'canvas') {
1349
+ return createCanvasBlob$1(mimeType);
1350
+ }
1351
+ if (contentKind === 'base64') {
1352
+ return new Blob([decodeBase64$1(content)], {
1353
+ type: mimeType
1354
+ });
1355
+ }
1356
+ return new Blob([content], {
1357
+ type: mimeType
1358
+ });
1359
+ };
1360
+ const appendStoredImageAttachmentForTest = async (state, sessionId, eventId, mimeType, name, contentKind, content, timestamp) => {
1361
+ const blob = await createBlob$1(mimeType, contentKind, content);
1362
+ await appendEvent({
1363
+ attachmentId: `attachment-${eventId}`,
1364
+ blob,
1365
+ eventId,
1366
+ mimeType,
1367
+ name,
1368
+ sessionId,
1369
+ timestamp,
1370
+ type: 'chat-attachment-added'
1371
+ });
1372
+ return state;
1373
+ };
1374
+
1322
1375
  const decodeBase64 = value => {
1323
1376
  const decoded = atob(value);
1324
1377
  const bytes = new Uint8Array(decoded.length);
@@ -1352,7 +1405,7 @@ const createBlob = async (mimeType, contentKind, content) => {
1352
1405
  type: mimeType
1353
1406
  });
1354
1407
  };
1355
- const appendStoredImageAttachmentForTest = async (state, sessionId, eventId, mimeType, name, contentKind, content, timestamp) => {
1408
+ const appendStoredRemovedImageAttachmentForTest = async (state, sessionId, eventId, mimeType, name, contentKind, content, timestamp) => {
1356
1409
  const blob = await createBlob(mimeType, contentKind, content);
1357
1410
  await appendEvent({
1358
1411
  attachmentId: `attachment-${eventId}`,
@@ -1362,7 +1415,7 @@ const appendStoredImageAttachmentForTest = async (state, sessionId, eventId, mim
1362
1415
  name,
1363
1416
  sessionId,
1364
1417
  timestamp,
1365
- type: 'chat-attachment-added'
1418
+ type: 'chat-attachment-removed'
1366
1419
  });
1367
1420
  return state;
1368
1421
  };
@@ -1782,12 +1835,15 @@ const Status$1 = 'status';
1782
1835
  const tableColumnNames = [Type, Status$1, Duration];
1783
1836
  const createTableColumns = () => {
1784
1837
  return [{
1838
+ isVisible: true,
1785
1839
  label: type(),
1786
1840
  name: Type
1787
1841
  }, {
1842
+ isVisible: true,
1788
1843
  label: status(),
1789
1844
  name: Status$1
1790
1845
  }, {
1846
+ isVisible: true,
1791
1847
  label: duration(),
1792
1848
  name: Duration
1793
1849
  }];
@@ -1796,12 +1852,22 @@ const defaultVisibleTableColumns = tableColumnNames;
1796
1852
  const isTableColumn = value => {
1797
1853
  return tableColumnNames.includes(value);
1798
1854
  };
1855
+ const getVisibleTableColumns = tableColumns => {
1856
+ return tableColumns.filter(column => column.isVisible).map(column => column.name);
1857
+ };
1858
+ const getTableColumnsWithVisibility = (tableColumns, visibleTableColumns) => {
1859
+ const visibleColumns = new Set(visibleTableColumns.filter(isTableColumn));
1860
+ return tableColumns.map(column => ({
1861
+ ...column,
1862
+ isVisible: visibleColumns.has(column.name)
1863
+ }));
1864
+ };
1799
1865
  const getOrderedVisibleTableColumns = (values, tableColumns = createTableColumns()) => {
1800
1866
  const visibleColumns = new Set(values.filter(isTableColumn));
1801
1867
  return tableColumns.map(column => column.name).filter(column => visibleColumns.has(column));
1802
1868
  };
1803
- const isVisibleTableColumn = (visibleTableColumns, column) => {
1804
- return visibleTableColumns.includes(column);
1869
+ const isVisibleTableColumn = (tableColumns, column) => {
1870
+ return tableColumns.some(tableColumn => tableColumn.name === column && tableColumn.isVisible);
1805
1871
  };
1806
1872
  const getTableColumnLabel = (tableColumns, name) => {
1807
1873
  const match = tableColumns.find(column => column.name === name);
@@ -1969,12 +2035,12 @@ const restoreTimelineEndSeconds = (savedState, currentTimelineEndSeconds) => {
1969
2035
  const restoreTimelineStartSeconds = (savedState, currentTimelineStartSeconds) => {
1970
2036
  return typeof savedState.timelineStartSeconds === 'string' ? savedState.timelineStartSeconds : currentTimelineStartSeconds;
1971
2037
  };
1972
- const restoreVisibleTableColumns = (savedState, currentVisibleTableColumns) => {
2038
+ const restoreVisibleTableColumns = (savedState, currentTableColumns) => {
1973
2039
  if (!Array.isArray(savedState.visibleTableColumns)) {
1974
- return currentVisibleTableColumns;
2040
+ return currentTableColumns;
1975
2041
  }
1976
2042
  const visibleTableColumns = savedState.visibleTableColumns.filter(value => typeof value === 'string');
1977
- return getOrderedVisibleTableColumns(visibleTableColumns);
2043
+ return getTableColumnsWithVisibility(currentTableColumns, visibleTableColumns);
1978
2044
  };
1979
2045
  const restoreTableColumnWidths = (savedState, currentTableColumnWidths) => {
1980
2046
  return isTableColumnWidths(savedState.tableColumnWidths) ? savedState.tableColumnWidths : currentTableColumnWidths;
@@ -1989,10 +2055,10 @@ const restoreSavedState = (state, savedState) => {
1989
2055
  detailTabs: restoreDetailTabs(savedState, state.detailTabs),
1990
2056
  filterValue: restoreFilterValue(savedState, state.filterValue),
1991
2057
  selectedEventId: restoreSelectedEventId(savedState, state.selectedEventId),
2058
+ tableColumns: restoreVisibleTableColumns(savedState, state.tableColumns),
1992
2059
  tableColumnWidths: restoreTableColumnWidths(savedState, state.tableColumnWidths),
1993
2060
  timelineEndSeconds: restoreTimelineEndSeconds(savedState, state.timelineEndSeconds),
1994
- timelineStartSeconds: restoreTimelineStartSeconds(savedState, state.timelineStartSeconds),
1995
- visibleTableColumns: restoreVisibleTableColumns(savedState, state.visibleTableColumns)
2061
+ timelineStartSeconds: restoreTimelineStartSeconds(savedState, state.timelineStartSeconds)
1996
2062
  };
1997
2063
  };
1998
2064
 
@@ -2154,6 +2220,8 @@ const createDefaultState = () => {
2154
2220
  largeBreakpoint: 900,
2155
2221
  mediumBreakpoint: 600,
2156
2222
  platform: 0,
2223
+ previewTextCursorColumnIndex: null,
2224
+ previewTextCursorRowIndex: null,
2157
2225
  sashPointerActive: false,
2158
2226
  selectedEvent: null,
2159
2227
  selectedEventId: null,
@@ -2165,12 +2233,18 @@ const createDefaultState = () => {
2165
2233
  showResponsePartEvents: false,
2166
2234
  sortColumn: '',
2167
2235
  sortDescending: false,
2168
- tableColumns: [],
2236
+ tableColumns: createTableColumns(),
2169
2237
  tableColumnWidths: defaultTableColumnWidths,
2238
+ tableDeltaY: 0,
2239
+ tableMaxLineY: 0,
2240
+ tableMinLineY: 0,
2170
2241
  tableResizerDownId: 0,
2242
+ tableScrollBarHandleOffset: 0,
2243
+ tableScrollBarPointerActive: false,
2171
2244
  tableWidth: defaultTableWidth,
2172
2245
  timelineEndSeconds: '',
2173
2246
  timelineEvents: [],
2247
+ timelineFilterDescription: '',
2174
2248
  timelineHoverPercent: null,
2175
2249
  timelineHoverSeconds: '',
2176
2250
  timelineInfo: emptyTimelineInfo,
@@ -2181,7 +2255,6 @@ const createDefaultState = () => {
2181
2255
  uid: 0,
2182
2256
  uri: '',
2183
2257
  useDevtoolsLayout: true,
2184
- visibleTableColumns: defaultVisibleTableColumns,
2185
2258
  width: 0,
2186
2259
  x: 0,
2187
2260
  y: 0
@@ -2219,7 +2292,7 @@ const RenderFocusContext = 4;
2219
2292
  const RenderFocus = 5;
2220
2293
 
2221
2294
  const diff = (oldState, newState) => {
2222
- 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.visibleTableColumns !== newState.visibleTableColumns || oldState.selectedEvent !== newState.selectedEvent || oldState.selectedEventIndex !== newState.selectedEventIndex || oldState.focus !== newState.focus || oldState.width !== newState.width || oldState.uid !== newState.uid) {
2295
+ if (oldState.categoryFilters !== newState.categoryFilters || oldState.detailTabs !== newState.detailTabs || oldState.errorMessage !== newState.errorMessage || oldState.events !== newState.events || oldState.filterValue !== newState.filterValue || oldState.previewTextCursorColumnIndex !== newState.previewTextCursorColumnIndex || oldState.previewTextCursorRowIndex !== newState.previewTextCursorRowIndex || 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.tableDeltaY !== newState.tableDeltaY || oldState.tableMaxLineY !== newState.tableMaxLineY || oldState.tableMinLineY !== newState.tableMinLineY || 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) {
2223
2296
  return [RenderIncremental, RenderCss];
2224
2297
  }
2225
2298
  return [];
@@ -2492,6 +2565,9 @@ const hasErrorStatus = event => {
2492
2565
  const {
2493
2566
  status
2494
2567
  } = event;
2568
+ if (status === 'error') {
2569
+ return true;
2570
+ }
2495
2571
  if (isErrorStatusCode(status)) {
2496
2572
  return true;
2497
2573
  }
@@ -2568,6 +2644,105 @@ const loadSelectedEvent = async (_databaseName, _dataBaseVersion, _eventStoreNam
2568
2644
  return loadSelectedEvent$1(sessionId, eventId, type);
2569
2645
  };
2570
2646
 
2647
+ const devtoolsTableHeaderHeight = 24;
2648
+ const devtoolsTableRowHeight = 24;
2649
+ const devtoolsTableScrollBarWidth = 12;
2650
+ const devtoolsTableSummaryHeight = 24;
2651
+ const minimumDevtoolsTableScrollBarHeight = 20;
2652
+
2653
+ const devtoolsRootGap = 4;
2654
+ const devtoolsTopHeight = 28;
2655
+ const devtoolsTimelineHeight = 88;
2656
+ const getTableBodyY = (state, hasTimeline) => {
2657
+ return state.y + viewPadding + devtoolsTopHeight + devtoolsRootGap + (hasTimeline ? devtoolsTimelineHeight : 0) + devtoolsTableHeaderHeight;
2658
+ };
2659
+
2660
+ const getTableBodyHeight = (state, eventCount) => {
2661
+ if (eventCount === 0) {
2662
+ return 0;
2663
+ }
2664
+ const tableBodyY = getTableBodyY(state, true);
2665
+ return Math.max(0, state.height - (tableBodyY - state.y) - viewPadding - devtoolsTableSummaryHeight);
2666
+ };
2667
+ const getVisibleRowCount = tableBodyHeight => {
2668
+ if (tableBodyHeight <= 0) {
2669
+ return 0;
2670
+ }
2671
+ return Math.max(1, Math.ceil(tableBodyHeight / devtoolsTableRowHeight));
2672
+ };
2673
+ const getMaxDeltaY = (eventCount, tableBodyHeight) => {
2674
+ return Math.max(eventCount * devtoolsTableRowHeight - tableBodyHeight, 0);
2675
+ };
2676
+ const clampTableDeltaY = (deltaY, eventCount, tableBodyHeight) => {
2677
+ const maxDeltaY = getMaxDeltaY(eventCount, tableBodyHeight);
2678
+ if (deltaY < 0) {
2679
+ return 0;
2680
+ }
2681
+ if (deltaY > maxDeltaY) {
2682
+ return maxDeltaY;
2683
+ }
2684
+ return deltaY;
2685
+ };
2686
+ const getScrollBarHeight = (eventCount, tableBodyHeight) => {
2687
+ if (eventCount === 0 || tableBodyHeight <= 0) {
2688
+ return 0;
2689
+ }
2690
+ const contentHeight = eventCount * devtoolsTableRowHeight;
2691
+ if (contentHeight <= tableBodyHeight) {
2692
+ return 0;
2693
+ }
2694
+ return Math.max(minimumDevtoolsTableScrollBarHeight, Math.floor(tableBodyHeight * tableBodyHeight / contentHeight));
2695
+ };
2696
+ const getScrollBarOffset = (deltaY, maxDeltaY, tableBodyHeight, scrollBarHeight) => {
2697
+ if (maxDeltaY <= 0 || scrollBarHeight <= 0 || tableBodyHeight <= scrollBarHeight) {
2698
+ return 0;
2699
+ }
2700
+ return Math.round(deltaY / maxDeltaY * (tableBodyHeight - scrollBarHeight));
2701
+ };
2702
+ const applyVirtualTableState = state => {
2703
+ const currentEvents = getCurrentEvents$2(state);
2704
+ const tableBodyHeight = getTableBodyHeight(state, currentEvents.length);
2705
+ const deltaY = clampTableDeltaY(state.tableDeltaY, currentEvents.length, tableBodyHeight);
2706
+ const minLineY = Math.floor(deltaY / devtoolsTableRowHeight);
2707
+ const visibleRowCount = getVisibleRowCount(tableBodyHeight);
2708
+ const maxLineY = Math.min(currentEvents.length, minLineY + visibleRowCount);
2709
+ return {
2710
+ ...state,
2711
+ tableDeltaY: deltaY,
2712
+ tableMaxLineY: maxLineY,
2713
+ tableMinLineY: minLineY
2714
+ };
2715
+ };
2716
+ const setTableDeltaY = (state, deltaY) => {
2717
+ return applyVirtualTableState({
2718
+ ...state,
2719
+ tableDeltaY: deltaY
2720
+ });
2721
+ };
2722
+ const withSelectedEventVisible = state => {
2723
+ if (state.selectedEventIndex === null || state.selectedEventIndex < 0) {
2724
+ return applyVirtualTableState(state);
2725
+ }
2726
+ const currentEvents = getCurrentEvents$2(state);
2727
+ const tableBodyHeight = getTableBodyHeight(state, currentEvents.length);
2728
+ const visibleRowCount = getVisibleRowCount(tableBodyHeight);
2729
+ if (visibleRowCount === 0) {
2730
+ return applyVirtualTableState(state);
2731
+ }
2732
+ const minLineY = Math.floor(state.tableDeltaY / devtoolsTableRowHeight);
2733
+ const maxLineY = minLineY + visibleRowCount;
2734
+ if (state.selectedEventIndex < minLineY) {
2735
+ return setTableDeltaY(state, state.selectedEventIndex * devtoolsTableRowHeight);
2736
+ }
2737
+ if (state.selectedEventIndex >= maxLineY) {
2738
+ return setTableDeltaY(state, (state.selectedEventIndex + 1) * devtoolsTableRowHeight - tableBodyHeight);
2739
+ }
2740
+ return applyVirtualTableState(state);
2741
+ };
2742
+
2743
+ const svgWidthRegex = /\bwidth=["']([\d.]+)(?:px)?["']/i;
2744
+ const svgHeightRegex = /\bheight=["']([\d.]+)(?:px)?["']/i;
2745
+ const svgViewBoxRegex = /\bviewBox=["'][^"']*?([\d.]+)\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)["']/i;
2571
2746
  const getBlob = event => {
2572
2747
  const {
2573
2748
  blob
@@ -2586,8 +2761,27 @@ const getAltText = event => {
2586
2761
  const isImageMimeType = mimeType => {
2587
2762
  return typeof mimeType === 'string' && mimeType.startsWith('image/');
2588
2763
  };
2589
- const shouldValidateImage = mimeType => {
2590
- return mimeType !== 'image/svg+xml';
2764
+ const formatImageSize = size => {
2765
+ if (size < 1024) {
2766
+ return `${size} B`;
2767
+ }
2768
+ return `${(size / 1024).toFixed(1)} kB`;
2769
+ };
2770
+ const formatImageStats = (width, height, size) => {
2771
+ return `${width} × ${height} px · ${formatImageSize(size)}`;
2772
+ };
2773
+ const getSvgImageStats = async blob => {
2774
+ const text = await blob.text();
2775
+ const widthMatch = text.match(svgWidthRegex);
2776
+ const heightMatch = text.match(svgHeightRegex);
2777
+ if (widthMatch && heightMatch) {
2778
+ return formatImageStats(Number(widthMatch[1]), Number(heightMatch[1]), blob.size);
2779
+ }
2780
+ const viewBoxMatch = text.match(svgViewBoxRegex);
2781
+ if (viewBoxMatch) {
2782
+ return formatImageStats(Number(viewBoxMatch[3]), Number(viewBoxMatch[4]), blob.size);
2783
+ }
2784
+ return undefined;
2591
2785
  };
2592
2786
  const readBlobAsPreviewUrl = blob => {
2593
2787
  if (typeof FileReaderSync === 'function') {
@@ -2599,15 +2793,29 @@ const readBlobAsPreviewUrl = blob => {
2599
2793
  }
2600
2794
  throw new Error('image preview reader is not available');
2601
2795
  };
2602
- const validateImage = async blob => {
2796
+ const getRasterImageStats = async blob => {
2603
2797
  if (typeof createImageBitmap !== 'function') {
2604
- return;
2798
+ throw new TypeError('image bitmap decoder is not available');
2605
2799
  }
2606
2800
  const bitmap = await createImageBitmap(blob);
2607
- bitmap.close?.();
2801
+ try {
2802
+ return formatImageStats(bitmap.width, bitmap.height, blob.size);
2803
+ } finally {
2804
+ bitmap.close?.();
2805
+ }
2806
+ };
2807
+ const getImageStats = async (blob, mimeType) => {
2808
+ if (mimeType === 'image/svg+xml') {
2809
+ const svgStats = await getSvgImageStats(blob);
2810
+ if (svgStats === undefined) {
2811
+ throw new TypeError('image stats are not available');
2812
+ }
2813
+ return svgStats;
2814
+ }
2815
+ return getRasterImageStats(blob);
2608
2816
  };
2609
2817
  const getAttachmentImagePreview = async event => {
2610
- if (event.type !== 'chat-attachment-added') {
2818
+ if (event.type !== 'chat-attachment-added' && event.type !== 'chat-attachment-removed') {
2611
2819
  return undefined;
2612
2820
  }
2613
2821
  const blob = getBlob(event);
@@ -2616,13 +2824,12 @@ const getAttachmentImagePreview = async event => {
2616
2824
  return undefined;
2617
2825
  }
2618
2826
  try {
2619
- if (shouldValidateImage(mimeType)) {
2620
- await validateImage(blob);
2621
- }
2827
+ const stats = await getImageStats(blob, mimeType);
2622
2828
  return {
2623
2829
  alt: getAltText(event),
2624
2830
  previewType: 'image',
2625
- src: readBlobAsPreviewUrl(blob)
2831
+ src: readBlobAsPreviewUrl(blob),
2832
+ stats
2626
2833
  };
2627
2834
  } catch {
2628
2835
  return imageCouldNotBeLoaded();
@@ -2677,13 +2884,15 @@ const selectEventAtIndex = async (state, selectedEventIndex, dependencies = sele
2677
2884
  }
2678
2885
  const selectedEventDetails = await dependencies.loadSelectedEvent(state.databaseName, state.dataBaseVersion, state.eventStoreName, state.sessionId, state.sessionIdIndexName, selectedEvent.eventId, selectedEvent.type);
2679
2886
  const resolvedSelectedEvent = await withPreparedSelectedEventPreview(selectedEventDetails ?? selectedEvent);
2680
- return {
2887
+ return withSelectedEventVisible({
2681
2888
  ...state,
2682
2889
  detailTabs: createDetailTabs(selectedDetailTab, resolvedSelectedEvent),
2890
+ previewTextCursorColumnIndex: null,
2891
+ previewTextCursorRowIndex: null,
2683
2892
  selectedEvent: resolvedSelectedEvent,
2684
2893
  selectedEventId: selectedEvent.eventId,
2685
2894
  selectedEventIndex
2686
- };
2895
+ });
2687
2896
  };
2688
2897
 
2689
2898
  const focusIndex = async (state, index) => {
@@ -2737,27 +2946,27 @@ const getMenuEntriesTableBody = props => {
2737
2946
  }];
2738
2947
  };
2739
2948
 
2740
- const getColumnVisibilityFlags = (state, column) => {
2741
- return isVisibleTableColumn(state.visibleTableColumns, column) ? Checked : Unchecked;
2949
+ const getColumnVisibilityFlags = (tableColumns, column) => {
2950
+ return isVisibleTableColumn(tableColumns, column) ? Checked : Unchecked;
2742
2951
  };
2743
2952
 
2744
2953
  const getMenuEntriesTableHeader = state => {
2745
2954
  return [{
2746
2955
  args: [Type],
2747
2956
  command: 'ChatDebug.toggleTableColumnVisibility',
2748
- flags: getColumnVisibilityFlags(state, Type),
2957
+ flags: getColumnVisibilityFlags(state.tableColumns, Type),
2749
2958
  id: 'type',
2750
2959
  label: type()
2751
2960
  }, {
2752
2961
  args: [Status$1],
2753
2962
  command: 'ChatDebug.toggleTableColumnVisibility',
2754
- flags: getColumnVisibilityFlags(state, Status$1),
2963
+ flags: getColumnVisibilityFlags(state.tableColumns, Status$1),
2755
2964
  id: 'status',
2756
2965
  label: status()
2757
2966
  }, {
2758
2967
  args: [Duration],
2759
2968
  command: 'ChatDebug.toggleTableColumnVisibility',
2760
- flags: getColumnVisibilityFlags(state, Duration),
2969
+ flags: getColumnVisibilityFlags(state.tableColumns, Duration),
2761
2970
  id: 'duration',
2762
2971
  label: duration()
2763
2972
  }, {
@@ -2781,16 +2990,6 @@ const show2 = async (uid, menuId, x, y, args) => {
2781
2990
  await showContextMenu2(uid, menuId, x, y, args);
2782
2991
  };
2783
2992
 
2784
- const devtoolsTableHeaderHeight = 24;
2785
- const devtoolsTableRowHeight = 24;
2786
-
2787
- const devtoolsRootGap = 4;
2788
- const devtoolsTopHeight = 28;
2789
- const devtoolsTimelineHeight = 88;
2790
- const getTableBodyY = (state, hasTimeline) => {
2791
- return state.y + viewPadding + devtoolsTopHeight + devtoolsRootGap + (hasTimeline ? devtoolsTimelineHeight : 0) + devtoolsTableHeaderHeight;
2792
- };
2793
-
2794
2993
  const getTableBodyEventIndex = (state, eventX, eventY) => {
2795
2994
  if (!state.useDevtoolsLayout) {
2796
2995
  return -1;
@@ -2808,8 +3007,8 @@ const getTableBodyEventIndex = (state, eventX, eventY) => {
2808
3007
  if (relativeX < 0 || relativeX >= tableWidth || relativeY < 0) {
2809
3008
  return -1;
2810
3009
  }
2811
- const eventIndex = Math.floor(relativeY / devtoolsTableRowHeight);
2812
- if (eventIndex < 0 || eventIndex >= currentEvents.length) {
3010
+ const eventIndex = state.tableMinLineY + Math.floor(relativeY / devtoolsTableRowHeight);
3011
+ if (eventIndex < state.tableMinLineY || eventIndex >= state.tableMaxLineY || eventIndex >= currentEvents.length) {
2813
3012
  return -1;
2814
3013
  }
2815
3014
  return eventIndex;
@@ -2949,13 +3148,30 @@ const getTimelineEvents = state => {
2949
3148
  return getFilteredEvents(events, filterValue, eventCategoryFilters, showInputEvents, showResponsePartEvents, showEventStreamFinishedEvents);
2950
3149
  };
2951
3150
 
3151
+ const getTimelineFilterDescription = (timelineStartSeconds, timelineEndSeconds) => {
3152
+ const trimmedStart = timelineStartSeconds.trim();
3153
+ const trimmedEnd = timelineEndSeconds.trim();
3154
+ if (trimmedStart && trimmedEnd) {
3155
+ return secondsRange(trimmedStart, trimmedEnd);
3156
+ }
3157
+ if (trimmedStart) {
3158
+ return fromSeconds(trimmedStart);
3159
+ }
3160
+ if (trimmedEnd) {
3161
+ return toSeconds(trimmedEnd);
3162
+ }
3163
+ return '';
3164
+ };
3165
+
2952
3166
  const getStateWithTimelineInfo = state => {
2953
3167
  const timelineEvents = getTimelineEvents(state);
2954
3168
  const effectiveRange = getEffectiveTimelineRange(state.timelineStartSeconds, state.timelineEndSeconds, state.timelineSelectionActive, state.timelineSelectionAnchorSeconds, state.timelineSelectionFocusSeconds);
2955
3169
  const timelineInfo = getTimelineInfo(timelineEvents, effectiveRange.startSeconds, effectiveRange.endSeconds);
3170
+ const timelineFilterDescription = getTimelineFilterDescription(state.timelineStartSeconds, state.timelineEndSeconds);
2956
3171
  return {
2957
3172
  ...state,
2958
3173
  timelineEvents,
3174
+ timelineFilterDescription,
2959
3175
  timelineInfo
2960
3176
  };
2961
3177
  };
@@ -3005,6 +3221,8 @@ const restoreSelectedEvent = async state => {
3005
3221
  if (state.selectedEventId === null) {
3006
3222
  return {
3007
3223
  ...state,
3224
+ previewTextCursorColumnIndex: null,
3225
+ previewTextCursorRowIndex: null,
3008
3226
  selectedEvent: null,
3009
3227
  selectedEventIndex: null
3010
3228
  };
@@ -3014,6 +3232,8 @@ const restoreSelectedEvent = async state => {
3014
3232
  if (selectedEventIndex === -1) {
3015
3233
  return {
3016
3234
  ...state,
3235
+ previewTextCursorColumnIndex: null,
3236
+ previewTextCursorRowIndex: null,
3017
3237
  selectedEvent: null,
3018
3238
  selectedEventId: null,
3019
3239
  selectedEventIndex: null
@@ -3023,6 +3243,8 @@ const restoreSelectedEvent = async state => {
3023
3243
  if (!selectedEvent || typeof selectedEvent.eventId !== 'number') {
3024
3244
  return {
3025
3245
  ...state,
3246
+ previewTextCursorColumnIndex: null,
3247
+ previewTextCursorRowIndex: null,
3026
3248
  selectedEvent: null,
3027
3249
  selectedEventId: null,
3028
3250
  selectedEventIndex: null
@@ -3032,6 +3254,8 @@ const restoreSelectedEvent = async state => {
3032
3254
  const resolvedSelectedEvent = selectedEventDetails ? await withPreparedSelectedEventPreview(selectedEventDetails) : null;
3033
3255
  return {
3034
3256
  ...state,
3257
+ previewTextCursorColumnIndex: null,
3258
+ previewTextCursorRowIndex: null,
3035
3259
  selectedEvent: resolvedSelectedEvent,
3036
3260
  selectedEventId: selectedEvent.eventId,
3037
3261
  selectedEventIndex
@@ -3047,7 +3271,7 @@ const loadEventsForSessionId = async (state, sessionId) => {
3047
3271
  } = state;
3048
3272
  const result = await loadEventsDependencies.listChatViewEvents(sessionId, databaseName, dataBaseVersion, eventStoreName, sessionIdIndexName);
3049
3273
  if (result.type === 'error') {
3050
- return getStateWithTimelineInfo({
3274
+ return applyVirtualTableState(getStateWithTimelineInfo({
3051
3275
  ...state,
3052
3276
  errorMessage: getFailedToLoadMessage(sessionId, result.error),
3053
3277
  events: [],
@@ -3056,13 +3280,13 @@ const loadEventsForSessionId = async (state, sessionId) => {
3056
3280
  selectedEventId: null,
3057
3281
  selectedEventIndex: null,
3058
3282
  sessionId
3059
- });
3283
+ }));
3060
3284
  }
3061
3285
  const {
3062
3286
  events
3063
3287
  } = result;
3064
3288
  if (events.length === 0) {
3065
- return getStateWithTimelineInfo({
3289
+ return applyVirtualTableState(getStateWithTimelineInfo({
3066
3290
  ...state,
3067
3291
  errorMessage: getSessionNotFoundMessage(sessionId),
3068
3292
  events: [],
@@ -3071,7 +3295,7 @@ const loadEventsForSessionId = async (state, sessionId) => {
3071
3295
  selectedEventId: null,
3072
3296
  selectedEventIndex: null,
3073
3297
  sessionId
3074
- });
3298
+ }));
3075
3299
  }
3076
3300
  const nextState = getStateWithTimelineInfo({
3077
3301
  ...state,
@@ -3080,7 +3304,8 @@ const loadEventsForSessionId = async (state, sessionId) => {
3080
3304
  initial: false,
3081
3305
  sessionId
3082
3306
  });
3083
- return restoreSelectedEvent(nextState);
3307
+ const restoredState = await restoreSelectedEvent(nextState);
3308
+ return withSelectedEventVisible(restoredState);
3084
3309
  };
3085
3310
 
3086
3311
  const loadEventsFromUri = async state => {
@@ -3113,6 +3338,8 @@ const handleClickRefresh = async state => {
3113
3338
  const handleCloseDetails = state => {
3114
3339
  return {
3115
3340
  ...state,
3341
+ previewTextCursorColumnIndex: null,
3342
+ previewTextCursorRowIndex: null,
3116
3343
  selectedEvent: null,
3117
3344
  selectedEventId: null,
3118
3345
  selectedEventIndex: null
@@ -3140,6 +3367,9 @@ const selectDetailTab = (state, value) => {
3140
3367
  detailTabs
3141
3368
  };
3142
3369
  };
3370
+ const handleDetailTabsFocus = (state, value) => {
3371
+ return selectDetailTab(state, value);
3372
+ };
3143
3373
 
3144
3374
  const handleEscape = state => {
3145
3375
  return state;
@@ -3193,12 +3423,12 @@ const getPreservedSelectedEventIndex$1 = (oldState, newState) => {
3193
3423
  const withPreservedSelection$1 = (state, nextState) => {
3194
3424
  const nextStateWithTimelineInfo = getStateWithTimelineInfo(nextState);
3195
3425
  const selectedEventIndex = getPreservedSelectedEventIndex$1(state, nextStateWithTimelineInfo);
3196
- return {
3426
+ return withSelectedEventVisible({
3197
3427
  ...nextStateWithTimelineInfo,
3198
3428
  selectedEvent: selectedEventIndex === null ? null : state.selectedEvent,
3199
3429
  selectedEventId: selectedEventIndex === null ? null : state.selectedEventId,
3200
3430
  selectedEventIndex
3201
- };
3431
+ });
3202
3432
  };
3203
3433
 
3204
3434
  const handleEventCategoryFilter = (state, value, ctrlKey = false, metaKey = false) => {
@@ -3305,12 +3535,14 @@ const parseSelectedEventIndex = value => {
3305
3535
  const withPreservedSelection = (state, nextState) => {
3306
3536
  const nextStateWithTimelineInfo = getStateWithTimelineInfo(nextState);
3307
3537
  const selectedEventIndex = getPreservedSelectedEventIndex(state, nextStateWithTimelineInfo);
3308
- return {
3538
+ return withSelectedEventVisible({
3309
3539
  ...nextStateWithTimelineInfo,
3540
+ previewTextCursorColumnIndex: selectedEventIndex === null ? null : state.previewTextCursorColumnIndex,
3541
+ previewTextCursorRowIndex: selectedEventIndex === null ? null : state.previewTextCursorRowIndex,
3310
3542
  selectedEvent: selectedEventIndex === null ? null : state.selectedEvent,
3311
3543
  selectedEventId: selectedEventIndex === null ? null : state.selectedEventId,
3312
3544
  selectedEventIndex
3313
- };
3545
+ });
3314
3546
  };
3315
3547
  const handleInput = (state, name, value, checked) => {
3316
3548
  if (name === Filter) {
@@ -3355,22 +3587,26 @@ const handleInput = (state, name, value, checked) => {
3355
3587
  if (name === UseDevtoolsLayout) {
3356
3588
  const useDevtoolsLayout = getBoolean(checked);
3357
3589
  const selectedEventIndex = useDevtoolsLayout ? getSelectedEventIndex(state) : null;
3358
- return {
3590
+ return applyVirtualTableState({
3359
3591
  ...state,
3592
+ previewTextCursorColumnIndex: useDevtoolsLayout && selectedEventIndex !== null ? state.previewTextCursorColumnIndex : null,
3593
+ previewTextCursorRowIndex: useDevtoolsLayout && selectedEventIndex !== null ? state.previewTextCursorRowIndex : null,
3360
3594
  selectedEvent: useDevtoolsLayout && selectedEventIndex !== null ? state.selectedEvent : null,
3361
3595
  selectedEventId: useDevtoolsLayout && selectedEventIndex !== null ? state.selectedEventId : null,
3362
3596
  selectedEventIndex,
3363
3597
  useDevtoolsLayout
3364
- };
3598
+ });
3365
3599
  }
3366
3600
  if (name === SelectedEventIndex) {
3367
3601
  const selectedEventIndex = parseSelectedEventIndex(value);
3368
- return {
3602
+ return withSelectedEventVisible({
3369
3603
  ...state,
3604
+ previewTextCursorColumnIndex: selectedEventIndex === null ? null : state.previewTextCursorColumnIndex,
3605
+ previewTextCursorRowIndex: selectedEventIndex === null ? null : state.previewTextCursorRowIndex,
3370
3606
  selectedEvent: selectedEventIndex === null ? null : state.selectedEvent,
3371
3607
  selectedEventId: selectedEventIndex === null ? null : state.selectedEventId,
3372
3608
  selectedEventIndex
3373
- };
3609
+ });
3374
3610
  }
3375
3611
  if (name === TimelineStartSeconds) {
3376
3612
  const nextState = {
@@ -3394,12 +3630,14 @@ const handleInput = (state, name, value, checked) => {
3394
3630
  return withPreservedSelection(state, nextState);
3395
3631
  }
3396
3632
  if (name === CloseDetails) {
3397
- return {
3633
+ return applyVirtualTableState({
3398
3634
  ...state,
3635
+ previewTextCursorColumnIndex: null,
3636
+ previewTextCursorRowIndex: null,
3399
3637
  selectedEvent: null,
3400
3638
  selectedEventId: null,
3401
3639
  selectedEventIndex: null
3402
- };
3640
+ });
3403
3641
  }
3404
3642
  if (name === DetailTab) {
3405
3643
  if (!isDetailTab(value)) {
@@ -3417,67 +3655,323 @@ const handleInput = (state, name, value, checked) => {
3417
3655
  return state;
3418
3656
  };
3419
3657
 
3420
- const handleSashPointerDown = (state, eventX, eventY) => {
3421
- if (state.sashPointerActive) {
3422
- return state;
3658
+ const getListFilesPreviewEvent = (event, name) => {
3659
+ if (name !== 'list_files') {
3660
+ return undefined;
3423
3661
  }
3424
- return {
3425
- ...state,
3426
- sashPointerActive: true
3427
- };
3428
- };
3429
-
3430
- const handleSashPointerMove = (state, eventX, eventY) => {
3431
- if (!state.sashPointerActive) {
3432
- return state;
3662
+ const {
3663
+ result
3664
+ } = event;
3665
+ if (typeof result !== 'object' || result === null) {
3666
+ return undefined;
3433
3667
  }
3434
- return {
3435
- ...state,
3436
- tableWidth: getTableWidthFromClientX(state.x, state.width, eventX)
3437
- };
3668
+ const {
3669
+ entries
3670
+ } = result;
3671
+ if (entries !== undefined) {
3672
+ return entries;
3673
+ }
3674
+ return result;
3438
3675
  };
3439
3676
 
3440
- const handleSashPointerUp = (state, eventX, eventY) => {
3441
- if (!state.sashPointerActive) {
3442
- return state;
3677
+ const getPreviewName = event => {
3678
+ if (typeof event.name === 'string' && event.name) {
3679
+ return event.name;
3443
3680
  }
3444
- return {
3445
- ...state,
3446
- sashPointerActive: false
3447
- };
3681
+ if (typeof event.toolName === 'string' && event.toolName) {
3682
+ return event.toolName;
3683
+ }
3684
+ return undefined;
3448
3685
  };
3449
3686
 
3450
- const FocusChatDebugTable = 221_139;
3687
+ const hasOwn = (event, key) => {
3688
+ return Object.hasOwn(event, key);
3689
+ };
3451
3690
 
3452
- const handleTableFocus = state => {
3453
- return {
3454
- ...state,
3455
- focus: FocusChatDebugTable
3456
- };
3691
+ const shouldIncludeArguments = (event, name) => {
3692
+ if (!hasOwn(event, 'arguments')) {
3693
+ return false;
3694
+ }
3695
+ if (name === 'getWorkspaceUri') {
3696
+ return false;
3697
+ }
3698
+ return true;
3457
3699
  };
3458
3700
 
3459
- const handleTableHeaderClick = (state, value) => {
3460
- if (!isTableColumn(value)) {
3461
- return state;
3701
+ const getPayloadEvent = event => {
3702
+ const name = getPreviewName(event);
3703
+ if (name === 'list_files' && hasOwn(event, 'arguments')) {
3704
+ return event.arguments;
3462
3705
  }
3463
- const sortDescending = state.sortColumn === value ? !state.sortDescending : false;
3464
- const nextState = {
3465
- ...state,
3466
- sortColumn: value,
3467
- sortDescending
3706
+ const payloadEvent = {
3707
+ ...(name === undefined ? {} : {
3708
+ name
3709
+ }),
3710
+ ...(shouldIncludeArguments(event, name) ? {
3711
+ arguments: event.arguments
3712
+ } : {}),
3713
+ ...(hasOwn(event, 'result') ? {
3714
+ result: event.result
3715
+ } : {})
3468
3716
  };
3469
- return withPreservedSelection$1(state, nextState);
3717
+ if (Object.keys(payloadEvent).length > 0) {
3718
+ return payloadEvent;
3719
+ }
3720
+ return event;
3470
3721
  };
3471
3722
 
3472
- const getTableResizerId = name => {
3473
- switch (name) {
3474
- case 'ResizerOne':
3475
- return 1;
3476
- case 'ResizerTwo':
3477
- return 2;
3478
- default:
3479
- return 0;
3480
- }
3723
+ const isChatMessageAddedEvent = event => {
3724
+ return event.type === 'chat-message-added';
3725
+ };
3726
+
3727
+ const isChatMessageUpdatedEvent = event => {
3728
+ return event.type === 'chat-message-updated';
3729
+ };
3730
+
3731
+ const getResponseContentText = content => {
3732
+ if (!content || typeof content !== 'object') {
3733
+ return undefined;
3734
+ }
3735
+ if (Array.isArray(content)) {
3736
+ const [firstContentItem] = content;
3737
+ if (!firstContentItem || typeof firstContentItem !== 'object') {
3738
+ return undefined;
3739
+ }
3740
+ const {
3741
+ text
3742
+ } = firstContentItem;
3743
+ return typeof text === 'string' ? text : undefined;
3744
+ }
3745
+ const {
3746
+ text
3747
+ } = content;
3748
+ return typeof text === 'string' ? text : undefined;
3749
+ };
3750
+ const getSseResponseCompletedPreviewText = event => {
3751
+ if (event.type !== 'sse-response-completed') {
3752
+ return undefined;
3753
+ }
3754
+ const {
3755
+ value
3756
+ } = event;
3757
+ if (!value || typeof value !== 'object') {
3758
+ return undefined;
3759
+ }
3760
+ const {
3761
+ response
3762
+ } = value;
3763
+ if (!response || typeof response !== 'object') {
3764
+ return undefined;
3765
+ }
3766
+ const {
3767
+ output
3768
+ } = response;
3769
+ if (!Array.isArray(output) || output.length === 0) {
3770
+ return undefined;
3771
+ }
3772
+ const [firstOutput] = output;
3773
+ if (!firstOutput || typeof firstOutput !== 'object') {
3774
+ return undefined;
3775
+ }
3776
+ const {
3777
+ content
3778
+ } = firstOutput;
3779
+ return getResponseContentText(content);
3780
+ };
3781
+ const getPreviewMessageText = event => {
3782
+ if (isChatMessageUpdatedEvent(event) && typeof event.text === 'string') {
3783
+ return event.text;
3784
+ }
3785
+ const sseResponseCompletedPreviewText = getSseResponseCompletedPreviewText(event);
3786
+ if (sseResponseCompletedPreviewText !== undefined) {
3787
+ return sseResponseCompletedPreviewText;
3788
+ }
3789
+ if (!isChatMessageAddedEvent(event)) {
3790
+ return undefined;
3791
+ }
3792
+ const {
3793
+ message
3794
+ } = event;
3795
+ if (!message || typeof message !== 'object') {
3796
+ return undefined;
3797
+ }
3798
+ if (!Object.hasOwn(message, 'text')) {
3799
+ return undefined;
3800
+ }
3801
+ const {
3802
+ text
3803
+ } = message;
3804
+ if (typeof text !== 'string') {
3805
+ return undefined;
3806
+ }
3807
+ return text;
3808
+ };
3809
+
3810
+ const getReadFilePreviewText = (event, name) => {
3811
+ if (name !== 'read_file') {
3812
+ return undefined;
3813
+ }
3814
+ const {
3815
+ result
3816
+ } = event;
3817
+ if (typeof result !== 'string') {
3818
+ return undefined;
3819
+ }
3820
+ return result;
3821
+ };
3822
+
3823
+ const getWriteFilePreviewText = (event, name) => {
3824
+ if (name !== 'write_file') {
3825
+ return undefined;
3826
+ }
3827
+ const {
3828
+ arguments: toolArguments
3829
+ } = event;
3830
+ if (typeof toolArguments !== 'object' || toolArguments === null || !Object.hasOwn(toolArguments, 'content')) {
3831
+ return undefined;
3832
+ }
3833
+ const {
3834
+ content
3835
+ } = toolArguments;
3836
+ if (typeof content !== 'string') {
3837
+ return undefined;
3838
+ }
3839
+ return content;
3840
+ };
3841
+
3842
+ const getPreviewEvent = event => {
3843
+ const selectedEventPreview = getSelectedEventPreview(event);
3844
+ if (selectedEventPreview !== undefined) {
3845
+ return selectedEventPreview;
3846
+ }
3847
+ const previewMessageText = getPreviewMessageText(event);
3848
+ if (previewMessageText !== undefined) {
3849
+ return previewMessageText;
3850
+ }
3851
+ const name = getPreviewName(event);
3852
+ const writeFilePreviewText = getWriteFilePreviewText(event, name);
3853
+ if (writeFilePreviewText !== undefined) {
3854
+ return writeFilePreviewText;
3855
+ }
3856
+ const readFilePreviewText = getReadFilePreviewText(event, name);
3857
+ if (readFilePreviewText !== undefined) {
3858
+ return readFilePreviewText;
3859
+ }
3860
+ const listFilesPreviewEvent = getListFilesPreviewEvent(event, name);
3861
+ if (listFilesPreviewEvent !== undefined) {
3862
+ return listFilesPreviewEvent;
3863
+ }
3864
+ return getPayloadEvent(event);
3865
+ };
3866
+
3867
+ const previewTextRowHeight = 20;
3868
+ const defaultPreviewTextColumnWidth = 9;
3869
+ const clamp = (value, min, max) => {
3870
+ return Math.min(Math.max(value, min), max);
3871
+ };
3872
+ const getPreviewTextCursorFromPoint = (value, x, y) => {
3873
+ const lines = value.split('\n');
3874
+ const rowIndex = clamp(Math.floor(Math.max(y, 0) / previewTextRowHeight), 0, Math.max(lines.length - 1, 0));
3875
+ const line = lines[rowIndex] || '';
3876
+ const columnIndex = clamp(Math.floor(Math.max(x, 0) / defaultPreviewTextColumnWidth), 0, line.length);
3877
+ return {
3878
+ columnIndex,
3879
+ rowIndex
3880
+ };
3881
+ };
3882
+ const getPreviewTextCursorStyle = cursor => {
3883
+ return `height: ${previewTextRowHeight}px; left: ${cursor.columnIndex * defaultPreviewTextColumnWidth}px; top: ${cursor.rowIndex * previewTextRowHeight}px; width: 0px;`;
3884
+ };
3885
+
3886
+ const hasNumberedTextPreview = (state, previewEvent) => {
3887
+ if (typeof previewEvent !== 'string') {
3888
+ return false;
3889
+ }
3890
+ if (previewEvent === ImageCouldNotBeLoaded) {
3891
+ return false;
3892
+ }
3893
+ return !state.selectedEvent || !isChatMessageUpdatedEvent(state.selectedEvent);
3894
+ };
3895
+ const handlePreviewTextPointerDown = (state, x, y) => {
3896
+ if (!state.selectedEvent) {
3897
+ return state;
3898
+ }
3899
+ const previewEvent = getPreviewEvent(state.selectedEvent);
3900
+ if (!hasNumberedTextPreview(state, previewEvent)) {
3901
+ return state;
3902
+ }
3903
+ const cursor = getPreviewTextCursorFromPoint(previewEvent, x, y);
3904
+ if (state.previewTextCursorColumnIndex === cursor.columnIndex && state.previewTextCursorRowIndex === cursor.rowIndex) {
3905
+ return state;
3906
+ }
3907
+ return {
3908
+ ...state,
3909
+ previewTextCursorColumnIndex: cursor.columnIndex,
3910
+ previewTextCursorRowIndex: cursor.rowIndex
3911
+ };
3912
+ };
3913
+
3914
+ const handleSashPointerDown = (state, eventX, eventY) => {
3915
+ if (state.sashPointerActive) {
3916
+ return state;
3917
+ }
3918
+ return {
3919
+ ...state,
3920
+ sashPointerActive: true
3921
+ };
3922
+ };
3923
+
3924
+ const handleSashPointerMove = (state, eventX, eventY) => {
3925
+ if (!state.sashPointerActive) {
3926
+ return state;
3927
+ }
3928
+ return {
3929
+ ...state,
3930
+ tableWidth: getTableWidthFromClientX(state.x, state.width, eventX)
3931
+ };
3932
+ };
3933
+
3934
+ const handleSashPointerUp = (state, eventX, eventY) => {
3935
+ if (!state.sashPointerActive) {
3936
+ return state;
3937
+ }
3938
+ return {
3939
+ ...state,
3940
+ sashPointerActive: false
3941
+ };
3942
+ };
3943
+
3944
+ const FocusChatDebugTable = 221_139;
3945
+
3946
+ const handleTableFocus = state => {
3947
+ return {
3948
+ ...state,
3949
+ focus: FocusChatDebugTable
3950
+ };
3951
+ };
3952
+
3953
+ const handleTableHeaderClick = (state, value) => {
3954
+ if (!isTableColumn(value)) {
3955
+ return state;
3956
+ }
3957
+ const sortDescending = state.sortColumn === value ? !state.sortDescending : false;
3958
+ const nextState = {
3959
+ ...state,
3960
+ sortColumn: value,
3961
+ sortDescending
3962
+ };
3963
+ return withPreservedSelection$1(state, nextState);
3964
+ };
3965
+
3966
+ const getTableResizerId = name => {
3967
+ switch (name) {
3968
+ case 'ResizerOne':
3969
+ return 1;
3970
+ case 'ResizerTwo':
3971
+ return 2;
3972
+ default:
3973
+ return 0;
3974
+ }
3481
3975
  };
3482
3976
  const handleTableResizerPointerDown = (state, name, clientX) => {
3483
3977
  return {
@@ -3492,7 +3986,7 @@ const handleTableResizerPointerMove = (state, clientX) => {
3492
3986
  }
3493
3987
  return {
3494
3988
  ...state,
3495
- tableColumnWidths: getResizedTableColumnWidths(state.width, state.tableWidth, state.visibleTableColumns, state.tableColumnWidths, state.x, clientX, state.tableResizerDownId)
3989
+ tableColumnWidths: getResizedTableColumnWidths(state.width, state.tableWidth, getVisibleTableColumns(state.tableColumns), state.tableColumnWidths, state.x, clientX, state.tableResizerDownId)
3496
3990
  };
3497
3991
  };
3498
3992
 
@@ -3517,6 +4011,82 @@ const handleTableRowCopy = async (state, eventIndex) => {
3517
4011
  return state;
3518
4012
  };
3519
4013
 
4014
+ const getHandleOffsetAndPercent = (tableBodyHeight, scrollBarHeight, relativeY) => {
4015
+ const halfScrollBarHeight = scrollBarHeight / 2;
4016
+ if (relativeY <= halfScrollBarHeight) {
4017
+ return {
4018
+ handleOffset: relativeY,
4019
+ percent: 0
4020
+ };
4021
+ }
4022
+ if (relativeY <= tableBodyHeight - halfScrollBarHeight) {
4023
+ return {
4024
+ handleOffset: halfScrollBarHeight,
4025
+ percent: (relativeY - halfScrollBarHeight) / Math.max(1, tableBodyHeight - scrollBarHeight)
4026
+ };
4027
+ }
4028
+ return {
4029
+ handleOffset: scrollBarHeight - tableBodyHeight + relativeY,
4030
+ percent: 1
4031
+ };
4032
+ };
4033
+ const handleTableScrollBarPointerDown = (state, eventY) => {
4034
+ const currentEvents = getCurrentEvents$2(state);
4035
+ const tableBodyHeight = getTableBodyHeight(state, currentEvents.length);
4036
+ const scrollBarHeight = getScrollBarHeight(currentEvents.length, tableBodyHeight);
4037
+ if (tableBodyHeight === 0 || scrollBarHeight === 0) {
4038
+ return state;
4039
+ }
4040
+ const relativeY = eventY - getTableBodyY(state, currentEvents.length > 0);
4041
+ const {
4042
+ handleOffset,
4043
+ percent
4044
+ } = getHandleOffsetAndPercent(tableBodyHeight, scrollBarHeight, relativeY);
4045
+ const maxDeltaY = getMaxDeltaY(currentEvents.length, tableBodyHeight);
4046
+ const nextState = setTableDeltaY(state, percent * maxDeltaY);
4047
+ return {
4048
+ ...nextState,
4049
+ tableScrollBarHandleOffset: handleOffset,
4050
+ tableScrollBarPointerActive: true
4051
+ };
4052
+ };
4053
+
4054
+ const handleTableScrollBarPointerMove = (state, eventY) => {
4055
+ if (!state.tableScrollBarPointerActive) {
4056
+ return state;
4057
+ }
4058
+ const currentEvents = getCurrentEvents$2(state);
4059
+ const tableBodyHeight = getTableBodyHeight(state, currentEvents.length);
4060
+ const scrollBarHeight = getScrollBarHeight(currentEvents.length, tableBodyHeight);
4061
+ if (tableBodyHeight === 0 || scrollBarHeight === 0) {
4062
+ return state;
4063
+ }
4064
+ const relativeY = eventY - getTableBodyY(state, currentEvents.length > 0);
4065
+ const nextHandleTop = Math.max(0, Math.min(tableBodyHeight - scrollBarHeight, relativeY - state.tableScrollBarHandleOffset));
4066
+ const percent = nextHandleTop / Math.max(1, tableBodyHeight - scrollBarHeight);
4067
+ const maxDeltaY = getMaxDeltaY(currentEvents.length, tableBodyHeight);
4068
+ const nextState = setTableDeltaY(state, percent * maxDeltaY);
4069
+ return {
4070
+ ...nextState,
4071
+ tableScrollBarPointerActive: true
4072
+ };
4073
+ };
4074
+
4075
+ const handleTableScrollBarPointerUp = state => {
4076
+ if (!state.tableScrollBarPointerActive && state.tableScrollBarHandleOffset === 0) {
4077
+ return state;
4078
+ }
4079
+ return {
4080
+ ...state,
4081
+ tableScrollBarHandleOffset: 0,
4082
+ tableScrollBarPointerActive: false
4083
+ };
4084
+ };
4085
+
4086
+ const handleTableWheel = (state, deltaY) => {
4087
+ return setTableDeltaY(state, state.tableDeltaY + deltaY);
4088
+ };
4089
+
3520
4090
  const handleTimelineContextMenu = state => {
3521
4091
  return state;
3522
4092
  };
@@ -3576,8 +4146,8 @@ const formatTimelinePresetValue = value => {
3576
4146
  return value.toFixed(3).replace(trailingZeroFractionRegex, '').replace(trailingFractionZeroRegex, '$1');
3577
4147
  };
3578
4148
 
3579
- const getTimelineEventX = (state, eventX) => {
3580
- return state.x + eventX;
4149
+ const getTimelineEventX = eventX => {
4150
+ return eventX;
3581
4151
  };
3582
4152
 
3583
4153
  const getTimelineLeft = state => {
@@ -3639,7 +4209,7 @@ const handleTimelinePointerDown = (state, name, eventX) => {
3639
4209
  }
3640
4210
  const timelineLeft = getTimelineLeft(state);
3641
4211
  const timelineWidth = getTimelineWidth(state);
3642
- const clientX = getTimelineEventX(state, eventX);
4212
+ const clientX = getTimelineEventX(eventX);
3643
4213
  const seconds = getTimelineSecondsFromClientX(state.timelineEvents, clientX, timelineLeft, timelineWidth);
3644
4214
  if (seconds === undefined) {
3645
4215
  return state;
@@ -3669,7 +4239,7 @@ const handleTimelinePointerLeave = state => {
3669
4239
  const handleTimelinePointerMove = (state, eventX) => {
3670
4240
  const timelineLeft = getTimelineLeft(state);
3671
4241
  const timelineWidth = getTimelineWidth(state);
3672
- const clientX = getTimelineEventX(state, eventX);
4242
+ const clientX = getTimelineEventX(eventX);
3673
4243
  const seconds = getTimelineSecondsFromClientX(state.timelineEvents, clientX, timelineLeft, timelineWidth);
3674
4244
  if (seconds === undefined) {
3675
4245
  return state;
@@ -3696,7 +4266,7 @@ const handleTimelinePointerUp = (state, eventX) => {
3696
4266
  }
3697
4267
  const timelineLeft = getTimelineLeft(state);
3698
4268
  const timelineWidth = getTimelineWidth(state);
3699
- const clientX = getTimelineEventX(state, eventX);
4269
+ const clientX = getTimelineEventX(eventX);
3700
4270
  const focusSeconds = getTimelineSecondsFromClientX(state.timelineEvents, clientX, timelineLeft, timelineWidth);
3701
4271
  if (focusSeconds === undefined) {
3702
4272
  return clearTimelineSelectionState(state);
@@ -3717,13 +4287,15 @@ const handleTimelinePointerUp = (state, eventX) => {
3717
4287
  const setUseDevtoolsLayout = (state, checked) => {
3718
4288
  const useDevtoolsLayout = getBoolean(checked);
3719
4289
  const selectedEventIndex = useDevtoolsLayout ? getSelectedEventIndex$1(state) : null;
3720
- return {
4290
+ return applyVirtualTableState({
3721
4291
  ...state,
4292
+ previewTextCursorColumnIndex: useDevtoolsLayout && selectedEventIndex !== null ? state.previewTextCursorColumnIndex : null,
4293
+ previewTextCursorRowIndex: useDevtoolsLayout && selectedEventIndex !== null ? state.previewTextCursorRowIndex : null,
3722
4294
  selectedEvent: useDevtoolsLayout && selectedEventIndex !== null ? state.selectedEvent : null,
3723
4295
  selectedEventId: useDevtoolsLayout && selectedEventIndex !== null ? state.selectedEventId : null,
3724
4296
  selectedEventIndex,
3725
4297
  useDevtoolsLayout
3726
- };
4298
+ });
3727
4299
  };
3728
4300
 
3729
4301
  const handleShowEventStreamFinishedEvents = (state, checked) => {
@@ -3748,22 +4320,46 @@ const handleShowResponsePartEvents = (state, checked) => {
3748
4320
  return withPreservedSelection$1(state, nextState);
3749
4321
  };
3750
4322
 
4323
+ const rpcId = 'handleStorageWorkerUpdate';
4324
+ const handleStorageWorkerUpdate = async uid => {
4325
+ await invoke('Viewlet.executeViewletCommand', uid, 'ChatDebug.handleClickRefresh');
4326
+ };
4327
+
4328
+ const loadContentDependencies = loadEventsDependencies;
4329
+ loadContentDependencies.registerUpdateListener = registerUpdateListener;
3751
4330
  const loadContent = async (state, savedState) => {
4331
+ await getPreference('chatDebug.autoRefresh');
3752
4332
  const nextState = await loadEventsFromUri(restoreSavedState(state, savedState));
3753
- return {
4333
+ if (nextState.sessionId) {
4334
+ try {
4335
+ await loadContentDependencies.registerUpdateListener(nextState.sessionId, rpcId, nextState.uid);
4336
+ } catch {
4337
+ // ignore
4338
+ }
4339
+ }
4340
+ return applyVirtualTableState({
3754
4341
  ...nextState,
3755
4342
  categoryFilters: createCategoryFilters(getSelectedEventCategoryFilters(nextState.categoryFilters)),
3756
4343
  detailTabs: createDetailTabs(getSelectedDetailTab(nextState.detailTabs), nextState.selectedEvent),
3757
4344
  tableColumns: createTableColumns()
3758
- };
4345
+ });
3759
4346
  };
3760
4347
 
4348
+ // cspell:ignore liga calt
4349
+
3761
4350
  const getCss = state => {
3762
4351
  const hasSelectedEvent = !!state.selectedEvent;
3763
4352
  const tableWidth = hasSelectedEvent ? clampTableWidth(state.width, state.tableWidth) : getMainWidth(state.width);
4353
+ const currentEvents = getCurrentEvents$2(state);
4354
+ const tableBodyHeight = getTableBodyHeight(state, currentEvents.length);
4355
+ const scrollBarHeight = getScrollBarHeight(currentEvents.length, tableBodyHeight);
4356
+ const maxDeltaY = getMaxDeltaY(currentEvents.length, tableBodyHeight);
4357
+ const showScrollBar = scrollBarHeight > 0;
4358
+ const scrollBarOffset = getScrollBarOffset(state.tableDeltaY, maxDeltaY, tableBodyHeight, scrollBarHeight);
4359
+ const tableContentWidth = Math.max(0, tableWidth - (showScrollBar ? devtoolsTableScrollBarWidth : 0));
3764
4360
  const detailsWidth = hasSelectedEvent ? getDetailsWidth(state.width, state.tableWidth) : 0;
3765
4361
  const topSize = state.width >= state.largeBreakpoint ? 30 : state.width >= state.mediumBreakpoint ? 60 : 60;
3766
- const tableColumnLayout = getTableColumnLayout(tableWidth, state.visibleTableColumns, state.tableColumnWidths);
4362
+ const tableColumnLayout = getTableColumnLayout(tableContentWidth, getVisibleTableColumns(state.tableColumns), state.tableColumnWidths);
3767
4363
  const [tableColZeroWidth = 0, tableColOneWidth = 0, tableColTwoWidth = 0] = tableColumnLayout.visibleColumnWidths;
3768
4364
  const resizerOneLeft = tableColumnLayout.resizerLefts[0] ?? 0;
3769
4365
  const resizerTwoLeft = tableColumnLayout.resizerLefts[1] ?? 0;
@@ -3773,6 +4369,7 @@ const getCss = state => {
3773
4369
  } = state.timelineInfo;
3774
4370
  return `
3775
4371
  .ChatDebugView {
4372
+ --ChatDebugViewTableBodyHeight: ${tableBodyHeight}px;
3776
4373
  --ChatDebugViewTableHeaderHeight: ${devtoolsTableHeaderHeight}px;
3777
4374
  --ChatDebugViewTableColZeroWidth: ${tableColZeroWidth}px;
3778
4375
  --ChatDebugViewTableColOneWidth: ${tableColOneWidth}px;
@@ -3780,6 +4377,9 @@ const getCss = state => {
3780
4377
  --ChatDebugViewDetailsWidth: ${detailsWidth}px;
3781
4378
  --ChatDebugViewDurationColumnWidth: ${state.tableColumnWidths.duration}px;
3782
4379
  --ChatDebugViewTableRowHeight: ${devtoolsTableRowHeight}px;
4380
+ --ChatDebugViewTableScrollBarHeight: ${scrollBarHeight}px;
4381
+ --ChatDebugViewTableScrollBarOffset: ${scrollBarOffset}px;
4382
+ --ChatDebugViewTableScrollBarWidth: ${showScrollBar ? devtoolsTableScrollBarWidth : 0}px;
3783
4383
  --ResizerOneLeft: ${resizerOneLeft}px;
3784
4384
  --ResizerTwoLeft: ${resizerTwoLeft}px;
3785
4385
  --ChatDebugViewSashWidth: ${sashWidth}px;
@@ -3790,546 +4390,38 @@ const getCss = state => {
3790
4390
  --ChatDebugViewTopSize: ${topSize}px;
3791
4391
  --ChatDebugViewTypeColumnWidth: ${state.tableColumnWidths.type}px;
3792
4392
  padding: ${viewPadding}px;
3793
- display: flex;
3794
- height: 100%;
3795
- box-sizing: border-box;
3796
- gap: 8px;
3797
- contain: strict;
3798
- flex: 1;
3799
- flex-direction: column;
3800
- }
3801
-
3802
- .ChatDebugView--devtools {
3803
- gap: 4px;
3804
- }
3805
-
3806
- .ChatDebugView--devtools > .ChatDebugViewTimeline {
3807
- flex: 0 0 auto;
3808
- }
3809
-
3810
- .ChatDebugView--devtools .ChatDebugViewEvents {
3811
- border-radius: 6px;
3812
- margin-bottom: 0;
3813
- overflow: hidden;
3814
- }
3815
-
3816
- .ChatDebugViewTop {
3817
- display: flex;
3818
- align-items: center;
3819
- flex: 0 0 var(--ChatDebugViewTopSize);
3820
- gap: 8px;
3821
- height: var(--ChatDebugViewTopSize);
3822
- min-height: var(--ChatDebugViewTopSize);
3823
- min-width: 0;
3824
- contain: strict;
3825
- }
3826
-
3827
- .ChatDebugViewTop--devtools {
3828
- align-items: stretch;
3829
- }
3830
-
3831
- .ChatDebugViewFilterInput {
3832
- flex: 1;
3833
- min-width: 0;
3834
- }
3835
-
3836
- .ChatDebugViewFilterInput--devtools {
3837
- flex: 1 1 220px;
3838
- min-width: 180px;
3839
- }
3840
-
3841
- .ChatDebugViewDevtoolsSplit {
3842
- display: flex;
3843
- flex: 1;
3844
- align-items: stretch;
3845
- gap: 0;
3846
- min-width: 0;
3847
- min-height: 0;
3848
- overflow: hidden;
3849
- contain: strict;
3850
4393
  }
3851
4394
 
3852
4395
  .TableWrapper {
3853
- position: relative;
3854
- width: min(100%, var(--ChatDebugViewTableWidth));
3855
- max-width: 100%;
3856
- flex: 1;
3857
- min-height: 0;
3858
- display: flex;
3859
- flex-direction: column;
3860
- }
3861
-
3862
- .FocusOutline {
3863
- outline: 2px solid var(--vscode-focusBorder, rgba(255, 255, 255, 0.45));
3864
- outline-offset: 1px;
3865
- }
3866
-
3867
- .Table {
3868
- width: 100%;
3869
- table-layout: fixed;
3870
- border-collapse: collapse;
3871
- }
3872
-
3873
- .TableRow {
3874
- height: var(--ChatDebugViewTableRowHeight);
3875
- }
3876
-
3877
- .TableSummary {
3878
- flex: none;
3879
- min-height: 24px;
3880
- width: min(100%, var(--ChatDebugViewTableWidth));
3881
- max-width: 100%;
3882
- padding: 6px 4px 0;
3883
- color: var(--vscode-descriptionForeground, inherit);
3884
- font-size: 12px;
3885
- line-height: 1.4;
3886
- }
3887
-
3888
- .TableCell {
3889
- box-sizing: border-box;
3890
- height: var(--ChatDebugViewTableHeaderHeight);
3891
- max-height: var(--ChatDebugViewTableHeaderHeight);
3892
- padding: 0 6px;
4396
+ height: calc(var(--ChatDebugViewTableHeaderHeight) + var(--ChatDebugViewTableBodyHeight));
3893
4397
  overflow: hidden;
3894
- text-overflow: ellipsis;
3895
- white-space: nowrap;
3896
- vertical-align: middle;
3897
- }
3898
-
3899
- .TableBody .TableCell {
3900
- height: var(--ChatDebugViewTableRowHeight);
3901
- max-height: var(--ChatDebugViewTableRowHeight);
3902
- line-height: var(--ChatDebugViewTableRowHeight);
3903
- }
3904
-
3905
- .TableCol {
3906
- width: auto;
3907
- }
3908
-
3909
- .TableColZero {
3910
- width: var(--ChatDebugViewTableColZeroWidth);
3911
- max-width: var(--ChatDebugViewTableColZeroWidth);
3912
- }
3913
-
3914
- .TableColOne {
3915
- width: var(--ChatDebugViewTableColOneWidth);
3916
- max-width: var(--ChatDebugViewTableColOneWidth);
3917
- }
3918
-
3919
- .TableColTwo {
3920
- width: var(--ChatDebugViewTableColTwoWidth);
3921
- max-width: var(--ChatDebugViewTableColTwoWidth);
3922
- }
3923
-
3924
- .Resizers {
3925
- position: absolute;
3926
- inset: 0;
3927
- pointer-events: none;
3928
- }
3929
-
3930
- .Resizer {
3931
- position: absolute;
3932
- top: 0;
3933
- bottom: 0;
3934
- width: 12px;
3935
- margin: 0;
3936
- padding: 0;
3937
- border: 0;
3938
- background: transparent;
3939
- pointer-events: auto;
3940
- cursor: col-resize;
3941
- }
3942
-
3943
- .ResizerOne {
3944
- left: var(--ResizerOneLeft);
3945
- transform: translateX(-50%);
3946
- }
3947
-
3948
- .ResizerTwo {
3949
- left: var(--ResizerTwoLeft);
3950
- transform: translateX(-50%);
3951
- }
3952
-
3953
- .ResizerInner {
3954
- position: absolute;
3955
- top: 0;
3956
- bottom: 0;
3957
- left: 50%;
3958
- width: 1px;
3959
- transform: translateX(-50%);
3960
- background: var(--vscode-widget-border, rgba(255, 255, 255, 0.18));
3961
- }
3962
-
3963
-
3964
- .ChatDebugViewDetails {
3965
- border: 1px solid var(--vscode-editorWidget-border, #454545);
3966
- border-radius: 6px;
3967
- overflow: hidden;
3968
- min-width: 0;
3969
- min-height: 0;
3970
- display: flex;
3971
- flex-direction: column;
3972
- contain: strict;
3973
- }
3974
-
3975
- .ChatDebugViewDevtoolsSplit > .ChatDebugViewDetails {
3976
- border-left: 0;
3977
- border-top-left-radius: 0;
3978
- border-bottom-left-radius: 0;
3979
- flex: 1;
3980
- }
3981
-
3982
- .ChatDebugViewDevtoolsSplit > .ChatDebugViewEvents {
3983
- flex: 0 1 var(--ChatDebugViewTableWidth);
3984
- min-width: 0;
3985
- }
3986
-
3987
- .ChatDebugViewDevtoolsSplit > .ChatDebugViewEvents.ChatDebugViewEventsFullWidth {
3988
- flex: 1 1 100%;
3989
- }
3990
-
3991
- .ChatDebugViewDetailsBottom {
3992
- color: var(--vscode-foreground, inherit);
3993
- overflow: auto;
3994
- display: flex;
3995
- flex-direction: column;
3996
- min-width: 0;
3997
- min-height: 0;
3998
- }
3999
-
4000
- .ChatDebugViewEventRawText {
4001
- margin: 0;
4002
- white-space: pre-wrap;
4003
- overflow-wrap: anywhere;
4004
- word-break: break-word;
4005
- flex: 1;
4006
- }
4007
-
4008
- .ChatDebugViewEventLineContent {
4009
- flex: 1;
4010
- min-width: 0;
4011
- overflow-wrap: anywhere;
4012
- white-space: pre-wrap;
4013
- word-break: break-word;
4014
- }
4015
-
4016
- .ChatDebugViewEventLineNumber {
4017
- flex: none;
4018
- }
4019
-
4020
- .row {
4021
- flex-shrink: 0;
4022
- min-width: 0;
4023
- width: 100%;
4024
- }
4025
-
4026
- .ChatDebugViewRefreshButton {
4027
- display: inline-flex;
4028
- align-items: center;
4029
- justify-content: center;
4030
- flex: none;
4031
- margin-left: auto;
4032
- min-height: 28px;
4033
- padding: 0 10px;
4034
- border: 1px solid rgba(255, 255, 255, 0.16);
4035
- border-radius: 6px;
4036
- background: linear-gradient(180deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.04));
4037
- color: inherit;
4038
- font: inherit;
4039
- font-size: 12px;
4040
- font-weight: 500;
4041
- line-height: 1;
4042
- white-space: nowrap;
4043
- cursor: pointer;
4044
- transition: background-color 120ms ease, border-color 120ms ease, transform 120ms ease;
4045
- }
4046
-
4047
- .ChatDebugViewRefreshButton:hover {
4048
- background: linear-gradient(180deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0.08));
4049
- border-color: rgba(255, 255, 255, 0.24);
4050
- }
4051
-
4052
- .ChatDebugViewRefreshButton:active {
4053
- transform: translateY(1px);
4054
- }
4055
-
4056
- .ChatDebugViewRefreshButton:focus-visible {
4057
- outline: 2px solid rgba(255, 255, 255, 0.4);
4058
- outline-offset: 1px;
4059
- }
4060
-
4061
- .ChatDebugViewDetailsClose {
4062
- display: inline-flex;
4063
- align-items: center;
4064
- justify-content: center;
4065
- flex: none;
4066
- margin-left: auto;
4067
- width: 28px;
4068
- height: 28px;
4069
- padding: 0;
4070
- border: 1px solid transparent;
4071
- border-radius: 6px;
4072
- background: transparent;
4073
- color: var(--vscode-descriptionForeground, inherit);
4074
- cursor: pointer;
4075
- }
4076
-
4077
- .ChatDebugViewDetailsClose:hover {
4078
- background: var(--vscode-toolbar-hoverBackground, rgba(255, 255, 255, 0.08));
4079
- color: var(--vscode-foreground, inherit);
4080
- }
4081
-
4082
- .ChatDebugViewDetailsClose:focus-visible {
4083
- outline: 2px solid var(--vscode-focusBorder, rgba(255, 255, 255, 0.45));
4084
- outline-offset: 1px;
4085
- }
4086
-
4087
-
4088
- .TableRow:hover {
4089
- background: var(--ListHoverBackground);
4090
- color: var(--ListHoverForeground);
4091
- }
4092
-
4093
- .ChatDebugViewImagePreview {
4094
- display: flex;
4095
- flex-direction: column;
4096
- align-items: flex-start;
4097
- gap: 8px;
4098
- width: 100%;
4099
- max-width: 100%;
4100
- min-height: 0;
4101
- }
4102
-
4103
- .ChatDebugViewImagePreviewImage {
4104
- display: block;
4105
- max-width: 100%;
4106
- width: auto;
4107
- height: auto;
4108
- max-height: 100%;
4109
- align-self: center;
4110
- border: 1px solid var(--vscode-widget-border, rgba(255, 255, 255, 0.14));
4111
- border-radius: 6px;
4112
- object-fit: contain;
4113
- }
4114
-
4115
- .ChatDebugViewImagePreviewLabel {
4116
- width: auto;
4117
- height: auto;
4118
- max-height: 100%;
4119
- align-self: center;
4120
- }
4121
-
4122
- .ChatDebugViewTimeline {
4123
- display: flex;
4124
- flex-direction: column;
4125
- gap: 8px;
4126
- }
4127
-
4128
- .ChatDebugViewTimelineTop {
4129
- display: flex;
4130
- align-items: center;
4131
- min-width: 0;
4132
- }
4133
-
4134
- .ChatDebugViewTimelineSummary {
4135
- margin: 0;
4136
- color: var(--vscode-descriptionForeground, inherit);
4137
- font-size: 11px;
4138
- font-weight: 600;
4139
- }
4140
-
4141
- .ChatDebugViewTimelineInteractive {
4142
4398
  position: relative;
4143
- height: 54px;
4144
- overflow: hidden;
4145
- border: 1px solid var(--vscode-widget-border, rgba(255, 255, 255, 0.14));
4146
- border-radius: 8px;
4147
- background: linear-gradient(180deg, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0.02));
4148
- contain: strict;
4149
- user-select: none;
4150
4399
  }
4151
4400
 
4152
- .ChatDebugViewTimelineBadges {
4153
- position: absolute;
4154
- inset: 4px 8px auto 8px;
4155
- height: 12px;
4156
- pointer-events: none;
4157
- z-index: 2;
4401
+ .Table {
4402
+ width: calc(100% - var(--ChatDebugViewTableScrollBarWidth));
4158
4403
  }
4159
4404
 
4160
- .ChatDebugViewTimelineBadge {
4161
- position: absolute;
4162
- top: 0;
4163
- display: flex;
4164
- align-items: center;
4165
- height: 12px;
4166
- padding: 0 5px;
4167
- border: 1px solid color-mix(in srgb, var(--vscode-widget-border, rgba(255, 255, 255, 0.18)) 82%, transparent);
4405
+ .TableScrollBar {
4406
+ background: rgba(255, 255, 255, 0.06);
4168
4407
  border-radius: 999px;
4169
- background: color-mix(in srgb, var(--vscode-editorWidget-background, rgba(30, 30, 30, 0.92)) 90%, transparent);
4170
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.16);
4171
- color: var(--vscode-descriptionForeground, inherit);
4172
- font-size: 9px;
4173
- font-weight: 600;
4174
- line-height: 1;
4175
- white-space: nowrap;
4176
- }
4177
-
4178
- .ChatDebugViewTimelineBuckets {
4408
+ height: var(--ChatDebugViewTableBodyHeight);
4179
4409
  position: absolute;
4180
- inset: 20px 8px 8px;
4181
- display: flex;
4182
- align-items: flex-end;
4183
- gap: 2px;
4410
+ right: 0;
4411
+ top: var(--ChatDebugViewTableHeaderHeight);
4412
+ width: var(--ChatDebugViewTableScrollBarWidth);
4184
4413
  }
4185
4414
 
4186
- .ChatDebugViewTimelineBucket {
4187
- display: flex;
4188
- flex: 1;
4189
- align-items: flex-end;
4190
- height: 100%;
4191
- min-width: 0;
4192
- cursor: pointer;
4193
- }
4194
-
4195
- .ChatDebugViewTimelineBucketBar {
4196
- display: flex;
4197
- flex: 1;
4198
- flex-direction: column;
4199
- justify-content: flex-end;
4200
- gap: 2px;
4201
- height: 100%;
4202
- }
4203
-
4204
- .ChatDebugViewTimelineBucketUnit {
4205
- flex: none;
4206
- height: 4px;
4415
+ .TableScrollBarThumb {
4416
+ background: rgba(255, 255, 255, 0.22);
4207
4417
  border-radius: 999px;
4208
- background: var(--vscode-charts-blue, rgba(91, 151, 255, 0.9));
4209
- }
4210
-
4211
- .ChatDebugViewTimelineBucketUnitEmpty {
4212
- opacity: 0.18;
4213
- }
4214
-
4215
- .ChatDebugViewTimelineBucketSelected .ChatDebugViewTimelineBucketUnit,
4216
- .ChatDebugViewTimelineBucketBarSelected .ChatDebugViewTimelineBucketUnit {
4217
- background: var(--vscode-charts-orange, rgba(255, 174, 0, 0.95));
4218
- }
4219
-
4220
- .ChatDebugViewTimelineSelectionOverlay {
4221
- position: absolute;
4222
- inset: 0;
4223
- pointer-events: none;
4224
- z-index: 1;
4225
- }
4226
-
4227
- .ChatDebugViewTimelineCursorGuide {
4228
- position: absolute;
4229
- top: 0;
4230
- bottom: 0;
4231
- width: 1px;
4232
- margin-left: -0.5px;
4233
- pointer-events: none;
4234
- background: color-mix(in srgb, var(--vscode-foreground, rgba(255, 255, 255, 0.88)) 58%, transparent);
4235
- box-shadow: 0 0 0 1px color-mix(in srgb, var(--vscode-editorWidget-background, rgba(30, 30, 30, 0.92)) 70%, transparent);
4236
- }
4237
-
4238
- .ChatDebugViewTimelineCursorGuideVisible {
4239
- left: var(--ChatDebugViewTimelineCursorGuideLeft);
4240
- }
4241
-
4242
- .ChatDebugViewTimelineSelectionRange {
4243
- position: absolute;
4244
- top: 20px;
4245
- bottom: 8px;
4246
- border-radius: 6px;
4247
- background: color-mix(in srgb, var(--vscode-charts-orange, rgba(255, 174, 0, 0.95)) 18%, transparent);
4248
- outline: 1px solid color-mix(in srgb, var(--vscode-charts-orange, rgba(255, 174, 0, 0.95)) 55%, transparent);
4249
- }
4250
-
4251
- .ChatDebugViewTimelineSelectionMarker {
4252
- position: absolute;
4253
- top: 0;
4254
- bottom: 0;
4255
- width: 14px;
4256
- margin-left: -7px;
4257
- padding: 0;
4258
- border: 0;
4259
- background: linear-gradient(
4260
- 90deg,
4261
- transparent calc(50% - 1px),
4262
- var(--vscode-charts-orange, rgba(255, 174, 0, 0.95)) calc(50% - 1px),
4263
- var(--vscode-charts-orange, rgba(255, 174, 0, 0.95)) calc(50% + 1px),
4264
- transparent calc(50% + 1px)
4265
- );
4266
- }
4267
-
4268
- .ChatDebugViewTimelineSelectionHandle {
4269
- pointer-events: auto;
4270
- cursor: ew-resize;
4271
- }
4272
-
4273
- .ChatDebugViewTimelineSelectionHandleStart,
4274
- .ChatDebugViewTimelineSelectionMarkerStart {
4275
- left: var(--ChatDebugViewTimelineSelectionStartLeft);
4276
- }
4277
-
4278
- .ChatDebugViewTimelineSelectionHandleEnd,
4279
- .ChatDebugViewTimelineSelectionMarkerEnd {
4280
- left: var(--ChatDebugViewTimelineSelectionEndLeft);
4281
- }
4282
-
4283
- .ChatDebugViewTimelineSelectionHandle::before {
4284
- content: '';
4418
+ height: var(--ChatDebugViewTableScrollBarHeight);
4419
+ left: 2px;
4285
4420
  position: absolute;
4286
- top: 0;
4287
- left: 50%;
4288
- width: 14px;
4289
- height: 16px;
4290
- transform: translateX(-50%);
4291
- border: 1px solid var(--vscode-widget-border, rgba(255, 255, 255, 0.22));
4292
- border-radius: 4px;
4293
- background: linear-gradient(180deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.08));
4294
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
4421
+ top: var(--ChatDebugViewTableScrollBarOffset);
4422
+ width: calc(100% - 4px);
4295
4423
  }
4296
4424
 
4297
- .ChatDebugViewTimelineSelectionHandle::after {
4298
- content: '';
4299
- position: absolute;
4300
- top: 5px;
4301
- left: 50%;
4302
- width: 7px;
4303
- height: 6px;
4304
- transform: translateX(-50%);
4305
- background: linear-gradient(
4306
- 90deg,
4307
- transparent 0,
4308
- transparent 1px,
4309
- var(--vscode-foreground, rgba(255, 255, 255, 0.88)) 1px,
4310
- var(--vscode-foreground, rgba(255, 255, 255, 0.88)) 2px,
4311
- transparent 2px,
4312
- transparent 4px,
4313
- var(--vscode-foreground, rgba(255, 255, 255, 0.88)) 4px,
4314
- var(--vscode-foreground, rgba(255, 255, 255, 0.88)) 5px,
4315
- transparent 5px,
4316
- transparent 100%
4317
- );
4318
- opacity: 0.8;
4319
- }
4320
-
4321
- .ChatDebugViewTimelineSelectionHandle:hover::before {
4322
- background: linear-gradient(180deg, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0.12));
4323
- }
4324
-
4325
- .ChatDebugViewTimelineSelectionHandle:focus-visible {
4326
- outline: 2px solid var(--vscode-focusBorder, rgba(255, 255, 255, 0.45));
4327
- outline-offset: 1px;
4328
- }
4329
-
4330
- .TokenString {
4331
- white-space: nowrap;
4332
- }
4333
4425
  `;
4334
4426
  };
4335
4427
 
@@ -4643,16 +4735,24 @@ const ChatDebugViewDevtools = 'ChatDebugView--devtools';
4643
4735
  const ChatDebugViewDetails = 'ChatDebugViewDetails';
4644
4736
  const ChatDebugViewDetailsBottom = 'ChatDebugViewDetailsBottom';
4645
4737
  const ChatDebugViewDetailsClose = 'ChatDebugViewDetailsClose';
4646
- const ChatDebugViewDetailsTab = 'ChatDebugViewDetailsTab';
4647
- const ChatDebugViewDetailsTabSelected = 'ChatDebugViewDetailsTabSelected';
4738
+ const EditorContainer = 'EditorContainer';
4739
+ const PanelTab = 'PanelTab';
4740
+ const PanelTabSelected = 'PanelTabSelected';
4648
4741
  const ChatDebugViewDetailsTabs = 'ChatDebugViewDetailsTabs';
4649
4742
  const ChatDebugViewDetailsTop = 'ChatDebugViewDetailsTop';
4650
4743
  const ChatDebugViewDevtoolsSplit = 'ChatDebugViewDevtoolsSplit';
4651
4744
  const ChatDebugViewEmpty = 'ChatDebugViewEmpty';
4652
4745
  const ChatDebugViewError = 'ChatDebugViewError';
4653
- const ChatDebugViewEventRawText = 'ChatDebugViewEventRawText';
4654
- const ChatDebugViewEventLineContent = 'ChatDebugViewEventLineContent';
4746
+ const EditorContent = 'EditorContent';
4747
+ const EditorInput = 'EditorInput';
4748
+ const EditorLayers = 'EditorLayers';
4749
+ const EditorRow = 'EditorRow';
4750
+ const EditorRows = 'EditorRows';
4751
+ const EditorSelection = 'EditorSelection';
4752
+ const EditorSelections = 'Selections';
4753
+ const EditorViewlet = 'Viewlet Editor';
4655
4754
  const ChatDebugViewEventLineNumber = 'ChatDebugViewEventLineNumber';
4755
+ const Gutter = 'Gutter';
4656
4756
  const TableRowSelected = 'TableRowSelected';
4657
4757
  const ChatDebugViewEvents = 'ChatDebugViewEvents';
4658
4758
  const ChatDebugViewEventsFullWidth = 'ChatDebugViewEventsFullWidth';
@@ -4660,6 +4760,7 @@ const ChatDebugViewFilterInput = 'ChatDebugViewFilterInput';
4660
4760
  const ChatDebugViewFilterInputDevtools = 'ChatDebugViewFilterInput--devtools';
4661
4761
  const ChatDebugViewHeaderCell = 'TableCell';
4662
4762
  const ChatDebugViewImagePreview = 'ChatDebugViewImagePreview';
4763
+ const ChatDebugViewImagePreviewImageWrapper = 'ChatDebugViewImagePreviewImageWrapper';
4663
4764
  const ChatDebugViewImagePreviewImage = 'ChatDebugViewImagePreviewImage';
4664
4765
  const ChatDebugViewImagePreviewLabel = 'ChatDebugViewImagePreviewLabel';
4665
4766
  const ChatDebugViewRefreshButton = 'ChatDebugViewRefreshButton';
@@ -4667,11 +4768,13 @@ const ChatDebugViewQuickFilterPill = 'ChatDebugViewQuickFilterPill';
4667
4768
  const ChatDebugViewQuickFilterPillSelected = 'ChatDebugViewQuickFilterPillSelected';
4668
4769
  const ChatDebugViewQuickFilters = 'ChatDebugViewQuickFilters';
4669
4770
  const Sash = 'Sash';
4670
- const ChatDebugViewSashLine = 'ChatDebugViewSashLine';
4671
4771
  const Table = 'Table';
4672
4772
  const TableBody = 'TableBody';
4673
4773
  const TableSummary = 'TableSummary';
4774
+ const TableScrollBar = 'TableScrollBar';
4775
+ const TableScrollBarThumb = 'TableScrollBarThumb';
4674
4776
  const TableWrapper = 'TableWrapper';
4777
+ const TableWrapperWrapper = 'TableWrapperWrapper';
4675
4778
  const FocusOutline = 'FocusOutline';
4676
4779
  const Resizer = 'Resizer';
4677
4780
  const ResizerInner = 'ResizerInner';
@@ -4704,19 +4807,24 @@ const ChatDebugViewTimelineSelectionMarkerEnd = 'ChatDebugViewTimelineSelectionM
4704
4807
  const ChatDebugViewTimelineSelectionMarkerStart = 'ChatDebugViewTimelineSelectionMarkerStart';
4705
4808
  const ChatDebugViewTimelineSelectionOverlay = 'ChatDebugViewTimelineSelectionOverlay';
4706
4809
  const ChatDebugViewTimelineSelectionRange = 'ChatDebugViewTimelineSelectionRange';
4707
- const ChatDebugViewTimelineSummary = 'ChatDebugViewTimelineSummary';
4708
- const ChatDebugViewTimelineTop = 'ChatDebugViewTimelineTop';
4709
4810
  const ChatDebugViewTiming = 'ChatDebugViewTiming';
4710
4811
  const ChatDebugViewTimingLabel = 'ChatDebugViewTimingLabel';
4812
+ const ChatDebugViewTimingPreview = 'ChatDebugViewTimingPreview';
4813
+ const ChatDebugViewTimingPreviewMarker = 'ChatDebugViewTimingPreviewMarker';
4814
+ const ChatDebugViewTimingPreviewMarkerEnd = 'ChatDebugViewTimingPreviewMarkerEnd';
4815
+ const ChatDebugViewTimingPreviewMarkerStart = 'ChatDebugViewTimingPreviewMarkerStart';
4816
+ const ChatDebugViewTimingPreviewRail = 'ChatDebugViewTimingPreviewRail';
4817
+ const ChatDebugViewTimingPreviewSegment = 'ChatDebugViewTimingPreviewSegment';
4818
+ const ChatDebugViewTimingPreviewTrack = 'ChatDebugViewTimingPreviewTrack';
4819
+ const ChatDebugViewTimingPreviewTrackOverlay = 'ChatDebugViewTimingPreviewTrackOverlay';
4711
4820
  const ChatDebugViewTimingRow = 'ChatDebugViewTimingRow';
4712
4821
  const ChatDebugViewTimingValue = 'ChatDebugViewTimingValue';
4713
4822
  const ChatDebugViewTop = 'ChatDebugViewTop';
4714
4823
  const ChatDebugViewTopDevtools = 'ChatDebugViewTop--devtools';
4715
4824
  const TableCell = 'TableCell';
4716
- const ChatDebugViewColumnFixed = 'ChatDebugViewColumnFixed';
4825
+ const ChatDebugViewCellDuration = 'ChatDebugViewCellDuration';
4717
4826
  const ChatDebugViewCellStatusError = 'ChatDebugViewCellStatusError';
4718
4827
  const InputBox = 'InputBox';
4719
- const Row = 'row';
4720
4828
  const TokenBoolean = 'Token TokenBoolean';
4721
4829
  const TokenKey = 'Token TokenKey';
4722
4830
  const TokenNumeric = 'Token TokenNumeric';
@@ -4763,6 +4871,26 @@ const HandleTimelineContextMenu = 26;
4763
4871
  const HandleTimelinePointerLeave = 27;
4764
4872
  const HandleEventRowClick = 28;
4765
4873
  const HandleTableFocus = 29;
4874
+ const HandleDetailTabsFocus = 30;
4875
+ const HandlePreviewTextPointerDown = 31;
4876
+ const HandleTableScrollBarPointerDown = 32;
4877
+ const HandleTableScrollBarPointerMove = 33;
4878
+ const HandleTableScrollBarPointerUp = 34;
4879
+ const HandleTableWheel = 35;
4880
+
4881
+ const getFilterInputDom = (filterValue, useDevtoolsLayout) => {
4882
+ return {
4883
+ autocomplete: 'off',
4884
+ childCount: 0,
4885
+ className: useDevtoolsLayout ? mergeClassNames(InputBox, ChatDebugViewFilterInput, ChatDebugViewFilterInputDevtools) : mergeClassNames(InputBox, ChatDebugViewFilterInput),
4886
+ inputType: 'search',
4887
+ name: Filter,
4888
+ onInput: HandleFilterInput,
4889
+ placeholder: filterEvents(),
4890
+ type: Input,
4891
+ value: filterValue
4892
+ };
4893
+ };
4766
4894
 
4767
4895
  const getQuickFilterDom = categoryFilter => {
4768
4896
  const {
@@ -4806,19 +4934,6 @@ const getRefreshButtonDom = () => {
4806
4934
  return refreshButtonDom;
4807
4935
  };
4808
4936
 
4809
- const getFilterInputDom = (filterValue, useDevtoolsLayout) => {
4810
- return {
4811
- autocomplete: 'off',
4812
- childCount: 0,
4813
- className: useDevtoolsLayout ? mergeClassNames(InputBox, ChatDebugViewFilterInput, ChatDebugViewFilterInputDevtools) : mergeClassNames(InputBox, ChatDebugViewFilterInput),
4814
- inputType: 'search',
4815
- name: Filter,
4816
- onInput: HandleFilterInput,
4817
- placeholder: filterEvents(),
4818
- type: Input,
4819
- value: filterValue
4820
- };
4821
- };
4822
4937
  const getDebugViewTopDom = (filterValue, useDevtoolsLayout, categoryFilters) => {
4823
4938
  const refreshButtonDom = getRefreshButtonDom();
4824
4939
  if (useDevtoolsLayout) {
@@ -4856,23 +4971,85 @@ const getDetailsCloseButtonDom = () => {
4856
4971
  return detailsCloseButtonDom;
4857
4972
  };
4858
4973
 
4859
- const getLineNodeDom = (line, index) => {
4974
+ const defaultEditorCursor = {
4975
+ columnIndex: 0,
4976
+ rowIndex: 1
4977
+ };
4978
+ const getEditorSelectionDom = (cursor = defaultEditorCursor) => {
4979
+ const hasCursor = cursor !== null;
4860
4980
  return [{
4981
+ childCount: hasCursor ? 1 : 0,
4982
+ className: EditorSelections,
4983
+ type: Div
4984
+ }, ...(hasCursor ? [{
4985
+ childCount: 0,
4986
+ className: EditorSelection,
4987
+ style: getPreviewTextCursorStyle(cursor),
4988
+ type: Div
4989
+ }] : [])];
4990
+ };
4991
+ const getGutterDom = (lineData, showLineNumbers) => {
4992
+ const gutterNodes = showLineNumbers ? lineData.flatMap((_, index) => {
4993
+ return [{
4994
+ childCount: 1,
4995
+ className: ChatDebugViewEventLineNumber,
4996
+ type: Span
4997
+ }, text(String(index + 1))];
4998
+ }) : [];
4999
+ return [{
5000
+ childCount: showLineNumbers ? lineData.length : 0,
5001
+ className: Gutter,
5002
+ type: Div
5003
+ }, ...gutterNodes];
5004
+ };
5005
+ const getEditorRowDom = line => {
5006
+ return [{
5007
+ childCount: line.childCount,
5008
+ className: EditorRow,
5009
+ type: Div
5010
+ }, ...line.nodes];
5011
+ };
5012
+ const getEditorRowsDom = lineData => {
5013
+ return [{
5014
+ childCount: lineData.length,
5015
+ className: EditorRows,
5016
+ type: Div
5017
+ }, ...lineData.flatMap(getEditorRowDom)];
5018
+ };
5019
+ const getEditorDom = (lineData, showLineNumbers = true, cursor = defaultEditorCursor, onPointerDown) => {
5020
+ return [{
5021
+ childCount: 1,
5022
+ className: EditorContainer,
5023
+ type: Div
5024
+ }, {
5025
+ childCount: 2,
5026
+ className: EditorViewlet,
5027
+ role: 'code',
5028
+ type: Div
5029
+ }, ...getGutterDom(lineData, showLineNumbers), {
4861
5030
  childCount: 2,
4862
- className: Row,
5031
+ className: EditorContent,
5032
+ onPointerDown,
4863
5033
  type: Div
4864
5034
  }, {
4865
- childCount: 1,
4866
- className: ChatDebugViewEventLineNumber,
4867
- type: Span
4868
- }, text(String(index + 1)), {
4869
- childCount: line.childCount,
4870
- className: ChatDebugViewEventLineContent,
4871
- type: Span
4872
- }, ...line.nodes];
4873
- };
4874
- const getLineNodes = lines => {
4875
- return lines.flatMap(getLineNodeDom);
5035
+ 'aria-autocomplete': 'list',
5036
+ 'aria-multiline': true,
5037
+ 'aria-roledescription': 'editor',
5038
+ autocapitalize: 'off',
5039
+ autocomplete: 'off',
5040
+ autocorrect: 'off',
5041
+ childCount: 0,
5042
+ className: EditorInput,
5043
+ name: 'editor',
5044
+ role: 'textbox',
5045
+ spellcheck: false,
5046
+ type: TextArea,
5047
+ wrap: 'off'
5048
+ }, {
5049
+ childCount: 2,
5050
+ className: EditorLayers,
5051
+ type: Div
5052
+ }, ...getEditorSelectionDom(cursor), ...getEditorRowsDom(lineData)];
4876
5053
  };
4877
5054
 
4878
5055
  const isDigit = character => {
@@ -5031,256 +5208,63 @@ const getEventNode = value => {
5031
5208
  type: getEventTypeLabel(value)
5032
5209
  } : value;
5033
5210
  const lines = getJsonLines(renderedValue);
5034
- const lineNodes = getLineNodes(lines.map(line => {
5211
+ const lineData = lines.map(line => {
5035
5212
  const lineContentNodes = getLineContentNodes(line);
5036
5213
  return {
5037
5214
  childCount: lineContentNodes.length / 2,
5038
5215
  nodes: lineContentNodes
5039
5216
  };
5040
- }));
5041
- return lineNodes;
5217
+ });
5218
+ return getEditorDom(lineData);
5042
5219
  };
5043
5220
 
5044
5221
  const getPanelId = detailTab => {
5045
5222
  return `ChatDebugViewDetailsPanel-${detailTab}`;
5046
5223
  };
5047
5224
 
5048
- const getPreviewName = event => {
5049
- if (typeof event.name === 'string' && event.name) {
5050
- return event.name;
5051
- }
5052
- if (typeof event.toolName === 'string' && event.toolName) {
5053
- return event.toolName;
5054
- }
5055
- return undefined;
5056
- };
5057
-
5058
- const hasOwn = (event, key) => {
5059
- return Object.hasOwn(event, key);
5060
- };
5061
-
5062
- const shouldIncludeArguments = (event, name) => {
5063
- if (!hasOwn(event, 'arguments')) {
5064
- return false;
5065
- }
5066
- if (name === 'getWorkspaceUri') {
5067
- return false;
5068
- }
5069
- return true;
5070
- };
5071
-
5072
- const getPayloadEvent = event => {
5073
- const name = getPreviewName(event);
5074
- if (name === 'list_files' && hasOwn(event, 'arguments')) {
5075
- return event.arguments;
5076
- }
5077
- const payloadEvent = {
5078
- ...(name === undefined ? {} : {
5079
- name
5080
- }),
5081
- ...(shouldIncludeArguments(event, name) ? {
5082
- arguments: event.arguments
5083
- } : {}),
5084
- ...(hasOwn(event, 'result') ? {
5085
- result: event.result
5086
- } : {})
5087
- };
5088
- if (Object.keys(payloadEvent).length > 0) {
5089
- return payloadEvent;
5090
- }
5091
- return event;
5092
- };
5093
-
5094
- const getListFilesPreviewEvent = (event, name) => {
5095
- if (name !== 'list_files') {
5096
- return undefined;
5097
- }
5098
- const {
5099
- result
5100
- } = event;
5101
- if (typeof result !== 'object' || result === null || !Object.hasOwn(result, 'entries')) {
5102
- return undefined;
5103
- }
5104
- const {
5105
- entries
5106
- } = result;
5107
- return entries;
5108
- };
5109
-
5110
- const isChatMessageAddedEvent = event => {
5111
- return event.type === 'chat-message-added';
5112
- };
5113
-
5114
- const isChatMessageUpdatedEvent = event => {
5115
- return event.type === 'chat-message-updated';
5116
- };
5117
-
5118
- const getResponseContentText = content => {
5119
- if (!content || typeof content !== 'object') {
5120
- return undefined;
5121
- }
5122
- if (Array.isArray(content)) {
5123
- const [firstContentItem] = content;
5124
- if (!firstContentItem || typeof firstContentItem !== 'object') {
5125
- return undefined;
5126
- }
5127
- const {
5128
- text
5129
- } = firstContentItem;
5130
- return typeof text === 'string' ? text : undefined;
5131
- }
5132
- const {
5133
- text
5134
- } = content;
5135
- return typeof text === 'string' ? text : undefined;
5136
- };
5137
- const getSseResponseCompletedPreviewText = event => {
5138
- if (event.type !== 'sse-response-completed') {
5139
- return undefined;
5140
- }
5141
- const {
5142
- value
5143
- } = event;
5144
- if (!value || typeof value !== 'object') {
5145
- return undefined;
5146
- }
5147
- const {
5148
- response
5149
- } = value;
5150
- if (!response || typeof response !== 'object') {
5151
- return undefined;
5152
- }
5153
- const {
5154
- output
5155
- } = response;
5156
- if (!Array.isArray(output) || output.length === 0) {
5157
- return undefined;
5158
- }
5159
- const [firstOutput] = output;
5160
- if (!firstOutput || typeof firstOutput !== 'object') {
5161
- return undefined;
5162
- }
5163
- const {
5164
- content
5165
- } = firstOutput;
5166
- return getResponseContentText(content);
5167
- };
5168
- const getPreviewMessageText = event => {
5169
- if (isChatMessageUpdatedEvent(event) && typeof event.text === 'string') {
5170
- return event.text;
5171
- }
5172
- const sseResponseCompletedPreviewText = getSseResponseCompletedPreviewText(event);
5173
- if (sseResponseCompletedPreviewText !== undefined) {
5174
- return sseResponseCompletedPreviewText;
5175
- }
5176
- if (!isChatMessageAddedEvent(event)) {
5177
- return undefined;
5178
- }
5179
- const {
5180
- message
5181
- } = event;
5182
- if (!message || typeof message !== 'object') {
5183
- return undefined;
5184
- }
5185
- if (!Object.hasOwn(message, 'text')) {
5186
- return undefined;
5187
- }
5188
- const {
5189
- text
5190
- } = message;
5191
- if (typeof text !== 'string') {
5192
- return undefined;
5193
- }
5194
- return text;
5195
- };
5196
-
5197
- const getReadFilePreviewText = (event, name) => {
5198
- if (name !== 'read_file') {
5199
- return undefined;
5200
- }
5201
- const {
5202
- result
5203
- } = event;
5204
- if (typeof result !== 'string') {
5205
- return undefined;
5206
- }
5207
- return result;
5208
- };
5209
-
5210
- const getWriteFilePreviewText = (event, name) => {
5211
- if (name !== 'write_file') {
5212
- return undefined;
5213
- }
5214
- const {
5215
- arguments: toolArguments
5216
- } = event;
5217
- if (typeof toolArguments !== 'object' || toolArguments === null || !Object.hasOwn(toolArguments, 'content')) {
5218
- return undefined;
5219
- }
5220
- const {
5221
- content
5222
- } = toolArguments;
5223
- if (typeof content !== 'string') {
5224
- return undefined;
5225
- }
5226
- return content;
5227
- };
5228
-
5229
- const getPreviewEvent = event => {
5230
- const selectedEventPreview = getSelectedEventPreview(event);
5231
- if (selectedEventPreview !== undefined) {
5232
- return selectedEventPreview;
5233
- }
5234
- const previewMessageText = getPreviewMessageText(event);
5235
- if (previewMessageText !== undefined) {
5236
- return previewMessageText;
5237
- }
5238
- const name = getPreviewName(event);
5239
- const writeFilePreviewText = getWriteFilePreviewText(event, name);
5240
- if (writeFilePreviewText !== undefined) {
5241
- return writeFilePreviewText;
5242
- }
5243
- const readFilePreviewText = getReadFilePreviewText(event, name);
5244
- if (readFilePreviewText !== undefined) {
5245
- return readFilePreviewText;
5246
- }
5247
- const listFilesPreviewEvent = getListFilesPreviewEvent(event, name);
5248
- if (listFilesPreviewEvent !== undefined) {
5249
- return listFilesPreviewEvent;
5250
- }
5251
- return getPayloadEvent(event);
5252
- };
5253
-
5254
5225
  const isAttachmentImagePreview = value => {
5255
5226
  return typeof value === 'object' && value !== null && value.previewType === 'image';
5256
5227
  };
5257
5228
 
5229
+ const getImagePreviewLabelDom = preview => {
5230
+ if (preview.stats === undefined) {
5231
+ return [{
5232
+ childCount: 1,
5233
+ className: ChatDebugViewImagePreviewLabel,
5234
+ type: Span
5235
+ }, text(preview.alt)];
5236
+ }
5237
+ return [{
5238
+ childCount: 2,
5239
+ className: ChatDebugViewImagePreviewLabel,
5240
+ type: Span
5241
+ }, {
5242
+ childCount: 1,
5243
+ type: Span
5244
+ }, text(preview.stats), {
5245
+ childCount: 1,
5246
+ type: Span
5247
+ }, text(preview.alt)];
5248
+ };
5258
5249
  const getImagePreviewDom = preview => {
5259
5250
  return [{
5260
5251
  childCount: 2,
5261
5252
  className: ChatDebugViewImagePreview,
5262
5253
  type: Div
5254
+ }, {
5255
+ childCount: 1,
5256
+ className: ChatDebugViewImagePreviewImageWrapper,
5257
+ type: Div
5263
5258
  }, {
5264
5259
  alt: preview.alt,
5265
5260
  childCount: 0,
5266
5261
  className: ChatDebugViewImagePreviewImage,
5267
5262
  src: preview.src,
5268
5263
  type: Img
5269
- }, {
5270
- childCount: 1,
5271
- className: ChatDebugViewImagePreviewLabel,
5272
- type: Span
5273
- }, text(preview.alt)];
5264
+ }, ...getImagePreviewLabelDom(preview)];
5274
5265
  };
5275
5266
 
5276
- const getTextNode = (value, showLineNumbers = true) => {
5277
- if (!showLineNumbers) {
5278
- return [{
5279
- childCount: 1,
5280
- className: ChatDebugViewEventRawText,
5281
- type: P
5282
- }, text(value)];
5283
- }
5267
+ const getTextNode = (value, showLineNumbers = true, cursor = null) => {
5284
5268
  const lines = value.split('\n');
5285
5269
  const lineData = lines.map(line => {
5286
5270
  return {
@@ -5292,16 +5276,15 @@ const getTextNode = (value, showLineNumbers = true) => {
5292
5276
  }, text(line)]
5293
5277
  };
5294
5278
  });
5295
- const lineNodes = getLineNodes(lineData);
5296
- return lineNodes;
5279
+ return getEditorDom(lineData, showLineNumbers, cursor, showLineNumbers ? HandlePreviewTextPointerDown : undefined);
5297
5280
  };
5298
5281
 
5299
- const getPreviewEventNodes = (previewEvent, selectedEvent) => {
5282
+ const getPreviewEventNodes = (previewEvent, selectedEvent, previewTextCursor) => {
5300
5283
  if (typeof previewEvent === 'string') {
5301
5284
  const isInvalidImageMessage = previewEvent === ImageCouldNotBeLoaded;
5302
5285
  const isChatMessageUpdatedPreview = !!selectedEvent && isChatMessageUpdatedEvent(selectedEvent);
5303
5286
  const showLineNumbers = !isInvalidImageMessage && !isChatMessageUpdatedPreview;
5304
- return getTextNode(previewEvent, showLineNumbers);
5287
+ return getTextNode(previewEvent, showLineNumbers, showLineNumbers ? previewTextCursor ?? null : null);
5305
5288
  }
5306
5289
  if (previewEvent === undefined) {
5307
5290
  return [];
@@ -5312,10 +5295,6 @@ const getPreviewEventNodes = (previewEvent, selectedEvent) => {
5312
5295
  return getEventNode(previewEvent);
5313
5296
  };
5314
5297
 
5315
- const getTabId = detailTab => {
5316
- return `ChatDebugViewDetailsTab-${detailTab}`;
5317
- };
5318
-
5319
5298
  const getDetailTabDom = detailTab => {
5320
5299
  const {
5321
5300
  isSelected
@@ -5324,11 +5303,11 @@ const getDetailTabDom = detailTab => {
5324
5303
  'aria-controls': getPanelId(detailTab.name),
5325
5304
  ariaSelected: isSelected,
5326
5305
  childCount: 1,
5327
- className: mergeClassNames(ChatDebugViewDetailsTab, isSelected ? ChatDebugViewDetailsTabSelected : ''),
5328
- id: getTabId(detailTab.name),
5306
+ className: mergeClassNames(PanelTab, isSelected ? PanelTabSelected : ''),
5329
5307
  name: detailTab.name,
5330
5308
  onChange: SelectDetailTab,
5331
5309
  onClick: SelectDetailTab,
5310
+ onFocus: HandleDetailTabsFocus,
5332
5311
  role: Tab,
5333
5312
  tabIndex: isSelected ? 0 : -1,
5334
5313
  type: Button$1
@@ -5377,9 +5356,58 @@ const getTimestampText = value => {
5377
5356
  const getEndText = event => {
5378
5357
  return getTimestampText(event.ended ?? event.endTime ?? event.endTimestamp ?? event.timestamp);
5379
5358
  };
5380
-
5381
- const getStartText = event => {
5382
- return getTimestampText(event.started ?? event.startTime ?? event.startTimestamp ?? event.timestamp);
5359
+
5360
+ const getStartText = event => {
5361
+ return getTimestampText(event.started ?? event.startTime ?? event.startTimestamp ?? event.timestamp);
5362
+ };
5363
+
5364
+ const getTimingPreviewSegments = event => {
5365
+ return [{
5366
+ endPercent: 100,
5367
+ label: getDurationText(event),
5368
+ startPercent: 0
5369
+ }];
5370
+ };
5371
+ const getTimingPreviewSegmentNodes = segments => {
5372
+ return [{
5373
+ childCount: segments.length,
5374
+ className: ChatDebugViewTimingPreviewTrackOverlay,
5375
+ type: Div
5376
+ }, ...segments.flatMap(segment => {
5377
+ const widthPercent = Math.max(0, segment.endPercent - segment.startPercent);
5378
+ return [{
5379
+ childCount: 1,
5380
+ className: ChatDebugViewTimingPreviewSegment,
5381
+ style: `left:${segment.startPercent}%;width:${widthPercent}%;min-width:2px;`,
5382
+ type: Div
5383
+ }, text(segment.label)];
5384
+ })];
5385
+ };
5386
+ const getTimingPreviewDom = event => {
5387
+ const segments = getTimingPreviewSegments(event);
5388
+ return [{
5389
+ childCount: 1,
5390
+ className: ChatDebugViewTimingPreview,
5391
+ type: Div
5392
+ }, {
5393
+ childCount: 4,
5394
+ className: ChatDebugViewTimingPreviewTrack,
5395
+ type: Div
5396
+ }, {
5397
+ childCount: 0,
5398
+ className: ChatDebugViewTimingPreviewRail,
5399
+ type: Div
5400
+ }, ...getTimingPreviewSegmentNodes(segments), {
5401
+ childCount: 0,
5402
+ className: `${ChatDebugViewTimingPreviewMarker} ${ChatDebugViewTimingPreviewMarkerStart}`,
5403
+ style: 'left:12px;',
5404
+ type: Div
5405
+ }, {
5406
+ childCount: 0,
5407
+ className: `${ChatDebugViewTimingPreviewMarker} ${ChatDebugViewTimingPreviewMarkerEnd}`,
5408
+ style: 'right:12px;',
5409
+ type: Div
5410
+ }];
5383
5411
  };
5384
5412
 
5385
5413
  const timingRowNode = {
@@ -5403,26 +5431,26 @@ const getTimingRowDom = (label, value) => {
5403
5431
 
5404
5432
  const getTimingDetailsDom = event => {
5405
5433
  return [{
5406
- childCount: 3,
5434
+ childCount: 4,
5407
5435
  className: ChatDebugViewTiming,
5408
5436
  type: Div
5409
- }, ...getTimingRowDom(started(), getStartText(event)), ...getTimingRowDom(ended(), getEndText(event)), ...getTimingRowDom(duration(), getDurationText(event))];
5437
+ }, ...getTimingPreviewDom(event), ...getTimingRowDom(started(), getStartText(event)), ...getTimingRowDom(ended(), getEndText(event)), ...getTimingRowDom(duration(), getDurationText(event))];
5410
5438
  };
5411
5439
 
5412
- const getNextSiblingIndex$1 = (nodes, index) => {
5440
+ const getNextSiblingIndex$2 = (nodes, index) => {
5413
5441
  let nextSiblingIndex = index + 1;
5414
5442
  const childCount = nodes[index]?.childCount || 0;
5415
5443
  for (let i = 0; i < childCount; i++) {
5416
- nextSiblingIndex = getNextSiblingIndex$1(nodes, nextSiblingIndex);
5444
+ nextSiblingIndex = getNextSiblingIndex$2(nodes, nextSiblingIndex);
5417
5445
  }
5418
5446
  return nextSiblingIndex;
5419
5447
  };
5420
- const getDirectChildCount = nodes => {
5448
+ const getDirectChildCount$1 = nodes => {
5421
5449
  let count = 0;
5422
5450
  let index = 0;
5423
5451
  while (index < nodes.length) {
5424
5452
  count++;
5425
- index = getNextSiblingIndex$1(nodes, index);
5453
+ index = getNextSiblingIndex$2(nodes, index);
5426
5454
  }
5427
5455
  return count;
5428
5456
  };
@@ -5432,12 +5460,13 @@ const getNormalizedDetailTabs = (selectedEvent, detailTabs) => {
5432
5460
  }
5433
5461
  return createDetailTabs(getSelectedDetailTab(detailTabs), selectedEvent);
5434
5462
  };
5435
- const getDetailsDom = (previewEventNodes, payloadEventNodes = previewEventNodes, responseEventNodes = payloadEventNodes, selectedEvent = null, detailTabs = createDetailTabs()) => {
5463
+ const getDetailsDom = (previewEventNodes, payloadEventNodes = previewEventNodes, responseEventNodes = payloadEventNodes, selectedEvent = null, detailTabs = createDetailTabs(), previewTextCursorRowIndex = null, previewTextCursorColumnIndex = null) => {
5436
5464
  if (previewEventNodes.length === 0 && payloadEventNodes.length === 0 && responseEventNodes.length === 0) {
5437
5465
  return [];
5438
5466
  }
5439
5467
  const normalizedDetailTabs = getNormalizedDetailTabs(selectedEvent, detailTabs);
5440
5468
  const safeSelectedDetailTab = getSelectedDetailTab(normalizedDetailTabs);
5469
+ const selectedDetailTab = normalizedDetailTabs.find(detailTab => detailTab.name === safeSelectedDetailTab) ?? normalizedDetailTabs[0];
5441
5470
  const getDetailContentDom = () => {
5442
5471
  const getDetailContentDomTiming = () => {
5443
5472
  if (selectedEvent === null) {
@@ -5452,7 +5481,10 @@ const getDetailsDom = (previewEventNodes, payloadEventNodes = previewEventNodes,
5452
5481
  if (selectedEvent === null) {
5453
5482
  return [];
5454
5483
  }
5455
- return getPreviewEventNodes(getPreviewEvent(selectedEvent), selectedEvent);
5484
+ return getPreviewEventNodes(getPreviewEvent(selectedEvent), selectedEvent, previewTextCursorRowIndex === null || previewTextCursorColumnIndex === null ? null : {
5485
+ columnIndex: previewTextCursorColumnIndex,
5486
+ rowIndex: previewTextCursorRowIndex
5487
+ });
5456
5488
  };
5457
5489
  const getDetailContentDomPayload = () => {
5458
5490
  if (payloadEventNodes.length > 0) {
@@ -5474,8 +5506,8 @@ const getDetailsDom = (previewEventNodes, payloadEventNodes = previewEventNodes,
5474
5506
  };
5475
5507
  const contentNodes = safeSelectedDetailTab === Timing ? getDetailContentDomTiming() : safeSelectedDetailTab === Preview ? getDetailContentDomPreview() : safeSelectedDetailTab === Payload ? getDetailContentDomPayload() : getDetailContentDomResponse();
5476
5508
  return [{
5477
- 'aria-labelledby': getTabId(safeSelectedDetailTab),
5478
- childCount: getDirectChildCount(contentNodes),
5509
+ 'aria-label': selectedDetailTab.label,
5510
+ childCount: getDirectChildCount$1(contentNodes),
5479
5511
  className: ChatDebugViewDetailsBottom,
5480
5512
  id: getPanelId(safeSelectedDetailTab),
5481
5513
  onContextMenu: HandleDetailsContextMenu,
@@ -5498,18 +5530,17 @@ const getDetailsDom = (previewEventNodes, payloadEventNodes = previewEventNodes,
5498
5530
  const getRowCellNodes = (event, isErrorStatus, visibleTableColumns) => {
5499
5531
  const orderedVisibleTableColumns = getOrderedVisibleTableColumns(visibleTableColumns);
5500
5532
  return orderedVisibleTableColumns.flatMap((column, index) => {
5501
- const isFixed = index < orderedVisibleTableColumns.length - 1;
5502
5533
  switch (column) {
5503
5534
  case Duration:
5504
5535
  return [{
5505
5536
  childCount: 1,
5506
- className: TableCell,
5537
+ className: mergeClassNames(TableCell, ChatDebugViewCellDuration),
5507
5538
  type: Td
5508
5539
  }, text(getEventTableDurationText(event))];
5509
5540
  case Status$1:
5510
5541
  return [{
5511
5542
  childCount: 1,
5512
- className: mergeClassNames(TableCell, isErrorStatus ? ChatDebugViewCellStatusError : '', isFixed ? ChatDebugViewColumnFixed : ''),
5543
+ className: mergeClassNames(TableCell, isErrorStatus ? ChatDebugViewCellStatusError : ''),
5513
5544
  type: Td
5514
5545
  }, text(getStatusText(event))];
5515
5546
  case Type:
@@ -5524,16 +5555,18 @@ const getRowCellNodes = (event, isErrorStatus, visibleTableColumns) => {
5524
5555
  });
5525
5556
  };
5526
5557
 
5527
- const getDevtoolsRows = (events, selectedEventIndex, visibleTableColumns = defaultVisibleTableColumns) => {
5558
+ const getDevtoolsRows = (events, selectedEventIndex, visibleTableColumns = defaultVisibleTableColumns, startIndex = 0) => {
5528
5559
  return events.flatMap((event, i) => {
5529
- const isEvenRow = i % 2 === 1;
5560
+ const actualIndex = startIndex + i;
5561
+ const isEvenRow = actualIndex % 2 === 1;
5530
5562
  const rowClassName = isEvenRow ? TableRowEven : TableRowOdd;
5531
- const isSelected = selectedEventIndex === i;
5563
+ const isSelected = selectedEventIndex === actualIndex;
5532
5564
  const isErrorStatus = hasErrorStatus(event);
5533
5565
  const rowCellNodes = getRowCellNodes(event, isErrorStatus, visibleTableColumns);
5534
5566
  return [{
5535
5567
  childCount: visibleTableColumns.length,
5536
5568
  className: mergeClassNames(TableRow, rowClassName, isSelected ? TableRowSelected : ''),
5569
+ 'data-index': `${actualIndex}`,
5537
5570
  type: Tr
5538
5571
  }, ...rowCellNodes];
5539
5572
  });
@@ -5554,14 +5587,10 @@ const getEventsClassName = hasSelectedEvent => {
5554
5587
  };
5555
5588
 
5556
5589
  const sashNodesDom = [{
5557
- childCount: 1,
5590
+ childCount: 0,
5558
5591
  className: Sash,
5559
5592
  onPointerDown: HandleSashPointerDown,
5560
5593
  type: Button$1
5561
- }, {
5562
- childCount: 0,
5563
- className: ChatDebugViewSashLine,
5564
- type: Div
5565
5594
  }];
5566
5595
  const getSashNodesDom = hasSelectedEvent => {
5567
5596
  if (!hasSelectedEvent) {
@@ -5573,7 +5602,33 @@ const getSashNodesDom = hasSelectedEvent => {
5573
5602
  const None = 'none';
5574
5603
  const Status = 'status';
5575
5604
 
5576
- const getSplitViewDom = (splitChildCount, eventsChildCount, eventsClassName, tableNodes, sashNodes, detailsNodes) => {
5605
+ const getNextSiblingIndex$1 = (nodes, index) => {
5606
+ let nextSiblingIndex = index + 1;
5607
+ const childCount = nodes[index]?.childCount || 0;
5608
+ for (let i = 0; i < childCount; i++) {
5609
+ nextSiblingIndex = getNextSiblingIndex$1(nodes, nextSiblingIndex);
5610
+ }
5611
+ return nextSiblingIndex;
5612
+ };
5613
+ const getDirectChildCount = nodes => {
5614
+ let count = 0;
5615
+ let index = 0;
5616
+ while (index < nodes.length) {
5617
+ count++;
5618
+ index = getNextSiblingIndex$1(nodes, index);
5619
+ }
5620
+ return count;
5621
+ };
5622
+ const getSplitViewDom = (splitChildCount, eventsClassName, tableNodes, sashNodes, detailsNodes) => {
5623
+ const eventsChildCount = getDirectChildCount(tableNodes);
5624
+ if (splitChildCount === 1) {
5625
+ return [{
5626
+ childCount: eventsChildCount,
5627
+ className: eventsClassName,
5628
+ role: 'application',
5629
+ type: Div
5630
+ }, ...tableNodes];
5631
+ }
5577
5632
  return [{
5578
5633
  childCount: splitChildCount,
5579
5634
  className: ChatDebugViewDevtoolsSplit,
@@ -5587,6 +5642,61 @@ const getSplitViewDom = (splitChildCount, eventsChildCount, eventsClassName, tab
5587
5642
  }, ...tableNodes, ...sashNodes, ...detailsNodes];
5588
5643
  };
5589
5644
 
5645
+ const formatTimelineMilliseconds = value => {
5646
+ return `${Math.round(value * 1000)}ms`;
5647
+ };
5648
+
5649
+ const formatTimelineSeconds = value => {
5650
+ if (Number.isInteger(value)) {
5651
+ return `${value}s`;
5652
+ }
5653
+ return `${Number(value.toFixed(1))}s`;
5654
+ };
5655
+
5656
+ const getEndTime = event => {
5657
+ return event.ended ?? event.endTime ?? event.timestamp;
5658
+ };
5659
+
5660
+ const getStartTime = event => {
5661
+ return event.started ?? event.startTime ?? event.timestamp;
5662
+ };
5663
+
5664
+ const formatTableSummaryDuration = durationMs => {
5665
+ if (durationMs < 1000) {
5666
+ return formatTimelineMilliseconds(durationMs / 1000);
5667
+ }
5668
+ return formatTimelineSeconds(durationMs / 1000);
5669
+ };
5670
+ const getTableSummary = events => {
5671
+ let minStart = Number.POSITIVE_INFINITY;
5672
+ let maxEnd = Number.NEGATIVE_INFINITY;
5673
+ for (const event of events) {
5674
+ const startTime = toTimeNumber(getStartTime(event));
5675
+ const endTime = toTimeNumber(getEndTime(event));
5676
+ if (typeof startTime === 'number' && Number.isFinite(startTime)) {
5677
+ minStart = Math.min(minStart, startTime);
5678
+ }
5679
+ if (typeof endTime === 'number' && Number.isFinite(endTime)) {
5680
+ maxEnd = Math.max(maxEnd, endTime);
5681
+ }
5682
+ }
5683
+ const durationMs = Number.isFinite(minStart) && Number.isFinite(maxEnd) ? Math.max(0, maxEnd - minStart) : 0;
5684
+ return tableSummary(events.length, formatTableSummaryDuration(durationMs));
5685
+ };
5686
+
5687
+ const tableSummaryNode = {
5688
+ childCount: 1,
5689
+ className: TableSummary,
5690
+ role: Status,
5691
+ type: Div
5692
+ };
5693
+ const getTableSummaryDom = summary => {
5694
+ if (!summary) {
5695
+ return [];
5696
+ }
5697
+ return [tableSummaryNode, text(summary)];
5698
+ };
5699
+
5590
5700
  const getTableBodyDom = (rowNodes, eventCount) => {
5591
5701
  return [{
5592
5702
  childCount: eventCount === 0 ? 1 : eventCount,
@@ -5611,42 +5721,21 @@ const getTableColumnGroupDom = visibleTableColumns => {
5611
5721
  }))];
5612
5722
  };
5613
5723
 
5724
+ const getHeaderCellNode = (column, tableColumns) => {
5725
+ return [{
5726
+ childCount: 1,
5727
+ className: ChatDebugViewHeaderCell,
5728
+ name: column,
5729
+ onClick: HandleTableHeaderClick,
5730
+ type: Th
5731
+ }, text(getTableColumnLabel(tableColumns, column))];
5732
+ };
5614
5733
  const getHeaderCellNodes = (visibleTableColumns, tableColumns = createTableColumns()) => {
5615
5734
  const orderedVisibleTableColumns = getOrderedVisibleTableColumns(visibleTableColumns, tableColumns);
5616
- return orderedVisibleTableColumns.flatMap(column => {
5617
- switch (column) {
5618
- case Duration:
5619
- return [{
5620
- childCount: 1,
5621
- className: ChatDebugViewHeaderCell,
5622
- name: column,
5623
- onClick: HandleTableHeaderClick,
5624
- type: Th
5625
- }, text(getTableColumnLabel(tableColumns, column))];
5626
- case Status$1:
5627
- return [{
5628
- childCount: 1,
5629
- className: ChatDebugViewHeaderCell,
5630
- name: column,
5631
- onClick: HandleTableHeaderClick,
5632
- type: Th
5633
- }, text(getTableColumnLabel(tableColumns, column))];
5634
- case Type:
5635
- return [{
5636
- childCount: 1,
5637
- className: ChatDebugViewHeaderCell,
5638
- name: column,
5639
- onClick: HandleTableHeaderClick,
5640
- type: Th
5641
- }, text(getTableColumnLabel(tableColumns, column))];
5642
- default:
5643
- return [];
5644
- }
5645
- });
5735
+ return orderedVisibleTableColumns.flatMap(column => getHeaderCellNode(column, tableColumns));
5646
5736
  };
5647
5737
 
5648
5738
  const getTableHeaderDom = (visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns()) => {
5649
- const headerCellNodes = getHeaderCellNodes(visibleTableColumns, tableColumns);
5650
5739
  return [{
5651
5740
  childCount: 1,
5652
5741
  className: TableHead,
@@ -5656,7 +5745,17 @@ const getTableHeaderDom = (visibleTableColumns = defaultVisibleTableColumns, tab
5656
5745
  childCount: visibleTableColumns.length,
5657
5746
  className: TableRow,
5658
5747
  type: Tr
5659
- }, ...headerCellNodes];
5748
+ }, ...getHeaderCellNodes(visibleTableColumns, tableColumns)];
5749
+ };
5750
+
5751
+ const getTableDom = (rowNodes, eventCount, visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns(), summary = '', focus = 0) => {
5752
+ return [{
5753
+ childCount: 3,
5754
+ className: Table,
5755
+ onFocus: HandleTableFocus,
5756
+ tabIndex: 0,
5757
+ type: Table$1
5758
+ }, ...getTableColumnGroupDom(visibleTableColumns), ...getTableHeaderDom(visibleTableColumns, tableColumns), ...getTableBodyDom(rowNodes, eventCount)];
5660
5759
  };
5661
5760
 
5662
5761
  const resizerNames = ['ResizerOne', 'ResizerTwo'];
@@ -5674,6 +5773,7 @@ const getTableResizersDom = visibleTableColumns => {
5674
5773
  name: resizerNames[index],
5675
5774
  onPointerDown: HandleTableResizerPointerDown,
5676
5775
  role: None,
5776
+ tabIndex: -1,
5677
5777
  type: Button$1
5678
5778
  }, {
5679
5779
  childCount: 0,
@@ -5682,80 +5782,50 @@ const getTableResizersDom = visibleTableColumns => {
5682
5782
  type: Div
5683
5783
  }]);
5684
5784
  return [{
5685
- childCount: resizerCount + 1,
5785
+ childCount: resizerCount,
5686
5786
  className: Resizers,
5687
5787
  type: Div
5688
5788
  }, ...resizerNodes];
5689
5789
  };
5690
5790
 
5691
- const tableSummaryNode = {
5692
- childCount: 1,
5693
- className: TableSummary,
5694
- role: Status,
5695
- type: Div
5696
- };
5697
- const getTableSummaryDom = summary => {
5698
- if (!summary) {
5791
+ const getTableScrollBarDom = visible => {
5792
+ if (!visible) {
5699
5793
  return [];
5700
5794
  }
5701
- return [tableSummaryNode, text(summary)];
5702
- };
5703
-
5704
- const getTableDom = (rowNodes, eventCount, visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns(), summary = '', focus = 0) => {
5705
- const tableWrapperClassName = mergeClassNames(TableWrapper, focus === FocusChatDebugTable ? FocusOutline : '');
5706
5795
  return [{
5707
- childCount: 2,
5708
- className: tableWrapperClassName,
5796
+ childCount: 1,
5797
+ className: TableScrollBar,
5798
+ onPointerDown: HandleTableScrollBarPointerDown,
5709
5799
  type: Div
5710
5800
  }, {
5711
- childCount: 3,
5712
- className: Table,
5713
- onFocus: HandleTableFocus,
5714
- tabIndex: 0,
5715
- type: Table$1
5716
- }, ...getTableColumnGroupDom(visibleTableColumns), ...getTableHeaderDom(visibleTableColumns, tableColumns), ...getTableBodyDom(rowNodes, eventCount), ...getTableResizersDom(visibleTableColumns), ...getTableSummaryDom(summary)];
5717
- };
5718
-
5719
- const formatTimelineMilliseconds = value => {
5720
- return `${Math.round(value * 1000)}ms`;
5721
- };
5722
-
5723
- const formatTimelineSeconds = value => {
5724
- if (Number.isInteger(value)) {
5725
- return `${value}s`;
5726
- }
5727
- return `${Number(value.toFixed(1))}s`;
5728
- };
5729
-
5730
- const getEndTime = event => {
5731
- return event.ended ?? event.endTime ?? event.timestamp;
5801
+ childCount: 0,
5802
+ className: TableScrollBarThumb,
5803
+ type: Div
5804
+ }];
5732
5805
  };
5733
5806
 
5734
- const getStartTime = event => {
5735
- return event.started ?? event.startTime ?? event.timestamp;
5807
+ const getTableWrapperDom = (rowNodes, eventCount, visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns(), summary = '', focus = 0, className = '', role = '', showScrollBar = false) => {
5808
+ const tableWrapperClassName = mergeClassNames(TableWrapper, focus === FocusChatDebugTable ? FocusOutline : '', className);
5809
+ const scrollBarNodes = getTableScrollBarDom(showScrollBar);
5810
+ const tableWrapperNode = {
5811
+ childCount: showScrollBar ? 3 : 2,
5812
+ className: tableWrapperClassName,
5813
+ onWheel: HandleTableWheel,
5814
+ type: Div,
5815
+ ...(role ? {
5816
+ role
5817
+ } : {})
5818
+ };
5819
+ return [tableWrapperNode, ...getTableDom(rowNodes, eventCount, visibleTableColumns, tableColumns, summary, focus), ...getTableResizersDom(visibleTableColumns), ...scrollBarNodes];
5736
5820
  };
5737
5821
 
5738
- const formatTableSummaryDuration = durationMs => {
5739
- if (durationMs < 1000) {
5740
- return formatTimelineMilliseconds(durationMs / 1000);
5741
- }
5742
- return formatTimelineSeconds(durationMs / 1000);
5743
- };
5744
- const getTableSummary = events => {
5745
- let minStart = Number.POSITIVE_INFINITY;
5746
- let maxEnd = Number.NEGATIVE_INFINITY;
5747
- for (const event of events) {
5748
- const startTime = toTimeNumber(getStartTime(event));
5749
- const endTime = toTimeNumber(getEndTime(event));
5750
- if (typeof startTime === 'number' && Number.isFinite(startTime)) {
5751
- minStart = Math.min(minStart, startTime);
5752
- }
5753
- if (typeof endTime === 'number' && Number.isFinite(endTime)) {
5754
- maxEnd = Math.max(maxEnd, endTime);
5755
- }
5756
- }
5757
- const durationMs = Number.isFinite(minStart) && Number.isFinite(maxEnd) ? Math.max(0, maxEnd - minStart) : 0;
5758
- return tableSummary(events.length, formatTableSummaryDuration(durationMs));
5822
+ const getTableWrapperWrapperDom = (rowNodes, eventCount, visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns(), summary = '', focus = 0, className = '', role = '', showScrollBar = false) => {
5823
+ const tableSummaryNodes = getTableSummaryDom(summary);
5824
+ return [{
5825
+ childCount: tableSummaryNodes.length === 0 ? 1 : 2,
5826
+ className: TableWrapperWrapper,
5827
+ type: Div
5828
+ }, ...getTableWrapperDom(rowNodes, eventCount, visibleTableColumns, tableColumns, summary, focus, className, role, showScrollBar), ...tableSummaryNodes];
5759
5829
  };
5760
5830
 
5761
5831
  const getBucketUnitDom = (unitCount, presetValue) => {
@@ -5881,40 +5951,31 @@ const getTimelineBadgeNodes = timelineInfo => {
5881
5951
  };
5882
5952
 
5883
5953
  const getTimelineSummary = timelineInfo => {
5954
+ if (timelineInfo.durationSeconds === 0) {
5955
+ return '';
5956
+ }
5884
5957
  if (timelineInfo.hasSelection && timelineInfo.startSeconds !== null && timelineInfo.endSeconds !== null) {
5885
5958
  return windowSummary(formatTimelineSeconds(timelineInfo.startSeconds), formatTimelineSeconds(timelineInfo.endSeconds), formatTimelineSeconds(timelineInfo.durationSeconds));
5886
5959
  }
5887
5960
  return windowSummary('0s', formatTimelineSeconds(timelineInfo.durationSeconds), formatTimelineSeconds(timelineInfo.durationSeconds));
5888
5961
  };
5889
5962
 
5890
- const getTimelineTopDom = timelineInfo => {
5891
- return [{
5892
- childCount: 1,
5893
- className: ChatDebugViewTimelineTop,
5894
- type: Div
5895
- }, {
5896
- childCount: 1,
5897
- className: ChatDebugViewTimelineSummary,
5898
- type: H2
5899
- }, text(getTimelineSummary(timelineInfo))];
5900
- };
5901
-
5902
5963
  // cspell:ignore gettimelinedom
5903
5964
  const getTimelineDom = (timelineInfo, hoverPercent = null) => {
5904
5965
  if (timelineInfo.buckets.length === 0) {
5905
5966
  return [];
5906
5967
  }
5968
+ const summary = getTimelineSummary(timelineInfo);
5907
5969
  const badgeNodes = getTimelineBadgeNodes(timelineInfo);
5908
5970
  const bucketNodes = getBucketsDom(timelineInfo.buckets);
5909
5971
  const selectionNodes = getSelectionNodesDom(timelineInfo.hasSelection, timelineInfo.selectionStartPercent, timelineInfo.selectionEndPercent);
5910
5972
  const cursorGuideNodes = getCursorGuideNodes(hoverPercent);
5911
- const timelineTopDom = getTimelineTopDom(timelineInfo);
5912
5973
  return [{
5913
- childCount: 2,
5974
+ childCount: summary ? 2 : 1,
5914
5975
  className: ChatDebugViewTimeline,
5915
5976
  onContextMenu: HandleTimelineContextMenu,
5916
5977
  type: Section
5917
- }, ...timelineTopDom, {
5978
+ }, ...(summary ? [text(summary)] : []), {
5918
5979
  childCount: 3,
5919
5980
  className: ChatDebugViewTimelineInteractive,
5920
5981
  onDblClick: HandleTimelineDoubleClick,
@@ -5935,23 +5996,33 @@ const getTimelineDom = (timelineInfo, hoverPercent = null) => {
5935
5996
  }, ...selectionNodes];
5936
5997
  };
5937
5998
 
5938
- const getDevtoolsDom = (events, selectedEvent, selectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage = noEventsFound(), timelineSelectionActive = false, timelineSelectionAnchorSeconds = '', timelineSelectionFocusSeconds = '', visibleTableColumns = defaultVisibleTableColumns, detailTabs = createDetailTabs(), tableColumns = createTableColumns(), timelineInfo, timelineHoverPercent = null, focus = 0) => {
5939
- const rowNodes = getDevtoolsRows(events, selectedEventIndex, visibleTableColumns);
5999
+ 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, previewTextCursorRowIndex = null, previewTextCursorColumnIndex = null, minLineY = 0, maxLineY = events.length) => {
6000
+ const visibleEvents = events.slice(minLineY, maxLineY);
6001
+ const rowNodes = getDevtoolsRows(visibleEvents, selectedEventIndex, visibleTableColumns, minLineY);
5940
6002
  const effectiveRange = getEffectiveTimelineRange(timelineStartSeconds, timelineEndSeconds, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds);
5941
6003
  const resolvedTimelineInfo = timelineInfo || getTimelineInfo(timelineEvents, effectiveRange.startSeconds, effectiveRange.endSeconds);
5942
6004
  const timelineNodes = getTimelineDom(resolvedTimelineInfo, timelineHoverPercent);
5943
6005
  const previewEvent = selectedEvent ? getPreviewEvent(selectedEvent) : undefined;
5944
- const previewEventNodes = getPreviewEventNodes(previewEvent, selectedEvent);
6006
+ const previewEventNodes = getPreviewEventNodes(previewEvent, selectedEvent, previewTextCursorRowIndex === null || previewTextCursorColumnIndex === null ? null : {
6007
+ columnIndex: previewTextCursorColumnIndex,
6008
+ rowIndex: previewTextCursorRowIndex
6009
+ });
5945
6010
  const payloadEventNodes = selectedEvent ? getEventNode(getPayloadEvent(selectedEvent)) : [];
5946
6011
  const responseEventNodes = selectedEvent ? getEventNode(selectedEvent) : [];
5947
6012
  const hasSelectedEvent = responseEventNodes.length > 0;
5948
- const eventsChildCount = events.length === 0 ? 1 : 2;
5949
- const tableNodes = events.length === 0 ? getEmptyStateDom(emptyMessage) : getTableDom(rowNodes, events.length, visibleTableColumns, tableColumns, getTableSummary(events), focus);
5950
6013
  const eventsClassName = getEventsClassName(hasSelectedEvent);
5951
- const detailsNodes = getDetailsDom(previewEventNodes, payloadEventNodes, responseEventNodes, selectedEvent, detailTabs);
6014
+ const summary = getTableSummary(events);
6015
+ const showScrollBar = visibleEvents.length < events.length;
6016
+ const tableNodes = events.length === 0 ? getEmptyStateDom(emptyMessage) : getTableWrapperWrapperDom(rowNodes, visibleEvents.length, visibleTableColumns, tableColumns, summary, focus, '', '', showScrollBar);
6017
+ const detailsNodes = getDetailsDom(previewEventNodes, payloadEventNodes, responseEventNodes, selectedEvent, detailTabs, previewTextCursorRowIndex, previewTextCursorColumnIndex);
5952
6018
  const sashNodes = getSashNodesDom(hasSelectedEvent);
5953
6019
  const splitChildCount = hasSelectedEvent ? 3 : 1;
5954
- return [...timelineNodes, ...getSplitViewDom(splitChildCount, eventsChildCount, eventsClassName, tableNodes, sashNodes, detailsNodes)];
6020
+ const rootChildCount = 3;
6021
+ return [{
6022
+ childCount: rootChildCount,
6023
+ className: mergeClassNames(ChatDebugView, ChatDebugViewDevtools),
6024
+ type: Div
6025
+ }, ...timelineNodes, ...getSplitViewDom(splitChildCount, eventsClassName, tableNodes, sashNodes, detailsNodes)];
5955
6026
  };
5956
6027
 
5957
6028
  const getEmptyMessage = (eventCount, hasFilterValue, useNoToolCallEventsMessage, noFilteredEventsMessage) => {
@@ -5974,21 +6045,6 @@ const getLegacyEventsDom = (errorMessage, emptyMessage, eventNodes) => {
5974
6045
  }, text(errorMessage || emptyMessage)] : eventNodes)];
5975
6046
  };
5976
6047
 
5977
- const getTimelineFilterDescription = (timelineStartSeconds, timelineEndSeconds) => {
5978
- const trimmedStart = timelineStartSeconds.trim();
5979
- const trimmedEnd = timelineEndSeconds.trim();
5980
- if (trimmedStart && trimmedEnd) {
5981
- return secondsRange(trimmedStart, trimmedEnd);
5982
- }
5983
- if (trimmedStart) {
5984
- return fromSeconds(trimmedStart);
5985
- }
5986
- if (trimmedEnd) {
5987
- return toSeconds(trimmedEnd);
5988
- }
5989
- return '';
5990
- };
5991
-
5992
6048
  const getNextSiblingIndex = (nodes, index) => {
5993
6049
  let nextSiblingIndex = index + 1;
5994
6050
  const childCount = nodes[index]?.childCount || 0;
@@ -6012,7 +6068,7 @@ const getEventCategoryFilterDescription = eventCategoryFilters => {
6012
6068
  }
6013
6069
  return eventCategoryFilters.map(eventCategoryFilter => getEventCategoryFilterLabel(eventCategoryFilter).toLowerCase()).join(', ');
6014
6070
  };
6015
- 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, timelineHoverPercent = null, focus = 0) => {
6071
+ 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, previewTextCursorRowIndex = null, previewTextCursorColumnIndex = null, minLineY = 0, maxLineY = events.length) => {
6016
6072
  if (errorMessage) {
6017
6073
  return getDebugErrorDom(errorMessage);
6018
6074
  }
@@ -6025,7 +6081,6 @@ const getChatDebugViewDom = (errorMessage, filterValue, eventCategoryFilters, ca
6025
6081
  if (trimmedFilterValue) {
6026
6082
  filterDescriptionParts.push(trimmedFilterValue);
6027
6083
  }
6028
- const timelineFilterDescription = getTimelineFilterDescription(timelineStartSeconds, timelineEndSeconds);
6029
6084
  if (timelineFilterDescription) {
6030
6085
  filterDescriptionParts.push(timelineFilterDescription);
6031
6086
  }
@@ -6036,7 +6091,18 @@ const getChatDebugViewDom = (errorMessage, filterValue, eventCategoryFilters, ca
6036
6091
  const useNoToolCallEventsMessage = eventCategoryFilters.length === 1 && eventCategoryFilters[0] === Tools && !trimmedFilterValue && !hasTimelineFilter;
6037
6092
  const emptyMessage = getEmptyMessage(events.length, hasFilterValue, useNoToolCallEventsMessage, noFilteredEventsMessage);
6038
6093
  const safeSelectedEventIndex = selectedEventIndex === null || selectedEventIndex < 0 || selectedEventIndex >= events.length ? null : selectedEventIndex;
6039
- const contentNodes = useDevtoolsLayout ? getDevtoolsDom(events, selectedEvent, safeSelectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds, visibleTableColumns, detailTabs, tableColumns, timelineInfo, timelineHoverPercent, focus) : getLegacyEventsDom(errorMessage, emptyMessage, events.flatMap(getEventNode));
6094
+ if (useDevtoolsLayout) {
6095
+ const devtoolsDom = getDevtoolsDom(events, selectedEvent, safeSelectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds, detailTabs, visibleTableColumns, tableColumns, timelineInfo, timelineHoverPercent, focus, previewTextCursorRowIndex, previewTextCursorColumnIndex, minLineY, maxLineY);
6096
+ const devtoolsContentNodes = devtoolsDom.slice(1);
6097
+ const topLevelNodes = [...getDebugViewTopDom(filterValue, useDevtoolsLayout, categoryFilters), ...devtoolsContentNodes];
6098
+ const rootChildCount = getTopLevelChildCount(topLevelNodes);
6099
+ return [{
6100
+ childCount: rootChildCount,
6101
+ className: mergeClassNames(ChatDebugView, ChatDebugViewDevtools),
6102
+ type: Div
6103
+ }, ...topLevelNodes];
6104
+ }
6105
+ const contentNodes = getLegacyEventsDom(errorMessage, emptyMessage, events.flatMap(getEventNode));
6040
6106
  const debugViewTopDom = getDebugViewTopDom(filterValue, useDevtoolsLayout, categoryFilters);
6041
6107
  const rootChildCount = 1 + getTopLevelChildCount(contentNodes);
6042
6108
  return [{
@@ -6058,8 +6124,8 @@ const renderItems = (oldState, newState) => {
6058
6124
  if (newState.initial) {
6059
6125
  return [SetDom2, newState.uid, []];
6060
6126
  }
6061
- const filteredEvents = filterEventsByTimelineRange(newState.timelineEvents, newState.timelineStartSeconds, newState.timelineEndSeconds);
6062
- 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, newState.timelineHoverPercent, newState.focus);
6127
+ const filteredEvents = getCurrentEvents$2(newState);
6128
+ 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, newState.previewTextCursorRowIndex, newState.previewTextCursorColumnIndex, newState.tableMinLineY, newState.tableMaxLineY);
6063
6129
  return [SetDom2, newState.uid, dom];
6064
6130
  };
6065
6131
 
@@ -6171,6 +6237,9 @@ const renderEventListeners = () => {
6171
6237
  }, {
6172
6238
  name: SelectDetailTab,
6173
6239
  params: ['selectDetailTab', TargetName]
6240
+ }, {
6241
+ name: HandleDetailTabsFocus,
6242
+ params: ['handleDetailTabsFocus', TargetName]
6174
6243
  }, {
6175
6244
  name: HandleTimelineRangePreset,
6176
6245
  params: ['handleTimelineRangePreset', 'event.target.dataset.value']
@@ -6200,6 +6269,20 @@ const renderEventListeners = () => {
6200
6269
  }, {
6201
6270
  name: HandleTableResizerPointerUp,
6202
6271
  params: ['handleTableResizerPointerUp']
6272
+ }, {
6273
+ name: HandleTableScrollBarPointerDown,
6274
+ params: ['handleTableScrollBarPointerDown', ClientY],
6275
+ trackPointerEvents: [HandleTableScrollBarPointerMove, HandleTableScrollBarPointerUp]
6276
+ }, {
6277
+ name: HandleTableScrollBarPointerMove,
6278
+ params: ['handleTableScrollBarPointerMove', ClientY]
6279
+ }, {
6280
+ name: HandleTableScrollBarPointerUp,
6281
+ params: ['handleTableScrollBarPointerUp']
6282
+ }, {
6283
+ name: HandleTableWheel,
6284
+ params: ['handleTableWheel', 'event.deltaY'],
6285
+ preventDefault: true
6203
6286
  }, {
6204
6287
  name: HandleTimelinePointerDown,
6205
6288
  params: ['handleTimelinePointerDown', TargetName, ClientX],
@@ -6216,6 +6299,9 @@ const renderEventListeners = () => {
6216
6299
  }, {
6217
6300
  name: HandleTimelineDoubleClick,
6218
6301
  params: ['handleTimelineDoubleClick']
6302
+ }, {
6303
+ name: HandlePreviewTextPointerDown,
6304
+ params: ['handlePreviewTextPointerDown', 'event.clientX - event.currentTarget.getBoundingClientRect().left', 'event.clientY - event.currentTarget.getBoundingClientRect().top']
6219
6305
  }];
6220
6306
  };
6221
6307
 
@@ -6223,18 +6309,14 @@ const rerender = state => {
6223
6309
  return structuredClone(state);
6224
6310
  };
6225
6311
 
6226
- const isSameVisibleTableColumns = (a, b) => {
6227
- return a.length === b.length && a.every((value, index) => value === b[index]);
6228
- };
6229
-
6230
6312
  const resetTableColumns = state => {
6231
- if (isSameVisibleTableColumns(state.visibleTableColumns, defaultVisibleTableColumns) && isSameTableColumnWidths(state.tableColumnWidths, defaultTableColumnWidths)) {
6313
+ if (getVisibleTableColumns(state.tableColumns).join(',') === defaultVisibleTableColumns.join(',') && isSameTableColumnWidths(state.tableColumnWidths, defaultTableColumnWidths)) {
6232
6314
  return state;
6233
6315
  }
6234
6316
  return {
6235
6317
  ...state,
6236
- tableColumnWidths: defaultTableColumnWidths,
6237
- visibleTableColumns: defaultVisibleTableColumns
6318
+ tableColumns: createTableColumns(),
6319
+ tableColumnWidths: defaultTableColumnWidths
6238
6320
  };
6239
6321
  };
6240
6322
 
@@ -6243,10 +6325,10 @@ const handleResize = (state, dimensions) => {
6243
6325
  ...state,
6244
6326
  ...dimensions
6245
6327
  };
6246
- return {
6328
+ return applyVirtualTableState({
6247
6329
  ...nextState,
6248
6330
  tableWidth: clampTableWidth(nextState.width, state.tableWidth)
6249
- };
6331
+ });
6250
6332
  };
6251
6333
 
6252
6334
  const isResizeDimensions = value => {
@@ -6266,10 +6348,10 @@ const saveState = state => {
6266
6348
  filterValue,
6267
6349
  selectedEventId,
6268
6350
  sessionId,
6351
+ tableColumns,
6269
6352
  tableColumnWidths,
6270
6353
  timelineEndSeconds,
6271
- timelineStartSeconds,
6272
- visibleTableColumns
6354
+ timelineStartSeconds
6273
6355
  } = state;
6274
6356
  return {
6275
6357
  eventCategoryFilter: getSelectedEventCategoryFilter(categoryFilters),
@@ -6281,7 +6363,7 @@ const saveState = state => {
6281
6363
  tableColumnWidths,
6282
6364
  timelineEndSeconds,
6283
6365
  timelineStartSeconds,
6284
- visibleTableColumns
6366
+ visibleTableColumns: getVisibleTableColumns(tableColumns)
6285
6367
  };
6286
6368
  };
6287
6369
 
@@ -6295,19 +6377,22 @@ const selectCurrent = async state => {
6295
6377
  };
6296
6378
 
6297
6379
  const setEvents = (state, events) => {
6298
- return getStateWithTimelineInfo({
6380
+ return applyVirtualTableState(getStateWithTimelineInfo({
6299
6381
  ...state,
6300
6382
  errorMessage: '',
6301
6383
  events,
6302
6384
  initial: false,
6385
+ previewTextCursorColumnIndex: null,
6386
+ previewTextCursorRowIndex: null,
6303
6387
  selectedEvent: null,
6304
6388
  selectedEventId: null,
6305
6389
  selectedEventIndex: null
6306
- });
6390
+ }));
6307
6391
  };
6308
6392
 
6309
6393
  const setSessionIdDependencies = {
6310
- listChatViewEvents: listChatViewEvents
6394
+ listChatViewEvents: listChatViewEvents,
6395
+ registerUpdateListener: registerUpdateListener
6311
6396
  };
6312
6397
  const setSessionId = async (state, sessionId) => {
6313
6398
  const {
@@ -6317,12 +6402,15 @@ const setSessionId = async (state, sessionId) => {
6317
6402
  sessionIdIndexName
6318
6403
  } = state;
6319
6404
  const result = await setSessionIdDependencies.listChatViewEvents(sessionId, databaseName, dataBaseVersion, eventStoreName, sessionIdIndexName);
6405
+ await setSessionIdDependencies.registerUpdateListener(sessionId, rpcId, state.uid);
6320
6406
  if (result.type === 'error') {
6321
6407
  return {
6322
6408
  ...state,
6323
6409
  errorMessage: getFailedToLoadMessage(sessionId, result.error),
6324
6410
  events: [],
6325
6411
  initial: false,
6412
+ previewTextCursorColumnIndex: null,
6413
+ previewTextCursorRowIndex: null,
6326
6414
  selectedEvent: null,
6327
6415
  selectedEventId: null,
6328
6416
  selectedEventIndex: null,
@@ -6337,6 +6425,8 @@ const setSessionId = async (state, sessionId) => {
6337
6425
  errorMessage: '',
6338
6426
  events,
6339
6427
  initial: false,
6428
+ previewTextCursorColumnIndex: null,
6429
+ previewTextCursorRowIndex: null,
6340
6430
  selectedEvent: null,
6341
6431
  selectedEventId: null,
6342
6432
  selectedEventIndex: null,
@@ -6348,16 +6438,24 @@ const toggleTableColumnVisibility = (state, column) => {
6348
6438
  if (!isTableColumn(column)) {
6349
6439
  return state;
6350
6440
  }
6351
- const nextVisibleColumns = state.visibleTableColumns.includes(column) ? state.visibleTableColumns.filter(visibleColumn => visibleColumn !== column) : [...state.visibleTableColumns, column];
6352
6441
  return {
6353
6442
  ...state,
6354
- visibleTableColumns: getOrderedVisibleTableColumns(nextVisibleColumns)
6443
+ tableColumns: state.tableColumns.map(tableColumn => {
6444
+ if (tableColumn.name !== column) {
6445
+ return tableColumn;
6446
+ }
6447
+ return {
6448
+ ...tableColumn,
6449
+ isVisible: !tableColumn.isVisible
6450
+ };
6451
+ })
6355
6452
  };
6356
6453
  };
6357
6454
 
6358
6455
  const commandMap = {
6359
6456
  'ChatDebug.appendStoredEventForTest': wrapCommand(appendStoredEventForTest),
6360
6457
  'ChatDebug.appendStoredImageAttachmentForTest': wrapCommand(appendStoredImageAttachmentForTest),
6458
+ 'ChatDebug.appendStoredRemovedImageAttachmentForTest': wrapCommand(appendStoredRemovedImageAttachmentForTest),
6361
6459
  'ChatDebug.create': create,
6362
6460
  'ChatDebug.diff2': diff2,
6363
6461
  'ChatDebug.focusFirst': wrapCommand(focusFirst),
@@ -6371,12 +6469,14 @@ const commandMap = {
6371
6469
  'ChatDebug.handleCloseDetails': wrapCommand(handleCloseDetails),
6372
6470
  'ChatDebug.handleDetailsContextMenu': wrapCommand(handleDetailsContextMenu),
6373
6471
  'ChatDebug.handleDetailsTopContextMenu': wrapCommand(handleDetailsTopContextMenu),
6472
+ 'ChatDebug.handleDetailTabsFocus': wrapCommand(handleDetailTabsFocus),
6374
6473
  'ChatDebug.handleEscape': wrapCommand(handleEscape),
6375
6474
  'ChatDebug.handleEventCategoryFilter': wrapCommand(handleEventCategoryFilter),
6376
6475
  'ChatDebug.handleEventRowClick': wrapCommand(handleEventRowClick),
6377
6476
  'ChatDebug.handleEventRowClickAt': wrapCommand(handleEventRowClickAt),
6378
6477
  'ChatDebug.handleHeaderContextMenu': wrapCommand(handleHeaderContextMenu),
6379
6478
  'ChatDebug.handleInput': wrapCommand(handleInput),
6479
+ 'ChatDebug.handlePreviewTextPointerDown': wrapCommand(handlePreviewTextPointerDown),
6380
6480
  'ChatDebug.handleSashPointerDown': wrapCommand(handleSashPointerDown),
6381
6481
  'ChatDebug.handleSashPointerMove': wrapCommand(handleSashPointerMove),
6382
6482
  'ChatDebug.handleSashPointerUp': wrapCommand(handleSashPointerUp),
@@ -6390,6 +6490,10 @@ const commandMap = {
6390
6490
  'ChatDebug.handleTableResizerPointerMove': wrapCommand(handleTableResizerPointerMove),
6391
6491
  'ChatDebug.handleTableResizerPointerUp': wrapCommand(handleTableResizerPointerUp),
6392
6492
  'ChatDebug.handleTableRowCopy': wrapCommand(handleTableRowCopy),
6493
+ 'ChatDebug.handleTableScrollBarPointerDown': wrapCommand(handleTableScrollBarPointerDown),
6494
+ 'ChatDebug.handleTableScrollBarPointerMove': wrapCommand(handleTableScrollBarPointerMove),
6495
+ 'ChatDebug.handleTableScrollBarPointerUp': wrapCommand(handleTableScrollBarPointerUp),
6496
+ 'ChatDebug.handleTableWheel': wrapCommand(handleTableWheel),
6393
6497
  'ChatDebug.handleTimelineContextMenu': wrapCommand(handleTimelineContextMenu),
6394
6498
  'ChatDebug.handleTimelineDoubleClick': wrapCommand(handleTimelineDoubleClick),
6395
6499
  'ChatDebug.handleTimelineEndSeconds': wrapCommand(handleTimelineEndSeconds),
@@ -6422,7 +6526,9 @@ const sendMessagePortToChatStorageWorker = async port => {
6422
6526
  };
6423
6527
  const initializeChatStorageWorker = async () => {
6424
6528
  const rpc = await create$4({
6425
- commandMap: {},
6529
+ commandMap: {
6530
+ [rpcId]: handleStorageWorkerUpdate
6531
+ },
6426
6532
  send: sendMessagePortToChatStorageWorker
6427
6533
  });
6428
6534
  set$2(rpc);