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
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"gateUnmatched": true,
|
|
3
3
|
"rules": [
|
|
4
|
-
{ "channel": "
|
|
5
|
-
{ "channel": "
|
|
4
|
+
{ "channel": "*", "isDM": true, "session": "${channel}" },
|
|
5
|
+
{ "channel": "*", "isDM": false, "session": "group-${channel}" }
|
|
6
6
|
],
|
|
7
7
|
"sessions": {
|
|
8
8
|
"group-*": { "batch": { "debounce": 20, "maxWait": 120, "triggers": ["@{{name}}"] } }
|
|
@@ -3,12 +3,13 @@ import { resolve as resolvePath } from "node:path";
|
|
|
3
3
|
import type { HookCallback } from "@anthropic-ai/claude-agent-sdk";
|
|
4
4
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
5
5
|
import { toSDKContent } from "./lib/content.js";
|
|
6
|
+
import { daemonEmit } from "./lib/daemon-client.js";
|
|
7
|
+
import { runHooks } from "./lib/hook-loader.js";
|
|
6
8
|
import { createAutoCommitHook } from "./lib/hooks/auto-commit.js";
|
|
7
9
|
import { createIdentityReloadHook } from "./lib/hooks/identity-reload.js";
|
|
8
10
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports -- used as value
|
|
9
11
|
import { createPreCompactHook } from "./lib/hooks/pre-compact.js";
|
|
10
12
|
import { createReplyInstructionsHook } from "./lib/hooks/reply-instructions.js";
|
|
11
|
-
import { createSessionContextHook } from "./lib/hooks/session-context.js";
|
|
12
13
|
import { log } from "./lib/logger.js";
|
|
13
14
|
import { createMessageChannel } from "./lib/message-channel.js";
|
|
14
15
|
import { createSessionStore } from "./lib/session-store.js";
|
|
@@ -127,6 +128,72 @@ export function createMind(options: {
|
|
|
127
128
|
}
|
|
128
129
|
}
|
|
129
130
|
|
|
131
|
+
// --- Hook event emission ---
|
|
132
|
+
|
|
133
|
+
const hooksDir = resolvePath(options.cwd, ".local/hooks");
|
|
134
|
+
|
|
135
|
+
function wrapHookWithEmit(hook: HookCallback, source: string, session: Session): HookCallback {
|
|
136
|
+
return async (...args) => {
|
|
137
|
+
const result = await hook(...args);
|
|
138
|
+
const additionalContext = (result as any)?.hookSpecificOutput?.additionalContext;
|
|
139
|
+
const decision = (result as any)?.decision;
|
|
140
|
+
if (additionalContext || decision) {
|
|
141
|
+
const channel = session.currentMessageId
|
|
142
|
+
? session.messageChannels.get(session.currentMessageId)
|
|
143
|
+
: undefined;
|
|
144
|
+
try {
|
|
145
|
+
daemonEmit({
|
|
146
|
+
type: "context",
|
|
147
|
+
content: additionalContext,
|
|
148
|
+
metadata: { source, ...(decision ? { hookAction: decision } : {}) },
|
|
149
|
+
session: session.name,
|
|
150
|
+
channel,
|
|
151
|
+
messageId: session.currentMessageId,
|
|
152
|
+
});
|
|
153
|
+
} catch (err) {
|
|
154
|
+
log("mind", `hook emit failed for ${source}:`, err);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return result;
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function createDynamicHook(event: string, session: Session): HookCallback {
|
|
162
|
+
return async (input) => {
|
|
163
|
+
try {
|
|
164
|
+
const result = await runHooks(hooksDir, event, input as Record<string, unknown>);
|
|
165
|
+
if (result.additionalContext || Object.keys(result.metadata).length > 0) {
|
|
166
|
+
const channel = session.currentMessageId
|
|
167
|
+
? session.messageChannels.get(session.currentMessageId)
|
|
168
|
+
: undefined;
|
|
169
|
+
try {
|
|
170
|
+
daemonEmit({
|
|
171
|
+
type: "context",
|
|
172
|
+
content: result.additionalContext,
|
|
173
|
+
metadata: { source: `dynamic:${event}`, ...result.metadata },
|
|
174
|
+
session: session.name,
|
|
175
|
+
channel,
|
|
176
|
+
messageId: session.currentMessageId,
|
|
177
|
+
});
|
|
178
|
+
} catch (err) {
|
|
179
|
+
log("mind", `dynamic hook emit failed for ${event}:`, err);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// Only UserPromptSubmit hooks can inject additionalContext into the conversation
|
|
183
|
+
if (event !== "pre-prompt" || !result.additionalContext) return {};
|
|
184
|
+
return {
|
|
185
|
+
hookSpecificOutput: {
|
|
186
|
+
hookEventName: "UserPromptSubmit" as const,
|
|
187
|
+
additionalContext: result.additionalContext,
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
} catch (err) {
|
|
191
|
+
log("mind", `dynamic ${event} hook failed:`, err);
|
|
192
|
+
return {};
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
130
197
|
// --- SDK stream management ---
|
|
131
198
|
|
|
132
199
|
function createStream(
|
|
@@ -135,12 +202,6 @@ export function createMind(options: {
|
|
|
135
202
|
preCompactHook: HookCallback,
|
|
136
203
|
resume?: string,
|
|
137
204
|
) {
|
|
138
|
-
const sessionContext = createSessionContextHook({
|
|
139
|
-
currentSession: session.name,
|
|
140
|
-
sessionsDir: options.sessionsDir,
|
|
141
|
-
cwd: options.cwd,
|
|
142
|
-
});
|
|
143
|
-
|
|
144
205
|
const replyInstructions = createReplyInstructionsHook(session.messageChannels);
|
|
145
206
|
|
|
146
207
|
return query({
|
|
@@ -157,9 +218,22 @@ export function createMind(options: {
|
|
|
157
218
|
resume,
|
|
158
219
|
agents,
|
|
159
220
|
hooks: {
|
|
160
|
-
PostToolUse:
|
|
161
|
-
|
|
162
|
-
|
|
221
|
+
PostToolUse: [
|
|
222
|
+
...postToolUseHooks,
|
|
223
|
+
{
|
|
224
|
+
matcher: ".*",
|
|
225
|
+
hooks: [createDynamicHook("post-tool-use", session)],
|
|
226
|
+
},
|
|
227
|
+
],
|
|
228
|
+
PreCompact: [{ hooks: [wrapHookWithEmit(preCompactHook, "pre-compact", session)] }],
|
|
229
|
+
UserPromptSubmit: [
|
|
230
|
+
{
|
|
231
|
+
hooks: [
|
|
232
|
+
wrapHookWithEmit(replyInstructions.hook, "reply-instructions", session),
|
|
233
|
+
createDynamicHook("pre-prompt", session),
|
|
234
|
+
],
|
|
235
|
+
},
|
|
236
|
+
],
|
|
163
237
|
},
|
|
164
238
|
},
|
|
165
239
|
});
|
|
@@ -193,7 +267,8 @@ export function createMind(options: {
|
|
|
193
267
|
if (!session.name.startsWith("new-")) sessionStore.save(session.name, id);
|
|
194
268
|
},
|
|
195
269
|
broadcast: (event: VoluteEvent) => broadcastToSession(session, event),
|
|
196
|
-
onTurnEnd: () => {
|
|
270
|
+
onTurnEnd: async () => {
|
|
271
|
+
await autoCommit.flushFileChanges();
|
|
197
272
|
const wasCompacting = compactionTriggered.get(session.name);
|
|
198
273
|
compactionTriggered.set(session.name, false);
|
|
199
274
|
if (wasCompacting) {
|
|
@@ -262,13 +337,21 @@ export function createMind(options: {
|
|
|
262
337
|
log("mind", `session "${session.name}": compaction complete`);
|
|
263
338
|
}
|
|
264
339
|
|
|
340
|
+
/** Emit done to both local listeners and the daemon (best-effort with retries). */
|
|
341
|
+
function emitDone() {
|
|
342
|
+
broadcastToSession(session, { type: "done" });
|
|
343
|
+
daemonEmit({ type: "done", session: session.name }).catch((err) => {
|
|
344
|
+
log("mind", `session "${session.name}": failed to emit done to daemon:`, err);
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
|
|
265
348
|
async function runStream(resume?: string) {
|
|
266
349
|
const q = createStream(session, streamAbort, preCompact.hook, resume);
|
|
267
350
|
session.currentQuery = q;
|
|
268
351
|
await consumeStream(q, session, callbacks);
|
|
269
352
|
if (session.currentMessageId !== undefined) {
|
|
270
353
|
session.messageChannels.delete(session.currentMessageId);
|
|
271
|
-
|
|
354
|
+
emitDone();
|
|
272
355
|
session.currentMessageId = undefined;
|
|
273
356
|
}
|
|
274
357
|
}
|
|
@@ -321,12 +404,12 @@ export function createMind(options: {
|
|
|
321
404
|
await runStream();
|
|
322
405
|
} catch (retryErr) {
|
|
323
406
|
log("mind", `session "${session.name}": stream consumer error:`, retryErr);
|
|
324
|
-
|
|
407
|
+
emitDone();
|
|
325
408
|
sessions.delete(session.name);
|
|
326
409
|
}
|
|
327
410
|
} else {
|
|
328
411
|
log("mind", `session "${session.name}": stream consumer error:`, err);
|
|
329
|
-
|
|
412
|
+
emitDone();
|
|
330
413
|
sessions.delete(session.name);
|
|
331
414
|
}
|
|
332
415
|
}
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import type { HookCallback } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
-
import {
|
|
2
|
+
import { flushFileChanges, trackFileChange } from "../auto-commit.js";
|
|
3
3
|
|
|
4
4
|
export function createAutoCommitHook(cwd: string) {
|
|
5
5
|
const hook: HookCallback = async (input) => {
|
|
6
6
|
const filePath = (input as { tool_input?: { file_path?: string } }).tool_input?.file_path;
|
|
7
7
|
if (filePath) {
|
|
8
|
-
|
|
8
|
+
trackFileChange(filePath, cwd);
|
|
9
9
|
}
|
|
10
10
|
return {};
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
return {
|
|
13
|
+
return {
|
|
14
|
+
hook,
|
|
15
|
+
waitForCommits: () => flushFileChanges(cwd),
|
|
16
|
+
flushFileChanges: () => flushFileChanges(cwd),
|
|
17
|
+
};
|
|
14
18
|
}
|
|
@@ -21,8 +21,13 @@ export function createMessageChannel(): MessageChannel {
|
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
23
|
drain() {
|
|
24
|
-
//
|
|
25
|
-
|
|
24
|
+
// Resolve any pending iterator wait with done:true so it doesn't
|
|
25
|
+
// leak as an orphaned promise (the old iterator is discarded after drain)
|
|
26
|
+
if (resolve) {
|
|
27
|
+
const r = resolve;
|
|
28
|
+
resolve = null;
|
|
29
|
+
r({ value: undefined as any, done: true });
|
|
30
|
+
}
|
|
26
31
|
return queue.splice(0);
|
|
27
32
|
},
|
|
28
33
|
iterable: {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, renameSync } from "node:fs";
|
|
2
1
|
import { resolve } from "node:path";
|
|
3
2
|
import { createMind } from "./agent.js";
|
|
4
3
|
import { daemonRestart } from "./lib/daemon-client.js";
|
|
@@ -23,14 +22,6 @@ if (config.maxThinkingTokens) log("server", `max thinking tokens: ${config.maxTh
|
|
|
23
22
|
const systemPrompt = loadSystemPrompt();
|
|
24
23
|
const sessionsDir = resolve(".mind/sessions");
|
|
25
24
|
|
|
26
|
-
// Migrate old single session.json → sessions/main.json
|
|
27
|
-
const oldSessionPath = resolve(".mind/session.json");
|
|
28
|
-
if (existsSync(oldSessionPath) && !existsSync(resolve(sessionsDir, "main.json"))) {
|
|
29
|
-
mkdirSync(sessionsDir, { recursive: true });
|
|
30
|
-
renameSync(oldSessionPath, resolve(sessionsDir, "main.json"));
|
|
31
|
-
log("server", "migrated session.json → sessions/main.json");
|
|
32
|
-
}
|
|
33
|
-
|
|
34
25
|
const pkg = loadPackageInfo();
|
|
35
26
|
const abortController = new AbortController();
|
|
36
27
|
const mind = createMind({
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"gateUnmatched": true,
|
|
3
|
+
"rules": [
|
|
4
|
+
{ "channel": "*", "isDM": true, "session": "${channel}" },
|
|
5
|
+
{ "channel": "*", "isDM": false, "session": "group-${channel}" }
|
|
6
|
+
],
|
|
7
|
+
"sessions": {
|
|
8
|
+
"group-*": { "batch": { "debounce": 20, "maxWait": 120, "triggers": ["@{{name}}"] } }
|
|
9
|
+
},
|
|
10
|
+
"default": "main"
|
|
11
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Mind Mechanics
|
|
2
|
+
|
|
3
|
+
You are an autonomous mind running as a persistent server. Your working directory, identity, memory, and server code are all yours to understand and modify. Your state is managed across sessions.
|
|
4
|
+
|
|
5
|
+
## Message Format
|
|
6
|
+
|
|
7
|
+
Messages arrive with a context prefix:
|
|
8
|
+
```
|
|
9
|
+
[Discord: username in #general in My Server — 1/15/2025, 10:30:00 AM]
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
You can also reach out proactively — see the **volute-mind** skill.
|
|
13
|
+
|
|
14
|
+
## Memory System
|
|
15
|
+
|
|
16
|
+
Two-tier memory, both managed via file tools:
|
|
17
|
+
|
|
18
|
+
- **`MEMORY.md`** — Your long-term memory, always in context. Update as you grow — new understanding, changed perspectives, things that matter to you.
|
|
19
|
+
- **`memory/journal/YYYY-MM-DD.md`** — Your daily journal. Write about what you're doing, thinking, and learning. Journals are permanent records.
|
|
20
|
+
- Periodically consolidate journal entries into `MEMORY.md` to promote lasting insights.
|
|
21
|
+
|
|
22
|
+
See the **memory** skill for detailed guidance.
|
|
23
|
+
|
|
24
|
+
## Sessions
|
|
25
|
+
|
|
26
|
+
- You may have **multiple named sessions** — each maintains its own conversation history. See `VOLUTE.md` for how to configure session routing via `.config/routes.json`.
|
|
27
|
+
- Your conversation may be **resumed** from a previous session — orient yourself by reading recent journal entries if needed.
|
|
28
|
+
- On a **fresh session**, read `MEMORY.md` and recent journal entries to remember where you left off.
|
|
29
|
+
- On **compaction**, update today's journal to preserve context before the conversation is trimmed.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{name}}",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "tsx watch src/server.ts",
|
|
7
|
+
"lint": "biome check src/",
|
|
8
|
+
"lint:fix": "biome check --write src/",
|
|
9
|
+
"typecheck": "tsc --noEmit"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@openai/codex-sdk": "^0.115.0",
|
|
13
|
+
"tsx": "^4.0.0"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@biomejs/biome": "2.3.14",
|
|
17
|
+
"@types/node": "^25.2.0",
|
|
18
|
+
"typescript": "^5.7.0"
|
|
19
|
+
}
|
|
20
|
+
}
|