@copilotkit/web-inspector 1.70.1 → 1.70.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/components/learning-view.cjs +1415 -0
  2. package/dist/components/learning-view.cjs.map +1 -0
  3. package/dist/components/learning-view.mjs +1415 -0
  4. package/dist/components/learning-view.mjs.map +1 -0
  5. package/dist/index.cjs +525 -227
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.cts +33 -8
  8. package/dist/index.d.cts.map +1 -1
  9. package/dist/index.d.mts +33 -8
  10. package/dist/index.d.mts.map +1 -1
  11. package/dist/index.mjs +526 -228
  12. package/dist/index.mjs.map +1 -1
  13. package/dist/index.umd.js +2194 -316
  14. package/dist/index.umd.js.map +1 -1
  15. package/dist/lib/home-briefing.cjs +1 -1
  16. package/dist/lib/home-briefing.cjs.map +1 -1
  17. package/dist/lib/home-briefing.mjs +1 -1
  18. package/dist/lib/home-briefing.mjs.map +1 -1
  19. package/dist/lib/inspector-learning.cjs +37 -0
  20. package/dist/lib/inspector-learning.cjs.map +1 -0
  21. package/dist/lib/inspector-learning.mjs +36 -0
  22. package/dist/lib/inspector-learning.mjs.map +1 -0
  23. package/dist/lib/learning-setup.cjs +83 -0
  24. package/dist/lib/learning-setup.cjs.map +1 -0
  25. package/dist/lib/learning-setup.mjs +78 -0
  26. package/dist/lib/learning-setup.mjs.map +1 -0
  27. package/dist/lib/telemetry.cjs +50 -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 +42 -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/package.json +5 -3
package/dist/index.cjs CHANGED
@@ -2,8 +2,11 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_generated = require('./styles/generated.cjs');
3
3
  const require_inspector_logo = require('./assets/inspector-logo.cjs');
4
4
  const require_inspector_logo_kite = require('./assets/inspector-logo-kite.cjs');
5
+ const require_learning_view = require('./components/learning-view.cjs');
5
6
  const require_context_helpers = require('./lib/context-helpers.cjs');
6
7
  const require_persistence = require('./lib/persistence.cjs');
8
+ const require_learning_setup = require('./lib/learning-setup.cjs');
9
+ const require_inspector_learning = require('./lib/inspector-learning.cjs');
7
10
  const require_pop_out = require('./lib/pop-out.cjs');
8
11
  const require_inspector_metadata = require('./lib/inspector-metadata.cjs');
9
12
  const require_home_briefing = require('./lib/home-briefing.cjs');
@@ -389,6 +392,52 @@ const INTELLIGENCE_STORY_CHAIN = [
389
392
  ];
390
393
  const THREADS_EXAMPLE_OVERVIEW_VIDEO_URL = "https://cdn.copilotkit.ai/corp-site/videos/copilotkit-generative-ui-agentic-frontend-demo.webm";
391
394
  const THREADS_EXAMPLE_OVERVIEW_VIDEO_FALLBACK = "The demo video is unavailable. Use the example threads to explore Messages, AG-UI Events, and State.";
395
+ const THREADS_LOCKED_VIDEO_URL = "https://www.loom.com/embed/79817778d29e490c97225127d2f17b3a?hide_owner=true&hide_share=true&hide_title=true&hideEmbedTopBar=true&hide_speed=true";
396
+ const LEARNING_LOCKED_VIDEO_URL = "https://www.loom.com/embed/2978fbfe42324e509057ac5fd46b7a70?hide_owner=true&hide_share=true&hide_title=true&hideEmbedTopBar=true&hide_speed=true";
397
+ const THREADS_LOCKED_FEATURE_OUTLINE = [
398
+ {
399
+ icon: "MessagesSquare",
400
+ title: "The whole conversation comes back",
401
+ description: "Rich Threads restores the complete interaction, not just a transcript. Messages, tool calls, shared state, generated interfaces, and supported files return together when a user reopens the thread."
402
+ },
403
+ {
404
+ icon: "LayoutGrid",
405
+ title: "Generated UI stays in the thread",
406
+ description: "Cards, charts, A2UI surfaces, MCP Apps, and tool renderers remain part of the conversation. The demo above shows a generated spending chart returning after a reload."
407
+ },
408
+ {
409
+ icon: "RefreshCw",
410
+ title: "Return without starting over",
411
+ description: "Users can move across sessions and devices while thread lists stay synchronized across open tabs. Rich Threads replays missed events and reconnects to work already in progress."
412
+ },
413
+ {
414
+ icon: "Server",
415
+ title: "Infrastructure you do not have to rebuild",
416
+ description: "CopilotKit handles durable event storage, replay, synchronization, lifecycle APIs, and thread locks on one portable AG-UI history model. Use CopilotKit Cloud or deploy Intelligence in your own Kubernetes environment."
417
+ }
418
+ ];
419
+ const LEARNING_LOCKED_FEATURE_OUTLINE = [
420
+ {
421
+ icon: "History",
422
+ title: "Memory across sessions",
423
+ description: "Keep useful facts, preferences, and decisions after the thread closes. Learning gives future conversations the context they need without asking users to repeat themselves."
424
+ },
425
+ {
426
+ icon: "Search",
427
+ title: "Recall by meaning",
428
+ description: "Surface relevant memories by what they mean, not by an exact phrase. Your agent can bring the right context into a new interaction even when the user asks in a completely different way."
429
+ },
430
+ {
431
+ icon: "Layers",
432
+ title: "Built-in structure",
433
+ description: "Turn raw interactions into organized topical, episodic, and operational knowledge. Learning separates enduring facts from individual experiences and useful instructions automatically."
434
+ },
435
+ {
436
+ icon: "Eye",
437
+ title: "Full visibility",
438
+ description: "Inspect exactly what your agent learned and trace each memory back to the threads that shaped it. Review the stored context instead of treating memory like a black box."
439
+ }
440
+ ];
392
441
  const THREADS_EXAMPLE_TOUR_STORAGE_KEY = "cpk:inspector:threads-example-tour:v1";
393
442
  const THREADS_EXAMPLE_AGENT_ID = "threads-feature";
394
443
  /** Keep one row per thread id when flattening per-agent stores. */
@@ -4854,6 +4903,21 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
4854
4903
  this._memoryUnsub = null;
4855
4904
  this._memorySubscribed = false;
4856
4905
  this._memoryStoreUnsupported = false;
4906
+ this.learningSnapshot = null;
4907
+ this.learningSnapshotScope = null;
4908
+ this.learningProjectIdentity = null;
4909
+ this.learningLoading = false;
4910
+ this.learningRefreshing = false;
4911
+ this.learningError = null;
4912
+ this.learningSupported = false;
4913
+ this.learningRequestGeneration = 0;
4914
+ this.learningAbortController = null;
4915
+ this.learningPollTimer = null;
4916
+ this.learningPollFailureCount = 0;
4917
+ this.learningSetupMarker = null;
4918
+ this.learningSetupUnsubscribe = null;
4919
+ this.learningPromptCopyState = "idle";
4920
+ this.learningViewedState = null;
4857
4921
  this._recallResults = null;
4858
4922
  this._recallLoading = false;
4859
4923
  this._recallError = null;
@@ -5090,10 +5154,158 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
5090
5154
  this.resizeEdge = "se";
5091
5155
  this.isResizing = false;
