volute 0.5.0 → 0.6.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.
Files changed (58) hide show
  1. package/dist/{agent-Z2B6EFEQ.js → agent-X7GJLBLW.js} +13 -9
  2. package/dist/{agent-manager-PXBKA2GK.js → agent-manager-JDVXU3ON.js} +4 -4
  3. package/dist/channel-SMCNOIVQ.js +262 -0
  4. package/dist/{chunk-5X7HGB6L.js → chunk-AOKAQGO4.js} +1 -1
  5. package/dist/{chunk-MXUCNIBG.js → chunk-BX7KI4S3.js} +68 -3
  6. package/dist/{chunk-MW2KFO3B.js → chunk-G6ZNGLUX.js} +3 -3
  7. package/dist/{chunk-HE67X4T6.js → chunk-H7AMDUIA.js} +1 -1
  8. package/dist/{chunk-7L4AN5D4.js → chunk-JR4UXCTO.js} +1 -1
  9. package/dist/{chunk-UX25Z2ND.js → chunk-UWHWAPGO.js} +7 -0
  10. package/dist/{chunk-UAVD2AHX.js → chunk-W76KWE23.js} +1 -1
  11. package/dist/chunk-ZZOOTYXK.js +583 -0
  12. package/dist/cli.js +18 -21
  13. package/dist/{connector-LYEMXQEV.js → connector-Y7JPNROO.js} +3 -3
  14. package/dist/connectors/discord.js +31 -4
  15. package/dist/connectors/slack.js +22 -3
  16. package/dist/connectors/telegram.js +34 -4
  17. package/dist/{create-RVCZN6HE.js → create-G525LWEA.js} +2 -2
  18. package/dist/{daemon-client-ZY6UUN2M.js → daemon-client-442IV43D.js} +2 -2
  19. package/dist/daemon.js +962 -525
  20. package/dist/{delete-3QH7VYIN.js → delete-2PH2CGDY.js} +3 -3
  21. package/dist/{down-O7IFZLVJ.js → down-FXWAN66A.js} +1 -1
  22. package/dist/{env-4D4REPJF.js → env-7GLUJCWS.js} +2 -2
  23. package/dist/{history-OEONB53Z.js → history-H72ZUIBN.js} +2 -2
  24. package/dist/{import-MXJB2EII.js → import-AVKQJDYC.js} +2 -2
  25. package/dist/{logs-DF342W4M.js → logs-EDGK26AK.js} +1 -1
  26. package/dist/{message-ADHWFHSI.js → message-SCOQDR3P.js} +2 -2
  27. package/dist/{package-VQOE7JNH.js → package-4DP4Y4UO.js} +1 -1
  28. package/dist/restart-O4ETYLJF.js +29 -0
  29. package/dist/{schedule-NAG6F463.js → schedule-S6QVC5ON.js} +2 -2
  30. package/dist/send-G7PE4DOJ.js +72 -0
  31. package/dist/{setup-RPRRGG2F.js → setup-F4TCWVSP.js} +2 -2
  32. package/dist/{start-TUOXDSFL.js → start-VHQ7LNWM.js} +2 -2
  33. package/dist/{status-A36EHRO4.js → status-QAJWXKMZ.js} +2 -2
  34. package/dist/{stop-AOJZLQ5X.js → stop-CAGCT5NI.js} +2 -2
  35. package/dist/{up-7ILD7GU7.js → up-CSX3ZUIU.js} +15 -3
  36. package/dist/{update-LPSIAWQ2.js → update-XSIX3GGP.js} +2 -2
  37. package/dist/{update-check-Y33QDCFL.js → update-check-5ZADDHCK.js} +2 -2
  38. package/dist/{upgrade-FX2TKJ2S.js → upgrade-YXKPWDRU.js} +2 -2
  39. package/dist/{variant-LAB67OC2.js → variant-4Z6W3PP6.js} +2 -2
  40. package/dist/web-assets/assets/index-D5PzIndO.js +308 -0
  41. package/dist/web-assets/index.html +1 -1
  42. package/package.json +1 -1
  43. package/templates/_base/.init/.config/scripts/session-reader.ts +59 -0
  44. package/templates/_base/_skills/sessions/SKILL.md +49 -0
  45. package/templates/_base/_skills/volute-agent/SKILL.md +13 -9
  46. package/templates/_base/src/lib/format-prefix.ts +6 -0
  47. package/templates/_base/src/lib/router.ts +30 -3
  48. package/templates/_base/src/lib/session-monitor.ts +400 -0
  49. package/templates/_base/src/lib/types.ts +2 -0
  50. package/templates/agent-sdk/src/agent.ts +16 -0
  51. package/templates/agent-sdk/src/lib/hooks/session-context.ts +32 -0
  52. package/templates/pi/src/agent.ts +7 -1
  53. package/templates/pi/src/lib/session-context-extension.ts +33 -0
  54. package/dist/channel-MK5OK2SI.js +0 -113
  55. package/dist/chunk-SMISE4SV.js +0 -226
  56. package/dist/conversation-ERXEQZTY.js +0 -163
  57. package/dist/send-66QMKRUH.js +0 -75
  58. package/dist/web-assets/assets/index-BbRmoxoA.js +0 -308
