@copilotkit/web-inspector 1.69.2 → 1.70.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -10,6 +10,7 @@ const require_home_briefing = require('./lib/home-briefing.cjs');
10
10
  const require_inspector_nav = require('./lib/inspector-nav.cjs');
11
11
  const require_thread_selection = require('./lib/thread-selection.cjs');
12
12
  const require_telemetry = require('./lib/telemetry.cjs');
13
+ const require_onboarding_prompt = require('./lib/onboarding-prompt.cjs');
13
14
  let lit = require("lit");
14
15
  let marked = require("marked");
15
16
  let lit_directives_style_map_js = require("lit/directives/style-map.js");
@@ -243,6 +244,21 @@ const LAUNCHER_BASE_LABEL = "Web Inspector";
243
244
  const EDGE_MARGIN = 16;
244
245
  /** HUD card plus the hover bridge. Used to pick left vs right. */
245
246
  const LAUNCHER_HUD_WIDTH = 248;
247
+ /**
248
+ * One page-load preview of the launcher's feature HUD.
249
+ *
250
+ * The card arrives after the host page has had a beat to settle. Its four rows
251
+ * then come online in order, stay readable, and leave together. Nothing is
252
+ * persisted: a new Inspector element means a new preview.
253
+ */
254
+ const LAUNCHER_HUD_INTRO_MS = {
255
+ delay: 500,
256
+ duration: 3400,
257
+ rowStart: 180,
258
+ rowStagger: 170,
259
+ rowDuration: 300,
260
+ blockedRetry: 250
261
+ };
246
262
  const DRAG_THRESHOLD = 6;
247
263
  const MIN_WINDOW_WIDTH = 880;
248
264
  const MIN_WINDOW_WIDTH_DOCKED_LEFT = 640;
@@ -282,6 +298,108 @@ const THREADS_RUNTIME_SETUP_PROMPT = [
282
298
  "Start the app and verify GET {basePath}/info reports threadEndpoints.list, inspect, mutations, and realtimeMetadata as true. Run focused tests, lint, and typecheck. Report the files changed, commands run, and verification result. If blocked, explain the missing input; do not invent setup."
283
299
  ].join("\n");
284
300
  const SELF_HOSTED_INTELLIGENCE_URL = "https://docs.copilotkit.ai/premium/self-hosting";
301
+ const INTELLIGENCE_STORY_BEATS = [
302
+ {
303
+ id: "threads",
304
+ label: "Threads",
305
+ duration: 6500,
306
+ lead: "You only see this session. Your users have all the others.",
307
+ support: "Rich Threads keep every conversation and its state, so you can open the one that broke instead of reproducing it."
308
+ },
309
+ {
310
+ id: "learning",
311
+ label: "Learning",
312
+ duration: 6e3,
313
+ lead: "Your users already told you what to fix.",
314
+ support: "Learning reads the runs behind those threads and finds the patterns — every Insight linked to the messages that back it."
315
+ },
316
+ {
317
+ id: "skill",
318
+ label: "Skills",
319
+ duration: 5500,
320
+ lead: "An Insight becomes a skill you own.",
321
+ support: "A SKILL.md built from that evidence — yours to review, edit and ship with your project."
322
+ },
323
+ {
324
+ id: "intelligence",
325
+ label: "Intelligence",
326
+ duration: 6e3,
327
+ lead: "Every round of real use leaves your agent better.",
328
+ support: "Approve a skill, pull it into your project, and the next run starts from what already worked."
329
+ }
330
+ ];
331
+ /**
332
+ * The threads the first beat shows.
333
+ *
334
+ * One of them failed, because that is the row a developer actually wants and
335
+ * the reason durable threads are worth paying for. It is a user's thread that
336
+ * went wrong, not a demo of our agent failing — the distinction matters for a
337
+ * card that has to argue for the product.
338
+ */
339
+ const INTELLIGENCE_STORY_THREADS = [
340
+ {
341
+ title: "Reschedule the Tuesday sync",
342
+ meta: "2 min ago",
343
+ failed: false
344
+ },
345
+ {
346
+ title: "Book time with the design team",
347
+ meta: "18 min ago",
348
+ failed: false
349
+ },
350
+ {
351
+ title: "Booked the wrong slot",
352
+ meta: "Needs a look",
353
+ failed: true
354
+ }
355
+ ];
356
+ /** The three rules the story derives, shown verbatim across all three beats. */
357
+ const INTELLIGENCE_STORY_RULES = [
358
+ "Check both calendars.",
359
+ "Propose several times.",
360
+ "Ask before booking."
361
+ ];
362
+ /**
363
+ * The raw thread signals the first beat collapses into those rules.
364
+ *
365
+ * Kept at real-message length and varied on purpose — these have to read as
366
+ * things people actually typed, not as three tidy bullet points. The longest
367
+ * one truncates in a narrow panel, which is honest: it is an excerpt.
368
+ */
369
+ const INTELLIGENCE_STORY_SIGNALS = [
370
+ "Check our calendars and find a time for both of us.",
371
+ "Could you share a few options?",
372
+ "Ask me before you book it."
373
+ ];
374
+ const INTELLIGENCE_STORY_SKILL_FILE = "meeting-scheduling/SKILL.md";
375
+ /**
376
+ * How long the copied confirmation stands before the button invites a second
377
+ * press. Longer than the 2s the Threads setup prompt uses, because this state
378
+ * also carries an instruction that has to be read, not just an acknowledgement.
379
+ */
380
+ const PROMPT_COPY_RESET_MS = 4e3;
381
+ const INTELLIGENCE_STORY_CHAIN = [
382
+ {
383
+ icon: "MessagesSquare",
384
+ name: "Threads",
385
+ detail: "Every conversation"
386
+ },
387
+ {
388
+ icon: "Lightbulb",
389
+ name: "Insights",
390
+ detail: "Backed by evidence"
391
+ },
392
+ {
393
+ icon: "FileText",
394
+ name: "Skills",
395
+ detail: "You approve"
396
+ },
397
+ {
398
+ icon: "Wand2",
399
+ name: "Your agent",
400
+ detail: "Starts from what worked"
401
+ }
402
+ ];
285
403
  const THREADS_EXAMPLE_OVERVIEW_VIDEO_URL = "https://cdn.copilotkit.ai/corp-site/videos/copilotkit-generative-ui-agentic-frontend-demo.webm";
286
404
  const THREADS_EXAMPLE_OVERVIEW_VIDEO_FALLBACK = "The demo video is unavailable. Use the example threads to explore Messages, AG-UI Events, and State.";
287
405
  const THREADS_EXAMPLE_TOUR_STORAGE_KEY = "cpk:inspector:threads-example-tour:v1";
@@ -348,6 +466,29 @@ const AGENT_EVENT_TYPES = [
348
466
  "ACTIVITY_SNAPSHOT",
349
467
  "ACTIVITY_DELTA"
350
468
  ];
469
+ const EMPTY_INSPECTOR_MESSAGES = [];
470
+ function textFromUnknownContent(content) {
471
+ if (typeof content === "string") return content;
472
+ if (Array.isArray(content)) {
473
+ const parts = [];
474
+ for (const part of content) {
475
+ if (typeof part === "string") {
476
+ parts.push(part);
477
+ continue;
478
+ }
479
+ if (typeof part === "object" && part !== null && "text" in part) {
480
+ const text = part.text;
481
+ if (typeof text === "string") parts.push(text);
482
+ }
483
+ }
484
+ return parts.join("");
485
+ }
486
+ if (typeof content === "object" && content !== null && "text" in content) {
487
+ const text = content.text;
488
+ if (typeof text === "string") return text;
489
+ }
490
+ return "";
491
+ }
351
492
  /**
352
493
  * Map core.tools (the registry INCLUDING disabled tools) into Capabilities-tab
353
494
  * frontend-tool rows. Pure: no DOM, no `this`. Reads current on/off state from
@@ -606,13 +747,6 @@ function highlightedJson(obj) {
606
747
  const cached = highlightedJsonCache.get(obj);
607
748
  if (cached !== void 0) return cached;
608
749
  }
609
- const colors = {
610
- key: "#5558B2",
611
- str: "#087653",
612
- num: "#8a5900",
613
- bool: "#c0333a",
614
- nil: "#68686e"
615
- };
616
750
  const json = JSON.stringify(obj, null, 2);
617
751
  if (!json) return "";
618
752
  const parts = [];
@@ -622,11 +756,11 @@ function highlightedJson(obj) {
622
756
  while ((match = re.exec(json)) !== null) {
623
757
  parts.push(escapeHtml(json.slice(lastIndex, match.index)));
624
758
  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>`);
759
+ let token = "num";
760
+ if (m.startsWith("\"")) token = m.trimEnd().endsWith(":") ? "key" : "str";
761
+ else if (m === "true" || m === "false") token = "bool";
762
+ else if (m === "null") token = "nil";
763
+ parts.push(`<span class="cpk-json-token cpk-json-token--${token}">${escapeHtml(m)}</span>`);
630
764
  lastIndex = match.index + m.length;
631
765
  }
632
766
  parts.push(escapeHtml(json.slice(lastIndex)));
@@ -651,31 +785,23 @@ function renderHighlightedJsonBlock(value, options = {}) {
651
785
  ${(0, lit_directives_unsafe_html_js.unsafeHTML)(highlightedJson(parsed))}</pre
652
786
  >`;
653
787
  }
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
- };
788
+ function humanizeEventType(type) {
789
+ const words = type.trim().split(/[_\s]+/).filter(Boolean).map((word) => word.toLowerCase());
790
+ if (words.length === 0) return "Event";
791
+ const [first = "event", ...rest] = words;
792
+ return [`${first.charAt(0).toUpperCase()}${first.slice(1)}`, ...rest].join(" ");
793
+ }
794
+ function messageTitle(role) {
795
+ const normalized = role.trim() || "message";
796
+ return `${`${normalized.charAt(0).toUpperCase()}${normalized.slice(1).toLowerCase()}`} message`;
797
+ }
798
+ function eventCategory(type) {
799
+ if (type === "RUN_ERROR" || type === "ERROR") return "error";
800
+ if (type.startsWith("TEXT_MESSAGE")) return "message";
801
+ if (type.startsWith("TOOL_CALL")) return "tool";
802
+ if (type.startsWith("STATE") || type.startsWith("MESSAGES")) return "state";
803
+ if (type.startsWith("RUN_") || type.startsWith("STEP_")) return "run";
804
+ return "event";
679
805
  }
680
806
  function formatTimestamp(ts) {
681
807
  const date = typeof ts === "number" ? new Date(ts) : new Date(ts);
@@ -1077,11 +1203,15 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1077
1203
  this.threadInspectionAvailable = false;
1078
1204
  this.agentStateInput = null;
1079
1205
  this.agentEventsInput = [];
1206
+ this.agentMessagesInput = EMPTY_INSPECTOR_MESSAGES;
1080
1207
  this.liveMessageVersion = 0;
1081
1208
  this.viewInAppMode = "hidden";
1082
1209
  this.viewInAppError = null;
1083
1210
  this.focusMessageId = null;
1084
1211
  this.focusRequestId = 0;
1212
+ this.tryFromHereAvailable = false;
1213
+ this.tryFromHereBusy = false;
1214
+ this.tryFromHereError = null;
1085
1215
  this._tab = "timeline";
1086
1216
  this._fetchedMetadata = null;
1087
1217
  this._conversation = [];
@@ -1141,6 +1271,15 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1141
1271
  if (target.hasPointerCapture(this._dividerPointerId)) target.releasePointerCapture(this._dividerPointerId);
1142
1272
  this._dividerResizing = false;
1143
1273
  };
1274
+ this.onTryFromHere = (event) => {
1275
+ event.preventDefault();
1276
+ if (!this.tryFromHereAvailable || this.tryFromHereBusy) return;
1277
+ this.dispatchEvent(new CustomEvent("tryFromHere", {
1278
+ detail: this.threadId,
1279
+ bubbles: true,
1280
+ composed: true
1281
+ }));
1282
+ };
1144
1283
  }
1145
1284
  static {
1146
1285
  this.properties = {
@@ -1152,11 +1291,15 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1152
1291
  threadInspectionAvailable: { attribute: false },
1153
1292
  agentStateInput: { attribute: false },
1154
1293
  agentEventsInput: { attribute: false },
1294
+ agentMessagesInput: { attribute: false },
1155
1295
  liveMessageVersion: { attribute: false },
1156
1296
  viewInAppMode: { attribute: false },
1157
1297
  viewInAppError: { attribute: false },
1158
1298
  focusMessageId: { attribute: false },
1159
1299
  focusRequestId: { attribute: false },
1300
+ tryFromHereAvailable: { attribute: false },
1301
+ tryFromHereBusy: { attribute: false },
1302
+ tryFromHereError: { attribute: false },
1160
1303
  _tab: { state: true },
1161
1304
  _fetchedMetadata: { state: true },
1162
1305
  _conversation: { state: true },
@@ -1233,7 +1376,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1233
1376
  return JSON.stringify(Object.entries(headers).sort(([leftKey], [rightKey]) => leftKey.localeCompare(rightKey)));
1234
1377
  }
1235
1378
  renderTabContent(id) {
1236
- if (id === "timeline") return this.renderTimeline();
1379
+ if (id === "timeline") return this.withMessagesToolbar(this.renderTimeline());
1237
1380
  if (id === "state") return this.renderState();
1238
1381
  return this.renderEvents();
1239
1382
  }
@@ -1296,6 +1439,11 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1296
1439
  display: flex;
1297
1440
  flex-direction: row;
1298
1441
  overflow: hidden;
1442
+ --cpk-json-key: #3d408f;
1443
+ --cpk-json-str: #0b6b4c;
1444
+ --cpk-json-num: #8a5900;
1445
+ --cpk-json-bool: #c0333a;
1446
+ --cpk-json-nil: #57575b;
1299
1447
  }
1300
1448
 
1301
1449
  .cpk-td {
@@ -1420,11 +1568,25 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1420
1568
  flex-shrink: 0;
1421
1569
  }
1422
1570
 
1423
- .cpk-td__metadata-strip {
1571
+ .cpk-td__chrome-actions {
1572
+ margin-inline-start: auto;
1424
1573
  display: flex;
1574
+ flex-wrap: wrap;
1425
1575
  align-items: center;
1576
+ justify-content: flex-end;
1426
1577
  gap: 6px;
1427
- flex-wrap: wrap;
1578
+ padding-inline: 8px;
1579
+ min-width: 0;
1580
+ }
1581
+
1582
+ .cpk-td__chrome-actions + .cpk-td__panel-toggle {
1583
+ margin-inline-start: 0;
1584
+ }
1585
+
1586
+ .cpk-td__metadata-strip {
1587
+ display: flex;
1588
+ flex-direction: column;
1589
+ gap: 8px;
1428
1590
  padding: 10px 16px;
1429
1591
  border-bottom: 1px solid #e9e9ef;
1430
1592
  background: #fbfbfd;
@@ -1433,19 +1595,22 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1433
1595
 
1434
1596
  .cpk-td__metadata-pills {
1435
1597
  display: flex;
1598
+ align-items: center;
1436
1599
  gap: 6px;
1437
- flex: 1;
1438
- flex-wrap: wrap;
1600
+ width: 100%;
1439
1601
  min-width: 0;
1602
+ flex-wrap: nowrap;
1440
1603
  }
1441
1604
 
1442
1605
  .cpk-td__metadata-pill {
1443
1606
  display: inline-flex;
1444
1607
  align-items: center;
1445
- gap: 5px;
1446
- max-width: 220px;
1447
- padding: 3px 7px;
1448
- border: 1px solid #e9e9ef;
1608
+ gap: 6px;
1609
+ flex: 1 1 0;
1610
+ min-width: 0;
1611
+ height: 24px;
1612
+ padding: 0 8px;
1613
+ border: 1px solid #dbdbe5;
1449
1614
  border-radius: 6px;
1450
1615
  background: #ffffff;
1451
1616
  color: #57575b;
@@ -1461,20 +1626,17 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1461
1626
  }
1462
1627
 
1463
1628
  .cpk-td__metadata-value {
1629
+ min-width: 0;
1464
1630
  overflow: hidden;
1465
1631
  text-overflow: ellipsis;
1632
+ white-space: nowrap;
1466
1633
  }
1467
1634
 
1635
+ .cpk-td__metadata-value--wrap,
1468
1636
  .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;
1637
+ overflow: hidden;
1638
+ text-overflow: ellipsis;
1639
+ white-space: nowrap;
1478
1640
  }
1479
1641
 
1480
1642
  .cpk-td__view-in-app {
@@ -1485,11 +1647,18 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1485
1647
  border-radius: 6px;
1486
1648
  background: #5558b2;
1487
1649
  color: #ffffff;
1488
- font-family: "Plus Jakarta Sans", sans-serif;
1489
- font-size: 11px;
1650
+ font-family: "Spline Sans Mono", monospace;
1651
+ font-size: 10px;
1490
1652
  font-weight: 600;
1491
- padding: 5px 10px;
1653
+ line-height: 1.2;
1654
+ min-height: 24px;
1655
+ padding: 3px 8px;
1492
1656
  cursor: pointer;
1657
+ transition:
1658
+ transform 160ms cubic-bezier(0.23, 1, 0.32, 1),
1659
+ background 120ms ease,
1660
+ color 120ms ease,
1661
+ border-color 120ms ease;
1493
1662
  }
1494
1663
 
1495
1664
  .cpk-td__view-in-app:focus-visible {
@@ -1497,6 +1666,10 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1497
1666
  outline-offset: 2px;
1498
1667
  }
1499
1668
 
1669
+ .cpk-td__view-in-app:active {
1670
+ transform: scale(0.96);
1671
+ }
1672
+
1500
1673
  .cpk-td__view-in-app--stop {
1501
1674
  background: #ffffff;
1502
1675
  color: #5558b2;
@@ -1508,6 +1681,65 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1508
1681
  font-size: 11px;
1509
1682
  }
1510
1683
 
1684
+ @media (prefers-reduced-motion: reduce) {
1685
+ .cpk-td__view-in-app {
1686
+ transition: none;
1687
+ }
1688
+
1689
+ .cpk-td__view-in-app:active {
1690
+ transform: none;
1691
+ }
1692
+ }
1693
+
1694
+ .cpk-td__try-from-here {
1695
+ display: inline-flex;
1696
+ align-items: center;
1697
+ gap: 4px;
1698
+ margin-inline-start: auto;
1699
+ padding: 6px 10px;
1700
+ border: 1px solid #dbdbe5;
1701
+ border-radius: 8px;
1702
+ background: #ffffff;
1703
+ color: #36363a;
1704
+ font-family: "Spline Sans Mono", monospace;
1705
+ font-size: 11px;
1706
+ font-weight: 600;
1707
+ line-height: 1.2;
1708
+ cursor: pointer;
1709
+ }
1710
+
1711
+ .cpk-td__try-from-here-icon {
1712
+ display: block;
1713
+ flex-shrink: 0;
1714
+ }
1715
+
1716
+ :host([dir="rtl"]) .cpk-td__try-from-here-icon {
1717
+ scale: -1 1;
1718
+ }
1719
+
1720
+ .cpk-td__try-from-here:hover:not(:disabled) {
1721
+ border-color: rgba(85, 88, 178, 0.38);
1722
+ background: #f7f7ff;
1723
+ color: #010507;
1724
+ }
1725
+
1726
+ .cpk-td__try-from-here:focus-visible {
1727
+ outline: 2px solid #a78bfa;
1728
+ outline-offset: 1px;
1729
+ }
1730
+
1731
+ .cpk-td__try-from-here:disabled {
1732
+ cursor: not-allowed;
1733
+ opacity: 0.55;
1734
+ }
1735
+
1736
+ .cpk-td__try-from-here-error {
1737
+ flex-basis: 100%;
1738
+ color: #c0333a;
1739
+ font-size: 11px;
1740
+ line-height: 1.4;
1741
+ }
1742
+
1511
1743
  /*
1512
1744
  * Each tab's content is wrapped in this panel so the keep-mounted
1513
1745
  * inactive panels can be hidden via display:none without disturbing
@@ -1704,15 +1936,16 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1704
1936
  .cpk-td__tool-pre {
1705
1937
  margin: 0;
1706
1938
  font-family: "Spline Sans Mono", monospace;
1707
- font-size: 10px;
1939
+ font-size: 12px;
1708
1940
  background: #f7f7f9;
1709
- padding: 6px 8px;
1710
- border-radius: 5px;
1941
+ padding: 10px 12px;
1942
+ border-radius: 6px;
1711
1943
  overflow-x: auto;
1712
1944
  white-space: pre-wrap;
1713
- word-break: break-all;
1945
+ overflow-wrap: anywhere;
1946
+ word-break: normal;
1714
1947
  color: #010507;
1715
- line-height: 1.6;
1948
+ line-height: 1.65;
1716
1949
  }
1717
1950
 
1718
1951
  /* ── Tool call group ─────────────────────────────────────────────── */
@@ -1765,12 +1998,31 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1765
1998
 
1766
1999
  /* ── Interaction timeline ───────────────────────────────────────── */
1767
2000
  .cpk-td__timeline-item {
1768
- border: 1px solid #e9e9ef;
1769
- border-radius: 7px;
1770
- background: #ffffff;
2001
+ border: 1px solid transparent;
2002
+ border-radius: 10px;
2003
+ background: transparent;
1771
2004
  overflow: hidden;
1772
2005
  }
1773
2006
 
2007
+ .cpk-td__timeline-item--run,
2008
+ .cpk-td__timeline-item--state,
2009
+ .cpk-td__timeline-item--event,
2010
+ .cpk-td__timeline-item--tool,
2011
+ .cpk-td__event--run,
2012
+ .cpk-td__event--event,
2013
+ .cpk-td__event--state,
2014
+ .cpk-td__event--message,
2015
+ .cpk-td__event--tool {
2016
+ border-color: #dbdbe5;
2017
+ background: #ffffff;
2018
+ }
2019
+
2020
+ .cpk-td__timeline-item--message {
2021
+ border-color: #dbdbe5;
2022
+ background: #ffffff;
2023
+ box-shadow: 0 1px 2px #0105070d;
2024
+ }
2025
+
1774
2026
  .cpk-td__timeline-item--warning {
1775
2027
  border-color: rgba(250, 95, 103, 0.35);
1776
2028
  background: rgba(250, 95, 103, 0.04);
@@ -1780,29 +2032,72 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1780
2032
  display: flex;
1781
2033
  align-items: center;
1782
2034
  gap: 8px;
1783
- padding: 7px 10px;
2035
+ padding: 6px 10px;
2036
+ background: transparent;
2037
+ }
2038
+
2039
+ .cpk-td__timeline-item--message .cpk-td__timeline-header {
2040
+ padding: 10px 12px;
1784
2041
  background: #f7f7f9;
1785
2042
  }
1786
2043
 
