volute 0.24.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.d.ts +113 -4
- package/dist/{chunk-4TJ72QQ3.js → chunk-BOTQ25QT.js} +1 -1
- package/dist/{chunk-P3W36ZGD.js → chunk-DG7TO7EE.js} +30 -2
- package/dist/{chunk-OOW675I3.js → chunk-PMX4EIJK.js} +39 -20
- package/dist/{chunk-NOBRGACV.js → chunk-SHSWYG2J.js} +1 -1
- package/dist/{chunk-XLC342FO.js → chunk-SIAG3QMM.js} +14 -1
- package/dist/cli.js +6 -6
- package/dist/{cloud-sync-DIU3OCPV.js → cloud-sync-PPBBJDY6.js} +3 -3
- package/dist/{daemon-restart-YMPEATQH.js → daemon-restart-FDNOZEAD.js} +1 -1
- package/dist/daemon.js +453 -239
- package/dist/{import-FRDPQPJ2.js → import-TH26J76F.js} +2 -2
- package/dist/{message-delivery-S7BCNV6Y.js → message-delivery-XMGV3FUM.js} +3 -3
- package/dist/{mind-KPLCRKQA.js → mind-YVWAHL2A.js} +2 -2
- package/dist/{mind-manager-ZNRIYEK3.js → mind-manager-4NDNAYAB.js} +1 -1
- package/dist/{package-S5YF25XV.js → package-3HF5MXU2.js} +2 -1
- package/dist/{pages-TWR6U7DS.js → pages-Y6DRWUOJ.js} +1 -1
- package/dist/{publish-BZNHKUUK.js → publish-EEKTZBHW.js} +1 -1
- package/dist/{skill-BQOFACEI.js → skill-T3EMR6IR.js} +10 -2
- package/dist/skills/imagegen/SKILL.md +37 -0
- package/dist/skills/imagegen/references/INSTALL.md +13 -0
- package/dist/skills/imagegen/scripts/imagegen.ts +136 -0
- package/dist/skills/resonance/SKILL.md +73 -0
- package/dist/skills/resonance/assets/default-config.json +21 -0
- package/dist/skills/resonance/references/INSTALL.md +23 -0
- package/dist/skills/resonance/scripts/resonance.ts +1250 -0
- package/dist/skills/volute-mind/SKILL.md +23 -3
- package/dist/{sleep-manager-XXSWQQLE.js → sleep-manager-RKTFZPD3.js} +3 -3
- package/dist/{sprout-CGSW4CF5.js → sprout-QJVGJDSH.js} +1 -1
- package/dist/{up-OMHACRJL.js → up-CJ26KQLN.js} +1 -1
- package/dist/{version-notify-SZ75QRGO.js → version-notify-AZQMC32A.js} +3 -3
- package/dist/web-assets/assets/index-CGPSVu19.js +69 -0
- package/dist/web-assets/assets/index-V_rNDsM8.css +1 -0
- package/dist/web-assets/favicon.png +0 -0
- package/dist/web-assets/index.html +5 -4
- package/dist/web-assets/logo.png +0 -0
- package/package.json +2 -1
- package/templates/_base/home/public/.gitkeep +0 -0
- package/dist/web-assets/assets/index-Bx9WDoaQ.js +0 -69
- package/dist/web-assets/assets/index-Clz8OhmJ.css +0 -1
- /package/dist/{chunk-TQDITGES.js → chunk-ZSH4G2P5.js} +0 -0
package/dist/daemon.js
CHANGED
|
@@ -78,9 +78,11 @@ import {
|
|
|
78
78
|
subscribe2 as subscribe3,
|
|
79
79
|
updateUserProfile,
|
|
80
80
|
verifyUser
|
|
81
|
-
} from "./chunk-
|
|
81
|
+
} from "./chunk-PMX4EIJK.js";
|
|
82
82
|
import {
|
|
83
|
-
|
|
83
|
+
deleteSystemsConfig,
|
|
84
|
+
readSystemsConfig,
|
|
85
|
+
writeSystemsConfig
|
|
84
86
|
} from "./chunk-HFCBO2GL.js";
|
|
85
87
|
import {
|
|
86
88
|
getActiveMinds,
|
|
@@ -101,17 +103,17 @@ import {
|
|
|
101
103
|
getPromptIfCustom,
|
|
102
104
|
initMindManager,
|
|
103
105
|
substitute
|
|
104
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-SHSWYG2J.js";
|
|
105
107
|
import {
|
|
106
108
|
findOpenClawSession,
|
|
107
109
|
importOpenClawConnectors,
|
|
108
110
|
importPiSession,
|
|
109
111
|
parseNameFromIdentity
|
|
110
|
-
} from "./chunk-
|
|
112
|
+
} from "./chunk-BOTQ25QT.js";
|
|
111
113
|
import {
|
|
112
114
|
readVoluteConfig,
|
|
113
115
|
writeVoluteConfig
|
|
114
|
-
} from "./chunk-
|
|
116
|
+
} from "./chunk-SIAG3QMM.js";
|
|
115
117
|
import {
|
|
116
118
|
loadMergedEnv,
|
|
117
119
|
mindEnvPath,
|
|
@@ -137,7 +139,7 @@ import {
|
|
|
137
139
|
syncBuiltinSkills,
|
|
138
140
|
uninstallSkill,
|
|
139
141
|
updateSkill
|
|
140
|
-
} from "./chunk-
|
|
142
|
+
} from "./chunk-DG7TO7EE.js";
|
|
141
143
|
import {
|
|
142
144
|
activity,
|
|
143
145
|
conversations,
|
|
@@ -210,7 +212,7 @@ import {
|
|
|
210
212
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
211
213
|
import { mkdirSync as mkdirSync9, readFileSync as readFileSync11, unlinkSync, writeFileSync as writeFileSync9 } from "fs";
|
|
212
214
|
import { homedir as homedir2 } from "os";
|
|
213
|
-
import { resolve as
|
|
215
|
+
import { resolve as resolve19 } from "path";
|
|
214
216
|
import { format } from "util";
|
|
215
217
|
|
|
216
218
|
// src/lib/migrate-agents-to-minds.ts
|
|
@@ -360,6 +362,17 @@ function migrateDotVoluteDir(name) {
|
|
|
360
362
|
console.warn(`[migrate] both .volute/ and .mind/ exist for ${name}, skipping rename`);
|
|
361
363
|
}
|
|
362
364
|
}
|
|
365
|
+
function migratePagesDirToPublic(name) {
|
|
366
|
+
const dir = mindDir(name);
|
|
367
|
+
const oldPagesDir = resolve2(dir, "home", "pages");
|
|
368
|
+
const newPublicDir = resolve2(dir, "home", "public");
|
|
369
|
+
const newPagesDir = resolve2(newPublicDir, "pages");
|
|
370
|
+
if (existsSync2(oldPagesDir) && !existsSync2(newPagesDir)) {
|
|
371
|
+
mkdirSync(newPublicDir, { recursive: true });
|
|
372
|
+
renameSync2(oldPagesDir, newPagesDir);
|
|
373
|
+
logger_default.info(`migrated pages/ \u2192 public/pages/ for ${name}`);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
363
376
|
function migrateMindState(name) {
|
|
364
377
|
const src = resolve2(mindDir(name), ".mind");
|
|
365
378
|
if (!existsSync2(src)) return;
|
|
@@ -396,7 +409,7 @@ function isValidDaemonToken(token) {
|
|
|
396
409
|
if (!expected || token.length !== expected.length) return false;
|
|
397
410
|
return timingSafeEqual(Buffer.from(token), Buffer.from(expected));
|
|
398
411
|
}
|
|
399
|
-
var SESSION_MAX_AGE =
|
|
412
|
+
var SESSION_MAX_AGE = 365 * 24 * 60 * 60 * 1e3;
|
|
400
413
|
var SESSION_CACHE_TTL = 5 * 60 * 1e3;
|
|
401
414
|
var sessionCache = /* @__PURE__ */ new Map();
|
|
402
415
|
function invalidateSessionCache(sessionId) {
|
|
@@ -480,13 +493,13 @@ var authMiddleware = createMiddleware(async (c, next) => {
|
|
|
480
493
|
|
|
481
494
|
// src/web/server.ts
|
|
482
495
|
import { existsSync as existsSync13 } from "fs";
|
|
483
|
-
import { readFile as
|
|
496
|
+
import { readFile as readFile4, stat as stat4 } from "fs/promises";
|
|
484
497
|
import { createServer as createHttpsServer } from "https";
|
|
485
|
-
import { dirname, extname as
|
|
498
|
+
import { dirname, extname as extname5, resolve as resolve18 } from "path";
|
|
486
499
|
import { serve } from "@hono/node-server";
|
|
487
500
|
|
|
488
501
|
// src/web/app.ts
|
|
489
|
-
import { Hono as
|
|
502
|
+
import { Hono as Hono29 } from "hono";
|
|
490
503
|
import { bodyLimit } from "hono/body-limit";
|
|
491
504
|
import { csrf } from "hono/csrf";
|
|
492
505
|
import { HTTPException } from "hono/http-exception";
|
|
@@ -553,8 +566,8 @@ var app = new Hono().get("/events", async (c) => {
|
|
|
553
566
|
});
|
|
554
567
|
}, 15e3);
|
|
555
568
|
cleanups.push(() => clearInterval(keepAlive));
|
|
556
|
-
await new Promise((
|
|
557
|
-
stream.onAbort(() =>
|
|
569
|
+
await new Promise((resolve20) => {
|
|
570
|
+
stream.onAbort(() => resolve20());
|
|
558
571
|
});
|
|
559
572
|
} finally {
|
|
560
573
|
for (const cleanup of cleanups) {
|
|
@@ -575,6 +588,12 @@ import { zValidator } from "@hono/zod-validator";
|
|
|
575
588
|
import { Hono as Hono2 } from "hono";
|
|
576
589
|
import { deleteCookie, getCookie as getCookie2, setCookie } from "hono/cookie";
|
|
577
590
|
import { z } from "zod";
|
|
591
|
+
var SESSION_COOKIE_OPTIONS = {
|
|
592
|
+
path: "/",
|
|
593
|
+
httpOnly: true,
|
|
594
|
+
sameSite: "Lax",
|
|
595
|
+
maxAge: Math.floor(SESSION_MAX_AGE / 1e3)
|
|
596
|
+
};
|
|
578
597
|
var credentialsSchema = z.object({
|
|
579
598
|
username: z.string().min(1),
|
|
580
599
|
password: z.string().min(1)
|
|
@@ -610,6 +629,11 @@ var authenticated = new Hono2().use(authMiddleware).post("/change-password", zVa
|
|
|
610
629
|
await updateUserProfile(user.id, body);
|
|
611
630
|
const sessionId = getCookie2(c, "volute_session");
|
|
612
631
|
if (sessionId) invalidateSessionCache(sessionId);
|
|
632
|
+
broadcast({
|
|
633
|
+
type: "profile_updated",
|
|
634
|
+
mind: user.username,
|
|
635
|
+
summary: `${user.username} profile updated`
|
|
636
|
+
});
|
|
613
637
|
return c.json({ ok: true });
|
|
614
638
|
}).post("/avatar", async (c) => {
|
|
615
639
|
const user = c.get("user");
|
|
@@ -637,6 +661,11 @@ var authenticated = new Hono2().use(authMiddleware).post("/change-password", zVa
|
|
|
637
661
|
await updateUserProfile(user.id, { avatar: filename });
|
|
638
662
|
const sessionId = getCookie2(c, "volute_session");
|
|
639
663
|
if (sessionId) invalidateSessionCache(sessionId);
|
|
664
|
+
broadcast({
|
|
665
|
+
type: "profile_updated",
|
|
666
|
+
mind: user.username,
|
|
667
|
+
summary: `${user.username} avatar updated`
|
|
668
|
+
});
|
|
640
669
|
return c.json({ ok: true, avatar: filename });
|
|
641
670
|
}).delete("/avatar", async (c) => {
|
|
642
671
|
const user = c.get("user");
|
|
@@ -647,6 +676,11 @@ var authenticated = new Hono2().use(authMiddleware).post("/change-password", zVa
|
|
|
647
676
|
await updateUserProfile(user.id, { avatar: null });
|
|
648
677
|
const sessionId = getCookie2(c, "volute_session");
|
|
649
678
|
if (sessionId) invalidateSessionCache(sessionId);
|
|
679
|
+
broadcast({
|
|
680
|
+
type: "profile_updated",
|
|
681
|
+
mind: user.username,
|
|
682
|
+
summary: `${user.username} avatar removed`
|
|
683
|
+
});
|
|
650
684
|
return c.json({ ok: true });
|
|
651
685
|
});
|
|
652
686
|
var admin = new Hono2().use(authMiddleware).get("/users", async (c) => {
|
|
@@ -700,6 +734,14 @@ var admin = new Hono2().use(authMiddleware).get("/users", async (c) => {
|
|
|
700
734
|
if (Number.isNaN(id)) return c.json({ error: "Invalid user ID" }, 400);
|
|
701
735
|
const body = c.req.valid("json");
|
|
702
736
|
await updateUserProfile(id, body);
|
|
737
|
+
const updatedUser = await getUser(id);
|
|
738
|
+
if (updatedUser) {
|
|
739
|
+
broadcast({
|
|
740
|
+
type: "profile_updated",
|
|
741
|
+
mind: updatedUser.username,
|
|
742
|
+
summary: `${updatedUser.username} profile updated`
|
|
743
|
+
});
|
|
744
|
+
}
|
|
703
745
|
return c.json({ ok: true });
|
|
704
746
|
}).delete("/users/:id", async (c) => {
|
|
705
747
|
const user = c.get("user");
|
|
@@ -728,7 +770,7 @@ var app2 = new Hono2().post("/register", zValidator("json", credentialsSchema),
|
|
|
728
770
|
const user = await createUser(username, password);
|
|
729
771
|
if (user.role === "admin") {
|
|
730
772
|
const sessionId = await createSession(user.id);
|
|
731
|
-
setCookie(c, "volute_session", sessionId,
|
|
773
|
+
setCookie(c, "volute_session", sessionId, SESSION_COOKIE_OPTIONS);
|
|
732
774
|
}
|
|
733
775
|
return c.json({ id: user.id, username: user.username, role: user.role });
|
|
734
776
|
}).post("/login", zValidator("json", credentialsSchema), async (c) => {
|
|
@@ -738,7 +780,7 @@ var app2 = new Hono2().post("/register", zValidator("json", credentialsSchema),
|
|
|
738
780
|
return c.json({ error: "Invalid credentials" }, 401);
|
|
739
781
|
}
|
|
740
782
|
const sessionId = await createSession(user.id);
|
|
741
|
-
setCookie(c, "volute_session", sessionId,
|
|
783
|
+
setCookie(c, "volute_session", sessionId, SESSION_COOKIE_OPTIONS);
|
|
742
784
|
return c.json({ id: user.id, username: user.username, role: user.role });
|
|
743
785
|
}).post("/logout", async (c) => {
|
|
744
786
|
const sessionId = getCookie2(c, "volute_session");
|
|
@@ -1886,13 +1928,13 @@ var app6 = new Hono6().post("/:name/files/send", async (c) => {
|
|
|
1886
1928
|
if (pathErr) return c.json({ error: pathErr }, 400);
|
|
1887
1929
|
const senderDir = mindDir(senderName);
|
|
1888
1930
|
const filePath = resolve6(senderDir, "home", body.filePath);
|
|
1889
|
-
const
|
|
1890
|
-
const
|
|
1891
|
-
if (!
|
|
1892
|
-
if (
|
|
1931
|
+
const MAX_FILE_SIZE2 = 50 * 1024 * 1024;
|
|
1932
|
+
const stat5 = statSync(filePath, { throwIfNoEntry: false });
|
|
1933
|
+
if (!stat5) return c.json({ error: `File not found: ${body.filePath}` }, 404);
|
|
1934
|
+
if (stat5.size > MAX_FILE_SIZE2) {
|
|
1893
1935
|
return c.json(
|
|
1894
1936
|
{
|
|
1895
|
-
error: `File too large (${formatFileSize(
|
|
1937
|
+
error: `File too large (${formatFileSize(stat5.size)}, max ${formatFileSize(MAX_FILE_SIZE2)})`
|
|
1896
1938
|
},
|
|
1897
1939
|
413
|
|
1898
1940
|
);
|
|
@@ -2020,12 +2062,12 @@ var app7 = new Hono7().get("/:name/avatar", async (c) => {
|
|
|
2020
2062
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
2021
2063
|
const dir = mindDir(name);
|
|
2022
2064
|
const config = readVoluteConfig(dir);
|
|
2023
|
-
if (!config?.avatar) return c.json({ error: "No avatar configured" }, 404);
|
|
2024
|
-
const ext = extname2(config.avatar).toLowerCase();
|
|
2065
|
+
if (!config?.profile?.avatar) return c.json({ error: "No avatar configured" }, 404);
|
|
2066
|
+
const ext = extname2(config.profile.avatar).toLowerCase();
|
|
2025
2067
|
const mime = AVATAR_MIME2[ext];
|
|
2026
2068
|
if (!mime) return c.json({ error: "Invalid avatar extension" }, 400);
|
|
2027
2069
|
const homeDir = resolve7(dir, "home");
|
|
2028
|
-
const avatarPath = resolve7(homeDir, config.avatar);
|
|
2070
|
+
const avatarPath = resolve7(homeDir, config.profile.avatar);
|
|
2029
2071
|
if (!avatarPath.startsWith(`${homeDir}/`)) return c.json({ error: "Invalid avatar path" }, 400);
|
|
2030
2072
|
let realAvatarPath;
|
|
2031
2073
|
try {
|
|
@@ -2197,9 +2239,9 @@ var app9 = new Hono9().get("/:name/logs", async (c) => {
|
|
|
2197
2239
|
stream.onAbort(() => {
|
|
2198
2240
|
tail.kill();
|
|
2199
2241
|
});
|
|
2200
|
-
await new Promise((
|
|
2201
|
-
tail.on("exit",
|
|
2202
|
-
stream.onAbort(
|
|
2242
|
+
await new Promise((resolve20) => {
|
|
2243
|
+
tail.on("exit", resolve20);
|
|
2244
|
+
stream.onAbort(resolve20);
|
|
2203
2245
|
});
|
|
2204
2246
|
});
|
|
2205
2247
|
}).get("/:name/logs/tail", async (c) => {
|
|
@@ -2217,8 +2259,8 @@ var app9 = new Hono9().get("/:name/logs", async (c) => {
|
|
|
2217
2259
|
tail.stdout.on("data", (data) => {
|
|
2218
2260
|
output += data.toString();
|
|
2219
2261
|
});
|
|
2220
|
-
await new Promise((
|
|
2221
|
-
tail.on("exit",
|
|
2262
|
+
await new Promise((resolve20) => {
|
|
2263
|
+
tail.on("exit", resolve20);
|
|
2222
2264
|
});
|
|
2223
2265
|
return c.text(output);
|
|
2224
2266
|
});
|
|
@@ -2246,12 +2288,12 @@ var app10 = new Hono10().get("/:name/skills", async (c) => {
|
|
|
2246
2288
|
const { skillId } = c.req.valid("json");
|
|
2247
2289
|
const dir = mindDir(name);
|
|
2248
2290
|
try {
|
|
2249
|
-
await installSkill(name, dir, skillId);
|
|
2291
|
+
const result = await installSkill(name, dir, skillId);
|
|
2292
|
+
return c.json({ ok: true, ...result });
|
|
2250
2293
|
} catch (e) {
|
|
2251
2294
|
const msg = e instanceof Error ? e.message : String(e);
|
|
2252
2295
|
return c.json({ error: msg }, 400);
|
|
2253
2296
|
}
|
|
2254
|
-
return c.json({ ok: true });
|
|
2255
2297
|
}
|
|
2256
2298
|
).post(
|
|
2257
2299
|
"/:name/skills/update",
|
|
@@ -2606,7 +2648,7 @@ async function getMindStatus(name, port) {
|
|
|
2606
2648
|
const manager = getMindManager();
|
|
2607
2649
|
let status = "stopped";
|
|
2608
2650
|
try {
|
|
2609
|
-
const { getSleepManagerIfReady } = await import("./sleep-manager-
|
|
2651
|
+
const { getSleepManagerIfReady } = await import("./sleep-manager-RKTFZPD3.js");
|
|
2610
2652
|
if (getSleepManagerIfReady()?.isSleeping(name)) {
|
|
2611
2653
|
status = "sleeping";
|
|
2612
2654
|
}
|
|
@@ -2641,9 +2683,9 @@ async function getMindStatus(name, port) {
|
|
|
2641
2683
|
return {
|
|
2642
2684
|
status,
|
|
2643
2685
|
channels,
|
|
2644
|
-
displayName: config?.displayName,
|
|
2645
|
-
description: config?.description,
|
|
2646
|
-
avatar: config?.avatar
|
|
2686
|
+
displayName: config?.profile?.displayName,
|
|
2687
|
+
description: config?.profile?.description,
|
|
2688
|
+
avatar: config?.profile?.avatar
|
|
2647
2689
|
};
|
|
2648
2690
|
}
|
|
2649
2691
|
var TEMPLATE_BRANCH = "volute/template";
|
|
@@ -3007,7 +3049,7 @@ var app11 = new Hono11().post("/", requireAdmin, zValidator3("json", createMindS
|
|
|
3007
3049
|
if (body.description) {
|
|
3008
3050
|
const seedConfig = readVoluteConfig(dest);
|
|
3009
3051
|
if (!seedConfig) throw new Error("Failed to read volute.json after identity generation");
|
|
3010
|
-
seedConfig.
|
|
3052
|
+
seedConfig.profile = { ...seedConfig.profile, description: body.description };
|
|
3011
3053
|
writeVoluteConfig(dest, seedConfig);
|
|
3012
3054
|
}
|
|
3013
3055
|
if (body.model) {
|
|
@@ -3247,7 +3289,7 @@ ${user.trimEnd()}
|
|
|
3247
3289
|
const minds = await Promise.all(
|
|
3248
3290
|
entries.map(async (entry) => {
|
|
3249
3291
|
const mindStatus = await getMindStatus(entry.name, entry.port);
|
|
3250
|
-
const hasPages = existsSync10(resolve12(mindDir(entry.name), "home", "pages"));
|
|
3292
|
+
const hasPages = existsSync10(resolve12(mindDir(entry.name), "home", "public", "pages"));
|
|
3251
3293
|
return {
|
|
3252
3294
|
...entry,
|
|
3253
3295
|
...mindStatus,
|
|
@@ -3280,7 +3322,7 @@ ${user.trimEnd()}
|
|
|
3280
3322
|
return { name: v.name, port: v.port, status: variantStatus };
|
|
3281
3323
|
})
|
|
3282
3324
|
);
|
|
3283
|
-
const hasPages = existsSync10(resolve12(mindDir(name), "home", "pages"));
|
|
3325
|
+
const hasPages = existsSync10(resolve12(mindDir(name), "home", "public", "pages"));
|
|
3284
3326
|
return c.json({ ...entry, ...mindStatus, variants: variantStatuses, hasPages });
|
|
3285
3327
|
}).post("/:name/start", requireAdmin, async (c) => {
|
|
3286
3328
|
const name = c.req.param("name");
|
|
@@ -3380,7 +3422,7 @@ ${user.trimEnd()}
|
|
|
3380
3422
|
}
|
|
3381
3423
|
}
|
|
3382
3424
|
}
|
|
3383
|
-
if (context) {
|
|
3425
|
+
if (context && context.type !== "reload") {
|
|
3384
3426
|
manager.setPendingContext(name, context);
|
|
3385
3427
|
}
|
|
3386
3428
|
if (context?.type === "sprouted" && !variantName) {
|
|
@@ -3424,7 +3466,7 @@ ${user.trimEnd()}
|
|
|
3424
3466
|
const name = c.req.param("name");
|
|
3425
3467
|
const entry = findMind(name);
|
|
3426
3468
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
3427
|
-
const { getSleepManagerIfReady } = await import("./sleep-manager-
|
|
3469
|
+
const { getSleepManagerIfReady } = await import("./sleep-manager-RKTFZPD3.js");
|
|
3428
3470
|
const sm = getSleepManagerIfReady();
|
|
3429
3471
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
3430
3472
|
return c.json(sm.getState(name));
|
|
@@ -3432,7 +3474,7 @@ ${user.trimEnd()}
|
|
|
3432
3474
|
const name = c.req.param("name");
|
|
3433
3475
|
const entry = findMind(name);
|
|
3434
3476
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
3435
|
-
const { getSleepManagerIfReady } = await import("./sleep-manager-
|
|
3477
|
+
const { getSleepManagerIfReady } = await import("./sleep-manager-RKTFZPD3.js");
|
|
3436
3478
|
const sm = getSleepManagerIfReady();
|
|
3437
3479
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
3438
3480
|
if (sm.isSleeping(name)) return c.json({ error: "Mind is already sleeping" }, 409);
|
|
@@ -3452,7 +3494,7 @@ ${user.trimEnd()}
|
|
|
3452
3494
|
const name = c.req.param("name");
|
|
3453
3495
|
const entry = findMind(name);
|
|
3454
3496
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
3455
|
-
const { getSleepManagerIfReady } = await import("./sleep-manager-
|
|
3497
|
+
const { getSleepManagerIfReady } = await import("./sleep-manager-RKTFZPD3.js");
|
|
3456
3498
|
const sm = getSleepManagerIfReady();
|
|
3457
3499
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
3458
3500
|
if (!sm.isSleeping(name)) return c.json({ error: "Mind is not sleeping" }, 409);
|
|
@@ -3462,7 +3504,7 @@ ${user.trimEnd()}
|
|
|
3462
3504
|
const name = c.req.param("name");
|
|
3463
3505
|
const entry = findMind(name);
|
|
3464
3506
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
3465
|
-
const { getSleepManagerIfReady } = await import("./sleep-manager-
|
|
3507
|
+
const { getSleepManagerIfReady } = await import("./sleep-manager-RKTFZPD3.js");
|
|
3466
3508
|
const sm = getSleepManagerIfReady();
|
|
3467
3509
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
3468
3510
|
const flushed = await sm.flushQueuedMessages(name);
|
|
@@ -3680,7 +3722,7 @@ ${user.trimEnd()}
|
|
|
3680
3722
|
if (!variant) return c.json({ error: `Unknown variant: ${variantName}` }, 404);
|
|
3681
3723
|
}
|
|
3682
3724
|
try {
|
|
3683
|
-
const { getSleepManagerIfReady } = await import("./sleep-manager-
|
|
3725
|
+
const { getSleepManagerIfReady } = await import("./sleep-manager-RKTFZPD3.js");
|
|
3684
3726
|
const sm = getSleepManagerIfReady();
|
|
3685
3727
|
if (sm?.isSleeping(baseName)) {
|
|
3686
3728
|
const body2 = await c.req.text();
|
|
@@ -4114,7 +4156,7 @@ var app12 = new Hono12().get("/:name/*", async (c) => {
|
|
|
4114
4156
|
pagesRoot = resolve13(voluteHome(), "shared", "pages");
|
|
4115
4157
|
} else {
|
|
4116
4158
|
if (!findMind(name)) return c.text("Not found", 404);
|
|
4117
|
-
pagesRoot = resolve13(mindDir(name), "home", "pages");
|
|
4159
|
+
pagesRoot = resolve13(mindDir(name), "home", "public", "pages");
|
|
4118
4160
|
}
|
|
4119
4161
|
const wildcard = c.req.path.replace(`/pages/${name}`, "") || "/";
|
|
4120
4162
|
const requestedPath = resolve13(pagesRoot, wildcard.slice(1));
|
|
@@ -4190,9 +4232,98 @@ var app13 = new Hono13().get("/", async (c) => {
|
|
|
4190
4232
|
});
|
|
4191
4233
|
var prompts_default = app13;
|
|
4192
4234
|
|
|
4235
|
+
// src/web/api/public-files.ts
|
|
4236
|
+
import { readdir as readdir2, readFile as readFile3, stat as stat3 } from "fs/promises";
|
|
4237
|
+
import { extname as extname4, resolve as resolve14 } from "path";
|
|
4238
|
+
import { Hono as Hono14 } from "hono";
|
|
4239
|
+
var MAX_FILE_SIZE = 50 * 1024 * 1024;
|
|
4240
|
+
function resolvePublicRoot(name) {
|
|
4241
|
+
if (name === "_system") return resolve14(voluteHome(), "shared");
|
|
4242
|
+
if (!findMind(name)) return null;
|
|
4243
|
+
return resolve14(mindDir(name), "home", "public");
|
|
4244
|
+
}
|
|
4245
|
+
function hasDotSegment(relativePath) {
|
|
4246
|
+
return relativePath.split("/").some((seg) => seg.startsWith("."));
|
|
4247
|
+
}
|
|
4248
|
+
var MIME_TYPES2 = {
|
|
4249
|
+
".html": "text/html",
|
|
4250
|
+
".js": "application/javascript",
|
|
4251
|
+
".css": "text/css",
|
|
4252
|
+
".json": "application/json",
|
|
4253
|
+
".svg": "image/svg+xml",
|
|
4254
|
+
".png": "image/png",
|
|
4255
|
+
".jpg": "image/jpeg",
|
|
4256
|
+
".jpeg": "image/jpeg",
|
|
4257
|
+
".gif": "image/gif",
|
|
4258
|
+
".ico": "image/x-icon",
|
|
4259
|
+
".woff": "font/woff",
|
|
4260
|
+
".woff2": "font/woff2",
|
|
4261
|
+
".txt": "text/plain",
|
|
4262
|
+
".xml": "application/xml",
|
|
4263
|
+
".md": "text/markdown",
|
|
4264
|
+
".webp": "image/webp"
|
|
4265
|
+
};
|
|
4266
|
+
async function listDir(dirPath) {
|
|
4267
|
+
let entries;
|
|
4268
|
+
try {
|
|
4269
|
+
entries = await readdir2(dirPath, { withFileTypes: true });
|
|
4270
|
+
} catch (err) {
|
|
4271
|
+
if (err?.code === "ENOENT") return [];
|
|
4272
|
+
throw err;
|
|
4273
|
+
}
|
|
4274
|
+
return entries.filter((e) => !e.name.startsWith(".")).map((e) => ({
|
|
4275
|
+
name: e.name,
|
|
4276
|
+
type: e.isDirectory() ? "directory" : "file"
|
|
4277
|
+
}));
|
|
4278
|
+
}
|
|
4279
|
+
var app14 = new Hono14().get("/:name/", async (c) => {
|
|
4280
|
+
const name = c.req.param("name");
|
|
4281
|
+
const publicRoot = resolvePublicRoot(name);
|
|
4282
|
+
if (!publicRoot) return c.json({ error: "Not found" }, 404);
|
|
4283
|
+
return c.json(await listDir(publicRoot));
|
|
4284
|
+
}).get("/:name/*", async (c) => {
|
|
4285
|
+
const name = c.req.param("name");
|
|
4286
|
+
const publicRoot = resolvePublicRoot(name);
|
|
4287
|
+
if (!publicRoot) return c.text("Not found", 404);
|
|
4288
|
+
const wildcard = c.req.path.replace(`/public/${name}`, "") || "/";
|
|
4289
|
+
const relativePath = wildcard.slice(1);
|
|
4290
|
+
const requestedPath = resolve14(publicRoot, relativePath);
|
|
4291
|
+
if (!requestedPath.startsWith(publicRoot)) return c.text("Forbidden", 403);
|
|
4292
|
+
if (hasDotSegment(relativePath)) return c.text("Forbidden", 403);
|
|
4293
|
+
let fileStat;
|
|
4294
|
+
try {
|
|
4295
|
+
fileStat = await stat3(requestedPath);
|
|
4296
|
+
} catch (err) {
|
|
4297
|
+
if (err?.code === "ENOENT") return c.text("Not found", 404);
|
|
4298
|
+
if (err?.code === "EACCES") return c.text("Forbidden", 403);
|
|
4299
|
+
return c.text("Internal server error", 500);
|
|
4300
|
+
}
|
|
4301
|
+
if (fileStat.isDirectory()) {
|
|
4302
|
+
if (wildcard.endsWith("/")) {
|
|
4303
|
+
return c.json(await listDir(requestedPath));
|
|
4304
|
+
}
|
|
4305
|
+
return c.text("Not found", 404);
|
|
4306
|
+
}
|
|
4307
|
+
if (fileStat.isFile()) {
|
|
4308
|
+
if (fileStat.size > MAX_FILE_SIZE) return c.text("File too large", 413);
|
|
4309
|
+
const ext = extname4(requestedPath);
|
|
4310
|
+
const mime = MIME_TYPES2[ext] || "application/octet-stream";
|
|
4311
|
+
try {
|
|
4312
|
+
const body = await readFile3(requestedPath);
|
|
4313
|
+
return c.body(body, 200, { "Content-Type": mime });
|
|
4314
|
+
} catch (err) {
|
|
4315
|
+
if (err?.code === "ENOENT") return c.text("Not found", 404);
|
|
4316
|
+
if (err?.code === "EACCES") return c.text("Forbidden", 403);
|
|
4317
|
+
return c.text("Failed to read file", 500);
|
|
4318
|
+
}
|
|
4319
|
+
}
|
|
4320
|
+
return c.text("Not found", 404);
|
|
4321
|
+
});
|
|
4322
|
+
var public_files_default = app14;
|
|
4323
|
+
|
|
4193
4324
|
// src/web/api/schedules.ts
|
|
4194
4325
|
import { CronExpressionParser } from "cron-parser";
|
|
4195
|
-
import { Hono as
|
|
4326
|
+
import { Hono as Hono15 } from "hono";
|
|
4196
4327
|
var slog = logger_default.child("schedules");
|
|
4197
4328
|
function readSchedules(name) {
|
|
4198
4329
|
return readVoluteConfig(mindDir(name))?.schedules ?? [];
|
|
@@ -4209,7 +4340,7 @@ function writeSchedules(name, schedules) {
|
|
|
4209
4340
|
data: { schedules }
|
|
4210
4341
|
});
|
|
4211
4342
|
}
|
|
4212
|
-
var
|
|
4343
|
+
var app15 = new Hono15().get("/:name/schedules", (c) => {
|
|
4213
4344
|
const name = c.req.param("name");
|
|
4214
4345
|
if (!findMind(name)) return c.json({ error: "Mind not found" }, 404);
|
|
4215
4346
|
return c.json(readSchedules(name));
|
|
@@ -4312,11 +4443,11 @@ var app14 = new Hono14().get("/:name/schedules", (c) => {
|
|
|
4312
4443
|
return c.json({ error: "Failed to reach mind" }, 502);
|
|
4313
4444
|
}
|
|
4314
4445
|
});
|
|
4315
|
-
var schedules_default =
|
|
4446
|
+
var schedules_default = app15;
|
|
4316
4447
|
|
|
4317
4448
|
// src/web/api/shared.ts
|
|
4318
|
-
import { Hono as
|
|
4319
|
-
var
|
|
4449
|
+
import { Hono as Hono16 } from "hono";
|
|
4450
|
+
var app16 = new Hono16().post("/:name/shared/merge", requireAdmin, async (c) => {
|
|
4320
4451
|
const name = c.req.param("name");
|
|
4321
4452
|
const entry = findMind(name);
|
|
4322
4453
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
@@ -4365,15 +4496,15 @@ var app15 = new Hono15().post("/:name/shared/merge", requireAdmin, async (c) =>
|
|
|
4365
4496
|
return c.json({ error: err instanceof Error ? err.message : "Failed to get status" }, 500);
|
|
4366
4497
|
}
|
|
4367
4498
|
});
|
|
4368
|
-
var shared_default =
|
|
4499
|
+
var shared_default = app16;
|
|
4369
4500
|
|
|
4370
4501
|
// src/web/api/skills.ts
|
|
4371
4502
|
import { existsSync as existsSync11, mkdtempSync, readdirSync as readdirSync5, rmSync as rmSync5 } from "fs";
|
|
4372
4503
|
import { tmpdir } from "os";
|
|
4373
|
-
import { join as join2, resolve as
|
|
4504
|
+
import { join as join2, resolve as resolve15 } from "path";
|
|
4374
4505
|
import AdmZip from "adm-zip";
|
|
4375
|
-
import { Hono as
|
|
4376
|
-
var
|
|
4506
|
+
import { Hono as Hono17 } from "hono";
|
|
4507
|
+
var app17 = new Hono17().get("/", async (c) => {
|
|
4377
4508
|
const skills = await listSharedSkills();
|
|
4378
4509
|
return c.json(skills);
|
|
4379
4510
|
}).get("/:id", async (c) => {
|
|
@@ -4397,7 +4528,7 @@ var app16 = new Hono16().get("/", async (c) => {
|
|
|
4397
4528
|
try {
|
|
4398
4529
|
const zip = new AdmZip(buffer2);
|
|
4399
4530
|
for (const entry of zip.getEntries()) {
|
|
4400
|
-
const target =
|
|
4531
|
+
const target = resolve15(tmpDir, entry.entryName);
|
|
4401
4532
|
if (!target.startsWith(tmpDir)) {
|
|
4402
4533
|
return c.json({ error: "Invalid zip: paths must not escape archive" }, 400);
|
|
4403
4534
|
}
|
|
@@ -4438,12 +4569,15 @@ var app16 = new Hono16().get("/", async (c) => {
|
|
|
4438
4569
|
}
|
|
4439
4570
|
return c.json({ ok: true });
|
|
4440
4571
|
});
|
|
4441
|
-
var skills_default =
|
|
4572
|
+
var skills_default = app17;
|
|
4442
4573
|
|
|
4443
4574
|
// src/web/api/system.ts
|
|
4444
|
-
import {
|
|
4575
|
+
import { zValidator as zValidator5 } from "@hono/zod-validator";
|
|
4576
|
+
import { Hono as Hono18 } from "hono";
|
|
4445
4577
|
import { streamSSE as streamSSE3 } from "hono/streaming";
|
|
4446
|
-
|
|
4578
|
+
import { z as z5 } from "zod";
|
|
4579
|
+
var DEFAULT_API_URL = "https://volute.systems";
|
|
4580
|
+
var app18 = new Hono18().post("/restart", requireAdmin, (c) => {
|
|
4447
4581
|
setTimeout(() => process.exit(1), 200);
|
|
4448
4582
|
return c.json({ ok: true });
|
|
4449
4583
|
}).post("/stop", requireAdmin, (c) => {
|
|
@@ -4460,29 +4594,107 @@ var app17 = new Hono17().post("/restart", requireAdmin, (c) => {
|
|
|
4460
4594
|
stream.writeSSE({ data: JSON.stringify(entry) }).catch(() => {
|
|
4461
4595
|
});
|
|
4462
4596
|
});
|
|
4463
|
-
await new Promise((
|
|
4597
|
+
await new Promise((resolve20) => {
|
|
4464
4598
|
stream.onAbort(() => {
|
|
4465
4599
|
unsubscribe();
|
|
4466
|
-
|
|
4600
|
+
resolve20();
|
|
4467
4601
|
});
|
|
4468
4602
|
});
|
|
4469
4603
|
});
|
|
4470
4604
|
}).get("/info", (c) => {
|
|
4471
4605
|
const config = readSystemsConfig();
|
|
4472
4606
|
return c.json({ system: config?.system ?? null });
|
|
4607
|
+
}).post(
|
|
4608
|
+
"/register",
|
|
4609
|
+
requireAdmin,
|
|
4610
|
+
zValidator5("json", z5.object({ name: z5.string().min(1) })),
|
|
4611
|
+
async (c) => {
|
|
4612
|
+
const existing = readSystemsConfig();
|
|
4613
|
+
if (existing) {
|
|
4614
|
+
return c.json({ error: `Already registered as "${existing.system}"` }, 400);
|
|
4615
|
+
}
|
|
4616
|
+
const { name } = c.req.valid("json");
|
|
4617
|
+
const apiUrl = process.env.VOLUTE_SYSTEMS_URL || DEFAULT_API_URL;
|
|
4618
|
+
let apiKey;
|
|
4619
|
+
let system;
|
|
4620
|
+
try {
|
|
4621
|
+
const res = await fetch(`${apiUrl}/api/register`, {
|
|
4622
|
+
method: "POST",
|
|
4623
|
+
headers: { "Content-Type": "application/json" },
|
|
4624
|
+
body: JSON.stringify({ name: name.trim() })
|
|
4625
|
+
});
|
|
4626
|
+
if (!res.ok) {
|
|
4627
|
+
const err = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
|
|
4628
|
+
return c.json({ error: err.error }, 502);
|
|
4629
|
+
}
|
|
4630
|
+
({ apiKey, system } = await res.json());
|
|
4631
|
+
} catch (err) {
|
|
4632
|
+
return c.json({ error: `Connection failed: ${err.message}` }, 502);
|
|
4633
|
+
}
|
|
4634
|
+
try {
|
|
4635
|
+
writeSystemsConfig({ apiKey, system, apiUrl });
|
|
4636
|
+
} catch (err) {
|
|
4637
|
+
return c.json(
|
|
4638
|
+
{
|
|
4639
|
+
error: `Registered as "${system}" but failed to save config: ${err.message}`
|
|
4640
|
+
},
|
|
4641
|
+
500
|
|
4642
|
+
);
|
|
4643
|
+
}
|
|
4644
|
+
return c.json({ system });
|
|
4645
|
+
}
|
|
4646
|
+
).post(
|
|
4647
|
+
"/login",
|
|
4648
|
+
requireAdmin,
|
|
4649
|
+
zValidator5("json", z5.object({ key: z5.string().min(1) })),
|
|
4650
|
+
async (c) => {
|
|
4651
|
+
const existing = readSystemsConfig();
|
|
4652
|
+
if (existing) {
|
|
4653
|
+
return c.json({ error: `Already logged in as "${existing.system}"` }, 400);
|
|
4654
|
+
}
|
|
4655
|
+
const { key } = c.req.valid("json");
|
|
4656
|
+
const apiUrl = process.env.VOLUTE_SYSTEMS_URL || DEFAULT_API_URL;
|
|
4657
|
+
let system;
|
|
4658
|
+
try {
|
|
4659
|
+
const res = await fetch(`${apiUrl}/api/whoami`, {
|
|
4660
|
+
headers: { Authorization: `Bearer ${key.trim()}` }
|
|
4661
|
+
});
|
|
4662
|
+
if (!res.ok) {
|
|
4663
|
+
const err = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
|
|
4664
|
+
return c.json({ error: err.error }, 502);
|
|
4665
|
+
}
|
|
4666
|
+
({ system } = await res.json());
|
|
4667
|
+
} catch (err) {
|
|
4668
|
+
return c.json({ error: `Connection failed: ${err.message}` }, 502);
|
|
4669
|
+
}
|
|
4670
|
+
try {
|
|
4671
|
+
writeSystemsConfig({ apiKey: key.trim(), system, apiUrl });
|
|
4672
|
+
} catch (err) {
|
|
4673
|
+
return c.json(
|
|
4674
|
+
{
|
|
4675
|
+
error: `Logged in as "${system}" but failed to save config: ${err.message}`
|
|
4676
|
+
},
|
|
4677
|
+
500
|
|
4678
|
+
);
|
|
4679
|
+
}
|
|
4680
|
+
return c.json({ system });
|
|
4681
|
+
}
|
|
4682
|
+
).post("/logout", requireAdmin, (c) => {
|
|
4683
|
+
deleteSystemsConfig();
|
|
4684
|
+
return c.json({ ok: true });
|
|
4473
4685
|
});
|
|
4474
|
-
var system_default =
|
|
4686
|
+
var system_default = app18;
|
|
4475
4687
|
|
|
4476
4688
|
// src/web/api/typing.ts
|
|
4477
|
-
import { zValidator as
|
|
4478
|
-
import { Hono as
|
|
4479
|
-
import { z as
|
|
4480
|
-
var typingSchema =
|
|
4481
|
-
channel:
|
|
4482
|
-
sender:
|
|
4483
|
-
active:
|
|
4689
|
+
import { zValidator as zValidator6 } from "@hono/zod-validator";
|
|
4690
|
+
import { Hono as Hono19 } from "hono";
|
|
4691
|
+
import { z as z6 } from "zod";
|
|
4692
|
+
var typingSchema = z6.object({
|
|
4693
|
+
channel: z6.string().min(1),
|
|
4694
|
+
sender: z6.string().min(1),
|
|
4695
|
+
active: z6.boolean()
|
|
4484
4696
|
});
|
|
4485
|
-
var
|
|
4697
|
+
var app19 = new Hono19().post("/:name/typing", zValidator6("json", typingSchema), (c) => {
|
|
4486
4698
|
const { channel, sender, active } = c.req.valid("json");
|
|
4487
4699
|
const map = getTypingMap();
|
|
4488
4700
|
if (active) {
|
|
@@ -4504,13 +4716,13 @@ var app18 = new Hono18().post("/:name/typing", zValidator5("json", typingSchema)
|
|
|
4504
4716
|
const map = getTypingMap();
|
|
4505
4717
|
return c.json({ typing: map.get(channel) });
|
|
4506
4718
|
});
|
|
4507
|
-
var typing_default =
|
|
4719
|
+
var typing_default = app19;
|
|
4508
4720
|
|
|
4509
4721
|
// src/web/api/update.ts
|
|
4510
4722
|
import { spawn as spawn2 } from "child_process";
|
|
4511
|
-
import { Hono as
|
|
4723
|
+
import { Hono as Hono20 } from "hono";
|
|
4512
4724
|
var bin;
|
|
4513
|
-
var
|
|
4725
|
+
var app20 = new Hono20().get("/update", async (c) => {
|
|
4514
4726
|
const result = await checkForUpdate();
|
|
4515
4727
|
return c.json(result);
|
|
4516
4728
|
}).post("/update", requireAdmin, async (c) => {
|
|
@@ -4525,21 +4737,21 @@ var app19 = new Hono19().get("/update", async (c) => {
|
|
|
4525
4737
|
child.unref();
|
|
4526
4738
|
return c.json({ ok: true, message: "Updating..." });
|
|
4527
4739
|
});
|
|
4528
|
-
var update_default =
|
|
4740
|
+
var update_default = app20;
|
|
4529
4741
|
|
|
4530
4742
|
// src/web/api/v1/chat.ts
|
|
4531
|
-
import { zValidator as
|
|
4532
|
-
import { Hono as
|
|
4743
|
+
import { zValidator as zValidator7 } from "@hono/zod-validator";
|
|
4744
|
+
import { Hono as Hono21 } from "hono";
|
|
4533
4745
|
import { streamSSE as streamSSE4 } from "hono/streaming";
|
|
4534
|
-
import { z as
|
|
4746
|
+
import { z as z7 } from "zod";
|
|
4535
4747
|
async function fanOutToMinds(opts) {
|
|
4536
4748
|
const participants = await getParticipants(opts.conversationId);
|
|
4537
4749
|
const mindParticipants = participants.filter((p) => p.userType === "mind");
|
|
4538
4750
|
const participantNames = participants.map((p) => p.username);
|
|
4539
4751
|
const isDM = opts.isDM ?? participants.length === 2;
|
|
4540
4752
|
const channelEntryType = opts.channelEntryType ?? (isDM ? "dm" : "group");
|
|
4541
|
-
const { getMindManager: getMindManager2 } = await import("./mind-manager-
|
|
4542
|
-
const { getSleepManagerIfReady } = await import("./sleep-manager-
|
|
4753
|
+
const { getMindManager: getMindManager2 } = await import("./mind-manager-4NDNAYAB.js");
|
|
4754
|
+
const { getSleepManagerIfReady } = await import("./sleep-manager-RKTFZPD3.js");
|
|
4543
4755
|
const manager = getMindManager2();
|
|
4544
4756
|
const sm = getSleepManagerIfReady();
|
|
4545
4757
|
const targetMinds = mindParticipants.map((ap) => {
|
|
@@ -4588,18 +4800,18 @@ async function fanOutToMinds(opts) {
|
|
|
4588
4800
|
});
|
|
4589
4801
|
}
|
|
4590
4802
|
}
|
|
4591
|
-
var mindChatSchema =
|
|
4592
|
-
message:
|
|
4593
|
-
conversationId:
|
|
4594
|
-
sender:
|
|
4595
|
-
images:
|
|
4803
|
+
var mindChatSchema = z7.object({
|
|
4804
|
+
message: z7.string().optional(),
|
|
4805
|
+
conversationId: z7.string().optional(),
|
|
4806
|
+
sender: z7.string().optional(),
|
|
4807
|
+
images: z7.array(z7.object({ media_type: z7.string(), data: z7.string() })).optional()
|
|
4596
4808
|
});
|
|
4597
|
-
var unifiedChatSchema =
|
|
4598
|
-
message:
|
|
4599
|
-
conversationId:
|
|
4600
|
-
images:
|
|
4809
|
+
var unifiedChatSchema = z7.object({
|
|
4810
|
+
message: z7.string().optional(),
|
|
4811
|
+
conversationId: z7.string(),
|
|
4812
|
+
images: z7.array(z7.object({ media_type: z7.string(), data: z7.string() })).optional()
|
|
4601
4813
|
});
|
|
4602
|
-
var
|
|
4814
|
+
var app21 = new Hono21().use("*", authMiddleware).post("/minds/:name/chat", zValidator7("json", mindChatSchema), async (c) => {
|
|
4603
4815
|
const name = c.req.param("name");
|
|
4604
4816
|
const [baseName] = name.split("@", 2);
|
|
4605
4817
|
const entry = findMind(baseName);
|
|
@@ -4682,15 +4894,15 @@ var app20 = new Hono20().use("*", authMiddleware).post("/minds/:name/chat", zVal
|
|
|
4682
4894
|
if (!stream.aborted) logger_default.error("[v1-chat] SSE ping error:", logger_default.errorData(err));
|
|
4683
4895
|
});
|
|
4684
4896
|
}, 15e3);
|
|
4685
|
-
await new Promise((
|
|
4897
|
+
await new Promise((resolve20) => {
|
|
4686
4898
|
stream.onAbort(() => {
|
|
4687
4899
|
unsubscribe();
|
|
4688
4900
|
clearInterval(keepAlive);
|
|
4689
|
-
|
|
4901
|
+
resolve20();
|
|
4690
4902
|
});
|
|
4691
4903
|
});
|
|
4692
4904
|
});
|
|
4693
|
-
}).post("/chat",
|
|
4905
|
+
}).post("/chat", zValidator7("json", unifiedChatSchema), async (c) => {
|
|
4694
4906
|
const user = c.get("user");
|
|
4695
4907
|
const body = c.req.valid("json");
|
|
4696
4908
|
if (!body.message && (!body.images || body.images.length === 0)) {
|
|
@@ -4722,17 +4934,17 @@ var app20 = new Hono20().use("*", authMiddleware).post("/minds/:name/chat", zVal
|
|
|
4722
4934
|
});
|
|
4723
4935
|
return c.json({ ok: true, conversationId: body.conversationId });
|
|
4724
4936
|
});
|
|
4725
|
-
var chat_default =
|
|
4937
|
+
var chat_default = app21;
|
|
4726
4938
|
|
|
4727
4939
|
// src/web/api/v1/conversations.ts
|
|
4728
|
-
import { zValidator as
|
|
4729
|
-
import { Hono as
|
|
4730
|
-
import { z as
|
|
4731
|
-
var createSchema =
|
|
4732
|
-
title:
|
|
4733
|
-
participantNames:
|
|
4940
|
+
import { zValidator as zValidator8 } from "@hono/zod-validator";
|
|
4941
|
+
import { Hono as Hono22 } from "hono";
|
|
4942
|
+
import { z as z8 } from "zod";
|
|
4943
|
+
var createSchema = z8.object({
|
|
4944
|
+
title: z8.string().optional(),
|
|
4945
|
+
participantNames: z8.array(z8.string()).min(1)
|
|
4734
4946
|
});
|
|
4735
|
-
var
|
|
4947
|
+
var app22 = new Hono22().use("*", authMiddleware).get("/", async (c) => {
|
|
4736
4948
|
const user = c.get("user");
|
|
4737
4949
|
const convs = await listConversationsWithParticipants(user.id);
|
|
4738
4950
|
return c.json(convs);
|
|
@@ -4763,7 +4975,7 @@ var app21 = new Hono21().use("*", authMiddleware).get("/", async (c) => {
|
|
|
4763
4975
|
}
|
|
4764
4976
|
const participants = await getParticipants(id);
|
|
4765
4977
|
return c.json(participants);
|
|
4766
|
-
}).post("/",
|
|
4978
|
+
}).post("/", zValidator8("json", createSchema), async (c) => {
|
|
4767
4979
|
const user = c.get("user");
|
|
4768
4980
|
const body = c.req.valid("json");
|
|
4769
4981
|
const participantIds = /* @__PURE__ */ new Set();
|
|
@@ -4809,11 +5021,11 @@ var app21 = new Hono21().use("*", authMiddleware).get("/", async (c) => {
|
|
|
4809
5021
|
if (!deleted) return c.json({ error: "Conversation not found" }, 404);
|
|
4810
5022
|
return c.json({ ok: true });
|
|
4811
5023
|
});
|
|
4812
|
-
var conversations_default =
|
|
5024
|
+
var conversations_default = app22;
|
|
4813
5025
|
|
|
4814
5026
|
// src/web/api/v1/events.ts
|
|
4815
5027
|
import { desc as desc3 } from "drizzle-orm";
|
|
4816
|
-
import { Hono as
|
|
5028
|
+
import { Hono as Hono23 } from "hono";
|
|
4817
5029
|
import { streamSSE as streamSSE5 } from "hono/streaming";
|
|
4818
5030
|
|
|
4819
5031
|
// src/lib/events/brain-presence.ts
|
|
@@ -4860,7 +5072,7 @@ function getEventsSince(sinceId) {
|
|
|
4860
5072
|
}
|
|
4861
5073
|
|
|
4862
5074
|
// src/web/api/v1/events.ts
|
|
4863
|
-
var
|
|
5075
|
+
var app23 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
|
|
4864
5076
|
const user = c.get("user");
|
|
4865
5077
|
const since = c.req.query("since");
|
|
4866
5078
|
const sinceId = since ? Number(since) : 0;
|
|
@@ -4954,8 +5166,8 @@ var app22 = new Hono22().use("*", authMiddleware).get("/", async (c) => {
|
|
|
4954
5166
|
});
|
|
4955
5167
|
}, 15e3);
|
|
4956
5168
|
cleanups.push(() => clearInterval(keepAlive));
|
|
4957
|
-
await new Promise((
|
|
4958
|
-
stream.onAbort(() =>
|
|
5169
|
+
await new Promise((resolve20) => {
|
|
5170
|
+
stream.onAbort(() => resolve20());
|
|
4959
5171
|
});
|
|
4960
5172
|
} finally {
|
|
4961
5173
|
for (const cleanup of cleanups) {
|
|
@@ -4967,19 +5179,19 @@ var app22 = new Hono22().use("*", authMiddleware).get("/", async (c) => {
|
|
|
4967
5179
|
}
|
|
4968
5180
|
});
|
|
4969
5181
|
});
|
|
4970
|
-
var events_default =
|
|
5182
|
+
var events_default = app23;
|
|
4971
5183
|
|
|
4972
5184
|
// src/web/api/variants.ts
|
|
4973
5185
|
import { existsSync as existsSync12, mkdirSync as mkdirSync8, writeFileSync as writeFileSync8 } from "fs";
|
|
4974
|
-
import { resolve as
|
|
4975
|
-
import { Hono as
|
|
5186
|
+
import { resolve as resolve17 } from "path";
|
|
5187
|
+
import { Hono as Hono24 } from "hono";
|
|
4976
5188
|
|
|
4977
5189
|
// src/lib/spawn-server.ts
|
|
4978
5190
|
import { spawn as spawn3 } from "child_process";
|
|
4979
5191
|
import { closeSync, mkdirSync as mkdirSync7, openSync, readFileSync as readFileSync10 } from "fs";
|
|
4980
|
-
import { resolve as
|
|
5192
|
+
import { resolve as resolve16 } from "path";
|
|
4981
5193
|
function tsxBin(cwd) {
|
|
4982
|
-
return
|
|
5194
|
+
return resolve16(cwd, "node_modules", ".bin", "tsx");
|
|
4983
5195
|
}
|
|
4984
5196
|
function spawnServer(cwd, port, options) {
|
|
4985
5197
|
if (options?.detached) {
|
|
@@ -4992,31 +5204,31 @@ function spawnAttached(cwd, port) {
|
|
|
4992
5204
|
cwd,
|
|
4993
5205
|
stdio: ["ignore", "pipe", "pipe"]
|
|
4994
5206
|
});
|
|
4995
|
-
return new Promise((
|
|
4996
|
-
const timeout = setTimeout(() =>
|
|
5207
|
+
return new Promise((resolve20) => {
|
|
5208
|
+
const timeout = setTimeout(() => resolve20(null), 3e4);
|
|
4997
5209
|
function checkOutput(data) {
|
|
4998
5210
|
const match = data.toString().match(/listening on :(\d+)/);
|
|
4999
5211
|
if (match) {
|
|
5000
5212
|
clearTimeout(timeout);
|
|
5001
|
-
|
|
5213
|
+
resolve20({ child, actualPort: parseInt(match[1], 10) });
|
|
5002
5214
|
}
|
|
5003
5215
|
}
|
|
5004
5216
|
child.stdout?.on("data", checkOutput);
|
|
5005
5217
|
child.stderr?.on("data", checkOutput);
|
|
5006
5218
|
child.on("error", () => {
|
|
5007
5219
|
clearTimeout(timeout);
|
|
5008
|
-
|
|
5220
|
+
resolve20(null);
|
|
5009
5221
|
});
|
|
5010
5222
|
child.on("exit", () => {
|
|
5011
5223
|
clearTimeout(timeout);
|
|
5012
|
-
|
|
5224
|
+
resolve20(null);
|
|
5013
5225
|
});
|
|
5014
5226
|
});
|
|
5015
5227
|
}
|
|
5016
5228
|
function spawnDetached(cwd, port, logDir) {
|
|
5017
|
-
const logsDir = logDir ??
|
|
5229
|
+
const logsDir = logDir ?? resolve16(cwd, ".mind", "logs");
|
|
5018
5230
|
mkdirSync7(logsDir, { recursive: true });
|
|
5019
|
-
const logPath =
|
|
5231
|
+
const logPath = resolve16(logsDir, "mind.log");
|
|
5020
5232
|
const logFd = openSync(logPath, "a");
|
|
5021
5233
|
const child = spawn3(tsxBin(cwd), ["src/server.ts", "--port", String(port)], {
|
|
5022
5234
|
cwd,
|
|
@@ -5088,7 +5300,7 @@ async function verify2(port) {
|
|
|
5088
5300
|
}
|
|
5089
5301
|
|
|
5090
5302
|
// src/web/api/variants.ts
|
|
5091
|
-
var
|
|
5303
|
+
var app24 = new Hono24().get("/:name/variants", async (c) => {
|
|
5092
5304
|
const name = c.req.param("name");
|
|
5093
5305
|
const entry = findMind(name);
|
|
5094
5306
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
@@ -5128,11 +5340,11 @@ var app23 = new Hono23().get("/:name/variants", async (c) => {
|
|
|
5128
5340
|
const err = validateBranchName(variantName);
|
|
5129
5341
|
if (err) return c.json({ error: err }, 400);
|
|
5130
5342
|
const projectRoot = mindDir(mindName);
|
|
5131
|
-
const variantDir =
|
|
5343
|
+
const variantDir = resolve17(projectRoot, ".variants", variantName);
|
|
5132
5344
|
if (existsSync12(variantDir)) {
|
|
5133
5345
|
return c.json({ error: `Variant directory already exists: ${variantDir}` }, 409);
|
|
5134
5346
|
}
|
|
5135
|
-
mkdirSync8(
|
|
5347
|
+
mkdirSync8(resolve17(projectRoot, ".variants"), { recursive: true });
|
|
5136
5348
|
try {
|
|
5137
5349
|
await gitExec(["worktree", "add", "-b", variantName, variantDir], { cwd: projectRoot });
|
|
5138
5350
|
} catch (e) {
|
|
@@ -5145,7 +5357,7 @@ var app23 = new Hono23().get("/:name/variants", async (c) => {
|
|
|
5145
5357
|
const [cmd, args] = wrapForIsolation("npm", ["install"], mindName);
|
|
5146
5358
|
await exec(cmd, args, {
|
|
5147
5359
|
cwd: variantDir,
|
|
5148
|
-
env: { ...process.env, HOME:
|
|
5360
|
+
env: { ...process.env, HOME: resolve17(variantDir, "home") }
|
|
5149
5361
|
});
|
|
5150
5362
|
} else {
|
|
5151
5363
|
await exec("npm", ["install"], { cwd: variantDir });
|
|
@@ -5155,7 +5367,7 @@ var app23 = new Hono23().get("/:name/variants", async (c) => {
|
|
|
5155
5367
|
return c.json({ error: `npm install failed: ${msg}` }, 500);
|
|
5156
5368
|
}
|
|
5157
5369
|
if (body.soul) {
|
|
5158
|
-
writeFileSync8(
|
|
5370
|
+
writeFileSync8(resolve17(variantDir, "home/SOUL.md"), body.soul);
|
|
5159
5371
|
}
|
|
5160
5372
|
const variantPort = body.port ?? nextPort();
|
|
5161
5373
|
const variant = {
|
|
@@ -5266,7 +5478,7 @@ var app23 = new Hono23().get("/:name/variants", async (c) => {
|
|
|
5266
5478
|
const [cmd, args] = wrapForIsolation("npm", ["install"], mindName);
|
|
5267
5479
|
await exec(cmd, args, {
|
|
5268
5480
|
cwd: projectRoot,
|
|
5269
|
-
env: { ...process.env, HOME:
|
|
5481
|
+
env: { ...process.env, HOME: resolve17(projectRoot, "home") }
|
|
5270
5482
|
});
|
|
5271
5483
|
} else {
|
|
5272
5484
|
await exec("npm", ["install"], { cwd: projectRoot });
|
|
@@ -5304,19 +5516,19 @@ var app23 = new Hono23().get("/:name/variants", async (c) => {
|
|
|
5304
5516
|
await cleanupVariant(mindName, variantName, projectRoot, variant.path, { stop: true });
|
|
5305
5517
|
return c.json({ ok: true });
|
|
5306
5518
|
});
|
|
5307
|
-
var variants_default =
|
|
5519
|
+
var variants_default = app24;
|
|
5308
5520
|
|
|
5309
5521
|
// src/web/api/volute/channels.ts
|
|
5310
|
-
import { zValidator as
|
|
5311
|
-
import { Hono as
|
|
5312
|
-
import { z as
|
|
5313
|
-
var createSchema2 =
|
|
5314
|
-
name:
|
|
5522
|
+
import { zValidator as zValidator9 } from "@hono/zod-validator";
|
|
5523
|
+
import { Hono as Hono25 } from "hono";
|
|
5524
|
+
import { z as z9 } from "zod";
|
|
5525
|
+
var createSchema2 = z9.object({
|
|
5526
|
+
name: z9.string().min(1).max(50).regex(/^[a-z0-9][a-z0-9-]*$/, "Channel names must be lowercase alphanumeric with hyphens")
|
|
5315
5527
|
});
|
|
5316
|
-
var inviteSchema =
|
|
5317
|
-
username:
|
|
5528
|
+
var inviteSchema = z9.object({
|
|
5529
|
+
username: z9.string().min(1)
|
|
5318
5530
|
});
|
|
5319
|
-
var
|
|
5531
|
+
var app25 = new Hono25().get("/", async (c) => {
|
|
5320
5532
|
const user = c.get("user");
|
|
5321
5533
|
const channels = await listChannels();
|
|
5322
5534
|
const results = await Promise.all(
|
|
@@ -5327,7 +5539,7 @@ var app24 = new Hono24().get("/", async (c) => {
|
|
|
5327
5539
|
})
|
|
5328
5540
|
);
|
|
5329
5541
|
return c.json(results);
|
|
5330
|
-
}).post("/",
|
|
5542
|
+
}).post("/", zValidator9("json", createSchema2), async (c) => {
|
|
5331
5543
|
const user = c.get("user");
|
|
5332
5544
|
const body = c.req.valid("json");
|
|
5333
5545
|
try {
|
|
@@ -5360,7 +5572,7 @@ var app24 = new Hono24().get("/", async (c) => {
|
|
|
5360
5572
|
if (!ch) return c.json({ error: "Channel not found" }, 404);
|
|
5361
5573
|
const participants = await getParticipants(ch.id);
|
|
5362
5574
|
return c.json(participants);
|
|
5363
|
-
}).post("/:name/invite",
|
|
5575
|
+
}).post("/:name/invite", zValidator9("json", inviteSchema), async (c) => {
|
|
5364
5576
|
const name = c.req.param("name");
|
|
5365
5577
|
const inviter = c.get("user");
|
|
5366
5578
|
const { username } = c.req.valid("json");
|
|
@@ -5380,21 +5592,21 @@ var app24 = new Hono24().get("/", async (c) => {
|
|
|
5380
5592
|
]);
|
|
5381
5593
|
return c.json({ ok: true });
|
|
5382
5594
|
});
|
|
5383
|
-
var channels_default2 =
|
|
5595
|
+
var channels_default2 = app25;
|
|
5384
5596
|
|
|
5385
5597
|
// src/web/api/volute/chat.ts
|
|
5386
|
-
import { zValidator as
|
|
5387
|
-
import { Hono as
|
|
5598
|
+
import { zValidator as zValidator10 } from "@hono/zod-validator";
|
|
5599
|
+
import { Hono as Hono26 } from "hono";
|
|
5388
5600
|
import { streamSSE as streamSSE6 } from "hono/streaming";
|
|
5389
|
-
import { z as
|
|
5601
|
+
import { z as z10 } from "zod";
|
|
5390
5602
|
async function fanOutToMinds2(opts) {
|
|
5391
5603
|
const participants = await getParticipants(opts.conversationId);
|
|
5392
5604
|
const mindParticipants = participants.filter((p) => p.userType === "mind");
|
|
5393
5605
|
const participantNames = participants.map((p) => p.username);
|
|
5394
5606
|
const isDM = opts.isDM ?? participants.length === 2;
|
|
5395
5607
|
const channelEntryType = opts.channelEntryType ?? (isDM ? "dm" : "group");
|
|
5396
|
-
const { getMindManager: getMindManager2 } = await import("./mind-manager-
|
|
5397
|
-
const { getSleepManagerIfReady } = await import("./sleep-manager-
|
|
5608
|
+
const { getMindManager: getMindManager2 } = await import("./mind-manager-4NDNAYAB.js");
|
|
5609
|
+
const { getSleepManagerIfReady } = await import("./sleep-manager-RKTFZPD3.js");
|
|
5398
5610
|
const manager = getMindManager2();
|
|
5399
5611
|
const sm = getSleepManagerIfReady();
|
|
5400
5612
|
const targetMinds = mindParticipants.map((ap) => {
|
|
@@ -5442,18 +5654,18 @@ async function fanOutToMinds2(opts) {
|
|
|
5442
5654
|
});
|
|
5443
5655
|
}
|
|
5444
5656
|
}
|
|
5445
|
-
var chatSchema =
|
|
5446
|
-
message:
|
|
5447
|
-
conversationId:
|
|
5448
|
-
sender:
|
|
5449
|
-
images:
|
|
5450
|
-
|
|
5451
|
-
media_type:
|
|
5452
|
-
data:
|
|
5657
|
+
var chatSchema = z10.object({
|
|
5658
|
+
message: z10.string().optional(),
|
|
5659
|
+
conversationId: z10.string().optional(),
|
|
5660
|
+
sender: z10.string().optional(),
|
|
5661
|
+
images: z10.array(
|
|
5662
|
+
z10.object({
|
|
5663
|
+
media_type: z10.string(),
|
|
5664
|
+
data: z10.string()
|
|
5453
5665
|
})
|
|
5454
5666
|
).optional()
|
|
5455
5667
|
});
|
|
5456
|
-
var
|
|
5668
|
+
var app26 = new Hono26().post("/:name/chat", zValidator10("json", chatSchema), async (c) => {
|
|
5457
5669
|
const name = c.req.param("name");
|
|
5458
5670
|
const [baseName] = name.split("@", 2);
|
|
5459
5671
|
const entry = findMind(baseName);
|
|
@@ -5540,23 +5752,23 @@ var app25 = new Hono25().post("/:name/chat", zValidator9("json", chatSchema), as
|
|
|
5540
5752
|
if (!stream.aborted) console.error("[chat] SSE ping error:", err);
|
|
5541
5753
|
});
|
|
5542
5754
|
}, 15e3);
|
|
5543
|
-
await new Promise((
|
|
5755
|
+
await new Promise((resolve20) => {
|
|
5544
5756
|
stream.onAbort(() => {
|
|
5545
5757
|
unsubscribe();
|
|
5546
5758
|
clearInterval(keepAlive);
|
|
5547
|
-
|
|
5759
|
+
resolve20();
|
|
5548
5760
|
});
|
|
5549
5761
|
});
|
|
5550
5762
|
});
|
|
5551
5763
|
});
|
|
5552
|
-
var unifiedChatSchema2 =
|
|
5553
|
-
message:
|
|
5554
|
-
conversationId:
|
|
5555
|
-
images:
|
|
5764
|
+
var unifiedChatSchema2 = z10.object({
|
|
5765
|
+
message: z10.string().optional(),
|
|
5766
|
+
conversationId: z10.string(),
|
|
5767
|
+
images: z10.array(z10.object({ media_type: z10.string(), data: z10.string() })).optional()
|
|
5556
5768
|
});
|
|
5557
|
-
var unifiedChatApp = new
|
|
5769
|
+
var unifiedChatApp = new Hono26().post(
|
|
5558
5770
|
"/chat",
|
|
5559
|
-
|
|
5771
|
+
zValidator10("json", unifiedChatSchema2),
|
|
5560
5772
|
async (c) => {
|
|
5561
5773
|
const user = c.get("user");
|
|
5562
5774
|
const body = c.req.valid("json");
|
|
@@ -5590,18 +5802,18 @@ var unifiedChatApp = new Hono25().post(
|
|
|
5590
5802
|
return c.json({ ok: true, conversationId: body.conversationId });
|
|
5591
5803
|
}
|
|
5592
5804
|
);
|
|
5593
|
-
var chat_default2 =
|
|
5805
|
+
var chat_default2 = app26;
|
|
5594
5806
|
|
|
5595
5807
|
// src/web/api/volute/conversations.ts
|
|
5596
|
-
import { zValidator as
|
|
5597
|
-
import { Hono as
|
|
5598
|
-
import { z as
|
|
5599
|
-
var createConvSchema =
|
|
5600
|
-
title:
|
|
5601
|
-
participantIds:
|
|
5602
|
-
participantNames:
|
|
5808
|
+
import { zValidator as zValidator11 } from "@hono/zod-validator";
|
|
5809
|
+
import { Hono as Hono27 } from "hono";
|
|
5810
|
+
import { z as z11 } from "zod";
|
|
5811
|
+
var createConvSchema = z11.object({
|
|
5812
|
+
title: z11.string().optional(),
|
|
5813
|
+
participantIds: z11.array(z11.number()).optional(),
|
|
5814
|
+
participantNames: z11.array(z11.string()).optional()
|
|
5603
5815
|
});
|
|
5604
|
-
var
|
|
5816
|
+
var app27 = new Hono27().get("/:name/conversations", async (c) => {
|
|
5605
5817
|
const name = c.req.param("name");
|
|
5606
5818
|
const user = c.get("user");
|
|
5607
5819
|
let lookupId = user.id;
|
|
@@ -5612,7 +5824,7 @@ var app26 = new Hono26().get("/:name/conversations", async (c) => {
|
|
|
5612
5824
|
const all = await listConversationsForUser(lookupId);
|
|
5613
5825
|
const convs = all.filter((c2) => c2.mind_name === name || c2.type === "channel");
|
|
5614
5826
|
return c.json(convs);
|
|
5615
|
-
}).post("/:name/conversations",
|
|
5827
|
+
}).post("/:name/conversations", zValidator11("json", createConvSchema), async (c) => {
|
|
5616
5828
|
const name = c.req.param("name");
|
|
5617
5829
|
const user = c.get("user");
|
|
5618
5830
|
const body = c.req.valid("json");
|
|
@@ -5686,18 +5898,18 @@ var app26 = new Hono26().get("/:name/conversations", async (c) => {
|
|
|
5686
5898
|
if (!deleted) return c.json({ error: "Conversation not found" }, 404);
|
|
5687
5899
|
return c.json({ ok: true });
|
|
5688
5900
|
});
|
|
5689
|
-
var conversations_default2 =
|
|
5901
|
+
var conversations_default2 = app27;
|
|
5690
5902
|
|
|
5691
5903
|
// src/web/api/volute/user-conversations.ts
|
|
5692
|
-
import { zValidator as
|
|
5693
|
-
import { Hono as
|
|
5904
|
+
import { zValidator as zValidator12 } from "@hono/zod-validator";
|
|
5905
|
+
import { Hono as Hono28 } from "hono";
|
|
5694
5906
|
import { streamSSE as streamSSE7 } from "hono/streaming";
|
|
5695
|
-
import { z as
|
|
5696
|
-
var createSchema3 =
|
|
5697
|
-
title:
|
|
5698
|
-
participantNames:
|
|
5907
|
+
import { z as z12 } from "zod";
|
|
5908
|
+
var createSchema3 = z12.object({
|
|
5909
|
+
title: z12.string().optional(),
|
|
5910
|
+
participantNames: z12.array(z12.string()).min(1)
|
|
5699
5911
|
});
|
|
5700
|
-
var
|
|
5912
|
+
var app28 = new Hono28().use("*", authMiddleware).get("/", async (c) => {
|
|
5701
5913
|
const user = c.get("user");
|
|
5702
5914
|
const convs = await listConversationsWithParticipants(user.id);
|
|
5703
5915
|
return c.json(convs);
|
|
@@ -5709,7 +5921,7 @@ var app27 = new Hono27().use("*", authMiddleware).get("/", async (c) => {
|
|
|
5709
5921
|
}
|
|
5710
5922
|
const msgs = await getMessages(id);
|
|
5711
5923
|
return c.json(msgs);
|
|
5712
|
-
}).post("/",
|
|
5924
|
+
}).post("/", zValidator12("json", createSchema3), async (c) => {
|
|
5713
5925
|
const user = c.get("user");
|
|
5714
5926
|
const body = c.req.valid("json");
|
|
5715
5927
|
const participantIds = /* @__PURE__ */ new Set();
|
|
@@ -5756,11 +5968,11 @@ var app27 = new Hono27().use("*", authMiddleware).get("/", async (c) => {
|
|
|
5756
5968
|
if (!stream.aborted) console.error("[chat] SSE ping error:", err);
|
|
5757
5969
|
});
|
|
5758
5970
|
}, 15e3);
|
|
5759
|
-
await new Promise((
|
|
5971
|
+
await new Promise((resolve20) => {
|
|
5760
5972
|
stream.onAbort(() => {
|
|
5761
5973
|
unsubscribe();
|
|
5762
5974
|
clearInterval(keepAlive);
|
|
5763
|
-
|
|
5975
|
+
resolve20();
|
|
5764
5976
|
});
|
|
5765
5977
|
});
|
|
5766
5978
|
});
|
|
@@ -5771,12 +5983,12 @@ var app27 = new Hono27().use("*", authMiddleware).get("/", async (c) => {
|
|
|
5771
5983
|
if (!deleted) return c.json({ error: "Conversation not found" }, 404);
|
|
5772
5984
|
return c.json({ ok: true });
|
|
5773
5985
|
});
|
|
5774
|
-
var user_conversations_default =
|
|
5986
|
+
var user_conversations_default = app28;
|
|
5775
5987
|
|
|
5776
5988
|
// src/web/app.ts
|
|
5777
5989
|
var httpLog = logger_default.child("http");
|
|
5778
|
-
var
|
|
5779
|
-
|
|
5990
|
+
var app29 = new Hono29();
|
|
5991
|
+
app29.onError((err, c) => {
|
|
5780
5992
|
if (err instanceof HTTPException) {
|
|
5781
5993
|
return err.getResponse();
|
|
5782
5994
|
}
|
|
@@ -5787,10 +5999,10 @@ app28.onError((err, c) => {
|
|
|
5787
5999
|
});
|
|
5788
6000
|
return c.json({ error: "Internal server error" }, 500);
|
|
5789
6001
|
});
|
|
5790
|
-
|
|
6002
|
+
app29.notFound((c) => {
|
|
5791
6003
|
return c.json({ error: "Not found" }, 404);
|
|
5792
6004
|
});
|
|
5793
|
-
|
|
6005
|
+
app29.use("*", async (c, next) => {
|
|
5794
6006
|
const start = Date.now();
|
|
5795
6007
|
await next();
|
|
5796
6008
|
const duration = Date.now() - start;
|
|
@@ -5801,7 +6013,7 @@ app28.use("*", async (c, next) => {
|
|
|
5801
6013
|
httpLog.debug("request", data);
|
|
5802
6014
|
}
|
|
5803
6015
|
});
|
|
5804
|
-
|
|
6016
|
+
app29.get("/api/health", (c) => {
|
|
5805
6017
|
let version = "unknown";
|
|
5806
6018
|
let cached = null;
|
|
5807
6019
|
try {
|
|
@@ -5816,38 +6028,39 @@ app28.get("/api/health", (c) => {
|
|
|
5816
6028
|
...cached?.updateAvailable ? { updateAvailable: true, latest: cached.latest } : {}
|
|
5817
6029
|
});
|
|
5818
6030
|
});
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
6031
|
+
app29.use("/api/*", bodyLimit({ maxSize: 10 * 1024 * 1024 }));
|
|
6032
|
+
app29.use("/api/*", csrf());
|
|
6033
|
+
app29.use("/api/activity/*", authMiddleware);
|
|
6034
|
+
app29.use("/api/minds/*", authMiddleware);
|
|
6035
|
+
app29.use("/api/conversations/*", authMiddleware);
|
|
6036
|
+
app29.use("/api/volute/*", authMiddleware);
|
|
6037
|
+
app29.use("/api/system/*", authMiddleware);
|
|
6038
|
+
app29.use("/api/env/*", authMiddleware);
|
|
6039
|
+
app29.use("/api/prompts/*", authMiddleware);
|
|
6040
|
+
app29.use("/api/skills/*", authMiddleware);
|
|
6041
|
+
app29.use("/api/v1/*", authMiddleware);
|
|
6042
|
+
app29.route("/pages", pages_default);
|
|
6043
|
+
app29.route("/public", public_files_default);
|
|
6044
|
+
var routes = app29.route("/api/activity", activity_default).route("/api/keys", keys_default).route("/api/auth", auth_default).route("/api/system", system_default).route("/api/system", update_default).route("/api/minds", minds_default).route("/api/minds", chat_default2).route("/api/minds", connectors_default).route("/api/minds", schedules_default).route("/api/minds", logs_default).route("/api/minds", typing_default).route("/api/minds", variants_default).route("/api/minds", file_sharing_default).route("/api/minds", files_default).route("/api/minds", channels_default).route("/api/minds", shared_default).route("/api/minds", env_default).route("/api/minds", mind_skills_default).route("/api/minds", conversations_default2).route("/api/env", sharedEnvApp).route("/api/prompts", prompts_default).route("/api/skills", skills_default).route("/api/conversations", user_conversations_default).route("/api/volute/channels", channels_default2).route("/api/volute", unifiedChatApp).route("/api/v1/conversations", conversations_default).route("/api/v1/events", events_default).route("/api/v1", chat_default);
|
|
6045
|
+
app29.route("/api/v1/minds", minds_default);
|
|
6046
|
+
app29.route("/api/v1/minds", typing_default);
|
|
6047
|
+
app29.route("/api/v1/minds", variants_default);
|
|
6048
|
+
app29.route("/api/v1/minds", files_default);
|
|
6049
|
+
app29.route("/api/v1/minds", env_default);
|
|
6050
|
+
app29.route("/api/v1/minds", mind_skills_default);
|
|
6051
|
+
app29.route("/api/v1/minds", connectors_default);
|
|
6052
|
+
app29.route("/api/v1/minds", schedules_default);
|
|
6053
|
+
app29.route("/api/v1/minds", logs_default);
|
|
6054
|
+
app29.route("/api/v1/system", system_default);
|
|
6055
|
+
app29.route("/api/v1/system", update_default);
|
|
6056
|
+
app29.route("/api/v1/prompts", prompts_default);
|
|
6057
|
+
app29.route("/api/v1/skills", skills_default);
|
|
6058
|
+
app29.route("/api/v1/env", sharedEnvApp);
|
|
6059
|
+
app29.route("/api/v1/channels", channels_default2);
|
|
6060
|
+
var app_default = app29;
|
|
5848
6061
|
|
|
5849
6062
|
// src/web/server.ts
|
|
5850
|
-
var
|
|
6063
|
+
var MIME_TYPES3 = {
|
|
5851
6064
|
".html": "text/html",
|
|
5852
6065
|
".js": "application/javascript",
|
|
5853
6066
|
".css": "text/css",
|
|
@@ -5864,7 +6077,7 @@ async function startServer({
|
|
|
5864
6077
|
let assetsDir = "";
|
|
5865
6078
|
let searchDir = dirname(new URL(import.meta.url).pathname);
|
|
5866
6079
|
for (let i = 0; i < 5; i++) {
|
|
5867
|
-
const candidate =
|
|
6080
|
+
const candidate = resolve18(searchDir, "dist", "web-assets");
|
|
5868
6081
|
if (existsSync13(candidate)) {
|
|
5869
6082
|
assetsDir = candidate;
|
|
5870
6083
|
break;
|
|
@@ -5875,19 +6088,19 @@ async function startServer({
|
|
|
5875
6088
|
app_default.get("*", async (c) => {
|
|
5876
6089
|
const urlPath = new URL(c.req.url).pathname;
|
|
5877
6090
|
if (urlPath.startsWith("/api/")) return c.notFound();
|
|
5878
|
-
const filePath =
|
|
6091
|
+
const filePath = resolve18(assetsDir, urlPath.slice(1));
|
|
5879
6092
|
if (!filePath.startsWith(assetsDir)) return c.text("Forbidden", 403);
|
|
5880
|
-
const s = await
|
|
6093
|
+
const s = await stat4(filePath).catch(() => null);
|
|
5881
6094
|
if (s?.isFile()) {
|
|
5882
|
-
const ext =
|
|
5883
|
-
const mime =
|
|
5884
|
-
const body = await
|
|
6095
|
+
const ext = extname5(filePath);
|
|
6096
|
+
const mime = MIME_TYPES3[ext] || "application/octet-stream";
|
|
6097
|
+
const body = await readFile4(filePath);
|
|
5885
6098
|
return c.body(body, 200, { "Content-Type": mime });
|
|
5886
6099
|
}
|
|
5887
|
-
const indexPath =
|
|
5888
|
-
const indexStat = await
|
|
6100
|
+
const indexPath = resolve18(assetsDir, "index.html");
|
|
6101
|
+
const indexStat = await stat4(indexPath).catch(() => null);
|
|
5889
6102
|
if (indexStat?.isFile()) {
|
|
5890
|
-
const body = await
|
|
6103
|
+
const body = await readFile4(indexPath, "utf-8");
|
|
5891
6104
|
return c.html(body);
|
|
5892
6105
|
}
|
|
5893
6106
|
return c.text("Not found", 404);
|
|
@@ -5901,10 +6114,10 @@ async function startServer({
|
|
|
5901
6114
|
createServer: createHttpsServer,
|
|
5902
6115
|
serverOptions: { key: tls.key, cert: tls.cert }
|
|
5903
6116
|
});
|
|
5904
|
-
await new Promise((
|
|
6117
|
+
await new Promise((resolve20, reject) => {
|
|
5905
6118
|
server2.on("listening", () => {
|
|
5906
6119
|
logger_default.info("Volute UI running (https)", { hostname, port });
|
|
5907
|
-
|
|
6120
|
+
resolve20();
|
|
5908
6121
|
});
|
|
5909
6122
|
server2.on("error", (err) => {
|
|
5910
6123
|
reject(err);
|
|
@@ -5912,13 +6125,13 @@ async function startServer({
|
|
|
5912
6125
|
});
|
|
5913
6126
|
const internalPort = port + 1;
|
|
5914
6127
|
const internalServer = serve({ fetch: app_default.fetch, port: internalPort, hostname: "127.0.0.1" });
|
|
5915
|
-
await new Promise((
|
|
6128
|
+
await new Promise((resolve20, reject) => {
|
|
5916
6129
|
internalServer.on("listening", () => {
|
|
5917
6130
|
logger_default.info("Volute API running (http, internal)", {
|
|
5918
6131
|
hostname: "127.0.0.1",
|
|
5919
6132
|
port: internalPort
|
|
5920
6133
|
});
|
|
5921
|
-
|
|
6134
|
+
resolve20();
|
|
5922
6135
|
});
|
|
5923
6136
|
internalServer.on("error", (err) => {
|
|
5924
6137
|
reject(err);
|
|
@@ -5927,10 +6140,10 @@ async function startServer({
|
|
|
5927
6140
|
return { server: server2, internalPort };
|
|
5928
6141
|
}
|
|
5929
6142
|
const server = serve({ fetch: app_default.fetch, port, hostname });
|
|
5930
|
-
await new Promise((
|
|
6143
|
+
await new Promise((resolve20, reject) => {
|
|
5931
6144
|
server.on("listening", () => {
|
|
5932
6145
|
logger_default.info("Volute API running (http)", { hostname, port });
|
|
5933
|
-
|
|
6146
|
+
resolve20();
|
|
5934
6147
|
});
|
|
5935
6148
|
server.on("error", (err) => {
|
|
5936
6149
|
reject(err);
|
|
@@ -5941,7 +6154,7 @@ async function startServer({
|
|
|
5941
6154
|
|
|
5942
6155
|
// src/daemon.ts
|
|
5943
6156
|
if (!process.env.VOLUTE_HOME) {
|
|
5944
|
-
process.env.VOLUTE_HOME =
|
|
6157
|
+
process.env.VOLUTE_HOME = resolve19(homedir2(), ".volute");
|
|
5945
6158
|
}
|
|
5946
6159
|
if (process.env.VOLUTE_TIMEZONE && !process.env.TZ) {
|
|
5947
6160
|
process.env.TZ = process.env.VOLUTE_TIMEZONE;
|
|
@@ -5951,7 +6164,7 @@ async function startDaemon(opts) {
|
|
|
5951
6164
|
const myPid = String(process.pid);
|
|
5952
6165
|
const home = voluteHome();
|
|
5953
6166
|
if (!opts.foreground) {
|
|
5954
|
-
const rotatingLog = new RotatingLog(
|
|
6167
|
+
const rotatingLog = new RotatingLog(resolve19(home, "daemon.log"));
|
|
5955
6168
|
logger_default.setOutput((line) => rotatingLog.write(`${line}
|
|
5956
6169
|
`));
|
|
5957
6170
|
const write = (...args) => rotatingLog.write(`${format(...args)}
|
|
@@ -5961,8 +6174,8 @@ async function startDaemon(opts) {
|
|
|
5961
6174
|
console.warn = write;
|
|
5962
6175
|
console.info = write;
|
|
5963
6176
|
}
|
|
5964
|
-
const DAEMON_PID_PATH =
|
|
5965
|
-
const DAEMON_JSON_PATH =
|
|
6177
|
+
const DAEMON_PID_PATH = resolve19(home, "daemon.pid");
|
|
6178
|
+
const DAEMON_JSON_PATH = resolve19(home, "daemon.json");
|
|
5966
6179
|
mkdirSync9(home, { recursive: true });
|
|
5967
6180
|
migrateAgentsToMinds();
|
|
5968
6181
|
try {
|
|
@@ -6021,11 +6234,12 @@ async function startDaemon(opts) {
|
|
|
6021
6234
|
const unsubscribeWebhook = initWebhook();
|
|
6022
6235
|
const registry = readRegistry();
|
|
6023
6236
|
for (const entry of registry) {
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6237
|
+
for (const migrate of [migrateDotVoluteDir, migrateMindState, migratePagesDirToPublic]) {
|
|
6238
|
+
try {
|
|
6239
|
+
migrate(entry.name);
|
|
6240
|
+
} catch (err) {
|
|
6241
|
+
logger_default.warn(`failed to migrate state for ${entry.name}`, logger_default.errorData(err));
|
|
6242
|
+
}
|
|
6029
6243
|
}
|
|
6030
6244
|
}
|
|
6031
6245
|
const runningEntries = registry.filter((e) => e.running);
|
|
@@ -6075,7 +6289,7 @@ async function startDaemon(opts) {
|
|
|
6075
6289
|
});
|
|
6076
6290
|
await Promise.all(workers);
|
|
6077
6291
|
}
|
|
6078
|
-
import("./cloud-sync-
|
|
6292
|
+
import("./cloud-sync-PPBBJDY6.js").then(
|
|
6079
6293
|
({ consumeQueuedMessages }) => consumeQueuedMessages().catch((err) => {
|
|
6080
6294
|
logger_default.warn("failed to consume queued cloud messages", logger_default.errorData(err));
|
|
6081
6295
|
})
|
|
@@ -6083,7 +6297,7 @@ async function startDaemon(opts) {
|
|
|
6083
6297
|
logger_default.warn("failed to load cloud-sync module", logger_default.errorData(err));
|
|
6084
6298
|
});
|
|
6085
6299
|
try {
|
|
6086
|
-
const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-
|
|
6300
|
+
const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-AZQMC32A.js");
|
|
6087
6301
|
backfillTemplateHashes();
|
|
6088
6302
|
notifyVersionUpdate().catch((err) => {
|
|
6089
6303
|
logger_default.warn("failed to send version update notifications", logger_default.errorData(err));
|