@xopcai/xopc 0.0.119 → 0.0.121

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 (286) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/dashscope/src/image-generation-provider.d.ts +6 -5
  3. package/dist/extensions/dashscope/src/image-generation-provider.js +40 -64
  4. package/dist/extensions/dashscope/src/image-generation-provider.js.map +1 -1
  5. package/dist/extensions/dashscope/src/index.d.ts +1 -1
  6. package/dist/extensions/dashscope/src/index.js +2 -2
  7. package/dist/extensions/dashscope/xopc.extension.json +3 -2
  8. package/dist/extensions/minimax/src/image-generation-provider.d.ts +7 -5
  9. package/dist/extensions/minimax/src/image-generation-provider.js +43 -37
  10. package/dist/extensions/minimax/src/image-generation-provider.js.map +1 -1
  11. package/dist/extensions/minimax/src/index.d.ts +1 -1
  12. package/dist/extensions/minimax/src/index.js +2 -2
  13. package/dist/extensions/minimax/xopc.extension.json +1 -1
  14. package/dist/extensions/telegram/xopc.extension.json +1 -1
  15. package/dist/gateway/static/root/assets/Combination-HAlzriaz.js +41 -0
  16. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CU8J6zou.js → agent-avatar-dicebear-4AW4JgSU.js} +1 -1
  17. package/dist/gateway/static/root/assets/agents-2SVUUPlp.js +2 -0
  18. package/dist/gateway/static/root/assets/{app-management-settings-panel-B9vfYoEr.js → app-management-settings-panel-CE6GkGU2.js} +1 -1
  19. package/dist/gateway/static/root/assets/{appearance-settings-ClOzIO24.js → appearance-settings-BmaUjghw.js} +1 -1
  20. package/dist/gateway/static/root/assets/{apps-page-DU0dz9Zo.js → apps-page-BWeQ1I49.js} +1 -1
  21. package/dist/gateway/static/root/assets/{archive-plugin-BkVIgZzA.js → archive-plugin-CX4_KWut.js} +1 -1
  22. package/dist/gateway/static/root/assets/{attachment-load-CaCMWh1D.js → attachment-load-jf-PIIUU.js} +1 -1
  23. package/dist/gateway/static/root/assets/{automation-suggestion-card-DhGDpKP3.js → automation-suggestion-card-BHk5rtJz.js} +1 -1
  24. package/dist/gateway/static/root/assets/automations-page-QHotl53D.js +1 -0
  25. package/dist/gateway/static/root/assets/{binary-plugins-B4TO_bsn.js → binary-plugins-DG9XQikd.js} +1 -1
  26. package/dist/gateway/static/root/assets/{block-editor-DJRWwWNI.js → block-editor-Up_VIxLJ.js} +6 -6
  27. package/dist/gateway/static/root/assets/browser-settings-page-Cmwi6IIQ.js +8 -0
  28. package/dist/gateway/static/root/assets/{capability-presets-api-Befi89CL.js → capability-presets-api-CGM4OyMw.js} +1 -1
  29. package/dist/gateway/static/root/assets/{capability-presets-settings-panel-_G8eb2vJ.js → capability-presets-settings-panel-CzWt0LBb.js} +1 -1
  30. package/dist/gateway/static/root/assets/{channel-recipient-api-BNSuJb5f.js → channel-recipient-api-BEByL4_o.js} +1 -1
  31. package/dist/gateway/static/root/assets/channels-settings-BOMCUe2J.js +1 -0
  32. package/dist/gateway/static/root/assets/connectors-page-C-Dexk_F.js +2 -0
  33. package/dist/gateway/static/root/assets/dist-Mys7eFJ5.js +1 -0
  34. package/dist/gateway/static/root/assets/dist-wO9a2_ID.js +1 -0
  35. package/dist/gateway/static/root/assets/dreaming-settings-WPEj8pir.js +1 -0
  36. package/dist/gateway/static/root/assets/{extension-debug-page-DYh402XV.js → extension-debug-page-DZxa_j7-.js} +1 -1
  37. package/dist/gateway/static/root/assets/{extension-page-Cr_TizrN.js → extension-page-CseziW53.js} +1 -1
  38. package/dist/gateway/static/root/assets/extension-settings-page-B_9J-xyo.js +1 -0
  39. package/dist/gateway/static/root/assets/{fetch-Y7AEX4H3.js → fetch-Cs4ck8zA.js} +1 -1
  40. package/dist/gateway/static/root/assets/{gateway-config-api-RbMmAOpX.js → gateway-config-api-Dl223a7r.js} +1 -1
  41. package/dist/gateway/static/root/assets/gateway-settings-DdzbtW9R.js +1 -0
  42. package/dist/gateway/static/root/assets/{gateway-startup-retry-DiD_Tx4N.js → gateway-startup-retry-IvePwjFE.js} +1 -1
  43. package/dist/gateway/static/root/assets/goal-detail-page-Dxldogms.js +1 -0
  44. package/dist/gateway/static/root/assets/{goals-config-api-DqxVi0p5.js → goals-config-api-CUCP6yCl.js} +1 -1
  45. package/dist/gateway/static/root/assets/goals-page-DU5Nd6Xp.js +2 -0
  46. package/dist/gateway/static/root/assets/goals-settings-Dj87qPxv.js +1 -0
  47. package/dist/gateway/static/root/assets/heartbeat-settings-Cgm5JmwH.js +1 -0
  48. package/dist/gateway/static/root/assets/index-BU1pvxmS.js +191 -0
  49. package/dist/gateway/static/root/assets/index-l54WfSqe.css +1 -0
  50. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-Dvg53qnd.js → keyboard-shortcuts-settings-DJgYw0nB.js} +1 -1
  51. package/dist/gateway/static/root/assets/{locale-store-DjbfSsfA.js → locale-store-Ba72bFmP.js} +1 -1
  52. package/dist/gateway/static/root/assets/logs-page-C10aS4XO.js +2 -0
  53. package/dist/gateway/static/root/assets/{markdown-split-CpHxbtWJ.js → markdown-split-gnQ_EiGo.js} +1 -1
  54. package/dist/gateway/static/root/assets/{media-plugins-SFPQRSxq.js → media-plugins-CQV-mgJn.js} +1 -1
  55. package/dist/gateway/static/root/assets/messages-C6Kc4Jhf.js +3 -0
  56. package/dist/gateway/static/root/assets/models-hub-panel-B35CAfg6.js +2 -0
  57. package/dist/gateway/static/root/assets/note-detail-page-Brlwse8x.js +2 -0
  58. package/dist/gateway/static/root/assets/{note-image-lightbox-BUYURRgn.js → note-image-lightbox-BthwKjLA.js} +1 -1
  59. package/dist/gateway/static/root/assets/{notes-page-BsIBSFyZ.js → notes-page-CoAwRc7L.js} +1 -1
  60. package/dist/gateway/static/root/assets/{preview-open-alternatives-BHz9iWYA.js → preview-open-alternatives-BPMXC-2u.js} +1 -1
  61. package/dist/gateway/static/root/assets/remote-access-hub-B36RQ05h.js +1 -0
  62. package/dist/gateway/static/root/assets/{save-bar-controls-CefkOlRg.js → save-bar-controls-BEHqwZjz.js} +1 -1
  63. package/dist/gateway/static/root/assets/schedule-field-CMY25m97.js +1 -0
  64. package/dist/gateway/static/root/assets/schema-form-CxjxsFfg.js +1 -0
  65. package/dist/gateway/static/root/assets/sessions-page-73THChnj.js +1 -0
  66. package/dist/gateway/static/root/assets/settings-advanced-gate-CR9VsY-R.js +1 -0
  67. package/dist/gateway/static/root/assets/{settings-collapsible-section-BouO6JTi.js → settings-collapsible-section-s-kiLAxP.js} +1 -1
  68. package/dist/gateway/static/root/assets/settings-form-section-CIxIEYxU.js +1 -0
  69. package/dist/gateway/static/root/assets/settings-page-BJ1AhfKI.js +1 -0
  70. package/dist/gateway/static/root/assets/{settings-page-layout-BJ4Gsef5.js → settings-page-layout--6qT7ZJa.js} +1 -1
  71. package/dist/gateway/static/root/assets/{setup-status-panel-CrUjHPQo.js → setup-status-panel-C1TtS1vJ.js} +1 -1
  72. package/dist/gateway/static/root/assets/{share-preview-page-BDy2btRN.js → share-preview-page-BZADSbS1.js} +1 -1
  73. package/dist/gateway/static/root/assets/shares-settings-gqC8Rmhy.js +1 -0
  74. package/dist/gateway/static/root/assets/skill-reload-api-C9P-WYvS.js +1 -0
  75. package/dist/gateway/static/root/assets/skills-page-CEpSvOhF.js +2 -0
  76. package/dist/gateway/static/root/assets/{system-settings-panel-CRngrlnZ.js → system-settings-panel-Czjf0kLJ.js} +1 -1
  77. package/dist/gateway/static/root/assets/{theme-store-CD2wtgZV.js → theme-store-Bt6vAkSB.js} +1 -1
  78. package/dist/gateway/static/root/assets/{typed-models-lib-BltBc0b-.js → typed-models-lib-Cmt8SYdI.js} +1 -1
  79. package/dist/gateway/static/root/assets/{use-channel-catalog-CjN-51e6.js → use-channel-catalog-DyM-ckEQ.js} +1 -1
  80. package/dist/gateway/static/root/assets/user-profile-settings-panel-BygLv8vm.js +1 -0
  81. package/dist/gateway/static/root/assets/{utils-B5M5-YvK.js → utils-CloW8coB.js} +1 -1
  82. package/dist/gateway/static/root/assets/voice-api-key-field-BsoqJba6.js +1 -0
  83. package/dist/gateway/static/root/assets/{voice-player-store-B7ykUlHM.js → voice-player-store-DduWlJYV.js} +1 -1
  84. package/dist/gateway/static/root/assets/workflow-run-setup-panel-CcQeX6l5.js +3 -0
  85. package/dist/gateway/static/root/assets/workflows-page-CeA8A9Ef.js +18 -0
  86. package/dist/gateway/static/root/index.html +9 -10
  87. package/dist/package.js +1 -1
  88. package/dist/src/agent/context/workspace-templates/AGENTS.md +3 -2
  89. package/dist/src/agent/embedded/xopc-auth-storage.d.ts +1 -5
  90. package/dist/src/agent/embedded/xopc-auth-storage.js +2 -8
  91. package/dist/src/agent/embedded/xopc-auth-storage.js.map +1 -1
  92. package/dist/src/agent/embedded/xopc-tools-bridge.js +23 -0
  93. package/dist/src/agent/embedded/xopc-tools-bridge.js.map +1 -1
  94. package/dist/src/agent/goals/checklist-judge.js +1 -1
  95. package/dist/src/agent/goals/checklist-judge.js.map +1 -1
  96. package/dist/src/agent/goals/judge.js +1 -1
  97. package/dist/src/agent/goals/judge.js.map +1 -1
  98. package/dist/src/agent/image/tool-model-config.d.ts +2 -0
  99. package/dist/src/agent/image/tool-model-config.js +2 -2
  100. package/dist/src/agent/image/tool-model-config.js.map +1 -1
  101. package/dist/src/agent/image/understanding/pi-ai-provider.js +1 -1
  102. package/dist/src/agent/image/understanding/pi-ai-provider.js.map +1 -1
  103. package/dist/src/agent/memory/builtin-memory-store.d.ts +1 -1
  104. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  105. package/dist/src/agent/memory/builtin-memory-store.js.map +1 -1
  106. package/dist/src/agent/memory/builtin-provider.d.ts +2 -2
  107. package/dist/src/agent/memory/builtin-provider.js +2 -2
  108. package/dist/src/agent/memory/builtin-provider.js.map +1 -1
  109. package/dist/src/agent/memory/compaction.d.ts +1 -1
  110. package/dist/src/agent/memory/compaction.js +1 -1
  111. package/dist/src/agent/memory/compaction.js.map +1 -1
  112. package/dist/src/agent/memory/dreaming/light-sweep.d.ts +0 -7
  113. package/dist/src/agent/memory/dreaming/light-sweep.js +16 -277
  114. package/dist/src/agent/memory/dreaming/light-sweep.js.map +1 -1
  115. package/dist/src/agent/memory/dreaming/rem-patterns.d.ts +1 -1
  116. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  117. package/dist/src/agent/memory/dreaming/rem-patterns.js.map +1 -1
  118. package/dist/src/agent/memory/dreaming/short-term-store.d.ts +3 -3
  119. package/dist/src/agent/memory/dreaming/short-term-store.js +5 -5
  120. package/dist/src/agent/memory/dreaming/short-term-store.js.map +1 -1
  121. package/dist/src/agent/memory/dreaming/utils.d.ts +2 -2
  122. package/dist/src/agent/memory/dreaming/utils.js +2 -2
  123. package/dist/src/agent/memory/dreaming/utils.js.map +1 -1
  124. package/dist/src/agent/memory/index.d.ts +0 -2
  125. package/dist/src/agent/memory/index.js +1 -2
  126. package/dist/src/agent/middleware/self-verify.d.ts +3 -0
  127. package/dist/src/agent/middleware/self-verify.js +18 -0
  128. package/dist/src/agent/middleware/self-verify.js.map +1 -1
  129. package/dist/src/agent/orchestration/agent-event-handler.js +28 -3
  130. package/dist/src/agent/orchestration/agent-event-handler.js.map +1 -1
  131. package/dist/src/agent/prompt/sections/memory-skills.js +11 -10
  132. package/dist/src/agent/prompt/sections/memory-skills.js.map +1 -1
  133. package/dist/src/agent/prompt/sections/tooling.js +23 -7
  134. package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
  135. package/dist/src/agent/prompt/service-prompt-builder.js +1 -0
  136. package/dist/src/agent/prompt/service-prompt-builder.js.map +1 -1
  137. package/dist/src/agent/prompt/system-prompt.d.ts +1 -0
  138. package/dist/src/agent/prompt/system-prompt.js +13 -1
  139. package/dist/src/agent/prompt/system-prompt.js.map +1 -1
  140. package/dist/src/agent/reply/startup-context.js +6 -105
  141. package/dist/src/agent/reply/startup-context.js.map +1 -1
  142. package/dist/src/agent/sandbox/path-policy.js +30 -6
  143. package/dist/src/agent/sandbox/path-policy.js.map +1 -1
  144. package/dist/src/agent/service/btw-query.js +1 -1
  145. package/dist/src/agent/service/btw-query.js.map +1 -1
  146. package/dist/src/agent/service.d.ts +0 -3
  147. package/dist/src/agent/service.js +0 -41
  148. package/dist/src/agent/service.js.map +1 -1
  149. package/dist/src/agent/starter-agents.js +16 -16
  150. package/dist/src/agent/starter-agents.js.map +1 -1
  151. package/dist/src/agent/tools/image-generate-tool.js +12 -1
  152. package/dist/src/agent/tools/image-generate-tool.js.map +1 -1
  153. package/dist/src/agent/tools/memory-tool.js +2 -2
  154. package/dist/src/agent/tools/memory-tool.js.map +1 -1
  155. package/dist/src/agent/tools/session-search-tool.js +1 -1
  156. package/dist/src/agent/tools/session-search-tool.js.map +1 -1
  157. package/dist/src/agent/tools/web-extract.js +1 -1
  158. package/dist/src/agent/tools/web-extract.js.map +1 -1
  159. package/dist/src/agent-manifest/index.js +2 -2
  160. package/dist/src/agent-manifest/schema.d.ts +66 -0
  161. package/dist/src/agent-manifest/schema.js +28 -2
  162. package/dist/src/agent-manifest/schema.js.map +1 -1
  163. package/dist/src/automations/draft/automation-draft-service.js +1 -1
  164. package/dist/src/automations/draft/automation-draft-service.js.map +1 -1
  165. package/dist/src/cli/commands/agent.js +2 -2
  166. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  167. package/dist/src/cli/commands/init.js +1 -1
  168. package/dist/src/cli/commands/init.js.map +1 -1
  169. package/dist/src/cli/commands/models.js +1 -1
  170. package/dist/src/cli/commands/onboard/model.js +161 -11
  171. package/dist/src/cli/commands/onboard/model.js.map +1 -1
  172. package/dist/src/cli/commands/onboard.js +1 -1
  173. package/dist/src/cli/commands/profile.js +1 -1
  174. package/dist/src/cli/commands/tunnel.js +1 -1
  175. package/dist/src/cli/commands/update.js +1 -1
  176. package/dist/src/cli/extension-cli-register.js +1 -1
  177. package/dist/src/cli/templates.js +3 -2
  178. package/dist/src/cli/templates.js.map +1 -1
  179. package/dist/src/config/agent-profile.js +1 -1
  180. package/dist/src/config/default-model.d.ts +11 -0
  181. package/dist/src/config/default-model.js +19 -0
  182. package/dist/src/config/default-model.js.map +1 -0
  183. package/dist/src/config/index.js +3 -3
  184. package/dist/src/config/schema.d.ts +73 -13
  185. package/dist/src/config/schema.js +59 -24
  186. package/dist/src/config/schema.js.map +1 -1
  187. package/dist/src/connectors/registries/smithery.js +10 -9
  188. package/dist/src/connectors/registries/smithery.js.map +1 -1
  189. package/dist/src/daemon/install-plan.js +2 -1
  190. package/dist/src/daemon/install-plan.js.map +1 -1
  191. package/dist/src/gateway/agents-admin.js +1 -1
  192. package/dist/src/gateway/global-defaults-admin.js +6 -16
  193. package/dist/src/gateway/global-defaults-admin.js.map +1 -1
  194. package/dist/src/gateway/hono/lib/config-payload.d.ts +24 -0
  195. package/dist/src/gateway/hono/routes/agents.js +1 -79
  196. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  197. package/dist/src/gateway/hono/routes/config-patch/misc.js +4 -1
  198. package/dist/src/gateway/hono/routes/config-patch/misc.js.map +1 -1
  199. package/dist/src/gateway/hono/routes/models.js +132 -14
  200. package/dist/src/gateway/hono/routes/models.js.map +1 -1
  201. package/dist/src/gateway/hono/routes/voice.js +1 -1
  202. package/dist/src/gateway/hono/routes/voice.js.map +1 -1
  203. package/dist/src/gateway/image-capabilities.d.ts +11 -1
  204. package/dist/src/gateway/image-capabilities.js +32 -43
  205. package/dist/src/gateway/image-capabilities.js.map +1 -1
  206. package/dist/src/gateway/run-loop.js +1 -1
  207. package/dist/src/gateway/workspace-editor-path.js +9 -1
  208. package/dist/src/gateway/workspace-editor-path.js.map +1 -1
  209. package/dist/src/generated/bundled-image-generation-providers.d.ts +4 -2
  210. package/dist/src/generated/bundled-image-generation-providers.js +6 -4
  211. package/dist/src/generated/bundled-image-generation-providers.js.map +1 -1
  212. package/dist/src/infra/update-restart.js +1 -1
  213. package/dist/src/mcp/channel-bridge.js +1 -1
  214. package/dist/src/media/paths.js +3 -4
  215. package/dist/src/media/paths.js.map +1 -1
  216. package/dist/src/notes/service.js +1 -1
  217. package/dist/src/notes/service.js.map +1 -1
  218. package/dist/src/providers/domestic-presets.d.ts +615 -0
  219. package/dist/src/providers/domestic-presets.js +834 -0
  220. package/dist/src/providers/domestic-presets.js.map +1 -0
  221. package/dist/src/providers/env-keys.js +29 -5
  222. package/dist/src/providers/env-keys.js.map +1 -1
  223. package/dist/src/providers/extension-stream-bridge.js +1 -1
  224. package/dist/src/providers/extension-stream-bridge.js.map +1 -1
  225. package/dist/src/providers/index.d.ts +5 -5
  226. package/dist/src/providers/index.js +101 -21
  227. package/dist/src/providers/index.js.map +1 -1
  228. package/dist/src/providers/model-discovery.d.ts +17 -0
  229. package/dist/src/providers/model-discovery.js +61 -0
  230. package/dist/src/providers/model-discovery.js.map +1 -0
  231. package/dist/src/providers/model-registry.d.ts +1 -1
  232. package/dist/src/providers/model-registry.js +1 -1
  233. package/dist/src/providers/model-registry.js.map +1 -1
  234. package/dist/src/providers/presentation.js +185 -14
  235. package/dist/src/providers/presentation.js.map +1 -1
  236. package/dist/src/session/session-title.js +1 -1
  237. package/dist/src/session/session-title.js.map +1 -1
  238. package/dist/src/storage/sqlite/row-mappers.js +3 -1
  239. package/dist/src/storage/sqlite/row-mappers.js.map +1 -1
  240. package/dist/src/tui/backends/embedded-backend.js +1 -2
  241. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  242. package/dist/src/tui/xopc-tui-keybindings.d.ts +1 -1
  243. package/dist/src/voice/tts/summarize.js +1 -1
  244. package/dist/src/voice/tts/summarize.js.map +1 -1
  245. package/dist/src/workflows/draft/workflow-draft-service.js +1 -1
  246. package/dist/src/workflows/draft/workflow-draft-service.js.map +1 -1
  247. package/package.json +6 -6
  248. package/dist/gateway/static/root/assets/Combination-BzaXOLd9.js +0 -41
  249. package/dist/gateway/static/root/assets/agents-B0hkpLhP.js +0 -2
  250. package/dist/gateway/static/root/assets/automations-page-CTedroVo.js +0 -1
  251. package/dist/gateway/static/root/assets/browser-settings-page-FCDwOOBK.js +0 -8
  252. package/dist/gateway/static/root/assets/channels-settings-C3d5JBJX.js +0 -1
  253. package/dist/gateway/static/root/assets/connectors-page-yaUNvt5u.js +0 -2
  254. package/dist/gateway/static/root/assets/dist-By6Rh2ee.js +0 -1
  255. package/dist/gateway/static/root/assets/dist-CkobR7mk.js +0 -1
  256. package/dist/gateway/static/root/assets/dist-DokQNVMQ.js +0 -1
  257. package/dist/gateway/static/root/assets/dreaming-settings-DNrdg1Ve.js +0 -1
  258. package/dist/gateway/static/root/assets/extension-settings-page-BU1KoKRj.js +0 -1
  259. package/dist/gateway/static/root/assets/gateway-settings-C79wkXef.js +0 -1
  260. package/dist/gateway/static/root/assets/goal-detail-page-9paXuHdo.js +0 -1
  261. package/dist/gateway/static/root/assets/goals-page-CS0R-Af2.js +0 -2
  262. package/dist/gateway/static/root/assets/goals-settings-CSuzZ8Ae.js +0 -1
  263. package/dist/gateway/static/root/assets/heartbeat-settings-DXPaYJm3.js +0 -1
  264. package/dist/gateway/static/root/assets/index-BoKafJIZ.js +0 -191
  265. package/dist/gateway/static/root/assets/index-CArhCcYn.css +0 -1
  266. package/dist/gateway/static/root/assets/logs-page-DLXPcksQ.js +0 -2
  267. package/dist/gateway/static/root/assets/messages-CrDHEbss.js +0 -3
  268. package/dist/gateway/static/root/assets/models-hub-panel-BDF2iyRk.js +0 -2
  269. package/dist/gateway/static/root/assets/note-detail-page-CSb_hwig.js +0 -2
  270. package/dist/gateway/static/root/assets/remote-access-hub-CwzSovcS.js +0 -1
  271. package/dist/gateway/static/root/assets/schedule-field-CmTRoOcE.js +0 -1
  272. package/dist/gateway/static/root/assets/schema-form-FMKv1vGu.js +0 -1
  273. package/dist/gateway/static/root/assets/sessions-page-PHmX-NmA.js +0 -1
  274. package/dist/gateway/static/root/assets/settings-advanced-gate-BRAeKJN4.js +0 -1
  275. package/dist/gateway/static/root/assets/settings-form-section-D-4lBl6X.js +0 -1
  276. package/dist/gateway/static/root/assets/settings-page-KKrbFjy8.js +0 -1
  277. package/dist/gateway/static/root/assets/shares-settings-B18OBmH5.js +0 -1
  278. package/dist/gateway/static/root/assets/skill-reload-api-C28-2uKQ.js +0 -1
  279. package/dist/gateway/static/root/assets/skills-page-Bm2ebkwl.js +0 -2
  280. package/dist/gateway/static/root/assets/user-profile-settings-panel-DJ1dKwZy.js +0 -1
  281. package/dist/gateway/static/root/assets/voice-api-key-field-CeEevm7z.js +0 -1
  282. package/dist/gateway/static/root/assets/workflow-run-setup-panel-C4PzUQjB.js +0 -3
  283. package/dist/gateway/static/root/assets/workflows-page-BL84_-Ky.js +0 -18
  284. package/dist/src/agent/memory/memory-flush.d.ts +0 -27
  285. package/dist/src/agent/memory/memory-flush.js +0 -124
  286. package/dist/src/agent/memory/memory-flush.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"global-defaults-admin.js","names":[],"sources":["../../../src/gateway/global-defaults-admin.ts"],"sourcesContent":["import {\n CapabilityPresetSchema,\n DEFAULT_CAPABILITY_PRESET_ID,\n type CapabilityPreset,\n} from '../agent-manifest/schema.js';\nimport type { Config } from '../config/schema.js';\nimport {\n getAllProviders,\n getModelsByProvider,\n getProviderAuthState,\n getProviderDisplayName,\n} from '../providers/index.js';\nimport { getRecommendedModelsForProvider } from '../providers/presentation.js';\n\nexport type GlobalDefaultsProviderSource = 'config' | 'env' | 'oauth' | 'extension' | 'models_json' | 'agent' | null;\n\nexport type GlobalDefaultsProviderRow = {\n id: string;\n name: string;\n configured: boolean;\n source: GlobalDefaultsProviderSource;\n};\n\nexport type GlobalDefaultsRecommendation = {\n provider: string;\n model: string;\n reason: 'configured-provider' | 'recommended';\n};\n\nexport type GlobalDefaultsPayload = {\n presetId: string;\n models: NonNullable<CapabilityPreset['models']>;\n providers: GlobalDefaultsProviderRow[];\n recommendations: GlobalDefaultsRecommendation[];\n};\n\nexport type UpdateGlobalDefaultsBody = {\n models?: CapabilityPreset['models'];\n};\n\nexport type GlobalDefaultsAdminResult<T> =\n | { ok: true; data: T }\n | { ok: false; error: string; status?: 400 | 404 | 500 };\n\nfunction defaultPresetId(cfg: Config): string {\n return cfg.agents.defaultPreset || DEFAULT_CAPABILITY_PRESET_ID;\n}\n\nfunction emptyGlobalDefaultsPreset(id: string): CapabilityPreset {\n return {\n id,\n name: 'Global defaults',\n description: 'Default capabilities inherited by every agent.',\n version: 1,\n models: {\n defaultRole: 'deep',\n roles: {},\n },\n };\n}\n\nexport function ensureGlobalDefaultsConfig(cfg: Config): Config {\n const presetId = defaultPresetId(cfg);\n const current = cfg.agents.capabilityPresets[presetId];\n const preset = current\n ? {\n ...current,\n id: presetId,\n name: current.name || 'Global defaults',\n version: current.version || 1,\n models: current.models ?? { defaultRole: 'deep', roles: {} },\n }\n : emptyGlobalDefaultsPreset(presetId);\n\n return {\n ...cfg,\n agents: {\n ...cfg.agents,\n defaultPreset: presetId,\n capabilityPresets: {\n ...cfg.agents.capabilityPresets,\n [presetId]: preset,\n },\n },\n };\n}\n\nfunction sourceFromAuthMode(authMode: string): GlobalDefaultsProviderSource {\n if (authMode === 'gateway') return 'config';\n if (authMode === 'env') return 'env';\n if (authMode === 'oauth') return 'oauth';\n if (authMode === 'extension') return 'extension';\n if (authMode === 'models_json') return 'models_json';\n if (authMode === 'agent') return 'agent';\n return null;\n}\n\nfunction recommendedModelForProvider(provider: string): string | null {\n const recommended = getRecommendedModelsForProvider(provider, 1)[0];\n if (recommended) return recommended.ref;\n const model = getModelsByProvider(provider)[0];\n return model ? `${provider}/${model.id}` : null;\n}\n\nexport async function listGlobalDefaults(cfg: Config): Promise<GlobalDefaultsPayload> {\n const normalized = ensureGlobalDefaultsConfig(cfg);\n const presetId = defaultPresetId(normalized);\n const preset = normalized.agents.capabilityPresets[presetId] ?? emptyGlobalDefaultsPreset(presetId);\n const providers: GlobalDefaultsProviderRow[] = [];\n const recommendations: GlobalDefaultsRecommendation[] = [];\n\n for (const provider of getAllProviders()) {\n const auth = await getProviderAuthState(provider);\n const configured = auth.authStatus === 'connected';\n const source = configured ? sourceFromAuthMode(auth.authMode) : null;\n providers.push({\n id: provider,\n name: getProviderDisplayName(provider),\n configured,\n source,\n });\n if (configured) {\n const model = recommendedModelForProvider(provider);\n if (model) {\n recommendations.push({ provider, model, reason: 'configured-provider' });\n }\n }\n }\n\n providers.sort((a, b) => Number(b.configured) - Number(a.configured) || a.name.localeCompare(b.name));\n\n return {\n presetId,\n models: preset.models ?? { defaultRole: 'deep', roles: {} },\n providers,\n recommendations,\n };\n}\n\nexport function prepareUpdateGlobalDefaults(\n cfg: Config,\n body: UpdateGlobalDefaultsBody,\n): GlobalDefaultsAdminResult<{ nextConfig: Config }> {\n const normalized = ensureGlobalDefaultsConfig(cfg);\n const presetId = defaultPresetId(normalized);\n const current = normalized.agents.capabilityPresets[presetId] ?? emptyGlobalDefaultsPreset(presetId);\n let nextPreset: CapabilityPreset = current;\n\n if (body.models !== undefined) {\n const parsed = CapabilityPresetSchema.pick({ models: true }).safeParse({ models: body.models });\n if (!parsed.success) {\n return { ok: false, error: `models ${parsed.error.issues[0]?.message ?? 'is invalid'}`, status: 400 };\n }\n const models = parsed.data.models ?? { defaultRole: 'deep', roles: {} };\n const roles = models.roles ?? {};\n const defaultRole = models.defaultRole ?? Object.keys(roles)[0] ?? 'deep';\n if (Object.keys(roles).length > 0 && !roles[defaultRole]) {\n return { ok: false, error: 'models.defaultRole must reference models.roles', status: 400 };\n }\n nextPreset = {\n ...nextPreset,\n models: { ...models, defaultRole, roles },\n };\n }\n\n return {\n ok: true,\n data: {\n nextConfig: {\n ...normalized,\n agents: {\n ...normalized.agents,\n capabilityPresets: {\n ...normalized.agents.capabilityPresets,\n [presetId]: nextPreset,\n },\n },\n },\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"global-defaults-admin.js","names":[],"sources":["../../../src/gateway/global-defaults-admin.ts"],"sourcesContent":["import {\n CapabilityPresetSchema,\n DEFAULT_CAPABILITY_PRESET_ID,\n type CapabilityPreset,\n} from '../agent-manifest/schema.js';\nimport { DEFAULT_AGENT_MODELS } from '../config/default-model.js';\nimport type { Config } from '../config/schema.js';\nimport {\n getAllProviders,\n getModelsByProvider,\n getProviderAuthState,\n getProviderDisplayName,\n} from '../providers/index.js';\nimport { getRecommendedModelsForProvider } from '../providers/presentation.js';\n\nexport type GlobalDefaultsProviderSource = 'config' | 'env' | 'oauth' | 'extension' | 'models_json' | 'agent' | null;\n\nexport type GlobalDefaultsProviderRow = {\n id: string;\n name: string;\n configured: boolean;\n source: GlobalDefaultsProviderSource;\n};\n\nexport type GlobalDefaultsRecommendation = {\n provider: string;\n model: string;\n reason: 'configured-provider' | 'recommended';\n};\n\nexport type GlobalDefaultsPayload = {\n presetId: string;\n models: NonNullable<CapabilityPreset['models']>;\n providers: GlobalDefaultsProviderRow[];\n recommendations: GlobalDefaultsRecommendation[];\n};\n\nexport type UpdateGlobalDefaultsBody = {\n models?: CapabilityPreset['models'];\n};\n\nexport type GlobalDefaultsAdminResult<T> =\n | { ok: true; data: T }\n | { ok: false; error: string; status?: 400 | 404 | 500 };\n\nfunction defaultPresetId(cfg: Config): string {\n return cfg.agents.defaultPreset || DEFAULT_CAPABILITY_PRESET_ID;\n}\n\nfunction emptyGlobalDefaultsPreset(id: string): CapabilityPreset {\n return {\n id,\n name: 'Global defaults',\n description: 'Default capabilities inherited by every agent.',\n version: 1,\n models: DEFAULT_AGENT_MODELS,\n };\n}\n\nexport function ensureGlobalDefaultsConfig(cfg: Config): Config {\n const presetId = defaultPresetId(cfg);\n const current = cfg.agents.capabilityPresets[presetId];\n const preset = current\n ? {\n ...current,\n id: presetId,\n name: current.name || 'Global defaults',\n version: current.version || 1,\n models: current.models ?? DEFAULT_AGENT_MODELS,\n }\n : emptyGlobalDefaultsPreset(presetId);\n\n return {\n ...cfg,\n agents: {\n ...cfg.agents,\n defaultPreset: presetId,\n capabilityPresets: {\n ...cfg.agents.capabilityPresets,\n [presetId]: preset,\n },\n },\n };\n}\n\nfunction sourceFromAuthMode(authMode: string): GlobalDefaultsProviderSource {\n if (authMode === 'gateway') return 'config';\n if (authMode === 'env') return 'env';\n if (authMode === 'oauth') return 'oauth';\n if (authMode === 'extension') return 'extension';\n if (authMode === 'models_json') return 'models_json';\n if (authMode === 'agent') return 'agent';\n return null;\n}\n\nfunction recommendedModelForProvider(provider: string): string | null {\n const recommended = getRecommendedModelsForProvider(provider, 1)[0];\n if (recommended) return recommended.ref;\n const model = getModelsByProvider(provider)[0];\n return model ? `${provider}/${model.id}` : null;\n}\n\nexport async function listGlobalDefaults(cfg: Config): Promise<GlobalDefaultsPayload> {\n const normalized = ensureGlobalDefaultsConfig(cfg);\n const presetId = defaultPresetId(normalized);\n const preset = normalized.agents.capabilityPresets[presetId] ?? emptyGlobalDefaultsPreset(presetId);\n const providers: GlobalDefaultsProviderRow[] = [];\n const recommendations: GlobalDefaultsRecommendation[] = [];\n\n for (const provider of getAllProviders()) {\n const auth = await getProviderAuthState(provider);\n const configured = auth.authStatus === 'connected';\n const source = configured ? sourceFromAuthMode(auth.authMode) : null;\n providers.push({\n id: provider,\n name: getProviderDisplayName(provider),\n configured,\n source,\n });\n if (configured) {\n const model = recommendedModelForProvider(provider);\n if (model) {\n recommendations.push({ provider, model, reason: 'configured-provider' });\n }\n }\n }\n\n providers.sort((a, b) => Number(b.configured) - Number(a.configured) || a.name.localeCompare(b.name));\n\n return {\n presetId,\n models: preset.models ?? DEFAULT_AGENT_MODELS,\n providers,\n recommendations,\n };\n}\n\nexport function prepareUpdateGlobalDefaults(\n cfg: Config,\n body: UpdateGlobalDefaultsBody,\n): GlobalDefaultsAdminResult<{ nextConfig: Config }> {\n const normalized = ensureGlobalDefaultsConfig(cfg);\n const presetId = defaultPresetId(normalized);\n const current = normalized.agents.capabilityPresets[presetId] ?? emptyGlobalDefaultsPreset(presetId);\n let nextPreset: CapabilityPreset = current;\n\n if (body.models !== undefined) {\n const parsed = CapabilityPresetSchema.pick({ models: true }).safeParse({ models: body.models });\n if (!parsed.success) {\n return { ok: false, error: `models ${parsed.error.issues[0]?.message ?? 'is invalid'}`, status: 400 };\n }\n const models = parsed.data.models ?? DEFAULT_AGENT_MODELS;\n const roles = models.roles ?? {};\n const defaultRole = models.defaultRole ?? Object.keys(roles)[0] ?? 'deep';\n if (Object.keys(roles).length > 0 && !roles[defaultRole]) {\n return { ok: false, error: 'models.defaultRole must reference models.roles', status: 400 };\n }\n nextPreset = {\n ...nextPreset,\n models: { ...models, defaultRole, roles },\n };\n }\n\n return {\n ok: true,\n data: {\n nextConfig: {\n ...normalized,\n agents: {\n ...normalized.agents,\n capabilityPresets: {\n ...normalized.agents.capabilityPresets,\n [presetId]: nextPreset,\n },\n },\n },\n },\n };\n}\n"],"mappings":"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"}
@@ -47,6 +47,18 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
47
47
  fallbacks?: string[];
48
48
  description?: string;
49
49
  }>;
