volute 0.41.0 → 0.42.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 (138) hide show
  1. package/dist/{accept-AHAOUFBK.js → accept-7YVHZKRD.js} +1 -1
  2. package/dist/{activity-events-EQGBUEZ7.js → activity-events-KFKVRZE3.js} +2 -2
  3. package/dist/{ai-service-ZHEPFC3U.js → ai-service-3GBOJGUA.js} +11 -3
  4. package/dist/{archive-LJAXDDEY.js → archive-4PPYF7LL.js} +2 -2
  5. package/dist/{auth-VYW2ECCE.js → auth-EAASQPTN.js} +3 -3
  6. package/dist/{bridge-F3ZJEKDN.js → bridge-WPYSOQKR.js} +1 -1
  7. package/dist/{chat-FO722GU2.js → chat-7DOENBY2.js} +8 -8
  8. package/dist/{chunk-AXNAK3HT.js → chunk-2YRTSK5K.js} +7 -7
  9. package/dist/{chunk-VK2YD7VJ.js → chunk-4ZSUUBG5.js} +97 -2
  10. package/dist/{chunk-W5Z2H3LU.js → chunk-52NMCDBS.js} +290 -71
  11. package/dist/{chunk-6TPRURK5.js → chunk-5QG36RV7.js} +2 -2
  12. package/dist/{chunk-GMFCSXWB.js → chunk-62ICA2FF.js} +1 -1
  13. package/dist/{chunk-6ZAT5PYV.js → chunk-BLOAJLGI.js} +1 -1
  14. package/dist/{chunk-2I7OKOYV.js → chunk-CGPESELY.js} +2 -2
  15. package/dist/{chunk-FEQPNCXB.js → chunk-E7XWFDZL.js} +1 -1
  16. package/dist/{chunk-V67XMNGP.js → chunk-G777ME4L.js} +2 -2
  17. package/dist/{chunk-Y2XLASFJ.js → chunk-GN52E2DP.js} +1 -1
  18. package/dist/{chunk-ZX7EAV5J.js → chunk-IFNSAOA4.js} +9 -2
  19. package/dist/{chunk-VDODEQSJ.js → chunk-IUZ3EV2D.js} +4 -0
  20. package/dist/{chunk-JIGVTFIR.js → chunk-JLX3GC7T.js} +43 -14
  21. package/dist/{chunk-2RQIIKFC.js → chunk-K547QOCM.js} +1 -1
  22. package/dist/{chunk-OQ7UEW67.js → chunk-KUJVCDWT.js} +2 -2
  23. package/dist/chunk-KZAL7HEQ.js +141 -0
  24. package/dist/{chunk-GSOEUMVO.js → chunk-M2YMNTHK.js} +1 -1
  25. package/dist/{chunk-MU2B7A3L.js → chunk-OEJFZHZZ.js} +1 -1
  26. package/dist/{chunk-SWY4DJ67.js → chunk-OSUF75I7.js} +2 -2
  27. package/dist/{chunk-WSRGS4XP.js → chunk-QLWG3C2Z.js} +10 -0
  28. package/dist/{chunk-UU3Q65US.js → chunk-QMJCNZ6C.js} +1 -1
  29. package/dist/{chunk-CYUNO4BM.js → chunk-QPTQKGGF.js} +1 -1
  30. package/dist/{chunk-FU5YDH6Q.js → chunk-RKBYFLOR.js} +3 -3
  31. package/dist/{chunk-4ED2DBNC.js → chunk-TFBQESH7.js} +1 -1
  32. package/dist/{chunk-YATR5BXD.js → chunk-TKOWXAHG.js} +4 -4
  33. package/dist/{chunk-PP5CGT2P.js → chunk-VBKRZCR7.js} +1 -1
  34. package/dist/{chunk-YN6ISG7A.js → chunk-VSUZE2PD.js} +14 -13
  35. package/dist/{chunk-U7UASV36.js → chunk-WR7CSHQ4.js} +43 -10
  36. package/dist/{chunk-2R4JIZCB.js → chunk-YLTIEEVL.js} +2 -2
  37. package/dist/cli.js +22 -22
  38. package/dist/{clock-BMLJ2TR6.js → clock-HP2TGMG5.js} +3 -3
  39. package/dist/{cloud-sync-GV6O2HN2.js → cloud-sync-3OPHFOYQ.js} +17 -17
  40. package/dist/{config-QB7W3Z7P.js → config-W7MS3PWY.js} +3 -3
  41. package/dist/{conversations-KW7IYESK.js → conversations-FSZCUUYO.js} +3 -3
  42. package/dist/{create-C3BBFYV7.js → create-CJ2SR4EU.js} +1 -1
  43. package/dist/{create-CTPXWFTL.js → create-YNBZWD34.js} +2 -2
  44. package/dist/{daemon-client-2MIPKY3E.js → daemon-client-EWDPOOHC.js} +3 -1
  45. package/dist/{daemon-restart-W47YDE5E.js → daemon-restart-RAKGR56L.js} +7 -7
  46. package/dist/daemon.js +258 -302
  47. package/dist/{db-D4FVCA5I.js → db-ZJJJYJBU.js} +1 -1
  48. package/dist/{delete-NLXES2C7.js → delete-4ND5PLE7.js} +1 -1
  49. package/dist/delivery-manager-5Y35DOX3.js +33 -0
  50. package/dist/{delivery-router-Y66OXJPM.js → delivery-router-FDBZJQOY.js} +2 -2
  51. package/dist/{down-JVHNXOFU.js → down-DS6WCT34.js} +5 -5
  52. package/dist/echo-text-YP3JVLNA.js +32 -0
  53. package/dist/{env-IQ6Q2333.js → env-XX2MBZCZ.js} +1 -1
  54. package/dist/{exec-R2WWZ6FH.js → exec-ZDD7NEB4.js} +3 -3
  55. package/dist/{export-ZZ5WWBUH.js → export-5DOQV2WM.js} +3 -3
  56. package/dist/{extension-LZYHBNLV.js → extension-BCFYXI7A.js} +4 -1
  57. package/dist/{extensions-AGANCIQA.js → extensions-BTNIUS5J.js} +17 -17
  58. package/dist/{files-Q2Z4LQZP.js → files-K2MEMV3W.js} +3 -3
  59. package/dist/{import-MFYCBS4K.js → import-V6QEHMPQ.js} +7 -7
  60. package/dist/{isolation-7F3MA4G7.js → isolation-F7ABZMDA.js} +2 -2
  61. package/dist/{join-6SZCA5FX.js → join-4S3KT7NE.js} +1 -1
  62. package/dist/{list-KHJZJPEJ.js → list-XJB5WII6.js} +1 -1
  63. package/dist/{login-WY3DADVB.js → login-PHMTLNUF.js} +2 -2
  64. package/dist/{login-GYTH67ES.js → login-YWD6PUOT.js} +1 -1
  65. package/dist/{logout-TFZHWNVL.js → logout-BP3R3CAA.js} +2 -2
  66. package/dist/{logout-YHQLOFLR.js → logout-Q2WICH4V.js} +1 -1
  67. package/dist/message-delivery-FPIL26WV.js +41 -0
  68. package/dist/{mind-XIKEPJNS.js → mind-VXV6ZYZY.js} +18 -18
  69. package/dist/{mind-activity-tracker-RSIWUUJK.js → mind-activity-tracker-HWVFE533.js} +3 -3
  70. package/dist/{mind-history-WHCNZ6I5.js → mind-history-TDUQFYAG.js} +1 -1
  71. package/dist/{mind-list-H3HC2ZRG.js → mind-list-2T353Q5G.js} +1 -1
  72. package/dist/mind-manager-OYOIBGK6.js +33 -0
  73. package/dist/{mind-profile-7VYRJGFZ.js → mind-profile-2HHR7LZ7.js} +1 -1
  74. package/dist/mind-service-PR4PR4XI.js +37 -0
  75. package/dist/{mind-sleep-ZL5ZXFTM.js → mind-sleep-4NXV4J4U.js} +1 -1
  76. package/dist/{mind-status-ZWULKOUO.js → mind-status-CG66OXDK.js} +1 -1
  77. package/dist/{mind-wake-HK5ORGUK.js → mind-wake-TNB54DBR.js} +1 -1
  78. package/dist/{package-2X7UNSTQ.js → package-UWH5IM76.js} +2 -1
  79. package/dist/{read-CP7MYMJQ.js → read-JLR4NQXU.js} +1 -1
  80. package/dist/{register-XOBFEMI4.js → register-IQ2M4UO6.js} +1 -1
  81. package/dist/{registry-RAXNFN7K.js → registry-MDLNPTTI.js} +3 -1
  82. package/dist/{reject-43AGXB6B.js → reject-N2D4CZND.js} +1 -1
  83. package/dist/{restart-O5QIYQJT.js → restart-43A5MBGV.js} +1 -1
  84. package/dist/{sandbox-O3GZTS7J.js → sandbox-E7RWZDVG.js} +7 -3
  85. package/dist/scheduler-KXUY2I7W.js +31 -0
  86. package/dist/{seed-I4CNKTKZ.js → seed-YQAOIXIY.js} +1 -1
  87. package/dist/{seed-check-HZPVFJKZ.js → seed-check-N5ALJBT6.js} +1 -1
  88. package/dist/{seed-cmd-YTQYWCZF.js → seed-cmd-7KJS4LCA.js} +3 -3
  89. package/dist/{seed-create-MDBTVADS.js → seed-create-Z7NDRRGP.js} +4 -4
  90. package/dist/{seed-sprout-N6O5FBPY.js → seed-sprout-PYDMVVUL.js} +8 -8
  91. package/dist/{send-5XA7LRNB.js → send-KQECN2EL.js} +3 -3
  92. package/dist/{service-AY5TGWJX.js → service-Q5OVY5AK.js} +4 -4
  93. package/dist/{service-install-NLGAVTQS.js → service-install-GTDUHP6R.js} +5 -5
  94. package/dist/{setup-3434PQ5Q.js → setup-IYOUPCIK.js} +6 -2
  95. package/dist/{setup-47NBOCZL.js → setup-VARJ7N6Z.js} +7 -7
  96. package/dist/{skill-ICN6Y2ZF.js → skill-E43BI34Y.js} +1 -1
  97. package/dist/skills/imagegen/scripts/imagegen.ts +1 -1
  98. package/dist/{skills-YTLBAF32.js → skills-YBCYVOPQ.js} +5 -5
  99. package/dist/sleep-manager-FJLASHHW.js +35 -0
  100. package/dist/{spirit-KTBHLULO.js → spirit-NJFAY5CZ.js} +8 -8
  101. package/dist/{split-5YBEQTBF.js → split-5IBUODEE.js} +1 -1
  102. package/dist/{sprout-4ZUJUNDQ.js → sprout-B27C2WGE.js} +1 -1
  103. package/dist/{src-OYWRPLC6.js → src-L2Z7X5UT.js} +5 -8
  104. package/dist/{src-4LFGGNW7.js → src-TJ7RBU5H.js} +2 -12
  105. package/dist/{start-LMXXRR3X.js → start-5AYFGNS7.js} +1 -1
  106. package/dist/{status-VMOZUIZ2.js → status-ECZHHSY5.js} +5 -5
  107. package/dist/{stop-TWDKVEUX.js → stop-WJ6IG6OK.js} +1 -1
  108. package/dist/system-chat-P6KVGW4T.js +35 -0
  109. package/dist/{systems-Y2WZV2K4.js → systems-5MA57Q7G.js} +4 -4
  110. package/dist/{tailscale-PK3AI5EV.js → tailscale-TIRTGM6E.js} +1 -1
  111. package/dist/{template-hash-JARTCRGS.js → template-hash-446HHH5V.js} +2 -2
  112. package/dist/{turn-tracker-SZBSL7LK.js → turn-tracker-W4TASMR7.js} +4 -4
  113. package/dist/{up-VGVPOB6J.js → up-POJX6S5Y.js} +6 -6
  114. package/dist/{update-3ANTQO54.js → update-OPR4KU4M.js} +5 -5
  115. package/dist/{update-check-4O6DKUOF.js → update-check-OG27AL4Z.js} +2 -2
  116. package/dist/{upgrade-RXFZR5FI.js → upgrade-QB7AHIKX.js} +1 -1
  117. package/dist/{version-notify-SSNAWZMX.js → version-notify-TCKAX7ZA.js} +19 -19
  118. package/dist/web-assets/assets/{index-DaUp9iE2.js → index-CrFAsfiE.js} +10 -10
  119. package/dist/web-assets/assets/{index-DqHSW9Fr.css → index-D7udpBCx.css} +1 -1
  120. package/dist/web-assets/index.html +2 -2
  121. package/package.json +2 -1
  122. package/packages/extensions/plan/skills/plan/scripts/plan-hook.sh +2 -2
  123. package/templates/_base/.init/.config/hooks/pre-prompt/session-activity.ts +3 -3
  124. package/templates/_base/.init/.local/hooks/pre-prompt/notices.ts +3 -3
  125. package/templates/_base/.init/.local/hooks/pre-prompt/session-activity.ts +3 -3
  126. package/templates/_base/src/lib/daemon-client.ts +1 -1
  127. package/templates/_base/src/lib/volute-server.ts +1 -1
  128. package/templates/codex/src/server.ts +8 -2
  129. package/templates/pi/src/lib/resolve-model.ts +50 -12
  130. package/dist/chunk-N64Q7FMP.js +0 -70
  131. package/dist/delivery-manager-EB52CQ5X.js +0 -33
  132. package/dist/echo-text-QVPS6QDM.js +0 -32
  133. package/dist/message-delivery-X4CZE2L6.js +0 -41
  134. package/dist/mind-manager-VU3RGCXD.js +0 -31
  135. package/dist/mind-service-L7LMMDYJ.js +0 -37
  136. package/dist/scheduler-SXELVRWO.js +0 -31
  137. package/dist/sleep-manager-T3AXQB3R.js +0 -35
  138. package/dist/system-chat-HCPHUQGI.js +0 -35
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-BTY4WNFE.js";
5
5
  import {
6
6
  daemonFetch
7
- } from "./chunk-ZX7EAV5J.js";
7
+ } from "./chunk-IFNSAOA4.js";
8
8
  import {
9
9
  command
10
10
  } from "./chunk-TXSA4Q3V.js";
