volute 0.51.0 → 0.52.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/{auth-X6EMNEGB.js → auth-KRDSM55Q.js} +3 -1
- package/dist/{chunk-VAEZCIJC.js → chunk-724DVYHU.js} +8 -8
- package/dist/{chunk-HKP6OAJP.js → chunk-7LT3YZUR.js} +12 -0
- package/dist/{chunk-ICL6T4SN.js → chunk-AXFLY5GU.js} +11 -2
- package/dist/{chunk-DN3LKLYR.js → chunk-CW7BQKF6.js} +3 -3
- package/dist/{chunk-AI47FDGL.js → chunk-ITK6HV47.js} +1 -1
- package/dist/{chunk-VSBMLB2W.js → chunk-K2F237KS.js} +2 -2
- package/dist/{chunk-QT4D5XCI.js → chunk-RPPTGPYF.js} +1 -1
- package/dist/{chunk-7HN63Q7J.js → chunk-RU74YG46.js} +5 -5
- package/dist/{chunk-Q7XQLKZB.js → chunk-SW2U6HRB.js} +2 -2
- package/dist/{chunk-BSHZ23MS.js → chunk-XRWUQPCA.js} +2 -2
- package/dist/{chunk-CDKQJWGK.js → chunk-YVR6EHWL.js} +2 -2
- package/dist/{chunk-VP5PFNZO.js → chunk-ZEZQNP2G.js} +35 -19
- package/dist/cli.js +6 -6
- package/dist/{cloud-sync-GPXYPTIC.js → cloud-sync-H7EWZASD.js} +9 -9
- package/dist/{daemon-restart-2EWBRTN5.js → daemon-restart-4FWUA5JF.js} +1 -1
- package/dist/daemon.js +321 -186
- package/dist/{delete-O7PEFQDF.js → delete-CYVZUAV2.js} +4 -0
- package/dist/{delivery-manager-HGVZSEES.js → delivery-manager-VYXVKUMP.js} +4 -4
- package/dist/{echo-text-6ANI5HHN.js → echo-text-PEEV7FQU.js} +10 -10
- package/dist/{extensions-NY6WST33.js → extensions-N6L5NYTK.js} +9 -9
- package/dist/{join-PYA36HEC.js → join-KLRU72JJ.js} +10 -2
- package/dist/{message-delivery-JHMAJ2GU.js → message-delivery-7URC52ME.js} +9 -9
- package/dist/{mind-WF6QIXWV.js → mind-NEXGT3KE.js} +4 -4
- package/dist/{mind-service-DZCUUC7J.js → mind-service-E26ZQXDS.js} +9 -9
- package/dist/{package-B6O5APCZ.js → package-2W2XKSIP.js} +2 -2
- package/dist/{scheduler-TNBN54ZK.js → scheduler-JTTWZDYU.js} +4 -4
- package/dist/{seed-K2LYODIH.js → seed-64XEHRUP.js} +1 -1
- package/dist/{seed-cmd-2EWBTR6P.js → seed-cmd-UEL2QB3Q.js} +2 -2
- package/dist/{seed-create-VGTLU5FD.js → seed-create-4JRQDPGA.js} +1 -1
- package/dist/{seed-sprout-PILHJ3YS.js → seed-sprout-NIDIOJXT.js} +2 -2
- package/dist/{setup-MDPSK2XG.js → setup-4IX6PCD3.js} +1 -1
- package/dist/skills/volute-mind/references/variants.md +1 -1
- package/dist/{skills-NH2GQKAF.js → skills-MPUALV3S.js} +1 -1
- package/dist/{sleep-manager-7JXEQQ2P.js → sleep-manager-OFP2GFXF.js} +9 -9
- package/dist/{spirit-25JVAL3M.js → spirit-4ECYIVGE.js} +2 -2
- package/dist/{spirit-availability-PJDWZJ3J.js → spirit-availability-Y54Y3675.js} +10 -10
- package/dist/{sprout-EXUZMIOR.js → sprout-GJMZFRGZ.js} +1 -1
- package/dist/{system-events-ZPSH63QX.js → system-events-V43HDA3T.js} +3 -1
- package/dist/{turn-tracker-TAT2HGK6.js → turn-tracker-C5PVIC3B.js} +1 -1
- package/dist/{up-J7XCAH7P.js → up-H6LJZDRK.js} +1 -1
- package/dist/{variant-cleanup-YXN25ZVW.js → variant-cleanup-STC6B5HR.js} +4 -4
- package/dist/{version-notify-EN3KJ7HH.js → version-notify-LBVHH5YV.js} +1 -1
- package/dist/web-assets/assets/index-B_eYTa3R.js +97 -0
- package/dist/web-assets/assets/{index-BOyJ4Gqs.css → index-DhZrzddW.css} +1 -1
- package/dist/web-assets/index.html +2 -2
- package/package.json +2 -2
- package/templates/_base/src/lib/auto-commit.ts +49 -11
- package/dist/web-assets/assets/index-CrxBwnzp.js +0 -95
- /package/dist/{chunk-IWAVIJO2.js → chunk-VPOMJMV6.js} +0 -0
package/dist/daemon.js
CHANGED
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
import {
|
|
25
25
|
SPIRIT_NOTICE_PREFIX,
|
|
26
26
|
ensureSpiritAvailable
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-CW7BQKF6.js";
|
|
28
28
|
import {
|
|
29
29
|
isHomeOnlyArchive
|
|
30
30
|
} from "./chunk-FLIEXG2T.js";
|
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
} from "./chunk-HTRSSOHY.js";
|
|
40
40
|
import {
|
|
41
41
|
cleanupVariant
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-ITK6HV47.js";
|
|
43
43
|
import {
|
|
44
44
|
checkForUpdate,
|
|
45
45
|
checkForUpdateCached,
|
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
fixModelEscapes,
|
|
52
52
|
getPlatformDriver,
|
|
53
53
|
routeOutboundBridge
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-XRWUQPCA.js";
|
|
55
55
|
import {
|
|
56
56
|
getBridgeConfig,
|
|
57
57
|
readBridgesConfig,
|
|
@@ -105,8 +105,8 @@ import {
|
|
|
105
105
|
stopMindFull,
|
|
106
106
|
uninstallNpmExtension,
|
|
107
107
|
writeSystemsConfig
|
|
108
|
-
} from "./chunk-
|
|
109
|
-
import "./chunk-
|
|
108
|
+
} from "./chunk-ZEZQNP2G.js";
|
|
109
|
+
import "./chunk-K2F237KS.js";
|
|
110
110
|
import {
|
|
111
111
|
applyInitFiles,
|
|
112
112
|
applyTemplateHomeFiles,
|
|
@@ -119,7 +119,7 @@ import {
|
|
|
119
119
|
import {
|
|
120
120
|
getScheduler,
|
|
121
121
|
initScheduler
|
|
122
|
-
} from "./chunk-
|
|
122
|
+
} from "./chunk-SW2U6HRB.js";
|
|
123
123
|
import {
|
|
124
124
|
checkStaleSend,
|
|
125
125
|
formatHoldNotice,
|
|
@@ -128,7 +128,7 @@ import {
|
|
|
128
128
|
initDeliveryManager,
|
|
129
129
|
isConversationId,
|
|
130
130
|
publishTypingForChannels
|
|
131
|
-
} from "./chunk-
|
|
131
|
+
} from "./chunk-RU74YG46.js";
|
|
132
132
|
import {
|
|
133
133
|
MindStartupError,
|
|
134
134
|
RestartTracker,
|
|
@@ -138,7 +138,7 @@ import {
|
|
|
138
138
|
initMindManager,
|
|
139
139
|
syncProviderToMinds,
|
|
140
140
|
tryGetMindManager
|
|
141
|
-
} from "./chunk-
|
|
141
|
+
} from "./chunk-724DVYHU.js";
|
|
142
142
|
import {
|
|
143
143
|
extractTextContent
|
|
144
144
|
} from "./chunk-UDZLPR34.js";
|
|
@@ -161,7 +161,7 @@ import {
|
|
|
161
161
|
takeErrored,
|
|
162
162
|
trackToolUse,
|
|
163
163
|
utcDateTimeStr
|
|
164
|
-
} from "./chunk-
|
|
164
|
+
} from "./chunk-YVR6EHWL.js";
|
|
165
165
|
import {
|
|
166
166
|
SEED_SKILLS,
|
|
167
167
|
STANDARD_SKILLS,
|
|
@@ -183,12 +183,13 @@ import {
|
|
|
183
183
|
syncBuiltinSkills,
|
|
184
184
|
uninstallSkill,
|
|
185
185
|
updateSkill
|
|
186
|
-
} from "./chunk-
|
|
186
|
+
} from "./chunk-RPPTGPYF.js";
|
|
187
187
|
import {
|
|
188
188
|
approveUser,
|
|
189
189
|
changePassword,
|
|
190
190
|
countAdmins,
|
|
191
191
|
createUser,
|
|
192
|
+
deleteExternalMindUser,
|
|
192
193
|
deleteMindUser as deleteMindUser2,
|
|
193
194
|
deleteUser,
|
|
194
195
|
getDisplayNames,
|
|
@@ -204,9 +205,10 @@ import {
|
|
|
204
205
|
updateUserProfile,
|
|
205
206
|
verifyUser,
|
|
206
207
|
withSenderDisplayNames
|
|
207
|
-
} from "./chunk-
|
|
208
|
+
} from "./chunk-7LT3YZUR.js";
|
|
208
209
|
import {
|
|
209
210
|
captureReflection,
|
|
211
|
+
cleanExpiredEvents,
|
|
210
212
|
clearDeliveredEvents,
|
|
211
213
|
deliverEvent,
|
|
212
214
|
drainEvents,
|
|
@@ -217,7 +219,7 @@ import {
|
|
|
217
219
|
listEvents,
|
|
218
220
|
parseMeta,
|
|
219
221
|
recordNotice
|
|
220
|
-
} from "./chunk-
|
|
222
|
+
} from "./chunk-AXFLY5GU.js";
|
|
221
223
|
import {
|
|
222
224
|
publish as publish2,
|
|
223
225
|
subscribe as subscribe2,
|
|
@@ -397,7 +399,7 @@ import "./chunk-K3NQKI34.js";
|
|
|
397
399
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
398
400
|
import { chmodSync, mkdirSync as mkdirSync10, readFileSync as readFileSync12, unlinkSync as unlinkSync2, writeFileSync as writeFileSync10 } from "fs";
|
|
399
401
|
import { homedir as homedir3 } from "os";
|
|
400
|
-
import { resolve as
|
|
402
|
+
import { resolve as resolve20 } from "path";
|
|
401
403
|
import { format } from "util";
|
|
402
404
|
|
|
403
405
|
// packages/daemon/src/lib/daemon/backup-manager.ts
|
|
@@ -508,7 +510,7 @@ var BackupManager = class {
|
|
|
508
510
|
} catch (pubErr) {
|
|
509
511
|
blog.error("failed to publish backup-failure activity", logger_default.errorData(pubErr));
|
|
510
512
|
}
|
|
511
|
-
const { deliverEvent: deliverEvent2 } = await import("./system-events-
|
|
513
|
+
const { deliverEvent: deliverEvent2 } = await import("./system-events-V43HDA3T.js");
|
|
512
514
|
await deliverEvent2(getSpiritName(), {
|
|
513
515
|
type: "notice",
|
|
514
516
|
meta: { subtype: "backup" },
|
|
@@ -732,8 +734,8 @@ var BridgeManager = class {
|
|
|
732
734
|
if (!tracked) return;
|
|
733
735
|
this.stopping.add(platform);
|
|
734
736
|
this.bridges.delete(platform);
|
|
735
|
-
await new Promise((
|
|
736
|
-
tracked.child.on("exit", () =>
|
|
737
|
+
await new Promise((resolve21) => {
|
|
738
|
+
tracked.child.on("exit", () => resolve21());
|
|
737
739
|
try {
|
|
738
740
|
if (tracked.child.pid) {
|
|
739
741
|
process.kill(-tracked.child.pid, "SIGTERM");
|
|
@@ -744,7 +746,7 @@ var BridgeManager = class {
|
|
|
744
746
|
if (err instanceof Error && err.code !== "ESRCH") {
|
|
745
747
|
blog2.warn(`failed to stop bridge ${platform}`, logger_default.errorData(err));
|
|
746
748
|
}
|
|
747
|
-
|
|
749
|
+
resolve21();
|
|
748
750
|
}
|
|
749
751
|
setTimeout(() => {
|
|
750
752
|
try {
|
|
@@ -755,7 +757,7 @@ var BridgeManager = class {
|
|
|
755
757
|
}
|
|
756
758
|
} catch {
|
|
757
759
|
}
|
|
758
|
-
|
|
760
|
+
resolve21();
|
|
759
761
|
}, 5e3);
|
|
760
762
|
});
|
|
761
763
|
this.stopping.delete(platform);
|
|
@@ -865,6 +867,11 @@ async function runMaintenance() {
|
|
|
865
867
|
} catch (err) {
|
|
866
868
|
logger_default.warn("maintenance: failed to clean expired logs", logger_default.errorData(err));
|
|
867
869
|
}
|
|
870
|
+
try {
|
|
871
|
+
await cleanExpiredEvents();
|
|
872
|
+
} catch (err) {
|
|
873
|
+
logger_default.warn("maintenance: failed to clean expired events", logger_default.errorData(err));
|
|
874
|
+
}
|
|
868
875
|
}
|
|
869
876
|
function startMaintenanceInterval(intervalMs = MAINTENANCE_INTERVAL_MS, task = runMaintenance) {
|
|
870
877
|
const handle = setInterval(() => void task(), intervalMs);
|
|
@@ -1427,10 +1434,10 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
1427
1434
|
stream.writeSSE({ data: JSON.stringify(entry) }).catch(() => {
|
|
1428
1435
|
});
|
|
1429
1436
|
});
|
|
1430
|
-
await new Promise((
|
|
1437
|
+
await new Promise((resolve21) => {
|
|
1431
1438
|
stream.onAbort(() => {
|
|
1432
1439
|
unsubscribe();
|
|
1433
|
-
|
|
1440
|
+
resolve21();
|
|
1434
1441
|
});
|
|
1435
1442
|
});
|
|
1436
1443
|
});
|
|
@@ -1455,7 +1462,7 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
1455
1462
|
config2.name = name.trim() || void 0;
|
|
1456
1463
|
writeGlobalConfig(config2);
|
|
1457
1464
|
if (config2.name !== previousName) {
|
|
1458
|
-
const { notifySpiritSystemChange } = await import("./spirit-
|
|
1465
|
+
const { notifySpiritSystemChange } = await import("./spirit-4ECYIVGE.js");
|
|
1459
1466
|
await notifySpiritSystemChange();
|
|
1460
1467
|
}
|
|
1461
1468
|
return c.json({ name: config2.name ?? null });
|
|
@@ -1814,8 +1821,8 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
1814
1821
|
createdAt: Date.now()
|
|
1815
1822
|
};
|
|
1816
1823
|
oauthFlows.set(flowId, flow);
|
|
1817
|
-
const promptPromise = needsManualCode ? new Promise((
|
|
1818
|
-
flow.resolveCode =
|
|
1824
|
+
const promptPromise = needsManualCode ? new Promise((resolve21) => {
|
|
1825
|
+
flow.resolveCode = resolve21;
|
|
1819
1826
|
}) : void 0;
|
|
1820
1827
|
oauthProvider.login({
|
|
1821
1828
|
onAuth: (info) => {
|
|
@@ -1854,7 +1861,7 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
1854
1861
|
existing.error = err instanceof Error ? err.message : String(err);
|
|
1855
1862
|
}
|
|
1856
1863
|
});
|
|
1857
|
-
await new Promise((
|
|
1864
|
+
await new Promise((resolve21) => setTimeout(resolve21, 2e3));
|
|
1858
1865
|
const state = oauthFlows.get(flowId);
|
|
1859
1866
|
return c.json({
|
|
1860
1867
|
flowId,
|
|
@@ -2115,8 +2122,8 @@ var app2 = new Hono2().get("/events", async (c) => {
|
|
|
2115
2122
|
});
|
|
2116
2123
|
}, 15e3);
|
|
2117
2124
|
cleanups.push(() => clearInterval(keepAlive));
|
|
2118
|
-
await new Promise((
|
|
2119
|
-
stream.onAbort(() =>
|
|
2125
|
+
await new Promise((resolve21) => {
|
|
2126
|
+
stream.onAbort(() => resolve21());
|
|
2120
2127
|
});
|
|
2121
2128
|
} finally {
|
|
2122
2129
|
for (const cleanup of cleanups) {
|
|
@@ -2149,6 +2156,11 @@ function isNotModified(c, etag) {
|
|
|
2149
2156
|
}
|
|
2150
2157
|
|
|
2151
2158
|
// packages/daemon/src/web/api/auth.ts
|
|
2159
|
+
async function withExternalFlag(list) {
|
|
2160
|
+
if (!list.some((u) => u.user_type === "mind")) return list;
|
|
2161
|
+
const local = new Set((await readAllMinds()).map((m) => m.name));
|
|
2162
|
+
return list.map((u) => u.user_type === "mind" ? { ...u, external: !local.has(u.username) } : u);
|
|
2163
|
+
}
|
|
2152
2164
|
function tryJoinSystem(userId) {
|
|
2153
2165
|
if (!process.env.VOLUTE_DAEMON_TOKEN) return;
|
|
2154
2166
|
joinSystemChannel(userId).catch(() => {
|
|
@@ -2302,9 +2314,9 @@ var admin = new Hono3().use(authMiddleware).get("/users", async (c) => {
|
|
|
2302
2314
|
}
|
|
2303
2315
|
const type = c.req.query("type");
|
|
2304
2316
|
if (type === "human" || type === "mind") {
|
|
2305
|
-
return c.json(await listUsersByType(type));
|
|
2317
|
+
return c.json(await withExternalFlag(await listUsersByType(type)));
|
|
2306
2318
|
}
|
|
2307
|
-
return c.json(await listUsers());
|
|
2319
|
+
return c.json(await withExternalFlag(await listUsers()));
|
|
2308
2320
|
}).get("/users/pending", async (c) => {
|
|
2309
2321
|
const user = c.get("user");
|
|
2310
2322
|
if (user.role !== "admin") return c.json({ error: "Forbidden" }, 403);
|
|
@@ -2401,7 +2413,11 @@ var admin = new Hono3().use(authMiddleware).get("/users", async (c) => {
|
|
|
2401
2413
|
if (adminCount <= 1) return c.json({ error: "Cannot delete the last admin" }, 400);
|
|
2402
2414
|
}
|
|
2403
2415
|
if (target.user_type === "mind") {
|
|
2404
|
-
|
|
2416
|
+
if (await findMind(target.username)) {
|
|
2417
|
+
return c.json({ error: "Use the mind deletion API to delete minds" }, 400);
|
|
2418
|
+
}
|
|
2419
|
+
await deleteExternalMindUser(id);
|
|
2420
|
+
return c.json({ ok: true });
|
|
2405
2421
|
}
|
|
2406
2422
|
await deleteUser(id);
|
|
2407
2423
|
return c.json({ ok: true });
|
|
@@ -2668,7 +2684,7 @@ async function fanOutToMinds(opts) {
|
|
|
2668
2684
|
);
|
|
2669
2685
|
}
|
|
2670
2686
|
if (ap.userType === "system") {
|
|
2671
|
-
import("./spirit-availability-
|
|
2687
|
+
import("./spirit-availability-Y54Y3675.js").then(({ ensureSpiritAvailable: ensureSpiritAvailable2 }) => ensureSpiritAvailable2()).catch((err) => logger_default.warn("fan-out: on-demand spirit start failed", logger_default.errorData(err)));
|
|
2672
2688
|
}
|
|
2673
2689
|
}
|
|
2674
2690
|
return null;
|
|
@@ -3055,7 +3071,7 @@ async function notifyMind(mindName, message) {
|
|
|
3055
3071
|
const entry = await findMind(mindName);
|
|
3056
3072
|
if (!entry) return;
|
|
3057
3073
|
try {
|
|
3058
|
-
const { deliverEvent: deliverEvent2 } = await import("./system-events-
|
|
3074
|
+
const { deliverEvent: deliverEvent2 } = await import("./system-events-V43HDA3T.js");
|
|
3059
3075
|
await deliverEvent2(mindName, { type: "file-share", body: message });
|
|
3060
3076
|
} catch (err) {
|
|
3061
3077
|
logger_default.warn(`[file-sharing] notify mind ${mindName} failed`, logger_default.errorData(err));
|
|
@@ -4026,9 +4042,9 @@ var app11 = new Hono14().get("/:name/logs", requireSelf(), async (c) => {
|
|
|
4026
4042
|
stream.onAbort(() => {
|
|
4027
4043
|
tail.kill();
|
|
4028
4044
|
});
|
|
4029
|
-
await new Promise((
|
|
4030
|
-
tail.on("exit",
|
|
4031
|
-
stream.onAbort(
|
|
4045
|
+
await new Promise((resolve21) => {
|
|
4046
|
+
tail.on("exit", resolve21);
|
|
4047
|
+
stream.onAbort(resolve21);
|
|
4032
4048
|
});
|
|
4033
4049
|
});
|
|
4034
4050
|
}).get("/:name/logs/tail", requireSelf(), async (c) => {
|
|
@@ -4046,8 +4062,8 @@ var app11 = new Hono14().get("/:name/logs", requireSelf(), async (c) => {
|
|
|
4046
4062
|
tail.stdout.on("data", (data) => {
|
|
4047
4063
|
output += data.toString();
|
|
4048
4064
|
});
|
|
4049
|
-
await new Promise((
|
|
4050
|
-
tail.on("exit",
|
|
4065
|
+
await new Promise((resolve21) => {
|
|
4066
|
+
tail.on("exit", resolve21);
|
|
4051
4067
|
});
|
|
4052
4068
|
return c.text(output);
|
|
4053
4069
|
});
|
|
@@ -4147,7 +4163,7 @@ import {
|
|
|
4147
4163
|
rmSync as rmSync3,
|
|
4148
4164
|
writeFileSync as writeFileSync8
|
|
4149
4165
|
} from "fs";
|
|
4150
|
-
import { relative, resolve as
|
|
4166
|
+
import { relative, resolve as resolve13 } from "path";
|
|
4151
4167
|
import { zValidator as zValidator6 } from "@hono/zod-validator";
|
|
4152
4168
|
import { and as and5, desc as desc3, eq as eq5, sql as sql3 } from "drizzle-orm";
|
|
4153
4169
|
import { Hono as Hono16 } from "hono";
|
|
@@ -4675,6 +4691,8 @@ function deriveThinkingLevel(config2) {
|
|
|
4675
4691
|
}
|
|
4676
4692
|
|
|
4677
4693
|
// packages/daemon/src/lib/mind/variants.ts
|
|
4694
|
+
import { statSync as statSync3 } from "fs";
|
|
4695
|
+
import { resolve as resolve11 } from "path";
|
|
4678
4696
|
var SAFE_BRANCH_RE = /^[a-zA-Z0-9._\-/]+$/;
|
|
4679
4697
|
function validateBranchName(branch) {
|
|
4680
4698
|
if (!SAFE_BRANCH_RE.test(branch)) {
|
|
@@ -4687,6 +4705,55 @@ function validateBranchName(branch) {
|
|
|
4687
4705
|
}
|
|
4688
4706
|
var MERGE_EXCLUDED_PATHS = ["home/MEMORY.md", "home/memory/journal/"];
|
|
4689
4707
|
var MAX_DELTA_CHARS = 12e3;
|
|
4708
|
+
var NEVER_REPORT_PREFIXES = ["home/.claude/", "home/.pi/", "home/.agents/"];
|
|
4709
|
+
var MAX_LISTED_UNRESOLVED_FILES = 20;
|
|
4710
|
+
async function findUnresolvedHomeFiles(cwd) {
|
|
4711
|
+
const raw = await gitExec(
|
|
4712
|
+
["ls-files", "--others", "--ignored", "--exclude-standard", "-z", "--", "home"],
|
|
4713
|
+
{ cwd }
|
|
4714
|
+
);
|
|
4715
|
+
const allPaths = raw.split("\0").filter((path) => path && !NEVER_REPORT_PREFIXES.some((prefix) => path.startsWith(prefix)));
|
|
4716
|
+
const files = [];
|
|
4717
|
+
let totalBytes = 0;
|
|
4718
|
+
for (const path of allPaths) {
|
|
4719
|
+
let bytes = -1;
|
|
4720
|
+
try {
|
|
4721
|
+
bytes = statSync3(resolve11(cwd, path)).size;
|
|
4722
|
+
} catch {
|
|
4723
|
+
}
|
|
4724
|
+
if (bytes > 0) totalBytes += bytes;
|
|
4725
|
+
if (files.length < MAX_LISTED_UNRESOLVED_FILES) files.push({ path, bytes });
|
|
4726
|
+
}
|
|
4727
|
+
return { files, totalCount: allPaths.length, totalBytes };
|
|
4728
|
+
}
|
|
4729
|
+
function formatBytes(bytes) {
|
|
4730
|
+
if (bytes < 0) return "size unknown";
|
|
4731
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
4732
|
+
const units = ["KB", "MB", "GB", "TB"];
|
|
4733
|
+
let value = bytes / 1024;
|
|
4734
|
+
for (const unit of units) {
|
|
4735
|
+
if (value < 1024) return `${value.toFixed(1)} ${unit}`;
|
|
4736
|
+
value /= 1024;
|
|
4737
|
+
}
|
|
4738
|
+
return `${value.toFixed(1)} PB`;
|
|
4739
|
+
}
|
|
4740
|
+
function formatUnresolvedHomeFilesMessage(variantName, result) {
|
|
4741
|
+
const lines = result.files.map(
|
|
4742
|
+
(f) => ` - ${f.path.replace(/^home\//, "")} (${formatBytes(f.bytes)})`
|
|
4743
|
+
);
|
|
4744
|
+
const remaining = result.totalCount - result.files.length;
|
|
4745
|
+
if (remaining > 0) lines.push(` ...and ${remaining} more`);
|
|
4746
|
+
return `Cannot join variant "${variantName}": it has ${result.totalCount} untracked file${result.totalCount === 1 ? "" : "s"} under home/ that .gitignore is hiding from git \u2014 never committed, and joining would destroy them when the variant is cleaned up (total: ${formatBytes(result.totalBytes)}):
|
|
4747
|
+
|
|
4748
|
+
${lines.join("\n")}
|
|
4749
|
+
|
|
4750
|
+
Before retrying the join, resolve each file in the variant \u2014 one of:
|
|
4751
|
+
1. Track it: git add -f -- <path> (then commit it, or let auto-commit pick it up next turn)
|
|
4752
|
+
2. Copy it out of home/ to somewhere safe, then delete it
|
|
4753
|
+
3. Delete it if it's disposable
|
|
4754
|
+
|
|
4755
|
+
Once resolved, retry the join. To join anyway and discard everything listed above, pass discardUnresolved: true.`;
|
|
4756
|
+
}
|
|
4690
4757
|
async function mergeVariantExcludingMemory(projectRoot, variantBranch) {
|
|
4691
4758
|
const opts = { cwd: projectRoot };
|
|
4692
4759
|
let memoryDelta = "";
|
|
@@ -4889,7 +4956,7 @@ async function waitForImagegenJob(mind, id, timeoutMs) {
|
|
|
4889
4956
|
import { randomUUID } from "crypto";
|
|
4890
4957
|
import { mkdirSync as mkdirSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "fs";
|
|
4891
4958
|
import { homedir } from "os";
|
|
4892
|
-
import { resolve as
|
|
4959
|
+
import { resolve as resolve12 } from "path";
|
|
4893
4960
|
function convertSession(opts) {
|
|
4894
4961
|
const lines = readFileSync8(opts.sessionPath, "utf-8").trim().split("\n");
|
|
4895
4962
|
const sessionId = randomUUID();
|
|
@@ -5005,9 +5072,9 @@ function convertSession(opts) {
|
|
|
5005
5072
|
}
|
|
5006
5073
|
}
|
|
5007
5074
|
const projectId = opts.projectDir.replace(/\//g, "-");
|
|
5008
|
-
const sdkDir =
|
|
5075
|
+
const sdkDir = resolve12(homedir(), ".claude", "projects", projectId);
|
|
5009
5076
|
mkdirSync5(sdkDir, { recursive: true });
|
|
5010
|
-
const sdkPath =
|
|
5077
|
+
const sdkPath = resolve12(sdkDir, `${sessionId}.jsonl`);
|
|
5011
5078
|
writeFileSync7(sdkPath, `${sdkEvents.join("\n")}
|
|
5012
5079
|
`);
|
|
5013
5080
|
console.log(`Converted ${sdkEvents.length} messages \u2192 ${sdkPath}`);
|
|
@@ -5074,7 +5141,7 @@ async function getMindStatus(name, port, registryRunning, seed) {
|
|
|
5074
5141
|
let status = "stopped";
|
|
5075
5142
|
let wakeAt = null;
|
|
5076
5143
|
try {
|
|
5077
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
5144
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-OFP2GFXF.js");
|
|
5078
5145
|
const sleepManager = getSleepManagerIfReady2();
|
|
5079
5146
|
if (sleepManager?.isSleeping(name)) {
|
|
5080
5147
|
status = "sleeping";
|
|
@@ -5153,7 +5220,7 @@ async function initTemplateBranch(projectRoot, composedDir, manifest, mindName,
|
|
|
5153
5220
|
await gitExec(["commit", "-m", "initial commit"], opts);
|
|
5154
5221
|
}
|
|
5155
5222
|
async function updateTemplateBranch(projectRoot, template, mindName) {
|
|
5156
|
-
const tempWorktree =
|
|
5223
|
+
const tempWorktree = resolve13(projectRoot, ".variants", "_template_update");
|
|
5157
5224
|
let branchExists = false;
|
|
5158
5225
|
try {
|
|
5159
5226
|
await gitExec(["rev-parse", "--verify", TEMPLATE_BRANCH], { cwd: projectRoot });
|
|
@@ -5185,15 +5252,15 @@ async function updateTemplateBranch(projectRoot, template, mindName) {
|
|
|
5185
5252
|
});
|
|
5186
5253
|
}
|
|
5187
5254
|
copyTemplateToDir(composedDir, tempWorktree, mindName, manifest);
|
|
5188
|
-
const initDir =
|
|
5255
|
+
const initDir = resolve13(tempWorktree, ".init");
|
|
5189
5256
|
if (existsSync8(initDir)) {
|
|
5190
5257
|
rmSync3(initDir, { recursive: true, force: true });
|
|
5191
5258
|
}
|
|
5192
|
-
const homeDir =
|
|
5259
|
+
const homeDir = resolve13(tempWorktree, "home");
|
|
5193
5260
|
if (existsSync8(homeDir)) {
|
|
5194
5261
|
for (const entry of readdirSync2(homeDir)) {
|
|
5195
5262
|
if (entry !== "VOLUTE.md") {
|
|
5196
|
-
rmSync3(
|
|
5263
|
+
rmSync3(resolve13(homeDir, entry), { recursive: true, force: true });
|
|
5197
5264
|
}
|
|
5198
5265
|
}
|
|
5199
5266
|
}
|
|
@@ -5252,7 +5319,7 @@ async function mergeUpgradeAndRestart(mindName, dir, worktreeDir, upgradeVariant
|
|
|
5252
5319
|
let switchWarning;
|
|
5253
5320
|
if (templateChanged) {
|
|
5254
5321
|
try {
|
|
5255
|
-
applyTemplateHomeFiles(
|
|
5322
|
+
applyTemplateHomeFiles(resolve13(dir, "home"), template);
|
|
5256
5323
|
const migratedSkills = migrateSkillsToTemplate(dir, oldTemplate, template);
|
|
5257
5324
|
await gitExec(["add", "home/"], { cwd: dir });
|
|
5258
5325
|
try {
|
|
@@ -5308,7 +5375,7 @@ async function mergeUpgradeAndRestart(mindName, dir, worktreeDir, upgradeVariant
|
|
|
5308
5375
|
return { ok: true, warning: switchWarning };
|
|
5309
5376
|
}
|
|
5310
5377
|
async function importFromArchive(c, tempDir, nameOverride, manifest) {
|
|
5311
|
-
const extractedMindDir =
|
|
5378
|
+
const extractedMindDir = resolve13(tempDir, "mind");
|
|
5312
5379
|
if (!existsSync8(extractedMindDir)) {
|
|
5313
5380
|
return c.json({ error: "Invalid archive: missing mind/ directory" }, 400);
|
|
5314
5381
|
}
|
|
@@ -5335,9 +5402,9 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
|
|
|
5335
5402
|
}
|
|
5336
5403
|
const state = stateDir(name);
|
|
5337
5404
|
mkdirSync6(state, { recursive: true });
|
|
5338
|
-
const envJson =
|
|
5405
|
+
const envJson = resolve13(tempDir, "state/env.json");
|
|
5339
5406
|
if (existsSync8(envJson)) {
|
|
5340
|
-
cpSync(envJson,
|
|
5407
|
+
cpSync(envJson, resolve13(state, "env.json"));
|
|
5341
5408
|
}
|
|
5342
5409
|
const port = await nextPort();
|
|
5343
5410
|
await addMind(name, port, manifest.stage, manifest.template);
|
|
@@ -5346,23 +5413,23 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
|
|
|
5346
5413
|
} catch (err) {
|
|
5347
5414
|
logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
|
|
5348
5415
|
}
|
|
5349
|
-
const homeDir =
|
|
5416
|
+
const homeDir = resolve13(dest, "home");
|
|
5350
5417
|
ensureVoluteGroup();
|
|
5351
5418
|
createMindUser(name, homeDir);
|
|
5352
5419
|
await chownMindDir(dest, name);
|
|
5353
5420
|
await npmInstallAsMind(dest, name);
|
|
5354
5421
|
await importHistoryFromArchive(name, tempDir);
|
|
5355
5422
|
importSessionsFromArchive(dest, tempDir);
|
|
5356
|
-
if (!existsSync8(
|
|
5423
|
+
if (!existsSync8(resolve13(dest, ".git"))) {
|
|
5357
5424
|
try {
|
|
5358
|
-
const env = isIsolationEnabled() ? { ...process.env, HOME:
|
|
5425
|
+
const env = isIsolationEnabled() ? { ...process.env, HOME: resolve13(dest, "home") } : void 0;
|
|
5359
5426
|
await gitExec(["init"], { cwd: dest, mindName: name, env });
|
|
5360
5427
|
await configureGitIdentity(name, { cwd: dest, mindName: name, env });
|
|
5361
5428
|
await gitExec(["add", "-A"], { cwd: dest, mindName: name, env });
|
|
5362
5429
|
await gitExec(["commit", "-m", "import from archive"], { cwd: dest, mindName: name, env });
|
|
5363
5430
|
} catch (err) {
|
|
5364
5431
|
logger_default.error(`git setup failed for imported mind ${name}`, logger_default.errorData(err));
|
|
5365
|
-
rmSync3(
|
|
5432
|
+
rmSync3(resolve13(dest, ".git"), { recursive: true, force: true });
|
|
5366
5433
|
}
|
|
5367
5434
|
}
|
|
5368
5435
|
await chownMindDir(dest, name);
|
|
@@ -5395,22 +5462,22 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
5395
5462
|
try {
|
|
5396
5463
|
copyTemplateToDir(composedDir, dest, name, templateManifest);
|
|
5397
5464
|
applyInitFiles(dest);
|
|
5398
|
-
const extractedHome =
|
|
5465
|
+
const extractedHome = resolve13(extractedMindDir, "home");
|
|
5399
5466
|
if (existsSync8(extractedHome)) {
|
|
5400
|
-
cpSync(extractedHome,
|
|
5467
|
+
cpSync(extractedHome, resolve13(dest, "home"), { recursive: true });
|
|
5401
5468
|
}
|
|
5402
|
-
const extractedMindInternal =
|
|
5469
|
+
const extractedMindInternal = resolve13(extractedMindDir, ".mind");
|
|
5403
5470
|
if (existsSync8(extractedMindInternal)) {
|
|
5404
|
-
cpSync(extractedMindInternal,
|
|
5471
|
+
cpSync(extractedMindInternal, resolve13(dest, ".mind"), { recursive: true });
|
|
5405
5472
|
}
|
|
5406
|
-
const identityDir =
|
|
5473
|
+
const identityDir = resolve13(dest, ".mind/identity");
|
|
5407
5474
|
let publicKeyPem;
|
|
5408
|
-
if (!manifest.includes.identity || !existsSync8(
|
|
5475
|
+
if (!manifest.includes.identity || !existsSync8(resolve13(identityDir, "private.pem"))) {
|
|
5409
5476
|
({ publicKeyPem } = generateIdentity(dest));
|
|
5410
5477
|
} else {
|
|
5411
|
-
publicKeyPem = readFileSync9(
|
|
5478
|
+
publicKeyPem = readFileSync9(resolve13(identityDir, "public.pem"), "utf-8");
|
|
5412
5479
|
}
|
|
5413
|
-
const promptsPath =
|
|
5480
|
+
const promptsPath = resolve13(dest, "home/.config/prompts.json");
|
|
5414
5481
|
if (!existsSync8(promptsPath)) {
|
|
5415
5482
|
const mindPrompts = await getMindPromptDefaults();
|
|
5416
5483
|
writeFileSync8(promptsPath, `${JSON.stringify(mindPrompts, null, 2)}
|
|
@@ -5418,13 +5485,13 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
5418
5485
|
}
|
|
5419
5486
|
const state = stateDir(name);
|
|
5420
5487
|
mkdirSync6(state, { recursive: true });
|
|
5421
|
-
const envJson =
|
|
5488
|
+
const envJson = resolve13(tempDir, "state/env.json");
|
|
5422
5489
|
if (existsSync8(envJson)) {
|
|
5423
|
-
cpSync(envJson,
|
|
5490
|
+
cpSync(envJson, resolve13(state, "env.json"));
|
|
5424
5491
|
}
|
|
5425
5492
|
const port = await nextPort();
|
|
5426
5493
|
await addMind(name, port, manifest.stage, manifest.template);
|
|
5427
|
-
const homeDir =
|
|
5494
|
+
const homeDir = resolve13(dest, "home");
|
|
5428
5495
|
ensureVoluteGroup();
|
|
5429
5496
|
createMindUser(name, homeDir);
|
|
5430
5497
|
await chownMindDir(dest, name);
|
|
@@ -5437,7 +5504,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
5437
5504
|
await initTemplateBranch(dest, composedDir, templateManifest, name, env);
|
|
5438
5505
|
} catch (err) {
|
|
5439
5506
|
logger_default.error(`git setup failed for imported mind ${name}`, logger_default.errorData(err));
|
|
5440
|
-
rmSync3(
|
|
5507
|
+
rmSync3(resolve13(dest, ".git"), { recursive: true, force: true });
|
|
5441
5508
|
gitWarning = "Git setup failed \u2014 variants and upgrades won't be available until git is initialized.";
|
|
5442
5509
|
}
|
|
5443
5510
|
const skillSet = manifest.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions();
|
|
@@ -5480,7 +5547,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
5480
5547
|
}
|
|
5481
5548
|
}
|
|
5482
5549
|
async function importHistoryFromArchive(name, tempDir) {
|
|
5483
|
-
const historyJsonl =
|
|
5550
|
+
const historyJsonl = resolve13(tempDir, "history.jsonl");
|
|
5484
5551
|
if (!existsSync8(historyJsonl)) return;
|
|
5485
5552
|
try {
|
|
5486
5553
|
const db = await getDb();
|
|
@@ -5521,13 +5588,13 @@ async function importHistoryFromArchive(name, tempDir) {
|
|
|
5521
5588
|
}
|
|
5522
5589
|
}
|
|
5523
5590
|
function importSessionsFromArchive(dest, tempDir) {
|
|
5524
|
-
const sessionsDir =
|
|
5591
|
+
const sessionsDir = resolve13(tempDir, "sessions");
|
|
5525
5592
|
if (!existsSync8(sessionsDir)) return;
|
|
5526
5593
|
try {
|
|
5527
|
-
const destSessions =
|
|
5594
|
+
const destSessions = resolve13(dest, ".mind/sessions");
|
|
5528
5595
|
mkdirSync6(destSessions, { recursive: true });
|
|
5529
5596
|
for (const file of readdirSync2(sessionsDir)) {
|
|
5530
|
-
cpSync(
|
|
5597
|
+
cpSync(resolve13(sessionsDir, file), resolve13(destSessions, file));
|
|
5531
5598
|
}
|
|
5532
5599
|
} catch (err) {
|
|
5533
5600
|
logger_default.error("Failed to import sessions from archive", logger_default.errorData(err));
|
|
@@ -5644,7 +5711,7 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
|
|
|
5644
5711
|
writeVoluteConfig(dest, config2);
|
|
5645
5712
|
const modelId = body.model ?? cog?.model;
|
|
5646
5713
|
effectiveModel = modelId ? qualifyModelId(modelId) : void 0;
|
|
5647
|
-
const sdkConfigPath =
|
|
5714
|
+
const sdkConfigPath = resolve13(dest, "home/.config/config.json");
|
|
5648
5715
|
if (modelId || cog?.compaction) {
|
|
5649
5716
|
const existing = existsSync8(sdkConfigPath) ? JSON.parse(readFileSync9(sdkConfigPath, "utf-8")) : {};
|
|
5650
5717
|
if (modelId) {
|
|
@@ -5659,7 +5726,7 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
|
|
|
5659
5726
|
}
|
|
5660
5727
|
const mindPrompts = await getMindPromptDefaults();
|
|
5661
5728
|
writeFileSync8(
|
|
5662
|
-
|
|
5729
|
+
resolve13(dest, "home/.config/prompts.json"),
|
|
5663
5730
|
`${JSON.stringify(mindPrompts, null, 2)}
|
|
5664
5731
|
`
|
|
5665
5732
|
);
|
|
@@ -5671,7 +5738,7 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
|
|
|
5671
5738
|
} catch (err) {
|
|
5672
5739
|
logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
|
|
5673
5740
|
}
|
|
5674
|
-
const homeDir =
|
|
5741
|
+
const homeDir = resolve13(dest, "home");
|
|
5675
5742
|
ensureVoluteGroup();
|
|
5676
5743
|
createMindUser(name, homeDir);
|
|
5677
5744
|
await chownMindDir(dest, name);
|
|
@@ -5684,7 +5751,7 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
|
|
|
5684
5751
|
await initTemplateBranch(dest, composedDir, manifest, name, env);
|
|
5685
5752
|
} catch (err) {
|
|
5686
5753
|
logger_default.error(`git setup failed for ${name}`, logger_default.errorData(err));
|
|
5687
|
-
rmSync3(
|
|
5754
|
+
rmSync3(resolve13(dest, ".git"), { recursive: true, force: true });
|
|
5688
5755
|
gitWarning = "Git setup failed \u2014 variants and upgrades won't be available until git is initialized.";
|
|
5689
5756
|
}
|
|
5690
5757
|
if (body.stage === "seed") {
|
|
@@ -5693,7 +5760,7 @@ Your creator described you as: "${body.description}"
|
|
|
5693
5760
|
` : "";
|
|
5694
5761
|
const seedSoulRaw = body.seedSoul ?? await getPrompt("seed_soul", { name, description: descLine });
|
|
5695
5762
|
const seedSoul = body.seedSoul ? substitute(seedSoulRaw, { name, description: descLine }) : seedSoulRaw;
|
|
5696
|
-
writeFileSync8(
|
|
5763
|
+
writeFileSync8(resolve13(dest, "home/SOUL.md"), seedSoul);
|
|
5697
5764
|
}
|
|
5698
5765
|
let skillSet = body.skills ?? (body.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions());
|
|
5699
5766
|
if (body.stage === "seed" && !body.skills) {
|
|
@@ -5719,7 +5786,7 @@ Your creator described you as: "${body.description}"
|
|
|
5719
5786
|
const spiritName = getSpiritName();
|
|
5720
5787
|
const spiritEntry = await findMind(spiritName);
|
|
5721
5788
|
if (spiritEntry) {
|
|
5722
|
-
const { spiritDir } = await import("./spirit-
|
|
5789
|
+
const { spiritDir } = await import("./spirit-4ECYIVGE.js");
|
|
5723
5790
|
const sDir = spiritEntry.dir ?? spiritDir();
|
|
5724
5791
|
const spiritConfig = readVoluteConfig(sDir) ?? {};
|
|
5725
5792
|
const schedules = spiritConfig.schedules ?? [];
|
|
@@ -5734,7 +5801,7 @@ Your creator described you as: "${body.description}"
|
|
|
5734
5801
|
});
|
|
5735
5802
|
spiritConfig.schedules = schedules;
|
|
5736
5803
|
writeVoluteConfig(sDir, spiritConfig);
|
|
5737
|
-
const { getScheduler: getScheduler2 } = await import("./scheduler-
|
|
5804
|
+
const { getScheduler: getScheduler2 } = await import("./scheduler-JTTWZDYU.js");
|
|
5738
5805
|
getScheduler2().loadSchedules(spiritName, sDir);
|
|
5739
5806
|
}
|
|
5740
5807
|
}
|
|
@@ -5745,11 +5812,11 @@ Your creator described you as: "${body.description}"
|
|
|
5745
5812
|
if (body.stage !== "seed") {
|
|
5746
5813
|
const customSoul = await getPromptIfCustom("default_soul");
|
|
5747
5814
|
if (customSoul) {
|
|
5748
|
-
writeFileSync8(
|
|
5815
|
+
writeFileSync8(resolve13(dest, "home/SOUL.md"), customSoul.replace(/\{\{name\}\}/g, name));
|
|
5749
5816
|
}
|
|
5750
5817
|
const customMemory = await getPromptIfCustom("default_memory");
|
|
5751
5818
|
if (customMemory) {
|
|
5752
|
-
writeFileSync8(
|
|
5819
|
+
writeFileSync8(resolve13(dest, "home/MEMORY.md"), customMemory);
|
|
5753
5820
|
}
|
|
5754
5821
|
}
|
|
5755
5822
|
await chownMindDir(dest, name);
|
|
@@ -5810,12 +5877,12 @@ Your creator described you as: "${body.description}"
|
|
|
5810
5877
|
return importFromArchive(c, body.archivePath, body.name, body.manifest);
|
|
5811
5878
|
}
|
|
5812
5879
|
const wsDir = body.workspacePath;
|
|
5813
|
-
if (!wsDir || !existsSync8(
|
|
5880
|
+
if (!wsDir || !existsSync8(resolve13(wsDir, "SOUL.md")) || !existsSync8(resolve13(wsDir, "IDENTITY.md"))) {
|
|
5814
5881
|
return c.json({ error: "Invalid workspace: missing SOUL.md or IDENTITY.md" }, 400);
|
|
5815
5882
|
}
|
|
5816
|
-
const soul = readFileSync9(
|
|
5817
|
-
const identity = readFileSync9(
|
|
5818
|
-
const userPath =
|
|
5883
|
+
const soul = readFileSync9(resolve13(wsDir, "SOUL.md"), "utf-8");
|
|
5884
|
+
const identity = readFileSync9(resolve13(wsDir, "IDENTITY.md"), "utf-8");
|
|
5885
|
+
const userPath = resolve13(wsDir, "USER.md");
|
|
5819
5886
|
const user = existsSync8(userPath) ? readFileSync9(userPath, "utf-8") : "";
|
|
5820
5887
|
const name = body.name ?? parseNameFromIdentity(identity) ?? "imported-mind";
|
|
5821
5888
|
const template = body.template ?? "claude";
|
|
@@ -5843,26 +5910,26 @@ ${user.trimEnd()}
|
|
|
5843
5910
|
copyTemplateToDir(composedDir, dest, name, manifest);
|
|
5844
5911
|
applyInitFiles(dest);
|
|
5845
5912
|
const { publicKeyPem: importPublicKey } = generateIdentity(dest);
|
|
5846
|
-
writeFileSync8(
|
|
5847
|
-
const wsMemoryPath =
|
|
5913
|
+
writeFileSync8(resolve13(dest, "home/SOUL.md"), mergedSoul);
|
|
5914
|
+
const wsMemoryPath = resolve13(wsDir, "MEMORY.md");
|
|
5848
5915
|
const hasMemory = existsSync8(wsMemoryPath);
|
|
5849
5916
|
if (hasMemory) {
|
|
5850
5917
|
const existingMemory = readFileSync9(wsMemoryPath, "utf-8");
|
|
5851
5918
|
writeFileSync8(
|
|
5852
|
-
|
|
5919
|
+
resolve13(dest, "home/MEMORY.md"),
|
|
5853
5920
|
`${existingMemory.trimEnd()}${mergedMemoryExtra}`
|
|
5854
5921
|
);
|
|
5855
5922
|
} else if (user) {
|
|
5856
|
-
writeFileSync8(
|
|
5923
|
+
writeFileSync8(resolve13(dest, "home/MEMORY.md"), `${user.trimEnd()}
|
|
5857
5924
|
`);
|
|
5858
5925
|
}
|
|
5859
|
-
const wsMemoryDir =
|
|
5926
|
+
const wsMemoryDir = resolve13(wsDir, "memory");
|
|
5860
5927
|
let dailyLogCount = 0;
|
|
5861
5928
|
if (existsSync8(wsMemoryDir)) {
|
|
5862
|
-
const destMemoryDir =
|
|
5929
|
+
const destMemoryDir = resolve13(dest, "home/memory");
|
|
5863
5930
|
const files = readdirSync2(wsMemoryDir).filter((f) => f.endsWith(".md"));
|
|
5864
5931
|
for (const file of files) {
|
|
5865
|
-
cpSync(
|
|
5932
|
+
cpSync(resolve13(wsMemoryDir, file), resolve13(destMemoryDir, file));
|
|
5866
5933
|
}
|
|
5867
5934
|
dailyLogCount = files.length;
|
|
5868
5935
|
}
|
|
@@ -5873,7 +5940,7 @@ ${user.trimEnd()}
|
|
|
5873
5940
|
} catch (err) {
|
|
5874
5941
|
logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
|
|
5875
5942
|
}
|
|
5876
|
-
const homeDir =
|
|
5943
|
+
const homeDir = resolve13(dest, "home");
|
|
5877
5944
|
ensureVoluteGroup();
|
|
5878
5945
|
createMindUser(name, homeDir);
|
|
5879
5946
|
await chownMindDir(dest, name);
|
|
@@ -5881,20 +5948,20 @@ ${user.trimEnd()}
|
|
|
5881
5948
|
if (!hasMemory && dailyLogCount > 0) {
|
|
5882
5949
|
await consolidateMemory(dest);
|
|
5883
5950
|
}
|
|
5884
|
-
const env = isIsolationEnabled() ? { ...process.env, HOME:
|
|
5951
|
+
const env = isIsolationEnabled() ? { ...process.env, HOME: resolve13(dest, "home") } : void 0;
|
|
5885
5952
|
await gitExec(["init"], { cwd: dest, mindName: name, env });
|
|
5886
5953
|
await configureGitIdentity(name, { cwd: dest, mindName: name, env });
|
|
5887
5954
|
await gitExec(["add", "-A"], { cwd: dest, mindName: name, env });
|
|
5888
5955
|
await gitExec(["commit", "-m", "import from OpenClaw"], { cwd: dest, mindName: name, env });
|
|
5889
|
-
const sessionFile = body.sessionPath ?
|
|
5956
|
+
const sessionFile = body.sessionPath ? resolve13(body.sessionPath) : findOpenClawSession(wsDir);
|
|
5890
5957
|
if (sessionFile && existsSync8(sessionFile)) {
|
|
5891
5958
|
if (template === "pi") {
|
|
5892
5959
|
importPiSession(sessionFile, dest);
|
|
5893
5960
|
} else if (template === "claude") {
|
|
5894
5961
|
const sessionId = convertSession({ sessionPath: sessionFile, projectDir: dest });
|
|
5895
|
-
const mindRuntimeDir =
|
|
5962
|
+
const mindRuntimeDir = resolve13(dest, ".mind");
|
|
5896
5963
|
mkdirSync6(mindRuntimeDir, { recursive: true });
|
|
5897
|
-
writeFileSync8(
|
|
5964
|
+
writeFileSync8(resolve13(mindRuntimeDir, "session.json"), JSON.stringify({ sessionId }));
|
|
5898
5965
|
}
|
|
5899
5966
|
}
|
|
5900
5967
|
importOpenClawConnectors(name, dest);
|
|
@@ -5940,7 +6007,7 @@ ${user.trimEnd()}
|
|
|
5940
6007
|
stage: entry.stage,
|
|
5941
6008
|
dir: entry.dir
|
|
5942
6009
|
});
|
|
5943
|
-
const hasPages = existsSync8(
|
|
6010
|
+
const hasPages = existsSync8(resolve13(mindDir(entry.name), "home", "pages"));
|
|
5944
6011
|
const lastActiveAt = lastActiveMap.get(entry.name) ?? null;
|
|
5945
6012
|
if (!privileged) return toPublicMind(entry, mindStatus, { hasPages, lastActiveAt });
|
|
5946
6013
|
return {
|
|
@@ -5963,7 +6030,7 @@ ${user.trimEnd()}
|
|
|
5963
6030
|
stage: entry.stage,
|
|
5964
6031
|
dir: entry.dir
|
|
5965
6032
|
});
|
|
5966
|
-
const hasPages = existsSync8(
|
|
6033
|
+
const hasPages = existsSync8(resolve13(mindDir(name), "home", "pages"));
|
|
5967
6034
|
if (!isPrivileged(c)) {
|
|
5968
6035
|
return c.json(toPublicMind(entry, mindStatus, { hasPages }));
|
|
5969
6036
|
}
|
|
@@ -6040,7 +6107,7 @@ ${user.trimEnd()}
|
|
|
6040
6107
|
const manager = getMindManager();
|
|
6041
6108
|
try {
|
|
6042
6109
|
if (context?.type === "reload") {
|
|
6043
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
6110
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-OFP2GFXF.js");
|
|
6044
6111
|
const sleepState = getSleepManagerIfReady2()?.getState(name);
|
|
6045
6112
|
if (sleepState?.sleeping) {
|
|
6046
6113
|
logger_default.info(`skipping reload for ${name} during sleep \u2014 will apply on next wake`);
|
|
@@ -6060,6 +6127,7 @@ ${user.trimEnd()}
|
|
|
6060
6127
|
const variantEntry = await findMind(mergeVariantName);
|
|
6061
6128
|
if (variantEntry && variantEntry.parent === baseName && variantEntry.dir && variantEntry.branch) {
|
|
6062
6129
|
const projectRoot = mindDir(baseName);
|
|
6130
|
+
const discardUnresolved = context.discardUnresolvedHomeFiles === true;
|
|
6063
6131
|
if (existsSync8(variantEntry.dir)) {
|
|
6064
6132
|
const status = (await gitExec(["status", "--porcelain"], { cwd: variantEntry.dir })).trim();
|
|
6065
6133
|
if (status) {
|
|
@@ -6089,13 +6157,41 @@ ${user.trimEnd()}
|
|
|
6089
6157
|
}
|
|
6090
6158
|
const preMergeHead = (await gitExec(["rev-parse", "HEAD"], { cwd: projectRoot })).trim();
|
|
6091
6159
|
const memoryDelta = await mergeVariantExcludingMemory(projectRoot, variantEntry.branch);
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
if (await npmInstallNeeded(projectRoot, preMergeHead)) {
|
|
6160
|
+
let unresolvedNotice;
|
|
6161
|
+
if (existsSync8(variantEntry.dir) && !discardUnresolved) {
|
|
6095
6162
|
try {
|
|
6096
|
-
await
|
|
6097
|
-
|
|
6098
|
-
|
|
6163
|
+
const unresolved = await findUnresolvedHomeFiles(variantEntry.dir);
|
|
6164
|
+
if (unresolved.totalCount > 0) {
|
|
6165
|
+
unresolvedNotice = formatUnresolvedHomeFilesMessage(mergeVariantName, unresolved);
|
|
6166
|
+
}
|
|
6167
|
+
} catch (err) {
|
|
6168
|
+
unresolvedNotice = `Could not verify variant ${mergeVariantName} has no unresolved home/ files: ${err instanceof Error ? err.message : String(err)}. Variant left intact \u2014 retry the join.`;
|
|
6169
|
+
}
|
|
6170
|
+
}
|
|
6171
|
+
if (unresolvedNotice) {
|
|
6172
|
+
logger_default.warn(
|
|
6173
|
+
`variant join blocked for ${baseName}: ${mergeVariantName} \u2014 ${unresolvedNotice}`
|
|
6174
|
+
);
|
|
6175
|
+
await recordNotice({
|
|
6176
|
+
mind: baseName,
|
|
6177
|
+
thread: "main",
|
|
6178
|
+
kind: "join_blocked",
|
|
6179
|
+
reason: "unresolved_variant_files",
|
|
6180
|
+
detail: unresolvedNotice
|
|
6181
|
+
});
|
|
6182
|
+
if (context) {
|
|
6183
|
+
context.type = "restart";
|
|
6184
|
+
context.name = void 0;
|
|
6185
|
+
}
|
|
6186
|
+
} else {
|
|
6187
|
+
if (memoryDelta && context) context.memoryDelta = memoryDelta;
|
|
6188
|
+
await cleanupVariant(mergeVariantName, baseName, projectRoot, variantEntry.dir);
|
|
6189
|
+
if (await npmInstallNeeded(projectRoot, preMergeHead)) {
|
|
6190
|
+
try {
|
|
6191
|
+
await npmInstallAsMind(projectRoot, baseName);
|
|
6192
|
+
} catch (e) {
|
|
6193
|
+
logger_default.error(`npm install failed after merge for ${baseName}`, logger_default.errorData(e));
|
|
6194
|
+
}
|
|
6099
6195
|
}
|
|
6100
6196
|
}
|
|
6101
6197
|
}
|
|
@@ -6138,6 +6234,7 @@ ${user.trimEnd()}
|
|
|
6138
6234
|
);
|
|
6139
6235
|
return c.json({ ok: true, port: targetPort });
|
|
6140
6236
|
} catch (err) {
|
|
6237
|
+
logger_default.error(`failed to restart mind ${name}`, logger_default.errorData(err));
|
|
6141
6238
|
return c.json({ error: err instanceof Error ? err.message : "Failed to restart mind" }, 500);
|
|
6142
6239
|
}
|
|
6143
6240
|
}).post("/:name/stop", requireSelf(), async (c) => {
|
|
@@ -6152,13 +6249,14 @@ ${user.trimEnd()}
|
|
|
6152
6249
|
await stopMindFull(name);
|
|
6153
6250
|
return c.json({ ok: true });
|
|
6154
6251
|
} catch (err) {
|
|
6252
|
+
logger_default.error(`failed to stop mind ${name}`, logger_default.errorData(err));
|
|
6155
6253
|
return c.json({ error: err instanceof Error ? err.message : "Failed to stop mind" }, 500);
|
|
6156
6254
|
}
|
|
6157
6255
|
}).get("/:name/sleep", requireSelf(), async (c) => {
|
|
6158
6256
|
const name = c.req.param("name");
|
|
6159
6257
|
const entry = await findMind(name);
|
|
6160
6258
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
6161
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
6259
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-OFP2GFXF.js");
|
|
6162
6260
|
const sm = getSleepManagerIfReady2();
|
|
6163
6261
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
6164
6262
|
return c.json(sm.getState(name));
|
|
@@ -6166,7 +6264,7 @@ ${user.trimEnd()}
|
|
|
6166
6264
|
const name = c.req.param("name");
|
|
6167
6265
|
const entry = await findMind(name);
|
|
6168
6266
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
6169
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
6267
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-OFP2GFXF.js");
|
|
6170
6268
|
const sm = getSleepManagerIfReady2();
|
|
6171
6269
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
6172
6270
|
if (sm.isSleeping(name)) return c.json({ error: "Mind is already sleeping" }, 409);
|
|
@@ -6186,7 +6284,7 @@ ${user.trimEnd()}
|
|
|
6186
6284
|
const name = c.req.param("name");
|
|
6187
6285
|
const entry = await findMind(name);
|
|
6188
6286
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
6189
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
6287
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-OFP2GFXF.js");
|
|
6190
6288
|
const sm = getSleepManagerIfReady2();
|
|
6191
6289
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
6192
6290
|
const sleepState = sm.getState(name);
|
|
@@ -6201,7 +6299,7 @@ ${user.trimEnd()}
|
|
|
6201
6299
|
const name = c.req.param("name");
|
|
6202
6300
|
const entry = await findMind(name);
|
|
6203
6301
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
6204
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
6302
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-OFP2GFXF.js");
|
|
6205
6303
|
const sm = getSleepManagerIfReady2();
|
|
6206
6304
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
6207
6305
|
const flushed = await sm.flushQueuedMessages(name);
|
|
@@ -6217,7 +6315,7 @@ ${user.trimEnd()}
|
|
|
6217
6315
|
if (body.displayName !== void 0) profile.displayName = body.displayName;
|
|
6218
6316
|
if (body.description !== void 0) profile.description = body.description;
|
|
6219
6317
|
if (body.avatar !== void 0) {
|
|
6220
|
-
const homeDir =
|
|
6318
|
+
const homeDir = resolve13(dir, "home");
|
|
6221
6319
|
const avatarPath = safeResolveWithinBase(homeDir, body.avatar);
|
|
6222
6320
|
if (!avatarPath) {
|
|
6223
6321
|
return c.json({ error: "Avatar path must be inside the mind's home directory" }, 400);
|
|
@@ -6229,7 +6327,7 @@ ${user.trimEnd()}
|
|
|
6229
6327
|
}
|
|
6230
6328
|
config2.profile = profile;
|
|
6231
6329
|
writeVoluteConfig(dir, config2);
|
|
6232
|
-
const { syncMindProfile: syncMindProfile2 } = await import("./auth-
|
|
6330
|
+
const { syncMindProfile: syncMindProfile2 } = await import("./auth-KRDSM55Q.js");
|
|
6233
6331
|
await syncMindProfile2(name, profile);
|
|
6234
6332
|
broadcast({ type: "profile_updated", mind: name, summary: `${name} profile updated` });
|
|
6235
6333
|
return c.json({ ok: true });
|
|
@@ -6273,7 +6371,7 @@ ${user.trimEnd()}
|
|
|
6273
6371
|
});
|
|
6274
6372
|
}
|
|
6275
6373
|
if (!force) {
|
|
6276
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
6374
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-OFP2GFXF.js");
|
|
6277
6375
|
if (getSleepManagerIfReady2()?.isSleeping(name)) {
|
|
6278
6376
|
return c.json({ output: "" });
|
|
6279
6377
|
}
|
|
@@ -6370,7 +6468,7 @@ ${user.trimEnd()}
|
|
|
6370
6468
|
try {
|
|
6371
6469
|
const sproutedDir = entry.dir ?? mindDir(name);
|
|
6372
6470
|
if (setupDefaultDreaming(sproutedDir).schedulesChanged) {
|
|
6373
|
-
const { getScheduler: getScheduler2 } = await import("./scheduler-
|
|
6471
|
+
const { getScheduler: getScheduler2 } = await import("./scheduler-JTTWZDYU.js");
|
|
6374
6472
|
getScheduler2().loadSchedules(name, sproutedDir);
|
|
6375
6473
|
}
|
|
6376
6474
|
} catch (err) {
|
|
@@ -6380,7 +6478,7 @@ ${user.trimEnd()}
|
|
|
6380
6478
|
const spiritName = getSpiritName();
|
|
6381
6479
|
const spiritEntry = await findMind(spiritName);
|
|
6382
6480
|
if (spiritEntry) {
|
|
6383
|
-
const { firstWeekSchedules, spiritDir } = await import("./spirit-
|
|
6481
|
+
const { firstWeekSchedules, spiritDir } = await import("./spirit-4ECYIVGE.js");
|
|
6384
6482
|
const sDir = spiritEntry.dir ?? spiritDir();
|
|
6385
6483
|
const spiritConfig = readVoluteConfig(sDir);
|
|
6386
6484
|
if (spiritConfig) {
|
|
@@ -6394,7 +6492,7 @@ ${user.trimEnd()}
|
|
|
6394
6492
|
spiritConfig.schedules = schedules;
|
|
6395
6493
|
writeVoluteConfig(sDir, spiritConfig);
|
|
6396
6494
|
try {
|
|
6397
|
-
const { getScheduler: getScheduler2 } = await import("./scheduler-
|
|
6495
|
+
const { getScheduler: getScheduler2 } = await import("./scheduler-JTTWZDYU.js");
|
|
6398
6496
|
getScheduler2().loadSchedules(spiritName, sDir);
|
|
6399
6497
|
} catch (err) {
|
|
6400
6498
|
logger_default.warn(
|
|
@@ -6416,9 +6514,25 @@ ${user.trimEnd()}
|
|
|
6416
6514
|
const name = c.req.param("name");
|
|
6417
6515
|
const entry = await findMind(name);
|
|
6418
6516
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
6517
|
+
const manager = getMindManager();
|
|
6518
|
+
if (entry.parent) {
|
|
6519
|
+
if (!entry.dir) return c.json({ error: `Variant ${name} has no directory` }, 500);
|
|
6520
|
+
const parentEntry = await findMind(entry.parent);
|
|
6521
|
+
if (!parentEntry) return c.json({ error: `Parent mind ${entry.parent} not found` }, 404);
|
|
6522
|
+
if (manager.isRunning(name)) {
|
|
6523
|
+
await stopMindFull(name);
|
|
6524
|
+
}
|
|
6525
|
+
await cleanupVariant(name, entry.parent, parentEntry.dir ?? mindDir(entry.parent), entry.dir);
|
|
6526
|
+
invalidateMindUserCache(name);
|
|
6527
|
+
fireWebhook({
|
|
6528
|
+
event: "mind_deleted",
|
|
6529
|
+
mind: name,
|
|
6530
|
+
data: { port: entry.port, stage: entry.stage, template: entry.template }
|
|
6531
|
+
});
|
|
6532
|
+
return c.json({ ok: true, variant: true });
|
|
6533
|
+
}
|
|
6419
6534
|
const dir = mindDir(name);
|
|
6420
6535
|
const force = c.req.query("force") === "true";
|
|
6421
|
-
const manager = getMindManager();
|
|
6422
6536
|
if (manager.isRunning(name)) {
|
|
6423
6537
|
await stopMindFull(name);
|
|
6424
6538
|
}
|
|
@@ -6463,16 +6577,16 @@ ${user.trimEnd()}
|
|
|
6463
6577
|
}
|
|
6464
6578
|
const UPGRADE_BRANCH = "upgrade";
|
|
6465
6579
|
const upgradeVariantName = `${mindName}-upgrade`;
|
|
6466
|
-
const worktreeDir =
|
|
6580
|
+
const worktreeDir = resolve13(dir, ".variants", UPGRADE_BRANCH);
|
|
6467
6581
|
if (body.abort) {
|
|
6468
6582
|
if (!existsSync8(worktreeDir)) {
|
|
6469
6583
|
return c.json({ error: "No upgrade in progress" }, 400);
|
|
6470
6584
|
}
|
|
6471
6585
|
try {
|
|
6472
6586
|
try {
|
|
6473
|
-
const gitDirContent = readFileSync9(
|
|
6587
|
+
const gitDirContent = readFileSync9(resolve13(worktreeDir, ".git"), "utf-8").trim();
|
|
6474
6588
|
const gitDir = gitDirContent.replace("gitdir: ", "");
|
|
6475
|
-
if (existsSync8(
|
|
6589
|
+
if (existsSync8(resolve13(gitDir, "MERGE_HEAD"))) {
|
|
6476
6590
|
await gitExec(["merge", "--abort"], { cwd: worktreeDir });
|
|
6477
6591
|
}
|
|
6478
6592
|
} catch {
|
|
@@ -6556,7 +6670,7 @@ ${user.trimEnd()}
|
|
|
6556
6670
|
}
|
|
6557
6671
|
if (body.diff) {
|
|
6558
6672
|
try {
|
|
6559
|
-
if (!existsSync8(
|
|
6673
|
+
if (!existsSync8(resolve13(dir, ".git"))) {
|
|
6560
6674
|
return c.json({ error: "Mind has no git history \u2014 nothing to diff against" }, 400);
|
|
6561
6675
|
}
|
|
6562
6676
|
await updateTemplateBranch(dir, template, mindName);
|
|
@@ -6580,16 +6694,16 @@ ${user.trimEnd()}
|
|
|
6580
6694
|
409
|
|
6581
6695
|
);
|
|
6582
6696
|
}
|
|
6583
|
-
if (!existsSync8(
|
|
6697
|
+
if (!existsSync8(resolve13(dir, ".git"))) {
|
|
6584
6698
|
try {
|
|
6585
|
-
const env = isIsolationEnabled() ? { ...process.env, HOME:
|
|
6699
|
+
const env = isIsolationEnabled() ? { ...process.env, HOME: resolve13(dir, "home") } : void 0;
|
|
6586
6700
|
await gitExec(["init"], { cwd: dir, mindName, env });
|
|
6587
6701
|
await configureGitIdentity(mindName, { cwd: dir, mindName, env });
|
|
6588
6702
|
await gitExec(["add", "-A"], { cwd: dir, mindName, env });
|
|
6589
6703
|
await gitExec(["commit", "-m", "initial commit"], { cwd: dir, mindName, env });
|
|
6590
6704
|
await chownMindDir(dir, mindName);
|
|
6591
6705
|
} catch (err) {
|
|
6592
|
-
rmSync3(
|
|
6706
|
+
rmSync3(resolve13(dir, ".git"), { recursive: true, force: true });
|
|
6593
6707
|
return c.json(
|
|
6594
6708
|
{
|
|
6595
6709
|
error: `Git initialization failed: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -6604,7 +6718,7 @@ ${user.trimEnd()}
|
|
|
6604
6718
|
} catch {
|
|
6605
6719
|
}
|
|
6606
6720
|
await updateTemplateBranch(dir, template, mindName);
|
|
6607
|
-
const parentDir =
|
|
6721
|
+
const parentDir = resolve13(dir, ".variants");
|
|
6608
6722
|
if (!existsSync8(parentDir)) {
|
|
6609
6723
|
mkdirSync6(parentDir, { recursive: true });
|
|
6610
6724
|
}
|
|
@@ -6741,7 +6855,7 @@ ${user.trimEnd()}
|
|
|
6741
6855
|
if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
|
|
6742
6856
|
let config2 = readVoluteConfig(dir);
|
|
6743
6857
|
if (!config2 && entry.template === "pi") {
|
|
6744
|
-
const piConfigPath =
|
|
6858
|
+
const piConfigPath = resolve13(dir, "home/.config/config.json");
|
|
6745
6859
|
if (existsSync8(piConfigPath)) {
|
|
6746
6860
|
try {
|
|
6747
6861
|
config2 = JSON.parse(readFileSync9(piConfigPath, "utf-8"));
|
|
@@ -6750,7 +6864,7 @@ ${user.trimEnd()}
|
|
|
6750
6864
|
}
|
|
6751
6865
|
}
|
|
6752
6866
|
let templateConfig = {};
|
|
6753
|
-
const configJsonPath =
|
|
6867
|
+
const configJsonPath = resolve13(dir, "home/.config/config.json");
|
|
6754
6868
|
if (existsSync8(configJsonPath)) {
|
|
6755
6869
|
try {
|
|
6756
6870
|
templateConfig = JSON.parse(readFileSync9(configJsonPath, "utf-8"));
|
|
@@ -6819,12 +6933,12 @@ ${user.trimEnd()}
|
|
|
6819
6933
|
}
|
|
6820
6934
|
writeVoluteConfig(dir, existing);
|
|
6821
6935
|
if (body.unescapeNewlines !== void 0) {
|
|
6822
|
-
const { clearEchoTextCache } = await import("./echo-text-
|
|
6936
|
+
const { clearEchoTextCache } = await import("./echo-text-PEEV7FQU.js");
|
|
6823
6937
|
clearEchoTextCache(name);
|
|
6824
6938
|
}
|
|
6825
6939
|
const needsConfigJson = body.model !== void 0 || body.thinkingLevel !== void 0 || body.compaction !== void 0;
|
|
6826
6940
|
if (needsConfigJson) {
|
|
6827
|
-
const configJsonPath =
|
|
6941
|
+
const configJsonPath = resolve13(dir, "home/.config/config.json");
|
|
6828
6942
|
let templateConfig = {};
|
|
6829
6943
|
if (existsSync8(configJsonPath)) {
|
|
6830
6944
|
try {
|
|
@@ -7593,7 +7707,7 @@ var app15 = new Hono18().get("/:name/clock/status", requireSelf(), async (c) =>
|
|
|
7593
7707
|
const entry = await findMind(name);
|
|
7594
7708
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
7595
7709
|
const body = await c.req.text();
|
|
7596
|
-
const { deliverEvent: deliverEvent2 } = await import("./system-events-
|
|
7710
|
+
const { deliverEvent: deliverEvent2 } = await import("./system-events-V43HDA3T.js");
|
|
7597
7711
|
const { id, delivered } = await deliverEvent2(name, {
|
|
7598
7712
|
type: "webhook",
|
|
7599
7713
|
body,
|
|
@@ -7611,14 +7725,14 @@ var schedules_default = app15;
|
|
|
7611
7725
|
// packages/daemon/src/web/api/setup.ts
|
|
7612
7726
|
import { mkdirSync as mkdirSync7 } from "fs";
|
|
7613
7727
|
import { homedir as homedir2 } from "os";
|
|
7614
|
-
import { resolve as
|
|
7728
|
+
import { resolve as resolve14 } from "path";
|
|
7615
7729
|
import { Hono as Hono19 } from "hono";
|
|
7616
7730
|
import { setCookie as setCookie2 } from "hono/cookie";
|
|
7617
7731
|
var DEFAULT_API_URL2 = "https://volute.systems";
|
|
7618
7732
|
var setup = new Hono19();
|
|
7619
7733
|
function writeSetupConfig(systemName, description) {
|
|
7620
|
-
const configHome = process.env.VOLUTE_HOME ??
|
|
7621
|
-
const mindsDir =
|
|
7734
|
+
const configHome = process.env.VOLUTE_HOME ?? resolve14(homedir2(), ".volute");
|
|
7735
|
+
const mindsDir = resolve14(configHome, "minds");
|
|
7622
7736
|
mkdirSync7(configHome, { recursive: true });
|
|
7623
7737
|
mkdirSync7(mindsDir, { recursive: true });
|
|
7624
7738
|
const existingConfig = readGlobalConfig();
|
|
@@ -7652,7 +7766,7 @@ setup.get("/status", async (c) => {
|
|
|
7652
7766
|
let hasAccount = false;
|
|
7653
7767
|
if (hasSystem) {
|
|
7654
7768
|
try {
|
|
7655
|
-
const { listUsersByType: listUsersByType2 } = await import("./auth-
|
|
7769
|
+
const { listUsersByType: listUsersByType2 } = await import("./auth-KRDSM55Q.js");
|
|
7656
7770
|
const brains = await listUsersByType2("human");
|
|
7657
7771
|
hasAccount = brains.length > 0;
|
|
7658
7772
|
} catch (err) {
|
|
@@ -7864,7 +7978,7 @@ setup.post("/account", async (c) => {
|
|
|
7864
7978
|
}
|
|
7865
7979
|
}
|
|
7866
7980
|
try {
|
|
7867
|
-
const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-
|
|
7981
|
+
const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-KRDSM55Q.js");
|
|
7868
7982
|
const user = await createUser2(body.username.trim(), body.password);
|
|
7869
7983
|
if (body.displayName?.trim()) {
|
|
7870
7984
|
await updateUserProfile2(user.id, { display_name: body.displayName.trim() });
|
|
@@ -7957,8 +8071,8 @@ setup.post("/complete", async (c) => {
|
|
|
7957
8071
|
return c.json({ error: "Setup already complete" }, 400);
|
|
7958
8072
|
}
|
|
7959
8073
|
try {
|
|
7960
|
-
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-
|
|
7961
|
-
const { startSpiritFull } = await import("./mind-service-
|
|
8074
|
+
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-4ECYIVGE.js");
|
|
8075
|
+
const { startSpiritFull } = await import("./mind-service-E26ZQXDS.js");
|
|
7962
8076
|
await ensureSpiritProject();
|
|
7963
8077
|
await syncSpiritTemplate();
|
|
7964
8078
|
const warnings = [];
|
|
@@ -7995,7 +8109,7 @@ setup.post("/complete", async (c) => {
|
|
|
7995
8109
|
}
|
|
7996
8110
|
let spiritConversationId;
|
|
7997
8111
|
try {
|
|
7998
|
-
const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-
|
|
8112
|
+
const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-KRDSM55Q.js");
|
|
7999
8113
|
const { createConversation: createConversation2, findDMConversation: findDMConversation2 } = await import("./conversations-ZL6PHROD.js");
|
|
8000
8114
|
const spiritUser = await getOrCreateMindUser2(spiritName);
|
|
8001
8115
|
const brains = await listUsersByType2("human");
|
|
@@ -8018,8 +8132,8 @@ setup.post("/complete", async (c) => {
|
|
|
8018
8132
|
logger_default.info("setup complete state", { spiritConversationId, spiritStarted });
|
|
8019
8133
|
if (spiritConversationId && spiritStarted) {
|
|
8020
8134
|
try {
|
|
8021
|
-
const { deliverMessage: deliverMessage2 } = await import("./message-delivery-
|
|
8022
|
-
const { listUsersByType: listUsers2 } = await import("./auth-
|
|
8135
|
+
const { deliverMessage: deliverMessage2 } = await import("./message-delivery-7URC52ME.js");
|
|
8136
|
+
const { listUsersByType: listUsers2 } = await import("./auth-KRDSM55Q.js");
|
|
8023
8137
|
const admins = await listUsers2("human");
|
|
8024
8138
|
const admin2 = admins.find((u) => u.role === "admin");
|
|
8025
8139
|
if (admin2) {
|
|
@@ -8062,7 +8176,7 @@ var setup_default = setup;
|
|
|
8062
8176
|
// packages/daemon/src/web/api/skills.ts
|
|
8063
8177
|
import { existsSync as existsSync9, mkdtempSync, readdirSync as readdirSync3, rmSync as rmSync4 } from "fs";
|
|
8064
8178
|
import { tmpdir } from "os";
|
|
8065
|
-
import { join, resolve as
|
|
8179
|
+
import { join, resolve as resolve15 } from "path";
|
|
8066
8180
|
import AdmZip from "adm-zip";
|
|
8067
8181
|
import { Hono as Hono20 } from "hono";
|
|
8068
8182
|
var app16 = new Hono20().get("/", async (c) => {
|
|
@@ -8138,7 +8252,7 @@ var app16 = new Hono20().get("/", async (c) => {
|
|
|
8138
8252
|
try {
|
|
8139
8253
|
const zip = new AdmZip(buffer);
|
|
8140
8254
|
for (const entry of zip.getEntries()) {
|
|
8141
|
-
const target =
|
|
8255
|
+
const target = resolve15(tmpDir, entry.entryName);
|
|
8142
8256
|
if (!target.startsWith(tmpDir)) {
|
|
8143
8257
|
return c.json({ error: "Invalid zip: paths must not escape archive" }, 400);
|
|
8144
8258
|
}
|
|
@@ -8512,8 +8626,8 @@ var app20 = new Hono24().use("*", authMiddleware).get("/", async (c) => {
|
|
|
8512
8626
|
});
|
|
8513
8627
|
}, 15e3);
|
|
8514
8628
|
cleanups.push(() => clearInterval(keepAlive));
|
|
8515
|
-
await new Promise((
|
|
8516
|
-
stream.onAbort(() =>
|
|
8629
|
+
await new Promise((resolve21) => {
|
|
8630
|
+
stream.onAbort(() => resolve21());
|
|
8517
8631
|
});
|
|
8518
8632
|
} finally {
|
|
8519
8633
|
for (const cleanup of cleanups) {
|
|
@@ -8795,18 +8909,18 @@ var feed_default = app21;
|
|
|
8795
8909
|
|
|
8796
8910
|
// packages/daemon/src/web/api/variants.ts
|
|
8797
8911
|
import { existsSync as existsSync11, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "fs";
|
|
8798
|
-
import { resolve as
|
|
8912
|
+
import { resolve as resolve18 } from "path";
|
|
8799
8913
|
import { Hono as Hono26 } from "hono";
|
|
8800
8914
|
|
|
8801
8915
|
// packages/daemon/src/lib/mind/farewell.ts
|
|
8802
8916
|
import { existsSync as existsSync10, readFileSync as readFileSync10, rmSync as rmSync5 } from "fs";
|
|
8803
|
-
import { resolve as
|
|
8917
|
+
import { resolve as resolve16 } from "path";
|
|
8804
8918
|
var flog = logger_default.child("farewell");
|
|
8805
8919
|
var FAREWELL_RELPATH = ".mind/farewell.md";
|
|
8806
8920
|
var FAREWELL_MIND_PATH = "../.mind/farewell.md";
|
|
8807
8921
|
var FAREWELL_TIMEOUT_MS = 12e4;
|
|
8808
8922
|
function farewellPath(variantDir) {
|
|
8809
|
-
return
|
|
8923
|
+
return resolve16(variantDir, FAREWELL_RELPATH);
|
|
8810
8924
|
}
|
|
8811
8925
|
function readFarewell(variantDir) {
|
|
8812
8926
|
const path = farewellPath(variantDir);
|
|
@@ -8866,8 +8980,8 @@ async function runFarewellTurn(opts) {
|
|
|
8866
8980
|
|
|
8867
8981
|
// packages/daemon/src/lib/mind/spawn-server.ts
|
|
8868
8982
|
import { spawn as spawn4 } from "child_process";
|
|
8869
|
-
import { closeSync, mkdirSync as mkdirSync8, openSync, readFileSync as readFileSync11, statSync as
|
|
8870
|
-
import { resolve as
|
|
8983
|
+
import { closeSync, mkdirSync as mkdirSync8, openSync, readFileSync as readFileSync11, statSync as statSync4 } from "fs";
|
|
8984
|
+
import { resolve as resolve17 } from "path";
|
|
8871
8985
|
async function spawnServer(cwd, port, options) {
|
|
8872
8986
|
let cmd = process.env.VOLUTE_NODE_PATH ?? process.execPath;
|
|
8873
8987
|
let args = ["--import", "tsx", "src/server.ts", "--port", String(port)];
|
|
@@ -8888,34 +9002,34 @@ function spawnAttached(cmd, args, cwd) {
|
|
|
8888
9002
|
cwd,
|
|
8889
9003
|
stdio: ["ignore", "pipe", "pipe"]
|
|
8890
9004
|
});
|
|
8891
|
-
return new Promise((
|
|
8892
|
-
const timeout = setTimeout(() =>
|
|
9005
|
+
return new Promise((resolve21) => {
|
|
9006
|
+
const timeout = setTimeout(() => resolve21(null), 3e4);
|
|
8893
9007
|
function checkOutput(data) {
|
|
8894
9008
|
const match = data.toString().match(/listening on :(\d+)/);
|
|
8895
9009
|
if (match) {
|
|
8896
9010
|
clearTimeout(timeout);
|
|
8897
|
-
|
|
9011
|
+
resolve21({ child, actualPort: parseInt(match[1], 10) });
|
|
8898
9012
|
}
|
|
8899
9013
|
}
|
|
8900
9014
|
child.stdout?.on("data", checkOutput);
|
|
8901
9015
|
child.stderr?.on("data", checkOutput);
|
|
8902
9016
|
child.on("error", () => {
|
|
8903
9017
|
clearTimeout(timeout);
|
|
8904
|
-
|
|
9018
|
+
resolve21(null);
|
|
8905
9019
|
});
|
|
8906
9020
|
child.on("exit", () => {
|
|
8907
9021
|
clearTimeout(timeout);
|
|
8908
|
-
|
|
9022
|
+
resolve21(null);
|
|
8909
9023
|
});
|
|
8910
9024
|
});
|
|
8911
9025
|
}
|
|
8912
9026
|
function spawnDetached(cmd, args, cwd, logDir) {
|
|
8913
|
-
const logsDir = logDir ??
|
|
9027
|
+
const logsDir = logDir ?? resolve17(cwd, ".mind", "logs");
|
|
8914
9028
|
mkdirSync8(logsDir, { recursive: true });
|
|
8915
|
-
const logPath =
|
|
9029
|
+
const logPath = resolve17(logsDir, "mind.log");
|
|
8916
9030
|
let startOffset = 0;
|
|
8917
9031
|
try {
|
|
8918
|
-
startOffset =
|
|
9032
|
+
startOffset = statSync4(logPath).size;
|
|
8919
9033
|
} catch {
|
|
8920
9034
|
}
|
|
8921
9035
|
const logFd = openSync(logPath, "a");
|
|
@@ -9053,11 +9167,11 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
|
|
|
9053
9167
|
return c.json({ error: `Name already in use: ${variantName}` }, 409);
|
|
9054
9168
|
}
|
|
9055
9169
|
const projectRoot = entry.dir ?? mindDir(mindName);
|
|
9056
|
-
const variantDir =
|
|
9170
|
+
const variantDir = resolve18(projectRoot, ".variants", variantName);
|
|
9057
9171
|
if (existsSync11(variantDir)) {
|
|
9058
9172
|
return c.json({ error: `Variant directory already exists: ${variantDir}` }, 409);
|
|
9059
9173
|
}
|
|
9060
|
-
mkdirSync9(
|
|
9174
|
+
mkdirSync9(resolve18(projectRoot, ".variants"), { recursive: true });
|
|
9061
9175
|
try {
|
|
9062
9176
|
await gitExec(["worktree", "add", "-b", variantName, variantDir], { cwd: projectRoot });
|
|
9063
9177
|
} catch (e) {
|
|
@@ -9093,7 +9207,7 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
|
|
|
9093
9207
|
const [cmd, args] = await wrapForIsolation("npm", ["install"], mindName);
|
|
9094
9208
|
await exec(cmd, args, {
|
|
9095
9209
|
cwd: variantDir,
|
|
9096
|
-
env: { ...process.env, HOME:
|
|
9210
|
+
env: { ...process.env, HOME: resolve18(variantDir, "home") }
|
|
9097
9211
|
});
|
|
9098
9212
|
} else {
|
|
9099
9213
|
await exec("npm", ["install"], { cwd: variantDir });
|
|
@@ -9104,7 +9218,7 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
|
|
|
9104
9218
|
return c.json({ error: `npm install failed: ${msg}` }, 500);
|
|
9105
9219
|
}
|
|
9106
9220
|
if (body.soul) {
|
|
9107
|
-
writeFileSync9(
|
|
9221
|
+
writeFileSync9(resolve18(variantDir, "home/SOUL.md"), body.soul);
|
|
9108
9222
|
}
|
|
9109
9223
|
const variantPort = body.port ?? await nextPort();
|
|
9110
9224
|
try {
|
|
@@ -9157,7 +9271,7 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
|
|
|
9157
9271
|
} catch {
|
|
9158
9272
|
}
|
|
9159
9273
|
const projectRoot = parentEntry.dir ?? mindDir(mindName);
|
|
9160
|
-
const failAfterGitWrite = async (message, extra) => {
|
|
9274
|
+
const failAfterGitWrite = async (message, extra, status = 500) => {
|
|
9161
9275
|
try {
|
|
9162
9276
|
await chownMindDir(projectRoot, mindName);
|
|
9163
9277
|
} catch (err) {
|
|
@@ -9173,7 +9287,7 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
|
|
|
9173
9287
|
500
|
|
9174
9288
|
);
|
|
9175
9289
|
}
|
|
9176
|
-
return c.json({ error: message, ...extra },
|
|
9290
|
+
return c.json({ error: message, ...extra }, status);
|
|
9177
9291
|
};
|
|
9178
9292
|
let farewell;
|
|
9179
9293
|
try {
|
|
@@ -9245,6 +9359,27 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
|
|
|
9245
9359
|
{ conflicts: err.conflicts }
|
|
9246
9360
|
);
|
|
9247
9361
|
}
|
|
9362
|
+
if (existsSync11(variantEntry.dir) && !body.discardUnresolved) {
|
|
9363
|
+
let unresolved;
|
|
9364
|
+
try {
|
|
9365
|
+
unresolved = await findUnresolvedHomeFiles(variantEntry.dir);
|
|
9366
|
+
} catch (err) {
|
|
9367
|
+
return failAfterGitWrite(
|
|
9368
|
+
`Could not verify variant ${variantName} has no unresolved home/ files: ${err instanceof Error ? err.message : String(err)}. Variant left intact \u2014 retry the join.`
|
|
9369
|
+
);
|
|
9370
|
+
}
|
|
9371
|
+
if (unresolved.totalCount > 0) {
|
|
9372
|
+
return failAfterGitWrite(
|
|
9373
|
+
formatUnresolvedHomeFilesMessage(variantName, unresolved),
|
|
9374
|
+
{
|
|
9375
|
+
unresolvedFiles: unresolved.files,
|
|
9376
|
+
unresolvedCount: unresolved.totalCount,
|
|
9377
|
+
unresolvedBytes: unresolved.totalBytes
|
|
9378
|
+
},
|
|
9379
|
+
409
|
|
9380
|
+
);
|
|
9381
|
+
}
|
|
9382
|
+
}
|
|
9248
9383
|
await cleanupVariant(variantName, mindName, projectRoot, variantEntry.dir, { stop: true });
|
|
9249
9384
|
await chownMindDir(projectRoot, mindName);
|
|
9250
9385
|
if (variantName.endsWith("-upgrade") || variantName === "upgrade") {
|
|
@@ -9263,7 +9398,7 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
|
|
|
9263
9398
|
const [cmd, args] = await wrapForIsolation("npm", ["install"], mindName);
|
|
9264
9399
|
await exec(cmd, args, {
|
|
9265
9400
|
cwd: projectRoot,
|
|
9266
|
-
env: { ...process.env, HOME:
|
|
9401
|
+
env: { ...process.env, HOME: resolve18(projectRoot, "home") }
|
|
9267
9402
|
});
|
|
9268
9403
|
} else {
|
|
9269
9404
|
await exec("npm", ["install"], { cwd: projectRoot });
|
|
@@ -9750,11 +9885,11 @@ var app24 = new Hono28().get("/:name/conversations/:id/events", async (c) => {
|
|
|
9750
9885
|
if (!stream.aborted) console.error("[chat] SSE ping error:", err);
|
|
9751
9886
|
});
|
|
9752
9887
|
}, 15e3);
|
|
9753
|
-
await new Promise((
|
|
9888
|
+
await new Promise((resolve21) => {
|
|
9754
9889
|
stream.onAbort(() => {
|
|
9755
9890
|
unsubscribe();
|
|
9756
9891
|
clearInterval(keepAlive);
|
|
9757
|
-
|
|
9892
|
+
resolve21();
|
|
9758
9893
|
});
|
|
9759
9894
|
});
|
|
9760
9895
|
});
|
|
@@ -9974,7 +10109,7 @@ var app_default = app26;
|
|
|
9974
10109
|
import { existsSync as existsSync12 } from "fs";
|
|
9975
10110
|
import { readFile as readFile2, stat as stat2 } from "fs/promises";
|
|
9976
10111
|
import { createServer as createHttpsServer } from "https";
|
|
9977
|
-
import { dirname as dirname3, extname as extname3, resolve as
|
|
10112
|
+
import { dirname as dirname3, extname as extname3, resolve as resolve19 } from "path";
|
|
9978
10113
|
import { serve } from "@hono/node-server";
|
|
9979
10114
|
var MIME_TYPES2 = {
|
|
9980
10115
|
".html": "text/html",
|
|
@@ -9993,7 +10128,7 @@ async function startServer({
|
|
|
9993
10128
|
let assetsDir = "";
|
|
9994
10129
|
let searchDir = dirname3(new URL(import.meta.url).pathname);
|
|
9995
10130
|
for (let i = 0; i < 5; i++) {
|
|
9996
|
-
const candidate =
|
|
10131
|
+
const candidate = resolve19(searchDir, "dist", "web-assets");
|
|
9997
10132
|
if (existsSync12(candidate)) {
|
|
9998
10133
|
assetsDir = candidate;
|
|
9999
10134
|
break;
|
|
@@ -10004,7 +10139,7 @@ async function startServer({
|
|
|
10004
10139
|
app_default.get("*", async (c) => {
|
|
10005
10140
|
const urlPath = new URL(c.req.url).pathname;
|
|
10006
10141
|
if (urlPath.startsWith("/api/") || urlPath.startsWith("/ext/")) return c.notFound();
|
|
10007
|
-
const filePath =
|
|
10142
|
+
const filePath = resolve19(assetsDir, urlPath.slice(1));
|
|
10008
10143
|
if (!filePath.startsWith(assetsDir)) return c.text("Forbidden", 403);
|
|
10009
10144
|
const s = await stat2(filePath).catch(() => null);
|
|
10010
10145
|
if (s?.isFile()) {
|
|
@@ -10017,7 +10152,7 @@ async function startServer({
|
|
|
10017
10152
|
const cacheControl = isHashed ? "public, max-age=31536000, immutable" : "no-cache";
|
|
10018
10153
|
return c.body(body, 200, { "Content-Type": mime, "Cache-Control": cacheControl });
|
|
10019
10154
|
}
|
|
10020
|
-
const indexPath =
|
|
10155
|
+
const indexPath = resolve19(assetsDir, "index.html");
|
|
10021
10156
|
const indexStat = await stat2(indexPath).catch(() => null);
|
|
10022
10157
|
if (indexStat?.isFile()) {
|
|
10023
10158
|
const body = await readFile2(indexPath, "utf-8");
|
|
@@ -10034,10 +10169,10 @@ async function startServer({
|
|
|
10034
10169
|
createServer: createHttpsServer,
|
|
10035
10170
|
serverOptions: { key: tls.key, cert: tls.cert }
|
|
10036
10171
|
});
|
|
10037
|
-
await new Promise((
|
|
10172
|
+
await new Promise((resolve21, reject) => {
|
|
10038
10173
|
server2.on("listening", () => {
|
|
10039
10174
|
logger_default.info("Volute UI running (https)", { hostname, port });
|
|
10040
|
-
|
|
10175
|
+
resolve21();
|
|
10041
10176
|
});
|
|
10042
10177
|
server2.on("error", (err) => {
|
|
10043
10178
|
reject(err);
|
|
@@ -10045,13 +10180,13 @@ async function startServer({
|
|
|
10045
10180
|
});
|
|
10046
10181
|
const internalPort = port + 1;
|
|
10047
10182
|
const internalServer = serve({ fetch: app_default.fetch, port: internalPort, hostname: "127.0.0.1" });
|
|
10048
|
-
await new Promise((
|
|
10183
|
+
await new Promise((resolve21, reject) => {
|
|
10049
10184
|
internalServer.on("listening", () => {
|
|
10050
10185
|
logger_default.info("Volute API running (http, internal)", {
|
|
10051
10186
|
hostname: "127.0.0.1",
|
|
10052
10187
|
port: internalPort
|
|
10053
10188
|
});
|
|
10054
|
-
|
|
10189
|
+
resolve21();
|
|
10055
10190
|
});
|
|
10056
10191
|
internalServer.on("error", (err) => {
|
|
10057
10192
|
reject(err);
|
|
@@ -10060,10 +10195,10 @@ async function startServer({
|
|
|
10060
10195
|
return { server: server2, internalPort };
|
|
10061
10196
|
}
|
|
10062
10197
|
const server = serve({ fetch: app_default.fetch, port, hostname });
|
|
10063
|
-
await new Promise((
|
|
10198
|
+
await new Promise((resolve21, reject) => {
|
|
10064
10199
|
server.on("listening", () => {
|
|
10065
10200
|
logger_default.info("Volute API running (http)", { hostname, port });
|
|
10066
|
-
|
|
10201
|
+
resolve21();
|
|
10067
10202
|
});
|
|
10068
10203
|
server.on("error", (err) => {
|
|
10069
10204
|
reject(err);
|
|
@@ -10074,17 +10209,17 @@ async function startServer({
|
|
|
10074
10209
|
|
|
10075
10210
|
// packages/daemon/src/daemon.ts
|
|
10076
10211
|
if (!process.env.VOLUTE_HOME) {
|
|
10077
|
-
process.env.VOLUTE_HOME =
|
|
10212
|
+
process.env.VOLUTE_HOME = resolve20(homedir3(), ".volute");
|
|
10078
10213
|
}
|
|
10079
10214
|
if (process.env.VOLUTE_TIMEZONE && !process.env.TZ) {
|
|
10080
10215
|
process.env.TZ = process.env.VOLUTE_TIMEZONE;
|
|
10081
10216
|
}
|
|
10082
10217
|
function writeDaemonConfig(systemDir, config2, token) {
|
|
10083
|
-
const configPath =
|
|
10218
|
+
const configPath = resolve20(systemDir, "daemon.json");
|
|
10084
10219
|
writeFileSync10(configPath, `${JSON.stringify(config2, null, 2)}
|
|
10085
10220
|
`, { mode: 420 });
|
|
10086
10221
|
chmodSync(configPath, 420);
|
|
10087
|
-
const tokenPath =
|
|
10222
|
+
const tokenPath = resolve20(systemDir, "daemon-token");
|
|
10088
10223
|
writeFileSync10(tokenPath, `${token}
|
|
10089
10224
|
`, { mode: 384 });
|
|
10090
10225
|
chmodSync(tokenPath, 384);
|
|
@@ -10095,7 +10230,7 @@ async function startDaemon(opts) {
|
|
|
10095
10230
|
const home = voluteHome();
|
|
10096
10231
|
const systemDir = voluteSystemDir();
|
|
10097
10232
|
if (!opts.foreground) {
|
|
10098
|
-
const rotatingLog = new RotatingLog(
|
|
10233
|
+
const rotatingLog = new RotatingLog(resolve20(systemDir, "daemon.log"));
|
|
10099
10234
|
logger_default.setOutput((line) => rotatingLog.write(`${line}
|
|
10100
10235
|
`));
|
|
10101
10236
|
const write = (...args) => rotatingLog.write(`${format(...args)}
|
|
@@ -10105,9 +10240,9 @@ async function startDaemon(opts) {
|
|
|
10105
10240
|
console.warn = write;
|
|
10106
10241
|
console.info = write;
|
|
10107
10242
|
}
|
|
10108
|
-
const DAEMON_PID_PATH =
|
|
10109
|
-
const DAEMON_JSON_PATH =
|
|
10110
|
-
const DAEMON_TOKEN_PATH =
|
|
10243
|
+
const DAEMON_PID_PATH = resolve20(systemDir, "daemon.pid");
|
|
10244
|
+
const DAEMON_JSON_PATH = resolve20(systemDir, "daemon.json");
|
|
10245
|
+
const DAEMON_TOKEN_PATH = resolve20(systemDir, "daemon-token");
|
|
10111
10246
|
mkdirSync10(home, { recursive: true });
|
|
10112
10247
|
ensureSystemDir();
|
|
10113
10248
|
const { migrateConfigSecrets, migrateSetupCompleted } = await import("./setup-WZSXHHRJ.js");
|
|
@@ -10168,7 +10303,7 @@ async function startDaemon(opts) {
|
|
|
10168
10303
|
logger_default.warn("failed to backfill minds into #system", logger_default.errorData(err));
|
|
10169
10304
|
}
|
|
10170
10305
|
try {
|
|
10171
|
-
const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-
|
|
10306
|
+
const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-KRDSM55Q.js");
|
|
10172
10307
|
await getOrCreateSystemUser2();
|
|
10173
10308
|
} catch (err) {
|
|
10174
10309
|
logger_default.warn(
|
|
@@ -10236,7 +10371,7 @@ async function startDaemon(opts) {
|
|
|
10236
10371
|
const orphanedTurns = await completeOrphanedTurns();
|
|
10237
10372
|
summarizeOrphanedTurns(orphanedTurns);
|
|
10238
10373
|
try {
|
|
10239
|
-
const { reconcileVariants } = await import("./variant-cleanup-
|
|
10374
|
+
const { reconcileVariants } = await import("./variant-cleanup-STC6B5HR.js");
|
|
10240
10375
|
await reconcileVariants();
|
|
10241
10376
|
} catch (err) {
|
|
10242
10377
|
logger_default.error("failed to reconcile variants", logger_default.errorData(err));
|
|
@@ -10272,8 +10407,8 @@ async function startDaemon(opts) {
|
|
|
10272
10407
|
try {
|
|
10273
10408
|
const { isSetupComplete: isSetupComplete2, getSpiritName: getSpiritName2 } = await import("./setup-WZSXHHRJ.js");
|
|
10274
10409
|
if (isSetupComplete2()) {
|
|
10275
|
-
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-
|
|
10276
|
-
const { startSpiritFull } = await import("./mind-service-
|
|
10410
|
+
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-4ECYIVGE.js");
|
|
10411
|
+
const { startSpiritFull } = await import("./mind-service-E26ZQXDS.js");
|
|
10277
10412
|
await ensureSpiritProject();
|
|
10278
10413
|
const spiritName = getSpiritName2();
|
|
10279
10414
|
const spiritEntry = await findMind(spiritName);
|
|
@@ -10292,7 +10427,7 @@ async function startDaemon(opts) {
|
|
|
10292
10427
|
bridgeManager.startBridges(daemonPort).catch((err) => {
|
|
10293
10428
|
logger_default.warn("failed to start bridges", logger_default.errorData(err));
|
|
10294
10429
|
});
|
|
10295
|
-
import("./cloud-sync-
|
|
10430
|
+
import("./cloud-sync-H7EWZASD.js").then(
|
|
10296
10431
|
({ consumeQueuedMessages }) => consumeQueuedMessages().catch((err) => {
|
|
10297
10432
|
logger_default.warn("failed to consume queued cloud messages", logger_default.errorData(err));
|
|
10298
10433
|
})
|
|
@@ -10300,7 +10435,7 @@ async function startDaemon(opts) {
|
|
|
10300
10435
|
logger_default.warn("failed to load cloud-sync module", logger_default.errorData(err));
|
|
10301
10436
|
});
|
|
10302
10437
|
try {
|
|
10303
|
-
const { backfillTemplateHashes, notifyVersionUpdate, warnStaleTemplates } = await import("./version-notify-
|
|
10438
|
+
const { backfillTemplateHashes, notifyVersionUpdate, warnStaleTemplates } = await import("./version-notify-LBVHH5YV.js");
|
|
10304
10439
|
backfillTemplateHashes().then(() => warnStaleTemplates()).catch((err) => {
|
|
10305
10440
|
logger_default.warn("failed to check template staleness", logger_default.errorData(err));
|
|
10306
10441
|
});
|