@dipertq/dsh-openviking-status 0.1.7 → 0.1.8

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/lib/client.js CHANGED
@@ -1,5 +1,12 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
1
8
  // src/client/OpenVikingStatusChip.tsx
2
- import {
9
+ import React2, {
3
10
  useState as useState2,
4
11
  useEffect as useEffect2,
5
12
  useCallback as useCallback2,
@@ -89,6 +96,8 @@ var OpenVikingClient = class {
89
96
  } else if (raw.startsWith("dsh-")) {
90
97
  const suffix = raw.slice("dsh-".length);
91
98
  candidates.push(raw, `dsh-session-${suffix}`);
99
+ } else if (raw.startsWith("session-")) {
100
+ candidates.push(`dsh-${raw}`, raw);
92
101
  } else {
93
102
  candidates.push(`dsh-session-${raw}`, `dsh-${raw}`, raw);
94
103
  }
@@ -124,12 +133,16 @@ var OpenVikingClient = class {
124
133
  }
125
134
  }
126
135
  /**
127
- * Получение метаданных сессии по идентификатору с автоматическим разрешением префикса.
128
- * При сетевых сбоях или ошибках авторизации возвращает null, не выбрасывая исключений.
136
+ * Чтение метаданных сессии с явной причиной неудачи.
137
+ *
138
+ * Демон может работать с `auth_mode: api_key`: тогда `/health` остаётся
139
+ * открытым, а сессия отвечает 401. Схлопывать это в «нет данных» нельзя —
140
+ * иначе интерфейс покажет живой индикатор рядом с нулями и умолчит о том,
141
+ * что счётчики просто недоступны.
129
142
  */
130
- async fetchSession(sessionId) {
143
+ async readSession(sessionId) {
131
144
  if (!sessionId || !sessionId.trim()) {
132
- return null;
145
+ return { status: "missing" };
133
146
  }
134
147
  const candidates = this.getCandidateSessionIds(sessionId);
135
148
  for (const candidateId of candidates) {
@@ -144,30 +157,48 @@ var OpenVikingClient = class {
144
157
  if (res.status === 404) {
145
158
  continue;
146
159
  }
160
+ if (res.status === 401 || res.status === 403) {
161
+ return { status: "unauthorized" };
162
+ }
147
163
  if (!res.ok) {
148
- return null;
164
+ return { status: "error", detail: `HTTP ${res.status}` };
149
165
  }
150
166
  const data = await res.json();
151
167
  const raw = data?.result ?? data?.data ?? data;
152
168
  if (!raw || typeof raw !== "object") {
153
- return null;
169
+ return { status: "error", detail: "malformed response body" };
154
170
  }
155
171
  this.resolvedSessionIds.set(sessionId.trim(), candidateId);
156
172
  return {
157
- session_id: typeof raw.session_id === "string" ? raw.session_id : candidateId,
158
- peer_id: typeof raw.peer_id === "string" ? raw.peer_id : void 0,
159
- pending_tokens: typeof raw.pending_tokens === "number" ? raw.pending_tokens : 0,
160
- message_count: typeof raw.message_count === "number" ? raw.message_count : void 0,
161
- commit_count: typeof raw.commit_count === "number" ? raw.commit_count : void 0,
162
- last_commit_at: typeof raw.last_commit_at === "string" ? raw.last_commit_at : typeof raw.last_commit === "string" ? raw.last_commit : void 0,
163
- created_at: typeof raw.created_at === "string" ? raw.created_at : void 0,
164
- updated_at: typeof raw.updated_at === "string" ? raw.updated_at : void 0
173
+ status: "ok",
174
+ session: {
175
+ session_id: typeof raw.session_id === "string" ? raw.session_id : candidateId,
176
+ peer_id: typeof raw.peer_id === "string" ? raw.peer_id : void 0,
177
+ pending_tokens: typeof raw.pending_tokens === "number" ? raw.pending_tokens : 0,
178
+ message_count: typeof raw.message_count === "number" ? raw.message_count : void 0,
179
+ commit_count: typeof raw.commit_count === "number" ? raw.commit_count : void 0,
180
+ last_commit_at: typeof raw.last_commit_at === "string" ? raw.last_commit_at : typeof raw.last_commit === "string" ? raw.last_commit : void 0,
181
+ created_at: typeof raw.created_at === "string" ? raw.created_at : void 0,
182
+ updated_at: typeof raw.updated_at === "string" ? raw.updated_at : void 0
183
+ }
184
+ };
185
+ } catch (err) {
186
+ return {
187
+ status: "unreachable",
188
+ detail: err instanceof Error ? err.message : String(err)
165
189
  };
166
- } catch {
167
- return null;
168
190
  }
169
191
  }
170
- return null;
192
+ return { status: "missing" };
193
+ }
194
+ /**
195
+ * Получение метаданных сессии по идентификатору.
196
+ * Обёртка над {@link readSession} для вызывающих, которым причина неудачи
197
+ * не нужна: любая неудача сводится к null.
198
+ */
199
+ async fetchSession(sessionId) {
200
+ const result = await this.readSession(sessionId);
201
+ return result.status === "ok" ? result.session : null;
171
202
  }
172
203
  /**
173
204
  * Алиас для fetchSession
@@ -233,6 +264,41 @@ function commitSession(sessionId, options, endpoint, apiKey) {
233
264
  return client.commitSession(sessionId, options);
234
265
  }
235
266
 
267
+ // src/client/theme.ts
268
+ var THEME = {
269
+ /** Фон всплывающей панели — тот же, что у меню и диалогов DSH. */
270
+ panelSurface: "--dsw-specific-menu",
271
+ /** Тень панели. */
272
+ panelElevation: "--dsw-elevation-prominent",
273
+ /** Контур панели; задаётся через переменную тени, а не через border. */
274
+ panelStroke: "--dsw-alias-border-l1",
275
+ /** Заголовки и акцентный текст. */
276
+ labelPrimary: "--dsw-alias-label-primary",
277
+ /** Основной текст панели. */
278
+ labelSecondary: "--dsw-alias-label-secondary",
279
+ /** Приглушённый текст: подписи, значения, текст чипа в покое. */
280
+ labelTertiary: "--dsw-alias-label-tertiary",
281
+ /** Разделительная линия внутри панели. */
282
+ hairline: "--dsw-alias-border-l2",
283
+ /** Подсветка интерактивного элемента под курсором. */
284
+ hoverBackground: "--dsw-alias-interactive-bg-hover",
285
+ /** Подсветка нажатого элемента. */
286
+ activeBackground: "--dsw-alias-interactive-bg-active",
287
+ /** Демон доступен. */
288
+ stateSuccess: "--dsw-alias-state-success-primary",
289
+ /** Демон недоступен или сессия нечитаема. */
290
+ stateError: "--dsw-alias-state-error-primary",
291
+ /** Идёт коммит, либо накоплено близко к порогу. */
292
+ stateWarning: "--dsw-alias-state-warn-primary",
293
+ /** Утопленная поверхность: дорожка прогресс-бара. */
294
+ insetSurface: "--dsw-alias-bg-layer-2",
295
+ /** Моноширинный шрифт для идентификаторов и путей. */
296
+ fontMono: "--dsw-font-markdown-code-font-family"
297
+ };
298
+ function themeVar(role) {
299
+ return `var(${THEME[role]})`;
300
+ }
301
+
236
302
  // src/client/recallParser.ts
237
303
  var KNOWN_CATEGORIES = /* @__PURE__ */ new Set([
238
304
  "preferences",
@@ -541,6 +607,15 @@ function parseRecalledMemories(input) {
541
607
  // src/client/OpenVikingStatusPopover.tsx
542
608
  import { useState, useEffect, useCallback, useRef } from "react";
543
609
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
610
+ function dshIcon(name2) {
611
+ try {
612
+ const primitives = typeof __require === "function" ? __require("@deepseek-ai/dsh-client-ui-primitives") : null;
613
+ const icon = primitives?.[name2];
614
+ return typeof icon === "function" ? icon : null;
615
+ } catch {
616
+ return null;
617
+ }
618
+ }
544
619
  function getProgressBarPercent(pendingTokens, threshold = COMMIT_THRESHOLD) {
545
620
  if (!threshold || threshold <= 0) return 0;
546
621
  const ratio = (pendingTokens || 0) / threshold;
@@ -548,9 +623,14 @@ function getProgressBarPercent(pendingTokens, threshold = COMMIT_THRESHOLD) {
548
623
  }
549
624
  function getProgressBarColor(percent) {
550
625
  if (percent >= 80) {
551
- return "var(--dsw-status-warning, #fbbf24)";
626
+ return themeVar("stateWarning");
552
627
  }
553
- return "var(--dsw-status-success, #34d399)";
628
+ return themeVar("stateSuccess");
629
+ }
630
+ function formatDaemonVersion(version) {
631
+ const value = version?.trim();
632
+ if (!value) return void 0;
633
+ return /^v/i.test(value) ? value : `v${value}`;
554
634
  }
555
635
  function formatRelativeTime(isoOrTimestamp, now = Date.now()) {
556
636
  if (!isoOrTimestamp) return void 0;
@@ -592,39 +672,8 @@ function truncateSessionId(id, maxLen = 16) {
592
672
  if (id.length <= maxLen) return id;
593
673
  return `${id.slice(0, maxLen)}...`;
594
674
  }
595
- function getCategoryBadgeStyle(category) {
596
- switch (category?.toLowerCase()) {
597
- case "preferences":
598
- return {
599
- backgroundColor: "rgba(168, 85, 247, 0.15)",
600
- color: "var(--dsw-status-purple, #c084fc)"
601
- };
602
- case "entities":
603
- return {
604
- backgroundColor: "rgba(59, 130, 246, 0.15)",
605
- color: "var(--dsw-status-info, #60a5fa)"
606
- };
607
- case "skills":
608
- return {
609
- backgroundColor: "rgba(236, 72, 153, 0.15)",
610
- color: "var(--dsw-status-pink, #f472b6)"
611
- };
612
- case "events":
613
- return {
614
- backgroundColor: "rgba(245, 158, 11, 0.15)",
615
- color: "var(--dsw-status-warning, #fbbf24)"
616
- };
617
- case "resources":
618
- return {
619
- backgroundColor: "rgba(20, 184, 166, 0.15)",
620
- color: "var(--dsw-status-teal, #2dd4bf)"
621
- };
622
- default:
623
- return {
624
- backgroundColor: "rgba(148, 163, 184, 0.15)",
625
- color: "var(--dsw-text-muted, #94a3b8)"
626
- };
627
- }
675
+ function getCategoryBadgeStyle(_category) {
676
+ return { color: themeVar("labelTertiary") };
628
677
  }
629
678
  function handleEscapeKey(event, onClose) {
630
679
  if (event.key === "Escape") {
@@ -637,6 +686,7 @@ function OpenVikingStatusPopover({
637
686
  sessionId,
638
687
  health,
639
688
  sessionData,
689
+ sessionRead,
640
690
  recalledResult,
641
691
  endpoint,
642
692
  isCommitting = false,
@@ -656,13 +706,17 @@ function OpenVikingStatusPopover({
656
706
  };
657
707
  }, []);
658
708
  const isOnline = health?.ok === true;
659
- const statusColor = isOnline ? "var(--dsw-status-success, #34d399)" : "var(--dsw-status-error, #f87171)";
709
+ const sessionUnreadable = isOnline && sessionRead != null && sessionRead.status !== "ok";
710
+ const unauthorized = sessionRead?.status === "unauthorized";
711
+ const statusColor = isOnline ? sessionUnreadable ? themeVar("stateWarning") : themeVar("stateSuccess") : themeVar("stateError");
660
712
  const displaySessionId = sessionData?.session_id || sessionId || "";
661
713
  const pendingTokens = sessionData?.pending_tokens ?? 0;
662
714
  const progressPercent = getProgressBarPercent(pendingTokens);
663
715
  const progressBarColor = getProgressBarColor(progressPercent);
664
716
  const memoryItems = recalledResult?.items || [];
665
717
  const recalledCount = recalledResult?.recalledCount ?? memoryItems.length;
718
+ const CopyIcon = dshIcon("IconCopyOutline16");
719
+ const CheckIcon = dshIcon("IconCheckOutline16");
666
720
  const handleCopySessionId = useCallback(() => {
667
721
  if (!displaySessionId) return;
668
722
  if (typeof navigator !== "undefined" && navigator.clipboard) {
@@ -678,7 +732,15 @@ function OpenVikingStatusPopover({
678
732
  }, 1500);
679
733
  }
680
734
  }, [displaySessionId]);
681
- const isCommitDisabled = isCommitting || !isOnline || pendingTokens === 0;
735
+ const isCommitDisabled = isCommitting || !isOnline || sessionUnreadable || pendingTokens === 0;
736
+ const pendingLabel = sessionUnreadable ? "unavailable" : `${pendingTokens.toLocaleString()} / ${COMMIT_THRESHOLD.toLocaleString()}`;
737
+ const rowStyle = {
738
+ display: "flex",
739
+ justifyContent: "space-between",
740
+ alignItems: "center"
741
+ };
742
+ const mutedStyle = { color: themeVar("labelTertiary") };
743
+ const monoStyle = { fontFamily: themeVar("fontMono") };
682
744
  return /* @__PURE__ */ jsxs(
683
745
  "div",
684
746
  {
@@ -689,17 +751,23 @@ function OpenVikingStatusPopover({
689
751
  position: "absolute",
690
752
  bottom: "calc(100% + 8px)",
691
753
  right: 0,
692
- width: "320px",
693
- backgroundColor: "var(--dsw-surface-overlay, #1e293b)",
694
- border: "1px solid var(--dsw-border-default, #334155)",
695
- borderRadius: "8px",
696
- padding: "12px",
697
- boxShadow: "0 10px 25px -5px rgba(0, 0, 0, 0.5)",
698
- zIndex: 1e3,
699
- fontSize: "12px",
700
- color: "var(--dsw-text-default, #f1f5f9)",
701
- fontFamily: "var(--dsw-font-sans, system-ui, sans-serif)",
754
+ zIndex: 1100,
702
755
  boxSizing: "border-box",
756
+ width: "max-content",
757
+ minWidth: "min(300px, 100vw - 24px)",
758
+ maxWidth: "min(440px, 100vw - 24px)",
759
+ background: themeVar("panelSurface"),
760
+ boxShadow: themeVar("panelElevation"),
761
+ color: themeVar("labelSecondary"),
762
+ cursor: "default",
763
+ border: 0,
764
+ borderRadius: "12px",
765
+ padding: "16px",
766
+ fontSize: "12px",
767
+ lineHeight: "18px",
768
+ ...{
769
+ "--dsw-elevation-stroke-color": themeVar("panelStroke")
770
+ },
703
771
  ...style
704
772
  },
705
773
  children: [
@@ -710,58 +778,41 @@ function OpenVikingStatusPopover({
710
778
  style: {
711
779
  display: "flex",
712
780
  justifyContent: "space-between",
713
- alignItems: "flex-start",
714
- marginBottom: "10px",
715
- paddingBottom: "8px",
716
- borderBottom: "1px solid var(--dsw-border-subtle, rgba(255, 255, 255, 0.08))"
781
+ gap: "16px",
782
+ marginBottom: "8px",
783
+ color: themeVar("labelPrimary"),
784
+ fontWeight: 500
717
785
  },
718
786
  children: [
719
- /* @__PURE__ */ jsxs("div", { children: [
720
- /* @__PURE__ */ jsx(
721
- "div",
722
- {
723
- style: {
724
- fontWeight: 600,
725
- fontSize: "13px",
726
- color: "var(--dsw-text-default, #f1f5f9)"
727
- },
728
- children: "OpenViking Memory"
729
- }
730
- ),
787
+ /* @__PURE__ */ jsxs("span", { style: { minWidth: 0 }, children: [
788
+ "OpenViking Memory",
789
+ " ",
731
790
  /* @__PURE__ */ jsx(
732
- "div",
791
+ "span",
733
792
  {
734
793
  "data-testid": "endpoint-label",
735
- style: {
736
- fontSize: "10px",
737
- color: "var(--dsw-text-muted, #94a3b8)",
738
- fontFamily: "var(--dsw-font-mono, monospace)",
739
- marginTop: "1px"
740
- },
794
+ style: { ...mutedStyle, ...monoStyle, fontWeight: 400 },
741
795
  children: formatEndpoint(endpoint)
742
796
  }
743
797
  )
744
798
  ] }),
745
799
  /* @__PURE__ */ jsxs(
746
- "div",
800
+ "span",
747
801
  {
748
802
  "data-testid": "status-badge",
749
803
  style: {
750
804
  display: "inline-flex",
751
805
  alignItems: "center",
752
- gap: "5px",
753
- fontSize: "10px",
754
- padding: "2px 7px",
755
- borderRadius: "4px",
756
- backgroundColor: isOnline ? "rgba(52, 211, 153, 0.15)" : "rgba(248, 113, 113, 0.15)",
806
+ gap: "6px",
757
807
  color: statusColor,
758
- fontWeight: 600
808
+ flexShrink: 0
759
809
  },
760
810
  children: [
761
811
  /* @__PURE__ */ jsx(
762
812
  "span",
763
813
  {
764
814
  "data-testid": "status-badge-dot",
815
+ "aria-hidden": "true",
765
816
  style: {
766
817
  width: "6px",
767
818
  height: "6px",
@@ -771,13 +822,27 @@ function OpenVikingStatusPopover({
771
822
  }
772
823
  }
773
824
  ),
774
- /* @__PURE__ */ jsx("span", { children: isOnline ? health?.version ? `ONLINE v${health.version}` : "ONLINE" : "OFFLINE" })
825
+ /* @__PURE__ */ jsx("span", { children: isOnline ? [
826
+ "ONLINE",
827
+ formatDaemonVersion(health?.version),
828
+ sessionUnreadable ? "\xB7 no session access" : null
829
+ ].filter(Boolean).join(" ") : "OFFLINE" })
775
830
  ]
776
831
  }
777
832
  )
778
833
  ]
779
834
  }
780
835
  ),
836
+ /* @__PURE__ */ jsx(
837
+ "div",
838
+ {
839
+ style: {
840
+ borderTop: `.5px solid ${themeVar("hairline")}`,
841
+ marginBottom: "10px"
842
+ },
843
+ "aria-hidden": "true"
844
+ }
845
+ ),
781
846
  /* @__PURE__ */ jsxs(
782
847
  "div",
783
848
  {
@@ -788,142 +853,88 @@ function OpenVikingStatusPopover({
788
853
  marginBottom: "10px"
789
854
  },
790
855
  children: [
791
- /* @__PURE__ */ jsxs(
792
- "div",
793
- {
794
- style: {
795
- display: "flex",
796
- justifyContent: "space-between",
797
- alignItems: "center"
798
- },
799
- children: [
800
- /* @__PURE__ */ jsx("span", { style: { color: "var(--dsw-text-muted, #94a3b8)" }, children: "Session ID:" }),
801
- /* @__PURE__ */ jsxs(
802
- "div",
803
- {
804
- style: {
805
- display: "flex",
806
- alignItems: "center",
807
- gap: "4px"
808
- },
809
- children: [
810
- /* @__PURE__ */ jsx(
811
- "span",
812
- {
813
- "data-testid": "session-id-value",
814
- role: "button",
815
- tabIndex: 0,
816
- onKeyDown: (e) => {
817
- if (e.key === "Enter" || e.key === " ") {
818
- e.preventDefault();
819
- handleCopySessionId();
820
- }
821
- },
822
- "aria-label": "Click to copy Session ID",
823
- style: {
824
- fontFamily: "var(--dsw-font-mono, monospace)",
825
- cursor: "pointer"
826
- },
827
- title: displaySessionId,
828
- onClick: handleCopySessionId,
829
- children: truncateSessionId(displaySessionId)
830
- }
831
- ),
832
- /* @__PURE__ */ jsx(
833
- "button",
834
- {
835
- type: "button",
836
- "data-testid": "copy-session-btn",
837
- onClick: handleCopySessionId,
838
- title: copied ? "Copied!" : "Copy Session ID",
839
- "aria-label": copied ? "Copied!" : "Copy Session ID",
840
- style: {
841
- background: "none",
842
- border: "none",
843
- cursor: "pointer",
844
- padding: "2px 4px",
845
- fontSize: "10px",
846
- color: copied ? "var(--dsw-status-success, #34d399)" : "var(--dsw-text-muted, #94a3b8)",
847
- borderRadius: "3px"
848
- },
849
- children: copied ? "\u2713" : "\u{1F4CB}"
850
- }
851
- )
852
- ]
853
- }
854
- )
855
- ]
856
- }
857
- ),
858
- sessionData?.peer_id && /* @__PURE__ */ jsxs(
859
- "div",
860
- {
861
- style: {
862
- display: "flex",
863
- justifyContent: "space-between",
864
- alignItems: "center"
865
- },
866
- children: [
867
- /* @__PURE__ */ jsx("span", { style: { color: "var(--dsw-text-muted, #94a3b8)" }, children: "Peer ID:" }),
868
- /* @__PURE__ */ jsx(
869
- "span",
870
- {
871
- "data-testid": "peer-id-value",
872
- style: {
873
- maxWidth: "180px",
874
- overflow: "hidden",
875
- textOverflow: "ellipsis",
876
- whiteSpace: "nowrap",
877
- fontFamily: "var(--dsw-font-mono, monospace)"
878
- },
879
- title: sessionData.peer_id,
880
- children: sessionData.peer_id
881
- }
882
- )
883
- ]
884
- }
885
- ),
886
- sessionData?.last_commit_at && /* @__PURE__ */ jsxs(
887
- "div",
888
- {
889
- style: {
890
- display: "flex",
891
- justifyContent: "space-between",
892
- alignItems: "center"
893
- },
894
- children: [
895
- /* @__PURE__ */ jsx("span", { style: { color: "var(--dsw-text-muted, #94a3b8)" }, children: "Last Commit:" }),
896
- /* @__PURE__ */ jsx(
897
- "span",
898
- {
899
- "data-testid": "last-commit-value",
900
- title: sessionData.last_commit_at,
901
- style: { color: "var(--dsw-text-default, #e2e8f0)" },
902
- children: formatRelativeTime(sessionData.last_commit_at) || sessionData.last_commit_at
903
- }
904
- )
905
- ]
906
- }
907
- )
856
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
857
+ /* @__PURE__ */ jsx("span", { style: mutedStyle, children: "Session ID:" }),
858
+ /* @__PURE__ */ jsxs("span", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
859
+ /* @__PURE__ */ jsx(
860
+ "span",
861
+ {
862
+ "data-testid": "session-id-value",
863
+ role: "button",
864
+ tabIndex: 0,
865
+ onKeyDown: (e) => {
866
+ if (e.key === "Enter" || e.key === " ") {
867
+ e.preventDefault();
868
+ handleCopySessionId();
869
+ }
870
+ },
871
+ "aria-label": "Click to copy Session ID",
872
+ style: { ...monoStyle, cursor: "pointer" },
873
+ title: displaySessionId,
874
+ onClick: handleCopySessionId,
875
+ children: truncateSessionId(displaySessionId)
876
+ }
877
+ ),
878
+ /* @__PURE__ */ jsx(
879
+ "button",
880
+ {
881
+ type: "button",
882
+ "data-testid": "copy-session-btn",
883
+ onClick: handleCopySessionId,
884
+ title: copied ? "Copied!" : "Copy Session ID",
885
+ "aria-label": copied ? "Copied!" : "Copy Session ID",
886
+ style: {
887
+ background: "none",
888
+ border: "none",
889
+ cursor: "pointer",
890
+ padding: "2px",
891
+ display: "inline-flex",
892
+ alignItems: "center",
893
+ color: copied ? themeVar("stateSuccess") : themeVar("labelTertiary")
894
+ },
895
+ children: copied ? CheckIcon && /* @__PURE__ */ jsx(CheckIcon, { size: 14 }) : CopyIcon && /* @__PURE__ */ jsx(CopyIcon, { size: 14 })
896
+ }
897
+ )
898
+ ] })
899
+ ] }),
900
+ sessionData?.peer_id && /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
901
+ /* @__PURE__ */ jsx("span", { style: mutedStyle, children: "Peer ID:" }),
902
+ /* @__PURE__ */ jsx(
903
+ "span",
904
+ {
905
+ "data-testid": "peer-id-value",
906
+ style: {
907
+ ...monoStyle,
908
+ maxWidth: "180px",
909
+ overflow: "hidden",
910
+ textOverflow: "ellipsis",
911
+ whiteSpace: "nowrap"
912
+ },
913
+ title: sessionData.peer_id,
914
+ children: sessionData.peer_id
915
+ }
916
+ )
917
+ ] }),
918
+ sessionData?.last_commit_at && /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
919
+ /* @__PURE__ */ jsx("span", { style: mutedStyle, children: "Last Commit:" }),
920
+ /* @__PURE__ */ jsx(
921
+ "span",
922
+ {
923
+ "data-testid": "last-commit-value",
924
+ title: sessionData.last_commit_at,
925
+ children: formatRelativeTime(sessionData.last_commit_at) || sessionData.last_commit_at
926
+ }
927
+ )
928
+ ] })
908
929
  ]
909
930
  }
910
931
  ),
911
932
  /* @__PURE__ */ jsxs("div", { style: { marginBottom: "12px" }, children: [
912
- /* @__PURE__ */ jsxs(
913
- "div",
914
- {
915
- style: {
916
- display: "flex",
917
- justifyContent: "space-between",
918
- marginBottom: "4px"
919
- },
920
- children: [
921
- /* @__PURE__ */ jsx("span", { style: { color: "var(--dsw-text-muted, #94a3b8)" }, children: "Pending Tokens:" }),
922
- /* @__PURE__ */ jsx("span", { "data-testid": "pending-tokens-label", style: { fontWeight: 500 }, children: `${pendingTokens.toLocaleString()} / ${COMMIT_THRESHOLD.toLocaleString()}` })
923
- ]
924
- }
925
- ),
926
- /* @__PURE__ */ jsx(
933
+ /* @__PURE__ */ jsxs("div", { style: { ...rowStyle, marginBottom: "4px" }, children: [
934
+ /* @__PURE__ */ jsx("span", { style: mutedStyle, children: "Pending Tokens:" }),
935
+ /* @__PURE__ */ jsx("span", { "data-testid": "pending-tokens-label", children: pendingLabel })
936
+ ] }),
937
+ !sessionUnreadable && /* @__PURE__ */ jsx(
927
938
  "div",
928
939
  {
929
940
  "data-testid": "progress-bar-track",
@@ -931,7 +942,7 @@ function OpenVikingStatusPopover({
931
942
  width: "100%",
932
943
  height: "6px",
933
944
  borderRadius: "3px",
934
- backgroundColor: "rgba(255, 255, 255, 0.1)",
945
+ backgroundColor: themeVar("insetSurface"),
935
946
  overflow: "hidden"
936
947
  },
937
948
  children: /* @__PURE__ */ jsx(
@@ -949,30 +960,34 @@ function OpenVikingStatusPopover({
949
960
  }
950
961
  )
951
962
  ] }),
963
+ sessionUnreadable && /* @__PURE__ */ jsx(
964
+ "div",
965
+ {
966
+ "data-testid": "session-unreadable-notice",
967
+ style: {
968
+ marginBottom: "12px",
969
+ color: themeVar("labelTertiary")
970
+ },
971
+ children: unauthorized ? "The daemon requires an API key. Set openviking_api_key in localStorage to read session counters." : "Session counters are unavailable right now."
972
+ }
973
+ ),
952
974
  /* @__PURE__ */ jsxs("div", { style: { marginBottom: "12px" }, children: [
953
975
  /* @__PURE__ */ jsx(
954
976
  "div",
955
977
  {
956
978
  style: {
957
- display: "flex",
958
- justifyContent: "space-between",
959
- alignItems: "center",
960
- marginBottom: "4px"
979
+ marginBottom: "4px",
980
+ color: themeVar("labelPrimary"),
981
+ fontWeight: 500
961
982
  },
962
- children: /* @__PURE__ */ jsx("span", { style: { fontWeight: 600, fontSize: "11px" }, children: `Recalled Memories (${recalledCount})` })
983
+ children: `Recalled Memories (${recalledCount})`
963
984
  }
964
985
  ),
965
986
  memoryItems.length === 0 ? /* @__PURE__ */ jsx(
966
987
  "div",
967
988
  {
968
989
  "data-testid": "empty-memories-message",
969
- style: {
970
- padding: "8px 0",
971
- color: "var(--dsw-text-muted, #94a3b8)",
972
- fontStyle: "italic",
973
- fontSize: "11px",
974
- textAlign: "center"
975
- },
990
+ style: { ...mutedStyle, padding: "4px 0" },
976
991
  children: "No memories recalled in this session"
977
992
  }
978
993
  ) : /* @__PURE__ */ jsx(
@@ -996,11 +1011,7 @@ function OpenVikingStatusPopover({
996
1011
  display: "flex",
997
1012
  alignItems: "center",
998
1013
  gap: "6px",
999
- padding: "4px 6px",
1000
- borderRadius: "4px",
1001
- backgroundColor: "rgba(255, 255, 255, 0.04)",
1002
- border: "1px solid var(--dsw-border-subtle, rgba(255, 255, 255, 0.05))",
1003
- fontSize: "11px"
1014
+ minWidth: 0
1004
1015
  },
1005
1016
  children: [
1006
1017
  /* @__PURE__ */ jsx(
@@ -1008,10 +1019,6 @@ function OpenVikingStatusPopover({
1008
1019
  {
1009
1020
  "data-testid": "memory-category-badge",
1010
1021
  style: {
1011
- fontSize: "9px",
1012
- fontWeight: 600,
1013
- padding: "1px 4px",
1014
- borderRadius: "3px",
1015
1022
  textTransform: "uppercase",
1016
1023
  flexShrink: 0,
1017
1024
  ...getCategoryBadgeStyle(item.category)
@@ -1023,21 +1030,7 @@ function OpenVikingStatusPopover({
1023
1030
  "span",
1024
1031
  {
1025
1032
  "data-testid": "memory-source-badge",
1026
- style: {
1027
- fontSize: "9px",
1028
- fontWeight: 600,
1029
- padding: "1px 4px",
1030
- borderRadius: "3px",
1031
- textTransform: "uppercase",
1032
- flexShrink: 0,
1033
- ...item.source === "profile" ? {
1034
- backgroundColor: "rgba(99, 102, 241, 0.15)",
1035
- color: "#818cf8"
1036
- } : {
1037
- backgroundColor: "rgba(16, 185, 129, 0.15)",
1038
- color: "var(--dsw-status-success, #34d399)"
1039
- }
1040
- },
1033
+ style: { ...mutedStyle, flexShrink: 0 },
1041
1034
  children: item.source
1042
1035
  }
1043
1036
  ),
@@ -1046,12 +1039,10 @@ function OpenVikingStatusPopover({
1046
1039
  {
1047
1040
  "data-testid": "memory-leaf-name",
1048
1041
  style: {
1049
- flex: 1,
1050
1042
  overflow: "hidden",
1051
1043
  textOverflow: "ellipsis",
1052
1044
  whiteSpace: "nowrap",
1053
- fontFamily: "var(--dsw-font-mono, monospace)",
1054
- color: "var(--dsw-text-default, #f1f5f9)"
1045
+ minWidth: 0
1055
1046
  },
1056
1047
  children: formatMemoryLeafName(item.uri)
1057
1048
  }
@@ -1067,16 +1058,7 @@ function OpenVikingStatusPopover({
1067
1058
  "div",
1068
1059
  {
1069
1060
  "data-testid": "commit-error-message",
1070
- style: {
1071
- marginBottom: "8px",
1072
- padding: "6px 8px",
1073
- borderRadius: "4px",
1074
- backgroundColor: "rgba(248, 113, 113, 0.1)",
1075
- border: "1px solid var(--dsw-status-error, #f87171)",
1076
- color: "var(--dsw-status-error, #f87171)",
1077
- fontSize: "11px",
1078
- wordBreak: "break-word"
1079
- },
1061
+ style: { marginBottom: "8px", color: themeVar("stateError") },
1080
1062
  children: commitError
1081
1063
  }
1082
1064
  ),
@@ -1085,19 +1067,17 @@ function OpenVikingStatusPopover({
1085
1067
  {
1086
1068
  type: "button",
1087
1069
  "data-testid": "commit-now-btn",
1088
- onClick: () => onCommitNow?.(),
1070
+ onClick: () => void onCommitNow?.(),
1089
1071
  disabled: isCommitDisabled,
1090
1072
  style: {
1091
1073
  width: "100%",
1092
- padding: "7px 0",
1093
- borderRadius: "6px",
1094
- border: "1px solid var(--dsw-border-default, #475569)",
1095
- backgroundColor: isCommitting ? "var(--dsw-surface-active, #334155)" : isCommitDisabled ? "rgba(255, 255, 255, 0.03)" : "var(--dsw-surface-base, #1e293b)",
1096
- color: isCommitDisabled ? "var(--dsw-text-muted, #64748b)" : "var(--dsw-text-default, #f8fafc)",
1097
- cursor: isCommitDisabled ? "not-allowed" : "pointer",
1098
- fontWeight: 600,
1099
- fontSize: "12px",
1100
- transition: "all 0.15s ease",
1074
+ padding: "6px 10px",
1075
+ borderRadius: "8px",
1076
+ border: `.5px solid ${themeVar("hairline")}`,
1077
+ background: isCommitDisabled ? "transparent" : themeVar("hoverBackground"),
1078
+ color: isCommitDisabled ? themeVar("labelTertiary") : themeVar("labelPrimary"),
1079
+ cursor: isCommitDisabled ? "default" : "pointer",
1080
+ font: "inherit",
1101
1081
  display: "flex",
1102
1082
  alignItems: "center",
1103
1083
  justifyContent: "center",
@@ -1107,12 +1087,13 @@ function OpenVikingStatusPopover({
1107
1087
  /* @__PURE__ */ jsx(
1108
1088
  "span",
1109
1089
  {
1090
+ "aria-hidden": "true",
1110
1091
  style: {
1111
1092
  display: "inline-block",
1112
1093
  width: "10px",
1113
1094
  height: "10px",
1114
1095
  borderRadius: "50%",
1115
- border: "2px solid var(--dsw-status-warning, #fbbf24)",
1096
+ border: `2px solid ${themeVar("stateWarning")}`,
1116
1097
  borderTopColor: "transparent",
1117
1098
  animation: "ov-spin 1s linear infinite"
1118
1099
  }
@@ -1144,11 +1125,15 @@ function formatTooltipTitle({
1144
1125
  isOnline,
1145
1126
  isCommitting = false,
1146
1127
  recalledCount,
1147
- pendingTokens
1128
+ pendingTokens,
1129
+ sessionUnreadable = false
1148
1130
  }) {
1149
1131
  if (!isOnline) {
1150
1132
  return "OpenViking: Offline";
1151
1133
  }
1134
+ if (sessionUnreadable) {
1135
+ return "OpenViking: session unreadable \u2014 the daemon requires an API key";
1136
+ }
1152
1137
  const countLabel = `${recalledCount} recalled`;
1153
1138
  const tokenLabel = `${(pendingTokens || 0).toLocaleString()} pending tokens`;
1154
1139
  if (isCommitting) {
@@ -1156,36 +1141,69 @@ function formatTooltipTitle({
1156
1141
  }
1157
1142
  return `OpenViking: Online (${countLabel}, ${tokenLabel})`;
1158
1143
  }
1159
- function getStatusIndicatorColor(isOnline, isCommitting = false) {
1144
+ function getStatusIndicatorColor(isOnline, isCommitting = false, sessionUnreadable = false) {
1160
1145
  if (!isOnline) {
1161
- return "var(--dsw-status-error, #f87171)";
1146
+ return themeVar("stateError");
1162
1147
  }
1163
- if (isCommitting) {
1164
- return "var(--dsw-status-warning, #fbbf24)";
1148
+ if (isCommitting || sessionUnreadable) {
1149
+ return themeVar("stateWarning");
1165
1150
  }
1166
- return "var(--dsw-status-success, #34d399)";
1151
+ return themeVar("stateSuccess");
1167
1152
  }
1168
- function getStatusGlow(isOnline, isCommitting = false) {
1169
- if (isOnline && !isCommitting) {
1170
- return "0 0 6px var(--dsw-status-success, #34d399)";
1171
- }
1172
- return "none";
1153
+ function chatNodesToText(nodes) {
1154
+ if (!nodes) return "";
1155
+ const source = Array.isArray(nodes) ? nodes : typeof nodes === "object" ? Object.values(nodes) : [];
1156
+ const parts = [];
1157
+ const visit = (value, depth = 0) => {
1158
+ if (depth > 4 || value === null || value === void 0) return;
1159
+ if (typeof value === "string") {
1160
+ parts.push(value);
1161
+ return;
1162
+ }
1163
+ if (Array.isArray(value)) {
1164
+ for (const item of value) visit(item, depth + 1);
1165
+ return;
1166
+ }
1167
+ if (typeof value === "object") {
1168
+ const record = value;
1169
+ for (const key of ["content", "text", "data", "body"]) {
1170
+ if (key in record) visit(record[key], depth + 1);
1171
+ }
1172
+ }
1173
+ };
1174
+ for (const node of source) visit(node);
1175
+ return parts.join("\n");
1173
1176
  }
1174
- function getFallbackSessionMessages(sessionId) {
1175
- if (!sessionId || typeof window === "undefined") {
1176
- return void 0;
1177
+ function OpenVikingStatusChip(props) {
1178
+ const { useChat, ...rest } = props;
1179
+ if (useChat && rest.contextText === void 0 && rest.messages === void 0) {
1180
+ return /* @__PURE__ */ jsx2(ChatReadBoundary, { fallback: /* @__PURE__ */ jsx2(StatusChipView, { ...rest }), children: /* @__PURE__ */ jsx2(ChatBackedStatusChip, { useChat, ...rest }) });
1177
1181
  }
1178
- const win = window;
1179
- if (win.__DSH_STORE__?.getState) {
1180
- const state = win.__DSH_STORE__.getState();
1181
- return state?.conversations?.[sessionId]?.messages || state?.sessions?.[sessionId]?.messages;
1182
+ return /* @__PURE__ */ jsx2(StatusChipView, { ...rest });
1183
+ }
1184
+ var ChatReadBoundary = class extends React2.Component {
1185
+ state = { failed: false };
1186
+ static getDerivedStateFromError() {
1187
+ return { failed: true };
1182
1188
  }
1183
- if (win.__DSH_SESSION_MESSAGES__?.[sessionId]) {
1184
- return win.__DSH_SESSION_MESSAGES__[sessionId];
1189
+ render() {
1190
+ return this.state.failed ? this.props.fallback : this.props.children;
1185
1191
  }
1186
- return void 0;
1192
+ };
1193
+ function ChatBackedStatusChip({
1194
+ useChat,
1195
+ ...rest
1196
+ }) {
1197
+ const nodes = useChat((snapshot) => {
1198
+ try {
1199
+ return snapshot?.legacy?.nodes !== void 0 ? snapshot.legacy.nodes : snapshot?.nodes;
1200
+ } catch {
1201
+ return void 0;
1202
+ }
1203
+ });
1204
+ return /* @__PURE__ */ jsx2(StatusChipView, { ...rest, messages: nodes });
1187
1205
  }
1188
- function OpenVikingStatusChip({
1206
+ function StatusChipView({
1189
1207
  sessionId,
1190
1208
  messages,
1191
1209
  contextText,
@@ -1194,32 +1212,28 @@ function OpenVikingStatusChip({
1194
1212
  className,
1195
1213
  initialHealth,
1196
1214
  initialSessionData,
1215
+ initialSessionRead,
1197
1216
  initialOpen = false
1198
1217
  }) {
1199
1218
  const [health, setHealth] = useState2(
1200
1219
  initialHealth ?? null
1201
1220
  );
1202
- const [sessionData, setSessionData] = useState2(
1203
- initialSessionData ?? null
1221
+ const [sessionRead, setSessionRead] = useState2(
1222
+ initialSessionRead ?? (initialSessionData ? { status: "ok", session: initialSessionData } : null)
1204
1223
  );
1205
1224
  const [isOpen, setIsOpen] = useState2(initialOpen);
1206
1225
  const [isCommitting, setIsCommitting] = useState2(false);
1207
1226
  const [commitError, setCommitError] = useState2(null);
1227
+ const [isHovered, setIsHovered] = useState2(false);
1208
1228
  const popoverRef = useRef2(null);
1209
1229
  const apiClient = client ?? defaultOpenVikingClient;
1210
- const fallbackMessages = useMemo(() => {
1211
- if (messages || contextText) return void 0;
1212
- return getFallbackSessionMessages(sessionId);
1213
- }, [sessionId, messages, contextText]);
1214
- const inputForParser = useMemo(() => {
1215
- if (contextText && messages) {
1216
- return [contextText, ...messages];
1217
- }
1218
- return contextText ?? messages ?? fallbackMessages;
1219
- }, [contextText, messages, fallbackMessages]);
1230
+ const conversationText = useMemo(() => {
1231
+ if (typeof contextText === "string") return contextText;
1232
+ return chatNodesToText(messages);
1233
+ }, [contextText, messages]);
1220
1234
  const recalledResult = useMemo(
1221
- () => parseRecalledMemories(inputForParser),
1222
- [inputForParser]
1235
+ () => parseRecalledMemories(conversationText),
1236
+ [conversationText]
1223
1237
  );
1224
1238
  const fetchStatus = useCallback2(async () => {
1225
1239
  try {
@@ -1228,8 +1242,7 @@ function OpenVikingStatusChip({
1228
1242
  if (!healthRes.ok) {
1229
1243
  return;
1230
1244
  }
1231
- const session = await apiClient.fetchSession(sessionId);
1232
- setSessionData(session);
1245
+ setSessionRead(await apiClient.readSession(sessionId));
1233
1246
  } catch {
1234
1247
  setHealth({ ok: false });
1235
1248
  }
@@ -1282,26 +1295,28 @@ function OpenVikingStatusChip({
1282
1295
  }
1283
1296
  };
1284
1297
  const isOnline = health?.ok === true;
1298
+ const sessionData = sessionRead?.status === "ok" ? sessionRead.session : null;
1299
+ const sessionUnreadable = isOnline && sessionRead !== null && sessionRead.status !== "ok";
1285
1300
  const pendingTokens = sessionData?.pending_tokens ?? 0;
1286
- const pendingTokensK = Math.round(pendingTokens / 1e3);
1287
1301
  const recalledCount = recalledResult.recalledCount;
1288
- const statusColor = getStatusIndicatorColor(isOnline, isCommitting);
1289
- const statusGlow = getStatusGlow(isOnline, isCommitting);
1302
+ const statusColor = getStatusIndicatorColor(
1303
+ isOnline,
1304
+ isCommitting,
1305
+ sessionUnreadable
1306
+ );
1290
1307
  const tooltipTitle = formatTooltipTitle({
1291
1308
  isOnline,
1292
1309
  isCommitting,
1293
1310
  recalledCount,
1294
- pendingTokens
1311
+ pendingTokens,
1312
+ sessionUnreadable
1295
1313
  });
1314
+ const label = !isOnline ? "OV offline" : sessionUnreadable ? `OV: ${recalledCount} rec \xB7 no access` : `OV: ${recalledCount} rec \xB7 ${Math.round(pendingTokens / 1e3)}k pend`;
1296
1315
  return /* @__PURE__ */ jsxs2(
1297
- "div",
1316
+ "span",
1298
1317
  {
1299
1318
  className,
1300
- style: {
1301
- position: "relative",
1302
- display: "inline-flex",
1303
- alignItems: "center"
1304
- },
1319
+ style: { minWidth: 0, display: "inline-flex", position: "relative" },
1305
1320
  ref: popoverRef,
1306
1321
  children: [
1307
1322
  /* @__PURE__ */ jsxs2(
@@ -1309,23 +1324,28 @@ function OpenVikingStatusChip({
1309
1324
  {
1310
1325
  type: "button",
1311
1326
  onClick: () => setIsOpen(!isOpen),
1327
+ onMouseEnter: () => setIsHovered(true),
1328
+ onMouseLeave: () => setIsHovered(false),
1312
1329
  "aria-expanded": isOpen,
1313
1330
  "aria-haspopup": "dialog",
1314
1331
  style: {
1315
- display: "inline-flex",
1332
+ // Геометрия и типографика повторяют штатный чип статистики DSH:
1333
+ // прозрачный фон, без рамки, шрифт и кегль наследуются от строки.
1334
+ boxSizing: "border-box",
1335
+ maxWidth: "100%",
1336
+ color: themeVar("labelTertiary"),
1337
+ font: "inherit",
1338
+ fontVariantNumeric: "tabular-nums",
1339
+ lineHeight: "inherit",
1340
+ whiteSpace: "nowrap",
1341
+ background: isHovered ? themeVar("hoverBackground") : "transparent",
1342
+ border: "none",
1343
+ borderRadius: "24px",
1316
1344
  alignItems: "center",
1317
1345
  gap: "6px",
1318
- height: "26px",
1319
- padding: "0 8px",
1320
- fontSize: "12px",
1321
- fontFamily: "var(--dsw-font-mono, monospace)",
1322
- borderRadius: "6px",
1323
- background: "var(--dsw-surface-base, rgba(255, 255, 255, 0.05))",
1324
- border: "1px solid var(--dsw-border-subtle, rgba(255, 255, 255, 0.1))",
1325
- color: "var(--dsw-text-muted, #94a3b8)",
1326
- cursor: "pointer",
1327
- transition: "all 0.15s ease",
1328
- userSelect: "none"
1346
+ padding: "1px 8px",
1347
+ display: "inline-flex",
1348
+ cursor: "pointer"
1329
1349
  },
1330
1350
  title: tooltipTitle,
1331
1351
  "aria-label": tooltipTitle,
@@ -1334,25 +1354,17 @@ function OpenVikingStatusChip({
1334
1354
  "span",
1335
1355
  {
1336
1356
  "data-testid": "status-dot",
1357
+ "aria-hidden": "true",
1337
1358
  style: {
1338
- width: "7px",
1339
- height: "7px",
1359
+ width: "6px",
1360
+ height: "6px",
1340
1361
  borderRadius: "50%",
1341
- backgroundColor: statusColor,
1342
- boxShadow: statusGlow,
1362
+ background: statusColor,
1343
1363
  flexShrink: 0
1344
1364
  }
1345
1365
  }
1346
1366
  ),
1347
- /* @__PURE__ */ jsx2(
1348
- "span",
1349
- {
1350
- style: { fontWeight: 600, color: "var(--dsw-text-default, #e2e8f0)" },
1351
- children: isOnline ? "OV:" : "OV"
1352
- }
1353
- ),
1354
- " ",
1355
- /* @__PURE__ */ jsx2("span", { children: isOnline ? `${recalledCount} rec \xB7 ${pendingTokensK}k pend` : "offline" })
1367
+ /* @__PURE__ */ jsx2("span", { style: { textOverflow: "ellipsis", minWidth: 0 }, children: label })
1356
1368
  ]
1357
1369
  }
1358
1370
  ),
@@ -1362,6 +1374,7 @@ function OpenVikingStatusChip({
1362
1374
  sessionId,
1363
1375
  health,
1364
1376
  sessionData,
1377
+ sessionRead,
1365
1378
  recalledResult,
1366
1379
  endpoint: apiClient.endpoint,
1367
1380
  isCommitting,
@@ -1381,10 +1394,10 @@ var inject = ["slots"];
1381
1394
  function apply(ctx) {
1382
1395
  ctx.effect(
1383
1396
  () => ctx.slots.inject(
1384
- "conversation.input.right",
1397
+ "conversation.composer.dock",
1385
1398
  () => ctx.slots.register(
1386
1399
  {
1387
- name: "conversation.input.right",
1400
+ name: "conversation.composer.dock",
1388
1401
  id: "openviking-status",
1389
1402
  order: 50,
1390
1403
  label: "OpenViking"
@@ -1392,7 +1405,7 @@ function apply(ctx) {
1392
1405
  OpenVikingStatusChip
1393
1406
  )
1394
1407
  ),
1395
- "openviking-status: composer chip"
1408
+ "openviking-status: composer stats chip"
1396
1409
  );
1397
1410
  }
1398
1411
  export {
@@ -1401,11 +1414,14 @@ export {
1401
1414
  OpenVikingClient,
1402
1415
  OpenVikingStatusChip,
1403
1416
  OpenVikingStatusPopover,
1417
+ THEME,
1404
1418
  apply,
1419
+ chatNodesToText,
1405
1420
  checkHealth,
1406
1421
  commitSession,
1407
1422
  defaultOpenVikingClient,
1408
1423
  fetchSession,
1424
+ formatDaemonVersion,
1409
1425
  formatEndpoint,
1410
1426
  formatMemoryLeafName,
1411
1427
  formatPendingTokens,
@@ -1413,11 +1429,9 @@ export {
1413
1429
  formatStatusLabel,
1414
1430
  formatTooltipTitle,
1415
1431
  getCategoryBadgeStyle,
1416
- getFallbackSessionMessages,
1417
1432
  getProgressBarColor,
1418
1433
  getProgressBarPercent,
1419
1434
  getSession,
1420
- getStatusGlow,
1421
1435
  getStatusIndicatorColor,
1422
1436
  handleEscapeKey,
1423
1437
  inferCategory,
@@ -1426,6 +1440,7 @@ export {
1426
1440
  parseRecalledMemories,
1427
1441
  resolveApiKey,
1428
1442
  resolveEndpoint,
1443
+ themeVar,
1429
1444
  truncateSessionId
1430
1445
  };
1431
1446
  //# sourceMappingURL=client.js.map