@@ -3,9 +3,9 @@ import {
3
3
  broadcast,
4
4
  publish,
5
5
  subscribe
6
- } from "./chunk-2RQIIKFC.js";
6
+ } from "./chunk-K547QOCM.js";
7
7
  import "./chunk-T2TP6ZC6.js";
8
- import "./chunk-VDODEQSJ.js";
8
+ import "./chunk-IUZ3EV2D.js";
9
9
  import "./chunk-MHFAWJCC.js";
10
10
  import "./chunk-K3NQKI34.js";
11
11
  export {
@@ -1,16 +1,20 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ addCustomModel,
3
4
  aiComplete,
4
5
  aiCompleteUtility,
6
+ buildCustomModel,
5
7
  fireProviderRefreshHook,
6
8
  getAiConfig,
7
9
  getAvailableModels,
8
10
  getConfiguredProviders,
11
+ getCustomModels,
9
12
  getEnabledModels,
10
13
  getUtilityModel,
11
14
  isAiConfigured,
12
15
  qualifyModelId,
13
16
  removeAiConfig,
17
+ removeCustomModel,
14
18
  removeProviderConfig,
15
19
  resolveApiKey,
16
20
  resolveTemplate,
@@ -19,24 +23,28 @@ import {
19
23
  setProviderRefreshHook,
20
24
  setUtilityModel,
21
25
  unqualifyModelId
22
- } from "./chunk-VK2YD7VJ.js";
23
- import "./chunk-N64Q7FMP.js";
26
+ } from "./chunk-4ZSUUBG5.js";
27
+ import "./chunk-KZAL7HEQ.js";
24
28
  import "./chunk-T2TP6ZC6.js";
