volute 0.2.1 → 0.3.1
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 +46 -0
- package/dist/agent-manager-AUCKMGPR.js +15 -0
- package/dist/{channel-2WJRM7PE.js → channel-7FZ6D25H.js} +7 -7
- package/dist/{chunk-6UCG6MIX.js → chunk-3C2XR4IY.js} +2 -7
- package/dist/{chunk-XZN4WPNC.js → chunk-5SKQ6J7T.js} +9 -1
- package/dist/{chunk-KFNNHQK7.js → chunk-DNOXHLE5.js} +1 -1
- package/dist/{chunk-L3BQEZ4Z.js → chunk-I6OHXCMV.js} +75 -14
- package/dist/chunk-K3NQKI34.js +10 -0
- package/dist/chunk-NETNFBA5.js +28 -0
- package/dist/chunk-SOZA2TLP.js +81 -0
- package/dist/chunk-VRVVQIYY.js +15 -0
- package/dist/{chunk-4YXYAMFT.js → chunk-YGFIWIOF.js} +7 -6
- package/dist/cli.js +57 -51
- package/dist/connector-TVJULIRT.js +96 -0
- package/dist/connectors/discord.js +27 -3
- package/dist/{create-23AM7H5B.js → create-BRG2DBWI.js} +22 -5
- package/dist/daemon-client-XR24PUJF.js +9 -0
- package/dist/daemon.js +168 -138
- package/dist/{delete-GDMSOW3U.js → delete-GQ7JEK2S.js} +7 -2
- package/dist/{down-WTF73FE7.js → down-3OB6UVAJ.js} +10 -3
- package/dist/{env-YKUJOFHE.js → env-JB27UAC3.js} +3 -2
- package/dist/{history-7WVVKMUY.js → history-3VRUBGGV.js} +9 -8
- package/dist/{import-42DOLBDT.js → import-K4MP2GX7.js} +143 -36
- package/dist/{logs-SYRQOL6B.js → logs-NXFFGUKY.js} +8 -7
- package/dist/{schedule-J37XQM6E.js → schedule-4I5TYHFH.js} +41 -41
- package/dist/{send-PLOYEYER.js → send-UK3JBZIB.js} +3 -2
- package/dist/service-SA4TTMDU.js +195 -0
- package/dist/setup-SRS7AUAA.js +148 -0
- package/dist/{start-AG7QLULK.js → start-LDPMCMYT.js} +3 -2
- package/dist/{status-GCNU4M3K.js → status-MVSQG54T.js} +3 -2
- package/dist/{stop-IL5Q6NER.js → stop-5PZTZCLL.js} +3 -2
- package/dist/{up-ZC6G6K4K.js → up-UT3IMKCA.js} +5 -3
- package/dist/{upgrade-DD5TNJWU.js → upgrade-CDKECCGN.js} +35 -21
- package/dist/variant-CVYM3EQG.js +497 -0
- package/dist/web-assets/assets/index-BC5eSqbY.js +296 -0
- package/dist/web-assets/index.html +1 -1
- package/drizzle/0002_wealthy_the_call.sql +6 -0
- package/drizzle/meta/0002_snapshot.json +339 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +4 -1
- package/templates/_base/.init/SOUL.md +5 -1
- package/templates/_base/_skills/memory/SKILL.md +2 -2
- package/templates/_base/_skills/volute-agent/SKILL.md +30 -12
- package/templates/_base/home/VOLUTE.md +4 -2
- package/templates/_base/src/lib/auto-commit.ts +8 -3
- package/templates/_base/src/lib/types.ts +6 -2
- package/templates/_base/src/lib/volute-server.ts +5 -0
- package/templates/agent-sdk/.init/CLAUDE.md +15 -13
- package/templates/agent-sdk/src/agent.ts +12 -1
- package/templates/agent-sdk/src/lib/agent-sessions.ts +28 -4
- package/templates/pi/.init/AGENTS.md +11 -9
- package/templates/pi/src/agent.ts +16 -3
- package/templates/pi/src/lib/agent-sessions.ts +26 -4
- package/dist/agent-manager-SSJUZWOV.js +0 -13
- package/dist/chunk-MY74SUOL.js +0 -81
- package/dist/connect-X5V5IMRW.js +0 -48
- package/dist/daemon-client-VN24HM5T.js +0 -10
- package/dist/disconnect-5JWFZ6RV.js +0 -30
- package/dist/fork-GRSVMBKI.js +0 -119
- package/dist/merge-CSAVLSLY.js +0 -216
- package/dist/variants-QQIEKT6M.js +0 -60
- package/dist/web-assets/assets/index-DNNPoxMn.js +0 -158
package/dist/cli.js
CHANGED
|
@@ -5,92 +5,98 @@ var command = process.argv[2];
|
|
|
5
5
|
var args = process.argv.slice(3);
|
|
6
6
|
switch (command) {
|
|
7
7
|
case "create":
|
|
8
|
-
await import("./create-
|
|
8
|
+
await import("./create-BRG2DBWI.js").then((m) => m.run(args));
|
|
9
9
|
break;
|
|
10
10
|
case "start":
|
|
11
|
-
await import("./start-
|
|
11
|
+
await import("./start-LDPMCMYT.js").then((m) => m.run(args));
|
|
12
12
|
break;
|
|
13
13
|
case "stop":
|
|
14
|
-
await import("./stop-
|
|
14
|
+
await import("./stop-5PZTZCLL.js").then((m) => m.run(args));
|
|
15
15
|
break;
|
|
16
16
|
case "logs":
|
|
17
|
-
await import("./logs-
|
|
17
|
+
await import("./logs-NXFFGUKY.js").then((m) => m.run(args));
|
|
18
18
|
break;
|
|
19
19
|
case "status":
|
|
20
|
-
await import("./status-
|
|
20
|
+
await import("./status-MVSQG54T.js").then((m) => m.run(args));
|
|
21
21
|
break;
|
|
22
|
-
case "
|
|
23
|
-
await import("./
|
|
24
|
-
break;
|
|
25
|
-
case "variants":
|
|
26
|
-
await import("./variants-QQIEKT6M.js").then((m) => m.run(args));
|
|
22
|
+
case "variant":
|
|
23
|
+
await import("./variant-CVYM3EQG.js").then((m) => m.run(args));
|
|
27
24
|
break;
|
|
28
25
|
case "send":
|
|
29
|
-
await import("./send-
|
|
30
|
-
break;
|
|
31
|
-
case "merge":
|
|
32
|
-
await import("./merge-CSAVLSLY.js").then((m) => m.run(args));
|
|
26
|
+
await import("./send-UK3JBZIB.js").then((m) => m.run(args));
|
|
33
27
|
break;
|
|
34
28
|
case "import":
|
|
35
|
-
await import("./import-
|
|
29
|
+
await import("./import-K4MP2GX7.js").then((m) => m.run(args));
|
|
36
30
|
break;
|
|
37
31
|
case "delete":
|
|
38
|
-
await import("./delete-
|
|
32
|
+
await import("./delete-GQ7JEK2S.js").then((m) => m.run(args));
|
|
39
33
|
break;
|
|
40
34
|
case "env":
|
|
41
|
-
await import("./env-
|
|
42
|
-
break;
|
|
43
|
-
case "connect":
|
|
44
|
-
await import("./connect-X5V5IMRW.js").then((m) => m.run(args));
|
|
35
|
+
await import("./env-JB27UAC3.js").then((m) => m.run(args));
|
|
45
36
|
break;
|
|
46
|
-
case "
|
|
47
|
-
await import("./
|
|
37
|
+
case "connector":
|
|
38
|
+
await import("./connector-TVJULIRT.js").then((m) => m.run(args));
|
|
48
39
|
break;
|
|
49
40
|
case "channel":
|
|
50
|
-
await import("./channel-
|
|
41
|
+
await import("./channel-7FZ6D25H.js").then((m) => m.run(args));
|
|
51
42
|
break;
|
|
52
43
|
case "upgrade":
|
|
53
|
-
await import("./upgrade-
|
|
44
|
+
await import("./upgrade-CDKECCGN.js").then((m) => m.run(args));
|
|
54
45
|
break;
|
|
55
46
|
case "up":
|
|
56
|
-
await import("./up-
|
|
47
|
+
await import("./up-UT3IMKCA.js").then((m) => m.run(args));
|
|
57
48
|
break;
|
|
58
49
|
case "down":
|
|
59
|
-
await import("./down-
|
|
50
|
+
await import("./down-3OB6UVAJ.js").then((m) => m.run(args));
|
|
60
51
|
break;
|
|
61
52
|
case "schedule":
|
|
62
|
-
await import("./schedule-
|
|
53
|
+
await import("./schedule-4I5TYHFH.js").then((m) => m.run(args));
|
|
63
54
|
break;
|
|
64
55
|
case "history":
|
|
65
|
-
await import("./history-
|
|
56
|
+
await import("./history-3VRUBGGV.js").then((m) => m.run(args));
|
|
57
|
+
break;
|
|
58
|
+
case "service":
|
|
59
|
+
await import("./service-SA4TTMDU.js").then((m) => m.run(args));
|
|
60
|
+
break;
|
|
61
|
+
case "setup":
|
|
62
|
+
await import("./setup-SRS7AUAA.js").then((m) => m.run(args));
|
|
66
63
|
break;
|
|
67
64
|
default:
|
|
68
65
|
console.log(`volute \u2014 create and manage AI agents
|
|
69
66
|
|
|
70
67
|
Commands:
|
|
71
|
-
volute create <name>
|
|
72
|
-
volute start <name>
|
|
73
|
-
volute stop <name>
|
|
74
|
-
volute status [<name>]
|
|
75
|
-
volute logs <name>
|
|
76
|
-
volute send <name> "<msg>"
|
|
77
|
-
volute
|
|
78
|
-
volute
|
|
79
|
-
volute merge <name>
|
|
80
|
-
volute
|
|
81
|
-
volute
|
|
82
|
-
volute
|
|
83
|
-
volute
|
|
84
|
-
volute
|
|
85
|
-
volute channel
|
|
86
|
-
volute
|
|
87
|
-
volute schedule
|
|
88
|
-
volute schedule
|
|
89
|
-
volute
|
|
90
|
-
volute
|
|
91
|
-
volute
|
|
92
|
-
volute
|
|
93
|
-
volute
|
|
68
|
+
volute create <name> Create a new agent
|
|
69
|
+
volute start <name> Start an agent (daemonized)
|
|
70
|
+
volute stop <name> Stop an agent
|
|
71
|
+
volute status [<name>] Check agent status (or list all)
|
|
72
|
+
volute logs [--agent <name>] Tail agent logs
|
|
73
|
+
volute send <name> "<msg>" Send a message to an agent
|
|
74
|
+
volute variant create <name> Create a variant (worktree + server)
|
|
75
|
+
volute variant list List variants for an agent
|
|
76
|
+
volute variant merge <name> Merge a variant back
|
|
77
|
+
volute variant delete <name> Delete a variant
|
|
78
|
+
volute import <path> Import an OpenClaw workspace
|
|
79
|
+
volute env <set|get|list|remove> Manage environment variables
|
|
80
|
+
volute connector connect <type> Enable a connector for an agent
|
|
81
|
+
volute connector disconnect <type> Disable a connector for an agent
|
|
82
|
+
volute channel read <uri> Read recent messages from a channel
|
|
83
|
+
volute channel send <uri> "<msg>" Send a message to a channel
|
|
84
|
+
volute schedule list List schedules for an agent
|
|
85
|
+
volute schedule add ... Add a cron schedule
|
|
86
|
+
volute schedule remove ... Remove a schedule
|
|
87
|
+
volute history View message history
|
|
88
|
+
volute up [--port N] Start the daemon (default: 4200)
|
|
89
|
+
volute down Stop the daemon
|
|
90
|
+
volute upgrade <name> Upgrade agent to latest template
|
|
91
|
+
volute delete <name> [--force] Delete an agent (--force removes files)
|
|
92
|
+
volute service install [--port N] Install as system service (auto-start)
|
|
93
|
+
volute service uninstall Remove system service
|
|
94
|
+
volute service status Check service status
|
|
95
|
+
volute setup [--port N] [--host H] Install system service with user isolation
|
|
96
|
+
volute setup uninstall [--force] Remove system service + isolation
|
|
97
|
+
|
|
98
|
+
Agent commands (variant, connector, schedule, logs, history, channel) use
|
|
99
|
+
--agent <name> or VOLUTE_AGENT env var to identify the agent.`);
|
|
94
100
|
if (command) {
|
|
95
101
|
console.error(`
|
|
96
102
|
Unknown command: ${command}`);
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
loadMergedEnv
|
|
4
|
+
} from "./chunk-DNOXHLE5.js";
|
|
5
|
+
import {
|
|
6
|
+
daemonFetch
|
|
7
|
+
} from "./chunk-YGFIWIOF.js";
|
|
8
|
+
import {
|
|
9
|
+
resolveAgentName
|
|
10
|
+
} from "./chunk-VRVVQIYY.js";
|
|
11
|
+
import {
|
|
12
|
+
parseArgs
|
|
13
|
+
} from "./chunk-D424ZQGI.js";
|
|
14
|
+
import {
|
|
15
|
+
resolveAgent
|
|
16
|
+
} from "./chunk-3C2XR4IY.js";
|
|
17
|
+
import "./chunk-K3NQKI34.js";
|
|
18
|
+
|
|
19
|
+
// src/commands/connector.ts
|
|
20
|
+
async function run(args) {
|
|
21
|
+
const subcommand = args[0];
|
|
22
|
+
switch (subcommand) {
|
|
23
|
+
case "connect":
|
|
24
|
+
await connectConnector(args.slice(1));
|
|
25
|
+
break;
|
|
26
|
+
case "disconnect":
|
|
27
|
+
await disconnectConnector(args.slice(1));
|
|
28
|
+
break;
|
|
29
|
+
default:
|
|
30
|
+
printUsage();
|
|
31
|
+
process.exit(subcommand ? 1 : 0);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function printUsage() {
|
|
35
|
+
console.error(`Usage:
|
|
36
|
+
volute connector connect <type> [--agent <name>]
|
|
37
|
+
volute connector disconnect <type> [--agent <name>]`);
|
|
38
|
+
}
|
|
39
|
+
async function connectConnector(args) {
|
|
40
|
+
const { positional, flags } = parseArgs(args, {
|
|
41
|
+
agent: { type: "string" }
|
|
42
|
+
});
|
|
43
|
+
const agentName = resolveAgentName(flags);
|
|
44
|
+
const type = positional[0];
|
|
45
|
+
if (!type) {
|
|
46
|
+
console.error("Usage: volute connector connect <type> [--agent <name>]");
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
const { dir } = resolveAgent(agentName);
|
|
50
|
+
if (type === "discord") {
|
|
51
|
+
const env = loadMergedEnv(dir);
|
|
52
|
+
if (!env.DISCORD_TOKEN) {
|
|
53
|
+
console.error("DISCORD_TOKEN not set. Run: volute env set DISCORD_TOKEN <token>");
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
} else {
|
|
57
|
+
console.error(`Unknown connector type: ${type}`);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
const res = await daemonFetch(
|
|
61
|
+
`/api/agents/${encodeURIComponent(agentName)}/connectors/${encodeURIComponent(type)}`,
|
|
62
|
+
{ method: "POST" }
|
|
63
|
+
);
|
|
64
|
+
if (!res.ok) {
|
|
65
|
+
const body = await res.json().catch(() => ({ error: "Unknown error" }));
|
|
66
|
+
console.error(`Failed to start ${type} connector: ${body.error}`);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
console.log(`${type} connector for ${agentName} started.`);
|
|
70
|
+
}
|
|
71
|
+
async function disconnectConnector(args) {
|
|
72
|
+
const { positional, flags } = parseArgs(args, {
|
|
73
|
+
agent: { type: "string" }
|
|
74
|
+
});
|
|
75
|
+
const agentName = resolveAgentName(flags);
|
|
76
|
+
const type = positional[0];
|
|
77
|
+
if (!type) {
|
|
78
|
+
console.error("Usage: volute connector disconnect <type> [--agent <name>]");
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
const res = await daemonFetch(
|
|
82
|
+
`/api/agents/${encodeURIComponent(agentName)}/connectors/${encodeURIComponent(type)}`,
|
|
83
|
+
{
|
|
84
|
+
method: "DELETE"
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
if (!res.ok) {
|
|
88
|
+
const body = await res.json().catch(() => ({ error: "Unknown error" }));
|
|
89
|
+
console.error(`Failed to stop ${type} connector: ${body.error}`);
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
console.log(`${type} connector for ${agentName} stopped.`);
|
|
93
|
+
}
|
|
94
|
+
export {
|
|
95
|
+
run
|
|
96
|
+
};
|
|
@@ -24,7 +24,7 @@ if (!token) {
|
|
|
24
24
|
var guildId = process.env.DISCORD_GUILD_ID;
|
|
25
25
|
var daemonUrl = process.env.VOLUTE_DAEMON_URL;
|
|
26
26
|
var daemonToken = process.env.VOLUTE_DAEMON_TOKEN;
|
|
27
|
-
var baseUrl = daemonUrl ? `${daemonUrl}/api/agents/${encodeURIComponent(agentName)}` : `http://
|
|
27
|
+
var baseUrl = daemonUrl ? `${daemonUrl}/api/agents/${encodeURIComponent(agentName)}` : `http://127.0.0.1:${agentPort}`;
|
|
28
28
|
var client = new Client({
|
|
29
29
|
intents: [
|
|
30
30
|
GatewayIntentBits.Guilds,
|
|
@@ -42,7 +42,7 @@ process.on("SIGINT", shutdown);
|
|
|
42
42
|
process.on("SIGTERM", shutdown);
|
|
43
43
|
client.once(Events.ClientReady, (c) => {
|
|
44
44
|
console.log(`Connected to Discord as ${c.user.tag}`);
|
|
45
|
-
console.log(`Bridging to agent: ${agentName}
|
|
45
|
+
console.log(`Bridging to agent: ${agentName} via ${baseUrl}/message`);
|
|
46
46
|
});
|
|
47
47
|
client.on(Events.MessageCreate, async (message) => {
|
|
48
48
|
if (message.author.bot) return;
|
|
@@ -72,7 +72,28 @@ client.on(Events.MessageCreate, async (message) => {
|
|
|
72
72
|
if (content.length === 0) return;
|
|
73
73
|
await handleAgentRequest(message, content);
|
|
74
74
|
});
|
|
75
|
-
|
|
75
|
+
async function loginWithRetry() {
|
|
76
|
+
try {
|
|
77
|
+
await client.login(token);
|
|
78
|
+
} catch (err) {
|
|
79
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
80
|
+
const match = msg.match(/resets at (.+)/);
|
|
81
|
+
if (match) {
|
|
82
|
+
const resetAt = new Date(match[1]);
|
|
83
|
+
const waitMs = resetAt.getTime() - Date.now();
|
|
84
|
+
if (waitMs > 0) {
|
|
85
|
+
console.error(`Session limit hit, waiting until ${resetAt.toISOString()}...`);
|
|
86
|
+
await new Promise((r) => setTimeout(r, waitMs + 5e3));
|
|
87
|
+
return loginWithRetry();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
throw err;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
loginWithRetry().catch((err) => {
|
|
94
|
+
console.error("Failed to connect to Discord:", err);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
});
|
|
76
97
|
function splitMessage(text) {
|
|
77
98
|
const chunks = [];
|
|
78
99
|
while (text.length > DISCORD_MAX_LENGTH) {
|
|
@@ -186,6 +207,8 @@ async function handleAgentRequest(message, content) {
|
|
|
186
207
|
})
|
|
187
208
|
});
|
|
188
209
|
if (!res.ok) {
|
|
210
|
+
const body = await res.text().catch(() => "");
|
|
211
|
+
console.error(`Agent returned ${res.status}: ${body}`);
|
|
189
212
|
await message.reply(`Error: agent returned ${res.status}`);
|
|
190
213
|
clearInterval(typingInterval);
|
|
191
214
|
return;
|
|
@@ -211,6 +234,7 @@ async function handleAgentRequest(message, content) {
|
|
|
211
234
|
}
|
|
212
235
|
await flush();
|
|
213
236
|
} catch (err) {
|
|
237
|
+
console.error(`Failed to reach agent at ${baseUrl}/message:`, err);
|
|
214
238
|
const errMsg = err instanceof TypeError && err.cause?.code === "ECONNREFUSED" ? "Agent is not running" : `Error: ${err}`;
|
|
215
239
|
await message.reply(errMsg).catch(() => {
|
|
216
240
|
});
|
|
@@ -8,7 +8,12 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
exec,
|
|
10
10
|
execInherit
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-5SKQ6J7T.js";
|
|
12
|
+
import {
|
|
13
|
+
chownAgentDir,
|
|
14
|
+
createAgentUser,
|
|
15
|
+
ensureVoluteGroup
|
|
16
|
+
} from "./chunk-SOZA2TLP.js";
|
|
12
17
|
import {
|
|
13
18
|
parseArgs
|
|
14
19
|
} from "./chunk-D424ZQGI.js";
|
|
@@ -17,7 +22,8 @@ import {
|
|
|
17
22
|
agentDir,
|
|
18
23
|
ensureVoluteHome,
|
|
19
24
|
nextPort
|
|
20
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-3C2XR4IY.js";
|
|
26
|
+
import "./chunk-K3NQKI34.js";
|
|
21
27
|
|
|
22
28
|
// src/commands/create.ts
|
|
23
29
|
import { existsSync, rmSync } from "fs";
|
|
@@ -49,9 +55,20 @@ async function run(args) {
|
|
|
49
55
|
addAgent(name, port);
|
|
50
56
|
console.log("Installing dependencies...");
|
|
51
57
|
await execInherit("npm", ["install"], { cwd: dest });
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
58
|
+
try {
|
|
59
|
+
await exec("git", ["init"], { cwd: dest });
|
|
60
|
+
await exec("git", ["add", "-A"], { cwd: dest });
|
|
61
|
+
await exec("git", ["commit", "-m", "initial commit"], { cwd: dest });
|
|
62
|
+
} catch {
|
|
63
|
+
console.warn(
|
|
64
|
+
"\nWarning: git init failed (git may not be installed or configured).",
|
|
65
|
+
"\nThe agent will work, but forking/variants won't be available.",
|
|
66
|
+
"\nTo fix: install git and run `git config --global user.name` / `git config --global user.email`"
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
ensureVoluteGroup();
|
|
70
|
+
createAgentUser(name);
|
|
71
|
+
chownAgentDir(dest, name);
|
|
55
72
|
console.log(`
|
|
56
73
|
Created agent: ${name} (port ${port})`);
|
|
57
74
|
console.log(`
|