volute 0.3.0 → 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/dist/{agent-manager-2LU6KULR.js → agent-manager-AUCKMGPR.js} +4 -4
- package/dist/{channel-H7N4SGR2.js → channel-7FZ6D25H.js} +2 -2
- package/dist/{chunk-RALYNMHR.js → chunk-3C2XR4IY.js} +1 -1
- package/dist/{chunk-YEIHRP2J.js → chunk-DNOXHLE5.js} +1 -1
- package/dist/{chunk-IPIPLGME.js → chunk-I6OHXCMV.js} +4 -4
- package/dist/{chunk-DEUAVGSA.js → chunk-SOZA2TLP.js} +1 -1
- package/dist/{chunk-VVD3XO3E.js → chunk-YGFIWIOF.js} +1 -1
- package/dist/cli.js +19 -18
- package/dist/{connector-6LWB5PRU.js → connector-TVJULIRT.js} +3 -3
- package/dist/connectors/discord.js +5 -2
- package/dist/{create-RSWWMGKT.js → create-BRG2DBWI.js} +2 -2
- package/dist/{daemon-client-27KMQQKX.js → daemon-client-XR24PUJF.js} +2 -2
- package/dist/daemon.js +11 -11
- package/dist/{delete-4ERL2QHH.js → delete-GQ7JEK2S.js} +3 -3
- package/dist/{down-HRC4MQCT.js → down-3OB6UVAJ.js} +1 -1
- package/dist/{env-DBWDTIP6.js → env-JB27UAC3.js} +2 -2
- package/dist/{history-W7BD2H74.js → history-3VRUBGGV.js} +2 -2
- package/dist/{import-6HTSSDFW.js → import-K4MP2GX7.js} +2 -2
- package/dist/{logs-NHWGHNBF.js → logs-NXFFGUKY.js} +1 -1
- package/dist/{schedule-DKZ2E2CL.js → schedule-4I5TYHFH.js} +2 -2
- package/dist/{send-5LEJXPYV.js → send-UK3JBZIB.js} +2 -2
- package/dist/{setup-ZMNTOJAV.js → setup-SRS7AUAA.js} +2 -2
- package/dist/{start-2BSXX6BS.js → start-LDPMCMYT.js} +2 -2
- package/dist/{status-N23CV27T.js → status-MVSQG54T.js} +2 -2
- package/dist/{stop-DSKBIJ2D.js → stop-5PZTZCLL.js} +2 -2
- package/dist/{up-4UGID4DM.js → up-UT3IMKCA.js} +1 -1
- package/dist/{upgrade-BGFVRCVP.js → upgrade-CDKECCGN.js} +32 -19
- package/dist/{variant-JPLJTS2P.js → variant-CVYM3EQG.js} +126 -14
- package/package.json +1 -1
- package/templates/_base/_skills/volute-agent/SKILL.md +2 -1
- package/dist/chunk-MY74SUOL.js +0 -81
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
AgentManager,
|
|
4
4
|
getAgentManager,
|
|
5
5
|
initAgentManager
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-I6OHXCMV.js";
|
|
7
|
+
import "./chunk-DNOXHLE5.js";
|
|
8
|
+
import "./chunk-SOZA2TLP.js";
|
|
9
|
+
import "./chunk-3C2XR4IY.js";
|
|
10
10
|
import "./chunk-K3NQKI34.js";
|
|
11
11
|
export {
|
|
12
12
|
AgentManager,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
loadMergedEnv
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-DNOXHLE5.js";
|
|
5
5
|
import {
|
|
6
6
|
resolveAgentName
|
|
7
7
|
} from "./chunk-VRVVQIYY.js";
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "./chunk-D424ZQGI.js";
|
|
11
11
|
import {
|
|
12
12
|
resolveAgent
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-3C2XR4IY.js";
|
|
14
14
|
import "./chunk-K3NQKI34.js";
|
|
15
15
|
|
|
16
16
|
// src/lib/channels/discord.ts
|
|
@@ -81,7 +81,7 @@ function removeAllVariants(agentName) {
|
|
|
81
81
|
}
|
|
82
82
|
async function checkHealth(port) {
|
|
83
83
|
try {
|
|
84
|
-
const res = await fetch(`http://
|
|
84
|
+
const res = await fetch(`http://127.0.0.1:${port}/health`, {
|
|
85
85
|
signal: AbortSignal.timeout(2e3)
|
|
86
86
|
});
|
|
87
87
|
if (!res.ok) return { ok: false };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
loadMergedEnv
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-DNOXHLE5.js";
|
|
5
5
|
import {
|
|
6
6
|
applyIsolation
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-SOZA2TLP.js";
|
|
8
8
|
import {
|
|
9
9
|
agentDir,
|
|
10
10
|
findAgent,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
setVariantRunning,
|
|
14
14
|
validateBranchName,
|
|
15
15
|
voluteHome
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-3C2XR4IY.js";
|
|
17
17
|
|
|
18
18
|
// src/lib/agent-manager.ts
|
|
19
19
|
import { execFile, spawn } from "child_process";
|
|
@@ -89,7 +89,7 @@ var AgentManager = class {
|
|
|
89
89
|
const { dir, isVariant, baseName, variantName } = target;
|
|
90
90
|
const port = target.port;
|
|
91
91
|
try {
|
|
92
|
-
const res = await fetch(`http://
|
|
92
|
+
const res = await fetch(`http://127.0.0.1:${port}/health`);
|
|
93
93
|
if (res.ok) {
|
|
94
94
|
console.error(`[daemon] killing orphan process on port ${port}`);
|
|
95
95
|
await killProcessOnPort(port);
|
package/dist/cli.js
CHANGED
|
@@ -5,61 +5,61 @@ 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
22
|
case "variant":
|
|
23
|
-
await import("./variant-
|
|
23
|
+
await import("./variant-CVYM3EQG.js").then((m) => m.run(args));
|
|
24
24
|
break;
|
|
25
25
|
case "send":
|
|
26
|
-
await import("./send-
|
|
26
|
+
await import("./send-UK3JBZIB.js").then((m) => m.run(args));
|
|
27
27
|
break;
|
|
28
28
|
case "import":
|
|
29
|
-
await import("./import-
|
|
29
|
+
await import("./import-K4MP2GX7.js").then((m) => m.run(args));
|
|
30
30
|
break;
|
|
31
31
|
case "delete":
|
|
32
|
-
await import("./delete-
|
|
32
|
+
await import("./delete-GQ7JEK2S.js").then((m) => m.run(args));
|
|
33
33
|
break;
|
|
34
34
|
case "env":
|
|
35
|
-
await import("./env-
|
|
35
|
+
await import("./env-JB27UAC3.js").then((m) => m.run(args));
|
|
36
36
|
break;
|
|
37
37
|
case "connector":
|
|
38
|
-
await import("./connector-
|
|
38
|
+
await import("./connector-TVJULIRT.js").then((m) => m.run(args));
|
|
39
39
|
break;
|
|
40
40
|
case "channel":
|
|
41
|
-
await import("./channel-
|
|
41
|
+
await import("./channel-7FZ6D25H.js").then((m) => m.run(args));
|
|
42
42
|
break;
|
|
43
43
|
case "upgrade":
|
|
44
|
-
await import("./upgrade-
|
|
44
|
+
await import("./upgrade-CDKECCGN.js").then((m) => m.run(args));
|
|
45
45
|
break;
|
|
46
46
|
case "up":
|
|
47
|
-
await import("./up-
|
|
47
|
+
await import("./up-UT3IMKCA.js").then((m) => m.run(args));
|
|
48
48
|
break;
|
|
49
49
|
case "down":
|
|
50
|
-
await import("./down-
|
|
50
|
+
await import("./down-3OB6UVAJ.js").then((m) => m.run(args));
|
|
51
51
|
break;
|
|
52
52
|
case "schedule":
|
|
53
|
-
await import("./schedule-
|
|
53
|
+
await import("./schedule-4I5TYHFH.js").then((m) => m.run(args));
|
|
54
54
|
break;
|
|
55
55
|
case "history":
|
|
56
|
-
await import("./history-
|
|
56
|
+
await import("./history-3VRUBGGV.js").then((m) => m.run(args));
|
|
57
57
|
break;
|
|
58
58
|
case "service":
|
|
59
59
|
await import("./service-SA4TTMDU.js").then((m) => m.run(args));
|
|
60
60
|
break;
|
|
61
61
|
case "setup":
|
|
62
|
-
await import("./setup-
|
|
62
|
+
await import("./setup-SRS7AUAA.js").then((m) => m.run(args));
|
|
63
63
|
break;
|
|
64
64
|
default:
|
|
65
65
|
console.log(`volute \u2014 create and manage AI agents
|
|
@@ -74,6 +74,7 @@ Commands:
|
|
|
74
74
|
volute variant create <name> Create a variant (worktree + server)
|
|
75
75
|
volute variant list List variants for an agent
|
|
76
76
|
volute variant merge <name> Merge a variant back
|
|
77
|
+
volute variant delete <name> Delete a variant
|
|
77
78
|
volute import <path> Import an OpenClaw workspace
|
|
78
79
|
volute env <set|get|list|remove> Manage environment variables
|
|
79
80
|
volute connector connect <type> Enable a connector for an agent
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
loadMergedEnv
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-DNOXHLE5.js";
|
|
5
5
|
import {
|
|
6
6
|
daemonFetch
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-YGFIWIOF.js";
|
|
8
8
|
import {
|
|
9
9
|
resolveAgentName
|
|
10
10
|
} from "./chunk-VRVVQIYY.js";
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
} from "./chunk-D424ZQGI.js";
|
|
14
14
|
import {
|
|
15
15
|
resolveAgent
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-3C2XR4IY.js";
|
|
17
17
|
import "./chunk-K3NQKI34.js";
|
|
18
18
|
|
|
19
19
|
// src/commands/connector.ts
|
|
@@ -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;
|
|
@@ -207,6 +207,8 @@ async function handleAgentRequest(message, content) {
|
|
|
207
207
|
})
|
|
208
208
|
});
|
|
209
209
|
if (!res.ok) {
|
|
210
|
+
const body = await res.text().catch(() => "");
|
|
211
|
+
console.error(`Agent returned ${res.status}: ${body}`);
|
|
210
212
|
await message.reply(`Error: agent returned ${res.status}`);
|
|
211
213
|
clearInterval(typingInterval);
|
|
212
214
|
return;
|
|
@@ -232,6 +234,7 @@ async function handleAgentRequest(message, content) {
|
|
|
232
234
|
}
|
|
233
235
|
await flush();
|
|
234
236
|
} catch (err) {
|
|
237
|
+
console.error(`Failed to reach agent at ${baseUrl}/message:`, err);
|
|
235
238
|
const errMsg = err instanceof TypeError && err.cause?.code === "ECONNREFUSED" ? "Agent is not running" : `Error: ${err}`;
|
|
236
239
|
await message.reply(errMsg).catch(() => {
|
|
237
240
|
});
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
chownAgentDir,
|
|
14
14
|
createAgentUser,
|
|
15
15
|
ensureVoluteGroup
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-SOZA2TLP.js";
|
|
17
17
|
import {
|
|
18
18
|
parseArgs
|
|
19
19
|
} from "./chunk-D424ZQGI.js";
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
agentDir,
|
|
23
23
|
ensureVoluteHome,
|
|
24
24
|
nextPort
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-3C2XR4IY.js";
|
|
26
26
|
import "./chunk-K3NQKI34.js";
|
|
27
27
|
|
|
28
28
|
// src/commands/create.ts
|
package/dist/daemon.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
initAgentManager,
|
|
6
6
|
loadJsonMap,
|
|
7
7
|
saveJsonMap
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-I6OHXCMV.js";
|
|
9
9
|
import {
|
|
10
10
|
logBuffer,
|
|
11
11
|
logger_default,
|
|
@@ -17,10 +17,10 @@ import {
|
|
|
17
17
|
} from "./chunk-NETNFBA5.js";
|
|
18
18
|
import {
|
|
19
19
|
loadMergedEnv
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-DNOXHLE5.js";
|
|
21
21
|
import {
|
|
22
22
|
applyIsolation
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-SOZA2TLP.js";
|
|
24
24
|
import {
|
|
25
25
|
agentDir,
|
|
26
26
|
checkHealth,
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
setAgentRunning,
|
|
35
35
|
setVariantRunning,
|
|
36
36
|
voluteHome
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-3C2XR4IY.js";
|
|
38
38
|
import {
|
|
39
39
|
__export
|
|
40
40
|
} from "./chunk-K3NQKI34.js";
|
|
@@ -138,7 +138,7 @@ var ConnectorManager = class {
|
|
|
138
138
|
VOLUTE_AGENT_PORT: String(agentPort),
|
|
139
139
|
VOLUTE_AGENT_NAME: agentName,
|
|
140
140
|
...daemonPort ? {
|
|
141
|
-
VOLUTE_DAEMON_URL: `http://
|
|
141
|
+
VOLUTE_DAEMON_URL: `http://127.0.0.1:${daemonPort}`,
|
|
142
142
|
VOLUTE_DAEMON_TOKEN: process.env.VOLUTE_DAEMON_TOKEN
|
|
143
143
|
} : {},
|
|
144
144
|
...connectorEnv
|
|
@@ -377,7 +377,7 @@ var Scheduler = class {
|
|
|
377
377
|
try {
|
|
378
378
|
let res;
|
|
379
379
|
if (this.daemonPort && this.daemonToken) {
|
|
380
|
-
const daemonUrl = `http://
|
|
380
|
+
const daemonUrl = `http://127.0.0.1:${this.daemonPort}`;
|
|
381
381
|
res = await fetch(`${daemonUrl}/api/agents/${encodeURIComponent(agentName)}/message`, {
|
|
382
382
|
method: "POST",
|
|
383
383
|
headers: {
|
|
@@ -388,7 +388,7 @@ var Scheduler = class {
|
|
|
388
388
|
body
|
|
389
389
|
});
|
|
390
390
|
} else {
|
|
391
|
-
res = await fetch(`http://
|
|
391
|
+
res = await fetch(`http://127.0.0.1:${entry.port}/message`, {
|
|
392
392
|
method: "POST",
|
|
393
393
|
headers: { "Content-Type": "application/json" },
|
|
394
394
|
body
|
|
@@ -866,7 +866,7 @@ var app = new Hono().get("/", async (c) => {
|
|
|
866
866
|
console.error(`[daemon] failed to persist inbound message for ${baseName}:`, err);
|
|
867
867
|
}
|
|
868
868
|
}
|
|
869
|
-
const res = await fetch(`http://
|
|
869
|
+
const res = await fetch(`http://127.0.0.1:${port}/message`, {
|
|
870
870
|
method: "POST",
|
|
871
871
|
headers: { "Content-Type": "application/json" },
|
|
872
872
|
body
|
|
@@ -1116,7 +1116,7 @@ var app3 = new Hono3().post("/:name/chat", zValidator2("json", chatSchema), asyn
|
|
|
1116
1116
|
if (!variant) return c.json({ error: `Unknown variant: ${variantName}` }, 404);
|
|
1117
1117
|
port = variant.port;
|
|
1118
1118
|
}
|
|
1119
|
-
const { getAgentManager: getAgentManager2 } = await import("./agent-manager-
|
|
1119
|
+
const { getAgentManager: getAgentManager2 } = await import("./agent-manager-AUCKMGPR.js");
|
|
1120
1120
|
if (!getAgentManager2().isRunning(name)) {
|
|
1121
1121
|
return c.json({ error: "Agent is not running" }, 409);
|
|
1122
1122
|
}
|
|
@@ -1155,7 +1155,7 @@ var app3 = new Hono3().post("/:name/chat", zValidator2("json", chatSchema), asyn
|
|
|
1155
1155
|
sender: user.username,
|
|
1156
1156
|
content: body.message ?? "[image]"
|
|
1157
1157
|
});
|
|
1158
|
-
const res = await fetch(`http://
|
|
1158
|
+
const res = await fetch(`http://127.0.0.1:${port}/message`, {
|
|
1159
1159
|
method: "POST",
|
|
1160
1160
|
headers: { "Content-Type": "application/json" },
|
|
1161
1161
|
body: JSON.stringify({
|
|
@@ -1451,7 +1451,7 @@ var app8 = new Hono8().get("/:name/schedules", (c) => {
|
|
|
1451
1451
|
const body = await c.req.text();
|
|
1452
1452
|
const message = `[webhook: ${event}] ${body}`;
|
|
1453
1453
|
try {
|
|
1454
|
-
const res = await fetch(`http://
|
|
1454
|
+
const res = await fetch(`http://127.0.0.1:${entry.port}/message`, {
|
|
1455
1455
|
method: "POST",
|
|
1456
1456
|
headers: { "Content-Type": "application/json" },
|
|
1457
1457
|
body: JSON.stringify({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
deleteAgentUser
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SOZA2TLP.js";
|
|
5
5
|
import {
|
|
6
6
|
parseArgs
|
|
7
7
|
} from "./chunk-D424ZQGI.js";
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
findAgent,
|
|
11
11
|
removeAgent,
|
|
12
12
|
removeAllVariants
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-3C2XR4IY.js";
|
|
14
14
|
import "./chunk-K3NQKI34.js";
|
|
15
15
|
|
|
16
16
|
// src/commands/delete.ts
|
|
@@ -30,7 +30,7 @@ async function run(args) {
|
|
|
30
30
|
process.exit(1);
|
|
31
31
|
}
|
|
32
32
|
try {
|
|
33
|
-
const { daemonFetch } = await import("./daemon-client-
|
|
33
|
+
const { daemonFetch } = await import("./daemon-client-XR24PUJF.js");
|
|
34
34
|
const res = await daemonFetch(`/api/agents/${encodeURIComponent(name)}/stop`, {
|
|
35
35
|
method: "POST"
|
|
36
36
|
});
|
|
@@ -5,13 +5,13 @@ import {
|
|
|
5
5
|
readEnv,
|
|
6
6
|
sharedEnvPath,
|
|
7
7
|
writeEnv
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-DNOXHLE5.js";
|
|
9
9
|
import {
|
|
10
10
|
parseArgs
|
|
11
11
|
} from "./chunk-D424ZQGI.js";
|
|
12
12
|
import {
|
|
13
13
|
resolveAgent
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-3C2XR4IY.js";
|
|
15
15
|
import "./chunk-K3NQKI34.js";
|
|
16
16
|
|
|
17
17
|
// src/commands/env.ts
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
daemonFetch
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-YGFIWIOF.js";
|
|
5
5
|
import {
|
|
6
6
|
resolveAgentName
|
|
7
7
|
} from "./chunk-VRVVQIYY.js";
|
|
8
8
|
import {
|
|
9
9
|
parseArgs
|
|
10
10
|
} from "./chunk-D424ZQGI.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-3C2XR4IY.js";
|
|
12
12
|
import "./chunk-K3NQKI34.js";
|
|
13
13
|
|
|
14
14
|
// src/commands/history.ts
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
agentEnvPath,
|
|
8
8
|
readEnv,
|
|
9
9
|
writeEnv
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-DNOXHLE5.js";
|
|
11
11
|
import {
|
|
12
12
|
composeTemplate,
|
|
13
13
|
copyTemplateToDir,
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
agentDir,
|
|
26
26
|
ensureVoluteHome,
|
|
27
27
|
nextPort
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-3C2XR4IY.js";
|
|
29
29
|
import "./chunk-K3NQKI34.js";
|
|
30
30
|
|
|
31
31
|
// src/commands/import.ts
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
daemonFetch
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-YGFIWIOF.js";
|
|
5
5
|
import {
|
|
6
6
|
resolveAgentName
|
|
7
7
|
} from "./chunk-VRVVQIYY.js";
|
|
8
8
|
import {
|
|
9
9
|
parseArgs
|
|
10
10
|
} from "./chunk-D424ZQGI.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-3C2XR4IY.js";
|
|
12
12
|
import "./chunk-K3NQKI34.js";
|
|
13
13
|
|
|
14
14
|
// src/commands/schedule.ts
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
} from "./chunk-5SKQ6J7T.js";
|
|
5
5
|
import {
|
|
6
6
|
ensureVoluteGroup
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-SOZA2TLP.js";
|
|
8
8
|
import {
|
|
9
9
|
parseArgs
|
|
10
10
|
} from "./chunk-D424ZQGI.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-3C2XR4IY.js";
|
|
12
12
|
import "./chunk-K3NQKI34.js";
|
|
13
13
|
|
|
14
14
|
// src/commands/setup.ts
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
daemonFetch
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-YGFIWIOF.js";
|
|
5
5
|
import {
|
|
6
6
|
resolveAgent
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-3C2XR4IY.js";
|
|
8
8
|
import "./chunk-K3NQKI34.js";
|
|
9
9
|
|
|
10
10
|
// src/commands/start.ts
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
daemonFetch
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-YGFIWIOF.js";
|
|
5
5
|
import {
|
|
6
6
|
resolveAgent
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-3C2XR4IY.js";
|
|
8
8
|
import "./chunk-K3NQKI34.js";
|
|
9
9
|
|
|
10
10
|
// src/commands/stop.ts
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
spawnServer
|
|
4
|
-
} from "./chunk-MY74SUOL.js";
|
|
5
2
|
import {
|
|
6
3
|
composeTemplate,
|
|
7
4
|
copyTemplateToDir,
|
|
@@ -11,13 +8,17 @@ import {
|
|
|
11
8
|
exec,
|
|
12
9
|
execInherit
|
|
13
10
|
} from "./chunk-5SKQ6J7T.js";
|
|
11
|
+
import {
|
|
12
|
+
daemonFetch
|
|
13
|
+
} from "./chunk-YGFIWIOF.js";
|
|
14
14
|
import {
|
|
15
15
|
parseArgs
|
|
16
16
|
} from "./chunk-D424ZQGI.js";
|
|
17
17
|
import {
|
|
18
18
|
addVariant,
|
|
19
|
+
nextPort,
|
|
19
20
|
resolveAgent
|
|
20
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-3C2XR4IY.js";
|
|
21
22
|
import "./chunk-K3NQKI34.js";
|
|
22
23
|
|
|
23
24
|
// src/commands/upgrade.ts
|
|
@@ -41,12 +42,12 @@ async function run(args) {
|
|
|
41
42
|
await continueUpgrade(agentName, projectRoot);
|
|
42
43
|
return;
|
|
43
44
|
}
|
|
44
|
-
const worktreeDir = resolve(projectRoot, ".
|
|
45
|
+
const worktreeDir = resolve(projectRoot, ".variants", VARIANT_NAME);
|
|
45
46
|
if (existsSync(worktreeDir)) {
|
|
46
47
|
console.error(
|
|
47
|
-
`Upgrade
|
|
48
|
+
`Upgrade variant already exists: ${worktreeDir}
|
|
48
49
|
If a previous upgrade is in progress, use --continue to finish it.
|
|
49
|
-
Otherwise, remove it with:
|
|
50
|
+
Otherwise, remove it with: volute variant delete ${VARIANT_NAME} --agent ${agentName}`
|
|
50
51
|
);
|
|
51
52
|
process.exit(1);
|
|
52
53
|
}
|
|
@@ -58,7 +59,7 @@ Otherwise, remove it with: git -C ${projectRoot} worktree remove .worktrees/${VA
|
|
|
58
59
|
console.log("Updating template branch...");
|
|
59
60
|
await updateTemplateBranch(projectRoot, template, agentName);
|
|
60
61
|
console.log("Creating upgrade variant...");
|
|
61
|
-
const parentDir = resolve(projectRoot, ".
|
|
62
|
+
const parentDir = resolve(projectRoot, ".variants");
|
|
62
63
|
if (!existsSync(parentDir)) {
|
|
63
64
|
mkdirSync(parentDir, { recursive: true });
|
|
64
65
|
}
|
|
@@ -78,7 +79,7 @@ Then run:`);
|
|
|
78
79
|
await installAndVerify(agentName, worktreeDir);
|
|
79
80
|
}
|
|
80
81
|
async function updateTemplateBranch(projectRoot, template, agentName) {
|
|
81
|
-
const tempWorktree = resolve(projectRoot, ".
|
|
82
|
+
const tempWorktree = resolve(projectRoot, ".variants", "_template_update");
|
|
82
83
|
let branchExists = false;
|
|
83
84
|
try {
|
|
84
85
|
await exec("git", ["rev-parse", "--verify", TEMPLATE_BRANCH], {
|
|
@@ -161,7 +162,7 @@ async function mergeTemplateBranch(worktreeDir) {
|
|
|
161
162
|
}
|
|
162
163
|
}
|
|
163
164
|
async function continueUpgrade(agentName, projectRoot) {
|
|
164
|
-
const worktreeDir = resolve(projectRoot, ".
|
|
165
|
+
const worktreeDir = resolve(projectRoot, ".variants", VARIANT_NAME);
|
|
165
166
|
if (!existsSync(worktreeDir)) {
|
|
166
167
|
console.error("No upgrade in progress. Run `volute upgrade` first.");
|
|
167
168
|
process.exit(1);
|
|
@@ -184,22 +185,34 @@ async function continueUpgrade(agentName, projectRoot) {
|
|
|
184
185
|
async function installAndVerify(agentName, worktreeDir) {
|
|
185
186
|
console.log("Installing dependencies...");
|
|
186
187
|
await execInherit("npm", ["install"], { cwd: worktreeDir });
|
|
187
|
-
|
|
188
|
-
const result = await spawnServer(worktreeDir, 0, { detached: true });
|
|
189
|
-
if (!result) {
|
|
190
|
-
console.error("Server failed to start within timeout");
|
|
191
|
-
process.exit(1);
|
|
192
|
-
}
|
|
193
|
-
const { actualPort } = result;
|
|
188
|
+
const variantPort = nextPort();
|
|
194
189
|
addVariant(agentName, {
|
|
195
190
|
name: VARIANT_NAME,
|
|
196
191
|
branch: VARIANT_NAME,
|
|
197
192
|
path: worktreeDir,
|
|
198
|
-
port:
|
|
193
|
+
port: variantPort,
|
|
199
194
|
created: (/* @__PURE__ */ new Date()).toISOString()
|
|
200
195
|
});
|
|
196
|
+
console.log("Starting upgrade variant...");
|
|
197
|
+
try {
|
|
198
|
+
const res = await daemonFetch(
|
|
199
|
+
`/api/agents/${encodeURIComponent(`${agentName}@${VARIANT_NAME}`)}/start`,
|
|
200
|
+
{ method: "POST" }
|
|
201
|
+
);
|
|
202
|
+
if (!res.ok) {
|
|
203
|
+
const data = await res.json();
|
|
204
|
+
console.error(data.error ?? "Failed to start variant");
|
|
205
|
+
process.exit(1);
|
|
206
|
+
}
|
|
207
|
+
} catch {
|
|
208
|
+
console.error("Failed to start variant. Is the daemon running? (volute up)");
|
|
209
|
+
console.error(
|
|
210
|
+
`The variant was created but not started. Use: volute start ${agentName}@${VARIANT_NAME}`
|
|
211
|
+
);
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
201
214
|
console.log(`
|
|
202
|
-
Upgrade variant running on port ${
|
|
215
|
+
Upgrade variant running on port ${variantPort}`);
|
|
203
216
|
console.log(`
|
|
204
217
|
Next steps:`);
|
|
205
218
|
console.log(` volute send ${agentName}@${VARIANT_NAME} "hello" # chat with upgraded variant`);
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
spawnServer
|
|
4
|
-
} from "./chunk-MY74SUOL.js";
|
|
5
2
|
import {
|
|
6
3
|
exec,
|
|
7
4
|
execInherit
|
|
8
5
|
} from "./chunk-5SKQ6J7T.js";
|
|
9
6
|
import {
|
|
10
7
|
daemonFetch
|
|
11
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-YGFIWIOF.js";
|
|
12
9
|
import {
|
|
13
10
|
resolveAgentName
|
|
14
11
|
} from "./chunk-VRVVQIYY.js";
|
|
@@ -25,12 +22,88 @@ import {
|
|
|
25
22
|
resolveAgent,
|
|
26
23
|
validateBranchName,
|
|
27
24
|
writeVariants
|
|
28
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-3C2XR4IY.js";
|
|
29
26
|
import "./chunk-K3NQKI34.js";
|
|
30
27
|
|
|
31
28
|
// src/commands/variant.ts
|
|
32
|
-
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
|
29
|
+
import { existsSync, mkdirSync as mkdirSync2, writeFileSync } from "fs";
|
|
30
|
+
import { resolve as resolve2 } from "path";
|
|
31
|
+
|
|
32
|
+
// src/lib/spawn-server.ts
|
|
33
|
+
import { spawn } from "child_process";
|
|
34
|
+
import { closeSync, mkdirSync, openSync, readFileSync } from "fs";
|
|
33
35
|
import { resolve } from "path";
|
|
36
|
+
function tsxBin(cwd) {
|
|
37
|
+
return resolve(cwd, "node_modules", ".bin", "tsx");
|
|
38
|
+
}
|
|
39
|
+
function spawnServer(cwd, port, options) {
|
|
40
|
+
if (options?.detached) {
|
|
41
|
+
return spawnDetached(cwd, port);
|
|
42
|
+
}
|
|
43
|
+
return spawnAttached(cwd, port);
|
|
44
|
+
}
|
|
45
|
+
function spawnAttached(cwd, port) {
|
|
46
|
+
const child = spawn(tsxBin(cwd), ["src/server.ts", "--port", String(port)], {
|
|
47
|
+
cwd,
|
|
48
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
49
|
+
});
|
|
50
|
+
return new Promise((resolve3) => {
|
|
51
|
+
const timeout = setTimeout(() => resolve3(null), 3e4);
|
|
52
|
+
function checkOutput(data) {
|
|
53
|
+
const match = data.toString().match(/listening on :(\d+)/);
|
|
54
|
+
if (match) {
|
|
55
|
+
clearTimeout(timeout);
|
|
56
|
+
resolve3({ child, actualPort: parseInt(match[1], 10) });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
child.stdout?.on("data", checkOutput);
|
|
60
|
+
child.stderr?.on("data", checkOutput);
|
|
61
|
+
child.on("error", () => {
|
|
62
|
+
clearTimeout(timeout);
|
|
63
|
+
resolve3(null);
|
|
64
|
+
});
|
|
65
|
+
child.on("exit", () => {
|
|
66
|
+
clearTimeout(timeout);
|
|
67
|
+
resolve3(null);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function spawnDetached(cwd, port) {
|
|
72
|
+
const logsDir = resolve(cwd, ".volute", "logs");
|
|
73
|
+
mkdirSync(logsDir, { recursive: true });
|
|
74
|
+
const logPath = resolve(logsDir, "agent.log");
|
|
75
|
+
const logFd = openSync(logPath, "a");
|
|
76
|
+
const child = spawn(tsxBin(cwd), ["src/server.ts", "--port", String(port)], {
|
|
77
|
+
cwd,
|
|
78
|
+
stdio: ["ignore", logFd, logFd],
|
|
79
|
+
detached: true
|
|
80
|
+
});
|
|
81
|
+
child.unref();
|
|
82
|
+
closeSync(logFd);
|
|
83
|
+
return new Promise((res) => {
|
|
84
|
+
let done = false;
|
|
85
|
+
function finish(result) {
|
|
86
|
+
if (done) return;
|
|
87
|
+
done = true;
|
|
88
|
+
clearInterval(interval);
|
|
89
|
+
clearTimeout(timeout);
|
|
90
|
+
res(result);
|
|
91
|
+
}
|
|
92
|
+
const interval = setInterval(() => {
|
|
93
|
+
try {
|
|
94
|
+
const content = readFileSync(logPath, "utf-8");
|
|
95
|
+
const match = content.match(/listening on :(\d+)/);
|
|
96
|
+
if (match) {
|
|
97
|
+
finish({ child, actualPort: parseInt(match[1], 10) });
|
|
98
|
+
}
|
|
99
|
+
} catch {
|
|
100
|
+
}
|
|
101
|
+
}, 100);
|
|
102
|
+
const timeout = setTimeout(() => finish(null), 3e4);
|
|
103
|
+
child.on("error", () => finish(null));
|
|
104
|
+
child.on("exit", () => finish(null));
|
|
105
|
+
});
|
|
106
|
+
}
|
|
34
107
|
|
|
35
108
|
// src/lib/verify.ts
|
|
36
109
|
async function verify(port) {
|
|
@@ -41,7 +114,7 @@ async function verify(port) {
|
|
|
41
114
|
}
|
|
42
115
|
console.log(" Health check: OK");
|
|
43
116
|
try {
|
|
44
|
-
const res = await fetch(`http://
|
|
117
|
+
const res = await fetch(`http://127.0.0.1:${port}/message`, {
|
|
45
118
|
method: "POST",
|
|
46
119
|
headers: { "Content-Type": "application/json" },
|
|
47
120
|
body: JSON.stringify({
|
|
@@ -106,6 +179,9 @@ async function run(args) {
|
|
|
106
179
|
case "merge":
|
|
107
180
|
await mergeVariant(args.slice(1));
|
|
108
181
|
break;
|
|
182
|
+
case "delete":
|
|
183
|
+
await deleteVariant(args.slice(1));
|
|
184
|
+
break;
|
|
109
185
|
default:
|
|
110
186
|
printUsage();
|
|
111
187
|
process.exit(subcommand ? 1 : 0);
|
|
@@ -115,7 +191,8 @@ function printUsage() {
|
|
|
115
191
|
console.error(`Usage:
|
|
116
192
|
volute variant create <variant> [--agent <name>] [--soul "..."] [--port N] [--no-start] [--json]
|
|
117
193
|
volute variant list [--agent <name>] [--json]
|
|
118
|
-
volute variant merge <variant> [--agent <name>] [--summary "..." --memory "..."] [--skip-verify]
|
|
194
|
+
volute variant merge <variant> [--agent <name>] [--summary "..." --memory "..."] [--skip-verify]
|
|
195
|
+
volute variant delete <variant> [--agent <name>]`);
|
|
119
196
|
}
|
|
120
197
|
async function createVariant(args) {
|
|
121
198
|
const { positional, flags } = parseArgs(args, {
|
|
@@ -141,12 +218,12 @@ async function createVariant(args) {
|
|
|
141
218
|
process.exit(1);
|
|
142
219
|
}
|
|
143
220
|
const { dir: projectRoot } = resolveAgent(agentName);
|
|
144
|
-
const variantDir =
|
|
221
|
+
const variantDir = resolve2(projectRoot, ".variants", variantName);
|
|
145
222
|
if (existsSync(variantDir)) {
|
|
146
223
|
console.error(`Variant directory already exists: ${variantDir}`);
|
|
147
224
|
process.exit(1);
|
|
148
225
|
}
|
|
149
|
-
|
|
226
|
+
mkdirSync2(resolve2(projectRoot, ".variants"), { recursive: true });
|
|
150
227
|
try {
|
|
151
228
|
await exec("git", ["worktree", "add", "-b", variantName, variantDir], { cwd: projectRoot });
|
|
152
229
|
} catch (e) {
|
|
@@ -167,7 +244,7 @@ async function createVariant(args) {
|
|
|
167
244
|
process.exit(1);
|
|
168
245
|
}
|
|
169
246
|
if (soul) {
|
|
170
|
-
writeFileSync(
|
|
247
|
+
writeFileSync(resolve2(variantDir, "home/SOUL.md"), soul);
|
|
171
248
|
}
|
|
172
249
|
const variantPort = port ?? nextPort();
|
|
173
250
|
const variant = {
|
|
@@ -353,10 +430,10 @@ async function mergeVariant(args) {
|
|
|
353
430
|
console.error("npm install failed:", e);
|
|
354
431
|
}
|
|
355
432
|
console.log(`Variant ${variantName} merged and cleaned up.`);
|
|
356
|
-
const voluteDir =
|
|
357
|
-
if (!existsSync(voluteDir))
|
|
433
|
+
const voluteDir = resolve2(projectRoot, ".volute");
|
|
434
|
+
if (!existsSync(voluteDir)) mkdirSync2(voluteDir, { recursive: true });
|
|
358
435
|
writeFileSync(
|
|
359
|
-
|
|
436
|
+
resolve2(voluteDir, "merged.json"),
|
|
360
437
|
JSON.stringify({
|
|
361
438
|
name: variantName,
|
|
362
439
|
...flags.summary && { summary: flags.summary },
|
|
@@ -380,6 +457,41 @@ async function mergeVariant(args) {
|
|
|
380
457
|
console.log(`Daemon not running. Start the agent manually: volute start ${agentName}`);
|
|
381
458
|
}
|
|
382
459
|
}
|
|
460
|
+
async function deleteVariant(args) {
|
|
461
|
+
const { positional, flags } = parseArgs(args, {
|
|
462
|
+
agent: { type: "string" }
|
|
463
|
+
});
|
|
464
|
+
const agentName = resolveAgentName(flags);
|
|
465
|
+
const variantName = positional[0];
|
|
466
|
+
if (!variantName) {
|
|
467
|
+
console.error("Usage: volute variant delete <variant> [--agent <name>]");
|
|
468
|
+
process.exit(1);
|
|
469
|
+
}
|
|
470
|
+
const { dir: projectRoot } = resolveAgent(agentName);
|
|
471
|
+
const variant = findVariant(agentName, variantName);
|
|
472
|
+
if (!variant) {
|
|
473
|
+
console.error(`Unknown variant: ${variantName}`);
|
|
474
|
+
process.exit(1);
|
|
475
|
+
}
|
|
476
|
+
try {
|
|
477
|
+
await daemonFetch(`/api/agents/${encodeURIComponent(`${agentName}@${variantName}`)}/stop`, {
|
|
478
|
+
method: "POST"
|
|
479
|
+
});
|
|
480
|
+
} catch {
|
|
481
|
+
}
|
|
482
|
+
if (existsSync(variant.path)) {
|
|
483
|
+
try {
|
|
484
|
+
await exec("git", ["worktree", "remove", "--force", variant.path], { cwd: projectRoot });
|
|
485
|
+
} catch {
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
try {
|
|
489
|
+
await exec("git", ["branch", "-D", variant.branch], { cwd: projectRoot });
|
|
490
|
+
} catch {
|
|
491
|
+
}
|
|
492
|
+
removeVariant(agentName, variantName);
|
|
493
|
+
console.log(`Variant ${variantName} deleted.`);
|
|
494
|
+
}
|
|
383
495
|
export {
|
|
384
496
|
run
|
|
385
497
|
};
|
package/package.json
CHANGED
|
@@ -18,6 +18,7 @@ You manage yourself through the `volute` CLI. Commands that operate on "your" ag
|
|
|
18
18
|
| `volute variant create <name> [--soul "..."] [--port N]` | Create a variant to experiment with changes |
|
|
19
19
|
| `volute variant list` | List your variants |
|
|
20
20
|
| `volute variant merge <name> [--summary "..." --memory "..."]` | Merge a variant back |
|
|
21
|
+
| `volute variant delete <name>` | Delete a variant without merging |
|
|
21
22
|
| `volute upgrade [--template <name>] [--continue]` | Upgrade your server code |
|
|
22
23
|
| `volute connector connect <type>` | Enable a connector (e.g. discord) |
|
|
23
24
|
| `volute connector disconnect <type>` | Disable a connector |
|
|
@@ -57,7 +58,7 @@ Edit `.config/hooks/startup-context.sh` to customize what you see when a new ses
|
|
|
57
58
|
Variants let you experiment safely — fork yourself, try changes, and merge back what works. Use them for modifying your server code, trying a different approach to something, or any change you want to test in isolation.
|
|
58
59
|
|
|
59
60
|
1. `volute variant create experiment` — creates an isolated copy with its own server
|
|
60
|
-
2. Make changes in the variant's worktree (at `../.
|
|
61
|
+
2. Make changes in the variant's worktree (at `../.variants/experiment/`)
|
|
61
62
|
3. Test: `volute send $VOLUTE_AGENT@experiment "hello"`
|
|
62
63
|
4. `volute variant merge experiment --summary "..." --memory "..."` — merges back after verification
|
|
63
64
|
|
package/dist/chunk-MY74SUOL.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// src/lib/spawn-server.ts
|
|
4
|
-
import { spawn } from "child_process";
|
|
5
|
-
import { closeSync, mkdirSync, openSync, readFileSync } from "fs";
|
|
6
|
-
import { resolve } from "path";
|
|
7
|
-
function tsxBin(cwd) {
|
|
8
|
-
return resolve(cwd, "node_modules", ".bin", "tsx");
|
|
9
|
-
}
|
|
10
|
-
function spawnServer(cwd, port, options) {
|
|
11
|
-
if (options?.detached) {
|
|
12
|
-
return spawnDetached(cwd, port);
|
|
13
|
-
}
|
|
14
|
-
return spawnAttached(cwd, port);
|
|
15
|
-
}
|
|
16
|
-
function spawnAttached(cwd, port) {
|
|
17
|
-
const child = spawn(tsxBin(cwd), ["src/server.ts", "--port", String(port)], {
|
|
18
|
-
cwd,
|
|
19
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
20
|
-
});
|
|
21
|
-
return new Promise((resolve2) => {
|
|
22
|
-
const timeout = setTimeout(() => resolve2(null), 3e4);
|
|
23
|
-
function checkOutput(data) {
|
|
24
|
-
const match = data.toString().match(/listening on :(\d+)/);
|
|
25
|
-
if (match) {
|
|
26
|
-
clearTimeout(timeout);
|
|
27
|
-
resolve2({ child, actualPort: parseInt(match[1], 10) });
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
child.stdout?.on("data", checkOutput);
|
|
31
|
-
child.stderr?.on("data", checkOutput);
|
|
32
|
-
child.on("error", () => {
|
|
33
|
-
clearTimeout(timeout);
|
|
34
|
-
resolve2(null);
|
|
35
|
-
});
|
|
36
|
-
child.on("exit", () => {
|
|
37
|
-
clearTimeout(timeout);
|
|
38
|
-
resolve2(null);
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
function spawnDetached(cwd, port) {
|
|
43
|
-
const logsDir = resolve(cwd, ".volute", "logs");
|
|
44
|
-
mkdirSync(logsDir, { recursive: true });
|
|
45
|
-
const logPath = resolve(logsDir, "agent.log");
|
|
46
|
-
const logFd = openSync(logPath, "a");
|
|
47
|
-
const child = spawn(tsxBin(cwd), ["src/server.ts", "--port", String(port)], {
|
|
48
|
-
cwd,
|
|
49
|
-
stdio: ["ignore", logFd, logFd],
|
|
50
|
-
detached: true
|
|
51
|
-
});
|
|
52
|
-
child.unref();
|
|
53
|
-
closeSync(logFd);
|
|
54
|
-
return new Promise((res) => {
|
|
55
|
-
let done = false;
|
|
56
|
-
function finish(result) {
|
|
57
|
-
if (done) return;
|
|
58
|
-
done = true;
|
|
59
|
-
clearInterval(interval);
|
|
60
|
-
clearTimeout(timeout);
|
|
61
|
-
res(result);
|
|
62
|
-
}
|
|
63
|
-
const interval = setInterval(() => {
|
|
64
|
-
try {
|
|
65
|
-
const content = readFileSync(logPath, "utf-8");
|
|
66
|
-
const match = content.match(/listening on :(\d+)/);
|
|
67
|
-
if (match) {
|
|
68
|
-
finish({ child, actualPort: parseInt(match[1], 10) });
|
|
69
|
-
}
|
|
70
|
-
} catch {
|
|
71
|
-
}
|
|
72
|
-
}, 100);
|
|
73
|
-
const timeout = setTimeout(() => finish(null), 3e4);
|
|
74
|
-
child.on("error", () => finish(null));
|
|
75
|
-
child.on("exit", () => finish(null));
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export {
|
|
80
|
-
spawnServer
|
|
81
|
-
};
|