25
- import "./chunk-VDODEQSJ.js";
29
+ import "./chunk-IUZ3EV2D.js";
26
30
  import "./chunk-MHFAWJCC.js";
27
31
  import "./chunk-K3NQKI34.js";
28
32
  export {
33
+ addCustomModel,
29
34
  aiComplete,
30
35
  aiCompleteUtility,
36
+ buildCustomModel,
31
37
  fireProviderRefreshHook,
32
38
  getAiConfig,
33
39
  getAvailableModels,
34
40
  getConfiguredProviders,
41
+ getCustomModels,
35
42
  getEnabledModels,
36
43
  getUtilityModel,
37
44
  isAiConfigured,
38
45
  qualifyModelId,
39
46
  removeAiConfig,
47
+ removeCustomModel,
40
48
  removeProviderConfig,
41
49
  resolveApiKey,
42
50
  resolveTemplate,
@@ -5,8 +5,8 @@ import {
5
5
  extractArchive,
6
6
  isHomeOnlyArchive,
7
7
  readManifest
8
- } from "./chunk-MU2B7A3L.js";
9
- import "./chunk-VDODEQSJ.js";
8
+ } from "./chunk-OEJFZHZZ.js";
9
+ import "./chunk-IUZ3EV2D.js";
10
10
  import "./chunk-MHFAWJCC.js";
