opencami 1.7.0 → 1.8.3
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 +167 -7
- package/bin/opencami.js +15 -6
- package/dist/client/assets/{CSPContext-a-MQmQQt.js → CSPContext-DeJH85nm.js} +1 -1
- package/dist/client/assets/{DirectionContext-DRcND-Cm.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-BX1MWO82.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-BlC2sH55.js → index-DtGzE-ea.js} +1 -1
- package/dist/client/assets/{index-Dg0mbvtv.js → index-Yo5UhdZV.js} +1 -1
- package/dist/client/assets/keyboard-shortcuts-dialog-BZwd-iyV.js +1 -0
- package/dist/client/assets/{main-CEuT8-Qi.js → main-CgwdHc9W.js} +16 -8
- package/dist/client/assets/{markdown-DKD6ZLRJ.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-DA69yVKc.js → opencami-logo-Bmge6-FB.js} +1 -1
- package/dist/client/assets/popupStateMapping-D0ZbJR_o.js +1 -0
- package/dist/client/assets/{proxy-Cawf6X0W.js → proxy-CYZeDXoy.js} +1 -1
- package/dist/client/assets/{react-K9goXsVv.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-DFL-3BRH.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-Cl9XA2_f.js → useControlled-B5pEEz2V.js} +1 -1
- package/dist/client/assets/{useMutation-C5bTdeC1.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-BBG3ZUlo.js → _sessionKey-C9o7YfxA.js} +878 -755
- 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-BgMPaOsU.js → index-Bw-bA_2M.js} +4 -3
- package/dist/server/assets/{router-Bl2uabfY.js → router-DCjikH21.js} +704 -207
- package/dist/server/assets/{search-dialog-BtSQW9SR.js → search-dialog-BnwiXpdA.js} +5 -4
- package/dist/server/assets/settings-dialog-ClKFnZ1x.js +1511 -0
- package/dist/server/server.js +2 -2
- package/package.json +1 -1
- package/dist/client/assets/_sessionKey-BAmpzUOP.js +0 -23
- package/dist/client/assets/agents-BkeWu_3a.js +0 -2
- package/dist/client/assets/agents-screen-Cb76bcxn.js +0 -1
- package/dist/client/assets/bots-CyJwr-JU.js +0 -2
- package/dist/client/assets/bots-screen-CzNjLsQH.js +0 -1
- package/dist/client/assets/button-DNC5N25i.js +0 -1
- package/dist/client/assets/composite-Bliqcmg4.js +0 -1
- package/dist/client/assets/file-explorer-screen-CpY1O_ag.js +0 -1
- package/dist/client/assets/files-HiN5rXWq.js +0 -2
- package/dist/client/assets/keyboard-shortcuts-dialog-C2Hq19LN.js +0 -1
- package/dist/client/assets/memory-lhzf-8Q4.js +0 -2
- package/dist/client/assets/memory-screen-Zq9qfnJK.js +0 -1
- package/dist/client/assets/menu-47ooFeSm.js +0 -1
- package/dist/client/assets/owner-CFRNz_Tp.js +0 -1
- package/dist/client/assets/popupStateMapping-D5k-jOeY.js +0 -1
- package/dist/client/assets/search-dialog-C5Yae9rb.js +0 -1
- package/dist/client/assets/session-export-dialog-CBeTfbll.js +0 -1
- package/dist/client/assets/settings-dialog-CoeG9M1b.js +0 -1
- package/dist/client/assets/skills-BEkw619A.js +0 -2
- package/dist/client/assets/styles-D4EBtWYc.css +0 -1
- package/dist/client/assets/switch-DAFvLxNX.js +0 -1
- package/dist/client/assets/tabs-B2Y_7MvG.js +0 -1
- package/dist/client/assets/tooltip-D57Pal0B.js +0 -1
- package/dist/client/assets/use-file-explorer-state-DppKEjcl.js +0 -12
- package/dist/client/assets/useButton-DVAfkehQ.js +0 -1
- package/dist/client/assets/useCompositeItem-CzdGhGcj.js +0 -1
- package/dist/client/assets/visuallyHidden-CO3ZD5AQ.js +0 -1
- package/dist/server/assets/_tanstack-start-manifest_v-DmMFarHb.js +0 -4
- package/dist/server/assets/settings-dialog-D3fOAswX.js +0 -1173
|
@@ -1,21 +1,29 @@
|
|
|
1
1
|
import { createRootRoute, Outlet, HeadContent, Scripts, createFileRoute, lazyRouteComponent, redirect, createRouter } from "@tanstack/react-router";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { QueryClientProvider, QueryClient } from "@tanstack/react-query";
|
|
4
|
-
import { randomUUID } from "node:crypto";
|
|
5
|
-
import
|
|
6
|
-
import { readFileSync, existsSync } from "node:fs";
|
|
7
|
-
import path, { join, resolve, relative, extname } from "node:path";
|
|
4
|
+
import crypto, { randomUUID } from "node:crypto";
|
|
5
|
+
import fs, { readFileSync, existsSync } from "node:fs";
|
|
8
6
|
import os, { homedir } from "node:os";
|
|
7
|
+
import path, { join, resolve, relative, extname } from "node:path";
|
|
8
|
+
import WebSocket from "ws";
|
|
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 = `
|
|
@@ -211,7 +220,7 @@ function NotFoundRedirect() {
|
|
|
211
220
|
}
|
|
212
221
|
return null;
|
|
213
222
|
}
|
|
214
|
-
const Route$
|
|
223
|
+
const Route$B = createRootRoute({
|
|
215
224
|
notFoundComponent: NotFoundRedirect,
|
|
216
225
|
head: () => ({
|
|
217
226
|
meta: [
|
|
@@ -319,12 +328,12 @@ function RootDocument({ children }) {
|
|
|
319
328
|
] })
|
|
320
329
|
] });
|
|
321
330
|
}
|
|
322
|
-
const $$splitComponentImporter$
|
|
323
|
-
const Route$
|
|
324
|
-
component: lazyRouteComponent($$splitComponentImporter$
|
|
331
|
+
const $$splitComponentImporter$9 = () => import("./skills-Cy8xclXY.js");
|
|
332
|
+
const Route$A = createFileRoute("/skills")({
|
|
333
|
+
component: lazyRouteComponent($$splitComponentImporter$9, "component")
|
|
325
334
|
});
|
|
326
|
-
const $$splitComponentImporter$
|
|
327
|
-
const Route$
|
|
335
|
+
const $$splitComponentImporter$8 = () => import("./new-Dzk5YxE9.js");
|
|
336
|
+
const Route$z = createFileRoute("/new")({
|
|
328
337
|
beforeLoad: function redirectToNewChat() {
|
|
329
338
|
throw redirect({
|
|
330
339
|
to: "/chat/$sessionKey",
|
|
@@ -334,34 +343,38 @@ const Route$v = createFileRoute("/new")({
|
|
|
334
343
|
replace: true
|
|
335
344
|
});
|
|
336
345
|
},
|
|
346
|
+
component: lazyRouteComponent($$splitComponentImporter$8, "component")
|
|
347
|
+
});
|
|
348
|
+
const $$splitComponentImporter$7 = () => import("./memory-BqZOoD7Q.js");
|
|
349
|
+
const Route$y = createFileRoute("/memory")({
|
|
337
350
|
component: lazyRouteComponent($$splitComponentImporter$7, "component")
|
|
338
351
|
});
|
|
339
|
-
const $$splitComponentImporter$6 = () => import("./
|
|
340
|
-
const Route$
|
|
352
|
+
const $$splitComponentImporter$6 = () => import("./files-DYdXlQDr.js");
|
|
353
|
+
const Route$x = createFileRoute("/files")({
|
|
341
354
|
component: lazyRouteComponent($$splitComponentImporter$6, "component")
|
|
342
355
|
});
|
|
343
|
-
const $$splitComponentImporter$5 = () => import("./
|
|
344
|
-
const Route$
|
|
356
|
+
const $$splitComponentImporter$5 = () => import("./dashboard-GCKodTiJ.js");
|
|
357
|
+
const Route$w = createFileRoute("/dashboard")({
|
|
345
358
|
component: lazyRouteComponent($$splitComponentImporter$5, "component")
|
|
346
359
|
});
|
|
347
360
|
const $$splitComponentImporter$4 = () => import("./connect-CbgijWz4.js");
|
|
348
|
-
const Route$
|
|
361
|
+
const Route$v = createFileRoute("/connect")({
|
|
349
362
|
component: lazyRouteComponent($$splitComponentImporter$4, "component")
|
|
350
363
|
});
|
|
351
364
|
const $$splitComponentImporter$3 = () => import("./bots-Byt6jv0a.js");
|
|
352
|
-
const Route$
|
|
365
|
+
const Route$u = createFileRoute("/bots")({
|
|
353
366
|
component: lazyRouteComponent($$splitComponentImporter$3, "component")
|
|
354
367
|
});
|
|
355
368
|
const $$splitComponentImporter$2 = () => import("./agents-CmQ4vvXm.js");
|
|
356
|
-
const Route$
|
|
369
|
+
const Route$t = createFileRoute("/agents")({
|
|
357
370
|
component: lazyRouteComponent($$splitComponentImporter$2, "component")
|
|
358
371
|
});
|
|
359
|
-
const $$splitComponentImporter$1 = () => import("./index-
|
|
360
|
-
const Route$
|
|
372
|
+
const $$splitComponentImporter$1 = () => import("./index-Bw-bA_2M.js");
|
|
373
|
+
const Route$s = createFileRoute("/")({
|
|
361
374
|
component: lazyRouteComponent($$splitComponentImporter$1, "component")
|
|
362
375
|
});
|
|
363
|
-
const $$splitComponentImporter = () => import("./_sessionKey-
|
|
364
|
-
const Route$
|
|
376
|
+
const $$splitComponentImporter = () => import("./_sessionKey-C9o7YfxA.js").then((n) => n.$);
|
|
377
|
+
const Route$r = createFileRoute("/chat/$sessionKey")({
|
|
365
378
|
component: lazyRouteComponent($$splitComponentImporter, "component")
|
|
366
379
|
});
|
|
367
380
|
function getGatewayConfig() {
|
|
@@ -375,24 +388,150 @@ function getGatewayConfig() {
|
|
|
375
388
|
}
|
|
376
389
|
return { url, token, password };
|
|
377
390
|
}
|
|
378
|
-
|
|
391
|
+
const ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
|
|
392
|
+
function base64UrlEncode(buf) {
|
|
393
|
+
return buf.toString("base64").replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/g, "");
|
|
394
|
+
}
|
|
395
|
+
function derivePublicKeyRaw(publicKeyPem) {
|
|
396
|
+
const spki = crypto.createPublicKey(publicKeyPem).export({ type: "spki", format: "der" });
|
|
397
|
+
if (spki.length === ED25519_SPKI_PREFIX.length + 32 && spki.subarray(0, ED25519_SPKI_PREFIX.length).equals(ED25519_SPKI_PREFIX)) {
|
|
398
|
+
return spki.subarray(ED25519_SPKI_PREFIX.length);
|
|
399
|
+
}
|
|
400
|
+
return spki;
|
|
401
|
+
}
|
|
402
|
+
function fingerprintPublicKey(publicKeyPem) {
|
|
403
|
+
const raw = derivePublicKeyRaw(publicKeyPem);
|
|
404
|
+
return crypto.createHash("sha256").update(raw).digest("hex");
|
|
405
|
+
}
|
|
406
|
+
function ensureDir(filePath) {
|
|
407
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
408
|
+
}
|
|
409
|
+
function resolveDeviceIdentityPath() {
|
|
410
|
+
return path.join(os.homedir(), ".opencami", "identity", "device.json");
|
|
411
|
+
}
|
|
412
|
+
function loadOrCreateDeviceIdentity(filePath = resolveDeviceIdentityPath()) {
|
|
413
|
+
try {
|
|
414
|
+
if (fs.existsSync(filePath)) {
|
|
415
|
+
const raw = fs.readFileSync(filePath, "utf8");
|
|
416
|
+
const parsed = JSON.parse(raw);
|
|
417
|
+
if (parsed?.version === 1 && typeof parsed.deviceId === "string" && typeof parsed.publicKeyPem === "string" && typeof parsed.privateKeyPem === "string") {
|
|
418
|
+
const derivedId = fingerprintPublicKey(parsed.publicKeyPem);
|
|
419
|
+
if (derivedId && derivedId !== parsed.deviceId) {
|
|
420
|
+
const updated = { ...parsed, deviceId: derivedId };
|
|
421
|
+
fs.writeFileSync(filePath, `${JSON.stringify(updated, null, 2)}
|
|
422
|
+
`, { mode: 384 });
|
|
423
|
+
try {
|
|
424
|
+
fs.chmodSync(filePath, 384);
|
|
425
|
+
} catch {
|
|
426
|
+
}
|
|
427
|
+
return { deviceId: derivedId, publicKeyPem: parsed.publicKeyPem, privateKeyPem: parsed.privateKeyPem };
|
|
428
|
+
}
|
|
429
|
+
return { deviceId: parsed.deviceId, publicKeyPem: parsed.publicKeyPem, privateKeyPem: parsed.privateKeyPem };
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
} catch {
|
|
433
|
+
}
|
|
434
|
+
const { publicKey, privateKey } = crypto.generateKeyPairSync("ed25519");
|
|
435
|
+
const publicKeyPem = publicKey.export({ type: "spki", format: "pem" }).toString();
|
|
436
|
+
const privateKeyPem = privateKey.export({ type: "pkcs8", format: "pem" }).toString();
|
|
437
|
+
const deviceId = fingerprintPublicKey(publicKeyPem);
|
|
438
|
+
ensureDir(filePath);
|
|
439
|
+
const stored = {
|
|
440
|
+
version: 1,
|
|
441
|
+
deviceId,
|
|
442
|
+
publicKeyPem,
|
|
443
|
+
privateKeyPem,
|
|
444
|
+
createdAtMs: Date.now()
|
|
445
|
+
};
|
|
446
|
+
fs.writeFileSync(filePath, `${JSON.stringify(stored, null, 2)}
|
|
447
|
+
`, { mode: 384 });
|
|
448
|
+
try {
|
|
449
|
+
fs.chmodSync(filePath, 384);
|
|
450
|
+
} catch {
|
|
451
|
+
}
|
|
452
|
+
return { deviceId, publicKeyPem, privateKeyPem };
|
|
453
|
+
}
|
|
454
|
+
function signDevicePayload(privateKeyPem, payload) {
|
|
455
|
+
const key = crypto.createPrivateKey(privateKeyPem);
|
|
456
|
+
return base64UrlEncode(crypto.sign(null, Buffer.from(payload, "utf8"), key));
|
|
457
|
+
}
|
|
458
|
+
function publicKeyRawBase64UrlFromPem(publicKeyPem) {
|
|
459
|
+
return base64UrlEncode(derivePublicKeyRaw(publicKeyPem));
|
|
460
|
+
}
|
|
461
|
+
function buildDeviceAuthPayload(args) {
|
|
462
|
+
const scopes = args.scopes.join(",");
|
|
463
|
+
const token = args.token ?? "";
|
|
464
|
+
return ["v2", args.deviceId, args.clientId, args.clientMode, args.role, scopes, String(args.signedAtMs), token, args.nonce].join("|");
|
|
465
|
+
}
|
|
466
|
+
function loadOrCreateInstanceId() {
|
|
467
|
+
const filePath = path.join(os.homedir(), ".opencami", "identity", "instance-id.txt");
|
|
468
|
+
try {
|
|
469
|
+
if (fs.existsSync(filePath)) {
|
|
470
|
+
const v2 = fs.readFileSync(filePath, "utf8").trim();
|
|
471
|
+
if (v2) return v2;
|
|
472
|
+
}
|
|
473
|
+
} catch {
|
|
474
|
+
}
|
|
475
|
+
const v = randomUUID();
|
|
476
|
+
ensureDir(filePath);
|
|
477
|
+
fs.writeFileSync(filePath, `${v}
|
|
478
|
+
`, { mode: 384 });
|
|
479
|
+
try {
|
|
480
|
+
fs.chmodSync(filePath, 384);
|
|
481
|
+
} catch {
|
|
482
|
+
}
|
|
483
|
+
return v;
|
|
484
|
+
}
|
|
485
|
+
function buildConnectParams(token, password, nonce) {
|
|
486
|
+
const clientId = "openclaw-control-ui";
|
|
487
|
+
const clientMode = "webchat";
|
|
488
|
+
const role = "operator";
|
|
489
|
+
const scopes = ["operator.read", "operator.write"];
|
|
490
|
+
if (!nonce) {
|
|
491
|
+
throw new Error(
|
|
492
|
+
"OpenClaw did not send connect.challenge nonce in time. If you are connecting cross-origin, ensure your origin is allowed (gateway.controlUi.allowedOrigins)."
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
const identity = loadOrCreateDeviceIdentity();
|
|
496
|
+
const signedAtMs = Date.now();
|
|
497
|
+
const payload = buildDeviceAuthPayload({
|
|
498
|
+
deviceId: identity.deviceId,
|
|
499
|
+
clientId,
|
|
500
|
+
clientMode,
|
|
501
|
+
role,
|
|
502
|
+
scopes,
|
|
503
|
+
signedAtMs,
|
|
504
|
+
token: token || null,
|
|
505
|
+
nonce
|
|
506
|
+
});
|
|
507
|
+
const signature = signDevicePayload(identity.privateKeyPem, payload);
|
|
379
508
|
return {
|
|
380
509
|
minProtocol: 3,
|
|
381
510
|
maxProtocol: 3,
|
|
382
511
|
client: {
|
|
383
|
-
id:
|
|
512
|
+
id: clientId,
|
|
384
513
|
displayName: "OpenCami",
|
|
385
514
|
version: "dev",
|
|
386
515
|
platform: process.platform,
|
|
387
|
-
mode:
|
|
388
|
-
instanceId:
|
|
516
|
+
mode: clientMode,
|
|
517
|
+
instanceId: loadOrCreateInstanceId()
|
|
389
518
|
},
|
|
519
|
+
caps: [],
|
|
390
520
|
auth: {
|
|
391
521
|
token: token || void 0,
|
|
392
522
|
password: password || void 0
|
|
393
523
|
},
|
|
394
524
|
role: "operator",
|
|
395
|
-
scopes
|
|
525
|
+
scopes,
|
|
526
|
+
device: {
|
|
527
|
+
id: identity.deviceId,
|
|
528
|
+
publicKey: publicKeyRawBase64UrlFromPem(identity.publicKeyPem),
|
|
529
|
+
signature,
|
|
530
|
+
signedAt: signedAtMs,
|
|
531
|
+
nonce
|
|
532
|
+
},
|
|
533
|
+
userAgent: `opencami/${process.env.npm_package_version ?? "dev"} (node ${process.version})`,
|
|
534
|
+
locale: process.env.LANG || "en"
|
|
396
535
|
};
|
|
397
536
|
}
|
|
398
537
|
class PersistentGatewayConnection {
|
|
@@ -427,7 +566,8 @@ class PersistentGatewayConnection {
|
|
|
427
566
|
async _connect() {
|
|
428
567
|
if (this.destroyed) throw new Error("Connection destroyed");
|
|
429
568
|
const { url, token, password } = getGatewayConfig();
|
|
430
|
-
const
|
|
569
|
+
const origin = process.env.OPENCAMI_ORIGIN?.trim();
|
|
570
|
+
const ws = origin ? new WebSocket(url, { headers: { Origin: origin } }) : new WebSocket(url);
|
|
431
571
|
this.ws = ws;
|
|
432
572
|
await new Promise((resolve2, reject) => {
|
|
433
573
|
const onOpen = () => {
|
|
@@ -445,19 +585,93 @@ class PersistentGatewayConnection {
|
|
|
445
585
|
ws.on("open", onOpen);
|
|
446
586
|
ws.on("error", onError);
|
|
447
587
|
});
|
|
588
|
+
const nonce = await new Promise((resolve2) => {
|
|
589
|
+
let done = false;
|
|
590
|
+
const timer = setTimeout(() => {
|
|
591
|
+
if (done) return;
|
|
592
|
+
done = true;
|
|
593
|
+
resolve2("");
|
|
594
|
+
}, 3e3);
|
|
595
|
+
const onMessage = (data) => {
|
|
596
|
+
try {
|
|
597
|
+
const str = typeof data === "string" ? data : data.toString();
|
|
598
|
+
const parsed = JSON.parse(str);
|
|
599
|
+
if (parsed.type === "event" && parsed.event === "connect.challenge") {
|
|
600
|
+
const n = parsed.payload?.nonce;
|
|
601
|
+
if (typeof n === "string" && n.length > 0) {
|
|
602
|
+
clearTimeout(timer);
|
|
603
|
+
ws.off("message", onMessage);
|
|
604
|
+
if (done) return;
|
|
605
|
+
done = true;
|
|
606
|
+
resolve2(n);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
} catch {
|
|
610
|
+
}
|
|
611
|
+
};
|
|
612
|
+
ws.on("message", onMessage);
|
|
613
|
+
});
|
|
448
614
|
ws.on("message", (data) => this._onMessage(data));
|
|
449
615
|
ws.on("close", () => this._onClose());
|
|
450
616
|
ws.on("error", () => {
|
|
451
617
|
});
|
|
452
618
|
const connectId = randomUUID();
|
|
453
|
-
const
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
619
|
+
const shouldFallback = process.env.OPENCAMI_DEVICE_AUTH_FALLBACK === "1" || process.env.OPENCAMI_DEVICE_AUTH_FALLBACK === "true";
|
|
620
|
+
try {
|
|
621
|
+
const connectParams = buildConnectParams(token, password, nonce);
|
|
622
|
+
ws.send(
|
|
623
|
+
JSON.stringify({
|
|
624
|
+
type: "req",
|
|
625
|
+
id: connectId,
|
|
626
|
+
method: "connect",
|
|
627
|
+
params: connectParams
|
|
628
|
+
})
|
|
629
|
+
);
|
|
630
|
+
const hello = await this._waitForRes(connectId, 1e4);
|
|
631
|
+
const grantedScopes = hello?.auth?.scopes;
|
|
632
|
+
if (Array.isArray(grantedScopes) && !grantedScopes.includes("operator.read")) {
|
|
633
|
+
throw new Error(
|
|
634
|
+
`Gateway connected but missing required scope: operator.read (granted: ${grantedScopes.join(", ")})`
|
|
635
|
+
);
|
|
636
|
+
}
|
|
637
|
+
} catch (err) {
|
|
638
|
+
if (!shouldFallback) throw err;
|
|
639
|
+
console.warn(
|
|
640
|
+
"[gateway-ws] Device auth connect failed; retrying without device identity (fallback enabled):",
|
|
641
|
+
err instanceof Error ? err.message : err
|
|
642
|
+
);
|
|
643
|
+
const fallbackId = randomUUID();
|
|
644
|
+
const fallbackParams = {
|
|
645
|
+
minProtocol: 3,
|
|
646
|
+
maxProtocol: 3,
|
|
647
|
+
client: {
|
|
648
|
+
id: "openclaw-control-ui",
|
|
649
|
+
displayName: "OpenCami",
|
|
650
|
+
version: "dev",
|
|
651
|
+
platform: process.platform,
|
|
652
|
+
mode: "webchat",
|
|
653
|
+
instanceId: loadOrCreateInstanceId()
|
|
654
|
+
},
|
|
655
|
+
caps: [],
|
|
656
|
+
auth: {
|
|
657
|
+
token: token || void 0,
|
|
658
|
+
password: password || void 0
|
|
659
|
+
},
|
|
660
|
+
role: "operator",
|
|
661
|
+
scopes: ["operator.read", "operator.write"],
|
|
662
|
+
userAgent: `opencami/${process.env.npm_package_version ?? "dev"} (node ${process.version})`,
|
|
663
|
+
locale: process.env.LANG || "en"
|
|
664
|
+
};
|
|
665
|
+
ws.send(
|
|
666
|
+
JSON.stringify({
|
|
667
|
+
type: "req",
|
|
668
|
+
id: fallbackId,
|
|
669
|
+
method: "connect",
|
|
670
|
+
params: fallbackParams
|
|
671
|
+
})
|
|
672
|
+
);
|
|
673
|
+
await this._waitForRes(fallbackId, 1e4);
|
|
674
|
+
}
|
|
461
675
|
this.connected = true;
|
|
462
676
|
this.reconnectDelay = 1e3;
|
|
463
677
|
console.log("[gateway-ws] Persistent connection established");
|
|
@@ -623,10 +837,12 @@ class PersistentGatewayConnection {
|
|
|
623
837
|
}
|
|
624
838
|
}
|
|
625
839
|
let _instance = null;
|
|
840
|
+
const _g = globalThis;
|
|
626
841
|
function getPersistentConnection() {
|
|
627
|
-
if (!
|
|
628
|
-
|
|
842
|
+
if (!_g.__opencamiGatewayInstance) {
|
|
843
|
+
_g.__opencamiGatewayInstance = new PersistentGatewayConnection();
|
|
629
844
|
}
|
|
845
|
+
_instance = _g.__opencamiGatewayInstance;
|
|
630
846
|
return _instance;
|
|
631
847
|
}
|
|
632
848
|
async function gatewayRpc(method, params) {
|
|
@@ -728,7 +944,7 @@ async function ttsEdge(text, voice) {
|
|
|
728
944
|
}
|
|
729
945
|
});
|
|
730
946
|
}
|
|
731
|
-
const Route$
|
|
947
|
+
const Route$q = createFileRoute("/api/tts")({
|
|
732
948
|
server: {
|
|
733
949
|
handlers: {
|
|
734
950
|
POST: async ({ request }) => {
|
|
@@ -883,7 +1099,7 @@ async function sttOpenAI(audioBlob, apiKey, language) {
|
|
|
883
1099
|
const data = await res.json();
|
|
884
1100
|
return { text: data.text || "" };
|
|
885
1101
|
}
|
|
886
|
-
const Route$
|
|
1102
|
+
const Route$p = createFileRoute("/api/stt")({
|
|
887
1103
|
server: {
|
|
888
1104
|
handlers: {
|
|
889
1105
|
POST: async ({ request }) => {
|
|
@@ -985,7 +1201,7 @@ const Route$m = createFileRoute("/api/stt")({
|
|
|
985
1201
|
}
|
|
986
1202
|
}
|
|
987
1203
|
});
|
|
988
|
-
const Route$
|
|
1204
|
+
const Route$o = createFileRoute("/api/stream")({
|
|
989
1205
|
server: {
|
|
990
1206
|
handlers: {
|
|
991
1207
|
GET: async ({ request }) => {
|
|
@@ -997,88 +1213,86 @@ const Route$l = createFileRoute("/api/stream")({
|
|
|
997
1213
|
{ status: 400, headers: { "content-type": "application/json" } }
|
|
998
1214
|
);
|
|
999
1215
|
}
|
|
1216
|
+
const pass = new PassThrough();
|
|
1000
1217
|
const encoder = new TextEncoder();
|
|
1001
|
-
let unsubscribe = null;
|
|
1002
1218
|
let closed = false;
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
try {
|
|
1009
|
-
controller.enqueue(
|
|
1010
|
-
encoder.encode(`event: ${event}
|
|
1219
|
+
let unsubscribe = null;
|
|
1220
|
+
function sendSSE(event, data) {
|
|
1221
|
+
if (closed) return;
|
|
1222
|
+
try {
|
|
1223
|
+
pass.write(encoder.encode(`event: ${event}
|
|
1011
1224
|
data: ${JSON.stringify(data)}
|
|
1012
1225
|
|
|
1013
|
-
`)
|
|
1014
|
-
|
|
1015
|
-
|
|
1226
|
+
`));
|
|
1227
|
+
} catch {
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
function cleanup() {
|
|
1231
|
+
if (closed) return;
|
|
1232
|
+
closed = true;
|
|
1233
|
+
if (unsubscribe) {
|
|
1234
|
+
unsubscribe();
|
|
1235
|
+
unsubscribe = null;
|
|
1236
|
+
}
|
|
1237
|
+
try {
|
|
1238
|
+
pass.end();
|
|
1239
|
+
} catch {
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
pass.write(encoder.encode(": connected\n\n"));
|
|
1243
|
+
let gotAgentStream = false;
|
|
1244
|
+
unsubscribe = subscribeGatewayEvents(sessionKey, (evt) => {
|
|
1245
|
+
if (evt.event === "agent") {
|
|
1246
|
+
const payload = evt.payload;
|
|
1247
|
+
const agentStream = payload.stream;
|
|
1248
|
+
if (agentStream === "assistant") {
|
|
1249
|
+
gotAgentStream = true;
|
|
1250
|
+
const data = payload.data ?? payload;
|
|
1251
|
+
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 : "";
|
|
1252
|
+
if (text) {
|
|
1253
|
+
sendSSE("delta", { text, sessionKey });
|
|
1254
|
+
}
|
|
1255
|
+
} else if (agentStream === "tool") {
|
|
1256
|
+
gotAgentStream = true;
|
|
1257
|
+
const tdata = payload.data ?? payload;
|
|
1258
|
+
sendSSE("tool", {
|
|
1259
|
+
name: tdata.name ?? tdata.toolName ?? payload.name ?? "",
|
|
1260
|
+
status: tdata.phase ?? tdata.status ?? payload.phase ?? "running",
|
|
1261
|
+
id: tdata.id ?? tdata.toolCallId ?? payload.id ?? "",
|
|
1262
|
+
sessionKey
|
|
1263
|
+
});
|
|
1264
|
+
} else if (agentStream === "lifecycle") {
|
|
1265
|
+
const ldata = payload.data ?? payload;
|
|
1266
|
+
const phase = ldata.phase ?? payload.phase;
|
|
1267
|
+
if (phase === "end" || phase === "error") {
|
|
1268
|
+
sendSSE("done", {
|
|
1269
|
+
sessionKey,
|
|
1270
|
+
status: phase,
|
|
1271
|
+
error: phase === "error" ? payload.error : void 0
|
|
1272
|
+
});
|
|
1273
|
+
cleanup();
|
|
1016
1274
|
}
|
|
1017
1275
|
}
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
sendSSE("delta", { text, sessionKey });
|
|
1029
|
-
}
|
|
1030
|
-
} else if (agentStream === "tool") {
|
|
1031
|
-
gotAgentStream = true;
|
|
1032
|
-
const tdata = payload.data ?? payload;
|
|
1033
|
-
sendSSE("tool", {
|
|
1034
|
-
name: tdata.name ?? tdata.toolName ?? payload.name ?? "",
|
|
1035
|
-
status: tdata.phase ?? tdata.status ?? payload.phase ?? "running",
|
|
1036
|
-
id: tdata.id ?? tdata.toolCallId ?? payload.id ?? "",
|
|
1037
|
-
sessionKey
|
|
1038
|
-
});
|
|
1039
|
-
} else if (agentStream === "lifecycle") {
|
|
1040
|
-
const ldata = payload.data ?? payload;
|
|
1041
|
-
const phase = ldata.phase ?? payload.phase;
|
|
1042
|
-
if (phase === "end" || phase === "error") {
|
|
1043
|
-
sendSSE("done", {
|
|
1044
|
-
sessionKey,
|
|
1045
|
-
status: phase,
|
|
1046
|
-
error: phase === "error" ? payload.error : void 0
|
|
1047
|
-
});
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
} else if (evt.event === "chat") {
|
|
1051
|
-
const payload = evt.payload;
|
|
1052
|
-
const kind = payload.kind;
|
|
1053
|
-
if (kind === "delta" && !gotAgentStream) {
|
|
1054
|
-
const text = typeof payload.text === "string" ? payload.text : typeof payload.delta === "string" ? payload.delta : "";
|
|
1055
|
-
if (text) {
|
|
1056
|
-
sendSSE("delta", { text, sessionKey });
|
|
1057
|
-
}
|
|
1058
|
-
} else if (kind === "final") {
|
|
1059
|
-
sendSSE("done", { sessionKey, status: "end" });
|
|
1060
|
-
}
|
|
1276
|
+
} else if (evt.event === "chat") {
|
|
1277
|
+
const payload = evt.payload;
|
|
1278
|
+
const state = payload.state ?? payload.kind;
|
|
1279
|
+
const msg = payload.message;
|
|
1280
|
+
if (state === "delta" && !gotAgentStream) {
|
|
1281
|
+
const content = Array.isArray(msg?.content) ? msg.content : [];
|
|
1282
|
+
const firstBlock = content[0];
|
|
1283
|
+
const text = typeof firstBlock?.text === "string" ? firstBlock.text : typeof payload.text === "string" ? payload.text : typeof payload.delta === "string" ? payload.delta : "";
|
|
1284
|
+
if (text) {
|
|
1285
|
+
sendSSE("delta", { text, sessionKey });
|
|
1061
1286
|
}
|
|
1062
|
-
})
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
closed = true;
|
|
1066
|
-
if (unsubscribe) {
|
|
1067
|
-
unsubscribe();
|
|
1068
|
-
unsubscribe = null;
|
|
1287
|
+
} else if (state === "final") {
|
|
1288
|
+
sendSSE("done", { sessionKey, status: "end" });
|
|
1289
|
+
cleanup();
|
|
1069
1290
|
}
|
|
1070
1291
|
}
|
|
1071
1292
|
});
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
if (unsubscribe) {
|
|
1076
|
-
unsubscribe();
|
|
1077
|
-
unsubscribe = null;
|
|
1078
|
-
}
|
|
1079
|
-
});
|
|
1080
|
-
}
|
|
1081
|
-
return new Response(stream, {
|
|
1293
|
+
request.signal?.addEventListener("abort", cleanup);
|
|
1294
|
+
const webStream = Readable.toWeb(pass);
|
|
1295
|
+
return new Response(webStream, {
|
|
1082
1296
|
headers: {
|
|
1083
1297
|
"content-type": "text/event-stream",
|
|
1084
1298
|
"cache-control": "no-cache, no-transform",
|
|
@@ -1144,7 +1358,7 @@ function parseSearchResults(output) {
|
|
|
1144
1358
|
return { slug: line.trim(), displayName: line.trim(), version: "", summary: "" };
|
|
1145
1359
|
});
|
|
1146
1360
|
}
|
|
1147
|
-
const Route$
|
|
1361
|
+
const Route$n = createFileRoute("/api/skills")({
|
|
1148
1362
|
server: {
|
|
1149
1363
|
handlers: {
|
|
1150
1364
|
GET: async ({ request }) => {
|
|
@@ -1263,7 +1477,7 @@ function normalizeSessions(payload) {
|
|
|
1263
1477
|
});
|
|
1264
1478
|
return { sessions: normalized };
|
|
1265
1479
|
}
|
|
1266
|
-
const Route$
|
|
1480
|
+
const Route$m = createFileRoute("/api/sessions")({
|
|
1267
1481
|
server: {
|
|
1268
1482
|
handlers: {
|
|
1269
1483
|
GET: async () => {
|
|
@@ -1416,7 +1630,7 @@ const Route$j = createFileRoute("/api/sessions")({
|
|
|
1416
1630
|
}
|
|
1417
1631
|
}
|
|
1418
1632
|
});
|
|
1419
|
-
const Route$
|
|
1633
|
+
const Route$l = createFileRoute("/api/send")({
|
|
1420
1634
|
server: {
|
|
1421
1635
|
handlers: {
|
|
1422
1636
|
POST: async ({ request }) => {
|
|
@@ -1482,7 +1696,7 @@ const Route$i = createFileRoute("/api/send")({
|
|
|
1482
1696
|
}
|
|
1483
1697
|
}
|
|
1484
1698
|
});
|
|
1485
|
-
const Route$
|
|
1699
|
+
const Route$k = createFileRoute("/api/ping")({
|
|
1486
1700
|
server: {
|
|
1487
1701
|
handlers: {
|
|
1488
1702
|
GET: async () => {
|
|
@@ -1506,7 +1720,7 @@ const categories = { "core": [{ "id": "cami", "name": "Cami", "emoji": "🦎", "
|
|
|
1506
1720
|
const personasData = {
|
|
1507
1721
|
categories
|
|
1508
1722
|
};
|
|
1509
|
-
const Route$
|
|
1723
|
+
const Route$j = createFileRoute("/api/personas")({
|
|
1510
1724
|
server: {
|
|
1511
1725
|
handlers: {
|
|
1512
1726
|
GET: async () => {
|
|
@@ -1551,7 +1765,7 @@ function resolveSessionsDir() {
|
|
|
1551
1765
|
)
|
|
1552
1766
|
};
|
|
1553
1767
|
}
|
|
1554
|
-
const Route$
|
|
1768
|
+
const Route$i = createFileRoute("/api/paths")({
|
|
1555
1769
|
server: {
|
|
1556
1770
|
handlers: {
|
|
1557
1771
|
GET: () => {
|
|
@@ -1576,7 +1790,7 @@ function parseModelName(modelId) {
|
|
|
1576
1790
|
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
1577
1791
|
}).join(" ");
|
|
1578
1792
|
}
|
|
1579
|
-
const Route$
|
|
1793
|
+
const Route$h = createFileRoute("/api/models")({
|
|
1580
1794
|
server: {
|
|
1581
1795
|
handlers: {
|
|
1582
1796
|
GET: async () => {
|
|
@@ -1755,11 +1969,13 @@ async function testApiKey(apiKey) {
|
|
|
1755
1969
|
}
|
|
1756
1970
|
function getLlmConfig(request) {
|
|
1757
1971
|
const headerKey = request.headers.get("X-OpenAI-API-Key");
|
|
1758
|
-
const
|
|
1972
|
+
const headerBaseUrl = request.headers.get("X-LLM-Base-URL")?.trim() || null;
|
|
1973
|
+
const baseUrl = headerBaseUrl || process.env.LLM_BASE_URL?.trim() || null;
|
|
1759
1974
|
const isOpenRouter = baseUrl?.includes("openrouter.ai");
|
|
1760
|
-
const
|
|
1975
|
+
const isKilocode = baseUrl?.includes("kilo.ai");
|
|
1976
|
+
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();
|
|
1761
1977
|
const apiKey = headerKey?.trim() || envKey || null;
|
|
1762
|
-
const model = request.headers.get("X-LLM-Model")?.trim() || null;
|
|
1978
|
+
const model = request.headers.get("X-LLM-Model")?.trim() || process.env.LLM_MODEL?.trim() || null;
|
|
1763
1979
|
return { apiKey, baseUrl, model };
|
|
1764
1980
|
}
|
|
1765
1981
|
function generateHeuristicTitle(message) {
|
|
@@ -1782,7 +1998,7 @@ function generateHeuristicTitle(message) {
|
|
|
1782
1998
|
}
|
|
1783
1999
|
return title || message.slice(0, 50);
|
|
1784
2000
|
}
|
|
1785
|
-
const Route$
|
|
2001
|
+
const Route$g = createFileRoute("/api/llm-features")({
|
|
1786
2002
|
server: {
|
|
1787
2003
|
handlers: {
|
|
1788
2004
|
/**
|
|
@@ -1792,10 +2008,12 @@ const Route$d = createFileRoute("/api/llm-features")({
|
|
|
1792
2008
|
try {
|
|
1793
2009
|
const hasEnvKey = Boolean(process.env.OPENAI_API_KEY?.trim());
|
|
1794
2010
|
const hasOpenRouterKey = Boolean(process.env.OPENROUTER_API_KEY?.trim());
|
|
2011
|
+
const hasKilocodeKey = Boolean(process.env.KILOCODE_API_KEY?.trim());
|
|
1795
2012
|
return json({
|
|
1796
2013
|
ok: true,
|
|
1797
2014
|
hasEnvKey,
|
|
1798
|
-
hasOpenRouterKey
|
|
2015
|
+
hasOpenRouterKey,
|
|
2016
|
+
hasKilocodeKey
|
|
1799
2017
|
});
|
|
1800
2018
|
} catch (err) {
|
|
1801
2019
|
return json({
|
|
@@ -1934,7 +2152,7 @@ const Route$d = createFileRoute("/api/llm-features")({
|
|
|
1934
2152
|
}
|
|
1935
2153
|
}
|
|
1936
2154
|
});
|
|
1937
|
-
const Route$
|
|
2155
|
+
const Route$f = createFileRoute("/api/history")({
|
|
1938
2156
|
server: {
|
|
1939
2157
|
handlers: {
|
|
1940
2158
|
GET: async ({ request }) => {
|
|
@@ -1997,7 +2215,7 @@ function parseFollowUps(text) {
|
|
|
1997
2215
|
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);
|
|
1998
2216
|
return lines.slice(0, 3);
|
|
1999
2217
|
}
|
|
2000
|
-
const Route$
|
|
2218
|
+
const Route$e = createFileRoute("/api/follow-ups")({
|
|
2001
2219
|
server: {
|
|
2002
2220
|
handlers: {
|
|
2003
2221
|
POST: async ({ request }) => {
|
|
@@ -2108,7 +2326,7 @@ function parsePatch(value) {
|
|
|
2108
2326
|
if (Object.keys(patch).length === 0) return null;
|
|
2109
2327
|
return patch;
|
|
2110
2328
|
}
|
|
2111
|
-
const Route$
|
|
2329
|
+
const Route$d = createFileRoute("/api/cron")({
|
|
2112
2330
|
server: {
|
|
2113
2331
|
handlers: {
|
|
2114
2332
|
GET: async ({ request }) => {
|
|
@@ -2185,7 +2403,7 @@ function resolveModel(m) {
|
|
|
2185
2403
|
if (typeof m === "object" && "primary" in m) return m.primary;
|
|
2186
2404
|
return void 0;
|
|
2187
2405
|
}
|
|
2188
|
-
const Route$
|
|
2406
|
+
const Route$c = createFileRoute("/api/agents")({
|
|
2189
2407
|
server: {
|
|
2190
2408
|
handlers: {
|
|
2191
2409
|
GET: async () => {
|
|
@@ -2605,7 +2823,7 @@ function validateFilename(filename) {
|
|
|
2605
2823
|
return true;
|
|
2606
2824
|
}
|
|
2607
2825
|
const MAX_FILE_SIZE = 100 * 1024 * 1024;
|
|
2608
|
-
const Route$
|
|
2826
|
+
const Route$b = createFileRoute("/api/files/upload")({
|
|
2609
2827
|
server: {
|
|
2610
2828
|
handlers: {
|
|
2611
2829
|
POST: async ({ request }) => {
|
|
@@ -2700,7 +2918,7 @@ const Route$8 = createFileRoute("/api/files/upload")({
|
|
|
2700
2918
|
}
|
|
2701
2919
|
});
|
|
2702
2920
|
const MAX_TEXT_SIZE$1 = 5 * 1024 * 1024;
|
|
2703
|
-
const Route$
|
|
2921
|
+
const Route$a = createFileRoute("/api/files/save")({
|
|
2704
2922
|
server: {
|
|
2705
2923
|
handlers: {
|
|
2706
2924
|
POST: async ({ request }) => {
|
|
@@ -2742,7 +2960,7 @@ const Route$7 = createFileRoute("/api/files/save")({
|
|
|
2742
2960
|
}
|
|
2743
2961
|
}
|
|
2744
2962
|
});
|
|
2745
|
-
const Route$
|
|
2963
|
+
const Route$9 = createFileRoute("/api/files/rename")({
|
|
2746
2964
|
server: {
|
|
2747
2965
|
handlers: {
|
|
2748
2966
|
POST: async ({ request }) => {
|
|
@@ -2885,7 +3103,7 @@ const TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
2885
3103
|
"diff",
|
|
2886
3104
|
"patch"
|
|
2887
3105
|
]);
|
|
2888
|
-
const Route$
|
|
3106
|
+
const Route$8 = createFileRoute("/api/files/read")({
|
|
2889
3107
|
server: {
|
|
2890
3108
|
handlers: {
|
|
2891
3109
|
GET: async ({ request }) => {
|
|
@@ -2977,7 +3195,7 @@ function validateFolderName(path2) {
|
|
|
2977
3195
|
throw new Error("Invalid folder name");
|
|
2978
3196
|
}
|
|
2979
3197
|
}
|
|
2980
|
-
const Route$
|
|
3198
|
+
const Route$7 = createFileRoute("/api/files/mkdir")({
|
|
2981
3199
|
server: {
|
|
2982
3200
|
handlers: {
|
|
2983
3201
|
POST: async ({ request }) => {
|
|
@@ -3026,7 +3244,7 @@ const Route$4 = createFileRoute("/api/files/mkdir")({
|
|
|
3026
3244
|
}
|
|
3027
3245
|
}
|
|
3028
3246
|
});
|
|
3029
|
-
const Route$
|
|
3247
|
+
const Route$6 = createFileRoute("/api/files/list")({
|
|
3030
3248
|
server: {
|
|
3031
3249
|
handlers: {
|
|
3032
3250
|
GET: async ({ request }) => {
|
|
@@ -3061,7 +3279,7 @@ const Route$3 = createFileRoute("/api/files/list")({
|
|
|
3061
3279
|
}
|
|
3062
3280
|
}
|
|
3063
3281
|
});
|
|
3064
|
-
const Route$
|
|
3282
|
+
const Route$5 = createFileRoute("/api/files/info")({
|
|
3065
3283
|
server: {
|
|
3066
3284
|
handlers: {
|
|
3067
3285
|
GET: async ({ request }) => {
|
|
@@ -3182,7 +3400,7 @@ function isStaticAsset(filename) {
|
|
|
3182
3400
|
const staticExts = ["png", "jpg", "jpeg", "gif", "webp", "svg", "css", "js", "woff", "woff2", "ttf", "otf"];
|
|
3183
3401
|
return staticExts.includes(ext);
|
|
3184
3402
|
}
|
|
3185
|
-
const Route$
|
|
3403
|
+
const Route$4 = createFileRoute("/api/files/download")({
|
|
3186
3404
|
server: {
|
|
3187
3405
|
handlers: {
|
|
3188
3406
|
GET: async ({ request }) => {
|
|
@@ -3248,7 +3466,7 @@ const Route$1 = createFileRoute("/api/files/download")({
|
|
|
3248
3466
|
}
|
|
3249
3467
|
}
|
|
3250
3468
|
});
|
|
3251
|
-
const Route = createFileRoute("/api/files/delete")({
|
|
3469
|
+
const Route$3 = createFileRoute("/api/files/delete")({
|
|
3252
3470
|
server: {
|
|
3253
3471
|
handlers: {
|
|
3254
3472
|
DELETE: async ({ request }) => {
|
|
@@ -3306,176 +3524,452 @@ const Route = createFileRoute("/api/files/delete")({
|
|
|
3306
3524
|
}
|
|
3307
3525
|
}
|
|
3308
3526
|
});
|
|
3309
|
-
|
|
3527
|
+
function clampPercent(value) {
|
|
3528
|
+
if (!Number.isFinite(value)) return 0;
|
|
3529
|
+
return Math.max(0, Math.min(100, value));
|
|
3530
|
+
}
|
|
3531
|
+
function sampleCpuTimes() {
|
|
3532
|
+
const cpus = os.cpus();
|
|
3533
|
+
let idle = 0;
|
|
3534
|
+
let total = 0;
|
|
3535
|
+
for (const cpu of cpus) {
|
|
3536
|
+
idle += cpu.times.idle;
|
|
3537
|
+
total += cpu.times.user + cpu.times.nice + cpu.times.sys + cpu.times.idle + cpu.times.irq;
|
|
3538
|
+
}
|
|
3539
|
+
return { idle, total };
|
|
3540
|
+
}
|
|
3541
|
+
async function getCpuUsagePercent(sampleMs = 500) {
|
|
3542
|
+
const start = sampleCpuTimes();
|
|
3543
|
+
await new Promise((resolve2) => setTimeout(resolve2, sampleMs));
|
|
3544
|
+
const end = sampleCpuTimes();
|
|
3545
|
+
const idleDelta = end.idle - start.idle;
|
|
3546
|
+
const totalDelta = end.total - start.total;
|
|
3547
|
+
if (totalDelta <= 0) return 0;
|
|
3548
|
+
return clampPercent((totalDelta - idleDelta) / totalDelta * 100);
|
|
3549
|
+
}
|
|
3550
|
+
function getDiskStats() {
|
|
3551
|
+
try {
|
|
3552
|
+
const raw = execSync("df -k / | tail -1", {
|
|
3553
|
+
encoding: "utf8",
|
|
3554
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
3555
|
+
}).trim();
|
|
3556
|
+
const parts = raw.split(/\s+/);
|
|
3557
|
+
if (parts.length < 5) return { used: 0, total: 0 };
|
|
3558
|
+
const totalKb = Number(parts[1]);
|
|
3559
|
+
const usedKb = Number(parts[2]);
|
|
3560
|
+
if (!Number.isFinite(totalKb) || totalKb <= 0) return { used: 0, total: 0 };
|
|
3561
|
+
const total = totalKb * 1024;
|
|
3562
|
+
const used = usedKb * 1024;
|
|
3563
|
+
return { used, total };
|
|
3564
|
+
} catch {
|
|
3565
|
+
return { used: 0, total: 0 };
|
|
3566
|
+
}
|
|
3567
|
+
}
|
|
3568
|
+
function formatUptime(seconds) {
|
|
3569
|
+
const d = Math.floor(seconds / 86400);
|
|
3570
|
+
const h = Math.floor(seconds % 86400 / 3600);
|
|
3571
|
+
const m = Math.floor(seconds % 3600 / 60);
|
|
3572
|
+
const parts = [];
|
|
3573
|
+
if (d > 0) parts.push(`${d}d`);
|
|
3574
|
+
if (h > 0) parts.push(`${h}h`);
|
|
3575
|
+
parts.push(`${m}m`);
|
|
3576
|
+
return parts.join(" ");
|
|
3577
|
+
}
|
|
3578
|
+
function formatBytesCompact(bytes) {
|
|
3579
|
+
const units = ["B", "KB", "MB", "GB", "TB"];
|
|
3580
|
+
let value = Math.max(0, bytes);
|
|
3581
|
+
let unitIndex = 0;
|
|
3582
|
+
while (value >= 1024 && unitIndex < units.length - 1) {
|
|
3583
|
+
value /= 1024;
|
|
3584
|
+
unitIndex += 1;
|
|
3585
|
+
}
|
|
3586
|
+
const digits = value >= 100 ? 0 : value >= 10 ? 1 : 2;
|
|
3587
|
+
return `${value.toFixed(digits)} ${units[unitIndex]}`;
|
|
3588
|
+
}
|
|
3589
|
+
function getNetworkIo() {
|
|
3590
|
+
try {
|
|
3591
|
+
const netRaw = execSync("cat /proc/net/dev", {
|
|
3592
|
+
encoding: "utf8",
|
|
3593
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
3594
|
+
timeout: 3e3
|
|
3595
|
+
});
|
|
3596
|
+
const lines = netRaw.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
3597
|
+
let selected = null;
|
|
3598
|
+
for (const line of lines.slice(2)) {
|
|
3599
|
+
const [ifaceRaw, dataRaw] = line.split(":");
|
|
3600
|
+
if (!ifaceRaw || !dataRaw) continue;
|
|
3601
|
+
const iface = ifaceRaw.trim();
|
|
3602
|
+
const fields = dataRaw.trim().split(/\s+/);
|
|
3603
|
+
if (fields.length < 16) continue;
|
|
3604
|
+
const rx = Number(fields[0]);
|
|
3605
|
+
const tx = Number(fields[8]);
|
|
3606
|
+
if (!Number.isFinite(rx) || !Number.isFinite(tx)) continue;
|
|
3607
|
+
const entry = { iface, rx, tx };
|
|
3608
|
+
if (iface !== "lo") {
|
|
3609
|
+
selected = entry;
|
|
3610
|
+
break;
|
|
3611
|
+
}
|
|
3612
|
+
if (!selected) selected = entry;
|
|
3613
|
+
}
|
|
3614
|
+
if (!selected) return { rx: "0 MB", tx: "0 MB" };
|
|
3615
|
+
return {
|
|
3616
|
+
rx: formatBytesCompact(selected.rx),
|
|
3617
|
+
tx: formatBytesCompact(selected.tx)
|
|
3618
|
+
};
|
|
3619
|
+
} catch {
|
|
3620
|
+
return { rx: "0 MB", tx: "0 MB" };
|
|
3621
|
+
}
|
|
3622
|
+
}
|
|
3623
|
+
function getTopProcesses() {
|
|
3624
|
+
try {
|
|
3625
|
+
const procs = execSync("ps aux --sort=-%cpu | head -6 | tail -5", {
|
|
3626
|
+
encoding: "utf8",
|
|
3627
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
3628
|
+
timeout: 3e3
|
|
3629
|
+
});
|
|
3630
|
+
return procs.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => {
|
|
3631
|
+
const parts = line.split(/\s+/);
|
|
3632
|
+
if (parts.length < 11) return null;
|
|
3633
|
+
const cpu = Number(parts[2]);
|
|
3634
|
+
const mem = Number(parts[3]);
|
|
3635
|
+
const command = parts.slice(10).join(" ");
|
|
3636
|
+
const name = command.split("/").pop()?.split(" ")[0] || command;
|
|
3637
|
+
if (!Number.isFinite(cpu) || !Number.isFinite(mem)) return null;
|
|
3638
|
+
return {
|
|
3639
|
+
name: name.slice(0, 30),
|
|
3640
|
+
cpu,
|
|
3641
|
+
mem
|
|
3642
|
+
};
|
|
3643
|
+
}).filter(
|
|
3644
|
+
(p) => p !== null
|
|
3645
|
+
);
|
|
3646
|
+
} catch {
|
|
3647
|
+
return [];
|
|
3648
|
+
}
|
|
3649
|
+
}
|
|
3650
|
+
async function getSystemStats() {
|
|
3651
|
+
const totalRam = os.totalmem();
|
|
3652
|
+
const freeRam = os.freemem();
|
|
3653
|
+
const usedRam = Math.max(0, totalRam - freeRam);
|
|
3654
|
+
const [cpuUsage, disk] = await Promise.all([
|
|
3655
|
+
getCpuUsagePercent(500),
|
|
3656
|
+
Promise.resolve(getDiskStats())
|
|
3657
|
+
]);
|
|
3658
|
+
const cpus = os.cpus();
|
|
3659
|
+
const cpuModel = cpus[0]?.model ?? "Unknown CPU";
|
|
3660
|
+
const cores = cpus.length;
|
|
3661
|
+
return {
|
|
3662
|
+
cpu: cpuUsage,
|
|
3663
|
+
ram: { used: usedRam, total: totalRam },
|
|
3664
|
+
disk,
|
|
3665
|
+
load: os.loadavg().map((v) => Number(v.toFixed(2))),
|
|
3666
|
+
uptime: formatUptime(os.uptime()),
|
|
3667
|
+
network: getNetworkIo(),
|
|
3668
|
+
topProcesses: getTopProcesses(),
|
|
3669
|
+
cpuModel,
|
|
3670
|
+
cores
|
|
3671
|
+
};
|
|
3672
|
+
}
|
|
3673
|
+
async function getGatewayStats() {
|
|
3674
|
+
try {
|
|
3675
|
+
const sessionsJson = execSync("openclaw sessions list --json 2>/dev/null", {
|
|
3676
|
+
encoding: "utf8",
|
|
3677
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
3678
|
+
timeout: 5e3
|
|
3679
|
+
});
|
|
3680
|
+
const sessionsData = JSON.parse(sessionsJson);
|
|
3681
|
+
const activeSessions = sessionsData.count ?? sessionsData.sessions?.length ?? 0;
|
|
3682
|
+
return { activeSessions, tokensToday: 0, costToday: 0 };
|
|
3683
|
+
} catch {
|
|
3684
|
+
return { activeSessions: 0, tokensToday: 0, costToday: 0 };
|
|
3685
|
+
}
|
|
3686
|
+
}
|
|
3687
|
+
async function getCronOverview() {
|
|
3688
|
+
try {
|
|
3689
|
+
const cronJson = execSync("openclaw cron list --json 2>/dev/null", {
|
|
3690
|
+
encoding: "utf8",
|
|
3691
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
3692
|
+
timeout: 5e3
|
|
3693
|
+
});
|
|
3694
|
+
const data = JSON.parse(cronJson);
|
|
3695
|
+
const jobs = data.jobs ?? [];
|
|
3696
|
+
return jobs.map((job) => {
|
|
3697
|
+
const schedule = job.schedule;
|
|
3698
|
+
const state = job.state;
|
|
3699
|
+
let scheduleStr = "—";
|
|
3700
|
+
if (schedule) {
|
|
3701
|
+
if (schedule.expr) scheduleStr = String(schedule.expr);
|
|
3702
|
+
else if (schedule.kind === "every" && schedule.everyMs)
|
|
3703
|
+
scheduleStr = `every ${Number(schedule.everyMs) / 1e3 / 60}m`;
|
|
3704
|
+
else if (schedule.kind === "at") scheduleStr = `at ${schedule.at}`;
|
|
3705
|
+
else if (schedule.kind) scheduleStr = String(schedule.kind);
|
|
3706
|
+
}
|
|
3707
|
+
let nextRun = null;
|
|
3708
|
+
if (state?.nextRunAtMs && Number(state.nextRunAtMs) > 0) {
|
|
3709
|
+
nextRun = new Date(Number(state.nextRunAtMs)).toISOString();
|
|
3710
|
+
}
|
|
3711
|
+
let lastRun = null;
|
|
3712
|
+
if (state?.lastRunAtMs && Number(state.lastRunAtMs) > 0) {
|
|
3713
|
+
lastRun = new Date(Number(state.lastRunAtMs)).toISOString();
|
|
3714
|
+
}
|
|
3715
|
+
const rawStatus = state?.lastStatus;
|
|
3716
|
+
const lastStatus = rawStatus === "ok" ? "ok" : rawStatus === "error" ? "error" : rawStatus === "idle" ? "idle" : "unknown";
|
|
3717
|
+
return {
|
|
3718
|
+
id: String(job.id ?? ""),
|
|
3719
|
+
name: String(job.name ?? job.id ?? "Unnamed"),
|
|
3720
|
+
schedule: scheduleStr,
|
|
3721
|
+
enabled: Boolean(job.enabled ?? true),
|
|
3722
|
+
nextRun,
|
|
3723
|
+
lastRun,
|
|
3724
|
+
lastStatus
|
|
3725
|
+
};
|
|
3726
|
+
});
|
|
3727
|
+
} catch {
|
|
3728
|
+
return [];
|
|
3729
|
+
}
|
|
3730
|
+
}
|
|
3731
|
+
const Route$2 = createFileRoute("/api/dashboard/system")({
|
|
3732
|
+
server: {
|
|
3733
|
+
handlers: {
|
|
3734
|
+
GET: async () => {
|
|
3735
|
+
try {
|
|
3736
|
+
const data = await getSystemStats();
|
|
3737
|
+
return json(data);
|
|
3738
|
+
} catch (err) {
|
|
3739
|
+
return json(
|
|
3740
|
+
{ error: err instanceof Error ? err.message : String(err) },
|
|
3741
|
+
{ status: 500 }
|
|
3742
|
+
);
|
|
3743
|
+
}
|
|
3744
|
+
}
|
|
3745
|
+
}
|
|
3746
|
+
}
|
|
3747
|
+
});
|
|
3748
|
+
const Route$1 = createFileRoute("/api/dashboard/gateway")({
|
|
3749
|
+
server: {
|
|
3750
|
+
handlers: {
|
|
3751
|
+
GET: async () => {
|
|
3752
|
+
try {
|
|
3753
|
+
const data = await getGatewayStats();
|
|
3754
|
+
return json(data);
|
|
3755
|
+
} catch (err) {
|
|
3756
|
+
return json(
|
|
3757
|
+
{ error: err instanceof Error ? err.message : String(err) },
|
|
3758
|
+
{ status: 500 }
|
|
3759
|
+
);
|
|
3760
|
+
}
|
|
3761
|
+
}
|
|
3762
|
+
}
|
|
3763
|
+
}
|
|
3764
|
+
});
|
|
3765
|
+
const Route = createFileRoute("/api/dashboard/crons")({
|
|
3766
|
+
server: {
|
|
3767
|
+
handlers: {
|
|
3768
|
+
GET: async () => {
|
|
3769
|
+
try {
|
|
3770
|
+
const data = await getCronOverview();
|
|
3771
|
+
return json({ jobs: data });
|
|
3772
|
+
} catch (err) {
|
|
3773
|
+
return json(
|
|
3774
|
+
{ error: err instanceof Error ? err.message : String(err) },
|
|
3775
|
+
{ status: 500 }
|
|
3776
|
+
);
|
|
3777
|
+
}
|
|
3778
|
+
}
|
|
3779
|
+
}
|
|
3780
|
+
}
|
|
3781
|
+
});
|
|
3782
|
+
const SkillsRoute = Route$A.update({
|
|
3310
3783
|
id: "/skills",
|
|
3311
3784
|
path: "/skills",
|
|
3312
|
-
getParentRoute: () => Route$
|
|
3785
|
+
getParentRoute: () => Route$B
|
|
3313
3786
|
});
|
|
3314
|
-
const NewRoute = Route$
|
|
3787
|
+
const NewRoute = Route$z.update({
|
|
3315
3788
|
id: "/new",
|
|
3316
3789
|
path: "/new",
|
|
3317
|
-
getParentRoute: () => Route$
|
|
3790
|
+
getParentRoute: () => Route$B
|
|
3318
3791
|
});
|
|
3319
|
-
const MemoryRoute = Route$
|
|
3792
|
+
const MemoryRoute = Route$y.update({
|
|
3320
3793
|
id: "/memory",
|
|
3321
3794
|
path: "/memory",
|
|
3322
|
-
getParentRoute: () => Route$
|
|
3795
|
+
getParentRoute: () => Route$B
|
|
3323
3796
|
});
|
|
3324
|
-
const FilesRoute = Route$
|
|
3797
|
+
const FilesRoute = Route$x.update({
|
|
3325
3798
|
id: "/files",
|
|
3326
3799
|
path: "/files",
|
|
3327
|
-
getParentRoute: () => Route$
|
|
3800
|
+
getParentRoute: () => Route$B
|
|
3801
|
+
});
|
|
3802
|
+
const DashboardRoute = Route$w.update({
|
|
3803
|
+
id: "/dashboard",
|
|
3804
|
+
path: "/dashboard",
|
|
3805
|
+
getParentRoute: () => Route$B
|
|
3328
3806
|
});
|
|
3329
|
-
const ConnectRoute = Route$
|
|
3807
|
+
const ConnectRoute = Route$v.update({
|
|
3330
3808
|
id: "/connect",
|
|
3331
3809
|
path: "/connect",
|
|
3332
|
-
getParentRoute: () => Route$
|
|
3810
|
+
getParentRoute: () => Route$B
|
|
3333
3811
|
});
|
|
3334
|
-
const BotsRoute = Route$
|
|
3812
|
+
const BotsRoute = Route$u.update({
|
|
3335
3813
|
id: "/bots",
|
|
3336
3814
|
path: "/bots",
|
|
3337
|
-
getParentRoute: () => Route$
|
|
3815
|
+
getParentRoute: () => Route$B
|
|
3338
3816
|
});
|
|
3339
|
-
const AgentsRoute = Route$
|
|
3817
|
+
const AgentsRoute = Route$t.update({
|
|
3340
3818
|
id: "/agents",
|
|
3341
3819
|
path: "/agents",
|
|
3342
|
-
getParentRoute: () => Route$
|
|
3820
|
+
getParentRoute: () => Route$B
|
|
3343
3821
|
});
|
|
3344
|
-
const IndexRoute = Route$
|
|
3822
|
+
const IndexRoute = Route$s.update({
|
|
3345
3823
|
id: "/",
|
|
3346
3824
|
path: "/",
|
|
3347
|
-
getParentRoute: () => Route$
|
|
3825
|
+
getParentRoute: () => Route$B
|
|
3348
3826
|
});
|
|
3349
|
-
const ChatSessionKeyRoute = Route$
|
|
3827
|
+
const ChatSessionKeyRoute = Route$r.update({
|
|
3350
3828
|
id: "/chat/$sessionKey",
|
|
3351
3829
|
path: "/chat/$sessionKey",
|
|
3352
|
-
getParentRoute: () => Route$
|
|
3830
|
+
getParentRoute: () => Route$B
|
|
3353
3831
|
});
|
|
3354
|
-
const ApiTtsRoute = Route$
|
|
3832
|
+
const ApiTtsRoute = Route$q.update({
|
|
3355
3833
|
id: "/api/tts",
|
|
3356
3834
|
path: "/api/tts",
|
|
3357
|
-
getParentRoute: () => Route$
|
|
3835
|
+
getParentRoute: () => Route$B
|
|
3358
3836
|
});
|
|
3359
|
-
const ApiSttRoute = Route$
|
|
3837
|
+
const ApiSttRoute = Route$p.update({
|
|
3360
3838
|
id: "/api/stt",
|
|
3361
3839
|
path: "/api/stt",
|
|
3362
|
-
getParentRoute: () => Route$
|
|
3840
|
+
getParentRoute: () => Route$B
|
|
3363
3841
|
});
|
|
3364
|
-
const ApiStreamRoute = Route$
|
|
3842
|
+
const ApiStreamRoute = Route$o.update({
|
|
3365
3843
|
id: "/api/stream",
|
|
3366
3844
|
path: "/api/stream",
|
|
3367
|
-
getParentRoute: () => Route$
|
|
3845
|
+
getParentRoute: () => Route$B
|
|
3368
3846
|
});
|
|
3369
|
-
const ApiSkillsRoute = Route$
|
|
3847
|
+
const ApiSkillsRoute = Route$n.update({
|
|
3370
3848
|
id: "/api/skills",
|
|
3371
3849
|
path: "/api/skills",
|
|
3372
|
-
getParentRoute: () => Route$
|
|
3850
|
+
getParentRoute: () => Route$B
|
|
3373
3851
|
});
|
|
3374
|
-
const ApiSessionsRoute = Route$
|
|
3852
|
+
const ApiSessionsRoute = Route$m.update({
|
|
3375
3853
|
id: "/api/sessions",
|
|
3376
3854
|
path: "/api/sessions",
|
|
3377
|
-
getParentRoute: () => Route$
|
|
3855
|
+
getParentRoute: () => Route$B
|
|
3378
3856
|
});
|
|
3379
|
-
const ApiSendRoute = Route$
|
|
3857
|
+
const ApiSendRoute = Route$l.update({
|
|
3380
3858
|
id: "/api/send",
|
|
3381
3859
|
path: "/api/send",
|
|
3382
|
-
getParentRoute: () => Route$
|
|
3860
|
+
getParentRoute: () => Route$B
|
|
3383
3861
|
});
|
|
3384
|
-
const ApiPingRoute = Route$
|
|
3862
|
+
const ApiPingRoute = Route$k.update({
|
|
3385
3863
|
id: "/api/ping",
|
|
3386
3864
|
path: "/api/ping",
|
|
3387
|
-
getParentRoute: () => Route$
|
|
3865
|
+
getParentRoute: () => Route$B
|
|
3388
3866
|
});
|
|
3389
|
-
const ApiPersonasRoute = Route$
|
|
3867
|
+
const ApiPersonasRoute = Route$j.update({
|
|
3390
3868
|
id: "/api/personas",
|
|
3391
3869
|
path: "/api/personas",
|
|
3392
|
-
getParentRoute: () => Route$
|
|
3870
|
+
getParentRoute: () => Route$B
|
|
3393
3871
|
});
|
|
3394
|
-
const ApiPathsRoute = Route$
|
|
3872
|
+
const ApiPathsRoute = Route$i.update({
|
|
3395
3873
|
id: "/api/paths",
|
|
3396
3874
|
path: "/api/paths",
|
|
3397
|
-
getParentRoute: () => Route$
|
|
3875
|
+
getParentRoute: () => Route$B
|
|
3398
3876
|
});
|
|
3399
|
-
const ApiModelsRoute = Route$
|
|
3877
|
+
const ApiModelsRoute = Route$h.update({
|
|
3400
3878
|
id: "/api/models",
|
|
3401
3879
|
path: "/api/models",
|
|
3402
|
-
getParentRoute: () => Route$
|
|
3880
|
+
getParentRoute: () => Route$B
|
|
3403
3881
|
});
|
|
3404
|
-
const ApiLlmFeaturesRoute = Route$
|
|
3882
|
+
const ApiLlmFeaturesRoute = Route$g.update({
|
|
3405
3883
|
id: "/api/llm-features",
|
|
3406
3884
|
path: "/api/llm-features",
|
|
3407
|
-
getParentRoute: () => Route$
|
|
3885
|
+
getParentRoute: () => Route$B
|
|
3408
3886
|
});
|
|
3409
|
-
const ApiHistoryRoute = Route$
|
|
3887
|
+
const ApiHistoryRoute = Route$f.update({
|
|
3410
3888
|
id: "/api/history",
|
|
3411
3889
|
path: "/api/history",
|
|
3412
|
-
getParentRoute: () => Route$
|
|
3890
|
+
getParentRoute: () => Route$B
|
|
3413
3891
|
});
|
|
3414
|
-
const ApiFollowUpsRoute = Route$
|
|
3892
|
+
const ApiFollowUpsRoute = Route$e.update({
|
|
3415
3893
|
id: "/api/follow-ups",
|
|
3416
3894
|
path: "/api/follow-ups",
|
|
3417
|
-
getParentRoute: () => Route$
|
|
3895
|
+
getParentRoute: () => Route$B
|
|
3418
3896
|
});
|
|
3419
|
-
const ApiCronRoute = Route$
|
|
3897
|
+
const ApiCronRoute = Route$d.update({
|
|
3420
3898
|
id: "/api/cron",
|
|
3421
3899
|
path: "/api/cron",
|
|
3422
|
-
getParentRoute: () => Route$
|
|
3900
|
+
getParentRoute: () => Route$B
|
|
3423
3901
|
});
|
|
3424
|
-
const ApiAgentsRoute = Route$
|
|
3902
|
+
const ApiAgentsRoute = Route$c.update({
|
|
3425
3903
|
id: "/api/agents",
|
|
3426
3904
|
path: "/api/agents",
|
|
3427
|
-
getParentRoute: () => Route$
|
|
3905
|
+
getParentRoute: () => Route$B
|
|
3428
3906
|
});
|
|
3429
|
-
const ApiFilesUploadRoute = Route$
|
|
3907
|
+
const ApiFilesUploadRoute = Route$b.update({
|
|
3430
3908
|
id: "/api/files/upload",
|
|
3431
3909
|
path: "/api/files/upload",
|
|
3432
|
-
getParentRoute: () => Route$
|
|
3910
|
+
getParentRoute: () => Route$B
|
|
3433
3911
|
});
|
|
3434
|
-
const ApiFilesSaveRoute = Route$
|
|
3912
|
+
const ApiFilesSaveRoute = Route$a.update({
|
|
3435
3913
|
id: "/api/files/save",
|
|
3436
3914
|
path: "/api/files/save",
|
|
3437
|
-
getParentRoute: () => Route$
|
|
3915
|
+
getParentRoute: () => Route$B
|
|
3438
3916
|
});
|
|
3439
|
-
const ApiFilesRenameRoute = Route$
|
|
3917
|
+
const ApiFilesRenameRoute = Route$9.update({
|
|
3440
3918
|
id: "/api/files/rename",
|
|
3441
3919
|
path: "/api/files/rename",
|
|
3442
|
-
getParentRoute: () => Route$
|
|
3920
|
+
getParentRoute: () => Route$B
|
|
3443
3921
|
});
|
|
3444
|
-
const ApiFilesReadRoute = Route$
|
|
3922
|
+
const ApiFilesReadRoute = Route$8.update({
|
|
3445
3923
|
id: "/api/files/read",
|
|
3446
3924
|
path: "/api/files/read",
|
|
3447
|
-
getParentRoute: () => Route$
|
|
3925
|
+
getParentRoute: () => Route$B
|
|
3448
3926
|
});
|
|
3449
|
-
const ApiFilesMkdirRoute = Route$
|
|
3927
|
+
const ApiFilesMkdirRoute = Route$7.update({
|
|
3450
3928
|
id: "/api/files/mkdir",
|
|
3451
3929
|
path: "/api/files/mkdir",
|
|
3452
|
-
getParentRoute: () => Route$
|
|
3930
|
+
getParentRoute: () => Route$B
|
|
3453
3931
|
});
|
|
3454
|
-
const ApiFilesListRoute = Route$
|
|
3932
|
+
const ApiFilesListRoute = Route$6.update({
|
|
3455
3933
|
id: "/api/files/list",
|
|
3456
3934
|
path: "/api/files/list",
|
|
3457
|
-
getParentRoute: () => Route$
|
|
3935
|
+
getParentRoute: () => Route$B
|
|
3458
3936
|
});
|
|
3459
|
-
const ApiFilesInfoRoute = Route$
|
|
3937
|
+
const ApiFilesInfoRoute = Route$5.update({
|
|
3460
3938
|
id: "/api/files/info",
|
|
3461
3939
|
path: "/api/files/info",
|
|
3462
|
-
getParentRoute: () => Route$
|
|
3940
|
+
getParentRoute: () => Route$B
|
|
3463
3941
|
});
|
|
3464
|
-
const ApiFilesDownloadRoute = Route$
|
|
3942
|
+
const ApiFilesDownloadRoute = Route$4.update({
|
|
3465
3943
|
id: "/api/files/download",
|
|
3466
3944
|
path: "/api/files/download",
|
|
3467
|
-
getParentRoute: () => Route$
|
|
3945
|
+
getParentRoute: () => Route$B
|
|
3468
3946
|
});
|
|
3469
|
-
const ApiFilesDeleteRoute = Route.update({
|
|
3947
|
+
const ApiFilesDeleteRoute = Route$3.update({
|
|
3470
3948
|
id: "/api/files/delete",
|
|
3471
3949
|
path: "/api/files/delete",
|
|
3472
|
-
getParentRoute: () => Route$
|
|
3950
|
+
getParentRoute: () => Route$B
|
|
3951
|
+
});
|
|
3952
|
+
const ApiDashboardSystemRoute = Route$2.update({
|
|
3953
|
+
id: "/api/dashboard/system",
|
|
3954
|
+
path: "/api/dashboard/system",
|
|
3955
|
+
getParentRoute: () => Route$B
|
|
3956
|
+
});
|
|
3957
|
+
const ApiDashboardGatewayRoute = Route$1.update({
|
|
3958
|
+
id: "/api/dashboard/gateway",
|
|
3959
|
+
path: "/api/dashboard/gateway",
|
|
3960
|
+
getParentRoute: () => Route$B
|
|
3961
|
+
});
|
|
3962
|
+
const ApiDashboardCronsRoute = Route.update({
|
|
3963
|
+
id: "/api/dashboard/crons",
|
|
3964
|
+
path: "/api/dashboard/crons",
|
|
3965
|
+
getParentRoute: () => Route$B
|
|
3473
3966
|
});
|
|
3474
3967
|
const rootRouteChildren = {
|
|
3475
3968
|
IndexRoute,
|
|
3476
3969
|
AgentsRoute,
|
|
3477
3970
|
BotsRoute,
|
|
3478
3971
|
ConnectRoute,
|
|
3972
|
+
DashboardRoute,
|
|
3479
3973
|
FilesRoute,
|
|
3480
3974
|
MemoryRoute,
|
|
3481
3975
|
NewRoute,
|
|
@@ -3496,6 +3990,9 @@ const rootRouteChildren = {
|
|
|
3496
3990
|
ApiSttRoute,
|
|
3497
3991
|
ApiTtsRoute,
|
|
3498
3992
|
ChatSessionKeyRoute,
|
|
3993
|
+
ApiDashboardCronsRoute,
|
|
3994
|
+
ApiDashboardGatewayRoute,
|
|
3995
|
+
ApiDashboardSystemRoute,
|
|
3499
3996
|
ApiFilesDeleteRoute,
|
|
3500
3997
|
ApiFilesDownloadRoute,
|
|
3501
3998
|
ApiFilesInfoRoute,
|
|
@@ -3506,7 +4003,7 @@ const rootRouteChildren = {
|
|
|
3506
4003
|
ApiFilesSaveRoute,
|
|
3507
4004
|
ApiFilesUploadRoute
|
|
3508
4005
|
};
|
|
3509
|
-
const routeTree = Route$
|
|
4006
|
+
const routeTree = Route$B._addFileChildren(rootRouteChildren)._addFileTypes();
|
|
3510
4007
|
const getRouter = () => {
|
|
3511
4008
|
const router2 = createRouter({
|
|
3512
4009
|
routeTree,
|
|
@@ -3521,7 +4018,7 @@ const router = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
|
|
|
3521
4018
|
getRouter
|
|
3522
4019
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
3523
4020
|
export {
|
|
3524
|
-
Route$
|
|
3525
|
-
Route$
|
|
4021
|
+
Route$s as R,
|
|
4022
|
+
Route$r as a,
|
|
3526
4023
|
router as r
|
|
3527
4024
|
};
|