volute 0.30.1 → 0.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. package/README.md +15 -22
  2. package/dist/{accept-E3PAH3QJ.js → accept-74M7I4RZ.js} +5 -4
  3. package/dist/{activity-events-BKBPPUBP.js → activity-events-HETAODOK.js} +3 -2
  4. package/dist/{ai-service-VAJT5UBS.js → ai-service-ZIPCV3MX.js} +20 -5
  5. package/dist/api.d.ts +341 -397
  6. package/dist/{archive-WWDBWYN2.js → archive-INXYFVCW.js} +3 -2
  7. package/dist/auth-6DMGES3I.js +44 -0
  8. package/dist/{bridge-RO37CUFM.js → bridge-BVCBTGPF.js} +5 -4
  9. package/dist/{chat-TCUNPFGO.js → chat-XT4OBJBU.js} +8 -8
  10. package/dist/{chunk-P7VFDSSG.js → chunk-2FLJ63GU.js} +2 -2
  11. package/dist/{chunk-ZWKTUQEL.js → chunk-2NGTS5UU.js} +1 -1
  12. package/dist/{chunk-JGFRDMR6.js → chunk-ALEF47VT.js} +1 -1
  13. package/dist/{chunk-MDPCSXZ4.js → chunk-D5G5YOPL.js} +163 -15
  14. package/dist/{chunk-VGWJSNHS.js → chunk-G53F3JA4.js} +1 -35
  15. package/dist/{chunk-A6TUJJ3L.js → chunk-G6BSYHPK.js} +2 -2
  16. package/dist/{chunk-DTC6EH5I.js → chunk-I5KY25PQ.js} +1 -9
  17. package/dist/{chunk-NSBFETWP.js → chunk-IYDIE3HG.js} +64 -26
  18. package/dist/{chunk-W5OOPLNP.js → chunk-JJ7W6WSB.js} +3 -3
  19. package/dist/{chunk-G3GBKZGG.js → chunk-LGB6JBHI.js} +54 -2
  20. package/dist/chunk-LRCG2JLP.js +251 -0
  21. package/dist/{chunk-FXHXHI2A.js → chunk-LSGWR54X.js} +3 -6
  22. package/dist/{chunk-S5LR3XYJ.js → chunk-M7UL5S3Q.js} +1 -1
  23. package/dist/chunk-PB65JZK2.js +85 -0
  24. package/dist/chunk-PVY5W6QN.js +41 -0
  25. package/dist/{chunk-QVAQ5454.js → chunk-QBQ424EM.js} +3007 -2126
  26. package/dist/{chunk-P27RV5WM.js → chunk-QZANELPX.js} +6 -2
  27. package/dist/{chunk-FSM45XD5.js → chunk-R7E6CRVQ.js} +1 -1
  28. package/dist/{chunk-HHTXM4JT.js → chunk-RPZZSXV3.js} +39 -195
  29. package/dist/{chunk-UPA6COHU.js → chunk-RSX4OPZY.js} +5 -5
  30. package/dist/{chunk-2C2VXEBB.js → chunk-S6NFERDC.js} +21 -57
  31. package/dist/chunk-SKLSMHXO.js +208 -0
  32. package/dist/{chunk-IKHDUZRH.js → chunk-SX5TKJBZ.js} +2 -2
  33. package/dist/chunk-TDRYEPH4.js +185 -0
  34. package/dist/chunk-TSXLLQZW.js +46 -0
  35. package/dist/{chunk-EFVHR7KH.js → chunk-UKVWJRKN.js} +24 -5
  36. package/dist/{chunk-2NDZC3S7.js → chunk-WKF5FEFK.js} +688 -389
  37. package/dist/cli.js +93 -24
  38. package/dist/{clock-G3ALCMLJ.js → clock-2UOZ6JPU.js} +11 -8
  39. package/dist/{cloud-sync-JV4LJOK3.js → cloud-sync-JN3NWKEM.js} +16 -14
  40. package/dist/config-H2H4UIF7.js +72 -0
  41. package/dist/connectors/discord-bridge.js +1 -1
  42. package/dist/connectors/slack-bridge.js +1 -1
  43. package/dist/connectors/telegram-bridge.js +1 -1
  44. package/dist/{conversations-7KVQV7EZ.js → conversations-3O5O6AS3.js} +8 -7
  45. package/dist/{create-JTLS7GX3.js → create-RNLNCORE.js} +5 -4
  46. package/dist/{create-VQSQHJQW.js → create-WBBYI6V7.js} +6 -2
  47. package/dist/daemon-client-6QXHZ7US.js +12 -0
  48. package/dist/{daemon-restart-4JGBHEJ4.js → daemon-restart-NGFHFAUF.js} +7 -7
  49. package/dist/daemon.js +2446 -1999
  50. package/dist/{db-HMFPIRO2.js → db-F34YLV7D.js} +2 -1
  51. package/dist/db-RA45JBFG.js +16 -0
  52. package/dist/{delete-JESHKE7F.js → delete-QTGWEDBI.js} +1 -1
  53. package/dist/delivery-manager-SDVXFD4W.js +28 -0
  54. package/dist/delivery-router-FL45JL7N.js +21 -0
  55. package/dist/down-TB3ESMNP.js +14 -0
  56. package/dist/{env-CLXXT7M2.js → env-RLYQBOOP.js} +5 -4
  57. package/dist/{export-EGA5M5PB.js → export-SUYRLI5Q.js} +4 -3
  58. package/dist/{extension-WZ4SUPJB.js → extension-FQ5D3NCC.js} +6 -6
  59. package/dist/{extensions-ECO4RPFQ.js → extensions-GDYWQXC4.js} +9 -7
  60. package/dist/{files-4VEJDASH.js → files-EAMPO2SJ.js} +6 -5
  61. package/dist/{history-EJMMLXDO.js → history-FO5PHBQ5.js} +9 -4
  62. package/dist/{import-YCGPMBSI.js → import-DDUFE7AY.js} +4 -3
  63. package/dist/{join-2GBJKZEN.js → join-I5QEE3LG.js} +1 -1
  64. package/dist/{list-Q6O7FGAN.js → list-DW2VRTOZ.js} +5 -4
  65. package/dist/{login-RL6AU2SM.js → login-7CHPW2PN.js} +5 -4
  66. package/dist/{login-RET5WESK.js → login-RIJF2F4G.js} +3 -2
  67. package/dist/{logout-CGAGJN3L.js → logout-5MLHZALK.js} +3 -2
  68. package/dist/{logout-JRPBEMMR.js → logout-UZJRGY4Z.js} +3 -2
  69. package/dist/message-delivery-2FIM7QKO.js +32 -0
  70. package/dist/{mind-LUWRQUQ5.js → mind-2B6M7Y25.js} +18 -18
  71. package/dist/{mind-activity-tracker-VYN2ZZ2M.js → mind-activity-tracker-NZZT2NTT.js} +4 -3
  72. package/dist/{mind-list-V5WW5DUA.js → mind-list-WUPMQDYQ.js} +3 -2
  73. package/dist/mind-manager-BNCMGYXW.js +28 -0
  74. package/dist/mind-service-AV273WT4.js +34 -0
  75. package/dist/{mind-sleep-R6PTNNW4.js → mind-sleep-B7BHJLH7.js} +5 -4
  76. package/dist/{mind-status-I4ISFJ6I.js → mind-status-L3EFFRPR.js} +3 -2
  77. package/dist/{mind-wake-67ZQEWAV.js → mind-wake-GY3RFX7Y.js} +5 -4
  78. package/dist/{package-OYUD4ZJ4.js → package-PK6JUFL3.js} +3 -3
  79. package/dist/read-5AMJRO3D.js +75 -0
  80. package/dist/{register-NZDSTLP3.js → register-V2JZZKFK.js} +5 -4
  81. package/dist/{registry-ODSALQQL.js → registry-PJ4S5PHQ.js} +8 -1
  82. package/dist/{reject-2HZOJEIJ.js → reject-33HEZMZ4.js} +5 -4
  83. package/dist/{restart-QHS3NT64.js → restart-3UCMRUVC.js} +5 -4
  84. package/dist/{sandbox-O5FUSF43.js → sandbox-JANNTX6U.js} +4 -3
  85. package/dist/schema-PA3M5ZKH.js +32 -0
  86. package/dist/seed-ALUQ55FF.js +112 -0
  87. package/dist/{send-OAN3RYYY.js → send-3MI36LEF.js} +58 -69
  88. package/dist/{setup-QMDK5RZX.js → setup-SZIARWI6.js} +5 -4
  89. package/dist/{setup-XJH3E7YM.js → setup-WENLVPVP.js} +9 -9
  90. package/dist/{skill-FZIN4W4Q.js → skill-TUVOTW4Z.js} +5 -4
  91. package/dist/skills/dreaming/SKILL.md +6 -4
  92. package/dist/skills/dreaming/references/INSTALL.md +4 -5
  93. package/dist/skills/dreaming/scripts/dream.ts +5 -27
  94. package/dist/skills/dreaming/scripts/wake-context-dreams.sh +1 -1
  95. package/dist/skills/imagegen/SKILL.md +6 -5
  96. package/dist/skills/imagegen/references/INSTALL.md +1 -1
  97. package/dist/skills/resonance/SKILL.md +4 -1
  98. package/dist/skills/resonance/references/INSTALL.md +2 -2
  99. package/dist/skills/resonance/scripts/resonance-hook.sh +2 -0
  100. package/dist/skills/resonance/scripts/resonance.ts +35 -5
  101. package/dist/skills/volute-admin/SKILL.md +83 -0
  102. package/dist/skills/volute-mind/SKILL.md +12 -12
  103. package/dist/skills-XNZK6P4K.js +61 -0
  104. package/dist/sleep-manager-53DZOWW7.js +32 -0
  105. package/dist/spirit-N4W4UQRH.js +217 -0
  106. package/dist/{split-EXYGGGQN.js → split-STOROBYJ.js} +1 -1
  107. package/dist/{sprout-AXQ6H5DB.js → sprout-L2GFOVF7.js} +9 -8
  108. package/dist/{start-MTOVL6SY.js → start-K2NCUUCG.js} +5 -4
  109. package/dist/{status-ZRO37MWR.js → status-TCUMUO6M.js} +5 -5
  110. package/dist/{stop-OK5WEPVC.js → stop-H26JZDXF.js} +5 -4
  111. package/dist/system-chat-NPYFYZVI.js +32 -0
  112. package/dist/{systems-W3BBMSOZ.js → systems-DHBKVYEY.js} +6 -5
  113. package/dist/{tailscale-BM72RXCJ.js → tailscale-XHQBZROW.js} +2 -1
  114. package/dist/{template-hash-3HOR4UAJ.js → template-hash-A6VVKOXJ.js} +2 -1
  115. package/dist/up-6I6BHRTO.js +17 -0
  116. package/dist/{update-PLPHMMZ2.js → update-QVPRF6GR.js} +5 -5
  117. package/dist/{update-check-CVCN7MF6.js → update-check-ZD6OOIYQ.js} +3 -2
  118. package/dist/{upgrade-I6NPCYUU.js → upgrade-O4Q7WJM3.js} +12 -14
  119. package/dist/{version-notify-2NTWVEHL.js → version-notify-TCKWBZZG.js} +22 -23
  120. package/dist/web-assets/assets/index-Bui7U9Uu.css +1 -0
  121. package/dist/web-assets/assets/index-e36DIo1b.js +73 -0
  122. package/dist/web-assets/ext-theme.css +94 -0
  123. package/dist/web-assets/index.html +2 -2
  124. package/drizzle/0000_baseline.sql +152 -0
  125. package/drizzle/0001_add_conversation_private.sql +1 -0
  126. package/drizzle/0002_turns.sql +21 -0
  127. package/drizzle/0003_turn_feed_links.sql +11 -0
  128. package/drizzle/0004_spirits.sql +5 -0
  129. package/drizzle/meta/0000_snapshot.json +3 -223
  130. package/drizzle/meta/0001_snapshot.json +3 -294
  131. package/drizzle/meta/0002_snapshot.json +3 -335
  132. package/drizzle/meta/0003_snapshot.json +3 -413
  133. package/drizzle/meta/0004_snapshot.json +3 -406
  134. package/drizzle/meta/_journal.json +10 -101
  135. package/package.json +3 -3
  136. package/packages/extensions/notes/dist/ui/assets/index-8jWEv9SA.js +61 -0
  137. package/packages/extensions/notes/dist/ui/assets/index-DkaB7Ytd.css +1 -0
  138. package/packages/extensions/notes/dist/ui/index.html +2 -2
  139. package/packages/extensions/notes/skills/notes/SKILL.md +8 -8
  140. package/packages/extensions/pages/skills/pages/SKILL.md +17 -44
  141. package/templates/_base/.init/.config/hooks/pre-prompt/session-activity.ts +40 -0
  142. package/templates/_base/.init/.local/bin/volute +27 -0
  143. package/templates/_base/.init/.local/hooks/pre-prompt/session-activity.ts +40 -0
  144. package/templates/_base/.init/.local/hooks/startup-context.ts +58 -0
  145. package/templates/_base/home/.config/routes.json +1 -1
  146. package/templates/_base/src/lib/auto-commit.ts +82 -43
  147. package/templates/_base/src/lib/daemon-client.ts +40 -36
  148. package/templates/_base/src/lib/format-prefix.ts +1 -0
  149. package/templates/_base/src/lib/hook-loader.ts +155 -0
  150. package/templates/_base/src/lib/router.ts +17 -1
  151. package/templates/_base/src/lib/startup.ts +17 -12
  152. package/templates/_base/src/lib/transparency.ts +2 -2
  153. package/templates/_base/src/lib/volute-server.ts +2 -5
  154. package/templates/claude/.init/.claude/settings.json +1 -1
  155. package/templates/claude/.init/.config/routes.json +2 -2
  156. package/templates/claude/src/agent.ts +97 -14
  157. package/templates/claude/src/lib/hooks/auto-commit.ts +7 -3
  158. package/templates/claude/src/lib/message-channel.ts +7 -2
  159. package/templates/claude/src/server.ts +0 -9
  160. package/templates/codex/.init/.config/routes.json +11 -0
  161. package/templates/codex/.init/AGENTS.md +29 -0
  162. package/templates/codex/home/.config/config.json.tmpl +7 -0
  163. package/templates/codex/package.json.tmpl +20 -0
  164. package/templates/codex/src/agent.ts +553 -0
  165. package/templates/codex/src/lib/content.ts +16 -0
  166. package/templates/codex/src/lib/session-store.ts +56 -0
  167. package/templates/codex/src/server.ts +59 -0
  168. package/templates/codex/volute-template.json +8 -0
  169. package/templates/pi/.init/.config/routes.json +2 -2
  170. package/templates/pi/package.json.tmpl +1 -1
  171. package/templates/pi/src/agent.ts +63 -9
  172. package/templates/pi/src/lib/event-handler.ts +6 -4
  173. package/templates/pi/src/lib/reply-instructions-extension.ts +32 -11
  174. package/dist/chunk-7D47T4RB.js +0 -84
  175. package/dist/chunk-CVH6Y2YG.js +0 -59
  176. package/dist/chunk-EFP3PE6C.js +0 -232
  177. package/dist/chunk-LIRWLNAK.js +0 -729
  178. package/dist/daemon-client-BCTFGVCZ.js +0 -9
  179. package/dist/down-NGBMGORS.js +0 -14
  180. package/dist/message-delivery-6YMVNOEC.js +0 -28
  181. package/dist/migrate-registry-to-db-FK35IPEH.js +0 -110
  182. package/dist/mind-manager-YFCOIAAX.js +0 -18
  183. package/dist/pages-watcher-Z3PKNROC.js +0 -21
  184. package/dist/read-WQMPTSN2.js +0 -46
  185. package/dist/seed-WUQMPLDM.js +0 -71
  186. package/dist/skills/sessions/SKILL.md +0 -49
  187. package/dist/sleep-manager-O7YQFCV5.js +0 -30
  188. package/dist/up-BXUAIDXB.js +0 -17
  189. package/dist/web-assets/assets/index--kREqKl9.js +0 -72
  190. package/dist/web-assets/assets/index-BXYTG0nJ.css +0 -1
  191. package/drizzle/0000_flaky_mariko_yashida.sql +0 -34
  192. package/drizzle/0001_careless_warpath.sql +0 -12
  193. package/drizzle/0002_wealthy_the_call.sql +0 -6
  194. package/drizzle/0003_clean_ego.sql +0 -12
  195. package/drizzle/0004_magical_silverclaw.sql +0 -1
  196. package/drizzle/0005_rename_agents_to_minds.sql +0 -11
  197. package/drizzle/0006_mind_history.sql +0 -20
  198. package/drizzle/0007_system_prompts.sql +0 -5
  199. package/drizzle/0008_volute_channels.sql +0 -24
  200. package/drizzle/0009_shared_skills.sql +0 -9
  201. package/drizzle/0010_delivery_queue.sql +0 -12
  202. package/drizzle/0011_rename_human_to_brain.sql +0 -1
  203. package/drizzle/0012_activity.sql +0 -11
  204. package/drizzle/0013_user_profiles.sql +0 -3
  205. package/drizzle/0014_conversation_reads.sql +0 -7
  206. package/drizzle/0015_notes.sql +0 -23
  207. package/drizzle/0016_note_reactions_and_replies.sql +0 -15
  208. package/drizzle/0017_minds.sql +0 -16
  209. package/drizzle/meta/0005_snapshot.json +0 -410
  210. package/drizzle/meta/0006_snapshot.json +0 -7
  211. package/drizzle/meta/0007_snapshot.json +0 -7
  212. package/drizzle/meta/0008_snapshot.json +0 -7
  213. package/drizzle/meta/0009_snapshot.json +0 -7
  214. package/drizzle/meta/0010_snapshot.json +0 -7
  215. package/drizzle/meta/0011_snapshot.json +0 -7
  216. package/drizzle/meta/0012_snapshot.json +0 -7
  217. package/drizzle/meta/0013_snapshot.json +0 -7
  218. package/packages/extensions/notes/dist/ui/assets/index-DgawVO5g.css +0 -1
  219. package/packages/extensions/notes/dist/ui/assets/index-qUWoeC4c.js +0 -2
  220. package/packages/extensions/notes/skills/notes/scripts/notes.mjs +0 -185
  221. package/templates/_base/.init/.config/hooks/startup-context.sh +0 -46
  222. package/templates/_base/.init/.config/scripts/session-reader.ts +0 -59
  223. package/templates/_base/home/public/.gitkeep +0 -0
  224. package/templates/_base/src/lib/session-monitor.ts +0 -400
  225. package/templates/claude/src/lib/hooks/session-context.ts +0 -32
  226. package/templates/pi/src/lib/session-context-extension.ts +0 -35
  227. /package/templates/_base/.init/{.config → .local}/hooks/wake-context.sh +0 -0
