volute 0.1.0 → 0.2.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 +1 -2
- package/dist/agent-manager-SSJUZWOV.js +13 -0
- package/dist/{channel-Q642YUZE.js → channel-2WJRM7PE.js} +2 -2
- package/dist/{chunk-H5XQARAP.js → chunk-4YXYAMFT.js} +3 -3
- package/dist/{chunk-5YW4B7CG.js → chunk-6UCG6MIX.js} +72 -23
- package/dist/{chunk-A5ZJEMHT.js → chunk-KFNNHQK7.js} +4 -4
- package/dist/chunk-L3BQEZ4Z.js +271 -0
- package/dist/{chunk-N4QN44LC.js → chunk-MY74SUOL.js} +29 -22
- package/dist/{chunk-KSMIWOCN.js → chunk-N4YNKR3Q.js} +6 -0
- package/dist/cli.js +23 -19
- package/dist/{connect-LW6G23AV.js → connect-X5V5IMRW.js} +3 -3
- package/dist/connectors/discord.js +9 -2
- package/dist/{create-3K6O2SDC.js → create-23AM7H5B.js} +1 -1
- package/dist/{daemon-client-ZTHW7ROS.js → daemon-client-VN24HM5T.js} +2 -2
- package/dist/daemon.js +394 -436
- package/dist/{delete-JNGY7ZFH.js → delete-GDMSOW3U.js} +2 -2
- package/dist/{disconnect-ACVTKTRE.js → disconnect-5JWFZ6RV.js} +2 -2
- package/dist/{down-FYCUYC5H.js → down-WTF73FE7.js} +5 -4
- package/dist/{env-7SLRN3MG.js → env-YKUJOFHE.js} +12 -5
- package/dist/{fork-BB3DZ426.js → fork-GRSVMBKI.js} +39 -32
- package/dist/history-7WVVKMUY.js +46 -0
- package/dist/{import-W2AMTEV5.js → import-42DOLBDT.js} +1 -1
- package/dist/{logs-BUHRIQ2L.js → logs-SYRQOL6B.js} +1 -1
- package/dist/{merge-446QTE7Q.js → merge-CSAVLSLY.js} +33 -36
- package/dist/{schedule-KKSOVUDF.js → schedule-J37XQM6E.js} +2 -2
- package/dist/{send-WQSVSRDD.js → send-PLOYEYER.js} +7 -5
- package/dist/{start-LKMWS6ZE.js → start-AG7QLULK.js} +2 -2
- package/dist/{status-CIEKUI3V.js → status-GCNU4M3K.js} +9 -2
- package/dist/{stop-YTOAGYE4.js → stop-IL5Q6NER.js} +2 -2
- package/dist/{up-AJJ4GCXY.js → up-ZC6G6K4K.js} +21 -37
- package/dist/{upgrade-JACA6YMO.js → upgrade-DD5TNJWU.js} +3 -5
- package/dist/{variants-HPY4DEWU.js → variants-QQIEKT6M.js} +2 -2
- package/drizzle/0000_flaky_mariko_yashida.sql +34 -0
- package/drizzle/0001_careless_warpath.sql +12 -0
- package/drizzle/meta/0000_snapshot.json +227 -0
- package/drizzle/meta/0001_snapshot.json +298 -0
- package/drizzle/meta/_journal.json +20 -0
- package/package.json +2 -1
- package/templates/_base/.init/.config/hooks/startup-context.sh +28 -0
- package/templates/_base/_skills/memory/SKILL.md +56 -13
- package/templates/_base/_skills/volute-agent/SKILL.md +27 -3
- package/templates/_base/home/VOLUTE.md +25 -0
- package/templates/_base/src/lib/format-prefix.ts +24 -0
- package/templates/_base/src/lib/sessions.ts +71 -0
- package/templates/_base/src/lib/startup.ts +132 -0
- package/templates/_base/src/lib/types.ts +3 -0
- package/templates/_base/src/lib/volute-server.ts +18 -2
- package/templates/agent-sdk/.init/.claude/settings.json +14 -0
- package/templates/agent-sdk/.init/.config/sessions.json +4 -0
- package/templates/agent-sdk/.init/CLAUDE.md +3 -2
- package/templates/agent-sdk/package.json.tmpl +1 -1
- package/templates/agent-sdk/src/agent.ts +101 -0
- package/templates/agent-sdk/src/lib/agent-sessions.ts +180 -0
- package/templates/agent-sdk/src/server.ts +33 -129
- package/templates/agent-sdk/volute-template.json +1 -1
- package/templates/pi/.init/.config/sessions.json +1 -0
- package/templates/pi/.init/AGENTS.md +2 -1
- package/templates/pi/src/agent.ts +61 -0
- package/templates/pi/src/lib/agent-sessions.ts +188 -0
- package/templates/pi/src/server.ts +28 -102
- package/templates/pi/volute-template.json +1 -1
- package/templates/agent-sdk/src/lib/agent.ts +0 -199
- package/templates/pi/src/lib/agent.ts +0 -205
- /package/templates/_base/.init/memory/{.gitkeep → journal/.gitkeep} +0 -0
- /package/templates/_base/{volute.json.tmpl → home/.config/volute.json.tmpl} +0 -0
- /package/templates/pi/{volute.json.tmpl → home/.config/volute.json.tmpl} +0 -0
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
findAgent,
|
|
8
8
|
removeAgent,
|
|
9
9
|
removeAllVariants
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-6UCG6MIX.js";
|
|
11
11
|
|
|
12
12
|
// src/commands/delete.ts
|
|
13
13
|
import { existsSync, rmSync } from "fs";
|
|
@@ -26,7 +26,7 @@ async function run(args) {
|
|
|
26
26
|
process.exit(1);
|
|
27
27
|
}
|
|
28
28
|
try {
|
|
29
|
-
const { daemonFetch } = await import("./daemon-client-
|
|
29
|
+
const { daemonFetch } = await import("./daemon-client-VN24HM5T.js");
|
|
30
30
|
const res = await daemonFetch(`/api/agents/${encodeURIComponent(name)}/stop`, {
|
|
31
31
|
method: "POST"
|
|
32
32
|
});
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
} from "./chunk-
|
|
3
|
+
voluteHome
|
|
4
|
+
} from "./chunk-6UCG6MIX.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/down.ts
|
|
7
7
|
import { existsSync, readFileSync, unlinkSync } from "fs";
|
|
8
8
|
import { resolve } from "path";
|
|
9
9
|
async function run(_args) {
|
|
10
|
-
const
|
|
10
|
+
const home = voluteHome();
|
|
11
|
+
const pidPath = resolve(home, "daemon.pid");
|
|
11
12
|
if (!existsSync(pidPath)) {
|
|
12
|
-
const configPath = resolve(
|
|
13
|
+
const configPath = resolve(home, "daemon.json");
|
|
13
14
|
let port = 4200;
|
|
14
15
|
if (existsSync(configPath)) {
|
|
15
16
|
try {
|
|
@@ -5,13 +5,13 @@ import {
|
|
|
5
5
|
readEnv,
|
|
6
6
|
sharedEnvPath,
|
|
7
7
|
writeEnv
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-KFNNHQK7.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-6UCG6MIX.js";
|
|
15
15
|
|
|
16
16
|
// src/commands/env.ts
|
|
17
17
|
function getEnvPath(agentName) {
|
|
@@ -51,9 +51,14 @@ async function promptValue(key) {
|
|
|
51
51
|
process.stdin.on("data", onData);
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
|
+
function maskValue(value) {
|
|
55
|
+
if (value.length <= 6) return "***";
|
|
56
|
+
return `${value.slice(0, 3)}...${value.slice(-3)}`;
|
|
57
|
+
}
|
|
54
58
|
async function run(args) {
|
|
55
59
|
const { positional, flags } = parseArgs(args, {
|
|
56
|
-
agent: { type: "string" }
|
|
60
|
+
agent: { type: "string" },
|
|
61
|
+
reveal: { type: "boolean" }
|
|
57
62
|
});
|
|
58
63
|
const subcommand = positional[0];
|
|
59
64
|
switch (subcommand) {
|
|
@@ -110,7 +115,8 @@ async function run(args) {
|
|
|
110
115
|
}
|
|
111
116
|
for (const key of [...allKeys].sort()) {
|
|
112
117
|
const scope = key in agent ? "agent" : "shared";
|
|
113
|
-
const
|
|
118
|
+
const raw = key in agent ? agent[key] : shared[key];
|
|
119
|
+
const value = flags.reveal ? raw : maskValue(raw);
|
|
114
120
|
console.log(`${key}=${value} [${scope}]`);
|
|
115
121
|
}
|
|
116
122
|
} else {
|
|
@@ -121,7 +127,8 @@ async function run(args) {
|
|
|
121
127
|
return;
|
|
122
128
|
}
|
|
123
129
|
for (const key of keys.sort()) {
|
|
124
|
-
|
|
130
|
+
const value = flags.reveal ? env[key] : maskValue(env[key]);
|
|
131
|
+
console.log(`${key}=${value} [shared]`);
|
|
125
132
|
}
|
|
126
133
|
}
|
|
127
134
|
break;
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
spawnServer
|
|
4
|
-
} from "./chunk-N4QN44LC.js";
|
|
5
2
|
import {
|
|
6
3
|
exec,
|
|
7
4
|
execInherit
|
|
8
5
|
} from "./chunk-XZN4WPNC.js";
|
|
6
|
+
import {
|
|
7
|
+
daemonFetch
|
|
8
|
+
} from "./chunk-4YXYAMFT.js";
|
|
9
9
|
import {
|
|
10
10
|
parseArgs
|
|
11
11
|
} from "./chunk-D424ZQGI.js";
|
|
12
12
|
import {
|
|
13
13
|
addVariant,
|
|
14
|
+
nextPort,
|
|
14
15
|
resolveAgent,
|
|
15
16
|
validateBranchName
|
|
16
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-6UCG6MIX.js";
|
|
17
18
|
|
|
18
19
|
// src/commands/fork.ts
|
|
19
20
|
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
|
@@ -41,17 +42,17 @@ async function run(args) {
|
|
|
41
42
|
process.exit(1);
|
|
42
43
|
}
|
|
43
44
|
const { dir: projectRoot } = resolveAgent(agentName);
|
|
44
|
-
const
|
|
45
|
-
if (existsSync(
|
|
46
|
-
console.error(`
|
|
45
|
+
const variantDir = resolve(projectRoot, ".variants", variantName);
|
|
46
|
+
if (existsSync(variantDir)) {
|
|
47
|
+
console.error(`Variant directory already exists: ${variantDir}`);
|
|
47
48
|
process.exit(1);
|
|
48
49
|
}
|
|
49
|
-
const parentDir = resolve(projectRoot, ".
|
|
50
|
+
const parentDir = resolve(projectRoot, ".variants");
|
|
50
51
|
if (!existsSync(parentDir)) {
|
|
51
52
|
mkdirSync(parentDir, { recursive: true });
|
|
52
53
|
}
|
|
53
54
|
try {
|
|
54
|
-
await exec("git", ["worktree", "add", "-b", variantName,
|
|
55
|
+
await exec("git", ["worktree", "add", "-b", variantName, variantDir], { cwd: projectRoot });
|
|
55
56
|
} catch (e) {
|
|
56
57
|
const msg = e instanceof Error ? e.message : String(e);
|
|
57
58
|
console.error(`Failed to create worktree: ${msg}`);
|
|
@@ -60,9 +61,9 @@ async function run(args) {
|
|
|
60
61
|
if (!json) console.log("Installing dependencies...");
|
|
61
62
|
try {
|
|
62
63
|
if (json) {
|
|
63
|
-
await exec("npm", ["install"], { cwd:
|
|
64
|
+
await exec("npm", ["install"], { cwd: variantDir });
|
|
64
65
|
} else {
|
|
65
|
-
await execInherit("npm", ["install"], { cwd:
|
|
66
|
+
await execInherit("npm", ["install"], { cwd: variantDir });
|
|
66
67
|
}
|
|
67
68
|
} catch (e) {
|
|
68
69
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -70,30 +71,39 @@ async function run(args) {
|
|
|
70
71
|
process.exit(1);
|
|
71
72
|
}
|
|
72
73
|
if (soul) {
|
|
73
|
-
writeFileSync(resolve(
|
|
74
|
-
}
|
|
75
|
-
let actualPort = null;
|
|
76
|
-
let pid = null;
|
|
77
|
-
if (!noStart) {
|
|
78
|
-
const requestedPort = port ?? 0;
|
|
79
|
-
if (!json) console.log("Starting server...");
|
|
80
|
-
const result = await spawnServer(worktreeDir, requestedPort, { detached: true });
|
|
81
|
-
if (!result) {
|
|
82
|
-
console.error("Server failed to start within timeout");
|
|
83
|
-
process.exit(1);
|
|
84
|
-
}
|
|
85
|
-
actualPort = result.actualPort;
|
|
86
|
-
pid = result.child.pid ?? null;
|
|
74
|
+
writeFileSync(resolve(variantDir, "home/SOUL.md"), soul);
|
|
87
75
|
}
|
|
76
|
+
const variantPort = port ?? nextPort();
|
|
88
77
|
const variant = {
|
|
89
78
|
name: variantName,
|
|
90
79
|
branch: variantName,
|
|
91
|
-
path:
|
|
92
|
-
port:
|
|
93
|
-
pid,
|
|
80
|
+
path: variantDir,
|
|
81
|
+
port: variantPort,
|
|
94
82
|
created: (/* @__PURE__ */ new Date()).toISOString()
|
|
95
83
|
};
|
|
96
84
|
addVariant(agentName, variant);
|
|
85
|
+
if (!noStart) {
|
|
86
|
+
if (!json) console.log("Starting variant via daemon...");
|
|
87
|
+
try {
|
|
88
|
+
const res = await daemonFetch(
|
|
89
|
+
`/api/agents/${encodeURIComponent(`${agentName}@${variantName}`)}/start`,
|
|
90
|
+
{
|
|
91
|
+
method: "POST"
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
if (!res.ok) {
|
|
95
|
+
const data = await res.json();
|
|
96
|
+
console.error(data.error ?? "Failed to start variant");
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
} catch {
|
|
100
|
+
console.error("Failed to start variant. Is the daemon running? (volute up)");
|
|
101
|
+
console.error(
|
|
102
|
+
`The variant was created but not started. Use: volute start ${agentName}@${variantName}`
|
|
103
|
+
);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
97
107
|
if (json) {
|
|
98
108
|
console.log(JSON.stringify(variant, null, 2));
|
|
99
109
|
} else {
|
|
@@ -101,10 +111,7 @@ async function run(args) {
|
|
|
101
111
|
Variant created: ${variantName}`);
|
|
102
112
|
console.log(` Branch: ${variant.branch}`);
|
|
103
113
|
console.log(` Path: ${variant.path}`);
|
|
104
|
-
|
|
105
|
-
console.log(` Port: ${actualPort}`);
|
|
106
|
-
console.log(` PID: ${pid}`);
|
|
107
|
-
}
|
|
114
|
+
console.log(` Port: ${variantPort}`);
|
|
108
115
|
}
|
|
109
116
|
}
|
|
110
117
|
export {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
daemonFetch
|
|
4
|
+
} from "./chunk-4YXYAMFT.js";
|
|
5
|
+
import {
|
|
6
|
+
parseArgs
|
|
7
|
+
} from "./chunk-D424ZQGI.js";
|
|
8
|
+
import "./chunk-6UCG6MIX.js";
|
|
9
|
+
|
|
10
|
+
// src/commands/history.ts
|
|
11
|
+
async function run(args) {
|
|
12
|
+
const { positional, flags } = parseArgs(args, {
|
|
13
|
+
channel: { type: "string" },
|
|
14
|
+
limit: { type: "string" }
|
|
15
|
+
});
|
|
16
|
+
const name = positional[0] || process.env.VOLUTE_AGENT;
|
|
17
|
+
if (!name) {
|
|
18
|
+
console.error("Usage: volute history [<agent>] [--channel <ch>] [--limit N]");
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
const params = new URLSearchParams();
|
|
22
|
+
if (flags.channel) params.set("channel", flags.channel);
|
|
23
|
+
if (flags.limit) params.set("limit", flags.limit);
|
|
24
|
+
const qs = params.toString();
|
|
25
|
+
const path = `/api/agents/${encodeURIComponent(name)}/history${qs ? `?${qs}` : ""}`;
|
|
26
|
+
const res = await daemonFetch(path);
|
|
27
|
+
if (!res.ok) {
|
|
28
|
+
let errorMsg = `Failed to get history: ${res.status}`;
|
|
29
|
+
try {
|
|
30
|
+
const data = await res.json();
|
|
31
|
+
if (data.error) errorMsg = data.error;
|
|
32
|
+
} catch {
|
|
33
|
+
}
|
|
34
|
+
console.error(errorMsg);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
const rows = await res.json();
|
|
38
|
+
for (const row of rows.reverse()) {
|
|
39
|
+
const time = new Date(row.created_at).toLocaleString();
|
|
40
|
+
const sender = row.sender ?? row.role;
|
|
41
|
+
console.log(`[${time}] [${row.channel}] ${sender}: ${row.content}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export {
|
|
45
|
+
run
|
|
46
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
spawnServer
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-MY74SUOL.js";
|
|
5
5
|
import {
|
|
6
6
|
exec,
|
|
7
7
|
execInherit
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
removeVariant,
|
|
16
16
|
resolveAgent,
|
|
17
17
|
validateBranchName
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-6UCG6MIX.js";
|
|
19
19
|
|
|
20
20
|
// src/commands/merge.ts
|
|
21
21
|
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
|
@@ -113,40 +113,30 @@ async function run(args) {
|
|
|
113
113
|
const status = (await exec("git", ["status", "--porcelain"], { cwd: variant.path })).trim();
|
|
114
114
|
if (status) {
|
|
115
115
|
console.log("Committing uncommitted changes in variant...");
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
116
|
+
try {
|
|
117
|
+
await exec("git", ["add", "-A"], { cwd: variant.path });
|
|
118
|
+
await exec("git", ["commit", "-m", "Auto-commit uncommitted changes before merge"], {
|
|
119
|
+
cwd: variant.path
|
|
120
|
+
});
|
|
121
|
+
} catch (err) {
|
|
122
|
+
console.error("Failed to auto-commit variant changes:", err);
|
|
123
|
+
console.error("Please commit or stash changes in the variant manually before merging.");
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
120
126
|
}
|
|
121
127
|
}
|
|
122
128
|
if (!flags["skip-verify"]) {
|
|
123
129
|
console.log("Verifying variant...");
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
process.kill(variant.pid, 0);
|
|
130
|
-
running = true;
|
|
131
|
-
} catch {
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
if (!running) {
|
|
135
|
-
console.log("Starting temporary server for verification...");
|
|
136
|
-
const result = await spawnServer(variant.path, 0, { detached: true });
|
|
137
|
-
if (!result) {
|
|
138
|
-
console.error("Failed to start server for verification. Use --skip-verify to skip.");
|
|
139
|
-
process.exit(1);
|
|
140
|
-
}
|
|
141
|
-
port = result.actualPort;
|
|
142
|
-
tempServerPid = result.child.pid;
|
|
130
|
+
console.log("Starting temporary server for verification...");
|
|
131
|
+
const result = await spawnServer(variant.path, 0, { detached: true });
|
|
132
|
+
if (!result) {
|
|
133
|
+
console.error("Failed to start server for verification. Use --skip-verify to skip.");
|
|
134
|
+
process.exit(1);
|
|
143
135
|
}
|
|
144
|
-
const verified = await verify(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
} catch {
|
|
149
|
-
}
|
|
136
|
+
const verified = await verify(result.actualPort);
|
|
137
|
+
try {
|
|
138
|
+
process.kill(result.child.pid);
|
|
139
|
+
} catch {
|
|
150
140
|
}
|
|
151
141
|
if (!verified) {
|
|
152
142
|
console.error("Verification failed. Fix issues or use --skip-verify to proceed anyway.");
|
|
@@ -154,11 +144,18 @@ async function run(args) {
|
|
|
154
144
|
}
|
|
155
145
|
console.log("Verification passed.");
|
|
156
146
|
}
|
|
157
|
-
|
|
147
|
+
const mainStatus = (await exec("git", ["status", "--porcelain"], { cwd: projectRoot })).trim();
|
|
148
|
+
if (mainStatus) {
|
|
149
|
+
console.log("Committing uncommitted changes in main...");
|
|
158
150
|
try {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
151
|
+
await exec("git", ["add", "-A"], { cwd: projectRoot });
|
|
152
|
+
await exec("git", ["commit", "-m", "Auto-commit uncommitted changes before merge"], {
|
|
153
|
+
cwd: projectRoot
|
|
154
|
+
});
|
|
155
|
+
} catch (err) {
|
|
156
|
+
console.error("Failed to auto-commit main changes:", err);
|
|
157
|
+
console.error("Please commit or stash your changes manually before merging.");
|
|
158
|
+
process.exit(1);
|
|
162
159
|
}
|
|
163
160
|
}
|
|
164
161
|
console.log(`Merging branch: ${variant.branch}`);
|
|
@@ -199,7 +196,7 @@ async function run(args) {
|
|
|
199
196
|
);
|
|
200
197
|
if (process.env.VOLUTE_SUPERVISOR) return;
|
|
201
198
|
try {
|
|
202
|
-
const { daemonFetch } = await import("./daemon-client-
|
|
199
|
+
const { daemonFetch } = await import("./daemon-client-VN24HM5T.js");
|
|
203
200
|
console.log("Restarting agent via daemon...");
|
|
204
201
|
const res = await daemonFetch(`/api/agents/${encodeURIComponent(agentName)}/restart`, {
|
|
205
202
|
method: "POST"
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
readNdjson
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-N4YNKR3Q.js";
|
|
5
5
|
import {
|
|
6
6
|
daemonFetch
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-4YXYAMFT.js";
|
|
8
|
+
import "./chunk-6UCG6MIX.js";
|
|
9
9
|
|
|
10
10
|
// src/commands/send.ts
|
|
11
11
|
import { userInfo } from "os";
|
|
@@ -16,13 +16,15 @@ async function run(args) {
|
|
|
16
16
|
console.error('Usage: volute send <name> "<message>"');
|
|
17
17
|
process.exit(1);
|
|
18
18
|
}
|
|
19
|
-
const
|
|
19
|
+
const agentSelf = process.env.VOLUTE_AGENT;
|
|
20
|
+
const sender = agentSelf || userInfo().username;
|
|
21
|
+
const channel = agentSelf ? "agent" : "cli";
|
|
20
22
|
const res = await daemonFetch(`/api/agents/${encodeURIComponent(name)}/message`, {
|
|
21
23
|
method: "POST",
|
|
22
24
|
headers: { "Content-Type": "application/json" },
|
|
23
25
|
body: JSON.stringify({
|
|
24
26
|
content: [{ type: "text", text: message }],
|
|
25
|
-
channel
|
|
27
|
+
channel,
|
|
26
28
|
sender
|
|
27
29
|
})
|
|
28
30
|
});
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
daemonFetch
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-4YXYAMFT.js";
|
|
5
5
|
import {
|
|
6
6
|
resolveAgent
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-6UCG6MIX.js";
|
|
8
8
|
|
|
9
9
|
// src/commands/start.ts
|
|
10
10
|
async function run(args) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
daemonFetch
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-4YXYAMFT.js";
|
|
5
|
+
import "./chunk-6UCG6MIX.js";
|
|
6
6
|
|
|
7
7
|
// src/commands/status.ts
|
|
8
8
|
async function run(args) {
|
|
@@ -44,6 +44,13 @@ async function run(args) {
|
|
|
44
44
|
for (const ch of agent.channels) {
|
|
45
45
|
console.log(`${ch.name}: ${ch.status}`);
|
|
46
46
|
}
|
|
47
|
+
if (agent.variants && agent.variants.length > 0) {
|
|
48
|
+
console.log("");
|
|
49
|
+
console.log("Variants:");
|
|
50
|
+
for (const v of agent.variants) {
|
|
51
|
+
console.log(` ${v.name} port=${v.port} ${v.status}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
47
54
|
}
|
|
48
55
|
export {
|
|
49
56
|
run
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
daemonFetch
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-4YXYAMFT.js";
|
|
5
5
|
import {
|
|
6
6
|
resolveAgent
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-6UCG6MIX.js";
|
|
8
8
|
|
|
9
9
|
// src/commands/stop.ts
|
|
10
10
|
async function run(args) {
|
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
parseArgs
|
|
4
4
|
} from "./chunk-D424ZQGI.js";
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
} from "./chunk-
|
|
6
|
+
voluteHome
|
|
7
|
+
} from "./chunk-6UCG6MIX.js";
|
|
8
8
|
|
|
9
9
|
// src/commands/up.ts
|
|
10
10
|
import { spawn } from "child_process";
|
|
@@ -13,10 +13,13 @@ import { dirname, resolve } from "path";
|
|
|
13
13
|
async function run(args) {
|
|
14
14
|
const { flags } = parseArgs(args, {
|
|
15
15
|
port: { type: "number" },
|
|
16
|
+
host: { type: "string" },
|
|
16
17
|
foreground: { type: "boolean" }
|
|
17
18
|
});
|
|
18
19
|
const port = flags.port ?? 4200;
|
|
19
|
-
const
|
|
20
|
+
const hostname = flags.host ?? "127.0.0.1";
|
|
21
|
+
const home = voluteHome();
|
|
22
|
+
const pidPath = resolve(home, "daemon.pid");
|
|
20
23
|
if (existsSync(pidPath)) {
|
|
21
24
|
try {
|
|
22
25
|
const pid = parseInt(readFileSync(pidPath, "utf-8").trim(), 10);
|
|
@@ -38,44 +41,25 @@ async function run(args) {
|
|
|
38
41
|
}
|
|
39
42
|
if (flags.foreground) {
|
|
40
43
|
const { startDaemon } = await import("./daemon.js");
|
|
41
|
-
await startDaemon({ port, foreground: true });
|
|
44
|
+
await startDaemon({ port, hostname, foreground: true });
|
|
42
45
|
return;
|
|
43
46
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const candidate = resolve(searchDir, "node_modules", ".bin", "tsx");
|
|
48
|
-
if (existsSync(candidate)) {
|
|
49
|
-
tsxBin = candidate;
|
|
50
|
-
break;
|
|
51
|
-
}
|
|
52
|
-
searchDir = dirname(searchDir);
|
|
53
|
-
}
|
|
54
|
-
if (!tsxBin) {
|
|
55
|
-
console.error("Could not find tsx binary.");
|
|
56
|
-
process.exit(1);
|
|
57
|
-
}
|
|
58
|
-
let daemonModule = "";
|
|
59
|
-
searchDir = dirname(new URL(import.meta.url).pathname);
|
|
60
|
-
for (let i = 0; i < 5; i++) {
|
|
61
|
-
const candidate = resolve(searchDir, "src", "daemon.ts");
|
|
62
|
-
if (existsSync(candidate)) {
|
|
63
|
-
daemonModule = candidate;
|
|
64
|
-
break;
|
|
65
|
-
}
|
|
66
|
-
searchDir = dirname(searchDir);
|
|
67
|
-
}
|
|
68
|
-
if (!daemonModule) {
|
|
69
|
-
console.error("Could not find daemon module.");
|
|
47
|
+
const daemonModule = resolve(dirname(new URL(import.meta.url).pathname), "daemon.js");
|
|
48
|
+
if (!existsSync(daemonModule)) {
|
|
49
|
+
console.error("Could not find daemon module. Run `npm run build` first.");
|
|
70
50
|
process.exit(1);
|
|
71
51
|
}
|
|
72
|
-
mkdirSync(
|
|
73
|
-
const logFile = resolve(
|
|
52
|
+
mkdirSync(home, { recursive: true });
|
|
53
|
+
const logFile = resolve(home, "daemon.log");
|
|
74
54
|
const logFd = openSync(logFile, "a");
|
|
75
|
-
const child = spawn(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
55
|
+
const child = spawn(
|
|
56
|
+
process.execPath,
|
|
57
|
+
[daemonModule, "--port", String(port), "--host", hostname],
|
|
58
|
+
{
|
|
59
|
+
stdio: ["ignore", logFd, logFd],
|
|
60
|
+
detached: true
|
|
61
|
+
}
|
|
62
|
+
);
|
|
79
63
|
child.unref();
|
|
80
64
|
const url = `http://localhost:${port}/api/health`;
|
|
81
65
|
const maxWait = 3e4;
|
|
@@ -84,7 +68,7 @@ async function run(args) {
|
|
|
84
68
|
try {
|
|
85
69
|
const res = await fetch(url);
|
|
86
70
|
if (res.ok) {
|
|
87
|
-
console.log(`Volute daemon running on
|
|
71
|
+
console.log(`Volute daemon running on ${hostname}:${port} (pid ${child.pid})`);
|
|
88
72
|
console.log(`Logs: ${logFile}`);
|
|
89
73
|
return;
|
|
90
74
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
spawnServer
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-MY74SUOL.js";
|
|
5
5
|
import {
|
|
6
6
|
composeTemplate,
|
|
7
7
|
copyTemplateToDir,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
import {
|
|
18
18
|
addVariant,
|
|
19
19
|
resolveAgent
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-6UCG6MIX.js";
|
|
21
21
|
|
|
22
22
|
// src/commands/upgrade.ts
|
|
23
23
|
import { existsSync, mkdirSync, rmSync } from "fs";
|
|
@@ -189,14 +189,12 @@ async function installAndVerify(agentName, worktreeDir) {
|
|
|
189
189
|
console.error("Server failed to start within timeout");
|
|
190
190
|
process.exit(1);
|
|
191
191
|
}
|
|
192
|
-
const { actualPort
|
|
193
|
-
const pid = child.pid ?? null;
|
|
192
|
+
const { actualPort } = result;
|
|
194
193
|
addVariant(agentName, {
|
|
195
194
|
name: VARIANT_NAME,
|
|
196
195
|
branch: VARIANT_NAME,
|
|
197
196
|
path: worktreeDir,
|
|
198
197
|
port: actualPort,
|
|
199
|
-
pid,
|
|
200
198
|
created: (/* @__PURE__ */ new Date()).toISOString()
|
|
201
199
|
});
|
|
202
200
|
console.log(`
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
readVariants,
|
|
8
8
|
resolveAgent,
|
|
9
9
|
writeVariants
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-6UCG6MIX.js";
|
|
11
11
|
|
|
12
12
|
// src/commands/variants.ts
|
|
13
13
|
async function run(args) {
|
|
@@ -39,7 +39,7 @@ async function run(args) {
|
|
|
39
39
|
);
|
|
40
40
|
const updated = results.map(({ status, ...v }) => ({
|
|
41
41
|
...v,
|
|
42
|
-
|
|
42
|
+
running: status === "running"
|
|
43
43
|
}));
|
|
44
44
|
writeVariants(name, updated);
|
|
45
45
|
if (json) {
|