50
+ imageModel?: {
51
+ primary: string;
52
+ fallbacks?: string[];
53
+ timeoutMs?: number;
54
+ autoProviderFallback?: boolean;
55
+ };
56
+ imageGenerationModel?: {
57
+ primary: string;
58
+ fallbacks?: string[];
59
+ timeoutMs?: number;
60
+ autoProviderFallback?: boolean;
61
+ };
50
62
  policy?: {
51
63
  allowFallbacks?: boolean;
52
64
  maxCostTier?: "low" | "medium" | "high";
@@ -169,6 +181,18 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
169
181
  fallbacks?: string[];
170
182
  description?: string;
171
183
  }>;
184
+ imageModel?: {
185
+ primary: string;
186
+ fallbacks?: string[];
187
+ timeoutMs?: number;
188
+ autoProviderFallback?: boolean;
189
+ };
190
+ imageGenerationModel?: {
191
+ primary: string;
192
+ fallbacks?: string[];
193
+ timeoutMs?: number;
194
+ autoProviderFallback?: boolean;
195
+ };
172
196
  policy?: {
173
197
  allowFallbacks?: boolean;
174
198
  maxCostTier?: "low" | "medium" | "high";
@@ -1,14 +1,11 @@
1
1
  import { MemoryPolicySchema, ToolPolicySetSchema, init_schema } from "../../../agent-manifest/schema.js";
2
- import { AgentModelsSchema, init_schema as init_schema$1, parseModelRef } from "../../../config/schema.js";
2
+ import { AgentModelsSchema, init_schema as init_schema$1 } from "../../../config/schema.js";
3
3
  import { init_agent_scope, normalizeAgentId } from "../../../agent/agent-scope.js";
4
- import { init_providers, isProviderConfigured, resolveModel } from "../../../providers/index.js";
5
4
  import { getVoiceModelsConfig } from "../../../config/voice.js";
6
5
  import { deleteAgentAvatarFile, finalizeCreateAgentDirs, getGatewayAgentEffectiveManifest, listAgentProfileFiles, listGatewayAgents, prepareCreateAgent, prepareDeleteAgent, prepareUpdateAgent, readAgentAvatarFile, readAgentProfileFile, readUserProfileFile, runAfterDeletePurge, writeAgentAvatarFromBase64, writeAgentProfileFile, writeUserProfileFile } from "../../agents-admin.js";
7
- import { resolveImageGenerationCapabilities, resolveImageUnderstandingCapabilities } from "../../image-capabilities.js";
8
6
  //#region src/gateway/hono/routes/agents.ts
9
7
  init_schema$1();
10
8
  init_schema();
11
- init_providers();
12
9
  init_agent_scope();
13
10
  function parseProfileFiles(raw) {
14
11
  if (raw === void 0) return;
@@ -408,81 +405,6 @@ function registerAgentsRoutes(authenticated, deps) {
408
405
  payload: { models }
409
406
  });
410
407
  });
