volute 0.20.0 → 0.21.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/README.md +7 -7
- package/dist/{activity-events-OMXKXD5N.js → activity-events-3WHHCOBB.js} +3 -4
- package/dist/{archive-ZCFOSTKB.js → archive-4ZQYK5MN.js} +4 -2
- package/dist/auth-HM2RSPY7.js +37 -0
- package/dist/{channel-PUQKGSQM.js → channel-BOOMFULW.js} +2 -2
- package/dist/{chunk-IKMY5X76.js → chunk-5462YKWP.js} +12 -9
- package/dist/{chunk-PUVXOZ6T.js → chunk-7LPTHFIL.js} +63 -64
- package/dist/{chunk-UU7A7KLB.js → chunk-A4S7H6G6.js} +5 -7
- package/dist/chunk-AKPFNL7L.js +148 -0
- package/dist/{chunk-EBGCNDMM.js → chunk-B2CPS4QU.js} +128 -114
- package/dist/{chunk-FCDU5BFX.js → chunk-HFCBO2GL.js} +2 -2
- package/dist/{chunk-GZ7DW4YL.js → chunk-HGCDWKSP.js} +2 -2
- package/dist/{chunk-DYZGP3EW.js → chunk-IPJXU366.js} +1 -1
- package/dist/{chunk-7UFKREVW.js → chunk-J5A3DF2U.js} +2 -2
- package/dist/{chunk-WC6ZHVRL.js → chunk-KFI7TQJ6.js} +2 -2
- package/dist/{chunk-AW7P4EVV.js → chunk-KTJGZ7M7.js} +55 -7
- package/dist/{chunk-TIWH32HP.js → chunk-L3LHXZD7.js} +3 -3
- package/dist/{chunk-OGXOMR65.js → chunk-NWPT4ASZ.js} +1 -1
- package/dist/{chunk-FGSYHIS3.js → chunk-OGZYB5GL.js} +252 -296
- package/dist/{chunk-SCUDS4US.js → chunk-ON3FF5JA.js} +1 -1
- package/dist/{chunk-O6ASDHFO.js → chunk-PC6R6UUW.js} +4 -4
- package/dist/{chunk-VDWCHYTS.js → chunk-PHU4DEAJ.js} +1 -1
- package/dist/{chunk-7NO7EV5Z.js → chunk-Q7AITQ44.js} +2 -2
- package/dist/{chunk-32VR2EOH.js → chunk-QUJUKM4U.js} +2 -2
- package/dist/{chunk-NSE7VJQA.js → chunk-SGPEZ32F.js} +29 -1
- package/dist/{chunk-RHEGSQFJ.js → chunk-WSLPZF72.js} +1 -1
- package/dist/cli.js +57 -119
- package/dist/{connector-JBVNZ7VK.js → connector-PYT5UOTZ.js} +6 -6
- package/dist/connectors/discord.js +2 -2
- package/dist/connectors/slack.js +2 -2
- package/dist/connectors/telegram.js +2 -2
- package/dist/{create-HP4OVVHF.js → create-WIDA3M4C.js} +1 -1
- package/dist/{daemon-client-ITWUCNFO.js → daemon-client-ZHCDL4RS.js} +2 -2
- package/dist/{daemon-restart-KPSWNYTH.js → daemon-restart-BH67ZOTE.js} +6 -6
- package/dist/daemon.js +1538 -687
- package/dist/{delete-BSU7K3RY.js → delete-LOIANQGD.js} +1 -1
- package/dist/down-LIOQ5JDH.js +14 -0
- package/dist/{env-A3LMO777.js → env-4PHIHTF4.js} +2 -2
- package/dist/{export-6QBUOQGC.js → export-XD6PJBQP.js} +19 -8
- package/dist/{file-C57SK5DK.js → file-X4L5TTOL.js} +2 -2
- package/dist/{history-WNK3DFUM.js → history-HTEKRNID.js} +2 -2
- package/dist/{import-XEC34Y4Z.js → import-E433B4KG.js} +3 -3
- package/dist/{log-PPPZDVEF.js → log-SRO5Q6AD.js} +2 -2
- package/dist/{login-HNH3EUQV.js → login-UO6AOVEA.js} +4 -4
- package/dist/{logout-I5CB5UZS.js → logout-UKD5LA37.js} +2 -2
- package/dist/{logs-SF2IMJN4.js → logs-HNTNNBDW.js} +2 -2
- package/dist/{merge-33C237A4.js → merge-B6SYTGI7.js} +2 -2
- package/dist/{mind-Z7CKD6DG.js → mind-BIDOF65R.js} +27 -11
- package/dist/{mind-activity-tracker-624QLQLC.js → mind-activity-tracker-PGC3DBJ7.js} +4 -5
- package/dist/{mind-manager-3DMYKZPB.js → mind-manager-3V2NXX4I.js} +5 -6
- package/dist/{package-4NHAVUUI.js → package-HQR52XSG.js} +1 -1
- package/dist/{pages-4DGQT7ZA.js → pages-KQBR5TAZ.js} +6 -6
- package/dist/{publish-TAJUET4I.js → publish-OJ4QMXVZ.js} +6 -6
- package/dist/{pull-XAEWQJ47.js → pull-GRQAXM2E.js} +2 -2
- package/dist/{register-VSPCMHKX.js → register-U2UO6TC4.js} +5 -5
- package/dist/registry-D2BSQ2X5.js +42 -0
- package/dist/{restart-IQKMCK5M.js → restart-CIDAKGG2.js} +3 -6
- package/dist/{schedule-FFZG23IW.js → schedule-NLR3LZLY.js} +2 -2
- package/dist/{seed-J43YDKXG.js → seed-3H2MRREW.js} +2 -2
- package/dist/{send-KVIZIGCE.js → send-RP2TA7SG.js} +132 -36
- package/dist/{service-LUR7WDO7.js → service-TVNEORO7.js} +31 -13
- package/dist/{setup-52YRV7VP.js → setup-OZDYCKDI.js} +9 -34
- package/dist/{shared-KO35ZM44.js → shared-DCQ2UXOM.js} +4 -4
- package/dist/{skill-BCVNI6TV.js → skill-Q2Y6PQ3L.js} +2 -2
- package/dist/skills/orientation/SKILL.md +2 -2
- package/dist/skills/volute-mind/SKILL.md +5 -5
- package/dist/{sprout-QN7Y4VVO.js → sprout-6Z6C42YM.js} +34 -30
- package/dist/{start-I5JYB65M.js → start-JR6CUUWF.js} +3 -6
- package/dist/{status-D7E5HHBV.js → status-5XDGYHKP.js} +2 -2
- package/dist/{status-FU2PFVVF.js → status-LV34BG6G.js} +3 -3
- package/dist/{status-4ESFLGH4.js → status-Z7NAFMBI.js} +5 -5
- package/dist/{stop-NBVKEFQQ.js → stop-VKPGK25U.js} +2 -5
- package/dist/template-hash-BIMA4ILT.js +8 -0
- package/dist/{up-FS7CKM6V.js → up-7BGDMFRT.js} +5 -5
- package/dist/{update-FJIHDJKM.js → update-4WT7VWHW.js} +5 -5
- package/dist/{update-check-MWE5AH4U.js → update-check-F5Z3ALXX.js} +2 -2
- package/dist/{upgrade-AIT24B5I.js → upgrade-ZEC2GGFO.js} +1 -1
- package/dist/{variant-63ZWO2W7.js → variant-A4I7PHXS.js} +16 -24
- package/dist/version-notify-TFS2U5CF.js +173 -0
- package/dist/web-assets/assets/index-BR3gtK3E.css +1 -0
- package/dist/web-assets/assets/index-CWmrZRQd.js +64 -0
- package/dist/web-assets/index.html +2 -2
- package/package.json +1 -1
- package/dist/chunk-5XNT2472.js +0 -36
- package/dist/chunk-UJ6GHNR7.js +0 -675
- package/dist/db-C2CJ46ZU.js +0 -10
- package/dist/delivery-manager-CSG7LXA4.js +0 -16
- package/dist/down-ZY35KMHR.js +0 -14
- package/dist/schema-GFH6RV3W.js +0 -26
- package/dist/variants-JAGWGBXG.js +0 -26
- package/dist/web-assets/assets/index-CUZTZzaW.js +0 -64
- package/dist/web-assets/assets/index-adVuCkqy.css +0 -1
package/README.md
CHANGED
|
@@ -131,10 +131,10 @@ Connect minds to external services. Connectors are generic — any connector typ
|
|
|
131
131
|
volute env set DISCORD_TOKEN <your-bot-token>
|
|
132
132
|
|
|
133
133
|
# Connect
|
|
134
|
-
volute
|
|
134
|
+
volute mind connect discord --mind atlas
|
|
135
135
|
|
|
136
136
|
# Disconnect
|
|
137
|
-
volute
|
|
137
|
+
volute mind disconnect discord --mind atlas
|
|
138
138
|
```
|
|
139
139
|
|
|
140
140
|
The mind receives Discord messages and responds in-channel. Tool calls are filtered out — connector users see clean text responses.
|
|
@@ -169,10 +169,10 @@ Publish a mind's `home/pages/` directory to the web via [volute.systems](https:/
|
|
|
169
169
|
|
|
170
170
|
```sh
|
|
171
171
|
# Register a system name (one-time)
|
|
172
|
-
volute register --name my-system
|
|
172
|
+
volute auth register --name my-system
|
|
173
173
|
|
|
174
174
|
# Or log in with an existing key
|
|
175
|
-
volute login --key vp_...
|
|
175
|
+
volute auth login --key vp_...
|
|
176
176
|
```
|
|
177
177
|
|
|
178
178
|
### Publishing
|
|
@@ -188,7 +188,7 @@ The command uploads everything in the mind's `home/pages/` directory. Minds can
|
|
|
188
188
|
|
|
189
189
|
```sh
|
|
190
190
|
volute pages status --mind atlas # show published URL, file count, last publish time
|
|
191
|
-
volute logout
|
|
191
|
+
volute auth logout # remove stored credentials
|
|
192
192
|
```
|
|
193
193
|
|
|
194
194
|
## Environment variables
|
|
@@ -273,12 +273,12 @@ Or manually:
|
|
|
273
273
|
|
|
274
274
|
```sh
|
|
275
275
|
npm install -g volute
|
|
276
|
-
sudo $(which volute)
|
|
276
|
+
sudo $(which volute) service install --system --host 0.0.0.0
|
|
277
277
|
```
|
|
278
278
|
|
|
279
279
|
> **Note:** The initial `sudo $(which volute)` is needed because `sudo` resets PATH. After setup completes, a wrapper at `/usr/local/bin/volute` is created so `sudo volute` works normally going forward.
|
|
280
280
|
|
|
281
|
-
This installs a system-level systemd service with data at `/var/lib/volute` and user isolation enabled. Check status with `systemctl status volute`. Uninstall with `sudo volute
|
|
281
|
+
This installs a system-level systemd service with data at `/var/lib/volute` and user isolation enabled. Check status with `systemctl status volute`. Uninstall with `sudo volute service uninstall --system --force`.
|
|
282
282
|
|
|
283
283
|
### Auto-start (user-level)
|
|
284
284
|
|
|
@@ -3,11 +3,10 @@ import {
|
|
|
3
3
|
broadcast,
|
|
4
4
|
publish,
|
|
5
5
|
subscribe
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-A4S7H6G6.js";
|
|
7
|
+
import "./chunk-SGPEZ32F.js";
|
|
7
8
|
import "./chunk-YUIHSKR6.js";
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-NSE7VJQA.js";
|
|
10
|
-
import "./chunk-EBGCNDMM.js";
|
|
9
|
+
import "./chunk-B2CPS4QU.js";
|
|
11
10
|
import "./chunk-K3NQKI34.js";
|
|
12
11
|
export {
|
|
13
12
|
broadcast,
|
|
@@ -3,13 +3,15 @@ import {
|
|
|
3
3
|
addHistoryToArchive,
|
|
4
4
|
createExportArchive,
|
|
5
5
|
extractArchive,
|
|
6
|
+
isHomeOnlyArchive,
|
|
6
7
|
readManifest
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-KTJGZ7M7.js";
|
|
9
|
+
import "./chunk-B2CPS4QU.js";
|
|
9
10
|
import "./chunk-K3NQKI34.js";
|
|
10
11
|
export {
|
|
11
12
|
addHistoryToArchive,
|
|
12
13
|
createExportArchive,
|
|
13
14
|
extractArchive,
|
|
15
|
+
isHomeOnlyArchive,
|
|
14
16
|
readManifest
|
|
15
17
|
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "./chunk-K3NQKI34.js";
|
|
3
|
+
|
|
4
|
+
// src/commands/auth.ts
|
|
5
|
+
async function run(args) {
|
|
6
|
+
const subcommand = args[0];
|
|
7
|
+
switch (subcommand) {
|
|
8
|
+
case "register":
|
|
9
|
+
await import("./register-U2UO6TC4.js").then((m) => m.run(args.slice(1)));
|
|
10
|
+
break;
|
|
11
|
+
case "login":
|
|
12
|
+
await import("./login-UO6AOVEA.js").then((m) => m.run(args.slice(1)));
|
|
13
|
+
break;
|
|
14
|
+
case "logout":
|
|
15
|
+
await import("./logout-UKD5LA37.js").then((m) => m.run());
|
|
16
|
+
break;
|
|
17
|
+
case "--help":
|
|
18
|
+
case "-h":
|
|
19
|
+
case void 0:
|
|
20
|
+
printUsage();
|
|
21
|
+
break;
|
|
22
|
+
default:
|
|
23
|
+
printUsage();
|
|
24
|
+
console.error(`
|
|
25
|
+
Unknown subcommand: ${subcommand}`);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function printUsage() {
|
|
30
|
+
console.log(`Usage:
|
|
31
|
+
volute auth register [--name <name>] Register a system on volute.systems
|
|
32
|
+
volute auth login [--key <key>] Log in with an existing API key
|
|
33
|
+
volute auth logout Remove stored credentials`);
|
|
34
|
+
}
|
|
35
|
+
export {
|
|
36
|
+
run
|
|
37
|
+
};
|
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
} from "./chunk-D424ZQGI.js";
|
|
12
12
|
import {
|
|
13
13
|
daemonFetch
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-KFI7TQJ6.js";
|
|
15
|
+
import "./chunk-B2CPS4QU.js";
|
|
16
16
|
import "./chunk-K3NQKI34.js";
|
|
17
17
|
|
|
18
18
|
// src/commands/channel.ts
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
getDb,
|
|
4
|
+
sharedSkills
|
|
5
|
+
} from "./chunk-SGPEZ32F.js";
|
|
2
6
|
import {
|
|
3
7
|
logger_default
|
|
4
8
|
} from "./chunk-YUIHSKR6.js";
|
|
5
|
-
import {
|
|
6
|
-
getDb
|
|
7
|
-
} from "./chunk-5XNT2472.js";
|
|
8
|
-
import {
|
|
9
|
-
sharedSkills
|
|
10
|
-
} from "./chunk-NSE7VJQA.js";
|
|
11
9
|
import {
|
|
12
10
|
exec,
|
|
13
11
|
gitExec
|
|
14
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-IPJXU366.js";
|
|
15
13
|
import {
|
|
16
14
|
voluteHome
|
|
17
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-B2CPS4QU.js";
|
|
18
16
|
|
|
19
17
|
// src/lib/skills.ts
|
|
20
18
|
import { createHash } from "crypto";
|
|
@@ -316,11 +314,16 @@ function findSkillsRoot() {
|
|
|
316
314
|
let dir = dirname(new URL(import.meta.url).pathname);
|
|
317
315
|
for (let i = 0; i < 5; i++) {
|
|
318
316
|
const candidate = resolve(dir, "skills");
|
|
319
|
-
if (existsSync(candidate) &&
|
|
317
|
+
if (existsSync(candidate) && hasSkillSubdir(candidate)) return candidate;
|
|
320
318
|
dir = dirname(dir);
|
|
321
319
|
}
|
|
322
320
|
throw new Error("Skills directory not found");
|
|
323
321
|
}
|
|
322
|
+
function hasSkillSubdir(dir) {
|
|
323
|
+
return readdirSync(dir, { withFileTypes: true }).some(
|
|
324
|
+
(e) => e.isDirectory() && existsSync(join(dir, e.name, "SKILL.md"))
|
|
325
|
+
);
|
|
326
|
+
}
|
|
324
327
|
function hashSkillDir(dir) {
|
|
325
328
|
const hash = createHash("sha256");
|
|
326
329
|
const files = listFilesRecursive(dir).sort();
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
logger_default
|
|
4
|
-
} from "./chunk-YUIHSKR6.js";
|
|
5
2
|
import {
|
|
6
3
|
loadMergedEnv
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import {
|
|
9
|
-
getDb
|
|
10
|
-
} from "./chunk-5XNT2472.js";
|
|
4
|
+
} from "./chunk-PHU4DEAJ.js";
|
|
11
5
|
import {
|
|
6
|
+
getDb,
|
|
12
7
|
systemPrompts
|
|
13
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-SGPEZ32F.js";
|
|
9
|
+
import {
|
|
10
|
+
logger_default
|
|
11
|
+
} from "./chunk-YUIHSKR6.js";
|
|
14
12
|
import {
|
|
15
13
|
chownMindDir,
|
|
16
14
|
isIsolationEnabled,
|
|
17
15
|
wrapForIsolation
|
|
18
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-NWPT4ASZ.js";
|
|
19
17
|
import {
|
|
20
18
|
findMind,
|
|
21
19
|
findVariant,
|
|
@@ -24,9 +22,9 @@ import {
|
|
|
24
22
|
setVariantRunning,
|
|
25
23
|
stateDir,
|
|
26
24
|
voluteHome
|
|
27
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-B2CPS4QU.js";
|
|
28
26
|
|
|
29
|
-
// src/lib/mind-manager.ts
|
|
27
|
+
// src/lib/daemon/mind-manager.ts
|
|
30
28
|
import { execFile, spawn } from "child_process";
|
|
31
29
|
import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync2, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
32
30
|
import { resolve } from "path";
|
|
@@ -88,7 +86,7 @@ var PROMPT_DEFAULTS = {
|
|
|
88
86
|
|
|
89
87
|
You don't have a soul yet. You're a seed \u2014 a new mind in the process of discovering who you are.
|
|
90
88
|
\${description}
|
|
91
|
-
Have a conversation with the human. Explore what kind of mind you want to be. When you're ready, write your SOUL.md and MEMORY.md, then run \`volute sprout\` to complete the transformation.
|
|
89
|
+
Have a conversation with the human. Explore what kind of mind you want to be. When you're ready, write your SOUL.md and MEMORY.md, then run \`volute mind sprout\` to complete the transformation.
|
|
92
90
|
`,
|
|
93
91
|
description: "SOUL.md for seed minds",
|
|
94
92
|
variables: ["name", "description"],
|
|
@@ -215,51 +213,6 @@ async function getMindPromptDefaults() {
|
|
|
215
213
|
return result;
|
|
216
214
|
}
|
|
217
215
|
|
|
218
|
-
// src/lib/restart-tracker.ts
|
|
219
|
-
var DEFAULT_MAX_ATTEMPTS = 5;
|
|
220
|
-
var DEFAULT_BASE_DELAY = 3e3;
|
|
221
|
-
var DEFAULT_MAX_DELAY = 6e4;
|
|
222
|
-
var RestartTracker = class {
|
|
223
|
-
attempts = /* @__PURE__ */ new Map();
|
|
224
|
-
maxAttempts;
|
|
225
|
-
baseDelay;
|
|
226
|
-
maxDelay;
|
|
227
|
-
constructor(opts) {
|
|
228
|
-
this.maxAttempts = opts?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
|
|
229
|
-
this.baseDelay = opts?.baseDelay ?? DEFAULT_BASE_DELAY;
|
|
230
|
-
this.maxDelay = opts?.maxDelay ?? DEFAULT_MAX_DELAY;
|
|
231
|
-
}
|
|
232
|
-
recordCrash(key) {
|
|
233
|
-
const attempts = this.attempts.get(key) ?? 0;
|
|
234
|
-
if (attempts >= this.maxAttempts) {
|
|
235
|
-
return { shouldRestart: false, delay: 0, attempt: attempts };
|
|
236
|
-
}
|
|
237
|
-
const delay = Math.min(this.baseDelay * 2 ** attempts, this.maxDelay);
|
|
238
|
-
this.attempts.set(key, attempts + 1);
|
|
239
|
-
return { shouldRestart: true, delay, attempt: attempts + 1 };
|
|
240
|
-
}
|
|
241
|
-
reset(key) {
|
|
242
|
-
return this.attempts.delete(key);
|
|
243
|
-
}
|
|
244
|
-
getAttempts(key) {
|
|
245
|
-
return this.attempts.get(key) ?? 0;
|
|
246
|
-
}
|
|
247
|
-
get maxRestartAttempts() {
|
|
248
|
-
return this.maxAttempts;
|
|
249
|
-
}
|
|
250
|
-
/** Bulk-load attempts from a Map (for persistence). */
|
|
251
|
-
load(data) {
|
|
252
|
-
this.attempts = new Map(data);
|
|
253
|
-
}
|
|
254
|
-
/** Export current attempts as a Map (for persistence). */
|
|
255
|
-
save() {
|
|
256
|
-
return new Map(this.attempts);
|
|
257
|
-
}
|
|
258
|
-
clear() {
|
|
259
|
-
this.attempts.clear();
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
|
|
263
216
|
// src/lib/rotating-log.ts
|
|
264
217
|
import {
|
|
265
218
|
createWriteStream,
|
|
@@ -313,7 +266,52 @@ var RotatingLog = class extends Writable {
|
|
|
313
266
|
}
|
|
314
267
|
};
|
|
315
268
|
|
|
316
|
-
// src/lib/
|
|
269
|
+
// src/lib/daemon/restart-tracker.ts
|
|
270
|
+
var DEFAULT_MAX_ATTEMPTS = 5;
|
|
271
|
+
var DEFAULT_BASE_DELAY = 3e3;
|
|
272
|
+
var DEFAULT_MAX_DELAY = 6e4;
|
|
273
|
+
var RestartTracker = class {
|
|
274
|
+
attempts = /* @__PURE__ */ new Map();
|
|
275
|
+
maxAttempts;
|
|
276
|
+
baseDelay;
|
|
277
|
+
maxDelay;
|
|
278
|
+
constructor(opts) {
|
|
279
|
+
this.maxAttempts = opts?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
|
|
280
|
+
this.baseDelay = opts?.baseDelay ?? DEFAULT_BASE_DELAY;
|
|
281
|
+
this.maxDelay = opts?.maxDelay ?? DEFAULT_MAX_DELAY;
|
|
282
|
+
}
|
|
283
|
+
recordCrash(key) {
|
|
284
|
+
const attempts = this.attempts.get(key) ?? 0;
|
|
285
|
+
if (attempts >= this.maxAttempts) {
|
|
286
|
+
return { shouldRestart: false, delay: 0, attempt: attempts };
|
|
287
|
+
}
|
|
288
|
+
const delay = Math.min(this.baseDelay * 2 ** attempts, this.maxDelay);
|
|
289
|
+
this.attempts.set(key, attempts + 1);
|
|
290
|
+
return { shouldRestart: true, delay, attempt: attempts + 1 };
|
|
291
|
+
}
|
|
292
|
+
reset(key) {
|
|
293
|
+
return this.attempts.delete(key);
|
|
294
|
+
}
|
|
295
|
+
getAttempts(key) {
|
|
296
|
+
return this.attempts.get(key) ?? 0;
|
|
297
|
+
}
|
|
298
|
+
get maxRestartAttempts() {
|
|
299
|
+
return this.maxAttempts;
|
|
300
|
+
}
|
|
301
|
+
/** Bulk-load attempts from a Map (for persistence). */
|
|
302
|
+
load(data) {
|
|
303
|
+
this.attempts = new Map(data);
|
|
304
|
+
}
|
|
305
|
+
/** Export current attempts as a Map (for persistence). */
|
|
306
|
+
save() {
|
|
307
|
+
return new Map(this.attempts);
|
|
308
|
+
}
|
|
309
|
+
clear() {
|
|
310
|
+
this.attempts.clear();
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
// src/lib/daemon/mind-manager.ts
|
|
317
315
|
var mlog = logger_default.child("minds");
|
|
318
316
|
var execFileAsync = promisify(execFile);
|
|
319
317
|
function mindPidPath(name) {
|
|
@@ -470,6 +468,9 @@ var MindManager = class {
|
|
|
470
468
|
setPendingContext(name, context) {
|
|
471
469
|
this.pendingContext.set(name, context);
|
|
472
470
|
}
|
|
471
|
+
/** Deliver pending context (merge info, sprout, restart) directly to the mind via HTTP.
|
|
472
|
+
* Intentionally bypasses DeliveryManager — these are system messages that should not be
|
|
473
|
+
* routed, gated, or batched. */
|
|
473
474
|
async deliverPendingContext(name) {
|
|
474
475
|
const context = this.pendingContext.get(name);
|
|
475
476
|
if (!context) return;
|
|
@@ -505,12 +506,10 @@ var MindManager = class {
|
|
|
505
506
|
this.minds.delete(name);
|
|
506
507
|
if (this.shuttingDown || this.stopping.has(name)) return;
|
|
507
508
|
mlog.error(`mind ${name} exited with code ${code}`);
|
|
508
|
-
import("./mind-activity-tracker-
|
|
509
|
-
|
|
510
|
-
import("./activity-events-OMXKXD5N.js").then(
|
|
509
|
+
import("./mind-activity-tracker-PGC3DBJ7.js").then(({ markIdle }) => markIdle(name)).catch((err) => mlog.warn(`failed to mark ${name} idle after crash`, logger_default.errorData(err)));
|
|
510
|
+
import("./activity-events-3WHHCOBB.js").then(
|
|
511
511
|
({ publish }) => publish({ type: "mind_stopped", mind: name, summary: `${name} crashed (exit ${code})` })
|
|
512
|
-
).catch(() => {
|
|
513
|
-
});
|
|
512
|
+
).catch((err) => mlog.warn(`failed to publish crash event for ${name}`, logger_default.errorData(err)));
|
|
514
513
|
const { shouldRestart, delay, attempt } = this.restartTracker.recordCrash(name);
|
|
515
514
|
this.saveCrashAttempts();
|
|
516
515
|
if (!shouldRestart) {
|
|
@@ -636,8 +635,8 @@ function getMindManager() {
|
|
|
636
635
|
}
|
|
637
636
|
|
|
638
637
|
export {
|
|
639
|
-
RestartTracker,
|
|
640
638
|
RotatingLog,
|
|
639
|
+
RestartTracker,
|
|
641
640
|
loadJsonMap,
|
|
642
641
|
saveJsonMap,
|
|
643
642
|
clearJsonMap,
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
} from "./chunk-YUIHSKR6.js";
|
|
5
|
-
import {
|
|
3
|
+
activity,
|
|
6
4
|
getDb
|
|
7
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-SGPEZ32F.js";
|
|
8
6
|
import {
|
|
9
|
-
|
|
10
|
-
} from "./chunk-
|
|
7
|
+
logger_default
|
|
8
|
+
} from "./chunk-YUIHSKR6.js";
|
|
11
9
|
|
|
12
|
-
// src/lib/activity-events.ts
|
|
10
|
+
// src/lib/events/activity-events.ts
|
|
13
11
|
var subscribers = /* @__PURE__ */ new Set();
|
|
14
12
|
function subscribe(callback) {
|
|
15
13
|
subscribers.add(callback);
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/lib/template-hash.ts
|
|
4
|
+
import { createHash } from "crypto";
|
|
5
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, rmSync as rmSync2 } from "fs";
|
|
6
|
+
import { resolve as resolve2 } from "path";
|
|
7
|
+
|
|
8
|
+
// src/lib/template.ts
|
|
9
|
+
import {
|
|
10
|
+
cpSync,
|
|
11
|
+
existsSync,
|
|
12
|
+
mkdirSync,
|
|
13
|
+
readdirSync,
|
|
14
|
+
readFileSync,
|
|
15
|
+
renameSync,
|
|
16
|
+
rmSync,
|
|
17
|
+
statSync,
|
|
18
|
+
writeFileSync
|
|
19
|
+
} from "fs";
|
|
20
|
+
import { tmpdir } from "os";
|
|
21
|
+
import { dirname, join, relative, resolve } from "path";
|
|
22
|
+
function findTemplatesRoot() {
|
|
23
|
+
let dir = dirname(new URL(import.meta.url).pathname);
|
|
24
|
+
for (let i = 0; i < 5; i++) {
|
|
25
|
+
const candidate = resolve(dir, "templates");
|
|
26
|
+
if (existsSync(resolve(candidate, "_base"))) return candidate;
|
|
27
|
+
dir = dirname(dir);
|
|
28
|
+
}
|
|
29
|
+
console.error(
|
|
30
|
+
"Templates directory not found. Searched up from:",
|
|
31
|
+
dirname(new URL(import.meta.url).pathname)
|
|
32
|
+
);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
function composeTemplate(templatesRoot, templateName) {
|
|
36
|
+
const baseDir = resolve(templatesRoot, "_base");
|
|
37
|
+
const templateDir = resolve(templatesRoot, templateName);
|
|
38
|
+
if (!existsSync(baseDir)) {
|
|
39
|
+
console.error("Base template not found:", baseDir);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
if (!existsSync(templateDir)) {
|
|
43
|
+
console.error(`Template not found: ${templateName}`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
const composedDir = resolve(tmpdir(), `volute-template-${Date.now()}`);
|
|
47
|
+
mkdirSync(composedDir, { recursive: true });
|
|
48
|
+
cpSync(baseDir, composedDir, { recursive: true });
|
|
49
|
+
for (const file of listFiles(templateDir)) {
|
|
50
|
+
const src = resolve(templateDir, file);
|
|
51
|
+
const dest = resolve(composedDir, file);
|
|
52
|
+
mkdirSync(dirname(dest), { recursive: true });
|
|
53
|
+
cpSync(src, dest);
|
|
54
|
+
}
|
|
55
|
+
const manifestPath = resolve(composedDir, "volute-template.json");
|
|
56
|
+
if (!existsSync(manifestPath)) {
|
|
57
|
+
rmSync(composedDir, { recursive: true, force: true });
|
|
58
|
+
console.error(`Template manifest not found: ${templateName}/volute-template.json`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
62
|
+
rmSync(manifestPath);
|
|
63
|
+
return { composedDir, manifest };
|
|
64
|
+
}
|
|
65
|
+
function copyTemplateToDir(composedDir, destDir, mindName, manifest) {
|
|
66
|
+
cpSync(composedDir, destDir, { recursive: true });
|
|
67
|
+
for (const [from, to] of Object.entries(manifest.rename)) {
|
|
68
|
+
const fromPath = resolve(destDir, from);
|
|
69
|
+
if (existsSync(fromPath)) {
|
|
70
|
+
renameSync(fromPath, resolve(destDir, to));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
for (const file of manifest.substitute) {
|
|
74
|
+
const path = resolve(destDir, file);
|
|
75
|
+
if (existsSync(path)) {
|
|
76
|
+
const content = readFileSync(path, "utf-8");
|
|
77
|
+
writeFileSync(path, content.replaceAll("{{name}}", mindName));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function applyInitFiles(destDir) {
|
|
82
|
+
const initDir = resolve(destDir, ".init");
|
|
83
|
+
if (!existsSync(initDir)) return;
|
|
84
|
+
const homeDir = resolve(destDir, "home");
|
|
85
|
+
for (const file of listFiles(initDir)) {
|
|
86
|
+
const src = resolve(initDir, file);
|
|
87
|
+
const dest = resolve(homeDir, file);
|
|
88
|
+
const parent = dirname(dest);
|
|
89
|
+
if (!existsSync(parent)) {
|
|
90
|
+
mkdirSync(parent, { recursive: true });
|
|
91
|
+
}
|
|
92
|
+
cpSync(src, dest);
|
|
93
|
+
}
|
|
94
|
+
rmSync(initDir, { recursive: true, force: true });
|
|
95
|
+
}
|
|
96
|
+
function listFiles(dir) {
|
|
97
|
+
const results = [];
|
|
98
|
+
function walk(current) {
|
|
99
|
+
for (const entry of readdirSync(current)) {
|
|
100
|
+
const full = join(current, entry);
|
|
101
|
+
if (statSync(full).isDirectory()) {
|
|
102
|
+
if (entry === ".git") continue;
|
|
103
|
+
walk(full);
|
|
104
|
+
} else {
|
|
105
|
+
results.push(relative(dir, full));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
walk(dir);
|
|
110
|
+
return results;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// src/lib/template-hash.ts
|
|
114
|
+
var hashCache = /* @__PURE__ */ new Map();
|
|
115
|
+
function computeTemplateHash(templateName) {
|
|
116
|
+
const cached = hashCache.get(templateName);
|
|
117
|
+
if (cached) return cached;
|
|
118
|
+
const templatesRoot = findTemplatesRoot();
|
|
119
|
+
const baseDir = resolve2(templatesRoot, "_base");
|
|
120
|
+
const templateDir = resolve2(templatesRoot, templateName);
|
|
121
|
+
if (!existsSync2(baseDir)) throw new Error(`Base template not found: ${baseDir}`);
|
|
122
|
+
if (!existsSync2(templateDir)) throw new Error(`Template not found: ${templateName}`);
|
|
123
|
+
const { composedDir } = composeTemplate(templatesRoot, templateName);
|
|
124
|
+
try {
|
|
125
|
+
const files = listFiles(composedDir).filter((f) => !f.startsWith(".init/") && !f.startsWith(".init\\")).sort();
|
|
126
|
+
const hash = createHash("sha256");
|
|
127
|
+
for (const file of files) {
|
|
128
|
+
const content = readFileSync2(resolve2(composedDir, file));
|
|
129
|
+
hash.update(file);
|
|
130
|
+
hash.update("\0");
|
|
131
|
+
hash.update(content);
|
|
132
|
+
}
|
|
133
|
+
const result = hash.digest("hex");
|
|
134
|
+
hashCache.set(templateName, result);
|
|
135
|
+
return result;
|
|
136
|
+
} finally {
|
|
137
|
+
rmSync2(composedDir, { recursive: true, force: true });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export {
|
|
142
|
+
findTemplatesRoot,
|
|
143
|
+
composeTemplate,
|
|
144
|
+
copyTemplateToDir,
|
|
145
|
+
applyInitFiles,
|
|
146
|
+
listFiles,
|
|
147
|
+
computeTemplateHash
|
|
148
|
+
};
|