volute 0.23.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/{activity-events-3WHHCOBB.js → activity-events-4O37J7PD.js} +2 -2
- package/dist/api.d.ts +419 -19
- package/dist/{channel-BOOMFULW.js → channel-HZOSHGNF.js} +1 -1
- package/dist/{chunk-QIXPN3OO.js → chunk-2767L2RZ.js} +5 -5
- package/dist/{chunk-SGPEZ32F.js → chunk-33XAVCS4.js} +16 -0
- package/dist/{chunk-VT5QODNE.js → chunk-3AIBT4TW.js} +4 -3
- package/dist/{chunk-A4S7H6G6.js → chunk-BFK6SOEJ.js} +1 -1
- package/dist/{chunk-RK627D57.js → chunk-BOTQ25QT.js} +3 -3
- package/dist/{chunk-TFS25FIM.js → chunk-DG7TO7EE.js} +31 -3
- package/dist/{chunk-HGCDWKSP.js → chunk-E7GOKNOT.js} +1 -1
- package/dist/{chunk-ISWZ6QUK.js → chunk-PMX4EIJK.js} +804 -115
- package/dist/{chunk-M5CNKH4J.js → chunk-SHSWYG2J.js} +7 -7
- package/dist/{chunk-XLC342FO.js → chunk-SIAG3QMM.js} +14 -1
- package/dist/{chunk-KFI7TQJ6.js → chunk-TRQEV3CD.js} +9 -5
- package/dist/{chunk-JG4CCJOA.js → chunk-ZSH4G2P5.js} +33 -15
- package/dist/cli.js +18 -18
- package/dist/{cloud-sync-PI47U2LT.js → cloud-sync-PPBBJDY6.js} +7 -9
- package/dist/{connector-PYT5UOTZ.js → connector-M6XFI6GM.js} +1 -1
- package/dist/{create-WIDA3M4C.js → create-VDQJER52.js} +1 -1
- package/dist/{daemon-client-ZHCDL4RS.js → daemon-client-JOVQZ52X.js} +1 -1
- package/dist/{daemon-restart-RMGOOGPE.js → daemon-restart-FDNOZEAD.js} +5 -5
- package/dist/daemon.js +1047 -981
- package/dist/{delete-LOIANQGD.js → delete-2MRR4JX5.js} +1 -1
- package/dist/{down-WSUASL5E.js → down-674SX2IZ.js} +2 -2
- package/dist/{env-4PHIHTF4.js → env-2FPOZK37.js} +1 -1
- package/dist/{export-XD6PJBQP.js → export-IKFAPRAO.js} +1 -1
- package/dist/{file-X4L5TTOL.js → file-KT3UIQM3.js} +1 -1
- package/dist/{history-HTEKRNID.js → history-46WZN5CN.js} +1 -1
- package/dist/{import-EAXTHHXL.js → import-TH26J76F.js} +2 -2
- package/dist/{log-SRO5Q6AD.js → log-6SGSSR3D.js} +1 -1
- package/dist/{logs-HNTNNBDW.js → logs-HRBONI5I.js} +1 -1
- package/dist/{merge-B6SYTGI7.js → merge-KSFJKX6T.js} +1 -1
- package/dist/{message-delivery-FHV4NO2F.js → message-delivery-XMGV3FUM.js} +6 -6
- package/dist/{mind-BTXR5B3C.js → mind-YVWAHL2A.js} +17 -17
- package/dist/{mind-activity-tracker-PGC3DBJ7.js → mind-activity-tracker-NMDDEV3K.js} +3 -3
- package/dist/{mind-manager-KMY4GA2J.js → mind-manager-4NDNAYAB.js} +2 -2
- package/dist/{mind-sleep-FWRBIFBS.js → mind-sleep-GHPTSAYN.js} +1 -1
- package/dist/{mind-wake-LJK2YU5X.js → mind-wake-BJDJFMDF.js} +1 -1
- package/dist/{package-CUBJ4PKS.js → package-3HF5MXU2.js} +2 -1
- package/dist/{pages-YSTRWJR4.js → pages-Y6DRWUOJ.js} +1 -1
- package/dist/{publish-BZNHKUUK.js → publish-EEKTZBHW.js} +1 -1
- package/dist/{pull-GRQAXM2E.js → pull-D32SPFVU.js} +1 -1
- package/dist/{restart-CIDAKGG2.js → restart-5BMNV7KU.js} +1 -1
- package/dist/{schedule-NLR3LZLY.js → schedule-YEFDLVMJ.js} +1 -1
- package/dist/{seed-3H2MRREW.js → seed-6FEKB3YC.js} +1 -1
- package/dist/{send-RP2TA7SG.js → send-IISDYFCL.js} +1 -1
- package/dist/{service-7BFXDI6J.js → service-FASYWLTC.js} +3 -3
- package/dist/{setup-SSIIXQMI.js → setup-BMLM2UTK.js} +1 -1
- package/dist/{shared-2OGT3NSL.js → shared-LWMNTTZN.js} +4 -4
- package/dist/{skill-Q2Y6PQ3L.js → skill-T3EMR6IR.js} +11 -3
- package/dist/skills/imagegen/SKILL.md +37 -0
- package/dist/skills/imagegen/references/INSTALL.md +13 -0
- package/dist/skills/imagegen/scripts/imagegen.ts +136 -0
- package/dist/skills/resonance/SKILL.md +73 -0
- package/dist/skills/resonance/assets/default-config.json +21 -0
- package/dist/skills/resonance/references/INSTALL.md +23 -0
- package/dist/skills/resonance/scripts/resonance.ts +1250 -0
- package/dist/skills/volute-mind/SKILL.md +94 -4
- package/dist/{sleep-manager-2TMQ65E4.js → sleep-manager-RKTFZPD3.js} +6 -6
- package/dist/{sprout-UKCYBGHK.js → sprout-QJVGJDSH.js} +3 -3
- package/dist/{start-JR6CUUWF.js → start-C7XITZ5O.js} +1 -1
- package/dist/{status-5XDGYHKP.js → status-LYS4NUOZ.js} +1 -1
- package/dist/{status-H2MKDN6L.js → status-SIRPLEZC.js} +4 -3
- package/dist/{stop-VKPGK25U.js → stop-CVKBSLXY.js} +1 -1
- package/dist/tailscale-AJ4VL5XK.js +49 -0
- package/dist/{up-Z5JRG2M2.js → up-CJ26KQLN.js} +2 -2
- package/dist/{update-ELC6MEUT.js → update-7XCZMYBT.js} +7 -7
- package/dist/{upgrade-GXW2EQY3.js → upgrade-7RUIXGOO.js} +1 -1
- package/dist/{variant-A4I7PHXS.js → variant-UGREB4G5.js} +4 -4
- package/dist/{version-notify-LKABEJSA.js → version-notify-AZQMC32A.js} +6 -6
- package/dist/web-assets/assets/index-CGPSVu19.js +69 -0
- package/dist/web-assets/assets/index-V_rNDsM8.css +1 -0
- package/dist/web-assets/favicon.png +0 -0
- package/dist/web-assets/index.html +5 -4
- package/dist/web-assets/logo.png +0 -0
- package/drizzle/0013_user_profiles.sql +3 -0
- package/drizzle/0014_conversation_reads.sql +7 -0
- package/drizzle/meta/0013_snapshot.json +7 -0
- package/drizzle/meta/_journal.json +14 -0
- package/package.json +2 -1
- package/templates/_base/home/public/.gitkeep +0 -0
- package/templates/_base/src/lib/format-prefix.ts +18 -2
- package/templates/_base/src/lib/routing.ts +2 -1
- package/templates/_base/src/lib/types.ts +8 -0
- package/dist/chunk-G5KRTU2F.js +0 -76
- package/dist/web-assets/assets/index-CZ26vsyY.js +0 -69
- package/dist/web-assets/assets/index-DyyAvJwW.css +0 -1
|
@@ -13,7 +13,7 @@ async function run(args) {
|
|
|
13
13
|
force: { type: "boolean" }
|
|
14
14
|
});
|
|
15
15
|
const name = resolveMindName({ mind: positional[0] });
|
|
16
|
-
const { daemonFetch } = await import("./daemon-client-
|
|
16
|
+
const { daemonFetch } = await import("./daemon-client-JOVQZ52X.js");
|
|
17
17
|
const { getClient, urlOf } = await import("./api-client-YPKOZP2O.js");
|
|
18
18
|
const client = getClient();
|
|
19
19
|
const url = urlOf(client.api.minds[":name"].$url({ param: { name } })) + (flags.force ? "?force=true" : "");
|
|
@@ -63,7 +63,7 @@ async function run(args) {
|
|
|
63
63
|
});
|
|
64
64
|
if (includeHistory) {
|
|
65
65
|
try {
|
|
66
|
-
const { daemonFetch } = await import("./daemon-client-
|
|
66
|
+
const { daemonFetch } = await import("./daemon-client-JOVQZ52X.js");
|
|
67
67
|
const { getClient, urlOf } = await import("./api-client-YPKOZP2O.js");
|
|
68
68
|
const client = getClient();
|
|
69
69
|
const res = await daemonFetch(
|
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
parseNameFromIdentity,
|
|
7
7
|
run,
|
|
8
8
|
sessionMatchesWorkspace
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-BOTQ25QT.js";
|
|
10
|
+
import "./chunk-SIAG3QMM.js";
|
|
11
11
|
import "./chunk-PHU4DEAJ.js";
|
|
12
12
|
import "./chunk-D424ZQGI.js";
|
|
13
13
|
import "./chunk-B2CPS4QU.js";
|
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
deliverMessage,
|
|
4
4
|
extractTextContent,
|
|
5
5
|
recordInbound
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-PMX4EIJK.js";
|
|
7
7
|
import "./chunk-HFCBO2GL.js";
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-E7GOKNOT.js";
|
|
9
|
+
import "./chunk-BFK6SOEJ.js";
|
|
10
|
+
import "./chunk-SHSWYG2J.js";
|
|
11
|
+
import "./chunk-SIAG3QMM.js";
|
|
12
12
|
import "./chunk-PHU4DEAJ.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-33XAVCS4.js";
|
|
14
14
|
import "./chunk-YUIHSKR6.js";
|
|
15
15
|
import "./chunk-JTDFJWI2.js";
|
|
16
16
|
import "./chunk-NWPT4ASZ.js";
|
|
@@ -6,63 +6,63 @@ async function run(args) {
|
|
|
6
6
|
const subcommand = args[0];
|
|
7
7
|
switch (subcommand) {
|
|
8
8
|
case "create":
|
|
9
|
-
await import("./create-
|
|
9
|
+
await import("./create-VDQJER52.js").then((m) => m.run(args.slice(1)));
|
|
10
10
|
break;
|
|
11
11
|
case "start":
|
|
12
|
-
await import("./start-
|
|
12
|
+
await import("./start-C7XITZ5O.js").then((m) => m.run(args.slice(1)));
|
|
13
13
|
break;
|
|
14
14
|
case "stop":
|
|
15
|
-
await import("./stop-
|
|
15
|
+
await import("./stop-CVKBSLXY.js").then((m) => m.run(args.slice(1)));
|
|
16
16
|
break;
|
|
17
17
|
case "restart":
|
|
18
|
-
await import("./restart-
|
|
18
|
+
await import("./restart-5BMNV7KU.js").then((m) => m.run(args.slice(1)));
|
|
19
19
|
break;
|
|
20
20
|
case "delete":
|
|
21
|
-
await import("./delete-
|
|
21
|
+
await import("./delete-2MRR4JX5.js").then((m) => m.run(args.slice(1)));
|
|
22
22
|
break;
|
|
23
23
|
case "list":
|
|
24
|
-
await import("./status-
|
|
24
|
+
await import("./status-SIRPLEZC.js").then((m) => m.run(args.slice(1)));
|
|
25
25
|
break;
|
|
26
26
|
case "status": {
|
|
27
27
|
const rest = args.slice(1);
|
|
28
28
|
if (!rest[0] && process.env.VOLUTE_MIND) {
|
|
29
29
|
rest.unshift(process.env.VOLUTE_MIND);
|
|
30
30
|
}
|
|
31
|
-
await import("./status-
|
|
31
|
+
await import("./status-SIRPLEZC.js").then((m) => m.run(rest));
|
|
32
32
|
break;
|
|
33
33
|
}
|
|
34
34
|
case "logs": {
|
|
35
35
|
const rest = args.slice(1);
|
|
36
36
|
const logsArgs = transformMindFlag(rest);
|
|
37
|
-
await import("./logs-
|
|
37
|
+
await import("./logs-HRBONI5I.js").then((m) => m.run(logsArgs));
|
|
38
38
|
break;
|
|
39
39
|
}
|
|
40
40
|
case "upgrade":
|
|
41
|
-
await import("./upgrade-
|
|
41
|
+
await import("./upgrade-7RUIXGOO.js").then((m) => m.run(args.slice(1)));
|
|
42
42
|
break;
|
|
43
43
|
case "import":
|
|
44
|
-
await import("./import-
|
|
44
|
+
await import("./import-TH26J76F.js").then((m) => m.run(args.slice(1)));
|
|
45
45
|
break;
|
|
46
46
|
case "export":
|
|
47
|
-
await import("./export-
|
|
47
|
+
await import("./export-IKFAPRAO.js").then((m) => m.run(args.slice(1)));
|
|
48
48
|
break;
|
|
49
49
|
case "connect":
|
|
50
|
-
await import("./connector-
|
|
50
|
+
await import("./connector-M6XFI6GM.js").then((m) => m.run(["connect", ...args.slice(1)]));
|
|
51
51
|
break;
|
|
52
52
|
case "disconnect":
|
|
53
|
-
await import("./connector-
|
|
53
|
+
await import("./connector-M6XFI6GM.js").then((m) => m.run(["disconnect", ...args.slice(1)]));
|
|
54
54
|
break;
|
|
55
55
|
case "seed":
|
|
56
|
-
await import("./seed-
|
|
56
|
+
await import("./seed-6FEKB3YC.js").then((m) => m.run(args.slice(1)));
|
|
57
57
|
break;
|
|
58
58
|
case "sprout":
|
|
59
|
-
await import("./sprout-
|
|
59
|
+
await import("./sprout-QJVGJDSH.js").then((m) => m.run(args.slice(1)));
|
|
60
60
|
break;
|
|
61
61
|
case "sleep":
|
|
62
|
-
await import("./mind-sleep-
|
|
62
|
+
await import("./mind-sleep-GHPTSAYN.js").then((m) => m.run(args.slice(1)));
|
|
63
63
|
break;
|
|
64
64
|
case "wake":
|
|
65
|
-
await import("./mind-wake-
|
|
65
|
+
await import("./mind-wake-BJDJFMDF.js").then((m) => m.run(args.slice(1)));
|
|
66
66
|
break;
|
|
67
67
|
case "--help":
|
|
68
68
|
case "-h":
|
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
markIdle,
|
|
5
5
|
onMindEvent,
|
|
6
6
|
stopAll
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-E7GOKNOT.js";
|
|
8
|
+
import "./chunk-BFK6SOEJ.js";
|
|
9
|
+
import "./chunk-33XAVCS4.js";
|
|
10
10
|
import "./chunk-YUIHSKR6.js";
|
|
11
11
|
import "./chunk-B2CPS4QU.js";
|
|
12
12
|
import "./chunk-K3NQKI34.js";
|
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
MindManager,
|
|
4
4
|
getMindManager,
|
|
5
5
|
initMindManager
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-SHSWYG2J.js";
|
|
7
7
|
import "./chunk-PHU4DEAJ.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-33XAVCS4.js";
|
|
9
9
|
import "./chunk-YUIHSKR6.js";
|
|
10
10
|
import "./chunk-NWPT4ASZ.js";
|
|
11
11
|
import "./chunk-B2CPS4QU.js";
|
|
@@ -4,7 +4,7 @@ import "./chunk-K3NQKI34.js";
|
|
|
4
4
|
// package.json
|
|
5
5
|
var package_default = {
|
|
6
6
|
name: "volute",
|
|
7
|
-
version: "0.
|
|
7
|
+
version: "0.25.0",
|
|
8
8
|
description: "CLI for creating and managing self-modifying AI minds powered by the Claude Agent SDK",
|
|
9
9
|
type: "module",
|
|
10
10
|
license: "MIT",
|
|
@@ -86,6 +86,7 @@ var package_default = {
|
|
|
86
86
|
dompurify: "^3.3.1",
|
|
87
87
|
"drizzle-kit": "^0.31.8",
|
|
88
88
|
lefthook: "^2.1.0",
|
|
89
|
+
libsql: "^0.5.22",
|
|
89
90
|
marked: "^17.0.1",
|
|
90
91
|
svelte: "^5.53.0",
|
|
91
92
|
tsup: "^8.0.0",
|
|
@@ -6,7 +6,7 @@ async function run(args) {
|
|
|
6
6
|
const subcommand = args[0];
|
|
7
7
|
switch (subcommand) {
|
|
8
8
|
case "publish":
|
|
9
|
-
await import("./publish-
|
|
9
|
+
await import("./publish-EEKTZBHW.js").then((m) => m.run(args.slice(1)));
|
|
10
10
|
break;
|
|
11
11
|
case "status":
|
|
12
12
|
await import("./status-LV34BG6G.js").then((m) => m.run(args.slice(1)));
|
|
@@ -42,7 +42,7 @@ async function run(args) {
|
|
|
42
42
|
pagesDir = resolve(sharedDir(), "pages");
|
|
43
43
|
} else if (flags.mind || process.env.VOLUTE_MIND) {
|
|
44
44
|
mindName = resolveMindName(flags);
|
|
45
|
-
pagesDir = resolve(mindDir(mindName), "home", "pages");
|
|
45
|
+
pagesDir = resolve(mindDir(mindName), "home", "public", "pages");
|
|
46
46
|
} else {
|
|
47
47
|
mindName = "system";
|
|
48
48
|
pagesDir = resolve(sharedDir(), "pages");
|
|
@@ -21,7 +21,7 @@ async function run(args) {
|
|
|
21
21
|
}
|
|
22
22
|
const template = flags.template ?? "claude";
|
|
23
23
|
const skills = flags.skills === "none" ? [] : flags.skills ? flags.skills.split(",") : void 0;
|
|
24
|
-
const { daemonFetch } = await import("./daemon-client-
|
|
24
|
+
const { daemonFetch } = await import("./daemon-client-JOVQZ52X.js");
|
|
25
25
|
const { getClient, urlOf } = await import("./api-client-YPKOZP2O.js");
|
|
26
26
|
const client = getClient();
|
|
27
27
|
const createRes = await daemonFetch(urlOf(client.api.minds.$url()), {
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
LAUNCHD_PLIST_PATH,
|
|
5
5
|
SYSTEM_SERVICE_PATH,
|
|
6
6
|
USER_SYSTEMD_UNIT
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-3AIBT4TW.js";
|
|
8
8
|
import {
|
|
9
9
|
parseArgs
|
|
10
10
|
} from "./chunk-D424ZQGI.js";
|
|
@@ -211,7 +211,7 @@ async function run(args) {
|
|
|
211
211
|
switch (subcommand) {
|
|
212
212
|
case "install":
|
|
213
213
|
if (flags.system) {
|
|
214
|
-
const setup = await import("./setup-
|
|
214
|
+
const setup = await import("./setup-BMLM2UTK.js");
|
|
215
215
|
setup.install(flags.port, flags.host);
|
|
216
216
|
} else {
|
|
217
217
|
await install(flags.port, flags.host);
|
|
@@ -219,7 +219,7 @@ async function run(args) {
|
|
|
219
219
|
break;
|
|
220
220
|
case "uninstall":
|
|
221
221
|
if (flags.system) {
|
|
222
|
-
const setup = await import("./setup-
|
|
222
|
+
const setup = await import("./setup-BMLM2UTK.js");
|
|
223
223
|
setup.uninstall(!!flags.force);
|
|
224
224
|
} else {
|
|
225
225
|
await uninstall();
|
|
@@ -6,16 +6,16 @@ async function run(args) {
|
|
|
6
6
|
const subcommand = args[0];
|
|
7
7
|
switch (subcommand) {
|
|
8
8
|
case "merge":
|
|
9
|
-
await import("./merge-
|
|
9
|
+
await import("./merge-KSFJKX6T.js").then((m) => m.run(args.slice(1)));
|
|
10
10
|
break;
|
|
11
11
|
case "pull":
|
|
12
|
-
await import("./pull-
|
|
12
|
+
await import("./pull-D32SPFVU.js").then((m) => m.run(args.slice(1)));
|
|
13
13
|
break;
|
|
14
14
|
case "log":
|
|
15
|
-
await import("./log-
|
|
15
|
+
await import("./log-6SGSSR3D.js").then((m) => m.run(args.slice(1)));
|
|
16
16
|
break;
|
|
17
17
|
case "status":
|
|
18
|
-
await import("./status-
|
|
18
|
+
await import("./status-LYS4NUOZ.js").then((m) => m.run(args.slice(1)));
|
|
19
19
|
break;
|
|
20
20
|
case "--help":
|
|
21
21
|
case "-h":
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "./chunk-D424ZQGI.js";
|
|
12
12
|
import {
|
|
13
13
|
daemonFetch
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-TRQEV3CD.js";
|
|
15
15
|
import "./chunk-B2CPS4QU.js";
|
|
16
16
|
import "./chunk-K3NQKI34.js";
|
|
17
17
|
|
|
@@ -146,11 +146,19 @@ async function installSkill(args) {
|
|
|
146
146
|
body: JSON.stringify({ skillId })
|
|
147
147
|
});
|
|
148
148
|
if (!res.ok) {
|
|
149
|
-
const
|
|
150
|
-
console.error(`Error: ${
|
|
149
|
+
const body2 = await res.json().catch(() => ({ error: "Unknown error" }));
|
|
150
|
+
console.error(`Error: ${body2.error}`);
|
|
151
151
|
process.exit(1);
|
|
152
152
|
}
|
|
153
|
+
const body = await res.json().catch(() => ({}));
|
|
153
154
|
console.log(`Installed skill "${skillId}" into ${mindName}.`);
|
|
155
|
+
if (body.npmInstalled?.length) {
|
|
156
|
+
console.log(`Installed npm dependencies: ${body.npmInstalled.join(", ")}`);
|
|
157
|
+
}
|
|
158
|
+
if (body.installNotes) {
|
|
159
|
+
console.log("");
|
|
160
|
+
console.log(body.installNotes);
|
|
161
|
+
}
|
|
154
162
|
}
|
|
155
163
|
async function updateSkill(args) {
|
|
156
164
|
const { positional, flags } = parseArgs(args, {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Image Generation
|
|
3
|
+
description: Generate images via the Replicate API. Use for "generate image", "create image", "image generation", "text to image", "search image models".
|
|
4
|
+
metadata:
|
|
5
|
+
npm-dependencies: replicate
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Image Generation
|
|
9
|
+
|
|
10
|
+
Generate images from text prompts using models on Replicate. Images are saved to `home/images/`.
|
|
11
|
+
|
|
12
|
+
## Commands
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx tsx .claude/skills/imagegen/scripts/imagegen.ts <command>
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
| Command | Description |
|
|
19
|
+
|---------|-------------|
|
|
20
|
+
| `generate "prompt" [--model M] [--filename F]` | Generate an image from a text prompt. Default model: `prunaai/z-image-turbo`. |
|
|
21
|
+
| `models "query"` | Search Replicate for text-to-image models. |
|
|
22
|
+
|
|
23
|
+
## Examples
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Generate an image with the default model
|
|
27
|
+
npx tsx .claude/skills/imagegen/scripts/imagegen.ts generate "a sunset over the ocean"
|
|
28
|
+
|
|
29
|
+
# Use a specific model
|
|
30
|
+
npx tsx .claude/skills/imagegen/scripts/imagegen.ts generate "a cat in space" --model black-forest-labs/flux-schnell
|
|
31
|
+
|
|
32
|
+
# Specify a filename
|
|
33
|
+
npx tsx .claude/skills/imagegen/scripts/imagegen.ts generate "mountain landscape" --filename mountains
|
|
34
|
+
|
|
35
|
+
# Search for models
|
|
36
|
+
npx tsx .claude/skills/imagegen/scripts/imagegen.ts models "text to image"
|
|
37
|
+
```
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Image Generation — Post-Install Setup
|
|
2
|
+
|
|
3
|
+
Set your Replicate API token:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
volute env set REPLICATE_API_TOKEN <your-token>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Then generate images:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx tsx .claude/skills/imagegen/scripts/imagegen.ts generate "a sunset over the ocean"
|
|
13
|
+
```
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* imagegen.ts — image generation via Replicate API
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* imagegen generate "prompt" [--model M] [--filename F] # generate an image
|
|
8
|
+
* imagegen models "query" # search for models
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { mkdirSync } from "node:fs";
|
|
12
|
+
import { writeFile } from "node:fs/promises";
|
|
13
|
+
import { createRequire } from "node:module";
|
|
14
|
+
import { join, resolve } from "node:path";
|
|
15
|
+
|
|
16
|
+
const replicateRequire = createRequire(import.meta.url);
|
|
17
|
+
|
|
18
|
+
function getHomePath(): string {
|
|
19
|
+
const mindDir = process.env.VOLUTE_MIND_DIR;
|
|
20
|
+
if (!mindDir) throw new Error("VOLUTE_MIND_DIR not set");
|
|
21
|
+
return join(mindDir, "home");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function slugify(text: string): string {
|
|
25
|
+
return text
|
|
26
|
+
.toLowerCase()
|
|
27
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
28
|
+
.replace(/^-|-$/g, "")
|
|
29
|
+
.slice(0, 60);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function getFlag(args: string[], flag: string): string | undefined {
|
|
33
|
+
const idx = args.indexOf(flag);
|
|
34
|
+
if (idx !== -1 && args[idx + 1]) return args[idx + 1];
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function generate(args: string[]): Promise<void> {
|
|
39
|
+
const prompt = args[0];
|
|
40
|
+
if (!prompt) {
|
|
41
|
+
console.log('Usage: imagegen generate "prompt" [--model M] [--filename F]');
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!process.env.REPLICATE_API_TOKEN) {
|
|
46
|
+
console.error(
|
|
47
|
+
"REPLICATE_API_TOKEN not set. Run: volute env set REPLICATE_API_TOKEN <your-token>",
|
|
48
|
+
);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const model = getFlag(args, "--model") || "prunaai/z-image-turbo";
|
|
53
|
+
const filename = getFlag(args, "--filename") || slugify(prompt) || `image-${Date.now()}`;
|
|
54
|
+
|
|
55
|
+
const Replicate = replicateRequire("replicate");
|
|
56
|
+
const replicate = new Replicate();
|
|
57
|
+
|
|
58
|
+
console.log(`generating image with ${model}...`);
|
|
59
|
+
const output = await replicate.run(model, { input: { prompt } });
|
|
60
|
+
|
|
61
|
+
// Output can be a single FileOutput or an array of them
|
|
62
|
+
const file = Array.isArray(output) ? output[0] : output;
|
|
63
|
+
if (!file) {
|
|
64
|
+
console.error(`error: model ${model} returned no output`);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const imagesDir = join(getHomePath(), "images");
|
|
69
|
+
mkdirSync(imagesDir, { recursive: true });
|
|
70
|
+
|
|
71
|
+
const filePath = join(imagesDir, `${filename}.png`);
|
|
72
|
+
await writeFile(filePath, file);
|
|
73
|
+
console.log(`saved: ${filePath}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async function models(args: string[]): Promise<void> {
|
|
77
|
+
const query = args[0];
|
|
78
|
+
if (!query) {
|
|
79
|
+
console.log('Usage: imagegen models "query"');
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (!process.env.REPLICATE_API_TOKEN) {
|
|
84
|
+
console.error(
|
|
85
|
+
"REPLICATE_API_TOKEN not set. Run: volute env set REPLICATE_API_TOKEN <your-token>",
|
|
86
|
+
);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const Replicate = replicateRequire("replicate");
|
|
91
|
+
const replicate = new Replicate();
|
|
92
|
+
|
|
93
|
+
const response = await replicate.models.search(query);
|
|
94
|
+
const results = response.results.slice(0, 10);
|
|
95
|
+
|
|
96
|
+
if (results.length === 0) {
|
|
97
|
+
console.log("no models found.");
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
for (const m of results) {
|
|
102
|
+
const desc = m.description ? ` — ${m.description.slice(0, 100)}` : "";
|
|
103
|
+
console.log(`${m.owner}/${m.name}${desc}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function main() {
|
|
108
|
+
const args = process.argv.slice(2);
|
|
109
|
+
const cmd = args[0];
|
|
110
|
+
|
|
111
|
+
if (!cmd) {
|
|
112
|
+
console.log("Usage: imagegen <generate|models> [args]");
|
|
113
|
+
process.exit(0);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (cmd === "generate") {
|
|
117
|
+
await generate(args.slice(1));
|
|
118
|
+
} else if (cmd === "models") {
|
|
119
|
+
await models(args.slice(1));
|
|
120
|
+
} else {
|
|
121
|
+
console.error(`unknown command: ${cmd}`);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const isDirectRun =
|
|
127
|
+
process.argv[1] !== undefined &&
|
|
128
|
+
(import.meta.url === `file://${process.argv[1]}` ||
|
|
129
|
+
import.meta.url === `file://${resolve(process.argv[1])}`);
|
|
130
|
+
|
|
131
|
+
if (isDirectRun) {
|
|
132
|
+
main().catch((err) => {
|
|
133
|
+
console.error(err);
|
|
134
|
+
process.exit(1);
|
|
135
|
+
});
|
|
136
|
+
}
|