@@ -6,39 +6,42 @@ async function run(args) {
6
6
  const subcommand = args[0];
7
7
  switch (subcommand) {
8
8
  case "create":
9
- await import("./create-RVCZN6HE.js").then((m) => m.run(args.slice(1)));
9
+ await import("./create-G525LWEA.js").then((m) => m.run(args.slice(1)));
10
10
  break;
11
11
  case "start":
12
- await import("./start-TUOXDSFL.js").then((m) => m.run(args.slice(1)));
12
+ await import("./start-VHQ7LNWM.js").then((m) => m.run(args.slice(1)));
13
13
  break;
14
14
  case "stop":
15
- await import("./stop-AOJZLQ5X.js").then((m) => m.run(args.slice(1)));
15
+ await import("./stop-CAGCT5NI.js").then((m) => m.run(args.slice(1)));
16
+ break;
17
+ case "restart":
18
+ await import("./restart-O4ETYLJF.js").then((m) => m.run(args.slice(1)));
16
19
  break;
17
20
  case "delete":
18
- await import("./delete-3QH7VYIN.js").then((m) => m.run(args.slice(1)));
21
+ await import("./delete-2PH2CGDY.js").then((m) => m.run(args.slice(1)));
19
22
  break;
20
23
  case "list":
21
- await import("./status-A36EHRO4.js").then((m) => m.run(args.slice(1)));
24
+ await import("./status-QAJWXKMZ.js").then((m) => m.run(args.slice(1)));
22
25
  break;
23
26
  case "status": {
24
27
  const rest = args.slice(1);
25
28
  if (!rest[0] && process.env.VOLUTE_AGENT) {
26
29
  rest.unshift(process.env.VOLUTE_AGENT);
27
30
  }
28
- await import("./status-A36EHRO4.js").then((m) => m.run(rest));
31
+ await import("./status-QAJWXKMZ.js").then((m) => m.run(rest));
29
32
  break;
30
33
  }
31
34
  case "logs": {
32
35
  const rest = args.slice(1);
33
36
  const logsArgs = transformAgentFlag(rest);
34
- await import("./logs-DF342W4M.js").then((m) => m.run(logsArgs));
37
+ await import("./logs-EDGK26AK.js").then((m) => m.run(logsArgs));
35
38
  break;
36
39
  }
37
40
  case "upgrade":
38
- await import("./upgrade-FX2TKJ2S.js").then((m) => m.run(args.slice(1)));
41
+ await import("./upgrade-YXKPWDRU.js").then((m) => m.run(args.slice(1)));
39
42
  break;
40
43
  case "import":
41
- await import("./import-MXJB2EII.js").then((m) => m.run(args.slice(1)));
44
+ await import("./import-AVKQJDYC.js").then((m) => m.run(args.slice(1)));
42
45
  break;
43
46
  case "--help":
44
47
  case "-h":
@@ -61,6 +64,7 @@ function printUsage() {
61
64
  volute agent create <name> [--template <name>]
62
65
  volute agent start <name>
63
66
  volute agent stop [name]
67
+ volute agent restart [name]
64
68
  volute agent delete [name] [--force]
65
69
  volute agent list
66
70
  volute agent status [name]
@@ -3,10 +3,10 @@ import {
3
3
  AgentManager,
4
4
  getAgentManager,
5
5
  initAgentManager
6
- } from "./chunk-MW2KFO3B.js";
7
- import "./chunk-HE67X4T6.js";
8
- import "./chunk-UAVD2AHX.js";
9
- import "./chunk-UX25Z2ND.js";
6
+ } from "./chunk-G6ZNGLUX.js";
7
+ import "./chunk-H7AMDUIA.js";
8
+ import "./chunk-W76KWE23.js";
9
+ import "./chunk-UWHWAPGO.js";
10
10
  import "./chunk-K3NQKI34.js";
11
11
  export {
12
12
  AgentManager,
@@ -0,0 +1,262 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ readStdin
4
+ } from "./chunk-ZYGKG6VC.js";
5
+ import {
6
+ resolveAgentName
7
+ } from "./chunk-AZEL2IEK.js";
8
+ import {
9
+ CHANNELS,
10
+ getChannelDriver
11
+ } from "./chunk-ZZOOTYXK.js";
12
+ import {
13
+ loadMergedEnv
14
+ } from "./chunk-H7AMDUIA.js";
15
+ import {
16
+ writeChannelEntry
17
+ } from "./chunk-BX7KI4S3.js";
18
+ import {
19
+ parseArgs
20
+ } from "./chunk-D424ZQGI.js";
21
+ import {
22
+ daemonFetch
23
+ } from "./chunk-JR4UXCTO.js";
24
+ import {
25
+ resolveAgent
26
+ } from "./chunk-UWHWAPGO.js";
27
+ import "./chunk-K3NQKI34.js";
28
+
29
+ // src/commands/channel.ts
30
+ async function run(args) {
31
+ const subcommand = args[0];
32
+ switch (subcommand) {
33
+ case "read":
34
+ await readChannel(args.slice(1));
35
+ break;
36
+ case "send":
37
+ await sendChannel(args.slice(1));
38
+ break;
39
+ case "list":
40
+ await listChannels(args.slice(1));
41
+ break;
42
+ case "users":
43
+ await listUsers(args.slice(1));
44
+ break;
45
+ case "create":
46
+ await createChannel(args.slice(1));
47
+ break;
48
+ case "typing":
49
+ await typingChannel(args.slice(1));
50
+ break;
51
+ case "--help":
52
+ case "-h":
53
+ case void 0:
54
+ printUsage();
55
+ break;
56
+ default:
57
+ printUsage();
58
+ process.exit(1);
59
+ }
60
+ }
61
+ function printUsage() {
62
+ console.log(`Usage:
63
+ volute channel read <channel-uri> [--limit N] [--agent <name>]
64
+ volute channel send <channel-uri> "<message>" [--agent <name>]
65
+ volute channel list [<platform>] [--agent <name>]
66
+ volute channel users <platform> [--agent <name>]
67
+ volute channel create <platform> --participants user1,user2 [--name "..."] [--agent <name>]
68
+ volute channel typing <channel-uri> [--agent <name>]
69
+ echo "message" | volute channel send <channel-uri> [--agent <name>]`);
70
+ }
71
+ async function readChannel(args) {
72
+ const { positional, flags } = parseArgs(args, {
73
+ agent: { type: "string" },
74
+ limit: { type: "number" }
75
+ });
76
+ const uri = positional[0];
77
+ if (!uri) {
78
+ console.error("Usage: volute channel read <channel-uri> [--limit N] [--agent <name>]");
79
+ process.exit(1);
80
+ }
81
+ const agentName = resolveAgentName(flags);
82
+ const { platform } = parseUri(uri);
83
+ const driver = requireDriver(platform);
84
+ const { dir } = resolveAgent(agentName);
85
+ const env = { ...loadMergedEnv(dir), VOLUTE_AGENT: agentName, VOLUTE_AGENT_DIR: dir };
86
+ try {
87
+ const limit = flags.limit ?? 20;
88
+ const output = await driver.read(env, uri, limit);
89
+ console.log(output);
90
+ } catch (err) {
91
+ console.error(err instanceof Error ? err.message : String(err));
92
+ process.exit(1);
93
+ }
94
+ }
95
+ async function sendChannel(args) {
96
+ const { positional, flags } = parseArgs(args, {
97
+ agent: { type: "string" }
98
+ });
99
+ const uri = positional[0];
100
+ const message = positional[1] ?? await readStdin();
101
+ if (!uri || !message) {
102
+ console.error('Usage: volute channel send <channel-uri> "<message>" [--agent <name>]');
103
+ console.error(' echo "message" | volute channel send <channel-uri> [--agent <name>]');
104
+ process.exit(1);
105
+ }
106
+ const agentName = resolveAgentName(flags);
107
+ const { platform } = parseUri(uri);
108
+ const driver = requireDriver(platform);
109
+ const { dir } = resolveAgent(agentName);
110
+ const env = { ...loadMergedEnv(dir), VOLUTE_AGENT: agentName, VOLUTE_AGENT_DIR: dir };
111
+ try {
112
+ await driver.send(env, uri, message);
113
+ try {
114
+ await daemonFetch(`/api/agents/${encodeURIComponent(agentName)}/history`, {
115
+ method: "POST",
116
+ headers: { "Content-Type": "application/json" },
117
+ body: JSON.stringify({ channel: uri, content: message })
118
+ });
119
+ } catch (err) {
120
+ console.error(`Failed to persist to history: ${err instanceof Error ? err.message : err}`);
121
+ }
122
+ } catch (err) {
123
+ console.error(err instanceof Error ? err.message : String(err));
124
+ process.exit(1);
125
+ }
126
+ }
127
+ async function listChannels(args) {
128
+ const { positional, flags } = parseArgs(args, {
129
+ agent: { type: "string" }
130
+ });
131
+ const platform = positional[0];
132
+ const agentName = resolveAgentName(flags);
133
+ const { dir } = resolveAgent(agentName);
134
+ const env = { ...loadMergedEnv(dir), VOLUTE_AGENT: agentName, VOLUTE_AGENT_DIR: dir };
135
+ const platforms = platform ? [platform] : Object.keys(CHANNELS);
136
+ for (const p of platforms) {
137
+ const driver = getChannelDriver(p);
138
+ if (!driver?.listConversations) continue;
139
+ try {
140
+ const convs = await driver.listConversations(env);
141
+ for (const conv of convs) {
142
+ writeChannelEntry(dir, conv.id, {
143
+ platformId: conv.platformId,
144
+ platform: p,
145
+ name: conv.name,
146
+ type: conv.type
147
+ });
148
+ const parts = [conv.id.padEnd(24), conv.name.padEnd(28), conv.type];
149
+ if (conv.participantCount != null) {
150
+ parts.push(String(conv.participantCount));
151
+ }
152
+ console.log(parts.join(" "));
153
+ }
154
+ } catch (err) {
155
+ console.error(`${p}: ${err instanceof Error ? err.message : String(err)}`);
156
+ }
157
+ }
158
+ }
159
+ async function listUsers(args) {
160
+ const { positional, flags } = parseArgs(args, {
161
+ agent: { type: "string" }
162
+ });
163
+ const platform = positional[0];
164
+ if (!platform) {
165
+ console.error("Usage: volute channel users <platform> [--agent <name>]");
166
+ process.exit(1);
167
+ }
168
+ const driver = requireDriver(platform);
169
+ if (!driver.listUsers) {
170
+ console.error(`Platform ${platform} does not support listing users`);
171
+ process.exit(1);
172
+ }
173
+ const agentName = resolveAgentName(flags);
174
+ const { dir } = resolveAgent(agentName);
175
+ const env = { ...loadMergedEnv(dir), VOLUTE_AGENT: agentName, VOLUTE_AGENT_DIR: dir };
176
+ try {
177
+ const users = await driver.listUsers(env);
178
+ for (const user of users) {
179
+ console.log(`${user.username.padEnd(20)} ${user.id.padEnd(20)} ${user.type ?? ""}`);
180
+ }
181
+ } catch (err) {
182
+ console.error(err instanceof Error ? err.message : String(err));
183
+ process.exit(1);
184
+ }
185
+ }
186
+ async function createChannel(args) {
187
+ const { positional, flags } = parseArgs(args, {
188
+ agent: { type: "string" },
189
+ participants: { type: "string" },
190
+ name: { type: "string" }
191
+ });
192
+ const platform = positional[0];
193
+ if (!platform || !flags.participants) {
194
+ console.error(
195
+ 'Usage: volute channel create <platform> --participants user1,user2 [--name "..."] [--agent <name>]'
196
+ );
197
+ process.exit(1);
198
+ }
199
+ const driver = requireDriver(platform);
200
+ if (!driver.createConversation) {
201
+ console.error(`Platform ${platform} does not support creating conversations`);
202
+ process.exit(1);
203
+ }
204
+ const agentName = resolveAgentName(flags);
205
+ const { dir } = resolveAgent(agentName);
206
+ const env = { ...loadMergedEnv(dir), VOLUTE_AGENT: agentName, VOLUTE_AGENT_DIR: dir };
207
+ const participants = flags.participants.split(",").map((s) => s.trim());
208
+ try {
209
+ const slug = await driver.createConversation(env, participants, flags.name);
210
+ console.log(slug);
211
+ } catch (err) {
212
+ console.error(err instanceof Error ? err.message : String(err));
213
+ process.exit(1);
214
+ }
215
+ }
216
+ async function typingChannel(args) {
217
+ const { positional, flags } = parseArgs(args, {
218
+ agent: { type: "string" }
219
+ });
220
+ const uri = positional[0];
221
+ if (!uri) {
222
+ console.error("Usage: volute channel typing <channel-uri> [--agent <name>]");
223
+ process.exit(1);
224
+ }
225
+ const agentName = resolveAgentName(flags);
226
+ try {
227
+ const res = await daemonFetch(
228
+ `/api/agents/${encodeURIComponent(agentName)}/typing?channel=${encodeURIComponent(uri)}`
229
+ );
230
+ if (!res.ok) {
231
+ const body = await res.json().catch(() => ({}));
232
+ console.error(body.error ?? `Server responded with ${res.status}`);
233
+ process.exit(1);
234
+ }
235
+ const data = await res.json();
236
+ if (data.typing.length > 0) {
237
+ console.log(data.typing.join(", "));
238
+ }
239
+ } catch (err) {
240
+ console.error(err instanceof Error ? err.message : String(err));
241
+ process.exit(1);
242
+ }
243
+ }
244
+ function parseUri(uri) {
245
+ const colonIdx = uri.indexOf(":");
246
+ if (colonIdx === -1) {
247
+ console.error(`Invalid channel URI: ${uri} (expected format: platform:id)`);
248
+ process.exit(1);
249
+ }
250
+ return { platform: uri.slice(0, colonIdx), channelId: uri.slice(colonIdx + 1) };
251
+ }
252
+ function requireDriver(platform) {
253
+ const driver = getChannelDriver(platform);
254
+ if (!driver) {
255
+ console.error(`No channel driver for platform: ${platform}`);
256
+ process.exit(1);
257
+ }
258
+ return driver;
259
+ }
260
+ export {
261
+ run
262
+ };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  voluteHome
4
- } from "./chunk-UX25Z2ND.js";
4
+ } from "./chunk-UWHWAPGO.js";
5
5
 