@@ -5,8 +5,9 @@ import {
5
5
  extractArchive,
6
6
  isHomeOnlyArchive,
7
7
  readManifest
8
- } from "./chunk-DTC6EH5I.js";
9
- import "./chunk-HHTXM4JT.js";
8
+ } from "./chunk-I5KY25PQ.js";
9
+ import "./chunk-LRCG2JLP.js";
10
+ import "./chunk-RPZZSXV3.js";
10
11
  import "./chunk-K3NQKI34.js";
11
12
  export {
12
13
  addHistoryToArchive,
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ approveUser,
4
+ changePassword,
5
+ countAdmins,
6
+ createUser,
7
+ deleteMindUser,
8
+ deleteUser,
9
+ getOrCreateMindUser,
10
+ getOrCreateSystemUser,
11
+ getUser,
12
+ getUserByUsername,
13
+ listPendingUsers,
14
+ listUsers,
15
+ listUsersByType,
16
+ setUserRole,
17
+ syncMindProfile,
18
+ updateUserProfile,
19
+ verifyUser
20
+ } from "./chunk-TDRYEPH4.js";
21
+ import "./chunk-QZANELPX.js";
22
+ import "./chunk-YUIHSKR6.js";
23
+ import "./chunk-LRCG2JLP.js";
24
+ import "./chunk-RPZZSXV3.js";
25
+ import "./chunk-K3NQKI34.js";
26
+ export {
27
+ approveUser,
28
+ changePassword,
29
+ countAdmins,
30
+ createUser,
31
+ deleteMindUser,
32
+ deleteUser,
33
+ getOrCreateMindUser,
34
+ getOrCreateSystemUser,
35
+ getUser,
36
+ getUserByUsername,
37
+ listPendingUsers,
38
+ listUsers,
39
+ listUsersByType,
40
+ setUserRole,
41
+ syncMindProfile,
42
+ updateUserProfile,
43
+ verifyUser
44
+ };
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- daemonFetch
4
- } from "./chunk-EFVHR7KH.js";
5
2
  import {
6
3
  parseArgs
7
4
  } from "./chunk-D424ZQGI.js";