2044
+ .cpk-td__timeline-item--user .cpk-td__timeline-header {
2045
+ background: #bec2ff1a;
2046
+ }
2047
+
2048
+ .cpk-td__timeline-item--assistant .cpk-td__timeline-header {
2049
+ background: #85ecce1a;
2050
+ }
2051
+
1787
2052
  .cpk-td__timeline-kind {
2053
+ display: inline-flex;
2054
+ align-items: center;
2055
+ padding: 4px 8px;
2056
+ border-radius: 999px;
2057
+ background: #f0f0f4;
2058
+ color: #57575b;
1788
2059
  font-family: "Spline Sans Mono", monospace;
1789
- font-size: 9px;
2060
+ font-size: 10px;
1790
2061
  font-weight: 600;
2062
+ letter-spacing: 0.04em;
2063
+ line-height: 1.2;
1791
2064
  text-transform: uppercase;
1792
- color: #5558b2;
2065
+ flex-shrink: 0;
2066
+ }
2067
+
2068
+ .cpk-td__timeline-item--message .cpk-td__timeline-kind {
2069
+ background: #bec2ff33;
2070
+ color: #010507;
2071
+ }
2072
+
2073
+ .cpk-td__timeline-item--assistant .cpk-td__timeline-kind {
2074
+ background: #85ecce4d;
2075
+ color: #010507;
2076
+ }
2077
+
2078
+ .cpk-td__timeline-item--warning .cpk-td__timeline-kind {
2079
+ background: rgba(250, 95, 103, 0.16);
2080
+ color: #c0333a;
1793
2081
  }
1794
2082
 
1795
2083
  .cpk-td__timeline-title {
1796
2084
  flex: 1;
1797
2085
  min-width: 0;
2086
+ font-family: "Plus Jakarta Sans", sans-serif;
1798
2087
  font-size: 12px;
1799
2088
  font-weight: 500;
1800
- color: #010507;
2089
+ color: #57575b;
1801
2090
  overflow: hidden;
1802
2091
  text-overflow: ellipsis;
1803
2092
  white-space: nowrap;
1804
2093
  }
1805
2094
 
2095
+ .cpk-td__timeline-item--message .cpk-td__timeline-title {
2096
+ font-size: 13px;
2097
+ font-weight: 600;
2098
+ color: #010507;
2099
+ }
2100
+
1806
2101
  .cpk-td__timeline-time {
1807
2102
  font-family: "Spline Sans Mono", monospace;
1808
2103
  font-size: 9px;
@@ -1813,6 +2108,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1813
2108
  .cpk-td__timeline-body {
1814
2109
  margin: 0;
1815
2110
  padding: 0 10px 9px;
2111
+ font-family: "Plus Jakarta Sans", sans-serif;
1816
2112
  font-size: 12px;
1817
2113
  line-height: 1.55;
1818
2114
  color: #57575b;
@@ -1820,21 +2116,28 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1820
2116
  word-break: break-word;
1821
2117
  }
1822
2118
 
2119
+ .cpk-td__timeline-item--message .cpk-td__timeline-body {
2120
+ padding: 0 12px 12px;
2121
+ font-size: 13px;
2122
+ color: #010507;
2123
+ }
2124
+
1823
2125
  .cpk-td__timeline-toolbar {
1824
2126
  display: flex;
2127
+ flex-wrap: wrap;
2128
+ align-items: center;
1825
2129
  gap: 6px;
1826
- margin-left: auto;
1827
2130
  }
1828
2131
 
1829
2132
  .cpk-td__timeline-bulk-toggle {
1830
2133
  margin: 0;
1831
- padding: 4px 8px;
1832
- border: 1px solid #dcdce8;
1833
- border-radius: 7px;
2134
+ padding: 6px 10px;
2135
+ border: 1px solid #dbdbe5;
2136
+ border-radius: 8px;
1834
2137
  background: #ffffff;
1835
2138
  color: #36363a;
1836
2139
  cursor: pointer;
1837
- font-family: "Inter", sans-serif;
2140
+ font-family: "Spline Sans Mono", monospace;
1838
2141
  font-size: 11px;
1839
2142
  font-weight: 600;
1840
2143
  line-height: 1.2;
@@ -1909,84 +2212,6 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1909
2212
  }
1910
2213
  }
