@copilotkit/web-inspector 1.62.1 → 1.62.2-canary.1783457132

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";
@@ -427,6 +427,8 @@ var CpkThreadInspector = class CpkThreadInspector extends LitElement {
427
427
  this._stateError = null;
428
428
  this._expandedTools = /* @__PURE__ */ new Set();
429
429
  this._expandedMessages = /* @__PURE__ */ new Set();
430
+ this._expandedTimelineDetails = /* @__PURE__ */ new Set();
431
+ this._expandedRawEvents = /* @__PURE__ */ new Set();
430
432
  this._showDetailPanel = false;
431
433
  this._detailPanelWidth = 250;
432
434
  this._eventsNotAvailable = false;
@@ -492,6 +494,8 @@ var CpkThreadInspector = class CpkThreadInspector extends LitElement {
492
494
  _stateError: { state: true },
493
495
  _expandedTools: { state: true },
494
496
  _expandedMessages: { state: true },
497
+ _expandedTimelineDetails: { state: true },
498
+ _expandedRawEvents: { state: true },
495
499
  _showDetailPanel: { state: true },
496
500
  _detailPanelWidth: { state: true },
497
501
  _eventsNotAvailable: { state: true },
@@ -706,6 +710,7 @@ var CpkThreadInspector = class CpkThreadInspector extends LitElement {
706
710
 
707
711
  .cpk-td__metadata-strip {
708
712
  display: flex;
713
+ align-items: center;
709
714
  gap: 6px;
710
715
  flex-wrap: wrap;
711
716
  padding: 10px 16px;
@@ -714,6 +719,14 @@ var CpkThreadInspector = class CpkThreadInspector extends LitElement {
714
719
  flex-shrink: 0;
715
720
  }
716
721
 
722
+ .cpk-td__metadata-pills {
723
+ display: flex;
724
+ gap: 6px;
725
+ flex: 1;
726
+ flex-wrap: wrap;
727
+ min-width: 0;
728
+ }
729
+
717
730
  .cpk-td__metadata-pill {
718
731
  display: inline-flex;
719
732
  align-items: center;
@@ -1008,13 +1021,44 @@ var CpkThreadInspector = class CpkThreadInspector extends LitElement {
1008
1021
  }
1009
1022
 
1010
1023
  .cpk-td__timeline-body {
1011
- padding: 9px 10px;
1024
+ margin: 0;
1025
+ padding: 0 10px 9px;
1012
1026
  font-size: 12px;
1013
1027
  line-height: 1.55;
1014
1028
  color: #57575b;
1015
1029
  white-space: pre-wrap;
1016
1030
  word-break: break-word;
1017
- border-top: 1px solid #e9e9ef;
1031
+ }
1032
+
1033
+ .cpk-td__timeline-toolbar {
1034
+ display: flex;
1035
+ gap: 6px;
1036
+ margin-left: auto;
1037
+ }
1038
+
1039
+ .cpk-td__timeline-bulk-toggle {
1040
+ margin: 0;
1041
+ padding: 4px 8px;
1042
+ border: 1px solid #dcdce8;
1043
+ border-radius: 6px;
1044
+ background: #ffffff;
1045
+ color: #36363a;
1046
+ cursor: pointer;
1047
+ font-family: "Inter", sans-serif;
1048
+ font-size: 11px;
1049
+ font-weight: 600;
1050
+ line-height: 1.2;
1051
+ }
1052
+
1053
+ .cpk-td__timeline-bulk-toggle:hover {
1054
+ border-color: rgba(85, 88, 178, 0.38);
1055
+ background: #f7f7ff;
1056
+ color: #010507;
1057
+ }
1058
+
1059
+ .cpk-td__timeline-bulk-toggle:disabled {
1060
+ cursor: not-allowed;
1061
+ opacity: 0.45;
1018
1062
  }
1019
1063
 
1020
1064
  .cpk-td__source-link {
@@ -1035,6 +1079,34 @@ var CpkThreadInspector = class CpkThreadInspector extends LitElement {
1035
1079
  color: #010507;
1036
1080
  }
1037
1081
 
1082
+ .cpk-td__timeline-details-toggle {
1083
+ margin: 0;
1084
+ padding: 5px 10px;
1085
+ border: none;
1086
+ background: #ffffff;
1087
+ color: #5558b2;
1088
+ cursor: pointer;
1089
+ display: inline-flex;
1090
+ align-items: center;
1091
+ gap: 5px;
1092
+ font-family: "Inter", sans-serif;
1093
+ font-size: 12px;
1094
+ font-weight: 600;
1095
+ line-height: 1.2;
1096
+ width: 100%;
1097
+ }
1098
+
1099
+ .cpk-td__timeline-details-toggle:hover {
1100
+ background: #f7f7ff;
1101
+ color: #010507;
1102
+ }
1103
+
1104
+ .cpk-td__timeline-details-toggle svg {
1105
+ width: 12px;
1106
+ height: 12px;
1107
+ stroke-width: 2;
1108
+ }
1109
+
1038
1110
  /* ── Generative UI ──────────────────────────────────────────────── */
1039
1111
  @keyframes cpk-genui-enter {
1040
1112
  from {
@@ -1292,6 +1364,8 @@ var CpkThreadInspector = class CpkThreadInspector extends LitElement {
1292
1364
  this._liveEventsWithSourceIndexCache = null;
1293
1365
  this._expandedTools = /* @__PURE__ */ new Set();
1294
1366
  this._expandedMessages = /* @__PURE__ */ new Set();
1367
+ this._expandedTimelineDetails = /* @__PURE__ */ new Set();
1368
+ this._expandedRawEvents = /* @__PURE__ */ new Set();
1295
1369
  this._metadataAbort?.abort();
1296
1370
  this._metadataAbort = null;
1297
1371
  this._messagesAbort?.abort();
@@ -1820,6 +1894,37 @@ var CpkThreadInspector = class CpkThreadInspector extends LitElement {
1820
1894
  else next.add(id);
1821
1895
  this._expandedMessages = next;
1822
1896
  }
1897
+ toggleTimelineDetails(id) {
1898
+ const next = new Set(this._expandedTimelineDetails);
1899
+ if (next.has(id)) next.delete(id);
1900
+ else next.add(id);
1901
+ this._expandedTimelineDetails = next;
1902
+ }
1903
+ expandTimelineDetails(ids) {
1904
+ this._expandedTimelineDetails = new Set([...this._expandedTimelineDetails, ...ids]);
1905
+ }
1906
+ collapseTimelineDetails(ids) {
1907
+ const next = new Set(this._expandedTimelineDetails);
1908
+ for (const id of ids) next.delete(id);
1909
+ this._expandedTimelineDetails = next;
1910
+ }
1911
+ toggleRawEventDetails(id) {
1912
+ const next = new Set(this._expandedRawEvents);
1913
+ if (next.has(id)) next.delete(id);
1914
+ else next.add(id);
1915
+ this._expandedRawEvents = next;
1916
+ }
1917
+ expandRawEventDetails(ids) {
1918
+ this._expandedRawEvents = new Set([...this._expandedRawEvents, ...ids]);
1919
+ }
1920
+ collapseRawEventDetails(ids) {
1921
+ const next = new Set(this._expandedRawEvents);
1922
+ for (const id of ids) next.delete(id);
1923
+ this._expandedRawEvents = next;
1924
+ }
1925
+ rawEventId(event) {
1926
+ return `raw-event-${event.sourceIndex ?? event.timestamp ?? event.type}`;
1927
+ }
1823
1928
  get activeEvents() {
1824
1929
  if (this._eventsNotAvailable) return [];
1825
1930
  const events = this._fetchedEvents ?? this.agentEventsInput ?? [];
@@ -1943,19 +2048,70 @@ var CpkThreadInspector = class CpkThreadInspector extends LitElement {
1943
2048
  value: metadata?.status
1944
2049
  }
1945
2050
  ].filter((pill) => pill.value != null && pill.value !== "");
1946
- if (pills.length === 0) return nothing;
2051
+ const bulkControls = this.renderActiveBulkControls();
2052
+ if (pills.length === 0 && bulkControls === nothing) return nothing;
1947
2053
  return html`
1948
2054
  <div class="cpk-td__metadata-strip" aria-label="Thread metadata">
1949
- ${pills.map((pill) => html`
1950
- <span class="cpk-td__metadata-pill" title=${pill.value ?? ""}>
1951
- <span class="cpk-td__metadata-label">${pill.label}</span>
1952
- <span class="cpk-td__metadata-value"
1953
- >${this.shortId(pill.value)}</span
1954
- >
1955
- </span>
1956
- `)}
2055
+ <div class="cpk-td__metadata-pills">
2056
+ ${pills.map((pill) => html`
2057
+ <span class="cpk-td__metadata-pill" title=${pill.value ?? ""}>
2058
+ <span class="cpk-td__metadata-label">${pill.label}</span>
2059
+ <span class="cpk-td__metadata-value"
2060
+ >${this.shortId(pill.value)}</span
2061
+ >
2062
+ </span>
2063
+ `)}
2064
+ </div>
2065
+ ${bulkControls}
1957
2066
  </div>
1958
2067
  `;
2068
+ }
2069
+ renderActiveBulkControls() {
2070
+ if (this._eventsNotAvailable) return nothing;
2071
+ if (this._tab === "raw-events") return this.renderRawEventBulkControls();
2072
+ if (this._tab !== "timeline") return nothing;
2073
+ const detailIds = this.timelineItemsForEvents(this.activeEvents).filter((item) => item.details).map((item) => item.id);
2074
+ if (detailIds.length <= 1) return nothing;
2075
+ return html`<div class="cpk-td__timeline-toolbar">
2076
+ <button
2077
+ type="button"
2078
+ class="cpk-td__timeline-bulk-toggle"
2079
+ ?disabled=${detailIds.every((id) => this._expandedTimelineDetails.has(id))}
2080
+ @click=${() => this.expandTimelineDetails(detailIds)}
2081
+ >
2082
+ Expand all
2083
+ </button>
2084
+ <button
2085
+ type="button"
2086
+ class="cpk-td__timeline-bulk-toggle"
2087
+ ?disabled=${detailIds.every((id) => !this._expandedTimelineDetails.has(id))}
2088
+ @click=${() => this.collapseTimelineDetails(detailIds)}
2089
+ >
2090
+ Collapse all
2091
+ </button>
2092
+ </div>`;
2093
+ }
2094
+ renderRawEventBulkControls() {
2095
+ const eventIds = this.activeEvents.map((event) => this.rawEventId(event));
2096
+ if (eventIds.length <= 1) return nothing;
2097
+ return html`<div class="cpk-td__timeline-toolbar">
2098
+ <button
2099
+ type="button"
2100
+ class="cpk-td__timeline-bulk-toggle"
2101
+ ?disabled=${eventIds.every((id) => this._expandedRawEvents.has(id))}
2102
+ @click=${() => this.expandRawEventDetails(eventIds)}
2103
+ >
2104
+ Expand all
2105
+ </button>
2106
+ <button
2107
+ type="button"
2108
+ class="cpk-td__timeline-bulk-toggle"
2109
+ ?disabled=${eventIds.every((id) => !this._expandedRawEvents.has(id))}
2110
+ @click=${() => this.collapseRawEventDetails(eventIds)}
2111
+ >
2112
+ Collapse all
2113
+ </button>
2114
+ </div>`;
1959
2115
  }
1960
2116
  revealSourceEvent(sourceIndex) {
1961
2117
  this._activatedTabs = new Set([...this._activatedTabs, "raw-events"]);
@@ -1986,7 +2142,7 @@ var CpkThreadInspector = class CpkThreadInspector extends LitElement {
1986
2142
  `;
1987
2143
  }
1988
2144
  const events = this.activeEvents;
1989
- const cachedTimeline = this.getCachedPanelTpl("timeline", [events]);
2145
+ const cachedTimeline = this.getCachedPanelTpl("timeline", [events, this._expandedTimelineDetails]);
1990
2146
  if (cachedTimeline) return cachedTimeline;
1991
2147
  const timelineItems = this.timelineItemsForEvents(events);
1992
2148
  if (timelineItems.length === 0) {
@@ -2002,14 +2158,14 @@ var CpkThreadInspector = class CpkThreadInspector extends LitElement {
2002
2158
  </div>
2003
2159
  `;
2004
2160
  }
2005
- return this.cachedPanelTpl("timeline", [events], () => {
2006
- return html`${timelineItems.map((item) => this.renderTimelineItem(item))}`;
2007
- });
2161
+ return this.cachedPanelTpl("timeline", [events, this._expandedTimelineDetails], () => html`${timelineItems.map((item) => this.renderTimelineItem(item))}`);
2008
2162
  }
2009
2163
  renderTimelineItem(item) {
2164
+ const isWarning = item.kind === "warning";
2165
+ const detailsExpanded = this._expandedTimelineDetails.has(item.id);
2010
2166
  return html`
2011
2167
  <div
2012
- class="cpk-td__timeline-item ${item.kind === "warning" ? "cpk-td__timeline-item--warning" : ""}"
2168
+ class="cpk-td__timeline-item ${isWarning ? "cpk-td__timeline-item--warning" : ""}"
2013
2169
  >
2014
2170
  <div class="cpk-td__timeline-header">
2015
2171
  <span class="cpk-td__timeline-kind"
@@ -2027,9 +2183,39 @@ var CpkThreadInspector = class CpkThreadInspector extends LitElement {
2027
2183
  >${formatTimestamp(item.timestamp)}</span
2028
2184
  >
2029
2185
  </div>
2030
- ${item.body ? html`<div class="cpk-td__timeline-body">${item.body}</div>` : item.details ? html`<pre class="cpk-td__timeline-body">
2031
- ${unsafeHTML(highlightedJson(item.details))}</pre
2032
- >` : nothing}
2186
+ ${item.details ? html`<button
2187
+ type="button"
2188
+ class="cpk-td__timeline-details-toggle"
2189
+ aria-expanded=${detailsExpanded ? "true" : "false"}
2190
+ @click=${() => this.toggleTimelineDetails(item.id)}
2191
+ >
2192
+ ${detailsExpanded ? html`
2193
+ <svg
2194
+ aria-hidden="true"
2195
+ viewBox="0 0 24 24"
2196
+ fill="none"
2197
+ stroke="currentColor"
2198
+ stroke-linecap="round"
2199
+ stroke-linejoin="round"
2200
+ >
2201
+ <path d="m6 9 6 6 6-6" />
2202
+ </svg>
2203
+ ` : html`
2204
+ <svg
2205
+ aria-hidden="true"
2206
+ viewBox="0 0 24 24"
2207
+ fill="none"
2208
+ stroke="currentColor"
2209
+ stroke-linecap="round"
2210
+ stroke-linejoin="round"
2211
+ >
2212
+ <path d="m9 18 6-6-6-6" />
2213
+ </svg>
2214
+ `}
2215
+ <span>${detailsExpanded ? "Hide details" : "Show details"}</span>
2216
+ </button>` : nothing}
2217
+ ${item.body ? html`<div class="cpk-td__timeline-body">${item.body}</div>` : nothing}
2218
+ ${item.details && detailsExpanded ? html`<pre class="cpk-td__timeline-body">${unsafeHTML(highlightedJson(item.details))}</pre>` : nothing}
2033
2219
  </div>
2034
2220
  `;
2035
2221
  }
@@ -2286,9 +2472,11 @@ ${unsafeHTML(highlightedJson(stateValue))}</pre
2286
2472
  >
2287
2473
  </div>
2288
2474
  `;
2289
- return this.cachedPanelTpl("raw-events", [events], () => {
2475
+ return this.cachedPanelTpl("raw-events", [events, this._expandedRawEvents], () => {
2290
2476
  return html`${events.map((event) => {
2291
2477
  const { bg, fg } = eventColors(event.type);
2478
+ const eventId = this.rawEventId(event);
2479
+ const detailsExpanded = this._expandedRawEvents.has(eventId);
2292
2480
  return html`
2293
2481
  <div class="cpk-td__event" data-source-index=${event.sourceIndex}>
2294
2482
  <div class="cpk-td__event-header" style="background:${bg}">
@@ -2299,9 +2487,38 @@ ${unsafeHTML(highlightedJson(stateValue))}</pre
2299
2487
  >${formatTimestamp(event.timestamp)}</span
2300
2488
  >
2301
2489
  </div>
2302
- <pre class="cpk-td__event-payload">
2303
- ${unsafeHTML(highlightedJson(event.rawEvent ?? event))}</pre
2490
+ <button
2491
+ type="button"
2492
+ class="cpk-td__timeline-details-toggle"
2493
+ aria-expanded=${detailsExpanded ? "true" : "false"}
2494
+ @click=${() => this.toggleRawEventDetails(eventId)}
2304
2495
  >
2496
+ ${detailsExpanded ? html`
2497
+ <svg
2498
+ aria-hidden="true"
2499
+ viewBox="0 0 24 24"
2500
+ fill="none"
2501
+ stroke="currentColor"
2502
+ stroke-linecap="round"
2503
+ stroke-linejoin="round"
2504
+ >
2505
+ <path d="m6 9 6 6 6-6" />
2506
+ </svg>
2507
+ ` : html`
2508
+ <svg
2509
+ aria-hidden="true"
2510
+ viewBox="0 0 24 24"
2511
+ fill="none"
2512
+ stroke="currentColor"
2513
+ stroke-linecap="round"
2514
+ stroke-linejoin="round"
2515
+ >
2516
+ <path d="m9 18 6-6-6-6" />
2517
+ </svg>
2518
+ `}
2519
+ <span>${detailsExpanded ? "Hide details" : "Show details"}</span>
2520
+ </button>
2521
+ ${detailsExpanded ? html`<pre class="cpk-td__event-payload">${unsafeHTML(highlightedJson(event.rawEvent ?? event))}</pre>` : nothing}
2305
2522
  </div>
2306
2523
  `;
2307
2524
  })}`;
@@ -2410,16 +2627,365 @@ ${unsafeHTML(highlightedJson(event.rawEvent ?? event))}</pre
2410
2627
  `;
2411
2628
  }
2412
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
+ };
2413
2970
  var ɵCpkThreadDetails = class extends CpkThreadInspector {};
2414
2971
  if (!customElements.get("cpk-thread-list")) customElements.define("cpk-thread-list", CpkThreadList);
2415
2972
  if (!customElements.get(THREAD_INSPECTOR_TAG)) customElements.define(THREAD_INSPECTOR_TAG, CpkThreadInspector);
2416
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);
2417
2975
  var WebInspectorElement = class extends LitElement {
2418
- constructor(..._args3) {
2419
- super(..._args3);
2976
+ constructor(..._args4) {
2977
+ super(..._args4);
2420
2978
  this._core = null;
2421
2979
  this.coreSubscriber = null;
2422
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;
2423
2989
  this.runtimeStatus = null;
2424
2990
  this.coreProperties = {};
2425
2991
  this.lastCoreError = null;
@@ -2835,6 +3401,11 @@ var WebInspectorElement = class extends LitElement {
2835
3401
  key: "threads",
2836
3402
  label: "Threads",
2837
3403
  icon: "MessageSquare"
3404
+ },
3405
+ {
3406
+ key: "memories",
3407
+ label: "Learning",
3408
+ icon: "Brain"
2838
3409
  }
2839
3410
  ];
2840
3411
  }
@@ -2860,6 +3431,13 @@ var WebInspectorElement = class extends LitElement {
2860
3431
  ...extra
2861
3432
  };
2862
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
+ }
2863
3441
  getIntelligenceSignupUrl() {
2864
3442
  return this.appendRefParam(INTELLIGENCE_SIGNUP_URL, "cpk-inspector");
2865
3443
  }
@@ -3024,12 +3602,75 @@ var WebInspectorElement = class extends LitElement {
3024
3602
  const threadStores = typeof core.getThreadStores === "function" ? core.getThreadStores() : {};
3025
3603
  for (const [agentId, store] of Object.entries(threadStores)) this.subscribeToThreadStore(agentId, store);
3026
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();
3027
3659
  }
3028
3660
  detachFromCore() {
3029
3661
  if (this.coreUnsubscribe) {
3030
3662
  this.coreUnsubscribe();
3031
3663
  this.coreUnsubscribe = null;
3032
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;
3033
3674
  this.coreSubscriber = null;
3034
3675
  this.runtimeStatus = null;
3035
3676
  this.lastCoreError = null;
@@ -4252,6 +4893,7 @@ ${argsString}</pre
4252
4893
  y: EDGE_MARGIN
4253
4894
  };
4254
4895
  this.hydrateStateFromStorage();
4896
+ if (this.selectedMenu === "memories") this.ensureMemorySubscription();
4255
4897
  if (this.isOpen && this.dockMode !== "floating") this.applyDockStyles(true);
4256
4898
  this.applyAnchorPosition("button");
4257
4899
  if (this.dockMode === "floating") if (this.hasCustomPosition.window) this.applyAnchorPosition("window");
@@ -4947,6 +5589,7 @@ ${argsString}</pre
4947
5589
  if (this.selectedMenu === "frontend-tools") return this.renderToolsView();
4948
5590
  if (this.selectedMenu === "agent-context") return this.renderContextView();
4949
5591
  if (this.selectedMenu === "threads") return this.renderThreadsView();
5592
+ if (this.selectedMenu === "memories") return this.renderMemoriesView();
4950
5593
  if (this.selectedMenu === "settings") return this.renderSettingsPanel();
4951
5594
  return nothing;
4952
5595
  }
@@ -5298,6 +5941,310 @@ ${argsString}</pre
5298
5941
  </div>
5299
5942
  </div>
5300
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>
5301
6248
  `;
5302
6249
  }
5303
6250
  renderThreadsView() {
@@ -5917,6 +6864,10 @@ ${prettyEvent}</pre
5917
6864
  if (previousMenu !== "threads" && !this.core?.telemetryDisabled) trackThreadsTabClicked(this.getThreadsTelemetryProps());
5918
6865
  this.autoSelectLatestThread();
5919
6866
  }
6867
+ if (key === "memories") {
6868
+ this.ensureMemorySubscription();
6869
+ if (previousMenu !== "memories" && !this.core?.telemetryDisabled) trackMemoriesTabClicked(this.getMemoriesTelemetryProps());
6870
+ }
5920
6871
  if (key === "ag-ui-events" || key === "agents") requestAnimationFrame(() => {
5921
6872
  const scroller = this.shadowRoot?.getElementById("cpk-main-scroll");
5922
6873
  if (scroller) scroller.scrollTop = 0;