5092
5156
  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>` };
5157
+ this.refreshLearningSnapshot = async (options = {}) => {
5158
+ const core = this.core;
5159
+ const runtimeUrl = core?.runtimeUrl;
5160
+ this.learningSupported = Boolean(core?.inspectorLearning);
5161
+ if (!core || !runtimeUrl || !this.learningSupported) {
5162
+ this.clearLearningSnapshot();
5163
+ this.requestUpdate();
5164
+ this.trackLearningViewState();
5165
+ return;
5166
+ }
5167
+ this.cancelLearningPoll();
5168
+ const startedAt = performance.now();
5169
+ let loadOutcome = "failure";
5170
+ let loadedSkills = 0;
5171
+ let loadedInsights = 0;
5172
+ let loadedPendingThreads = 0;
5173
+ let resetSkillsPage = false;
5174
+ let resetInsightsPage = false;
5175
+ const previousSnapshot = this.learningSnapshot;
5176
+ const agentId = this.getLearningAgentId();
5177
+ const requestContext = `${runtimeUrl.replace(/\/+$/u, "")}|${agentId ?? ""}`;
5178
+ if (this.learningSnapshotScope && !this.learningSnapshotScope.startsWith(`${requestContext}|`)) this.clearLearningSnapshot();
5179
+ const generation = ++this.learningRequestGeneration;
5180
+ this.learningAbortController?.abort();
5181
+ const controller = new AbortController();
5182
+ this.learningAbortController = controller;
5183
+ const preserve = options.preserve === true && this.learningSnapshot !== null;
5184
+ this.learningLoading = !preserve;
5185
+ this.learningRefreshing = preserve;
5186
+ this.learningError = null;
5187
+ this.requestUpdate();
5188
+ try {
5189
+ const snapshot = await require_inspector_learning.fetchInspectorLearning({
5190
+ runtimeUrl,
5191
+ runtimeTransport: core.runtimeTransport,
5192
+ request: {
5193
+ ...agentId ? { agentId } : {},
5194
+ skillsPage: options.skillsPage ?? this.learningSnapshot?.skillsPage.page ?? 1,
5195
+ insightsPage: options.insightsPage ?? this.learningSnapshot?.insightsPage.page ?? 1
5196
+ },
5197
+ fetch: core.ɵruntimeFetch,
5198
+ headers: core.headers,
5199
+ credentials: core.credentials,
5200
+ signal: controller.signal
5201
+ });
5202
+ if (generation !== this.learningRequestGeneration) return;
5203
+ if (snapshot.pendingThreadCount > 0 && !snapshot.links.runs || snapshot.pendingCandidateCount > 0 && !snapshot.links.candidates) throw new Error("Learning snapshot is missing a required web-app link.");
5204
+ const containerId = snapshot.configuration.state === "configured" ? snapshot.configuration.container.id : "";
5205
+ const previousContainerId = previousSnapshot?.configuration.state === "configured" ? previousSnapshot.configuration.container.id : "";
5206
+ const scopeChanged = previousSnapshot !== null && (previousSnapshot.projectKey !== snapshot.projectKey || previousContainerId !== containerId);
5207
+ const isBackgroundRefresh = options.skillsPage === void 0 && options.insightsPage === void 0;
5208
+ resetSkillsPage = Boolean(isBackgroundRefresh && previousSnapshot && previousSnapshot.skillsPage.page > 1 && (scopeChanged || JSON.stringify([previousSnapshot.skillsPage.total, previousSnapshot.skillsPage.items.map((skill) => [skill.id, skill.revision])]) !== JSON.stringify([snapshot.skillsPage.total, snapshot.skillsPage.items.map((skill) => [skill.id, skill.revision])])));
5209
+ resetInsightsPage = Boolean(isBackgroundRefresh && previousSnapshot && previousSnapshot.insightsPage.page > 1 && (scopeChanged || JSON.stringify([previousSnapshot.insightsPage.total, previousSnapshot.insightsPage.items.map((insight) => insight.id)]) !== JSON.stringify([snapshot.insightsPage.total, snapshot.insightsPage.items.map((insight) => insight.id)])));
5210
+ this.learningSnapshot = snapshot;
5211
+ loadOutcome = "success";
5212
+ loadedSkills = snapshot.skillsPage.total;
5213
+ loadedInsights = snapshot.insightsPage.total;
5214
+ loadedPendingThreads = snapshot.pendingThreadCount;
5215
+ this.learningSnapshotScope = `${requestContext}|${snapshot.projectKey}|${containerId}`;
5216
+ this.learningError = null;
5217
+ this.learningPollFailureCount = 0;
5218
+ if (snapshot.configuration.state === "configured") {
5219
+ require_learning_setup.clearLearningSetupMarker();
5220
+ this.learningSetupMarker = null;
5221
+ }
5222
+ } catch (error) {
5223
+ if (generation !== this.learningRequestGeneration || controller.signal.aborted) return;
5224
+ if (error instanceof require_inspector_learning.InspectorLearningUnsupportedError) {
5225
+ loadOutcome = "unsupported";
5226
+ this.learningSupported = false;
5227
+ this.learningSnapshot = null;
5228
+ } else {
5229
+ this.learningError = error instanceof Error ? error.message : "Learning data is unavailable.";
5230
+ this.learningPollFailureCount += 1;
5231
+ }
5232
+ } finally {
5233
+ if (generation === this.learningRequestGeneration) {
5234
+ this.learningLoading = false;
5235
+ this.learningRefreshing = false;
5236
+ this.learningAbortController = null;
5237
+ if (!core.telemetryDisabled) require_telemetry.trackLearningSnapshotLoaded({
5238
+ outcome: loadOutcome,
5239
+ duration_bucket: require_telemetry.learningDurationBucket(performance.now() - startedAt),
5240
+ skills_bucket: require_telemetry.learningCountBucket(loadedSkills),
5241
+ insights_bucket: require_telemetry.learningCountBucket(loadedInsights),
5242
+ pending_threads_bucket: require_telemetry.learningCountBucket(loadedPendingThreads)
5243
+ });
5244
+ this.scheduleLearningPoll();
5245
+ this.requestUpdate();
5246
+ this.trackLearningViewState();
5247
+ if (resetSkillsPage || resetInsightsPage) this.refreshLearningSnapshot({
5248
+ preserve: true,
5249
+ ...resetSkillsPage ? { skillsPage: 1 } : {},
5250
+ ...resetInsightsPage ? { insightsPage: 1 } : {}
5251
+ });
5252
+ }
5253
+ }
5254
+ };
5255
+ this.copyFeaturePromptToClipboard = async (service, event, onboardingRunId = require_onboarding_prompt.createOnboardingRunId()) => {
5256
+ const clipboard = this.getClipboard(event);
5257
+ if (!clipboard?.writeText) return false;
5258
+ try {
5259
+ await clipboard.writeText(require_home_briefing.homeFeatureImplementationPrompt(service, { onboardingRunId }));
5260
+ return true;
5261
+ } catch {
5262
+ return false;
5263
+ }
5264
+ };
5265
+ this.handleLearningSetupCopy = async (event) => {
5266
+ const service = this.getHomeFeaturePromptTarget("threads");
5267
+ if (!service || !this.core?.runtimeUrl) return;
5268
+ const copied = await this.copyFeaturePromptToClipboard(service, event, this.getOnboardingRunId());
5269
+ if (!this.core.telemetryDisabled) require_telemetry.trackLearningSetupPromptClicked({ outcome: copied ? "success" : "failure" });
5270
+ if (!copied) {
5271
+ this.learningPromptCopyState = "error";
5272
+ this.requestUpdate();
5273
+ return;
5274
+ }
5275
+ this.learningPromptCopyState = "copied";
5276
+ this.learningSetupMarker = require_learning_setup.writeLearningSetupMarker({
5277
+ runtimeUrl: this.core.runtimeUrl,
5278
+ agentId: this.getLearningAgentId()
5279
+ });
5280
+ this.selectedMenu = "memories";
5281
+ this.persistState();
5282
+ this.requestUpdate();
5283
+ this.refreshLearningSnapshot({ preserve: false });
5284
+ };
5285
+ this.handleLearningPage = (event) => {
5286
+ const { section, page } = event.detail;
5287
+ const currentPage = section === "skills" ? this.learningSnapshot?.skillsPage.page ?? 1 : this.learningSnapshot?.insightsPage.page ?? 1;
5288
+ if (!this.core?.telemetryDisabled) require_telemetry.trackLearningPageChanged({
5289
+ section,
5290
+ direction: page < currentPage ? "previous" : "next"
5291
+ });
5292
+ this.refreshLearningSnapshot({
5293
+ preserve: true,
5294
+ ...section === "skills" ? { skillsPage: page } : { insightsPage: page }
5295
+ });
5296
+ };
5297
+ this.handleLearningEvidence = (event) => {
5298
+ this.focusThread({
5299
+ threadId: event.detail.threadId,
5300
+ ...event.detail.messageId ? { messageId: event.detail.messageId } : {}
5301
+ });
5302
+ };
5093
5303
  this.handleDocumentVisibilityChange = () => {
5094
5304
  this.accountCtaMotionPaused = document.visibilityState !== "visible";
5095
5305
  this.refreshInspectorDismissalState();
5096
5306
  if (document.visibilityState === "visible" && !this.isOpen && !this.isInspectorDismissed) this.flushPendingSignalPulse();
5307
+ if (document.visibilityState === "visible" && this.isOpen && this.selectedMenu === "memories") this.refreshLearningSnapshot({ preserve: true });
5308
+ else this.cancelLearningPoll();
5097
5309
  this.requestUpdate();
5098
5310
  };
5099
5311
  this.handlePillClick = (event) => {
@@ -5215,17 +5427,8 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
5215
5427
  feature_id: service.id,
5216
5428
  onboarding_run_id: onboardingRunId
5217
5429
  });
5218
- const clipboard = this.getClipboard(event);
5219
- if (!clipboard?.writeText) {
5220
- this.showHomeFeaturePromptCopyState(service.id, "error", generation);
5221
- return;
5222
- }
5223
- try {
5224
- await clipboard.writeText(require_home_briefing.homeFeatureImplementationPrompt(service, { onboardingRunId }));
5225
- this.showHomeFeaturePromptCopyState(service.id, "copied", generation);
5226
- } catch {
5227
- this.showHomeFeaturePromptCopyState(service.id, "error", generation);
5228
- }
5430
+ if (await this.copyFeaturePromptToClipboard(service, event, onboardingRunId)) this.showHomeFeaturePromptCopyState(service.id, "copied", generation);
5431
+ else this.showHomeFeaturePromptCopyState(service.id, "error", generation);
5229
5432
  };
5230
5433
  this.handleIntelligencePromptCopy = async (event) => {
5231
5434
  this.clearIntelligencePromptReset();
@@ -6078,6 +6281,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
6078
6281
  this._threadsByAgent.set(agentId, threads);
6079
6282
  this.rebuildFlattenedThreads();
6080
6283
  this.autoSelectLatestThread();
6284
+ if (this.selectedMenu === "memories" && this.shouldPollLearningSetup() && !this.learningLoading && !this.learningRefreshing) this.refreshLearningSnapshot({ preserve: true });
6081
6285
  this.requestUpdate();
6082
6286
  });
6083
6287
  const statusSub = store.select(createThreadStoreStatusSelector()).subscribe(({ error, isLoading }) => {
@@ -6258,6 +6462,8 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
6258
6462
  this.clearAllEventErrors();
6259
6463
  const supportsInspectorMetadata = this.coreSupportsInspectorMetadata(core);
6260
6464
  this.updateInspectorMetadataProjection(this.readCoreInspectorMetadata(core));
6465
+ this.learningSupported = core.inspectorLearning;
6466
+ this.learningProjectIdentity = JSON.stringify(this.inspectorMetadataProjection.identity ?? null);
6261
6467
  this.coreSubscriber = {
6262
6468
  onRuntimeConnectionStatusChanged: ({ status }) => {
6263
6469
  this.runtimeStatus = status;
@@ -6265,16 +6471,22 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
6265
6471
  const threadCapabilityWasEnabled = this.threadCapabilityEnabled === true;
6266
6472
  this.synchronizeThreadCapability();
6267
6473
  if (status === "connected") {
6474
+ this.learningSupported = core.inspectorLearning;
6268
6475
  if (!core.telemetryDisabled) {
6269
6476
  require_telemetry.ensureTelemetryDistinctId();
6270
6477
  require_telemetry.maybeShowDisclosure();
6271
6478
  }
6272
6479
  this.flushPendingWhatsNewTelemetry();
6480
+ if (this.isLearningStatusVisible()) {
6481
+ this.clearLearningSnapshot();
6482
+ this.refreshLearningSnapshot({ preserve: false });
6483
+ }
6273
6484
  if (threadCapabilityWasEnabled && this.areThreadEndpointsAvailable()) for (const agentId of this._ownedThreadStores.keys()) this.refreshOwnedThreadStore(agentId);
6274
6485
  } else {
6275
6486
  this._threadsByAgent.clear();
6276
6487
  this._threads = [];
6277
6488
  this.clearInspectorUsageRefresh();
6489
+ this.clearLearningSnapshot();
6278
6490
  }
6279
6491
  this.requestUpdate();
6280
6492
  },
@@ -6289,6 +6501,12 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
6289
6501
  ...supportsInspectorMetadata ? { onInspectorMetadataChanged: ({ inspectorMetadata }) => {
6290
6502
  if (this._core !== core) return;
6291
6503
  this.updateInspectorMetadataProjection(inspectorMetadata);
6504
+ const identity = JSON.stringify(this.inspectorMetadataProjection.identity ?? null);
6505
+ if (identity !== this.learningProjectIdentity) {
6506
+ this.learningProjectIdentity = identity;
6507
+ this.clearLearningSnapshot();
6508
+ if (this.isLearningStatusVisible()) this.refreshLearningSnapshot({ preserve: false });
6509
+ }
6292
6510
  this.requestUpdate();
6293
6511
  } } : {},
6294
6512
  onError: ({ code, error, context }) => {
@@ -6448,6 +6666,68 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
6448
6666
  this._recallQuery = "";
6449
6667
  this.requestUpdate();
6450
6668
  }
6669
+ getLearningAgentId() {
6670
+ if (this.selectedContext !== "all-agents" && this.core?.agents[this.selectedContext]) return this.selectedContext;
6671
+ return null;
6672
+ }
6673
+ /** Whether a visible surface needs the current Learning connection status. */
6674
+ isLearningStatusVisible() {
6675
+ return this.launcherHudOpen || this.isOpen && (this.selectedMenu === "home" || this.selectedMenu === "memories");
6676
+ }
6677
+ isLearningSetupActive() {
6678
+ const runtimeUrl = this.core?.runtimeUrl;
6679
+ if (!runtimeUrl) return false;
6680
+ return require_learning_setup.learningSetupMarkerMatches(this.learningSetupMarker, runtimeUrl, this.getLearningAgentId());
6681
+ }
6682
+ trackLearningViewState() {
6683
+ if (!this.isOpen || this.selectedMenu !== "memories" || this.core?.telemetryDisabled) return;
6684
+ const state = require_learning_view.deriveLearningViewState({
6685
+ supported: this.learningSupported,
6686
+ loading: this.learningLoading,
6687
+ error: this.learningError,
6688
+ snapshot: this.learningSnapshot,
6689
+ setupActive: this.isLearningSetupActive()
6690
+ });
6691
+ if (state === this.learningViewedState) return;
6692
+ this.learningViewedState = state;
6693
+ require_telemetry.trackLearningPaneViewed({ state });
6694
+ }
6695
+ cancelLearningPoll() {
6696
+ if (this.learningPollTimer !== null) {
6697
+ clearTimeout(this.learningPollTimer);
6698
+ this.learningPollTimer = null;
6699
+ }
6700
+ }
6701
+ shouldPollLearningSetup() {
6702
+ if (!this.isOpen || this.selectedMenu !== "memories" || document.visibilityState !== "visible" || !this.learningSupported) return false;
6703
+ const snapshot = this.learningSnapshot;
6704
+ if (!snapshot) return this.isLearningSetupActive();
6705
+ if (snapshot.configuration.state === "not_configured") return this.isLearningSetupActive();
6706
+ return snapshot.configuration.state === "configured" && !snapshot.run.hasEverSucceeded && !snapshot.run.hasActiveRun && snapshot.pendingThreadCount === 0 && snapshot.skillsPage.total === 0 && snapshot.insightsPage.total === 0;
6707
+ }
6708
+ scheduleLearningPoll() {
6709
+ this.cancelLearningPoll();
6710
+ if (!this.shouldPollLearningSetup()) return;
6711
+ const delay = this.learningPollFailureCount === 0 ? 5e3 : this.learningPollFailureCount === 1 ? 1e4 : 3e4;
6712
+ this.learningPollTimer = setTimeout(() => {
6713
+ this.learningPollTimer = null;
6714
+ this.refreshLearningSnapshot({ preserve: true });
6715
+ }, delay);
6716
+ }
6717
+ clearLearningSnapshot() {
6718
+ this.cancelLearningRequest();
6719
+ this.learningSnapshot = null;
6720
+ this.learningSnapshotScope = null;
6721
+ this.learningError = null;
6722
+ this.learningLoading = false;
6723
+ this.learningRefreshing = false;
6724
+ this.cancelLearningPoll();
6725
+ }
6726
+ cancelLearningRequest() {
6727
+ this.learningRequestGeneration += 1;
6728
+ this.learningAbortController?.abort();
6729
+ this.learningAbortController = null;
6730
+ }
6451
6731
  detachFromCore() {
6452
6732
  this.threadCapabilityGeneration += 1;
6453
6733
  this.threadCapabilityEnabled = null;
@@ -6474,6 +6754,8 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
6474
6754
  this._recallLoading = false;
6475
6755
  this._recallError = null;
6476
6756
  this._recallQuery = "";
6757
+ this.clearLearningSnapshot();
6758
+ this.learningSupported = false;
6477
6759
  this.coreSubscriber = null;
6478
6760
  this.runtimeStatus = null;
6479
6761
  this.cancelThreadRefreshDebounce();
@@ -6500,6 +6782,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
6500
6782
  this.eventCounter = 0;
6501
6783
  }
6502
6784
  processAgentsChanged(agents) {
6785
+ const previousLearningAgentId = this.getLearningAgentId();
6503
6786
  this.synchronizeThreadCapability();
6504
6787
  const seenAgentIds = /* @__PURE__ */ new Set();
6505
6788
  for (const agent of Object.values(agents)) {
@@ -6515,6 +6798,15 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
6515
6798
  this.agentStates.delete(agentId);
6516
6799
  }
6517
6800
  this.updateContextOptions(seenAgentIds);
6801
+ const learningAgentId = this.getLearningAgentId();
6802
+ if (learningAgentId && this.core?.runtimeUrl && this.learningSetupMarker?.agentId === null && require_learning_setup.learningSetupMarkerMatches(this.learningSetupMarker, this.core.runtimeUrl, null)) this.learningSetupMarker = require_learning_setup.writeLearningSetupMarker({
6803
+ runtimeUrl: this.core.runtimeUrl,
6804
+ agentId: learningAgentId
6805
+ });
6806
+ if (previousLearningAgentId !== learningAgentId && this.isLearningStatusVisible()) {
6807
+ this.clearLearningSnapshot();
6808
+ this.refreshLearningSnapshot({ preserve: false });
6809
+ }
6518
6810
  this.refreshToolsSnapshot();
6519
6811
  this.requestUpdate();
6520
6812
  }
@@ -8595,8 +8887,8 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
8595
8887
 
8596
8888
  .cpk-launcher-hud__toggle[data-enabled="true"]
8597
8889
  .cpk-launcher-hud__toggle-track {
8598
- border-color: var(--hud-accent);
8599
- background: color-mix(in srgb, var(--hud-accent) 76%, transparent);
8890
+ border-color: #087653;
8891
+ background: #087653;
8600
8892
  }
8601
8893
 
8602
8894
  .cpk-launcher-hud__toggle[data-enabled="true"]
@@ -8619,8 +8911,8 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
8619
8911
  .cpk-launcher-hud[data-color-scheme="light"]
8620
8912
  .cpk-launcher-hud__toggle[data-enabled="true"]
8621
8913
  .cpk-launcher-hud__toggle-track {
8622
- border-color: #6757b0;
8623
- background: #7563c7;
8914
+ border-color: #087653;
8915
+ background: #087653;
8624
8916
  }
8625
8917
 
8626
8918
  .cpk-launcher-hud[data-color-scheme="light"]
@@ -8866,6 +9158,11 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
8866
9158
  height: 100%;
8867
9159
  object-fit: cover;
8868
9160
  }
9161
+ .cpk-threads-overview-video-embed {
9162
+ width: 100%;
9163
+ height: 100%;
9164
+ border: 0;
9165
+ }
8869
9166
 
8870
9167
  /* ── Header controls on the branded account strip ──────────── */
8871
9168
  .drag-handle > div[data-inspector-account-strip] button {
@@ -9169,6 +9466,12 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
9169
9466
  const viteHot = {}.hot;
9170
9467
  if (viteHot) viteHot.on("vite:beforeUpdate", this.handleAppBeforeUnload);
9171
9468
  this.hydrateStateFromStorageEarly();
9469
+ this.learningSetupMarker = require_learning_setup.readLearningSetupMarker();
9470
+ this.learningSetupUnsubscribe = require_learning_setup.subscribeToLearningSetupMarker((marker) => {
9471
+ this.learningSetupMarker = marker;
9472
+ this.requestUpdate();
9473
+ this.scheduleLearningPoll();
9474
+ });
9172
9475
  this.refreshInspectorDismissalState();
9173
9476
  this.subscribeToSystemColorScheme();
9174
9477
  this.exampleTourDismissed = this.readThreadsExampleTourDismissed();
@@ -9200,6 +9503,9 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
9200
9503
  }
9201
9504
  this.clearIconRailContextCloseTimer();
9202
9505
  this.unsubscribeFromInspectorThreadBridge();
9506
+ this.learningSetupUnsubscribe?.();
9507
+ this.learningSetupUnsubscribe = null;
9508
+ this.clearLearningSnapshot();
9203
9509
  this.stopIntelligenceStory();
9204
9510
  this.clearIntelligencePromptReset();
9205
9511
  this.homeFeaturePromptCopyGeneration += 1;
@@ -9509,6 +9815,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
9509
9815
  this.resolveLauncherHudSide();
9510
9816
  this.launcherHudIntro = true;
9511
9817
  this.launcherHudOpen = true;
9818
+ this.refreshLearningSnapshot({ preserve: true });
9512
9819
  this.requestUpdate();
9513
9820
  this.launcherHudIntroEndTimer = setTimeout(() => {
9514
9821
  this.launcherHudIntroEndTimer = null;
@@ -9556,6 +9863,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
9556
9863
  }
9557
9864
  if (this.launcherHudOpen) return;
9558
9865
  this.launcherHudOpen = true;
9866
+ this.refreshLearningSnapshot({ preserve: true });
9559
9867
  this.requestUpdate();
9560
9868
  }
9561
9869
  closeLauncherHud() {
@@ -9950,7 +10258,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
9950
10258
  type: lastRuntimeEvent.type,
9951
10259
  timestamp: lastRuntimeEvent.timestamp
9952
10260
  } : void 0,
9953
- memoriesOn: this._memorySubscribed && !this._memoriesLoading && this._memoriesAvailable,
10261
+ learningOn: this.learningSupported && this.learningError === null && this.learningSnapshot?.configuration.state === "configured",
9954
10262
  a2uiOn: this._core?.a2uiEnabled === true,
9955
10263
  openGenUiOn: this._core?.openGenerativeUIEnabled === true,
9956
10264
  suggestionsOn: this._core?.suggestions === true,
@@ -10489,10 +10797,10 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
10489
10797
  getHomeFeaturePromptTarget(serviceId) {
10490
10798
  return this.getHomeModel().services.find((service) => service.id === serviceId);
10491
10799
  }
10492
- renderFeatureSetupPrompt(serviceId, className) {
10800
+ renderFeatureSetupPrompt(serviceId, className, options) {
10493
10801
  const service = this.getHomeFeaturePromptTarget(serviceId);
10494
10802
  if (!service) return lit.nothing;
10495
- const copyState = this.homeFeaturePromptCopyState?.serviceId === service.id ? this.homeFeaturePromptCopyState.state : "idle";
10803
+ const copyState = options?.copyState ?? (this.homeFeaturePromptCopyState?.serviceId === service.id ? this.homeFeaturePromptCopyState.state : "idle");
10496
10804
  const label = copyState === "copied" ? "Copied" : copyState === "error" ? "Copy blocked" : "Copy setup prompt";
10497
10805
  return lit.html`