1911
2214
 
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
2215
  .cpk-td__genui {
1991
2216
  display: flex;
1992
2217
  flex-direction: column;
@@ -2028,8 +2253,9 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2028
2253
  /* ── AG-UI Events ────────────────────────────────────────────────── */
2029
2254
  .cpk-td__event {
2030
2255
  flex-shrink: 0;
2031
- border: 1px solid #e9e9ef;
2032
- border-radius: 7px;
2256
+ border: 1px solid #dbdbe5;
2257
+ border-radius: 10px;
2258
+ background: #ffffff;
2033
2259
  overflow: hidden;
2034
2260
  /*
2035
2261
  * content-visibility: auto lets the browser skip layout + paint for
@@ -2045,48 +2271,89 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2045
2271
  contain-intrinsic-size: 0 80px;
2046
2272
  }
2047
2273
 
2274
+ .cpk-td__event--error {
2275
+ border-color: rgba(250, 95, 103, 0.35);
2276
+ background: rgba(250, 95, 103, 0.04);
2277
+ }
2278
+
2048
2279
  .cpk-td__event-header {
2049
2280
  display: flex;
2050
- justify-content: space-between;
2051
2281
  align-items: center;
2052
- padding: 5px 10px;
2282
+ gap: 8px;
2283
+ padding: 6px 10px;
2284
+ background: transparent;
2053
2285
  }
2054
2286
 
2055
2287
  .cpk-td__event-type {
2288
+ display: inline-flex;
2289
+ align-items: center;
2290
+ padding: 4px 8px;
2291
+ border-radius: 999px;
2292
+ background: #f0f0f4;
2293
+ color: #010507;
2056
2294
  font-family: "Spline Sans Mono", monospace;
2057
- font-size: 9px;
2058
- font-weight: 500;
2059
- text-transform: uppercase;
2295
+ font-size: 10px;
2296
+ font-weight: 600;
2297
+ letter-spacing: 0.02em;
2298
+ line-height: 1.2;
2299
+ }
2300
+
2301
+ .cpk-td__event--message .cpk-td__event-type {
2302
+ background: #bec2ff33;
2303
+ }
2304
+
2305
+ .cpk-td__event--tool .cpk-td__event-type {
2306
+ background: #85ecce4d;
2307
+ }
2308
+
2309
+ .cpk-td__event--error .cpk-td__event-type {
2310
+ background: rgba(250, 95, 103, 0.16);
2311
+ color: #c0333a;
2060
2312
  }
2061
2313
 
2062
2314
  .cpk-td__event-time {
2315
+ margin-inline-start: auto;
2063
2316
  font-family: "Spline Sans Mono", monospace;
2064
2317
  font-size: 9px;
2065
2318
  color: #68686e;
2319
+ flex-shrink: 0;
2066
2320
  }
2067
2321
 
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) ────────────────────────────────────── */
2322
+ .cpk-td__event-payload,
2081
2323
  .cpk-td__json-block,
2082
2324
  .cpk-json-block {
2083
2325
  margin: 0;
2326
+ padding: 10px 12px;
2327
+ border-top: 1px solid #dbdbe5;
2328
+ background: #f7f7f9;
2084
2329
  font-family: "Spline Sans Mono", monospace;
2085
- font-size: 11px;
2086
- line-height: 1.8;
2330
+ font-size: 12px;
2331
+ line-height: 1.65;
2087
2332
  white-space: pre-wrap;
2088
- word-break: break-all;
2089
- color: #57575b;
2333
+ overflow-wrap: anywhere;
2334
+ word-break: normal;
2335
+ color: #010507;
2336
+ overflow: auto;
2337
+ }
2338
+
2339
+ .cpk-json-token--key {
2340
+ color: var(--cpk-json-key);
2341
+ }
2342
+
2343
+ .cpk-json-token--str {
2344
+ color: var(--cpk-json-str);
2345
+ }
2346
+
2347
+ .cpk-json-token--num {
2348
+ color: var(--cpk-json-num);
2349
+ }
2350
+
2351
+ .cpk-json-token--bool {
2352
+ color: var(--cpk-json-bool);
2353
+ }
2354
+
2355
+ .cpk-json-token--nil {
2356
+ color: var(--cpk-json-nil);
2090
2357
  }
2091
2358
 
2092
2359
  /* ── Resize divider ──────────────────────────────────────────────── */
@@ -2185,6 +2452,11 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2185
2452
 
2186
2453
  :host([data-color-scheme="dark"]) {
2187
2454
  color-scheme: dark;
2455
+ --cpk-json-key: #bec2ff;
2456
+ --cpk-json-str: #85ecce;
2457
+ --cpk-json-num: #ffac4d;
2458
+ --cpk-json-bool: #fa5f67;
2459
+ --cpk-json-nil: #afafb7;
2188
2460
  }
2189
2461
 
2190
2462
  :host([data-color-scheme="dark"]) .cpk-td {
@@ -2196,6 +2468,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2196
2468
  :host([data-color-scheme="dark"]) .cpk-td__panel-toggle,
2197
2469
  :host([data-color-scheme="dark"]) .cpk-td__metadata-strip,
2198
2470
  :host([data-color-scheme="dark"]) .cpk-td__metadata-pill,
2471
+ :host([data-color-scheme="dark"]) .cpk-td__try-from-here,
2199
2472
  :host([data-color-scheme="dark"]) .cpk-td__tool-block,
2200
2473
  :host([data-color-scheme="dark"]) .cpk-td__tool-header,
2201
2474
  :host([data-color-scheme="dark"]) .cpk-td__tool-body,
@@ -2213,6 +2486,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2213
2486
  }
2214
2487
 
2215
2488
  :host([data-color-scheme="dark"]) .cpk-td__metadata-pill,
2489
+ :host([data-color-scheme="dark"]) .cpk-td__try-from-here,
2216
2490
  :host([data-color-scheme="dark"]) .cpk-td__bubble-inner--assistant,
2217
2491
  :host([data-color-scheme="dark"]) .cpk-td__tool-block,
2218
2492
  :host([data-color-scheme="dark"]) .cpk-td__event,
@@ -2225,11 +2499,15 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2225
2499
  }
2226
2500
 
2227
2501
  :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 {
2502
+ :host([data-color-scheme="dark"]) .cpk-td__tool-body {
2230
2503
  background: #171a22;
2231
2504
  }
2232
2505
 
2506
+ :host([data-color-scheme="dark"]) .cpk-td__tool-pre {
2507
+ background: #111319;
2508
+ color: #f3f4f8;
2509
+ }
2510
+
2233
2511
  :host([data-color-scheme="dark"]) .cpk-td__panel-toggle:hover,
2234
2512
  :host([data-color-scheme="dark"]) .cpk-td__tool-header:hover,
2235
2513
  :host([data-color-scheme="dark"]) .cpk-td__timeline-bulk-toggle:hover,
@@ -2239,12 +2517,115 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2239
2517
 
2240
2518
  :host([data-color-scheme="dark"]) .cpk-td__panel-toggle--active,
2241
2519
  :host([data-color-scheme="dark"]) .cpk-td__inline-chip,
2242
- :host([data-color-scheme="dark"]) .cpk-td__timeline-kind,
2243
2520
  :host([data-color-scheme="dark"]) .cpk-td__genui-badge {
2244
2521
  background: #302b43;
2245
2522
  color: #d8d9ff;
2246
2523
  }
2247
2524
 
2525
+ :host([data-color-scheme="dark"]) .cpk-td__timeline-item--message {
2526
+ background: #191c24;
2527
+ border-color: #343742;
2528
+ box-shadow: none;
2529
+ }
2530
+
2531
+ :host([data-color-scheme="dark"])
2532
+ .cpk-td__timeline-item--user
2533
+ .cpk-td__timeline-header {
2534
+ background: #bec2ff1a;
2535
+ }
2536
+
2537
+ :host([data-color-scheme="dark"])
2538
+ .cpk-td__timeline-item--assistant
2539
+ .cpk-td__timeline-header {
2540
+ background: #85ecce1a;
2541
+ }
2542
+
2543
+ :host([data-color-scheme="dark"])
2544
+ .cpk-td__timeline-item--message
2545
+ .cpk-td__timeline-kind {
2546
+ background: #302b43;
2547
+ color: #d8d9ff;
2548
+ }
2549
+
2550
+ :host([data-color-scheme="dark"])
2551
+ .cpk-td__timeline-item--assistant
2552
+ .cpk-td__timeline-kind {
2553
+ background: #1a3a32;
2554
+ color: #85ecce;
2555
+ }
2556
+
2557
+ :host([data-color-scheme="dark"]) .cpk-td__timeline-item--run,
2558
+ :host([data-color-scheme="dark"]) .cpk-td__timeline-item--event,
2559
+ :host([data-color-scheme="dark"]) .cpk-td__timeline-item--state,
2560
+ :host([data-color-scheme="dark"]) .cpk-td__timeline-item--tool,
2561
+ :host([data-color-scheme="dark"]) .cpk-td__event--run,
2562
+ :host([data-color-scheme="dark"]) .cpk-td__event--event,
2563
+ :host([data-color-scheme="dark"]) .cpk-td__event--state,
2564
+ :host([data-color-scheme="dark"]) .cpk-td__event--message,
2565
+ :host([data-color-scheme="dark"]) .cpk-td__event--tool {
2566
+ background: #191c24;
2567
+ border-color: #343742;
2568
+ }
2569
+
2570
+ :host([data-color-scheme="dark"])
2571
+ .cpk-td__timeline-item--run
2572
+ .cpk-td__timeline-header,
2573
+ :host([data-color-scheme="dark"])
2574
+ .cpk-td__timeline-item--event
2575
+ .cpk-td__timeline-header,
2576
+ :host([data-color-scheme="dark"])
2577
+ .cpk-td__timeline-item--state
2578
+ .cpk-td__timeline-header {
2579
+ background: transparent;
2580
+ }
2581
+
2582
+ :host([data-color-scheme="dark"]) .cpk-td__timeline-kind {
2583
+ background: #20232d;
2584
+ color: #aeb1bd;
2585
+ }
2586
+
2587
+ :host([data-color-scheme="dark"])
2588
+ .cpk-td__timeline-item--run
2589
+ .cpk-td__timeline-title,
2590
+ :host([data-color-scheme="dark"])
2591
+ .cpk-td__timeline-item--event
2592
+ .cpk-td__timeline-title,
2593
+ :host([data-color-scheme="dark"])
2594
+ .cpk-td__timeline-item--state
2595
+ .cpk-td__timeline-title {
2596
+ color: #aeb1bd;
2597
+ }
2598
+
2599
+ :host([data-color-scheme="dark"]) .cpk-td__event-header {
2600
+ background: transparent;
2601
+ }
2602
+
2603
+ :host([data-color-scheme="dark"]) .cpk-td__event-type {
2604
+ background: #20232d;
2605
+ color: #f3f4f8;
2606
+ }
2607
+
2608
+ :host([data-color-scheme="dark"]) .cpk-td__event--message .cpk-td__event-type {
2609
+ background: #302b43;
2610
+ color: #d8d9ff;
2611
+ }
2612
+
2613
+ :host([data-color-scheme="dark"]) .cpk-td__event--tool .cpk-td__event-type {
2614
+ background: #1a3a32;
2615
+ color: #85ecce;
2616
+ }
2617
+
2618
+ :host([data-color-scheme="dark"]) .cpk-td__event--error .cpk-td__event-type {
2619
+ background: rgba(250, 95, 103, 0.2);
2620
+ color: #fa5f67;
2621
+ }
2622
+
2623
+ :host([data-color-scheme="dark"])
2624
+ .cpk-td__timeline-item--message
2625
+ .cpk-td__timeline-body {
2626
+ color: #f3f4f8;
2627
+ }
2628
+
2248
2629
  :host([data-color-scheme="dark"]) .cpk-td__tab,
2249
2630
  :host([data-color-scheme="dark"]) .cpk-td__panel-toggle,
2250
2631
  :host([data-color-scheme="dark"]) .cpk-td__metadata-label,
@@ -2264,6 +2645,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2264
2645
  :host([data-color-scheme="dark"]) .cpk-td__timeline-title,
2265
2646
  :host([data-color-scheme="dark"]) .cpk-td__timeline-bulk-toggle,
2266
2647
  :host([data-color-scheme="dark"]) .cpk-td__timeline-details-toggle,
2648
+ :host([data-color-scheme="dark"]) .cpk-td__try-from-here,
2267
2649
  :host([data-color-scheme="dark"]) .cpk-tdp__value {
2268
2650
  color: #f3f4f8;
2269
2651
  }
@@ -2271,7 +2653,9 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2271
2653
  :host([data-color-scheme="dark"]) .cpk-td__event-payload,
2272
2654
  :host([data-color-scheme="dark"]) .cpk-td__json-block,
2273
2655
  :host([data-color-scheme="dark"]) .cpk-json-block {
2274
- color: #c7c9d2;
2656
+ background: #111319;
2657
+ border-top-color: #343742;
2658
+ color: #f3f4f8;
2275
2659
  }
2276
2660
 
2277
2661
  :host([data-color-scheme="dark"]) .cpk-tdp__divider {
@@ -2291,7 +2675,8 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2291
2675
  if (this.canFetchEvents()) {
2292
2676
  this._eventsFetched = true;
2293
2677
  this.fetchEvents(this.threadId);
2294
- } else this.fetchMessages(this.threadId);
2678
+ }
2679
+ if (this.canFetchMessages()) this.fetchMessages(this.threadId);
2295
2680
  } else {
2296
2681
  this._fetchedMetadata = null;
2297
2682
  this._conversation = [];
@@ -2302,7 +2687,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2302
2687
  this._messagesAbort = null;
2303
2688
  this.fetchMessages(this.threadId, true);
2304
2689
  }
2305
- const focusedContentChanged = _changed.has("_fetchedEvents") || _changed.has("agentEventsInput") || _changed.has("_conversation");
2690
+ const focusedContentChanged = _changed.has("_fetchedEvents") || _changed.has("agentEventsInput") || _changed.has("agentMessagesInput") || _changed.has("_conversation");
2306
2691
  if (this.focusMessageId && (this.focusRequestId > this._scrolledFocusRequestId || focusedContentChanged)) {
2307
2692
  if (this._tab !== "timeline") {
2308
2693
  this._activatedTabs = new Set([...this._activatedTabs, "timeline"]);
@@ -2459,18 +2844,14 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2459
2844
  if (result.status === "not-available") {
2460
2845
  this._eventsNotAvailable = true;
2461
2846
  this._fetchedEvents = [];
2462
- if (this.canFetchMessages()) this.fetchMessages(threadId);
2463
2847
  return;
2464
2848
  }
2465
- const mappedEvents = this.mapApiEvents(result.events);
2466
- this._fetchedEvents = mappedEvents;
2467
- if (mappedEvents.length === 0 && this.canFetchMessages()) this.fetchMessages(threadId);
2849
+ this._fetchedEvents = this.mapApiEvents(result.events);
2468
2850
  } catch (err) {
2469
2851
  if (err instanceof Error && err.name === "AbortError") return;
2470
2852
  if (this.threadId !== threadId) return;
2471
2853
  this._eventsError = err instanceof Error ? err.message : "Failed to load events";
2472
2854
  this._fetchedEvents = [];
2473
- if (this.canFetchMessages()) this.fetchMessages(threadId);
2474
2855
  } finally {
2475
2856
  if (!controller.signal.aborted && this.threadId === threadId) this._loadingEvents = false;
2476
2857
  }
@@ -2544,13 +2925,15 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2544
2925
  mapMessages(messages) {
2545
2926
  const items = [];
2546
2927
  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") {
2928
+ for (const msg of messages) if (msg.role === "user") {
2929
+ const content = textFromUnknownContent(msg.content);
2930
+ if (content) items.push({
2931
+ id: msg.id,
2932
+ type: "user",
2933
+ content,
2934
+ createdAt: ""
2935
+ });
2936
+ } else if (msg.role === "assistant") {
2554
2937
  if (msg.toolCalls?.length) for (const tc of msg.toolCalls) {
2555
2938
  let args = {};
2556
2939
  if (typeof tc.args === "string") try {
@@ -2579,10 +2962,11 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2579
2962
  toolCallMap.set(tc.id, item);
2580
2963
  items.push(item);
2581
2964
  }
2582
- if (msg.content) items.push({
2965
+ const assistantContent = textFromUnknownContent(msg.content);
2966
+ if (assistantContent) items.push({
2583
2967
  id: msg.id,
2584
2968
  type: "assistant",
2585
- content: msg.content,
2969
+ content: assistantContent,
2586
2970
  createdAt: ""
2587
2971
  });
2588
2972
  } else if (msg.role === "activity") items.push({
@@ -2630,14 +3014,86 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2630
3014
  return this.timelineItemsForEvents(this.activeEvents);
2631
3015
  }
2632
3016
  timelineItemsForEvents(events) {
2633
- if (this._timelineItemsCache?.events === events) return this._timelineItemsCache.items;
2634
- const items = this.timelineItemsFromEvents(events);
3017
+ const conversation = this._conversation;
3018
+ const agentMessages = this.agentMessagesInput;
3019
+ if (this._timelineItemsCache?.events === events && this._timelineItemsCache.conversation === conversation && this._timelineItemsCache.agentMessages === agentMessages) return this._timelineItemsCache.items;
3020
+ const items = this.mergeUserMessagesIntoTimeline(this.timelineItemsFromEvents(events));
2635
3021
  this._timelineItemsCache = {
2636
3022
  events,
3023
+ conversation,
3024
+ agentMessages,
2637
3025
  items
2638
3026
  };
2639
3027
  return items;
2640
3028
  }
3029
+ conversationUsers() {
3030
+ const users = [];
3031
+ const seenIds = /* @__PURE__ */ new Set();
3032
+ const seenBodies = /* @__PURE__ */ new Set();
3033
+ const push = (user) => {
3034
+ const body = user.content.trim();
3035
+ if (!body) return;
3036
+ if (seenIds.has(user.id) || seenBodies.has(body)) return;
3037
+ seenIds.add(user.id);
3038
+ seenBodies.add(body);
3039
+ users.push(user);
3040
+ };
3041
+ for (const item of this._conversation) if (item.type === "user") push(item);
3042
+ this.agentMessagesInput.forEach((message, index) => {
3043
+ if (message.role !== "user") return;
3044
+ push({
3045
+ id: message.id ?? `live-user-${index}`,
3046
+ type: "user",
3047
+ content: message.contentText,
3048
+ createdAt: ""
3049
+ });
3050
+ });
3051
+ return users;
3052
+ }
3053
+ mergeUserMessagesIntoTimeline(items) {
3054
+ if (items.length === 0) return items;
3055
+ const users = this.conversationUsers();
3056
+ if (users.length === 0) return items;
3057
+ const shownIds = /* @__PURE__ */ new Set();
3058
+ const shownBodies = /* @__PURE__ */ new Set();
3059
+ for (const item of items) {
3060
+ if (item.kind !== "message") continue;
3061
+ if (!item.title.toLowerCase().startsWith("user")) continue;
3062
+ if (item.messageId) shownIds.add(item.messageId);
3063
+ const body = item.body?.trim();
3064
+ if (body) shownBodies.add(body);
3065
+ }
3066
+ const missing = users.filter((user) => {
3067
+ if (shownIds.has(user.id)) return false;
3068
+ if (shownBodies.has(user.content.trim())) return false;
3069
+ return true;
3070
+ });
3071
+ if (missing.length === 0) return items;
3072
+ const insertAt = [];
3073
+ for (let index = 0; index < items.length; index++) {
3074
+ const item = items[index];
3075
+ if (item.kind === "run" && item.title === "Run started") insertAt.push(index);
3076
+ }
3077
+ if (insertAt.length === 0) for (let index = 0; index < items.length; index++) {
3078
+ const item = items[index];
3079
+ if (item.kind === "message" && item.title.toLowerCase().includes("assistant")) insertAt.push(index);
3080
+ }
3081
+ const merged = [...items];
3082
+ for (let index = missing.length - 1; index >= 0; index--) {
3083
+ const user = missing[index];
3084
+ const row = {
3085
+ id: `conversation-user-${user.id}`,
3086
+ messageId: user.id,
3087
+ kind: "message",
3088
+ title: "User message",
3089
+ body: user.content,
3090
+ timestamp: user.createdAt || 0,
3091
+ sourceIndex: 0
3092
+ };
3093
+ merged.splice(insertAt[index] ?? 0, 0, row);
3094
+ }
3095
+ return merged;
3096
+ }
2641
3097
  timelineItemsFromEvents(events) {
2642
3098
  if (events.length === 0) return [];
2643
3099
  const items = [];
@@ -2676,7 +3132,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2676
3132
  id: `message-${key}`,
2677
3133
  messageId: key,
2678
3134
  kind: "message",
2679
- title: `${role || "message"} message`,
3135
+ title: messageTitle(role || "message"),
2680
3136
  body: "",
2681
3137
  timestamp: event.timestamp,
2682
3138
  sourceIndex
@@ -2824,7 +3280,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2824
3280
  items.push({
2825
3281
  id: `${type}-${sourceIndex}`,
2826
3282
  kind: "state",
2827
- title: type === "STATE_SNAPSHOT" ? "State snapshot captured" : "State delta captured",
3283
+ title: type === "STATE_SNAPSHOT" ? "State snapshot" : "State delta",
2828
3284
  timestamp: event.timestamp,
2829
3285
  sourceIndex,
2830
3286
  details: payload
@@ -2834,7 +3290,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2834
3290
  items.push({
2835
3291
  id: `event-${sourceIndex}`,
2836
3292
  kind: "event",
2837
- title: type,
3293
+ title: humanizeEventType(type),
2838
3294
  timestamp: event.timestamp,
2839
3295
  sourceIndex,
2840
3296
  details: payload
@@ -2973,6 +3429,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2973
3429
  });
2974
3430
  }
2975
3431
  render() {
3432
+ const viewInApp = this.renderViewInAppAction();
2976
3433
  return lit.html`
2977
3434
  <div class="cpk-td">
2978
3435
  <!-- ── Left area: tabs + content ─────────────────────────────────── -->
@@ -3000,6 +3457,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3000
3457
  </button>
3001
3458
  `)}
3002
3459
  </div>
3460
+ ${viewInApp !== lit.nothing ? lit.html`<div class="cpk-td__chrome-actions">${viewInApp}</div>` : lit.nothing}
3003
3461
  ${this.renderPanelToggle()}
3004
3462
  </div>
3005
3463
  ${this.renderMetadataStrip()}
@@ -3054,8 +3512,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3054
3512
  value: metadata?.name ?? this.thread?.name ?? "Untitled"
3055
3513
  }, {
3056
3514
  label: "ID",
3057
- value: metadata?.id ?? this.threadId ?? "—",
3058
- wrap: true
3515
+ value: metadata?.id ?? this.threadId ?? "—"
3059
3516
  }];
3060
3517
  for (const fact of [
3061
3518
  {
@@ -3077,7 +3534,6 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3077
3534
  value: fact.label === "Created" || fact.label === "Updated" ? this.fmtTime(fact.value) : fact.value
3078
3535
  });
3079
3536
  }
3080
- const bulkControls = this.renderActiveBulkControls();
3081
3537
  return lit.html`
3082
3538
  <div
3083
3539
  class="cpk-td__metadata-strip"
@@ -3100,8 +3556,6 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3100
3556
  </span>
3101
3557
  `)}
3102
3558
  </div>
3103
- ${this.renderViewInAppAction()}
3104
- ${bulkControls}
3105
3559
  </div>
3106
3560
  `;
3107
3561
  }
@@ -3124,17 +3578,55 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3124
3578
  ${isStop ? "Stop viewing" : "View in your app"}
3125
3579
  </button>
3126
3580
  ${this.viewInAppError ? lit.html`<span class="cpk-td__view-in-app-error" role="alert"
3127
- >${this.viewInAppError}</span
3128
- >` : lit.nothing}
3581
+ >${this.viewInAppError}</span
3582
+ >` : lit.nothing}
3583
+ `;
3584
+ }
3585
+ renderTryFromHereControl() {
3586
+ if (!this.tryFromHereAvailable) return lit.nothing;
3587
+ return lit.html`
3588
+ <button
3589
+ type="button"
3590
+ class="cpk-td__try-from-here"
3591
+ aria-label="Try from here"
3592
+ ?disabled=${this.tryFromHereBusy}
3593
+ @click=${this.onTryFromHere}
3594
+ >
3595
+ ${this.tryFromHereBusy ? "Loading…" : "Try from here"}
3596
+ <svg
3597
+ class="cpk-td__try-from-here-icon"
3598
+ aria-hidden="true"
3599
+ width="12"
3600
+ height="12"
3601
+ viewBox="0 0 24 24"
3602
+ fill="none"
3603
+ stroke="currentColor"
3604
+ stroke-width="2"
3605
+ stroke-linecap="round"
3606
+ stroke-linejoin="round"
3607
+ >
3608
+ <path d="M7 7h10v10" />
3609
+ <path d="M7 17 17 7" />
3610
+ </svg>
3611
+ </button>
3612
+ ${this.tryFromHereError ? lit.html`<span class="cpk-td__try-from-here-error" role="alert"
3613
+ >${this.tryFromHereError}</span
3614
+ >` : lit.nothing}
3129
3615
  `;
3130
3616
  }
3131
- renderActiveBulkControls() {
3617
+ renderTimelineBulkControls() {
3618
+ const bulk = this.renderTimelineBulkButtons();
3619
+ const tryFromHere = this.renderTryFromHereControl();
3620
+ if (bulk === lit.nothing && tryFromHere === lit.nothing) return lit.nothing;
3621
+ return lit.html`<div class="cpk-td__timeline-toolbar">
3622
+ ${bulk}${tryFromHere}
3623
+ </div>`;
3624
+ }
3625
+ renderTimelineBulkButtons() {
3132
3626
  if (this._eventsNotAvailable) return lit.nothing;
3133
- if (this._tab === "raw-events") return this.renderRawEventBulkControls();
3134
- if (this._tab !== "timeline") return lit.nothing;
3135
3627
  const detailIds = this.timelineItemsForEvents(this.activeEvents).filter((item) => item.details).map((item) => item.id);
3136
3628
  if (detailIds.length <= 1) return lit.nothing;
3137
- return lit.html`<div class="cpk-td__timeline-toolbar">
3629
+ return lit.html`
3138
3630
  <button
3139
3631
  type="button"
3140
3632
  class="cpk-td__timeline-bulk-toggle"
@@ -3151,7 +3643,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3151
3643
  >
3152
3644
  Collapse all
3153
3645
  </button>
3154
- </div>`;
3646
+ `;
3155
3647
  }
3156
3648
  renderRawEventBulkControls() {
3157
3649
  const eventIds = this.activeEvents.map((event) => this.rawEventId(event));
@@ -3183,6 +3675,9 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3183
3675
  (this.shadowRoot?.querySelector(`[data-source-index="${sourceIndex}"]`))?.scrollIntoView?.({ block: "center" });
3184
3676
  });
3185
3677
  }
3678
+ withMessagesToolbar(content) {
3679
+ return lit.html`${this.renderTimelineBulkControls()}${content}`;
3680
+ }
3186
3681
  renderTimeline() {
3187
3682
  if (this._loadingEvents) return lit.html`
3188
3683
  <div class="cpk-td__status">Loading timeline…</div>
@@ -3204,7 +3699,12 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3204
3699
  `;
3205
3700
  }
3206
3701
  const events = this.activeEvents;
3207
- const cachedTimeline = this.getCachedPanelTpl("timeline", [events, this._expandedTimelineDetails]);
3702
+ const cachedTimeline = this.getCachedPanelTpl("timeline", [
3703
+ events,
3704
+ this._conversation,
3705
+ this.agentMessagesInput,
3706
+ this._expandedTimelineDetails
3707
+ ]);
3208
3708
  if (cachedTimeline) return cachedTimeline;
3209
3709
  const timelineItems = this.timelineItemsForEvents(events);
3210
3710
  if (timelineItems.length === 0) {
@@ -3220,14 +3720,28 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3220
3720
  </div>
3221
3721
  `;
3222
3722
  }
3223
- return this.cachedPanelTpl("timeline", [events, this._expandedTimelineDetails], () => lit.html`${timelineItems.map((item) => this.renderTimelineItem(item))}`);
3723
+ return this.cachedPanelTpl("timeline", [
3724
+ events,
3725
+ this._conversation,
3726
+ this.agentMessagesInput,
3727
+ this._expandedTimelineDetails
3728
+ ], () => lit.html`${timelineItems.map((item) => this.renderTimelineItem(item))}`);
3729
+ }
3730
+ timelineItemClass(item) {
3731
+ const classes = ["cpk-td__timeline-item", `cpk-td__timeline-item--${item.kind}`];
3732
+ if (item.kind === "warning" || item.severity === "error") classes.push("cpk-td__timeline-item--warning");
3733
+ if (item.kind === "message") {
3734
+ const title = item.title.toLowerCase();
3735
+ if (title.startsWith("user")) classes.push("cpk-td__timeline-item--user");
3736
+ else if (title.includes("assistant")) classes.push("cpk-td__timeline-item--assistant");
3737
+ }
3738
+ return classes.join(" ");
3224
3739
  }
3225
3740
  renderTimelineItem(item) {
3226
- const isWarning = item.kind === "warning";
3227
3741
  const detailsExpanded = this._expandedTimelineDetails.has(item.id);
3228
3742
  return lit.html`
3229
3743
  <div
3230
- class="cpk-td__timeline-item ${isWarning ? "cpk-td__timeline-item--warning" : ""}"
3744
+ class=${this.timelineItemClass(item)}
3231
3745
  data-message-id=${item.messageId ?? lit.nothing}
3232
3746
  >
3233
3747
  <div class="cpk-td__timeline-header">
@@ -3235,13 +3749,15 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3235
3749
  >${item.severity === "error" ? "error" : item.kind}</span
3236
3750
  >
3237
3751
  <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>
3752
+ ${item.sourceIndex ? lit.html`
3753
+ <button
3754
+ type="button"
3755
+ class="cpk-td__source-link"
3756
+ @click=${() => this.revealSourceEvent(item.sourceIndex)}
3757
+ >
3758
+ Source event #${item.sourceIndex}
3759
+ </button>
3760
+ ` : lit.nothing}
3245
3761
  <span class="cpk-td__timeline-time"
3246
3762
  >${formatTimestamp(item.timestamp)}</span
3247
3763
  >
@@ -3278,9 +3794,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3278
3794
  <span>${detailsExpanded ? "Hide details" : "Show details"}</span>
3279
3795
  </button>` : lit.nothing}
3280
3796
  ${item.body ? lit.html`<div class="cpk-td__timeline-body">${item.body}</div>` : lit.nothing}
3281
- ${item.details && detailsExpanded ? lit.html`<pre class="cpk-td__timeline-body">
3282
- ${(0, lit_directives_unsafe_html_js.unsafeHTML)(highlightedJson(item.details))}</pre
3283
- >` : lit.nothing}
3797
+ ${item.details && detailsExpanded ? renderHighlightedJsonBlock(item.details) : lit.nothing}
3284
3798
  </div>
3285
3799
  `;
3286
3800
  }
@@ -3410,9 +3924,7 @@ ${(0, lit_directives_unsafe_html_js.unsafeHTML)(highlightedJson(item.details))}<
3410
3924
  ${expanded ? lit.html`
3411
3925
  <div class="cpk-td__tool-body">
3412
3926
  <div class="cpk-td__tool-section-label">Arguments</div>
3413
- <pre class="cpk-td__tool-pre">
3414
- ${(0, lit_directives_unsafe_html_js.unsafeHTML)(highlightedJson(item.arguments))}</pre
3415
- >
3927
+ ${renderHighlightedJsonBlock(item.arguments)}
3416
3928
  ${item.result ? lit.html`
3417
3929
  <div
3418
3930
  class="cpk-td__tool-section-label"
@@ -3420,9 +3932,7 @@ ${(0, lit_directives_unsafe_html_js.unsafeHTML)(highlightedJson(item.arguments))
3420
3932
  >
3421
3933
  Result
3422
3934
  </div>
3423
- <pre class="cpk-td__tool-pre">
3424
- ${(0, lit_directives_unsafe_html_js.unsafeHTML)(highlightedJson(item.result))}</pre
3425
- >
3935
+ ${renderHighlightedJsonBlock(item.result)}
3426
3936
  ` : lit.nothing}
3427
3937
  </div>
3428
3938
  ` : lit.nothing}
@@ -3537,58 +4047,58 @@ ${(0, lit_directives_unsafe_html_js.unsafeHTML)(highlightedJson(item.result))}</
3537
4047
  </div>
3538
4048
  `;
3539
4049
  return this.cachedPanelTpl("raw-events", [events, this._expandedRawEvents], () => {
3540
- return lit.html`${events.map((event) => {
3541
- const { bg, fg } = eventColors(event.type);
4050
+ return lit.html`${this.renderRawEventBulkControls()}${events.map((event) => {
3542
4051
  const eventId = this.rawEventId(event);
3543
4052
  const detailsExpanded = this._expandedRawEvents.has(eventId);
3544
4053
  return lit.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
3549
- >
3550
- <span class="cpk-td__event-time"
3551
- >${formatTimestamp(event.timestamp)}</span
3552
- >
3553
- </div>
3554
- <button
3555
- type="button"
3556
- class="cpk-td__timeline-details-toggle"
3557
- aria-expanded=${detailsExpanded ? "true" : "false"}
3558
- @click=${() => this.toggleRawEventDetails(eventId)}
4054
+ <div
4055
+ class="cpk-td__event cpk-td__event--${eventCategory(event.type)}"
4056
+ data-source-index=${event.sourceIndex}
3559
4057
  >
3560
- ${detailsExpanded ? lit.html`
3561
- <svg
3562
- aria-hidden="true"
3563
- viewBox="0 0 24 24"
3564
- fill="none"
3565
- stroke="currentColor"
3566
- stroke-linecap="round"
3567
- stroke-linejoin="round"
3568
- >
3569
- <path d="m6 9 6 6 6-6" />
3570
- </svg>
3571
- ` : lit.html`
3572
- <svg
3573
- aria-hidden="true"
3574
- viewBox="0 0 24 24"
3575
- fill="none"
3576
- stroke="currentColor"
3577
- stroke-linecap="round"
3578
- stroke-linejoin="round"
3579
- >
3580
- <path d="m9 18 6-6-6-6" />
3581
- </svg>
3582
- `}
3583
- <span
3584
- >${detailsExpanded ? "Hide details" : "Show details"}</span
4058
+ <div class="cpk-td__event-header">
4059
+ <span class="cpk-td__event-type" title=${event.type}
4060
+ >${humanizeEventType(event.type)}</span
4061
+ >
4062
+ <span class="cpk-td__event-time"
4063
+ >${formatTimestamp(event.timestamp)}</span
4064
+ >
4065
+ </div>
4066
+ <button
4067
+ type="button"
4068
+ class="cpk-td__timeline-details-toggle"
4069
+ aria-expanded=${detailsExpanded ? "true" : "false"}
4070
+ @click=${() => this.toggleRawEventDetails(eventId)}
3585
4071
  >
3586
- </button>
3587
- ${detailsExpanded ? lit.html`<pre class="cpk-td__event-payload">
3588
- ${(0, lit_directives_unsafe_html_js.unsafeHTML)(highlightedJson(event.rawEvent ?? event))}</pre
3589
- >` : lit.nothing}
3590
- </div>
3591
- `;
4072
+ ${detailsExpanded ? lit.html`
4073
+ <svg
4074
+ aria-hidden="true"
4075
+ viewBox="0 0 24 24"
4076
+ fill="none"
4077
+ stroke="currentColor"
4078
+ stroke-linecap="round"
4079
+ stroke-linejoin="round"
4080
+ >
4081
+ <path d="m6 9 6 6 6-6" />
4082
+ </svg>
4083
+ ` : lit.html`
4084
+ <svg
4085
+ aria-hidden="true"
4086
+ viewBox="0 0 24 24"
4087
+ fill="none"
4088
+ stroke="currentColor"
4089
+ stroke-linecap="round"
4090
+ stroke-linejoin="round"
4091
+ >
4092
+ <path d="m9 18 6-6-6-6" />
4093
+ </svg>
4094
+ `}
4095
+ <span
4096
+ >${detailsExpanded ? "Hide details" : "Show details"}</span
4097
+ >
4098
+ </button>
4099
+ ${detailsExpanded ? renderHighlightedJsonBlock(event.rawEvent ?? event) : lit.nothing}
4100
+ </div>
4101
+ `;
3592
4102
  })}`;
3593
4103
  });
3594
4104
  }
@@ -4397,6 +4907,13 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
4397
4907
  this.systemColorSchemeMediaQuery = null;
4398
4908
  this.briefingRestoreMenu = null;
4399
4909
  this.homeViewedThisOpen = false;
4910
+ this.onboardingRunId = null;
4911
+ this.promptCopyState = "idle";
4912
+ this.promptCopyResetTimer = null;
4913
+ this.intelStoryBeat = 0;
4914
+ this.intelStoryUserPinned = false;
4915
+ this.intelStoryTimer = null;
4916
+ this.intelStoryReducedMotion = null;
4400
4917
  this.hasResolvedCore = false;
4401
4918
  this.settingsOpen = false;
4402
4919
  this.lastSelectedMenuByGroup = {
@@ -4442,9 +4959,12 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
4442
4959
  this.playgroundError = null;
4443
4960
  this.playgroundSourceThreadId = null;
4444
4961
  this.playgroundShowEphemeralNotice = false;
4962
+ this.tryFromHereBusy = false;
4963
+ this.tryFromHereError = null;
4445
4964
  this.threadCapabilityEnabled = null;
4446
4965
  this.threadCapabilityGeneration = 0;
4447
4966
  this.contextMenuOpen = false;
4967
+ this.iconRailContextCloseTimer = null;
4448
4968
  this.layoutMenuOpen = false;
4449
4969
  this.dockMode = "floating";
4450
4970
  this.popOut = null;
@@ -4506,6 +5026,9 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
4506
5026
  this.launcherHudSide = "left";
4507
5027
  this.launcherHudHelp = null;
4508
5028
  this.launcherHudCloseTimer = null;
5029
+ this.launcherHudIntro = false;
5030
+ this.launcherHudIntroStartTimer = null;
5031
+ this.launcherHudIntroEndTimer = null;
4509
5032
  this.hudLandingMenu = null;
4510
5033
  this.pillOutcome = null;
4511
5034
  this.viewedNewsSignalIds = /* @__PURE__ */ new Set();
@@ -4590,6 +5113,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
4590
5113
  this.openInspector("floating_button");
4591
5114
  };
4592
5115
  this.handleLauncherHudEnter = () => {
5116
+ this.cancelLauncherHudIntro();
4593
5117
  this.openLauncherHud();
4594
5118
  };
4595
5119
  this.handleLauncherHudLeave = () => {
@@ -4600,6 +5124,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
4600
5124
  }, 160);
4601
5125
  };
4602
5126
  this.handleLauncherHudFocusIn = () => {
5127
+ this.cancelLauncherHudIntro();
4603
5128
  this.openLauncherHud();
4604
5129
  };
4605
5130
  this.handleLauncherHudFocusOut = (event) => {
@@ -4676,6 +5201,26 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
4676
5201
  this.applyEventErrorLanding(key);
4677
5202
  this.requestUpdate();
4678
5203
  };
5204
+ this.handleIntelligencePromptCopy = async (event) => {
5205
+ this.clearIntelligencePromptReset();
5206
+ const runId = this.getOnboardingRunId();
5207
+ const clipboard = this.getClipboard(event);
5208
+ let outcome = "failed";
5209
+ if (clipboard?.writeText) try {
5210
+ await clipboard.writeText(require_onboarding_prompt.createOnboardingPrompt(runId));
5211
+ outcome = "copied";
5212
+ } catch {
5213
+ outcome = "failed";
5214
+ }
5215
+ if (!this.isConnected) return;
5216
+ this.promptCopyState = outcome;
5217
+ this.requestUpdate();
5218
+ if (outcome === "copied") this.scheduleIntelligencePromptReset();
5219
+ if (!this.core?.telemetryDisabled) require_telemetry.trackHomePromptCopied({
5220
+ onboarding_run_id: runId,
5221
+ outcome
5222
+ });
5223
+ };
4679
5224
  this.handleSystemColorSchemeChange = (event) => {
4680
5225
  if (this.hasExplicitColorScheme) return;
4681
5226
  this.colorScheme = event.matches ? "dark" : "light";
@@ -4920,21 +5465,14 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
4920
5465
  this.startPlaygroundSession(false);
4921
5466
  return;
4922
5467
  }
4923
- const core = this._core;
4924
5468
  const thread = this._threads.find((candidate) => candidate.id === threadId);
4925
- if (!core?.runtimeUrl || !thread) return;
5469
+ if (!thread) return;
4926
5470
  this.playgroundIsLoadingThread = true;
4927
5471
  this.playgroundError = null;
4928
5472
  this.requestUpdate();
4929
5473
  try {
4930
- const baseUrl = core.runtimeUrl.replace(/\/+$/, "");
4931
- const encodedThreadId = encodeURIComponent(threadId);
4932
- const [messagesResponse, stateResponse] = await Promise.all([fetch(`${baseUrl}/threads/${encodedThreadId}/messages`, { headers: { ...core.headers } }), fetch(`${baseUrl}/threads/${encodedThreadId}/state`, { headers: { ...core.headers } })]);
4933
- if (!messagesResponse.ok) throw new Error(`Failed to load thread (HTTP ${messagesResponse.status}).`);
4934
- const messagesBody = await messagesResponse.json();
4935
- const stateBody = stateResponse.ok ? await stateResponse.json() : { state: {} };
4936
- this.startPlaygroundSession(false, this.mapThreadMessagesToPlayground(messagesBody.messages ?? []), stateBody.state ?? {}, thread.agentId);
4937
- this.playgroundSourceThreadId = threadId;
5474
+ const snapshot = await this.loadThreadSnapshot(thread);
5475
+ this.applyThreadSnapshotToPlayground(thread, snapshot);
4938
5476
  } catch (error) {
4939
5477
  this.playgroundError = error instanceof Error ? error.message : "Failed to load thread.";
4940
5478
  } finally {
@@ -4942,6 +5480,35 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
4942
5480
  this.requestUpdate();
4943
5481
  }
4944
5482
  };
5483
+ this.handleTryFromHere = async (threadId) => {
5484
+ if (!threadId || this.tryFromHereBusy) return;
5485
+ const thread = this._threads.find((candidate) => candidate.id === threadId) ?? null;
5486
+ if (!thread) return;
5487
+ this.tryFromHereBusy = true;
5488
+ this.tryFromHereError = null;
5489
+ this.requestUpdate();
5490
+ const isCurrentTryFromHereRequest = () => this.selectedThreadId === threadId && this.selectedMenu === "threads";
5491
+ try {
5492
+ const snapshot = await this.loadThreadSnapshot(thread);
5493
+ if (isCurrentTryFromHereRequest()) {
5494
+ this.applyThreadSnapshotToPlayground(thread, snapshot);
5495
+ this.handleMenuSelect("playground");
5496
+ }
5497
+ if (!this.core?.telemetryDisabled) require_telemetry.trackThreadsTryFromHereClicked({
5498
+ ...this.getThreadsTelemetryProps(),
5499
+ outcome: "success"
5500
+ });
5501
+ } catch (error) {
5502
+ if (isCurrentTryFromHereRequest()) this.tryFromHereError = error instanceof Error ? error.message : "Failed to load thread.";
5503
+ if (!this.core?.telemetryDisabled) require_telemetry.trackThreadsTryFromHereClicked({
5504
+ ...this.getThreadsTelemetryProps(),
5505
+ outcome: "failure"
5506
+ });
5507
+ } finally {
5508
+ this.tryFromHereBusy = false;
5509
+ this.requestUpdate();
5510
+ }
5511
+ };
4945
5512
  this.runPlaygroundAgent = async () => {
4946
5513
  const core = this._core;
4947
5514
  const agent = this.playgroundAgent;
@@ -5146,15 +5713,21 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
5146
5713
  this.requestUpdate();
5147
5714
  };
5148
5715
  this.handleIconRailContextPointerEnter = (event) => {
5149
- if (event.pointerType === "touch" || this.contextMenuOpen) return;
5716
+ if (event.pointerType === "touch") return;
5717
+ this.clearIconRailContextCloseTimer();
5718
+ if (this.contextMenuOpen) return;
5150
5719
  this.layoutMenuOpen = false;
5151
5720
  this.contextMenuOpen = true;
5152
5721
  this.requestUpdate();
5153
5722
  };
5154
5723
  this.handleIconRailContextPointerLeave = () => {
5155
5724
  if (!this.contextMenuOpen) return;
5156
- this.contextMenuOpen = false;
5157
- this.requestUpdate();
5725
+ this.clearIconRailContextCloseTimer();
5726
+ this.iconRailContextCloseTimer = setTimeout(() => {
5727
+ this.iconRailContextCloseTimer = null;
5728
+ this.contextMenuOpen = false;
5729
+ this.requestUpdate();
5730
+ }, 180);
5158
5731
  };
5159
5732
  this.handleIconRailContextPointerDown = (event) => {
5160
5733
  if (event.pointerType === "touch") {
@@ -5165,6 +5738,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
5165
5738
  event.stopPropagation();
5166
5739
  };
5167
5740
  this.handleIconRailContextFocusIn = () => {
5741
+ this.clearIconRailContextCloseTimer();
5168
5742
  if (this.contextMenuOpen) return;
5169
5743
  this.layoutMenuOpen = false;
5170
5744
  this.contextMenuOpen = true;
@@ -5585,7 +6159,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
5585
6159
  if (this.core?.getThreadStore(agentId)) return;
5586
6160
  const core = this.core;
5587
6161
  if (!core?.runtimeUrl) return;
5588
- const store = (0, _copilotkit_core.ɵcreateThreadStore)({ fetch: globalThis.fetch });
6162
+ const store = (0, _copilotkit_core.ɵcreateThreadStore)({ fetch: typeof core.ɵruntimeFetch === "function" ? core.ɵruntimeFetch : globalThis.fetch });
5589
6163
  store.start();
5590
6164
  store.setContext({
5591
6165
  runtimeUrl: core.runtimeUrl,
@@ -6135,7 +6709,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
6135
6709
  const messages = this.normalizeAgentMessages(agent.messages);
6136
6710
  if (messages) this.agentMessages.set(agent.agentId, messages);
6137
6711
  else this.agentMessages.delete(agent.agentId);
6138
- const runThreadId = agent.threadId;
6712
+ const runThreadId = this.readAgentThreadId(agent);
6139
6713
  if (runThreadId) this.liveMessageVersion.set(runThreadId, (this.liveMessageVersion.get(runThreadId) ?? 0) + 1);
6140
6714
  this.requestUpdate();
6141
6715
  } catch (error) {
@@ -6239,6 +6813,20 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
6239
6813
  getLatestMessagesForAgent(agentId) {
6240
6814
  return this.agentMessages.get(agentId) ?? null;
6241
6815
  }
6816
+ readAgentThreadId(agent) {
6817
+ if (!("threadId" in agent)) return void 0;
6818
+ const threadId = agent.threadId;
6819
+ return typeof threadId === "string" ? threadId : void 0;
6820
+ }
6821
+ getLiveAgentMessagesForThread(thread) {
6822
+ const messages = this.agentMessages.get(thread.agentId) ?? EMPTY_INSPECTOR_MESSAGES;
6823
+ const core = this._core;
6824
+ if (!core || typeof core.getAgent !== "function") return messages;
6825
+ const agent = core.getAgent(thread.agentId);
6826
+ if (!agent) return EMPTY_INSPECTOR_MESSAGES;
6827
+ if (this.readAgentThreadId(agent) !== thread.id) return EMPTY_INSPECTOR_MESSAGES;
6828
+ return messages;
6829
+ }
6242
6830
  getAgentStatus(agentId) {
6243
6831
  const events = this.agentEvents.get(agentId) ?? [];
6244
6832
  if (events.length === 0) return "idle";
@@ -6282,14 +6870,14 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
6282
6870
  <span>${functionName}${isFailedCall ? " failed" : ""}</span>
6283
6871
  <span class="text-[10px] text-gray-600">ID: ${callId}</span>
6284
6872
  </div>
6285
- ${isFailedCall && toolError?.message ? lit.html`<p class="mt-2 break-words leading-relaxed text-gray-800">
6873
+ ${isFailedCall && toolError?.message ? lit.html`<p
6874
+ class="mt-2 break-words leading-relaxed text-gray-800"
6875
+ >
6286
6876
  ${toolError.message}
6287
6877
  </p>` : lit.nothing}
6288
- ${argsString ? lit.html`<pre
6289
- class="mt-2 overflow-auto rounded bg-white p-2 text-[11px] leading-relaxed text-gray-800"
6290
- >
6291
- ${argsString}</pre
6292
- >` : lit.nothing}
6878
+ ${argsString ? lit.html`<div class="mt-2">
6879
+ ${renderHighlightedJsonBlock(coerceJsonValue(call.function?.arguments))}
6880
+ </div>` : lit.nothing}
6293
6881
  </div>
6294
6882
  `;
6295
6883
  })}
@@ -6341,15 +6929,14 @@ ${argsString}</pre
6341
6929
  return String(state);
6342
6930
  }
6343
6931
  getEventBadgeClasses(type) {
6344
- const base = "font-mono text-[10px] font-medium inline-flex items-center rounded-sm px-1.5 py-0.5 border";
6345
- if (type === "RUN_ERROR") return `${base} bg-rose-50 text-rose-700 border-rose-200`;
6346
- if (type.startsWith("RUN_")) return `${base} bg-blue-50 text-blue-700 border-blue-200`;
6347
- if (type.startsWith("TEXT_MESSAGE")) return `${base} bg-emerald-50 text-emerald-700 border-emerald-200`;
6348
- if (type.startsWith("TOOL_CALL")) return `${base} bg-amber-50 text-amber-700 border-amber-200`;
6349
- if (type.startsWith("REASONING")) return `${base} bg-fuchsia-50 text-fuchsia-700 border-fuchsia-200`;
6350
- if (type.startsWith("STATE")) return `${base} bg-violet-50 text-violet-700 border-violet-200`;
6351
- if (type.startsWith("MESSAGES")) return `${base} bg-sky-50 text-sky-700 border-sky-200`;
6352
- return `${base} bg-gray-100 text-gray-600 border-gray-200`;
6932
+ const base = "font-mono text-[10px] font-semibold inline-flex items-center rounded-sm px-1.5 py-0.5 border";
6933
+ if (type === "RUN_ERROR") return `${base} bg-rose-50 text-rose-800 border-rose-200`;
6934
+ if (type.startsWith("TEXT_MESSAGE")) return `${base} bg-violet-50 text-gray-900 border-violet-200`;
6935
+ if (type.startsWith("TOOL_CALL")) return `${base} bg-emerald-50 text-gray-900 border-emerald-200`;
6936
+ if (type.startsWith("RUN_") || type.startsWith("STEP_")) return `${base} bg-gray-100 text-gray-900 border-gray-200`;
6937
+ if (type.startsWith("REASONING")) return `${base} bg-violet-50 text-gray-900 border-violet-200`;
6938
+ if (type.startsWith("STATE") || type.startsWith("MESSAGES")) return `${base} bg-violet-50 text-gray-900 border-violet-200`;
6939
+ return `${base} bg-gray-100 text-gray-900 border-gray-200`;
6353
6940
  }
6354
6941
  stringifyPayload(payload, pretty) {
6355
6942
  try {
@@ -6396,6 +6983,13 @@ ${argsString}</pre
6396
6983
  static {
6397
6984
  this.styles = [(0, lit.unsafeCSS)(require_generated.default), lit.css`
6398
6985
  :host {
6986
+ --cpk-inspector-shell-radius: 5px;
6987
+ --cpk-inspector-surface-dark: #111319;
6988
+ --cpk-json-key: #3d408f;
6989
+ --cpk-json-str: #0b6b4c;
6990
+ --cpk-json-num: #8a5900;
6991
+ --cpk-json-bool: #c0333a;
6992
+ --cpk-json-nil: #57575b;
6399
6993
  position: fixed;
6400
6994
  top: 0;
6401
6995
  left: 0;
@@ -6405,6 +6999,194 @@ ${argsString}</pre
6405
6999
  font-family: "Plus Jakarta Sans", system-ui, sans-serif;
6406
7000
  }
6407
7001
 
7002
+ :host([data-color-scheme="dark"]),
7003
+ .inspector-window[data-color-scheme="dark"] {
7004
+ --cpk-json-key: #bec2ff;
7005
+ --cpk-json-str: #85ecce;
7006
+ --cpk-json-num: #ffac4d;
7007
+ --cpk-json-bool: #fa5f67;
7008
+ --cpk-json-nil: #afafb7;
7009
+ }
7010
+
7011
+ .cpk-json-token--key {
7012
+ color: var(--cpk-json-key);
7013
+ }
7014
+
7015
+ .cpk-json-token--str {
7016
+ color: var(--cpk-json-str);
7017
+ }
7018
+
7019
+ .cpk-json-token--num {
7020
+ color: var(--cpk-json-num);
7021
+ }
7022
+
7023
+ .cpk-json-token--bool {
7024
+ color: var(--cpk-json-bool);
7025
+ }
7026
+
7027
+ .cpk-json-token--nil {
7028
+ color: var(--cpk-json-nil);
7029
+ }
7030
+
7031
+ .cpk-json-block {
7032
+ margin: 0;
7033
+ padding: 10px 12px;
7034
+ border: 1px solid #dbdbe5;
7035
+ border-radius: 8px;
7036
+ background: #f7f7f9;
7037
+ font-family: "Spline Sans Mono", monospace;
7038
+ font-size: 12px;
7039
+ line-height: 1.65;
7040
+ white-space: pre-wrap;
7041
+ overflow-wrap: anywhere;
7042
+ word-break: normal;
7043
+ color: #010507;
7044
+ overflow: auto;
7045
+ }
7046
+
7047
+ :host([data-color-scheme="dark"]) .cpk-json-block,
7048
+ .inspector-window[data-color-scheme="dark"] .cpk-json-block {
7049
+ background: #111319;
7050
+ border-color: #343742;
7051
+ color: #f3f4f8;
7052
+ }
7053
+
7054
+ @keyframes cpk-playground-message-enter {
7055
+ from {
7056
+ opacity: 0;
7057
+ filter: blur(2px);
7058
+ transform: translateY(4px);
7059
+ }
7060
+ to {
7061
+ opacity: 1;
7062
+ filter: blur(0);
7063
+ transform: translateY(0);
7064
+ }
7065
+ }
7066
+
7067
+ @keyframes cpk-playground-thinking {
7068
+ 0%,
7069
+ 60%,
7070
+ 100% {
7071
+ opacity: 0.28;
7072
+ transform: translateY(0);
7073
+ }
7074
+ 30% {
7075
+ opacity: 1;
7076
+ transform: translateY(-2px);
7077
+ }
7078
+ }
7079
+
7080
+ .cpk-playground-root {
7081
+ container-type: inline-size;
7082
+ background: #fbfbfd !important;
7083
+ }
7084
+
7085
+ .cpk-playground-header {
7086
+ min-height: 58px;
7087
+ background: #f7f6fd !important;
7088
+ }
7089
+
7090
+ .cpk-playground-welcome {
7091
+ max-width: 560px;
7092
+ padding: 24px;
7093
+ }
7094
+
7095
+ .cpk-playground-welcome-title {
7096
+ color: #24242b;
7097
+ font-size: 15px;
7098
+ font-weight: 600;
7099
+ letter-spacing: -0.015em;
7100
+ }
7101
+
7102
+ .cpk-playground-composer {
7103
+ border: 1px solid #dcdce8;
7104
+ box-shadow:
7105
+ 0 8px 22px rgba(31, 23, 57, 0.08),
7106
+ 0 1px 2px rgba(31, 23, 57, 0.1);
7107
+ }
7108
+
7109
+ .cpk-playground-composer:focus-within {
7110
+ border-color: #aaa4d4;
7111
+ box-shadow:
7112
+ 0 10px 26px rgba(86, 53, 155, 0.13),
7113
+ 0 0 0 3px rgba(190, 194, 255, 0.3);
7114
+ }
7115
+
7116
+ .inspector-window[data-color-scheme="dark"] .cpk-playground-root,
7117
+ .inspector-window[data-color-scheme="dark"] .cpk-playground-header {
7118
+ background: #15171e !important;
7119
+ }
7120
+
7121
+ .inspector-window[data-color-scheme="dark"]
7122
+ .cpk-playground-welcome-title {
7123
+ color: #f3f4f8 !important;
7124
+ }
7125
+
7126
+ .inspector-window[data-color-scheme="dark"] .cpk-playground-composer {
7127
+ border-color: #464957;
7128
+ background: #15171e !important;
7129
+ box-shadow:
7130
+ 0 8px 22px rgba(0, 0, 0, 0.26),
7131
+ 0 1px 2px rgba(0, 0, 0, 0.36);
7132
+ }
7133
+
7134
+ .inspector-window[data-color-scheme="dark"]
7135
+ .cpk-playground-composer:focus-within {
7136
+ border-color: #777aae;
7137
+ box-shadow:
7138
+ 0 10px 26px rgba(0, 0, 0, 0.34),
7139
+ 0 0 0 3px rgba(102, 106, 158, 0.3);
7140
+ }
7141
+
7142
+ .cpk-playground-message-enter {
7143
+ animation: cpk-playground-message-enter 0.24s
7144
+ cubic-bezier(0.16, 1, 0.3, 1) both;
7145
+ }
7146
+
7147
+ .cpk-playground-thinking-dot {
7148
+ animation: cpk-playground-thinking 1.2s ease-in-out infinite;
7149
+ }
7150
+
7151
+ .cpk-playground-thinking-dot:nth-child(2) {
7152
+ animation-delay: 0.12s;
7153
+ }
7154
+
7155
+ .cpk-playground-thinking-dot:nth-child(3) {
7156
+ animation-delay: 0.24s;
7157
+ }
7158
+
7159
+ .cpk-playground-reasoning summary::-webkit-details-marker {
7160
+ display: none;
7161
+ }
7162
+
7163
+ .cpk-playground-reasoning[open] .cpk-playground-reasoning-chevron {
7164
+ transform: rotate(90deg);
7165
+ }
7166
+
7167
+ @container (max-width: 560px) {
7168
+ .cpk-playground-header {
7169
+ align-items: stretch;
7170
+ }
7171
+
7172
+ .cpk-playground-actions {
7173
+ width: 100%;
7174
+ }
7175
+
7176
+ .cpk-playground-thread-select {
7177
+ min-width: 0;
7178
+ max-width: none;
7179
+ flex: 1;
7180
+ }
7181
+ }
7182
+
7183
+ @media (prefers-reduced-motion: reduce) {
7184
+ .cpk-playground-message-enter,
7185
+ .cpk-playground-thinking-dot {
7186
+ animation: none;
7187
+ }
7188
+ }
7189
+
6408
7190
  .rounded-sm {
6409
7191
  border-radius: 3px;
6410
7192
  }
@@ -6464,6 +7246,10 @@ ${argsString}</pre
6464
7246
  box-sizing: border-box;
6465
7247
  transition:
6466
7248
  transform 300ms cubic-bezier(0.34, 1.56, 0.64, 1),
7249
+ scale 300ms cubic-bezier(0.34, 1.56, 0.64, 1),
7250
+ background-color 200ms ease,
7251
+ border-color 200ms ease,
7252
+ box-shadow 200ms ease,
6467
7253
  opacity 160ms ease;
6468
7254
  }
6469
7255
 
@@ -6491,6 +7277,7 @@ ${argsString}</pre
6491
7277
  touch-action: none;
6492
7278
  user-select: none;
6493
7279
  z-index: 60;
7280
+ background: transparent;
6494
7281
  }
6495
7282
 
6496
7283
  .edge-resize-handle {
@@ -6625,11 +7412,67 @@ ${argsString}</pre
6625
7412
  flex-shrink: 0;
6626
7413
  transition:
6627
7414
  background-color 0.15s,
6628
- border-color 0.15s;
7415
+ border-color 0.15s,
7416
+ color 0.15s;
7417
+ }
7418
+ .cpk-copy-btn:hover {
7419
+ background-color: #f0f0f4;
7420
+ border-color: #afafb7;
7421
+ }
7422
+
7423
+ .inspector-window[data-color-scheme="dark"] .cpk-copy-btn {
7424
+ background: #191c24;
7425
+ border-color: #3a3d49;
7426
+ color: #f3f4f8;
7427
+ }
7428
+
7429
+ .inspector-window[data-color-scheme="dark"] .cpk-copy-btn:hover {
7430
+ background: #20232d;
7431
+ border-color: #57575b;
7432
+ }
7433
+
7434
+ .inspector-sidebar[data-icon-rail="true"]
7435
+ .inspector-sidebar-agent-scope
7436
+ [data-context-dropdown-root="true"]
7437
+ > div {
7438
+ left: 100%;
7439
+ margin-inline-start: 8px;
7440
+ }
7441
+
7442
+ .inspector-icon-rail-menu {
7443
+ transform-origin: left center;
7444
+ opacity: 0;
7445
+ visibility: hidden;
7446
+ pointer-events: none;
7447
+ transform: translateX(-8px) scale(0.96);
7448
+ transition:
7449
+ opacity 180ms ease,
7450
+ transform 180ms ease,
7451
+ visibility 180ms ease;
7452
+ }
7453
+
7454
+ .inspector-icon-rail-menu[data-open="true"] {
7455
+ opacity: 1;
7456
+ visibility: visible;
7457
+ pointer-events: auto;
7458
+ transform: translateX(0) scale(1);
7459
+ }
7460
+
7461
+ @media (prefers-reduced-motion: reduce) {
7462
+ .inspector-icon-rail-menu {
7463
+ transition: none;
7464
+ }
6629
7465
  }
6630
- .cpk-copy-btn:hover {
6631
- background-color: #f0f0f4;
6632
- border-color: #afafb7;
7466
+
7467
+ .inspector-sidebar[data-icon-rail="true"]
7468
+ .inspector-sidebar-agent-scope
7469
+ [data-context-dropdown-root="true"]
7470
+ > div::before {
7471
+ content: "";
7472
+ position: absolute;
7473
+ inset-block: 0;
7474
+ inset-inline-end: 100%;
7475
+ width: 12px;
6633
7476
  }
6634
7477
 
6635
7478
  .cpk-section-header {
@@ -6637,6 +7480,9 @@ ${argsString}</pre
6637
7480
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
6638
7481
  padding: 10px 16px;
6639
7482
  }
7483
+ .inspector-window[data-color-scheme="dark"] .cpk-section-header {
7484
+ border-bottom-color: #3a3d49;
7485
+ }
6640
7486
  .cpk-section-header h4 {
6641
7487
  font-size: 11px;
6642
7488
  font-weight: 600;
@@ -6883,6 +7729,7 @@ ${argsString}</pre
6883
7729
  .console-button:hover {
6884
7730
  background-color: var(--cpk-launcher-face-solid) !important;
6885
7731
  border-color: rgba(190, 194, 255, 0.45) !important;
7732
+ transform: scale(1.05);
6886
7733
  }
6887
7734
  .console-button:focus-visible {
6888
7735
  outline-color: #bec2ff !important;
@@ -7231,6 +8078,12 @@ ${argsString}</pre
7231
8078
  .cpk-launcher-signal-wash {
7232
8079
  animation: none !important;
7233
8080
  }
8081
+ .console-button {
8082
+ transition: opacity 160ms ease;
8083
+ }
8084
+ .console-button:hover {
8085
+ transform: none;
8086
+ }
7234
8087
  }
7235
8088
 
7236
8089
  /* ── Launcher HUD: hover menu, quieter than the error island ── */
@@ -7242,6 +8095,9 @@ ${argsString}</pre
7242
8095
  }
7243
8096
 
7244
8097
  .cpk-launcher-hud {
8098
+ --hud-fill: var(--cpk-inspector-surface-dark);
8099
+ --hud-line: rgb(190 194 255 / 0.5);
8100
+ --hud-blur: blur(12px) saturate(1.2);
7245
8101
  position: absolute;
7246
8102
  top: 0;
7247
8103
  z-index: 4;
@@ -7275,38 +8131,47 @@ ${argsString}</pre
7275
8131
  }
7276
8132
 
7277
8133
  .cpk-launcher-hud__card {
7278
- --hud-fill: rgb(28 31 36 / 0.88);
7279
- --hud-line: rgb(190 194 255 / 0.5);
7280
8134
  position: relative;
7281
8135
  width: 228px;
7282
8136
  padding: 4px;
7283
8137
  border: 1px dotted var(--hud-line);
7284
- border-radius: 10px;
8138
+ border-radius: var(--cpk-inspector-shell-radius);
7285
8139
  background: var(--hud-fill);
7286
8140
  color: #fff;
7287
- backdrop-filter: blur(12px) saturate(1.2);
8141
+ backdrop-filter: var(--hud-blur);
8142
+ -webkit-backdrop-filter: var(--hud-blur);
7288
8143
  box-shadow: 0 8px 20px rgb(1 5 7 / 0.18);
7289
8144
  }
7290
8145
 
8146
+ .cpk-launcher-hud[data-color-scheme="light"] {
8147
+ --hud-fill: #fff;
8148
+ --hud-line: #d8d8e8;
8149
+ }
8150
+
8151
+ .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__card {
8152
+ color: #010507;
8153
+ }
8154
+
7291
8155
  .cpk-launcher-hud__arrow {
7292
8156
  position: absolute;
7293
8157
  top: calc(var(--cpk-launcher-size) / 2);
8158
+ z-index: 1;
7294
8159
  width: 10px;
7295
8160
  height: 10px;
7296
- background: var(--hud-fill);
8161
+ border: 0;
8162
+ /* The card frosts the page behind it, so it reads lighter than the
8163
+ raw fill. Mix a little white so the arrow matches the glass card
8164
+ without going lighter than the HUD. */
8165
+ background: color-mix(in srgb, var(--hud-fill) 88%, white 12%);
7297
8166
  transform: translateY(-50%) rotate(45deg);
7298
8167
  }
7299
8168
 
7300
8169
  .cpk-launcher-hud[data-cpk-hud-side="left"] .cpk-launcher-hud__arrow {
7301
- right: -5px;
7302
- border-top: 1px solid var(--hud-line);
7303
- border-right: 1px solid var(--hud-line);
8170
+ right: 9px;
7304
8171
  }
7305
8172
 
7306
8173
  .cpk-launcher-hud[data-cpk-hud-side="right"] .cpk-launcher-hud__arrow {
7307
- left: -5px;
7308
- border-bottom: 1px solid var(--hud-line);
7309
- border-left: 1px solid var(--hud-line);
8174
+ left: 9px;
7310
8175
  }
7311
8176
 
7312
8177
  .cpk-launcher-hud__list {
@@ -7340,6 +8205,14 @@ ${argsString}</pre
7340
8205
  background: rgb(255 255 255 / 0.06);
7341
8206
  }
7342
8207
 
8208
+ .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__row:hover,
8209
+ .cpk-launcher-hud[data-color-scheme="light"]
8210
+ .cpk-launcher-hud__row:focus-within,
8211
+ .cpk-launcher-hud[data-color-scheme="light"]
8212
+ .cpk-launcher-hud__row[data-cpk-hud-help="open"] {
8213
+ background: #f0f0f4;
8214
+ }
8215
+
7343
8216
  .cpk-launcher-hud__action {
7344
8217
  display: flex;
7345
8218
  gap: 8px;
@@ -7357,6 +8230,10 @@ ${argsString}</pre
7357
8230
  cursor: pointer;
7358
8231
  }
7359
8232
 
8233
+ .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__action {
8234
+ color: #010507;
8235
+ }
8236
+
7360
8237
  /* Stretch the row action over the whole tab, including the detail
7361
8238
  copy. The help mark sits above this layer. */
7362
8239
  .cpk-launcher-hud__action::after {
@@ -7400,6 +8277,10 @@ ${argsString}</pre
7400
8277
  line-height: 1;
7401
8278
  }
7402
8279
 
8280
+ .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__help {
8281
+ color: #68686e;
8282
+ }
8283
+
7403
8284
  .cpk-launcher-hud__help:focus-visible,
7404
8285
  .cpk-launcher-hud__action:focus-visible {
7405
8286
  outline: 2px solid #bec2ff;
@@ -7426,9 +8307,14 @@ ${argsString}</pre
7426
8307
  padding-bottom 200ms cubic-bezier(0.16, 1, 0.3, 1);
7427
8308
  }
7428
8309
 
8310
+ .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__detail {
8311
+ color: #68686e;
8312
+ }
8313
+
7429
8314
  .cpk-launcher-hud__row:hover .cpk-launcher-hud__detail,
7430
8315
  .cpk-launcher-hud__row:focus-within .cpk-launcher-hud__detail,
7431
- .cpk-launcher-hud__row[data-cpk-hud-help="open"] .cpk-launcher-hud__detail {
8316
+ .cpk-launcher-hud__row[data-cpk-hud-help="open"]
8317
+ .cpk-launcher-hud__detail {
7432
8318
  max-height: 72px;
7433
8319
  padding: 0 8px 7px;
7434
8320
  opacity: 1;
@@ -7442,6 +8328,98 @@ ${argsString}</pre
7442
8328
  }
7443
8329
  }
7444
8330
 
8331
+ /*
8332
+ * On mount, borrow the hover HUD for one short introduction. The card
8333
+ * establishes the destination first; its rows then resolve in order so
8334
+ * the eye can count the available features instead of receiving one
8335
+ * undifferentiated block. Only opacity and transform move.
8336
+ */
8337
+ @keyframes cpk-launcher-hud-intro {
8338
+ 0% {
8339
+ opacity: 0;
8340
+ transform: translateX(8px);
8341
+ }
8342
+ 8%,
8343
+ 88% {
8344
+ opacity: 1;
8345
+ transform: none;
8346
+ }
8347
+ 100% {
8348
+ opacity: 0;
8349
+ transform: translateX(4px);
8350
+ }
8351
+ }
8352
+
8353
+ @keyframes cpk-launcher-hud-intro-right {
8354
+ 0% {
8355
+ opacity: 0;
8356
+ transform: translateX(-8px);
8357
+ }
8358
+ 8%,
8359
+ 88% {
8360
+ opacity: 1;
8361
+ transform: none;
8362
+ }
8363
+ 100% {
8364
+ opacity: 0;
8365
+ transform: translateX(-4px);
8366
+ }
8367
+ }
8368
+
8369
+ @keyframes cpk-launcher-hud-row-online {
8370
+ from {
8371
+ opacity: 0;
8372
+ transform: translateY(4px);
8373
+ }
8374
+ to {
8375
+ opacity: 1;
8376
+ transform: none;
8377
+ }
8378
+ }
8379
+
8380
+ @keyframes cpk-launcher-hud-check-online {
8381
+ from {
8382
+ opacity: 0;
8383
+ transform: scale(0.65);
8384
+ }
8385
+ to {
8386
+ opacity: 1;
8387
+ transform: scale(1);
8388
+ }
8389
+ }
8390
+
8391
+ .cpk-launcher-hud[data-cpk-hud-intro="true"] {
8392
+ animation: cpk-launcher-hud-intro var(--cpk-launcher-hud-intro-duration)
8393
+ cubic-bezier(0.16, 1, 0.3, 1) both;
8394
+ }
8395
+
8396
+ .cpk-launcher-hud[data-cpk-hud-intro="true"][data-cpk-hud-side="right"] {
8397
+ animation-name: cpk-launcher-hud-intro-right;
8398
+ }
8399
+
8400
+ .cpk-launcher-hud[data-cpk-hud-intro="true"] .cpk-launcher-hud__row {
8401
+ animation: cpk-launcher-hud-row-online
8402
+ var(--cpk-launcher-hud-row-duration) cubic-bezier(0.16, 1, 0.3, 1)
8403
+ both;
8404
+ animation-delay: var(--cpk-hud-row-delay);
8405
+ }
8406
+
8407
+ .cpk-launcher-hud[data-cpk-hud-intro="true"] .cpk-launcher-hud__check {
8408
+ animation: cpk-launcher-hud-check-online 220ms
8409
+ cubic-bezier(0.16, 1, 0.3, 1) both;
8410
+ animation-delay: calc(var(--cpk-hud-row-delay) + 90ms);
8411
+ }
8412
+
8413
+ @media (prefers-reduced-motion: reduce) {
8414
+ .cpk-launcher-hud[data-cpk-hud-intro="true"],
8415
+ .cpk-launcher-hud[data-cpk-hud-intro="true"] .cpk-launcher-hud__row,
8416
+ .cpk-launcher-hud[data-cpk-hud-intro="true"] .cpk-launcher-hud__check {
8417
+ animation: none !important;
8418
+ opacity: 1;
8419
+ transform: none;
8420
+ }
8421
+ }
8422
+
7445
8423
  /*
7446
8424
  * Marker on the navigation entry, which is what keeps a signal alive
7447
8425
  * once the panel is open and the launcher is hidden. Static by design:
@@ -7468,7 +8446,7 @@ ${argsString}</pre
7468
8446
  /* ── Inspector window ────────────────────────────────────────── */
7469
8447
  .inspector-window {
7470
8448
  border: 1px solid #d8d8e8 !important;
7471
- border-radius: 5px !important;
8449
+ border-radius: var(--cpk-inspector-shell-radius) !important;
7472
8450
  box-shadow: none !important;
7473
8451
  }
7474
8452
 
@@ -7584,10 +8562,71 @@ ${argsString}</pre
7584
8562
  .inspector-sidebar[data-icon-rail="true"] .inspector-nav-control,
7585
8563
  .inspector-sidebar[data-icon-rail="true"] .inspector-sidebar-control,
7586
8564
  .inspector-sidebar[data-icon-rail="true"] .inspector-sidebar-toggle {
8565
+ box-sizing: border-box !important;
8566
+ width: 36px !important;
8567
+ height: 36px !important;
8568
+ min-width: 36px !important;
8569
+ min-height: 36px !important;
8570
+ justify-content: center !important;
8571
+ align-items: center !important;
8572
+ gap: 0 !important;
8573
+ padding: 0 !important;
8574
+ overflow: visible !important;
8575
+ }
8576
+ .inspector-sidebar[data-icon-rail="true"] .inspector-nav-icon,
8577
+ .inspector-sidebar[data-icon-rail="true"] .inspector-nav-icon svg,
8578
+ .inspector-sidebar[data-icon-rail="true"]
8579
+ .inspector-context-dropdown-icon,
8580
+ .inspector-sidebar[data-icon-rail="true"]
8581
+ .inspector-context-dropdown-icon
8582
+ svg,
8583
+ .inspector-sidebar[data-icon-rail="true"]
8584
+ .inspector-agent-placeholder
8585
+ svg {
8586
+ width: 18px !important;
8587
+ height: 18px !important;
8588
+ overflow: visible !important;
8589
+ }
8590
+ .inspector-sidebar[data-icon-rail="true"]
8591
+ .inspector-agent-selector
8592
+ > [data-context-dropdown-root="true"] {
8593
+ display: flex !important;
8594
+ flex: none !important;
8595
+ width: 36px !important;
8596
+ min-width: 36px !important;
8597
+ max-width: 36px !important;
7587
8598
  justify-content: center !important;
7588
8599
  align-items: center !important;
8600
+ }
8601
+ .inspector-sidebar[data-icon-rail="true"]
8602
+ .inspector-agent-selector
8603
+ > [data-context-dropdown-root="true"]
8604
+ > button,
8605
+ .inspector-sidebar[data-icon-rail="true"] .inspector-agent-placeholder {
8606
+ display: flex !important;
8607
+ width: 36px !important;
8608
+ height: 36px !important;
8609
+ min-width: 36px !important;
8610
+ min-height: 36px !important;
8611
+ max-width: 36px !important;
8612
+ align-items: center !important;
8613
+ justify-content: center !important;
7589
8614
  gap: 0 !important;
7590
- padding-inline: 0 !important;
8615
+ padding: 0 !important;
8616
+ transition:
8617
+ background-color 180ms ease,
8618
+ border-color 180ms ease,
8619
+ color 180ms ease !important;
8620
+ }
8621
+ .inspector-sidebar[data-icon-rail="true"]
8622
+ .inspector-context-dropdown-label,
8623
+ .inspector-sidebar[data-icon-rail="true"]
8624
+ .inspector-context-dropdown-chevron {
8625
+ display: none !important;
8626
+ width: 0 !important;
8627
+ min-width: 0 !important;
8628
+ flex: none !important;
8629
+ overflow: hidden !important;
7591
8630
  }
7592
8631
  .inspector-sidebar[data-icon-rail="true"] .inspector-nav-label,
7593
8632
  .inspector-sidebar[data-icon-rail="true"] .inspector-sidebar-label {
@@ -7817,7 +8856,10 @@ ${argsString}</pre
7817
8856
  clearTimeout(this.transitionTimeoutId);
7818
8857
  this.transitionTimeoutId = null;
7819
8858
  }
8859
+ this.clearIconRailContextCloseTimer();
7820
8860
  this.unsubscribeFromInspectorThreadBridge();
8861
+ this.stopIntelligenceStory();
8862
+ this.clearIntelligencePromptReset();
7821
8863
  this.threadsSetupPromptCopyGeneration += 1;
7822
8864
  if (this.threadsSetupPromptCopyResetTimeoutId !== null) {
7823
8865
  window.clearTimeout(this.threadsSetupPromptCopyResetTimeoutId);
@@ -7826,6 +8868,7 @@ ${argsString}</pre
7826
8868
  this.threadsSetupPromptCopyState = "idle";
7827
8869
  this.stopSignalPulse();
7828
8870
  this.cancelGestureTail();
8871
+ this.cancelLauncherHudIntro();
7829
8872
  this.cancelThreadRefreshDebounce();
7830
8873
  this.clearInspectorUsageRefresh();
7831
8874
  this.cleanupThreadsExampleOverviewVideo();
@@ -7862,6 +8905,7 @@ ${argsString}</pre
7862
8905
  else this.centerContext("window");
7863
8906
  this.ensureAnnouncementLoading();
7864
8907
  this.updateHostTransform(this.isOpen ? "window" : "button");
8908
+ this.scheduleLauncherHudIntro();
7865
8909
  }
7866
8910
  render() {
7867
8911
  return this.isOpen ? lit.html`
@@ -7885,6 +8929,7 @@ ${argsString}</pre
7885
8929
  this.maybeCompleteEventErrorView();
7886
8930
  this.flushErrorLandingScroll();
7887
8931
  this.maybeTrackHomeViewed();
8932
+ this.syncIntelligenceStory();
7888
8933
  if (!this.isOpen) {
7889
8934
  this.lastScrolledAgentNavigationLayout = null;
7890
8935
  return;
@@ -7924,8 +8969,6 @@ ${argsString}</pre
7924
8969
  "text-xs",
7925
8970
  "font-medium",
7926
8971
  "text-white",
7927
- "transition",
7928
- "hover:scale-105",
7929
8972
  "focus-visible:outline",
7930
8973
  "focus-visible:outline-2",
7931
8974
  "focus-visible:outline-offset-2",
@@ -8045,6 +9088,41 @@ ${argsString}</pre
8045
9088
  isLauncherHudBlocked() {
8046
9089
  return this.gestureSignal !== null;
8047
9090
  }
9091
+ scheduleLauncherHudIntro(delay = LAUNCHER_HUD_INTRO_MS.delay) {
9092
+ if (this.launcherHudIntroStartTimer !== null) clearTimeout(this.launcherHudIntroStartTimer);
9093
+ this.launcherHudIntroStartTimer = setTimeout(() => {
9094
+ this.launcherHudIntroStartTimer = null;
9095
+ if (!this.isConnected || this.isOpen) return;
9096
+ if (this.isLauncherHudBlocked()) {
9097
+ this.scheduleLauncherHudIntro(LAUNCHER_HUD_INTRO_MS.blockedRetry);
9098
+ return;
9099
+ }
9100
+ this.resolveLauncherHudSide();
9101
+ this.launcherHudIntro = true;
9102
+ this.launcherHudOpen = true;
9103
+ this.requestUpdate();
9104
+ this.launcherHudIntroEndTimer = setTimeout(() => {
9105
+ this.launcherHudIntroEndTimer = null;
9106
+ this.launcherHudIntro = false;
9107
+ this.launcherHudOpen = false;
9108
+ this.launcherHudHelp = null;
9109
+ this.requestUpdate();
9110
+ }, LAUNCHER_HUD_INTRO_MS.duration);
9111
+ }, delay);
9112
+ }
9113
+ cancelLauncherHudIntro() {
9114
+ if (this.launcherHudIntroStartTimer !== null) {
9115
+ clearTimeout(this.launcherHudIntroStartTimer);
9116
+ this.launcherHudIntroStartTimer = null;
9117
+ }
9118
+ if (this.launcherHudIntroEndTimer !== null) {
9119
+ clearTimeout(this.launcherHudIntroEndTimer);
9120
+ this.launcherHudIntroEndTimer = null;
9121
+ }
9122
+ if (!this.launcherHudIntro) return;
9123
+ this.launcherHudIntro = false;
9124
+ if (this.isConnected) this.requestUpdate();
9125
+ }
8048
9126
  resolveLauncherHudSide() {
8049
9127
  if (typeof window === "undefined") {
8050
9128
  this.launcherHudSide = "left";
@@ -8073,6 +9151,7 @@ ${argsString}</pre
8073
9151
  this.requestUpdate();
8074
9152
  }
8075
9153
  closeLauncherHud() {
9154
+ this.cancelLauncherHudIntro();
8076
9155
  if (this.launcherHudCloseTimer !== null) {
8077
9156
  clearTimeout(this.launcherHudCloseTimer);
8078
9157
  this.launcherHudCloseTimer = null;
@@ -8110,6 +9189,10 @@ ${argsString}</pre
8110
9189
  class="cpk-launcher-hud__row"
8111
9190
  data-cpk-hud-row=${args.id}
8112
9191
  data-cpk-hud-help=${helpOpen ? "open" : lit.nothing}
9192
+ style=${(0, lit_directives_style_map_js.styleMap)({
9193
+ "--cpk-hud-row-index": `${args.introIndex}`,
9194
+ "--cpk-hud-row-delay": `${LAUNCHER_HUD_INTRO_MS.rowStart + args.introIndex * LAUNCHER_HUD_INTRO_MS.rowStagger}ms`
9195
+ })}
8113
9196
  @click=${(event) => this.handleHudRowClick(event, args.id)}
8114
9197
  >
8115
9198
  <button
@@ -8139,23 +9222,31 @@ ${argsString}</pre
8139
9222
  }
8140
9223
  renderLauncherHud() {
8141
9224
  if (!this.launcherHudOpen) return lit.nothing;
8142
- const threadsOn = this.areThreadEndpointsAvailable();
8143
- const intelligenceOn = Boolean(this._core?.intelligence);
8144
- const learningOn = intelligenceOn && this._memoriesAvailable;
9225
+ const homeModel = this.getHomeModel();
9226
+ const threadsOn = homeModel.services.some((service) => service.id === "threads" && service.enabled);
9227
+ const learningOn = homeModel.services.some((service) => service.id === "memory" && service.enabled);
9228
+ const intelligenceOn = homeModel.hero.connection === "connected";
8145
9229
  return lit.html`
8146
9230
  <div
8147
9231
  class="cpk-launcher-hud"
8148
9232
  id="cpk-launcher-hud"
8149
9233
  data-cpk-launcher-hud
8150
9234
  data-cpk-hud-side=${this.launcherHudSide}
9235
+ data-cpk-hud-intro=${this.launcherHudIntro ? "true" : lit.nothing}
9236
+ data-color-scheme=${this.colorScheme}
9237
+ style=${(0, lit_directives_style_map_js.styleMap)({
9238
+ "--cpk-launcher-hud-intro-duration": `${LAUNCHER_HUD_INTRO_MS.duration}ms`,
9239
+ "--cpk-launcher-hud-row-duration": `${LAUNCHER_HUD_INTRO_MS.rowDuration}ms`
9240
+ })}
8151
9241
  >
9242
+ <span class="cpk-launcher-hud__arrow" aria-hidden="true"></span>
8152
9243
  <div class="cpk-launcher-hud__card">
8153
- <span class="cpk-launcher-hud__arrow" aria-hidden="true"></span>
8154
9244
  <ul class="cpk-launcher-hud__list" role="list">
8155
9245
  ${this.renderHudRow({
8156
9246
  id: "inspector",
8157
9247
  label: HUD_OPEN_INSPECTOR_LABEL,
8158
- detail: HUD_OPEN_INSPECTOR_DETAIL
9248
+ detail: HUD_OPEN_INSPECTOR_DETAIL,
9249
+ introIndex: 0
8159
9250
  })}
8160
9251
  </ul>
8161
9252
  <ul class="cpk-launcher-hud__list" role="list">
@@ -8163,19 +9254,22 @@ ${argsString}</pre
8163
9254
  id: "threads",
8164
9255
  label: threadsOn ? HUD_THREADS_ON_LABEL : HUD_THREADS_OFF_LABEL,
8165
9256
  detail: threadsOn ? HUD_THREADS_ON_DETAIL : HUD_THREADS_OFF_DETAIL,
8166
- connected: threadsOn
9257
+ connected: threadsOn,
9258
+ introIndex: 1
8167
9259
  })}
