volute 0.25.0 → 0.27.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 (145) hide show
  1. package/README.md +28 -33
  2. package/dist/{activity-events-4O37J7PD.js → activity-events-BBIEA2F4.js} +2 -3
  3. package/dist/api.d.ts +886 -220
  4. package/dist/{archive-4ZQYK5MN.js → archive-UA4BDFXQ.js} +2 -2
  5. package/dist/{auth-HM2RSPY7.js → auth-D3OT2ARB.js} +3 -3
  6. package/dist/bridge-FQHZL3MC.js +206 -0
  7. package/dist/chat-MHJ3L6JQ.js +58 -0
  8. package/dist/{chunk-PHU4DEAJ.js → chunk-2WPW7OT6.js} +3 -3
  9. package/dist/{chunk-BOTQ25QT.js → chunk-2YP2TVDT.js} +138 -56
  10. package/dist/{chunk-DG7TO7EE.js → chunk-4WXYUOAK.js} +5 -7
  11. package/dist/{chunk-JTDFJWI2.js → chunk-AW7PFDVN.js} +5 -5
  12. package/dist/{chunk-2767L2RZ.js → chunk-EHYDTZTF.js} +6 -6
  13. package/dist/{chunk-ZSH4G2P5.js → chunk-GIE6CSN5.js} +17 -17
  14. package/dist/chunk-H7OZRFJB.js +432 -0
  15. package/dist/{chunk-ON3FF5JA.js → chunk-HDN7MNGD.js} +3 -3
  16. package/dist/chunk-IAYBDWVG.js +477 -0
  17. package/dist/chunk-IKRVFPWU.js +83 -0
  18. package/dist/{chunk-TRQEV3CD.js → chunk-JGFVMROS.js} +32 -6
  19. package/dist/{chunk-PHHKNGA3.js → chunk-JKOWNZ4P.js} +3 -3
  20. package/dist/{chunk-E7GOKNOT.js → chunk-K5NAC55T.js} +1 -1
  21. package/dist/{chunk-HFCBO2GL.js → chunk-KDGS53OS.js} +4 -4
  22. package/dist/chunk-KTLFDYPT.js +61 -0
  23. package/dist/{chunk-3AIBT4TW.js → chunk-LAC664WU.js} +30 -4
  24. package/dist/{chunk-PMX4EIJK.js → chunk-OQZH4PBB.js} +467 -1054
  25. package/dist/{chunk-SHSWYG2J.js → chunk-PHSAT7YL.js} +71 -58
  26. package/dist/chunk-RKQEHRBB.js +177 -0
  27. package/dist/{chunk-RVKR2R7F.js → chunk-SSI47XP2.js} +10 -2
  28. package/dist/chunk-T6HKBWXZ.js +23 -0
  29. package/dist/chunk-USUXRNVD.js +113 -0
  30. package/dist/{chunk-BFK6SOEJ.js → chunk-VIVMW2H2.js} +4 -4
  31. package/dist/{chunk-KTJGZ7M7.js → chunk-XBLSAVJF.js} +1 -1
  32. package/dist/chunk-ZYGKG6VC.js +22 -0
  33. package/dist/cli.js +51 -32
  34. package/dist/{cloud-sync-PPBBJDY6.js → cloud-sync-T7M3ESC3.js} +15 -12
  35. package/dist/connectors/discord-bridge.js +158 -0
  36. package/dist/connectors/slack-bridge.js +119 -0
  37. package/dist/connectors/telegram-bridge.js +133 -0
  38. package/dist/conversations-M2K4253F.js +55 -0
  39. package/dist/create-D7J73A6H.js +45 -0
  40. package/dist/{create-VDQJER52.js → create-QWV73WXD.js} +1 -1
  41. package/dist/{daemon-client-JOVQZ52X.js → daemon-client-I42FK2BF.js} +2 -2
  42. package/dist/{daemon-restart-FDNOZEAD.js → daemon-restart-M2QTYMEG.js} +7 -6
  43. package/dist/daemon.js +2247 -1085
  44. package/dist/db-IC4J52XQ.js +8 -0
  45. package/dist/{delete-2MRR4JX5.js → delete-4JYGD4VN.js} +1 -1
  46. package/dist/down-LVBXEULC.js +14 -0
  47. package/dist/{env-2FPOZK37.js → env-YJMUMFIY.js} +5 -5
  48. package/dist/{export-IKFAPRAO.js → export-BOJQWBMA.js} +4 -4
  49. package/dist/{file-KT3UIQM3.js → file-CR36YUPD.js} +4 -4
  50. package/dist/{history-46WZN5CN.js → history-XKRTAFS2.js} +7 -7
  51. package/dist/{import-TH26J76F.js → import-SRTQXBGH.js} +4 -4
  52. package/dist/join-J4QU42DL.js +66 -0
  53. package/dist/list-R73GENNL.js +40 -0
  54. package/dist/{log-6SGSSR3D.js → log-ABYNVYJ3.js} +4 -4
  55. package/dist/login-3QZNR2DF.js +46 -0
  56. package/dist/{login-UO6AOVEA.js → login-XX37I52P.js} +3 -3
  57. package/dist/logout-T53VKCPU.js +39 -0
  58. package/dist/{logout-UKD5LA37.js → logout-W4KOOBIT.js} +2 -2
  59. package/dist/{logs-HRBONI5I.js → logs-U35JR2KE.js} +7 -7
  60. package/dist/{merge-KSFJKX6T.js → merge-LNSMSAOF.js} +4 -4
  61. package/dist/message-delivery-LDXLGERA.js +25 -0
  62. package/dist/migrate-registry-to-db-XC7T5B7P.js +110 -0
  63. package/dist/{mind-YVWAHL2A.js → mind-DI33C74K.js} +25 -25
  64. package/dist/{mind-activity-tracker-NMDDEV3K.js → mind-activity-tracker-EN6XNXPF.js} +3 -4
  65. package/dist/{mind-manager-4NDNAYAB.js → mind-manager-M6EMUW5I.js} +6 -5
  66. package/dist/{mind-sleep-GHPTSAYN.js → mind-sleep-BTSWQNAC.js} +4 -4
  67. package/dist/{mind-wake-BJDJFMDF.js → mind-wake-SBAKIDVP.js} +4 -4
  68. package/dist/notes-XCER3I7M.js +220 -0
  69. package/dist/{package-3HF5MXU2.js → package-7WY6VKU3.js} +2 -1
  70. package/dist/{pages-Y6DRWUOJ.js → pages-6EBS6CBR.js} +2 -2
  71. package/dist/{publish-EEKTZBHW.js → publish-66UB2ZFY.js} +5 -5
  72. package/dist/{pull-D32SPFVU.js → pull-XCHJTM5M.js} +4 -4
  73. package/dist/read-36UFXN3G.js +46 -0
  74. package/dist/{register-U2UO6TC4.js → register-6B2CXTYM.js} +3 -3
  75. package/dist/{registry-D2BSQ2X5.js → registry-NDNOOYG4.js} +15 -9
  76. package/dist/{restart-5BMNV7KU.js → restart-6ESL3NBO.js} +6 -6
  77. package/dist/sandbox-TGBX22DS.js +19 -0
  78. package/dist/{schedule-YEFDLVMJ.js → schedule-QTJMFATP.js} +7 -7
  79. package/dist/{seed-6FEKB3YC.js → seed-SSUCYYDF.js} +2 -2
  80. package/dist/{send-IISDYFCL.js → send-ZNCJDSRP.js} +28 -36
  81. package/dist/service-6LIN3F3K.js +122 -0
  82. package/dist/setup-JG4QAEBV.js +371 -0
  83. package/dist/setup-JHL5ZEST.js +17 -0
  84. package/dist/{shared-LWMNTTZN.js → shared-ML5I4Q2A.js} +4 -4
  85. package/dist/{skill-T3EMR6IR.js → skill-AUAQTSP5.js} +7 -7
  86. package/dist/skills/dreaming/SKILL.md +68 -0
  87. package/dist/skills/dreaming/references/INSTALL.md +56 -0
  88. package/dist/skills/dreaming/scripts/dream.ts +289 -0
  89. package/dist/skills/dreaming/scripts/wake-context-dreams.sh +30 -0
  90. package/dist/skills/notes/SKILL.md +34 -0
  91. package/dist/skills/orientation/SKILL.md +3 -3
  92. package/dist/skills/volute-mind/SKILL.md +32 -30
  93. package/dist/sleep-manager-MWYHM5HV.js +29 -0
  94. package/dist/split-TKJ5OT3P.js +63 -0
  95. package/dist/{sprout-QJVGJDSH.js → sprout-IJVVKSJ2.js} +6 -7
  96. package/dist/{start-C7XITZ5O.js → start-EUJSS5R4.js} +4 -4
  97. package/dist/{status-SIRPLEZC.js → status-77YEPHMW.js} +5 -5
  98. package/dist/{status-LYS4NUOZ.js → status-7GA4SM4Y.js} +4 -4
  99. package/dist/{status-LV34BG6G.js → status-THLOBLWG.js} +2 -2
  100. package/dist/{stop-CVKBSLXY.js → stop-3XAITBBF.js} +6 -6
  101. package/dist/{tailscale-AJ4VL5XK.js → tailscale-NY5MUMY3.js} +1 -1
  102. package/dist/up-NKSMXBWR.js +17 -0
  103. package/dist/{update-7XCZMYBT.js → update-PTSH22AZ.js} +11 -11
  104. package/dist/{update-check-F5Z3ALXX.js → update-check-64FWC4Y2.js} +2 -2
  105. package/dist/{upgrade-7RUIXGOO.js → upgrade-HA47CS4C.js} +12 -5
  106. package/dist/variant-7TGZHOU3.js +41 -0
  107. package/dist/{version-notify-AZQMC32A.js → version-notify-5Z4MNR6M.js} +26 -28
  108. package/dist/web-assets/assets/index-CI5wgghI.css +1 -0
  109. package/dist/web-assets/assets/index-is5CvJWH.js +75 -0
  110. package/dist/web-assets/favicon.png +0 -0
  111. package/dist/web-assets/index.html +2 -2
  112. package/drizzle/0015_notes.sql +23 -0
  113. package/drizzle/0016_note_reactions_and_replies.sql +15 -0
  114. package/drizzle/0017_minds.sql +16 -0
  115. package/drizzle/meta/_journal.json +21 -0
  116. package/package.json +2 -1
  117. package/templates/_base/.init/.config/hooks/wake-context.sh +7 -0
  118. package/templates/_base/.init/.config/prompts.json +2 -2
  119. package/templates/_base/home/VOLUTE.md +5 -5
  120. package/templates/_base/src/lib/startup.ts +10 -2
  121. package/templates/claude/src/agent.ts +51 -1
  122. package/templates/claude/src/server.ts +1 -0
  123. package/templates/pi/package.json.tmpl +1 -0
  124. package/templates/pi/src/agent.ts +48 -1
  125. package/templates/pi/src/lib/subagents.ts +150 -0
  126. package/templates/pi/src/server.ts +1 -0
  127. package/dist/channel-HZOSHGNF.js +0 -260
  128. package/dist/chunk-33XAVCS4.js +0 -203
  129. package/dist/chunk-B2CPS4QU.js +0 -283
  130. package/dist/chunk-NWPT4ASZ.js +0 -89
  131. package/dist/chunk-SIAG3QMM.js +0 -42
  132. package/dist/chunk-WSLPZF72.js +0 -173
  133. package/dist/connector-M6XFI6GM.js +0 -147
  134. package/dist/connectors/discord.js +0 -177
  135. package/dist/connectors/slack.js +0 -181
  136. package/dist/connectors/telegram.js +0 -187
  137. package/dist/down-674SX2IZ.js +0 -14
  138. package/dist/message-delivery-XMGV3FUM.js +0 -23
  139. package/dist/service-FASYWLTC.js +0 -247
  140. package/dist/setup-BMLM2UTK.js +0 -230
  141. package/dist/sleep-manager-RKTFZPD3.js +0 -27
  142. package/dist/up-CJ26KQLN.js +0 -15
  143. package/dist/variant-UGREB4G5.js +0 -207
  144. package/dist/web-assets/assets/index-CGPSVu19.js +0 -69
  145. package/dist/web-assets/assets/index-V_rNDsM8.css +0 -1