8
- import "./chunk-HHTXM4JT.js";
5
+ import {
6
+ daemonFetch
7
+ } from "./chunk-UKVWJRKN.js";
8
+ import "./chunk-LRCG2JLP.js";
9
+ import "./chunk-RPZZSXV3.js";
9
10
  import "./chunk-K3NQKI34.js";
10
11
 
11
12
  // src/commands/chat/bridge.ts
@@ -7,28 +7,28 @@ async function run(args) {
7
7
  const subArgs = args.slice(1);
8
8
  switch (subcommand) {
9
9
  case "send":
10
- await import("./send-OAN3RYYY.js").then((m) => m.run(subArgs));
10
+ await import("./send-3MI36LEF.js").then((m) => m.run(subArgs));
11
11
  break;
12
12
  case "list":
13
- await import("./list-Q6O7FGAN.js").then((m) => m.run(subArgs));
13
+ await import("./list-DW2VRTOZ.js").then((m) => m.run(subArgs));
14
14
  break;
15
15
  case "read":
16
- await import("./read-WQMPTSN2.js").then((m) => m.run(subArgs));
16
+ await import("./read-5AMJRO3D.js").then((m) => m.run(subArgs));
17
17
  break;
18
18
  case "create":
19
- await import("./create-JTLS7GX3.js").then((m) => m.run(subArgs));
19
+ await import("./create-RNLNCORE.js").then((m) => m.run(subArgs));
20
20
  break;
21
21
  case "bridge":
22
- await import("./bridge-RO37CUFM.js").then((m) => m.run(subArgs));
22
+ await import("./bridge-BVCBTGPF.js").then((m) => m.run(subArgs));
23
23
  break;
24
24
  case "files":
25
- await import("./files-4VEJDASH.js").then((m) => m.run(subArgs));
25
+ await import("./files-EAMPO2SJ.js").then((m) => m.run(subArgs));
26
26
  break;
27
27
  case "accept":
28
- await import("./accept-E3PAH3QJ.js").then((m) => m.run(subArgs));
28
+ await import("./accept-74M7I4RZ.js").then((m) => m.run(subArgs));
29
29
  break;
30
30
  case "reject":
31
- await import("./reject-2HZOJEIJ.js").then((m) => m.run(subArgs));
31
+ await import("./reject-33HEZMZ4.js").then((m) => m.run(subArgs));
32
32
  break;
33
33
  case "--help":
34
34
  case "-h":
@@ -5,10 +5,10 @@ import {
5
5
  pollHealthDown,
6
6
  readDaemonConfig,
7
7
  stopService
8
- } from "./chunk-FXHXHI2A.js";
8
+ } from "./chunk-LSGWR54X.js";
9
9
  import {
10
10
  voluteSystemDir
11
- } from "./chunk-HHTXM4JT.js";
11
+ } from "./chunk-LRCG2JLP.js";
12
12
 
