@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/README.md +19 -3
- package/lib/client.cjs +385 -367
- package/lib/client.cjs.map +1 -1
- package/lib/client.d.cts +156 -34
- package/lib/client.js +382 -367
- package/lib/client.js.map +1 -1
- package/package.json +3 -2
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
|
-
*
|
|
136
|
+
* Чтение метаданных сессии с явной причиной неудачи.
|
|
137
|
+
*
|
|
138
|
+
* Демон может работать с `auth_mode: api_key`: тогда `/health` остаётся
|
|
139
|
+
* открытым, а сессия отвечает 401. Схлопывать это в «нет данных» нельзя —
|
|
140
|
+
* иначе интерфейс покажет живой индикатор рядом с нулями и умолчит о том,
|
|
141
|
+
* что счётчики просто недоступны.
|
|
129
142
|
*/
|
|
130
|
-
async
|
|
143
|
+
async readSession(sessionId) {
|
|
131
144
|
if (!sessionId || !sessionId.trim()) {
|
|
132
|
-
return
|
|
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
|
|
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
|
|
169
|
+
return { status: "error", detail: "malformed response body" };
|
|
154
170
|
}
|
|
155
171
|
this.resolvedSessionIds.set(sessionId.trim(), candidateId);
|
|
156
172
|
return {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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
|
|
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 "
|
|
626
|
+
return themeVar("stateWarning");
|
|
552
627
|
}
|
|
553
|
-
return "
|
|
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(
|
|
596
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
714
|
-
marginBottom: "
|
|
715
|
-
|
|
716
|
-
|
|
781
|
+
gap: "16px",
|
|
782
|
+
marginBottom: "8px",
|
|
783
|
+
color: themeVar("labelPrimary"),
|
|
784
|
+
fontWeight: 500
|
|
717
785
|
},
|
|
718
786
|
children: [
|
|
719
|
-
/* @__PURE__ */ jsxs("
|
|
720
|
-
|
|
721
|
-
|
|
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
|
-
"
|
|
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
|
-
"
|
|
800
|
+
"span",
|
|
747
801
|
{
|
|
748
802
|
"data-testid": "status-badge",
|
|
749
803
|
style: {
|
|
750
804
|
display: "inline-flex",
|
|
751
805
|
alignItems: "center",
|
|
752
|
-
gap: "
|
|
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
|
-
|
|
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 ?
|
|
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
|
-
"
|
|
793
|
-
{
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
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
|
-
"
|
|
914
|
-
{
|
|
915
|
-
|
|
916
|
-
|
|
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: "
|
|
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
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
marginBottom: "4px"
|
|
979
|
+
marginBottom: "4px",
|
|
980
|
+
color: themeVar("labelPrimary"),
|
|
981
|
+
fontWeight: 500
|
|
961
982
|
},
|
|
962
|
-
children:
|
|
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
|
-
|
|
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
|
-
|
|
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: "
|
|
1093
|
-
borderRadius: "
|
|
1094
|
-
border:
|
|
1095
|
-
|
|
1096
|
-
color: isCommitDisabled ? "
|
|
1097
|
-
cursor: isCommitDisabled ? "
|
|
1098
|
-
|
|
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:
|
|
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 "
|
|
1146
|
+
return themeVar("stateError");
|
|
1162
1147
|
}
|
|
1163
|
-
if (isCommitting) {
|
|
1164
|
-
return "
|
|
1148
|
+
if (isCommitting || sessionUnreadable) {
|
|
1149
|
+
return themeVar("stateWarning");
|
|
1165
1150
|
}
|
|
1166
|
-
return "
|
|
1151
|
+
return themeVar("stateSuccess");
|
|
1167
1152
|
}
|
|
1168
|
-
function
|
|
1169
|
-
if (
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
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
|
|
1175
|
-
|
|
1176
|
-
|
|
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
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
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
|
-
|
|
1184
|
-
return
|
|
1189
|
+
render() {
|
|
1190
|
+
return this.state.failed ? this.props.fallback : this.props.children;
|
|
1185
1191
|
}
|
|
1186
|
-
|
|
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
|
|
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 [
|
|
1203
|
-
|
|
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
|
|
1211
|
-
if (
|
|
1212
|
-
return
|
|
1213
|
-
}, [
|
|
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(
|
|
1222
|
-
[
|
|
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
|
-
|
|
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(
|
|
1289
|
-
|
|
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
|
-
"
|
|
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
|
-
|
|
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
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
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: "
|
|
1339
|
-
height: "
|
|
1359
|
+
width: "6px",
|
|
1360
|
+
height: "6px",
|
|
1340
1361
|
borderRadius: "50%",
|
|
1341
|
-
|
|
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.
|
|
1397
|
+
"conversation.composer.dock",
|
|
1385
1398
|
() => ctx.slots.register(
|
|
1386
1399
|
{
|
|
1387
|
-
name: "conversation.
|
|
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
|