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