10498
10806
  <button
@@ -10502,7 +10810,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
10502
10810
  data-inspector-threads-setup-prompt=${service.id === "threads" ? "" : lit.nothing}
10503
10811
  data-copy-state=${copyState}
10504
10812
  aria-label=${copyState === "copied" ? `${service.label} setup prompt copied` : copyState === "error" ? `Could not copy the ${service.label} setup prompt. Try again` : `Copy setup prompt for ${service.label}`}
10505
- @click=${(event) => this.handleHomeFeaturePromptCopy(service, event)}
10813
+ @click=${(event) => options?.onClick ? options.onClick(event) : this.handleHomeFeaturePromptCopy(service, event)}
10506
10814
  >
10507
10815
  ${this.renderIcon(copyState === "copied" ? "Check" : "Copy")}
10508
10816
  ${label}
@@ -11528,6 +11836,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
11528
11836
  }
11529
11837
  this.ensureAnnouncementLoading();
11530
11838
  this.isOpen = true;
11839
+ if (this.isLearningStatusVisible()) this.refreshLearningSnapshot({ preserve: this.learningSnapshot !== null });
11531
11840
  this.cancelGestureTail();
11532
11841
  this.persistState();
11533
11842
  this.trackOpened(source, hadUnseenAnnouncement, firstOpen, activeSignalAtOpen);