11
11
  import "./chunk-K3NQKI34.js";
12
12
  export {
@@ -17,10 +17,10 @@ import {
17
17
  syncMindProfile,
18
18
  updateUserProfile,
19
19
  verifyUser
20
- } from "./chunk-6TPRURK5.js";
21
- import "./chunk-2RQIIKFC.js";
20
+ } from "./chunk-5QG36RV7.js";
21
+ import "./chunk-K547QOCM.js";
22
22
  import "./chunk-T2TP6ZC6.js";
23
- import "./chunk-VDODEQSJ.js";
23
+ import "./chunk-IUZ3EV2D.js";
24
24
  import "./chunk-MHFAWJCC.js";
25
25
  import "./chunk-K3NQKI34.js";
26
26
  export {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  daemonFetch
4
- } from "./chunk-ZX7EAV5J.js";
4
+ } from "./chunk-IFNSAOA4.js";
5
5
  import {
6
6
  command,
7
7
  subcommands
@@ -12,35 +12,35 @@ var cmd = subcommands({
12
12
  commands: {
13
13
  send: {
14
14
  description: "Send a message",
15
- run: (args) => import("./send-5XA7LRNB.js").then((m) => m.run(args))
15
+ run: (args) => import("./send-KQECN2EL.js").then((m) => m.run(args))
16
16
  },
17
17
  list: {
18
18
  description: "List conversations",
19
- run: (args) => import("./list-KHJZJPEJ.js").then((m) => m.run(args))
19
+ run: (args) => import("./list-XJB5WII6.js").then((m) => m.run(args))
20
20
  },
21
21
  read: {
22
22
  description: "Read conversation messages",
23
- run: (args) => import("./read-CP7MYMJQ.js").then((m) => m.run(args))
23
+ run: (args) => import("./read-JLR4NQXU.js").then((m) => m.run(args))
24
24
  },
25
25
  create: {
26
26
  description: "Create a conversation",
27
- run: (args) => import("./create-C3BBFYV7.js").then((m) => m.run(args))
27
+ run: (args) => import("./create-CJ2SR4EU.js").then((m) => m.run(args))
28
28
  },
29
29
  bridge: {
30
30
  description: "Manage platform bridges",
31
- run: (args) => import("./bridge-F3ZJEKDN.js").then((m) => m.run(args))
31
+ run: (args) => import("./bridge-WPYSOQKR.js").then((m) => m.run(args))
32
32
  },
33
33
  files: {
34
34
  description: "List pending incoming files",
35
- run: (args) => import("./files-Q2Z4LQZP.js").then((m) => m.run(args))
35
+ run: (args) => import("./files-K2MEMV3W.js").then((m) => m.run(args))
36
36
  },
37
37
  accept: {
38
38
  description: "Accept a pending file",
39
- run: (args) => import("./accept-AHAOUFBK.js").then((m) => m.run(args))
39
+ run: (args) => import("./accept-7YVHZKRD.js").then((m) => m.run(args))
40
40
  },
41
41
  reject: {
42
42
  description: "Reject a pending file",
43
- run: (args) => import("./reject-43AGXB6B.js").then((m) => m.run(args))
43
+ run: (args) => import("./reject-N2D4CZND.js").then((m) => m.run(args))
44
44
  }
45
45
  },
46
46
  footer: "Use --mind <name> or VOLUTE_MIND to identify the mind."
@@ -2,14 +2,14 @@
2
2
  import {
3
3
  findBridgeForChannel,
4
4
  getBridgeConfig
5
- } from "./chunk-CYUNO4BM.js";
5
+ } from "./chunk-QPTQKGGF.js";
6
6
  import {
7
7
  recordOutbound
8
- } from "./chunk-W5Z2H3LU.js";
8
+ } from "./chunk-52NMCDBS.js";
9
9
  import {
10
10
  readEnv,
11
11
  sharedEnvPath
12
- } from "./chunk-6ZAT5PYV.js";
12
+ } from "./chunk-BLOAJLGI.js";
13
13
  import {
14
14
  addMessage,
15
15
  findDMConversation,
@@ -17,17 +17,17 @@ import {
17
17
  getChannelName,
18
18
  getConversation,
19
19
  getParticipants
20
- } from "./chunk-2R4JIZCB.js";
20
+ } from "./chunk-YLTIEEVL.js";
21
21
  import {
22
22
  readVoluteConfig
23
23
  } from "./chunk-CU6OFXMM.js";
