@xopcai/xopc 0.0.162 → 0.0.163

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 (230) hide show
  1. package/README.md +4 -2
  2. package/README.zh-CN.md +4 -2
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/telegram/xopc.extension.json +1 -1
  5. package/dist/gateway/static/root/assets/{activity-store-hpcNv9MZ.js → activity-store-Xj95LzTv.js} +1 -1
  6. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-Zf9UQEmQ.js → agent-avatar-dicebear-C-QeUFwU.js} +1 -1
  7. package/dist/gateway/static/root/assets/agents-DVKlWKJE.js +2 -0
  8. package/dist/gateway/static/root/assets/{api-Dnatri09.js → api-BTLmAm1_.js} +1 -1
  9. package/dist/gateway/static/root/assets/{app-management-settings-panel-BBTR9wJP.js → app-management-settings-panel-zc6Gf-S5.js} +1 -1
  10. package/dist/gateway/static/root/assets/{appearance-settings-C2zpLCHD.js → appearance-settings-0fMLnOWn.js} +1 -1
  11. package/dist/gateway/static/root/assets/apps-page-BZXEJDIV.js +1 -0
  12. package/dist/gateway/static/root/assets/{archive-plugin-9eR_ODY1.js → archive-plugin-DOiR_E21.js} +1 -1
  13. package/dist/gateway/static/root/assets/{attachment-load-DPuWYUeX.js → attachment-load-BxmYl1D1.js} +1 -1
  14. package/dist/gateway/static/root/assets/{automation-suggestion-card-Dw49OJRl.js → automation-suggestion-card-BhZOirad.js} +1 -1
  15. package/dist/gateway/static/root/assets/automations-page-B8CnkoXv.js +6 -0
  16. package/dist/gateway/static/root/assets/{binary-plugins-BdkJpDFm.js → binary-plugins-DTTKsvgk.js} +1 -1
  17. package/dist/gateway/static/root/assets/{block-editor-CAi7SXYU.js → block-editor-C7se7iqg.js} +31 -31
  18. package/dist/gateway/static/root/assets/browser-settings-page-BCPWKI9V.js +8 -0
  19. package/dist/gateway/static/root/assets/{browser-workflow-inputs-Dx6wkGz1.js → browser-workflow-inputs-kxmStCcv.js} +1 -1
  20. package/dist/gateway/static/root/assets/{browser-workflows-page-Skertc-A.js → browser-workflows-page-CwYf9OM_.js} +2 -2
  21. package/dist/gateway/static/root/assets/capabilities-settings-panel-C7lr_mX2.js +2 -0
  22. package/dist/gateway/static/root/assets/{capability-presets-api-CNFl7dM3.js → capability-presets-api-BZKh2cWX.js} +1 -1
  23. package/dist/gateway/static/root/assets/capability-presets-settings-panel-Ble9kHRu.js +2 -0
  24. package/dist/gateway/static/root/assets/{channel-recipient-api-DYQyGDw4.js → channel-recipient-api-r7tdbnJE.js} +1 -1
  25. package/dist/gateway/static/root/assets/channels-settings-CtQQQHrv.js +1 -0
  26. package/dist/gateway/static/root/assets/channels-status-swr-_VirfMKW.js +1 -0
  27. package/dist/gateway/static/root/assets/{connector-logo-Bng6kxYF.js → connector-logo-BpnQYAxA.js} +1 -1
  28. package/dist/gateway/static/root/assets/connectors-page-BXWJSJeY.js +2 -0
  29. package/dist/gateway/static/root/assets/desktop-pet-B86W4a5c.js +1 -0
  30. package/dist/gateway/static/root/assets/{desktop-pet-settings-BVUyefSd.js → desktop-pet-settings-uv8Grtgk.js} +1 -1
  31. package/dist/gateway/static/root/assets/{directory-picker-path-field-DjSZAPz_.js → directory-picker-path-field-C4TTvf7p.js} +1 -1
  32. package/dist/gateway/static/root/assets/{dreaming-settings-CAZk2AM4.js → dreaming-settings-CzJAUPvM.js} +2 -2
  33. package/dist/gateway/static/root/assets/{extension-debug-page-C2F6vTTd.js → extension-debug-page-Ci2mOYUt.js} +1 -1
  34. package/dist/gateway/static/root/assets/{extension-page-AnIt4bn4.js → extension-page-DeXdmhXQ.js} +1 -1
  35. package/dist/gateway/static/root/assets/extension-settings-page-C93vaOsU.js +1 -0
  36. package/dist/gateway/static/root/assets/{gateway-config-api-DLFyZv33.js → gateway-config-api-C31Hlblp.js} +1 -1
  37. package/dist/gateway/static/root/assets/{gateway-settings-DnQAA-qq.js → gateway-settings-D3zS6RZh.js} +1 -1
  38. package/dist/gateway/static/root/assets/{gateway-startup-retry-DbzLyJ3R.js → gateway-startup-retry-CSRvCqxh.js} +1 -1
  39. package/dist/gateway/static/root/assets/{goal-create-dialog-DrnKFC6M.js → goal-create-dialog-CWp2b7__.js} +1 -1
  40. package/dist/gateway/static/root/assets/goal-detail-page-Dtm29FxD.js +4 -0
  41. package/dist/gateway/static/root/assets/{goals-config-api-REmr3QCr.js → goals-config-api-D4wYNRrf.js} +1 -1
  42. package/dist/gateway/static/root/assets/goals-page-jMzBJs6e.js +2 -0
  43. package/dist/gateway/static/root/assets/{goals-settings-Dz0F3uRO.js → goals-settings-Bx2jVvhQ.js} +1 -1
  44. package/dist/gateway/static/root/assets/{heartbeat-settings-CQFY5gYs.js → heartbeat-settings-BEIF1eXy.js} +1 -1
  45. package/dist/gateway/static/root/assets/index-BXtJvaQl.css +1 -0
  46. package/dist/gateway/static/root/assets/{index-C8JkTS6d.js → index-HZdBKfk_.js} +70 -70
  47. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BnOQXU5k.js → keyboard-shortcuts-settings-DOEDpvTM.js} +1 -1
  48. package/dist/gateway/static/root/assets/local-app-workbench-page-CseW9jD3.js +2 -0
  49. package/dist/gateway/static/root/assets/{local-apps-page-KsOtWOyM.js → local-apps-page-B0OpGpxv.js} +1 -1
  50. package/dist/gateway/static/root/assets/{locale-store-0lpYdNDr.js → locale-store-Ys6RP7Be.js} +1 -1
  51. package/dist/gateway/static/root/assets/logs-page-DVqPbth5.js +7 -0
  52. package/dist/gateway/static/root/assets/{markdown-split-D5GRg10r.js → markdown-split-CEZwysCH.js} +1 -1
  53. package/dist/gateway/static/root/assets/{media-plugins-C1ryULGs.js → media-plugins-CpGKE7B0.js} +1 -1
  54. package/dist/gateway/static/root/assets/messages-BzI9Wx30.js +5 -0
  55. package/dist/gateway/static/root/assets/{notes-page-CIeZ1_DT.js → notes-page-CdiuDZ5a.js} +1 -1
  56. package/dist/gateway/static/root/assets/notes-workbench-mrc3xtpn.js +4 -0
  57. package/dist/gateway/static/root/assets/{page-tabs-Caj1-E_X.js → page-tabs-BkH5AVV2.js} +1 -1
  58. package/dist/gateway/static/root/assets/{preview-open-alternatives-DKwEce-9.js → preview-open-alternatives-CQai8f9D.js} +1 -1
  59. package/dist/gateway/static/root/assets/{product-open-page-B90ZskkN.js → product-open-page-B2kSdB2b.js} +1 -1
  60. package/dist/gateway/static/root/assets/project-detail-page-CfhPJLkH.js +1 -0
  61. package/dist/gateway/static/root/assets/projects-page-BfMoKjdm.js +1 -0
  62. package/dist/gateway/static/root/assets/remote-access-hub-CrDtcsZ9.js +1 -0
  63. package/dist/gateway/static/root/assets/{save-bar-controls-BDYt53uQ.js → save-bar-controls-NGYnO7n7.js} +1 -1
  64. package/dist/gateway/static/root/assets/schedule-field-nLOphnv3.js +1 -0
  65. package/dist/gateway/static/root/assets/{schema-form-D7oCARF7.js → schema-form-D0e90ndE.js} +1 -1
  66. package/dist/gateway/static/root/assets/sessions-page-D3DbF3dV.js +1 -0
  67. package/dist/gateway/static/root/assets/settings-advanced-gate-BZp0O2dH.js +1 -0
  68. package/dist/gateway/static/root/assets/{settings-form-section-CARTHCxH.js → settings-form-section-X2Sl-EAk.js} +1 -1
  69. package/dist/gateway/static/root/assets/{settings-loading-skeleton-DEwYqESe.js → settings-loading-skeleton-DOnUabm7.js} +1 -1
  70. package/dist/gateway/static/root/assets/{settings-page-B6vVdHeQ.js → settings-page-C4UUNi1n.js} +1 -1
  71. package/dist/gateway/static/root/assets/{settings-page-layout-D3srt5Bi.js → settings-page-layout-C1yYqbT6.js} +1 -1
  72. package/dist/gateway/static/root/assets/setup-status-panel-84iao4DZ.js +1 -0
  73. package/dist/gateway/static/root/assets/{share-preview-page-Ck9SxiXw.js → share-preview-page-Cfy_pH7V.js} +1 -1
  74. package/dist/gateway/static/root/assets/shares-settings-DtcwQvRG.js +1 -0
  75. package/dist/gateway/static/root/assets/skill-reload-api-L7j5Gc8Z.js +1 -0
  76. package/dist/gateway/static/root/assets/skills-page-1Ps8PjsP.js +2 -0
  77. package/dist/gateway/static/root/assets/{system-settings-panel-DLBUQSk2.js → system-settings-panel-Da81RJ6G.js} +1 -1
  78. package/dist/gateway/static/root/assets/{theme-store-C1oaqeD2.js → theme-store-DflSp9o4.js} +1 -1
  79. package/dist/gateway/static/root/assets/time-picker-BIkOW-2L.js +1 -0
  80. package/dist/gateway/static/root/assets/{typed-models-lib-Divbg_C4.js → typed-models-lib--HptwFcD.js} +1 -1
  81. package/dist/gateway/static/root/assets/{use-channel-catalog-CP9a_rAf.js → use-channel-catalog-CMHY4ZfW.js} +1 -1
  82. package/dist/gateway/static/root/assets/user-context-page-BYAAs2iW.js +1 -0
  83. package/dist/gateway/static/root/assets/voice-api-key-field-nvIZerol.js +1 -0
  84. package/dist/gateway/static/root/assets/work-discovery-page-J35JkJ7_.js +1 -0
  85. package/dist/gateway/static/root/assets/work-item-detail-page-C4wYDYqV.js +1 -0
  86. package/dist/gateway/static/root/assets/work-page-DMvitV6c.js +1 -0
  87. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-DbDPYQwB.js → workflow-run-setup-panel-D96MHABy.js} +2 -2
  88. package/dist/gateway/static/root/assets/workflows-page-JMN0nMbM.js +11 -0
  89. package/dist/gateway/static/root/index.html +7 -7
  90. package/dist/package.js +1 -1
  91. package/dist/src/agent/client-error-format.d.ts +1 -1
  92. package/dist/src/agent/client-error-format.js +6 -2
  93. package/dist/src/agent/embedded/run-for-session.js +38 -31
  94. package/dist/src/agent/embedded/session-runner.d.ts +1 -0
  95. package/dist/src/agent/embedded/session-runner.js +12 -4
  96. package/dist/src/agent/failover-error.d.ts +1 -1
  97. package/dist/src/agent/image/generation/openai-compatible-image-provider.d.ts +2 -6
  98. package/dist/src/agent/image/generation/openai-compatible-image-provider.js +1 -3
  99. package/dist/src/agent/image/generation/provider-registry.d.ts +5 -46
  100. package/dist/src/agent/image/generation/provider-registry.js +24 -73
  101. package/dist/{extensions/dashscope/src/image-generation-provider.d.ts → src/agent/image/generation/providers/dashscope.d.ts} +3 -6
  102. package/dist/{extensions/dashscope/src/image-generation-provider.js → src/agent/image/generation/providers/dashscope.js} +36 -59
  103. package/dist/{extensions/fal/src/image-generation-provider.d.ts → src/agent/image/generation/providers/fal.d.ts} +1 -1
  104. package/dist/{extensions/fal/src/image-generation-provider.js → src/agent/image/generation/providers/fal.js} +19 -29
  105. package/dist/{extensions/google/src/image-generation-provider.d.ts → src/agent/image/generation/providers/google.d.ts} +2 -2
  106. package/dist/{extensions/google/src/image-generation-provider.js → src/agent/image/generation/providers/google.js} +23 -30
  107. package/dist/{extensions/minimax/src/image-generation-provider.d.ts → src/agent/image/generation/providers/minimax.d.ts} +2 -5
  108. package/dist/{extensions/minimax/src/image-generation-provider.js → src/agent/image/generation/providers/minimax.js} +35 -51
  109. package/dist/{extensions/openai/src/image-generation-provider.d.ts → src/agent/image/generation/providers/openai.d.ts} +2 -2
  110. package/dist/{extensions/openai/src/image-generation-provider.js → src/agent/image/generation/providers/openai.js} +13 -38
  111. package/dist/src/agent/image/generation/runtime-types.d.ts +1 -0
  112. package/dist/src/agent/image/generation/runtime.d.ts +1 -3
  113. package/dist/src/agent/image/generation/runtime.js +6 -6
  114. package/dist/src/agent/image/generation/types.d.ts +23 -3
  115. package/dist/src/agent/image/index.d.ts +1 -1
  116. package/dist/src/agent/image/index.js +2 -2
  117. package/dist/src/agent/media-generation/runtime-shared.d.ts +2 -0
  118. package/dist/src/agent/media-generation/runtime-shared.js +1 -0
  119. package/dist/src/agent/tools/factory.js +4 -1
  120. package/dist/src/agent/tools/image-generate-tool.d.ts +2 -0
  121. package/dist/src/agent/tools/image-generate-tool.js +14 -7
  122. package/dist/src/auth/sync-provider-auth.d.ts +3 -0
  123. package/dist/src/auth/sync-provider-auth.js +12 -1
  124. package/dist/src/cli/commands/models.js +2 -5
  125. package/dist/src/cli/commands/onboard/model.js +3 -2
  126. package/dist/src/cli/commands/setup-shared/types.d.ts +1 -1
  127. package/dist/src/config/index.js +2 -2
  128. package/dist/src/config/models-json.d.ts +6 -0
  129. package/dist/src/config/models-json.js +2 -6
  130. package/dist/src/config/schema.d.ts +26 -15
  131. package/dist/src/config/schema.js +23 -12
  132. package/dist/src/gateway/hono/app.js +12 -6
  133. package/dist/src/gateway/hono/lib/safe-providers-config.d.ts +0 -3
  134. package/dist/src/gateway/hono/lib/safe-providers-config.js +1 -3
  135. package/dist/src/gateway/hono/middleware/strict-rate-limit.d.ts +4 -0
  136. package/dist/src/gateway/hono/middleware/strict-rate-limit.js +8 -1
  137. package/dist/src/gateway/hono/routes/config-patch/misc.js +2 -11
  138. package/dist/src/gateway/hono/routes/deps.d.ts +1 -0
  139. package/dist/src/gateway/hono/routes/lazy-bundles.js +9 -2
  140. package/dist/src/gateway/hono/routes/models.js +151 -129
  141. package/dist/src/gateway/image-generation-setup.d.ts +40 -0
  142. package/dist/src/gateway/image-generation-setup.js +130 -0
  143. package/dist/src/gateway/rate-limit/buckets.d.ts +3 -0
  144. package/dist/src/gateway/rate-limit/buckets.js +12 -0
  145. package/dist/src/gateway/service.d.ts +3 -0
  146. package/dist/src/gateway/service.js +10 -0
  147. package/dist/src/media-shared/http/private-network.d.ts +1 -1
  148. package/dist/src/media-shared/http/private-network.js +1 -1
  149. package/dist/src/providers/auth-runtime/resolve-api-key.d.ts +2 -4
  150. package/dist/src/providers/auth-runtime/resolve-api-key.js +2 -4
  151. package/dist/src/providers/auth-runtime/resolve-auth.d.ts +3 -4
  152. package/dist/src/providers/auth-runtime/resolve-auth.js +18 -18
  153. package/dist/src/providers/domestic-presets.d.ts +22 -0
  154. package/dist/src/providers/domestic-presets.js +25 -0
  155. package/dist/src/providers/model-catalog-store.d.ts +71 -0
  156. package/dist/src/providers/model-catalog-store.js +102 -0
  157. package/dist/src/providers/model-catalog-sync-service.d.ts +41 -0
  158. package/dist/src/providers/model-catalog-sync-service.js +142 -0
  159. package/dist/src/providers/model-reference-auditor.d.ts +14 -0
  160. package/dist/src/providers/model-reference-auditor.js +71 -0
  161. package/dist/src/providers/model-registry.d.ts +4 -1
  162. package/dist/src/providers/model-registry.js +35 -2
  163. package/dist/src/providers/presentation.js +2 -0
  164. package/dist/src/providers/xopc-cloud-connection.d.ts +51 -0
  165. package/dist/src/providers/xopc-cloud-connection.js +196 -0
  166. package/dist/src/session/index.d.ts +1 -1
  167. package/dist/src/session/index.js +2 -2
  168. package/dist/src/session/session-title.d.ts +2 -0
  169. package/dist/src/session/session-title.js +24 -3
  170. package/package.json +5 -7
  171. package/dist/extensions/dashscope/src/index.d.ts +0 -4
  172. package/dist/extensions/dashscope/src/index.js +0 -2
  173. package/dist/extensions/dashscope/xopc.extension.json +0 -15
  174. package/dist/extensions/fal/src/index.d.ts +0 -4
  175. package/dist/extensions/fal/src/index.js +0 -2
  176. package/dist/extensions/fal/xopc.extension.json +0 -14
  177. package/dist/extensions/google/src/index.d.ts +0 -4
  178. package/dist/extensions/google/src/index.js +0 -2
  179. package/dist/extensions/google/xopc.extension.json +0 -14
  180. package/dist/extensions/minimax/src/index.d.ts +0 -4
  181. package/dist/extensions/minimax/src/index.js +0 -2
  182. package/dist/extensions/minimax/xopc.extension.json +0 -15
  183. package/dist/extensions/openai/src/index.d.ts +0 -4
  184. package/dist/extensions/openai/src/index.js +0 -2
  185. package/dist/extensions/openai/xopc.extension.json +0 -14
  186. package/dist/gateway/static/root/assets/agents-DfVkZlHc.js +0 -2
  187. package/dist/gateway/static/root/assets/apps-page-BMtAa4Ra.js +0 -1
  188. package/dist/gateway/static/root/assets/automations-page-BiSAMYTr.js +0 -6
  189. package/dist/gateway/static/root/assets/browser-settings-page-DHmaEJS2.js +0 -8
  190. package/dist/gateway/static/root/assets/capabilities-settings-panel-B5wSgf4f.js +0 -2
  191. package/dist/gateway/static/root/assets/capability-presets-settings-panel-DyvFZwBj.js +0 -2
  192. package/dist/gateway/static/root/assets/channels-settings-BBKEqDZn.js +0 -1
  193. package/dist/gateway/static/root/assets/channels-status-swr-Drk110ve.js +0 -1
  194. package/dist/gateway/static/root/assets/connectors-page-HpgaUDQ1.js +0 -2
  195. package/dist/gateway/static/root/assets/desktop-pet-Bpf6oegd.js +0 -1
  196. package/dist/gateway/static/root/assets/extension-settings-page-CLSc6682.js +0 -1
  197. package/dist/gateway/static/root/assets/goal-detail-page-Cw1hpJkZ.js +0 -4
  198. package/dist/gateway/static/root/assets/goals-page-BDGkTVma.js +0 -2
  199. package/dist/gateway/static/root/assets/index-hmrG55qg.css +0 -1
  200. package/dist/gateway/static/root/assets/local-app-workbench-page-Bdef1b7F.js +0 -2
  201. package/dist/gateway/static/root/assets/logs-page-CwLPgrWh.js +0 -7
  202. package/dist/gateway/static/root/assets/messages-BwQ3WssU.js +0 -5
  203. package/dist/gateway/static/root/assets/notes-workbench-Cf06q19x.js +0 -4
  204. package/dist/gateway/static/root/assets/project-detail-page-SHTurM4t.js +0 -1
  205. package/dist/gateway/static/root/assets/projects-page-BcC2qUAw.js +0 -1
  206. package/dist/gateway/static/root/assets/remote-access-hub-6vGefBHv.js +0 -1
  207. package/dist/gateway/static/root/assets/schedule-field-Bcdni4Pj.js +0 -1
  208. package/dist/gateway/static/root/assets/sessions-page-C5014a53.js +0 -1
  209. package/dist/gateway/static/root/assets/settings-advanced-gate-CDY3ZI1K.js +0 -1
  210. package/dist/gateway/static/root/assets/settings-collapsible-section-6eNF8Jey.js +0 -1
  211. package/dist/gateway/static/root/assets/setup-status-panel-z-rF0Hdg.js +0 -1
  212. package/dist/gateway/static/root/assets/shares-settings-CHZFXE_d.js +0 -1
  213. package/dist/gateway/static/root/assets/skill-reload-api-B7p2QNXt.js +0 -1
  214. package/dist/gateway/static/root/assets/skills-page-ncw3tX9P.js +0 -2
  215. package/dist/gateway/static/root/assets/user-context-page-iYfeSLKI.js +0 -1
  216. package/dist/gateway/static/root/assets/voice-api-key-field-CrwkicvT.js +0 -1
  217. package/dist/gateway/static/root/assets/work-discovery-page-BQWxyPg8.js +0 -1
  218. package/dist/gateway/static/root/assets/work-item-detail-page-50ZzGay5.js +0 -1
  219. package/dist/gateway/static/root/assets/work-page-DPqEahx7.js +0 -1
  220. package/dist/gateway/static/root/assets/workflows-page-C3eIC5HZ.js +0 -11
  221. package/dist/src/agent/image/generation/bundled-registry.d.ts +0 -18
  222. package/dist/src/agent/image/generation/bundled-registry.js +0 -35
  223. package/dist/src/agent/image/generation/bundled.d.ts +0 -10
  224. package/dist/src/agent/image/generation/bundled.js +0 -15
  225. package/dist/src/agent/image/generation/image-provider-ui.d.ts +0 -20
  226. package/dist/src/agent/image/generation/image-provider-ui.js +0 -1
  227. package/dist/src/gateway/image-capabilities.d.ts +0 -28
  228. package/dist/src/gateway/image-capabilities.js +0 -78
  229. package/dist/src/generated/bundled-image-generation-providers.d.ts +0 -14
  230. package/dist/src/generated/bundled-image-generation-providers.js +0 -17
