@copilotkit/web-inspector 1.62.2 → 1.62.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.
package/dist/index.mjs CHANGED
@@ -3,13 +3,13 @@ import inspector_logo_default from "./assets/inspector-logo.mjs";
3
3
  import inspector_logo_icon_default from "./assets/inspector-logo-icon.mjs";
4
4
  import { applyAnchorPosition, centerContext, clampSize, constrainToViewport, keepPositionWithinViewport, updateAnchorFromPosition, updateSizeFromElement } from "./lib/context-helpers.mjs";
5
5
  import { isValidAnchor, isValidDockMode, isValidPosition, isValidSize, loadInspectorState, saveInspectorState } from "./lib/persistence.mjs";
6
- import { TELEMETRY_DOCS_URL, ensureTelemetryDistinctId, getRuntimeUrlType, getTelemetryDistinctIdForUrl, maybeShowDisclosure, trackBannerClicked, trackBannerViewed, trackTalkToEngineerClicked, trackThreadsEmptyEnabledViewed, trackThreadsEnabledViewed, trackThreadsIntelligenceSignupClicked, trackThreadsLockedViewed, trackThreadsTabClicked, trackThreadsTalkToEngineerClicked } from "./lib/telemetry.mjs";
6
+ import { TELEMETRY_DOCS_URL, ensureTelemetryDistinctId, getRuntimeUrlType, getTelemetryDistinctIdForUrl, maybeShowDisclosure, trackBannerClicked, trackBannerViewed, trackMemoriesTabClicked, trackTalkToEngineerClicked, trackThreadsEmptyEnabledViewed, trackThreadsEnabledViewed, trackThreadsIntelligenceSignupClicked, trackThreadsLockedViewed, trackThreadsTabClicked, trackThreadsTalkToEngineerClicked } from "./lib/telemetry.mjs";
7
7
  import { LitElement, css, html, nothing, unsafeCSS } from "lit";
8
8
  import { marked } from "marked";
9
9
  import { styleMap } from "lit/directives/style-map.js";
10
10
  import { unsafeHTML } from "lit/directives/unsafe-html.js";
11
11
  import { icons } from "lucide";
12
- import { CopilotKitCoreRuntimeConnectionStatus, ɵcreateThreadStore, ɵselectThreads, ɵselectThreadsError } from "@copilotkit/core";
12
+ import { CopilotKitCoreRuntimeConnectionStatus, ɵcreateThreadStore, ɵselectMemories, ɵselectMemoriesAvailable, ɵselectMemoriesError, ɵselectMemoriesIsLoading, ɵselectMemoriesRealtimeStatus, ɵselectThreads, ɵselectThreadsError } from "@copilotkit/core";
13
13
 
14
14
  //#region src/index.ts
15
15
  const WEB_INSPECTOR_TAG = "cpk-web-inspector";