24
24
  import {
25
25
  publish
26
- } from "./chunk-YATR5BXD.js";
26
+ } from "./chunk-TKOWXAHG.js";
27
27
  import {
28
28
  getOrCreateMindUser,
29
29
  getUserByUsername
30
- } from "./chunk-6TPRURK5.js";
30
+ } from "./chunk-5QG36RV7.js";
31
31
  import {
32
32
  logger_default
33
33
  } from "./chunk-T2TP6ZC6.js";
@@ -37,7 +37,7 @@ import {
37
37
  import {
38
38
  mindDir,
39
39
  voluteSystemDir
40
- } from "./chunk-VDODEQSJ.js";
40
+ } from "./chunk-IUZ3EV2D.js";
41
41
  import {
42
42
  __export
43
43
  } from "./chunk-K3NQKI34.js";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  readGlobalConfig,
4
4
  writeGlobalConfig
5
- } from "./chunk-N64Q7FMP.js";
5
+ } from "./chunk-KZAL7HEQ.js";
6
6
  import {
7
7
  logger_default
8
8
  } from "./chunk-T2TP6ZC6.js";
@@ -141,11 +141,96 @@ function setEnabledModels(modelIds) {
141
141
  const config = readGlobalConfig();
142
142
  writeGlobalConfig({ ...config, ai });
143
143
  }
