From 077152139b8a9a95cb4e30252e633d76ff8b7007 Mon Sep 17 00:00:00 2001 From: Morpheus Developer Date: Wed, 25 Feb 2026 17:41:21 -0800 Subject: [PATCH 1/3] Add Morpheus as a provider with dynamic model fetching Add Morpheus decentralized AI inference as a provider option. Models are fetched in real time from the Morpheus marketplace API via a schema-driven x-models-url mechanism, with graceful fallback to manual text input if the API is unreachable. --- .env.example | 3 + .../node/create_nodes/providers_schema.json | 22 ++++++- .../src/assets/schemas/providers_schema.json | 22 ++++++- .../components/Simulator/ProviderModal.vue | 58 ++++++++++++++++++- 4 files changed, 101 insertions(+), 4 deletions(-) diff --git a/.env.example b/.env.example index d962e2360..cec496ca8 100644 --- a/.env.example +++ b/.env.example @@ -83,6 +83,9 @@ OPENROUTERAPIKEY='' # If you want to use IO.net, add your key here IONETAPIKEY='' +# If you want to use Morpheus decentralized AI, add your key here +MORPHEUSAPIKEY='' + ######################################## # API Rate Limiting Configuration RATE_LIMIT_ENABLED='false' # Enable/disable API key rate limiting diff --git a/backend/node/create_nodes/providers_schema.json b/backend/node/create_nodes/providers_schema.json index 46985f095..b81be4f97 100644 --- a/backend/node/create_nodes/providers_schema.json +++ b/backend/node/create_nodes/providers_schema.json @@ -12,7 +12,8 @@ "anthropic", "xai", "google", - "openrouter" + "openrouter", + "morpheus" ] }, "model": { @@ -212,6 +213,25 @@ } } }, + { + "if": { + "properties": { + "provider": { "const": "morpheus" } + } + }, + "then": { + "x-models-url": "https://api.mor.org/api/v1/models", + "x-plugin-config-defaults": { + "api_key_env_var": "MORPHEUSAPIKEY", + "api_url": "https://api.mor.org/api/v1" + }, + "properties": { + "plugin": { + "const": "openai-compatible" + } + } + } + }, { "if": { "properties": { diff --git a/frontend/src/assets/schemas/providers_schema.json b/frontend/src/assets/schemas/providers_schema.json index 57de3ce2f..e5d83f630 100644 --- a/frontend/src/assets/schemas/providers_schema.json +++ b/frontend/src/assets/schemas/providers_schema.json @@ -11,7 +11,8 @@ "openai", "anthropic", "xai", - "google" + "google", + "morpheus" ] }, "model": { @@ -150,6 +151,25 @@ } } }, + { + "if": { + "properties": { + "provider": { "const": "morpheus" } + } + }, + "then": { + "x-models-url": "https://api.mor.org/api/v1/models", + "x-plugin-config-defaults": { + "api_key_env_var": "MORPHEUSAPIKEY", + "api_url": "https://api.mor.org/api/v1" + }, + "properties": { + "plugin": { + "const": "openai-compatible" + } + } + } + }, { "if": { "properties": { diff --git a/frontend/src/components/Simulator/ProviderModal.vue b/frontend/src/components/Simulator/ProviderModal.vue index 0266b6557..51849cd43 100644 --- a/frontend/src/components/Simulator/ProviderModal.vue +++ b/frontend/src/components/Simulator/ProviderModal.vue @@ -98,6 +98,8 @@ const pluginOptions = ref([]); const modelOptions = ref([]); const isPluginLocked = ref(false); const customProvider = ref(false); +const isLoadingModels = ref(false); +const modelFetchError = ref(''); const providerOptions = ref([]); const availablePluginOptions = computed(() => { @@ -201,6 +203,30 @@ function extractDefaults( return defaults; } +const fetchDynamicModels = async (modelsUrl: string) => { + isLoadingModels.value = true; + modelFetchError.value = ''; + try { + const response = await fetch(modelsUrl); + if (!response.ok) throw new Error(`HTTP ${response.status}`); + const data = await response.json(); + if (data?.data && Array.isArray(data.data)) { + modelOptions.value = data.data + .filter((m: any) => !m.modelType || m.modelType === 'LLM') + .map((m: any) => m.id); + if (modelOptions.value.length > 0 && isCreateMode.value) { + newProviderData.model = modelOptions.value[0]; + } + } + } catch (err) { + console.error('Failed to fetch models:', err); + modelFetchError.value = + 'Could not fetch available models. You can type a model name manually.'; + } finally { + isLoadingModels.value = false; + } +}; + const pluginConfigProperties = ref>({}); const configProperties = ref>({}); @@ -259,6 +285,27 @@ const checkRules = () => { } } }); + + // Provider-specific post-processing (x-models-url, x-plugin-config-defaults) + schema.allOf.forEach((rule: any) => { + if (rule.if?.properties?.provider?.const === newProviderData.provider) { + // Override plugin_config with provider-specific defaults + if (rule.then?.['x-plugin-config-defaults'] && isCreateMode.value) { + Object.assign( + newProviderData.plugin_config, + rule.then['x-plugin-config-defaults'], + ); + } + // Fetch models dynamically for providers with x-models-url + if ( + rule.then?.['x-models-url'] && + modelOptions.value.length === 0 && + isCreateMode.value + ) { + fetchDynamicModels(rule.then['x-models-url']); + } + } + }); }; const toggleCustomProvider = () => { @@ -390,8 +437,15 @@ const configurationError = computed(() => { + +
+ Loading available models... +
+ + {{ modelFetchError }} + { placeholder="i.e. my-model" /> Date: Thu, 26 Feb 2026 11:51:06 -0800 Subject: [PATCH 2/3] Sync openrouter and ionet providers to frontend schema The backend schema included openrouter and ionet provider blocks (added in #1427/#1429) but these were never mirrored to the frontend. Sync the examples array and allOf conditional blocks so both schemas list the same set of providers. --- .../node/create_nodes/providers_schema.json | 1 + .../src/assets/schemas/providers_schema.json | 57 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/backend/node/create_nodes/providers_schema.json b/backend/node/create_nodes/providers_schema.json index b81be4f97..5431dfd6a 100644 --- a/backend/node/create_nodes/providers_schema.json +++ b/backend/node/create_nodes/providers_schema.json @@ -13,6 +13,7 @@ "xai", "google", "openrouter", + "ionet", "morpheus" ] }, diff --git a/frontend/src/assets/schemas/providers_schema.json b/frontend/src/assets/schemas/providers_schema.json index e5d83f630..e61a4963b 100644 --- a/frontend/src/assets/schemas/providers_schema.json +++ b/frontend/src/assets/schemas/providers_schema.json @@ -12,6 +12,8 @@ "anthropic", "xai", "google", + "openrouter", + "ionet", "morpheus" ] }, @@ -103,6 +105,61 @@ } } }, + { + "if": { + "properties": { + "provider": { "const": "openrouter" } + } + }, + "then": { + "properties": { + "plugin": { + "const": "openai-compatible" + }, + "model": { + "enum": [ + "@preset/rally-testnet-gpt-5-1", + "@preset/rally-testnet-sonnet-4-5", + "@preset/rally-testnet-gemini-3-flash", + "openai/gpt-5.2", + "openai/gpt-5.1", + "openai/gpt-5-mini", + "z-ai/glm-4.7", + "moonshotai/kimi-k2-0905", + "moonshotai/kimi-k2.5", + "deepseek/deepseek-v3.2", + "qwen/qwen3-235b-a22b-2507", + "anthropic/claude-sonnet-4.5", + "google/gemini-3-flash-preview", + "x-ai/grok-4", + "mistralai/mistral-large-2512", + "meta-llama/llama-4-maverick", + "nvidia/llama-3.1-nemotron-ultra-253b-v1" + ] + } + } + } + }, + { + "if": { + "properties": { + "provider": { "const": "ionet" } + } + }, + "then": { + "properties": { + "plugin": { + "const": "openai-compatible" + }, + "model": { + "enum": [ + "deepseek-ai/DeepSeek-V3.2", + "meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8" + ] + } + } + } + }, { "if": { "properties": { From 1822e91c889ce743d45924d4a568a04031c92c03 Mon Sep 17 00:00:00 2001 From: BetterBrand Date: Sat, 28 Feb 2026 11:58:36 -0800 Subject: [PATCH 3/3] Rename MORPHEUSAPIKEY to MORPHEUS_API_KEY Match the underscore convention used by newer providers (ANTHROPIC_API_KEY, XAI_API_KEY, GEMINI_API_KEY). --- .env.example | 2 +- backend/node/create_nodes/providers_schema.json | 2 +- frontend/src/assets/schemas/providers_schema.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.env.example b/.env.example index cec496ca8..0bd20720f 100644 --- a/.env.example +++ b/.env.example @@ -84,7 +84,7 @@ OPENROUTERAPIKEY='' IONETAPIKEY='' # If you want to use Morpheus decentralized AI, add your key here -MORPHEUSAPIKEY='' +MORPHEUS_API_KEY='' ######################################## # API Rate Limiting Configuration diff --git a/backend/node/create_nodes/providers_schema.json b/backend/node/create_nodes/providers_schema.json index 5431dfd6a..40a6ab716 100644 --- a/backend/node/create_nodes/providers_schema.json +++ b/backend/node/create_nodes/providers_schema.json @@ -223,7 +223,7 @@ "then": { "x-models-url": "https://api.mor.org/api/v1/models", "x-plugin-config-defaults": { - "api_key_env_var": "MORPHEUSAPIKEY", + "api_key_env_var": "MORPHEUS_API_KEY", "api_url": "https://api.mor.org/api/v1" }, "properties": { diff --git a/frontend/src/assets/schemas/providers_schema.json b/frontend/src/assets/schemas/providers_schema.json index e61a4963b..d82068c85 100644 --- a/frontend/src/assets/schemas/providers_schema.json +++ b/frontend/src/assets/schemas/providers_schema.json @@ -217,7 +217,7 @@ "then": { "x-models-url": "https://api.mor.org/api/v1/models", "x-plugin-config-defaults": { - "api_key_env_var": "MORPHEUSAPIKEY", + "api_key_env_var": "MORPHEUS_API_KEY", "api_url": "https://api.mor.org/api/v1" }, "properties": {