@@ -1,260 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- getClient,
4
- urlOf
5
- } from "./chunk-4RQBJWQX.js";
6
- import {
7
- resolveMindName
8
- } from "./chunk-NAOW2CLO.js";
9
- import {
10
- parseArgs
11
- } from "./chunk-D424ZQGI.js";
12
- import {
13
- daemonFetch
14
- } from "./chunk-TRQEV3CD.js";
15
- import "./chunk-B2CPS4QU.js";
16
- import "./chunk-K3NQKI34.js";
17
-
18
- // src/commands/channel.ts
19
- async function run(args) {
20
- const subcommand = args[0];
21
- switch (subcommand) {
22
- case "read":
23
- await readChannel(args.slice(1));
24
- break;
25
- case "list":
26
- await listChannels(args.slice(1));
27
- break;
28
- case "users":
29
- await listUsers(args.slice(1));
30
- break;
31
- case "create":
32
- await createChannel(args.slice(1));
33
- break;
34
- case "typing":
35
- await typingChannel(args.slice(1));
36
- break;
37
- case "invite":
38
- await inviteChannel(args.slice(1));
39
- break;
40
- case "pending":
41
- await pendingChannel(args.slice(1));
42
- break;
43
- case "--help":
44
- case "-h":
45
- case void 0:
46
- printUsage();
47
- break;
48
- default:
49
- printUsage();
50
- process.exit(1);
51
- }
52
- }
53
- function printUsage() {
54
- console.log(`Usage:
55
- volute channel read <channel-uri> [--limit N] [--mind <name>]
56
- volute channel list [<platform>] [--mind <name>]
57
- volute channel users <platform> [--mind <name>]
58
- volute channel create <platform> --participants user1,user2 [--name "..."] [--mind <name>]
59
- volute channel typing <channel-uri> [--mind <name>]
60
- volute channel invite <channel-name> <username>
61
- volute channel pending [--mind <name>]`);
62
- }
63
- async function readChannel(args) {
64
- const { positional, flags } = parseArgs(args, {
65
- mind: { type: "string" },
66
- limit: { type: "number" }
67
- });
68
- const uri = positional[0];
69
- if (!uri) {
70
- console.error("Usage: volute channel read <channel-uri> [--limit N] [--mind <name>]");
71
- process.exit(1);
72
- }
73
- const mindName = resolveMindName(flags);
74
- const { platform } = parseUri(uri);
75
- const limit = flags.limit ?? 20;
76
- const client = getClient();
77
- const url = client.api.minds[":name"].channels.read.$url({ param: { name: mindName } });
78
- url.searchParams.set("platform", platform);
79
- url.searchParams.set("uri", uri);
80
- url.searchParams.set("limit", String(limit));
81
- const res = await daemonFetch(urlOf(url));
82
- if (!res.ok) {
83
- const body = await res.json().catch(() => ({}));
84
- console.error(body.error ?? `Server responded with ${res.status}`);
85
- process.exit(1);
86
- }
87
- const output = await res.text();
88
- console.log(output);
89
- }
90
- async function listChannels(args) {
91
- const { positional, flags } = parseArgs(args, {
92
- mind: { type: "string" }
93
- });
94
- const platform = positional[0];
95
- const mindName = resolveMindName(flags);
96
- const client = getClient();
97
- const url = client.api.minds[":name"].channels.list.$url({ param: { name: mindName } });
98
- if (platform) url.searchParams.set("platform", platform);
99
- const res = await daemonFetch(urlOf(url));
100
- if (!res.ok) {
101
- const body = await res.json().catch(() => ({}));
102
- console.error(body.error ?? `Server responded with ${res.status}`);
103
- process.exit(1);
104
- }
105
- const results = await res.json();
106
- for (const [p, convs] of Object.entries(results)) {
107
- for (const conv of convs) {
108
- if (conv.error) {
109
- console.error(`${p}: ${conv.error}`);
110
- continue;
111
- }
112
- const parts = [conv.id.padEnd(24), conv.name.padEnd(28), conv.type];
113
- if (conv.participantCount != null) {
114
- parts.push(String(conv.participantCount));
115
- }
116
- console.log(parts.join(" "));
117
- }
118
- }
119
- }
120
- async function listUsers(args) {
121
- const { positional, flags } = parseArgs(args, {
122
- mind: { type: "string" }
123
- });
124
- const platform = positional[0];
125
- if (!platform) {
126
- console.error("Usage: volute channel users <platform> [--mind <name>]");
127
- process.exit(1);
128
- }
129
- const mindName = resolveMindName(flags);
130
- const client = getClient();
131
- const url = client.api.minds[":name"].channels.users.$url({ param: { name: mindName } });
132
- url.searchParams.set("platform", platform);
133
- const res = await daemonFetch(urlOf(url));
134
- if (!res.ok) {
135
- const body = await res.json().catch(() => ({}));
136
- console.error(body.error ?? `Server responded with ${res.status}`);
137
- process.exit(1);
138
- }
139
- const users = await res.json();
140
- for (const user of users) {
141
- console.log(`${user.username.padEnd(20)} ${user.id.padEnd(20)} ${user.type ?? ""}`);
142
- }
143
- }
144
- async function createChannel(args) {
145
- const { positional, flags } = parseArgs(args, {
146
- mind: { type: "string" },
147
- participants: { type: "string" },
148
- name: { type: "string" }
149
- });
150
- const platform = positional[0];
151
- if (!platform || !flags.participants) {
152
- console.error(
153
- 'Usage: volute channel create <platform> --participants user1,user2 [--name "..."] [--mind <name>]'
154
- );
155
- process.exit(1);
156
- }
157
- const mindName = resolveMindName(flags);
158
- const participants = flags.participants.split(",").map((s) => s.trim());
159
- const client = getClient();
160
- const res = await daemonFetch(
161
- urlOf(client.api.minds[":name"].channels.create.$url({ param: { name: mindName } })),
162
- {
163
- method: "POST",
164
- headers: { "Content-Type": "application/json" },
165
- body: JSON.stringify({ platform, participants, name: flags.name })
166
- }
167
- );
168
- if (!res.ok) {
169
- const body = await res.json().catch(() => ({}));
170
- console.error(body.error ?? `Server responded with ${res.status}`);
171
- process.exit(1);
172
- }
173
- const data = await res.json();
174
- console.log(data.slug);
175
- }
176
- async function typingChannel(args) {
177
- const { positional, flags } = parseArgs(args, {
178
- mind: { type: "string" }
179
- });
180
- const uri = positional[0];
181
- if (!uri) {
182
- console.error("Usage: volute channel typing <channel-uri> [--mind <name>]");
183
- process.exit(1);
184
- }
185
- const mindName = resolveMindName(flags);
186
- try {
187
- const client = getClient();
188
- const url = client.api.minds[":name"].typing.$url({ param: { name: mindName } });
189
- url.searchParams.set("channel", uri);
190
- const res = await daemonFetch(urlOf(url));
191
- if (!res.ok) {
192
- const body = await res.json().catch(() => ({}));
193
- console.error(body.error ?? `Server responded with ${res.status}`);
194
- process.exit(1);
195
- }
196
- const data = await res.json();
197
- if (data.typing.length > 0) {
198
- console.log(data.typing.join(", "));
199
- }
200
- } catch (err) {
201
- console.error(err instanceof Error ? err.message : String(err));
202
- process.exit(1);
203
- }
204
- }
205
- async function inviteChannel(args) {
206
- const { positional } = parseArgs(args, {});
207
- const channelName = positional[0];
208
- const username = positional[1];
209
- if (!channelName || !username) {
210
- console.error("Usage: volute channel invite <channel-name> <username>");
211
- process.exit(1);
212
- }
213
- const res = await daemonFetch(`/api/volute/channels/${encodeURIComponent(channelName)}/invite`, {
214
- method: "POST",
215
- headers: { "Content-Type": "application/json" },
216
- body: JSON.stringify({ username })
217
- });
218
- if (!res.ok) {
219
- const body = await res.json().catch(() => ({}));
220
- console.error(body.error ?? `Server responded with ${res.status}`);
221
- process.exit(1);
222
- }
223
- console.log(`Invited ${username} to #${channelName}`);
224
- }
225
- async function pendingChannel(args) {
226
- const { flags } = parseArgs(args, {
227
- mind: { type: "string" }
228
- });
229
- const mindName = resolveMindName(flags);
230
- const res = await daemonFetch(`/api/minds/${encodeURIComponent(mindName)}/delivery/pending`);
231
- if (!res.ok) {
232
- const body = await res.json().catch(() => ({}));
233
- console.error(body.error ?? `Server responded with ${res.status}`);
234
- process.exit(1);
235
- }
236
- const pending = await res.json();
237
- if (pending.length === 0) {
238
- console.log("No pending messages.");
239
- return;
240
- }
241
- for (const entry of pending) {
242
- console.log(
243
- `${(entry.channel ?? "unknown").padEnd(30)} ${String(entry.count).padEnd(6)} ${entry.sender ?? "unknown"}`
244
- );
245
- console.log(` First seen: ${entry.firstSeen}`);
246
- console.log(` Preview: ${entry.preview}`);
247
- console.log();
248
- }
249
- }
250
- function parseUri(uri) {
251
- const colonIdx = uri.indexOf(":");
252
- if (colonIdx === -1) {
253
- console.error(`Invalid channel URI: ${uri} (expected format: platform:id)`);
254
- process.exit(1);
255
- }
256
- return { platform: uri.slice(0, colonIdx), channelId: uri.slice(colonIdx + 1) };
257
- }
258
- export {
259
- run
260
- };
@@ -1,203 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- voluteHome
4
- } from "./chunk-B2CPS4QU.js";
5
- import {
6
- __export
7
- } from "./chunk-K3NQKI34.js";
8
-
9
- // src/lib/schema.ts
10
- var schema_exports = {};
11
- __export(schema_exports, {
12
- activity: () => activity,
13
- conversationParticipants: () => conversationParticipants,
14
- conversationReads: () => conversationReads,
15
- conversations: () => conversations,
16
- deliveryQueue: () => deliveryQueue,
17
- messages: () => messages,
18
- mindHistory: () => mindHistory,
19
- sessions: () => sessions,
20
- sharedSkills: () => sharedSkills,
21
- systemPrompts: () => systemPrompts,
22
- users: () => users
23
- });
24
- import { sql } from "drizzle-orm";
25
- import { index, integer, sqliteTable, text, uniqueIndex } from "drizzle-orm/sqlite-core";
26
- var users = sqliteTable("users", {
27
- id: integer("id").primaryKey({ autoIncrement: true }),
28
- username: text("username").unique().notNull(),
29
- password_hash: text("password_hash").notNull(),
30
- role: text("role").notNull().default("pending"),
31
- user_type: text("user_type").notNull().default("brain"),
32
- display_name: text("display_name"),
33
- description: text("description"),
34
- avatar: text("avatar"),
35
- created_at: text("created_at").notNull().default(sql`(datetime('now'))`)
36
- });
37
- var conversations = sqliteTable(
38
- "conversations",
39
- {
40
- id: text("id").primaryKey(),
41
- mind_name: text("mind_name"),
42
- channel: text("channel").notNull(),
43
- type: text("type").notNull().default("dm"),
44
- name: text("name"),
45
- user_id: integer("user_id").references(() => users.id),
46
- title: text("title"),
47
- created_at: text("created_at").notNull().default(sql`(datetime('now'))`),
48
- updated_at: text("updated_at").notNull().default(sql`(datetime('now'))`)
49
- },
50
- (table) => [
51
- index("idx_conversations_mind_name").on(table.mind_name),
52
- index("idx_conversations_user_id").on(table.user_id),
53
- index("idx_conversations_updated_at").on(table.updated_at),
54
- uniqueIndex("idx_conversations_name").on(table.name)
55
- ]
56
- );
57
- var mindHistory = sqliteTable(
58
- "mind_history",
59
- {
60
- id: integer("id").primaryKey({ autoIncrement: true }),
61
- mind: text("mind").notNull(),
62
- channel: text("channel"),
63
- session: text("session"),
64
- sender: text("sender"),
65
- message_id: text("message_id"),
66
- type: text("type").notNull(),
67
- content: text("content"),
68
- metadata: text("metadata"),
69
- created_at: text("created_at").notNull().default(sql`(datetime('now'))`)
70
- },
71
- (table) => [
72
- index("idx_mind_history_mind").on(table.mind),
73
- index("idx_mind_history_mind_channel").on(table.mind, table.channel),
74
- index("idx_mind_history_mind_type").on(table.mind, table.type)
75
- ]
76
- );
77
- var conversationParticipants = sqliteTable(
78
- "conversation_participants",
79
- {
80
- conversation_id: text("conversation_id").notNull().references(() => conversations.id, { onDelete: "cascade" }),
81
- user_id: integer("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
82
- role: text("role").notNull().default("member"),
83
- joined_at: text("joined_at").notNull().default(sql`(datetime('now'))`)
84
- },
85
- (table) => [
86
- uniqueIndex("idx_cp_unique").on(table.conversation_id, table.user_id),
87
- index("idx_cp_user_id").on(table.user_id)
88
- ]
89
- );
90
- var sessions = sqliteTable("sessions", {
91
- id: text("id").primaryKey(),
92
- userId: integer("user_id").references(() => users.id, { onDelete: "cascade" }).notNull(),
93
- createdAt: integer("created_at").notNull()
94
- });
95
- var systemPrompts = sqliteTable("system_prompts", {
96
- key: text("key").primaryKey(),
97
- content: text("content").notNull(),
98
- updated_at: text("updated_at").notNull().default(sql`(datetime('now'))`)
99
- });
100
- var sharedSkills = sqliteTable("shared_skills", {
101
- id: text("id").primaryKey(),
102
- name: text("name").notNull(),
103
- description: text("description").notNull().default(""),
104
- author: text("author").notNull(),
105
- version: integer("version").notNull().default(1),
106
- created_at: text("created_at").notNull().default(sql`(datetime('now'))`),
107
- updated_at: text("updated_at").notNull().default(sql`(datetime('now'))`)
108
- });
109
- var deliveryQueue = sqliteTable(
110
- "delivery_queue",
111
- {
112
- id: integer("id").primaryKey({ autoIncrement: true }),
113
- mind: text("mind").notNull(),
114
- session: text("session").notNull(),
115
- channel: text("channel"),
116
- sender: text("sender"),
117
- status: text("status").notNull().default("pending"),
118
- payload: text("payload").notNull(),
119
- created_at: text("created_at").notNull().default(sql`(datetime('now'))`)
120
- },
121
- (table) => [
122
- index("idx_delivery_queue_mind_session").on(table.mind, table.session),
123
- index("idx_delivery_queue_mind_status").on(table.mind, table.status)
124
- ]
125
- );
126
- var activity = sqliteTable(
127
- "activity",
128
- {
129
- id: integer("id").primaryKey({ autoIncrement: true }),
130
- type: text("type").notNull(),
131
- mind: text("mind").notNull(),
132
- summary: text("summary").notNull(),
133
- metadata: text("metadata"),
134
- created_at: text("created_at").notNull().default(sql`(datetime('now'))`)
135
- },
136
- (table) => [
137
- index("idx_activity_created_at").on(table.created_at),
138
- index("idx_activity_mind").on(table.mind)
139
- ]
140
- );
141
- var conversationReads = sqliteTable(
142
- "conversation_reads",
143
- {
144
- user_id: integer("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
145
- conversation_id: text("conversation_id").notNull().references(() => conversations.id, { onDelete: "cascade" }),
146
- last_read_message_id: integer("last_read_message_id").notNull().default(0)
147
- },
148
- (table) => [
149
- uniqueIndex("idx_conversation_reads_unique").on(table.user_id, table.conversation_id)
150
- ]
151
- );
152
- var messages = sqliteTable(
153
- "messages",
154
- {
155
- id: integer("id").primaryKey({ autoIncrement: true }),
156
- conversation_id: text("conversation_id").notNull().references(() => conversations.id, { onDelete: "cascade" }),
157
- role: text("role").notNull(),
158
- sender_name: text("sender_name"),
159
- content: text("content").notNull(),
160
- created_at: text("created_at").notNull().default(sql`(datetime('now'))`)
161
- },
162
- (table) => [index("idx_messages_conversation_id").on(table.conversation_id)]
163
- );
164
-
165
- // src/lib/db.ts
166
- import { chmodSync, existsSync } from "fs";
167
- import { dirname, resolve } from "path";
168
- import { fileURLToPath } from "url";
169
- import { drizzle } from "drizzle-orm/libsql";
170
- import { migrate } from "drizzle-orm/libsql/migrator";
171
- var __dirname = dirname(fileURLToPath(import.meta.url));
172
- var migrationsFolder = existsSync(resolve(__dirname, "../drizzle")) ? resolve(__dirname, "../drizzle") : resolve(__dirname, "../../drizzle");
173
- var db = null;
174
- async function getDb() {
175
- if (db) return db;
176
- const dbPath = process.env.VOLUTE_DB_PATH || resolve(voluteHome(), "volute.db");
177
- db = drizzle({ connection: { url: `file:${dbPath}` }, schema: schema_exports });
178
- await migrate(db, { migrationsFolder });
179
- try {
180
- chmodSync(dbPath, 384);
181
- } catch (err) {
182
- console.error(
183
- `[volute] WARNING: Failed to restrict database file permissions on ${dbPath}:`,
184
- err
185
- );
186
- }
187
- return db;
188
- }
189
-
190
- export {
191
- users,
192
- conversations,
193
- mindHistory,
194
- conversationParticipants,
195
- sessions,
196
- systemPrompts,
197
- sharedSkills,
198
- deliveryQueue,
199
- activity,
200
- conversationReads,
201
- messages,
202
- getDb
203
- };