volute 0.36.0 → 0.37.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{accept-ZBDVVCEU.js → accept-AHAOUFBK.js} +4 -4
- package/dist/{activity-events-PWOGSMRL.js → activity-events-N6HCHU4P.js} +4 -4
- package/dist/{ai-service-GSZWIETO.js → ai-service-C2YNARGH.js} +5 -5
- package/dist/{api-client-3A77HMH7.js → api-client-LC5YRA32.js} +1 -1
- package/dist/{archive-Y2YEOCGB.js → archive-AWIJTVQV.js} +4 -4
- package/dist/{auth-YTQME4EV.js → auth-2QOOPMBX.js} +5 -5
- package/dist/{bridge-PXIO6PS2.js → bridge-F3ZJEKDN.js} +4 -4
- package/dist/{chat-ED7YOGKO.js → chat-5Y4FD77E.js} +9 -9
- package/dist/{chunk-75AJ54GM.js → chunk-2NHRJ3YO.js} +1 -1
- package/dist/{chunk-PJ4IPTIN.js → chunk-3F7XK5Q7.js} +1 -1
- package/dist/{chunk-6F3YNULE.js → chunk-4L2Q7IP5.js} +16 -16
- package/dist/{chunk-IIWF2IPD.js → chunk-5DPRTREW.js} +3 -3
- package/dist/{chunk-X2J7QUFH.js → chunk-7AZQFSOV.js} +1 -1
- package/dist/{chunk-NUX47Y2V.js → chunk-A6FLW5XD.js} +1 -1
- package/dist/{chunk-SWW6AUVW.js → chunk-BIEWHAAM.js} +1 -1
- package/dist/{chunk-TWAN7ZNO.js → chunk-CF4SO5L3.js} +3 -3
- package/dist/{chunk-7PTQGPJY.js → chunk-CJ26DXZL.js} +1 -1
- package/dist/{chunk-PY557GDR.js → chunk-GVVVMZ4J.js} +1 -1
- package/dist/chunk-K3NQKI34.js +10 -0
- package/dist/{chunk-BOLJUV77.js → chunk-KXXJYY62.js} +4 -4
- package/dist/chunk-LIIX2MOM.js +853 -0
- package/dist/chunk-LQ6Z4FXN.js +87 -0
- package/dist/{chunk-N2AUHW4C.js → chunk-MQRS4J24.js} +2 -2
- package/dist/{chunk-B35VNNSS.js → chunk-N42QMDID.js} +2 -2
- package/dist/{chunk-M5RYAA5I.js → chunk-ORNY3MZR.js} +4 -4
- package/dist/{chunk-YDBAY3NA.js → chunk-PMMHVSCR.js} +1 -1
- package/dist/{chunk-GBDVNPN2.js → chunk-QJGLTPAP.js} +8 -8
- package/dist/{chunk-DQ7VBXAP.js → chunk-RUIVWCYY.js} +122 -81
- package/dist/{chunk-L72WYMF7.js → chunk-SNW2NPP4.js} +1 -1
- package/dist/chunk-SZJWC2GA.js +125 -0
- package/dist/{chunk-DJT5Y4UF.js → chunk-TNZ5XQA4.js} +2 -2
- package/dist/{chunk-DMV5P2LU.js → chunk-UIM5NHPP.js} +3 -3
- package/dist/{chunk-ZTVKQOU7.js → chunk-WC635OPK.js} +1 -1
- package/dist/{chunk-YTWZORJN.js → chunk-XLBQYIHH.js} +1 -1
- package/dist/cli.js +24 -24
- package/dist/{clock-HSEKS5AR.js → clock-BMLJ2TR6.js} +8 -8
- package/dist/{cloud-sync-BOCZSDIA.js → cloud-sync-EZKCEIBX.js} +18 -18
- package/dist/{config-UTS7QULS.js → config-QB7W3Z7P.js} +4 -4
- 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-HH3CJD4E.js → conversations-G6YRSABR.js} +5 -5
- package/dist/{create-5BPOOJAN.js → create-C3BBFYV7.js} +4 -4
- package/dist/{create-QBEPSD2Z.js → create-PN73742N.js} +4 -4
- package/dist/{daemon-client-RVIKXGFQ.js → daemon-client-2MIPKY3E.js} +1 -1
- package/dist/{daemon-restart-SIR3UR4B.js → daemon-restart-S6SOD3C5.js} +11 -11
- package/dist/daemon.js +392 -1101
- package/dist/db-CBOCDYVA.js +9 -0
- package/dist/{db-BDMH4SZ2.js → db-IJL6B26S.js} +1 -1
- package/dist/{delete-L5PAVDGQ.js → delete-NLXES2C7.js} +3 -3
- package/dist/delivery-manager-3I7CA734.js +30 -0
- package/dist/{delivery-router-VSULHXNH.js → delivery-router-QTFEZ26O.js} +4 -4
- package/dist/down-25L2RKCQ.js +17 -0
- package/dist/echo-text-IWAQKNTC.js +31 -0
- package/dist/{env-E4XHO2BI.js → env-IQ6Q2333.js} +6 -6
- package/dist/exec-ONYZEA5B.js +17 -0
- package/dist/{export-HTFOHOKL.js → export-JPDBQESV.js} +6 -6
- package/dist/{extension-AKZ46YSL.js → extension-LZYHBNLV.js} +4 -4
- package/dist/{extensions-OOSFVH7U.js → extensions-PCOXTHNM.js} +17 -17
- package/dist/{files-H2YLRD37.js → files-LAQ3NXQK.js} +7 -7
- package/dist/{import-OL5BZX7S.js → import-EROF27RH.js} +11 -10
- package/dist/{isolation-N74RWOUX.js → isolation-G5J3MTKU.js} +4 -4
- package/dist/{join-DF5XSJAC.js → join-6SZCA5FX.js} +3 -3
- package/dist/{list-GJ4RUQQT.js → list-KHJZJPEJ.js} +4 -4
- package/dist/{login-JXRVMBRB.js → login-F6YMAVLE.js} +6 -6
- package/dist/{login-GOTAYLXP.js → login-GYTH67ES.js} +4 -4
- package/dist/{logout-FW243JBU.js → logout-HHPH52KZ.js} +6 -6
- package/dist/{logout-6KIA74EV.js → logout-YHQLOFLR.js} +4 -4
- package/dist/message-delivery-NWL7XEIX.js +40 -0
- package/dist/{mind-6VJJHF65.js → mind-MM2IYMJ3.js} +19 -19
- package/dist/{mind-activity-tracker-66UVYIFW.js → mind-activity-tracker-42ENM32S.js} +5 -5
- package/dist/{mind-history-MII2SK7F.js → mind-history-WHCNZ6I5.js} +5 -5
- package/dist/{mind-list-GEWHWAL4.js → mind-list-H3HC2ZRG.js} +4 -4
- package/dist/mind-manager-VOEQ2IZL.js +30 -0
- package/dist/{mind-profile-DCBDVF5B.js → mind-profile-7VYRJGFZ.js} +2 -2
- package/dist/mind-service-WRTOQSAL.js +36 -0
- package/dist/{mind-sleep-ITCF6OQA.js → mind-sleep-ZL5ZXFTM.js} +4 -4
- package/dist/{mind-status-X4SX3YUG.js → mind-status-ZWULKOUO.js} +4 -4
- package/dist/{mind-wake-KXMKMGWX.js → mind-wake-HK5ORGUK.js} +4 -4
- package/dist/{package-3W2MEXHB.js → package-TA6IHIED.js} +2 -2
- package/dist/{read-ZUDG4JWU.js → read-CP7MYMJQ.js} +4 -4
- package/dist/{read-stdin-3X5VYKNS.js → read-stdin-4B5UYPPM.js} +1 -1
- package/dist/{register-SB7NXCOE.js → register-XOBFEMI4.js} +4 -4
- package/dist/{registry-YPHK534W.js → registry-KMELPC3X.js} +3 -3
- package/dist/{reject-MUR2KWJ4.js → reject-43AGXB6B.js} +4 -4
- package/dist/{restart-5EGG4JXU.js → restart-O5QIYQJT.js} +5 -5
- package/dist/{sandbox-LP6YRAXS.js → sandbox-PQYEICEF.js} +5 -5
- package/dist/scheduler-355E746X.js +30 -0
- package/dist/{schema-MISD3JFG.js → schema-K575EBPE.js} +2 -2
- package/dist/{seed-CEC4RC23.js → seed-6S4Z6TAM.js} +2 -2
- package/dist/{seed-check-KJNTL72M.js → seed-check-HZPVFJKZ.js} +2 -2
- package/dist/{seed-cmd-WTTG7SRQ.js → seed-cmd-CBWLJWYD.js} +4 -4
- package/dist/{seed-create-M6RCC6RP.js → seed-create-NT6DG4SE.js} +6 -6
- package/dist/{seed-sprout-ZKCHFJKH.js → seed-sprout-GQLSK4EF.js} +14 -14
- package/dist/{send-LXUT2GGR.js → send-7CIP5GLS.js} +8 -8
- package/dist/{service-M6N3RUYU.js → service-YMHWPDXW.js} +6 -6
- package/dist/{setup-PJOF5UV5.js → setup-APNN7KJB.js} +32 -37
- package/dist/{setup-PMJHCZQX.js → setup-PF7JSFMO.js} +4 -4
- package/dist/{skill-TAAKEYBV.js → skill-ICN6Y2ZF.js} +6 -6
- package/dist/{skills-2PTRTBQP.js → skills-ZFVNN4TU.js} +7 -7
- package/dist/sleep-manager-PBOIEBJZ.js +34 -0
- package/dist/{spirit-6KVDIROQ.js → spirit-4QOYM33G.js} +9 -9
- package/dist/{split-AWVOYOPZ.js → split-5YBEQTBF.js} +3 -3
- package/dist/{sprout-WX2FFYLP.js → sprout-UDLZPMEO.js} +2 -2
- package/dist/{src-QEOLMAYC.js → src-LT6ZBYYX.js} +2 -2
- package/dist/{src-GW6FP6VL.js → src-O4PRLMKM.js} +1 -1
- package/dist/{src-FQE4BHRG.js → src-OYWRPLC6.js} +1 -1
- package/dist/{start-3UXOPXQG.js → start-LMXXRR3X.js} +5 -5
- package/dist/{status-3IVSLJDN.js → status-MC2P7DBG.js} +7 -7
- package/dist/{stop-3XYIBGFM.js → stop-TWDKVEUX.js} +5 -5
- package/dist/system-chat-7AIN3U5M.js +34 -0
- package/dist/{systems-O43WGQY6.js → systems-Y2WZV2K4.js} +7 -7
- package/dist/{tailscale-DZU4WM3E.js → tailscale-LTYNKIPZ.js} +3 -3
- package/dist/{template-hash-6ITI3WC4.js → template-hash-SSIBEEYK.js} +1 -1
- package/dist/up-4T32B7OB.js +19 -0
- package/dist/{update-RIQYUPVN.js → update-UOP2INF2.js} +7 -7
- package/dist/{update-check-4TIJKVGD.js → update-check-IKS7SGK5.js} +4 -4
- package/dist/{upgrade-ZMDGC7M2.js → upgrade-RXFZR5FI.js} +3 -3
- package/dist/{variant-QWL2WSRI.js → variant-HHDTW74J.js} +1 -1
- package/dist/{version-notify-UXSHBZ35.js → version-notify-NCRIN5QK.js} +18 -18
- package/dist/{volute-config-V7UFFBG3.js → volute-config-TS62GS6A.js} +1 -1
- package/dist/web-assets/assets/{index-C-eYso8Y.js → index-B3xLeex8.js} +16 -16
- package/dist/web-assets/assets/{index-CCv_fSte.css → index-Dr4A90Lo.css} +1 -1
- package/dist/web-assets/index.html +2 -2
- package/package.json +1 -1
- package/templates/_base/src/lib/context-breakdown.ts +22 -16
- package/dist/chunk-7KJOFUNN.js +0 -22
- package/dist/chunk-PZYJBOQP.js +0 -207
- package/dist/db-URORGSXQ.js +0 -9
- package/dist/delivery-manager-WTGIPBGY.js +0 -30
- package/dist/down-DGGLZ5TA.js +0 -17
- package/dist/exec-X3C6ZZTQ.js +0 -17
- package/dist/lib-DYEZMGW7.js +0 -6588
- package/dist/message-delivery-YORUXKDQ.js +0 -40
- package/dist/mind-manager-TJ2SUPRX.js +0 -30
- package/dist/mind-service-E7FM2WZF.js +0 -36
- package/dist/scheduler-FRJ5DK24.js +0 -30
- package/dist/sleep-manager-WAZWMFJT.js +0 -34
- package/dist/system-chat-2IFS5HCX.js +0 -34
- package/dist/up-4SCIUIMG.js +0 -19
package/dist/daemon.js
CHANGED
|
@@ -1,20 +1,44 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
acceptPending,
|
|
4
|
+
formatFileSize,
|
|
5
|
+
listPending,
|
|
6
|
+
rejectPending,
|
|
7
|
+
stageFile,
|
|
8
|
+
validateFilePath
|
|
9
|
+
} from "./chunk-XLBQYIHH.js";
|
|
10
|
+
import {
|
|
11
|
+
findOpenClawSession,
|
|
12
|
+
importOpenClawConnectors,
|
|
13
|
+
importPiSession,
|
|
14
|
+
parseNameFromIdentity
|
|
15
|
+
} from "./chunk-SZJWC2GA.js";
|
|
2
16
|
import {
|
|
3
17
|
checkForUpdate,
|
|
4
18
|
checkForUpdateCached,
|
|
5
19
|
getCurrentVersion
|
|
6
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-WC635OPK.js";
|
|
21
|
+
import {
|
|
22
|
+
isHomeOnlyArchive
|
|
23
|
+
} from "./chunk-BIEWHAAM.js";
|
|
7
24
|
import {
|
|
8
25
|
computeTemplateHash
|
|
9
26
|
} from "./chunk-KAB6UGOL.js";
|
|
10
27
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
28
|
+
PLATFORMS,
|
|
29
|
+
echoTextToChannel,
|
|
30
|
+
getPlatformDriver,
|
|
31
|
+
routeOutboundBridge
|
|
32
|
+
} from "./chunk-LIIX2MOM.js";
|
|
33
|
+
import {
|
|
34
|
+
getBridgeConfig,
|
|
35
|
+
readBridgesConfig,
|
|
36
|
+
removeBridgeConfig,
|
|
37
|
+
removeChannelMapping,
|
|
38
|
+
resolveChannelMapping,
|
|
39
|
+
setBridgeConfig,
|
|
40
|
+
setChannelMapping
|
|
41
|
+
} from "./chunk-LQ6Z4FXN.js";
|
|
18
42
|
import {
|
|
19
43
|
PROMPT_DEFAULTS,
|
|
20
44
|
PROMPT_KEYS,
|
|
@@ -77,8 +101,15 @@ import {
|
|
|
77
101
|
trackToolUse,
|
|
78
102
|
uninstallNpmExtension,
|
|
79
103
|
writeSystemsConfig
|
|
80
|
-
} from "./chunk-
|
|
81
|
-
import
|
|
104
|
+
} from "./chunk-RUIVWCYY.js";
|
|
105
|
+
import {
|
|
106
|
+
loadMergedEnv,
|
|
107
|
+
mindEnvPath,
|
|
108
|
+
readEnv,
|
|
109
|
+
sharedEnvPath,
|
|
110
|
+
writeEnv
|
|
111
|
+
} from "./chunk-PMMHVSCR.js";
|
|
112
|
+
import "./chunk-4L2Q7IP5.js";
|
|
82
113
|
import {
|
|
83
114
|
applyInitFiles,
|
|
84
115
|
composeTemplate,
|
|
@@ -105,12 +136,33 @@ import {
|
|
|
105
136
|
syncBuiltinSkills,
|
|
106
137
|
uninstallSkill,
|
|
107
138
|
updateSkill
|
|
108
|
-
} from "./chunk-
|
|
139
|
+
} from "./chunk-QJGLTPAP.js";
|
|
140
|
+
import {
|
|
141
|
+
readVoluteConfig,
|
|
142
|
+
writeVoluteConfig
|
|
143
|
+
} from "./chunk-CU6OFXMM.js";
|
|
144
|
+
import "./chunk-KXXJYY62.js";
|
|
145
|
+
import {
|
|
146
|
+
extractTextContent
|
|
147
|
+
} from "./chunk-7AZQFSOV.js";
|
|
109
148
|
import {
|
|
110
149
|
getActiveMinds,
|
|
111
150
|
onMindEvent,
|
|
112
151
|
stopAll
|
|
113
|
-
} from "./chunk-
|
|
152
|
+
} from "./chunk-GVVVMZ4J.js";
|
|
153
|
+
import {
|
|
154
|
+
exec,
|
|
155
|
+
gitExec,
|
|
156
|
+
resolveVoluteBin
|
|
157
|
+
} from "./chunk-3F7XK5Q7.js";
|
|
158
|
+
import {
|
|
159
|
+
chownMindDir,
|
|
160
|
+
createMindUser,
|
|
161
|
+
deleteMindUser,
|
|
162
|
+
ensureVoluteGroup,
|
|
163
|
+
isIsolationEnabled,
|
|
164
|
+
wrapForIsolation
|
|
165
|
+
} from "./chunk-SNW2NPP4.js";
|
|
114
166
|
import {
|
|
115
167
|
approveUser,
|
|
116
168
|
changePassword,
|
|
@@ -129,7 +181,28 @@ import {
|
|
|
129
181
|
syncMindProfile,
|
|
130
182
|
updateUserProfile,
|
|
131
183
|
verifyUser
|
|
132
|
-
} from "./chunk-
|
|
184
|
+
} from "./chunk-UIM5NHPP.js";
|
|
185
|
+
import {
|
|
186
|
+
getAiConfig,
|
|
187
|
+
getAvailableModels,
|
|
188
|
+
getConfiguredProviders,
|
|
189
|
+
getEnabledModels,
|
|
190
|
+
getUtilityModel,
|
|
191
|
+
qualifyModelId,
|
|
192
|
+
removeAiConfig,
|
|
193
|
+
removeProviderConfig,
|
|
194
|
+
resolveApiKey,
|
|
195
|
+
resolveTemplate,
|
|
196
|
+
saveProviderConfig,
|
|
197
|
+
setEnabledModels,
|
|
198
|
+
setUtilityModel,
|
|
199
|
+
unqualifyModelId
|
|
200
|
+
} from "./chunk-ORNY3MZR.js";
|
|
201
|
+
import {
|
|
202
|
+
isSetupComplete,
|
|
203
|
+
readGlobalConfig,
|
|
204
|
+
writeGlobalConfig
|
|
205
|
+
} from "./chunk-A6FLW5XD.js";
|
|
133
206
|
import {
|
|
134
207
|
addMessage,
|
|
135
208
|
createChannel,
|
|
@@ -161,81 +234,15 @@ import {
|
|
|
161
234
|
setConversationPrivate,
|
|
162
235
|
subscribe as subscribe2,
|
|
163
236
|
updateChannelSettings
|
|
164
|
-
} from "./chunk-
|
|
237
|
+
} from "./chunk-5DPRTREW.js";
|
|
165
238
|
import {
|
|
166
239
|
broadcast,
|
|
167
240
|
subscribe
|
|
168
|
-
} from "./chunk-
|
|
169
|
-
import {
|
|
170
|
-
readVoluteConfig,
|
|
171
|
-
writeVoluteConfig
|
|
172
|
-
} from "./chunk-CU6OFXMM.js";
|
|
173
|
-
import "./chunk-BOLJUV77.js";
|
|
174
|
-
import {
|
|
175
|
-
extractTextContent
|
|
176
|
-
} from "./chunk-X2J7QUFH.js";
|
|
177
|
-
import {
|
|
178
|
-
findBridgeForChannel,
|
|
179
|
-
findOpenClawSession,
|
|
180
|
-
getBridgeConfig,
|
|
181
|
-
importOpenClawConnectors,
|
|
182
|
-
importPiSession,
|
|
183
|
-
parseNameFromIdentity,
|
|
184
|
-
readBridgesConfig,
|
|
185
|
-
removeBridgeConfig,
|
|
186
|
-
removeChannelMapping,
|
|
187
|
-
resolveChannelMapping,
|
|
188
|
-
setBridgeConfig,
|
|
189
|
-
setChannelMapping
|
|
190
|
-
} from "./chunk-PZYJBOQP.js";
|
|
191
|
-
import {
|
|
192
|
-
loadMergedEnv,
|
|
193
|
-
mindEnvPath,
|
|
194
|
-
readEnv,
|
|
195
|
-
sharedEnvPath,
|
|
196
|
-
writeEnv
|
|
197
|
-
} from "./chunk-YDBAY3NA.js";
|
|
198
|
-
import {
|
|
199
|
-
isHomeOnlyArchive
|
|
200
|
-
} from "./chunk-SWW6AUVW.js";
|
|
201
|
-
import {
|
|
202
|
-
getAiConfig,
|
|
203
|
-
getAvailableModels,
|
|
204
|
-
getConfiguredProviders,
|
|
205
|
-
getEnabledModels,
|
|
206
|
-
getUtilityModel,
|
|
207
|
-
qualifyModelId,
|
|
208
|
-
removeAiConfig,
|
|
209
|
-
removeProviderConfig,
|
|
210
|
-
resolveApiKey,
|
|
211
|
-
resolveTemplate,
|
|
212
|
-
saveProviderConfig,
|
|
213
|
-
setEnabledModels,
|
|
214
|
-
setUtilityModel,
|
|
215
|
-
unqualifyModelId
|
|
216
|
-
} from "./chunk-M5RYAA5I.js";
|
|
241
|
+
} from "./chunk-N42QMDID.js";
|
|
217
242
|
import {
|
|
218
243
|
logBuffer,
|
|
219
244
|
logger_default
|
|
220
245
|
} from "./chunk-T2TP6ZC6.js";
|
|
221
|
-
import {
|
|
222
|
-
exec,
|
|
223
|
-
gitExec,
|
|
224
|
-
resolveVoluteBin
|
|
225
|
-
} from "./chunk-PJ4IPTIN.js";
|
|
226
|
-
import {
|
|
227
|
-
chownMindDir,
|
|
228
|
-
createMindUser,
|
|
229
|
-
deleteMindUser,
|
|
230
|
-
ensureVoluteGroup,
|
|
231
|
-
isIsolationEnabled,
|
|
232
|
-
wrapForIsolation
|
|
233
|
-
} from "./chunk-L72WYMF7.js";
|
|
234
|
-
import {
|
|
235
|
-
isSetupComplete,
|
|
236
|
-
readGlobalConfig,
|
|
237
|
-
writeGlobalConfig
|
|
238
|
-
} from "./chunk-NUX47Y2V.js";
|
|
239
246
|
import {
|
|
240
247
|
buildVoluteSlug
|
|
241
248
|
} from "./chunk-LGNUFVMR.js";
|
|
@@ -261,7 +268,7 @@ import {
|
|
|
261
268
|
validateMindName,
|
|
262
269
|
voluteHome,
|
|
263
270
|
voluteSystemDir
|
|
264
|
-
} from "./chunk-
|
|
271
|
+
} from "./chunk-2NHRJ3YO.js";
|
|
265
272
|
import {
|
|
266
273
|
activity,
|
|
267
274
|
channels,
|
|
@@ -273,16 +280,14 @@ import {
|
|
|
273
280
|
systemPrompts,
|
|
274
281
|
turns,
|
|
275
282
|
users
|
|
276
|
-
} from "./chunk-
|
|
277
|
-
import
|
|
278
|
-
__export
|
|
279
|
-
} from "./chunk-7KJOFUNN.js";
|
|
283
|
+
} from "./chunk-CJ26DXZL.js";
|
|
284
|
+
import "./chunk-K3NQKI34.js";
|
|
280
285
|
|
|
281
286
|
// packages/daemon/src/daemon.ts
|
|
282
287
|
import { randomBytes } from "crypto";
|
|
283
|
-
import { mkdirSync as mkdirSync10, readFileSync as
|
|
288
|
+
import { mkdirSync as mkdirSync10, readFileSync as readFileSync10, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "fs";
|
|
284
289
|
import { homedir as homedir3 } from "os";
|
|
285
|
-
import { resolve as
|
|
290
|
+
import { resolve as resolve16 } from "path";
|
|
286
291
|
import { format } from "util";
|
|
287
292
|
|
|
288
293
|
// packages/daemon/src/lib/daemon/bridge-manager.ts
|
|
@@ -492,8 +497,8 @@ var BridgeManager = class {
|
|
|
492
497
|
if (!tracked) return;
|
|
493
498
|
this.stopping.add(platform);
|
|
494
499
|
this.bridges.delete(platform);
|
|
495
|
-
await new Promise((
|
|
496
|
-
tracked.child.on("exit", () =>
|
|
500
|
+
await new Promise((resolve17) => {
|
|
501
|
+
tracked.child.on("exit", () => resolve17());
|
|
497
502
|
try {
|
|
498
503
|
if (tracked.child.pid) {
|
|
499
504
|
process.kill(-tracked.child.pid, "SIGTERM");
|
|
@@ -504,7 +509,7 @@ var BridgeManager = class {
|
|
|
504
509
|
if (err instanceof Error && err.code !== "ESRCH") {
|
|
505
510
|
blog.warn(`failed to stop bridge ${platform}`, logger_default.errorData(err));
|
|
506
511
|
}
|
|
507
|
-
|
|
512
|
+
resolve17();
|
|
508
513
|
}
|
|
509
514
|
setTimeout(() => {
|
|
510
515
|
try {
|
|
@@ -515,7 +520,7 @@ var BridgeManager = class {
|
|
|
515
520
|
}
|
|
516
521
|
} catch {
|
|
517
522
|
}
|
|
518
|
-
|
|
523
|
+
resolve17();
|
|
519
524
|
}, 5e3);
|
|
520
525
|
});
|
|
521
526
|
this.stopping.delete(platform);
|
|
@@ -979,10 +984,10 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
979
984
|
stream.writeSSE({ data: JSON.stringify(entry) }).catch(() => {
|
|
980
985
|
});
|
|
981
986
|
});
|
|
982
|
-
await new Promise((
|
|
987
|
+
await new Promise((resolve17) => {
|
|
983
988
|
stream.onAbort(() => {
|
|
984
989
|
unsubscribe();
|
|
985
|
-
|
|
990
|
+
resolve17();
|
|
986
991
|
});
|
|
987
992
|
});
|
|
988
993
|
});
|
|
@@ -1287,14 +1292,16 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
1287
1292
|
cleanupOAuthFlows();
|
|
1288
1293
|
const flowId = crypto.randomUUID();
|
|
1289
1294
|
const needsManualCode = !!oauthProvider.usesCallbackServer;
|
|
1295
|
+
const abortController = new AbortController();
|
|
1290
1296
|
const flow = {
|
|
1291
1297
|
status: "pending",
|
|
1292
1298
|
needsManualCode,
|
|
1299
|
+
abortController,
|
|
1293
1300
|
createdAt: Date.now()
|
|
1294
1301
|
};
|
|
1295
1302
|
oauthFlows.set(flowId, flow);
|
|
1296
|
-
const promptPromise = needsManualCode ? new Promise((
|
|
1297
|
-
flow.resolveCode =
|
|
1303
|
+
const promptPromise = needsManualCode ? new Promise((resolve17) => {
|
|
1304
|
+
flow.resolveCode = resolve17;
|
|
1298
1305
|
}) : void 0;
|
|
1299
1306
|
oauthProvider.login({
|
|
1300
1307
|
onAuth: (info) => {
|
|
@@ -1310,7 +1317,8 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
1310
1317
|
}
|
|
1311
1318
|
return "";
|
|
1312
1319
|
},
|
|
1313
|
-
onManualCodeInput: needsManualCode ? () => promptPromise : void 0
|
|
1320
|
+
onManualCodeInput: needsManualCode ? () => promptPromise : void 0,
|
|
1321
|
+
signal: abortController.signal
|
|
1314
1322
|
}).then(async (credentials) => {
|
|
1315
1323
|
saveProviderConfig(provider, { oauth: credentials });
|
|
1316
1324
|
const existing = oauthFlows.get(flowId);
|
|
@@ -1323,7 +1331,7 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
1323
1331
|
existing.error = err instanceof Error ? err.message : String(err);
|
|
1324
1332
|
}
|
|
1325
1333
|
});
|
|
1326
|
-
await new Promise((
|
|
1334
|
+
await new Promise((resolve17) => setTimeout(resolve17, 2e3));
|
|
1327
1335
|
const state = oauthFlows.get(flowId);
|
|
1328
1336
|
return c.json({
|
|
1329
1337
|
flowId,
|
|
@@ -1364,6 +1372,8 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
1364
1372
|
status: flow.status,
|
|
1365
1373
|
waitingForCode: flow.waitingForCode
|
|
1366
1374
|
};
|
|
1375
|
+
if (flow.url) result.url = flow.url;
|
|
1376
|
+
if (flow.instructions) result.instructions = flow.instructions;
|
|
1367
1377
|
if (flow.error) result.error = flow.error;
|
|
1368
1378
|
if (flow.status !== "pending") {
|
|
1369
1379
|
setTimeout(() => oauthFlows.delete(flowId), 3e4);
|
|
@@ -1418,13 +1428,12 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
|
|
|
1418
1428
|
}
|
|
1419
1429
|
);
|
|
1420
1430
|
var oauthFlows = /* @__PURE__ */ new Map();
|
|
1421
|
-
var OAUTH_FLOW_TTL_MS = 10 * 60 * 1e3;
|
|
1422
1431
|
function cleanupOAuthFlows() {
|
|
1423
|
-
const now = Date.now();
|
|
1424
1432
|
for (const [id, flow] of oauthFlows) {
|
|
1425
|
-
if (
|
|
1426
|
-
|
|
1433
|
+
if (flow.status === "pending") {
|
|
1434
|
+
flow.abortController?.abort();
|
|
1427
1435
|
}
|
|
1436
|
+
oauthFlows.delete(id);
|
|
1428
1437
|
}
|
|
1429
1438
|
}
|
|
1430
1439
|
var PROVIDER_TEMPLATES = {
|
|
@@ -1579,8 +1588,8 @@ var app2 = new Hono2().get("/events", async (c) => {
|
|
|
1579
1588
|
});
|
|
1580
1589
|
}, 15e3);
|
|
1581
1590
|
cleanups.push(() => clearInterval(keepAlive));
|
|
1582
|
-
await new Promise((
|
|
1583
|
-
stream.onAbort(() =>
|
|
1591
|
+
await new Promise((resolve17) => {
|
|
1592
|
+
stream.onAbort(() => resolve17());
|
|
1584
1593
|
});
|
|
1585
1594
|
} finally {
|
|
1586
1595
|
for (const cleanup of cleanups) {
|
|
@@ -1983,7 +1992,7 @@ var app4 = new Hono4().post("/:platform/inbound", zValidator3("json", inboundSch
|
|
|
1983
1992
|
}
|
|
1984
1993
|
const participants = await getParticipants(channel.id);
|
|
1985
1994
|
if (!participants.some((p) => p.userId === puppet.id)) {
|
|
1986
|
-
const { addParticipant } = await import("./conversations-
|
|
1995
|
+
const { addParticipant } = await import("./conversations-G6YRSABR.js");
|
|
1987
1996
|
await addParticipant(channel.id, puppet.id);
|
|
1988
1997
|
}
|
|
1989
1998
|
const contentBlocks = body.content;
|
|
@@ -2076,8 +2085,8 @@ async function fanOutToBridgedMinds(opts) {
|
|
|
2076
2085
|
const participants = await getParticipants(opts.conversationId);
|
|
2077
2086
|
const mindParticipants = participants.filter((p) => p.userType === "mind");
|
|
2078
2087
|
const participantNames = participants.map((p) => p.username);
|
|
2079
|
-
const { getMindManager: getMindManager2 } = await import("./mind-manager-
|
|
2080
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
2088
|
+
const { getMindManager: getMindManager2 } = await import("./mind-manager-VOEQ2IZL.js");
|
|
2089
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-PBOIEBJZ.js");
|
|
2081
2090
|
const manager = getMindManager2();
|
|
2082
2091
|
const sm = getSleepManagerIfReady2();
|
|
2083
2092
|
const targetMinds = mindParticipants.filter((ap) => {
|
|
@@ -2106,656 +2115,6 @@ var bridges_default = app4;
|
|
|
2106
2115
|
|
|
2107
2116
|
// packages/daemon/src/web/api/channels.ts
|
|
2108
2117
|
import { Hono as Hono5 } from "hono";
|
|
2109
|
-
|
|
2110
|
-
// packages/platforms/src/drivers/discord.ts
|
|
2111
|
-
var discord_exports = {};
|
|
2112
|
-
__export(discord_exports, {
|
|
2113
|
-
createConversation: () => createConversation2,
|
|
2114
|
-
listConversations: () => listConversations,
|
|
2115
|
-
listUsers: () => listUsers2,
|
|
2116
|
-
read: () => read,
|
|
2117
|
-
send: () => send
|
|
2118
|
-
});
|
|
2119
|
-
|
|
2120
|
-
// packages/platforms/src/slugify.ts
|
|
2121
|
-
function slugify(text) {
|
|
2122
|
-
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
2123
|
-
}
|
|
2124
|
-
|
|
2125
|
-
// packages/platforms/src/split-message.ts
|
|
2126
|
-
function splitMessage(text, maxLength) {
|
|
2127
|
-
const chunks = [];
|
|
2128
|
-
while (text.length > maxLength) {
|
|
2129
|
-
let splitAt = text.lastIndexOf("\n", maxLength);
|
|
2130
|
-
if (splitAt < maxLength / 2) splitAt = maxLength;
|
|
2131
|
-
chunks.push(text.slice(0, splitAt));
|
|
2132
|
-
text = text.slice(splitAt).replace(/^\n/, "");
|
|
2133
|
-
}
|
|
2134
|
-
if (text) chunks.push(text);
|
|
2135
|
-
return chunks;
|
|
2136
|
-
}
|
|
2137
|
-
|
|
2138
|
-
// packages/platforms/src/drivers/discord.ts
|
|
2139
|
-
var DISCORD_MAX_LENGTH = 2e3;
|
|
2140
|
-
var API_BASE = "https://discord.com/api/v10";
|
|
2141
|
-
function requireToken(env) {
|
|
2142
|
-
const token = env.DISCORD_TOKEN;
|
|
2143
|
-
if (!token) throw new Error("DISCORD_TOKEN not set");
|
|
2144
|
-
return token;
|
|
2145
|
-
}
|
|
2146
|
-
async function discordGet(token, path) {
|
|
2147
|
-
const res = await fetch(`${API_BASE}${path}`, {
|
|
2148
|
-
headers: { Authorization: `Bot ${token}` }
|
|
2149
|
-
});
|
|
2150
|
-
if (!res.ok) {
|
|
2151
|
-
throw new Error(`Discord API error: ${res.status} ${res.statusText}`);
|
|
2152
|
-
}
|
|
2153
|
-
return res.json();
|
|
2154
|
-
}
|
|
2155
|
-
async function read(env, channelSlug, limit) {
|
|
2156
|
-
const token = requireToken(env);
|
|
2157
|
-
const channelId = resolvePlatformId(channelSlug);
|
|
2158
|
-
const res = await fetch(`${API_BASE}/channels/${channelId}/messages?limit=${limit}`, {
|
|
2159
|
-
headers: { Authorization: `Bot ${token}` }
|
|
2160
|
-
});
|
|
2161
|
-
if (!res.ok) {
|
|
2162
|
-
throw new Error(`Discord API error: ${res.status} ${res.statusText}`);
|
|
2163
|
-
}
|
|
2164
|
-
const messages = await res.json();
|
|
2165
|
-
return messages.reverse().map((m) => `${m.author.username}: ${m.content}`).join("\n");
|
|
2166
|
-
}
|
|
2167
|
-
async function send(env, channelSlug, message, images) {
|
|
2168
|
-
const token = requireToken(env);
|
|
2169
|
-
const channelId = resolvePlatformId(channelSlug);
|
|
2170
|
-
if (images?.length) {
|
|
2171
|
-
for (let i = 0; i < images.length; i++) {
|
|
2172
|
-
const img = images[i];
|
|
2173
|
-
const ext = img.media_type.split("/")[1] || "png";
|
|
2174
|
-
const form = new FormData();
|
|
2175
|
-
const content = i === 0 ? message.slice(0, DISCORD_MAX_LENGTH) : "";
|
|
2176
|
-
form.append("payload_json", JSON.stringify({ content }));
|
|
2177
|
-
form.append(
|
|
2178
|
-
"files[0]",
|
|
2179
|
-
new Blob([Buffer.from(img.data, "base64")], { type: img.media_type }),
|
|
2180
|
-
`image.${ext}`
|
|
2181
|
-
);
|
|
2182
|
-
const res = await fetch(`${API_BASE}/channels/${channelId}/messages`, {
|
|
2183
|
-
method: "POST",
|
|
2184
|
-
headers: { Authorization: `Bot ${token}` },
|
|
2185
|
-
body: form
|
|
2186
|
-
});
|
|
2187
|
-
if (!res.ok) {
|
|
2188
|
-
const body = await res.text().catch(() => "");
|
|
2189
|
-
const partial = i > 0 ? ` (${i}/${images.length} images were already sent)` : "";
|
|
2190
|
-
throw new Error(`Discord API error: ${res.status} ${body || res.statusText}${partial}`);
|
|
2191
|
-
}
|
|
2192
|
-
}
|
|
2193
|
-
return;
|
|
2194
|
-
}
|
|
2195
|
-
const chunks = splitMessage(message, DISCORD_MAX_LENGTH);
|
|
2196
|
-
for (let i = 0; i < chunks.length; i++) {
|
|
2197
|
-
const res = await fetch(`${API_BASE}/channels/${channelId}/messages`, {
|
|
2198
|
-
method: "POST",
|
|
2199
|
-
headers: {
|
|
2200
|
-
Authorization: `Bot ${token}`,
|
|
2201
|
-
"Content-Type": "application/json"
|
|
2202
|
-
},
|
|
2203
|
-
body: JSON.stringify({ content: chunks[i] })
|
|
2204
|
-
});
|
|
2205
|
-
if (!res.ok) {
|
|
2206
|
-
const partial = i > 0 ? ` (${i}/${chunks.length} chunks were already sent)` : "";
|
|
2207
|
-
throw new Error(`Discord API error: ${res.status} ${res.statusText}${partial}`);
|
|
2208
|
-
}
|
|
2209
|
-
}
|
|
2210
|
-
}
|
|
2211
|
-
async function listConversations(env) {
|
|
2212
|
-
const token = requireToken(env);
|
|
2213
|
-
const results = [];
|
|
2214
|
-
const guilds = await discordGet(token, "/users/@me/guilds");
|
|
2215
|
-
for (const guild of guilds) {
|
|
2216
|
-
const channels2 = await discordGet(token, `/guilds/${guild.id}/channels`);
|
|
2217
|
-
for (const ch of channels2) {
|
|
2218
|
-
if (ch.type !== 0) continue;
|
|
2219
|
-
results.push({
|
|
2220
|
-
id: `discord:${slugify(guild.name)}/${slugify(ch.name)}`,
|
|
2221
|
-
platformId: ch.id,
|
|
2222
|
-
name: `#${ch.name}`,
|
|
2223
|
-
type: "channel"
|
|
2224
|
-
});
|
|
2225
|
-
}
|
|
2226
|
-
}
|
|
2227
|
-
const dms = await discordGet(token, "/users/@me/channels");
|
|
2228
|
-
for (const dm of dms) {
|
|
2229
|
-
const recipients = dm.recipients?.map((r) => r.username) ?? [];
|
|
2230
|
-
const slug = recipients.length === 0 ? `discord:${dm.id}` : recipients.length === 1 ? `discord:@${slugify(recipients[0])}` : `discord:@${recipients.map(slugify).sort().join(",")}`;
|
|
2231
|
-
results.push({
|
|
2232
|
-
id: slug,
|
|
2233
|
-
platformId: dm.id,
|
|
2234
|
-
name: recipients.join(", ") || "DM",
|
|
2235
|
-
type: dm.type === 1 ? "dm" : "channel"
|
|
2236
|
-
});
|
|
2237
|
-
}
|
|
2238
|
-
return results;
|
|
2239
|
-
}
|
|
2240
|
-
async function listUsers2(env) {
|
|
2241
|
-
const token = requireToken(env);
|
|
2242
|
-
const seen = /* @__PURE__ */ new Map();
|
|
2243
|
-
const guilds = await discordGet(token, "/users/@me/guilds");
|
|
2244
|
-
for (const guild of guilds) {
|
|
2245
|
-
const members = await discordGet(token, `/guilds/${guild.id}/members?limit=1000`);
|
|
2246
|
-
for (const m of members) {
|
|
2247
|
-
if (!seen.has(m.user.id)) {
|
|
2248
|
-
seen.set(m.user.id, {
|
|
2249
|
-
id: m.user.id,
|
|
2250
|
-
username: m.user.username,
|
|
2251
|
-
type: m.user.bot ? "bot" : "human"
|
|
2252
|
-
});
|
|
2253
|
-
}
|
|
2254
|
-
}
|
|
2255
|
-
}
|
|
2256
|
-
return [...seen.values()];
|
|
2257
|
-
}
|
|
2258
|
-
async function createConversation2(env, participants, _name) {
|
|
2259
|
-
const token = requireToken(env);
|
|
2260
|
-
if (participants.length !== 1) {
|
|
2261
|
-
throw new Error(
|
|
2262
|
-
"Discord group creation not supported via bot \u2014 use threads in an existing channel"
|
|
2263
|
-
);
|
|
2264
|
-
}
|
|
2265
|
-
const allUsers = await listUsers2(env);
|
|
2266
|
-
const target = allUsers.find((u) => u.username.toLowerCase() === participants[0].toLowerCase());
|
|
2267
|
-
if (!target) {
|
|
2268
|
-
throw new Error(`User not found: ${participants[0]}`);
|
|
2269
|
-
}
|
|
2270
|
-
const res = await fetch(`${API_BASE}/users/@me/channels`, {
|
|
2271
|
-
method: "POST",
|
|
2272
|
-
headers: {
|
|
2273
|
-
Authorization: `Bot ${token}`,
|
|
2274
|
-
"Content-Type": "application/json"
|
|
2275
|
-
},
|
|
2276
|
-
body: JSON.stringify({ recipient_id: target.id })
|
|
2277
|
-
});
|
|
2278
|
-
if (!res.ok) {
|
|
2279
|
-
throw new Error(`Discord API error: ${res.status} ${res.statusText}`);
|
|
2280
|
-
}
|
|
2281
|
-
const dmChannel = await res.json();
|
|
2282
|
-
return `discord:${dmChannel.id}`;
|
|
2283
|
-
}
|
|
2284
|
-
|
|
2285
|
-
// packages/platforms/src/drivers/slack.ts
|
|
2286
|
-
var slack_exports = {};
|
|
2287
|
-
__export(slack_exports, {
|
|
2288
|
-
createConversation: () => createConversation3,
|
|
2289
|
-
listConversations: () => listConversations2,
|
|
2290
|
-
listUsers: () => listUsers3,
|
|
2291
|
-
read: () => read2,
|
|
2292
|
-
send: () => send2
|
|
2293
|
-
});
|
|
2294
|
-
var SLACK_MAX_LENGTH = 4e3;
|
|
2295
|
-
var API_BASE2 = "https://slack.com/api";
|
|
2296
|
-
function requireToken2(env) {
|
|
2297
|
-
const token = env.SLACK_BOT_TOKEN;
|
|
2298
|
-
if (!token) throw new Error("SLACK_BOT_TOKEN not set");
|
|
2299
|
-
return token;
|
|
2300
|
-
}
|
|
2301
|
-
async function slackApi(token, method, body) {
|
|
2302
|
-
const res = await fetch(`${API_BASE2}/${method}`, {
|
|
2303
|
-
method: "POST",
|
|
2304
|
-
headers: {
|
|
2305
|
-
Authorization: `Bearer ${token}`,
|
|
2306
|
-
"Content-Type": "application/json"
|
|
2307
|
-
},
|
|
2308
|
-
body: JSON.stringify(body)
|
|
2309
|
-
});
|
|
2310
|
-
if (!res.ok) {
|
|
2311
|
-
throw new Error(`Slack API HTTP error: ${res.status} ${res.statusText}`);
|
|
2312
|
-
}
|
|
2313
|
-
const data = await res.json();
|
|
2314
|
-
if (!data.ok) {
|
|
2315
|
-
throw new Error(`Slack API error: ${data.error}`);
|
|
2316
|
-
}
|
|
2317
|
-
return data;
|
|
2318
|
-
}
|
|
2319
|
-
async function read2(env, channelSlug, limit) {
|
|
2320
|
-
const token = requireToken2(env);
|
|
2321
|
-
const channelId = resolvePlatformId(channelSlug);
|
|
2322
|
-
const data = await slackApi(token, "conversations.history", {
|
|
2323
|
-
channel: channelId,
|
|
2324
|
-
limit
|
|
2325
|
-
});
|
|
2326
|
-
return data.messages.reverse().map((m) => `${m.user ?? m.bot_id ?? "unknown"}: ${m.text}`).join("\n");
|
|
2327
|
-
}
|
|
2328
|
-
async function send2(env, channelSlug, message, images) {
|
|
2329
|
-
const token = requireToken2(env);
|
|
2330
|
-
const channelId = resolvePlatformId(channelSlug);
|
|
2331
|
-
if (images?.length) {
|
|
2332
|
-
for (const img of images) {
|
|
2333
|
-
const ext = img.media_type.split("/")[1] || "png";
|
|
2334
|
-
const filename = `image.${ext}`;
|
|
2335
|
-
const binary = Buffer.from(img.data, "base64");
|
|
2336
|
-
const uploadData = await slackApi(token, "files.getUploadURLExternal", {
|
|
2337
|
-
filename,
|
|
2338
|
-
length: binary.length
|
|
2339
|
-
});
|
|
2340
|
-
const uploadRes = await fetch(uploadData.upload_url, {
|
|
2341
|
-
method: "POST",
|
|
2342
|
-
body: binary
|
|
2343
|
-
});
|
|
2344
|
-
if (!uploadRes.ok) {
|
|
2345
|
-
throw new Error(`Slack file upload failed: ${uploadRes.status} ${uploadRes.statusText}`);
|
|
2346
|
-
}
|
|
2347
|
-
await slackApi(token, "files.completeUploadExternal", {
|
|
2348
|
-
files: [{ id: uploadData.file_id }],
|
|
2349
|
-
channel_id: channelId
|
|
2350
|
-
});
|
|
2351
|
-
}
|
|
2352
|
-
if (message) {
|
|
2353
|
-
const chunks2 = splitMessage(message, SLACK_MAX_LENGTH);
|
|
2354
|
-
for (const chunk of chunks2) {
|
|
2355
|
-
await slackApi(token, "chat.postMessage", {
|
|
2356
|
-
channel: channelId,
|
|
2357
|
-
text: chunk
|
|
2358
|
-
});
|
|
2359
|
-
}
|
|
2360
|
-
}
|
|
2361
|
-
return;
|
|
2362
|
-
}
|
|
2363
|
-
const chunks = splitMessage(message, SLACK_MAX_LENGTH);
|
|
2364
|
-
for (let i = 0; i < chunks.length; i++) {
|
|
2365
|
-
try {
|
|
2366
|
-
await slackApi(token, "chat.postMessage", {
|
|
2367
|
-
channel: channelId,
|
|
2368
|
-
text: chunks[i]
|
|
2369
|
-
});
|
|
2370
|
-
} catch (err) {
|
|
2371
|
-
const partial = i > 0 ? ` (${i}/${chunks.length} chunks were already sent)` : "";
|
|
2372
|
-
throw new Error(`${err instanceof Error ? err.message : err}${partial}`);
|
|
2373
|
-
}
|
|
2374
|
-
}
|
|
2375
|
-
}
|
|
2376
|
-
async function listConversations2(env) {
|
|
2377
|
-
const token = requireToken2(env);
|
|
2378
|
-
const authData = await slackApi(token, "auth.test", {});
|
|
2379
|
-
const teamName = authData.team ?? "workspace";
|
|
2380
|
-
const data = await slackApi(token, "conversations.list", {
|
|
2381
|
-
types: "public_channel,private_channel,mpim,im",
|
|
2382
|
-
limit: 1e3
|
|
2383
|
-
});
|
|
2384
|
-
const userMap = /* @__PURE__ */ new Map();
|
|
2385
|
-
const imChannels = data.channels.filter((ch) => ch.is_im && ch.user);
|
|
2386
|
-
if (imChannels.length > 0) {
|
|
2387
|
-
const users2 = await listUsers3(env);
|
|
2388
|
-
for (const u of users2) {
|
|
2389
|
-
userMap.set(u.id, u.username);
|
|
2390
|
-
}
|
|
2391
|
-
}
|
|
2392
|
-
return data.channels.map((ch) => {
|
|
2393
|
-
let type = "channel";
|
|
2394
|
-
if (ch.is_im) type = "dm";
|
|
2395
|
-
let slug;
|
|
2396
|
-
let name;
|
|
2397
|
-
if (ch.is_im && ch.user) {
|
|
2398
|
-
const username = userMap.get(ch.user) ?? ch.user;
|
|
2399
|
-
slug = `slack:@${slugify(username)}`;
|
|
2400
|
-
name = username;
|
|
2401
|
-
} else if (ch.name) {
|
|
2402
|
-
slug = `slack:${slugify(teamName)}/${slugify(ch.name)}`;
|
|
2403
|
-
name = ch.name;
|
|
2404
|
-
} else {
|
|
2405
|
-
slug = `slack:${ch.id}`;
|
|
2406
|
-
name = ch.id;
|
|
2407
|
-
}
|
|
2408
|
-
return {
|
|
2409
|
-
id: slug,
|
|
2410
|
-
platformId: ch.id,
|
|
2411
|
-
name,
|
|
2412
|
-
type,
|
|
2413
|
-
participantCount: ch.num_members
|
|
2414
|
-
};
|
|
2415
|
-
});
|
|
2416
|
-
}
|
|
2417
|
-
async function listUsers3(env) {
|
|
2418
|
-
const token = requireToken2(env);
|
|
2419
|
-
const data = await slackApi(token, "users.list", {});
|
|
2420
|
-
return data.members.filter((m) => !m.deleted).map((m) => ({
|
|
2421
|
-
id: m.id,
|
|
2422
|
-
username: m.name,
|
|
2423
|
-
type: m.is_bot ? "bot" : "human"
|
|
2424
|
-
}));
|
|
2425
|
-
}
|
|
2426
|
-
async function createConversation3(env, participants, name) {
|
|
2427
|
-
const token = requireToken2(env);
|
|
2428
|
-
const allUsers = await listUsers3(env);
|
|
2429
|
-
const ids = [];
|
|
2430
|
-
for (const p of participants) {
|
|
2431
|
-
const user = allUsers.find((u) => u.username.toLowerCase() === p.toLowerCase());
|
|
2432
|
-
if (!user) throw new Error(`User not found: ${p}`);
|
|
2433
|
-
ids.push(user.id);
|
|
2434
|
-
}
|
|
2435
|
-
if (name) {
|
|
2436
|
-
const createData = await slackApi(token, "conversations.create", {
|
|
2437
|
-
name,
|
|
2438
|
-
is_private: true
|
|
2439
|
-
});
|
|
2440
|
-
const channelId = createData.channel.id;
|
|
2441
|
-
for (const userId of ids) {
|
|
2442
|
-
await slackApi(token, "conversations.invite", {
|
|
2443
|
-
channel: channelId,
|
|
2444
|
-
users: userId
|
|
2445
|
-
});
|
|
2446
|
-
}
|
|
2447
|
-
const authData = await slackApi(token, "auth.test", {});
|
|
2448
|
-
const teamName = authData.team ?? "workspace";
|
|
2449
|
-
const slug = `slack:${slugify(teamName)}/${slugify(name)}`;
|
|
2450
|
-
return slug;
|
|
2451
|
-
}
|
|
2452
|
-
const openData = await slackApi(token, "conversations.open", { users: ids.join(",") });
|
|
2453
|
-
return `slack:${openData.channel.id}`;
|
|
2454
|
-
}
|
|
2455
|
-
|
|
2456
|
-
// packages/platforms/src/drivers/telegram.ts
|
|
2457
|
-
var telegram_exports = {};
|
|
2458
|
-
__export(telegram_exports, {
|
|
2459
|
-
createConversation: () => createConversation4,
|
|
2460
|
-
listConversations: () => listConversations3,
|
|
2461
|
-
listUsers: () => listUsers4,
|
|
2462
|
-
read: () => read3,
|
|
2463
|
-
send: () => send3
|
|
2464
|
-
});
|
|
2465
|
-
var TELEGRAM_MAX_LENGTH = 4096;
|
|
2466
|
-
var API_BASE3 = "https://api.telegram.org";
|
|
2467
|
-
function requireToken3(env) {
|
|
2468
|
-
const token = env.TELEGRAM_BOT_TOKEN;
|
|
2469
|
-
if (!token) throw new Error("TELEGRAM_BOT_TOKEN not set");
|
|
2470
|
-
return token;
|
|
2471
|
-
}
|
|
2472
|
-
async function read3(_env, _channelSlug, _limit) {
|
|
2473
|
-
throw new Error(
|
|
2474
|
-
"Telegram Bot API does not support reading chat history. Use volute chat send instead."
|
|
2475
|
-
);
|
|
2476
|
-
}
|
|
2477
|
-
async function send3(env, channelSlug, message, images) {
|
|
2478
|
-
const token = requireToken3(env);
|
|
2479
|
-
const chatId = resolvePlatformId(channelSlug);
|
|
2480
|
-
if (images?.length) {
|
|
2481
|
-
const CAPTION_MAX = 1024;
|
|
2482
|
-
for (let i = 0; i < images.length; i++) {
|
|
2483
|
-
const img = images[i];
|
|
2484
|
-
const ext = img.media_type.split("/")[1] || "png";
|
|
2485
|
-
const form = new FormData();
|
|
2486
|
-
form.append("chat_id", chatId);
|
|
2487
|
-
form.append(
|
|
2488
|
-
"photo",
|
|
2489
|
-
new Blob([Buffer.from(img.data, "base64")], { type: img.media_type }),
|
|
2490
|
-
`image.${ext}`
|
|
2491
|
-
);
|
|
2492
|
-
if (i === 0 && message) {
|
|
2493
|
-
form.append("caption", message.slice(0, CAPTION_MAX));
|
|
2494
|
-
}
|
|
2495
|
-
const res = await fetch(`${API_BASE3}/bot${token}/sendPhoto`, {
|
|
2496
|
-
method: "POST",
|
|
2497
|
-
body: form
|
|
2498
|
-
});
|
|
2499
|
-
if (!res.ok) {
|
|
2500
|
-
const body = await res.text().catch(() => "");
|
|
2501
|
-
const partial = i > 0 ? ` (${i}/${images.length} images were already sent)` : "";
|
|
2502
|
-
throw new Error(`Telegram API error: ${res.status} ${body}${partial}`);
|
|
2503
|
-
}
|
|
2504
|
-
}
|
|
2505
|
-
if (message && message.length > CAPTION_MAX) {
|
|
2506
|
-
const remaining = message.slice(CAPTION_MAX);
|
|
2507
|
-
const chunks2 = splitMessage(remaining, TELEGRAM_MAX_LENGTH);
|
|
2508
|
-
for (const chunk of chunks2) {
|
|
2509
|
-
const res = await fetch(`${API_BASE3}/bot${token}/sendMessage`, {
|
|
2510
|
-
method: "POST",
|
|
2511
|
-
headers: { "Content-Type": "application/json" },
|
|
2512
|
-
body: JSON.stringify({ chat_id: chatId, text: chunk })
|
|
2513
|
-
});
|
|
2514
|
-
if (!res.ok) {
|
|
2515
|
-
const body = await res.text().catch(() => "");
|
|
2516
|
-
throw new Error(`Telegram API error: ${res.status} ${body}`);
|
|
2517
|
-
}
|
|
2518
|
-
}
|
|
2519
|
-
}
|
|
2520
|
-
return;
|
|
2521
|
-
}
|
|
2522
|
-
const chunks = splitMessage(message, TELEGRAM_MAX_LENGTH);
|
|
2523
|
-
for (let i = 0; i < chunks.length; i++) {
|
|
2524
|
-
const res = await fetch(`${API_BASE3}/bot${token}/sendMessage`, {
|
|
2525
|
-
method: "POST",
|
|
2526
|
-
headers: { "Content-Type": "application/json" },
|
|
2527
|
-
body: JSON.stringify({ chat_id: chatId, text: chunks[i] })
|
|
2528
|
-
});
|
|
2529
|
-
if (!res.ok) {
|
|
2530
|
-
const body = await res.text().catch(() => "");
|
|
2531
|
-
const partial = i > 0 ? ` (${i}/${chunks.length} chunks were already sent)` : "";
|
|
2532
|
-
throw new Error(`Telegram API error: ${res.status} ${body}${partial}`);
|
|
2533
|
-
}
|
|
2534
|
-
}
|
|
2535
|
-
}
|
|
2536
|
-
async function listConversations3() {
|
|
2537
|
-
throw new Error(
|
|
2538
|
-
"Telegram Bot API does not support listing conversations. Users must message the bot first."
|
|
2539
|
-
);
|
|
2540
|
-
}
|
|
2541
|
-
async function listUsers4() {
|
|
2542
|
-
throw new Error(
|
|
2543
|
-
"Telegram Bot API does not support listing users. Users must message the bot first."
|
|
2544
|
-
);
|
|
2545
|
-
}
|
|
2546
|
-
async function createConversation4() {
|
|
2547
|
-
throw new Error(
|
|
2548
|
-
"Telegram Bot API does not support creating conversations. Users must message the bot first."
|
|
2549
|
-
);
|
|
2550
|
-
}
|
|
2551
|
-
|
|
2552
|
-
// packages/platforms/src/index.ts
|
|
2553
|
-
var PLATFORMS = {
|
|
2554
|
-
discord: {
|
|
2555
|
-
name: "discord",
|
|
2556
|
-
displayName: "Discord",
|
|
2557
|
-
driver: discord_exports
|
|
2558
|
-
},
|
|
2559
|
-
slack: {
|
|
2560
|
-
name: "slack",
|
|
2561
|
-
displayName: "Slack",
|
|
2562
|
-
driver: slack_exports
|
|
2563
|
-
},
|
|
2564
|
-
telegram: {
|
|
2565
|
-
name: "telegram",
|
|
2566
|
-
displayName: "Telegram",
|
|
2567
|
-
driver: telegram_exports
|
|
2568
|
-
},
|
|
2569
|
-
volute: { name: "volute", displayName: "Volute" },
|
|
2570
|
-
mail: { name: "mail", displayName: "Email" },
|
|
2571
|
-
system: { name: "system", displayName: "System" }
|
|
2572
|
-
};
|
|
2573
|
-
function registerPlatform(name, platform) {
|
|
2574
|
-
PLATFORMS[name] = platform;
|
|
2575
|
-
}
|
|
2576
|
-
function getPlatformDriver(platform) {
|
|
2577
|
-
return PLATFORMS[platform]?.driver ?? null;
|
|
2578
|
-
}
|
|
2579
|
-
function resolvePlatformId(slug) {
|
|
2580
|
-
const colonIdx = slug.indexOf(":");
|
|
2581
|
-
return colonIdx !== -1 ? slug.slice(colonIdx + 1) : slug;
|
|
2582
|
-
}
|
|
2583
|
-
|
|
2584
|
-
// packages/daemon/src/lib/platforms/volute.ts
|
|
2585
|
-
var volute_exports = {};
|
|
2586
|
-
__export(volute_exports, {
|
|
2587
|
-
createConversation: () => createConversation5,
|
|
2588
|
-
listConversations: () => listConversations4,
|
|
2589
|
-
listUsers: () => listUsers5,
|
|
2590
|
-
read: () => read4,
|
|
2591
|
-
send: () => send4
|
|
2592
|
-
});
|
|
2593
|
-
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
|
|
2594
|
-
import { resolve as resolve4 } from "path";
|
|
2595
|
-
function readSessionFile(mindDir2) {
|
|
2596
|
-
try {
|
|
2597
|
-
const p = resolve4(mindDir2, ".mind", "current-session");
|
|
2598
|
-
if (existsSync4(p)) return readFileSync4(p, "utf-8").trim() || void 0;
|
|
2599
|
-
} catch (err) {
|
|
2600
|
-
const code = err.code;
|
|
2601
|
-
if (code !== "ENOENT") {
|
|
2602
|
-
console.error(`[volute] failed to read session file: ${code ?? err}`);
|
|
2603
|
-
}
|
|
2604
|
-
}
|
|
2605
|
-
return void 0;
|
|
2606
|
-
}
|
|
2607
|
-
function getDaemonConfig() {
|
|
2608
|
-
const configPath = resolve4(voluteSystemDir(), "daemon.json");
|
|
2609
|
-
if (!existsSync4(configPath)) {
|
|
2610
|
-
throw new Error("Volute daemon is not running");
|
|
2611
|
-
}
|
|
2612
|
-
let config2;
|
|
2613
|
-
try {
|
|
2614
|
-
config2 = JSON.parse(readFileSync4(configPath, "utf-8"));
|
|
2615
|
-
} catch (err) {
|
|
2616
|
-
throw new Error(`Failed to parse ${configPath}: ${err}`);
|
|
2617
|
-
}
|
|
2618
|
-
if (typeof config2.port !== "number") {
|
|
2619
|
-
throw new Error(`Invalid or missing port in ${configPath}`);
|
|
2620
|
-
}
|
|
2621
|
-
const url = new URL("http://localhost");
|
|
2622
|
-
url.hostname = config2.hostname || "localhost";
|
|
2623
|
-
url.port = String(config2.port);
|
|
2624
|
-
return { url: url.origin, token: config2.token };
|
|
2625
|
-
}
|
|
2626
|
-
async function read4(env, channelSlug, limit) {
|
|
2627
|
-
const mindName = env.VOLUTE_MIND;
|
|
2628
|
-
if (!mindName) throw new Error("VOLUTE_MIND not set");
|
|
2629
|
-
const conversationId = resolvePlatformId(channelSlug);
|
|
2630
|
-
const { url, token } = getDaemonConfig();
|
|
2631
|
-
const headers = { Origin: url };
|
|
2632
|
-
if (token) headers.Authorization = `Bearer ${token}`;
|
|
2633
|
-
const res = await fetch(
|
|
2634
|
-
`${url}/api/minds/${encodeURIComponent(mindName)}/conversations/${encodeURIComponent(conversationId)}/messages`,
|
|
2635
|
-
{ headers }
|
|
2636
|
-
);
|
|
2637
|
-
if (!res.ok) {
|
|
2638
|
-
throw new Error(`Failed to read conversation: ${res.status} ${res.statusText}`);
|
|
2639
|
-
}
|
|
2640
|
-
const data = await res.json();
|
|
2641
|
-
if (!Array.isArray(data.items)) {
|
|
2642
|
-
throw new Error("Unexpected response format when reading conversation messages");
|
|
2643
|
-
}
|
|
2644
|
-
return data.items.slice(-limit).map((m) => {
|
|
2645
|
-
const text = Array.isArray(m.content) ? m.content.filter((b) => b.type === "text").map((b) => b.text).join("") : m.content;
|
|
2646
|
-
return `${m.sender_name ?? m.role}: ${text}`;
|
|
2647
|
-
}).join("\n");
|
|
2648
|
-
}
|
|
2649
|
-
async function send4(env, channelSlug, message, images) {
|
|
2650
|
-
const mindName = env.VOLUTE_MIND;
|
|
2651
|
-
if (!mindName) throw new Error("VOLUTE_MIND not set");
|
|
2652
|
-
const conversationId = resolvePlatformId(channelSlug);
|
|
2653
|
-
const { url, token } = getDaemonConfig();
|
|
2654
|
-
const headers = {
|
|
2655
|
-
"Content-Type": "application/json",
|
|
2656
|
-
Origin: url
|
|
2657
|
-
};
|
|
2658
|
-
if (token) headers.Authorization = `Bearer ${token}`;
|
|
2659
|
-
const voluteSession = env.VOLUTE_SESSION || (env.VOLUTE_MIND_DIR ? readSessionFile(env.VOLUTE_MIND_DIR) : void 0);
|
|
2660
|
-
if (voluteSession) headers["X-Volute-Session"] = voluteSession;
|
|
2661
|
-
const res = await fetch(`${url}/api/v1/chat`, {
|
|
2662
|
-
method: "POST",
|
|
2663
|
-
headers,
|
|
2664
|
-
body: JSON.stringify({
|
|
2665
|
-
message,
|
|
2666
|
-
conversationId,
|
|
2667
|
-
sender: env.VOLUTE_SENDER ?? mindName,
|
|
2668
|
-
images,
|
|
2669
|
-
targetMind: mindName
|
|
2670
|
-
})
|
|
2671
|
-
});
|
|
2672
|
-
if (!res.ok) {
|
|
2673
|
-
const data = await res.json().catch(() => ({}));
|
|
2674
|
-
throw new Error(data.error ?? `Failed to send: ${res.status}`);
|
|
2675
|
-
}
|
|
2676
|
-
}
|
|
2677
|
-
async function listConversations4(env) {
|
|
2678
|
-
const mindName = env.VOLUTE_MIND;
|
|
2679
|
-
if (!mindName) throw new Error("VOLUTE_MIND not set");
|
|
2680
|
-
const { url, token } = getDaemonConfig();
|
|
2681
|
-
const headers = { Origin: url };
|
|
2682
|
-
if (token) headers.Authorization = `Bearer ${token}`;
|
|
2683
|
-
const res = await fetch(`${url}/api/minds/${encodeURIComponent(mindName)}/conversations`, {
|
|
2684
|
-
headers
|
|
2685
|
-
});
|
|
2686
|
-
if (!res.ok) {
|
|
2687
|
-
throw new Error(`Failed to list conversations: ${res.status} ${res.statusText}`);
|
|
2688
|
-
}
|
|
2689
|
-
const convs = await res.json();
|
|
2690
|
-
const results = [];
|
|
2691
|
-
for (const conv of convs) {
|
|
2692
|
-
const participants = conv.participants ?? [];
|
|
2693
|
-
const slug = buildVoluteSlug({
|
|
2694
|
-
participants,
|
|
2695
|
-
mindUsername: mindName,
|
|
2696
|
-
conversationId: conv.id,
|
|
2697
|
-
convType: conv.type,
|
|
2698
|
-
convName: conv.channel_name
|
|
2699
|
-
});
|
|
2700
|
-
const convType = conv.type === "channel" ? "channel" : "dm";
|
|
2701
|
-
const other = participants.find((p) => p.username !== mindName);
|
|
2702
|
-
const displayName = conv.type === "channel" && conv.channel_name ? `#${conv.channel_name}` : other ? `@${other.username}` : "(untitled)";
|
|
2703
|
-
results.push({
|
|
2704
|
-
id: slug,
|
|
2705
|
-
platformId: conv.id,
|
|
2706
|
-
name: displayName,
|
|
2707
|
-
type: convType,
|
|
2708
|
-
participantCount: participants.length
|
|
2709
|
-
});
|
|
2710
|
-
}
|
|
2711
|
-
return results;
|
|
2712
|
-
}
|
|
2713
|
-
async function listUsers5(_env) {
|
|
2714
|
-
const { url, token } = getDaemonConfig();
|
|
2715
|
-
const headers = { Origin: url };
|
|
2716
|
-
if (token) headers.Authorization = `Bearer ${token}`;
|
|
2717
|
-
const res = await fetch(`${url}/api/auth/users`, { headers });
|
|
2718
|
-
if (!res.ok) {
|
|
2719
|
-
throw new Error(`Failed to list users: ${res.status} ${res.statusText}`);
|
|
2720
|
-
}
|
|
2721
|
-
const data = await res.json();
|
|
2722
|
-
return data.map((u) => ({
|
|
2723
|
-
id: String(u.id),
|
|
2724
|
-
username: u.username,
|
|
2725
|
-
type: u.user_type
|
|
2726
|
-
}));
|
|
2727
|
-
}
|
|
2728
|
-
async function createConversation5(env, participants, name) {
|
|
2729
|
-
const mindName = env.VOLUTE_MIND;
|
|
2730
|
-
if (!mindName) throw new Error("VOLUTE_MIND not set");
|
|
2731
|
-
const { url, token } = getDaemonConfig();
|
|
2732
|
-
const headers = {
|
|
2733
|
-
"Content-Type": "application/json",
|
|
2734
|
-
Origin: url
|
|
2735
|
-
};
|
|
2736
|
-
if (token) headers.Authorization = `Bearer ${token}`;
|
|
2737
|
-
const res = await fetch(`${url}/api/minds/${encodeURIComponent(mindName)}/conversations`, {
|
|
2738
|
-
method: "POST",
|
|
2739
|
-
headers,
|
|
2740
|
-
body: JSON.stringify({ participantNames: participants })
|
|
2741
|
-
});
|
|
2742
|
-
if (!res.ok) {
|
|
2743
|
-
const data = await res.json().catch(() => ({}));
|
|
2744
|
-
throw new Error(data.error ?? `Failed to create conversation: ${res.status}`);
|
|
2745
|
-
}
|
|
2746
|
-
const conv = await res.json();
|
|
2747
|
-
return conv.id;
|
|
2748
|
-
}
|
|
2749
|
-
|
|
2750
|
-
// packages/daemon/src/lib/platforms.ts
|
|
2751
|
-
registerPlatform("volute", {
|
|
2752
|
-
name: "volute",
|
|
2753
|
-
displayName: "Volute",
|
|
2754
|
-
builtIn: true,
|
|
2755
|
-
driver: volute_exports
|
|
2756
|
-
});
|
|
2757
|
-
|
|
2758
|
-
// packages/daemon/src/web/api/channels.ts
|
|
2759
2118
|
function buildEnv(name) {
|
|
2760
2119
|
return { ...loadMergedEnv(name), VOLUTE_MIND: name, VOLUTE_MIND_DIR: mindDir(name) };
|
|
2761
2120
|
}
|
|
@@ -2932,14 +2291,14 @@ var app7 = new Hono8().get("/", (c) => {
|
|
|
2932
2291
|
var extensions_default = app7;
|
|
2933
2292
|
|
|
2934
2293
|
// packages/daemon/src/web/api/file-sharing.ts
|
|
2935
|
-
import { readFileSync as
|
|
2936
|
-
import { resolve as
|
|
2294
|
+
import { readFileSync as readFileSync4, statSync } from "fs";
|
|
2295
|
+
import { resolve as resolve4 } from "path";
|
|
2937
2296
|
import { Hono as Hono9 } from "hono";
|
|
2938
2297
|
async function notifyMind(mindName, message) {
|
|
2939
2298
|
const entry = await findMind(mindName);
|
|
2940
2299
|
if (!entry) return;
|
|
2941
2300
|
try {
|
|
2942
|
-
const { sendSystemMessage } = await import("./system-chat-
|
|
2301
|
+
const { sendSystemMessage } = await import("./system-chat-7AIN3U5M.js");
|
|
2943
2302
|
await sendSystemMessage(mindName, message);
|
|
2944
2303
|
} catch (err) {
|
|
2945
2304
|
logger_default.warn(`[file-sharing] notify mind ${mindName} failed`, logger_default.errorData(err));
|
|
@@ -2958,7 +2317,7 @@ var app8 = new Hono9().post("/:name/files/send", requireSelf(), async (c) => {
|
|
|
2958
2317
|
const pathErr = validateFilePath(body.filePath);
|
|
2959
2318
|
if (pathErr) return c.json({ error: pathErr }, 400);
|
|
2960
2319
|
const senderDir = mindDir(senderName);
|
|
2961
|
-
const filePath =
|
|
2320
|
+
const filePath = resolve4(senderDir, "home", body.filePath);
|
|
2962
2321
|
const MAX_FILE_SIZE3 = 50 * 1024 * 1024;
|
|
2963
2322
|
const stat3 = statSync(filePath, { throwIfNoEntry: false });
|
|
2964
2323
|
if (!stat3) return c.json({ error: `File not found: ${body.filePath}` }, 404);
|
|
@@ -2972,7 +2331,7 @@ var app8 = new Hono9().post("/:name/files/send", requireSelf(), async (c) => {
|
|
|
2972
2331
|
}
|
|
2973
2332
|
let content;
|
|
2974
2333
|
try {
|
|
2975
|
-
content =
|
|
2334
|
+
content = readFileSync4(filePath);
|
|
2976
2335
|
} catch (err) {
|
|
2977
2336
|
const code = err.code;
|
|
2978
2337
|
if (code === "ENOENT") {
|
|
@@ -3064,7 +2423,7 @@ var file_sharing_default = app8;
|
|
|
3064
2423
|
// packages/daemon/src/web/api/files.ts
|
|
3065
2424
|
import { mkdirSync as mkdirSync3, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
3066
2425
|
import { readdir, readFile, realpath, stat } from "fs/promises";
|
|
3067
|
-
import { extname as extname2, resolve as
|
|
2426
|
+
import { extname as extname2, resolve as resolve5 } from "path";
|
|
3068
2427
|
import { Hono as Hono10 } from "hono";
|
|
3069
2428
|
var AVATAR_MIME2 = {
|
|
3070
2429
|
".png": "image/png",
|
|
@@ -3109,13 +2468,13 @@ var app9 = new Hono10().post("/:name/avatar", requireSelf(), async (c) => {
|
|
|
3109
2468
|
return c.json({ error: "Invalid file type (png, jpg, gif, webp only)" }, 400);
|
|
3110
2469
|
}
|
|
3111
2470
|
const dir = entry.dir ?? mindDir(name);
|
|
3112
|
-
const homeDir =
|
|
2471
|
+
const homeDir = resolve5(dir, "home");
|
|
3113
2472
|
const filename = `avatar${ext}`;
|
|
3114
|
-
const avatarPath =
|
|
2473
|
+
const avatarPath = resolve5(homeDir, filename);
|
|
3115
2474
|
const config2 = readVoluteConfig(dir) ?? {};
|
|
3116
2475
|
const oldAvatar = config2.profile?.avatar;
|
|
3117
2476
|
if (oldAvatar && oldAvatar !== filename) {
|
|
3118
|
-
rmSync2(
|
|
2477
|
+
rmSync2(resolve5(homeDir, oldAvatar), { force: true });
|
|
3119
2478
|
}
|
|
3120
2479
|
const buffer2 = Buffer.from(await file.arrayBuffer());
|
|
3121
2480
|
mkdirSync3(homeDir, { recursive: true });
|
|
@@ -3137,8 +2496,8 @@ var app9 = new Hono10().post("/:name/avatar", requireSelf(), async (c) => {
|
|
|
3137
2496
|
const ext = extname2(config2.profile.avatar).toLowerCase();
|
|
3138
2497
|
const mime = AVATAR_MIME2[ext];
|
|
3139
2498
|
if (!mime) return c.json({ error: "Invalid avatar extension" }, 400);
|
|
3140
|
-
const homeDir =
|
|
3141
|
-
const avatarPath =
|
|
2499
|
+
const homeDir = resolve5(dir, "home");
|
|
2500
|
+
const avatarPath = resolve5(homeDir, config2.profile.avatar);
|
|
3142
2501
|
if (!avatarPath.startsWith(`${homeDir}/`)) return c.json({ error: "Invalid avatar path" }, 400);
|
|
3143
2502
|
let realAvatarPath;
|
|
3144
2503
|
try {
|
|
@@ -3166,7 +2525,7 @@ var app9 = new Hono10().post("/:name/avatar", requireSelf(), async (c) => {
|
|
|
3166
2525
|
const name = c.req.param("name");
|
|
3167
2526
|
const entry = await findMind(name);
|
|
3168
2527
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
3169
|
-
const homeDir =
|
|
2528
|
+
const homeDir = resolve5(entry.dir ?? mindDir(name), "home");
|
|
3170
2529
|
let entries;
|
|
3171
2530
|
try {
|
|
3172
2531
|
entries = await readdir(homeDir, { withFileTypes: true });
|
|
@@ -3181,10 +2540,10 @@ var app9 = new Hono10().post("/:name/avatar", requireSelf(), async (c) => {
|
|
|
3181
2540
|
const name = c.req.param("name");
|
|
3182
2541
|
const entry = await findMind(name);
|
|
3183
2542
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
3184
|
-
const homeDir =
|
|
2543
|
+
const homeDir = resolve5(entry.dir ?? mindDir(name), "home");
|
|
3185
2544
|
const wildcard = c.req.path.replace(new RegExp(`^.*/minds/${name}/files`), "") || "/";
|
|
3186
2545
|
const relativePath = wildcard.slice(1);
|
|
3187
|
-
const requestedPath =
|
|
2546
|
+
const requestedPath = resolve5(homeDir, relativePath);
|
|
3188
2547
|
if (requestedPath !== homeDir && !requestedPath.startsWith(`${homeDir}/`))
|
|
3189
2548
|
return c.text("Forbidden", 403);
|
|
3190
2549
|
if (relativePath.split("/").some((seg) => seg.startsWith("."))) return c.text("Forbidden", 403);
|
|
@@ -3471,7 +2830,7 @@ var history = new Hono11().get("/turns", async (c) => {
|
|
|
3471
2830
|
const stream = new ReadableStream({
|
|
3472
2831
|
start(controller) {
|
|
3473
2832
|
const encoder = new TextEncoder();
|
|
3474
|
-
const
|
|
2833
|
+
const send = (data) => {
|
|
3475
2834
|
controller.enqueue(encoder.encode(`data: ${data}
|
|
3476
2835
|
|
|
3477
2836
|
`));
|
|
@@ -3488,7 +2847,7 @@ var history = new Hono11().get("/turns", async (c) => {
|
|
|
3488
2847
|
if (mindFilter) {
|
|
3489
2848
|
unsubscribe = subscribe3(mindFilter, (event) => {
|
|
3490
2849
|
try {
|
|
3491
|
-
|
|
2850
|
+
send(JSON.stringify(event));
|
|
3492
2851
|
} catch {
|
|
3493
2852
|
clearInterval(pingInterval);
|
|
3494
2853
|
unsubscribe?.();
|
|
@@ -3497,7 +2856,7 @@ var history = new Hono11().get("/turns", async (c) => {
|
|
|
3497
2856
|
} else {
|
|
3498
2857
|
unsubscribe = subscribeAll((event) => {
|
|
3499
2858
|
try {
|
|
3500
|
-
|
|
2859
|
+
send(JSON.stringify(event));
|
|
3501
2860
|
} catch {
|
|
3502
2861
|
clearInterval(pingInterval);
|
|
3503
2862
|
unsubscribe?.();
|
|
@@ -3615,17 +2974,17 @@ import { Hono as Hono12 } from "hono";
|
|
|
3615
2974
|
|
|
3616
2975
|
// packages/daemon/src/lib/mind/identity.ts
|
|
3617
2976
|
import { createHash, generateKeyPairSync, sign, verify } from "crypto";
|
|
3618
|
-
import { existsSync as
|
|
3619
|
-
import { resolve as
|
|
2977
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
2978
|
+
import { resolve as resolve6 } from "path";
|
|
3620
2979
|
function generateIdentity(mindDir2) {
|
|
3621
|
-
const identityDir =
|
|
2980
|
+
const identityDir = resolve6(mindDir2, ".mind/identity");
|
|
3622
2981
|
mkdirSync4(identityDir, { recursive: true });
|
|
3623
2982
|
const { publicKey, privateKey } = generateKeyPairSync("ed25519", {
|
|
3624
2983
|
publicKeyEncoding: { type: "spki", format: "pem" },
|
|
3625
2984
|
privateKeyEncoding: { type: "pkcs8", format: "pem" }
|
|
3626
2985
|
});
|
|
3627
|
-
const privatePath =
|
|
3628
|
-
const publicPath =
|
|
2986
|
+
const privatePath = resolve6(identityDir, "private.pem");
|
|
2987
|
+
const publicPath = resolve6(identityDir, "public.pem");
|
|
3629
2988
|
writeFileSync4(privatePath, privateKey, { mode: 384 });
|
|
3630
2989
|
writeFileSync4(publicPath, publicKey, { mode: 420 });
|
|
3631
2990
|
const config2 = readVoluteConfig(mindDir2) ?? {};
|
|
@@ -3640,9 +2999,9 @@ function getPublicKey(mindDir2) {
|
|
|
3640
2999
|
const config2 = readVoluteConfig(mindDir2);
|
|
3641
3000
|
const relPath = config2?.identity?.publicKey;
|
|
3642
3001
|
if (!relPath) return null;
|
|
3643
|
-
const fullPath =
|
|
3644
|
-
if (!
|
|
3645
|
-
return
|
|
3002
|
+
const fullPath = resolve6(mindDir2, relPath);
|
|
3003
|
+
if (!existsSync4(fullPath)) return null;
|
|
3004
|
+
return readFileSync5(fullPath, "utf-8");
|
|
3646
3005
|
}
|
|
3647
3006
|
function getFingerprint(publicKeyPem) {
|
|
3648
3007
|
return createHash("sha256").update(publicKeyPem).digest("hex");
|
|
@@ -3689,16 +3048,16 @@ var keys_default = app10;
|
|
|
3689
3048
|
|
|
3690
3049
|
// packages/daemon/src/web/api/logs.ts
|
|
3691
3050
|
import { spawn as spawn2 } from "child_process";
|
|
3692
|
-
import { existsSync as
|
|
3693
|
-
import { resolve as
|
|
3051
|
+
import { existsSync as existsSync5 } from "fs";
|
|
3052
|
+
import { resolve as resolve7 } from "path";
|
|
3694
3053
|
import { Hono as Hono13 } from "hono";
|
|
3695
3054
|
import { streamSSE as streamSSE3 } from "hono/streaming";
|
|
3696
3055
|
var app11 = new Hono13().get("/:name/logs", async (c) => {
|
|
3697
3056
|
const name = c.req.param("name");
|
|
3698
3057
|
const entry = await findMind(name);
|
|
3699
3058
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
3700
|
-
const logFile =
|
|
3701
|
-
if (!
|
|
3059
|
+
const logFile = resolve7(stateDir(name), "logs", "mind.log");
|
|
3060
|
+
if (!existsSync5(logFile)) {
|
|
3702
3061
|
return c.json({ error: "No log file found" }, 404);
|
|
3703
3062
|
}
|
|
3704
3063
|
return streamSSE3(c, async (stream) => {
|
|
@@ -3716,17 +3075,17 @@ var app11 = new Hono13().get("/:name/logs", async (c) => {
|
|
|
3716
3075
|
stream.onAbort(() => {
|
|
3717
3076
|
tail.kill();
|
|
3718
3077
|
});
|
|
3719
|
-
await new Promise((
|
|
3720
|
-
tail.on("exit",
|
|
3721
|
-
stream.onAbort(
|
|
3078
|
+
await new Promise((resolve17) => {
|
|
3079
|
+
tail.on("exit", resolve17);
|
|
3080
|
+
stream.onAbort(resolve17);
|
|
3722
3081
|
});
|
|
3723
3082
|
});
|
|
3724
3083
|
}).get("/:name/logs/tail", async (c) => {
|
|
3725
3084
|
const name = c.req.param("name");
|
|
3726
3085
|
const entry = await findMind(name);
|
|
3727
3086
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
3728
|
-
const logFile =
|
|
3729
|
-
if (!
|
|
3087
|
+
const logFile = resolve7(stateDir(name), "logs", "mind.log");
|
|
3088
|
+
if (!existsSync5(logFile)) {
|
|
3730
3089
|
return c.json({ error: "No log file found" }, 404);
|
|
3731
3090
|
}
|
|
3732
3091
|
const nParam = parseInt(c.req.query("n") ?? "50", 10);
|
|
@@ -3736,8 +3095,8 @@ var app11 = new Hono13().get("/:name/logs", async (c) => {
|
|
|
3736
3095
|
tail.stdout.on("data", (data) => {
|
|
3737
3096
|
output += data.toString();
|
|
3738
3097
|
});
|
|
3739
|
-
await new Promise((
|
|
3740
|
-
tail.on("exit",
|
|
3098
|
+
await new Promise((resolve17) => {
|
|
3099
|
+
tail.on("exit", resolve17);
|
|
3741
3100
|
});
|
|
3742
3101
|
return c.text(output);
|
|
3743
3102
|
});
|
|
@@ -3827,33 +3186,33 @@ var mind_skills_default = app12;
|
|
|
3827
3186
|
// packages/daemon/src/web/api/minds.ts
|
|
3828
3187
|
import {
|
|
3829
3188
|
cpSync,
|
|
3830
|
-
existsSync as
|
|
3189
|
+
existsSync as existsSync7,
|
|
3831
3190
|
mkdirSync as mkdirSync6,
|
|
3832
3191
|
readdirSync as readdirSync2,
|
|
3833
|
-
readFileSync as
|
|
3192
|
+
readFileSync as readFileSync8,
|
|
3834
3193
|
rmSync as rmSync4,
|
|
3835
3194
|
writeFileSync as writeFileSync7
|
|
3836
3195
|
} from "fs";
|
|
3837
|
-
import { resolve as
|
|
3196
|
+
import { resolve as resolve10 } from "path";
|
|
3838
3197
|
import { zValidator as zValidator5 } from "@hono/zod-validator";
|
|
3839
3198
|
import { and as and4, desc as desc3, eq as eq5, sql as sql2 } from "drizzle-orm";
|
|
3840
3199
|
import { Hono as Hono15 } from "hono";
|
|
3841
3200
|
import { z as z5 } from "zod";
|
|
3842
3201
|
|
|
3843
3202
|
// packages/daemon/src/lib/mind/consolidate.ts
|
|
3844
|
-
import { readdirSync, readFileSync as
|
|
3845
|
-
import { resolve as
|
|
3203
|
+
import { readdirSync, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
3204
|
+
import { resolve as resolve8 } from "path";
|
|
3846
3205
|
async function consolidateMemory(mindDir2) {
|
|
3847
|
-
const soulPath =
|
|
3848
|
-
const memoryPath =
|
|
3849
|
-
const memoryDir =
|
|
3850
|
-
const soul =
|
|
3206
|
+
const soulPath = resolve8(mindDir2, "home/SOUL.md");
|
|
3207
|
+
const memoryPath = resolve8(mindDir2, "home/MEMORY.md");
|
|
3208
|
+
const memoryDir = resolve8(mindDir2, "home/memory");
|
|
3209
|
+
const soul = readFileSync6(soulPath, "utf-8");
|
|
3851
3210
|
const logs = [];
|
|
3852
3211
|
try {
|
|
3853
3212
|
const files = readdirSync(memoryDir).filter((f) => /^\d{4}-\d{2}-\d{2}\.md$/.test(f)).sort();
|
|
3854
3213
|
for (const filename of files) {
|
|
3855
3214
|
const date = filename.replace(".md", "");
|
|
3856
|
-
const content2 =
|
|
3215
|
+
const content2 = readFileSync6(resolve8(memoryDir, filename), "utf-8").trim();
|
|
3857
3216
|
if (content2) {
|
|
3858
3217
|
logs.push(`### ${date}
|
|
3859
3218
|
|
|
@@ -3912,7 +3271,7 @@ ${content2}`);
|
|
|
3912
3271
|
}
|
|
3913
3272
|
|
|
3914
3273
|
// packages/daemon/src/lib/mind/variant-cleanup.ts
|
|
3915
|
-
import { existsSync as
|
|
3274
|
+
import { existsSync as existsSync6, rmSync as rmSync3 } from "fs";
|
|
3916
3275
|
async function cleanupVariant(variantName, projectRoot, variantPath, opts) {
|
|
3917
3276
|
if (opts?.stop) {
|
|
3918
3277
|
try {
|
|
@@ -3921,10 +3280,10 @@ async function cleanupVariant(variantName, projectRoot, variantPath, opts) {
|
|
|
3921
3280
|
logger_default.warn(`failed to stop variant ${variantName}`, logger_default.errorData(err));
|
|
3922
3281
|
}
|
|
3923
3282
|
}
|
|
3924
|
-
const { findMind: findMind2 } = await import("./registry-
|
|
3283
|
+
const { findMind: findMind2 } = await import("./registry-KMELPC3X.js");
|
|
3925
3284
|
const variantEntry = await findMind2(variantName);
|
|
3926
3285
|
const branchName = variantEntry?.branch ?? variantName;
|
|
3927
|
-
if (
|
|
3286
|
+
if (existsSync6(variantPath)) {
|
|
3928
3287
|
try {
|
|
3929
3288
|
await gitExec(["worktree", "remove", "--force", variantPath], { cwd: projectRoot });
|
|
3930
3289
|
} catch {
|
|
@@ -3971,11 +3330,11 @@ function validateBranchName(branch) {
|
|
|
3971
3330
|
|
|
3972
3331
|
// packages/daemon/src/lib/template/convert-session.ts
|
|
3973
3332
|
import { randomUUID } from "crypto";
|
|
3974
|
-
import { mkdirSync as mkdirSync5, readFileSync as
|
|
3333
|
+
import { mkdirSync as mkdirSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
|
|
3975
3334
|
import { homedir } from "os";
|
|
3976
|
-
import { resolve as
|
|
3335
|
+
import { resolve as resolve9 } from "path";
|
|
3977
3336
|
function convertSession(opts) {
|
|
3978
|
-
const lines =
|
|
3337
|
+
const lines = readFileSync7(opts.sessionPath, "utf-8").trim().split("\n");
|
|
3979
3338
|
const sessionId = randomUUID();
|
|
3980
3339
|
const idMap = /* @__PURE__ */ new Map();
|
|
3981
3340
|
const messages = [];
|
|
@@ -4089,9 +3448,9 @@ function convertSession(opts) {
|
|
|
4089
3448
|
}
|
|
4090
3449
|
}
|
|
4091
3450
|
const projectId = opts.projectDir.replace(/\//g, "-");
|
|
4092
|
-
const sdkDir =
|
|
3451
|
+
const sdkDir = resolve9(homedir(), ".claude", "projects", projectId);
|
|
4093
3452
|
mkdirSync5(sdkDir, { recursive: true });
|
|
4094
|
-
const sdkPath =
|
|
3453
|
+
const sdkPath = resolve9(sdkDir, `${sessionId}.jsonl`);
|
|
4095
3454
|
writeFileSync6(sdkPath, `${sdkEvents.join("\n")}
|
|
4096
3455
|
`);
|
|
4097
3456
|
console.log(`Converted ${sdkEvents.length} messages \u2192 ${sdkPath}`);
|
|
@@ -4165,7 +3524,7 @@ async function getMindStatus(name, port, registryRunning) {
|
|
|
4165
3524
|
const manager = getMindManager();
|
|
4166
3525
|
let status = "stopped";
|
|
4167
3526
|
try {
|
|
4168
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
3527
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-PBOIEBJZ.js");
|
|
4169
3528
|
if (getSleepManagerIfReady2()?.isSleeping(name)) {
|
|
4170
3529
|
status = "sleeping";
|
|
4171
3530
|
}
|
|
@@ -4211,7 +3570,7 @@ async function initTemplateBranch(projectRoot, composedDir, manifest, mindName,
|
|
|
4211
3570
|
await gitExec(["commit", "-m", "initial commit"], opts);
|
|
4212
3571
|
}
|
|
4213
3572
|
async function updateTemplateBranch(projectRoot, template, mindName) {
|
|
4214
|
-
const tempWorktree =
|
|
3573
|
+
const tempWorktree = resolve10(projectRoot, ".variants", "_template_update");
|
|
4215
3574
|
let branchExists = false;
|
|
4216
3575
|
try {
|
|
4217
3576
|
await gitExec(["rev-parse", "--verify", TEMPLATE_BRANCH], { cwd: projectRoot });
|
|
@@ -4222,7 +3581,7 @@ async function updateTemplateBranch(projectRoot, template, mindName) {
|
|
|
4222
3581
|
await gitExec(["worktree", "remove", "--force", tempWorktree], { cwd: projectRoot });
|
|
4223
3582
|
} catch {
|
|
4224
3583
|
}
|
|
4225
|
-
if (
|
|
3584
|
+
if (existsSync7(tempWorktree)) {
|
|
4226
3585
|
rmSync4(tempWorktree, { recursive: true, force: true });
|
|
4227
3586
|
}
|
|
4228
3587
|
const templatesRoot = findTemplatesRoot();
|
|
@@ -4243,15 +3602,15 @@ async function updateTemplateBranch(projectRoot, template, mindName) {
|
|
|
4243
3602
|
});
|
|
4244
3603
|
}
|
|
4245
3604
|
copyTemplateToDir(composedDir, tempWorktree, mindName, manifest);
|
|
4246
|
-
const initDir =
|
|
4247
|
-
if (
|
|
3605
|
+
const initDir = resolve10(tempWorktree, ".init");
|
|
3606
|
+
if (existsSync7(initDir)) {
|
|
4248
3607
|
rmSync4(initDir, { recursive: true, force: true });
|
|
4249
3608
|
}
|
|
4250
|
-
const homeDir =
|
|
4251
|
-
if (
|
|
3609
|
+
const homeDir = resolve10(tempWorktree, "home");
|
|
3610
|
+
if (existsSync7(homeDir)) {
|
|
4252
3611
|
for (const entry of readdirSync2(homeDir)) {
|
|
4253
3612
|
if (entry !== "VOLUTE.md") {
|
|
4254
|
-
rmSync4(
|
|
3613
|
+
rmSync4(resolve10(homeDir, entry), { recursive: true, force: true });
|
|
4255
3614
|
}
|
|
4256
3615
|
}
|
|
4257
3616
|
}
|
|
@@ -4266,7 +3625,7 @@ async function updateTemplateBranch(projectRoot, template, mindName) {
|
|
|
4266
3625
|
await gitExec(["worktree", "remove", "--force", tempWorktree], { cwd: projectRoot });
|
|
4267
3626
|
} catch {
|
|
4268
3627
|
}
|
|
4269
|
-
if (
|
|
3628
|
+
if (existsSync7(tempWorktree)) {
|
|
4270
3629
|
rmSync4(tempWorktree, { recursive: true, force: true });
|
|
4271
3630
|
}
|
|
4272
3631
|
rmSync4(composedDir, { recursive: true, force: true });
|
|
@@ -4292,7 +3651,7 @@ async function mergeTemplateBranch(worktreeDir) {
|
|
|
4292
3651
|
async function npmInstallAsMind(cwd, mindName) {
|
|
4293
3652
|
if (isIsolationEnabled()) {
|
|
4294
3653
|
const [cmd, args] = await wrapForIsolation("npm", ["install"], mindName);
|
|
4295
|
-
await exec(cmd, args, { cwd, env: { ...process.env, HOME:
|
|
3654
|
+
await exec(cmd, args, { cwd, env: { ...process.env, HOME: resolve10(cwd, "home") } });
|
|
4296
3655
|
} else {
|
|
4297
3656
|
await exec("npm", ["install"], { cwd });
|
|
4298
3657
|
}
|
|
@@ -4343,8 +3702,8 @@ async function mergeUpgradeAndRestart(mindName, dir, worktreeDir, upgradeVariant
|
|
|
4343
3702
|
return { ok: true };
|
|
4344
3703
|
}
|
|
4345
3704
|
async function importFromArchive(c, tempDir, nameOverride, manifest) {
|
|
4346
|
-
const extractedMindDir =
|
|
4347
|
-
if (!
|
|
3705
|
+
const extractedMindDir = resolve10(tempDir, "mind");
|
|
3706
|
+
if (!existsSync7(extractedMindDir)) {
|
|
4348
3707
|
return c.json({ error: "Invalid archive: missing mind/ directory" }, 400);
|
|
4349
3708
|
}
|
|
4350
3709
|
if (!manifest?.includes || !manifest.name || !manifest.template) {
|
|
@@ -4362,7 +3721,7 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
|
|
|
4362
3721
|
if (await findMind(name)) return c.json({ error: `Mind already exists: ${name}` }, 409);
|
|
4363
3722
|
ensureVoluteHome();
|
|
4364
3723
|
const dest = mindDir(name);
|
|
4365
|
-
if (
|
|
3724
|
+
if (existsSync7(dest)) return c.json({ error: "Mind directory already exists" }, 409);
|
|
4366
3725
|
try {
|
|
4367
3726
|
cpSync(extractedMindDir, dest, { recursive: true });
|
|
4368
3727
|
if (!manifest.includes.identity) {
|
|
@@ -4370,9 +3729,9 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
|
|
|
4370
3729
|
}
|
|
4371
3730
|
const state = stateDir(name);
|
|
4372
3731
|
mkdirSync6(state, { recursive: true });
|
|
4373
|
-
const envJson =
|
|
4374
|
-
if (
|
|
4375
|
-
cpSync(envJson,
|
|
3732
|
+
const envJson = resolve10(tempDir, "state/env.json");
|
|
3733
|
+
if (existsSync7(envJson)) {
|
|
3734
|
+
cpSync(envJson, resolve10(state, "env.json"));
|
|
4376
3735
|
}
|
|
4377
3736
|
const port = await nextPort();
|
|
4378
3737
|
await addMind(name, port, manifest.stage, manifest.template);
|
|
@@ -4381,30 +3740,30 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
|
|
|
4381
3740
|
} catch (err) {
|
|
4382
3741
|
logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
|
|
4383
3742
|
}
|
|
4384
|
-
const homeDir =
|
|
3743
|
+
const homeDir = resolve10(dest, "home");
|
|
4385
3744
|
ensureVoluteGroup();
|
|
4386
3745
|
createMindUser(name, homeDir);
|
|
4387
3746
|
chownMindDir(dest, name);
|
|
4388
3747
|
await npmInstallAsMind(dest, name);
|
|
4389
3748
|
await importHistoryFromArchive(name, tempDir);
|
|
4390
3749
|
importSessionsFromArchive(dest, tempDir);
|
|
4391
|
-
if (!
|
|
3750
|
+
if (!existsSync7(resolve10(dest, ".git"))) {
|
|
4392
3751
|
try {
|
|
4393
|
-
const env = isIsolationEnabled() ? { ...process.env, HOME:
|
|
3752
|
+
const env = isIsolationEnabled() ? { ...process.env, HOME: resolve10(dest, "home") } : void 0;
|
|
4394
3753
|
await gitExec(["init"], { cwd: dest, mindName: name, env });
|
|
4395
3754
|
await configureGitIdentity(name, { cwd: dest, mindName: name, env });
|
|
4396
3755
|
await gitExec(["add", "-A"], { cwd: dest, mindName: name, env });
|
|
4397
3756
|
await gitExec(["commit", "-m", "import from archive"], { cwd: dest, mindName: name, env });
|
|
4398
3757
|
} catch (err) {
|
|
4399
3758
|
logger_default.error(`git setup failed for imported mind ${name}`, logger_default.errorData(err));
|
|
4400
|
-
rmSync4(
|
|
3759
|
+
rmSync4(resolve10(dest, ".git"), { recursive: true, force: true });
|
|
4401
3760
|
}
|
|
4402
3761
|
}
|
|
4403
3762
|
chownMindDir(dest, name);
|
|
4404
3763
|
rmSync4(tempDir, { recursive: true, force: true });
|
|
4405
3764
|
return c.json({ ok: true, name, port, message: `Imported mind: ${name} (port ${port})` });
|
|
4406
3765
|
} catch (err) {
|
|
4407
|
-
if (
|
|
3766
|
+
if (existsSync7(dest)) rmSync4(dest, { recursive: true, force: true });
|
|
4408
3767
|
try {
|
|
4409
3768
|
await removeMind(name);
|
|
4410
3769
|
} catch (cleanupErr) {
|
|
@@ -4421,7 +3780,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
4421
3780
|
if (await findMind(name)) return c.json({ error: `Mind already exists: ${name}` }, 409);
|
|
4422
3781
|
ensureVoluteHome();
|
|
4423
3782
|
const dest = mindDir(name);
|
|
4424
|
-
if (
|
|
3783
|
+
if (existsSync7(dest)) return c.json({ error: "Mind directory already exists" }, 409);
|
|
4425
3784
|
const templatesRoot = findTemplatesRoot();
|
|
4426
3785
|
const { composedDir, manifest: templateManifest } = composeTemplate(
|
|
4427
3786
|
templatesRoot,
|
|
@@ -4430,36 +3789,36 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
4430
3789
|
try {
|
|
4431
3790
|
copyTemplateToDir(composedDir, dest, name, templateManifest);
|
|
4432
3791
|
applyInitFiles(dest);
|
|
4433
|
-
const extractedHome =
|
|
4434
|
-
if (
|
|
4435
|
-
cpSync(extractedHome,
|
|
3792
|
+
const extractedHome = resolve10(extractedMindDir, "home");
|
|
3793
|
+
if (existsSync7(extractedHome)) {
|
|
3794
|
+
cpSync(extractedHome, resolve10(dest, "home"), { recursive: true });
|
|
4436
3795
|
}
|
|
4437
|
-
const extractedMindInternal =
|
|
4438
|
-
if (
|
|
4439
|
-
cpSync(extractedMindInternal,
|
|
3796
|
+
const extractedMindInternal = resolve10(extractedMindDir, ".mind");
|
|
3797
|
+
if (existsSync7(extractedMindInternal)) {
|
|
3798
|
+
cpSync(extractedMindInternal, resolve10(dest, ".mind"), { recursive: true });
|
|
4440
3799
|
}
|
|
4441
|
-
const identityDir =
|
|
3800
|
+
const identityDir = resolve10(dest, ".mind/identity");
|
|
4442
3801
|
let publicKeyPem;
|
|
4443
|
-
if (!manifest.includes.identity || !
|
|
3802
|
+
if (!manifest.includes.identity || !existsSync7(resolve10(identityDir, "private.pem"))) {
|
|
4444
3803
|
({ publicKeyPem } = generateIdentity(dest));
|
|
4445
3804
|
} else {
|
|
4446
|
-
publicKeyPem =
|
|
3805
|
+
publicKeyPem = readFileSync8(resolve10(identityDir, "public.pem"), "utf-8");
|
|
4447
3806
|
}
|
|
4448
|
-
const promptsPath =
|
|
4449
|
-
if (!
|
|
3807
|
+
const promptsPath = resolve10(dest, "home/.config/prompts.json");
|
|
3808
|
+
if (!existsSync7(promptsPath)) {
|
|
4450
3809
|
const mindPrompts = await getMindPromptDefaults();
|
|
4451
3810
|
writeFileSync7(promptsPath, `${JSON.stringify(mindPrompts, null, 2)}
|
|
4452
3811
|
`);
|
|
4453
3812
|
}
|
|
4454
3813
|
const state = stateDir(name);
|
|
4455
3814
|
mkdirSync6(state, { recursive: true });
|
|
4456
|
-
const envJson =
|
|
4457
|
-
if (
|
|
4458
|
-
cpSync(envJson,
|
|
3815
|
+
const envJson = resolve10(tempDir, "state/env.json");
|
|
3816
|
+
if (existsSync7(envJson)) {
|
|
3817
|
+
cpSync(envJson, resolve10(state, "env.json"));
|
|
4459
3818
|
}
|
|
4460
3819
|
const port = await nextPort();
|
|
4461
3820
|
await addMind(name, port, manifest.stage, manifest.template);
|
|
4462
|
-
const homeDir =
|
|
3821
|
+
const homeDir = resolve10(dest, "home");
|
|
4463
3822
|
ensureVoluteGroup();
|
|
4464
3823
|
createMindUser(name, homeDir);
|
|
4465
3824
|
chownMindDir(dest, name);
|
|
@@ -4472,7 +3831,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
4472
3831
|
await initTemplateBranch(dest, composedDir, templateManifest, name, env);
|
|
4473
3832
|
} catch (err) {
|
|
4474
3833
|
logger_default.error(`git setup failed for imported mind ${name}`, logger_default.errorData(err));
|
|
4475
|
-
rmSync4(
|
|
3834
|
+
rmSync4(resolve10(dest, ".git"), { recursive: true, force: true });
|
|
4476
3835
|
gitWarning = "Git setup failed \u2014 variants and upgrades won't be available until git is initialized.";
|
|
4477
3836
|
}
|
|
4478
3837
|
const skillSet = manifest.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions();
|
|
@@ -4502,7 +3861,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
4502
3861
|
...skillWarnings.length > 0 && { skillWarnings }
|
|
4503
3862
|
});
|
|
4504
3863
|
} catch (err) {
|
|
4505
|
-
if (
|
|
3864
|
+
if (existsSync7(dest)) rmSync4(dest, { recursive: true, force: true });
|
|
4506
3865
|
try {
|
|
4507
3866
|
await removeMind(name);
|
|
4508
3867
|
} catch (cleanupErr) {
|
|
@@ -4515,11 +3874,11 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
|
|
|
4515
3874
|
}
|
|
4516
3875
|
}
|
|
4517
3876
|
async function importHistoryFromArchive(name, tempDir) {
|
|
4518
|
-
const historyJsonl =
|
|
4519
|
-
if (!
|
|
3877
|
+
const historyJsonl = resolve10(tempDir, "history.jsonl");
|
|
3878
|
+
if (!existsSync7(historyJsonl)) return;
|
|
4520
3879
|
try {
|
|
4521
3880
|
const db = await getDb();
|
|
4522
|
-
const lines =
|
|
3881
|
+
const lines = readFileSync8(historyJsonl, "utf-8").trim().split("\n");
|
|
4523
3882
|
let imported = 0;
|
|
4524
3883
|
let failed = 0;
|
|
4525
3884
|
for (const line of lines) {
|
|
@@ -4555,13 +3914,13 @@ async function importHistoryFromArchive(name, tempDir) {
|
|
|
4555
3914
|
}
|
|
4556
3915
|
}
|
|
4557
3916
|
function importSessionsFromArchive(dest, tempDir) {
|
|
4558
|
-
const sessionsDir =
|
|
4559
|
-
if (!
|
|
3917
|
+
const sessionsDir = resolve10(tempDir, "sessions");
|
|
3918
|
+
if (!existsSync7(sessionsDir)) return;
|
|
4560
3919
|
try {
|
|
4561
|
-
const destSessions =
|
|
3920
|
+
const destSessions = resolve10(dest, ".mind/sessions");
|
|
4562
3921
|
mkdirSync6(destSessions, { recursive: true });
|
|
4563
3922
|
for (const file of readdirSync2(sessionsDir)) {
|
|
4564
|
-
cpSync(
|
|
3923
|
+
cpSync(resolve10(sessionsDir, file), resolve10(destSessions, file));
|
|
4565
3924
|
}
|
|
4566
3925
|
} catch (err) {
|
|
4567
3926
|
logger_default.error("Failed to import sessions from archive", logger_default.errorData(err));
|
|
@@ -4596,7 +3955,7 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
|
|
|
4596
3955
|
if (await findMind(name)) return c.json({ error: `Mind already exists: ${name}` }, 409);
|
|
4597
3956
|
ensureVoluteHome();
|
|
4598
3957
|
const dest = mindDir(name);
|
|
4599
|
-
if (
|
|
3958
|
+
if (existsSync7(dest)) return c.json({ error: "Mind directory already exists" }, 409);
|
|
4600
3959
|
const templatesRoot = findTemplatesRoot();
|
|
4601
3960
|
const { composedDir, manifest } = composeTemplate(templatesRoot, template);
|
|
4602
3961
|
try {
|
|
@@ -4604,7 +3963,7 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
|
|
|
4604
3963
|
applyInitFiles(dest);
|
|
4605
3964
|
const { publicKeyPem } = generateIdentity(dest);
|
|
4606
3965
|
{
|
|
4607
|
-
const { readGlobalConfig: readGlobal } = await import("./setup-
|
|
3966
|
+
const { readGlobalConfig: readGlobal } = await import("./setup-PF7JSFMO.js");
|
|
4608
3967
|
const mindDefaults = readGlobal().mindDefaults;
|
|
4609
3968
|
const config2 = readVoluteConfig(dest);
|
|
4610
3969
|
if (!config2) throw new Error("Failed to read volute.json after identity generation");
|
|
@@ -4641,9 +4000,9 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
|
|
|
4641
4000
|
}
|
|
4642
4001
|
writeVoluteConfig(dest, config2);
|
|
4643
4002
|
const modelId = body.model ?? cog?.model;
|
|
4644
|
-
const sdkConfigPath =
|
|
4003
|
+
const sdkConfigPath = resolve10(dest, "home/.config/config.json");
|
|
4645
4004
|
if (modelId || cog?.compaction) {
|
|
4646
|
-
const existing =
|
|
4005
|
+
const existing = existsSync7(sdkConfigPath) ? JSON.parse(readFileSync8(sdkConfigPath, "utf-8")) : {};
|
|
4647
4006
|
if (modelId) {
|
|
4648
4007
|
existing.model = template === "pi" ? qualifyModelId(modelId) : unqualifyModelId(modelId);
|
|
4649
4008
|
}
|
|
@@ -4656,7 +4015,7 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
|
|
|
4656
4015
|
}
|
|
4657
4016
|
const mindPrompts = await getMindPromptDefaults();
|
|
4658
4017
|
writeFileSync7(
|
|
4659
|
-
|
|
4018
|
+
resolve10(dest, "home/.config/prompts.json"),
|
|
4660
4019
|
`${JSON.stringify(mindPrompts, null, 2)}
|
|
4661
4020
|
`
|
|
4662
4021
|
);
|
|
@@ -4668,7 +4027,7 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
|
|
|
4668
4027
|
} catch (err) {
|
|
4669
4028
|
logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
|
|
4670
4029
|
}
|
|
4671
|
-
const homeDir =
|
|
4030
|
+
const homeDir = resolve10(dest, "home");
|
|
4672
4031
|
ensureVoluteGroup();
|
|
4673
4032
|
createMindUser(name, homeDir);
|
|
4674
4033
|
chownMindDir(dest, name);
|
|
@@ -4681,7 +4040,7 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
|
|
|
4681
4040
|
await initTemplateBranch(dest, composedDir, manifest, name, env);
|
|
4682
4041
|
} catch (err) {
|
|
4683
4042
|
logger_default.error(`git setup failed for ${name}`, logger_default.errorData(err));
|
|
4684
|
-
rmSync4(
|
|
4043
|
+
rmSync4(resolve10(dest, ".git"), { recursive: true, force: true });
|
|
4685
4044
|
gitWarning = "Git setup failed \u2014 variants and upgrades won't be available until git is initialized.";
|
|
4686
4045
|
}
|
|
4687
4046
|
chownMindDir(dest, name);
|
|
@@ -4691,11 +4050,11 @@ The human who planted you described you as: "${body.description}"
|
|
|
4691
4050
|
` : "";
|
|
4692
4051
|
const seedSoulRaw = body.seedSoul ?? await getPrompt("seed_soul", { name, description: descLine });
|
|
4693
4052
|
const seedSoul = body.seedSoul ? substitute(seedSoulRaw, { name, description: descLine }) : seedSoulRaw;
|
|
4694
|
-
writeFileSync7(
|
|
4053
|
+
writeFileSync7(resolve10(dest, "home/SOUL.md"), seedSoul);
|
|
4695
4054
|
}
|
|
4696
4055
|
let skillSet = body.skills ?? (body.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions());
|
|
4697
4056
|
if (body.stage === "seed" && !body.skills) {
|
|
4698
|
-
const { isImagegenEnabled } = await import("./setup-
|
|
4057
|
+
const { isImagegenEnabled } = await import("./setup-PF7JSFMO.js");
|
|
4699
4058
|
if (isImagegenEnabled()) {
|
|
4700
4059
|
skillSet = [...skillSet, "imagegen"];
|
|
4701
4060
|
}
|
|
@@ -4713,7 +4072,7 @@ The human who planted you described you as: "${body.description}"
|
|
|
4713
4072
|
try {
|
|
4714
4073
|
const spiritEntry = await findMind("volute");
|
|
4715
4074
|
if (spiritEntry) {
|
|
4716
|
-
const { spiritDir } = await import("./spirit-
|
|
4075
|
+
const { spiritDir } = await import("./spirit-4QOYM33G.js");
|
|
4717
4076
|
const sDir = spiritEntry.dir ?? spiritDir();
|
|
4718
4077
|
const spiritConfig = readVoluteConfig(sDir) ?? {};
|
|
4719
4078
|
const schedules = spiritConfig.schedules ?? [];
|
|
@@ -4728,7 +4087,7 @@ The human who planted you described you as: "${body.description}"
|
|
|
4728
4087
|
});
|
|
4729
4088
|
spiritConfig.schedules = schedules;
|
|
4730
4089
|
writeVoluteConfig(sDir, spiritConfig);
|
|
4731
|
-
const { getScheduler: getScheduler2 } = await import("./scheduler-
|
|
4090
|
+
const { getScheduler: getScheduler2 } = await import("./scheduler-355E746X.js");
|
|
4732
4091
|
getScheduler2().loadSchedules("volute", sDir);
|
|
4733
4092
|
}
|
|
4734
4093
|
}
|
|
@@ -4739,11 +4098,11 @@ The human who planted you described you as: "${body.description}"
|
|
|
4739
4098
|
if (body.stage !== "seed") {
|
|
4740
4099
|
const customSoul = await getPromptIfCustom("default_soul");
|
|
4741
4100
|
if (customSoul) {
|
|
4742
|
-
writeFileSync7(
|
|
4101
|
+
writeFileSync7(resolve10(dest, "home/SOUL.md"), customSoul.replace(/\{\{name\}\}/g, name));
|
|
4743
4102
|
}
|
|
4744
4103
|
const customMemory = await getPromptIfCustom("default_memory");
|
|
4745
4104
|
if (customMemory) {
|
|
4746
|
-
writeFileSync7(
|
|
4105
|
+
writeFileSync7(resolve10(dest, "home/MEMORY.md"), customMemory);
|
|
4747
4106
|
}
|
|
4748
4107
|
}
|
|
4749
4108
|
publishPublicKey(name, publicKeyPem).catch(
|
|
@@ -4772,7 +4131,7 @@ The human who planted you described you as: "${body.description}"
|
|
|
4772
4131
|
...skillWarnings.length > 0 && { skillWarnings }
|
|
4773
4132
|
});
|
|
4774
4133
|
} catch (err) {
|
|
4775
|
-
if (
|
|
4134
|
+
if (existsSync7(dest)) rmSync4(dest, { recursive: true, force: true });
|
|
4776
4135
|
try {
|
|
4777
4136
|
await removeMind(name);
|
|
4778
4137
|
} catch {
|
|
@@ -4792,13 +4151,13 @@ The human who planted you described you as: "${body.description}"
|
|
|
4792
4151
|
return importFromArchive(c, body.archivePath, body.name, body.manifest);
|
|
4793
4152
|
}
|
|
4794
4153
|
const wsDir = body.workspacePath;
|
|
4795
|
-
if (!wsDir || !
|
|
4154
|
+
if (!wsDir || !existsSync7(resolve10(wsDir, "SOUL.md")) || !existsSync7(resolve10(wsDir, "IDENTITY.md"))) {
|
|
4796
4155
|
return c.json({ error: "Invalid workspace: missing SOUL.md or IDENTITY.md" }, 400);
|
|
4797
4156
|
}
|
|
4798
|
-
const soul =
|
|
4799
|
-
const identity =
|
|
4800
|
-
const userPath =
|
|
4801
|
-
const user =
|
|
4157
|
+
const soul = readFileSync8(resolve10(wsDir, "SOUL.md"), "utf-8");
|
|
4158
|
+
const identity = readFileSync8(resolve10(wsDir, "IDENTITY.md"), "utf-8");
|
|
4159
|
+
const userPath = resolve10(wsDir, "USER.md");
|
|
4160
|
+
const user = existsSync7(userPath) ? readFileSync8(userPath, "utf-8") : "";
|
|
4802
4161
|
const name = body.name ?? parseNameFromIdentity(identity) ?? "imported-mind";
|
|
4803
4162
|
const template = body.template ?? "claude";
|
|
4804
4163
|
const nameErr = validateMindName(name);
|
|
@@ -4818,33 +4177,33 @@ ${user.trimEnd()}
|
|
|
4818
4177
|
` : "";
|
|
4819
4178
|
ensureVoluteHome();
|
|
4820
4179
|
const dest = mindDir(name);
|
|
4821
|
-
if (
|
|
4180
|
+
if (existsSync7(dest)) return c.json({ error: "Mind directory already exists" }, 409);
|
|
4822
4181
|
const templatesRoot = findTemplatesRoot();
|
|
4823
4182
|
const { composedDir, manifest } = composeTemplate(templatesRoot, template);
|
|
4824
4183
|
try {
|
|
4825
4184
|
copyTemplateToDir(composedDir, dest, name, manifest);
|
|
4826
4185
|
applyInitFiles(dest);
|
|
4827
4186
|
const { publicKeyPem: importPublicKey } = generateIdentity(dest);
|
|
4828
|
-
writeFileSync7(
|
|
4829
|
-
const wsMemoryPath =
|
|
4830
|
-
const hasMemory =
|
|
4187
|
+
writeFileSync7(resolve10(dest, "home/SOUL.md"), mergedSoul);
|
|
4188
|
+
const wsMemoryPath = resolve10(wsDir, "MEMORY.md");
|
|
4189
|
+
const hasMemory = existsSync7(wsMemoryPath);
|
|
4831
4190
|
if (hasMemory) {
|
|
4832
|
-
const existingMemory =
|
|
4191
|
+
const existingMemory = readFileSync8(wsMemoryPath, "utf-8");
|
|
4833
4192
|
writeFileSync7(
|
|
4834
|
-
|
|
4193
|
+
resolve10(dest, "home/MEMORY.md"),
|
|
4835
4194
|
`${existingMemory.trimEnd()}${mergedMemoryExtra}`
|
|
4836
4195
|
);
|
|
4837
4196
|
} else if (user) {
|
|
4838
|
-
writeFileSync7(
|
|
4197
|
+
writeFileSync7(resolve10(dest, "home/MEMORY.md"), `${user.trimEnd()}
|
|
4839
4198
|
`);
|
|
4840
4199
|
}
|
|
4841
|
-
const wsMemoryDir =
|
|
4200
|
+
const wsMemoryDir = resolve10(wsDir, "memory");
|
|
4842
4201
|
let dailyLogCount = 0;
|
|
4843
|
-
if (
|
|
4844
|
-
const destMemoryDir =
|
|
4202
|
+
if (existsSync7(wsMemoryDir)) {
|
|
4203
|
+
const destMemoryDir = resolve10(dest, "home/memory");
|
|
4845
4204
|
const files = readdirSync2(wsMemoryDir).filter((f) => f.endsWith(".md"));
|
|
4846
4205
|
for (const file of files) {
|
|
4847
|
-
cpSync(
|
|
4206
|
+
cpSync(resolve10(wsMemoryDir, file), resolve10(destMemoryDir, file));
|
|
4848
4207
|
}
|
|
4849
4208
|
dailyLogCount = files.length;
|
|
4850
4209
|
}
|
|
@@ -4855,7 +4214,7 @@ ${user.trimEnd()}
|
|
|
4855
4214
|
} catch (err) {
|
|
4856
4215
|
logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
|
|
4857
4216
|
}
|
|
4858
|
-
const homeDir =
|
|
4217
|
+
const homeDir = resolve10(dest, "home");
|
|
4859
4218
|
ensureVoluteGroup();
|
|
4860
4219
|
createMindUser(name, homeDir);
|
|
4861
4220
|
chownMindDir(dest, name);
|
|
@@ -4863,20 +4222,20 @@ ${user.trimEnd()}
|
|
|
4863
4222
|
if (!hasMemory && dailyLogCount > 0) {
|
|
4864
4223
|
await consolidateMemory(dest);
|
|
4865
4224
|
}
|
|
4866
|
-
const env = isIsolationEnabled() ? { ...process.env, HOME:
|
|
4225
|
+
const env = isIsolationEnabled() ? { ...process.env, HOME: resolve10(dest, "home") } : void 0;
|
|
4867
4226
|
await gitExec(["init"], { cwd: dest, mindName: name, env });
|
|
4868
4227
|
await configureGitIdentity(name, { cwd: dest, mindName: name, env });
|
|
4869
4228
|
await gitExec(["add", "-A"], { cwd: dest, mindName: name, env });
|
|
4870
4229
|
await gitExec(["commit", "-m", "import from OpenClaw"], { cwd: dest, mindName: name, env });
|
|
4871
|
-
const sessionFile = body.sessionPath ?
|
|
4872
|
-
if (sessionFile &&
|
|
4230
|
+
const sessionFile = body.sessionPath ? resolve10(body.sessionPath) : findOpenClawSession(wsDir);
|
|
4231
|
+
if (sessionFile && existsSync7(sessionFile)) {
|
|
4873
4232
|
if (template === "pi") {
|
|
4874
4233
|
importPiSession(sessionFile, dest);
|
|
4875
4234
|
} else if (template === "claude") {
|
|
4876
4235
|
const sessionId = convertSession({ sessionPath: sessionFile, projectDir: dest });
|
|
4877
|
-
const mindRuntimeDir =
|
|
4236
|
+
const mindRuntimeDir = resolve10(dest, ".mind");
|
|
4878
4237
|
mkdirSync6(mindRuntimeDir, { recursive: true });
|
|
4879
|
-
writeFileSync7(
|
|
4238
|
+
writeFileSync7(resolve10(mindRuntimeDir, "session.json"), JSON.stringify({ sessionId }));
|
|
4880
4239
|
}
|
|
4881
4240
|
}
|
|
4882
4241
|
importOpenClawConnectors(name, dest);
|
|
@@ -4886,7 +4245,7 @@ ${user.trimEnd()}
|
|
|
4886
4245
|
);
|
|
4887
4246
|
return c.json({ ok: true, name, port, message: `Imported mind: ${name} (port ${port})` });
|
|
4888
4247
|
} catch (err) {
|
|
4889
|
-
if (
|
|
4248
|
+
if (existsSync7(dest)) rmSync4(dest, { recursive: true, force: true });
|
|
4890
4249
|
try {
|
|
4891
4250
|
await removeMind(name);
|
|
4892
4251
|
} catch {
|
|
@@ -4917,7 +4276,7 @@ ${user.trimEnd()}
|
|
|
4917
4276
|
const minds = await Promise.all(
|
|
4918
4277
|
entries.map(async (entry) => {
|
|
4919
4278
|
const mindStatus = await getMindStatus(entry.name, entry.port, entry.running);
|
|
4920
|
-
const hasPages =
|
|
4279
|
+
const hasPages = existsSync7(resolve10(mindDir(entry.name), "home", "pages"));
|
|
4921
4280
|
return {
|
|
4922
4281
|
...entry,
|
|
4923
4282
|
...mindStatus,
|
|
@@ -4932,7 +4291,7 @@ ${user.trimEnd()}
|
|
|
4932
4291
|
const entry = await findMind(name);
|
|
4933
4292
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
4934
4293
|
const dir = entry.dir ?? mindDir(entry.parent ?? name);
|
|
4935
|
-
if (!
|
|
4294
|
+
if (!existsSync7(dir)) return c.json({ error: "Mind directory missing" }, 404);
|
|
4936
4295
|
const mindStatus = await getMindStatus(name, entry.port);
|
|
4937
4296
|
const variants = await findVariants(name);
|
|
4938
4297
|
const manager = getMindManager();
|
|
@@ -4946,7 +4305,7 @@ ${user.trimEnd()}
|
|
|
4946
4305
|
return { name: s.name, port: s.port, status: variantStatus };
|
|
4947
4306
|
})
|
|
4948
4307
|
);
|
|
4949
|
-
const hasPages =
|
|
4308
|
+
const hasPages = existsSync7(resolve10(mindDir(name), "home", "pages"));
|
|
4950
4309
|
return c.json({ ...entry, ...mindStatus, variants: variantStatuses, hasPages });
|
|
4951
4310
|
}).get("/:name/context", async (c) => {
|
|
4952
4311
|
const name = c.req.param("name");
|
|
@@ -4983,7 +4342,7 @@ ${user.trimEnd()}
|
|
|
4983
4342
|
if (!entry.dir) return c.json({ error: `Variant ${name} has no directory` }, 404);
|
|
4984
4343
|
} else {
|
|
4985
4344
|
const dir = mindDir(name);
|
|
4986
|
-
if (!
|
|
4345
|
+
if (!existsSync7(dir)) return c.json({ error: "Mind directory missing" }, 404);
|
|
4987
4346
|
}
|
|
4988
4347
|
if (getMindManager().isRunning(name)) {
|
|
4989
4348
|
return c.json({ error: "Mind already running" }, 409);
|
|
@@ -5004,7 +4363,7 @@ ${user.trimEnd()}
|
|
|
5004
4363
|
if (!entry.dir) return c.json({ error: `Variant ${name} has no directory` }, 404);
|
|
5005
4364
|
} else {
|
|
5006
4365
|
const dir = mindDir(name);
|
|
5007
|
-
if (!
|
|
4366
|
+
if (!existsSync7(dir)) return c.json({ error: "Mind directory missing" }, 404);
|
|
5008
4367
|
}
|
|
5009
4368
|
let context;
|
|
5010
4369
|
const contentType = c.req.header("content-type");
|
|
@@ -5019,7 +4378,7 @@ ${user.trimEnd()}
|
|
|
5019
4378
|
const manager = getMindManager();
|
|
5020
4379
|
try {
|
|
5021
4380
|
if (context?.type === "reload") {
|
|
5022
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4381
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-PBOIEBJZ.js");
|
|
5023
4382
|
const sleepState = getSleepManagerIfReady2()?.getState(name);
|
|
5024
4383
|
if (sleepState?.sleeping) {
|
|
5025
4384
|
logger_default.info(`skipping reload for ${name} during sleep \u2014 will apply on next wake`);
|
|
@@ -5039,7 +4398,7 @@ ${user.trimEnd()}
|
|
|
5039
4398
|
const variantEntry = await findMind(mergeVariantName);
|
|
5040
4399
|
if (variantEntry && variantEntry.parent === baseName && variantEntry.dir && variantEntry.branch) {
|
|
5041
4400
|
const projectRoot = mindDir(baseName);
|
|
5042
|
-
if (
|
|
4401
|
+
if (existsSync7(variantEntry.dir)) {
|
|
5043
4402
|
const status = (await gitExec(["status", "--porcelain"], { cwd: variantEntry.dir })).trim();
|
|
5044
4403
|
if (status) {
|
|
5045
4404
|
try {
|
|
@@ -5114,7 +4473,7 @@ ${user.trimEnd()}
|
|
|
5114
4473
|
const name = c.req.param("name");
|
|
5115
4474
|
const entry = await findMind(name);
|
|
5116
4475
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
5117
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4476
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-PBOIEBJZ.js");
|
|
5118
4477
|
const sm = getSleepManagerIfReady2();
|
|
5119
4478
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
5120
4479
|
return c.json(sm.getState(name));
|
|
@@ -5122,7 +4481,7 @@ ${user.trimEnd()}
|
|
|
5122
4481
|
const name = c.req.param("name");
|
|
5123
4482
|
const entry = await findMind(name);
|
|
5124
4483
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
5125
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4484
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-PBOIEBJZ.js");
|
|
5126
4485
|
const sm = getSleepManagerIfReady2();
|
|
5127
4486
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
5128
4487
|
if (sm.isSleeping(name)) return c.json({ error: "Mind is already sleeping" }, 409);
|
|
@@ -5142,7 +4501,7 @@ ${user.trimEnd()}
|
|
|
5142
4501
|
const name = c.req.param("name");
|
|
5143
4502
|
const entry = await findMind(name);
|
|
5144
4503
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
5145
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4504
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-PBOIEBJZ.js");
|
|
5146
4505
|
const sm = getSleepManagerIfReady2();
|
|
5147
4506
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
5148
4507
|
const sleepState = sm.getState(name);
|
|
@@ -5157,7 +4516,7 @@ ${user.trimEnd()}
|
|
|
5157
4516
|
const name = c.req.param("name");
|
|
5158
4517
|
const entry = await findMind(name);
|
|
5159
4518
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
5160
|
-
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-
|
|
4519
|
+
const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-PBOIEBJZ.js");
|
|
5161
4520
|
const sm = getSleepManagerIfReady2();
|
|
5162
4521
|
if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
|
|
5163
4522
|
const flushed = await sm.flushQueuedMessages(name);
|
|
@@ -5175,7 +4534,7 @@ ${user.trimEnd()}
|
|
|
5175
4534
|
if (body.avatar !== void 0) profile.avatar = body.avatar;
|
|
5176
4535
|
config2.profile = profile;
|
|
5177
4536
|
writeVoluteConfig(dir, config2);
|
|
5178
|
-
const { syncMindProfile: syncMindProfile2 } = await import("./auth-
|
|
4537
|
+
const { syncMindProfile: syncMindProfile2 } = await import("./auth-2QOOPMBX.js");
|
|
5179
4538
|
await syncMindProfile2(name, profile);
|
|
5180
4539
|
broadcast({ type: "profile_updated", mind: name, summary: `${name} profile updated` });
|
|
5181
4540
|
return c.json({ ok: true });
|
|
@@ -5215,14 +4574,14 @@ ${user.trimEnd()}
|
|
|
5215
4574
|
return c.json({ output: "" });
|
|
5216
4575
|
}
|
|
5217
4576
|
const dir = entry.dir ?? mindDir(name);
|
|
5218
|
-
const soulPath =
|
|
5219
|
-
const memoryPath =
|
|
5220
|
-
const soulCustom =
|
|
5221
|
-
const memoryWritten =
|
|
4577
|
+
const soulPath = resolve10(dir, "home/SOUL.md");
|
|
4578
|
+
const memoryPath = resolve10(dir, "home/MEMORY.md");
|
|
4579
|
+
const soulCustom = existsSync7(soulPath) && !readFileSync8(soulPath, "utf-8").includes(ORIENTATION_MARKER);
|
|
4580
|
+
const memoryWritten = existsSync7(memoryPath) && readFileSync8(memoryPath, "utf-8").trim().length > 0;
|
|
5222
4581
|
const config2 = readVoluteConfig(dir);
|
|
5223
4582
|
const displayNameSet = !!config2?.profile?.displayName;
|
|
5224
4583
|
const avatarSet = !!config2?.profile?.avatar;
|
|
5225
|
-
const { isImagegenEnabled } = await import("./setup-
|
|
4584
|
+
const { isImagegenEnabled } = await import("./setup-PF7JSFMO.js");
|
|
5226
4585
|
const imagegenEnabled = isImagegenEnabled();
|
|
5227
4586
|
const done = [];
|
|
5228
4587
|
const remaining = [];
|
|
@@ -5260,7 +4619,7 @@ ${user.trimEnd()}
|
|
|
5260
4619
|
try {
|
|
5261
4620
|
const spiritEntry = await findMind("volute");
|
|
5262
4621
|
if (spiritEntry) {
|
|
5263
|
-
const { spiritDir } = await import("./spirit-
|
|
4622
|
+
const { spiritDir } = await import("./spirit-4QOYM33G.js");
|
|
5264
4623
|
const sDir = spiritEntry.dir ?? spiritDir();
|
|
5265
4624
|
const spiritConfig = readVoluteConfig(sDir);
|
|
5266
4625
|
if (spiritConfig?.schedules) {
|
|
@@ -5268,7 +4627,7 @@ ${user.trimEnd()}
|
|
|
5268
4627
|
spiritConfig.schedules = spiritConfig.schedules.filter((s) => s.id !== nurtureId);
|
|
5269
4628
|
if (spiritConfig.schedules.length === 0) spiritConfig.schedules = void 0;
|
|
5270
4629
|
writeVoluteConfig(sDir, spiritConfig);
|
|
5271
|
-
const { getScheduler: getScheduler2 } = await import("./scheduler-
|
|
4630
|
+
const { getScheduler: getScheduler2 } = await import("./scheduler-355E746X.js");
|
|
5272
4631
|
getScheduler2().loadSchedules("volute", sDir);
|
|
5273
4632
|
}
|
|
5274
4633
|
}
|
|
@@ -5296,10 +4655,10 @@ ${user.trimEnd()}
|
|
|
5296
4655
|
await deleteMindUser2(name);
|
|
5297
4656
|
invalidateMindUserCache(name);
|
|
5298
4657
|
const state = stateDir(name);
|
|
5299
|
-
if (
|
|
4658
|
+
if (existsSync7(state)) {
|
|
5300
4659
|
rmSync4(state, { recursive: true, force: true });
|
|
5301
4660
|
}
|
|
5302
|
-
if (force &&
|
|
4661
|
+
if (force && existsSync7(dir)) {
|
|
5303
4662
|
rmSync4(dir, { recursive: true, force: true });
|
|
5304
4663
|
deleteMindUser(name);
|
|
5305
4664
|
}
|
|
@@ -5314,7 +4673,7 @@ ${user.trimEnd()}
|
|
|
5314
4673
|
const entry = await findMind(mindName);
|
|
5315
4674
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
5316
4675
|
const dir = mindDir(mindName);
|
|
5317
|
-
if (!
|
|
4676
|
+
if (!existsSync7(dir)) return c.json({ error: "Mind directory missing" }, 404);
|
|
5318
4677
|
let body = {};
|
|
5319
4678
|
try {
|
|
5320
4679
|
body = await c.req.json();
|
|
@@ -5323,16 +4682,16 @@ ${user.trimEnd()}
|
|
|
5323
4682
|
const template = body.template ?? entry.template ?? "claude";
|
|
5324
4683
|
const UPGRADE_BRANCH = "upgrade";
|
|
5325
4684
|
const upgradeVariantName = `${mindName}-upgrade`;
|
|
5326
|
-
const worktreeDir =
|
|
4685
|
+
const worktreeDir = resolve10(dir, ".variants", UPGRADE_BRANCH);
|
|
5327
4686
|
if (body.abort) {
|
|
5328
|
-
if (!
|
|
4687
|
+
if (!existsSync7(worktreeDir)) {
|
|
5329
4688
|
return c.json({ error: "No upgrade in progress" }, 400);
|
|
5330
4689
|
}
|
|
5331
4690
|
try {
|
|
5332
4691
|
try {
|
|
5333
|
-
const gitDirContent =
|
|
4692
|
+
const gitDirContent = readFileSync8(resolve10(worktreeDir, ".git"), "utf-8").trim();
|
|
5334
4693
|
const gitDir = gitDirContent.replace("gitdir: ", "");
|
|
5335
|
-
if (
|
|
4694
|
+
if (existsSync7(resolve10(gitDir, "MERGE_HEAD"))) {
|
|
5336
4695
|
await gitExec(["merge", "--abort"], { cwd: worktreeDir });
|
|
5337
4696
|
}
|
|
5338
4697
|
} catch {
|
|
@@ -5351,7 +4710,7 @@ ${user.trimEnd()}
|
|
|
5351
4710
|
}
|
|
5352
4711
|
}
|
|
5353
4712
|
if (body.continue) {
|
|
5354
|
-
if (!
|
|
4713
|
+
if (!existsSync7(worktreeDir)) {
|
|
5355
4714
|
return c.json({ error: "No upgrade in progress" }, 400);
|
|
5356
4715
|
}
|
|
5357
4716
|
const status = await gitExec(["status", "--porcelain"], { cwd: worktreeDir });
|
|
@@ -5400,7 +4759,7 @@ ${user.trimEnd()}
|
|
|
5400
4759
|
}
|
|
5401
4760
|
}
|
|
5402
4761
|
if (body.accept) {
|
|
5403
|
-
if (
|
|
4762
|
+
if (existsSync7(worktreeDir)) {
|
|
5404
4763
|
try {
|
|
5405
4764
|
await cleanupVariant(upgradeVariantName, dir, worktreeDir, { stop: true });
|
|
5406
4765
|
} catch (err) {
|
|
@@ -5415,7 +4774,7 @@ ${user.trimEnd()}
|
|
|
5415
4774
|
}
|
|
5416
4775
|
if (body.diff) {
|
|
5417
4776
|
try {
|
|
5418
|
-
if (!
|
|
4777
|
+
if (!existsSync7(resolve10(dir, ".git"))) {
|
|
5419
4778
|
return c.json({ error: "Mind has no git history \u2014 nothing to diff against" }, 400);
|
|
5420
4779
|
}
|
|
5421
4780
|
await updateTemplateBranch(dir, template, mindName);
|
|
@@ -5433,22 +4792,22 @@ ${user.trimEnd()}
|
|
|
5433
4792
|
);
|
|
5434
4793
|
}
|
|
5435
4794
|
}
|
|
5436
|
-
if (
|
|
4795
|
+
if (existsSync7(worktreeDir)) {
|
|
5437
4796
|
return c.json(
|
|
5438
4797
|
{ error: "Upgrade variant already exists. Use continue or delete it first." },
|
|
5439
4798
|
409
|
|
5440
4799
|
);
|
|
5441
4800
|
}
|
|
5442
|
-
if (!
|
|
4801
|
+
if (!existsSync7(resolve10(dir, ".git"))) {
|
|
5443
4802
|
try {
|
|
5444
|
-
const env = isIsolationEnabled() ? { ...process.env, HOME:
|
|
4803
|
+
const env = isIsolationEnabled() ? { ...process.env, HOME: resolve10(dir, "home") } : void 0;
|
|
5445
4804
|
await gitExec(["init"], { cwd: dir, mindName, env });
|
|
5446
4805
|
await configureGitIdentity(mindName, { cwd: dir, mindName, env });
|
|
5447
4806
|
await gitExec(["add", "-A"], { cwd: dir, mindName, env });
|
|
5448
4807
|
await gitExec(["commit", "-m", "initial commit"], { cwd: dir, mindName, env });
|
|
5449
4808
|
chownMindDir(dir, mindName);
|
|
5450
4809
|
} catch (err) {
|
|
5451
|
-
rmSync4(
|
|
4810
|
+
rmSync4(resolve10(dir, ".git"), { recursive: true, force: true });
|
|
5452
4811
|
return c.json(
|
|
5453
4812
|
{
|
|
5454
4813
|
error: `Git initialization failed: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -5463,8 +4822,8 @@ ${user.trimEnd()}
|
|
|
5463
4822
|
} catch {
|
|
5464
4823
|
}
|
|
5465
4824
|
await updateTemplateBranch(dir, template, mindName);
|
|
5466
|
-
const parentDir =
|
|
5467
|
-
if (!
|
|
4825
|
+
const parentDir = resolve10(dir, ".variants");
|
|
4826
|
+
if (!existsSync7(parentDir)) {
|
|
5468
4827
|
mkdirSync6(parentDir, { recursive: true });
|
|
5469
4828
|
}
|
|
5470
4829
|
await gitExec(["worktree", "add", "-b", UPGRADE_BRANCH, worktreeDir], { cwd: dir });
|
|
@@ -5593,22 +4952,22 @@ ${user.trimEnd()}
|
|
|
5593
4952
|
const entry = await findMind(name);
|
|
5594
4953
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
5595
4954
|
const dir = entry.dir ?? mindDir(name);
|
|
5596
|
-
if (!
|
|
4955
|
+
if (!existsSync7(dir)) return c.json({ error: "Mind directory missing" }, 404);
|
|
5597
4956
|
let config2 = readVoluteConfig(dir);
|
|
5598
4957
|
if (!config2 && entry.template === "pi") {
|
|
5599
|
-
const piConfigPath =
|
|
5600
|
-
if (
|
|
4958
|
+
const piConfigPath = resolve10(dir, "home/.config/config.json");
|
|
4959
|
+
if (existsSync7(piConfigPath)) {
|
|
5601
4960
|
try {
|
|
5602
|
-
config2 = JSON.parse(
|
|
4961
|
+
config2 = JSON.parse(readFileSync8(piConfigPath, "utf-8"));
|
|
5603
4962
|
} catch {
|
|
5604
4963
|
}
|
|
5605
4964
|
}
|
|
5606
4965
|
}
|
|
5607
4966
|
let templateConfig = {};
|
|
5608
|
-
const configJsonPath =
|
|
5609
|
-
if (
|
|
4967
|
+
const configJsonPath = resolve10(dir, "home/.config/config.json");
|
|
4968
|
+
if (existsSync7(configJsonPath)) {
|
|
5610
4969
|
try {
|
|
5611
|
-
templateConfig = JSON.parse(
|
|
4970
|
+
templateConfig = JSON.parse(readFileSync8(configJsonPath, "utf-8"));
|
|
5612
4971
|
} catch {
|
|
5613
4972
|
}
|
|
5614
4973
|
}
|
|
@@ -5662,7 +5021,7 @@ ${user.trimEnd()}
|
|
|
5662
5021
|
const entry = await findMind(name);
|
|
5663
5022
|
if (!entry) return c.json({ error: "Mind not found" }, 404);
|
|
5664
5023
|
const dir = entry.dir ?? mindDir(name);
|
|
5665
|
-
if (!
|
|
5024
|
+
if (!existsSync7(dir)) return c.json({ error: "Mind directory missing" }, 404);
|
|
5666
5025
|
const body = c.req.valid("json");
|
|
5667
5026
|
const existing = readVoluteConfig(dir) ?? {};
|
|
5668
5027
|
if (body.model !== void 0) existing.model = body.model;
|
|
@@ -5693,11 +5052,11 @@ ${user.trimEnd()}
|
|
|
5693
5052
|
writeVoluteConfig(dir, existing);
|
|
5694
5053
|
const needsConfigJson = body.model !== void 0 || body.thinkingLevel !== void 0 || body.maxThinkingTokens !== void 0 || body.compaction !== void 0;
|
|
5695
5054
|
if (needsConfigJson) {
|
|
5696
|
-
const configJsonPath =
|
|
5055
|
+
const configJsonPath = resolve10(dir, "home/.config/config.json");
|
|
5697
5056
|
let templateConfig = {};
|
|
5698
|
-
if (
|
|
5057
|
+
if (existsSync7(configJsonPath)) {
|
|
5699
5058
|
try {
|
|
5700
|
-
templateConfig = JSON.parse(
|
|
5059
|
+
templateConfig = JSON.parse(readFileSync8(configJsonPath, "utf-8"));
|
|
5701
5060
|
} catch {
|
|
5702
5061
|
}
|
|
5703
5062
|
}
|
|
@@ -5765,7 +5124,7 @@ ${user.trimEnd()}
|
|
|
5765
5124
|
}
|
|
5766
5125
|
if (entry.mindType === "spirit" && body.model !== void 0) {
|
|
5767
5126
|
try {
|
|
5768
|
-
const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-
|
|
5127
|
+
const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-PF7JSFMO.js");
|
|
5769
5128
|
const globalConfig = readGlobalConfig2();
|
|
5770
5129
|
globalConfig.spiritModel = body.model;
|
|
5771
5130
|
writeGlobalConfig2(globalConfig);
|
|
@@ -5793,7 +5152,7 @@ ${user.trimEnd()}
|
|
|
5793
5152
|
if (!body.systemPrompt || !body.message) {
|
|
5794
5153
|
return c.json({ error: "systemPrompt and message required" }, 400);
|
|
5795
5154
|
}
|
|
5796
|
-
const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-
|
|
5155
|
+
const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-C2YNARGH.js");
|
|
5797
5156
|
if (!isAiConfigured()) {
|
|
5798
5157
|
return c.json({ error: "AI service not configured" }, 503);
|
|
5799
5158
|
}
|
|
@@ -5883,6 +5242,17 @@ ${user.trimEnd()}
|
|
|
5883
5242
|
metadata: body.metadata,
|
|
5884
5243
|
turnId: turnId ?? void 0
|
|
5885
5244
|
});
|
|
5245
|
+
if (body.type === "text" && body.channel && cleanContent) {
|
|
5246
|
+
echoTextToChannel(
|
|
5247
|
+
baseName,
|
|
5248
|
+
body.channel,
|
|
5249
|
+
cleanContent,
|
|
5250
|
+
turnId ?? void 0,
|
|
5251
|
+
insertedId
|
|
5252
|
+
).catch(
|
|
5253
|
+
(err) => logger_default.error(`echo-text failed for ${baseName} on ${body.channel}`, logger_default.errorData(err))
|
|
5254
|
+
);
|
|
5255
|
+
}
|
|
5886
5256
|
onMindEvent(baseName, body.type, body.channel);
|
|
5887
5257
|
if ((body.type === "text" || body.type === "outbound") && body.channel) {
|
|
5888
5258
|
const map = getTypingMap();
|
|
@@ -5951,7 +5321,7 @@ ${user.trimEnd()}
|
|
|
5951
5321
|
const stream = new ReadableStream({
|
|
5952
5322
|
start(controller) {
|
|
5953
5323
|
const encoder = new TextEncoder();
|
|
5954
|
-
const
|
|
5324
|
+
const send = (data) => {
|
|
5955
5325
|
controller.enqueue(encoder.encode(`data: ${data}
|
|
5956
5326
|
|
|
5957
5327
|
`));
|
|
@@ -5970,7 +5340,7 @@ ${user.trimEnd()}
|
|
|
5970
5340
|
if (sessionFilter && event.session !== sessionFilter) return;
|
|
5971
5341
|
if (channelFilter && event.channel !== channelFilter) return;
|
|
5972
5342
|
try {
|
|
5973
|
-
|
|
5343
|
+
send(JSON.stringify(event));
|
|
5974
5344
|
} catch {
|
|
5975
5345
|
clearInterval(pingInterval);
|
|
5976
5346
|
unsubscribe?.();
|
|
@@ -6492,7 +5862,7 @@ var app15 = new Hono17().get("/:name/clock/status", async (c) => {
|
|
|
6492
5862
|
const body = await c.req.text();
|
|
6493
5863
|
const message = `[webhook: ${event}] ${body}`;
|
|
6494
5864
|
try {
|
|
6495
|
-
const { sendSystemMessage } = await import("./system-chat-
|
|
5865
|
+
const { sendSystemMessage } = await import("./system-chat-7AIN3U5M.js");
|
|
6496
5866
|
await sendSystemMessage(name, message);
|
|
6497
5867
|
return c.json({ ok: true });
|
|
6498
5868
|
} catch (err) {
|
|
@@ -6505,14 +5875,14 @@ var schedules_default = app15;
|
|
|
6505
5875
|
// packages/daemon/src/web/api/setup.ts
|
|
6506
5876
|
import { mkdirSync as mkdirSync7 } from "fs";
|
|
6507
5877
|
import { homedir as homedir2 } from "os";
|
|
6508
|
-
import { resolve as
|
|
5878
|
+
import { resolve as resolve11 } from "path";
|
|
6509
5879
|
import { Hono as Hono18 } from "hono";
|
|
6510
5880
|
import { setCookie as setCookie2 } from "hono/cookie";
|
|
6511
5881
|
var DEFAULT_API_URL2 = "https://volute.systems";
|
|
6512
5882
|
var setup = new Hono18();
|
|
6513
5883
|
function writeSetupConfig(systemName, description) {
|
|
6514
|
-
const configHome = process.env.VOLUTE_HOME ??
|
|
6515
|
-
const mindsDir =
|
|
5884
|
+
const configHome = process.env.VOLUTE_HOME ?? resolve11(homedir2(), ".volute");
|
|
5885
|
+
const mindsDir = resolve11(configHome, "minds");
|
|
6516
5886
|
mkdirSync7(configHome, { recursive: true });
|
|
6517
5887
|
mkdirSync7(mindsDir, { recursive: true });
|
|
6518
5888
|
const existingConfig = readGlobalConfig();
|
|
@@ -6526,7 +5896,8 @@ function writeSetupConfig(systemName, description) {
|
|
|
6526
5896
|
...existingConfig,
|
|
6527
5897
|
name: systemName,
|
|
6528
5898
|
description: description || existingConfig.description,
|
|
6529
|
-
setup: setupConfig
|
|
5899
|
+
setup: setupConfig,
|
|
5900
|
+
setupCompleted: false
|
|
6530
5901
|
};
|
|
6531
5902
|
writeGlobalConfig(config2);
|
|
6532
5903
|
return config2;
|
|
@@ -6545,7 +5916,7 @@ setup.get("/status", async (c) => {
|
|
|
6545
5916
|
let hasAccount = false;
|
|
6546
5917
|
if (hasSystem) {
|
|
6547
5918
|
try {
|
|
6548
|
-
const { listUsersByType: listUsersByType2 } = await import("./auth-
|
|
5919
|
+
const { listUsersByType: listUsersByType2 } = await import("./auth-2QOOPMBX.js");
|
|
6549
5920
|
const brains = await listUsersByType2("brain");
|
|
6550
5921
|
hasAccount = brains.length > 0;
|
|
6551
5922
|
} catch (err) {
|
|
@@ -6734,7 +6105,7 @@ setup.post("/account", async (c) => {
|
|
|
6734
6105
|
}
|
|
6735
6106
|
}
|
|
6736
6107
|
try {
|
|
6737
|
-
const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-
|
|
6108
|
+
const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-2QOOPMBX.js");
|
|
6738
6109
|
const user = await createUser2(body.username.trim(), body.password);
|
|
6739
6110
|
if (body.displayName?.trim()) {
|
|
6740
6111
|
await updateUserProfile2(user.id, { display_name: body.displayName.trim() });
|
|
@@ -6780,7 +6151,7 @@ setup.post("/models", async (c) => {
|
|
|
6780
6151
|
return c.json({ error: "Spirit model is required" }, 400);
|
|
6781
6152
|
}
|
|
6782
6153
|
try {
|
|
6783
|
-
const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-
|
|
6154
|
+
const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-C2YNARGH.js");
|
|
6784
6155
|
setEnabledModels3(body.models);
|
|
6785
6156
|
const config2 = readGlobalConfig();
|
|
6786
6157
|
config2.spiritModel = body.spiritModel.trim();
|
|
@@ -6798,8 +6169,8 @@ setup.post("/complete", async (c) => {
|
|
|
6798
6169
|
return c.json({ error: "Setup already complete" }, 400);
|
|
6799
6170
|
}
|
|
6800
6171
|
try {
|
|
6801
|
-
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-
|
|
6802
|
-
const { startSpiritFull } = await import("./mind-service-
|
|
6172
|
+
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-4QOYM33G.js");
|
|
6173
|
+
const { startSpiritFull } = await import("./mind-service-WRTOQSAL.js");
|
|
6803
6174
|
await ensureSpiritProject();
|
|
6804
6175
|
await syncSpiritTemplate();
|
|
6805
6176
|
const warnings = [];
|
|
@@ -6815,8 +6186,8 @@ setup.post("/complete", async (c) => {
|
|
|
6815
6186
|
}
|
|
6816
6187
|
let spiritConversationId;
|
|
6817
6188
|
try {
|
|
6818
|
-
const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-
|
|
6819
|
-
const { createConversation:
|
|
6189
|
+
const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-2QOOPMBX.js");
|
|
6190
|
+
const { createConversation: createConversation2, findDMConversation: findDMConversation2 } = await import("./conversations-G6YRSABR.js");
|
|
6820
6191
|
const spiritUser = await getOrCreateMindUser2("volute");
|
|
6821
6192
|
const brains = await listUsersByType2("brain");
|
|
6822
6193
|
const admin2 = brains.find((u) => u.role === "admin");
|
|
@@ -6825,7 +6196,7 @@ setup.post("/complete", async (c) => {
|
|
|
6825
6196
|
if (existing) {
|
|
6826
6197
|
spiritConversationId = existing;
|
|
6827
6198
|
} else {
|
|
6828
|
-
const conv = await
|
|
6199
|
+
const conv = await createConversation2({
|
|
6829
6200
|
participantIds: [admin2.id, spiritUser.id]
|
|
6830
6201
|
});
|
|
6831
6202
|
spiritConversationId = conv.id;
|
|
@@ -6838,9 +6209,9 @@ setup.post("/complete", async (c) => {
|
|
|
6838
6209
|
logger_default.info("setup complete state", { spiritConversationId, spiritStarted });
|
|
6839
6210
|
if (spiritConversationId && spiritStarted) {
|
|
6840
6211
|
try {
|
|
6841
|
-
const { deliverMessage: deliverMessage2 } = await import("./message-delivery-
|
|
6842
|
-
const { listUsersByType:
|
|
6843
|
-
const admins = await
|
|
6212
|
+
const { deliverMessage: deliverMessage2 } = await import("./message-delivery-NWL7XEIX.js");
|
|
6213
|
+
const { listUsersByType: listUsers2 } = await import("./auth-2QOOPMBX.js");
|
|
6214
|
+
const admins = await listUsers2("brain");
|
|
6844
6215
|
const admin2 = admins.find((u) => u.role === "admin");
|
|
6845
6216
|
const adminName = admin2?.display_name || admin2?.username || "the admin";
|
|
6846
6217
|
const welcomePrompt = `Setup is complete. ${adminName} just finished setting up this system and is now in your chat. Welcome them and help them create their first mind. Keep it brief \u2014 a short greeting, then ask what kind of being they'd like to bring into the world. Remember: minds are beings with their own experience, not tools \u2014 ask about personality and character, never about tasks or utility.`;
|
|
@@ -6876,9 +6247,9 @@ setup.post("/complete", async (c) => {
|
|
|
6876
6247
|
var setup_default = setup;
|
|
6877
6248
|
|
|
6878
6249
|
// packages/daemon/src/web/api/skills.ts
|
|
6879
|
-
import { existsSync as
|
|
6250
|
+
import { existsSync as existsSync8, mkdtempSync, readdirSync as readdirSync3, rmSync as rmSync5 } from "fs";
|
|
6880
6251
|
import { tmpdir } from "os";
|
|
6881
|
-
import { join, resolve as
|
|
6252
|
+
import { join, resolve as resolve12 } from "path";
|
|
6882
6253
|
import AdmZip from "adm-zip";
|
|
6883
6254
|
import { Hono as Hono19 } from "hono";
|
|
6884
6255
|
var app16 = new Hono19().get("/", async (c) => {
|
|
@@ -6954,19 +6325,19 @@ var app16 = new Hono19().get("/", async (c) => {
|
|
|
6954
6325
|
try {
|
|
6955
6326
|
const zip = new AdmZip(buffer2);
|
|
6956
6327
|
for (const entry of zip.getEntries()) {
|
|
6957
|
-
const target =
|
|
6328
|
+
const target = resolve12(tmpDir, entry.entryName);
|
|
6958
6329
|
if (!target.startsWith(tmpDir)) {
|
|
6959
6330
|
return c.json({ error: "Invalid zip: paths must not escape archive" }, 400);
|
|
6960
6331
|
}
|
|
6961
6332
|
}
|
|
6962
6333
|
zip.extractAllTo(tmpDir, true);
|
|
6963
6334
|
let skillDir = null;
|
|
6964
|
-
if (
|
|
6335
|
+
if (existsSync8(join(tmpDir, "SKILL.md"))) {
|
|
6965
6336
|
skillDir = tmpDir;
|
|
6966
6337
|
} else {
|
|
6967
6338
|
const entries = readdirSync3(tmpDir, { withFileTypes: true }).filter((e) => e.isDirectory());
|
|
6968
6339
|
for (const entry of entries) {
|
|
6969
|
-
if (
|
|
6340
|
+
if (existsSync8(join(tmpDir, entry.name, "SKILL.md"))) {
|
|
6970
6341
|
skillDir = join(tmpDir, entry.name);
|
|
6971
6342
|
break;
|
|
6972
6343
|
}
|
|
@@ -7296,8 +6667,8 @@ var app20 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
|
|
|
7296
6667
|
});
|
|
7297
6668
|
}, 15e3);
|
|
7298
6669
|
cleanups.push(() => clearInterval(keepAlive));
|
|
7299
|
-
await new Promise((
|
|
7300
|
-
stream.onAbort(() =>
|
|
6670
|
+
await new Promise((resolve17) => {
|
|
6671
|
+
stream.onAbort(() => resolve17());
|
|
7301
6672
|
});
|
|
7302
6673
|
} finally {
|
|
7303
6674
|
for (const cleanup of cleanups) {
|
|
@@ -7312,16 +6683,16 @@ var app20 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
|
|
|
7312
6683
|
var events_default = app20;
|
|
7313
6684
|
|
|
7314
6685
|
// packages/daemon/src/web/api/variants.ts
|
|
7315
|
-
import { existsSync as
|
|
7316
|
-
import { resolve as
|
|
6686
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync9, writeFileSync as writeFileSync8 } from "fs";
|
|
6687
|
+
import { resolve as resolve14 } from "path";
|
|
7317
6688
|
import { Hono as Hono24 } from "hono";
|
|
7318
6689
|
|
|
7319
6690
|
// packages/daemon/src/lib/mind/spawn-server.ts
|
|
7320
6691
|
import { spawn as spawn4 } from "child_process";
|
|
7321
|
-
import { closeSync, mkdirSync as mkdirSync8, openSync, readFileSync as
|
|
7322
|
-
import { resolve as
|
|
6692
|
+
import { closeSync, mkdirSync as mkdirSync8, openSync, readFileSync as readFileSync9 } from "fs";
|
|
6693
|
+
import { resolve as resolve13 } from "path";
|
|
7323
6694
|
function tsxBin(cwd) {
|
|
7324
|
-
return
|
|
6695
|
+
return resolve13(cwd, "node_modules", ".bin", "tsx");
|
|
7325
6696
|
}
|
|
7326
6697
|
function spawnServer(cwd, port, options) {
|
|
7327
6698
|
if (options?.detached) {
|
|
@@ -7334,31 +6705,31 @@ function spawnAttached(cwd, port) {
|
|
|
7334
6705
|
cwd,
|
|
7335
6706
|
stdio: ["ignore", "pipe", "pipe"]
|
|
7336
6707
|
});
|
|
7337
|
-
return new Promise((
|
|
7338
|
-
const timeout = setTimeout(() =>
|
|
6708
|
+
return new Promise((resolve17) => {
|
|
6709
|
+
const timeout = setTimeout(() => resolve17(null), 3e4);
|
|
7339
6710
|
function checkOutput(data) {
|
|
7340
6711
|
const match = data.toString().match(/listening on :(\d+)/);
|
|
7341
6712
|
if (match) {
|
|
7342
6713
|
clearTimeout(timeout);
|
|
7343
|
-
|
|
6714
|
+
resolve17({ child, actualPort: parseInt(match[1], 10) });
|
|
7344
6715
|
}
|
|
7345
6716
|
}
|
|
7346
6717
|
child.stdout?.on("data", checkOutput);
|
|
7347
6718
|
child.stderr?.on("data", checkOutput);
|
|
7348
6719
|
child.on("error", () => {
|
|
7349
6720
|
clearTimeout(timeout);
|
|
7350
|
-
|
|
6721
|
+
resolve17(null);
|
|
7351
6722
|
});
|
|
7352
6723
|
child.on("exit", () => {
|
|
7353
6724
|
clearTimeout(timeout);
|
|
7354
|
-
|
|
6725
|
+
resolve17(null);
|
|
7355
6726
|
});
|
|
7356
6727
|
});
|
|
7357
6728
|
}
|
|
7358
6729
|
function spawnDetached(cwd, port, logDir) {
|
|
7359
|
-
const logsDir = logDir ??
|
|
6730
|
+
const logsDir = logDir ?? resolve13(cwd, ".mind", "logs");
|
|
7360
6731
|
mkdirSync8(logsDir, { recursive: true });
|
|
7361
|
-
const logPath =
|
|
6732
|
+
const logPath = resolve13(logsDir, "mind.log");
|
|
7362
6733
|
const logFd = openSync(logPath, "a");
|
|
7363
6734
|
const child = spawn4(tsxBin(cwd), ["src/server.ts", "--port", String(port)], {
|
|
7364
6735
|
cwd,
|
|
@@ -7378,7 +6749,7 @@ function spawnDetached(cwd, port, logDir) {
|
|
|
7378
6749
|
}
|
|
7379
6750
|
const interval = setInterval(() => {
|
|
7380
6751
|
try {
|
|
7381
|
-
const content =
|
|
6752
|
+
const content = readFileSync9(logPath, "utf-8");
|
|
7382
6753
|
const match = content.match(/listening on :(\d+)/);
|
|
7383
6754
|
if (match) {
|
|
7384
6755
|
finish({ child, actualPort: parseInt(match[1], 10) });
|
|
@@ -7474,11 +6845,11 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7474
6845
|
return c.json({ error: `Name already in use: ${variantName}` }, 409);
|
|
7475
6846
|
}
|
|
7476
6847
|
const projectRoot = mindDir(mindName);
|
|
7477
|
-
const variantDir =
|
|
7478
|
-
if (
|
|
6848
|
+
const variantDir = resolve14(projectRoot, ".variants", variantName);
|
|
6849
|
+
if (existsSync9(variantDir)) {
|
|
7479
6850
|
return c.json({ error: `Variant directory already exists: ${variantDir}` }, 409);
|
|
7480
6851
|
}
|
|
7481
|
-
mkdirSync9(
|
|
6852
|
+
mkdirSync9(resolve14(projectRoot, ".variants"), { recursive: true });
|
|
7482
6853
|
try {
|
|
7483
6854
|
await gitExec(["worktree", "add", "-b", variantName, variantDir], { cwd: projectRoot });
|
|
7484
6855
|
} catch (e) {
|
|
@@ -7491,7 +6862,7 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7491
6862
|
const [cmd, args] = await wrapForIsolation("npm", ["install"], mindName);
|
|
7492
6863
|
await exec(cmd, args, {
|
|
7493
6864
|
cwd: variantDir,
|
|
7494
|
-
env: { ...process.env, HOME:
|
|
6865
|
+
env: { ...process.env, HOME: resolve14(variantDir, "home") }
|
|
7495
6866
|
});
|
|
7496
6867
|
} else {
|
|
7497
6868
|
await exec("npm", ["install"], { cwd: variantDir });
|
|
@@ -7501,7 +6872,7 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7501
6872
|
return c.json({ error: `npm install failed: ${msg}` }, 500);
|
|
7502
6873
|
}
|
|
7503
6874
|
if (body.soul) {
|
|
7504
|
-
writeFileSync8(
|
|
6875
|
+
writeFileSync8(resolve14(variantDir, "home/SOUL.md"), body.soul);
|
|
7505
6876
|
}
|
|
7506
6877
|
const variantPort = body.port ?? await nextPort();
|
|
7507
6878
|
await addVariant(variantName, mindName, variantPort, variantDir, variantName);
|
|
@@ -7536,7 +6907,7 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7536
6907
|
} catch {
|
|
7537
6908
|
}
|
|
7538
6909
|
const projectRoot = mindDir(mindName);
|
|
7539
|
-
if (
|
|
6910
|
+
if (existsSync9(variantEntry.dir)) {
|
|
7540
6911
|
const status = (await gitExec(["status", "--porcelain"], { cwd: variantEntry.dir })).trim();
|
|
7541
6912
|
if (status) {
|
|
7542
6913
|
try {
|
|
@@ -7596,8 +6967,8 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7596
6967
|
await cleanupVariant(variantName, projectRoot, variantEntry.dir);
|
|
7597
6968
|
if (variantName.endsWith("-upgrade") || variantName === "upgrade") {
|
|
7598
6969
|
try {
|
|
7599
|
-
const { computeTemplateHash: computeTemplateHash2 } = await import("./template-hash-
|
|
7600
|
-
const { setMindTemplateHash: setMindTemplateHash2 } = await import("./registry-
|
|
6970
|
+
const { computeTemplateHash: computeTemplateHash2 } = await import("./template-hash-SSIBEEYK.js");
|
|
6971
|
+
const { setMindTemplateHash: setMindTemplateHash2 } = await import("./registry-KMELPC3X.js");
|
|
7601
6972
|
const tmpl = parentEntry.template ?? "claude";
|
|
7602
6973
|
await setMindTemplateHash2(mindName, computeTemplateHash2(tmpl));
|
|
7603
6974
|
} catch (err) {
|
|
@@ -7610,7 +6981,7 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
|
|
|
7610
6981
|
const [cmd, args] = await wrapForIsolation("npm", ["install"], mindName);
|
|
7611
6982
|
await exec(cmd, args, {
|
|
7612
6983
|
cwd: projectRoot,
|
|
7613
|
-
env: { ...process.env, HOME:
|
|
6984
|
+
env: { ...process.env, HOME: resolve14(projectRoot, "home") }
|
|
7614
6985
|
});
|
|
7615
6986
|
} else {
|
|
7616
6987
|
await exec("npm", ["install"], { cwd: projectRoot });
|
|
@@ -7764,86 +7135,6 @@ import { zValidator as zValidator10 } from "@hono/zod-validator";
|
|
|
7764
7135
|
import { Hono as Hono26 } from "hono";
|
|
7765
7136
|
import { streamSSE as streamSSE5 } from "hono/streaming";
|
|
7766
7137
|
import { z as z10 } from "zod";
|
|
7767
|
-
|
|
7768
|
-
// packages/daemon/src/lib/bridges/bridge-outbound.ts
|
|
7769
|
-
function extractContent(contentBlocks) {
|
|
7770
|
-
const text = contentBlocks.filter((b) => b.type === "text").map((b) => b.text).join("\n");
|
|
7771
|
-
const images = contentBlocks.filter((b) => b.type === "image").map((b) => ({ media_type: b.media_type, data: b.data }));
|
|
7772
|
-
return { text, images };
|
|
7773
|
-
}
|
|
7774
|
-
async function routeOutboundBridge(conversationId, senderName, contentBlocks) {
|
|
7775
|
-
try {
|
|
7776
|
-
const conv = await getConversation(conversationId);
|
|
7777
|
-
if (!conv) return;
|
|
7778
|
-
if (conv.type === "channel") {
|
|
7779
|
-
const channelName = await getChannelName(conversationId);
|
|
7780
|
-
if (channelName) {
|
|
7781
|
-
await routeChannelOutbound(channelName, senderName, contentBlocks);
|
|
7782
|
-
} else {
|
|
7783
|
-
logger_default.warn(
|
|
7784
|
-
`channel conversation ${conversationId} has no channel name \u2014 skipping bridge outbound`
|
|
7785
|
-
);
|
|
7786
|
-
}
|
|
7787
|
-
} else if (conv.type === "dm") {
|
|
7788
|
-
await routeDMOutbound(conversationId, senderName, contentBlocks);
|
|
7789
|
-
}
|
|
7790
|
-
} catch (err) {
|
|
7791
|
-
logger_default.error(`bridge outbound failed for conversation ${conversationId}`, logger_default.errorData(err));
|
|
7792
|
-
}
|
|
7793
|
-
}
|
|
7794
|
-
async function routeChannelOutbound(channelName, senderName, contentBlocks) {
|
|
7795
|
-
const bridgeInfo = findBridgeForChannel(channelName);
|
|
7796
|
-
if (!bridgeInfo) return;
|
|
7797
|
-
const driver = getPlatformDriver(bridgeInfo.platform);
|
|
7798
|
-
if (!driver) {
|
|
7799
|
-
logger_default.warn(`no channel driver for bridge platform: ${bridgeInfo.platform}`);
|
|
7800
|
-
return;
|
|
7801
|
-
}
|
|
7802
|
-
const { text, images } = extractContent(contentBlocks);
|
|
7803
|
-
if (!text) return;
|
|
7804
|
-
const env = readEnv(sharedEnvPath());
|
|
7805
|
-
env.VOLUTE_SENDER = senderName;
|
|
7806
|
-
await driver.send(env, bridgeInfo.externalChannel, text, images.length > 0 ? images : void 0);
|
|
7807
|
-
logger_default.debug(`bridge outbound: sent to ${bridgeInfo.platform}:${bridgeInfo.externalChannel}`);
|
|
7808
|
-
}
|
|
7809
|
-
async function routeDMOutbound(conversationId, senderName, contentBlocks) {
|
|
7810
|
-
const participants = await getParticipants(conversationId);
|
|
7811
|
-
const puppets = participants.filter((p) => p.userType === "puppet");
|
|
7812
|
-
if (puppets.length === 0) return;
|
|
7813
|
-
const { text, images } = extractContent(contentBlocks);
|
|
7814
|
-
if (!text) return;
|
|
7815
|
-
for (const puppet of puppets) {
|
|
7816
|
-
const colonIdx = puppet.username.indexOf(":");
|
|
7817
|
-
if (colonIdx === -1) {
|
|
7818
|
-
logger_default.warn(
|
|
7819
|
-
`puppet user ${puppet.username} has malformed username (expected platform:id format)`
|
|
7820
|
-
);
|
|
7821
|
-
continue;
|
|
7822
|
-
}
|
|
7823
|
-
const platform = puppet.username.slice(0, colonIdx);
|
|
7824
|
-
const externalUserId = puppet.username.slice(colonIdx + 1);
|
|
7825
|
-
const bridgeConfig = getBridgeConfig(platform);
|
|
7826
|
-
if (!bridgeConfig?.enabled) continue;
|
|
7827
|
-
const driver = getPlatformDriver(platform);
|
|
7828
|
-
if (!driver?.createConversation) {
|
|
7829
|
-
logger_default.warn(`no channel driver with DM support for bridge platform: ${platform}`);
|
|
7830
|
-
continue;
|
|
7831
|
-
}
|
|
7832
|
-
try {
|
|
7833
|
-
const env = readEnv(sharedEnvPath());
|
|
7834
|
-
env.VOLUTE_SENDER = senderName;
|
|
7835
|
-
env.VOLUTE_MIND = senderName;
|
|
7836
|
-
env.VOLUTE_MIND_DIR = mindDir(senderName);
|
|
7837
|
-
const slug = await driver.createConversation(env, [externalUserId]);
|
|
7838
|
-
await driver.send(env, slug, text, images.length > 0 ? images : void 0);
|
|
7839
|
-
logger_default.debug(`bridge outbound DM: sent to ${platform}:${externalUserId}`);
|
|
7840
|
-
} catch (err) {
|
|
7841
|
-
logger_default.error(`bridge outbound DM failed for puppet ${puppet.username}`, logger_default.errorData(err));
|
|
7842
|
-
}
|
|
7843
|
-
}
|
|
7844
|
-
}
|
|
7845
|
-
|
|
7846
|
-
// packages/daemon/src/web/api/volute/chat.ts
|
|
7847
7138
|
async function fanOutToMinds(opts) {
|
|
7848
7139
|
const participants = opts.participants;
|
|
7849
7140
|
const mindParticipants = participants.filter(
|
|
@@ -8098,11 +7389,11 @@ var app23 = new Hono26().get("/:name/conversations/:id/events", async (c) => {
|
|
|
8098
7389
|
if (!stream.aborted) console.error("[chat] SSE ping error:", err);
|
|
8099
7390
|
});
|
|
8100
7391
|
}, 15e3);
|
|
8101
|
-
await new Promise((
|
|
7392
|
+
await new Promise((resolve17) => {
|
|
8102
7393
|
stream.onAbort(() => {
|
|
8103
7394
|
unsubscribe();
|
|
8104
7395
|
clearInterval(keepAlive);
|
|
8105
|
-
|
|
7396
|
+
resolve17();
|
|
8106
7397
|
});
|
|
8107
7398
|
});
|
|
8108
7399
|
});
|
|
@@ -8312,10 +7603,10 @@ app25.route("/api/conversations", conversations_default);
|
|
|
8312
7603
|
var app_default = app25;
|
|
8313
7604
|
|
|
8314
7605
|
// packages/daemon/src/web/server.ts
|
|
8315
|
-
import { existsSync as
|
|
7606
|
+
import { existsSync as existsSync10 } from "fs";
|
|
8316
7607
|
import { readFile as readFile2, stat as stat2 } from "fs/promises";
|
|
8317
7608
|
import { createServer as createHttpsServer } from "https";
|
|
8318
|
-
import { dirname as dirname2, extname as extname3, resolve as
|
|
7609
|
+
import { dirname as dirname2, extname as extname3, resolve as resolve15 } from "path";
|
|
8319
7610
|
import { serve } from "@hono/node-server";
|
|
8320
7611
|
var MIME_TYPES2 = {
|
|
8321
7612
|
".html": "text/html",
|
|
@@ -8334,8 +7625,8 @@ async function startServer({
|
|
|
8334
7625
|
let assetsDir = "";
|
|
8335
7626
|
let searchDir = dirname2(new URL(import.meta.url).pathname);
|
|
8336
7627
|
for (let i = 0; i < 5; i++) {
|
|
8337
|
-
const candidate =
|
|
8338
|
-
if (
|
|
7628
|
+
const candidate = resolve15(searchDir, "dist", "web-assets");
|
|
7629
|
+
if (existsSync10(candidate)) {
|
|
8339
7630
|
assetsDir = candidate;
|
|
8340
7631
|
break;
|
|
8341
7632
|
}
|
|
@@ -8345,7 +7636,7 @@ async function startServer({
|
|
|
8345
7636
|
app_default.get("*", async (c) => {
|
|
8346
7637
|
const urlPath = new URL(c.req.url).pathname;
|
|
8347
7638
|
if (urlPath.startsWith("/api/") || urlPath.startsWith("/ext/")) return c.notFound();
|
|
8348
|
-
const filePath =
|
|
7639
|
+
const filePath = resolve15(assetsDir, urlPath.slice(1));
|
|
8349
7640
|
if (!filePath.startsWith(assetsDir)) return c.text("Forbidden", 403);
|
|
8350
7641
|
const s = await stat2(filePath).catch(() => null);
|
|
8351
7642
|
if (s?.isFile()) {
|
|
@@ -8358,7 +7649,7 @@ async function startServer({
|
|
|
8358
7649
|
const cacheControl = isHashed ? "public, max-age=31536000, immutable" : "no-cache";
|
|
8359
7650
|
return c.body(body, 200, { "Content-Type": mime, "Cache-Control": cacheControl });
|
|
8360
7651
|
}
|
|
8361
|
-
const indexPath =
|
|
7652
|
+
const indexPath = resolve15(assetsDir, "index.html");
|
|
8362
7653
|
const indexStat = await stat2(indexPath).catch(() => null);
|
|
8363
7654
|
if (indexStat?.isFile()) {
|
|
8364
7655
|
const body = await readFile2(indexPath, "utf-8");
|
|
@@ -8375,10 +7666,10 @@ async function startServer({
|
|
|
8375
7666
|
createServer: createHttpsServer,
|
|
8376
7667
|
serverOptions: { key: tls.key, cert: tls.cert }
|
|
8377
7668
|
});
|
|
8378
|
-
await new Promise((
|
|
7669
|
+
await new Promise((resolve17, reject) => {
|
|
8379
7670
|
server2.on("listening", () => {
|
|
8380
7671
|
logger_default.info("Volute UI running (https)", { hostname, port });
|
|
8381
|
-
|
|
7672
|
+
resolve17();
|
|
8382
7673
|
});
|
|
8383
7674
|
server2.on("error", (err) => {
|
|
8384
7675
|
reject(err);
|
|
@@ -8386,13 +7677,13 @@ async function startServer({
|
|
|
8386
7677
|
});
|
|
8387
7678
|
const internalPort = port + 1;
|
|
8388
7679
|
const internalServer = serve({ fetch: app_default.fetch, port: internalPort, hostname: "127.0.0.1" });
|
|
8389
|
-
await new Promise((
|
|
7680
|
+
await new Promise((resolve17, reject) => {
|
|
8390
7681
|
internalServer.on("listening", () => {
|
|
8391
7682
|
logger_default.info("Volute API running (http, internal)", {
|
|
8392
7683
|
hostname: "127.0.0.1",
|
|
8393
7684
|
port: internalPort
|
|
8394
7685
|
});
|
|
8395
|
-
|
|
7686
|
+
resolve17();
|
|
8396
7687
|
});
|
|
8397
7688
|
internalServer.on("error", (err) => {
|
|
8398
7689
|
reject(err);
|
|
@@ -8401,10 +7692,10 @@ async function startServer({
|
|
|
8401
7692
|
return { server: server2, internalPort };
|
|
8402
7693
|
}
|
|
8403
7694
|
const server = serve({ fetch: app_default.fetch, port, hostname });
|
|
8404
|
-
await new Promise((
|
|
7695
|
+
await new Promise((resolve17, reject) => {
|
|
8405
7696
|
server.on("listening", () => {
|
|
8406
7697
|
logger_default.info("Volute API running (http)", { hostname, port });
|
|
8407
|
-
|
|
7698
|
+
resolve17();
|
|
8408
7699
|
});
|
|
8409
7700
|
server.on("error", (err) => {
|
|
8410
7701
|
reject(err);
|
|
@@ -8415,7 +7706,7 @@ async function startServer({
|
|
|
8415
7706
|
|
|
8416
7707
|
// packages/daemon/src/daemon.ts
|
|
8417
7708
|
if (!process.env.VOLUTE_HOME) {
|
|
8418
|
-
process.env.VOLUTE_HOME =
|
|
7709
|
+
process.env.VOLUTE_HOME = resolve16(homedir3(), ".volute");
|
|
8419
7710
|
}
|
|
8420
7711
|
if (process.env.VOLUTE_TIMEZONE && !process.env.TZ) {
|
|
8421
7712
|
process.env.TZ = process.env.VOLUTE_TIMEZONE;
|
|
@@ -8426,7 +7717,7 @@ async function startDaemon(opts) {
|
|
|
8426
7717
|
const home = voluteHome();
|
|
8427
7718
|
const systemDir = voluteSystemDir();
|
|
8428
7719
|
if (!opts.foreground) {
|
|
8429
|
-
const rotatingLog = new RotatingLog(
|
|
7720
|
+
const rotatingLog = new RotatingLog(resolve16(systemDir, "daemon.log"));
|
|
8430
7721
|
logger_default.setOutput((line) => rotatingLog.write(`${line}
|
|
8431
7722
|
`));
|
|
8432
7723
|
const write = (...args) => rotatingLog.write(`${format(...args)}
|
|
@@ -8436,22 +7727,22 @@ async function startDaemon(opts) {
|
|
|
8436
7727
|
console.warn = write;
|
|
8437
7728
|
console.info = write;
|
|
8438
7729
|
}
|
|
8439
|
-
const DAEMON_PID_PATH =
|
|
8440
|
-
const DAEMON_JSON_PATH =
|
|
7730
|
+
const DAEMON_PID_PATH = resolve16(systemDir, "daemon.pid");
|
|
7731
|
+
const DAEMON_JSON_PATH = resolve16(systemDir, "daemon.json");
|
|
8441
7732
|
mkdirSync10(home, { recursive: true });
|
|
8442
7733
|
ensureSystemDir();
|
|
8443
|
-
const { migrateSetupCompleted } = await import("./setup-
|
|
7734
|
+
const { migrateSetupCompleted } = await import("./setup-PF7JSFMO.js");
|
|
8444
7735
|
migrateSetupCompleted();
|
|
8445
|
-
await (await import("./db-
|
|
7736
|
+
await (await import("./db-CBOCDYVA.js")).getDb();
|
|
8446
7737
|
try {
|
|
8447
7738
|
const { eq: eq7, and: and5 } = await import("drizzle-orm");
|
|
8448
|
-
const { users: users2 } = await import("./schema-
|
|
8449
|
-
const db = await (await import("./db-
|
|
7739
|
+
const { users: users2 } = await import("./schema-K575EBPE.js");
|
|
7740
|
+
const db = await (await import("./db-CBOCDYVA.js")).getDb();
|
|
8450
7741
|
await db.update(users2).set({ role: "system" }).where(and5(eq7(users2.user_type, "system"), eq7(users2.role, "user")));
|
|
8451
7742
|
} catch (err) {
|
|
8452
7743
|
logger_default.warn("failed to migrate system user role", logger_default.errorData(err));
|
|
8453
7744
|
}
|
|
8454
|
-
const { initSandbox } = await import("./sandbox-
|
|
7745
|
+
const { initSandbox } = await import("./sandbox-PQYEICEF.js");
|
|
8455
7746
|
await initSandbox();
|
|
8456
7747
|
try {
|
|
8457
7748
|
await syncBuiltinSkills();
|
|
@@ -8478,7 +7769,7 @@ async function startDaemon(opts) {
|
|
|
8478
7769
|
logger_default.warn("failed to ensure #system channel", logger_default.errorData(err));
|
|
8479
7770
|
}
|
|
8480
7771
|
try {
|
|
8481
|
-
const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-
|
|
7772
|
+
const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-2QOOPMBX.js");
|
|
8482
7773
|
await getOrCreateSystemUser2();
|
|
8483
7774
|
} catch (err) {
|
|
8484
7775
|
logger_default.warn(
|
|
@@ -8489,7 +7780,7 @@ async function startDaemon(opts) {
|
|
|
8489
7780
|
const token = process.env.VOLUTE_DAEMON_TOKEN || randomBytes(32).toString("hex");
|
|
8490
7781
|
let tls;
|
|
8491
7782
|
if (opts.tailscale) {
|
|
8492
|
-
const { getTailscaleTls } = await import("./tailscale-
|
|
7783
|
+
const { getTailscaleTls } = await import("./tailscale-LTYNKIPZ.js");
|
|
8493
7784
|
const tlsConfig = await getTailscaleTls();
|
|
8494
7785
|
tls = { key: tlsConfig.key, cert: tlsConfig.cert };
|
|
8495
7786
|
logger_default.info("Tailscale HTTPS enabled", { hostname: tlsConfig.hostname });
|
|
@@ -8562,10 +7853,10 @@ async function startDaemon(opts) {
|
|
|
8562
7853
|
await Promise.all(workers);
|
|
8563
7854
|
}
|
|
8564
7855
|
try {
|
|
8565
|
-
const { isSetupComplete: isSetupComplete2 } = await import("./setup-
|
|
7856
|
+
const { isSetupComplete: isSetupComplete2 } = await import("./setup-PF7JSFMO.js");
|
|
8566
7857
|
if (isSetupComplete2()) {
|
|
8567
|
-
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-
|
|
8568
|
-
const { startSpiritFull } = await import("./mind-service-
|
|
7858
|
+
const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-4QOYM33G.js");
|
|
7859
|
+
const { startSpiritFull } = await import("./mind-service-WRTOQSAL.js");
|
|
8569
7860
|
await ensureSpiritProject();
|
|
8570
7861
|
await syncSpiritTemplate();
|
|
8571
7862
|
const spiritEntry = await findMind("volute");
|
|
@@ -8582,7 +7873,7 @@ async function startDaemon(opts) {
|
|
|
8582
7873
|
bridgeManager.startBridges(daemonPort).catch((err) => {
|
|
8583
7874
|
logger_default.warn("failed to start bridges", logger_default.errorData(err));
|
|
8584
7875
|
});
|
|
8585
|
-
import("./cloud-sync-
|
|
7876
|
+
import("./cloud-sync-EZKCEIBX.js").then(
|
|
8586
7877
|
({ consumeQueuedMessages }) => consumeQueuedMessages().catch((err) => {
|
|
8587
7878
|
logger_default.warn("failed to consume queued cloud messages", logger_default.errorData(err));
|
|
8588
7879
|
})
|
|
@@ -8590,7 +7881,7 @@ async function startDaemon(opts) {
|
|
|
8590
7881
|
logger_default.warn("failed to load cloud-sync module", logger_default.errorData(err));
|
|
8591
7882
|
});
|
|
8592
7883
|
try {
|
|
8593
|
-
const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-
|
|
7884
|
+
const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-NCRIN5QK.js");
|
|
8594
7885
|
backfillTemplateHashes();
|
|
8595
7886
|
notifyVersionUpdate().catch((err) => {
|
|
8596
7887
|
logger_default.warn("failed to send version update notifications", logger_default.errorData(err));
|
|
@@ -8611,13 +7902,13 @@ async function startDaemon(opts) {
|
|
|
8611
7902
|
logger_default.info(`running on ${hostname}:${port}, pid ${myPid}`);
|
|
8612
7903
|
function cleanup() {
|
|
8613
7904
|
try {
|
|
8614
|
-
if (
|
|
7905
|
+
if (readFileSync10(DAEMON_PID_PATH, "utf-8").trim() === myPid) {
|
|
8615
7906
|
unlinkSync2(DAEMON_PID_PATH);
|
|
8616
7907
|
}
|
|
8617
7908
|
} catch {
|
|
8618
7909
|
}
|
|
8619
7910
|
try {
|
|
8620
|
-
const data = JSON.parse(
|
|
7911
|
+
const data = JSON.parse(readFileSync10(DAEMON_JSON_PATH, "utf-8"));
|
|
8621
7912
|
if (data.token === token) {
|
|
8622
7913
|
unlinkSync2(DAEMON_JSON_PATH);
|
|
8623
7914
|
}
|