@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.
- package/README.md +4 -2
- package/README.zh-CN.md +4 -2
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{activity-store-hpcNv9MZ.js → activity-store-Xj95LzTv.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-Zf9UQEmQ.js → agent-avatar-dicebear-C-QeUFwU.js} +1 -1
- package/dist/gateway/static/root/assets/agents-DVKlWKJE.js +2 -0
- package/dist/gateway/static/root/assets/{api-Dnatri09.js → api-BTLmAm1_.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-BBTR9wJP.js → app-management-settings-panel-zc6Gf-S5.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-C2zpLCHD.js → appearance-settings-0fMLnOWn.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-BZXEJDIV.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-9eR_ODY1.js → archive-plugin-DOiR_E21.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-DPuWYUeX.js → attachment-load-BxmYl1D1.js} +1 -1
- package/dist/gateway/static/root/assets/{automation-suggestion-card-Dw49OJRl.js → automation-suggestion-card-BhZOirad.js} +1 -1
- package/dist/gateway/static/root/assets/automations-page-B8CnkoXv.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-BdkJpDFm.js → binary-plugins-DTTKsvgk.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-CAi7SXYU.js → block-editor-C7se7iqg.js} +31 -31
- package/dist/gateway/static/root/assets/browser-settings-page-BCPWKI9V.js +8 -0
- package/dist/gateway/static/root/assets/{browser-workflow-inputs-Dx6wkGz1.js → browser-workflow-inputs-kxmStCcv.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-Skertc-A.js → browser-workflows-page-CwYf9OM_.js} +2 -2
- package/dist/gateway/static/root/assets/capabilities-settings-panel-C7lr_mX2.js +2 -0
- package/dist/gateway/static/root/assets/{capability-presets-api-CNFl7dM3.js → capability-presets-api-BZKh2cWX.js} +1 -1
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-Ble9kHRu.js +2 -0
- package/dist/gateway/static/root/assets/{channel-recipient-api-DYQyGDw4.js → channel-recipient-api-r7tdbnJE.js} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-CtQQQHrv.js +1 -0
- package/dist/gateway/static/root/assets/channels-status-swr-_VirfMKW.js +1 -0
- package/dist/gateway/static/root/assets/{connector-logo-Bng6kxYF.js → connector-logo-BpnQYAxA.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-BXWJSJeY.js +2 -0
- package/dist/gateway/static/root/assets/desktop-pet-B86W4a5c.js +1 -0
- package/dist/gateway/static/root/assets/{desktop-pet-settings-BVUyefSd.js → desktop-pet-settings-uv8Grtgk.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-DjSZAPz_.js → directory-picker-path-field-C4TTvf7p.js} +1 -1
- package/dist/gateway/static/root/assets/{dreaming-settings-CAZk2AM4.js → dreaming-settings-CzJAUPvM.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-debug-page-C2F6vTTd.js → extension-debug-page-Ci2mOYUt.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-AnIt4bn4.js → extension-page-DeXdmhXQ.js} +1 -1
- package/dist/gateway/static/root/assets/extension-settings-page-C93vaOsU.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-config-api-DLFyZv33.js → gateway-config-api-C31Hlblp.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-DnQAA-qq.js → gateway-settings-D3zS6RZh.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-DbzLyJ3R.js → gateway-startup-retry-CSRvCqxh.js} +1 -1
- package/dist/gateway/static/root/assets/{goal-create-dialog-DrnKFC6M.js → goal-create-dialog-CWp2b7__.js} +1 -1
- package/dist/gateway/static/root/assets/goal-detail-page-Dtm29FxD.js +4 -0
- package/dist/gateway/static/root/assets/{goals-config-api-REmr3QCr.js → goals-config-api-D4wYNRrf.js} +1 -1
- package/dist/gateway/static/root/assets/goals-page-jMzBJs6e.js +2 -0
- package/dist/gateway/static/root/assets/{goals-settings-Dz0F3uRO.js → goals-settings-Bx2jVvhQ.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-CQFY5gYs.js → heartbeat-settings-BEIF1eXy.js} +1 -1
- package/dist/gateway/static/root/assets/index-BXtJvaQl.css +1 -0
- package/dist/gateway/static/root/assets/{index-C8JkTS6d.js → index-HZdBKfk_.js} +70 -70
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BnOQXU5k.js → keyboard-shortcuts-settings-DOEDpvTM.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-CseW9jD3.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-KsOtWOyM.js → local-apps-page-B0OpGpxv.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-0lpYdNDr.js → locale-store-Ys6RP7Be.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-DVqPbth5.js +7 -0
- package/dist/gateway/static/root/assets/{markdown-split-D5GRg10r.js → markdown-split-CEZwysCH.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-C1ryULGs.js → media-plugins-CpGKE7B0.js} +1 -1
- package/dist/gateway/static/root/assets/messages-BzI9Wx30.js +5 -0
- package/dist/gateway/static/root/assets/{notes-page-CIeZ1_DT.js → notes-page-CdiuDZ5a.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-mrc3xtpn.js +4 -0
- package/dist/gateway/static/root/assets/{page-tabs-Caj1-E_X.js → page-tabs-BkH5AVV2.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-DKwEce-9.js → preview-open-alternatives-CQai8f9D.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-B90ZskkN.js → product-open-page-B2kSdB2b.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-CfhPJLkH.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-BfMoKjdm.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-CrDtcsZ9.js +1 -0
- package/dist/gateway/static/root/assets/{save-bar-controls-BDYt53uQ.js → save-bar-controls-NGYnO7n7.js} +1 -1
- package/dist/gateway/static/root/assets/schedule-field-nLOphnv3.js +1 -0
- package/dist/gateway/static/root/assets/{schema-form-D7oCARF7.js → schema-form-D0e90ndE.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-D3DbF3dV.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-BZp0O2dH.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-CARTHCxH.js → settings-form-section-X2Sl-EAk.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-DEwYqESe.js → settings-loading-skeleton-DOnUabm7.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-B6vVdHeQ.js → settings-page-C4UUNi1n.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-layout-D3srt5Bi.js → settings-page-layout-C1yYqbT6.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-84iao4DZ.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-Ck9SxiXw.js → share-preview-page-Cfy_pH7V.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-DtcwQvRG.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-L7j5Gc8Z.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-1Ps8PjsP.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-DLBUQSk2.js → system-settings-panel-Da81RJ6G.js} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-C1oaqeD2.js → theme-store-DflSp9o4.js} +1 -1
- package/dist/gateway/static/root/assets/time-picker-BIkOW-2L.js +1 -0
- package/dist/gateway/static/root/assets/{typed-models-lib-Divbg_C4.js → typed-models-lib--HptwFcD.js} +1 -1
- package/dist/gateway/static/root/assets/{use-channel-catalog-CP9a_rAf.js → use-channel-catalog-CMHY4ZfW.js} +1 -1
- package/dist/gateway/static/root/assets/user-context-page-BYAAs2iW.js +1 -0
- package/dist/gateway/static/root/assets/voice-api-key-field-nvIZerol.js +1 -0
- package/dist/gateway/static/root/assets/work-discovery-page-J35JkJ7_.js +1 -0
- package/dist/gateway/static/root/assets/work-item-detail-page-C4wYDYqV.js +1 -0
- package/dist/gateway/static/root/assets/work-page-DMvitV6c.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-DbDPYQwB.js → workflow-run-setup-panel-D96MHABy.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-JMN0nMbM.js +11 -0
- package/dist/gateway/static/root/index.html +7 -7
- package/dist/package.js +1 -1
- package/dist/src/agent/client-error-format.d.ts +1 -1
- package/dist/src/agent/client-error-format.js +6 -2
- package/dist/src/agent/embedded/run-for-session.js +38 -31
- package/dist/src/agent/embedded/session-runner.d.ts +1 -0
- package/dist/src/agent/embedded/session-runner.js +12 -4
- package/dist/src/agent/failover-error.d.ts +1 -1
- package/dist/src/agent/image/generation/openai-compatible-image-provider.d.ts +2 -6
- package/dist/src/agent/image/generation/openai-compatible-image-provider.js +1 -3
- package/dist/src/agent/image/generation/provider-registry.d.ts +5 -46
- package/dist/src/agent/image/generation/provider-registry.js +24 -73
- package/dist/{extensions/dashscope/src/image-generation-provider.d.ts → src/agent/image/generation/providers/dashscope.d.ts} +3 -6
- package/dist/{extensions/dashscope/src/image-generation-provider.js → src/agent/image/generation/providers/dashscope.js} +36 -59
- package/dist/{extensions/fal/src/image-generation-provider.d.ts → src/agent/image/generation/providers/fal.d.ts} +1 -1
- package/dist/{extensions/fal/src/image-generation-provider.js → src/agent/image/generation/providers/fal.js} +19 -29
- package/dist/{extensions/google/src/image-generation-provider.d.ts → src/agent/image/generation/providers/google.d.ts} +2 -2
- package/dist/{extensions/google/src/image-generation-provider.js → src/agent/image/generation/providers/google.js} +23 -30
- package/dist/{extensions/minimax/src/image-generation-provider.d.ts → src/agent/image/generation/providers/minimax.d.ts} +2 -5
- package/dist/{extensions/minimax/src/image-generation-provider.js → src/agent/image/generation/providers/minimax.js} +35 -51
- package/dist/{extensions/openai/src/image-generation-provider.d.ts → src/agent/image/generation/providers/openai.d.ts} +2 -2
- package/dist/{extensions/openai/src/image-generation-provider.js → src/agent/image/generation/providers/openai.js} +13 -38
- package/dist/src/agent/image/generation/runtime-types.d.ts +1 -0
- package/dist/src/agent/image/generation/runtime.d.ts +1 -3
- package/dist/src/agent/image/generation/runtime.js +6 -6
- package/dist/src/agent/image/generation/types.d.ts +23 -3
- package/dist/src/agent/image/index.d.ts +1 -1
- package/dist/src/agent/image/index.js +2 -2
- package/dist/src/agent/media-generation/runtime-shared.d.ts +2 -0
- package/dist/src/agent/media-generation/runtime-shared.js +1 -0
- package/dist/src/agent/tools/factory.js +4 -1
- package/dist/src/agent/tools/image-generate-tool.d.ts +2 -0
- package/dist/src/agent/tools/image-generate-tool.js +14 -7
- package/dist/src/auth/sync-provider-auth.d.ts +3 -0
- package/dist/src/auth/sync-provider-auth.js +12 -1
- package/dist/src/cli/commands/models.js +2 -5
- package/dist/src/cli/commands/onboard/model.js +3 -2
- package/dist/src/cli/commands/setup-shared/types.d.ts +1 -1
- package/dist/src/config/index.js +2 -2
- package/dist/src/config/models-json.d.ts +6 -0
- package/dist/src/config/models-json.js +2 -6
- package/dist/src/config/schema.d.ts +26 -15
- package/dist/src/config/schema.js +23 -12
- package/dist/src/gateway/hono/app.js +12 -6
- package/dist/src/gateway/hono/lib/safe-providers-config.d.ts +0 -3
- package/dist/src/gateway/hono/lib/safe-providers-config.js +1 -3
- package/dist/src/gateway/hono/middleware/strict-rate-limit.d.ts +4 -0
- package/dist/src/gateway/hono/middleware/strict-rate-limit.js +8 -1
- package/dist/src/gateway/hono/routes/config-patch/misc.js +2 -11
- package/dist/src/gateway/hono/routes/deps.d.ts +1 -0
- package/dist/src/gateway/hono/routes/lazy-bundles.js +9 -2
- package/dist/src/gateway/hono/routes/models.js +151 -129
- package/dist/src/gateway/image-generation-setup.d.ts +40 -0
- package/dist/src/gateway/image-generation-setup.js +130 -0
- package/dist/src/gateway/rate-limit/buckets.d.ts +3 -0
- package/dist/src/gateway/rate-limit/buckets.js +12 -0
- package/dist/src/gateway/service.d.ts +3 -0
- package/dist/src/gateway/service.js +10 -0
- package/dist/src/media-shared/http/private-network.d.ts +1 -1
- package/dist/src/media-shared/http/private-network.js +1 -1
- package/dist/src/providers/auth-runtime/resolve-api-key.d.ts +2 -4
- package/dist/src/providers/auth-runtime/resolve-api-key.js +2 -4
- package/dist/src/providers/auth-runtime/resolve-auth.d.ts +3 -4
- package/dist/src/providers/auth-runtime/resolve-auth.js +18 -18
- package/dist/src/providers/domestic-presets.d.ts +22 -0
- package/dist/src/providers/domestic-presets.js +25 -0
- package/dist/src/providers/model-catalog-store.d.ts +71 -0
- package/dist/src/providers/model-catalog-store.js +102 -0
- package/dist/src/providers/model-catalog-sync-service.d.ts +41 -0
- package/dist/src/providers/model-catalog-sync-service.js +142 -0
- package/dist/src/providers/model-reference-auditor.d.ts +14 -0
- package/dist/src/providers/model-reference-auditor.js +71 -0
- package/dist/src/providers/model-registry.d.ts +4 -1
- package/dist/src/providers/model-registry.js +35 -2
- package/dist/src/providers/presentation.js +2 -0
- package/dist/src/providers/xopc-cloud-connection.d.ts +51 -0
- package/dist/src/providers/xopc-cloud-connection.js +196 -0
- package/dist/src/session/index.d.ts +1 -1
- package/dist/src/session/index.js +2 -2
- package/dist/src/session/session-title.d.ts +2 -0
- package/dist/src/session/session-title.js +24 -3
- package/package.json +5 -7
- package/dist/extensions/dashscope/src/index.d.ts +0 -4
- package/dist/extensions/dashscope/src/index.js +0 -2
- package/dist/extensions/dashscope/xopc.extension.json +0 -15
- package/dist/extensions/fal/src/index.d.ts +0 -4
- package/dist/extensions/fal/src/index.js +0 -2
- package/dist/extensions/fal/xopc.extension.json +0 -14
- package/dist/extensions/google/src/index.d.ts +0 -4
- package/dist/extensions/google/src/index.js +0 -2
- package/dist/extensions/google/xopc.extension.json +0 -14
- package/dist/extensions/minimax/src/index.d.ts +0 -4
- package/dist/extensions/minimax/src/index.js +0 -2
- package/dist/extensions/minimax/xopc.extension.json +0 -15
- package/dist/extensions/openai/src/index.d.ts +0 -4
- package/dist/extensions/openai/src/index.js +0 -2
- package/dist/extensions/openai/xopc.extension.json +0 -14
- package/dist/gateway/static/root/assets/agents-DfVkZlHc.js +0 -2
- package/dist/gateway/static/root/assets/apps-page-BMtAa4Ra.js +0 -1
- package/dist/gateway/static/root/assets/automations-page-BiSAMYTr.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-DHmaEJS2.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-B5wSgf4f.js +0 -2
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-DyvFZwBj.js +0 -2
- package/dist/gateway/static/root/assets/channels-settings-BBKEqDZn.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-Drk110ve.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-HpgaUDQ1.js +0 -2
- package/dist/gateway/static/root/assets/desktop-pet-Bpf6oegd.js +0 -1
- package/dist/gateway/static/root/assets/extension-settings-page-CLSc6682.js +0 -1
- package/dist/gateway/static/root/assets/goal-detail-page-Cw1hpJkZ.js +0 -4
- package/dist/gateway/static/root/assets/goals-page-BDGkTVma.js +0 -2
- package/dist/gateway/static/root/assets/index-hmrG55qg.css +0 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-Bdef1b7F.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-CwLPgrWh.js +0 -7
- package/dist/gateway/static/root/assets/messages-BwQ3WssU.js +0 -5
- package/dist/gateway/static/root/assets/notes-workbench-Cf06q19x.js +0 -4
- package/dist/gateway/static/root/assets/project-detail-page-SHTurM4t.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-BcC2qUAw.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-6vGefBHv.js +0 -1
- package/dist/gateway/static/root/assets/schedule-field-Bcdni4Pj.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-C5014a53.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-CDY3ZI1K.js +0 -1
- package/dist/gateway/static/root/assets/settings-collapsible-section-6eNF8Jey.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-z-rF0Hdg.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-CHZFXE_d.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-B7p2QNXt.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-ncw3tX9P.js +0 -2
- package/dist/gateway/static/root/assets/user-context-page-iYfeSLKI.js +0 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-CrwkicvT.js +0 -1
- package/dist/gateway/static/root/assets/work-discovery-page-BQWxyPg8.js +0 -1
- package/dist/gateway/static/root/assets/work-item-detail-page-50ZzGay5.js +0 -1
- package/dist/gateway/static/root/assets/work-page-DPqEahx7.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-C3eIC5HZ.js +0 -11
- package/dist/src/agent/image/generation/bundled-registry.d.ts +0 -18
- package/dist/src/agent/image/generation/bundled-registry.js +0 -35
- package/dist/src/agent/image/generation/bundled.d.ts +0 -10
- package/dist/src/agent/image/generation/bundled.js +0 -15
- package/dist/src/agent/image/generation/image-provider-ui.d.ts +0 -20
- package/dist/src/agent/image/generation/image-provider-ui.js +0 -1
- package/dist/src/gateway/image-capabilities.d.ts +0 -28
- package/dist/src/gateway/image-capabilities.js +0 -78
- package/dist/src/generated/bundled-image-generation-providers.d.ts +0 -14
- 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
|
|
10
|
-
import {
|
|
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 {
|
|
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/
|
|
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.
|
|
234
|
-
let body;
|
|
296
|
+
authenticated.get("/api/agents/:agentId/image-generation", (c) => {
|
|
235
297
|
try {
|
|
236
|
-
|
|
237
|
-
|
|
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:
|
|
241
|
-
},
|
|
305
|
+
error: { message: error instanceof Error ? error.message : String(error) }
|
|
306
|
+
}, 404);
|
|
242
307
|
}
|
|
243
|
-
|
|
244
|
-
|
|
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: "
|
|
313
|
+
error: { message: "providerId is required" }
|
|
247
314
|
}, 400);
|
|
248
|
-
const
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
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
|
-
|
|
267
|
-
|
|
268
|
-
|
|
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:
|
|
271
|
-
|
|
272
|
-
|
|
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
|
-
|
|
284
|
-
|
|
285
|
-
|
|
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/:
|
|
310
|
-
const
|
|
311
|
-
|
|
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:
|
|
316
|
-
},
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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:
|