@copilotkit/web-inspector 1.69.3 → 1.70.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -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");
@@ -111,20 +112,15 @@ const EVENT_ERROR_GUIDANCE = {
111
112
  * an announcement, and it would double the spoken length.
112
113
  */
113
114
  const PILL_SUBLINE_LABEL = "Open Inspector for details";
114
- const HUD_OPEN_INSPECTOR_LABEL = "Open Inspector";
115
- const HUD_THREADS_OFF_LABEL = "Turn on Threads";
116
- const HUD_THREADS_ON_LABEL = "Threads on";
117
- const HUD_INTELLIGENCE_OFF_LABEL = "Turn on Intelligence";
118
- const HUD_INTELLIGENCE_ON_LABEL = "Intelligence connected";
119
- const HUD_THREADS_OFF_DETAIL = "Inspect conversations from this app.";
120
- const HUD_THREADS_ON_DETAIL = "Threads is on. Opens the Threads view.";
121
- const HUD_INTELLIGENCE_OFF_DETAIL = "Connect Intelligence to use Threads and Learning.";
122
- const HUD_INTELLIGENCE_ON_DETAIL = "Intelligence is connected. Opens Home.";
123
- const HUD_LEARNING_OFF_LABEL = "Turn on Learning";
124
- const HUD_LEARNING_ON_LABEL = "Learning on";
125
- const HUD_LEARNING_OFF_DETAIL = "Connect Intelligence to use Learning.";
126
- const HUD_LEARNING_ON_DETAIL = "Learning is on. Opens the Learning view.";
127
- const HUD_OPEN_INSPECTOR_DETAIL = "Same as clicking the circle. Opens the full Inspector.";
115
+ const HUD_INSPECTOR_LABEL = "CopilotKit Inspector";
116
+ const HUD_ANNOUNCEMENT_TITLE_LIMIT = 80;
117
+ const HUD_THREADS_LABEL = "Rich Threads";
118
+ const HUD_LEARNING_LABEL = "Automatic Learning";
119
+ const HUD_LEARN_MORE_LABEL = "Click to learn more";
120
+ const INSPECTOR_DISMISSAL_MS = {
121
+ day: 1440 * 60 * 1e3,
122
+ week: require_persistence.INSPECTOR_DISMISSAL_MAX_DURATION_MS
123
+ };
128
124
  const LAUNCHER_SIGNALS = {
129
125
  "whats-new": {
130
126
  tone: "news",
@@ -242,22 +238,24 @@ const THREAD_LIST_DEBOUNCE_MS = 300;
242
238
  const LAUNCHER_BASE_LABEL = "Web Inspector";
243
239
  const EDGE_MARGIN = 16;
244
240
  /** HUD card plus the hover bridge. Used to pick left vs right. */
245
- const LAUNCHER_HUD_WIDTH = 248;
241
+ const LAUNCHER_HUD_WIDTH = 258;
246
242
  /**
247
243
  * One page-load preview of the launcher's feature HUD.
248
244
  *
249
- * The card arrives after the host page has had a beat to settle. Its four rows
250
- * then come online in order, stay readable, and leave together. Nothing is
251
- * persisted: a new Inspector element means a new preview.
245
+ * The card arrives after the host page has had a beat to settle. Its feature
246
+ * contents then arrive from top to bottom, stay readable, and leave together.
247
+ * Nothing is persisted: a new Inspector element means a new preview.
252
248
  */
253
249
  const LAUNCHER_HUD_INTRO_MS = {
254
250
  delay: 500,
255
251
  duration: 3400,
256
- rowStart: 180,
257
- rowStagger: 170,
258
- rowDuration: 300,
252
+ waterfallStart: 180,
253
+ waterfallStagger: 170,
254
+ waterfallDuration: 300,
259
255
  blockedRetry: 250
260
256
  };
257
+ /** Return the staggered reveal delay for one launcher HUD layer. */
258
+ const launcherHudWaterfallDelay = (introIndex) => `${LAUNCHER_HUD_INTRO_MS.waterfallStart + introIndex * LAUNCHER_HUD_INTRO_MS.waterfallStagger}ms`;
261
259
  const DRAG_THRESHOLD = 6;
262
260
  const MIN_WINDOW_WIDTH = 880;
263
261
  const MIN_WINDOW_WIDTH_DOCKED_LEFT = 640;
@@ -286,17 +284,109 @@ function createPlaygroundThreadId() {
286
284
  return globalThis.crypto?.randomUUID?.() ?? `playground-${Date.now()}`;
287
285
  }
288
286
  const THREADS_DOCS_URL = "https://docs.copilotkit.ai/threads";
289
- const THREADS_RUNTIME_SETUP_DOCS_URL = "https://docs.copilotkit.ai/backend/runtime-endpoints#enable-rich-threads-routes";
290
- const THREADS_RUNTIME_SETUP_PROMPT = [
291
- `Read ${THREADS_RUNTIME_SETUP_DOCS_URL} and finish setting up Rich Threads in this repository.`,
292
- "",
293
- "First inspect the repository's agent instructions, installed CopilotKit versions, Runtime adapter, frontend provider, route or proxy setup, and existing authentication. Preserve the current framework and deployment model. Preserve existing authentication middleware and access checks on every Runtime route.",
294
- "",
295
- "Follow the guide to enable the multi-route Runtime, align the frontend transport, scope identifyUser to the existing server-verified signed-in application user, and expose the full Runtime subtree for GET, POST, PATCH, and DELETE. Never use a fixed demo identity in production. If no trusted user identity exists, stop and ask me which auth source to use.",
296
- "",
297
- "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."
298
- ].join("\n");
299
- const SELF_HOSTED_INTELLIGENCE_URL = "https://docs.copilotkit.ai/premium/self-hosting";
287
+ const SELF_HOSTED_INTELLIGENCE_URL = "https://docs.copilotkit.ai/intelligence/self-hosting";
288
+ const INTELLIGENCE_STORY_BEATS = [
289
+ {
290
+ id: "threads",
291
+ label: "Threads",
292
+ duration: 6500,
293
+ lead: "You only see this session. Your users have all the others.",
294
+ support: "Rich Threads keep every conversation and its state, so you can open the one that broke instead of reproducing it."
295
+ },
296
+ {
297
+ id: "learning",
298
+ label: "Learning",
299
+ duration: 6e3,
300
+ lead: "Your users already told you what to fix.",
301
+ support: "Learning reads the runs behind those threads and finds the patterns — every Insight linked to the messages that back it."
302
+ },
303
+ {
304
+ id: "skill",
305
+ label: "Skills",
306
+ duration: 5500,
307
+ lead: "An Insight becomes a skill you own.",
308
+ support: "A SKILL.md built from that evidence — yours to review, edit and ship with your project."
309
+ },
310
+ {
311
+ id: "intelligence",
312
+ label: "Intelligence",
313
+ duration: 6e3,
314
+ lead: "Every round of real use leaves your agent better.",
315
+ support: "Approve a skill, pull it into your project, and the next run starts from what already worked."
316
+ }
317
+ ];
318
+ /**
319
+ * The threads the first beat shows.
320
+ *
321
+ * One of them failed, because that is the row a developer actually wants and
322
+ * the reason durable threads are worth paying for. It is a user's thread that
323
+ * went wrong, not a demo of our agent failing — the distinction matters for a
324
+ * card that has to argue for the product.
325
+ */
326
+ const INTELLIGENCE_STORY_THREADS = [
327
+ {
328
+ title: "Reschedule the Tuesday sync",
329
+ meta: "2 min ago",
330
+ failed: false
331
+ },
332
+ {
333
+ title: "Book time with the design team",
334
+ meta: "18 min ago",
335
+ failed: false
336
+ },
337
+ {
338
+ title: "Booked the wrong slot",
339
+ meta: "Needs a look",
340
+ failed: true
341
+ }
342
+ ];
343
+ /** The three rules the story derives, shown verbatim across all three beats. */
344
+ const INTELLIGENCE_STORY_RULES = [
345
+ "Check both calendars.",
346
+ "Propose several times.",
347
+ "Ask before booking."
348
+ ];
349
+ /**
350
+ * The raw thread signals the first beat collapses into those rules.
351
+ *
352
+ * Kept at real-message length and varied on purpose — these have to read as
353
+ * things people actually typed, not as three tidy bullet points. The longest
354
+ * one truncates in a narrow panel, which is honest: it is an excerpt.
355
+ */
356
+ const INTELLIGENCE_STORY_SIGNALS = [
357
+ "Check our calendars and find a time for both of us.",
358
+ "Could you share a few options?",
359
+ "Ask me before you book it."
360
+ ];
361
+ const INTELLIGENCE_STORY_SKILL_FILE = "meeting-scheduling/SKILL.md";
362
+ /**
363
+ * How long the copied confirmation stands before the button invites a second
364
+ * press. Longer than the 2s the Threads setup prompt uses, because this state
365
+ * also carries an instruction that has to be read, not just an acknowledgement.
366
+ */
367
+ const PROMPT_COPY_RESET_MS = 4e3;
368
+ const INTELLIGENCE_STORY_CHAIN = [
369
+ {
370
+ icon: "MessagesSquare",
371
+ name: "Threads",
372
+ detail: "Every conversation"
373
+ },
374
+ {
375
+ icon: "Lightbulb",
376
+ name: "Insights",
377
+ detail: "Backed by evidence"
378
+ },
379
+ {
380
+ icon: "FileText",
381
+ name: "Skills",
382
+ detail: "You approve"
383
+ },
384
+ {
385
+ icon: "Wand2",
386
+ name: "Your agent",
387
+ detail: "Starts from what worked"
388
+ }
389
+ ];
300
390
  const THREADS_EXAMPLE_OVERVIEW_VIDEO_URL = "https://cdn.copilotkit.ai/corp-site/videos/copilotkit-generative-ui-agentic-frontend-demo.webm";
301
391
  const THREADS_EXAMPLE_OVERVIEW_VIDEO_FALLBACK = "The demo video is unavailable. Use the example threads to explore Messages, AG-UI Events, and State.";
302
392
  const THREADS_EXAMPLE_TOUR_STORAGE_KEY = "cpk:inspector:threads-example-tour:v1";
@@ -1106,6 +1196,9 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1106
1196
  this.viewInAppError = null;
1107
1197
  this.focusMessageId = null;
1108
1198
  this.focusRequestId = 0;
1199
+ this.tryFromHereAvailable = false;
1200
+ this.tryFromHereBusy = false;
1201
+ this.tryFromHereError = null;
1109
1202
  this._tab = "timeline";
1110
1203
  this._fetchedMetadata = null;
1111
1204
  this._conversation = [];
@@ -1165,6 +1258,15 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1165
1258
  if (target.hasPointerCapture(this._dividerPointerId)) target.releasePointerCapture(this._dividerPointerId);
1166
1259
  this._dividerResizing = false;
1167
1260
  };
1261
+ this.onTryFromHere = (event) => {
1262
+ event.preventDefault();
1263
+ if (!this.tryFromHereAvailable || this.tryFromHereBusy) return;
1264
+ this.dispatchEvent(new CustomEvent("tryFromHere", {
1265
+ detail: this.threadId,
1266
+ bubbles: true,
1267
+ composed: true
1268
+ }));
1269
+ };
1168
1270
  }
1169
1271
  static {
1170
1272
  this.properties = {
@@ -1182,6 +1284,9 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1182
1284
  viewInAppError: { attribute: false },
1183
1285
  focusMessageId: { attribute: false },
1184
1286
  focusRequestId: { attribute: false },
1287
+ tryFromHereAvailable: { attribute: false },
1288
+ tryFromHereBusy: { attribute: false },
1289
+ tryFromHereError: { attribute: false },
1185
1290
  _tab: { state: true },
1186
1291
  _fetchedMetadata: { state: true },
1187
1292
  _conversation: { state: true },
@@ -1258,7 +1363,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1258
1363
  return JSON.stringify(Object.entries(headers).sort(([leftKey], [rightKey]) => leftKey.localeCompare(rightKey)));
1259
1364
  }
1260
1365
  renderTabContent(id) {
1261
- if (id === "timeline") return this.renderTimeline();
1366
+ if (id === "timeline") return this.withMessagesToolbar(this.renderTimeline());
1262
1367
  if (id === "state") return this.renderState();
1263
1368
  return this.renderEvents();
1264
1369
  }
@@ -1573,6 +1678,55 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1573
1678
  }
1574
1679
  }
1575
1680
 
1681
+ .cpk-td__try-from-here {
1682
+ display: inline-flex;
1683
+ align-items: center;
1684
+ gap: 4px;
1685
+ margin-inline-start: auto;
1686
+ padding: 6px 10px;
1687
+ border: 1px solid #dbdbe5;
1688
+ border-radius: 8px;
1689
+ background: #ffffff;
1690
+ color: #36363a;
1691
+ font-family: "Spline Sans Mono", monospace;
1692
+ font-size: 11px;
1693
+ font-weight: 600;
1694
+ line-height: 1.2;
1695
+ cursor: pointer;
1696
+ }
1697
+
1698
+ .cpk-td__try-from-here-icon {
1699
+ display: block;
1700
+ flex-shrink: 0;
1701
+ }
1702
+
1703
+ :host([dir="rtl"]) .cpk-td__try-from-here-icon {
1704
+ scale: -1 1;
1705
+ }
1706
+
1707
+ .cpk-td__try-from-here:hover:not(:disabled) {
1708
+ border-color: rgba(85, 88, 178, 0.38);
1709
+ background: #f7f7ff;
1710
+ color: #010507;
1711
+ }
1712
+
1713
+ .cpk-td__try-from-here:focus-visible {
1714
+ outline: 2px solid #a78bfa;
1715
+ outline-offset: 1px;
1716
+ }
1717
+
1718
+ .cpk-td__try-from-here:disabled {
1719
+ cursor: not-allowed;
1720
+ opacity: 0.55;
1721
+ }
1722
+
1723
+ .cpk-td__try-from-here-error {
1724
+ flex-basis: 100%;
1725
+ color: #c0333a;
1726
+ font-size: 11px;
1727
+ line-height: 1.4;
1728
+ }
1729
+
1576
1730
  /*
1577
1731
  * Each tab's content is wrapped in this panel so the keep-mounted
1578
1732
  * inactive panels can be hidden via display:none without disturbing
@@ -1957,6 +2111,8 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
1957
2111
 
1958
2112
  .cpk-td__timeline-toolbar {
1959
2113
  display: flex;
2114
+ flex-wrap: wrap;
2115
+ align-items: center;
1960
2116
  gap: 6px;
1961
2117
  }
1962
2118
 
@@ -2299,6 +2455,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2299
2455
  :host([data-color-scheme="dark"]) .cpk-td__panel-toggle,
2300
2456
  :host([data-color-scheme="dark"]) .cpk-td__metadata-strip,
2301
2457
  :host([data-color-scheme="dark"]) .cpk-td__metadata-pill,
2458
+ :host([data-color-scheme="dark"]) .cpk-td__try-from-here,
2302
2459
  :host([data-color-scheme="dark"]) .cpk-td__tool-block,
2303
2460
  :host([data-color-scheme="dark"]) .cpk-td__tool-header,
2304
2461
  :host([data-color-scheme="dark"]) .cpk-td__tool-body,
@@ -2316,6 +2473,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2316
2473
  }
2317
2474
 
2318
2475
  :host([data-color-scheme="dark"]) .cpk-td__metadata-pill,
2476
+ :host([data-color-scheme="dark"]) .cpk-td__try-from-here,
2319
2477
  :host([data-color-scheme="dark"]) .cpk-td__bubble-inner--assistant,
2320
2478
  :host([data-color-scheme="dark"]) .cpk-td__tool-block,
2321
2479
  :host([data-color-scheme="dark"]) .cpk-td__event,
@@ -2474,6 +2632,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
2474
2632
  :host([data-color-scheme="dark"]) .cpk-td__timeline-title,
2475
2633
  :host([data-color-scheme="dark"]) .cpk-td__timeline-bulk-toggle,
2476
2634
  :host([data-color-scheme="dark"]) .cpk-td__timeline-details-toggle,
2635
+ :host([data-color-scheme="dark"]) .cpk-td__try-from-here,
2477
2636
  :host([data-color-scheme="dark"]) .cpk-tdp__value {
2478
2637
  color: #f3f4f8;
2479
2638
  }
@@ -3406,15 +3565,55 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3406
3565
  ${isStop ? "Stop viewing" : "View in your app"}
3407
3566
  </button>
3408
3567
  ${this.viewInAppError ? lit.html`<span class="cpk-td__view-in-app-error" role="alert"
3409
- >${this.viewInAppError}</span
3410
- >` : lit.nothing}
3568
+ >${this.viewInAppError}</span
3569
+ >` : lit.nothing}
3570
+ `;
3571
+ }
3572
+ renderTryFromHereControl() {
3573
+ if (!this.tryFromHereAvailable) return lit.nothing;
3574
+ return lit.html`
3575
+ <button
3576
+ type="button"
3577
+ class="cpk-td__try-from-here"
3578
+ aria-label="Try from here"
3579
+ ?disabled=${this.tryFromHereBusy}
3580
+ @click=${this.onTryFromHere}
3581
+ >
3582
+ ${this.tryFromHereBusy ? "Loading…" : "Try from here"}
3583
+ <svg
3584
+ class="cpk-td__try-from-here-icon"
3585
+ aria-hidden="true"
3586
+ width="12"
3587
+ height="12"
3588
+ viewBox="0 0 24 24"
3589
+ fill="none"
3590
+ stroke="currentColor"
3591
+ stroke-width="2"
3592
+ stroke-linecap="round"
3593
+ stroke-linejoin="round"
3594
+ >
3595
+ <path d="M7 7h10v10" />
3596
+ <path d="M7 17 17 7" />
3597
+ </svg>
3598
+ </button>
3599
+ ${this.tryFromHereError ? lit.html`<span class="cpk-td__try-from-here-error" role="alert"
3600
+ >${this.tryFromHereError}</span
3601
+ >` : lit.nothing}
3411
3602
  `;
3412
3603
  }
3413
3604
  renderTimelineBulkControls() {
3605
+ const bulk = this.renderTimelineBulkButtons();
3606
+ const tryFromHere = this.renderTryFromHereControl();
3607
+ if (bulk === lit.nothing && tryFromHere === lit.nothing) return lit.nothing;
3608
+ return lit.html`<div class="cpk-td__timeline-toolbar">
3609
+ ${bulk}${tryFromHere}
3610
+ </div>`;
3611
+ }
3612
+ renderTimelineBulkButtons() {
3414
3613
  if (this._eventsNotAvailable) return lit.nothing;
3415
3614
  const detailIds = this.timelineItemsForEvents(this.activeEvents).filter((item) => item.details).map((item) => item.id);
3416
3615
  if (detailIds.length <= 1) return lit.nothing;
3417
- return lit.html`<div class="cpk-td__timeline-toolbar">
3616
+ return lit.html`
3418
3617
  <button
3419
3618
  type="button"
3420
3619
  class="cpk-td__timeline-bulk-toggle"
@@ -3431,7 +3630,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3431
3630
  >
3432
3631
  Collapse all
3433
3632
  </button>
3434
- </div>`;
3633
+ `;
3435
3634
  }
3436
3635
  renderRawEventBulkControls() {
3437
3636
  const eventIds = this.activeEvents.map((event) => this.rawEventId(event));
@@ -3463,6 +3662,9 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3463
3662
  (this.shadowRoot?.querySelector(`[data-source-index="${sourceIndex}"]`))?.scrollIntoView?.({ block: "center" });
3464
3663
  });
3465
3664
  }
3665
+ withMessagesToolbar(content) {
3666
+ return lit.html`${this.renderTimelineBulkControls()}${content}`;
3667
+ }
3466
3668
  renderTimeline() {
3467
3669
  if (this._loadingEvents) return lit.html`
3468
3670
  <div class="cpk-td__status">Loading timeline…</div>
@@ -3510,7 +3712,7 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3510
3712
  this._conversation,
3511
3713
  this.agentMessagesInput,
3512
3714
  this._expandedTimelineDetails
3513
- ], () => lit.html`${this.renderTimelineBulkControls()}${timelineItems.map((item) => this.renderTimelineItem(item))}`);
3715
+ ], () => lit.html`${timelineItems.map((item) => this.renderTimelineItem(item))}`);
3514
3716
  }
3515
3717
  timelineItemClass(item) {
3516
3718
  const classes = ["cpk-td__timeline-item", `cpk-td__timeline-item--${item.kind}`];
@@ -3535,14 +3737,14 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3535
3737
  >
3536
3738
  <span class="cpk-td__timeline-title">${item.title}</span>
3537
3739
  ${item.sourceIndex ? lit.html`
3538
- <button
3539
- type="button"
3540
- class="cpk-td__source-link"
3541
- @click=${() => this.revealSourceEvent(item.sourceIndex)}
3542
- >
3543
- Source event #${item.sourceIndex}
3544
- </button>
3545
- ` : lit.nothing}
3740
+ <button
3741
+ type="button"
3742
+ class="cpk-td__source-link"
3743
+ @click=${() => this.revealSourceEvent(item.sourceIndex)}
3744
+ >
3745
+ Source event #${item.sourceIndex}
3746
+ </button>
3747
+ ` : lit.nothing}
3546
3748
  <span class="cpk-td__timeline-time"
3547
3749
  >${formatTimestamp(item.timestamp)}</span
3548
3750
  >
@@ -3836,54 +4038,54 @@ var CpkThreadInspector = class CpkThreadInspector extends PortableLitElement {
3836
4038
  const eventId = this.rawEventId(event);
3837
4039
  const detailsExpanded = this._expandedRawEvents.has(eventId);
3838
4040
  return lit.html`
3839
- <div
3840
- class="cpk-td__event cpk-td__event--${eventCategory(event.type)}"
3841
- data-source-index=${event.sourceIndex}
3842
- >
3843
- <div class="cpk-td__event-header">
3844
- <span class="cpk-td__event-type" title=${event.type}
3845
- >${humanizeEventType(event.type)}</span
3846
- >
3847
- <span class="cpk-td__event-time"
3848
- >${formatTimestamp(event.timestamp)}</span
3849
- >
3850
- </div>
3851
- <button
3852
- type="button"
3853
- class="cpk-td__timeline-details-toggle"
3854
- aria-expanded=${detailsExpanded ? "true" : "false"}
3855
- @click=${() => this.toggleRawEventDetails(eventId)}
4041
+ <div
4042
+ class="cpk-td__event cpk-td__event--${eventCategory(event.type)}"
4043
+ data-source-index=${event.sourceIndex}
3856
4044
  >
3857
- ${detailsExpanded ? lit.html`
3858
- <svg
3859
- aria-hidden="true"
3860
- viewBox="0 0 24 24"
3861
- fill="none"
3862
- stroke="currentColor"
3863
- stroke-linecap="round"
3864
- stroke-linejoin="round"
3865
- >
3866
- <path d="m6 9 6 6 6-6" />
3867
- </svg>
3868
- ` : lit.html`
3869
- <svg
3870
- aria-hidden="true"
3871
- viewBox="0 0 24 24"
3872
- fill="none"
3873
- stroke="currentColor"
3874
- stroke-linecap="round"
3875
- stroke-linejoin="round"
3876
- >
3877
- <path d="m9 18 6-6-6-6" />
3878
- </svg>
3879
- `}
3880
- <span
3881
- >${detailsExpanded ? "Hide details" : "Show details"}</span
4045
+ <div class="cpk-td__event-header">
4046
+ <span class="cpk-td__event-type" title=${event.type}
4047
+ >${humanizeEventType(event.type)}</span
4048
+ >
4049
+ <span class="cpk-td__event-time"
4050
+ >${formatTimestamp(event.timestamp)}</span
4051
+ >
4052
+ </div>
4053
+ <button
4054
+ type="button"
4055
+ class="cpk-td__timeline-details-toggle"
4056
+ aria-expanded=${detailsExpanded ? "true" : "false"}
4057
+ @click=${() => this.toggleRawEventDetails(eventId)}
3882
4058
  >
3883
- </button>
3884
- ${detailsExpanded ? renderHighlightedJsonBlock(event.rawEvent ?? event) : lit.nothing}
3885
- </div>
3886
- `;
4059
+ ${detailsExpanded ? lit.html`
4060
+ <svg
4061
+ aria-hidden="true"
4062
+ viewBox="0 0 24 24"
4063
+ fill="none"
4064
+ stroke="currentColor"
4065
+ stroke-linecap="round"
4066
+ stroke-linejoin="round"
4067
+ >
4068
+ <path d="m6 9 6 6 6-6" />
4069
+ </svg>
4070
+ ` : lit.html`
4071
+ <svg
4072
+ aria-hidden="true"
4073
+ viewBox="0 0 24 24"
4074
+ fill="none"
4075
+ stroke="currentColor"
4076
+ stroke-linecap="round"
4077
+ stroke-linejoin="round"
4078
+ >
4079
+ <path d="m9 18 6-6-6-6" />
4080
+ </svg>
4081
+ `}
4082
+ <span
4083
+ >${detailsExpanded ? "Hide details" : "Show details"}</span
4084
+ >
4085
+ </button>
4086
+ ${detailsExpanded ? renderHighlightedJsonBlock(event.rawEvent ?? event) : lit.nothing}
4087
+ </div>
4088
+ `;
3887
4089
  })}`;
3888
4090
  });
3889
4091
  }
@@ -4692,6 +4894,13 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
4692
4894
  this.systemColorSchemeMediaQuery = null;
4693
4895
  this.briefingRestoreMenu = null;
4694
4896
  this.homeViewedThisOpen = false;
4897
+ this.onboardingRunId = null;
4898
+ this.promptCopyState = "idle";
4899
+ this.promptCopyResetTimer = null;
4900
+ this.intelStoryBeat = 0;
4901
+ this.intelStoryUserPinned = false;
4902
+ this.intelStoryTimer = null;
4903
+ this.intelStoryReducedMotion = null;
4695
4904
  this.hasResolvedCore = false;
4696
4905
  this.settingsOpen = false;
4697
4906
  this.lastSelectedMenuByGroup = {
@@ -4737,6 +4946,8 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
4737
4946
  this.playgroundError = null;
4738
4947
  this.playgroundSourceThreadId = null;
4739
4948
  this.playgroundShowEphemeralNotice = false;
4949
+ this.tryFromHereBusy = false;
4950
+ this.tryFromHereError = null;
4740
4951
  this.threadCapabilityEnabled = null;
4741
4952
  this.threadCapabilityGeneration = 0;
4742
4953
  this.contextMenuOpen = false;
@@ -4800,11 +5011,12 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
4800
5011
  this.pillTimeoutId = null;
4801
5012
  this.launcherHudOpen = false;
4802
5013
  this.launcherHudSide = "left";
4803
- this.launcherHudHelp = null;
4804
5014
  this.launcherHudCloseTimer = null;
4805
5015
  this.launcherHudIntro = false;
4806
5016
  this.launcherHudIntroStartTimer = null;
4807
5017
  this.launcherHudIntroEndTimer = null;
5018
+ this.inspectorDismissedUntil = null;
5019
+ this.inspectorDismissalTimer = null;
4808
5020
  this.hudLandingMenu = null;
4809
5021
  this.pillOutcome = null;
4810
5022
  this.viewedNewsSignalIds = /* @__PURE__ */ new Set();