13
13
  // src/commands/down.ts
14
14
  import { existsSync, readFileSync, unlinkSync } from "fs";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  stateDir,
4
4
  voluteSystemDir
5
- } from "./chunk-HHTXM4JT.js";
5
+ } from "./chunk-LRCG2JLP.js";
6
6
 
7
7
  // src/lib/env.ts
8
8
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  stateDir
4
- } from "./chunk-HHTXM4JT.js";
4
+ } from "./chunk-LRCG2JLP.js";
5
5
 
6
6
  // src/lib/file-sharing.ts
7
7
  import { randomBytes } from "crypto";
@@ -5,16 +5,18 @@ import {
5
5
  import {
6
6
  exec,
7
7
  gitExec
8
- } from "./chunk-CVH6Y2YG.js";
8
+ } from "./chunk-LGB6JBHI.js";
9
9
  import {
10
10
  readGlobalConfig,
11
11
  writeGlobalConfig
12
- } from "./chunk-7D47T4RB.js";
12
+ } from "./chunk-TSXLLQZW.js";
13
13
  import {
14
14
  getDb,
15
- sharedSkills,
16
15
  voluteHome
17
- } from "./chunk-HHTXM4JT.js";
16
+ } from "./chunk-LRCG2JLP.js";
17
+ import {
18
+ sharedSkills
19
+ } from "./chunk-RPZZSXV3.js";
18
20
 
