opencami 1.6.1 → 1.8.2
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 +4 -2
- package/dist/client/assets/{CSPContext-CCZJblsW.js → CSPContext-DeJH85nm.js} +1 -1
- package/dist/client/assets/{DirectionContext-CAS2SgNN.js → DirectionContext-CxhRpXkm.js} +1 -1
- package/dist/client/assets/_sessionKey-CQE0brGK.js +23 -0
- package/dist/client/assets/agents-CMTFd_sG.js +2 -0
- package/dist/client/assets/agents-screen-BNQGEqcW.js +1 -0
- package/dist/client/assets/bots-B6oGzCxP.js +2 -0
- package/dist/client/assets/bots-screen-Be3cfGgq.js +1 -0
- package/dist/client/assets/button-D9Plv7hu.js +1 -0
- package/dist/client/assets/composite-B2KCZKKL.js +1 -0
- package/dist/client/assets/{connect-9Vns9nqk.js → connect-DuJfnyNK.js} +1 -1
- package/dist/client/assets/dashboard-00GpXm5V.js +1 -0
- package/dist/client/assets/event-DD8Cz4O9.js +1 -0
- package/dist/client/assets/file-explorer-screen-CxwemBES.js +1 -0
- package/dist/client/assets/files-DyBJVXBu.js +2 -0
- package/dist/client/assets/{index-BvN0Cj0s.js → index-DtGzE-ea.js} +1 -1
- package/dist/client/assets/{index-CRgPm0pb.js → index-Yo5UhdZV.js} +1 -1
- package/dist/client/assets/keyboard-shortcuts-dialog-BZwd-iyV.js +1 -0
- package/dist/client/assets/{main-ZPHfbCuz.js → main-CgwdHc9W.js} +27 -10
- package/dist/client/assets/{markdown-1-xJ1B1H.js → markdown-DtWnt4NA.js} +1 -1
- package/dist/client/assets/memory-l756yiNq.js +2 -0
- package/dist/client/assets/memory-screen-BQtVRuzE.js +1 -0
- package/dist/client/assets/menu-BsS6CDf_.js +1 -0
- package/dist/client/assets/{opencami-logo-CxC-KcS9.js → opencami-logo-Bmge6-FB.js} +1 -1
- package/dist/client/assets/popupStateMapping-D0ZbJR_o.js +1 -0
- package/dist/client/assets/{proxy-aJlrsYWj.js → proxy-CYZeDXoy.js} +1 -1
- package/dist/client/assets/{react-DuiuJSA1.js → react-DODKNyyU.js} +1 -1
- package/dist/client/assets/search-dialog-DW91SK30.js +1 -0
- package/dist/client/assets/session-export-dialog-CliO9Ob-.js +1 -0
- package/dist/client/assets/settings-dialog-C1u52aju.js +1 -0
- package/dist/client/assets/skills-8T_avaVb.js +2 -0
- package/dist/client/assets/{skills-panel-oNmWCyiv.js → skills-panel-DSiH-DLs.js} +1 -1
- package/dist/client/assets/styles-DvaLh0o1.css +1 -0
- package/dist/client/assets/switch-DbgQPO6i.js +1 -0
- package/dist/client/assets/tabs-BsAvZnlD.js +1 -0
- package/dist/client/assets/tooltip-DLmutB5C.js +1 -0
- package/dist/client/assets/use-file-explorer-state-Cg_yDYJl.js +12 -0
- package/dist/client/assets/useBaseUiId-KQTzRPLp.js +1 -0
- package/dist/client/assets/useCompositeItem-BPY2_hF_.js +1 -0
- package/dist/client/assets/{useControlled-byIifl1i.js → useControlled-B5pEEz2V.js} +1 -1
- package/dist/client/assets/{useMutation-D5JCmjGc.js → useMutation-BsQD6FKe.js} +1 -1
- package/dist/client/assets/useQuery-CmAJuY2W.js +1 -0
- package/dist/client/assets/visuallyHidden-COI6QeQH.js +1 -0
- package/dist/client/sw.js +5 -164
- package/dist/server/assets/{_sessionKey-BCdHKOq7.js → _sessionKey-Bq_fl7uv.js} +1070 -695
- package/dist/server/assets/_tanstack-start-manifest_v-BMCAWon2.js +4 -0
- package/dist/server/assets/dashboard-GCKodTiJ.js +214 -0
- package/dist/server/assets/{index-r4KOEzK3.js → index-C2hVqxBl.js} +2 -1
- package/dist/server/assets/{router-CkcOXH0V.js → router-bN_iTo0B.js} +518 -193
- package/dist/server/assets/{search-dialog-CuuZvlyq.js → search-dialog-DReM5ZD2.js} +3 -2
- package/dist/server/assets/settings-dialog-BUOrQN3Z.js +1511 -0
- package/dist/server/server.js +2 -2
- package/package.json +1 -1
- package/dist/client/assets/_sessionKey-f5UgmhlK.js +0 -14
- package/dist/client/assets/agents-DBx41wBT.js +0 -2
- package/dist/client/assets/agents-screen-CjqM2uOb.js +0 -1
- package/dist/client/assets/bots-BqD0EQcs.js +0 -2
- package/dist/client/assets/bots-screen-ivWEgfTv.js +0 -1
- package/dist/client/assets/button-DzGUU5Tc.js +0 -1
- package/dist/client/assets/composite-afaLtloO.js +0 -1
- package/dist/client/assets/file-explorer-screen-Di0232pk.js +0 -1
- package/dist/client/assets/files-BlMyTMb7.js +0 -2
- package/dist/client/assets/keyboard-shortcuts-dialog-C5kjcplH.js +0 -1
- package/dist/client/assets/memory-rR6pG57i.js +0 -2
- package/dist/client/assets/memory-screen-BV4YRKim.js +0 -1
- package/dist/client/assets/menu-9GT8MQlt.js +0 -1
- package/dist/client/assets/owner-Bm20thei.js +0 -1
- package/dist/client/assets/popupStateMapping-C797EAip.js +0 -1
- package/dist/client/assets/search-dialog-DD_ESAph.js +0 -1
- package/dist/client/assets/session-export-dialog-5X5WKL4z.js +0 -1
- package/dist/client/assets/settings-dialog-Bd0RXSk3.js +0 -1
- package/dist/client/assets/skills-DAKbQw5l.js +0 -2
- package/dist/client/assets/styles-Ecf_rLDJ.css +0 -1
- package/dist/client/assets/switch-BJY4FNiL.js +0 -1
- package/dist/client/assets/tabs-DBIBgGyG.js +0 -1
- package/dist/client/assets/tooltip-BoKzJ7ag.js +0 -1
- package/dist/client/assets/use-file-explorer-state-EK2HTABk.js +0 -12
- package/dist/client/assets/useButton-Bh6gEhdL.js +0 -1
- package/dist/client/assets/useCompositeItem-BR34_3gK.js +0 -1
- package/dist/client/assets/visuallyHidden-ChUPUs-q.js +0 -1
- package/dist/server/assets/_tanstack-start-manifest_v-XVyva8_b.js +0 -4
- package/dist/server/assets/settings-dialog-S2HICL7l.js +0 -1166
|
@@ -7,15 +7,23 @@ import { readFileSync, existsSync } from "node:fs";
|
|
|
7
7
|
import path, { join, resolve, relative, extname } from "node:path";
|
|
8
8
|
import os, { homedir } from "node:os";
|
|
9
9
|
import { json } from "@tanstack/router-core/ssr/client";
|
|
10
|
+
import { PassThrough, Readable } from "node:stream";
|
|
10
11
|
import { execSync } from "node:child_process";
|
|
11
12
|
import { readFile, mkdir, writeFile, rename, stat, readdir, rm, realpath, lstat } from "node:fs/promises";
|
|
12
13
|
import { posix } from "path";
|
|
13
|
-
const appCss = "/assets/styles-
|
|
14
|
+
const appCss = "/assets/styles-DvaLh0o1.css";
|
|
14
15
|
const swRegisterScript = `
|
|
15
16
|
(() => {
|
|
16
17
|
// Skip PWA service worker inside Capacitor native shell — they conflict
|
|
17
18
|
// with the native networking layer and caching.
|
|
18
19
|
if (window.Capacitor && window.Capacitor.isNativePlatform && window.Capacitor.isNativePlatform()) return;
|
|
20
|
+
// Unregister any existing service workers — old SW was breaking SSE streaming
|
|
21
|
+
if ('serviceWorker' in navigator) {
|
|
22
|
+
navigator.serviceWorker.getRegistrations().then((regs) => {
|
|
23
|
+
regs.forEach((reg) => reg.unregister());
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
if (false) { // SW disabled — causes streaming issues
|
|
19
27
|
if ('serviceWorker' in navigator) {
|
|
20
28
|
window.addEventListener('load', () => {
|
|
21
29
|
navigator.serviceWorker.register('/sw.js', { scope: '/' })
|
|
@@ -37,6 +45,7 @@ const swRegisterScript = `
|
|
|
37
45
|
.catch((err) => console.warn('[SW] Registration failed:', err));
|
|
38
46
|
});
|
|
39
47
|
}
|
|
48
|
+
}
|
|
40
49
|
})()
|
|
41
50
|
`;
|
|
42
51
|
const themeScript = `
|
|
@@ -55,16 +64,25 @@ const themeScript = `
|
|
|
55
64
|
const media = window.matchMedia('(prefers-color-scheme: dark)')
|
|
56
65
|
const apply = () => {
|
|
57
66
|
root.classList.remove('light', 'dark', 'system', 'chameleon', 'frost', 'frost-light', 'frost-dark')
|
|
67
|
+
root.style.colorScheme = ''
|
|
58
68
|
root.classList.add(theme)
|
|
59
|
-
|
|
69
|
+
|
|
70
|
+
const isFrostLight = theme === 'frost-light'
|
|
71
|
+
const isFrostDark = theme === 'frost-dark'
|
|
72
|
+
|
|
73
|
+
if (isFrostLight || isFrostDark) {
|
|
60
74
|
root.classList.add('frost')
|
|
61
75
|
}
|
|
62
|
-
if (
|
|
76
|
+
if (isFrostDark) {
|
|
63
77
|
root.classList.add('dark')
|
|
64
78
|
}
|
|
65
79
|
if (theme === 'system' && media.matches) {
|
|
66
80
|
root.classList.add('dark')
|
|
67
81
|
}
|
|
82
|
+
if (isFrostLight) {
|
|
83
|
+
root.classList.remove('dark')
|
|
84
|
+
root.style.colorScheme = 'light'
|
|
85
|
+
}
|
|
68
86
|
}
|
|
69
87
|
apply()
|
|
70
88
|
media.addEventListener('change', () => {
|
|
@@ -202,7 +220,7 @@ function NotFoundRedirect() {
|
|
|
202
220
|
}
|
|
203
221
|
return null;
|
|
204
222
|
}
|
|
205
|
-
const Route$
|
|
223
|
+
const Route$B = createRootRoute({
|
|
206
224
|
notFoundComponent: NotFoundRedirect,
|
|
207
225
|
head: () => ({
|
|
208
226
|
meta: [
|
|
@@ -310,12 +328,12 @@ function RootDocument({ children }) {
|
|
|
310
328
|
] })
|
|
311
329
|
] });
|
|
312
330
|
}
|
|
313
|
-
const $$splitComponentImporter$
|
|
314
|
-
const Route$
|
|
315
|
-
component: lazyRouteComponent($$splitComponentImporter$
|
|
331
|
+
const $$splitComponentImporter$9 = () => import("./skills-Cy8xclXY.js");
|
|
332
|
+
const Route$A = createFileRoute("/skills")({
|
|
333
|
+
component: lazyRouteComponent($$splitComponentImporter$9, "component")
|
|
316
334
|
});
|
|
317
|
-
const $$splitComponentImporter$
|
|
318
|
-
const Route$
|
|
335
|
+
const $$splitComponentImporter$8 = () => import("./new-Dzk5YxE9.js");
|
|
336
|
+
const Route$z = createFileRoute("/new")({
|
|
319
337
|
beforeLoad: function redirectToNewChat() {
|
|
320
338
|
throw redirect({
|
|
321
339
|
to: "/chat/$sessionKey",
|
|
@@ -325,34 +343,38 @@ const Route$v = createFileRoute("/new")({
|
|
|
325
343
|
replace: true
|
|
326
344
|
});
|
|
327
345
|
},
|
|
346
|
+
component: lazyRouteComponent($$splitComponentImporter$8, "component")
|
|
347
|
+
});
|
|
348
|
+
const $$splitComponentImporter$7 = () => import("./memory-BqZOoD7Q.js");
|
|
349
|
+
const Route$y = createFileRoute("/memory")({
|
|
328
350
|
component: lazyRouteComponent($$splitComponentImporter$7, "component")
|
|
329
351
|
});
|
|
330
|
-
const $$splitComponentImporter$6 = () => import("./
|
|
331
|
-
const Route$
|
|
352
|
+
const $$splitComponentImporter$6 = () => import("./files-DYdXlQDr.js");
|
|
353
|
+
const Route$x = createFileRoute("/files")({
|
|
332
354
|
component: lazyRouteComponent($$splitComponentImporter$6, "component")
|
|
333
355
|
});
|
|
334
|
-
const $$splitComponentImporter$5 = () => import("./
|
|
335
|
-
const Route$
|
|
356
|
+
const $$splitComponentImporter$5 = () => import("./dashboard-GCKodTiJ.js");
|
|
357
|
+
const Route$w = createFileRoute("/dashboard")({
|
|
336
358
|
component: lazyRouteComponent($$splitComponentImporter$5, "component")
|
|
337
359
|
});
|
|
338
360
|
const $$splitComponentImporter$4 = () => import("./connect-CbgijWz4.js");
|
|
339
|
-
const Route$
|
|
361
|
+
const Route$v = createFileRoute("/connect")({
|
|
340
362
|
component: lazyRouteComponent($$splitComponentImporter$4, "component")
|
|
341
363
|
});
|
|
342
364
|
const $$splitComponentImporter$3 = () => import("./bots-Byt6jv0a.js");
|
|
343
|
-
const Route$
|
|
365
|
+
const Route$u = createFileRoute("/bots")({
|
|
344
366
|
component: lazyRouteComponent($$splitComponentImporter$3, "component")
|
|
345
367
|
});
|
|
346
368
|
const $$splitComponentImporter$2 = () => import("./agents-CmQ4vvXm.js");
|
|
347
|
-
const Route$
|
|
369
|
+
const Route$t = createFileRoute("/agents")({
|
|
348
370
|
component: lazyRouteComponent($$splitComponentImporter$2, "component")
|
|
349
371
|
});
|
|
350
|
-
const $$splitComponentImporter$1 = () => import("./index-
|
|
351
|
-
const Route$
|
|
372
|
+
const $$splitComponentImporter$1 = () => import("./index-C2hVqxBl.js");
|
|
373
|
+
const Route$s = createFileRoute("/")({
|
|
352
374
|
component: lazyRouteComponent($$splitComponentImporter$1, "component")
|
|
353
375
|
});
|
|
354
|
-
const $$splitComponentImporter = () => import("./_sessionKey-
|
|
355
|
-
const Route$
|
|
376
|
+
const $$splitComponentImporter = () => import("./_sessionKey-Bq_fl7uv.js").then((n) => n.$);
|
|
377
|
+
const Route$r = createFileRoute("/chat/$sessionKey")({
|
|
356
378
|
component: lazyRouteComponent($$splitComponentImporter, "component")
|
|
357
379
|
});
|
|
358
380
|
function getGatewayConfig() {
|
|
@@ -614,10 +636,12 @@ class PersistentGatewayConnection {
|
|
|
614
636
|
}
|
|
615
637
|
}
|
|
616
638
|
let _instance = null;
|
|
639
|
+
const _g = globalThis;
|
|
617
640
|
function getPersistentConnection() {
|
|
618
|
-
if (!
|
|
619
|
-
|
|
641
|
+
if (!_g.__opencamiGatewayInstance) {
|
|
642
|
+
_g.__opencamiGatewayInstance = new PersistentGatewayConnection();
|
|
620
643
|
}
|
|
644
|
+
_instance = _g.__opencamiGatewayInstance;
|
|
621
645
|
return _instance;
|
|
622
646
|
}
|
|
623
647
|
async function gatewayRpc(method, params) {
|
|
@@ -719,7 +743,7 @@ async function ttsEdge(text, voice) {
|
|
|
719
743
|
}
|
|
720
744
|
});
|
|
721
745
|
}
|
|
722
|
-
const Route$
|
|
746
|
+
const Route$q = createFileRoute("/api/tts")({
|
|
723
747
|
server: {
|
|
724
748
|
handlers: {
|
|
725
749
|
POST: async ({ request }) => {
|
|
@@ -874,7 +898,7 @@ async function sttOpenAI(audioBlob, apiKey, language) {
|
|
|
874
898
|
const data = await res.json();
|
|
875
899
|
return { text: data.text || "" };
|
|
876
900
|
}
|
|
877
|
-
const Route$
|
|
901
|
+
const Route$p = createFileRoute("/api/stt")({
|
|
878
902
|
server: {
|
|
879
903
|
handlers: {
|
|
880
904
|
POST: async ({ request }) => {
|
|
@@ -976,7 +1000,7 @@ const Route$m = createFileRoute("/api/stt")({
|
|
|
976
1000
|
}
|
|
977
1001
|
}
|
|
978
1002
|
});
|
|
979
|
-
const Route$
|
|
1003
|
+
const Route$o = createFileRoute("/api/stream")({
|
|
980
1004
|
server: {
|
|
981
1005
|
handlers: {
|
|
982
1006
|
GET: async ({ request }) => {
|
|
@@ -988,88 +1012,86 @@ const Route$l = createFileRoute("/api/stream")({
|
|
|
988
1012
|
{ status: 400, headers: { "content-type": "application/json" } }
|
|
989
1013
|
);
|
|
990
1014
|
}
|
|
1015
|
+
const pass = new PassThrough();
|
|
991
1016
|
const encoder = new TextEncoder();
|
|
992
|
-
let unsubscribe = null;
|
|
993
1017
|
let closed = false;
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
try {
|
|
1000
|
-
controller.enqueue(
|
|
1001
|
-
encoder.encode(`event: ${event}
|
|
1018
|
+
let unsubscribe = null;
|
|
1019
|
+
function sendSSE(event, data) {
|
|
1020
|
+
if (closed) return;
|
|
1021
|
+
try {
|
|
1022
|
+
pass.write(encoder.encode(`event: ${event}
|
|
1002
1023
|
data: ${JSON.stringify(data)}
|
|
1003
1024
|
|
|
1004
|
-
`)
|
|
1005
|
-
|
|
1006
|
-
|
|
1025
|
+
`));
|
|
1026
|
+
} catch {
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
function cleanup() {
|
|
1030
|
+
if (closed) return;
|
|
1031
|
+
closed = true;
|
|
1032
|
+
if (unsubscribe) {
|
|
1033
|
+
unsubscribe();
|
|
1034
|
+
unsubscribe = null;
|
|
1035
|
+
}
|
|
1036
|
+
try {
|
|
1037
|
+
pass.end();
|
|
1038
|
+
} catch {
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
pass.write(encoder.encode(": connected\n\n"));
|
|
1042
|
+
let gotAgentStream = false;
|
|
1043
|
+
unsubscribe = subscribeGatewayEvents(sessionKey, (evt) => {
|
|
1044
|
+
if (evt.event === "agent") {
|
|
1045
|
+
const payload = evt.payload;
|
|
1046
|
+
const agentStream = payload.stream;
|
|
1047
|
+
if (agentStream === "assistant") {
|
|
1048
|
+
gotAgentStream = true;
|
|
1049
|
+
const data = payload.data ?? payload;
|
|
1050
|
+
const text = typeof data.delta === "string" ? data.delta : typeof data.text === "string" ? data.text : typeof payload.text === "string" ? payload.text : typeof payload.delta === "string" ? payload.delta : "";
|
|
1051
|
+
if (text) {
|
|
1052
|
+
sendSSE("delta", { text, sessionKey });
|
|
1053
|
+
}
|
|
1054
|
+
} else if (agentStream === "tool") {
|
|
1055
|
+
gotAgentStream = true;
|
|
1056
|
+
const tdata = payload.data ?? payload;
|
|
1057
|
+
sendSSE("tool", {
|
|
1058
|
+
name: tdata.name ?? tdata.toolName ?? payload.name ?? "",
|
|
1059
|
+
status: tdata.phase ?? tdata.status ?? payload.phase ?? "running",
|
|
1060
|
+
id: tdata.id ?? tdata.toolCallId ?? payload.id ?? "",
|
|
1061
|
+
sessionKey
|
|
1062
|
+
});
|
|
1063
|
+
} else if (agentStream === "lifecycle") {
|
|
1064
|
+
const ldata = payload.data ?? payload;
|
|
1065
|
+
const phase = ldata.phase ?? payload.phase;
|
|
1066
|
+
if (phase === "end" || phase === "error") {
|
|
1067
|
+
sendSSE("done", {
|
|
1068
|
+
sessionKey,
|
|
1069
|
+
status: phase,
|
|
1070
|
+
error: phase === "error" ? payload.error : void 0
|
|
1071
|
+
});
|
|
1072
|
+
cleanup();
|
|
1007
1073
|
}
|
|
1008
1074
|
}
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
sendSSE("delta", { text, sessionKey });
|
|
1020
|
-
}
|
|
1021
|
-
} else if (agentStream === "tool") {
|
|
1022
|
-
gotAgentStream = true;
|
|
1023
|
-
const tdata = payload.data ?? payload;
|
|
1024
|
-
sendSSE("tool", {
|
|
1025
|
-
name: tdata.name ?? tdata.toolName ?? payload.name ?? "",
|
|
1026
|
-
status: tdata.phase ?? tdata.status ?? payload.phase ?? "running",
|
|
1027
|
-
id: tdata.id ?? tdata.toolCallId ?? payload.id ?? "",
|
|
1028
|
-
sessionKey
|
|
1029
|
-
});
|
|
1030
|
-
} else if (agentStream === "lifecycle") {
|
|
1031
|
-
const ldata = payload.data ?? payload;
|
|
1032
|
-
const phase = ldata.phase ?? payload.phase;
|
|
1033
|
-
if (phase === "end" || phase === "error") {
|
|
1034
|
-
sendSSE("done", {
|
|
1035
|
-
sessionKey,
|
|
1036
|
-
status: phase,
|
|
1037
|
-
error: phase === "error" ? payload.error : void 0
|
|
1038
|
-
});
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
} else if (evt.event === "chat") {
|
|
1042
|
-
const payload = evt.payload;
|
|
1043
|
-
const kind = payload.kind;
|
|
1044
|
-
if (kind === "delta" && !gotAgentStream) {
|
|
1045
|
-
const text = typeof payload.text === "string" ? payload.text : typeof payload.delta === "string" ? payload.delta : "";
|
|
1046
|
-
if (text) {
|
|
1047
|
-
sendSSE("delta", { text, sessionKey });
|
|
1048
|
-
}
|
|
1049
|
-
} else if (kind === "final") {
|
|
1050
|
-
sendSSE("done", { sessionKey, status: "end" });
|
|
1051
|
-
}
|
|
1075
|
+
} else if (evt.event === "chat") {
|
|
1076
|
+
const payload = evt.payload;
|
|
1077
|
+
const state = payload.state ?? payload.kind;
|
|
1078
|
+
const msg = payload.message;
|
|
1079
|
+
if (state === "delta" && !gotAgentStream) {
|
|
1080
|
+
const content = Array.isArray(msg?.content) ? msg.content : [];
|
|
1081
|
+
const firstBlock = content[0];
|
|
1082
|
+
const text = typeof firstBlock?.text === "string" ? firstBlock.text : typeof payload.text === "string" ? payload.text : typeof payload.delta === "string" ? payload.delta : "";
|
|
1083
|
+
if (text) {
|
|
1084
|
+
sendSSE("delta", { text, sessionKey });
|
|
1052
1085
|
}
|
|
1053
|
-
})
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
closed = true;
|
|
1057
|
-
if (unsubscribe) {
|
|
1058
|
-
unsubscribe();
|
|
1059
|
-
unsubscribe = null;
|
|
1086
|
+
} else if (state === "final") {
|
|
1087
|
+
sendSSE("done", { sessionKey, status: "end" });
|
|
1088
|
+
cleanup();
|
|
1060
1089
|
}
|
|
1061
1090
|
}
|
|
1062
1091
|
});
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
if (unsubscribe) {
|
|
1067
|
-
unsubscribe();
|
|
1068
|
-
unsubscribe = null;
|
|
1069
|
-
}
|
|
1070
|
-
});
|
|
1071
|
-
}
|
|
1072
|
-
return new Response(stream, {
|
|
1092
|
+
request.signal?.addEventListener("abort", cleanup);
|
|
1093
|
+
const webStream = Readable.toWeb(pass);
|
|
1094
|
+
return new Response(webStream, {
|
|
1073
1095
|
headers: {
|
|
1074
1096
|
"content-type": "text/event-stream",
|
|
1075
1097
|
"cache-control": "no-cache, no-transform",
|
|
@@ -1135,7 +1157,7 @@ function parseSearchResults(output) {
|
|
|
1135
1157
|
return { slug: line.trim(), displayName: line.trim(), version: "", summary: "" };
|
|
1136
1158
|
});
|
|
1137
1159
|
}
|
|
1138
|
-
const Route$
|
|
1160
|
+
const Route$n = createFileRoute("/api/skills")({
|
|
1139
1161
|
server: {
|
|
1140
1162
|
handlers: {
|
|
1141
1163
|
GET: async ({ request }) => {
|
|
@@ -1254,7 +1276,7 @@ function normalizeSessions(payload) {
|
|
|
1254
1276
|
});
|
|
1255
1277
|
return { sessions: normalized };
|
|
1256
1278
|
}
|
|
1257
|
-
const Route$
|
|
1279
|
+
const Route$m = createFileRoute("/api/sessions")({
|
|
1258
1280
|
server: {
|
|
1259
1281
|
handlers: {
|
|
1260
1282
|
GET: async () => {
|
|
@@ -1407,7 +1429,7 @@ const Route$j = createFileRoute("/api/sessions")({
|
|
|
1407
1429
|
}
|
|
1408
1430
|
}
|
|
1409
1431
|
});
|
|
1410
|
-
const Route$
|
|
1432
|
+
const Route$l = createFileRoute("/api/send")({
|
|
1411
1433
|
server: {
|
|
1412
1434
|
handlers: {
|
|
1413
1435
|
POST: async ({ request }) => {
|
|
@@ -1473,7 +1495,7 @@ const Route$i = createFileRoute("/api/send")({
|
|
|
1473
1495
|
}
|
|
1474
1496
|
}
|
|
1475
1497
|
});
|
|
1476
|
-
const Route$
|
|
1498
|
+
const Route$k = createFileRoute("/api/ping")({
|
|
1477
1499
|
server: {
|
|
1478
1500
|
handlers: {
|
|
1479
1501
|
GET: async () => {
|
|
@@ -1497,7 +1519,7 @@ const categories = { "core": [{ "id": "cami", "name": "Cami", "emoji": "🦎", "
|
|
|
1497
1519
|
const personasData = {
|
|
1498
1520
|
categories
|
|
1499
1521
|
};
|
|
1500
|
-
const Route$
|
|
1522
|
+
const Route$j = createFileRoute("/api/personas")({
|
|
1501
1523
|
server: {
|
|
1502
1524
|
handlers: {
|
|
1503
1525
|
GET: async () => {
|
|
@@ -1542,7 +1564,7 @@ function resolveSessionsDir() {
|
|
|
1542
1564
|
)
|
|
1543
1565
|
};
|
|
1544
1566
|
}
|
|
1545
|
-
const Route$
|
|
1567
|
+
const Route$i = createFileRoute("/api/paths")({
|
|
1546
1568
|
server: {
|
|
1547
1569
|
handlers: {
|
|
1548
1570
|
GET: () => {
|
|
@@ -1567,7 +1589,7 @@ function parseModelName(modelId) {
|
|
|
1567
1589
|
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
1568
1590
|
}).join(" ");
|
|
1569
1591
|
}
|
|
1570
|
-
const Route$
|
|
1592
|
+
const Route$h = createFileRoute("/api/models")({
|
|
1571
1593
|
server: {
|
|
1572
1594
|
handlers: {
|
|
1573
1595
|
GET: async () => {
|
|
@@ -1746,11 +1768,13 @@ async function testApiKey(apiKey) {
|
|
|
1746
1768
|
}
|
|
1747
1769
|
function getLlmConfig(request) {
|
|
1748
1770
|
const headerKey = request.headers.get("X-OpenAI-API-Key");
|
|
1749
|
-
const
|
|
1771
|
+
const headerBaseUrl = request.headers.get("X-LLM-Base-URL")?.trim() || null;
|
|
1772
|
+
const baseUrl = headerBaseUrl || process.env.LLM_BASE_URL?.trim() || null;
|
|
1750
1773
|
const isOpenRouter = baseUrl?.includes("openrouter.ai");
|
|
1751
|
-
const
|
|
1774
|
+
const isKilocode = baseUrl?.includes("kilo.ai");
|
|
1775
|
+
const envKey = isOpenRouter ? process.env.OPENROUTER_API_KEY?.trim() || process.env.OPENAI_API_KEY?.trim() : isKilocode ? process.env.KILOCODE_API_KEY?.trim() || process.env.OPENAI_API_KEY?.trim() : process.env.OPENAI_API_KEY?.trim();
|
|
1752
1776
|
const apiKey = headerKey?.trim() || envKey || null;
|
|
1753
|
-
const model = request.headers.get("X-LLM-Model")?.trim() || null;
|
|
1777
|
+
const model = request.headers.get("X-LLM-Model")?.trim() || process.env.LLM_MODEL?.trim() || null;
|
|
1754
1778
|
return { apiKey, baseUrl, model };
|
|
1755
1779
|
}
|
|
1756
1780
|
function generateHeuristicTitle(message) {
|
|
@@ -1773,7 +1797,7 @@ function generateHeuristicTitle(message) {
|
|
|
1773
1797
|
}
|
|
1774
1798
|
return title || message.slice(0, 50);
|
|
1775
1799
|
}
|
|
1776
|
-
const Route$
|
|
1800
|
+
const Route$g = createFileRoute("/api/llm-features")({
|
|
1777
1801
|
server: {
|
|
1778
1802
|
handlers: {
|
|
1779
1803
|
/**
|
|
@@ -1783,10 +1807,12 @@ const Route$d = createFileRoute("/api/llm-features")({
|
|
|
1783
1807
|
try {
|
|
1784
1808
|
const hasEnvKey = Boolean(process.env.OPENAI_API_KEY?.trim());
|
|
1785
1809
|
const hasOpenRouterKey = Boolean(process.env.OPENROUTER_API_KEY?.trim());
|
|
1810
|
+
const hasKilocodeKey = Boolean(process.env.KILOCODE_API_KEY?.trim());
|
|
1786
1811
|
return json({
|
|
1787
1812
|
ok: true,
|
|
1788
1813
|
hasEnvKey,
|
|
1789
|
-
hasOpenRouterKey
|
|
1814
|
+
hasOpenRouterKey,
|
|
1815
|
+
hasKilocodeKey
|
|
1790
1816
|
});
|
|
1791
1817
|
} catch (err) {
|
|
1792
1818
|
return json({
|
|
@@ -1925,7 +1951,7 @@ const Route$d = createFileRoute("/api/llm-features")({
|
|
|
1925
1951
|
}
|
|
1926
1952
|
}
|
|
1927
1953
|
});
|
|
1928
|
-
const Route$
|
|
1954
|
+
const Route$f = createFileRoute("/api/history")({
|
|
1929
1955
|
server: {
|
|
1930
1956
|
handlers: {
|
|
1931
1957
|
GET: async ({ request }) => {
|
|
@@ -1988,7 +2014,7 @@ function parseFollowUps(text) {
|
|
|
1988
2014
|
const lines = text.split("\n").map((line) => line.trim()).filter((line) => line.length > 0).map((line) => line.replace(/^\d+[.)\s]+/, "").trim()).map((line) => line.replace(/^[-•*]\s*/, "").trim()).map((line) => line.replace(/^["']|["']$/g, "").trim()).filter((line) => line.length > 0 && line.length < 150);
|
|
1989
2015
|
return lines.slice(0, 3);
|
|
1990
2016
|
}
|
|
1991
|
-
const Route$
|
|
2017
|
+
const Route$e = createFileRoute("/api/follow-ups")({
|
|
1992
2018
|
server: {
|
|
1993
2019
|
handlers: {
|
|
1994
2020
|
POST: async ({ request }) => {
|
|
@@ -2099,7 +2125,7 @@ function parsePatch(value) {
|
|
|
2099
2125
|
if (Object.keys(patch).length === 0) return null;
|
|
2100
2126
|
return patch;
|
|
2101
2127
|
}
|
|
2102
|
-
const Route$
|
|
2128
|
+
const Route$d = createFileRoute("/api/cron")({
|
|
2103
2129
|
server: {
|
|
2104
2130
|
handlers: {
|
|
2105
2131
|
GET: async ({ request }) => {
|
|
@@ -2176,7 +2202,7 @@ function resolveModel(m) {
|
|
|
2176
2202
|
if (typeof m === "object" && "primary" in m) return m.primary;
|
|
2177
2203
|
return void 0;
|
|
2178
2204
|
}
|
|
2179
|
-
const Route$
|
|
2205
|
+
const Route$c = createFileRoute("/api/agents")({
|
|
2180
2206
|
server: {
|
|
2181
2207
|
handlers: {
|
|
2182
2208
|
GET: async () => {
|
|
@@ -2596,7 +2622,7 @@ function validateFilename(filename) {
|
|
|
2596
2622
|
return true;
|
|
2597
2623
|
}
|
|
2598
2624
|
const MAX_FILE_SIZE = 100 * 1024 * 1024;
|
|
2599
|
-
const Route$
|
|
2625
|
+
const Route$b = createFileRoute("/api/files/upload")({
|
|
2600
2626
|
server: {
|
|
2601
2627
|
handlers: {
|
|
2602
2628
|
POST: async ({ request }) => {
|
|
@@ -2691,7 +2717,7 @@ const Route$8 = createFileRoute("/api/files/upload")({
|
|
|
2691
2717
|
}
|
|
2692
2718
|
});
|
|
2693
2719
|
const MAX_TEXT_SIZE$1 = 5 * 1024 * 1024;
|
|
2694
|
-
const Route$
|
|
2720
|
+
const Route$a = createFileRoute("/api/files/save")({
|
|
2695
2721
|
server: {
|
|
2696
2722
|
handlers: {
|
|
2697
2723
|
POST: async ({ request }) => {
|
|
@@ -2733,7 +2759,7 @@ const Route$7 = createFileRoute("/api/files/save")({
|
|
|
2733
2759
|
}
|
|
2734
2760
|
}
|
|
2735
2761
|
});
|
|
2736
|
-
const Route$
|
|
2762
|
+
const Route$9 = createFileRoute("/api/files/rename")({
|
|
2737
2763
|
server: {
|
|
2738
2764
|
handlers: {
|
|
2739
2765
|
POST: async ({ request }) => {
|
|
@@ -2876,7 +2902,7 @@ const TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
2876
2902
|
"diff",
|
|
2877
2903
|
"patch"
|
|
2878
2904
|
]);
|
|
2879
|
-
const Route$
|
|
2905
|
+
const Route$8 = createFileRoute("/api/files/read")({
|
|
2880
2906
|
server: {
|
|
2881
2907
|
handlers: {
|
|
2882
2908
|
GET: async ({ request }) => {
|
|
@@ -2968,7 +2994,7 @@ function validateFolderName(path2) {
|
|
|
2968
2994
|
throw new Error("Invalid folder name");
|
|
2969
2995
|
}
|
|
2970
2996
|
}
|
|
2971
|
-
const Route$
|
|
2997
|
+
const Route$7 = createFileRoute("/api/files/mkdir")({
|
|
2972
2998
|
server: {
|
|
2973
2999
|
handlers: {
|
|
2974
3000
|
POST: async ({ request }) => {
|
|
@@ -3017,7 +3043,7 @@ const Route$4 = createFileRoute("/api/files/mkdir")({
|
|
|
3017
3043
|
}
|
|
3018
3044
|
}
|
|
3019
3045
|
});
|
|
3020
|
-
const Route$
|
|
3046
|
+
const Route$6 = createFileRoute("/api/files/list")({
|
|
3021
3047
|
server: {
|
|
3022
3048
|
handlers: {
|
|
3023
3049
|
GET: async ({ request }) => {
|
|
@@ -3052,7 +3078,7 @@ const Route$3 = createFileRoute("/api/files/list")({
|
|
|
3052
3078
|
}
|
|
3053
3079
|
}
|
|
3054
3080
|
});
|
|
3055
|
-
const Route$
|
|
3081
|
+
const Route$5 = createFileRoute("/api/files/info")({
|
|
3056
3082
|
server: {
|
|
3057
3083
|
handlers: {
|
|
3058
3084
|
GET: async ({ request }) => {
|
|
@@ -3069,8 +3095,10 @@ const Route$2 = createFileRoute("/api/files/info")({
|
|
|
3069
3095
|
);
|
|
3070
3096
|
}
|
|
3071
3097
|
const path2 = validatePath(rawPath, "Path parameter");
|
|
3072
|
-
const
|
|
3073
|
-
|
|
3098
|
+
const root = process.env.FILES_ROOT?.trim() ? resolve(process.env.FILES_ROOT) : process.env.HOME || "/home";
|
|
3099
|
+
const absolutePath = resolve(root, path2.replace(/^\/+/, ""));
|
|
3100
|
+
const stats = await stat(absolutePath);
|
|
3101
|
+
return json({ size: stats.size });
|
|
3074
3102
|
} catch (err) {
|
|
3075
3103
|
const error = err;
|
|
3076
3104
|
if (error.message.includes("invalid characters") || error.message.includes("traversal attempts")) {
|
|
@@ -3082,6 +3110,24 @@ const Route$2 = createFileRoute("/api/files/info")({
|
|
|
3082
3110
|
{ status: 400 }
|
|
3083
3111
|
);
|
|
3084
3112
|
}
|
|
3113
|
+
if (error.code === "ENOENT") {
|
|
3114
|
+
return json(
|
|
3115
|
+
{
|
|
3116
|
+
error: "File not found",
|
|
3117
|
+
code: "NOT_FOUND"
|
|
3118
|
+
},
|
|
3119
|
+
{ status: 404 }
|
|
3120
|
+
);
|
|
3121
|
+
}
|
|
3122
|
+
if (error.code === "EACCES") {
|
|
3123
|
+
return json(
|
|
3124
|
+
{
|
|
3125
|
+
error: "Permission denied",
|
|
3126
|
+
code: "PERMISSION_DENIED"
|
|
3127
|
+
},
|
|
3128
|
+
{ status: 403 }
|
|
3129
|
+
);
|
|
3130
|
+
}
|
|
3085
3131
|
const status = error.status || 500;
|
|
3086
3132
|
const code = error.code || "INTERNAL_ERROR";
|
|
3087
3133
|
return json(
|
|
@@ -3153,7 +3199,7 @@ function isStaticAsset(filename) {
|
|
|
3153
3199
|
const staticExts = ["png", "jpg", "jpeg", "gif", "webp", "svg", "css", "js", "woff", "woff2", "ttf", "otf"];
|
|
3154
3200
|
return staticExts.includes(ext);
|
|
3155
3201
|
}
|
|
3156
|
-
const Route$
|
|
3202
|
+
const Route$4 = createFileRoute("/api/files/download")({
|
|
3157
3203
|
server: {
|
|
3158
3204
|
handlers: {
|
|
3159
3205
|
GET: async ({ request }) => {
|
|
@@ -3219,7 +3265,7 @@ const Route$1 = createFileRoute("/api/files/download")({
|
|
|
3219
3265
|
}
|
|
3220
3266
|
}
|
|
3221
3267
|
});
|
|
3222
|
-
const Route = createFileRoute("/api/files/delete")({
|
|
3268
|
+
const Route$3 = createFileRoute("/api/files/delete")({
|
|
3223
3269
|
server: {
|
|
3224
3270
|
handlers: {
|
|
3225
3271
|
DELETE: async ({ request }) => {
|
|
@@ -3277,176 +3323,452 @@ const Route = createFileRoute("/api/files/delete")({
|
|
|
3277
3323
|
}
|
|
3278
3324
|
}
|
|
3279
3325
|
});
|
|
3280
|
-
|
|
3326
|
+
function clampPercent(value) {
|
|
3327
|
+
if (!Number.isFinite(value)) return 0;
|
|
3328
|
+
return Math.max(0, Math.min(100, value));
|
|
3329
|
+
}
|
|
3330
|
+
function sampleCpuTimes() {
|
|
3331
|
+
const cpus = os.cpus();
|
|
3332
|
+
let idle = 0;
|
|
3333
|
+
let total = 0;
|
|
3334
|
+
for (const cpu of cpus) {
|
|
3335
|
+
idle += cpu.times.idle;
|
|
3336
|
+
total += cpu.times.user + cpu.times.nice + cpu.times.sys + cpu.times.idle + cpu.times.irq;
|
|
3337
|
+
}
|
|
3338
|
+
return { idle, total };
|
|
3339
|
+
}
|
|
3340
|
+
async function getCpuUsagePercent(sampleMs = 500) {
|
|
3341
|
+
const start = sampleCpuTimes();
|
|
3342
|
+
await new Promise((resolve2) => setTimeout(resolve2, sampleMs));
|
|
3343
|
+
const end = sampleCpuTimes();
|
|
3344
|
+
const idleDelta = end.idle - start.idle;
|
|
3345
|
+
const totalDelta = end.total - start.total;
|
|
3346
|
+
if (totalDelta <= 0) return 0;
|
|
3347
|
+
return clampPercent((totalDelta - idleDelta) / totalDelta * 100);
|
|
3348
|
+
}
|
|
3349
|
+
function getDiskStats() {
|
|
3350
|
+
try {
|
|
3351
|
+
const raw = execSync("df -k / | tail -1", {
|
|
3352
|
+
encoding: "utf8",
|
|
3353
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
3354
|
+
}).trim();
|
|
3355
|
+
const parts = raw.split(/\s+/);
|
|
3356
|
+
if (parts.length < 5) return { used: 0, total: 0 };
|
|
3357
|
+
const totalKb = Number(parts[1]);
|
|
3358
|
+
const usedKb = Number(parts[2]);
|
|
3359
|
+
if (!Number.isFinite(totalKb) || totalKb <= 0) return { used: 0, total: 0 };
|
|
3360
|
+
const total = totalKb * 1024;
|
|
3361
|
+
const used = usedKb * 1024;
|
|
3362
|
+
return { used, total };
|
|
3363
|
+
} catch {
|
|
3364
|
+
return { used: 0, total: 0 };
|
|
3365
|
+
}
|
|
3366
|
+
}
|
|
3367
|
+
function formatUptime(seconds) {
|
|
3368
|
+
const d = Math.floor(seconds / 86400);
|
|
3369
|
+
const h = Math.floor(seconds % 86400 / 3600);
|
|
3370
|
+
const m = Math.floor(seconds % 3600 / 60);
|
|
3371
|
+
const parts = [];
|
|
3372
|
+
if (d > 0) parts.push(`${d}d`);
|
|
3373
|
+
if (h > 0) parts.push(`${h}h`);
|
|
3374
|
+
parts.push(`${m}m`);
|
|
3375
|
+
return parts.join(" ");
|
|
3376
|
+
}
|
|
3377
|
+
function formatBytesCompact(bytes) {
|
|
3378
|
+
const units = ["B", "KB", "MB", "GB", "TB"];
|
|
3379
|
+
let value = Math.max(0, bytes);
|
|
3380
|
+
let unitIndex = 0;
|
|
3381
|
+
while (value >= 1024 && unitIndex < units.length - 1) {
|
|
3382
|
+
value /= 1024;
|
|
3383
|
+
unitIndex += 1;
|
|
3384
|
+
}
|
|
3385
|
+
const digits = value >= 100 ? 0 : value >= 10 ? 1 : 2;
|
|
3386
|
+
return `${value.toFixed(digits)} ${units[unitIndex]}`;
|
|
3387
|
+
}
|
|
3388
|
+
function getNetworkIo() {
|
|
3389
|
+
try {
|
|
3390
|
+
const netRaw = execSync("cat /proc/net/dev", {
|
|
3391
|
+
encoding: "utf8",
|
|
3392
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
3393
|
+
timeout: 3e3
|
|
3394
|
+
});
|
|
3395
|
+
const lines = netRaw.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
3396
|
+
let selected = null;
|
|
3397
|
+
for (const line of lines.slice(2)) {
|
|
3398
|
+
const [ifaceRaw, dataRaw] = line.split(":");
|
|
3399
|
+
if (!ifaceRaw || !dataRaw) continue;
|
|
3400
|
+
const iface = ifaceRaw.trim();
|
|
3401
|
+
const fields = dataRaw.trim().split(/\s+/);
|
|
3402
|
+
if (fields.length < 16) continue;
|
|
3403
|
+
const rx = Number(fields[0]);
|
|
3404
|
+
const tx = Number(fields[8]);
|
|
3405
|
+
if (!Number.isFinite(rx) || !Number.isFinite(tx)) continue;
|
|
3406
|
+
const entry = { iface, rx, tx };
|
|
3407
|
+
if (iface !== "lo") {
|
|
3408
|
+
selected = entry;
|
|
3409
|
+
break;
|
|
3410
|
+
}
|
|
3411
|
+
if (!selected) selected = entry;
|
|
3412
|
+
}
|
|
3413
|
+
if (!selected) return { rx: "0 MB", tx: "0 MB" };
|
|
3414
|
+
return {
|
|
3415
|
+
rx: formatBytesCompact(selected.rx),
|
|
3416
|
+
tx: formatBytesCompact(selected.tx)
|
|
3417
|
+
};
|
|
3418
|
+
} catch {
|
|
3419
|
+
return { rx: "0 MB", tx: "0 MB" };
|
|
3420
|
+
}
|
|
3421
|
+
}
|
|
3422
|
+
function getTopProcesses() {
|
|
3423
|
+
try {
|
|
3424
|
+
const procs = execSync("ps aux --sort=-%cpu | head -6 | tail -5", {
|
|
3425
|
+
encoding: "utf8",
|
|
3426
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
3427
|
+
timeout: 3e3
|
|
3428
|
+
});
|
|
3429
|
+
return procs.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => {
|
|
3430
|
+
const parts = line.split(/\s+/);
|
|
3431
|
+
if (parts.length < 11) return null;
|
|
3432
|
+
const cpu = Number(parts[2]);
|
|
3433
|
+
const mem = Number(parts[3]);
|
|
3434
|
+
const command = parts.slice(10).join(" ");
|
|
3435
|
+
const name = command.split("/").pop()?.split(" ")[0] || command;
|
|
3436
|
+
if (!Number.isFinite(cpu) || !Number.isFinite(mem)) return null;
|
|
3437
|
+
return {
|
|
3438
|
+
name: name.slice(0, 30),
|
|
3439
|
+
cpu,
|
|
3440
|
+
mem
|
|
3441
|
+
};
|
|
3442
|
+
}).filter(
|
|
3443
|
+
(p) => p !== null
|
|
3444
|
+
);
|
|
3445
|
+
} catch {
|
|
3446
|
+
return [];
|
|
3447
|
+
}
|
|
3448
|
+
}
|
|
3449
|
+
async function getSystemStats() {
|
|
3450
|
+
const totalRam = os.totalmem();
|
|
3451
|
+
const freeRam = os.freemem();
|
|
3452
|
+
const usedRam = Math.max(0, totalRam - freeRam);
|
|
3453
|
+
const [cpuUsage, disk] = await Promise.all([
|
|
3454
|
+
getCpuUsagePercent(500),
|
|
3455
|
+
Promise.resolve(getDiskStats())
|
|
3456
|
+
]);
|
|
3457
|
+
const cpus = os.cpus();
|
|
3458
|
+
const cpuModel = cpus[0]?.model ?? "Unknown CPU";
|
|
3459
|
+
const cores = cpus.length;
|
|
3460
|
+
return {
|
|
3461
|
+
cpu: cpuUsage,
|
|
3462
|
+
ram: { used: usedRam, total: totalRam },
|
|
3463
|
+
disk,
|
|
3464
|
+
load: os.loadavg().map((v) => Number(v.toFixed(2))),
|
|
3465
|
+
uptime: formatUptime(os.uptime()),
|
|
3466
|
+
network: getNetworkIo(),
|
|
3467
|
+
topProcesses: getTopProcesses(),
|
|
3468
|
+
cpuModel,
|
|
3469
|
+
cores
|
|
3470
|
+
};
|
|
3471
|
+
}
|
|
3472
|
+
async function getGatewayStats() {
|
|
3473
|
+
try {
|
|
3474
|
+
const sessionsJson = execSync("openclaw sessions list --json 2>/dev/null", {
|
|
3475
|
+
encoding: "utf8",
|
|
3476
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
3477
|
+
timeout: 5e3
|
|
3478
|
+
});
|
|
3479
|
+
const sessionsData = JSON.parse(sessionsJson);
|
|
3480
|
+
const activeSessions = sessionsData.count ?? sessionsData.sessions?.length ?? 0;
|
|
3481
|
+
return { activeSessions, tokensToday: 0, costToday: 0 };
|
|
3482
|
+
} catch {
|
|
3483
|
+
return { activeSessions: 0, tokensToday: 0, costToday: 0 };
|
|
3484
|
+
}
|
|
3485
|
+
}
|
|
3486
|
+
async function getCronOverview() {
|
|
3487
|
+
try {
|
|
3488
|
+
const cronJson = execSync("openclaw cron list --json 2>/dev/null", {
|
|
3489
|
+
encoding: "utf8",
|
|
3490
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
3491
|
+
timeout: 5e3
|
|
3492
|
+
});
|
|
3493
|
+
const data = JSON.parse(cronJson);
|
|
3494
|
+
const jobs = data.jobs ?? [];
|
|
3495
|
+
return jobs.map((job) => {
|
|
3496
|
+
const schedule = job.schedule;
|
|
3497
|
+
const state = job.state;
|
|
3498
|
+
let scheduleStr = "—";
|
|
3499
|
+
if (schedule) {
|
|
3500
|
+
if (schedule.expr) scheduleStr = String(schedule.expr);
|
|
3501
|
+
else if (schedule.kind === "every" && schedule.everyMs)
|
|
3502
|
+
scheduleStr = `every ${Number(schedule.everyMs) / 1e3 / 60}m`;
|
|
3503
|
+
else if (schedule.kind === "at") scheduleStr = `at ${schedule.at}`;
|
|
3504
|
+
else if (schedule.kind) scheduleStr = String(schedule.kind);
|
|
3505
|
+
}
|
|
3506
|
+
let nextRun = null;
|
|
3507
|
+
if (state?.nextRunAtMs && Number(state.nextRunAtMs) > 0) {
|
|
3508
|
+
nextRun = new Date(Number(state.nextRunAtMs)).toISOString();
|
|
3509
|
+
}
|
|
3510
|
+
let lastRun = null;
|
|
3511
|
+
if (state?.lastRunAtMs && Number(state.lastRunAtMs) > 0) {
|
|
3512
|
+
lastRun = new Date(Number(state.lastRunAtMs)).toISOString();
|
|
3513
|
+
}
|
|
3514
|
+
const rawStatus = state?.lastStatus;
|
|
3515
|
+
const lastStatus = rawStatus === "ok" ? "ok" : rawStatus === "error" ? "error" : rawStatus === "idle" ? "idle" : "unknown";
|
|
3516
|
+
return {
|
|
3517
|
+
id: String(job.id ?? ""),
|
|
3518
|
+
name: String(job.name ?? job.id ?? "Unnamed"),
|
|
3519
|
+
schedule: scheduleStr,
|
|
3520
|
+
enabled: Boolean(job.enabled ?? true),
|
|
3521
|
+
nextRun,
|
|
3522
|
+
lastRun,
|
|
3523
|
+
lastStatus
|
|
3524
|
+
};
|
|
3525
|
+
});
|
|
3526
|
+
} catch {
|
|
3527
|
+
return [];
|
|
3528
|
+
}
|
|
3529
|
+
}
|
|
3530
|
+
const Route$2 = createFileRoute("/api/dashboard/system")({
|
|
3531
|
+
server: {
|
|
3532
|
+
handlers: {
|
|
3533
|
+
GET: async () => {
|
|
3534
|
+
try {
|
|
3535
|
+
const data = await getSystemStats();
|
|
3536
|
+
return json(data);
|
|
3537
|
+
} catch (err) {
|
|
3538
|
+
return json(
|
|
3539
|
+
{ error: err instanceof Error ? err.message : String(err) },
|
|
3540
|
+
{ status: 500 }
|
|
3541
|
+
);
|
|
3542
|
+
}
|
|
3543
|
+
}
|
|
3544
|
+
}
|
|
3545
|
+
}
|
|
3546
|
+
});
|
|
3547
|
+
const Route$1 = createFileRoute("/api/dashboard/gateway")({
|
|
3548
|
+
server: {
|
|
3549
|
+
handlers: {
|
|
3550
|
+
GET: async () => {
|
|
3551
|
+
try {
|
|
3552
|
+
const data = await getGatewayStats();
|
|
3553
|
+
return json(data);
|
|
3554
|
+
} catch (err) {
|
|
3555
|
+
return json(
|
|
3556
|
+
{ error: err instanceof Error ? err.message : String(err) },
|
|
3557
|
+
{ status: 500 }
|
|
3558
|
+
);
|
|
3559
|
+
}
|
|
3560
|
+
}
|
|
3561
|
+
}
|
|
3562
|
+
}
|
|
3563
|
+
});
|
|
3564
|
+
const Route = createFileRoute("/api/dashboard/crons")({
|
|
3565
|
+
server: {
|
|
3566
|
+
handlers: {
|
|
3567
|
+
GET: async () => {
|
|
3568
|
+
try {
|
|
3569
|
+
const data = await getCronOverview();
|
|
3570
|
+
return json({ jobs: data });
|
|
3571
|
+
} catch (err) {
|
|
3572
|
+
return json(
|
|
3573
|
+
{ error: err instanceof Error ? err.message : String(err) },
|
|
3574
|
+
{ status: 500 }
|
|
3575
|
+
);
|
|
3576
|
+
}
|
|
3577
|
+
}
|
|
3578
|
+
}
|
|
3579
|
+
}
|
|
3580
|
+
});
|
|
3581
|
+
const SkillsRoute = Route$A.update({
|
|
3281
3582
|
id: "/skills",
|
|
3282
3583
|
path: "/skills",
|
|
3283
|
-
getParentRoute: () => Route$
|
|
3584
|
+
getParentRoute: () => Route$B
|
|
3284
3585
|
});
|
|
3285
|
-
const NewRoute = Route$
|
|
3586
|
+
const NewRoute = Route$z.update({
|
|
3286
3587
|
id: "/new",
|
|
3287
3588
|
path: "/new",
|
|
3288
|
-
getParentRoute: () => Route$
|
|
3589
|
+
getParentRoute: () => Route$B
|
|
3289
3590
|
});
|
|
3290
|
-
const MemoryRoute = Route$
|
|
3591
|
+
const MemoryRoute = Route$y.update({
|
|
3291
3592
|
id: "/memory",
|
|
3292
3593
|
path: "/memory",
|
|
3293
|
-
getParentRoute: () => Route$
|
|
3594
|
+
getParentRoute: () => Route$B
|
|
3294
3595
|
});
|
|
3295
|
-
const FilesRoute = Route$
|
|
3596
|
+
const FilesRoute = Route$x.update({
|
|
3296
3597
|
id: "/files",
|
|
3297
3598
|
path: "/files",
|
|
3298
|
-
getParentRoute: () => Route$
|
|
3599
|
+
getParentRoute: () => Route$B
|
|
3299
3600
|
});
|
|
3300
|
-
const
|
|
3601
|
+
const DashboardRoute = Route$w.update({
|
|
3602
|
+
id: "/dashboard",
|
|
3603
|
+
path: "/dashboard",
|
|
3604
|
+
getParentRoute: () => Route$B
|
|
3605
|
+
});
|
|
3606
|
+
const ConnectRoute = Route$v.update({
|
|
3301
3607
|
id: "/connect",
|
|
3302
3608
|
path: "/connect",
|
|
3303
|
-
getParentRoute: () => Route$
|
|
3609
|
+
getParentRoute: () => Route$B
|
|
3304
3610
|
});
|
|
3305
|
-
const BotsRoute = Route$
|
|
3611
|
+
const BotsRoute = Route$u.update({
|
|
3306
3612
|
id: "/bots",
|
|
3307
3613
|
path: "/bots",
|
|
3308
|
-
getParentRoute: () => Route$
|
|
3614
|
+
getParentRoute: () => Route$B
|
|
3309
3615
|
});
|
|
3310
|
-
const AgentsRoute = Route$
|
|
3616
|
+
const AgentsRoute = Route$t.update({
|
|
3311
3617
|
id: "/agents",
|
|
3312
3618
|
path: "/agents",
|
|
3313
|
-
getParentRoute: () => Route$
|
|
3619
|
+
getParentRoute: () => Route$B
|
|
3314
3620
|
});
|
|
3315
|
-
const IndexRoute = Route$
|
|
3621
|
+
const IndexRoute = Route$s.update({
|
|
3316
3622
|
id: "/",
|
|
3317
3623
|
path: "/",
|
|
3318
|
-
getParentRoute: () => Route$
|
|
3624
|
+
getParentRoute: () => Route$B
|
|
3319
3625
|
});
|
|
3320
|
-
const ChatSessionKeyRoute = Route$
|
|
3626
|
+
const ChatSessionKeyRoute = Route$r.update({
|
|
3321
3627
|
id: "/chat/$sessionKey",
|
|
3322
3628
|
path: "/chat/$sessionKey",
|
|
3323
|
-
getParentRoute: () => Route$
|
|
3629
|
+
getParentRoute: () => Route$B
|
|
3324
3630
|
});
|
|
3325
|
-
const ApiTtsRoute = Route$
|
|
3631
|
+
const ApiTtsRoute = Route$q.update({
|
|
3326
3632
|
id: "/api/tts",
|
|
3327
3633
|
path: "/api/tts",
|
|
3328
|
-
getParentRoute: () => Route$
|
|
3634
|
+
getParentRoute: () => Route$B
|
|
3329
3635
|
});
|
|
3330
|
-
const ApiSttRoute = Route$
|
|
3636
|
+
const ApiSttRoute = Route$p.update({
|
|
3331
3637
|
id: "/api/stt",
|
|
3332
3638
|
path: "/api/stt",
|
|
3333
|
-
getParentRoute: () => Route$
|
|
3639
|
+
getParentRoute: () => Route$B
|
|
3334
3640
|
});
|
|
3335
|
-
const ApiStreamRoute = Route$
|
|
3641
|
+
const ApiStreamRoute = Route$o.update({
|
|
3336
3642
|
id: "/api/stream",
|
|
3337
3643
|
path: "/api/stream",
|
|
3338
|
-
getParentRoute: () => Route$
|
|
3644
|
+
getParentRoute: () => Route$B
|
|
3339
3645
|
});
|
|
3340
|
-
const ApiSkillsRoute = Route$
|
|
3646
|
+
const ApiSkillsRoute = Route$n.update({
|
|
3341
3647
|
id: "/api/skills",
|
|
3342
3648
|
path: "/api/skills",
|
|
3343
|
-
getParentRoute: () => Route$
|
|
3649
|
+
getParentRoute: () => Route$B
|
|
3344
3650
|
});
|
|
3345
|
-
const ApiSessionsRoute = Route$
|
|
3651
|
+
const ApiSessionsRoute = Route$m.update({
|
|
3346
3652
|
id: "/api/sessions",
|
|
3347
3653
|
path: "/api/sessions",
|
|
3348
|
-
getParentRoute: () => Route$
|
|
3654
|
+
getParentRoute: () => Route$B
|
|
3349
3655
|
});
|
|
3350
|
-
const ApiSendRoute = Route$
|
|
3656
|
+
const ApiSendRoute = Route$l.update({
|
|
3351
3657
|
id: "/api/send",
|
|
3352
3658
|
path: "/api/send",
|
|
3353
|
-
getParentRoute: () => Route$
|
|
3659
|
+
getParentRoute: () => Route$B
|
|
3354
3660
|
});
|
|
3355
|
-
const ApiPingRoute = Route$
|
|
3661
|
+
const ApiPingRoute = Route$k.update({
|
|
3356
3662
|
id: "/api/ping",
|
|
3357
3663
|
path: "/api/ping",
|
|
3358
|
-
getParentRoute: () => Route$
|
|
3664
|
+
getParentRoute: () => Route$B
|
|
3359
3665
|
});
|
|
3360
|
-
const ApiPersonasRoute = Route$
|
|
3666
|
+
const ApiPersonasRoute = Route$j.update({
|
|
3361
3667
|
id: "/api/personas",
|
|
3362
3668
|
path: "/api/personas",
|
|
3363
|
-
getParentRoute: () => Route$
|
|
3669
|
+
getParentRoute: () => Route$B
|
|
3364
3670
|
});
|
|
3365
|
-
const ApiPathsRoute = Route$
|
|
3671
|
+
const ApiPathsRoute = Route$i.update({
|
|
3366
3672
|
id: "/api/paths",
|
|
3367
3673
|
path: "/api/paths",
|
|
3368
|
-
getParentRoute: () => Route$
|
|
3674
|
+
getParentRoute: () => Route$B
|
|
3369
3675
|
});
|
|
3370
|
-
const ApiModelsRoute = Route$
|
|
3676
|
+
const ApiModelsRoute = Route$h.update({
|
|
3371
3677
|
id: "/api/models",
|
|
3372
3678
|
path: "/api/models",
|
|
3373
|
-
getParentRoute: () => Route$
|
|
3679
|
+
getParentRoute: () => Route$B
|
|
3374
3680
|
});
|
|
3375
|
-
const ApiLlmFeaturesRoute = Route$
|
|
3681
|
+
const ApiLlmFeaturesRoute = Route$g.update({
|
|
3376
3682
|
id: "/api/llm-features",
|
|
3377
3683
|
path: "/api/llm-features",
|
|
3378
|
-
getParentRoute: () => Route$
|
|
3684
|
+
getParentRoute: () => Route$B
|
|
3379
3685
|
});
|
|
3380
|
-
const ApiHistoryRoute = Route$
|
|
3686
|
+
const ApiHistoryRoute = Route$f.update({
|
|
3381
3687
|
id: "/api/history",
|
|
3382
3688
|
path: "/api/history",
|
|
3383
|
-
getParentRoute: () => Route$
|
|
3689
|
+
getParentRoute: () => Route$B
|
|
3384
3690
|
});
|
|
3385
|
-
const ApiFollowUpsRoute = Route$
|
|
3691
|
+
const ApiFollowUpsRoute = Route$e.update({
|
|
3386
3692
|
id: "/api/follow-ups",
|
|
3387
3693
|
path: "/api/follow-ups",
|
|
3388
|
-
getParentRoute: () => Route$
|
|
3694
|
+
getParentRoute: () => Route$B
|
|
3389
3695
|
});
|
|
3390
|
-
const ApiCronRoute = Route$
|
|
3696
|
+
const ApiCronRoute = Route$d.update({
|
|
3391
3697
|
id: "/api/cron",
|
|
3392
3698
|
path: "/api/cron",
|
|
3393
|
-
getParentRoute: () => Route$
|
|
3699
|
+
getParentRoute: () => Route$B
|
|
3394
3700
|
});
|
|
3395
|
-
const ApiAgentsRoute = Route$
|
|
3701
|
+
const ApiAgentsRoute = Route$c.update({
|
|
3396
3702
|
id: "/api/agents",
|
|
3397
3703
|
path: "/api/agents",
|
|
3398
|
-
getParentRoute: () => Route$
|
|
3704
|
+
getParentRoute: () => Route$B
|
|
3399
3705
|
});
|
|
3400
|
-
const ApiFilesUploadRoute = Route$
|
|
3706
|
+
const ApiFilesUploadRoute = Route$b.update({
|
|
3401
3707
|
id: "/api/files/upload",
|
|
3402
3708
|
path: "/api/files/upload",
|
|
3403
|
-
getParentRoute: () => Route$
|
|
3709
|
+
getParentRoute: () => Route$B
|
|
3404
3710
|
});
|
|
3405
|
-
const ApiFilesSaveRoute = Route$
|
|
3711
|
+
const ApiFilesSaveRoute = Route$a.update({
|
|
3406
3712
|
id: "/api/files/save",
|
|
3407
3713
|
path: "/api/files/save",
|
|
3408
|
-
getParentRoute: () => Route$
|
|
3714
|
+
getParentRoute: () => Route$B
|
|
3409
3715
|
});
|
|
3410
|
-
const ApiFilesRenameRoute = Route$
|
|
3716
|
+
const ApiFilesRenameRoute = Route$9.update({
|
|
3411
3717
|
id: "/api/files/rename",
|
|
3412
3718
|
path: "/api/files/rename",
|
|
3413
|
-
getParentRoute: () => Route$
|
|
3719
|
+
getParentRoute: () => Route$B
|
|
3414
3720
|
});
|
|
3415
|
-
const ApiFilesReadRoute = Route$
|
|
3721
|
+
const ApiFilesReadRoute = Route$8.update({
|
|
3416
3722
|
id: "/api/files/read",
|
|
3417
3723
|
path: "/api/files/read",
|
|
3418
|
-
getParentRoute: () => Route$
|
|
3724
|
+
getParentRoute: () => Route$B
|
|
3419
3725
|
});
|
|
3420
|
-
const ApiFilesMkdirRoute = Route$
|
|
3726
|
+
const ApiFilesMkdirRoute = Route$7.update({
|
|
3421
3727
|
id: "/api/files/mkdir",
|
|
3422
3728
|
path: "/api/files/mkdir",
|
|
3423
|
-
getParentRoute: () => Route$
|
|
3729
|
+
getParentRoute: () => Route$B
|
|
3424
3730
|
});
|
|
3425
|
-
const ApiFilesListRoute = Route$
|
|
3731
|
+
const ApiFilesListRoute = Route$6.update({
|
|
3426
3732
|
id: "/api/files/list",
|
|
3427
3733
|
path: "/api/files/list",
|
|
3428
|
-
getParentRoute: () => Route$
|
|
3734
|
+
getParentRoute: () => Route$B
|
|
3429
3735
|
});
|
|
3430
|
-
const ApiFilesInfoRoute = Route$
|
|
3736
|
+
const ApiFilesInfoRoute = Route$5.update({
|
|
3431
3737
|
id: "/api/files/info",
|
|
3432
3738
|
path: "/api/files/info",
|
|
3433
|
-
getParentRoute: () => Route$
|
|
3739
|
+
getParentRoute: () => Route$B
|
|
3434
3740
|
});
|
|
3435
|
-
const ApiFilesDownloadRoute = Route$
|
|
3741
|
+
const ApiFilesDownloadRoute = Route$4.update({
|
|
3436
3742
|
id: "/api/files/download",
|
|
3437
3743
|
path: "/api/files/download",
|
|
3438
|
-
getParentRoute: () => Route$
|
|
3744
|
+
getParentRoute: () => Route$B
|
|
3439
3745
|
});
|
|
3440
|
-
const ApiFilesDeleteRoute = Route.update({
|
|
3746
|
+
const ApiFilesDeleteRoute = Route$3.update({
|
|
3441
3747
|
id: "/api/files/delete",
|
|
3442
3748
|
path: "/api/files/delete",
|
|
3443
|
-
getParentRoute: () => Route$
|
|
3749
|
+
getParentRoute: () => Route$B
|
|
3750
|
+
});
|
|
3751
|
+
const ApiDashboardSystemRoute = Route$2.update({
|
|
3752
|
+
id: "/api/dashboard/system",
|
|
3753
|
+
path: "/api/dashboard/system",
|
|
3754
|
+
getParentRoute: () => Route$B
|
|
3755
|
+
});
|
|
3756
|
+
const ApiDashboardGatewayRoute = Route$1.update({
|
|
3757
|
+
id: "/api/dashboard/gateway",
|
|
3758
|
+
path: "/api/dashboard/gateway",
|
|
3759
|
+
getParentRoute: () => Route$B
|
|
3760
|
+
});
|
|
3761
|
+
const ApiDashboardCronsRoute = Route.update({
|
|
3762
|
+
id: "/api/dashboard/crons",
|
|
3763
|
+
path: "/api/dashboard/crons",
|
|
3764
|
+
getParentRoute: () => Route$B
|
|
3444
3765
|
});
|
|
3445
3766
|
const rootRouteChildren = {
|
|
3446
3767
|
IndexRoute,
|
|
3447
3768
|
AgentsRoute,
|
|
3448
3769
|
BotsRoute,
|
|
3449
3770
|
ConnectRoute,
|
|
3771
|
+
DashboardRoute,
|
|
3450
3772
|
FilesRoute,
|
|
3451
3773
|
MemoryRoute,
|
|
3452
3774
|
NewRoute,
|
|
@@ -3467,6 +3789,9 @@ const rootRouteChildren = {
|
|
|
3467
3789
|
ApiSttRoute,
|
|
3468
3790
|
ApiTtsRoute,
|
|
3469
3791
|
ChatSessionKeyRoute,
|
|
3792
|
+
ApiDashboardCronsRoute,
|
|
3793
|
+
ApiDashboardGatewayRoute,
|
|
3794
|
+
ApiDashboardSystemRoute,
|
|
3470
3795
|
ApiFilesDeleteRoute,
|
|
3471
3796
|
ApiFilesDownloadRoute,
|
|
3472
3797
|
ApiFilesInfoRoute,
|
|
@@ -3477,7 +3802,7 @@ const rootRouteChildren = {
|
|
|
3477
3802
|
ApiFilesSaveRoute,
|
|
3478
3803
|
ApiFilesUploadRoute
|
|
3479
3804
|
};
|
|
3480
|
-
const routeTree = Route$
|
|
3805
|
+
const routeTree = Route$B._addFileChildren(rootRouteChildren)._addFileTypes();
|
|
3481
3806
|
const getRouter = () => {
|
|
3482
3807
|
const router2 = createRouter({
|
|
3483
3808
|
routeTree,
|
|
@@ -3492,7 +3817,7 @@ const router = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
|
|
|
3492
3817
|
getRouter
|
|
3493
3818
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
3494
3819
|
export {
|
|
3495
|
-
Route$
|
|
3496
|
-
Route$
|
|
3820
|
+
Route$s as R,
|
|
3821
|
+
Route$r as a,
|
|
3497
3822
|
router as r
|
|
3498
3823
|
};
|