@dipertq/dsh-openviking-status 0.1.8 → 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 +5 -13
- package/lib/client.cjs +724 -6
- package/lib/client.cjs.map +1 -1
- package/lib/client.d.cts +39 -11
- package/lib/client.js +724 -6
- 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 +5 -2
package/lib/client.js
CHANGED
|
@@ -13,6 +13,7 @@ import React2, {
|
|
|
13
13
|
useRef as useRef2,
|
|
14
14
|
useMemo
|
|
15
15
|
} from "react";
|
|
16
|
+
import ReactDOM from "react-dom";
|
|
16
17
|
|
|
17
18
|
// src/client/api.ts
|
|
18
19
|
var DEFAULT_OPENVIKING_ENDPOINT = "http://127.0.0.1:1933";
|
|
@@ -66,6 +67,30 @@ var OpenVikingClient = class {
|
|
|
66
67
|
this.endpoint = resolveEndpoint(endpoint);
|
|
67
68
|
this.apiKey = resolveApiKey(apiKey);
|
|
68
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Обновление конфигурации клиента на лету (например, после сохранения настроек в UI).
|
|
72
|
+
*/
|
|
73
|
+
updateConfig(config) {
|
|
74
|
+
if (config.endpoint && config.endpoint.trim()) {
|
|
75
|
+
this.endpoint = resolveEndpoint(config.endpoint);
|
|
76
|
+
}
|
|
77
|
+
if (config.apiKey !== void 0) {
|
|
78
|
+
this.apiKey = resolveApiKey(config.apiKey);
|
|
79
|
+
}
|
|
80
|
+
this.resolvedSessionIds.clear();
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Очистить кэш разрешенных идентификаторов сессий.
|
|
84
|
+
*/
|
|
85
|
+
clearResolvedSessions() {
|
|
86
|
+
this.resolvedSessionIds.clear();
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Проверка, работает ли клиент через DSH Web Server proxy.
|
|
90
|
+
*/
|
|
91
|
+
isProxy() {
|
|
92
|
+
return this.endpoint.startsWith("/") || this.endpoint.includes("/openviking-status/api");
|
|
93
|
+
}
|
|
69
94
|
/**
|
|
70
95
|
* Формирование заголовков запроса, включая опциональный заголовок авторизации
|
|
71
96
|
*/
|
|
@@ -107,6 +132,32 @@ var OpenVikingClient = class {
|
|
|
107
132
|
* Проверка доступности и состояния сервиса OpenViking
|
|
108
133
|
*/
|
|
109
134
|
async checkHealth() {
|
|
135
|
+
if (this.isProxy()) {
|
|
136
|
+
try {
|
|
137
|
+
const res = await fetch(`${this.endpoint}/health`, {
|
|
138
|
+
method: "GET",
|
|
139
|
+
headers: this.getHeaders()
|
|
140
|
+
});
|
|
141
|
+
if (!res.ok) {
|
|
142
|
+
return {
|
|
143
|
+
ok: false,
|
|
144
|
+
error: `HTTP ${res.status}: ${res.statusText}`
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
const body = await res.json().catch(() => ({}));
|
|
148
|
+
const isOk = body.ok !== false && body.status !== "error" && (body.ok === true || body.status === "ok" || body.status === "healthy" || res.ok);
|
|
149
|
+
return {
|
|
150
|
+
ok: isOk,
|
|
151
|
+
version: typeof body.version === "string" ? body.version : void 0,
|
|
152
|
+
storage: typeof body.storage === "string" ? body.storage : void 0
|
|
153
|
+
};
|
|
154
|
+
} catch (err) {
|
|
155
|
+
return {
|
|
156
|
+
ok: false,
|
|
157
|
+
error: err instanceof Error ? err.message : String(err)
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
}
|
|
110
161
|
try {
|
|
111
162
|
const res = await fetch(`${this.endpoint}/health`, {
|
|
112
163
|
method: "GET",
|
|
@@ -144,6 +195,48 @@ var OpenVikingClient = class {
|
|
|
144
195
|
if (!sessionId || !sessionId.trim()) {
|
|
145
196
|
return { status: "missing" };
|
|
146
197
|
}
|
|
198
|
+
if (this.isProxy()) {
|
|
199
|
+
try {
|
|
200
|
+
const res = await fetch(
|
|
201
|
+
`${this.endpoint}/session?id=${encodeURIComponent(sessionId.trim())}`,
|
|
202
|
+
{
|
|
203
|
+
method: "GET",
|
|
204
|
+
headers: this.getHeaders()
|
|
205
|
+
}
|
|
206
|
+
);
|
|
207
|
+
if (res.status === 401 || res.status === 403) {
|
|
208
|
+
return { status: "unauthorized" };
|
|
209
|
+
}
|
|
210
|
+
if (!res.ok) {
|
|
211
|
+
return { status: "error", detail: `HTTP ${res.status}` };
|
|
212
|
+
}
|
|
213
|
+
const data = await res.json();
|
|
214
|
+
if (data.status === "unauthorized") return { status: "unauthorized" };
|
|
215
|
+
if (data.status === "missing") return { status: "missing" };
|
|
216
|
+
if (data.status === "unreachable")
|
|
217
|
+
return {
|
|
218
|
+
status: "unreachable",
|
|
219
|
+
detail: typeof data.detail === "string" ? data.detail : void 0
|
|
220
|
+
};
|
|
221
|
+
if (data.status === "error")
|
|
222
|
+
return {
|
|
223
|
+
status: "error",
|
|
224
|
+
detail: typeof data.detail === "string" ? data.detail : void 0
|
|
225
|
+
};
|
|
226
|
+
if (data.status === "ok" && data.session) {
|
|
227
|
+
return {
|
|
228
|
+
status: "ok",
|
|
229
|
+
session: data.session
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
return { status: "error", detail: "malformed response from proxy" };
|
|
233
|
+
} catch (err) {
|
|
234
|
+
return {
|
|
235
|
+
status: "unreachable",
|
|
236
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
147
240
|
const candidates = this.getCandidateSessionIds(sessionId);
|
|
148
241
|
for (const candidateId of candidates) {
|
|
149
242
|
try {
|
|
@@ -213,6 +306,31 @@ var OpenVikingClient = class {
|
|
|
213
306
|
if (!sessionId || !sessionId.trim()) {
|
|
214
307
|
return { ok: false, error: "Missing sessionId" };
|
|
215
308
|
}
|
|
309
|
+
if (this.isProxy()) {
|
|
310
|
+
try {
|
|
311
|
+
const res = await fetch(`${this.endpoint}/session/commit`, {
|
|
312
|
+
method: "POST",
|
|
313
|
+
headers: this.getHeaders(),
|
|
314
|
+
body: JSON.stringify({
|
|
315
|
+
sessionId: sessionId.trim(),
|
|
316
|
+
...options ?? { keep_recent_count: 10 }
|
|
317
|
+
})
|
|
318
|
+
});
|
|
319
|
+
if (!res.ok) {
|
|
320
|
+
return { ok: false, error: `HTTP ${res.status}` };
|
|
321
|
+
}
|
|
322
|
+
const data = await res.json().catch(() => ({}));
|
|
323
|
+
return {
|
|
324
|
+
ok: data.ok === true,
|
|
325
|
+
error: typeof data.error === "string" ? data.error : void 0
|
|
326
|
+
};
|
|
327
|
+
} catch (err) {
|
|
328
|
+
return {
|
|
329
|
+
ok: false,
|
|
330
|
+
error: err instanceof Error ? err.message : String(err)
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
}
|
|
216
334
|
const candidates = this.getCandidateSessionIds(sessionId);
|
|
217
335
|
const bodyPayload = JSON.stringify(options ?? { keep_recent_count: 10 });
|
|
218
336
|
let lastError = "Session commit failed";
|
|
@@ -292,6 +410,10 @@ var THEME = {
|
|
|
292
410
|
stateWarning: "--dsw-alias-state-warn-primary",
|
|
293
411
|
/** Утопленная поверхность: дорожка прогресс-бара. */
|
|
294
412
|
insetSurface: "--dsw-alias-bg-layer-2",
|
|
413
|
+
/** Заливка основной кнопки действий. */
|
|
414
|
+
buttonPrimaryFill: "--dsw-alias-button-primary-fill",
|
|
415
|
+
/** Цвет текста на основной кнопке действий. */
|
|
416
|
+
buttonPrimaryText: "--dsw-alias-label-primary-inverted",
|
|
295
417
|
/** Моноширинный шрифт для идентификаторов и путей. */
|
|
296
418
|
fontMono: "--dsw-font-markdown-code-font-family"
|
|
297
419
|
};
|
|
@@ -1225,8 +1347,22 @@ function StatusChipView({
|
|
|
1225
1347
|
const [isCommitting, setIsCommitting] = useState2(false);
|
|
1226
1348
|
const [commitError, setCommitError] = useState2(null);
|
|
1227
1349
|
const [isHovered, setIsHovered] = useState2(false);
|
|
1350
|
+
const [statsHost, setStatsHost] = useState2(null);
|
|
1228
1351
|
const popoverRef = useRef2(null);
|
|
1229
1352
|
const apiClient = client ?? defaultOpenVikingClient;
|
|
1353
|
+
useEffect2(() => {
|
|
1354
|
+
if (typeof document === "undefined") return;
|
|
1355
|
+
function findHost() {
|
|
1356
|
+
const el = document.querySelector("[data-composer-stats]");
|
|
1357
|
+
setStatsHost((prev) => prev !== el ? el : prev);
|
|
1358
|
+
}
|
|
1359
|
+
findHost();
|
|
1360
|
+
const observer = new MutationObserver(() => {
|
|
1361
|
+
findHost();
|
|
1362
|
+
});
|
|
1363
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
1364
|
+
return () => observer.disconnect();
|
|
1365
|
+
}, []);
|
|
1230
1366
|
const conversationText = useMemo(() => {
|
|
1231
1367
|
if (typeof contextText === "string") return contextText;
|
|
1232
1368
|
return chatNodesToText(messages);
|
|
@@ -1312,10 +1448,11 @@ function StatusChipView({
|
|
|
1312
1448
|
sessionUnreadable
|
|
1313
1449
|
});
|
|
1314
1450
|
const label = !isOnline ? "OV offline" : sessionUnreadable ? `OV: ${recalledCount} rec \xB7 no access` : `OV: ${recalledCount} rec \xB7 ${Math.round(pendingTokens / 1e3)}k pend`;
|
|
1315
|
-
|
|
1451
|
+
const chipElement = /* @__PURE__ */ jsxs2(
|
|
1316
1452
|
"span",
|
|
1317
1453
|
{
|
|
1318
1454
|
className,
|
|
1455
|
+
"data-openviking-status": "true",
|
|
1319
1456
|
style: { minWidth: 0, display: "inline-flex", position: "relative" },
|
|
1320
1457
|
ref: popoverRef,
|
|
1321
1458
|
children: [
|
|
@@ -1329,14 +1466,13 @@ function StatusChipView({
|
|
|
1329
1466
|
"aria-expanded": isOpen,
|
|
1330
1467
|
"aria-haspopup": "dialog",
|
|
1331
1468
|
style: {
|
|
1332
|
-
// Геометрия и типографика повторяют штатный чип статистики DSH:
|
|
1333
|
-
// прозрачный фон, без рамки, шрифт и кегль наследуются от строки.
|
|
1334
1469
|
boxSizing: "border-box",
|
|
1335
1470
|
maxWidth: "100%",
|
|
1336
|
-
color: themeVar("labelTertiary"),
|
|
1337
|
-
|
|
1471
|
+
color: isHovered ? themeVar("labelSecondary") : themeVar("labelTertiary"),
|
|
1472
|
+
fontFamily: "var(--dsw-font-family, system-ui)",
|
|
1473
|
+
fontSize: "var(--dsh-content-font-size-secondary, 13px)",
|
|
1474
|
+
lineHeight: "calc(20px + var(--dsh-content-font-delta-secondary, 0px))",
|
|
1338
1475
|
fontVariantNumeric: "tabular-nums",
|
|
1339
|
-
lineHeight: "inherit",
|
|
1340
1476
|
whiteSpace: "nowrap",
|
|
1341
1477
|
background: isHovered ? themeVar("hoverBackground") : "transparent",
|
|
1342
1478
|
border: "none",
|
|
@@ -1386,6 +1522,572 @@ function StatusChipView({
|
|
|
1386
1522
|
]
|
|
1387
1523
|
}
|
|
1388
1524
|
);
|
|
1525
|
+
if (statsHost && typeof document !== "undefined") {
|
|
1526
|
+
return ReactDOM.createPortal(chipElement, statsHost);
|
|
1527
|
+
}
|
|
1528
|
+
return /* @__PURE__ */ jsx2(
|
|
1529
|
+
"div",
|
|
1530
|
+
{
|
|
1531
|
+
style: {
|
|
1532
|
+
maxWidth: "var(--dsh-chat-content-width, 748px)",
|
|
1533
|
+
boxSizing: "border-box",
|
|
1534
|
+
width: "100%",
|
|
1535
|
+
padding: "4px calc(var(--dsh-composer-side-clearance, 0px) + 16px) 0px",
|
|
1536
|
+
fontSize: "var(--dsh-content-font-size-secondary, 13px)",
|
|
1537
|
+
lineHeight: "calc(20px + var(--dsh-content-font-delta-secondary, 0px))",
|
|
1538
|
+
justifyContent: "center",
|
|
1539
|
+
gap: "12px",
|
|
1540
|
+
margin: "0 auto",
|
|
1541
|
+
display: "flex"
|
|
1542
|
+
},
|
|
1543
|
+
children: chipElement
|
|
1544
|
+
}
|
|
1545
|
+
);
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
// src/client/OpenVikingSettingsSection.tsx
|
|
1549
|
+
import { useState as useState3, useEffect as useEffect3 } from "react";
|
|
1550
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1551
|
+
var API_CONFIG = "/openviking-status/api/config";
|
|
1552
|
+
var API_TEST = "/openviking-status/api/test-connection";
|
|
1553
|
+
var SOURCE_LABELS = {
|
|
1554
|
+
ovcli: "Auto-detected from ~/.openviking/ovcli.conf",
|
|
1555
|
+
env: "Auto-detected from environment variables",
|
|
1556
|
+
ov: "Auto-detected from ~/.openviking/ov.conf",
|
|
1557
|
+
settings: "Custom override in DSH settings.yaml",
|
|
1558
|
+
default: "Default local configuration"
|
|
1559
|
+
};
|
|
1560
|
+
function OpenVikingSettingsSection({
|
|
1561
|
+
initialConfig,
|
|
1562
|
+
onConfigSaved,
|
|
1563
|
+
className,
|
|
1564
|
+
style
|
|
1565
|
+
}) {
|
|
1566
|
+
const [endpoint, setEndpoint] = useState3(
|
|
1567
|
+
initialConfig?.endpoint || "http://127.0.0.1:1933"
|
|
1568
|
+
);
|
|
1569
|
+
const [apiKey, setApiKey] = useState3("");
|
|
1570
|
+
const [showKey, setShowKey] = useState3(false);
|
|
1571
|
+
const [source, setSource] = useState3(
|
|
1572
|
+
initialConfig?.source || "default"
|
|
1573
|
+
);
|
|
1574
|
+
const [hasStoredKey, setHasStoredKey] = useState3(
|
|
1575
|
+
initialConfig?.hasApiKey || false
|
|
1576
|
+
);
|
|
1577
|
+
const [loading, setLoading] = useState3(!initialConfig);
|
|
1578
|
+
const [testing, setTesting] = useState3(false);
|
|
1579
|
+
const [saving, setSaving] = useState3(false);
|
|
1580
|
+
const [testResult, setTestResult] = useState3(null);
|
|
1581
|
+
const [flash, setFlash] = useState3(null);
|
|
1582
|
+
useEffect3(() => {
|
|
1583
|
+
if (initialConfig) return;
|
|
1584
|
+
let active = true;
|
|
1585
|
+
async function fetchConfig() {
|
|
1586
|
+
try {
|
|
1587
|
+
setLoading(true);
|
|
1588
|
+
const res = await fetch(API_CONFIG, { cache: "no-store" });
|
|
1589
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
1590
|
+
const data = await res.json();
|
|
1591
|
+
if (!active) return;
|
|
1592
|
+
const newEp = data.endpoint || "http://127.0.0.1:1933";
|
|
1593
|
+
setEndpoint(newEp);
|
|
1594
|
+
setSource(data.source || "default");
|
|
1595
|
+
setHasStoredKey(data.hasApiKey);
|
|
1596
|
+
defaultOpenVikingClient.clearResolvedSessions();
|
|
1597
|
+
} catch {
|
|
1598
|
+
} finally {
|
|
1599
|
+
if (active) setLoading(false);
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
void fetchConfig();
|
|
1603
|
+
return () => {
|
|
1604
|
+
active = false;
|
|
1605
|
+
};
|
|
1606
|
+
}, [initialConfig]);
|
|
1607
|
+
async function handleTestConnection() {
|
|
1608
|
+
setTesting(true);
|
|
1609
|
+
setTestResult(null);
|
|
1610
|
+
setFlash(null);
|
|
1611
|
+
try {
|
|
1612
|
+
const res = await fetch(API_TEST, {
|
|
1613
|
+
method: "POST",
|
|
1614
|
+
headers: { "Content-Type": "application/json" },
|
|
1615
|
+
body: JSON.stringify({
|
|
1616
|
+
endpoint: endpoint.trim(),
|
|
1617
|
+
apiKey: apiKey.trim() || void 0
|
|
1618
|
+
})
|
|
1619
|
+
});
|
|
1620
|
+
const data = await res.json();
|
|
1621
|
+
setTestResult(data);
|
|
1622
|
+
} catch (err) {
|
|
1623
|
+
setTestResult({
|
|
1624
|
+
ok: false,
|
|
1625
|
+
authenticated: false,
|
|
1626
|
+
error: String(err instanceof Error ? err.message : err)
|
|
1627
|
+
});
|
|
1628
|
+
} finally {
|
|
1629
|
+
setTesting(false);
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
async function handleSave() {
|
|
1633
|
+
setSaving(true);
|
|
1634
|
+
setFlash(null);
|
|
1635
|
+
try {
|
|
1636
|
+
const res = await fetch(API_CONFIG, {
|
|
1637
|
+
method: "POST",
|
|
1638
|
+
headers: { "Content-Type": "application/json" },
|
|
1639
|
+
body: JSON.stringify({
|
|
1640
|
+
endpoint: endpoint.trim(),
|
|
1641
|
+
apiKey: apiKey.trim() || void 0
|
|
1642
|
+
})
|
|
1643
|
+
});
|
|
1644
|
+
const data = await res.json();
|
|
1645
|
+
if (!res.ok || data.error) {
|
|
1646
|
+
throw new Error(data.error || `HTTP ${res.status}`);
|
|
1647
|
+
}
|
|
1648
|
+
setFlash({ kind: "ok", message: "Settings saved successfully" });
|
|
1649
|
+
setSource("settings");
|
|
1650
|
+
defaultOpenVikingClient.clearResolvedSessions();
|
|
1651
|
+
if (apiKey.trim()) {
|
|
1652
|
+
setHasStoredKey(true);
|
|
1653
|
+
setApiKey("");
|
|
1654
|
+
}
|
|
1655
|
+
onConfigSaved?.(
|
|
1656
|
+
data.config || {
|
|
1657
|
+
endpoint,
|
|
1658
|
+
hasApiKey: hasStoredKey || Boolean(apiKey.trim()),
|
|
1659
|
+
source: "settings"
|
|
1660
|
+
}
|
|
1661
|
+
);
|
|
1662
|
+
} catch (err) {
|
|
1663
|
+
setFlash({
|
|
1664
|
+
kind: "err",
|
|
1665
|
+
message: `Failed to save: ${err instanceof Error ? err.message : String(err)}`
|
|
1666
|
+
});
|
|
1667
|
+
} finally {
|
|
1668
|
+
setSaving(false);
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
async function handleReset() {
|
|
1672
|
+
setSaving(true);
|
|
1673
|
+
setFlash(null);
|
|
1674
|
+
setTestResult(null);
|
|
1675
|
+
try {
|
|
1676
|
+
const res = await fetch(API_CONFIG, {
|
|
1677
|
+
method: "POST",
|
|
1678
|
+
headers: { "Content-Type": "application/json" },
|
|
1679
|
+
body: JSON.stringify({ reset: true })
|
|
1680
|
+
});
|
|
1681
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
1682
|
+
const cfgRes = await fetch(API_CONFIG, { cache: "no-store" });
|
|
1683
|
+
if (cfgRes.ok) {
|
|
1684
|
+
const data = await cfgRes.json();
|
|
1685
|
+
const newEp = data.endpoint || "http://127.0.0.1:1933";
|
|
1686
|
+
setEndpoint(newEp);
|
|
1687
|
+
setSource(data.source || "default");
|
|
1688
|
+
setHasStoredKey(data.hasApiKey);
|
|
1689
|
+
setApiKey("");
|
|
1690
|
+
defaultOpenVikingClient.clearResolvedSessions();
|
|
1691
|
+
setFlash({
|
|
1692
|
+
kind: "ok",
|
|
1693
|
+
message: "Reset to auto-detected local settings"
|
|
1694
|
+
});
|
|
1695
|
+
onConfigSaved?.(data);
|
|
1696
|
+
}
|
|
1697
|
+
} catch (err) {
|
|
1698
|
+
setFlash({
|
|
1699
|
+
kind: "err",
|
|
1700
|
+
message: `Failed to reset: ${err instanceof Error ? err.message : String(err)}`
|
|
1701
|
+
});
|
|
1702
|
+
} finally {
|
|
1703
|
+
setSaving(false);
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
const sourceBadgeText = SOURCE_LABELS[source] || SOURCE_LABELS["default"];
|
|
1707
|
+
return /* @__PURE__ */ jsxs3(
|
|
1708
|
+
"div",
|
|
1709
|
+
{
|
|
1710
|
+
className: `ov-settings-root ${className || ""}`,
|
|
1711
|
+
style: {
|
|
1712
|
+
display: "flex",
|
|
1713
|
+
flexDirection: "column",
|
|
1714
|
+
gap: 20,
|
|
1715
|
+
maxWidth: 720,
|
|
1716
|
+
padding: "24px 28px",
|
|
1717
|
+
color: themeVar("labelPrimary"),
|
|
1718
|
+
fontSize: 14,
|
|
1719
|
+
lineHeight: 1.6,
|
|
1720
|
+
...style
|
|
1721
|
+
},
|
|
1722
|
+
children: [
|
|
1723
|
+
/* @__PURE__ */ jsxs3("div", { children: [
|
|
1724
|
+
/* @__PURE__ */ jsxs3(
|
|
1725
|
+
"div",
|
|
1726
|
+
{
|
|
1727
|
+
style: {
|
|
1728
|
+
display: "flex",
|
|
1729
|
+
alignItems: "baseline",
|
|
1730
|
+
gap: 12,
|
|
1731
|
+
marginBottom: 6
|
|
1732
|
+
},
|
|
1733
|
+
children: [
|
|
1734
|
+
/* @__PURE__ */ jsx3(
|
|
1735
|
+
"h2",
|
|
1736
|
+
{
|
|
1737
|
+
style: {
|
|
1738
|
+
fontSize: 20,
|
|
1739
|
+
fontWeight: 600,
|
|
1740
|
+
margin: 0,
|
|
1741
|
+
color: themeVar("labelPrimary")
|
|
1742
|
+
},
|
|
1743
|
+
children: "OpenViking Status"
|
|
1744
|
+
}
|
|
1745
|
+
),
|
|
1746
|
+
/* @__PURE__ */ jsx3(
|
|
1747
|
+
"span",
|
|
1748
|
+
{
|
|
1749
|
+
style: {
|
|
1750
|
+
fontSize: 12,
|
|
1751
|
+
fontWeight: 500,
|
|
1752
|
+
padding: "2px 8px",
|
|
1753
|
+
borderRadius: 6,
|
|
1754
|
+
background: themeVar("insetSurface"),
|
|
1755
|
+
border: `1px solid ${themeVar("hairline")}`,
|
|
1756
|
+
color: themeVar("labelSecondary")
|
|
1757
|
+
},
|
|
1758
|
+
children: sourceBadgeText
|
|
1759
|
+
}
|
|
1760
|
+
)
|
|
1761
|
+
]
|
|
1762
|
+
}
|
|
1763
|
+
),
|
|
1764
|
+
/* @__PURE__ */ jsx3(
|
|
1765
|
+
"p",
|
|
1766
|
+
{
|
|
1767
|
+
style: { margin: 0, color: themeVar("labelSecondary"), fontSize: 13 },
|
|
1768
|
+
children: "Configure connection credentials for monitoring OpenViking persistent memory and session status."
|
|
1769
|
+
}
|
|
1770
|
+
)
|
|
1771
|
+
] }),
|
|
1772
|
+
/* @__PURE__ */ jsxs3(
|
|
1773
|
+
"div",
|
|
1774
|
+
{
|
|
1775
|
+
style: {
|
|
1776
|
+
border: `1px solid ${themeVar("hairline")}`,
|
|
1777
|
+
borderRadius: 12,
|
|
1778
|
+
padding: 20,
|
|
1779
|
+
background: themeVar("insetSurface"),
|
|
1780
|
+
display: "flex",
|
|
1781
|
+
flexDirection: "column",
|
|
1782
|
+
gap: 16
|
|
1783
|
+
},
|
|
1784
|
+
children: [
|
|
1785
|
+
/* @__PURE__ */ jsxs3("div", { children: [
|
|
1786
|
+
/* @__PURE__ */ jsx3(
|
|
1787
|
+
"label",
|
|
1788
|
+
{
|
|
1789
|
+
style: {
|
|
1790
|
+
display: "block",
|
|
1791
|
+
fontSize: 13,
|
|
1792
|
+
fontWeight: 600,
|
|
1793
|
+
marginBottom: 6,
|
|
1794
|
+
color: themeVar("labelPrimary")
|
|
1795
|
+
},
|
|
1796
|
+
children: "Daemon Endpoint"
|
|
1797
|
+
}
|
|
1798
|
+
),
|
|
1799
|
+
/* @__PURE__ */ jsx3(
|
|
1800
|
+
"input",
|
|
1801
|
+
{
|
|
1802
|
+
type: "text",
|
|
1803
|
+
value: endpoint,
|
|
1804
|
+
onChange: (e) => setEndpoint(e.target.value),
|
|
1805
|
+
placeholder: "http://127.0.0.1:1933",
|
|
1806
|
+
style: {
|
|
1807
|
+
width: "100%",
|
|
1808
|
+
boxSizing: "border-box",
|
|
1809
|
+
padding: "9px 12px",
|
|
1810
|
+
fontSize: 14,
|
|
1811
|
+
fontFamily: themeVar("fontMono"),
|
|
1812
|
+
borderRadius: 8,
|
|
1813
|
+
border: `1px solid ${themeVar("hairline")}`,
|
|
1814
|
+
background: themeVar("panelSurface"),
|
|
1815
|
+
color: themeVar("labelPrimary"),
|
|
1816
|
+
outline: "none"
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
),
|
|
1820
|
+
/* @__PURE__ */ jsx3(
|
|
1821
|
+
"span",
|
|
1822
|
+
{
|
|
1823
|
+
style: {
|
|
1824
|
+
fontSize: 12,
|
|
1825
|
+
color: themeVar("labelTertiary"),
|
|
1826
|
+
marginTop: 4,
|
|
1827
|
+
display: "block"
|
|
1828
|
+
},
|
|
1829
|
+
children: "The URL of the local or remote OpenViking HTTP server. Resolved from the DSH host."
|
|
1830
|
+
}
|
|
1831
|
+
)
|
|
1832
|
+
] }),
|
|
1833
|
+
/* @__PURE__ */ jsxs3("div", { children: [
|
|
1834
|
+
/* @__PURE__ */ jsxs3(
|
|
1835
|
+
"div",
|
|
1836
|
+
{
|
|
1837
|
+
style: {
|
|
1838
|
+
display: "flex",
|
|
1839
|
+
justifyContent: "space-between",
|
|
1840
|
+
alignItems: "center",
|
|
1841
|
+
marginBottom: 6
|
|
1842
|
+
},
|
|
1843
|
+
children: [
|
|
1844
|
+
/* @__PURE__ */ jsx3(
|
|
1845
|
+
"label",
|
|
1846
|
+
{
|
|
1847
|
+
style: {
|
|
1848
|
+
fontSize: 13,
|
|
1849
|
+
fontWeight: 600,
|
|
1850
|
+
color: themeVar("labelPrimary")
|
|
1851
|
+
},
|
|
1852
|
+
children: "API Token (Authentication)"
|
|
1853
|
+
}
|
|
1854
|
+
),
|
|
1855
|
+
hasStoredKey && !apiKey && /* @__PURE__ */ jsx3(
|
|
1856
|
+
"span",
|
|
1857
|
+
{
|
|
1858
|
+
style: {
|
|
1859
|
+
fontSize: 12,
|
|
1860
|
+
color: themeVar("stateSuccess"),
|
|
1861
|
+
fontWeight: 500
|
|
1862
|
+
},
|
|
1863
|
+
children: "\u25CF Active token configured"
|
|
1864
|
+
}
|
|
1865
|
+
)
|
|
1866
|
+
]
|
|
1867
|
+
}
|
|
1868
|
+
),
|
|
1869
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: 8 }, children: [
|
|
1870
|
+
/* @__PURE__ */ jsx3(
|
|
1871
|
+
"input",
|
|
1872
|
+
{
|
|
1873
|
+
type: showKey ? "text" : "password",
|
|
1874
|
+
value: apiKey,
|
|
1875
|
+
onChange: (e) => setApiKey(e.target.value),
|
|
1876
|
+
placeholder: hasStoredKey ? "(Token stored \u2014 leave blank to keep unchanged)" : "Optional or required if daemon uses auth_mode: api_key",
|
|
1877
|
+
style: {
|
|
1878
|
+
flex: 1,
|
|
1879
|
+
padding: "9px 12px",
|
|
1880
|
+
fontSize: 14,
|
|
1881
|
+
fontFamily: themeVar("fontMono"),
|
|
1882
|
+
borderRadius: 8,
|
|
1883
|
+
border: `1px solid ${themeVar("hairline")}`,
|
|
1884
|
+
background: themeVar("panelSurface"),
|
|
1885
|
+
color: themeVar("labelPrimary"),
|
|
1886
|
+
outline: "none"
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
),
|
|
1890
|
+
/* @__PURE__ */ jsx3(
|
|
1891
|
+
"button",
|
|
1892
|
+
{
|
|
1893
|
+
type: "button",
|
|
1894
|
+
onClick: () => setShowKey((v) => !v),
|
|
1895
|
+
style: {
|
|
1896
|
+
padding: "0 14px",
|
|
1897
|
+
fontSize: 13,
|
|
1898
|
+
fontWeight: 500,
|
|
1899
|
+
borderRadius: 8,
|
|
1900
|
+
border: `1px solid ${themeVar("hairline")}`,
|
|
1901
|
+
background: themeVar("panelSurface"),
|
|
1902
|
+
color: themeVar("labelSecondary"),
|
|
1903
|
+
cursor: "pointer"
|
|
1904
|
+
},
|
|
1905
|
+
children: showKey ? "Hide" : "Show"
|
|
1906
|
+
}
|
|
1907
|
+
)
|
|
1908
|
+
] }),
|
|
1909
|
+
/* @__PURE__ */ jsx3(
|
|
1910
|
+
"span",
|
|
1911
|
+
{
|
|
1912
|
+
style: {
|
|
1913
|
+
fontSize: 12,
|
|
1914
|
+
color: themeVar("labelTertiary"),
|
|
1915
|
+
marginTop: 4,
|
|
1916
|
+
display: "block"
|
|
1917
|
+
},
|
|
1918
|
+
children: "Required when the daemon runs with auth_mode: api_key. Local tokens are typically found in ~/.openviking/ovcli.conf."
|
|
1919
|
+
}
|
|
1920
|
+
)
|
|
1921
|
+
] }),
|
|
1922
|
+
testResult && /* @__PURE__ */ jsxs3(
|
|
1923
|
+
"div",
|
|
1924
|
+
{
|
|
1925
|
+
style: {
|
|
1926
|
+
padding: "10px 14px",
|
|
1927
|
+
borderRadius: 8,
|
|
1928
|
+
fontSize: 13,
|
|
1929
|
+
display: "flex",
|
|
1930
|
+
alignItems: "center",
|
|
1931
|
+
gap: 8,
|
|
1932
|
+
border: `1px solid ${testResult.ok && testResult.authenticated ? themeVar("stateSuccess") : themeVar("stateError")}`,
|
|
1933
|
+
background: themeVar("panelSurface"),
|
|
1934
|
+
color: testResult.ok && testResult.authenticated ? themeVar("stateSuccess") : themeVar("stateError")
|
|
1935
|
+
},
|
|
1936
|
+
children: [
|
|
1937
|
+
/* @__PURE__ */ jsx3("span", { children: testResult.ok && testResult.authenticated ? "\u25CF" : "\u2715" }),
|
|
1938
|
+
/* @__PURE__ */ jsx3("div", { style: { flex: 1 }, children: testResult.ok && testResult.authenticated ? /* @__PURE__ */ jsxs3("div", { children: [
|
|
1939
|
+
/* @__PURE__ */ jsx3("strong", { children: "Connected successfully" }),
|
|
1940
|
+
testResult.version && /* @__PURE__ */ jsxs3("span", { children: [
|
|
1941
|
+
" \xB7 ",
|
|
1942
|
+
testResult.version
|
|
1943
|
+
] }),
|
|
1944
|
+
testResult.storage && /* @__PURE__ */ jsxs3("span", { children: [
|
|
1945
|
+
" (storage: ",
|
|
1946
|
+
testResult.storage,
|
|
1947
|
+
")"
|
|
1948
|
+
] })
|
|
1949
|
+
] }) : /* @__PURE__ */ jsxs3("div", { children: [
|
|
1950
|
+
/* @__PURE__ */ jsx3("strong", { children: "Connection failed: " }),
|
|
1951
|
+
/* @__PURE__ */ jsx3("span", { children: testResult.error || "Unable to reach daemon or token unauthorized" })
|
|
1952
|
+
] }) })
|
|
1953
|
+
]
|
|
1954
|
+
}
|
|
1955
|
+
),
|
|
1956
|
+
/* @__PURE__ */ jsxs3(
|
|
1957
|
+
"div",
|
|
1958
|
+
{
|
|
1959
|
+
style: {
|
|
1960
|
+
display: "flex",
|
|
1961
|
+
flexWrap: "wrap",
|
|
1962
|
+
alignItems: "center",
|
|
1963
|
+
gap: 10,
|
|
1964
|
+
paddingTop: 4
|
|
1965
|
+
},
|
|
1966
|
+
children: [
|
|
1967
|
+
/* @__PURE__ */ jsx3(
|
|
1968
|
+
"button",
|
|
1969
|
+
{
|
|
1970
|
+
type: "button",
|
|
1971
|
+
disabled: testing || loading,
|
|
1972
|
+
onClick: () => void handleTestConnection(),
|
|
1973
|
+
style: {
|
|
1974
|
+
padding: "8px 16px",
|
|
1975
|
+
fontSize: 13,
|
|
1976
|
+
fontWeight: 500,
|
|
1977
|
+
borderRadius: 8,
|
|
1978
|
+
border: `1px solid ${themeVar("hairline")}`,
|
|
1979
|
+
background: themeVar("panelSurface"),
|
|
1980
|
+
color: themeVar("labelPrimary"),
|
|
1981
|
+
cursor: testing ? "not-allowed" : "pointer",
|
|
1982
|
+
opacity: testing ? 0.6 : 1
|
|
1983
|
+
},
|
|
1984
|
+
children: testing ? "Testing..." : "Test Connection"
|
|
1985
|
+
}
|
|
1986
|
+
),
|
|
1987
|
+
/* @__PURE__ */ jsx3(
|
|
1988
|
+
"button",
|
|
1989
|
+
{
|
|
1990
|
+
type: "button",
|
|
1991
|
+
disabled: saving || loading,
|
|
1992
|
+
onClick: () => void handleSave(),
|
|
1993
|
+
style: {
|
|
1994
|
+
padding: "8px 18px",
|
|
1995
|
+
fontSize: 13,
|
|
1996
|
+
fontWeight: 600,
|
|
1997
|
+
borderRadius: 8,
|
|
1998
|
+
border: "none",
|
|
1999
|
+
background: themeVar("buttonPrimaryFill"),
|
|
2000
|
+
color: themeVar("buttonPrimaryText"),
|
|
2001
|
+
cursor: saving ? "not-allowed" : "pointer",
|
|
2002
|
+
opacity: saving ? 0.6 : 1
|
|
2003
|
+
},
|
|
2004
|
+
children: saving ? "Saving..." : "Save Settings"
|
|
2005
|
+
}
|
|
2006
|
+
),
|
|
2007
|
+
source === "settings" && /* @__PURE__ */ jsx3(
|
|
2008
|
+
"button",
|
|
2009
|
+
{
|
|
2010
|
+
type: "button",
|
|
2011
|
+
disabled: saving || loading,
|
|
2012
|
+
onClick: () => void handleReset(),
|
|
2013
|
+
style: {
|
|
2014
|
+
padding: "8px 14px",
|
|
2015
|
+
fontSize: 13,
|
|
2016
|
+
fontWeight: 500,
|
|
2017
|
+
borderRadius: 8,
|
|
2018
|
+
border: `1px solid ${themeVar("hairline")}`,
|
|
2019
|
+
background: "transparent",
|
|
2020
|
+
color: themeVar("labelSecondary"),
|
|
2021
|
+
cursor: "pointer",
|
|
2022
|
+
marginLeft: "auto"
|
|
2023
|
+
},
|
|
2024
|
+
children: "Reset to Auto-detected"
|
|
2025
|
+
}
|
|
2026
|
+
),
|
|
2027
|
+
flash && /* @__PURE__ */ jsx3(
|
|
2028
|
+
"span",
|
|
2029
|
+
{
|
|
2030
|
+
style: {
|
|
2031
|
+
fontSize: 13,
|
|
2032
|
+
color: flash.kind === "ok" ? themeVar("stateSuccess") : themeVar("stateError"),
|
|
2033
|
+
fontWeight: 500
|
|
2034
|
+
},
|
|
2035
|
+
children: flash.message
|
|
2036
|
+
}
|
|
2037
|
+
)
|
|
2038
|
+
]
|
|
2039
|
+
}
|
|
2040
|
+
)
|
|
2041
|
+
]
|
|
2042
|
+
}
|
|
2043
|
+
),
|
|
2044
|
+
/* @__PURE__ */ jsxs3(
|
|
2045
|
+
"div",
|
|
2046
|
+
{
|
|
2047
|
+
style: {
|
|
2048
|
+
border: `1px solid ${themeVar("hairline")}`,
|
|
2049
|
+
borderRadius: 10,
|
|
2050
|
+
padding: "14px 18px",
|
|
2051
|
+
background: themeVar("panelSurface"),
|
|
2052
|
+
fontSize: 13,
|
|
2053
|
+
color: themeVar("labelSecondary"),
|
|
2054
|
+
lineHeight: 1.5
|
|
2055
|
+
},
|
|
2056
|
+
children: [
|
|
2057
|
+
/* @__PURE__ */ jsx3(
|
|
2058
|
+
"p",
|
|
2059
|
+
{
|
|
2060
|
+
style: {
|
|
2061
|
+
margin: "0 0 6px 0",
|
|
2062
|
+
fontWeight: 600,
|
|
2063
|
+
color: themeVar("labelPrimary")
|
|
2064
|
+
},
|
|
2065
|
+
children: "How OpenViking connection works:"
|
|
2066
|
+
}
|
|
2067
|
+
),
|
|
2068
|
+
/* @__PURE__ */ jsxs3("ul", { style: { margin: 0, paddingLeft: 18 }, children: [
|
|
2069
|
+
/* @__PURE__ */ jsx3("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." }),
|
|
2070
|
+
/* @__PURE__ */ jsxs3("li", { style: { marginBottom: 4 }, children: [
|
|
2071
|
+
"If OpenViking runs locally on the standard port (1933), the plugin auto-detects credentials from ",
|
|
2072
|
+
/* @__PURE__ */ jsx3("code", { children: "~/.openviking/ovcli.conf" }),
|
|
2073
|
+
"."
|
|
2074
|
+
] }),
|
|
2075
|
+
/* @__PURE__ */ jsxs3("li", { children: [
|
|
2076
|
+
"Custom values saved here are persisted in",
|
|
2077
|
+
" ",
|
|
2078
|
+
/* @__PURE__ */ jsx3("code", { children: "~/.dsh/settings.yaml" }),
|
|
2079
|
+
" under the",
|
|
2080
|
+
" ",
|
|
2081
|
+
/* @__PURE__ */ jsx3("code", { children: "openviking-status" }),
|
|
2082
|
+
" namespace."
|
|
2083
|
+
] })
|
|
2084
|
+
] })
|
|
2085
|
+
]
|
|
2086
|
+
}
|
|
2087
|
+
)
|
|
2088
|
+
]
|
|
2089
|
+
}
|
|
2090
|
+
);
|
|
1389
2091
|
}
|
|
1390
2092
|
|
|
1391
2093
|
// src/client/index.tsx
|
|
@@ -1407,11 +2109,27 @@ function apply(ctx) {
|
|
|
1407
2109
|
),
|
|
1408
2110
|
"openviking-status: composer stats chip"
|
|
1409
2111
|
);
|
|
2112
|
+
ctx.effect(
|
|
2113
|
+
() => ctx.slots.inject(
|
|
2114
|
+
"settings.section",
|
|
2115
|
+
() => ctx.slots.register(
|
|
2116
|
+
{
|
|
2117
|
+
name: "settings.section",
|
|
2118
|
+
id: "openviking-status",
|
|
2119
|
+
order: 35,
|
|
2120
|
+
label: () => "OpenViking"
|
|
2121
|
+
},
|
|
2122
|
+
OpenVikingSettingsSection
|
|
2123
|
+
)
|
|
2124
|
+
),
|
|
2125
|
+
"openviking-status: settings section"
|
|
2126
|
+
);
|
|
1410
2127
|
}
|
|
1411
2128
|
export {
|
|
1412
2129
|
COMMIT_THRESHOLD,
|
|
1413
2130
|
DEFAULT_OPENVIKING_ENDPOINT,
|
|
1414
2131
|
OpenVikingClient,
|
|
2132
|
+
OpenVikingSettingsSection,
|
|
1415
2133
|
OpenVikingStatusChip,
|
|
1416
2134
|
OpenVikingStatusPopover,
|
|
1417
2135
|
THEME,
|