@lvce-editor/chat-debug-view 5.2.0 → 5.4.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.
@@ -1171,465 +1171,127 @@ const diff2 = uid => {
1171
1171
  return diff(oldState, newState);
1172
1172
  };
1173
1173
 
1174
+ const handleCloseDetails = state => {
1175
+ return {
1176
+ ...state,
1177
+ selectedEvent: null,
1178
+ selectedEventId: null,
1179
+ selectedEventIndex: null
1180
+ };
1181
+ };
1182
+
1174
1183
  const handleDetailsContextMenu = state => {
1175
1184
  return state;
1176
1185
  };
1177
1186
 
1178
- // cspell:ignore IDBP
1187
+ const handleDetailTab = (state, value) => {
1188
+ if (!isDetailTab(value)) {
1189
+ return state;
1190
+ }
1191
+ return {
1192
+ ...state,
1193
+ selectedDetailTab: value
1194
+ };
1195
+ };
1196
+
1197
+ const hasMatchingToolName$1 = (startedEvent, finishedEvent) => {
1198
+ if (typeof startedEvent.toolName === 'string' && typeof finishedEvent.toolName === 'string') {
1199
+ return startedEvent.toolName === finishedEvent.toolName;
1200
+ }
1201
+ return true;
1202
+ };
1203
+
1204
+ const isMatchingToolExecutionPair = (startedEvent, finishedEvent) => {
1205
+ return startedEvent.sessionId === finishedEvent.sessionId && hasMatchingToolName$1(startedEvent, finishedEvent);
1206
+ };
1179
1207
 
1180
1208
  const startedEventType$1 = 'tool-execution-started';
1181
1209
  const finishedEventType$1 = 'tool-execution-finished';
1182
- const getRawEventBySessionIdAndEventId = async (store, sessionId, sessionIdIndexName, eventId) => {
1183
- if (eventId < 1) {
1184
- return undefined;
1185
- }
1186
- if (store.indexNames.contains(sessionIdIndexName)) {
1187
- const index = store.index(sessionIdIndexName);
1188
- const keys = await index.getAllKeys(sessionId, eventId);
1189
- if (keys.length < eventId) {
1190
- return undefined;
1191
- }
1192
- const key = keys.at(-1);
1193
- if (key === undefined) {
1194
- return undefined;
1195
- }
1196
- const event = await store.get(key);
1197
- return event;
1198
- }
1199
- const all = await store.getAll();
1200
- const events = all.filter(event => event.sessionId === sessionId);
1201
- return events[eventId - 1];
1210
+ const mergedEventType = 'tool-execution';
1211
+
1212
+ const isToolExecutionFinishedEvent = event => {
1213
+ return event.type === finishedEventType$1;
1202
1214
  };
1215
+
1216
+ const isToolExecutionStartedEvent = event => {
1217
+ return event.type === startedEventType$1;
1218
+ };
1219
+
1203
1220
  const getTimestamp$1 = value => {
1204
1221
  return typeof value === 'string' || typeof value === 'number' ? value : undefined;
1205
1222
  };
1206
- const hasMatchingToolName$1 = (startedEvent, finishedEvent) => {
1207
- if (typeof startedEvent.toolName === 'string' && typeof finishedEvent.toolName === 'string') {
1208
- return startedEvent.toolName === finishedEvent.toolName;
1223
+
1224
+ const getEndedTimestamp = event => {
1225
+ return getTimestamp$1(event.ended) ?? getTimestamp$1(event.endTime) ?? getTimestamp$1(event.endTimestamp) ?? getTimestamp$1(event.timestamp);
1226
+ };
1227
+
1228
+ const eventStableIds = new WeakMap();
1229
+ const eventStableIdState = {
1230
+ nextStableEventId: 1
1231
+ };
1232
+
1233
+ const getOrCreateStableEventId = event => {
1234
+ const existingStableEventId = eventStableIds.get(event);
1235
+ if (existingStableEventId) {
1236
+ return existingStableEventId;
1209
1237
  }
1210
- return true;
1238
+ const stableEventId = `event-${eventStableIdState.nextStableEventId++}`;
1239
+ eventStableIds.set(event, stableEventId);
1240
+ return stableEventId;
1211
1241
  };
1212
- const mergeToolExecutionEvents$1 = (startedEvent, finishedEvent, eventId) => {
1213
- const ended = getTimestamp$1(finishedEvent.ended) ?? getTimestamp$1(finishedEvent.endTime) ?? getTimestamp$1(finishedEvent.timestamp);
1214
- const started = getTimestamp$1(startedEvent.started) ?? getTimestamp$1(startedEvent.startTime) ?? getTimestamp$1(startedEvent.timestamp);
1215
- return {
1242
+
1243
+ const getStartedTimestamp = event => {
1244
+ return getTimestamp$1(event.started) ?? getTimestamp$1(event.startTime) ?? getTimestamp$1(event.startTimestamp) ?? getTimestamp$1(event.timestamp);
1245
+ };
1246
+
1247
+ const setStableEventId = (event, stableEventId) => {
1248
+ eventStableIds.set(event, stableEventId);
1249
+ };
1250
+
1251
+ const mergeToolExecutionEvents$1 = (startedEvent, finishedEvent) => {
1252
+ const ended = getEndedTimestamp(finishedEvent);
1253
+ const {
1254
+ eventId
1255
+ } = startedEvent;
1256
+ const started = getStartedTimestamp(startedEvent);
1257
+ const mergedEvent = {
1216
1258
  ...startedEvent,
1217
1259
  ...finishedEvent,
1218
1260
  ...(ended === undefined ? {} : {
1219
1261
  ended
1220
1262
  }),
1221
- eventId,
1263
+ ...(eventId === undefined ? {} : {
1264
+ eventId
1265
+ }),
1222
1266
  ...(started === undefined ? {} : {
1223
1267
  started
1224
1268
  }),
1225
- type: 'tool-execution'
1269
+ type: mergedEventType
1226
1270
  };
1271
+ const stableEventId = `${getOrCreateStableEventId(startedEvent)}:${getOrCreateStableEventId(finishedEvent)}`;
1272
+ setStableEventId(mergedEvent, stableEventId);
1273
+ return mergedEvent;
1227
1274
  };
1228
- const getEventDetailsBySessionIdAndEventId = async (store, sessionId, sessionIdIndexName, eventId, summaryType) => {
1229
- const event = await getRawEventBySessionIdAndEventId(store, sessionId, sessionIdIndexName, eventId);
1230
- if (!event) {
1231
- return undefined;
1232
- }
1233
- if (summaryType !== 'tool-execution') {
1234
- return {
1235
- ...event,
1236
- eventId
1237
- };
1238
- }
1239
- if (event.type !== startedEventType$1) {
1240
- return {
1241
- ...event,
1242
- eventId
1243
- };
1244
- }
1245
- const nextEvent = await getRawEventBySessionIdAndEventId(store, sessionId, sessionIdIndexName, eventId + 1);
1246
- if (!nextEvent || nextEvent.type !== finishedEventType$1 || nextEvent.sessionId !== sessionId || !hasMatchingToolName$1(event, nextEvent)) {
1247
- return {
1248
- ...event,
1249
- eventId
1250
- };
1251
- }
1252
- return mergeToolExecutionEvents$1(event, nextEvent, eventId);
1275
+
1276
+ const getStableEventId = event => {
1277
+ return getOrCreateStableEventId(event);
1253
1278
  };
1254
1279
 
1255
- const instanceOfAny = (object, constructors) => constructors.some(c => object instanceof c);
1256
- let idbProxyableTypes;
1257
- let cursorAdvanceMethods;
1258
- // This is a function to prevent it throwing up in node environments.
1259
- function getIdbProxyableTypes() {
1260
- return idbProxyableTypes || (idbProxyableTypes = [IDBDatabase, IDBObjectStore, IDBIndex, IDBCursor, IDBTransaction]);
1261
- }
1262
- // This is a function to prevent it throwing up in node environments.
1263
- function getCursorAdvanceMethods() {
1264
- return cursorAdvanceMethods || (cursorAdvanceMethods = [IDBCursor.prototype.advance, IDBCursor.prototype.continue, IDBCursor.prototype.continuePrimaryKey]);
1265
- }
1266
- const transactionDoneMap = new WeakMap();
1267
- const transformCache = new WeakMap();
1268
- const reverseTransformCache = new WeakMap();
1269
- function promisifyRequest(request) {
1270
- const promise = new Promise((resolve, reject) => {
1271
- const unlisten = () => {
1272
- request.removeEventListener('success', success);
1273
- request.removeEventListener('error', error);
1274
- };
1275
- const success = () => {
1276
- resolve(wrap(request.result));
1277
- unlisten();
1278
- };
1279
- const error = () => {
1280
- reject(request.error);
1281
- unlisten();
1282
- };
1283
- request.addEventListener('success', success);
1284
- request.addEventListener('error', error);
1285
- });
1286
- // This mapping exists in reverseTransformCache but doesn't exist in transformCache. This
1287
- // is because we create many promises from a single IDBRequest.
1288
- reverseTransformCache.set(promise, request);
1289
- return promise;
1290
- }
1291
- function cacheDonePromiseForTransaction(tx) {
1292
- // Early bail if we've already created a done promise for this transaction.
1293
- if (transactionDoneMap.has(tx)) return;
1294
- const done = new Promise((resolve, reject) => {
1295
- const unlisten = () => {
1296
- tx.removeEventListener('complete', complete);
1297
- tx.removeEventListener('error', error);
1298
- tx.removeEventListener('abort', error);
1299
- };
1300
- const complete = () => {
1301
- resolve();
1302
- unlisten();
1303
- };
1304
- const error = () => {
1305
- reject(tx.error || new DOMException('AbortError', 'AbortError'));
1306
- unlisten();
1307
- };
1308
- tx.addEventListener('complete', complete);
1309
- tx.addEventListener('error', error);
1310
- tx.addEventListener('abort', error);
1311
- });
1312
- // Cache it for later retrieval.
1313
- transactionDoneMap.set(tx, done);
1314
- }
1315
- let idbProxyTraps = {
1316
- get(target, prop, receiver) {
1317
- if (target instanceof IDBTransaction) {
1318
- // Special handling for transaction.done.
1319
- if (prop === 'done') return transactionDoneMap.get(target);
1320
- // Make tx.store return the only store in the transaction, or undefined if there are many.
1321
- if (prop === 'store') {
1322
- return receiver.objectStoreNames[1] ? undefined : receiver.objectStore(receiver.objectStoreNames[0]);
1280
+ const collapseToolExecutionEvents = events => {
1281
+ const collapsedEvents = [];
1282
+ for (let i = 0; i < events.length; i++) {
1283
+ const event = events[i];
1284
+ if (isToolExecutionStartedEvent(event)) {
1285
+ const nextEvent = events[i + 1];
1286
+ if (nextEvent && isToolExecutionFinishedEvent(nextEvent) && isMatchingToolExecutionPair(event, nextEvent)) {
1287
+ collapsedEvents.push(mergeToolExecutionEvents$1(event, nextEvent));
1288
+ i++;
1289
+ continue;
1323
1290
  }
1324
1291
  }
1325
- // Else transform whatever we get back.
1326
- return wrap(target[prop]);
1327
- },
1328
- set(target, prop, value) {
1329
- target[prop] = value;
1330
- return true;
1331
- },
1332
- has(target, prop) {
1333
- if (target instanceof IDBTransaction && (prop === 'done' || prop === 'store')) {
1334
- return true;
1335
- }
1336
- return prop in target;
1292
+ collapsedEvents.push(event);
1337
1293
  }
1338
- };
1339
- function replaceTraps(callback) {
1340
- idbProxyTraps = callback(idbProxyTraps);
1341
- }
1342
- function wrapFunction(func) {
1343
- // Due to expected object equality (which is enforced by the caching in `wrap`), we
1344
- // only create one new func per func.
1345
- // Cursor methods are special, as the behaviour is a little more different to standard IDB. In
1346
- // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the
1347
- // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense
1348
- // with real promises, so each advance methods returns a new promise for the cursor object, or
1349
- // undefined if the end of the cursor has been reached.
1350
- if (getCursorAdvanceMethods().includes(func)) {
1351
- return function (...args) {
1352
- // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
1353
- // the original object.
1354
- func.apply(unwrap(this), args);
1355
- return wrap(this.request);
1356
- };
1357
- }
1358
- return function (...args) {
1359
- // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
1360
- // the original object.
1361
- return wrap(func.apply(unwrap(this), args));
1362
- };
1363
- }
1364
- function transformCachableValue(value) {
1365
- if (typeof value === 'function') return wrapFunction(value);
1366
- // This doesn't return, it just creates a 'done' promise for the transaction,
1367
- // which is later returned for transaction.done (see idbObjectHandler).
1368
- if (value instanceof IDBTransaction) cacheDonePromiseForTransaction(value);
1369
- if (instanceOfAny(value, getIdbProxyableTypes())) return new Proxy(value, idbProxyTraps);
1370
- // Return the same value back if we're not going to transform it.
1371
- return value;
1372
- }
1373
- function wrap(value) {
1374
- // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because
1375
- // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.
1376
- if (value instanceof IDBRequest) return promisifyRequest(value);
1377
- // If we've already transformed this value before, reuse the transformed value.
1378
- // This is faster, but it also provides object equality.
1379
- if (transformCache.has(value)) return transformCache.get(value);
1380
- const newValue = transformCachableValue(value);
1381
- // Not all types are transformed.
1382
- // These may be primitive types, so they can't be WeakMap keys.
1383
- if (newValue !== value) {
1384
- transformCache.set(value, newValue);
1385
- reverseTransformCache.set(newValue, value);
1386
- }
1387
- return newValue;
1388
- }
1389
- const unwrap = value => reverseTransformCache.get(value);
1390
-
1391
- /**
1392
- * Open a database.
1393
- *
1394
- * @param name Name of the database.
1395
- * @param version Schema version.
1396
- * @param callbacks Additional callbacks.
1397
- */
1398
- function openDB(name, version, {
1399
- blocked,
1400
- upgrade,
1401
- blocking,
1402
- terminated
1403
- } = {}) {
1404
- const request = indexedDB.open(name, version);
1405
- const openPromise = wrap(request);
1406
- if (upgrade) {
1407
- request.addEventListener('upgradeneeded', event => {
1408
- upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction), event);
1409
- });
1410
- }
1411
- if (blocked) {
1412
- request.addEventListener('blocked', event => blocked(
1413
- // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405
1414
- event.oldVersion, event.newVersion, event));
1415
- }
1416
- openPromise.then(db => {
1417
- if (terminated) db.addEventListener('close', () => terminated());
1418
- if (blocking) {
1419
- db.addEventListener('versionchange', event => blocking(event.oldVersion, event.newVersion, event));
1420
- }
1421
- }).catch(() => {});
1422
- return openPromise;
1423
- }
1424
- const readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];
1425
- const writeMethods = ['put', 'add', 'delete', 'clear'];
1426
- const cachedMethods = new Map();
1427
- function getMethod(target, prop) {
1428
- if (!(target instanceof IDBDatabase && !(prop in target) && typeof prop === 'string')) {
1429
- return;
1430
- }
1431
- if (cachedMethods.get(prop)) return cachedMethods.get(prop);
1432
- const targetFuncName = prop.replace(/FromIndex$/, '');
1433
- const useIndex = prop !== targetFuncName;
1434
- const isWrite = writeMethods.includes(targetFuncName);
1435
- if (
1436
- // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.
1437
- !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) || !(isWrite || readMethods.includes(targetFuncName))) {
1438
- return;
1439
- }
1440
- const method = async function (storeName, ...args) {
1441
- // isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(
1442
- const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');
1443
- let target = tx.store;
1444
- if (useIndex) target = target.index(args.shift());
1445
- // Must reject if op rejects.
1446
- // If it's a write operation, must reject if tx.done rejects.
1447
- // Must reject with op rejection first.
1448
- // Must resolve with op value.
1449
- // Must handle both promises (no unhandled rejections)
1450
- return (await Promise.all([target[targetFuncName](...args), isWrite && tx.done]))[0];
1451
- };
1452
- cachedMethods.set(prop, method);
1453
- return method;
1454
- }
1455
- replaceTraps(oldTraps => ({
1456
- ...oldTraps,
1457
- get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),
1458
- has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop)
1459
- }));
1460
- const advanceMethodProps = ['continue', 'continuePrimaryKey', 'advance'];
1461
- const methodMap = {};
1462
- const advanceResults = new WeakMap();
1463
- const ittrProxiedCursorToOriginalProxy = new WeakMap();
1464
- const cursorIteratorTraps = {
1465
- get(target, prop) {
1466
- if (!advanceMethodProps.includes(prop)) return target[prop];
1467
- let cachedFunc = methodMap[prop];
1468
- if (!cachedFunc) {
1469
- cachedFunc = methodMap[prop] = function (...args) {
1470
- advanceResults.set(this, ittrProxiedCursorToOriginalProxy.get(this)[prop](...args));
1471
- };
1472
- }
1473
- return cachedFunc;
1474
- }
1475
- };
1476
- async function* iterate(...args) {
1477
- // tslint:disable-next-line:no-this-assignment
1478
- let cursor = this;
1479
- if (!(cursor instanceof IDBCursor)) {
1480
- cursor = await cursor.openCursor(...args);
1481
- }
1482
- if (!cursor) return;
1483
- cursor = cursor;
1484
- const proxiedCursor = new Proxy(cursor, cursorIteratorTraps);
1485
- ittrProxiedCursorToOriginalProxy.set(proxiedCursor, cursor);
1486
- // Map this double-proxy back to the original, so other cursor methods work.
1487
- reverseTransformCache.set(proxiedCursor, unwrap(cursor));
1488
- while (cursor) {
1489
- yield proxiedCursor;
1490
- // If one of the advancing methods was not called, call continue().
1491
- cursor = await (advanceResults.get(proxiedCursor) || cursor.continue());
1492
- advanceResults.delete(proxiedCursor);
1493
- }
1494
- }
1495
- function isIteratorProp(target, prop) {
1496
- return prop === Symbol.asyncIterator && instanceOfAny(target, [IDBIndex, IDBObjectStore, IDBCursor]) || prop === 'iterate' && instanceOfAny(target, [IDBIndex, IDBObjectStore]);
1497
- }
1498
- replaceTraps(oldTraps => ({
1499
- ...oldTraps,
1500
- get(target, prop, receiver) {
1501
- if (isIteratorProp(target, prop)) return iterate;
1502
- return oldTraps.get(target, prop, receiver);
1503
- },
1504
- has(target, prop) {
1505
- return isIteratorProp(target, prop) || oldTraps.has(target, prop);
1506
- }
1507
- }));
1508
-
1509
- const openDatabaseDependencies = {
1510
- openDB: openDB
1511
- };
1512
- const openDatabase = async (databaseName, dataBaseVersion) => {
1513
- return openDatabaseDependencies.openDB(databaseName, dataBaseVersion);
1514
- };
1515
-
1516
- const loadSelectedEventDependencies = {
1517
- getEventDetailsBySessionIdAndEventId: getEventDetailsBySessionIdAndEventId,
1518
- openDatabase: openDatabase
1519
- };
1520
- const loadSelectedEvent = async (databaseName, dataBaseVersion, eventStoreName, sessionId, sessionIdIndexName, eventId, type) => {
1521
- const database = await loadSelectedEventDependencies.openDatabase(databaseName, dataBaseVersion);
1522
- try {
1523
- if (!database.objectStoreNames.contains(eventStoreName)) {
1524
- return null;
1525
- }
1526
- const transaction = database.transaction(eventStoreName, 'readonly');
1527
- const store = transaction.objectStore(eventStoreName);
1528
- const event = await loadSelectedEventDependencies.getEventDetailsBySessionIdAndEventId(store, sessionId, sessionIdIndexName, eventId, type);
1529
- return event ?? null;
1530
- } finally {
1531
- database.close();
1532
- }
1533
- };
1534
-
1535
- const hasMatchingToolName = (startedEvent, finishedEvent) => {
1536
- if (typeof startedEvent.toolName === 'string' && typeof finishedEvent.toolName === 'string') {
1537
- return startedEvent.toolName === finishedEvent.toolName;
1538
- }
1539
- return true;
1540
- };
1541
-
1542
- const isMatchingToolExecutionPair = (startedEvent, finishedEvent) => {
1543
- return startedEvent.sessionId === finishedEvent.sessionId && hasMatchingToolName(startedEvent, finishedEvent);
1544
- };
1545
-
1546
- const startedEventType = 'tool-execution-started';
1547
- const finishedEventType = 'tool-execution-finished';
1548
- const mergedEventType = 'tool-execution';
1549
-
1550
- const isToolExecutionFinishedEvent = event => {
1551
- return event.type === finishedEventType;
1552
- };
1553
-
1554
- const isToolExecutionStartedEvent = event => {
1555
- return event.type === startedEventType;
1556
- };
1557
-
1558
- const getTimestamp = value => {
1559
- return typeof value === 'string' || typeof value === 'number' ? value : undefined;
1560
- };
1561
-
1562
- const getEndedTimestamp = event => {
1563
- return getTimestamp(event.ended) ?? getTimestamp(event.endTime) ?? getTimestamp(event.endTimestamp) ?? getTimestamp(event.timestamp);
1564
- };
1565
-
1566
- const eventStableIds = new WeakMap();
1567
- const eventStableIdState = {
1568
- nextStableEventId: 1
1569
- };
1570
-
1571
- const getOrCreateStableEventId = event => {
1572
- const existingStableEventId = eventStableIds.get(event);
1573
- if (existingStableEventId) {
1574
- return existingStableEventId;
1575
- }
1576
- const stableEventId = `event-${eventStableIdState.nextStableEventId++}`;
1577
- eventStableIds.set(event, stableEventId);
1578
- return stableEventId;
1579
- };
1580
-
1581
- const getStartedTimestamp = event => {
1582
- return getTimestamp(event.started) ?? getTimestamp(event.startTime) ?? getTimestamp(event.startTimestamp) ?? getTimestamp(event.timestamp);
1583
- };
1584
-
1585
- const setStableEventId = (event, stableEventId) => {
1586
- eventStableIds.set(event, stableEventId);
1587
- };
1588
-
1589
- const mergeToolExecutionEvents = (startedEvent, finishedEvent) => {
1590
- const ended = getEndedTimestamp(finishedEvent);
1591
- const {
1592
- eventId
1593
- } = startedEvent;
1594
- const started = getStartedTimestamp(startedEvent);
1595
- const mergedEvent = {
1596
- ...startedEvent,
1597
- ...finishedEvent,
1598
- ...(ended === undefined ? {} : {
1599
- ended
1600
- }),
1601
- ...(eventId === undefined ? {} : {
1602
- eventId
1603
- }),
1604
- ...(started === undefined ? {} : {
1605
- started
1606
- }),
1607
- type: mergedEventType
1608
- };
1609
- const stableEventId = `${getOrCreateStableEventId(startedEvent)}:${getOrCreateStableEventId(finishedEvent)}`;
1610
- setStableEventId(mergedEvent, stableEventId);
1611
- return mergedEvent;
1612
- };
1613
-
1614
- const getStableEventId = event => {
1615
- return getOrCreateStableEventId(event);
1616
- };
1617
-
1618
- const collapseToolExecutionEvents = events => {
1619
- const collapsedEvents = [];
1620
- for (let i = 0; i < events.length; i++) {
1621
- const event = events[i];
1622
- if (isToolExecutionStartedEvent(event)) {
1623
- const nextEvent = events[i + 1];
1624
- if (nextEvent && isToolExecutionFinishedEvent(nextEvent) && isMatchingToolExecutionPair(event, nextEvent)) {
1625
- collapsedEvents.push(mergeToolExecutionEvents(event, nextEvent));
1626
- i++;
1627
- continue;
1628
- }
1629
- }
1630
- collapsedEvents.push(event);
1631
- }
1632
- return collapsedEvents;
1294
+ return collapsedEvents;
1633
1295
  };
1634
1296
 
1635
1297
  const getVisibleEvents = (events, showInputEvents, showResponsePartEvents, showEventStreamFinishedEvents) => {
@@ -1737,117 +1399,537 @@ const getEventsWithTime = events => {
1737
1399
  if (time === undefined) {
1738
1400
  return [];
1739
1401
  }
1740
- return [{
1741
- event,
1742
- time
1743
- }];
1744
- });
1745
- };
1746
- const getTimelineDurationSeconds = events => {
1747
- const eventsWithTime = getEventsWithTime(events);
1748
- if (eventsWithTime.length === 0) {
1749
- return 0;
1750
- }
1751
- const baseTime = eventsWithTime[0].time;
1752
- const lastTime = eventsWithTime.at(-1)?.time ?? baseTime;
1753
- return roundSeconds(Math.max(0, lastTime - baseTime) / 1000);
1754
- };
1755
- const getSelectionPercent = (value, durationSeconds) => {
1756
- if (durationSeconds <= 0) {
1757
- return 0;
1402
+ return [{
1403
+ event,
1404
+ time
1405
+ }];
1406
+ });
1407
+ };
1408
+ const getTimelineDurationSeconds = events => {
1409
+ const eventsWithTime = getEventsWithTime(events);
1410
+ if (eventsWithTime.length === 0) {
1411
+ return 0;
1412
+ }
1413
+ const baseTime = eventsWithTime[0].time;
1414
+ const lastTime = eventsWithTime.at(-1)?.time ?? baseTime;
1415
+ return roundSeconds(Math.max(0, lastTime - baseTime) / 1000);
1416
+ };
1417
+ const getSelectionPercent = (value, durationSeconds) => {
1418
+ if (durationSeconds <= 0) {
1419
+ return 0;
1420
+ }
1421
+ return Number((value / durationSeconds * 100).toFixed(3));
1422
+ };
1423
+ const getNormalizedRange = (durationSeconds, startValue, endValue) => {
1424
+ const parsedStart = parseTimelineSeconds(startValue);
1425
+ const parsedEnd = parseTimelineSeconds(endValue);
1426
+ if (parsedStart === undefined && parsedEnd === undefined) {
1427
+ return {
1428
+ endSeconds: null,
1429
+ hasSelection: false,
1430
+ startSeconds: null
1431
+ };
1432
+ }
1433
+ const rawStart = parsedStart ?? 0;
1434
+ const rawEnd = parsedEnd ?? durationSeconds;
1435
+ const normalizedStart = Math.max(0, Math.min(durationSeconds, Math.min(rawStart, rawEnd)));
1436
+ const normalizedEnd = Math.max(0, Math.min(durationSeconds, Math.max(rawStart, rawEnd)));
1437
+ return {
1438
+ endSeconds: roundSeconds(normalizedEnd),
1439
+ hasSelection: true,
1440
+ startSeconds: roundSeconds(normalizedStart)
1441
+ };
1442
+ };
1443
+ const filterEventsByTimelineRange = (events, startValue, endValue) => {
1444
+ const eventsWithTime = getEventsWithTime(events);
1445
+ if (eventsWithTime.length === 0) {
1446
+ return events;
1447
+ }
1448
+ const baseTime = eventsWithTime[0].time;
1449
+ const lastTime = eventsWithTime.at(-1)?.time ?? baseTime;
1450
+ const durationSeconds = roundSeconds(Math.max(0, lastTime - baseTime) / 1000);
1451
+ const range = getNormalizedRange(durationSeconds, startValue, endValue);
1452
+ if (!range.hasSelection || range.startSeconds === null || range.endSeconds === null) {
1453
+ return events;
1454
+ }
1455
+ const startTime = baseTime + range.startSeconds * 1000;
1456
+ const endTime = baseTime + range.endSeconds * 1000;
1457
+ return eventsWithTime.filter(item => item.time >= startTime && item.time <= endTime).map(item => item.event);
1458
+ };
1459
+ const getTimelineInfo = (events, startValue, endValue) => {
1460
+ const eventsWithTime = getEventsWithTime(events);
1461
+ if (eventsWithTime.length === 0) {
1462
+ return {
1463
+ buckets: [],
1464
+ durationSeconds: 0,
1465
+ endSeconds: null,
1466
+ hasSelection: false,
1467
+ selectionEndPercent: null,
1468
+ selectionStartPercent: null,
1469
+ startSeconds: null
1470
+ };
1471
+ }
1472
+ const baseTime = eventsWithTime[0].time;
1473
+ const lastTime = eventsWithTime.at(-1)?.time ?? baseTime;
1474
+ const durationMs = Math.max(0, lastTime - baseTime);
1475
+ const durationSeconds = roundSeconds(durationMs / 1000);
1476
+ const range = getNormalizedRange(durationSeconds, startValue, endValue);
1477
+ const bucketCount = durationSeconds === 0 ? 1 : Math.max(12, Math.min(48, Math.ceil(durationSeconds)));
1478
+ const bucketDurationMs = durationMs === 0 ? 1000 : durationMs / bucketCount;
1479
+ const counts = Array.from({
1480
+ length: bucketCount
1481
+ }).fill(0);
1482
+ for (const item of eventsWithTime) {
1483
+ const offsetMs = item.time - baseTime;
1484
+ const index = durationMs === 0 ? 0 : Math.min(bucketCount - 1, Math.floor(offsetMs / durationMs * bucketCount));
1485
+ counts[index] += 1;
1486
+ }
1487
+ const maxCount = Math.max(...counts);
1488
+ const selectionStartPercent = range.hasSelection && range.startSeconds !== null ? getSelectionPercent(range.startSeconds, durationSeconds) : null;
1489
+ const selectionEndPercent = range.hasSelection && range.endSeconds !== null ? getSelectionPercent(range.endSeconds, durationSeconds) : null;
1490
+ const buckets = counts.map((count, index) => {
1491
+ const bucketStartMs = index * bucketDurationMs;
1492
+ const bucketEndMs = index === bucketCount - 1 ? durationMs : (index + 1) * bucketDurationMs;
1493
+ const hasSelection = range.hasSelection && range.startSeconds !== null && range.endSeconds !== null;
1494
+ const selectionStartMs = hasSelection ? range.startSeconds * 1000 : 0;
1495
+ const selectionEndMs = hasSelection ? range.endSeconds * 1000 : 0;
1496
+ return {
1497
+ count,
1498
+ endSeconds: roundSeconds(bucketEndMs / 1000),
1499
+ isSelected: hasSelection && bucketEndMs >= selectionStartMs && bucketStartMs <= selectionEndMs,
1500
+ startSeconds: roundSeconds(bucketStartMs / 1000),
1501
+ unitCount: count === 0 ? 0 : Math.max(1, Math.round(count / maxCount * maxBarUnits))
1502
+ };
1503
+ });
1504
+ return {
1505
+ buckets,
1506
+ durationSeconds,
1507
+ endSeconds: range.endSeconds,
1508
+ hasSelection: range.hasSelection,
1509
+ selectionEndPercent,
1510
+ selectionStartPercent,
1511
+ startSeconds: range.startSeconds
1512
+ };
1513
+ };
1514
+
1515
+ const getCurrentEvents$3 = state => {
1516
+ const filteredEvents = getFilteredEvents(state.events, state.filterValue, state.eventCategoryFilter, state.showInputEvents, state.showResponsePartEvents, state.showEventStreamFinishedEvents);
1517
+ return filterEventsByTimelineRange(filteredEvents, state.timelineStartSeconds, state.timelineEndSeconds);
1518
+ };
1519
+ const getEventIndexByStableId$1 = (events, event) => {
1520
+ const stableEventId = getStableEventId(event);
1521
+ return events.findIndex(candidate => getStableEventId(candidate) === stableEventId);
1522
+ };
1523
+ const getSelectedEventIndex$1 = state => {
1524
+ const {
1525
+ selectedEventIndex
1526
+ } = state;
1527
+ if (selectedEventIndex === null) {
1528
+ return null;
1529
+ }
1530
+ const filteredEvents = getCurrentEvents$3(state);
1531
+ const selectedEvent = filteredEvents[selectedEventIndex];
1532
+ if (!selectedEvent) {
1533
+ return null;
1534
+ }
1535
+ const newIndex = getEventIndexByStableId$1(filteredEvents, selectedEvent);
1536
+ if (newIndex === -1) {
1537
+ return null;
1538
+ }
1539
+ return newIndex;
1540
+ };
1541
+ const getPreservedSelectedEventIndex$1 = (oldState, newState) => {
1542
+ const {
1543
+ selectedEventIndex
1544
+ } = oldState;
1545
+ if (selectedEventIndex === null) {
1546
+ return null;
1547
+ }
1548
+ const oldFilteredEvents = getCurrentEvents$3(oldState);
1549
+ const selectedEvent = oldFilteredEvents[selectedEventIndex];
1550
+ if (!selectedEvent) {
1551
+ return null;
1552
+ }
1553
+ const newFilteredEvents = getCurrentEvents$3(newState);
1554
+ const newIndex = getEventIndexByStableId$1(newFilteredEvents, selectedEvent);
1555
+ if (newIndex === -1) {
1556
+ return null;
1557
+ }
1558
+ return newIndex;
1559
+ };
1560
+ const withPreservedSelection$1 = (state, nextState) => {
1561
+ const selectedEventIndex = getPreservedSelectedEventIndex$1(state, nextState);
1562
+ return {
1563
+ ...nextState,
1564
+ selectedEvent: selectedEventIndex === null ? null : state.selectedEvent,
1565
+ selectedEventId: selectedEventIndex === null ? null : state.selectedEventId,
1566
+ selectedEventIndex
1567
+ };
1568
+ };
1569
+
1570
+ const handleEventCategoryFilter = (state, value) => {
1571
+ const nextState = {
1572
+ ...state,
1573
+ eventCategoryFilter: value || All
1574
+ };
1575
+ return withPreservedSelection$1(state, nextState);
1576
+ };
1577
+
1578
+ // cspell:ignore IDBP
1579
+
1580
+ const startedEventType = 'tool-execution-started';
1581
+ const finishedEventType = 'tool-execution-finished';
1582
+ const getRawEventBySessionIdAndEventId = async (store, sessionId, sessionIdIndexName, eventId) => {
1583
+ if (eventId < 1) {
1584
+ return undefined;
1585
+ }
1586
+ if (store.indexNames.contains(sessionIdIndexName)) {
1587
+ const index = store.index(sessionIdIndexName);
1588
+ const keys = await index.getAllKeys(sessionId, eventId);
1589
+ if (keys.length < eventId) {
1590
+ return undefined;
1591
+ }
1592
+ const key = keys.at(-1);
1593
+ if (key === undefined) {
1594
+ return undefined;
1595
+ }
1596
+ const event = await store.get(key);
1597
+ return event;
1598
+ }
1599
+ const all = await store.getAll();
1600
+ const events = all.filter(event => event.sessionId === sessionId);
1601
+ return events[eventId - 1];
1602
+ };
1603
+ const getTimestamp = value => {
1604
+ return typeof value === 'string' || typeof value === 'number' ? value : undefined;
1605
+ };
1606
+ const hasMatchingToolName = (startedEvent, finishedEvent) => {
1607
+ if (typeof startedEvent.toolName === 'string' && typeof finishedEvent.toolName === 'string') {
1608
+ return startedEvent.toolName === finishedEvent.toolName;
1609
+ }
1610
+ return true;
1611
+ };
1612
+ const mergeToolExecutionEvents = (startedEvent, finishedEvent, eventId) => {
1613
+ const ended = getTimestamp(finishedEvent.ended) ?? getTimestamp(finishedEvent.endTime) ?? getTimestamp(finishedEvent.timestamp);
1614
+ const started = getTimestamp(startedEvent.started) ?? getTimestamp(startedEvent.startTime) ?? getTimestamp(startedEvent.timestamp);
1615
+ return {
1616
+ ...startedEvent,
1617
+ ...finishedEvent,
1618
+ ...(ended === undefined ? {} : {
1619
+ ended
1620
+ }),
1621
+ eventId,
1622
+ ...(started === undefined ? {} : {
1623
+ started
1624
+ }),
1625
+ type: 'tool-execution'
1626
+ };
1627
+ };
1628
+ const getEventDetailsBySessionIdAndEventId = async (store, sessionId, sessionIdIndexName, eventId, summaryType) => {
1629
+ const event = await getRawEventBySessionIdAndEventId(store, sessionId, sessionIdIndexName, eventId);
1630
+ if (!event) {
1631
+ return undefined;
1632
+ }
1633
+ if (summaryType !== 'tool-execution') {
1634
+ return {
1635
+ ...event,
1636
+ eventId
1637
+ };
1638
+ }
1639
+ if (event.type !== startedEventType) {
1640
+ return {
1641
+ ...event,
1642
+ eventId
1643
+ };
1644
+ }
1645
+ const nextEvent = await getRawEventBySessionIdAndEventId(store, sessionId, sessionIdIndexName, eventId + 1);
1646
+ if (!nextEvent || nextEvent.type !== finishedEventType || nextEvent.sessionId !== sessionId || !hasMatchingToolName(event, nextEvent)) {
1647
+ return {
1648
+ ...event,
1649
+ eventId
1650
+ };
1651
+ }
1652
+ return mergeToolExecutionEvents(event, nextEvent, eventId);
1653
+ };
1654
+
1655
+ const instanceOfAny = (object, constructors) => constructors.some(c => object instanceof c);
1656
+ let idbProxyableTypes;
1657
+ let cursorAdvanceMethods;
1658
+ // This is a function to prevent it throwing up in node environments.
1659
+ function getIdbProxyableTypes() {
1660
+ return idbProxyableTypes || (idbProxyableTypes = [IDBDatabase, IDBObjectStore, IDBIndex, IDBCursor, IDBTransaction]);
1661
+ }
1662
+ // This is a function to prevent it throwing up in node environments.
1663
+ function getCursorAdvanceMethods() {
1664
+ return cursorAdvanceMethods || (cursorAdvanceMethods = [IDBCursor.prototype.advance, IDBCursor.prototype.continue, IDBCursor.prototype.continuePrimaryKey]);
1665
+ }
1666
+ const transactionDoneMap = new WeakMap();
1667
+ const transformCache = new WeakMap();
1668
+ const reverseTransformCache = new WeakMap();
1669
+ function promisifyRequest(request) {
1670
+ const promise = new Promise((resolve, reject) => {
1671
+ const unlisten = () => {
1672
+ request.removeEventListener('success', success);
1673
+ request.removeEventListener('error', error);
1674
+ };
1675
+ const success = () => {
1676
+ resolve(wrap(request.result));
1677
+ unlisten();
1678
+ };
1679
+ const error = () => {
1680
+ reject(request.error);
1681
+ unlisten();
1682
+ };
1683
+ request.addEventListener('success', success);
1684
+ request.addEventListener('error', error);
1685
+ });
1686
+ // This mapping exists in reverseTransformCache but doesn't exist in transformCache. This
1687
+ // is because we create many promises from a single IDBRequest.
1688
+ reverseTransformCache.set(promise, request);
1689
+ return promise;
1690
+ }
1691
+ function cacheDonePromiseForTransaction(tx) {
1692
+ // Early bail if we've already created a done promise for this transaction.
1693
+ if (transactionDoneMap.has(tx)) return;
1694
+ const done = new Promise((resolve, reject) => {
1695
+ const unlisten = () => {
1696
+ tx.removeEventListener('complete', complete);
1697
+ tx.removeEventListener('error', error);
1698
+ tx.removeEventListener('abort', error);
1699
+ };
1700
+ const complete = () => {
1701
+ resolve();
1702
+ unlisten();
1703
+ };
1704
+ const error = () => {
1705
+ reject(tx.error || new DOMException('AbortError', 'AbortError'));
1706
+ unlisten();
1707
+ };
1708
+ tx.addEventListener('complete', complete);
1709
+ tx.addEventListener('error', error);
1710
+ tx.addEventListener('abort', error);
1711
+ });
1712
+ // Cache it for later retrieval.
1713
+ transactionDoneMap.set(tx, done);
1714
+ }
1715
+ let idbProxyTraps = {
1716
+ get(target, prop, receiver) {
1717
+ if (target instanceof IDBTransaction) {
1718
+ // Special handling for transaction.done.
1719
+ if (prop === 'done') return transactionDoneMap.get(target);
1720
+ // Make tx.store return the only store in the transaction, or undefined if there are many.
1721
+ if (prop === 'store') {
1722
+ return receiver.objectStoreNames[1] ? undefined : receiver.objectStore(receiver.objectStoreNames[0]);
1723
+ }
1724
+ }
1725
+ // Else transform whatever we get back.
1726
+ return wrap(target[prop]);
1727
+ },
1728
+ set(target, prop, value) {
1729
+ target[prop] = value;
1730
+ return true;
1731
+ },
1732
+ has(target, prop) {
1733
+ if (target instanceof IDBTransaction && (prop === 'done' || prop === 'store')) {
1734
+ return true;
1735
+ }
1736
+ return prop in target;
1737
+ }
1738
+ };
1739
+ function replaceTraps(callback) {
1740
+ idbProxyTraps = callback(idbProxyTraps);
1741
+ }
1742
+ function wrapFunction(func) {
1743
+ // Due to expected object equality (which is enforced by the caching in `wrap`), we
1744
+ // only create one new func per func.
1745
+ // Cursor methods are special, as the behaviour is a little more different to standard IDB. In
1746
+ // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the
1747
+ // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense
1748
+ // with real promises, so each advance methods returns a new promise for the cursor object, or
1749
+ // undefined if the end of the cursor has been reached.
1750
+ if (getCursorAdvanceMethods().includes(func)) {
1751
+ return function (...args) {
1752
+ // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
1753
+ // the original object.
1754
+ func.apply(unwrap(this), args);
1755
+ return wrap(this.request);
1756
+ };
1757
+ }
1758
+ return function (...args) {
1759
+ // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
1760
+ // the original object.
1761
+ return wrap(func.apply(unwrap(this), args));
1762
+ };
1763
+ }
1764
+ function transformCachableValue(value) {
1765
+ if (typeof value === 'function') return wrapFunction(value);
1766
+ // This doesn't return, it just creates a 'done' promise for the transaction,
1767
+ // which is later returned for transaction.done (see idbObjectHandler).
1768
+ if (value instanceof IDBTransaction) cacheDonePromiseForTransaction(value);
1769
+ if (instanceOfAny(value, getIdbProxyableTypes())) return new Proxy(value, idbProxyTraps);
1770
+ // Return the same value back if we're not going to transform it.
1771
+ return value;
1772
+ }
1773
+ function wrap(value) {
1774
+ // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because
1775
+ // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.
1776
+ if (value instanceof IDBRequest) return promisifyRequest(value);
1777
+ // If we've already transformed this value before, reuse the transformed value.
1778
+ // This is faster, but it also provides object equality.
1779
+ if (transformCache.has(value)) return transformCache.get(value);
1780
+ const newValue = transformCachableValue(value);
1781
+ // Not all types are transformed.
1782
+ // These may be primitive types, so they can't be WeakMap keys.
1783
+ if (newValue !== value) {
1784
+ transformCache.set(value, newValue);
1785
+ reverseTransformCache.set(newValue, value);
1786
+ }
1787
+ return newValue;
1788
+ }
1789
+ const unwrap = value => reverseTransformCache.get(value);
1790
+
1791
+ /**
1792
+ * Open a database.
1793
+ *
1794
+ * @param name Name of the database.
1795
+ * @param version Schema version.
1796
+ * @param callbacks Additional callbacks.
1797
+ */
1798
+ function openDB(name, version, {
1799
+ blocked,
1800
+ upgrade,
1801
+ blocking,
1802
+ terminated
1803
+ } = {}) {
1804
+ const request = indexedDB.open(name, version);
1805
+ const openPromise = wrap(request);
1806
+ if (upgrade) {
1807
+ request.addEventListener('upgradeneeded', event => {
1808
+ upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction), event);
1809
+ });
1810
+ }
1811
+ if (blocked) {
1812
+ request.addEventListener('blocked', event => blocked(
1813
+ // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405
1814
+ event.oldVersion, event.newVersion, event));
1815
+ }
1816
+ openPromise.then(db => {
1817
+ if (terminated) db.addEventListener('close', () => terminated());
1818
+ if (blocking) {
1819
+ db.addEventListener('versionchange', event => blocking(event.oldVersion, event.newVersion, event));
1820
+ }
1821
+ }).catch(() => {});
1822
+ return openPromise;
1823
+ }
1824
+ const readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];
1825
+ const writeMethods = ['put', 'add', 'delete', 'clear'];
1826
+ const cachedMethods = new Map();
1827
+ function getMethod(target, prop) {
1828
+ if (!(target instanceof IDBDatabase && !(prop in target) && typeof prop === 'string')) {
1829
+ return;
1830
+ }
1831
+ if (cachedMethods.get(prop)) return cachedMethods.get(prop);
1832
+ const targetFuncName = prop.replace(/FromIndex$/, '');
1833
+ const useIndex = prop !== targetFuncName;
1834
+ const isWrite = writeMethods.includes(targetFuncName);
1835
+ if (
1836
+ // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.
1837
+ !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) || !(isWrite || readMethods.includes(targetFuncName))) {
1838
+ return;
1839
+ }
1840
+ const method = async function (storeName, ...args) {
1841
+ // isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(
1842
+ const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');
1843
+ let target = tx.store;
1844
+ if (useIndex) target = target.index(args.shift());
1845
+ // Must reject if op rejects.
1846
+ // If it's a write operation, must reject if tx.done rejects.
1847
+ // Must reject with op rejection first.
1848
+ // Must resolve with op value.
1849
+ // Must handle both promises (no unhandled rejections)
1850
+ return (await Promise.all([target[targetFuncName](...args), isWrite && tx.done]))[0];
1851
+ };
1852
+ cachedMethods.set(prop, method);
1853
+ return method;
1854
+ }
1855
+ replaceTraps(oldTraps => ({
1856
+ ...oldTraps,
1857
+ get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),
1858
+ has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop)
1859
+ }));
1860
+ const advanceMethodProps = ['continue', 'continuePrimaryKey', 'advance'];
1861
+ const methodMap = {};
1862
+ const advanceResults = new WeakMap();
1863
+ const ittrProxiedCursorToOriginalProxy = new WeakMap();
1864
+ const cursorIteratorTraps = {
1865
+ get(target, prop) {
1866
+ if (!advanceMethodProps.includes(prop)) return target[prop];
1867
+ let cachedFunc = methodMap[prop];
1868
+ if (!cachedFunc) {
1869
+ cachedFunc = methodMap[prop] = function (...args) {
1870
+ advanceResults.set(this, ittrProxiedCursorToOriginalProxy.get(this)[prop](...args));
1871
+ };
1872
+ }
1873
+ return cachedFunc;
1758
1874
  }
1759
- return Number((value / durationSeconds * 100).toFixed(3));
1760
1875
  };
1761
- const getNormalizedRange = (durationSeconds, startValue, endValue) => {
1762
- const parsedStart = parseTimelineSeconds(startValue);
1763
- const parsedEnd = parseTimelineSeconds(endValue);
1764
- if (parsedStart === undefined && parsedEnd === undefined) {
1765
- return {
1766
- endSeconds: null,
1767
- hasSelection: false,
1768
- startSeconds: null
1769
- };
1876
+ async function* iterate(...args) {
1877
+ // tslint:disable-next-line:no-this-assignment
1878
+ let cursor = this;
1879
+ if (!(cursor instanceof IDBCursor)) {
1880
+ cursor = await cursor.openCursor(...args);
1770
1881
  }
1771
- const rawStart = parsedStart ?? 0;
1772
- const rawEnd = parsedEnd ?? durationSeconds;
1773
- const normalizedStart = Math.max(0, Math.min(durationSeconds, Math.min(rawStart, rawEnd)));
1774
- const normalizedEnd = Math.max(0, Math.min(durationSeconds, Math.max(rawStart, rawEnd)));
1775
- return {
1776
- endSeconds: roundSeconds(normalizedEnd),
1777
- hasSelection: true,
1778
- startSeconds: roundSeconds(normalizedStart)
1779
- };
1780
- };
1781
- const filterEventsByTimelineRange = (events, startValue, endValue) => {
1782
- const eventsWithTime = getEventsWithTime(events);
1783
- if (eventsWithTime.length === 0) {
1784
- return events;
1882
+ if (!cursor) return;
1883
+ cursor = cursor;
1884
+ const proxiedCursor = new Proxy(cursor, cursorIteratorTraps);
1885
+ ittrProxiedCursorToOriginalProxy.set(proxiedCursor, cursor);
1886
+ // Map this double-proxy back to the original, so other cursor methods work.
1887
+ reverseTransformCache.set(proxiedCursor, unwrap(cursor));
1888
+ while (cursor) {
1889
+ yield proxiedCursor;
1890
+ // If one of the advancing methods was not called, call continue().
1891
+ cursor = await (advanceResults.get(proxiedCursor) || cursor.continue());
1892
+ advanceResults.delete(proxiedCursor);
1785
1893
  }
1786
- const baseTime = eventsWithTime[0].time;
1787
- const lastTime = eventsWithTime.at(-1)?.time ?? baseTime;
1788
- const durationSeconds = roundSeconds(Math.max(0, lastTime - baseTime) / 1000);
1789
- const range = getNormalizedRange(durationSeconds, startValue, endValue);
1790
- if (!range.hasSelection || range.startSeconds === null || range.endSeconds === null) {
1791
- return events;
1894
+ }
1895
+ function isIteratorProp(target, prop) {
1896
+ return prop === Symbol.asyncIterator && instanceOfAny(target, [IDBIndex, IDBObjectStore, IDBCursor]) || prop === 'iterate' && instanceOfAny(target, [IDBIndex, IDBObjectStore]);
1897
+ }
1898
+ replaceTraps(oldTraps => ({
1899
+ ...oldTraps,
1900
+ get(target, prop, receiver) {
1901
+ if (isIteratorProp(target, prop)) return iterate;
1902
+ return oldTraps.get(target, prop, receiver);
1903
+ },
1904
+ has(target, prop) {
1905
+ return isIteratorProp(target, prop) || oldTraps.has(target, prop);
1792
1906
  }
1793
- const startTime = baseTime + range.startSeconds * 1000;
1794
- const endTime = baseTime + range.endSeconds * 1000;
1795
- return eventsWithTime.filter(item => item.time >= startTime && item.time <= endTime).map(item => item.event);
1907
+ }));
1908
+
1909
+ const openDatabaseDependencies = {
1910
+ openDB: openDB
1796
1911
  };
1797
- const getTimelineInfo = (events, startValue, endValue) => {
1798
- const eventsWithTime = getEventsWithTime(events);
1799
- if (eventsWithTime.length === 0) {
1800
- return {
1801
- buckets: [],
1802
- durationSeconds: 0,
1803
- endSeconds: null,
1804
- hasSelection: false,
1805
- selectionEndPercent: null,
1806
- selectionStartPercent: null,
1807
- startSeconds: null
1808
- };
1809
- }
1810
- const baseTime = eventsWithTime[0].time;
1811
- const lastTime = eventsWithTime.at(-1)?.time ?? baseTime;
1812
- const durationMs = Math.max(0, lastTime - baseTime);
1813
- const durationSeconds = roundSeconds(durationMs / 1000);
1814
- const range = getNormalizedRange(durationSeconds, startValue, endValue);
1815
- const bucketCount = durationSeconds === 0 ? 1 : Math.max(12, Math.min(48, Math.ceil(durationSeconds)));
1816
- const bucketDurationMs = durationMs === 0 ? 1000 : durationMs / bucketCount;
1817
- const counts = Array.from({
1818
- length: bucketCount
1819
- }).fill(0);
1820
- for (const item of eventsWithTime) {
1821
- const offsetMs = item.time - baseTime;
1822
- const index = durationMs === 0 ? 0 : Math.min(bucketCount - 1, Math.floor(offsetMs / durationMs * bucketCount));
1823
- counts[index] += 1;
1912
+ const openDatabase = async (databaseName, dataBaseVersion) => {
1913
+ return openDatabaseDependencies.openDB(databaseName, dataBaseVersion);
1914
+ };
1915
+
1916
+ const loadSelectedEventDependencies = {
1917
+ getEventDetailsBySessionIdAndEventId: getEventDetailsBySessionIdAndEventId,
1918
+ openDatabase: openDatabase
1919
+ };
1920
+ const loadSelectedEvent = async (databaseName, dataBaseVersion, eventStoreName, sessionId, sessionIdIndexName, eventId, type) => {
1921
+ const database = await loadSelectedEventDependencies.openDatabase(databaseName, dataBaseVersion);
1922
+ try {
1923
+ if (!database.objectStoreNames.contains(eventStoreName)) {
1924
+ return null;
1925
+ }
1926
+ const transaction = database.transaction(eventStoreName, 'readonly');
1927
+ const store = transaction.objectStore(eventStoreName);
1928
+ const event = await loadSelectedEventDependencies.getEventDetailsBySessionIdAndEventId(store, sessionId, sessionIdIndexName, eventId, type);
1929
+ return event ?? null;
1930
+ } finally {
1931
+ database.close();
1824
1932
  }
1825
- const maxCount = Math.max(...counts);
1826
- const selectionStartPercent = range.hasSelection && range.startSeconds !== null ? getSelectionPercent(range.startSeconds, durationSeconds) : null;
1827
- const selectionEndPercent = range.hasSelection && range.endSeconds !== null ? getSelectionPercent(range.endSeconds, durationSeconds) : null;
1828
- const buckets = counts.map((count, index) => {
1829
- const bucketStartMs = index * bucketDurationMs;
1830
- const bucketEndMs = index === bucketCount - 1 ? durationMs : (index + 1) * bucketDurationMs;
1831
- const hasSelection = range.hasSelection && range.startSeconds !== null && range.endSeconds !== null;
1832
- const selectionStartMs = hasSelection ? range.startSeconds * 1000 : 0;
1833
- const selectionEndMs = hasSelection ? range.endSeconds * 1000 : 0;
1834
- return {
1835
- count,
1836
- endSeconds: roundSeconds(bucketEndMs / 1000),
1837
- isSelected: hasSelection && bucketEndMs >= selectionStartMs && bucketStartMs <= selectionEndMs,
1838
- startSeconds: roundSeconds(bucketStartMs / 1000),
1839
- unitCount: count === 0 ? 0 : Math.max(1, Math.round(count / maxCount * maxBarUnits))
1840
- };
1841
- });
1842
- return {
1843
- buckets,
1844
- durationSeconds,
1845
- endSeconds: range.endSeconds,
1846
- hasSelection: range.hasSelection,
1847
- selectionEndPercent,
1848
- selectionStartPercent,
1849
- startSeconds: range.startSeconds
1850
- };
1851
1933
  };
1852
1934
 
1853
1935
  const getCurrentEvents$2 = state => {
@@ -1895,7 +1977,7 @@ const parseSelectedEventIndex$1 = value => {
1895
1977
  }
1896
1978
  return parsed;
1897
1979
  };
1898
- const handleEventRowClick = async (state, value, button) => {
1980
+ const handleEventRowClick = async (state, value, button = 0) => {
1899
1981
  if (!isPrimaryButton(button)) {
1900
1982
  return state;
1901
1983
  }
@@ -1931,7 +2013,7 @@ const getCurrentEvents$1 = state => {
1931
2013
  const filteredEvents = getFilteredEvents(state.events, state.filterValue, state.eventCategoryFilter, state.showInputEvents, state.showResponsePartEvents, state.showEventStreamFinishedEvents);
1932
2014
  return filterEventsByTimelineRange(filteredEvents, state.timelineStartSeconds, state.timelineEndSeconds);
1933
2015
  };
1934
- const parseTimelineRangePreset = value => {
2016
+ const parseTimelineRangePreset$1 = value => {
1935
2017
  if (!value) {
1936
2018
  return {
1937
2019
  timelineEndSeconds: '',
@@ -2074,7 +2156,7 @@ const handleInput = (state, name, value, checked) => {
2074
2156
  if (name === TimelineRangePreset) {
2075
2157
  const nextState = {
2076
2158
  ...state,
2077
- ...parseTimelineRangePreset(value)
2159
+ ...parseTimelineRangePreset$1(value)
2078
2160
  };
2079
2161
  return withPreservedSelection(state, nextState);
2080
2162
  }
@@ -2126,8 +2208,43 @@ const clearTimelineSelectionState = state => {
2126
2208
  };
2127
2209
  };
2128
2210
 
2211
+ const parseTimelineRangePreset = value => {
2212
+ if (!value) {
2213
+ return {
2214
+ timelineEndSeconds: '',
2215
+ timelineStartSeconds: ''
2216
+ };
2217
+ }
2218
+ const [timelineStartSeconds = '', timelineEndSeconds = ''] = value.split(':', 2);
2219
+ return {
2220
+ timelineEndSeconds,
2221
+ timelineStartSeconds
2222
+ };
2223
+ };
2224
+ const handleTimelineStartSeconds = (state, value) => {
2225
+ const nextState = {
2226
+ ...state,
2227
+ timelineStartSeconds: value
2228
+ };
2229
+ return withPreservedSelection$1(state, nextState);
2230
+ };
2231
+ const handleTimelineEndSeconds = (state, value) => {
2232
+ const nextState = {
2233
+ ...state,
2234
+ timelineEndSeconds: value
2235
+ };
2236
+ return withPreservedSelection$1(state, nextState);
2237
+ };
2238
+ const handleTimelineRangePreset = (state, value) => {
2239
+ const nextState = {
2240
+ ...state,
2241
+ ...parseTimelineRangePreset(value)
2242
+ };
2243
+ return withPreservedSelection$1(state, nextState);
2244
+ };
2245
+
2129
2246
  const handleTimelineDoubleClick = state => {
2130
- const nextState = handleInput(state, TimelineRangePreset, '', false);
2247
+ const nextState = handleTimelineRangePreset(state, '');
2131
2248
  return clearTimelineSelectionState(nextState);
2132
2249
  };
2133
2250
 
@@ -2217,10 +2334,44 @@ const handleTimelinePointerUp = (state, eventX) => {
2217
2334
  const focus = Number.parseFloat(focusSeconds);
2218
2335
  const startSeconds = formatTimelinePresetValue(Math.min(anchor, focus));
2219
2336
  const endSeconds = formatTimelinePresetValue(Math.max(anchor, focus));
2220
- const nextState = handleInput(state, TimelineRangePreset, `${startSeconds}:${endSeconds}`, false);
2337
+ const nextState = handleTimelineRangePreset(state, `${startSeconds}:${endSeconds}`);
2221
2338
  return clearTimelineSelectionState(nextState);
2222
2339
  };
2223
2340
 
2341
+ const handleUseDevtoolsLayout = (state, checked) => {
2342
+ const useDevtoolsLayout = getBoolean(checked);
2343
+ const selectedEventIndex = useDevtoolsLayout ? getSelectedEventIndex$1(state) : null;
2344
+ return {
2345
+ ...state,
2346
+ selectedEvent: useDevtoolsLayout && selectedEventIndex !== null ? state.selectedEvent : null,
2347
+ selectedEventId: useDevtoolsLayout && selectedEventIndex !== null ? state.selectedEventId : null,
2348
+ selectedEventIndex,
2349
+ useDevtoolsLayout
2350
+ };
2351
+ };
2352
+
2353
+ const handleShowEventStreamFinishedEvents = (state, checked) => {
2354
+ const nextState = {
2355
+ ...state,
2356
+ showEventStreamFinishedEvents: getBoolean(checked)
2357
+ };
2358
+ return withPreservedSelection$1(state, nextState);
2359
+ };
2360
+ const handleShowInputEvents = (state, checked) => {
2361
+ const nextState = {
2362
+ ...state,
2363
+ showInputEvents: getBoolean(checked)
2364
+ };
2365
+ return withPreservedSelection$1(state, nextState);
2366
+ };
2367
+ const handleShowResponsePartEvents = (state, checked) => {
2368
+ const nextState = {
2369
+ ...state,
2370
+ showResponsePartEvents: getBoolean(checked)
2371
+ };
2372
+ return withPreservedSelection$1(state, nextState);
2373
+ };
2374
+
2224
2375
  const getFailedToLoadMessage = sessionId => {
2225
2376
  return `Failed to load chat debug session "${sessionId}". Please try again.`;
2226
2377
  };
@@ -2571,9 +2722,23 @@ const refresh = async state => {
2571
2722
  return refreshEvents(state);
2572
2723
  };
2573
2724
 
2725
+ const Button = 1;
2726
+ const Div = 4;
2727
+ const Input = 6;
2728
+ const Span = 8;
2729
+ const Table = 9;
2730
+ const TBody = 10;
2731
+ const Td = 11;
2732
+ const Text = 12;
2733
+ const Th = 13;
2734
+ const THead = 14;
2735
+ const Tr = 15;
2736
+ const Search = 42;
2737
+ const Label = 66;
2738
+ const Reference = 100;
2739
+
2574
2740
  const ClientX = 'event.clientX';
2575
2741
  const ClientY = 'event.clientY';
2576
- const TargetChecked = 'event.target.checked';
2577
2742
  const TargetName = 'event.target.name';
2578
2743
  const TargetValue = 'event.target.value';
2579
2744
 
@@ -3319,21 +3484,6 @@ const renderCss = (oldState, newState) => {
3319
3484
  return [SetCss, newState.uid, css];
3320
3485
  };
3321
3486
 
3322
- const Button = 1;
3323
- const Div = 4;
3324
- const Input = 6;
3325
- const Span = 8;
3326
- const Table = 9;
3327
- const TBody = 10;
3328
- const Td = 11;
3329
- const Text = 12;
3330
- const Th = 13;
3331
- const THead = 14;
3332
- const Tr = 15;
3333
- const Search = 42;
3334
- const Label = 66;
3335
- const Reference = 100;
3336
-
3337
3487
  const text = data => {
3338
3488
  return {
3339
3489
  childCount: 0,
@@ -3715,9 +3865,9 @@ const getDebugErrorDom = errorMessage => {
3715
3865
  }, text(errorMessage)];
3716
3866
  };
3717
3867
 
3718
- const HandleInput = 4;
3868
+ const HandleEventCategoryFilter = 4;
3719
3869
  const HandleFilterInput = 5;
3720
- const HandleSimpleInput = 6;
3870
+ const HandleDetailTab = 6;
3721
3871
  const HandleEventRowClick = 7;
3722
3872
  const HandleHeaderContextMenu = 8;
3723
3873
  const HandleSashPointerDown = 9;
@@ -3730,6 +3880,8 @@ const HandleTimelinePointerMove = 15;
3730
3880
  const HandleTimelinePointerUp = 16;
3731
3881
  const HandleTimelineDoubleClick = 17;
3732
3882
  const HandleTableKeyDown = 18;
3883
+ const HandleTimelineRangePreset = 19;
3884
+ const HandleCloseDetails = 20;
3733
3885
 
3734
3886
  const getDebugViewTopDom = (filterValue, useDevtoolsLayout, quickFilterNodes) => {
3735
3887
  if (useDevtoolsLayout) {
@@ -3857,8 +4009,8 @@ const getTabNodes = selectedDetailTab => {
3857
4009
  className: joinClassNames(ChatDebugViewDetailsTab, isSelected && ChatDebugViewDetailsTabSelected),
3858
4010
  id: getTabId(detailTab),
3859
4011
  name: DetailTab,
3860
- onChange: HandleSimpleInput,
3861
- onClick: HandleSimpleInput,
4012
+ onChange: HandleDetailTab,
4013
+ onClick: HandleDetailTab,
3862
4014
  role: 'tab',
3863
4015
  tabIndex: isSelected ? 0 : -1,
3864
4016
  type: Button,
@@ -3884,8 +4036,8 @@ const getDetailsDom = (previewEventNodes, responseEventNodes = previewEventNodes
3884
4036
  childCount: 0,
3885
4037
  className: ChatDebugViewDetailsClose,
3886
4038
  name: CloseDetails,
3887
- onChange: HandleSimpleInput,
3888
- onClick: HandleSimpleInput,
4039
+ onChange: HandleCloseDetails,
4040
+ onClick: HandleCloseDetails,
3889
4041
  type: Button,
3890
4042
  value: 'close'
3891
4043
  }, {
@@ -4179,6 +4331,9 @@ const getEventsClassName = hasSelectedEvent => {
4179
4331
  const hasOwn = (event, key) => {
4180
4332
  return Object.hasOwn(event, key);
4181
4333
  };
4334
+ const isChatMessageUpdatedEvent = event => {
4335
+ return event.type === 'chat-message-updated';
4336
+ };
4182
4337
  const getPreviewName = event => {
4183
4338
  if (typeof event.name === 'string' && event.name) {
4184
4339
  return event.name;
@@ -4198,6 +4353,9 @@ const shouldIncludeArguments = (event, name) => {
4198
4353
  return true;
4199
4354
  };
4200
4355
  const getPreviewEvent = event => {
4356
+ if (isChatMessageUpdatedEvent(event) && typeof event.text === 'string') {
4357
+ return event.text;
4358
+ }
4201
4359
  const name = getPreviewName(event);
4202
4360
  const previewEvent = {
4203
4361
  ...(name === undefined ? {} : {
@@ -4310,7 +4468,7 @@ const getBucketDom = bucket => {
4310
4468
  className: ChatDebugViewTimelinePresetInput,
4311
4469
  inputType: 'radio',
4312
4470
  name: TimelineRangePreset,
4313
- onChange: HandleSimpleInput,
4471
+ onChange: HandleTimelineRangePreset,
4314
4472
  type: Input,
4315
4473
  value: presetValue
4316
4474
  }, {
@@ -4460,7 +4618,7 @@ const getQuickFilterNodes = (eventCategoryFilter, eventCategoryFilterOptions) =>
4460
4618
  className: ChatDebugViewQuickFilterInput,
4461
4619
  inputType: 'radio',
4462
4620
  name: EventCategoryFilter,
4463
- onChange: HandleInput,
4621
+ onChange: HandleEventCategoryFilter,
4464
4622
  type: Input,
4465
4623
  value: option.value
4466
4624
  }, text(option.label)];
@@ -4498,10 +4656,12 @@ const getChatDebugViewDom = (errorMessage, filterValue, eventCategoryFilter, eve
4498
4656
  if (timelineFilterDescription) {
4499
4657
  filterDescriptionParts.push(timelineFilterDescription);
4500
4658
  }
4659
+ const hasTimelineFilter = Boolean(timelineFilterDescription);
4501
4660
  const hasFilterValue = filterDescriptionParts.length > 0;
4502
4661
  const filterDescription = filterDescriptionParts.join(' ');
4503
4662
  const noFilteredEventsMessage = `no events found matching ${filterDescription}`;
4504
- const emptyMessage = events.length === 0 && hasFilterValue ? noFilteredEventsMessage : 'No events have been found';
4663
+ const useNoToolCallEventsMessage = eventCategoryFilter === Tools && !trimmedFilterValue && !hasTimelineFilter;
4664
+ const emptyMessage = events.length === 0 && hasFilterValue ? useNoToolCallEventsMessage ? 'No tool call events.' : noFilteredEventsMessage : 'No events have been found';
4505
4665
  const safeSelectedEventIndex = selectedEventIndex === null || selectedEventIndex < 0 || selectedEventIndex >= events.length ? null : selectedEventIndex;
4506
4666
  const contentNodes = useDevtoolsLayout ? getDevtoolsDom(events, selectedEvent, safeSelectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds, isDetailTab(selectedDetailTab) ? selectedDetailTab : Response) : getLegacyEventsDom(errorMessage, emptyMessage, events.flatMap(getEventNode));
4507
4667
  const quickFilterNodes = useDevtoolsLayout ? getQuickFilterNodes(eventCategoryFilter, eventCategoryFilterOptions) : [];
@@ -4585,11 +4745,17 @@ const renderEventListeners = () => {
4585
4745
  name: HandleFilterInput,
4586
4746
  params: ['handleInput', TargetName, TargetValue]
4587
4747
  }, {
4588
- name: HandleInput,
4589
- params: ['handleInput', TargetName, TargetValue, TargetChecked]
4748
+ name: HandleEventCategoryFilter,
4749
+ params: ['handleEventCategoryFilter', TargetValue]
4590
4750
  }, {
4591
- name: HandleSimpleInput,
4592
- params: ['handleInput', TargetName, TargetValue]
4751
+ name: HandleDetailTab,
4752
+ params: ['handleDetailTab', TargetValue]
4753
+ }, {
4754
+ name: HandleTimelineRangePreset,
4755
+ params: ['handleTimelineRangePreset', TargetValue]
4756
+ }, {
4757
+ name: HandleCloseDetails,
4758
+ params: ['handleCloseDetails']
4593
4759
  }, {
4594
4760
  name: HandleSashPointerDown,
4595
4761
  params: ['handleSashPointerDown', ClientX, ClientY],
@@ -4686,8 +4852,11 @@ const setIndexedDbSupportForTest = supported => {
4686
4852
  return setIndexedDbSupportOverride(supported);
4687
4853
  };
4688
4854
 
4855
+ const setSessionIdDependencies = {
4856
+ listChatViewEvents: listChatViewEvents
4857
+ };
4689
4858
  const setSessionId = async (state, sessionId) => {
4690
- const result = await listChatViewEvents(sessionId, state.databaseName, state.dataBaseVersion, state.eventStoreName, state.sessionIdIndexName);
4859
+ const result = await setSessionIdDependencies.listChatViewEvents(sessionId, state.databaseName, state.dataBaseVersion, state.eventStoreName, state.sessionIdIndexName, state.indexedDbSupportOverride);
4691
4860
  if (result.type === 'not-supported') {
4692
4861
  return {
4693
4862
  ...state,
@@ -4696,6 +4865,7 @@ const setSessionId = async (state, sessionId) => {
4696
4865
  initial: false,
4697
4866
  selectedEvent: null,
4698
4867
  selectedEventId: null,
4868
+ selectedEventIndex: null,
4699
4869
  sessionId
4700
4870
  };
4701
4871
  }
@@ -4707,6 +4877,7 @@ const setSessionId = async (state, sessionId) => {
4707
4877
  initial: false,
4708
4878
  selectedEvent: null,
4709
4879
  selectedEventId: null,
4880
+ selectedEventIndex: null,
4710
4881
  sessionId
4711
4882
  };
4712
4883
  }
@@ -4720,6 +4891,7 @@ const setSessionId = async (state, sessionId) => {
4720
4891
  initial: false,
4721
4892
  selectedEvent: null,
4722
4893
  selectedEventId: null,
4894
+ selectedEventIndex: null,
4723
4895
  sessionId
4724
4896
  };
4725
4897
  };
@@ -4728,18 +4900,28 @@ const commandMap = {
4728
4900
  'ChatDebug.create': create,
4729
4901
  'ChatDebug.diff2': diff2,
4730
4902
  'ChatDebug.getCommandIds': getCommandIds,
4903
+ 'ChatDebug.handleCloseDetails': wrapCommand(handleCloseDetails),
4731
4904
  'ChatDebug.handleDetailsContextMenu': wrapCommand(handleDetailsContextMenu),
4905
+ 'ChatDebug.handleDetailTab': wrapCommand(handleDetailTab),
4906
+ 'ChatDebug.handleEventCategoryFilter': wrapCommand(handleEventCategoryFilter),
4732
4907
  'ChatDebug.handleEventRowClick': wrapCommand(handleEventRowClick),
4733
4908
  'ChatDebug.handleHeaderContextMenu': wrapCommand(handleHeaderContextMenu),
4734
4909
  'ChatDebug.handleInput': wrapCommand(handleInput),
4735
4910
  'ChatDebug.handleSashPointerDown': wrapCommand(handleSashPointerDown),
4736
4911
  'ChatDebug.handleSashPointerMove': wrapCommand(handleSashPointerMove),
4737
4912
  'ChatDebug.handleSashPointerUp': wrapCommand(handleSashPointerUp),
4913
+ 'ChatDebug.handleShowEventStreamFinishedEvents': wrapCommand(handleShowEventStreamFinishedEvents),
4914
+ 'ChatDebug.handleShowInputEvents': wrapCommand(handleShowInputEvents),
4915
+ 'ChatDebug.handleShowResponsePartEvents': wrapCommand(handleShowResponsePartEvents),
4738
4916
  'ChatDebug.handleTableBodyContextMenu': wrapCommand(handleTableBodyContextMenu),
4739
4917
  'ChatDebug.handleTimelineDoubleClick': wrapCommand(handleTimelineDoubleClick),
4918
+ 'ChatDebug.handleTimelineEndSeconds': wrapCommand(handleTimelineEndSeconds),
4740
4919
  'ChatDebug.handleTimelinePointerDown': wrapCommand(handleTimelinePointerDown),
4741
4920
  'ChatDebug.handleTimelinePointerMove': wrapCommand(handleTimelinePointerMove),
4742
4921
  'ChatDebug.handleTimelinePointerUp': wrapCommand(handleTimelinePointerUp),
4922
+ 'ChatDebug.handleTimelineRangePreset': wrapCommand(handleTimelineRangePreset),
4923
+ 'ChatDebug.handleTimelineStartSeconds': wrapCommand(handleTimelineStartSeconds),
4924
+ 'ChatDebug.handleUseDevtoolsLayout': wrapCommand(handleUseDevtoolsLayout),
4743
4925
  'ChatDebug.loadContent': wrapCommand(loadContent),
4744
4926
  'ChatDebug.loadContent2': wrapCommand(loadContent),
4745
4927
  'ChatDebug.refresh': wrapCommand(refresh),