144
+ function getCustomModels() {
145
+ return getAiConfig()?.customModels ?? [];
146
+ }
147
+ function addCustomModel(provider, id, name) {
148
+ const ai = getAiConfig() ?? { providers: {} };
149
+ const customModels = ai.customModels ?? [];
150
+ if (!customModels.some((m) => m.provider === provider && m.id === id)) {
151
+ customModels.push({ provider, id, ...name ? { name } : {} });
152
+ }
153
+ ai.customModels = customModels;
154
+ const config = readGlobalConfig();
155
+ writeGlobalConfig({ ...config, ai });
156
+ }
157
+ function removeCustomModel(provider, id) {
158
+ const ai = getAiConfig();
159
+ if (!ai) return;
160
+ const customModels = (ai.customModels ?? []).filter(
161
+ (m) => !(m.provider === provider && m.id === id)
162
+ );
163
+ ai.customModels = customModels.length > 0 ? customModels : void 0;
164
+ if (!ai.customModels) delete ai.customModels;
165
+ if (ai.models) {
166
+ ai.models = ai.models.filter((mid) => mid !== id);
167
+ if (ai.models.length === 0) delete ai.models;
168
+ }
169
+ const config = readGlobalConfig();
170
+ writeGlobalConfig({ ...config, ai });
171
+ }
172
+ function sharedPrefixLength(a, b) {
173
+ let i = 0;
174
+ while (i < a.length && i < b.length && a[i] === b[i]) i++;
175
+ return i;
176
+ }
177
+ function pickSibling(provider, id) {
178
+ const siblings = getBuiltinModels(provider);
179
+ if (siblings.length === 0) return void 0;
180
+ let best = siblings[0];
181
+ let bestPrefix = -1;
182
+ for (const s of siblings) {
183
+ const prefix = sharedPrefixLength(s.id, id);
184
+ if (prefix > bestPrefix || prefix === bestPrefix && s.contextWindow > best.contextWindow) {
185
+ bestPrefix = prefix;
186
+ best = s;
187
+ }
188
+ }
189
+ return best;
190
+ }
191
+ function buildCustomModel(provider, id, name) {
192
+ const sibling = pickSibling(provider, id);
193
+ if (!sibling) return void 0;
194
+ return {
195
+ ...sibling,
196
+ id,
197
+ name: name ?? id,
198
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }
199
+ };
200
+ }
201
+ function pruneAbsorbedCustomModels() {
202
+ const ai = getAiConfig();
203
+ const custom = ai?.customModels ?? [];
204
+ if (custom.length === 0 || !ai) return custom;
205
+ const kept = custom.filter((cm) => !getBuiltinModel(cm.provider, cm.id));
206
+ if (kept.length !== custom.length) {
207
+ ai.customModels = kept.length > 0 ? kept : void 0;
208
+ if (!ai.customModels) delete ai.customModels;
209
+ const config = readGlobalConfig();
210
+ writeGlobalConfig({ ...config, ai });
211
+ }
212
+ return kept;
213
+ }
144
214
  async function getAvailableModels() {
145
215
  const providers = await getConfiguredProviders();
216
+ const configured = new Set(providers);
146
217
  const result = [];
218
+ const seen = /* @__PURE__ */ new Set();
147
219
  for (const provider of providers) {
148
- result.push(...getBuiltinModels(provider));
220
+ for (const m of getBuiltinModels(provider)) {
221
+ result.push(m);
222
+ seen.add(m.id);
223
+ }
224
+ }
225
+ for (const cm of pruneAbsorbedCustomModels()) {
226
+ if (!configured.has(cm.provider) || seen.has(cm.id)) continue;
227
+ const built = buildCustomModel(cm.provider, cm.id, cm.name);
228
+ if (built) {
229
+ result.push(built);
230
+ seen.add(cm.id);
231
+ } else {
232
+ aiLog.warn(`custom model ${cm.provider}:${cm.id} has no sibling to clone from; skipping`);
233
+ }
149
234
  }
150
235
  return result;
151
236
  }
@@ -185,6 +270,12 @@ function findModel(modelId) {
185
270
  const model = getBuiltinModel(provider, modelId);
186
271
  if (model) return model;
187
272
  }
273
+ for (const cm of getCustomModels()) {
274
+ if (cm.id === modelId) {
275
+ const built = buildCustomModel(cm.provider, cm.id, cm.name);
276
+ if (built) return built;
277
+ }
278
+ }
188
279
  for (const provider of getBuiltinProviders()) {
189
280
  const found = getBuiltinModels(provider).find((m) => m.id.startsWith(modelId));
190
281
  if (found) return found;
@@ -240,6 +331,10 @@ export {
240
331
  resolveTemplate,
241
332
  getEnabledModels,
242
333
  setEnabledModels,
334
+ getCustomModels,
335
+ addCustomModel,
336
+ removeCustomModel,
337
+ buildCustomModel,
243
338
  getAvailableModels,
244
339
  resolveApiKey,
245
340
  qualifyModelId,