volute 0.12.0 → 0.13.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.
Files changed (61) hide show
  1. package/dist/{agent-2AQPI3QV.js → agent-HYX2ZTFM.js} +10 -10
  2. package/dist/{agent-manager-RMWXST3T.js → agent-manager-HHBAAL2D.js} +4 -4
  3. package/dist/{channel-2WHBRDTD.js → channel-72YET5JC.js} +2 -2
  4. package/dist/{chunk-QF22MYDJ.js → chunk-BJDLYTPS.js} +1 -1
  5. package/dist/{chunk-46S7YHUB.js → chunk-EN3NHRQC.js} +12 -19
  6. package/dist/{chunk-DP2DX4WV.js → chunk-ESTOWEG2.js} +12 -3
  7. package/dist/{chunk-POLMWJFC.js → chunk-GPZCPGV3.js} +1 -1
  8. package/dist/{chunk-ZKNBD5P3.js → chunk-IELXXS7E.js} +2 -2
  9. package/dist/{chunk-STOEJOJO.js → chunk-J3IHIXDB.js} +1 -1
  10. package/dist/{chunk-R3VB7NF5.js → chunk-KYHC7LHS.js} +2 -2
  11. package/dist/{chunk-YY2QX2J6.js → chunk-LG4ROCHN.js} +1 -1
  12. package/dist/{chunk-PHJCXAWJ.js → chunk-NQKKTRET.js} +19 -37
  13. package/dist/{chunk-IZEQ47HW.js → chunk-PEQQ7MRI.js} +2 -2
  14. package/dist/{chunk-WKPMR5B2.js → chunk-PTK3GBCG.js} +2 -2
  15. package/dist/{chunk-RGWADNLT.js → chunk-RH3XLDY2.js} +2 -2
  16. package/dist/{chunk-WTJI3JVR.js → chunk-VRAOTXDF.js} +9 -6
  17. package/dist/chunk-XUA3JUFK.js +121 -0
  18. package/dist/cli.js +26 -17
  19. package/dist/{connector-L2HBLZBW.js → connector-Z5KYVTZ5.js} +2 -2
  20. package/dist/connectors/discord.js +2 -2
  21. package/dist/connectors/slack.js +2 -2
  22. package/dist/connectors/telegram.js +2 -2
  23. package/dist/{create-VBZZNJOG.js → create-AAI52BC2.js} +1 -1
  24. package/dist/{daemon-client-P44NU3KU.js → daemon-client-WXN43USO.js} +2 -2
  25. package/dist/{daemon-restart-IVJ7X4PF.js → daemon-restart-4OXIGWV6.js} +6 -5
  26. package/dist/daemon.js +502 -540
  27. package/dist/{delete-BOTVU4YO.js → delete-BJ3LNU2I.js} +1 -1
  28. package/dist/down-IMZE7V42.js +14 -0
  29. package/dist/{env-CGORIKVF.js → env-EOO2C7L7.js} +2 -2
  30. package/dist/{history-NI5QP27M.js → history-J7TURCZS.js} +2 -2
  31. package/dist/{import-2BZUWT23.js → import-TKF67X4R.js} +3 -3
  32. package/dist/{logs-APWVWGNX.js → logs-KHBOS6IZ.js} +2 -2
  33. package/dist/{package-5LQNWBH7.js → package-TPXKJXLG.js} +1 -1
  34. package/dist/{restart-CCYM3MEC.js → restart-CMP63H6A.js} +2 -2
  35. package/dist/{schedule-E4MFGYSA.js → schedule-YMAJZ52M.js} +2 -2
  36. package/dist/seed-M6QPHFTV.js +68 -0
  37. package/dist/{send-V5ESR5O2.js → send-EZYEIVMA.js} +18 -6
  38. package/dist/{service-UL3OCODG.js → service-DDFZA7Q3.js} +4 -3
  39. package/dist/{setup-7N4KYOYN.js → setup-DCZWBBD7.js} +7 -7
  40. package/dist/sprout-EAWETTWZ.js +89 -0
  41. package/dist/{start-6YRS6FF6.js → start-54JXJ7VV.js} +2 -2
  42. package/dist/{status-DFWM342I.js → status-PMMS4XUH.js} +7 -5
  43. package/dist/{stop-UQSNF4CG.js → stop-WXU42NWP.js} +2 -2
  44. package/dist/{up-A6XT6AFX.js → up-N2OWDCT6.js} +5 -4
  45. package/dist/{update-PV3XM6DX.js → update-FXLGIIWH.js} +5 -4
  46. package/dist/{update-check-YPGH5X4E.js → update-check-NBHTSTHK.js} +2 -2
  47. package/dist/{upgrade-RSE4CZNE.js → upgrade-TEI7N6CQ.js} +1 -1
  48. package/dist/{variant-7IZF6OWO.js → variant-ZCZS3JAP.js} +4 -4
  49. package/dist/web-assets/assets/index-TqXd1QOX.js +307 -0
  50. package/dist/web-assets/index.html +1 -1
  51. package/package.json +1 -1
  52. package/templates/_base/_skills/orientation/SKILL.md +58 -0
  53. package/templates/_base/home/.config/config.json.tmpl +3 -0
  54. package/templates/_base/src/lib/startup.ts +8 -4
  55. package/templates/agent-sdk/volute-template.json +1 -1
  56. package/templates/pi/home/.config/config.json.tmpl +3 -0
  57. package/templates/pi/volute-template.json +1 -1
  58. package/dist/down-O2EQJ5DO.js +0 -13
  59. package/dist/web-assets/assets/index-D-3zx6vs.js +0 -307
  60. package/templates/_base/home/.config/volute.json.tmpl +0 -3
  61. package/templates/pi/home/.config/volute.json.tmpl +0 -3
package/dist/daemon.js CHANGED
@@ -1,4 +1,11 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ applyInitFiles,
4
+ composeTemplate,
5
+ copyTemplateToDir,
6
+ findTemplatesRoot,
7
+ listFiles
8
+ } from "./chunk-XUA3JUFK.js";
2
9
  import {
3
10
  RotatingLog,
4
11
  clearJsonMap,
@@ -6,16 +13,7 @@ import {
6
13
  initAgentManager,
7
14
  loadJsonMap,
8
15
  saveJsonMap
9
- } from "./chunk-PHJCXAWJ.js";
10
- import {
11
- applyIsolation,
12
- chownAgentDir,
13
- createAgentUser,
14
- deleteAgentUser,
15
- ensureVoluteGroup,
16
- getAgentUserIds,
17
- isIsolationEnabled
18
- } from "./chunk-46S7YHUB.js";
16
+ } from "./chunk-NQKKTRET.js";
19
17
  import {
20
18
  findOpenClawSession,
21
19
  importOpenClawConnectors,
@@ -23,33 +21,41 @@ import {
23
21
  parseNameFromIdentity,
24
22
  readVoluteConfig,
25
23
  writeVoluteConfig
26
- } from "./chunk-R3VB7NF5.js";
24
+ } from "./chunk-KYHC7LHS.js";
27
25
  import {
28
26
  agentEnvPath,
29
27
  loadMergedEnv,
30
28
  readEnv,
31
29
  sharedEnvPath,
32
30
  writeEnv
33
- } from "./chunk-QF22MYDJ.js";
31
+ } from "./chunk-BJDLYTPS.js";
34
32
  import {
35
33
  CHANNELS,
36
34
  getChannelDriver
37
- } from "./chunk-WKPMR5B2.js";
35
+ } from "./chunk-PTK3GBCG.js";
38
36
  import {
39
37
  exec,
40
38
  gitExec,
41
39
  resolveVoluteBin
42
- } from "./chunk-WTJI3JVR.js";
40
+ } from "./chunk-VRAOTXDF.js";
41
+ import {
42
+ chownAgentDir,
43
+ createAgentUser,
44
+ deleteAgentUser,
45
+ ensureVoluteGroup,
46
+ isIsolationEnabled,
47
+ wrapForIsolation
48
+ } from "./chunk-EN3NHRQC.js";
43
49
  import {
44
50
  checkForUpdate,
45
51
  checkForUpdateCached,
46
52
  getCurrentVersion
47
- } from "./chunk-YY2QX2J6.js";
53
+ } from "./chunk-LG4ROCHN.js";
48
54
  import "./chunk-D424ZQGI.js";
49
55
  import {
50
56
  buildVoluteSlug,
51
57
  writeChannelEntry
52
- } from "./chunk-POLMWJFC.js";
58
+ } from "./chunk-GPZCPGV3.js";
53
59
  import {
54
60
  addAgent,
55
61
  addVariant,
@@ -72,16 +78,16 @@ import {
72
78
  validateAgentName,
73
79
  validateBranchName,
74
80
  voluteHome
75
- } from "./chunk-DP2DX4WV.js";
81
+ } from "./chunk-ESTOWEG2.js";
76
82
  import {
77
83
  __export
78
84
  } from "./chunk-K3NQKI34.js";
79
85
 
80
86
  // src/daemon.ts
81
87
  import { randomBytes } from "crypto";
82
- import { mkdirSync as mkdirSync8, readFileSync as readFileSync9, unlinkSync as unlinkSync2, writeFileSync as writeFileSync7 } from "fs";
88
+ import { mkdirSync as mkdirSync7, readFileSync as readFileSync8, unlinkSync as unlinkSync2, writeFileSync as writeFileSync6 } from "fs";
83
89
  import { homedir as homedir2 } from "os";
84
- import { resolve as resolve16 } from "path";
90
+ import { resolve as resolve15 } from "path";
85
91
  import { format } from "util";
86
92
 
87
93
  // src/lib/connector-manager.ts
@@ -277,8 +283,8 @@ var ConnectorManager = class {
277
283
  ...connectorEnv
278
284
  }
279
285
  };
280
- await applyIsolation(spawnOpts, agentName);
281
- const child = spawn(runtime, [connectorScript], spawnOpts);
286
+ const [spawnCmd, spawnArgs] = wrapForIsolation(runtime, [connectorScript], agentName);
287
+ const child = spawn(spawnCmd, spawnArgs, spawnOpts);
282
288
  let lastStderr = "";
283
289
  child.stdout?.pipe(logStream);
