@copilotkit/web-inspector 1.69.1 → 1.69.3

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.
Files changed (39) hide show
  1. package/dist/index.cjs +1221 -994
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +30 -46
  4. package/dist/index.d.cts.map +1 -1
  5. package/dist/index.d.mts +30 -46
  6. package/dist/index.d.mts.map +1 -1
  7. package/dist/index.mjs +1223 -994
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/index.umd.js +1304 -1644
  10. package/dist/index.umd.js.map +1 -1
  11. package/dist/lib/inspector-nav.cjs +0 -1
  12. package/dist/lib/inspector-nav.cjs.map +1 -1
  13. package/dist/lib/inspector-nav.mjs +0 -1
  14. package/dist/lib/inspector-nav.mjs.map +1 -1
  15. package/dist/lib/telemetry.cjs +1 -19
  16. package/dist/lib/telemetry.cjs.map +1 -1
  17. package/dist/lib/telemetry.d.cts.map +1 -1
  18. package/dist/lib/telemetry.d.mts.map +1 -1
  19. package/dist/lib/telemetry.mjs +2 -18
  20. package/dist/lib/telemetry.mjs.map +1 -1
  21. package/dist/package.cjs +1 -1
  22. package/dist/package.mjs +1 -1
  23. package/dist/styles/generated.cjs +1 -1
  24. package/dist/styles/generated.cjs.map +1 -1
  25. package/dist/styles/generated.mjs +1 -1
  26. package/dist/styles/generated.mjs.map +1 -1
  27. package/package.json +3 -3
  28. package/dist/lib/event-snippets.cjs +0 -559
  29. package/dist/lib/event-snippets.cjs.map +0 -1
  30. package/dist/lib/event-snippets.d.cts +0 -61
  31. package/dist/lib/event-snippets.d.cts.map +0 -1
  32. package/dist/lib/event-snippets.d.mts +0 -61
  33. package/dist/lib/event-snippets.d.mts.map +0 -1
  34. package/dist/lib/event-snippets.mjs +0 -537
  35. package/dist/lib/event-snippets.mjs.map +0 -1
  36. package/dist/lib/inspector-nav.d.cts +0 -11
  37. package/dist/lib/inspector-nav.d.cts.map +0 -1
  38. package/dist/lib/inspector-nav.d.mts +0 -11
  39. package/dist/lib/inspector-nav.d.mts.map +0 -1
package/dist/index.mjs CHANGED
@@ -8,14 +8,13 @@ import { projectInspectorMetadata } from "./lib/inspector-metadata.mjs";
8
8
  import { buildHomeModel, runtimeConnectionNeedsAttention } from "./lib/home-briefing.mjs";
9
9
  import { INSPECTOR_GROUPS, INSPECTOR_NAV_SECTIONS, getGroupForMenu, isInspectorMenuKey, shouldUseIconRail } from "./lib/inspector-nav.mjs";
10
10
  import { selectVisibleRealThreadId } from "./lib/thread-selection.mjs";
11
- import { ACTIVITY_STARTERS, compileActivityRecipe, compileChatSnippet, compileFromActivityMessage, compileReasoningRecipe, compileTextRecipe, compileToolCallRecipe, createSnippetId, deleteEventSnippet, editorStateFromSnippet, expandSnippetEventsForRun, exportEventSnippetsJson, groupEventSnippets, importEventSnippets, loadEventSnippets, parseSnippetEvents, recipeIconName, recipeIconWrapClass, recipeLabel, snippetContainsToolCall, snippetJsonIsRunnable, upsertEventSnippet } from "./lib/event-snippets.mjs";
12
- import { TELEMETRY_DOCS_URL, ensureTelemetryDistinctId, getRuntimeUrlType, getTelemetryDistinctIdForUrl, maybeShowDisclosure, trackErrorSignalViewed, trackEventSnippetsRun, trackEventSnippetsSaved, trackHomeCtaClicked, trackHomeViewed, trackInspectorOpened, trackMemoriesTabClicked, trackMetadataActionClicked, trackMetadataModuleViewed, trackTalkToEngineerClicked, trackThreadsEmptyEnabledViewed, trackThreadsEnabledViewed, trackThreadsExampleSelected, trackThreadsExampleTourCompleted, trackThreadsExampleTourDismissed, trackThreadsExampleTourReopened, trackThreadsExampleTourStarted, trackThreadsExampleTourStepViewed, trackThreadsExampleViewed, trackThreadsIntelligenceSignupClicked, trackThreadsLockedViewed, trackThreadsTabClicked, trackThreadsTalkToEngineerClicked, trackWhatsNewClicked, trackWhatsNewSignalViewed, trackWhatsNewViewed } from "./lib/telemetry.mjs";
11
+ import { TELEMETRY_DOCS_URL, ensureTelemetryDistinctId, getRuntimeUrlType, getTelemetryDistinctIdForUrl, maybeShowDisclosure, trackErrorSignalViewed, trackHomeCtaClicked, trackHomeViewed, trackInspectorOpened, trackMemoriesTabClicked, trackMetadataActionClicked, trackMetadataModuleViewed, trackTalkToEngineerClicked, trackThreadsEmptyEnabledViewed, trackThreadsEnabledViewed, trackThreadsExampleSelected, trackThreadsExampleTourCompleted, trackThreadsExampleTourDismissed, trackThreadsExampleTourReopened, trackThreadsExampleTourStarted, trackThreadsExampleTourStepViewed, trackThreadsExampleViewed, trackThreadsIntelligenceSignupClicked, trackThreadsLockedViewed, trackThreadsTabClicked, trackThreadsTalkToEngineerClicked, trackWhatsNewClicked, trackWhatsNewSignalViewed, trackWhatsNewViewed } from "./lib/telemetry.mjs";
13
12
  import { LitElement, css, html, nothing, render, unsafeCSS } from "lit";
14
13
  import { marked } from "marked";
15
14
  import { styleMap } from "lit/directives/style-map.js";
16
15
  import { unsafeHTML } from "lit/directives/unsafe-html.js";
17
16
  import { icons } from "lucide";
18
- import { CopilotKitCoreErrorCode, CopilotKitCoreRuntimeConnectionStatus, createInspectorThreadRequestId, emitInspectorStopViewing, emitInspectorViewThread, isInspectorThreadBridgeEnabled, onInspectorActiveThread, onInspectorViewThreadResult, ɵcreateThreadStore, ɵinjectInspectorEvents, ɵresetInspectorInject, ɵselectMemories, ɵselectMemoriesAvailable, ɵselectMemoriesError, ɵselectMemoriesIsLoading, ɵselectMemoriesRealtimeStatus, ɵselectThreads, ɵselectThreadsError, ɵselectThreadsIsLoading } from "@copilotkit/core";
17
+ import { CopilotKitCoreErrorCode, CopilotKitCoreRuntimeConnectionStatus, createInspectorThreadRequestId, emitInspectorStopViewing, emitInspectorViewThread, isInspectorThreadBridgeEnabled, onInspectorActiveThread, onInspectorViewThreadResult, ɵcreateThreadStore, ɵselectMemories, ɵselectMemoriesAvailable, ɵselectMemoriesError, ɵselectMemoriesIsLoading, ɵselectMemoriesRealtimeStatus, ɵselectThreads, ɵselectThreadsError, ɵselectThreadsIsLoading } from "@copilotkit/core";
19
18
 
20
19
  //#region src/index.ts
21
20
  const WEB_INSPECTOR_TAG = "cpk-web-inspector";
@@ -243,6 +242,21 @@ const LAUNCHER_BASE_LABEL = "Web Inspector";
243
242
  const EDGE_MARGIN = 16;
244
243
  /** HUD card plus the hover bridge. Used to pick left vs right. */
245
244
  const LAUNCHER_HUD_WIDTH = 248;
245
+ /**
246
+ * One page-load preview of the launcher's feature HUD.
247
+ *
248
+ * The card arrives after the host page has had a beat to settle. Its four rows
249
+ * then come online in order, stay readable, and leave together. Nothing is
250
+ * persisted: a new Inspector element means a new preview.
251
+ */
252
+ const LAUNCHER_HUD_INTRO_MS = {
253
+ delay: 500,
254
+ duration: 3400,
255
+ rowStart: 180,
256
+ rowStagger: 170,
257
+ rowDuration: 300,
258
+ blockedRetry: 250
259
+ };
246
260
  const DRAG_THRESHOLD = 6;
247
261
  const MIN_WINDOW_WIDTH = 880;
248
262
  const MIN_WINDOW_WIDTH_DOCKED_LEFT = 640;
@@ -348,6 +362,29 @@ const AGENT_EVENT_TYPES = [
348
362
  "ACTIVITY_SNAPSHOT",
349
363
  "ACTIVITY_DELTA"
350
364
  ];
365
+ const EMPTY_INSPECTOR_MESSAGES = [];
366
+ function textFromUnknownContent(content) {
367
+ if (typeof content === "string") return content;
368
+ if (Array.isArray(content)) {
369
+ const parts = [];
370
+ for (const part of content) {
371
+ if (typeof part === "string") {
372
+ parts.push(part);
373
+ continue;
374
+ }
375
+ if (typeof part === "object" && part !== null && "text" in part) {
376
+ const text = part.text;
377
+ if (typeof text === "string") parts.push(text);
378
+ }
379
+ }
380
+ return parts.join("");
381
+ }
382
+ if (typeof content === "object" && content !== null && "text" in content) {
383
+ const text = content.text;
384
+ if (typeof text === "string") return text;
385
+ }
386
+ return "";
387
+ }
351
388
  /**
352
389
  * Map core.tools (the registry INCLUDING disabled tools) into Capabilities-tab
353
390
  * frontend-tool rows. Pure: no DOM, no `this`. Reads current on/off state from
@@ -606,13 +643,6 @@ function highlightedJson(obj) {
606
643
  const cached = highlightedJsonCache.get(obj);
607
644
  if (cached !== void 0) return cached;
608
645
  }
609
- const colors = {
610
- key: "#5558B2",
611
- str: "#087653",
612
- num: "#8a5900",
613
- bool: "#c0333a",
614
- nil: "#68686e"
615
- };
616
646
  const json = JSON.stringify(obj, null, 2);
617
647
  if (!json) return "";
618
648
  const parts = [];
@@ -622,11 +652,11 @@ function highlightedJson(obj) {
622
652
  while ((match = re.exec(json)) !== null) {
623
653
  parts.push(escapeHtml(json.slice(lastIndex, match.index)));
624
654
  const m = match[0];
625
- let color = colors.num;
626
- if (m.startsWith("\"")) color = m.trimEnd().endsWith(":") ? colors.key : colors.str;
627
- else if (m === "true" || m === "false") color = colors.bool;
628
- else if (m === "null") color = colors.nil;
629
- parts.push(`<span style="color:${color}">${escapeHtml(m)}</span>`);
655
+ let token = "num";
656
+ if (m.startsWith("\"")) token = m.trimEnd().endsWith(":") ? "key" : "str";
657
+ else if (m === "true" || m === "false") token = "bool";
658
+ else if (m === "null") token = "nil";
659
+ parts.push(`<span class="cpk-json-token cpk-json-token--${token}">${escapeHtml(m)}</span>`);
630
660
  lastIndex = match.index + m.length;
631
661
  }
632
662
  parts.push(escapeHtml(json.slice(lastIndex)));
@@ -651,31 +681,23 @@ function renderHighlightedJsonBlock(value, options = {}) {
651
681
  ${unsafeHTML(highlightedJson(parsed))}</pre
652
682
  >`;
653
683
  }
654
- function eventColors(type) {
655
- if (type.startsWith("TEXT_MESSAGE")) return {
656
- bg: "#EEE6FE",
657
- fg: "#57575B"
658
- };
659
- if (type.startsWith("TOOL_CALL")) return {
660
- bg: "rgba(133,236,206,0.15)",
661
- fg: "#087653"
662
- };
663
- if (type.startsWith("STATE")) return {
664
- bg: "rgba(190,194,255,0.102)",
665
- fg: "#5558B2"
666
- };
667
- if (type === "RUN_ERROR" || type === "ERROR") return {
668
- bg: "rgba(250,95,103,0.13)",
669
- fg: "#c0333a"
670
- };
671
- if (type.startsWith("RUN_") || type.startsWith("STEP_")) return {
672
- bg: "rgba(255,172,77,0.2)",
673
- fg: "#8a5900"
674
- };
675
- return {
676
- bg: "#F7F7F9",
677
- fg: "#68686e"
678
- };
684
+ function humanizeEventType(type) {
685
+ const words = type.trim().split(/[_\s]+/).filter(Boolean).map((word) => word.toLowerCase());
686
+ if (words.length === 0) return "Event";
687
+ const [first = "event", ...rest] = words;
688
+ return [`${first.charAt(0).toUpperCase()}${first.slice(1)}`, ...rest].join(" ");
689
+ }
690
+ function messageTitle(role) {
691
+ const normalized = role.trim() || "message";
692
+ return `${`${normalized.charAt(0).toUpperCase()}${normalized.slice(1).toLowerCase()}`} message`;
693
+ }
694
+ function eventCategory(type) {
695
+ if (type === "RUN_ERROR" || type === "ERROR") return "error";
696
+ if (type.startsWith("TEXT_MESSAGE")) return "message";
697
+ if (type.startsWith("TOOL_CALL")) return "tool";
698
+ if (type.startsWith("STATE") || type.startsWith("MESSAGES")) return "state";
699
+ if (type.startsWith("RUN_") || type.startsWith("STEP_")) return "run";
700
+ return "event";
679
701
  }
680
702
  function formatTimestamp(ts) {
681
703
  const date = typeof ts === "number" ? new Date(ts) : new Date(ts);
@@ -1077,6 +1099,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1077
1099
  this.threadInspectionAvailable = false;
1078
1100
  this.agentStateInput = null;
1079
1101
  this.agentEventsInput = [];
1102
+ this.agentMessagesInput = EMPTY_INSPECTOR_MESSAGES;
1080
1103
  this.liveMessageVersion = 0;
1081
1104
  this.viewInAppMode = "hidden";
1082
1105
  this.viewInAppError = null;
@@ -1152,6 +1175,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1152
1175
  threadInspectionAvailable: { attribute: false },
1153
1176
  agentStateInput: { attribute: false },
1154
1177
  agentEventsInput: { attribute: false },
1178
+ agentMessagesInput: { attribute: false },
1155
1179
  liveMessageVersion: { attribute: false },
1156
1180
  viewInAppMode: { attribute: false },
1157
1181
  viewInAppError: { attribute: false },
@@ -1296,6 +1320,11 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1296
1320
  display: flex;
1297
1321
  flex-direction: row;
1298
1322
  overflow: hidden;
1323
+ --cpk-json-key: #3d408f;
1324
+ --cpk-json-str: #0b6b4c;
1325
+ --cpk-json-num: #8a5900;
1326
+ --cpk-json-bool: #c0333a;
1327
+ --cpk-json-nil: #57575b;
1299
1328
  }
1300
1329
 
1301
1330
  .cpk-td {
@@ -1420,11 +1449,25 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1420
1449
  flex-shrink: 0;
1421
1450
  }
1422
1451
 
1423
- .cpk-td__metadata-strip {
1452
+ .cpk-td__chrome-actions {
1453
+ margin-inline-start: auto;
1424
1454
  display: flex;
1455
+ flex-wrap: wrap;
1425
1456
  align-items: center;
1457
+ justify-content: flex-end;
1426
1458
  gap: 6px;
1427
- flex-wrap: wrap;
1459
+ padding-inline: 8px;
1460
+ min-width: 0;
1461
+ }
1462
+
1463
+ .cpk-td__chrome-actions + .cpk-td__panel-toggle {
1464
+ margin-inline-start: 0;
1465
+ }
1466
+
1467
+ .cpk-td__metadata-strip {
1468
+ display: flex;
1469
+ flex-direction: column;
1470
+ gap: 8px;
1428
1471
  padding: 10px 16px;
1429
1472
  border-bottom: 1px solid #e9e9ef;
1430
1473
  background: #fbfbfd;
@@ -1433,19 +1476,22 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1433
1476
 
1434
1477
  .cpk-td__metadata-pills {
1435
1478
  display: flex;
1479
+ align-items: center;
1436
1480
  gap: 6px;
1437
- flex: 1;
1438
- flex-wrap: wrap;
1481
+ width: 100%;
1439
1482
  min-width: 0;
1483
+ flex-wrap: nowrap;
1440
1484
  }
1441
1485
 
1442
1486
  .cpk-td__metadata-pill {
1443
1487
  display: inline-flex;
1444
1488
  align-items: center;
1445
- gap: 5px;
1446
- max-width: 220px;
1447
- padding: 3px 7px;
1448
- border: 1px solid #e9e9ef;
1489
+ gap: 6px;
1490
+ flex: 1 1 0;
1491
+ min-width: 0;
1492
+ height: 24px;
1493
+ padding: 0 8px;
1494
+ border: 1px solid #dbdbe5;
1449
1495
  border-radius: 6px;
1450
1496
  background: #ffffff;
1451
1497
  color: #57575b;
@@ -1461,20 +1507,17 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1461
1507
  }
1462
1508
 
1463
1509
  .cpk-td__metadata-value {
1510
+ min-width: 0;
1464
1511
  overflow: hidden;
1465
1512
  text-overflow: ellipsis;
1513
+ white-space: nowrap;
1466
1514
  }
1467
1515
 
1516
+ .cpk-td__metadata-value--wrap,
1468
1517
  .cpk-td__metadata-pill--wrap {
1469
- max-width: 100%;
1470
- white-space: normal;
1471
- }
1472
-
1473
- .cpk-td__metadata-value--wrap {
1474
- overflow: visible;
1475
- text-overflow: clip;
1476
- white-space: normal;
1477
- overflow-wrap: anywhere;
1518
+ overflow: hidden;
1519
+ text-overflow: ellipsis;
1520
+ white-space: nowrap;
1478
1521
  }
1479
1522
 
1480
1523
  .cpk-td__view-in-app {
@@ -1485,11 +1528,18 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1485
1528
  border-radius: 6px;
1486
1529
  background: #5558b2;
1487
1530
  color: #ffffff;
1488
- font-family: "Plus Jakarta Sans", sans-serif;
1489
- font-size: 11px;
1531
+ font-family: "Spline Sans Mono", monospace;
1532
+ font-size: 10px;
1490
1533
  font-weight: 600;
1491
- padding: 5px 10px;
1534
+ line-height: 1.2;
1535
+ min-height: 24px;
1536
+ padding: 3px 8px;
1492
1537
  cursor: pointer;
1538
+ transition:
1539
+ transform 160ms cubic-bezier(0.23, 1, 0.32, 1),
1540
+ background 120ms ease,
1541
+ color 120ms ease,
1542
+ border-color 120ms ease;
1493
1543
  }
1494
1544
 
1495
1545
  .cpk-td__view-in-app:focus-visible {
@@ -1497,6 +1547,10 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1497
1547
  outline-offset: 2px;
1498
1548
  }
1499
1549
 
1550
+ .cpk-td__view-in-app:active {
1551
+ transform: scale(0.96);
1552
+ }
1553
+
1500
1554
  .cpk-td__view-in-app--stop {
1501
1555
  background: #ffffff;
1502
1556
  color: #5558b2;
@@ -1508,6 +1562,16 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1508
1562
  font-size: 11px;
1509
1563
  }
1510
1564
 
1565
+ @media (prefers-reduced-motion: reduce) {
1566
+ .cpk-td__view-in-app {
1567
+ transition: none;
1568
+ }
1569
+
1570
+ .cpk-td__view-in-app:active {
1571
+ transform: none;
1572
+ }
1573
+ }
1574
+
1511
1575
  /*
1512
1576
  * Each tab's content is wrapped in this panel so the keep-mounted
1513
1577
  * inactive panels can be hidden via display:none without disturbing
@@ -1704,15 +1768,16 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1704
1768
  .cpk-td__tool-pre {
1705
1769
  margin: 0;
1706
1770
  font-family: "Spline Sans Mono", monospace;
1707
- font-size: 10px;
1771
+ font-size: 12px;
1708
1772
  background: #f7f7f9;
1709
- padding: 6px 8px;
1710
- border-radius: 5px;
1773
+ padding: 10px 12px;
1774
+ border-radius: 6px;
1711
1775
  overflow-x: auto;
1712
1776
  white-space: pre-wrap;
1713
- word-break: break-all;
1777
+ overflow-wrap: anywhere;
1778
+ word-break: normal;
1714
1779
  color: #010507;
1715
- line-height: 1.6;
1780
+ line-height: 1.65;
1716
1781
  }
1717
1782
 
1718
1783
  /* ── Tool call group ─────────────────────────────────────────────── */