@@ -11545,6 +11854,9 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
11545
11854
  if (this.isPoppedOut) return;
11546
11855
  if (!this.isOpen) return;
11547
11856
  this.isOpen = false;
11857
+ this.cancelLearningPoll();
11858
+ this.cancelLearningRequest();
11859
+ this.learningViewedState = null;
11548
11860
  if (this.dockMode !== "floating") this.removeDockStyles();
11549
11861
  this.persistState();
11550
11862
  this.updateHostTransform("button");
@@ -12446,15 +12758,11 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
12446
12758
  });
12447
12759
  }
12448
12760
  getVisibleInspectorMetadataAction() {
12449
- const { threadsFooterAction, lockedAction } = this.inspectorMetadataProjection;
12450
- if (threadsFooterAction && !this.settingsOpen && this.selectedMenu === "threads") return {
12761
+ const { threadsFooterAction } = this.inspectorMetadataProjection;
12762
+ if (threadsFooterAction && !this.settingsOpen && this.selectedMenu === "threads" && this.areThreadEndpointsAvailable()) return {
12451
12763
  action: threadsFooterAction,
12452
12764
  placement: "threads-footer"
12453
12765
  };
12454
- if (lockedAction && !this.settingsOpen && this.selectedMenu === "threads" && !this.areThreadEndpointsAvailable()) return {
12455
- action: lockedAction,
12456
- placement: "locked"
12457
- };
12458
12766
  }
12459
12767
  /** Return paired stable navigation keys, or neither for an invalid leaf. */
12460
12768
  getMetadataTelemetryNavigation() {
@@ -12555,8 +12863,8 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
12555
12863
  else if (state === "empty_enabled") require_telemetry.trackThreadsEmptyEnabledViewed(props);
12556
12864
  else require_telemetry.trackThreadsEnabledViewed(props);
12557
12865
  }
12558
- shouldRenderExampleThreads(locked, displayThreads, threadsErrorMessage, threadsLoading) {
12559
- return locked || !threadsErrorMessage && !threadsLoading && displayThreads.length === 0;
12866
+ shouldRenderExampleThreads(displayThreads, threadsErrorMessage, threadsLoading) {
12867
+ return !threadsErrorMessage && !threadsLoading && displayThreads.length === 0;
12560
12868
  }
12561
12869
  isExampleThreadId(threadId) {
12562
12870
  return THREADS_EXAMPLE_THREADS.some((thread) => thread.id === threadId);
@@ -12967,44 +13275,112 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
12967
13275
  ` : lit.nothing}
12968
13276
  `;
12969
13277
  }
12970
- renderThreadsExampleOverview(locked) {
12971
- const lockedCopy = locked ? this.getThreadsLockedCopy() : void 0;
12972
- const { lockedAction } = this.inspectorMetadataProjection;
13278
+ renderThreadsExampleOverview() {
12973
13279
  const onboardingAction = this.getThreadsEmptyOnboardingAction();
12974
13280
  return lit.html`
12975
13281
  <div class="cpk-threads-overview">
12976
13282
  <div class="cpk-threads-overview-content">
12977
13283
  <h2 class="cpk-threads-overview-title">
12978
- ${lockedCopy?.heading ?? "Threads are persistent, inspectable conversations"}
13284
+ Threads are persistent, inspectable conversations
12979
13285
  </h2>
12980
13286
  ${this.renderThreadsExampleOverviewVideo()}
12981
13287
  <p class="cpk-threads-overview-copy">
12982
- ${lockedCopy?.description ?? "Take a tour with the example threads in the sidebar. Then, start chatting in your app to create the first real thread."}
13288
+ Take a tour with the example threads in the sidebar. Then, start
13289
+ chatting in your app to create the first real thread.
12983
13290
  </p>
12984
- ${locked ? this.renderRuntimeEntitlementDiagnostic(this.getRuntimeEntitlementDiagnostic()) : lit.nothing}
12985
13291
  <div class="cpk-threads-overview-actions">
12986
- ${locked ? lit.html`
12987
- ${this.renderFeatureSetupPrompt("threads", "cpk-threads-overview-action cpk-threads-overview-action-primary")}
12988
- ${lockedAction ? this.renderInspectorAction(lockedAction, "locked") : lit.nothing}
12989
- ` : lit.html`
12990
- <a
12991
- href=${this.getThreadsDocsUrl()}
12992
- target="_blank"
12993
- rel="noopener"
12994
- class="cpk-threads-overview-action cpk-threads-overview-action-primary"
12995
- >
12996
- Learn how Threads work
12997
- </a>
12998
- <a
12999
- href=${onboardingAction.href}
13000
- target="_blank"
13001
- rel="noopener"
13002
- class="cpk-threads-overview-action cpk-threads-overview-action-secondary"
13003
- >
13004
- ${onboardingAction.label}
13005
- </a>
13006
- `}
13292
+ <a
13293
+ href=${this.getThreadsDocsUrl()}
13294
+ target="_blank"
13295
+ rel="noopener"
13296
+ class="cpk-threads-overview-action cpk-threads-overview-action-primary"
13297
+ >
13298
+ Learn how Threads work
13299
+ </a>
13300
+ <a
13301
+ href=${onboardingAction.href}
13302
+ target="_blank"
13303
+ rel="noopener"
13304
+ class="cpk-threads-overview-action cpk-threads-overview-action-secondary"
13305
+ >
13306
+ ${onboardingAction.label}
13307
+ </a>
13308
+ </div>
13309
+ </div>
13310
+ </div>
13311
+ `;
13312
+ }
13313
+ renderLockedFeatureOverview({ serviceId, featureName, heading, description, videoUrl, videoTitle, outlineItems, setupPrompt }) {
13314
+ return lit.html`
13315
+ <div
13316
+ class="cpk-locked-feature"
13317
+ data-inspector-locked-feature=${serviceId}
13318
+ >
13319
+ <div class="cpk-locked-feature-layout">
13320
+ <div class="cpk-locked-feature-hero">
13321
+ <div class="cpk-locked-feature-copy">
13322
+ <div class="cpk-locked-feature-name">
13323
+ <span class="cpk-locked-feature-icon" aria-hidden="true">
13324
+ ${serviceId === "threads" ? (0, lit_directives_unsafe_html_js.unsafeHTML)(this.customTabIcons.threads) : this.renderIcon("Brain")}
13325
+ </span>
13326
+ ${featureName}
13327
+ </div>
13328
+ <h2 class="cpk-locked-feature-title">${heading}</h2>
13329
+ <p class="cpk-locked-feature-description">${description}</p>
13330
+ <div class="cpk-threads-overview-actions">
13331
+ ${this.renderFeatureSetupPrompt(setupPrompt?.serviceId ?? serviceId, "inspector-account-cta cpk-locked-feature-setup-cta", setupPrompt ? {
13332
+ copyState: setupPrompt.copyState,
13333
+ onClick: setupPrompt.onClick
13334
+ } : void 0)}
13335
+ <a
13336
+ data-inspector-locked-feature-talk=${serviceId}
13337
+ href=${this.getTalkToEngineerUrl()}
13338
+ target="_blank"
13339
+ rel="noopener noreferrer"
13340
+ aria-label="Talk to an Engineer (opens in a new tab)"
13341
+ class="cpk-threads-overview-action cpk-threads-overview-action-secondary"
13342
+ @click=${this.handleThreadsTalkToEngineerClick}
13343
+ >
13344
+ Talk to an Engineer
13345
+ </a>
13346
+ </div>
13347
+ </div>
13348
+ <div class="cpk-locked-feature-media">
13349
+ <div class="cpk-threads-overview-video-frame cpk-locked-feature-video">
13350
+ <iframe
13351
+ class="cpk-threads-overview-video-embed"
13352
+ data-inspector-feature-video=${serviceId}
13353
+ src=${videoUrl}
13354
+ title=${videoTitle}
13355
+ loading="lazy"
13356
+ allow="fullscreen; picture-in-picture"
13357
+ allowfullscreen
13358
+ ></iframe>
13359
+ </div>
13360
+ </div>
13007
13361
  </div>
13362
+ <section
13363
+ class="cpk-locked-feature-outline"
13364
+ data-inspector-feature-outline=${serviceId}
13365
+ aria-label="${featureName} capabilities"
13366
+ >
13367
+ <div class="cpk-locked-feature-outline-list">
13368
+ ${outlineItems.map((item) => lit.html`
13369
+ <section class="cpk-locked-feature-outline-item">
13370
+ <h3>
13371
+ <span
13372
+ class="cpk-locked-feature-outline-icon"
13373
+ aria-hidden="true"
13374
+ >
13375
+ ${this.renderIcon(item.icon)}
13376
+ </span>
13377
+ ${item.title}
13378
+ </h3>
13379
+ <p>${item.description}</p>
13380
+ </section>
13381
+ `)}
13382
+ </div>
13383
+ </section>
13008
13384
  </div>
13009
13385
  </div>
13010
13386
  `;
@@ -13062,56 +13438,6 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
13062
13438
  </div>
13063
13439
  </div>
13064
13440
  </div>
13065
- `;
13066
- }
13067
- renderThreadsLockedBackgroundMockup() {
13068
- return lit.html`
13069
- <div aria-hidden="true" class="cpk-locked-preview">
13070
- <div class="cpk-locked-preview-sidebar">
13071
- ${[
13072
- {
13073
- width: 74,
13074
- accent: true
13075
- },
13076
- { width: 92 },
13077
- { width: 68 },
13078
- { width: 84 },
13079
- { width: 58 },
13080
- { width: 76 }
13081
- ].map((row) => lit.html`
13082
- <div
13083
- class="cpk-locked-preview-row"
13084
- data-accent=${row.accent ? "true" : "false"}
13085
- >
13086
- <div
13087
- class="cpk-locked-preview-bar cpk-locked-preview-row-title"
13088
- style="--preview-width: ${row.width}%;"
13089
- ></div>
13090
- <div
13091
- class="cpk-locked-preview-bar cpk-locked-preview-row-line"
13092
- ></div>
13093
- <div
13094
- class="cpk-locked-preview-bar cpk-locked-preview-row-line"
13095
- ></div>
13096
- </div>
13097
- `)}
13098
- </div>
13099
- <div class="cpk-locked-preview-main">
13100
- <div class="cpk-locked-preview-bar cpk-locked-preview-heading"></div>
13101
- <div class="cpk-locked-preview-bar cpk-locked-preview-copy"></div>
13102
- <div class="cpk-locked-preview-bar cpk-locked-preview-copy"></div>
13103
- <div class="cpk-locked-preview-cards">
13104
- <div class="cpk-locked-preview-card"></div>
13105
- <div class="cpk-locked-preview-card"></div>
13106
- </div>
13107
- <div
13108
- class="cpk-locked-preview-bar cpk-locked-preview-footer-line"
13109
- ></div>
13110
- <div
13111
- class="cpk-locked-preview-bar cpk-locked-preview-footer-line"
13112
- ></div>
13113
- </div>
13114
- </div>
13115
13441
  `;
13116
13442
  }
13117
13443
  getThreadsLockedCopy() {
@@ -13120,89 +13446,18 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
13120
13446
  heading: "Finish setting up Rich Threads",
13121
13447
  description: "Copy this prompt into your coding agent to finish the setup."
13122
13448
  };
13123
- case "none": return {
13124
- heading: "Enable Intelligence to inspect Threads.",
13125
- description: "Persist conversations and inspect saved thread history from the Inspector."
13449
+ case "none":
13450
+ case "unknown": return {
13451
+ heading: "Production-grade chat threads without the complexity. Self hostable.",
13452
+ description: "Chat threads that go beyond text with generative UI and multimodal inputs, built to replay missed events and stay in sync across tabs, sessions, and devices."
13126
13453
  };
13127
13454
  case "expired": return {
13128
13455
  heading: "Renew Intelligence to inspect Threads.",
13129
13456
  description: "Your Intelligence access has expired. Renew it to inspect saved thread history."
13130
13457
  };
13131
- case "unknown": return {
13132
- heading: "Threads are unavailable.",
13133
- description: "This runtime does not expose Threads for the Inspector."
13134
- };
13135
13458
  }
13136
13459
  }
13137
13460
  /**
13138
- * Prefer the Runtime's structured entitlement diagnostic and derive a
13139
- * compatibility diagnostic only when an older Core exposes legacy status.
13140
- */
13141
- getRuntimeEntitlementDiagnostic() {
13142
- const runtimeEntitlements = this.core?.runtimeEntitlements;
13143
- if (runtimeEntitlements) return runtimeEntitlements.status === "ready" ? { status: runtimeEntitlements.status } : {
13144
- status: runtimeEntitlements.status,
13145
- error: runtimeEntitlements.error
13146
- };
13147
- switch (this.core?.licenseStatus) {
13148
- case "valid": return { status: "ready" };
13149
- case "expired": return {
13150
- status: "degraded",
13151
- error: {
13152
- code: "legacy_license_expired",
13153
- message: "Legacy Runtime license has expired.",
13154
- retryable: false
13155
- }
13156
- };
13157
- case "expiring": return {
13158
- status: "degraded",
13159
- error: {
13160
- code: "legacy_license_expiring",
13161
- message: "Legacy Runtime license is expiring.",
13162
- retryable: false
13163
- }
13164
- };
13165
- case "invalid": return {
13166
- status: "misconfigured",
13167
- error: {
13168
- code: "legacy_license_invalid",
13169
- message: "Legacy Runtime license is invalid.",
13170
- retryable: false
13171
- }
13172
- };
13173
- case "none":
13174
- case "unknown": return { status: "unavailable" };
13175
- default: return null;
13176
- }
13177
- }
13178
- /** Render exact Runtime entitlement correlation details without gating UI. */
13179
- renderRuntimeEntitlementDiagnostic(diagnostic) {
13180
- if (!diagnostic) return lit.nothing;
13181
- return lit.html`
13182
- <div
13183
- role="status"
13184
- data-runtime-entitlement-status=${diagnostic.status}
13185
- style="
13186
- margin: -8px auto 18px;
13187
- max-width: 380px;
13188
- font-size: 11px;
13189
- line-height: 1.5;
13190
- color: #57575b;
13191
- "
13192
- >
13193
- <div style="font-weight: 600;">
13194
- Runtime entitlement: ${diagnostic.status}
13195
- </div>
13196
- ${diagnostic.error ? lit.html`
13197
- <div>${diagnostic.error.message}</div>
13198
- <div>Code: ${diagnostic.error.code}</div>
13199
- ${diagnostic.error.requestId ? lit.html`<div>Request ID: ${diagnostic.error.requestId}</div>` : lit.nothing}
13200
- ${diagnostic.error.traceId ? lit.html`<div>Trace ID: ${diagnostic.error.traceId}</div>` : lit.nothing}
13201
- ` : lit.nothing}
13202
- </div>
13203
- `;
13204
- }
13205
- /**
13206
13461
  * Renders the realtime-connection indicator in the memory-store header.
13207
13462
  * Only `"connected"` shows the live (green-dot) state; `"connecting"` shows a
13208
13463
  * muted amber "reconnecting" and `"unavailable"` a muted grey "offline", so
@@ -13237,44 +13492,64 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
13237
13492
  `;
13238
13493
  }
13239
13494
  renderMemoriesView() {
13240
- if (!this.getHomeModel().services.some((service) => service.id === "memory" && service.enabled)) return lit.html`
13241
- <div class="cpk-memory-locked">
13242
- ${this.renderThreadsLockedBackgroundMockup()}
13243
- <div aria-hidden="true" class="cpk-memory-locked-scrim"></div>
13244
- <div class="cpk-memory-locked-content">
13245
- <div aria-hidden="true" class="cpk-memory-locked-icon-wrap">
13246
- <div class="cpk-memory-locked-icon">
13247
- ${this.renderIcon("Lock")}
13248
- </div>
13249
- </div>
13250
- <h2 class="cpk-memory-locked-title">Learning</h2>
13251
- <p class="cpk-memory-locked-copy">
13252
- ${this._memoryStoreUnsupported ? "Learning is unavailable in this version of the @copilotkit SDK. Upgrade @copilotkit/core (and @copilotkit/react) to a version that supports long-term memory." : "Learning turns durable information from agent interactions into reusable context. It isn't enabled on this deployment."}
13253
- </p>
13254
- <div class="cpk-memory-locked-actions">
13255
- ${this.renderFeatureSetupPrompt("memory", "cpk-memory-locked-action")}
13256
- <a
13257
- href=${this.getTalkToEngineerUrl()}
13258
- target="_blank"
13259
- rel="noopener"
13260
- class="cpk-memory-locked-action"
13261
- @click=${this.handleThreadsTalkToEngineerClick}
13262
- >
13263
- Talk to an Engineer
13264
- </a>
13265
- <a
13266
- href=${this.getIntelligenceSignupUrl()}
13267
- target="_blank"
13268
- rel="noopener"
13269
- class="cpk-memory-locked-action cpk-memory-locked-action-secondary"
13270
- @click=${this.handleThreadsIntelligenceSignupClick}
13271
- >
13272
- Sign up for Intelligence
13273
- </a>
13274
- </div>
13275
- </div>
13276
- </div>
13277
- `;
13495
+ if (require_learning_view.deriveLearningViewState({
13496
+ supported: this.learningSupported,
13497
+ loading: this.learningLoading,
13498
+ error: this.learningError,
13499
+ snapshot: this.learningSnapshot,
13500
+ setupActive: this.isLearningSetupActive()
13501
+ }) === "landing") return this.renderLockedFeatureOverview({
13502
+ serviceId: "memory",
13503
+ featureName: "Learning",
13504
+ heading: "Turn every interaction into reusable context.",
13505
+ description: "Learning captures durable information from agent interactions and brings it back when it matters, so your product gets more useful over time.",
13506
+ videoUrl: LEARNING_LOCKED_VIDEO_URL,
13507
+ videoTitle: "CopilotKit Learning overview",
13508
+ outlineItems: LEARNING_LOCKED_FEATURE_OUTLINE,
13509
+ setupPrompt: {
13510
+ serviceId: "threads",
13511
+ copyState: this.learningPromptCopyState,
13512
+ onClick: (event) => void this.handleLearningSetupCopy(event)
13513
+ }
13514
+ });
13515
+ return lit.html`
13516
+ <cpk-learning-view
13517
+ data-color-scheme=${this.colorScheme}
13518
+ .supported=${this.learningSupported}
13519
+ .loading=${this.learningLoading}
13520
+ .refreshing=${this.learningRefreshing}
13521
+ .error=${this.learningError}
13522
+ .snapshot=${this.learningSnapshot}
13523
+ .setupActive=${this.isLearningSetupActive()}
13524
+ .copyState=${this.learningPromptCopyState}
13525
+ .setupPrompt=${this.getHomeFeaturePromptTarget("threads") ? require_home_briefing.homeFeatureImplementationPrompt(this.getHomeFeaturePromptTarget("threads"), { onboardingRunId: this.getOnboardingRunId() }) : ""}
13526
+ @learning-retry=${() => this.refreshLearningSnapshot({ preserve: this.learningSnapshot !== null })}
13527
+ @learning-copy-setup=${(event) => this.handleLearningSetupCopy(event)}
13528
+ @learning-page=${(event) => this.handleLearningPage(event)}
13529
+ @learning-open-evidence=${(event) => this.handleLearningEvidence(event)}
13530
+ @learning-evidence-opened=${() => {
13531
+ if (!this.core?.telemetryDisabled) require_telemetry.trackLearningEvidenceOpened();
13532
+ }}
13533
+ @learning-skill-toggle=${(event) => {
13534
+ if (!this.core?.telemetryDisabled) require_telemetry.trackLearningSkillToggled({ action: event.detail.action });
13535
+ }}
13536
+ @learning-web-link=${(event) => {
13537
+ if (!this.core?.telemetryDisabled) require_telemetry.trackLearningWebAppOpened({ category: event.detail.category });
13538
+ }}
13539
+ ></cpk-learning-view>
13540
+ `;
13541
+ }
13542
+ /** Legacy Memory rendering kept isolated while published Memory APIs remain. */
13543
+ renderLegacyMemoriesView() {
13544
+ if (!this.getHomeModel().services.some((service) => service.id === "memory" && service.enabled)) return this.renderLockedFeatureOverview({
13545
+ serviceId: "memory",
13546
+ featureName: "Learning",
13547
+ heading: this._memoryStoreUnsupported ? "Upgrade to enable Learning" : "Turn every interaction into reusable context.",
13548
+ description: this._memoryStoreUnsupported ? "Learning requires a newer version of @copilotkit/core and @copilotkit/react. Copy the setup prompt to upgrade and add long-term memory." : "Learning captures durable information from agent interactions and brings it back when it matters, so your product gets more useful over time.",
13549
+ videoUrl: LEARNING_LOCKED_VIDEO_URL,
13550
+ videoTitle: "CopilotKit Learning overview",
13551
+ outlineItems: LEARNING_LOCKED_FEATURE_OUTLINE
13552
+ });
13278
13553
  if (this._memoriesError && this._memories.length === 0) return lit.html`
13279
13554
  <div
13280
13555
  style="
@@ -13485,16 +13760,27 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
13485
13760
  `;
13486
13761
  }
13487
13762
  renderThreadsView() {
13488
- const locked = !this.areThreadEndpointsAvailable();
13763
+ if (!this.areThreadEndpointsAvailable()) {
13764
+ this.trackThreadsViewStateOnce("locked");
13765
+ const lockedCopy = this.getThreadsLockedCopy();
13766
+ return this.renderLockedFeatureOverview({
13767
+ serviceId: "threads",
13768
+ featureName: "Rich Threads",
13769
+ heading: lockedCopy.heading,
13770
+ description: lockedCopy.description,
13771
+ videoUrl: THREADS_LOCKED_VIDEO_URL,
13772
+ videoTitle: "Rich Threads overview",
13773
+ outlineItems: THREADS_LOCKED_FEATURE_OUTLINE
13774
+ });
13775
+ }
13489
13776
  const { displayThreads, threadsErrorMessage, threadsLoading } = this.getActiveThreadsState();
13490
- const loadingWithoutRows = !locked && threadsLoading && !threadsErrorMessage && displayThreads.length === 0;
13491
- const showingExamples = this.shouldRenderExampleThreads(locked, displayThreads, threadsErrorMessage, threadsLoading);
13492
- const visibleThreads = !locked && (threadsErrorMessage || loadingWithoutRows) ? [] : showingExamples ? THREADS_EXAMPLE_THREADS : displayThreads;
13777
+ const loadingWithoutRows = threadsLoading && !threadsErrorMessage && displayThreads.length === 0;
13778
+ const showingExamples = this.shouldRenderExampleThreads(displayThreads, threadsErrorMessage, threadsLoading);
13779
+ const visibleThreads = threadsErrorMessage || loadingWithoutRows ? [] : showingExamples ? THREADS_EXAMPLE_THREADS : displayThreads;
13493
13780
  if (showingExamples) this.trackThreadsExampleViewedOnce();
13494
13781
  const selectedThread = this.selectedThreadId != null ? visibleThreads.find((t) => t.id === this.selectedThreadId) ?? null : null;
13495
13782
  const selectedThreadIsLocalExample = selectedThread !== null && selectedThread.id === this.selectedLocalExampleThreadId;
13496
- if (locked) this.trackThreadsViewStateOnce("locked");
13497
- else if (!threadsErrorMessage && (!threadsLoading || displayThreads.length > 0)) this.trackThreadsViewStateOnce(displayThreads.length === 0 ? "empty_enabled" : "enabled");
13783
+ if (!threadsErrorMessage && (!threadsLoading || displayThreads.length > 0)) this.trackThreadsViewStateOnce(displayThreads.length === 0 ? "empty_enabled" : "enabled");
13498
13784
  return lit.html`
13499
13785
  <div
13500
13786
  style="display:flex;height:100%;overflow:hidden;flex-direction:column;"
@@ -13532,7 +13818,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
13532
13818
  <div
13533
13819
  style="flex:1;min-width:0;overflow:hidden;display:flex;position:relative;"
13534
13820
  >
13535
- ${!locked && threadsErrorMessage ? lit.html`
13821
+ ${threadsErrorMessage ? lit.html`
13536
13822
  <div
13537
13823
  role="alert"
13538
13824
  style="
@@ -13595,7 +13881,7 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
13595
13881
  this.handleTryFromHere(event.detail);
13596
13882
  }}
13597
13883
  ></cpk-thread-details>
13598
- ${selectedThreadIsLocalExample ? this.renderThreadsExampleTour() : lit.nothing}` : showingExamples ? this.renderThreadsExampleOverview(locked) : lit.html`
13884
+ ${selectedThreadIsLocalExample ? this.renderThreadsExampleTour() : lit.nothing}` : showingExamples ? this.renderThreadsExampleOverview() : lit.html`
13599
13885
  <div
13600
13886
  style="
13601
13887
  flex: 1;
@@ -14287,10 +14573,18 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
14287
14573
  }
14288
14574
  if (key === "playground" && !this.playgroundAgent) this.startPlaygroundSession(false);
14289
14575
  if (key === "memories") {
14290
- this.ensureMemorySubscription();
14576
+ this.learningSupported = Boolean(this.core?.inspectorLearning);
14577
+ if (previousMenu !== "memories" || this.learningSnapshot === null) this.refreshLearningSnapshot({ preserve: previousMenu === "memories" });
14291
14578
  if (previousMenu !== "memories" && !this.core?.telemetryDisabled) require_telemetry.trackMemoriesTabClicked(this.getMemoriesTelemetryProps());
14579
+ } else if (previousMenu === "memories") {
14580
+ this.learningViewedState = null;
14581
+ this.cancelLearningPoll();
14582
+ this.cancelLearningRequest();
14583
+ }
14584
+ if (key === "home" && previousMenu !== "home") {
14585
+ this.refreshLearningSnapshot({ preserve: true });
14586
+ this.homeViewedThisOpen = false;
14292
14587
  }
14293
- if (key === "home" && previousMenu !== "home") this.homeViewedThisOpen = false;
14294
14588
  if (key === "ag-ui-events" || key === "agents") {
14295
14589
  if (!(this.pendingScrollToEventId !== null || this.pendingScrollToToolCallId !== null)) requestAnimationFrame(() => {
14296
14590
  const scroller = this.activeRoot.querySelector("#cpk-main-scroll");
@@ -14322,6 +14616,10 @@ var WebInspectorElement = class WebInspectorElement extends lit.LitElement {
14322
14616
  this.expandedRows.clear();
14323
14617
  this.autoSelectLatestThread();
14324
14618
  if (this.selectedMenu === "playground") this.startPlaygroundSession(false);
14619
+ else if (this.isLearningStatusVisible()) {
14620
+ this.clearLearningSnapshot();
14621
+ this.refreshLearningSnapshot({ preserve: false });
14622
+ }
14325
14623
  }
14326
14624
  this.contextMenuOpen = false;
14327
14625
  this.persistState();