@lvce-editor/chat-debug-view 10.21.0 → 10.23.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.
@@ -1138,6 +1138,7 @@ const Img = 17;
1138
1138
  const Section = 41;
1139
1139
  const Search = 42;
1140
1140
  const Li = 48;
1141
+ const A = 53;
1141
1142
  const Ul = 60;
1142
1143
  const TextArea = 62;
1143
1144
  const Reference = 100;
@@ -1469,6 +1470,7 @@ const i18nString = (key, placeholders = emptyObject) => {
1469
1470
  const All = 'All';
1470
1471
  const CloseDetails = 'Close details';
1471
1472
  const Copy = 'Copy';
1473
+ const CopyAsFetch = 'Copy As Fetch';
1472
1474
  const CachedTokens = 'Cached Tokens';
1473
1475
  const DetailSections = 'Detail sections';
1474
1476
  const Duration$1 = 'Time';
@@ -1481,11 +1483,11 @@ const General$1 = 'General';
1481
1483
  const Headers = 'Headers';
1482
1484
  const ImageCouldNotBeLoaded = 'image could not be loaded';
1483
1485
  const InputTokens = 'Input Tokens';
1484
- const InvalidSessionId = 'Invalid session id';
1485
- const InvalidUriEncoding = 'Invalid URI encoding';
1486
- const InvalidUriFormat = 'Invalid URI format';
1486
+ const InvalidSessionId$1 = 'Invalid session id';
1487
+ const InvalidUriEncoding$1 = 'Invalid URI encoding';
1488
+ const InvalidUriFormat$1 = 'Invalid URI format';
1487
1489
  const Method$1 = 'Method';
1488
- const MissingUri = 'Missing URI';
1490
+ const MissingUri$1 = 'Missing URI';
1489
1491
  const Network = 'Network';
1490
1492
  const NoChatSessionFound = 'No chat session found for sessionId "{PH1}".';
1491
1493
  const NoEventsFound = 'No events have been found';
@@ -1503,14 +1505,16 @@ const RequestMethod = 'Request Method';
1503
1505
  const RequestUrl = 'Request URL';
1504
1506
  const Response = 'Response';
1505
1507
  const ResponseHeaders$1 = 'Response Headers';
1508
+ const ResponseHeadersInfo = 'Some headers may not be displayed due to Access-Control-Expose-Headers header.';
1506
1509
  const SecondsRange = '{PH1}s-{PH2}s';
1507
1510
  const Size$1 = 'Size';
1508
1511
  const Started = 'Started';
1509
1512
  const Status$2 = 'Status';
1510
1513
  const StatusCode = 'Status Code';
1511
1514
  const Stream = 'Stream';
1512
- const TableSummaryPlural = '{PH1} events, {PH2} from start to finish';
1513
- const TableSummarySingular = '{PH1} event, {PH2} from start to finish';
1515
+ const TableSummaryRequestPlural = '{PH1} requests';
1516
+ const TableSummaryRequestSingular = '{PH1} request';
1517
+ const TableSummaryFinish = 'Finish {PH1}';
1514
1518
  const Timing = 'Timing';
1515
1519
  const Tokens = 'Tokens';
1516
1520
  const ToSeconds = 'to {PH1}s';
@@ -1524,6 +1528,9 @@ const WindowSummary = 'Window {PH1}-{PH2} of {PH3}';
1524
1528
  const copy = () => {
1525
1529
  return i18nString(Copy);
1526
1530
  };
1531
+ const copyAsFetch = () => {
1532
+ return i18nString(CopyAsFetch);
1533
+ };
1527
1534
  const openInNewTab = () => {
1528
1535
  return i18nString(OpenInNewTab);
1529
1536
  };
@@ -1574,7 +1581,7 @@ const headers = () => {
1574
1581
  return i18nString(Headers);
1575
1582
  };
1576
1583
  const invalidSessionId = () => {
1577
- return i18nString(InvalidSessionId);
1584
+ return i18nString(InvalidSessionId$1);
1578
1585
  };
1579
1586
  const imageCouldNotBeLoaded = () => {
1580
1587
  return i18nString(ImageCouldNotBeLoaded);
@@ -1583,13 +1590,13 @@ const inputTokens = () => {
1583
1590
  return i18nString(InputTokens);
1584
1591
  };
1585
1592
  const invalidUriEncoding = () => {
1586
- return i18nString(InvalidUriEncoding);
1593
+ return i18nString(InvalidUriEncoding$1);
1587
1594
  };
1588
1595
  const invalidUriFormat = () => {
1589
- return i18nString(InvalidUriFormat);
1596
+ return i18nString(InvalidUriFormat$1);
1590
1597
  };
1591
1598
  const missingUri = () => {
1592
- return i18nString(MissingUri);
1599
+ return i18nString(MissingUri$1);
1593
1600
  };
1594
1601
  const method = () => {
1595
1602
  return i18nString(Method$1);
@@ -1640,6 +1647,9 @@ const requestUrl = () => {
1640
1647
  const responseHeaders = () => {
1641
1648
  return i18nString(ResponseHeaders$1);
1642
1649
  };
1650
+ const responseHeadersInfo = () => {
1651
+ return i18nString(ResponseHeadersInfo);
1652
+ };
1643
1653
  const resetColumns = () => {
1644
1654
  return i18nString(ResetColumns);
1645
1655
  };
@@ -1670,10 +1680,14 @@ const timing = () => {
1670
1680
  const tokens = () => {
1671
1681
  return i18nString(Tokens);
1672
1682
  };
1673
- const tableSummary = (eventCount, duration) => {
1674
- return i18nString(eventCount === 1 ? TableSummarySingular : TableSummaryPlural, {
1675
- PH1: String(eventCount),
1676
- PH2: duration
1683
+ const tableSummaryRequests = eventCount => {
1684
+ return i18nString(eventCount === 1 ? TableSummaryRequestSingular : TableSummaryRequestPlural, {
1685
+ PH1: String(eventCount)
1686
+ });
1687
+ };
1688
+ const tableSummaryFinish = duration => {
1689
+ return i18nString(TableSummaryFinish, {
1690
+ PH1: duration
1677
1691
  });
1678
1692
  };
1679
1693
  const toSeconds = seconds => {
@@ -1811,25 +1825,6 @@ const isDetailTab = value => {
1811
1825
  return value === Response$1 || value === Preview$1 || value === Payload$1 || value === Headers$1 || value === Tokens$1 || value === Headers$1 || value === Timing$1;
1812
1826
  };
1813
1827
 
1814
- const RE_SPACE = /\s+/;
1815
- const tokenToEventCategoryFilter = new Map([['@tools', Tools$1], ['@network', Network$1], ['@ui', Ui$1], ['@stream', Stream$1]]);
1816
- const parseFilterValue = filterValue => {
1817
- const normalizedFilter = filterValue.trim().toLowerCase();
1818
- if (!normalizedFilter) {
1819
- return {
1820
- eventCategoryFilter: All$1,
1821
- filterText: ''
1822
- };
1823
- }
1824
- const parts = normalizedFilter.split(RE_SPACE);
1825
- const eventCategoryFilter = parts.map(part => tokenToEventCategoryFilter.get(part)).find(Boolean) || All$1;
1826
- const filterText = parts.filter(part => !tokenToEventCategoryFilter.has(part)).join(' ');
1827
- return {
1828
- eventCategoryFilter,
1829
- filterText
1830
- };
1831
- };
1832
-
1833
1828
  const hasDetailTab = (detailTabs, value) => {
1834
1829
  return detailTabs.some(detailTab => detailTab.name === value);
1835
1830
  };
@@ -1852,28 +1847,45 @@ const Duration = 'duration';
1852
1847
  const Status$1 = 'status';
1853
1848
  const Size = 'size';
1854
1849
  const tableColumnNames = [Type, Method, Status$1, Size, Duration];
1855
- const createTableColumns = () => {
1856
- return [{
1857
- isVisible: true,
1858
- label: type(),
1859
- name: Type
1860
- }, {
1861
- isVisible: true,
1850
+ const tableColumnDefinitions = {
1851
+ [Duration]: {
1852
+ defaultWidth: 110,
1853
+ label: duration(),
1854
+ minimumWidth: 80
1855
+ },
1856
+ [Method]: {
1857
+ defaultWidth: 90,
1862
1858
  label: method(),
1863
- name: Method
1864
- }, {
1865
- isVisible: true,
1866
- label: status(),
1867
- name: Status$1
1868
- }, {
1869
- isVisible: true,
1859
+ minimumWidth: 56
1860
+ },
1861
+ [Size]: {
1862
+ defaultWidth: 100,
1870
1863
  label: size(),
1871
- name: Size
1872
- }, {
1873
- isVisible: true,
1874
- label: duration(),
1875
- name: Duration
1876
- }];
1864
+ minimumWidth: 80
1865
+ },
1866
+ [Status$1]: {
1867
+ defaultWidth: 110,
1868
+ label: status(),
1869
+ minimumWidth: 56
1870
+ },
1871
+ [Type]: {
1872
+ defaultWidth: 260,
1873
+ label: type(),
1874
+ minimumWidth: 80
1875
+ }
1876
+ };
1877
+ const createTableColumns = () => {
1878
+ return tableColumnNames.map(name => {
1879
+ const definition = tableColumnDefinitions[name];
1880
+ return {
1881
+ defaultWidth: definition.defaultWidth,
1882
+ isVisible: true,
1883
+ label: definition.label,
1884
+ minimumWidth: definition.minimumWidth,
1885
+ name,
1886
+ width: definition.defaultWidth
1887
+ };
1888
+ });
1877
1889
  };
1878
1890
  const defaultVisibleTableColumns = tableColumnNames;
1879
1891
  const isTableColumn = value => {
@@ -1889,13 +1901,45 @@ const getTableColumnsWithVisibility = (tableColumns, visibleTableColumns) => {
1889
1901
  isVisible: visibleColumns.has(column.name)
1890
1902
  }));
1891
1903
  };
1904
+ const getTableColumnByName = (tableColumns, name) => {
1905
+ return tableColumns.find(column => column.name === name);
1906
+ };
1907
+ const getTableColumnWidth = (tableColumns, name) => {
1908
+ return getTableColumnByName(tableColumns, name)?.width ?? 0;
1909
+ };
1910
+ const getTableColumnMinimumWidth = (tableColumns, name) => {
1911
+ return getTableColumnByName(tableColumns, name)?.minimumWidth ?? 0;
1912
+ };
1913
+ const getTableColumnWidths = tableColumns => {
1914
+ return {
1915
+ duration: getTableColumnWidth(tableColumns, Duration),
1916
+ method: getTableColumnWidth(tableColumns, Method),
1917
+ size: getTableColumnWidth(tableColumns, Size),
1918
+ status: getTableColumnWidth(tableColumns, Status$1),
1919
+ type: getTableColumnWidth(tableColumns, Type)
1920
+ };
1921
+ };
1922
+ const setTableColumnWidths = (tableColumns, tableColumnWidths) => {
1923
+ return tableColumns.map(column => ({
1924
+ ...column,
1925
+ width: tableColumnWidths[column.name]
1926
+ }));
1927
+ };
1928
+ const setTableColumnWidth = (tableColumns, columnName, width) => {
1929
+ return tableColumns.map(column => {
1930
+ if (column.name !== columnName) {
1931
+ return column;
1932
+ }
1933
+ return {
1934
+ ...column,
1935
+ width
1936
+ };
1937
+ });
1938
+ };
1892
1939
  const getOrderedVisibleTableColumns = (values, tableColumns = createTableColumns()) => {
1893
1940
  const visibleColumns = new Set(values.filter(isTableColumn));
1894
1941
  return tableColumns.map(column => column.name).filter(column => visibleColumns.has(column));
1895
1942
  };
1896
- const isVisibleTableColumn = (tableColumns, column) => {
1897
- return tableColumns.some(tableColumn => tableColumn.name === column && tableColumn.isVisible);
1898
- };
1899
1943
  const getTableColumnLabel = (tableColumns, name) => {
1900
1944
  const match = tableColumns.find(column => column.name === name);
1901
1945
  if (match) {
@@ -1917,17 +1961,15 @@ const getTableColumnLabel = (tableColumns, name) => {
1917
1961
  }
1918
1962
  };
1919
1963
 
1920
- const defaultTableColumnWidths = {
1921
- duration: 110,
1922
- method: 90,
1923
- size: 100,
1924
- status: 110,
1925
- type: 260
1926
- };
1927
-
1928
1964
  const getMainWidth = state => {
1929
1965
  return Math.max(0, state.width - state.horizontalPadding);
1930
1966
  };
1967
+ const getNarrowMainWidthBreakpoint = state => {
1968
+ return Math.max(0, state.mediumBreakpoint - state.horizontalPadding);
1969
+ };
1970
+ const isNarrowSplitLayout = state => {
1971
+ return getMainWidth(state) <= getNarrowMainWidthBreakpoint(state);
1972
+ };
1931
1973
  const clampTableWidth = (state, tableWidth) => {
1932
1974
  const mainWidth = getMainWidth(state);
1933
1975
  const maxTableWidth = Math.max(0, mainWidth - state.minDetailsWidth - state.sashWidth);
@@ -1939,24 +1981,21 @@ const getDetailsWidth = (state, tableWidth) => {
1939
1981
  const clampedTableWidth = clampTableWidth(state, tableWidth);
1940
1982
  return Math.max(0, mainWidth - clampedTableWidth - state.sashWidth);
1941
1983
  };
1984
+ const getBalancedSplitTableWidth = state => {
1985
+ const mainWidth = getMainWidth(state);
1986
+ const balancedTableWidth = Math.floor(Math.max(0, mainWidth - state.sashWidth) / 2);
1987
+ return clampTableWidth(state, balancedTableWidth);
1988
+ };
1989
+ const shouldUseBalancedSplitTableWidth = state => {
1990
+ return !!state.selectedEvent && state.useDevtoolsLayout && !state.tableWidthManuallyResized && isNarrowSplitLayout(state);
1991
+ };
1942
1992
  const getTableWidthFromClientX = (state, clientX) => {
1943
1993
  const nextTableWidth = clientX - state.x - state.leftPadding;
1944
1994
  return clampTableWidth(state, nextTableWidth);
1945
1995
  };
1946
1996
 
1947
- const minimumTableColumnWidths = {
1948
- [Duration]: 80,
1949
- [Method]: 56,
1950
- [Size]: 80,
1951
- [Status$1]: 56,
1952
- [Type]: 80
1953
- };
1954
- const getMinimumTableColumnWidth = column => {
1955
- return minimumTableColumnWidths[column];
1956
- };
1957
-
1958
- const getTableColumnLayout = (tableWidth, visibleTableColumns, tableColumnWidths) => {
1959
- const visibleColumns = getOrderedVisibleTableColumns(visibleTableColumns);
1997
+ const getTableColumnLayout = (tableWidth, visibleTableColumns, tableColumns) => {
1998
+ const visibleColumns = getOrderedVisibleTableColumns(visibleTableColumns, tableColumns);
1960
1999
  if (visibleColumns.length === 0) {
1961
2000
  return {
1962
2001
  fixedColumns: [],
@@ -1973,10 +2012,10 @@ const getTableColumnLayout = (tableWidth, visibleTableColumns, tableColumnWidths
1973
2012
  visibleColumnWidths.push(Math.max(0, remainingWidth));
1974
2013
  continue;
1975
2014
  }
1976
- const minimumWidth = getMinimumTableColumnWidth(column);
1977
- const minimumRemainingWidth = visibleColumns.slice(index + 1).reduce((total, remainingColumn) => total + getMinimumTableColumnWidth(remainingColumn), 0);
2015
+ const minimumWidth = getTableColumnMinimumWidth(tableColumns, column);
2016
+ const minimumRemainingWidth = visibleColumns.slice(index + 1).reduce((total, remainingColumn) => total + getTableColumnMinimumWidth(tableColumns, remainingColumn), 0);
1978
2017
  const maxWidth = Math.max(minimumWidth, remainingWidth - minimumRemainingWidth);
1979
- const preferredWidth = tableColumnWidths[column];
2018
+ const preferredWidth = getTableColumnWidth(tableColumns, column);
1980
2019
  const clampedWidth = Math.max(minimumWidth, Math.min(preferredWidth, maxWidth));
1981
2020
  visibleColumnWidths.push(clampedWidth);
1982
2021
  remainingWidth -= clampedWidth;
@@ -1995,24 +2034,21 @@ const getTableColumnLayout = (tableWidth, visibleTableColumns, tableColumnWidths
1995
2034
  };
1996
2035
  };
1997
2036
 
1998
- const getResizedTableColumnWidths = (state, visibleTableColumns, tableColumnWidths, clientX, resizerDownId) => {
2037
+ const getResizedTableColumnWidths = (state, visibleTableColumns, tableColumns, clientX, resizerDownId) => {
1999
2038
  const clampedTableWidth = clampTableWidth(state, state.tableWidth);
2000
- const layout = getTableColumnLayout(clampedTableWidth, visibleTableColumns, tableColumnWidths);
2039
+ const layout = getTableColumnLayout(clampedTableWidth, visibleTableColumns, tableColumns);
2001
2040
  if (resizerDownId < 1 || resizerDownId >= layout.visibleColumns.length) {
2002
- return tableColumnWidths;
2041
+ return tableColumns;
2003
2042
  }
2004
2043
  const boundaryIndex = resizerDownId - 1;
2005
2044
  const precedingWidth = layout.visibleColumnWidths.slice(0, boundaryIndex).reduce((total, current) => total + current, 0);
2006
2045
  const resizedColumn = layout.visibleColumns[boundaryIndex];
2007
- const minimumWidth = getMinimumTableColumnWidth(resizedColumn);
2008
- const minimumRemainingWidth = layout.visibleColumns.slice(boundaryIndex + 1).reduce((total, column) => total + getMinimumTableColumnWidth(column), 0);
2046
+ const minimumWidth = getTableColumnMinimumWidth(tableColumns, resizedColumn);
2047
+ const minimumRemainingWidth = layout.visibleColumns.slice(boundaryIndex + 1).reduce((total, column) => total + getTableColumnMinimumWidth(tableColumns, column), 0);
2009
2048
  const maxWidth = Math.max(minimumWidth, clampedTableWidth - precedingWidth - minimumRemainingWidth);
2010
2049
  const nextWidth = clientX - state.x - state.leftPadding - precedingWidth;
2011
2050
  const clampedWidth = Math.max(minimumWidth, Math.min(nextWidth, maxWidth));
2012
- return {
2013
- ...tableColumnWidths,
2014
- [resizedColumn]: clampedWidth
2015
- };
2051
+ return setTableColumnWidth(tableColumns, resizedColumn, clampedWidth);
2016
2052
  };
2017
2053
 
2018
2054
  const isSameTableColumnWidths = (first, second) => {
@@ -2049,9 +2085,6 @@ const restoreCategoryFilters = (savedState, currentCategoryFilters) => {
2049
2085
  if (typeof savedState.eventCategoryFilter === 'string' && validEventCategoryFilters.has(savedState.eventCategoryFilter)) {
2050
2086
  return selectCategoryFilter(currentCategoryFilters, savedState.eventCategoryFilter);
2051
2087
  }
2052
- if (typeof savedState.filterValue === 'string') {
2053
- return selectCategoryFilter(currentCategoryFilters, parseFilterValue(savedState.filterValue).eventCategoryFilter);
2054
- }
2055
2088
  return currentCategoryFilters;
2056
2089
  };
2057
2090
  const restoreFilterValue = (savedState, currentFilterValue) => {
@@ -2081,24 +2114,26 @@ const restoreVisibleTableColumns = (savedState, currentTableColumns) => {
2081
2114
  }
2082
2115
  return getTableColumnsWithVisibility(currentTableColumns, visibleTableColumns);
2083
2116
  };
2084
- const restoreTableColumnWidths = (savedState, currentTableColumnWidths) => {
2117
+ const restoreTableColumns = (savedState, currentTableColumns) => {
2118
+ const tableColumnsWithVisibility = restoreVisibleTableColumns(savedState, currentTableColumns);
2085
2119
  const {
2086
2120
  tableColumnWidths: savedTableColumnWidths
2087
2121
  } = savedState;
2088
2122
  if (isTableColumnWidths(savedTableColumnWidths)) {
2089
- return savedTableColumnWidths;
2123
+ return setTableColumnWidths(tableColumnsWithVisibility, savedTableColumnWidths);
2090
2124
  }
2091
2125
  if (isLegacyTableColumnWidths(savedTableColumnWidths)) {
2092
2126
  const legacyTableColumnWidths = savedTableColumnWidths;
2093
- return {
2127
+ const currentTableColumnWidths = getTableColumnWidths(currentTableColumns);
2128
+ return setTableColumnWidths(tableColumnsWithVisibility, {
2094
2129
  duration: legacyTableColumnWidths.duration,
2095
2130
  method: legacyTableColumnWidths.method,
2096
2131
  size: currentTableColumnWidths.size,
2097
2132
  status: legacyTableColumnWidths.status,
2098
2133
  type: legacyTableColumnWidths.type
2099
- };
2134
+ });
2100
2135
  }
2101
- return currentTableColumnWidths;
2136
+ return tableColumnsWithVisibility;
2102
2137
  };
2103
2138
  const restoreSavedState = (state, savedState) => {
2104
2139
  if (!isSavedState(savedState)) {
@@ -2110,8 +2145,7 @@ const restoreSavedState = (state, savedState) => {
2110
2145
  detailTabs: restoreDetailTabs(savedState, state.detailTabs),
2111
2146
  filterValue: restoreFilterValue(savedState, state.filterValue),
2112
2147
  selectedEventId: restoreSelectedEventId(savedState, state.selectedEventId),
2113
- tableColumns: restoreVisibleTableColumns(savedState, state.tableColumns),
2114
- tableColumnWidths: restoreTableColumnWidths(savedState, state.tableColumnWidths),
2148
+ tableColumns: restoreTableColumns(savedState, state.tableColumns),
2115
2149
  timelineEndSeconds: restoreTimelineEndSeconds(savedState, state.timelineEndSeconds),
2116
2150
  timelineStartSeconds: restoreTimelineStartSeconds(savedState, state.timelineStartSeconds)
2117
2151
  };
@@ -2322,7 +2356,7 @@ const getEventsWithTime = events => {
2322
2356
  });
2323
2357
  };
2324
2358
 
2325
- const clamp$1 = (value, minimum, maximum) => {
2359
+ const clamp = (value, minimum, maximum) => {
2326
2360
  return Math.max(minimum, Math.min(value, maximum));
2327
2361
  };
2328
2362
 
@@ -2356,8 +2390,8 @@ const getNormalizedRange = (durationSeconds, startValue, endValue) => {
2356
2390
  const rawEnd = parsedEnd ?? durationSeconds;
2357
2391
  const rangeStart = Math.min(rawStart, rawEnd);
2358
2392
  const rangeEnd = Math.max(rawStart, rawEnd);
2359
- const normalizedStart = clamp$1(rangeStart, 0, durationSeconds);
2360
- const normalizedEnd = clamp$1(rangeEnd, 0, durationSeconds);
2393
+ const normalizedStart = clamp(rangeStart, 0, durationSeconds);
2394
+ const normalizedEnd = clamp(rangeEnd, 0, durationSeconds);
2361
2395
  return {
2362
2396
  endSeconds: roundSeconds(normalizedEnd),
2363
2397
  hasSelection: true,
@@ -2481,8 +2515,8 @@ const createDefaultState = () => {
2481
2515
  showResponsePartEvents: false,
2482
2516
  sortColumn: '',
2483
2517
  sortDescending: false,
2518
+ summaries: [],
2484
2519
  tableColumns: createTableColumns(),
2485
- tableColumnWidths: defaultTableColumnWidths,
2486
2520
  tableDeltaY: 0,
2487
2521
  tableMaxLineY: 0,
2488
2522
  tableMinLineY: 0,
@@ -2490,6 +2524,7 @@ const createDefaultState = () => {
2490
2524
  tableScrollBarHandleOffset: 0,
2491
2525
  tableScrollBarPointerActive: false,
2492
2526
  tableWidth: defaultTableWidth,
2527
+ tableWidthManuallyResized: false,
2493
2528
  timelineEndSeconds: '',
2494
2529
  timelineEvents: [],
2495
2530
  timelineFilterDescription: '',
@@ -2542,7 +2577,7 @@ const RenderFocusContext = 4;
2542
2577
  const RenderFocus = 5;
2543
2578
 
2544
2579
  const diff = (oldState, newState) => {
2545
- if (oldState.categoryFilters !== newState.categoryFilters || oldState.collapsedHeaderSections !== newState.collapsedHeaderSections || 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.previewTextDeltaY !== newState.previewTextDeltaY || 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.timelineHeight !== newState.timelineHeight || 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) {
2580
+ if (oldState.categoryFilters !== newState.categoryFilters || oldState.collapsedHeaderSections !== newState.collapsedHeaderSections || 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.previewTextDeltaY !== newState.previewTextDeltaY || oldState.summaries !== newState.summaries || 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.tableDeltaY !== newState.tableDeltaY || oldState.tableMaxLineY !== newState.tableMaxLineY || oldState.tableMinLineY !== newState.tableMinLineY || oldState.tableWidth !== newState.tableWidth || oldState.timelineEndSeconds !== newState.timelineEndSeconds || oldState.timelineHeight !== newState.timelineHeight || 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) {
2546
2581
  return [RenderIncremental, RenderCss];
2547
2582
  }
2548
2583
  return [];
@@ -2579,6 +2614,45 @@ const mergedEventType = 'tool-execution';
2579
2614
  const handleSubmitEventType = 'handle-submit';
2580
2615
  const sseResponseCompletedEventType = 'sse-response-completed';
2581
2616
 
2617
+ const encoder = new TextEncoder();
2618
+ const getEndValuePayload = event => {
2619
+ const {
2620
+ endValue
2621
+ } = event;
2622
+ return endValue?.value;
2623
+ };
2624
+ const getResponsePayload = event => {
2625
+ const endValuePayload = getEndValuePayload(event);
2626
+ if (endValuePayload !== undefined) {
2627
+ return endValuePayload;
2628
+ }
2629
+ if ('value' in event && event.value !== undefined) {
2630
+ return event.value;
2631
+ }
2632
+ if ('response' in event && event.response !== undefined) {
2633
+ return event.response;
2634
+ }
2635
+ return undefined;
2636
+ };
2637
+ const getPayloadText = payload => {
2638
+ if (typeof payload === 'string') {
2639
+ return payload;
2640
+ }
2641
+ const serialized = JSON.stringify(payload);
2642
+ return serialized ?? '';
2643
+ };
2644
+ const getResponsePayloadSize = event => {
2645
+ const payload = getResponsePayload(event);
2646
+ if (payload === undefined) {
2647
+ return 0;
2648
+ }
2649
+ try {
2650
+ return encoder.encode(getPayloadText(payload)).length;
2651
+ } catch {
2652
+ return 0;
2653
+ }
2654
+ };
2655
+
2582
2656
  const hasMatchingToolName = (startedEvent, finishedEvent) => {
2583
2657
  if (typeof startedEvent.toolName === 'string' && typeof finishedEvent.toolName === 'string') {
2584
2658
  return startedEvent.toolName === finishedEvent.toolName;
@@ -2684,7 +2758,8 @@ const mergeRequestResponseEvents = (startedEvent, finishedEvent) => {
2684
2758
  return {
2685
2759
  ...mergeToolExecutionEvents(startedEvent, finishedEvent, startedEvent.type),
2686
2760
  requestEvent: startedEvent,
2687
- responseEvent: finishedEvent
2761
+ responseEvent: finishedEvent,
2762
+ size: getResponsePayloadSize(finishedEvent)
2688
2763
  };
2689
2764
  };
2690
2765
  const isMatchingRequestResponsePair = (startedEvent, finishedEvent) => {
@@ -2790,12 +2865,8 @@ const matchesEventCategoryFilter = (event, eventCategoryFilters) => {
2790
2865
  const getFilteredEvents = (events, filterValue, eventCategoryFilters, showInputEvents, showResponsePartEvents, showEventStreamFinishedEvents) => {
2791
2866
  const visibleEvents = getVisibleEvents(events, showInputEvents, showResponsePartEvents, showEventStreamFinishedEvents);
2792
2867
  const collapsedEvents = collapseToolExecutionEvents(visibleEvents);
2793
- const parsedFilter = parseFilterValue(filterValue);
2794
- const activeEventCategoryFilters = parsedFilter.eventCategoryFilter === All$1 ? eventCategoryFilters : [parsedFilter.eventCategoryFilter];
2795
- const filteredByCategory = collapsedEvents.filter(event => matchesEventCategoryFilter(event, activeEventCategoryFilters));
2796
- const {
2797
- filterText
2798
- } = parsedFilter;
2868
+ const filteredByCategory = collapsedEvents.filter(event => matchesEventCategoryFilter(event, eventCategoryFilters));
2869
+ const filterText = filterValue.trim().toLowerCase();
2799
2870
  if (!filterText) {
2800
2871
  return filteredByCategory;
2801
2872
  }
@@ -2983,10 +3054,22 @@ const sortEventsByTableColumn = (events, sortColumn, sortDescending) => {
2983
3054
  };
2984
3055
 
2985
3056
  const getCurrentEvents$1 = state => {
2986
- const eventCategoryFilters = getSelectedEventCategoryFilters(state.categoryFilters);
2987
- const filteredEvents = getFilteredEvents(state.events, state.filterValue, eventCategoryFilters, state.showInputEvents, state.showResponsePartEvents, state.showEventStreamFinishedEvents);
2988
- const timelineEvents = filterEventsByTimelineRange(filteredEvents, state.timelineStartSeconds, state.timelineEndSeconds);
2989
- return sortEventsByTableColumn(timelineEvents, state.sortColumn, state.sortDescending);
3057
+ const {
3058
+ categoryFilters,
3059
+ events,
3060
+ filterValue,
3061
+ showEventStreamFinishedEvents,
3062
+ showInputEvents,
3063
+ showResponsePartEvents,
3064
+ sortColumn,
3065
+ sortDescending,
3066
+ timelineEndSeconds,
3067
+ timelineStartSeconds
3068
+ } = state;
3069
+ const eventCategoryFilters = getSelectedEventCategoryFilters(categoryFilters);
3070
+ const filteredEvents = getFilteredEvents(events, filterValue, eventCategoryFilters, showInputEvents, showResponsePartEvents, showEventStreamFinishedEvents);
3071
+ const timelineEvents = filterEventsByTimelineRange(filteredEvents, timelineStartSeconds, timelineEndSeconds);
3072
+ return sortEventsByTableColumn(timelineEvents, sortColumn, sortDescending);
2990
3073
  };
2991
3074
 
2992
3075
  const getCurrentEvents = state => getCurrentEvents$1(state);
@@ -3009,6 +3092,8 @@ const loadSelectedEvent = async ({
3009
3092
  sessionId,
3010
3093
  type
3011
3094
  }) => {
3095
+ // TODO load them in parallel
3096
+ // or adjust worker function to load both start and end event
3012
3097
  const raw = await loadSelectedEvent$1(sessionId, eventId, type);
3013
3098
  if (endEventId && endEventId !== -1) {
3014
3099
  const end = await loadSelectedEvent$1(sessionId, endEventId, type);
@@ -3323,7 +3408,7 @@ const selectEventAtIndex = async (state, selectedEventIndex) => {
3323
3408
  type: selectedEvent.type
3324
3409
  });
3325
3410
  const resolvedSelectedEvent = await withPreparedSelectedEventPreview(mergeSelectedEventDetails(selectedEvent, selectedEventDetails));
3326
- return withSelectedEventVisible({
3411
+ const nextState = {
3327
3412
  ...state,
3328
3413
  detailTabs: createDetailTabs(selectedDetailTab, resolvedSelectedEvent),
3329
3414
  previewTextCursorColumnIndex: null,
@@ -3334,6 +3419,10 @@ const selectEventAtIndex = async (state, selectedEventIndex) => {
3334
3419
  selectedEvent: resolvedSelectedEvent,
3335
3420
  selectedEventId: selectedEvent.eventId,
3336
3421
  selectedEventIndex
3422
+ };
3423
+ return withSelectedEventVisible({
3424
+ ...nextState,
3425
+ tableWidth: shouldUseBalancedSplitTableWidth(nextState) ? getBalancedSplitTableWidth(nextState) : state.tableWidth
3337
3426
  });
3338
3427
  };
3339
3428
 
@@ -3385,6 +3474,12 @@ const getMenuEntriesTableBody = props => {
3385
3474
  flags: None$1,
3386
3475
  id: 'copy',
3387
3476
  label: copy()
3477
+ }, {
3478
+ args: [props.eventIndex],
3479
+ command: 'ChatDebug.handleTableRowCopyAsFetch',
3480
+ flags: None$1,
3481
+ id: 'copy-as-fetch',
3482
+ label: copyAsFetch()
3388
3483
  }, {
3389
3484
  args: [props.eventIndex],
3390
3485
  command: 'ChatDebug.handleTableRowOpenInNewTab',
@@ -3394,36 +3489,17 @@ const getMenuEntriesTableBody = props => {
3394
3489
  }];
3395
3490
  };
3396
3491
 
3397
- const getColumnVisibilityFlags = (tableColumns, column) => {
3398
- return isVisibleTableColumn(tableColumns, column) ? Checked : Unchecked;
3492
+ const getColumnMenuEntry = (columnName, label, isVisible) => {
3493
+ return {
3494
+ args: [columnName],
3495
+ command: 'ChatDebug.toggleTableColumnVisibility',
3496
+ flags: isVisible ? Checked : Unchecked,
3497
+ id: columnName,
3498
+ label
3499
+ };
3399
3500
  };
3400
-
3401
3501
  const getMenuEntriesTableHeader = state => {
3402
- return [{
3403
- args: [Type],
3404
- command: 'ChatDebug.toggleTableColumnVisibility',
3405
- flags: getColumnVisibilityFlags(state.tableColumns, Type),
3406
- id: 'type',
3407
- label: type()
3408
- }, {
3409
- args: [Status$1],
3410
- command: 'ChatDebug.toggleTableColumnVisibility',
3411
- flags: getColumnVisibilityFlags(state.tableColumns, Status$1),
3412
- id: 'status',
3413
- label: status()
3414
- }, {
3415
- args: [Size],
3416
- command: 'ChatDebug.toggleTableColumnVisibility',
3417
- flags: getColumnVisibilityFlags(state.tableColumns, Size),
3418
- id: 'size',
3419
- label: size()
3420
- }, {
3421
- args: [Duration],
3422
- command: 'ChatDebug.toggleTableColumnVisibility',
3423
- flags: getColumnVisibilityFlags(state.tableColumns, Duration),
3424
- id: 'duration',
3425
- label: duration()
3426
- }, {
3502
+ return [...state.tableColumns.map(column => getColumnMenuEntry(column.name, column.label, column.isVisible)), {
3427
3503
  args: [],
3428
3504
  command: 'ChatDebug.resetTableColumns',
3429
3505
  flags: None$1,
@@ -3502,12 +3578,10 @@ const getMenuIds = () => {
3502
3578
  return [MenuChatDebugTableHeader, MenuChatDebugTableBody, 556, 557];
3503
3579
  };
3504
3580
 
3505
- const ParseChatDebugUriErrorCode = {
3506
- InvalidSessionId: 1,
3507
- InvalidUriEncoding: 2,
3508
- InvalidUriFormat: 3,
3509
- MissingUri: 4
3510
- };
3581
+ const InvalidSessionId = 1;
3582
+ const InvalidUriEncoding = 2;
3583
+ const InvalidUriFormat = 3;
3584
+ const MissingUri = 4;
3511
3585
 
3512
3586
  const ParseChatDebugUriResultType = {
3513
3587
  Error: 2,
@@ -3519,7 +3593,7 @@ const invalidSessionIdPattern = /[/?#]/;
3519
3593
  const parseChatDebugUri = uri => {
3520
3594
  if (!uri) {
3521
3595
  return {
3522
- code: ParseChatDebugUriErrorCode.MissingUri,
3596
+ code: MissingUri,
3523
3597
  message: missingUri(),
3524
3598
  type: ParseChatDebugUriResultType.Error
3525
3599
  };
@@ -3527,7 +3601,7 @@ const parseChatDebugUri = uri => {
3527
3601
  const match = uri.match(chatDebugUriPattern);
3528
3602
  if (!match) {
3529
3603
  return {
3530
- code: ParseChatDebugUriErrorCode.InvalidUriFormat,
3604
+ code: InvalidUriFormat,
3531
3605
  message: invalidUriFormat(),
3532
3606
  type: ParseChatDebugUriResultType.Error
3533
3607
  };
@@ -3538,14 +3612,14 @@ const parseChatDebugUri = uri => {
3538
3612
  sessionId = decodeURIComponent(encodedSessionId);
3539
3613
  } catch {
3540
3614
  return {
3541
- code: ParseChatDebugUriErrorCode.InvalidUriEncoding,
3615
+ code: InvalidUriEncoding,
3542
3616
  message: invalidUriEncoding(),
3543
3617
  type: ParseChatDebugUriResultType.Error
3544
3618
  };
3545
3619
  }
3546
3620
  if (!sessionId || invalidSessionIdPattern.test(sessionId)) {
3547
3621
  return {
3548
- code: ParseChatDebugUriErrorCode.InvalidSessionId,
3622
+ code: InvalidSessionId,
3549
3623
  message: invalidSessionId(),
3550
3624
  type: ParseChatDebugUriResultType.Error
3551
3625
  };
@@ -3565,7 +3639,7 @@ const getSessionIdFromUri = state => {
3565
3639
  };
3566
3640
 
3567
3641
  const getInvalidUriMessage = (uri, code) => {
3568
- if (code === ParseChatDebugUriErrorCode.MissingUri) {
3642
+ if (code === MissingUri) {
3569
3643
  return unableToLoadDebugSessionMissingUri();
3570
3644
  }
3571
3645
  return unableToLoadDebugSessionInvalidUri(uri);
@@ -3584,6 +3658,49 @@ const getEffectiveTimelineRange = (timelineStartSeconds, timelineEndSeconds, tim
3584
3658
  };
3585
3659
  };
3586
3660
 
3661
+ const formatTimelineMilliseconds = value => {
3662
+ return `${Math.round(value * 1000)}ms`;
3663
+ };
3664
+
3665
+ const formatTimelineSeconds = value => {
3666
+ if (Number.isInteger(value)) {
3667
+ return `${value}s`;
3668
+ }
3669
+ return `${Number(value.toFixed(1))}s`;
3670
+ };
3671
+
3672
+ const getEndTime = event => {
3673
+ return event.ended ?? event.endTime ?? event.timestamp;
3674
+ };
3675
+
3676
+ const getStartTime = event => {
3677
+ return event.started ?? event.startTime ?? event.timestamp;
3678
+ };
3679
+
3680
+ const formatTableSummaryDuration = durationMs => {
3681
+ if (durationMs < 1000) {
3682
+ return formatTimelineMilliseconds(durationMs / 1000);
3683
+ }
3684
+ return formatTimelineSeconds(durationMs / 1000);
3685
+ };
3686
+ const getTableSummaries = events => {
3687
+ let minStart = Number.POSITIVE_INFINITY;
3688
+ let maxEnd = Number.NEGATIVE_INFINITY;
3689
+ for (const event of events) {
3690
+ const startTime = toTimeNumber(getStartTime(event));
3691
+ const endTime = toTimeNumber(getEndTime(event));
3692
+ if (typeof startTime === 'number' && Number.isFinite(startTime)) {
3693
+ minStart = Math.min(minStart, startTime);
3694
+ }
3695
+ if (typeof endTime === 'number' && Number.isFinite(endTime)) {
3696
+ maxEnd = Math.max(maxEnd, endTime);
3697
+ }
3698
+ }
3699
+ const durationMs = Number.isFinite(minStart) && Number.isFinite(maxEnd) ? Math.max(0, maxEnd - minStart) : 0;
3700
+ const duration = formatTableSummaryDuration(durationMs);
3701
+ return [tableSummaryRequests(events.length), tableSummaryFinish(duration)];
3702
+ };
3703
+
3587
3704
  const getTimelineEvents = state => {
3588
3705
  const {
3589
3706
  events,
@@ -3616,12 +3733,16 @@ const getStateWithTimelineInfo = state => {
3616
3733
  const effectiveRange = getEffectiveTimelineRange(state.timelineStartSeconds, state.timelineEndSeconds, state.timelineSelectionActive, state.timelineSelectionAnchorSeconds, state.timelineSelectionFocusSeconds);
3617
3734
  const timelineInfo = getTimelineInfo(timelineEvents, effectiveRange.startSeconds, effectiveRange.endSeconds);
3618
3735
  const timelineFilterDescription = getTimelineFilterDescription(state.timelineStartSeconds, state.timelineEndSeconds);
3619
- return {
3736
+ const nextState = {
3620
3737
  ...state,
3621
3738
  timelineEvents,
3622
3739
  timelineFilterDescription,
3623
3740
  timelineInfo
3624
3741
  };
3742
+ return {
3743
+ ...nextState,
3744
+ summaries: getTableSummaries(getCurrentEvents$1(nextState))
3745
+ };
3625
3746
  };
3626
3747
 
3627
3748
  const getStateWithInvalidUri = state => {
@@ -3691,7 +3812,7 @@ const getMergedRequestResponseEvent = (item, response) => {
3691
3812
  eventEndId: response.eventId,
3692
3813
  eventId: item.eventId,
3693
3814
  method: 'POST',
3694
- size: 0,
3815
+ size: getResponsePayloadSize(response),
3695
3816
  ...(started === undefined ? {} : {
3696
3817
  started
3697
3818
  }),
@@ -3708,7 +3829,7 @@ const getMergedRequestResponseEvent = (item, response) => {
3708
3829
  eventEndId: response.eventId,
3709
3830
  eventId: item.eventId,
3710
3831
  method: 'POST',
3711
- size: 0,
3832
+ size: getResponsePayloadSize(response),
3712
3833
  ...(started === undefined ? {} : {
3713
3834
  started
3714
3835
  }),
@@ -3759,7 +3880,10 @@ const listChatViewEvents = async (sessionId, _databaseName, _dataBaseVersion, _e
3759
3880
  };
3760
3881
 
3761
3882
  const restoreSelectedEvent = async state => {
3762
- if (state.selectedEventId === null) {
3883
+ const {
3884
+ selectedEventId
3885
+ } = state;
3886
+ if (selectedEventId === null) {
3763
3887
  return {
3764
3888
  ...state,
3765
3889
  previewTextCursorColumnIndex: null,
@@ -3860,11 +3984,14 @@ const loadEventsForSessionId = async (state, sessionId) => {
3860
3984
  };
3861
3985
 
3862
3986
  const refreshEvents = async state => {
3863
- const sessionId = state.sessionId || getSessionIdFromUri(state);
3864
- if (!sessionId) {
3987
+ const {
3988
+ sessionId
3989
+ } = state;
3990
+ const actual = sessionId || getSessionIdFromUri(state);
3991
+ if (!actual) {
3865
3992
  return getStateWithInvalidUri(state);
3866
3993
  }
3867
- return loadEventsForSessionId(state, sessionId);
3994
+ return loadEventsForSessionId(state, actual);
3868
3995
  };
3869
3996
 
3870
3997
  const refresh = async state => {
@@ -3919,6 +4046,9 @@ const handleEscape = state => {
3919
4046
  };
3920
4047
 
3921
4048
  const getEventIndexByStableId$1 = (events, event) => {
4049
+ if (typeof event.eventId !== 'number') {
4050
+ return -1;
4051
+ }
3922
4052
  return events.findIndex(candidate => candidate.eventId === event.eventId);
3923
4053
  };
3924
4054
 
@@ -4013,7 +4143,7 @@ const getBoolean = value => {
4013
4143
  const General = 'general';
4014
4144
  const RequestHeaders = 'requestHeaders';
4015
4145
  const ResponseHeaders = 'responseHeaders';
4016
- const headerSectionKeys = [General, RequestHeaders, ResponseHeaders];
4146
+ const headerSectionKeys = [General, ResponseHeaders, RequestHeaders];
4017
4147
  const isHeaderSectionKey = value => {
4018
4148
  return headerSectionKeys.includes(value);
4019
4149
  };
@@ -4046,6 +4176,9 @@ const parseTimelineRangePreset$1 = value => {
4046
4176
  };
4047
4177
  };
4048
4178
  const getEventIndexByStableId = (events, event) => {
4179
+ if (typeof event.eventId !== 'number') {
4180
+ return -1;
4181
+ }
4049
4182
  return events.findIndex(candidate => candidate.eventId === event.eventId);
4050
4183
  };
4051
4184
  const getSelectedEventIndex = state => {
@@ -4143,7 +4276,7 @@ const handleUseDevtoolsLayout = (state, _value, checked) => {
4143
4276
  const useDevtoolsLayout = getBoolean(checked);
4144
4277
  const selectedEventIndex = useDevtoolsLayout ? getSelectedEventIndex(state) : null;
4145
4278
  const hasSelectedEvent = useDevtoolsLayout && selectedEventIndex !== null;
4146
- return applyVirtualTableState({
4279
+ const nextState = {
4147
4280
  ...state,
4148
4281
  previewTextCursorColumnIndex: hasSelectedEvent ? state.previewTextCursorColumnIndex : null,
4149
4282
  previewTextCursorRowIndex: hasSelectedEvent ? state.previewTextCursorRowIndex : null,
@@ -4151,6 +4284,10 @@ const handleUseDevtoolsLayout = (state, _value, checked) => {
4151
4284
  selectedEventId: hasSelectedEvent ? state.selectedEventId : null,
4152
4285
  selectedEventIndex,
4153
4286
  useDevtoolsLayout
4287
+ };
4288
+ return applyVirtualTableState({
4289
+ ...nextState,
4290
+ tableWidth: shouldUseBalancedSplitTableWidth(nextState) ? getBalancedSplitTableWidth(nextState) : state.tableWidth
4154
4291
  });
4155
4292
  };
4156
4293
  const handleSelectedEventIndex = (state, value) => {
@@ -4574,9 +4711,6 @@ const getPreviewEvent = event => {
4574
4711
 
4575
4712
  const previewTextRowHeight = 20;
4576
4713
  const defaultPreviewTextColumnWidth = 9;
4577
- const clamp = (value, min, max) => {
4578
- return Math.min(Math.max(value, min), max);
4579
- };
4580
4714
  const getPreviewTextCursorFromPoint = (value, x, y) => {
4581
4715
  const lines = value.split('\n');
4582
4716
  const rowIndex = clamp(Math.floor(Math.max(y, 0) / previewTextRowHeight), 0, Math.max(lines.length - 1, 0));
@@ -4797,7 +4931,8 @@ const handleSashPointerMove = (state, eventX, eventY) => {
4797
4931
  }
4798
4932
  return {
4799
4933
  ...state,
4800
- tableWidth: getTableWidthFromClientX(state, eventX)
4934
+ tableWidth: getTableWidthFromClientX(state, eventX),
4935
+ tableWidthManuallyResized: true
4801
4936
  };
4802
4937
  };
4803
4938
 
@@ -4864,7 +4999,7 @@ const handleTableResizerPointerMove = (state, clientX) => {
4864
4999
  }
4865
5000
  return {
4866
5001
  ...state,
4867
- tableColumnWidths: getResizedTableColumnWidths(state, getVisibleTableColumns(state.tableColumns), state.tableColumnWidths, clientX, state.tableResizerDownId)
5002
+ tableColumns: getResizedTableColumnWidths(state, getVisibleTableColumns(state.tableColumns), state.tableColumns, clientX, state.tableResizerDownId)
4868
5003
  };
4869
5004
  };
4870
5005
 
@@ -4889,6 +5024,88 @@ const handleTableRowCopy = async (state, eventIndex) => {
4889
5024
  return state;
4890
5025
  };
4891
5026
 
5027
+ const indent = (value, count) => {
5028
+ const prefix = ' '.repeat(count);
5029
+ return value.split('\n').map(line => `${prefix}${line}`).join('\n');
5030
+ };
5031
+
5032
+ const escapeSingleQuotedString = value => {
5033
+ return value.replaceAll('\\', '\\\\').replaceAll("'", "\\'");
5034
+ };
5035
+
5036
+ const toSingleQuotedString = value => {
5037
+ return `'${escapeSingleQuotedString(value)}'`;
5038
+ };
5039
+
5040
+ const getBodyLine = value => {
5041
+ if (typeof value === 'string') {
5042
+ return ` body: ${toSingleQuotedString(value)},`;
5043
+ }
5044
+ if (typeof value === 'function' || typeof value === 'symbol' || typeof value === 'bigint') {
5045
+ return ` body: ${toSingleQuotedString(String(value))},`;
5046
+ }
5047
+ let serializedBody;
5048
+ try {
5049
+ serializedBody = JSON.stringify(value, null, 2);
5050
+ } catch {
5051
+ return ` body: ${toSingleQuotedString(String(value))},`;
5052
+ }
5053
+ if (!serializedBody) {
5054
+ return ` body: ${toSingleQuotedString(String(value))},`;
5055
+ }
5056
+ return ` body: JSON.stringify(\n${indent(serializedBody, 4)}\n ),`;
5057
+ };
5058
+
5059
+ const getHeaderLines = value => {
5060
+ if (!isRecord(value)) {
5061
+ return [];
5062
+ }
5063
+ const lines = [];
5064
+ for (const [key, headerValue] of Object.entries(value)) {
5065
+ if (typeof headerValue === 'string' || typeof headerValue === 'number' || typeof headerValue === 'boolean') {
5066
+ lines.push(` ${toSingleQuotedString(key)}: ${toSingleQuotedString(String(headerValue))},`);
5067
+ }
5068
+ }
5069
+ if (lines.length === 0) {
5070
+ return [];
5071
+ }
5072
+ return [' headers: {', ...lines, ' },'];
5073
+ };
5074
+
5075
+ const getFetchCode = event => {
5076
+ if (typeof event.url !== 'string') {
5077
+ return undefined;
5078
+ }
5079
+ const lines = [];
5080
+ if (typeof event.method === 'string' && event.method !== 'GET') {
5081
+ lines.push(` method: ${toSingleQuotedString(event.method)},`);
5082
+ }
5083
+ lines.push(...getHeaderLines(event.headers));
5084
+ if (event.body !== undefined) {
5085
+ lines.push(getBodyLine(event.body));
5086
+ }
5087
+ if (lines.length === 0) {
5088
+ return `fetch(${toSingleQuotedString(event.url)})`;
5089
+ }
5090
+ return `fetch(${toSingleQuotedString(event.url)}, {\n${lines.join('\n')}\n})`;
5091
+ };
5092
+
5093
+ const handleTableRowCopyAsFetch = async (state, eventIndex) => {
5094
+ const currentEvents = getCurrentEvents$1(state);
5095
+ const event = currentEvents[eventIndex];
5096
+ if (!event) {
5097
+ return state;
5098
+ }
5099
+ const fetchCode = getFetchCode(event);
5100
+ if (fetchCode) {
5101
+ await writeClipBoardText(fetchCode);
5102
+ return state;
5103
+ }
5104
+ const text = JSON.stringify(event, null, 2);
5105
+ await writeClipBoardText(text);
5106
+ return state;
5107
+ };
5108
+
4892
5109
  const toDataUri$1 = text => {
4893
5110
  return `data:application/json,${encodeURIComponent(text)}`;
4894
5111
  };
@@ -5203,17 +5420,22 @@ const handleTimelinePointerUp = (state, eventX) => {
5203
5420
  const setUseDevtoolsLayout = (state, checked) => {
5204
5421
  const useDevtoolsLayout = getBoolean(checked);
5205
5422
  const selectedEventIndex = useDevtoolsLayout ? getSelectedEventIndex$1(state) : null;
5206
- return applyVirtualTableState({
5423
+ const hasSelectedEvent = useDevtoolsLayout && selectedEventIndex !== null;
5424
+ const nextState = {
5207
5425
  ...state,
5208
- previewTextCursorColumnIndex: useDevtoolsLayout && selectedEventIndex !== null ? state.previewTextCursorColumnIndex : null,
5209
- previewTextCursorRowIndex: useDevtoolsLayout && selectedEventIndex !== null ? state.previewTextCursorRowIndex : null,
5210
- previewTextDeltaY: useDevtoolsLayout && selectedEventIndex !== null ? state.previewTextDeltaY : 0,
5426
+ previewTextCursorColumnIndex: hasSelectedEvent ? state.previewTextCursorColumnIndex : null,
5427
+ previewTextCursorRowIndex: hasSelectedEvent ? state.previewTextCursorRowIndex : null,
5428
+ previewTextDeltaY: hasSelectedEvent ? state.previewTextDeltaY : 0,
5211
5429
  previewTextScrollBarHandleOffset: 0,
5212
5430
  previewTextScrollBarPointerActive: false,
5213
- selectedEvent: useDevtoolsLayout && selectedEventIndex !== null ? state.selectedEvent : null,
5214
- selectedEventId: useDevtoolsLayout && selectedEventIndex !== null ? state.selectedEventId : null,
5431
+ selectedEvent: hasSelectedEvent ? state.selectedEvent : null,
5432
+ selectedEventId: hasSelectedEvent ? state.selectedEventId : null,
5215
5433
  selectedEventIndex,
5216
5434
  useDevtoolsLayout
5435
+ };
5436
+ return applyVirtualTableState({
5437
+ ...nextState,
5438
+ tableWidth: shouldUseBalancedSplitTableWidth(nextState) ? getBalancedSplitTableWidth(nextState) : state.tableWidth
5217
5439
  });
5218
5440
  };
5219
5441
 
@@ -5254,7 +5476,8 @@ const loadEventsFromUri = async state => {
5254
5476
 
5255
5477
  const loadContent = async (state, savedState) => {
5256
5478
  await getPreference('chatDebug.autoRefresh');
5257
- const nextState = await loadEventsFromUri(restoreSavedState(state, savedState));
5479
+ const restoredState = restoreSavedState(state, savedState);
5480
+ const nextState = await loadEventsFromUri(restoredState);
5258
5481
  if (nextState.sessionId) {
5259
5482
  try {
5260
5483
  await registerUpdateListener(nextState.sessionId, rpcId, nextState.uid);
@@ -5359,7 +5582,7 @@ const getCss = state => {
5359
5582
  if (state.width >= state.largeBreakpoint) {
5360
5583
  topSize = 30;
5361
5584
  }
5362
- const tableColumnLayout = getTableColumnLayout(tableContentWidth, getVisibleTableColumns(state.tableColumns), state.tableColumnWidths);
5585
+ const tableColumnLayout = getTableColumnLayout(tableContentWidth, getVisibleTableColumns(state.tableColumns), state.tableColumns);
5363
5586
  const [tableColZeroWidth = 0, tableColOneWidth = 0, tableColTwoWidth = 0, tableColThreeWidth = 0, tableColFourWidth = 0] = tableColumnLayout.visibleColumnWidths;
5364
5587
  const resizerOneLeft = tableColumnLayout.resizerLefts[0] ?? 0;
5365
5588
  const resizerTwoLeft = tableColumnLayout.resizerLefts[1] ?? 0;
@@ -5384,7 +5607,7 @@ const getCss = state => {
5384
5607
  --ChatDebugViewPreviewScrollBarWidth: ${previewVirtualization.showScrollBar ? devtoolsTableScrollBarWidth : 0}px;
5385
5608
  --ChatDebugViewPreviewViewportHeight: ${previewVirtualization.viewportHeight}px;
5386
5609
  --ChatDebugViewDetailsWidth: ${detailsWidth}px;
5387
- --ChatDebugViewDurationColumnWidth: ${state.tableColumnWidths.duration}px;
5610
+ --ChatDebugViewDurationColumnWidth: ${getTableColumnWidth(state.tableColumns, Duration)}px;
5388
5611
  --ChatDebugViewTableRowHeight: ${devtoolsTableRowHeight}px;
5389
5612
  --ChatDebugViewTableScrollBarHeight: ${scrollBarHeight}px;
5390
5613
  --ChatDebugViewTableScrollBarOffset: ${scrollBarOffset}px;
@@ -5400,7 +5623,7 @@ const getCss = state => {
5400
5623
  --ChatDebugViewTimelineSelectionEndLeft: ${selectionEndPercent ?? 0}%;
5401
5624
  --ChatDebugViewTimelineSelectionStartLeft: ${selectionStartPercent ?? 0}%;
5402
5625
  --ChatDebugViewTopSize: ${topSize}px;
5403
- --ChatDebugViewTypeColumnWidth: ${state.tableColumnWidths.type}px;
5626
+ --ChatDebugViewTypeColumnWidth: ${getTableColumnWidth(state.tableColumns, Type)}px;
5404
5627
  padding: ${state.viewPadding}px;
5405
5628
  padding-right: 0;
5406
5629
  }
@@ -5565,6 +5788,14 @@ const getCss = state => {
5565
5788
  .ChatDebugViewHeadersCellName {
5566
5789
  font-weight: 500;
5567
5790
  }
5791
+
5792
+ .ChatDebugViewHeadersSectionInfo {
5793
+ color: var(--vscode-descriptionForeground, rgba(255, 255, 255, 0.7));
5794
+ font-size: 11px;
5795
+ line-height: 1.4;
5796
+ margin-top: 8px;
5797
+ }
5798
+
5568
5799
  .PreviewVirtualizedEditor {
5569
5800
  height: var(--ChatDebugViewPreviewViewportHeight);
5570
5801
  overflow: hidden;
@@ -5972,6 +6203,7 @@ const ChatDebugViewHeadersRowEven = 'ChatDebugViewHeadersRowEven';
5972
6203
  const ChatDebugViewHeadersRowOdd = 'ChatDebugViewHeadersRowOdd';
5973
6204
  const ChatDebugViewHeadersSection = 'ChatDebugViewHeadersSection';
5974
6205
  const ChatDebugViewHeadersSectionHeading = 'ChatDebugViewHeadersSectionHeading';
6206
+ const ChatDebugViewHeadersSectionInfo = 'ChatDebugViewHeadersSectionInfo';
5975
6207
  const ChatDebugViewHeadersTable = 'ChatDebugViewHeadersTable';
5976
6208
  const ChatDebugViewDevtoolsSplit = 'ChatDebugViewDevtoolsSplit';
5977
6209
  const ChatDebugViewEmpty = 'ChatDebugViewEmpty';
@@ -6315,6 +6547,87 @@ const getNormalizedDetailTabs = (selectedEvent, detailTabs) => {
6315
6547
  return createDetailTabs(getSelectedDetailTab(detailTabs), selectedEvent);
6316
6548
  };
6317
6549
 
6550
+ const getHeaderRowNodes = (item, index) => {
6551
+ return [{
6552
+ childCount: 2,
6553
+ className: mergeClassNames(ChatDebugViewHeadersRow, index % 2 === 0 ? ChatDebugViewHeadersRowOdd : ChatDebugViewHeadersRowEven),
6554
+ type: Li
6555
+ }, {
6556
+ childCount: 1,
6557
+ className: mergeClassNames(ChatDebugViewHeadersCell, ChatDebugViewHeadersCellName),
6558
+ type: Div
6559
+ }, text(item.key), {
6560
+ childCount: 1,
6561
+ className: mergeClassNames(ChatDebugViewHeadersCell, ChatDebugViewHeadersCellValue),
6562
+ type: Div
6563
+ }, text(item.value)];
6564
+ };
6565
+
6566
+ const getHeadersTableNodes = items => {
6567
+ const headerRows = [];
6568
+ for (const [index, item] of items.entries()) {
6569
+ headerRows.push(...getHeaderRowNodes(item, index));
6570
+ }
6571
+ return [{
6572
+ childCount: items.length,
6573
+ className: ChatDebugViewHeadersTable,
6574
+ type: Ul
6575
+ }, ...headerRows];
6576
+ };
6577
+
6578
+ const accessControlExposeHeadersText = 'Access-Control-Expose-Headers';
6579
+ const accessControlExposeHeadersUrl = 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers';
6580
+ const getInfoNodes = section => {
6581
+ if (section.key !== ResponseHeaders) {
6582
+ return [text(section.info)];
6583
+ }
6584
+ const linkIndex = section.info.indexOf(accessControlExposeHeadersText);
6585
+ if (linkIndex === -1) {
6586
+ return [text(section.info)];
6587
+ }
6588
+ const infoNodes = [];
6589
+ const prefix = section.info.slice(0, linkIndex);
6590
+ const suffix = section.info.slice(linkIndex + accessControlExposeHeadersText.length);
6591
+ if (prefix) {
6592
+ infoNodes.push(text(prefix));
6593
+ }
6594
+ infoNodes.push({
6595
+ childCount: 1,
6596
+ href: accessControlExposeHeadersUrl,
6597
+ rel: 'noopener noreferrer',
6598
+ target: '_blank',
6599
+ type: A
6600
+ });
6601
+ infoNodes.push(text(accessControlExposeHeadersText));
6602
+ if (suffix) {
6603
+ infoNodes.push(text(suffix));
6604
+ }
6605
+ return infoNodes;
6606
+ };
6607
+ const getHeaderSectionNodes = section => {
6608
+ const hasInfoMessage = section.isExpanded && section.info !== '';
6609
+ const childCount = section.isExpanded ? 2 + Number(hasInfoMessage) : 1;
6610
+ const infoNodes = hasInfoMessage ? getInfoNodes(section) : [];
6611
+ return [{
6612
+ childCount,
6613
+ className: ChatDebugViewHeadersSection,
6614
+ type: Div
6615
+ }, {
6616
+ ariaExpanded: section.isExpanded,
6617
+ childCount: 1,
6618
+ className: ChatDebugViewHeadersSectionHeading,
6619
+ name: ToggleHeadersSection,
6620
+ onChange: HandleFilterInput,
6621
+ onClick: HandleFilterInput,
6622
+ type: Button$1,
6623
+ value: section.key
6624
+ }, text(section.heading), ...(section.isExpanded ? getHeadersTableNodes(section.items) : []), ...(hasInfoMessage ? [{
6625
+ childCount: infoNodes.length,
6626
+ className: ChatDebugViewHeadersSectionInfo,
6627
+ type: Div
6628
+ }, ...infoNodes] : [])];
6629
+ };
6630
+
6318
6631
  const httpStatusLabels = {
6319
6632
  100: 'Continue',
6320
6633
  101: 'Switching Protocols',
@@ -6408,9 +6721,7 @@ const formatHttpStatusCode = value => {
6408
6721
  const isHeadersRecord = value => {
6409
6722
  return typeof value === 'object' && value !== null && !Array.isArray(value);
6410
6723
  };
6411
- const isNonEmptyString = value => {
6412
- return typeof value === 'string' && value.length > 0;
6413
- };
6724
+
6414
6725
  const getStatusCodeValue = selectedEvent => {
6415
6726
  if (!selectedEvent) {
6416
6727
  return undefined;
@@ -6427,6 +6738,36 @@ const getStatusCodeValue = selectedEvent => {
6427
6738
  }
6428
6739
  return undefined;
6429
6740
  };
6741
+
6742
+ const isNonEmptyString = value => {
6743
+ return typeof value === 'string' && value.length > 0;
6744
+ };
6745
+
6746
+ const getGeneralEntries = selectedEvent => {
6747
+ if (!selectedEvent) {
6748
+ return [];
6749
+ }
6750
+ const entries = [];
6751
+ if (isNonEmptyString(selectedEvent.url)) {
6752
+ entries.push([requestUrl(), selectedEvent.url]);
6753
+ }
6754
+ if (isNonEmptyString(selectedEvent.method)) {
6755
+ entries.push([requestMethod(), selectedEvent.method]);
6756
+ }
6757
+ const statusCode$1 = getStatusCodeValue(selectedEvent);
6758
+ if (statusCode$1 !== undefined && statusCode$1 !== '') {
6759
+ entries.push([statusCode(), formatHttpStatusCode(statusCode$1)]);
6760
+ }
6761
+ return entries;
6762
+ };
6763
+
6764
+ const getHeaders = value => {
6765
+ if (!isHeadersRecord(value)) {
6766
+ return [];
6767
+ }
6768
+ return Object.entries(value);
6769
+ };
6770
+
6430
6771
  const stringifyHeaderValue = value => {
6431
6772
  try {
6432
6773
  return JSON.stringify(value, (_key, nestedValue) => {
@@ -6439,6 +6780,7 @@ const stringifyHeaderValue = value => {
6439
6780
  return '[unserializable]';
6440
6781
  }
6441
6782
  };
6783
+
6442
6784
  const getHeaderValueText = value => {
6443
6785
  if (typeof value === 'string') {
6444
6786
  return value;
@@ -6460,87 +6802,44 @@ const getHeaderValueText = value => {
6460
6802
  }
6461
6803
  return stringifyHeaderValue(value);
6462
6804
  };
6463
- const getHeaders = value => {
6464
- if (!isHeadersRecord(value)) {
6465
- return [];
6466
- }
6467
- return Object.entries(value);
6468
- };
6469
- const getGeneralEntries = selectedEvent => {
6470
- if (!selectedEvent) {
6471
- return [];
6472
- }
6473
- const entries = [];
6474
- if (isNonEmptyString(selectedEvent.url)) {
6475
- entries.push([requestUrl(), selectedEvent.url]);
6476
- }
6477
- if (isNonEmptyString(selectedEvent.method)) {
6478
- entries.push([requestMethod(), selectedEvent.method]);
6479
- }
6480
- const statusCode$1 = getStatusCodeValue(selectedEvent);
6481
- if (statusCode$1 !== undefined && statusCode$1 !== '') {
6482
- entries.push([statusCode(), formatHttpStatusCode(statusCode$1)]);
6483
- }
6484
- return entries;
6805
+
6806
+ const toHeaderSectionItems = entries => {
6807
+ return entries.map(([key, value]) => ({
6808
+ key,
6809
+ value: getHeaderValueText(value)
6810
+ }));
6485
6811
  };
6486
- const getHeaderRowNodes = (headerName, headerValue, index) => {
6487
- return [{
6488
- childCount: 2,
6489
- className: mergeClassNames(ChatDebugViewHeadersRow, index % 2 === 0 ? ChatDebugViewHeadersRowOdd : ChatDebugViewHeadersRowEven),
6490
- type: Li
6812
+ const getVisibleHeaderSections = (selectedEvent, collapsedHeaderSections = []) => {
6813
+ const sections = [{
6814
+ heading: general(),
6815
+ info: '',
6816
+ items: toHeaderSectionItems(getGeneralEntries(selectedEvent)),
6817
+ key: General
6491
6818
  }, {
6492
- childCount: 1,
6493
- className: mergeClassNames(ChatDebugViewHeadersCell, ChatDebugViewHeadersCellName),
6494
- type: Div
6495
- }, text(headerName), {
6496
- childCount: 1,
6497
- className: mergeClassNames(ChatDebugViewHeadersCell, ChatDebugViewHeadersCellValue),
6498
- type: Div
6499
- }, text(getHeaderValueText(headerValue))];
6500
- };
6501
- const getHeadersTableNodes = headers => {
6502
- const headerRows = [];
6503
- for (const [index, [headerName, headerValue]] of headers.entries()) {
6504
- headerRows.push(...getHeaderRowNodes(headerName, headerValue, index));
6505
- }
6506
- return [{
6507
- childCount: headers.length,
6508
- className: ChatDebugViewHeadersTable,
6509
- type: Ul
6510
- }, ...headerRows];
6511
- };
6512
- const getHeaderSectionNodes = (section, label, headers, collapsedHeaderSections) => {
6513
- const isCollapsed = collapsedHeaderSections.includes(section);
6514
- return [{
6515
- childCount: isCollapsed ? 1 : 2,
6516
- className: ChatDebugViewHeadersSection,
6517
- type: Div
6819
+ heading: responseHeaders(),
6820
+ info: responseHeadersInfo(),
6821
+ items: toHeaderSectionItems(getHeaders(isHeadersRecord(selectedEvent?.endValue) ? selectedEvent.endValue.headers : undefined)),
6822
+ key: ResponseHeaders
6518
6823
  }, {
6519
- childCount: 1,
6520
- className: ChatDebugViewHeadersSectionHeading,
6521
- name: ToggleHeadersSection,
6522
- onChange: HandleFilterInput,
6523
- onClick: HandleFilterInput,
6524
- type: Button$1,
6525
- value: section
6526
- }, text(label), ...(isCollapsed ? [] : getHeadersTableNodes(headers))];
6824
+ heading: requestHeaders(),
6825
+ info: '',
6826
+ items: toHeaderSectionItems(getHeaders(selectedEvent?.headers)),
6827
+ key: RequestHeaders
6828
+ }];
6829
+ return sections.filter(section => section.items.length > 0).map(section => ({
6830
+ ...section,
6831
+ isExpanded: !collapsedHeaderSections.includes(section.key)
6832
+ }));
6527
6833
  };
6834
+
6528
6835
  const getHeadersContentNodes = (responseEventNodes, selectedEvent, collapsedHeaderSections = []) => {
6529
- const generalEntries = getGeneralEntries(selectedEvent);
6530
- const requestHeaders$1 = getHeaders(selectedEvent?.headers);
6531
- const responseHeaders$1 = getHeaders(isHeadersRecord(selectedEvent?.endValue) ? selectedEvent.endValue.headers : undefined);
6532
- if (generalEntries.length === 0 && requestHeaders$1.length === 0 && responseHeaders$1.length === 0) {
6836
+ const sections = getVisibleHeaderSections(selectedEvent, collapsedHeaderSections);
6837
+ if (sections.length === 0) {
6533
6838
  return responseEventNodes;
6534
6839
  }
6535
6840
  const nodes = [];
6536
- if (generalEntries.length > 0) {
6537
- nodes.push(...getHeaderSectionNodes(General, general(), generalEntries, collapsedHeaderSections));
6538
- }
6539
- if (requestHeaders$1.length > 0) {
6540
- nodes.push(...getHeaderSectionNodes(RequestHeaders, requestHeaders(), requestHeaders$1, collapsedHeaderSections));
6541
- }
6542
- if (responseHeaders$1.length > 0) {
6543
- nodes.push(...getHeaderSectionNodes(ResponseHeaders, responseHeaders(), responseHeaders$1, collapsedHeaderSections));
6841
+ for (const section of sections) {
6842
+ nodes.push(...getHeaderSectionNodes(section));
6544
6843
  }
6545
6844
  return nodes;
6546
6845
  };
@@ -7841,59 +8140,42 @@ const getSplitViewDom = (splitChildCount, eventsClassName, tableNodes, sashNodes
7841
8140
  }, ...tableNodes, ...sashNodes, ...detailsNodes];
7842
8141
  };
7843
8142
 
7844
- const formatTimelineMilliseconds = value => {
7845
- return `${Math.round(value * 1000)}ms`;
7846
- };
7847
-
7848
- const formatTimelineSeconds = value => {
7849
- if (Number.isInteger(value)) {
7850
- return `${value}s`;
7851
- }
7852
- return `${Number(value.toFixed(1))}s`;
7853
- };
7854
-
7855
- const getEndTime = event => {
7856
- return event.ended ?? event.endTime ?? event.timestamp;
7857
- };
7858
-
7859
- const getStartTime = event => {
7860
- return event.started ?? event.startTime ?? event.timestamp;
7861
- };
7862
-
7863
- const formatTableSummaryDuration = durationMs => {
7864
- if (durationMs < 1000) {
7865
- return formatTimelineMilliseconds(durationMs / 1000);
7866
- }
7867
- return formatTimelineSeconds(durationMs / 1000);
7868
- };
7869
- const getTableSummary = events => {
7870
- let minStart = Number.POSITIVE_INFINITY;
7871
- let maxEnd = Number.NEGATIVE_INFINITY;
7872
- for (const event of events) {
7873
- const startTime = toTimeNumber(getStartTime(event));
7874
- const endTime = toTimeNumber(getEndTime(event));
7875
- if (typeof startTime === 'number' && Number.isFinite(startTime)) {
7876
- minStart = Math.min(minStart, startTime);
7877
- }
7878
- if (typeof endTime === 'number' && Number.isFinite(endTime)) {
7879
- maxEnd = Math.max(maxEnd, endTime);
7880
- }
7881
- }
7882
- const durationMs = Number.isFinite(minStart) && Number.isFinite(maxEnd) ? Math.max(0, maxEnd - minStart) : 0;
7883
- return tableSummary(events.length, formatTableSummaryDuration(durationMs));
7884
- };
7885
-
7886
8143
  const tableSummaryNode = {
7887
- childCount: 1,
8144
+ childCount: 0,
7888
8145
  className: TableSummary,
7889
8146
  role: Status,
7890
8147
  type: Div
7891
8148
  };
7892
- const getTableSummaryDom = summary => {
7893
- if (!summary) {
8149
+ const tableSummaryItemNode = {
8150
+ childCount: 1,
8151
+ type: Span
8152
+ };
8153
+ const tableSummaryNodes = new Map();
8154
+ const getTableSummaryNode = childCount => {
8155
+ const existing = tableSummaryNodes.get(childCount);
8156
+ if (existing) {
8157
+ return existing;
8158
+ }
8159
+ const node = {
8160
+ ...tableSummaryNode,
8161
+ childCount
8162
+ };
8163
+ tableSummaryNodes.set(childCount, node);
8164
+ return node;
8165
+ };
8166
+ const getTableSummaryDom = summaries => {
8167
+ const nonEmptySummaries = summaries.filter(Boolean);
8168
+ if (nonEmptySummaries.length === 0) {
7894
8169
  return [];
7895
8170
  }
7896
- return [tableSummaryNode, text(summary)];
8171
+ const nodes = [getTableSummaryNode(nonEmptySummaries.length * 2 - 1)];
8172
+ for (let i = 0; i < nonEmptySummaries.length; i++) {
8173
+ nodes.push(tableSummaryItemNode, text(nonEmptySummaries[i]));
8174
+ if (i < nonEmptySummaries.length - 1) {
8175
+ nodes.push(text(' | '));
8176
+ }
8177
+ }
8178
+ return nodes;
7897
8179
  };
7898
8180
 
7899
8181
  const getTableBodyDom = (rowNodes, eventCount) => {
@@ -7952,7 +8234,7 @@ const getTableHeaderDom = (visibleTableColumns = defaultVisibleTableColumns, tab
7952
8234
  }, ...getHeaderCellNodes(visibleTableColumns, tableColumns)];
7953
8235
  };
7954
8236
 
7955
- const getTableDom = (rowNodes, eventCount, visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns(), summary = '', focus = 0) => {
8237
+ const getTableDom = (rowNodes, eventCount, visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns(), summaries = [], focus = 0) => {
7956
8238
  return [{
7957
8239
  childCount: 3,
7958
8240
  className: Table,
@@ -8009,7 +8291,7 @@ const getTableScrollBarDom = visible => {
8009
8291
  }];
8010
8292
  };
8011
8293
 
8012
- const getTableWrapperDom = (rowNodes, eventCount, visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns(), summary = '', focus = 0, className = '', role = 'none', showScrollBar = false) => {
8294
+ const getTableWrapperDom = (rowNodes, eventCount, visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns(), summaries = [], focus = 0, className = '', role = 'none', showScrollBar = false) => {
8013
8295
  const tableWrapperClassName = mergeClassNames(TableWrapper, focus === FocusChatDebugTable ? FocusOutline : '', className);
8014
8296
  const tableWrapperNode = {
8015
8297
  childCount: showScrollBar ? 3 : 2,
@@ -8020,16 +8302,16 @@ const getTableWrapperDom = (rowNodes, eventCount, visibleTableColumns = defaultV
8020
8302
  role
8021
8303
  } : {})
8022
8304
  };
8023
- return [tableWrapperNode, ...getTableDom(rowNodes, eventCount, visibleTableColumns, tableColumns, summary, focus), ...getTableResizersDom(visibleTableColumns), ...getTableScrollBarDom(showScrollBar)];
8305
+ return [tableWrapperNode, ...getTableDom(rowNodes, eventCount, visibleTableColumns, tableColumns, summaries, focus), ...getTableResizersDom(visibleTableColumns), ...getTableScrollBarDom(showScrollBar)];
8024
8306
  };
8025
8307
 
8026
- const getTableWrapperWrapperDom = (rowNodes, eventCount, visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns(), summary = '', focus = 0, className = '', role = 'none', showScrollBar = false) => {
8027
- const tableSummaryNodes = getTableSummaryDom(summary);
8308
+ const getTableWrapperWrapperDom = (rowNodes, eventCount, visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns(), summaries = [], focus = 0, className = '', role = 'none', showScrollBar = false) => {
8309
+ const tableSummaryNodes = getTableSummaryDom(summaries);
8028
8310
  return [{
8029
8311
  childCount: tableSummaryNodes.length === 0 ? 1 : 2,
8030
8312
  className: TableWrapperWrapper,
8031
8313
  type: Div
8032
- }, ...getTableWrapperDom(rowNodes, eventCount, visibleTableColumns, tableColumns, summary, focus, className, role, showScrollBar), ...tableSummaryNodes];
8314
+ }, ...getTableWrapperDom(rowNodes, eventCount, visibleTableColumns, tableColumns, summaries, focus, className, role, showScrollBar), ...tableSummaryNodes];
8033
8315
  };
8034
8316
 
8035
8317
  const getBucketUnitDom = (unitCount, presetValue) => {
@@ -8202,7 +8484,7 @@ const getTimelineDom = (timelineInfo, hoverPercent = null) => {
8202
8484
  }, ...selectionNodes];
8203
8485
  };
8204
8486
 
8205
- 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, previewTextDeltaY = 0, previewTextViewportHeight = 0, minLineY = 0, maxLineY = events.length, collapsedHeaderSections = []) => {
8487
+ 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, previewTextDeltaY = 0, previewTextViewportHeight = 0, minLineY = 0, maxLineY = events.length, collapsedHeaderSections = [], summaries = getTableSummaries(events)) => {
8206
8488
  const visibleEvents = events.slice(minLineY, maxLineY);
8207
8489
  const rows = createDevtoolsRows(visibleEvents, selectedEventIndex, minLineY);
8208
8490
  const rowNodes = getDevtoolsRows(rows, visibleTableColumns);
@@ -8224,9 +8506,8 @@ const getDevtoolsDom = (events, selectedEvent, selectedEventIndex, timelineEvent
8224
8506
  const responseEventNodes = selectedEvent ? getEventNode(getResponseEvent(selectedEvent)) : [];
8225
8507
  const hasSelectedEvent = !!selectedEvent;
8226
8508
  const eventsClassName = getEventsClassName(hasSelectedEvent);
8227
- const summary = getTableSummary(events);
8228
8509
  const showScrollBar = visibleEvents.length < events.length;
8229
- const tableNodes = events.length === 0 ? getEmptyStateDom(emptyMessage) : getTableWrapperWrapperDom(rowNodes, visibleEvents.length, visibleTableColumns, tableColumns, summary, focus, '', '', showScrollBar);
8510
+ const tableNodes = events.length === 0 ? getEmptyStateDom(emptyMessage) : getTableWrapperWrapperDom(rowNodes, visibleEvents.length, visibleTableColumns, tableColumns, summaries, focus, '', '', showScrollBar);
8230
8511
  const detailsNodes = getDetailsDom(previewEventNodes, payloadEventNodes, responseEventNodes, selectedEvent, detailTabs, previewTextCursorRowIndex, previewTextCursorColumnIndex, previewVirtualizationOptions, collapsedHeaderSections);
8231
8512
  const sashNodes = getSashNodesDom(hasSelectedEvent);
8232
8513
  const splitChildCount = hasSelectedEvent ? 3 : 1;
@@ -8281,7 +8562,7 @@ const getEventCategoryFilterDescription = eventCategoryFilters => {
8281
8562
  }
8282
8563
  return eventCategoryFilters.map(eventCategoryFilter => getEventCategoryFilterLabel(eventCategoryFilter).toLowerCase()).join(', ');
8283
8564
  };
8284
- 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, previewTextDeltaY = 0, previewTextViewportHeight = 0, collapsedHeaderSections = []) => {
8565
+ 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, previewTextDeltaY = 0, previewTextViewportHeight = 0, collapsedHeaderSections = [], summaries = getTableSummaries(events)) => {
8285
8566
  if (errorMessage) {
8286
8567
  return getDebugErrorDom(errorMessage);
8287
8568
  }
@@ -8305,7 +8586,7 @@ const getChatDebugViewDom = (errorMessage, filterValue, eventCategoryFilters, ca
8305
8586
  const emptyMessage = getEmptyMessage(events.length, hasFilterValue, useNoToolCallEventsMessage, noFilteredEventsMessage);
8306
8587
  const safeSelectedEventIndex = selectedEventIndex === null || selectedEventIndex < 0 || selectedEventIndex >= events.length ? null : selectedEventIndex;
8307
8588
  if (useDevtoolsLayout) {
8308
- const devtoolsDom = getDevtoolsDom(events, selectedEvent, safeSelectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds, detailTabs, visibleTableColumns, tableColumns, timelineInfo, timelineHoverPercent, focus, previewTextCursorRowIndex, previewTextCursorColumnIndex, previewTextDeltaY, previewTextViewportHeight, minLineY, maxLineY, collapsedHeaderSections);
8589
+ const devtoolsDom = getDevtoolsDom(events, selectedEvent, safeSelectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds, detailTabs, visibleTableColumns, tableColumns, timelineInfo, timelineHoverPercent, focus, previewTextCursorRowIndex, previewTextCursorColumnIndex, previewTextDeltaY, previewTextViewportHeight, minLineY, maxLineY, collapsedHeaderSections, summaries);
8309
8590
  const devtoolsContentNodes = devtoolsDom.slice(1);
8310
8591
  const topLevelNodes = [...getDebugViewTopDom(filterValue, useDevtoolsLayout, categoryFilters), ...devtoolsContentNodes];
8311
8592
  const rootChildCount = getTopLevelChildCount(topLevelNodes);
@@ -8341,7 +8622,7 @@ const renderItems = (oldState, newState) => {
8341
8622
  }
8342
8623
  const filteredEvents = getCurrentEvents$1(newState);
8343
8624
  const previewTextViewportHeight = getPreviewTextViewportHeight(newState);
8344
- 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, newState.previewTextDeltaY, previewTextViewportHeight, newState.collapsedHeaderSections);
8625
+ 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, newState.previewTextDeltaY, previewTextViewportHeight, newState.collapsedHeaderSections, newState.summaries);
8345
8626
  return [SetDom2, newState.uid, dom];
8346
8627
  };
8347
8628
 
@@ -8547,15 +8828,20 @@ const rerender = state => {
8547
8828
  };
8548
8829
 
8549
8830
  const resetTableColumns = state => {
8550
- if (getVisibleTableColumns(state.tableColumns).join(',') === defaultVisibleTableColumns.join(',') && isSameTableColumnWidths(state.tableColumnWidths, defaultTableColumnWidths) && state.sortColumn === '' && state.sortDescending === false) {
8831
+ const {
8832
+ sortColumn,
8833
+ sortDescending,
8834
+ tableColumns
8835
+ } = state;
8836
+ const defaultTableColumns = createTableColumns();
8837
+ if (getVisibleTableColumns(tableColumns).join(',') === defaultVisibleTableColumns.join(',') && isSameTableColumnWidths(getTableColumnWidths(tableColumns), getTableColumnWidths(defaultTableColumns)) && sortColumn === '' && sortDescending === false) {
8551
8838
  return state;
8552
8839
  }
8553
8840
  return {
8554
8841
  ...state,
8555
8842
  sortColumn: '',
8556
8843
  sortDescending: false,
8557
- tableColumns: createTableColumns(),
8558
- tableColumnWidths: defaultTableColumnWidths
8844
+ tableColumns: defaultTableColumns
8559
8845
  };
8560
8846
  };
8561
8847
 
@@ -8564,9 +8850,10 @@ const handleResize = (state, dimensions) => {
8564
8850
  ...state,
8565
8851
  ...dimensions
8566
8852
  };
8853
+ const tableWidth = shouldUseBalancedSplitTableWidth(nextState) ? getBalancedSplitTableWidth(nextState) : clampTableWidth(nextState, state.tableWidth);
8567
8854
  return applyVirtualTableState({
8568
8855
  ...nextState,
8569
- tableWidth: clampTableWidth(nextState, state.tableWidth)
8856
+ tableWidth
8570
8857
  });
8571
8858
  };
8572
8859
 
@@ -8588,7 +8875,6 @@ const saveState = state => {
8588
8875
  selectedEventId,
8589
8876
  sessionId,
8590
8877
  tableColumns,
8591
- tableColumnWidths,
8592
8878
  timelineEndSeconds,
8593
8879
  timelineStartSeconds
8594
8880
  } = state;
@@ -8599,7 +8885,7 @@ const saveState = state => {
8599
8885
  selectedDetailTab: getSelectedDetailTab(detailTabs),
8600
8886
  selectedEventId,
8601
8887
  sessionId,
8602
- tableColumnWidths,
8888
+ tableColumnWidths: getTableColumnWidths(tableColumns),
8603
8889
  timelineEndSeconds,
8604
8890
  timelineStartSeconds,
8605
8891
  visibleTableColumns: getVisibleTableColumns(tableColumns)
@@ -8673,12 +8959,15 @@ const setSessionId = async (state, sessionId) => {
8673
8959
  };
8674
8960
 
8675
8961
  const toggleTableColumnVisibility = (state, column) => {
8962
+ const {
8963
+ tableColumns
8964
+ } = state;
8676
8965
  if (!isTableColumn(column)) {
8677
8966
  return state;
8678
8967
  }
8679
8968
  return {
8680
8969
  ...state,
8681
- tableColumns: state.tableColumns.map(tableColumn => {
8970
+ tableColumns: tableColumns.map(tableColumn => {
8682
8971
  if (tableColumn.name !== column) {
8683
8972
  return tableColumn;
8684
8973
  }
@@ -8733,6 +9022,7 @@ const commandMap = {
8733
9022
  'ChatDebug.handleTableResizerPointerMove': wrapCommand(handleTableResizerPointerMove),
8734
9023
  'ChatDebug.handleTableResizerPointerUp': wrapCommand(handleTableResizerPointerUp),
8735
9024
  'ChatDebug.handleTableRowCopy': wrapCommand(handleTableRowCopy),
9025
+ 'ChatDebug.handleTableRowCopyAsFetch': wrapCommand(handleTableRowCopyAsFetch),
8736
9026
  'ChatDebug.handleTableRowDoubleClick': wrapCommand(handleTableRowDoubleClick),
8737
9027
  'ChatDebug.handleTableRowOpenInNewTab': wrapCommand(handleTableRowOpenInNewTab),
8738
9028
  'ChatDebug.handleTableScrollBarPointerDown': wrapCommand(handleTableScrollBarPointerDown),