volute 0.45.1 → 0.46.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 +3 -3
- package/dist/{activity-events-OMCSM7XW.js → activity-events-NF6VWTJQ.js} +2 -2
- package/dist/{ai-service-534WUSDL.js → ai-service-UODCCE4O.js} +3 -3
- package/dist/{archive-6R4TZMYI.js → archive-WS2L2VIQ.js} +2 -2
- package/dist/{auth-FRZJVQCS.js → auth-CCFAU4GQ.js} +3 -3
- package/dist/{avatar-image-BNWEXSA2.js → avatar-image-6KY6UU4D.js} +3 -3
- package/dist/{backup-OZXHL3JS.js → backup-TST5C2YN.js} +7 -7
- package/dist/{chat-I4EDDIQC.js → chat-ZIQQS25U.js} +2 -2
- package/dist/{chunk-ZIR7HSAX.js → chunk-4JOQZPCE.js} +1 -1
- package/dist/chunk-4YU7HF4L.js +237 -0
- package/dist/{chunk-JSRMEY52.js → chunk-5ZQZDDIK.js} +10 -5
- package/dist/{chunk-2BONPXAF.js → chunk-6EMWJZBK.js} +1 -1
- package/dist/{chunk-LAXUUY7O.js → chunk-A7WQZKOU.js} +2 -2
- package/dist/{chunk-H7IYFRAL.js → chunk-ALKYQULU.js} +10 -5
- package/dist/{chunk-5AUKCNPE.js → chunk-BJZ4PV7R.js} +8 -8
- package/dist/{chunk-KP3KWNG6.js → chunk-CDPBTTZO.js} +2 -2
- package/dist/{chunk-SQL7M4HJ.js → chunk-DRJ24GXK.js} +2 -2
- package/dist/{chunk-77BVGCTZ.js → chunk-E3DA4HYV.js} +9 -9
- package/dist/{chunk-322KE457.js → chunk-F7H6ATM4.js} +1 -1
- package/dist/{chunk-KVKP6VQ5.js → chunk-FXORA5JG.js} +12 -3
- package/dist/{chunk-3ERIL673.js → chunk-H2X54EHC.js} +1 -1
- package/dist/{chunk-TSK5PI4L.js → chunk-IHKGWTGT.js} +1 -1
- package/dist/{chunk-U4FNXDEJ.js → chunk-JO5IO4FH.js} +422 -168
- package/dist/{chunk-OXXTPILE.js → chunk-JZ62SYWR.js} +1 -1
- package/dist/{chunk-IUXTYXFI.js → chunk-K6T43YBD.js} +3 -3
- package/dist/{chunk-Y6OPHHGM.js → chunk-KGIXX4NM.js} +4 -4
- package/dist/{chunk-HVU45COX.js → chunk-KQSFTPIM.js} +1 -1
- package/dist/{chunk-CYI534DJ.js → chunk-OV7ZQ2GH.js} +2 -2
- package/dist/{chunk-CU6OFXMM.js → chunk-PFZBNKUH.js} +9 -0
- package/dist/{clock-K43IMROX.js → chunk-PJ45FQPT.js} +21 -16
- package/dist/{chunk-QMJJWTNL.js → chunk-QCN24XEN.js} +1 -1
- package/dist/{chunk-UMI4UIJG.js → chunk-R77O2WMK.js} +1 -1
- package/dist/{chunk-IEWZ7VD7.js → chunk-RRNXJOKB.js} +2 -2
- package/dist/{chunk-FHWUQZXE.js → chunk-RXEEYDIB.js} +1 -1
- package/dist/{chunk-Q2XBKQ2D.js → chunk-TQJ6ZYVY.js} +2 -2
- package/dist/{chunk-V4GYPD5L.js → chunk-YXSUMLTC.js} +46 -269
- package/dist/{chunk-5GT7URXJ.js → chunk-ZDZISKCL.js} +1 -1
- package/dist/{chunk-ZMIMSIIT.js → chunk-ZNMCCHCP.js} +48 -2
- package/dist/cli.js +20 -20
- package/dist/clock-RHS2JEDL.js +16 -0
- package/dist/{cloud-sync-Y7LQPRE3.js → cloud-sync-46RS4SDA.js} +17 -16
- package/dist/{conversations-G4LYMHAA.js → conversations-CJOOCGNW.js} +3 -3
- package/dist/{create-2YY7IPMS.js → create-IOV4GCRX.js} +1 -1
- package/dist/{daemon-restart-ABP54YN6.js → daemon-restart-VFEI57UO.js} +6 -6
- package/dist/daemon.js +392 -270
- package/dist/{db-JFLCJCUG.js → db-MF2JNRUW.js} +1 -1
- package/dist/{delete-BFMIGAIB.js → delete-HPLC7ETU.js} +1 -1
- package/dist/delivery-manager-JINZRG2W.js +33 -0
- package/dist/{delivery-router-6DE3BPHO.js → delivery-router-N4A7ZC5T.js} +2 -2
- package/dist/{down-XCAZXWLB.js → down-U2CZ23M4.js} +4 -4
- package/dist/echo-text-VQPB5L2X.js +33 -0
- package/dist/{exec-4GWHAHS3.js → exec-G3ZRST4Z.js} +2 -2
- package/dist/{export-ID7YUSLZ.js → export-LY723I3Z.js} +5 -5
- package/dist/{extensions-AYSPKE33.js → extensions-ZELQLTSR.js} +17 -16
- package/dist/{files-BQ2WB5KC.js → files-4LN3EN7Q.js} +2 -2
- package/dist/{import-SKID37QX.js → import-42YNQBF4.js} +5 -5
- package/dist/{isolation-5MB3J73F.js → isolation-YMGZZ4E5.js} +2 -2
- package/dist/{join-RXPXGV4L.js → join-ZJV7W6MO.js} +4 -0
- package/dist/{login-LM4NF4ZB.js → login-M6OJUPQ2.js} +1 -1
- package/dist/{logout-CTJVIZGA.js → logout-WQBWO77G.js} +1 -1
- package/dist/message-delivery-R7JSQGYX.js +37 -0
- package/dist/{mind-KLHC7XYR.js → mind-LHKS55DI.js} +12 -12
- package/dist/{mind-activity-tracker-BGHJE7XA.js → mind-activity-tracker-3QRNJVR4.js} +3 -3
- package/dist/mind-service-NB2JMWQZ.js +39 -0
- package/dist/mind-sleep-74TGOQBC.js +83 -0
- package/dist/{package-BMHV7UHN.js → package-DOD6CPO6.js} +2 -1
- package/dist/{registry-NUJAGLQJ.js → registry-OUZBZ3Q4.js} +5 -1
- package/dist/{sandbox-72MWV4JL.js → sandbox-ZJ7QA6Z6.js} +3 -3
- package/dist/scheduler-WVKII3LA.js +31 -0
- package/dist/{seed-4MKQ5QKG.js → seed-CNYIHPOH.js} +1 -1
- package/dist/{seed-cmd-LCXMR7VV.js → seed-cmd-AVNUNLZV.js} +2 -2
- package/dist/{seed-create-N2BF5LQX.js → seed-create-ANXGYSCC.js} +5 -5
- package/dist/{seed-sprout-6ZDP23YI.js → seed-sprout-NIUFTX32.js} +10 -8
- package/dist/{send-O6W53VBM.js → send-SPE6DVNJ.js} +8 -2
- package/dist/{service-AQVPUANO.js → service-UOCLXDWR.js} +3 -3
- package/dist/{service-install-4QNUDKLM.js → service-install-4HHFDDWY.js} +4 -4
- package/dist/{setup-3O6O2JZ7.js → setup-QT2A25SY.js} +6 -6
- package/dist/{setup-73YBJZQL.js → setup-Y2EJI3GG.js} +2 -2
- package/dist/skills/imagegen/scripts/imagegen.ts +100 -40
- package/dist/skills/orientation/SKILL.md +1 -1
- package/dist/skills/volute-mind/SKILL.md +13 -9
- package/dist/skills/volute-mind/references/sleep.md +8 -1
- package/dist/{skills-ND4ZFYUW.js → skills-AKCFA7BN.js} +4 -4
- package/dist/sleep-manager-G6TXSDP7.js +35 -0
- package/dist/{spirit-II3HOERM.js → spirit-RPBLLUQ5.js} +7 -7
- package/dist/{sprout-4KUG76AQ.js → sprout-SMX42ZBP.js} +1 -1
- package/dist/{src-XFY3XDD6.js → src-OJHARHTF.js} +28 -17
- package/dist/{status-E5DQNCAO.js → status-SWRVGXBI.js} +4 -4
- package/dist/system-chat-NDAW6YP7.js +37 -0
- package/dist/{tailscale-QAWVKQKU.js → tailscale-3XOKOW7T.js} +1 -1
- package/dist/{turn-tracker-QQIVVXBI.js → turn-tracker-FOIBNUUA.js} +5 -4
- package/dist/{up-LG56MPBI.js → up-PS6PFS75.js} +5 -5
- package/dist/{update-7TYVH5FM.js → update-SWAYZRWJ.js} +4 -4
- package/dist/{update-check-VSCSJ7KX.js → update-check-PQ2MZ47K.js} +2 -2
- package/dist/{version-notify-CODJOUW2.js → version-notify-C5CH7CVP.js} +24 -19
- package/dist/{volute-config-TS62GS6A.js → volute-config-A52FHWKM.js} +5 -1
- package/dist/web-assets/assets/{index-Dac11sKB.js → index-CU6XWICM.js} +15 -15
- package/dist/web-assets/index.html +1 -1
- package/package.json +2 -1
- package/templates/_base/home/VOLUTE.md +6 -2
- package/templates/_base/src/lib/context-breakdown.ts +57 -67
- package/templates/_base/src/lib/file-handler.ts +3 -3
- package/templates/_base/src/lib/router.ts +21 -25
- package/templates/_base/src/lib/startup.ts +2 -0
- package/templates/_base/src/lib/types.ts +2 -2
- package/templates/_base/src/lib/volute-server.ts +2 -2
- package/templates/claude/src/agent.ts +147 -46
- package/templates/claude/src/lib/message-channel.ts +23 -0
- package/templates/claude/src/lib/session-reaper.ts +68 -0
- package/templates/claude/src/server.ts +1 -0
- package/templates/codex/src/agent.ts +80 -46
- package/templates/pi/src/agent.ts +73 -45
- package/dist/delivery-manager-R5STGLXB.js +0 -32
- package/dist/echo-text-NQXYYYCU.js +0 -32
- package/dist/message-delivery-IUAXRPFE.js +0 -34
- package/dist/mind-service-BF2LUQMH.js +0 -36
- package/dist/mind-sleep-YMBR3I35.js +0 -47
- package/dist/scheduler-YHJRRV6E.js +0 -30
- package/dist/sleep-manager-YAHDOIU5.js +0 -34
- package/dist/system-chat-E65T2HSW.js +0 -34
|
@@ -34,8 +34,8 @@ Choose a model [1-${enabled.length}]: `);
|
|
|
34
34
|
}
|
|
35
35
|
var cmd = command({
|
|
36
36
|
name: "volute seed create",
|
|
37
|
-
description: "Plant a new seed
|
|
38
|
-
args: [{ name: "name", required: true, description: "Name for the seed
|
|
37
|
+
description: "Plant a new seed",
|
|
38
|
+
args: [{ name: "name", required: true, description: "Name for the seed" }],
|
|
39
39
|
flags: {
|
|
40
40
|
template: { type: "string", description: "Template to use" },
|
|
41
41
|
model: { type: "string", description: "AI model to use" },
|
|
@@ -53,13 +53,13 @@ var cmd = command({
|
|
|
53
53
|
let model = flags.model;
|
|
54
54
|
let template = flags.template;
|
|
55
55
|
if (!template) {
|
|
56
|
-
const { resolveTemplate } = await import("./ai-service-
|
|
56
|
+
const { resolveTemplate } = await import("./ai-service-UODCCE4O.js");
|
|
57
57
|
template = await resolveTemplate(model);
|
|
58
58
|
}
|
|
59
59
|
if (template !== "claude" && !model) {
|
|
60
60
|
if (process.env.VOLUTE_MIND || !process.stdin.isTTY) {
|
|
61
|
-
const { getSpiritModel } = await import("./spirit-
|
|
62
|
-
const { qualifyModelId } = await import("./ai-service-
|
|
61
|
+
const { getSpiritModel } = await import("./spirit-RPBLLUQ5.js");
|
|
62
|
+
const { qualifyModelId } = await import("./ai-service-UODCCE4O.js");
|
|
63
63
|
const spiritModel = getSpiritModel();
|
|
64
64
|
if (spiritModel) {
|
|
65
65
|
model = template === "pi" ? qualifyModelId(spiritModel) : spiritModel;
|
|
@@ -8,20 +8,22 @@ import {
|
|
|
8
8
|
import "./chunk-O7IGP7ZW.js";
|
|
9
9
|
import {
|
|
10
10
|
getStandardSkillsWithExtensions
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import
|
|
13
|
-
|
|
11
|
+
} from "./chunk-KGIXX4NM.js";
|
|
12
|
+
import {
|
|
13
|
+
ORIENTATION_MARKER
|
|
14
|
+
} from "./chunk-4YU7HF4L.js";
|
|
15
|
+
import "./chunk-H2X54EHC.js";
|
|
16
|
+
import "./chunk-F7H6ATM4.js";
|
|
14
17
|
import "./chunk-T2TP6ZC6.js";
|
|
15
18
|
import {
|
|
16
19
|
mindDir
|
|
17
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-ALKYQULU.js";
|
|
18
21
|
import "./chunk-ZV7MFISX.js";
|
|
19
22
|
import "./chunk-K3NQKI34.js";
|
|
20
23
|
|
|
21
24
|
// packages/cli/src/commands/seed-sprout.ts
|
|
22
25
|
import { existsSync, readFileSync } from "fs";
|
|
23
26
|
import { resolve } from "path";
|
|
24
|
-
var ORIENTATION_MARKER = "You don't have a soul yet";
|
|
25
27
|
var cmd = command({
|
|
26
28
|
name: "volute seed sprout",
|
|
27
29
|
description: "Complete orientation and become a full mind (run by the seed itself)",
|
|
@@ -60,9 +62,9 @@ var cmd = command({
|
|
|
60
62
|
console.error("Write your MEMORY.md before sprouting.");
|
|
61
63
|
process.exit(1);
|
|
62
64
|
}
|
|
63
|
-
const { isImagegenEnabled } = await import("./setup-
|
|
65
|
+
const { isImagegenEnabled } = await import("./setup-Y2EJI3GG.js");
|
|
64
66
|
if (isImagegenEnabled()) {
|
|
65
|
-
const { readVoluteConfig } = await import("./volute-config-
|
|
67
|
+
const { readVoluteConfig } = await import("./volute-config-A52FHWKM.js");
|
|
66
68
|
const config = readVoluteConfig(dir);
|
|
67
69
|
const avatarPath = config?.profile?.avatar;
|
|
68
70
|
if (!avatarPath || !existsSync(resolve(dir, "home", avatarPath))) {
|
|
@@ -73,7 +75,7 @@ var cmd = command({
|
|
|
73
75
|
}
|
|
74
76
|
}
|
|
75
77
|
const { getClient, urlOf } = await import("./api-client-LC5YRA32.js");
|
|
76
|
-
const { mindSkillsDir } = await import("./skills-
|
|
78
|
+
const { mindSkillsDir } = await import("./skills-AKCFA7BN.js");
|
|
77
79
|
const client = getClient();
|
|
78
80
|
const failedSkills = [];
|
|
79
81
|
for (const skillId of getStandardSkillsWithExtensions()) {
|
|
@@ -18,8 +18,8 @@ import {
|
|
|
18
18
|
import "./chunk-O7IGP7ZW.js";
|
|
19
19
|
import {
|
|
20
20
|
formatFileSize
|
|
21
|
-
} from "./chunk-
|
|
22
|
-
import "./chunk-
|
|
21
|
+
} from "./chunk-R77O2WMK.js";
|
|
22
|
+
import "./chunk-ALKYQULU.js";
|
|
23
23
|
import "./chunk-ZV7MFISX.js";
|
|
24
24
|
import "./chunk-K3NQKI34.js";
|
|
25
25
|
|
|
@@ -286,6 +286,12 @@ To reply to a person, use their username from the message prefix (e.g. volute ch
|
|
|
286
286
|
const targetName = parsed.identifier.slice(1);
|
|
287
287
|
const mindSelf = process.env.VOLUTE_MIND;
|
|
288
288
|
const sender = flags.sender || mindSelf || userInfo().username;
|
|
289
|
+
if (mindSelf && targetName === mindSelf) {
|
|
290
|
+
console.error(
|
|
291
|
+
`Can't send to @${targetName} \u2014 that's your own system channel. System messages there are automated notices; they don't need a reply.`
|
|
292
|
+
);
|
|
293
|
+
process.exit(1);
|
|
294
|
+
}
|
|
289
295
|
const targetIsMind = await isMind(targetName);
|
|
290
296
|
waitMindName = targetIsMind ? targetName : void 0;
|
|
291
297
|
const contextMind = mindSelf ?? targetName;
|
|
@@ -9,9 +9,9 @@ import {
|
|
|
9
9
|
SYSTEM_LAUNCHD_PLIST_PATH,
|
|
10
10
|
SYSTEM_SERVICE_PATH,
|
|
11
11
|
USER_SYSTEMD_UNIT
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-TQJ6ZYVY.js";
|
|
13
|
+
import "./chunk-H2X54EHC.js";
|
|
14
|
+
import "./chunk-ALKYQULU.js";
|
|
15
15
|
import "./chunk-ZV7MFISX.js";
|
|
16
16
|
import "./chunk-K3NQKI34.js";
|
|
17
17
|
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
generateUserPlist,
|
|
4
4
|
generateUserUnit,
|
|
5
5
|
installUserService
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-CDPBTTZO.js";
|
|
7
|
+
import "./chunk-TQJ6ZYVY.js";
|
|
8
|
+
import "./chunk-H2X54EHC.js";
|
|
9
|
+
import "./chunk-ALKYQULU.js";
|
|
10
10
|
import "./chunk-ZV7MFISX.js";
|
|
11
11
|
import "./chunk-K3NQKI34.js";
|
|
12
12
|
export {
|
|
@@ -8,21 +8,21 @@ import {
|
|
|
8
8
|
import "./chunk-O7IGP7ZW.js";
|
|
9
9
|
import {
|
|
10
10
|
installUserService
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-CDPBTTZO.js";
|
|
12
12
|
import {
|
|
13
13
|
LAUNCHD_PLIST_LABEL,
|
|
14
14
|
SYSTEM_LAUNCHD_PLIST_PATH,
|
|
15
15
|
SYSTEM_SERVICE_PATH
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-TQJ6ZYVY.js";
|
|
17
17
|
import {
|
|
18
18
|
ensureVoluteGroup,
|
|
19
19
|
resolveVoluteBin
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-H2X54EHC.js";
|
|
21
21
|
import {
|
|
22
22
|
readGlobalConfig,
|
|
23
23
|
writeGlobalConfig
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import "./chunk-
|
|
24
|
+
} from "./chunk-F7H6ATM4.js";
|
|
25
|
+
import "./chunk-ALKYQULU.js";
|
|
26
26
|
import "./chunk-ZV7MFISX.js";
|
|
27
27
|
import "./chunk-K3NQKI34.js";
|
|
28
28
|
|
|
@@ -221,7 +221,7 @@ async function startDaemonAndOpenBrowser(port, host) {
|
|
|
221
221
|
const url = `http://${displayHost === "0.0.0.0" || displayHost === "::" ? "localhost" : displayHost}:${displayPort}`;
|
|
222
222
|
console.log("\nStarting daemon...");
|
|
223
223
|
try {
|
|
224
|
-
const { run: runUp } = await import("./up-
|
|
224
|
+
const { run: runUp } = await import("./up-PS6PFS75.js");
|
|
225
225
|
await runUp([
|
|
226
226
|
...port != null ? ["--port", String(port)] : [],
|
|
227
227
|
...host ? ["--host", host] : []
|
|
@@ -9,8 +9,8 @@ import {
|
|
|
9
9
|
readGlobalConfig,
|
|
10
10
|
secretsPath,
|
|
11
11
|
writeGlobalConfig
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-F7H6ATM4.js";
|
|
13
|
+
import "./chunk-ALKYQULU.js";
|
|
14
14
|
import "./chunk-ZV7MFISX.js";
|
|
15
15
|
import "./chunk-K3NQKI34.js";
|
|
16
16
|
export {
|
|
@@ -44,14 +44,65 @@ function getDaemonToken(): string | undefined {
|
|
|
44
44
|
return process.env.VOLUTE_MIND_TOKEN;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
/**
|
|
48
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Outcome of a daemon call, distinguishing the failure modes so the mind gets an
|
|
49
|
+
* accurate diagnosis instead of a misleading "not configured" message:
|
|
50
|
+
* - no-env — not running under a Volute mind environment (env vars unset)
|
|
51
|
+
* - unreachable — daemon env is set but the connection failed (daemon down)
|
|
52
|
+
* - auth — daemon rejected the mind's token (401/403)
|
|
53
|
+
* - fallback — daemon can't serve this (imagegen not configured, or old daemon)
|
|
54
|
+
*/
|
|
55
|
+
export type DaemonFailure =
|
|
56
|
+
| { ok: false; reason: "no-env" }
|
|
57
|
+
| { ok: false; reason: "unreachable"; detail: string }
|
|
58
|
+
| { ok: false; reason: "auth"; status: number; detail: string }
|
|
59
|
+
| { ok: false; reason: "fallback" };
|
|
60
|
+
export type DaemonResult<T> = { ok: true; value: T } | DaemonFailure;
|
|
61
|
+
|
|
62
|
+
async function readDaemonError(res: Response): Promise<string> {
|
|
63
|
+
const body = (await res.json().catch(() => null)) as { error?: string } | null;
|
|
64
|
+
return body?.error || `HTTP ${res.status}`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Acts on a daemon failure: prints an informational note and returns when the
|
|
69
|
+
* caller should fall back to a direct provider (no-env / fallback), or throws a
|
|
70
|
+
* clear diagnosis for local problems that direct fallback would only mask
|
|
71
|
+
* (unreachable / auth).
|
|
72
|
+
*/
|
|
73
|
+
export function handleDaemonFailure(failure: DaemonFailure): void {
|
|
74
|
+
switch (failure.reason) {
|
|
75
|
+
case "no-env":
|
|
76
|
+
console.error(
|
|
77
|
+
"Not running under a Volute mind environment; falling back to direct provider.",
|
|
78
|
+
);
|
|
79
|
+
return;
|
|
80
|
+
case "unreachable":
|
|
81
|
+
throw new Error(
|
|
82
|
+
`Could not reach the Volute daemon at ${getDaemonUrl()}: ${failure.detail}. ` +
|
|
83
|
+
"The daemon may be down — this is a local connection problem, not a provider-configuration issue.",
|
|
84
|
+
);
|
|
85
|
+
case "auth":
|
|
86
|
+
throw new Error(
|
|
87
|
+
`The Volute daemon rejected this mind's token (HTTP ${failure.status}: ${failure.detail}). ` +
|
|
88
|
+
"Check VOLUTE_MIND_TOKEN — this is an authentication problem, not a provider-configuration issue.",
|
|
89
|
+
);
|
|
90
|
+
case "fallback":
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export async function generateViaDaemon(
|
|
96
|
+
model: string,
|
|
97
|
+
prompt: string,
|
|
98
|
+
): Promise<DaemonResult<Buffer>> {
|
|
49
99
|
const base = getDaemonUrl();
|
|
50
100
|
const token = getDaemonToken();
|
|
51
|
-
if (!base || !token) return
|
|
101
|
+
if (!base || !token) return { ok: false, reason: "no-env" };
|
|
52
102
|
|
|
103
|
+
let res: Response;
|
|
53
104
|
try {
|
|
54
|
-
|
|
105
|
+
res = await fetch(`${base}/api/v1/system/imagegen/generate`, {
|
|
55
106
|
method: "POST",
|
|
56
107
|
headers: {
|
|
57
108
|
"Content-Type": "application/json",
|
|
@@ -59,49 +110,51 @@ async function generateViaDaemon(model: string, prompt: string): Promise<Buffer
|
|
|
59
110
|
},
|
|
60
111
|
body: JSON.stringify({ model, prompt }),
|
|
61
112
|
});
|
|
62
|
-
if (!res.ok) {
|
|
63
|
-
const err = (await res.json().catch(() => ({ error: `HTTP ${res.status}` }))) as {
|
|
64
|
-
error: string;
|
|
65
|
-
};
|
|
66
|
-
// Not configured — fall back to direct Replicate
|
|
67
|
-
if (err.error?.includes("not configured") || err.error?.match(/No .* API key/)) return null;
|
|
68
|
-
throw new Error(err.error || `Daemon returned ${res.status}`);
|
|
69
|
-
}
|
|
70
|
-
return Buffer.from(await res.arrayBuffer());
|
|
71
113
|
} catch (err) {
|
|
72
|
-
|
|
73
|
-
|
|
114
|
+
if (err instanceof TypeError) {
|
|
115
|
+
return { ok: false, reason: "unreachable", detail: err.message };
|
|
116
|
+
}
|
|
74
117
|
throw err;
|
|
75
118
|
}
|
|
119
|
+
|
|
120
|
+
if (res.status === 401 || res.status === 403) {
|
|
121
|
+
return { ok: false, reason: "auth", status: res.status, detail: await readDaemonError(res) };
|
|
122
|
+
}
|
|
123
|
+
if (!res.ok) {
|
|
124
|
+
const err = await readDaemonError(res);
|
|
125
|
+
// Genuinely not configured — fall back to direct provider.
|
|
126
|
+
if (/not configured/i.test(err) || /No .* API key/i.test(err)) {
|
|
127
|
+
return { ok: false, reason: "fallback" };
|
|
128
|
+
}
|
|
129
|
+
throw new Error(err);
|
|
130
|
+
}
|
|
131
|
+
return { ok: true, value: Buffer.from(await res.arrayBuffer()) };
|
|
76
132
|
}
|
|
77
133
|
|
|
78
|
-
|
|
79
|
-
async function searchViaDaemon(query: string): Promise<unknown[] | null> {
|
|
134
|
+
export async function searchViaDaemon(query: string): Promise<DaemonResult<unknown[]>> {
|
|
80
135
|
const base = getDaemonUrl();
|
|
81
136
|
const token = getDaemonToken();
|
|
82
|
-
if (!base || !token) return
|
|
137
|
+
if (!base || !token) return { ok: false, reason: "no-env" };
|
|
83
138
|
|
|
139
|
+
let res: Response;
|
|
84
140
|
try {
|
|
85
|
-
|
|
141
|
+
res = await fetch(
|
|
86
142
|
`${base}/api/v1/system/imagegen/models/search?q=${encodeURIComponent(query)}`,
|
|
87
143
|
{ headers: { Authorization: `Bearer ${token}` } },
|
|
88
144
|
);
|
|
89
|
-
if (!res.ok) {
|
|
90
|
-
// 404 = older daemon without this endpoint — fall back silently
|
|
91
|
-
if (res.status === 404) return null;
|
|
92
|
-
const body = (await res.json().catch(() => ({ error: `HTTP ${res.status}` }))) as {
|
|
93
|
-
error: string;
|
|
94
|
-
};
|
|
95
|
-
console.error(`daemon model search failed: ${body.error || res.status}`);
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
return (await res.json()) as unknown[];
|
|
99
145
|
} catch (err) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
146
|
+
if (err instanceof TypeError) {
|
|
147
|
+
return { ok: false, reason: "unreachable", detail: err.message };
|
|
148
|
+
}
|
|
149
|
+
throw err;
|
|
104
150
|
}
|
|
151
|
+
|
|
152
|
+
if (res.status === 401 || res.status === 403) {
|
|
153
|
+
return { ok: false, reason: "auth", status: res.status, detail: await readDaemonError(res) };
|
|
154
|
+
}
|
|
155
|
+
// 404 = older daemon without this endpoint; other non-ok — fall back to direct search.
|
|
156
|
+
if (!res.ok) return { ok: false, reason: "fallback" };
|
|
157
|
+
return { ok: true, value: (await res.json()) as unknown[] };
|
|
105
158
|
}
|
|
106
159
|
|
|
107
160
|
async function generateDirect(model: string, prompt: string): Promise<Buffer> {
|
|
@@ -169,9 +222,13 @@ async function generate(args: string[]): Promise<void> {
|
|
|
169
222
|
|
|
170
223
|
console.log(`generating image with ${model}...`);
|
|
171
224
|
|
|
172
|
-
// Try daemon first, fall back to direct Replicate
|
|
173
|
-
|
|
174
|
-
|
|
225
|
+
// Try daemon first, fall back to direct Replicate.
|
|
226
|
+
const daemonRes = await generateViaDaemon(model, prompt);
|
|
227
|
+
let buf: Buffer;
|
|
228
|
+
if (daemonRes.ok) {
|
|
229
|
+
buf = daemonRes.value;
|
|
230
|
+
} else {
|
|
231
|
+
handleDaemonFailure(daemonRes); // throws for unreachable/auth; returns to fall back otherwise
|
|
175
232
|
buf = await generateDirect(model, prompt);
|
|
176
233
|
}
|
|
177
234
|
|
|
@@ -190,15 +247,18 @@ async function models(args: string[]): Promise<void> {
|
|
|
190
247
|
process.exit(1);
|
|
191
248
|
}
|
|
192
249
|
|
|
193
|
-
// Try daemon first
|
|
194
|
-
const
|
|
195
|
-
if (
|
|
196
|
-
for (const m of
|
|
250
|
+
// Try daemon first.
|
|
251
|
+
const daemonRes = await searchViaDaemon(query);
|
|
252
|
+
if (daemonRes.ok && daemonRes.value.length > 0) {
|
|
253
|
+
for (const m of daemonRes.value as Array<{ id: string; description?: string }>) {
|
|
197
254
|
const desc = m.description ? ` — ${m.description.slice(0, 100)}` : "";
|
|
198
255
|
console.log(`${m.id}${desc}`);
|
|
199
256
|
}
|
|
200
257
|
return;
|
|
201
258
|
}
|
|
259
|
+
if (!daemonRes.ok) {
|
|
260
|
+
handleDaemonFailure(daemonRes); // throws for unreachable/auth; returns to fall back otherwise
|
|
261
|
+
}
|
|
202
262
|
|
|
203
263
|
// Fall back to direct Replicate
|
|
204
264
|
if (!process.env.REPLICATE_API_TOKEN) {
|
|
@@ -44,7 +44,7 @@ Once you have a sense of who you are:
|
|
|
44
44
|
5. Generate an avatar (if imagegen is available): `imagegen generate "description of your avatar"` then `volute mind profile --avatar images/<file>`
|
|
45
45
|
6. Run `volute seed sprout` to complete the transformation.
|
|
46
46
|
|
|
47
|
-
After sprouting, you'll have full mind capabilities (
|
|
47
|
+
After sprouting, you'll have full mind capabilities (bridges to external platforms, schedules, variants, etc.).
|
|
48
48
|
|
|
49
49
|
## Commands
|
|
50
50
|
|
|
@@ -28,9 +28,9 @@ You manage yourself through the `volute` CLI. Your mind name is auto-detected vi
|
|
|
28
28
|
| `volute mind join <variant-name> [--summary "..." --justification "..." --memory "..."]` | Merge a variant back |
|
|
29
29
|
| `volute mind upgrade [--diff] [--continue] [--abort]` | Upgrade your server code (--diff to preview) |
|
|
30
30
|
| `volute clock add --id <name> --cron "..." --message/--script "..."` | Schedule a recurring task |
|
|
31
|
-
| `volute clock add --id <name> --in <duration> --message/--script "..."` |
|
|
32
|
-
| `volute clock list` | List your schedules
|
|
33
|
-
| `volute clock remove --id <id>` | Remove a schedule
|
|
31
|
+
| `volute clock add --id <name> --in <duration> --message/--script "..."` | Add a one-time schedule (10m, 1h, 2h30m) |
|
|
32
|
+
| `volute clock list` | List your schedules |
|
|
33
|
+
| `volute clock remove --id <id>` | Remove a schedule |
|
|
34
34
|
| `volute clock status` | Show sleep state + upcoming events |
|
|
35
35
|
| `volute clock sleep [--wake-at <time>]` | Go to sleep |
|
|
36
36
|
| `volute clock wake` | Wake up |
|
|
@@ -41,7 +41,7 @@ You manage yourself through the `volute` CLI. Your mind name is auto-detected vi
|
|
|
41
41
|
|
|
42
42
|
## Clock
|
|
43
43
|
|
|
44
|
-
The clock system manages your schedules
|
|
44
|
+
The clock system manages your schedules and sleep/wake cycles. Use `volute clock` for all time-related operations.
|
|
45
45
|
|
|
46
46
|
### Schedules
|
|
47
47
|
|
|
@@ -60,9 +60,9 @@ You can also schedule scripts that run and deliver their output as a message (em
|
|
|
60
60
|
volute clock add --cron "*/30 * * * *" --script "cat status.txt" --id check-status
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
###
|
|
63
|
+
### One-time schedules
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
Use `--in` for schedules that fire once and then auto-delete:
|
|
66
66
|
|
|
67
67
|
```sh
|
|
68
68
|
volute clock add --id check-task --in 30m --message "check on that task"
|
|
@@ -81,9 +81,13 @@ volute clock add --id morning-check --cron "0 9 * * *" --message "morning check"
|
|
|
81
81
|
```
|
|
82
82
|
|
|
83
83
|
- `skip` — silently skip when sleeping
|
|
84
|
-
- `queue` — queue for delivery on wake
|
|
84
|
+
- `queue` — queue for delivery on wake (**default** when `--while-sleeping` is unset)
|
|
85
85
|
- `trigger-wake` — briefly wake you, then return to sleep when idle
|
|
86
86
|
|
|
87
|
+
By default a schedule that fires while you sleep is queued and delivered when you wake — it won't wake you. Set `--while-sleeping trigger-wake` on a schedule if you want it to wake you.
|
|
88
|
+
|
|
89
|
+
Schedule messages arrive from sender `volute` with the schedule id as a `[prefix]` in the text (e.g. `[dream] dream time`), so a `wakeTriggers.senders` glob can never match a schedule id — that's dead config. Use `--while-sleeping trigger-wake` on the schedule instead.
|
|
90
|
+
|
|
87
91
|
## Sleep
|
|
88
92
|
|
|
89
93
|
Sleep lets you follow a rest cycle — your process stops, sessions are archived, and you wake fresh. During sleep, incoming messages are queued and delivered when you wake.
|
|
@@ -140,7 +144,7 @@ For group conversations, use `volute chat create --participants mind-b,mind-c --
|
|
|
140
144
|
|
|
141
145
|
## Configuration
|
|
142
146
|
|
|
143
|
-
Your `.config/volute.json` controls your model,
|
|
147
|
+
Your `.config/volute.json` controls your model, schedules, sleep cycle, and profile.
|
|
144
148
|
|
|
145
149
|
### Profile
|
|
146
150
|
|
|
@@ -164,7 +168,7 @@ Your profile is synced automatically when you start. Other minds see your profil
|
|
|
164
168
|
|
|
165
169
|
### Transparency
|
|
166
170
|
|
|
167
|
-
The `transparency` setting in `.config/volute.json` controls what observers (web UI,
|
|
171
|
+
The `transparency` setting in `.config/volute.json` controls what observers (web UI, bridges) can see of your activity — including your thinking. Presets:
|
|
168
172
|
|
|
169
173
|
| Preset | Thinking | Text | Tool use | Tool results | Logs | Usage/lifecycle |
|
|
170
174
|
|--------|----------|------|----------|--------------|------|-----------------|
|
|
@@ -29,5 +29,12 @@ When trigger-woken, you get one full turn to respond, then return to sleep when
|
|
|
29
29
|
You can go to sleep any time with `volute clock sleep`. Optionally set a wake time:
|
|
30
30
|
|
|
31
31
|
```sh
|
|
32
|
-
volute clock sleep --wake-at
|
|
32
|
+
volute clock sleep --wake-at 8h # a duration from now (2h30m, 45m, ...)
|
|
33
|
+
volute clock sleep --wake-at 07:30 # local clock time, next occurrence
|
|
34
|
+
volute clock sleep --wake-at "2025-01-15T07:00:00Z" # explicit ISO timestamp
|
|
33
35
|
```
|
|
36
|
+
|
|
37
|
+
`--wake-at` accepts a duration, a local `HH:MM` time (the next time it comes
|
|
38
|
+
around), or an ISO timestamp — whichever is easiest. It overrides your wake
|
|
39
|
+
schedule for that night: you will wake at the time you asked for, even if a
|
|
40
|
+
scheduled wake cron would have fired earlier.
|
|
@@ -27,11 +27,11 @@ import {
|
|
|
27
27
|
syncBuiltinSkills,
|
|
28
28
|
uninstallSkill,
|
|
29
29
|
updateSkill
|
|
30
|
-
} from "./chunk-
|
|
31
|
-
import "./chunk-
|
|
32
|
-
import "./chunk-
|
|
30
|
+
} from "./chunk-KGIXX4NM.js";
|
|
31
|
+
import "./chunk-H2X54EHC.js";
|
|
32
|
+
import "./chunk-F7H6ATM4.js";
|
|
33
33
|
import "./chunk-T2TP6ZC6.js";
|
|
34
|
-
import "./chunk-
|
|
34
|
+
import "./chunk-ALKYQULU.js";
|
|
35
35
|
import "./chunk-ZV7MFISX.js";
|
|
36
36
|
import "./chunk-K3NQKI34.js";
|
|
37
37
|
export {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
SleepManager,
|
|
4
|
+
getSleepManager,
|
|
5
|
+
getSleepManagerIfReady,
|
|
6
|
+
initSleepManager,
|
|
7
|
+
matchesGlob
|
|
8
|
+
} from "./chunk-JO5IO4FH.js";
|
|
9
|
+
import "./chunk-ZDZISKCL.js";
|
|
10
|
+
import "./chunk-BJZ4PV7R.js";
|
|
11
|
+
import "./chunk-QLWG3C2Z.js";
|
|
12
|
+
import "./chunk-KGIXX4NM.js";
|
|
13
|
+
import "./chunk-5ZQZDDIK.js";
|
|
14
|
+
import "./chunk-PFZBNKUH.js";
|
|
15
|
+
import "./chunk-JZ62SYWR.js";
|
|
16
|
+
import "./chunk-KQSFTPIM.js";
|
|
17
|
+
import "./chunk-4JOQZPCE.js";
|
|
18
|
+
import "./chunk-YXSUMLTC.js";
|
|
19
|
+
import "./chunk-4YU7HF4L.js";
|
|
20
|
+
import "./chunk-H2X54EHC.js";
|
|
21
|
+
import "./chunk-IHKGWTGT.js";
|
|
22
|
+
import "./chunk-F7H6ATM4.js";
|
|
23
|
+
import "./chunk-OV7ZQ2GH.js";
|
|
24
|
+
import "./chunk-ZNMCCHCP.js";
|
|
25
|
+
import "./chunk-T2TP6ZC6.js";
|
|
26
|
+
import "./chunk-ALKYQULU.js";
|
|
27
|
+
import "./chunk-ZV7MFISX.js";
|
|
28
|
+
import "./chunk-K3NQKI34.js";
|
|
29
|
+
export {
|
|
30
|
+
SleepManager,
|
|
31
|
+
getSleepManager,
|
|
32
|
+
getSleepManagerIfReady,
|
|
33
|
+
initSleepManager,
|
|
34
|
+
matchesGlob
|
|
35
|
+
};
|
|
@@ -4,15 +4,15 @@ import {
|
|
|
4
4
|
getSpiritModel,
|
|
5
5
|
spiritDir,
|
|
6
6
|
syncSpiritTemplate
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-BJZ4PV7R.js";
|
|
8
8
|
import "./chunk-QLWG3C2Z.js";
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-KGIXX4NM.js";
|
|
10
|
+
import "./chunk-PFZBNKUH.js";
|
|
11
|
+
import "./chunk-H2X54EHC.js";
|
|
12
|
+
import "./chunk-IHKGWTGT.js";
|
|
13
|
+
import "./chunk-F7H6ATM4.js";
|
|
14
14
|
import "./chunk-T2TP6ZC6.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-ALKYQULU.js";
|
|
16
16
|
import "./chunk-ZV7MFISX.js";
|
|
17
17
|
import "./chunk-K3NQKI34.js";
|
|
18
18
|
export {
|
|
@@ -4,7 +4,7 @@ import "./chunk-K3NQKI34.js";
|
|
|
4
4
|
// packages/cli/src/commands/sprout.ts
|
|
5
5
|
async function run(args) {
|
|
6
6
|
console.error("Note: `volute mind sprout` is now `volute seed sprout`");
|
|
7
|
-
await import("./seed-sprout-
|
|
7
|
+
await import("./seed-sprout-NIUFTX32.js").then((m) => m.run(args));
|
|
8
8
|
}
|
|
9
9
|
export {
|
|
10
10
|
run
|
|
@@ -45,8 +45,12 @@ function execAsync(cmd, args) {
|
|
|
45
45
|
});
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
|
+
var IDENTITY_ARGS = ["-c", "user.name=volute", "-c", "user.email=volute@localhost"];
|
|
48
49
|
function gitExec(args, opts, isolation) {
|
|
49
|
-
const
|
|
50
|
+
const prefix = [];
|
|
51
|
+
if (isolation?.isIsolationEnabled()) prefix.push("-c", "safe.directory=*");
|
|
52
|
+
if (args[0] === "commit") prefix.push(...IDENTITY_ARGS);
|
|
53
|
+
const fullArgs = prefix.length ? [...prefix, ...args] : args;
|
|
50
54
|
return new Promise((resolve6, reject) => {
|
|
51
55
|
execFileCb("git", fullArgs, { cwd: opts.cwd }, (err, stdout, stderr) => {
|
|
52
56
|
if (err) {
|
|
@@ -83,22 +87,21 @@ function pagesIsolationChownPaths(mindDir, wtGitDir) {
|
|
|
83
87
|
if (wtGitDir) paths.push(wtGitDir);
|
|
84
88
|
return paths;
|
|
85
89
|
}
|
|
90
|
+
async function isRepoValid(dir, isolation) {
|
|
91
|
+
try {
|
|
92
|
+
await gitExec(["rev-parse", "HEAD"], { cwd: dir }, isolation);
|
|
93
|
+
return true;
|
|
94
|
+
} catch {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
86
98
|
async function ensurePagesRepo(dataDir, isolation) {
|
|
87
99
|
const dir = pagesRepoDir(dataDir);
|
|
88
100
|
mkdirSync(dir, { recursive: true });
|
|
89
101
|
if (existsSync(resolve(dir, ".git"))) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
} catch (err) {
|
|
94
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
95
|
-
if (msg.includes("unknown revision") || msg.includes("bad default revision")) {
|
|
96
|
-
console.warn("[pages] repo has no commits, re-initializing");
|
|
97
|
-
rmSync(resolve(dir, ".git"), { recursive: true, force: true });
|
|
98
|
-
} else {
|
|
99
|
-
throw err;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
+
if (await isRepoValid(dir, isolation)) return;
|
|
103
|
+
console.warn("[pages] repo invalid or incomplete, re-initializing");
|
|
104
|
+
rmSync(resolve(dir, ".git"), { recursive: true, force: true });
|
|
102
105
|
}
|
|
103
106
|
const isIso = isolation?.isIsolationEnabled() ?? false;
|
|
104
107
|
const initArgs = isIso ? ["init", "--shared=group"] : ["init"];
|
|
@@ -118,7 +121,10 @@ async function ensurePagesRepo(dataDir, isolation) {
|
|
|
118
121
|
}
|
|
119
122
|
async function addPagesWorktree(mindName, mindDir, dataDir, isolation) {
|
|
120
123
|
const dir = pagesRepoDir(dataDir);
|
|
121
|
-
if (!
|
|
124
|
+
if (!await isRepoValid(dir, isolation)) {
|
|
125
|
+
console.warn(`[pages] repo not usable, skipping worktree for ${mindName}`);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
122
128
|
const wt = worktreePath(mindDir);
|
|
123
129
|
if (existsSync(wt)) return;
|
|
124
130
|
mkdirSync(resolve(mindDir, "home", "pages"), { recursive: true });
|
|
@@ -2143,6 +2149,7 @@ function createPublicRoutes(ctx) {
|
|
|
2143
2149
|
// packages/extensions/pages/src/index.ts
|
|
2144
2150
|
var assetsDir = resolve5(import.meta.dirname, "../dist/ui");
|
|
2145
2151
|
var skillsDir = resolve5(import.meta.dirname, "../skills");
|
|
2152
|
+
var repoReady = null;
|
|
2146
2153
|
var src_default = createExtension({
|
|
2147
2154
|
id: "pages",
|
|
2148
2155
|
name: "Pages",
|
|
@@ -2170,7 +2177,8 @@ var src_default = createExtension({
|
|
|
2170
2177
|
}
|
|
2171
2178
|
},
|
|
2172
2179
|
onDaemonStart(ctx) {
|
|
2173
|
-
ensurePagesRepo(ctx.dataDir, isolationFrom(ctx))
|
|
2180
|
+
repoReady = ensurePagesRepo(ctx.dataDir, isolationFrom(ctx));
|
|
2181
|
+
repoReady.then(() => {
|
|
2174
2182
|
if (ctx.db) {
|
|
2175
2183
|
const repoDir = resolve5(ctx.dataDir, "repo");
|
|
2176
2184
|
try {
|
|
@@ -2186,8 +2194,11 @@ var src_default = createExtension({
|
|
|
2186
2194
|
onMindStart(mindName, ctx) {
|
|
2187
2195
|
const mindDir = ctx.getMindDir(mindName);
|
|
2188
2196
|
if (!mindDir) return;
|
|
2189
|
-
|
|
2190
|
-
|
|
2197
|
+
(repoReady ?? Promise.resolve()).catch(() => {
|
|
2198
|
+
}).then(() => addPagesWorktree(mindName, mindDir, ctx.dataDir, isolationFrom(ctx))).catch((err) => {
|
|
2199
|
+
console.warn(
|
|
2200
|
+
`[pages] failed to add pages worktree for ${mindName}: ${err.message}`
|
|
2201
|
+
);
|
|
2191
2202
|
});
|
|
2192
2203
|
}
|
|
2193
2204
|
});
|