19
21
  // src/lib/skills.ts
20
22
  import { createHash } from "crypto";
@@ -32,7 +34,7 @@ import { basename, dirname, join, resolve } from "path";
32
34
  import { eq, sql } from "drizzle-orm";
33
35
  var VALID_SKILL_ID = /^[a-zA-Z0-9_-]+$/;
34
36
  var SEED_SKILLS = ["orientation", "memory"];
35
- var STANDARD_SKILLS = ["volute-mind", "memory", "sessions", "dreaming", "shared-files"];
37
+ var STANDARD_SKILLS = ["volute-mind", "memory", "dreaming", "shared-files"];
36
38
  function getStandardSkillsWithExtensions() {
37
39
  const config = readGlobalConfig();
38
40
  if (config.defaultSkills) return [...config.defaultSkills];
@@ -42,7 +44,7 @@ async function initDefaultSkills() {
42
44
  const config = readGlobalConfig();
43
45
  let extensionSkills = [];
44
46
  try {
45
- const { getExtensionStandardSkills } = await import("./extensions-ECO4RPFQ.js");
47
+ const { getExtensionStandardSkills } = await import("./extensions-GDYWQXC4.js");
46
48
  extensionSkills = getExtensionStandardSkills();
47
49
  } catch (err) {
48
50
  logger_default.warn("failed to load extension standard skills during init", logger_default.errorData(err));
@@ -66,15 +68,43 @@ function sharedSkillsDir() {
66
68
  }
67
69
  function parseSkillMd(content) {
68
70
  const match = content.match(/^---\n([\s\S]*?)\n---/);
69
- if (!match) return { name: "", description: "", npmDependencies: [] };
71
+ if (!match) return { name: "", description: "", npmDependencies: [], hooks: {}, bin: null };
70
72
  const frontmatter = match[1];
71
73
  const nameMatch = frontmatter.match(/^name:\s*(.+)$/m);
72
74
  const descMatch = frontmatter.match(/^description:\s*(.+)$/m);
73
75
  const depsMatch = frontmatter.match(/^\s*npm-dependencies:\s*(.+)$/m);
76
+ const binMatch = frontmatter.match(/^\s*bin:\s*(.+)$/m);
77
+ const hooks = {};
78
+ const lines = frontmatter.split("\n");
79
+ let inHooks = false;
80
+ let hooksIndent = -1;
81
+ for (const line of lines) {
82
+ if (!line.trim()) continue;
83
+ const hooksStart = line.match(/^(\s+)hooks:\s*$/);
84
+ if (hooksStart) {
85
+ inHooks = true;
86
+ hooksIndent = hooksStart[1].length;
87
+ continue;
88
+ }
89
+ if (inHooks) {
90
+ const lineIndentMatch = line.match(/^(\s*)/);
91
+ const lineIndent = lineIndentMatch ? lineIndentMatch[1].length : 0;
92
+ if (lineIndent <= hooksIndent) {
93
+ inHooks = false;
94
+ continue;
95
+ }
96
+ const hookMatch = line.match(/^\s+([a-z0-9-]+):\s*(.+)$/);
97
+ if (hookMatch) {
98
+ hooks[hookMatch[1]] = hookMatch[2].trim();
99
+ }
100
+ }
101
+ }
74
102
  return {
75
103
  name: nameMatch?.[1].trim() ?? "",
76
104
  description: descMatch?.[1].trim() ?? "",
77
- npmDependencies: depsMatch ? depsMatch[1].trim().split(/[\s,]+/).filter(Boolean) : []
105
+ npmDependencies: depsMatch ? depsMatch[1].trim().split(/[\s,]+/).filter(Boolean) : [],
106
+ hooks,
107
+ bin: binMatch?.[1].trim() ?? null
78
108
  };
79
109
  }
80
110
  async function listSharedSkills() {
@@ -128,8 +158,24 @@ async function removeSharedSkill(id) {
128
158
  const dir = join(sharedSkillsDir(), id);
129
159
  if (existsSync(dir)) rmSync(dir, { recursive: true });
130
160
  }
161
+ var TEMPLATE_SKILLS_DIR = {
162
+ claude: ".claude/skills",
163
+ pi: ".pi/skills",
164
+ codex: ".agents/skills"
165
+ };
131
166
  function mindSkillsDir(dir) {
132
- return resolve(dir, "home", ".claude", "skills");
167
+ const home = resolve(dir, "home");
168
+ let subdir = TEMPLATE_SKILLS_DIR.claude;
169
+ if (existsSync(join(home, "AGENTS.md"))) {
170
+ subdir = TEMPLATE_SKILLS_DIR.codex;
171
+ } else if (existsSync(join(home, "MINDS.md"))) {
172
+ subdir = TEMPLATE_SKILLS_DIR.pi;
173
+ }
174
+ return resolve(home, subdir);
175
+ }
176
+ function relSkillsPath(dir) {
177
+ const home = resolve(dir, "home");
178
+ return join("home", mindSkillsDir(dir).slice(home.length + 1));
133
179
  }
134
180
  function readUpstream(skillDir) {
135
181
  const upstreamPath = join(skillDir, ".upstream.json");
@@ -172,12 +218,21 @@ async function installSkill(_mindName, dir, skillId) {
172
218
  }
173
219
  }
174
220
  }
221
+ if (existsSync(skillMdPath)) {
222
+ const { hooks, bin } = parseSkillMd(readFileSync(skillMdPath, "utf-8"));
223
+ installHookShims(dir, skillId, hooks);
224
+ if (bin) installBinShim(dir, skillId, bin);
225
+ }
175
226
  let installNotes = null;
176
227
  const installMdPath = join(destDir, "references", "INSTALL.md");
177
228
  if (existsSync(installMdPath)) {
178
229
  installNotes = readFileSync(installMdPath, "utf-8");
179
230
  }
180
- await gitExec(["add", join("home", ".claude", "skills", skillId)], { cwd: dir });
231
+ await gitExec(["add", join(relSkillsPath(dir), skillId)], { cwd: dir });
232
+ await gitExec(["add", join("home", ".local", "hooks")], { cwd: dir }).catch(() => {
233
+ });
234
+ await gitExec(["add", join("home", ".local", "bin")], { cwd: dir }).catch(() => {
235
+ });
181
236
  if (npmInstalled.length > 0) {
182
237
  await gitExec(["add", "package.json", "package-lock.json"], { cwd: dir });
183
238
  }
@@ -190,7 +245,7 @@ async function installSkill(_mindName, dir, skillId) {
190
245
  };
191
246
  writeFileSync(join(destDir, ".upstream.json"), `${JSON.stringify(upstream, null, 2)}
192
247
  `);
193
- await gitExec(["add", join("home", ".claude", "skills", skillId, ".upstream.json")], {
248
+ await gitExec(["add", join(relSkillsPath(dir), skillId, ".upstream.json")], {
194
249
  cwd: dir
195
250
  });
196
251
  await gitExec(["commit", "--amend", "--no-edit"], { cwd: dir });
@@ -200,8 +255,18 @@ async function uninstallSkill(_mindName, dir, skillId) {
200
255
  validateSkillId(skillId);
201
256
  const skillDir = join(mindSkillsDir(dir), skillId);
202
257
  if (!existsSync(skillDir)) throw new Error(`Skill not installed: ${skillId}`);
258
+ removeHookShims(dir, skillId);
259
+ const skillMdPath = join(skillDir, "SKILL.md");
260
+ if (existsSync(skillMdPath)) {
261
+ const { bin } = parseSkillMd(readFileSync(skillMdPath, "utf-8"));
262
+ if (bin) removeBinShim(dir, bin);
263
+ }
203
264
  rmSync(skillDir, { recursive: true });
204
- await gitExec(["add", join("home", ".claude", "skills", skillId)], { cwd: dir });
265
+ await gitExec(["add", join(relSkillsPath(dir), skillId)], { cwd: dir });
266
+ await gitExec(["add", join("home", ".local", "hooks")], { cwd: dir }).catch(() => {
267
+ });
268
+ await gitExec(["add", join("home", ".local", "bin")], { cwd: dir }).catch(() => {
269
+ });
205
270
  await gitExec(["commit", "-m", `Uninstall skill: ${skillId}`], { cwd: dir });
206
271
  }
207
272
  async function updateSkill(_mindName, dir, skillId) {
@@ -217,7 +282,7 @@ async function updateSkill(_mindName, dir, skillId) {
217
282
  }
218
283
  const sourceDir = join(sharedSkillsDir(), upstream.source);
219
284
  if (!existsSync(sourceDir)) throw new Error(`Shared skill files missing: ${upstream.source}`);
220
- const relSkillPath = join("home", ".claude", "skills", skillId);
285
+ const relSkillPath = join(relSkillsPath(dir), skillId);
221
286
  const currentFiles = listFilesRecursive(skillDir).filter((f) => f !== ".upstream.json");
222
287
  const newFiles = listFilesRecursive(sourceDir).filter((f) => f !== ".upstream.json");
223
288
  const allFiles = [.../* @__PURE__ */ new Set([...currentFiles, ...newFiles])];
@@ -241,7 +306,9 @@ async function updateSkill(_mindName, dir, skillId) {
241
306
  try {
242
307
  baseContent2 = await gitExec(
243
308
  ["show", `${upstream.baseCommit}:${join(relSkillPath, file)}`],
244
- { cwd: dir }
309
+ {
310
+ cwd: dir
311
+ }
245
312
  );
246
313
  } catch {
247
314
  continue;
@@ -256,7 +323,9 @@ async function updateSkill(_mindName, dir, skillId) {
256
323
  try {
257
324
  baseContent = await gitExec(
258
325
  ["show", `${upstream.baseCommit}:${join(relSkillPath, file)}`],
259
- { cwd: dir }
326
+ {
327
+ cwd: dir
328
+ }
260
329
  );
261
330
  } catch {
262
331
  baseContent = "";
@@ -352,6 +421,77 @@ async function publishSkill(mindName, dir, skillId) {
352
421
  if (!existsSync(skillMdPath)) throw new Error(`SKILL.md not found in ${skillId}`);
353
422
  return importSkillFromDir(skillDir, mindName);
354
423
  }
424
+ function shimContent(skillId, scriptPath, skillsSubdir) {
425
+ const ext = scriptPath.split(".").pop() ?? "sh";
426
+ const skillScriptPath = `${skillsSubdir}/${skillId}/${scriptPath}`;
427
+ if (ext === "ts") {
428
+ return `#!/bin/bash
429
+ exec node --import tsx ${skillScriptPath} "$@"
430
+ `;
431
+ }
432
+ if (ext === "js") {
433
+ return `#!/bin/bash
434
+ exec node ${skillScriptPath} "$@"
435
+ `;
436
+ }
437
+ return `#!/bin/bash
438
+ exec bash ${skillScriptPath} "$@"
439
+ `;
440
+ }
441
+ function installHookShims(dir, skillId, hooks) {
442
+ const home = resolve(dir, "home");
443
+ const skillsSubdir = mindSkillsDir(dir).slice(home.length + 1);
444
+ for (const [event, scriptPath] of Object.entries(hooks)) {
445
+ const eventDir = join(dir, "home", ".local", "hooks", event);
446
+ mkdirSync(eventDir, { recursive: true });
447
+ const shimPath = join(eventDir, `50-${skillId}.sh`);
448
+ const content = shimContent(skillId, scriptPath, skillsSubdir);
449
+ writeFileSync(shimPath, content, { mode: 493 });
450
+ }
451
+ }
452
+ function removeHookShims(dir, skillId) {
453
+ const hooksBase = join(dir, "home", ".local", "hooks");
454
+ if (!existsSync(hooksBase)) return;
455
+ for (const eventDir of readdirSync(hooksBase, { withFileTypes: true })) {
456
+ if (!eventDir.isDirectory()) continue;
457
+ const shimPath = join(hooksBase, eventDir.name, `50-${skillId}.sh`);
458
+ if (existsSync(shimPath)) rmSync(shimPath);
459
+ }
460
+ }
461
+ function binShimContent(skillId, scriptPath, skillsSubdir) {
462
+ const skillScriptPath = `${skillsSubdir}/${skillId}/${scriptPath}`;
463
+ const ext = scriptPath.split(".").pop() ?? "sh";
464
+ if (ext === "ts") {
465
+ return `#!/bin/bash
466
+ exec node --import tsx ${skillScriptPath} "$@"
467
+ `;
468
+ }
469
+ if (ext === "js") {
470
+ return `#!/bin/bash
471
+ exec node ${skillScriptPath} "$@"
472
+ `;
473
+ }
474
+ return `#!/bin/bash
475
+ exec bash ${skillScriptPath} "$@"
476
+ `;
477
+ }
478
+ function binCommandName(scriptPath) {
479
+ return basename(scriptPath).replace(/\.[^.]+$/, "");
480
+ }
481
+ function installBinShim(dir, skillId, scriptPath) {
482
+ const home = resolve(dir, "home");
483
+ const skillsSubdir = mindSkillsDir(dir).slice(home.length + 1);
484
+ const binDir = join(dir, "home", ".local", "bin");
485
+ mkdirSync(binDir, { recursive: true });
486
+ const cmdName = binCommandName(scriptPath);
487
+ const shimPath = join(binDir, cmdName);
488
+ writeFileSync(shimPath, binShimContent(skillId, scriptPath, skillsSubdir), { mode: 493 });
489
+ }
490
+ function removeBinShim(dir, scriptPath) {
491
+ const cmdName = binCommandName(scriptPath);
492
+ const shimPath = join(dir, "home", ".local", "bin", cmdName);
493
+ if (existsSync(shimPath)) rmSync(shimPath);
494
+ }
355
495
  function listFilesRecursive(dir, prefix = "") {
356
496
  const results = [];
357
497
  for (const entry of readdirSync(dir, { withFileTypes: true })) {
@@ -420,16 +560,24 @@ export {
420
560
  getStandardSkillsWithExtensions,
421
561
  initDefaultSkills,
422
562
  sharedSkillsDir,
563
+ parseSkillMd,
423
564
  listSharedSkills,
424
565
  getSharedSkill,
425
566
  importSkillFromDir,
426
567
  removeSharedSkill,
568
+ mindSkillsDir,
569
+ readUpstream,
427
570
  installSkill,
428
571
  uninstallSkill,
429
572
  updateSkill,
430
573
  listMindSkills,
431
574
  publishSkill,
575
+ installHookShims,
576
+ removeHookShims,
577
+ installBinShim,
578
+ removeBinShim,
432
579
  listFilesRecursive,
580
+ findSkillsRoot,
433
581
  hashSkillDir,
434
582
  syncBuiltinSkills
435
583
  };
@@ -1,10 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // src/lib/template-hash.ts
4
- import { createHash } from "crypto";
5
- import { existsSync as existsSync2, readFileSync as readFileSync2, rmSync as rmSync2 } from "fs";
6
- import { resolve as resolve2 } from "path";
7
-
8
3
  // src/lib/template.ts
9
4
  import {
10
5
  cpSync,
@@ -110,39 +105,10 @@ function listFiles(dir) {
110
105
  return results;
111
106
  }
112
107
 
113
- // src/lib/template-hash.ts
114
- var hashCache = /* @__PURE__ */ new Map();
115
- function computeTemplateHash(templateName) {
116
- const cached = hashCache.get(templateName);
117
- if (cached) return cached;
118
- const templatesRoot = findTemplatesRoot();
119
- const baseDir = resolve2(templatesRoot, "_base");
120
- const templateDir = resolve2(templatesRoot, templateName);
121
- if (!existsSync2(baseDir)) throw new Error(`Base template not found: ${baseDir}`);
122
- if (!existsSync2(templateDir)) throw new Error(`Template not found: ${templateName}`);
123
- const { composedDir } = composeTemplate(templatesRoot, templateName);
124
- try {
125
- const files = listFiles(composedDir).filter((f) => !f.startsWith(".init/") && !f.startsWith(".init\\")).sort();
126
- const hash = createHash("sha256");
127
- for (const file of files) {
128
- const content = readFileSync2(resolve2(composedDir, file));
129
- hash.update(file);
130
- hash.update("\0");
131
- hash.update(content);
132
- }
133
- const result = hash.digest("hex");
134
- hashCache.set(templateName, result);
135
- return result;
136
- } finally {
137
- rmSync2(composedDir, { recursive: true, force: true });
138
- }
139
- }
140
-
141
108
  export {
142
109
  findTemplatesRoot,
143
110
  composeTemplate,
144
111
  copyTemplateToDir,
145
112
  applyInitFiles,
146
- listFiles,
147
- computeTemplateHash
113
+ listFiles
148
114
  };
@@ -6,11 +6,11 @@ function slugify(text) {
6
6
  }
7
7
  function buildVoluteSlug(opts) {
8
8
  if (opts.convType === "channel" && opts.convName) {
9
- return `volute:#${opts.convName}`;
9
+ return `#${opts.convName}`;
10
10
  }
11
11
  const other = opts.participants.find((p) => p.username !== opts.mindUsername);
12
12
  const otherSlug = other ? slugify(other.username) : "";
13
- return otherSlug ? `volute:@${otherSlug}` : `volute:${opts.conversationId}`;
13
+ return otherSlug ? `@${otherSlug}` : opts.conversationId;
14
14
  }
15
15
 
16
16
  export {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  mindDir,
4
4
  stateDir
5
- } from "./chunk-HHTXM4JT.js";
5
+ } from "./chunk-LRCG2JLP.js";
6
6
 
7
7
  // src/lib/archive.ts
8
8
  import { execFileSync } from "child_process";
@@ -91,12 +91,6 @@ function createExportArchive(options) {
91
91
  }
92
92
  }
93
93
  }
94
- if (existsSync(state)) {
95
- const channelsPath = resolve(state, "channels.json");
96
- if (existsSync(channelsPath)) {
97
- zip.addFile("state/channels.json", readFileSync(channelsPath));
98
- }
99
- }
100
94
  if (includeEnv && existsSync(state)) {
101
95
  const envPath = resolve(state, "env.json");
102
96
  if (existsSync(envPath)) {
@@ -184,14 +178,12 @@ function extractArchive(archivePath, destDir) {
184
178
  mkdirSync(resolve(destPath, ".."), { recursive: true });
185
179
  writeFileSync(destPath, entry.getData());
186
180
  }
187
- const channelsJson = resolve(extractedStateDir, "channels.json");
188
181
  const envJson = resolve(extractedStateDir, "env.json");
189
182
  const historyJsonl = resolve(normalizedDestDir, "history.jsonl");
190
183
  const sessionsDir = resolve(normalizedDestDir, "sessions");
191
184
  return {
192
185
  manifest,
193
186
  mindDir: extractedMindDir,
194
- channelsJson: existsSync(channelsJson) ? channelsJson : null,
195
187
  envJson: existsSync(envJson) ? envJson : null,
196
188
  historyJsonl: existsSync(historyJsonl) ? historyJsonl : null,
197
189
  sessionsDir: existsSync(sessionsDir) ? sessionsDir : null
@@ -5,36 +5,15 @@ import {
5
5
  import {
6
6
  readGlobalConfig,
7
7
  writeGlobalConfig
8
- } from "./chunk-7D47T4RB.js";
8
+ } from "./chunk-TSXLLQZW.js";
9
9
 
10
10
  // src/lib/ai-service.ts
11
- import {
12
- complete,
13
- getEnvApiKey,
14
- getModel,
15
- getModels,
16
- getOAuthApiKey,
17
- getProviders
18
- } from "@mariozechner/pi-ai";
11
+ import { complete, getEnvApiKey, getModel, getModels, getProviders } from "@mariozechner/pi-ai";
12
+ import { getOAuthApiKey } from "@mariozechner/pi-ai/oauth";
19
13
  var aiLog = logger_default.child("ai-service");
20
14
  function getAiConfig() {
21
15
  const config = readGlobalConfig();
22
- if (!config.ai) return null;
23
- const ai = config.ai;
24
- if ("provider" in ai && !("providers" in ai)) {
25
- const old = ai;
26
- const migrated = {
27
- providers: {
28
- [old.provider]: {
29
- ...old.apiKey ? { apiKey: old.apiKey } : {},
30
- ...old.oauth ? { oauth: old.oauth } : {}
31
- }
32
- }
33
- };
34
- writeGlobalConfig({ ...config, ai: migrated });
35
- return migrated;
36
- }
37
- return config.ai;
16
+ return config.ai ?? null;
38
17
  }
39
18
  function saveProviderConfig(providerId, providerConfig) {
40
19
  const ai = getAiConfig() ?? { providers: {} };
@@ -78,6 +57,47 @@ function getConfiguredProviders() {
78
57
  function isAiConfigured() {
79
58
  return getEnabledModels().length > 0;
80
59
  }
60
+ function getUtilityModel() {
61
+ const ai = getAiConfig();
62
+ return ai?.utilityModel;
63
+ }
64
+ function setUtilityModel(modelId) {
65
+ const ai = getAiConfig() ?? { providers: {} };
66
+ ai.utilityModel = modelId;
67
+ const config = readGlobalConfig();
68
+ writeGlobalConfig({ ...config, ai });
69
+ }
70
+ async function aiCompleteUtility(systemPrompt, userMessage) {
71
+ const utilityModel = getUtilityModel();
72
+ return aiComplete(systemPrompt, userMessage, utilityModel);
73
+ }
74
+ function templateForProvider(provider) {
75
+ if (provider === "anthropic") return "claude";
76
+ if (provider === "openai-codex") return "codex";
77
+ return "pi";
78
+ }
79
+ function resolveTemplate(modelId) {
80
+ if (!modelId) {
81
+ const enabled = getEnabledModels();
82
+ if (enabled.length > 0) {
83
+ const model2 = findModel(enabled[0]);
84
+ if (model2) return templateForProvider(model2.provider);
85
+ }
86
+ const providers = getConfiguredProviders();
87
+ if (providers.length === 1) return templateForProvider(providers[0]);
88
+ if (providers.length > 0 && !providers.includes("anthropic")) {
89
+ return templateForProvider(providers[0]);
90
+ }
91
+ return "claude";
92
+ }
93
+ if (modelId.includes(":")) {
94
+ const provider = modelId.split(":")[0];
95
+ return templateForProvider(provider);
96
+ }
97
+ const model = findModel(modelId);
98
+ if (model) return templateForProvider(model.provider);
99
+ return "claude";
100
+ }
81
101
  function getEnabledModels() {
82
102
  const ai = getAiConfig();
83
103
  return ai?.models ?? [];
@@ -95,7 +115,7 @@ function getAvailableModels() {
95
115
  try {
96
116
  models.push(...getModels(provider));
97
117
  } catch (err) {
98
- aiLog.debug(`no models for provider ${provider}`, logger_default.errorData(err));
118
+ aiLog.warn(`failed to load models for provider ${provider}`, logger_default.errorData(err));
99
119
  }
100
120
  }
101
121
  return models;
@@ -121,6 +141,16 @@ async function resolveApiKey(providerId) {
121
141
  if (providerConfig?.apiKey) return providerConfig.apiKey;
122
142
  return getEnvApiKey(providerId) ?? void 0;
123
143
  }
144
+ function qualifyModelId(modelId) {
145
+ if (modelId.includes(":")) return modelId;
146
+ const model = findModel(modelId);
147
+ if (model) return `${model.provider}:${model.id}`;
148
+ return modelId;
149
+ }
150
+ function unqualifyModelId(modelId) {
151
+ const idx = modelId.indexOf(":");
152
+ return idx >= 0 ? modelId.slice(idx + 1) : modelId;
153
+ }
124
154
  function findModel(modelId) {
125
155
  const providers = getConfiguredProviders();
126
156
  for (const provider of providers) {
@@ -154,6 +184,7 @@ async function aiComplete(systemPrompt, userMessage, modelId) {
154
184
  const model = modelId ? findModel(modelId) : autoSelectModel();
155
185
  if (!model) {
156
186
  if (modelId) aiLog.warn(`model not found: ${modelId}`);
187
+ else aiLog.debug("no enabled model available for auto-selection");
157
188
  return null;
158
189
  }
159
190
  try {
@@ -181,8 +212,15 @@ export {
181
212
  removeAiConfig,
182
213
  getConfiguredProviders,
183
214
  isAiConfigured,
215
+ getUtilityModel,
216
+ setUtilityModel,
217
+ aiCompleteUtility,
218
+ resolveTemplate,
184
219
  getEnabledModels,
185
220
  setEnabledModels,
186
221
  getAvailableModels,
222
+ resolveApiKey,
223
+ qualifyModelId,
224
+ unqualifyModelId,
187
225
  aiComplete
188
226
  };