@lvce-editor/chat-debug-view 9.0.0 → 10.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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('.');
@@ -1319,6 +1321,54 @@ const appendStoredEventForTest = async (state, event) => {
1319
1321
  return state;
1320
1322
  };
1321
1323
 
1324
+ const decodeBase64$1 = value => {
1325
+ const decoded = atob(value);
1326
+ const bytes = new Uint8Array(decoded.length);
1327
+ for (let i = 0; i < decoded.length; i++) {
1328
+ bytes[i] = decoded.codePointAt(i) || 0;
1329
+ }
1330
+ return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
1331
+ };
1332
+ const createCanvasBlob$1 = async mimeType => {
1333
+ const canvas = new OffscreenCanvas(2, 2);
1334
+ const context = canvas.getContext('2d');
1335
+ if (!context) {
1336
+ throw new Error('2d canvas context is not available');
1337
+ }
1338
+ context.fillStyle = '#0b6';
1339
+ context.fillRect(0, 0, 2, 2);
1340
+ return canvas.convertToBlob({
1341
+ type: mimeType
1342
+ });
1343
+ };
1344
+ const createBlob$1 = async (mimeType, contentKind, content) => {
1345
+ if (contentKind === 'canvas') {
1346
+ return createCanvasBlob$1(mimeType);
1347
+ }
1348
+ if (contentKind === 'base64') {
1349
+ return new Blob([decodeBase64$1(content)], {
1350
+ type: mimeType
1351
+ });
1352
+ }
1353
+ return new Blob([content], {
1354
+ type: mimeType
1355
+ });
1356
+ };
1357
+ const appendStoredImageAttachmentForTest = async (state, sessionId, eventId, mimeType, name, contentKind, content, timestamp) => {
1358
+ const blob = await createBlob$1(mimeType, contentKind, content);
1359
+ await appendEvent({
1360
+ attachmentId: `attachment-${eventId}`,
1361
+ blob,
1362
+ eventId,
1363
+ mimeType,
1364
+ name,
1365
+ sessionId,
1366
+ timestamp,
1367
+ type: 'chat-attachment-added'
1368
+ });
1369
+ return state;
1370
+ };
1371
+
1322
1372
  const decodeBase64 = value => {
1323
1373
  const decoded = atob(value);
1324
1374
  const bytes = new Uint8Array(decoded.length);
@@ -1352,7 +1402,7 @@ const createBlob = async (mimeType, contentKind, content) => {
1352
1402
  type: mimeType
1353
1403
  });
1354
1404
  };