@@ -1765,12 +1830,31 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1765
1830
 
1766
1831
  /* ── Interaction timeline ───────────────────────────────────────── */
1767
1832
  .cpk-td__timeline-item {
1768
- border: 1px solid #e9e9ef;
1769
- border-radius: 7px;
1770
- background: #ffffff;
1833
+ border: 1px solid transparent;
1834
+ border-radius: 10px;
1835
+ background: transparent;
1771
1836
  overflow: hidden;
1772
1837
  }
1773
1838
 
1839
+ .cpk-td__timeline-item--run,
1840
+ .cpk-td__timeline-item--state,
1841
+ .cpk-td__timeline-item--event,
1842
+ .cpk-td__timeline-item--tool,
1843
+ .cpk-td__event--run,
1844
+ .cpk-td__event--event,
1845
+ .cpk-td__event--state,
1846
+ .cpk-td__event--message,
1847
+ .cpk-td__event--tool {
1848
+ border-color: #dbdbe5;
1849
+ background: #ffffff;
1850
+ }
1851
+
1852
+ .cpk-td__timeline-item--message {
1853
+ border-color: #dbdbe5;
1854
+ background: #ffffff;
1855
+ box-shadow: 0 1px 2px #0105070d;
1856
+ }
1857
+
1774
1858
  .cpk-td__timeline-item--warning {
1775
1859
  border-color: rgba(250, 95, 103, 0.35);
1776
1860
  background: rgba(250, 95, 103, 0.04);
@@ -1780,29 +1864,72 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1780
1864
  display: flex;
1781
1865
  align-items: center;
1782
1866
  gap: 8px;
1783
- padding: 7px 10px;
1867
+ padding: 6px 10px;
1868
+ background: transparent;
1869
+ }
1870
+
1871
+ .cpk-td__timeline-item--message .cpk-td__timeline-header {
1872
+ padding: 10px 12px;
1784
1873
  background: #f7f7f9;
1785
1874
  }
1786
1875
 
1876
+ .cpk-td__timeline-item--user .cpk-td__timeline-header {
1877
+ background: #bec2ff1a;
1878
+ }
1879
+
1880
+ .cpk-td__timeline-item--assistant .cpk-td__timeline-header {
1881
+ background: #85ecce1a;
1882
+ }
1883
+
1787
1884
  .cpk-td__timeline-kind {
1885
+ display: inline-flex;
1886
+ align-items: center;
1887
+ padding: 4px 8px;
1888
+ border-radius: 999px;
1889
+ background: #f0f0f4;
1890
+ color: #57575b;
1788
1891
  font-family: "Spline Sans Mono", monospace;
1789
- font-size: 9px;
1892
+ font-size: 10px;
1790
1893
  font-weight: 600;
1894
+ letter-spacing: 0.04em;
1895
+ line-height: 1.2;
1791
1896
  text-transform: uppercase;
1792
- color: #5558b2;
1897
+ flex-shrink: 0;
1898
+ }
1899
+
1900
+ .cpk-td__timeline-item--message .cpk-td__timeline-kind {
1901
+ background: #bec2ff33;
1902
+ color: #010507;
1903
+ }
1904
+
1905
+ .cpk-td__timeline-item--assistant .cpk-td__timeline-kind {
1906
+ background: #85ecce4d;
1907
+ color: #010507;
1908
+ }
1909
+
1910
+ .cpk-td__timeline-item--warning .cpk-td__timeline-kind {
1911
+ background: rgba(250, 95, 103, 0.16);
1912
+ color: #c0333a;
1793
1913
  }
1794
1914
 
1795
1915
  .cpk-td__timeline-title {
1796
1916
  flex: 1;
1797
1917
  min-width: 0;
1918
+ font-family: "Plus Jakarta Sans", sans-serif;
1798
1919
  font-size: 12px;
1799
1920
  font-weight: 500;
1800
- color: #010507;
1921
+ color: #57575b;
1801
1922
  overflow: hidden;
1802
1923
  text-overflow: ellipsis;
1803
1924
  white-space: nowrap;
1804
1925
  }
1805
1926
 
1927
+ .cpk-td__timeline-item--message .cpk-td__timeline-title {
1928
+ font-size: 13px;
1929
+ font-weight: 600;
1930
+ color: #010507;
1931
+ }
1932
+
1806
1933
  .cpk-td__timeline-time {
1807
1934
  font-family: "Spline Sans Mono", monospace;
1808
1935
  font-size: 9px;
@@ -1813,6 +1940,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1813
1940
  .cpk-td__timeline-body {
1814
1941
  margin: 0;
1815
1942
  padding: 0 10px 9px;
1943
+ font-family: "Plus Jakarta Sans", sans-serif;
1816
1944
  font-size: 12px;
1817
1945
  line-height: 1.55;
1818
1946
  color: #57575b;
@@ -1820,21 +1948,26 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1820
1948
  word-break: break-word;
1821
1949
  }
1822
1950
 
1951
+ .cpk-td__timeline-item--message .cpk-td__timeline-body {
1952
+ padding: 0 12px 12px;
1953
+ font-size: 13px;
1954
+ color: #010507;
1955
+ }
1956
+
1823
1957
  .cpk-td__timeline-toolbar {
1824
1958
  display: flex;
1825
1959
  gap: 6px;
1826
- margin-left: auto;
1827
1960
  }
1828
1961
 
1829
1962
  .cpk-td__timeline-bulk-toggle {
1830
1963
  margin: 0;
1831
- padding: 4px 8px;
1832
- border: 1px solid #dcdce8;
1833
- border-radius: 7px;
1964
+ padding: 6px 10px;
1965
+ border: 1px solid #dbdbe5;
1966
+ border-radius: 8px;
1834
1967
  background: #ffffff;
1835
1968
  color: #36363a;
1836
1969
  cursor: pointer;
1837
- font-family: "Inter", sans-serif;
1970
+ font-family: "Spline Sans Mono", monospace;
1838
1971
  font-size: 11px;
1839
1972
  font-weight: 600;
1840
1973
  line-height: 1.2;
@@ -1909,84 +2042,6 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1909
2042
  }
1910
2043
  }
1911
2044
 