8168
9260
  ${this.renderHudRow({
8169
9261
  id: "intelligence",
8170
9262
  label: intelligenceOn ? HUD_INTELLIGENCE_ON_LABEL : HUD_INTELLIGENCE_OFF_LABEL,
8171
9263
  detail: intelligenceOn ? HUD_INTELLIGENCE_ON_DETAIL : HUD_INTELLIGENCE_OFF_DETAIL,
8172
- connected: intelligenceOn
9264
+ connected: intelligenceOn,
9265
+ introIndex: 2
8173
9266
  })}
8174
9267
  ${this.renderHudRow({
8175
9268
  id: "learning",
8176
9269
  label: learningOn ? HUD_LEARNING_ON_LABEL : HUD_LEARNING_OFF_LABEL,
8177
9270
  detail: learningOn ? HUD_LEARNING_ON_DETAIL : HUD_LEARNING_OFF_DETAIL,
8178
- connected: learningOn
9271
+ connected: learningOn,
9272
+ introIndex: 3
8179
9273
  })}
8180
9274
  </ul>
8181
9275
  </div>
@@ -8264,12 +9358,12 @@ ${argsString}</pre
8264
9358
  </span>
8265
9359
  <span class="inspector-nav-label">${item.label}</span>
8266
9360
  ${marker ? lit.html`
8267
- <span
8268
- class="inspector-nav-signal-dot"
8269
- data-cpk-signal-tone=${marker.tone}
8270
- aria-hidden="true"
8271
- ></span>
8272
- ` : lit.nothing}
9361
+ <span
9362
+ class="inspector-nav-signal-dot"
9363
+ data-cpk-signal-tone=${marker.tone}
9364
+ aria-hidden="true"
9365
+ ></span>
9366
+ ` : lit.nothing}
8273
9367
  </button>
8274
9368
  `;