@@ -1,25 +1,26 @@
1
- import { init_schema, parseModelRef } from "../../../config/schema.js";
2
1
  import { resolveModelsJsonPath } from "../../../config/paths.js";
3
2
  import { init_resolve_config_value, testApiKeyResolution } from "../../../config/resolve-config-value.js";
4
3
  import { init_models_json, loadModelsJson, saveModelsJson, validateModelsConfig } from "../../../config/models-json.js";
4
+ import { getModelCatalogStore, init_model_catalog_store } from "../../../providers/model-catalog-store.js";
5
5
  import { getModelRegistry } from "../../../providers/model-registry.js";
6
6
  import { CredentialResolver, init_credentials } from "../../../auth/credentials.js";
7
7
  import "../../../providers/constants.js";
8
8
  import { getProviderRegistry, init_plugin_registry } from "../../../providers/plugin-registry.js";
9
- import { PROVIDER_META, getAllModels, getAllProviders, getAvailableModels, getProviderAuthState, init_providers, isProviderConfigured, resolveModel } from "../../../providers/index.js";
10
- import { getImageGenerationProvider } from "../../../agent/image/generation/provider-registry.js";
11
- import { listImageGenerationProvidersSummary } from "../../../agent/image/generation/runtime.js";
9
+ import { PROVIDER_META, getAllModels, getAllProviders, getAvailableModels, getProviderAuthState, init_providers, isProviderConfigured } from "../../../providers/index.js";
10
+ import { SessionConfigStore } from "../../../session/config-store.js";
12
11
  import { getDomesticProviderPreset, getDomesticProviderPresetIds } from "../../../providers/domestic-presets.js";
