@lvce-editor/chat-debug-view 10.11.0 → 10.15.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.
@@ -1185,6 +1185,9 @@ const writeClipBoardText = async text => {
1185
1185
  const getPreference = async key => {
1186
1186
  return await invoke('Preferences.get', key);
1187
1187
  };
1188
+ const openUri = async (uri, focus, options) => {
1189
+ await invoke('Main.openUri', uri, focus, options);
1190
+ };
1188
1191
 
1189
1192
  const toCommandId = key => {
1190
1193
  const dotIndex = key.indexOf('.');
@@ -1420,6 +1423,31 @@ const appendStoredRemovedImageAttachmentForTest = async (state, sessionId, event
1420
1423
  return state;
1421
1424
  };
1422
1425
 
1426
+ const Filter = 'filter';
1427
+ const EventCategoryFilter = 'eventCategoryFilter';
1428
+ const ShowEventStreamFinishedEvents = 'showEventStreamFinishedEvents';
1429
+ const ShowInputEvents = 'showInputEvents';
1430
+ const ShowResponsePartEvents = 'showResponsePartEvents';
1431
+ const UseDevtoolsLayout = 'useDevtoolsLayout';
1432
+ const SelectedEventIndex = 'selectedEventIndex';
1433
+ const CloseDetails$1 = 'closeDetails';
1434
+ const DetailTab = 'detailTab';
1435
+ const TimelineStartSeconds = 'timelineStartSeconds';
1436
+ const TimelineEndSeconds = 'timelineEndSeconds';
1437
+ const TimelineRangePreset = 'timelineRangePreset';
1438
+ const Refresh$1 = 'refresh';
1439
+ const All$1 = 'all';
1440
+ const Tools$1 = 'tools';
1441
+ const Network$1 = 'network';
1442
+ const Ui$1 = 'ui';
1443
+ const Stream$1 = 'stream';
1444
+ const Response$1 = 'response';
1445
+ const Preview$1 = 'preview';
1446
+ const Payload$1 = 'payload';
1447
+ const Headers$1 = 'headers';
1448
+ const Tokens$1 = 'tokens';
1449
+ const Timing$1 = 'timing';
1450
+
1423
1451
  const emptyObject = {};
1424
1452
  const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
1425
1453
  const i18nString = (key, placeholders = emptyObject) => {
@@ -1432,8 +1460,8 @@ const i18nString = (key, placeholders = emptyObject) => {
1432
1460
  return key.replaceAll(RE_PLACEHOLDER, replacer);
1433
1461
  };
1434
1462
 
1435
- const All$1 = 'All';
1436
- const CloseDetails$1 = 'Close details';
1463
+ const All = 'All';
1464
+ const CloseDetails = 'Close details';
1437
1465
  const Copy = 'Copy';
1438
1466
  const CachedTokens = 'Cached Tokens';
1439
1467
  const DetailSections = 'Detail sections';
@@ -1443,7 +1471,7 @@ const FailedToLoadChatDebugSession = 'Failed to load chat debug session "{PH1}".
1443
1471
  const FailedToLoadChatDebugSessionWithError = 'Failed to load chat debug session "{PH1}": {PH2}';
1444
1472
  const FilterEvents = 'Filter events';
1445
1473
  const FromSeconds = 'from {PH1}s';
1446
- const Headers$1 = 'Headers';
1474
+ const Headers = 'Headers';
1447
1475
  const ImageCouldNotBeLoaded = 'image could not be loaded';
1448
1476
  const InputTokens = 'Input Tokens';
1449
1477
  const InvalidSessionId = 'Invalid session id';
@@ -1452,30 +1480,31 @@ const InvalidUriFormat = 'Invalid URI format';
1452
1480
  const Method$1 = 'Method';
1453
1481
  const MissingUri = 'Missing URI';
1454
1482
  const Name = 'Name';
1455
- const Network$1 = 'Network';
1483
+ const Network = 'Network';
1456
1484
  const NoChatSessionFound = 'No chat session found for sessionId "{PH1}".';
1457
1485
  const NoEventsFound = 'No events have been found';
1458
1486
  const NoEventsFoundMatching = 'No events found matching {PH1}';
1459
1487
  const NoToolCallEvents = 'No tool call events.';
1488
+ const OpenInNewTab = 'Open in New Tab';
1460
1489
  const OutputTokens = 'Output Tokens';
1461
- const Payload$1 = 'Payload';
1462
- const Preview$1 = 'Preview';
1463
- const Refresh$1 = 'Refresh';
1490
+ const Payload = 'Payload';
1491
+ const Preview = 'Preview';
1492
+ const Refresh = 'Refresh';
1464
1493
  const RefreshEvents = 'Refresh events';
1465
1494
  const ResetColumns = 'Reset columns';
1466
- const Response$1 = 'Response';
1495
+ const Response = 'Response';
1467
1496
  const SecondsRange = '{PH1}s-{PH2}s';
1468
1497
  const Started = 'Started';
1469
1498
  const Status$2 = 'Status';
1470
- const Stream$1 = 'Stream';
1499
+ const Stream = 'Stream';
1471
1500
  const TableSummaryPlural = '{PH1} events, {PH2} from start to finish';
1472
1501
  const TableSummarySingular = '{PH1} event, {PH2} from start to finish';
1473
- const Timing$1 = 'Timing';
1474
- const Tokens$1 = 'Tokens';
1502
+ const Timing = 'Timing';
1503
+ const Tokens = 'Tokens';
1475
1504
  const ToSeconds = 'to {PH1}s';
1476
- const Tools$1 = 'Tools';
1505
+ const Tools = 'Tools';
1477
1506
  const Type$1 = 'Type';
1478
- const Ui$1 = 'UI';
1507
+ const Ui = 'UI';
1479
1508
  const UnableToLoadDebugSessionInvalidUri = 'Unable to load debug session: invalid URI "{PH1}". Expected format: chat-debug://<sessionId>.';
1480
1509
  const UnableToLoadDebugSessionMissingUri = 'Unable to load debug session: missing URI. Expected format: chat-debug://<sessionId>.';
1481
1510
  const Value = 'Value';
@@ -1484,6 +1513,9 @@ const WindowSummary = 'Window {PH1}-{PH2} of {PH3}';
1484
1513
  const copy = () => {
1485
1514
  return i18nString(Copy);
1486
1515
  };
1516
+ const openInNewTab = () => {
1517
+ return i18nString(OpenInNewTab);
1518
+ };
1487
1519
  const cachedTokens = () => {
1488
1520
  return i18nString(CachedTokens);
1489
1521
  };
@@ -1491,10 +1523,10 @@ const status = () => {
1491
1523
  return i18nString(Status$2);
1492
1524
  };
1493
1525
  const all = () => {
1494
- return i18nString(All$1);
1526
+ return i18nString(All);
1495
1527
  };
1496
1528
  const closeDetails = () => {
1497
- return i18nString(CloseDetails$1);
1529
+ return i18nString(CloseDetails);
1498
1530
  };
1499
1531
  const detailSections = () => {
1500
1532
  return i18nString(DetailSections);
@@ -1525,7 +1557,7 @@ const fromSeconds = seconds => {
1525
1557
  });
1526
1558
  };
1527
1559
  const headers = () => {
1528
- return i18nString(Headers$1);
1560
+ return i18nString(Headers);
1529
1561
  };
1530
1562
  const invalidSessionId = () => {
1531
1563
  return i18nString(InvalidSessionId);
@@ -1552,7 +1584,7 @@ const name = () => {
1552
1584
  return i18nString(Name);
1553
1585
  };
1554
1586
  const network = () => {
1555
- return i18nString(Network$1);
1587
+ return i18nString(Network);
1556
1588
  };
1557
1589
  const noChatSessionFound = sessionId => {
1558
1590
  return i18nString(NoChatSessionFound, {
@@ -1571,16 +1603,16 @@ const noToolCallEvents = () => {
1571
1603
  return i18nString(NoToolCallEvents);
1572
1604
  };
1573
1605
  const preview = () => {
1574
- return i18nString(Preview$1);
1606
+ return i18nString(Preview);
1575
1607
  };
1576
1608
  const payload = () => {
1577
- return i18nString(Payload$1);
1609
+ return i18nString(Payload);
1578
1610
  };
1579
1611
  const outputTokens = () => {
1580
1612
  return i18nString(OutputTokens);
1581
1613
  };
1582
1614
  const refresh$1 = () => {
1583
- return i18nString(Refresh$1);
1615
+ return i18nString(Refresh);
1584
1616
  };
1585
1617
  const refreshEvents$1 = () => {
1586
1618
  return i18nString(RefreshEvents);
@@ -1589,7 +1621,7 @@ const resetColumns = () => {
1589
1621
  return i18nString(ResetColumns);
1590
1622
  };
1591
1623
  const response = () => {
1592
- return i18nString(Response$1);
1624
+ return i18nString(Response);
1593
1625
  };
1594
1626
  const secondsRange = (start, end) => {
1595
1627
  return i18nString(SecondsRange, {
@@ -1601,13 +1633,13 @@ const started = () => {
1601
1633
  return i18nString(Started);
1602
1634
  };
1603
1635
  const stream = () => {
1604
- return i18nString(Stream$1);
1636
+ return i18nString(Stream);
1605
1637
  };
1606
1638
  const timing = () => {
1607
- return i18nString(Timing$1);
1639
+ return i18nString(Timing);
1608
1640
  };
1609
1641
  const tokens = () => {
1610
- return i18nString(Tokens$1);
1642
+ return i18nString(Tokens);
1611
1643
  };
1612
1644
  const tableSummary = (eventCount, duration) => {
1613
1645
  return i18nString(eventCount === 1 ? TableSummarySingular : TableSummaryPlural, {
@@ -1621,7 +1653,7 @@ const toSeconds = seconds => {
1621
1653
  });
1622
1654
  };
1623
1655
  const tools = () => {
1624
- return i18nString(Tools$1);
1656
+ return i18nString(Tools);
1625
1657
  };
1626
1658
  const type = () => {
1627
1659
  return i18nString(Type$1);
@@ -1630,7 +1662,7 @@ const value = () => {
1630
1662
  return i18nString(Value);
1631
1663
  };
1632
1664
  const ui = () => {
1633
- return i18nString(Ui$1);
1665
+ return i18nString(Ui);
1634
1666
  };
1635
1667
  const unableToLoadDebugSessionInvalidUri = uri => {
1636
1668
  return i18nString(UnableToLoadDebugSessionInvalidUri, {
@@ -1648,262 +1680,66 @@ const windowSummary = (start, end, duration) => {
1648
1680
  });
1649
1681
  };
1650
1682
 
1651
- const Filter = 'filter';
1652
- const EventCategoryFilter = 'eventCategoryFilter';
1653
- const ShowEventStreamFinishedEvents = 'showEventStreamFinishedEvents';
1654
- const ShowInputEvents = 'showInputEvents';
1655
- const ShowResponsePartEvents = 'showResponsePartEvents';
1656
- const UseDevtoolsLayout = 'useDevtoolsLayout';
1657
- const SelectedEventIndex = 'selectedEventIndex';
1658
- const CloseDetails = 'closeDetails';
1659
- const DetailTab = 'detailTab';
1660
- const TimelineStartSeconds = 'timelineStartSeconds';
1661
- const TimelineEndSeconds = 'timelineEndSeconds';
1662
- const TimelineRangePreset = 'timelineRangePreset';
1663
- const Refresh = 'refresh';
1664
- const All = 'all';
1665
- const Tools = 'tools';
1666
- const Network = 'network';
1667
- const Ui = 'ui';
1668
- const Stream = 'stream';
1669
- const Response = 'response';
1670
- const Preview = 'preview';
1671
- const Payload = 'payload';
1672
- const Headers = 'headers';
1673
- const Tokens = 'tokens';
1674
- const Timing = 'timing';
1675
-
1676
- const isDetailTab = value => {
1677
- return value === Response || value === Preview || value === Payload || value === Headers || value === Tokens || value === Headers || value === Timing;
1678
- };
1679
-
1680
- const getSafeSelectedDetailTab = selectedDetailTab => {
1681
- return isDetailTab(selectedDetailTab) ? selectedDetailTab : Response;
1682
- };
1683
-
1684
- const isHeadersRecord$1 = value => {
1685
- return typeof value === 'object' && value !== null && !Array.isArray(value);
1686
- };
1687
- const hasHeadersDetails = event => {
1688
- return event.type === 'ai-request' && isHeadersRecord$1(event.headers);
1689
- };
1690
-
1691
- const hasTimingDetails = event => {
1692
- const hasDuration = typeof event.duration === 'number' || typeof event.durationMs === 'number';
1693
- const hasStart = event.started !== undefined || event.startTime !== undefined || event.startTimestamp !== undefined;
1694
- const hasEnd = event.ended !== undefined || event.endTime !== undefined || event.endTimestamp !== undefined;
1695
- return hasDuration || hasStart && hasEnd;
1696
- };
1697
-
1698
- const getResponseEvent = event => {
1699
- const {
1700
- responseEvent
1701
- } = event;
1702
- if (responseEvent && typeof responseEvent === 'object' && typeof responseEvent.type === 'string') {
1703
- const mergedResponseEvent = responseEvent;
1704
- if (mergedResponseEvent.value !== undefined) {
1705
- return mergedResponseEvent.value;
1706
- }
1707
- return responseEvent;
1708
- }
1709
- return event;
1710
- };
1711
-
1712
- const isObject = value => {
1713
- return typeof value === 'object' && value !== null;
1714
- };
1715
- const getNumber = (value, ...keys) => {
1716
- for (const key of keys) {
1717
- if (typeof value[key] === 'number') {
1718
- return value[key];
1719
- }
1720
- }
1721
- return undefined;
1722
- };
1723
- const getUsage = event => {
1724
- const responseEvent = getResponseEvent(event);
1725
- if (isObject(responseEvent) && isObject(responseEvent.usage)) {
1726
- return responseEvent.usage;
1727
- }
1728
- if (isObject(responseEvent) && isObject(responseEvent.value) && isObject(responseEvent.value.usage)) {
1729
- return responseEvent.value.usage;
1730
- }
1731
- return undefined;
1732
- };
1733
- const getTokenUsageDetails = event => {
1734
- const usage = getUsage(event);
1735
- if (!usage) {
1736
- return undefined;
1737
- }
1738
- const inputTokens = getNumber(usage, 'input_tokens', 'inputTokens');
1739
- const outputTokens = getNumber(usage, 'output_tokens', 'outputTokens');
1740
- let inputTokenDetails;
1741
- if (isObject(usage.input_tokens_details)) {
1742
- inputTokenDetails = usage.input_tokens_details;
1743
- } else if (isObject(usage.inputTokensDetails)) {
1744
- inputTokenDetails = usage.inputTokensDetails;
1745
- }
1746
- const cachedTokens = inputTokenDetails ? getNumber(inputTokenDetails, 'cached_tokens', 'cachedTokens') : getNumber(usage, 'cached_tokens', 'cachedTokens');
1747
- if (inputTokens === undefined && outputTokens === undefined && cachedTokens === undefined) {
1748
- return undefined;
1749
- }
1750
- return {
1751
- ...(cachedTokens === undefined ? undefined : {
1752
- cachedTokens
1753
- }),
1754
- ...(inputTokens === undefined ? undefined : {
1755
- inputTokens
1756
- }),
1757
- ...(outputTokens === undefined ? undefined : {
1758
- outputTokens
1759
- })
1760
- };
1761
- };
1762
-
1763
- const hasTokenUsageDetails = event => {
1764
- return getTokenUsageDetails(event) !== undefined;
1765
- };
1766
-
1767
- const createDetailTabs = (selectedDetailTab = Response, event) => {
1768
- const hasHeadersTab = event ? hasHeadersDetails(event) : false;
1769
- const hasTokensTab = event ? hasTokenUsageDetails(event) : false;
1770
- const hasTimingTab = event ? hasTimingDetails(event) : true;
1771
- const safeSelectedDetailTab = getSafeSelectedDetailTab(selectedDetailTab);
1772
- let normalizedSelectedDetailTab = safeSelectedDetailTab;
1773
- if (!hasHeadersTab && normalizedSelectedDetailTab === Headers) {
1774
- normalizedSelectedDetailTab = Response;
1775
- }
1776
- if (!hasTokensTab && normalizedSelectedDetailTab === Tokens) {
1777
- normalizedSelectedDetailTab = Response;
1778
- }
1779
- if (!hasTimingTab && normalizedSelectedDetailTab === Timing) {
1780
- normalizedSelectedDetailTab = Response;
1781
- }
1782
- const detailTabs = [{
1783
- isSelected: normalizedSelectedDetailTab === Preview,
1784
- label: preview(),
1785
- name: Preview
1786
- }, {
1787
- isSelected: normalizedSelectedDetailTab === Payload,
1788
- label: payload(),
1789
- name: Payload
1790
- }, {
1791
- isSelected: normalizedSelectedDetailTab === Response,
1792
- label: response(),
1793
- name: Response
1794
- }];
1795
- if (hasHeadersTab) {
1796
- detailTabs.push({
1797
- isSelected: normalizedSelectedDetailTab === Headers,
1798
- label: headers(),
1799
- name: Headers
1800
- });
1801
- }
1802
- if (hasTokensTab) {
1803
- detailTabs.push({
1804
- isSelected: normalizedSelectedDetailTab === Tokens,
1805
- label: tokens(),
1806
- name: Tokens
1807
- });
1808
- }
1809
- if (hasTimingTab) {
1810
- detailTabs.push({
1811
- isSelected: normalizedSelectedDetailTab === Timing,
1812
- label: timing(),
1813
- name: Timing
1814
- });
1815
- }
1816
- return detailTabs;
1817
- };
1818
-
1819
- const getSelectedDetailTab = detailTabs => {
1820
- const selectedDetailTab = detailTabs.find(detailTab => detailTab.isSelected);
1821
- if (selectedDetailTab) {
1822
- return selectedDetailTab.name;
1823
- }
1824
- const responseTab = detailTabs.find(detailTab => detailTab.name === Response);
1825
- if (responseTab) {
1826
- return responseTab.name;
1827
- }
1828
- return detailTabs[0]?.name ?? Response;
1829
- };
1830
-
1831
- const hasDetailTab = (detailTabs, value) => {
1832
- return detailTabs.some(detailTab => detailTab.name === value);
1833
- };
1834
-
1835
- const selectDetailTab$1 = (detailTabs, selectedDetailTab) => {
1836
- if (!hasDetailTab(detailTabs, selectedDetailTab)) {
1837
- return detailTabs;
1838
- }
1839
- return detailTabs.map(detailTab => {
1840
- return {
1841
- ...detailTab,
1842
- isSelected: detailTab.name === selectedDetailTab
1843
- };
1844
- });
1845
- };
1846
-
1847
1683
  const getEventCategoryFilterLabel = eventCategoryFilter => {
1848
1684
  switch (eventCategoryFilter) {
1849
- case Network:
1685
+ case Network$1:
1850
1686
  return network();
1851
- case Stream:
1687
+ case Stream$1:
1852
1688
  return stream();
1853
- case Tools:
1689
+ case Tools$1:
1854
1690
  return tools();
1855
- case Ui:
1691
+ case Ui$1:
1856
1692
  return ui();
1857
1693
  default:
1858
1694
  return all();
1859
1695
  }
1860
1696
  };
1861
1697
 
1862
- const eventCategoryFilters = [All, Tools, Network, Ui, Stream];
1863
- const normalizeSelectedEventCategoryFilters = (selectedEventCategoryFilter = All) => {
1698
+ const eventCategoryFilters = [All$1, Tools$1, Network$1, Ui$1, Stream$1];
1699
+ const normalizeSelectedEventCategoryFilters = (selectedEventCategoryFilter = All$1) => {
1864
1700
  const selectedEventCategoryFilters = Array.isArray(selectedEventCategoryFilter) ? selectedEventCategoryFilter : [selectedEventCategoryFilter];
1865
1701
  const uniqueSelectedEventCategoryFilters = [...new Set(selectedEventCategoryFilters)];
1866
1702
  const validSelectedEventCategoryFilters = uniqueSelectedEventCategoryFilters.filter(value => {
1867
1703
  return eventCategoryFilters.includes(value);
1868
1704
  });
1869
1705
  if (validSelectedEventCategoryFilters.length === 0) {
1870
- return [All];
1706
+ return [All$1];
1871
1707
  }
1872
- if (validSelectedEventCategoryFilters.includes(All)) {
1873
- return [All];
1708
+ if (validSelectedEventCategoryFilters.includes(All$1)) {
1709
+ return [All$1];
1874
1710
  }
1875
1711
  return validSelectedEventCategoryFilters;
1876
1712
  };
1877
- const createCategoryFilters$1 = (selectedEventCategoryFilter = All) => {
1713
+ const createCategoryFilters$1 = (selectedEventCategoryFilter = All$1) => {
1878
1714
  const selectedEventCategoryFilters = normalizeSelectedEventCategoryFilters(selectedEventCategoryFilter);
1879
1715
  return [{
1880
- isSelected: selectedEventCategoryFilters.includes(All),
1716
+ isSelected: selectedEventCategoryFilters.includes(All$1),
1881
1717
  label: all(),
1882
- name: All
1718
+ name: All$1
1883
1719
  }, {
1884
- isSelected: selectedEventCategoryFilters.includes(Tools),
1720
+ isSelected: selectedEventCategoryFilters.includes(Tools$1),
1885
1721
  label: tools(),
1886
- name: Tools
1722
+ name: Tools$1
1887
1723
  }, {
1888
- isSelected: selectedEventCategoryFilters.includes(Network),
1724
+ isSelected: selectedEventCategoryFilters.includes(Network$1),
1889
1725
  label: network(),
1890
- name: Network
1726
+ name: Network$1
1891
1727
  }, {
1892
- isSelected: selectedEventCategoryFilters.includes(Ui),
1728
+ isSelected: selectedEventCategoryFilters.includes(Ui$1),
1893
1729
  label: ui(),
1894
- name: Ui
1730
+ name: Ui$1
1895
1731
  }, {
1896
- isSelected: selectedEventCategoryFilters.includes(Stream),
1732
+ isSelected: selectedEventCategoryFilters.includes(Stream$1),
1897
1733
  label: stream(),
1898
- name: Stream
1734
+ name: Stream$1
1899
1735
  }];
1900
1736
  };
1901
1737
 
1902
- const createCategoryFilters = (selectedEventCategoryFilter = All) => {
1738
+ const createCategoryFilters = (selectedEventCategoryFilter = All$1) => {
1903
1739
  return createCategoryFilters$1(selectedEventCategoryFilter);
1904
1740
  };
1905
1741
  const isEventCategoryFilter = value => {
1906
- return value === All || value === Tools || value === Network || value === Ui || value === Stream;
1742
+ return value === All$1 || value === Tools$1 || value === Network$1 || value === Ui$1 || value === Stream$1;
1907
1743
  };
1908
1744
  const getSelectedEventCategoryFilters = categoryFilters => {
1909
1745
  const selectedCategoryFilters = categoryFilters.filter(categoryFilter => categoryFilter.isSelected);
@@ -1915,7 +1751,7 @@ const getSelectedEventCategoryFilter = categoryFilters => {
1915
1751
  if (selectedEventCategoryFilters.length === 1) {
1916
1752
  return selectedEventCategoryFilters[0];
1917
1753
  }
1918
- return All;
1754
+ return All$1;
1919
1755
  };
1920
1756
  const selectCategoryFilters = (categoryFilters, selectedEventCategoryFilters) => {
1921
1757
  const normalizedSelectedEventCategoryFilters = normalizeSelectedEventCategoryFilters(selectedEventCategoryFilters.filter(value => isEventCategoryFilter(value)));
@@ -1934,29 +1770,33 @@ const selectCategoryFilter = (categoryFilters, selectedEventCategoryFilter, addi
1934
1770
  if (!isEventCategoryFilter(selectedEventCategoryFilter)) {
1935
1771
  return categoryFilters;
1936
1772
  }
1937
- if (!additive || selectedEventCategoryFilter === All) {
1773
+ if (!additive || selectedEventCategoryFilter === All$1) {
1938
1774
  return selectCategoryFilters(categoryFilters, [selectedEventCategoryFilter]);
1939
1775
  }
1940
- const selectedEventCategoryFilters = getSelectedEventCategoryFilters(categoryFilters).filter(value => value !== All);
1776
+ const selectedEventCategoryFilters = getSelectedEventCategoryFilters(categoryFilters).filter(value => value !== All$1);
1941
1777
  const nextSelectedEventCategoryFilters = selectedEventCategoryFilters.includes(selectedEventCategoryFilter) ? selectedEventCategoryFilters.filter(value => value !== selectedEventCategoryFilter) : [...selectedEventCategoryFilters, selectedEventCategoryFilter];
1942
1778
  if (nextSelectedEventCategoryFilters.length === 0) {
1943
- return selectCategoryFilters(categoryFilters, [All]);
1779
+ return selectCategoryFilters(categoryFilters, [All$1]);
1944
1780
  }
1945
1781
  return selectCategoryFilters(categoryFilters, nextSelectedEventCategoryFilters);
1946
1782
  };
1947
1783
 
1784
+ const isDetailTab = value => {
1785
+ return value === Response$1 || value === Preview$1 || value === Payload$1 || value === Headers$1 || value === Tokens$1 || value === Headers$1 || value === Timing$1;
1786
+ };
1787
+
1948
1788
  const RE_SPACE = /\s+/;
1949
- const tokenToEventCategoryFilter = new Map([['@tools', Tools], ['@network', Network], ['@ui', Ui], ['@stream', Stream]]);
1789
+ const tokenToEventCategoryFilter = new Map([['@tools', Tools$1], ['@network', Network$1], ['@ui', Ui$1], ['@stream', Stream$1]]);
1950
1790
  const parseFilterValue = filterValue => {
1951
1791
  const normalizedFilter = filterValue.trim().toLowerCase();
1952
1792
  if (!normalizedFilter) {
1953
1793
  return {
1954
- eventCategoryFilter: All,
1794
+ eventCategoryFilter: All$1,
1955
1795
  filterText: ''
1956
1796
  };
1957
1797
  }
1958
1798
  const parts = normalizedFilter.split(RE_SPACE);
1959
- const eventCategoryFilter = parts.map(part => tokenToEventCategoryFilter.get(part)).find(Boolean) || All;
1799
+ const eventCategoryFilter = parts.map(part => tokenToEventCategoryFilter.get(part)).find(Boolean) || All$1;
1960
1800
  const filterText = parts.filter(part => !tokenToEventCategoryFilter.has(part)).join(' ');
1961
1801
  return {
1962
1802
  eventCategoryFilter,
@@ -1964,6 +1804,22 @@ const parseFilterValue = filterValue => {
1964
1804
  };
1965
1805
  };
1966
1806
 
1807
+ const hasDetailTab = (detailTabs, value) => {
1808
+ return detailTabs.some(detailTab => detailTab.name === value);
1809
+ };
1810
+
1811
+ const selectDetailTab$1 = (detailTabs, selectedDetailTab) => {
1812
+ if (!hasDetailTab(detailTabs, selectedDetailTab)) {
1813
+ return detailTabs;
1814
+ }
1815
+ return detailTabs.map(detailTab => {
1816
+ return {
1817
+ ...detailTab,
1818
+ isSelected: detailTab.name === selectedDetailTab
1819
+ };
1820
+ });
1821
+ };
1822
+
1967
1823
  const Type = 'type';
1968
1824
  const Method = 'method';
1969
1825
  const Duration = 'duration';
@@ -2140,7 +1996,7 @@ const isTableColumnWidths = value => {
2140
1996
  return isFiniteNumber(record.type) && isFiniteNumber(record.method) && isFiniteNumber(record.duration) && isFiniteNumber(record.status);
2141
1997
  };
2142
1998
 
2143
- const validEventCategoryFilters = new Set([All, Network, Stream, Tools, Ui]);
1999
+ const validEventCategoryFilters = new Set([All$1, Network$1, Stream$1, Tools$1, Ui$1]);
2144
2000
  const isSavedState = value => {
2145
2001
  return typeof value === 'object' && value !== null;
2146
2002
  };
@@ -2207,6 +2063,145 @@ const {
2207
2063
  wrapGetter
2208
2064
  } = create$1();
2209
2065
 
2066
+ const getSafeSelectedDetailTab = selectedDetailTab => {
2067
+ return isDetailTab(selectedDetailTab) ? selectedDetailTab : Response$1;
2068
+ };
2069
+
2070
+ const isHeadersRecord$1 = value => {
2071
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
2072
+ };
2073
+ const hasHeadersDetails = event => {
2074
+ return event.type === 'ai-request' && isHeadersRecord$1(event.headers);
2075
+ };
2076
+
2077
+ const hasTimingDetails = event => {
2078
+ const hasDuration = typeof event.duration === 'number' || typeof event.durationMs === 'number';
2079
+ const hasStart = event.started !== undefined || event.startTime !== undefined || event.startTimestamp !== undefined;
2080
+ const hasEnd = event.ended !== undefined || event.endTime !== undefined || event.endTimestamp !== undefined;
2081
+ return hasDuration || hasStart && hasEnd;
2082
+ };
2083
+
2084
+ const getResponseEvent = event => {
2085
+ const {
2086
+ responseEvent
2087
+ } = event;
2088
+ if (responseEvent && typeof responseEvent === 'object' && typeof responseEvent.type === 'string') {
2089
+ const mergedResponseEvent = responseEvent;
2090
+ if (mergedResponseEvent.value !== undefined) {
2091
+ return mergedResponseEvent.value;
2092
+ }
2093
+ return responseEvent;
2094
+ }
2095
+ return event;
2096
+ };
2097
+
2098
+ const isObject = value => {
2099
+ return typeof value === 'object' && value !== null;
2100
+ };
2101
+ const getNumber = (value, ...keys) => {
2102
+ for (const key of keys) {
2103
+ if (typeof value[key] === 'number') {
2104
+ return value[key];
2105
+ }
2106
+ }
2107
+ return undefined;
2108
+ };
2109
+ const getUsage = event => {
2110
+ const responseEvent = getResponseEvent(event);
2111
+ if (isObject(responseEvent) && isObject(responseEvent.usage)) {
2112
+ return responseEvent.usage;
2113
+ }
2114
+ if (isObject(responseEvent) && isObject(responseEvent.value) && isObject(responseEvent.value.usage)) {
2115
+ return responseEvent.value.usage;
2116
+ }
2117
+ return undefined;
2118
+ };
2119
+ const getTokenUsageDetails = event => {
2120
+ const usage = getUsage(event);
2121
+ if (!usage) {
2122
+ return undefined;
2123
+ }
2124
+ const inputTokens = getNumber(usage, 'input_tokens', 'inputTokens');
2125
+ const outputTokens = getNumber(usage, 'output_tokens', 'outputTokens');
2126
+ let inputTokenDetails;
2127
+ if (isObject(usage.input_tokens_details)) {
2128
+ inputTokenDetails = usage.input_tokens_details;
2129
+ } else if (isObject(usage.inputTokensDetails)) {
2130
+ inputTokenDetails = usage.inputTokensDetails;
2131
+ }
2132
+ const cachedTokens = inputTokenDetails ? getNumber(inputTokenDetails, 'cached_tokens', 'cachedTokens') : getNumber(usage, 'cached_tokens', 'cachedTokens');
2133
+ if (inputTokens === undefined && outputTokens === undefined && cachedTokens === undefined) {
2134
+ return undefined;
2135
+ }
2136
+ return {
2137
+ ...(cachedTokens === undefined ? undefined : {
2138
+ cachedTokens
2139
+ }),
2140
+ ...(inputTokens === undefined ? undefined : {
2141
+ inputTokens
2142
+ }),
2143
+ ...(outputTokens === undefined ? undefined : {
2144
+ outputTokens
2145
+ })
2146
+ };
2147
+ };
2148
+
2149
+ const hasTokenUsageDetails = event => {
2150
+ return getTokenUsageDetails(event) !== undefined;
2151
+ };
2152
+
2153
+ const createDetailTabs = (selectedDetailTab = Response$1, event) => {
2154
+ const hasHeadersTab = event ? hasHeadersDetails(event) : false;
2155
+ const hasTokensTab = event ? hasTokenUsageDetails(event) : false;
2156
+ const hasTimingTab = event ? hasTimingDetails(event) : true;
2157
+ const safeSelectedDetailTab = getSafeSelectedDetailTab(selectedDetailTab);
2158
+ let normalizedSelectedDetailTab = safeSelectedDetailTab;
2159
+ if (!hasHeadersTab && normalizedSelectedDetailTab === Headers$1) {
2160
+ normalizedSelectedDetailTab = Response$1;
2161
+ }
2162
+ if (!hasTokensTab && normalizedSelectedDetailTab === Tokens$1) {
2163
+ normalizedSelectedDetailTab = Response$1;
2164
+ }
2165
+ if (!hasTimingTab && normalizedSelectedDetailTab === Timing$1) {
2166
+ normalizedSelectedDetailTab = Response$1;
2167
+ }
2168
+ const detailTabs = [{
2169
+ isSelected: normalizedSelectedDetailTab === Preview$1,
2170
+ label: preview(),
2171
+ name: Preview$1
2172
+ }, {
2173
+ isSelected: normalizedSelectedDetailTab === Payload$1,
2174
+ label: payload(),
2175
+ name: Payload$1
2176
+ }, {
2177
+ isSelected: normalizedSelectedDetailTab === Response$1,
2178
+ label: response(),
2179
+ name: Response$1
2180
+ }];
2181
+ if (hasHeadersTab) {
2182
+ detailTabs.push({
2183
+ isSelected: normalizedSelectedDetailTab === Headers$1,
2184
+ label: headers(),
2185
+ name: Headers$1
2186
+ });
2187
+ }
2188
+ if (hasTokensTab) {
2189
+ detailTabs.push({
2190
+ isSelected: normalizedSelectedDetailTab === Tokens$1,
2191
+ label: tokens(),
2192
+ name: Tokens$1
2193
+ });
2194
+ }
2195
+ if (hasTimingTab) {
2196
+ detailTabs.push({
2197
+ isSelected: normalizedSelectedDetailTab === Timing$1,
2198
+ label: timing(),
2199
+ name: Timing$1
2200
+ });
2201
+ }
2202
+ return detailTabs;
2203
+ };
2204
+
2210
2205
  const toTimeNumber = value => {
2211
2206
  if (typeof value === 'number' && Number.isFinite(value)) {
2212
2207
  return value;
@@ -2237,6 +2232,10 @@ const getEventsWithTime = events => {
2237
2232
  });
2238
2233
  };
2239
2234
 
2235
+ const clamp$1 = (value, minimum, maximum) => {
2236
+ return Math.max(minimum, Math.min(value, maximum));
2237
+ };
2238
+
2240
2239
  const parseTimelineSeconds = value => {
2241
2240
  const trimmed = value.trim();
2242
2241
  if (!trimmed) {
@@ -2265,8 +2264,10 @@ const getNormalizedRange = (durationSeconds, startValue, endValue) => {
2265
2264
  }
2266
2265
  const rawStart = parsedStart ?? 0;
2267
2266
  const rawEnd = parsedEnd ?? durationSeconds;
2268
- const normalizedStart = Math.max(0, Math.min(durationSeconds, Math.min(rawStart, rawEnd)));
2269
- const normalizedEnd = Math.max(0, Math.min(durationSeconds, Math.max(rawStart, rawEnd)));
2267
+ const rangeStart = Math.min(rawStart, rawEnd);
2268
+ const rangeEnd = Math.max(rawStart, rawEnd);
2269
+ const normalizedStart = clamp$1(rangeStart, 0, durationSeconds);
2270
+ const normalizedEnd = clamp$1(rangeEnd, 0, durationSeconds);
2270
2271
  return {
2271
2272
  endSeconds: roundSeconds(normalizedEnd),
2272
2273
  hasSelection: true,
@@ -2465,6 +2466,18 @@ const diff2 = uid => {
2465
2466
  return diff(oldState, newState);
2466
2467
  };
2467
2468
 
2469
+ const getSelectedDetailTab = detailTabs => {
2470
+ const selectedDetailTab = detailTabs.find(detailTab => detailTab.isSelected);
2471
+ if (selectedDetailTab) {
2472
+ return selectedDetailTab.name;
2473
+ }
2474
+ const responseTab = detailTabs.find(detailTab => detailTab.name === Response$1);
2475
+ if (responseTab) {
2476
+ return responseTab.name;
2477
+ }
2478
+ return detailTabs[0]?.name ?? Response$1;
2479
+ };
2480
+
2468
2481
  const filterEventsByTimelineRange = (events, startValue, endValue) => {
2469
2482
  const eventsWithTime = getEventsWithTime(events);
2470
2483
  if (eventsWithTime.length === 0) {
@@ -2677,20 +2690,20 @@ const isUiEvent = event => {
2677
2690
 
2678
2691
  const matchesSingleEventCategoryFilter = (event, eventCategoryFilter) => {
2679
2692
  switch (eventCategoryFilter) {
2680
- case Network:
2693
+ case Network$1:
2681
2694
  return isNetworkEvent(event);
2682
- case Stream:
2695
+ case Stream$1:
2683
2696
  return isStreamEvent(event);
2684
- case Tools:
2697
+ case Tools$1:
2685
2698
  return isToolEvent(event);
2686
- case Ui:
2699
+ case Ui$1:
2687
2700
  return isUiEvent(event);
2688
2701
  default:
2689
2702
  return true;
2690
2703
  }
2691
2704
  };
2692
2705
  const matchesEventCategoryFilter = (event, eventCategoryFilters) => {
2693
- if (eventCategoryFilters.length === 0 || eventCategoryFilters.includes(All)) {
2706
+ if (eventCategoryFilters.length === 0 || eventCategoryFilters.includes(All$1)) {
2694
2707
  return true;
2695
2708
  }
2696
2709
  return eventCategoryFilters.some(eventCategoryFilter => matchesSingleEventCategoryFilter(event, eventCategoryFilter));
@@ -2700,7 +2713,7 @@ const getFilteredEvents = (events, filterValue, eventCategoryFilters, showInputE
2700
2713
  const visibleEvents = getVisibleEvents(events, showInputEvents, showResponsePartEvents, showEventStreamFinishedEvents);
2701
2714
  const collapsedEvents = collapseToolExecutionEvents(visibleEvents);
2702
2715
  const parsedFilter = parseFilterValue(filterValue);
2703
- const activeEventCategoryFilters = parsedFilter.eventCategoryFilter === All ? eventCategoryFilters : [parsedFilter.eventCategoryFilter];
2716
+ const activeEventCategoryFilters = parsedFilter.eventCategoryFilter === All$1 ? eventCategoryFilters : [parsedFilter.eventCategoryFilter];
2704
2717
  const filteredByCategory = collapsedEvents.filter(event => matchesEventCategoryFilter(event, activeEventCategoryFilters));
2705
2718
  const {
2706
2719
  filterText
@@ -3122,12 +3135,17 @@ const withPreparedSelectedEventPreview = async event => {
3122
3135
  return setSelectedEventPreview(event, preview);
3123
3136
  };
3124
3137
 
3125
- const selectEventAtIndexDependencies = {
3126
- loadSelectedEvent: loadSelectedEvent
3127
- };
3128
3138
  const getCurrentEvents$1 = state => getCurrentEvents$2(state);
3129
- const selectEventAtIndex = async (state, selectedEventIndex, dependencies = selectEventAtIndexDependencies) => {
3130
- const selectedDetailTab = getSelectedDetailTab(state.detailTabs);
3139
+ const selectEventAtIndex = async (state, selectedEventIndex, loadSelectedEvent$1 = loadSelectedEvent) => {
3140
+ const {
3141
+ databaseName,
3142
+ dataBaseVersion,
3143
+ detailTabs,
3144
+ eventStoreName,
3145
+ sessionId,
3146
+ sessionIdIndexName
3147
+ } = state;
3148
+ const selectedDetailTab = getSelectedDetailTab(detailTabs);
3131
3149
  const currentEvents = getCurrentEvents$1(state);
3132
3150
  const selectedEvent = currentEvents[selectedEventIndex];
3133
3151
  if (!selectedEvent) {
@@ -3146,7 +3164,7 @@ const selectEventAtIndex = async (state, selectedEventIndex, dependencies = sele
3146
3164
  selectedEventIndex
3147
3165
  };
3148
3166
  }
3149
- const selectedEventDetails = await dependencies.loadSelectedEvent(state.databaseName, state.dataBaseVersion, state.eventStoreName, state.sessionId, state.sessionIdIndexName, selectedEvent.eventId, selectedEvent.type);
3167
+ const selectedEventDetails = await loadSelectedEvent$1(databaseName, dataBaseVersion, eventStoreName, sessionId, sessionIdIndexName, selectedEvent.eventId, selectedEvent.type);
3150
3168
  const resolvedSelectedEvent = await withPreparedSelectedEventPreview(mergeSelectedEventDetails(selectedEvent, selectedEventDetails));
3151
3169
  return withSelectedEventVisible({
3152
3170
  ...state,
@@ -3210,6 +3228,12 @@ const getMenuEntriesTableBody = props => {
3210
3228
  flags: None$1,
3211
3229
  id: 'copy',
3212
3230
  label: copy()
3231
+ }, {
3232
+ args: [props.eventIndex],
3233
+ command: 'ChatDebug.handleTableRowOpenInNewTab',
3234
+ flags: None$1,
3235
+ id: 'open-in-new-tab',
3236
+ label: openInNewTab()
3213
3237
  }];
3214
3238
  };
3215
3239
 
@@ -3247,7 +3271,10 @@ const getMenuEntriesTableHeader = state => {
3247
3271
 
3248
3272
  const MenuChatDebugTableHeader = 2189;
3249
3273
  const handleHeaderContextMenu = async (state, eventX, eventY) => {
3250
- await showContextMenu2(state.uid, MenuChatDebugTableHeader, eventX, eventY, {
3274
+ const {
3275
+ uid
3276
+ } = state;
3277
+ await showContextMenu2(uid, MenuChatDebugTableHeader, eventX, eventY, {
3251
3278
  menuId: MenuChatDebugTableHeader
3252
3279
  });
3253
3280
  return state;
@@ -3312,9 +3339,51 @@ const getMenuIds = () => {
3312
3339
  return [MenuChatDebugTableHeader, MenuChatDebugTableBody, 556, 557];
3313
3340
  };
3314
3341
 
3342
+ const getResponseMap = events => {
3343
+ const seen = Object.create(null);
3344
+ for (const event of events) {
3345
+ if (event.type === 'ai-response' && 'requestId' in event && typeof event.requestId === 'string') {
3346
+ seen[event.requestId] = event;
3347
+ }
3348
+ }
3349
+ return seen;
3350
+ };
3351
+
3352
+ const toPrettyEvents = rawEvents => {
3353
+ if (rawEvents.type === 'error') {
3354
+ return [];
3355
+ }
3356
+ const pretty = [];
3357
+ const map = getResponseMap(rawEvents.events);
3358
+ for (const item of rawEvents.events) {
3359
+ if (item.type === 'ai-request' && 'requestId' in item && typeof item.requestId === 'string') {
3360
+ const response = map[item.requestId];
3361
+ if (response) {
3362
+ pretty.push({
3363
+ eventId: item.eventId,
3364
+ type: 'ai-request-response'
3365
+ });
3366
+ } else {
3367
+ pretty.push(item);
3368
+ }
3369
+ } else if (item.type === 'ai-response' && 'requestId' in item && typeof item.requestId === 'string') ; else {
3370
+ pretty.push(item);
3371
+ }
3372
+ }
3373
+ return pretty;
3374
+ };
3375
+
3315
3376
  const listChatViewEvents = async (sessionId, _databaseName, _dataBaseVersion, _eventStoreName, _sessionIdIndexName) => {
3316
3377
  try {
3317
- return await listChatViewEvents$1(sessionId);
3378
+ const rawEvents = await listChatViewEvents$1(sessionId);
3379
+ if (rawEvents.type === 'error') {
3380
+ return rawEvents;
3381
+ }
3382
+ const prettyEvents = toPrettyEvents(rawEvents);
3383
+ return {
3384
+ events: prettyEvents,
3385
+ type: 'success'
3386
+ };
3318
3387
  } catch (error) {
3319
3388
  return {
3320
3389
  error,
@@ -3724,7 +3793,7 @@ const handleEventCategoryFilter$1 = (state, value, ctrlKey = false, metaKey = fa
3724
3793
  const {
3725
3794
  categoryFilters
3726
3795
  } = state;
3727
- const newCategoryFilters = selectCategoryFilter(categoryFilters, value || All, ctrlKey || metaKey);
3796
+ const newCategoryFilters = selectCategoryFilter(categoryFilters, value || All$1, ctrlKey || metaKey);
3728
3797
  if (newCategoryFilters === categoryFilters) {
3729
3798
  return state;
3730
3799
  }
@@ -3735,13 +3804,10 @@ const handleEventCategoryFilter$1 = (state, value, ctrlKey = false, metaKey = fa
3735
3804
  return withPreservedSelection$1(state, nextState);
3736
3805
  };
3737
3806
 
3738
- const handleEventRowClickDependencies = {
3739
- loadSelectedEvent: loadSelectedEvent
3740
- };
3741
3807
  const isPrimaryButton = button => {
3742
3808
  return button === 0;
3743
3809
  };
3744
- const handleEventRowClick = async (state, index, button = 0) => {
3810
+ const handleEventRowClick = async (state, index, button = 0, loadSelectedEvent) => {
3745
3811
  const actual = typeof index === 'string' ? Number.parseInt(index, 10) : index;
3746
3812
  if (!isPrimaryButton(button)) {
3747
3813
  return state;
@@ -3749,12 +3815,12 @@ const handleEventRowClick = async (state, index, button = 0) => {
3749
3815
  if (actual === -1) {
3750
3816
  return state;
3751
3817
  }
3752
- return selectEventAtIndex(state, actual, handleEventRowClickDependencies);
3818
+ return selectEventAtIndex(state, actual, loadSelectedEvent);
3753
3819
  };
3754
3820
 
3755
- const handleEventRowClickAt = async (state, eventX, eventY, button = 0) => {
3821
+ const handleEventRowClickAt = async (state, eventX, eventY, button = 0, loadSelectedEvent) => {
3756
3822
  const selectedEventIndex = getTableBodyEventIndex(state, eventX, eventY);
3757
- return handleEventRowClick(state, selectedEventIndex, button);
3823
+ return handleEventRowClick(state, selectedEventIndex, button, loadSelectedEvent);
3758
3824
  };
3759
3825
 
3760
3826
  const getBoolean = value => {
@@ -3845,7 +3911,7 @@ const handleFilter = (state, value) => {
3845
3911
  });
3846
3912
  };
3847
3913
  const handleEventCategoryFilter = (state, value) => {
3848
- const categoryFilters = selectCategoryFilter(state.categoryFilters, value || All);
3914
+ const categoryFilters = selectCategoryFilter(state.categoryFilters, value || All$1);
3849
3915
  if (categoryFilters === state.categoryFilters) {
3850
3916
  return state;
3851
3917
  }
@@ -3931,7 +3997,7 @@ const handleDetailTab = (state, value) => {
3931
3997
  };
3932
3998
  };
3933
3999
  const inputHandlers = {
3934
- [CloseDetails]: handleCloseDetails,
4000
+ [CloseDetails$1]: handleCloseDetails,
3935
4001
  [DetailTab]: handleDetailTab,
3936
4002
  [EventCategoryFilter]: handleEventCategoryFilter,
3937
4003
  [Filter]: handleFilter,
@@ -4409,16 +4475,22 @@ const handlePreviewTextScrollBarPointerDown = (state, eventY) => {
4409
4475
  };
4410
4476
 
4411
4477
  const handlePreviewTextScrollBarPointerMove = (state, eventY) => {
4412
- if (!state.previewTextScrollBarPointerActive) {
4478
+ const {
4479
+ previewTextDeltaY,
4480
+ previewTextScrollBarHandleOffset,
4481
+ previewTextScrollBarPointerActive,
4482
+ selectedEvent
4483
+ } = state;
4484
+ if (!previewTextScrollBarPointerActive) {
4413
4485
  return state;
4414
4486
  }
4415
4487
  const viewportHeight = getPreviewTextViewportHeight(state);
4416
- const virtualization = getPreviewVirtualizationState(state.selectedEvent, viewportHeight, state.previewTextDeltaY);
4488
+ const virtualization = getPreviewVirtualizationState(selectedEvent, viewportHeight, previewTextDeltaY);
4417
4489
  if (viewportHeight === 0 || virtualization.scrollBarHeight === 0) {
4418
4490
  return state;
4419
4491
  }
4420
4492
  const relativeY = eventY - getPreviewTextBodyY(state);
4421
- const nextHandleTop = Math.max(0, Math.min(viewportHeight - virtualization.scrollBarHeight, relativeY - state.previewTextScrollBarHandleOffset));
4493
+ const nextHandleTop = Math.max(0, Math.min(viewportHeight - virtualization.scrollBarHeight, relativeY - previewTextScrollBarHandleOffset));
4422
4494
  const percent = nextHandleTop / Math.max(1, viewportHeight - virtualization.scrollBarHeight);
4423
4495
  const nextState = setPreviewTextDeltaY(state, percent * virtualization.maxDeltaY);
4424
4496
  return {
@@ -4439,7 +4511,10 @@ const handlePreviewTextScrollBarPointerUp = state => {
4439
4511
  };
4440
4512
 
4441
4513
  const handlePreviewTextWheel = (state, deltaY) => {
4442
- return setPreviewTextDeltaY(state, state.previewTextDeltaY + deltaY);
4514
+ const {
4515
+ previewTextDeltaY
4516
+ } = state;
4517
+ return setPreviewTextDeltaY(state, previewTextDeltaY + deltaY);
4443
4518
  };
4444
4519
 
4445
4520
  const handleRootContextMenu = state => {
@@ -4552,6 +4627,20 @@ const handleTableRowCopy = async (state, eventIndex) => {
4552
4627
  return state;
4553
4628
  };
4554
4629
 
4630
+ const toDataUri = text => {
4631
+ return `data:application/json,${encodeURIComponent(text)}`;
4632
+ };
4633
+ const handleTableRowOpenInNewTab = async (state, eventIndex) => {
4634
+ const currentEvents = getCurrentEvents$1(state);
4635
+ const event = currentEvents[eventIndex];
4636
+ if (!event) {
4637
+ return state;
4638
+ }
4639
+ const text = JSON.stringify(event, null, 2);
4640
+ await openUri(toDataUri(text));
4641
+ return state;
4642
+ };
4643
+
4555
4644
  const getHandleOffsetAndPercent = (tableBodyHeight, scrollBarHeight, relativeY) => {
4556
4645
  const halfScrollBarHeight = scrollBarHeight / 2;
4557
4646
  if (relativeY <= halfScrollBarHeight) {
@@ -4939,13 +5028,13 @@ const getLineCount = state => {
4939
5028
  return 0;
4940
5029
  }
4941
5030
  const selectedDetailTab = getSelectedDetailTab(state.detailTabs);
4942
- if (selectedDetailTab === Timing || selectedDetailTab === Tokens) {
5031
+ if (selectedDetailTab === Timing$1 || selectedDetailTab === Tokens$1) {
4943
5032
  return 0;
4944
5033
  }
4945
- if (selectedDetailTab === Preview) {
5034
+ if (selectedDetailTab === Preview$1) {
4946
5035
  return getPreviewLineCount(selectedEvent);
4947
5036
  }
4948
- if (selectedDetailTab === Payload) {
5037
+ if (selectedDetailTab === Payload$1) {
4949
5038
  return getJsonLineCount(getPayloadEvent(selectedEvent));
4950
5039
  }
4951
5040
  return getJsonLineCount(getResponseEvent(selectedEvent));
@@ -5705,6 +5794,7 @@ const getFilterInputDom = (filterValue, useDevtoolsLayout) => {
5705
5794
  };
5706
5795
  };
5707
5796
 
5797
+ const selectedClassName = mergeClassNames(ChatDebugViewQuickFilterPill, ChatDebugViewQuickFilterPillSelected);
5708
5798
  const getQuickFilterDom = categoryFilter => {
5709
5799
  const {
5710
5800
  isSelected,
@@ -5714,7 +5804,7 @@ const getQuickFilterDom = categoryFilter => {
5714
5804
  return [{
5715
5805
  ariaSelected: isSelected,
5716
5806
  childCount: 1,
5717
- className: mergeClassNames(ChatDebugViewQuickFilterPill, isSelected ? ChatDebugViewQuickFilterPillSelected : ''),
5807
+ className: isSelected ? selectedClassName : ChatDebugViewQuickFilterPill,
5718
5808
  name,
5719
5809
  onClick: HandleEventCategoryFilter,
5720
5810
  role: Option,
@@ -5738,10 +5828,10 @@ const refreshButtonDom = [{
5738
5828
  'aria-label': refreshEvents$1(),
5739
5829
  childCount: 1,
5740
5830
  className: ChatDebugViewRefreshButton,
5741
- name: Refresh,
5831
+ name: Refresh$1,
5742
5832
  onClick: HandleClickRefresh,
5743
5833
  type: Button$1,
5744
- value: Refresh
5834
+ value: Refresh$1
5745
5835
  }, text(refresh$1())];
5746
5836
  const getRefreshButtonDom = () => {
5747
5837
  return refreshButtonDom;
@@ -5764,6 +5854,19 @@ const getDebugViewTopDom = (filterValue, useDevtoolsLayout, categoryFilters) =>
5764
5854
  }, getFilterInputDom(filterValue, false), ...refreshButtonDom];
5765
5855
  };
5766
5856
 
5857
+ const createDevtoolsRows = (events, selectedEventIndex, startIndex = 0) => {
5858
+ return events.map((event, index) => {
5859
+ const actualIndex = startIndex + index;
5860
+ return {
5861
+ event,
5862
+ index: actualIndex,
5863
+ isErrorStatus: hasErrorStatus(event),
5864
+ isEven: actualIndex % 2 === 1,
5865
+ isSelected: selectedEventIndex === actualIndex
5866
+ };
5867
+ });
5868
+ };
5869
+
5767
5870
  const getNextSiblingIndex$2 = (nodes, index) => {
5768
5871
  let nextSiblingIndex = index + 1;
5769
5872
  const childCount = nodes[index]?.childCount || 0;
@@ -5803,7 +5906,7 @@ const detailsCloseButtonDom = [{
5803
5906
  'aria-label': closeDetails(),
5804
5907
  childCount: 1,
5805
5908
  className: ChatDebugViewDetailsClose,
5806
- name: CloseDetails,
5909
+ name: CloseDetails$1,
5807
5910
  onChange: HandleCloseDetails,
5808
5911
  onClick: HandleCloseDetails,
5809
5912
  type: Button$1,
@@ -5817,6 +5920,44 @@ const getDetailsCloseButtonDom = () => {
5817
5920
  return detailsCloseButtonDom;
5818
5921
  };
5819
5922
 
5923
+ const getDetailTabDom = detailTab => {
5924
+ const {
5925
+ isSelected
5926
+ } = detailTab;
5927
+ return [{
5928
+ 'aria-controls': getPanelId(detailTab.name),
5929
+ ariaSelected: isSelected,
5930
+ childCount: 1,
5931
+ className: mergeClassNames(PanelTab, isSelected ? PanelTabSelected : ''),
5932
+ name: detailTab.name,
5933
+ onChange: SelectDetailTab,
5934
+ onClick: SelectDetailTab,
5935
+ onFocus: HandleDetailTabsFocus,
5936
+ role: Tab,
5937
+ tabIndex: isSelected ? 0 : -1,
5938
+ type: Button$1
5939
+ }, text(detailTab.label)];
5940
+ };
5941
+
5942
+ const getTabNodes = detailTabs => {
5943
+ return [{
5944
+ 'aria-label': detailSections(),
5945
+ childCount: detailTabs.length,
5946
+ className: ChatDebugViewDetailsTabs,
5947
+ role: 'tablist',
5948
+ type: Div
5949
+ }, ...detailTabs.flatMap(getDetailTabDom)];
5950
+ };
5951
+
5952
+ const getDetailsTopVirtualDom = detailTabs => {
5953
+ return [{
5954
+ childCount: 2,
5955
+ className: ChatDebugViewDetailsTop,
5956
+ onContextMenu: HandleDetailsTopContextMenu,
5957
+ type: Div
5958
+ }, ...getDetailsCloseButtonDom(), ...getTabNodes(detailTabs)];
5959
+ };
5960
+
5820
5961
  const getNormalizedDetailTabs = (selectedEvent, detailTabs) => {
5821
5962
  if (selectedEvent === null) {
5822
5963
  return detailTabs;
@@ -6795,12 +6936,15 @@ const getTextNode = (value, showLineNumbers = true, cursor = null, tokenSegments
6795
6936
  return getEditorDom(lineData, showLineNumbers, cursor, showLineNumbers ? HandlePreviewTextPointerDown : undefined);
6796
6937
  };
6797
6938
 
6939
+ const getTextEvent = (previewEvent, selectedEvent, previewTextCursor, virtualization) => {
6940
+ const isInvalidImageMessage = previewEvent === ImageCouldNotBeLoaded;
6941
+ const isChatMessageUpdatedPreview = !!selectedEvent && isChatMessageUpdatedEvent(selectedEvent);
6942
+ const showLineNumbers = !isInvalidImageMessage && !isChatMessageUpdatedPreview;
6943
+ return getTextNode(previewEvent, showLineNumbers, showLineNumbers ? previewTextCursor ?? null : null, undefined, virtualization);
6944
+ };
6798
6945
  const getPreviewEventNodes = (previewEvent, selectedEvent, previewTextCursor, virtualization) => {
6799
6946
  if (typeof previewEvent === 'string') {
6800
- const isInvalidImageMessage = previewEvent === ImageCouldNotBeLoaded;
6801
- const isChatMessageUpdatedPreview = !!selectedEvent && isChatMessageUpdatedEvent(selectedEvent);
6802
- const showLineNumbers = !isInvalidImageMessage && !isChatMessageUpdatedPreview;
6803
- return getTextNode(previewEvent, showLineNumbers, showLineNumbers ? previewTextCursor ?? null : null, undefined, virtualization);
6947
+ return getTextEvent(previewEvent, selectedEvent, previewTextCursor, virtualization);
6804
6948
  }
6805
6949
  if (isWriteFilePreview(previewEvent)) {
6806
6950
  const language = getLanguageFromFileExtension(previewEvent.uri);
@@ -6993,53 +7137,24 @@ const getTokenUsageContentNodes = (responseEventNodes, selectedEvent) => {
6993
7137
  };
6994
7138
 
6995
7139
  const getSelectedContentNodes = (safeSelectedDetailTab, previewEventNodes, payloadEventNodes, responseEventNodes, selectedEvent, previewTextCursorRowIndex, previewTextCursorColumnIndex, previewVirtualization) => {
6996
- if (safeSelectedDetailTab === Tokens) {
7140
+ if (safeSelectedDetailTab === Tokens$1) {
6997
7141
  return getTokenUsageContentNodes(responseEventNodes, selectedEvent);
6998
7142
  }
6999
- if (safeSelectedDetailTab === Timing) {
7143
+ if (safeSelectedDetailTab === Timing$1) {
7000
7144
  return getTimingContentNodes(responseEventNodes, selectedEvent);
7001
7145
  }
7002
- if (safeSelectedDetailTab === Preview) {
7146
+ if (safeSelectedDetailTab === Preview$1) {
7003
7147
  return getPreviewContentNodes(previewEventNodes, selectedEvent, previewTextCursorRowIndex, previewTextCursorColumnIndex, previewVirtualization);
7004
7148
  }
7005
- if (safeSelectedDetailTab === Payload) {
7149
+ if (safeSelectedDetailTab === Payload$1) {
7006
7150
  return getPayloadContentNodes(payloadEventNodes, selectedEvent);
7007
7151
  }
7008
- if (safeSelectedDetailTab === Headers) {
7152
+ if (safeSelectedDetailTab === Headers$1) {
7009
7153
  return getHeadersContentNodes(responseEventNodes, selectedEvent);
7010
7154
  }
7011
7155
  return getResponseContentNodes(responseEventNodes, selectedEvent);
7012
7156
  };
7013
7157
 
7014
- const getDetailTabDom = detailTab => {
7015
- const {
7016
- isSelected
7017
- } = detailTab;
7018
- return [{
7019
- 'aria-controls': getPanelId(detailTab.name),
7020
- ariaSelected: isSelected,
7021
- childCount: 1,
7022
- className: mergeClassNames(PanelTab, isSelected ? PanelTabSelected : ''),
7023
- name: detailTab.name,
7024
- onChange: SelectDetailTab,
7025
- onClick: SelectDetailTab,
7026
- onFocus: HandleDetailTabsFocus,
7027
- role: Tab,
7028
- tabIndex: isSelected ? 0 : -1,
7029
- type: Button$1
7030
- }, text(detailTab.label)];
7031
- };
7032
-
7033
- const getTabNodes = detailTabs => {
7034
- return [{
7035
- 'aria-label': detailSections(),
7036
- childCount: detailTabs.length,
7037
- className: ChatDebugViewDetailsTabs,
7038
- role: 'tablist',
7039
- type: Div
7040
- }, ...detailTabs.flatMap(getDetailTabDom)];
7041
- };
7042
-
7043
7158
  const getDetailsDom = (previewEventNodes, payloadEventNodes = previewEventNodes, responseEventNodes = payloadEventNodes, selectedEvent = null, detailTabs = createDetailTabs(), previewTextCursorRowIndex = null, previewTextCursorColumnIndex = null, previewVirtualization) => {
7044
7159
  if (previewEventNodes.length === 0 && payloadEventNodes.length === 0 && responseEventNodes.length === 0) {
7045
7160
  return [];
@@ -7052,12 +7167,7 @@ const getDetailsDom = (previewEventNodes, payloadEventNodes = previewEventNodes,
7052
7167
  childCount: 2,
7053
7168
  className: ChatDebugViewDetails,
7054
7169
  type: Section
7055
- }, {
7056
- childCount: 2,
7057
- className: ChatDebugViewDetailsTop,
7058
- onContextMenu: HandleDetailsTopContextMenu,
7059
- type: Div
7060
- }, ...getDetailsCloseButtonDom(), ...getTabNodes(normalizedDetailTabs), ...getDetailContentDom(selectedDetailTab, safeSelectedDetailTab, contentNodes)];
7170
+ }, ...getDetailsTopVirtualDom(normalizedDetailTabs), ...getDetailContentDom(selectedDetailTab, safeSelectedDetailTab, contentNodes)];
7061
7171
  };
7062
7172
 
7063
7173
  const getMethods = new Set(['list_dir', 'list_files', 'read_file']);
@@ -7080,52 +7190,51 @@ const getEventTableMethodLabel = event => {
7080
7190
  return '';
7081
7191
  };
7082
7192
 
7193
+ const getTableCellDom = (column, event, isErrorStatus) => {
7194
+ switch (column) {
7195
+ case Duration:
7196
+ return [{
7197
+ childCount: 1,
7198
+ className: mergeClassNames(TableCell, ChatDebugViewCellDuration),
7199
+ type: Td
7200
+ }, text(getEventTableDurationText(event))];
7201
+ case Method:
7202
+ return [{
7203
+ childCount: 1,
7204
+ className: TableCell,
7205
+ type: Td
7206
+ }, text(getEventTableMethodLabel(event))];
7207
+ case Status$1:
7208
+ return [{
7209
+ childCount: 1,
7210
+ className: mergeClassNames(TableCell, isErrorStatus ? ChatDebugViewCellStatusError : ''),
7211
+ type: Td
7212
+ }, text(getStatusText(event))];
7213
+ case Type:
7214
+ return [{
7215
+ childCount: 1,
7216
+ className: TableCell,
7217
+ type: Td
7218
+ }, text(getEventTableTypeLabel(event))];
7219
+ default:
7220
+ return [];
7221
+ }
7222
+ };
7083
7223
  const getRowCellNodes = (event, isErrorStatus, visibleTableColumns) => {
7084
7224
  const orderedVisibleTableColumns = getOrderedVisibleTableColumns(visibleTableColumns);
7085
- return orderedVisibleTableColumns.flatMap((column, index) => {
7086
- switch (column) {
7087
- case Duration:
7088
- return [{
7089
- childCount: 1,
7090
- className: mergeClassNames(TableCell, ChatDebugViewCellDuration),
7091
- type: Td
7092
- }, text(getEventTableDurationText(event))];
7093
- case Method:
7094
- return [{
7095
- childCount: 1,
7096
- className: TableCell,
7097
- type: Td
7098
- }, text(getEventTableMethodLabel(event))];
7099
- case Status$1:
7100
- return [{
7101
- childCount: 1,
7102
- className: mergeClassNames(TableCell, isErrorStatus ? ChatDebugViewCellStatusError : ''),
7103
- type: Td
7104
- }, text(getStatusText(event))];
7105
- case Type:
7106
- return [{
7107
- childCount: 1,
7108
- className: TableCell,
7109
- type: Td
7110
- }, text(getEventTableTypeLabel(event))];
7111
- default:
7112
- return [];
7113
- }
7225
+ return orderedVisibleTableColumns.flatMap(column => {
7226
+ return getTableCellDom(column, event, isErrorStatus);
7114
7227
  });
7115
7228
  };
7116
7229
 
7117
- const getDevtoolsRows = (events, selectedEventIndex, visibleTableColumns = defaultVisibleTableColumns, startIndex = 0) => {
7118
- return events.flatMap((event, i) => {
7119
- const actualIndex = startIndex + i;
7120
- const isEvenRow = actualIndex % 2 === 1;
7121
- const rowClassName = isEvenRow ? TableRowEven : TableRowOdd;
7122
- const isSelected = selectedEventIndex === actualIndex;
7123
- const isErrorStatus = hasErrorStatus(event);
7124
- const rowCellNodes = getRowCellNodes(event, isErrorStatus, visibleTableColumns);
7230
+ const getDevtoolsRows = (rows, visibleTableColumns = defaultVisibleTableColumns) => {
7231
+ return rows.flatMap(row => {
7232
+ const rowClassName = row.isEven ? TableRowEven : TableRowOdd;
7233
+ const rowCellNodes = getRowCellNodes(row.event, row.isErrorStatus, visibleTableColumns);
7125
7234
  return [{
7126
7235
  childCount: visibleTableColumns.length,
7127
- className: mergeClassNames(TableRow, rowClassName, isSelected ? TableRowSelected : ''),
7128
- 'data-index': `${actualIndex}`,
7236
+ className: mergeClassNames(TableRow, rowClassName, row.isSelected ? TableRowSelected : ''),
7237
+ 'data-index': `${row.index}`,
7129
7238
  type: Tr
7130
7239
  }, ...rowCellNodes];
7131
7240
  });
@@ -7448,6 +7557,20 @@ const formatPercent = value => {
7448
7557
  return `${Number(value.toFixed(3))}%`;
7449
7558
  };
7450
7559
 
7560
+ const startHandle = {
7561
+ childCount: 0,
7562
+ className: mergeClassNames(ChatDebugViewTimelineSelectionHandle, ChatDebugViewTimelineSelectionHandleStart, ChatDebugViewTimelineSelectionMarker, ChatDebugViewTimelineSelectionMarkerStart),
7563
+ name: Start,
7564
+ role: None,
7565
+ type: Button$1
7566
+ };
7567
+ const endHandle = {
7568
+ childCount: 0,
7569
+ className: mergeClassNames(ChatDebugViewTimelineSelectionHandle, ChatDebugViewTimelineSelectionHandleEnd, ChatDebugViewTimelineSelectionMarker, ChatDebugViewTimelineSelectionMarkerEnd),
7570
+ name: End,
7571
+ role: None,
7572
+ type: Button$1
7573
+ };
7451
7574
  const getSelectionNodesDom = (hasSelection, selectionStartPercent, selectionEndPercent) => {
7452
7575
  if (!hasSelection || selectionStartPercent === null || selectionEndPercent === null) {
7453
7576
  return [];
@@ -7457,19 +7580,7 @@ const getSelectionNodesDom = (hasSelection, selectionStartPercent, selectionEndP
7457
7580
  className: ChatDebugViewTimelineSelectionRange,
7458
7581
  style: `left:${formatPercent(selectionStartPercent)};width:${formatPercent(selectionEndPercent - selectionStartPercent)};`,
7459
7582
  type: Div
7460
- }, {
7461
- childCount: 0,
7462
- className: mergeClassNames(ChatDebugViewTimelineSelectionHandle, ChatDebugViewTimelineSelectionHandleStart, ChatDebugViewTimelineSelectionMarker, ChatDebugViewTimelineSelectionMarkerStart),
7463
- name: Start,
7464
- role: None,
7465
- type: Button$1
7466
- }, {
7467
- childCount: 0,
7468
- className: mergeClassNames(ChatDebugViewTimelineSelectionHandle, ChatDebugViewTimelineSelectionHandleEnd, ChatDebugViewTimelineSelectionMarker, ChatDebugViewTimelineSelectionMarkerEnd),
7469
- name: End,
7470
- role: None,
7471
- type: Button$1
7472
- }];
7583
+ }, startHandle, endHandle];
7473
7584
  };
7474
7585
 
7475
7586
  const getTimelineBadgeValues = durationSeconds => {
@@ -7558,7 +7669,8 @@ const getTimelineDom = (timelineInfo, hoverPercent = null) => {
7558
7669
 
7559
7670
  const getDevtoolsDom = (events, selectedEvent, selectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage = noEventsFound(), timelineSelectionActive = false, timelineSelectionAnchorSeconds = '', timelineSelectionFocusSeconds = '', detailTabs = createDetailTabs(), visibleTableColumns = defaultVisibleTableColumns, tableColumns = createTableColumns(), timelineInfo, timelineHoverPercent = null, focus = 0, previewTextCursorRowIndex = null, previewTextCursorColumnIndex = null, previewTextDeltaY = 0, previewTextViewportHeight = 0, minLineY = 0, maxLineY = events.length) => {
7560
7671
  const visibleEvents = events.slice(minLineY, maxLineY);
7561
- const rowNodes = getDevtoolsRows(visibleEvents, selectedEventIndex, visibleTableColumns, minLineY);
7672
+ const rows = createDevtoolsRows(visibleEvents, selectedEventIndex, minLineY);
7673
+ const rowNodes = getDevtoolsRows(rows, visibleTableColumns);
7562
7674
  const effectiveRange = getEffectiveTimelineRange(timelineStartSeconds, timelineEndSeconds, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds);
7563
7675
  const resolvedTimelineInfo = timelineInfo || getTimelineInfo(timelineEvents, effectiveRange.startSeconds, effectiveRange.endSeconds);
7564
7676
  const timelineNodes = getTimelineDom(resolvedTimelineInfo, timelineHoverPercent);
@@ -7629,7 +7741,7 @@ const getTopLevelChildCount = nodes => {
7629
7741
  return count;
7630
7742
  };
7631
7743
  const getEventCategoryFilterDescription = eventCategoryFilters => {
7632
- if (eventCategoryFilters.length === 0 || eventCategoryFilters.includes(All)) {
7744
+ if (eventCategoryFilters.length === 0 || eventCategoryFilters.includes(All$1)) {
7633
7745
  return '';
7634
7746
  }
7635
7747
  return eventCategoryFilters.map(eventCategoryFilter => getEventCategoryFilterLabel(eventCategoryFilter).toLowerCase()).join(', ');
@@ -7654,7 +7766,7 @@ const getChatDebugViewDom = (errorMessage, filterValue, eventCategoryFilters, ca
7654
7766
  const hasFilterValue = filterDescriptionParts.length > 0;
7655
7767
  const filterDescription = filterDescriptionParts.join(' ');
7656
7768
  const noFilteredEventsMessage = noEventsFoundMatching(filterDescription);
7657
- const useNoToolCallEventsMessage = eventCategoryFilters.length === 1 && eventCategoryFilters[0] === Tools && !trimmedFilterValue && !hasTimelineFilter;
7769
+ const useNoToolCallEventsMessage = eventCategoryFilters.length === 1 && eventCategoryFilters[0] === Tools$1 && !trimmedFilterValue && !hasTimelineFilter;
7658
7770
  const emptyMessage = getEmptyMessage(events.length, hasFilterValue, useNoToolCallEventsMessage, noFilteredEventsMessage);
7659
7771
  const safeSelectedEventIndex = selectedEventIndex === null || selectedEventIndex < 0 || selectedEventIndex >= events.length ? null : selectedEventIndex;
7660
7772
  if (useDevtoolsLayout) {
@@ -8093,6 +8205,7 @@ const commandMap = {
8093
8205
  'ChatDebug.handleTableResizerPointerMove': wrapCommand(handleTableResizerPointerMove),
8094
8206
  'ChatDebug.handleTableResizerPointerUp': wrapCommand(handleTableResizerPointerUp),
8095
8207
  'ChatDebug.handleTableRowCopy': wrapCommand(handleTableRowCopy),
8208
+ 'ChatDebug.handleTableRowOpenInNewTab': wrapCommand(handleTableRowOpenInNewTab),
8096
8209
  'ChatDebug.handleTableScrollBarPointerDown': wrapCommand(handleTableScrollBarPointerDown),
8097
8210
  'ChatDebug.handleTableScrollBarPointerMove': wrapCommand(handleTableScrollBarPointerMove),
8098
8211
  'ChatDebug.handleTableScrollBarPointerUp': wrapCommand(handleTableScrollBarPointerUp),