8275
9369
  })}
@@ -8278,34 +9372,34 @@ ${argsString}</pre
8278
9372
  })}
8279
9373
  </nav>
8280
9374
  ${automaticallyCollapsed ? lit.nothing : lit.html`
8281
- <button
8282
- type="button"
8283
- class="inspector-sidebar-toggle"
8284
- data-inspector-sidebar-toggle
8285
- aria-label=${iconRail ? "Expand sidebar" : "Collapse sidebar"}
8286
- aria-expanded=${iconRail ? "false" : "true"}
8287
- data-inspector-tooltip=${iconRail ? "Expand sidebar" : lit.nothing}
8288
- title=${iconRail ? lit.nothing : "Collapse sidebar"}
8289
- style=${INTERACTIVE_FOCUS_BASE_STYLE}
8290
- @pointerenter=${iconRail ? this.handleSidebarRailTooltipShow : lit.nothing}
8291
- @pointerleave=${iconRail ? this.handleSidebarRailTooltipHide : lit.nothing}
8292
- @focus=${iconRail ? this.handleSidebarRailTooltipShow : lit.nothing}
8293
- @blur=${iconRail ? this.handleSidebarRailTooltipHide : lit.nothing}
8294
- @click=${this.handleSidebarToggle}
8295
- >
8296
- <span class="inspector-nav-icon" aria-hidden="true">
8297
- ${this.renderIcon(iconRail ? "ChevronRight" : "ChevronLeft")}
8298
- </span>
8299
- <span class="inspector-nav-label"
8300
- >${iconRail ? "Expand" : "Collapse"}</span
8301
- >
8302
- </button>
8303
- `}
8304
- ${iconRail ? lit.nothing : lit.html`
8305
9375
  <div class="inspector-sidebar-footer">
8306
- <div class="inspector-sidebar-status-list">
8307
- ${this.renderSidebarIntelligenceStatus(homeModel)}
8308
- </div>
9376
+ ${iconRail ? lit.nothing : lit.html`
9377
+ <div class="inspector-sidebar-status-list">
9378
+ ${this.renderSidebarIntelligenceStatus(homeModel)}
9379
+ </div>
9380
+ `}
9381
+ <button
9382
+ type="button"
9383
+ class="inspector-sidebar-toggle"
9384
+ data-inspector-sidebar-toggle
9385
+ aria-label=${iconRail ? "Expand sidebar" : "Collapse sidebar"}
9386
+ aria-expanded=${iconRail ? "false" : "true"}
9387
+ data-inspector-tooltip=${iconRail ? "Expand sidebar" : lit.nothing}
9388
+ title=${iconRail ? lit.nothing : "Collapse sidebar"}
9389
+ style=${INTERACTIVE_FOCUS_BASE_STYLE}
9390
+ @pointerenter=${iconRail ? this.handleSidebarRailTooltipShow : lit.nothing}
9391
+ @pointerleave=${iconRail ? this.handleSidebarRailTooltipHide : lit.nothing}
9392
+ @focus=${iconRail ? this.handleSidebarRailTooltipShow : lit.nothing}
9393
+ @blur=${iconRail ? this.handleSidebarRailTooltipHide : lit.nothing}
9394
+ @click=${this.handleSidebarToggle}
9395
+ >
9396
+ <span class="inspector-nav-icon" aria-hidden="true">
9397
+ ${this.renderIcon(iconRail ? "ChevronRight" : "ChevronLeft")}
9398
+ </span>
9399
+ <span class="inspector-nav-label"
9400
+ >${iconRail ? "Expand" : "Collapse"}</span
9401
+ >
9402
+ </button>
8309
9403
  </div>
8310
9404
  `}