13
12
  import { getOnboardingFeaturedProviders, getProviderHint, getRecommendedModelsForProvider, isRecommendedModel, sortModelsForPicker, sortProvidersForPicker } from "../../../providers/presentation.js";
14
- import { resolveCurrentImageModelCapabilities, resolveImageGenerationCapabilities, resolveImageUnderstandingCapabilities } from "../../image-capabilities.js";
15
- import { respondStartupUnavailable } from "../lib/startup-unavailable.js";
13
+ import { getAgentImageGenerationConfig, getImageGenerationCatalog, prepareImageGenerationSetup, verifyImageGenerationCredential } from "../../image-generation-setup.js";
16
14
  import { discoverProviderModels, isProviderApiDiscoverable } from "../../../providers/model-discovery.js";
15
+ import { XopcCloudHttpError } from "../../../providers/xopc-cloud-connection.js";
16
+ import { respondStartupUnavailable } from "../lib/startup-unavailable.js";
17
+ import { auditModelReferences } from "../../../providers/model-reference-auditor.js";
17
18
  //#region src/gateway/hono/routes/models.ts
18
19
  init_models_json();
19
- init_schema();
20
20
  init_resolve_config_value();
21
21
  init_providers();
22
22
  init_credentials();
23
+ init_model_catalog_store();
23
24
  init_plugin_registry();