6
6
  // src/lib/update-check.ts
7
7
  import { existsSync, readFileSync, writeFileSync } from "fs";
@@ -1,8 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ // src/lib/slugify.ts
4
+ function slugify(text) {
5
+ return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
6
+ }
7
+
3
8
  // src/connectors/sdk.ts
4
- import { existsSync, readFileSync } from "fs";
5
- import { resolve } from "path";
9
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
10
+ import { join, resolve } from "path";
6
11
  function loadEnv() {
7
12
  const agentPort = process.env.VOLUTE_AGENT_PORT;
8
13
  const agentName = process.env.VOLUTE_AGENT_NAME;
@@ -92,6 +97,15 @@ function onShutdown(cleanup) {
92
97
  process.on("SIGINT", handler);
93
98
  process.on("SIGTERM", handler);
94
99
  }
100
+ function reportTyping(env, channel, sender, active) {
101
+ fetch(`${env.baseUrl}/typing`, {
102
+ method: "POST",
103
+ headers: getHeaders(env),
104
+ body: JSON.stringify({ channel, sender, active })
105
+ }).catch((err) => {
106
+ console.warn(`[typing] failed to report for ${sender} on ${channel}: ${err}`);
107
+ });
108
+ }
95
109
  async function fireAndForget(env, payload) {
96
110
  try {
97
111
  const res = await fetch(`${env.baseUrl}/message`, {
@@ -157,12 +171,63 @@ async function handleAgentMessage(env, payload, handlers) {
157
171
  await handlers.onError(errMsg);
158
172
  }
159
173
  }
174
+ function buildChannelSlug(platform, meta) {
175
+ if (meta.isDM) {
176
+ if (meta.recipients && meta.recipients.length > 0) {
177
+ const sorted = meta.recipients.map(slugify).sort();
178
+ return `${platform}:@${sorted.join(",")}`;
179
+ }
180
+ if (meta.senderName) {
181
+ return `${platform}:@${slugify(meta.senderName)}`;
182
+ }
183
+ }
184
+ if (meta.channelName && meta.serverName) {
185
+ return `${platform}:${slugify(meta.serverName)}/${slugify(meta.channelName)}`;
186
+ }
187
+ if (meta.channelName) {
188
+ return `${platform}:${slugify(meta.channelName)}`;
189
+ }
190
+ if (meta.platformId) {
191
+ return `${platform}:${meta.platformId}`;
192
+ }
193
+ return `${platform}:unknown`;
194
+ }
195
+ function readChannelMap(agentDir) {
196
+ const filePath = join(agentDir, ".volute", "channels.json");
197
+ if (!existsSync(filePath)) return {};
198
+ try {
199
+ return JSON.parse(readFileSync(filePath, "utf-8"));
200
+ } catch {
201
+ return {};
202
+ }
203
+ }
204
+ function writeChannelEntry(agentDir, slug, entry) {
205
+ const voluteDir = join(agentDir, ".volute");
206
+ mkdirSync(voluteDir, { recursive: true });
207
+ const filePath = join(voluteDir, "channels.json");
208
+ const map = readChannelMap(agentDir);
209
+ map[slug] = entry;
210
+ writeFileSync(filePath, JSON.stringify(map, null, 2) + "\n");
211
+ }
212
+ function resolveChannelId(agentDir, slug) {
213
+ const map = readChannelMap(agentDir);
214
+ if (map[slug]) {
215
+ return map[slug].platformId;
216
+ }
217
+ const colonIndex = slug.indexOf(":");
218
+ return colonIndex >= 0 ? slug.slice(colonIndex + 1) : slug;
219
+ }
160
220
 
161
221
  export {
222
+ slugify,
162
223
  loadEnv,
163
224
  loadFollowedChannels,
164
225
  splitMessage,
165
226
  onShutdown,
227
+ reportTyping,
166
228
  fireAndForget,
167
- handleAgentMessage
229
+ handleAgentMessage,
230
+ buildChannelSlug,
231
+ writeChannelEntry,
232
+ resolveChannelId
168
233
  };
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  loadMergedEnv
4
- } from "./chunk-HE67X4T6.js";
4
+ } from "./chunk-H7AMDUIA.js";
5
5
  import {
6
6
  applyIsolation
7
- } from "./chunk-UAVD2AHX.js";
7
+ } from "./chunk-W76KWE23.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-UX25Z2ND.js";
16
+ } from "./chunk-UWHWAPGO.js";
17
17
 
