@dipertq/dsh-openviking-status 0.1.7 → 0.2.0
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 +11 -3
- package/lib/client.cjs +1103 -367
- package/lib/client.cjs.map +1 -1
- package/lib/client.d.cts +186 -36
- package/lib/client.js +1100 -367
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +32 -4
- package/lib/index.js +1206 -5
- package/lib/index.js.map +1 -1
- package/package.json +6 -2
package/lib/client.cjs
CHANGED
|
@@ -4,9 +4,11 @@ window.__ModuleLoader__.load({
|
|
|
4
4
|
var module = { exports: {} };
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
"use strict";
|
|
7
|
+
var __create = Object.create;
|
|
7
8
|
var __defProp = Object.defineProperty;
|
|
8
9
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
9
10
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
11
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
10
12
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
11
13
|
var __export = (target, all) => {
|
|
12
14
|
for (var name2 in all)
|
|
@@ -20,6 +22,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
20
22
|
}
|
|
21
23
|
return to;
|
|
22
24
|
};
|
|
25
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
26
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
27
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
28
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
29
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
30
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
31
|
+
mod
|
|
32
|
+
));
|
|
23
33
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
24
34
|
|
|
25
35
|
// src/client/index.tsx
|
|
@@ -28,13 +38,17 @@ __export(client_exports, {
|
|
|
28
38
|
COMMIT_THRESHOLD: () => COMMIT_THRESHOLD,
|
|
29
39
|
DEFAULT_OPENVIKING_ENDPOINT: () => DEFAULT_OPENVIKING_ENDPOINT,
|
|
30
40
|
OpenVikingClient: () => OpenVikingClient,
|
|
41
|
+
OpenVikingSettingsSection: () => OpenVikingSettingsSection,
|
|
31
42
|
OpenVikingStatusChip: () => OpenVikingStatusChip,
|
|
32
43
|
OpenVikingStatusPopover: () => OpenVikingStatusPopover,
|
|
44
|
+
THEME: () => THEME,
|
|
33
45
|
apply: () => apply,
|
|
46
|
+
chatNodesToText: () => chatNodesToText,
|
|
34
47
|
checkHealth: () => checkHealth,
|
|
35
48
|
commitSession: () => commitSession,
|
|
36
49
|
defaultOpenVikingClient: () => defaultOpenVikingClient,
|
|
37
50
|
fetchSession: () => fetchSession,
|
|
51
|
+
formatDaemonVersion: () => formatDaemonVersion,
|
|
38
52
|
formatEndpoint: () => formatEndpoint,
|
|
39
53
|
formatMemoryLeafName: () => formatMemoryLeafName,
|
|
40
54
|
formatPendingTokens: () => formatPendingTokens,
|
|
@@ -42,11 +56,9 @@ __export(client_exports, {
|
|
|
42
56
|
formatStatusLabel: () => formatStatusLabel,
|
|
43
57
|
formatTooltipTitle: () => formatTooltipTitle,
|
|
44
58
|
getCategoryBadgeStyle: () => getCategoryBadgeStyle,
|
|
45
|
-
getFallbackSessionMessages: () => getFallbackSessionMessages,
|
|
46
59
|
getProgressBarColor: () => getProgressBarColor,
|
|
47
60
|
getProgressBarPercent: () => getProgressBarPercent,
|
|
48
61
|
getSession: () => getSession,
|
|
49
|
-
getStatusGlow: () => getStatusGlow,
|
|
50
62
|
getStatusIndicatorColor: () => getStatusIndicatorColor,
|
|
51
63
|
handleEscapeKey: () => handleEscapeKey,
|
|
52
64
|
inferCategory: () => inferCategory,
|
|
@@ -55,12 +67,14 @@ __export(client_exports, {
|
|
|
55
67
|
parseRecalledMemories: () => parseRecalledMemories,
|
|
56
68
|
resolveApiKey: () => resolveApiKey,
|
|
57
69
|
resolveEndpoint: () => resolveEndpoint,
|
|
70
|
+
themeVar: () => themeVar,
|
|
58
71
|
truncateSessionId: () => truncateSessionId
|
|
59
72
|
});
|
|
60
73
|
module.exports = __toCommonJS(client_exports);
|
|
61
74
|
|
|
62
75
|
// src/client/OpenVikingStatusChip.tsx
|
|
63
|
-
var import_react2 = require("react");
|
|
76
|
+
var import_react2 = __toESM(require("react"), 1);
|
|
77
|
+
var import_react_dom = __toESM(require("react-dom"), 1);
|
|
64
78
|
|
|
65
79
|
// src/client/api.ts
|
|
66
80
|
var DEFAULT_OPENVIKING_ENDPOINT = "http://127.0.0.1:1933";
|
|
@@ -114,6 +128,30 @@ var OpenVikingClient = class {
|
|
|
114
128
|
this.endpoint = resolveEndpoint(endpoint);
|
|
115
129
|
this.apiKey = resolveApiKey(apiKey);
|
|
116
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Обновление конфигурации клиента на лету (например, после сохранения настроек в UI).
|
|
133
|
+
*/
|
|
134
|
+
updateConfig(config) {
|
|
135
|
+
if (config.endpoint && config.endpoint.trim()) {
|
|
136
|
+
this.endpoint = resolveEndpoint(config.endpoint);
|
|
137
|
+
}
|
|
138
|
+
if (config.apiKey !== void 0) {
|
|
139
|
+
this.apiKey = resolveApiKey(config.apiKey);
|
|
140
|
+
}
|
|
141
|
+
this.resolvedSessionIds.clear();
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Очистить кэш разрешенных идентификаторов сессий.
|
|
145
|
+
*/
|
|
146
|
+
clearResolvedSessions() {
|
|
147
|
+
this.resolvedSessionIds.clear();
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Проверка, работает ли клиент через DSH Web Server proxy.
|
|
151
|
+
*/
|
|
152
|
+
isProxy() {
|
|
153
|
+
return this.endpoint.startsWith("/") || this.endpoint.includes("/openviking-status/api");
|
|
154
|
+
}
|
|
117
155
|
/**
|
|
118
156
|
* Формирование заголовков запроса, включая опциональный заголовок авторизации
|
|
119
157
|
*/
|
|
@@ -144,6 +182,8 @@ var OpenVikingClient = class {
|
|
|
144
182
|
} else if (raw.startsWith("dsh-")) {
|
|
145
183
|
const suffix = raw.slice("dsh-".length);
|
|
146
184
|
candidates.push(raw, `dsh-session-${suffix}`);
|
|
185
|
+
} else if (raw.startsWith("session-")) {
|
|
186
|
+
candidates.push(`dsh-${raw}`, raw);
|
|
147
187
|
} else {
|
|
148
188
|
candidates.push(`dsh-session-${raw}`, `dsh-${raw}`, raw);
|
|
149
189
|
}
|
|
@@ -153,6 +193,32 @@ var OpenVikingClient = class {
|
|
|
153
193
|
* Проверка доступности и состояния сервиса OpenViking
|
|
154
194
|
*/
|
|
155
195
|
async checkHealth() {
|
|
196
|
+
if (this.isProxy()) {
|
|
197
|
+
try {
|
|
198
|
+
const res = await fetch(`${this.endpoint}/health`, {
|
|
199
|
+
method: "GET",
|
|
200
|
+
headers: this.getHeaders()
|
|
201
|
+
});
|
|
202
|
+
if (!res.ok) {
|
|
203
|
+
return {
|
|
204
|
+
ok: false,
|
|
205
|
+
error: `HTTP ${res.status}: ${res.statusText}`
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
const body = await res.json().catch(() => ({}));
|
|
209
|
+
const isOk = body.ok !== false && body.status !== "error" && (body.ok === true || body.status === "ok" || body.status === "healthy" || res.ok);
|
|
210
|
+
return {
|
|
211
|
+
ok: isOk,
|
|
212
|
+
version: typeof body.version === "string" ? body.version : void 0,
|
|
213
|
+
storage: typeof body.storage === "string" ? body.storage : void 0
|
|
214
|
+
};
|
|
215
|
+
} catch (err) {
|
|
216
|
+
return {
|
|
217
|
+
ok: false,
|
|
218
|
+
error: err instanceof Error ? err.message : String(err)
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
}
|
|
156
222
|
try {
|
|
157
223
|
const res = await fetch(`${this.endpoint}/health`, {
|
|
158
224
|
method: "GET",
|
|
@@ -179,12 +245,58 @@ var OpenVikingClient = class {
|
|
|
179
245
|
}
|
|
180
246
|
}
|
|
181
247
|
/**
|
|
182
|
-
*
|
|
183
|
-
*
|
|
248
|
+
* Чтение метаданных сессии с явной причиной неудачи.
|
|
249
|
+
*
|
|
250
|
+
* Демон может работать с `auth_mode: api_key`: тогда `/health` остаётся
|
|
251
|
+
* открытым, а сессия отвечает 401. Схлопывать это в «нет данных» нельзя —
|
|
252
|
+
* иначе интерфейс покажет живой индикатор рядом с нулями и умолчит о том,
|
|
253
|
+
* что счётчики просто недоступны.
|
|
184
254
|
*/
|
|
185
|
-
async
|
|
255
|
+
async readSession(sessionId) {
|
|
186
256
|
if (!sessionId || !sessionId.trim()) {
|
|
187
|
-
return
|
|
257
|
+
return { status: "missing" };
|
|
258
|
+
}
|
|
259
|
+
if (this.isProxy()) {
|
|
260
|
+
try {
|
|
261
|
+
const res = await fetch(
|
|
262
|
+
`${this.endpoint}/session?id=${encodeURIComponent(sessionId.trim())}`,
|
|
263
|
+
{
|
|
264
|
+
method: "GET",
|
|
265
|
+
headers: this.getHeaders()
|
|
266
|
+
}
|
|
267
|
+
);
|
|
268
|
+
if (res.status === 401 || res.status === 403) {
|
|
269
|
+
return { status: "unauthorized" };
|
|
270
|
+
}
|
|
271
|
+
if (!res.ok) {
|
|
272
|
+
return { status: "error", detail: `HTTP ${res.status}` };
|
|
273
|
+
}
|
|
274
|
+
const data = await res.json();
|
|
275
|
+
if (data.status === "unauthorized") return { status: "unauthorized" };
|
|
276
|
+
if (data.status === "missing") return { status: "missing" };
|
|
277
|
+
if (data.status === "unreachable")
|
|
278
|
+
return {
|
|
279
|
+
status: "unreachable",
|
|
280
|
+
detail: typeof data.detail === "string" ? data.detail : void 0
|
|
281
|
+
};
|
|
282
|
+
if (data.status === "error")
|
|
283
|
+
return {
|
|
284
|
+
status: "error",
|
|
285
|
+
detail: typeof data.detail === "string" ? data.detail : void 0
|
|
286
|
+
};
|
|
287
|
+
if (data.status === "ok" && data.session) {
|
|
288
|
+
return {
|
|
289
|
+
status: "ok",
|
|
290
|
+
session: data.session
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
return { status: "error", detail: "malformed response from proxy" };
|
|
294
|
+
} catch (err) {
|
|
295
|
+
return {
|
|
296
|
+
status: "unreachable",
|
|
297
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
298
|
+
};
|
|
299
|
+
}
|
|
188
300
|
}
|
|
189
301
|
const candidates = this.getCandidateSessionIds(sessionId);
|
|
190
302
|
for (const candidateId of candidates) {
|
|
@@ -199,30 +311,48 @@ var OpenVikingClient = class {
|
|
|
199
311
|
if (res.status === 404) {
|
|
200
312
|
continue;
|
|
201
313
|
}
|
|
314
|
+
if (res.status === 401 || res.status === 403) {
|
|
315
|
+
return { status: "unauthorized" };
|
|
316
|
+
}
|
|
202
317
|
if (!res.ok) {
|
|
203
|
-
return
|
|
318
|
+
return { status: "error", detail: `HTTP ${res.status}` };
|
|
204
319
|
}
|
|
205
320
|
const data = await res.json();
|
|
206
321
|
const raw = data?.result ?? data?.data ?? data;
|
|
207
322
|
if (!raw || typeof raw !== "object") {
|
|
208
|
-
return
|
|
323
|
+
return { status: "error", detail: "malformed response body" };
|
|
209
324
|
}
|
|
210
325
|
this.resolvedSessionIds.set(sessionId.trim(), candidateId);
|
|
211
326
|
return {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
327
|
+
status: "ok",
|
|
328
|
+
session: {
|
|
329
|
+
session_id: typeof raw.session_id === "string" ? raw.session_id : candidateId,
|
|
330
|
+
peer_id: typeof raw.peer_id === "string" ? raw.peer_id : void 0,
|
|
331
|
+
pending_tokens: typeof raw.pending_tokens === "number" ? raw.pending_tokens : 0,
|
|
332
|
+
message_count: typeof raw.message_count === "number" ? raw.message_count : void 0,
|
|
333
|
+
commit_count: typeof raw.commit_count === "number" ? raw.commit_count : void 0,
|
|
334
|
+
last_commit_at: typeof raw.last_commit_at === "string" ? raw.last_commit_at : typeof raw.last_commit === "string" ? raw.last_commit : void 0,
|
|
335
|
+
created_at: typeof raw.created_at === "string" ? raw.created_at : void 0,
|
|
336
|
+
updated_at: typeof raw.updated_at === "string" ? raw.updated_at : void 0
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
} catch (err) {
|
|
340
|
+
return {
|
|
341
|
+
status: "unreachable",
|
|
342
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
220
343
|
};
|
|
221
|
-
} catch {
|
|
222
|
-
return null;
|
|
223
344
|
}
|
|
224
345
|
}
|
|
225
|
-
return
|
|
346
|
+
return { status: "missing" };
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Получение метаданных сессии по идентификатору.
|
|
350
|
+
* Обёртка над {@link readSession} для вызывающих, которым причина неудачи
|
|
351
|
+
* не нужна: любая неудача сводится к null.
|
|
352
|
+
*/
|
|
353
|
+
async fetchSession(sessionId) {
|
|
354
|
+
const result = await this.readSession(sessionId);
|
|
355
|
+
return result.status === "ok" ? result.session : null;
|
|
226
356
|
}
|
|
227
357
|
/**
|
|
228
358
|
* Алиас для fetchSession
|
|
@@ -237,6 +367,31 @@ var OpenVikingClient = class {
|
|
|
237
367
|
if (!sessionId || !sessionId.trim()) {
|
|
238
368
|
return { ok: false, error: "Missing sessionId" };
|
|
239
369
|
}
|
|
370
|
+
if (this.isProxy()) {
|
|
371
|
+
try {
|
|
372
|
+
const res = await fetch(`${this.endpoint}/session/commit`, {
|
|
373
|
+
method: "POST",
|
|
374
|
+
headers: this.getHeaders(),
|
|
375
|
+
body: JSON.stringify({
|
|
376
|
+
sessionId: sessionId.trim(),
|
|
377
|
+
...options ?? { keep_recent_count: 10 }
|
|
378
|
+
})
|
|
379
|
+
});
|
|
380
|
+
if (!res.ok) {
|
|
381
|
+
return { ok: false, error: `HTTP ${res.status}` };
|
|
382
|
+
}
|
|
383
|
+
const data = await res.json().catch(() => ({}));
|
|
384
|
+
return {
|
|
385
|
+
ok: data.ok === true,
|
|
386
|
+
error: typeof data.error === "string" ? data.error : void 0
|
|
387
|
+
};
|
|
388
|
+
} catch (err) {
|
|
389
|
+
return {
|
|
390
|
+
ok: false,
|
|
391
|
+
error: err instanceof Error ? err.message : String(err)
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
}
|
|
240
395
|
const candidates = this.getCandidateSessionIds(sessionId);
|
|
241
396
|
const bodyPayload = JSON.stringify(options ?? { keep_recent_count: 10 });
|
|
242
397
|
let lastError = "Session commit failed";
|
|
@@ -288,6 +443,45 @@ function commitSession(sessionId, options, endpoint, apiKey) {
|
|
|
288
443
|
return client.commitSession(sessionId, options);
|
|
289
444
|
}
|
|
290
445
|
|
|
446
|
+
// src/client/theme.ts
|
|
447
|
+
var THEME = {
|
|
448
|
+
/** Фон всплывающей панели — тот же, что у меню и диалогов DSH. */
|
|
449
|
+
panelSurface: "--dsw-specific-menu",
|
|
450
|
+
/** Тень панели. */
|
|
451
|
+
panelElevation: "--dsw-elevation-prominent",
|
|
452
|
+
/** Контур панели; задаётся через переменную тени, а не через border. */
|
|
453
|
+
panelStroke: "--dsw-alias-border-l1",
|
|
454
|
+
/** Заголовки и акцентный текст. */
|
|
455
|
+
labelPrimary: "--dsw-alias-label-primary",
|
|
456
|
+
/** Основной текст панели. */
|
|
457
|
+
labelSecondary: "--dsw-alias-label-secondary",
|
|
458
|
+
/** Приглушённый текст: подписи, значения, текст чипа в покое. */
|
|
459
|
+
labelTertiary: "--dsw-alias-label-tertiary",
|
|
460
|
+
/** Разделительная линия внутри панели. */
|
|
461
|
+
hairline: "--dsw-alias-border-l2",
|
|
462
|
+
/** Подсветка интерактивного элемента под курсором. */
|
|
463
|
+
hoverBackground: "--dsw-alias-interactive-bg-hover",
|
|
464
|
+
/** Подсветка нажатого элемента. */
|
|
465
|
+
activeBackground: "--dsw-alias-interactive-bg-active",
|
|
466
|
+
/** Демон доступен. */
|
|
467
|
+
stateSuccess: "--dsw-alias-state-success-primary",
|
|
468
|
+
/** Демон недоступен или сессия нечитаема. */
|
|
469
|
+
stateError: "--dsw-alias-state-error-primary",
|
|
470
|
+
/** Идёт коммит, либо накоплено близко к порогу. */
|
|
471
|
+
stateWarning: "--dsw-alias-state-warn-primary",
|
|
472
|
+
/** Утопленная поверхность: дорожка прогресс-бара. */
|
|
473
|
+
insetSurface: "--dsw-alias-bg-layer-2",
|
|
474
|
+
/** Заливка основной кнопки действий. */
|
|
475
|
+
buttonPrimaryFill: "--dsw-alias-button-primary-fill",
|
|
476
|
+
/** Цвет текста на основной кнопке действий. */
|
|
477
|
+
buttonPrimaryText: "--dsw-alias-label-primary-inverted",
|
|
478
|
+
/** Моноширинный шрифт для идентификаторов и путей. */
|
|
479
|
+
fontMono: "--dsw-font-markdown-code-font-family"
|
|
480
|
+
};
|
|
481
|
+
function themeVar(role) {
|
|
482
|
+
return `var(${THEME[role]})`;
|
|
483
|
+
}
|
|
484
|
+
|
|
291
485
|
// src/client/recallParser.ts
|
|
292
486
|
var KNOWN_CATEGORIES = /* @__PURE__ */ new Set([
|
|
293
487
|
"preferences",
|
|
@@ -596,6 +790,15 @@ function parseRecalledMemories(input) {
|
|
|
596
790
|
// src/client/OpenVikingStatusPopover.tsx
|
|
597
791
|
var import_react = require("react");
|
|
598
792
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
793
|
+
function dshIcon(name2) {
|
|
794
|
+
try {
|
|
795
|
+
const primitives = typeof require === "function" ? require("@deepseek-ai/dsh-client-ui-primitives") : null;
|
|
796
|
+
const icon = primitives?.[name2];
|
|
797
|
+
return typeof icon === "function" ? icon : null;
|
|
798
|
+
} catch {
|
|
799
|
+
return null;
|
|
800
|
+
}
|
|
801
|
+
}
|
|
599
802
|
function getProgressBarPercent(pendingTokens, threshold = COMMIT_THRESHOLD) {
|
|
600
803
|
if (!threshold || threshold <= 0) return 0;
|
|
601
804
|
const ratio = (pendingTokens || 0) / threshold;
|
|
@@ -603,9 +806,14 @@ function getProgressBarPercent(pendingTokens, threshold = COMMIT_THRESHOLD) {
|
|
|
603
806
|
}
|
|
604
807
|
function getProgressBarColor(percent) {
|
|
605
808
|
if (percent >= 80) {
|
|
606
|
-
return "
|
|
809
|
+
return themeVar("stateWarning");
|
|
607
810
|
}
|
|
608
|
-
return "
|
|
811
|
+
return themeVar("stateSuccess");
|
|
812
|
+
}
|
|
813
|
+
function formatDaemonVersion(version) {
|
|
814
|
+
const value = version?.trim();
|
|
815
|
+
if (!value) return void 0;
|
|
816
|
+
return /^v/i.test(value) ? value : `v${value}`;
|
|
609
817
|
}
|
|
610
818
|
function formatRelativeTime(isoOrTimestamp, now = Date.now()) {
|
|
611
819
|
if (!isoOrTimestamp) return void 0;
|
|
@@ -647,39 +855,8 @@ function truncateSessionId(id, maxLen = 16) {
|
|
|
647
855
|
if (id.length <= maxLen) return id;
|
|
648
856
|
return `${id.slice(0, maxLen)}...`;
|
|
649
857
|
}
|
|
650
|
-
function getCategoryBadgeStyle(
|
|
651
|
-
|
|
652
|
-
case "preferences":
|
|
653
|
-
return {
|
|
654
|
-
backgroundColor: "rgba(168, 85, 247, 0.15)",
|
|
655
|
-
color: "var(--dsw-status-purple, #c084fc)"
|
|
656
|
-
};
|
|
657
|
-
case "entities":
|
|
658
|
-
return {
|
|
659
|
-
backgroundColor: "rgba(59, 130, 246, 0.15)",
|
|
660
|
-
color: "var(--dsw-status-info, #60a5fa)"
|
|
661
|
-
};
|
|
662
|
-
case "skills":
|
|
663
|
-
return {
|
|
664
|
-
backgroundColor: "rgba(236, 72, 153, 0.15)",
|
|
665
|
-
color: "var(--dsw-status-pink, #f472b6)"
|
|
666
|
-
};
|
|
667
|
-
case "events":
|
|
668
|
-
return {
|
|
669
|
-
backgroundColor: "rgba(245, 158, 11, 0.15)",
|
|
670
|
-
color: "var(--dsw-status-warning, #fbbf24)"
|
|
671
|
-
};
|
|
672
|
-
case "resources":
|
|
673
|
-
return {
|
|
674
|
-
backgroundColor: "rgba(20, 184, 166, 0.15)",
|
|
675
|
-
color: "var(--dsw-status-teal, #2dd4bf)"
|
|
676
|
-
};
|
|
677
|
-
default:
|
|
678
|
-
return {
|
|
679
|
-
backgroundColor: "rgba(148, 163, 184, 0.15)",
|
|
680
|
-
color: "var(--dsw-text-muted, #94a3b8)"
|
|
681
|
-
};
|
|
682
|
-
}
|
|
858
|
+
function getCategoryBadgeStyle(_category) {
|
|
859
|
+
return { color: themeVar("labelTertiary") };
|
|
683
860
|
}
|
|
684
861
|
function handleEscapeKey(event, onClose) {
|
|
685
862
|
if (event.key === "Escape") {
|
|
@@ -692,6 +869,7 @@ function OpenVikingStatusPopover({
|
|
|
692
869
|
sessionId,
|
|
693
870
|
health,
|
|
694
871
|
sessionData,
|
|
872
|
+
sessionRead,
|
|
695
873
|
recalledResult,
|
|
696
874
|
endpoint,
|
|
697
875
|
isCommitting = false,
|
|
@@ -711,13 +889,17 @@ function OpenVikingStatusPopover({
|
|
|
711
889
|
};
|
|
712
890
|
}, []);
|
|
713
891
|
const isOnline = health?.ok === true;
|
|
714
|
-
const
|
|
892
|
+
const sessionUnreadable = isOnline && sessionRead != null && sessionRead.status !== "ok";
|
|
893
|
+
const unauthorized = sessionRead?.status === "unauthorized";
|
|
894
|
+
const statusColor = isOnline ? sessionUnreadable ? themeVar("stateWarning") : themeVar("stateSuccess") : themeVar("stateError");
|
|
715
895
|
const displaySessionId = sessionData?.session_id || sessionId || "";
|
|
716
896
|
const pendingTokens = sessionData?.pending_tokens ?? 0;
|
|
717
897
|
const progressPercent = getProgressBarPercent(pendingTokens);
|
|
718
898
|
const progressBarColor = getProgressBarColor(progressPercent);
|
|
719
899
|
const memoryItems = recalledResult?.items || [];
|
|
720
900
|
const recalledCount = recalledResult?.recalledCount ?? memoryItems.length;
|
|
901
|
+
const CopyIcon = dshIcon("IconCopyOutline16");
|
|
902
|
+
const CheckIcon = dshIcon("IconCheckOutline16");
|
|
721
903
|
const handleCopySessionId = (0, import_react.useCallback)(() => {
|
|
722
904
|
if (!displaySessionId) return;
|
|
723
905
|
if (typeof navigator !== "undefined" && navigator.clipboard) {
|
|
@@ -733,7 +915,15 @@ function OpenVikingStatusPopover({
|
|
|
733
915
|
}, 1500);
|
|
734
916
|
}
|
|
735
917
|
}, [displaySessionId]);
|
|
736
|
-
const isCommitDisabled = isCommitting || !isOnline || pendingTokens === 0;
|
|
918
|
+
const isCommitDisabled = isCommitting || !isOnline || sessionUnreadable || pendingTokens === 0;
|
|
919
|
+
const pendingLabel = sessionUnreadable ? "unavailable" : `${pendingTokens.toLocaleString()} / ${COMMIT_THRESHOLD.toLocaleString()}`;
|
|
920
|
+
const rowStyle = {
|
|
921
|
+
display: "flex",
|
|
922
|
+
justifyContent: "space-between",
|
|
923
|
+
alignItems: "center"
|
|
924
|
+
};
|
|
925
|
+
const mutedStyle = { color: themeVar("labelTertiary") };
|
|
926
|
+
const monoStyle = { fontFamily: themeVar("fontMono") };
|
|
737
927
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
738
928
|
"div",
|
|
739
929
|
{
|
|
@@ -744,17 +934,23 @@ function OpenVikingStatusPopover({
|
|
|
744
934
|
position: "absolute",
|
|
745
935
|
bottom: "calc(100% + 8px)",
|
|
746
936
|
right: 0,
|
|
747
|
-
|
|
748
|
-
backgroundColor: "var(--dsw-surface-overlay, #1e293b)",
|
|
749
|
-
border: "1px solid var(--dsw-border-default, #334155)",
|
|
750
|
-
borderRadius: "8px",
|
|
751
|
-
padding: "12px",
|
|
752
|
-
boxShadow: "0 10px 25px -5px rgba(0, 0, 0, 0.5)",
|
|
753
|
-
zIndex: 1e3,
|
|
754
|
-
fontSize: "12px",
|
|
755
|
-
color: "var(--dsw-text-default, #f1f5f9)",
|
|
756
|
-
fontFamily: "var(--dsw-font-sans, system-ui, sans-serif)",
|
|
937
|
+
zIndex: 1100,
|
|
757
938
|
boxSizing: "border-box",
|
|
939
|
+
width: "max-content",
|
|
940
|
+
minWidth: "min(300px, 100vw - 24px)",
|
|
941
|
+
maxWidth: "min(440px, 100vw - 24px)",
|
|
942
|
+
background: themeVar("panelSurface"),
|
|
943
|
+
boxShadow: themeVar("panelElevation"),
|
|
944
|
+
color: themeVar("labelSecondary"),
|
|
945
|
+
cursor: "default",
|
|
946
|
+
border: 0,
|
|
947
|
+
borderRadius: "12px",
|
|
948
|
+
padding: "16px",
|
|
949
|
+
fontSize: "12px",
|
|
950
|
+
lineHeight: "18px",
|
|
951
|
+
...{
|
|
952
|
+
"--dsw-elevation-stroke-color": themeVar("panelStroke")
|
|
953
|
+
},
|
|
758
954
|
...style
|
|
759
955
|
},
|
|
760
956
|
children: [
|
|
@@ -765,58 +961,41 @@ function OpenVikingStatusPopover({
|
|
|
765
961
|
style: {
|
|
766
962
|
display: "flex",
|
|
767
963
|
justifyContent: "space-between",
|
|
768
|
-
|
|
769
|
-
marginBottom: "
|
|
770
|
-
|
|
771
|
-
|
|
964
|
+
gap: "16px",
|
|
965
|
+
marginBottom: "8px",
|
|
966
|
+
color: themeVar("labelPrimary"),
|
|
967
|
+
fontWeight: 500
|
|
772
968
|
},
|
|
773
969
|
children: [
|
|
774
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
{
|
|
778
|
-
style: {
|
|
779
|
-
fontWeight: 600,
|
|
780
|
-
fontSize: "13px",
|
|
781
|
-
color: "var(--dsw-text-default, #f1f5f9)"
|
|
782
|
-
},
|
|
783
|
-
children: "OpenViking Memory"
|
|
784
|
-
}
|
|
785
|
-
),
|
|
970
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { minWidth: 0 }, children: [
|
|
971
|
+
"OpenViking Memory",
|
|
972
|
+
" ",
|
|
786
973
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
787
|
-
"
|
|
974
|
+
"span",
|
|
788
975
|
{
|
|
789
976
|
"data-testid": "endpoint-label",
|
|
790
|
-
style: {
|
|
791
|
-
fontSize: "10px",
|
|
792
|
-
color: "var(--dsw-text-muted, #94a3b8)",
|
|
793
|
-
fontFamily: "var(--dsw-font-mono, monospace)",
|
|
794
|
-
marginTop: "1px"
|
|
795
|
-
},
|
|
977
|
+
style: { ...mutedStyle, ...monoStyle, fontWeight: 400 },
|
|
796
978
|
children: formatEndpoint(endpoint)
|
|
797
979
|
}
|
|
798
980
|
)
|
|
799
981
|
] }),
|
|
800
982
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
801
|
-
"
|
|
983
|
+
"span",
|
|
802
984
|
{
|
|
803
985
|
"data-testid": "status-badge",
|
|
804
986
|
style: {
|
|
805
987
|
display: "inline-flex",
|
|
806
988
|
alignItems: "center",
|
|
807
|
-
gap: "
|
|
808
|
-
fontSize: "10px",
|
|
809
|
-
padding: "2px 7px",
|
|
810
|
-
borderRadius: "4px",
|
|
811
|
-
backgroundColor: isOnline ? "rgba(52, 211, 153, 0.15)" : "rgba(248, 113, 113, 0.15)",
|
|
989
|
+
gap: "6px",
|
|
812
990
|
color: statusColor,
|
|
813
|
-
|
|
991
|
+
flexShrink: 0
|
|
814
992
|
},
|
|
815
993
|
children: [
|
|
816
994
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
817
995
|
"span",
|
|
818
996
|
{
|
|
819
997
|
"data-testid": "status-badge-dot",
|
|
998
|
+
"aria-hidden": "true",
|
|
820
999
|
style: {
|
|
821
1000
|
width: "6px",
|
|
822
1001
|
height: "6px",
|
|
@@ -826,13 +1005,27 @@ function OpenVikingStatusPopover({
|
|
|
826
1005
|
}
|
|
827
1006
|
}
|
|
828
1007
|
),
|
|
829
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: isOnline ?
|
|
1008
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: isOnline ? [
|
|
1009
|
+
"ONLINE",
|
|
1010
|
+
formatDaemonVersion(health?.version),
|
|
1011
|
+
sessionUnreadable ? "\xB7 no session access" : null
|
|
1012
|
+
].filter(Boolean).join(" ") : "OFFLINE" })
|
|
830
1013
|
]
|
|
831
1014
|
}
|
|
832
1015
|
)
|
|
833
1016
|
]
|
|
834
1017
|
}
|
|
835
1018
|
),
|
|
1019
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1020
|
+
"div",
|
|
1021
|
+
{
|
|
1022
|
+
style: {
|
|
1023
|
+
borderTop: `.5px solid ${themeVar("hairline")}`,
|
|
1024
|
+
marginBottom: "10px"
|
|
1025
|
+
},
|
|
1026
|
+
"aria-hidden": "true"
|
|
1027
|
+
}
|
|
1028
|
+
),
|
|
836
1029
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
837
1030
|
"div",
|
|
838
1031
|
{
|
|
@@ -843,142 +1036,88 @@ function OpenVikingStatusPopover({
|
|
|
843
1036
|
marginBottom: "10px"
|
|
844
1037
|
},
|
|
845
1038
|
children: [
|
|
846
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
847
|
-
"
|
|
848
|
-
{
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
alignItems: "center"
|
|
920
|
-
},
|
|
921
|
-
children: [
|
|
922
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: "var(--dsw-text-muted, #94a3b8)" }, children: "Peer ID:" }),
|
|
923
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
924
|
-
"span",
|
|
925
|
-
{
|
|
926
|
-
"data-testid": "peer-id-value",
|
|
927
|
-
style: {
|
|
928
|
-
maxWidth: "180px",
|
|
929
|
-
overflow: "hidden",
|
|
930
|
-
textOverflow: "ellipsis",
|
|
931
|
-
whiteSpace: "nowrap",
|
|
932
|
-
fontFamily: "var(--dsw-font-mono, monospace)"
|
|
933
|
-
},
|
|
934
|
-
title: sessionData.peer_id,
|
|
935
|
-
children: sessionData.peer_id
|
|
936
|
-
}
|
|
937
|
-
)
|
|
938
|
-
]
|
|
939
|
-
}
|
|
940
|
-
),
|
|
941
|
-
sessionData?.last_commit_at && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
942
|
-
"div",
|
|
943
|
-
{
|
|
944
|
-
style: {
|
|
945
|
-
display: "flex",
|
|
946
|
-
justifyContent: "space-between",
|
|
947
|
-
alignItems: "center"
|
|
948
|
-
},
|
|
949
|
-
children: [
|
|
950
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: "var(--dsw-text-muted, #94a3b8)" }, children: "Last Commit:" }),
|
|
951
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
952
|
-
"span",
|
|
953
|
-
{
|
|
954
|
-
"data-testid": "last-commit-value",
|
|
955
|
-
title: sessionData.last_commit_at,
|
|
956
|
-
style: { color: "var(--dsw-text-default, #e2e8f0)" },
|
|
957
|
-
children: formatRelativeTime(sessionData.last_commit_at) || sessionData.last_commit_at
|
|
958
|
-
}
|
|
959
|
-
)
|
|
960
|
-
]
|
|
961
|
-
}
|
|
962
|
-
)
|
|
1039
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: rowStyle, children: [
|
|
1040
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: mutedStyle, children: "Session ID:" }),
|
|
1041
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
|
|
1042
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1043
|
+
"span",
|
|
1044
|
+
{
|
|
1045
|
+
"data-testid": "session-id-value",
|
|
1046
|
+
role: "button",
|
|
1047
|
+
tabIndex: 0,
|
|
1048
|
+
onKeyDown: (e) => {
|
|
1049
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
1050
|
+
e.preventDefault();
|
|
1051
|
+
handleCopySessionId();
|
|
1052
|
+
}
|
|
1053
|
+
},
|
|
1054
|
+
"aria-label": "Click to copy Session ID",
|
|
1055
|
+
style: { ...monoStyle, cursor: "pointer" },
|
|
1056
|
+
title: displaySessionId,
|
|
1057
|
+
onClick: handleCopySessionId,
|
|
1058
|
+
children: truncateSessionId(displaySessionId)
|
|
1059
|
+
}
|
|
1060
|
+
),
|
|
1061
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1062
|
+
"button",
|
|
1063
|
+
{
|
|
1064
|
+
type: "button",
|
|
1065
|
+
"data-testid": "copy-session-btn",
|
|
1066
|
+
onClick: handleCopySessionId,
|
|
1067
|
+
title: copied ? "Copied!" : "Copy Session ID",
|
|
1068
|
+
"aria-label": copied ? "Copied!" : "Copy Session ID",
|
|
1069
|
+
style: {
|
|
1070
|
+
background: "none",
|
|
1071
|
+
border: "none",
|
|
1072
|
+
cursor: "pointer",
|
|
1073
|
+
padding: "2px",
|
|
1074
|
+
display: "inline-flex",
|
|
1075
|
+
alignItems: "center",
|
|
1076
|
+
color: copied ? themeVar("stateSuccess") : themeVar("labelTertiary")
|
|
1077
|
+
},
|
|
1078
|
+
children: copied ? CheckIcon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CheckIcon, { size: 14 }) : CopyIcon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CopyIcon, { size: 14 })
|
|
1079
|
+
}
|
|
1080
|
+
)
|
|
1081
|
+
] })
|
|
1082
|
+
] }),
|
|
1083
|
+
sessionData?.peer_id && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: rowStyle, children: [
|
|
1084
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: mutedStyle, children: "Peer ID:" }),
|
|
1085
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1086
|
+
"span",
|
|
1087
|
+
{
|
|
1088
|
+
"data-testid": "peer-id-value",
|
|
1089
|
+
style: {
|
|
1090
|
+
...monoStyle,
|
|
1091
|
+
maxWidth: "180px",
|
|
1092
|
+
overflow: "hidden",
|
|
1093
|
+
textOverflow: "ellipsis",
|
|
1094
|
+
whiteSpace: "nowrap"
|
|
1095
|
+
},
|
|
1096
|
+
title: sessionData.peer_id,
|
|
1097
|
+
children: sessionData.peer_id
|
|
1098
|
+
}
|
|
1099
|
+
)
|
|
1100
|
+
] }),
|
|
1101
|
+
sessionData?.last_commit_at && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: rowStyle, children: [
|
|
1102
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: mutedStyle, children: "Last Commit:" }),
|
|
1103
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1104
|
+
"span",
|
|
1105
|
+
{
|
|
1106
|
+
"data-testid": "last-commit-value",
|
|
1107
|
+
title: sessionData.last_commit_at,
|
|
1108
|
+
children: formatRelativeTime(sessionData.last_commit_at) || sessionData.last_commit_at
|
|
1109
|
+
}
|
|
1110
|
+
)
|
|
1111
|
+
] })
|
|
963
1112
|
]
|
|
964
1113
|
}
|
|
965
1114
|
),
|
|
966
1115
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginBottom: "12px" }, children: [
|
|
967
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
968
|
-
"
|
|
969
|
-
{
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
justifyContent: "space-between",
|
|
973
|
-
marginBottom: "4px"
|
|
974
|
-
},
|
|
975
|
-
children: [
|
|
976
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: "var(--dsw-text-muted, #94a3b8)" }, children: "Pending Tokens:" }),
|
|
977
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "data-testid": "pending-tokens-label", style: { fontWeight: 500 }, children: `${pendingTokens.toLocaleString()} / ${COMMIT_THRESHOLD.toLocaleString()}` })
|
|
978
|
-
]
|
|
979
|
-
}
|
|
980
|
-
),
|
|
981
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1116
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...rowStyle, marginBottom: "4px" }, children: [
|
|
1117
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: mutedStyle, children: "Pending Tokens:" }),
|
|
1118
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "data-testid": "pending-tokens-label", children: pendingLabel })
|
|
1119
|
+
] }),
|
|
1120
|
+
!sessionUnreadable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
982
1121
|
"div",
|
|
983
1122
|
{
|
|
984
1123
|
"data-testid": "progress-bar-track",
|
|
@@ -986,7 +1125,7 @@ function OpenVikingStatusPopover({
|
|
|
986
1125
|
width: "100%",
|
|
987
1126
|
height: "6px",
|
|
988
1127
|
borderRadius: "3px",
|
|
989
|
-
backgroundColor: "
|
|
1128
|
+
backgroundColor: themeVar("insetSurface"),
|
|
990
1129
|
overflow: "hidden"
|
|
991
1130
|
},
|
|
992
1131
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -1004,30 +1143,34 @@ function OpenVikingStatusPopover({
|
|
|
1004
1143
|
}
|
|
1005
1144
|
)
|
|
1006
1145
|
] }),
|
|
1146
|
+
sessionUnreadable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1147
|
+
"div",
|
|
1148
|
+
{
|
|
1149
|
+
"data-testid": "session-unreadable-notice",
|
|
1150
|
+
style: {
|
|
1151
|
+
marginBottom: "12px",
|
|
1152
|
+
color: themeVar("labelTertiary")
|
|
1153
|
+
},
|
|
1154
|
+
children: unauthorized ? "The daemon requires an API key. Set openviking_api_key in localStorage to read session counters." : "Session counters are unavailable right now."
|
|
1155
|
+
}
|
|
1156
|
+
),
|
|
1007
1157
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginBottom: "12px" }, children: [
|
|
1008
1158
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1009
1159
|
"div",
|
|
1010
1160
|
{
|
|
1011
1161
|
style: {
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
marginBottom: "4px"
|
|
1162
|
+
marginBottom: "4px",
|
|
1163
|
+
color: themeVar("labelPrimary"),
|
|
1164
|
+
fontWeight: 500
|
|
1016
1165
|
},
|
|
1017
|
-
children:
|
|
1166
|
+
children: `Recalled Memories (${recalledCount})`
|
|
1018
1167
|
}
|
|
1019
1168
|
),
|
|
1020
1169
|
memoryItems.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1021
1170
|
"div",
|
|
1022
1171
|
{
|
|
1023
1172
|
"data-testid": "empty-memories-message",
|
|
1024
|
-
style: {
|
|
1025
|
-
padding: "8px 0",
|
|
1026
|
-
color: "var(--dsw-text-muted, #94a3b8)",
|
|
1027
|
-
fontStyle: "italic",
|
|
1028
|
-
fontSize: "11px",
|
|
1029
|
-
textAlign: "center"
|
|
1030
|
-
},
|
|
1173
|
+
style: { ...mutedStyle, padding: "4px 0" },
|
|
1031
1174
|
children: "No memories recalled in this session"
|
|
1032
1175
|
}
|
|
1033
1176
|
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -1051,11 +1194,7 @@ function OpenVikingStatusPopover({
|
|
|
1051
1194
|
display: "flex",
|
|
1052
1195
|
alignItems: "center",
|
|
1053
1196
|
gap: "6px",
|
|
1054
|
-
|
|
1055
|
-
borderRadius: "4px",
|
|
1056
|
-
backgroundColor: "rgba(255, 255, 255, 0.04)",
|
|
1057
|
-
border: "1px solid var(--dsw-border-subtle, rgba(255, 255, 255, 0.05))",
|
|
1058
|
-
fontSize: "11px"
|
|
1197
|
+
minWidth: 0
|
|
1059
1198
|
},
|
|
1060
1199
|
children: [
|
|
1061
1200
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -1063,10 +1202,6 @@ function OpenVikingStatusPopover({
|
|
|
1063
1202
|
{
|
|
1064
1203
|
"data-testid": "memory-category-badge",
|
|
1065
1204
|
style: {
|
|
1066
|
-
fontSize: "9px",
|
|
1067
|
-
fontWeight: 600,
|
|
1068
|
-
padding: "1px 4px",
|
|
1069
|
-
borderRadius: "3px",
|
|
1070
1205
|
textTransform: "uppercase",
|
|
1071
1206
|
flexShrink: 0,
|
|
1072
1207
|
...getCategoryBadgeStyle(item.category)
|
|
@@ -1078,21 +1213,7 @@ function OpenVikingStatusPopover({
|
|
|
1078
1213
|
"span",
|
|
1079
1214
|
{
|
|
1080
1215
|
"data-testid": "memory-source-badge",
|
|
1081
|
-
style: {
|
|
1082
|
-
fontSize: "9px",
|
|
1083
|
-
fontWeight: 600,
|
|
1084
|
-
padding: "1px 4px",
|
|
1085
|
-
borderRadius: "3px",
|
|
1086
|
-
textTransform: "uppercase",
|
|
1087
|
-
flexShrink: 0,
|
|
1088
|
-
...item.source === "profile" ? {
|
|
1089
|
-
backgroundColor: "rgba(99, 102, 241, 0.15)",
|
|
1090
|
-
color: "#818cf8"
|
|
1091
|
-
} : {
|
|
1092
|
-
backgroundColor: "rgba(16, 185, 129, 0.15)",
|
|
1093
|
-
color: "var(--dsw-status-success, #34d399)"
|
|
1094
|
-
}
|
|
1095
|
-
},
|
|
1216
|
+
style: { ...mutedStyle, flexShrink: 0 },
|
|
1096
1217
|
children: item.source
|
|
1097
1218
|
}
|
|
1098
1219
|
),
|
|
@@ -1101,12 +1222,10 @@ function OpenVikingStatusPopover({
|
|
|
1101
1222
|
{
|
|
1102
1223
|
"data-testid": "memory-leaf-name",
|
|
1103
1224
|
style: {
|
|
1104
|
-
flex: 1,
|
|
1105
1225
|
overflow: "hidden",
|
|
1106
1226
|
textOverflow: "ellipsis",
|
|
1107
1227
|
whiteSpace: "nowrap",
|
|
1108
|
-
|
|
1109
|
-
color: "var(--dsw-text-default, #f1f5f9)"
|
|
1228
|
+
minWidth: 0
|
|
1110
1229
|
},
|
|
1111
1230
|
children: formatMemoryLeafName(item.uri)
|
|
1112
1231
|
}
|
|
@@ -1122,16 +1241,7 @@ function OpenVikingStatusPopover({
|
|
|
1122
1241
|
"div",
|
|
1123
1242
|
{
|
|
1124
1243
|
"data-testid": "commit-error-message",
|
|
1125
|
-
style: {
|
|
1126
|
-
marginBottom: "8px",
|
|
1127
|
-
padding: "6px 8px",
|
|
1128
|
-
borderRadius: "4px",
|
|
1129
|
-
backgroundColor: "rgba(248, 113, 113, 0.1)",
|
|
1130
|
-
border: "1px solid var(--dsw-status-error, #f87171)",
|
|
1131
|
-
color: "var(--dsw-status-error, #f87171)",
|
|
1132
|
-
fontSize: "11px",
|
|
1133
|
-
wordBreak: "break-word"
|
|
1134
|
-
},
|
|
1244
|
+
style: { marginBottom: "8px", color: themeVar("stateError") },
|
|
1135
1245
|
children: commitError
|
|
1136
1246
|
}
|
|
1137
1247
|
),
|
|
@@ -1140,19 +1250,17 @@ function OpenVikingStatusPopover({
|
|
|
1140
1250
|
{
|
|
1141
1251
|
type: "button",
|
|
1142
1252
|
"data-testid": "commit-now-btn",
|
|
1143
|
-
onClick: () => onCommitNow?.(),
|
|
1253
|
+
onClick: () => void onCommitNow?.(),
|
|
1144
1254
|
disabled: isCommitDisabled,
|
|
1145
1255
|
style: {
|
|
1146
1256
|
width: "100%",
|
|
1147
|
-
padding: "
|
|
1148
|
-
borderRadius: "
|
|
1149
|
-
border:
|
|
1150
|
-
|
|
1151
|
-
color: isCommitDisabled ? "
|
|
1152
|
-
cursor: isCommitDisabled ? "
|
|
1153
|
-
|
|
1154
|
-
fontSize: "12px",
|
|
1155
|
-
transition: "all 0.15s ease",
|
|
1257
|
+
padding: "6px 10px",
|
|
1258
|
+
borderRadius: "8px",
|
|
1259
|
+
border: `.5px solid ${themeVar("hairline")}`,
|
|
1260
|
+
background: isCommitDisabled ? "transparent" : themeVar("hoverBackground"),
|
|
1261
|
+
color: isCommitDisabled ? themeVar("labelTertiary") : themeVar("labelPrimary"),
|
|
1262
|
+
cursor: isCommitDisabled ? "default" : "pointer",
|
|
1263
|
+
font: "inherit",
|
|
1156
1264
|
display: "flex",
|
|
1157
1265
|
alignItems: "center",
|
|
1158
1266
|
justifyContent: "center",
|
|
@@ -1162,12 +1270,13 @@ function OpenVikingStatusPopover({
|
|
|
1162
1270
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1163
1271
|
"span",
|
|
1164
1272
|
{
|
|
1273
|
+
"aria-hidden": "true",
|
|
1165
1274
|
style: {
|
|
1166
1275
|
display: "inline-block",
|
|
1167
1276
|
width: "10px",
|
|
1168
1277
|
height: "10px",
|
|
1169
1278
|
borderRadius: "50%",
|
|
1170
|
-
border:
|
|
1279
|
+
border: `2px solid ${themeVar("stateWarning")}`,
|
|
1171
1280
|
borderTopColor: "transparent",
|
|
1172
1281
|
animation: "ov-spin 1s linear infinite"
|
|
1173
1282
|
}
|
|
@@ -1199,11 +1308,15 @@ function formatTooltipTitle({
|
|
|
1199
1308
|
isOnline,
|
|
1200
1309
|
isCommitting = false,
|
|
1201
1310
|
recalledCount,
|
|
1202
|
-
pendingTokens
|
|
1311
|
+
pendingTokens,
|
|
1312
|
+
sessionUnreadable = false
|
|
1203
1313
|
}) {
|
|
1204
1314
|
if (!isOnline) {
|
|
1205
1315
|
return "OpenViking: Offline";
|
|
1206
1316
|
}
|
|
1317
|
+
if (sessionUnreadable) {
|
|
1318
|
+
return "OpenViking: session unreadable \u2014 the daemon requires an API key";
|
|
1319
|
+
}
|
|
1207
1320
|
const countLabel = `${recalledCount} recalled`;
|
|
1208
1321
|
const tokenLabel = `${(pendingTokens || 0).toLocaleString()} pending tokens`;
|
|
1209
1322
|
if (isCommitting) {
|
|
@@ -1211,36 +1324,69 @@ function formatTooltipTitle({
|
|
|
1211
1324
|
}
|
|
1212
1325
|
return `OpenViking: Online (${countLabel}, ${tokenLabel})`;
|
|
1213
1326
|
}
|
|
1214
|
-
function getStatusIndicatorColor(isOnline, isCommitting = false) {
|
|
1327
|
+
function getStatusIndicatorColor(isOnline, isCommitting = false, sessionUnreadable = false) {
|
|
1215
1328
|
if (!isOnline) {
|
|
1216
|
-
return "
|
|
1329
|
+
return themeVar("stateError");
|
|
1217
1330
|
}
|
|
1218
|
-
if (isCommitting) {
|
|
1219
|
-
return "
|
|
1331
|
+
if (isCommitting || sessionUnreadable) {
|
|
1332
|
+
return themeVar("stateWarning");
|
|
1220
1333
|
}
|
|
1221
|
-
return "
|
|
1334
|
+
return themeVar("stateSuccess");
|
|
1222
1335
|
}
|
|
1223
|
-
function
|
|
1224
|
-
if (
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1336
|
+
function chatNodesToText(nodes) {
|
|
1337
|
+
if (!nodes) return "";
|
|
1338
|
+
const source = Array.isArray(nodes) ? nodes : typeof nodes === "object" ? Object.values(nodes) : [];
|
|
1339
|
+
const parts = [];
|
|
1340
|
+
const visit = (value, depth = 0) => {
|
|
1341
|
+
if (depth > 4 || value === null || value === void 0) return;
|
|
1342
|
+
if (typeof value === "string") {
|
|
1343
|
+
parts.push(value);
|
|
1344
|
+
return;
|
|
1345
|
+
}
|
|
1346
|
+
if (Array.isArray(value)) {
|
|
1347
|
+
for (const item of value) visit(item, depth + 1);
|
|
1348
|
+
return;
|
|
1349
|
+
}
|
|
1350
|
+
if (typeof value === "object") {
|
|
1351
|
+
const record = value;
|
|
1352
|
+
for (const key of ["content", "text", "data", "body"]) {
|
|
1353
|
+
if (key in record) visit(record[key], depth + 1);
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
};
|
|
1357
|
+
for (const node of source) visit(node);
|
|
1358
|
+
return parts.join("\n");
|
|
1228
1359
|
}
|
|
1229
|
-
function
|
|
1230
|
-
|
|
1231
|
-
|
|
1360
|
+
function OpenVikingStatusChip(props) {
|
|
1361
|
+
const { useChat, ...rest } = props;
|
|
1362
|
+
if (useChat && rest.contextText === void 0 && rest.messages === void 0) {
|
|
1363
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChatReadBoundary, { fallback: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(StatusChipView, { ...rest }), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChatBackedStatusChip, { useChat, ...rest }) });
|
|
1232
1364
|
}
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1365
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(StatusChipView, { ...rest });
|
|
1366
|
+
}
|
|
1367
|
+
var ChatReadBoundary = class extends import_react2.default.Component {
|
|
1368
|
+
state = { failed: false };
|
|
1369
|
+
static getDerivedStateFromError() {
|
|
1370
|
+
return { failed: true };
|
|
1237
1371
|
}
|
|
1238
|
-
|
|
1239
|
-
return
|
|
1372
|
+
render() {
|
|
1373
|
+
return this.state.failed ? this.props.fallback : this.props.children;
|
|
1240
1374
|
}
|
|
1241
|
-
|
|
1375
|
+
};
|
|
1376
|
+
function ChatBackedStatusChip({
|
|
1377
|
+
useChat,
|
|
1378
|
+
...rest
|
|
1379
|
+
}) {
|
|
1380
|
+
const nodes = useChat((snapshot) => {
|
|
1381
|
+
try {
|
|
1382
|
+
return snapshot?.legacy?.nodes !== void 0 ? snapshot.legacy.nodes : snapshot?.nodes;
|
|
1383
|
+
} catch {
|
|
1384
|
+
return void 0;
|
|
1385
|
+
}
|
|
1386
|
+
});
|
|
1387
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(StatusChipView, { ...rest, messages: nodes });
|
|
1242
1388
|
}
|
|
1243
|
-
function
|
|
1389
|
+
function StatusChipView({
|
|
1244
1390
|
sessionId,
|
|
1245
1391
|
messages,
|
|
1246
1392
|
contextText,
|
|
@@ -1249,32 +1395,42 @@ function OpenVikingStatusChip({
|
|
|
1249
1395
|
className,
|
|
1250
1396
|
initialHealth,
|
|
1251
1397
|
initialSessionData,
|
|
1398
|
+
initialSessionRead,
|
|
1252
1399
|
initialOpen = false
|
|
1253
1400
|
}) {
|
|
1254
1401
|
const [health, setHealth] = (0, import_react2.useState)(
|
|
1255
1402
|
initialHealth ?? null
|
|
1256
1403
|
);
|
|
1257
|
-
const [
|
|
1258
|
-
|
|
1404
|
+
const [sessionRead, setSessionRead] = (0, import_react2.useState)(
|
|
1405
|
+
initialSessionRead ?? (initialSessionData ? { status: "ok", session: initialSessionData } : null)
|
|
1259
1406
|
);
|
|
1260
1407
|
const [isOpen, setIsOpen] = (0, import_react2.useState)(initialOpen);
|
|
1261
1408
|
const [isCommitting, setIsCommitting] = (0, import_react2.useState)(false);
|
|
1262
1409
|
const [commitError, setCommitError] = (0, import_react2.useState)(null);
|
|
1410
|
+
const [isHovered, setIsHovered] = (0, import_react2.useState)(false);
|
|
1411
|
+
const [statsHost, setStatsHost] = (0, import_react2.useState)(null);
|
|
1263
1412
|
const popoverRef = (0, import_react2.useRef)(null);
|
|
1264
1413
|
const apiClient = client ?? defaultOpenVikingClient;
|
|
1265
|
-
|
|
1266
|
-
if (
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
if (contextText && messages) {
|
|
1271
|
-
return [contextText, ...messages];
|
|
1414
|
+
(0, import_react2.useEffect)(() => {
|
|
1415
|
+
if (typeof document === "undefined") return;
|
|
1416
|
+
function findHost() {
|
|
1417
|
+
const el = document.querySelector("[data-composer-stats]");
|
|
1418
|
+
setStatsHost((prev) => prev !== el ? el : prev);
|
|
1272
1419
|
}
|
|
1273
|
-
|
|
1274
|
-
|
|
1420
|
+
findHost();
|
|
1421
|
+
const observer = new MutationObserver(() => {
|
|
1422
|
+
findHost();
|
|
1423
|
+
});
|
|
1424
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
1425
|
+
return () => observer.disconnect();
|
|
1426
|
+
}, []);
|
|
1427
|
+
const conversationText = (0, import_react2.useMemo)(() => {
|
|
1428
|
+
if (typeof contextText === "string") return contextText;
|
|
1429
|
+
return chatNodesToText(messages);
|
|
1430
|
+
}, [contextText, messages]);
|
|
1275
1431
|
const recalledResult = (0, import_react2.useMemo)(
|
|
1276
|
-
() => parseRecalledMemories(
|
|
1277
|
-
[
|
|
1432
|
+
() => parseRecalledMemories(conversationText),
|
|
1433
|
+
[conversationText]
|
|
1278
1434
|
);
|
|
1279
1435
|
const fetchStatus = (0, import_react2.useCallback)(async () => {
|
|
1280
1436
|
try {
|
|
@@ -1283,8 +1439,7 @@ function OpenVikingStatusChip({
|
|
|
1283
1439
|
if (!healthRes.ok) {
|
|
1284
1440
|
return;
|
|
1285
1441
|
}
|
|
1286
|
-
|
|
1287
|
-
setSessionData(session);
|
|
1442
|
+
setSessionRead(await apiClient.readSession(sessionId));
|
|
1288
1443
|
} catch {
|
|
1289
1444
|
setHealth({ ok: false });
|
|
1290
1445
|
}
|
|
@@ -1337,26 +1492,29 @@ function OpenVikingStatusChip({
|
|
|
1337
1492
|
}
|
|
1338
1493
|
};
|
|
1339
1494
|
const isOnline = health?.ok === true;
|
|
1495
|
+
const sessionData = sessionRead?.status === "ok" ? sessionRead.session : null;
|
|
1496
|
+
const sessionUnreadable = isOnline && sessionRead !== null && sessionRead.status !== "ok";
|
|
1340
1497
|
const pendingTokens = sessionData?.pending_tokens ?? 0;
|
|
1341
|
-
const pendingTokensK = Math.round(pendingTokens / 1e3);
|
|
1342
1498
|
const recalledCount = recalledResult.recalledCount;
|
|
1343
|
-
const statusColor = getStatusIndicatorColor(
|
|
1344
|
-
|
|
1499
|
+
const statusColor = getStatusIndicatorColor(
|
|
1500
|
+
isOnline,
|
|
1501
|
+
isCommitting,
|
|
1502
|
+
sessionUnreadable
|
|
1503
|
+
);
|
|
1345
1504
|
const tooltipTitle = formatTooltipTitle({
|
|
1346
1505
|
isOnline,
|
|
1347
1506
|
isCommitting,
|
|
1348
1507
|
recalledCount,
|
|
1349
|
-
pendingTokens
|
|
1508
|
+
pendingTokens,
|
|
1509
|
+
sessionUnreadable
|
|
1350
1510
|
});
|
|
1351
|
-
|
|
1352
|
-
|
|
1511
|
+
const label = !isOnline ? "OV offline" : sessionUnreadable ? `OV: ${recalledCount} rec \xB7 no access` : `OV: ${recalledCount} rec \xB7 ${Math.round(pendingTokens / 1e3)}k pend`;
|
|
1512
|
+
const chipElement = /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1513
|
+
"span",
|
|
1353
1514
|
{
|
|
1354
1515
|
className,
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
display: "inline-flex",
|
|
1358
|
-
alignItems: "center"
|
|
1359
|
-
},
|
|
1516
|
+
"data-openviking-status": "true",
|
|
1517
|
+
style: { minWidth: 0, display: "inline-flex", position: "relative" },
|
|
1360
1518
|
ref: popoverRef,
|
|
1361
1519
|
children: [
|
|
1362
1520
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
@@ -1364,23 +1522,27 @@ function OpenVikingStatusChip({
|
|
|
1364
1522
|
{
|
|
1365
1523
|
type: "button",
|
|
1366
1524
|
onClick: () => setIsOpen(!isOpen),
|
|
1525
|
+
onMouseEnter: () => setIsHovered(true),
|
|
1526
|
+
onMouseLeave: () => setIsHovered(false),
|
|
1367
1527
|
"aria-expanded": isOpen,
|
|
1368
1528
|
"aria-haspopup": "dialog",
|
|
1369
1529
|
style: {
|
|
1370
|
-
|
|
1530
|
+
boxSizing: "border-box",
|
|
1531
|
+
maxWidth: "100%",
|
|
1532
|
+
color: isHovered ? themeVar("labelSecondary") : themeVar("labelTertiary"),
|
|
1533
|
+
fontFamily: "var(--dsw-font-family, system-ui)",
|
|
1534
|
+
fontSize: "var(--dsh-content-font-size-secondary, 13px)",
|
|
1535
|
+
lineHeight: "calc(20px + var(--dsh-content-font-delta-secondary, 0px))",
|
|
1536
|
+
fontVariantNumeric: "tabular-nums",
|
|
1537
|
+
whiteSpace: "nowrap",
|
|
1538
|
+
background: isHovered ? themeVar("hoverBackground") : "transparent",
|
|
1539
|
+
border: "none",
|
|
1540
|
+
borderRadius: "24px",
|
|
1371
1541
|
alignItems: "center",
|
|
1372
1542
|
gap: "6px",
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
fontFamily: "var(--dsw-font-mono, monospace)",
|
|
1377
|
-
borderRadius: "6px",
|
|
1378
|
-
background: "var(--dsw-surface-base, rgba(255, 255, 255, 0.05))",
|
|
1379
|
-
border: "1px solid var(--dsw-border-subtle, rgba(255, 255, 255, 0.1))",
|
|
1380
|
-
color: "var(--dsw-text-muted, #94a3b8)",
|
|
1381
|
-
cursor: "pointer",
|
|
1382
|
-
transition: "all 0.15s ease",
|
|
1383
|
-
userSelect: "none"
|
|
1543
|
+
padding: "1px 8px",
|
|
1544
|
+
display: "inline-flex",
|
|
1545
|
+
cursor: "pointer"
|
|
1384
1546
|
},
|
|
1385
1547
|
title: tooltipTitle,
|
|
1386
1548
|
"aria-label": tooltipTitle,
|
|
@@ -1389,25 +1551,17 @@ function OpenVikingStatusChip({
|
|
|
1389
1551
|
"span",
|
|
1390
1552
|
{
|
|
1391
1553
|
"data-testid": "status-dot",
|
|
1554
|
+
"aria-hidden": "true",
|
|
1392
1555
|
style: {
|
|
1393
|
-
width: "
|
|
1394
|
-
height: "
|
|
1556
|
+
width: "6px",
|
|
1557
|
+
height: "6px",
|
|
1395
1558
|
borderRadius: "50%",
|
|
1396
|
-
|
|
1397
|
-
boxShadow: statusGlow,
|
|
1559
|
+
background: statusColor,
|
|
1398
1560
|
flexShrink: 0
|
|
1399
1561
|
}
|
|
1400
1562
|
}
|
|
1401
1563
|
),
|
|
1402
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1403
|
-
"span",
|
|
1404
|
-
{
|
|
1405
|
-
style: { fontWeight: 600, color: "var(--dsw-text-default, #e2e8f0)" },
|
|
1406
|
-
children: isOnline ? "OV:" : "OV"
|
|
1407
|
-
}
|
|
1408
|
-
),
|
|
1409
|
-
" ",
|
|
1410
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: isOnline ? `${recalledCount} rec \xB7 ${pendingTokensK}k pend` : "offline" })
|
|
1564
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { textOverflow: "ellipsis", minWidth: 0 }, children: label })
|
|
1411
1565
|
]
|
|
1412
1566
|
}
|
|
1413
1567
|
),
|
|
@@ -1417,6 +1571,7 @@ function OpenVikingStatusChip({
|
|
|
1417
1571
|
sessionId,
|
|
1418
1572
|
health,
|
|
1419
1573
|
sessionData,
|
|
1574
|
+
sessionRead,
|
|
1420
1575
|
recalledResult,
|
|
1421
1576
|
endpoint: apiClient.endpoint,
|
|
1422
1577
|
isCommitting,
|
|
@@ -1428,6 +1583,572 @@ function OpenVikingStatusChip({
|
|
|
1428
1583
|
]
|
|
1429
1584
|
}
|
|
1430
1585
|
);
|
|
1586
|
+
if (statsHost && typeof document !== "undefined") {
|
|
1587
|
+
return import_react_dom.default.createPortal(chipElement, statsHost);
|
|
1588
|
+
}
|
|
1589
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1590
|
+
"div",
|
|
1591
|
+
{
|
|
1592
|
+
style: {
|
|
1593
|
+
maxWidth: "var(--dsh-chat-content-width, 748px)",
|
|
1594
|
+
boxSizing: "border-box",
|
|
1595
|
+
width: "100%",
|
|
1596
|
+
padding: "4px calc(var(--dsh-composer-side-clearance, 0px) + 16px) 0px",
|
|
1597
|
+
fontSize: "var(--dsh-content-font-size-secondary, 13px)",
|
|
1598
|
+
lineHeight: "calc(20px + var(--dsh-content-font-delta-secondary, 0px))",
|
|
1599
|
+
justifyContent: "center",
|
|
1600
|
+
gap: "12px",
|
|
1601
|
+
margin: "0 auto",
|
|
1602
|
+
display: "flex"
|
|
1603
|
+
},
|
|
1604
|
+
children: chipElement
|
|
1605
|
+
}
|
|
1606
|
+
);
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
// src/client/OpenVikingSettingsSection.tsx
|
|
1610
|
+
var import_react3 = require("react");
|
|
1611
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1612
|
+
var API_CONFIG = "/openviking-status/api/config";
|
|
1613
|
+
var API_TEST = "/openviking-status/api/test-connection";
|
|
1614
|
+
var SOURCE_LABELS = {
|
|
1615
|
+
ovcli: "Auto-detected from ~/.openviking/ovcli.conf",
|
|
1616
|
+
env: "Auto-detected from environment variables",
|
|
1617
|
+
ov: "Auto-detected from ~/.openviking/ov.conf",
|
|
1618
|
+
settings: "Custom override in DSH settings.yaml",
|
|
1619
|
+
default: "Default local configuration"
|
|
1620
|
+
};
|
|
1621
|
+
function OpenVikingSettingsSection({
|
|
1622
|
+
initialConfig,
|
|
1623
|
+
onConfigSaved,
|
|
1624
|
+
className,
|
|
1625
|
+
style
|
|
1626
|
+
}) {
|
|
1627
|
+
const [endpoint, setEndpoint] = (0, import_react3.useState)(
|
|
1628
|
+
initialConfig?.endpoint || "http://127.0.0.1:1933"
|
|
1629
|
+
);
|
|
1630
|
+
const [apiKey, setApiKey] = (0, import_react3.useState)("");
|
|
1631
|
+
const [showKey, setShowKey] = (0, import_react3.useState)(false);
|
|
1632
|
+
const [source, setSource] = (0, import_react3.useState)(
|
|
1633
|
+
initialConfig?.source || "default"
|
|
1634
|
+
);
|
|
1635
|
+
const [hasStoredKey, setHasStoredKey] = (0, import_react3.useState)(
|
|
1636
|
+
initialConfig?.hasApiKey || false
|
|
1637
|
+
);
|
|
1638
|
+
const [loading, setLoading] = (0, import_react3.useState)(!initialConfig);
|
|
1639
|
+
const [testing, setTesting] = (0, import_react3.useState)(false);
|
|
1640
|
+
const [saving, setSaving] = (0, import_react3.useState)(false);
|
|
1641
|
+
const [testResult, setTestResult] = (0, import_react3.useState)(null);
|
|
1642
|
+
const [flash, setFlash] = (0, import_react3.useState)(null);
|
|
1643
|
+
(0, import_react3.useEffect)(() => {
|
|
1644
|
+
if (initialConfig) return;
|
|
1645
|
+
let active = true;
|
|
1646
|
+
async function fetchConfig() {
|
|
1647
|
+
try {
|
|
1648
|
+
setLoading(true);
|
|
1649
|
+
const res = await fetch(API_CONFIG, { cache: "no-store" });
|
|
1650
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
1651
|
+
const data = await res.json();
|
|
1652
|
+
if (!active) return;
|
|
1653
|
+
const newEp = data.endpoint || "http://127.0.0.1:1933";
|
|
1654
|
+
setEndpoint(newEp);
|
|
1655
|
+
setSource(data.source || "default");
|
|
1656
|
+
setHasStoredKey(data.hasApiKey);
|
|
1657
|
+
defaultOpenVikingClient.clearResolvedSessions();
|
|
1658
|
+
} catch {
|
|
1659
|
+
} finally {
|
|
1660
|
+
if (active) setLoading(false);
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
void fetchConfig();
|
|
1664
|
+
return () => {
|
|
1665
|
+
active = false;
|
|
1666
|
+
};
|
|
1667
|
+
}, [initialConfig]);
|
|
1668
|
+
async function handleTestConnection() {
|
|
1669
|
+
setTesting(true);
|
|
1670
|
+
setTestResult(null);
|
|
1671
|
+
setFlash(null);
|
|
1672
|
+
try {
|
|
1673
|
+
const res = await fetch(API_TEST, {
|
|
1674
|
+
method: "POST",
|
|
1675
|
+
headers: { "Content-Type": "application/json" },
|
|
1676
|
+
body: JSON.stringify({
|
|
1677
|
+
endpoint: endpoint.trim(),
|
|
1678
|
+
apiKey: apiKey.trim() || void 0
|
|
1679
|
+
})
|
|
1680
|
+
});
|
|
1681
|
+
const data = await res.json();
|
|
1682
|
+
setTestResult(data);
|
|
1683
|
+
} catch (err) {
|
|
1684
|
+
setTestResult({
|
|
1685
|
+
ok: false,
|
|
1686
|
+
authenticated: false,
|
|
1687
|
+
error: String(err instanceof Error ? err.message : err)
|
|
1688
|
+
});
|
|
1689
|
+
} finally {
|
|
1690
|
+
setTesting(false);
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
async function handleSave() {
|
|
1694
|
+
setSaving(true);
|
|
1695
|
+
setFlash(null);
|
|
1696
|
+
try {
|
|
1697
|
+
const res = await fetch(API_CONFIG, {
|
|
1698
|
+
method: "POST",
|
|
1699
|
+
headers: { "Content-Type": "application/json" },
|
|
1700
|
+
body: JSON.stringify({
|
|
1701
|
+
endpoint: endpoint.trim(),
|
|
1702
|
+
apiKey: apiKey.trim() || void 0
|
|
1703
|
+
})
|
|
1704
|
+
});
|
|
1705
|
+
const data = await res.json();
|
|
1706
|
+
if (!res.ok || data.error) {
|
|
1707
|
+
throw new Error(data.error || `HTTP ${res.status}`);
|
|
1708
|
+
}
|
|
1709
|
+
setFlash({ kind: "ok", message: "Settings saved successfully" });
|
|
1710
|
+
setSource("settings");
|
|
1711
|
+
defaultOpenVikingClient.clearResolvedSessions();
|
|
1712
|
+
if (apiKey.trim()) {
|
|
1713
|
+
setHasStoredKey(true);
|
|
1714
|
+
setApiKey("");
|
|
1715
|
+
}
|
|
1716
|
+
onConfigSaved?.(
|
|
1717
|
+
data.config || {
|
|
1718
|
+
endpoint,
|
|
1719
|
+
hasApiKey: hasStoredKey || Boolean(apiKey.trim()),
|
|
1720
|
+
source: "settings"
|
|
1721
|
+
}
|
|
1722
|
+
);
|
|
1723
|
+
} catch (err) {
|
|
1724
|
+
setFlash({
|
|
1725
|
+
kind: "err",
|
|
1726
|
+
message: `Failed to save: ${err instanceof Error ? err.message : String(err)}`
|
|
1727
|
+
});
|
|
1728
|
+
} finally {
|
|
1729
|
+
setSaving(false);
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
async function handleReset() {
|
|
1733
|
+
setSaving(true);
|
|
1734
|
+
setFlash(null);
|
|
1735
|
+
setTestResult(null);
|
|
1736
|
+
try {
|
|
1737
|
+
const res = await fetch(API_CONFIG, {
|
|
1738
|
+
method: "POST",
|
|
1739
|
+
headers: { "Content-Type": "application/json" },
|
|
1740
|
+
body: JSON.stringify({ reset: true })
|
|
1741
|
+
});
|
|
1742
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
1743
|
+
const cfgRes = await fetch(API_CONFIG, { cache: "no-store" });
|
|
1744
|
+
if (cfgRes.ok) {
|
|
1745
|
+
const data = await cfgRes.json();
|
|
1746
|
+
const newEp = data.endpoint || "http://127.0.0.1:1933";
|
|
1747
|
+
setEndpoint(newEp);
|
|
1748
|
+
setSource(data.source || "default");
|
|
1749
|
+
setHasStoredKey(data.hasApiKey);
|
|
1750
|
+
setApiKey("");
|
|
1751
|
+
defaultOpenVikingClient.clearResolvedSessions();
|
|
1752
|
+
setFlash({
|
|
1753
|
+
kind: "ok",
|
|
1754
|
+
message: "Reset to auto-detected local settings"
|
|
1755
|
+
});
|
|
1756
|
+
onConfigSaved?.(data);
|
|
1757
|
+
}
|
|
1758
|
+
} catch (err) {
|
|
1759
|
+
setFlash({
|
|
1760
|
+
kind: "err",
|
|
1761
|
+
message: `Failed to reset: ${err instanceof Error ? err.message : String(err)}`
|
|
1762
|
+
});
|
|
1763
|
+
} finally {
|
|
1764
|
+
setSaving(false);
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
const sourceBadgeText = SOURCE_LABELS[source] || SOURCE_LABELS["default"];
|
|
1768
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1769
|
+
"div",
|
|
1770
|
+
{
|
|
1771
|
+
className: `ov-settings-root ${className || ""}`,
|
|
1772
|
+
style: {
|
|
1773
|
+
display: "flex",
|
|
1774
|
+
flexDirection: "column",
|
|
1775
|
+
gap: 20,
|
|
1776
|
+
maxWidth: 720,
|
|
1777
|
+
padding: "24px 28px",
|
|
1778
|
+
color: themeVar("labelPrimary"),
|
|
1779
|
+
fontSize: 14,
|
|
1780
|
+
lineHeight: 1.6,
|
|
1781
|
+
...style
|
|
1782
|
+
},
|
|
1783
|
+
children: [
|
|
1784
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
1785
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1786
|
+
"div",
|
|
1787
|
+
{
|
|
1788
|
+
style: {
|
|
1789
|
+
display: "flex",
|
|
1790
|
+
alignItems: "baseline",
|
|
1791
|
+
gap: 12,
|
|
1792
|
+
marginBottom: 6
|
|
1793
|
+
},
|
|
1794
|
+
children: [
|
|
1795
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1796
|
+
"h2",
|
|
1797
|
+
{
|
|
1798
|
+
style: {
|
|
1799
|
+
fontSize: 20,
|
|
1800
|
+
fontWeight: 600,
|
|
1801
|
+
margin: 0,
|
|
1802
|
+
color: themeVar("labelPrimary")
|
|
1803
|
+
},
|
|
1804
|
+
children: "OpenViking Status"
|
|
1805
|
+
}
|
|
1806
|
+
),
|
|
1807
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1808
|
+
"span",
|
|
1809
|
+
{
|
|
1810
|
+
style: {
|
|
1811
|
+
fontSize: 12,
|
|
1812
|
+
fontWeight: 500,
|
|
1813
|
+
padding: "2px 8px",
|
|
1814
|
+
borderRadius: 6,
|
|
1815
|
+
background: themeVar("insetSurface"),
|
|
1816
|
+
border: `1px solid ${themeVar("hairline")}`,
|
|
1817
|
+
color: themeVar("labelSecondary")
|
|
1818
|
+
},
|
|
1819
|
+
children: sourceBadgeText
|
|
1820
|
+
}
|
|
1821
|
+
)
|
|
1822
|
+
]
|
|
1823
|
+
}
|
|
1824
|
+
),
|
|
1825
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1826
|
+
"p",
|
|
1827
|
+
{
|
|
1828
|
+
style: { margin: 0, color: themeVar("labelSecondary"), fontSize: 13 },
|
|
1829
|
+
children: "Configure connection credentials for monitoring OpenViking persistent memory and session status."
|
|
1830
|
+
}
|
|
1831
|
+
)
|
|
1832
|
+
] }),
|
|
1833
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1834
|
+
"div",
|
|
1835
|
+
{
|
|
1836
|
+
style: {
|
|
1837
|
+
border: `1px solid ${themeVar("hairline")}`,
|
|
1838
|
+
borderRadius: 12,
|
|
1839
|
+
padding: 20,
|
|
1840
|
+
background: themeVar("insetSurface"),
|
|
1841
|
+
display: "flex",
|
|
1842
|
+
flexDirection: "column",
|
|
1843
|
+
gap: 16
|
|
1844
|
+
},
|
|
1845
|
+
children: [
|
|
1846
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
1847
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1848
|
+
"label",
|
|
1849
|
+
{
|
|
1850
|
+
style: {
|
|
1851
|
+
display: "block",
|
|
1852
|
+
fontSize: 13,
|
|
1853
|
+
fontWeight: 600,
|
|
1854
|
+
marginBottom: 6,
|
|
1855
|
+
color: themeVar("labelPrimary")
|
|
1856
|
+
},
|
|
1857
|
+
children: "Daemon Endpoint"
|
|
1858
|
+
}
|
|
1859
|
+
),
|
|
1860
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1861
|
+
"input",
|
|
1862
|
+
{
|
|
1863
|
+
type: "text",
|
|
1864
|
+
value: endpoint,
|
|
1865
|
+
onChange: (e) => setEndpoint(e.target.value),
|
|
1866
|
+
placeholder: "http://127.0.0.1:1933",
|
|
1867
|
+
style: {
|
|
1868
|
+
width: "100%",
|
|
1869
|
+
boxSizing: "border-box",
|
|
1870
|
+
padding: "9px 12px",
|
|
1871
|
+
fontSize: 14,
|
|
1872
|
+
fontFamily: themeVar("fontMono"),
|
|
1873
|
+
borderRadius: 8,
|
|
1874
|
+
border: `1px solid ${themeVar("hairline")}`,
|
|
1875
|
+
background: themeVar("panelSurface"),
|
|
1876
|
+
color: themeVar("labelPrimary"),
|
|
1877
|
+
outline: "none"
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
),
|
|
1881
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1882
|
+
"span",
|
|
1883
|
+
{
|
|
1884
|
+
style: {
|
|
1885
|
+
fontSize: 12,
|
|
1886
|
+
color: themeVar("labelTertiary"),
|
|
1887
|
+
marginTop: 4,
|
|
1888
|
+
display: "block"
|
|
1889
|
+
},
|
|
1890
|
+
children: "The URL of the local or remote OpenViking HTTP server. Resolved from the DSH host."
|
|
1891
|
+
}
|
|
1892
|
+
)
|
|
1893
|
+
] }),
|
|
1894
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
1895
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1896
|
+
"div",
|
|
1897
|
+
{
|
|
1898
|
+
style: {
|
|
1899
|
+
display: "flex",
|
|
1900
|
+
justifyContent: "space-between",
|
|
1901
|
+
alignItems: "center",
|
|
1902
|
+
marginBottom: 6
|
|
1903
|
+
},
|
|
1904
|
+
children: [
|
|
1905
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1906
|
+
"label",
|
|
1907
|
+
{
|
|
1908
|
+
style: {
|
|
1909
|
+
fontSize: 13,
|
|
1910
|
+
fontWeight: 600,
|
|
1911
|
+
color: themeVar("labelPrimary")
|
|
1912
|
+
},
|
|
1913
|
+
children: "API Token (Authentication)"
|
|
1914
|
+
}
|
|
1915
|
+
),
|
|
1916
|
+
hasStoredKey && !apiKey && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1917
|
+
"span",
|
|
1918
|
+
{
|
|
1919
|
+
style: {
|
|
1920
|
+
fontSize: 12,
|
|
1921
|
+
color: themeVar("stateSuccess"),
|
|
1922
|
+
fontWeight: 500
|
|
1923
|
+
},
|
|
1924
|
+
children: "\u25CF Active token configured"
|
|
1925
|
+
}
|
|
1926
|
+
)
|
|
1927
|
+
]
|
|
1928
|
+
}
|
|
1929
|
+
),
|
|
1930
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: 8 }, children: [
|
|
1931
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1932
|
+
"input",
|
|
1933
|
+
{
|
|
1934
|
+
type: showKey ? "text" : "password",
|
|
1935
|
+
value: apiKey,
|
|
1936
|
+
onChange: (e) => setApiKey(e.target.value),
|
|
1937
|
+
placeholder: hasStoredKey ? "(Token stored \u2014 leave blank to keep unchanged)" : "Optional or required if daemon uses auth_mode: api_key",
|
|
1938
|
+
style: {
|
|
1939
|
+
flex: 1,
|
|
1940
|
+
padding: "9px 12px",
|
|
1941
|
+
fontSize: 14,
|
|
1942
|
+
fontFamily: themeVar("fontMono"),
|
|
1943
|
+
borderRadius: 8,
|
|
1944
|
+
border: `1px solid ${themeVar("hairline")}`,
|
|
1945
|
+
background: themeVar("panelSurface"),
|
|
1946
|
+
color: themeVar("labelPrimary"),
|
|
1947
|
+
outline: "none"
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
),
|
|
1951
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1952
|
+
"button",
|
|
1953
|
+
{
|
|
1954
|
+
type: "button",
|
|
1955
|
+
onClick: () => setShowKey((v) => !v),
|
|
1956
|
+
style: {
|
|
1957
|
+
padding: "0 14px",
|
|
1958
|
+
fontSize: 13,
|
|
1959
|
+
fontWeight: 500,
|
|
1960
|
+
borderRadius: 8,
|
|
1961
|
+
border: `1px solid ${themeVar("hairline")}`,
|
|
1962
|
+
background: themeVar("panelSurface"),
|
|
1963
|
+
color: themeVar("labelSecondary"),
|
|
1964
|
+
cursor: "pointer"
|
|
1965
|
+
},
|
|
1966
|
+
children: showKey ? "Hide" : "Show"
|
|
1967
|
+
}
|
|
1968
|
+
)
|
|
1969
|
+
] }),
|
|
1970
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1971
|
+
"span",
|
|
1972
|
+
{
|
|
1973
|
+
style: {
|
|
1974
|
+
fontSize: 12,
|
|
1975
|
+
color: themeVar("labelTertiary"),
|
|
1976
|
+
marginTop: 4,
|
|
1977
|
+
display: "block"
|
|
1978
|
+
},
|
|
1979
|
+
children: "Required when the daemon runs with auth_mode: api_key. Local tokens are typically found in ~/.openviking/ovcli.conf."
|
|
1980
|
+
}
|
|
1981
|
+
)
|
|
1982
|
+
] }),
|
|
1983
|
+
testResult && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1984
|
+
"div",
|
|
1985
|
+
{
|
|
1986
|
+
style: {
|
|
1987
|
+
padding: "10px 14px",
|
|
1988
|
+
borderRadius: 8,
|
|
1989
|
+
fontSize: 13,
|
|
1990
|
+
display: "flex",
|
|
1991
|
+
alignItems: "center",
|
|
1992
|
+
gap: 8,
|
|
1993
|
+
border: `1px solid ${testResult.ok && testResult.authenticated ? themeVar("stateSuccess") : themeVar("stateError")}`,
|
|
1994
|
+
background: themeVar("panelSurface"),
|
|
1995
|
+
color: testResult.ok && testResult.authenticated ? themeVar("stateSuccess") : themeVar("stateError")
|
|
1996
|
+
},
|
|
1997
|
+
children: [
|
|
1998
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: testResult.ok && testResult.authenticated ? "\u25CF" : "\u2715" }),
|
|
1999
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { flex: 1 }, children: testResult.ok && testResult.authenticated ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
2000
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: "Connected successfully" }),
|
|
2001
|
+
testResult.version && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
|
|
2002
|
+
" \xB7 ",
|
|
2003
|
+
testResult.version
|
|
2004
|
+
] }),
|
|
2005
|
+
testResult.storage && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
|
|
2006
|
+
" (storage: ",
|
|
2007
|
+
testResult.storage,
|
|
2008
|
+
")"
|
|
2009
|
+
] })
|
|
2010
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
2011
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: "Connection failed: " }),
|
|
2012
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: testResult.error || "Unable to reach daemon or token unauthorized" })
|
|
2013
|
+
] }) })
|
|
2014
|
+
]
|
|
2015
|
+
}
|
|
2016
|
+
),
|
|
2017
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2018
|
+
"div",
|
|
2019
|
+
{
|
|
2020
|
+
style: {
|
|
2021
|
+
display: "flex",
|
|
2022
|
+
flexWrap: "wrap",
|
|
2023
|
+
alignItems: "center",
|
|
2024
|
+
gap: 10,
|
|
2025
|
+
paddingTop: 4
|
|
2026
|
+
},
|
|
2027
|
+
children: [
|
|
2028
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2029
|
+
"button",
|
|
2030
|
+
{
|
|
2031
|
+
type: "button",
|
|
2032
|
+
disabled: testing || loading,
|
|
2033
|
+
onClick: () => void handleTestConnection(),
|
|
2034
|
+
style: {
|
|
2035
|
+
padding: "8px 16px",
|
|
2036
|
+
fontSize: 13,
|
|
2037
|
+
fontWeight: 500,
|
|
2038
|
+
borderRadius: 8,
|
|
2039
|
+
border: `1px solid ${themeVar("hairline")}`,
|
|
2040
|
+
background: themeVar("panelSurface"),
|
|
2041
|
+
color: themeVar("labelPrimary"),
|
|
2042
|
+
cursor: testing ? "not-allowed" : "pointer",
|
|
2043
|
+
opacity: testing ? 0.6 : 1
|
|
2044
|
+
},
|
|
2045
|
+
children: testing ? "Testing..." : "Test Connection"
|
|
2046
|
+
}
|
|
2047
|
+
),
|
|
2048
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2049
|
+
"button",
|
|
2050
|
+
{
|
|
2051
|
+
type: "button",
|
|
2052
|
+
disabled: saving || loading,
|
|
2053
|
+
onClick: () => void handleSave(),
|
|
2054
|
+
style: {
|
|
2055
|
+
padding: "8px 18px",
|
|
2056
|
+
fontSize: 13,
|
|
2057
|
+
fontWeight: 600,
|
|
2058
|
+
borderRadius: 8,
|
|
2059
|
+
border: "none",
|
|
2060
|
+
background: themeVar("buttonPrimaryFill"),
|
|
2061
|
+
color: themeVar("buttonPrimaryText"),
|
|
2062
|
+
cursor: saving ? "not-allowed" : "pointer",
|
|
2063
|
+
opacity: saving ? 0.6 : 1
|
|
2064
|
+
},
|
|
2065
|
+
children: saving ? "Saving..." : "Save Settings"
|
|
2066
|
+
}
|
|
2067
|
+
),
|
|
2068
|
+
source === "settings" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2069
|
+
"button",
|
|
2070
|
+
{
|
|
2071
|
+
type: "button",
|
|
2072
|
+
disabled: saving || loading,
|
|
2073
|
+
onClick: () => void handleReset(),
|
|
2074
|
+
style: {
|
|
2075
|
+
padding: "8px 14px",
|
|
2076
|
+
fontSize: 13,
|
|
2077
|
+
fontWeight: 500,
|
|
2078
|
+
borderRadius: 8,
|
|
2079
|
+
border: `1px solid ${themeVar("hairline")}`,
|
|
2080
|
+
background: "transparent",
|
|
2081
|
+
color: themeVar("labelSecondary"),
|
|
2082
|
+
cursor: "pointer",
|
|
2083
|
+
marginLeft: "auto"
|
|
2084
|
+
},
|
|
2085
|
+
children: "Reset to Auto-detected"
|
|
2086
|
+
}
|
|
2087
|
+
),
|
|
2088
|
+
flash && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2089
|
+
"span",
|
|
2090
|
+
{
|
|
2091
|
+
style: {
|
|
2092
|
+
fontSize: 13,
|
|
2093
|
+
color: flash.kind === "ok" ? themeVar("stateSuccess") : themeVar("stateError"),
|
|
2094
|
+
fontWeight: 500
|
|
2095
|
+
},
|
|
2096
|
+
children: flash.message
|
|
2097
|
+
}
|
|
2098
|
+
)
|
|
2099
|
+
]
|
|
2100
|
+
}
|
|
2101
|
+
)
|
|
2102
|
+
]
|
|
2103
|
+
}
|
|
2104
|
+
),
|
|
2105
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2106
|
+
"div",
|
|
2107
|
+
{
|
|
2108
|
+
style: {
|
|
2109
|
+
border: `1px solid ${themeVar("hairline")}`,
|
|
2110
|
+
borderRadius: 10,
|
|
2111
|
+
padding: "14px 18px",
|
|
2112
|
+
background: themeVar("panelSurface"),
|
|
2113
|
+
fontSize: 13,
|
|
2114
|
+
color: themeVar("labelSecondary"),
|
|
2115
|
+
lineHeight: 1.5
|
|
2116
|
+
},
|
|
2117
|
+
children: [
|
|
2118
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2119
|
+
"p",
|
|
2120
|
+
{
|
|
2121
|
+
style: {
|
|
2122
|
+
margin: "0 0 6px 0",
|
|
2123
|
+
fontWeight: 600,
|
|
2124
|
+
color: themeVar("labelPrimary")
|
|
2125
|
+
},
|
|
2126
|
+
children: "How OpenViking connection works:"
|
|
2127
|
+
}
|
|
2128
|
+
),
|
|
2129
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("ul", { style: { margin: 0, paddingLeft: 18 }, children: [
|
|
2130
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("li", { style: { marginBottom: 4 }, children: "All requests to OpenViking proxy through the DSH Desktop host, making it work seamlessly even when managing DSH remotely over Tailscale, mobile, or LAN." }),
|
|
2131
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { style: { marginBottom: 4 }, children: [
|
|
2132
|
+
"If OpenViking runs locally on the standard port (1933), the plugin auto-detects credentials from ",
|
|
2133
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("code", { children: "~/.openviking/ovcli.conf" }),
|
|
2134
|
+
"."
|
|
2135
|
+
] }),
|
|
2136
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { children: [
|
|
2137
|
+
"Custom values saved here are persisted in",
|
|
2138
|
+
" ",
|
|
2139
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("code", { children: "~/.dsh/settings.yaml" }),
|
|
2140
|
+
" under the",
|
|
2141
|
+
" ",
|
|
2142
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("code", { children: "openviking-status" }),
|
|
2143
|
+
" namespace."
|
|
2144
|
+
] })
|
|
2145
|
+
] })
|
|
2146
|
+
]
|
|
2147
|
+
}
|
|
2148
|
+
)
|
|
2149
|
+
]
|
|
2150
|
+
}
|
|
2151
|
+
);
|
|
1431
2152
|
}
|
|
1432
2153
|
|
|
1433
2154
|
// src/client/index.tsx
|
|
@@ -1436,10 +2157,10 @@ var inject = ["slots"];
|
|
|
1436
2157
|
function apply(ctx) {
|
|
1437
2158
|
ctx.effect(
|
|
1438
2159
|
() => ctx.slots.inject(
|
|
1439
|
-
"conversation.
|
|
2160
|
+
"conversation.composer.dock",
|
|
1440
2161
|
() => ctx.slots.register(
|
|
1441
2162
|
{
|
|
1442
|
-
name: "conversation.
|
|
2163
|
+
name: "conversation.composer.dock",
|
|
1443
2164
|
id: "openviking-status",
|
|
1444
2165
|
order: 50,
|
|
1445
2166
|
label: "OpenViking"
|
|
@@ -1447,7 +2168,22 @@ function apply(ctx) {
|
|
|
1447
2168
|
OpenVikingStatusChip
|
|
1448
2169
|
)
|
|
1449
2170
|
),
|
|
1450
|
-
"openviking-status: composer chip"
|
|
2171
|
+
"openviking-status: composer stats chip"
|
|
2172
|
+
);
|
|
2173
|
+
ctx.effect(
|
|
2174
|
+
() => ctx.slots.inject(
|
|
2175
|
+
"settings.section",
|
|
2176
|
+
() => ctx.slots.register(
|
|
2177
|
+
{
|
|
2178
|
+
name: "settings.section",
|
|
2179
|
+
id: "openviking-status",
|
|
2180
|
+
order: 35,
|
|
2181
|
+
label: () => "OpenViking"
|
|
2182
|
+
},
|
|
2183
|
+
OpenVikingSettingsSection
|
|
2184
|
+
)
|
|
2185
|
+
),
|
|
2186
|
+
"openviking-status: settings section"
|
|
1451
2187
|
);
|
|
1452
2188
|
}
|
|
1453
2189
|
return module.exports;
|