1355
- const appendStoredImageAttachmentForTest = async (state, sessionId, eventId, mimeType, name, contentKind, content, timestamp) => {
1405
+ const appendStoredRemovedImageAttachmentForTest = async (state, sessionId, eventId, mimeType, name, contentKind, content, timestamp) => {
1356
1406
  const blob = await createBlob(mimeType, contentKind, content);
1357
1407
  await appendEvent({
1358
1408
  attachmentId: `attachment-${eventId}`,
@@ -1362,7 +1412,7 @@ const appendStoredImageAttachmentForTest = async (state, sessionId, eventId, mim
1362
1412
  name,
1363
1413
  sessionId,
1364
1414
  timestamp,
1365
- type: 'chat-attachment-added'
1415
+ type: 'chat-attachment-removed'
1366
1416
  });
1367
1417
  return state;
1368
1418
  };
@@ -1782,12 +1832,15 @@ const Status$1 = 'status';
1782
1832
  const tableColumnNames = [Type, Status$1, Duration];
1783
1833
  const createTableColumns = () => {
1784
1834
  return [{
1835
+ isVisible: true,
1785
1836
  label: type(),
1786
1837
  name: Type
1787
1838
  }, {
1839
+ isVisible: true,
1788
1840
  label: status(),
1789
1841
  name: Status$1
1790
1842
  }, {
1843
+ isVisible: true,
1791
1844
  label: duration(),
1792
1845
  name: Duration
1793
1846
  }];
@@ -1796,12 +1849,22 @@ const defaultVisibleTableColumns = tableColumnNames;
1796
1849
  const isTableColumn = value => {
1797
1850
  return tableColumnNames.includes(value);
1798
1851
  };
1852
+ const getVisibleTableColumns = tableColumns => {
1853
+ return tableColumns.filter(column => column.isVisible).map(column => column.name);
1854
+ };
1855
+ const getTableColumnsWithVisibility = (tableColumns, visibleTableColumns) => {
1856
+ const visibleColumns = new Set(visibleTableColumns.filter(isTableColumn));
1857
+ return tableColumns.map(column => ({
1858
+ ...column,
1859
+ isVisible: visibleColumns.has(column.name)
1860
+ }));
1861
+ };
1799
1862
  const getOrderedVisibleTableColumns = (values, tableColumns = createTableColumns()) => {
1800
1863
  const visibleColumns = new Set(values.filter(isTableColumn));
1801
1864
  return tableColumns.map(column => column.name).filter(column => visibleColumns.has(column));
1802
1865
  };
1803
- const isVisibleTableColumn = (visibleTableColumns, column) => {
1804
- return visibleTableColumns.includes(column);
1866
+ const isVisibleTableColumn = (tableColumns, column) => {
1867
+ return tableColumns.some(tableColumn => tableColumn.name === column && tableColumn.isVisible);
1805
1868
  };
1806
1869
  const getTableColumnLabel = (tableColumns, name) => {
1807
1870
  const match = tableColumns.find(column => column.name === name);
@@ -1969,12 +2032,12 @@ const restoreTimelineEndSeconds = (savedState, currentTimelineEndSeconds) => {
1969
2032
  const restoreTimelineStartSeconds = (savedState, currentTimelineStartSeconds) => {
1970
2033
  return typeof savedState.timelineStartSeconds === 'string' ? savedState.timelineStartSeconds : currentTimelineStartSeconds;
1971
2034
  };
1972
- const restoreVisibleTableColumns = (savedState, currentVisibleTableColumns) => {
2035
+ const restoreVisibleTableColumns = (savedState, currentTableColumns) => {
1973
2036
  if (!Array.isArray(savedState.visibleTableColumns)) {
1974
- return currentVisibleTableColumns;
2037
+ return currentTableColumns;
1975
2038
  }
1976
2039
  const visibleTableColumns = savedState.visibleTableColumns.filter(value => typeof value === 'string');
1977
- return getOrderedVisibleTableColumns(visibleTableColumns);
2040
+ return getTableColumnsWithVisibility(currentTableColumns, visibleTableColumns);
1978
2041
  };
1979
2042
  const restoreTableColumnWidths = (savedState, currentTableColumnWidths) => {
1980
2043
  return isTableColumnWidths(savedState.tableColumnWidths) ? savedState.tableColumnWidths : currentTableColumnWidths;
@@ -1989,10 +2052,10 @@ const restoreSavedState = (state, savedState) => {
1989
2052
  detailTabs: restoreDetailTabs(savedState, state.detailTabs),
1990
2053
  filterValue: restoreFilterValue(savedState, state.filterValue),
1991
2054
  selectedEventId: restoreSelectedEventId(savedState, state.selectedEventId),
2055
+ tableColumns: restoreVisibleTableColumns(savedState, state.tableColumns),
1992
2056
  tableColumnWidths: restoreTableColumnWidths(savedState, state.tableColumnWidths),
1993
2057
  timelineEndSeconds: restoreTimelineEndSeconds(savedState, state.timelineEndSeconds),
1994
- timelineStartSeconds: restoreTimelineStartSeconds(savedState, state.timelineStartSeconds),
1995
- visibleTableColumns: restoreVisibleTableColumns(savedState, state.visibleTableColumns)
2058
+ timelineStartSeconds: restoreTimelineStartSeconds(savedState, state.timelineStartSeconds)
1996
2059
  };
1997
2060
  };
1998
2061
 
@@ -2165,12 +2228,13 @@ const createDefaultState = () => {
2165
2228
  showResponsePartEvents: false,
2166
2229
  sortColumn: '',
2167
2230
  sortDescending: false,
2168
- tableColumns: [],
2231
+ tableColumns: createTableColumns(),
2169
2232
  tableColumnWidths: defaultTableColumnWidths,
2170
2233
  tableResizerDownId: 0,
2171
2234
  tableWidth: defaultTableWidth,
2172
2235
  timelineEndSeconds: '',
2173
2236
  timelineEvents: [],
2237
+ timelineFilterDescription: '',
2174
2238
  timelineHoverPercent: null,
2175
2239
  timelineHoverSeconds: '',
2176
2240
  timelineInfo: emptyTimelineInfo,
@@ -2181,7 +2245,6 @@ const createDefaultState = () => {
2181
2245
  uid: 0,
2182
2246
  uri: '',
2183
2247
  useDevtoolsLayout: true,
2184
- visibleTableColumns: defaultVisibleTableColumns,
2185
2248
  width: 0,
2186
2249
  x: 0,
2187
2250
  y: 0
@@ -2219,7 +2282,7 @@ const RenderFocusContext = 4;
2219
2282
  const RenderFocus = 5;
2220
2283
 
2221
2284
  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) {
2285
+ if (oldState.categoryFilters !== newState.categoryFilters || oldState.detailTabs !== newState.detailTabs || oldState.errorMessage !== newState.errorMessage || oldState.events !== newState.events || oldState.filterValue !== newState.filterValue || oldState.sessionId !== newState.sessionId || oldState.showEventStreamFinishedEvents !== newState.showEventStreamFinishedEvents || oldState.showInputEvents !== newState.showInputEvents || oldState.showResponsePartEvents !== newState.showResponsePartEvents || oldState.sortColumn !== newState.sortColumn || oldState.sortDescending !== newState.sortDescending || oldState.tableColumnWidths !== newState.tableColumnWidths || oldState.tableWidth !== newState.tableWidth || oldState.timelineEndSeconds !== newState.timelineEndSeconds || oldState.timelineHoverPercent !== newState.timelineHoverPercent || oldState.timelineHoverSeconds !== newState.timelineHoverSeconds || oldState.timelineSelectionActive !== newState.timelineSelectionActive || oldState.timelineSelectionAnchorSeconds !== newState.timelineSelectionAnchorSeconds || oldState.timelineSelectionFocusSeconds !== newState.timelineSelectionFocusSeconds || oldState.timelineStartSeconds !== newState.timelineStartSeconds || oldState.useDevtoolsLayout !== newState.useDevtoolsLayout || oldState.tableColumns !== newState.tableColumns || oldState.selectedEvent !== newState.selectedEvent || oldState.selectedEventIndex !== newState.selectedEventIndex || oldState.focus !== newState.focus || oldState.width !== newState.width || oldState.uid !== newState.uid) {
2223
2286
  return [RenderIncremental, RenderCss];
2224
2287
  }
2225
2288
  return [];
@@ -2568,6 +2631,9 @@ const loadSelectedEvent = async (_databaseName, _dataBaseVersion, _eventStoreNam
2568
2631
  return loadSelectedEvent$1(sessionId, eventId, type);
2569
2632
  };
2570
2633
 
2634
+ const svgWidthRegex = /\bwidth=["']([\d.]+)(?:px)?["']/i;
2635
+ const svgHeightRegex = /\bheight=["']([\d.]+)(?:px)?["']/i;
2636
+ const svgViewBoxRegex = /\bviewBox=["'][^"']*?([\d.]+)\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)["']/i;
2571
2637
  const getBlob = event => {
2572
2638
  const {
2573
2639
  blob
@@ -2586,8 +2652,27 @@ const getAltText = event => {
2586
2652
  const isImageMimeType = mimeType => {
2587
2653
  return typeof mimeType === 'string' && mimeType.startsWith('image/');
2588
2654
  };
2589
- const shouldValidateImage = mimeType => {
2590
- return mimeType !== 'image/svg+xml';
2655
+ const formatImageSize = size => {
2656
+ if (size < 1024) {
2657
+ return `${size} B`;
2658
+ }
2659
+ return `${(size / 1024).toFixed(1)} kB`;
2660
+ };
2661
+ const formatImageStats = (width, height, size) => {
2662
+ return `${width} × ${height} px · ${formatImageSize(size)}`;
2663
+ };
2664
+ const getSvgImageStats = async blob => {
2665
+ const text = await blob.text();
2666
+ const widthMatch = text.match(svgWidthRegex);
2667
+ const heightMatch = text.match(svgHeightRegex);
2668
+ if (widthMatch && heightMatch) {
2669
+ return formatImageStats(Number(widthMatch[1]), Number(heightMatch[1]), blob.size);
2670
+ }
2671
+ const viewBoxMatch = text.match(svgViewBoxRegex);
2672
+ if (viewBoxMatch) {
2673
+ return formatImageStats(Number(viewBoxMatch[3]), Number(viewBoxMatch[4]), blob.size);
2674
+ }
2675
+ return undefined;
2591
2676
  };
2592
2677
  const readBlobAsPreviewUrl = blob => {
2593
2678
  if (typeof FileReaderSync === 'function') {
@@ -2599,15 +2684,29 @@ const readBlobAsPreviewUrl = blob => {
2599
2684
  }
2600
2685
  throw new Error('image preview reader is not available');
2601
2686
  };
2602
- const validateImage = async blob => {
2687
+ const getRasterImageStats = async blob => {
2603
2688
  if (typeof createImageBitmap !== 'function') {
2604
- return;
2689
+ throw new TypeError('image bitmap decoder is not available');
2605
2690
  }
2606
2691
  const bitmap = await createImageBitmap(blob);
2607
- bitmap.close?.();
2692
+ try {
2693
+ return formatImageStats(bitmap.width, bitmap.height, blob.size);
2694
+ } finally {
2695
+ bitmap.close?.();
2696
+ }
2697
+ };
2698
+ const getImageStats = async (blob, mimeType) => {
2699
+ if (mimeType === 'image/svg+xml') {
2700
+ const svgStats = await getSvgImageStats(blob);
2701
+ if (svgStats === undefined) {
2702
+ throw new TypeError('image stats are not available');
2703
+ }
2704
+ return svgStats;
2705
+ }
2706
+ return getRasterImageStats(blob);
2608
2707
  };
2609
2708
  const getAttachmentImagePreview = async event => {
2610
- if (event.type !== 'chat-attachment-added') {
2709
+ if (event.type !== 'chat-attachment-added' && event.type !== 'chat-attachment-removed') {
2611
2710
  return undefined;
2612
2711
  }
2613
2712
  const blob = getBlob(event);
@@ -2616,13 +2715,12 @@ const getAttachmentImagePreview = async event => {
2616
2715
  return undefined;
2617
2716
  }
2618
2717
  try {
2619
- if (shouldValidateImage(mimeType)) {
2620
- await validateImage(blob);
2621
- }
2718
+ const stats = await getImageStats(blob, mimeType);
2622
2719
  return {
2623
2720
  alt: getAltText(event),
2624
2721
  previewType: 'image',
2625
- src: readBlobAsPreviewUrl(blob)
2722
+ src: readBlobAsPreviewUrl(blob),
2723
+ stats
2626
2724
  };
2627
2725
  } catch {
2628
2726
  return imageCouldNotBeLoaded();
@@ -2737,27 +2835,27 @@ const getMenuEntriesTableBody = props => {
2737
2835
  }];
2738
2836
  };
2739
2837
 
2740
- const getColumnVisibilityFlags = (state, column) => {
2741
- return isVisibleTableColumn(state.visibleTableColumns, column) ? Checked : Unchecked;
2838
+ const getColumnVisibilityFlags = (tableColumns, column) => {
2839
+ return isVisibleTableColumn(tableColumns, column) ? Checked : Unchecked;
2742
2840
  };
2743
2841
 
2744
2842
  const getMenuEntriesTableHeader = state => {
2745
2843
  return [{
2746
2844
  args: [Type],
2747
2845
  command: 'ChatDebug.toggleTableColumnVisibility',
2748
- flags: getColumnVisibilityFlags(state, Type),
2846
+ flags: getColumnVisibilityFlags(state.tableColumns, Type),
2749
2847
  id: 'type',
2750
2848
  label: type()
2751
2849
  }, {
2752
2850
  args: [Status$1],
2753
2851
  command: 'ChatDebug.toggleTableColumnVisibility',
2754
- flags: getColumnVisibilityFlags(state, Status$1),
2852
+ flags: getColumnVisibilityFlags(state.tableColumns, Status$1),
2755
2853
  id: 'status',
2756
2854
  label: status()
2757
2855
  }, {
2758
2856
  args: [Duration],
2759
2857
  command: 'ChatDebug.toggleTableColumnVisibility',
2760
- flags: getColumnVisibilityFlags(state, Duration),
2858
+ flags: getColumnVisibilityFlags(state.tableColumns, Duration),
2761
2859
  id: 'duration',
2762
2860
  label: duration()
2763
2861
  }, {
@@ -2949,13 +3047,30 @@ const getTimelineEvents = state => {
2949
3047
  return getFilteredEvents(events, filterValue, eventCategoryFilters, showInputEvents, showResponsePartEvents, showEventStreamFinishedEvents);
2950
3048
  };
2951
3049
 
3050
+ const getTimelineFilterDescription = (timelineStartSeconds, timelineEndSeconds) => {
3051
+ const trimmedStart = timelineStartSeconds.trim();
3052
+ const trimmedEnd = timelineEndSeconds.trim();
3053
+ if (trimmedStart && trimmedEnd) {
3054
+ return secondsRange(trimmedStart, trimmedEnd);
3055
+ }
3056
+ if (trimmedStart) {
3057
+ return fromSeconds(trimmedStart);
3058
+ }
3059
+ if (trimmedEnd) {
3060
+ return toSeconds(trimmedEnd);
3061
+ }
3062
+ return '';
3063
+ };
3064
+
2952
3065
  const getStateWithTimelineInfo = state => {
2953
3066
  const timelineEvents = getTimelineEvents(state);
2954
3067
  const effectiveRange = getEffectiveTimelineRange(state.timelineStartSeconds, state.timelineEndSeconds, state.timelineSelectionActive, state.timelineSelectionAnchorSeconds, state.timelineSelectionFocusSeconds);
2955
3068
  const timelineInfo = getTimelineInfo(timelineEvents, effectiveRange.startSeconds, effectiveRange.endSeconds);
3069
+ const timelineFilterDescription = getTimelineFilterDescription(state.timelineStartSeconds, state.timelineEndSeconds);
2956
3070
  return {
2957
3071
  ...state,
2958
3072
  timelineEvents,
3073
+ timelineFilterDescription,
2959
3074
  timelineInfo
2960
3075
  };
2961
3076
  };
@@ -3140,6 +3255,9 @@ const selectDetailTab = (state, value) => {
3140
3255
  detailTabs
3141
3256
  };
3142
3257
  };
3258
+ const handleDetailTabsFocus = (state, value) => {
3259
+ return selectDetailTab(state, value);
3260
+ };
3143
3261
 
3144
3262
  const handleEscape = state => {
3145
3263
  return state;
@@ -3492,7 +3610,7 @@ const handleTableResizerPointerMove = (state, clientX) => {
3492
3610
  }
3493
3611
  return {
3494
3612
  ...state,
3495
- tableColumnWidths: getResizedTableColumnWidths(state.width, state.tableWidth, state.visibleTableColumns, state.tableColumnWidths, state.x, clientX, state.tableResizerDownId)
3613
+ tableColumnWidths: getResizedTableColumnWidths(state.width, state.tableWidth, getVisibleTableColumns(state.tableColumns), state.tableColumnWidths, state.x, clientX, state.tableResizerDownId)
3496
3614
  };
3497
3615
  };
3498
3616
 
@@ -3749,6 +3867,7 @@ const handleShowResponsePartEvents = (state, checked) => {
3749
3867
  };
3750
3868
 
3751
3869
  const loadContent = async (state, savedState) => {
3870
+ await getPreference('chatDebug.autoRefresh');
3752
3871
  const nextState = await loadEventsFromUri(restoreSavedState(state, savedState));
3753
3872
  return {
3754
3873
  ...nextState,
@@ -3758,12 +3877,14 @@ const loadContent = async (state, savedState) => {
3758
3877
  };
3759
3878
  };
3760
3879
 
3880
+ // cspell:ignore liga calt
3881
+
3761
3882
  const getCss = state => {
3762
3883
  const hasSelectedEvent = !!state.selectedEvent;
3763
3884
  const tableWidth = hasSelectedEvent ? clampTableWidth(state.width, state.tableWidth) : getMainWidth(state.width);
3764
3885
  const detailsWidth = hasSelectedEvent ? getDetailsWidth(state.width, state.tableWidth) : 0;
3765
3886
  const topSize = state.width >= state.largeBreakpoint ? 30 : state.width >= state.mediumBreakpoint ? 60 : 60;
3766
- const tableColumnLayout = getTableColumnLayout(tableWidth, state.visibleTableColumns, state.tableColumnWidths);
3887
+ const tableColumnLayout = getTableColumnLayout(tableWidth, getVisibleTableColumns(state.tableColumns), state.tableColumnWidths);
3767
3888
  const [tableColZeroWidth = 0, tableColOneWidth = 0, tableColTwoWidth = 0] = tableColumnLayout.visibleColumnWidths;
3768
3889
  const resizerOneLeft = tableColumnLayout.resizerLefts[0] ?? 0;
3769
3890
  const resizerTwoLeft = tableColumnLayout.resizerLefts[1] ?? 0;
@@ -3790,546 +3911,8 @@ const getCss = state => {
3790
3911
  --ChatDebugViewTopSize: ${topSize}px;
3791
3912
  --ChatDebugViewTypeColumnWidth: ${state.tableColumnWidths.type}px;
3792
3913
  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
- }
3851
-
3852
- .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;
3893
- 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
- 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
- }
4151
-
4152
- .ChatDebugViewTimelineBadges {
4153
- position: absolute;
4154
- inset: 4px 8px auto 8px;
4155
- height: 12px;
4156
- pointer-events: none;
4157
- z-index: 2;
4158
- }
4159
-
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);
4168
- 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 {
4179
- position: absolute;
4180
- inset: 20px 8px 8px;
4181
- display: flex;
4182
- align-items: flex-end;
4183
- gap: 2px;
4184
- }
4185
-
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;
4207
- 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: '';
4285
- 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);
4295
- }
4296
-
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
3914
  }
4329
3915
 
4330
- .TokenString {
4331
- white-space: nowrap;
4332
- }
4333
3916
  `;
4334
3917
  };
4335
3918
 
@@ -4643,16 +4226,24 @@ const ChatDebugViewDevtools = 'ChatDebugView--devtools';
4643
4226
  const ChatDebugViewDetails = 'ChatDebugViewDetails';
4644
4227
  const ChatDebugViewDetailsBottom = 'ChatDebugViewDetailsBottom';
4645
4228
  const ChatDebugViewDetailsClose = 'ChatDebugViewDetailsClose';
4646
- const ChatDebugViewDetailsTab = 'ChatDebugViewDetailsTab';
4647
- const ChatDebugViewDetailsTabSelected = 'ChatDebugViewDetailsTabSelected';
4229
+ const EditorContainer = 'EditorContainer';
4230
+ const PanelTab = 'PanelTab';
4231
+ const PanelTabSelected = 'PanelTabSelected';
4648
4232
  const ChatDebugViewDetailsTabs = 'ChatDebugViewDetailsTabs';
4649
4233
  const ChatDebugViewDetailsTop = 'ChatDebugViewDetailsTop';
4650
4234
  const ChatDebugViewDevtoolsSplit = 'ChatDebugViewDevtoolsSplit';
4651
4235
  const ChatDebugViewEmpty = 'ChatDebugViewEmpty';
4652
4236
  const ChatDebugViewError = 'ChatDebugViewError';
4653
- const ChatDebugViewEventRawText = 'ChatDebugViewEventRawText';
4654
- const ChatDebugViewEventLineContent = 'ChatDebugViewEventLineContent';
4237
+ const EditorContent = 'EditorContent';
4238
+ const EditorInput = 'EditorInput';
4239
+ const EditorLayers = 'EditorLayers';
4240
+ const EditorRow = 'EditorRow';
4241
+ const EditorRows = 'EditorRows';
4242
+ const EditorSelection = 'EditorSelection';
4243
+ const EditorSelections = 'Selections';
4244
+ const EditorViewlet = 'Viewlet Editor';
4655
4245
  const ChatDebugViewEventLineNumber = 'ChatDebugViewEventLineNumber';
4246
+ const Gutter = 'Gutter';
4656
4247
  const TableRowSelected = 'TableRowSelected';
4657
4248
  const ChatDebugViewEvents = 'ChatDebugViewEvents';
4658
4249
  const ChatDebugViewEventsFullWidth = 'ChatDebugViewEventsFullWidth';
@@ -4660,6 +4251,7 @@ const ChatDebugViewFilterInput = 'ChatDebugViewFilterInput';
4660
4251
  const ChatDebugViewFilterInputDevtools = 'ChatDebugViewFilterInput--devtools';
4661
4252
  const ChatDebugViewHeaderCell = 'TableCell';
4662
4253
  const ChatDebugViewImagePreview = 'ChatDebugViewImagePreview';
4254
+ const ChatDebugViewImagePreviewImageWrapper = 'ChatDebugViewImagePreviewImageWrapper';
4663
4255
  const ChatDebugViewImagePreviewImage = 'ChatDebugViewImagePreviewImage';
4664
4256
  const ChatDebugViewImagePreviewLabel = 'ChatDebugViewImagePreviewLabel';
4665
4257
  const ChatDebugViewRefreshButton = 'ChatDebugViewRefreshButton';
@@ -4672,6 +4264,7 @@ const Table = 'Table';
4672
4264
  const TableBody = 'TableBody';
4673
4265
  const TableSummary = 'TableSummary';
4674
4266
  const TableWrapper = 'TableWrapper';
4267
+ const TableWrapperWrapper = 'TableWrapperWrapper';
4675
4268
  const FocusOutline = 'FocusOutline';
4676
4269
  const Resizer = 'Resizer';
4677
4270
  const ResizerInner = 'ResizerInner';
@@ -4704,19 +4297,26 @@ const ChatDebugViewTimelineSelectionMarkerEnd = 'ChatDebugViewTimelineSelectionM
4704
4297
  const ChatDebugViewTimelineSelectionMarkerStart = 'ChatDebugViewTimelineSelectionMarkerStart';
4705
4298
  const ChatDebugViewTimelineSelectionOverlay = 'ChatDebugViewTimelineSelectionOverlay';
4706
4299
  const ChatDebugViewTimelineSelectionRange = 'ChatDebugViewTimelineSelectionRange';
4707
- const ChatDebugViewTimelineSummary = 'ChatDebugViewTimelineSummary';
4708
4300
  const ChatDebugViewTimelineTop = 'ChatDebugViewTimelineTop';
4709
4301
  const ChatDebugViewTiming = 'ChatDebugViewTiming';
4710
4302
  const ChatDebugViewTimingLabel = 'ChatDebugViewTimingLabel';
4303
+ const ChatDebugViewTimingPreview = 'ChatDebugViewTimingPreview';
4304
+ const ChatDebugViewTimingPreviewMarker = 'ChatDebugViewTimingPreviewMarker';
4305
+ const ChatDebugViewTimingPreviewMarkerEnd = 'ChatDebugViewTimingPreviewMarkerEnd';
4306
+ const ChatDebugViewTimingPreviewMarkerStart = 'ChatDebugViewTimingPreviewMarkerStart';
4307
+ const ChatDebugViewTimingPreviewRail = 'ChatDebugViewTimingPreviewRail';
4308
+ const ChatDebugViewTimingPreviewSegment = 'ChatDebugViewTimingPreviewSegment';
4309
+ const ChatDebugViewTimingPreviewTrack = 'ChatDebugViewTimingPreviewTrack';
4310
+ const ChatDebugViewTimingPreviewTrackOverlay = 'ChatDebugViewTimingPreviewTrackOverlay';
4711
4311
  const ChatDebugViewTimingRow = 'ChatDebugViewTimingRow';
4712
4312
  const ChatDebugViewTimingValue = 'ChatDebugViewTimingValue';
4713
4313
  const ChatDebugViewTop = 'ChatDebugViewTop';
4714
4314
  const ChatDebugViewTopDevtools = 'ChatDebugViewTop--devtools';
4715
4315
  const TableCell = 'TableCell';
4716
4316
  const ChatDebugViewColumnFixed = 'ChatDebugViewColumnFixed';
4317
+ const ChatDebugViewCellDuration = 'ChatDebugViewCellDuration';
4717
4318
  const ChatDebugViewCellStatusError = 'ChatDebugViewCellStatusError';
4718
4319
  const InputBox = 'InputBox';
4719
- const Row = 'row';
4720
4320
  const TokenBoolean = 'Token TokenBoolean';
4721
4321
  const TokenKey = 'Token TokenKey';
4722
4322
  const TokenNumeric = 'Token TokenNumeric';
@@ -4763,6 +4363,21 @@ const HandleTimelineContextMenu = 26;
4763
4363
  const HandleTimelinePointerLeave = 27;
4764
4364
  const HandleEventRowClick = 28;
4765
4365
  const HandleTableFocus = 29;
4366
+ const HandleDetailTabsFocus = 30;
4367
+
4368
+ const getFilterInputDom = (filterValue, useDevtoolsLayout) => {
4369
+ return {
4370
+ autocomplete: 'off',
4371
+ childCount: 0,
4372
+ className: useDevtoolsLayout ? mergeClassNames(InputBox, ChatDebugViewFilterInput, ChatDebugViewFilterInputDevtools) : mergeClassNames(InputBox, ChatDebugViewFilterInput),
4373
+ inputType: 'search',
4374
+ name: Filter,
4375
+ onInput: HandleFilterInput,
4376
+ placeholder: filterEvents(),
4377
+ type: Input,
4378
+ value: filterValue
4379
+ };
4380
+ };
4766
4381
 
4767
4382
  const getQuickFilterDom = categoryFilter => {
4768
4383
  const {
@@ -4806,19 +4421,6 @@ const getRefreshButtonDom = () => {
4806
4421
  return refreshButtonDom;
4807
4422
  };
4808
4423
 
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
4424
  const getDebugViewTopDom = (filterValue, useDevtoolsLayout, categoryFilters) => {
4823
4425
  const refreshButtonDom = getRefreshButtonDom();
4824
4426
  if (useDevtoolsLayout) {
@@ -4856,23 +4458,79 @@ const getDetailsCloseButtonDom = () => {
4856
4458
  return detailsCloseButtonDom;
4857
4459
  };
4858
4460
 
4859
- const getLineNodeDom = (line, index) => {
4461
+ const getEditorSelectionDom = () => {
4860
4462
  return [{
4861
- childCount: 2,
4862
- className: Row,
4463
+ childCount: 1,
4464
+ className: EditorSelections,
4863
4465
  type: Div
4864
4466
  }, {
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);
4467
+ childCount: 0,
4468
+ className: EditorSelection,
4469
+ style: 'height: 20px; left: 0px; top: 20px; width: 0px;',
4470
+ type: Div
4471
+ }];
4472
+ };
4473
+ const getGutterDom = (lineData, showLineNumbers) => {
4474
+ const gutterNodes = showLineNumbers ? lineData.flatMap((_, index) => {
4475
+ return [{
4476
+ childCount: 1,
4477
+ className: ChatDebugViewEventLineNumber,
4478
+ type: Span
4479
+ }, text(String(index + 1))];
4480
+ }) : [];
4481
+ return [{
4482
+ childCount: showLineNumbers ? lineData.length : 0,
4483
+ className: Gutter,
4484
+ type: Div
4485
+ }, ...gutterNodes];
4486
+ };
4487
+ const getEditorRowDom = line => {
4488
+ return [{
4489
+ childCount: line.childCount,
4490
+ className: EditorRow,
4491
+ type: Div
4492
+ }, ...line.nodes];
4493
+ };
4494
+ const getEditorRowsDom = lineData => {
4495
+ return [{
4496
+ childCount: lineData.length,
4497
+ className: EditorRows,
4498
+ type: Div
4499
+ }, ...lineData.flatMap(getEditorRowDom)];
4500
+ };
4501
+ const getEditorDom = (lineData, showLineNumbers = true) => {
4502
+ return [{
4503
+ childCount: 1,
4504
+ className: EditorContainer,
4505
+ type: Div
4506
+ }, {
4507
+ childCount: 2,
4508
+ className: EditorViewlet,
4509
+ role: 'code',
4510
+ type: Div
4511
+ }, ...getGutterDom(lineData, showLineNumbers), {
4512
+ childCount: 2,
4513
+ className: EditorContent,
4514
+ type: Div
4515
+ }, {
4516
+ 'aria-autocomplete': 'list',
4517
+ 'aria-multiline': true,
4518
+ 'aria-roledescription': 'editor',
4519
+ autocapitalize: 'off',
4520
+ autocomplete: 'off',
4521
+ autocorrect: 'off',
4522
+ childCount: 0,
4523
+ className: EditorInput,
4524
+ name: 'editor',
4525
+ role: 'textbox',
4526
+ spellcheck: false,
4527
+ type: TextArea,
4528
+ wrap: 'off'
4529
+ }, {
4530
+ childCount: 2,
4531
+ className: EditorLayers,
4532
+ type: Div
4533
+ }, ...getEditorSelectionDom(), ...getEditorRowsDom(lineData)];
4876
4534
  };
4877
4535
 
4878
4536
  const isDigit = character => {
@@ -5031,14 +4689,14 @@ const getEventNode = value => {
5031
4689
  type: getEventTypeLabel(value)
5032
4690
  } : value;
5033
4691
  const lines = getJsonLines(renderedValue);
5034
- const lineNodes = getLineNodes(lines.map(line => {
4692
+ const lineData = lines.map(line => {
5035
4693
  const lineContentNodes = getLineContentNodes(line);
5036
4694
  return {
5037
4695
  childCount: lineContentNodes.length / 2,
5038
4696
  nodes: lineContentNodes
5039
4697
  };
5040
- }));
5041
- return lineNodes;
4698
+ });
4699
+ return getEditorDom(lineData);
5042
4700
  };
5043
4701
 
5044
4702
  const getPanelId = detailTab => {
@@ -5098,13 +4756,17 @@ const getListFilesPreviewEvent = (event, name) => {
5098
4756
  const {
5099
4757
  result
5100
4758
  } = event;
5101
- if (typeof result !== 'object' || result === null || !Object.hasOwn(result, 'entries')) {
4759
+ if (typeof result !== 'object' || result === null) {
5102
4760
  return undefined;
5103
4761
  }
5104
4762
  const {
5105
- entries
4763
+ entries,
4764
+ error
5106
4765
  } = result;
5107
- return entries;
4766
+ if (entries !== undefined) {
4767
+ return entries;
4768
+ }
4769
+ return error;
5108
4770
  };
5109
4771
 
5110
4772
  const isChatMessageAddedEvent = event => {
@@ -5255,36 +4917,49 @@ const isAttachmentImagePreview = value => {
5255
4917
  return typeof value === 'object' && value !== null && value.previewType === 'image';
5256
4918
  };
5257
4919
 
4920
+ const getImagePreviewLabelDom = preview => {
4921
+ if (preview.stats === undefined) {
4922
+ return [{
4923
+ childCount: 1,
4924
+ className: ChatDebugViewImagePreviewLabel,
4925
+ type: Span
4926
+ }, text(preview.alt)];
4927
+ }
4928
+ return [{
4929
+ childCount: 2,
4930
+ className: ChatDebugViewImagePreviewLabel,
4931
+ type: Span
4932
+ }, {
4933
+ childCount: 1,
4934
+ type: Span
4935
+ }, text(preview.stats), {
4936
+ childCount: 1,
4937
+ type: Span
4938
+ }, text(preview.alt)];
4939
+ };
5258
4940
  const getImagePreviewDom = preview => {
5259
4941
  return [{
5260
4942
  childCount: 2,
5261
4943
  className: ChatDebugViewImagePreview,
5262
4944
  type: Div
4945
+ }, {
4946
+ childCount: 1,
4947
+ className: ChatDebugViewImagePreviewImageWrapper,
4948
+ type: Div
5263
4949
  }, {
5264
4950
  alt: preview.alt,
5265
4951
  childCount: 0,
5266
4952
  className: ChatDebugViewImagePreviewImage,
5267
4953
  src: preview.src,
5268
4954
  type: Img
5269
- }, {
5270
- childCount: 1,
5271
- className: ChatDebugViewImagePreviewLabel,
5272
- type: Span
5273
- }, text(preview.alt)];
4955
+ }, ...getImagePreviewLabelDom(preview)];
5274
4956
  };
5275
4957
 
5276
4958
  const getTextNode = (value, showLineNumbers = true) => {
5277
- if (!showLineNumbers) {
5278
- return [{
5279
- childCount: 1,
5280
- className: ChatDebugViewEventRawText,
5281
- type: P
5282
- }, text(value)];
5283
- }
5284
4959
  const lines = value.split('\n');
5285
4960
  const lineData = lines.map(line => {
5286
4961
  return {
5287
- childCount: 1,
4962
+ childCount: 2,
5288
4963
  nodes: [{
5289
4964
  childCount: 1,
5290
4965
  className: TokenText,
@@ -5292,8 +4967,7 @@ const getTextNode = (value, showLineNumbers = true) => {
5292
4967
  }, text(line)]
5293
4968
  };
5294
4969
  });
5295
- const lineNodes = getLineNodes(lineData);
5296
- return lineNodes;
4970
+ return getEditorDom(lineData, showLineNumbers);
5297
4971
  };
5298
4972
 
5299
4973
  const getPreviewEventNodes = (previewEvent, selectedEvent) => {
@@ -5312,10 +4986,6 @@ const getPreviewEventNodes = (previewEvent, selectedEvent) => {
5312
4986
  return getEventNode(previewEvent);
5313
4987
  };
5314
4988
 
5315
- const getTabId = detailTab => {
5316
- return `ChatDebugViewDetailsTab-${detailTab}`;
5317
- };
5318
-
5319
4989
  const getDetailTabDom = detailTab => {
5320
4990
  const {
5321
4991
  isSelected
@@ -5324,11 +4994,11 @@ const getDetailTabDom = detailTab => {
5324
4994
  'aria-controls': getPanelId(detailTab.name),
5325
4995
  ariaSelected: isSelected,
5326
4996
  childCount: 1,
5327
- className: mergeClassNames(ChatDebugViewDetailsTab, isSelected ? ChatDebugViewDetailsTabSelected : ''),
5328
- id: getTabId(detailTab.name),
4997
+ className: mergeClassNames(PanelTab, isSelected ? PanelTabSelected : ''),
5329
4998
  name: detailTab.name,
5330
4999
  onChange: SelectDetailTab,
5331
5000
  onClick: SelectDetailTab,
5001
+ onFocus: HandleDetailTabsFocus,
5332
5002
  role: Tab,
5333
5003
  tabIndex: isSelected ? 0 : -1,
5334
5004
  type: Button$1
@@ -5382,6 +5052,55 @@ const getStartText = event => {
5382
5052
  return getTimestampText(event.started ?? event.startTime ?? event.startTimestamp ?? event.timestamp);
5383
5053
  };
5384
5054
 
5055
+ const getTimingPreviewSegments = event => {
5056
+ return [{
5057
+ endPercent: 100,
5058
+ label: getDurationText(event),
5059
+ startPercent: 0
5060
+ }];
5061
+ };
5062
+ const getTimingPreviewSegmentNodes = segments => {
5063
+ return [{
5064
+ childCount: segments.length,
5065
+ className: ChatDebugViewTimingPreviewTrackOverlay,
5066
+ type: Div
5067
+ }, ...segments.flatMap(segment => {
5068
+ const widthPercent = Math.max(0, segment.endPercent - segment.startPercent);
5069
+ return [{
5070
+ childCount: 1,
5071
+ className: ChatDebugViewTimingPreviewSegment,
5072
+ style: `left:${segment.startPercent}%;width:${widthPercent}%;min-width:2px;`,
5073
+ type: Div
5074
+ }, text(segment.label)];
5075
+ })];
5076
+ };
5077
+ const getTimingPreviewDom = event => {
5078
+ const segments = getTimingPreviewSegments(event);
5079
+ return [{
5080
+ childCount: 1,
5081
+ className: ChatDebugViewTimingPreview,
5082
+ type: Div
5083
+ }, {
5084
+ childCount: 4,
5085
+ className: ChatDebugViewTimingPreviewTrack,
5086
+ type: Div
5087
+ }, {
5088
+ childCount: 0,
5089
+ className: ChatDebugViewTimingPreviewRail,
5090
+ type: Div
5091
+ }, ...getTimingPreviewSegmentNodes(segments), {
5092
+ childCount: 0,
5093
+ className: `${ChatDebugViewTimingPreviewMarker} ${ChatDebugViewTimingPreviewMarkerStart}`,
5094
+ style: 'left:12px;',
5095
+ type: Div
5096
+ }, {
5097
+ childCount: 0,
5098
+ className: `${ChatDebugViewTimingPreviewMarker} ${ChatDebugViewTimingPreviewMarkerEnd}`,
5099
+ style: 'right:12px;',
5100
+ type: Div
5101
+ }];
5102
+ };
5103
+
5385
5104
  const timingRowNode = {
5386
5105
  childCount: 2,
5387
5106
  className: ChatDebugViewTimingRow,
@@ -5403,26 +5122,26 @@ const getTimingRowDom = (label, value) => {
5403
5122
 
5404
5123
  const getTimingDetailsDom = event => {
5405
5124
  return [{
5406
- childCount: 3,
5125
+ childCount: 4,
5407
5126
  className: ChatDebugViewTiming,
5408
5127
  type: Div
5409
- }, ...getTimingRowDom(started(), getStartText(event)), ...getTimingRowDom(ended(), getEndText(event)), ...getTimingRowDom(duration(), getDurationText(event))];
5128
+ }, ...getTimingPreviewDom(event), ...getTimingRowDom(started(), getStartText(event)), ...getTimingRowDom(ended(), getEndText(event)), ...getTimingRowDom(duration(), getDurationText(event))];
5410
5129
  };
5411
5130
 
5412
- const getNextSiblingIndex$1 = (nodes, index) => {
5131
+ const getNextSiblingIndex$2 = (nodes, index) => {
5413
5132
  let nextSiblingIndex = index + 1;
5414
5133
  const childCount = nodes[index]?.childCount || 0;
5415
5134
  for (let i = 0; i < childCount; i++) {
5416
- nextSiblingIndex = getNextSiblingIndex$1(nodes, nextSiblingIndex);
5135
+ nextSiblingIndex = getNextSiblingIndex$2(nodes, nextSiblingIndex);
5417
5136
  }
5418
5137
  return nextSiblingIndex;
5419
5138
  };
5420
- const getDirectChildCount = nodes => {
5139
+ const getDirectChildCount$1 = nodes => {
5421
5140
  let count = 0;
5422
5141
  let index = 0;
5423
5142
  while (index < nodes.length) {
5424
5143
  count++;
5425
- index = getNextSiblingIndex$1(nodes, index);
5144
+ index = getNextSiblingIndex$2(nodes, index);
5426
5145
  }
5427
5146
  return count;
5428
5147
  };
@@ -5438,6 +5157,7 @@ const getDetailsDom = (previewEventNodes, payloadEventNodes = previewEventNodes,
5438
5157
  }
5439
5158
  const normalizedDetailTabs = getNormalizedDetailTabs(selectedEvent, detailTabs);
5440
5159
  const safeSelectedDetailTab = getSelectedDetailTab(normalizedDetailTabs);
5160
+ const selectedDetailTab = normalizedDetailTabs.find(detailTab => detailTab.name === safeSelectedDetailTab) ?? normalizedDetailTabs[0];
5441
5161
  const getDetailContentDom = () => {
5442
5162
  const getDetailContentDomTiming = () => {
5443
5163
  if (selectedEvent === null) {
@@ -5474,8 +5194,8 @@ const getDetailsDom = (previewEventNodes, payloadEventNodes = previewEventNodes,
5474
5194
  };
5475
5195
  const contentNodes = safeSelectedDetailTab === Timing ? getDetailContentDomTiming() : safeSelectedDetailTab === Preview ? getDetailContentDomPreview() : safeSelectedDetailTab === Payload ? getDetailContentDomPayload() : getDetailContentDomResponse();
5476
5196
  return [{
5477
- 'aria-labelledby': getTabId(safeSelectedDetailTab),
5478
- childCount: getDirectChildCount(contentNodes),
5197
+ 'aria-label': selectedDetailTab.label,
5198
+ childCount: getDirectChildCount$1(contentNodes),
5479
5199
  className: ChatDebugViewDetailsBottom,
5480
5200
  id: getPanelId(safeSelectedDetailTab),
5481
5201
  onContextMenu: HandleDetailsContextMenu,
@@ -5503,7 +5223,7 @@ const getRowCellNodes = (event, isErrorStatus, visibleTableColumns) => {
5503
5223
  case Duration:
5504
5224
  return [{
5505
5225
  childCount: 1,
5506
- className: TableCell,
5226
+ className: mergeClassNames(TableCell, ChatDebugViewCellDuration),
5507
5227
  type: Td
5508
5228
  }, text(getEventTableDurationText(event))];
5509
5229
  case Status$1:
@@ -5573,7 +5293,33 @@ const getSashNodesDom = hasSelectedEvent => {
5573
5293
  const None = 'none';
5574
5294
  const Status = 'status';
5575
5295
 
5576
- const getSplitViewDom = (splitChildCount, eventsChildCount, eventsClassName, tableNodes, sashNodes, detailsNodes) => {
5296
+ const getNextSiblingIndex$1 = (nodes, index) => {
5297
+ let nextSiblingIndex = index + 1;
5298
+ const childCount = nodes[index]?.childCount || 0;
5299
+ for (let i = 0; i < childCount; i++) {
5300
+ nextSiblingIndex = getNextSiblingIndex$1(nodes, nextSiblingIndex);
5301
+ }
5302
+ return nextSiblingIndex;
5303
+ };
5304
+ const getDirectChildCount = nodes => {
5305
+ let count = 0;
5306
+ let index = 0;
5307
+ while (index < nodes.length) {
5308
+ count++;
5309
+ index = getNextSiblingIndex$1(nodes, index);
5310
+ }
5311
+ return count;
5312
+ };
5313
+ const getSplitViewDom = (splitChildCount, eventsClassName, tableNodes, sashNodes, detailsNodes) => {
5314
+ const eventsChildCount = getDirectChildCount(tableNodes);
5315
+ if (splitChildCount === 1) {
5316
+ return [{
5317
+ childCount: eventsChildCount,
5318
+ className: eventsClassName,
5319
+ role: 'application',
5320
+ type: Div
5321
+ }, ...tableNodes];
5322
+ }
5577
5323
  return [{
5578
5324
  childCount: splitChildCount,
5579
5325
  className: ChatDebugViewDevtoolsSplit,
@@ -5587,6 +5333,61 @@ const getSplitViewDom = (splitChildCount, eventsChildCount, eventsClassName, tab
5587
5333
  }, ...tableNodes, ...sashNodes, ...detailsNodes];
5588
5334
  };
5589
5335
 
5336
+ const formatTimelineMilliseconds = value => {
5337
+ return `${Math.round(value * 1000)}ms`;
5338
+ };
5339
+
5340
+ const formatTimelineSeconds = value => {
5341
+ if (Number.isInteger(value)) {
5342
+ return `${value}s`;
5343
+ }
5344
+ return `${Number(value.toFixed(1))}s`;
5345
+ };
5346
+
5347
+ const getEndTime = event => {
5348
+ return event.ended ?? event.endTime ?? event.timestamp;
5349
+ };
5350
+
5351
+ const getStartTime = event => {
5352
+ return event.started ?? event.startTime ?? event.timestamp;
5353
+ };
5354
+
5355
+ const formatTableSummaryDuration = durationMs => {
5356
+ if (durationMs < 1000) {
5357
+ return formatTimelineMilliseconds(durationMs / 1000);
5358
+ }
5359
+ return formatTimelineSeconds(durationMs / 1000);
5360
+ };
5361
+ const getTableSummary = events => {
5362
+ let minStart = Number.POSITIVE_INFINITY;
5363
+ let maxEnd = Number.NEGATIVE_INFINITY;
5364
+ for (const event of events) {
5365
+ const startTime = toTimeNumber(getStartTime(event));
5366
+ const endTime = toTimeNumber(getEndTime(event));
5367
+ if (typeof startTime === 'number' && Number.isFinite(startTime)) {
5368
+ minStart = Math.min(minStart, startTime);
5369
+ }
5370
+ if (typeof endTime === 'number' && Number.isFinite(endTime)) {
5371
+ maxEnd = Math.max(maxEnd, endTime);
5372
+ }
5373
+ }
5374
+ const durationMs = Number.isFinite(minStart) && Number.isFinite(maxEnd) ? Math.max(0, maxEnd - minStart) : 0;
5375
+ return tableSummary(events.length, formatTableSummaryDuration(durationMs));
5376
+ };
5377
+
5378
+ const tableSummaryNode = {
5379
+ childCount: 1,
5380
+ className: TableSummary,
5381
+ role: Status,
5382
+ type: Div
5383
+ };
5384
+ const getTableSummaryDom = summary => {
5385
+ if (!summary) {
5386
+ return [];
5387
+ }
5388
+ return [tableSummaryNode, text(summary)];
5389
+ };
5390
+
5590
5391
  const getTableBodyDom = (rowNodes, eventCount) => {
5591
5392
  return [{
5592
5393
  childCount: eventCount === 0 ? 1 : eventCount,
@@ -5611,42 +5412,21 @@ const getTableColumnGroupDom = visibleTableColumns => {
5611
5412
  }))];
5612
5413
  };
5613
5414
 
5415
+ const getHeaderCellNode = (column, tableColumns) => {
5416
+ return [{
5417
+ childCount: 1,
5418
+ className: ChatDebugViewHeaderCell,
5419
+ name: column,
5420
+ onClick: HandleTableHeaderClick,
5421
+ type: Th
5422
+ }, text(getTableColumnLabel(tableColumns, column))];
5423
+ };
5614
5424
  const getHeaderCellNodes = (visibleTableColumns, tableColumns = createTableColumns()) => {
5615
5425
  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
- });
5426
+ return orderedVisibleTableColumns.flatMap(column => getHeaderCellNode(column, tableColumns));
5646
5427
  };
5647
5428
 
5648
5429
  const getTableHeaderDom = (visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns()) => {
5649
- const headerCellNodes = getHeaderCellNodes(visibleTableColumns, tableColumns);
5650
5430
  return [{
5651
5431
  childCount: 1,
5652
5432
  className: TableHead,
@@ -5656,7 +5436,17 @@ const getTableHeaderDom = (visibleTableColumns = defaultVisibleTableColumns, tab
5656
5436
  childCount: visibleTableColumns.length,
5657
5437
  className: TableRow,
5658
5438
  type: Tr
5659
- }, ...headerCellNodes];
5439
+ }, ...getHeaderCellNodes(visibleTableColumns, tableColumns)];
5440
+ };
5441
+
5442
+ const getTableDom = (rowNodes, eventCount, visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns(), summary = '', focus = 0) => {
5443
+ return [{
5444
+ childCount: 3,
5445
+ className: Table,
5446
+ onFocus: HandleTableFocus,
5447
+ tabIndex: 0,
5448
+ type: Table$1
5449
+ }, ...getTableColumnGroupDom(visibleTableColumns), ...getTableHeaderDom(visibleTableColumns, tableColumns), ...getTableBodyDom(rowNodes, eventCount)];
5660
5450
  };
5661
5451
 
5662
5452
  const resizerNames = ['ResizerOne', 'ResizerTwo'];
@@ -5674,6 +5464,7 @@ const getTableResizersDom = visibleTableColumns => {
5674
5464
  name: resizerNames[index],
5675
5465
  onPointerDown: HandleTableResizerPointerDown,
5676
5466
  role: None,
5467
+ tabIndex: -1,
5677
5468
  type: Button$1
5678
5469
  }, {
5679
5470
  childCount: 0,
@@ -5682,80 +5473,32 @@ const getTableResizersDom = visibleTableColumns => {
5682
5473
  type: Div
5683
5474
  }]);
5684
5475
  return [{
5685
- childCount: resizerCount + 1,
5476
+ childCount: resizerCount,
5686
5477
  className: Resizers,
5687
5478
  type: Div
5688
5479
  }, ...resizerNodes];
5689
5480
  };
5690
5481
 
5691
- const tableSummaryNode = {
5692
- childCount: 1,
5693
- className: TableSummary,
5694
- role: Status,
5695
- type: Div
5696
- };
5697
- const getTableSummaryDom = summary => {
5698
- if (!summary) {
5699
- return [];
5700
- }
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
- return [{
5482
+ const getTableWrapperDom = (rowNodes, eventCount, visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns(), summary = '', focus = 0, className = '', role = '') => {
5483
+ const tableWrapperClassName = mergeClassNames(TableWrapper, focus === FocusChatDebugTable ? FocusOutline : '', className);
5484
+ const tableWrapperNode = {
5707
5485
  childCount: 2,
5708
5486
  className: tableWrapperClassName,
5709
- type: Div
5710
- }, {
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;
5732
- };
5733
-
5734
- const getStartTime = event => {
5735
- return event.started ?? event.startTime ?? event.timestamp;
5487
+ type: Div,
5488
+ ...(role ? {
5489
+ role
5490
+ } : {})
5491
+ };
5492
+ return [tableWrapperNode, ...getTableDom(rowNodes, eventCount, visibleTableColumns, tableColumns, summary, focus), ...getTableResizersDom(visibleTableColumns)];
5736
5493
  };
5737
5494
 
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));
5495
+ const getTableWrapperWrapperDom = (rowNodes, eventCount, visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns(), summary = '', focus = 0, className = '', role = '') => {
5496
+ const tableSummaryNodes = getTableSummaryDom(summary);
5497
+ return [{
5498
+ childCount: tableSummaryNodes.length === 0 ? 1 : 2,
5499
+ className: TableWrapperWrapper,
5500
+ type: Div
5501
+ }, ...getTableWrapperDom(rowNodes, eventCount, visibleTableColumns, tableColumns, summary, focus, className, role), ...tableSummaryNodes];
5759
5502
  };
5760
5503
 
5761
5504
  const getBucketUnitDom = (unitCount, presetValue) => {
@@ -5892,10 +5635,6 @@ const getTimelineTopDom = timelineInfo => {
5892
5635
  childCount: 1,
5893
5636
  className: ChatDebugViewTimelineTop,
5894
5637
  type: Div
5895
- }, {
5896
- childCount: 1,
5897
- className: ChatDebugViewTimelineSummary,
5898
- type: H2
5899
5638
  }, text(getTimelineSummary(timelineInfo))];
5900
5639
  };
5901
5640
 
@@ -5935,7 +5674,7 @@ const getTimelineDom = (timelineInfo, hoverPercent = null) => {
5935
5674
  }, ...selectionNodes];
5936
5675
  };
5937
5676
 
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) => {
5677
+ const getDevtoolsDom = (events, selectedEvent, selectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage = noEventsFound(), timelineSelectionActive = false, timelineSelectionAnchorSeconds = '', timelineSelectionFocusSeconds = '', detailTabs = createDetailTabs(), visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns(), timelineInfo, timelineHoverPercent = null, focus = 0) => {
5939
5678
  const rowNodes = getDevtoolsRows(events, selectedEventIndex, visibleTableColumns);
5940
5679
  const effectiveRange = getEffectiveTimelineRange(timelineStartSeconds, timelineEndSeconds, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds);
5941
5680
  const resolvedTimelineInfo = timelineInfo || getTimelineInfo(timelineEvents, effectiveRange.startSeconds, effectiveRange.endSeconds);
@@ -5945,13 +5684,18 @@ const getDevtoolsDom = (events, selectedEvent, selectedEventIndex, timelineEvent
5945
5684
  const payloadEventNodes = selectedEvent ? getEventNode(getPayloadEvent(selectedEvent)) : [];
5946
5685
  const responseEventNodes = selectedEvent ? getEventNode(selectedEvent) : [];
5947
5686
  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
5687
  const eventsClassName = getEventsClassName(hasSelectedEvent);
5688
+ const summary = getTableSummary(events);
5689
+ const tableNodes = events.length === 0 ? getEmptyStateDom(emptyMessage) : getTableWrapperWrapperDom(rowNodes, events.length, visibleTableColumns, tableColumns, summary, focus);
5951
5690
  const detailsNodes = getDetailsDom(previewEventNodes, payloadEventNodes, responseEventNodes, selectedEvent, detailTabs);
5952
5691
  const sashNodes = getSashNodesDom(hasSelectedEvent);
5953
5692
  const splitChildCount = hasSelectedEvent ? 3 : 1;
5954
- return [...timelineNodes, ...getSplitViewDom(splitChildCount, eventsChildCount, eventsClassName, tableNodes, sashNodes, detailsNodes)];
5693
+ const rootChildCount = 3;
5694
+ return [{
5695
+ childCount: rootChildCount,
5696
+ className: mergeClassNames(ChatDebugView, ChatDebugViewDevtools),
5697
+ type: Div
5698
+ }, ...timelineNodes, ...getSplitViewDom(splitChildCount, eventsClassName, tableNodes, sashNodes, detailsNodes)];
5955
5699
  };
5956
5700
 
5957
5701
  const getEmptyMessage = (eventCount, hasFilterValue, useNoToolCallEventsMessage, noFilteredEventsMessage) => {
@@ -5974,21 +5718,6 @@ const getLegacyEventsDom = (errorMessage, emptyMessage, eventNodes) => {
5974
5718
  }, text(errorMessage || emptyMessage)] : eventNodes)];
5975
5719
  };
5976
5720
 
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
5721
  const getNextSiblingIndex = (nodes, index) => {
5993
5722
  let nextSiblingIndex = index + 1;
5994
5723
  const childCount = nodes[index]?.childCount || 0;
@@ -6012,7 +5741,7 @@ const getEventCategoryFilterDescription = eventCategoryFilters => {
6012
5741
  }
6013
5742
  return eventCategoryFilters.map(eventCategoryFilter => getEventCategoryFilterLabel(eventCategoryFilter).toLowerCase()).join(', ');
6014
5743
  };
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) => {
5744
+ const getChatDebugViewDom = (errorMessage, filterValue, eventCategoryFilters, categoryFilters, _showEventStreamFinishedEvents, _showInputEvents, _showResponsePartEvents, useDevtoolsLayout, selectedEvent, selectedEventIndex, timelineStartSeconds, timelineEndSeconds, timelineFilterDescription, timelineEvents, events, timelineSelectionActive = false, timelineSelectionAnchorSeconds = '', timelineSelectionFocusSeconds = '', visibleTableColumns = defaultVisibleTableColumns, detailTabs = createDetailTabs(), tableColumns = createTableColumns(), timelineInfo, timelineHoverPercent = null, focus = 0) => {
6016
5745
  if (errorMessage) {
6017
5746
  return getDebugErrorDom(errorMessage);
6018
5747
  }
@@ -6025,7 +5754,6 @@ const getChatDebugViewDom = (errorMessage, filterValue, eventCategoryFilters, ca
6025
5754
  if (trimmedFilterValue) {
6026
5755
  filterDescriptionParts.push(trimmedFilterValue);
6027
5756
  }
6028
- const timelineFilterDescription = getTimelineFilterDescription(timelineStartSeconds, timelineEndSeconds);
6029
5757
  if (timelineFilterDescription) {
6030
5758
  filterDescriptionParts.push(timelineFilterDescription);
6031
5759
  }
@@ -6036,7 +5764,18 @@ const getChatDebugViewDom = (errorMessage, filterValue, eventCategoryFilters, ca
6036
5764
  const useNoToolCallEventsMessage = eventCategoryFilters.length === 1 && eventCategoryFilters[0] === Tools && !trimmedFilterValue && !hasTimelineFilter;
6037
5765
  const emptyMessage = getEmptyMessage(events.length, hasFilterValue, useNoToolCallEventsMessage, noFilteredEventsMessage);
6038
5766
  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));
5767
+ if (useDevtoolsLayout) {
5768
+ const devtoolsDom = getDevtoolsDom(events, selectedEvent, safeSelectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds, detailTabs, visibleTableColumns, tableColumns, timelineInfo, timelineHoverPercent, focus);
5769
+ const devtoolsContentNodes = devtoolsDom.slice(1);
5770
+ const topLevelNodes = [...getDebugViewTopDom(filterValue, useDevtoolsLayout, categoryFilters), ...devtoolsContentNodes];
5771
+ const rootChildCount = getTopLevelChildCount(topLevelNodes);
5772
+ return [{
5773
+ childCount: rootChildCount,
5774
+ className: mergeClassNames(ChatDebugView, ChatDebugViewDevtools),
5775
+ type: Div
5776
+ }, ...topLevelNodes];
5777
+ }
5778
+ const contentNodes = getLegacyEventsDom(errorMessage, emptyMessage, events.flatMap(getEventNode));
6040
5779
  const debugViewTopDom = getDebugViewTopDom(filterValue, useDevtoolsLayout, categoryFilters);
6041
5780
  const rootChildCount = 1 + getTopLevelChildCount(contentNodes);
6042
5781
  return [{
@@ -6059,7 +5798,7 @@ const renderItems = (oldState, newState) => {
6059
5798
  return [SetDom2, newState.uid, []];
6060
5799
  }
6061
5800
  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);
5801
+ const dom = getChatDebugViewDom(newState.errorMessage, newState.filterValue, getSelectedEventCategoryFilters(newState.categoryFilters), newState.categoryFilters, newState.showEventStreamFinishedEvents, newState.showInputEvents, newState.showResponsePartEvents, newState.useDevtoolsLayout, newState.selectedEvent, newState.selectedEventIndex, newState.timelineStartSeconds, newState.timelineEndSeconds, newState.timelineFilterDescription, withSessionEventIds(newState.timelineEvents), withSessionEventIds(filteredEvents), newState.timelineSelectionActive, newState.timelineSelectionAnchorSeconds, newState.timelineSelectionFocusSeconds, getVisibleTableColumns(newState.tableColumns), newState.detailTabs, newState.tableColumns, newState.timelineInfo, newState.timelineHoverPercent, newState.focus);
6063
5802
  return [SetDom2, newState.uid, dom];
6064
5803
  };
6065
5804
 
@@ -6171,6 +5910,9 @@ const renderEventListeners = () => {
6171
5910
  }, {
6172
5911
  name: SelectDetailTab,
6173
5912
  params: ['selectDetailTab', TargetName]
5913
+ }, {
5914
+ name: HandleDetailTabsFocus,
5915
+ params: ['handleDetailTabsFocus', TargetName]
6174
5916
  }, {
6175
5917
  name: HandleTimelineRangePreset,
6176
5918
  params: ['handleTimelineRangePreset', 'event.target.dataset.value']
@@ -6223,18 +5965,14 @@ const rerender = state => {
6223
5965
  return structuredClone(state);
6224
5966
  };
6225
5967
 
6226
- const isSameVisibleTableColumns = (a, b) => {
6227
- return a.length === b.length && a.every((value, index) => value === b[index]);
6228
- };
6229
-
6230
5968
  const resetTableColumns = state => {
6231
- if (isSameVisibleTableColumns(state.visibleTableColumns, defaultVisibleTableColumns) && isSameTableColumnWidths(state.tableColumnWidths, defaultTableColumnWidths)) {
5969
+ if (getVisibleTableColumns(state.tableColumns).join(',') === defaultVisibleTableColumns.join(',') && isSameTableColumnWidths(state.tableColumnWidths, defaultTableColumnWidths)) {
6232
5970
  return state;
6233
5971
  }
6234
5972
  return {
6235
5973
  ...state,
6236
- tableColumnWidths: defaultTableColumnWidths,
6237
- visibleTableColumns: defaultVisibleTableColumns
5974
+ tableColumns: createTableColumns(),
5975
+ tableColumnWidths: defaultTableColumnWidths
6238
5976
  };
6239
5977
  };
6240
5978
 
@@ -6266,10 +6004,10 @@ const saveState = state => {
6266
6004
  filterValue,
6267
6005
  selectedEventId,
6268
6006
  sessionId,
6007
+ tableColumns,
6269
6008
  tableColumnWidths,
6270
6009
  timelineEndSeconds,
6271
- timelineStartSeconds,
6272
- visibleTableColumns
6010
+ timelineStartSeconds
6273
6011
  } = state;
6274
6012
  return {
6275
6013
  eventCategoryFilter: getSelectedEventCategoryFilter(categoryFilters),
@@ -6281,7 +6019,7 @@ const saveState = state => {
6281
6019
  tableColumnWidths,
6282
6020
  timelineEndSeconds,
6283
6021
  timelineStartSeconds,
6284
- visibleTableColumns
6022
+ visibleTableColumns: getVisibleTableColumns(tableColumns)
6285
6023
  };
6286
6024
  };
6287
6025
 
@@ -6348,16 +6086,24 @@ const toggleTableColumnVisibility = (state, column) => {
6348
6086
  if (!isTableColumn(column)) {
6349
6087
  return state;
6350
6088
  }
6351
- const nextVisibleColumns = state.visibleTableColumns.includes(column) ? state.visibleTableColumns.filter(visibleColumn => visibleColumn !== column) : [...state.visibleTableColumns, column];
6352
6089
  return {
6353
6090
  ...state,
6354
- visibleTableColumns: getOrderedVisibleTableColumns(nextVisibleColumns)
6091
+ tableColumns: state.tableColumns.map(tableColumn => {
6092
+ if (tableColumn.name !== column) {
6093
+ return tableColumn;
6094
+ }
6095
+ return {
6096
+ ...tableColumn,
6097
+ isVisible: !tableColumn.isVisible
6098
+ };
6099
+ })
6355
6100
  };
6356
6101
  };
6357
6102
 
6358
6103
  const commandMap = {
6359
6104
  'ChatDebug.appendStoredEventForTest': wrapCommand(appendStoredEventForTest),
6360
6105
  'ChatDebug.appendStoredImageAttachmentForTest': wrapCommand(appendStoredImageAttachmentForTest),
6106
+ 'ChatDebug.appendStoredRemovedImageAttachmentForTest': wrapCommand(appendStoredRemovedImageAttachmentForTest),
6361
6107
  'ChatDebug.create': create,
6362
6108
  'ChatDebug.diff2': diff2,
6363
6109
  'ChatDebug.focusFirst': wrapCommand(focusFirst),
@@ -6371,6 +6117,7 @@ const commandMap = {
6371
6117
  'ChatDebug.handleCloseDetails': wrapCommand(handleCloseDetails),
6372
6118
  'ChatDebug.handleDetailsContextMenu': wrapCommand(handleDetailsContextMenu),
6373
6119
  'ChatDebug.handleDetailsTopContextMenu': wrapCommand(handleDetailsTopContextMenu),
6120
+ 'ChatDebug.handleDetailTabsFocus': wrapCommand(handleDetailTabsFocus),
6374
6121
  'ChatDebug.handleEscape': wrapCommand(handleEscape),
6375
6122
  'ChatDebug.handleEventCategoryFilter': wrapCommand(handleEventCategoryFilter),
6376
6123
  'ChatDebug.handleEventRowClick': wrapCommand(handleEventRowClick),