@copilotkit/web-inspector 1.61.2 → 1.62.1

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/index.cjs CHANGED
@@ -14,6 +14,7 @@ let _copilotkit_core = require("@copilotkit/core");
14
14
 
15
15
  //#region src/index.ts
16
16
  const WEB_INSPECTOR_TAG = "cpk-web-inspector";
17
+ const THREAD_INSPECTOR_TAG = "cpk-thread-inspector";
17
18
  const EDGE_MARGIN = 16;
18
19
  const DRAG_THRESHOLD = 6;
19
20
  const MIN_WINDOW_WIDTH = 600;
@@ -354,28 +355,30 @@ var CpkThreadList = class extends lit.LitElement {
354
355
  ${filtered.length === 0 ? lit.html`
355
356
  <div class="cpk-tl__empty">
356
357
  ${this.errorMessage ? lit.html`
357
- <svg
358
- width="24"
359
- height="24"
360
- viewBox="0 0 24 24"
361
- fill="none"
362
- stroke="currentColor"
363
- stroke-width="1.5"
364
- stroke-linecap="round"
365
- stroke-linejoin="round"
366
- class="cpk-tl__empty-icon"
358
+ <svg
359
+ width="24"
360
+ height="24"
361
+ viewBox="0 0 24 24"
362
+ fill="none"
363
+ stroke="currentColor"
364
+ stroke-width="1.5"
365
+ stroke-linecap="round"
366
+ stroke-linejoin="round"
367
+ class="cpk-tl__empty-icon"
368
+ >
369
+ <circle cx="12" cy="12" r="10" />
370
+ <line x1="12" y1="8" x2="12" y2="12" />
371
+ <line x1="12" y1="16" x2="12.01" y2="16" />
372
+ </svg>
373
+ <div>
374
+ Failed to load threads
375
+ <div
376
+ style="font-size:11px;margin-top:4px;color:#c0333a;"
367
377
  >
368
- <circle cx="12" cy="12" r="10" />
369
- <line x1="12" y1="8" x2="12" y2="12" />
370
- <line x1="12" y1="16" x2="12.01" y2="16" />
371
- </svg>
372
- <div>
373
- Failed to load threads
374
- <div style="font-size:11px;margin-top:4px;color:#c0333a;">
375
- ${this.errorMessage}
376
- </div>
378
+ ${this.errorMessage}
377
379
  </div>
378
- ` : this.threads.length === 0 ? lit.html`
380
+ </div>
381
+ ` : this.threads.length === 0 ? lit.html`
379
382
  <svg
380
383
  width="24"
381
384
  height="24"
@@ -400,10 +403,11 @@ var CpkThreadList = class extends lit.LitElement {
400
403
  `;
401
404
  }
402
405
  };
403
- var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
406
+ var CpkThreadInspector = class CpkThreadInspector extends lit.LitElement {
404
407
  constructor(..._args2) {
405
408
  super(..._args2);
406
409
  this.threadId = null;
410
+ this.provider = null;
407
411
  this.thread = null;
408
412
  this.runtimeUrl = "";
409
413
  this.headers = {};
@@ -411,7 +415,8 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
411
415
  this.agentStateInput = null;
412
416
  this.agentEventsInput = [];
413
417
  this.liveMessageVersion = 0;
414
- this._tab = "conversation";
418
+ this._tab = "timeline";
419
+ this._fetchedMetadata = null;
415
420
  this._conversation = [];
416
421
  this._fetchedEvents = null;
417
422
  this._fetchedState = null;
@@ -428,12 +433,15 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
428
433
  this._eventsNotAvailable = false;
429
434
  this._stateNotAvailable = false;
430
435
  this._panelInitializing = false;
431
- this._activatedTabs = new Set(["conversation"]);
436
+ this._activatedTabs = new Set(["timeline"]);
432
437
  this._panelTplCache = /* @__PURE__ */ new Map();
438
+ this._timelineItemsCache = null;
439
+ this._liveEventsWithSourceIndexCache = null;
433
440
  this._eventsFetched = false;
434
441
  this._stateFetched = false;
435
- this._lastFetchedThreadId = null;
442
+ this._lastLoadKey = null;
436
443
  this._lastSeenLiveMessageVersion = 0;
444
+ this._metadataAbort = null;
437
445
  this._messagesAbort = null;
438
446
  this._eventsAbort = null;
439
447
  this._stateAbort = null;
@@ -464,6 +472,7 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
464
472
  static {
465
473
  this.properties = {
466
474
  threadId: { attribute: false },
475
+ provider: { attribute: false },
467
476
  thread: { attribute: false },
468
477
  runtimeUrl: { attribute: false },
469
478
  headers: { attribute: false },
@@ -472,6 +481,7 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
472
481
  agentEventsInput: { attribute: false },
473
482
  liveMessageVersion: { attribute: false },
474
483
  _tab: { state: true },
484
+ _fetchedMetadata: { state: true },
475
485
  _conversation: { state: true },
476
486
  _fetchedEvents: { state: true },
477
487
  _fetchedState: { state: true },
@@ -497,22 +507,52 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
497
507
  static {
498
508
  this.TAB_LIST = [
499
509
  {
500
- id: "conversation",
501
- label: "Conversation"
510
+ id: "timeline",
511
+ label: "Timeline"
502
512
  },
503
513
  {
504
- id: "agent-state",
505
- label: "Agent State"
514
+ id: "raw-events",
515
+ label: "Raw AG-UI Events"
506
516
  },
507
517
  {
508
- id: "ag-ui-events",
509
- label: "AG-UI Events"
518
+ id: "state",
519
+ label: "State"
510
520
  }
511
521
  ];
512
522
  }
523
+ static {
524
+ this.providerIds = /* @__PURE__ */ new WeakMap();
525
+ }
526
+ static {
527
+ this.nextProviderId = 1;
528
+ }
529
+ static providerLoadKey(provider) {
530
+ if (!provider) return "provider:none";
531
+ let id = CpkThreadInspector.providerIds.get(provider);
532
+ if (!id) {
533
+ id = CpkThreadInspector.nextProviderId;
534
+ CpkThreadInspector.nextProviderId += 1;
535
+ CpkThreadInspector.providerIds.set(provider, id);
536
+ }
537
+ return [
538
+ `provider:${id}`,
539
+ provider.getThreadMetadata ? "metadata:1" : "metadata:0",
540
+ provider.getMessages ? "messages:1" : "messages:0",
541
+ provider.getEvents ? "events:1" : "events:0",
542
+ provider.getState ? "state:1" : "state:0"
543
+ ].join("|");
544
+ }
545
+ /**
546
+ * Build a deterministic signature for runtime fetch headers so auth/CSRF
547
+ * changes invalidate cached thread data even when the selected thread is
548
+ * otherwise unchanged.
549
+ */
550
+ static headersLoadKey(headers) {
551
+ return JSON.stringify(Object.entries(headers).sort(([leftKey], [rightKey]) => leftKey.localeCompare(rightKey)));
552
+ }
513
553
  renderTabContent(id) {
514
- if (id === "conversation") return this.renderConversation();
515
- if (id === "agent-state") return this.renderState();
554
+ if (id === "timeline") return this.renderTimeline();
555
+ if (id === "state") return this.renderState();
516
556
  return this.renderEvents();
517
557
  }
518
558
  activateTab(id) {
@@ -530,10 +570,10 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
530
570
  }
531
571
  maybeFetchTabData(id) {
532
572
  if (!this.threadId) return;
533
- if (id === "ag-ui-events" && !this._eventsFetched) {
573
+ if ((id === "timeline" || id === "raw-events") && !this._eventsFetched) {
534
574
  this._eventsFetched = true;
535
575
  this.fetchEvents(this.threadId);
536
- } else if (id === "agent-state" && !this._stateFetched) {
576
+ } else if (id === "state" && !this._stateFetched) {
537
577
  this._stateFetched = true;
538
578
  this.fetchState(this.threadId);
539
579
  }
@@ -665,6 +705,42 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
665
705
  flex-shrink: 0;
666
706
  }
667
707
 
708
+ .cpk-td__metadata-strip {
709
+ display: flex;
710
+ gap: 6px;
711
+ flex-wrap: wrap;
712
+ padding: 10px 16px;
713
+ border-bottom: 1px solid #e9e9ef;
714
+ background: #fbfbfd;
715
+ flex-shrink: 0;
716
+ }
717
+
718
+ .cpk-td__metadata-pill {
719
+ display: inline-flex;
720
+ align-items: center;
721
+ gap: 5px;
722
+ max-width: 220px;
723
+ padding: 3px 7px;
724
+ border: 1px solid #e9e9ef;
725
+ border-radius: 5px;
726
+ background: #ffffff;
727
+ color: #57575b;
728
+ font-family: "Spline Sans Mono", monospace;
729
+ font-size: 10px;
730
+ white-space: nowrap;
731
+ }
732
+
733
+ .cpk-td__metadata-label {
734
+ color: #838389;
735
+ text-transform: uppercase;
736
+ font-size: 9px;
737
+ }
738
+
739
+ .cpk-td__metadata-value {
740
+ overflow: hidden;
741
+ text-overflow: ellipsis;
742
+ }
743
+
668
744
  /*
669
745
  * Each tab's content is wrapped in this panel so the keep-mounted
670
746
  * inactive panels can be hidden via display:none without disturbing
@@ -885,6 +961,81 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
885
961
  background: #e9e9ef;
886
962
  }
887
963
 
964
+ /* ── Interaction timeline ───────────────────────────────────────── */
965
+ .cpk-td__timeline-item {
966
+ border: 1px solid #e9e9ef;
967
+ border-radius: 6px;
968
+ background: #ffffff;
969
+ overflow: hidden;
970
+ }
971
+
972
+ .cpk-td__timeline-item--warning {
973
+ border-color: rgba(250, 95, 103, 0.35);
974
+ background: rgba(250, 95, 103, 0.04);
975
+ }
976
+
977
+ .cpk-td__timeline-header {
978
+ display: flex;
979
+ align-items: center;
980
+ gap: 8px;
981
+ padding: 7px 10px;
982
+ background: #f7f7f9;
983
+ }
984
+
985
+ .cpk-td__timeline-kind {
986
+ font-family: "Spline Sans Mono", monospace;
987
+ font-size: 9px;
988
+ font-weight: 600;
989
+ text-transform: uppercase;
990
+ color: #5558b2;
991
+ }
992
+
993
+ .cpk-td__timeline-title {
994
+ flex: 1;
995
+ min-width: 0;
996
+ font-size: 12px;
997
+ font-weight: 500;
998
+ color: #010507;
999
+ overflow: hidden;
1000
+ text-overflow: ellipsis;
1001
+ white-space: nowrap;
1002
+ }
1003
+
1004
+ .cpk-td__timeline-time {
1005
+ font-family: "Spline Sans Mono", monospace;
1006
+ font-size: 9px;
1007
+ color: #838389;
1008
+ flex-shrink: 0;
1009
+ }
1010
+
1011
+ .cpk-td__timeline-body {
1012
+ padding: 9px 10px;
1013
+ font-size: 12px;
1014
+ line-height: 1.55;
1015
+ color: #57575b;
1016
+ white-space: pre-wrap;
1017
+ word-break: break-word;
1018
+ border-top: 1px solid #e9e9ef;
1019
+ }
1020
+
1021
+ .cpk-td__source-link {
1022
+ margin: 0;
1023
+ padding: 0;
1024
+ border: none;
1025
+ background: transparent;
1026
+ color: #5558b2;
1027
+ cursor: pointer;
1028
+ font-family: "Spline Sans Mono", monospace;
1029
+ font-size: 9px;
1030
+ text-decoration: underline;
1031
+ text-underline-offset: 2px;
1032
+ flex-shrink: 0;
1033
+ }
1034
+
1035
+ .cpk-td__source-link:hover {
1036
+ color: #010507;
1037
+ }
1038
+
888
1039
  /* ── Generative UI ──────────────────────────────────────────────── */
889
1040
  @keyframes cpk-genui-enter {
890
1041
  from {
@@ -1094,26 +1245,21 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
1094
1245
  `;
1095
1246
  }
1096
1247
  updated(_changed) {
1097
- if (this.threadId !== this._lastFetchedThreadId) {
1098
- this._lastFetchedThreadId = this.threadId;
1248
+ const loadKey = this.currentLoadKey();
1249
+ if (loadKey !== this._lastLoadKey) {
1250
+ this._lastLoadKey = loadKey;
1099
1251
  this._lastSeenLiveMessageVersion = this.liveMessageVersion;
1100
- this._tab = "conversation";
1101
- this._activatedTabs = new Set(["conversation"]);
1102
- this._panelTplCache = /* @__PURE__ */ new Map();
1103
- this._expandedTools = /* @__PURE__ */ new Set();
1104
- this._expandedMessages = /* @__PURE__ */ new Set();
1105
- this._messagesAbort?.abort();
1106
- this._messagesAbort = null;
1107
- this._eventsAbort?.abort();
1108
- this._eventsAbort = null;
1109
- this._stateAbort?.abort();
1110
- this._stateAbort = null;
1111
- this._eventsFetched = false;
1112
- this._stateFetched = false;
1113
- this._fetchedEvents = null;
1114
- this._fetchedState = null;
1115
- if (this.threadId) this.fetchMessages(this.threadId);
1116
- else this._conversation = [];
1252
+ this.resetLoadedThreadData();
1253
+ if (this.threadId) {
1254
+ this.fetchMetadata(this.threadId);
1255
+ if (this.canFetchEvents()) {
1256
+ this._eventsFetched = true;
1257
+ this.fetchEvents(this.threadId);
1258
+ } else this.fetchMessages(this.threadId);
1259
+ } else {
1260
+ this._fetchedMetadata = null;
1261
+ this._conversation = [];
1262
+ }
1117
1263
  } else if (this.threadId && this.liveMessageVersion !== this._lastSeenLiveMessageVersion) {
1118
1264
  this._lastSeenLiveMessageVersion = this.liveMessageVersion;
1119
1265
  this._messagesAbort?.abort();
@@ -1121,6 +1267,70 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
1121
1267
  this.fetchMessages(this.threadId, true);
1122
1268
  }
1123
1269
  }
1270
+ canFetchMessages() {
1271
+ return !!this.provider?.getMessages || !!this.runtimeUrl && this.threadInspectionAvailable;
1272
+ }
1273
+ canFetchEvents() {
1274
+ return !!this.provider?.getEvents || !!this.runtimeUrl && this.threadInspectionAvailable;
1275
+ }
1276
+ canFetchState() {
1277
+ return !!this.provider?.getState || !!this.runtimeUrl && this.threadInspectionAvailable;
1278
+ }
1279
+ currentLoadKey() {
1280
+ return [
1281
+ this.threadId ?? "thread:none",
1282
+ CpkThreadInspector.providerLoadKey(this.provider),
1283
+ `runtime:${this.runtimeUrl}`,
1284
+ `headers:${CpkThreadInspector.headersLoadKey(this.headers)}`,
1285
+ `inspect:${this.threadInspectionAvailable ? "1" : "0"}`
1286
+ ].join("||");
1287
+ }
1288
+ resetLoadedThreadData() {
1289
+ this._tab = "timeline";
1290
+ this._activatedTabs = new Set(["timeline"]);
1291
+ this._panelTplCache = /* @__PURE__ */ new Map();
1292
+ this._timelineItemsCache = null;
1293
+ this._liveEventsWithSourceIndexCache = null;
1294
+ this._expandedTools = /* @__PURE__ */ new Set();
1295
+ this._expandedMessages = /* @__PURE__ */ new Set();
1296
+ this._metadataAbort?.abort();
1297
+ this._metadataAbort = null;
1298
+ this._messagesAbort?.abort();
1299
+ this._messagesAbort = null;
1300
+ this._eventsAbort?.abort();
1301
+ this._eventsAbort = null;
1302
+ this._stateAbort?.abort();
1303
+ this._stateAbort = null;
1304
+ this._eventsFetched = false;
1305
+ this._stateFetched = false;
1306
+ this._eventsNotAvailable = false;
1307
+ this._stateNotAvailable = false;
1308
+ this._loadingMessages = false;
1309
+ this._loadingEvents = false;
1310
+ this._loadingState = false;
1311
+ this._messagesError = null;
1312
+ this._eventsError = null;
1313
+ this._stateError = null;
1314
+ this._fetchedMetadata = null;
1315
+ this._conversation = [];
1316
+ this._fetchedEvents = null;
1317
+ this._fetchedState = null;
1318
+ }
1319
+ async fetchMetadata(threadId) {
1320
+ if (!this.provider?.getThreadMetadata) return;
1321
+ this._metadataAbort?.abort();
1322
+ const controller = new AbortController();
1323
+ this._metadataAbort = controller;
1324
+ try {
1325
+ const metadata = await this.provider.getThreadMetadata(threadId, { signal: controller.signal });
1326
+ if (controller.signal.aborted || this.threadId !== threadId) return;
1327
+ this._fetchedMetadata = metadata;
1328
+ } catch (err) {
1329
+ if (err instanceof Error && err.name === "AbortError") return;
1330
+ if (this.threadId !== threadId) return;
1331
+ this._fetchedMetadata = null;
1332
+ }
1333
+ }
1124
1334
  /**
1125
1335
  * Fetch the canonical conversation for `threadId` from the runtime.
1126
1336
  *
@@ -1132,10 +1342,11 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
1132
1342
  * so users see an explicit loading indicator on first load.
1133
1343
  */
1134
1344
  async fetchMessages(threadId, silent = false) {
1135
- if (!this.runtimeUrl || !this.threadInspectionAvailable) {
1345
+ if (!this.canFetchMessages()) {
1136
1346
  if (!silent) this._conversation = [];
1137
1347
  return;
1138
1348
  }
1349
+ this._messagesAbort?.abort();
1139
1350
  const controller = new AbortController();
1140
1351
  this._messagesAbort = controller;
1141
1352
  if (!silent) {
@@ -1143,15 +1354,9 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
1143
1354
  this._messagesError = null;
1144
1355
  }
1145
1356
  try {
1146
- const res = await fetch(this.getThreadInspectionUrl(threadId, "messages"), {
1147
- headers: { ...this.headers },
1148
- signal: controller.signal
1149
- });
1150
- if (controller.signal.aborted || this.threadId !== threadId) return;
1151
- if (!res.ok) throw new Error(`HTTP ${res.status}`);
1152
- const data = await res.json();
1357
+ const messages = this.provider?.getMessages ? await this.provider.getMessages(threadId, { signal: controller.signal }) : await this.fetchRuntimeMessages(threadId, controller.signal);
1153
1358
  if (controller.signal.aborted || this.threadId !== threadId) return;
1154
- this._conversation = this.mapMessages(data.messages);
1359
+ this._conversation = this.mapMessages(messages);
1155
1360
  } catch (err) {
1156
1361
  if (err instanceof Error && err.name === "AbortError") return;
1157
1362
  if (!silent) {
@@ -1163,64 +1368,62 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
1163
1368
  }
1164
1369
  }
1165
1370
  async fetchEvents(threadId) {
1166
- this._eventsNotAvailable = false;
1167
- if (!this.runtimeUrl || !this.threadInspectionAvailable) {
1371
+ if (!this.canFetchEvents()) {
1168
1372
  this._fetchedEvents = null;
1169
1373
  return;
1170
1374
  }
1375
+ this._eventsAbort?.abort();
1171
1376
  const controller = new AbortController();
1172
1377
  this._eventsAbort = controller;
1173
1378
  this._loadingEvents = true;
1174
1379
  this._eventsError = null;
1175
1380
  try {
1176
- const res = await fetch(this.getThreadInspectionUrl(threadId, "events"), {
1177
- headers: { ...this.headers },
1178
- signal: controller.signal
1179
- });
1381
+ const result = this.provider?.getEvents ? {
1382
+ status: "available",
1383
+ events: await this.provider.getEvents(threadId, { signal: controller.signal })
1384
+ } : await this.fetchRuntimeEvents(threadId, controller.signal);
1180
1385
  if (controller.signal.aborted || this.threadId !== threadId) return;
1181
- if (res.status === 501) {
1386
+ if (result.status === "not-available") {
1182
1387
  this._eventsNotAvailable = true;
1183
- this._fetchedEvents = null;
1388
+ this._fetchedEvents = [];
1389
+ if (this.canFetchMessages()) this.fetchMessages(threadId);
1184
1390
  return;
1185
1391
  }
1186
- if (!res.ok) throw new Error(`HTTP ${res.status}`);
1187
- const data = await res.json();
1188
- if (controller.signal.aborted || this.threadId !== threadId) return;
1189
- this._fetchedEvents = this.mapApiEvents(data.events);
1392
+ const mappedEvents = this.mapApiEvents(result.events);
1393
+ this._fetchedEvents = mappedEvents;
1394
+ if (mappedEvents.length === 0 && this.canFetchMessages()) this.fetchMessages(threadId);
1190
1395
  } catch (err) {
1191
1396
  if (err instanceof Error && err.name === "AbortError") return;
1192
1397
  if (this.threadId !== threadId) return;
1193
1398
  this._eventsError = err instanceof Error ? err.message : "Failed to load events";
1194
1399
  this._fetchedEvents = [];
1400
+ if (this.canFetchMessages()) this.fetchMessages(threadId);
1195
1401
  } finally {
1196
1402
  if (!controller.signal.aborted && this.threadId === threadId) this._loadingEvents = false;
1197
1403
  }
1198
1404
  }
1199
1405
  async fetchState(threadId) {
1200
- this._stateNotAvailable = false;
1201
- if (!this.runtimeUrl || !this.threadInspectionAvailable) {
1406
+ if (!this.canFetchState()) {
1202
1407
  this._fetchedState = null;
1203
1408
  return;
1204
1409
  }
1410
+ this._stateAbort?.abort();
1205
1411
  const controller = new AbortController();
1206
1412
  this._stateAbort = controller;
1207
1413
  this._loadingState = true;
1208
1414
  this._stateError = null;
1209
1415
  try {
1210
- const res = await fetch(this.getThreadInspectionUrl(threadId, "state"), {
1211
- headers: { ...this.headers },
1212
- signal: controller.signal
1213
- });
1416
+ const result = this.provider?.getState ? {
1417
+ status: "available",
1418
+ state: await this.provider.getState(threadId, { signal: controller.signal })
1419
+ } : await this.fetchRuntimeState(threadId, controller.signal);
1214
1420
  if (controller.signal.aborted || this.threadId !== threadId) return;
1215
- if (res.status === 501) {
1421
+ if (result.status === "not-available") {
1216
1422
  this._stateNotAvailable = true;
1217
1423
  this._fetchedState = null;
1218
1424
  return;
1219
1425
  }
1220
- if (!res.ok) throw new Error(`HTTP ${res.status}`);
1221
- const data = await res.json();
1222
- if (controller.signal.aborted || this.threadId !== threadId) return;
1223
- this._fetchedState = data.state ?? null;
1426
+ this._fetchedState = result.state ?? null;
1224
1427
  } catch (err) {
1225
1428
  if (err instanceof Error && err.name === "AbortError") return;
1226
1429
  if (this.threadId !== threadId) return;
@@ -1230,6 +1433,38 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
1230
1433
  if (!controller.signal.aborted && this.threadId === threadId) this._loadingState = false;
1231
1434
  }
1232
1435
  }
1436
+ async fetchRuntimeMessages(threadId, signal) {
1437
+ const res = await fetch(this.getThreadInspectionUrl(threadId, "messages"), {
1438
+ headers: { ...this.headers },
1439
+ signal
1440
+ });
1441
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
1442
+ return (await res.json()).messages;
1443
+ }
1444
+ async fetchRuntimeEvents(threadId, signal) {
1445
+ const res = await fetch(this.getThreadInspectionUrl(threadId, "events"), {
1446
+ headers: { ...this.headers },
1447
+ signal
1448
+ });
1449
+ if (res.status === 501) return { status: "not-available" };
1450
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
1451
+ return {
1452
+ status: "available",
1453
+ events: (await res.json()).events
1454
+ };
1455
+ }
1456
+ async fetchRuntimeState(threadId, signal) {
1457
+ const res = await fetch(this.getThreadInspectionUrl(threadId, "state"), {
1458
+ headers: { ...this.headers },
1459
+ signal
1460
+ });
1461
+ if (res.status === 501) return { status: "not-available" };
1462
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
1463
+ return {
1464
+ status: "available",
1465
+ state: (await res.json()).state ?? null
1466
+ };
1467
+ }
1233
1468
  getThreadInspectionUrl(threadId, resource) {
1234
1469
  return `${this.runtimeUrl.replace(/\/+$/, "")}/threads/${encodeURIComponent(threadId)}/${resource}`;
1235
1470
  }
@@ -1245,7 +1480,7 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
1245
1480
  else if (msg.role === "assistant") {
1246
1481
  if (msg.toolCalls?.length) for (const tc of msg.toolCalls) {
1247
1482
  let args = {};
1248
- try {
1483
+ if (typeof tc.args === "string") try {
1249
1484
  args = JSON.parse(tc.args);
1250
1485
  } catch (err) {
1251
1486
  console.error("[CopilotKit Inspector] Failed to parse tool-call arguments", {
@@ -1258,6 +1493,7 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
1258
1493
  __raw: tc.args
1259
1494
  };
1260
1495
  }
1496
+ else args = tc.args;
1261
1497
  const item = {
1262
1498
  id: tc.id,
1263
1499
  type: "tool_call",
@@ -1301,15 +1537,232 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
1301
1537
  return items;
1302
1538
  }
1303
1539
  mapApiEvents(events) {
1304
- return events.map((event) => {
1305
- const { type, timestamp, ...rest } = event;
1540
+ return events.map((event, index) => {
1541
+ const { type, timestamp, payload, ...rest } = event;
1306
1542
  return {
1307
1543
  type: typeof type === "string" ? type : "UNKNOWN",
1308
1544
  timestamp: typeof timestamp === "string" || typeof timestamp === "number" ? timestamp : Date.now(),
1309
- payload: rest
1545
+ payload: payload ?? rest,
1546
+ sourceIndex: index + 1,
1547
+ rawEvent: event
1310
1548
  };
1311
1549
  });
1312
1550
  }
1551
+ get activeTimelineItems() {
1552
+ return this.timelineItemsForEvents(this.activeEvents);
1553
+ }
1554
+ timelineItemsForEvents(events) {
1555
+ if (this._timelineItemsCache?.events === events) return this._timelineItemsCache.items;
1556
+ const items = this.timelineItemsFromEvents(events);
1557
+ this._timelineItemsCache = {
1558
+ events,
1559
+ items
1560
+ };
1561
+ return items;
1562
+ }
1563
+ timelineItemsFromEvents(events) {
1564
+ if (events.length === 0) return [];
1565
+ const items = [];
1566
+ const messageItems = /* @__PURE__ */ new Map();
1567
+ const toolItems = /* @__PURE__ */ new Map();
1568
+ const readString = (payload, keys) => {
1569
+ for (const key of keys) {
1570
+ const value = payload[key];
1571
+ if (typeof value === "string") return value;
1572
+ }
1573
+ return null;
1574
+ };
1575
+ const sourceIndexFor = (event) => event.sourceIndex ?? 0;
1576
+ const appendWarning = (event, title, body, severity = "warning") => {
1577
+ const sourceIndex = sourceIndexFor(event);
1578
+ items.push({
1579
+ id: `warning-${sourceIndex}-${items.length}`,
1580
+ kind: "warning",
1581
+ title,
1582
+ body,
1583
+ timestamp: event.timestamp,
1584
+ sourceIndex,
1585
+ severity
1586
+ });
1587
+ };
1588
+ const ensureMessage = (event, role) => {
1589
+ const sourceIndex = sourceIndexFor(event);
1590
+ const key = readString(event.payload, [
1591
+ "messageId",
1592
+ "message_id",
1593
+ "id"
1594
+ ]) ?? `message-${sourceIndex}`;
1595
+ let item = messageItems.get(key);
1596
+ if (!item) {
1597
+ item = {
1598
+ id: `message-${key}`,
1599
+ kind: "message",
1600
+ title: `${role || "message"} message`,
1601
+ body: "",
1602
+ timestamp: event.timestamp,
1603
+ sourceIndex
1604
+ };
1605
+ messageItems.set(key, item);
1606
+ items.push(item);
1607
+ }
1608
+ return item;
1609
+ };
1610
+ const ensureTool = (event) => {
1611
+ const sourceIndex = sourceIndexFor(event);
1612
+ const key = readString(event.payload, [
1613
+ "toolCallId",
1614
+ "tool_call_id",
1615
+ "id",
1616
+ "callId"
1617
+ ]) ?? `tool-${sourceIndex}`;
1618
+ let item = toolItems.get(key);
1619
+ if (!item) {
1620
+ item = {
1621
+ id: `tool-${key}`,
1622
+ kind: "tool",
1623
+ title: readString(event.payload, [
1624
+ "toolCallName",
1625
+ "toolName",
1626
+ "name",
1627
+ "functionName"
1628
+ ]) ?? "Tool call",
1629
+ body: "",
1630
+ timestamp: event.timestamp,
1631
+ sourceIndex
1632
+ };
1633
+ toolItems.set(key, item);
1634
+ items.push(item);
1635
+ }
1636
+ return item;
1637
+ };
1638
+ for (const event of events) {
1639
+ const { type, payload } = event;
1640
+ const sourceIndex = sourceIndexFor(event);
1641
+ if (type === "UNKNOWN") {
1642
+ appendWarning(event, "Unknown AG-UI event", "The event is missing a string type and could not be normalized.");
1643
+ continue;
1644
+ }
1645
+ if (type === "RUN_STARTED" || type === "STEP_STARTED") {
1646
+ items.push({
1647
+ id: `${type}-${sourceIndex}`,
1648
+ kind: "run",
1649
+ title: type === "RUN_STARTED" ? "Run started" : "Step started",
1650
+ timestamp: event.timestamp,
1651
+ sourceIndex,
1652
+ details: payload
1653
+ });
1654
+ continue;
1655
+ }
1656
+ if (type === "RUN_FINISHED" || type === "STEP_FINISHED") {
1657
+ items.push({
1658
+ id: `${type}-${sourceIndex}`,
1659
+ kind: "run",
1660
+ title: type === "RUN_FINISHED" ? "Run finished" : "Step finished",
1661
+ timestamp: event.timestamp,
1662
+ sourceIndex,
1663
+ details: payload
1664
+ });
1665
+ continue;
1666
+ }
1667
+ if (type === "RUN_ERROR" || type === "ERROR") {
1668
+ items.push({
1669
+ id: `${type}-${sourceIndex}`,
1670
+ kind: "warning",
1671
+ title: "Run error",
1672
+ body: readString(payload, [
1673
+ "message",
1674
+ "error",
1675
+ "description"
1676
+ ]) ?? "",
1677
+ timestamp: event.timestamp,
1678
+ sourceIndex,
1679
+ severity: "error",
1680
+ details: payload
1681
+ });
1682
+ continue;
1683
+ }
1684
+ if (type === "TEXT_MESSAGE_START") {
1685
+ ensureMessage(event, readString(payload, ["role"]) ?? "assistant");
1686
+ continue;
1687
+ }
1688
+ if (type === "TEXT_MESSAGE_CONTENT") {
1689
+ const item = ensureMessage(event, readString(payload, ["role"]) ?? "assistant");
1690
+ item.body = `${item.body ?? ""}${readString(payload, [
1691
+ "delta",
1692
+ "content",
1693
+ "text"
1694
+ ]) ?? ""}`;
1695
+ continue;
1696
+ }
1697
+ if (type === "TEXT_MESSAGE_END") {
1698
+ ensureMessage(event, readString(payload, ["role"]) ?? "assistant");
1699
+ continue;
1700
+ }
1701
+ if (type === "TOOL_CALL_START") {
1702
+ ensureTool(event);
1703
+ continue;
1704
+ }
1705
+ if (type === "TOOL_CALL_ARGS") {
1706
+ const item = ensureTool(event);
1707
+ const chunk = readString(payload, [
1708
+ "args",
1709
+ "arguments",
1710
+ "delta"
1711
+ ]) ?? (typeof payload.args === "object" ? JSON.stringify(payload.args) : null);
1712
+ if (chunk) {
1713
+ item.rawArgs = `${item.rawArgs ?? ""}${chunk}`;
1714
+ item.body = item.rawArgs;
1715
+ }
1716
+ continue;
1717
+ }
1718
+ if (type === "TOOL_CALL_END") {
1719
+ const item = ensureTool(event);
1720
+ if (item.rawArgs) try {
1721
+ JSON.parse(item.rawArgs);
1722
+ } catch {
1723
+ appendWarning(event, "Could not decode tool call arguments", item.rawArgs);
1724
+ }
1725
+ continue;
1726
+ }
1727
+ if (type === "TOOL_CALL_RESULT") {
1728
+ const item = ensureTool(event);
1729
+ const result = readString(payload, [
1730
+ "result",
1731
+ "content",
1732
+ "delta"
1733
+ ]);
1734
+ if (result) {
1735
+ item.body = item.body ? `${item.body}\nResult: ${result}` : `Result: ${result}`;
1736
+ try {
1737
+ JSON.parse(result);
1738
+ } catch {
1739
+ appendWarning(event, "Could not decode tool result", result);
1740
+ }
1741
+ }
1742
+ continue;
1743
+ }
1744
+ if (type.startsWith("STATE_")) {
1745
+ items.push({
1746
+ id: `${type}-${sourceIndex}`,
1747
+ kind: "state",
1748
+ title: type === "STATE_SNAPSHOT" ? "State snapshot captured" : "State delta captured",
1749
+ timestamp: event.timestamp,
1750
+ sourceIndex,
1751
+ details: payload
1752
+ });
1753
+ continue;
1754
+ }
1755
+ items.push({
1756
+ id: `event-${sourceIndex}`,
1757
+ kind: "event",
1758
+ title: type,
1759
+ timestamp: event.timestamp,
1760
+ sourceIndex,
1761
+ details: payload
1762
+ });
1763
+ }
1764
+ return items;
1765
+ }
1313
1766
  get renderItems() {
1314
1767
  const items = this._conversation;
1315
1768
  const result = [];
@@ -1347,7 +1800,7 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
1347
1800
  };
1348
1801
  }
1349
1802
  get duration() {
1350
- const t = this.thread;
1803
+ const t = this.metadata;
1351
1804
  if (!t?.createdAt || !t?.updatedAt) return "—";
1352
1805
  const ms = new Date(t.updatedAt).getTime() - new Date(t.createdAt).getTime();
1353
1806
  if (ms < 0) return "—";
@@ -1370,7 +1823,18 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
1370
1823
  }
1371
1824
  get activeEvents() {
1372
1825
  if (this._eventsNotAvailable) return [];
1373
- return this._fetchedEvents ?? this.agentEventsInput ?? [];
1826
+ const events = this._fetchedEvents ?? this.agentEventsInput ?? [];
1827
+ if (events.every((event) => event.sourceIndex != null)) return events;
1828
+ if (this._liveEventsWithSourceIndexCache?.events === events) return this._liveEventsWithSourceIndexCache.indexedEvents;
1829
+ const indexedEvents = events.map((event, index) => event.sourceIndex == null ? {
1830
+ ...event,
1831
+ sourceIndex: index + 1
1832
+ } : event);
1833
+ this._liveEventsWithSourceIndexCache = {
1834
+ events,
1835
+ indexedEvents
1836
+ };
1837
+ return indexedEvents;
1374
1838
  }
1375
1839
  get activeState() {
1376
1840
  if (this._stateNotAvailable) return null;
@@ -1384,6 +1848,9 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
1384
1848
  if (!id) return "—";
1385
1849
  return id.length > 20 ? id.slice(0, 8) + "…" : id;
1386
1850
  }
1851
+ get metadata() {
1852
+ return this._fetchedMetadata ?? this.thread ?? null;
1853
+ }
1387
1854
  fmtTime(dateStr) {
1388
1855
  if (!dateStr) return "—";
1389
1856
  const d = new Date(dateStr);
@@ -1403,7 +1870,7 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
1403
1870
  <!-- Tab bar -->
1404
1871
  <div class="cpk-td__tabs-header">
1405
1872
  <div class="cpk-td__tab-group" role="tablist">
1406
- ${ɵCpkThreadDetails.TAB_LIST.map((tab) => lit.html`
1873
+ ${CpkThreadInspector.TAB_LIST.map((tab) => lit.html`
1407
1874
  <button
1408
1875
  role="tab"
1409
1876
  class="cpk-td__tab ${this._tab === tab.id ? "cpk-td__tab--active" : ""}"
@@ -1415,18 +1882,19 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
1415
1882
  </div>
1416
1883
  ${this.renderPanelToggle()}
1417
1884
  </div>
1885
+ ${this.renderMetadataStrip()}
1418
1886
 
1419
1887
  <!-- Scrollable content -->
1420
1888
  <div class="cpk-td__content">
1421
1889
  ${this._panelInitializing ? lit.html`
1422
1890
  <div class="cpk-td__status">Loading…</div>
1423
1891
  ` : lit.nothing}
1424
- ${ɵCpkThreadDetails.TAB_LIST.map((tab) => this._activatedTabs.has(tab.id) ? lit.html`<div
1425
- class="cpk-td__panel"
1426
- style=${this._tab === tab.id && !this._panelInitializing ? "" : "display:none"}
1427
- >
1428
- ${this.renderTabContent(tab.id)}
1429
- </div>` : lit.nothing)}
1892
+ ${CpkThreadInspector.TAB_LIST.map((tab) => this._activatedTabs.has(tab.id) ? lit.html`<div
1893
+ class="cpk-td__panel"
1894
+ style=${this._tab === tab.id && !this._panelInitializing ? "" : "display:none"}
1895
+ >
1896
+ ${this.renderTabContent(tab.id)}
1897
+ </div>` : lit.nothing)}
1430
1898
  </div>
1431
1899
  </div>
1432
1900
 
@@ -1454,6 +1922,116 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
1454
1922
  ${this.renderDetailPanel()}
1455
1923
  </div>
1456
1924
  </div>
1925
+ `;
1926
+ }
1927
+ renderMetadataStrip() {
1928
+ const metadata = this.metadata;
1929
+ const pills = [
1930
+ {
1931
+ label: "Thread",
1932
+ value: metadata?.id ?? this.threadId
1933
+ },
1934
+ {
1935
+ label: "Agent",
1936
+ value: metadata?.agentId
1937
+ },
1938
+ {
1939
+ label: "End user",
1940
+ value: metadata?.endUserId ?? metadata?.createdById
1941
+ },
1942
+ {
1943
+ label: "Status",
1944
+ value: metadata?.status
1945
+ }
1946
+ ].filter((pill) => pill.value != null && pill.value !== "");
1947
+ if (pills.length === 0) return lit.nothing;
1948
+ return lit.html`
1949
+ <div class="cpk-td__metadata-strip" aria-label="Thread metadata">
1950
+ ${pills.map((pill) => lit.html`
1951
+ <span class="cpk-td__metadata-pill" title=${pill.value ?? ""}>
1952
+ <span class="cpk-td__metadata-label">${pill.label}</span>
1953
+ <span class="cpk-td__metadata-value"
1954
+ >${this.shortId(pill.value)}</span
1955
+ >
1956
+ </span>
1957
+ `)}
1958
+ </div>
1959
+ `;
1960
+ }
1961
+ revealSourceEvent(sourceIndex) {
1962
+ this._activatedTabs = new Set([...this._activatedTabs, "raw-events"]);
1963
+ this._tab = "raw-events";
1964
+ this.requestUpdate();
1965
+ requestAnimationFrame(() => {
1966
+ (this.shadowRoot?.querySelector(`[data-source-index="${sourceIndex}"]`))?.scrollIntoView?.({ block: "center" });
1967
+ });
1968
+ }
1969
+ renderTimeline() {
1970
+ if (this._loadingEvents) return lit.html`
1971
+ <div class="cpk-td__status">Loading timeline…</div>
1972
+ `;
1973
+ if (this._eventsError) return lit.html`<div class="cpk-td__status cpk-td__status--error">
1974
+ ${this._eventsError}
1975
+ </div>`;
1976
+ if (this._eventsNotAvailable) {
1977
+ if (this._conversation.length > 0) return this.renderConversation();
1978
+ if (this._loadingMessages) return this.renderConversation();
1979
+ return lit.html`
1980
+ <div class="cpk-td__empty-state">
1981
+ <span>Timeline event history not available</span>
1982
+ <span class="cpk-td__empty-hint"
1983
+ >This runtime doesn't yet expose per-thread AG-UI events. Check State for
1984
+ the latest snapshot when available.</span
1985
+ >
1986
+ </div>
1987
+ `;
1988
+ }
1989
+ const events = this.activeEvents;
1990
+ const cachedTimeline = this.getCachedPanelTpl("timeline", [events]);
1991
+ if (cachedTimeline) return cachedTimeline;
1992
+ const timelineItems = this.timelineItemsForEvents(events);
1993
+ if (timelineItems.length === 0) {
1994
+ if (this._conversation.length > 0) return this.renderConversation();
1995
+ if (this._loadingMessages) return this.renderConversation();
1996
+ return lit.html`
1997
+ <div class="cpk-td__empty-state">
1998
+ <span>No timeline events captured</span>
1999
+ <span class="cpk-td__empty-hint"
2000
+ >Timeline rows are normalized from AG-UI events. Open Raw AG-UI Events or
2001
+ State to inspect the available thread data.</span
2002
+ >
2003
+ </div>
2004
+ `;
2005
+ }
2006
+ return this.cachedPanelTpl("timeline", [events], () => {
2007
+ return lit.html`${timelineItems.map((item) => this.renderTimelineItem(item))}`;
2008
+ });
2009
+ }
2010
+ renderTimelineItem(item) {
2011
+ return lit.html`
2012
+ <div
2013
+ class="cpk-td__timeline-item ${item.kind === "warning" ? "cpk-td__timeline-item--warning" : ""}"
2014
+ >
2015
+ <div class="cpk-td__timeline-header">
2016
+ <span class="cpk-td__timeline-kind"
2017
+ >${item.severity === "error" ? "error" : item.kind}</span
2018
+ >
2019
+ <span class="cpk-td__timeline-title">${item.title}</span>
2020
+ <button
2021
+ type="button"
2022
+ class="cpk-td__source-link"
2023
+ @click=${() => this.revealSourceEvent(item.sourceIndex)}
2024
+ >
2025
+ Source event #${item.sourceIndex}
2026
+ </button>
2027
+ <span class="cpk-td__timeline-time"
2028
+ >${formatTimestamp(item.timestamp)}</span
2029
+ >
2030
+ </div>
2031
+ ${item.body ? lit.html`<div class="cpk-td__timeline-body">${item.body}</div>` : item.details ? lit.html`<pre class="cpk-td__timeline-body">
2032
+ ${(0, lit_directives_unsafe_html_js.unsafeHTML)(highlightedJson(item.details))}</pre
2033
+ >` : lit.nothing}
2034
+ </div>
1457
2035
  `;
1458
2036
  }
1459
2037
  renderConversation() {
@@ -1480,7 +2058,7 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
1480
2058
  <span>No messages yet</span>
1481
2059
  </div>
1482
2060
  `;
1483
- return this.cachedPanelTpl("conversation", [
2061
+ return this.cachedPanelTpl("timeline-fallback", [
1484
2062
  this._conversation,
1485
2063
  this._expandedTools,
1486
2064
  this._expandedMessages
@@ -1498,8 +2076,8 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
1498
2076
  * change without the listed key flipping.
1499
2077
  */
1500
2078
  cachedPanelTpl(slot, key, build) {
1501
- const cached = this._panelTplCache.get(slot);
1502
- if (cached && cached.key.length === key.length && cached.key.every((v, i) => v === key[i])) return cached.tpl;
2079
+ const cached = this.getCachedPanelTpl(slot, key);
2080
+ if (cached) return cached;
1503
2081
  const tpl = build();
1504
2082
  this._panelTplCache.set(slot, {
1505
2083
  key,
@@ -1507,6 +2085,11 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
1507
2085
  });
1508
2086
  return tpl;
1509
2087
  }
2088
+ getCachedPanelTpl(slot, key) {
2089
+ const cached = this._panelTplCache.get(slot);
2090
+ if (cached && cached.key.length === key.length && cached.key.every((v, i) => v === key[i])) return cached.tpl;
2091
+ return null;
2092
+ }
1510
2093
  renderRenderItem(item) {
1511
2094
  switch (item.type) {
1512
2095
  case "user":
@@ -1527,7 +2110,7 @@ var ɵCpkThreadDetails = class ɵCpkThreadDetails extends lit.LitElement {
1527
2110
  }
1528
2111
  renderBubble(item) {
1529
2112
  const isUser = item.type === "user";
1530
- const threshold = ɵCpkThreadDetails.COLLAPSE_THRESHOLD;
2113
+ const threshold = CpkThreadInspector.COLLAPSE_THRESHOLD;
1531
2114
  const expanded = this._expandedMessages.has(item.id);
1532
2115
  const tooLong = item.content.length > threshold;
1533
2116
  const shown = tooLong && !expanded ? item.content.slice(0, threshold) + "…" : item.content;
@@ -1673,7 +2256,7 @@ ${(0, lit_directives_unsafe_html_js.unsafeHTML)(highlightedJson(item.result))}</
1673
2256
  </div>
1674
2257
  `;
1675
2258
  const stateValue = this.activeState;
1676
- return this.cachedPanelTpl("agent-state", [stateValue], () => {
2259
+ return this.cachedPanelTpl("state", [stateValue], () => {
1677
2260
  return lit.html`<pre class="cpk-td__json-block">
1678
2261
  ${(0, lit_directives_unsafe_html_js.unsafeHTML)(highlightedJson(stateValue))}</pre
1679
2262
  >`;
@@ -1704,11 +2287,11 @@ ${(0, lit_directives_unsafe_html_js.unsafeHTML)(highlightedJson(stateValue))}</p
1704
2287
  >
1705
2288
  </div>
1706
2289
  `;
1707
- return this.cachedPanelTpl("ag-ui-events", [events], () => {
2290
+ return this.cachedPanelTpl("raw-events", [events], () => {
1708
2291
  return lit.html`${events.map((event) => {
1709
2292
  const { bg, fg } = eventColors(event.type);
1710
2293
  return lit.html`
1711
- <div class="cpk-td__event">
2294
+ <div class="cpk-td__event" data-source-index=${event.sourceIndex}>
1712
2295
  <div class="cpk-td__event-header" style="background:${bg}">
1713
2296
  <span class="cpk-td__event-type" style="color:${fg}"
1714
2297
  >${event.type}</span
@@ -1718,7 +2301,7 @@ ${(0, lit_directives_unsafe_html_js.unsafeHTML)(highlightedJson(stateValue))}</p
1718
2301
  >
1719
2302
  </div>
1720
2303
  <pre class="cpk-td__event-payload">
1721
- ${(0, lit_directives_unsafe_html_js.unsafeHTML)(highlightedJson(event.payload))}</pre
2304
+ ${(0, lit_directives_unsafe_html_js.unsafeHTML)(highlightedJson(event.rawEvent ?? event))}</pre
1722
2305
  >
1723
2306
  </div>
1724
2307
  `;
@@ -1753,29 +2336,42 @@ ${(0, lit_directives_unsafe_html_js.unsafeHTML)(highlightedJson(event.payload))}
1753
2336
  }
1754
2337
  renderDetailPanel() {
1755
2338
  const counts = this.activityCounts;
2339
+ const metadata = this.metadata;
1756
2340
  return lit.html`
1757
2341
  <!-- Thread -->
1758
2342
  <div class="cpk-tdp__section-title">Thread</div>
1759
2343
  <div class="cpk-tdp__row">
1760
2344
  <span class="cpk-tdp__label">ID</span>
1761
2345
  <span class="cpk-tdp__value cpk-tdp__value--wrap"
1762
- >${this.shortId(this.thread?.id)}</span
2346
+ >${this.shortId(metadata?.id)}</span
1763
2347
  >
1764
2348
  </div>
1765
2349
  <div class="cpk-tdp__row">
1766
2350
  <span class="cpk-tdp__label">Name</span>
1767
- <span class="cpk-tdp__value">${this.thread?.name ?? "—"}</span>
2351
+ <span class="cpk-tdp__value">${metadata?.name ?? "—"}</span>
1768
2352
  </div>
1769
2353
  <div class="cpk-tdp__row">
1770
2354
  <span class="cpk-tdp__label">Agent</span>
1771
2355
  <span class="cpk-tdp__value cpk-tdp__value--truncate"
1772
- >${this.thread?.agentId ?? "—"}</span
2356
+ >${metadata?.agentId ?? "—"}</span
2357
+ >
2358
+ </div>
2359
+ <div class="cpk-tdp__row">
2360
+ <span class="cpk-tdp__label">End user</span>
2361
+ <span class="cpk-tdp__value cpk-tdp__value--truncate"
2362
+ >${metadata?.endUserId ?? "—"}</span
1773
2363
  >
1774
2364
  </div>
1775
2365
  <div class="cpk-tdp__row">
1776
2366
  <span class="cpk-tdp__label">Created by</span>
1777
2367
  <span class="cpk-tdp__value cpk-tdp__value--truncate"
1778
- >${this.thread?.createdById ?? "—"}</span
2368
+ >${metadata?.createdById ?? "—"}</span
2369
+ >
2370
+ </div>
2371
+ <div class="cpk-tdp__row">
2372
+ <span class="cpk-tdp__label">Status</span>
2373
+ <span class="cpk-tdp__value cpk-tdp__value--truncate"
2374
+ >${metadata?.status ?? "—"}</span
1779
2375
  >
1780
2376
  </div>
1781
2377
 
@@ -1785,11 +2381,11 @@ ${(0, lit_directives_unsafe_html_js.unsafeHTML)(highlightedJson(event.payload))}
1785
2381
  <div class="cpk-tdp__section-title">Timestamps</div>
1786
2382
  <div class="cpk-tdp__row">
1787
2383
  <span class="cpk-tdp__label">Created</span>
1788
- <span class="cpk-tdp__value">${this.fmtTime(this.thread?.createdAt)}</span>
2384
+ <span class="cpk-tdp__value">${this.fmtTime(metadata?.createdAt)}</span>
1789
2385
  </div>
1790
2386
  <div class="cpk-tdp__row">
1791
2387
  <span class="cpk-tdp__label">Updated</span>
1792
- <span class="cpk-tdp__value">${this.fmtTime(this.thread?.updatedAt)}</span>
2388
+ <span class="cpk-tdp__value">${this.fmtTime(metadata?.updatedAt)}</span>
1793
2389
  </div>
1794
2390
  <div class="cpk-tdp__row">
1795
2391
  <span class="cpk-tdp__label">Duration</span>
@@ -1815,7 +2411,9 @@ ${(0, lit_directives_unsafe_html_js.unsafeHTML)(highlightedJson(event.payload))}
1815
2411
  `;
1816
2412
  }
1817
2413
  };
2414
+ var ɵCpkThreadDetails = class extends CpkThreadInspector {};
1818
2415
  if (!customElements.get("cpk-thread-list")) customElements.define("cpk-thread-list", CpkThreadList);
2416
+ if (!customElements.get(THREAD_INSPECTOR_TAG)) customElements.define(THREAD_INSPECTOR_TAG, CpkThreadInspector);
1819
2417
  if (!customElements.get("cpk-thread-details")) customElements.define("cpk-thread-details", ɵCpkThreadDetails);
1820
2418
  var WebInspectorElement = class extends lit.LitElement {
1821
2419
  constructor(..._args3) {
@@ -2380,6 +2978,7 @@ var WebInspectorElement = class extends lit.LitElement {
2380
2978
  },
2381
2979
  onHeadersChanged: ({ headers }) => {
2382
2980
  this.updateOwnedThreadStoreHeaders(headers);
2981
+ this.requestUpdate();
2383
2982
  },
2384
2983
  onError: ({ code, error }) => {
2385
2984
  this.lastCoreError = {
@@ -2391,6 +2990,9 @@ var WebInspectorElement = class extends lit.LitElement {
2391
2990
  onAgentsChanged: ({ agents }) => {
2392
2991
  this.processAgentsChanged(agents);
2393
2992
  },
2993
+ onAgentRunStarted: ({ agent }) => {
2994
+ if (agent?.agentId) this.subscribeToAgent(agent);
2995
+ },
2394
2996
  onContextChanged: ({ context }) => {
2395
2997
  this.contextStore = this.normalizeContextStore(context);
2396
2998
  this.requestUpdate();
@@ -4359,7 +4961,9 @@ ${argsString}</pre
4359
4961
 
4360
4962
  <div class="space-y-2">
4361
4963
  <h3 class="text-sm text-slate-500">Privacy</h3>
4362
- <div class="rounded-lg border border-slate-200 bg-white p-4 space-y-3">
4964
+ <div
4965
+ class="rounded-lg border border-slate-200 bg-white p-4 space-y-3"
4966
+ >
4363
4967
  <p class="text-sm text-gray-600 flex items-start gap-2">
4364
4968
  <span>${optedOut ? "❌" : "✅"}</span>
4365
4969
  <span>
@@ -4371,7 +4975,8 @@ ${argsString}</pre
4371
4975
  href=${require_telemetry.TELEMETRY_DOCS_URL}
4372
4976
  target="_blank"
4373
4977
  rel="noopener"
4374
- >Learn more →</a>
4978
+ >Learn more →</a
4979
+ >
4375
4980
  </div>
4376
4981
  </div>
4377
4982
  </div>
@@ -4901,10 +5506,10 @@ ${argsString}</pre
4901
5506
  <div class="relative h-full w-full overflow-y-auto overflow-x-hidden">
4902
5507
  <table class="w-full table-fixed border-collapse text-xs box-border">
4903
5508
  <colgroup>
4904
- <col style="width:${this.evtColWidths[0]}px">
4905
- <col style="width:${this.evtColWidths[1]}px">
4906
- <col style="width:${this.evtColWidths[2]}px">
4907
- <col>
5509
+ <col style="width:${this.evtColWidths[0]}px" />
5510
+ <col style="width:${this.evtColWidths[1]}px" />
5511
+ <col style="width:${this.evtColWidths[2]}px" />
5512
+ <col />
4908
5513
  </colgroup>
4909
5514
  <thead class="sticky top-0 z-10">
4910
5515
  <tr class="bg-white">
@@ -4912,20 +5517,19 @@ ${argsString}</pre
4912
5517
  "Agent",
4913
5518
  "Time",
4914
5519
  "Event Type"
4915
- ].map((label, col) => lit.html`
4916
- <th
4917
- class="border-b border-gray-200 bg-white px-3 py-2 text-left font-medium text-gray-900"
4918
- style="position:relative;overflow:hidden;"
4919
- >
4920
- ${label}
4921
- <div
4922
- style="position:absolute;top:0;right:0;width:5px;height:100%;cursor:col-resize;user-select:none;background:transparent;"
4923
- @pointerdown=${(e) => this._onEvtColResizeStart(e, col)}
4924
- @pointermove=${(e) => this._onEvtColResizeMove(e)}
4925
- @pointerup=${() => this._onEvtColResizeEnd()}
4926
- @pointercancel=${() => this._onEvtColResizeEnd()}
4927
- ></div>
4928
- </th>`)}
5520
+ ].map((label, col) => lit.html` <th
5521
+ class="border-b border-gray-200 bg-white px-3 py-2 text-left font-medium text-gray-900"
5522
+ style="position:relative;overflow:hidden;"
5523
+ >
5524
+ ${label}
5525
+ <div
5526
+ style="position:absolute;top:0;right:0;width:5px;height:100%;cursor:col-resize;user-select:none;background:transparent;"
5527
+ @pointerdown=${(e) => this._onEvtColResizeStart(e, col)}
5528
+ @pointermove=${(e) => this._onEvtColResizeMove(e)}
5529
+ @pointerup=${() => this._onEvtColResizeEnd()}
5530
+ @pointercancel=${() => this._onEvtColResizeEnd()}
5531
+ ></div>
5532
+ </th>`)}
4929
5533
  <th
4930
5534
  class="border-b border-gray-200 bg-white px-3 py-2 text-left font-medium text-gray-900"
4931
5535
  >
@@ -5182,8 +5786,14 @@ ${prettyEvent}</pre
5182
5786
  ${messages && messages.length > 0 ? lit.html`
5183
5787
  <div class="w-full text-xs">
5184
5788
  <div class="flex bg-gray-50">
5185
- <div class="w-40 shrink-0 px-4 py-2 font-medium text-gray-700">Role</div>
5186
- <div class="flex-1 px-4 py-2 font-medium text-gray-700">Content</div>
5789
+ <div
5790
+ class="w-40 shrink-0 px-4 py-2 font-medium text-gray-700"
5791
+ >
5792
+ Role
5793
+ </div>
5794
+ <div class="flex-1 px-4 py-2 font-medium text-gray-700">
5795
+ Content
5796
+ </div>
5187
5797
  </div>
5188
5798
  <div class="divide-y divide-gray-200">
5189
5799
  ${messages.map((msg) => {
@@ -5820,7 +6430,9 @@ ${prettyEvent}</pre
5820
6430
  <span>Loading latest announcement…</span>
5821
6431
  </div>`;
5822
6432
  if (!this.announcementHtml) return lit.nothing;
5823
- return lit.html`<div class="mx-4 mt-3 mb-3 rounded-xl border border-slate-200 bg-white px-4 py-3">
6433
+ return lit.html`<div
6434
+ class="mx-4 mt-3 mb-3 rounded-xl border border-slate-200 bg-white px-4 py-3"
6435
+ >
5824
6436
  <div
5825
6437
  class="mb-2 flex items-center gap-2 text-xs font-semibold text-slate-900"
5826
6438
  >
@@ -5839,7 +6451,9 @@ ${prettyEvent}</pre
5839
6451
  ${this.renderIcon("X")}
5840
6452
  </button>
5841
6453
  </div>
5842
- <div class="announcement-body ${this.announcementExpanded ? "announcement-body--expanded" : "announcement-body--collapsed"}">
6454
+ <div
6455
+ class="announcement-body ${this.announcementExpanded ? "announcement-body--expanded" : "announcement-body--collapsed"}"
6456
+ >
5843
6457
  <div
5844
6458
  class="announcement-content"
5845
6459
  @click=${this.handleAnnouncementContentClick}
@@ -6027,6 +6641,8 @@ function defineWebInspector() {
6027
6641
  defineWebInspector();
6028
6642
 
6029
6643
  //#endregion
6644
+ exports.CpkThreadInspector = CpkThreadInspector;
6645
+ exports.THREAD_INSPECTOR_TAG = THREAD_INSPECTOR_TAG;
6030
6646
  exports.WEB_INSPECTOR_TAG = WEB_INSPECTOR_TAG;
6031
6647
  exports.WebInspectorElement = WebInspectorElement;
6032
6648
  exports.defineWebInspector = defineWebInspector;