8311
9405
  </aside>
@@ -8510,23 +9604,37 @@ ${argsString}</pre
8510
9604
  const connected = model.hero.connection === "connected";
8511
9605
  const action = model.hero.action;
8512
9606
  const renewing = action?.kind === "renew";
9607
+ const installing = !connected && !renewing;
8513
9608
  return lit.html`
8514
9609
  <section
8515
9610
  class="inspector-home-section inspector-intelligence-hud"
8516
9611
  data-inspector-home-card="intelligence"
8517
9612
  data-state=${connected ? "connected" : "disconnected"}
9613
+ data-mode=${connected ? "connected" : renewing ? "renew" : "install"}
8518
9614
  aria-label="Intelligence ${connected ? "connected" : renewing ? "plan expired" : "not enabled"}"
8519
9615
  >
8520
9616
  <header class="inspector-intelligence-hud-header">
8521
9617
  <div class="inspector-intelligence-hud-heading">
8522
9618
  <h2 class="inspector-home-section-title">
9619
+ ${installing ? lit.html`
9620
+ <img
9621
+ class="inspector-intelligence-mark"
9622
+ src=${require_inspector_logo_kite.default}
9623
+ alt=""
9624
+ aria-hidden="true"
9625
+ />
9626
+ ` : lit.nothing}
8523
9627
  ${connected ? "Intelligence" : model.hero.title}
8524
9628
  </h2>
8525
- ${connected ? lit.nothing : lit.html`
8526
- <p class="inspector-intelligence-hud-description">
8527
- ${model.hero.body}
8528
- </p>
8529
- `}
9629
+ ${connected ? lit.nothing : installing ? lit.html`
9630
+ <p class="inspector-intelligence-sr-summary">
9631
+ ${model.hero.body}
9632
+ </p>
9633
+ ` : lit.html`
9634
+ <p class="inspector-intelligence-hud-description">
9635
+ ${model.hero.body}
9636
+ </p>
9637
+ `}
8530
9638
  </div>
8531
9639
  <div class="inspector-intelligence-hud-header-actions">
8532
9640
  ${connected || renewing ? lit.html`
@@ -8538,7 +9646,7 @@ ${argsString}</pre
8538
9646
  ${connected ? "Connected" : "Plan expired"}
8539
9647
  </span>
8540
9648
  ` : lit.nothing}
8541
- ${!connected && action ? lit.html`
9649
+ ${renewing && action ? lit.html`
8542
9650
  <a
8543
9651
  class="inspector-intelligence-hud-action inspector-intelligence-hud-connect-action"
8544
9652
  data-inspector-home-intelligence-action=${action.kind}
@@ -8552,9 +9660,18 @@ ${argsString}</pre
8552
9660
  ${action.label} ${this.renderIcon("ArrowUpRight")}
8553
9661
  </a>
8554
9662
  ` : lit.nothing}
9663
+ ${installing ? this.renderIntelligenceInstallActions(action) : lit.nothing}
8555
9664
  </div>
8556
9665
  </header>
8557
9666
 
9667
+ ${installing && this.promptCopyState === "failed" ? lit.html`
9668
+ <code
9669
+ class="inspector-intelligence-install-fallback"
9670
+ tabindex="0"
9671
+ >${require_onboarding_prompt.createOnboardingPrompt(this.getOnboardingRunId())}</code
9672
+ >
9673
+ ` : lit.nothing}
9674
+ ${installing ? this.renderIntelligenceStory() : lit.nothing}
8558
9675
  ${connected ? lit.html`
8559
9676
  <div
8560
9677
  class="inspector-intelligence-hud-details"
@@ -8837,24 +9954,394 @@ ${argsString}</pre
8837
9954
  data-feature-state-group="available"
8838
9955
  aria-label="Available features"
8839
9956
  >
8840
- <header class="inspector-home-feature-group-header">
8841
- <strong>Available</strong>
8842
- <span>${disabledServices.length}</span>
8843
- </header>
8844
- <div class="inspector-home-feature-list">
8845
- ${disabledServices.length > 0 ? disabledServices.map(renderService) : lit.html`
8846
- <p class="inspector-home-feature-group-empty">Everything is active</p>
8847
- `}
8848
- </div>
8849
- </section>
8850
- </div>
8851
- `}
8852
- </section>
9957
+ <header class="inspector-home-feature-group-header">
9958
+ <strong>Available</strong>
9959
+ <span>${disabledServices.length}</span>
9960
+ </header>
9961
+ <div class="inspector-home-feature-list">
9962
+ ${disabledServices.length > 0 ? disabledServices.map(renderService) : lit.html`
9963
+ <p class="inspector-home-feature-group-empty">Everything is active</p>
9964
+ `}
9965
+ </div>
9966
+ </section>
9967
+ </div>
9968
+ `}
9969
+ </section>
9970
+ `;
9971
+ }
9972
+ handleHomeHeroCta(action) {
9973
+ if (this.core?.telemetryDisabled) return;
9974
+ require_telemetry.trackHomeCtaClicked({ action_kind: action.kind });
9975
+ }
9976
+ /**
9977
+ * The install row: copy the prompt, or fall back to the signup page.
9978
+ *
9979
+ * The prompt is primary and the link is secondary, which is the inversion
9980
+ * this card exists for. Leaving for a signup page is where developers drop
9981
+ * out; pasting into the editor they are already in is not.
9982
+ *
9983
+ * No third-party coding-agent logos here, unlike the Intelligence app. That
9984
+ * app is a private hosted surface; this one is a published npm package
9985
+ * embedded in other people's sites, and shipping Anthropic's and OpenAI's
9986
+ * marks inside it is a trademark call that is not ours to make quietly. The
9987
+ * helper line names the agents in text instead.
9988
+ */
9989
+ renderIntelligenceInstallActions(action) {
9990
+ const copied = this.promptCopyState === "copied";
9991
+ const failed = this.promptCopyState === "failed";
9992
+ return lit.html`
9993
+ <div
9994
+ class="inspector-intelligence-install"
9995
+ data-copy-state=${this.promptCopyState}
9996
+ >
9997
+ ${this.promptCopyState === "idle" ? action ? lit.html`
9998
+ <a
9999
+ class="inspector-intelligence-install-secondary"
10000
+ data-inspector-home-intelligence-action=${action.kind}
10001
+ href=${action.url}
10002
+ target="_blank"
10003
+ rel="noopener noreferrer"
10004
+ aria-label="Set Intelligence up yourself (opens in a new tab)"
10005
+ style=${INTERACTIVE_FOCUS_BASE_STYLE}
10006
+ @click=${() => this.handleHomeHeroCta(action)}
10007
+ >
10008
+ Set it up yourself ${this.renderIcon("ArrowUpRight")}
10009
+ </a>
10010
+ ` : lit.nothing : lit.html`
10011
+ <p
10012
+ class="inspector-intelligence-install-hint"
10013
+ data-tone=${failed ? "error" : "success"}
10014
+ role="status"
10015
+ >
10016
+ ${failed ? "Clipboard blocked — copy the prompt below." : "Paste it into your coding agent."}
10017
+ </p>
10018
+ `}
10019
+ <button
10020
+ type="button"
10021
+ class="inspector-intelligence-hud-action inspector-intelligence-install-copy"
10022
+ data-inspector-intelligence-copy-prompt
10023
+ aria-label=${copied ? "Install prompt copied to clipboard. Paste it into your coding agent." : "Copy the Intelligence install prompt"}
10024
+ style=${INTERACTIVE_FOCUS_BASE_STYLE}
10025
+ @click=${this.handleIntelligencePromptCopy}
10026
+ >
10027
+ ${this.renderIcon(copied ? "Check" : "ClipboardCopy")}
10028
+ ${copied ? "Prompt copied" : "Copy setup prompt"}
10029
+ </button>
10030
+ </div>
10031
+ `;
10032
+ }
10033
+ /** One run id per element lifetime; minted on first use, never rotated. */
10034
+ getOnboardingRunId() {
10035
+ this.onboardingRunId ??= require_onboarding_prompt.createOnboardingRunId();
10036
+ return this.onboardingRunId;
10037
+ }
10038
+ /**
10039
+ * Return the button and its secondary line to the idle state.
10040
+ *
10041
+ * Long enough to read six words, short enough that a developer who went to
10042
+ * their editor and came back — because the paste went somewhere wrong, or
10043
+ * the terminal is gone — finds a button that plainly invites a second press
10044
+ * rather than a spent one wearing a checkmark.
10045
+ *
10046
+ * Only the copied state resets. A failed copy has the prompt on screen for
10047
+ * manual selection, and yanking that away mid-drag would be worse than the
10048
+ * clipboard failing in the first place.
10049
+ */
10050
+ scheduleIntelligencePromptReset() {
10051
+ this.clearIntelligencePromptReset();
10052
+ this.promptCopyResetTimer = setTimeout(() => {
10053
+ this.promptCopyResetTimer = null;
10054
+ if (!this.isConnected || this.promptCopyState !== "copied") return;
10055
+ this.promptCopyState = "idle";
10056
+ this.requestUpdate();
10057
+ }, PROMPT_COPY_RESET_MS);
10058
+ }
10059
+ clearIntelligencePromptReset() {
10060
+ if (this.promptCopyResetTimer !== null) {
10061
+ clearTimeout(this.promptCopyResetTimer);
10062
+ this.promptCopyResetTimer = null;
10063
+ }
10064
+ }
10065
+ /**
10066
+ * The three-beat Intelligence story.
10067
+ *
10068
+ * Every beat is in the DOM at all times and switched by opacity, so the
10069
+ * strip never reflows and screen readers get one stable structure. The
10070
+ * caption is the live text; the beats themselves are decorative and hidden
10071
+ * from assistive tech, because reading out a mocked code listing helps
10072
+ * nobody.
10073
+ */
10074
+ /**
10075
+ * The rotating argument, paired to whatever the picture below is showing.
10076
+ *
10077
+ * Hidden from assistive tech: a sentence that replaces itself every few
10078
+ * seconds is noise in a screen reader, so the stable summary above carries
10079
+ * the message there instead. Both sentences are always in the DOM and only
10080
+ * their opacity changes, so the block cannot reflow and the card never jumps
10081
+ * height mid-loop.
10082
+ */
10083
+ /**
10084
+ * Where a slide sits relative to the one on screen.
10085
+ *
10086
+ * This is what makes the motion agree with the rail: the rail reads left to
10087
+ * right, so a slide that has not been reached yet waits to the right, and one
10088
+ * already passed leaves to the left. Deriving it from the indices rather than
10089
+ * remembering a direction means clicking backwards through the tabs animates
10090
+ * backwards for free, with no state to keep in sync. The loop's wrap from the
10091
+ * last tab to the first therefore reads as a rewind, which is what it is.
10092
+ */
10093
+ intelligenceSlidePosition(index) {
10094
+ if (index === this.intelStoryBeat) return "active";
10095
+ return index < this.intelStoryBeat ? "before" : "after";
10096
+ }
10097
+ /** Same rule, addressed by beat id, for the picture halves. */
10098
+ intelligenceBeatPosition(beatId) {
10099
+ return this.intelligenceSlidePosition(INTELLIGENCE_STORY_BEATS.findIndex((beat) => beat.id === beatId));
10100
+ }
10101
+ renderIntelligenceStoryCopy() {
10102
+ return lit.html`
10103
+ <div
10104
+ class="inspector-intelligence-copy"
10105
+ data-inspector-intelligence-copy
10106
+ data-beat=${INTELLIGENCE_STORY_BEATS[this.intelStoryBeat]?.id ?? "threads"}
10107
+ aria-hidden="true"
10108
+ >
10109
+ ${INTELLIGENCE_STORY_BEATS.map((beat, index) => lit.html`
10110
+ <div
10111
+ class="inspector-intelligence-copy-slide"
10112
+ data-beat-id=${beat.id}
10113
+ data-active=${index === this.intelStoryBeat}
10114
+ data-position=${this.intelligenceSlidePosition(index)}
10115
+ >
10116
+ <strong>${beat.lead}</strong>
10117
+ <span>${beat.support}</span>
10118
+ </div>
10119
+ `)}
10120
+ </div>
10121
+ `;
10122
+ }
10123
+ renderIntelligenceStory() {
10124
+ return lit.html`
10125
+ <section
10126
+ class="inspector-intelligence-story"
10127
+ data-inspector-intelligence-story
10128
+ data-beat=${INTELLIGENCE_STORY_BEATS[this.intelStoryBeat]?.id ?? "threads"}
10129
+ >
10130
+ ${this.renderIntelligenceStoryCopy()}
10131
+ <div class="inspector-intelligence-story-stage" aria-hidden="true">
10132
+ ${this.renderIntelligenceStoryThreads()}
10133
+ ${this.renderIntelligenceStoryLearning()}
10134
+ ${this.renderIntelligenceStorySkill()}
10135
+ ${this.renderIntelligenceStoryReuse()}
10136
+ </div>
10137
+ <div
10138
+ class="inspector-intelligence-story-rail"
10139
+ role="tablist"
10140
+ aria-label="What Intelligence adds"
10141
+ >
10142
+ ${INTELLIGENCE_STORY_BEATS.map((beat, index) => lit.html`
10143
+ <button
10144
+ type="button"
10145
+ role="tab"
10146
+ class="inspector-intelligence-story-tab"
10147
+ aria-selected=${index === this.intelStoryBeat}
10148
+ data-active=${index === this.intelStoryBeat}
10149
+ style=${INTERACTIVE_FOCUS_BASE_STYLE}
10150
+ @click=${() => this.pinIntelligenceStoryBeat(index)}
10151
+ >
10152
+ ${beat.label}
10153
+ </button>
10154
+ `)}
10155
+ </div>
10156
+ </section>
10157
+ `;
10158
+ }
10159
+ /** Beat 1 — the developer's own users' conversations, one of them broken. */
10160
+ renderIntelligenceStoryThreads() {
10161
+ return lit.html`
10162
+ <div
10163
+ class="inspector-intelligence-beat"
10164
+ data-beat-id="threads"
10165
+ data-position=${this.intelligenceBeatPosition("threads")}
10166
+ >
10167
+ <div class="inspector-intelligence-threads">
10168
+ ${INTELLIGENCE_STORY_THREADS.map((thread, index) => lit.html`
10169
+ <span
10170
+ class="inspector-intelligence-thread"
10171
+ data-failed=${thread.failed}
10172
+ style="--thread-index:${index}"
10173
+ >
10174
+ <i></i>
10175
+ <strong>${thread.title}</strong>
10176
+ <small>${thread.meta}</small>
10177
+ </span>
10178
+ `)}
10179
+ </div>
10180
+ </div>
10181
+ `;
10182
+ }
10183
+ renderIntelligenceStoryLearning() {
10184
+ return lit.html`
10185
+ <div
10186
+ class="inspector-intelligence-beat"
10187
+ data-beat-id="learning"
10188
+ data-position=${this.intelligenceBeatPosition("learning")}
10189
+ >
10190
+ <div class="inspector-intelligence-beat-col">
10191
+ <span class="inspector-intelligence-beat-label">
10192
+ Signals from ${INTELLIGENCE_STORY_SIGNALS.length} threads
10193
+ </span>
10194
+ ${INTELLIGENCE_STORY_SIGNALS.map((signal, index) => lit.html`
10195
+ <span
10196
+ class="inspector-intelligence-signal"
10197
+ style="--signal-index:${index}"
10198
+ >${signal}</span
10199
+ >
10200
+ `)}
10201
+ </div>
10202
+ <div class="inspector-intelligence-beat-flow">
10203
+ ${this.renderIcon("ArrowRight")}
10204
+ </div>
10205
+ <div class="inspector-intelligence-beat-col">
10206
+ <span class="inspector-intelligence-beat-label">
10207
+ Reusable pattern
10208
+ </span>
10209
+ ${INTELLIGENCE_STORY_RULES.map((rule, index) => lit.html`
10210
+ <span
10211
+ class="inspector-intelligence-rule"
10212
+ style="--rule-index:${index}"
10213
+ >
10214
+ <i>${this.renderIcon("Check")}</i>${rule}
10215
+ </span>
10216
+ `)}
10217
+ </div>
10218
+ </div>
10219
+ `;
10220
+ }
10221
+ renderIntelligenceStorySkill() {
10222
+ return lit.html`
10223
+ <div
10224
+ class="inspector-intelligence-beat"
10225
+ data-beat-id="skill"
10226
+ data-position=${this.intelligenceBeatPosition("skill")}
10227
+ >
10228
+ <div class="inspector-intelligence-skill-file">
10229
+ <header>
10230
+ ${this.renderIcon("FileText")}
10231
+ <strong>${INTELLIGENCE_STORY_SKILL_FILE}</strong>
10232
+ <em>Pending review</em>
10233
+ </header>
10234
+ <div class="inspector-intelligence-skill-code">
10235
+ <span data-line="1"><b># Meeting scheduling</b></span>
10236
+ <span data-line="2">When planning a meeting:</span>
10237
+ ${INTELLIGENCE_STORY_RULES.map((rule, index) => lit.html`
10238
+ <span data-line=${index + 3} style="--rule-index:${index}"
10239
+ >${index + 1}. ${rule}</span
10240
+ >
10241
+ `)}
10242
+ </div>
10243
+ </div>
10244
+ </div>
8853
10245
  `;
8854
10246
  }
