volute 0.11.4 → 0.12.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-manager-AZUDAKCP.js → agent-manager-RMWXST3T.js} +1 -1
- package/dist/{chunk-YTOPX4PB.js → chunk-PHJCXAWJ.js} +11 -2
- package/dist/{chunk-N6MLQ26B.js → chunk-POLMWJFC.js} +10 -0
- package/dist/{chunk-LIPPXNIE.js → chunk-WKPMR5B2.js} +16 -17
- package/dist/cli.js +4 -4
- package/dist/connectors/discord.js +1 -1
- package/dist/connectors/slack.js +1 -1
- package/dist/connectors/telegram.js +1 -1
- package/dist/{daemon-restart-5W5AGBZ2.js → daemon-restart-IVJ7X4PF.js} +1 -1
- package/dist/daemon.js +37 -23
- package/dist/{package-KVUXPTEW.js → package-5LQNWBH7.js} +1 -1
- package/dist/{send-X6OQGSD6.js → send-V5ESR5O2.js} +2 -2
- package/dist/{up-365HL7UT.js → up-A6XT6AFX.js} +1 -1
- package/package.json +1 -1
- /package/dist/{chunk-D5EVQTGJ.js → chunk-IZEQ47HW.js} +0 -0
|
@@ -188,7 +188,13 @@ var AgentManager = class {
|
|
|
188
188
|
const logsDir = resolve(agentStateDir, "logs");
|
|
189
189
|
mkdirSync(logsDir, { recursive: true });
|
|
190
190
|
if (isIsolationEnabled()) {
|
|
191
|
-
|
|
191
|
+
try {
|
|
192
|
+
chownAgentDir(agentStateDir, baseName);
|
|
193
|
+
} catch (err) {
|
|
194
|
+
throw new Error(
|
|
195
|
+
`Cannot start agent ${name}: failed to set ownership on state directory ${agentStateDir}: ${err instanceof Error ? err.message : err}`
|
|
196
|
+
);
|
|
197
|
+
}
|
|
192
198
|
}
|
|
193
199
|
const logStream = new RotatingLog(resolve(logsDir, "agent.log"));
|
|
194
200
|
const agentEnv = loadMergedEnv(name);
|
|
@@ -200,8 +206,11 @@ var AgentManager = class {
|
|
|
200
206
|
VOLUTE_AGENT_DIR: dir,
|
|
201
207
|
VOLUTE_AGENT_PORT: String(port)
|
|
202
208
|
};
|
|
209
|
+
if (isIsolationEnabled()) {
|
|
210
|
+
env.HOME = resolve(dir, "home");
|
|
211
|
+
}
|
|
203
212
|
if (isIsolationEnabled() && process.env.CLAUDE_CONFIG_DIR) {
|
|
204
|
-
const agentClaudeDir = resolve(dir, ".claude");
|
|
213
|
+
const agentClaudeDir = resolve(dir, "home", ".claude");
|
|
205
214
|
try {
|
|
206
215
|
mkdirSync(agentClaudeDir, { recursive: true });
|
|
207
216
|
} catch (err) {
|
|
@@ -7,6 +7,15 @@ import {
|
|
|
7
7
|
function slugify(text) {
|
|
8
8
|
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
9
9
|
}
|
|
10
|
+
function buildVoluteSlug(opts) {
|
|
11
|
+
const isDM = opts.participants.length === 2;
|
|
12
|
+
if (isDM) {
|
|
13
|
+
const other = opts.participants.find((p) => p.username !== opts.agentUsername);
|
|
14
|
+
const otherSlug = other ? slugify(other.username) : "";
|
|
15
|
+
return otherSlug ? `volute:@${otherSlug}` : `volute:${opts.conversationId}`;
|
|
16
|
+
}
|
|
17
|
+
return opts.convTitle ? `volute:${slugify(opts.convTitle)}` : `volute:${opts.conversationId}`;
|
|
18
|
+
}
|
|
10
19
|
|
|
11
20
|
// src/connectors/sdk.ts
|
|
12
21
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -148,6 +157,7 @@ function resolveChannelId(agentName, slug) {
|
|
|
148
157
|
|
|
149
158
|
export {
|
|
150
159
|
slugify,
|
|
160
|
+
buildVoluteSlug,
|
|
151
161
|
loadEnv,
|
|
152
162
|
loadFollowedChannels,
|
|
153
163
|
splitMessage,
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
buildVoluteSlug,
|
|
3
4
|
resolveChannelId,
|
|
4
5
|
slugify,
|
|
5
6
|
splitMessage,
|
|
6
7
|
writeChannelEntry
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-POLMWJFC.js";
|
|
8
9
|
import {
|
|
9
10
|
voluteHome
|
|
10
11
|
} from "./chunk-DP2DX4WV.js";
|
|
@@ -452,26 +453,33 @@ async function listConversations4(env) {
|
|
|
452
453
|
const convs = await res.json();
|
|
453
454
|
const results = [];
|
|
454
455
|
for (const conv of convs) {
|
|
455
|
-
let
|
|
456
|
+
let participants = [];
|
|
456
457
|
try {
|
|
457
458
|
const pRes = await fetch(
|
|
458
459
|
`${url}/api/agents/${encodeURIComponent(agentName)}/conversations/${encodeURIComponent(conv.id)}/participants`,
|
|
459
460
|
{ headers }
|
|
460
461
|
);
|
|
461
462
|
if (pRes.ok) {
|
|
462
|
-
|
|
463
|
-
|
|
463
|
+
participants = await pRes.json();
|
|
464
|
+
} else {
|
|
465
|
+
console.error(`[volute] failed to fetch participants for ${conv.id}: HTTP ${pRes.status}`);
|
|
464
466
|
}
|
|
465
467
|
} catch (err) {
|
|
466
468
|
console.error(`[volute] failed to fetch participants for ${conv.id}:`, err);
|
|
467
469
|
}
|
|
468
|
-
const
|
|
470
|
+
const isDM = participants.length === 2;
|
|
471
|
+
const slug = buildVoluteSlug({
|
|
472
|
+
participants,
|
|
473
|
+
agentUsername: agentName,
|
|
474
|
+
convTitle: conv.title,
|
|
475
|
+
conversationId: conv.id
|
|
476
|
+
});
|
|
469
477
|
results.push({
|
|
470
478
|
id: slug,
|
|
471
479
|
platformId: conv.id,
|
|
472
480
|
name: conv.title ?? "(untitled)",
|
|
473
|
-
type:
|
|
474
|
-
participantCount
|
|
481
|
+
type: isDM ? "dm" : "group",
|
|
482
|
+
participantCount: participants.length
|
|
475
483
|
});
|
|
476
484
|
}
|
|
477
485
|
return results;
|
|
@@ -510,16 +518,7 @@ async function createConversation4(env, participants, name) {
|
|
|
510
518
|
throw new Error(data.error ?? `Failed to create conversation: ${res.status}`);
|
|
511
519
|
}
|
|
512
520
|
const conv = await res.json();
|
|
513
|
-
|
|
514
|
-
if (agentName) {
|
|
515
|
-
writeChannelEntry(agentName, slug, {
|
|
516
|
-
platformId: conv.id,
|
|
517
|
-
platform: "volute",
|
|
518
|
-
name: name ?? participants.join(", "),
|
|
519
|
-
type: participants.length <= 1 ? "dm" : "group"
|
|
520
|
-
});
|
|
521
|
-
}
|
|
522
|
-
return slug;
|
|
521
|
+
return `volute:${conv.id}`;
|
|
523
522
|
}
|
|
524
523
|
|
|
525
524
|
// src/lib/channels.ts
|
package/dist/cli.js
CHANGED
|
@@ -9,7 +9,7 @@ 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-5LQNWBH7.js");
|
|
13
13
|
console.log(pkg.version);
|
|
14
14
|
process.exit(0);
|
|
15
15
|
}
|
|
@@ -18,7 +18,7 @@ switch (command) {
|
|
|
18
18
|
await import("./agent-2AQPI3QV.js").then((m) => m.run(args));
|
|
19
19
|
break;
|
|
20
20
|
case "send":
|
|
21
|
-
await import("./send-
|
|
21
|
+
await import("./send-V5ESR5O2.js").then((m) => m.run(args));
|
|
22
22
|
break;
|
|
23
23
|
case "history":
|
|
24
24
|
await import("./history-NI5QP27M.js").then((m) => m.run(args));
|
|
@@ -39,13 +39,13 @@ switch (command) {
|
|
|
39
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-A6XT6AFX.js").then((m) => m.run(args));
|
|
43
43
|
break;
|
|
44
44
|
case "down":
|
|
45
45
|
await import("./down-O2EQJ5DO.js").then((m) => m.run(args));
|
|
46
46
|
break;
|
|
47
47
|
case "restart":
|
|
48
|
-
await import("./daemon-restart-
|
|
48
|
+
await import("./daemon-restart-IVJ7X4PF.js").then((m) => m.run(args));
|
|
49
49
|
break;
|
|
50
50
|
case "setup":
|
|
51
51
|
await import("./setup-7N4KYOYN.js").then((m) => m.run(args));
|
package/dist/connectors/slack.js
CHANGED
package/dist/daemon.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
initAgentManager,
|
|
7
7
|
loadJsonMap,
|
|
8
8
|
saveJsonMap
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-PHJCXAWJ.js";
|
|
10
10
|
import {
|
|
11
11
|
applyIsolation,
|
|
12
12
|
chownAgentDir,
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
import {
|
|
35
35
|
CHANNELS,
|
|
36
36
|
getChannelDriver
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-WKPMR5B2.js";
|
|
38
38
|
import {
|
|
39
39
|
exec,
|
|
40
40
|
gitExec,
|
|
@@ -47,9 +47,9 @@ import {
|
|
|
47
47
|
} from "./chunk-YY2QX2J6.js";
|
|
48
48
|
import "./chunk-D424ZQGI.js";
|
|
49
49
|
import {
|
|
50
|
-
|
|
50
|
+
buildVoluteSlug,
|
|
51
51
|
writeChannelEntry
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-POLMWJFC.js";
|
|
53
53
|
import {
|
|
54
54
|
addAgent,
|
|
55
55
|
addVariant,
|
|
@@ -248,8 +248,14 @@ var ConnectorManager = class {
|
|
|
248
248
|
const logsDir = resolve2(agentStateDir, "logs");
|
|
249
249
|
mkdirSync(logsDir, { recursive: true });
|
|
250
250
|
if (isIsolationEnabled()) {
|
|
251
|
-
|
|
252
|
-
|
|
251
|
+
try {
|
|
252
|
+
const [base] = agentName.split("@", 2);
|
|
253
|
+
chownAgentDir(agentStateDir, base);
|
|
254
|
+
} catch (err) {
|
|
255
|
+
throw new Error(
|
|
256
|
+
`Cannot start connector ${type} for ${agentName}: failed to set ownership on state directory ${agentStateDir}: ${err instanceof Error ? err.message : err}`
|
|
257
|
+
);
|
|
258
|
+
}
|
|
253
259
|
}
|
|
254
260
|
const logStream = new RotatingLog(resolve2(logsDir, `${type}.log`));
|
|
255
261
|
const agentEnv = loadMergedEnv(agentName);
|
|
@@ -1713,7 +1719,7 @@ var app = new Hono().post("/", requireAdmin, async (c) => {
|
|
|
1713
1719
|
createAgentUser(name);
|
|
1714
1720
|
chownAgentDir(dest, name);
|
|
1715
1721
|
const ids = isIsolationEnabled() ? await getAgentUserIds(name) : void 0;
|
|
1716
|
-
const env = ids ? { ...process.env, HOME: dest } : void 0;
|
|
1722
|
+
const env = ids ? { ...process.env, HOME: resolve9(dest, "home") } : void 0;
|
|
1717
1723
|
await exec("npm", ["install"], { cwd: dest, uid: ids?.uid, gid: ids?.gid, env });
|
|
1718
1724
|
let gitWarning;
|
|
1719
1725
|
try {
|
|
@@ -1809,7 +1815,7 @@ ${user.trimEnd()}
|
|
|
1809
1815
|
createAgentUser(name);
|
|
1810
1816
|
chownAgentDir(dest, name);
|
|
1811
1817
|
const ids = isIsolationEnabled() ? await getAgentUserIds(name) : void 0;
|
|
1812
|
-
const env = ids ? { ...process.env, HOME: dest } : void 0;
|
|
1818
|
+
const env = ids ? { ...process.env, HOME: resolve9(dest, "home") } : void 0;
|
|
1813
1819
|
await exec("npm", ["install"], { cwd: dest, uid: ids?.uid, gid: ids?.gid, env });
|
|
1814
1820
|
if (!hasMemory && dailyLogCount > 0) {
|
|
1815
1821
|
await consolidateMemory(dest);
|
|
@@ -3513,7 +3519,6 @@ var app13 = new Hono13().post("/:name/chat", zValidator3("json", chatSchema), as
|
|
|
3513
3519
|
}
|
|
3514
3520
|
const conv = await getConversation(conversationId);
|
|
3515
3521
|
const convTitle = conv?.title;
|
|
3516
|
-
const channel = convTitle ? `volute:${slugify(convTitle)}` : `volute:${conversationId}`;
|
|
3517
3522
|
const contentBlocks = [];
|
|
3518
3523
|
if (body.message) {
|
|
3519
3524
|
contentBlocks.push({ type: "text", text: body.message });
|
|
@@ -3527,13 +3532,21 @@ var app13 = new Hono13().post("/:name/chat", zValidator3("json", chatSchema), as
|
|
|
3527
3532
|
const participants = await getParticipants(conversationId);
|
|
3528
3533
|
const agentParticipants = participants.filter((p) => p.userType === "agent");
|
|
3529
3534
|
const participantNames = participants.map((p) => p.username);
|
|
3530
|
-
const { getAgentManager: getAgentManager2 } = await import("./agent-manager-
|
|
3535
|
+
const { getAgentManager: getAgentManager2 } = await import("./agent-manager-RMWXST3T.js");
|
|
3531
3536
|
const manager = getAgentManager2();
|
|
3532
3537
|
const runningAgents = agentParticipants.map((ap) => {
|
|
3533
3538
|
const agentKey = ap.username === baseName ? name : ap.username;
|
|
3534
3539
|
return manager.isRunning(agentKey) ? ap.username : null;
|
|
3535
3540
|
}).filter((n) => n !== null && n !== senderName);
|
|
3536
3541
|
const isDM = participants.length === 2;
|
|
3542
|
+
function channelForAgent(agentUsername) {
|
|
3543
|
+
return buildVoluteSlug({
|
|
3544
|
+
participants,
|
|
3545
|
+
agentUsername,
|
|
3546
|
+
convTitle,
|
|
3547
|
+
conversationId
|
|
3548
|
+
});
|
|
3549
|
+
}
|
|
3537
3550
|
const channelEntry = {
|
|
3538
3551
|
platformId: conversationId,
|
|
3539
3552
|
platform: "volute",
|
|
@@ -3542,25 +3555,26 @@ var app13 = new Hono13().post("/:name/chat", zValidator3("json", chatSchema), as
|
|
|
3542
3555
|
};
|
|
3543
3556
|
for (const ap of agentParticipants) {
|
|
3544
3557
|
try {
|
|
3545
|
-
writeChannelEntry(ap.username,
|
|
3558
|
+
writeChannelEntry(ap.username, channelForAgent(ap.username), channelEntry);
|
|
3546
3559
|
} catch (err) {
|
|
3547
3560
|
console.warn(`[chat] failed to write channel entry for ${ap.username}:`, err);
|
|
3548
3561
|
}
|
|
3549
3562
|
}
|
|
3550
|
-
const typingMap = getTypingMap();
|
|
3551
|
-
const currentlyTyping = typingMap.get(channel);
|
|
3552
|
-
const payload = JSON.stringify({
|
|
3553
|
-
content: contentBlocks,
|
|
3554
|
-
channel,
|
|
3555
|
-
conversationId,
|
|
3556
|
-
sender: senderName,
|
|
3557
|
-
participants: participantNames,
|
|
3558
|
-
participantCount: participants.length,
|
|
3559
|
-
isDM,
|
|
3560
|
-
...currentlyTyping.length > 0 ? { typing: currentlyTyping } : {}
|
|
3561
|
-
});
|
|
3562
3563
|
for (const agentName of runningAgents) {
|
|
3563
3564
|
const targetName = agentName === baseName ? name : agentName;
|
|
3565
|
+
const channel = channelForAgent(agentName);
|
|
3566
|
+
const typingMap = getTypingMap();
|
|
3567
|
+
const currentlyTyping = typingMap.get(channel);
|
|
3568
|
+
const payload = JSON.stringify({
|
|
3569
|
+
content: contentBlocks,
|
|
3570
|
+
channel,
|
|
3571
|
+
conversationId,
|
|
3572
|
+
sender: senderName,
|
|
3573
|
+
participants: participantNames,
|
|
3574
|
+
participantCount: participants.length,
|
|
3575
|
+
isDM,
|
|
3576
|
+
...currentlyTyping.length > 0 ? { typing: currentlyTyping } : {}
|
|
3577
|
+
});
|
|
3564
3578
|
daemonFetchInternal(`/api/agents/${encodeURIComponent(targetName)}/message`, payload).then(async (res) => {
|
|
3565
3579
|
if (!res.ok) {
|
|
3566
3580
|
const text2 = await res.text().catch(() => "");
|
|
@@ -4,7 +4,7 @@ import "./chunk-K3NQKI34.js";
|
|
|
4
4
|
// package.json
|
|
5
5
|
var package_default = {
|
|
6
6
|
name: "volute",
|
|
7
|
-
version: "0.
|
|
7
|
+
version: "0.12.0",
|
|
8
8
|
description: "CLI for creating and managing self-modifying AI agents powered by the Claude Agent SDK",
|
|
9
9
|
type: "module",
|
|
10
10
|
license: "MIT",
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
} from "./chunk-AZEL2IEK.js";
|
|
5
5
|
import {
|
|
6
6
|
getChannelDriver
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-WKPMR5B2.js";
|
|
8
8
|
import {
|
|
9
9
|
parseArgs
|
|
10
10
|
} from "./chunk-D424ZQGI.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-POLMWJFC.js";
|
|
12
12
|
import {
|
|
13
13
|
daemonFetch
|
|
14
14
|
} from "./chunk-STOEJOJO.js";
|
package/package.json
CHANGED
|
File without changes
|