volute 0.7.0 → 0.8.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.
Files changed (77) hide show
  1. package/README.md +16 -14
  2. package/dist/{agent-7JF7MT73.js → agent-YORVRB6I.js} +10 -10
  3. package/dist/{agent-manager-IMZ7ZMBF.js → agent-manager-CMMH5KQQ.js} +4 -4
  4. package/dist/{channel-SMCNOIVQ.js → channel-RDGHBFSI.js} +16 -56
  5. package/dist/{chunk-JR4UXCTO.js → chunk-23L3MKEV.js} +1 -1
  6. package/dist/{chunk-5SKQ6J7T.js → chunk-5C5JWR2L.js} +15 -7
  7. package/dist/{chunk-UWHWAPGO.js → chunk-DP2DX4WV.js} +9 -1
  8. package/dist/{chunk-7ACDT3P2.js → chunk-ECPQXRLB.js} +1 -2
  9. package/dist/{chunk-LLJNZPCU.js → chunk-HZ5LTOEJ.js} +1 -1
  10. package/dist/{chunk-W76KWE23.js → chunk-IQXBMFZG.js} +6 -4
  11. package/dist/{chunk-ZZOOTYXK.js → chunk-LIPPXNIE.js} +60 -74
  12. package/dist/{chunk-BX7KI4S3.js → chunk-N6MLQ26B.js} +23 -96
  13. package/dist/{chunk-H7AMDUIA.js → chunk-QF22MYDJ.js} +6 -5
  14. package/dist/{chunk-NKXULRSW.js → chunk-RT6Y7AR3.js} +1 -1
  15. package/dist/{chunk-62X577Y7.js → chunk-W6TMWYU3.js} +126 -73
  16. package/dist/{chunk-EG45HBSJ.js → chunk-XSJ27WEM.js} +1 -1
  17. package/dist/cli.js +22 -20
  18. package/dist/{connector-Y7JPNROO.js → connector-ZP6MEFF4.js} +3 -3
  19. package/dist/connectors/discord.js +18 -59
  20. package/dist/connectors/slack.js +21 -38
  21. package/dist/connectors/telegram.js +31 -49
  22. package/dist/{create-G525LWEA.js → create-HGJHLABX.js} +22 -17
  23. package/dist/{daemon-client-442IV43D.js → daemon-client-54J3EIZD.js} +2 -2
  24. package/dist/{daemon-restart-4HVEKYFY.js → daemon-restart-CPBLMMRI.js} +3 -3
  25. package/dist/daemon.js +342 -402
  26. package/dist/{delete-UOU4AFQN.js → delete-45TGQC4N.js} +10 -5
  27. package/dist/{down-AZVH5TCD.js → down-O4EWZTVA.js} +2 -2
  28. package/dist/{env-7GLUJCWS.js → env-KMNYGVZ2.js} +7 -9
  29. package/dist/{history-H72ZUIBN.js → history-PXJVYLVY.js} +2 -2
  30. package/dist/{import-AVKQJDYC.js → import-CNEDF3TD.js} +6 -6
  31. package/dist/{logs-EDGK26AK.js → logs-TZB3MTLZ.js} +5 -4
  32. package/dist/{package-T2WAVJOU.js → package-RJSONENE.js} +1 -1
  33. package/dist/{restart-O4ETYLJF.js → restart-KVH3TK5N.js} +2 -2
  34. package/dist/{schedule-S6QVC5ON.js → schedule-HCUCBNQI.js} +2 -2
  35. package/dist/send-BNC2S5BY.js +162 -0
  36. package/dist/{service-HZNIDNJF.js → service-XCADRKIS.js} +8 -1
  37. package/dist/{setup-F4TCWVSP.js → setup-32KH5KLN.js} +85 -26
  38. package/dist/{start-VHQ7LNWM.js → start-QU73YTJW.js} +2 -2
  39. package/dist/{status-QAJWXKMZ.js → status-Q6ZQJXNI.js} +2 -2
  40. package/dist/{stop-CAGCT5NI.js → stop-N7U5N6A7.js} +2 -2
  41. package/dist/{up-RWZF6MLT.js → up-V6EAA7OZ.js} +2 -2
  42. package/dist/{update-F7QWV2LB.js → update-EUCZ7XGG.js} +3 -3
  43. package/dist/{update-check-B4J6IEQ4.js → update-check-SM4244SU.js} +2 -2
  44. package/dist/{upgrade-YXKPWDRU.js → upgrade-CZF6PN7Y.js} +4 -4
  45. package/dist/{variant-4Z6W3PP6.js → variant-RKXPN5DH.js} +20 -46
  46. package/dist/web-assets/assets/index-D-3zx6vs.js +307 -0
  47. package/dist/web-assets/index.html +1 -1
  48. package/drizzle/0004_magical_silverclaw.sql +1 -0
  49. package/drizzle/meta/0004_snapshot.json +410 -0
  50. package/drizzle/meta/_journal.json +7 -0
  51. package/package.json +1 -1
  52. package/templates/_base/_skills/volute-agent/SKILL.md +32 -16
  53. package/templates/_base/home/.config/routes.json +4 -8
  54. package/templates/_base/home/VOLUTE.md +16 -14
  55. package/templates/_base/src/lib/auto-reply.ts +38 -0
  56. package/templates/_base/src/lib/daemon-client.ts +53 -0
  57. package/templates/_base/src/lib/router.ts +66 -14
  58. package/templates/_base/src/lib/routing.ts +48 -9
  59. package/templates/_base/src/lib/startup.ts +1 -25
  60. package/templates/_base/src/lib/types.ts +2 -1
  61. package/templates/_base/src/lib/volute-server.ts +29 -14
  62. package/templates/agent-sdk/src/agent.ts +53 -111
  63. package/templates/agent-sdk/src/lib/content.ts +41 -0
  64. package/templates/agent-sdk/src/lib/session-store.ts +43 -0
  65. package/templates/agent-sdk/src/lib/stream-consumer.ts +66 -0
  66. package/templates/agent-sdk/src/server.ts +5 -13
  67. package/templates/pi/.init/AGENTS.md +5 -5
  68. package/templates/pi/src/agent.ts +32 -84
  69. package/templates/pi/src/lib/content.ts +15 -0
  70. package/templates/pi/src/lib/event-handler.ts +74 -0
  71. package/templates/pi/src/lib/resolve-model.ts +21 -0
  72. package/templates/pi/src/server.ts +3 -7
  73. package/dist/chunk-B3R6L2GW.js +0 -24
  74. package/dist/chunk-ZYGKG6VC.js +0 -22
  75. package/dist/message-SCOQDR3P.js +0 -32
  76. package/dist/send-G7PE4DOJ.js +0 -72
  77. package/dist/web-assets/assets/index-B1CqjUYD.js +0 -308