8855
- handleHomeHeroCta(action) {
8856
- if (this.core?.telemetryDisabled) return;
8857
- require_telemetry.trackHomeCtaClicked({ action_kind: action.kind });
10247
+ renderIntelligenceStoryReuse() {
10248
+ return lit.html`
10249
+ <div
10250
+ class="inspector-intelligence-beat"
10251
+ data-beat-id="intelligence"
10252
+ data-position=${this.intelligenceBeatPosition("intelligence")}
10253
+ >
10254
+ <div class="inspector-intelligence-chain">
10255
+ ${INTELLIGENCE_STORY_CHAIN.map((step, index) => lit.html`
10256
+ <span
10257
+ class="inspector-intelligence-chain-step"
10258
+ style="--step-index:${index}"
10259
+ >
10260
+ <i>${this.renderIcon(step.icon)}</i>
10261
+ <strong>${step.name}</strong>
10262
+ <small>${step.detail}</small>
10263
+ </span>
10264
+ ${index === INTELLIGENCE_STORY_CHAIN.length - 1 ? lit.nothing : lit.html`
10265
+ <span
10266
+ class="inspector-intelligence-chain-arrow"
10267
+ style="--step-index:${index}"
10268
+ >${this.renderIcon("ChevronRight")}</span
10269
+ >
10270
+ `}
10271
+ `)}
10272
+ </div>
10273
+ <span class="inspector-intelligence-chain-proof">
10274
+ ${this.renderIcon("Sparkles")} Next run starts with
10275
+ <code>${INTELLIGENCE_STORY_SKILL_FILE}</code>
10276
+ </span>
10277
+ </div>
10278
+ `;
10279
+ }
10280
+ /** A press pins that beat and stops the loop; the developer is now driving. */
10281
+ pinIntelligenceStoryBeat(index) {
10282
+ this.intelStoryUserPinned = true;
10283
+ this.intelStoryBeat = index;
10284
+ this.stopIntelligenceStory();
10285
+ this.requestUpdate();
10286
+ if (!this.core?.telemetryDisabled) {
10287
+ const beat = INTELLIGENCE_STORY_BEATS[index];
10288
+ if (beat) require_telemetry.trackHomeStoryBeatSelected({
10289
+ beat: beat.id,
10290
+ beat_index: index
10291
+ });
10292
+ }
10293
+ }
10294
+ /**
10295
+ * Advance the story only while it is actually on screen.
10296
+ *
10297
+ * Gated on the panel being open, Home being the visible tab, settings being
10298
+ * closed and the document being visible. Anything less and a debugging tool
10299
+ * would be holding a repeating timer behind a closed panel.
10300
+ */
10301
+ syncIntelligenceStory() {
10302
+ if (!(this.isOpen && !this.settingsOpen && this.selectedMenu === "home" && !this._core?.intelligence && typeof document !== "undefined" && document.visibilityState !== "hidden")) {
10303
+ this.intelStoryUserPinned = false;
10304
+ this.stopIntelligenceStory();
10305
+ return;
10306
+ }
10307
+ if (this.intelStoryUserPinned || this.prefersReducedMotion()) {
10308
+ this.stopIntelligenceStory();
10309
+ return;
10310
+ }
10311
+ if (this.intelStoryTimer !== null) return;
10312
+ const advance = () => {
10313
+ const current = INTELLIGENCE_STORY_BEATS[this.intelStoryBeat];
10314
+ this.intelStoryTimer = setTimeout(() => {
10315
+ this.intelStoryTimer = null;
10316
+ if (!this.isConnected) return;
10317
+ this.intelStoryBeat = (this.intelStoryBeat + 1) % INTELLIGENCE_STORY_BEATS.length;
10318
+ this.requestUpdate();
10319
+ advance();
10320
+ }, current?.duration ?? 3800);
10321
+ };
10322
+ advance();
10323
+ }
10324
+ stopIntelligenceStory() {
10325
+ if (this.intelStoryTimer !== null) {
10326
+ clearTimeout(this.intelStoryTimer);
10327
+ this.intelStoryTimer = null;
10328
+ }
10329
+ }
10330
+ /**
10331
+ * Reduced motion parks the story on the closing beat.
10332
+ *
10333
+ * That beat is the whole argument in one static frame, so a developer who
10334
+ * asked their OS for less motion still gets the point rather than a
10335
+ * fragment of it.
10336
+ */
10337
+ prefersReducedMotion() {
10338
+ if (typeof window === "undefined" || !window.matchMedia) return false;
10339
+ this.intelStoryReducedMotion ??= window.matchMedia("(prefers-reduced-motion: reduce)");
10340
+ if (this.intelStoryReducedMotion.matches) {
10341
+ this.intelStoryBeat = INTELLIGENCE_STORY_BEATS.length - 1;
10342
+ return true;
10343
+ }
10344
+ return false;
8858
10345
  }
8859
10346
  maybeTrackHomeViewed() {
8860
10347
  if (this.selectedMenu !== "home" || this.settingsOpen || !this.isOpen) return;
@@ -9068,16 +10555,6 @@ ${argsString}</pre
9068
10555
  @pointerup=${this.handleResizePointerUp}
9069
10556
  @pointercancel=${this.handleResizePointerCancel}
9070
10557
  ></div>
9071
- <div
9072
- 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"
9073
- data-resize-edge="sw"
9074
- role="presentation"
9075
- aria-hidden="true"
9076
- @pointerdown=${this.handleResizePointerDown}
9077
- @pointermove=${this.handleResizePointerMove}
9078
- @pointerup=${this.handleResizePointerUp}
9079
- @pointercancel=${this.handleResizePointerCancel}
9080
- ></div>
9081
10558
  `}
9082
10559
  <div
9083
10560
  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"
@@ -9669,11 +11146,8 @@ ${argsString}</pre
9669
11146
  return this.sanitizeForLogging(payload);
9670
11147
  }
9671
11148
  normalizeMessageContent(content) {
9672
- if (typeof content === "string") return content;
9673
- if (content && typeof content === "object" && "text" in content) {
9674
- const maybeText = content.text;
9675
- if (typeof maybeText === "string") return maybeText;
9676
- }
11149
+ const extracted = textFromUnknownContent(content);
11150
+ if (extracted) return extracted;
9677
11151
  if (content === null || content === void 0) return "";
9678
11152
  if (typeof content === "object") try {
9679
11153
  return JSON.stringify(this.sanitizeForLogging(content));
@@ -9874,6 +11348,24 @@ ${argsString}</pre
9874
11348
  });
9875
11349
  return mapped;
9876
11350
  }
11351
+ async loadThreadSnapshot(thread) {
11352
+ const core = this._core;
11353
+ if (!core?.runtimeUrl) throw new Error("Failed to load thread.");
11354
+ const baseUrl = core.runtimeUrl.replace(/\/+$/, "");
11355
+ const encodedThreadId = encodeURIComponent(thread.id);
11356
+ const [messagesResponse, stateResponse] = await Promise.all([fetch(`${baseUrl}/threads/${encodedThreadId}/messages`, { headers: { ...core.headers } }), fetch(`${baseUrl}/threads/${encodedThreadId}/state`, { headers: { ...core.headers } })]);
11357
+ if (!messagesResponse.ok) throw new Error(`Failed to load thread (HTTP ${messagesResponse.status}).`);
11358
+ const messagesBody = await messagesResponse.json();
11359
+ const stateBody = stateResponse.ok ? await stateResponse.json() : { state: {} };
11360
+ return {
11361
+ messages: this.mapThreadMessagesToPlayground(messagesBody.messages ?? []),
11362
+ state: stateBody.state ?? {}
11363
+ };
11364
+ }
11365
+ applyThreadSnapshotToPlayground(thread, snapshot) {
11366
+ this.startPlaygroundSession(false, snapshot.messages, snapshot.state, thread.agentId);
11367
+ this.playgroundSourceThreadId = thread.id;
11368
+ }
9877
11369
  sendPlaygroundMessage(content) {
9878
11370
  if (!content || this.playgroundIsRunning || this.playgroundIsLoadingThread) return;
9879
11371
  const selectedAgentId = this.resolvePlaygroundAgentId(this.selectedContext);
@@ -9893,39 +11385,39 @@ ${argsString}</pre
9893
11385
  const sendDisabled = !agentId || this.playgroundIsLoadingThread || !this.playgroundIsRunning && !this.playgroundInput.trim();
9894
11386
  return lit.html`
9895
11387
  <form
9896
- class=${centered ? "mt-5 w-full" : "bg-white px-3 pb-3 pt-1.5"}
11388
+ class=${centered ? "cpk-playground-form mt-5 w-full" : "cpk-playground-form bg-white px-3 pb-3 pt-1.5"}
9897
11389
  @submit=${this.handlePlaygroundSubmit}
9898
11390
  >
9899
11391
  ${this.playgroundError ? lit.html`<div
9900
- class="mx-auto mb-2 flex max-w-3xl items-start gap-2 rounded-lg border border-rose-200 bg-rose-50 px-2.5 py-2 text-[10px] text-rose-950"
9901
- role="alert"
9902
- data-playground-error
11392
+ class="mx-auto mb-2 flex max-w-3xl items-start gap-2 rounded-lg border border-rose-200 bg-rose-50 px-2.5 py-2 text-[10px] text-rose-950"
11393
+ role="alert"
11394
+ data-playground-error
11395
+ >
11396
+ <span class="mt-0.5 shrink-0"
11397
+ >${this.renderIcon("TriangleAlert")}</span
9903
11398
  >
9904
- <span class="mt-0.5 shrink-0"
9905
- >${this.renderIcon("TriangleAlert")}</span
9906
- >
9907
- <div class="min-w-0 flex-1">
9908
- <p class="font-semibold">Agent run failed</p>
9909
- <p class="mt-0.5 break-words leading-relaxed">
9910
- ${this.playgroundError}
9911
- </p>
9912
- </div>
9913
- ${hasRetry ? lit.html`
9914
- <button
9915
- type="button"
9916
- class="shrink-0 rounded-md border border-rose-200 bg-white px-2 py-1 font-medium text-rose-700 transition hover:bg-rose-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-rose-300 focus-visible:ring-offset-1 disabled:opacity-50"
9917
- ?disabled=${busy}
9918
- @click=${this.handlePlaygroundRetry}
9919
- >
9920
- Retry
9921
- </button>
9922
- ` : lit.nothing}
9923
- </div>` : lit.nothing}
11399
+ <div class="min-w-0 flex-1">
11400
+ <p class="font-semibold">Agent run failed</p>
11401
+ <p class="mt-0.5 break-words leading-relaxed">
11402
+ ${this.playgroundError}
11403
+ </p>
11404
+ </div>
11405
+ ${hasRetry ? lit.html`
11406
+ <button
11407
+ type="button"
11408
+ class="shrink-0 rounded-md border border-rose-200 bg-white px-2 py-1 font-medium text-rose-700 transition hover:bg-rose-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-rose-300 focus-visible:ring-offset-1 disabled:opacity-50"
11409
+ ?disabled=${busy}
11410
+ @click=${this.handlePlaygroundRetry}
11411
+ >
11412
+ Retry
11413
+ </button>
11414
+ ` : lit.nothing}
11415
+ </div>` : lit.nothing}
9924
11416
  <div
9925
- 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]"
11417
+ 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]"
9926
11418
  >
9927
11419
  <textarea
9928
- 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"
11420
+ 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"
9929
11421
  rows="1"
9930
11422
  placeholder=${placeholder}
9931
11423
  aria-label="Playground message"
@@ -9936,7 +11428,7 @@ ${argsString}</pre
9936
11428
  ></textarea>
9937
11429
  <button
9938
11430
  type=${this.playgroundIsRunning ? "button" : "submit"}
9939
- 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"}`}
11431
+ 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"}`}
9940
11432
  aria-label=${this.playgroundIsRunning ? "Stop agent" : "Send playground message"}
9941
11433
  ?disabled=${sendDisabled}
9942
11434
  @click=${this.playgroundIsRunning ? this.handlePlaygroundStop : lit.nothing}
@@ -10008,31 +11500,41 @@ ${argsString}</pre
10008
11500
  class="h-3 w-px shrink-0 bg-gray-200"
10009
11501
  aria-hidden="true"
10010
11502
  ></span>
10011
- <span class="truncate" title=${runtimeLabel}>${runtimeLabel}</span>
11503
+ <span class="truncate" title=${runtimeLabel}
11504
+ >${runtimeLabel}</span
11505
+ >
10012
11506
  </div>
10013
11507
  </div>
10014
11508
  <div
10015
11509
  class="cpk-playground-actions ml-auto flex min-w-0 items-center gap-2"
10016
11510
  >
10017
11511
  ${sourceThreads.length > 0 ? lit.html`
10018
- <label class="sr-only" for="cpk-playground-thread-source"
10019
- >Start from a thread</label
10020
- >
10021
- <select
10022
- id="cpk-playground-thread-source"
10023
- class="cpk-playground-thread-select max-w-[200px] rounded-md border border-gray-200 bg-white px-2 py-1 text-[10px] text-gray-700 outline-none transition hover:border-gray-300 focus:border-violet-400 focus:ring-2 focus:ring-violet-100 disabled:cursor-not-allowed disabled:opacity-50"
10024
- .value=${this.playgroundSourceThreadId ?? ""}
10025
- ?disabled=${busy}
10026
- @change=${this.handlePlaygroundThreadSourceChange}
11512
+ <label class="sr-only" for="cpk-playground-thread-source"
11513
+ >Start from a thread</label
11514
+ >
11515
+ <select
11516
+ id="cpk-playground-thread-source"
11517
+ class="cpk-playground-thread-select max-w-[200px] rounded-md border border-gray-200 bg-white px-2 py-1 text-[10px] text-gray-700 outline-none transition hover:border-gray-300 focus:border-violet-400 focus:ring-2 focus:ring-violet-100 disabled:cursor-not-allowed disabled:opacity-50"
11518
+ .value=${this.playgroundSourceThreadId ?? ""}
11519
+ ?disabled=${busy}
11520
+ @change=${this.handlePlaygroundThreadSourceChange}
11521
+ >
11522
+ <option
11523
+ value=""
11524
+ ?selected=${!this.playgroundSourceThreadId}
10027
11525
  >
10028
- <option value="">Load a thread...</option>
10029
- ${sourceThreads.map((thread) => lit.html`
10030
- <option value=${thread.id}>
10031
- ${thread.name?.trim() || `Thread ${thread.id.slice(0, 8)}`}
10032
- </option>
10033
- `)}
10034
- </select>
10035
- ` : lit.nothing}
11526
+ Load a thread...
11527
+ </option>
11528
+ ${sourceThreads.map((thread) => lit.html`
11529
+ <option
11530
+ value=${thread.id}
11531
+ ?selected=${this.playgroundSourceThreadId === thread.id}
11532
+ >
11533
+ ${thread.name?.trim() || `Thread ${thread.id.slice(0, 8)}`}
11534
+ </option>
11535
+ `)}
11536
+ </select>
11537
+ ` : lit.nothing}
10036
11538
  <button
10037
11539
  type="button"
10038
11540
  class="inline-flex shrink-0 items-center gap-1 rounded-md border border-gray-200 bg-white px-2 py-1 text-[10px] font-medium text-gray-700 transition hover:border-gray-300 hover:bg-gray-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-300 focus-visible:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-50 [&>svg]:h-3.5 [&>svg]:w-3.5"
@@ -10045,67 +11547,66 @@ ${argsString}</pre
10045
11547
  </header>
10046
11548
 
10047
11549
  ${this.playgroundShowEphemeralNotice && runtimeMode !== "intelligence" ? lit.html`
10048
- <div
10049
- role="alert"
10050
- class="mx-3 mt-2 flex items-start gap-2 rounded-lg border border-violet-200 bg-violet-50 px-2.5 py-2 text-[10px] text-violet-950"
10051
- data-playground-ephemeral-notice
11550
+ <div
11551
+ role="alert"
11552
+ class="mx-3 mt-2 flex items-start gap-2 rounded-lg border border-violet-200 bg-violet-50 px-2.5 py-2 text-[10px] text-violet-950"
11553
+ data-playground-ephemeral-notice
11554
+ >
11555
+ <span class="mt-0.5 text-violet-600 [&>svg]:h-3.5 [&>svg]:w-3.5"
11556
+ >${this.renderIcon("Clock3")}</span
10052
11557
  >
10053
- <span
10054
- class="mt-0.5 text-violet-600 [&>svg]:h-3.5 [&>svg]:w-3.5"
10055
- >${this.renderIcon("Clock3")}</span
10056
- >
10057
- <p class="min-w-0 flex-1 leading-relaxed">
10058
- Scratch threads are ephemeral and will be deleted when your
10059
- local session ends. Need durable history?
10060
- <a
10061
- class="font-semibold underline decoration-violet-300 underline-offset-2 hover:decoration-violet-700 focus-visible:rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-400 focus-visible:ring-offset-1"
10062
- href=${this.getThreadsIntelligenceSignupUrl()}
10063
- target="_blank"
10064
- rel="noopener noreferrer"
10065
- >Set up Intelligence</a
10066
- >.
10067
- </p>
10068
- <button
10069
- type="button"
10070
- class="rounded p-0.5 text-violet-500 transition hover:bg-violet-100 hover:text-violet-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-400 focus-visible:ring-offset-1"
10071
- aria-label="Dismiss ephemeral thread notice"
10072
- @click=${() => {
11558
+ <p class="min-w-0 flex-1 leading-relaxed">
11559
+ Scratch threads are ephemeral and will be deleted when your
11560
+ local session ends. Need durable history?
11561
+ <a
11562
+ class="font-semibold underline decoration-violet-300 underline-offset-2 hover:decoration-violet-700 focus-visible:rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-400 focus-visible:ring-offset-1"
11563
+ href=${this.getThreadsIntelligenceSignupUrl()}
11564
+ target="_blank"
11565
+ rel="noopener noreferrer"
11566
+ >Set up Intelligence</a
11567
+ >.
11568
+ </p>
11569
+ <button
11570
+ type="button"
11571
+ class="rounded p-0.5 text-violet-500 transition hover:bg-violet-100 hover:text-violet-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-400 focus-visible:ring-offset-1"
11572
+ aria-label="Dismiss ephemeral thread notice"
11573
+ @click=${() => {
10073
11574
  this.playgroundShowEphemeralNotice = false;
10074
11575
  this.requestUpdate();
10075
11576
  }}
10076
- >
10077
- ${this.renderIcon("X")}
10078
- </button>
10079
- </div>
10080
- ` : lit.nothing}
11577
+ >
11578
+ ${this.renderIcon("X")}
11579
+ </button>
11580
+ </div>
11581
+ ` : lit.nothing}
10081
11582
 
10082
11583
  <div
10083
11584
  class="min-h-0 flex-1 overflow-y-auto px-3 py-3"
10084
11585
  data-playground-messages
10085
11586
  >
10086
11587
  ${this.playgroundIsLoadingThread ? lit.html`
11588
+ <div
11589
+ class="flex h-full items-center justify-center gap-1.5 text-[10px] text-gray-600"
11590
+ >
11591
+ <span
11592
+ class="text-gray-500 [&>svg]:animate-spin"
11593
+ aria-hidden="true"
11594
+ >${this.renderIcon("LoaderCircle")}</span
11595
+ >
11596
+ Loading thread into a scratch session...
11597
+ </div>
11598
+ ` : visibleMessages.length === 0 ? lit.html`
10087
11599
  <div
10088
- class="flex h-full items-center justify-center gap-1.5 text-[10px] text-gray-600"
11600
+ class="cpk-playground-welcome mx-auto flex h-full w-full flex-col items-center justify-center text-center"
10089
11601
  >
10090
- <span
10091
- class="text-gray-500 [&>svg]:animate-spin"
10092
- aria-hidden="true"
10093
- >${this.renderIcon("LoaderCircle")}</span
10094
- >
10095
- Loading thread into a scratch session...
11602
+ <p class="cpk-playground-welcome-title">
11603
+ How can I help you today?
11604
+ </p>
11605
+ ${this.renderPlaygroundComposer(agentId, busy, hasRetry, true)}
10096
11606
  </div>
10097
- ` : visibleMessages.length === 0 ? lit.html`
10098
- <div
10099
- class="mx-auto flex h-full w-full max-w-3xl flex-col items-center justify-center text-center"
10100
- >
10101
- <p class="text-base font-medium tracking-tight text-gray-900">
10102
- How can I help you today?
10103
- </p>
10104
- ${this.renderPlaygroundComposer(agentId, busy, hasRetry, true)}
10105
- </div>
10106
- ` : lit.html`
10107
- <div class="mx-auto flex max-w-3xl flex-col pb-5">
10108
- ${visibleMessages.map((message, index) => {
11607
+ ` : lit.html`
11608
+ <div class="mx-auto flex max-w-3xl flex-col pb-5">
11609
+ ${visibleMessages.map((message, index) => {
10109
11610
  const isUser = message.role === "user";
10110
11611
  const isReasoning = message.role === "reasoning";
10111
11612
  const isActivity = message.role === "activity";
@@ -10117,152 +11618,156 @@ ${argsString}</pre
10117
11618
  const durationLabel = duration === void 0 || duration < 1e3 ? "a few seconds" : `${Math.round(duration / 1e3)} seconds`;
10118
11619
  const label = isStreaming ? "Thinking…" : `Thought for ${durationLabel}`;
10119
11620
  if (isStreaming) return lit.html`
10120
- <section
10121
- class="cpk-playground-message-enter my-1 text-[11px] text-gray-500"
11621
+ <section
11622
+ class="cpk-playground-message-enter my-1 text-[11px] text-gray-500"
11623
+ data-playground-message-role="reasoning"
11624
+ >
11625
+ <div
11626
+ class="inline-flex items-center gap-1 py-1 font-medium"
11627
+ >
11628
+ <span>${label}</span>
11629
+ ${content ? lit.nothing : lit.html`
11630
+ <span
11631
+ class="cpk-playground-thinking-dot ml-1 h-1.5 w-1.5 rounded-full bg-gray-500"
11632
+ aria-hidden="true"
11633
+ ></span>
11634
+ `}
11635
+ </div>
11636
+ ${content ? lit.html`<div
11637
+ class="pb-2 pt-1 leading-5 text-gray-500"
11638
+ >
11639
+ ${content}
11640
+ </div>` : lit.nothing}
11641
+ </section>
11642
+ `;
11643
+ return content ? lit.html`
11644
+ <details
11645
+ class="cpk-playground-message-enter cpk-playground-reasoning my-1 text-[11px] text-gray-500"
10122
11646
  data-playground-message-role="reasoning"
10123
11647
  >
10124
- <div
10125
- class="inline-flex items-center gap-1 py-1 font-medium"
11648
+ <summary
11649
+ class="inline-flex cursor-pointer list-none items-center gap-1 py-1 font-medium transition-colors hover:text-gray-900 focus-visible:rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-300 focus-visible:ring-offset-1"
10126
11650
  >
10127
11651
  <span>${label}</span>
10128
- ${content ? lit.nothing : lit.html`
10129
- <span
10130
- class="cpk-playground-thinking-dot ml-1 h-1.5 w-1.5 rounded-full bg-gray-500"
10131
- aria-hidden="true"
10132
- ></span>
10133
- `}
11652
+ <span
11653
+ class="cpk-playground-reasoning-chevron transition-transform duration-200 [&>svg]:h-3 [&>svg]:w-3"
11654
+ >${this.renderIcon("ChevronRight")}</span
11655
+ >
11656
+ </summary>
11657
+ <div class="pb-2 pt-1 leading-5 text-gray-500">
11658
+ ${content}
10134
11659
  </div>
10135
- ${content ? lit.html`<div
10136
- class="pb-2 pt-1 leading-5 text-gray-500"
10137
- >
10138
- ${content}
10139
- </div>` : lit.nothing}
10140
- </section>
11660
+ </details>
11661
+ ` : lit.html`
11662
+ <div
11663
+ class="cpk-playground-message-enter my-1 py-1 text-[11px] font-medium text-gray-500"
11664
+ data-playground-message-role="reasoning"
11665
+ >
11666
+ ${label}
11667
+ </div>
10141
11668
  `;
10142
- return content ? lit.html`
10143
- <details
10144
- class="cpk-playground-message-enter cpk-playground-reasoning my-1 text-[11px] text-gray-500"
10145
- data-playground-message-role="reasoning"
11669
+ }
11670
+ const isMultiline = content.includes("\n") || content.length > 72;
11671
+ const copyKey = `playground-message-${message.id ?? index}`;
11672
+ const showToolbar = !isUser && !isActivity && Boolean(content) && !(this.playgroundIsRunning && index === lastAssistantIndex);
11673
+ return lit.html`
11674
+ <article
11675
+ class=${isActivity ? "cpk-playground-message-enter mr-auto mt-3 flex max-w-full items-center gap-1.5 rounded-lg border border-gray-200 bg-gray-50 px-2.5 py-1.5 text-[10px] text-gray-600" : isUser ? "cpk-playground-message-enter flex w-full flex-col items-end pt-8" : "cpk-playground-message-enter w-full"}
11676
+ data-playground-message-role=${message.role}
11677
+ >
11678
+ ${isActivity ? lit.html`
11679
+ <span class="text-gray-500"
11680
+ >${this.renderIcon("Activity")}</span
11681
+ >
11682
+ <span class="font-medium text-gray-700"
11683
+ >Activity</span
10146
11684
  >
10147
- <summary
10148
- class="inline-flex cursor-pointer list-none items-center gap-1 py-1 font-medium transition-colors hover:text-gray-900 focus-visible:rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-300 focus-visible:ring-offset-1"
11685
+ <span class="truncate">${content}</span>
11686
+ ` : isUser ? lit.html`
11687
+ <div
11688
+ class=${`max-w-[80%] whitespace-pre-wrap break-words rounded-[16px] bg-gray-100 px-3 text-[13px] leading-5 text-gray-900 ${isMultiline ? "py-2.5" : "py-1"}`}
11689
+ >
11690
+ ${content}
11691
+ </div>
11692
+ ` : lit.html`
11693
+ <div
11694
+ class="whitespace-pre-wrap break-words py-3 text-[13px] leading-[22px] text-gray-800"
10149
11695
  >
10150
- <span>${label}</span>
10151
- <span
10152
- class="cpk-playground-reasoning-chevron transition-transform duration-200 [&>svg]:h-3 [&>svg]:w-3"
10153
- >${this.renderIcon("ChevronRight")}</span
10154
- >
10155
- </summary>
10156
- <div class="pb-2 pt-1 leading-5 text-gray-500">
10157
11696
  ${content}
10158
11697
  </div>
10159
- </details>
10160
- ` : lit.html`
11698
+ `}
11699
+ ${!isUser && message.toolCalls.length > 0 ? this.renderToolCallDetails(message.toolCalls) : lit.nothing}
11700
+ ${showToolbar ? lit.html`
10161
11701
  <div
10162
- class="cpk-playground-message-enter my-1 py-1 text-[11px] font-medium text-gray-500"
10163
- data-playground-message-role="reasoning"
11702
+ class="-ml-1 flex min-h-7 w-full items-center gap-1 bg-transparent"
11703
+ data-playground-assistant-toolbar
10164
11704
  >
10165
- ${label}
11705
+ <button
11706
+ type="button"
11707
+ class="flex h-7 w-7 items-center justify-center rounded-md text-gray-500 transition hover:bg-gray-100 hover:text-gray-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-300 focus-visible:ring-offset-1 [&>svg]:h-3.5 [&>svg]:w-3.5"
11708
+ title="Copy message"
11709
+ aria-label="Copy message"
11710
+ @click=${(event) => this.copyToClipboard(content, copyKey, event)}
11711
+ >
11712
+ ${this.copiedEvents.has(copyKey) ? this.renderIcon("Check") : this.renderIcon("Copy")}
11713
+ </button>
11714
+ ${index === lastAssistantIndex && hasRetry && !busy && !this.playgroundError ? lit.html`
11715
+ <button
11716
+ type="button"
11717
+ class="flex h-7 w-7 items-center justify-center rounded-md text-gray-500 transition hover:bg-gray-100 hover:text-gray-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-300 focus-visible:ring-offset-1 [&>svg]:h-3.5 [&>svg]:w-3.5"
11718
+ title="Retry last prompt"
11719
+ aria-label="Retry last prompt"
11720
+ @click=${this.handlePlaygroundRetry}
11721
+ >
11722
+ ${this.renderIcon("RotateCcw")}
11723
+ </button>
11724
+ ` : lit.nothing}
10166
11725
  </div>
10167
- `;
10168
- }
10169
- const isMultiline = content.includes("\n") || content.length > 72;
10170
- const copyKey = `playground-message-${message.id ?? index}`;
10171
- const showToolbar = !isUser && !isActivity && Boolean(content) && !(this.playgroundIsRunning && index === lastAssistantIndex);
10172
- return lit.html`
10173
- <article
10174
- class=${isActivity ? "cpk-playground-message-enter mr-auto mt-3 flex max-w-full items-center gap-1.5 rounded-lg border border-gray-200 bg-gray-50 px-2.5 py-1.5 text-[10px] text-gray-600" : isUser ? "cpk-playground-message-enter flex w-full flex-col items-end pt-8" : "cpk-playground-message-enter w-full"}
10175
- data-playground-message-role=${message.role}
10176
- >
10177
- ${isActivity ? lit.html`
10178
- <span class="text-gray-500"
10179
- >${this.renderIcon("Activity")}</span
10180
- >
10181
- <span class="font-medium text-gray-700"
10182
- >Activity</span
10183
- >
10184
- <span class="truncate">${content}</span>
10185
- ` : isUser ? lit.html`
10186
- <div
10187
- class=${`max-w-[80%] whitespace-pre-wrap break-words rounded-[16px] bg-gray-100 px-3 text-[13px] leading-5 text-gray-900 ${isMultiline ? "py-2.5" : "py-1"}`}
10188
- >${content}</div>
10189
- ` : lit.html`
10190
- <div
10191
- class="whitespace-pre-wrap break-words py-3 text-[13px] leading-[22px] text-gray-800"
10192
- >${content}</div>
10193
- `}
10194
- ${!isUser && message.toolCalls.length > 0 ? this.renderToolCallDetails(message.toolCalls) : lit.nothing}
10195
- ${showToolbar ? lit.html`
10196
- <div
10197
- class="-ml-1 flex min-h-7 w-full items-center gap-1 bg-transparent"
10198
- data-playground-assistant-toolbar
10199
- >
10200
- <button
10201
- type="button"
10202
- class="flex h-7 w-7 items-center justify-center rounded-md text-gray-500 transition hover:bg-gray-100 hover:text-gray-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-300 focus-visible:ring-offset-1 [&>svg]:h-3.5 [&>svg]:w-3.5"
10203
- title="Copy message"
10204
- aria-label="Copy message"
10205
- @click=${(event) => this.copyToClipboard(content, copyKey, event)}
10206
- >
10207
- ${this.copiedEvents.has(copyKey) ? this.renderIcon("Check") : this.renderIcon("Copy")}
10208
- </button>
10209
- ${index === lastAssistantIndex && hasRetry && !busy && !this.playgroundError ? lit.html`
10210
- <button
10211
- type="button"
10212
- class="flex h-7 w-7 items-center justify-center rounded-md text-gray-500 transition hover:bg-gray-100 hover:text-gray-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-300 focus-visible:ring-offset-1 [&>svg]:h-3.5 [&>svg]:w-3.5"
10213
- title="Retry last prompt"
10214
- aria-label="Retry last prompt"
10215
- @click=${this.handlePlaygroundRetry}
10216
- >
10217
- ${this.renderIcon("RotateCcw")}
10218
- </button>
10219
- ` : lit.nothing}
10220
- </div>
10221
- ` : lit.nothing}
10222
- </article>
10223
- `;
11726
+ ` : lit.nothing}
11727
+ </article>
11728
+ `;
10224
11729
  })}
10225
- ${this.playgroundIsRunning && lastReasoningIndex < 0 ? lit.html`
10226
- <div
10227
- class="cpk-playground-message-enter mt-3 flex items-center gap-1 px-1 py-1"
10228
- aria-label="Agent is working"
10229
- >
10230
- <span
10231
- class="cpk-playground-thinking-dot h-1.5 w-1.5 rounded-full bg-gray-500"
10232
- ></span>
10233
- <span
10234
- class="cpk-playground-thinking-dot h-1.5 w-1.5 rounded-full bg-gray-500"
10235
- ></span>
10236
- <span
10237
- class="cpk-playground-thinking-dot h-1.5 w-1.5 rounded-full bg-gray-500"
10238
- ></span>
10239
- </div>
10240
- ` : lit.nothing}
10241
- ${!busy && lastAssistantIndex >= 0 && suggestions.length > 0 ? lit.html`
10242
- <div
10243
- class="mt-3 flex flex-wrap items-center gap-1.5"
10244
- data-playground-suggestions
10245
- >
10246
- ${suggestions.map((suggestion) => lit.html`
10247
- <button
10248
- type="button"
10249
- class="inline-flex h-7 items-center gap-1 rounded-full border border-gray-200 bg-white px-2.5 text-[10px] font-medium leading-none text-gray-900 transition-colors hover:bg-gray-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-300 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:text-gray-500"
10250
- ?disabled=${suggestion.isLoading}
10251
- aria-busy=${suggestion.isLoading ? "true" : "false"}
10252
- @click=${() => this.handlePlaygroundSuggestion(suggestion.message)}
10253
- >
10254
- ${suggestion.isLoading ? lit.html`<span
10255
- class="[&>svg]:animate-spin"
10256
- aria-hidden="true"
10257
- >${this.renderIcon("LoaderCircle")}</span
10258
- >` : lit.nothing}
10259
- <span>${suggestion.title}</span>
10260
- </button>
10261
- `)}
10262
- </div>
10263
- ` : lit.nothing}
10264
- </div>
10265
- `}
11730
+ ${this.playgroundIsRunning && lastReasoningIndex < 0 ? lit.html`
11731
+ <div
11732
+ class="cpk-playground-message-enter mt-3 flex items-center gap-1 px-1 py-1"
11733
+ aria-label="Agent is working"
11734
+ >
11735
+ <span
11736
+ class="cpk-playground-thinking-dot h-1.5 w-1.5 rounded-full bg-gray-500"
11737
+ ></span>
11738
+ <span
11739
+ class="cpk-playground-thinking-dot h-1.5 w-1.5 rounded-full bg-gray-500"
11740
+ ></span>
11741
+ <span
11742
+ class="cpk-playground-thinking-dot h-1.5 w-1.5 rounded-full bg-gray-500"
11743
+ ></span>
11744
+ </div>
11745
+ ` : lit.nothing}
11746
+ ${!busy && lastAssistantIndex >= 0 && suggestions.length > 0 ? lit.html`
11747
+ <div
11748
+ class="mt-3 flex flex-wrap items-center gap-1.5"
11749
+ data-playground-suggestions
11750
+ >
11751
+ ${suggestions.map((suggestion) => lit.html`
11752
+ <button
11753
+ type="button"
11754
+ class="inline-flex h-7 items-center gap-1 rounded-full border border-gray-200 bg-white px-2.5 text-[10px] font-medium leading-none text-gray-900 transition-colors hover:bg-gray-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-300 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:text-gray-500"
11755
+ ?disabled=${suggestion.isLoading}
11756
+ aria-busy=${suggestion.isLoading ? "true" : "false"}
11757
+ @click=${() => this.handlePlaygroundSuggestion(suggestion.message)}
11758
+ >
11759
+ ${suggestion.isLoading ? lit.html`<span
11760
+ class="[&>svg]:animate-spin"
11761
+ aria-hidden="true"
11762
+ >${this.renderIcon("LoaderCircle")}</span
11763
+ >` : lit.nothing}
11764
+ <span>${suggestion.title}</span>
11765
+ </button>
11766
+ `)}
11767
+ </div>
11768
+ ` : lit.nothing}
11769
+ </div>
11770
+ `}
10266
11771
  </div>
10267
11772
 
10268
11773
  ${showWelcome ? lit.nothing : this.renderPlaygroundComposer(agentId, busy, hasRetry)}
@@ -10649,6 +12154,7 @@ ${argsString}</pre
10649
12154
  this.requestUpdate();
10650
12155
  return;
10651
12156
  }
12157
+ this.tryFromHereError = null;
10652
12158
  this.selectedThreadId = threadId;
10653
12159
  if (showingExamples && this.isExampleThreadId(threadId)) {
10654
12160
  this.selectedRealThreadIsExplicit = false;
@@ -10912,6 +12418,7 @@ ${argsString}</pre
10912
12418
  <p class="cpk-threads-overview-copy">
10913
12419
  ${lockedCopy?.description ?? "Take a tour with the example threads in the sidebar. Then, start chatting in your app to create the first real thread."}
10914
12420
  </p>
12421
+ ${locked ? this.renderRuntimeEntitlementDiagnostic(this.getRuntimeEntitlementDiagnostic()) : lit.nothing}
10915
12422
  <div class="cpk-threads-overview-actions">
10916
12423
  ${locked ? lit.html`