1912
- @keyframes cpk-playground-message-enter {
1913
- from {
1914
- opacity: 0;
1915
- filter: blur(2px);
1916
- transform: translateY(4px);
1917
- }
1918
- to {
1919
- opacity: 1;
1920
- filter: blur(0);
1921
- transform: translateY(0);
1922
- }
1923
- }
1924
-
1925
- @keyframes cpk-playground-thinking {
1926
- 0%,
1927
- 60%,
1928
- 100% {
1929
- opacity: 0.28;
1930
- transform: translateY(0);
1931
- }
1932
- 30% {
1933
- opacity: 1;
1934
- transform: translateY(-2px);
1935
- }
1936
- }
1937
-
1938
- .cpk-playground-root {
1939
- container-type: inline-size;
1940
- }
1941
-
1942
- .cpk-playground-message-enter {
1943
- animation: cpk-playground-message-enter 0.24s cubic-bezier(0.16, 1, 0.3, 1)
1944
- both;
1945
- }
1946
-
1947
- .cpk-playground-thinking-dot {
1948
- animation: cpk-playground-thinking 1.2s ease-in-out infinite;
1949
- }
1950
-
1951
- .cpk-playground-thinking-dot:nth-child(2) {
1952
- animation-delay: 0.12s;
1953
- }
1954
-
1955
- .cpk-playground-thinking-dot:nth-child(3) {
1956
- animation-delay: 0.24s;
1957
- }
1958
-
1959
- .cpk-playground-reasoning summary::-webkit-details-marker {
1960
- display: none;
1961
- }
1962
-
1963
- .cpk-playground-reasoning[open] .cpk-playground-reasoning-chevron {
1964
- transform: rotate(90deg);
1965
- }
1966
-
1967
- @container (max-width: 560px) {
1968
- .cpk-playground-header {
1969
- align-items: stretch;
1970
- }
1971
-
1972
- .cpk-playground-actions {
1973
- width: 100%;
1974
- }
1975
-
1976
- .cpk-playground-thread-select {
1977
- min-width: 0;
1978
- max-width: none;
1979
- flex: 1;
1980
- }
1981
- }
1982
-
1983
- @media (prefers-reduced-motion: reduce) {
1984
- .cpk-playground-message-enter,
1985
- .cpk-playground-thinking-dot {
1986
- animation: none;
1987
- }
1988
- }
1989
-
1990
2045
  .cpk-td__genui {
1991
2046
  display: flex;
1992
2047
  flex-direction: column;
@@ -2028,8 +2083,9 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2028
2083
  /* ── AG-UI Events ────────────────────────────────────────────────── */
2029
2084
  .cpk-td__event {
2030
2085
  flex-shrink: 0;
2031
- border: 1px solid #e9e9ef;
2032
- border-radius: 7px;
2086
+ border: 1px solid #dbdbe5;
2087
+ border-radius: 10px;
2088
+ background: #ffffff;
2033
2089
  overflow: hidden;
2034
2090
  /*
2035
2091
  * content-visibility: auto lets the browser skip layout + paint for
@@ -2045,48 +2101,89 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2045
2101
  contain-intrinsic-size: 0 80px;
2046
2102
  }
2047
2103
 
2104
+ .cpk-td__event--error {
2105
+ border-color: rgba(250, 95, 103, 0.35);
2106
+ background: rgba(250, 95, 103, 0.04);
2107
+ }
2108
+
2048
2109
  .cpk-td__event-header {
2049
2110
  display: flex;
2050
- justify-content: space-between;
2051
2111
  align-items: center;
2052
- padding: 5px 10px;
2112
+ gap: 8px;
2113
+ padding: 6px 10px;
2114
+ background: transparent;
2053
2115
  }
2054
2116
 
2055
2117
  .cpk-td__event-type {
2118
+ display: inline-flex;
2119
+ align-items: center;
2120
+ padding: 4px 8px;
2121
+ border-radius: 999px;
2122
+ background: #f0f0f4;
2123
+ color: #010507;
2056
2124
  font-family: "Spline Sans Mono", monospace;
2057
- font-size: 9px;
2058
- font-weight: 500;
2059
- text-transform: uppercase;
2125
+ font-size: 10px;
2126
+ font-weight: 600;
2127
+ letter-spacing: 0.02em;
2128
+ line-height: 1.2;
2129
+ }
2130
+
2131
+ .cpk-td__event--message .cpk-td__event-type {
2132
+ background: #bec2ff33;
2133
+ }
2134
+
2135
+ .cpk-td__event--tool .cpk-td__event-type {
2136
+ background: #85ecce4d;
2137
+ }
2138
+
2139
+ .cpk-td__event--error .cpk-td__event-type {
2140
+ background: rgba(250, 95, 103, 0.16);
2141
+ color: #c0333a;
2060
2142
  }
2061
2143
 
2062
2144
  .cpk-td__event-time {
2145
+ margin-inline-start: auto;
2063
2146
  font-family: "Spline Sans Mono", monospace;
2064
2147
  font-size: 9px;
2065
2148
  color: #68686e;
2149
+ flex-shrink: 0;
2066
2150
  }
2067
2151
 
2068
- .cpk-td__event-payload {
2069
- margin: 0;
2070
- font-family: "Spline Sans Mono", monospace;
2071
- font-size: 10px;
2072
- line-height: 1.6;
2073
- white-space: pre-wrap;
2074
- word-break: break-all;
2075
- color: #57575b;
2076
- padding: 8px 10px;
2077
- border-top: 1px solid #e9e9ef;
2078
- }
2079
-
2080
- /* ── JSON block (agent state) ────────────────────────────────────── */
2152
+ .cpk-td__event-payload,
2081
2153
  .cpk-td__json-block,
2082
2154
  .cpk-json-block {
2083
2155
  margin: 0;
2156
+ padding: 10px 12px;
2157
+ border-top: 1px solid #dbdbe5;
2158
+ background: #f7f7f9;
2084
2159
  font-family: "Spline Sans Mono", monospace;
2085
- font-size: 11px;
2086
- line-height: 1.8;
2160
+ font-size: 12px;
2161
+ line-height: 1.65;
2087
2162
  white-space: pre-wrap;
2088
- word-break: break-all;
2089
- color: #57575b;
2163
+ overflow-wrap: anywhere;
2164
+ word-break: normal;
2165
+ color: #010507;
2166
+ overflow: auto;
2167
+ }
2168
+
2169
+ .cpk-json-token--key {
2170
+ color: var(--cpk-json-key);
2171
+ }
2172
+
2173
+ .cpk-json-token--str {
2174
+ color: var(--cpk-json-str);
2175
+ }
2176
+
2177
+ .cpk-json-token--num {
2178
+ color: var(--cpk-json-num);
2179
+ }
2180
+
2181
+ .cpk-json-token--bool {
2182
+ color: var(--cpk-json-bool);
2183
+ }
2184
+
2185
+ .cpk-json-token--nil {
2186
+ color: var(--cpk-json-nil);
2090
2187
  }
2091
2188
 
2092
2189
  /* ── Resize divider ──────────────────────────────────────────────── */
@@ -2185,6 +2282,11 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2185
2282
 
2186
2283
  :host([data-color-scheme="dark"]) {
2187
2284
  color-scheme: dark;
2285
+ --cpk-json-key: #bec2ff;
2286
+ --cpk-json-str: #85ecce;
2287
+ --cpk-json-num: #ffac4d;
2288
+ --cpk-json-bool: #fa5f67;
2289
+ --cpk-json-nil: #afafb7;
2188
2290
  }
2189
2291
 
2190
2292
  :host([data-color-scheme="dark"]) .cpk-td {
@@ -2225,11 +2327,15 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2225
2327
  }
2226
2328
 
2227
2329
  :host([data-color-scheme="dark"]) .cpk-td__timeline-header,
2228
- :host([data-color-scheme="dark"]) .cpk-td__tool-body,
2229
- :host([data-color-scheme="dark"]) .cpk-td__tool-pre {
2330
+ :host([data-color-scheme="dark"]) .cpk-td__tool-body {
2230
2331
  background: #171a22;
2231
2332
  }
2232
2333
 
2334
+ :host([data-color-scheme="dark"]) .cpk-td__tool-pre {
2335
+ background: #111319;
2336
+ color: #f3f4f8;
2337
+ }
2338
+
2233
2339
  :host([data-color-scheme="dark"]) .cpk-td__panel-toggle:hover,
2234
2340
  :host([data-color-scheme="dark"]) .cpk-td__tool-header:hover,
2235
2341
  :host([data-color-scheme="dark"]) .cpk-td__timeline-bulk-toggle:hover,
@@ -2239,12 +2345,115 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2239
2345
 
2240
2346
  :host([data-color-scheme="dark"]) .cpk-td__panel-toggle--active,
2241
2347
  :host([data-color-scheme="dark"]) .cpk-td__inline-chip,
2242
- :host([data-color-scheme="dark"]) .cpk-td__timeline-kind,
2243
2348
  :host([data-color-scheme="dark"]) .cpk-td__genui-badge {
2244
2349
  background: #302b43;
2245
2350
  color: #d8d9ff;
2246
2351
  }
2247
2352
 
2353
+ :host([data-color-scheme="dark"]) .cpk-td__timeline-item--message {
2354
+ background: #191c24;
2355
+ border-color: #343742;
2356
+ box-shadow: none;
2357
+ }
2358
+
2359
+ :host([data-color-scheme="dark"])
2360
+ .cpk-td__timeline-item--user
2361
+ .cpk-td__timeline-header {
2362
+ background: #bec2ff1a;
2363
+ }
2364
+
2365
+ :host([data-color-scheme="dark"])
2366
+ .cpk-td__timeline-item--assistant
2367
+ .cpk-td__timeline-header {
2368
+ background: #85ecce1a;
2369
+ }
2370
+
2371
+ :host([data-color-scheme="dark"])
2372
+ .cpk-td__timeline-item--message
2373
+ .cpk-td__timeline-kind {
2374
+ background: #302b43;
2375
+ color: #d8d9ff;
2376
+ }
2377
+
2378
+ :host([data-color-scheme="dark"])
2379
+ .cpk-td__timeline-item--assistant
2380
+ .cpk-td__timeline-kind {
2381
+ background: #1a3a32;
2382
+ color: #85ecce;
2383
+ }
2384
+
2385
+ :host([data-color-scheme="dark"]) .cpk-td__timeline-item--run,
2386
+ :host([data-color-scheme="dark"]) .cpk-td__timeline-item--event,
2387
+ :host([data-color-scheme="dark"]) .cpk-td__timeline-item--state,
2388
+ :host([data-color-scheme="dark"]) .cpk-td__timeline-item--tool,
2389
+ :host([data-color-scheme="dark"]) .cpk-td__event--run,
2390
+ :host([data-color-scheme="dark"]) .cpk-td__event--event,
2391
+ :host([data-color-scheme="dark"]) .cpk-td__event--state,
2392
+ :host([data-color-scheme="dark"]) .cpk-td__event--message,
2393
+ :host([data-color-scheme="dark"]) .cpk-td__event--tool {
2394
+ background: #191c24;
2395
+ border-color: #343742;
2396
+ }
2397
+
2398
+ :host([data-color-scheme="dark"])
2399
+ .cpk-td__timeline-item--run
2400
+ .cpk-td__timeline-header,
2401
+ :host([data-color-scheme="dark"])
2402
+ .cpk-td__timeline-item--event
2403
+ .cpk-td__timeline-header,
2404
+ :host([data-color-scheme="dark"])
2405
+ .cpk-td__timeline-item--state
2406
+ .cpk-td__timeline-header {
2407
+ background: transparent;
2408
+ }
2409
+
2410
+ :host([data-color-scheme="dark"]) .cpk-td__timeline-kind {
2411
+ background: #20232d;
2412
+ color: #aeb1bd;
2413
+ }
2414
+
2415
+ :host([data-color-scheme="dark"])
2416
+ .cpk-td__timeline-item--run
2417
+ .cpk-td__timeline-title,
2418
+ :host([data-color-scheme="dark"])
2419
+ .cpk-td__timeline-item--event
2420
+ .cpk-td__timeline-title,
2421
+ :host([data-color-scheme="dark"])
2422
+ .cpk-td__timeline-item--state
2423
+ .cpk-td__timeline-title {
2424
+ color: #aeb1bd;
2425
+ }
2426
+
2427
+ :host([data-color-scheme="dark"]) .cpk-td__event-header {
2428
+ background: transparent;
2429
+ }
2430
+
2431
+ :host([data-color-scheme="dark"]) .cpk-td__event-type {
2432
+ background: #20232d;
2433
+ color: #f3f4f8;
2434
+ }
2435
+
2436
+ :host([data-color-scheme="dark"]) .cpk-td__event--message .cpk-td__event-type {
2437
+ background: #302b43;
2438
+ color: #d8d9ff;
2439
+ }
2440
+
2441
+ :host([data-color-scheme="dark"]) .cpk-td__event--tool .cpk-td__event-type {
2442
+ background: #1a3a32;
2443
+ color: #85ecce;
2444
+ }
2445
+
2446
+ :host([data-color-scheme="dark"]) .cpk-td__event--error .cpk-td__event-type {
2447
+ background: rgba(250, 95, 103, 0.2);
2448
+ color: #fa5f67;
2449
+ }
2450
+
2451
+ :host([data-color-scheme="dark"])
2452
+ .cpk-td__timeline-item--message
2453
+ .cpk-td__timeline-body {
2454
+ color: #f3f4f8;
2455
+ }
2456
+
2248
2457
  :host([data-color-scheme="dark"]) .cpk-td__tab,
2249
2458
  :host([data-color-scheme="dark"]) .cpk-td__panel-toggle,
2250
2459
  :host([data-color-scheme="dark"]) .cpk-td__metadata-label,
@@ -2271,7 +2480,9 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2271
2480
  :host([data-color-scheme="dark"]) .cpk-td__event-payload,
2272
2481
  :host([data-color-scheme="dark"]) .cpk-td__json-block,
2273
2482
  :host([data-color-scheme="dark"]) .cpk-json-block {
2274
- color: #c7c9d2;
2483
+ background: #111319;
2484
+ border-top-color: #343742;
2485
+ color: #f3f4f8;
2275
2486
  }
2276
2487
 
2277
2488
  :host([data-color-scheme="dark"]) .cpk-tdp__divider {
@@ -2291,7 +2502,8 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2291
2502
  if (this.canFetchEvents()) {
2292
2503
  this._eventsFetched = true;
2293
2504
  this.fetchEvents(this.threadId);
2294
- } else this.fetchMessages(this.threadId);
2505
+ }
2506
+ if (this.canFetchMessages()) this.fetchMessages(this.threadId);
2295
2507
  } else {
2296
2508
  this._fetchedMetadata = null;
2297
2509
  this._conversation = [];
@@ -2302,7 +2514,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2302
2514
  this._messagesAbort = null;
2303
2515
  this.fetchMessages(this.threadId, true);
2304
2516
  }
2305
- const focusedContentChanged = _changed.has("_fetchedEvents") || _changed.has("agentEventsInput") || _changed.has("_conversation");
2517
+ const focusedContentChanged = _changed.has("_fetchedEvents") || _changed.has("agentEventsInput") || _changed.has("agentMessagesInput") || _changed.has("_conversation");
2306
2518
  if (this.focusMessageId && (this.focusRequestId > this._scrolledFocusRequestId || focusedContentChanged)) {
2307
2519
  if (this._tab !== "timeline") {
2308
2520
  this._activatedTabs = new Set([...this._activatedTabs, "timeline"]);
@@ -2459,18 +2671,14 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2459
2671
  if (result.status === "not-available") {
2460
2672
  this._eventsNotAvailable = true;
2461
2673
  this._fetchedEvents = [];
2462
- if (this.canFetchMessages()) this.fetchMessages(threadId);
2463
2674
  return;
2464
2675
  }
2465
- const mappedEvents = this.mapApiEvents(result.events);
2466
- this._fetchedEvents = mappedEvents;
2467
- if (mappedEvents.length === 0 && this.canFetchMessages()) this.fetchMessages(threadId);
2676
+ this._fetchedEvents = this.mapApiEvents(result.events);
2468
2677
  } catch (err) {
2469
2678
  if (err instanceof Error && err.name === "AbortError") return;
2470
2679
  if (this.threadId !== threadId) return;
2471
2680
  this._eventsError = err instanceof Error ? err.message : "Failed to load events";
2472
2681
  this._fetchedEvents = [];
2473
- if (this.canFetchMessages()) this.fetchMessages(threadId);
2474
2682
  } finally {
2475
2683
  if (!controller.signal.aborted && this.threadId === threadId) this._loadingEvents = false;
2476
2684
  }
@@ -2544,13 +2752,15 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2544
2752
  mapMessages(messages) {
2545
2753
  const items = [];
2546
2754
  const toolCallMap = /* @__PURE__ */ new Map();
2547
- for (const msg of messages) if (msg.role === "user" && msg.content) items.push({
2548
- id: msg.id,
2549
- type: "user",
2550
- content: msg.content,
2551
- createdAt: ""
2552
- });
2553
- else if (msg.role === "assistant") {
2755
+ for (const msg of messages) if (msg.role === "user") {
2756
+ const content = textFromUnknownContent(msg.content);
2757
+ if (content) items.push({
2758
+ id: msg.id,
2759
+ type: "user",
2760
+ content,
2761
+ createdAt: ""
2762
+ });
2763
+ } else if (msg.role === "assistant") {
2554
2764
  if (msg.toolCalls?.length) for (const tc of msg.toolCalls) {
2555
2765
  let args = {};
2556
2766
  if (typeof tc.args === "string") try {
@@ -2579,10 +2789,11 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2579
2789
  toolCallMap.set(tc.id, item);
2580
2790
  items.push(item);
2581
2791
  }
2582
- if (msg.content) items.push({
2792
+ const assistantContent = textFromUnknownContent(msg.content);
2793
+ if (assistantContent) items.push({
2583
2794
  id: msg.id,
2584
2795
  type: "assistant",
2585
- content: msg.content,
2796
+ content: assistantContent,
2586
2797
  createdAt: ""
2587
2798
  });
2588
2799
  } else if (msg.role === "activity") items.push({
@@ -2630,14 +2841,86 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2630
2841
  return this.timelineItemsForEvents(this.activeEvents);
2631
2842
  }
2632
2843
  timelineItemsForEvents(events) {
2633
- if (this._timelineItemsCache?.events === events) return this._timelineItemsCache.items;
2634
- const items = this.timelineItemsFromEvents(events);
2844
+ const conversation = this._conversation;
2845
+ const agentMessages = this.agentMessagesInput;
2846
+ if (this._timelineItemsCache?.events === events && this._timelineItemsCache.conversation === conversation && this._timelineItemsCache.agentMessages === agentMessages) return this._timelineItemsCache.items;
2847
+ const items = this.mergeUserMessagesIntoTimeline(this.timelineItemsFromEvents(events));
2635
2848
  this._timelineItemsCache = {
2636
2849
  events,
2850
+ conversation,
2851
+ agentMessages,
2637
2852
  items
2638
2853
  };
2639
2854
  return items;
2640
2855
  }
2856
+ conversationUsers() {
2857
+ const users = [];
2858
+ const seenIds = /* @__PURE__ */ new Set();
2859
+ const seenBodies = /* @__PURE__ */ new Set();
2860
+ const push = (user) => {
2861
+ const body = user.content.trim();
2862
+ if (!body) return;
2863
+ if (seenIds.has(user.id) || seenBodies.has(body)) return;
2864
+ seenIds.add(user.id);
2865
+ seenBodies.add(body);
2866
+ users.push(user);
2867
+ };
2868
+ for (const item of this._conversation) if (item.type === "user") push(item);
2869
+ this.agentMessagesInput.forEach((message, index) => {
2870
+ if (message.role !== "user") return;
2871
+ push({
2872
+ id: message.id ?? `live-user-${index}`,
2873
+ type: "user",
2874
+ content: message.contentText,
2875
+ createdAt: ""
2876
+ });
2877
+ });
2878
+ return users;
2879
+ }
2880
+ mergeUserMessagesIntoTimeline(items) {
2881
+ if (items.length === 0) return items;
2882
+ const users = this.conversationUsers();
2883
+ if (users.length === 0) return items;
2884
+ const shownIds = /* @__PURE__ */ new Set();
2885
+ const shownBodies = /* @__PURE__ */ new Set();
2886
+ for (const item of items) {
2887
+ if (item.kind !== "message") continue;
2888
+ if (!item.title.toLowerCase().startsWith("user")) continue;
2889
+ if (item.messageId) shownIds.add(item.messageId);
2890
+ const body = item.body?.trim();
2891
+ if (body) shownBodies.add(body);
2892
+ }
2893
+ const missing = users.filter((user) => {
2894
+ if (shownIds.has(user.id)) return false;
2895
+ if (shownBodies.has(user.content.trim())) return false;
2896
+ return true;
2897
+ });
2898
+ if (missing.length === 0) return items;
2899
+ const insertAt = [];
2900
+ for (let index = 0; index < items.length; index++) {
2901
+ const item = items[index];
2902
+ if (item.kind === "run" && item.title === "Run started") insertAt.push(index);
2903
+ }
2904
+ if (insertAt.length === 0) for (let index = 0; index < items.length; index++) {
2905
+ const item = items[index];
2906
+ if (item.kind === "message" && item.title.toLowerCase().includes("assistant")) insertAt.push(index);
2907
+ }
2908
+ const merged = [...items];
2909
+ for (let index = missing.length - 1; index >= 0; index--) {
2910
+ const user = missing[index];
2911
+ const row = {
2912
+ id: `conversation-user-${user.id}`,
2913
+ messageId: user.id,
2914
+ kind: "message",
2915
+ title: "User message",
2916
+ body: user.content,
2917
+ timestamp: user.createdAt || 0,
2918
+ sourceIndex: 0
2919
+ };
2920
+ merged.splice(insertAt[index] ?? 0, 0, row);
2921
+ }
2922
+ return merged;
2923
+ }
2641
2924
  timelineItemsFromEvents(events) {
2642
2925
  if (events.length === 0) return [];
2643
2926
  const items = [];
@@ -2676,7 +2959,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2676
2959
  id: `message-${key}`,
2677
2960
  messageId: key,
2678
2961
  kind: "message",
2679
- title: `${role || "message"} message`,
2962
+ title: messageTitle(role || "message"),
2680
2963
  body: "",
2681
2964
  timestamp: event.timestamp,
2682
2965
  sourceIndex
@@ -2824,7 +3107,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2824
3107
  items.push({
2825
3108
  id: `${type}-${sourceIndex}`,
2826
3109
  kind: "state",
2827
- title: type === "STATE_SNAPSHOT" ? "State snapshot captured" : "State delta captured",
3110
+ title: type === "STATE_SNAPSHOT" ? "State snapshot" : "State delta",
2828
3111
  timestamp: event.timestamp,
2829
3112
  sourceIndex,
2830
3113
  details: payload
@@ -2834,7 +3117,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2834
3117
  items.push({
2835
3118
  id: `event-${sourceIndex}`,
2836
3119
  kind: "event",
2837
- title: type,
3120
+ title: humanizeEventType(type),
2838
3121
  timestamp: event.timestamp,
2839
3122
  sourceIndex,
2840
3123
  details: payload
@@ -2973,6 +3256,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2973
3256
  });
2974
3257
  }
2975
3258
  render() {
3259
+ const viewInApp = this.renderViewInAppAction();
2976
3260
  return html`
2977
3261
  <div class="cpk-td">
2978
3262
  <!-- ── Left area: tabs + content ─────────────────────────────────── -->
@@ -3000,6 +3284,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3000
3284
  </button>
3001
3285
  `)}
3002
3286
  </div>
3287
+ ${viewInApp !== nothing ? html`<div class="cpk-td__chrome-actions">${viewInApp}</div>` : nothing}
3003
3288
  ${this.renderPanelToggle()}
3004
3289
  </div>
3005
3290
  ${this.renderMetadataStrip()}
@@ -3054,8 +3339,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3054
3339
  value: metadata?.name ?? this.thread?.name ?? "Untitled"
3055
3340
  }, {
3056
3341
  label: "ID",
3057
- value: metadata?.id ?? this.threadId ?? "—",
3058
- wrap: true
3342
+ value: metadata?.id ?? this.threadId ?? "—"
3059
3343
  }];
3060
3344
  for (const fact of [
3061
3345
  {
@@ -3077,7 +3361,6 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3077
3361
  value: fact.label === "Created" || fact.label === "Updated" ? this.fmtTime(fact.value) : fact.value
3078
3362
  });
3079
3363
  }
3080
- const bulkControls = this.renderActiveBulkControls();
3081
3364
  return html`
3082
3365
  <div
3083
3366
  class="cpk-td__metadata-strip"
@@ -3100,8 +3383,6 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3100
3383
  </span>
3101
3384
  `)}
3102
3385
  </div>
3103
- ${this.renderViewInAppAction()}
3104
- ${bulkControls}
3105
3386
  </div>
3106
3387
  `;
3107
3388
  }
@@ -3128,10 +3409,8 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3128
3409
  >` : nothing}
3129
3410
  `;
3130
3411
  }
3131
- renderActiveBulkControls() {
3412
+ renderTimelineBulkControls() {
3132
3413
  if (this._eventsNotAvailable) return nothing;
3133
- if (this._tab === "raw-events") return this.renderRawEventBulkControls();
3134
- if (this._tab !== "timeline") return nothing;
3135
3414
  const detailIds = this.timelineItemsForEvents(this.activeEvents).filter((item) => item.details).map((item) => item.id);
3136
3415
  if (detailIds.length <= 1) return nothing;
3137
3416
  return html`<div class="cpk-td__timeline-toolbar">
@@ -3204,7 +3483,12 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3204
3483
  `;
3205
3484
  }
3206
3485
  const events = this.activeEvents;
3207
- const cachedTimeline = this.getCachedPanelTpl("timeline", [events, this._expandedTimelineDetails]);
3486
+ const cachedTimeline = this.getCachedPanelTpl("timeline", [
3487
+ events,
3488
+ this._conversation,
3489
+ this.agentMessagesInput,
3490
+ this._expandedTimelineDetails
3491
+ ]);
3208
3492
  if (cachedTimeline) return cachedTimeline;
3209
3493
  const timelineItems = this.timelineItemsForEvents(events);
3210
3494
  if (timelineItems.length === 0) {
@@ -3220,14 +3504,28 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3220
3504
  </div>
3221
3505
  `;
3222
3506
  }
3223
- return this.cachedPanelTpl("timeline", [events, this._expandedTimelineDetails], () => html`${timelineItems.map((item) => this.renderTimelineItem(item))}`);
3507
+ return this.cachedPanelTpl("timeline", [
3508
+ events,
3509
+ this._conversation,
3510
+ this.agentMessagesInput,
3511
+ this._expandedTimelineDetails
3512
+ ], () => html`${this.renderTimelineBulkControls()}${timelineItems.map((item) => this.renderTimelineItem(item))}`);
3513
+ }
3514
+ timelineItemClass(item) {
3515
+ const classes = ["cpk-td__timeline-item", `cpk-td__timeline-item--${item.kind}`];
3516
+ if (item.kind === "warning" || item.severity === "error") classes.push("cpk-td__timeline-item--warning");
3517
+ if (item.kind === "message") {
3518
+ const title = item.title.toLowerCase();
3519
+ if (title.startsWith("user")) classes.push("cpk-td__timeline-item--user");
3520
+ else if (title.includes("assistant")) classes.push("cpk-td__timeline-item--assistant");
3521
+ }
3522
+ return classes.join(" ");
3224
3523
  }
3225
3524
  renderTimelineItem(item) {
3226
- const isWarning = item.kind === "warning";
3227
3525
  const detailsExpanded = this._expandedTimelineDetails.has(item.id);
3228
3526
  return html`
3229
3527
  <div
3230
- class="cpk-td__timeline-item ${isWarning ? "cpk-td__timeline-item--warning" : ""}"
3528
+ class=${this.timelineItemClass(item)}
3231
3529
  data-message-id=${item.messageId ?? nothing}
3232
3530
  >
3233
3531
  <div class="cpk-td__timeline-header">
@@ -3235,13 +3533,15 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3235
3533
  >${item.severity === "error" ? "error" : item.kind}</span
3236
3534
  >
3237
3535
  <span class="cpk-td__timeline-title">${item.title}</span>
3238
- <button
3239
- type="button"
3240
- class="cpk-td__source-link"
3241
- @click=${() => this.revealSourceEvent(item.sourceIndex)}
3242
- >
3243
- Source event #${item.sourceIndex}
3244
- </button>
3536
+ ${item.sourceIndex ? html`
3537
+ <button
3538
+ type="button"
3539
+ class="cpk-td__source-link"
3540
+ @click=${() => this.revealSourceEvent(item.sourceIndex)}
3541
+ >
3542
+ Source event #${item.sourceIndex}
3543
+ </button>
3544
+ ` : nothing}
3245
3545
  <span class="cpk-td__timeline-time"
3246
3546
  >${formatTimestamp(item.timestamp)}</span
3247
3547
  >
@@ -3278,9 +3578,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3278
3578
  <span>${detailsExpanded ? "Hide details" : "Show details"}</span>
3279
3579
  </button>` : nothing}
3280
3580
  ${item.body ? html`<div class="cpk-td__timeline-body">${item.body}</div>` : nothing}
3281
- ${item.details && detailsExpanded ? html`<pre class="cpk-td__timeline-body">
3282
- ${unsafeHTML(highlightedJson(item.details))}</pre
3283
- >` : nothing}
3581
+ ${item.details && detailsExpanded ? renderHighlightedJsonBlock(item.details) : nothing}
3284
3582
  </div>
3285
3583
  `;
3286
3584
  }
@@ -3410,9 +3708,7 @@ ${unsafeHTML(highlightedJson(item.details))}</pre
3410
3708
  ${expanded ? html`
3411
3709
  <div class="cpk-td__tool-body">
3412
3710
  <div class="cpk-td__tool-section-label">Arguments</div>
3413
- <pre class="cpk-td__tool-pre">
3414
- ${unsafeHTML(highlightedJson(item.arguments))}</pre
3415
- >
3711
+ ${renderHighlightedJsonBlock(item.arguments)}
3416
3712
  ${item.result ? html`
3417
3713
  <div
3418
3714
  class="cpk-td__tool-section-label"
@@ -3420,9 +3716,7 @@ ${unsafeHTML(highlightedJson(item.arguments))}</pre
3420
3716
  >
3421
3717
  Result
3422
3718
  </div>
3423
- <pre class="cpk-td__tool-pre">
3424
- ${unsafeHTML(highlightedJson(item.result))}</pre
3425
- >
3719
+ ${renderHighlightedJsonBlock(item.result)}
3426
3720
  ` : nothing}
3427
3721
  </div>
3428
3722
  ` : nothing}
@@ -3537,15 +3831,17 @@ ${unsafeHTML(highlightedJson(item.result))}</pre
3537
3831
  </div>
3538
3832
  `;
3539
3833
  return this.cachedPanelTpl("raw-events", [events, this._expandedRawEvents], () => {
3540
- return html`${events.map((event) => {
3541
- const { bg, fg } = eventColors(event.type);
3834
+ return html`${this.renderRawEventBulkControls()}${events.map((event) => {
3542
3835
  const eventId = this.rawEventId(event);
3543
3836
  const detailsExpanded = this._expandedRawEvents.has(eventId);
3544
3837
  return html`
3545
- <div class="cpk-td__event" data-source-index=${event.sourceIndex}>
3546
- <div class="cpk-td__event-header" style="background:${bg}">
3547
- <span class="cpk-td__event-type" style="color:${fg}"
3548
- >${event.type}</span
3838
+ <div
3839
+ class="cpk-td__event cpk-td__event--${eventCategory(event.type)}"
3840
+ data-source-index=${event.sourceIndex}
3841
+ >
3842
+ <div class="cpk-td__event-header">
3843
+ <span class="cpk-td__event-type" title=${event.type}
3844
+ >${humanizeEventType(event.type)}</span
3549
3845
  >
3550
3846
  <span class="cpk-td__event-time"
3551
3847
  >${formatTimestamp(event.timestamp)}</span
@@ -3584,9 +3880,7 @@ ${unsafeHTML(highlightedJson(item.result))}</pre
3584
3880
  >${detailsExpanded ? "Hide details" : "Show details"}</span
3585
3881
  >
3586
3882
  </button>
3587
- ${detailsExpanded ? html`<pre class="cpk-td__event-payload">
3588
- ${unsafeHTML(highlightedJson(event.rawEvent ?? event))}</pre
3589
- >` : nothing}
3883
+ ${detailsExpanded ? renderHighlightedJsonBlock(event.rawEvent ?? event) : nothing}
3590
3884
  </div>
3591
3885
  `;
3592
3886
  })}`;
@@ -4405,26 +4699,6 @@ var WebInspectorElement = class WebInspectorElement extends LitElement {
4405
4699
  inspect: "ag-ui-events"
4406
4700
  };
4407
4701
  this.lastScrolledAgentNavigationLayout = null;
4408
- this.eventSnippets = [];
4409
- this.selectedSnippetId = null;
4410
- this.snippetRecipe = "tool-call";
4411
- this.snippetName = "";
4412
- this.snippetJson = "[]";
4413
- this.snippetToolName = "";
4414
- this.snippetToolArgs = "{}";
4415
- this.snippetReasoningText = "";
4416
- this.snippetTextContent = "";
4417
- this.snippetActivityType = "a2ui-surface";
4418
- this.snippetActivityContent = "{}";
4419
- this.snippetError = null;
4420
- this.snippetBanner = null;
4421
- this.snippetConfirmOpen = false;
4422
- this.lastInject = null;
4423
- this.snippetListWidth = 200;
4424
- this.snippetDividerResizing = false;
4425
- this.snippetDividerPointerId = -1;
4426
- this.snippetDividerStartX = 0;
4427
- this.snippetDividerStartWidth = 0;
4428
4702
  this.selectedThreadId = null;
4429
4703
  this.inAppThreadId = null;
4430
4704
  this.inAppAgentId = null;
@@ -4465,6 +4739,7 @@ var WebInspectorElement = class WebInspectorElement extends LitElement {
4465
4739
  this.threadCapabilityEnabled = null;
4466
4740
  this.threadCapabilityGeneration = 0;
4467
4741
  this.contextMenuOpen = false;
4742
+ this.iconRailContextCloseTimer = null;
4468
4743
  this.layoutMenuOpen = false;
4469
4744
  this.dockMode = "floating";
4470
4745
  this.popOut = null;
@@ -4526,6 +4801,9 @@ var WebInspectorElement = class WebInspectorElement extends LitElement {
4526
4801
  this.launcherHudSide = "left";
4527
4802
  this.launcherHudHelp = null;
4528
4803
  this.launcherHudCloseTimer = null;
4804
+ this.launcherHudIntro = false;
4805
+ this.launcherHudIntroStartTimer = null;
4806
+ this.launcherHudIntroEndTimer = null;
4529
4807
  this.hudLandingMenu = null;
4530
4808
  this.pillOutcome = null;
4531
4809
  this.viewedNewsSignalIds = /* @__PURE__ */ new Set();
@@ -4610,6 +4888,7 @@ var WebInspectorElement = class WebInspectorElement extends LitElement {
4610
4888
  this.openInspector("floating_button");
4611
4889
  };
4612
4890
  this.handleLauncherHudEnter = () => {
4891
+ this.cancelLauncherHudIntro();
4613
4892
  this.openLauncherHud();
4614
4893
  };
4615
4894
  this.handleLauncherHudLeave = () => {
@@ -4620,6 +4899,7 @@ var WebInspectorElement = class WebInspectorElement extends LitElement {
4620
4899
  }, 160);
4621
4900
  };
4622
4901
  this.handleLauncherHudFocusIn = () => {
4902
+ this.cancelLauncherHudIntro();
4623
4903
  this.openLauncherHud();
4624
4904
  };
4625
4905
  this.handleLauncherHudFocusOut = (event) => {
@@ -5025,19 +5305,6 @@ var WebInspectorElement = class WebInspectorElement extends LitElement {
5025
5305
  this.handlePlaygroundStop = () => {
5026
5306
  this.playgroundAgent?.abortRun();
5027
5307
  };
5028
- this.handleSnippetImportChange = async (event) => {
5029
- const input = event.target;
5030
- const file = input.files?.[0];
5031
- input.value = "";
5032
- if (!file) return;
5033
- try {
5034
- this.eventSnippets = importEventSnippets(await file.text());
5035
- this.snippetError = null;
5036
- } catch (error) {
5037
- this.snippetError = error instanceof Error ? error.message : "Import failed.";
5038
- }
5039
- this.requestUpdate();
5040
- };
5041
5308
  this.handleInspectorMetadataActionClick = (action, placement) => {
5042
5309
  if (!this.isOpen || this.runtimeStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected || this.core?.telemetryDisabled) return;
5043
5310
  if (action.kind === "enable_intelligence") {
@@ -5065,26 +5332,6 @@ var WebInspectorElement = class WebInspectorElement extends LitElement {
5065
5332
  if (this.core?.telemetryDisabled) return;
5066
5333
  trackThreadsTalkToEngineerClicked(this.getThreadsCtaTelemetryProps("talk_to_engineer", "threads_locked"));
5067
5334
  };
5068
- this.handleSnippetListDividerPointerDown = (event) => {
5069
- this.snippetDividerResizing = true;
5070
- this.snippetDividerPointerId = event.pointerId;
5071
- this.snippetDividerStartX = event.clientX;
5072
- this.snippetDividerStartWidth = this.snippetListWidth;
5073
- event.currentTarget.setPointerCapture(event.pointerId);
5074
- event.preventDefault();
5075
- };
5076
- this.handleSnippetListDividerPointerMove = (event) => {
5077
- if (!this.snippetDividerResizing || this.snippetDividerPointerId !== event.pointerId) return;
5078
- const delta = event.clientX - this.snippetDividerStartX;
5079
- this.snippetListWidth = Math.max(160, Math.min(360, this.snippetDividerStartWidth + delta));
5080
- this.requestUpdate();
5081
- };
5082
- this.handleSnippetListDividerPointerUp = (event) => {
5083
- if (this.snippetDividerPointerId !== event.pointerId) return;
5084
- const target = event.currentTarget;
5085
- if (target.hasPointerCapture(this.snippetDividerPointerId)) target.releasePointerCapture(this.snippetDividerPointerId);
5086
- this.snippetDividerResizing = false;
5087
- };
5088
5335
  this.handleThreadDividerPointerDown = (event) => {
5089
5336
  this.threadDividerResizing = true;
5090
5337
  this.threadDividerPointerId = event.pointerId;
@@ -5199,15 +5446,21 @@ var WebInspectorElement = class WebInspectorElement extends LitElement {
5199
5446
  this.requestUpdate();
5200
5447
  };
5201
5448
  this.handleIconRailContextPointerEnter = (event) => {
5202
- if (event.pointerType === "touch" || this.contextMenuOpen) return;
5449
+ if (event.pointerType === "touch") return;
5450
+ this.clearIconRailContextCloseTimer();
5451
+ if (this.contextMenuOpen) return;
5203
5452
  this.layoutMenuOpen = false;
5204
5453
  this.contextMenuOpen = true;
5205
5454
  this.requestUpdate();
5206
5455
  };
5207
5456
  this.handleIconRailContextPointerLeave = () => {
5208
5457
  if (!this.contextMenuOpen) return;
5209
- this.contextMenuOpen = false;
5210
- this.requestUpdate();
5458
+ this.clearIconRailContextCloseTimer();
5459
+ this.iconRailContextCloseTimer = setTimeout(() => {
5460
+ this.iconRailContextCloseTimer = null;
5461
+ this.contextMenuOpen = false;
5462
+ this.requestUpdate();
5463
+ }, 180);
5211
5464
  };
5212
5465
  this.handleIconRailContextPointerDown = (event) => {
5213
5466
  if (event.pointerType === "touch") {
@@ -5218,6 +5471,7 @@ var WebInspectorElement = class WebInspectorElement extends LitElement {
5218
5471
  event.stopPropagation();
5219
5472
  };
5220
5473
  this.handleIconRailContextFocusIn = () => {
5474
+ this.clearIconRailContextCloseTimer();
5221
5475
  if (this.contextMenuOpen) return;
5222
5476
  this.layoutMenuOpen = false;
5223
5477
  this.contextMenuOpen = true;
@@ -5341,11 +5595,6 @@ var WebInspectorElement = class WebInspectorElement extends LitElement {
5341
5595
  label: "AG-UI Events",
5342
5596
  icon: "Zap"
5343
5597
  },
5344
- {
5345
- key: "event-snippets",
5346
- label: "Event Snippets",
5347
- icon: "Code"
5348
- },
5349
5598
  {
5350
5599
  key: "agents",
5351
5600
  label: "Agent",
@@ -6193,7 +6442,7 @@ var WebInspectorElement = class WebInspectorElement extends LitElement {
6193
6442
  const messages = this.normalizeAgentMessages(agent.messages);
6194
6443
  if (messages) this.agentMessages.set(agent.agentId, messages);
6195
6444
  else this.agentMessages.delete(agent.agentId);
6196
- const runThreadId = agent.threadId;
6445
+ const runThreadId = this.readAgentThreadId(agent);
6197
6446
  if (runThreadId) this.liveMessageVersion.set(runThreadId, (this.liveMessageVersion.get(runThreadId) ?? 0) + 1);
6198
6447
  this.requestUpdate();
6199
6448
  } catch (error) {
@@ -6276,19 +6525,6 @@ var WebInspectorElement = class WebInspectorElement extends LitElement {
6276
6525
  this.persistState();
6277
6526
  this.requestUpdate();
6278
6527
  }
6279
- focusEventSnippets(options) {
6280
- this.pendingPersistedMenu = null;
6281
- this.selectedMenu = "event-snippets";
6282
- this.settingsOpen = false;
6283
- this.lastSelectedMenuByGroup.inspect = "event-snippets";
6284
- this.contextMenuOpen = false;
6285
- this.layoutMenuOpen = false;
6286
- this.reloadEventSnippets();
6287
- if (options.snippetId) this.selectEventSnippet(options.snippetId);
6288
- if (options.agentId && this.contextOptions.some((option) => option.key === options.agentId)) this.selectedContext = options.agentId;
6289
- this.persistState();
6290
- this.requestUpdate();
6291
- }
6292
6528
  filterEvents(events) {
6293
6529
  const query = this.eventFilterText.trim().toLowerCase();
6294
6530
  return events.filter((event) => {
@@ -6310,6 +6546,20 @@ var WebInspectorElement = class WebInspectorElement extends LitElement {
6310
6546
  getLatestMessagesForAgent(agentId) {
6311
6547
  return this.agentMessages.get(agentId) ?? null;
6312
6548
  }
6549
+ readAgentThreadId(agent) {
6550
+ if (!("threadId" in agent)) return void 0;
6551
+ const threadId = agent.threadId;
6552
+ return typeof threadId === "string" ? threadId : void 0;
6553
+ }
6554
+ getLiveAgentMessagesForThread(thread) {
6555
+ const messages = this.agentMessages.get(thread.agentId) ?? EMPTY_INSPECTOR_MESSAGES;
6556
+ const core = this._core;
6557
+ if (!core || typeof core.getAgent !== "function") return messages;
6558
+ const agent = core.getAgent(thread.agentId);
6559
+ if (!agent) return EMPTY_INSPECTOR_MESSAGES;
6560
+ if (this.readAgentThreadId(agent) !== thread.id) return EMPTY_INSPECTOR_MESSAGES;
6561
+ return messages;
6562
+ }
6313
6563
  getAgentStatus(agentId) {
6314
6564
  const events = this.agentEvents.get(agentId) ?? [];
6315
6565
  if (events.length === 0) return "idle";
@@ -6356,11 +6606,9 @@ var WebInspectorElement = class WebInspectorElement extends LitElement {
6356
6606
  ${isFailedCall && toolError?.message ? html`<p class="mt-2 break-words leading-relaxed text-gray-800">
6357
6607
  ${toolError.message}
6358
6608
  </p>` : nothing}
6359
- ${argsString ? html`<pre
6360
- class="mt-2 overflow-auto rounded bg-white p-2 text-[11px] leading-relaxed text-gray-800"
6361
- >
6362
- ${argsString}</pre
6363
- >` : nothing}
6609
+ ${argsString ? html`<div class="mt-2">
6610
+ ${renderHighlightedJsonBlock(coerceJsonValue(call.function?.arguments))}
6611
+ </div>` : nothing}
6364
6612
  </div>
6365
6613
  `;
6366
6614
  })}
@@ -6412,15 +6660,14 @@ ${argsString}</pre
6412
6660
  return String(state);
6413
6661
  }
6414
6662
  getEventBadgeClasses(type) {
6415
- const base = "font-mono text-[10px] font-medium inline-flex items-center rounded-sm px-1.5 py-0.5 border";
6416
- if (type === "RUN_ERROR") return `${base} bg-rose-50 text-rose-700 border-rose-200`;
6417
- if (type.startsWith("RUN_")) return `${base} bg-blue-50 text-blue-700 border-blue-200`;
6418
- if (type.startsWith("TEXT_MESSAGE")) return `${base} bg-emerald-50 text-emerald-700 border-emerald-200`;
6419
- if (type.startsWith("TOOL_CALL")) return `${base} bg-amber-50 text-amber-700 border-amber-200`;
6420
- if (type.startsWith("REASONING")) return `${base} bg-fuchsia-50 text-fuchsia-700 border-fuchsia-200`;
6421
- if (type.startsWith("STATE")) return `${base} bg-violet-50 text-violet-700 border-violet-200`;
6422
- if (type.startsWith("MESSAGES")) return `${base} bg-sky-50 text-sky-700 border-sky-200`;
6423
- return `${base} bg-gray-100 text-gray-600 border-gray-200`;
6663
+ const base = "font-mono text-[10px] font-semibold inline-flex items-center rounded-sm px-1.5 py-0.5 border";
6664
+ if (type === "RUN_ERROR") return `${base} bg-rose-50 text-rose-800 border-rose-200`;
6665
+ if (type.startsWith("TEXT_MESSAGE")) return `${base} bg-violet-50 text-gray-900 border-violet-200`;
6666
+ if (type.startsWith("TOOL_CALL")) return `${base} bg-emerald-50 text-gray-900 border-emerald-200`;
6667
+ if (type.startsWith("RUN_") || type.startsWith("STEP_")) return `${base} bg-gray-100 text-gray-900 border-gray-200`;
6668
+ if (type.startsWith("REASONING")) return `${base} bg-violet-50 text-gray-900 border-violet-200`;
6669
+ if (type.startsWith("STATE") || type.startsWith("MESSAGES")) return `${base} bg-violet-50 text-gray-900 border-violet-200`;
6670
+ return `${base} bg-gray-100 text-gray-900 border-gray-200`;
6424
6671
  }
6425
6672
  stringifyPayload(payload, pretty) {
6426
6673
  try {
@@ -6467,6 +6714,13 @@ ${argsString}</pre
6467
6714
  static {
6468
6715
  this.styles = [unsafeCSS(generated_default), css`
6469
6716
  :host {
6717
+ --cpk-inspector-shell-radius: 5px;
6718
+ --cpk-inspector-surface-dark: #111319;
6719
+ --cpk-json-key: #3d408f;
6720
+ --cpk-json-str: #0b6b4c;
6721
+ --cpk-json-num: #8a5900;
6722
+ --cpk-json-bool: #c0333a;
6723
+ --cpk-json-nil: #57575b;
6470
6724
  position: fixed;
6471
6725
  top: 0;
6472
6726
  left: 0;
@@ -6476,6 +6730,191 @@ ${argsString}</pre
6476
6730
  font-family: "Plus Jakarta Sans", system-ui, sans-serif;
6477
6731
  }
6478
6732
 
6733
+ :host([data-color-scheme="dark"]),
6734
+ .inspector-window[data-color-scheme="dark"] {
6735
+ --cpk-json-key: #bec2ff;
6736
+ --cpk-json-str: #85ecce;
6737
+ --cpk-json-num: #ffac4d;
6738
+ --cpk-json-bool: #fa5f67;
6739
+ --cpk-json-nil: #afafb7;
6740
+ }
6741
+
6742
+ .cpk-json-token--key {
6743
+ color: var(--cpk-json-key);
6744
+ }
6745
+
6746
+ .cpk-json-token--str {
6747
+ color: var(--cpk-json-str);
6748
+ }
6749
+
6750
+ .cpk-json-token--num {
6751
+ color: var(--cpk-json-num);
6752
+ }
6753
+
6754
+ .cpk-json-token--bool {
6755
+ color: var(--cpk-json-bool);
6756
+ }
6757
+
6758
+ .cpk-json-token--nil {
6759
+ color: var(--cpk-json-nil);
6760
+ }
6761
+
6762
+ .cpk-json-block {
6763
+ margin: 0;
6764
+ padding: 10px 12px;
6765
+ border: 1px solid #dbdbe5;
6766
+ border-radius: 8px;
6767
+ background: #f7f7f9;
6768
+ font-family: "Spline Sans Mono", monospace;
6769
+ font-size: 12px;
6770
+ line-height: 1.65;
6771
+ white-space: pre-wrap;
6772
+ overflow-wrap: anywhere;
6773
+ word-break: normal;
6774
+ color: #010507;
6775
+ overflow: auto;
6776
+ }
6777
+
6778
+ :host([data-color-scheme="dark"]) .cpk-json-block,
6779
+ .inspector-window[data-color-scheme="dark"] .cpk-json-block {
6780
+ background: #111319;
6781
+ border-color: #343742;
6782
+ color: #f3f4f8;
6783
+ }
6784
+
6785
+ @keyframes cpk-playground-message-enter {
6786
+ from {
6787
+ opacity: 0;
6788
+ filter: blur(2px);
6789
+ transform: translateY(4px);
6790
+ }
6791
+ to {
6792
+ opacity: 1;
6793
+ filter: blur(0);
6794
+ transform: translateY(0);
6795
+ }
6796
+ }
6797
+
6798
+ @keyframes cpk-playground-thinking {
6799
+ 0%,
6800
+ 60%,
6801
+ 100% {
6802
+ opacity: 0.28;
6803
+ transform: translateY(0);
6804
+ }
6805
+ 30% {
6806
+ opacity: 1;
6807
+ transform: translateY(-2px);
6808
+ }
6809
+ }
6810
+
6811
+ .cpk-playground-root {
6812
+ container-type: inline-size;
6813
+ background: #fbfbfd !important;
6814
+ }
6815
+
6816
+ .cpk-playground-header {
6817
+ min-height: 58px;
6818
+ background: #f7f6fd !important;
6819
+ }
6820
+
6821
+ .cpk-playground-welcome {
6822
+ max-width: 560px;
6823
+ padding: 24px;
6824
+ }
6825
+
6826
+ .cpk-playground-welcome-title {
6827
+ color: #24242b;
6828
+ font-size: 15px;
6829
+ font-weight: 600;
6830
+ letter-spacing: -0.015em;
6831
+ }
6832
+
6833
+ .cpk-playground-composer {
6834
+ border: 1px solid #dcdce8;
6835
+ box-shadow: 0 8px 22px rgba(31, 23, 57, 0.08),
6836
+ 0 1px 2px rgba(31, 23, 57, 0.1);
6837
+ }
6838
+
6839
+ .cpk-playground-composer:focus-within {
6840
+ border-color: #aaa4d4;
6841
+ box-shadow: 0 10px 26px rgba(86, 53, 155, 0.13),
6842
+ 0 0 0 3px rgba(190, 194, 255, 0.3);
6843
+ }
6844
+
6845
+ .inspector-window[data-color-scheme="dark"] .cpk-playground-root,
6846
+ .inspector-window[data-color-scheme="dark"] .cpk-playground-header {
6847
+ background: #15171e !important;
6848
+ }
6849
+
6850
+ .inspector-window[data-color-scheme="dark"]
6851
+ .cpk-playground-welcome-title {
6852
+ color: #f3f4f8 !important;
6853
+ }
6854
+
6855
+ .inspector-window[data-color-scheme="dark"] .cpk-playground-composer {
6856
+ border-color: #464957;
6857
+ background: #15171e !important;
6858
+ box-shadow: 0 8px 22px rgba(0, 0, 0, 0.26),
6859
+ 0 1px 2px rgba(0, 0, 0, 0.36);
6860
+ }
6861
+
6862
+ .inspector-window[data-color-scheme="dark"]
6863
+ .cpk-playground-composer:focus-within {
6864
+ border-color: #777aae;
6865
+ box-shadow: 0 10px 26px rgba(0, 0, 0, 0.34),
6866
+ 0 0 0 3px rgba(102, 106, 158, 0.3);
6867
+ }
6868
+
6869
+ .cpk-playground-message-enter {
6870
+ animation: cpk-playground-message-enter 0.24s cubic-bezier(0.16, 1, 0.3, 1)
6871
+ both;
6872
+ }
6873
+
6874
+ .cpk-playground-thinking-dot {
6875
+ animation: cpk-playground-thinking 1.2s ease-in-out infinite;
6876
+ }
6877
+
6878
+ .cpk-playground-thinking-dot:nth-child(2) {
6879
+ animation-delay: 0.12s;
6880
+ }
6881
+
6882
+ .cpk-playground-thinking-dot:nth-child(3) {
6883
+ animation-delay: 0.24s;
6884
+ }
6885
+
6886
+ .cpk-playground-reasoning summary::-webkit-details-marker {
6887
+ display: none;
6888
+ }
6889
+
6890
+ .cpk-playground-reasoning[open]
6891
+ .cpk-playground-reasoning-chevron {
6892
+ transform: rotate(90deg);
6893
+ }
6894
+
6895
+ @container (max-width: 560px) {
6896
+ .cpk-playground-header {
6897
+ align-items: stretch;
6898
+ }
6899
+
6900
+ .cpk-playground-actions {
6901
+ width: 100%;
6902
+ }
6903
+
6904
+ .cpk-playground-thread-select {
6905
+ min-width: 0;
6906
+ max-width: none;
6907
+ flex: 1;
6908
+ }
6909
+ }
6910
+
6911
+ @media (prefers-reduced-motion: reduce) {
6912
+ .cpk-playground-message-enter,
6913
+ .cpk-playground-thinking-dot {
6914
+ animation: none;
6915
+ }
6916
+ }
6917
+
6479
6918
  .rounded-sm {
6480
6919
  border-radius: 3px;
6481
6920
  }
@@ -6511,8 +6950,8 @@ ${argsString}</pre
6511
6950
  the two cannot drift apart. A dark grey rather than near-black: the
6512
6951
  launcher sits on a customer's page, and 1,5,7 against white is a
6513
6952
  harder edge than this surface needs. */
6514
- --cpk-launcher-face: rgba(28, 31, 36, 0.95);
6515
- --cpk-launcher-face-solid: rgb(28, 31, 36);
6953
+ --cpk-launcher-face: rgba(24, 28, 31, 0.95);
6954
+ --cpk-launcher-face-solid: rgb(24, 28, 31);
6516
6955
  --cpk-launcher-edge: rgba(190, 194, 255, 0.25);
6517
6956
  /* The launcher's own size, exposed so the signal dot can be placed
6518
6957
  against the OUTER rim with a length rather than a percentage.
@@ -6535,6 +6974,10 @@ ${argsString}</pre
6535
6974
  box-sizing: border-box;
6536
6975
  transition:
6537
6976
  transform 300ms cubic-bezier(0.34, 1.56, 0.64, 1),
6977
+ scale 300ms cubic-bezier(0.34, 1.56, 0.64, 1),
6978
+ background-color 200ms ease,
6979
+ border-color 200ms ease,
6980
+ box-shadow 200ms ease,
6538
6981
  opacity 160ms ease;
6539
6982
  }
6540
6983
 
@@ -6562,6 +7005,7 @@ ${argsString}</pre
6562
7005
  touch-action: none;
6563
7006
  user-select: none;
6564
7007
  z-index: 60;
7008
+ background: transparent;
6565
7009
  }
6566
7010
 
6567
7011
  .edge-resize-handle {
@@ -6696,18 +7140,77 @@ ${argsString}</pre
6696
7140
  flex-shrink: 0;
6697
7141
  transition:
6698
7142
  background-color 0.15s,
6699
- border-color 0.15s;
7143
+ border-color 0.15s,
7144
+ color 0.15s;
6700
7145
  }
6701
7146
  .cpk-copy-btn:hover {
6702
7147
  background-color: #f0f0f4;
6703
7148
  border-color: #afafb7;
6704
7149
  }
6705
7150
 
7151
+ .inspector-window[data-color-scheme="dark"] .cpk-copy-btn {
7152
+ background: #191c24;
7153
+ border-color: #3a3d49;
7154
+ color: #f3f4f8;
7155
+ }
7156
+
7157
+ .inspector-window[data-color-scheme="dark"] .cpk-copy-btn:hover {
7158
+ background: #20232d;
7159
+ border-color: #57575b;
7160
+ }
7161
+
7162
+ .inspector-sidebar[data-icon-rail="true"]
7163
+ .inspector-sidebar-agent-scope
7164
+ [data-context-dropdown-root="true"]
7165
+ > div {
7166
+ left: 100%;
7167
+ margin-inline-start: 8px;
7168
+ }
7169
+
7170
+ .inspector-icon-rail-menu {
7171
+ transform-origin: left center;
7172
+ opacity: 0;
7173
+ visibility: hidden;
7174
+ pointer-events: none;
7175
+ transform: translateX(-8px) scale(0.96);
7176
+ transition:
7177
+ opacity 180ms ease,
7178
+ transform 180ms ease,
7179
+ visibility 180ms ease;
7180
+ }
7181
+
7182
+ .inspector-icon-rail-menu[data-open="true"] {
7183
+ opacity: 1;
7184
+ visibility: visible;
7185
+ pointer-events: auto;
7186
+ transform: translateX(0) scale(1);
7187
+ }
7188
+
7189
+ @media (prefers-reduced-motion: reduce) {
7190
+ .inspector-icon-rail-menu {
7191
+ transition: none;
7192
+ }
7193
+ }
7194
+
7195
+ .inspector-sidebar[data-icon-rail="true"]
7196
+ .inspector-sidebar-agent-scope
7197
+ [data-context-dropdown-root="true"]
7198
+ > div::before {
7199
+ content: "";
7200
+ position: absolute;
7201
+ inset-block: 0;
7202
+ inset-inline-end: 100%;
7203
+ width: 12px;
7204
+ }
7205
+
6706
7206
  .cpk-section-header {
6707
7207
  background: #e8edf5;
6708
7208
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
6709
7209
  padding: 10px 16px;
6710
7210
  }
7211
+ .inspector-window[data-color-scheme="dark"] .cpk-section-header {
7212
+ border-bottom-color: #3a3d49;
7213
+ }
6711
7214
  .cpk-section-header h4 {
6712
7215
  font-size: 11px;
6713
7216
  font-weight: 600;
@@ -6932,13 +7435,29 @@ ${argsString}</pre
6932
7435
  .console-button {
6933
7436
  background-color: var(--cpk-launcher-face) !important;
6934
7437
  border-color: var(--cpk-launcher-edge) !important;
7438
+ /* One hairline, not two. The border above is it; a second ring used to
7439
+ sit 1px outside as a box-shadow and hardcoded the lilac instead of
7440
+ reading the --cpk-launcher-edge token, so it could not follow it.
7441
+ What replaces it is a one-pixel light edge along the top, which is
7442
+ what keeps the face from reading flat without drawing a frame.
7443
+
7444
+ The border is not decoration: the face is #181C1F, which against a
7445
+ dark host page (GitHub dark 1.10:1, Tailwind slate-900 1.04:1) is
7446
+ indistinguishable from the page. It is the only thing that gives the
7447
+ launcher an outline there, so it stays. */
6935
7448
  box-shadow:
6936
- 0 0 0 1px rgba(190, 194, 255, 0.15),
7449
+ inset 0 1px 0 rgba(255, 255, 255, 0.07),
6937
7450
  0 4px 14px rgba(1, 5, 7, 0.28) !important;
7451
+ /* Promotes the launcher to its own compositing layer, which the
7452
+ backdrop-filter this replaces used to do as a side effect. Without
7453
+ a layer the hover scale re-rasterises the mark every frame and it
7454
+ visibly jitters; with one, the compositor scales it as a texture. */
7455
+ will-change: transform;
6938
7456
  }
6939
7457
  .console-button:hover {
6940
7458
  background-color: var(--cpk-launcher-face-solid) !important;
6941
7459
  border-color: rgba(190, 194, 255, 0.45) !important;
7460
+ transform: scale(1.05);
6942
7461
  }
6943
7462
  .console-button:focus-visible {
6944
7463
  outline-color: #bec2ff !important;
@@ -7060,8 +7579,23 @@ ${argsString}</pre
7060
7579
  width: 19%;
7061
7580
  height: 19%;
7062
7581
  border-radius: 50%;
7063
- background: var(--cpk-launcher-signal);
7064
- box-shadow: 0 0 0 1.5px var(--cpk-launcher-face);
7582
+ /* Lit from the upper left and shaded at the lower right, so the dot
7583
+ reads as a lens rather than a flat disc. Both stops are derived from
7584
+ the signal colour, so a new tone needs no new values. */
7585
+ background: radial-gradient(
7586
+ circle at 32% 28%,
7587
+ color-mix(in srgb, var(--cpk-launcher-signal), white 40%) 0%,
7588
+ var(--cpk-launcher-signal) 60%,
7589
+ color-mix(in srgb, var(--cpk-launcher-signal), black 20%) 100%
7590
+ );
7591
+ /* Replaces an opaque 1.5px collar in the launcher's own face. That
7592
+ collar was 21% of the dot's footprint, and because the dot's centre
7593
+ sits *on* the rim, its outer half painted a hard dark crescent onto
7594
+ the host page rather than onto the launcher. A hairline plus a soft
7595
+ drop does the same separating job without the hard edge. */
7596
+ box-shadow:
7597
+ 0 0 0 0.5px rgba(1, 5, 7, 0.4),
7598
+ 0 1px 2.5px rgba(1, 5, 7, 0.5);
7065
7599
  }
7066
7600
 
7067
7601
  /* ── Launcher pill: the launcher opens sideways and says what ─── */
@@ -7272,6 +7806,12 @@ ${argsString}</pre
7272
7806
  .cpk-launcher-signal-wash {
7273
7807
  animation: none !important;
7274
7808
  }
7809
+ .console-button {
7810
+ transition: opacity 160ms ease;
7811
+ }
7812
+ .console-button:hover {
7813
+ transform: none;
7814
+ }
7275
7815
  }
7276
7816
 
7277
7817
  /* ── Launcher HUD: hover menu, quieter than the error island ── */
@@ -7283,6 +7823,9 @@ ${argsString}</pre
7283
7823
  }
7284
7824
 
7285
7825
  .cpk-launcher-hud {
7826
+ --hud-fill: var(--cpk-inspector-surface-dark);
7827
+ --hud-line: rgb(190 194 255 / 0.5);
7828
+ --hud-blur: blur(12px) saturate(1.2);
7286
7829
  position: absolute;
7287
7830
  top: 0;
7288
7831
  z-index: 4;
@@ -7316,38 +7859,47 @@ ${argsString}</pre
7316
7859
  }
7317
7860
 
7318
7861
  .cpk-launcher-hud__card {
7319
- --hud-fill: rgb(28 31 36 / 0.88);
7320
- --hud-line: rgb(190 194 255 / 0.5);
7321
7862
  position: relative;
7322
7863
  width: 228px;
7323
7864
  padding: 4px;
7324
7865
  border: 1px dotted var(--hud-line);
7325
- border-radius: 10px;
7866
+ border-radius: var(--cpk-inspector-shell-radius);
7326
7867
  background: var(--hud-fill);
7327
7868
  color: #fff;
7328
- backdrop-filter: blur(12px) saturate(1.2);
7869
+ backdrop-filter: var(--hud-blur);
7870
+ -webkit-backdrop-filter: var(--hud-blur);
7329
7871
  box-shadow: 0 8px 20px rgb(1 5 7 / 0.18);
7330
7872
  }
7331
7873
 
7874
+ .cpk-launcher-hud[data-color-scheme="light"] {
7875
+ --hud-fill: #fff;
7876
+ --hud-line: #d8d8e8;
7877
+ }
7878
+
7879
+ .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__card {
7880
+ color: #010507;
7881
+ }
7882
+
7332
7883
  .cpk-launcher-hud__arrow {
7333
7884
  position: absolute;
7334
7885
  top: calc(var(--cpk-launcher-size) / 2);
7886
+ z-index: 1;
7335
7887
  width: 10px;
7336
7888
  height: 10px;
7337
- background: var(--hud-fill);
7889
+ border: 0;
7890
+ /* The card frosts the page behind it, so it reads lighter than the
7891
+ raw fill. Mix a little white so the arrow matches the glass card
7892
+ without going lighter than the HUD. */
7893
+ background: color-mix(in srgb, var(--hud-fill) 88%, white 12%);
7338
7894
  transform: translateY(-50%) rotate(45deg);
7339
7895
  }
7340
7896
 
7341
7897
  .cpk-launcher-hud[data-cpk-hud-side="left"] .cpk-launcher-hud__arrow {
7342
- right: -5px;
7343
- border-top: 1px solid var(--hud-line);
7344
- border-right: 1px solid var(--hud-line);
7898
+ right: 9px;
7345
7899
  }
7346
7900
 
7347
7901
  .cpk-launcher-hud[data-cpk-hud-side="right"] .cpk-launcher-hud__arrow {
7348
- left: -5px;
7349
- border-bottom: 1px solid var(--hud-line);
7350
- border-left: 1px solid var(--hud-line);
7902
+ left: 9px;
7351
7903
  }
7352
7904
 
7353
7905
  .cpk-launcher-hud__list {
@@ -7381,6 +7933,12 @@ ${argsString}</pre
7381
7933
  background: rgb(255 255 255 / 0.06);
7382
7934
  }
7383
7935
 
7936
+ .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__row:hover,
7937
+ .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__row:focus-within,
7938
+ .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__row[data-cpk-hud-help="open"] {
7939
+ background: #f0f0f4;
7940
+ }
7941
+
7384
7942
  .cpk-launcher-hud__action {
7385
7943
  display: flex;
7386
7944
  gap: 8px;
@@ -7398,6 +7956,10 @@ ${argsString}</pre
7398
7956
  cursor: pointer;
7399
7957
  }
7400
7958
 
7959
+ .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__action {
7960
+ color: #010507;
7961
+ }
7962
+
7401
7963
  /* Stretch the row action over the whole tab, including the detail
7402
7964
  copy. The help mark sits above this layer. */
7403
7965
  .cpk-launcher-hud__action::after {
@@ -7441,6 +8003,10 @@ ${argsString}</pre
7441
8003
  line-height: 1;
7442
8004
  }
7443
8005
 
8006
+ .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__help {
8007
+ color: #68686e;
8008
+ }
8009
+
7444
8010
  .cpk-launcher-hud__help:focus-visible,
7445
8011
  .cpk-launcher-hud__action:focus-visible {
7446
8012
  outline: 2px solid #bec2ff;
@@ -7467,19 +8033,120 @@ ${argsString}</pre
7467
8033
  padding-bottom 200ms cubic-bezier(0.16, 1, 0.3, 1);
7468
8034
  }
7469
8035
 
7470
- .cpk-launcher-hud__row:hover .cpk-launcher-hud__detail,
7471
- .cpk-launcher-hud__row:focus-within .cpk-launcher-hud__detail,
7472
- .cpk-launcher-hud__row[data-cpk-hud-help="open"] .cpk-launcher-hud__detail {
7473
- max-height: 72px;
7474
- padding: 0 8px 7px;
7475
- opacity: 1;
7476
- transform: none;
8036
+ .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__detail {
8037
+ color: #68686e;
8038
+ }
8039
+
8040
+ .cpk-launcher-hud__row:hover .cpk-launcher-hud__detail,
8041
+ .cpk-launcher-hud__row:focus-within .cpk-launcher-hud__detail,
8042
+ .cpk-launcher-hud__row[data-cpk-hud-help="open"] .cpk-launcher-hud__detail {
8043
+ max-height: 72px;
8044
+ padding: 0 8px 7px;
8045
+ opacity: 1;
8046
+ transform: none;
8047
+ }
8048
+
8049
+ @media (prefers-reduced-motion: reduce) {
8050
+ .cpk-launcher-hud,
8051
+ .cpk-launcher-hud__detail {
8052
+ transition: none;
8053
+ }
8054
+ }
8055
+
8056
+ /*
8057
+ * On mount, borrow the hover HUD for one short introduction. The card
8058
+ * establishes the destination first; its rows then resolve in order so
8059
+ * the eye can count the available features instead of receiving one
8060
+ * undifferentiated block. Only opacity and transform move.
8061
+ */
8062
+ @keyframes cpk-launcher-hud-intro {
8063
+ 0% {
8064
+ opacity: 0;
8065
+ transform: translateX(8px);
8066
+ }
8067
+ 8%,
8068
+ 88% {
8069
+ opacity: 1;
8070
+ transform: none;
8071
+ }
8072
+ 100% {
8073
+ opacity: 0;
8074
+ transform: translateX(4px);
8075
+ }
8076
+ }
8077
+
8078
+ @keyframes cpk-launcher-hud-intro-right {
8079
+ 0% {
8080
+ opacity: 0;
8081
+ transform: translateX(-8px);
8082
+ }
8083
+ 8%,
8084
+ 88% {
8085
+ opacity: 1;
8086
+ transform: none;
8087
+ }
8088
+ 100% {
8089
+ opacity: 0;
8090
+ transform: translateX(-4px);
8091
+ }
8092
+ }
8093
+
8094
+ @keyframes cpk-launcher-hud-row-online {
8095
+ from {
8096
+ opacity: 0;
8097
+ transform: translateY(4px);
8098
+ }
8099
+ to {
8100
+ opacity: 1;
8101
+ transform: none;
8102
+ }
8103
+ }
8104
+
8105
+ @keyframes cpk-launcher-hud-check-online {
8106
+ from {
8107
+ opacity: 0;
8108
+ transform: scale(0.65);
8109
+ }
8110
+ to {
8111
+ opacity: 1;
8112
+ transform: scale(1);
8113
+ }
8114
+ }
8115
+
8116
+ .cpk-launcher-hud[data-cpk-hud-intro="true"] {
8117
+ animation: cpk-launcher-hud-intro
8118
+ var(--cpk-launcher-hud-intro-duration)
8119
+ cubic-bezier(0.16, 1, 0.3, 1) both;
8120
+ }
8121
+
8122
+ .cpk-launcher-hud[data-cpk-hud-intro="true"][data-cpk-hud-side="right"] {
8123
+ animation-name: cpk-launcher-hud-intro-right;
8124
+ }
8125
+
8126
+ .cpk-launcher-hud[data-cpk-hud-intro="true"]
8127
+ .cpk-launcher-hud__row {
8128
+ animation: cpk-launcher-hud-row-online
8129
+ var(--cpk-launcher-hud-row-duration)
8130
+ cubic-bezier(0.16, 1, 0.3, 1) both;
8131
+ animation-delay: var(--cpk-hud-row-delay);
8132
+ }
8133
+
8134
+ .cpk-launcher-hud[data-cpk-hud-intro="true"]
8135
+ .cpk-launcher-hud__check {
8136
+ animation: cpk-launcher-hud-check-online 220ms
8137
+ cubic-bezier(0.16, 1, 0.3, 1) both;
8138
+ animation-delay: calc(var(--cpk-hud-row-delay) + 90ms);
7477
8139
  }
7478
8140
 
7479
8141
  @media (prefers-reduced-motion: reduce) {
7480
- .cpk-launcher-hud,
7481
- .cpk-launcher-hud__detail {
7482
- transition: none;
8142
+ .cpk-launcher-hud[data-cpk-hud-intro="true"],
8143
+ .cpk-launcher-hud[data-cpk-hud-intro="true"]
8144
+ .cpk-launcher-hud__row,
8145
+ .cpk-launcher-hud[data-cpk-hud-intro="true"]
8146
+ .cpk-launcher-hud__check {
8147
+ animation: none !important;
8148
+ opacity: 1;
8149
+ transform: none;
7483
8150
  }
7484
8151
  }
7485
8152
 
@@ -7509,7 +8176,7 @@ ${argsString}</pre
7509
8176
  /* ── Inspector window ────────────────────────────────────────── */
7510
8177
  .inspector-window {
7511
8178
  border: 1px solid #d8d8e8 !important;
7512
- border-radius: 5px !important;
8179
+ border-radius: var(--cpk-inspector-shell-radius) !important;
7513
8180
  box-shadow: none !important;
7514
8181
  }
7515
8182
 
@@ -7625,10 +8292,69 @@ ${argsString}</pre
7625
8292
  .inspector-sidebar[data-icon-rail="true"] .inspector-nav-control,
7626
8293
  .inspector-sidebar[data-icon-rail="true"] .inspector-sidebar-control,
7627
8294
  .inspector-sidebar[data-icon-rail="true"] .inspector-sidebar-toggle {
8295
+ box-sizing: border-box !important;
8296
+ width: 36px !important;
8297
+ height: 36px !important;
8298
+ min-width: 36px !important;
8299
+ min-height: 36px !important;
8300
+ justify-content: center !important;
8301
+ align-items: center !important;
8302
+ gap: 0 !important;
8303
+ padding: 0 !important;
8304
+ overflow: visible !important;
8305
+ }
8306
+ .inspector-sidebar[data-icon-rail="true"] .inspector-nav-icon,
8307
+ .inspector-sidebar[data-icon-rail="true"] .inspector-nav-icon svg,
8308
+ .inspector-sidebar[data-icon-rail="true"]
8309
+ .inspector-context-dropdown-icon,
8310
+ .inspector-sidebar[data-icon-rail="true"]
8311
+ .inspector-context-dropdown-icon
8312
+ svg,
8313
+ .inspector-sidebar[data-icon-rail="true"] .inspector-agent-placeholder svg {
8314
+ width: 18px !important;
8315
+ height: 18px !important;
8316
+ overflow: visible !important;
8317
+ }
8318
+ .inspector-sidebar[data-icon-rail="true"]
8319
+ .inspector-agent-selector
8320
+ > [data-context-dropdown-root="true"] {
8321
+ display: flex !important;
8322
+ flex: none !important;
8323
+ width: 36px !important;
8324
+ min-width: 36px !important;
8325
+ max-width: 36px !important;
7628
8326
  justify-content: center !important;
7629
8327
  align-items: center !important;
8328
+ }
8329
+ .inspector-sidebar[data-icon-rail="true"]
8330
+ .inspector-agent-selector
8331
+ > [data-context-dropdown-root="true"]
8332
+ > button,
8333
+ .inspector-sidebar[data-icon-rail="true"] .inspector-agent-placeholder {
8334
+ display: flex !important;
8335
+ width: 36px !important;
8336
+ height: 36px !important;
8337
+ min-width: 36px !important;
8338
+ min-height: 36px !important;
8339
+ max-width: 36px !important;
8340
+ align-items: center !important;
8341
+ justify-content: center !important;
7630
8342
  gap: 0 !important;
7631
- padding-inline: 0 !important;
8343
+ padding: 0 !important;
8344
+ transition:
8345
+ background-color 180ms ease,
8346
+ border-color 180ms ease,
8347
+ color 180ms ease !important;
8348
+ }
8349
+ .inspector-sidebar[data-icon-rail="true"]
8350
+ .inspector-context-dropdown-label,
8351
+ .inspector-sidebar[data-icon-rail="true"]
8352
+ .inspector-context-dropdown-chevron {
8353
+ display: none !important;
8354
+ width: 0 !important;
8355
+ min-width: 0 !important;
8356
+ flex: none !important;
8357
+ overflow: hidden !important;
7632
8358
  }
7633
8359
  .inspector-sidebar[data-icon-rail="true"] .inspector-nav-label,
7634
8360
  .inspector-sidebar[data-icon-rail="true"] .inspector-sidebar-label {
@@ -7858,6 +8584,7 @@ ${argsString}</pre
7858
8584
  clearTimeout(this.transitionTimeoutId);
7859
8585
  this.transitionTimeoutId = null;
7860
8586
  }
8587
+ this.clearIconRailContextCloseTimer();
7861
8588
  this.unsubscribeFromInspectorThreadBridge();
7862
8589
  this.threadsSetupPromptCopyGeneration += 1;
7863
8590
  if (this.threadsSetupPromptCopyResetTimeoutId !== null) {
@@ -7867,6 +8594,7 @@ ${argsString}</pre
7867
8594
  this.threadsSetupPromptCopyState = "idle";
7868
8595
  this.stopSignalPulse();
7869
8596
  this.cancelGestureTail();
8597
+ this.cancelLauncherHudIntro();
7870
8598
  this.cancelThreadRefreshDebounce();
7871
8599
  this.clearInspectorUsageRefresh();
7872
8600
  this.cleanupThreadsExampleOverviewVideo();
@@ -7903,6 +8631,7 @@ ${argsString}</pre
7903
8631
  else this.centerContext("window");
7904
8632
  this.ensureAnnouncementLoading();
7905
8633
  this.updateHostTransform(this.isOpen ? "window" : "button");
8634
+ this.scheduleLauncherHudIntro();
7906
8635
  }
7907
8636
  render() {
7908
8637
  return this.isOpen ? html`
@@ -7962,18 +8691,9 @@ ${argsString}</pre
7962
8691
  "justify-center",
7963
8692
  "rounded-full",
7964
8693
  "border",
7965
- "border-white/20",
7966
- "bg-slate-950/95",
7967
8694
  "text-xs",
7968
8695
  "font-medium",
7969
8696
  "text-white",
7970
- "ring-1",
7971
- "ring-white/10",
7972
- "backdrop-blur-md",
7973
- "transition",
7974
- "hover:border-white/30",
7975
- "hover:bg-slate-900/95",
7976
- "hover:scale-105",
7977
8697
  "focus-visible:outline",
7978
8698
  "focus-visible:outline-2",
7979
8699
  "focus-visible:outline-offset-2",
@@ -8093,6 +8813,41 @@ ${argsString}</pre
8093
8813
  isLauncherHudBlocked() {
8094
8814
  return this.gestureSignal !== null;
8095
8815
  }
8816
+ scheduleLauncherHudIntro(delay = LAUNCHER_HUD_INTRO_MS.delay) {
8817
+ if (this.launcherHudIntroStartTimer !== null) clearTimeout(this.launcherHudIntroStartTimer);
8818
+ this.launcherHudIntroStartTimer = setTimeout(() => {
8819
+ this.launcherHudIntroStartTimer = null;
8820
+ if (!this.isConnected || this.isOpen) return;
8821
+ if (this.isLauncherHudBlocked()) {
8822
+ this.scheduleLauncherHudIntro(LAUNCHER_HUD_INTRO_MS.blockedRetry);
8823
+ return;
8824
+ }
8825
+ this.resolveLauncherHudSide();
8826
+ this.launcherHudIntro = true;
8827
+ this.launcherHudOpen = true;
8828
+ this.requestUpdate();
8829
+ this.launcherHudIntroEndTimer = setTimeout(() => {
8830
+ this.launcherHudIntroEndTimer = null;
8831
+ this.launcherHudIntro = false;
8832
+ this.launcherHudOpen = false;
8833
+ this.launcherHudHelp = null;
8834
+ this.requestUpdate();
8835
+ }, LAUNCHER_HUD_INTRO_MS.duration);
8836
+ }, delay);
8837
+ }
8838
+ cancelLauncherHudIntro() {
8839
+ if (this.launcherHudIntroStartTimer !== null) {
8840
+ clearTimeout(this.launcherHudIntroStartTimer);
8841
+ this.launcherHudIntroStartTimer = null;
8842
+ }
8843
+ if (this.launcherHudIntroEndTimer !== null) {
8844
+ clearTimeout(this.launcherHudIntroEndTimer);
8845
+ this.launcherHudIntroEndTimer = null;
8846
+ }
8847
+ if (!this.launcherHudIntro) return;
8848
+ this.launcherHudIntro = false;
8849
+ if (this.isConnected) this.requestUpdate();
8850
+ }
8096
8851
  resolveLauncherHudSide() {
8097
8852
  if (typeof window === "undefined") {
8098
8853
  this.launcherHudSide = "left";
@@ -8121,6 +8876,7 @@ ${argsString}</pre
8121
8876
  this.requestUpdate();
8122
8877
  }
8123
8878
  closeLauncherHud() {
8879
+ this.cancelLauncherHudIntro();
8124
8880
  if (this.launcherHudCloseTimer !== null) {
8125
8881
  clearTimeout(this.launcherHudCloseTimer);
8126
8882
  this.launcherHudCloseTimer = null;
@@ -8158,6 +8914,10 @@ ${argsString}</pre
8158
8914
  class="cpk-launcher-hud__row"
8159
8915
  data-cpk-hud-row=${args.id}
8160
8916
  data-cpk-hud-help=${helpOpen ? "open" : nothing}
8917
+ style=${styleMap({
8918
+ "--cpk-hud-row-index": `${args.introIndex}`,
8919
+ "--cpk-hud-row-delay": `${LAUNCHER_HUD_INTRO_MS.rowStart + args.introIndex * LAUNCHER_HUD_INTRO_MS.rowStagger}ms`
8920
+ })}
8161
8921
  @click=${(event) => this.handleHudRowClick(event, args.id)}
8162
8922
  >
8163
8923
  <button
@@ -8187,23 +8947,31 @@ ${argsString}</pre
8187
8947
  }
8188
8948
  renderLauncherHud() {
8189
8949
  if (!this.launcherHudOpen) return nothing;
8190
- const threadsOn = this.areThreadEndpointsAvailable();
8191
- const intelligenceOn = Boolean(this._core?.intelligence);
8192
- const learningOn = intelligenceOn && this._memoriesAvailable;
8950
+ const homeModel = this.getHomeModel();
8951
+ const threadsOn = homeModel.services.some((service) => service.id === "threads" && service.enabled);
8952
+ const learningOn = homeModel.services.some((service) => service.id === "memory" && service.enabled);
8953
+ const intelligenceOn = homeModel.hero.connection === "connected";
8193
8954
  return html`
8194
8955
  <div
8195
8956
  class="cpk-launcher-hud"
8196
8957
  id="cpk-launcher-hud"
8197
8958
  data-cpk-launcher-hud
8198
8959
  data-cpk-hud-side=${this.launcherHudSide}
8960
+ data-cpk-hud-intro=${this.launcherHudIntro ? "true" : nothing}
8961
+ data-color-scheme=${this.colorScheme}
8962
+ style=${styleMap({
8963
+ "--cpk-launcher-hud-intro-duration": `${LAUNCHER_HUD_INTRO_MS.duration}ms`,
8964
+ "--cpk-launcher-hud-row-duration": `${LAUNCHER_HUD_INTRO_MS.rowDuration}ms`
8965
+ })}
8199
8966
  >
8967
+ <span class="cpk-launcher-hud__arrow" aria-hidden="true"></span>
8200
8968
  <div class="cpk-launcher-hud__card">
8201
- <span class="cpk-launcher-hud__arrow" aria-hidden="true"></span>
8202
8969
  <ul class="cpk-launcher-hud__list" role="list">
8203
8970
  ${this.renderHudRow({
8204
8971
  id: "inspector",
8205
8972
  label: HUD_OPEN_INSPECTOR_LABEL,
8206
- detail: HUD_OPEN_INSPECTOR_DETAIL
8973
+ detail: HUD_OPEN_INSPECTOR_DETAIL,
8974
+ introIndex: 0
8207
8975
  })}
8208
8976
  </ul>
8209
8977
  <ul class="cpk-launcher-hud__list" role="list">
@@ -8211,19 +8979,22 @@ ${argsString}</pre
8211
8979
  id: "threads",
8212
8980
  label: threadsOn ? HUD_THREADS_ON_LABEL : HUD_THREADS_OFF_LABEL,
8213
8981
  detail: threadsOn ? HUD_THREADS_ON_DETAIL : HUD_THREADS_OFF_DETAIL,
8214
- connected: threadsOn
8982
+ connected: threadsOn,
8983
+ introIndex: 1
8215
8984
  })}
8216
8985
  ${this.renderHudRow({
8217
8986
  id: "intelligence",
8218
8987
  label: intelligenceOn ? HUD_INTELLIGENCE_ON_LABEL : HUD_INTELLIGENCE_OFF_LABEL,
8219
8988
  detail: intelligenceOn ? HUD_INTELLIGENCE_ON_DETAIL : HUD_INTELLIGENCE_OFF_DETAIL,
8220
- connected: intelligenceOn
8989
+ connected: intelligenceOn,
8990
+ introIndex: 2
8221
8991
  })}
8222
8992
  ${this.renderHudRow({
8223
8993
  id: "learning",
8224
8994
  label: learningOn ? HUD_LEARNING_ON_LABEL : HUD_LEARNING_OFF_LABEL,
8225
8995
  detail: learningOn ? HUD_LEARNING_ON_DETAIL : HUD_LEARNING_OFF_DETAIL,
8226
- connected: learningOn
8996
+ connected: learningOn,
8997
+ introIndex: 3
8227
8998
  })}
8228
8999
  </ul>
8229
9000
  </div>
@@ -8326,34 +9097,34 @@ ${argsString}</pre
8326
9097
  })}
8327
9098
  </nav>
8328
9099
  ${automaticallyCollapsed ? nothing : html`
8329
- <button
8330
- type="button"
8331
- class="inspector-sidebar-toggle"
8332
- data-inspector-sidebar-toggle
8333
- aria-label=${iconRail ? "Expand sidebar" : "Collapse sidebar"}
8334
- aria-expanded=${iconRail ? "false" : "true"}
8335
- data-inspector-tooltip=${iconRail ? "Expand sidebar" : nothing}
8336
- title=${iconRail ? nothing : "Collapse sidebar"}
8337
- style=${INTERACTIVE_FOCUS_BASE_STYLE}
8338
- @pointerenter=${iconRail ? this.handleSidebarRailTooltipShow : nothing}
8339
- @pointerleave=${iconRail ? this.handleSidebarRailTooltipHide : nothing}
8340
- @focus=${iconRail ? this.handleSidebarRailTooltipShow : nothing}
8341
- @blur=${iconRail ? this.handleSidebarRailTooltipHide : nothing}
8342
- @click=${this.handleSidebarToggle}
8343
- >
8344
- <span class="inspector-nav-icon" aria-hidden="true">
8345
- ${this.renderIcon(iconRail ? "ChevronRight" : "ChevronLeft")}
8346
- </span>
8347
- <span class="inspector-nav-label"
8348
- >${iconRail ? "Expand" : "Collapse"}</span
8349
- >
8350
- </button>
8351
- `}
8352
- ${iconRail ? nothing : html`
8353
9100
  <div class="inspector-sidebar-footer">
8354
- <div class="inspector-sidebar-status-list">
8355
- ${this.renderSidebarIntelligenceStatus(homeModel)}
8356
- </div>
9101
+ ${iconRail ? nothing : html`
9102
+ <div class="inspector-sidebar-status-list">
9103
+ ${this.renderSidebarIntelligenceStatus(homeModel)}
9104
+ </div>
9105
+ `}
9106
+ <button
9107
+ type="button"
9108
+ class="inspector-sidebar-toggle"
9109
+ data-inspector-sidebar-toggle
9110
+ aria-label=${iconRail ? "Expand sidebar" : "Collapse sidebar"}
9111
+ aria-expanded=${iconRail ? "false" : "true"}
9112
+ data-inspector-tooltip=${iconRail ? "Expand sidebar" : nothing}
9113
+ title=${iconRail ? nothing : "Collapse sidebar"}
9114
+ style=${INTERACTIVE_FOCUS_BASE_STYLE}
9115
+ @pointerenter=${iconRail ? this.handleSidebarRailTooltipShow : nothing}
9116
+ @pointerleave=${iconRail ? this.handleSidebarRailTooltipHide : nothing}
9117
+ @focus=${iconRail ? this.handleSidebarRailTooltipShow : nothing}
9118
+ @blur=${iconRail ? this.handleSidebarRailTooltipHide : nothing}
9119
+ @click=${this.handleSidebarToggle}
9120
+ >
9121
+ <span class="inspector-nav-icon" aria-hidden="true">
9122
+ ${this.renderIcon(iconRail ? "ChevronRight" : "ChevronLeft")}
9123
+ </span>
9124
+ <span class="inspector-nav-label"
9125
+ >${iconRail ? "Expand" : "Collapse"}</span
9126
+ >
9127
+ </button>
8357
9128
  </div>
8358
9129
  `}
8359
9130
  </aside>
@@ -9116,16 +9887,6 @@ ${argsString}</pre
9116
9887
  @pointerup=${this.handleResizePointerUp}
9117
9888
  @pointercancel=${this.handleResizePointerCancel}
9118
9889
  ></div>
9119
- <div
9120
- class="resize-handle pointer-events-auto absolute bottom-0 left-0 flex h-7 w-7 cursor-nesw-resize items-center justify-center text-gray-600 transition hover:text-gray-900"
9121
- data-resize-edge="sw"
9122
- role="presentation"
9123
- aria-hidden="true"
9124
- @pointerdown=${this.handleResizePointerDown}
9125
- @pointermove=${this.handleResizePointerMove}
9126
- @pointerup=${this.handleResizePointerUp}
9127
- @pointercancel=${this.handleResizePointerCancel}
9128
- ></div>
9129
9890
  `}
9130
9891
  <div
9131
9892
  class="resize-handle pointer-events-auto absolute bottom-0 right-0 flex h-7 w-7 cursor-nwse-resize items-center justify-center text-gray-600 transition hover:text-gray-900"
@@ -9533,8 +10294,7 @@ ${argsString}</pre
9533
10294
  this.draggedDuringInteraction = false;
9534
10295
  }
9535
10296
  openInspector(source, options = {}) {
9536
- if (options.snippetId || options.menu === "event-snippets") this.focusEventSnippets(options);
9537
- else if (options.threadId) this.focusThread(options);
10297
+ if (options.threadId) this.focusThread(options);
9538
10298
  if (this.isPoppedOut) return;
9539
10299
  if (this.isOpen) return;
9540
10300
  const hadUnseenAnnouncement = this.newsSignalArmed;
@@ -9718,11 +10478,8 @@ ${argsString}</pre
9718
10478
  return this.sanitizeForLogging(payload);
9719
10479
  }
9720
10480
  normalizeMessageContent(content) {
9721
- if (typeof content === "string") return content;
9722
- if (content && typeof content === "object" && "text" in content) {
9723
- const maybeText = content.text;
9724
- if (typeof maybeText === "string") return maybeText;
9725
- }
10481
+ const extracted = textFromUnknownContent(content);
10482
+ if (extracted) return extracted;
9726
10483
  if (content === null || content === void 0) return "";
9727
10484
  if (typeof content === "object") try {
9728
10485
  return JSON.stringify(this.sanitizeForLogging(content));
@@ -9942,7 +10699,7 @@ ${argsString}</pre
9942
10699
  const sendDisabled = !agentId || this.playgroundIsLoadingThread || !this.playgroundIsRunning && !this.playgroundInput.trim();
9943
10700
  return html`
9944
10701
  <form
9945
- class=${centered ? "mt-5 w-full" : "bg-white px-3 pb-3 pt-1.5"}
10702
+ class=${centered ? "cpk-playground-form mt-5 w-full" : "cpk-playground-form bg-white px-3 pb-3 pt-1.5"}
9946
10703
  @submit=${this.handlePlaygroundSubmit}
9947
10704
  >
9948
10705
  ${this.playgroundError ? html`<div
@@ -9971,10 +10728,10 @@ ${argsString}</pre
9971
10728
  ` : nothing}
9972
10729
  </div>` : nothing}
9973
10730
  <div
9974
- class="mx-auto flex max-w-3xl items-end gap-1.5 rounded-[28px] bg-white px-2.5 py-1.5 shadow-[0_4px_4px_0_#0000000a,0_0_1px_0_#0000009e] transition-shadow duration-200 focus-within:shadow-[0_6px_18px_0_#00000014,0_0_1px_0_#0000009e]"
10731
+ class="cpk-playground-composer mx-auto flex max-w-3xl items-end gap-1.5 rounded-[28px] bg-white px-2.5 py-1.5 shadow-[0_4px_4px_0_#0000000a,0_0_1px_0_#0000009e] transition-shadow duration-200 focus-within:shadow-[0_6px_18px_0_#00000014,0_0_1px_0_#0000009e]"
9975
10732
  >
9976
10733
  <textarea
9977
- class="min-h-[40px] max-h-32 flex-1 resize-none bg-transparent px-2.5 py-2.5 text-[13px] leading-5 text-gray-900 outline-none placeholder:text-gray-500 disabled:cursor-not-allowed disabled:opacity-60"
10734
+ class="cpk-playground-input min-h-[40px] max-h-32 flex-1 resize-none bg-transparent px-2.5 py-2.5 text-[13px] leading-5 text-gray-900 outline-none placeholder:text-gray-500 disabled:cursor-not-allowed disabled:opacity-60"
9978
10735
  rows="1"
9979
10736
  placeholder=${placeholder}
9980
10737
  aria-label="Playground message"
@@ -9985,7 +10742,7 @@ ${argsString}</pre
9985
10742
  ></textarea>
9986
10743
  <button
9987
10744
  type=${this.playgroundIsRunning ? "button" : "submit"}
9988
- class=${`mb-0.5 flex h-9 w-9 shrink-0 items-center justify-center rounded-full transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-400 focus-visible:ring-offset-2 [&>svg]:h-[18px] [&>svg]:w-[18px] ${sendDisabled ? "cursor-not-allowed bg-[#00000014] text-[rgb(13,13,13)] opacity-50" : "cursor-pointer bg-black text-white hover:opacity-70 active:opacity-60"}`}
10745
+ class=${`cpk-playground-send mb-0.5 flex h-9 w-9 shrink-0 items-center justify-center rounded-full transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-400 focus-visible:ring-offset-2 [&>svg]:h-[18px] [&>svg]:w-[18px] ${sendDisabled ? "cursor-not-allowed bg-[#00000014] text-[rgb(13,13,13)] opacity-50" : "cursor-pointer bg-black text-white hover:opacity-70 active:opacity-60"}`}
9989
10746
  aria-label=${this.playgroundIsRunning ? "Stop agent" : "Send playground message"}
9990
10747
  ?disabled=${sendDisabled}
9991
10748
  @click=${this.playgroundIsRunning ? this.handlePlaygroundStop : nothing}
@@ -9999,549 +10756,6 @@ ${argsString}</pre
9999
10756
  AI can make mistakes. Please verify important information.
10000
10757
  </p>
10001
10758
  </form>
10002
- `;
10003
- }
10004
- reloadEventSnippets() {
10005
- this.eventSnippets = loadEventSnippets();
10006
- }
10007
- renderSnippetImportControl() {
10008
- return html`
10009
- <label
10010
- class="inline-flex shrink-0 cursor-pointer items-center rounded-md border border-gray-300 bg-white px-3 py-1.5 text-[11px] text-gray-700"
10011
- data-testid="cpk-snippet-import"
10012
- >
10013
- Import
10014
- <input
10015
- type="file"
10016
- accept="application/json"
10017
- class="hidden"
10018
- @change=${this.handleSnippetImportChange}
10019
- />
10020
- </label>
10021
- `;
10022
- }
10023
- selectEventSnippet(id) {
10024
- const snippet = this.eventSnippets.find((item) => item.id === id);
10025
- this.selectedSnippetId = id;
10026
- if (!snippet) {
10027
- this.requestUpdate();
10028
- return;
10029
- }
10030
- const editor = editorStateFromSnippet(snippet);
10031
- this.snippetRecipe = editor.recipe;
10032
- this.snippetName = editor.name;
10033
- this.snippetJson = editor.json;
10034
- this.snippetToolName = editor.draft.toolName;
10035
- this.snippetToolArgs = editor.draft.toolArgs;
10036
- this.snippetReasoningText = editor.draft.reasoningText;
10037
- this.snippetTextContent = editor.draft.textContent;
10038
- this.snippetActivityType = editor.draft.activityType;
10039
- this.snippetActivityContent = editor.draft.activityContent;
10040
- this.snippetError = null;
10041
- this.requestUpdate();
10042
- }
10043
- compileSnippetDraft() {
10044
- switch (this.snippetRecipe) {
10045
- case "tool-call": return compileToolCallRecipe({
10046
- toolName: this.snippetToolName,
10047
- argsJson: this.snippetToolArgs,
10048
- threadId: this.getSnippetThreadId(),
10049
- runId: this.getSnippetRunId()
10050
- });
10051
- case "reasoning": return compileReasoningRecipe({
10052
- text: this.snippetReasoningText,
10053
- threadId: this.getSnippetThreadId(),
10054
- runId: this.getSnippetRunId()
10055
- });
10056
- case "text": return compileTextRecipe({
10057
- text: this.snippetTextContent,
10058
- threadId: this.getSnippetThreadId(),
10059
- runId: this.getSnippetRunId()
10060
- });
10061
- case "activity": return compileActivityRecipe({
10062
- activityType: this.snippetActivityType,
10063
- contentJson: this.snippetActivityContent,
10064
- threadId: this.getSnippetThreadId(),
10065
- runId: this.getSnippetRunId()
10066
- });
10067
- case "raw": return parseSnippetEvents(this.snippetJson);
10068
- }
10069
- }
10070
- getSnippetThreadId() {
10071
- return this.selectedThreadId ?? "inspector-snippet";
10072
- }
10073
- getSnippetRunId() {
10074
- return `inspector-snippet-${Date.now()}`;
10075
- }
10076
- getSnippetTargetAgent() {
10077
- const core = this._core;
10078
- if (!core) return null;
10079
- const selected = this.selectedContext !== "all-agents" ? this.selectedContext : null;
10080
- if (selected) return core.getAgent(selected) ?? null;
10081
- const first = this.contextOptions.find((option) => option.key !== "all-agents");
10082
- return first ? core.getAgent(first.key) ?? null : null;
10083
- }
10084
- applyRecipeToEditor() {
10085
- try {
10086
- const events = this.compileSnippetDraft();
10087
- this.snippetJson = JSON.stringify(events, null, 2);
10088
- this.snippetError = null;
10089
- } catch (error) {
10090
- this.snippetError = error instanceof Error ? error.message : "Could not compile recipe.";
10091
- }
10092
- this.requestUpdate();
10093
- }
10094
- handleSnippetRecipeChange(event) {
10095
- const value = event.target.value;
10096
- if (value === "tool-call" || value === "reasoning" || value === "text" || value === "activity" || value === "raw") {
10097
- this.snippetRecipe = value;
10098
- if (value !== "raw") this.applyRecipeToEditor();
10099
- else this.requestUpdate();
10100
- }
10101
- }
10102
- saveCurrentSnippet(source) {
10103
- try {
10104
- const events = parseSnippetEvents(this.snippetJson);
10105
- const now = (/* @__PURE__ */ new Date()).toISOString();
10106
- const snippet = {
10107
- id: this.selectedSnippetId ?? createSnippetId(),
10108
- name: this.snippetName.trim() || recipeLabel(this.snippetRecipe),
10109
- recipe: this.snippetRecipe,
10110
- events,
10111
- createdAt: this.eventSnippets.find((item) => item.id === this.selectedSnippetId)?.createdAt ?? now,
10112
- updatedAt: now
10113
- };
10114
- this.eventSnippets = upsertEventSnippet(snippet);
10115
- this.selectedSnippetId = snippet.id;
10116
- this.snippetBanner = "Snippet saved.";
10117
- this.snippetError = null;
10118
- if (!this.core?.telemetryDisabled) trackEventSnippetsSaved({
10119
- recipe: this.snippetRecipe,
10120
- source,
10121
- success: true
10122
- });
10123
- } catch (error) {
10124
- this.snippetError = error instanceof Error ? error.message : "Could not save snippet.";
10125
- if (!this.core?.telemetryDisabled) trackEventSnippetsSaved({
10126
- recipe: this.snippetRecipe,
10127
- source,
10128
- success: false
10129
- });
10130
- }
10131
- this.requestUpdate();
10132
- }
10133
- async runCurrentSnippet() {
10134
- this.snippetError = null;
10135
- this.snippetBanner = null;
10136
- let events;
10137
- try {
10138
- events = expandSnippetEventsForRun(parseSnippetEvents(this.snippetJson));
10139
- } catch (error) {
10140
- this.snippetError = error instanceof Error ? error.message : "Snippet JSON is invalid.";
10141
- this.requestUpdate();
10142
- return;
10143
- }
10144
- if (snippetContainsToolCall(events) && !this.snippetConfirmOpen) {
10145
- this.snippetConfirmOpen = true;
10146
- this.requestUpdate();
10147
- return;
10148
- }
10149
- this.snippetConfirmOpen = false;
10150
- const core = this._core;
10151
- const agent = this.getSnippetTargetAgent();
10152
- if (!core || !agent) {
10153
- this.snippetError = "No agent is available to inject into.";
10154
- this.requestUpdate();
10155
- return;
10156
- }
10157
- if (agent.isRunning) {
10158
- this.snippetError = "The agent is running. Wait for the current run to end.";
10159
- this.requestUpdate();
10160
- return;
10161
- }
10162
- try {
10163
- const result = await ɵinjectInspectorEvents({
10164
- core,
10165
- agent,
10166
- events
10167
- });
10168
- this.lastInject = {
10169
- snippetId: this.selectedSnippetId ?? "unsaved",
10170
- agentId: agent.agentId ?? "default",
10171
- runId: this.getSnippetRunId(),
10172
- messageIds: result.messageIds
10173
- };
10174
- this.snippetBanner = "Inspector injected these events into the live thread.";
10175
- if (!this.core?.telemetryDisabled) trackEventSnippetsRun({
10176
- recipe: this.snippetRecipe,
10177
- source: "pane",
10178
- success: true
10179
- });
10180
- } catch (error) {
10181
- this.snippetError = error instanceof Error ? error.message : "Could not run snippet.";
10182
- if (!this.core?.telemetryDisabled) trackEventSnippetsRun({
10183
- recipe: this.snippetRecipe,
10184
- source: "pane",
10185
- success: false
10186
- });
10187
- }
10188
- this.requestUpdate();
10189
- }
10190
- resetLastSnippetRun() {
10191
- const last = this.lastInject;
10192
- const core = this._core;
10193
- if (!last || !core) return;
10194
- const agent = core.getAgent(last.agentId);
10195
- if (!agent) {
10196
- this.snippetError = "The injected agent is no longer available.";
10197
- this.requestUpdate();
10198
- return;
10199
- }
10200
- ɵresetInspectorInject({
10201
- agent,
10202
- messageIds: last.messageIds
10203
- });
10204
- this.lastInject = null;
10205
- this.snippetBanner = "Last inject was removed from the thread. App state from a tool handler was not undone.";
10206
- this.requestUpdate();
10207
- }
10208
- renderEventSnippetsView() {
10209
- if (this.eventSnippets.length === 0 && this.selectedSnippetId === null) this.reloadEventSnippets();
10210
- const agent = this.getSnippetTargetAgent();
10211
- const runBlocked = agent?.isRunning === true;
10212
- const canRunJson = snippetJsonIsRunnable(this.snippetJson);
10213
- const canRun = canRunJson && !!agent && !runBlocked;
10214
- const canSave = canRunJson;
10215
- const canDelete = this.selectedSnippetId !== null;
10216
- const canExport = this.eventSnippets.length > 0;
10217
- const canReset = this.lastInject !== null;
10218
- const snippetGroups = groupEventSnippets(this.eventSnippets);
10219
- const tools = this._core?.tools ?? [];
10220
- return html`
10221
- <div class="flex h-full min-h-0 flex-col bg-white">
10222
- <div
10223
- class="flex items-center justify-between gap-4 border-b border-gray-200 px-4 py-3"
10224
- >
10225
- <div class="min-w-0">
10226
- <h2 class="text-sm font-semibold text-gray-900">Event Snippets</h2>
10227
- <p class="mt-1 text-[11px] text-gray-500">
10228
- Compile AG-UI events, run them on the live agent, and save them
10229
- for later. Tool-call runs use the real frontend-tool handler.
10230
- </p>
10231
- </div>
10232
- ${this.renderSnippetImportControl()}
10233
- </div>
10234
- ${this.snippetBanner ? html`<div
10235
- class="border-b border-emerald-200 bg-emerald-50 px-4 py-2 text-[11px] text-emerald-800"
10236
- role="status"
10237
- >
10238
- ${this.snippetBanner}
10239
- </div>` : nothing}
10240
- ${this.snippetError ? html`<div
10241
- class="border-b border-rose-200 bg-rose-50 px-4 py-2 text-[11px] text-rose-800"
10242
- role="alert"
10243
- >
10244
- ${this.snippetError}
10245
- </div>` : nothing}
10246
- ${this.snippetConfirmOpen ? html`<div
10247
- class="border-b border-amber-200 bg-amber-50 px-4 py-2 text-[11px] text-amber-900"
10248
- role="alertdialog"
10249
- aria-label="Confirm tool-call run"
10250
- >
10251
- <p>
10252
- This snippet contains a tool call. Run will execute the real
10253
- handler on the live thread.
10254
- </p>
10255
- <div class="mt-2 flex gap-2">
10256
- <button
10257
- type="button"
10258
- class="rounded-md bg-gray-900 px-2 py-1 text-[11px] text-white"
10259
- data-testid="cpk-snippet-run-handler"
10260
- @click=${() => {
10261
- this.snippetConfirmOpen = true;
10262
- this.runCurrentSnippet();
10263
- }}
10264
- >
10265
- Run handler
10266
- </button>
10267
- <button
10268
- type="button"
10269
- class="rounded-md border border-gray-300 bg-white px-2 py-1 text-[11px]"
10270
- @click=${() => {
10271
- this.snippetConfirmOpen = false;
10272
- this.requestUpdate();
10273
- }}
10274
- >
10275
- Cancel
10276
- </button>
10277
- </div>
10278
- </div>` : nothing}
10279
- <div class="flex min-h-0 flex-1">
10280
- <div
10281
- class="inspector-snippet-sidebar shrink-0"
10282
- style="width:${this.snippetListWidth}px"
10283
- data-testid="cpk-snippet-list"
10284
- >
10285
- ${snippetGroups.length === 0 ? html`
10286
- <p class="px-2 py-2 text-[11px] text-gray-500">No saved snippets yet.</p>
10287
- ` : html`
10288
- <nav class="inspector-sidebar-nav" aria-label="Saved snippets">
10289
- ${snippetGroups.map((group) => html`
10290
- <div class="inspector-sidebar-section">
10291
- <div
10292
- class="inspector-sidebar-label"
10293
- data-testid="cpk-snippet-category"
10294
- data-recipe=${group.recipe}
10295
- >
10296
- ${group.label}
10297
- </div>
10298
- ${group.snippets.map((snippet) => {
10299
- const isSelected = snippet.id === this.selectedSnippetId;
10300
- return html`
10301
- <button
10302
- type="button"
10303
- class="inspector-nav-control inspector-sidebar-control ${isSelected ? "inspector-nav-control-active" : ""}"
10304
- data-testid="cpk-snippet-item"
10305
- data-recipe=${snippet.recipe}
10306
- aria-current=${isSelected ? "page" : nothing}
10307
- aria-label="${recipeLabel(snippet.recipe)}: ${snippet.name}"
10308
- style=${INTERACTIVE_FOCUS_BASE_STYLE}
10309
- @click=${() => this.selectEventSnippet(snippet.id)}
10310
- >
10311
- <span
10312
- class="inspector-nav-icon"
10313
- aria-hidden="true"
10314
- >
10315
- <span
10316
- class="flex h-6 w-6 items-center justify-center rounded-md ${recipeIconWrapClass(snippet.recipe)}"
10317
- >
10318
- ${this.renderIcon(recipeIconName(snippet.recipe))}
10319
- </span>
10320
- </span>
10321
- <span class="inspector-nav-label"
10322
- >${snippet.name}</span
10323
- >
10324
- </button>
10325
- `;
10326
- })}
10327
- </div>
10328
- `)}
10329
- </nav>
10330
- `}
10331
- </div>
10332
- <div
10333
- class="w-1.5 shrink-0 cursor-col-resize bg-gray-200 hover:bg-gray-400"
10334
- role="separator"
10335
- aria-orientation="vertical"
10336
- aria-label="Resize snippet list"
10337
- title="Drag to resize"
10338
- data-testid="cpk-snippet-list-resize"
10339
- style="touch-action:none"
10340
- @pointerdown=${this.handleSnippetListDividerPointerDown}
10341
- @pointermove=${this.handleSnippetListDividerPointerMove}
10342
- @pointerup=${this.handleSnippetListDividerPointerUp}
10343
- @pointercancel=${this.handleSnippetListDividerPointerUp}
10344
- ></div>
10345
- <div class="flex min-h-0 min-w-0 flex-1 flex-col gap-2 overflow-auto p-4">
10346
- <label class="text-[11px] text-gray-600">
10347
- Name
10348
- <input
10349
- class="mt-1 w-full rounded-md border border-gray-200 px-2 py-1 text-[11px]"
10350
- data-testid="cpk-snippet-name"
10351
- .value=${this.snippetName}
10352
- @input=${(event) => {
10353
- this.snippetName = event.target.value;
10354
- }}
10355
- />
10356
- </label>
10357
- <label class="text-[11px] text-gray-600">
10358
- Recipe
10359
- <select
10360
- class="mt-1 w-full rounded-md border border-gray-200 px-2 py-1 text-[11px]"
10361
- data-testid="cpk-snippet-recipe"
10362
- .value=${this.snippetRecipe}
10363
- @change=${this.handleSnippetRecipeChange}
10364
- >
10365
- ${[
10366
- "tool-call",
10367
- "reasoning",
10368
- "text",
10369
- "activity",
10370
- "raw"
10371
- ].map((recipe) => html`<option
10372
- value=${recipe}
10373
- ?selected=${recipe === this.snippetRecipe}
10374
- >
10375
- ${recipeLabel(recipe)}
10376
- </option>`)}
10377
- </select>
10378
- </label>
10379
- ${this.snippetRecipe === "tool-call" ? html`
10380
- <label class="text-[11px] text-gray-600">
10381
- Tool
10382
- <input
10383
- list="cpk-snippet-tools"
10384
- class="mt-1 w-full rounded-md border border-gray-200 px-2 py-1 text-[11px]"
10385
- data-testid="cpk-snippet-tool-name"
10386
- .value=${this.snippetToolName}
10387
- @input=${(event) => {
10388
- this.snippetToolName = event.target.value;
10389
- this.applyRecipeToEditor();
10390
- }}
10391
- />
10392
- <datalist id="cpk-snippet-tools">
10393
- ${tools.map((tool) => html`<option value=${tool.name}></option>`)}
10394
- </datalist>
10395
- </label>
10396
- <label class="text-[11px] text-gray-600">
10397
- Args JSON
10398
- <textarea
10399
- class="mt-1 h-20 w-full rounded-md border border-gray-200 px-2 py-1 font-mono text-[11px]"
10400
- data-testid="cpk-snippet-tool-args"
10401
- .value=${this.snippetToolArgs}
10402
- @input=${(event) => {
10403
- this.snippetToolArgs = event.target.value;
10404
- this.applyRecipeToEditor();
10405
- }}
10406
- ></textarea>
10407
- </label>
10408
- ` : nothing}
10409
- ${this.snippetRecipe === "reasoning" ? html`<label class="text-[11px] text-gray-600">
10410
- Reasoning
10411
- <textarea
10412
- class="mt-1 h-20 w-full rounded-md border border-gray-200 px-2 py-1 text-[11px]"
10413
- data-testid="cpk-snippet-reasoning"
10414
- .value=${this.snippetReasoningText}
10415
- @input=${(event) => {
10416
- this.snippetReasoningText = event.target.value;
10417
- this.applyRecipeToEditor();
10418
- }}
10419
- ></textarea>
10420
- </label>` : nothing}
10421
- ${this.snippetRecipe === "text" ? html`<label class="text-[11px] text-gray-600">
10422
- Assistant text
10423
- <textarea
10424
- class="mt-1 h-20 w-full rounded-md border border-gray-200 px-2 py-1 text-[11px]"
10425
- data-testid="cpk-snippet-text"
10426
- .value=${this.snippetTextContent}
10427
- @input=${(event) => {
10428
- this.snippetTextContent = event.target.value;
10429
- this.applyRecipeToEditor();
10430
- }}
10431
- ></textarea>
10432
- </label>` : nothing}
10433
- ${this.snippetRecipe === "activity" ? html`
10434
- <label class="text-[11px] text-gray-600">
10435
- Activity type
10436
- <input
10437
- list="cpk-snippet-activity"
10438
- class="mt-1 w-full rounded-md border border-gray-200 px-2 py-1 text-[11px]"
10439
- data-testid="cpk-snippet-activity-type"
10440
- .value=${this.snippetActivityType}
10441
- @input=${(event) => {
10442
- this.snippetActivityType = event.target.value;
10443
- this.applyRecipeToEditor();
10444
- }}
10445
- />
10446
- <datalist id="cpk-snippet-activity">
10447
- ${ACTIVITY_STARTERS.map((type) => html`<option value=${type}></option>`)}
10448
- </datalist>
10449
- </label>
10450
- <label class="text-[11px] text-gray-600">
10451
- Content JSON
10452
- <textarea
10453
- class="mt-1 h-24 w-full rounded-md border border-gray-200 px-2 py-1 font-mono text-[11px]"
10454
- data-testid="cpk-snippet-activity-content"
10455
- .value=${this.snippetActivityContent}
10456
- @input=${(event) => {
10457
- this.snippetActivityContent = event.target.value;
10458
- this.applyRecipeToEditor();
10459
- }}
10460
- ></textarea>
10461
- </label>
10462
- ` : nothing}
10463
- <label class="text-[11px] text-gray-600">
10464
- Events JSON
10465
- <textarea
10466
- class="mt-1 h-40 w-full rounded-md border border-gray-200 px-2 py-1 font-mono text-[11px]"
10467
- data-testid="cpk-snippet-json"
10468
- .value=${this.snippetJson}
10469
- @input=${(event) => {
10470
- this.snippetJson = event.target.value;
10471
- this.requestUpdate();
10472
- }}
10473
- ></textarea>
10474
- </label>
10475
- <div class="flex flex-wrap gap-2">
10476
- <button
10477
- type="button"
10478
- class="rounded-md bg-gray-900 px-3 py-1.5 text-[11px] text-white disabled:opacity-50"
10479
- data-testid="cpk-snippet-run"
10480
- ?disabled=${!canRun}
10481
- title=${runBlocked ? "The agent is running. Wait for the current run to end." : !agent ? "No agent is available to inject into." : !canRunJson ? "Events JSON must be a non-empty event array." : "Run snippet"}
10482
- @click=${() => void this.runCurrentSnippet()}
10483
- >
10484
- ${runBlocked ? "Agent running" : "Run"}
10485
- </button>
10486
- <button
10487
- type="button"
10488
- class="rounded-md border border-gray-300 bg-white px-3 py-1.5 text-[11px] disabled:opacity-50"
10489
- data-testid="cpk-snippet-save"
10490
- ?disabled=${!canSave}
10491
- title=${canSave ? "Save snippet" : "Events JSON must be a non-empty event array."}
10492
- @click=${() => this.saveCurrentSnippet("pane")}
10493
- >
10494
- Save
10495
- </button>
10496
- <button
10497
- type="button"
10498
- class="rounded-md border border-gray-300 bg-white px-3 py-1.5 text-[11px] disabled:opacity-50"
10499
- data-testid="cpk-snippet-reset"
10500
- ?disabled=${!canReset}
10501
- title=${canReset ? "Remove the last inject from the thread" : "No Inspector inject to reset."}
10502
- @click=${() => this.resetLastSnippetRun()}
10503
- >
10504
- Reset last run
10505
- </button>
10506
- <button
10507
- type="button"
10508
- class="rounded-md border border-gray-300 bg-white px-3 py-1.5 text-[11px] disabled:opacity-50"
10509
- data-testid="cpk-snippet-delete"
10510
- ?disabled=${!canDelete}
10511
- title=${canDelete ? "Delete this snippet" : "Select a snippet to delete."}
10512
- @click=${() => {
10513
- if (!this.selectedSnippetId) return;
10514
- if (!window.confirm("Delete this snippet?")) return;
10515
- this.eventSnippets = deleteEventSnippet(this.selectedSnippetId);
10516
- this.selectedSnippetId = null;
10517
- this.requestUpdate();
10518
- }}
10519
- >
10520
- Delete
10521
- </button>
10522
- <button
10523
- type="button"
10524
- class="rounded-md border border-gray-300 bg-white px-3 py-1.5 text-[11px] disabled:opacity-50"
10525
- data-testid="cpk-snippet-export"
10526
- ?disabled=${!canExport}
10527
- title=${canExport ? "Export snippets" : "Save a snippet before you export."}
10528
- @click=${() => {
10529
- if (!canExport) return;
10530
- const blob = new Blob([exportEventSnippetsJson(this.eventSnippets)], { type: "application/json" });
10531
- const url = URL.createObjectURL(blob);
10532
- const link = document.createElement("a");
10533
- link.href = url;
10534
- link.download = "event-snippets.json";
10535
- link.click();
10536
- URL.revokeObjectURL(url);
10537
- }}
10538
- >
10539
- Export
10540
- </button>
10541
- </div>
10542
- </div>
10543
- </div>
10544
- </div>
10545
10759
  `;
10546
10760
  }
10547
10761
  renderMainContent() {
@@ -10557,7 +10771,6 @@ ${argsString}</pre
10557
10771
  </div>
10558
10772
  `;
10559
10773
  if (this.selectedMenu === "playground") return this.renderPlaygroundView();
10560
- if (this.selectedMenu === "event-snippets") return this.renderEventSnippetsView();
10561
10774
  if (this.selectedMenu === "agents") return this.renderAgentsView();
10562
10775
  if (this.selectedMenu === "frontend-tools") return this.renderToolsView();
10563
10776
  if (this.selectedMenu === "capabilities") return this.renderCapabilitiesView();
@@ -10689,9 +10902,9 @@ ${argsString}</pre
10689
10902
  </div>
10690
10903
  ` : visibleMessages.length === 0 ? html`
10691
10904
  <div
10692
- class="mx-auto flex h-full w-full max-w-3xl flex-col items-center justify-center text-center"
10905
+ class="cpk-playground-welcome mx-auto flex h-full w-full flex-col items-center justify-center text-center"
10693
10906
  >
10694
- <p class="text-base font-medium tracking-tight text-gray-900">
10907
+ <p class="cpk-playground-welcome-title">
10695
10908
  How can I help you today?
10696
10909
  </p>
10697
10910
  ${this.renderPlaygroundComposer(agentId, busy, hasRetry, true)}
@@ -12066,6 +12279,7 @@ ${argsString}</pre
12066
12279
  .focusRequestId=${this.threadFocusRequestId}
12067
12280
  .agentStateInput=${this.getLatestStateForAgent(selectedThread.agentId)}
12068
12281
  .agentEventsInput=${this.agentEvents.get(selectedThread.agentId) ?? []}
12282
+ .agentMessagesInput=${selectedThreadIsLocalExample ? EMPTY_INSPECTOR_MESSAGES : this.getLiveAgentMessagesForThread(selectedThread)}
12069
12283
  ></cpk-thread-details>
12070
12284
  ${selectedThreadIsLocalExample ? this.renderThreadsExampleTour() : nothing}` : showingExamples ? this.renderThreadsExampleOverview(locked) : html`
12071
12285
  <div
@@ -12306,11 +12520,7 @@ ${argsString}</pre
12306
12520
  >
12307
12521
  ${isExpanded ? html`
12308
12522
  <div class="group relative">
12309
- <pre
12310
- class="m-0 whitespace-pre-wrap break-words text-[10px] font-mono text-gray-600"
12311
- >
12312
- ${prettyEvent}</pre
12313
- >
12523
+ ${renderHighlightedJsonBlock(extractedEvent)}
12314
12524
  <button
12315
12525
  class="absolute right-0 top-0 cursor-pointer rounded px-2 py-1 text-[10px] opacity-0 transition group-hover:opacity-100 ${this.copiedEvents.has(event.id) ? "bg-green-100 text-green-700" : "bg-gray-100 text-gray-600 hover:bg-gray-200 hover:text-gray-900"}"
12316
12526
  @click=${(e) => {
@@ -12532,7 +12742,7 @@ ${prettyEvent}</pre
12532
12742
  <div class="overflow-auto">
12533
12743
  ${messages && messages.length > 0 ? html`
12534
12744
  <div class="w-full text-xs">
12535
- <div class="flex bg-gray-50">
12745
+ <div class="cpk-agent-messages-head flex bg-gray-50">
12536
12746
  <div
12537
12747
  class="w-40 shrink-0 px-4 py-2 font-medium text-gray-700"
12538
12748
  >
@@ -12542,7 +12752,7 @@ ${prettyEvent}</pre
12542
12752
  Content
12543
12753
  </div>
12544
12754
  </div>
12545
- <div class="divide-y divide-gray-200">
12755
+ <div class="cpk-agent-messages-rows">
12546
12756
  ${messages.map((msg) => {
12547
12757
  const role = msg.role || "unknown";
12548
12758
  const roleColors = {
@@ -12560,7 +12770,7 @@ ${prettyEvent}</pre
12560
12770
  const isFailedResult = role === "tool" && toolError?.toolCallId !== void 0 && toolError.toolCallId === msg.toolCallId;
12561
12771
  return html`
12562
12772
  <div
12563
- class=${isFailedResult ? "flex items-start bg-rose-50" : "flex items-start"}
12773
+ class=${isFailedResult ? "cpk-agent-message-row flex items-start bg-rose-50" : "cpk-agent-message-row flex items-start"}
12564
12774
  data-cpk-failed-tool-result=${isFailedResult ? msg.toolCallId : nothing}
12565
12775
  >
12566
12776
  <div class="w-40 shrink-0 px-4 py-2">
@@ -12642,10 +12852,12 @@ ${prettyEvent}</pre
12642
12852
  >${this.renderIcon("ChevronDown")}</span
12643
12853
  >
12644
12854
  </button>
12645
- ${this.contextMenuOpen ? html`
12855
+ ${iconRail || this.contextMenuOpen ? html`
12646
12856
  <div
12647
- class="absolute left-0 z-50 mt-1.5 w-40 rounded-md border border-gray-200 bg-white py-1 shadow-md ring-1 ring-black/5"
12857
+ class="absolute left-0 z-50 mt-1.5 w-40 rounded-md border border-gray-200 bg-white py-1 shadow-md ring-1 ring-black/5${iconRail ? " inspector-icon-rail-menu" : ""}"
12648
12858
  data-context-dropdown-root="true"
12859
+ data-open=${this.contextMenuOpen ? "true" : "false"}
12860
+ aria-hidden=${this.contextMenuOpen ? "false" : "true"}
12649
12861
  >
12650
12862
  ${filteredOptions.map((option) => html`
12651
12863
  <button
@@ -12764,7 +12976,6 @@ ${prettyEvent}</pre
12764
12976
  if (previousMenu !== "memories" && !this.core?.telemetryDisabled) trackMemoriesTabClicked(this.getMemoriesTelemetryProps());
12765
12977
  }
12766
12978
  if (key === "home" && previousMenu !== "home") this.homeViewedThisOpen = false;
12767
- if (key === "event-snippets") this.reloadEventSnippets();
12768
12979
  if (key === "ag-ui-events" || key === "agents") {
12769
12980
  if (!(this.pendingScrollToEventId !== null || this.pendingScrollToToolCallId !== null)) requestAnimationFrame(() => {
12770
12981
  const scroller = this.activeRoot.querySelector("#cpk-main-scroll");
@@ -12783,8 +12994,14 @@ ${prettyEvent}</pre
12783
12994
  this.contextMenuOpen = !this.contextMenuOpen;
12784
12995
  this.requestUpdate();
12785
12996
  }
12997
+ clearIconRailContextCloseTimer() {
12998
+ if (this.iconRailContextCloseTimer === null) return;
12999
+ clearTimeout(this.iconRailContextCloseTimer);
13000
+ this.iconRailContextCloseTimer = null;
13001
+ }
12786
13002
  handleContextOptionSelect(key) {
12787
13003
  if (!this.contextOptions.some((option) => option.key === key)) return;
13004
+ this.clearIconRailContextCloseTimer();
12788
13005
  if (this.selectedContext !== key) {
12789
13006
  this.selectedContext = key;
12790
13007
  this.expandedRows.clear();
@@ -13279,23 +13496,25 @@ ${prettyEvent}</pre
13279
13496
  </button>
13280
13497
 
13281
13498
  ${isExpanded ? html`
13282
- <div class="border-t border-gray-200 bg-gray-50/50 px-4 py-3">
13499
+ <div class="border-t border-gray-200 px-4 py-3">
13283
13500
  <div class="mb-3">
13284
- <h5 class="mb-1 text-xs font-semibold text-gray-700">ID</h5>
13285
- <code
13286
- class="font-mono text-xs font-medium text-gray-800 flex-1 truncate min-w-0"
13287
- >${id}</code
13288
- >
13289
- <button
13290
- type="button"
13291
- class="cpk-copy-btn"
13292
- @click=${(e) => {
13501
+ <div class="mb-1 flex items-center justify-between gap-2">
13502
+ <h5 class="text-xs font-semibold text-gray-700">ID</h5>
13503
+ <button
13504
+ type="button"
13505
+ class="cpk-copy-btn"
13506
+ @click=${(e) => {
13293
13507
  e.stopPropagation();
13294
13508
  this.copyContextValue(id, `${id}:id`, e);
13295
13509
  }}
13510
+ >
13511
+ ${this.copiedContextItems.has(`${id}:id`) ? "Copied" : "Copy"}
13512
+ </button>
13513
+ </div>
13514
+ <code
13515
+ class="block min-w-0 truncate font-mono text-xs font-medium text-gray-800"
13516
+ >${id}</code
13296
13517
  >
13297
- ${this.copiedContextItems.has(`${id}:id`) ? "✓" : "Copy"}
13298
- </button>
13299
13518
  </div>
13300
13519
  ${hasValue ? html`
13301
13520
  <div class="mb-2 flex items-center justify-between gap-2">
@@ -14022,8 +14241,18 @@ function defineWebInspector(registry = globalThis.customElements) {
14022
14241
  defineElementOnce(registry, "cpk-memory-list", CpkMemoryList);
14023
14242
  defineElementOnce(registry, WEB_INSPECTOR_TAG, WebInspectorElement);
14024
14243
  }
14244
+ /**
14245
+ * Bind a host-owned core before an Inspector is connected to the DOM. Disabling
14246
+ * auto-attachment first prevents `connectedCallback` from briefly selecting a
14247
+ * different global core.
14248
+ */
14249
+ function configureWebInspectorElement(inspector, core) {
14250
+ inspector.autoAttachCore = false;
14251
+ inspector.core = core;
14252
+ return inspector;
14253
+ }
14025
14254
  defineWebInspector();
14026
14255
 
14027
14256
  //#endregion
14028
- export { CpkThreadInspector, THREAD_INSPECTOR_TAG, WEB_INSPECTOR_TAG, WebInspectorElement, compileChatSnippet, compileFromActivityMessage, defineWebInspector, upsertEventSnippet, ɵCpkThreadDetails, buildCapabilityRows as ɵbuildCapabilityRows, maxRecallScore as ɵmaxRecallScore, normalizeRelevance as ɵnormalizeRelevance, relevanceBarWidth as ɵrelevanceBarWidth };
14257
+ export { CpkThreadInspector, THREAD_INSPECTOR_TAG, WEB_INSPECTOR_TAG, WebInspectorElement, configureWebInspectorElement, defineWebInspector, ɵCpkThreadDetails, buildCapabilityRows as ɵbuildCapabilityRows, maxRecallScore as ɵmaxRecallScore, normalizeRelevance as ɵnormalizeRelevance, relevanceBarWidth as ɵrelevanceBarWidth };
14029
14258
  //# sourceMappingURL=index.mjs.map