@@ -2627,16 +2627,365 @@ ${unsafeHTML(highlightedJson(stateValue))}</pre
2627
2627
  `;
2628
2628
  }
2629
2629
  };
2630
+ var CpkMemoryList = class extends LitElement {
2631
+ constructor(..._args3) {
2632
+ super(..._args3);
2633
+ this.memories = [];
2634
+ this.search = "";
2635
+ this.kind = "all";
2636
+ this.onSearchInput = (event) => {
2637
+ this.search = event.target.value;
2638
+ };
2639
+ this.onKindClick = (event) => {
2640
+ const seg = event.target.closest("[data-kind]");
2641
+ if (!seg) return;
2642
+ this.kind = seg.dataset["kind"];
2643
+ };
2644
+ }
2645
+ static {
2646
+ this.properties = {
2647
+ memories: { attribute: false },
2648
+ search: { state: true },
2649
+ kind: { state: true }
2650
+ };
2651
+ }
2652
+ static {
2653
+ this.styles = css`
2654
+ @import url("https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600&family=Spline+Sans+Mono:wght@400;500&display=swap");
2655
+
2656
+ :host {
2657
+ display: flex;
2658
+ flex-direction: column;
2659
+ height: 100%;
2660
+ overflow: hidden;
2661
+ }
2662
+
2663
+ .cpk-ml {
2664
+ font-family: "Plus Jakarta Sans", sans-serif;
2665
+ display: flex;
2666
+ flex-direction: column;
2667
+ height: 100%;
2668
+ overflow: hidden;
2669
+ background: #f7f7f9;
2670
+ }
2671
+
2672
+ /* ── Search ── */
2673
+ .cpk-ml__search {
2674
+ padding: 10px 12px;
2675
+ border-bottom: 1px solid #dbdbe5;
2676
+ flex-shrink: 0;
2677
+ }
2678
+
2679
+ .cpk-ml__search-input {
2680
+ width: 100%;
2681
+ box-sizing: border-box;
2682
+ font-family: "Plus Jakarta Sans", sans-serif;
2683
+ font-size: 12px;
2684
+ padding: 7px 10px;
2685
+ border-radius: 6px;
2686
+ border: 1px solid #dbdbe5;
2687
+ background: #ffffff;
2688
+ color: #010507;
2689
+ outline: none;
2690
+ transition: border-color 0.15s;
2691
+ }
2692
+
2693
+ .cpk-ml__search-input:focus {
2694
+ border-color: #bec2ff;
2695
+ }
2696
+
2697
+ /* ── Kind filter ── */
2698
+ .cpk-ml__filter {
2699
+ display: flex;
2700
+ gap: 4px;
2701
+ padding: 8px 12px;
2702
+ border-bottom: 1px solid #dbdbe5;
2703
+ flex-shrink: 0;
2704
+ flex-wrap: wrap;
2705
+ }
2706
+
2707
+ .cpk-ml__filter-seg {
2708
+ font-family: "Plus Jakarta Sans", sans-serif;
2709
+ font-size: 11px;
2710
+ font-weight: 500;
2711
+ padding: 3px 9px;
2712
+ border-radius: 5px;
2713
+ border: 1px solid #dbdbe5;
2714
+ background: #ffffff;
2715
+ color: #57575b;
2716
+ cursor: pointer;
2717
+ transition:
2718
+ background 0.1s,
2719
+ border-color 0.1s,
2720
+ color 0.1s;
2721
+ user-select: none;
2722
+ }
2723
+
2724
+ .cpk-ml__filter-seg:hover {
2725
+ background: #f0f0f5;
2726
+ }
2727
+
2728
+ .cpk-ml__filter-seg--active {
2729
+ background: #bec2ff1a;
2730
+ border-color: #bec2ff;
2731
+ color: #010507;
2732
+ }
2733
+
2734
+ .cpk-ml__filter-count {
2735
+ font-family: "Spline Sans Mono", monospace;
2736
+ font-size: 9px;
2737
+ margin-left: 4px;
2738
+ color: #838389;
2739
+ }
2740
+
2741
+ /* ── List ── */
2742
+ .cpk-ml__list {
2743
+ flex: 1;
2744
+ overflow-y: auto;
2745
+ padding: 8px 12px;
2746
+ display: flex;
2747
+ flex-direction: column;
2748
+ gap: 8px;
2749
+ }
2750
+
2751
+ /* ── Card ── */
2752
+ .cpk-ml__card {
2753
+ background: #ffffff;
2754
+ border: 1px solid #e9e9ef;
2755
+ border-radius: 8px;
2756
+ padding: 10px 12px;
2757
+ display: flex;
2758
+ flex-direction: column;
2759
+ gap: 6px;
2760
+ }
2761
+
2762
+ .cpk-ml__card-badges {
2763
+ display: flex;
2764
+ gap: 6px;
2765
+ align-items: center;
2766
+ flex-wrap: wrap;
2767
+ }
2768
+
2769
+ /* Kind badge — color per kind */
2770
+ .cpk-ml__kind-badge {
2771
+ font-family: "Spline Sans Mono", monospace;
2772
+ font-size: 9px;
2773
+ padding: 1px 7px;
2774
+ border-radius: 4px;
2775
+ text-transform: uppercase;
2776
+ font-weight: 500;
2777
+ white-space: nowrap;
2778
+ }
2779
+
2780
+ .cpk-ml__kind-badge--topical {
2781
+ background: #eee6fe;
2782
+ color: #57575b;
2783
+ }
2784
+
2785
+ .cpk-ml__kind-badge--episodic {
2786
+ background: #e6f4fe;
2787
+ color: #2d5f80;
2788
+ }
2789
+
2790
+ .cpk-ml__kind-badge--operational {
2791
+ background: #e6feee;
2792
+ color: #2d6645;
2793
+ }
2794
+
2795
+ /* Scope badge */
2796
+ .cpk-ml__scope-badge {
2797
+ font-family: "Spline Sans Mono", monospace;
2798
+ font-size: 9px;
2799
+ padding: 1px 7px;
2800
+ border-radius: 4px;
2801
+ text-transform: uppercase;
2802
+ font-weight: 500;
2803
+ white-space: nowrap;
2804
+ background: #f0f0f5;
2805
+ color: #838389;
2806
+ }
2807
+
2808
+ /* Content */
2809
+ .cpk-ml__content {
2810
+ font-size: 12px;
2811
+ color: #010507;
2812
+ line-height: 1.5;
2813
+ word-break: break-word;
2814
+ }
2815
+
2816
+ /* Footer */
2817
+ .cpk-ml__footer {
2818
+ display: flex;
2819
+ align-items: center;
2820
+ justify-content: space-between;
2821
+ gap: 8px;
2822
+ margin-top: 2px;
2823
+ }
2824
+
2825
+ .cpk-ml__footer-threads {
2826
+ font-size: 10px;
2827
+ color: #838389;
2828
+ }
2829
+
2830
+ .cpk-ml__footer-id {
2831
+ font-family: "Spline Sans Mono", monospace;
2832
+ font-size: 9px;
2833
+ color: #c0c0c8;
2834
+ }
2835
+
2836
+ /* ── Empty state ── */
2837
+ .cpk-ml__empty {
2838
+ padding: 32px 16px;
2839
+ text-align: center;
2840
+ color: #838389;
2841
+ font-size: 12px;
2842
+ display: flex;
2843
+ flex-direction: column;
2844
+ align-items: center;
2845
+ gap: 8px;
2846
+ }
2847
+
2848
+ .cpk-ml__empty-icon {
2849
+ color: #c0c0c8;
2850
+ }
2851
+ `;
2852
+ }
2853
+ /** Memories that pass the current text search (before kind filter). */
2854
+ get searchFiltered() {
2855
+ const q = this.search.trim().toLowerCase();
2856
+ if (!q) return this.memories;
2857
+ return this.memories.filter((m) => m.content.toLowerCase().includes(q));
2858
+ }
2859
+ /** Memories that pass both search and kind filter. */
2860
+ get filtered() {
2861
+ const searched = this.searchFiltered;
2862
+ if (this.kind === "all") return searched;
2863
+ return searched.filter((m) => m.kind === this.kind);
2864
+ }
2865
+ /** Count of search-filtered memories for a given kind (for segment labels). */
2866
+ countForKind(kind) {
2867
+ return this.searchFiltered.filter((m) => m.kind === kind).length;
2868
+ }
2869
+ /** Truncate an id to first-4…last-4 characters. */
2870
+ shortId(id) {
2871
+ if (id.length <= 12) return id;
2872
+ return `${id.slice(0, 4)}…${id.slice(-4)}`;
2873
+ }
2874
+ renderKindBadge(kind) {
2875
+ return html`<span class="cpk-ml__kind-badge cpk-ml__kind-badge--${kind}"
2876
+ >${kind}</span
2877
+ >`;
2878
+ }
2879
+ renderEmpty() {
2880
+ const q = this.search.trim();
2881
+ if (this.memories.length === 0) return html`
2882
+ <div class="cpk-ml__empty">
2883
+ <svg
2884
+ width="24"
2885
+ height="24"
2886
+ viewBox="0 0 24 24"
2887
+ fill="none"
2888
+ stroke="currentColor"
2889
+ stroke-width="1.5"
2890
+ stroke-linecap="round"
2891
+ stroke-linejoin="round"
2892
+ class="cpk-ml__empty-icon"
2893
+ >
2894
+ <ellipse cx="12" cy="5" rx="9" ry="3" />
2895
+ <path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3" />
2896
+ <path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5" />
2897
+ </svg>
2898
+ No memories yet — tell the agent a durable fact and watch it appear.
2899
+ </div>
2900
+ `;
2901
+ if (q) return html`
2902
+ <div class="cpk-ml__empty">
2903
+ No memories match &ldquo;${q}&rdquo;.
2904
+ </div>
2905
+ `;
2906
+ return html`
2907
+ <div class="cpk-ml__empty">No ${this.kind} memories yet.</div>
2908
+ `;
2909
+ }
2910
+ render() {
2911
+ const filtered = this.filtered;
2912
+ return html`
2913
+ <div class="cpk-ml">
2914
+ <!-- Search -->
2915
+ <div class="cpk-ml__search">
2916
+ <input
2917
+ type="text"
2918
+ placeholder="Search memories…"
2919
+ .value=${this.search}
2920
+ @input=${this.onSearchInput}
2921
+ class="cpk-ml__search-input"
2922
+ />
2923
+ </div>
2924
+
2925
+ <!-- Kind filter -->
2926
+ <div class="cpk-ml__filter" @click=${this.onKindClick}>
2927
+ <button
2928
+ class="cpk-ml__filter-seg ${this.kind === "all" ? "cpk-ml__filter-seg--active" : ""}"
2929
+ data-kind="all"
2930
+ >
2931
+ All<span class="cpk-ml__filter-count">${this.searchFiltered.length}</span>
2932
+ </button>
2933
+ ${[
2934
+ "topical",
2935
+ "episodic",
2936
+ "operational"
2937
+ ].map((k) => html`
2938
+ <button
2939
+ class="cpk-ml__filter-seg ${this.kind === k ? "cpk-ml__filter-seg--active" : ""}"
2940
+ data-kind="${k}"
2941
+ >
2942
+ ${k}<span class="cpk-ml__filter-count">${this.countForKind(k)}</span>
2943
+ </button>
2944
+ `)}
2945
+ </div>
2946
+
2947
+ <!-- Memory list -->
2948
+ <div class="cpk-ml__list">
2949
+ ${filtered.map((m) => html`
2950
+ <div class="cpk-ml__card">
2951
+ <div class="cpk-ml__card-badges">
2952
+ ${this.renderKindBadge(m.kind)}
2953
+ <span class="cpk-ml__scope-badge">${m.scope}</span>
2954
+ </div>
2955
+ <div class="cpk-ml__content">${m.content}</div>
2956
+ <div class="cpk-ml__footer">
2957
+ <span class="cpk-ml__footer-threads"
2958
+ >${m.sourceThreadIds.length} source thread${m.sourceThreadIds.length === 1 ? "" : "s"}</span
2959
+ >
2960
+ <span class="cpk-ml__footer-id">${this.shortId(m.id)}</span>
2961
+ </div>
2962
+ </div>
2963
+ `)}
2964
+ ${filtered.length === 0 ? this.renderEmpty() : nothing}
2965
+ </div>
2966
+ </div>
2967
+ `;
2968
+ }
2969
+ };
2630
2970
  var ɵCpkThreadDetails = class extends CpkThreadInspector {};
2631
2971
  if (!customElements.get("cpk-thread-list")) customElements.define("cpk-thread-list", CpkThreadList);
2632
2972
  if (!customElements.get(THREAD_INSPECTOR_TAG)) customElements.define(THREAD_INSPECTOR_TAG, CpkThreadInspector);
2633
2973
  if (!customElements.get("cpk-thread-details")) customElements.define("cpk-thread-details", ɵCpkThreadDetails);
2974
+ if (!customElements.get("cpk-memory-list")) customElements.define("cpk-memory-list", CpkMemoryList);
2634
2975
  var WebInspectorElement = class extends LitElement {
2635
- constructor(..._args3) {
2636
- super(..._args3);
2976
+ constructor(..._args4) {
2977
+ super(..._args4);
2637
2978
  this._core = null;
2638
2979
  this.coreSubscriber = null;
2639
2980
  this.coreUnsubscribe = null;
2981
+ this._memories = [];
2982
+ this._memoriesLoading = false;
2983
+ this._memoriesError = null;
2984
+ this._memoriesAvailable = true;
2985
+ this._memoriesRealtimeStatus = "connecting";
2986
+ this._memoryUnsub = null;
2987
+ this._memorySubscribed = false;
2988
+ this._memoryStoreUnsupported = false;
2640
2989
  this.runtimeStatus = null;
2641
2990
  this.coreProperties = {};
2642
2991
  this.lastCoreError = null;
@@ -3052,6 +3401,11 @@ var WebInspectorElement = class extends LitElement {
3052
3401
  key: "threads",
3053
3402
  label: "Threads",
3054
3403
  icon: "MessageSquare"
3404
+ },
3405
+ {
3406
+ key: "memories",
3407
+ label: "Learning",
3408
+ icon: "Brain"
3055
3409
  }
3056
3410
  ];
3057
3411
  }
@@ -3077,6 +3431,13 @@ var WebInspectorElement = class extends LitElement {
3077
3431
  ...extra
3078
3432
  };
3079
3433
  }
3434
+ getMemoriesTelemetryProps() {
3435
+ return {
3436
+ posthog_distinct_id: (!this.core?.telemetryDisabled ? getTelemetryDistinctIdForUrl() : null) ?? void 0,
3437
+ memory_count: this._memories.length,
3438
+ available: this._memoriesAvailable
3439
+ };
3440
+ }
3080
3441
  getIntelligenceSignupUrl() {
3081
3442
  return this.appendRefParam(INTELLIGENCE_SIGNUP_URL, "cpk-inspector");
3082
3443
  }
@@ -3241,12 +3602,75 @@ var WebInspectorElement = class extends LitElement {
3241
3602
  const threadStores = typeof core.getThreadStores === "function" ? core.getThreadStores() : {};
3242
3603
  for (const [agentId, store] of Object.entries(threadStores)) this.subscribeToThreadStore(agentId, store);
3243
3604
  if (core.context) this.contextStore = this.normalizeContextStore(core.context);
3605
+ if (this.selectedMenu === "memories") this.ensureMemorySubscription();
3606
+ }
3607
+ /**
3608
+ * Lazily subscribes to the singleton memory store the first time the user
3609
+ * activates the Memories tab. This is deferred out of `attachToCore` because
3610
+ * `core.getMemoryStore()` is what creates + starts the store and opens
3611
+ * realtime — doing it on attach would start memory for apps that never use
3612
+ * it. Idempotent: repeated tab activations are guarded by
3613
+ * `_memorySubscribed`. On an older @copilotkit/core without `getMemoryStore`,
3614
+ * records the unsupported state so the teaser can guide an SDK upgrade.
3615
+ */
3616
+ ensureMemorySubscription() {
3617
+ if (this._memorySubscribed) return;
3618
+ const core = this._core;
3619
+ if (!core) return;
3620
+ if (typeof core.getMemoryStore !== "function") {
3621
+ this._memoryStoreUnsupported = true;
3622
+ this._memoriesAvailable = false;
3623
+ this.requestUpdate();
3624
+ return;
3625
+ }
3626
+ this._memorySubscribed = true;
3627
+ this._memoryStoreUnsupported = false;
3628
+ const memoryStore = core.getMemoryStore();
3629
+ const ms = memoryStore.getState();
3630
+ this._memories = ɵselectMemories(ms);
3631
+ this._memoriesLoading = ɵselectMemoriesIsLoading(ms);
3632
+ this._memoriesError = ɵselectMemoriesError(ms);
3633
+ this._memoriesAvailable = ɵselectMemoriesAvailable(ms);
3634
+ this._memoriesRealtimeStatus = ɵselectMemoriesRealtimeStatus(ms);
3635
+ const memSubs = [
3636
+ memoryStore.select(ɵselectMemories).subscribe((v) => {
3637
+ this._memories = v;
3638
+ this.requestUpdate();
3639
+ }),
3640
+ memoryStore.select(ɵselectMemoriesIsLoading).subscribe((v) => {
3641
+ this._memoriesLoading = v;
3642
+ this.requestUpdate();
3643
+ }),
3644
+ memoryStore.select(ɵselectMemoriesError).subscribe((v) => {
3645
+ this._memoriesError = v;
3646
+ this.requestUpdate();
3647
+ }),
3648
+ memoryStore.select(ɵselectMemoriesAvailable).subscribe((v) => {
3649
+ this._memoriesAvailable = v;
3650
+ this.requestUpdate();
3651
+ }),
3652
+ memoryStore.select(ɵselectMemoriesRealtimeStatus).subscribe((v) => {
3653
+ this._memoriesRealtimeStatus = v;
3654
+ this.requestUpdate();
3655
+ })
3656
+ ];
3657
+ this._memoryUnsub = () => memSubs.forEach((s) => s.unsubscribe());
3658
+ this.requestUpdate();
3244
3659
  }
3245
3660
  detachFromCore() {
3246
3661
  if (this.coreUnsubscribe) {
3247
3662
  this.coreUnsubscribe();
3248
3663
  this.coreUnsubscribe = null;
3249
3664
  }
3665
+ this._memoryUnsub?.();
3666
+ this._memoryUnsub = null;
3667
+ this._memories = [];
3668
+ this._memoriesLoading = false;
3669
+ this._memoriesError = null;
3670
+ this._memoriesAvailable = true;
3671
+ this._memoriesRealtimeStatus = "connecting";
3672
+ this._memorySubscribed = false;
3673
+ this._memoryStoreUnsupported = false;
3250
3674
  this.coreSubscriber = null;
3251
3675
  this.runtimeStatus = null;
3252
3676
  this.lastCoreError = null;
@@ -4469,6 +4893,7 @@ ${argsString}</pre
4469
4893
  y: EDGE_MARGIN
4470
4894
  };
4471
4895
  this.hydrateStateFromStorage();
4896
+ if (this.selectedMenu === "memories") this.ensureMemorySubscription();
4472
4897
  if (this.isOpen && this.dockMode !== "floating") this.applyDockStyles(true);
4473
4898
  this.applyAnchorPosition("button");
4474
4899
  if (this.dockMode === "floating") if (this.hasCustomPosition.window) this.applyAnchorPosition("window");
@@ -5164,6 +5589,7 @@ ${argsString}</pre
5164
5589
  if (this.selectedMenu === "frontend-tools") return this.renderToolsView();
5165
5590
  if (this.selectedMenu === "agent-context") return this.renderContextView();
5166
5591
  if (this.selectedMenu === "threads") return this.renderThreadsView();
5592
+ if (this.selectedMenu === "memories") return this.renderMemoriesView();
5167
5593
  if (this.selectedMenu === "settings") return this.renderSettingsPanel();
5168
5594
  return nothing;
5169
5595
  }
@@ -5515,6 +5941,310 @@ ${argsString}</pre
5515
5941
  </div>
5516
5942
  </div>
5517
5943
  </div>
5944
+ `;
5945
+ }
5946
+ /**
5947
+ * Renders the realtime-connection indicator in the memory-store header.
5948
+ * Only `"connected"` shows the live (green-dot) state; `"connecting"` shows a
5949
+ * muted amber "reconnecting" and `"unavailable"` a muted grey "offline", so
5950
+ * the indicator never claims "live" over a frozen snapshot once the realtime
5951
+ * socket has permanently given up.
5952
+ */
5953
+ renderMemoryRealtimeIndicator() {
5954
+ const status = this._memoriesRealtimeStatus;
5955
+ const connected = status === "connected";
5956
+ return html`
5957
+ <span
5958
+ style="
5959
+ display: inline-flex;
5960
+ align-items: center;
5961
+ gap: 4px;
5962
+ font-size: 10px;
5963
+ font-weight: 500;
5964
+ color: ${connected ? "#57575b" : "#838389"};
5965
+ "
5966
+ >
5967
+ <span
5968
+ style="
5969
+ display: inline-block;
5970
+ width: 6px;
5971
+ height: 6px;
5972
+ border-radius: 50%;
5973
+ background: ${connected ? "#22c55e" : status === "connecting" ? "#f59e0b" : "#9ca3af"};
5974
+ "
5975
+ ></span>
5976
+ ${status === "connected" ? "live" : status === "connecting" ? "reconnecting" : "offline"}
5977
+ </span>
5978
+ `;
5979
+ }
5980
+ renderMemoriesView() {
5981
+ if (!this.core?.intelligence || !this._memoriesAvailable) return html`
5982
+ <div
5983
+ style="
5984
+ position: relative;
5985
+ height: 100%;
5986
+ display: flex;
5987
+ align-items: center;
5988
+ justify-content: center;
5989
+ padding: 32px;
5990
+ overflow: hidden;
5991
+ background: #ffffff;
5992
+ "
5993
+ >
5994
+ ${this.renderThreadsLockedBackgroundMockup()}
5995
+ <div
5996
+ aria-hidden="true"
5997
+ style="
5998
+ position: absolute;
5999
+ inset: 0;
6000
+ pointer-events: none;
6001
+ background:
6002
+ radial-gradient(circle at center, rgba(255,255,255,0.9) 0, rgba(255,255,255,0.78) 24%, rgba(255,255,255,0.34) 48%, rgba(255,255,255,0.56) 100%);
6003
+ "
6004
+ ></div>
6005
+ <div
6006
+ style="
6007
+ position: relative;
6008
+ z-index: 1;
6009
+ max-width: 440px;
6010
+ text-align: center;
6011
+ color: #57575b;
6012
+ "
6013
+ >
6014
+ <div
6015
+ aria-hidden="true"
6016
+ style="
6017
+ margin: 0 auto 18px;
6018
+ display: flex;
6019
+ justify-content: center;
6020
+ "
6021
+ >
6022
+ <div
6023
+ style="
6024
+ display: flex;
6025
+ height: 44px;
6026
+ width: 44px;
6027
+ align-items: center;
6028
+ justify-content: center;
6029
+ border: 1px solid #dfd6fb;
6030
+ border-radius: 8px;
6031
+ background: #eee6fe;
6032
+ color: #57575b;
6033
+ box-shadow: 0 8px 18px rgba(87, 87, 91, 0.14);
6034
+ "
6035
+ >
6036
+ ${this.renderIcon("Lock")}
6037
+ </div>
6038
+ </div>
6039
+ <h2
6040
+ style="
6041
+ margin: 0 0 8px;
6042
+ font-size: 16px;
6043
+ line-height: 1.35;
6044
+ font-weight: 600;
6045
+ color: #010507;
6046
+ "
6047
+ >
6048
+ Long-term memory
6049
+ </h2>
6050
+ <p
6051
+ style="
6052
+ margin: 0 auto 18px;
6053
+ max-width: 380px;
6054
+ font-size: 13px;
6055
+ line-height: 1.55;
6056
+ color: #57575b;
6057
+ "
6058
+ >
6059
+ ${this._memoryStoreUnsupported ? "Long-term memory isn't available in this version of the @copilotkit SDK. Upgrade @copilotkit/core (and @copilotkit/react) to a version that supports memory." : "Long-term memory isn't enabled on this deployment."}
6060
+ </p>
6061
+ <div
6062
+ style="
6063
+ display: flex;
6064
+ flex-wrap: wrap;
6065
+ justify-content: center;
6066
+ gap: 8px;
6067
+ "
6068
+ >
6069
+ <a
6070
+ href=${this.getTalkToEngineerUrl()}
6071
+ target="_blank"
6072
+ rel="noopener"
6073
+ style="
6074
+ display: inline-flex;
6075
+ min-height: 34px;
6076
+ align-items: center;
6077
+ justify-content: center;
6078
+ gap: 6px;
6079
+ border-radius: 6px;
6080
+ background: #010507;
6081
+ padding: 8px 12px;
6082
+ font-size: 12px;
6083
+ font-weight: 600;
6084
+ color: #ffffff;
6085
+ text-decoration: none;
6086
+ "
6087
+ @click=${this.handleThreadsTalkToEngineerClick}
6088
+ >
6089
+ Talk to an Engineer
6090
+ </a>
6091
+ <a
6092
+ href=${this.getIntelligenceSignupUrl()}
6093
+ target="_blank"
6094
+ rel="noopener"
6095
+ style="
6096
+ display: inline-flex;
6097
+ min-height: 34px;
6098
+ align-items: center;
6099
+ justify-content: center;
6100
+ gap: 6px;
6101
+ border-radius: 6px;
6102
+ border: 1px solid #dbdbe5;
6103
+ background: #ffffff;
6104
+ padding: 8px 12px;
6105
+ font-size: 12px;
6106
+ font-weight: 600;
6107
+ color: #57575b;
6108
+ text-decoration: none;
6109
+ "
6110
+ @click=${this.handleThreadsIntelligenceSignupClick}
6111
+ >
6112
+ Sign up for Intelligence
6113
+ </a>
6114
+ </div>
6115
+ </div>
6116
+ </div>
6117
+ `;
6118
+ if (this._memoriesError && this._memories.length === 0) return html`
6119
+ <div
6120
+ style="
6121
+ display: flex;
6122
+ height: 100%;
6123
+ flex-direction: column;
6124
+ align-items: center;
6125
+ justify-content: center;
6126
+ gap: 8px;
6127
+ color: #838389;
6128
+ "
6129
+ >
6130
+ <svg
6131
+ width="24"
6132
+ height="24"
6133
+ viewBox="0 0 24 24"
6134
+ fill="none"
6135
+ stroke="#c0333a"
6136
+ stroke-width="1.5"
6137
+ stroke-linecap="round"
6138
+ stroke-linejoin="round"
6139
+ >
6140
+ <circle cx="12" cy="12" r="10" />
6141
+ <line x1="12" y1="8" x2="12" y2="12" />
6142
+ <line x1="12" y1="16" x2="12.01" y2="16" />
6143
+ </svg>
6144
+ <span style="font-size: 13px; color: #c0333a;">
6145
+ Failed to load memories
6146
+ </span>
6147
+ <span
6148
+ style="
6149
+ max-width: 320px;
6150
+ text-align: center;
6151
+ font-size: 11px;
6152
+ line-height: 1.5;
6153
+ color: #c0333a;
6154
+ "
6155
+ >
6156
+ ${this._memoriesError.message}
6157
+ </span>
6158
+ </div>
6159
+ `;
6160
+ if (this._memoriesLoading && this._memories.length === 0) return html`
6161
+ <div
6162
+ style="
6163
+ display: flex;
6164
+ height: 100%;
6165
+ flex-direction: column;
6166
+ align-items: center;
6167
+ justify-content: center;
6168
+ gap: 8px;
6169
+ color: #838389;
6170
+ "
6171
+ >
6172
+ <svg
6173
+ width="24"
6174
+ height="24"
6175
+ viewBox="0 0 24 24"
6176
+ fill="none"
6177
+ stroke="#c0c0c8"
6178
+ stroke-width="1.5"
6179
+ stroke-linecap="round"
6180
+ stroke-linejoin="round"
6181
+ >
6182
+ <path d="M21 12a9 9 0 1 1-6.219-8.56" />
6183
+ </svg>
6184
+ <span style="font-size: 13px">Loading memories…</span>
6185
+ </div>
6186
+ `;
6187
+ return html`
6188
+ <div style="display:flex;height:100%;overflow:hidden;flex-direction:column;">
6189
+ <div class="cpk-section-header" style="display:flex;align-items:center;justify-content:space-between;">
6190
+ <h4>Learning</h4>
6191
+ <div style="display:flex;align-items:center;gap:6px;">
6192
+ ${this.renderMemoryRealtimeIndicator()}
6193
+ <span
6194
+ style="
6195
+ font-size: 11px;
6196
+ font-weight: 500;
6197
+ color: #57575b;
6198
+ background: rgba(0,0,0,0.07);
6199
+ border-radius: 9999px;
6200
+ padding: 1px 7px;
6201
+ "
6202
+ >
6203
+ ${this._memories.length}
6204
+ </span>
6205
+ </div>
6206
+ </div>
6207
+ ${this._memoriesError ? html`
6208
+ <div
6209
+ role="alert"
6210
+ style="
6211
+ display: flex;
6212
+ align-items: flex-start;
6213
+ gap: 8px;
6214
+ flex-shrink: 0;
6215
+ border-bottom: 1px solid #f1c7c9;
6216
+ background: #fdf3f3;
6217
+ padding: 8px 12px;
6218
+ color: #c0333a;
6219
+ font-size: 12px;
6220
+ line-height: 1.45;
6221
+ "
6222
+ >
6223
+ <svg
6224
+ width="16"
6225
+ height="16"
6226
+ viewBox="0 0 24 24"
6227
+ fill="none"
6228
+ stroke="#c0333a"
6229
+ stroke-width="1.5"
6230
+ stroke-linecap="round"
6231
+ stroke-linejoin="round"
6232
+ style="flex-shrink:0;margin-top:1px;"
6233
+ >
6234
+ <circle cx="12" cy="12" r="10" />
6235
+ <line x1="12" y1="8" x2="12" y2="12" />
6236
+ <line x1="12" y1="16" x2="12.01" y2="16" />
6237
+ </svg>
6238
+ <span>Action failed: ${this._memoriesError.message}</span>
6239
+ </div>
6240
+ ` : nothing}
6241
+ <div style="flex:1;min-height:0;overflow:hidden;">
6242
+ <cpk-memory-list
6243
+ style="height:100%;"
6244
+ .memories=${this._memories}
6245
+ ></cpk-memory-list>
6246
+ </div>
6247
+ </div>
5518
6248
  `;
5519
6249
  }
5520
6250
  renderThreadsView() {
@@ -6134,6 +6864,10 @@ ${prettyEvent}</pre
6134
6864
  if (previousMenu !== "threads" && !this.core?.telemetryDisabled) trackThreadsTabClicked(this.getThreadsTelemetryProps());
6135
6865
  this.autoSelectLatestThread();
6136
6866
  }
6867
+ if (key === "memories") {
6868
+ this.ensureMemorySubscription();
6869
+ if (previousMenu !== "memories" && !this.core?.telemetryDisabled) trackMemoriesTabClicked(this.getMemoriesTelemetryProps());
6870
+ }
6137
6871
  if (key === "ag-ui-events" || key === "agents") requestAnimationFrame(() => {
6138
6872
  const scroller = this.shadowRoot?.getElementById("cpk-main-scroll");
6139
6873
  if (scroller) scroller.scrollTop = 0;