24
25
  function readModelsJsonProviderApiKey(providerId) {
25
26
  const { config } = loadModelsJson(resolveModelsJsonPath());
@@ -31,14 +32,6 @@ function readStringRecord(value) {
31
32
  const entries = Object.entries(value).filter((entry) => typeof entry[1] === "string");
32
33
  return entries.length > 0 ? Object.fromEntries(entries) : void 0;
33
34
  }
34
- /** Plaintext key only when persisted under `cfg.providers.<id>.apiKey` (not env / credential store). */
35
- function readProviderApiKeyFromConfigFileOnly(cfg, providerId) {
36
- const id = providerId.trim().toLowerCase();
37
- const bucket = cfg.providers?.[id];
38
- if (!bucket || typeof bucket !== "object" || Array.isArray(bucket)) return void 0;
39
- const k = bucket.apiKey;
40
- return typeof k === "string" && k.trim() ? k.trim() : void 0;
41
- }
42
35
  /** Extension id from manifest `providers[]` (e.g. provider `demo` → extension `demo-provider`). */
43
36
  function resolveExtensionIdForProvider(service, providerId) {
44
37
  const loader = service.getExtensionLoader();
@@ -70,7 +63,85 @@ function mapPluginModel(providerId, model, available) {
70
63
  };
71
64
  }
72
65
  function registerModelsRoutes(authenticated, deps) {
73
- const { service, strictRateLimitMiddleware } = deps;
66
+ const { service, strictRateLimitMiddleware, xopcCloudPollRateLimitMiddleware } = deps;
67
+ const catalogSync = service.getModelCatalogSync();
68
+ const xopcCloud = catalogSync.getXopcCloudConnection();
69
+ authenticated.post("/api/models/xopc-cloud/connect", strictRateLimitMiddleware, async (c) => {
70
+ const body = await c.req.json().catch(() => ({}));
71
+ const clientType = body.clientType === "electron" || body.clientType === "cli" ? body.clientType : "web";
72
+ try {
73
+ return c.json({
74
+ ok: true,
75
+ payload: await xopcCloud.start(clientType)
76
+ }, 201);
77
+ } catch (error) {
78
+ return c.json({
79
+ ok: false,
80
+ error: { message: error instanceof Error ? error.message : "Connection failed" }
81
+ }, 502);
82
+ }
83
+ });
84
+ authenticated.post("/api/models/xopc-cloud/connect/:requestId/poll", xopcCloudPollRateLimitMiddleware, async (c) => {
85
+ try {
86
+ const result = await xopcCloud.poll(c.req.param("requestId"));
87
+ if (result.status === "pending") return c.json({
88
+ ok: true,
89
+ payload: result
90
+ }, 202);
91
+ service.emit("model-catalog.updated", { modelCount: getModelRegistry().getAll().length });
92
+ return c.json({
93
+ ok: true,
94
+ payload: result
95
+ });
96
+ } catch (error) {
97
+ return c.json({
98
+ ok: false,
99
+ error: { message: error instanceof Error ? error.message : "Connection failed" }
100
+ }, 400);
101
+ }
102
+ });
103
+ authenticated.post("/api/models/xopc-cloud/refresh", strictRateLimitMiddleware, async (c) => {
104
+ try {
105
+ const result = await catalogSync.refreshNow();
106
+ return c.json({
107
+ ok: true,
108
+ payload: result
109
+ });
110
+ } catch (error) {
111
+ const status = error instanceof XopcCloudHttpError && error.status === 401 ? 401 : error instanceof XopcCloudHttpError && error.status === 403 ? 403 : 502;
112
+ return c.json({
113
+ ok: false,
114
+ error: {
115
+ message: error instanceof Error ? error.message : "Refresh failed",
116
+ ...error instanceof XopcCloudHttpError && error.code ? { code: error.code } : {}
117
+ }
118
+ }, status);
119
+ }
120
+ });
121
+ authenticated.get("/api/models/catalog/status", (c) => c.json({
122
+ ok: true,
123
+ payload: catalogSync.getStatus()
124
+ }));
125
+ authenticated.get("/api/models/catalog", async (c) => {
126
+ const catalog = getModelCatalogStore().load();
127
+ const sessionConfigs = await new SessionConfigStore("").getAll();
128
+ const references = auditModelReferences(service.currentConfig, sessionConfigs, { catalog });
129
+ return c.json({
130
+ ok: true,
131
+ payload: {
132
+ sources: catalog.sources,
133
+ sync: catalogSync.getStatus(),
134
+ references
135
+ }
136
+ });
137
+ });
138
+ authenticated.post("/api/models/catalog/refresh", strictRateLimitMiddleware, async (c) => {
139
+ const result = await catalogSync.refreshAll();
140
+ return c.json({
141
+ ok: true,
142
+ payload: result
143
+ });
144
+ });
74
145
  authenticated.get("/api/models-json", async (c) => {
75
146
  const path = resolveModelsJsonPath();
76
147
  const { config, error } = loadModelsJson(path);
@@ -216,142 +287,93 @@ function registerModelsRoutes(authenticated, deps) {
216
287
  payload: { models }
217
288
  });
218
289
  });
219
- authenticated.get("/api/image/capabilities", async (c) => {
220
- const config = service.currentConfig;
221
- const agentId = c.req.query("agentId")?.trim() || void 0;
222
- const imageGenerationProviders = await resolveImageGenerationCapabilities(config);
223
- const imageUnderstandingProviders = await resolveImageUnderstandingCapabilities(config);
290
+ authenticated.get("/api/image-generation/catalog", (c) => {
224
291
  return c.json({
225
292
  ok: true,
226
- payload: {
227
- current: resolveCurrentImageModelCapabilities(config, agentId),
228
- imageGeneration: { providers: imageGenerationProviders },
229
- imageUnderstanding: { providers: imageUnderstandingProviders }
230
- }
293
+ payload: { providers: getImageGenerationCatalog(service.currentConfig) }
231
294
  });
232
295
  });
233
- authenticated.post("/api/image/validate-model", strictRateLimitMiddleware, async (c) => {
234
- let body;
296
+ authenticated.get("/api/agents/:agentId/image-generation", (c) => {
235
297
  try {
236
- body = await c.req.json();
237
- } catch {
298
+ return c.json({
299
+ ok: true,
300
+ payload: getAgentImageGenerationConfig(service.currentConfig, c.req.param("agentId"))
301
+ });
302
+ } catch (error) {
238
303
  return c.json({
239
304
  ok: false,
240
- error: "Invalid JSON"
241
- }, 400);
305
+ error: { message: error instanceof Error ? error.message : String(error) }
306
+ }, 404);
242
307
  }
243
- const modelRef = body.modelRef;
244
- if (!modelRef || typeof modelRef !== "string") return c.json({
308
+ });
309
+ authenticated.post("/api/agents/:agentId/image-generation/setup", strictRateLimitMiddleware, async (c) => {
310
+ const body = await c.req.json().catch(() => null);
311
+ if (!body || typeof body.providerId !== "string") return c.json({
245
312
  ok: false,
246
- error: "modelRef is required"
313
+ error: { message: "providerId is required" }
247
314
  }, 400);
248
- const parsed = parseModelRef(modelRef);
249
- if (!parsed) return c.json({
250
- ok: true,
251
- payload: {
252
- valid: false,
253
- reason: "invalid_format",
254
- message: "Model reference must be in \"provider/model\" format"
255
- }
256
- });
257
- if (!await isProviderConfigured(parsed.provider)) return c.json({
258
- ok: true,
259
- payload: {
260
- valid: false,
261
- reason: "provider_not_configured",
262
- message: `Provider "${parsed.provider}" is not configured. Set the API key first.`,
263
- provider: parsed.provider
264
- }
315
+ const prepared = prepareImageGenerationSetup(service.currentConfig, c.req.param("agentId"), {
316
+ providerId: body.providerId,
317
+ ...typeof body.modelId === "string" ? { modelId: body.modelId } : {},
318
+ ...body.region === "cn" || body.region === "intl" ? { region: body.region } : {},
319
+ ...typeof body.baseUrl === "string" ? { baseUrl: body.baseUrl } : {}
265
320
  });
266
- try {
267
- resolveModel(modelRef);
268
- } catch {
321
+ if (prepared.ok === false) return c.json({
322
+ ok: false,
323
+ error: { message: prepared.error }
324
+ }, 400);
325
+ const resolver = new CredentialResolver();
326
+ const previousKey = await resolver.revealGatewayStoredApiKey(prepared.providerId);
327
+ const suppliedKey = typeof body.apiKey === "string" ? body.apiKey.trim() : "";
328
+ if (!(suppliedKey || await resolver.resolveApiKey(prepared.providerId))) return c.json({
329
+ ok: false,
330
+ error: { message: "API key is required" }
331
+ }, 400);
332
+ const verification = suppliedKey ? await verifyImageGenerationCredential({
333
+ providerId: prepared.providerId,
334
+ apiKey: suppliedKey,
335
+ baseUrl: typeof body.baseUrl === "string" ? body.baseUrl : void 0
336
+ }) : {
337
+ verified: false,
338
+ supported: false
339
+ };
340
+ if (verification.supported && !verification.verified) return c.json({
341
+ ok: false,
342
+ error: { message: verification.message ?? "Credential verification failed" }
343
+ }, 400);
344
+ if (suppliedKey) await resolver.saveApiKey(prepared.providerId, suppliedKey, { profileName: "default" });
345
+ const saved = await service.saveConfig(prepared.config);
346
+ if (!saved.saved) {
347
+ if (suppliedKey) if (previousKey) await resolver.saveApiKey(prepared.providerId, previousKey, { profileName: "default" });
348
+ else await resolver.deleteProfile(`${prepared.providerId}:default`);
269
349
  return c.json({
270
- ok: true,
271
- payload: {
272
- valid: false,
273
- reason: "model_not_found",
274
- message: `Model not found in registry: ${modelRef}`,
275
- provider: parsed.provider,
276
- model: parsed.model
277
- }
278
- });
350
+ ok: false,
351
+ error: { message: saved.error ?? "Failed to save configuration" }
352
+ }, 500);
279
353
  }
280
354
  return c.json({
281
355
  ok: true,
282
356
  payload: {
283
- valid: true,
284
- provider: parsed.provider,
285
- model: parsed.model
286
- }
287
- });
288
- });
289
- authenticated.get("/api/image/providers", (c) => {
290
- const cfg = deps.service.currentConfig;
291
- const providers = listImageGenerationProvidersSummary(cfg).map((p) => {
292
- const provider = getImageGenerationProvider(p.id, cfg);
293
- let configured = false;
294
- try {
295
- configured = provider?.isConfigured?.({ cfg }) === true;
296
- } catch {
297
- configured = false;
357
+ agent: getAgentImageGenerationConfig(service.currentConfig, c.req.param("agentId")),
358
+ providers: getImageGenerationCatalog(service.currentConfig),
359
+ verification
298
360
  }
299
- return {
300
- ...p,
301
- configured
302
- };
303
- });
304
- return c.json({
305
- ok: true,
306
- payload: { providers }
307
361
  });
308
362
  });
309
- authenticated.post("/api/image/providers/:id/test", (c) => {
310
- const id = c.req.param("id");
311
- const cfg = deps.service.currentConfig;
312
- const provider = getImageGenerationProvider(id, cfg);
313
- if (!provider) return c.json({
363
+ authenticated.post("/api/image-generation/providers/:providerId/verify", strictRateLimitMiddleware, async (c) => {
364
+ const body = await c.req.json().catch(() => null);
365
+ if (!body || typeof body.apiKey !== "string") return c.json({
314
366
  ok: false,
315
- error: { message: `Image generation provider not found: ${id}` }
316
- }, 404);
317
- let configured = false;
318
- let reason;
319
- try {
320
- configured = provider.isConfigured?.({ cfg }) === true;
321
- if (!configured) reason = "Missing API key (set via config or environment).";
322
- } catch (err) {
323
- reason = err instanceof Error ? err.message : String(err);
324
- }
325
- return c.json({
326
- ok: true,
327
- payload: {
328
- id: provider.id,
329
- configured,
330
- ...reason ? { reason } : {},
331
- defaultModel: provider.defaultModel ?? null
332
- }
367
+ error: { message: "apiKey is required" }
368
+ }, 400);
369
+ const result = await verifyImageGenerationCredential({
370
+ providerId: c.req.param("providerId"),
371
+ apiKey: body.apiKey,
372
+ baseUrl: typeof body.baseUrl === "string" ? body.baseUrl : void 0
333
373
  });
334
- });
335
- /**
336
- * POST /api/image/providers/:id/reveal-api-key — return `cfg.providers.<id>.apiKey` plaintext for the
337
- * gateway console (same auth as PATCH /api/config). Does not resolve env vars or credential files.
338
- */
339
- authenticated.post("/api/image/providers/:id/reveal-api-key", strictRateLimitMiddleware, async (c) => {
340
- const rawId = c.req.param("id");
341
- const cfg = deps.service.currentConfig;
342
- const provider = getImageGenerationProvider(rawId, cfg);
343
- if (!provider) return c.json({
344
- ok: false,
345
- error: { message: `Image generation provider not found: ${rawId}` }
346
- }, 404);
347
- const apiKey = readProviderApiKeyFromConfigFileOnly(cfg, provider.id);
348
374
  return c.json({
349
375
  ok: true,
350
- payload: {
351
- id: provider.id,
352
- apiKey: apiKey ?? null,
353
- source: apiKey ? "config" : "none"
354
- }
376
+ payload: result
355
377
  });
356
378
  });
357
379
  authenticated.get("/api/providers", async (c) => {
@@ -0,0 +1,40 @@
1
+ import { listImageGenerationProvidersSummary } from '../agent/image/generation/provider-registry.js';
2
+ import { type Config } from '../config/schema.js';
3
+ export type ImageGenerationSetupInput = {
4
+ providerId: string;
5
+ modelId?: string;
6
+ region?: 'cn' | 'intl';
7
+ baseUrl?: string;
8
+ };
9
+ export type ImageGenerationCatalogItem = ReturnType<typeof listImageGenerationProvidersSummary>[number] & {
10
+ configured: boolean;
11
+ requiresRegion: boolean;
12
+ };
13
+ export declare function getImageGenerationCatalog(config: Config): ImageGenerationCatalogItem[];
14
+ export declare function getAgentImageGenerationConfig(config: Config, agentIdRaw: string): {
15
+ agentId: string;
16
+ model: {
17
+ primary: string;
18
+ fallbacks?: string[];
19
+ timeoutMs?: number;
20
+ autoProviderFallback?: boolean;
21
+ };
22
+ };
23
+ export declare function prepareImageGenerationSetup(config: Config, agentIdRaw: string, input: ImageGenerationSetupInput): {
24
+ ok: true;
25
+ config: Config;
26
+ providerId: string;
27
+ modelId: string;
28
+ } | {
29
+ ok: false;
30
+ error: string;
31
+ };
32
+ export declare function verifyImageGenerationCredential(input: {
33
+ providerId: string;
34
+ apiKey: string;
35
+ baseUrl?: string;
36
+ }): Promise<{
37
+ verified: boolean;
38
+ supported: boolean;
39
+ message?: string;
40
+ }>;
@@ -0,0 +1,130 @@
1
+ import { ConfigSchema, init_schema } from "../config/schema.js";
2
+ import { init_agent_scope, normalizeAgentId } from "../agent/agent-scope.js";
3
+ import { resolveEffectiveAgentManifestForAgent } from "../config/agent-profile.js";
4
+ import { fetchWithTimeoutGuarded } from "../media-shared/http/provider-http.js";
5
+ import "../media-shared/http/index.js";
6
+ import { getImageGenerationProvider, listImageGenerationProvidersSummary } from "../agent/image/generation/provider-registry.js";
7
+ //#region src/gateway/image-generation-setup.ts
8
+ init_agent_scope();
9
+ init_schema();
10
+ function getImageGenerationCatalog(config) {
11
+ return listImageGenerationProvidersSummary().map((summary) => {
12
+ const provider = getImageGenerationProvider(summary.id);
13
+ return {
14
+ ...summary,
15
+ configured: provider.isConfigured({ cfg: config }),
16
+ requiresRegion: summary.id === "dashscope" || summary.id === "minimax"
17
+ };
18
+ });
19
+ }
20
+ function getAgentImageGenerationConfig(config, agentIdRaw) {
21
+ const agentId = normalizeAgentId(agentIdRaw);
22
+ if (!config.agents.list.some((entry) => entry.enabled !== false && normalizeAgentId(entry.id) === agentId)) throw new Error(`Agent not found: ${agentId}`);
23
+ return {
24
+ agentId,
25
+ model: resolveEffectiveAgentManifestForAgent(config, agentId).models.imageGenerationModel ?? null
26
+ };
27
+ }
28
+ function prepareImageGenerationSetup(config, agentIdRaw, input) {
29
+ const agentId = normalizeAgentId(agentIdRaw);
30
+ if (!config.agents.list.some((entry) => entry.enabled !== false && normalizeAgentId(entry.id) === agentId)) return {
31
+ ok: false,
32
+ error: `Agent not found: ${agentId}`
33
+ };
34
+ const providerId = input.providerId.trim();
35
+ const provider = getImageGenerationProvider(providerId);
36
+ if (!provider) return {
37
+ ok: false,
38
+ error: `Unknown image provider: ${providerId}`
39
+ };
40
+ const modelId = input.modelId?.trim() || provider.defaultModel;
41
+ if (!provider.models.includes(modelId)) return {
42
+ ok: false,
43
+ error: `Unknown ${providerId} image model: ${modelId}`
44
+ };
45
+ if ((providerId === "dashscope" || providerId === "minimax") && input.region !== "cn" && input.region !== "intl") return {
46
+ ok: false,
47
+ error: `${providerId} requires region "cn" or "intl"`
48
+ };
49
+ const next = structuredClone(config);
50
+ const index = next.agents.list.findIndex((entry) => entry.enabled !== false && normalizeAgentId(entry.id) === agentId);
51
+ if (index < 0) return {
52
+ ok: false,
53
+ error: `Agent not found: ${agentId}`
54
+ };
55
+ const connection = {
56
+ ...input.region ? { region: input.region } : {},
57
+ ...input.baseUrl?.trim() ? { baseUrl: input.baseUrl.trim() } : {}
58
+ };
59
+ next.providers = {
60
+ ...next.providers ?? {},
61
+ [providerId]: {
62
+ ...next.providers?.[providerId] ?? {},
63
+ ...connection
64
+ }
65
+ };
66
+ const entry = next.agents.list[index];
67
+ entry.models.imageGenerationModel = { primary: `${providerId}/${modelId}` };
68
+ const parsed = ConfigSchema.safeParse(next);
69
+ if (!parsed.success) return {
70
+ ok: false,
71
+ error: parsed.error.issues.map((issue) => issue.message).join("; ")
72
+ };
73
+ return {
74
+ ok: true,
75
+ config: next,
76
+ providerId,
77
+ modelId
78
+ };
79
+ }
80
+ async function verifyImageGenerationCredential(input) {
81
+ const apiKey = input.apiKey.trim();
82
+ if (!apiKey) return {
83
+ verified: false,
84
+ supported: true,
85
+ message: "API key is required"
86
+ };
87
+ if (!getImageGenerationProvider(input.providerId)) return {
88
+ verified: false,
89
+ supported: true,
90
+ message: `Unknown image provider: ${input.providerId}`
91
+ };
92
+ let url;
93
+ let headers = {};
94
+ if (input.providerId === "openai") {
95
+ url = `${input.baseUrl?.trim().replace(/\/+$/, "") || "https://api.openai.com/v1"}/models`;
96
+ headers = { Authorization: `Bearer ${apiKey}` };
97
+ } else if (input.providerId === "google") url = `${input.baseUrl?.trim().replace(/\/+$/, "") || "https://generativelanguage.googleapis.com"}/v1beta/models?pageSize=1&key=${encodeURIComponent(apiKey)}`;
98
+ else return {
99
+ verified: false,
100
+ supported: false
101
+ };
102
+ try {
103
+ const response = await fetchWithTimeoutGuarded(url, {
104
+ timeoutMs: 1e4,
105
+ label: `${input.providerId} credential verification`,
106
+ allowPrivateNetwork: false,
107
+ init: {
108
+ headers,
109
+ redirect: "error"
110
+ }
111
+ });
112
+ if (response.ok) return {
113
+ verified: true,
114
+ supported: true
115
+ };
116
+ return {
117
+ verified: false,
118
+ supported: true,
119
+ message: `Provider returned HTTP ${response.status}`
120
+ };
121
+ } catch (error) {
122
+ return {
123
+ verified: false,
124
+ supported: true,
125
+ message: error instanceof Error ? error.message : String(error)
126
+ };
127
+ }
128
+ }
129
+ //#endregion
130
+ export { getAgentImageGenerationConfig, getImageGenerationCatalog, prepareImageGenerationSetup, verifyImageGenerationCredential };
@@ -35,6 +35,7 @@ declare class BucketRegistry {
35
35
  private authFailureLimiter?;
36
36
  private authFailureSignature?;
37
37
  private strictApiLimiter?;
38
+ private xopcCloudPollLimiter?;
38
39
  private channelApiLimiter?;
39
40
  private tunnelMutateLimiter?;
40
41
  private pairingExchangeLimiter?;
@@ -48,6 +49,8 @@ declare class BucketRegistry {
48
49
  authFailure(cfg: ResolvedAuthRateLimitConfig): FailureLimiter;
49
50
  /** Sensitive admin / mutation endpoints — 15 req / 60 s per client IP. */
50
51
  strictApi(): RateLimiter;
52
+ /** XOPC Cloud authorization polling — 60 req / 60 s per client IP. */
53
+ xopcCloudPoll(): RateLimiter;
51
54
  /** Channel mutation/action endpoints — 20 req / 60 s per client IP. */
52
55
  channelApi(): RateLimiter;
53
56
  /** Tunnel mutation calls — 12 req / 5 min per gateway-token fingerprint. */
@@ -47,6 +47,7 @@ var BucketRegistry = class {
47
47
  authFailureLimiter;
48
48
  authFailureSignature;
49
49
  strictApiLimiter;
50
+ xopcCloudPollLimiter;
50
51
  channelApiLimiter;
51
52
  tunnelMutateLimiter;
52
53
  pairingExchangeLimiter;
@@ -79,6 +80,14 @@ var BucketRegistry = class {
79
80
  });
80
81
  return this.strictApiLimiter;
81
82
  }
83
+ /** XOPC Cloud authorization polling — 60 req / 60 s per client IP. */
84
+ xopcCloudPoll() {
85
+ if (!this.xopcCloudPollLimiter) this.xopcCloudPollLimiter = new RateLimiter({
86
+ maxRequests: 60,
87
+ windowMs: 6e4
88
+ });
89
+ return this.xopcCloudPollLimiter;
90
+ }
82
91
  /** Channel mutation/action endpoints — 20 req / 60 s per client IP. */
83
92
  channelApi() {
84
93
  if (!this.channelApiLimiter) this.channelApiLimiter = new RateLimiter({
@@ -123,6 +132,7 @@ var BucketRegistry = class {
123
132
  destroyAll() {
124
133
  this.authFailureLimiter?.destroy();
125
134
  this.strictApiLimiter?.destroy();
135
+ this.xopcCloudPollLimiter?.destroy();
126
136
  this.channelApiLimiter?.destroy();
127
137
  this.tunnelMutateLimiter?.destroy();
128
138
  this.pairingExchangeLimiter?.destroy();
@@ -130,6 +140,7 @@ var BucketRegistry = class {
130
140
  this.sharePublicLongLimiter?.destroy();
131
141
  this.authFailureLimiter = void 0;
132
142
  this.strictApiLimiter = void 0;
143
+ this.xopcCloudPollLimiter = void 0;
133
144
  this.channelApiLimiter = void 0;
134
145
  this.tunnelMutateLimiter = void 0;
135
146
  this.pairingExchangeLimiter = void 0;
@@ -141,6 +152,7 @@ var BucketRegistry = class {
141
152
  resetAllForTests() {
142
153
  this.authFailureLimiter?.resetForTests();
143
154
  this.strictApiLimiter?.resetForTests();
155
+ this.xopcCloudPollLimiter?.resetForTests();
144
156
  this.channelApiLimiter?.resetForTests();
145
157
  this.tunnelMutateLimiter?.resetForTests();
146
158
  this.pairingExchangeLimiter?.resetForTests();
@@ -7,6 +7,7 @@ import { ExtensionLoader } from '../extensions/index.js';
7
7
  import { SessionIndex } from '../session/index.js';
8
8
  import type { Config } from '../config/schema.js';
9
9
  import { type ResolvedGatewayAuth } from './auth.js';
10
+ import { ModelCatalogSyncService } from '../providers/model-catalog-sync-service.js';
10
11
  import { AgentRunRelay } from './agent-run-relay.js';
11
12
  import { type EnqueueGoalRunOptions } from '../goals/index.js';
12
13
  import { ProjectService } from '../projects/index.js';
@@ -41,9 +42,11 @@ export declare class GatewayService {
41
42
  private startTime;
42
43
  private workspacePath;
43
44
  private readonly configCoordinator;
45
+ private readonly modelCatalogSync;
44
46
  private auth;
45
47
  private readonly sse;
46
48
  getConfig(): Config;
49
+ getModelCatalogSync(): ModelCatalogSyncService;
47
50
  get browserRecipes(): BrowserRecipeService;
48
51
  private stopGatewayUpdateCheck;
49
52
  /** When set (e.g. by `GatewayServer`), `triggerGatewayProcessRestart` can stop HTTP then exit. */
@@ -74,6 +74,7 @@ import { isGatewayStrictSecurityEnabled } from "./rate-limit/env-flags.js";
74
74
  import "./rate-limit/index.js";
75
75
  import { assertGatewayRuntimeConfig } from "./runtime-config.js";
76
76
  import { auditGatewayConfig } from "./security/audit.js";
77
+ import { ModelCatalogSyncService } from "../providers/model-catalog-sync-service.js";
77
78
  import { runBootstrapMigrationsSync } from "../migrations/runner.js";
78
79
  import { MobileNotificationService } from "../mobile/notification-service.js";
79
80
  import { LocalAppService } from "../local-apps/service.js";
@@ -124,11 +125,18 @@ var GatewayService = class {
124
125
  startTime = Date.now();
125
126
  workspacePath;
126
127
  configCoordinator;
128
+ modelCatalogSync = new ModelCatalogSyncService({
129
+ onUpdated: (modelCount) => this.emit("model-catalog.updated", { modelCount }),
130
+ getConfig: () => this.config
131
+ });
127
132
  auth;
128
133
  sse = new GatewaySseHub();
129
134
  getConfig() {
130
135
  return this.config;
131
136
  }
137
+ getModelCatalogSync() {
138
+ return this.modelCatalogSync;
139
+ }
132
140
  get browserRecipes() {
133
141
  if (!this.browserRecipeService) this.browserRecipeService = createRuntimeBrowserRecipeService({
134
142
  getConfig: () => this.config,
@@ -582,6 +590,7 @@ var GatewayService = class {
582
590
  phase: "sidecars.model_prewarm"
583
591
  }, `Model registry prewarm failed: ${em}`);
584
592
  }
593
+ this.modelCatalogSync.start();
585
594
  if (!this.extensionLoader || areExtensionsGloballyDisabled(this.config)) return;
586
595
  try {
587
596
  if (trace) await trace.measure("extensions.deferred-load", () => this.loadDeferredExtensions());
@@ -827,6 +836,7 @@ var GatewayService = class {
827
836
  this.stopGatewayUpdateCheck();
828
837
  this.stopGatewayUpdateCheck = null;
829
838
  }
839
+ this.modelCatalogSync.stop();
830
840
  await this.configCoordinator.stopHotReloader();
831
841
  this.heartbeatService?.stop();
832
842
  this.connectorSupervisor?.stop();
@@ -2,7 +2,7 @@
2
2
  * SSRF / private-network protection for provider HTTP calls.
3
3
  *
4
4
  * Provider URLs are mostly user-controllable (cfg.providers.<id>.baseUrl,
5
- * imageBaseUrl, etc.). Without a guard a malicious config could make xopc
5
+ * custom provider base URLs. Without a guard a malicious config could make xopc
6
6
  * fetch internal services (169.254.x.x metadata, 127.0.0.1, RFC1918, …).
7
7
  *
8
8
  * Policy:
@@ -4,7 +4,7 @@ import { isIP } from "node:net";
4
4
  * SSRF / private-network protection for provider HTTP calls.
5
5
  *
6
6
  * Provider URLs are mostly user-controllable (cfg.providers.<id>.baseUrl,
7
- * imageBaseUrl, etc.). Without a guard a malicious config could make xopc
7
+ * custom provider base URLs. Without a guard a malicious config could make xopc
8
8
  * fetch internal services (169.254.x.x metadata, 127.0.0.1, RFC1918, …).
9
9
  *
10
10
  * Policy: