@lvce-editor/chat-debug-view 5.0.0 → 5.2.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.
- package/dist/chatDebugViewWorkerMain.js +693 -492
- package/package.json +1 -1
|
@@ -1024,12 +1024,16 @@ const {
|
|
|
1024
1024
|
} = create$1();
|
|
1025
1025
|
|
|
1026
1026
|
const Response = 'response';
|
|
1027
|
+
const Preview = 'preview';
|
|
1027
1028
|
const Timing = 'timing';
|
|
1028
|
-
const detailTabs = [Response, Timing];
|
|
1029
|
+
const detailTabs = [Preview, Response, Timing];
|
|
1029
1030
|
const isDetailTab = value => {
|
|
1030
|
-
return value === Response || value === Timing;
|
|
1031
|
+
return value === Response || value === Preview || value === Timing;
|
|
1031
1032
|
};
|
|
1032
1033
|
const getDetailTabLabel = value => {
|
|
1034
|
+
if (value === Preview) {
|
|
1035
|
+
return 'Preview';
|
|
1036
|
+
}
|
|
1033
1037
|
if (value === Timing) {
|
|
1034
1038
|
return 'Timing';
|
|
1035
1039
|
}
|
|
@@ -1161,334 +1165,20 @@ const diff = (oldState, newState) => {
|
|
|
1161
1165
|
|
|
1162
1166
|
const diff2 = uid => {
|
|
1163
1167
|
const {
|
|
1164
|
-
newState,
|
|
1165
|
-
oldState
|
|
1166
|
-
} = get(uid);
|
|
1167
|
-
return diff(oldState, newState);
|
|
1168
|
-
};
|
|
1169
|
-
|
|
1170
|
-
const
|
|
1171
|
-
|
|
1172
|
-
return startedEvent.toolName === finishedEvent.toolName;
|
|
1173
|
-
}
|
|
1174
|
-
return true;
|
|
1175
|
-
};
|
|
1176
|
-
|
|
1177
|
-
const isMatchingToolExecutionPair = (startedEvent, finishedEvent) => {
|
|
1178
|
-
return startedEvent.sessionId === finishedEvent.sessionId && hasMatchingToolName$1(startedEvent, finishedEvent);
|
|
1179
|
-
};
|
|
1180
|
-
|
|
1181
|
-
const startedEventType$1 = 'tool-execution-started';
|
|
1182
|
-
const finishedEventType$1 = 'tool-execution-finished';
|
|
1183
|
-
const mergedEventType = 'tool-execution';
|
|
1184
|
-
|
|
1185
|
-
const isToolExecutionFinishedEvent = event => {
|
|
1186
|
-
return event.type === finishedEventType$1;
|
|
1187
|
-
};
|
|
1188
|
-
|
|
1189
|
-
const isToolExecutionStartedEvent = event => {
|
|
1190
|
-
return event.type === startedEventType$1;
|
|
1191
|
-
};
|
|
1192
|
-
|
|
1193
|
-
const getTimestamp$1 = value => {
|
|
1194
|
-
return typeof value === 'string' || typeof value === 'number' ? value : undefined;
|
|
1195
|
-
};
|
|
1196
|
-
|
|
1197
|
-
const getEndedTimestamp = event => {
|
|
1198
|
-
return getTimestamp$1(event.ended) ?? getTimestamp$1(event.endTime) ?? getTimestamp$1(event.endTimestamp) ?? getTimestamp$1(event.timestamp);
|
|
1199
|
-
};
|
|
1200
|
-
|
|
1201
|
-
const eventStableIds = new WeakMap();
|
|
1202
|
-
const eventStableIdState = {
|
|
1203
|
-
nextStableEventId: 1
|
|
1204
|
-
};
|
|
1205
|
-
|
|
1206
|
-
const getOrCreateStableEventId = event => {
|
|
1207
|
-
const existingStableEventId = eventStableIds.get(event);
|
|
1208
|
-
if (existingStableEventId) {
|
|
1209
|
-
return existingStableEventId;
|
|
1210
|
-
}
|
|
1211
|
-
const stableEventId = `event-${eventStableIdState.nextStableEventId++}`;
|
|
1212
|
-
eventStableIds.set(event, stableEventId);
|
|
1213
|
-
return stableEventId;
|
|
1214
|
-
};
|
|
1215
|
-
|
|
1216
|
-
const getStartedTimestamp = event => {
|
|
1217
|
-
return getTimestamp$1(event.started) ?? getTimestamp$1(event.startTime) ?? getTimestamp$1(event.startTimestamp) ?? getTimestamp$1(event.timestamp);
|
|
1218
|
-
};
|
|
1219
|
-
|
|
1220
|
-
const setStableEventId = (event, stableEventId) => {
|
|
1221
|
-
eventStableIds.set(event, stableEventId);
|
|
1222
|
-
};
|
|
1223
|
-
|
|
1224
|
-
const mergeToolExecutionEvents$1 = (startedEvent, finishedEvent) => {
|
|
1225
|
-
const ended = getEndedTimestamp(finishedEvent);
|
|
1226
|
-
const {
|
|
1227
|
-
eventId
|
|
1228
|
-
} = startedEvent;
|
|
1229
|
-
const started = getStartedTimestamp(startedEvent);
|
|
1230
|
-
const mergedEvent = {
|
|
1231
|
-
...startedEvent,
|
|
1232
|
-
...finishedEvent,
|
|
1233
|
-
...(ended === undefined ? {} : {
|
|
1234
|
-
ended
|
|
1235
|
-
}),
|
|
1236
|
-
...(eventId === undefined ? {} : {
|
|
1237
|
-
eventId
|
|
1238
|
-
}),
|
|
1239
|
-
...(started === undefined ? {} : {
|
|
1240
|
-
started
|
|
1241
|
-
}),
|
|
1242
|
-
type: mergedEventType
|
|
1243
|
-
};
|
|
1244
|
-
const stableEventId = `${getOrCreateStableEventId(startedEvent)}:${getOrCreateStableEventId(finishedEvent)}`;
|
|
1245
|
-
setStableEventId(mergedEvent, stableEventId);
|
|
1246
|
-
return mergedEvent;
|
|
1247
|
-
};
|
|
1248
|
-
|
|
1249
|
-
const getStableEventId = event => {
|
|
1250
|
-
return getOrCreateStableEventId(event);
|
|
1251
|
-
};
|
|
1252
|
-
|
|
1253
|
-
const collapseToolExecutionEvents = events => {
|
|
1254
|
-
const collapsedEvents = [];
|
|
1255
|
-
for (let i = 0; i < events.length; i++) {
|
|
1256
|
-
const event = events[i];
|
|
1257
|
-
if (isToolExecutionStartedEvent(event)) {
|
|
1258
|
-
const nextEvent = events[i + 1];
|
|
1259
|
-
if (nextEvent && isToolExecutionFinishedEvent(nextEvent) && isMatchingToolExecutionPair(event, nextEvent)) {
|
|
1260
|
-
collapsedEvents.push(mergeToolExecutionEvents$1(event, nextEvent));
|
|
1261
|
-
i++;
|
|
1262
|
-
continue;
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
collapsedEvents.push(event);
|
|
1266
|
-
}
|
|
1267
|
-
return collapsedEvents;
|
|
1268
|
-
};
|
|
1269
|
-
|
|
1270
|
-
const getVisibleEvents = (events, showInputEvents, showResponsePartEvents, showEventStreamFinishedEvents) => {
|
|
1271
|
-
return events.filter(event => {
|
|
1272
|
-
if (!showInputEvents && event.type === 'handle-input') {
|
|
1273
|
-
return false;
|
|
1274
|
-
}
|
|
1275
|
-
if (!showResponsePartEvents && event.type === 'sse-response-part') {
|
|
1276
|
-
return false;
|
|
1277
|
-
}
|
|
1278
|
-
if (!showEventStreamFinishedEvents && event.type === 'event-stream-finished') {
|
|
1279
|
-
return false;
|
|
1280
|
-
}
|
|
1281
|
-
// hide session creation events by default — not useful in the debug view
|
|
1282
|
-
if (event.type === 'chat-session-created') {
|
|
1283
|
-
return false;
|
|
1284
|
-
}
|
|
1285
|
-
return true;
|
|
1286
|
-
});
|
|
1287
|
-
};
|
|
1288
|
-
|
|
1289
|
-
const isNetworkEvent = event => {
|
|
1290
|
-
const normalizedType = event.type.toLowerCase();
|
|
1291
|
-
return normalizedType === 'request' || normalizedType === 'response' || normalizedType === 'handle-response' || normalizedType.includes('fetch') || normalizedType.includes('xhr');
|
|
1292
|
-
};
|
|
1293
|
-
|
|
1294
|
-
const isStreamEvent = event => {
|
|
1295
|
-
return event.type === 'sse-response-part' || event.type === 'event-stream-finished';
|
|
1296
|
-
};
|
|
1297
|
-
|
|
1298
|
-
const toolEventTypePrefix = 'tool-execution';
|
|
1299
|
-
const isToolEvent = event => {
|
|
1300
|
-
return event.type.startsWith(toolEventTypePrefix);
|
|
1301
|
-
};
|
|
1302
|
-
|
|
1303
|
-
const isUiEvent = event => {
|
|
1304
|
-
return event.type.startsWith('handle-') && event.type !== 'handle-response';
|
|
1305
|
-
};
|
|
1306
|
-
|
|
1307
|
-
const matchesEventCategoryFilter = (event, eventCategoryFilter) => {
|
|
1308
|
-
switch (eventCategoryFilter) {
|
|
1309
|
-
case Network:
|
|
1310
|
-
return isNetworkEvent(event);
|
|
1311
|
-
case Stream:
|
|
1312
|
-
return isStreamEvent(event);
|
|
1313
|
-
case Tools:
|
|
1314
|
-
return isToolEvent(event);
|
|
1315
|
-
case Ui:
|
|
1316
|
-
return isUiEvent(event);
|
|
1317
|
-
default:
|
|
1318
|
-
return true;
|
|
1319
|
-
}
|
|
1320
|
-
};
|
|
1321
|
-
|
|
1322
|
-
const getFilteredEvents = (events, filterValue, eventCategoryFilter, showInputEvents, showResponsePartEvents, showEventStreamFinishedEvents) => {
|
|
1323
|
-
const visibleEvents = getVisibleEvents(events, showInputEvents, showResponsePartEvents, showEventStreamFinishedEvents);
|
|
1324
|
-
const collapsedEvents = collapseToolExecutionEvents(visibleEvents);
|
|
1325
|
-
const parsedFilter = parseFilterValue(filterValue);
|
|
1326
|
-
const activeEventCategoryFilter = parsedFilter.eventCategoryFilter === All ? eventCategoryFilter : parsedFilter.eventCategoryFilter;
|
|
1327
|
-
const filteredByCategory = collapsedEvents.filter(event => matchesEventCategoryFilter(event, activeEventCategoryFilter));
|
|
1328
|
-
const {
|
|
1329
|
-
filterText
|
|
1330
|
-
} = parsedFilter;
|
|
1331
|
-
if (!filterText) {
|
|
1332
|
-
return filteredByCategory;
|
|
1333
|
-
}
|
|
1334
|
-
return filteredByCategory.filter(event => JSON.stringify(event).toLowerCase().includes(filterText));
|
|
1335
|
-
};
|
|
1336
|
-
|
|
1337
|
-
const toTimeNumber = value => {
|
|
1338
|
-
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
1339
|
-
return value;
|
|
1340
|
-
}
|
|
1341
|
-
if (typeof value === 'string') {
|
|
1342
|
-
const timestamp = Date.parse(value);
|
|
1343
|
-
if (!Number.isNaN(timestamp)) {
|
|
1344
|
-
return timestamp;
|
|
1345
|
-
}
|
|
1346
|
-
}
|
|
1347
|
-
return undefined;
|
|
1348
|
-
};
|
|
1349
|
-
|
|
1350
|
-
const getEventTime = event => {
|
|
1351
|
-
return toTimeNumber(event.started ?? event.startTime ?? event.startTimestamp ?? event.timestamp);
|
|
1352
|
-
};
|
|
1353
|
-
|
|
1354
|
-
const maxBarUnits = 8;
|
|
1355
|
-
const parseTimelineSeconds = value => {
|
|
1356
|
-
const trimmed = value.trim();
|
|
1357
|
-
if (!trimmed) {
|
|
1358
|
-
return undefined;
|
|
1359
|
-
}
|
|
1360
|
-
const parsed = Number.parseFloat(trimmed);
|
|
1361
|
-
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
1362
|
-
return undefined;
|
|
1363
|
-
}
|
|
1364
|
-
return parsed;
|
|
1365
|
-
};
|
|
1366
|
-
const roundSeconds = value => {
|
|
1367
|
-
return Number(value.toFixed(3));
|
|
1368
|
-
};
|
|
1369
|
-
const getEventsWithTime = events => {
|
|
1370
|
-
return events.flatMap(event => {
|
|
1371
|
-
const time = getEventTime(event);
|
|
1372
|
-
if (time === undefined) {
|
|
1373
|
-
return [];
|
|
1374
|
-
}
|
|
1375
|
-
return [{
|
|
1376
|
-
event,
|
|
1377
|
-
time
|
|
1378
|
-
}];
|
|
1379
|
-
});
|
|
1380
|
-
};
|
|
1381
|
-
const getTimelineDurationSeconds = events => {
|
|
1382
|
-
const eventsWithTime = getEventsWithTime(events);
|
|
1383
|
-
if (eventsWithTime.length === 0) {
|
|
1384
|
-
return 0;
|
|
1385
|
-
}
|
|
1386
|
-
const baseTime = eventsWithTime[0].time;
|
|
1387
|
-
const lastTime = eventsWithTime.at(-1)?.time ?? baseTime;
|
|
1388
|
-
return roundSeconds(Math.max(0, lastTime - baseTime) / 1000);
|
|
1389
|
-
};
|
|
1390
|
-
const getSelectionPercent = (value, durationSeconds) => {
|
|
1391
|
-
if (durationSeconds <= 0) {
|
|
1392
|
-
return 0;
|
|
1393
|
-
}
|
|
1394
|
-
return Number((value / durationSeconds * 100).toFixed(3));
|
|
1395
|
-
};
|
|
1396
|
-
const getNormalizedRange = (durationSeconds, startValue, endValue) => {
|
|
1397
|
-
const parsedStart = parseTimelineSeconds(startValue);
|
|
1398
|
-
const parsedEnd = parseTimelineSeconds(endValue);
|
|
1399
|
-
if (parsedStart === undefined && parsedEnd === undefined) {
|
|
1400
|
-
return {
|
|
1401
|
-
endSeconds: null,
|
|
1402
|
-
hasSelection: false,
|
|
1403
|
-
startSeconds: null
|
|
1404
|
-
};
|
|
1405
|
-
}
|
|
1406
|
-
const rawStart = parsedStart ?? 0;
|
|
1407
|
-
const rawEnd = parsedEnd ?? durationSeconds;
|
|
1408
|
-
const normalizedStart = Math.max(0, Math.min(durationSeconds, Math.min(rawStart, rawEnd)));
|
|
1409
|
-
const normalizedEnd = Math.max(0, Math.min(durationSeconds, Math.max(rawStart, rawEnd)));
|
|
1410
|
-
return {
|
|
1411
|
-
endSeconds: roundSeconds(normalizedEnd),
|
|
1412
|
-
hasSelection: true,
|
|
1413
|
-
startSeconds: roundSeconds(normalizedStart)
|
|
1414
|
-
};
|
|
1415
|
-
};
|
|
1416
|
-
const filterEventsByTimelineRange = (events, startValue, endValue) => {
|
|
1417
|
-
const eventsWithTime = getEventsWithTime(events);
|
|
1418
|
-
if (eventsWithTime.length === 0) {
|
|
1419
|
-
return events;
|
|
1420
|
-
}
|
|
1421
|
-
const baseTime = eventsWithTime[0].time;
|
|
1422
|
-
const lastTime = eventsWithTime.at(-1)?.time ?? baseTime;
|
|
1423
|
-
const durationSeconds = roundSeconds(Math.max(0, lastTime - baseTime) / 1000);
|
|
1424
|
-
const range = getNormalizedRange(durationSeconds, startValue, endValue);
|
|
1425
|
-
if (!range.hasSelection || range.startSeconds === null || range.endSeconds === null) {
|
|
1426
|
-
return events;
|
|
1427
|
-
}
|
|
1428
|
-
const startTime = baseTime + range.startSeconds * 1000;
|
|
1429
|
-
const endTime = baseTime + range.endSeconds * 1000;
|
|
1430
|
-
return eventsWithTime.filter(item => item.time >= startTime && item.time <= endTime).map(item => item.event);
|
|
1431
|
-
};
|
|
1432
|
-
const getTimelineInfo = (events, startValue, endValue) => {
|
|
1433
|
-
const eventsWithTime = getEventsWithTime(events);
|
|
1434
|
-
if (eventsWithTime.length === 0) {
|
|
1435
|
-
return {
|
|
1436
|
-
buckets: [],
|
|
1437
|
-
durationSeconds: 0,
|
|
1438
|
-
endSeconds: null,
|
|
1439
|
-
hasSelection: false,
|
|
1440
|
-
selectionEndPercent: null,
|
|
1441
|
-
selectionStartPercent: null,
|
|
1442
|
-
startSeconds: null
|
|
1443
|
-
};
|
|
1444
|
-
}
|
|
1445
|
-
const baseTime = eventsWithTime[0].time;
|
|
1446
|
-
const lastTime = eventsWithTime.at(-1)?.time ?? baseTime;
|
|
1447
|
-
const durationMs = Math.max(0, lastTime - baseTime);
|
|
1448
|
-
const durationSeconds = roundSeconds(durationMs / 1000);
|
|
1449
|
-
const range = getNormalizedRange(durationSeconds, startValue, endValue);
|
|
1450
|
-
const bucketCount = durationSeconds === 0 ? 1 : Math.max(12, Math.min(48, Math.ceil(durationSeconds)));
|
|
1451
|
-
const bucketDurationMs = durationMs === 0 ? 1000 : durationMs / bucketCount;
|
|
1452
|
-
const counts = Array.from({
|
|
1453
|
-
length: bucketCount
|
|
1454
|
-
}).fill(0);
|
|
1455
|
-
for (const item of eventsWithTime) {
|
|
1456
|
-
const offsetMs = item.time - baseTime;
|
|
1457
|
-
const index = durationMs === 0 ? 0 : Math.min(bucketCount - 1, Math.floor(offsetMs / durationMs * bucketCount));
|
|
1458
|
-
counts[index] += 1;
|
|
1459
|
-
}
|
|
1460
|
-
const maxCount = Math.max(...counts);
|
|
1461
|
-
const selectionStartPercent = range.hasSelection && range.startSeconds !== null ? getSelectionPercent(range.startSeconds, durationSeconds) : null;
|
|
1462
|
-
const selectionEndPercent = range.hasSelection && range.endSeconds !== null ? getSelectionPercent(range.endSeconds, durationSeconds) : null;
|
|
1463
|
-
const buckets = counts.map((count, index) => {
|
|
1464
|
-
const bucketStartMs = index * bucketDurationMs;
|
|
1465
|
-
const bucketEndMs = index === bucketCount - 1 ? durationMs : (index + 1) * bucketDurationMs;
|
|
1466
|
-
const hasSelection = range.hasSelection && range.startSeconds !== null && range.endSeconds !== null;
|
|
1467
|
-
const selectionStartMs = hasSelection ? range.startSeconds * 1000 : 0;
|
|
1468
|
-
const selectionEndMs = hasSelection ? range.endSeconds * 1000 : 0;
|
|
1469
|
-
return {
|
|
1470
|
-
count,
|
|
1471
|
-
endSeconds: roundSeconds(bucketEndMs / 1000),
|
|
1472
|
-
isSelected: hasSelection && bucketEndMs >= selectionStartMs && bucketStartMs <= selectionEndMs,
|
|
1473
|
-
startSeconds: roundSeconds(bucketStartMs / 1000),
|
|
1474
|
-
unitCount: count === 0 ? 0 : Math.max(1, Math.round(count / maxCount * maxBarUnits))
|
|
1475
|
-
};
|
|
1476
|
-
});
|
|
1477
|
-
return {
|
|
1478
|
-
buckets,
|
|
1479
|
-
durationSeconds,
|
|
1480
|
-
endSeconds: range.endSeconds,
|
|
1481
|
-
hasSelection: range.hasSelection,
|
|
1482
|
-
selectionEndPercent,
|
|
1483
|
-
selectionStartPercent,
|
|
1484
|
-
startSeconds: range.startSeconds
|
|
1485
|
-
};
|
|
1168
|
+
newState,
|
|
1169
|
+
oldState
|
|
1170
|
+
} = get(uid);
|
|
1171
|
+
return diff(oldState, newState);
|
|
1172
|
+
};
|
|
1173
|
+
|
|
1174
|
+
const handleDetailsContextMenu = state => {
|
|
1175
|
+
return state;
|
|
1486
1176
|
};
|
|
1487
1177
|
|
|
1488
1178
|
// cspell:ignore IDBP
|
|
1489
1179
|
|
|
1490
|
-
const startedEventType = 'tool-execution-started';
|
|
1491
|
-
const finishedEventType = 'tool-execution-finished';
|
|
1180
|
+
const startedEventType$1 = 'tool-execution-started';
|
|
1181
|
+
const finishedEventType$1 = 'tool-execution-finished';
|
|
1492
1182
|
const getRawEventBySessionIdAndEventId = async (store, sessionId, sessionIdIndexName, eventId) => {
|
|
1493
1183
|
if (eventId < 1) {
|
|
1494
1184
|
return undefined;
|
|
@@ -1510,18 +1200,18 @@ const getRawEventBySessionIdAndEventId = async (store, sessionId, sessionIdIndex
|
|
|
1510
1200
|
const events = all.filter(event => event.sessionId === sessionId);
|
|
1511
1201
|
return events[eventId - 1];
|
|
1512
1202
|
};
|
|
1513
|
-
const getTimestamp = value => {
|
|
1203
|
+
const getTimestamp$1 = value => {
|
|
1514
1204
|
return typeof value === 'string' || typeof value === 'number' ? value : undefined;
|
|
1515
1205
|
};
|
|
1516
|
-
const hasMatchingToolName = (startedEvent, finishedEvent) => {
|
|
1206
|
+
const hasMatchingToolName$1 = (startedEvent, finishedEvent) => {
|
|
1517
1207
|
if (typeof startedEvent.toolName === 'string' && typeof finishedEvent.toolName === 'string') {
|
|
1518
1208
|
return startedEvent.toolName === finishedEvent.toolName;
|
|
1519
1209
|
}
|
|
1520
1210
|
return true;
|
|
1521
1211
|
};
|
|
1522
|
-
const mergeToolExecutionEvents = (startedEvent, finishedEvent, eventId) => {
|
|
1523
|
-
const ended = getTimestamp(finishedEvent.ended) ?? getTimestamp(finishedEvent.endTime) ?? getTimestamp(finishedEvent.timestamp);
|
|
1524
|
-
const started = getTimestamp(startedEvent.started) ?? getTimestamp(startedEvent.startTime) ?? getTimestamp(startedEvent.timestamp);
|
|
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);
|
|
1525
1215
|
return {
|
|
1526
1216
|
...startedEvent,
|
|
1527
1217
|
...finishedEvent,
|
|
@@ -1546,20 +1236,20 @@ const getEventDetailsBySessionIdAndEventId = async (store, sessionId, sessionIdI
|
|
|
1546
1236
|
eventId
|
|
1547
1237
|
};
|
|
1548
1238
|
}
|
|
1549
|
-
if (event.type !== startedEventType) {
|
|
1239
|
+
if (event.type !== startedEventType$1) {
|
|
1550
1240
|
return {
|
|
1551
1241
|
...event,
|
|
1552
1242
|
eventId
|
|
1553
1243
|
};
|
|
1554
1244
|
}
|
|
1555
1245
|
const nextEvent = await getRawEventBySessionIdAndEventId(store, sessionId, sessionIdIndexName, eventId + 1);
|
|
1556
|
-
if (!nextEvent || nextEvent.type !== finishedEventType || nextEvent.sessionId !== sessionId || !hasMatchingToolName(event, nextEvent)) {
|
|
1246
|
+
if (!nextEvent || nextEvent.type !== finishedEventType$1 || nextEvent.sessionId !== sessionId || !hasMatchingToolName$1(event, nextEvent)) {
|
|
1557
1247
|
return {
|
|
1558
1248
|
...event,
|
|
1559
1249
|
eventId
|
|
1560
1250
|
};
|
|
1561
1251
|
}
|
|
1562
|
-
return mergeToolExecutionEvents(event, nextEvent, eventId);
|
|
1252
|
+
return mergeToolExecutionEvents$1(event, nextEvent, eventId);
|
|
1563
1253
|
};
|
|
1564
1254
|
|
|
1565
1255
|
const instanceOfAny = (object, constructors) => constructors.some(c => object instanceof c);
|
|
@@ -1819,48 +1509,352 @@ replaceTraps(oldTraps => ({
|
|
|
1819
1509
|
const openDatabaseDependencies = {
|
|
1820
1510
|
openDB: openDB
|
|
1821
1511
|
};
|
|
1822
|
-
const openDatabase = async (databaseName, dataBaseVersion) => {
|
|
1823
|
-
return openDatabaseDependencies.openDB(databaseName, dataBaseVersion);
|
|
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;
|
|
1633
|
+
};
|
|
1634
|
+
|
|
1635
|
+
const getVisibleEvents = (events, showInputEvents, showResponsePartEvents, showEventStreamFinishedEvents) => {
|
|
1636
|
+
return events.filter(event => {
|
|
1637
|
+
if (!showInputEvents && event.type === 'handle-input') {
|
|
1638
|
+
return false;
|
|
1639
|
+
}
|
|
1640
|
+
if (!showResponsePartEvents && event.type === 'sse-response-part') {
|
|
1641
|
+
return false;
|
|
1642
|
+
}
|
|
1643
|
+
if (!showEventStreamFinishedEvents && event.type === 'event-stream-finished') {
|
|
1644
|
+
return false;
|
|
1645
|
+
}
|
|
1646
|
+
// hide session creation events by default — not useful in the debug view
|
|
1647
|
+
if (event.type === 'chat-session-created') {
|
|
1648
|
+
return false;
|
|
1649
|
+
}
|
|
1650
|
+
return true;
|
|
1651
|
+
});
|
|
1652
|
+
};
|
|
1653
|
+
|
|
1654
|
+
const isNetworkEvent = event => {
|
|
1655
|
+
const normalizedType = event.type.toLowerCase();
|
|
1656
|
+
return normalizedType === 'request' || normalizedType === 'response' || normalizedType === 'handle-response' || normalizedType.includes('fetch') || normalizedType.includes('xhr');
|
|
1657
|
+
};
|
|
1658
|
+
|
|
1659
|
+
const isStreamEvent = event => {
|
|
1660
|
+
return event.type === 'sse-response-part' || event.type === 'event-stream-finished';
|
|
1661
|
+
};
|
|
1662
|
+
|
|
1663
|
+
const toolEventTypePrefix = 'tool-execution';
|
|
1664
|
+
const isToolEvent = event => {
|
|
1665
|
+
return event.type.startsWith(toolEventTypePrefix);
|
|
1666
|
+
};
|
|
1667
|
+
|
|
1668
|
+
const isUiEvent = event => {
|
|
1669
|
+
return event.type.startsWith('handle-') && event.type !== 'handle-response';
|
|
1670
|
+
};
|
|
1671
|
+
|
|
1672
|
+
const matchesEventCategoryFilter = (event, eventCategoryFilter) => {
|
|
1673
|
+
switch (eventCategoryFilter) {
|
|
1674
|
+
case Network:
|
|
1675
|
+
return isNetworkEvent(event);
|
|
1676
|
+
case Stream:
|
|
1677
|
+
return isStreamEvent(event);
|
|
1678
|
+
case Tools:
|
|
1679
|
+
return isToolEvent(event);
|
|
1680
|
+
case Ui:
|
|
1681
|
+
return isUiEvent(event);
|
|
1682
|
+
default:
|
|
1683
|
+
return true;
|
|
1684
|
+
}
|
|
1685
|
+
};
|
|
1686
|
+
|
|
1687
|
+
const getFilteredEvents = (events, filterValue, eventCategoryFilter, showInputEvents, showResponsePartEvents, showEventStreamFinishedEvents) => {
|
|
1688
|
+
const visibleEvents = getVisibleEvents(events, showInputEvents, showResponsePartEvents, showEventStreamFinishedEvents);
|
|
1689
|
+
const collapsedEvents = collapseToolExecutionEvents(visibleEvents);
|
|
1690
|
+
const parsedFilter = parseFilterValue(filterValue);
|
|
1691
|
+
const activeEventCategoryFilter = parsedFilter.eventCategoryFilter === All ? eventCategoryFilter : parsedFilter.eventCategoryFilter;
|
|
1692
|
+
const filteredByCategory = collapsedEvents.filter(event => matchesEventCategoryFilter(event, activeEventCategoryFilter));
|
|
1693
|
+
const {
|
|
1694
|
+
filterText
|
|
1695
|
+
} = parsedFilter;
|
|
1696
|
+
if (!filterText) {
|
|
1697
|
+
return filteredByCategory;
|
|
1698
|
+
}
|
|
1699
|
+
return filteredByCategory.filter(event => JSON.stringify(event).toLowerCase().includes(filterText));
|
|
1700
|
+
};
|
|
1701
|
+
|
|
1702
|
+
const toTimeNumber = value => {
|
|
1703
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
1704
|
+
return value;
|
|
1705
|
+
}
|
|
1706
|
+
if (typeof value === 'string') {
|
|
1707
|
+
const timestamp = Date.parse(value);
|
|
1708
|
+
if (!Number.isNaN(timestamp)) {
|
|
1709
|
+
return timestamp;
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
return undefined;
|
|
1713
|
+
};
|
|
1714
|
+
|
|
1715
|
+
const getEventTime = event => {
|
|
1716
|
+
return toTimeNumber(event.started ?? event.startTime ?? event.startTimestamp ?? event.timestamp);
|
|
1717
|
+
};
|
|
1718
|
+
|
|
1719
|
+
const maxBarUnits = 8;
|
|
1720
|
+
const parseTimelineSeconds = value => {
|
|
1721
|
+
const trimmed = value.trim();
|
|
1722
|
+
if (!trimmed) {
|
|
1723
|
+
return undefined;
|
|
1724
|
+
}
|
|
1725
|
+
const parsed = Number.parseFloat(trimmed);
|
|
1726
|
+
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
1727
|
+
return undefined;
|
|
1728
|
+
}
|
|
1729
|
+
return parsed;
|
|
1730
|
+
};
|
|
1731
|
+
const roundSeconds = value => {
|
|
1732
|
+
return Number(value.toFixed(3));
|
|
1733
|
+
};
|
|
1734
|
+
const getEventsWithTime = events => {
|
|
1735
|
+
return events.flatMap(event => {
|
|
1736
|
+
const time = getEventTime(event);
|
|
1737
|
+
if (time === undefined) {
|
|
1738
|
+
return [];
|
|
1739
|
+
}
|
|
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;
|
|
1758
|
+
}
|
|
1759
|
+
return Number((value / durationSeconds * 100).toFixed(3));
|
|
1760
|
+
};
|
|
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
|
+
};
|
|
1770
|
+
}
|
|
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
|
+
};
|
|
1824
1780
|
};
|
|
1825
|
-
|
|
1826
|
-
const
|
|
1827
|
-
|
|
1828
|
-
|
|
1781
|
+
const filterEventsByTimelineRange = (events, startValue, endValue) => {
|
|
1782
|
+
const eventsWithTime = getEventsWithTime(events);
|
|
1783
|
+
if (eventsWithTime.length === 0) {
|
|
1784
|
+
return events;
|
|
1785
|
+
}
|
|
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;
|
|
1792
|
+
}
|
|
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);
|
|
1829
1796
|
};
|
|
1830
|
-
const
|
|
1831
|
-
const
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
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;
|
|
1842
1824
|
}
|
|
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
|
+
};
|
|
1843
1851
|
};
|
|
1844
1852
|
|
|
1845
|
-
const handleEventRowClickDependencies = {
|
|
1846
|
-
loadSelectedEvent: loadSelectedEvent
|
|
1847
|
-
};
|
|
1848
1853
|
const getCurrentEvents$2 = state => {
|
|
1849
1854
|
const filteredEvents = getFilteredEvents(state.events, state.filterValue, state.eventCategoryFilter, state.showInputEvents, state.showResponsePartEvents, state.showEventStreamFinishedEvents);
|
|
1850
1855
|
return filterEventsByTimelineRange(filteredEvents, state.timelineStartSeconds, state.timelineEndSeconds);
|
|
1851
1856
|
};
|
|
1852
|
-
const
|
|
1853
|
-
const parsed = Number.parseInt(value, 10);
|
|
1854
|
-
if (Number.isNaN(parsed) || parsed < 0) {
|
|
1855
|
-
return null;
|
|
1856
|
-
}
|
|
1857
|
-
return parsed;
|
|
1858
|
-
};
|
|
1859
|
-
const handleEventRowClick = async (state, value) => {
|
|
1860
|
-
const selectedEventIndex = parseSelectedEventIndex$1(value);
|
|
1861
|
-
if (selectedEventIndex === null) {
|
|
1862
|
-
return state;
|
|
1863
|
-
}
|
|
1857
|
+
const selectEventAtIndex = async (state, selectedEventIndex, dependencies) => {
|
|
1864
1858
|
const currentEvents = getCurrentEvents$2(state);
|
|
1865
1859
|
const selectedEvent = currentEvents[selectedEventIndex];
|
|
1866
1860
|
if (!selectedEvent) {
|
|
@@ -1879,7 +1873,7 @@ const handleEventRowClick = async (state, value) => {
|
|
|
1879
1873
|
selectedEventIndex
|
|
1880
1874
|
};
|
|
1881
1875
|
}
|
|
1882
|
-
const selectedEventDetails = await
|
|
1876
|
+
const selectedEventDetails = await dependencies.loadSelectedEvent(state.databaseName, state.dataBaseVersion, state.eventStoreName, state.sessionId, state.sessionIdIndexName, selectedEvent.eventId, selectedEvent.type);
|
|
1883
1877
|
return {
|
|
1884
1878
|
...state,
|
|
1885
1879
|
selectedEvent: selectedEventDetails ?? selectedEvent,
|
|
@@ -1888,6 +1882,34 @@ const handleEventRowClick = async (state, value) => {
|
|
|
1888
1882
|
};
|
|
1889
1883
|
};
|
|
1890
1884
|
|
|
1885
|
+
const handleEventRowClickDependencies = {
|
|
1886
|
+
loadSelectedEvent: loadSelectedEvent
|
|
1887
|
+
};
|
|
1888
|
+
const isPrimaryButton = button => {
|
|
1889
|
+
return button === 0;
|
|
1890
|
+
};
|
|
1891
|
+
const parseSelectedEventIndex$1 = value => {
|
|
1892
|
+
const parsed = Number.parseInt(value, 10);
|
|
1893
|
+
if (Number.isNaN(parsed) || parsed < 0) {
|
|
1894
|
+
return null;
|
|
1895
|
+
}
|
|
1896
|
+
return parsed;
|
|
1897
|
+
};
|
|
1898
|
+
const handleEventRowClick = async (state, value, button) => {
|
|
1899
|
+
if (!isPrimaryButton(button)) {
|
|
1900
|
+
return state;
|
|
1901
|
+
}
|
|
1902
|
+
const selectedEventIndex = parseSelectedEventIndex$1(value);
|
|
1903
|
+
if (selectedEventIndex === null) {
|
|
1904
|
+
return state;
|
|
1905
|
+
}
|
|
1906
|
+
return selectEventAtIndex(state, selectedEventIndex, handleEventRowClickDependencies);
|
|
1907
|
+
};
|
|
1908
|
+
|
|
1909
|
+
const handleHeaderContextMenu = state => {
|
|
1910
|
+
return state;
|
|
1911
|
+
};
|
|
1912
|
+
|
|
1891
1913
|
const getBoolean = value => {
|
|
1892
1914
|
return value === true || value === 'true' || value === 'on' || value === '1';
|
|
1893
1915
|
};
|
|
@@ -2110,7 +2132,15 @@ const handleTimelineDoubleClick = state => {
|
|
|
2110
2132
|
};
|
|
2111
2133
|
|
|
2112
2134
|
const getTimelineEvents = state => {
|
|
2113
|
-
|
|
2135
|
+
const {
|
|
2136
|
+
eventCategoryFilter,
|
|
2137
|
+
events,
|
|
2138
|
+
filterValue,
|
|
2139
|
+
showEventStreamFinishedEvents,
|
|
2140
|
+
showInputEvents,
|
|
2141
|
+
showResponsePartEvents
|
|
2142
|
+
} = state;
|
|
2143
|
+
return getFilteredEvents(events, filterValue, eventCategoryFilter, showInputEvents, showResponsePartEvents, showEventStreamFinishedEvents);
|
|
2114
2144
|
};
|
|
2115
2145
|
|
|
2116
2146
|
const getTimelineLeft = state => {
|
|
@@ -2901,12 +2931,26 @@ const getCss = state => {
|
|
|
2901
2931
|
white-space: nowrap;
|
|
2902
2932
|
min-width: 0;
|
|
2903
2933
|
font-size: 11px;
|
|
2904
|
-
text-transform: uppercase;
|
|
2905
2934
|
letter-spacing: 0.04em;
|
|
2906
2935
|
opacity: 0.8;
|
|
2907
2936
|
contain: content;
|
|
2908
2937
|
}
|
|
2909
2938
|
|
|
2939
|
+
.ChatDebugViewTableHeaderRow > .ChatDebugViewHeaderCell:nth-child(1) {
|
|
2940
|
+
flex: 1 1 140px;
|
|
2941
|
+
min-width: 0;
|
|
2942
|
+
}
|
|
2943
|
+
|
|
2944
|
+
.ChatDebugViewTableHeaderRow > .ChatDebugViewHeaderCell:nth-child(2) {
|
|
2945
|
+
flex: 0 0 90px;
|
|
2946
|
+
justify-content: flex-end;
|
|
2947
|
+
}
|
|
2948
|
+
|
|
2949
|
+
.ChatDebugViewTableHeaderRow > .ChatDebugViewHeaderCell:nth-child(3) {
|
|
2950
|
+
flex: 0 0 96px;
|
|
2951
|
+
justify-content: flex-end;
|
|
2952
|
+
}
|
|
2953
|
+
|
|
2910
2954
|
.ChatDebugViewTableBody {
|
|
2911
2955
|
display: flex;
|
|
2912
2956
|
flex-direction: column;
|
|
@@ -2936,8 +2980,12 @@ const getCss = state => {
|
|
|
2936
2980
|
|
|
2937
2981
|
.ChatDebugViewEventRow {
|
|
2938
2982
|
padding: 2px 8px;
|
|
2939
|
-
|
|
2940
|
-
cursor:
|
|
2983
|
+
background: color-mix(in srgb, var(--vscode-editorWidget-background, transparent) 92%, var(--vscode-list-hoverBackground, rgba(90, 93, 94, 0.31)) 8%);
|
|
2984
|
+
cursor: default;
|
|
2985
|
+
}
|
|
2986
|
+
|
|
2987
|
+
.ChatDebugViewTableBody > .ChatDebugViewEventRow:nth-child(even) {
|
|
2988
|
+
background: color-mix(in srgb, var(--vscode-editorWidget-background, transparent) 84%, var(--vscode-list-hoverBackground, rgba(90, 93, 94, 0.31)) 16%);
|
|
2941
2989
|
}
|
|
2942
2990
|
|
|
2943
2991
|
.ChatDebugViewEventRow:hover {
|
|
@@ -2952,6 +3000,7 @@ const getCss = state => {
|
|
|
2952
3000
|
text-overflow: ellipsis;
|
|
2953
3001
|
white-space: nowrap;
|
|
2954
3002
|
min-width: 0;
|
|
3003
|
+
pointer-events: none;
|
|
2955
3004
|
contain: content;
|
|
2956
3005
|
}
|
|
2957
3006
|
|
|
@@ -2977,6 +3026,10 @@ const getCss = state => {
|
|
|
2977
3026
|
text-align: right;
|
|
2978
3027
|
}
|
|
2979
3028
|
|
|
3029
|
+
.ChatDebugViewCellStatusError {
|
|
3030
|
+
color: var(--vscode-errorForeground, #f14c4c);
|
|
3031
|
+
}
|
|
3032
|
+
|
|
2980
3033
|
.ChatDebugViewDetails {
|
|
2981
3034
|
border: 1px solid var(--vscode-editorWidget-border, #454545);
|
|
2982
3035
|
border-radius: 6px;
|
|
@@ -2995,6 +3048,7 @@ const getCss = state => {
|
|
|
2995
3048
|
gap: 8px;
|
|
2996
3049
|
padding: 0 8px;
|
|
2997
3050
|
border-bottom: 1px solid var(--vscode-editorWidget-border, #454545);
|
|
3051
|
+
background: color-mix(in srgb, var(--vscode-editorWidget-background, transparent) 72%, var(--vscode-list-hoverBackground, rgba(90, 93, 94, 0.18)) 28%);
|
|
2998
3052
|
contain: content;
|
|
2999
3053
|
}
|
|
3000
3054
|
|
|
@@ -3071,7 +3125,7 @@ const getCss = state => {
|
|
|
3071
3125
|
color: var(--vscode-descriptionForeground, var(--vscode-foreground, #cccccc));
|
|
3072
3126
|
cursor: pointer;
|
|
3073
3127
|
white-space: nowrap;
|
|
3074
|
-
contain:
|
|
3128
|
+
contain: content;
|
|
3075
3129
|
}
|
|
3076
3130
|
|
|
3077
3131
|
.ChatDebugViewDetailsTab:hover {
|
|
@@ -3080,7 +3134,7 @@ const getCss = state => {
|
|
|
3080
3134
|
|
|
3081
3135
|
.ChatDebugViewDetailsTabSelected {
|
|
3082
3136
|
border-bottom-color: var(--vscode-focusBorder, #007fd4);
|
|
3083
|
-
color: var(--vscode-
|
|
3137
|
+
color: var(--vscode-focusBorder, #007fd4);
|
|
3084
3138
|
}
|
|
3085
3139
|
|
|
3086
3140
|
.ChatDebugViewDetailsPanel {
|
|
@@ -3138,17 +3192,18 @@ const getCss = state => {
|
|
|
3138
3192
|
.row {
|
|
3139
3193
|
display: flex;
|
|
3140
3194
|
align-items: baseline;
|
|
3195
|
+
gap: 12px;
|
|
3141
3196
|
min-width: 100%;
|
|
3142
3197
|
width: max-content;
|
|
3143
3198
|
white-space: nowrap;
|
|
3144
|
-
contain:
|
|
3199
|
+
contain: strict;
|
|
3200
|
+
height: 20px;
|
|
3145
3201
|
}
|
|
3146
3202
|
|
|
3147
3203
|
.ChatDebugViewEventLineNumber {
|
|
3148
3204
|
display: flex;
|
|
3149
3205
|
justify-content: flex-end;
|
|
3150
3206
|
flex: 0 0 3ch;
|
|
3151
|
-
margin-right: 12px;
|
|
3152
3207
|
opacity: 0.6;
|
|
3153
3208
|
user-select: none;
|
|
3154
3209
|
contain: content;
|
|
@@ -3170,9 +3225,6 @@ const getCss = state => {
|
|
|
3170
3225
|
display: flex;
|
|
3171
3226
|
flex-direction: column;
|
|
3172
3227
|
width: 100%;
|
|
3173
|
-
border: 1px solid var(--vscode-editorWidget-border, #454545);
|
|
3174
|
-
border-radius: 6px;
|
|
3175
|
-
overflow: hidden;
|
|
3176
3228
|
contain: strict;
|
|
3177
3229
|
flex: 1;
|
|
3178
3230
|
}
|
|
@@ -3578,14 +3630,87 @@ const diffTree = (oldNodes, newNodes) => {
|
|
|
3578
3630
|
return removeTrailingNavigationPatches(patches);
|
|
3579
3631
|
};
|
|
3580
3632
|
|
|
3633
|
+
const ChatDebugView = 'ChatDebugView';
|
|
3634
|
+
const ChatDebugViewDevtools = 'ChatDebugView--devtools';
|
|
3635
|
+
const ChatDebugViewDetails = 'ChatDebugViewDetails';
|
|
3636
|
+
const ChatDebugViewDetailsBody = 'ChatDebugViewDetailsBody';
|
|
3637
|
+
const ChatDebugViewDetailsClose = 'ChatDebugViewDetailsClose';
|
|
3638
|
+
const ChatDebugViewDetailsPanel = 'ChatDebugViewDetailsPanel';
|
|
3639
|
+
const ChatDebugViewDetailsTab = 'ChatDebugViewDetailsTab';
|
|
3640
|
+
const ChatDebugViewDetailsTabSelected = 'ChatDebugViewDetailsTabSelected';
|
|
3641
|
+
const ChatDebugViewDetailsTabs = 'ChatDebugViewDetailsTabs';
|
|
3642
|
+
const ChatDebugViewDetailsTop = 'ChatDebugViewDetailsTop';
|
|
3643
|
+
const ChatDebugViewDevtoolsMain = 'ChatDebugViewDevtoolsMain';
|
|
3644
|
+
const ChatDebugViewDevtoolsSplit = 'ChatDebugViewDevtoolsSplit';
|
|
3645
|
+
const ChatDebugViewEmpty = 'ChatDebugViewEmpty';
|
|
3646
|
+
const ChatDebugViewError = 'ChatDebugViewError';
|
|
3647
|
+
const ChatDebugViewEvent = 'ChatDebugViewEvent';
|
|
3648
|
+
const ChatDebugViewEventLineContent = 'ChatDebugViewEventLineContent';
|
|
3649
|
+
const ChatDebugViewEventLineNumber = 'ChatDebugViewEventLineNumber';
|
|
3650
|
+
const ChatDebugViewEventRow = 'ChatDebugViewEventRow';
|
|
3651
|
+
const ChatDebugViewEventRowSelected = 'ChatDebugViewEventRowSelected';
|
|
3652
|
+
const ChatDebugViewEvents = 'ChatDebugViewEvents';
|
|
3653
|
+
const ChatDebugViewEventsFullWidth = 'ChatDebugViewEventsFullWidth';
|
|
3654
|
+
const ChatDebugViewFilterInput = 'ChatDebugViewFilterInput';
|
|
3655
|
+
const ChatDebugViewFilterInputDevtools = 'ChatDebugViewFilterInput--devtools';
|
|
3656
|
+
const ChatDebugViewHeaderCell = 'ChatDebugViewHeaderCell';
|
|
3657
|
+
const ChatDebugViewQuickFilterInput = 'ChatDebugViewQuickFilterInput';
|
|
3658
|
+
const ChatDebugViewQuickFilterPill = 'ChatDebugViewQuickFilterPill';
|
|
3659
|
+
const ChatDebugViewQuickFilterPillSelected = 'ChatDebugViewQuickFilterPillSelected';
|
|
3660
|
+
const ChatDebugViewQuickFilters = 'ChatDebugViewQuickFilters';
|
|
3661
|
+
const ChatDebugViewSash = 'ChatDebugViewSash';
|
|
3662
|
+
const ChatDebugViewSashLine = 'ChatDebugViewSashLine';
|
|
3663
|
+
const ChatDebugViewTable = 'ChatDebugViewTable';
|
|
3664
|
+
const ChatDebugViewTableBody = 'ChatDebugViewTableBody';
|
|
3665
|
+
const ChatDebugViewTableHeader = 'ChatDebugViewTableHeader';
|
|
3666
|
+
const ChatDebugViewTableHeaderRow = 'ChatDebugViewTableHeaderRow';
|
|
3667
|
+
const ChatDebugViewTimeline = 'ChatDebugViewTimeline';
|
|
3668
|
+
const ChatDebugViewTimelineBucket = 'ChatDebugViewTimelineBucket';
|
|
3669
|
+
const ChatDebugViewTimelineBucketBar = 'ChatDebugViewTimelineBucketBar';
|
|
3670
|
+
const ChatDebugViewTimelineBucketBarSelected = 'ChatDebugViewTimelineBucketBarSelected';
|
|
3671
|
+
const ChatDebugViewTimelineBucketSelected = 'ChatDebugViewTimelineBucketSelected';
|
|
3672
|
+
const ChatDebugViewTimelineBucketUnit = 'ChatDebugViewTimelineBucketUnit';
|
|
3673
|
+
const ChatDebugViewTimelineBucketUnitEmpty = 'ChatDebugViewTimelineBucketUnitEmpty';
|
|
3674
|
+
const ChatDebugViewTimelineBuckets = 'ChatDebugViewTimelineBuckets';
|
|
3675
|
+
const ChatDebugViewTimelineInteractive = 'ChatDebugViewTimelineInteractive';
|
|
3676
|
+
const ChatDebugViewTimelinePresetInput = 'ChatDebugViewTimelinePresetInput';
|
|
3677
|
+
const ChatDebugViewTimelineSelectionMarker = 'ChatDebugViewTimelineSelectionMarker';
|
|
3678
|
+
const ChatDebugViewTimelineSelectionMarkerEnd = 'ChatDebugViewTimelineSelectionMarkerEnd';
|
|
3679
|
+
const ChatDebugViewTimelineSelectionMarkerStart = 'ChatDebugViewTimelineSelectionMarkerStart';
|
|
3680
|
+
const ChatDebugViewTimelineSelectionOverlay = 'ChatDebugViewTimelineSelectionOverlay';
|
|
3681
|
+
const ChatDebugViewTimelineSelectionRange = 'ChatDebugViewTimelineSelectionRange';
|
|
3682
|
+
const ChatDebugViewTimelineSummary = 'ChatDebugViewTimelineSummary';
|
|
3683
|
+
const ChatDebugViewTimelineTop = 'ChatDebugViewTimelineTop';
|
|
3684
|
+
const ChatDebugViewTiming = 'ChatDebugViewTiming';
|
|
3685
|
+
const ChatDebugViewTimingLabel = 'ChatDebugViewTimingLabel';
|
|
3686
|
+
const ChatDebugViewTimingRow = 'ChatDebugViewTimingRow';
|
|
3687
|
+
const ChatDebugViewTimingValue = 'ChatDebugViewTimingValue';
|
|
3688
|
+
const ChatDebugViewTop = 'ChatDebugViewTop';
|
|
3689
|
+
const ChatDebugViewTopDevtools = 'ChatDebugViewTop--devtools';
|
|
3690
|
+
const ChatDebugViewCell = 'ChatDebugViewCell';
|
|
3691
|
+
const ChatDebugViewCellDuration = 'ChatDebugViewCellDuration';
|
|
3692
|
+
const ChatDebugViewCellStatus = 'ChatDebugViewCellStatus';
|
|
3693
|
+
const ChatDebugViewCellStatusError = 'ChatDebugViewCellStatusError';
|
|
3694
|
+
const ChatDebugViewCellType = 'ChatDebugViewCellType';
|
|
3695
|
+
const InputBox = 'InputBox';
|
|
3696
|
+
const Row = 'row';
|
|
3697
|
+
const TokenBoolean = 'TokenBoolean';
|
|
3698
|
+
const TokenKey = 'TokenKey';
|
|
3699
|
+
const TokenNumeric = 'TokenNumeric';
|
|
3700
|
+
const TokenString = 'TokenString';
|
|
3701
|
+
const TokenText = 'TokenText';
|
|
3702
|
+
const joinClassNames = (...classNames) => {
|
|
3703
|
+
return classNames.filter(Boolean).join(' ');
|
|
3704
|
+
};
|
|
3705
|
+
|
|
3581
3706
|
const getDebugErrorDom = errorMessage => {
|
|
3582
3707
|
return [{
|
|
3583
3708
|
childCount: 1,
|
|
3584
|
-
className:
|
|
3709
|
+
className: ChatDebugView,
|
|
3585
3710
|
type: Div
|
|
3586
3711
|
}, {
|
|
3587
3712
|
childCount: 1,
|
|
3588
|
-
className:
|
|
3713
|
+
className: ChatDebugViewError,
|
|
3589
3714
|
type: Div
|
|
3590
3715
|
}, text(errorMessage)];
|
|
3591
3716
|
};
|
|
@@ -3594,25 +3719,29 @@ const HandleInput = 4;
|
|
|
3594
3719
|
const HandleFilterInput = 5;
|
|
3595
3720
|
const HandleSimpleInput = 6;
|
|
3596
3721
|
const HandleEventRowClick = 7;
|
|
3597
|
-
const
|
|
3598
|
-
const
|
|
3599
|
-
const
|
|
3600
|
-
const
|
|
3601
|
-
const
|
|
3602
|
-
const
|
|
3603
|
-
const
|
|
3604
|
-
const
|
|
3722
|
+
const HandleHeaderContextMenu = 8;
|
|
3723
|
+
const HandleSashPointerDown = 9;
|
|
3724
|
+
const HandleSashPointerMove = 10;
|
|
3725
|
+
const HandleSashPointerUp = 11;
|
|
3726
|
+
const HandleTableBodyContextMenu = 12;
|
|
3727
|
+
const HandleDetailsContextMenu = 13;
|
|
3728
|
+
const HandleTimelinePointerDown = 14;
|
|
3729
|
+
const HandleTimelinePointerMove = 15;
|
|
3730
|
+
const HandleTimelinePointerUp = 16;
|
|
3731
|
+
const HandleTimelineDoubleClick = 17;
|
|
3732
|
+
const HandleTableKeyDown = 18;
|
|
3605
3733
|
|
|
3606
3734
|
const getDebugViewTopDom = (filterValue, useDevtoolsLayout, quickFilterNodes) => {
|
|
3607
3735
|
if (useDevtoolsLayout) {
|
|
3608
3736
|
return [{
|
|
3609
3737
|
childCount: 1 + (quickFilterNodes.length > 0 ? 1 : 0),
|
|
3610
|
-
className:
|
|
3738
|
+
className: joinClassNames(ChatDebugViewTop, ChatDebugViewTopDevtools),
|
|
3739
|
+
onContextMenu: HandleHeaderContextMenu,
|
|
3611
3740
|
type: Search
|
|
3612
3741
|
}, {
|
|
3613
3742
|
autocomplete: 'off',
|
|
3614
3743
|
childCount: 0,
|
|
3615
|
-
className:
|
|
3744
|
+
className: joinClassNames(InputBox, ChatDebugViewFilterInput, ChatDebugViewFilterInputDevtools),
|
|
3616
3745
|
inputType: 'search',
|
|
3617
3746
|
name: Filter,
|
|
3618
3747
|
onInput: HandleFilterInput,
|
|
@@ -3623,12 +3752,13 @@ const getDebugViewTopDom = (filterValue, useDevtoolsLayout, quickFilterNodes) =>
|
|
|
3623
3752
|
}
|
|
3624
3753
|
return [{
|
|
3625
3754
|
childCount: 1,
|
|
3626
|
-
className:
|
|
3755
|
+
className: ChatDebugViewTop,
|
|
3756
|
+
onContextMenu: HandleHeaderContextMenu,
|
|
3627
3757
|
type: Search
|
|
3628
3758
|
}, {
|
|
3629
3759
|
autocomplete: 'off',
|
|
3630
3760
|
childCount: 0,
|
|
3631
|
-
className:
|
|
3761
|
+
className: joinClassNames(InputBox, ChatDebugViewFilterInput),
|
|
3632
3762
|
inputType: 'search',
|
|
3633
3763
|
name: Filter,
|
|
3634
3764
|
onInput: HandleFilterInput,
|
|
@@ -3691,22 +3821,22 @@ const getStartText = event => {
|
|
|
3691
3821
|
const getTimingRowDom = (label, value) => {
|
|
3692
3822
|
return [{
|
|
3693
3823
|
childCount: 2,
|
|
3694
|
-
className:
|
|
3824
|
+
className: ChatDebugViewTimingRow,
|
|
3695
3825
|
type: Div
|
|
3696
3826
|
}, {
|
|
3697
3827
|
childCount: 1,
|
|
3698
|
-
className:
|
|
3828
|
+
className: ChatDebugViewTimingLabel,
|
|
3699
3829
|
type: Span
|
|
3700
3830
|
}, text(label), {
|
|
3701
3831
|
childCount: 1,
|
|
3702
|
-
className:
|
|
3832
|
+
className: ChatDebugViewTimingValue,
|
|
3703
3833
|
type: Span
|
|
3704
3834
|
}, text(value)];
|
|
3705
3835
|
};
|
|
3706
3836
|
const getTimingDetailsDom = event => {
|
|
3707
3837
|
return [{
|
|
3708
3838
|
childCount: 3,
|
|
3709
|
-
className:
|
|
3839
|
+
className: ChatDebugViewTiming,
|
|
3710
3840
|
type: Div
|
|
3711
3841
|
}, ...getTimingRowDom('Started', getStartText(event)), ...getTimingRowDom('Ended', getEndText(event)), ...getTimingRowDom('Duration', getDurationText(event))];
|
|
3712
3842
|
};
|
|
@@ -3724,7 +3854,7 @@ const getTabNodes = selectedDetailTab => {
|
|
|
3724
3854
|
'aria-controls': getPanelId(detailTab),
|
|
3725
3855
|
'aria-selected': isSelected,
|
|
3726
3856
|
childCount: 1,
|
|
3727
|
-
className: isSelected
|
|
3857
|
+
className: joinClassNames(ChatDebugViewDetailsTab, isSelected && ChatDebugViewDetailsTabSelected),
|
|
3728
3858
|
id: getTabId(detailTab),
|
|
3729
3859
|
name: DetailTab,
|
|
3730
3860
|
onChange: HandleSimpleInput,
|
|
@@ -3736,43 +3866,45 @@ const getTabNodes = selectedDetailTab => {
|
|
|
3736
3866
|
}, text(getDetailTabLabel(detailTab))];
|
|
3737
3867
|
});
|
|
3738
3868
|
};
|
|
3739
|
-
const getDetailsDom = (
|
|
3740
|
-
if (
|
|
3869
|
+
const getDetailsDom = (previewEventNodes, responseEventNodes = previewEventNodes, selectedEvent = null, selectedDetailTab = Response) => {
|
|
3870
|
+
if (previewEventNodes.length === 0 && responseEventNodes.length === 0) {
|
|
3741
3871
|
return [];
|
|
3742
3872
|
}
|
|
3743
|
-
const contentNodes = selectedDetailTab === Timing && selectedEvent ? getTimingDetailsDom(selectedEvent) :
|
|
3873
|
+
const contentNodes = selectedDetailTab === Timing && selectedEvent ? getTimingDetailsDom(selectedEvent) : selectedDetailTab === Preview ? previewEventNodes : responseEventNodes;
|
|
3744
3874
|
return [{
|
|
3745
3875
|
childCount: 2,
|
|
3746
|
-
className:
|
|
3876
|
+
className: ChatDebugViewDetails,
|
|
3747
3877
|
type: Div
|
|
3748
3878
|
}, {
|
|
3749
3879
|
childCount: 2,
|
|
3750
|
-
className:
|
|
3880
|
+
className: ChatDebugViewDetailsTop,
|
|
3751
3881
|
type: Div
|
|
3752
3882
|
}, {
|
|
3753
|
-
'aria-label': 'Detail sections',
|
|
3754
|
-
childCount: detailTabs.length,
|
|
3755
|
-
className: 'ChatDebugViewDetailsTabs',
|
|
3756
|
-
role: 'tablist',
|
|
3757
|
-
type: Div
|
|
3758
|
-
}, ...getTabNodes(selectedDetailTab), {
|
|
3759
3883
|
'aria-label': 'Close details',
|
|
3760
3884
|
childCount: 0,
|
|
3761
|
-
className:
|
|
3885
|
+
className: ChatDebugViewDetailsClose,
|
|
3762
3886
|
name: CloseDetails,
|
|
3763
3887
|
onChange: HandleSimpleInput,
|
|
3764
3888
|
onClick: HandleSimpleInput,
|
|
3765
3889
|
type: Button,
|
|
3766
3890
|
value: 'close'
|
|
3767
3891
|
}, {
|
|
3892
|
+
'aria-label': 'Detail sections',
|
|
3893
|
+
childCount: detailTabs.length,
|
|
3894
|
+
className: ChatDebugViewDetailsTabs,
|
|
3895
|
+
role: 'tablist',
|
|
3896
|
+
type: Div
|
|
3897
|
+
}, ...getTabNodes(selectedDetailTab), {
|
|
3768
3898
|
childCount: 1,
|
|
3769
|
-
className:
|
|
3899
|
+
className: ChatDebugViewDetailsBody,
|
|
3900
|
+
role: 'document',
|
|
3770
3901
|
type: Div
|
|
3771
3902
|
}, {
|
|
3772
3903
|
'aria-labelledby': getTabId(selectedDetailTab),
|
|
3773
3904
|
childCount: 1,
|
|
3774
|
-
className:
|
|
3905
|
+
className: ChatDebugViewDetailsPanel,
|
|
3775
3906
|
id: getPanelId(selectedDetailTab),
|
|
3907
|
+
onContextMenu: HandleDetailsContextMenu,
|
|
3776
3908
|
role: 'tabpanel',
|
|
3777
3909
|
type: Div
|
|
3778
3910
|
}, ...contentNodes];
|
|
@@ -3811,6 +3943,19 @@ const getEventTypeLabel = event => {
|
|
|
3811
3943
|
return `${event.type}, ${toolName}`;
|
|
3812
3944
|
};
|
|
3813
3945
|
|
|
3946
|
+
const isRecord = value => {
|
|
3947
|
+
return typeof value === 'object' && value !== null;
|
|
3948
|
+
};
|
|
3949
|
+
const isErrorStatusCode = value => {
|
|
3950
|
+
if (typeof value === 'number') {
|
|
3951
|
+
return value >= 400;
|
|
3952
|
+
}
|
|
3953
|
+
if (typeof value === 'string') {
|
|
3954
|
+
const parsedStatus = Number(value);
|
|
3955
|
+
return Number.isFinite(parsedStatus) && parsedStatus >= 400;
|
|
3956
|
+
}
|
|
3957
|
+
return false;
|
|
3958
|
+
};
|
|
3814
3959
|
const hasErrorStatus = event => {
|
|
3815
3960
|
if (event.type === 'error') {
|
|
3816
3961
|
return true;
|
|
@@ -3821,12 +3966,17 @@ const hasErrorStatus = event => {
|
|
|
3821
3966
|
const {
|
|
3822
3967
|
status
|
|
3823
3968
|
} = event;
|
|
3824
|
-
if (
|
|
3969
|
+
if (isErrorStatusCode(status)) {
|
|
3825
3970
|
return true;
|
|
3826
3971
|
}
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3972
|
+
const {
|
|
3973
|
+
result
|
|
3974
|
+
} = event;
|
|
3975
|
+
if (isRecord(result)) {
|
|
3976
|
+
if (isErrorStatusCode(result.status)) {
|
|
3977
|
+
return true;
|
|
3978
|
+
}
|
|
3979
|
+
if (typeof result.error === 'string' || typeof result.errorMessage === 'string' || typeof result.exception === 'string') {
|
|
3830
3980
|
return true;
|
|
3831
3981
|
}
|
|
3832
3982
|
}
|
|
@@ -3840,26 +3990,24 @@ const getStatusText = event => {
|
|
|
3840
3990
|
const getDevtoolsRows = (events, selectedEventIndex) => {
|
|
3841
3991
|
return events.flatMap((event, i) => {
|
|
3842
3992
|
const isSelected = selectedEventIndex === i;
|
|
3993
|
+
const isErrorStatus = hasErrorStatus(event);
|
|
3843
3994
|
const rowIndex = String(i);
|
|
3844
3995
|
return [{
|
|
3845
3996
|
childCount: 3,
|
|
3846
|
-
className:
|
|
3997
|
+
className: joinClassNames(ChatDebugViewEventRow, isSelected && ChatDebugViewEventRowSelected),
|
|
3847
3998
|
'data-index': rowIndex,
|
|
3848
3999
|
type: Tr
|
|
3849
4000
|
}, {
|
|
3850
4001
|
childCount: 1,
|
|
3851
|
-
className:
|
|
3852
|
-
'data-index': rowIndex,
|
|
4002
|
+
className: joinClassNames(ChatDebugViewCell, ChatDebugViewCellType),
|
|
3853
4003
|
type: Td
|
|
3854
4004
|
}, text(getEventTypeLabel(event)), {
|
|
3855
4005
|
childCount: 1,
|
|
3856
|
-
className:
|
|
3857
|
-
'data-index': rowIndex,
|
|
4006
|
+
className: joinClassNames(ChatDebugViewCell, ChatDebugViewCellDuration),
|
|
3858
4007
|
type: Td
|
|
3859
4008
|
}, text(getDurationText(event)), {
|
|
3860
4009
|
childCount: 1,
|
|
3861
|
-
className:
|
|
3862
|
-
'data-index': rowIndex,
|
|
4010
|
+
className: joinClassNames(ChatDebugViewCell, ChatDebugViewCellStatus, isErrorStatus && ChatDebugViewCellStatusError),
|
|
3863
4011
|
type: Td
|
|
3864
4012
|
}, text(getStatusText(event))];
|
|
3865
4013
|
});
|
|
@@ -3868,7 +4016,7 @@ const getDevtoolsRows = (events, selectedEventIndex) => {
|
|
|
3868
4016
|
const getEmptyStateDom = emptyMessage => {
|
|
3869
4017
|
return [{
|
|
3870
4018
|
childCount: 1,
|
|
3871
|
-
className:
|
|
4019
|
+
className: ChatDebugViewEmpty,
|
|
3872
4020
|
type: Div
|
|
3873
4021
|
}, text(emptyMessage)];
|
|
3874
4022
|
};
|
|
@@ -3918,32 +4066,32 @@ const getTokenSegments = json => {
|
|
|
3918
4066
|
while (lookAheadIndex < json.length && whitespaceRegex.test(json[lookAheadIndex])) {
|
|
3919
4067
|
lookAheadIndex++;
|
|
3920
4068
|
}
|
|
3921
|
-
const className = json[lookAheadIndex] === ':' ?
|
|
4069
|
+
const className = json[lookAheadIndex] === ':' ? TokenKey : TokenString;
|
|
3922
4070
|
segments = pushToken(segments, className, tokenValue);
|
|
3923
4071
|
continue;
|
|
3924
4072
|
}
|
|
3925
4073
|
const numberMatch = numberRegex.exec(json.slice(i));
|
|
3926
4074
|
if (numberMatch) {
|
|
3927
|
-
segments = pushToken(segments,
|
|
4075
|
+
segments = pushToken(segments, TokenNumeric, numberMatch[0]);
|
|
3928
4076
|
i += numberMatch[0].length;
|
|
3929
4077
|
continue;
|
|
3930
4078
|
}
|
|
3931
4079
|
if (json.startsWith('true', i)) {
|
|
3932
|
-
segments = pushToken(segments,
|
|
4080
|
+
segments = pushToken(segments, TokenBoolean, 'true');
|
|
3933
4081
|
i += 4;
|
|
3934
4082
|
continue;
|
|
3935
4083
|
}
|
|
3936
4084
|
if (json.startsWith('false', i)) {
|
|
3937
|
-
segments = pushToken(segments,
|
|
4085
|
+
segments = pushToken(segments, TokenBoolean, 'false');
|
|
3938
4086
|
i += 5;
|
|
3939
4087
|
continue;
|
|
3940
4088
|
}
|
|
3941
4089
|
if (json.startsWith('null', i)) {
|
|
3942
|
-
segments = pushToken(segments,
|
|
4090
|
+
segments = pushToken(segments, TokenBoolean, 'null');
|
|
3943
4091
|
i += 4;
|
|
3944
4092
|
continue;
|
|
3945
4093
|
}
|
|
3946
|
-
segments = pushToken(segments,
|
|
4094
|
+
segments = pushToken(segments, TokenText, character);
|
|
3947
4095
|
i++;
|
|
3948
4096
|
}
|
|
3949
4097
|
return segments;
|
|
@@ -3953,7 +4101,7 @@ const getJsonLines = value => {
|
|
|
3953
4101
|
const json = JSON.stringify(value, null, 2);
|
|
3954
4102
|
if (!json) {
|
|
3955
4103
|
return [[{
|
|
3956
|
-
className:
|
|
4104
|
+
className: TokenText,
|
|
3957
4105
|
value: String(json)
|
|
3958
4106
|
}]];
|
|
3959
4107
|
}
|
|
@@ -3993,50 +4141,93 @@ const getLineNodes = lines => {
|
|
|
3993
4141
|
const lineContentNodes = getLineContentNodes(line);
|
|
3994
4142
|
return [{
|
|
3995
4143
|
childCount: 2,
|
|
3996
|
-
className:
|
|
4144
|
+
className: Row,
|
|
3997
4145
|
type: Div
|
|
3998
4146
|
}, {
|
|
3999
4147
|
childCount: 1,
|
|
4000
|
-
className:
|
|
4148
|
+
className: ChatDebugViewEventLineNumber,
|
|
4001
4149
|
type: Span
|
|
4002
4150
|
}, text(String(index + 1)), {
|
|
4003
4151
|
childCount: lineContentNodes.length / 2,
|
|
4004
|
-
className:
|
|
4152
|
+
className: ChatDebugViewEventLineContent,
|
|
4005
4153
|
type: Span
|
|
4006
4154
|
}, ...lineContentNodes];
|
|
4007
4155
|
});
|
|
4008
4156
|
};
|
|
4009
|
-
const
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4157
|
+
const isChatViewEvent = value => {
|
|
4158
|
+
return typeof value === 'object' && value !== null && typeof value.type === 'string';
|
|
4159
|
+
};
|
|
4160
|
+
const getEventNode = value => {
|
|
4161
|
+
const renderedValue = isChatViewEvent(value) ? {
|
|
4162
|
+
...value,
|
|
4163
|
+
type: getEventTypeLabel(value)
|
|
4164
|
+
} : value;
|
|
4165
|
+
const lines = getJsonLines(renderedValue);
|
|
4015
4166
|
const lineNodes = getLineNodes(lines);
|
|
4016
4167
|
return [{
|
|
4017
4168
|
childCount: lines.length,
|
|
4018
|
-
className:
|
|
4169
|
+
className: ChatDebugViewEvent,
|
|
4019
4170
|
type: Div
|
|
4020
4171
|
}, ...lineNodes];
|
|
4021
4172
|
};
|
|
4022
4173
|
|
|
4023
4174
|
const getEventsClassName = hasSelectedEvent => {
|
|
4024
|
-
const widthClassName =
|
|
4175
|
+
const widthClassName = joinClassNames(ChatDebugViewEvents, !hasSelectedEvent && ChatDebugViewEventsFullWidth);
|
|
4025
4176
|
return widthClassName;
|
|
4026
4177
|
};
|
|
4027
4178
|
|
|
4179
|
+
const hasOwn = (event, key) => {
|
|
4180
|
+
return Object.hasOwn(event, key);
|
|
4181
|
+
};
|
|
4182
|
+
const getPreviewName = event => {
|
|
4183
|
+
if (typeof event.name === 'string' && event.name) {
|
|
4184
|
+
return event.name;
|
|
4185
|
+
}
|
|
4186
|
+
if (typeof event.toolName === 'string' && event.toolName) {
|
|
4187
|
+
return event.toolName;
|
|
4188
|
+
}
|
|
4189
|
+
return undefined;
|
|
4190
|
+
};
|
|
4191
|
+
const shouldIncludeArguments = (event, name) => {
|
|
4192
|
+
if (!hasOwn(event, 'arguments')) {
|
|
4193
|
+
return false;
|
|
4194
|
+
}
|
|
4195
|
+
if (name === 'getWorkspaceUri') {
|
|
4196
|
+
return false;
|
|
4197
|
+
}
|
|
4198
|
+
return true;
|
|
4199
|
+
};
|
|
4200
|
+
const getPreviewEvent = event => {
|
|
4201
|
+
const name = getPreviewName(event);
|
|
4202
|
+
const previewEvent = {
|
|
4203
|
+
...(name === undefined ? {} : {
|
|
4204
|
+
name
|
|
4205
|
+
}),
|
|
4206
|
+
...(shouldIncludeArguments(event, name) ? {
|
|
4207
|
+
arguments: event.arguments
|
|
4208
|
+
} : {}),
|
|
4209
|
+
...(hasOwn(event, 'result') ? {
|
|
4210
|
+
result: event.result
|
|
4211
|
+
} : {})
|
|
4212
|
+
};
|
|
4213
|
+
if (Object.keys(previewEvent).length > 0) {
|
|
4214
|
+
return previewEvent;
|
|
4215
|
+
}
|
|
4216
|
+
return event;
|
|
4217
|
+
};
|
|
4218
|
+
|
|
4028
4219
|
const getSashNodesDom = hasSelectedEvent => {
|
|
4029
4220
|
if (!hasSelectedEvent) {
|
|
4030
4221
|
return [];
|
|
4031
4222
|
}
|
|
4032
4223
|
return [{
|
|
4033
4224
|
childCount: 1,
|
|
4034
|
-
className:
|
|
4225
|
+
className: ChatDebugViewSash,
|
|
4035
4226
|
onPointerDown: HandleSashPointerDown,
|
|
4036
4227
|
type: Div
|
|
4037
4228
|
}, {
|
|
4038
4229
|
childCount: 0,
|
|
4039
|
-
className:
|
|
4230
|
+
className: ChatDebugViewSashLine,
|
|
4040
4231
|
type: Div
|
|
4041
4232
|
}];
|
|
4042
4233
|
};
|
|
@@ -4044,7 +4235,7 @@ const getSashNodesDom = hasSelectedEvent => {
|
|
|
4044
4235
|
const getTableBodyDom = (rowNodes, eventCount) => {
|
|
4045
4236
|
return [{
|
|
4046
4237
|
childCount: eventCount === 0 ? 1 : eventCount,
|
|
4047
|
-
className:
|
|
4238
|
+
className: ChatDebugViewTableBody,
|
|
4048
4239
|
onContextMenu: HandleTableBodyContextMenu,
|
|
4049
4240
|
onPointerDown: HandleEventRowClick,
|
|
4050
4241
|
type: TBody
|
|
@@ -4054,25 +4245,25 @@ const getTableBodyDom = (rowNodes, eventCount) => {
|
|
|
4054
4245
|
const getTableHeaderDom = () => {
|
|
4055
4246
|
return [{
|
|
4056
4247
|
childCount: 1,
|
|
4057
|
-
className:
|
|
4248
|
+
className: ChatDebugViewTableHeader,
|
|
4058
4249
|
type: THead
|
|
4059
4250
|
}, {
|
|
4060
4251
|
childCount: 3,
|
|
4061
|
-
className:
|
|
4252
|
+
className: ChatDebugViewTableHeaderRow,
|
|
4062
4253
|
type: Tr
|
|
4063
4254
|
}, {
|
|
4064
4255
|
childCount: 1,
|
|
4065
|
-
className:
|
|
4256
|
+
className: ChatDebugViewHeaderCell,
|
|
4066
4257
|
scope: 'col',
|
|
4067
4258
|
type: Th
|
|
4068
4259
|
}, text('Type'), {
|
|
4069
4260
|
childCount: 1,
|
|
4070
|
-
className:
|
|
4261
|
+
className: ChatDebugViewHeaderCell,
|
|
4071
4262
|
scope: 'col',
|
|
4072
4263
|
type: Th
|
|
4073
4264
|
}, text('Duration'), {
|
|
4074
4265
|
childCount: 1,
|
|
4075
|
-
className:
|
|
4266
|
+
className: ChatDebugViewHeaderCell,
|
|
4076
4267
|
scope: 'col',
|
|
4077
4268
|
type: Th
|
|
4078
4269
|
}, text('Status')];
|
|
@@ -4081,16 +4272,20 @@ const getTableHeaderDom = () => {
|
|
|
4081
4272
|
const getTableDom = (rowNodes, eventCount) => {
|
|
4082
4273
|
return [{
|
|
4083
4274
|
childCount: 2,
|
|
4084
|
-
className:
|
|
4275
|
+
className: ChatDebugViewTable,
|
|
4085
4276
|
type: Table
|
|
4086
4277
|
}, ...getTableHeaderDom(), ...getTableBodyDom(rowNodes, eventCount)];
|
|
4087
4278
|
};
|
|
4088
4279
|
|
|
4280
|
+
const formatPercent = value => {
|
|
4281
|
+
return `${Number(value.toFixed(3))}%`;
|
|
4282
|
+
};
|
|
4283
|
+
|
|
4089
4284
|
const getBucketUnitDom = unitCount => {
|
|
4090
4285
|
if (unitCount === 0) {
|
|
4091
4286
|
return [{
|
|
4092
4287
|
childCount: 0,
|
|
4093
|
-
className:
|
|
4288
|
+
className: joinClassNames(ChatDebugViewTimelineBucketUnit, ChatDebugViewTimelineBucketUnitEmpty),
|
|
4094
4289
|
type: Div
|
|
4095
4290
|
}];
|
|
4096
4291
|
}
|
|
@@ -4098,7 +4293,7 @@ const getBucketUnitDom = unitCount => {
|
|
|
4098
4293
|
length: unitCount
|
|
4099
4294
|
}).fill({
|
|
4100
4295
|
childCount: 0,
|
|
4101
|
-
className:
|
|
4296
|
+
className: ChatDebugViewTimelineBucketUnit,
|
|
4102
4297
|
type: Div
|
|
4103
4298
|
});
|
|
4104
4299
|
};
|
|
@@ -4107,12 +4302,12 @@ const getBucketDom = bucket => {
|
|
|
4107
4302
|
const presetValue = `${formatTimelinePresetValue(bucket.startSeconds)}:${formatTimelinePresetValue(bucket.endSeconds)}`;
|
|
4108
4303
|
return [{
|
|
4109
4304
|
childCount: 2,
|
|
4110
|
-
className:
|
|
4305
|
+
className: joinClassNames(ChatDebugViewTimelineBucket, bucket.isSelected && ChatDebugViewTimelineBucketSelected),
|
|
4111
4306
|
type: Label
|
|
4112
4307
|
}, {
|
|
4113
4308
|
checked: false,
|
|
4114
4309
|
childCount: 0,
|
|
4115
|
-
className:
|
|
4310
|
+
className: ChatDebugViewTimelinePresetInput,
|
|
4116
4311
|
inputType: 'radio',
|
|
4117
4312
|
name: TimelineRangePreset,
|
|
4118
4313
|
onChange: HandleSimpleInput,
|
|
@@ -4120,11 +4315,24 @@ const getBucketDom = bucket => {
|
|
|
4120
4315
|
value: presetValue
|
|
4121
4316
|
}, {
|
|
4122
4317
|
childCount: bucket.unitCount === 0 ? 1 : bucket.unitCount,
|
|
4123
|
-
className:
|
|
4318
|
+
className: joinClassNames(ChatDebugViewTimelineBucketBar, bucket.isSelected && ChatDebugViewTimelineBucketBarSelected),
|
|
4124
4319
|
type: Div
|
|
4125
4320
|
}, ...getBucketUnitDom(bucket.unitCount)];
|
|
4126
4321
|
};
|
|
4127
4322
|
|
|
4323
|
+
const getEffectiveTimelineRange = (timelineStartSeconds, timelineEndSeconds, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds) => {
|
|
4324
|
+
if (!timelineSelectionActive) {
|
|
4325
|
+
return {
|
|
4326
|
+
endSeconds: timelineEndSeconds,
|
|
4327
|
+
startSeconds: timelineStartSeconds
|
|
4328
|
+
};
|
|
4329
|
+
}
|
|
4330
|
+
return {
|
|
4331
|
+
endSeconds: timelineSelectionFocusSeconds,
|
|
4332
|
+
startSeconds: timelineSelectionAnchorSeconds
|
|
4333
|
+
};
|
|
4334
|
+
};
|
|
4335
|
+
|
|
4128
4336
|
const formatTimelineSeconds = value => {
|
|
4129
4337
|
if (Number.isInteger(value)) {
|
|
4130
4338
|
return `${value}s`;
|
|
@@ -4140,21 +4348,6 @@ const getTimelineSummary = (timelineEvents, timelineStartSeconds, timelineEndSec
|
|
|
4140
4348
|
return `Window 0s-${formatTimelineSeconds(timelineInfo.durationSeconds)} of ${formatTimelineSeconds(timelineInfo.durationSeconds)}`;
|
|
4141
4349
|
};
|
|
4142
4350
|
|
|
4143
|
-
const getEffectiveTimelineRange = (timelineStartSeconds, timelineEndSeconds, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds) => {
|
|
4144
|
-
if (!timelineSelectionActive) {
|
|
4145
|
-
return {
|
|
4146
|
-
endSeconds: timelineEndSeconds,
|
|
4147
|
-
startSeconds: timelineStartSeconds
|
|
4148
|
-
};
|
|
4149
|
-
}
|
|
4150
|
-
return {
|
|
4151
|
-
endSeconds: timelineSelectionFocusSeconds,
|
|
4152
|
-
startSeconds: timelineSelectionAnchorSeconds
|
|
4153
|
-
};
|
|
4154
|
-
};
|
|
4155
|
-
const formatPercent = value => {
|
|
4156
|
-
return `${Number(value.toFixed(3))}%`;
|
|
4157
|
-
};
|
|
4158
4351
|
const getTimelineNodes = (timelineEvents, timelineStartSeconds, timelineEndSeconds, timelineSelectionActive = false, timelineSelectionAnchorSeconds = '', timelineSelectionFocusSeconds = '') => {
|
|
4159
4352
|
const effectiveRange = getEffectiveTimelineRange(timelineStartSeconds, timelineEndSeconds, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds);
|
|
4160
4353
|
const timelineInfo = getTimelineInfo(timelineEvents, effectiveRange.startSeconds, effectiveRange.endSeconds);
|
|
@@ -4163,45 +4356,45 @@ const getTimelineNodes = (timelineEvents, timelineStartSeconds, timelineEndSecon
|
|
|
4163
4356
|
}
|
|
4164
4357
|
const selectionNodes = timelineInfo.hasSelection && timelineInfo.selectionStartPercent !== null && timelineInfo.selectionEndPercent !== null ? [{
|
|
4165
4358
|
childCount: 0,
|
|
4166
|
-
className:
|
|
4359
|
+
className: ChatDebugViewTimelineSelectionRange,
|
|
4167
4360
|
style: `left:${formatPercent(timelineInfo.selectionStartPercent)};width:${formatPercent(timelineInfo.selectionEndPercent - timelineInfo.selectionStartPercent)};`,
|
|
4168
4361
|
type: Div
|
|
4169
4362
|
}, {
|
|
4170
4363
|
childCount: 0,
|
|
4171
|
-
className:
|
|
4364
|
+
className: joinClassNames(ChatDebugViewTimelineSelectionMarker, ChatDebugViewTimelineSelectionMarkerStart),
|
|
4172
4365
|
style: `left:${formatPercent(timelineInfo.selectionStartPercent)};`,
|
|
4173
4366
|
type: Div
|
|
4174
4367
|
}, {
|
|
4175
4368
|
childCount: 0,
|
|
4176
|
-
className:
|
|
4369
|
+
className: joinClassNames(ChatDebugViewTimelineSelectionMarker, ChatDebugViewTimelineSelectionMarkerEnd),
|
|
4177
4370
|
style: `left:${formatPercent(timelineInfo.selectionEndPercent)};`,
|
|
4178
4371
|
type: Div
|
|
4179
4372
|
}] : [];
|
|
4180
4373
|
return [{
|
|
4181
4374
|
childCount: 2,
|
|
4182
|
-
className:
|
|
4375
|
+
className: ChatDebugViewTimeline,
|
|
4183
4376
|
type: Div
|
|
4184
4377
|
}, {
|
|
4185
4378
|
childCount: 1,
|
|
4186
|
-
className:
|
|
4379
|
+
className: ChatDebugViewTimelineTop,
|
|
4187
4380
|
type: Div
|
|
4188
4381
|
}, {
|
|
4189
4382
|
childCount: 1,
|
|
4190
|
-
className:
|
|
4383
|
+
className: ChatDebugViewTimelineSummary,
|
|
4191
4384
|
type: Div
|
|
4192
4385
|
}, text(getTimelineSummary(timelineEvents, effectiveRange.startSeconds, effectiveRange.endSeconds)), {
|
|
4193
4386
|
childCount: 2,
|
|
4194
|
-
className:
|
|
4387
|
+
className: ChatDebugViewTimelineInteractive,
|
|
4195
4388
|
onDoubleClick: HandleTimelineDoubleClick,
|
|
4196
4389
|
onPointerDown: HandleTimelinePointerDown,
|
|
4197
4390
|
type: Div
|
|
4198
4391
|
}, {
|
|
4199
4392
|
childCount: timelineInfo.buckets.length,
|
|
4200
|
-
className:
|
|
4393
|
+
className: ChatDebugViewTimelineBuckets,
|
|
4201
4394
|
type: Div
|
|
4202
4395
|
}, ...timelineInfo.buckets.flatMap(getBucketDom), {
|
|
4203
4396
|
childCount: selectionNodes.length,
|
|
4204
|
-
className:
|
|
4397
|
+
className: ChatDebugViewTimelineSelectionOverlay,
|
|
4205
4398
|
type: Div
|
|
4206
4399
|
}, ...selectionNodes];
|
|
4207
4400
|
};
|
|
@@ -4209,25 +4402,29 @@ const getTimelineNodes = (timelineEvents, timelineStartSeconds, timelineEndSecon
|
|
|
4209
4402
|
const getDevtoolsDom = (events, selectedEvent, selectedEventIndex, timelineEvents, timelineStartSeconds, timelineEndSeconds, emptyMessage = 'No events have been found', timelineSelectionActive = false, timelineSelectionAnchorSeconds = '', timelineSelectionFocusSeconds = '', selectedDetailTab = Response) => {
|
|
4210
4403
|
const rowNodes = getDevtoolsRows(events, selectedEventIndex);
|
|
4211
4404
|
const timelineNodes = getTimelineNodes(timelineEvents, timelineStartSeconds, timelineEndSeconds, timelineSelectionActive, timelineSelectionAnchorSeconds, timelineSelectionFocusSeconds);
|
|
4212
|
-
const
|
|
4213
|
-
const
|
|
4405
|
+
const previewEventNodes = selectedEvent ? getEventNode(getPreviewEvent(selectedEvent)) : [];
|
|
4406
|
+
const responseEventNodes = selectedEvent ? getEventNode(selectedEvent) : [];
|
|
4407
|
+
const hasSelectedEvent = responseEventNodes.length > 0;
|
|
4214
4408
|
const tableNodes = events.length === 0 ? getEmptyStateDom(emptyMessage) : getTableDom(rowNodes, events.length);
|
|
4215
4409
|
const eventsClassName = getEventsClassName(hasSelectedEvent);
|
|
4216
|
-
const detailsNodes = getDetailsDom(
|
|
4410
|
+
const detailsNodes = getDetailsDom(previewEventNodes, responseEventNodes, selectedEvent, isDetailTab(selectedDetailTab) ? selectedDetailTab : Response);
|
|
4217
4411
|
const sashNodes = getSashNodesDom(hasSelectedEvent);
|
|
4218
4412
|
const splitChildCount = hasSelectedEvent ? 3 : 1;
|
|
4219
4413
|
const mainChildCount = 1 + (timelineNodes.length > 0 ? 1 : 0);
|
|
4220
4414
|
return [{
|
|
4221
4415
|
childCount: mainChildCount,
|
|
4222
|
-
className:
|
|
4416
|
+
className: ChatDebugViewDevtoolsMain,
|
|
4223
4417
|
type: Div
|
|
4224
4418
|
}, ...timelineNodes, {
|
|
4225
4419
|
childCount: splitChildCount,
|
|
4226
|
-
className:
|
|
4420
|
+
className: ChatDebugViewDevtoolsSplit,
|
|
4227
4421
|
type: Div
|
|
4228
4422
|
}, {
|
|
4229
4423
|
childCount: 1,
|
|
4230
4424
|
className: eventsClassName,
|
|
4425
|
+
onKeyDown: HandleTableKeyDown,
|
|
4426
|
+
role: 'application',
|
|
4427
|
+
tabIndex: 0,
|
|
4231
4428
|
type: Div
|
|
4232
4429
|
}, ...tableNodes, ...sashNodes, ...detailsNodes];
|
|
4233
4430
|
};
|
|
@@ -4235,11 +4432,13 @@ const getDevtoolsDom = (events, selectedEvent, selectedEventIndex, timelineEvent
|
|
|
4235
4432
|
const getLegacyEventsDom = (errorMessage, emptyMessage, eventNodes) => {
|
|
4236
4433
|
return [{
|
|
4237
4434
|
childCount: eventNodes.length === 0 ? 1 : eventNodes.length,
|
|
4238
|
-
className:
|
|
4435
|
+
className: ChatDebugViewEvents,
|
|
4436
|
+
role: 'application',
|
|
4437
|
+
tabIndex: 0,
|
|
4239
4438
|
type: Div
|
|
4240
4439
|
}, ...(eventNodes.length === 0 ? [{
|
|
4241
4440
|
childCount: 1,
|
|
4242
|
-
className: errorMessage ?
|
|
4441
|
+
className: errorMessage ? ChatDebugViewError : ChatDebugViewEmpty,
|
|
4243
4442
|
type: Div
|
|
4244
4443
|
}, text(errorMessage || emptyMessage)] : eventNodes)];
|
|
4245
4444
|
};
|
|
@@ -4247,18 +4446,18 @@ const getLegacyEventsDom = (errorMessage, emptyMessage, eventNodes) => {
|
|
|
4247
4446
|
const getQuickFilterNodes = (eventCategoryFilter, eventCategoryFilterOptions) => {
|
|
4248
4447
|
return [{
|
|
4249
4448
|
childCount: eventCategoryFilterOptions.length,
|
|
4250
|
-
className:
|
|
4449
|
+
className: ChatDebugViewQuickFilters,
|
|
4251
4450
|
type: Div
|
|
4252
4451
|
}, ...eventCategoryFilterOptions.flatMap(option => {
|
|
4253
4452
|
const isSelected = option.value === eventCategoryFilter;
|
|
4254
4453
|
return [{
|
|
4255
4454
|
childCount: 2,
|
|
4256
|
-
className:
|
|
4455
|
+
className: joinClassNames(ChatDebugViewQuickFilterPill, isSelected && ChatDebugViewQuickFilterPillSelected),
|
|
4257
4456
|
type: Label
|
|
4258
4457
|
}, {
|
|
4259
4458
|
checked: isSelected,
|
|
4260
4459
|
childCount: 0,
|
|
4261
|
-
className:
|
|
4460
|
+
className: ChatDebugViewQuickFilterInput,
|
|
4262
4461
|
inputType: 'radio',
|
|
4263
4462
|
name: EventCategoryFilter,
|
|
4264
4463
|
onChange: HandleInput,
|
|
@@ -4310,7 +4509,7 @@ const getChatDebugViewDom = (errorMessage, filterValue, eventCategoryFilter, eve
|
|
|
4310
4509
|
const rootChildCount = 2;
|
|
4311
4510
|
return [{
|
|
4312
4511
|
childCount: rootChildCount,
|
|
4313
|
-
className:
|
|
4512
|
+
className: joinClassNames(ChatDebugView, useDevtoolsLayout && ChatDebugViewDevtools),
|
|
4314
4513
|
type: Div
|
|
4315
4514
|
}, ...debugViewTopDom, ...contentNodes];
|
|
4316
4515
|
};
|
|
@@ -4377,7 +4576,7 @@ const render2 = (uid, diffResult) => {
|
|
|
4377
4576
|
const renderEventListeners = () => {
|
|
4378
4577
|
return [{
|
|
4379
4578
|
name: HandleEventRowClick,
|
|
4380
|
-
params: ['handleEventRowClick', 'event.target.dataset.index']
|
|
4579
|
+
params: ['handleEventRowClick', 'event.target.dataset.index', 'event.button']
|
|
4381
4580
|
}, {
|
|
4382
4581
|
name: HandleTableBodyContextMenu,
|
|
4383
4582
|
params: ['handleTableBodyContextMenu'],
|
|
@@ -4529,7 +4728,9 @@ const commandMap = {
|
|
|
4529
4728
|
'ChatDebug.create': create,
|
|
4530
4729
|
'ChatDebug.diff2': diff2,
|
|
4531
4730
|
'ChatDebug.getCommandIds': getCommandIds,
|
|
4731
|
+
'ChatDebug.handleDetailsContextMenu': wrapCommand(handleDetailsContextMenu),
|
|
4532
4732
|
'ChatDebug.handleEventRowClick': wrapCommand(handleEventRowClick),
|
|
4733
|
+
'ChatDebug.handleHeaderContextMenu': wrapCommand(handleHeaderContextMenu),
|
|
4533
4734
|
'ChatDebug.handleInput': wrapCommand(handleInput),
|
|
4534
4735
|
'ChatDebug.handleSashPointerDown': wrapCommand(handleSashPointerDown),
|
|
4535
4736
|
'ChatDebug.handleSashPointerMove': wrapCommand(handleSashPointerMove),
|