284
290
  child.stderr?.on("data", (chunk) => {
@@ -332,19 +338,19 @@ var ConnectorManager = class {
332
338
  const stopKey = `${agentName}:${type}`;
333
339
  this.stopping.add(stopKey);
334
340
  agentMap.delete(type);
335
- await new Promise((resolve17) => {
336
- tracked.child.on("exit", () => resolve17());
341
+ await new Promise((resolve16) => {
342
+ tracked.child.on("exit", () => resolve16());
337
343
  try {
338
344
  tracked.child.kill("SIGTERM");
339
345
  } catch {
340
- resolve17();
346
+ resolve16();
341
347
  }
342
348
  setTimeout(() => {
343
349
  try {
344
350
  tracked.child.kill("SIGKILL");
345
351
  } catch {
346
352
  }
347
- resolve17();
353
+ resolve16();
348
354
  }, 5e3);
349
355
  });
350
356
  this.stopping.delete(stopKey);
@@ -1054,9 +1060,9 @@ var authMiddleware = createMiddleware(async (c, next) => {
1054
1060
  });
1055
1061
 
1056
1062
  // src/web/server.ts
1057
- import { existsSync as existsSync10 } from "fs";
1063
+ import { existsSync as existsSync9 } from "fs";
1058
1064
  import { readFile as readFile2, stat } from "fs/promises";
1059
- import { dirname as dirname4, extname, resolve as resolve15 } from "path";
1065
+ import { dirname as dirname3, extname, resolve as resolve14 } from "path";
1060
1066
  import { serve } from "@hono/node-server";
1061
1067
 
1062
1068
  // src/lib/log-buffer.ts
@@ -1111,17 +1117,19 @@ import { HTTPException } from "hono/http-exception";
1111
1117
 
1112
1118
  // src/web/routes/agents.ts
1113
1119
  import {
1114
- cpSync as cpSync2,
1115
- existsSync as existsSync6,
1116
- mkdirSync as mkdirSync5,
1117
- readdirSync as readdirSync4,
1118
- readFileSync as readFileSync6,
1119
- rmSync as rmSync2,
1120
- writeFileSync as writeFileSync5
1120
+ cpSync,
1121
+ existsSync as existsSync5,
1122
+ mkdirSync as mkdirSync4,
1123
+ readdirSync as readdirSync3,
1124
+ readFileSync as readFileSync5,
1125
+ rmSync,
1126
+ writeFileSync as writeFileSync4
1121
1127
  } from "fs";
1122
- import { resolve as resolve9 } from "path";
1123
- import { and as and2, desc, eq as eq3 } from "drizzle-orm";
1128
+ import { resolve as resolve8 } from "path";
1129
+ import { zValidator } from "@hono/zod-validator";
1130
+ import { and as and3, desc as desc2, eq as eq4, sql as sql3 } from "drizzle-orm";
1124
1131
  import { Hono } from "hono";
1132
+ import { z } from "zod";
1125
1133
 
1126
1134
  // src/lib/consolidate.ts
1127
1135
  import { readdirSync as readdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
@@ -1194,14 +1202,209 @@ ${content2}`);
1194
1202
  }
1195
1203
  }
1196
1204
 
1197
- // src/lib/convert-session.ts
1205
+ // src/lib/conversations.ts
1198
1206
  import { randomUUID } from "crypto";
1207
+ import { and as and2, desc, eq as eq3, inArray, isNull, sql as sql2 } from "drizzle-orm";
1208
+
1209
+ // src/lib/conversation-events.ts
1210
+ var subscribers = /* @__PURE__ */ new Map();
1211
+ function subscribe(conversationId, callback) {
1212
+ let set = subscribers.get(conversationId);
1213
+ if (!set) {
1214
+ set = /* @__PURE__ */ new Set();
1215
+ subscribers.set(conversationId, set);
1216
+ }
1217
+ set.add(callback);
1218
+ return () => {
1219
+ set.delete(callback);
1220
+ if (set.size === 0) subscribers.delete(conversationId);
1221
+ };
1222
+ }
1223
+ function publish(conversationId, event) {
1224
+ const set = subscribers.get(conversationId);
1225
+ if (!set) return;
1226
+ for (const cb of set) {
1227
+ try {
1228
+ cb(event);
1229
+ } catch (err) {
1230
+ console.error("[conversation-events] subscriber threw:", err);
1231
+ set.delete(cb);
1232
+ if (set.size === 0) subscribers.delete(conversationId);
1233
+ }
1234
+ }
1235
+ }
1236
+
1237
+ // src/lib/conversations.ts
1238
+ async function createConversation(agentName, channel, opts) {
1239
+ const db2 = await getDb();
1240
+ const id = randomUUID();
1241
+ await db2.insert(conversations).values({
1242
+ id,
1243
+ agent_name: agentName,
1244
+ channel,
1245
+ user_id: opts?.userId ?? null,
1246
+ title: opts?.title ?? null
1247
+ });
1248
+ if (opts?.participantIds && opts.participantIds.length > 0) {
1249
+ await db2.insert(conversationParticipants).values(
1250
+ opts.participantIds.map((uid, i) => ({
1251
+ conversation_id: id,
1252
+ user_id: uid,
1253
+ role: i === 0 ? "owner" : "member"
1254
+ }))
1255
+ );
1256
+ }
1257
+ return {
1258
+ id,
1259
+ agent_name: agentName,
1260
+ channel,
1261
+ user_id: opts?.userId ?? null,
1262
+ title: opts?.title ?? null,
1263
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
1264
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
1265
+ };
1266
+ }
1267
+ async function getConversation(id) {
1268
+ const db2 = await getDb();
1269
+ const row = await db2.select().from(conversations).where(eq3(conversations.id, id)).get();
1270
+ return row ?? null;
1271
+ }
1272
+ async function getParticipants(conversationId) {
1273
+ const db2 = await getDb();
1274
+ const rows = await db2.select({
1275
+ userId: conversationParticipants.user_id,
1276
+ username: users.username,
1277
+ userType: users.user_type,
1278
+ role: conversationParticipants.role
1279
+ }).from(conversationParticipants).innerJoin(users, eq3(conversationParticipants.user_id, users.id)).where(eq3(conversationParticipants.conversation_id, conversationId)).all();
1280
+ return rows;
1281
+ }
1282
+ async function isParticipant(conversationId, userId) {
1283
+ const db2 = await getDb();
1284
+ const row = await db2.select({ user_id: conversationParticipants.user_id }).from(conversationParticipants).where(
1285
+ and2(
1286
+ eq3(conversationParticipants.conversation_id, conversationId),
1287
+ eq3(conversationParticipants.user_id, userId)
1288
+ )
1289
+ ).get();
1290
+ return row != null;
1291
+ }
1292
+ async function listConversationsForUser(userId) {
1293
+ const db2 = await getDb();
1294
+ const participantRows = await db2.select({ conversation_id: conversationParticipants.conversation_id }).from(conversationParticipants).where(eq3(conversationParticipants.user_id, userId)).all();
1295
+ if (participantRows.length === 0) return [];
1296
+ const convIds = participantRows.map((r) => r.conversation_id);
1297
+ return db2.select().from(conversations).where(inArray(conversations.id, convIds)).orderBy(desc(conversations.updated_at)).all();
1298
+ }
1299
+ async function isParticipantOrOwner(conversationId, userId) {
1300
+ if (await isParticipant(conversationId, userId)) return true;
1301
+ const db2 = await getDb();
1302
+ const row = await db2.select().from(conversations).where(and2(eq3(conversations.id, conversationId), eq3(conversations.user_id, userId))).get();
1303
+ return row != null;
1304
+ }
1305
+ async function deleteConversationForUser(id, userId) {
1306
+ if (!await isParticipantOrOwner(id, userId)) return false;
1307
+ await deleteConversation(id);
1308
+ return true;
1309
+ }
1310
+ async function addMessage(conversationId, role, senderName, content) {
1311
+ const db2 = await getDb();
1312
+ const serialized = JSON.stringify(content);
1313
+ const [result] = await db2.insert(messages).values({ conversation_id: conversationId, role, sender_name: senderName, content: serialized }).returning({ id: messages.id, created_at: messages.created_at });
1314
+ await db2.update(conversations).set({ updated_at: sql2`datetime('now')` }).where(eq3(conversations.id, conversationId));
1315
+ if (role === "user") {
1316
+ const firstText = content.find((b) => b.type === "text");
1317
+ const title = firstText ? firstText.text.slice(0, 80) : "";
1318
+ if (title) {
1319
+ await db2.update(conversations).set({ title }).where(and2(eq3(conversations.id, conversationId), isNull(conversations.title)));
1320
+ }
1321
+ }
1322
+ const msg = {
1323
+ id: result.id,
1324
+ conversation_id: conversationId,
1325
+ role,
1326
+ sender_name: senderName,
1327
+ content,
1328
+ created_at: result.created_at
1329
+ };
1330
+ publish(conversationId, {
1331
+ type: "message",
1332
+ id: msg.id,
1333
+ role: msg.role,
1334
+ senderName: msg.sender_name,
1335
+ content: msg.content,
1336
+ createdAt: msg.created_at
1337
+ });
1338
+ return msg;
1339
+ }
1340
+ async function getMessages(conversationId) {
1341
+ const db2 = await getDb();
1342
+ const rows = await db2.select().from(messages).where(eq3(messages.conversation_id, conversationId)).orderBy(messages.created_at).all();
1343
+ return rows.map((row) => {
1344
+ let content;
1345
+ try {
1346
+ const parsed = JSON.parse(row.content);
1347
+ content = Array.isArray(parsed) ? parsed : [{ type: "text", text: row.content }];
1348
+ } catch {
1349
+ content = [{ type: "text", text: row.content }];
1350
+ }
1351
+ return { ...row, content };
1352
+ });
1353
+ }
1354
+ async function listConversationsWithParticipants(userId) {
1355
+ const convs = await listConversationsForUser(userId);
1356
+ if (convs.length === 0) return [];
1357
+ const db2 = await getDb();
1358
+ const convIds = convs.map((c) => c.id);
1359
+ const rows = await db2.select({
1360
+ conversationId: conversationParticipants.conversation_id,
1361
+ userId: users.id,
1362
+ username: users.username,
1363
+ userType: users.user_type,
1364
+ role: conversationParticipants.role
1365
+ }).from(conversationParticipants).innerJoin(users, eq3(conversationParticipants.user_id, users.id)).where(inArray(conversationParticipants.conversation_id, convIds));
1366
+ const byConv = /* @__PURE__ */ new Map();
1367
+ for (const r of rows) {
1368
+ let arr = byConv.get(r.conversationId);
1369
+ if (!arr) {
1370
+ arr = [];
1371
+ byConv.set(r.conversationId, arr);
1372
+ }
1373
+ arr.push({
1374
+ userId: r.userId,
1375
+ username: r.username,
1376
+ userType: r.userType,
1377
+ role: r.role
1378
+ });
1379
+ }
1380
+ return convs.map((c) => ({ ...c, participants: byConv.get(c.id) ?? [] }));
1381
+ }
1382
+ async function findDMConversation(agentName, participantIds) {
1383
+ const db2 = await getDb();
1384
+ const agentConvs = await db2.select({ id: conversations.id }).from(conversations).where(eq3(conversations.agent_name, agentName)).all();
1385
+ for (const conv of agentConvs) {
1386
+ const rows = await db2.select({ user_id: conversationParticipants.user_id }).from(conversationParticipants).where(eq3(conversationParticipants.conversation_id, conv.id)).all();
1387
+ if (rows.length !== 2) continue;
1388
+ const ids = new Set(rows.map((r) => r.user_id));
1389
+ if (ids.has(participantIds[0]) && ids.has(participantIds[1])) {
1390
+ return conv.id;
1391
+ }
1392
+ }
1393
+ return null;
1394
+ }
1395
+ async function deleteConversation(id) {
1396
+ const db2 = await getDb();
1397
+ await db2.delete(conversations).where(eq3(conversations.id, id));
1398
+ }
1399
+
1400
+ // src/lib/convert-session.ts
1401
+ import { randomUUID as randomUUID2 } from "crypto";
1199
1402
  import { mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
1200
1403
  import { homedir } from "os";
1201
1404
  import { resolve as resolve7 } from "path";
1202
1405
  function convertSession(opts) {
1203
1406
  const lines = readFileSync4(opts.sessionPath, "utf-8").trim().split("\n");
1204
- const sessionId = randomUUID();
1407
+ const sessionId = randomUUID2();
1205
1408
  const idMap = /* @__PURE__ */ new Map();
1206
1409
  const messages2 = [];
1207
1410
  for (const line of lines) {
@@ -1216,7 +1419,7 @@ function convertSession(opts) {
1216
1419
  const event = messages2[i];
1217
1420
  const msg = event.message;
1218
1421
  if (msg.role === "user") {
1219
- const uuid = randomUUID();
1422
+ const uuid = randomUUID2();
1220
1423
  idMap.set(event.id, uuid);
1221
1424
  const parentUuid = event.parentId ? idMap.get(event.parentId) ?? null : null;
1222
1425
  const sdkEvent = {
@@ -1240,7 +1443,7 @@ function convertSession(opts) {
1240
1443
  } else if (msg.role === "assistant") {
1241
1444
  const content = convertAssistantContent(msg.content);
1242
1445
  if (content.length === 0) continue;
1243
- const uuid = randomUUID();
1446
+ const uuid = randomUUID2();
1244
1447
  idMap.set(event.id, uuid);
1245
1448
  const parentUuid = event.parentId ? idMap.get(event.parentId) ?? null : null;
1246
1449
  const stopReason = mapStopReason(msg.stopReason);
@@ -1255,12 +1458,12 @@ function convertSession(opts) {
1255
1458
  isSidechain: false,
1256
1459
  userType: "external",
1257
1460
  type: "assistant",
1258
- requestId: `req_imported_${randomUUID()}`,
1461
+ requestId: `req_imported_${randomUUID2()}`,
1259
1462
  message: {
1260
1463
  role: "assistant",
1261
1464
  content,
1262
1465
  type: "message",
1263
- id: `msg_imported_${randomUUID()}`,
1466
+ id: `msg_imported_${randomUUID2()}`,
1264
1467
  model: mapModel(msg.model),
1265
1468
  stop_reason: stopReason,
1266
1469
  stop_sequence: null,
@@ -1288,7 +1491,7 @@ function convertSession(opts) {
1288
1491
  j++;
1289
1492
  }
1290
1493
  i = j - 1;
1291
- const uuid = randomUUID();
1494
+ const uuid = randomUUID2();
1292
1495
  idMap.set(lastToolResultId, uuid);
1293
1496
  const parentUuid = event.parentId ? idMap.get(event.parentId) ?? null : lastSdkUuid;
1294
1497
  const sdkEvent = {
@@ -1368,118 +1571,6 @@ function convertAssistantContent(content) {
1368
1571
  return result;
1369
1572
  }
1370
1573
 
1371
- // src/lib/template.ts
1372
- import {
1373
- cpSync,
1374
- existsSync as existsSync5,
1375
- mkdirSync as mkdirSync4,
1376
- readdirSync as readdirSync3,
1377
- readFileSync as readFileSync5,
1378
- renameSync,
1379
- rmSync,
1380
- statSync,
1381
- writeFileSync as writeFileSync4
1382
- } from "fs";
1383
- import { tmpdir } from "os";
1384
- import { dirname as dirname3, join, relative, resolve as resolve8 } from "path";
1385
- function findTemplatesRoot() {
1386
- let dir = dirname3(new URL(import.meta.url).pathname);
1387
- for (let i = 0; i < 5; i++) {
1388
- const candidate = resolve8(dir, "templates");
1389
- if (existsSync5(resolve8(candidate, "_base"))) return candidate;
1390
- dir = dirname3(dir);
1391
- }
1392
- console.error(
1393
- "Templates directory not found. Searched up from:",
1394
- dirname3(new URL(import.meta.url).pathname)
1395
- );
1396
- process.exit(1);
1397
- }
1398
- function composeTemplate(templatesRoot, templateName) {
1399
- const baseDir = resolve8(templatesRoot, "_base");
1400
- const templateDir = resolve8(templatesRoot, templateName);
1401
- if (!existsSync5(baseDir)) {
1402
- console.error("Base template not found:", baseDir);
1403
- process.exit(1);
1404
- }
1405
- if (!existsSync5(templateDir)) {
1406
- console.error(`Template not found: ${templateName}`);
1407
- process.exit(1);
1408
- }
1409
- const composedDir = resolve8(tmpdir(), `volute-template-${Date.now()}`);
1410
- mkdirSync4(composedDir, { recursive: true });
1411
- cpSync(baseDir, composedDir, { recursive: true });
1412
- for (const file of listFiles(templateDir)) {
1413
- const src = resolve8(templateDir, file);
1414
- const dest = resolve8(composedDir, file);
1415
- mkdirSync4(dirname3(dest), { recursive: true });
1416
- cpSync(src, dest);
1417
- }
1418
- const manifestPath = resolve8(composedDir, "volute-template.json");
1419
- if (!existsSync5(manifestPath)) {
1420
- rmSync(composedDir, { recursive: true, force: true });
1421
- console.error(`Template manifest not found: ${templateName}/volute-template.json`);
1422
- process.exit(1);
1423
- }
1424
- const manifest = JSON.parse(readFileSync5(manifestPath, "utf-8"));
1425
- const skillsSrc = resolve8(composedDir, "_skills");
1426
- if (existsSync5(skillsSrc)) {
1427
- const skillsDest = resolve8(composedDir, manifest.skillsDir);
1428
- mkdirSync4(skillsDest, { recursive: true });
1429
- cpSync(skillsSrc, skillsDest, { recursive: true });
1430
- rmSync(skillsSrc, { recursive: true, force: true });
1431
- }
1432
- rmSync(manifestPath);
1433
- return { composedDir, manifest };
1434
- }
1435
- function copyTemplateToDir(composedDir, destDir, agentName, manifest) {
1436
- cpSync(composedDir, destDir, { recursive: true });
1437
- for (const [from, to] of Object.entries(manifest.rename)) {
1438
- const fromPath = resolve8(destDir, from);
1439
- if (existsSync5(fromPath)) {
1440
- renameSync(fromPath, resolve8(destDir, to));
1441
- }
1442
- }
1443
- for (const file of manifest.substitute) {
1444
- const path = resolve8(destDir, file);
1445
- if (existsSync5(path)) {
1446
- const content = readFileSync5(path, "utf-8");
1447
- writeFileSync4(path, content.replaceAll("{{name}}", agentName));
1448
- }
1449
- }
1450
- }
1451
- function applyInitFiles(destDir) {
1452
- const initDir = resolve8(destDir, ".init");
1453
- if (!existsSync5(initDir)) return;
1454
- const homeDir = resolve8(destDir, "home");
1455
- for (const file of listFiles(initDir)) {
1456
- const src = resolve8(initDir, file);
1457
- const dest = resolve8(homeDir, file);
1458
- const parent = dirname3(dest);
1459
- if (!existsSync5(parent)) {
1460
- mkdirSync4(parent, { recursive: true });
1461
- }
1462
- cpSync(src, dest);
1463
- }
1464
- rmSync(initDir, { recursive: true, force: true });
1465
- }
1466
- function listFiles(dir) {
1467
- const results = [];
1468
- function walk(current) {
1469
- for (const entry of readdirSync3(current)) {
1470
- const full = join(current, entry);
1471
- if (statSync(full).isDirectory()) {
1472
- if (entry === ".git") continue;
1473
- walk(full);
1474
- } else {
1475
- results.push(relative(dir, full));
1476
- }
1477
- }
1478
- }
1479
- walk(dir);
1480
- return results;
1481
- }
1482
-
1483
1574
  // src/lib/typing.ts
1484
1575
  var DEFAULT_TTL_MS = 1e4;
1485
1576
  var SWEEP_INTERVAL_MS = 5e3;
@@ -1551,6 +1642,7 @@ function getTypingMap() {
1551
1642
  async function startAgentFull(name, baseName, variantName) {
1552
1643
  await getAgentManager().startAgent(name);
1553
1644
  if (variantName) return;
1645
+ if (findAgent(baseName)?.stage === "seed") return;
1554
1646
  const dir = agentDir(baseName);
1555
1647
  const entry = findAgent(baseName);
1556
1648
  await getConnectorManager().startConnectors(baseName, dir, entry.port, getDaemonPort());
@@ -1573,7 +1665,7 @@ function extractTextContent(content) {
1573
1665
  }
1574
1666
  function getDaemonPort() {
1575
1667
  try {
1576
- const data = JSON.parse(readFileSync6(resolve9(voluteHome(), "daemon.json"), "utf-8"));
1668
+ const data = JSON.parse(readFileSync5(resolve8(voluteHome(), "daemon.json"), "utf-8"));
1577
1669
  return data.port;
1578
1670
  } catch (err) {
1579
1671
  if (err?.code !== "ENOENT") {
@@ -1613,9 +1705,9 @@ async function getAgentStatus(name, port) {
1613
1705
  return { status, channels };
1614
1706
  }
1615
1707
  var TEMPLATE_BRANCH = "volute/template";
1616
- async function initTemplateBranch(projectRoot, composedDir, manifest, ids, env) {
1708
+ async function initTemplateBranch(projectRoot, composedDir, manifest, agentName, env) {
1617
1709
  const templateFiles = listFiles(composedDir).filter((f) => !f.startsWith(".init/") && !f.startsWith(".init\\")).map((f) => manifest.rename[f] ?? f);
1618
- const opts = { cwd: projectRoot, uid: ids?.uid, gid: ids?.gid, env };
1710
+ const opts = { cwd: projectRoot, agentName, env };
1619
1711
  await gitExec(["checkout", "--orphan", TEMPLATE_BRANCH], opts);
1620
1712
  await gitExec(["add", "--", ...templateFiles], opts);
1621
1713
  await gitExec(["commit", "-m", "template update"], opts);
@@ -1624,7 +1716,7 @@ async function initTemplateBranch(projectRoot, composedDir, manifest, ids, env)
1624
1716
  await gitExec(["commit", "-m", "initial commit"], opts);
1625
1717
  }
1626
1718
  async function updateTemplateBranch(projectRoot, template, agentName) {
1627
- const tempWorktree = resolve9(projectRoot, ".variants", "_template_update");
1719
+ const tempWorktree = resolve8(projectRoot, ".variants", "_template_update");
1628
1720
  let branchExists = false;
1629
1721
  try {
1630
1722
  await gitExec(["rev-parse", "--verify", TEMPLATE_BRANCH], { cwd: projectRoot });
@@ -1635,8 +1727,8 @@ async function updateTemplateBranch(projectRoot, template, agentName) {
1635
1727
  await gitExec(["worktree", "remove", "--force", tempWorktree], { cwd: projectRoot });
1636
1728
  } catch {
1637
1729
  }
1638
- if (existsSync6(tempWorktree)) {
1639
- rmSync2(tempWorktree, { recursive: true, force: true });
1730
+ if (existsSync5(tempWorktree)) {
1731
+ rmSync(tempWorktree, { recursive: true, force: true });
1640
1732
  }
1641
1733
  const templatesRoot = findTemplatesRoot();
1642
1734
  const { composedDir, manifest } = composeTemplate(templatesRoot, template);
@@ -1656,9 +1748,9 @@ async function updateTemplateBranch(projectRoot, template, agentName) {
1656
1748
  });
1657
1749
  }
1658
1750
  copyTemplateToDir(composedDir, tempWorktree, agentName, manifest);
1659
- const initDir = resolve9(tempWorktree, ".init");
1660
- if (existsSync6(initDir)) {
1661
- rmSync2(initDir, { recursive: true, force: true });
1751
+ const initDir = resolve8(tempWorktree, ".init");
1752
+ if (existsSync5(initDir)) {
1753
+ rmSync(initDir, { recursive: true, force: true });
1662
1754
  }
1663
1755
  await gitExec(["add", "-A"], { cwd: tempWorktree });
1664
1756
  try {
@@ -1671,10 +1763,10 @@ async function updateTemplateBranch(projectRoot, template, agentName) {
1671
1763
  await gitExec(["worktree", "remove", "--force", tempWorktree], { cwd: projectRoot });
1672
1764
  } catch {
1673
1765
  }
1674
- if (existsSync6(tempWorktree)) {
1675
- rmSync2(tempWorktree, { recursive: true, force: true });
1766
+ if (existsSync5(tempWorktree)) {
1767
+ rmSync(tempWorktree, { recursive: true, force: true });
1676
1768
  }
1677
- rmSync2(composedDir, { recursive: true, force: true });
1769
+ rmSync(composedDir, { recursive: true, force: true });
1678
1770
  }
1679
1771
  }
1680
1772
  async function mergeTemplateBranch(worktreeDir) {
@@ -1694,57 +1786,87 @@ async function mergeTemplateBranch(worktreeDir) {
1694
1786
  throw e;
1695
1787
  }
1696
1788
  }
1697
- var app = new Hono().post("/", requireAdmin, async (c) => {
1698
- let body;
1699
- try {
1700
- body = await c.req.json();
1701
- } catch {
1702
- return c.json({ error: "Invalid JSON" }, 400);
1703
- }
1789
+ var createAgentSchema = z.object({
1790
+ name: z.string(),
1791
+ template: z.string().optional(),
1792
+ stage: z.enum(["seed", "mind"]).optional(),
1793
+ description: z.string().optional(),
1794
+ model: z.string().optional()
1795
+ });
1796
+ var app = new Hono().post("/", requireAdmin, zValidator("json", createAgentSchema), async (c) => {
1797
+ const body = c.req.valid("json");
1704
1798
  const { name, template = "agent-sdk" } = body;
1705
1799
  const nameErr = validateAgentName(name);
1706
1800
  if (nameErr) return c.json({ error: nameErr }, 400);
1707
1801
  if (findAgent(name)) return c.json({ error: `Agent already exists: ${name}` }, 409);
1708
1802
  ensureVoluteHome();
1709
1803
  const dest = agentDir(name);
1710
- if (existsSync6(dest)) return c.json({ error: "Agent directory already exists" }, 409);
1804
+ if (existsSync5(dest)) return c.json({ error: "Agent directory already exists" }, 409);
1711
1805
  const templatesRoot = findTemplatesRoot();
1712
1806
  const { composedDir, manifest } = composeTemplate(templatesRoot, template);
1713
1807
  try {
1714
1808
  copyTemplateToDir(composedDir, dest, name, manifest);
1715
1809
  applyInitFiles(dest);
1810
+ if (body.model) {
1811
+ const configPath = resolve8(dest, "home/.config/config.json");
1812
+ const existing = existsSync5(configPath) ? JSON.parse(readFileSync5(configPath, "utf-8")) : {};
1813
+ existing.model = body.model;
1814
+ writeFileSync4(configPath, `${JSON.stringify(existing, null, 2)}
1815
+ `);
1816
+ }
1817
+ if (body.stage === "seed") {
1818
+ const descLine = body.description ? `
1819
+ The human who planted you described you as: "${body.description}"
1820
+ ` : "";
1821
+ writeFileSync4(
1822
+ resolve8(dest, "home/SOUL.md"),
1823
+ `You are ${name}.
1824
+
1825
+ You don't have a soul yet. You're a seed \u2014 a new agent in the process of discovering who you are.
1826
+ ${descLine}
1827
+ Have a conversation with the human. Explore what kind of agent you want to be. When you're ready, write your SOUL.md and MEMORY.md, then run \`volute sprout\` to complete the transformation.
1828
+ `
1829
+ );
1830
+ const skillsDir = resolve8(dest, manifest.skillsDir);
1831
+ for (const skill of ["volute-agent", "memory", "sessions"]) {
1832
+ const skillPath = resolve8(skillsDir, skill);
1833
+ if (existsSync5(skillPath)) rmSync(skillPath, { recursive: true, force: true });
1834
+ }
1835
+ }
1716
1836
  const port = nextPort();
1717
- addAgent(name, port);
1837
+ addAgent(name, port, body.stage);
1838
+ const homeDir = resolve8(dest, "home");
1718
1839
  ensureVoluteGroup();
1719
- createAgentUser(name);
1840
+ createAgentUser(name, homeDir);
1720
1841
  chownAgentDir(dest, name);
1721
- const ids = isIsolationEnabled() ? await getAgentUserIds(name) : void 0;
1722
- const env = ids ? { ...process.env, HOME: resolve9(dest, "home") } : void 0;
1723
- await exec("npm", ["install"], { cwd: dest, uid: ids?.uid, gid: ids?.gid, env });
1842
+ const agentName = isIsolationEnabled() ? name : void 0;
1843
+ const env = agentName ? { ...process.env, HOME: homeDir } : void 0;
1844
+ await exec("npm", ["install"], { cwd: dest, agentName, env });
1724
1845
  let gitWarning;
1725
1846
  try {
1726
- await gitExec(["init"], { cwd: dest, uid: ids?.uid, gid: ids?.gid, env });
1727
- await initTemplateBranch(dest, composedDir, manifest, ids, env);
1847
+ await gitExec(["init"], { cwd: dest, agentName, env });
1848
+ await initTemplateBranch(dest, composedDir, manifest, agentName, env);
1728
1849
  } catch {
1729
- rmSync2(resolve9(dest, ".git"), { recursive: true, force: true });
1850
+ rmSync(resolve8(dest, ".git"), { recursive: true, force: true });
1730
1851
  gitWarning = "Git setup failed \u2014 variants and upgrades won't be available until git is initialized.";
1731
1852
  }
1732
1853
  return c.json({
1733
1854
  ok: true,
1734
1855
  name,
1735
1856
  port,
1857
+ stage: body.stage ?? "mind",
1736
1858
  message: `Created agent: ${name} (port ${port})`,
1737
1859
  ...gitWarning && { warning: gitWarning }
1738
1860
  });
1739
1861
  } catch (err) {
1740
- if (existsSync6(dest)) rmSync2(dest, { recursive: true, force: true });
1862
+ if (existsSync5(dest)) rmSync(dest, { recursive: true, force: true });
1741
1863
  try {
1742
1864
  removeAgent(name);
1743
1865
  } catch {
1744
1866
  }
1745
1867
  return c.json({ error: err instanceof Error ? err.message : "Failed to create agent" }, 500);
1746
1868
  } finally {
1747
- rmSync2(composedDir, { recursive: true, force: true });
1869
+ rmSync(composedDir, { recursive: true, force: true });
1748
1870
  }
1749
1871
  }).post("/import", requireAdmin, async (c) => {
1750
1872
  let body;
@@ -1754,13 +1876,13 @@ var app = new Hono().post("/", requireAdmin, async (c) => {
1754
1876
  return c.json({ error: "Invalid JSON" }, 400);
1755
1877
  }
1756
1878
  const wsDir = body.workspacePath;
1757
- if (!wsDir || !existsSync6(resolve9(wsDir, "SOUL.md")) || !existsSync6(resolve9(wsDir, "IDENTITY.md"))) {
1879
+ if (!wsDir || !existsSync5(resolve8(wsDir, "SOUL.md")) || !existsSync5(resolve8(wsDir, "IDENTITY.md"))) {
1758
1880
  return c.json({ error: "Invalid workspace: missing SOUL.md or IDENTITY.md" }, 400);
1759
1881
  }
1760
- const soul = readFileSync6(resolve9(wsDir, "SOUL.md"), "utf-8");
1761
- const identity = readFileSync6(resolve9(wsDir, "IDENTITY.md"), "utf-8");
1762
- const userPath = resolve9(wsDir, "USER.md");
1763
- const user = existsSync6(userPath) ? readFileSync6(userPath, "utf-8") : "";
1882
+ const soul = readFileSync5(resolve8(wsDir, "SOUL.md"), "utf-8");
1883
+ const identity = readFileSync5(resolve8(wsDir, "IDENTITY.md"), "utf-8");
1884
+ const userPath = resolve8(wsDir, "USER.md");
1885
+ const user = existsSync5(userPath) ? readFileSync5(userPath, "utf-8") : "";
1764
1886
  const name = body.name ?? parseNameFromIdentity(identity) ?? "imported-agent";
1765
1887
  const template = body.template ?? "agent-sdk";
1766
1888
  const nameErr = validateAgentName(name);
@@ -1780,76 +1902,72 @@ ${user.trimEnd()}
1780
1902
  ` : "";
1781
1903
  ensureVoluteHome();
1782
1904
  const dest = agentDir(name);
1783
- if (existsSync6(dest)) return c.json({ error: "Agent directory already exists" }, 409);
1905
+ if (existsSync5(dest)) return c.json({ error: "Agent directory already exists" }, 409);
1784
1906
  const templatesRoot = findTemplatesRoot();
1785
1907
  const { composedDir, manifest } = composeTemplate(templatesRoot, template);
1786
1908
  try {
1787
1909
  copyTemplateToDir(composedDir, dest, name, manifest);
1788
1910
  applyInitFiles(dest);
1789
- writeFileSync5(resolve9(dest, "home/SOUL.md"), mergedSoul);
1790
- const wsMemoryPath = resolve9(wsDir, "MEMORY.md");
1791
- const hasMemory = existsSync6(wsMemoryPath);
1911
+ writeFileSync4(resolve8(dest, "home/SOUL.md"), mergedSoul);
1912
+ const wsMemoryPath = resolve8(wsDir, "MEMORY.md");
1913
+ const hasMemory = existsSync5(wsMemoryPath);
1792
1914
  if (hasMemory) {
1793
- const existingMemory = readFileSync6(wsMemoryPath, "utf-8");
1794
- writeFileSync5(
1795
- resolve9(dest, "home/MEMORY.md"),
1915
+ const existingMemory = readFileSync5(wsMemoryPath, "utf-8");
1916
+ writeFileSync4(
1917
+ resolve8(dest, "home/MEMORY.md"),
1796
1918
  `${existingMemory.trimEnd()}${mergedMemoryExtra}`
1797
1919
  );
1798
1920
  } else if (user) {
1799
- writeFileSync5(resolve9(dest, "home/MEMORY.md"), `${user.trimEnd()}
1921
+ writeFileSync4(resolve8(dest, "home/MEMORY.md"), `${user.trimEnd()}
1800
1922
  `);
1801
1923
  }
1802
- const wsMemoryDir = resolve9(wsDir, "memory");
1924
+ const wsMemoryDir = resolve8(wsDir, "memory");
1803
1925
  let dailyLogCount = 0;
1804
- if (existsSync6(wsMemoryDir)) {
1805
- const destMemoryDir = resolve9(dest, "home/memory");
1806
- const files = readdirSync4(wsMemoryDir).filter((f) => f.endsWith(".md"));
1926
+ if (existsSync5(wsMemoryDir)) {
1927
+ const destMemoryDir = resolve8(dest, "home/memory");
1928
+ const files = readdirSync3(wsMemoryDir).filter((f) => f.endsWith(".md"));
1807
1929
  for (const file of files) {
1808
- cpSync2(resolve9(wsMemoryDir, file), resolve9(destMemoryDir, file));
1930
+ cpSync(resolve8(wsMemoryDir, file), resolve8(destMemoryDir, file));
1809
1931
  }
1810
1932
  dailyLogCount = files.length;
1811
1933
  }
1812
1934
  const port = nextPort();
1813
1935
  addAgent(name, port);
1936
+ const homeDir = resolve8(dest, "home");
1814
1937
  ensureVoluteGroup();
1815
- createAgentUser(name);
1938
+ createAgentUser(name, homeDir);
1816
1939
  chownAgentDir(dest, name);
1817
- const ids = isIsolationEnabled() ? await getAgentUserIds(name) : void 0;
1818
- const env = ids ? { ...process.env, HOME: resolve9(dest, "home") } : void 0;
1819
- await exec("npm", ["install"], { cwd: dest, uid: ids?.uid, gid: ids?.gid, env });
1940
+ const agentName = isIsolationEnabled() ? name : void 0;
1941
+ const env = agentName ? { ...process.env, HOME: homeDir } : void 0;
1942
+ await exec("npm", ["install"], { cwd: dest, agentName, env });
1820
1943
  if (!hasMemory && dailyLogCount > 0) {
1821
1944
  await consolidateMemory(dest);
1822
1945
  }
1823
- await gitExec(["init"], { cwd: dest, uid: ids?.uid, gid: ids?.gid, env });
1824
- await gitExec(["add", "-A"], { cwd: dest, uid: ids?.uid, gid: ids?.gid, env });
1825
- await gitExec(["commit", "-m", "import from OpenClaw"], {
1826
- cwd: dest,
1827
- uid: ids?.uid,
1828
- gid: ids?.gid,
1829
- env
1830
- });
1831
- const sessionFile = body.sessionPath ? resolve9(body.sessionPath) : findOpenClawSession(wsDir);
1832
- if (sessionFile && existsSync6(sessionFile)) {
1946
+ await gitExec(["init"], { cwd: dest, agentName, env });
1947
+ await gitExec(["add", "-A"], { cwd: dest, agentName, env });
1948
+ await gitExec(["commit", "-m", "import from OpenClaw"], { cwd: dest, agentName, env });
1949
+ const sessionFile = body.sessionPath ? resolve8(body.sessionPath) : findOpenClawSession(wsDir);
1950
+ if (sessionFile && existsSync5(sessionFile)) {
1833
1951
  if (template === "pi") {
1834
1952
  importPiSession(sessionFile, dest);
1835
1953
  } else if (template === "agent-sdk") {
1836
1954
  const sessionId = convertSession({ sessionPath: sessionFile, projectDir: dest });
1837
- const voluteDir = resolve9(dest, ".volute");
1838
- mkdirSync5(voluteDir, { recursive: true });
1839
- writeFileSync5(resolve9(voluteDir, "session.json"), JSON.stringify({ sessionId }));
1955
+ const voluteDir = resolve8(dest, ".volute");
1956
+ mkdirSync4(voluteDir, { recursive: true });
1957
+ writeFileSync4(resolve8(voluteDir, "session.json"), JSON.stringify({ sessionId }));
1840
1958
  }
1841
1959
  }
1842
1960
  importOpenClawConnectors(name, dest);
1843
1961
  return c.json({ ok: true, name, port, message: `Imported agent: ${name} (port ${port})` });
1844
1962
  } catch (err) {
1845
- if (existsSync6(dest)) rmSync2(dest, { recursive: true, force: true });
1963
+ if (existsSync5(dest)) rmSync(dest, { recursive: true, force: true });
1846
1964
  try {
1847
1965
  removeAgent(name);
1848
1966
  } catch {
1849
1967
  }
1850
1968
  return c.json({ error: err instanceof Error ? err.message : "Failed to import agent" }, 500);
1851
1969
  } finally {
1852
- rmSync2(composedDir, { recursive: true, force: true });
1970
+ rmSync(composedDir, { recursive: true, force: true });
1853
1971
  }
1854
1972
  }).get("/", async (c) => {
1855
1973
  const entries = readRegistry();
@@ -1864,7 +1982,7 @@ ${user.trimEnd()}
1864
1982
  const name = c.req.param("name");
1865
1983
  const entry = findAgent(name);
1866
1984
  if (!entry) return c.json({ error: "Agent not found" }, 404);
1867
- if (!existsSync6(agentDir(name))) return c.json({ error: "Agent directory missing" }, 404);
1985
+ if (!existsSync5(agentDir(name))) return c.json({ error: "Agent directory missing" }, 404);
1868
1986
  const { status, channels } = await getAgentStatus(name, entry.port);
1869
1987
  const variants = readVariants(name);
1870
1988
  const manager = getAgentManager();
@@ -1890,7 +2008,7 @@ ${user.trimEnd()}
1890
2008
  if (!variant) return c.json({ error: `Unknown variant: ${variantName}` }, 404);
1891
2009
  } else {
1892
2010
  const dir = agentDir(baseName);
1893
- if (!existsSync6(dir)) return c.json({ error: "Agent directory missing" }, 404);
2011
+ if (!existsSync5(dir)) return c.json({ error: "Agent directory missing" }, 404);
1894
2012
  }
1895
2013
  if (getAgentManager().isRunning(name)) {
1896
2014
  return c.json({ error: "Agent already running" }, 409);
@@ -1911,7 +2029,7 @@ ${user.trimEnd()}
1911
2029
  if (!variant) return c.json({ error: `Unknown variant: ${variantName}` }, 404);
1912
2030
  } else {
1913
2031
  const dir = agentDir(baseName);
1914
- if (!existsSync6(dir)) return c.json({ error: "Agent directory missing" }, 404);
2032
+ if (!existsSync5(dir)) return c.json({ error: "Agent directory missing" }, 404);
1915
2033
  }
1916
2034
  let context;
1917
2035
  const contentType = c.req.header("content-type");
@@ -1942,7 +2060,7 @@ ${user.trimEnd()}
1942
2060
  const variant = findVariant(baseName, mergeVariantName);
1943
2061
  if (variant) {
1944
2062
  const projectRoot = agentDir(baseName);
1945
- if (existsSync6(variant.path)) {
2063
+ if (existsSync5(variant.path)) {
1946
2064
  const status = (await gitExec(["status", "--porcelain"], { cwd: variant.path })).trim();
1947
2065
  if (status) {
1948
2066
  try {
@@ -1970,7 +2088,7 @@ ${user.trimEnd()}
1970
2088
  }
1971
2089
  }
1972
2090
  await gitExec(["merge", variant.branch], { cwd: projectRoot });
1973
- if (existsSync6(variant.path)) {
2091
+ if (existsSync5(variant.path)) {
1974
2092
  try {
1975
2093
  await gitExec(["worktree", "remove", "--force", variant.path], {
1976
2094
  cwd: projectRoot
@@ -1994,6 +2112,19 @@ ${user.trimEnd()}
1994
2112
  if (context) {
1995
2113
  manager.setPendingContext(name, context);
1996
2114
  }
2115
+ if (context?.type === "sprouted" && !variantName) {
2116
+ try {
2117
+ const db2 = await getDb();
2118
+ const activeConvs = await db2.select({ id: conversations.id }).from(conversations).where(eq4(conversations.agent_name, baseName)).all();
2119
+ for (const conv of activeConvs) {
2120
+ await addMessage(conv.id, "assistant", "system", [
2121
+ { type: "text", text: "[seed has sprouted]" }
2122
+ ]);
2123
+ }
2124
+ } catch (err) {
2125
+ console.error(`[daemon] failed to inject sprouted message for ${baseName}:`, err);
2126
+ }
2127
+ }
1997
2128
  await startAgentFull(name, baseName, variantName);
1998
2129
  return c.json({ ok: true });
1999
2130
  } catch (err) {
@@ -2039,11 +2170,11 @@ ${user.trimEnd()}
2039
2170
  removeAgent(name);
2040
2171
  await deleteAgentUser2(name);
2041
2172
  const state = stateDir(name);
2042
- if (existsSync6(state)) {
2043
- rmSync2(state, { recursive: true, force: true });
2173
+ if (existsSync5(state)) {
2174
+ rmSync(state, { recursive: true, force: true });
2044
2175
  }
2045
- if (force && existsSync6(dir)) {
2046
- rmSync2(dir, { recursive: true, force: true });
2176
+ if (force && existsSync5(dir)) {
2177
+ rmSync(dir, { recursive: true, force: true });
2047
2178
  deleteAgentUser(name);
2048
2179
  }
2049
2180
  return c.json({ ok: true });
@@ -2052,7 +2183,7 @@ ${user.trimEnd()}
2052
2183
  const entry = findAgent(agentName);
2053
2184
  if (!entry) return c.json({ error: "Agent not found" }, 404);
2054
2185
  const dir = agentDir(agentName);
2055
- if (!existsSync6(dir)) return c.json({ error: "Agent directory missing" }, 404);
2186
+ if (!existsSync5(dir)) return c.json({ error: "Agent directory missing" }, 404);
2056
2187
  let body = {};
2057
2188
  try {
2058
2189
  body = await c.req.json();
@@ -2061,8 +2192,8 @@ ${user.trimEnd()}
2061
2192
  const template = body.template ?? "agent-sdk";
2062
2193
  const UPGRADE_VARIANT = "upgrade";
2063
2194
  if (body.continue) {
2064
- const worktreeDir2 = resolve9(dir, ".variants", UPGRADE_VARIANT);
2065
- if (!existsSync6(worktreeDir2)) {
2195
+ const worktreeDir2 = resolve8(dir, ".variants", UPGRADE_VARIANT);
2196
+ if (!existsSync5(worktreeDir2)) {
2066
2197
  return c.json({ error: "No upgrade in progress" }, 400);
2067
2198
  }
2068
2199
  const status = await gitExec(["status", "--porcelain"], { cwd: worktreeDir2 });
@@ -2122,8 +2253,8 @@ ${user.trimEnd()}
2122
2253
  );
2123
2254
  }
2124
2255
  }
2125
- const worktreeDir = resolve9(dir, ".variants", UPGRADE_VARIANT);
2126
- if (existsSync6(worktreeDir)) {
2256
+ const worktreeDir = resolve8(dir, ".variants", UPGRADE_VARIANT);
2257
+ if (existsSync5(worktreeDir)) {
2127
2258
  return c.json(
2128
2259
  { error: "Upgrade variant already exists. Use continue or delete it first." },
2129
2260
  409
@@ -2135,9 +2266,9 @@ ${user.trimEnd()}
2135
2266
  } catch {
2136
2267
  }
2137
2268
  await updateTemplateBranch(dir, template, agentName);
2138
- const parentDir = resolve9(dir, ".variants");
2139
- if (!existsSync6(parentDir)) {
2140
- mkdirSync5(parentDir, { recursive: true });
2269
+ const parentDir = resolve8(dir, ".variants");
2270
+ if (!existsSync5(parentDir)) {
2271
+ mkdirSync4(parentDir, { recursive: true });
2141
2272
  }
2142
2273
  await gitExec(["worktree", "add", "-b", UPGRADE_VARIANT, worktreeDir], { cwd: dir });
2143
2274
  const hasConflicts = await mergeTemplateBranch(worktreeDir);
@@ -2264,6 +2395,24 @@ ${user.trimEnd()}
2264
2395
  budget.acknowledgeWarning(baseName);
2265
2396
  forwardBody = JSON.stringify(parsed);
2266
2397
  }
2398
+ const seedEntry = findAgent(baseName);
2399
+ if (seedEntry?.stage === "seed" && parsed) {
2400
+ try {
2401
+ const countResult = await db2.select({ count: sql3`count(*)` }).from(agentMessages).where(eq4(agentMessages.agent, baseName));
2402
+ const msgCount = countResult[0]?.count ?? 0;
2403
+ if (msgCount >= 10 && msgCount % 10 === 0) {
2404
+ const nudge = "\n[You've been exploring for a while. Whenever you feel ready, write your SOUL.md and MEMORY.md, then run volute sprout.]";
2405
+ if (typeof parsed.content === "string") {
2406
+ parsed.content = parsed.content + nudge;
2407
+ } else if (Array.isArray(parsed.content)) {
2408
+ parsed.content = [...parsed.content, { type: "text", text: nudge }];
2409
+ }
2410
+ forwardBody = JSON.stringify(parsed);
2411
+ }
2412
+ } catch (err) {
2413
+ console.error(`[daemon] failed to check seed message count for ${baseName}:`, err);
2414
+ }
2415
+ }
2267
2416
  typingMap.set(channel, baseName, { persistent: true });
2268
2417
  const conversationId = parsed?.conversationId ?? null;
2269
2418
  if (conversationId) typingMap.set(`volute:${conversationId}`, baseName, { persistent: true });
@@ -2330,7 +2479,7 @@ ${user.trimEnd()}
2330
2479
  }).get("/:name/history/channels", async (c) => {
2331
2480
  const name = c.req.param("name");
2332
2481
  const db2 = await getDb();
2333
- const rows = await db2.selectDistinct({ channel: agentMessages.channel }).from(agentMessages).where(eq3(agentMessages.agent, name));
2482
+ const rows = await db2.selectDistinct({ channel: agentMessages.channel }).from(agentMessages).where(eq4(agentMessages.agent, name));
2334
2483
  return c.json(rows.map((r) => r.channel));
2335
2484
  }).get("/:name/history", async (c) => {
2336
2485
  const name = c.req.param("name");
@@ -2338,23 +2487,23 @@ ${user.trimEnd()}
2338
2487
  const limit = Math.min(Math.max(parseInt(c.req.query("limit") ?? "50", 10) || 50, 1), 200);
2339
2488
  const offset = Math.max(parseInt(c.req.query("offset") ?? "0", 10) || 0, 0);
2340
2489
  const db2 = await getDb();
2341
- const conditions = [eq3(agentMessages.agent, name)];
2490
+ const conditions = [eq4(agentMessages.agent, name)];
2342
2491
  if (channel) {
2343
- conditions.push(eq3(agentMessages.channel, channel));
2492
+ conditions.push(eq4(agentMessages.channel, channel));
2344
2493
  }
2345
- const rows = await db2.select().from(agentMessages).where(and2(...conditions)).orderBy(desc(agentMessages.created_at)).limit(limit).offset(offset);
2494
+ const rows = await db2.select().from(agentMessages).where(and3(...conditions)).orderBy(desc2(agentMessages.created_at)).limit(limit).offset(offset);
2346
2495
  return c.json(rows);
2347
2496
  });
2348
2497
  var agents_default = app;
2349
2498
 
2350
2499
  // src/web/routes/auth.ts
2351
- import { zValidator } from "@hono/zod-validator";
2500
+ import { zValidator as zValidator2 } from "@hono/zod-validator";
2352
2501
  import { Hono as Hono2 } from "hono";
2353
2502
  import { deleteCookie, getCookie as getCookie2, setCookie } from "hono/cookie";
2354
- import { z } from "zod";
2355
- var credentialsSchema = z.object({
2356
- username: z.string().min(1),
2357
- password: z.string().min(1)
2503
+ import { z as z2 } from "zod";
2504
+ var credentialsSchema = z2.object({
2505
+ username: z2.string().min(1),
2506
+ password: z2.string().min(1)
2358
2507
  });
2359
2508
  var admin = new Hono2().use(authMiddleware).get("/users", async (c) => {
2360
2509
  const user = c.get("user");
@@ -2379,7 +2528,7 @@ var admin = new Hono2().use(authMiddleware).get("/users", async (c) => {
2379
2528
  await approveUser(id);
2380
2529
  return c.json({ ok: true });
2381
2530
  });
2382
- var app2 = new Hono2().post("/register", zValidator("json", credentialsSchema), async (c) => {
2531
+ var app2 = new Hono2().post("/register", zValidator2("json", credentialsSchema), async (c) => {
2383
2532
  const { username, password } = c.req.valid("json");
2384
2533
  const existing = await getUserByUsername(username);
2385
2534
  if (existing) {
@@ -2391,7 +2540,7 @@ var app2 = new Hono2().post("/register", zValidator("json", credentialsSchema),
2391
2540
  setCookie(c, "volute_session", sessionId, { path: "/", httpOnly: true, sameSite: "Lax" });
2392
2541
  }
2393
2542
  return c.json({ id: user.id, username: user.username, role: user.role });
2394
- }).post("/login", zValidator("json", credentialsSchema), async (c) => {
2543
+ }).post("/login", zValidator2("json", credentialsSchema), async (c) => {
2395
2544
  const { username, password } = c.req.valid("json");
2396
2545
  const user = await verifyUser(username, password);
2397
2546
  if (!user) {
@@ -2540,6 +2689,8 @@ var app4 = new Hono4().get("/:name/connectors", (c) => {
2540
2689
  }
2541
2690
  const entry = findAgent(name);
2542
2691
  if (!entry) return c.json({ error: "Agent not found" }, 404);
2692
+ if (entry.stage === "seed")
2693
+ return c.json({ error: "Seed agents cannot use connectors \u2014 sprout first" }, 403);
2543
2694
  const dir = agentDir(name);
2544
2695
  const manager = getConnectorManager();
2545
2696
  const envCheck = manager.checkConnectorEnv(type, name, dir);
@@ -2661,9 +2812,9 @@ var sharedEnvApp = new Hono5().get("/", (c) => {
2661
2812
  var env_default = app5;
2662
2813
 
2663
2814
  // src/web/routes/files.ts
2664
- import { existsSync as existsSync7 } from "fs";
2815
+ import { existsSync as existsSync6 } from "fs";
2665
2816
  import { readdir, readFile } from "fs/promises";
2666
- import { resolve as resolve10 } from "path";
2817
+ import { resolve as resolve9 } from "path";
2667
2818
  import { Hono as Hono6 } from "hono";
2668
2819
  var ALLOWED_FILES = /* @__PURE__ */ new Set(["SOUL.md", "MEMORY.md", "CLAUDE.md", "VOLUTE.md"]);
2669
2820
  var app6 = new Hono6().get("/:name/files", async (c) => {
@@ -2671,8 +2822,8 @@ var app6 = new Hono6().get("/:name/files", async (c) => {
2671
2822
  const entry = findAgent(name);
2672
2823
  if (!entry) return c.json({ error: "Agent not found" }, 404);
2673
2824
  const dir = agentDir(name);
2674
- const homeDir = resolve10(dir, "home");
2675
- if (!existsSync7(homeDir)) return c.json({ error: "Home directory missing" }, 404);
2825
+ const homeDir = resolve9(dir, "home");
2826
+ if (!existsSync6(homeDir)) return c.json({ error: "Home directory missing" }, 404);
2676
2827
  const allFiles = await readdir(homeDir);
2677
2828
  const files = allFiles.filter((f) => f.endsWith(".md") && ALLOWED_FILES.has(f));
2678
2829
  return c.json(files);
@@ -2685,8 +2836,8 @@ var app6 = new Hono6().get("/:name/files", async (c) => {
2685
2836
  const entry = findAgent(name);
2686
2837
  if (!entry) return c.json({ error: "Agent not found" }, 404);
2687
2838
  const dir = agentDir(name);
2688
- const filePath = resolve10(dir, "home", filename);
2689
- if (!existsSync7(filePath)) {
2839
+ const filePath = resolve9(dir, "home", filename);
2840
+ if (!existsSync6(filePath)) {
2690
2841
  return c.json({ error: "File not found" }, 404);
2691
2842
  }
2692
2843
  const content = await readFile(filePath, "utf-8");
@@ -2696,16 +2847,16 @@ var files_default = app6;
2696
2847
 
2697
2848
  // src/web/routes/logs.ts
2698
2849
  import { spawn as spawn2 } from "child_process";
2699
- import { existsSync as existsSync8 } from "fs";
2700
- import { resolve as resolve11 } from "path";
2850
+ import { existsSync as existsSync7 } from "fs";
2851
+ import { resolve as resolve10 } from "path";
2701
2852
  import { Hono as Hono7 } from "hono";
2702
2853
  import { streamSSE } from "hono/streaming";
2703
2854
  var app7 = new Hono7().get("/:name/logs", async (c) => {
2704
2855
  const name = c.req.param("name");
2705
2856
  const entry = findAgent(name);
2706
2857
  if (!entry) return c.json({ error: "Agent not found" }, 404);
2707
- const logFile = resolve11(stateDir(name), "logs", "agent.log");
2708
- if (!existsSync8(logFile)) {
2858
+ const logFile = resolve10(stateDir(name), "logs", "agent.log");
2859
+ if (!existsSync7(logFile)) {
2709
2860
  return c.json({ error: "No log file found" }, 404);
2710
2861
  }
2711
2862
  return streamSSE(c, async (stream) => {
@@ -2723,17 +2874,17 @@ var app7 = new Hono7().get("/:name/logs", async (c) => {
2723
2874
  stream.onAbort(() => {
2724
2875
  tail.kill();
2725
2876
  });
2726
- await new Promise((resolve17) => {
2727
- tail.on("exit", resolve17);
2728
- stream.onAbort(resolve17);
2877
+ await new Promise((resolve16) => {
2878
+ tail.on("exit", resolve16);
2879
+ stream.onAbort(resolve16);
2729
2880
  });
2730
2881
  });
2731
2882
  }).get("/:name/logs/tail", async (c) => {
2732
2883
  const name = c.req.param("name");
2733
2884
  const entry = findAgent(name);
2734
2885
  if (!entry) return c.json({ error: "Agent not found" }, 404);
2735
- const logFile = resolve11(stateDir(name), "logs", "agent.log");
2736
- if (!existsSync8(logFile)) {
2886
+ const logFile = resolve10(stateDir(name), "logs", "agent.log");
2887
+ if (!existsSync7(logFile)) {
2737
2888
  return c.json({ error: "No log file found" }, 404);
2738
2889
  }
2739
2890
  const nParam = parseInt(c.req.query("n") ?? "50", 10);
@@ -2743,8 +2894,8 @@ var app7 = new Hono7().get("/:name/logs", async (c) => {
2743
2894
  tail.stdout.on("data", (data) => {
2744
2895
  output += data.toString();
2745
2896
  });
2746
- await new Promise((resolve17) => {
2747
- tail.on("exit", resolve17);
2897
+ await new Promise((resolve16) => {
2898
+ tail.on("exit", resolve16);
2748
2899
  });
2749
2900
  return c.text(output);
2750
2901
  });
@@ -2768,7 +2919,10 @@ var app8 = new Hono8().get("/:name/schedules", (c) => {
2768
2919
  return c.json(readSchedules(name));
2769
2920
  }).post("/:name/schedules", requireAdmin, async (c) => {
2770
2921
  const name = c.req.param("name");
2771
- if (!findAgent(name)) return c.json({ error: "Agent not found" }, 404);
2922
+ const entry = findAgent(name);
2923
+ if (!entry) return c.json({ error: "Agent not found" }, 404);
2924
+ if (entry.stage === "seed")
2925
+ return c.json({ error: "Seed agents cannot use schedules \u2014 sprout first" }, 403);
2772
2926
  const body = await c.req.json();
2773
2927
  if (!body.cron || !body.message) {
2774
2928
  return c.json({ error: "cron and message are required" }, 400);
@@ -2852,10 +3006,10 @@ var app9 = new Hono9().post("/restart", requireAdmin, (c) => {
2852
3006
  stream.writeSSE({ data: JSON.stringify(entry) }).catch(() => {
2853
3007
  });
2854
3008
  });
2855
- await new Promise((resolve17) => {
3009
+ await new Promise((resolve16) => {
2856
3010
  stream.onAbort(() => {
2857
3011
  unsubscribe();
2858
- resolve17();
3012
+ resolve16();
2859
3013
  });
2860
3014
  });
2861
3015
  });
@@ -2863,15 +3017,15 @@ var app9 = new Hono9().post("/restart", requireAdmin, (c) => {
2863
3017
  var system_default = app9;
2864
3018
 
2865
3019
  // src/web/routes/typing.ts
2866
- import { zValidator as zValidator2 } from "@hono/zod-validator";
3020
+ import { zValidator as zValidator3 } from "@hono/zod-validator";
2867
3021
  import { Hono as Hono10 } from "hono";
2868
- import { z as z2 } from "zod";
2869
- var typingSchema = z2.object({
2870
- channel: z2.string().min(1),
2871
- sender: z2.string().min(1),
2872
- active: z2.boolean()
3022
+ import { z as z3 } from "zod";
3023
+ var typingSchema = z3.object({
3024
+ channel: z3.string().min(1),
3025
+ sender: z3.string().min(1),
3026
+ active: z3.boolean()
2873
3027
  });
2874
- var app10 = new Hono10().post("/:name/typing", zValidator2("json", typingSchema), (c) => {
3028
+ var app10 = new Hono10().post("/:name/typing", zValidator3("json", typingSchema), (c) => {
2875
3029
  const { channel, sender, active } = c.req.valid("json");
2876
3030
  const map = getTypingMap();
2877
3031
  if (active) {
@@ -2912,16 +3066,16 @@ var app11 = new Hono11().get("/update", async (c) => {
2912
3066
  var update_default = app11;
2913
3067
 
2914
3068
  // src/web/routes/variants.ts
2915
- import { existsSync as existsSync9, mkdirSync as mkdirSync7, writeFileSync as writeFileSync6 } from "fs";
2916
- import { resolve as resolve13 } from "path";
3069
+ import { existsSync as existsSync8, mkdirSync as mkdirSync6, writeFileSync as writeFileSync5 } from "fs";
3070
+ import { resolve as resolve12 } from "path";
2917
3071
  import { Hono as Hono12 } from "hono";
2918
3072
 
2919
3073
  // src/lib/spawn-server.ts
2920
3074
  import { spawn as spawn4 } from "child_process";
2921
- import { closeSync, mkdirSync as mkdirSync6, openSync, readFileSync as readFileSync7 } from "fs";
2922
- import { resolve as resolve12 } from "path";
3075
+ import { closeSync, mkdirSync as mkdirSync5, openSync, readFileSync as readFileSync6 } from "fs";
3076
+ import { resolve as resolve11 } from "path";
2923
3077
  function tsxBin(cwd) {
2924
- return resolve12(cwd, "node_modules", ".bin", "tsx");
3078
+ return resolve11(cwd, "node_modules", ".bin", "tsx");
2925
3079
  }
2926
3080
  function spawnServer(cwd, port, options) {
2927
3081
  if (options?.detached) {
@@ -2934,31 +3088,31 @@ function spawnAttached(cwd, port) {
2934
3088
  cwd,
2935
3089
  stdio: ["ignore", "pipe", "pipe"]
2936
3090
  });
2937
- return new Promise((resolve17) => {
2938
- const timeout = setTimeout(() => resolve17(null), 3e4);
3091
+ return new Promise((resolve16) => {
3092
+ const timeout = setTimeout(() => resolve16(null), 3e4);
2939
3093
  function checkOutput(data) {
2940
3094
  const match = data.toString().match(/listening on :(\d+)/);
2941
3095
  if (match) {
2942
3096
  clearTimeout(timeout);
2943
- resolve17({ child, actualPort: parseInt(match[1], 10) });
3097
+ resolve16({ child, actualPort: parseInt(match[1], 10) });
2944
3098
  }
2945
3099
  }
2946
3100
  child.stdout?.on("data", checkOutput);
2947
3101
  child.stderr?.on("data", checkOutput);
2948
3102
  child.on("error", () => {
2949
3103
  clearTimeout(timeout);
2950
- resolve17(null);
3104
+ resolve16(null);
2951
3105
  });
2952
3106
  child.on("exit", () => {
2953
3107
  clearTimeout(timeout);
2954
- resolve17(null);
3108
+ resolve16(null);
2955
3109
  });
2956
3110
  });
2957
3111
  }
2958
3112
  function spawnDetached(cwd, port, logDir) {
2959
- const logsDir = logDir ?? resolve12(cwd, ".volute", "logs");
2960
- mkdirSync6(logsDir, { recursive: true });
2961
- const logPath = resolve12(logsDir, "agent.log");
3113
+ const logsDir = logDir ?? resolve11(cwd, ".volute", "logs");
3114
+ mkdirSync5(logsDir, { recursive: true });
3115
+ const logPath = resolve11(logsDir, "agent.log");
2962
3116
  const logFd = openSync(logPath, "a");
2963
3117
  const child = spawn4(tsxBin(cwd), ["src/server.ts", "--port", String(port)], {
2964
3118
  cwd,
@@ -2978,7 +3132,7 @@ function spawnDetached(cwd, port, logDir) {
2978
3132
  }
2979
3133
  const interval = setInterval(() => {
2980
3134
  try {
2981
- const content = readFileSync7(logPath, "utf-8");
3135
+ const content = readFileSync6(logPath, "utf-8");
2982
3136
  const match = content.match(/listening on :(\d+)/);
2983
3137
  if (match) {
2984
3138
  finish({ child, actualPort: parseInt(match[1], 10) });
@@ -3047,6 +3201,8 @@ var app12 = new Hono12().get("/:name/variants", async (c) => {
3047
3201
  const agentName = c.req.param("name");
3048
3202
  const entry = findAgent(agentName);
3049
3203
  if (!entry) return c.json({ error: "Agent not found" }, 404);
3204
+ if (entry.stage === "seed")
3205
+ return c.json({ error: "Seed agents cannot create variants \u2014 sprout first" }, 403);
3050
3206
  let body;
3051
3207
  try {
3052
3208
  body = await c.req.json();
@@ -3058,11 +3214,11 @@ var app12 = new Hono12().get("/:name/variants", async (c) => {
3058
3214
  const err = validateBranchName(variantName);
3059
3215
  if (err) return c.json({ error: err }, 400);
3060
3216
  const projectRoot = agentDir(agentName);
3061
- const variantDir = resolve13(projectRoot, ".variants", variantName);
3062
- if (existsSync9(variantDir)) {
3217
+ const variantDir = resolve12(projectRoot, ".variants", variantName);
3218
+ if (existsSync8(variantDir)) {
3063
3219
  return c.json({ error: `Variant directory already exists: ${variantDir}` }, 409);
3064
3220
  }
3065
- mkdirSync7(resolve13(projectRoot, ".variants"), { recursive: true });
3221
+ mkdirSync6(resolve12(projectRoot, ".variants"), { recursive: true });
3066
3222
  try {
3067
3223
  await gitExec(["worktree", "add", "-b", variantName, variantDir], { cwd: projectRoot });
3068
3224
  } catch (e) {
@@ -3076,7 +3232,7 @@ var app12 = new Hono12().get("/:name/variants", async (c) => {
3076
3232
  return c.json({ error: `npm install failed: ${msg}` }, 500);
3077
3233
  }
3078
3234
  if (body.soul) {
3079
- writeFileSync6(resolve13(variantDir, "home/SOUL.md"), body.soul);
3235
+ writeFileSync5(resolve12(variantDir, "home/SOUL.md"), body.soul);
3080
3236
  }
3081
3237
  const variantPort = body.port ?? nextPort();
3082
3238
  const variant = {
@@ -3115,7 +3271,7 @@ var app12 = new Hono12().get("/:name/variants", async (c) => {
3115
3271
  } catch {
3116
3272
  }
3117
3273
  const projectRoot = agentDir(agentName);
3118
- if (existsSync9(variant.path)) {
3274
+ if (existsSync8(variant.path)) {
3119
3275
  const status = (await gitExec(["status", "--porcelain"], { cwd: variant.path })).trim();
3120
3276
  if (status) {
3121
3277
  try {
@@ -3172,7 +3328,7 @@ var app12 = new Hono12().get("/:name/variants", async (c) => {
3172
3328
  } catch (e) {
3173
3329
  return c.json({ error: "Merge failed. Resolve conflicts manually." }, 500);
3174
3330
  }
3175
- if (existsSync9(variant.path)) {
3331
+ if (existsSync8(variant.path)) {
3176
3332
  try {
3177
3333
  await gitExec(["worktree", "remove", "--force", variant.path], { cwd: projectRoot });
3178
3334
  } catch {
@@ -3224,7 +3380,7 @@ var app12 = new Hono12().get("/:name/variants", async (c) => {
3224
3380
  } catch {
3225
3381
  }
3226
3382
  }
3227
- if (existsSync9(variant.path)) {
3383
+ if (existsSync8(variant.path)) {
3228
3384
  try {
3229
3385
  await gitExec(["worktree", "remove", "--force", variant.path], { cwd: projectRoot });
3230
3386
  } catch {
@@ -3241,221 +3397,26 @@ var app12 = new Hono12().get("/:name/variants", async (c) => {
3241
3397
  var variants_default = app12;
3242
3398
 
3243
3399
  // src/web/routes/volute/chat.ts
3244
- import { readFileSync as readFileSync8 } from "fs";
3245
- import { resolve as resolve14 } from "path";
3246
- import { zValidator as zValidator3 } from "@hono/zod-validator";
3400
+ import { readFileSync as readFileSync7 } from "fs";
3401
+ import { resolve as resolve13 } from "path";
3402
+ import { zValidator as zValidator4 } from "@hono/zod-validator";
3247
3403
  import { Hono as Hono13 } from "hono";
3248
3404
  import { streamSSE as streamSSE3 } from "hono/streaming";
3249
- import { z as z3 } from "zod";
3250
-
3251
- // src/lib/conversation-events.ts
3252
- var subscribers = /* @__PURE__ */ new Map();
3253
- function subscribe(conversationId, callback) {
3254
- let set = subscribers.get(conversationId);
3255
- if (!set) {
3256
- set = /* @__PURE__ */ new Set();
3257
- subscribers.set(conversationId, set);
3258
- }
3259
- set.add(callback);
3260
- return () => {
3261
- set.delete(callback);
3262
- if (set.size === 0) subscribers.delete(conversationId);
3263
- };
3264
- }
3265
- function publish(conversationId, event) {
3266
- const set = subscribers.get(conversationId);
3267
- if (!set) return;
3268
- for (const cb of set) {
3269
- try {
3270
- cb(event);
3271
- } catch (err) {
3272
- console.error("[conversation-events] subscriber threw:", err);
3273
- set.delete(cb);
3274
- if (set.size === 0) subscribers.delete(conversationId);
3275
- }
3276
- }
3277
- }
3278
-
3279
- // src/lib/conversations.ts
3280
- import { randomUUID as randomUUID2 } from "crypto";
3281
- import { and as and3, desc as desc2, eq as eq4, inArray, isNull, sql as sql2 } from "drizzle-orm";
3282
- async function createConversation(agentName, channel, opts) {
3283
- const db2 = await getDb();
3284
- const id = randomUUID2();
3285
- await db2.insert(conversations).values({
3286
- id,
3287
- agent_name: agentName,
3288
- channel,
3289
- user_id: opts?.userId ?? null,
3290
- title: opts?.title ?? null
3291
- });
3292
- if (opts?.participantIds && opts.participantIds.length > 0) {
3293
- await db2.insert(conversationParticipants).values(
3294
- opts.participantIds.map((uid, i) => ({
3295
- conversation_id: id,
3296
- user_id: uid,
3297
- role: i === 0 ? "owner" : "member"
3298
- }))
3299
- );
3300
- }
3301
- return {
3302
- id,
3303
- agent_name: agentName,
3304
- channel,
3305
- user_id: opts?.userId ?? null,
3306
- title: opts?.title ?? null,
3307
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
3308
- updated_at: (/* @__PURE__ */ new Date()).toISOString()
3309
- };
3310
- }
3311
- async function getConversation(id) {
3312
- const db2 = await getDb();
3313
- const row = await db2.select().from(conversations).where(eq4(conversations.id, id)).get();
3314
- return row ?? null;
3315
- }
3316
- async function getParticipants(conversationId) {
3317
- const db2 = await getDb();
3318
- const rows = await db2.select({
3319
- userId: conversationParticipants.user_id,
3320
- username: users.username,
3321
- userType: users.user_type,
3322
- role: conversationParticipants.role
3323
- }).from(conversationParticipants).innerJoin(users, eq4(conversationParticipants.user_id, users.id)).where(eq4(conversationParticipants.conversation_id, conversationId)).all();
3324
- return rows;
3325
- }
3326
- async function isParticipant(conversationId, userId) {
3327
- const db2 = await getDb();
3328
- const row = await db2.select({ user_id: conversationParticipants.user_id }).from(conversationParticipants).where(
3329
- and3(
3330
- eq4(conversationParticipants.conversation_id, conversationId),
3331
- eq4(conversationParticipants.user_id, userId)
3332
- )
3333
- ).get();
3334
- return row != null;
3335
- }
3336
- async function listConversationsForUser(userId) {
3337
- const db2 = await getDb();
3338
- const participantRows = await db2.select({ conversation_id: conversationParticipants.conversation_id }).from(conversationParticipants).where(eq4(conversationParticipants.user_id, userId)).all();
3339
- if (participantRows.length === 0) return [];
3340
- const convIds = participantRows.map((r) => r.conversation_id);
3341
- return db2.select().from(conversations).where(inArray(conversations.id, convIds)).orderBy(desc2(conversations.updated_at)).all();
3342
- }
3343
- async function isParticipantOrOwner(conversationId, userId) {
3344
- if (await isParticipant(conversationId, userId)) return true;
3345
- const db2 = await getDb();
3346
- const row = await db2.select().from(conversations).where(and3(eq4(conversations.id, conversationId), eq4(conversations.user_id, userId))).get();
3347
- return row != null;
3348
- }
3349
- async function deleteConversationForUser(id, userId) {
3350
- if (!await isParticipantOrOwner(id, userId)) return false;
3351
- await deleteConversation(id);
3352
- return true;
3353
- }
3354
- async function addMessage(conversationId, role, senderName, content) {
3355
- const db2 = await getDb();
3356
- const serialized = JSON.stringify(content);
3357
- const [result] = await db2.insert(messages).values({ conversation_id: conversationId, role, sender_name: senderName, content: serialized }).returning({ id: messages.id, created_at: messages.created_at });
3358
- await db2.update(conversations).set({ updated_at: sql2`datetime('now')` }).where(eq4(conversations.id, conversationId));
3359
- if (role === "user") {
3360
- const firstText = content.find((b) => b.type === "text");
3361
- const title = firstText ? firstText.text.slice(0, 80) : "";
3362
- if (title) {
3363
- await db2.update(conversations).set({ title }).where(and3(eq4(conversations.id, conversationId), isNull(conversations.title)));
3364
- }
3365
- }
3366
- const msg = {
3367
- id: result.id,
3368
- conversation_id: conversationId,
3369
- role,
3370
- sender_name: senderName,
3371
- content,
3372
- created_at: result.created_at
3373
- };
3374
- publish(conversationId, {
3375
- type: "message",
3376
- id: msg.id,
3377
- role: msg.role,
3378
- senderName: msg.sender_name,
3379
- content: msg.content,
3380
- createdAt: msg.created_at
3381
- });
3382
- return msg;
3383
- }
3384
- async function getMessages(conversationId) {
3385
- const db2 = await getDb();
3386
- const rows = await db2.select().from(messages).where(eq4(messages.conversation_id, conversationId)).orderBy(messages.created_at).all();
3387
- return rows.map((row) => {
3388
- let content;
3389
- try {
3390
- const parsed = JSON.parse(row.content);
3391
- content = Array.isArray(parsed) ? parsed : [{ type: "text", text: row.content }];
3392
- } catch {
3393
- content = [{ type: "text", text: row.content }];
3394
- }
3395
- return { ...row, content };
3396
- });
3397
- }
3398
- async function listConversationsWithParticipants(userId) {
3399
- const convs = await listConversationsForUser(userId);
3400
- if (convs.length === 0) return [];
3401
- const db2 = await getDb();
3402
- const convIds = convs.map((c) => c.id);
3403
- const rows = await db2.select({
3404
- conversationId: conversationParticipants.conversation_id,
3405
- userId: users.id,
3406
- username: users.username,
3407
- userType: users.user_type,
3408
- role: conversationParticipants.role
3409
- }).from(conversationParticipants).innerJoin(users, eq4(conversationParticipants.user_id, users.id)).where(inArray(conversationParticipants.conversation_id, convIds));
3410
- const byConv = /* @__PURE__ */ new Map();
3411
- for (const r of rows) {
3412
- let arr = byConv.get(r.conversationId);
3413
- if (!arr) {
3414
- arr = [];
3415
- byConv.set(r.conversationId, arr);
3416
- }
3417
- arr.push({
3418
- userId: r.userId,
3419
- username: r.username,
3420
- userType: r.userType,
3421
- role: r.role
3422
- });
3423
- }
3424
- return convs.map((c) => ({ ...c, participants: byConv.get(c.id) ?? [] }));
3425
- }
3426
- async function findDMConversation(agentName, participantIds) {
3427
- const db2 = await getDb();
3428
- const agentConvs = await db2.select({ id: conversations.id }).from(conversations).where(eq4(conversations.agent_name, agentName)).all();
3429
- for (const conv of agentConvs) {
3430
- const rows = await db2.select({ user_id: conversationParticipants.user_id }).from(conversationParticipants).where(eq4(conversationParticipants.conversation_id, conv.id)).all();
3431
- if (rows.length !== 2) continue;
3432
- const ids = new Set(rows.map((r) => r.user_id));
3433
- if (ids.has(participantIds[0]) && ids.has(participantIds[1])) {
3434
- return conv.id;
3435
- }
3436
- }
3437
- return null;
3438
- }
3439
- async function deleteConversation(id) {
3440
- const db2 = await getDb();
3441
- await db2.delete(conversations).where(eq4(conversations.id, id));
3442
- }
3443
-
3444
- // src/web/routes/volute/chat.ts
3445
- var chatSchema = z3.object({
3446
- message: z3.string().optional(),
3447
- conversationId: z3.string().optional(),
3448
- sender: z3.string().optional(),
3449
- images: z3.array(
3450
- z3.object({
3451
- media_type: z3.string(),
3452
- data: z3.string()
3405
+ import { z as z4 } from "zod";
3406
+ var chatSchema = z4.object({
3407
+ message: z4.string().optional(),
3408
+ conversationId: z4.string().optional(),
3409
+ sender: z4.string().optional(),
3410
+ images: z4.array(
3411
+ z4.object({
3412
+ media_type: z4.string(),
3413
+ data: z4.string()
3453
3414
  })
3454
3415
  ).optional()
3455
3416
  });
3456
3417
  function getDaemonUrl() {
3457
3418
  try {
3458
- const data = JSON.parse(readFileSync8(resolve14(voluteHome(), "daemon.json"), "utf-8"));
3419
+ const data = JSON.parse(readFileSync7(resolve13(voluteHome(), "daemon.json"), "utf-8"));
3459
3420
  return `http://${daemonLoopback()}:${data.port}`;
3460
3421
  } catch (err) {
3461
3422
  throw new Error(`Failed to read daemon config: ${err instanceof Error ? err.message : err}`);
@@ -3471,7 +3432,7 @@ function daemonFetchInternal(path, body) {
3471
3432
  if (token) headers.Authorization = `Bearer ${token}`;
3472
3433
  return fetch(`${daemonUrl}${path}`, { method: "POST", headers, body });
3473
3434
  }
3474
- var app13 = new Hono13().post("/:name/chat", zValidator3("json", chatSchema), async (c) => {
3435
+ var app13 = new Hono13().post("/:name/chat", zValidator4("json", chatSchema), async (c) => {
3475
3436
  const name = c.req.param("name");
3476
3437
  const [baseName] = name.split("@", 2);
3477
3438
  const entry = findAgent(baseName);
@@ -3532,7 +3493,7 @@ var app13 = new Hono13().post("/:name/chat", zValidator3("json", chatSchema), as
3532
3493
  const participants = await getParticipants(conversationId);
3533
3494
  const agentParticipants = participants.filter((p) => p.userType === "agent");
3534
3495
  const participantNames = participants.map((p) => p.username);
3535
- const { getAgentManager: getAgentManager2 } = await import("./agent-manager-RMWXST3T.js");
3496
+ const { getAgentManager: getAgentManager2 } = await import("./agent-manager-HHBAAL2D.js");
3536
3497
  const manager = getAgentManager2();
3537
3498
  const runningAgents = agentParticipants.map((ap) => {
3538
3499
  const agentKey = ap.username === baseName ? name : ap.username;
@@ -3602,11 +3563,11 @@ var app13 = new Hono13().post("/:name/chat", zValidator3("json", chatSchema), as
3602
3563
  if (!stream.aborted) console.error("[chat] SSE ping error:", err);
3603
3564
  });
3604
3565
  }, 15e3);
3605
- await new Promise((resolve17) => {
3566
+ await new Promise((resolve16) => {
3606
3567
  stream.onAbort(() => {
3607
3568
  unsubscribe();
3608
3569
  clearInterval(keepAlive);
3609
- resolve17();
3570
+ resolve16();
3610
3571
  });
3611
3572
  });
3612
3573
  });
@@ -3614,13 +3575,13 @@ var app13 = new Hono13().post("/:name/chat", zValidator3("json", chatSchema), as
3614
3575
  var chat_default = app13;
3615
3576
 
3616
3577
  // src/web/routes/volute/conversations.ts
3617
- import { zValidator as zValidator4 } from "@hono/zod-validator";
3578
+ import { zValidator as zValidator5 } from "@hono/zod-validator";
3618
3579
  import { Hono as Hono14 } from "hono";
3619
- import { z as z4 } from "zod";
3620
- var createConvSchema = z4.object({
3621
- title: z4.string().optional(),
3622
- participantIds: z4.array(z4.number()).optional(),
3623
- participantNames: z4.array(z4.string()).optional()
3580
+ import { z as z5 } from "zod";
3581
+ var createConvSchema = z5.object({
3582
+ title: z5.string().optional(),
3583
+ participantIds: z5.array(z5.number()).optional(),
3584
+ participantNames: z5.array(z5.string()).optional()
3624
3585
  });
3625
3586
  var app14 = new Hono14().get("/:name/conversations", async (c) => {
3626
3587
  const name = c.req.param("name");
@@ -3633,7 +3594,7 @@ var app14 = new Hono14().get("/:name/conversations", async (c) => {
3633
3594
  const all = await listConversationsForUser(lookupId);
3634
3595
  const convs = all.filter((c2) => c2.agent_name === name);
3635
3596
  return c.json(convs);
3636
- }).post("/:name/conversations", zValidator4("json", createConvSchema), async (c) => {
3597
+ }).post("/:name/conversations", zValidator5("json", createConvSchema), async (c) => {
3637
3598
  const name = c.req.param("name");
3638
3599
  const user = c.get("user");
3639
3600
  const body = c.req.valid("json");
@@ -3710,12 +3671,12 @@ var app14 = new Hono14().get("/:name/conversations", async (c) => {
3710
3671
  var conversations_default = app14;
3711
3672
 
3712
3673
  // src/web/routes/volute/user-conversations.ts
3713
- import { zValidator as zValidator5 } from "@hono/zod-validator";
3674
+ import { zValidator as zValidator6 } from "@hono/zod-validator";
3714
3675
  import { Hono as Hono15 } from "hono";
3715
- import { z as z5 } from "zod";
3716
- var createSchema = z5.object({
3717
- title: z5.string().optional(),
3718
- participantNames: z5.array(z5.string()).min(1)
3676
+ import { z as z6 } from "zod";
3677
+ var createSchema = z6.object({
3678
+ title: z6.string().optional(),
3679
+ participantNames: z6.array(z6.string()).min(1)
3719
3680
  });
3720
3681
  var app15 = new Hono15().use("*", authMiddleware).get("/", async (c) => {
3721
3682
  const user = c.get("user");
@@ -3729,7 +3690,7 @@ var app15 = new Hono15().use("*", authMiddleware).get("/", async (c) => {
3729
3690
  }
3730
3691
  const msgs = await getMessages(id);
3731
3692
  return c.json(msgs);
3732
- }).post("/", zValidator5("json", createSchema), async (c) => {
3693
+ }).post("/", zValidator6("json", createSchema), async (c) => {
3733
3694
  const user = c.get("user");
3734
3695
  const body = c.req.valid("json");
3735
3696
  const participantIds = /* @__PURE__ */ new Set();
@@ -3834,20 +3795,20 @@ async function startServer({
3834
3795
  hostname = "127.0.0.1"
3835
3796
  }) {
3836
3797
  let assetsDir = "";
3837
- let searchDir = dirname4(new URL(import.meta.url).pathname);
3798
+ let searchDir = dirname3(new URL(import.meta.url).pathname);
3838
3799
  for (let i = 0; i < 5; i++) {
3839
- const candidate = resolve15(searchDir, "dist", "web-assets");
3840
- if (existsSync10(candidate)) {
3800
+ const candidate = resolve14(searchDir, "dist", "web-assets");
3801
+ if (existsSync9(candidate)) {
3841
3802
  assetsDir = candidate;
3842
3803
  break;
3843
3804
  }
3844
- searchDir = dirname4(searchDir);
3805
+ searchDir = dirname3(searchDir);
3845
3806
  }
3846
3807
  if (assetsDir) {
3847
3808
  app_default.get("*", async (c) => {
3848
3809
  const urlPath = new URL(c.req.url).pathname;
3849
3810
  if (urlPath.startsWith("/api/")) return c.notFound();
3850
- const filePath = resolve15(assetsDir, urlPath.slice(1));
3811
+ const filePath = resolve14(assetsDir, urlPath.slice(1));
3851
3812
  if (!filePath.startsWith(assetsDir)) return c.text("Forbidden", 403);
3852
3813
  const s = await stat(filePath).catch(() => null);
3853
3814
  if (s?.isFile()) {
@@ -3856,7 +3817,7 @@ async function startServer({
3856
3817
  const body = await readFile2(filePath);
3857
3818
  return c.body(body, 200, { "Content-Type": mime });
3858
3819
  }
3859
- const indexPath = resolve15(assetsDir, "index.html");
3820
+ const indexPath = resolve14(assetsDir, "index.html");
3860
3821
  const indexStat = await stat(indexPath).catch(() => null);
3861
3822
  if (indexStat?.isFile()) {
3862
3823
  const body = await readFile2(indexPath, "utf-8");
@@ -3866,10 +3827,10 @@ async function startServer({
3866
3827
  });
3867
3828
  }
3868
3829
  const server = serve({ fetch: app_default.fetch, port, hostname });
3869
- await new Promise((resolve17, reject) => {
3830
+ await new Promise((resolve16, reject) => {
3870
3831
  server.on("listening", () => {
3871
3832
  logger_default.info("Volute UI running", { hostname, port });
3872
- resolve17();
3833
+ resolve16();
3873
3834
  });
3874
3835
  server.on("error", (err) => {
3875
3836
  reject(err);
@@ -3880,14 +3841,14 @@ async function startServer({
3880
3841
 
3881
3842
  // src/daemon.ts
3882
3843
  if (!process.env.VOLUTE_HOME) {
3883
- process.env.VOLUTE_HOME = resolve16(homedir2(), ".volute");
3844
+ process.env.VOLUTE_HOME = resolve15(homedir2(), ".volute");
3884
3845
  }
3885
3846
  async function startDaemon(opts) {
3886
3847
  const { port, hostname } = opts;
3887
3848
  const myPid = String(process.pid);
3888
3849
  const home = voluteHome();
3889
3850
  if (!opts.foreground) {
3890
- const log2 = new RotatingLog(resolve16(home, "daemon.log"));
3851
+ const log2 = new RotatingLog(resolve15(home, "daemon.log"));
3891
3852
  const write2 = (...args) => log2.write(`${format(...args)}
3892
3853
  `);
3893
3854
  console.log = write2;
@@ -3895,9 +3856,9 @@ async function startDaemon(opts) {
3895
3856
  console.warn = write2;
3896
3857
  console.info = write2;
3897
3858
  }
3898
- const DAEMON_PID_PATH = resolve16(home, "daemon.pid");
3899
- const DAEMON_JSON_PATH = resolve16(home, "daemon.json");
3900
- mkdirSync8(home, { recursive: true });
3859
+ const DAEMON_PID_PATH = resolve15(home, "daemon.pid");
3860
+ const DAEMON_JSON_PATH = resolve15(home, "daemon.json");
3861
+ mkdirSync7(home, { recursive: true });
3901
3862
  const token = process.env.VOLUTE_DAEMON_TOKEN || randomBytes(32).toString("hex");
3902
3863
  process.env.VOLUTE_DAEMON_TOKEN = token;
3903
3864
  process.env.VOLUTE_DAEMON_PORT = String(port);
@@ -3913,8 +3874,8 @@ async function startDaemon(opts) {
3913
3874
  }
3914
3875
  throw err;
3915
3876
  }
3916
- writeFileSync7(DAEMON_PID_PATH, myPid, { mode: 420 });
3917
- writeFileSync7(DAEMON_JSON_PATH, `${JSON.stringify({ port, hostname, token }, null, 2)}
3877
+ writeFileSync6(DAEMON_PID_PATH, myPid, { mode: 420 });
3878
+ writeFileSync6(DAEMON_JSON_PATH, `${JSON.stringify({ port, hostname, token }, null, 2)}
3918
3879
  `, {
3919
3880
  mode: 420
3920
3881
  });
@@ -3937,6 +3898,7 @@ async function startDaemon(opts) {
3937
3898
  if (!entry.running) continue;
3938
3899
  try {
3939
3900
  await manager.startAgent(entry.name);
3901
+ if (entry.stage === "seed") continue;
3940
3902
  const dir = agentDir(entry.name);
3941
3903
  await connectors.startConnectors(entry.name, dir, entry.port, port);
3942
3904
  scheduler.loadSchedules(entry.name);
@@ -3968,13 +3930,13 @@ async function startDaemon(opts) {
3968
3930
  console.error(`[daemon] running on ${hostname}:${port}, pid ${myPid}`);
3969
3931
  function cleanup() {
3970
3932
  try {
3971
- if (readFileSync9(DAEMON_PID_PATH, "utf-8").trim() === myPid) {
3933
+ if (readFileSync8(DAEMON_PID_PATH, "utf-8").trim() === myPid) {
3972
3934
  unlinkSync2(DAEMON_PID_PATH);
3973
3935
  }
3974
3936
  } catch {
3975
3937
  }
3976
3938
  try {
3977
- const data = JSON.parse(readFileSync9(DAEMON_JSON_PATH, "utf-8"));
3939
+ const data = JSON.parse(readFileSync8(DAEMON_JSON_PATH, "utf-8"));
3978
3940
  if (data.token === token) {
3979
3941
  unlinkSync2(DAEMON_JSON_PATH);
3980
3942
  }