volute 0.9.0 → 0.10.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/dist/{agent-MB3OTRRK.js → agent-ECRX44DB.js} +5 -5
- package/dist/{agent-manager-CMMH5KQQ.js → agent-manager-MRHHKAB6.js} +2 -2
- package/dist/{chunk-YNNK4QN2.js → chunk-FYQGANL6.js} +40 -2
- package/dist/chunk-R3VB7NF5.js +205 -0
- package/dist/cli.js +14 -14
- package/dist/create-VBZZNJOG.js +38 -0
- package/dist/daemon-restart-QCLR6ZZV.js +61 -0
- package/dist/daemon.js +1492 -170
- package/dist/delete-BOTVU4YO.js +35 -0
- package/dist/{down-4DGRZRJU.js → down-4LIQG3CE.js} +3 -1
- package/dist/import-2BZUWT23.js +21 -0
- package/dist/{package-WPX6LCYE.js → package-ERGXEDAF.js} +1 -1
- package/dist/{up-J7AHQHIM.js → up-MNNPCMFF.js} +1 -1
- package/dist/upgrade-RSE4CZNE.js +55 -0
- package/dist/variant-7IZF6OWO.js +215 -0
- package/package.json +1 -1
- package/dist/chunk-ECPQXRLB.js +0 -264
- package/dist/chunk-NETNFBA5.js +0 -28
- package/dist/chunk-XUA3JUFK.js +0 -121
- package/dist/create-HGJHLABX.js +0 -96
- package/dist/daemon-restart-EKDXXHKH.js +0 -28
- package/dist/delete-WKQKE3FT.js +0 -70
- package/dist/import-CNEDF3TD.js +0 -532
- package/dist/upgrade-BRNMSQBX.js +0 -233
- package/dist/variant-AQRAN6FR.js +0 -493
- package/dist/{channel-G5D4VBXY.js → channel-2WHBRDTD.js} +3 -3
- package/dist/{chunk-AWHQZDB4.js → chunk-4NAGJV3I.js} +0 -0
- package/dist/{chunk-W6TMWYU3.js → chunk-WV4W7BAT.js} +3 -3
- package/dist/{connector-PK7D5GTN.js → connector-L2HBLZBW.js} +3 -3
- package/dist/{env-HZMZSWWD.js → env-CGORIKVF.js} +3 -3
- package/dist/{history-SH25BAA5.js → history-NI5QP27M.js} +3 -3
- package/dist/{logs-V54B6QSG.js → logs-APWVWGNX.js} +3 -3
- package/dist/{schedule-XGBUF7NU.js → schedule-E4MFGYSA.js} +3 -3
- package/dist/{send-TFZ62XPZ.js → send-X6OQGSD6.js} +4 -4
- package/dist/{service-56CY4S6Z.js → service-OW35VZ5G.js} +3 -3
- package/dist/{setup-7SPMWF2O.js → setup-ABMZK6LS.js} +3 -3
|
@@ -6,7 +6,7 @@ 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-VBZZNJOG.js").then((m) => m.run(args.slice(1)));
|
|
10
10
|
break;
|
|
11
11
|
case "start":
|
|
12
12
|
await import("./start-6YRS6FF6.js").then((m) => m.run(args.slice(1)));
|
|
@@ -18,7 +18,7 @@ async function run(args) {
|
|
|
18
18
|
await import("./restart-CCYM3MEC.js").then((m) => m.run(args.slice(1)));
|
|
19
19
|
break;
|
|
20
20
|
case "delete":
|
|
21
|
-
await import("./delete-
|
|
21
|
+
await import("./delete-BOTVU4YO.js").then((m) => m.run(args.slice(1)));
|
|
22
22
|
break;
|
|
23
23
|
case "list":
|
|
24
24
|
await import("./status-SIMKH3ZE.js").then((m) => m.run(args.slice(1)));
|
|
@@ -34,14 +34,14 @@ async function run(args) {
|
|
|
34
34
|
case "logs": {
|
|
35
35
|
const rest = args.slice(1);
|
|
36
36
|
const logsArgs = transformAgentFlag(rest);
|
|
37
|
-
await import("./logs-
|
|
37
|
+
await import("./logs-APWVWGNX.js").then((m) => m.run(logsArgs));
|
|
38
38
|
break;
|
|
39
39
|
}
|
|
40
40
|
case "upgrade":
|
|
41
|
-
await import("./upgrade-
|
|
41
|
+
await import("./upgrade-RSE4CZNE.js").then((m) => m.run(args.slice(1)));
|
|
42
42
|
break;
|
|
43
43
|
case "import":
|
|
44
|
-
await import("./import-
|
|
44
|
+
await import("./import-2BZUWT23.js").then((m) => m.run(args.slice(1)));
|
|
45
45
|
break;
|
|
46
46
|
case "--help":
|
|
47
47
|
case "-h":
|
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
AgentManager,
|
|
4
4
|
getAgentManager,
|
|
5
5
|
initAgentManager
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-QF22MYDJ.js";
|
|
6
|
+
} from "./chunk-WV4W7BAT.js";
|
|
8
7
|
import "./chunk-IQXBMFZG.js";
|
|
8
|
+
import "./chunk-QF22MYDJ.js";
|
|
9
9
|
import "./chunk-DP2DX4WV.js";
|
|
10
10
|
import "./chunk-K3NQKI34.js";
|
|
11
11
|
export {
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
daemonFetch
|
|
4
|
+
} from "./chunk-STOEJOJO.js";
|
|
2
5
|
import {
|
|
3
6
|
voluteHome
|
|
4
7
|
} from "./chunk-DP2DX4WV.js";
|
|
8
|
+
import {
|
|
9
|
+
getClient,
|
|
10
|
+
urlOf
|
|
11
|
+
} from "./chunk-4RQBJWQX.js";
|
|
5
12
|
|
|
6
13
|
// src/commands/down.ts
|
|
7
14
|
import { execFileSync } from "child_process";
|
|
@@ -112,8 +119,39 @@ async function run(_args) {
|
|
|
112
119
|
const result = await stopDaemon();
|
|
113
120
|
if (result.stopped) return;
|
|
114
121
|
if (result.reason === "systemd") {
|
|
115
|
-
|
|
116
|
-
|
|
122
|
+
const client = getClient();
|
|
123
|
+
await daemonFetch(urlOf(client.api.system.stop.$url()), { method: "POST" });
|
|
124
|
+
const home = voluteHome();
|
|
125
|
+
const configPath = resolve(home, "daemon.json");
|
|
126
|
+
let hostname = "localhost";
|
|
127
|
+
let port = 4200;
|
|
128
|
+
if (existsSync(configPath)) {
|
|
129
|
+
try {
|
|
130
|
+
const config = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
131
|
+
hostname = config.hostname || "localhost";
|
|
132
|
+
port = config.port ?? 4200;
|
|
133
|
+
} catch {
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (hostname === "0.0.0.0") hostname = "127.0.0.1";
|
|
137
|
+
if (hostname === "::") hostname = "[::1]";
|
|
138
|
+
const url = new URL("http://localhost");
|
|
139
|
+
url.hostname = hostname;
|
|
140
|
+
url.port = String(port);
|
|
141
|
+
const healthUrl = `${url.origin}/api/health`;
|
|
142
|
+
const maxWait = 1e4;
|
|
143
|
+
const start = Date.now();
|
|
144
|
+
while (Date.now() - start < maxWait) {
|
|
145
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
146
|
+
try {
|
|
147
|
+
await fetch(healthUrl);
|
|
148
|
+
} catch {
|
|
149
|
+
console.log("Daemon stopped.");
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
console.error("Daemon may not have stopped. Check with: volute service status");
|
|
154
|
+
process.exit(1);
|
|
117
155
|
} else if (result.reason === "orphan") {
|
|
118
156
|
console.error(`Daemon appears to be running on port ${result.port} but PID file is missing.`);
|
|
119
157
|
console.error(`Kill the process manually: lsof -ti :${result.port} | xargs kill`);
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
agentEnvPath,
|
|
4
|
+
readEnv,
|
|
5
|
+
writeEnv
|
|
6
|
+
} from "./chunk-QF22MYDJ.js";
|
|
7
|
+
import {
|
|
8
|
+
parseArgs
|
|
9
|
+
} from "./chunk-D424ZQGI.js";
|
|
10
|
+
|
|
11
|
+
// src/commands/import.ts
|
|
12
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync2, statSync, writeFileSync as writeFileSync2 } from "fs";
|
|
13
|
+
import { homedir } from "os";
|
|
14
|
+
import { basename, resolve as resolve2 } from "path";
|
|
15
|
+
|
|
16
|
+
// src/lib/volute-config.ts
|
|
17
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
18
|
+
import { dirname, resolve } from "path";
|
|
19
|
+
function readJson(path) {
|
|
20
|
+
if (!existsSync(path)) return null;
|
|
21
|
+
try {
|
|
22
|
+
return JSON.parse(readFileSync(path, "utf-8"));
|
|
23
|
+
} catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function readVoluteConfig(agentDir) {
|
|
28
|
+
const path = resolve(agentDir, "home/.config/volute.json");
|
|
29
|
+
return readJson(path);
|
|
30
|
+
}
|
|
31
|
+
function writeVoluteConfig(agentDir, config) {
|
|
32
|
+
const path = resolve(agentDir, "home/.config/volute.json");
|
|
33
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
34
|
+
writeFileSync(path, `${JSON.stringify(config, null, 2)}
|
|
35
|
+
`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// src/commands/import.ts
|
|
39
|
+
async function run(args) {
|
|
40
|
+
const { positional, flags } = parseArgs(args, {
|
|
41
|
+
name: { type: "string" },
|
|
42
|
+
session: { type: "string" },
|
|
43
|
+
template: { type: "string" }
|
|
44
|
+
});
|
|
45
|
+
const wsDir = resolveWorkspace(positional[0]);
|
|
46
|
+
const { daemonFetch } = await import("./daemon-client-P44NU3KU.js");
|
|
47
|
+
const { getClient, urlOf } = await import("./api-client-YPKOZP2O.js");
|
|
48
|
+
const client = getClient();
|
|
49
|
+
const res = await daemonFetch(urlOf(client.api.agents.import.$url()), {
|
|
50
|
+
method: "POST",
|
|
51
|
+
headers: { "Content-Type": "application/json" },
|
|
52
|
+
body: JSON.stringify({
|
|
53
|
+
workspacePath: wsDir,
|
|
54
|
+
name: flags.name,
|
|
55
|
+
template: flags.template,
|
|
56
|
+
sessionPath: flags.session
|
|
57
|
+
})
|
|
58
|
+
});
|
|
59
|
+
const data = await res.json();
|
|
60
|
+
if (!res.ok) {
|
|
61
|
+
console.error(data.error ?? "Failed to import agent");
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
console.log(`
|
|
65
|
+
${data.message ?? `Imported agent: ${data.name} (port ${data.port})`}`);
|
|
66
|
+
console.log(`
|
|
67
|
+
volute agent start ${data.name}`);
|
|
68
|
+
}
|
|
69
|
+
function resolveWorkspace(explicitPath) {
|
|
70
|
+
if (explicitPath) {
|
|
71
|
+
const wsDir = resolve2(explicitPath);
|
|
72
|
+
if (!existsSync2(resolve2(wsDir, "SOUL.md")) || !existsSync2(resolve2(wsDir, "IDENTITY.md"))) {
|
|
73
|
+
console.error("Not a valid OpenClaw workspace: missing SOUL.md or IDENTITY.md");
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
return wsDir;
|
|
77
|
+
}
|
|
78
|
+
const cwd = process.cwd();
|
|
79
|
+
if (existsSync2(resolve2(cwd, "SOUL.md")) && existsSync2(resolve2(cwd, "IDENTITY.md"))) {
|
|
80
|
+
console.log(`Using workspace: ${cwd}`);
|
|
81
|
+
return cwd;
|
|
82
|
+
}
|
|
83
|
+
const openclawWs = resolve2(homedir(), ".openclaw/workspace");
|
|
84
|
+
if (existsSync2(resolve2(openclawWs, "SOUL.md")) && existsSync2(resolve2(openclawWs, "IDENTITY.md"))) {
|
|
85
|
+
console.log(`Using workspace: ${openclawWs}`);
|
|
86
|
+
return openclawWs;
|
|
87
|
+
}
|
|
88
|
+
console.error(
|
|
89
|
+
"Usage: volute agent import [<workspace-path>] [--name <name>] [--session <path>] [--template <name>]\n\nNo OpenClaw workspace found. Provide a path, run from a workspace, or ensure ~/.openclaw/workspace exists."
|
|
90
|
+
);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
function findOpenClawSession(workspaceDir) {
|
|
94
|
+
const agentsDir = resolve2(homedir(), ".openclaw/agents");
|
|
95
|
+
if (!existsSync2(agentsDir)) return void 0;
|
|
96
|
+
const matches = [];
|
|
97
|
+
try {
|
|
98
|
+
for (const agent of readdirSync(agentsDir)) {
|
|
99
|
+
const sessionsDir = resolve2(agentsDir, agent, "sessions");
|
|
100
|
+
if (!existsSync2(sessionsDir)) continue;
|
|
101
|
+
for (const file of readdirSync(sessionsDir)) {
|
|
102
|
+
if (!file.endsWith(".jsonl")) continue;
|
|
103
|
+
const fullPath = resolve2(sessionsDir, file);
|
|
104
|
+
if (sessionMatchesWorkspace(fullPath, workspaceDir)) {
|
|
105
|
+
matches.push({ path: fullPath, mtime: statSync(fullPath).mtimeMs });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
} catch (err) {
|
|
110
|
+
console.warn("Warning: error scanning OpenClaw sessions:", err);
|
|
111
|
+
return void 0;
|
|
112
|
+
}
|
|
113
|
+
if (matches.length === 0) return void 0;
|
|
114
|
+
matches.sort((a, b) => b.mtime - a.mtime);
|
|
115
|
+
console.log(`Found session: ${matches[0].path}`);
|
|
116
|
+
return matches[0].path;
|
|
117
|
+
}
|
|
118
|
+
function sessionMatchesWorkspace(sessionPath, workspaceDir) {
|
|
119
|
+
try {
|
|
120
|
+
const fd = readFileSync2(sessionPath, "utf-8");
|
|
121
|
+
const firstLine = fd.slice(0, fd.indexOf("\n"));
|
|
122
|
+
const header = JSON.parse(firstLine);
|
|
123
|
+
return header.type === "session" && resolve2(header.cwd) === resolve2(workspaceDir);
|
|
124
|
+
} catch {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function importPiSession(sessionFile, agentDirPath) {
|
|
129
|
+
const homeDir = resolve2(agentDirPath, "home");
|
|
130
|
+
const piSessionDir = resolve2(agentDirPath, ".volute/pi-sessions/main");
|
|
131
|
+
mkdirSync2(piSessionDir, { recursive: true });
|
|
132
|
+
const content = readFileSync2(sessionFile, "utf-8");
|
|
133
|
+
const lines = content.trim().split("\n");
|
|
134
|
+
try {
|
|
135
|
+
const header = JSON.parse(lines[0]);
|
|
136
|
+
if (header.type === "session") {
|
|
137
|
+
header.cwd = homeDir;
|
|
138
|
+
lines[0] = JSON.stringify(header);
|
|
139
|
+
}
|
|
140
|
+
} catch {
|
|
141
|
+
}
|
|
142
|
+
const filename = basename(sessionFile);
|
|
143
|
+
const destPath = resolve2(piSessionDir, filename);
|
|
144
|
+
writeFileSync2(destPath, `${lines.join("\n")}
|
|
145
|
+
`);
|
|
146
|
+
console.log(`Imported session (${lines.length} entries)`);
|
|
147
|
+
}
|
|
148
|
+
function importOpenClawConnectors(agentName, agentDirPath) {
|
|
149
|
+
const configPath = resolve2(homedir(), ".openclaw/openclaw.json");
|
|
150
|
+
if (!existsSync2(configPath)) return;
|
|
151
|
+
let config;
|
|
152
|
+
try {
|
|
153
|
+
config = JSON.parse(readFileSync2(configPath, "utf-8"));
|
|
154
|
+
} catch (err) {
|
|
155
|
+
console.warn("Warning: failed to parse openclaw.json:", err);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const discord = config.channels?.discord;
|
|
159
|
+
if (!discord?.enabled || !discord.token) return;
|
|
160
|
+
const envPath = agentEnvPath(agentName);
|
|
161
|
+
const env = readEnv(envPath);
|
|
162
|
+
env.DISCORD_TOKEN = discord.token;
|
|
163
|
+
writeEnv(envPath, env);
|
|
164
|
+
const channelNames = /* @__PURE__ */ new Set();
|
|
165
|
+
if (discord.guilds) {
|
|
166
|
+
for (const guild of Object.values(discord.guilds)) {
|
|
167
|
+
if (!guild.channels) continue;
|
|
168
|
+
for (const [name, ch] of Object.entries(guild.channels)) {
|
|
169
|
+
if (ch.allow) channelNames.add(name);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const voluteConfig = readVoluteConfig(agentDirPath) ?? {};
|
|
174
|
+
const connectors = new Set(voluteConfig.connectors ?? []);
|
|
175
|
+
connectors.add("discord");
|
|
176
|
+
voluteConfig.connectors = [...connectors];
|
|
177
|
+
if (channelNames.size > 0) {
|
|
178
|
+
voluteConfig.discord = { channels: [...channelNames] };
|
|
179
|
+
}
|
|
180
|
+
writeVoluteConfig(agentDirPath, voluteConfig);
|
|
181
|
+
console.log("Imported Discord connector config");
|
|
182
|
+
if (channelNames.size > 0) {
|
|
183
|
+
console.log(`Imported followed channels: ${[...channelNames].join(", ")}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function parseNameFromIdentity(identity) {
|
|
187
|
+
const match = identity.match(/\*\*Name:\*\*\s*(.+)/);
|
|
188
|
+
if (match) {
|
|
189
|
+
const raw = match[1].trim();
|
|
190
|
+
if (!raw || raw.startsWith("*") || raw.startsWith("(")) return void 0;
|
|
191
|
+
return raw.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9.-]/g, "");
|
|
192
|
+
}
|
|
193
|
+
return void 0;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export {
|
|
197
|
+
readVoluteConfig,
|
|
198
|
+
writeVoluteConfig,
|
|
199
|
+
run,
|
|
200
|
+
findOpenClawSession,
|
|
201
|
+
sessionMatchesWorkspace,
|
|
202
|
+
importPiSession,
|
|
203
|
+
importOpenClawConnectors,
|
|
204
|
+
parseNameFromIdentity
|
|
205
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -9,49 +9,49 @@ if (!process.env.VOLUTE_HOME) {
|
|
|
9
9
|
var command = process.argv[2];
|
|
10
10
|
var args = process.argv.slice(3);
|
|
11
11
|
if (command === "--version" || command === "-v") {
|
|
12
|
-
const { default: pkg } = await import("./package-
|
|
12
|
+
const { default: pkg } = await import("./package-ERGXEDAF.js");
|
|
13
13
|
console.log(pkg.version);
|
|
14
14
|
process.exit(0);
|
|
15
15
|
}
|
|
16
16
|
switch (command) {
|
|
17
17
|
case "agent":
|
|
18
|
-
await import("./agent-
|
|
18
|
+
await import("./agent-ECRX44DB.js").then((m) => m.run(args));
|
|
19
19
|
break;
|
|
20
20
|
case "send":
|
|
21
|
-
await import("./send-
|
|
21
|
+
await import("./send-X6OQGSD6.js").then((m) => m.run(args));
|
|
22
22
|
break;
|
|
23
23
|
case "history":
|
|
24
|
-
await import("./history-
|
|
24
|
+
await import("./history-NI5QP27M.js").then((m) => m.run(args));
|
|
25
25
|
break;
|
|
26
26
|
case "variant":
|
|
27
|
-
await import("./variant-
|
|
27
|
+
await import("./variant-7IZF6OWO.js").then((m) => m.run(args));
|
|
28
28
|
break;
|
|
29
29
|
case "connector":
|
|
30
|
-
await import("./connector-
|
|
30
|
+
await import("./connector-L2HBLZBW.js").then((m) => m.run(args));
|
|
31
31
|
break;
|
|
32
32
|
case "channel":
|
|
33
|
-
await import("./channel-
|
|
33
|
+
await import("./channel-2WHBRDTD.js").then((m) => m.run(args));
|
|
34
34
|
break;
|
|
35
35
|
case "schedule":
|
|
36
|
-
await import("./schedule-
|
|
36
|
+
await import("./schedule-E4MFGYSA.js").then((m) => m.run(args));
|
|
37
37
|
break;
|
|
38
38
|
case "env":
|
|
39
|
-
await import("./env-
|
|
39
|
+
await import("./env-CGORIKVF.js").then((m) => m.run(args));
|
|
40
40
|
break;
|
|
41
41
|
case "up":
|
|
42
|
-
await import("./up-
|
|
42
|
+
await import("./up-MNNPCMFF.js").then((m) => m.run(args));
|
|
43
43
|
break;
|
|
44
44
|
case "down":
|
|
45
|
-
await import("./down-
|
|
45
|
+
await import("./down-4LIQG3CE.js").then((m) => m.run(args));
|
|
46
46
|
break;
|
|
47
47
|
case "restart":
|
|
48
|
-
await import("./daemon-restart-
|
|
48
|
+
await import("./daemon-restart-QCLR6ZZV.js").then((m) => m.run(args));
|
|
49
49
|
break;
|
|
50
50
|
case "setup":
|
|
51
|
-
await import("./setup-
|
|
51
|
+
await import("./setup-ABMZK6LS.js").then((m) => m.run(args));
|
|
52
52
|
break;
|
|
53
53
|
case "service":
|
|
54
|
-
await import("./service-
|
|
54
|
+
await import("./service-OW35VZ5G.js").then((m) => m.run(args));
|
|
55
55
|
break;
|
|
56
56
|
case "update":
|
|
57
57
|
await import("./update-3TGXUTO2.js").then((m) => m.run(args));
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
parseArgs
|
|
4
|
+
} from "./chunk-D424ZQGI.js";
|
|
5
|
+
import "./chunk-K3NQKI34.js";
|
|
6
|
+
|
|
7
|
+
// src/commands/create.ts
|
|
8
|
+
async function run(args) {
|
|
9
|
+
const { positional, flags } = parseArgs(args, {
|
|
10
|
+
template: { type: "string" }
|
|
11
|
+
});
|
|
12
|
+
const name = positional[0];
|
|
13
|
+
const template = flags.template ?? "agent-sdk";
|
|
14
|
+
if (!name) {
|
|
15
|
+
console.error("Usage: volute agent create <name> [--template <name>]");
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
const { daemonFetch } = await import("./daemon-client-P44NU3KU.js");
|
|
19
|
+
const { getClient, urlOf } = await import("./api-client-YPKOZP2O.js");
|
|
20
|
+
const client = getClient();
|
|
21
|
+
const res = await daemonFetch(urlOf(client.api.agents.$url()), {
|
|
22
|
+
method: "POST",
|
|
23
|
+
headers: { "Content-Type": "application/json" },
|
|
24
|
+
body: JSON.stringify({ name, template })
|
|
25
|
+
});
|
|
26
|
+
const data = await res.json();
|
|
27
|
+
if (!res.ok) {
|
|
28
|
+
console.error(data.error ?? "Failed to create agent");
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
console.log(`
|
|
32
|
+
${data.message ?? `Created agent: ${data.name} (port ${data.port})`}`);
|
|
33
|
+
console.log(`
|
|
34
|
+
volute agent start ${data.name ?? name}`);
|
|
35
|
+
}
|
|
36
|
+
export {
|
|
37
|
+
run
|
|
38
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
run
|
|
4
|
+
} from "./chunk-4NAGJV3I.js";
|
|
5
|
+
import {
|
|
6
|
+
stopDaemon
|
|
7
|
+
} from "./chunk-FYQGANL6.js";
|
|
8
|
+
import "./chunk-D424ZQGI.js";
|
|
9
|
+
import {
|
|
10
|
+
daemonFetch
|
|
11
|
+
} from "./chunk-STOEJOJO.js";
|
|
12
|
+
import {
|
|
13
|
+
voluteHome
|
|
14
|
+
} from "./chunk-DP2DX4WV.js";
|
|
15
|
+
import {
|
|
16
|
+
getClient,
|
|
17
|
+
urlOf
|
|
18
|
+
} from "./chunk-4RQBJWQX.js";
|
|
19
|
+
import "./chunk-K3NQKI34.js";
|
|
20
|
+
|
|
21
|
+
// src/commands/daemon-restart.ts
|
|
22
|
+
import { readFileSync } from "fs";
|
|
23
|
+
import { resolve } from "path";
|
|
24
|
+
async function run2(args) {
|
|
25
|
+
const result = await stopDaemon();
|
|
26
|
+
if (!result.stopped && result.reason === "systemd") {
|
|
27
|
+
const client = getClient();
|
|
28
|
+
await daemonFetch(urlOf(client.api.system.restart.$url()), { method: "POST" });
|
|
29
|
+
const config = JSON.parse(readFileSync(resolve(voluteHome(), "daemon.json"), "utf-8"));
|
|
30
|
+
let hostname = config.hostname || "localhost";
|
|
31
|
+
if (hostname === "0.0.0.0") hostname = "127.0.0.1";
|
|
32
|
+
if (hostname === "::") hostname = "[::1]";
|
|
33
|
+
const url = new URL("http://localhost");
|
|
34
|
+
url.hostname = hostname;
|
|
35
|
+
url.port = String(config.port ?? 4200);
|
|
36
|
+
const healthUrl = `${url.origin}/api/health`;
|
|
37
|
+
const maxWait = 15e3;
|
|
38
|
+
const start = Date.now();
|
|
39
|
+
while (Date.now() - start < maxWait) {
|
|
40
|
+
try {
|
|
41
|
+
const res = await fetch(healthUrl);
|
|
42
|
+
if (res.ok) {
|
|
43
|
+
console.log("Daemon restarted.");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
} catch {
|
|
47
|
+
}
|
|
48
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
49
|
+
}
|
|
50
|
+
console.error("Daemon did not restart within 15s. Check logs.");
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
if (!result.stopped && result.reason === "kill-failed") {
|
|
54
|
+
console.error("Cannot restart: failed to stop the running daemon.");
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
await run(args);
|
|
58
|
+
}
|
|
59
|
+
export {
|
|
60
|
+
run2 as run
|
|
61
|
+
};
|