411
- authenticated.get("/api/image/capabilities", async (c) => {
412
- const config = service.currentConfig;
413
- const imageGenerationProviders = await resolveImageGenerationCapabilities(config);
414
- const imageUnderstandingProviders = await resolveImageUnderstandingCapabilities(config);
415
- return c.json({
416
- ok: true,
417
- payload: {
418
- current: {
419
- imageModel: null,
420
- imageModelFallbacks: [],
421
- imageGenerationModel: null,
422
- imageGenerationModelFallbacks: [],
423
- mediaMaxMb: null
424
- },
425
- imageGeneration: { providers: imageGenerationProviders },
426
- imageUnderstanding: { providers: imageUnderstandingProviders }
427
- }
428
- });
429
- });
430
- authenticated.post("/api/image/validate-model", strictRateLimitMiddleware, async (c) => {
431
- let body;
432
- try {
433
- body = await c.req.json();
434
- } catch {
435
- return c.json({
436
- ok: false,
437
- error: "Invalid JSON"
438
- }, 400);
439
- }
440
- const modelRef = body.modelRef;
441
- if (!modelRef || typeof modelRef !== "string") return c.json({
442
- ok: false,
443
- error: "modelRef is required"
444
- }, 400);
445
- const parsed = parseModelRef(modelRef);
446
- if (!parsed) return c.json({
447
- ok: true,
448
- payload: {
449
- valid: false,
450
- reason: "invalid_format",
451
- message: "Model reference must be in \"provider/model\" format"
452
- }
453
- });
454
- if (!await isProviderConfigured(parsed.provider)) return c.json({
455
- ok: true,
456
- payload: {
457
- valid: false,
458
- reason: "provider_not_configured",
459
- message: `Provider "${parsed.provider}" is not configured. Set the API key first.`,
460
- provider: parsed.provider
461
- }
462
- });
463
- try {
464
- resolveModel(modelRef);
465
- } catch {
466
- return c.json({
467
- ok: true,
468
- payload: {
469
- valid: false,
470
- reason: "model_not_found",
471
- message: `Model not found in registry: ${modelRef}`,
472
- provider: parsed.provider,
473
- model: parsed.model
474
- }
475
- });
476
- }
477
- return c.json({
478
- ok: true,
479
- payload: {
480
- valid: true,
481
- provider: parsed.provider,
482
- model: parsed.model
483
- }
484
- });
485
- });
486
408
  }
