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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1117,11 +1117,17 @@ const create$2 = rpcId => {
1117
1117
  };
1118
1118
  };
1119
1119
 
1120
+ const ListBox = 'listbox';
1121
+ const Option = 'option';
1122
+ const Tab = 'tab';
1123
+
1120
1124
  const Button$1 = 1;
1125
+ const Col = 2;
1126
+ const ColGroup = 3;
1121
1127
  const Div = 4;
1122
1128
  const Input = 6;
1123
1129
  const Span = 8;
1124
- const Table = 9;
1130
+ const Table$1 = 9;
1125
1131
  const TBody = 10;
1126
1132
  const Td = 11;
1127
1133
  const Text = 12;
@@ -1132,6 +1138,7 @@ const Img = 17;
1132
1138
  const H2 = 22;
1133
1139
  const Section = 41;
1134
1140
  const Search = 42;
1141
+ const P = 50;
1135
1142
  const Reference = 100;
1136
1143
 
1137
1144
  const Button = 'event.button';
@@ -1147,8 +1154,10 @@ const Unchecked = 3;
1147
1154
  const ChatStorageWorker = 6003;
1148
1155
  const RendererWorker = 1;
1149
1156
 
1157
+ const FocusSelector = 'Viewlet.focusSelector';
1150
1158
  const SetCss = 'Viewlet.setCss';
1151
1159
  const SetDom2 = 'Viewlet.setDom2';
1160
+ const SetFocusContext = 'Viewlet.setFocusContext';
1152
1161
  const SetPatches = 'Viewlet.setPatches';
1153
1162
 
