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