18
18
  // src/lib/agent-manager.ts
19
19
  import { execFile, spawn } from "child_process";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  voluteHome
4
- } from "./chunk-UX25Z2ND.js";
4
+ } from "./chunk-UWHWAPGO.js";
5
5
 
6
6
  // src/lib/env.ts
7
7
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  voluteHome
4
- } from "./chunk-UX25Z2ND.js";
4
+ } from "./chunk-UWHWAPGO.js";
5
5
 
6
6
  // src/lib/daemon-client.ts
7
7
  import { existsSync, readFileSync } from "fs";
@@ -90,6 +90,12 @@ function nextPort() {
90
90
  if (port > 65535) throw new Error("No available ports \u2014 all ports 4100-65535 are allocated");
91
91
  return port;
92
92
  }
93
+ function daemonLoopback() {
94
+ const host = process.env.VOLUTE_DAEMON_HOSTNAME || "127.0.0.1";
95
+ if (host === "0.0.0.0") return "127.0.0.1";
96
+ if (host === "::") return "[::1]";
97
+ return host;
98
+ }
93
99
  function resolveAgent(name) {
94
100
  const [baseName, variantName] = name.split("@", 2);
95
101
  const entry = findAgent(baseName);
@@ -227,5 +233,6 @@ export {
227
233
  findAgent,
228
234
  agentDir,
229
235
  nextPort,
236
+ daemonLoopback,
230
237
  resolveAgent
231
238
  };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  validateAgentName
4
- } from "./chunk-UX25Z2ND.js";
4
+ } from "./chunk-UWHWAPGO.js";
5
5
 
6
6
  // src/lib/isolation.ts
7
7
  import { execFile, execFileSync } from "child_process";