@@ -2,11 +2,12 @@
2
2
  import {
3
3
  resolveChannelId,
4
4
  slugify,
5
+ splitMessage,
5
6
  writeChannelEntry
6
- } from "./chunk-BX7KI4S3.js";
7
+ } from "./chunk-N6MLQ26B.js";
7
8
  import {
8
9
  voluteHome
9
- } from "./chunk-UWHWAPGO.js";
10
+ } from "./chunk-DP2DX4WV.js";
10
11
  import {
11
12
  __export
12
13
  } from "./chunk-K3NQKI34.js";
@@ -20,6 +21,7 @@ __export(discord_exports, {
20
21
  read: () => read,
21
22
  send: () => send
22
23
  });
24
+ var DISCORD_MAX_LENGTH = 2e3;
23
25
  var API_BASE = "https://discord.com/api/v10";
24
26
  function requireToken(env) {
25
27
  const token = env.DISCORD_TOKEN;
@@ -50,16 +52,20 @@ async function read(env, channelSlug, limit) {
50
52
  async function send(env, channelSlug, message) {
51
53
  const token = requireToken(env);
52
54
  const channelId = resolveChannelId2(env, channelSlug);
53
- const res = await fetch(`${API_BASE}/channels/${channelId}/messages`, {
54
- method: "POST",
55
- headers: {
56
- Authorization: `Bot ${token}`,
57
- "Content-Type": "application/json"
58
- },
59
- body: JSON.stringify({ content: message })
60
- });
61
- if (!res.ok) {
62
- throw new Error(`Discord API error: ${res.status} ${res.statusText}`);
55
+ const chunks = splitMessage(message, DISCORD_MAX_LENGTH);
56
+ for (let i = 0; i < chunks.length; i++) {
57
+ const res = await fetch(`${API_BASE}/channels/${channelId}/messages`, {
58
+ method: "POST",
59
+ headers: {
60
+ Authorization: `Bot ${token}`,
61
+ "Content-Type": "application/json"
62
+ },
63
+ body: JSON.stringify({ content: chunks[i] })
64
+ });
65
+ if (!res.ok) {
66
+ const partial = i > 0 ? ` (${i}/${chunks.length} chunks were already sent)` : "";
67
+ throw new Error(`Discord API error: ${res.status} ${res.statusText}${partial}`);
68
+ }
63
69
  }
64
70
  }
65
71
  async function listConversations(env) {
@@ -134,9 +140,9 @@ async function createConversation(env, participants, _name) {
134
140
  }
135
141
  const dm = await res.json();
136
142
  const slug = `discord:@${slugify(participants[0])}`;
137
- const agentDir = env.VOLUTE_AGENT_DIR;
138
- if (agentDir) {
139
- writeChannelEntry(agentDir, slug, {
143
+ const agentName = env.VOLUTE_AGENT;
144
+ if (agentName) {
145
+ writeChannelEntry(agentName, slug, {
140
146
  platformId: dm.id,
141
147
  platform: "discord",
142
148
  name: participants[0],
@@ -155,6 +161,7 @@ __export(slack_exports, {
155
161
  read: () => read2,
156
162
  send: () => send2
157
163
  });
164
+ var SLACK_MAX_LENGTH = 4e3;
158
165
  var API_BASE2 = "https://slack.com/api";
159
166
  function requireToken2(env) {
160
167
  const token = env.SLACK_BOT_TOKEN;
@@ -191,10 +198,18 @@ async function read2(env, channelSlug, limit) {
191
198
  async function send2(env, channelSlug, message) {
192
199
  const token = requireToken2(env);
193
200
  const channelId = resolveChannelId2(env, channelSlug);
194
- await slackApi(token, "chat.postMessage", {
195
- channel: channelId,
196
- text: message
197
- });
201
+ const chunks = splitMessage(message, SLACK_MAX_LENGTH);
202
+ for (let i = 0; i < chunks.length; i++) {
203
+ try {
204
+ await slackApi(token, "chat.postMessage", {
205
+ channel: channelId,
206
+ text: chunks[i]
207
+ });
208
+ } catch (err) {
209
+ const partial = i > 0 ? ` (${i}/${chunks.length} chunks were already sent)` : "";
210
+ throw new Error(`${err instanceof Error ? err.message : err}${partial}`);
211
+ }
212
+ }
198
213
  }
199
214
  async function listConversations2(env) {
200
215
  const token = requireToken2(env);
@@ -256,7 +271,7 @@ async function createConversation2(env, participants, name) {
256
271
  if (!user) throw new Error(`User not found: ${p}`);
257
272
  ids.push(user.id);
258
273
  }
259
- const agentDir = env.VOLUTE_AGENT_DIR;
274
+ const agentName = env.VOLUTE_AGENT;
260
275
  if (name) {
261
276
  const createData = await slackApi(token, "conversations.create", {
262
277
  name,
@@ -272,8 +287,8 @@ async function createConversation2(env, participants, name) {
272
287
  const authData = await slackApi(token, "auth.test", {});
273
288
  const teamName = authData.team ?? "workspace";
274
289
  const slug2 = `slack:${slugify(teamName)}/${slugify(name)}`;
275
- if (agentDir) {
276
- writeChannelEntry(agentDir, slug2, {
290
+ if (agentName) {
291
+ writeChannelEntry(agentName, slug2, {
277
292
  platformId: channelId,
278
293
  platform: "slack",
279
294
  name,
@@ -287,8 +302,8 @@ async function createConversation2(env, participants, name) {
287
302
  });
288
303
  const platformId = openData.channel.id;
289
304
  const slug = participants.length === 1 ? `slack:@${slugify(participants[0])}` : `slack:@${participants.map(slugify).sort().join(",")}`;
290
- if (agentDir) {
291
- writeChannelEntry(agentDir, slug, {
305
+ if (agentName) {
306
+ writeChannelEntry(agentName, slug, {
292
307
  platformId,
293
308
  platform: "slack",
294
309
  name: participants.join(", "),
@@ -307,6 +322,7 @@ __export(telegram_exports, {
307
322
  read: () => read3,
308
323
  send: () => send3
309
324
  });
325
+ var TELEGRAM_MAX_LENGTH = 4096;
310
326
  var API_BASE3 = "https://api.telegram.org";
311
327
  function requireToken3(env) {
312
328
  const token = env.TELEGRAM_BOT_TOKEN;
@@ -315,20 +331,24 @@ function requireToken3(env) {
315
331
  }
316
332
  async function read3(_env, _channelSlug, _limit) {
317
333
  throw new Error(
318
- "Telegram Bot API does not support reading chat history. Use volute channel send instead."
334
+ "Telegram Bot API does not support reading chat history. Use volute send instead."
319
335
  );
320
336
  }
321
337
  async function send3(env, channelSlug, message) {
322
338
  const token = requireToken3(env);
323
339
  const chatId = resolveChannelId2(env, channelSlug);
324
- const res = await fetch(`${API_BASE3}/bot${token}/sendMessage`, {
325
- method: "POST",
326
- headers: { "Content-Type": "application/json" },
327
- body: JSON.stringify({ chat_id: chatId, text: message })
328
- });
329
- if (!res.ok) {
330
- const body = await res.text().catch(() => "");
331
- throw new Error(`Telegram API error: ${res.status} ${body}`);
340
+ const chunks = splitMessage(message, TELEGRAM_MAX_LENGTH);
341
+ for (let i = 0; i < chunks.length; i++) {
342
+ const res = await fetch(`${API_BASE3}/bot${token}/sendMessage`, {
343
+ method: "POST",
344
+ headers: { "Content-Type": "application/json" },
345
+ body: JSON.stringify({ chat_id: chatId, text: chunks[i] })
346
+ });
347
+ if (!res.ok) {
348
+ const body = await res.text().catch(() => "");
349
+ const partial = i > 0 ? ` (${i}/${chunks.length} chunks were already sent)` : "";
350
+ throw new Error(`Telegram API error: ${res.status} ${body}${partial}`);
351
+ }
332
352
  }
333
353
  }
334
354
  async function listConversations3() {
@@ -354,8 +374,7 @@ __export(volute_exports, {
354
374
  listConversations: () => listConversations4,
355
375
  listUsers: () => listUsers4,
356
376
  read: () => read4,
357
- send: () => send4,
358
- sendAndStream: () => sendAndStream
377
+ send: () => send4
359
378
  });
360
379
  import { existsSync, readFileSync } from "fs";
361
380
  import { resolve } from "path";
@@ -398,7 +417,7 @@ async function read4(env, channelSlug, limit) {
398
417
  return `${m.sender_name ?? m.role}: ${text}`;
399
418
  }).join("\n");
400
419
  }
401
- async function* sendAndStream(env, channelSlug, message) {
420
+ async function send4(env, channelSlug, message) {
402
421
  const agentName = env.VOLUTE_AGENT;
403
422
  if (!agentName) throw new Error("VOLUTE_AGENT not set");
404
423
  const conversationId = resolveChannelId2(env, channelSlug);
@@ -417,38 +436,6 @@ async function* sendAndStream(env, channelSlug, message) {
417
436
  const data = await res.json().catch(() => ({}));
418
437
  throw new Error(data.error ?? `Failed to send: ${res.status}`);
419
438
  }
420
- if (!res.body) return;
421
- const reader = res.body.getReader();
422
- const decoder = new TextDecoder();
423
- let buffer = "";
424
- try {
425
- while (true) {
426
- const { done, value } = await reader.read();
427
- if (done) break;
428
- buffer += decoder.decode(value, { stream: true });
429
- const lines = buffer.split("\n");
430
- buffer = lines.pop() ?? "";
431
- for (const line of lines) {
432
- if (!line.startsWith("data:")) continue;
433
- const data = line.slice(5).trim();
434
- if (!data) continue;
435
- try {
436
- const event = JSON.parse(data);
437
- yield event;
438
- if (event.type === "done") return;
439
- } catch (err) {
440
- console.error(`[volute] failed to parse SSE data: ${data}`, err);
441
- }
442
- }
443
- }
444
- } finally {
445
- reader.releaseLock();
446
- }
447
- }
448
- async function send4(env, channelSlug, message) {
449
- for await (const event of sendAndStream(env, channelSlug, message)) {
450
- if (event.type === "done") break;
451
- }
452
439
  }
453
440
  async function listConversations4(env) {
454
441
  const agentName = env.VOLUTE_AGENT;
@@ -524,9 +511,8 @@ async function createConversation4(env, participants, name) {
524
511
  }
525
512
  const conv = await res.json();
526
513
  const slug = name ? `volute:${slugify(name)}` : `volute:${conv.id}`;
527
- const agentDir = env.VOLUTE_AGENT_DIR;
528
- if (agentDir) {
529
- writeChannelEntry(agentDir, slug, {
514
+ if (agentName) {
515
+ writeChannelEntry(agentName, slug, {
530
516
  platformId: conv.id,
531
517
  platform: "volute",
532
518
  name: name ?? participants.join(", "),
@@ -569,12 +555,12 @@ function getChannelDriver(platform) {
569
555
  return CHANNELS[platform]?.driver ?? null;
570
556
  }
571
557
  function resolveChannelId2(env, slug) {
572
- const agentDir = env.VOLUTE_AGENT_DIR;
573
- if (!agentDir) {
558
+ const agentName = env.VOLUTE_AGENT;
559
+ if (!agentName) {
574
560
  const colonIdx = slug.indexOf(":");
575
561
  return colonIdx !== -1 ? slug.slice(colonIdx + 1) : slug;
576
562
  }
577
- return resolveChannelId(agentDir, slug);
563
+ return resolveChannelId(agentName, slug);
578
564
  }
579
565
 
580
566
  export {
@@ -1,4 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ stateDir
4
+ } from "./chunk-DP2DX4WV.js";
2
5
 
3
6
  // src/lib/slugify.ts
4
7
  function slugify(text) {
@@ -45,37 +48,6 @@ function splitMessage(text, maxLength) {
45
48
  if (text) chunks.push(text);
46
49
  return chunks;
47
50
  }
48
- async function* readNdjson(body) {
49
- const reader = body.getReader();
50
- const decoder = new TextDecoder();
51
- let buffer = "";
52
- try {
53
- while (true) {
54
- const { done, value } = await reader.read();
55
- if (done) break;
56
- buffer += decoder.decode(value, { stream: true });
57
- const lines = buffer.split("\n");
58
- buffer = lines.pop() || "";
59
- for (const line of lines) {
60
- if (!line.trim()) continue;
61
- try {
62
- yield JSON.parse(line);
63
- } catch {
64
- console.warn(`ndjson: skipping invalid line: ${line.slice(0, 100)}`);
65
- }
66
- }
67
- }
68
- if (buffer.trim()) {
69
- try {
70
- yield JSON.parse(buffer);
71
- } catch {
72
- console.warn(`ndjson: skipping invalid line: ${buffer.slice(0, 100)}`);
73
- }
74
- }
75
- } finally {
76
- reader.releaseLock();
77
- }
78
- }
79
51
  function getHeaders(env) {
80
52
  const headers = { "Content-Type": "application/json" };
81
53
  if (env.daemonUrl && env.daemonToken) {
@@ -106,28 +78,10 @@ function reportTyping(env, channel, sender, active) {
106
78
  console.warn(`[typing] failed to report for ${sender} on ${channel}: ${err}`);
107
79
  });
108
80
  }
109
- async function fireAndForget(env, payload) {
110
- try {
111
- const res = await fetch(`${env.baseUrl}/message`, {
112
- method: "POST",
113
- headers: getHeaders(env),
114
- body: JSON.stringify(payload)
115
- });
116
- if (!res.ok) {
117
- console.error(`fireAndForget: agent returned ${res.status}`);
118
- }
119
- if (res.body) {
120
- const reader = res.body.getReader();
121
- while (!(await reader.read()).done) {
122
- }
123
- }
124
- } catch (err) {
125
- console.error(`Failed to forward message: ${err}`);
126
- }
127
- }
128
- async function handleAgentMessage(env, payload, handlers) {
81
+ async function sendToAgent(env, payload) {
82
+ const url = `${env.baseUrl}/message`;
129
83
  try {
130
- const res = await fetch(`${env.baseUrl}/message`, {
84
+ const res = await fetch(url, {
131
85
  method: "POST",
132
86
  headers: getHeaders(env),
133
87
  body: JSON.stringify(payload)
@@ -135,40 +89,13 @@ async function handleAgentMessage(env, payload, handlers) {
135
89
  if (!res.ok) {
136
90
  const body = await res.text().catch(() => "");
137
91
  console.error(`Agent returned ${res.status}: ${body}`);
138
- await handlers.onError(`Error: agent returned ${res.status}`);
139
- return;
140
- }
141
- if (!res.body) {
142
- await handlers.onError("Error: no response from agent");
143
- return;
144
- }
145
- let accumulated = "";
146
- const pendingImages = [];
147
- for await (const event of readNdjson(res.body)) {
148
- if (event.type === "text") {
149
- accumulated += event.content;
150
- } else if (event.type === "image") {
151
- pendingImages.push({ data: event.data, media_type: event.media_type });
152
- } else if (event.type === "tool_use") {
153
- const text2 = accumulated.trim();
154
- accumulated = "";
155
- const images2 = pendingImages.splice(0);
156
- if (text2 || images2.length > 0) {
157
- await handlers.onFlush(text2, images2);
158
- }
159
- } else if (event.type === "done") {
160
- break;
161
- }
162
- }
163
- const text = accumulated.trim();
164
- const images = pendingImages.splice(0);
165
- if (text || images.length > 0) {
166
- await handlers.onFlush(text, images);
92
+ return { ok: false, error: `Agent returned ${res.status}` };
167
93
  }
94
+ return { ok: true };
168
95
  } catch (err) {
169
- console.error(`Failed to reach agent at ${env.baseUrl}/message:`, err);
170
- const errMsg = err instanceof TypeError && err.cause?.code === "ECONNREFUSED" ? "Agent is not running" : `Error: ${err}`;
171
- await handlers.onError(errMsg);
96
+ console.error(`Failed to forward message: ${err}`);
97
+ const isConnRefused = err instanceof TypeError && err.cause?.code === "ECONNREFUSED";
98
+ return { ok: false, error: isConnRefused ? "Agent is not running" : "Failed to reach agent" };
172
99
  }
173
100
  }
174
101
  function buildChannelSlug(platform, meta) {
@@ -192,25 +119,26 @@ function buildChannelSlug(platform, meta) {
192
119
  }
193
120
  return `${platform}:unknown`;
194
121
  }
195
- function readChannelMap(agentDir) {
196
- const filePath = join(agentDir, ".volute", "channels.json");
122
+ function readChannelMap(agentName) {
123
+ const filePath = join(stateDir(agentName), "channels.json");
197
124
  if (!existsSync(filePath)) return {};
198
125
  try {
199
126
  return JSON.parse(readFileSync(filePath, "utf-8"));
200
- } catch {
127
+ } catch (err) {
128
+ console.error(`[sdk] failed to parse ${filePath}:`, err);
201
129
  return {};
202
130
  }
203
131
  }
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);
132
+ function writeChannelEntry(agentName, slug, entry) {
133
+ const dir = stateDir(agentName);
134
+ mkdirSync(dir, { recursive: true });
135
+ const filePath = join(dir, "channels.json");
136
+ const map = readChannelMap(agentName);
209
137
  map[slug] = entry;
210
138
  writeFileSync(filePath, JSON.stringify(map, null, 2) + "\n");
211
139
  }
212
- function resolveChannelId(agentDir, slug) {
213
- const map = readChannelMap(agentDir);
140
+ function resolveChannelId(agentName, slug) {
141
+ const map = readChannelMap(agentName);
214
142
  if (map[slug]) {
215
143
  return map[slug].platformId;
216
144
  }
@@ -225,8 +153,7 @@ export {
225
153
  splitMessage,
226
154
  onShutdown,
227
155
  reportTyping,
228
- fireAndForget,
229
- handleAgentMessage,
156
+ sendToAgent,
230
157
  buildChannelSlug,
231
158
  writeChannelEntry,
232
159
  resolveChannelId
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ stateDir,
3
4
  voluteHome
4
- } from "./chunk-UWHWAPGO.js";
5
+ } from "./chunk-DP2DX4WV.js";
5
6
 
6
7
  // src/lib/env.ts
7
8
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -9,8 +10,8 @@ import { dirname, resolve } from "path";
9
10
  function sharedEnvPath() {
10
11
  return resolve(voluteHome(), "env.json");
11
12
  }
12
- function agentEnvPath(agentDir) {
13
- return resolve(agentDir, ".volute", "env.json");
13
+ function agentEnvPath(agentName) {
14
+ return resolve(stateDir(agentName), "env.json");
14
15
  }
15
16
  function readEnv(path) {
16
17
  if (!existsSync(path)) return {};
@@ -25,9 +26,9 @@ function writeEnv(path, env) {
25
26
  writeFileSync(path, `${JSON.stringify(env, null, 2)}
26
27
  `, { mode: 384 });
27
28
  }
28
- function loadMergedEnv(agentDir) {
29
+ function loadMergedEnv(agentName) {
29
30
  const shared = readEnv(sharedEnvPath());
30
- const agent = readEnv(agentEnvPath(agentDir));
31
+ const agent = readEnv(agentEnvPath(agentName));
31
32
  return { ...shared, ...agent };
32
33
  }
33
34
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  voluteHome
4
- } from "./chunk-UWHWAPGO.js";
4
+ } from "./chunk-DP2DX4WV.js";
5
5
 
6
6
  // src/lib/update-check.ts
7
7
  import { existsSync, readFileSync, writeFileSync } from "fs";