@copilotkit/web-inspector 1.73.3 → 1.75.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/index.cjs +250 -233
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +24 -6
  4. package/dist/index.d.cts.map +1 -1
  5. package/dist/index.d.mts +24 -6
  6. package/dist/index.d.mts.map +1 -1
  7. package/dist/index.mjs +251 -234
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/index.umd.js +1165 -591
  10. package/dist/index.umd.js.map +1 -1
  11. package/dist/lib/notification-loader.cjs +38 -0
  12. package/dist/lib/notification-loader.cjs.map +1 -0
  13. package/dist/lib/notification-loader.mjs +38 -0
  14. package/dist/lib/notification-loader.mjs.map +1 -0
  15. package/dist/lib/notifications.cjs +173 -0
  16. package/dist/lib/notifications.cjs.map +1 -0
  17. package/dist/lib/notifications.d.cts +17 -0
  18. package/dist/lib/notifications.d.cts.map +1 -0
  19. package/dist/lib/notifications.d.mts +17 -0
  20. package/dist/lib/notifications.d.mts.map +1 -0
  21. package/dist/lib/notifications.mjs +168 -0
  22. package/dist/lib/notifications.mjs.map +1 -0
  23. package/dist/lib/persistence.cjs +124 -48
  24. package/dist/lib/persistence.cjs.map +1 -1
  25. package/dist/lib/persistence.mjs +121 -45
  26. package/dist/lib/persistence.mjs.map +1 -1
  27. package/dist/lib/telemetry.cjs +42 -0
  28. package/dist/lib/telemetry.cjs.map +1 -1
  29. package/dist/lib/telemetry.d.cts.map +1 -1
  30. package/dist/lib/telemetry.d.mts.map +1 -1
  31. package/dist/lib/telemetry.mjs +35 -1
  32. package/dist/lib/telemetry.mjs.map +1 -1
  33. package/dist/package.cjs +1 -1
  34. package/dist/package.mjs +1 -1
  35. package/dist/styles/generated.cjs +1 -1
  36. package/dist/styles/generated.cjs.map +1 -1
  37. package/dist/styles/generated.mjs +1 -1
  38. package/dist/styles/generated.mjs.map +1 -1
  39. package/dist/styles/notification-article.cjs +244 -0
  40. package/dist/styles/notification-article.cjs.map +1 -0
  41. package/dist/styles/notification-article.mjs +244 -0
  42. package/dist/styles/notification-article.mjs.map +1 -0
  43. package/package.json +4 -3
package/dist/index.cjs CHANGED
@@ -1,10 +1,13 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_notifications = require('./lib/notifications.cjs');
3
+ const require_notification_loader = require('./lib/notification-loader.cjs');
4
+ const require_persistence = require('./lib/persistence.cjs');
2
5
  const require_generated = require('./styles/generated.cjs');
6
+ const require_notification_article = require('./styles/notification-article.cjs');
3
7
  const require_inspector_logo = require('./assets/inspector-logo.cjs');
4
8
  const require_inspector_logo_kite = require('./assets/inspector-logo-kite.cjs');
5
9
  const require_learning_view = require('./components/learning-view.cjs');
6
10
  const require_context_helpers = require('./lib/context-helpers.cjs');
7
- const require_persistence = require('./lib/persistence.cjs');
8
11
  const require_learning_setup = require('./lib/learning-setup.cjs');
9
12
  const require_inspector_learning = require('./lib/inspector-learning.cjs');
10
13
  const require_pop_out = require('./lib/pop-out.cjs');
@@ -265,7 +268,6 @@ const MIN_WINDOW_WIDTH = 880;
265
268
  const MIN_WINDOW_WIDTH_DOCKED_LEFT = 640;
266
269
  const MIN_WINDOW_HEIGHT = 480;
267
270
  const INSPECTOR_STORAGE_KEY = "cpk:inspector:state";
268
- const ANNOUNCEMENT_URL = "https://cdn.copilotkit.ai/announcements.json";
269
271
  const LAUNCHER_MIN_SIZE = 51.84;
270
272
  const LAUNCHER_MAX_SIZE = 62.208;
271
273
  const DEFAULT_BUTTON_SIZE = {
@@ -5132,11 +5134,13 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
5132
5134
  150
5133
5135
  ];
5134
5136
  this._evtColResize = null;
5137
+ this.notificationContext = { development: false };
5138
+ this.notificationFeed = null;
5139
+ this.notificationState = require_notifications.emptyNotificationState();
5140
+ this.notificationDocuments = /* @__PURE__ */ new Map();
5141
+ this.selectedNotificationId = null;
5135
5142
  this.announcementHtml = null;
5136
- this.announcementMarkdown = null;
5137
- this.announcementTimestamp = null;
5138
- this.announcementPreviewText = null;
5139
- this.announcementCtaLabel = null;
5143
+ this.announcementId = null;
5140
5144
  this.announcementLoaded = false;
5141
5145
  this.announcementPromise = null;
5142
5146
  this.newsSignalArmed = false;
@@ -5173,6 +5177,10 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
5173
5177
  this.launcherHudIntro = false;
5174
5178
  this.launcherHudIntroStartTimer = null;
5175
5179
  this.launcherHudIntroEndTimer = null;