487
409
  //#endregion
488
410
  export { registerAgentsRoutes };
@@ -1 +1 @@
1
- {"version":3,"file":"agents.js","names":[],"sources":["../../../../../src/gateway/hono/routes/agents.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { AgentModelsSchema, type Config, parseModelRef } from '../../../config/schema.js';\nimport { MemoryPolicySchema, ToolPolicySetSchema } from '../../../agent-manifest/schema.js';\nimport { getVoiceModelsConfig } from '../../../config/voice.js';\nimport {\n isProviderConfigured,\n resolveModel,\n} from '../../../providers/index.js';\nimport { normalizeAgentId } from '../../../agent/agent-scope.js';\nimport {\n deleteAgentAvatarFile,\n finalizeCreateAgentDirs,\n getGatewayAgentEffectiveManifest,\n listAgentProfileFiles,\n listGatewayAgents,\n prepareCreateAgent,\n prepareDeleteAgent,\n prepareUpdateAgent,\n readAgentAvatarFile,\n readAgentProfileFile,\n readUserProfileFile,\n runAfterDeletePurge,\n writeAgentAvatarFromBase64,\n writeAgentProfileFile,\n writeUserProfileFile,\n type CreateAgentBody,\n} from '../../agents-admin.js';\nimport {\n resolveImageGenerationCapabilities,\n resolveImageUnderstandingCapabilities,\n} from '../../image-capabilities.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nfunction parseProfileFiles(raw: unknown): Record<string, string> | undefined | { error: string } {\n if (raw === undefined) {\n return undefined;\n }\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n return { error: 'profileFiles must be an object' };\n }\n const profileFiles: Record<string, string> = {};\n for (const [name, content] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof content !== 'string') {\n return { error: `profileFiles[\"${name}\"] must be a string` };\n }\n profileFiles[name] = content;\n }\n return profileFiles;\n}\n\nfunction isParseError(value: unknown): value is { error: string } {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'error' in value &&\n typeof (value as { error: string }).error === 'string'\n );\n}\n\nfunction parseCreateAgentBody(raw: unknown): CreateAgentBody | { error: string } {\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n return { error: 'each agent must be an object' };\n }\n const body = raw as Record<string, unknown>;\n if (Object.hasOwn(body, 'model')) {\n return { error: 'model is not supported; use models.defaultRole and models.roles' };\n }\n if (Object.hasOwn(body, 'toolsDisable')) {\n return { error: 'toolsDisable was removed; use tools.builtin policies' };\n }\n if (Object.hasOwn(body, 'typedModels')) {\n return { error: 'typedModels is not supported; use models.roles' };\n }\n if (Object.hasOwn(body, 'agentDir')) {\n return { error: 'agentDir was removed from agent manifests' };\n }\n if (Object.hasOwn(body, 'name')) {\n return { error: 'name is not supported; write IDENTITY.md in profileFiles' };\n }\n if (Object.hasOwn(body, 'description')) {\n return { error: 'description is not supported; write IDENTITY.md in profileFiles' };\n }\n const workspace = typeof body.workspace === 'string' ? body.workspace : '';\n const models = Object.hasOwn(body, 'models')\n ? AgentModelsSchema.safeParse(body.models)\n : undefined;\n if (models && !models.success) {\n return { error: `models ${models.error.issues[0]?.message ?? 'is invalid'}` };\n }\n const id = typeof body.id === 'string' ? body.id : undefined;\n const skills = Object.hasOwn(body, 'skills')\n ? Array.isArray(body.skills)\n ? body.skills.map((x: unknown) => String(x).trim()).filter(Boolean)\n : null\n : undefined;\n if (skills === null) {\n return { error: 'skills must be an array' };\n }\n const toolsRaw = Object.hasOwn(body, 'tools') ? body.tools : undefined;\n let tools: CreateAgentBody['tools'] | undefined;\n if (toolsRaw !== undefined) {\n if (toolsRaw === null || typeof toolsRaw !== 'object' || Array.isArray(toolsRaw)) {\n return { error: 'tools must be an object' };\n }\n const parsedTools = ToolPolicySetSchema.safeParse(toolsRaw);\n if (!parsedTools.success) {\n return { error: `tools ${parsedTools.error.issues[0]?.message ?? 'is invalid'}` };\n }\n tools = parsedTools.data;\n }\n let profileFiles: Record<string, string> | undefined;\n if (Object.hasOwn(body, 'profileFiles')) {\n const parsed = parseProfileFiles(body.profileFiles);\n if (isParseError(parsed)) {\n return parsed;\n }\n profileFiles = parsed;\n }\n if (!profileFiles?.['IDENTITY.md'] && typeof body.cloneFrom !== 'string') {\n return { error: 'profileFiles.IDENTITY.md is required' };\n }\n const cloneFrom = typeof body.cloneFrom === 'string' ? body.cloneFrom : undefined;\n return {\n workspace,\n ...(models && models.data !== undefined ? { models: models.data } : {}),\n ...(id !== undefined ? { id } : {}),\n ...(skills !== undefined ? { skills } : {}),\n ...(tools !== undefined ? { tools } : {}),\n ...(profileFiles !== undefined ? { profileFiles } : {}),\n ...(cloneFrom !== undefined ? { cloneFrom } : {}),\n };\n}\n\ntype PatchModels = {\n defaultRole?: string | null;\n roles?: Record<string, { model: string; fallbacks?: string[]; description?: string }>;\n};\n\nfunction parsePatchModels(raw: unknown): PatchModels | null | undefined | { error: string } {\n if (raw === undefined) {\n return undefined;\n }\n if (raw === null) {\n return null;\n }\n if (typeof raw !== 'object' || Array.isArray(raw)) {\n return { error: 'models must be an object or null' };\n }\n const body = raw as Record<string, unknown>;\n const out: PatchModels = {};\n if (Object.hasOwn(body, 'defaultRole')) {\n out.defaultRole = body.defaultRole === null ? null : String(body.defaultRole ?? '').trim();\n }\n if (Object.hasOwn(body, 'roles')) {\n if (body.roles === null) {\n return { error: 'models.roles must be an object' };\n } else {\n const parsed = AgentModelsSchema.safeParse({ roles: body.roles });\n if (!parsed.success) {\n return { error: `models.roles ${parsed.error.issues[0]?.message ?? 'is invalid'}` };\n }\n out.roles = parsed.data?.roles;\n }\n }\n return out;\n}\n\nexport function registerAgentsRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service, strictRateLimitMiddleware } = deps;\n\n authenticated.get('/api/agents', async (c) => {\n const cfg = service.currentConfig as Config;\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const payload = await listGatewayAgents(cfg, { locale });\n return c.json({ ok: true, payload });\n });\n\n authenticated.get('/api/user-profile', async (c) => {\n const res = await readUserProfileFile();\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.put('/api/user-profile', strictRateLimitMiddleware, async (c) => {\n let content = '';\n try {\n const body = (await c.req.json()) as { content?: unknown };\n content = typeof body.content === 'string' ? body.content : '';\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const res = await writeUserProfileFile(content);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.post('/api/agents', strictRateLimitMiddleware, async (c) => {\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const parsed = parseCreateAgentBody(body);\n if ('error' in parsed) {\n return c.json({ ok: false, error: { message: parsed.error } }, 400);\n }\n const prep = prepareCreateAgent(service.currentConfig as Config, parsed);\n if (prep.ok === false) {\n return c.json({ ok: false, error: { message: prep.error } }, prep.status ?? 400);\n }\n const { nextConfig, agentId } = prep.data;\n const save = await service.saveConfig(nextConfig);\n if (!save.saved) {\n return c.json({ ok: false, error: { message: save.error ?? 'save failed' } }, 500);\n }\n const finalized = await finalizeCreateAgentDirs(service.currentConfig as Config, agentId, {\n ...(parsed.profileFiles !== undefined ? { profileFiles: parsed.profileFiles } : {}),\n ...(parsed.cloneFrom ? { cloneFrom: parsed.cloneFrom } : {}),\n });\n if (finalized.ok === false) {\n return c.json({ ok: false, error: { message: finalized.error } }, finalized.status ?? 400);\n }\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const agentsPayload = await listGatewayAgents(service.currentConfig as Config, { locale });\n return c.json({\n ok: true,\n payload: {\n agentId,\n agents: agentsPayload,\n },\n });\n });\n\n authenticated.get('/api/agents/:id/effective-manifest', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = getGatewayAgentEffectiveManifest(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.patch('/api/agents/:id', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n if (Object.hasOwn(body, 'model')) {\n return c.json({ ok: false, error: { message: 'model is not supported; use models.defaultRole and models.roles' } }, 400);\n }\n if (Object.hasOwn(body, 'typedModels')) {\n return c.json({ ok: false, error: { message: 'typedModels is not supported; use models.roles' } }, 400);\n }\n if (Object.hasOwn(body, 'toolsDisable')) {\n return c.json({ ok: false, error: { message: 'toolsDisable was removed; use tools.builtin policies' } }, 400);\n }\n if (Object.hasOwn(body, 'agentDir')) {\n return c.json({ ok: false, error: { message: 'agentDir was removed from agent manifests' } }, 400);\n }\n if (Object.hasOwn(body, 'name')) {\n return c.json({ ok: false, error: { message: 'name is not supported; edit IDENTITY.md' } }, 400);\n }\n if (Object.hasOwn(body, 'description')) {\n return c.json({ ok: false, error: { message: 'description is not supported; edit IDENTITY.md' } }, 400);\n }\n const skillsPatch =\n body.skills === null\n ? null\n : Array.isArray(body.skills)\n ? body.skills.map((x: unknown) => String(x).trim()).filter(Boolean)\n : undefined;\n const extendsPatch = Object.hasOwn(body, 'extends')\n ? Array.isArray(body.extends)\n ? body.extends.map((x: unknown) => String(x).trim()).filter(Boolean)\n : undefined\n : undefined;\n if (Object.hasOwn(body, 'extends') && extendsPatch === undefined) {\n return c.json({ ok: false, error: { message: 'extends must be an array' } }, 400);\n }\n let toolsPatch: CreateAgentBody['tools'] | null | undefined;\n if (Object.hasOwn(body, 'tools')) {\n if (body.tools === null) {\n toolsPatch = null;\n } else if (typeof body.tools === 'object' && !Array.isArray(body.tools)) {\n const parsedTools = ToolPolicySetSchema.safeParse(body.tools);\n if (!parsedTools.success) {\n return c.json({ ok: false, error: { message: `tools ${parsedTools.error.issues[0]?.message ?? 'is invalid'}` } }, 400);\n }\n toolsPatch = parsedTools.data;\n } else {\n return c.json({ ok: false, error: { message: 'tools must be an object or null' } }, 400);\n }\n }\n const modelsPatch = Object.hasOwn(body, 'models') ? parsePatchModels(body.models) : undefined;\n if (isParseError(modelsPatch)) {\n return c.json({ ok: false, error: { message: modelsPatch.error } }, 400);\n }\n let memoryPatch: Config['agents']['list'][number]['memory'] | undefined;\n if (Object.hasOwn(body, 'memory')) {\n const parsedMemory = MemoryPolicySchema.safeParse(body.memory);\n if (!parsedMemory.success) {\n return c.json({ ok: false, error: { message: `memory ${parsedMemory.error.issues[0]?.message ?? 'is invalid'}` } }, 400);\n }\n memoryPatch = parsedMemory.data;\n }\n\n const prep = prepareUpdateAgent(service.currentConfig as Config, id, {\n workspace: typeof body.workspace === 'string' ? body.workspace : undefined,\n ...(extendsPatch !== undefined ? { extends: extendsPatch } : {}),\n ...(modelsPatch !== undefined ? { models: modelsPatch } : {}),\n setDefault: body.setDefault === true,\n ...(skillsPatch !== undefined ? { skills: skillsPatch } : {}),\n ...(toolsPatch !== undefined ? { tools: toolsPatch } : {}),\n ...(memoryPatch !== undefined ? { memory: memoryPatch } : {}),\n });\n if (prep.ok === false) {\n return c.json({ ok: false, error: { message: prep.error } }, prep.status ?? 400);\n }\n const save = await service.saveConfig(prep.data.nextConfig);\n if (!save.saved) {\n return c.json({ ok: false, error: { message: save.error ?? 'save failed' } }, 500);\n }\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const agentsPayload = await listGatewayAgents(service.currentConfig as Config, { locale });\n return c.json({ ok: true, payload: agentsPayload });\n });\n\n authenticated.delete('/api/agents/:id', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const purge = c.req.query('purge') === '1' || c.req.query('purge') === 'true';\n const prep = prepareDeleteAgent(service.currentConfig as Config, id);\n if (prep.ok === false) {\n return c.json({ ok: false, error: { message: prep.error } }, prep.status ?? 400);\n }\n const { nextConfig, agentId } = prep.data;\n const save = await service.saveConfig(nextConfig);\n if (!save.saved) {\n return c.json({ ok: false, error: { message: save.error ?? 'save failed' } }, 500);\n }\n if (purge) {\n await runAfterDeletePurge(service.currentConfig as Config, agentId);\n }\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const agentsPayload = await listGatewayAgents(service.currentConfig as Config, { locale });\n return c.json({\n ok: true,\n payload: { agentId, purged: purge, agents: agentsPayload },\n });\n });\n\n authenticated.get('/api/agents/:id/avatar', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = await readAgentAvatarFile(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return new Response(res.data.buffer, {\n status: 200,\n headers: {\n 'Content-Type': res.data.contentType,\n 'Cache-Control': 'private, max-age=3600',\n },\n });\n });\n\n authenticated.put('/api/agents/:id/avatar', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const base64 = typeof body.base64 === 'string' ? body.base64 : '';\n const mimeType = typeof body.mimeType === 'string' ? body.mimeType : '';\n const res = await writeAgentAvatarFromBase64(service.currentConfig as Config, id, base64, mimeType);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId } });\n });\n\n authenticated.delete('/api/agents/:id/avatar', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = await deleteAgentAvatarFile(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId } });\n });\n\n authenticated.get('/api/agents/:id/files', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = await listAgentProfileFiles(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.get('/api/agents/:id/files/:name', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const name = decodeURIComponent(c.req.param('name') ?? '');\n const res = await readAgentProfileFile(service.currentConfig as Config, id, name);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId, name, content: res.data.content } });\n });\n\n authenticated.put('/api/agents/:id/files/:name', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const name = decodeURIComponent(c.req.param('name') ?? '');\n let content = '';\n try {\n const body = (await c.req.json()) as { content?: unknown };\n content = typeof body.content === 'string' ? body.content : '';\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const res = await writeAgentProfileFile(service.currentConfig as Config, id, name, content);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId, name } });\n });\n\n // GET /api/voice/models - Get available STT/TTS models\n authenticated.get('/api/voice/models', (c) => {\n const models = getVoiceModelsConfig();\n return c.json({ ok: true, payload: { models } });\n });\n\n authenticated.get('/api/image/capabilities', async (c) => {\n const config = service.currentConfig as Config;\n const imageGenerationProviders = await resolveImageGenerationCapabilities(config);\n const imageUnderstandingProviders = await resolveImageUnderstandingCapabilities(config);\n return c.json({\n ok: true,\n payload: {\n current: {\n imageModel: null,\n imageModelFallbacks: [],\n imageGenerationModel: null,\n imageGenerationModelFallbacks: [],\n mediaMaxMb: null,\n },\n imageGeneration: { providers: imageGenerationProviders },\n imageUnderstanding: { providers: imageUnderstandingProviders },\n },\n });\n });\n\n authenticated.post('/api/image/validate-model', strictRateLimitMiddleware, async (c) => {\n let body: { modelRef?: unknown };\n try {\n body = (await c.req.json()) as { modelRef?: unknown };\n } catch {\n return c.json({ ok: false, error: 'Invalid JSON' }, 400);\n }\n const modelRef = body.modelRef;\n if (!modelRef || typeof modelRef !== 'string') {\n return c.json({ ok: false, error: 'modelRef is required' }, 400);\n }\n\n const parsed = parseModelRef(modelRef);\n if (!parsed) {\n return c.json({\n ok: true,\n payload: {\n valid: false,\n reason: 'invalid_format',\n message: 'Model reference must be in \"provider/model\" format',\n },\n });\n }\n\n const configured = await isProviderConfigured(parsed.provider);\n if (!configured) {\n return c.json({\n ok: true,\n payload: {\n valid: false,\n reason: 'provider_not_configured',\n message: `Provider \"${parsed.provider}\" is not configured. Set the API key first.`,\n provider: parsed.provider,\n },\n });\n }\n\n try {\n resolveModel(modelRef);\n } catch {\n return c.json({\n ok: true,\n payload: {\n valid: false,\n reason: 'model_not_found',\n message: `Model not found in registry: ${modelRef}`,\n provider: parsed.provider,\n model: parsed.model,\n },\n });\n }\n\n return c.json({\n ok: true,\n payload: {\n valid: true,\n provider: parsed.provider,\n model: parsed.model,\n },\n });\n });\n\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"agents.js","names":[],"sources":["../../../../../src/gateway/hono/routes/agents.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { AgentModelsSchema, type Config } from '../../../config/schema.js';\nimport { MemoryPolicySchema, ToolPolicySetSchema } from '../../../agent-manifest/schema.js';\nimport { getVoiceModelsConfig } from '../../../config/voice.js';\nimport { normalizeAgentId } from '../../../agent/agent-scope.js';\nimport {\n deleteAgentAvatarFile,\n finalizeCreateAgentDirs,\n getGatewayAgentEffectiveManifest,\n listAgentProfileFiles,\n listGatewayAgents,\n prepareCreateAgent,\n prepareDeleteAgent,\n prepareUpdateAgent,\n readAgentAvatarFile,\n readAgentProfileFile,\n readUserProfileFile,\n runAfterDeletePurge,\n writeAgentAvatarFromBase64,\n writeAgentProfileFile,\n writeUserProfileFile,\n type CreateAgentBody,\n} from '../../agents-admin.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nfunction parseProfileFiles(raw: unknown): Record<string, string> | undefined | { error: string } {\n if (raw === undefined) {\n return undefined;\n }\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n return { error: 'profileFiles must be an object' };\n }\n const profileFiles: Record<string, string> = {};\n for (const [name, content] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof content !== 'string') {\n return { error: `profileFiles[\"${name}\"] must be a string` };\n }\n profileFiles[name] = content;\n }\n return profileFiles;\n}\n\nfunction isParseError(value: unknown): value is { error: string } {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'error' in value &&\n typeof (value as { error: string }).error === 'string'\n );\n}\n\nfunction parseCreateAgentBody(raw: unknown): CreateAgentBody | { error: string } {\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n return { error: 'each agent must be an object' };\n }\n const body = raw as Record<string, unknown>;\n if (Object.hasOwn(body, 'model')) {\n return { error: 'model is not supported; use models.defaultRole and models.roles' };\n }\n if (Object.hasOwn(body, 'toolsDisable')) {\n return { error: 'toolsDisable was removed; use tools.builtin policies' };\n }\n if (Object.hasOwn(body, 'typedModels')) {\n return { error: 'typedModels is not supported; use models.roles' };\n }\n if (Object.hasOwn(body, 'agentDir')) {\n return { error: 'agentDir was removed from agent manifests' };\n }\n if (Object.hasOwn(body, 'name')) {\n return { error: 'name is not supported; write IDENTITY.md in profileFiles' };\n }\n if (Object.hasOwn(body, 'description')) {\n return { error: 'description is not supported; write IDENTITY.md in profileFiles' };\n }\n const workspace = typeof body.workspace === 'string' ? body.workspace : '';\n const models = Object.hasOwn(body, 'models')\n ? AgentModelsSchema.safeParse(body.models)\n : undefined;\n if (models && !models.success) {\n return { error: `models ${models.error.issues[0]?.message ?? 'is invalid'}` };\n }\n const id = typeof body.id === 'string' ? body.id : undefined;\n const skills = Object.hasOwn(body, 'skills')\n ? Array.isArray(body.skills)\n ? body.skills.map((x: unknown) => String(x).trim()).filter(Boolean)\n : null\n : undefined;\n if (skills === null) {\n return { error: 'skills must be an array' };\n }\n const toolsRaw = Object.hasOwn(body, 'tools') ? body.tools : undefined;\n let tools: CreateAgentBody['tools'] | undefined;\n if (toolsRaw !== undefined) {\n if (toolsRaw === null || typeof toolsRaw !== 'object' || Array.isArray(toolsRaw)) {\n return { error: 'tools must be an object' };\n }\n const parsedTools = ToolPolicySetSchema.safeParse(toolsRaw);\n if (!parsedTools.success) {\n return { error: `tools ${parsedTools.error.issues[0]?.message ?? 'is invalid'}` };\n }\n tools = parsedTools.data;\n }\n let profileFiles: Record<string, string> | undefined;\n if (Object.hasOwn(body, 'profileFiles')) {\n const parsed = parseProfileFiles(body.profileFiles);\n if (isParseError(parsed)) {\n return parsed;\n }\n profileFiles = parsed;\n }\n if (!profileFiles?.['IDENTITY.md'] && typeof body.cloneFrom !== 'string') {\n return { error: 'profileFiles.IDENTITY.md is required' };\n }\n const cloneFrom = typeof body.cloneFrom === 'string' ? body.cloneFrom : undefined;\n return {\n workspace,\n ...(models && models.data !== undefined ? { models: models.data } : {}),\n ...(id !== undefined ? { id } : {}),\n ...(skills !== undefined ? { skills } : {}),\n ...(tools !== undefined ? { tools } : {}),\n ...(profileFiles !== undefined ? { profileFiles } : {}),\n ...(cloneFrom !== undefined ? { cloneFrom } : {}),\n };\n}\n\ntype PatchModels = {\n defaultRole?: string | null;\n roles?: Record<string, { model: string; fallbacks?: string[]; description?: string }>;\n};\n\nfunction parsePatchModels(raw: unknown): PatchModels | null | undefined | { error: string } {\n if (raw === undefined) {\n return undefined;\n }\n if (raw === null) {\n return null;\n }\n if (typeof raw !== 'object' || Array.isArray(raw)) {\n return { error: 'models must be an object or null' };\n }\n const body = raw as Record<string, unknown>;\n const out: PatchModels = {};\n if (Object.hasOwn(body, 'defaultRole')) {\n out.defaultRole = body.defaultRole === null ? null : String(body.defaultRole ?? '').trim();\n }\n if (Object.hasOwn(body, 'roles')) {\n if (body.roles === null) {\n return { error: 'models.roles must be an object' };\n } else {\n const parsed = AgentModelsSchema.safeParse({ roles: body.roles });\n if (!parsed.success) {\n return { error: `models.roles ${parsed.error.issues[0]?.message ?? 'is invalid'}` };\n }\n out.roles = parsed.data?.roles;\n }\n }\n return out;\n}\n\nexport function registerAgentsRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service, strictRateLimitMiddleware } = deps;\n\n authenticated.get('/api/agents', async (c) => {\n const cfg = service.currentConfig as Config;\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const payload = await listGatewayAgents(cfg, { locale });\n return c.json({ ok: true, payload });\n });\n\n authenticated.get('/api/user-profile', async (c) => {\n const res = await readUserProfileFile();\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.put('/api/user-profile', strictRateLimitMiddleware, async (c) => {\n let content = '';\n try {\n const body = (await c.req.json()) as { content?: unknown };\n content = typeof body.content === 'string' ? body.content : '';\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const res = await writeUserProfileFile(content);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.post('/api/agents', strictRateLimitMiddleware, async (c) => {\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const parsed = parseCreateAgentBody(body);\n if ('error' in parsed) {\n return c.json({ ok: false, error: { message: parsed.error } }, 400);\n }\n const prep = prepareCreateAgent(service.currentConfig as Config, parsed);\n if (prep.ok === false) {\n return c.json({ ok: false, error: { message: prep.error } }, prep.status ?? 400);\n }\n const { nextConfig, agentId } = prep.data;\n const save = await service.saveConfig(nextConfig);\n if (!save.saved) {\n return c.json({ ok: false, error: { message: save.error ?? 'save failed' } }, 500);\n }\n const finalized = await finalizeCreateAgentDirs(service.currentConfig as Config, agentId, {\n ...(parsed.profileFiles !== undefined ? { profileFiles: parsed.profileFiles } : {}),\n ...(parsed.cloneFrom ? { cloneFrom: parsed.cloneFrom } : {}),\n });\n if (finalized.ok === false) {\n return c.json({ ok: false, error: { message: finalized.error } }, finalized.status ?? 400);\n }\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const agentsPayload = await listGatewayAgents(service.currentConfig as Config, { locale });\n return c.json({\n ok: true,\n payload: {\n agentId,\n agents: agentsPayload,\n },\n });\n });\n\n authenticated.get('/api/agents/:id/effective-manifest', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = getGatewayAgentEffectiveManifest(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.patch('/api/agents/:id', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n if (Object.hasOwn(body, 'model')) {\n return c.json({ ok: false, error: { message: 'model is not supported; use models.defaultRole and models.roles' } }, 400);\n }\n if (Object.hasOwn(body, 'typedModels')) {\n return c.json({ ok: false, error: { message: 'typedModels is not supported; use models.roles' } }, 400);\n }\n if (Object.hasOwn(body, 'toolsDisable')) {\n return c.json({ ok: false, error: { message: 'toolsDisable was removed; use tools.builtin policies' } }, 400);\n }\n if (Object.hasOwn(body, 'agentDir')) {\n return c.json({ ok: false, error: { message: 'agentDir was removed from agent manifests' } }, 400);\n }\n if (Object.hasOwn(body, 'name')) {\n return c.json({ ok: false, error: { message: 'name is not supported; edit IDENTITY.md' } }, 400);\n }\n if (Object.hasOwn(body, 'description')) {\n return c.json({ ok: false, error: { message: 'description is not supported; edit IDENTITY.md' } }, 400);\n }\n const skillsPatch =\n body.skills === null\n ? null\n : Array.isArray(body.skills)\n ? body.skills.map((x: unknown) => String(x).trim()).filter(Boolean)\n : undefined;\n const extendsPatch = Object.hasOwn(body, 'extends')\n ? Array.isArray(body.extends)\n ? body.extends.map((x: unknown) => String(x).trim()).filter(Boolean)\n : undefined\n : undefined;\n if (Object.hasOwn(body, 'extends') && extendsPatch === undefined) {\n return c.json({ ok: false, error: { message: 'extends must be an array' } }, 400);\n }\n let toolsPatch: CreateAgentBody['tools'] | null | undefined;\n if (Object.hasOwn(body, 'tools')) {\n if (body.tools === null) {\n toolsPatch = null;\n } else if (typeof body.tools === 'object' && !Array.isArray(body.tools)) {\n const parsedTools = ToolPolicySetSchema.safeParse(body.tools);\n if (!parsedTools.success) {\n return c.json({ ok: false, error: { message: `tools ${parsedTools.error.issues[0]?.message ?? 'is invalid'}` } }, 400);\n }\n toolsPatch = parsedTools.data;\n } else {\n return c.json({ ok: false, error: { message: 'tools must be an object or null' } }, 400);\n }\n }\n const modelsPatch = Object.hasOwn(body, 'models') ? parsePatchModels(body.models) : undefined;\n if (isParseError(modelsPatch)) {\n return c.json({ ok: false, error: { message: modelsPatch.error } }, 400);\n }\n let memoryPatch: Config['agents']['list'][number]['memory'] | undefined;\n if (Object.hasOwn(body, 'memory')) {\n const parsedMemory = MemoryPolicySchema.safeParse(body.memory);\n if (!parsedMemory.success) {\n return c.json({ ok: false, error: { message: `memory ${parsedMemory.error.issues[0]?.message ?? 'is invalid'}` } }, 400);\n }\n memoryPatch = parsedMemory.data;\n }\n\n const prep = prepareUpdateAgent(service.currentConfig as Config, id, {\n workspace: typeof body.workspace === 'string' ? body.workspace : undefined,\n ...(extendsPatch !== undefined ? { extends: extendsPatch } : {}),\n ...(modelsPatch !== undefined ? { models: modelsPatch } : {}),\n setDefault: body.setDefault === true,\n ...(skillsPatch !== undefined ? { skills: skillsPatch } : {}),\n ...(toolsPatch !== undefined ? { tools: toolsPatch } : {}),\n ...(memoryPatch !== undefined ? { memory: memoryPatch } : {}),\n });\n if (prep.ok === false) {\n return c.json({ ok: false, error: { message: prep.error } }, prep.status ?? 400);\n }\n const save = await service.saveConfig(prep.data.nextConfig);\n if (!save.saved) {\n return c.json({ ok: false, error: { message: save.error ?? 'save failed' } }, 500);\n }\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const agentsPayload = await listGatewayAgents(service.currentConfig as Config, { locale });\n return c.json({ ok: true, payload: agentsPayload });\n });\n\n authenticated.delete('/api/agents/:id', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const purge = c.req.query('purge') === '1' || c.req.query('purge') === 'true';\n const prep = prepareDeleteAgent(service.currentConfig as Config, id);\n if (prep.ok === false) {\n return c.json({ ok: false, error: { message: prep.error } }, prep.status ?? 400);\n }\n const { nextConfig, agentId } = prep.data;\n const save = await service.saveConfig(nextConfig);\n if (!save.saved) {\n return c.json({ ok: false, error: { message: save.error ?? 'save failed' } }, 500);\n }\n if (purge) {\n await runAfterDeletePurge(service.currentConfig as Config, agentId);\n }\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const agentsPayload = await listGatewayAgents(service.currentConfig as Config, { locale });\n return c.json({\n ok: true,\n payload: { agentId, purged: purge, agents: agentsPayload },\n });\n });\n\n authenticated.get('/api/agents/:id/avatar', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = await readAgentAvatarFile(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return new Response(res.data.buffer, {\n status: 200,\n headers: {\n 'Content-Type': res.data.contentType,\n 'Cache-Control': 'private, max-age=3600',\n },\n });\n });\n\n authenticated.put('/api/agents/:id/avatar', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const base64 = typeof body.base64 === 'string' ? body.base64 : '';\n const mimeType = typeof body.mimeType === 'string' ? body.mimeType : '';\n const res = await writeAgentAvatarFromBase64(service.currentConfig as Config, id, base64, mimeType);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId } });\n });\n\n authenticated.delete('/api/agents/:id/avatar', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = await deleteAgentAvatarFile(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId } });\n });\n\n authenticated.get('/api/agents/:id/files', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = await listAgentProfileFiles(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.get('/api/agents/:id/files/:name', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const name = decodeURIComponent(c.req.param('name') ?? '');\n const res = await readAgentProfileFile(service.currentConfig as Config, id, name);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId, name, content: res.data.content } });\n });\n\n authenticated.put('/api/agents/:id/files/:name', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const name = decodeURIComponent(c.req.param('name') ?? '');\n let content = '';\n try {\n const body = (await c.req.json()) as { content?: unknown };\n content = typeof body.content === 'string' ? body.content : '';\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const res = await writeAgentProfileFile(service.currentConfig as Config, id, name, content);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId, name } });\n });\n\n // GET /api/voice/models - Get available STT/TTS models\n authenticated.get('/api/voice/models', (c) => {\n const models = getVoiceModelsConfig();\n return c.json({ ok: true, payload: { models } });\n });\n\n}\n"],"mappings":"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"}
@@ -31,7 +31,10 @@ async function applyMiscPatch(config, body) {
31
31
  if (body.tui !== void 0) {
32
32
  if (typeof body.tui !== "object" || body.tui === null || Array.isArray(body.tui)) return patchError("tui must be an object");
33
33
  const tuiPatch = body.tui;
34
- if (tuiPatch.defaultAgent !== void 0) {
34
+ if (tuiPatch.defaultAgent !== void 0) if (tuiPatch.defaultAgent === null) {
35
+ config.tui = { ...config.tui };
36
+ delete config.tui.defaultAgent;
37
+ } else {
35
38
  if (typeof tuiPatch.defaultAgent !== "string" || !tuiPatch.defaultAgent.trim()) return patchError("tui.defaultAgent must be a non-empty string");
36
39
  const result = setTuiDefaultAgentConfig(config, tuiPatch.defaultAgent);
37
40
  if (result.ok === false) return patchError(result.message);
@@ -1 +1 @@
1
- {"version":3,"file":"misc.js","names":[],"sources":["../../../../../../src/gateway/hono/routes/config-patch/misc.ts"],"sourcesContent":["/**\n * `PATCH /api/config` — tail sections that are each <50 lines:\n * update / goals / session / gateway.{skillsMarketplaceProvider,\n * skillsStoreBaseUrl} / providers / providersConfig / stt / tts / tools /\n * tunnel / bindings / mcp.\n *\n * Most of these delegate to a `mergeXxxConfigPatch(config, body) → { ok,\n * message? }` helper that lives next to the schema, so this file is mostly\n * \"validate object shape, call helper, surface 400 on failure\". The async\n * `providers` branch saves into the credential resolver rather than config.\n *\n * Final validation (resolveGatewayAuth + assertGatewayRuntimeConfig) runs\n * after every gateway-touching patch lands, so it sees the merged shape.\n */\nimport type { Config } from '../../../../config/schema.js';\nimport { BindingsConfigSchema, BrowserConfigSchema, McpConfigSchema } from '../../../../config/schema.js';\nimport { CredentialResolver } from '../../../../auth/credentials.js';\nimport { isMaskedSecretPatchValue } from '../../lib/mask-secret-length.js';\nimport { applyToolsWebPatch } from '../../../config-tools-web.js';\nimport { mergeTunnelConfigPatch } from '../../../../tunnel/tunnel-config.js';\nimport { canonicalizeConfiguredMcpServer } from '../../../../config/mcp-config-normalize.js';\nimport { setTuiDefaultAgentConfig } from '../../../../commands/agents.config.js';\nimport {\n mergeGatewaySkillsMarketplacePatch,\n mergeGoalsConfigPatch,\n mergeSessionConfigPatch,\n mergeUpdateConfigPatch,\n} from '../../../../config/web-patch.js';\nimport { mergeSttConfigPatch, mergeTtsConfigPatch } from '../../lib/safe-voice-config.js';\nimport { assertGatewayRuntimeConfig } from '../../../runtime-config.js';\nimport { resolveGatewayAuth, assertGatewayAuthConfigured } from '../../../auth.js';\nimport { type PatchResult, PATCH_OK, patchError } from './result.js';\n\nexport async function applyMiscPatch(config: Config, body: any): Promise<PatchResult> {\n if (body.update !== undefined && typeof body.update === 'object' && body.update !== null) {\n const updateResult = mergeUpdateConfigPatch(config, body.update as Record<string, unknown>);\n if (updateResult.ok === false) {\n return patchError(updateResult.message);\n }\n }\n\n if (body.goals !== undefined) {\n if (typeof body.goals !== 'object' || body.goals === null || Array.isArray(body.goals)) {\n return patchError('goals must be an object');\n }\n const goalsResult = mergeGoalsConfigPatch(config, body.goals as Record<string, unknown>);\n if (goalsResult.ok === false) {\n return patchError(goalsResult.message);\n }\n }\n\n if (body.session !== undefined) {\n if (typeof body.session !== 'object' || body.session === null || Array.isArray(body.session)) {\n return patchError('session must be an object');\n }\n const sessionResult = mergeSessionConfigPatch(config, body.session as Record<string, unknown>);\n if (sessionResult.ok === false) {\n return patchError(sessionResult.message);\n }\n }\n\n if (body.tui !== undefined) {\n if (typeof body.tui !== 'object' || body.tui === null || Array.isArray(body.tui)) {\n return patchError('tui must be an object');\n }\n const tuiPatch = body.tui as Record<string, unknown>;\n if (tuiPatch.defaultAgent !== undefined) {\n if (typeof tuiPatch.defaultAgent !== 'string' || !tuiPatch.defaultAgent.trim()) {\n return patchError('tui.defaultAgent must be a non-empty string');\n }\n const result = setTuiDefaultAgentConfig(config, tuiPatch.defaultAgent);\n if (result.ok === false) {\n return patchError(result.message);\n }\n config.tui = result.config.tui;\n }\n }\n\n if (body.browser !== undefined) {\n if (typeof body.browser !== 'object' || body.browser === null || Array.isArray(body.browser)) {\n return patchError('browser must be an object');\n }\n const parsed = BrowserConfigSchema.safeParse(body.browser);\n if (!parsed.success) {\n return patchError(parsed.error.issues.map((i) => i.message).join('; '));\n }\n config.browser = parsed.data;\n }\n\n if (\n body.gateway !== undefined &&\n typeof body.gateway === 'object' &&\n body.gateway !== null &&\n !Array.isArray(body.gateway)\n ) {\n const gwPatch = body.gateway as Record<string, unknown>;\n if (gwPatch.skillsMarketplaceProvider !== undefined || gwPatch.skillsStoreBaseUrl !== undefined) {\n const skillsResult = mergeGatewaySkillsMarketplacePatch(config, {\n ...(gwPatch.skillsMarketplaceProvider !== undefined\n ? { skillsMarketplaceProvider: gwPatch.skillsMarketplaceProvider }\n : {}),\n ...(gwPatch.skillsStoreBaseUrl !== undefined\n ? { skillsStoreBaseUrl: gwPatch.skillsStoreBaseUrl }\n : {}),\n });\n if (skillsResult.ok === false) {\n return patchError(skillsResult.message);\n }\n }\n }\n\n // LLM provider credentials — saved into the credential system (not config).\n if (body.providers) {\n const resolver = new CredentialResolver();\n for (const [key, apiKey] of Object.entries(body.providers)) {\n if (\n apiKey !== undefined &&\n typeof apiKey === 'string' &&\n apiKey.trim() &&\n !isMaskedSecretPatchValue(apiKey)\n ) {\n await resolver.saveApiKey(key, apiKey, { profileName: 'default' });\n }\n }\n }\n\n // Structured per-vendor provider config (cfg.providers.<id>) for capability\n // providers (image / audio / video). Distinct from `body.providers` above\n // which targets the LLM-side credential resolver.\n if (body.providersConfig && typeof body.providersConfig === 'object' && !Array.isArray(body.providersConfig)) {\n const cfgProviders = (config as { providers?: Record<string, Record<string, unknown>> }).providers ?? {};\n for (const [vendorId, raw] of Object.entries(body.providersConfig as Record<string, unknown>)) {\n if (!vendorId || typeof vendorId !== 'string') continue;\n if (raw === null) {\n delete cfgProviders[vendorId];\n continue;\n }\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) continue;\n const next = (cfgProviders[vendorId] ?? {}) as Record<string, unknown>;\n const patch = raw as Record<string, unknown>;\n for (const field of ['apiKey', 'baseUrl', 'region', 'imageBaseUrl'] as const) {\n if (patch[field] === null || patch[field] === '') {\n delete next[field];\n } else if (typeof patch[field] === 'string') {\n const trimmed = (patch[field] as string).trim();\n if (field === 'apiKey' && isMaskedSecretPatchValue(trimmed)) {\n continue;\n }\n next[field] = trimmed;\n }\n }\n if (patch.azure === null) {\n delete next.azure;\n } else if (patch.azure && typeof patch.azure === 'object' && !Array.isArray(patch.azure)) {\n next.azure = { ...(next.azure as Record<string, unknown> ?? {}), ...(patch.azure as Record<string, unknown>) };\n }\n if (patch.request === null) {\n delete next.request;\n } else if (patch.request && typeof patch.request === 'object' && !Array.isArray(patch.request)) {\n next.request = { ...(next.request as Record<string, unknown> ?? {}), ...(patch.request as Record<string, unknown>) };\n }\n cfgProviders[vendorId] = next;\n }\n (config as { providers?: Record<string, Record<string, unknown>> }).providers = cfgProviders;\n }\n\n // PATCH `stt` writes to tools.media.audio; PATCH `tts` writes to messages.tts.\n if (body.stt !== undefined) {\n config.tools = config.tools ?? {};\n config.tools.media = config.tools.media ?? {};\n (config.tools.media as Record<string, unknown>).audio = mergeSttConfigPatch(\n config.tools.media.audio,\n body.stt,\n );\n }\n if (body.tts !== undefined) {\n config.messages = config.messages ?? {};\n (config.messages as Record<string, unknown>).tts = mergeTtsConfigPatch(\n config.messages.tts,\n body.tts,\n );\n }\n\n const toolsPatchErr = applyToolsWebPatch(config, body as Record<string, unknown>);\n if (toolsPatchErr) {\n return patchError(toolsPatchErr);\n }\n\n if (body.tunnel !== undefined) {\n if (!body.tunnel || typeof body.tunnel !== 'object' || Array.isArray(body.tunnel)) {\n return patchError('tunnel must be an object');\n }\n const tunnelResult = mergeTunnelConfigPatch(config, body.tunnel as Record<string, unknown>);\n if (tunnelResult.ok === false) {\n return patchError(tunnelResult.message);\n }\n }\n\n if (body.bindings !== undefined) {\n if (!Array.isArray(body.bindings)) {\n return patchError('bindings must be an array');\n }\n const parsed = BindingsConfigSchema.safeParse(body.bindings);\n if (!parsed.success) {\n return patchError(parsed.error.issues.map((i) => i.message).join('; '));\n }\n config.bindings = parsed.data;\n }\n\n if (body.mcp !== undefined) {\n if (body.mcp === null) {\n delete config.mcp;\n } else if (typeof body.mcp !== 'object' || Array.isArray(body.mcp)) {\n return patchError('mcp must be an object');\n } else {\n const parsed = McpConfigSchema.safeParse(body.mcp);\n if (!parsed.success) {\n return patchError(parsed.error.issues.map((i) => i.message).join('; '));\n }\n if (parsed.data === undefined) {\n delete config.mcp;\n } else {\n const next = { ...parsed.data };\n if (next.servers) {\n next.servers = Object.fromEntries(\n Object.entries(next.servers).map(([name, server]) => [\n name,\n canonicalizeConfiguredMcpServer(server as Record<string, unknown>),\n ]),\n );\n }\n config.mcp = next;\n }\n }\n }\n\n return PATCH_OK;\n}\n\n/**\n * Re-validate gateway runtime config when `body.gateway` touched anything that\n * could break the bind/auth contract. Runs *after* all per-section patches\n * land so it sees the fully merged shape.\n */\nexport function validateGatewayAfterPatch(config: Config, body: any): PatchResult {\n if (body.gateway === undefined) return PATCH_OK;\n try {\n const auth = resolveGatewayAuth({ authConfig: config.gateway?.auth });\n assertGatewayAuthConfigured(auth);\n assertGatewayRuntimeConfig({\n cfg: config,\n auth,\n port: config.gateway?.port ?? 18790,\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return patchError(message);\n }\n return PATCH_OK;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"misc.js","names":[],"sources":["../../../../../../src/gateway/hono/routes/config-patch/misc.ts"],"sourcesContent":["/**\n * `PATCH /api/config` — tail sections that are each <50 lines:\n * update / goals / session / gateway.{skillsMarketplaceProvider,\n * skillsStoreBaseUrl} / providers / providersConfig / stt / tts / tools /\n * tunnel / bindings / mcp.\n *\n * Most of these delegate to a `mergeXxxConfigPatch(config, body) → { ok,\n * message? }` helper that lives next to the schema, so this file is mostly\n * \"validate object shape, call helper, surface 400 on failure\". The async\n * `providers` branch saves into the credential resolver rather than config.\n *\n * Final validation (resolveGatewayAuth + assertGatewayRuntimeConfig) runs\n * after every gateway-touching patch lands, so it sees the merged shape.\n */\nimport type { Config } from '../../../../config/schema.js';\nimport { BindingsConfigSchema, BrowserConfigSchema, McpConfigSchema } from '../../../../config/schema.js';\nimport { CredentialResolver } from '../../../../auth/credentials.js';\nimport { isMaskedSecretPatchValue } from '../../lib/mask-secret-length.js';\nimport { applyToolsWebPatch } from '../../../config-tools-web.js';\nimport { mergeTunnelConfigPatch } from '../../../../tunnel/tunnel-config.js';\nimport { canonicalizeConfiguredMcpServer } from '../../../../config/mcp-config-normalize.js';\nimport { setTuiDefaultAgentConfig } from '../../../../commands/agents.config.js';\nimport {\n mergeGatewaySkillsMarketplacePatch,\n mergeGoalsConfigPatch,\n mergeSessionConfigPatch,\n mergeUpdateConfigPatch,\n} from '../../../../config/web-patch.js';\nimport { mergeSttConfigPatch, mergeTtsConfigPatch } from '../../lib/safe-voice-config.js';\nimport { assertGatewayRuntimeConfig } from '../../../runtime-config.js';\nimport { resolveGatewayAuth, assertGatewayAuthConfigured } from '../../../auth.js';\nimport { type PatchResult, PATCH_OK, patchError } from './result.js';\n\nexport async function applyMiscPatch(config: Config, body: any): Promise<PatchResult> {\n if (body.update !== undefined && typeof body.update === 'object' && body.update !== null) {\n const updateResult = mergeUpdateConfigPatch(config, body.update as Record<string, unknown>);\n if (updateResult.ok === false) {\n return patchError(updateResult.message);\n }\n }\n\n if (body.goals !== undefined) {\n if (typeof body.goals !== 'object' || body.goals === null || Array.isArray(body.goals)) {\n return patchError('goals must be an object');\n }\n const goalsResult = mergeGoalsConfigPatch(config, body.goals as Record<string, unknown>);\n if (goalsResult.ok === false) {\n return patchError(goalsResult.message);\n }\n }\n\n if (body.session !== undefined) {\n if (typeof body.session !== 'object' || body.session === null || Array.isArray(body.session)) {\n return patchError('session must be an object');\n }\n const sessionResult = mergeSessionConfigPatch(config, body.session as Record<string, unknown>);\n if (sessionResult.ok === false) {\n return patchError(sessionResult.message);\n }\n }\n\n if (body.tui !== undefined) {\n if (typeof body.tui !== 'object' || body.tui === null || Array.isArray(body.tui)) {\n return patchError('tui must be an object');\n }\n const tuiPatch = body.tui as Record<string, unknown>;\n if (tuiPatch.defaultAgent !== undefined) {\n if (tuiPatch.defaultAgent === null) {\n config.tui = { ...config.tui };\n delete config.tui.defaultAgent;\n } else {\n if (typeof tuiPatch.defaultAgent !== 'string' || !tuiPatch.defaultAgent.trim()) {\n return patchError('tui.defaultAgent must be a non-empty string');\n }\n const result = setTuiDefaultAgentConfig(config, tuiPatch.defaultAgent);\n if (result.ok === false) {\n return patchError(result.message);\n }\n config.tui = result.config.tui;\n }\n }\n }\n\n if (body.browser !== undefined) {\n if (typeof body.browser !== 'object' || body.browser === null || Array.isArray(body.browser)) {\n return patchError('browser must be an object');\n }\n const parsed = BrowserConfigSchema.safeParse(body.browser);\n if (!parsed.success) {\n return patchError(parsed.error.issues.map((i) => i.message).join('; '));\n }\n config.browser = parsed.data;\n }\n\n if (\n body.gateway !== undefined &&\n typeof body.gateway === 'object' &&\n body.gateway !== null &&\n !Array.isArray(body.gateway)\n ) {\n const gwPatch = body.gateway as Record<string, unknown>;\n if (gwPatch.skillsMarketplaceProvider !== undefined || gwPatch.skillsStoreBaseUrl !== undefined) {\n const skillsResult = mergeGatewaySkillsMarketplacePatch(config, {\n ...(gwPatch.skillsMarketplaceProvider !== undefined\n ? { skillsMarketplaceProvider: gwPatch.skillsMarketplaceProvider }\n : {}),\n ...(gwPatch.skillsStoreBaseUrl !== undefined\n ? { skillsStoreBaseUrl: gwPatch.skillsStoreBaseUrl }\n : {}),\n });\n if (skillsResult.ok === false) {\n return patchError(skillsResult.message);\n }\n }\n }\n\n // LLM provider credentials — saved into the credential system (not config).\n if (body.providers) {\n const resolver = new CredentialResolver();\n for (const [key, apiKey] of Object.entries(body.providers)) {\n if (\n apiKey !== undefined &&\n typeof apiKey === 'string' &&\n apiKey.trim() &&\n !isMaskedSecretPatchValue(apiKey)\n ) {\n await resolver.saveApiKey(key, apiKey, { profileName: 'default' });\n }\n }\n }\n\n // Structured per-vendor provider config (cfg.providers.<id>) for capability\n // providers (image / audio / video). Distinct from `body.providers` above\n // which targets the LLM-side credential resolver.\n if (body.providersConfig && typeof body.providersConfig === 'object' && !Array.isArray(body.providersConfig)) {\n const cfgProviders = (config as { providers?: Record<string, Record<string, unknown>> }).providers ?? {};\n for (const [vendorId, raw] of Object.entries(body.providersConfig as Record<string, unknown>)) {\n if (!vendorId || typeof vendorId !== 'string') continue;\n if (raw === null) {\n delete cfgProviders[vendorId];\n continue;\n }\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) continue;\n const next = (cfgProviders[vendorId] ?? {}) as Record<string, unknown>;\n const patch = raw as Record<string, unknown>;\n for (const field of ['apiKey', 'baseUrl', 'region', 'imageBaseUrl'] as const) {\n if (patch[field] === null || patch[field] === '') {\n delete next[field];\n } else if (typeof patch[field] === 'string') {\n const trimmed = (patch[field] as string).trim();\n if (field === 'apiKey' && isMaskedSecretPatchValue(trimmed)) {\n continue;\n }\n next[field] = trimmed;\n }\n }\n if (patch.azure === null) {\n delete next.azure;\n } else if (patch.azure && typeof patch.azure === 'object' && !Array.isArray(patch.azure)) {\n next.azure = { ...(next.azure as Record<string, unknown> ?? {}), ...(patch.azure as Record<string, unknown>) };\n }\n if (patch.request === null) {\n delete next.request;\n } else if (patch.request && typeof patch.request === 'object' && !Array.isArray(patch.request)) {\n next.request = { ...(next.request as Record<string, unknown> ?? {}), ...(patch.request as Record<string, unknown>) };\n }\n cfgProviders[vendorId] = next;\n }\n (config as { providers?: Record<string, Record<string, unknown>> }).providers = cfgProviders;\n }\n\n // PATCH `stt` writes to tools.media.audio; PATCH `tts` writes to messages.tts.\n if (body.stt !== undefined) {\n config.tools = config.tools ?? {};\n config.tools.media = config.tools.media ?? {};\n (config.tools.media as Record<string, unknown>).audio = mergeSttConfigPatch(\n config.tools.media.audio,\n body.stt,\n );\n }\n if (body.tts !== undefined) {\n config.messages = config.messages ?? {};\n (config.messages as Record<string, unknown>).tts = mergeTtsConfigPatch(\n config.messages.tts,\n body.tts,\n );\n }\n\n const toolsPatchErr = applyToolsWebPatch(config, body as Record<string, unknown>);\n if (toolsPatchErr) {\n return patchError(toolsPatchErr);\n }\n\n if (body.tunnel !== undefined) {\n if (!body.tunnel || typeof body.tunnel !== 'object' || Array.isArray(body.tunnel)) {\n return patchError('tunnel must be an object');\n }\n const tunnelResult = mergeTunnelConfigPatch(config, body.tunnel as Record<string, unknown>);\n if (tunnelResult.ok === false) {\n return patchError(tunnelResult.message);\n }\n }\n\n if (body.bindings !== undefined) {\n if (!Array.isArray(body.bindings)) {\n return patchError('bindings must be an array');\n }\n const parsed = BindingsConfigSchema.safeParse(body.bindings);\n if (!parsed.success) {\n return patchError(parsed.error.issues.map((i) => i.message).join('; '));\n }\n config.bindings = parsed.data;\n }\n\n if (body.mcp !== undefined) {\n if (body.mcp === null) {\n delete config.mcp;\n } else if (typeof body.mcp !== 'object' || Array.isArray(body.mcp)) {\n return patchError('mcp must be an object');\n } else {\n const parsed = McpConfigSchema.safeParse(body.mcp);\n if (!parsed.success) {\n return patchError(parsed.error.issues.map((i) => i.message).join('; '));\n }\n if (parsed.data === undefined) {\n delete config.mcp;\n } else {\n const next = { ...parsed.data };\n if (next.servers) {\n next.servers = Object.fromEntries(\n Object.entries(next.servers).map(([name, server]) => [\n name,\n canonicalizeConfiguredMcpServer(server as Record<string, unknown>),\n ]),\n );\n }\n config.mcp = next;\n }\n }\n }\n\n return PATCH_OK;\n}\n\n/**\n * Re-validate gateway runtime config when `body.gateway` touched anything that\n * could break the bind/auth contract. Runs *after* all per-section patches\n * land so it sees the fully merged shape.\n */\nexport function validateGatewayAfterPatch(config: Config, body: any): PatchResult {\n if (body.gateway === undefined) return PATCH_OK;\n try {\n const auth = resolveGatewayAuth({ authConfig: config.gateway?.auth });\n assertGatewayAuthConfigured(auth);\n assertGatewayRuntimeConfig({\n cfg: config,\n auth,\n port: config.gateway?.port ?? 18790,\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return patchError(message);\n }\n return PATCH_OK;\n}\n"],"mappings":"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"}
@@ -1,16 +1,21 @@
1
+ import { init_schema, parseModelRef } from "../../../config/schema.js";
1
2
  import { resolveModelsJsonPath } from "../../../config/paths.js";
2
3
  import { init_resolve_config_value, testApiKeyResolution } from "../../../config/resolve-config-value.js";
3
4
  import { init_models_json, loadModelsJson, saveModelsJson, validateModelsConfig } from "../../../config/models-json.js";
4
5
  import { getModelRegistry } from "../../../providers/model-registry.js";
5
6
  import { CredentialResolver, init_credentials } from "../../../auth/credentials.js";
6
7
  import { getProviderRegistry, init_plugin_registry } from "../../../providers/plugin-registry.js";
7
- import { PROVIDER_META, getAllModels, getAllProviders, getAvailableModels, getProviderAuthState, init_providers, isProviderConfigured } from "../../../providers/index.js";
8
+ import { PROVIDER_META, getAllModels, getAllProviders, getAvailableModels, getProviderAuthState, init_providers, isProviderConfigured, resolveModel } from "../../../providers/index.js";
8
9
  import { getImageGenerationProvider } from "../../../agent/image/generation/provider-registry.js";
9
10
  import { listImageGenerationProvidersSummary } from "../../../agent/image/generation/runtime.js";
10
- import { getProviderHint, getRecommendedModelsForProvider, isRecommendedModel, sortModelsForPicker, sortProvidersForPicker } from "../../../providers/presentation.js";
11
+ import { getDomesticProviderPreset, getDomesticProviderPresetIds } from "../../../providers/domestic-presets.js";
12
+ import { getOnboardingFeaturedProviders, getProviderHint, getRecommendedModelsForProvider, isRecommendedModel, sortModelsForPicker, sortProvidersForPicker } from "../../../providers/presentation.js";
13
+ import { resolveCurrentImageModelCapabilities, resolveImageGenerationCapabilities, resolveImageUnderstandingCapabilities } from "../../image-capabilities.js";
11
14
  import { respondStartupUnavailable } from "../lib/startup-unavailable.js";
15
+ import { discoverProviderModels, isProviderApiDiscoverable } from "../../../providers/model-discovery.js";
12
16
  //#region src/gateway/hono/routes/models.ts
13
17
  init_models_json();
18
+ init_schema();
14
19
  init_resolve_config_value();
15
20
  init_providers();
16
21
  init_credentials();
@@ -20,6 +25,11 @@ function readModelsJsonProviderApiKey(providerId) {
20
25
  const key = (config.providers?.[providerId.trim()])?.apiKey;
21
26
  return typeof key === "string" && key.trim() ? key.trim() : void 0;
22
27
  }
28
+ function readStringRecord(value) {
29
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
30
+ const entries = Object.entries(value).filter((entry) => typeof entry[1] === "string");
31
+ return entries.length > 0 ? Object.fromEntries(entries) : void 0;
32
+ }
23
33
  /** Plaintext key only when persisted under `cfg.providers.<id>.apiKey` (not env / credential store). */
24
34
  function readProviderApiKeyFromConfigFileOnly(cfg, providerId) {
25
35
  const id = providerId.trim().toLowerCase();
@@ -125,6 +135,50 @@ function registerModelsRoutes(authenticated, deps) {
125
135
  payload: result
126
136
  });
127
137
  });
138
+ authenticated.post("/api/models-json/discover-models", strictRateLimitMiddleware, async (c) => {
139
+ const body = await c.req.json().catch(() => ({}));
140
+ const rawProviderId = typeof body.providerId === "string" ? body.providerId.trim() : "";
141
+ const rawBaseUrl = typeof body.baseUrl === "string" ? body.baseUrl.trim() : "";
142
+ const rawApiKey = typeof body.apiKey === "string" ? body.apiKey.trim() : void 0;
143
+ const api = typeof body.api === "string" ? body.api : void 0;
144
+ const headers = readStringRecord(body.headers);
145
+ if (!rawProviderId) return c.json({
146
+ ok: false,
147
+ error: { message: "Missing providerId" }
148
+ }, 400);
149
+ if (!rawBaseUrl || !URL.canParse(rawBaseUrl)) return c.json({
150
+ ok: false,
151
+ error: { message: "Missing or invalid baseUrl" }
152
+ }, 400);
153
+ const providerApi = api;
154
+ if (!isProviderApiDiscoverable(providerApi)) return c.json({
155
+ ok: false,
156
+ error: { message: "Model discovery requires an OpenAI-compatible API type" }
157
+ }, 400);
158
+ try {
159
+ const models = await discoverProviderModels({
160
+ providerId: rawProviderId,
161
+ baseUrl: rawBaseUrl,
162
+ apiKey: rawApiKey,
163
+ api: providerApi,
164
+ headers
165
+ });
166
+ return c.json({
167
+ ok: true,
168
+ payload: { models: models.map((model) => ({
169
+ id: model.id,
170
+ name: model.name ?? model.id,
171
+ input: model.input ?? ["text"],
172
+ source: model.source
173
+ })) }
174
+ });
175
+ } catch (error) {
176
+ return c.json({
177
+ ok: false,
178
+ error: { message: error instanceof Error ? error.message : String(error) }
179
+ }, 502);
180
+ }
181
+ });
128
182
  authenticated.get("/api/models", async (c) => {
129
183
  if (!service.isGatewayReady()) return respondStartupUnavailable(c, "models.list");
130
184
  const pluginRegistry = getProviderRegistry();
@@ -161,6 +215,75 @@ function registerModelsRoutes(authenticated, deps) {
161
215
  payload: { models }
162
216
  });
163
217
  });
218
+ authenticated.get("/api/image/capabilities", async (c) => {
219
+ const config = service.currentConfig;
220
+ const imageGenerationProviders = await resolveImageGenerationCapabilities(config);
221
+ const imageUnderstandingProviders = await resolveImageUnderstandingCapabilities(config);
222
+ return c.json({
223
+ ok: true,
224
+ payload: {
225
+ current: resolveCurrentImageModelCapabilities(config),
226
+ imageGeneration: { providers: imageGenerationProviders },
227
+ imageUnderstanding: { providers: imageUnderstandingProviders }
228
+ }
229
+ });
230
+ });
231
+ authenticated.post("/api/image/validate-model", strictRateLimitMiddleware, async (c) => {
232
+ let body;
233
+ try {
234
+ body = await c.req.json();
235
+ } catch {
236
+ return c.json({
237
+ ok: false,
238
+ error: "Invalid JSON"
239
+ }, 400);
240
+ }
241
+ const modelRef = body.modelRef;
242
+ if (!modelRef || typeof modelRef !== "string") return c.json({
243
+ ok: false,
244
+ error: "modelRef is required"
245
+ }, 400);
246
+ const parsed = parseModelRef(modelRef);
247
+ if (!parsed) return c.json({
248
+ ok: true,
249
+ payload: {
250
+ valid: false,
251
+ reason: "invalid_format",
252
+ message: "Model reference must be in \"provider/model\" format"
253
+ }
254
+ });
255
+ if (!await isProviderConfigured(parsed.provider)) return c.json({
256
+ ok: true,
257
+ payload: {
258
+ valid: false,
259
+ reason: "provider_not_configured",
260
+ message: `Provider "${parsed.provider}" is not configured. Set the API key first.`,
261
+ provider: parsed.provider
262
+ }
263
+ });
264
+ try {
265
+ resolveModel(modelRef);
266
+ } catch {
267
+ return c.json({
268
+ ok: true,
269
+ payload: {
270
+ valid: false,
271
+ reason: "model_not_found",
272
+ message: `Model not found in registry: ${modelRef}`,
273
+ provider: parsed.provider,
274
+ model: parsed.model
275
+ }
276
+ });
277
+ }
278
+ return c.json({
279
+ ok: true,
280
+ payload: {
281
+ valid: true,
282
+ provider: parsed.provider,
283
+ model: parsed.model
284
+ }
285
+ });
286
+ });
164
287
  authenticated.get("/api/image/providers", (c) => {
165
288
  const cfg = deps.service.currentConfig;
166
289
  const providers = listImageGenerationProvidersSummary(cfg).map((p) => {
@@ -269,30 +392,25 @@ function registerModelsRoutes(authenticated, deps) {
269
392
  });
270
393
  });
271
394
  authenticated.get("/api/providers/meta", async (c) => {
272
- const providers = sortProvidersForPicker(getAllProviders());
395
+ const providers = sortProvidersForPicker([...new Set([...getAllProviders(), ...getDomesticProviderPresetIds()])]);
273
396
  const pluginRegistry = getProviderRegistry();
274
397
  const meta = await Promise.all(providers.map(async (provider) => {
275
398
  const plugin = pluginRegistry.get(provider);
399
+ const domesticPreset = getDomesticProviderPreset(provider);
276
400
  const extensionId = plugin ? resolveExtensionIdForProvider(service, provider) : void 0;
277
401
  const authState = await getProviderAuthState(provider);
278
402
  const configured = authState.authMode !== "none" || await isProviderConfigured(provider);
403
+ const registryModelCount = getAllModels().filter((m) => m.provider === provider).length;
279
404
  return {
280
405
  id: provider,
281
- name: plugin?.name ?? PROVIDER_META[provider]?.name ?? provider,
282
- category: plugin ? "extension" : PROVIDER_META[provider]?.category || "specialty",
406
+ name: plugin?.name ?? domesticPreset?.displayName ?? PROVIDER_META[provider]?.name ?? provider,
407
+ category: plugin ? "extension" : PROVIDER_META[provider]?.category || (domesticPreset ? "domestic" : "specialty"),
283
408
  supportsOAuth: plugin ? false : PROVIDER_META[provider]?.supportsOAuth ?? false,
284
409
  supportsApiKey: plugin ? false : PROVIDER_META[provider]?.supportsApiKey ?? true,
285
410
  configured,
286
- onboardingFeatured: [
287
- "openai",
288
- "anthropic",
289
- "xai",
290
- "google",
291
- "openrouter",
292
- "deepseek"
293
- ].includes(provider),
411
+ onboardingFeatured: getOnboardingFeaturedProviders().includes(provider),
294
412
  recommendedModels: getRecommendedModelsForProvider(provider),
295
- modelCount: getAllModels().filter((m) => m.provider === provider).length,
413
+ modelCount: registryModelCount || domesticPreset?.models.length || 0,
296
414
  ...getProviderHint(provider) ? { hint: getProviderHint(provider) } : {},
297
415
  activeKeySource: authState.authMode,
298
416
  authMode: authState.authMode,