volute 0.30.1 → 0.32.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/README.md +15 -22
- package/dist/{accept-E3PAH3QJ.js → accept-74M7I4RZ.js} +5 -4
- package/dist/{activity-events-BKBPPUBP.js → activity-events-HETAODOK.js} +3 -2
- package/dist/{ai-service-VAJT5UBS.js → ai-service-ZIPCV3MX.js} +20 -5
- package/dist/api.d.ts +341 -397
- package/dist/{archive-WWDBWYN2.js → archive-INXYFVCW.js} +3 -2
- package/dist/auth-6DMGES3I.js +44 -0
- package/dist/{bridge-RO37CUFM.js → bridge-BVCBTGPF.js} +5 -4
- package/dist/{chat-TCUNPFGO.js → chat-XT4OBJBU.js} +8 -8
- package/dist/{chunk-P7VFDSSG.js → chunk-2FLJ63GU.js} +2 -2
- package/dist/{chunk-ZWKTUQEL.js → chunk-2NGTS5UU.js} +1 -1
- package/dist/{chunk-JGFRDMR6.js → chunk-ALEF47VT.js} +1 -1
- package/dist/{chunk-MDPCSXZ4.js → chunk-D5G5YOPL.js} +163 -15
- package/dist/{chunk-VGWJSNHS.js → chunk-G53F3JA4.js} +1 -35
- package/dist/{chunk-A6TUJJ3L.js → chunk-G6BSYHPK.js} +2 -2
- package/dist/{chunk-DTC6EH5I.js → chunk-I5KY25PQ.js} +1 -9
- package/dist/{chunk-NSBFETWP.js → chunk-IYDIE3HG.js} +64 -26
- package/dist/{chunk-W5OOPLNP.js → chunk-JJ7W6WSB.js} +3 -3
- package/dist/{chunk-G3GBKZGG.js → chunk-LGB6JBHI.js} +54 -2
- package/dist/chunk-LRCG2JLP.js +251 -0
- package/dist/{chunk-FXHXHI2A.js → chunk-LSGWR54X.js} +3 -6
- package/dist/{chunk-S5LR3XYJ.js → chunk-M7UL5S3Q.js} +1 -1
- package/dist/chunk-PB65JZK2.js +85 -0
- package/dist/chunk-PVY5W6QN.js +41 -0
- package/dist/{chunk-QVAQ5454.js → chunk-QBQ424EM.js} +3007 -2126
- package/dist/{chunk-P27RV5WM.js → chunk-QZANELPX.js} +6 -2
- package/dist/{chunk-FSM45XD5.js → chunk-R7E6CRVQ.js} +1 -1
- package/dist/{chunk-HHTXM4JT.js → chunk-RPZZSXV3.js} +39 -195
- package/dist/{chunk-UPA6COHU.js → chunk-RSX4OPZY.js} +5 -5
- package/dist/{chunk-2C2VXEBB.js → chunk-S6NFERDC.js} +21 -57
- package/dist/chunk-SKLSMHXO.js +208 -0
- package/dist/{chunk-IKHDUZRH.js → chunk-SX5TKJBZ.js} +2 -2
- package/dist/chunk-TDRYEPH4.js +185 -0
- package/dist/chunk-TSXLLQZW.js +46 -0
- package/dist/{chunk-EFVHR7KH.js → chunk-UKVWJRKN.js} +24 -5
- package/dist/{chunk-2NDZC3S7.js → chunk-WKF5FEFK.js} +688 -389
- package/dist/cli.js +93 -24
- package/dist/{clock-G3ALCMLJ.js → clock-2UOZ6JPU.js} +11 -8
- package/dist/{cloud-sync-JV4LJOK3.js → cloud-sync-JN3NWKEM.js} +16 -14
- package/dist/config-H2H4UIF7.js +72 -0
- package/dist/connectors/discord-bridge.js +1 -1
- package/dist/connectors/slack-bridge.js +1 -1
- package/dist/connectors/telegram-bridge.js +1 -1
- package/dist/{conversations-7KVQV7EZ.js → conversations-3O5O6AS3.js} +8 -7
- package/dist/{create-JTLS7GX3.js → create-RNLNCORE.js} +5 -4
- package/dist/{create-VQSQHJQW.js → create-WBBYI6V7.js} +6 -2
- package/dist/daemon-client-6QXHZ7US.js +12 -0
- package/dist/{daemon-restart-4JGBHEJ4.js → daemon-restart-NGFHFAUF.js} +7 -7
- package/dist/daemon.js +2446 -1999
- package/dist/{db-HMFPIRO2.js → db-F34YLV7D.js} +2 -1
- package/dist/db-RA45JBFG.js +16 -0
- package/dist/{delete-JESHKE7F.js → delete-QTGWEDBI.js} +1 -1
- package/dist/delivery-manager-SDVXFD4W.js +28 -0
- package/dist/delivery-router-FL45JL7N.js +21 -0
- package/dist/down-TB3ESMNP.js +14 -0
- package/dist/{env-CLXXT7M2.js → env-RLYQBOOP.js} +5 -4
- package/dist/{export-EGA5M5PB.js → export-SUYRLI5Q.js} +4 -3
- package/dist/{extension-WZ4SUPJB.js → extension-FQ5D3NCC.js} +6 -6
- package/dist/{extensions-ECO4RPFQ.js → extensions-GDYWQXC4.js} +9 -7
- package/dist/{files-4VEJDASH.js → files-EAMPO2SJ.js} +6 -5
- package/dist/{history-EJMMLXDO.js → history-FO5PHBQ5.js} +9 -4
- package/dist/{import-YCGPMBSI.js → import-DDUFE7AY.js} +4 -3
- package/dist/{join-2GBJKZEN.js → join-I5QEE3LG.js} +1 -1
- package/dist/{list-Q6O7FGAN.js → list-DW2VRTOZ.js} +5 -4
- package/dist/{login-RL6AU2SM.js → login-7CHPW2PN.js} +5 -4
- package/dist/{login-RET5WESK.js → login-RIJF2F4G.js} +3 -2
- package/dist/{logout-CGAGJN3L.js → logout-5MLHZALK.js} +3 -2
- package/dist/{logout-JRPBEMMR.js → logout-UZJRGY4Z.js} +3 -2
- package/dist/message-delivery-2FIM7QKO.js +32 -0
- package/dist/{mind-LUWRQUQ5.js → mind-2B6M7Y25.js} +18 -18
- package/dist/{mind-activity-tracker-VYN2ZZ2M.js → mind-activity-tracker-NZZT2NTT.js} +4 -3
- package/dist/{mind-list-V5WW5DUA.js → mind-list-WUPMQDYQ.js} +3 -2
- package/dist/mind-manager-BNCMGYXW.js +28 -0
- package/dist/mind-service-AV273WT4.js +34 -0
- package/dist/{mind-sleep-R6PTNNW4.js → mind-sleep-B7BHJLH7.js} +5 -4
- package/dist/{mind-status-I4ISFJ6I.js → mind-status-L3EFFRPR.js} +3 -2
- package/dist/{mind-wake-67ZQEWAV.js → mind-wake-GY3RFX7Y.js} +5 -4
- package/dist/{package-OYUD4ZJ4.js → package-PK6JUFL3.js} +3 -3
- package/dist/read-5AMJRO3D.js +75 -0
- package/dist/{register-NZDSTLP3.js → register-V2JZZKFK.js} +5 -4
- package/dist/{registry-ODSALQQL.js → registry-PJ4S5PHQ.js} +8 -1
- package/dist/{reject-2HZOJEIJ.js → reject-33HEZMZ4.js} +5 -4
- package/dist/{restart-QHS3NT64.js → restart-3UCMRUVC.js} +5 -4
- package/dist/{sandbox-O5FUSF43.js → sandbox-JANNTX6U.js} +4 -3
- package/dist/schema-PA3M5ZKH.js +32 -0
- package/dist/seed-ALUQ55FF.js +112 -0
- package/dist/{send-OAN3RYYY.js → send-3MI36LEF.js} +58 -69
- package/dist/{setup-QMDK5RZX.js → setup-SZIARWI6.js} +5 -4
- package/dist/{setup-XJH3E7YM.js → setup-WENLVPVP.js} +9 -9
- package/dist/{skill-FZIN4W4Q.js → skill-TUVOTW4Z.js} +5 -4
- package/dist/skills/dreaming/SKILL.md +6 -4
- package/dist/skills/dreaming/references/INSTALL.md +4 -5
- package/dist/skills/dreaming/scripts/dream.ts +5 -27
- package/dist/skills/dreaming/scripts/wake-context-dreams.sh +1 -1
- package/dist/skills/imagegen/SKILL.md +6 -5
- package/dist/skills/imagegen/references/INSTALL.md +1 -1
- package/dist/skills/resonance/SKILL.md +4 -1
- package/dist/skills/resonance/references/INSTALL.md +2 -2
- package/dist/skills/resonance/scripts/resonance-hook.sh +2 -0
- package/dist/skills/resonance/scripts/resonance.ts +35 -5
- package/dist/skills/volute-admin/SKILL.md +83 -0
- package/dist/skills/volute-mind/SKILL.md +12 -12
- package/dist/skills-XNZK6P4K.js +61 -0
- package/dist/sleep-manager-53DZOWW7.js +32 -0
- package/dist/spirit-N4W4UQRH.js +217 -0
- package/dist/{split-EXYGGGQN.js → split-STOROBYJ.js} +1 -1
- package/dist/{sprout-AXQ6H5DB.js → sprout-L2GFOVF7.js} +9 -8
- package/dist/{start-MTOVL6SY.js → start-K2NCUUCG.js} +5 -4
- package/dist/{status-ZRO37MWR.js → status-TCUMUO6M.js} +5 -5
- package/dist/{stop-OK5WEPVC.js → stop-H26JZDXF.js} +5 -4
- package/dist/system-chat-NPYFYZVI.js +32 -0
- package/dist/{systems-W3BBMSOZ.js → systems-DHBKVYEY.js} +6 -5
- package/dist/{tailscale-BM72RXCJ.js → tailscale-XHQBZROW.js} +2 -1
- package/dist/{template-hash-3HOR4UAJ.js → template-hash-A6VVKOXJ.js} +2 -1
- package/dist/up-6I6BHRTO.js +17 -0
- package/dist/{update-PLPHMMZ2.js → update-QVPRF6GR.js} +5 -5
- package/dist/{update-check-CVCN7MF6.js → update-check-ZD6OOIYQ.js} +3 -2
- package/dist/{upgrade-I6NPCYUU.js → upgrade-O4Q7WJM3.js} +12 -14
- package/dist/{version-notify-2NTWVEHL.js → version-notify-TCKWBZZG.js} +22 -23
- package/dist/web-assets/assets/index-Bui7U9Uu.css +1 -0
- package/dist/web-assets/assets/index-e36DIo1b.js +73 -0
- package/dist/web-assets/ext-theme.css +94 -0
- package/dist/web-assets/index.html +2 -2
- package/drizzle/0000_baseline.sql +152 -0
- package/drizzle/0001_add_conversation_private.sql +1 -0
- package/drizzle/0002_turns.sql +21 -0
- package/drizzle/0003_turn_feed_links.sql +11 -0
- package/drizzle/0004_spirits.sql +5 -0
- package/drizzle/meta/0000_snapshot.json +3 -223
- package/drizzle/meta/0001_snapshot.json +3 -294
- package/drizzle/meta/0002_snapshot.json +3 -335
- package/drizzle/meta/0003_snapshot.json +3 -413
- package/drizzle/meta/0004_snapshot.json +3 -406
- package/drizzle/meta/_journal.json +10 -101
- package/package.json +3 -3
- package/packages/extensions/notes/dist/ui/assets/index-8jWEv9SA.js +61 -0
- package/packages/extensions/notes/dist/ui/assets/index-DkaB7Ytd.css +1 -0
- package/packages/extensions/notes/dist/ui/index.html +2 -2
- package/packages/extensions/notes/skills/notes/SKILL.md +8 -8
- package/packages/extensions/pages/skills/pages/SKILL.md +17 -44
- package/templates/_base/.init/.config/hooks/pre-prompt/session-activity.ts +40 -0
- package/templates/_base/.init/.local/bin/volute +27 -0
- package/templates/_base/.init/.local/hooks/pre-prompt/session-activity.ts +40 -0
- package/templates/_base/.init/.local/hooks/startup-context.ts +58 -0
- package/templates/_base/home/.config/routes.json +1 -1
- package/templates/_base/src/lib/auto-commit.ts +82 -43
- package/templates/_base/src/lib/daemon-client.ts +40 -36
- package/templates/_base/src/lib/format-prefix.ts +1 -0
- package/templates/_base/src/lib/hook-loader.ts +155 -0
- package/templates/_base/src/lib/router.ts +17 -1
- package/templates/_base/src/lib/startup.ts +17 -12
- package/templates/_base/src/lib/transparency.ts +2 -2
- package/templates/_base/src/lib/volute-server.ts +2 -5
- package/templates/claude/.init/.claude/settings.json +1 -1
- package/templates/claude/.init/.config/routes.json +2 -2
- package/templates/claude/src/agent.ts +97 -14
- package/templates/claude/src/lib/hooks/auto-commit.ts +7 -3
- package/templates/claude/src/lib/message-channel.ts +7 -2
- package/templates/claude/src/server.ts +0 -9
- package/templates/codex/.init/.config/routes.json +11 -0
- package/templates/codex/.init/AGENTS.md +29 -0
- package/templates/codex/home/.config/config.json.tmpl +7 -0
- package/templates/codex/package.json.tmpl +20 -0
- package/templates/codex/src/agent.ts +553 -0
- package/templates/codex/src/lib/content.ts +16 -0
- package/templates/codex/src/lib/session-store.ts +56 -0
- package/templates/codex/src/server.ts +59 -0
- package/templates/codex/volute-template.json +8 -0
- package/templates/pi/.init/.config/routes.json +2 -2
- package/templates/pi/package.json.tmpl +1 -1
- package/templates/pi/src/agent.ts +63 -9
- package/templates/pi/src/lib/event-handler.ts +6 -4
- package/templates/pi/src/lib/reply-instructions-extension.ts +32 -11
- package/dist/chunk-7D47T4RB.js +0 -84
- package/dist/chunk-CVH6Y2YG.js +0 -59
- package/dist/chunk-EFP3PE6C.js +0 -232
- package/dist/chunk-LIRWLNAK.js +0 -729
- package/dist/daemon-client-BCTFGVCZ.js +0 -9
- package/dist/down-NGBMGORS.js +0 -14
- package/dist/message-delivery-6YMVNOEC.js +0 -28
- package/dist/migrate-registry-to-db-FK35IPEH.js +0 -110
- package/dist/mind-manager-YFCOIAAX.js +0 -18
- package/dist/pages-watcher-Z3PKNROC.js +0 -21
- package/dist/read-WQMPTSN2.js +0 -46
- package/dist/seed-WUQMPLDM.js +0 -71
- package/dist/skills/sessions/SKILL.md +0 -49
- package/dist/sleep-manager-O7YQFCV5.js +0 -30
- package/dist/up-BXUAIDXB.js +0 -17
- package/dist/web-assets/assets/index--kREqKl9.js +0 -72
- package/dist/web-assets/assets/index-BXYTG0nJ.css +0 -1
- package/drizzle/0000_flaky_mariko_yashida.sql +0 -34
- package/drizzle/0001_careless_warpath.sql +0 -12
- package/drizzle/0002_wealthy_the_call.sql +0 -6
- package/drizzle/0003_clean_ego.sql +0 -12
- package/drizzle/0004_magical_silverclaw.sql +0 -1
- package/drizzle/0005_rename_agents_to_minds.sql +0 -11
- package/drizzle/0006_mind_history.sql +0 -20
- package/drizzle/0007_system_prompts.sql +0 -5
- package/drizzle/0008_volute_channels.sql +0 -24
- package/drizzle/0009_shared_skills.sql +0 -9
- package/drizzle/0010_delivery_queue.sql +0 -12
- package/drizzle/0011_rename_human_to_brain.sql +0 -1
- package/drizzle/0012_activity.sql +0 -11
- package/drizzle/0013_user_profiles.sql +0 -3
- package/drizzle/0014_conversation_reads.sql +0 -7
- package/drizzle/0015_notes.sql +0 -23
- package/drizzle/0016_note_reactions_and_replies.sql +0 -15
- package/drizzle/0017_minds.sql +0 -16
- package/drizzle/meta/0005_snapshot.json +0 -410
- package/drizzle/meta/0006_snapshot.json +0 -7
- package/drizzle/meta/0007_snapshot.json +0 -7
- package/drizzle/meta/0008_snapshot.json +0 -7
- package/drizzle/meta/0009_snapshot.json +0 -7
- package/drizzle/meta/0010_snapshot.json +0 -7
- package/drizzle/meta/0011_snapshot.json +0 -7
- package/drizzle/meta/0012_snapshot.json +0 -7
- package/drizzle/meta/0013_snapshot.json +0 -7
- package/packages/extensions/notes/dist/ui/assets/index-DgawVO5g.css +0 -1
- package/packages/extensions/notes/dist/ui/assets/index-qUWoeC4c.js +0 -2
- package/packages/extensions/notes/skills/notes/scripts/notes.mjs +0 -185
- package/templates/_base/.init/.config/hooks/startup-context.sh +0 -46
- package/templates/_base/.init/.config/scripts/session-reader.ts +0 -59
- package/templates/_base/home/public/.gitkeep +0 -0
- package/templates/_base/src/lib/session-monitor.ts +0 -400
- package/templates/claude/src/lib/hooks/session-context.ts +0 -32
- package/templates/pi/src/lib/session-context-extension.ts +0 -35
- /package/templates/_base/.init/{.config → .local}/hooks/wake-context.sh +0 -0
|
@@ -3,9 +3,11 @@ import {
|
|
|
3
3
|
logger_default
|
|
4
4
|
} from "./chunk-YUIHSKR6.js";
|
|
5
5
|
import {
|
|
6
|
-
activity,
|
|
7
6
|
getDb
|
|
8
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-LRCG2JLP.js";
|
|
8
|
+
import {
|
|
9
|
+
activity
|
|
10
|
+
} from "./chunk-RPZZSXV3.js";
|
|
9
11
|
|
|
10
12
|
// src/lib/events/activity-events.ts
|
|
11
13
|
var subscribers = /* @__PURE__ */ new Set();
|
|
@@ -25,6 +27,8 @@ async function publish(event) {
|
|
|
25
27
|
mind: event.mind,
|
|
26
28
|
summary: event.summary,
|
|
27
29
|
metadata: event.metadata ? JSON.stringify(event.metadata) : null,
|
|
30
|
+
turn_id: event.turn_id ?? null,
|
|
31
|
+
source_event_id: event.source_event_id ?? null,
|
|
28
32
|
created_at
|
|
29
33
|
});
|
|
30
34
|
id = Number(result.lastInsertRowid);
|
|
@@ -3,20 +3,6 @@ import {
|
|
|
3
3
|
__export
|
|
4
4
|
} from "./chunk-K3NQKI34.js";
|
|
5
5
|
|
|
6
|
-
// src/lib/db.ts
|
|
7
|
-
import { chmodSync, existsSync } from "fs";
|
|
8
|
-
import { dirname as dirname2, resolve as resolve2 } from "path";
|
|
9
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
10
|
-
import { drizzle } from "drizzle-orm/libsql";
|
|
11
|
-
import { migrate } from "drizzle-orm/libsql/migrator";
|
|
12
|
-
|
|
13
|
-
// src/lib/registry.ts
|
|
14
|
-
import { mkdirSync } from "fs";
|
|
15
|
-
import { homedir } from "os";
|
|
16
|
-
import { dirname, resolve } from "path";
|
|
17
|
-
import { fileURLToPath } from "url";
|
|
18
|
-
import { eq, isNull } from "drizzle-orm";
|
|
19
|
-
|
|
20
6
|
// src/lib/schema.ts
|
|
21
7
|
var schema_exports = {};
|
|
22
8
|
__export(schema_exports, {
|
|
@@ -31,6 +17,7 @@ __export(schema_exports, {
|
|
|
31
17
|
sessions: () => sessions,
|
|
32
18
|
sharedSkills: () => sharedSkills,
|
|
33
19
|
systemPrompts: () => systemPrompts,
|
|
20
|
+
turns: () => turns,
|
|
34
21
|
users: () => users
|
|
35
22
|
});
|
|
36
23
|
import { sql } from "drizzle-orm";
|
|
@@ -47,9 +34,14 @@ var minds = sqliteTable(
|
|
|
47
34
|
template: text("template"),
|
|
48
35
|
template_hash: text("template_hash"),
|
|
49
36
|
running: integer("running").notNull().default(0),
|
|
37
|
+
mind_type: text("mind_type").notNull().default("mind"),
|
|
38
|
+
created_by: text("created_by"),
|
|
50
39
|
created_at: text("created_at").notNull().default(sql`(datetime('now'))`)
|
|
51
40
|
},
|
|
52
|
-
(table) => [
|
|
41
|
+
(table) => [
|
|
42
|
+
index("idx_minds_parent").on(table.parent),
|
|
43
|
+
index("idx_minds_mind_type").on(table.mind_type)
|
|
44
|
+
]
|
|
53
45
|
);
|
|
54
46
|
var users = sqliteTable("users", {
|
|
55
47
|
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
@@ -72,6 +64,7 @@ var conversations = sqliteTable(
|
|
|
72
64
|
name: text("name"),
|
|
73
65
|
user_id: integer("user_id").references(() => users.id),
|
|
74
66
|
title: text("title"),
|
|
67
|
+
private: integer("private").notNull().default(0),
|
|
75
68
|
created_at: text("created_at").notNull().default(sql`(datetime('now'))`),
|
|
76
69
|
updated_at: text("updated_at").notNull().default(sql`(datetime('now'))`)
|
|
77
70
|
},
|
|
@@ -82,6 +75,22 @@ var conversations = sqliteTable(
|
|
|
82
75
|
uniqueIndex("idx_conversations_name").on(table.name)
|
|
83
76
|
]
|
|
84
77
|
);
|
|
78
|
+
var turns = sqliteTable(
|
|
79
|
+
"turns",
|
|
80
|
+
{
|
|
81
|
+
id: text("id").primaryKey(),
|
|
82
|
+
mind: text("mind").notNull(),
|
|
83
|
+
session: text("session"),
|
|
84
|
+
trigger_event_id: integer("trigger_event_id"),
|
|
85
|
+
summary_event_id: integer("summary_event_id"),
|
|
86
|
+
status: text("status").notNull().default("active"),
|
|
87
|
+
created_at: text("created_at").notNull().default(sql`(datetime('now'))`)
|
|
88
|
+
},
|
|
89
|
+
(table) => [
|
|
90
|
+
index("idx_turns_mind").on(table.mind),
|
|
91
|
+
index("idx_turns_mind_status").on(table.mind, table.status)
|
|
92
|
+
]
|
|
93
|
+
);
|
|
85
94
|
var mindHistory = sqliteTable(
|
|
86
95
|
"mind_history",
|
|
87
96
|
{
|
|
@@ -94,12 +103,14 @@ var mindHistory = sqliteTable(
|
|
|
94
103
|
type: text("type").notNull(),
|
|
95
104
|
content: text("content"),
|
|
96
105
|
metadata: text("metadata"),
|
|
106
|
+
turn_id: text("turn_id"),
|
|
97
107
|
created_at: text("created_at").notNull().default(sql`(datetime('now'))`)
|
|
98
108
|
},
|
|
99
109
|
(table) => [
|
|
100
110
|
index("idx_mind_history_mind").on(table.mind),
|
|
101
111
|
index("idx_mind_history_mind_channel").on(table.mind, table.channel),
|
|
102
|
-
index("idx_mind_history_mind_type").on(table.mind, table.type)
|
|
112
|
+
index("idx_mind_history_mind_type").on(table.mind, table.type),
|
|
113
|
+
index("idx_mind_history_turn_id").on(table.turn_id)
|
|
103
114
|
]
|
|
104
115
|
);
|
|
105
116
|
var conversationParticipants = sqliteTable(
|
|
@@ -159,11 +170,14 @@ var activity = sqliteTable(
|
|
|
159
170
|
mind: text("mind").notNull(),
|
|
160
171
|
summary: text("summary").notNull(),
|
|
161
172
|
metadata: text("metadata"),
|
|
173
|
+
turn_id: text("turn_id"),
|
|
174
|
+
source_event_id: integer("source_event_id"),
|
|
162
175
|
created_at: text("created_at").notNull().default(sql`(datetime('now'))`)
|
|
163
176
|
},
|
|
164
177
|
(table) => [
|
|
165
178
|
index("idx_activity_created_at").on(table.created_at),
|
|
166
|
-
index("idx_activity_mind").on(table.mind)
|
|
179
|
+
index("idx_activity_mind").on(table.mind),
|
|
180
|
+
index("idx_activity_turn_id").on(table.turn_id)
|
|
167
181
|
]
|
|
168
182
|
);
|
|
169
183
|
var conversationReads = sqliteTable(
|
|
@@ -185,170 +199,21 @@ var messages = sqliteTable(
|
|
|
185
199
|
role: text("role").notNull(),
|
|
186
200
|
sender_name: text("sender_name"),
|
|
187
201
|
content: text("content").notNull(),
|
|
202
|
+
source_event_id: integer("source_event_id"),
|
|
203
|
+
turn_id: text("turn_id"),
|
|
188
204
|
created_at: text("created_at").notNull().default(sql`(datetime('now'))`)
|
|
189
205
|
},
|
|
190
|
-
(table) => [
|
|
206
|
+
(table) => [
|
|
207
|
+
index("idx_messages_conversation_id").on(table.conversation_id),
|
|
208
|
+
index("idx_messages_turn_id").on(table.turn_id)
|
|
209
|
+
]
|
|
191
210
|
);
|
|
192
211
|
|
|
193
|
-
// src/lib/registry.ts
|
|
194
|
-
function voluteHome() {
|
|
195
|
-
if (process.env.VOLUTE_HOME) return process.env.VOLUTE_HOME;
|
|
196
|
-
const dir = dirname(fileURLToPath(import.meta.url));
|
|
197
|
-
if (dir.endsWith("/src/lib")) {
|
|
198
|
-
throw new Error(
|
|
199
|
-
'VOLUTE_HOME must be set when running from source. For tests, run via "npm test" or add "--import ./test/setup.ts".'
|
|
200
|
-
);
|
|
201
|
-
}
|
|
202
|
-
return resolve(homedir(), ".volute");
|
|
203
|
-
}
|
|
204
|
-
function voluteUserHome() {
|
|
205
|
-
if (process.env.VOLUTE_USER_HOME) return process.env.VOLUTE_USER_HOME;
|
|
206
|
-
return resolve(homedir(), ".volute");
|
|
207
|
-
}
|
|
208
|
-
function voluteSystemDir() {
|
|
209
|
-
return resolve(voluteHome(), "system");
|
|
210
|
-
}
|
|
211
|
-
function ensureSystemDir() {
|
|
212
|
-
mkdirSync(voluteSystemDir(), { recursive: true });
|
|
213
|
-
}
|
|
214
|
-
function ensureVoluteHome() {
|
|
215
|
-
const mindsBase = process.env.VOLUTE_MINDS_DIR ?? resolve(voluteHome(), "minds");
|
|
216
|
-
mkdirSync(mindsBase, { recursive: true });
|
|
217
|
-
ensureSystemDir();
|
|
218
|
-
}
|
|
219
|
-
function rowToEntry(row) {
|
|
220
|
-
return {
|
|
221
|
-
name: row.name,
|
|
222
|
-
port: row.port,
|
|
223
|
-
created: row.created_at,
|
|
224
|
-
running: row.running === 1,
|
|
225
|
-
stage: row.stage ?? (row.parent ? void 0 : "sprouted"),
|
|
226
|
-
template: row.template ?? void 0,
|
|
227
|
-
templateHash: row.template_hash ?? void 0,
|
|
228
|
-
parent: row.parent ?? void 0,
|
|
229
|
-
dir: row.dir ?? void 0,
|
|
230
|
-
branch: row.branch ?? void 0
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
async function readRegistry() {
|
|
234
|
-
const db2 = await getDb();
|
|
235
|
-
const rows = await db2.select().from(minds).where(isNull(minds.parent));
|
|
236
|
-
return rows.map(rowToEntry);
|
|
237
|
-
}
|
|
238
|
-
async function readAllMinds() {
|
|
239
|
-
const db2 = await getDb();
|
|
240
|
-
const rows = await db2.select().from(minds);
|
|
241
|
-
return rows.map(rowToEntry);
|
|
242
|
-
}
|
|
243
|
-
var MIND_NAME_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
|
|
244
|
-
var MIND_NAME_MAX = 64;
|
|
245
|
-
function validateMindName(name) {
|
|
246
|
-
if (!name) return "Mind name is required";
|
|
247
|
-
if (name.length > MIND_NAME_MAX) return `Mind name must be at most ${MIND_NAME_MAX} characters`;
|
|
248
|
-
if (!MIND_NAME_RE.test(name)) {
|
|
249
|
-
return "Mind name must start with alphanumeric and contain only alphanumeric, dots, dashes, or underscores";
|
|
250
|
-
}
|
|
251
|
-
return null;
|
|
252
|
-
}
|
|
253
|
-
async function addMind(name, port, stage, template) {
|
|
254
|
-
const err = validateMindName(name);
|
|
255
|
-
if (err) throw new Error(err);
|
|
256
|
-
const db2 = await getDb();
|
|
257
|
-
await db2.insert(minds).values({ name, port, stage: stage ?? null, template: template ?? null }).onConflictDoUpdate({
|
|
258
|
-
target: minds.name,
|
|
259
|
-
set: { port, stage: stage ?? null, template: template ?? null }
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
async function addVariant(name, parent, port, dir, branch) {
|
|
263
|
-
const err = validateMindName(name);
|
|
264
|
-
if (err) throw new Error(err);
|
|
265
|
-
const db2 = await getDb();
|
|
266
|
-
await db2.insert(minds).values({ name, port, parent, dir, branch }).onConflictDoUpdate({
|
|
267
|
-
target: minds.name,
|
|
268
|
-
set: { port, parent, dir, branch }
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
async function removeMind(name) {
|
|
272
|
-
const db2 = await getDb();
|
|
273
|
-
await db2.delete(minds).where(eq(minds.name, name));
|
|
274
|
-
}
|
|
275
|
-
async function setMindRunning(name, running) {
|
|
276
|
-
const db2 = await getDb();
|
|
277
|
-
await db2.update(minds).set({ running: running ? 1 : 0 }).where(eq(minds.name, name));
|
|
278
|
-
}
|
|
279
|
-
async function setMindStage(name, stage) {
|
|
280
|
-
const db2 = await getDb();
|
|
281
|
-
await db2.update(minds).set({ stage }).where(eq(minds.name, name));
|
|
282
|
-
}
|
|
283
|
-
async function setMindTemplateHash(name, hash) {
|
|
284
|
-
const db2 = await getDb();
|
|
285
|
-
await db2.update(minds).set({ template_hash: hash }).where(eq(minds.name, name));
|
|
286
|
-
}
|
|
287
|
-
async function findMind(name) {
|
|
288
|
-
const db2 = await getDb();
|
|
289
|
-
const rows = await db2.select().from(minds).where(eq(minds.name, name));
|
|
290
|
-
if (rows.length === 0) return void 0;
|
|
291
|
-
return rowToEntry(rows[0]);
|
|
292
|
-
}
|
|
293
|
-
async function findVariants(parent) {
|
|
294
|
-
const db2 = await getDb();
|
|
295
|
-
const rows = await db2.select().from(minds).where(eq(minds.parent, parent));
|
|
296
|
-
return rows.map(rowToEntry);
|
|
297
|
-
}
|
|
298
|
-
async function getBaseName(name) {
|
|
299
|
-
const entry = await findMind(name);
|
|
300
|
-
return entry?.parent ?? name;
|
|
301
|
-
}
|
|
302
|
-
function mindDir(name) {
|
|
303
|
-
if (process.env.VOLUTE_MINDS_DIR) {
|
|
304
|
-
return resolve(process.env.VOLUTE_MINDS_DIR, name);
|
|
305
|
-
}
|
|
306
|
-
return resolve(voluteHome(), "minds", name);
|
|
307
|
-
}
|
|
308
|
-
function stateDir(name) {
|
|
309
|
-
return resolve(voluteSystemDir(), "state", name);
|
|
310
|
-
}
|
|
311
|
-
async function nextPort() {
|
|
312
|
-
const db2 = await getDb();
|
|
313
|
-
const rows = await db2.select({ port: minds.port }).from(minds);
|
|
314
|
-
const usedPorts = new Set(rows.map((r) => r.port));
|
|
315
|
-
const basePort = parseInt(process.env.VOLUTE_BASE_PORT || "4100", 10);
|
|
316
|
-
let port = basePort;
|
|
317
|
-
while (usedPorts.has(port)) port++;
|
|
318
|
-
if (port > 65535) throw new Error("No available ports \u2014 all ports 4100-65535 are allocated");
|
|
319
|
-
return port;
|
|
320
|
-
}
|
|
321
|
-
function daemonLoopback() {
|
|
322
|
-
const host = process.env.VOLUTE_DAEMON_HOSTNAME || "127.0.0.1";
|
|
323
|
-
if (host === "0.0.0.0") return "127.0.0.1";
|
|
324
|
-
if (host === "::") return "[::1]";
|
|
325
|
-
return host;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// src/lib/db.ts
|
|
329
|
-
var __dirname = dirname2(fileURLToPath2(import.meta.url));
|
|
330
|
-
var migrationsFolder = existsSync(resolve2(__dirname, "../drizzle")) ? resolve2(__dirname, "../drizzle") : resolve2(__dirname, "../../drizzle");
|
|
331
|
-
var db = null;
|
|
332
|
-
async function getDb() {
|
|
333
|
-
if (db) return db;
|
|
334
|
-
const dbPath = process.env.VOLUTE_DB_PATH || resolve2(voluteSystemDir(), "volute.db");
|
|
335
|
-
db = drizzle({ connection: { url: `file:${dbPath}` }, schema: schema_exports });
|
|
336
|
-
await migrate(db, { migrationsFolder });
|
|
337
|
-
try {
|
|
338
|
-
chmodSync(dbPath, 384);
|
|
339
|
-
} catch (err) {
|
|
340
|
-
console.error(
|
|
341
|
-
`[volute] WARNING: Failed to restrict database file permissions on ${dbPath}:`,
|
|
342
|
-
err
|
|
343
|
-
);
|
|
344
|
-
}
|
|
345
|
-
return db;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
212
|
export {
|
|
349
213
|
minds,
|
|
350
214
|
users,
|
|
351
215
|
conversations,
|
|
216
|
+
turns,
|
|
352
217
|
mindHistory,
|
|
353
218
|
conversationParticipants,
|
|
354
219
|
sessions,
|
|
@@ -358,26 +223,5 @@ export {
|
|
|
358
223
|
activity,
|
|
359
224
|
conversationReads,
|
|
360
225
|
messages,
|
|
361
|
-
|
|
362
|
-
voluteHome,
|
|
363
|
-
voluteUserHome,
|
|
364
|
-
voluteSystemDir,
|
|
365
|
-
ensureSystemDir,
|
|
366
|
-
ensureVoluteHome,
|
|
367
|
-
readRegistry,
|
|
368
|
-
readAllMinds,
|
|
369
|
-
validateMindName,
|
|
370
|
-
addMind,
|
|
371
|
-
addVariant,
|
|
372
|
-
removeMind,
|
|
373
|
-
setMindRunning,
|
|
374
|
-
setMindStage,
|
|
375
|
-
setMindTemplateHash,
|
|
376
|
-
findMind,
|
|
377
|
-
findVariants,
|
|
378
|
-
getBaseName,
|
|
379
|
-
mindDir,
|
|
380
|
-
stateDir,
|
|
381
|
-
nextPort,
|
|
382
|
-
daemonLoopback
|
|
226
|
+
schema_exports
|
|
383
227
|
};
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
readEnv,
|
|
4
4
|
sharedEnvPath,
|
|
5
5
|
writeEnv
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2NGTS5UU.js";
|
|
7
7
|
import {
|
|
8
8
|
logger_default
|
|
9
9
|
} from "./chunk-YUIHSKR6.js";
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from "./chunk-D424ZQGI.js";
|
|
13
13
|
import {
|
|
14
14
|
voluteSystemDir
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-LRCG2JLP.js";
|
|
16
16
|
|
|
17
17
|
// src/commands/import.ts
|
|
18
18
|
import {
|
|
@@ -112,7 +112,7 @@ async function run(args) {
|
|
|
112
112
|
return;
|
|
113
113
|
}
|
|
114
114
|
const wsDir = resolveWorkspace(inputPath);
|
|
115
|
-
const { daemonFetch } = await import("./daemon-client-
|
|
115
|
+
const { daemonFetch } = await import("./daemon-client-6QXHZ7US.js");
|
|
116
116
|
const { getClient, urlOf } = await import("./api-client-YPKOZP2O.js");
|
|
117
117
|
const client = getClient();
|
|
118
118
|
const res = await daemonFetch(urlOf(client.api.minds.import.$url()), {
|
|
@@ -152,7 +152,7 @@ async function importArchive(archivePath, nameOverride) {
|
|
|
152
152
|
console.error(`File not found: ${archivePath}`);
|
|
153
153
|
process.exit(1);
|
|
154
154
|
}
|
|
155
|
-
const { extractArchive } = await import("./archive-
|
|
155
|
+
const { extractArchive } = await import("./archive-INXYFVCW.js");
|
|
156
156
|
const tempDir = resolve2(tmpdir(), `volute-import-${Date.now()}`);
|
|
157
157
|
mkdirSync(tempDir, { recursive: true });
|
|
158
158
|
let extracted;
|
|
@@ -164,7 +164,7 @@ async function importArchive(archivePath, nameOverride) {
|
|
|
164
164
|
process.exit(1);
|
|
165
165
|
}
|
|
166
166
|
try {
|
|
167
|
-
const { daemonFetch } = await import("./daemon-client-
|
|
167
|
+
const { daemonFetch } = await import("./daemon-client-6QXHZ7US.js");
|
|
168
168
|
const { getClient, urlOf } = await import("./api-client-YPKOZP2O.js");
|
|
169
169
|
const client = getClient();
|
|
170
170
|
const res = await daemonFetch(urlOf(client.api.minds.import.$url()), {
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
subscribe
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-QZANELPX.js";
|
|
5
5
|
import {
|
|
6
6
|
logger_default
|
|
7
7
|
} from "./chunk-YUIHSKR6.js";
|
|
8
|
+
import {
|
|
9
|
+
getDb
|
|
10
|
+
} from "./chunk-LRCG2JLP.js";
|
|
8
11
|
import {
|
|
9
12
|
conversationParticipants,
|
|
10
13
|
conversationReads,
|
|
11
14
|
conversations,
|
|
12
|
-
getDb,
|
|
13
15
|
messages,
|
|
14
16
|
users
|
|
15
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-RPZZSXV3.js";
|
|
16
18
|
|
|
17
19
|
// src/lib/events/conversations.ts
|
|
18
20
|
import { randomUUID } from "crypto";
|
|
@@ -109,53 +111,6 @@ function publish(conversationId, event) {
|
|
|
109
111
|
}
|
|
110
112
|
|
|
111
113
|
// src/lib/events/conversations.ts
|
|
112
|
-
async function migrateGroupDMsToChannels() {
|
|
113
|
-
const db = await getDb();
|
|
114
|
-
await db.transaction(async (tx) => {
|
|
115
|
-
const overloadedDMs = await tx.select({
|
|
116
|
-
conversationId: conversationParticipants.conversation_id,
|
|
117
|
-
count: sql`COUNT(*)`
|
|
118
|
-
}).from(conversationParticipants).innerJoin(conversations, eq(conversationParticipants.conversation_id, conversations.id)).where(eq(conversations.type, "dm")).groupBy(conversationParticipants.conversation_id).having(sql`COUNT(*) > 2`);
|
|
119
|
-
const dmIds = overloadedDMs.map((r) => r.conversationId);
|
|
120
|
-
await tx.update(conversations).set({
|
|
121
|
-
type: "channel",
|
|
122
|
-
name: sql`COALESCE(${conversations.name}, ${conversations.title})`
|
|
123
|
-
}).where(eq(conversations.type, "group"));
|
|
124
|
-
if (dmIds.length > 0) {
|
|
125
|
-
await tx.update(conversations).set({
|
|
126
|
-
type: "channel",
|
|
127
|
-
name: sql`COALESCE(${conversations.name}, ${conversations.title})`
|
|
128
|
-
}).where(inArray(conversations.id, dmIds));
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
await migrateChannelEntryTypes();
|
|
132
|
-
}
|
|
133
|
-
async function migrateChannelEntryTypes() {
|
|
134
|
-
const { existsSync, readdirSync, readFileSync, writeFileSync } = await import("fs");
|
|
135
|
-
const { join } = await import("path");
|
|
136
|
-
const home = join((await import("os")).homedir(), ".volute", "state");
|
|
137
|
-
if (!existsSync(home)) return;
|
|
138
|
-
for (const name of readdirSync(home)) {
|
|
139
|
-
const filePath = join(home, name, "channels.json");
|
|
140
|
-
if (!existsSync(filePath)) continue;
|
|
141
|
-
try {
|
|
142
|
-
const raw = readFileSync(filePath, "utf-8");
|
|
143
|
-
const map = JSON.parse(raw);
|
|
144
|
-
let changed = false;
|
|
145
|
-
for (const entry of Object.values(map)) {
|
|
146
|
-
if (entry.type === "group") {
|
|
147
|
-
entry.type = "channel";
|
|
148
|
-
changed = true;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
if (changed) {
|
|
152
|
-
writeFileSync(filePath, `${JSON.stringify(map, null, 2)}
|
|
153
|
-
`);
|
|
154
|
-
}
|
|
155
|
-
} catch {
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
114
|
async function createConversation(mindName, channel, opts) {
|
|
160
115
|
const db = await getDb();
|
|
161
116
|
const id = randomUUID();
|
|
@@ -194,6 +149,7 @@ async function createConversation(mindName, channel, opts) {
|
|
|
194
149
|
name,
|
|
195
150
|
user_id: opts?.userId ?? null,
|
|
196
151
|
title: opts?.title ?? null,
|
|
152
|
+
private: 0,
|
|
197
153
|
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
198
154
|
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
199
155
|
};
|
|
@@ -263,20 +219,24 @@ async function listConversationsForUser(userId) {
|
|
|
263
219
|
return await db.select().from(conversations).where(inArray(conversations.id, convIds)).orderBy(desc(conversations.updated_at)).all();
|
|
264
220
|
}
|
|
265
221
|
async function isParticipantOrOwner(conversationId, userId) {
|
|
266
|
-
|
|
267
|
-
const db = await getDb();
|
|
268
|
-
const row = await db.select().from(conversations).where(and(eq(conversations.id, conversationId), eq(conversations.user_id, userId))).get();
|
|
269
|
-
return row != null;
|
|
222
|
+
return isParticipant(conversationId, userId);
|
|
270
223
|
}
|
|
271
224
|
async function deleteConversationForUser(id, userId) {
|
|
272
225
|
if (!await isParticipantOrOwner(id, userId)) return false;
|
|
273
226
|
await deleteConversation(id);
|
|
274
227
|
return true;
|
|
275
228
|
}
|
|
276
|
-
async function addMessage(conversationId, role, senderName, content) {
|
|
229
|
+
async function addMessage(conversationId, role, senderName, content, opts) {
|
|
277
230
|
const db = await getDb();
|
|
278
231
|
const serialized = JSON.stringify(content);
|
|
279
|
-
const [result] = await db.insert(messages).values({
|
|
232
|
+
const [result] = await db.insert(messages).values({
|
|
233
|
+
conversation_id: conversationId,
|
|
234
|
+
role,
|
|
235
|
+
sender_name: senderName,
|
|
236
|
+
content: serialized,
|
|
237
|
+
source_event_id: opts?.sourceEventId ?? null,
|
|
238
|
+
turn_id: opts?.turnId ?? null
|
|
239
|
+
}).returning({ id: messages.id, created_at: messages.created_at });
|
|
280
240
|
await db.update(conversations).set({ updated_at: sql`datetime('now')` }).where(eq(conversations.id, conversationId));
|
|
281
241
|
if (role === "user") {
|
|
282
242
|
const firstText = content.find((b) => b.type === "text");
|
|
@@ -522,6 +482,10 @@ async function isConversationForMind(mindName, conversationId) {
|
|
|
522
482
|
).get();
|
|
523
483
|
return !!participant;
|
|
524
484
|
}
|
|
485
|
+
async function setConversationPrivate(id, isPrivate) {
|
|
486
|
+
const db = await getDb();
|
|
487
|
+
await db.update(conversations).set({ private: isPrivate ? 1 : 0 }).where(eq(conversations.id, id));
|
|
488
|
+
}
|
|
525
489
|
async function deleteConversation(id) {
|
|
526
490
|
const db = await getDb();
|
|
527
491
|
await db.delete(conversations).where(eq(conversations.id, id));
|
|
@@ -593,7 +557,6 @@ export {
|
|
|
593
557
|
initWebhook,
|
|
594
558
|
subscribe2 as subscribe,
|
|
595
559
|
publish,
|
|
596
|
-
migrateGroupDMsToChannels,
|
|
597
560
|
createConversation,
|
|
598
561
|
getOrCreateConversation,
|
|
599
562
|
getConversation,
|
|
@@ -611,6 +574,7 @@ export {
|
|
|
611
574
|
findDMConversation,
|
|
612
575
|
listConversationsForMind,
|
|
613
576
|
isConversationForMind,
|
|
577
|
+
setConversationPrivate,
|
|
614
578
|
deleteConversation,
|
|
615
579
|
createChannel,
|
|
616
580
|
getChannelByName,
|