5180
+ this.viewedHudElement = null;
5181
+ this.launcherHudTrigger = "user";
5182
+ this.viewedHudParts = /* @__PURE__ */ new Set();
5183
+ this.pendingHudTelemetry = [];
5176
5184
  this.inspectorDismissedUntil = null;
5177
5185
  this.lastReportedInspectorVisibility = null;
5178
5186
  this.inspectorDismissalTimer = null;
@@ -5461,9 +5469,18 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
5461
5469
  this.closeLauncherHud();
5462
5470
  this.activeRoot.querySelector(".console-button")?.focus();
5463
5471
  };
5464
- this.handleHudActionClick = (event, row) => {
5472
+ this.handleHudActionClick = (event, row, control) => {
5465
5473
  event.preventDefault();
5466
5474
  event.stopPropagation();
5475
+ const trigger = this.launcherHudTrigger;
5476
+ this.queueHudTelemetry(() => control === "toggle" ? require_telemetry.trackHudFeatureToggleClicked({
5477
+ feature: row,
5478
+ trigger
5479
+ }) : require_telemetry.trackHudFeatureClicked({
5480
+ feature: row,
5481
+ control,
5482
+ trigger
5483
+ }));
5467
5484
  this.hudLandingMenu = row === "threads" ? "threads" : row === "learning" ? "memories" : "home";
5468
5485
  this.closeLauncherHud();
5469
5486
  this.openInspector("floating_button");
@@ -5471,24 +5488,47 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
5471
5488
  this.handleHudRowClick = (event, row) => {
5472
5489
  const target = event.target;
5473
5490
  if (target instanceof Element && target.closest(".cpk-launcher-hud__controls, [data-cpk-hud-action]")) return;
5474
- this.handleHudActionClick(event, row);
5491
+ this.handleHudActionClick(event, row, "row");
5475
5492
  };
5476
5493
  this.handleHudNewsClick = (event) => {
5477
5494
  event.preventDefault();
5478
5495
  event.stopPropagation();
5496
+ const banner_id = this.announcementId;
5497
+ if (banner_id) {
5498
+ const trigger = this.launcherHudTrigger;
5499
+ this.queueHudTelemetry(() => require_telemetry.trackHudNotificationClicked({
5500
+ banner_id,
5501
+ notification_id: banner_id,
5502
+ action: "open",
5503
+ trigger
5504
+ }));
5505
+ }
5479
5506
  this.hudLandingMenu = WHATS_NEW_MENU_KEY;
5507
+ if (this.notificationState.activeId) this.readNotification(this.notificationState.activeId);
5480
5508
  this.closeLauncherHud();
5481
5509
  this.openInspector("floating_button");
5482
5510
  };
5483
5511
  this.handleHudNewsDismissClick = (event) => {
5484
5512
  event.preventDefault();
5485
5513
  event.stopPropagation();
5514
+ const banner_id = this.announcementId;
5515
+ if (banner_id) {
5516
+ const trigger = this.launcherHudTrigger;
5517
+ this.queueHudTelemetry(() => require_telemetry.trackHudNotificationClicked({
5518
+ banner_id,
5519
+ notification_id: banner_id,
5520
+ action: "dismiss",
5521
+ trigger
5522
+ }));
5523
+ }
5486
5524
  this.clearNewsSignal();
5487
5525
  this.activeRoot.querySelector(".console-button")?.focus({ preventScroll: true });
5488
5526
  };
5489
5527
  this.handleHudDismissDayClick = (event) => {
5490
5528
  event.preventDefault();
5491
5529
  event.stopPropagation();
5530
+ const trigger = this.launcherHudTrigger;
5531
+ this.queueHudTelemetry(() => require_telemetry.trackHudHideClicked({ trigger }));
5492
5532
  this.dismissInspectorFor("day");
5493
5533
  };
5494
5534
  this.handleSidebarToggle = () => {
@@ -6139,6 +6179,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
6139
6179
  static {
6140
6180
  this.properties = {
6141
6181
  core: { attribute: false },
6182
+ notificationContext: { attribute: false },
6142
6183
  autoAttachCore: {
6143
6184
  type: Boolean,
6144
6185
  attribute: "auto-attach-core"
@@ -6574,6 +6615,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
6574
6615
  runtimeLicense = void 0;
6575
6616
  }
6576
6617
  this.inspectorMetadataProjection = require_inspector_metadata.projectInspectorMetadata(value, runtimeLicense);
6618
+ this.refreshNotifications();
6577
6619
  }
6578
6620
  attachToCore(core) {
6579
6621
  this.runtimeStatus = core.runtimeConnectionStatus;
@@ -7927,158 +7969,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
7927
7969
  font-weight: 600 !important;
7928
7970
  }
7929
7971
 
7930
- .announcement-content {
7931
- color: #1f2230;
7932
- font-size: 13px;
7933
- font-family: "Plus Jakarta Sans", system-ui, sans-serif;
7934
- line-height: 1.55;
7935
- }
7936
-
7937
- .announcement-content h1,
7938
- .announcement-content h2,
7939
- .announcement-content h3 {
7940
- color: #010507;
7941
- font-weight: 700;
7942
- line-height: 1.3;
7943
- margin: 0.9rem 0 0.4rem;
7944
- }
7945
- .announcement-content > h1:first-child,
7946
- .announcement-content > h2:first-child,
7947
- .announcement-content > h3:first-child {
7948
- margin-top: 0;
7949
- }
7950
-
7951
- .announcement-content h1 {
7952
- font-size: 1.15rem;
7953
- letter-spacing: -0.01em;
7954
- }
7955
- .announcement-content h2 {
7956
- font-size: 1rem;
7957
- }
7958
- .announcement-content h3 {
7959
- font-size: 0.9rem;
7960
- text-transform: none;
7961
- }
7962
-
7963
- .announcement-content p {
7964
- margin: 0.45rem 0;
7965
- }
7966
-
7967
- .announcement-content strong {
7968
- color: #010507;
7969
- font-weight: 700;
7970
- }
7971
-
7972
- .announcement-content ul {
7973
- list-style: disc;
7974
- padding-left: 1.25rem;
7975
- margin: 0.45rem 0;
7976
- }
7977
-
7978
- .announcement-content ol {
7979
- list-style: decimal;
7980
- padding-left: 1.25rem;
7981
- margin: 0.45rem 0;
7982
- }
7983
-
7984
- .announcement-content li + li {
7985
- margin-top: 0.15rem;
7986
- }
7987
-
7988
- .announcement-content a {
7989
- color: #5558b2;
7990
- text-decoration: underline;
7991
- }
7992
-
7993
- .announcement-content :not(pre) > code {
7994
- background: #f3f3f7;
7995
- border: 1px solid #e4e4ec;
7996
- border-radius: 5px;
7997
- padding: 1px 5px;
7998
- font-size: 0.85em;
7999
- color: #4a3a8a;
8000
- }
8001
-
8002
- .announcement-code {
8003
- position: relative;
8004
- margin: 0.6rem 0;
8005
- }
8006
-
8007
- .announcement-code pre {
8008
- background: #0f1117;
8009
- color: #e6e8f2;
8010
- border-radius: 10px;
8011
- padding: 10px 12px;
8012
- overflow-x: auto;
8013
- font-size: 12px;
8014
- line-height: 1.5;
8015
- white-space: pre;
8016
- }
8017
-
8018
- .announcement-code pre code::after {
8019
- content: "";
8020
- display: inline-block;
8021
- width: 80px;
8022
- }
8023
-
8024
- .announcement-code__copy-shield {
8025
- position: absolute;
8026
- top: 4px;
8027
- right: 4px;
8028
- padding: 4px 4px 4px 24px;
8029
- border-top-right-radius: 10px;
8030
- background: linear-gradient(
8031
- to right,
8032
- rgba(15, 17, 23, 0) 0%,
8033
- rgba(15, 17, 23, 0.95) 40%,
8034
- #0f1117 100%
8035
- );
8036
- pointer-events: none;
8037
- }
8038
-
8039
- .announcement-code pre code {
8040
- background: transparent;
8041
- border: none;
8042
- padding: 0;
8043
- color: inherit;
8044
- font-size: inherit;
8045
- }
8046
-
8047
- .announcement-code pre::-webkit-scrollbar {
8048
- height: 6px;
8049
- }
8050
- .announcement-code pre::-webkit-scrollbar-track {
8051
- background: transparent;
8052
- }
8053
- .announcement-code pre::-webkit-scrollbar-thumb {
8054
- background: rgba(255, 255, 255, 0.2);
8055
- border-radius: 4px;
8056
- }
8057
-
8058
- .announcement-code__copy {
8059
- position: relative;
8060
- pointer-events: auto;
8061
- padding: 3px 8px;
8062
- font-family: "Plus Jakarta Sans", system-ui, sans-serif;
8063
- font-size: 11px;
8064
- font-weight: 600;
8065
- color: #e6e8f2;
8066
- background: #1f222d;
8067
- border: 1px solid rgba(255, 255, 255, 0.15);
8068
- border-radius: 6px;
8069
- cursor: pointer;
8070
- transition:
8071
- background 0.12s ease,
8072
- color 0.12s ease;
8073
- }
8074
- .announcement-code__copy:hover {
8075
- background: #2a2e3c;
8076
- }
8077
- .announcement-code__copy[data-copied="true"] {
8078
- background: #eee6fe;
8079
- color: #6430ab;
8080
- border-color: transparent;
8081
- }
7972
+ ${require_notification_article.notificationArticleStyles}
8082
7973
 
8083
7974
  /* ── What's new ──────────────────────────────────────────────── */
8084
7975
  .whats-new {
@@ -9606,6 +9497,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
9606
9497
  }
9607
9498
  connectedCallback() {
9608
9499
  super.connectedCallback();
9500
+ this.notificationState = require_persistence.loadNotificationState();
9609
9501
  if (typeof window !== "undefined") {
9610
9502
  this.accountCtaMotionPaused = document.visibilityState !== "visible";
9611
9503
  this.threadsExampleOverviewVideoReducedMotion = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? false;
@@ -9720,7 +9612,11 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
9720
9612
  if (this.isOpen && this.dockMode === "docked-left") this.setAttribute("data-docked", "true");
9721
9613
  else this.removeAttribute("data-docked");
9722
9614
  }
9723
- updated() {
9615
+ updated(changed) {
9616
+ if (changed.has("notificationContext") || changed.has("core")) {
9617
+ this.ensureAnnouncementLoading();
9618
+ this.refreshNotifications();
9619
+ }
9724
9620
  const visible = !this.isInspectorDismissed;
9725
9621
  if (visible !== this.lastReportedInspectorVisibility) {
9726
9622
  this.lastReportedInspectorVisibility = visible;
@@ -9730,6 +9626,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
9730
9626
  this.syncThreadsExampleOverviewVideo();
9731
9627
  this.maybeTrackInspectorMetadataViews();
9732
9628
  this.maybeTrackNewsSignalViewed();
9629
+ this.maybeTrackHudViews();
9733
9630
  this.resolvePillDirection();
9734
9631
  this.maybeTrackErrorSignalViewed();
9735
9632
  this.maybeCompleteWhatsNewView();
@@ -9971,6 +9868,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
9971
9868
  this.resolveLauncherHudSide();
9972
9869
  this.launcherHudIntro = true;
9973
9870
  this.launcherHudOpen = true;
9871
+ this.launcherHudTrigger = "intro";
9974
9872
  this.refreshLearningSnapshot({ preserve: true });
9975
9873
  this.requestUpdate();
9976
9874
  this.launcherHudIntroEndTimer = setTimeout(() => {
@@ -10019,6 +9917,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
10019
9917
  }
10020
9918
  if (this.launcherHudOpen) return;
10021
9919
  this.launcherHudOpen = true;
9920
+ this.launcherHudTrigger = "user";
10022
9921
  this.refreshLearningSnapshot({ preserve: true });
10023
9922
  this.requestUpdate();
10024
9923
  }
@@ -10030,11 +9929,61 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
10030
9929
  }
10031
9930
  if (!this.launcherHudOpen) return;
10032
9931
  this.launcherHudOpen = false;
9932
+ this.viewedHudElement = null;
9933
+ this.viewedHudParts.clear();
10033
9934
  this.requestUpdate();
10034
9935
  }
9936
+ queueHudTelemetry(send) {
9937
+ if (this.core?.telemetryDisabled) return;
9938
+ if (this.runtimeStatus === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connected) send();
9939
+ else if (this.pendingHudTelemetry.length < MAX_PENDING_BANNER_VIEWED) this.pendingHudTelemetry.push(send);
9940
+ }
9941
+ flushPendingHudTelemetry() {
9942
+ if (this.core?.telemetryDisabled) {
9943
+ this.pendingHudTelemetry = [];
9944
+ return;
9945
+ }
9946
+ if (this.runtimeStatus !== _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connected) return;
9947
+ const queued = this.pendingHudTelemetry;
9948
+ this.pendingHudTelemetry = [];
9949
+ for (const send of queued) send();
9950
+ }
9951
+ maybeTrackHudViews() {
9952
+ const hud = this.activeRoot.querySelector("[data-cpk-launcher-hud]");
9953
+ if (!hud) {
9954
+ this.viewedHudElement = null;
9955
+ this.viewedHudParts.clear();
9956
+ return;
9957
+ }
9958
+ if (document.visibilityState !== "visible") return;
9959
+ if (hud !== this.viewedHudElement) {
9960
+ this.viewedHudElement = hud;
9961
+ this.viewedHudParts.clear();
9962
+ }
9963
+ const once = (key, send) => {
9964
+ if (this.viewedHudParts.has(key)) return;
9965
+ this.viewedHudParts.add(key);
9966
+ this.queueHudTelemetry(send);
9967
+ };
9968
+ const trigger = this.launcherHudTrigger;
9969
+ once("hud", () => require_telemetry.trackHudViewed({ trigger }));
9970
+ if (hud.querySelector("[data-cpk-hud-news]") && this.announcementId) {
9971
+ const banner_id = this.announcementId;
9972
+ once(`notification:${banner_id}`, () => require_telemetry.trackHudNotificationViewed({
9973
+ banner_id,
9974
+ notification_id: banner_id,
9975
+ trigger
9976
+ }));
9977
+ }
9978
+ for (const feature of ["threads", "learning"]) if (hud.querySelector(`[data-cpk-hud-toggle="${feature}"]`)) once(`toggle:${feature}`, () => require_telemetry.trackHudFeatureToggleViewed({
9979
+ feature,
9980
+ trigger
9981
+ }));
9982
+ if (hud.querySelector("[data-cpk-dismiss-inspector=\"day\"]")) once("hide", () => require_telemetry.trackHudHideViewed({ trigger }));
9983
+ }
10035
9984
  getUnreadAnnouncementTitle() {
10036
9985
  if (!this.newsSignalArmed || !this.announcementLoaded) return null;
10037
- const title = this.announcementPreviewText?.trim() || "New in CopilotKit";
9986
+ const title = this.notificationFeed?.notifications.find((notice) => notice.id === this.notificationState.activeId)?.title.trim() || "New in CopilotKit";
10038
9987
  const titleCharacters = Array.from(title);
10039
9988
  return titleCharacters.length > HUD_ANNOUNCEMENT_TITLE_LIMIT ? `${titleCharacters.slice(0, HUD_ANNOUNCEMENT_TITLE_LIMIT).join("").trimEnd()}...` : title;
10040
9989
  }
@@ -10055,7 +10004,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
10055
10004
  class="cpk-launcher-hud__action"
10056
10005
  data-cpk-hud-action
10057
10006
  aria-label=${`Open ${args.label} in Inspector`}
10058
- @click=${(event) => this.handleHudActionClick(event, args.id)}
10007
+ @click=${(event) => this.handleHudActionClick(event, args.id, "action")}
10059
10008
  @pointerdown=${(event) => event.stopPropagation()}
10060
10009
  >
10061
10010
  <span
@@ -10080,7 +10029,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
10080
10029
  data-cpk-hud-learn-more=${args.id}
10081
10030
  aria-label=${`Learn more about ${args.label}`}
10082
10031
  aria-describedby=${detailId}
10083
- @click=${(event) => this.handleHudActionClick(event, args.id)}
10032
+ @click=${(event) => this.handleHudActionClick(event, args.id, "learn_more")}
10084
10033
  @pointerdown=${(event) => event.stopPropagation()}
10085
10034
  >
10086
10035
  ${this.renderIcon("CircleHelp")}
@@ -10092,7 +10041,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
10092
10041
  data-enabled=${args.connected ? "true" : "false"}
10093
10042
  aria-label=${args.connected ? `${args.label} is enabled` : `Open ${args.label} in Inspector`}
10094
10043
  ?disabled=${args.connected}
10095
- @click=${(event) => this.handleHudActionClick(event, args.id)}
10044
+ @click=${(event) => this.handleHudActionClick(event, args.id, "toggle")}
10096
10045
  @pointerdown=${(event) => event.stopPropagation()}
10097
10046
  >
10098
10047
  <span
@@ -10409,6 +10358,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
10409
10358
  }
10410
10359
  getHomeModel() {
10411
10360
  const lastRuntimeEvent = this.flattenedEvents[0];
10361
+ const activeNotice = this.notificationFeed?.notifications.find((notice) => notice.id === this.notificationState.activeId);
10412
10362
  return require_home_briefing.buildHomeModel({
10413
10363
  intelligenceConnected: Boolean(this._core?.intelligence),
10414
10364
  threadsAvailable: this.areThreadEndpointsAvailable(),
@@ -10427,9 +10377,9 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
10427
10377
  suggestionsOn: this._core?.suggestions === true,
10428
10378
  audioOn: this._core?.audioFileTranscriptionEnabled === true,
10429
10379
  websocketUrl: this._core?.intelligence?.wsUrl,
10430
- announcementPreviewText: this.announcementPreviewText ?? void 0,
10431
- announcementMarkdown: this.announcementMarkdown ?? void 0,
10432
- announcementHtml: this.announcementHtml ?? void 0,
10380
+ announcementPreviewText: activeNotice?.title,
10381
+ announcementMarkdown: activeNotice?.body,
10382
+ announcementHtml: activeNotice ? this.notificationDocuments.get(activeNotice.id) : void 0,
10433
10383
  intelligenceSignupUrl: this.getIntelligenceSignupUrl()
10434
10384
  });
10435
10385
  }
@@ -10465,7 +10415,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
10465
10415
  data-inspector-whats-new-preview
10466
10416
  aria-label="Open What's New"
10467
10417
  style=${INTERACTIVE_FOCUS_BASE_STYLE}
10468
- @click=${() => this.handleMenuSelect(WHATS_NEW_MENU_KEY)}
10418
+ @click=${() => this.notificationState.activeId ? this.readNotification(this.notificationState.activeId) : this.handleMenuSelect(WHATS_NEW_MENU_KEY)}
10469
10419
  >
10470
10420
  <span class="inspector-whats-new-preview-copy">
10471
10421
  <span class="inspector-whats-new-preview-title">
@@ -10482,47 +10432,89 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
10482
10432
  `;
10483
10433
  }
10484
10434
  renderWhatsNewView() {
10485
- const state = this.getWhatsNewState();
10486
- const news = this.getHomeModel().news;
10487
- const updatedAt = this.announcementTimestamp ? new Date(this.announcementTimestamp) : null;
10488
- const updatedLabel = updatedAt && !Number.isNaN(updatedAt.getTime()) ? new Intl.DateTimeFormat(void 0, {
10489
- month: "long",
10435
+ const notices = this.notificationFeed?.notifications.filter((n) => this.notificationState.eligibleIds.includes(n.id)).sort(require_notifications.compareNotifications) ?? [];
10436
+ const selected = notices.find((n) => n.id === this.selectedNotificationId);
10437
+ const formatDate = (date) => new Date(date).toLocaleDateString(void 0, {
10438
+ month: "short",
10490
10439
  day: "numeric",
10491
10440
  year: "numeric"
10492
- }).format(updatedAt) : null;
10441
+ });
10493
10442
  return lit.html`
10494
10443
  <div
10495
10444
  class="inspector-home inspector-whats-new"
10496
10445
  data-inspector-whats-new
10497
10446
  data-cpk-whats-new
10498
- data-cpk-whats-new-state=${state}
10447
+ data-cpk-whats-new-state=${this.getWhatsNewState()}
10499
10448
  >
10500
- <header class="inspector-whats-new-header">
10501
- <h1 class="inspector-home-title">What's New</h1>
10502
- ${updatedLabel ? lit.html`
10503
- <p class="inspector-whats-new-updated">
10504
- Updated
10505
- <time datetime=${updatedAt?.toISOString()}
10506
- >${updatedLabel}</time
10507
- >
10508
- </p>
10509
- ` : lit.nothing}
10510
- </header>
10511
10449
  <section class="inspector-home-news" aria-label="CopilotKit updates">
10512
- ${news.empty || !news.documentHtml ? lit.html`
10513
- <article class="inspector-whats-new-empty">
10514
- <h2 class="inspector-home-card-title">${news.title}</h2>
10515
- <p class="inspector-home-card-copy">${news.previewText}</p>
10516
- </article>
10517
- ` : lit.html`
10450
+ ${selected ? lit.html`
10451
+ <button
10452
+ type="button"
10453
+ class="inspector-whats-new-back"
10454
+ @click=${() => {
10455
+ this.selectedNotificationId = null;
10456
+ this.requestUpdate();
10457
+ }}
10458
+ >
10459
+ <span aria-hidden="true"
10460
+ >${this.renderIcon("ArrowLeft")}</span
10461
+ >
10462
+ All updates
10463
+ </button>
10518
10464
  <article class="inspector-whats-new-document">
10465
+ <header class="inspector-whats-new-document-header">
10466
+ <h1>${selected.title}</h1>
10467
+ <time datetime=${selected.publishedAt}>
10468
+ ${formatDate(selected.publishedAt)}
10469
+ </time>
10470
+ </header>
10519
10471
  <div
10520
10472
  class="announcement-content"
10521
10473
  @click=${this.handleAnnouncementContentClick}
10522
10474
  >
10523
- ${(0, lit_directives_unsafe_html_js.unsafeHTML)(news.documentHtml)}
10475
+ ${(0, lit_directives_unsafe_html_js.unsafeHTML)(this.notificationDocuments.get(selected.id) ?? "")}
10524
10476
  </div>
10525
10477
  </article>
10478
+ ` : lit.html`
10479
+ <header class="inspector-whats-new-header">
10480
+ <h1 class="inspector-home-title">What's New</h1>
10481
+ </header>
10482
+ ${notices.length ? lit.html`
10483
+ <ul class="inspector-whats-new-list">
10484
+ ${notices.map((notice) => {
10485
+ const read = this.notificationState.readIds.includes(notice.id);
10486
+ return lit.html`
10487
+ <li>
10488
+ <button
10489
+ type="button"
10490
+ class="cpk-notification-row"
10491
+ data-notification-id=${notice.id}
10492
+ @click=${() => this.readNotification(notice.id)}
10493
+ >
10494
+ <span class="cpk-notification-copy">
10495
+ <strong>${notice.title}</strong>
10496
+ <span class="cpk-notification-meta">
10497
+ <time datetime=${notice.publishedAt}
10498
+ >${formatDate(notice.publishedAt)}</time
10499
+ >
10500
+ ${read ? lit.nothing : lit.html`
10501
+ <span class="cpk-notification-unread">Unread</span>
10502
+ `}
10503
+ </span>
10504
+ </span>
10505
+ <span
10506
+ class="cpk-notification-chevron"
10507
+ aria-hidden="true"
10508
+ >${this.renderIcon("ChevronRight")}</span
10509
+ >
10510
+ </button>
10511
+ </li>
10512
+ `;
10513
+ })}
10514
+ </ul>
10515
+ ` : lit.html`<p class="inspector-whats-new-empty" role="status">
10516
+ ${this.announcementLoaded || !this.notificationContext.development ? "You're all caught up." : "Loading updates…"}
10517
+ </p>`}
10526
10518
  `}
10527
10519
  </section>
10528
10520
  </div>
@@ -13005,15 +12997,15 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
13005
12997
  }
13006
12998
  trackWhatsNewClickedOnce(opts) {
13007
12999
  if (this.runtimeStatus !== _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connected || this.core?.telemetryDisabled) return;
13008
- const id = this.announcementTimestamp;
13000
+ const id = this.announcementId;
13009
13001
  if (!id) return;
13010
13002
  const key = `${id}:${opts.cta}`;
13011
13003
  if (this.clickedBannerIds.has(key)) return;
13012
13004
  this.clickedBannerIds.add(key);
13013
13005
  require_telemetry.trackWhatsNewClicked({
13014
13006
  banner_id: id,
13015
- cta: opts.cta,
13016
- cta_label: this.announcementCtaLabel ?? void 0
13007
+ notification_id: id,
13008
+ cta: opts.cta
13017
13009
  });
13018
13010
  }
13019
13011
  trackThreadsViewStateOnce(state) {
@@ -15525,11 +15517,9 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
15525
15517
  else if (!wasArmed) this.requestUpdate();
15526
15518
  }
15527
15519
  clearNewsSignal() {
15528
- if (!this.newsSignalArmed) return;
15529
- this.newsSignalArmed = false;
15530
- if (this.announcementTimestamp) require_persistence.saveAnnouncementReadTimestamp(this.announcementTimestamp);
15531
- this.retireSignal(NEWS_SIGNAL_ID);
15532
- this.requestUpdate();
15520
+ if (!this.notificationState.activeId) return;
15521
+ this.notificationState = require_notifications.acknowledgeNotification(this.notificationState, this.notificationState.activeId);
15522
+ this.refreshNotifications();
15533
15523
  }
15534
15524
  /**
15535
15525
  * Requests one beat for a signal, running it now or deferring it.
@@ -15562,7 +15552,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
15562
15552
  this.pendingPulseSignal = null;
15563
15553
  this.pulsingSignal = key;
15564
15554
  if (isWiringErrorKey(key)) this.errorBeatSpent = true;
15565
- else if (this.announcementTimestamp && key === NEWS_SIGNAL_ID) require_persistence.saveAnnouncementPulsedTimestamp(this.announcementTimestamp);
15555
+ else if (this.notificationState.activeId && key === NEWS_SIGNAL_ID) require_persistence.saveNotificationPulsedId(this.notificationState.activeId);
15566
15556
  this.beginGestureTail(key);
15567
15557
  this.requestUpdate();
15568
15558
  if (typeof window === "undefined") return;
@@ -15862,14 +15852,14 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
15862
15852
  }
15863
15853
  maybeTrackNewsSignalViewed() {
15864
15854
  if (!this.newsSignalArmed || this.pulsingSignal !== NEWS_SIGNAL_ID || this.isOpen || typeof document === "undefined" || document.visibilityState !== "visible") return;
15865
- const id = this.announcementTimestamp;
15855
+ const id = (this.notificationFeed?.notifications.find((n) => n.id === this.notificationState.activeId))?.id;
15866
15856
  if (!id || this.viewedNewsSignalIds.has(id)) return;
15867
15857
  this.viewedNewsSignalIds.add(id);
15868
15858
  this.pendingNewsSignalViewed = {
15869
15859
  banner_id: id,
15860
+ notification_id: id,
15870
15861
  surface: "launcher",
15871
- presentation: typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches ? "reduced_motion" : "animated",
15872
- cta_label: this.announcementCtaLabel ?? void 0
15862
+ presentation: typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches ? "reduced_motion" : "animated"
15873
15863
  };
15874
15864
  this.flushPendingWhatsNewTelemetry();
15875
15865
  }
@@ -15887,7 +15877,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
15887
15877
  getVisibleBannerSurface() {
15888
15878
  if (!this.isOpen || this.settingsOpen) return null;
15889
15879
  if (this.selectedMenu !== WHATS_NEW_MENU_KEY) return null;
15890
- return this.announcementHtml ? "whats_new" : null;
15880
+ return this.selectedNotificationId && this.announcementHtml ? "whats_new" : null;
15891
15881
  }
15892
15882
  /**
15893
15883
  * The single condition that retires the news signal: What's new has
@@ -15906,14 +15896,13 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
15906
15896
  maybeCompleteWhatsNewView() {
15907
15897
  if (!this.getVisibleBannerSurface()) return;
15908
15898
  this.maybeTrackWhatsNewViewed();
15909
- this.clearNewsSignal();
15910
15899
  }
15911
15900
  /**
15912
15901
  * Records a `whats_new_viewed` impression for whichever surface is
15913
15902
  * currently visible, once per announcement per surface.
15914
15903
  */
15915
15904
  maybeTrackWhatsNewViewed() {
15916
- const id = this.announcementTimestamp;
15905
+ const id = this.announcementId;
15917
15906
  if (!id) return;
15918
15907
  const surface = this.getVisibleBannerSurface();
15919
15908
  if (!surface) return;
@@ -15923,12 +15912,13 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
15923
15912
  this.viewedBannerSurfaces.add(key);
15924
15913
  this.pendingBannerViewed.push({
15925
15914
  banner_id: id,
15926
- surface,
15927
- cta_label: this.announcementCtaLabel ?? void 0
15915
+ notification_id: id,
15916
+ surface
15928
15917
  });
15929
15918
  this.flushPendingWhatsNewTelemetry();
15930
15919
  }
15931
15920
  flushPendingWhatsNewTelemetry() {
15921
+ this.flushPendingHudTelemetry();
15932
15922
  if (this.pendingBannerViewed.length === 0 && !this.pendingNewsSignalViewed) return;
15933
15923
  if (this.core?.telemetryDisabled) {
15934
15924
  this.pendingBannerViewed = [];
@@ -15946,32 +15936,58 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
15946
15936
  }
15947
15937
  }
15948
15938
  ensureAnnouncementLoading() {
15949
- if (this.announcementPromise || typeof window === "undefined" || typeof fetch === "undefined") return;
15939
+ if (this.isInspectorDismissed || !this.notificationContext.development || !this.isConnected || this.announcementPromise || typeof window === "undefined" || typeof fetch === "undefined") return;
15950
15940
  this.announcementPromise = this.fetchAnnouncement();
15951
15941
  }
15952
15942
  async fetchAnnouncement() {
15953
15943
  try {
15954
- const response = await fetch(ANNOUNCEMENT_URL, { cache: "no-cache" });
15955
- if (!response.ok) throw new Error(`Failed to load announcement (${response.status})`);
15956
- const data = await response.json();
15957
- const timestamp = typeof data?.timestamp === "string" ? data.timestamp : null;
15958
- const previewText = typeof data?.previewText === "string" ? data.previewText : null;
15959
- const markdown = typeof data?.announcement === "string" ? data.announcement : null;
15960
- const ctaLabel = typeof data?.cta_label === "string" ? data.cta_label : null;
15961
- if (!timestamp || !markdown) throw new Error("Malformed announcement payload");
15962
- this.announcementTimestamp = timestamp;
15963
- this.announcementPreviewText = previewText ?? "";
15964
- this.announcementMarkdown = markdown;
15965
- this.announcementCtaLabel = ctaLabel;
15966
- this.announcementHtml = await this.convertMarkdownToHtml(markdown);
15967
- this.announcementLoaded = true;
15968
- if (this.announcementHtml && require_persistence.loadAnnouncementReadTimestamp() !== timestamp) this.armNewsSignal({ pulse: require_persistence.loadAnnouncementPulsedTimestamp() !== timestamp });
15969
- this.requestUpdate();
15970
- } catch (error) {
15971
- console.warn("[CopilotKit Inspector] Failed to load announcement", error);
15972
- this.announcementLoaded = true;
15973
- this.requestUpdate();
15944
+ const feed = await require_notification_loader.loadNotificationFeed(this.notificationContext);
15945
+ if (feed) {
15946
+ const documents = await Promise.all(feed.notifications.map(async (notice) => [notice.id, await this.convertMarkdownToHtml(notice.body) ?? ""]));
15947
+ this.notificationDocuments = new Map(documents);
15948
+ this.notificationFeed = feed;
15949
+ }
15950
+ } catch {}
15951
+ this.announcementLoaded = true;
15952
+ this.refreshNotifications();
15953
+ this.requestUpdate();
15954
+ }
15955
+ /** Resolve only confirmed runtime metadata; missing fields stay unknown. */
15956
+ getNotificationContext() {
15957
+ const base = this.notificationContext;
15958
+ const core = this.core;
15959
+ if (!core || this.runtimeStatus !== _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connected) return base;
15960
+ const mode = core.runtimeMode;
15961
+ const entitlement = core.runtimeEntitlements?.status === "ready" ? core.runtimeEntitlements.entitlement : void 0;
15962
+ return {
15963
+ ...base,
15964
+ intelligence: mode === "intelligence" ? "enabled" : mode === "sse" ? "disabled" : void 0,
15965
+ plan: this.inspectorMetadataProjection.plan?.code ?? entitlement?.planCode,
15966
+ deployment: entitlement?.source === "managedOrgSubscription" ? "managed" : entitlement ? "self-hosted" : void 0
15967
+ };
15968
+ }
15969
+ refreshNotifications() {
15970
+ if (!this.notificationFeed) return;
15971
+ this.notificationState = require_persistence.migrateAnnouncementReadState(this.notificationState, this.notificationFeed);
15972
+ const previousActiveId = this.notificationState.activeId;
15973
+ this.notificationState = require_notifications.reconcileNotifications(this.notificationState, this.notificationFeed, this.getNotificationContext());
15974
+ require_persistence.saveNotificationState(this.notificationState);
15975
+ if (!this.notificationState.eligibleIds.includes(this.selectedNotificationId ?? "")) this.selectedNotificationId = null;
15976
+ const notice = this.notificationFeed.notifications.find((n) => this.notificationState.eligibleIds.includes(n.id) && n.id === (this.selectedNotificationId ?? this.notificationState.activeId)) ?? this.notificationFeed.notifications.filter((n) => this.notificationState.eligibleIds.includes(n.id)).sort(require_notifications.compareNotifications)[0];
15977
+ this.announcementId = notice?.id ?? null;
15978
+ this.announcementHtml = notice ? this.notificationDocuments.get(notice.id) ?? null : null;
15979
+ if (this.notificationState.activeId && this.notificationState.eligibleIds.includes(this.notificationState.activeId)) this.armNewsSignal({ pulse: (previousActiveId !== this.notificationState.activeId || !this.newsSignalArmed) && !require_persistence.hasNotificationPulsed(this.notificationState.activeId, this.notificationFeed.notifications.find((n) => n.id === this.notificationState.activeId).publishedAt) });
15980
+ else {
15981
+ this.newsSignalArmed = false;
15982
+ this.retireSignal(NEWS_SIGNAL_ID);
15974
15983
  }
15984
+ this.requestUpdate();
15985
+ }
15986
+ readNotification(id) {
15987
+ this.selectedNotificationId = id;
15988
+ this.notificationState = require_notifications.acknowledgeNotification(this.notificationState, id);
15989
+ this.refreshNotifications();
15990
+ this.handleMenuSelect(WHATS_NEW_MENU_KEY);
15975
15991
  }
15976
15992
  async convertMarkdownToHtml(markdown) {
15977
15993
  const renderer = new marked.marked.Renderer();
@@ -16046,8 +16062,9 @@ function defineWebInspector(registry = globalThis.customElements) {
16046
16062
  * auto-attachment first prevents `connectedCallback` from briefly selecting a
16047
16063
  * different global core.
16048
16064
  */
16049
- function configureWebInspectorElement(inspector, core) {
16065
+ function configureWebInspectorElement(inspector, core, notificationContext = { development: false }) {
16050
16066
  inspector.autoAttachCore = false;
16067
+ inspector.notificationContext = notificationContext;
16051
16068
  inspector.core = core;
16052
16069
  return inspector;
16053
16070
  }