10917
12424
  ${this.inspectorMetadataProjection.licenseState === "valid" ? lit.html`
@@ -11090,6 +12597,74 @@ ${argsString}</pre
11090
12597
  }
11091
12598
  }
11092
12599
  /**
12600
+ * Prefer the Runtime's structured entitlement diagnostic and derive a
12601
+ * compatibility diagnostic only when an older Core exposes legacy status.
12602
+ */
12603
+ getRuntimeEntitlementDiagnostic() {
12604
+ const runtimeEntitlements = this.core?.runtimeEntitlements;
12605
+ if (runtimeEntitlements) return runtimeEntitlements.status === "ready" ? { status: runtimeEntitlements.status } : {
12606
+ status: runtimeEntitlements.status,
12607
+ error: runtimeEntitlements.error
12608
+ };
12609
+ switch (this.core?.licenseStatus) {
12610
+ case "valid": return { status: "ready" };
12611
+ case "expired": return {
12612
+ status: "degraded",
12613
+ error: {
12614
+ code: "legacy_license_expired",
12615
+ message: "Legacy Runtime license has expired.",
12616
+ retryable: false
12617
+ }
12618
+ };
12619
+ case "expiring": return {
12620
+ status: "degraded",
12621
+ error: {
12622
+ code: "legacy_license_expiring",
12623
+ message: "Legacy Runtime license is expiring.",
12624
+ retryable: false
12625
+ }
12626
+ };
12627
+ case "invalid": return {
12628
+ status: "misconfigured",
12629
+ error: {
12630
+ code: "legacy_license_invalid",
12631
+ message: "Legacy Runtime license is invalid.",
12632
+ retryable: false
12633
+ }
12634
+ };
12635
+ case "none":
12636
+ case "unknown": return { status: "unavailable" };
12637
+ default: return null;
12638
+ }
12639
+ }
12640
+ /** Render exact Runtime entitlement correlation details without gating UI. */
12641
+ renderRuntimeEntitlementDiagnostic(diagnostic) {
12642
+ if (!diagnostic) return lit.nothing;
12643
+ return lit.html`
12644
+ <div
12645
+ role="status"
12646
+ data-runtime-entitlement-status=${diagnostic.status}
12647
+ style="
12648
+ margin: -8px auto 18px;
12649
+ max-width: 380px;
12650
+ font-size: 11px;
12651
+ line-height: 1.5;
12652
+ color: #57575b;
12653
+ "
12654
+ >
12655
+ <div style="font-weight: 600;">
12656
+ Runtime entitlement: ${diagnostic.status}
12657
+ </div>
12658
+ ${diagnostic.error ? lit.html`
12659
+ <div>${diagnostic.error.message}</div>
12660
+ <div>Code: ${diagnostic.error.code}</div>
12661
+ ${diagnostic.error.requestId ? lit.html`<div>Request ID: ${diagnostic.error.requestId}</div>` : lit.nothing}
12662
+ ${diagnostic.error.traceId ? lit.html`<div>Trace ID: ${diagnostic.error.traceId}</div>` : lit.nothing}
12663
+ ` : lit.nothing}
12664
+ </div>
12665
+ `;
12666
+ }
12667
+ /**
11093
12668
  * Renders the realtime-connection indicator in the memory-store header.
11094
12669
  * Only `"connected"` shows the live (green-dot) state; `"connecting"` shows a
11095
12670
  * muted amber "reconnecting" and `"unavailable"` a muted grey "offline", so
@@ -11473,6 +13048,13 @@ ${argsString}</pre
11473
13048
  .focusRequestId=${this.threadFocusRequestId}
11474
13049
  .agentStateInput=${this.getLatestStateForAgent(selectedThread.agentId)}
11475
13050
  .agentEventsInput=${this.agentEvents.get(selectedThread.agentId) ?? []}
13051
+ .agentMessagesInput=${selectedThreadIsLocalExample ? EMPTY_INSPECTOR_MESSAGES : this.getLiveAgentMessagesForThread(selectedThread)}
13052
+ .tryFromHereAvailable=${!selectedThreadIsLocalExample && this.areThreadEndpointsAvailable() && this._core?.threadEndpoints?.inspect !== false}
13053
+ .tryFromHereBusy=${this.tryFromHereBusy}
13054
+ .tryFromHereError=${this.tryFromHereError}
13055
+ @tryFromHere=${(event) => {
13056
+ this.handleTryFromHere(event.detail);
13057
+ }}
11476
13058
  ></cpk-thread-details>
11477
13059
  ${selectedThreadIsLocalExample ? this.renderThreadsExampleTour() : lit.nothing}` : showingExamples ? this.renderThreadsExampleOverview(locked) : lit.html`
11478
13060
  <div
@@ -11713,11 +13295,7 @@ ${argsString}</pre
11713
13295
  >
11714
13296
  ${isExpanded ? lit.html`
11715
13297
  <div class="group relative">
11716
- <pre
11717
- class="m-0 whitespace-pre-wrap break-words text-[10px] font-mono text-gray-600"
11718
- >
11719
- ${prettyEvent}</pre
11720
- >
13298
+ ${renderHighlightedJsonBlock(extractedEvent)}
11721
13299
  <button
11722
13300
  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"}"
11723
13301
  @click=${(e) => {
@@ -11939,7 +13517,7 @@ ${prettyEvent}</pre
11939
13517
  <div class="overflow-auto">
11940
13518
  ${messages && messages.length > 0 ? lit.html`
11941
13519
  <div class="w-full text-xs">
11942
- <div class="flex bg-gray-50">
13520
+ <div class="cpk-agent-messages-head flex bg-gray-50">
11943
13521
  <div
11944
13522
  class="w-40 shrink-0 px-4 py-2 font-medium text-gray-700"
11945
13523
  >
@@ -11949,7 +13527,7 @@ ${prettyEvent}</pre
11949
13527
  Content
11950
13528
  </div>
11951
13529
  </div>
11952
- <div class="divide-y divide-gray-200">
13530
+ <div class="cpk-agent-messages-rows">
11953
13531
  ${messages.map((msg) => {
11954
13532
  const role = msg.role || "unknown";
11955
13533
  const roleColors = {
@@ -11967,7 +13545,7 @@ ${prettyEvent}</pre
11967
13545
  const isFailedResult = role === "tool" && toolError?.toolCallId !== void 0 && toolError.toolCallId === msg.toolCallId;
11968
13546
  return lit.html`
11969
13547
  <div
11970
- class=${isFailedResult ? "flex items-start bg-rose-50" : "flex items-start"}
13548
+ class=${isFailedResult ? "cpk-agent-message-row flex items-start bg-rose-50" : "cpk-agent-message-row flex items-start"}
11971
13549
  data-cpk-failed-tool-result=${isFailedResult ? msg.toolCallId : lit.nothing}
11972
13550
  >
11973
13551
  <div class="w-40 shrink-0 px-4 py-2">
@@ -11978,9 +13556,10 @@ ${prettyEvent}</pre
11978
13556
  </span>
11979
13557
  </div>
11980
13558
  <div class="flex-1 px-4 py-2">
11981
- ${hasContent ? lit.html`<div
11982
- class="whitespace-pre-wrap break-words text-gray-700"
11983
- >${rawContent}</div>` : lit.html`<div class="italic text-gray-400">
13559
+ ${hasContent ? lit.html`
13560
+ <!-- prettier-ignore -->
13561
+ <div class="whitespace-pre-wrap break-words text-gray-700">${rawContent}</div>
13562
+ ` : lit.html`<div class="italic text-gray-400">
11984
13563
  ${contentFallback}
11985
13564
  </div>`}
11986
13565
  ${role === "assistant" && toolCalls.length > 0 ? this.renderToolCallDetails(toolCalls) : lit.nothing}
@@ -12049,10 +13628,12 @@ ${prettyEvent}</pre
12049
13628
  >${this.renderIcon("ChevronDown")}</span
12050
13629
  >
12051
13630
  </button>
12052
- ${this.contextMenuOpen ? lit.html`
13631
+ ${iconRail || this.contextMenuOpen ? lit.html`
12053
13632
  <div
12054
- 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"
13633
+ 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" : ""}"
12055
13634
  data-context-dropdown-root="true"
13635
+ data-open=${this.contextMenuOpen ? "true" : "false"}
13636
+ aria-hidden=${this.contextMenuOpen ? "false" : "true"}
12056
13637
  >
12057
13638
  ${filteredOptions.map((option) => lit.html`
12058
13639
  <button
@@ -12189,8 +13770,14 @@ ${prettyEvent}</pre
12189
13770
  this.contextMenuOpen = !this.contextMenuOpen;
12190
13771
  this.requestUpdate();
12191
13772
  }
13773
+ clearIconRailContextCloseTimer() {
13774
+ if (this.iconRailContextCloseTimer === null) return;
13775
+ clearTimeout(this.iconRailContextCloseTimer);
13776
+ this.iconRailContextCloseTimer = null;
13777
+ }
12192
13778
  handleContextOptionSelect(key) {
12193
13779
  if (!this.contextOptions.some((option) => option.key === key)) return;
13780
+ this.clearIconRailContextCloseTimer();
12194
13781
  if (this.selectedContext !== key) {
12195
13782
  this.selectedContext = key;
12196
13783
  this.expandedRows.clear();
@@ -12685,23 +14272,25 @@ ${prettyEvent}</pre
12685
14272
  </button>
12686
14273
 
12687
14274
  ${isExpanded ? lit.html`
12688
- <div class="border-t border-gray-200 bg-gray-50/50 px-4 py-3">
14275
+ <div class="border-t border-gray-200 px-4 py-3">
12689
14276
  <div class="mb-3">
12690
- <h5 class="mb-1 text-xs font-semibold text-gray-700">ID</h5>
12691
- <code
12692
- class="font-mono text-xs font-medium text-gray-800 flex-1 truncate min-w-0"
12693
- >${id}</code
12694
- >
12695
- <button
12696
- type="button"
12697
- class="cpk-copy-btn"
12698
- @click=${(e) => {
14277
+ <div class="mb-1 flex items-center justify-between gap-2">
14278
+ <h5 class="text-xs font-semibold text-gray-700">ID</h5>
14279
+ <button
14280
+ type="button"
14281
+ class="cpk-copy-btn"
14282
+ @click=${(e) => {
12699
14283
  e.stopPropagation();
12700
14284
  this.copyContextValue(id, `${id}:id`, e);
12701
14285
  }}
14286
+ >
14287
+ ${this.copiedContextItems.has(`${id}:id`) ? "Copied" : "Copy"}
14288
+ </button>
14289
+ </div>
14290
+ <code
14291
+ class="block min-w-0 truncate font-mono text-xs font-medium text-gray-800"
14292
+ >${id}</code
12702
14293
  >
12703
- ${this.copiedContextItems.has(`${id}:id`) ? "✓" : "Copy"}
12704
- </button>
12705
14294
  </div>
12706
14295
  ${hasValue ? lit.html`
12707
14296
  <div class="mb-2 flex items-center justify-between gap-2">
@@ -13428,6 +15017,16 @@ function defineWebInspector(registry = globalThis.customElements) {
13428
15017
  defineElementOnce(registry, "cpk-memory-list", CpkMemoryList);
13429
15018
  defineElementOnce(registry, WEB_INSPECTOR_TAG, WebInspectorElement);
13430
15019
  }
15020
+ /**
15021
+ * Bind a host-owned core before an Inspector is connected to the DOM. Disabling
15022
+ * auto-attachment first prevents `connectedCallback` from briefly selecting a
15023
+ * different global core.
15024
+ */
15025
+ function configureWebInspectorElement(inspector, core) {
15026
+ inspector.autoAttachCore = false;
15027
+ inspector.core = core;
15028
+ return inspector;
15029
+ }
13431
15030
  defineWebInspector();
13432
15031
 
13433
15032
  //#endregion
@@ -13435,6 +15034,7 @@ exports.CpkThreadInspector = CpkThreadInspector;
13435
15034
  exports.THREAD_INSPECTOR_TAG = THREAD_INSPECTOR_TAG;
13436
15035
  exports.WEB_INSPECTOR_TAG = WEB_INSPECTOR_TAG;
13437
15036
  exports.WebInspectorElement = WebInspectorElement;
15037
+ exports.configureWebInspectorElement = configureWebInspectorElement;
13438
15038
  exports.defineWebInspector = defineWebInspector;
13439
15039
  exports.ɵCpkThreadDetails = ɵCpkThreadDetails;
13440
15040
  exports.ɵbuildCapabilityRows = buildCapabilityRows;