1154
1163
  const {
@@ -1374,7 +1383,7 @@ const All$1 = 'All';
1374
1383
  const CloseDetails$1 = 'Close details';
1375
1384
  const Copy = 'Copy';
1376
1385
  const DetailSections = 'Detail sections';
1377
- const Duration$1 = 'Duration';
1386
+ const Duration$1 = 'Time';
1378
1387
  const Ended = 'Ended';
1379
1388
  const FailedToLoadChatDebugSession = 'Failed to load chat debug session "{PH1}". Please try again.';
1380
1389
  const FailedToLoadChatDebugSessionWithError = 'Failed to load chat debug session "{PH1}": {PH2}';
@@ -1398,8 +1407,10 @@ const ResetColumns = 'Reset columns';
1398
1407
  const Response$1 = 'Response';
1399
1408
  const SecondsRange = '{PH1}s-{PH2}s';
1400
1409
  const Started = 'Started';
1401
- const Status$1 = 'Status';
1410
+ const Status$2 = 'Status';
1402
1411
  const Stream$1 = 'Stream';
1412
+ const TableSummaryPlural = '{PH1} events, {PH2} from start to finish';
1413
+ const TableSummarySingular = '{PH1} event, {PH2} from start to finish';
1403
1414
  const Timing$1 = 'Timing';
1404
1415
  const ToSeconds = 'to {PH1}s';
1405
1416
  const Tools$1 = 'Tools';
@@ -1413,7 +1424,7 @@ const copy = () => {
1413
1424
  return i18nString(Copy);
1414
1425
  };
1415
1426
  const status = () => {
1416
- return i18nString(Status$1);
1427
+ return i18nString(Status$2);
1417
1428
  };
1418
1429
  const all = () => {
1419
1430
  return i18nString(All$1);
@@ -1516,6 +1527,12 @@ const stream = () => {
1516
1527
  const timing = () => {
1517
1528
  return i18nString(Timing$1);
1518
1529
  };
1530
+ const tableSummary = (eventCount, duration) => {
1531
+ return i18nString(eventCount === 1 ? TableSummarySingular : TableSummaryPlural, {
1532
+ PH1: String(eventCount),
1533
+ PH2: duration
1534
+ });
1535
+ };
1519
1536
  const toSeconds = seconds => {
1520
1537
  return i18nString(ToSeconds, {
1521
1538
  PH1: seconds
@@ -1632,13 +1649,9 @@ const selectDetailTab$1 = (detailTabs, selectedDetailTab) => {
1632
1649
  return detailTabs;
1633
1650
  }
1634
1651
  return detailTabs.map(detailTab => {
1635
- const isSelectedProperty = detailTab.name === selectedDetailTab;
1636
- if (detailTab.isSelected === isSelectedProperty) {
1637
- return detailTab;
1638
- }
1639
1652
  return {
1640
1653
  ...detailTab,
1641
- isSelected: isSelectedProperty
1654
+ isSelected: detailTab.name === selectedDetailTab
1642
1655
  };
1643
1656
  });
1644
1657
  };
@@ -1765,18 +1778,18 @@ const parseFilterValue = filterValue => {
1765
1778
 
1766
1779
  const Type = 'type';
1767
1780
  const Duration = 'duration';
1768
- const Status = 'status';
1769
- const tableColumnNames = [Type, Duration, Status];
1781
+ const Status$1 = 'status';
1782
+ const tableColumnNames = [Type, Status$1, Duration];
1770
1783
  const createTableColumns = () => {
1771
1784
  return [{
1772
1785
  label: type(),
1773
1786
  name: Type
1787
+ }, {
1788
+ label: status(),
1789
+ name: Status$1
1774
1790
  }, {
1775
1791
  label: duration(),
1776
1792
  name: Duration
1777
- }, {
1778
- label: status(),
1779
- name: Status
1780
1793
  }];
1781
1794
  };
1782
1795
  const defaultVisibleTableColumns = tableColumnNames;
@@ -1798,7 +1811,7 @@ const getTableColumnLabel = (tableColumns, name) => {
1798
1811
  switch (name) {
1799
1812
  case Duration:
1800
1813
  return duration();
1801
- case Status:
1814
+ case Status$1:
1802
1815
  return status();
1803
1816
  case Type:
1804
1817
  return type();
@@ -1840,7 +1853,14 @@ const getTableWidthFromClientX = (viewX, width, clientX) => {
1840
1853
  return clampTableWidth(width, nextTableWidth);
1841
1854
  };
1842
1855
 
1843
- const minimumTableColumnWidth = 80;
1856
+ const minimumTableColumnWidths = {
1857
+ [Duration]: 80,
1858
+ [Status$1]: 56,
1859
+ [Type]: 80
1860
+ };
1861
+ const getMinimumTableColumnWidth = column => {
1862
+ return minimumTableColumnWidths[column];
1863
+ };
1844
1864
 
1845
1865
  const getTableColumnLayout = (tableWidth, visibleTableColumns, tableColumnWidths) => {
1846
1866
  const visibleColumns = getOrderedVisibleTableColumns(visibleTableColumns);
@@ -1854,19 +1874,19 @@ const getTableColumnLayout = (tableWidth, visibleTableColumns, tableColumnWidths
1854
1874
  }
1855
1875
  const visibleColumnWidths = [];
1856
1876
  let remainingWidth = tableWidth;
1857
- let remainingColumnCount = visibleColumns.length;
1858
1877
  for (let index = 0; index < visibleColumns.length; index++) {
1859
1878
  const column = visibleColumns[index];
1860
1879
  if (index === visibleColumns.length - 1) {
1861
1880
  visibleColumnWidths.push(Math.max(0, remainingWidth));
1862
1881
  continue;
1863
1882
  }
1864
- const maxWidth = Math.max(minimumTableColumnWidth, remainingWidth - minimumTableColumnWidth * (remainingColumnCount - 1));
1883
+ const minimumWidth = getMinimumTableColumnWidth(column);
1884
+ const minimumRemainingWidth = visibleColumns.slice(index + 1).reduce((total, remainingColumn) => total + getMinimumTableColumnWidth(remainingColumn), 0);
1885
+ const maxWidth = Math.max(minimumWidth, remainingWidth - minimumRemainingWidth);
1865
1886
  const preferredWidth = tableColumnWidths[column];
1866
- const clampedWidth = Math.max(minimumTableColumnWidth, Math.min(preferredWidth, maxWidth));
1887
+ const clampedWidth = Math.max(minimumWidth, Math.min(preferredWidth, maxWidth));
1867
1888
  visibleColumnWidths.push(clampedWidth);
1868
1889
  remainingWidth -= clampedWidth;
1869
- remainingColumnCount -= 1;
1870
1890
  }
1871
1891
  const resizerLefts = [];
1872
1892
  let cumulativeWidth = 0;
@@ -1890,11 +1910,12 @@ const getResizedTableColumnWidths = (width, tableWidth, visibleTableColumns, tab
1890
1910
  }
1891
1911
  const boundaryIndex = resizerDownId - 1;
1892
1912
  const precedingWidth = layout.visibleColumnWidths.slice(0, boundaryIndex).reduce((total, current) => total + current, 0);
1893
- const remainingVisibleColumnCount = layout.visibleColumns.length - boundaryIndex - 1;
1894
- const maxWidth = Math.max(minimumTableColumnWidth, clampedTableWidth - precedingWidth - minimumTableColumnWidth * remainingVisibleColumnCount);
1895
- const nextWidth = clientX - viewX - leftPadding - precedingWidth;
1896
- const clampedWidth = Math.max(minimumTableColumnWidth, Math.min(nextWidth, maxWidth));
1897
1913
  const resizedColumn = layout.visibleColumns[boundaryIndex];
1914
+ const minimumWidth = getMinimumTableColumnWidth(resizedColumn);
1915
+ const minimumRemainingWidth = layout.visibleColumns.slice(boundaryIndex + 1).reduce((total, column) => total + getMinimumTableColumnWidth(column), 0);
1916
+ const maxWidth = Math.max(minimumWidth, clampedTableWidth - precedingWidth - minimumRemainingWidth);
1917
+ const nextWidth = clientX - viewX - leftPadding - precedingWidth;
1918
+ const clampedWidth = Math.max(minimumWidth, Math.min(nextWidth, maxWidth));
1898
1919
  return {
1899
1920
  ...tableColumnWidths,
1900
1921
  [resizedColumn]: clampedWidth
@@ -2127,8 +2148,11 @@ const createDefaultState = () => {
2127
2148
  events: [],
2128
2149
  eventStoreName: 'chat-view-events',
2129
2150
  filterValue: '',
2151
+ focus: 0,
2130
2152
  height: 0,
2131
2153
  initial: false,
2154
+ largeBreakpoint: 900,
2155
+ mediumBreakpoint: 600,
2132
2156
  platform: 0,
2133
2157
  sashPointerActive: false,
2134
2158
  selectedEvent: null,
@@ -2139,12 +2163,16 @@ const createDefaultState = () => {
2139
2163
  showEventStreamFinishedEvents: false,
2140
2164
  showInputEvents: false,
2141
2165
  showResponsePartEvents: false,
2166
+ sortColumn: '',
2167
+ sortDescending: false,
2142
2168
  tableColumns: [],
2143
2169
  tableColumnWidths: defaultTableColumnWidths,
2144
2170
  tableResizerDownId: 0,
2145
2171
  tableWidth: defaultTableWidth,
2146
2172
  timelineEndSeconds: '',
2147
2173
  timelineEvents: [],
2174
+ timelineHoverPercent: null,
2175
+ timelineHoverSeconds: '',
2148
2176
  timelineInfo: emptyTimelineInfo,
2149
2177
  timelineSelectionActive: false,
2150
2178
  timelineSelectionAnchorSeconds: '',
@@ -2168,6 +2196,7 @@ const create = (uid, uri, x, y, width, height, platform, assetDir, sessionId = '
2168
2196
  databaseName,
2169
2197
  dataBaseVersion,
2170
2198
  eventStoreName,
2199
+ focus: 0,
2171
2200
  height,
2172
2201
  initial: true,
2173
2202
  platform,
@@ -2186,9 +2215,11 @@ const create = (uid, uri, x, y, width, height, platform, assetDir, sessionId = '
2186
2215
  const RenderItems = 1;
2187
2216
  const RenderCss = 2;
2188
2217
  const RenderIncremental = 3;
2218
+ const RenderFocusContext = 4;
2219
+ const RenderFocus = 5;
2189
2220
 
2190
2221
  const diff = (oldState, newState) => {
2191
- if (oldState.categoryFilters !== newState.categoryFilters || oldState.detailTabs !== newState.detailTabs || oldState.errorMessage !== newState.errorMessage || oldState.events !== newState.events || oldState.filterValue !== newState.filterValue || oldState.sessionId !== newState.sessionId || oldState.showEventStreamFinishedEvents !== newState.showEventStreamFinishedEvents || oldState.showInputEvents !== newState.showInputEvents || oldState.showResponsePartEvents !== newState.showResponsePartEvents || oldState.tableColumnWidths !== newState.tableColumnWidths || oldState.tableWidth !== newState.tableWidth || oldState.timelineEndSeconds !== newState.timelineEndSeconds || oldState.timelineSelectionActive !== newState.timelineSelectionActive || oldState.timelineSelectionAnchorSeconds !== newState.timelineSelectionAnchorSeconds || oldState.timelineSelectionFocusSeconds !== newState.timelineSelectionFocusSeconds || oldState.timelineStartSeconds !== newState.timelineStartSeconds || oldState.useDevtoolsLayout !== newState.useDevtoolsLayout || oldState.visibleTableColumns !== newState.visibleTableColumns || oldState.selectedEvent !== newState.selectedEvent || oldState.selectedEventIndex !== newState.selectedEventIndex || oldState.width !== newState.width || oldState.uid !== newState.uid) {
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) {
2192
2223
  return [RenderIncremental, RenderCss];
2193
2224
  }
2194
2225
  return [];
@@ -2202,26 +2233,6 @@ const diff2 = uid => {
2202
2233
  return diff(oldState, newState);
2203
2234
  };
2204
2235
 
2205
- const getColumnVisibilityFlags = (state, column) => {
2206
- return isVisibleTableColumn(state.visibleTableColumns, column) ? Checked : Unchecked;
2207
- };
2208
-
2209
- const MenuChatDebugTableHeader = 2189;
2210
- const handleHeaderContextMenu = async (state, eventX, eventY) => {
2211
- await showContextMenu2(state.uid, MenuChatDebugTableHeader, eventX, eventY, {
2212
- menuId: MenuChatDebugTableHeader
2213
- });
2214
- return state;
2215
- };
2216
-
2217
- const devtoolsRootGap = 4;
2218
- const devtoolsTopHeight = 28;
2219
- const devtoolsTimelineHeight = 88;
2220
- const devtoolsTableHeaderHeight = 24;
2221
- const getTableBodyY = (state, hasTimeline) => {
2222
- return state.y + viewPadding + devtoolsTopHeight + devtoolsRootGap + (hasTimeline ? devtoolsTimelineHeight : 0) + devtoolsTableHeaderHeight;
2223
- };
2224
-
2225
2236
  const filterEventsByTimelineRange = (events, startValue, endValue) => {
2226
2237
  const eventsWithTime = getEventsWithTime(events);
2227
2238
  if (eventsWithTime.length === 0) {
@@ -2239,6 +2250,12 @@ const filterEventsByTimelineRange = (events, startValue, endValue) => {
2239
2250
  return eventsWithTime.filter(item => item.time >= startTime && item.time <= endTime).map(item => item.event);
2240
2251
  };
2241
2252
 
2253
+ const startedEventType = 'tool-execution-started';
2254
+ const finishedEventType = 'tool-execution-finished';
2255
+ const mergedEventType = 'tool-execution';
2256
+ const handleSubmitEventType = 'handle-submit';
2257
+ const sseResponseCompletedEventType = 'sse-response-completed';
2258
+
2242
2259
  const hasMatchingToolName = (startedEvent, finishedEvent) => {
2243
2260
  if (typeof startedEvent.toolName === 'string' && typeof finishedEvent.toolName === 'string') {
2244
2261
  return startedEvent.toolName === finishedEvent.toolName;
@@ -2250,10 +2267,6 @@ const isMatchingToolExecutionPair = (startedEvent, finishedEvent) => {
2250
2267
  return startedEvent.sessionId === finishedEvent.sessionId && hasMatchingToolName(startedEvent, finishedEvent);
2251
2268
  };
2252
2269
 
2253
- const startedEventType = 'tool-execution-started';
2254
- const finishedEventType = 'tool-execution-finished';
2255
- const mergedEventType = 'tool-execution';
2256
-
2257
2270
  const isToolExecutionFinishedEvent = event => {
2258
2271
  return event.type === finishedEventType;
2259
2272
  };
@@ -2274,7 +2287,7 @@ const getStartedTimestamp = event => {
2274
2287
  return getTimestamp(event.started) ?? getTimestamp(event.startTime) ?? getTimestamp(event.startTimestamp) ?? getTimestamp(event.timestamp);
2275
2288
  };
2276
2289
 
2277
- const mergeToolExecutionEvents = (startedEvent, finishedEvent) => {
2290
+ const mergeToolExecutionEvents = (startedEvent, finishedEvent, type = mergedEventType) => {
2278
2291
  const ended = getEndedTimestamp(finishedEvent);
2279
2292
  const {
2280
2293
  eventId
@@ -2292,22 +2305,28 @@ const mergeToolExecutionEvents = (startedEvent, finishedEvent) => {
2292
2305
  ...(started === undefined ? {} : {
2293
2306
  started
2294
2307
  }),
2295
- type: mergedEventType
2308
+ type
2296
2309
  };
2297
2310
  return mergedEvent;
2298
2311
  };
2299
2312
 
2313
+ const isMatchingHandleSubmitPair = (startedEvent, finishedEvent) => {
2314
+ return startedEvent.type === handleSubmitEventType && finishedEvent.type === sseResponseCompletedEventType && startedEvent.sessionId === finishedEvent.sessionId;
2315
+ };
2300
2316
  const collapseToolExecutionEvents = events => {
2301
2317
  const collapsedEvents = [];
2302
2318
  for (let i = 0; i < events.length; i++) {
2303
2319
  const event = events[i];
2304
- if (isToolExecutionStartedEvent(event)) {
2305
- const nextEvent = events[i + 1];
2306
- if (nextEvent && isToolExecutionFinishedEvent(nextEvent) && isMatchingToolExecutionPair(event, nextEvent)) {
2307
- collapsedEvents.push(mergeToolExecutionEvents(event, nextEvent));
2308
- i++;
2309
- continue;
2310
- }
2320
+ const nextEvent = events[i + 1];
2321
+ if (nextEvent && isToolExecutionStartedEvent(event) && isToolExecutionFinishedEvent(nextEvent) && isMatchingToolExecutionPair(event, nextEvent)) {
2322
+ collapsedEvents.push(mergeToolExecutionEvents(event, nextEvent));
2323
+ i++;
2324
+ continue;
2325
+ }
2326
+ if (nextEvent && isMatchingHandleSubmitPair(event, nextEvent)) {
2327
+ collapsedEvents.push(mergeToolExecutionEvents(event, nextEvent, handleSubmitEventType));
2328
+ i++;
2329
+ continue;
2311
2330
  }
2312
2331
  collapsedEvents.push(event);
2313
2332
  }
@@ -2387,6 +2406,164 @@ const getFilteredEvents = (events, filterValue, eventCategoryFilters, showInputE
2387
2406
  return filteredByCategory.filter(event => JSON.stringify(event).toLowerCase().includes(filterText));
2388
2407
  };
2389
2408
 
2409
+ const getDurationText = event => {
2410
+ const explicitDuration = event.durationMs ?? event.duration;
2411
+ if (typeof explicitDuration === 'number' && Number.isFinite(explicitDuration)) {
2412
+ return `${explicitDuration}ms`;
2413
+ }
2414
+ const start = toTimeNumber(event.started ?? event.startTime ?? event.startTimestamp ?? event.timestamp);
2415
+ const end = toTimeNumber(event.ended ?? event.endTime ?? event.endTimestamp ?? event.timestamp);
2416
+ if (start === undefined || end === undefined || end < start) {
2417
+ return '-';
2418
+ }
2419
+ return `${end - start}ms`;
2420
+ };
2421
+
2422
+ const getEventTableDurationText = event => {
2423
+ const durationText = getDurationText(event);
2424
+ if (!durationText.endsWith('ms')) {
2425
+ return durationText;
2426
+ }
2427
+ return `${durationText.slice(0, -2)} ms`;
2428
+ };
2429
+
2430
+ const toolExecutionTypePrefix = 'tool-execution';
2431
+ const getToolName = event => {
2432
+ if (typeof event.toolName === 'string' && event.toolName) {
2433
+ return event.toolName;
2434
+ }
2435
+ if (typeof event.name === 'string' && event.name) {
2436
+ return event.name;
2437
+ }
2438
+ const {
2439
+ arguments: toolArguments
2440
+ } = event;
2441
+ if (!toolArguments || typeof toolArguments !== 'object') {
2442
+ return undefined;
2443
+ }
2444
+ const {
2445
+ name
2446
+ } = toolArguments;
2447
+ if (typeof name !== 'string' || !name) {
2448
+ return undefined;
2449
+ }
2450
+ return name;
2451
+ };
2452
+ const getEventTypeLabel = event => {
2453
+ if (!event.type.startsWith(toolExecutionTypePrefix)) {
2454
+ return event.type;
2455
+ }
2456
+ const toolName = getToolName(event);
2457
+ if (!toolName) {
2458
+ return event.type;
2459
+ }
2460
+ return `${event.type}, ${toolName}`;
2461
+ };
2462
+
2463
+ const getEventTableTypeLabel = event => {
2464
+ if (event.name === 'list_files') {
2465
+ return event.name;
2466
+ }
2467
+ return getEventTypeLabel(event);
2468
+ };
2469
+
2470
+ const isErrorStatusCode = value => {
2471
+ if (typeof value === 'number') {
2472
+ return value >= 400;
2473
+ }
2474
+ if (typeof value === 'string') {
2475
+ const parsedStatus = Number(value);
2476
+ return Number.isFinite(parsedStatus) && parsedStatus >= 400;
2477
+ }
2478
+ return false;
2479
+ };
2480
+
2481
+ const isRecord = value => {
2482
+ return typeof value === 'object' && value !== null;
2483
+ };
2484
+
2485
+ const hasErrorStatus = event => {
2486
+ if (event.type === 'error') {
2487
+ return true;
2488
+ }
2489
+ if (event.success === false || event.ok === false) {
2490
+ return true;
2491
+ }
2492
+ const {
2493
+ status
2494
+ } = event;
2495
+ if (isErrorStatusCode(status)) {
2496
+ return true;
2497
+ }
2498
+ const {
2499
+ result
2500
+ } = event;
2501
+ if (isRecord(result)) {
2502
+ if (isErrorStatusCode(result.status)) {
2503
+ return true;
2504
+ }
2505
+ if (isToolEvent(event) && 'error' in result && result.error !== undefined) {
2506
+ return true;
2507
+ }
2508
+ if (typeof result.error === 'string' || typeof result.errorMessage === 'string' || typeof result.exception === 'string') {
2509
+ return true;
2510
+ }
2511
+ }
2512
+ return typeof event.error === 'string' || typeof event.errorMessage === 'string' || typeof event.exception === 'string';
2513
+ };
2514
+
2515
+ const getStatusText = event => {
2516
+ return hasErrorStatus(event) ? '400' : '200';
2517
+ };
2518
+
2519
+ const getEventTableColumnValue = (event, column) => {
2520
+ switch (column) {
2521
+ case Duration:
2522
+ return getEventTableDurationText(event);
2523
+ case Status$1:
2524
+ return getStatusText(event);
2525
+ case Type:
2526
+ return getEventTableTypeLabel(event);
2527
+ default:
2528
+ return '';
2529
+ }
2530
+ };
2531
+
2532
+ const compareValues = (a, b, descending) => {
2533
+ const result = a.localeCompare(b, undefined, {
2534
+ sensitivity: 'base'
2535
+ });
2536
+ return descending ? -result : result;
2537
+ };
2538
+ const compareSortableEventEntries = (a, b, sortDescending) => {
2539
+ const compared = compareValues(a.value, b.value, sortDescending);
2540
+ if (compared !== 0) {
2541
+ return compared;
2542
+ }
2543
+ return a.index - b.index;
2544
+ };
2545
+ const sortEventsByTableColumn = (events, sortColumn, sortDescending) => {
2546
+ if (!sortColumn || !isTableColumn(sortColumn)) {
2547
+ return events;
2548
+ }
2549
+ const sortableEvents = events.map((event, index) => ({
2550
+ event,
2551
+ index,
2552
+ value: getEventTableColumnValue(event, sortColumn)
2553
+ }));
2554
+ const compareEntries = (a, b) => {
2555
+ return compareSortableEventEntries(a, b, sortDescending);
2556
+ };
2557
+ return sortableEvents.toSorted(compareEntries).map(item => item.event);
2558
+ };
2559
+
2560
+ const getCurrentEvents$2 = state => {
2561
+ const eventCategoryFilters = getSelectedEventCategoryFilters(state.categoryFilters);
2562
+ const filteredEvents = getFilteredEvents(state.events, state.filterValue, eventCategoryFilters, state.showInputEvents, state.showResponsePartEvents, state.showEventStreamFinishedEvents);
2563
+ const timelineEvents = filterEventsByTimelineRange(filteredEvents, state.timelineStartSeconds, state.timelineEndSeconds);
2564
+ return sortEventsByTableColumn(timelineEvents, state.sortColumn, state.sortDescending);
2565
+ };
2566
+
2390
2567
  const loadSelectedEvent = async (_databaseName, _dataBaseVersion, _eventStoreName, sessionId, _sessionIdIndexName, eventId, type) => {
2391
2568
  return loadSelectedEvent$1(sessionId, eventId, type);
2392
2569
  };
@@ -2477,23 +2654,10 @@ const withPreparedSelectedEventPreview = async event => {
2477
2654
  const selectEventAtIndexDependencies = {
2478
2655
  loadSelectedEvent: loadSelectedEvent
2479
2656
  };
2480
- const getCurrentEvents$3 = state => {
2481
- const {
2482
- events,
2483
- filterValue,
2484
- showEventStreamFinishedEvents,
2485
- showInputEvents,
2486
- showResponsePartEvents,
2487
- timelineEndSeconds,
2488
- timelineStartSeconds
2489
- } = state;
2490
- const eventCategoryFilters = getSelectedEventCategoryFilters(state.categoryFilters);
2491
- const filteredEvents = getFilteredEvents(events, filterValue, eventCategoryFilters, showInputEvents, showResponsePartEvents, showEventStreamFinishedEvents);
2492
- return filterEventsByTimelineRange(filteredEvents, timelineStartSeconds, timelineEndSeconds);
2493
- };
2657
+ const getCurrentEvents$1 = state => getCurrentEvents$2(state);
2494
2658
  const selectEventAtIndex = async (state, selectedEventIndex, dependencies = selectEventAtIndexDependencies) => {
2495
2659
  const selectedDetailTab = getSelectedDetailTab(state.detailTabs);
2496
- const currentEvents = getCurrentEvents$3(state);
2660
+ const currentEvents = getCurrentEvents$1(state);
2497
2661
  const selectedEvent = currentEvents[selectedEventIndex];
2498
2662
  if (!selectedEvent) {
2499
2663
  return {
@@ -2522,39 +2686,59 @@ const selectEventAtIndex = async (state, selectedEventIndex, dependencies = sele
2522
2686
  };
2523
2687
  };
2524
2688
 
2525
- const devtoolsTableRowHeight = 24;
2526
- const getTableBodyEventIndex = (state, eventX, eventY) => {
2527
- if (!state.useDevtoolsLayout) {
2528
- return -1;
2689
+ const focusIndex = async (state, index) => {
2690
+ const currentEvents = getCurrentEvents$1(state);
2691
+ if (currentEvents.length === 0 || state.selectedEventIndex === index) {
2692
+ return state;
2529
2693
  }
2530
- const currentEvents = getCurrentEvents$3(state);
2694
+ return selectEventAtIndex(state, index);
2695
+ };
2696
+
2697
+ const focusFirst = async state => {
2698
+ return focusIndex(state, 0);
2699
+ };
2700
+
2701
+ const focusLast = async state => {
2702
+ const currentEvents = getCurrentEvents$1(state);
2531
2703
  if (currentEvents.length === 0) {
2532
- return -1;
2704
+ return state;
2533
2705
  }
2534
- const tableX = state.x + leftPadding;
2535
- const tableWidth = clampTableWidth(state.width, state.tableWidth);
2536
- const hasTimeline = currentEvents.length > 0;
2537
- const tableBodyY = getTableBodyY(state, hasTimeline);
2538
- const relativeX = eventX - tableX;
2539
- const relativeY = eventY - tableBodyY;
2540
- if (relativeX < 0 || relativeX >= tableWidth || relativeY < 0) {
2541
- return -1;
2706
+ const lastIndex = currentEvents.length - 1;
2707
+ return focusIndex(state, lastIndex);
2708
+ };
2709
+
2710
+ const focusNext = async state => {
2711
+ const currentEvents = getCurrentEvents$1(state);
2712
+ if (currentEvents.length === 0) {
2713
+ return state;
2542
2714
  }
2543
- const eventIndex = Math.floor(relativeY / devtoolsTableRowHeight);
2544
- if (eventIndex < 0 || eventIndex >= currentEvents.length) {
2545
- return -1;
2715
+ const currentIndex = state.selectedEventIndex === null || state.selectedEventIndex < 0 ? -1 : state.selectedEventIndex;
2716
+ const nextIndex = Math.min(currentEvents.length - 1, currentIndex + 1);
2717
+ return focusIndex(state, nextIndex);
2718
+ };
2719
+
2720
+ const focusPrevious = async state => {
2721
+ const currentEvents = getCurrentEvents$1(state);
2722
+ if (currentEvents.length === 0) {
2723
+ return state;
2546
2724
  }
2547
- return eventIndex;
2725
+ const currentIndex = state.selectedEventIndex === null || state.selectedEventIndex >= currentEvents.length ? currentEvents.length : state.selectedEventIndex;
2726
+ const nextIndex = Math.max(0, currentIndex - 1);
2727
+ return focusIndex(state, nextIndex);
2548
2728
  };
2549
2729
 
2550
- const MenuChatDebugTableBody = 2190;
2551
- const handleTableBodyContextMenu = async (state, eventX, eventY) => {
2552
- const eventIndex = getTableBodyEventIndex(state, eventX, eventY);
2553
- await showContextMenu2(state.uid, MenuChatDebugTableBody, eventX, eventY, {
2554
- eventIndex,
2555
- menuId: MenuChatDebugTableBody
2556
- });
2557
- return state;
2730
+ const getMenuEntriesTableBody = props => {
2731
+ return [{
2732
+ args: [props.eventIndex],
2733
+ command: 'ChatDebug.handleTableRowCopy',
2734
+ flags: None$1,
2735
+ id: 'copy',
2736
+ label: copy()
2737
+ }];
2738
+ };
2739
+
2740
+ const getColumnVisibilityFlags = (state, column) => {
2741
+ return isVisibleTableColumn(state.visibleTableColumns, column) ? Checked : Unchecked;
2558
2742
  };
2559
2743
 
2560
2744
  const getMenuEntriesTableHeader = state => {
@@ -2564,18 +2748,18 @@ const getMenuEntriesTableHeader = state => {
2564
2748
  flags: getColumnVisibilityFlags(state, Type),
2565
2749
  id: 'type',
2566
2750
  label: type()
2751
+ }, {
2752
+ args: [Status$1],
2753
+ command: 'ChatDebug.toggleTableColumnVisibility',
2754
+ flags: getColumnVisibilityFlags(state, Status$1),
2755
+ id: 'status',
2756
+ label: status()
2567
2757
  }, {
2568
2758
  args: [Duration],
2569
2759
  command: 'ChatDebug.toggleTableColumnVisibility',
2570
2760
  flags: getColumnVisibilityFlags(state, Duration),
2571
2761
  id: 'duration',
2572
2762
  label: duration()
2573
- }, {
2574
- args: [Status],
2575
- command: 'ChatDebug.toggleTableColumnVisibility',
2576
- flags: getColumnVisibilityFlags(state, Status),
2577
- id: 'status',
2578
- label: status()
2579
2763
  }, {
2580
2764
  args: [],
2581
2765
  command: 'ChatDebug.resetTableColumns',
@@ -2584,19 +2768,67 @@ const getMenuEntriesTableHeader = state => {
2584
2768
  label: resetColumns()
2585
2769
  }];
2586
2770
  };
2587
- const getMenuEntriesTableBody = props => {
2588
- return [{
2589
- args: [props.eventIndex],
2590
- command: 'ChatDebug.handleTableRowCopy',
2591
- flags: None$1,
2592
- id: 'copy',
2593
- label: copy()
2594
- }];
2595
- };
2596
- const getMenuEntries2 = (state, props) => {
2597
- if (props.menuId === MenuChatDebugTableHeader) {
2598
- return getMenuEntriesTableHeader(state);
2599
- }
2771
+
2772
+ const MenuChatDebugTableHeader = 2189;
2773
+ const handleHeaderContextMenu = async (state, eventX, eventY) => {
2774
+ await showContextMenu2(state.uid, MenuChatDebugTableHeader, eventX, eventY, {
2775
+ menuId: MenuChatDebugTableHeader
2776
+ });
2777
+ return state;
2778
+ };
2779
+
2780
+ const show2 = async (uid, menuId, x, y, args) => {
2781
+ await showContextMenu2(uid, menuId, x, y, args);
2782
+ };
2783
+
2784
+ const devtoolsTableHeaderHeight = 24;
2785
+ const devtoolsTableRowHeight = 24;
2786
+
2787
+ const devtoolsRootGap = 4;
2788
+ const devtoolsTopHeight = 28;
2789
+ const devtoolsTimelineHeight = 88;
2790
+ const getTableBodyY = (state, hasTimeline) => {
2791
+ return state.y + viewPadding + devtoolsTopHeight + devtoolsRootGap + (hasTimeline ? devtoolsTimelineHeight : 0) + devtoolsTableHeaderHeight;
2792
+ };
2793
+
2794
+ const getTableBodyEventIndex = (state, eventX, eventY) => {
2795
+ if (!state.useDevtoolsLayout) {
2796
+ return -1;
2797
+ }
2798
+ const currentEvents = getCurrentEvents$1(state);
2799
+ if (currentEvents.length === 0) {
2800
+ return -1;
2801
+ }
2802
+ const tableX = state.x + leftPadding;
2803
+ const tableWidth = clampTableWidth(state.width, state.tableWidth);
2804
+ const hasTimeline = currentEvents.length > 0;
2805
+ const tableBodyY = getTableBodyY(state, hasTimeline);
2806
+ const relativeX = eventX - tableX;
2807
+ const relativeY = eventY - tableBodyY;
2808
+ if (relativeX < 0 || relativeX >= tableWidth || relativeY < 0) {
2809
+ return -1;
2810
+ }
2811
+ const eventIndex = Math.floor(relativeY / devtoolsTableRowHeight);
2812
+ if (eventIndex < 0 || eventIndex >= currentEvents.length) {
2813
+ return -1;
2814
+ }
2815
+ return eventIndex;
2816
+ };
2817
+
2818
+ const MenuChatDebugTableBody = 2190;
2819
+ const handleTableBodyContextMenu = async (state, eventX, eventY) => {
2820
+ const eventIndex = getTableBodyEventIndex(state, eventX, eventY);
2821
+ await show2(state.uid, MenuChatDebugTableBody, eventX, eventY, {
2822
+ eventIndex,
2823
+ menuId: MenuChatDebugTableBody
2824
+ });
2825
+ return state;
2826
+ };
2827
+
2828
+ const getMenuEntries2 = (state, props) => {
2829
+ if (props.menuId === MenuChatDebugTableHeader) {
2830
+ return getMenuEntriesTableHeader(state);
2831
+ }
2600
2832
  if (props.menuId === MenuChatDebugTableBody) {
2601
2833
  return getMenuEntriesTableBody(props);
2602
2834
  }
@@ -2769,12 +3001,6 @@ const getSessionNotFoundMessage = sessionId => {
2769
3001
  return noChatSessionFound(sessionId);
2770
3002
  };
2771
3003
 
2772
- const getCurrentEvents$2 = state => {
2773
- const eventCategoryFilters = getSelectedEventCategoryFilters(state.categoryFilters);
2774
- const filteredEvents = getFilteredEvents(state.events, state.filterValue, eventCategoryFilters, state.showInputEvents, state.showResponsePartEvents, state.showEventStreamFinishedEvents);
2775
- return filterEventsByTimelineRange(filteredEvents, state.timelineStartSeconds, state.timelineEndSeconds);
2776
- };
2777
-
2778
3004
  const restoreSelectedEvent = async state => {
2779
3005
  if (state.selectedEventId === null) {
2780
3006
  return {
@@ -2915,12 +3141,12 @@ const selectDetailTab = (state, value) => {
2915
3141
  };
2916
3142
  };
2917
3143
 
2918
- const getCurrentEvents$1 = state => {
2919
- const eventCategoryFilters = getSelectedEventCategoryFilters(state.categoryFilters);
2920
- const filteredEvents = getFilteredEvents(state.events, state.filterValue, eventCategoryFilters, state.showInputEvents, state.showResponsePartEvents, state.showEventStreamFinishedEvents);
2921
- return filterEventsByTimelineRange(filteredEvents, state.timelineStartSeconds, state.timelineEndSeconds);
3144
+ const handleEscape = state => {
3145
+ return state;
2922
3146
  };
2923
3147
 
3148
+ const getCurrentEvents = state => getCurrentEvents$2(state);
3149
+
2924
3150
  const getEventIndexByStableId$1 = (events, event) => {
2925
3151
  return events.findIndex(candidate => candidate.eventId === event.eventId);
2926
3152
  };
@@ -2932,7 +3158,7 @@ const getSelectedEventIndex$1 = state => {
2932
3158
  if (selectedEventIndex === null) {
2933
3159
  return null;
2934
3160
  }
2935
- const filteredEvents = getCurrentEvents$1(state);
3161
+ const filteredEvents = getCurrentEvents(state);
2936
3162
  const selectedEvent = filteredEvents[selectedEventIndex];
2937
3163
  if (!selectedEvent) {
2938
3164
  return null;
@@ -2951,12 +3177,12 @@ const getPreservedSelectedEventIndex$1 = (oldState, newState) => {
2951
3177
  if (selectedEventIndex === null) {
2952
3178
  return null;
2953
3179
  }
2954
- const oldFilteredEvents = getCurrentEvents$1(oldState);
3180
+ const oldFilteredEvents = getCurrentEvents(oldState);
2955
3181
  const selectedEvent = oldFilteredEvents[selectedEventIndex];
2956
3182
  if (!selectedEvent) {
2957
3183
  return null;
2958
3184
  }
2959
- const newFilteredEvents = getCurrentEvents$1(newState);
3185
+ const newFilteredEvents = getCurrentEvents(newState);
2960
3186
  const newIndex = getEventIndexByStableId$1(newFilteredEvents, selectedEvent);
2961
3187
  if (newIndex === -1) {
2962
3188
  return null;
@@ -2976,51 +3202,46 @@ const withPreservedSelection$1 = (state, nextState) => {
2976
3202
  };
2977
3203
 
2978
3204
  const handleEventCategoryFilter = (state, value, ctrlKey = false, metaKey = false) => {
2979
- const categoryFilters = selectCategoryFilter(state.categoryFilters, value || All, ctrlKey || metaKey);
2980
- if (categoryFilters === state.categoryFilters) {
3205
+ const {
3206
+ categoryFilters
3207
+ } = state;
3208
+ const newCategoryFilters = selectCategoryFilter(categoryFilters, value || All, ctrlKey || metaKey);
3209
+ if (newCategoryFilters === categoryFilters) {
2981
3210
  return state;
2982
3211
  }
2983
3212
  const nextState = {
2984
3213
  ...state,
2985
- categoryFilters
3214
+ categoryFilters: newCategoryFilters
2986
3215
  };
2987
3216
  return withPreservedSelection$1(state, nextState);
2988
3217
  };
2989
3218
 
2990
- const parseSelectedEventIndex$1 = value => {
2991
- const parsed = Number.parseInt(value, 10);
2992
- if (Number.isNaN(parsed) || parsed < 0) {
2993
- return null;
2994
- }
2995
- return parsed;
2996
- };
2997
-
2998
3219
  const handleEventRowClickDependencies = {
2999
3220
  loadSelectedEvent: loadSelectedEvent
3000
3221
  };
3001
3222
  const isPrimaryButton = button => {
3002
3223
  return button === 0;
3003
3224
  };
3004
- const handleEventRowClick = async (state, value, button = 0) => {
3225
+ const handleEventRowClick = async (state, index, button = 0) => {
3226
+ const actual = typeof index === 'string' ? Number.parseInt(index, 10) : index;
3005
3227
  if (!isPrimaryButton(button)) {
3006
3228
  return state;
3007
3229
  }
3008
- const selectedEventIndex = parseSelectedEventIndex$1(value);
3009
- if (selectedEventIndex === null) {
3230
+ if (actual === -1) {
3010
3231
  return state;
3011
3232
  }
3012
- return selectEventAtIndex(state, selectedEventIndex, handleEventRowClickDependencies);
3233
+ return selectEventAtIndex(state, actual, handleEventRowClickDependencies);
3234
+ };
3235
+
3236
+ const handleEventRowClickAt = async (state, eventX, eventY, button = 0) => {
3237
+ const selectedEventIndex = getTableBodyEventIndex(state, eventX, eventY);
3238
+ return handleEventRowClick(state, selectedEventIndex, button);
3013
3239
  };
3014
3240
 
3015
3241
  const getBoolean = value => {
3016
3242
  return value === true || value === 'true' || value === 'on' || value === '1';
3017
3243
  };
3018
3244
 
3019
- const getCurrentEvents = state => {
3020
- const eventCategoryFilters = getSelectedEventCategoryFilters(state.categoryFilters);
3021
- const filteredEvents = getFilteredEvents(state.events, state.filterValue, eventCategoryFilters, state.showInputEvents, state.showResponsePartEvents, state.showEventStreamFinishedEvents);
3022
- return filterEventsByTimelineRange(filteredEvents, state.timelineStartSeconds, state.timelineEndSeconds);
3023
- };
3024
3245
  const parseTimelineRangePreset$1 = value => {
3025
3246
  if (!value) {
3026
3247
  return {
@@ -3044,7 +3265,7 @@ const getSelectedEventIndex = state => {
3044
3265
  if (selectedEventIndex === null) {
3045
3266
  return null;
3046
3267
  }
3047
- const filteredEvents = getCurrentEvents(state);
3268
+ const filteredEvents = getCurrentEvents$2(state);
3048
3269
  const selectedEvent = filteredEvents[selectedEventIndex];
3049
3270
  if (!selectedEvent) {
3050
3271
  return null;
@@ -3062,12 +3283,12 @@ const getPreservedSelectedEventIndex = (oldState, newState) => {
3062
3283
  if (selectedEventIndex === null) {
3063
3284
  return null;
3064
3285
  }
3065
- const oldFilteredEvents = getCurrentEvents(oldState);
3286
+ const oldFilteredEvents = getCurrentEvents$2(oldState);
3066
3287
  const selectedEvent = oldFilteredEvents[selectedEventIndex];
3067
3288
  if (!selectedEvent) {
3068
3289
  return null;
3069
3290
  }
3070
- const newFilteredEvents = getCurrentEvents(newState);
3291
+ const newFilteredEvents = getCurrentEvents$2(newState);
3071
3292
  const newIndex = getEventIndexByStableId(newFilteredEvents, selectedEvent);
3072
3293
  if (newIndex === -1) {
3073
3294
  return null;
@@ -3226,6 +3447,28 @@ const handleSashPointerUp = (state, eventX, eventY) => {
3226
3447
  };
3227
3448
  };
3228
3449
 
3450
+ const FocusChatDebugTable = 221_139;
3451
+
3452
+ const handleTableFocus = state => {
3453
+ return {
3454
+ ...state,
3455
+ focus: FocusChatDebugTable
3456
+ };
3457
+ };
3458
+
3459
+ const handleTableHeaderClick = (state, value) => {
3460
+ if (!isTableColumn(value)) {
3461
+ return state;
3462
+ }
3463
+ const sortDescending = state.sortColumn === value ? !state.sortDescending : false;
3464
+ const nextState = {
3465
+ ...state,
3466
+ sortColumn: value,
3467
+ sortDescending
3468
+ };
3469
+ return withPreservedSelection$1(state, nextState);
3470
+ };
3471
+
3229
3472
  const getTableResizerId = name => {
3230
3473
  switch (name) {
3231
3474
  case 'ResizerOne':
@@ -3264,7 +3507,7 @@ const handleTableResizerPointerUp = state => {
3264
3507
  };
3265
3508
 
3266
3509
  const handleTableRowCopy = async (state, eventIndex) => {
3267
- const currentEvents = getCurrentEvents$3(state);
3510
+ const currentEvents = getCurrentEvents$1(state);
3268
3511
  const event = currentEvents[eventIndex];
3269
3512
  if (!event) {
3270
3513
  return state;
@@ -3333,6 +3576,10 @@ const formatTimelinePresetValue = value => {
3333
3576
  return value.toFixed(3).replace(trailingZeroFractionRegex, '').replace(trailingFractionZeroRegex, '$1');
3334
3577
  };
3335
3578
 
3579
+ const getTimelineEventX = (state, eventX) => {
3580
+ return state.x + eventX;
3581
+ };
3582
+
3336
3583
  const getTimelineLeft = state => {
3337
3584
  return state.x + viewPadding + timelineHorizontalPadding;
3338
3585
  };
@@ -3392,32 +3639,53 @@ const handleTimelinePointerDown = (state, name, eventX) => {
3392
3639
  }
3393
3640
  const timelineLeft = getTimelineLeft(state);
3394
3641
  const timelineWidth = getTimelineWidth(state);
3395
- const clientX = state.x + eventX;
3642
+ const clientX = getTimelineEventX(state, eventX);
3396
3643
  const seconds = getTimelineSecondsFromClientX(state.timelineEvents, clientX, timelineLeft, timelineWidth);
3397
3644
  if (seconds === undefined) {
3398
3645
  return state;
3399
3646
  }
3647
+ const timelineHoverPercent = getSelectionPercent(Number.parseFloat(seconds), state.timelineInfo.durationSeconds);
3400
3648
  return getStateWithTimelineInfo({
3401
3649
  ...state,
3650
+ timelineHoverPercent,
3651
+ timelineHoverSeconds: seconds,
3402
3652
  timelineSelectionActive: true,
3403
3653
  timelineSelectionAnchorSeconds: seconds,
3404
3654
  timelineSelectionFocusSeconds: seconds
3405
3655
  });
3406
3656
  };
3407
3657
 
3408
- const handleTimelinePointerMove = (state, eventX) => {
3409
- if (!state.timelineSelectionActive) {
3658
+ const handleTimelinePointerLeave = state => {
3659
+ if (state.timelineHoverPercent === null && state.timelineHoverSeconds === '') {
3410
3660
  return state;
3411
3661
  }
3662
+ return {
3663
+ ...state,
3664
+ timelineHoverPercent: null,
3665
+ timelineHoverSeconds: ''
3666
+ };
3667
+ };
3668
+
3669
+ const handleTimelinePointerMove = (state, eventX) => {
3412
3670
  const timelineLeft = getTimelineLeft(state);
3413
3671
  const timelineWidth = getTimelineWidth(state);
3414
- const clientX = state.x + eventX;
3672
+ const clientX = getTimelineEventX(state, eventX);
3415
3673
  const seconds = getTimelineSecondsFromClientX(state.timelineEvents, clientX, timelineLeft, timelineWidth);
3416
3674
  if (seconds === undefined) {
3417
3675
  return state;
3418
3676
  }
3677
+ const timelineHoverPercent = getSelectionPercent(Number.parseFloat(seconds), state.timelineInfo.durationSeconds);
3678
+ if (!state.timelineSelectionActive) {
3679
+ return {
3680
+ ...state,
3681
+ timelineHoverPercent,
3682
+ timelineHoverSeconds: seconds
3683
+ };
3684
+ }
3419
3685
  return getStateWithTimelineInfo({
3420
3686
  ...state,
3687
+ timelineHoverPercent,
3688
+ timelineHoverSeconds: seconds,
3421
3689
  timelineSelectionFocusSeconds: seconds
3422
3690
  });
3423
3691
  };
@@ -3428,17 +3696,22 @@ const handleTimelinePointerUp = (state, eventX) => {
3428
3696
  }
3429
3697
  const timelineLeft = getTimelineLeft(state);
3430
3698
  const timelineWidth = getTimelineWidth(state);
3431
- const clientX = state.x + eventX;
3699
+ const clientX = getTimelineEventX(state, eventX);
3432
3700
  const focusSeconds = getTimelineSecondsFromClientX(state.timelineEvents, clientX, timelineLeft, timelineWidth);
3433
3701
  if (focusSeconds === undefined) {
3434
3702
  return clearTimelineSelectionState(state);
3435
3703
  }
3704
+ const timelineHoverPercent = getSelectionPercent(Number.parseFloat(focusSeconds), state.timelineInfo.durationSeconds);
3436
3705
  const anchor = Number.parseFloat(state.timelineSelectionAnchorSeconds);
3437
3706
  const focus = Number.parseFloat(focusSeconds);
3438
3707
  const startSeconds = formatTimelinePresetValue(Math.min(anchor, focus));
3439
3708
  const endSeconds = formatTimelinePresetValue(Math.max(anchor, focus));
3440
3709
  const nextState = handleTimelineRangePreset(state, `${startSeconds}:${endSeconds}`);
3441
- return clearTimelineSelectionState(nextState);
3710
+ return clearTimelineSelectionState({
3711
+ ...nextState,
3712
+ timelineHoverPercent,
3713
+ timelineHoverSeconds: focusSeconds
3714
+ });
3442
3715
  };
3443
3716
 
3444
3717
  const setUseDevtoolsLayout = (state, checked) => {
@@ -3489,26 +3762,70 @@ const getCss = state => {
3489
3762
  const hasSelectedEvent = !!state.selectedEvent;
3490
3763
  const tableWidth = hasSelectedEvent ? clampTableWidth(state.width, state.tableWidth) : getMainWidth(state.width);
3491
3764
  const detailsWidth = hasSelectedEvent ? getDetailsWidth(state.width, state.tableWidth) : 0;
3765
+ const topSize = state.width >= state.largeBreakpoint ? 30 : state.width >= state.mediumBreakpoint ? 60 : 60;
3492
3766
  const tableColumnLayout = getTableColumnLayout(tableWidth, state.visibleTableColumns, state.tableColumnWidths);
3493
- const resizerOneLeft = tableColumnLayout.resizerLefts[0] || 0;
3494
- const resizerTwoLeft = tableColumnLayout.resizerLefts[1] || 0;
3767
+ const [tableColZeroWidth = 0, tableColOneWidth = 0, tableColTwoWidth = 0] = tableColumnLayout.visibleColumnWidths;
3768
+ const resizerOneLeft = tableColumnLayout.resizerLefts[0] ?? 0;
3769
+ const resizerTwoLeft = tableColumnLayout.resizerLefts[1] ?? 0;
3770
+ const {
3771
+ selectionEndPercent,
3772
+ selectionStartPercent
3773
+ } = state.timelineInfo;
3495
3774
  return `
3496
3775
  .ChatDebugView {
3776
+ --ChatDebugViewTableHeaderHeight: ${devtoolsTableHeaderHeight}px;
3777
+ --ChatDebugViewTableColZeroWidth: ${tableColZeroWidth}px;
3778
+ --ChatDebugViewTableColOneWidth: ${tableColOneWidth}px;
3779
+ --ChatDebugViewTableColTwoWidth: ${tableColTwoWidth}px;
3497
3780
  --ChatDebugViewDetailsWidth: ${detailsWidth}px;
3498
3781
  --ChatDebugViewDurationColumnWidth: ${state.tableColumnWidths.duration}px;
3499
- --ChatDebugViewResizerOneLeft: ${resizerOneLeft}px;
3500
- --ChatDebugViewResizerTwoLeft: ${resizerTwoLeft}px;
3782
+ --ChatDebugViewTableRowHeight: ${devtoolsTableRowHeight}px;
3783
+ --ResizerOneLeft: ${resizerOneLeft}px;
3784
+ --ResizerTwoLeft: ${resizerTwoLeft}px;
3501
3785
  --ChatDebugViewSashWidth: ${sashWidth}px;
3502
3786
  --ChatDebugViewTableWidth: ${tableWidth}px;
3787
+ --ChatDebugViewTimelineCursorGuideLeft: ${state.timelineHoverPercent ?? 0}%;
3788
+ --ChatDebugViewTimelineSelectionEndLeft: ${selectionEndPercent ?? 0}%;
3789
+ --ChatDebugViewTimelineSelectionStartLeft: ${selectionStartPercent ?? 0}%;
3790
+ --ChatDebugViewTopSize: ${topSize}px;
3503
3791
  --ChatDebugViewTypeColumnWidth: ${state.tableColumnWidths.type}px;
3504
3792
  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;
3505
3814
  }
3506
3815
 
3507
3816
  .ChatDebugViewTop {
3508
3817
  display: flex;
3509
3818
  align-items: center;
3819
+ flex: 0 0 var(--ChatDebugViewTopSize);
3510
3820
  gap: 8px;
3821
+ height: var(--ChatDebugViewTopSize);
3822
+ min-height: var(--ChatDebugViewTopSize);
3511
3823
  min-width: 0;
3824
+ contain: strict;
3825
+ }
3826
+
3827
+ .ChatDebugViewTop--devtools {
3828
+ align-items: stretch;
3512
3829
  }
3513
3830
 
3514
3831
  .ChatDebugViewFilterInput {
@@ -3521,47 +3838,96 @@ const getCss = state => {
3521
3838
  min-width: 180px;
3522
3839
  }
3523
3840
 
3524
- .ChatDebugViewTableWrapper {
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 {
3525
3853
  position: relative;
3526
3854
  width: min(100%, var(--ChatDebugViewTableWidth));
3527
3855
  max-width: 100%;
3528
- flex:1;
3529
- display:flex
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;
3530
3865
  }
3531
3866
 
3532
- .ChatDebugViewTable {
3867
+ .Table {
3533
3868
  width: 100%;
3534
3869
  table-layout: fixed;
3535
3870
  border-collapse: collapse;
3536
- flex: 1;
3537
3871
  }
3538
3872
 
3539
- .ChatDebugViewHeaderCell,
3540
- .ChatDebugViewCell {
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;
3541
3893
  overflow: hidden;
3542
3894
  text-overflow: ellipsis;
3543
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;
3544
3907
  }
3545
3908
 
3546
- .ChatDebugViewHeaderCellType.ChatDebugViewColumnFixed,
3547
- .ChatDebugViewCellType.ChatDebugViewColumnFixed {
3548
- width: var(--ChatDebugViewTypeColumnWidth);
3549
- max-width: var(--ChatDebugViewTypeColumnWidth);
3909
+ .TableColZero {
3910
+ width: var(--ChatDebugViewTableColZeroWidth);
3911
+ max-width: var(--ChatDebugViewTableColZeroWidth);
3550
3912
  }
3551
3913
 
3552
- .ChatDebugViewHeaderCellDuration.ChatDebugViewColumnFixed,
3553
- .ChatDebugViewCellDuration.ChatDebugViewColumnFixed {
3554
- width: var(--ChatDebugViewDurationColumnWidth);
3555
- max-width: var(--ChatDebugViewDurationColumnWidth);
3914
+ .TableColOne {
3915
+ width: var(--ChatDebugViewTableColOneWidth);
3916
+ max-width: var(--ChatDebugViewTableColOneWidth);
3556
3917
  }
3557
3918
 
3558
- .ChatDebugViewResizers {
3919
+ .TableColTwo {
3920
+ width: var(--ChatDebugViewTableColTwoWidth);
3921
+ max-width: var(--ChatDebugViewTableColTwoWidth);
3922
+ }
3923
+
3924
+ .Resizers {
3559
3925
  position: absolute;
3560
3926
  inset: 0;
3561
3927
  pointer-events: none;
3562
3928
  }
3563
3929
 
3564
- .ChatDebugViewResizer {
3930
+ .Resizer {
3565
3931
  position: absolute;
3566
3932
  top: 0;
3567
3933
  bottom: 0;
@@ -3574,17 +3940,17 @@ const getCss = state => {
3574
3940
  cursor: col-resize;
3575
3941
  }
3576
3942
 
3577
- .ChatDebugViewResizerOne {
3578
- left: var(--ChatDebugViewResizerOneLeft);
3943
+ .ResizerOne {
3944
+ left: var(--ResizerOneLeft);
3579
3945
  transform: translateX(-50%);
3580
3946
  }
3581
3947
 
3582
- .ChatDebugViewResizerTwo {
3583
- left: var(--ChatDebugViewResizerTwoLeft);
3948
+ .ResizerTwo {
3949
+ left: var(--ResizerTwoLeft);
3584
3950
  transform: translateX(-50%);
3585
3951
  }
3586
3952
 
3587
- .ChatDebugViewResizerInner {
3953
+ .ResizerInner {
3588
3954
  position: absolute;
3589
3955
  top: 0;
3590
3956
  bottom: 0;
@@ -3595,37 +3961,57 @@ const getCss = state => {
3595
3961
  }
3596
3962
 
3597
3963
 
3598
- .ChatDebugViewDetails {
3599
- margin-left: auto;
3600
- min-height: 26px;
3601
- }
3602
- border: 1px solid transparent;
3603
- border-radius: 4px;
3604
- background: transparent;
3605
- color: var(--vscode-descriptionForeground, inherit);
3606
- }
3607
- font-size: 11px;
3608
- font-weight: 600;
3609
- letter-spacing: 0.02em;
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;
3610
3970
  display: flex;
3971
+ flex-direction: column;
3611
3972
  contain: strict;
3612
- flex:1;
3613
- transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease, transform 120ms ease;
3973
+ }
3614
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;
3615
3985
  }
3616
- .ChatDebugViewEvent {
3617
- border-color: var(--vscode-widget-border, rgba(255, 255, 255, 0.14));
3618
- background: var(--vscode-toolbar-hoverBackground, rgba(255, 255, 255, 0.06));
3986
+
3987
+ .ChatDebugViewDevtoolsSplit > .ChatDebugViewEvents.ChatDebugViewEventsFullWidth {
3988
+ flex: 1 1 100%;
3989
+ }
3990
+
3991
+ .ChatDebugViewDetailsBottom {
3619
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
+ }
3620
4007
 
3621
4008
  .ChatDebugViewEventLineContent {
3622
4009
  flex: 1;
3623
- background: var(--vscode-toolbar-activeBackground, rgba(255, 255, 255, 0.1));
3624
4010
  min-width: 0;
3625
4011
  overflow-wrap: anywhere;
3626
4012
  white-space: pre-wrap;
3627
4013
  word-break: break-word;
3628
- outline: 1px solid var(--vscode-focusBorder, rgba(255, 255, 255, 0.4));
4014
+ }
3629
4015
 
3630
4016
  .ChatDebugViewEventLineNumber {
3631
4017
  flex: none;
@@ -3634,6 +4020,7 @@ const getCss = state => {
3634
4020
  .row {
3635
4021
  flex-shrink: 0;
3636
4022
  min-width: 0;
4023
+ width: 100%;
3637
4024
  }
3638
4025
 
3639
4026
  .ChatDebugViewRefreshButton {
@@ -3671,7 +4058,34 @@ const getCss = state => {
3671
4058
  outline-offset: 1px;
3672
4059
  }
3673
4060
 
3674
- .ChatDebugViewEventRow:hover {
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 {
3675
4089
  background: var(--ListHoverBackground);
3676
4090
  color: var(--ListHoverForeground);
3677
4091
  }
@@ -3681,20 +4095,28 @@ const getCss = state => {
3681
4095
  flex-direction: column;
3682
4096
  align-items: flex-start;
3683
4097
  gap: 8px;
4098
+ width: 100%;
3684
4099
  max-width: 100%;
4100
+ min-height: 0;
3685
4101
  }
3686
4102
 
3687
4103
  .ChatDebugViewImagePreviewImage {
3688
4104
  display: block;
3689
4105
  max-width: 100%;
3690
- max-height: 320px;
4106
+ width: auto;
4107
+ height: auto;
4108
+ max-height: 100%;
4109
+ align-self: center;
3691
4110
  border: 1px solid var(--vscode-widget-border, rgba(255, 255, 255, 0.14));
3692
4111
  border-radius: 6px;
3693
4112
  object-fit: contain;
3694
4113
  }
3695
4114
 
3696
4115
  .ChatDebugViewImagePreviewLabel {
3697
- color: var(--vscode-descriptionForeground, inherit);
4116
+ width: auto;
4117
+ height: auto;
4118
+ max-height: 100%;
4119
+ align-self: center;
3698
4120
  }
3699
4121
 
3700
4122
  .ChatDebugViewTimeline {
@@ -3727,9 +4149,35 @@ const getCss = state => {
3727
4149
  user-select: none;
3728
4150
  }
3729
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
+
3730
4178
  .ChatDebugViewTimelineBuckets {
3731
4179
  position: absolute;
3732
- inset: 18px 8px 8px;
4180
+ inset: 20px 8px 8px;
3733
4181
  display: flex;
3734
4182
  align-items: flex-end;
3735
4183
  gap: 2px;
@@ -3773,11 +4221,27 @@ const getCss = state => {
3773
4221
  position: absolute;
3774
4222
  inset: 0;
3775
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);
3776
4240
  }
3777
4241
 
3778
4242
  .ChatDebugViewTimelineSelectionRange {
3779
4243
  position: absolute;
3780
- top: 18px;
4244
+ top: 20px;
3781
4245
  bottom: 8px;
3782
4246
  border-radius: 6px;
3783
4247
  background: color-mix(in srgb, var(--vscode-charts-orange, rgba(255, 174, 0, 0.95)) 18%, transparent);
@@ -3806,6 +4270,16 @@ const getCss = state => {
3806
4270
  cursor: ew-resize;
3807
4271
  }
3808
4272
 
4273
+ .ChatDebugViewTimelineSelectionHandleStart,
4274
+ .ChatDebugViewTimelineSelectionMarkerStart {
4275
+ left: var(--ChatDebugViewTimelineSelectionStartLeft);
4276
+ }
4277
+
4278
+ .ChatDebugViewTimelineSelectionHandleEnd,
4279
+ .ChatDebugViewTimelineSelectionMarkerEnd {
4280
+ left: var(--ChatDebugViewTimelineSelectionEndLeft);
4281
+ }
4282
+
3809
4283
  .ChatDebugViewTimelineSelectionHandle::before {
3810
4284
  content: '';
3811
4285
  position: absolute;
@@ -3852,7 +4326,11 @@ const getCss = state => {
3852
4326
  outline: 2px solid var(--vscode-focusBorder, rgba(255, 255, 255, 0.45));
3853
4327
  outline-offset: 1px;
3854
4328
  }
3855
- `;
4329
+
4330
+ .TokenString {
4331
+ white-space: nowrap;
4332
+ }
4333
+ `;
3856
4334
  };
3857
4335
 
3858
4336
  const renderCss = (oldState, newState) => {
@@ -4169,23 +4647,18 @@ const ChatDebugViewDetailsTab = 'ChatDebugViewDetailsTab';
4169
4647
  const ChatDebugViewDetailsTabSelected = 'ChatDebugViewDetailsTabSelected';
4170
4648
  const ChatDebugViewDetailsTabs = 'ChatDebugViewDetailsTabs';
4171
4649
  const ChatDebugViewDetailsTop = 'ChatDebugViewDetailsTop';
4172
- const ChatDebugViewDevtoolsMain = 'ChatDebugViewDevtoolsMain';
4173
4650
  const ChatDebugViewDevtoolsSplit = 'ChatDebugViewDevtoolsSplit';
4174
4651
  const ChatDebugViewEmpty = 'ChatDebugViewEmpty';
4175
4652
  const ChatDebugViewError = 'ChatDebugViewError';
4176
- const ChatDebugViewEvent = 'ChatDebugViewEvent';
4653
+ const ChatDebugViewEventRawText = 'ChatDebugViewEventRawText';
4177
4654
  const ChatDebugViewEventLineContent = 'ChatDebugViewEventLineContent';
4178
4655
  const ChatDebugViewEventLineNumber = 'ChatDebugViewEventLineNumber';
4179
- const ChatDebugViewEventRow = 'ChatDebugViewEventRow';
4180
- const ChatDebugViewEventRowSelected = 'ChatDebugViewEventRowSelected';
4656
+ const TableRowSelected = 'TableRowSelected';
4181
4657
  const ChatDebugViewEvents = 'ChatDebugViewEvents';
4182
4658
  const ChatDebugViewEventsFullWidth = 'ChatDebugViewEventsFullWidth';
4183
4659
  const ChatDebugViewFilterInput = 'ChatDebugViewFilterInput';
4184
4660
  const ChatDebugViewFilterInputDevtools = 'ChatDebugViewFilterInput--devtools';
4185
- const ChatDebugViewHeaderCell = 'ChatDebugViewHeaderCell';
4186
- const ChatDebugViewHeaderCellDuration = 'ChatDebugViewHeaderCellDuration';
4187
- const ChatDebugViewHeaderCellStatus = 'ChatDebugViewHeaderCellStatus';
4188
- const ChatDebugViewHeaderCellType = 'ChatDebugViewHeaderCellType';
4661
+ const ChatDebugViewHeaderCell = 'TableCell';
4189
4662
  const ChatDebugViewImagePreview = 'ChatDebugViewImagePreview';
4190
4663
  const ChatDebugViewImagePreviewImage = 'ChatDebugViewImagePreviewImage';
4191
4664
  const ChatDebugViewImagePreviewLabel = 'ChatDebugViewImagePreviewLabel';
@@ -4193,20 +4666,26 @@ const ChatDebugViewRefreshButton = 'ChatDebugViewRefreshButton';
4193
4666
  const ChatDebugViewQuickFilterPill = 'ChatDebugViewQuickFilterPill';
4194
4667
  const ChatDebugViewQuickFilterPillSelected = 'ChatDebugViewQuickFilterPillSelected';
4195
4668
  const ChatDebugViewQuickFilters = 'ChatDebugViewQuickFilters';
4196
- const ChatDebugViewSash = 'ChatDebugViewSash';
4669
+ const Sash = 'Sash';
4197
4670
  const ChatDebugViewSashLine = 'ChatDebugViewSashLine';
4198
- const ChatDebugViewTable = 'ChatDebugViewTable';
4199
- const ChatDebugViewTableBody = 'ChatDebugViewTableBody';
4200
- const ChatDebugViewTableHeader = 'ChatDebugViewTableHeader';
4201
- const ChatDebugViewTableHeaderRow = 'ChatDebugViewTableHeaderRow';
4202
- const ChatDebugViewTableWrapper = 'ChatDebugViewTableWrapper';
4203
- const ChatDebugViewResizer = 'ChatDebugViewResizer';
4204
- const ChatDebugViewResizerInner = 'ChatDebugViewResizerInner';
4205
- const ChatDebugViewResizerOne = 'ChatDebugViewResizerOne';
4206
- const ChatDebugViewResizerTwo = 'ChatDebugViewResizerTwo';
4207
- const ChatDebugViewResizers = 'ChatDebugViewResizers';
4671
+ const Table = 'Table';
4672
+ const TableBody = 'TableBody';
4673
+ const TableSummary = 'TableSummary';
4674
+ const TableWrapper = 'TableWrapper';
4675
+ const FocusOutline = 'FocusOutline';
4676
+ const Resizer = 'Resizer';
4677
+ const ResizerInner = 'ResizerInner';
4678
+ const ResizerOne = 'ResizerOne';
4679
+ const ResizerTwo = 'ResizerTwo';
4680
+ const TableHead = 'TableHead';
4681
+ const Resizers = 'Resizers';
4682
+ const TableCol = 'TableCol';
4683
+ const TableRow = 'TableRow';
4684
+ const TableRowOdd = 'TableRowOdd';
4208
4685
  const TableRowEven = 'TableRowEven';
4209
4686
  const ChatDebugViewTimeline = 'ChatDebugViewTimeline';
4687
+ const ChatDebugViewTimelineBadge = 'ChatDebugViewTimelineBadge';
4688
+ const ChatDebugViewTimelineBadges = 'ChatDebugViewTimelineBadges';
4210
4689
  const ChatDebugViewTimelineBucket = 'ChatDebugViewTimelineBucket';
4211
4690
  const ChatDebugViewTimelineBucketBar = 'ChatDebugViewTimelineBucketBar';
4212
4691
  const ChatDebugViewTimelineBucketBarSelected = 'ChatDebugViewTimelineBucketBarSelected';
@@ -4214,8 +4693,12 @@ const ChatDebugViewTimelineBucketSelected = 'ChatDebugViewTimelineBucketSelected
4214
4693
  const ChatDebugViewTimelineBucketUnit = 'ChatDebugViewTimelineBucketUnit';
4215
4694
  const ChatDebugViewTimelineBucketUnitEmpty = 'ChatDebugViewTimelineBucketUnitEmpty';
4216
4695
  const ChatDebugViewTimelineBuckets = 'ChatDebugViewTimelineBuckets';
4696
+ const ChatDebugViewTimelineCursorGuide = 'ChatDebugViewTimelineCursorGuide';
4697
+ const ChatDebugViewTimelineCursorGuideVisible = 'ChatDebugViewTimelineCursorGuideVisible';
4217
4698
  const ChatDebugViewTimelineInteractive = 'ChatDebugViewTimelineInteractive';
4218
4699
  const ChatDebugViewTimelineSelectionHandle = 'ChatDebugViewTimelineSelectionHandle';
4700
+ const ChatDebugViewTimelineSelectionHandleEnd = 'ChatDebugViewTimelineSelectionHandleEnd';
4701
+ const ChatDebugViewTimelineSelectionHandleStart = 'ChatDebugViewTimelineSelectionHandleStart';
4219
4702
  const ChatDebugViewTimelineSelectionMarker = 'ChatDebugViewTimelineSelectionMarker';
4220
4703
  const ChatDebugViewTimelineSelectionMarkerEnd = 'ChatDebugViewTimelineSelectionMarkerEnd';
4221
4704
  const ChatDebugViewTimelineSelectionMarkerStart = 'ChatDebugViewTimelineSelectionMarkerStart';
@@ -4229,12 +4712,9 @@ const ChatDebugViewTimingRow = 'ChatDebugViewTimingRow';
4229
4712
  const ChatDebugViewTimingValue = 'ChatDebugViewTimingValue';
4230
4713
  const ChatDebugViewTop = 'ChatDebugViewTop';
4231
4714
  const ChatDebugViewTopDevtools = 'ChatDebugViewTop--devtools';
4232
- const ChatDebugViewCell = 'ChatDebugViewCell';
4715
+ const TableCell = 'TableCell';
4233
4716
  const ChatDebugViewColumnFixed = 'ChatDebugViewColumnFixed';
4234
- const ChatDebugViewCellDuration = 'ChatDebugViewCellDuration';
4235
- const ChatDebugViewCellStatus = 'ChatDebugViewCellStatus';
4236
4717
  const ChatDebugViewCellStatusError = 'ChatDebugViewCellStatusError';
4237
- const ChatDebugViewCellType = 'ChatDebugViewCellType';
4238
4718
  const InputBox = 'InputBox';
4239
4719
  const Row = 'row';
4240
4720
  const TokenBoolean = 'Token TokenBoolean';
@@ -4260,7 +4740,7 @@ const getDebugErrorDom = errorMessage => {
4260
4740
  const HandleEventCategoryFilter = 4;
4261
4741
  const HandleFilterInput = 5;
4262
4742
  const SelectDetailTab = 6;
4263
- const HandleEventRowClick = 7;
4743
+ const HandleEventRowClickAt = 7;
4264
4744
  const HandleHeaderContextMenu = 8;
4265
4745
  const HandleSashPointerDown = 9;
4266
4746
  const HandleSashPointerMove = 10;
@@ -4274,11 +4754,44 @@ const HandleTimelinePointerDown = 17;
4274
4754
  const HandleTimelinePointerMove = 18;
4275
4755
  const HandleTimelinePointerUp = 19;
4276
4756
  const HandleTimelineDoubleClick = 20;
4757
+ const HandleTableHeaderClick = 21;
4277
4758
  const HandleTimelineRangePreset = 22;
4278
4759
  const HandleCloseDetails = 23;
4279
4760
  const HandleClickRefresh = 24;
4280
4761
  const HandleDetailsTopContextMenu = 25;
4281
4762
  const HandleTimelineContextMenu = 26;
4763
+ const HandleTimelinePointerLeave = 27;
4764
+ const HandleEventRowClick = 28;
4765
+ const HandleTableFocus = 29;
4766
+
4767
+ const getQuickFilterDom = categoryFilter => {
4768
+ const {
4769
+ isSelected,
4770
+ label,
4771
+ name
4772
+ } = categoryFilter;
4773
+ return [{
4774
+ ariaSelected: isSelected,
4775
+ childCount: 1,
4776
+ className: mergeClassNames(ChatDebugViewQuickFilterPill, isSelected ? ChatDebugViewQuickFilterPillSelected : ''),
4777
+ name,
4778
+ onClick: HandleEventCategoryFilter,
4779
+ role: Option,
4780
+ type: Button$1
4781
+ }, text(label)];
4782
+ };
4783
+
4784
+ // cspell:ignore multiselectable
4785
+ const getQuickFilterNodes = categoryFilters => {
4786
+ return [{
4787
+ 'aria-multiselectable': true,
4788
+ childCount: categoryFilters.length,
4789
+ className: ChatDebugViewQuickFilters,
4790
+ onClick: HandleEventCategoryFilter,
4791
+ role: ListBox,
4792
+ type: Div
4793
+ }, ...categoryFilters.flatMap(getQuickFilterDom)];
4794
+ };
4282
4795
 
4283
4796
  const refreshButtonDom = [{
4284
4797
  'aria-label': refreshEvents$1(),
@@ -4293,382 +4806,95 @@ const getRefreshButtonDom = () => {
4293
4806
  return refreshButtonDom;
4294
4807
  };
4295
4808
 
4296
- const getDebugViewTopDom = (filterValue, useDevtoolsLayout, quickFilterNodes) => {
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
+ const getDebugViewTopDom = (filterValue, useDevtoolsLayout, categoryFilters) => {
4297
4823
  const refreshButtonDom = getRefreshButtonDom();
4298
4824
  if (useDevtoolsLayout) {
4825
+ const quickFilterNodes = getQuickFilterNodes(categoryFilters);
4299
4826
  return [{
4300
4827
  childCount: 2 + (quickFilterNodes.length > 0 ? 1 : 0),
4301
4828
  className: mergeClassNames(ChatDebugViewTop, ChatDebugViewTopDevtools),
4302
4829
  onContextMenu: HandleHeaderContextMenu,
4303
4830
  type: Search
4304
- }, {
4305
- autocomplete: 'off',
4306
- childCount: 0,
4307
- className: mergeClassNames(InputBox, ChatDebugViewFilterInput, ChatDebugViewFilterInputDevtools),
4308
- inputType: 'search',
4309
- name: Filter,
4310
- onInput: HandleFilterInput,
4311
- placeholder: filterEvents(),
4312
- type: Input,
4313
- value: filterValue
4314
- }, ...quickFilterNodes, ...refreshButtonDom];
4831
+ }, getFilterInputDom(filterValue, true), ...quickFilterNodes, ...refreshButtonDom];
4315
4832
  }
4316
4833
  return [{
4317
4834
  childCount: 2,
4318
4835
  className: ChatDebugViewTop,
4319
4836
  onContextMenu: HandleHeaderContextMenu,
4320
4837
  type: Search
4321
- }, {
4322
- autocomplete: 'off',
4323
- childCount: 0,
4324
- className: mergeClassNames(InputBox, ChatDebugViewFilterInput),
4325
- inputType: 'search',
4326
- name: Filter,
4327
- onInput: HandleFilterInput,
4328
- placeholder: filterEvents(),
4329
- type: Input,
4330
- value: filterValue
4331
- }, ...refreshButtonDom];
4332
- };
4333
-
4334
- const None = 'none';
4335
-
4336
- const getPanelId = detailTab => {
4337
- return `ChatDebugViewDetailsPanel-${detailTab}`;
4338
- };
4339
-
4340
- const getTabId = detailTab => {
4341
- return `ChatDebugViewDetailsTab-${detailTab}`;
4342
- };
4343
-
4344
- const getDetailTabDom = detailTab => {
4345
- const {
4346
- isSelected
4347
- } = detailTab;
4348
- return [{
4349
- 'aria-controls': getPanelId(detailTab.name),
4350
- 'aria-selected': isSelected,
4351
- childCount: 1,
4352
- className: mergeClassNames(ChatDebugViewDetailsTab, isSelected ? ChatDebugViewDetailsTabSelected : ''),
4353
- id: getTabId(detailTab.name),
4354
- name: DetailTab,
4355
- onChange: SelectDetailTab,
4356
- onClick: SelectDetailTab,
4357
- role: 'tab',
4358
- tabIndex: isSelected ? 0 : -1,
4359
- type: Button$1,
4360
- value: detailTab.name
4361
- }, text(detailTab.label)];
4362
- };
4363
-
4364
- const getTabNodes = detailTabs => {
4365
- return [{
4366
- 'aria-label': detailSections(),
4367
- childCount: detailTabs.length,
4368
- className: ChatDebugViewDetailsTabs,
4369
- role: 'tablist',
4370
- type: Div
4371
- }, ...detailTabs.flatMap(getDetailTabDom)];
4372
- };
4373
-
4374
- const getDurationText = event => {
4375
- const explicitDuration = event.durationMs ?? event.duration;
4376
- if (typeof explicitDuration === 'number' && Number.isFinite(explicitDuration)) {
4377
- return `${explicitDuration}ms`;
4378
- }
4379
- const start = toTimeNumber(event.started ?? event.startTime ?? event.startTimestamp ?? event.timestamp);
4380
- const end = toTimeNumber(event.ended ?? event.endTime ?? event.endTimestamp ?? event.timestamp);
4381
- if (start === undefined || end === undefined || end < start) {
4382
- return '-';
4383
- }
4384
- return `${end - start}ms`;
4385
- };
4386
-
4387
- const timestampFormatter = new Intl.DateTimeFormat('en-US', {
4388
- day: '2-digit',
4389
- fractionalSecondDigits: 3,
4390
- hour: '2-digit',
4391
- hourCycle: 'h23',
4392
- minute: '2-digit',
4393
- month: 'short',
4394
- second: '2-digit',
4395
- timeZone: 'UTC',
4396
- year: 'numeric'
4397
- });
4398
- const formatTimestamp = date => {
4399
- return `${timestampFormatter.format(date)} UTC`;
4400
- };
4401
-
4402
- const getTimestampText = value => {
4403
- if (typeof value === 'string') {
4404
- const timestamp = Date.parse(value);
4405
- if (!Number.isNaN(timestamp)) {
4406
- return formatTimestamp(new Date(timestamp));
4407
- }
4408
- return value;
4409
- }
4410
- if (typeof value === 'number' && Number.isFinite(value)) {
4411
- return formatTimestamp(new Date(value));
4412
- }
4413
- return '-';
4414
- };
4415
-
4416
- const getEndText = event => {
4417
- return getTimestampText(event.ended ?? event.endTime ?? event.endTimestamp ?? event.timestamp);
4418
- };
4419
-
4420
- const getStartText = event => {
4421
- return getTimestampText(event.started ?? event.startTime ?? event.startTimestamp ?? event.timestamp);
4838
+ }, getFilterInputDom(filterValue, false), ...refreshButtonDom];
4422
4839
  };
4423
4840
 
4424
- const timingRowNode = {
4425
- childCount: 2,
4426
- className: ChatDebugViewTimingRow,
4427
- type: Div
4428
- };
4429
- const timingLabelNode = {
4430
- childCount: 1,
4431
- className: ChatDebugViewTimingLabel,
4432
- type: Span
4433
- };
4434
- const timingValueNode = {
4841
+ const detailsCloseButtonDom = [{
4842
+ 'aria-label': closeDetails(),
4435
4843
  childCount: 1,
4436
- className: ChatDebugViewTimingValue,
4437
- type: Span
4438
- };
4439
- const getTimingRowDom = (label, value) => {
4440
- return [timingRowNode, timingLabelNode, text(label), timingValueNode, text(value)];
4441
- };
4442
-
4443
- const getTimingDetailsDom = event => {
4444
- return [{
4445
- childCount: 3,
4446
- className: ChatDebugViewTiming,
4447
- type: Div
4448
- }, ...getTimingRowDom(started(), getStartText(event)), ...getTimingRowDom(ended(), getEndText(event)), ...getTimingRowDom(duration(), getDurationText(event))];
4844
+ className: ChatDebugViewDetailsClose,
4845
+ name: CloseDetails,
4846
+ onChange: HandleCloseDetails,
4847
+ onClick: HandleCloseDetails,
4848
+ type: Button$1,
4849
+ value: 'close'
4850
+ }, {
4851
+ childCount: 0,
4852
+ className: 'MaskIcon MaskIconClose',
4853
+ type: Div
4854
+ }];
4855
+ const getDetailsCloseButtonDom = () => {
4856
+ return detailsCloseButtonDom;
4449
4857
  };
4450
4858
 
4451
- const getContentNode = (previewEventNodes, payloadEventNodes, responseEventNodes, selectedEvent, detailTabs) => {
4452
- const safeSelectedDetailTab = getSelectedDetailTab(detailTabs);
4453
- const contentNodes = safeSelectedDetailTab === Timing && selectedEvent ? getTimingDetailsDom(selectedEvent) : safeSelectedDetailTab === Preview ? previewEventNodes : safeSelectedDetailTab === Payload ? payloadEventNodes : responseEventNodes;
4454
- return {
4455
- contentNodes,
4456
- safeSelectedDetailTab
4457
- };
4458
- };
4459
- const getDetailsDom = (previewEventNodes, payloadEventNodes = previewEventNodes, responseEventNodes = payloadEventNodes, selectedEvent = null, detailTabs = createDetailTabs()) => {
4460
- if (previewEventNodes.length === 0 && payloadEventNodes.length === 0 && responseEventNodes.length === 0) {
4461
- return [];
4462
- }
4463
- const normalizedDetailTabs = selectedEvent ? createDetailTabs(getSelectedDetailTab(detailTabs), selectedEvent) : detailTabs;
4464
- const {
4465
- contentNodes,
4466
- safeSelectedDetailTab
4467
- } = getContentNode(previewEventNodes, payloadEventNodes, responseEventNodes, selectedEvent, normalizedDetailTabs);
4859
+ const getLineNodeDom = (line, index) => {
4468
4860
  return [{
4469
4861
  childCount: 2,
4470
- className: ChatDebugViewDetails,
4471
- type: Section
4472
- }, {
4473
- childCount: 2,
4474
- className: ChatDebugViewDetailsTop,
4475
- onContextMenu: HandleDetailsTopContextMenu,
4862
+ className: Row,
4476
4863
  type: Div
4477
4864
  }, {
4478
- 'aria-label': closeDetails(),
4479
- childCount: 0,
4480
- className: ChatDebugViewDetailsClose,
4481
- name: CloseDetails,
4482
- onChange: HandleCloseDetails,
4483
- onClick: HandleCloseDetails,
4484
- type: Button$1,
4485
- value: 'close'
4486
- }, ...getTabNodes(normalizedDetailTabs), {
4487
- 'aria-labelledby': getTabId(safeSelectedDetailTab),
4488
4865
  childCount: 1,
4489
- className: ChatDebugViewDetailsBottom,
4490
- id: getPanelId(safeSelectedDetailTab),
4491
- onContextMenu: HandleDetailsContextMenu,
4492
- role: 'tabpanel',
4493
- type: Div
4494
- }, ...contentNodes];
4495
- };
4496
-
4497
- const toolExecutionTypePrefix = 'tool-execution';
4498
- const getToolName = event => {
4499
- if (typeof event.toolName === 'string' && event.toolName) {
4500
- return event.toolName;
4501
- }
4502
- if (typeof event.name === 'string' && event.name) {
4503
- return event.name;
4504
- }
4505
- const {
4506
- arguments: toolArguments
4507
- } = event;
4508
- if (!toolArguments || typeof toolArguments !== 'object') {
4509
- return undefined;
4510
- }
4511
- const {
4512
- name
4513
- } = toolArguments;
4514
- if (typeof name !== 'string' || !name) {
4515
- return undefined;
4516
- }
4517
- return name;
4866
+ className: ChatDebugViewEventLineNumber,
4867
+ type: Span
4868
+ }, text(String(index + 1)), {
4869
+ childCount: line.childCount,
4870
+ className: ChatDebugViewEventLineContent,
4871
+ type: Span
4872
+ }, ...line.nodes];
4518
4873
  };
4519
- const getEventTypeLabel = event => {
4520
- if (!event.type.startsWith(toolExecutionTypePrefix)) {
4521
- return event.type;
4522
- }
4523
- const toolName = getToolName(event);
4524
- if (!toolName) {
4525
- return event.type;
4526
- }
4527
- return `${event.type}, ${toolName}`;
4874
+ const getLineNodes = lines => {
4875
+ return lines.flatMap(getLineNodeDom);
4528
4876
  };
4529
4877
 
4530
- const isErrorStatusCode = value => {
4531
- if (typeof value === 'number') {
4532
- return value >= 400;
4533
- }
4534
- if (typeof value === 'string') {
4535
- const parsedStatus = Number(value);
4536
- return Number.isFinite(parsedStatus) && parsedStatus >= 400;
4537
- }
4538
- return false;
4878
+ const isDigit = character => {
4879
+ return character !== undefined && character >= '0' && character <= '9';
4539
4880
  };
4540
-
4541
- const isRecord = value => {
4542
- return typeof value === 'object' && value !== null;
4881
+ const isWhitespace = character => {
4882
+ return character === ' ' || character === '\n' || character === '\r' || character === '\t';
4543
4883
  };
4544
-
4545
- const hasErrorStatus = event => {
4546
- if (event.type === 'error') {
4547
- return true;
4884
+ const getNumberEnd = (json, start) => {
4885
+ let i = start;
4886
+ if (json[i] === '-') {
4887
+ i++;
4548
4888
  }
4549
- if (event.success === false || event.ok === false) {
4550
- return true;
4551
- }
4552
- const {
4553
- status
4554
- } = event;
4555
- if (isErrorStatusCode(status)) {
4556
- return true;
4557
- }
4558
- const {
4559
- result
4560
- } = event;
4561
- if (isRecord(result)) {
4562
- if (isErrorStatusCode(result.status)) {
4563
- return true;
4564
- }
4565
- if (isToolEvent(event) && 'error' in result && result.error !== undefined) {
4566
- return true;
4567
- }
4568
- if (typeof result.error === 'string' || typeof result.errorMessage === 'string' || typeof result.exception === 'string') {
4569
- return true;
4570
- }
4571
- }
4572
- return typeof event.error === 'string' || typeof event.errorMessage === 'string' || typeof event.exception === 'string';
4573
- };
4574
-
4575
- const getStatusText = event => {
4576
- return hasErrorStatus(event) ? '400' : '200';
4577
- };
4578
-
4579
- const getRowCellNodes = (event, isErrorStatus, visibleTableColumns) => {
4580
- const orderedVisibleTableColumns = getOrderedVisibleTableColumns(visibleTableColumns);
4581
- return orderedVisibleTableColumns.flatMap((column, index) => {
4582
- const isFixed = index < orderedVisibleTableColumns.length - 1;
4583
- switch (column) {
4584
- case Duration:
4585
- return [{
4586
- childCount: 1,
4587
- className: mergeClassNames(ChatDebugViewCell, ChatDebugViewCellDuration, isFixed ? ChatDebugViewColumnFixed : ''),
4588
- type: Td
4589
- }, text(getDurationText(event))];
4590
- case Status:
4591
- return [{
4592
- childCount: 1,
4593
- className: mergeClassNames(ChatDebugViewCell, ChatDebugViewCellStatus, isErrorStatus ? ChatDebugViewCellStatusError : '', isFixed ? ChatDebugViewColumnFixed : ''),
4594
- type: Td
4595
- }, text(getStatusText(event))];
4596
- case Type:
4597
- return [{
4598
- childCount: 1,
4599
- className: mergeClassNames(ChatDebugViewCell, ChatDebugViewCellType, isFixed ? ChatDebugViewColumnFixed : ''),
4600
- type: Td
4601
- }, text(getEventTypeLabel(event))];
4602
- default:
4603
- return [];
4604
- }
4605
- });
4606
- };
4607
-
4608
- const getDevtoolsRows = (events, selectedEventIndex, visibleTableColumns = defaultVisibleTableColumns) => {
4609
- return events.flatMap((event, i) => {
4610
- const isEvenRow = i % 2 === 1;
4611
- const isSelected = selectedEventIndex === i;
4612
- const isErrorStatus = hasErrorStatus(event);
4613
- const rowIndex = String(i);
4614
- const rowCellNodes = getRowCellNodes(event, isErrorStatus, visibleTableColumns);
4615
- return [{
4616
- childCount: visibleTableColumns.length,
4617
- className: mergeClassNames(ChatDebugViewEventRow, isEvenRow ? TableRowEven : '', isSelected ? ChatDebugViewEventRowSelected : ''),
4618
- 'data-index': rowIndex,
4619
- type: Tr
4620
- }, ...rowCellNodes];
4621
- });
4622
- };
4623
-
4624
- const emptyStateNode = {
4625
- childCount: 1,
4626
- className: ChatDebugViewEmpty,
4627
- type: Div
4628
- };
4629
- const getEmptyStateDom = emptyMessage => {
4630
- return [emptyStateNode, text(emptyMessage)];
4631
- };
4632
-
4633
- const getLineNodeDom = (line, index) => {
4634
- return [{
4635
- childCount: 2,
4636
- className: Row,
4637
- type: Div
4638
- }, {
4639
- childCount: 1,
4640
- className: ChatDebugViewEventLineNumber,
4641
- type: Span
4642
- }, text(String(index + 1)), {
4643
- childCount: line.childCount,
4644
- className: ChatDebugViewEventLineContent,
4645
- type: Span
4646
- }, ...line.nodes];
4647
- };
4648
- const getLineNodes = lines => {
4649
- return lines.flatMap(getLineNodeDom);
4650
- };
4651
-
4652
- const isDigit = character => {
4653
- return character !== undefined && character >= '0' && character <= '9';
4654
- };
4655
- const isWhitespace = character => {
4656
- return character === ' ' || character === '\n' || character === '\r' || character === '\t';
4657
- };
4658
- const getNumberEnd = (json, start) => {
4659
- let i = start;
4660
- if (json[i] === '-') {
4661
- i++;
4662
- }
4663
- if (json[i] === '0') {
4664
- i++;
4665
- } else {
4666
- if (!isDigit(json[i])) {
4667
- return start;
4668
- }
4669
- while (isDigit(json[i])) {
4670
- i++;
4671
- }
4889
+ if (json[i] === '0') {
4890
+ i++;
4891
+ } else {
4892
+ if (!isDigit(json[i])) {
4893
+ return start;
4894
+ }
4895
+ while (isDigit(json[i])) {
4896
+ i++;
4897
+ }
4672
4898
  }
4673
4899
  if (json[i] === '.') {
4674
4900
  const decimalStart = i;
@@ -4812,16 +5038,11 @@ const getEventNode = value => {
4812
5038
  nodes: lineContentNodes
4813
5039
  };
4814
5040
  }));
4815
- return [{
4816
- childCount: lines.length,
4817
- className: ChatDebugViewEvent,
4818
- type: Div
4819
- }, ...lineNodes];
5041
+ return lineNodes;
4820
5042
  };
4821
5043
 
4822
- const getEventsClassName = hasSelectedEvent => {
4823
- const widthClassName = mergeClassNames(ChatDebugViewEvents, hasSelectedEvent ? '' : ChatDebugViewEventsFullWidth);
4824
- return widthClassName;
5044
+ const getPanelId = detailTab => {
5045
+ return `ChatDebugViewDetailsPanel-${detailTab}`;
4825
5046
  };
4826
5047
 
4827
5048
  const getPreviewName = event => {
@@ -4850,6 +5071,9 @@ const shouldIncludeArguments = (event, name) => {
4850
5071
 
4851
5072
  const getPayloadEvent = event => {
4852
5073
  const name = getPreviewName(event);
5074
+ if (name === 'list_files' && hasOwn(event, 'arguments')) {
5075
+ return event.arguments;
5076
+ }
4853
5077
  const payloadEvent = {
4854
5078
  ...(name === undefined ? {} : {
4855
5079
  name
@@ -4867,6 +5091,22 @@ const getPayloadEvent = event => {
4867
5091
  return event;
4868
5092
  };
4869
5093
 
5094
+ const getListFilesPreviewEvent = (event, name) => {
5095
+ if (name !== 'list_files') {
5096
+ return undefined;
5097
+ }
5098
+ const {
5099
+ result
5100
+ } = event;
5101
+ if (typeof result !== 'object' || result === null || !Object.hasOwn(result, 'entries')) {
5102
+ return undefined;
5103
+ }
5104
+ const {
5105
+ entries
5106
+ } = result;
5107
+ return entries;
5108
+ };
5109
+
4870
5110
  const isChatMessageAddedEvent = event => {
4871
5111
  return event.type === 'chat-message-added';
4872
5112
  };
@@ -4875,10 +5115,64 @@ const isChatMessageUpdatedEvent = event => {
4875
5115
  return event.type === 'chat-message-updated';
4876
5116
  };
4877
5117
 
5118
+ const getResponseContentText = content => {
5119
+ if (!content || typeof content !== 'object') {
5120
+ return undefined;
5121
+ }
5122
+ if (Array.isArray(content)) {
5123
+ const [firstContentItem] = content;
5124
+ if (!firstContentItem || typeof firstContentItem !== 'object') {
5125
+ return undefined;
5126
+ }
5127
+ const {
5128
+ text
5129
+ } = firstContentItem;
5130
+ return typeof text === 'string' ? text : undefined;
5131
+ }
5132
+ const {
5133
+ text
5134
+ } = content;
5135
+ return typeof text === 'string' ? text : undefined;
5136
+ };
5137
+ const getSseResponseCompletedPreviewText = event => {
5138
+ if (event.type !== 'sse-response-completed') {
5139
+ return undefined;
5140
+ }
5141
+ const {
5142
+ value
5143
+ } = event;
5144
+ if (!value || typeof value !== 'object') {
5145
+ return undefined;
5146
+ }
5147
+ const {
5148
+ response
5149
+ } = value;
5150
+ if (!response || typeof response !== 'object') {
5151
+ return undefined;
5152
+ }
5153
+ const {
5154
+ output
5155
+ } = response;
5156
+ if (!Array.isArray(output) || output.length === 0) {
5157
+ return undefined;
5158
+ }
5159
+ const [firstOutput] = output;
5160
+ if (!firstOutput || typeof firstOutput !== 'object') {
5161
+ return undefined;
5162
+ }
5163
+ const {
5164
+ content
5165
+ } = firstOutput;
5166
+ return getResponseContentText(content);
5167
+ };
4878
5168
  const getPreviewMessageText = event => {
4879
5169
  if (isChatMessageUpdatedEvent(event) && typeof event.text === 'string') {
4880
5170
  return event.text;
4881
5171
  }
5172
+ const sseResponseCompletedPreviewText = getSseResponseCompletedPreviewText(event);
5173
+ if (sseResponseCompletedPreviewText !== undefined) {
5174
+ return sseResponseCompletedPreviewText;
5175
+ }
4882
5176
  if (!isChatMessageAddedEvent(event)) {
4883
5177
  return undefined;
4884
5178
  }
@@ -4900,6 +5194,19 @@ const getPreviewMessageText = event => {
4900
5194
  return text;
4901
5195
  };
4902
5196
 
5197
+ const getReadFilePreviewText = (event, name) => {
5198
+ if (name !== 'read_file') {
5199
+ return undefined;
5200
+ }
5201
+ const {
5202
+ result
5203
+ } = event;
5204
+ if (typeof result !== 'string') {
5205
+ return undefined;
5206
+ }
5207
+ return result;
5208
+ };
5209
+
4903
5210
  const getWriteFilePreviewText = (event, name) => {
4904
5211
  if (name !== 'write_file') {
4905
5212
  return undefined;
@@ -4919,82 +5226,338 @@ const getWriteFilePreviewText = (event, name) => {
4919
5226
  return content;
4920
5227
  };
4921
5228
 
4922
- const getPreviewEvent = event => {
4923
- const selectedEventPreview = getSelectedEventPreview(event);
4924
- if (selectedEventPreview !== undefined) {
4925
- return selectedEventPreview;
4926
- }
4927
- const previewMessageText = getPreviewMessageText(event);
4928
- if (previewMessageText !== undefined) {
4929
- return previewMessageText;
4930
- }
4931
- const name = getPreviewName(event);
4932
- const writeFilePreviewText = getWriteFilePreviewText(event, name);
4933
- if (writeFilePreviewText !== undefined) {
4934
- return writeFilePreviewText;
4935
- }
4936
- return getPayloadEvent(event);
5229
+ const getPreviewEvent = event => {
5230
+ const selectedEventPreview = getSelectedEventPreview(event);
5231
+ if (selectedEventPreview !== undefined) {
5232
+ return selectedEventPreview;
5233
+ }
5234
+ const previewMessageText = getPreviewMessageText(event);
5235
+ if (previewMessageText !== undefined) {
5236
+ return previewMessageText;
5237
+ }
5238
+ const name = getPreviewName(event);
5239
+ const writeFilePreviewText = getWriteFilePreviewText(event, name);
5240
+ if (writeFilePreviewText !== undefined) {
5241
+ return writeFilePreviewText;
5242
+ }
5243
+ const readFilePreviewText = getReadFilePreviewText(event, name);
5244
+ if (readFilePreviewText !== undefined) {
5245
+ return readFilePreviewText;
5246
+ }
5247
+ const listFilesPreviewEvent = getListFilesPreviewEvent(event, name);
5248
+ if (listFilesPreviewEvent !== undefined) {
5249
+ return listFilesPreviewEvent;
5250
+ }
5251
+ return getPayloadEvent(event);
5252
+ };
5253
+
5254
+ const isAttachmentImagePreview = value => {
5255
+ return typeof value === 'object' && value !== null && value.previewType === 'image';
5256
+ };
5257
+
5258
+ const getImagePreviewDom = preview => {
5259
+ return [{
5260
+ childCount: 2,
5261
+ className: ChatDebugViewImagePreview,
5262
+ type: Div
5263
+ }, {
5264
+ alt: preview.alt,
5265
+ childCount: 0,
5266
+ className: ChatDebugViewImagePreviewImage,
5267
+ src: preview.src,
5268
+ type: Img
5269
+ }, {
5270
+ childCount: 1,
5271
+ className: ChatDebugViewImagePreviewLabel,
5272
+ type: Span
5273
+ }, text(preview.alt)];
5274
+ };
5275
+
5276
+ const getTextNode = (value, showLineNumbers = true) => {
5277
+ if (!showLineNumbers) {
5278
+ return [{
5279
+ childCount: 1,
5280
+ className: ChatDebugViewEventRawText,
5281
+ type: P
5282
+ }, text(value)];
5283
+ }
5284
+ const lines = value.split('\n');
5285
+ const lineData = lines.map(line => {
5286
+ return {
5287
+ childCount: 1,
5288
+ nodes: [{
5289
+ childCount: 1,
5290
+ className: TokenText,
5291
+ type: Span
5292
+ }, text(line)]
5293
+ };
5294
+ });
5295
+ const lineNodes = getLineNodes(lineData);
5296
+ return lineNodes;
5297
+ };
5298
+
5299
+ const getPreviewEventNodes = (previewEvent, selectedEvent) => {
5300
+ if (typeof previewEvent === 'string') {
5301
+ const isInvalidImageMessage = previewEvent === ImageCouldNotBeLoaded;
5302
+ const isChatMessageUpdatedPreview = !!selectedEvent && isChatMessageUpdatedEvent(selectedEvent);
5303
+ const showLineNumbers = !isInvalidImageMessage && !isChatMessageUpdatedPreview;
5304
+ return getTextNode(previewEvent, showLineNumbers);
5305
+ }
5306
+ if (previewEvent === undefined) {
5307
+ return [];
5308
+ }
5309
+ if (isAttachmentImagePreview(previewEvent)) {
5310
+ return getImagePreviewDom(previewEvent);
5311
+ }
5312
+ return getEventNode(previewEvent);
5313
+ };
5314
+
5315
+ const getTabId = detailTab => {
5316
+ return `ChatDebugViewDetailsTab-${detailTab}`;
5317
+ };
5318
+
5319
+ const getDetailTabDom = detailTab => {
5320
+ const {
5321
+ isSelected
5322
+ } = detailTab;
5323
+ return [{
5324
+ 'aria-controls': getPanelId(detailTab.name),
5325
+ ariaSelected: isSelected,
5326
+ childCount: 1,
5327
+ className: mergeClassNames(ChatDebugViewDetailsTab, isSelected ? ChatDebugViewDetailsTabSelected : ''),
5328
+ id: getTabId(detailTab.name),
5329
+ name: detailTab.name,
5330
+ onChange: SelectDetailTab,
5331
+ onClick: SelectDetailTab,
5332
+ role: Tab,
5333
+ tabIndex: isSelected ? 0 : -1,
5334
+ type: Button$1
5335
+ }, text(detailTab.label)];
5336
+ };
5337
+
5338
+ const getTabNodes = detailTabs => {
5339
+ return [{
5340
+ 'aria-label': detailSections(),
5341
+ childCount: detailTabs.length,
5342
+ className: ChatDebugViewDetailsTabs,
5343
+ role: 'tablist',
5344
+ type: Div
5345
+ }, ...detailTabs.flatMap(getDetailTabDom)];
5346
+ };
5347
+
5348
+ const timestampFormatter = new Intl.DateTimeFormat('en-US', {
5349
+ day: '2-digit',
5350
+ fractionalSecondDigits: 3,
5351
+ hour: '2-digit',
5352
+ hourCycle: 'h23',
5353
+ minute: '2-digit',
5354
+ month: 'short',
5355
+ second: '2-digit',
5356
+ timeZone: 'UTC',
5357
+ year: 'numeric'
5358
+ });
5359
+ const formatTimestamp = date => {
5360
+ return `${timestampFormatter.format(date)} UTC`;
5361
+ };
5362
+
5363
+ const getTimestampText = value => {
5364
+ if (typeof value === 'string') {
5365
+ const timestamp = Date.parse(value);
5366
+ if (!Number.isNaN(timestamp)) {
5367
+ return formatTimestamp(new Date(timestamp));
5368
+ }
5369
+ return value;
5370
+ }
5371
+ if (typeof value === 'number' && Number.isFinite(value)) {
5372
+ return formatTimestamp(new Date(value));
5373
+ }
5374
+ return '-';
5375
+ };
5376
+
5377
+ const getEndText = event => {
5378
+ return getTimestampText(event.ended ?? event.endTime ?? event.endTimestamp ?? event.timestamp);
5379
+ };
5380
+
5381
+ const getStartText = event => {
5382
+ return getTimestampText(event.started ?? event.startTime ?? event.startTimestamp ?? event.timestamp);
5383
+ };
5384
+
5385
+ const timingRowNode = {
5386
+ childCount: 2,
5387
+ className: ChatDebugViewTimingRow,
5388
+ type: Div
5389
+ };
5390
+ const timingLabelNode = {
5391
+ childCount: 1,
5392
+ className: ChatDebugViewTimingLabel,
5393
+ type: Span
5394
+ };
5395
+ const timingValueNode = {
5396
+ childCount: 1,
5397
+ className: ChatDebugViewTimingValue,
5398
+ type: Span
5399
+ };
5400
+ const getTimingRowDom = (label, value) => {
5401
+ return [timingRowNode, timingLabelNode, text(label), timingValueNode, text(value)];
5402
+ };
5403
+
5404
+ const getTimingDetailsDom = event => {
5405
+ return [{
5406
+ childCount: 3,
5407
+ className: ChatDebugViewTiming,
5408
+ type: Div
5409
+ }, ...getTimingRowDom(started(), getStartText(event)), ...getTimingRowDom(ended(), getEndText(event)), ...getTimingRowDom(duration(), getDurationText(event))];
5410
+ };
5411
+
5412
+ const getNextSiblingIndex$1 = (nodes, index) => {
5413
+ let nextSiblingIndex = index + 1;
5414
+ const childCount = nodes[index]?.childCount || 0;
5415
+ for (let i = 0; i < childCount; i++) {
5416
+ nextSiblingIndex = getNextSiblingIndex$1(nodes, nextSiblingIndex);
5417
+ }
5418
+ return nextSiblingIndex;
5419
+ };
5420
+ const getDirectChildCount = nodes => {
5421
+ let count = 0;
5422
+ let index = 0;
5423
+ while (index < nodes.length) {
5424
+ count++;
5425
+ index = getNextSiblingIndex$1(nodes, index);
5426
+ }
5427
+ return count;
5428
+ };
5429
+ const getNormalizedDetailTabs = (selectedEvent, detailTabs) => {
5430
+ if (selectedEvent === null) {
5431
+ return detailTabs;
5432
+ }
5433
+ return createDetailTabs(getSelectedDetailTab(detailTabs), selectedEvent);
5434
+ };
5435
+ const getDetailsDom = (previewEventNodes, payloadEventNodes = previewEventNodes, responseEventNodes = payloadEventNodes, selectedEvent = null, detailTabs = createDetailTabs()) => {
5436
+ if (previewEventNodes.length === 0 && payloadEventNodes.length === 0 && responseEventNodes.length === 0) {
5437
+ return [];
5438
+ }
5439
+ const normalizedDetailTabs = getNormalizedDetailTabs(selectedEvent, detailTabs);
5440
+ const safeSelectedDetailTab = getSelectedDetailTab(normalizedDetailTabs);
5441
+ const getDetailContentDom = () => {
5442
+ const getDetailContentDomTiming = () => {
5443
+ if (selectedEvent === null) {
5444
+ return responseEventNodes;
5445
+ }
5446
+ return getTimingDetailsDom(selectedEvent);
5447
+ };
5448
+ const getDetailContentDomPreview = () => {
5449
+ if (previewEventNodes.length > 0) {
5450
+ return previewEventNodes;
5451
+ }
5452
+ if (selectedEvent === null) {
5453
+ return [];
5454
+ }
5455
+ return getPreviewEventNodes(getPreviewEvent(selectedEvent), selectedEvent);
5456
+ };
5457
+ const getDetailContentDomPayload = () => {
5458
+ if (payloadEventNodes.length > 0) {
5459
+ return payloadEventNodes;
5460
+ }
5461
+ if (selectedEvent === null) {
5462
+ return [];
5463
+ }
5464
+ return getEventNode(getPayloadEvent(selectedEvent));
5465
+ };
5466
+ const getDetailContentDomResponse = () => {
5467
+ if (responseEventNodes.length > 0) {
5468
+ return responseEventNodes;
5469
+ }
5470
+ if (selectedEvent === null) {
5471
+ return [];
5472
+ }
5473
+ return getEventNode(selectedEvent);
5474
+ };
5475
+ const contentNodes = safeSelectedDetailTab === Timing ? getDetailContentDomTiming() : safeSelectedDetailTab === Preview ? getDetailContentDomPreview() : safeSelectedDetailTab === Payload ? getDetailContentDomPayload() : getDetailContentDomResponse();
5476
+ return [{
5477
+ 'aria-labelledby': getTabId(safeSelectedDetailTab),
5478
+ childCount: getDirectChildCount(contentNodes),
5479
+ className: ChatDebugViewDetailsBottom,
5480
+ id: getPanelId(safeSelectedDetailTab),
5481
+ onContextMenu: HandleDetailsContextMenu,
5482
+ role: 'tabpanel',
5483
+ type: Div
5484
+ }, ...contentNodes];
5485
+ };
5486
+ return [{
5487
+ childCount: 2,
5488
+ className: ChatDebugViewDetails,
5489
+ type: Section
5490
+ }, {
5491
+ childCount: 2,
5492
+ className: ChatDebugViewDetailsTop,
5493
+ onContextMenu: HandleDetailsTopContextMenu,
5494
+ type: Div
5495
+ }, ...getDetailsCloseButtonDom(), ...getTabNodes(normalizedDetailTabs), ...getDetailContentDom()];
5496
+ };
5497
+
5498
+ const getRowCellNodes = (event, isErrorStatus, visibleTableColumns) => {
5499
+ const orderedVisibleTableColumns = getOrderedVisibleTableColumns(visibleTableColumns);
5500
+ return orderedVisibleTableColumns.flatMap((column, index) => {
5501
+ const isFixed = index < orderedVisibleTableColumns.length - 1;
5502
+ switch (column) {
5503
+ case Duration:
5504
+ return [{
5505
+ childCount: 1,
5506
+ className: TableCell,
5507
+ type: Td
5508
+ }, text(getEventTableDurationText(event))];
5509
+ case Status$1:
5510
+ return [{
5511
+ childCount: 1,
5512
+ className: mergeClassNames(TableCell, isErrorStatus ? ChatDebugViewCellStatusError : '', isFixed ? ChatDebugViewColumnFixed : ''),
5513
+ type: Td
5514
+ }, text(getStatusText(event))];
5515
+ case Type:
5516
+ return [{
5517
+ childCount: 1,
5518
+ className: TableCell,
5519
+ type: Td
5520
+ }, text(getEventTableTypeLabel(event))];
5521
+ default:
5522
+ return [];
5523
+ }
5524
+ });
4937
5525
  };
4938
5526
 
4939
- const isAttachmentImagePreview = value => {
4940
- return typeof value === 'object' && value !== null && value.previewType === 'image';
5527
+ const getDevtoolsRows = (events, selectedEventIndex, visibleTableColumns = defaultVisibleTableColumns) => {
5528
+ return events.flatMap((event, i) => {
5529
+ const isEvenRow = i % 2 === 1;
5530
+ const rowClassName = isEvenRow ? TableRowEven : TableRowOdd;
5531
+ const isSelected = selectedEventIndex === i;
5532
+ const isErrorStatus = hasErrorStatus(event);
5533
+ const rowCellNodes = getRowCellNodes(event, isErrorStatus, visibleTableColumns);
5534
+ return [{
5535
+ childCount: visibleTableColumns.length,
5536
+ className: mergeClassNames(TableRow, rowClassName, isSelected ? TableRowSelected : ''),
5537
+ type: Tr
5538
+ }, ...rowCellNodes];
5539
+ });
4941
5540
  };
4942
5541
 
4943
- const getImagePreviewDom = preview => {
4944
- return [{
4945
- childCount: 2,
4946
- className: ChatDebugViewImagePreview,
4947
- type: Div
4948
- }, {
4949
- alt: preview.alt,
4950
- childCount: 0,
4951
- className: ChatDebugViewImagePreviewImage,
4952
- src: preview.src,
4953
- type: Img
4954
- }, {
4955
- childCount: 1,
4956
- className: ChatDebugViewImagePreviewLabel,
4957
- type: Span
4958
- }, text(preview.alt)];
5542
+ const emptyStateNode = {
5543
+ childCount: 1,
5544
+ className: ChatDebugViewEmpty,
5545
+ type: Div
4959
5546
  };
4960
-
4961
- const getTextNode = value => {
4962
- const lines = value.split('\n');
4963
- const lineNodes = getLineNodes(lines.map(line => {
4964
- return {
4965
- childCount: 1,
4966
- nodes: [{
4967
- childCount: 1,
4968
- className: TokenText,
4969
- type: Span
4970
- }, text(line)]
4971
- };
4972
- }));
4973
- return [{
4974
- childCount: lines.length,
4975
- className: ChatDebugViewEvent,
4976
- type: Div
4977
- }, ...lineNodes];
5547
+ const getEmptyStateDom = emptyMessage => {
5548
+ return [emptyStateNode, text(emptyMessage)];
4978
5549
  };
4979
5550
 
4980
- const getPreviewEventNodes = previewEvent => {
4981
- if (typeof previewEvent === 'string') {
4982
- return getTextNode(previewEvent);
4983
- }
4984
- if (previewEvent === undefined) {
4985
- return [];
4986
- }
4987
- if (isAttachmentImagePreview(previewEvent)) {
4988
- return getImagePreviewDom(previewEvent);
4989
- }
4990
- return getEventNode(previewEvent);
5551
+ const getEventsClassName = hasSelectedEvent => {
5552
+ const widthClassName = mergeClassNames(ChatDebugViewEvents, hasSelectedEvent ? '' : ChatDebugViewEventsFullWidth);
5553
+ return widthClassName;
4991
5554
  };
4992
5555
 
4993
5556
  const sashNodesDom = [{
4994
5557
  childCount: 1,
4995
- className: ChatDebugViewSash,
5558
+ className: Sash,
4996
5559
  onPointerDown: HandleSashPointerDown,
4997
- type: Div
5560
+ type: Button$1
4998
5561
  }, {
4999
5562
  childCount: 0,
5000
5563
  className: ChatDebugViewSashLine,
@@ -5007,40 +5570,73 @@ const getSashNodesDom = hasSelectedEvent => {
5007
5570
  return sashNodesDom;
5008
5571
  };
5009
5572
 
5573
+ const None = 'none';
5574
+ const Status = 'status';
5575
+
5576
+ const getSplitViewDom = (splitChildCount, eventsChildCount, eventsClassName, tableNodes, sashNodes, detailsNodes) => {
5577
+ return [{
5578
+ childCount: splitChildCount,
5579
+ className: ChatDebugViewDevtoolsSplit,
5580
+ role: None,
5581
+ type: Div
5582
+ }, {
5583
+ childCount: eventsChildCount,
5584
+ className: eventsClassName,
5585
+ role: 'application',
5586
+ type: Div
5587
+ }, ...tableNodes, ...sashNodes, ...detailsNodes];
5588
+ };
5589
+
5010
5590
  const getTableBodyDom = (rowNodes, eventCount) => {
5011
5591
  return [{
5012
5592
  childCount: eventCount === 0 ? 1 : eventCount,
5013
- className: ChatDebugViewTableBody,
5593
+ className: TableBody,
5014
5594
  onContextMenu: HandleTableBodyContextMenu,
5015
- onPointerDown: HandleEventRowClick,
5595
+ onPointerDown: HandleEventRowClickAt,
5016
5596
  type: TBody
5017
5597
  }, ...rowNodes];
5018
5598
  };
5019
5599
 
5600
+ const tableColClassNames = ['TableColZero', 'TableColOne', 'TableColTwo'];
5601
+ const getTableColumnGroupDom = visibleTableColumns => {
5602
+ const orderedVisibleTableColumns = getOrderedVisibleTableColumns(visibleTableColumns);
5603
+ return [{
5604
+ childCount: orderedVisibleTableColumns.length,
5605
+ className: 'ColGroup',
5606
+ type: ColGroup
5607
+ }, ...orderedVisibleTableColumns.map((_, index) => ({
5608
+ childCount: 0,
5609
+ className: `${TableCol} ${tableColClassNames[index]}`,
5610
+ type: Col
5611
+ }))];
5612
+ };
5613
+
5020
5614
  const getHeaderCellNodes = (visibleTableColumns, tableColumns = createTableColumns()) => {
5021
5615
  const orderedVisibleTableColumns = getOrderedVisibleTableColumns(visibleTableColumns, tableColumns);
5022
- return orderedVisibleTableColumns.flatMap((column, index) => {
5023
- const isFixed = index < orderedVisibleTableColumns.length - 1;
5616
+ return orderedVisibleTableColumns.flatMap(column => {
5024
5617
  switch (column) {
5025
5618
  case Duration:
5026
5619
  return [{
5027
5620
  childCount: 1,
5028
- className: mergeClassNames(ChatDebugViewHeaderCell, ChatDebugViewHeaderCellDuration, isFixed ? ChatDebugViewColumnFixed : ''),
5029
- scope: 'col',
5621
+ className: ChatDebugViewHeaderCell,
5622
+ name: column,
5623
+ onClick: HandleTableHeaderClick,
5030
5624
  type: Th
5031
5625
  }, text(getTableColumnLabel(tableColumns, column))];
5032
- case Status:
5626
+ case Status$1:
5033
5627
  return [{
5034
5628
  childCount: 1,
5035
- className: mergeClassNames(ChatDebugViewHeaderCell, ChatDebugViewHeaderCellStatus, isFixed ? ChatDebugViewColumnFixed : ''),
5036
- scope: 'col',
5629
+ className: ChatDebugViewHeaderCell,
5630
+ name: column,
5631
+ onClick: HandleTableHeaderClick,
5037
5632
  type: Th
5038
5633
  }, text(getTableColumnLabel(tableColumns, column))];
5039
5634
  case Type:
5040
5635
  return [{
5041
5636
  childCount: 1,
5042
- className: mergeClassNames(ChatDebugViewHeaderCell, ChatDebugViewHeaderCellType, isFixed ? ChatDebugViewColumnFixed : ''),
5043
- scope: 'col',
5637
+ className: ChatDebugViewHeaderCell,
5638
+ name: column,
5639
+ onClick: HandleTableHeaderClick,
5044
5640
  type: Th
5045
5641
  }, text(getTableColumnLabel(tableColumns, column))];
5046
5642
  default:
@@ -5053,18 +5649,18 @@ const getTableHeaderDom = (visibleTableColumns = defaultVisibleTableColumns, tab
5053
5649
  const headerCellNodes = getHeaderCellNodes(visibleTableColumns, tableColumns);
5054
5650
  return [{
5055
5651
  childCount: 1,
5056
- className: ChatDebugViewTableHeader,
5652
+ className: TableHead,
5057
5653
  onContextMenu: HandleHeaderContextMenu,
5058
5654
  type: THead
5059
5655
  }, {
5060
5656
  childCount: visibleTableColumns.length,
5061
- className: ChatDebugViewTableHeaderRow,
5657
+ className: TableRow,
5062
5658
  type: Tr
5063
5659
  }, ...headerCellNodes];
5064
5660
  };
5065
5661
 
5066
5662
  const resizerNames = ['ResizerOne', 'ResizerTwo'];
5067
- const resizerClassNames = [ChatDebugViewResizerOne, ChatDebugViewResizerTwo];
5663
+ const resizerClassNames = [ResizerOne, ResizerTwo];
5068
5664
  const getTableResizersDom = visibleTableColumns => {
5069
5665
  const visibleColumnCount = getOrderedVisibleTableColumns(visibleTableColumns).length;
5070
5666
  const resizerCount = Math.max(0, visibleColumnCount - 1);
@@ -5074,34 +5670,92 @@ const getTableResizersDom = visibleTableColumns => {
5074
5670
  const visibleResizerClassNames = resizerClassNames.slice(0, resizerCount);
5075
5671
  const resizerNodes = visibleResizerClassNames.flatMap((resizerClassName, index) => [{
5076
5672
  childCount: 1,
5077
- className: `${ChatDebugViewResizer} ${resizerClassName}`,
5673
+ className: mergeClassNames(Resizer, resizerClassName),
5078
5674
  name: resizerNames[index],
5079
5675
  onPointerDown: HandleTableResizerPointerDown,
5080
5676
  role: None,
5081
5677
  type: Button$1
5082
5678
  }, {
5083
5679
  childCount: 0,
5084
- className: ChatDebugViewResizerInner,
5680
+ className: ResizerInner,
5681
+ role: None,
5085
5682
  type: Div
5086
5683
  }]);
5087
5684
  return [{
5088
- childCount: resizerCount,
5089
- className: ChatDebugViewResizers,
5685
+ childCount: resizerCount + 1,
5686
+ className: Resizers,
5090
5687
  type: Div
5091
5688
  }, ...resizerNodes];
5092
5689
  };
5093
5690
 
5094
- const getTableDom = (rowNodes, eventCount, visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns()) => {
5095
- const resizerNodes = getTableResizersDom(visibleTableColumns);
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 : '');
5096
5706
  return [{
5097
- childCount: 1 + (resizerNodes.length > 0 ? 1 : 0),
5098
- className: ChatDebugViewTableWrapper,
5707
+ childCount: 2,
5708
+ className: tableWrapperClassName,
5099
5709
  type: Div
5100
5710
  }, {
5101
- childCount: 2,
5102
- className: ChatDebugViewTable,
5103
- type: Table
5104
- }, ...getTableHeaderDom(visibleTableColumns, tableColumns), ...getTableBodyDom(rowNodes, eventCount), ...resizerNodes];
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;
5736
+ };
5737
+
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));
5105
5759
  };
5106
5760
 
5107
5761
  const getBucketUnitDom = (unitCount, presetValue) => {
@@ -5143,6 +5797,23 @@ const getBucketDom = bucket => {
5143
5797
  }, ...getBucketUnitDom(bucket.unitCount, presetValue)];
5144
5798
  };
5145
5799
 
5800
+ const getBucketsDom = buckets => {
5801
+ return [{
5802
+ childCount: buckets.length,
5803
+ className: ChatDebugViewTimelineBuckets,
5804
+ type: Div
5805
+ }, ...buckets.flatMap(getBucketDom)];
5806
+ };
5807
+
5808
+ const getCursorGuideNodes = hoverPercent => {
5809
+ return hoverPercent === null ? [] : [{
5810
+ childCount: 0,
5811
+ className: mergeClassNames(ChatDebugViewTimelineCursorGuide, ChatDebugViewTimelineCursorGuideVisible),
5812
+ style: `left:${hoverPercent}%;`,
5813
+ type: Div
5814
+ }];
5815
+ };
5816
+
5146
5817
  const formatPercent = value => {
5147
5818
  return `${Number(value.toFixed(3))}%`;
5148
5819
  };
@@ -5158,26 +5829,55 @@ const getSelectionNodesDom = (hasSelection, selectionStartPercent, selectionEndP
5158
5829
  type: Div
5159
5830
  }, {
5160
5831
  childCount: 0,
5161
- className: mergeClassNames(ChatDebugViewTimelineSelectionHandle, ChatDebugViewTimelineSelectionMarker, ChatDebugViewTimelineSelectionMarkerStart),
5832
+ className: mergeClassNames(ChatDebugViewTimelineSelectionHandle, ChatDebugViewTimelineSelectionHandleStart, ChatDebugViewTimelineSelectionMarker, ChatDebugViewTimelineSelectionMarkerStart),
5162
5833
  name: Start,
5163
5834
  role: None,
5164
- style: `left:${formatPercent(selectionStartPercent)};`,
5165
5835
  type: Button$1
5166
5836
  }, {
5167
5837
  childCount: 0,
5168
- className: mergeClassNames(ChatDebugViewTimelineSelectionHandle, ChatDebugViewTimelineSelectionMarker, ChatDebugViewTimelineSelectionMarkerEnd),
5838
+ className: mergeClassNames(ChatDebugViewTimelineSelectionHandle, ChatDebugViewTimelineSelectionHandleEnd, ChatDebugViewTimelineSelectionMarker, ChatDebugViewTimelineSelectionMarkerEnd),
5169
5839
  name: End,
5170
5840
  role: None,
5171
- style: `left:${formatPercent(selectionEndPercent)};`,
5172
5841
  type: Button$1
5173
5842
  }];
5174
5843
  };
5175
5844
 
5176
- const formatTimelineSeconds = value => {
5177
- if (Number.isInteger(value)) {
5178
- return `${value}s`;
5845
+ const getTimelineBadgeValues = durationSeconds => {
5846
+ if (durationSeconds <= 0) {
5847
+ return [0];
5179
5848
  }
5180
- return `${Number(value.toFixed(1))}s`;
5849
+ const segmentCount = durationSeconds < 1 ? 2 : Math.min(5, Math.max(1, Math.ceil(durationSeconds)));
5850
+ return Array.from({
5851
+ length: segmentCount + 1
5852
+ }, (_, index) => {
5853
+ if (index === segmentCount) {
5854
+ return durationSeconds;
5855
+ }
5856
+ return roundSeconds(durationSeconds / segmentCount * index);
5857
+ });
5858
+ };
5859
+ const getTimelineBadgeStyle = (index, lastIndex) => {
5860
+ if (index === 0 || lastIndex === 0) {
5861
+ return 'left:0;transform:translateX(0);';
5862
+ }
5863
+ if (index === lastIndex) {
5864
+ return 'left:100%;transform:translateX(-100%);';
5865
+ }
5866
+ return `left:${roundSeconds(index / lastIndex * 100)}%;transform:translateX(-50%);`;
5867
+ };
5868
+ const getTimelineBadgeNodes = timelineInfo => {
5869
+ const badgeValues = getTimelineBadgeValues(timelineInfo.durationSeconds);
5870
+ const lastIndex = badgeValues.length - 1;
5871
+ return [{
5872
+ childCount: badgeValues.length,
5873
+ className: ChatDebugViewTimelineBadges,
5874
+ type: Div
5875
+ }, ...badgeValues.flatMap((value, index) => [{
5876
+ childCount: 1,
5877
+ className: ChatDebugViewTimelineBadge,
5878
+ style: getTimelineBadgeStyle(index, lastIndex),
5879
+ type: Span
5880
+ }, text(formatTimelineMilliseconds(value))])];
5181
5881
  };
5182
5882
 
5183
5883
  const getTimelineSummary = timelineInfo => {
@@ -5187,17 +5887,8 @@ const getTimelineSummary = timelineInfo => {
5187
5887
  return windowSummary('0s', formatTimelineSeconds(timelineInfo.durationSeconds), formatTimelineSeconds(timelineInfo.durationSeconds));
5188
5888
  };
5189
5889
 
5190
- const getTimelineNodes = timelineInfo => {
5191
- if (timelineInfo.buckets.length === 0) {
5192
- return [];
5193
- }
5194
- const selectionNodes = getSelectionNodesDom(timelineInfo.hasSelection, timelineInfo.selectionStartPercent, timelineInfo.selectionEndPercent);
5890
+ const getTimelineTopDom = timelineInfo => {
5195
5891
  return [{
5196
- childCount: 2,
5197
- className: ChatDebugViewTimeline,
5198
- onContextMenu: HandleTimelineContextMenu,
5199
- type: Section
5200
- }, {
5201
5892
  childCount: 1,
5202
5893
  className: ChatDebugViewTimelineTop,
5203
5894
  type: Div
@@ -5205,56 +5896,62 @@ const getTimelineNodes = timelineInfo => {
5205
5896
  childCount: 1,
5206
5897
  className: ChatDebugViewTimelineSummary,
5207
5898
  type: H2
5208
- }, text(getTimelineSummary(timelineInfo)), {
5899
+ }, text(getTimelineSummary(timelineInfo))];
5900
+ };
5901
+
5902
+ // cspell:ignore gettimelinedom
5903
+ const getTimelineDom = (timelineInfo, hoverPercent = null) => {
5904
+ if (timelineInfo.buckets.length === 0) {
5905
+ return [];
5906
+ }
5907
+ const badgeNodes = getTimelineBadgeNodes(timelineInfo);
5908
+ const bucketNodes = getBucketsDom(timelineInfo.buckets);
5909
+ const selectionNodes = getSelectionNodesDom(timelineInfo.hasSelection, timelineInfo.selectionStartPercent, timelineInfo.selectionEndPercent);
5910
+ const cursorGuideNodes = getCursorGuideNodes(hoverPercent);
5911
+ const timelineTopDom = getTimelineTopDom(timelineInfo);
5912
+ return [{
5209
5913
  childCount: 2,
5914
+ className: ChatDebugViewTimeline,
5915
+ onContextMenu: HandleTimelineContextMenu,
5916
+ type: Section
5917
+ }, ...timelineTopDom, {
5918
+ childCount: 3,
5210
5919
  className: ChatDebugViewTimelineInteractive,
5211
- onDoubleClick: HandleTimelineDoubleClick,
5920
+ onDblClick: HandleTimelineDoubleClick,
5212
5921
  onPointerDown: HandleTimelinePointerDown,
5922
+ onPointerLeave: HandleTimelinePointerLeave,
5923
+ onPointerMove: HandleTimelinePointerMove,
5924
+ type: Div
5925
+ }, ...badgeNodes, ...bucketNodes, {
5926
+ childCount: 2,
5927
+ className: ChatDebugViewTimelineSelectionOverlay,
5213
5928
  type: Div
5214
5929
  }, {
5215
- childCount: timelineInfo.buckets.length,
5216
- className: ChatDebugViewTimelineBuckets,
5930
+ childCount: cursorGuideNodes.length,
5217
5931
  type: Div
5218
- }, ...timelineInfo.buckets.flatMap(getBucketDom), {
5932
+ }, ...cursorGuideNodes, {
5219
5933
  childCount: selectionNodes.length,
5220
- className: ChatDebugViewTimelineSelectionOverlay,
5221
5934
  type: Div
5222
5935
  }, ...selectionNodes];
5223
5936
  };
5224
5937
 
5225
- const getDevtoolsDom = (events, selectedEvent, selectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage = noEventsFound(), timelineSelectionActive = false, timelineSelectionAnchorSeconds = '', timelineSelectionFocusSeconds = '', visibleTableColumns = defaultVisibleTableColumns, detailTabs = createDetailTabs(), tableColumns = createTableColumns(), timelineInfo) => {
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) => {
5226
5939
  const rowNodes = getDevtoolsRows(events, selectedEventIndex, visibleTableColumns);
5227
5940
  const effectiveRange = getEffectiveTimelineRange(timelineStartSeconds, timelineEndSeconds, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds);
5228
5941
  const resolvedTimelineInfo = timelineInfo || getTimelineInfo(timelineEvents, effectiveRange.startSeconds, effectiveRange.endSeconds);
5229
- const timelineNodes = getTimelineNodes(resolvedTimelineInfo);
5942
+ const timelineNodes = getTimelineDom(resolvedTimelineInfo, timelineHoverPercent);
5230
5943
  const previewEvent = selectedEvent ? getPreviewEvent(selectedEvent) : undefined;
5231
- const previewEventNodes = getPreviewEventNodes(previewEvent);
5944
+ const previewEventNodes = getPreviewEventNodes(previewEvent, selectedEvent);
5232
5945
  const payloadEventNodes = selectedEvent ? getEventNode(getPayloadEvent(selectedEvent)) : [];
5233
5946
  const responseEventNodes = selectedEvent ? getEventNode(selectedEvent) : [];
5234
5947
  const hasSelectedEvent = responseEventNodes.length > 0;
5235
- const tableNodes = events.length === 0 ? getEmptyStateDom(emptyMessage) : getTableDom(rowNodes, events.length, visibleTableColumns, tableColumns);
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);
5236
5950
  const eventsClassName = getEventsClassName(hasSelectedEvent);
5237
5951
  const detailsNodes = getDetailsDom(previewEventNodes, payloadEventNodes, responseEventNodes, selectedEvent, detailTabs);
5238
5952
  const sashNodes = getSashNodesDom(hasSelectedEvent);
5239
5953
  const splitChildCount = hasSelectedEvent ? 3 : 1;
5240
- const mainChildCount = 1 + (timelineNodes.length > 0 ? 1 : 0);
5241
- return [{
5242
- childCount: mainChildCount,
5243
- className: ChatDebugViewDevtoolsMain,
5244
- role: None,
5245
- type: Div
5246
- }, ...timelineNodes, {
5247
- childCount: splitChildCount,
5248
- className: ChatDebugViewDevtoolsSplit,
5249
- role: None,
5250
- type: Div
5251
- }, {
5252
- childCount: 1,
5253
- className: eventsClassName,
5254
- role: 'application',
5255
- tabIndex: 0,
5256
- type: Div
5257
- }, ...tableNodes, ...sashNodes, ...detailsNodes];
5954
+ return [...timelineNodes, ...getSplitViewDom(splitChildCount, eventsChildCount, eventsClassName, tableNodes, sashNodes, detailsNodes)];
5258
5955
  };
5259
5956
 
5260
5957
  const getEmptyMessage = (eventCount, hasFilterValue, useNoToolCallEventsMessage, noFilteredEventsMessage) => {
@@ -5269,7 +5966,6 @@ const getLegacyEventsDom = (errorMessage, emptyMessage, eventNodes) => {
5269
5966
  childCount: eventNodes.length === 0 ? 1 : eventNodes.length,
5270
5967
  className: ChatDebugViewEvents,
5271
5968
  role: 'application',
5272
- tabIndex: 0,
5273
5969
  type: Div
5274
5970
  }, ...(eventNodes.length === 0 ? [{
5275
5971
  childCount: 1,
@@ -5278,33 +5974,6 @@ const getLegacyEventsDom = (errorMessage, emptyMessage, eventNodes) => {
5278
5974
  }, text(errorMessage || emptyMessage)] : eventNodes)];
5279
5975
  };
5280
5976
 
5281
- // cspell:ignore multiselectable
5282
- const getQuickFilterNodes = categoryFilters => {
5283
- return [{
5284
- 'aria-multiselectable': true,
5285
- childCount: categoryFilters.length,
5286
- className: ChatDebugViewQuickFilters,
5287
- onClick: HandleEventCategoryFilter,
5288
- role: 'listbox',
5289
- type: Div
5290
- }, ...categoryFilters.flatMap(categoryFilter => {
5291
- const {
5292
- isSelected,
5293
- label,
5294
- name
5295
- } = categoryFilter;
5296
- return [{
5297
- 'aria-selected': isSelected,
5298
- childCount: 1,
5299
- className: mergeClassNames(ChatDebugViewQuickFilterPill, isSelected ? ChatDebugViewQuickFilterPillSelected : ''),
5300
- 'data-value': name,
5301
- onClick: HandleEventCategoryFilter,
5302
- role: 'option',
5303
- type: Div
5304
- }, text(label)];
5305
- })];
5306
- };
5307
-
5308
5977
  const getTimelineFilterDescription = (timelineStartSeconds, timelineEndSeconds) => {
5309
5978
  const trimmedStart = timelineStartSeconds.trim();
5310
5979
  const trimmedEnd = timelineEndSeconds.trim();
@@ -5320,13 +5989,30 @@ const getTimelineFilterDescription = (timelineStartSeconds, timelineEndSeconds)
5320
5989
  return '';
5321
5990
  };
5322
5991
 
5992
+ const getNextSiblingIndex = (nodes, index) => {
5993
+ let nextSiblingIndex = index + 1;
5994
+ const childCount = nodes[index]?.childCount || 0;
5995
+ for (let i = 0; i < childCount; i++) {
5996
+ nextSiblingIndex = getNextSiblingIndex(nodes, nextSiblingIndex);
5997
+ }
5998
+ return nextSiblingIndex;
5999
+ };
6000
+ const getTopLevelChildCount = nodes => {
6001
+ let count = 0;
6002
+ let index = 0;
6003
+ while (index < nodes.length) {
6004
+ count++;
6005
+ index = getNextSiblingIndex(nodes, index);
6006
+ }
6007
+ return count;
6008
+ };
5323
6009
  const getEventCategoryFilterDescription = eventCategoryFilters => {
5324
6010
  if (eventCategoryFilters.length === 0 || eventCategoryFilters.includes(All)) {
5325
6011
  return '';
5326
6012
  }
5327
6013
  return eventCategoryFilters.map(eventCategoryFilter => getEventCategoryFilterLabel(eventCategoryFilter).toLowerCase()).join(', ');
5328
6014
  };
5329
- const getChatDebugViewDom = (errorMessage, filterValue, eventCategoryFilters, categoryFilters, _showEventStreamFinishedEvents, _showInputEvents, _showResponsePartEvents, useDevtoolsLayout, selectedEvent, selectedEventIndex, timelineStartSeconds, timelineEndSeconds, timelineEvents, events, timelineSelectionActive = false, timelineSelectionAnchorSeconds = '', timelineSelectionFocusSeconds = '', visibleTableColumns = defaultVisibleTableColumns, detailTabs = createDetailTabs(), tableColumns = createTableColumns(), timelineInfo) => {
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) => {
5330
6016
  if (errorMessage) {
5331
6017
  return getDebugErrorDom(errorMessage);
5332
6018
  }
@@ -5350,10 +6036,9 @@ const getChatDebugViewDom = (errorMessage, filterValue, eventCategoryFilters, ca
5350
6036
  const useNoToolCallEventsMessage = eventCategoryFilters.length === 1 && eventCategoryFilters[0] === Tools && !trimmedFilterValue && !hasTimelineFilter;
5351
6037
  const emptyMessage = getEmptyMessage(events.length, hasFilterValue, useNoToolCallEventsMessage, noFilteredEventsMessage);
5352
6038
  const safeSelectedEventIndex = selectedEventIndex === null || selectedEventIndex < 0 || selectedEventIndex >= events.length ? null : selectedEventIndex;
5353
- const contentNodes = useDevtoolsLayout ? getDevtoolsDom(events, selectedEvent, safeSelectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds, visibleTableColumns, detailTabs, tableColumns, timelineInfo) : getLegacyEventsDom(errorMessage, emptyMessage, events.flatMap(getEventNode));
5354
- const quickFilterNodes = useDevtoolsLayout ? getQuickFilterNodes(categoryFilters) : [];
5355
- const debugViewTopDom = getDebugViewTopDom(filterValue, useDevtoolsLayout, quickFilterNodes);
5356
- const rootChildCount = 2;
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));
6040
+ const debugViewTopDom = getDebugViewTopDom(filterValue, useDevtoolsLayout, categoryFilters);
6041
+ const rootChildCount = 1 + getTopLevelChildCount(contentNodes);
5357
6042
  return [{
5358
6043
  childCount: rootChildCount,
5359
6044
  className: mergeClassNames(ChatDebugView, useDevtoolsLayout ? ChatDebugViewDevtools : ''),
@@ -5374,7 +6059,7 @@ const renderItems = (oldState, newState) => {
5374
6059
  return [SetDom2, newState.uid, []];
5375
6060
  }
5376
6061
  const filteredEvents = filterEventsByTimelineRange(newState.timelineEvents, newState.timelineStartSeconds, newState.timelineEndSeconds);
5377
- const dom = getChatDebugViewDom(newState.errorMessage, newState.filterValue, getSelectedEventCategoryFilters(newState.categoryFilters), newState.categoryFilters, newState.showEventStreamFinishedEvents, newState.showInputEvents, newState.showResponsePartEvents, newState.useDevtoolsLayout, newState.selectedEvent, newState.selectedEventIndex, newState.timelineStartSeconds, newState.timelineEndSeconds, withSessionEventIds(newState.timelineEvents), withSessionEventIds(filteredEvents), newState.timelineSelectionActive, newState.timelineSelectionAnchorSeconds, newState.timelineSelectionFocusSeconds, newState.visibleTableColumns, newState.detailTabs, newState.tableColumns, newState.timelineInfo);
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);
5378
6063
  return [SetDom2, newState.uid, dom];
5379
6064
  };
5380
6065
 
@@ -5385,10 +6070,35 @@ const renderIncremental = (oldState, newState) => {
5385
6070
  return [SetPatches, newState.uid, patches];
5386
6071
  };
5387
6072
 
6073
+ const getSelector = focus => {
6074
+ if (focus === 0) {
6075
+ return '.Table';
6076
+ }
6077
+ return '';
6078
+ };
6079
+ const renderFocus = (oldState, newState) => {
6080
+ const {
6081
+ uid
6082
+ } = newState;
6083
+ const selector = getSelector(newState.focus);
6084
+ return [FocusSelector, uid, selector];
6085
+ };
6086
+
6087
+ const renderFocusContext = (oldState, newState) => {
6088
+ const {
6089
+ uid
6090
+ } = newState;
6091
+ return [SetFocusContext, uid, FocusChatDebugTable];
6092
+ };
6093
+
5388
6094
  const getRenderer = diffType => {
5389
6095
  switch (diffType) {
5390
6096
  case RenderCss:
5391
6097
  return renderCss;
6098
+ case RenderFocus:
6099
+ return renderFocus;
6100
+ case RenderFocusContext:
6101
+ return renderFocusContext;
5392
6102
  case RenderIncremental:
5393
6103
  return renderIncremental;
5394
6104
  case RenderItems:
@@ -5426,11 +6136,17 @@ const renderEventListeners = () => {
5426
6136
  preventDefault: true
5427
6137
  }, {
5428
6138
  name: HandleEventRowClick,
5429
- params: ['handleEventRowClick', 'event.target.dataset.index', Button]
6139
+ params: ['handleEventRowClick', '0', Button]
6140
+ }, {
6141
+ name: HandleEventRowClickAt,
6142
+ params: ['handleEventRowClickAt', ClientX, ClientY, Button]
5430
6143
  }, {
5431
6144
  name: HandleTableBodyContextMenu,
5432
6145
  params: ['handleTableBodyContextMenu', ClientX, ClientY],
5433
6146
  preventDefault: true
6147
+ }, {
6148
+ name: HandleTableFocus,
6149
+ params: ['handleTableFocus']
5434
6150
  }, {
5435
6151
  name: HandleDetailsContextMenu,
5436
6152
  params: ['handleDetailsContextMenu'],
@@ -5448,10 +6164,13 @@ const renderEventListeners = () => {
5448
6164
  params: ['handleInput', TargetName, TargetValue]
5449
6165
  }, {
5450
6166
  name: HandleEventCategoryFilter,
5451
- params: ['handleEventCategoryFilter', 'event.target.dataset.value', 'event.ctrlKey', 'event.metaKey']
6167
+ params: ['handleEventCategoryFilter', TargetName, 'event.ctrlKey']
6168
+ }, {
6169
+ name: HandleTableHeaderClick,
6170
+ params: ['handleTableHeaderClick', TargetName]
5452
6171
  }, {
5453
6172
  name: SelectDetailTab,
5454
- params: ['selectDetailTab', TargetValue]
6173
+ params: ['selectDetailTab', TargetName]
5455
6174
  }, {
5456
6175
  name: HandleTimelineRangePreset,
5457
6176
  params: ['handleTimelineRangePreset', 'event.target.dataset.value']
@@ -5488,6 +6207,9 @@ const renderEventListeners = () => {
5488
6207
  }, {
5489
6208
  name: HandleTimelinePointerMove,
5490
6209
  params: ['handleTimelinePointerMove', ClientX]
6210
+ }, {
6211
+ name: HandleTimelinePointerLeave,
6212
+ params: ['handleTimelinePointerLeave']
5491
6213
  }, {
5492
6214
  name: HandleTimelinePointerUp,
5493
6215
  params: ['handleTimelinePointerUp', ClientX]
@@ -5563,6 +6285,15 @@ const saveState = state => {
5563
6285
  };
5564
6286
  };
5565
6287
 
6288
+ const selectCurrent = async state => {
6289
+ const currentEvents = getCurrentEvents$1(state);
6290
+ if (currentEvents.length === 0) {
6291
+ return state;
6292
+ }
6293
+ const selectedEventIndex = state.selectedEventIndex === null ? 0 : state.selectedEventIndex;
6294
+ return focusIndex(state, selectedEventIndex);
6295
+ };
6296
+
5566
6297
  const setEvents = (state, events) => {
5567
6298
  return getStateWithTimelineInfo({
5568
6299
  ...state,
@@ -5629,6 +6360,10 @@ const commandMap = {
5629
6360
  'ChatDebug.appendStoredImageAttachmentForTest': wrapCommand(appendStoredImageAttachmentForTest),
5630
6361
  'ChatDebug.create': create,
5631
6362
  'ChatDebug.diff2': diff2,
6363
+ 'ChatDebug.focusFirst': wrapCommand(focusFirst),
6364
+ 'ChatDebug.focusLast': wrapCommand(focusLast),
6365
+ 'ChatDebug.focusNext': wrapCommand(focusNext),
6366
+ 'ChatDebug.focusPrevious': wrapCommand(focusPrevious),
5632
6367
  'ChatDebug.getCommandIds': getCommandIds,
5633
6368
  'ChatDebug.getMenuEntries': wrapGetter(getMenuEntries2),
5634
6369
  'ChatDebug.getMenuIds': getMenuIds,
@@ -5636,8 +6371,10 @@ const commandMap = {
5636
6371
  'ChatDebug.handleCloseDetails': wrapCommand(handleCloseDetails),
5637
6372
  'ChatDebug.handleDetailsContextMenu': wrapCommand(handleDetailsContextMenu),
5638
6373
  'ChatDebug.handleDetailsTopContextMenu': wrapCommand(handleDetailsTopContextMenu),
6374
+ 'ChatDebug.handleEscape': wrapCommand(handleEscape),
5639
6375
  'ChatDebug.handleEventCategoryFilter': wrapCommand(handleEventCategoryFilter),
5640
6376
  'ChatDebug.handleEventRowClick': wrapCommand(handleEventRowClick),
6377
+ 'ChatDebug.handleEventRowClickAt': wrapCommand(handleEventRowClickAt),
5641
6378
  'ChatDebug.handleHeaderContextMenu': wrapCommand(handleHeaderContextMenu),
5642
6379
  'ChatDebug.handleInput': wrapCommand(handleInput),
5643
6380
  'ChatDebug.handleSashPointerDown': wrapCommand(handleSashPointerDown),
@@ -5647,6 +6384,8 @@ const commandMap = {
5647
6384
  'ChatDebug.handleShowInputEvents': wrapCommand(handleShowInputEvents),
5648
6385
  'ChatDebug.handleShowResponsePartEvents': wrapCommand(handleShowResponsePartEvents),
5649
6386
  'ChatDebug.handleTableBodyContextMenu': wrapCommand(handleTableBodyContextMenu),
6387
+ 'ChatDebug.handleTableFocus': wrapCommand(handleTableFocus),
6388
+ 'ChatDebug.handleTableHeaderClick': wrapCommand(handleTableHeaderClick),
5650
6389
  'ChatDebug.handleTableResizerPointerDown': wrapCommand(handleTableResizerPointerDown),
5651
6390
  'ChatDebug.handleTableResizerPointerMove': wrapCommand(handleTableResizerPointerMove),
5652
6391
  'ChatDebug.handleTableResizerPointerUp': wrapCommand(handleTableResizerPointerUp),
@@ -5655,6 +6394,7 @@ const commandMap = {
5655
6394
  'ChatDebug.handleTimelineDoubleClick': wrapCommand(handleTimelineDoubleClick),
5656
6395
  'ChatDebug.handleTimelineEndSeconds': wrapCommand(handleTimelineEndSeconds),
5657
6396
  'ChatDebug.handleTimelinePointerDown': wrapCommand(handleTimelinePointerDown),
6397
+ 'ChatDebug.handleTimelinePointerLeave': wrapCommand(handleTimelinePointerLeave),
5658
6398
  'ChatDebug.handleTimelinePointerMove': wrapCommand(handleTimelinePointerMove),
5659
6399
  'ChatDebug.handleTimelinePointerUp': wrapCommand(handleTimelinePointerUp),
5660
6400
  'ChatDebug.handleTimelineRangePreset': wrapCommand(handleTimelineRangePreset),
@@ -5669,6 +6409,7 @@ const commandMap = {
5669
6409
  'ChatDebug.resetTableColumns': wrapCommand(resetTableColumns),
5670
6410
  'ChatDebug.resize': wrapCommand(resize),
5671
6411
  'ChatDebug.saveState': wrapGetter(saveState),
6412
+ 'ChatDebug.selectCurrent': wrapCommand(selectCurrent),
5672
6413
  'ChatDebug.selectDetailTab': wrapCommand(selectDetailTab),
5673
6414
  'ChatDebug.setEvents': wrapCommand(setEvents),
5674
6415
  'ChatDebug.setSessionId': wrapCommand(setSessionId),
@@ -5701,3 +6442,5 @@ const main = async () => {
5701
6442
  };
5702
6443
 
5703
6444
  main();
6445
+
6446
+ // console.log('hi3')