@@ -4832,9 +5044,9 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
4832
5044
  this.threadsExampleOverviewVideoPlayAttemptGeneration = 0;
4833
5045
  this.threadsExampleOverviewVideoPlayPromise = null;
4834
5046
  this.threadsExampleOverviewVideoPlayOnNextBind = false;
4835
- this.threadsSetupPromptCopyState = "idle";
4836
- this.threadsSetupPromptCopyResetTimeoutId = null;
4837
- this.threadsSetupPromptCopyGeneration = 0;
5047
+ this.homeFeaturePromptCopyState = null;
5048
+ this.homeFeaturePromptCopyResetTimeoutId = null;
5049
+ this.homeFeaturePromptCopyGeneration = 0;
4838
5050
  this.contextState = {
4839
5051
  button: {
4840
5052
  position: {
@@ -4880,7 +5092,8 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
4880
5092
  this.customTabIcons = { threads: `<svg class="h-3.5 w-3.5" width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9.04167 15C8.29167 15 7.65972 14.7431 7.14583 14.2292C6.63194 13.7153 6.375 13.0972 6.375 12.375C6.375 11.3194 6.80208 10.3646 7.65625 9.51042C8.51042 8.65625 9.57639 8.125 10.8542 7.91667C10.8125 7.41667 10.6875 7.03819 10.4792 6.78125C10.2708 6.52431 9.98611 6.39583 9.625 6.39583C9.20833 6.39583 8.75694 6.56944 8.27083 6.91667C7.78472 7.26389 7.20833 7.83333 6.54167 8.625C5.45833 9.91667 4.66319 10.7569 4.15625 11.1458C3.64931 11.5347 3.10417 11.7292 2.52083 11.7292C1.8125 11.7292 1.21528 11.4653 0.729167 10.9375C0.243056 10.4097 0 9.77083 0 9.02083C0 8.27083 0.163194 7.50347 0.489583 6.71875C0.815972 5.93403 1.36806 4.99306 2.14583 3.89583C2.40972 3.53472 2.60417 3.22917 2.72917 2.97917C2.85417 2.72917 2.91667 2.52778 2.91667 2.375C2.91667 2.27778 2.89931 2.20486 2.86458 2.15625C2.82986 2.10764 2.77778 2.08333 2.70833 2.08333C2.56944 2.08333 2.39583 2.17014 2.1875 2.34375C1.97917 2.51736 1.73611 2.78472 1.45833 3.14583L0 1.66667C0.444444 1.125 0.895833 0.711806 1.35417 0.427083C1.8125 0.142361 2.26389 0 2.70833 0C3.34722 0 3.88889 0.222222 4.33333 0.666667C4.77778 1.11111 5 1.66667 5 2.33333C5 2.73611 4.89583 3.18056 4.6875 3.66667C4.47917 4.15278 4.13194 4.73611 3.64583 5.41667C3.11806 6.16667 2.72569 6.82639 2.46875 7.39583C2.21181 7.96528 2.08333 8.46528 2.08333 8.89583C2.08333 9.13194 2.12153 9.31597 2.19792 9.44792C2.27431 9.57986 2.38194 9.64583 2.52083 9.64583C2.65972 9.64583 2.78125 9.60764 2.88542 9.53125C2.98958 9.45486 3.18056 9.27083 3.45833 8.97917C3.63889 8.78472 3.85417 8.54514 4.10417 8.26042C4.35417 7.97569 4.65972 7.625 5.02083 7.20833C5.89583 6.16667 6.6875 5.42361 7.39583 4.97917C8.10417 4.53472 8.84722 4.3125 9.625 4.3125C10.5556 4.3125 11.3194 4.625 11.9167 5.25C12.5139 5.875 12.8542 6.72917 12.9375 7.8125H15V9.89583H12.9375C12.8264 11.4514 12.4201 12.691 11.7188 13.6146C11.0174 14.5382 10.125 15 9.04167 15ZM9.08333 12.9167C9.52778 12.9167 9.90278 12.6632 10.2083 12.1562C10.5139 11.6493 10.7222 10.9444 10.8333 10.0417C10.1944 10.1944 9.63889 10.4965 9.16667 10.9479C8.69444 11.3993 8.45833 11.8472 8.45833 12.2917C8.45833 12.4861 8.51389 12.6389 8.625 12.75C8.73611 12.8611 8.88889 12.9167 9.08333 12.9167Z" fill="currentColor"/></svg>` };
4881
5093
  this.handleDocumentVisibilityChange = () => {
4882
5094
  this.accountCtaMotionPaused = document.visibilityState !== "visible";
4883
- if (document.visibilityState === "visible" && !this.isOpen) this.flushPendingSignalPulse();
5095
+ this.refreshInspectorDismissalState();
5096
+ if (document.visibilityState === "visible" && !this.isOpen && !this.isInspectorDismissed) this.flushPendingSignalPulse();
4884
5097
  this.requestUpdate();
4885
5098
  };
4886
5099
  this.handlePillClick = (event) => {
@@ -4920,21 +5133,33 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
4920
5133
  this.handleHudActionClick = (event, row) => {
4921
5134
  event.preventDefault();
4922
5135
  event.stopPropagation();
4923
- this.hudLandingMenu = row === "inspector" ? null : row === "threads" ? "threads" : row === "learning" ? "memories" : "home";
5136
+ this.hudLandingMenu = row === "threads" ? "threads" : row === "learning" ? "memories" : "home";
4924
5137
  this.closeLauncherHud();
4925
5138
  this.openInspector("floating_button");
4926
5139
  };
4927
- this.handleHudHelpClick = (event, row) => {
4928
- event.preventDefault();
4929
- event.stopPropagation();
4930
- this.launcherHudHelp = this.launcherHudHelp === row ? null : row;
4931
- this.requestUpdate();
4932
- };
4933
5140
  this.handleHudRowClick = (event, row) => {
4934
5141
  const target = event.target;
4935
- if (target instanceof Element && target.closest(".cpk-launcher-hud__help, [data-cpk-hud-action]")) return;
5142
+ if (target instanceof Element && target.closest(".cpk-launcher-hud__controls, [data-cpk-hud-action]")) return;
4936
5143
  this.handleHudActionClick(event, row);
4937
5144
  };
5145
+ this.handleHudNewsClick = (event) => {
5146
+ event.preventDefault();
5147
+ event.stopPropagation();
5148
+ this.hudLandingMenu = WHATS_NEW_MENU_KEY;
5149
+ this.closeLauncherHud();
5150
+ this.openInspector("floating_button");
5151
+ };
5152
+ this.handleHudNewsDismissClick = (event) => {
5153
+ event.preventDefault();
5154
+ event.stopPropagation();
5155
+ this.clearNewsSignal();
5156
+ this.activeRoot.querySelector(".console-button")?.focus({ preventScroll: true });
5157
+ };
5158
+ this.handleHudDismissDayClick = (event) => {
5159
+ event.preventDefault();
5160
+ event.stopPropagation();
5161
+ this.dismissInspectorFor("day");
5162
+ };
4938
5163
  this.handleSidebarToggle = () => {
4939
5164
  this.sidebarRailTooltip = null;
4940
5165
  this.sidebarCollapsed = !this.sidebarCollapsed;
@@ -4977,6 +5202,51 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
4977
5202
  this.applyEventErrorLanding(key);
4978
5203
  this.requestUpdate();
4979
5204
  };
5205
+ this.handleHomeFeaturePromptCopy = async (service, event) => {
5206
+ const generation = this.homeFeaturePromptCopyGeneration += 1;
5207
+ if (this.homeFeaturePromptCopyResetTimeoutId !== null) {
5208
+ window.clearTimeout(this.homeFeaturePromptCopyResetTimeoutId);
5209
+ this.homeFeaturePromptCopyResetTimeoutId = null;
5210
+ }
5211
+ this.homeFeaturePromptCopyState = null;
5212
+ this.requestUpdate();
5213
+ const onboardingRunId = require_onboarding_prompt.createOnboardingRunId();
5214
+ if (!this.core?.telemetryDisabled) require_telemetry.trackHomeFeaturePromptClicked({
5215
+ feature_id: service.id,
5216
+ onboarding_run_id: onboardingRunId
5217
+ });
5218
+ const clipboard = this.getClipboard(event);
5219
+ if (!clipboard?.writeText) {
5220
+ this.showHomeFeaturePromptCopyState(service.id, "error", generation);
5221
+ return;
5222
+ }
5223
+ try {
5224
+ await clipboard.writeText(require_home_briefing.homeFeatureImplementationPrompt(service, { onboardingRunId }));
5225
+ this.showHomeFeaturePromptCopyState(service.id, "copied", generation);
5226
+ } catch {
5227
+ this.showHomeFeaturePromptCopyState(service.id, "error", generation);
5228
+ }
5229
+ };
5230
+ this.handleIntelligencePromptCopy = async (event) => {
5231
+ this.clearIntelligencePromptReset();
5232
+ const runId = this.getOnboardingRunId();
5233
+ const clipboard = this.getClipboard(event);
5234
+ let outcome = "failed";
5235
+ if (clipboard?.writeText) try {
5236
+ await clipboard.writeText(require_onboarding_prompt.createOnboardingPrompt(runId));
5237
+ outcome = "copied";
5238
+ } catch {
5239
+ outcome = "failed";
5240
+ }
5241
+ if (!this.isConnected) return;
5242
+ this.promptCopyState = outcome;
5243
+ this.requestUpdate();
5244
+ if (outcome === "copied") this.scheduleIntelligencePromptReset();
5245
+ if (!this.core?.telemetryDisabled) require_telemetry.trackHomePromptCopied({
5246
+ onboarding_run_id: runId,
5247
+ outcome
5248
+ });
5249
+ };
4980
5250
  this.handleSystemColorSchemeChange = (event) => {
4981
5251
  if (this.hasExplicitColorScheme) return;
4982
5252
  this.colorScheme = event.matches ? "dark" : "light";
@@ -5221,21 +5491,14 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
5221
5491
  this.startPlaygroundSession(false);
5222
5492
  return;
5223
5493
  }
5224
- const core = this._core;
5225
5494
  const thread = this._threads.find((candidate) => candidate.id === threadId);
5226
- if (!core?.runtimeUrl || !thread) return;
5495
+ if (!thread) return;
5227
5496
  this.playgroundIsLoadingThread = true;
5228
5497
  this.playgroundError = null;
5229
5498
  this.requestUpdate();
5230
5499
  try {
5231
- const baseUrl = core.runtimeUrl.replace(/\/+$/, "");
5232
- const encodedThreadId = encodeURIComponent(threadId);
5233
- const [messagesResponse, stateResponse] = await Promise.all([fetch(`${baseUrl}/threads/${encodedThreadId}/messages`, { headers: { ...core.headers } }), fetch(`${baseUrl}/threads/${encodedThreadId}/state`, { headers: { ...core.headers } })]);
5234
- if (!messagesResponse.ok) throw new Error(`Failed to load thread (HTTP ${messagesResponse.status}).`);
5235
- const messagesBody = await messagesResponse.json();
5236
- const stateBody = stateResponse.ok ? await stateResponse.json() : { state: {} };
5237
- this.startPlaygroundSession(false, this.mapThreadMessagesToPlayground(messagesBody.messages ?? []), stateBody.state ?? {}, thread.agentId);
5238
- this.playgroundSourceThreadId = threadId;
5500
+ const snapshot = await this.loadThreadSnapshot(thread);
5501
+ this.applyThreadSnapshotToPlayground(thread, snapshot);
5239
5502
  } catch (error) {
5240
5503
  this.playgroundError = error instanceof Error ? error.message : "Failed to load thread.";
5241
5504
  } finally {
@@ -5243,6 +5506,35 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
5243
5506
  this.requestUpdate();
5244
5507
  }
5245
5508
  };
5509
+ this.handleTryFromHere = async (threadId) => {
5510
+ if (!threadId || this.tryFromHereBusy) return;
5511
+ const thread = this._threads.find((candidate) => candidate.id === threadId) ?? null;
5512
+ if (!thread) return;
5513
+ this.tryFromHereBusy = true;
5514
+ this.tryFromHereError = null;
5515
+ this.requestUpdate();
5516
+ const isCurrentTryFromHereRequest = () => this.selectedThreadId === threadId && this.selectedMenu === "threads";
5517
+ try {
5518
+ const snapshot = await this.loadThreadSnapshot(thread);
5519
+ if (isCurrentTryFromHereRequest()) {
5520
+ this.applyThreadSnapshotToPlayground(thread, snapshot);
5521
+ this.handleMenuSelect("playground");
5522
+ }
5523
+ if (!this.core?.telemetryDisabled) require_telemetry.trackThreadsTryFromHereClicked({
5524
+ ...this.getThreadsTelemetryProps(),
5525
+ outcome: "success"
5526
+ });
5527
+ } catch (error) {
5528
+ if (isCurrentTryFromHereRequest()) this.tryFromHereError = error instanceof Error ? error.message : "Failed to load thread.";
5529
+ if (!this.core?.telemetryDisabled) require_telemetry.trackThreadsTryFromHereClicked({
5530
+ ...this.getThreadsTelemetryProps(),
5531
+ outcome: "failure"
5532
+ });
5533
+ } finally {
5534
+ this.tryFromHereBusy = false;
5535
+ this.requestUpdate();
5536
+ }
5537
+ };
5246
5538
  this.runPlaygroundAgent = async () => {
5247
5539
  const core = this._core;
5248
5540
  const agent = this.playgroundAgent;
@@ -5414,26 +5706,6 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
5414
5706
  }
5415
5707
  this.playThreadsExampleOverviewVideo(video, lifecycleGeneration);
5416
5708
  };
5417
- this.handleThreadsSetupPromptCopy = async (event) => {
5418
- const generation = this.threadsSetupPromptCopyGeneration += 1;
5419
- if (this.threadsSetupPromptCopyResetTimeoutId !== null) {
5420
- window.clearTimeout(this.threadsSetupPromptCopyResetTimeoutId);
5421
- this.threadsSetupPromptCopyResetTimeoutId = null;
5422
- }
5423
- this.threadsSetupPromptCopyState = "idle";
5424
- this.requestUpdate();
5425
- const clipboard = this.getClipboard(event);
5426
- if (!clipboard?.writeText) {
5427
- this.showThreadsSetupPromptCopyState("error", generation);
5428
- return;
5429
- }
5430
- try {
5431
- await clipboard.writeText(THREADS_RUNTIME_SETUP_PROMPT);
5432
- this.showThreadsSetupPromptCopyState("copied", generation);
5433
- } catch {
5434
- this.showThreadsSetupPromptCopyState("error", generation);
5435
- }
5436
- };
5437
5709
  this.handleClearEvents = () => {
5438
5710
  if (this.selectedContext === "all-agents") {
5439
5711
  this.agentEvents.clear();
@@ -5779,9 +6051,6 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
5779
6051
  getThreadsDocsUrl() {
5780
6052
  return this.appendRefParam(THREADS_DOCS_URL, "cpk-inspector-threads");
5781
6053
  }
5782
- getThreadsRuntimeSetupDocsUrl() {
5783
- return this.appendRefParam(THREADS_RUNTIME_SETUP_DOCS_URL, "cpk-inspector-threads");
5784
- }
5785
6054
  getThreadsIntelligenceSignupUrl() {
5786
6055
  return this.appendRefParam(INTELLIGENCE_SIGNUP_URL, "cpk-inspector-threads");
5787
6056
  }
@@ -5893,7 +6162,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
5893
6162
  if (this.core?.getThreadStore(agentId)) return;
5894
6163
  const core = this.core;
5895
6164
  if (!core?.runtimeUrl) return;
5896
- const store = (0, _copilotkit_core.ɵcreateThreadStore)({ fetch: globalThis.fetch });
6165
+ const store = (0, _copilotkit_core.ɵcreateThreadStore)({ fetch: typeof core.ɵruntimeFetch === "function" ? core.ɵruntimeFetch : globalThis.fetch });
5897
6166
  store.start();
5898
6167
  store.setContext({
5899
6168
  runtimeUrl: core.runtimeUrl,
@@ -6604,7 +6873,9 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
6604
6873
  <span>${functionName}${isFailedCall ? " failed" : ""}</span>
6605
6874
  <span class="text-[10px] text-gray-600">ID: ${callId}</span>
6606
6875
  </div>
6607
- ${isFailedCall && toolError?.message ? lit.html`<p class="mt-2 break-words leading-relaxed text-gray-800">
6876
+ ${isFailedCall && toolError?.message ? lit.html`<p
6877
+ class="mt-2 break-words leading-relaxed text-gray-800"
6878
+ >
6608
6879
  ${toolError.message}
6609
6880
  </p>` : lit.nothing}
6610
6881
  ${argsString ? lit.html`<div class="mt-2">
@@ -6833,13 +7104,15 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
6833
7104
 
6834
7105
  .cpk-playground-composer {
6835
7106
  border: 1px solid #dcdce8;
6836
- box-shadow: 0 8px 22px rgba(31, 23, 57, 0.08),
7107
+ box-shadow:
7108
+ 0 8px 22px rgba(31, 23, 57, 0.08),
6837
7109
  0 1px 2px rgba(31, 23, 57, 0.1);
6838
7110
  }
6839
7111
 
6840
7112
  .cpk-playground-composer:focus-within {
6841
7113
  border-color: #aaa4d4;
6842
- box-shadow: 0 10px 26px rgba(86, 53, 155, 0.13),
7114
+ box-shadow:
7115
+ 0 10px 26px rgba(86, 53, 155, 0.13),
6843
7116
  0 0 0 3px rgba(190, 194, 255, 0.3);
6844
7117
  }
6845
7118
 
@@ -6856,20 +7129,22 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
6856
7129
  .inspector-window[data-color-scheme="dark"] .cpk-playground-composer {
6857
7130
  border-color: #464957;
6858
7131
  background: #15171e !important;
6859
- box-shadow: 0 8px 22px rgba(0, 0, 0, 0.26),
7132
+ box-shadow:
7133
+ 0 8px 22px rgba(0, 0, 0, 0.26),
6860
7134
  0 1px 2px rgba(0, 0, 0, 0.36);
6861
7135
  }
6862
7136
 
6863
7137
  .inspector-window[data-color-scheme="dark"]
6864
7138
  .cpk-playground-composer:focus-within {
6865
7139
  border-color: #777aae;
6866
- box-shadow: 0 10px 26px rgba(0, 0, 0, 0.34),
7140
+ box-shadow:
7141
+ 0 10px 26px rgba(0, 0, 0, 0.34),
6867
7142
  0 0 0 3px rgba(102, 106, 158, 0.3);
6868
7143
  }
6869
7144
 
6870
7145
  .cpk-playground-message-enter {
6871
- animation: cpk-playground-message-enter 0.24s cubic-bezier(0.16, 1, 0.3, 1)
6872
- both;
7146
+ animation: cpk-playground-message-enter 0.24s
7147
+ cubic-bezier(0.16, 1, 0.3, 1) both;
6873
7148
  }
6874
7149
 
6875
7150
  .cpk-playground-thinking-dot {
@@ -6888,8 +7163,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
6888
7163
  display: none;
6889
7164
  }
6890
7165
 
6891
- .cpk-playground-reasoning[open]
6892
- .cpk-playground-reasoning-chevron {
7166
+ .cpk-playground-reasoning[open] .cpk-playground-reasoning-chevron {
6893
7167
  transform: rotate(90deg);
6894
7168
  }
6895
7169
 
@@ -7825,56 +8099,66 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
7825
8099
 
7826
8100
  .cpk-launcher-hud {
7827
8101
  --hud-fill: var(--cpk-inspector-surface-dark);
7828
- --hud-line: rgb(190 194 255 / 0.5);
8102
+ --hud-line: rgb(190 194 255 / 0.38);
8103
+ --hud-accent: #b8adf5;
8104
+ --hud-accent-soft: rgb(184 173 245 / 0.13);
8105
+ --hud-hover-fill: #252231;
7829
8106
  --hud-blur: blur(12px) saturate(1.2);
8107
+ --hud-card-gap: 8px;
8108
+ --hud-dismiss-day-height: 32px;
7830
8109
  position: absolute;
7831
- top: 0;
7832
8110
  z-index: 4;
7833
- padding-right: 14px;
8111
+ width: 258px;
7834
8112
  pointer-events: none;
7835
8113
  opacity: 0;
7836
8114
  visibility: hidden;
7837
- transform: translateX(8px);
7838
8115
  transition:
7839
8116
  opacity 160ms ease,
7840
8117
  transform 200ms cubic-bezier(0.16, 1, 0.3, 1);
7841
8118
  }
7842
8119
 
8120
+ .cpk-launcher-hud[data-cpk-hud-vertical="top"] {
8121
+ top: 0;
8122
+ bottom: auto;
8123
+ }
8124
+
8125
+ .cpk-launcher-hud[data-cpk-hud-vertical="bottom"] {
8126
+ top: auto;
8127
+ bottom: 0;
8128
+ }
8129
+
7843
8130
  .cpk-launcher-hud[data-cpk-hud-side="left"] {
7844
8131
  right: 100%;
8132
+ left: auto;
7845
8133
  padding-right: 14px;
7846
- padding-left: 0;
8134
+ transform: translateX(8px);
7847
8135
  }
7848
8136
 
7849
8137
  .cpk-launcher-hud[data-cpk-hud-side="right"] {
7850
8138
  left: 100%;
7851
8139
  right: auto;
7852
- padding-right: 0;
7853
8140
  padding-left: 14px;
7854
8141
  transform: translateX(-8px);
7855
8142
  }
7856
8143
 
7857
- .console-button-wrapper[data-cpk-hud="open"]
7858
- .cpk-launcher-hud[data-cpk-hud-side="right"] {
8144
+ .console-button-wrapper[data-cpk-hud="open"] .cpk-launcher-hud {
7859
8145
  transform: none;
7860
8146
  }
7861
8147
 
7862
8148
  .cpk-launcher-hud__card {
7863
8149
  position: relative;
7864
- width: 228px;
7865
- padding: 4px;
7866
- border: 1px dotted var(--hud-line);
7867
- border-radius: var(--cpk-inspector-shell-radius);
7868
- background: var(--hud-fill);
8150
+ display: grid;
8151
+ width: 244px;
8152
+ gap: var(--hud-card-gap);
7869
8153
  color: #fff;
7870
- backdrop-filter: var(--hud-blur);
7871
- -webkit-backdrop-filter: var(--hud-blur);
7872
- box-shadow: 0 8px 20px rgb(1 5 7 / 0.18);
7873
8154
  }
7874
8155
 
7875
8156
  .cpk-launcher-hud[data-color-scheme="light"] {
7876
8157
  --hud-fill: #fff;
7877
- --hud-line: #d8d8e8;
8158
+ --hud-line: #ddd6f4;
8159
+ --hud-accent: #6757b0;
8160
+ --hud-accent-soft: #f1edff;
8161
+ --hud-hover-fill: #f1edff;
7878
8162
  }
7879
8163
 
7880
8164
  .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__card {
@@ -7884,70 +8168,297 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
7884
8168
  .cpk-launcher-hud__arrow {
7885
8169
  position: absolute;
7886
8170
  top: calc(var(--cpk-launcher-size) / 2);
7887
- z-index: 1;
8171
+ z-index: 2;
7888
8172
  width: 10px;
7889
8173
  height: 10px;
7890
8174
  border: 0;
7891
- /* The card frosts the page behind it, so it reads lighter than the
7892
- raw fill. Mix a little white so the arrow matches the glass card
7893
- without going lighter than the HUD. */
7894
- background: color-mix(in srgb, var(--hud-fill) 88%, white 12%);
7895
- transform: translateY(-50%) rotate(45deg);
8175
+ background: var(--hud-fill);
8176
+ transform: rotate(45deg);
8177
+ transition: background 120ms ease;
7896
8178
  }
7897
8179
 
7898
8180
  .cpk-launcher-hud[data-cpk-hud-side="left"] .cpk-launcher-hud__arrow {
7899
8181
  right: 9px;
8182
+ border-top: 1px solid var(--hud-line);
8183
+ border-right: 1px solid var(--hud-line);
7900
8184
  }
7901
8185
 
7902
8186
  .cpk-launcher-hud[data-cpk-hud-side="right"] .cpk-launcher-hud__arrow {
7903
8187
  left: 9px;
8188
+ border-bottom: 1px solid var(--hud-line);
8189
+ border-left: 1px solid var(--hud-line);
7904
8190
  }
7905
8191
 
7906
- .cpk-launcher-hud__list {
7907
- margin: 0;
7908
- padding: 0;
7909
- list-style: none;
8192
+ .cpk-launcher-hud[data-cpk-hud-vertical="top"] .cpk-launcher-hud__arrow {
8193
+ top: calc(var(--cpk-launcher-size) / 2 - 5px);
7910
8194
  }
7911
8195
 
7912
- .cpk-launcher-hud__list + .cpk-launcher-hud__list {
7913
- margin-top: 4px;
7914
- padding-top: 4px;
7915
- border-top: 1px dotted var(--hud-line);
8196
+ .cpk-launcher-hud[data-cpk-hud-vertical="bottom"]
8197
+ .cpk-launcher-hud__arrow {
8198
+ top: auto;
8199
+ bottom: calc(var(--cpk-launcher-size) / 2 - 5px);
8200
+ }
8201
+
8202
+ /* A bottom-anchored HUD can end with the narrower dismissal bubble.
8203
+ Keep the pointer attached to the full-width feature panel instead of
8204
+ letting it float in the empty space beside that final action. */
8205
+ .cpk-launcher-hud[data-cpk-hud-vertical="bottom"]:has(
8206
+ .cpk-launcher-hud__dismiss-day
8207
+ )
8208
+ .cpk-launcher-hud__arrow {
8209
+ bottom: calc(
8210
+ var(--hud-dismiss-day-height) + var(--hud-card-gap) + 2px
8211
+ );
8212
+ }
8213
+
8214
+ .cpk-launcher-hud__list {
8215
+ margin: 0;
8216
+ padding: 0;
8217
+ list-style: none;
8218
+ }
8219
+
8220
+ .cpk-launcher-hud__masthead {
8221
+ position: relative;
8222
+ z-index: 1;
8223
+ margin-top: 6px;
8224
+ padding: 0;
8225
+ border: 1px solid var(--hud-line);
8226
+ border-radius: var(--cpk-inspector-shell-radius);
8227
+ background: var(--hud-fill);
8228
+ backdrop-filter: var(--hud-blur);
8229
+ -webkit-backdrop-filter: var(--hud-blur);
8230
+ box-shadow: 0 10px 28px rgb(46 37 91 / 0.16);
8231
+ transition: background 120ms ease;
8232
+ }
8233
+
8234
+ .cpk-launcher-hud__news-wrap {
8235
+ position: relative;
8236
+ margin: 0;
8237
+ }
8238
+
8239
+ .cpk-launcher-hud__news {
8240
+ position: relative;
8241
+ display: flex;
8242
+ width: 100%;
8243
+ min-width: 0;
8244
+ flex-direction: column;
8245
+ align-items: flex-start;
8246
+ padding: 18px 12px 11px;
8247
+ border: 0;
8248
+ border-radius: calc(var(--cpk-inspector-shell-radius) - 1px);
8249
+ background: transparent;
8250
+ color: #fff;
8251
+ font-family: inherit;
8252
+ line-height: 1;
8253
+ text-align: start;
8254
+ cursor: pointer;
8255
+ }
8256
+
8257
+ .cpk-launcher-hud__news:hover,
8258
+ .cpk-launcher-hud__news:focus-visible {
8259
+ background: transparent;
8260
+ }
8261
+
8262
+ .cpk-launcher-hud__masthead:has(.cpk-launcher-hud__news:hover),
8263
+ .cpk-launcher-hud__masthead:has(.cpk-launcher-hud__news:focus-visible),
8264
+ .cpk-launcher-hud:has(.cpk-launcher-hud__news:hover)
8265
+ .cpk-launcher-hud__arrow,
8266
+ .cpk-launcher-hud:has(.cpk-launcher-hud__news:focus-visible)
8267
+ .cpk-launcher-hud__arrow {
8268
+ background: var(--hud-hover-fill);
8269
+ }
8270
+
8271
+ .cpk-launcher-hud__news:focus-visible {
8272
+ outline: 2px solid #bec2ff;
8273
+ outline-offset: 1px;
8274
+ }
8275
+
8276
+ .cpk-launcher-hud__news-title {
8277
+ display: block;
8278
+ font-size: 12px;
8279
+ font-weight: 650;
8280
+ line-height: 1.32;
8281
+ overflow-wrap: anywhere;
8282
+ white-space: normal;
8283
+ }
8284
+
8285
+ .cpk-launcher-hud__news-label {
8286
+ position: absolute;
8287
+ top: -9px;
8288
+ left: 12px;
8289
+ display: inline-flex;
8290
+ min-height: 20px;
8291
+ align-items: center;
8292
+ padding: 3px 8px;
8293
+ border-radius: 6px;
8294
+ background: #7563c7;
8295
+ color: #fff;
8296
+ box-shadow: 0 3px 8px rgb(46 37 91 / 0.18);
8297
+ font-size: 9px;
8298
+ font-weight: 700;
8299
+ line-height: 1;
8300
+ }
8301
+
8302
+ .cpk-launcher-hud__news-dismiss {
8303
+ position: absolute;
8304
+ top: -1px;
8305
+ right: 2px;
8306
+ z-index: 2;
8307
+ display: inline-flex;
8308
+ width: 20px;
8309
+ height: 20px;
8310
+ align-items: center;
8311
+ justify-content: center;
8312
+ padding: 0;
8313
+ border: 0;
8314
+ border-radius: 4px;
8315
+ background: transparent;
8316
+ color: rgb(255 255 255 / 0.68);
8317
+ cursor: pointer;
8318
+ }
8319
+
8320
+ .cpk-launcher-hud__news-dismiss:hover,
8321
+ .cpk-launcher-hud__news-dismiss:focus-visible {
8322
+ background: var(--hud-accent-soft);
8323
+ color: #fff;
8324
+ }
8325
+
8326
+ .cpk-launcher-hud[data-color-scheme="light"]
8327
+ .cpk-launcher-hud__news-dismiss {
8328
+ color: #6e697c;
8329
+ }
8330
+
8331
+ .cpk-launcher-hud[data-color-scheme="light"]
8332
+ .cpk-launcher-hud__news-dismiss:hover,
8333
+ .cpk-launcher-hud[data-color-scheme="light"]
8334
+ .cpk-launcher-hud__news-dismiss:focus-visible {
8335
+ color: #27233a;
8336
+ }
8337
+
8338
+ .cpk-launcher-hud__news-dismiss:focus-visible {
8339
+ outline: 2px solid #bec2ff;
8340
+ outline-offset: 1px;
8341
+ }
8342
+
8343
+ .cpk-launcher-hud__news-dismiss svg {
8344
+ width: 7px;
8345
+ height: 7px;
8346
+ }
8347
+
8348
+ .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__news {
8349
+ color: #17131f;
8350
+ }
8351
+
8352
+ .cpk-launcher-hud__dismiss-day {
8353
+ position: relative;
8354
+ z-index: 1;
8355
+ display: flex;
8356
+ width: auto;
8357
+ min-height: var(--hud-dismiss-day-height);
8358
+ align-items: center;
8359
+ justify-content: center;
8360
+ justify-self: center;
8361
+ gap: 6px;
8362
+ margin: 0;
8363
+ padding: 7px 13px;
8364
+ border: 1px solid var(--hud-line);
8365
+ border-radius: var(--cpk-inspector-shell-radius);
8366
+ background: var(--hud-fill);
8367
+ color: #c9cad3;
8368
+ box-shadow: 0 8px 20px rgb(17 14 29 / 0.18);
8369
+ font-family: inherit;
8370
+ font-size: 10px;
8371
+ font-weight: 650;
8372
+ line-height: 1.2;
8373
+ cursor: pointer;
8374
+ transition:
8375
+ border-color 120ms ease,
8376
+ background 120ms ease,
8377
+ color 120ms ease;
8378
+ }
8379
+
8380
+ .cpk-launcher-hud__dismiss-day:hover,
8381
+ .cpk-launcher-hud__dismiss-day:focus-visible {
8382
+ border-color: var(--hud-accent);
8383
+ background: var(--hud-hover-fill);
8384
+ color: #f3f4f8;
8385
+ }
8386
+
8387
+ .cpk-launcher-hud__dismiss-day:focus-visible {
8388
+ outline: 2px solid #bec2ff;
8389
+ outline-offset: 1px;
8390
+ }
8391
+
8392
+ .cpk-launcher-hud__dismiss-day svg {
8393
+ width: 12px;
8394
+ height: 12px;
8395
+ }
8396
+
8397
+ .cpk-launcher-hud[data-color-scheme="light"]
8398
+ .cpk-launcher-hud__dismiss-day {
8399
+ box-shadow: 0 8px 20px rgb(46 37 91 / 0.12);
8400
+ color: #5f6068;
8401
+ }
8402
+
8403
+ .cpk-launcher-hud[data-color-scheme="light"]
8404
+ .cpk-launcher-hud__dismiss-day:hover,
8405
+ .cpk-launcher-hud[data-color-scheme="light"]
8406
+ .cpk-launcher-hud__dismiss-day:focus-visible {
8407
+ color: #36373d;
8408
+ }
8409
+
8410
+ .cpk-launcher-hud__feature-list {
8411
+ position: relative;
8412
+ z-index: 1;
8413
+ padding: 5px;
8414
+ border: 1px solid var(--hud-line);
8415
+ border-radius: var(--cpk-inspector-shell-radius);
8416
+ background: var(--hud-fill);
8417
+ backdrop-filter: var(--hud-blur);
8418
+ -webkit-backdrop-filter: var(--hud-blur);
8419
+ box-shadow: 0 10px 28px rgb(46 37 91 / 0.16);
7916
8420
  }
7917
8421
 
7918
8422
  .cpk-launcher-hud__row {
7919
8423
  position: relative;
7920
8424
  display: grid;
7921
- grid-template-columns: 1fr 28px;
7922
- align-items: start;
7923
- border-radius: 7px;
8425
+ grid-template-columns: minmax(0, 1fr) auto;
8426
+ align-items: center;
8427
+ min-height: 54px;
8428
+ border-radius: 9px;
7924
8429
  cursor: pointer;
7925
8430
  }
7926
8431
 
7927
8432
  .cpk-launcher-hud__row + .cpk-launcher-hud__row {
7928
- margin-top: 1px;
8433
+ border-top: 1px solid var(--hud-line);
8434
+ border-radius: 0 0 9px 9px;
7929
8435
  }
7930
8436
 
7931
8437
  .cpk-launcher-hud__row:hover,
7932
- .cpk-launcher-hud__row:focus-within,
7933
- .cpk-launcher-hud__row[data-cpk-hud-help="open"] {
8438
+ .cpk-launcher-hud__row:focus-within {
7934
8439
  background: rgb(255 255 255 / 0.06);
7935
8440
  }
7936
8441
 
7937
8442
  .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__row:hover,
7938
- .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__row:focus-within,
7939
- .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__row[data-cpk-hud-help="open"] {
7940
- background: #f0f0f4;
8443
+ .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__row:focus-within {
8444
+ background: #f7f5ff;
8445
+ }
8446
+
8447
+ .cpk-launcher-hud__primary {
8448
+ position: relative;
8449
+ display: flex;
8450
+ min-width: 0;
7941
8451
  }
7942
8452
 
7943
8453
  .cpk-launcher-hud__action {
7944
8454
  display: flex;
8455
+ width: 100%;
7945
8456
  gap: 8px;
7946
- min-height: 32px;
8457
+ min-height: 52px;
7947
8458
  align-items: center;
7948
- padding: 6px 8px;
8459
+ padding: 7px 4px;
7949
8460
  border: 0;
7950
- border-radius: 7px;
8461
+ border-radius: 9px;
7951
8462
  background: transparent;
7952
8463
  color: #fff;
7953
8464
  font-family: inherit;
@@ -7957,129 +8468,243 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
7957
8468
  cursor: pointer;
7958
8469
  }
7959
8470
 
8471
+ .cpk-launcher-hud__label {
8472
+ min-width: 0;
8473
+ }
8474
+
8475
+ .cpk-launcher-hud__feature-icon {
8476
+ display: inline-flex;
8477
+ width: 28px;
8478
+ height: 32px;
8479
+ flex: none;
8480
+ align-items: center;
8481
+ justify-content: center;
8482
+ background: transparent;
8483
+ color: var(--hud-accent);
8484
+ }
8485
+
8486
+ .cpk-launcher-hud__feature-icon svg {
8487
+ width: 17px;
8488
+ height: 17px;
8489
+ stroke-width: 1.8;
8490
+ }
8491
+
7960
8492
  .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__action {
7961
8493
  color: #010507;
7962
8494
  }
7963
8495
 
7964
- /* Stretch the row action over the whole tab, including the detail
7965
- copy. The help mark sits above this layer. */
8496
+ /* Stretch the row action over the whole tab. The icon controls sit
8497
+ above this layer and keep their own focused interactions. */
7966
8498
  .cpk-launcher-hud__action::after {
7967
8499
  content: "";
7968
8500
  position: absolute;
7969
8501
  inset: 0;
7970
8502
  }
7971
8503
 
7972
- .cpk-launcher-hud__check {
7973
- flex: none;
7974
- width: 14px;
7975
- height: 14px;
7976
- color: #34d399;
7977
- }
7978
-
7979
- .cpk-launcher-hud__help {
8504
+ .cpk-launcher-hud__controls {
7980
8505
  position: relative;
7981
8506
  z-index: 1;
8507
+ display: flex;
8508
+ gap: 0;
8509
+ align-items: center;
8510
+ padding-right: 5px;
8511
+ }
8512
+
8513
+ .cpk-launcher-hud__learn-more {
7982
8514
  display: inline-flex;
7983
- width: 28px;
7984
- height: 32px;
8515
+ width: 24px;
8516
+ height: 44px;
7985
8517
  align-items: center;
7986
8518
  justify-content: center;
7987
8519
  padding: 0;
7988
8520
  border: 0;
7989
8521
  background: transparent;
7990
- color: rgb(255 255 255 / 0.78);
7991
- font-size: 12px;
7992
- font-weight: 600;
8522
+ color: rgb(190 194 255 / 0.72);
7993
8523
  cursor: pointer;
7994
8524
  }
7995
8525
 
7996
- .cpk-launcher-hud__help span {
7997
- display: inline-flex;
8526
+ .cpk-launcher-hud__learn-more:hover,
8527
+ .cpk-launcher-hud__learn-more:focus-visible {
8528
+ color: #fff;
8529
+ }
8530
+
8531
+ .cpk-launcher-hud[data-color-scheme="light"]
8532
+ .cpk-launcher-hud__learn-more {
8533
+ color: #777080;
8534
+ }
8535
+
8536
+ .cpk-launcher-hud[data-color-scheme="light"]
8537
+ .cpk-launcher-hud__learn-more:hover,
8538
+ .cpk-launcher-hud[data-color-scheme="light"]
8539
+ .cpk-launcher-hud__learn-more:focus-visible {
8540
+ color: #4b416b;
8541
+ }
8542
+
8543
+ .cpk-launcher-hud__learn-more svg {
7998
8544
  width: 16px;
7999
8545
  height: 16px;
8546
+ stroke-width: 1.8;
8547
+ }
8548
+
8549
+ .cpk-launcher-hud__toggle {
8550
+ display: inline-flex;
8551
+ width: 38px;
8552
+ height: 44px;
8000
8553
  align-items: center;
8001
8554
  justify-content: center;
8002
- border: 1px dotted rgb(190 194 255 / 0.55);
8555
+ padding: 0;
8556
+ border: 0;
8557
+ background: transparent;
8558
+ color: rgb(255 255 255 / 0.78);
8559
+ font-size: 12px;
8560
+ font-weight: 600;
8561
+ cursor: pointer;
8562
+ }
8563
+
8564
+ .cpk-launcher-hud__toggle:disabled {
8565
+ cursor: not-allowed;
8566
+ opacity: 1;
8567
+ }
8568
+
8569
+ .cpk-launcher-hud__toggle-track {
8570
+ position: relative;
8571
+ display: block;
8572
+ width: 34px;
8573
+ height: 20px;
8574
+ border: 1px solid rgb(190 194 255 / 0.38);
8575
+ border-radius: 999px;
8576
+ background: rgb(255 255 255 / 0.08);
8577
+ transition:
8578
+ border-color 120ms ease,
8579
+ background 120ms ease;
8580
+ }
8581
+
8582
+ .cpk-launcher-hud__toggle-track::after {
8583
+ content: "";
8584
+ position: absolute;
8585
+ top: 2px;
8586
+ left: 2px;
8587
+ width: 14px;
8588
+ height: 14px;
8003
8589
  border-radius: 50%;
8004
- line-height: 1;
8590
+ background: #8c8e99;
8591
+ transition:
8592
+ background 120ms ease,
8593
+ transform 120ms ease;
8005
8594
  }
8006
8595
 
8007
- .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__help {
8008
- color: #68686e;
8596
+ .cpk-launcher-hud__toggle[data-enabled="true"]
8597
+ .cpk-launcher-hud__toggle-track {
8598
+ border-color: var(--hud-accent);
8599
+ background: color-mix(in srgb, var(--hud-accent) 76%, transparent);
8600
+ }
8601
+
8602
+ .cpk-launcher-hud__toggle[data-enabled="true"]
8603
+ .cpk-launcher-hud__toggle-track::after {
8604
+ background: #fff;
8605
+ transform: translateX(14px);
8606
+ }
8607
+
8608
+ .cpk-launcher-hud[data-color-scheme="light"]
8609
+ .cpk-launcher-hud__toggle-track {
8610
+ border-color: #c9c9d2;
8611
+ background: #e7e7ec;
8612
+ }
8613
+
8614
+ .cpk-launcher-hud[data-color-scheme="light"]
8615
+ .cpk-launcher-hud__toggle-track::after {
8616
+ background: #777780;
8617
+ }
8618
+
8619
+ .cpk-launcher-hud[data-color-scheme="light"]
8620
+ .cpk-launcher-hud__toggle[data-enabled="true"]
8621
+ .cpk-launcher-hud__toggle-track {
8622
+ border-color: #6757b0;
8623
+ background: #7563c7;
8624
+ }
8625
+
8626
+ .cpk-launcher-hud[data-color-scheme="light"]
8627
+ .cpk-launcher-hud__toggle[data-enabled="true"]
8628
+ .cpk-launcher-hud__toggle-track::after {
8629
+ background: #fff;
8009
8630
  }
8010
8631
 
8011
- .cpk-launcher-hud__help:focus-visible,
8632
+ .cpk-launcher-hud__toggle:focus-visible,
8633
+ .cpk-launcher-hud__learn-more:focus-visible,
8012
8634
  .cpk-launcher-hud__action:focus-visible {
8013
8635
  outline: 2px solid #bec2ff;
8014
8636
  outline-offset: 1px;
8015
8637
  }
8016
8638
 
8017
- .cpk-launcher-hud__detail {
8018
- grid-column: 1 / -1;
8019
- max-height: 0;
8020
- margin: 0;
8021
- padding: 0 8px;
8022
- overflow: hidden;
8023
- color: rgb(255 255 255 / 0.78);
8024
- font-size: 11px;
8025
- font-weight: 400;
8026
- line-height: 1.4;
8639
+ .cpk-launcher-hud__tooltip {
8640
+ position: absolute;
8641
+ top: 50%;
8642
+ z-index: 30;
8643
+ width: max-content;
8644
+ max-width: min(220px, 52vw);
8645
+ padding: 7px 9px;
8646
+ border: 1px solid #3a3d49;
8647
+ border-radius: 4px;
8648
+ background: #15171e;
8649
+ color: #f3f4f8;
8650
+ box-shadow: 0 8px 20px rgb(1 5 7 / 0.18);
8651
+ font-size: 10px;
8652
+ font-weight: 500;
8653
+ line-height: 1.45;
8027
8654
  opacity: 0;
8028
8655
  pointer-events: none;
8029
- transform: translateY(-6px);
8656
+ transform: translate(3px, -50%);
8657
+ white-space: normal;
8030
8658
  transition:
8031
- max-height 200ms cubic-bezier(0.16, 1, 0.3, 1),
8032
- opacity 150ms ease-out,
8033
- transform 200ms cubic-bezier(0.16, 1, 0.3, 1),
8034
- padding-bottom 200ms cubic-bezier(0.16, 1, 0.3, 1);
8659
+ opacity 120ms ease,
8660
+ transform 120ms ease;
8035
8661
  }
8036
8662
 
8037
- .cpk-launcher-hud[data-color-scheme="light"] .cpk-launcher-hud__detail {
8038
- color: #68686e;
8663
+ .cpk-launcher-hud__row:has(.cpk-launcher-hud__learn-more:hover)
8664
+ .cpk-launcher-hud__tooltip,
8665
+ .cpk-launcher-hud__row:has(.cpk-launcher-hud__learn-more:focus-visible)
8666
+ .cpk-launcher-hud__tooltip {
8667
+ opacity: 1;
8668
+ transform: translate(0, -50%);
8039
8669
  }
8040
8670
 
8041
- .cpk-launcher-hud__row:hover .cpk-launcher-hud__detail,
8042
- .cpk-launcher-hud__row:focus-within .cpk-launcher-hud__detail,
8043
- .cpk-launcher-hud__row[data-cpk-hud-help="open"] .cpk-launcher-hud__detail {
8044
- max-height: 72px;
8045
- padding: 0 8px 7px;
8046
- opacity: 1;
8047
- transform: none;
8671
+ .cpk-launcher-hud[data-cpk-hud-side="left"] .cpk-launcher-hud__tooltip {
8672
+ right: calc(100% + 8px);
8673
+ left: auto;
8674
+ }
8675
+
8676
+ .cpk-launcher-hud[data-cpk-hud-side="right"] .cpk-launcher-hud__tooltip {
8677
+ right: auto;
8678
+ left: calc(100% + 8px);
8679
+ transform: translate(-3px, -50%);
8680
+ }
8681
+
8682
+ .cpk-launcher-hud[data-cpk-hud-side="right"]
8683
+ .cpk-launcher-hud__row:has(.cpk-launcher-hud__learn-more:hover)
8684
+ .cpk-launcher-hud__tooltip,
8685
+ .cpk-launcher-hud[data-cpk-hud-side="right"]
8686
+ .cpk-launcher-hud__row:has(.cpk-launcher-hud__learn-more:focus-visible)
8687
+ .cpk-launcher-hud__tooltip {
8688
+ transform: translate(0, -50%);
8048
8689
  }
8049
8690
 
8050
8691
  @media (prefers-reduced-motion: reduce) {
8051
8692
  .cpk-launcher-hud,
8052
- .cpk-launcher-hud__detail {
8693
+ .cpk-launcher-hud__tooltip {
8053
8694
  transition: none;
8054
8695
  }
8055
8696
  }
8056
8697
 
8057
8698
  /*
8058
8699
  * On mount, borrow the hover HUD for one short introduction. The card
8059
- * establishes the destination first; its rows then resolve in order so
8060
- * the eye can count the available features instead of receiving one
8061
- * undifferentiated block. Only opacity and transform move.
8700
+ * establishes the destination first; notification, features, and hide
8701
+ * action then fall into place from top to bottom. Only opacity and
8702
+ * transform move.
8062
8703
  */
8063
8704
  @keyframes cpk-launcher-hud-intro {
8064
8705
  0% {
8065
8706
  opacity: 0;
8066
- transform: translateX(8px);
8067
- }
8068
- 8%,
8069
- 88% {
8070
- opacity: 1;
8071
- transform: none;
8072
- }
8073
- 100% {
8074
- opacity: 0;
8075
- transform: translateX(4px);
8076
- }
8077
- }
8078
-
8079
- @keyframes cpk-launcher-hud-intro-right {
8080
- 0% {
8081
- opacity: 0;
8082
- transform: translateX(-8px);
8707
+ transform: translateY(-4px);
8083
8708
  }
8084
8709
  8%,
8085
8710
  88% {
@@ -8088,14 +8713,14 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
8088
8713
  }
8089
8714
  100% {
8090
8715
  opacity: 0;
8091
- transform: translateX(-4px);
8716
+ transform: translateY(3px);
8092
8717
  }
8093
8718
  }
8094
8719
 
8095
- @keyframes cpk-launcher-hud-row-online {
8720
+ @keyframes cpk-launcher-hud-waterfall {
8096
8721
  from {
8097
8722
  opacity: 0;
8098
- transform: translateY(4px);
8723
+ transform: translateY(-8px);
8099
8724
  }
8100
8725
  to {
8101
8726
  opacity: 1;
@@ -8103,48 +8728,33 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
8103
8728
  }
8104
8729
  }
8105
8730
 
8106
- @keyframes cpk-launcher-hud-check-online {
8107
- from {
8108
- opacity: 0;
8109
- transform: scale(0.65);
8110
- }
8111
- to {
8112
- opacity: 1;
8113
- transform: scale(1);
8114
- }
8115
- }
8116
-
8117
8731
  .cpk-launcher-hud[data-cpk-hud-intro="true"] {
8118
- animation: cpk-launcher-hud-intro
8119
- var(--cpk-launcher-hud-intro-duration)
8120
- cubic-bezier(0.16, 1, 0.3, 1) both;
8121
- }
8122
-
8123
- .cpk-launcher-hud[data-cpk-hud-intro="true"][data-cpk-hud-side="right"] {
8124
- animation-name: cpk-launcher-hud-intro-right;
8125
- }
8126
-
8127
- .cpk-launcher-hud[data-cpk-hud-intro="true"]
8128
- .cpk-launcher-hud__row {
8129
- animation: cpk-launcher-hud-row-online
8130
- var(--cpk-launcher-hud-row-duration)
8732
+ animation: cpk-launcher-hud-intro var(--cpk-launcher-hud-intro-duration)
8131
8733
  cubic-bezier(0.16, 1, 0.3, 1) both;
8132
- animation-delay: var(--cpk-hud-row-delay);
8133
8734
  }
8134
8735
 
8135
8736
  .cpk-launcher-hud[data-cpk-hud-intro="true"]
8136
- .cpk-launcher-hud__check {
8137
- animation: cpk-launcher-hud-check-online 220ms
8737
+ :is(
8738
+ .cpk-launcher-hud__masthead,
8739
+ .cpk-launcher-hud__feature-list,
8740
+ .cpk-launcher-hud__row,
8741
+ .cpk-launcher-hud__dismiss-day
8742
+ ) {
8743
+ animation: cpk-launcher-hud-waterfall
8744
+ var(--cpk-launcher-hud-waterfall-duration)
8138
8745
  cubic-bezier(0.16, 1, 0.3, 1) both;
8139
- animation-delay: calc(var(--cpk-hud-row-delay) + 90ms);
8746
+ animation-delay: var(--cpk-hud-waterfall-delay);
8140
8747
  }
8141
8748
 
8142
8749
  @media (prefers-reduced-motion: reduce) {
8143
8750
  .cpk-launcher-hud[data-cpk-hud-intro="true"],
8144
8751
  .cpk-launcher-hud[data-cpk-hud-intro="true"]
8145
- .cpk-launcher-hud__row,
8146
- .cpk-launcher-hud[data-cpk-hud-intro="true"]
8147
- .cpk-launcher-hud__check {
8752
+ :is(
8753
+ .cpk-launcher-hud__masthead,
8754
+ .cpk-launcher-hud__feature-list,
8755
+ .cpk-launcher-hud__row,
8756
+ .cpk-launcher-hud__dismiss-day
8757
+ ) {
8148
8758
  animation: none !important;
8149
8759
  opacity: 1;
8150
8760
  transform: none;
@@ -8188,15 +8798,15 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
8188
8798
  }
8189
8799
 
8190
8800
  .inspector-account-strip {
8191
- background: linear-gradient(
8192
- 90deg,
8193
- #ffffff 0%,
8194
- #f3f1ff 58%,
8195
- #eefbf7 100%
8196
- ) !important;
8801
+ background: #f7f6fd !important;
8197
8802
  color: #010507 !important;
8198
8803
  }
8199
8804
 
8805
+ .inspector-window[data-color-scheme="dark"] .drag-handle,
8806
+ .inspector-window[data-color-scheme="dark"] .inspector-account-strip {
8807
+ background: #15171e !important;
8808
+ }
8809
+
8200
8810
  /* ── Tab buttons ─────────────────────────────────────────────── */
8201
8811
  /*
8202
8812
  * Named classes owned by this component — no Tailwind conflict.
@@ -8311,7 +8921,9 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
8311
8921
  .inspector-sidebar[data-icon-rail="true"]
8312
8922
  .inspector-context-dropdown-icon
8313
8923
  svg,
8314
- .inspector-sidebar[data-icon-rail="true"] .inspector-agent-placeholder svg {
8924
+ .inspector-sidebar[data-icon-rail="true"]
8925
+ .inspector-agent-placeholder
8926
+ svg {
8315
8927
  width: 18px !important;
8316
8928
  height: 18px !important;
8317
8929
  overflow: visible !important;
@@ -8557,11 +9169,12 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
8557
9169
  const viteHot = {}.hot;
8558
9170
  if (viteHot) viteHot.on("vite:beforeUpdate", this.handleAppBeforeUnload);
8559
9171
  this.hydrateStateFromStorageEarly();
9172
+ this.refreshInspectorDismissalState();
8560
9173
  this.subscribeToSystemColorScheme();
8561
9174
  this.exampleTourDismissed = this.readThreadsExampleTourDismissed();
8562
9175
  require_persistence.clearLegacyAnnouncementReadState();
8563
9176
  this.tryAutoAttachCore();
8564
- this.ensureAnnouncementLoading();
9177
+ if (!this.isInspectorDismissed) this.ensureAnnouncementLoading();
8565
9178
  this.subscribeToInspectorThreadBridge();
8566
9179
  }
8567
9180
  this.requestUpdate();
@@ -8587,15 +9200,18 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
8587
9200
  }
8588
9201
  this.clearIconRailContextCloseTimer();
8589
9202
  this.unsubscribeFromInspectorThreadBridge();
8590
- this.threadsSetupPromptCopyGeneration += 1;
8591
- if (this.threadsSetupPromptCopyResetTimeoutId !== null) {
8592
- window.clearTimeout(this.threadsSetupPromptCopyResetTimeoutId);
8593
- this.threadsSetupPromptCopyResetTimeoutId = null;
8594
- }
8595
- this.threadsSetupPromptCopyState = "idle";
9203
+ this.stopIntelligenceStory();
9204
+ this.clearIntelligencePromptReset();
9205
+ this.homeFeaturePromptCopyGeneration += 1;
9206
+ if (this.homeFeaturePromptCopyResetTimeoutId !== null) {
9207
+ window.clearTimeout(this.homeFeaturePromptCopyResetTimeoutId);
9208
+ this.homeFeaturePromptCopyResetTimeoutId = null;
9209
+ }
9210
+ this.homeFeaturePromptCopyState = null;
8596
9211
  this.stopSignalPulse();
8597
9212
  this.cancelGestureTail();
8598
9213
  this.cancelLauncherHudIntro();
9214
+ this.clearInspectorDismissalTimer();
8599
9215
  this.cancelThreadRefreshDebounce();
8600
9216
  this.clearInspectorUsageRefresh();
8601
9217
  this.cleanupThreadsExampleOverviewVideo();
@@ -8630,11 +9246,13 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
8630
9246
  this.applyAnchorPosition("button");
8631
9247
  if (this.dockMode === "floating") if (this.hasCustomPosition.window) this.applyAnchorPosition("window");
8632
9248
  else this.centerContext("window");
8633
- this.ensureAnnouncementLoading();
9249
+ if (this.isInspectorDismissed) this.persistState();
9250
+ else this.ensureAnnouncementLoading();
8634
9251
  this.updateHostTransform(this.isOpen ? "window" : "button");
8635
- this.scheduleLauncherHudIntro();
9252
+ if (!this.isInspectorDismissed) this.scheduleLauncherHudIntro();
8636
9253
  }
8637
9254
  render() {
9255
+ if (this.isInspectorDismissed) return lit.nothing;
8638
9256
  return this.isOpen ? lit.html`
8639
9257
  <div data-inspector-portal-anchor></div>
8640
9258
  ` : this.renderButton();
@@ -8656,6 +9274,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
8656
9274
  this.maybeCompleteEventErrorView();
8657
9275
  this.flushErrorLandingScroll();
8658
9276
  this.maybeTrackHomeViewed();
9277
+ this.syncIntelligenceStory();
8659
9278
  if (!this.isOpen) {
8660
9279
  this.lastScrolledAgentNavigationLayout = null;
8661
9280
  return;
@@ -8726,7 +9345,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
8726
9345
  aria-expanded=${this.launcherHudOpen ? "true" : "false"}
8727
9346
  aria-controls=${this.launcherHudOpen ? "cpk-launcher-hud" : lit.nothing}
8728
9347
  aria-label=${signal && signal.tone === "error" ? `${LAUNCHER_BASE_LABEL}, ${signal.accessibleLabel}` : LAUNCHER_BASE_LABEL}
8729
- title=${activeSignal === NEWS_SIGNAL_ID ? `${WHATS_NEW_VIEW_LABEL} — unread` : lit.nothing}
9348
+ title=${HUD_INSPECTOR_LABEL}
8730
9349
  data-drag-context="button"
8731
9350
  data-cpk-signal=${signal ? signal.tone : lit.nothing}
8732
9351
  data-cpk-signal-pulsing=${activeSignal !== null && this.pulsingSignal === activeSignal ? "true" : lit.nothing}
@@ -8811,14 +9430,78 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
8811
9430
  </span>
8812
9431
  `;
8813
9432
  }
9433
+ /** Whether a persisted temporary dismissal is still active. */
9434
+ get isInspectorDismissed() {
9435
+ return this.inspectorDismissedUntil !== null && this.inspectorDismissedUntil > Date.now();
9436
+ }
9437
+ /** Cancel the timer that restores Inspector after a temporary dismissal. */
9438
+ clearInspectorDismissalTimer() {
9439
+ if (this.inspectorDismissalTimer === null) return;
9440
+ clearTimeout(this.inspectorDismissalTimer);
9441
+ this.inspectorDismissalTimer = null;
9442
+ }
9443
+ /** Schedule Inspector to return just after its persisted deadline. */
9444
+ scheduleInspectorDismissalExpiry() {
9445
+ this.clearInspectorDismissalTimer();
9446
+ if (this.inspectorDismissedUntil === null) return;
9447
+ const delay = Math.max(0, this.inspectorDismissedUntil - Date.now() + 25);
9448
+ this.inspectorDismissalTimer = setTimeout(() => {
9449
+ this.inspectorDismissalTimer = null;
9450
+ this.refreshInspectorDismissalState();
9451
+ }, delay);
9452
+ }
9453
+ /** Reconcile this tab with host-scoped dismissal state from other ports. */
9454
+ refreshInspectorDismissalState() {
9455
+ const hadDismissal = this.inspectorDismissedUntil !== null;
9456
+ this.inspectorDismissedUntil = require_persistence.loadInspectorDismissedUntil();
9457
+ this.clearInspectorDismissalTimer();
9458
+ if (this.inspectorDismissedUntil !== null) {
9459
+ this.closePopOut();
9460
+ this.closeInspector();
9461
+ this.scheduleInspectorDismissalExpiry();
9462
+ if (!hadDismissal) this.requestUpdate();
9463
+ return;
9464
+ }
9465
+ if (!hadDismissal || !this.isConnected) return;
9466
+ this.ensureAnnouncementLoading();
9467
+ this.requestUpdate();
9468
+ this.updateComplete.then(() => {
9469
+ if (!this.isConnected || this.isInspectorDismissed) return;
9470
+ this.measureContext("button");
9471
+ this.applyAnchorPosition("button");
9472
+ this.scheduleLauncherHudIntro();
9473
+ this.flushPendingSignalPulse();
9474
+ });
9475
+ }
9476
+ /** Hide Inspector for a supported duration and persist it for this host. */
9477
+ dismissInspectorFor(duration) {
9478
+ const now = Date.now();
9479
+ const until = now + INSPECTOR_DISMISSAL_MS[duration];
9480
+ require_persistence.saveInspectorDismissedUntil(until, now);
9481
+ this.inspectorDismissedUntil = until;
9482
+ this.scheduleInspectorDismissalExpiry();
9483
+ this.settingsOpen = false;
9484
+ this.closeLauncherHud();
9485
+ this.stopSignalPulse();
9486
+ this.cancelGestureTail();
9487
+ this.cancelLauncherHudIntro();
9488
+ this.closePopOut();
9489
+ if (this.isOpen) {
9490
+ this.closeInspector();
9491
+ return;
9492
+ }
9493
+ this.persistState();
9494
+ this.requestUpdate();
9495
+ }
8814
9496
  isLauncherHudBlocked() {
8815
- return this.gestureSignal !== null;
9497
+ return this.gestureSignal !== null || this.isInspectorDismissed;
8816
9498
  }
8817
9499
  scheduleLauncherHudIntro(delay = LAUNCHER_HUD_INTRO_MS.delay) {
9500
+ if (this.isInspectorDismissed) return;
8818
9501
  if (this.launcherHudIntroStartTimer !== null) clearTimeout(this.launcherHudIntroStartTimer);
8819
9502
  this.launcherHudIntroStartTimer = setTimeout(() => {
8820
9503
  this.launcherHudIntroStartTimer = null;
8821
- if (!this.isConnected || this.isOpen) return;
9504
+ if (!this.isConnected || this.isOpen || this.isInspectorDismissed) return;
8822
9505
  if (this.isLauncherHudBlocked()) {
8823
9506
  this.scheduleLauncherHudIntro(LAUNCHER_HUD_INTRO_MS.blockedRetry);
8824
9507
  return;
@@ -8831,7 +9514,6 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
8831
9514
  this.launcherHudIntroEndTimer = null;
8832
9515
  this.launcherHudIntro = false;
8833
9516
  this.launcherHudOpen = false;
8834
- this.launcherHudHelp = null;
8835
9517
  this.requestUpdate();
8836
9518
  }, LAUNCHER_HUD_INTRO_MS.duration);
8837
9519
  }, delay);
@@ -8882,67 +9564,78 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
8882
9564
  clearTimeout(this.launcherHudCloseTimer);
8883
9565
  this.launcherHudCloseTimer = null;
8884
9566
  }
8885
- if (!this.launcherHudOpen && this.launcherHudHelp === null) return;
9567
+ if (!this.launcherHudOpen) return;
8886
9568
  this.launcherHudOpen = false;
8887
- this.launcherHudHelp = null;
8888
9569
  this.requestUpdate();
8889
9570
  }
8890
- renderHudCheck() {
8891
- return lit.html`
8892
- <svg
8893
- class="cpk-launcher-hud__check"
8894
- viewBox="0 0 16 16"
8895
- aria-hidden="true"
8896
- focusable="false"
8897
- data-cpk-hud-check
8898
- >
8899
- <path
8900
- fill="none"
8901
- stroke="currentColor"
8902
- stroke-width="2"
8903
- stroke-linecap="round"
8904
- stroke-linejoin="round"
8905
- d="M3 8.5 6.5 12 13 4.5"
8906
- />
8907
- </svg>
8908
- `;
9571
+ getUnreadAnnouncementTitle() {
9572
+ if (!this.newsSignalArmed || !this.announcementLoaded) return null;
9573
+ const title = this.announcementPreviewText?.trim() || "New in CopilotKit";
9574
+ const titleCharacters = Array.from(title);
9575
+ return titleCharacters.length > HUD_ANNOUNCEMENT_TITLE_LIMIT ? `${titleCharacters.slice(0, HUD_ANNOUNCEMENT_TITLE_LIMIT).join("").trimEnd()}...` : title;
8909
9576
  }
8910
9577
  renderHudRow(args) {
8911
- const helpOpen = this.launcherHudHelp === args.id;
8912
9578
  const detailId = `cpk-hud-detail-${args.id}`;
8913
9579
  return lit.html`
8914
9580
  <li
8915
9581
  class="cpk-launcher-hud__row"
8916
9582
  data-cpk-hud-row=${args.id}
8917
- data-cpk-hud-help=${helpOpen ? "open" : lit.nothing}
8918
- style=${(0, lit_directives_style_map_js.styleMap)({
8919
- "--cpk-hud-row-index": `${args.introIndex}`,
8920
- "--cpk-hud-row-delay": `${LAUNCHER_HUD_INTRO_MS.rowStart + args.introIndex * LAUNCHER_HUD_INTRO_MS.rowStagger}ms`
8921
- })}
9583
+ data-cpk-hud-action-kind="navigate"
9584
+ style=${(0, lit_directives_style_map_js.styleMap)({ "--cpk-hud-waterfall-delay": launcherHudWaterfallDelay(args.introIndex) })}
8922
9585
  @click=${(event) => this.handleHudRowClick(event, args.id)}
8923
9586
  >
8924
- <button
8925
- type="button"
8926
- class="cpk-launcher-hud__action"
8927
- data-cpk-hud-action
8928
- aria-describedby=${detailId}
8929
- @click=${(event) => this.handleHudActionClick(event, args.id)}
8930
- @pointerdown=${(event) => event.stopPropagation()}
8931
- >
8932
- ${args.connected ? this.renderHudCheck() : lit.nothing}${args.label}
8933
- </button>
8934
- <button
8935
- type="button"
8936
- class="cpk-launcher-hud__help"
8937
- aria-expanded=${helpOpen ? "true" : "false"}
8938
- aria-controls=${detailId}
8939
- aria-label=${`About ${args.label}`}
8940
- @click=${(event) => this.handleHudHelpClick(event, args.id)}
8941
- @pointerdown=${(event) => event.stopPropagation()}
8942
- >
8943
- <span aria-hidden="true">?</span>
8944
- </button>
8945
- <p class="cpk-launcher-hud__detail" id=${detailId}>${args.detail}</p>
9587
+ <span class="cpk-launcher-hud__primary">
9588
+ <button
9589
+ type="button"
9590
+ class="cpk-launcher-hud__action"
9591
+ data-cpk-hud-action
9592
+ aria-label=${`Open ${args.label} in Inspector`}
9593
+ @click=${(event) => this.handleHudActionClick(event, args.id)}
9594
+ @pointerdown=${(event) => event.stopPropagation()}
9595
+ >
9596
+ <span
9597
+ class="cpk-launcher-hud__feature-icon"
9598
+ data-cpk-hud-icon=${args.id}
9599
+ aria-hidden="true"
9600
+ >${this.renderIcon(args.icon)}</span
9601
+ >
9602
+ <span class="cpk-launcher-hud__label">${args.label}</span>
9603
+ </button>
9604
+ <span
9605
+ class="cpk-launcher-hud__tooltip"
9606
+ id=${detailId}
9607
+ role="tooltip"
9608
+ >${HUD_LEARN_MORE_LABEL}</span
9609
+ >
9610
+ </span>
9611
+ <span class="cpk-launcher-hud__controls">
9612
+ <button
9613
+ type="button"
9614
+ class="cpk-launcher-hud__learn-more"
9615
+ data-cpk-hud-learn-more=${args.id}
9616
+ aria-label=${`Learn more about ${args.label}`}
9617
+ aria-describedby=${detailId}
9618
+ @click=${(event) => this.handleHudActionClick(event, args.id)}
9619
+ @pointerdown=${(event) => event.stopPropagation()}
9620
+ >
9621
+ ${this.renderIcon("CircleHelp")}
9622
+ </button>
9623
+ <button
9624
+ type="button"
9625
+ class="cpk-launcher-hud__toggle"
9626
+ data-cpk-hud-toggle=${args.id}
9627
+ data-enabled=${args.connected ? "true" : "false"}
9628
+ aria-label=${args.connected ? `${args.label} is enabled` : `Open ${args.label} in Inspector`}
9629
+ ?disabled=${args.connected}
9630
+ @click=${(event) => this.handleHudActionClick(event, args.id)}
9631
+ @pointerdown=${(event) => event.stopPropagation()}
9632
+ >
9633
+ <span
9634
+ class="cpk-launcher-hud__toggle-track"
9635
+ aria-hidden="true"
9636
+ ></span>
9637
+ </button>
9638
+ </span>
8946
9639
  </li>
8947
9640
  `;
8948
9641
  }
@@ -8951,53 +9644,92 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
8951
9644
  const homeModel = this.getHomeModel();
8952
9645
  const threadsOn = homeModel.services.some((service) => service.id === "threads" && service.enabled);
8953
9646
  const learningOn = homeModel.services.some((service) => service.id === "memory" && service.enabled);
8954
- const intelligenceOn = homeModel.hero.connection === "connected";
9647
+ const announcementTitle = this.getUnreadAnnouncementTitle();
9648
+ const featureBlockIntroIndex = announcementTitle ? 1 : 0;
8955
9649
  return lit.html`
8956
9650
  <div
8957
9651
  class="cpk-launcher-hud"
8958
9652
  id="cpk-launcher-hud"
8959
9653
  data-cpk-launcher-hud
8960
9654
  data-cpk-hud-side=${this.launcherHudSide}
9655
+ data-cpk-hud-vertical=${this.contextState.button.anchor.vertical}
8961
9656
  data-cpk-hud-intro=${this.launcherHudIntro ? "true" : lit.nothing}
8962
9657
  data-color-scheme=${this.colorScheme}
8963
9658
  style=${(0, lit_directives_style_map_js.styleMap)({
8964
9659
  "--cpk-launcher-hud-intro-duration": `${LAUNCHER_HUD_INTRO_MS.duration}ms`,
8965
- "--cpk-launcher-hud-row-duration": `${LAUNCHER_HUD_INTRO_MS.rowDuration}ms`
9660
+ "--cpk-launcher-hud-waterfall-duration": `${LAUNCHER_HUD_INTRO_MS.waterfallDuration}ms`
8966
9661
  })}
8967
9662
  >
8968
9663
  <span class="cpk-launcher-hud__arrow" aria-hidden="true"></span>
8969
9664
  <div class="cpk-launcher-hud__card">
8970
- <ul class="cpk-launcher-hud__list" role="list">
8971
- ${this.renderHudRow({
8972
- id: "inspector",
8973
- label: HUD_OPEN_INSPECTOR_LABEL,
8974
- detail: HUD_OPEN_INSPECTOR_DETAIL,
8975
- introIndex: 0
8976
- })}
8977
- </ul>
8978
- <ul class="cpk-launcher-hud__list" role="list">
9665
+ ${announcementTitle ? lit.html`
9666
+ <div
9667
+ class="cpk-launcher-hud__masthead"
9668
+ style=${(0, lit_directives_style_map_js.styleMap)({ "--cpk-hud-waterfall-delay": launcherHudWaterfallDelay(0) })}
9669
+ >
9670
+ <div class="cpk-launcher-hud__news-wrap">
9671
+ <button
9672
+ type="button"
9673
+ class="cpk-launcher-hud__news"
9674
+ data-cpk-hud-news
9675
+ aria-label=${`Open new notification: ${announcementTitle}`}
9676
+ @click=${this.handleHudNewsClick}
9677
+ @pointerdown=${(event) => event.stopPropagation()}
9678
+ >
9679
+ <span
9680
+ class="cpk-launcher-hud__news-label"
9681
+ data-cpk-hud-news-label
9682
+ aria-hidden="true"
9683
+ >New</span
9684
+ >
9685
+ <span class="cpk-launcher-hud__news-title"
9686
+ >${announcementTitle}</span
9687
+ >
9688
+ </button>
9689
+ <button
9690
+ type="button"
9691
+ class="cpk-launcher-hud__news-dismiss"
9692
+ data-cpk-hud-news-dismiss
9693
+ aria-label="Dismiss notification"
9694
+ @click=${this.handleHudNewsDismissClick}
9695
+ @pointerdown=${(event) => event.stopPropagation()}
9696
+ >
9697
+ ${this.renderIcon("X")}
9698
+ </button>
9699
+ </div>
9700
+ </div>
9701
+ ` : lit.nothing}
9702
+ <ul
9703
+ class="cpk-launcher-hud__list cpk-launcher-hud__feature-list"
9704
+ role="list"
9705
+ style=${(0, lit_directives_style_map_js.styleMap)({ "--cpk-hud-waterfall-delay": launcherHudWaterfallDelay(featureBlockIntroIndex) })}
9706
+ >
8979
9707
  ${this.renderHudRow({
8980
9708
  id: "threads",
8981
- label: threadsOn ? HUD_THREADS_ON_LABEL : HUD_THREADS_OFF_LABEL,
8982
- detail: threadsOn ? HUD_THREADS_ON_DETAIL : HUD_THREADS_OFF_DETAIL,
9709
+ label: HUD_THREADS_LABEL,
9710
+ icon: "MessageSquare",
8983
9711
  connected: threadsOn,
8984
- introIndex: 1
8985
- })}
8986
- ${this.renderHudRow({
8987
- id: "intelligence",
8988
- label: intelligenceOn ? HUD_INTELLIGENCE_ON_LABEL : HUD_INTELLIGENCE_OFF_LABEL,
8989
- detail: intelligenceOn ? HUD_INTELLIGENCE_ON_DETAIL : HUD_INTELLIGENCE_OFF_DETAIL,
8990
- connected: intelligenceOn,
8991
- introIndex: 2
9712
+ introIndex: featureBlockIntroIndex + 1
8992
9713
  })}
8993
9714
  ${this.renderHudRow({
8994
9715
  id: "learning",
8995
- label: learningOn ? HUD_LEARNING_ON_LABEL : HUD_LEARNING_OFF_LABEL,
8996
- detail: learningOn ? HUD_LEARNING_ON_DETAIL : HUD_LEARNING_OFF_DETAIL,
9716
+ label: HUD_LEARNING_LABEL,
9717
+ icon: "Brain",
8997
9718
  connected: learningOn,
8998
- introIndex: 3
9719
+ introIndex: featureBlockIntroIndex + 2
8999
9720
  })}
9000
9721
  </ul>
9722
+ <button
9723
+ type="button"
9724
+ class="cpk-launcher-hud__dismiss-day"
9725
+ data-cpk-dismiss-inspector="day"
9726
+ style=${(0, lit_directives_style_map_js.styleMap)({ "--cpk-hud-waterfall-delay": launcherHudWaterfallDelay(featureBlockIntroIndex + 3) })}
9727
+ @click=${this.handleHudDismissDayClick}
9728
+ @pointerdown=${(event) => event.stopPropagation()}
9729
+ >
9730
+ <span aria-hidden="true">${this.renderIcon("Clock")}</span>
9731
+ Hide Inspector for a day
9732
+ </button>
9001
9733
  </div>
9002
9734
  </div>
9003
9735
  `;
@@ -9084,12 +9816,12 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
9084
9816
  </span>
9085
9817
  <span class="inspector-nav-label">${item.label}</span>
9086
9818
  ${marker ? lit.html`
9087
- <span
9088
- class="inspector-nav-signal-dot"
9089
- data-cpk-signal-tone=${marker.tone}
9090
- aria-hidden="true"
9091
- ></span>
9092
- ` : lit.nothing}
9819
+ <span
9820
+ class="inspector-nav-signal-dot"
9821
+ data-cpk-signal-tone=${marker.tone}
9822
+ aria-hidden="true"
9823
+ ></span>
9824
+ ` : lit.nothing}
9093
9825
  </button>
9094
9826
  `;
9095
9827
  })}
@@ -9218,7 +9950,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
9218
9950
  type: lastRuntimeEvent.type,
9219
9951
  timestamp: lastRuntimeEvent.timestamp
9220
9952
  } : void 0,
9221
- memoriesOn: this._memoriesAvailable,
9953
+ memoriesOn: this._memorySubscribed && !this._memoriesLoading && this._memoriesAvailable,
9222
9954
  a2uiOn: this._core?.a2uiEnabled === true,
9223
9955
  openGenUiOn: this._core?.openGenerativeUIEnabled === true,
9224
9956
  suggestionsOn: this._core?.suggestions === true,
@@ -9330,23 +10062,37 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
9330
10062
  const connected = model.hero.connection === "connected";
9331
10063
  const action = model.hero.action;
9332
10064
  const renewing = action?.kind === "renew";
10065
+ const installing = !connected && !renewing;
9333
10066
  return lit.html`
9334
10067
  <section
9335
10068
  class="inspector-home-section inspector-intelligence-hud"
9336
10069
  data-inspector-home-card="intelligence"
9337
10070
  data-state=${connected ? "connected" : "disconnected"}
10071
+ data-mode=${connected ? "connected" : renewing ? "renew" : "install"}
9338
10072
  aria-label="Intelligence ${connected ? "connected" : renewing ? "plan expired" : "not enabled"}"
9339
10073
  >
9340
10074
  <header class="inspector-intelligence-hud-header">
9341
10075
  <div class="inspector-intelligence-hud-heading">
9342
10076
  <h2 class="inspector-home-section-title">
10077
+ ${installing ? lit.html`
10078
+ <img
10079
+ class="inspector-intelligence-mark"
10080
+ src=${require_inspector_logo_kite.default}
10081
+ alt=""
10082
+ aria-hidden="true"
10083
+ />
10084
+ ` : lit.nothing}
9343
10085
  ${connected ? "Intelligence" : model.hero.title}
9344
10086
  </h2>
9345
- ${connected ? lit.nothing : lit.html`
9346
- <p class="inspector-intelligence-hud-description">
9347
- ${model.hero.body}
9348
- </p>
9349
- `}
10087
+ ${connected ? lit.nothing : installing ? lit.html`
10088
+ <p class="inspector-intelligence-sr-summary">
10089
+ ${model.hero.body}
10090
+ </p>
10091
+ ` : lit.html`
10092
+ <p class="inspector-intelligence-hud-description">
10093
+ ${model.hero.body}
10094
+ </p>
10095
+ `}
9350
10096
  </div>
9351
10097
  <div class="inspector-intelligence-hud-header-actions">
9352
10098
  ${connected || renewing ? lit.html`
@@ -9358,7 +10104,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
9358
10104
  ${connected ? "Connected" : "Plan expired"}
9359
10105
  </span>
9360
10106
  ` : lit.nothing}
9361
- ${!connected && action ? lit.html`
10107
+ ${renewing && action ? lit.html`
9362
10108
  <a
9363
10109
  class="inspector-intelligence-hud-action inspector-intelligence-hud-connect-action"
9364
10110
  data-inspector-home-intelligence-action=${action.kind}
@@ -9372,9 +10118,18 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
9372
10118
  ${action.label} ${this.renderIcon("ArrowUpRight")}
9373
10119
  </a>
9374
10120
  ` : lit.nothing}
10121
+ ${installing ? this.renderIntelligenceInstallActions(action) : lit.nothing}
9375
10122
  </div>
9376
10123
  </header>
9377
10124
 
10125
+ ${installing && this.promptCopyState === "failed" ? lit.html`
10126
+ <code
10127
+ class="inspector-intelligence-install-fallback"
10128
+ tabindex="0"
10129
+ >${require_onboarding_prompt.createOnboardingPrompt(this.getOnboardingRunId())}</code
10130
+ >
10131
+ ` : lit.nothing}
10132
+ ${installing ? this.renderIntelligenceStory() : lit.nothing}
9378
10133
  ${connected ? lit.html`
9379
10134
  <div
9380
10135
  class="inspector-intelligence-hud-details"
@@ -9603,23 +10358,67 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
9603
10358
  renderHomeFeatures(model) {
9604
10359
  const enabledServices = model.services.filter((service) => service.enabled);
9605
10360
  const disabledServices = model.services.filter((service) => !service.enabled);
9606
- const renderService = (service) => lit.html`
9607
- <a
10361
+ const renderService = (service) => {
10362
+ const copyState = this.homeFeaturePromptCopyState?.serviceId === service.id ? this.homeFeaturePromptCopyState.state : "idle";
10363
+ const stateDescription = `${service.label} is ${service.enabled ? "enabled in your runtime" : "not enabled in your runtime"}`;
10364
+ const copyLabel = copyState === "copied" ? "Copied" : copyState === "error" ? "Copy failed" : "Copy prompt";
10365
+ const copyTitle = copyLabel;
10366
+ return lit.html`
10367
+ <div
9608
10368
  class="inspector-home-feature"
9609
10369
  data-inspector-service=${service.id}
9610
10370
  data-state=${service.enabled ? "on" : "off"}
9611
- href=${this.appendRefParam(service.docsUrl, "cpk-inspector-home")}
9612
- target="_blank"
9613
- rel="noopener noreferrer"
9614
- aria-label="Learn more about ${service.label}, currently ${service.enabled ? "on" : "off"}"
10371
+ role="listitem"
9615
10372
  >
9616
- <span>${service.label}</span>
9617
- <small>${service.enabled ? "On" : "Off"}</small>
9618
- <span class="inspector-home-feature-arrow" aria-hidden="true">
9619
- ${this.renderIcon("ArrowUpRight")}
10373
+ <span
10374
+ class="inspector-home-feature-status"
10375
+ role="img"
10376
+ aria-label=${stateDescription}
10377
+ title=${stateDescription}
10378
+ >
10379
+ <span aria-hidden="true"></span>
9620
10380
  </span>
9621
- </a>
10381
+ <a
10382
+ class="inspector-home-feature-label"
10383
+ data-inspector-home-feature-docs=${service.id}
10384
+ href=${this.appendRefParam(service.docsUrl, "cpk-inspector-home")}
10385
+ target="_blank"
10386
+ rel="noopener noreferrer"
10387
+ aria-label="Open ${service.label} documentation in a new tab"
10388
+ >
10389
+ <span>${service.label}</span>
10390
+ <span class="inspector-home-feature-label-icon" aria-hidden="true"
10391
+ >${this.renderIcon("ArrowUpRight")}</span
10392
+ >
10393
+ </a>
10394
+ <span class="inspector-home-feature-actions">
10395
+ ${service.enabled ? lit.nothing : lit.html`
10396
+ <button
10397
+ type="button"
10398
+ class="inspector-home-feature-action inspector-system-health-url"
10399
+ data-inspector-home-feature-prompt=${service.id}
10400
+ data-copy-state=${copyState}
10401
+ data-full-value=${copyTitle}
10402
+ aria-label="${copyLabel} for ${service.label}"
10403
+ @click=${(event) => this.handleHomeFeaturePromptCopy(service, event)}
10404
+ >
10405
+ <span class="inspector-home-feature-action-icon" aria-hidden="true"
10406
+ >${this.renderIcon(copyState === "copied" ? "Check" : "Bot")}</span
10407
+ >
10408
+ <span class="inspector-home-feature-action-label"
10409
+ >${copyTitle}</span
10410
+ >
10411
+ </button>
10412
+ `}
10413
+ ${service.enabled ? lit.nothing : lit.html`
10414
+ <span class="sr-only" aria-live="polite">
10415
+ ${copyState === "copied" ? `${service.label} implementation prompt copied.` : copyState === "error" ? `Could not copy the ${service.label} implementation prompt.` : ""}
10416
+ </span>
10417
+ `}
10418
+ </span>
10419
+ </div>
9622
10420
  `;
10421
+ };
9623
10422
  return lit.html`
9624
10423
  <section
9625
10424
  class="inspector-home-section inspector-home-features"
@@ -9628,7 +10427,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
9628
10427
  <header class="inspector-home-section-header">
9629
10428
  <h2 class="inspector-home-section-title">Features</h2>
9630
10429
  <span>
9631
- ${enabledServices.length} active, ${disabledServices.length} off
10430
+ ${enabledServices.length} enabled, ${disabledServices.length} available
9632
10431
  </span>
9633
10432
  </header>
9634
10433
  ${model.services.length === 0 ? lit.html`
@@ -9640,13 +10439,13 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
9640
10439
  <section
9641
10440
  class="inspector-home-feature-group"
9642
10441
  data-feature-state-group="active"
9643
- aria-label="Active features"
10442
+ aria-label="Enabled features"
9644
10443
  >
9645
10444
  <header class="inspector-home-feature-group-header">
9646
- <strong>Active</strong>
10445
+ <strong>Enabled</strong>
9647
10446
  <span>${enabledServices.length}</span>
9648
10447
  </header>
9649
- <div class="inspector-home-feature-list">
10448
+ <div class="inspector-home-feature-list" role="list">
9650
10449
  ${enabledServices.length > 0 ? enabledServices.map(renderService) : lit.html`
9651
10450
  <p class="inspector-home-feature-group-empty">None enabled</p>
9652
10451
  `}
@@ -9655,26 +10454,437 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
9655
10454
  <section
9656
10455
  class="inspector-home-feature-group"
9657
10456
  data-feature-state-group="available"
9658
- aria-label="Available features"
10457
+ aria-label="Features available to add"
10458
+ >
10459
+ <header class="inspector-home-feature-group-header">
10460
+ <strong>Available to add</strong>
10461
+ <span>${disabledServices.length}</span>
10462
+ </header>
10463
+ <div class="inspector-home-feature-list" role="list">
10464
+ ${disabledServices.length > 0 ? disabledServices.map(renderService) : lit.html`
10465
+ <p class="inspector-home-feature-group-empty">Everything is active</p>
10466
+ `}
10467
+ </div>
10468
+ </section>
10469
+ </div>
10470
+ `}
10471
+ </section>
10472
+ `;
10473
+ }
10474
+ showHomeFeaturePromptCopyState(serviceId, state, generation) {
10475
+ if (!this.isConnected || generation !== this.homeFeaturePromptCopyGeneration) return;
10476
+ if (this.homeFeaturePromptCopyResetTimeoutId !== null) window.clearTimeout(this.homeFeaturePromptCopyResetTimeoutId);
10477
+ this.homeFeaturePromptCopyState = {
10478
+ serviceId,
10479
+ state
10480
+ };
10481
+ this.requestUpdate();
10482
+ this.homeFeaturePromptCopyResetTimeoutId = window.setTimeout(() => {
10483
+ if (!this.isConnected || generation !== this.homeFeaturePromptCopyGeneration) return;
10484
+ this.homeFeaturePromptCopyState = null;
10485
+ this.homeFeaturePromptCopyResetTimeoutId = null;
10486
+ this.requestUpdate();
10487
+ }, 2e3);
10488
+ }
10489
+ getHomeFeaturePromptTarget(serviceId) {
10490
+ return this.getHomeModel().services.find((service) => service.id === serviceId);
10491
+ }
10492
+ renderFeatureSetupPrompt(serviceId, className) {
10493
+ const service = this.getHomeFeaturePromptTarget(serviceId);
10494
+ if (!service) return lit.nothing;
10495
+ const copyState = this.homeFeaturePromptCopyState?.serviceId === service.id ? this.homeFeaturePromptCopyState.state : "idle";
10496
+ const label = copyState === "copied" ? "Copied" : copyState === "error" ? "Copy blocked" : "Copy setup prompt";
10497
+ return lit.html`
10498
+ <button
10499
+ type="button"
10500
+ class=${className}
10501
+ data-inspector-feature-setup-prompt=${service.id}
10502
+ data-inspector-threads-setup-prompt=${service.id === "threads" ? "" : lit.nothing}
10503
+ data-copy-state=${copyState}
10504
+ aria-label=${copyState === "copied" ? `${service.label} setup prompt copied` : copyState === "error" ? `Could not copy the ${service.label} setup prompt. Try again` : `Copy setup prompt for ${service.label}`}
10505
+ @click=${(event) => this.handleHomeFeaturePromptCopy(service, event)}
10506
+ >
10507
+ ${this.renderIcon(copyState === "copied" ? "Check" : "Copy")}
10508
+ ${label}
10509
+ </button>
10510
+ <span class="sr-only" aria-live="polite">
10511
+ ${copyState === "copied" ? `${service.label} setup prompt copied.` : copyState === "error" ? `Could not copy the ${service.label} setup prompt.` : ""}
10512
+ </span>
10513
+ `;
10514
+ }
10515
+ handleHomeHeroCta(action) {
10516
+ if (this.core?.telemetryDisabled) return;
10517
+ require_telemetry.trackHomeCtaClicked({ action_kind: action.kind });
10518
+ }
10519
+ /**
10520
+ * The install row: copy the prompt, or fall back to the signup page.
10521
+ *
10522
+ * The prompt is primary and the link is secondary, which is the inversion
10523
+ * this card exists for. Leaving for a signup page is where developers drop
10524
+ * out; pasting into the editor they are already in is not.
10525
+ *
10526
+ * No third-party coding-agent logos here, unlike the Intelligence app. That
10527
+ * app is a private hosted surface; this one is a published npm package
10528
+ * embedded in other people's sites, and shipping Anthropic's and OpenAI's
10529
+ * marks inside it is a trademark call that is not ours to make quietly. The
10530
+ * helper line names the agents in text instead.
10531
+ */
10532
+ renderIntelligenceInstallActions(action) {
10533
+ const copied = this.promptCopyState === "copied";
10534
+ const failed = this.promptCopyState === "failed";
10535
+ return lit.html`
10536
+ <div
10537
+ class="inspector-intelligence-install"
10538
+ data-copy-state=${this.promptCopyState}
10539
+ >
10540
+ ${this.promptCopyState === "idle" ? action ? lit.html`
10541
+ <a
10542
+ class="inspector-intelligence-install-secondary"
10543
+ data-inspector-home-intelligence-action=${action.kind}
10544
+ href=${action.url}
10545
+ target="_blank"
10546
+ rel="noopener noreferrer"
10547
+ aria-label="Set Intelligence up yourself (opens in a new tab)"
10548
+ style=${INTERACTIVE_FOCUS_BASE_STYLE}
10549
+ @click=${() => this.handleHomeHeroCta(action)}
10550
+ >
10551
+ Set it up yourself ${this.renderIcon("ArrowUpRight")}
10552
+ </a>
10553
+ ` : lit.nothing : lit.html`
10554
+ <p
10555
+ class="inspector-intelligence-install-hint"
10556
+ data-tone=${failed ? "error" : "success"}
10557
+ role="status"
10558
+ >
10559
+ ${failed ? "Clipboard blocked — copy the prompt below." : "Paste it into your coding agent."}
10560
+ </p>
10561
+ `}
10562
+ <button
10563
+ type="button"
10564
+ class="inspector-intelligence-hud-action inspector-intelligence-install-copy"
10565
+ data-inspector-intelligence-copy-prompt
10566
+ aria-label=${copied ? "Install prompt copied to clipboard. Paste it into your coding agent." : "Copy the Intelligence install prompt"}
10567
+ style=${INTERACTIVE_FOCUS_BASE_STYLE}
10568
+ @click=${this.handleIntelligencePromptCopy}
10569
+ >
10570
+ ${this.renderIcon(copied ? "Check" : "ClipboardCopy")}
10571
+ ${copied ? "Prompt copied" : "Copy setup prompt"}
10572
+ </button>
10573
+ </div>
10574
+ `;
10575
+ }
10576
+ /** One run id per element lifetime; minted on first use, never rotated. */
10577
+ getOnboardingRunId() {
10578
+ this.onboardingRunId ??= require_onboarding_prompt.createOnboardingRunId();
10579
+ return this.onboardingRunId;
10580
+ }
10581
+ /**
10582
+ * Return the button and its secondary line to the idle state.
10583
+ *
10584
+ * Long enough to read six words, short enough that a developer who went to
10585
+ * their editor and came back — because the paste went somewhere wrong, or
10586
+ * the terminal is gone — finds a button that plainly invites a second press
10587
+ * rather than a spent one wearing a checkmark.
10588
+ *
10589
+ * Only the copied state resets. A failed copy has the prompt on screen for
10590
+ * manual selection, and yanking that away mid-drag would be worse than the
10591
+ * clipboard failing in the first place.
10592
+ */
10593
+ scheduleIntelligencePromptReset() {
10594
+ this.clearIntelligencePromptReset();
10595
+ this.promptCopyResetTimer = setTimeout(() => {
10596
+ this.promptCopyResetTimer = null;
10597
+ if (!this.isConnected || this.promptCopyState !== "copied") return;
10598
+ this.promptCopyState = "idle";
10599
+ this.requestUpdate();
10600
+ }, PROMPT_COPY_RESET_MS);
10601
+ }
10602
+ clearIntelligencePromptReset() {
10603
+ if (this.promptCopyResetTimer !== null) {
10604
+ clearTimeout(this.promptCopyResetTimer);
10605
+ this.promptCopyResetTimer = null;
10606
+ }
10607
+ }
10608
+ /**
10609
+ * The three-beat Intelligence story.
10610
+ *
10611
+ * Every beat is in the DOM at all times and switched by opacity, so the
10612
+ * strip never reflows and screen readers get one stable structure. The
10613
+ * caption is the live text; the beats themselves are decorative and hidden
10614
+ * from assistive tech, because reading out a mocked code listing helps
10615
+ * nobody.
10616
+ */
10617
+ /**
10618
+ * The rotating argument, paired to whatever the picture below is showing.
10619
+ *
10620
+ * Hidden from assistive tech: a sentence that replaces itself every few
10621
+ * seconds is noise in a screen reader, so the stable summary above carries
10622
+ * the message there instead. Both sentences are always in the DOM and only
10623
+ * their opacity changes, so the block cannot reflow and the card never jumps
10624
+ * height mid-loop.
10625
+ */
10626
+ /**
10627
+ * Where a slide sits relative to the one on screen.
10628
+ *
10629
+ * This is what makes the motion agree with the rail: the rail reads left to
10630
+ * right, so a slide that has not been reached yet waits to the right, and one
10631
+ * already passed leaves to the left. Deriving it from the indices rather than
10632
+ * remembering a direction means clicking backwards through the tabs animates
10633
+ * backwards for free, with no state to keep in sync. The loop's wrap from the
10634
+ * last tab to the first therefore reads as a rewind, which is what it is.
10635
+ */
10636
+ intelligenceSlidePosition(index) {
10637
+ if (index === this.intelStoryBeat) return "active";
10638
+ return index < this.intelStoryBeat ? "before" : "after";
10639
+ }
10640
+ /** Same rule, addressed by beat id, for the picture halves. */
10641
+ intelligenceBeatPosition(beatId) {
10642
+ return this.intelligenceSlidePosition(INTELLIGENCE_STORY_BEATS.findIndex((beat) => beat.id === beatId));
10643
+ }
10644
+ renderIntelligenceStoryCopy() {
10645
+ return lit.html`
10646
+ <div
10647
+ class="inspector-intelligence-copy"
10648
+ data-inspector-intelligence-copy
10649
+ data-beat=${INTELLIGENCE_STORY_BEATS[this.intelStoryBeat]?.id ?? "threads"}
10650
+ aria-hidden="true"
10651
+ >
10652
+ ${INTELLIGENCE_STORY_BEATS.map((beat, index) => lit.html`
10653
+ <div
10654
+ class="inspector-intelligence-copy-slide"
10655
+ data-beat-id=${beat.id}
10656
+ data-active=${index === this.intelStoryBeat}
10657
+ data-position=${this.intelligenceSlidePosition(index)}
10658
+ >
10659
+ <strong>${beat.lead}</strong>
10660
+ <span>${beat.support}</span>
10661
+ </div>
10662
+ `)}
10663
+ </div>
10664
+ `;
10665
+ }
10666
+ renderIntelligenceStory() {
10667
+ return lit.html`
10668
+ <section
10669
+ class="inspector-intelligence-story"
10670
+ data-inspector-intelligence-story
10671
+ data-beat=${INTELLIGENCE_STORY_BEATS[this.intelStoryBeat]?.id ?? "threads"}
10672
+ >
10673
+ ${this.renderIntelligenceStoryCopy()}
10674
+ <div class="inspector-intelligence-story-stage" aria-hidden="true">
10675
+ ${this.renderIntelligenceStoryThreads()}
10676
+ ${this.renderIntelligenceStoryLearning()}
10677
+ ${this.renderIntelligenceStorySkill()}
10678
+ ${this.renderIntelligenceStoryReuse()}
10679
+ </div>
10680
+ <div
10681
+ class="inspector-intelligence-story-rail"
10682
+ role="tablist"
10683
+ aria-label="What Intelligence adds"
10684
+ >
10685
+ ${INTELLIGENCE_STORY_BEATS.map((beat, index) => lit.html`
10686
+ <button
10687
+ type="button"
10688
+ role="tab"
10689
+ class="inspector-intelligence-story-tab"
10690
+ aria-selected=${index === this.intelStoryBeat}
10691
+ data-active=${index === this.intelStoryBeat}
10692
+ style=${INTERACTIVE_FOCUS_BASE_STYLE}
10693
+ @click=${() => this.pinIntelligenceStoryBeat(index)}
10694
+ >
10695
+ ${beat.label}
10696
+ </button>
10697
+ `)}
10698
+ </div>
10699
+ </section>
10700
+ `;
10701
+ }
10702
+ /** Beat 1 — the developer's own users' conversations, one of them broken. */
10703
+ renderIntelligenceStoryThreads() {
10704
+ return lit.html`
10705
+ <div
10706
+ class="inspector-intelligence-beat"
10707
+ data-beat-id="threads"
10708
+ data-position=${this.intelligenceBeatPosition("threads")}
10709
+ >
10710
+ <div class="inspector-intelligence-threads">
10711
+ ${INTELLIGENCE_STORY_THREADS.map((thread, index) => lit.html`
10712
+ <span
10713
+ class="inspector-intelligence-thread"
10714
+ data-failed=${thread.failed}
10715
+ style="--thread-index:${index}"
10716
+ >
10717
+ <i></i>
10718
+ <strong>${thread.title}</strong>
10719
+ <small>${thread.meta}</small>
10720
+ </span>
10721
+ `)}
10722
+ </div>
10723
+ </div>
10724
+ `;
10725
+ }
10726
+ renderIntelligenceStoryLearning() {
10727
+ return lit.html`
10728
+ <div
10729
+ class="inspector-intelligence-beat"
10730
+ data-beat-id="learning"
10731
+ data-position=${this.intelligenceBeatPosition("learning")}
10732
+ >
10733
+ <div class="inspector-intelligence-beat-col">
10734
+ <span class="inspector-intelligence-beat-label">
10735
+ Signals from ${INTELLIGENCE_STORY_SIGNALS.length} threads
10736
+ </span>
10737
+ ${INTELLIGENCE_STORY_SIGNALS.map((signal, index) => lit.html`
10738
+ <span
10739
+ class="inspector-intelligence-signal"
10740
+ style="--signal-index:${index}"
10741
+ >${signal}</span
10742
+ >
10743
+ `)}
10744
+ </div>
10745
+ <div class="inspector-intelligence-beat-flow">
10746
+ ${this.renderIcon("ArrowRight")}
10747
+ </div>
10748
+ <div class="inspector-intelligence-beat-col">
10749
+ <span class="inspector-intelligence-beat-label">
10750
+ Reusable pattern
10751
+ </span>
10752
+ ${INTELLIGENCE_STORY_RULES.map((rule, index) => lit.html`
10753
+ <span
10754
+ class="inspector-intelligence-rule"
10755
+ style="--rule-index:${index}"
10756
+ >
10757
+ <i>${this.renderIcon("Check")}</i>${rule}
10758
+ </span>
10759
+ `)}
10760
+ </div>
10761
+ </div>
10762
+ `;
10763
+ }
10764
+ renderIntelligenceStorySkill() {
10765
+ return lit.html`
10766
+ <div
10767
+ class="inspector-intelligence-beat"
10768
+ data-beat-id="skill"
10769
+ data-position=${this.intelligenceBeatPosition("skill")}
10770
+ >
10771
+ <div class="inspector-intelligence-skill-file">
10772
+ <header>
10773
+ ${this.renderIcon("FileText")}
10774
+ <strong>${INTELLIGENCE_STORY_SKILL_FILE}</strong>
10775
+ <em>Pending review</em>
10776
+ </header>
10777
+ <div class="inspector-intelligence-skill-code">
10778
+ <span data-line="1"><b># Meeting scheduling</b></span>
10779
+ <span data-line="2">When planning a meeting:</span>
10780
+ ${INTELLIGENCE_STORY_RULES.map((rule, index) => lit.html`
10781
+ <span data-line=${index + 3} style="--rule-index:${index}"
10782
+ >${index + 1}. ${rule}</span
9659
10783
  >
9660
- <header class="inspector-home-feature-group-header">
9661
- <strong>Available</strong>
9662
- <span>${disabledServices.length}</span>
9663
- </header>
9664
- <div class="inspector-home-feature-list">
9665
- ${disabledServices.length > 0 ? disabledServices.map(renderService) : lit.html`
9666
- <p class="inspector-home-feature-group-empty">Everything is active</p>
9667
- `}
9668
- </div>
9669
- </section>
9670
- </div>
9671
- `}
9672
- </section>
10784
+ `)}
10785
+ </div>
10786
+ </div>
10787
+ </div>
9673
10788
  `;
9674
10789
  }
9675
- handleHomeHeroCta(action) {
9676
- if (this.core?.telemetryDisabled) return;
9677
- require_telemetry.trackHomeCtaClicked({ action_kind: action.kind });
10790
+ renderIntelligenceStoryReuse() {
10791
+ return lit.html`
10792
+ <div
10793
+ class="inspector-intelligence-beat"
10794
+ data-beat-id="intelligence"
10795
+ data-position=${this.intelligenceBeatPosition("intelligence")}
10796
+ >
10797
+ <div class="inspector-intelligence-chain">
10798
+ ${INTELLIGENCE_STORY_CHAIN.map((step, index) => lit.html`
10799
+ <span
10800
+ class="inspector-intelligence-chain-step"
10801
+ style="--step-index:${index}"
10802
+ >
10803
+ <i>${this.renderIcon(step.icon)}</i>
10804
+ <strong>${step.name}</strong>
10805
+ <small>${step.detail}</small>
10806
+ </span>
10807
+ ${index === INTELLIGENCE_STORY_CHAIN.length - 1 ? lit.nothing : lit.html`
10808
+ <span
10809
+ class="inspector-intelligence-chain-arrow"
10810
+ style="--step-index:${index}"
10811
+ >${this.renderIcon("ChevronRight")}</span
10812
+ >
10813
+ `}
10814
+ `)}
10815
+ </div>
10816
+ <span class="inspector-intelligence-chain-proof">
10817
+ ${this.renderIcon("Sparkles")} Next run starts with
10818
+ <code>${INTELLIGENCE_STORY_SKILL_FILE}</code>
10819
+ </span>
10820
+ </div>
10821
+ `;
10822
+ }
10823
+ /** A press pins that beat and stops the loop; the developer is now driving. */
10824
+ pinIntelligenceStoryBeat(index) {
10825
+ this.intelStoryUserPinned = true;
10826
+ this.intelStoryBeat = index;
10827
+ this.stopIntelligenceStory();
10828
+ this.requestUpdate();
10829
+ if (!this.core?.telemetryDisabled) {
10830
+ const beat = INTELLIGENCE_STORY_BEATS[index];
10831
+ if (beat) require_telemetry.trackHomeStoryBeatSelected({
10832
+ beat: beat.id,
10833
+ beat_index: index
10834
+ });
10835
+ }
10836
+ }
10837
+ /**
10838
+ * Advance the story only while it is actually on screen.
10839
+ *
10840
+ * Gated on the panel being open, Home being the visible tab, settings being
10841
+ * closed and the document being visible. Anything less and a debugging tool
10842
+ * would be holding a repeating timer behind a closed panel.
10843
+ */
10844
+ syncIntelligenceStory() {
10845
+ if (!(this.isOpen && !this.settingsOpen && this.selectedMenu === "home" && !this._core?.intelligence && typeof document !== "undefined" && document.visibilityState !== "hidden")) {
10846
+ this.intelStoryUserPinned = false;
10847
+ this.stopIntelligenceStory();
10848
+ return;
10849
+ }
10850
+ if (this.intelStoryUserPinned || this.prefersReducedMotion()) {
10851
+ this.stopIntelligenceStory();
10852
+ return;
10853
+ }
10854
+ if (this.intelStoryTimer !== null) return;
10855
+ const advance = () => {
10856
+ const current = INTELLIGENCE_STORY_BEATS[this.intelStoryBeat];
10857
+ this.intelStoryTimer = setTimeout(() => {
10858
+ this.intelStoryTimer = null;
10859
+ if (!this.isConnected) return;
10860
+ this.intelStoryBeat = (this.intelStoryBeat + 1) % INTELLIGENCE_STORY_BEATS.length;
10861
+ this.requestUpdate();
10862
+ advance();
10863
+ }, current?.duration ?? 3800);
10864
+ };
10865
+ advance();
10866
+ }
10867
+ stopIntelligenceStory() {
10868
+ if (this.intelStoryTimer !== null) {
10869
+ clearTimeout(this.intelStoryTimer);
10870
+ this.intelStoryTimer = null;
10871
+ }
10872
+ }
10873
+ /**
10874
+ * Reduced motion parks the story on the closing beat.
10875
+ *
10876
+ * That beat is the whole argument in one static frame, so a developer who
10877
+ * asked their OS for less motion still gets the point rather than a
10878
+ * fragment of it.
10879
+ */
10880
+ prefersReducedMotion() {
10881
+ if (typeof window === "undefined" || !window.matchMedia) return false;
10882
+ this.intelStoryReducedMotion ??= window.matchMedia("(prefers-reduced-motion: reduce)");
10883
+ if (this.intelStoryReducedMotion.matches) {
10884
+ this.intelStoryBeat = INTELLIGENCE_STORY_BEATS.length - 1;
10885
+ return true;
10886
+ }
10887
+ return false;
9678
10888
  }
9679
10889
  maybeTrackHomeViewed() {
9680
10890
  if (this.selectedMenu !== "home" || this.settingsOpen || !this.isOpen) return;
@@ -10295,6 +11505,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
10295
11505
  this.draggedDuringInteraction = false;
10296
11506
  }
10297
11507
  openInspector(source, options = {}) {
11508
+ if (this.isInspectorDismissed) return;
10298
11509
  if (options.threadId) this.focusThread(options);
10299
11510
  if (this.isPoppedOut) return;
10300
11511
  if (this.isOpen) return;
@@ -10306,10 +11517,8 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
10306
11517
  this.closeLauncherHud();
10307
11518
  const hudMenu = this.hudLandingMenu;
10308
11519
  this.hudLandingMenu = null;
10309
- if (hudMenu) {
10310
- this.selectedMenu = hudMenu;
10311
- this.lastSelectedMenuByGroup[require_inspector_nav.getGroupForMenu(hudMenu)] = hudMenu;
10312
- } else if (activeSignalAtOpen !== null && source === "floating_button") {
11520
+ if (hudMenu) this.handleMenuSelect(hudMenu);
11521
+ else if (activeSignalAtOpen !== null && source === "floating_button") {
10313
11522
  const landing = LAUNCHER_SIGNALS[activeSignalAtOpen].landingTarget;
10314
11523
  this.selectedMenu = landing;
10315
11524
  this.lastSelectedMenuByGroup[require_inspector_nav.getGroupForMenu(landing)] = landing;
@@ -10681,6 +11890,24 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
10681
11890
  });
10682
11891
  return mapped;
10683
11892
  }
11893
+ async loadThreadSnapshot(thread) {
11894
+ const core = this._core;
11895
+ if (!core?.runtimeUrl) throw new Error("Failed to load thread.");
11896
+ const baseUrl = core.runtimeUrl.replace(/\/+$/, "");
11897
+ const encodedThreadId = encodeURIComponent(thread.id);
11898
+ const [messagesResponse, stateResponse] = await Promise.all([fetch(`${baseUrl}/threads/${encodedThreadId}/messages`, { headers: { ...core.headers } }), fetch(`${baseUrl}/threads/${encodedThreadId}/state`, { headers: { ...core.headers } })]);
11899
+ if (!messagesResponse.ok) throw new Error(`Failed to load thread (HTTP ${messagesResponse.status}).`);
11900
+ const messagesBody = await messagesResponse.json();
11901
+ const stateBody = stateResponse.ok ? await stateResponse.json() : { state: {} };
11902
+ return {
11903
+ messages: this.mapThreadMessagesToPlayground(messagesBody.messages ?? []),
11904
+ state: stateBody.state ?? {}
11905
+ };
11906
+ }
11907
+ applyThreadSnapshotToPlayground(thread, snapshot) {
11908
+ this.startPlaygroundSession(false, snapshot.messages, snapshot.state, thread.agentId);
11909
+ this.playgroundSourceThreadId = thread.id;
11910
+ }
10684
11911
  sendPlaygroundMessage(content) {
10685
11912
  if (!content || this.playgroundIsRunning || this.playgroundIsLoadingThread) return;
10686
11913
  const selectedAgentId = this.resolvePlaygroundAgentId(this.selectedContext);
@@ -10704,30 +11931,30 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
10704
11931
  @submit=${this.handlePlaygroundSubmit}
10705
11932
  >
10706
11933
  ${this.playgroundError ? lit.html`<div
10707
- 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"
10708
- role="alert"
10709
- data-playground-error
11934
+ 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"
11935
+ role="alert"
11936
+ data-playground-error
11937
+ >
11938
+ <span class="mt-0.5 shrink-0"
11939
+ >${this.renderIcon("TriangleAlert")}</span
10710
11940
  >
10711
- <span class="mt-0.5 shrink-0"
10712
- >${this.renderIcon("TriangleAlert")}</span
10713
- >
10714
- <div class="min-w-0 flex-1">
10715
- <p class="font-semibold">Agent run failed</p>
10716
- <p class="mt-0.5 break-words leading-relaxed">
10717
- ${this.playgroundError}
10718
- </p>
10719
- </div>
10720
- ${hasRetry ? lit.html`
10721
- <button
10722
- type="button"
10723
- 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"
10724
- ?disabled=${busy}
10725
- @click=${this.handlePlaygroundRetry}
10726
- >
10727
- Retry
10728
- </button>
10729
- ` : lit.nothing}
10730
- </div>` : lit.nothing}
11941
+ <div class="min-w-0 flex-1">
11942
+ <p class="font-semibold">Agent run failed</p>
11943
+ <p class="mt-0.5 break-words leading-relaxed">
11944
+ ${this.playgroundError}
11945
+ </p>
11946
+ </div>
11947
+ ${hasRetry ? lit.html`
11948
+ <button
11949
+ type="button"
11950
+ 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"
11951
+ ?disabled=${busy}
11952
+ @click=${this.handlePlaygroundRetry}
11953
+ >
11954
+ Retry
11955
+ </button>
11956
+ ` : lit.nothing}
11957
+ </div>` : lit.nothing}
10731
11958
  <div
10732
11959
  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]"
10733
11960
  >
@@ -10815,31 +12042,41 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
10815
12042
  class="h-3 w-px shrink-0 bg-gray-200"
10816
12043
  aria-hidden="true"
10817
12044
  ></span>
10818
- <span class="truncate" title=${runtimeLabel}>${runtimeLabel}</span>
12045
+ <span class="truncate" title=${runtimeLabel}
12046
+ >${runtimeLabel}</span
12047
+ >
10819
12048
  </div>
10820
12049
  </div>
10821
12050
  <div
10822
12051
  class="cpk-playground-actions ml-auto flex min-w-0 items-center gap-2"
10823
12052
  >
10824
12053
  ${sourceThreads.length > 0 ? lit.html`
10825
- <label class="sr-only" for="cpk-playground-thread-source"
10826
- >Start from a thread</label
10827
- >
10828
- <select
10829
- id="cpk-playground-thread-source"
10830
- 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"
10831
- .value=${this.playgroundSourceThreadId ?? ""}
10832
- ?disabled=${busy}
10833
- @change=${this.handlePlaygroundThreadSourceChange}
12054
+ <label class="sr-only" for="cpk-playground-thread-source"
12055
+ >Start from a thread</label
12056
+ >
12057
+ <select
12058
+ id="cpk-playground-thread-source"
12059
+ 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"
12060
+ .value=${this.playgroundSourceThreadId ?? ""}
12061
+ ?disabled=${busy}
12062
+ @change=${this.handlePlaygroundThreadSourceChange}
12063
+ >
12064
+ <option
12065
+ value=""
12066
+ ?selected=${!this.playgroundSourceThreadId}
10834
12067
  >
10835
- <option value="">Load a thread...</option>
10836
- ${sourceThreads.map((thread) => lit.html`
10837
- <option value=${thread.id}>
10838
- ${thread.name?.trim() || `Thread ${thread.id.slice(0, 8)}`}
10839
- </option>
10840
- `)}
10841
- </select>
10842
- ` : lit.nothing}
12068
+ Load a thread...
12069
+ </option>
12070
+ ${sourceThreads.map((thread) => lit.html`
12071
+ <option
12072
+ value=${thread.id}
12073
+ ?selected=${this.playgroundSourceThreadId === thread.id}
12074
+ >
12075
+ ${thread.name?.trim() || `Thread ${thread.id.slice(0, 8)}`}
12076
+ </option>
12077
+ `)}
12078
+ </select>
12079
+ ` : lit.nothing}
10843
12080
  <button
10844
12081
  type="button"
10845
12082
  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"
@@ -10852,67 +12089,66 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
10852
12089
  </header>
10853
12090
 
10854
12091
  ${this.playgroundShowEphemeralNotice && runtimeMode !== "intelligence" ? lit.html`
10855
- <div
10856
- role="alert"
10857
- 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"
10858
- data-playground-ephemeral-notice
12092
+ <div
12093
+ role="alert"
12094
+ 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"
12095
+ data-playground-ephemeral-notice
12096
+ >
12097
+ <span class="mt-0.5 text-violet-600 [&>svg]:h-3.5 [&>svg]:w-3.5"
12098
+ >${this.renderIcon("Clock3")}</span
10859
12099
  >
10860
- <span
10861
- class="mt-0.5 text-violet-600 [&>svg]:h-3.5 [&>svg]:w-3.5"
10862
- >${this.renderIcon("Clock3")}</span
10863
- >
10864
- <p class="min-w-0 flex-1 leading-relaxed">
10865
- Scratch threads are ephemeral and will be deleted when your
10866
- local session ends. Need durable history?
10867
- <a
10868
- 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"
10869
- href=${this.getThreadsIntelligenceSignupUrl()}
10870
- target="_blank"
10871
- rel="noopener noreferrer"
10872
- >Set up Intelligence</a
10873
- >.
10874
- </p>
10875
- <button
10876
- type="button"
10877
- 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"
10878
- aria-label="Dismiss ephemeral thread notice"
10879
- @click=${() => {
12100
+ <p class="min-w-0 flex-1 leading-relaxed">
12101
+ Scratch threads are ephemeral and will be deleted when your
12102
+ local session ends. Need durable history?
12103
+ <a
12104
+ 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"
12105
+ href=${this.getThreadsIntelligenceSignupUrl()}
12106
+ target="_blank"
12107
+ rel="noopener noreferrer"
12108
+ >Set up Intelligence</a
12109
+ >.
12110
+ </p>
12111
+ <button
12112
+ type="button"
12113
+ 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"
12114
+ aria-label="Dismiss ephemeral thread notice"
12115
+ @click=${() => {
10880
12116
  this.playgroundShowEphemeralNotice = false;
10881
12117
  this.requestUpdate();
10882
12118
  }}
10883
- >
10884
- ${this.renderIcon("X")}
10885
- </button>
10886
- </div>
10887
- ` : lit.nothing}
12119
+ >
12120
+ ${this.renderIcon("X")}
12121
+ </button>
12122
+ </div>
12123
+ ` : lit.nothing}
10888
12124
 
10889
12125
  <div
10890
12126
  class="min-h-0 flex-1 overflow-y-auto px-3 py-3"
10891
12127
  data-playground-messages
10892
12128
  >
10893
12129
  ${this.playgroundIsLoadingThread ? lit.html`
12130
+ <div
12131
+ class="flex h-full items-center justify-center gap-1.5 text-[10px] text-gray-600"
12132
+ >
12133
+ <span
12134
+ class="text-gray-500 [&>svg]:animate-spin"
12135
+ aria-hidden="true"
12136
+ >${this.renderIcon("LoaderCircle")}</span
12137
+ >
12138
+ Loading thread into a scratch session...
12139
+ </div>
12140
+ ` : visibleMessages.length === 0 ? lit.html`
10894
12141
  <div
10895
- class="flex h-full items-center justify-center gap-1.5 text-[10px] text-gray-600"
12142
+ class="cpk-playground-welcome mx-auto flex h-full w-full flex-col items-center justify-center text-center"
10896
12143
  >
10897
- <span
10898
- class="text-gray-500 [&>svg]:animate-spin"
10899
- aria-hidden="true"
10900
- >${this.renderIcon("LoaderCircle")}</span
10901
- >
10902
- Loading thread into a scratch session...
12144
+ <p class="cpk-playground-welcome-title">
12145
+ How can I help you today?
12146
+ </p>
12147
+ ${this.renderPlaygroundComposer(agentId, busy, hasRetry, true)}
10903
12148
  </div>
10904
- ` : visibleMessages.length === 0 ? lit.html`
10905
- <div
10906
- class="cpk-playground-welcome mx-auto flex h-full w-full flex-col items-center justify-center text-center"
10907
- >
10908
- <p class="cpk-playground-welcome-title">
10909
- How can I help you today?
10910
- </p>
10911
- ${this.renderPlaygroundComposer(agentId, busy, hasRetry, true)}
10912
- </div>
10913
- ` : lit.html`
10914
- <div class="mx-auto flex max-w-3xl flex-col pb-5">
10915
- ${visibleMessages.map((message, index) => {
12149
+ ` : lit.html`
12150
+ <div class="mx-auto flex max-w-3xl flex-col pb-5">
12151
+ ${visibleMessages.map((message, index) => {
10916
12152
  const isUser = message.role === "user";
10917
12153
  const isReasoning = message.role === "reasoning";
10918
12154
  const isActivity = message.role === "activity";
@@ -10924,152 +12160,156 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
10924
12160
  const durationLabel = duration === void 0 || duration < 1e3 ? "a few seconds" : `${Math.round(duration / 1e3)} seconds`;
10925
12161
  const label = isStreaming ? "Thinking…" : `Thought for ${durationLabel}`;
10926
12162
  if (isStreaming) return lit.html`
10927
- <section
10928
- class="cpk-playground-message-enter my-1 text-[11px] text-gray-500"
12163
+ <section
12164
+ class="cpk-playground-message-enter my-1 text-[11px] text-gray-500"
12165
+ data-playground-message-role="reasoning"
12166
+ >
12167
+ <div
12168
+ class="inline-flex items-center gap-1 py-1 font-medium"
12169
+ >
12170
+ <span>${label}</span>
12171
+ ${content ? lit.nothing : lit.html`
12172
+ <span
12173
+ class="cpk-playground-thinking-dot ml-1 h-1.5 w-1.5 rounded-full bg-gray-500"
12174
+ aria-hidden="true"
12175
+ ></span>
12176
+ `}
12177
+ </div>
12178
+ ${content ? lit.html`<div
12179
+ class="pb-2 pt-1 leading-5 text-gray-500"
12180
+ >
12181
+ ${content}
12182
+ </div>` : lit.nothing}
12183
+ </section>
12184
+ `;
12185
+ return content ? lit.html`
12186
+ <details
12187
+ class="cpk-playground-message-enter cpk-playground-reasoning my-1 text-[11px] text-gray-500"
10929
12188
  data-playground-message-role="reasoning"
10930
12189
  >
10931
- <div
10932
- class="inline-flex items-center gap-1 py-1 font-medium"
12190
+ <summary
12191
+ 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"
10933
12192
  >
10934
12193
  <span>${label}</span>
10935
- ${content ? lit.nothing : lit.html`
10936
- <span
10937
- class="cpk-playground-thinking-dot ml-1 h-1.5 w-1.5 rounded-full bg-gray-500"
10938
- aria-hidden="true"
10939
- ></span>
10940
- `}
12194
+ <span
12195
+ class="cpk-playground-reasoning-chevron transition-transform duration-200 [&>svg]:h-3 [&>svg]:w-3"
12196
+ >${this.renderIcon("ChevronRight")}</span
12197
+ >
12198
+ </summary>
12199
+ <div class="pb-2 pt-1 leading-5 text-gray-500">
12200
+ ${content}
10941
12201
  </div>
10942
- ${content ? lit.html`<div
10943
- class="pb-2 pt-1 leading-5 text-gray-500"
10944
- >
10945
- ${content}
10946
- </div>` : lit.nothing}
10947
- </section>
12202
+ </details>
12203
+ ` : lit.html`
12204
+ <div
12205
+ class="cpk-playground-message-enter my-1 py-1 text-[11px] font-medium text-gray-500"
12206
+ data-playground-message-role="reasoning"
12207
+ >
12208
+ ${label}
12209
+ </div>
10948
12210
  `;
10949
- return content ? lit.html`
10950
- <details
10951
- class="cpk-playground-message-enter cpk-playground-reasoning my-1 text-[11px] text-gray-500"
10952
- data-playground-message-role="reasoning"
12211
+ }
12212
+ const isMultiline = content.includes("\n") || content.length > 72;
12213
+ const copyKey = `playground-message-${message.id ?? index}`;
12214
+ const showToolbar = !isUser && !isActivity && Boolean(content) && !(this.playgroundIsRunning && index === lastAssistantIndex);
12215
+ return lit.html`
12216
+ <article
12217
+ 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"}
12218
+ data-playground-message-role=${message.role}
12219
+ >
12220
+ ${isActivity ? lit.html`
12221
+ <span class="text-gray-500"
12222
+ >${this.renderIcon("Activity")}</span
10953
12223
  >
10954
- <summary
10955
- 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"
12224
+ <span class="font-medium text-gray-700"
12225
+ >Activity</span
12226
+ >
12227
+ <span class="truncate">${content}</span>
12228
+ ` : isUser ? lit.html`
12229
+ <div
12230
+ 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"}`}
10956
12231
  >
10957
- <span>${label}</span>
10958
- <span
10959
- class="cpk-playground-reasoning-chevron transition-transform duration-200 [&>svg]:h-3 [&>svg]:w-3"
10960
- >${this.renderIcon("ChevronRight")}</span
10961
- >
10962
- </summary>
10963
- <div class="pb-2 pt-1 leading-5 text-gray-500">
10964
12232
  ${content}
10965
12233
  </div>
10966
- </details>
10967
- ` : lit.html`
12234
+ ` : lit.html`
12235
+ <div
12236
+ class="whitespace-pre-wrap break-words py-3 text-[13px] leading-[22px] text-gray-800"
12237
+ >
12238
+ ${content}
12239
+ </div>
12240
+ `}
12241
+ ${!isUser && message.toolCalls.length > 0 ? this.renderToolCallDetails(message.toolCalls) : lit.nothing}
12242
+ ${showToolbar ? lit.html`
10968
12243
  <div
10969
- class="cpk-playground-message-enter my-1 py-1 text-[11px] font-medium text-gray-500"
10970
- data-playground-message-role="reasoning"
12244
+ class="-ml-1 flex min-h-7 w-full items-center gap-1 bg-transparent"
12245
+ data-playground-assistant-toolbar
10971
12246
  >
10972
- ${label}
12247
+ <button
12248
+ type="button"
12249
+ 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"
12250
+ title="Copy message"
12251
+ aria-label="Copy message"
12252
+ @click=${(event) => this.copyToClipboard(content, copyKey, event)}
12253
+ >
12254
+ ${this.copiedEvents.has(copyKey) ? this.renderIcon("Check") : this.renderIcon("Copy")}
12255
+ </button>
12256
+ ${index === lastAssistantIndex && hasRetry && !busy && !this.playgroundError ? lit.html`
12257
+ <button
12258
+ type="button"
12259
+ 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"
12260
+ title="Retry last prompt"
12261
+ aria-label="Retry last prompt"
12262
+ @click=${this.handlePlaygroundRetry}
12263
+ >
12264
+ ${this.renderIcon("RotateCcw")}
12265
+ </button>
12266
+ ` : lit.nothing}
10973
12267
  </div>
10974
- `;
10975
- }
10976
- const isMultiline = content.includes("\n") || content.length > 72;
10977
- const copyKey = `playground-message-${message.id ?? index}`;
10978
- const showToolbar = !isUser && !isActivity && Boolean(content) && !(this.playgroundIsRunning && index === lastAssistantIndex);
10979
- return lit.html`
10980
- <article
10981
- 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"}
10982
- data-playground-message-role=${message.role}
10983
- >
10984
- ${isActivity ? lit.html`
10985
- <span class="text-gray-500"
10986
- >${this.renderIcon("Activity")}</span
10987
- >
10988
- <span class="font-medium text-gray-700"
10989
- >Activity</span
10990
- >
10991
- <span class="truncate">${content}</span>
10992
- ` : isUser ? lit.html`
10993
- <div
10994
- 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"}`}
10995
- >${content}</div>
10996
- ` : lit.html`
10997
- <div
10998
- class="whitespace-pre-wrap break-words py-3 text-[13px] leading-[22px] text-gray-800"
10999
- >${content}</div>
11000
- `}
11001
- ${!isUser && message.toolCalls.length > 0 ? this.renderToolCallDetails(message.toolCalls) : lit.nothing}
11002
- ${showToolbar ? lit.html`
11003
- <div
11004
- class="-ml-1 flex min-h-7 w-full items-center gap-1 bg-transparent"
11005
- data-playground-assistant-toolbar
11006
- >
11007
- <button
11008
- type="button"
11009
- 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"
11010
- title="Copy message"
11011
- aria-label="Copy message"
11012
- @click=${(event) => this.copyToClipboard(content, copyKey, event)}
11013
- >
11014
- ${this.copiedEvents.has(copyKey) ? this.renderIcon("Check") : this.renderIcon("Copy")}
11015
- </button>
11016
- ${index === lastAssistantIndex && hasRetry && !busy && !this.playgroundError ? lit.html`
11017
- <button
11018
- type="button"
11019
- 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"
11020
- title="Retry last prompt"
11021
- aria-label="Retry last prompt"
11022
- @click=${this.handlePlaygroundRetry}
11023
- >
11024
- ${this.renderIcon("RotateCcw")}
11025
- </button>
11026
- ` : lit.nothing}
11027
- </div>
11028
- ` : lit.nothing}
11029
- </article>
11030
- `;
12268
+ ` : lit.nothing}
12269
+ </article>
12270
+ `;
11031
12271
  })}
11032
- ${this.playgroundIsRunning && lastReasoningIndex < 0 ? lit.html`
11033
- <div
11034
- class="cpk-playground-message-enter mt-3 flex items-center gap-1 px-1 py-1"
11035
- aria-label="Agent is working"
11036
- >
11037
- <span
11038
- class="cpk-playground-thinking-dot h-1.5 w-1.5 rounded-full bg-gray-500"
11039
- ></span>
11040
- <span
11041
- class="cpk-playground-thinking-dot h-1.5 w-1.5 rounded-full bg-gray-500"
11042
- ></span>
11043
- <span
11044
- class="cpk-playground-thinking-dot h-1.5 w-1.5 rounded-full bg-gray-500"
11045
- ></span>
11046
- </div>
11047
- ` : lit.nothing}
11048
- ${!busy && lastAssistantIndex >= 0 && suggestions.length > 0 ? lit.html`
11049
- <div
11050
- class="mt-3 flex flex-wrap items-center gap-1.5"
11051
- data-playground-suggestions
11052
- >
11053
- ${suggestions.map((suggestion) => lit.html`
11054
- <button
11055
- type="button"
11056
- 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"
11057
- ?disabled=${suggestion.isLoading}
11058
- aria-busy=${suggestion.isLoading ? "true" : "false"}
11059
- @click=${() => this.handlePlaygroundSuggestion(suggestion.message)}
11060
- >
11061
- ${suggestion.isLoading ? lit.html`<span
11062
- class="[&>svg]:animate-spin"
11063
- aria-hidden="true"
11064
- >${this.renderIcon("LoaderCircle")}</span
11065
- >` : lit.nothing}
11066
- <span>${suggestion.title}</span>
11067
- </button>
11068
- `)}
11069
- </div>
11070
- ` : lit.nothing}
11071
- </div>
11072
- `}
12272
+ ${this.playgroundIsRunning && lastReasoningIndex < 0 ? lit.html`
12273
+ <div
12274
+ class="cpk-playground-message-enter mt-3 flex items-center gap-1 px-1 py-1"
12275
+ aria-label="Agent is working"
12276
+ >
12277
+ <span
12278
+ class="cpk-playground-thinking-dot h-1.5 w-1.5 rounded-full bg-gray-500"
12279
+ ></span>
12280
+ <span
12281
+ class="cpk-playground-thinking-dot h-1.5 w-1.5 rounded-full bg-gray-500"
12282
+ ></span>
12283
+ <span
12284
+ class="cpk-playground-thinking-dot h-1.5 w-1.5 rounded-full bg-gray-500"
12285
+ ></span>
12286
+ </div>
12287
+ ` : lit.nothing}
12288
+ ${!busy && lastAssistantIndex >= 0 && suggestions.length > 0 ? lit.html`
12289
+ <div
12290
+ class="mt-3 flex flex-wrap items-center gap-1.5"
12291
+ data-playground-suggestions
12292
+ >
12293
+ ${suggestions.map((suggestion) => lit.html`
12294
+ <button
12295
+ type="button"
12296
+ 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"
12297
+ ?disabled=${suggestion.isLoading}
12298
+ aria-busy=${suggestion.isLoading ? "true" : "false"}
12299
+ @click=${() => this.handlePlaygroundSuggestion(suggestion.message)}
12300
+ >
12301
+ ${suggestion.isLoading ? lit.html`<span
12302
+ class="[&>svg]:animate-spin"
12303
+ aria-hidden="true"
12304
+ >${this.renderIcon("LoaderCircle")}</span
12305
+ >` : lit.nothing}
12306
+ <span>${suggestion.title}</span>
12307
+ </button>
12308
+ `)}
12309
+ </div>
12310
+ ` : lit.nothing}
12311
+ </div>
12312
+ `}
11073
12313
  </div>
11074
12314
 
11075
12315
  ${showWelcome ? lit.nothing : this.renderPlaygroundComposer(agentId, busy, hasRetry)}
@@ -11152,6 +12392,40 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
11152
12392
  </a>
11153
12393
  </div>
11154
12394
  </section>
12395
+
12396
+ <section
12397
+ class="inspector-settings-section"
12398
+ aria-labelledby="inspector-settings-visibility-title"
12399
+ >
12400
+ <div class="inspector-settings-section-heading">
12401
+ <span class="inspector-settings-section-icon" aria-hidden="true">
12402
+ ${this.renderIcon("EyeOff")}
12403
+ </span>
12404
+ <div>
12405
+ <h2 id="inspector-settings-visibility-title">Visibility</h2>
12406
+ <p>Temporarily hide the Inspector on this domain.</p>
12407
+ </div>
12408
+ </div>
12409
+
12410
+ <div class="inspector-settings-visibility">
12411
+ <div>
12412
+ <h3>Take a break from the Inspector</h3>
12413
+ <p>
12414
+ Hide the Inspector for seven days. It will return automatically
12415
+ when the week is over.
12416
+ </p>
12417
+ </div>
12418
+ <button
12419
+ type="button"
12420
+ class="inspector-settings-dismiss"
12421
+ data-cpk-dismiss-inspector="week"
12422
+ @click=${() => this.dismissInspectorFor("week")}
12423
+ >
12424
+ <span aria-hidden="true">${this.renderIcon("Clock")}</span>
12425
+ Hide Inspector for one week
12426
+ </button>
12427
+ </div>
12428
+ </section>
11155
12429
  </div>
11156
12430
  `;
11157
12431
  }
@@ -11456,6 +12730,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
11456
12730
  this.requestUpdate();
11457
12731
  return;
11458
12732
  }
12733
+ this.tryFromHereError = null;
11459
12734
  this.selectedThreadId = threadId;
11460
12735
  if (showingExamples && this.isExampleThreadId(threadId)) {
11461
12736
  this.selectedRealThreadIsExplicit = false;
@@ -11692,19 +12967,6 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
11692
12967
  ` : lit.nothing}
11693
12968
  `;
11694
12969
  }
11695
- /** Show a copy result briefly and announce it to assistive technology. */
11696
- showThreadsSetupPromptCopyState(state, generation) {
11697
- if (!this.isConnected || generation !== this.threadsSetupPromptCopyGeneration) return;
11698
- if (this.threadsSetupPromptCopyResetTimeoutId !== null) window.clearTimeout(this.threadsSetupPromptCopyResetTimeoutId);
11699
- this.threadsSetupPromptCopyState = state;
11700
- this.requestUpdate();
11701
- this.threadsSetupPromptCopyResetTimeoutId = window.setTimeout(() => {
11702
- if (!this.isConnected || generation !== this.threadsSetupPromptCopyGeneration) return;
11703
- this.threadsSetupPromptCopyState = "idle";
11704
- this.threadsSetupPromptCopyResetTimeoutId = null;
11705
- this.requestUpdate();
11706
- }, 2e3);
11707
- }
11708
12970
  renderThreadsExampleOverview(locked) {
11709
12971
  const lockedCopy = locked ? this.getThreadsLockedCopy() : void 0;
11710
12972
  const { lockedAction } = this.inspectorMetadataProjection;
@@ -11719,34 +12981,10 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
11719
12981
  <p class="cpk-threads-overview-copy">
11720
12982
  ${lockedCopy?.description ?? "Take a tour with the example threads in the sidebar. Then, start chatting in your app to create the first real thread."}
11721
12983
  </p>
12984
+ ${locked ? this.renderRuntimeEntitlementDiagnostic(this.getRuntimeEntitlementDiagnostic()) : lit.nothing}
11722
12985
  <div class="cpk-threads-overview-actions">
11723
12986
  ${locked ? lit.html`
11724
- ${this.inspectorMetadataProjection.licenseState === "valid" ? lit.html`
11725
- <button
11726
- data-inspector-threads-setup-prompt
11727
- type="button"
11728
- aria-label=${this.threadsSetupPromptCopyState === "copied" ? "Setup prompt copied" : this.threadsSetupPromptCopyState === "error" ? "Copy setup prompt failed. Try again" : "Copy setup prompt for your coding agent"}
11729
- @click=${this.handleThreadsSetupPromptCopy}
11730
- >
11731
- ${this.renderIcon(this.threadsSetupPromptCopyState === "copied" ? "Check" : "Copy")}
11732
- ${this.threadsSetupPromptCopyState === "copied" ? "Copied" : this.threadsSetupPromptCopyState === "error" ? "Copy blocked" : "Copy prompt for your agent"}
11733
- </button>
11734
- <a
11735
- data-inspector-threads-setup-link
11736
- href=${this.getThreadsRuntimeSetupDocsUrl()}
11737
- target="_blank"
11738
- rel="noopener"
11739
- aria-label="Open setup guide (opens in a new tab)"
11740
- >
11741
- Open setup guide
11742
- </a>
11743
- <span
11744
- class="sr-only"
11745
- data-inspector-threads-setup-copy-status
11746
- aria-live="polite"
11747
- >${this.threadsSetupPromptCopyState === "copied" ? "Setup prompt copied." : this.threadsSetupPromptCopyState === "error" ? "Setup prompt copy failed. Open the setup guide and copy it manually." : ""}</span
11748
- >
11749
- ` : lit.nothing}
12987
+ ${this.renderFeatureSetupPrompt("threads", "cpk-threads-overview-action cpk-threads-overview-action-primary")}
11750
12988
  ${lockedAction ? this.renderInspectorAction(lockedAction, "locked") : lit.nothing}
11751
12989
  ` : lit.html`
11752
12990
  <a
@@ -11897,6 +13135,74 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
11897
13135
  }
11898
13136
  }
11899
13137
  /**
13138
+ * Prefer the Runtime's structured entitlement diagnostic and derive a
13139
+ * compatibility diagnostic only when an older Core exposes legacy status.
13140
+ */
13141
+ getRuntimeEntitlementDiagnostic() {
13142
+ const runtimeEntitlements = this.core?.runtimeEntitlements;
13143
+ if (runtimeEntitlements) return runtimeEntitlements.status === "ready" ? { status: runtimeEntitlements.status } : {
13144
+ status: runtimeEntitlements.status,
13145
+ error: runtimeEntitlements.error
13146
+ };
13147
+ switch (this.core?.licenseStatus) {
13148
+ case "valid": return { status: "ready" };
13149
+ case "expired": return {
13150
+ status: "degraded",
13151
+ error: {
13152
+ code: "legacy_license_expired",
13153
+ message: "Legacy Runtime license has expired.",
13154
+ retryable: false
13155
+ }
13156
+ };
13157
+ case "expiring": return {
13158
+ status: "degraded",
13159
+ error: {
13160
+ code: "legacy_license_expiring",
13161
+ message: "Legacy Runtime license is expiring.",
13162
+ retryable: false
13163
+ }
13164
+ };
13165
+ case "invalid": return {
13166
+ status: "misconfigured",
13167
+ error: {
13168
+ code: "legacy_license_invalid",
13169
+ message: "Legacy Runtime license is invalid.",
13170
+ retryable: false
13171
+ }
13172
+ };
13173
+ case "none":
13174
+ case "unknown": return { status: "unavailable" };
13175
+ default: return null;
13176
+ }
13177
+ }
13178
+ /** Render exact Runtime entitlement correlation details without gating UI. */
13179
+ renderRuntimeEntitlementDiagnostic(diagnostic) {
13180
+ if (!diagnostic) return lit.nothing;
13181
+ return lit.html`
13182
+ <div
13183
+ role="status"
13184
+ data-runtime-entitlement-status=${diagnostic.status}
13185
+ style="
13186
+ margin: -8px auto 18px;
13187
+ max-width: 380px;
13188
+ font-size: 11px;
13189
+ line-height: 1.5;
13190
+ color: #57575b;
13191
+ "
13192
+ >
13193
+ <div style="font-weight: 600;">
13194
+ Runtime entitlement: ${diagnostic.status}
13195
+ </div>
13196
+ ${diagnostic.error ? lit.html`
13197
+ <div>${diagnostic.error.message}</div>
13198
+ <div>Code: ${diagnostic.error.code}</div>
13199
+ ${diagnostic.error.requestId ? lit.html`<div>Request ID: ${diagnostic.error.requestId}</div>` : lit.nothing}
13200
+ ${diagnostic.error.traceId ? lit.html`<div>Trace ID: ${diagnostic.error.traceId}</div>` : lit.nothing}
13201
+ ` : lit.nothing}
13202
+ </div>
13203
+ `;
13204
+ }
13205
+ /**
11900
13206
  * Renders the realtime-connection indicator in the memory-store header.
11901
13207
  * Only `"connected"` shows the live (green-dot) state; `"connecting"` shows a
11902
13208
  * muted amber "reconnecting" and `"unavailable"` a muted grey "offline", so
@@ -11931,7 +13237,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
11931
13237
  `;
11932
13238
  }
11933
13239
  renderMemoriesView() {
11934
- if (!this.core?.intelligence || !this._memoriesAvailable) return lit.html`
13240
+ if (!this.getHomeModel().services.some((service) => service.id === "memory" && service.enabled)) return lit.html`
11935
13241
  <div class="cpk-memory-locked">
11936
13242
  ${this.renderThreadsLockedBackgroundMockup()}
11937
13243
  <div aria-hidden="true" class="cpk-memory-locked-scrim"></div>
@@ -11946,6 +13252,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
11946
13252
  ${this._memoryStoreUnsupported ? "Learning is unavailable in this version of the @copilotkit SDK. Upgrade @copilotkit/core (and @copilotkit/react) to a version that supports long-term memory." : "Learning turns durable information from agent interactions into reusable context. It isn't enabled on this deployment."}
11947
13253
  </p>
11948
13254
  <div class="cpk-memory-locked-actions">
13255
+ ${this.renderFeatureSetupPrompt("memory", "cpk-memory-locked-action")}
11949
13256
  <a
11950
13257
  href=${this.getTalkToEngineerUrl()}
11951
13258
  target="_blank"
@@ -12281,6 +13588,12 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
12281
13588
  .agentStateInput=${this.getLatestStateForAgent(selectedThread.agentId)}
12282
13589
  .agentEventsInput=${this.agentEvents.get(selectedThread.agentId) ?? []}
12283
13590
  .agentMessagesInput=${selectedThreadIsLocalExample ? EMPTY_INSPECTOR_MESSAGES : this.getLiveAgentMessagesForThread(selectedThread)}
13591
+ .tryFromHereAvailable=${!selectedThreadIsLocalExample && this.areThreadEndpointsAvailable() && this._core?.threadEndpoints?.inspect !== false}
13592
+ .tryFromHereBusy=${this.tryFromHereBusy}
13593
+ .tryFromHereError=${this.tryFromHereError}
13594
+ @tryFromHere=${(event) => {
13595
+ this.handleTryFromHere(event.detail);
13596
+ }}
12284
13597
  ></cpk-thread-details>
12285
13598
  ${selectedThreadIsLocalExample ? this.renderThreadsExampleTour() : lit.nothing}` : showingExamples ? this.renderThreadsExampleOverview(locked) : lit.html`
12286
13599
  <div
@@ -12782,9 +14095,10 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
12782
14095
  </span>
12783
14096
  </div>
12784
14097
  <div class="flex-1 px-4 py-2">
12785
- ${hasContent ? lit.html`<div
12786
- class="whitespace-pre-wrap break-words text-gray-700"
12787
- >${rawContent}</div>` : lit.html`<div class="italic text-gray-400">
14098
+ ${hasContent ? lit.html`
14099
+ <!-- prettier-ignore -->
14100
+ <div class="whitespace-pre-wrap break-words text-gray-700">${rawContent}</div>
14101
+ ` : lit.html`<div class="italic text-gray-400">
12788
14102
  ${contentFallback}
12789
14103
  </div>`}
12790
14104
  ${role === "assistant" && toolCalls.length > 0 ? this.renderToolCallDetails(toolCalls) : lit.nothing}
@@ -13735,12 +15049,12 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
13735
15049
  /**
13736
15050
  * Requests one beat for a signal, running it now or deferring it.
13737
15051
  *
13738
- * There is a single pending slot and four reasons a beat cannot land. All
13739
- * four are the same situation — "cannot land now, run later" — and treating
15052
+ * There is a single pending slot and five reasons a beat cannot land. All
15053
+ * five are the same situation — "cannot land now, run later" — and treating
13740
15054
  * them alike is the point: three separate behaviours for one situation would
13741
15055
  * not survive a third signal.
13742
15056
  *
13743
- * Reason 3 is not cosmetic. Starting a beat while one runs does not restart
15057
+ * Reason 4 is not cosmetic. Starting a beat while one runs does not restart
13744
15058
  * the animation, because the attribute it binds to does not change value and
13745
15059
  * the pseudo-element selectors match on attribute *presence*; the running
13746
15060
  * beat would merely change colour mid-flight. A failure that arms during an
@@ -13749,11 +15063,11 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
13749
15063
  *
13750
15064
  * A failure's beat is followed by a pill, and the whole 3.4-second gesture
13751
15065
  * holds this one slot for its full duration. That is not a second scheduling
13752
- * concept: reason 3 already says "another beat is running", and a gesture is
15066
+ * concept: reason 4 already says "another beat is running", and a gesture is
13753
15067
  * simply a longer beat.
13754
15068
  */
13755
15069
  startSignalPulse(key) {
13756
- if (this.isOpen || typeof document !== "undefined" && document.visibilityState !== "visible" || this.gestureSlotSignal !== null && this.gestureSlotSignal !== key || this.getActiveLauncherSignal() !== key) {
15070
+ if (this.isOpen || this.isInspectorDismissed || typeof document !== "undefined" && document.visibilityState !== "visible" || this.gestureSlotSignal !== null && this.gestureSlotSignal !== key || this.getActiveLauncherSignal() !== key) {
13757
15071
  const pending = this.pendingPulseSignal;
13758
15072
  if (pending === null || LAUNCHER_SIGNALS[key].priority >= LAUNCHER_SIGNALS[pending].priority) this.pendingPulseSignal = key;
13759
15073
  this.requestUpdate();
@@ -13818,7 +15132,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
13818
15132
  }
13819
15133
  /**
13820
15134
  * The signal holding the single gesture slot: a beat in flight, or the pill
13821
- * and spoken sentence that follow it. One slot, not two — see reason 3 in
15135
+ * and spoken sentence that follow it. One slot, not two — see reason 4 in
13822
15136
  * `startSignalPulse`.
13823
15137
  */
13824
15138
  get gestureSlotSignal() {