volute 0.35.0 → 0.36.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/{activity-events-ZW4SDL2C.js → activity-events-PWOGSMRL.js} +4 -4
- package/dist/{ai-service-LURBEDDB.js → ai-service-GSZWIETO.js} +5 -5
- package/dist/{archive-ESU2FUN4.js → archive-Y2YEOCGB.js} +3 -3
- package/dist/{auth-WX4TESEI.js → auth-YTQME4EV.js} +5 -5
- package/dist/{chat-QXAJF3FU.js → chat-ED7YOGKO.js} +4 -4
- package/dist/{chunk-AOB6GVRM.js → chunk-46DYYHN6.js} +8 -3
- package/dist/{chunk-5XJYUFZH.js → chunk-6F3YNULE.js} +68 -22
- package/dist/{chunk-BDYXIWA5.js → chunk-75AJ54GM.js} +13 -2
- package/dist/{chunk-5N7Y5WAM.js → chunk-7PTQGPJY.js} +28 -12
- package/dist/{chunk-CORXD635.js → chunk-B35VNNSS.js} +3 -3
- package/dist/{chunk-PWQ2ITYG.js → chunk-BOLJUV77.js} +4 -4
- package/dist/{chunk-ZSR72JB3.js → chunk-CU6OFXMM.js} +1 -1
- package/dist/{chunk-2TGZJFAT.js → chunk-DJT5Y4UF.js} +3 -3
- package/dist/{chunk-XRQSAMX2.js → chunk-DMV5P2LU.js} +3 -3
- package/dist/{chunk-WJPROOU5.js → chunk-DQ7VBXAP.js} +635 -3692
- package/dist/{chunk-IJHIXLVN.js → chunk-GBDVNPN2.js} +13 -11
- package/dist/{chunk-WZRZFFCL.js → chunk-IIWF2IPD.js} +146 -186
- package/dist/{chunk-F7ZNLYKZ.js → chunk-KAB6UGOL.js} +2 -2
- package/dist/{chunk-VHJRZM2S.js → chunk-L72WYMF7.js} +2 -2
- package/dist/{chunk-NJK5SDGR.js → chunk-LGNUFVMR.js} +1 -1
- package/dist/{chunk-FT5KETXZ.js → chunk-M5RYAA5I.js} +2 -2
- package/dist/{chunk-J6CJQDWI.js → chunk-N2AUHW4C.js} +2 -2
- package/dist/{chunk-BMZQYACC.js → chunk-NUX47Y2V.js} +19 -4
- package/dist/{chunk-AN2W47GW.js → chunk-PJ4IPTIN.js} +2 -2
- package/dist/{chunk-N446KRP7.js → chunk-PY557GDR.js} +2 -2
- package/dist/{chunk-MDJGMOSD.js → chunk-PZYJBOQP.js} +6 -6
- package/dist/chunk-RG5TOL4O.js +18 -0
- package/dist/{chunk-N5LMGYXX.js → chunk-SWW6AUVW.js} +2 -2
- package/dist/{chunk-BKF4WQCY.js → chunk-T2TP6ZC6.js} +20 -8
- package/dist/{chunk-VY3RB2V7.js → chunk-TWAN7ZNO.js} +3 -3
- package/dist/{chunk-QCH6K235.js → chunk-UI7RPV2B.js} +1 -1
- package/dist/{chunk-QWTR6AWZ.js → chunk-X2J7QUFH.js} +2 -2
- package/dist/{chunk-A2ZLHBHG.js → chunk-YDBAY3NA.js} +2 -2
- package/dist/{chunk-BV65KRHM.js → chunk-YTWZORJN.js} +2 -2
- package/dist/{chunk-OTC67N2Z.js → chunk-ZTVKQOU7.js} +1 -1
- package/dist/cli.js +16 -16
- package/dist/{cloud-sync-6JL4C24T.js → cloud-sync-BOCZSDIA.js} +19 -20
- package/dist/connectors/discord-bridge.js +3 -3
- package/dist/connectors/slack-bridge.js +3 -3
- package/dist/connectors/telegram-bridge.js +3 -3
- package/dist/{conversations-2PW57WO2.js → conversations-HH3CJD4E.js} +15 -9
- package/dist/{create-UVCK2CS6.js → create-QBEPSD2Z.js} +1 -1
- package/dist/{daemon-restart-HSZ3BCX5.js → daemon-restart-SIR3UR4B.js} +10 -10
- package/dist/daemon.js +446 -328
- package/dist/{db-BVBJ57TU.js → db-URORGSXQ.js} +2 -2
- package/dist/delivery-manager-WTGIPBGY.js +30 -0
- package/dist/{delivery-router-HEJSJAHQ.js → delivery-router-VSULHXNH.js} +4 -4
- package/dist/down-DGGLZ5TA.js +17 -0
- package/dist/{exec-PY7THYH4.js → exec-X3C6ZZTQ.js} +4 -4
- package/dist/{export-OAS6QVBN.js → export-HTFOHOKL.js} +3 -3
- package/dist/{extension-D74CNM7G.js → extension-AKZ46YSL.js} +22 -3
- package/dist/{extensions-XDDFY72A.js → extensions-OOSFVH7U.js} +21 -20
- package/dist/{files-CWTK6V3H.js → files-H2YLRD37.js} +3 -3
- package/dist/{import-5A3T7QV4.js → import-OL5BZX7S.js} +6 -6
- package/dist/{isolation-TK5RX2WM.js → isolation-N74RWOUX.js} +3 -3
- package/dist/{list-PDMQM7ZV.js → list-GJ4RUQQT.js} +7 -1
- package/dist/{login-7TE6CIZF.js → login-JXRVMBRB.js} +2 -2
- package/dist/{logout-T4XS6LRU.js → logout-FW243JBU.js} +2 -2
- package/dist/message-delivery-YORUXKDQ.js +40 -0
- package/dist/{mind-5IEYKV7I.js → mind-6VJJHF65.js} +6 -6
- package/dist/{mind-activity-tracker-QBLIV7ZJ.js → mind-activity-tracker-66UVYIFW.js} +5 -5
- package/dist/{mind-history-IE2QH7U5.js → mind-history-MII2SK7F.js} +81 -14
- package/dist/mind-manager-TJ2SUPRX.js +30 -0
- package/dist/mind-service-E7FM2WZF.js +36 -0
- package/dist/{package-D2FSVFAX.js → package-3W2MEXHB.js} +5 -5
- package/dist/{read-67VRP2DO.js → read-ZUDG4JWU.js} +4 -4
- package/dist/{registry-GBSNW3HG.js → registry-YPHK534W.js} +2 -2
- package/dist/{sandbox-R37VIU36.js → sandbox-LP6YRAXS.js} +5 -5
- package/dist/scheduler-FRJ5DK24.js +30 -0
- package/dist/{schema-XVZ2CLKW.js → schema-MISD3JFG.js} +3 -1
- package/dist/{seed-EQORWX77.js → seed-CEC4RC23.js} +1 -1
- package/dist/{seed-cmd-ZM2XGVU2.js → seed-cmd-WTTG7SRQ.js} +2 -2
- package/dist/{seed-create-DRWGGHEI.js → seed-create-M6RCC6RP.js} +3 -3
- package/dist/{seed-sprout-JYXGXOP3.js → seed-sprout-ZKCHFJKH.js} +10 -10
- package/dist/{send-JBJJQ7CA.js → send-LXUT2GGR.js} +3 -3
- package/dist/{service-WNPCNHOX.js → service-M6N3RUYU.js} +5 -5
- package/dist/{setup-BJ4YAY26.js → setup-PJOF5UV5.js} +7 -7
- package/dist/{setup-RHJRFURI.js → setup-PMJHCZQX.js} +5 -3
- package/dist/skills/tending/SKILL.md +52 -0
- package/dist/{skills-EKMCQ46K.js → skills-2PTRTBQP.js} +7 -7
- package/dist/sleep-manager-WAZWMFJT.js +34 -0
- package/dist/spirit-6KVDIROQ.js +24 -0
- package/dist/{sprout-HE4TITMK.js → sprout-WX2FFYLP.js} +1 -1
- package/dist/src-FQE4BHRG.js +617 -0
- package/dist/src-GW6FP6VL.js +425 -0
- package/dist/src-QEOLMAYC.js +2133 -0
- package/dist/{status-ZK34WYIM.js → status-3IVSLJDN.js} +6 -6
- package/dist/system-chat-2IFS5HCX.js +34 -0
- package/dist/{tailscale-ZIZ2HWJ5.js → tailscale-DZU4WM3E.js} +3 -3
- package/dist/{template-hash-A7FNHTB7.js → template-hash-6ITI3WC4.js} +2 -2
- package/dist/up-4SCIUIMG.js +19 -0
- package/dist/{update-ANE5ZM7F.js → update-RIQYUPVN.js} +6 -6
- package/dist/{update-check-UV55CBEP.js → update-check-4TIJKVGD.js} +3 -3
- package/dist/{version-notify-FXSEMXWW.js → version-notify-UXSHBZ35.js} +21 -22
- package/dist/{volute-config-D2XVS2YI.js → volute-config-V7UFFBG3.js} +1 -1
- package/dist/web-assets/assets/index-C-eYso8Y.js +75 -0
- package/dist/web-assets/assets/index-CCv_fSte.css +1 -0
- package/dist/web-assets/index.html +2 -2
- package/drizzle/0006_channels.sql +17 -0
- package/drizzle/0007_drop_conversation_name_title.sql +11 -0
- package/drizzle/0008_performance_indexes.sql +6 -0
- package/drizzle/meta/0006_snapshot.json +7 -0
- package/drizzle/meta/0007_snapshot.json +7 -0
- package/drizzle/meta/_journal.json +21 -0
- package/package.json +5 -5
- package/templates/_base/home/.config/routes.json +2 -2
- package/templates/_base/home/VOLUTE.md +1 -2
- package/templates/_base/src/lib/format-prefix.ts +1 -7
- package/templates/claude/.init/.config/routes.json +2 -2
- package/templates/codex/.init/.config/routes.json +2 -2
- package/templates/pi/.init/.config/routes.json +2 -2
- package/dist/delivery-manager-H5ZVBMCQ.js +0 -31
- package/dist/down-74VXM45A.js +0 -17
- package/dist/message-delivery-GRC4W6P7.js +0 -41
- package/dist/mind-manager-HFLB5653.js +0 -31
- package/dist/mind-service-X2CAA6W6.js +0 -37
- package/dist/scheduler-Y7O4CJXL.js +0 -31
- package/dist/sleep-manager-7KFK3USC.js +0 -35
- package/dist/spirit-ZFRDXMG7.js +0 -23
- package/dist/system-chat-IDPHYHY4.js +0 -35
- package/dist/up-77ICEDEW.js +0 -19
- package/dist/web-assets/assets/index-BhxWKvbB.css +0 -1
- package/dist/web-assets/assets/index-CHVKJ9II.js +0 -75
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
logger_default
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-T2TP6ZC6.js";
|
|
5
5
|
import {
|
|
6
6
|
exec,
|
|
7
7
|
gitExec
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-PJ4IPTIN.js";
|
|
9
9
|
import {
|
|
10
10
|
readGlobalConfig,
|
|
11
11
|
writeGlobalConfig
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-NUX47Y2V.js";
|
|
13
13
|
import {
|
|
14
14
|
getDb,
|
|
15
15
|
mindDir,
|
|
16
16
|
readRegistry,
|
|
17
17
|
voluteHome
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-75AJ54GM.js";
|
|
19
19
|
import {
|
|
20
20
|
sharedSkills
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-7PTQGPJY.js";
|
|
22
22
|
|
|
23
23
|
// packages/daemon/src/lib/skills.ts
|
|
24
24
|
import { createHash } from "crypto";
|
|
@@ -46,7 +46,7 @@ async function initDefaultSkills() {
|
|
|
46
46
|
const config = readGlobalConfig();
|
|
47
47
|
let extensionSkills = [];
|
|
48
48
|
try {
|
|
49
|
-
const { getExtensionStandardSkills } = await import("./extensions-
|
|
49
|
+
const { getExtensionStandardSkills } = await import("./extensions-OOSFVH7U.js");
|
|
50
50
|
extensionSkills = getExtensionStandardSkills();
|
|
51
51
|
} catch (err) {
|
|
52
52
|
logger_default.warn("failed to load extension standard skills during init", logger_default.errorData(err));
|
|
@@ -206,7 +206,7 @@ async function installSkill(_mindName, dir, skillId) {
|
|
|
206
206
|
const npmInstalled = [];
|
|
207
207
|
const skillMdPath = join(sourceDir, "SKILL.md");
|
|
208
208
|
if (existsSync(skillMdPath)) {
|
|
209
|
-
const { npmDependencies } = parseSkillMd(readFileSync(skillMdPath, "utf-8"));
|
|
209
|
+
const { npmDependencies, hooks, bin } = parseSkillMd(readFileSync(skillMdPath, "utf-8"));
|
|
210
210
|
if (npmDependencies.length > 0) {
|
|
211
211
|
try {
|
|
212
212
|
await exec("npm", ["install", ...npmDependencies], { cwd: dir });
|
|
@@ -219,9 +219,6 @@ async function installSkill(_mindName, dir, skillId) {
|
|
|
219
219
|
);
|
|
220
220
|
}
|
|
221
221
|
}
|
|
222
|
-
}
|
|
223
|
-
if (existsSync(skillMdPath)) {
|
|
224
|
-
const { hooks, bin } = parseSkillMd(readFileSync(skillMdPath, "utf-8"));
|
|
225
222
|
installHookShims(dir, skillId, hooks);
|
|
226
223
|
if (bin) installBinShim(dir, skillId, bin);
|
|
227
224
|
}
|
|
@@ -506,11 +503,16 @@ function listFilesRecursive(dir, prefix = "") {
|
|
|
506
503
|
}
|
|
507
504
|
return results;
|
|
508
505
|
}
|
|
506
|
+
var _skillsRoot = null;
|
|
509
507
|
function findSkillsRoot() {
|
|
508
|
+
if (_skillsRoot) return _skillsRoot;
|
|
510
509
|
let dir = dirname(new URL(import.meta.url).pathname);
|
|
511
510
|
for (let i = 0; i < 5; i++) {
|
|
512
511
|
const candidate = resolve(dir, "skills");
|
|
513
|
-
if (existsSync(candidate) && hasSkillSubdir(candidate))
|
|
512
|
+
if (existsSync(candidate) && hasSkillSubdir(candidate)) {
|
|
513
|
+
_skillsRoot = candidate;
|
|
514
|
+
return _skillsRoot;
|
|
515
|
+
}
|
|
514
516
|
dir = dirname(dir);
|
|
515
517
|
}
|
|
516
518
|
throw new Error("Skills directory not found");
|
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
subscribe
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-B35VNNSS.js";
|
|
5
5
|
import {
|
|
6
6
|
logger_default
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-T2TP6ZC6.js";
|
|
8
8
|
import {
|
|
9
9
|
getDb
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-75AJ54GM.js";
|
|
11
11
|
import {
|
|
12
|
+
channels,
|
|
12
13
|
conversationParticipants,
|
|
13
14
|
conversationReads,
|
|
14
15
|
conversations,
|
|
15
16
|
messages,
|
|
16
17
|
users
|
|
17
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-7PTQGPJY.js";
|
|
18
19
|
|
|
19
20
|
// packages/daemon/src/lib/events/conversations.ts
|
|
20
21
|
import { randomUUID } from "crypto";
|
|
21
|
-
import { and, desc, eq, inArray,
|
|
22
|
+
import { aliasedTable, and, desc, eq, inArray, lt, sql } from "drizzle-orm";
|
|
22
23
|
|
|
23
24
|
// packages/daemon/src/lib/webhook.ts
|
|
24
25
|
var slog = logger_default.child("webhook");
|
|
@@ -111,19 +112,14 @@ function publish(conversationId, event) {
|
|
|
111
112
|
}
|
|
112
113
|
|
|
113
114
|
// packages/daemon/src/lib/events/conversations.ts
|
|
114
|
-
async function createConversation(
|
|
115
|
+
async function createConversation(opts) {
|
|
115
116
|
const db = await getDb();
|
|
116
117
|
const id = randomUUID();
|
|
117
118
|
const type = opts?.type ?? "dm";
|
|
118
|
-
const name = opts?.name ?? null;
|
|
119
119
|
await db.insert(conversations).values({
|
|
120
120
|
id,
|
|
121
|
-
mind_name: mindName,
|
|
122
|
-
channel,
|
|
123
121
|
type,
|
|
124
|
-
|
|
125
|
-
user_id: opts?.userId ?? null,
|
|
126
|
-
title: opts?.title ?? null
|
|
122
|
+
user_id: opts?.userId ?? null
|
|
127
123
|
});
|
|
128
124
|
if (opts?.participantIds && opts.participantIds.length > 0) {
|
|
129
125
|
await db.insert(conversationParticipants).values(
|
|
@@ -136,34 +132,18 @@ async function createConversation(mindName, channel, opts) {
|
|
|
136
132
|
}
|
|
137
133
|
fireWebhook({
|
|
138
134
|
event: "conversation_created",
|
|
139
|
-
mind:
|
|
140
|
-
data: { id,
|
|
135
|
+
mind: "",
|
|
136
|
+
data: { id, type }
|
|
141
137
|
});
|
|
142
138
|
return {
|
|
143
139
|
id,
|
|
144
|
-
mind_name: mindName,
|
|
145
|
-
channel,
|
|
146
140
|
type,
|
|
147
|
-
name,
|
|
148
141
|
user_id: opts?.userId ?? null,
|
|
149
|
-
title: opts?.title ?? null,
|
|
150
142
|
private: 0,
|
|
151
143
|
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
152
144
|
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
153
145
|
};
|
|
154
146
|
}
|
|
155
|
-
async function getOrCreateConversation(mindName, channel, opts) {
|
|
156
|
-
const db = await getDb();
|
|
157
|
-
const existing = await db.select().from(conversations).where(
|
|
158
|
-
and(
|
|
159
|
-
eq(conversations.mind_name, mindName),
|
|
160
|
-
eq(conversations.channel, channel),
|
|
161
|
-
eq(conversations.type, "dm")
|
|
162
|
-
)
|
|
163
|
-
).orderBy(desc(conversations.updated_at)).limit(1).get();
|
|
164
|
-
if (existing) return existing;
|
|
165
|
-
return createConversation(mindName, channel, opts);
|
|
166
|
-
}
|
|
167
147
|
async function getConversation(id) {
|
|
168
148
|
const db = await getDb();
|
|
169
149
|
const row = await db.select().from(conversations).where(eq(conversations.id, id)).get();
|
|
@@ -236,13 +216,6 @@ async function addMessage(conversationId, role, senderName, content, opts) {
|
|
|
236
216
|
turn_id: opts?.turnId ?? null
|
|
237
217
|
}).returning({ id: messages.id, created_at: messages.created_at });
|
|
238
218
|
await db.update(conversations).set({ updated_at: sql`datetime('now')` }).where(eq(conversations.id, conversationId));
|
|
239
|
-
if (role === "user") {
|
|
240
|
-
const firstText = content.find((b) => b.type === "text");
|
|
241
|
-
const title = firstText ? firstText.text.slice(0, 80) : "";
|
|
242
|
-
if (title) {
|
|
243
|
-
await db.update(conversations).set({ title }).where(and(eq(conversations.id, conversationId), isNull(conversations.title)));
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
219
|
const msg = {
|
|
247
220
|
id: result.id,
|
|
248
221
|
conversation_id: conversationId,
|
|
@@ -259,10 +232,9 @@ async function addMessage(conversationId, role, senderName, content, opts) {
|
|
|
259
232
|
content: msg.content,
|
|
260
233
|
createdAt: msg.created_at
|
|
261
234
|
});
|
|
262
|
-
const conv = await db.select({ mind_name: conversations.mind_name }).from(conversations).where(eq(conversations.id, conversationId)).get();
|
|
263
235
|
fireWebhook({
|
|
264
236
|
event: "message_created",
|
|
265
|
-
mind:
|
|
237
|
+
mind: "",
|
|
266
238
|
data: {
|
|
267
239
|
conversationId,
|
|
268
240
|
messageId: result.id,
|
|
@@ -274,10 +246,10 @@ async function addMessage(conversationId, role, senderName, content, opts) {
|
|
|
274
246
|
});
|
|
275
247
|
return msg;
|
|
276
248
|
}
|
|
277
|
-
async function getMessages(conversationId) {
|
|
249
|
+
async function getMessages(conversationId, limit = 200) {
|
|
278
250
|
const db = await getDb();
|
|
279
|
-
const rows = await db.select().from(messages).where(eq(messages.conversation_id, conversationId)).orderBy(messages.
|
|
280
|
-
return rows.map(parseMessageRow);
|
|
251
|
+
const rows = await db.select().from(messages).where(eq(messages.conversation_id, conversationId)).orderBy(desc(messages.id)).limit(limit).all();
|
|
252
|
+
return rows.reverse().map(parseMessageRow);
|
|
281
253
|
}
|
|
282
254
|
async function getMessagesPaginated(conversationId, opts) {
|
|
283
255
|
const db = await getDb();
|
|
@@ -304,8 +276,7 @@ function parseMessageRow(row) {
|
|
|
304
276
|
}
|
|
305
277
|
return { ...row, role: row.role, content };
|
|
306
278
|
}
|
|
307
|
-
async function
|
|
308
|
-
const convs = await listConversationsForUser(userId);
|
|
279
|
+
async function enrichConversations(convs) {
|
|
309
280
|
if (convs.length === 0) return [];
|
|
310
281
|
const db = await getDb();
|
|
311
282
|
const convIds = convs.map((c) => c.id);
|
|
@@ -317,168 +288,93 @@ async function listConversationsWithParticipants(userId) {
|
|
|
317
288
|
role: conversationParticipants.role,
|
|
318
289
|
displayName: users.display_name,
|
|
319
290
|
description: users.description,
|
|
320
|
-
avatar: users.avatar
|
|
321
|
-
|
|
291
|
+
avatar: users.avatar,
|
|
292
|
+
channelName: channels.name
|
|
293
|
+
}).from(conversationParticipants).innerJoin(users, eq(conversationParticipants.user_id, users.id)).leftJoin(channels, eq(channels.conversation_id, conversationParticipants.conversation_id)).where(inArray(conversationParticipants.conversation_id, convIds));
|
|
322
294
|
const byConv = /* @__PURE__ */ new Map();
|
|
295
|
+
const channelNames = /* @__PURE__ */ new Map();
|
|
323
296
|
for (const r of rows) {
|
|
324
297
|
let arr = byConv.get(r.conversationId);
|
|
325
298
|
if (!arr) {
|
|
326
299
|
arr = [];
|
|
327
300
|
byConv.set(r.conversationId, arr);
|
|
328
301
|
}
|
|
329
|
-
arr.
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
302
|
+
if (!arr.some((p) => p.userId === r.userId)) {
|
|
303
|
+
arr.push({
|
|
304
|
+
userId: r.userId,
|
|
305
|
+
username: r.username,
|
|
306
|
+
userType: r.userType,
|
|
307
|
+
role: r.role,
|
|
308
|
+
displayName: r.displayName,
|
|
309
|
+
description: r.description,
|
|
310
|
+
avatar: r.avatar
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
if (r.channelName && !channelNames.has(r.conversationId)) {
|
|
314
|
+
channelNames.set(r.conversationId, r.channelName);
|
|
315
|
+
}
|
|
338
316
|
}
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
}).from(messages).where(inArray(messages.conversation_id, convIds)).groupBy(messages.conversation_id);
|
|
317
|
+
const msgRows = await db.select().from(messages).where(
|
|
318
|
+
sql`${messages.id} IN (SELECT MAX(id) FROM ${messages} WHERE ${messages.conversation_id} IN ${convIds} GROUP BY ${messages.conversation_id})`
|
|
319
|
+
);
|
|
343
320
|
const byLastMsg = /* @__PURE__ */ new Map();
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
)
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
try {
|
|
354
|
-
const parsed = JSON.parse(m.content);
|
|
355
|
-
const blocks = Array.isArray(parsed) ? parsed : [];
|
|
356
|
-
const textBlock = blocks.find((b) => b.type === "text");
|
|
357
|
-
if (textBlock && "text" in textBlock) text = textBlock.text;
|
|
358
|
-
} catch {
|
|
359
|
-
text = m.content;
|
|
360
|
-
}
|
|
361
|
-
byLastMsg.set(m.conversation_id, {
|
|
362
|
-
role: m.role,
|
|
363
|
-
senderName: m.sender_name,
|
|
364
|
-
text,
|
|
365
|
-
createdAt: m.created_at
|
|
366
|
-
});
|
|
321
|
+
for (const m of msgRows) {
|
|
322
|
+
let text = "";
|
|
323
|
+
try {
|
|
324
|
+
const parsed = JSON.parse(m.content);
|
|
325
|
+
const blocks = Array.isArray(parsed) ? parsed : [];
|
|
326
|
+
const textBlock = blocks.find((b) => b.type === "text");
|
|
327
|
+
if (textBlock && "text" in textBlock) text = textBlock.text;
|
|
328
|
+
} catch {
|
|
329
|
+
text = m.content;
|
|
367
330
|
}
|
|
331
|
+
byLastMsg.set(m.conversation_id, {
|
|
332
|
+
role: m.role,
|
|
333
|
+
senderName: m.sender_name,
|
|
334
|
+
text,
|
|
335
|
+
createdAt: m.created_at
|
|
336
|
+
});
|
|
368
337
|
}
|
|
369
338
|
return convs.map((c) => ({
|
|
370
339
|
...c,
|
|
340
|
+
channel_name: channelNames.get(c.id) ?? null,
|
|
371
341
|
participants: byConv.get(c.id) ?? [],
|
|
372
342
|
lastMessage: byLastMsg.get(c.id)
|
|
373
343
|
}));
|
|
374
344
|
}
|
|
375
|
-
async function
|
|
345
|
+
async function listConversationsWithParticipants(userId) {
|
|
346
|
+
const convs = await listConversationsForUser(userId);
|
|
347
|
+
return enrichConversations(convs);
|
|
348
|
+
}
|
|
349
|
+
async function findDMConversation(participantIds) {
|
|
376
350
|
const db = await getDb();
|
|
377
|
-
const
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
351
|
+
const [id1, id2] = participantIds;
|
|
352
|
+
const cp2 = aliasedTable(conversationParticipants, "cp2");
|
|
353
|
+
const row = await db.select({ conversation_id: conversationParticipants.conversation_id }).from(conversationParticipants).innerJoin(cp2, eq(conversationParticipants.conversation_id, cp2.conversation_id)).innerJoin(conversations, eq(conversations.id, conversationParticipants.conversation_id)).where(
|
|
354
|
+
and(
|
|
355
|
+
eq(conversationParticipants.user_id, id1),
|
|
356
|
+
eq(cp2.user_id, id2),
|
|
357
|
+
eq(conversations.type, "dm"),
|
|
358
|
+
sql`(SELECT COUNT(*) FROM conversation_participants cp3 WHERE cp3.conversation_id = ${conversations.id}) = 2`
|
|
359
|
+
)
|
|
360
|
+
).get();
|
|
361
|
+
return row?.conversation_id ?? null;
|
|
387
362
|
}
|
|
388
363
|
async function listConversationsForMind(mindName) {
|
|
389
364
|
const db = await getDb();
|
|
390
|
-
const byName = await db.select().from(conversations).where(eq(conversations.mind_name, mindName)).orderBy(desc(conversations.updated_at)).all();
|
|
391
365
|
const mindUser = await db.select({ id: users.id }).from(users).where(and(eq(users.username, mindName), eq(users.user_type, "mind"))).get();
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
if (
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
byParticipation = await db.select().from(conversations).where(inArray(conversations.id, extraIds)).orderBy(desc(conversations.updated_at)).all();
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
const convs = [...byName, ...byParticipation].sort(
|
|
402
|
-
(a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime()
|
|
403
|
-
);
|
|
404
|
-
if (convs.length === 0) return [];
|
|
405
|
-
const convIds = convs.map((c) => c.id);
|
|
406
|
-
const rows = await db.select({
|
|
407
|
-
conversationId: conversationParticipants.conversation_id,
|
|
408
|
-
userId: users.id,
|
|
409
|
-
username: users.username,
|
|
410
|
-
userType: users.user_type,
|
|
411
|
-
role: conversationParticipants.role,
|
|
412
|
-
displayName: users.display_name,
|
|
413
|
-
description: users.description,
|
|
414
|
-
avatar: users.avatar
|
|
415
|
-
}).from(conversationParticipants).innerJoin(users, eq(conversationParticipants.user_id, users.id)).where(inArray(conversationParticipants.conversation_id, convIds));
|
|
416
|
-
const byConv = /* @__PURE__ */ new Map();
|
|
417
|
-
for (const r of rows) {
|
|
418
|
-
let arr = byConv.get(r.conversationId);
|
|
419
|
-
if (!arr) {
|
|
420
|
-
arr = [];
|
|
421
|
-
byConv.set(r.conversationId, arr);
|
|
422
|
-
}
|
|
423
|
-
arr.push({
|
|
424
|
-
userId: r.userId,
|
|
425
|
-
username: r.username,
|
|
426
|
-
userType: r.userType,
|
|
427
|
-
role: r.role,
|
|
428
|
-
displayName: r.displayName,
|
|
429
|
-
description: r.description,
|
|
430
|
-
avatar: r.avatar
|
|
431
|
-
});
|
|
432
|
-
}
|
|
433
|
-
const lastMsgIds = await db.select({
|
|
434
|
-
conversationId: messages.conversation_id,
|
|
435
|
-
maxId: sql`MAX(${messages.id})`
|
|
436
|
-
}).from(messages).where(inArray(messages.conversation_id, convIds)).groupBy(messages.conversation_id);
|
|
437
|
-
const byLastMsg = /* @__PURE__ */ new Map();
|
|
438
|
-
if (lastMsgIds.length > 0) {
|
|
439
|
-
const msgRows = await db.select().from(messages).where(
|
|
440
|
-
inArray(
|
|
441
|
-
messages.id,
|
|
442
|
-
lastMsgIds.map((r) => r.maxId)
|
|
443
|
-
)
|
|
444
|
-
);
|
|
445
|
-
for (const m of msgRows) {
|
|
446
|
-
let text = "";
|
|
447
|
-
try {
|
|
448
|
-
const parsed = JSON.parse(m.content);
|
|
449
|
-
const blocks = Array.isArray(parsed) ? parsed : [];
|
|
450
|
-
const textBlock = blocks.find((b) => b.type === "text");
|
|
451
|
-
if (textBlock && "text" in textBlock) text = textBlock.text;
|
|
452
|
-
} catch {
|
|
453
|
-
text = m.content;
|
|
454
|
-
}
|
|
455
|
-
byLastMsg.set(m.conversation_id, {
|
|
456
|
-
role: m.role,
|
|
457
|
-
senderName: m.sender_name,
|
|
458
|
-
text,
|
|
459
|
-
createdAt: m.created_at
|
|
460
|
-
});
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
return convs.map((c) => ({
|
|
464
|
-
...c,
|
|
465
|
-
participants: byConv.get(c.id) ?? [],
|
|
466
|
-
lastMessage: byLastMsg.get(c.id)
|
|
467
|
-
}));
|
|
366
|
+
if (!mindUser) return [];
|
|
367
|
+
const participantRows = await db.select({ conversation_id: conversationParticipants.conversation_id }).from(conversationParticipants).where(eq(conversationParticipants.user_id, mindUser.id)).all();
|
|
368
|
+
if (participantRows.length === 0) return [];
|
|
369
|
+
const convIds = participantRows.map((r) => r.conversation_id);
|
|
370
|
+
const convs = await db.select().from(conversations).where(inArray(conversations.id, convIds)).orderBy(desc(conversations.updated_at)).all();
|
|
371
|
+
return enrichConversations(convs);
|
|
468
372
|
}
|
|
469
373
|
async function isConversationForMind(mindName, conversationId) {
|
|
470
374
|
const db = await getDb();
|
|
471
|
-
const byName = await db.select({ id: conversations.id }).from(conversations).where(and(eq(conversations.id, conversationId), eq(conversations.mind_name, mindName))).get();
|
|
472
|
-
if (byName) return true;
|
|
473
375
|
const mindUser = await db.select({ id: users.id }).from(users).where(and(eq(users.username, mindName), eq(users.user_type, "mind"))).get();
|
|
474
376
|
if (!mindUser) return false;
|
|
475
|
-
|
|
476
|
-
and(
|
|
477
|
-
eq(conversationParticipants.conversation_id, conversationId),
|
|
478
|
-
eq(conversationParticipants.user_id, mindUser.id)
|
|
479
|
-
)
|
|
480
|
-
).get();
|
|
481
|
-
return !!participant;
|
|
377
|
+
return isParticipant(conversationId, mindUser.id);
|
|
482
378
|
}
|
|
483
379
|
async function setConversationPrivate(id, isPrivate) {
|
|
484
380
|
const db = await getDb();
|
|
@@ -488,23 +384,84 @@ async function deleteConversation(id) {
|
|
|
488
384
|
const db = await getDb();
|
|
489
385
|
await db.delete(conversations).where(eq(conversations.id, id));
|
|
490
386
|
}
|
|
491
|
-
async function createChannel(name, creatorId) {
|
|
387
|
+
async function createChannel(name, creatorId, settings) {
|
|
492
388
|
const participantIds = creatorId ? [creatorId] : [];
|
|
493
|
-
|
|
389
|
+
const conv = await createConversation({
|
|
494
390
|
type: "channel",
|
|
495
|
-
name,
|
|
496
|
-
title: name,
|
|
497
391
|
participantIds
|
|
498
392
|
});
|
|
393
|
+
const db = await getDb();
|
|
394
|
+
try {
|
|
395
|
+
const isPrivate = settings?.private ? 1 : 0;
|
|
396
|
+
await db.insert(channels).values({
|
|
397
|
+
conversation_id: conv.id,
|
|
398
|
+
name,
|
|
399
|
+
description: settings?.description ?? null,
|
|
400
|
+
rules: settings?.rules ?? null,
|
|
401
|
+
char_limit: settings?.charLimit ?? null,
|
|
402
|
+
private: isPrivate
|
|
403
|
+
});
|
|
404
|
+
if (isPrivate) {
|
|
405
|
+
await db.update(conversations).set({ private: 1 }).where(eq(conversations.id, conv.id));
|
|
406
|
+
}
|
|
407
|
+
} catch (err) {
|
|
408
|
+
try {
|
|
409
|
+
await db.delete(conversations).where(eq(conversations.id, conv.id));
|
|
410
|
+
} catch {
|
|
411
|
+
}
|
|
412
|
+
throw err;
|
|
413
|
+
}
|
|
414
|
+
return conv;
|
|
415
|
+
}
|
|
416
|
+
async function getChannelName(conversationId) {
|
|
417
|
+
const db = await getDb();
|
|
418
|
+
const row = await db.select({ name: channels.name }).from(channels).where(eq(channels.conversation_id, conversationId)).get();
|
|
419
|
+
return row?.name ?? null;
|
|
499
420
|
}
|
|
500
421
|
async function getChannelByName(name) {
|
|
501
422
|
const db = await getDb();
|
|
502
|
-
const
|
|
423
|
+
const ch = await db.select().from(channels).where(eq(channels.name, name)).get();
|
|
424
|
+
if (!ch) return null;
|
|
425
|
+
return getConversation(ch.conversation_id);
|
|
426
|
+
}
|
|
427
|
+
async function getChannelSettings(name) {
|
|
428
|
+
const db = await getDb();
|
|
429
|
+
const row = await db.select().from(channels).where(eq(channels.name, name)).get();
|
|
503
430
|
return row ?? null;
|
|
504
431
|
}
|
|
432
|
+
function formatChannelSettings(row) {
|
|
433
|
+
if (!row) return null;
|
|
434
|
+
return {
|
|
435
|
+
description: row.description,
|
|
436
|
+
rules: row.rules,
|
|
437
|
+
charLimit: row.char_limit,
|
|
438
|
+
private: !!row.private
|
|
439
|
+
};
|
|
440
|
+
}
|
|
505
441
|
async function listChannels() {
|
|
506
442
|
const db = await getDb();
|
|
507
|
-
|
|
443
|
+
const rows = await db.select().from(conversations).innerJoin(channels, eq(channels.conversation_id, conversations.id)).where(eq(conversations.type, "channel")).orderBy(channels.name).all();
|
|
444
|
+
return rows.map((r) => ({
|
|
445
|
+
...r.conversations,
|
|
446
|
+
channel_name: r.channels.name
|
|
447
|
+
}));
|
|
448
|
+
}
|
|
449
|
+
async function updateChannelSettings(name, settings) {
|
|
450
|
+
const db = await getDb();
|
|
451
|
+
const updates = {
|
|
452
|
+
updated_at: sql`(datetime('now'))`
|
|
453
|
+
};
|
|
454
|
+
if (settings.description !== void 0) updates.description = settings.description;
|
|
455
|
+
if (settings.rules !== void 0) updates.rules = settings.rules;
|
|
456
|
+
if (settings.charLimit !== void 0) updates.char_limit = settings.charLimit;
|
|
457
|
+
if (settings.private !== void 0) updates.private = settings.private ? 1 : 0;
|
|
458
|
+
await db.update(channels).set(updates).where(eq(channels.name, name));
|
|
459
|
+
if (settings.private !== void 0) {
|
|
460
|
+
const ch = await db.select().from(channels).where(eq(channels.name, name)).get();
|
|
461
|
+
if (ch) {
|
|
462
|
+
await db.update(conversations).set({ private: settings.private ? 1 : 0 }).where(eq(conversations.id, ch.conversation_id));
|
|
463
|
+
}
|
|
464
|
+
}
|
|
508
465
|
}
|
|
509
466
|
async function joinChannel(conversationId, userId) {
|
|
510
467
|
if (await isParticipant(conversationId, userId)) return;
|
|
@@ -556,7 +513,6 @@ export {
|
|
|
556
513
|
subscribe2 as subscribe,
|
|
557
514
|
publish,
|
|
558
515
|
createConversation,
|
|
559
|
-
getOrCreateConversation,
|
|
560
516
|
getConversation,
|
|
561
517
|
addParticipant,
|
|
562
518
|
removeParticipant,
|
|
@@ -575,8 +531,12 @@ export {
|
|
|
575
531
|
setConversationPrivate,
|
|
576
532
|
deleteConversation,
|
|
577
533
|
createChannel,
|
|
534
|
+
getChannelName,
|
|
578
535
|
getChannelByName,
|
|
536
|
+
getChannelSettings,
|
|
537
|
+
formatChannelSettings,
|
|
579
538
|
listChannels,
|
|
539
|
+
updateChannelSettings,
|
|
580
540
|
joinChannel,
|
|
581
541
|
leaveChannel,
|
|
582
542
|
getUnreadCounts,
|
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
composeTemplate,
|
|
4
4
|
findTemplatesRoot,
|
|
5
5
|
listFiles
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-46DYYHN6.js";
|
|
7
7
|
|
|
8
|
-
// packages/daemon/src/lib/template-hash.ts
|
|
8
|
+
// packages/daemon/src/lib/template/template-hash.ts
|
|
9
9
|
import { createHash } from "crypto";
|
|
10
10
|
import { existsSync, readFileSync, rmSync } from "fs";
|
|
11
11
|
import { resolve } from "path";
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
getBaseName,
|
|
4
4
|
validateMindName
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-75AJ54GM.js";
|
|
6
6
|
|
|
7
|
-
// packages/daemon/src/lib/isolation.ts
|
|
7
|
+
// packages/daemon/src/lib/mind/isolation.ts
|
|
8
8
|
import { execFileSync } from "child_process";
|
|
9
9
|
function isIsolationEnabled() {
|
|
10
10
|
return process.env.VOLUTE_ISOLATION === "user";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
logger_default
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-T2TP6ZC6.js";
|
|
5
5
|
import {
|
|
6
6
|
readGlobalConfig,
|
|
7
7
|
writeGlobalConfig
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-NUX47Y2V.js";
|
|
9
9
|
|
|
10
10
|
// packages/daemon/src/lib/ai-service.ts
|
|
11
11
|
import { complete, getEnvApiKey, getModel, getModels, getProviders } from "@mariozechner/pi-ai";
|
|
@@ -5,13 +5,13 @@ import {
|
|
|
5
5
|
pollHealthDown,
|
|
6
6
|
readDaemonConfig,
|
|
7
7
|
stopService
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-DJT5Y4UF.js";
|
|
9
9
|
import {
|
|
10
10
|
command
|
|
11
11
|
} from "./chunk-TXSA4Q3V.js";
|
|
12
12
|
import {
|
|
13
13
|
voluteSystemDir
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-75AJ54GM.js";
|
|
15
15
|
|
|
16
16
|
// src/commands/down.ts
|
|
17
17
|
import { existsSync, readFileSync, unlinkSync } from "fs";
|
|
@@ -1,19 +1,32 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
voluteSystemDir
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-75AJ54GM.js";
|
|
5
5
|
|
|
6
|
-
// packages/daemon/src/lib/setup.ts
|
|
6
|
+
// packages/daemon/src/lib/config/setup.ts
|
|
7
7
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
8
8
|
import { resolve } from "path";
|
|
9
9
|
function configPath() {
|
|
10
10
|
return resolve(voluteSystemDir(), "config.json");
|
|
11
11
|
}
|
|
12
|
+
var _cachedConfig = null;
|
|
13
|
+
var CONFIG_CACHE_TTL = 2e3;
|
|
14
|
+
function _resetConfigCache() {
|
|
15
|
+
_cachedConfig = null;
|
|
16
|
+
}
|
|
12
17
|
function readGlobalConfig() {
|
|
18
|
+
if (_cachedConfig && Date.now() - _cachedConfig.ts < CONFIG_CACHE_TTL) {
|
|
19
|
+
return { ..._cachedConfig.config };
|
|
20
|
+
}
|
|
13
21
|
const path = configPath();
|
|
14
|
-
if (!existsSync(path))
|
|
22
|
+
if (!existsSync(path)) {
|
|
23
|
+
_cachedConfig = null;
|
|
24
|
+
return {};
|
|
25
|
+
}
|
|
15
26
|
try {
|
|
16
|
-
|
|
27
|
+
const config = JSON.parse(readFileSync(path, "utf-8"));
|
|
28
|
+
_cachedConfig = { config, ts: Date.now() };
|
|
29
|
+
return config;
|
|
17
30
|
} catch (err) {
|
|
18
31
|
console.error(`Failed to parse ${path}: ${err instanceof Error ? err.message : err}`);
|
|
19
32
|
return {};
|
|
@@ -24,6 +37,7 @@ function writeGlobalConfig(config) {
|
|
|
24
37
|
mkdirSync(voluteSystemDir(), { recursive: true });
|
|
25
38
|
writeFileSync(path, `${JSON.stringify(config, null, 2)}
|
|
26
39
|
`);
|
|
40
|
+
_cachedConfig = { config, ts: Date.now() };
|
|
27
41
|
}
|
|
28
42
|
function isSetupComplete() {
|
|
29
43
|
const config = readGlobalConfig();
|
|
@@ -47,6 +61,7 @@ function migrateSetupCompleted() {
|
|
|
47
61
|
|
|
48
62
|
export {
|
|
49
63
|
configPath,
|
|
64
|
+
_resetConfigCache,
|
|
50
65
|
readGlobalConfig,
|
|
51
66
|
writeGlobalConfig,
|
|
52
67
|
isSetupComplete,
|