diff --git a/src/lib/components/AddToolServerModal.svelte b/src/lib/components/AddToolServerModal.svelte index afde028abe..4865278da0 100644 --- a/src/lib/components/AddToolServerModal.svelte +++ b/src/lib/components/AddToolServerModal.svelte @@ -5,7 +5,7 @@ const { saveAs } = fileSaver; import { toast } from 'svelte-sonner'; - import { getContext, onMount } from 'svelte'; + import { getContext, tick } from 'svelte'; const i18n = getContext('i18n'); import Modal from '$lib/components/common/Modal.svelte'; @@ -17,6 +17,7 @@ import Switch from '$lib/components/common/Switch.svelte'; import Tags from './common/Tags.svelte'; import { getToolServerData } from '$lib/apis'; + import { slugify } from '$lib/utils'; import { verifyToolServerConnection, registerOAuthClient, @@ -88,9 +89,15 @@ ? $i18n.t('OAuth discovery successful') : $i18n.t('Connection successful'); + const ensureConnectionId = () => { + if (type === 'mcp' && !edit && !id.trim()) { + id = slugify(name.trim()) || uuidv4(); + } + }; + const authorizeOAuthHandler = () => { if (!id) { - toast.error($i18n.t('Please enter a valid ID')); + toast.error($i18n.t('Please enter a Connection ID before authorizing OAuth.')); return; } @@ -112,13 +119,14 @@ return; } - if (id === '') { - toast.error($i18n.t('Please enter a valid ID')); + if (auth_type === 'oauth_2.1_static' && (!oauthClientId || !oauthClientSecret)) { + toast.error($i18n.t('Please enter Client ID and Client Secret')); return; } - if (auth_type === 'oauth_2.1_static' && (!oauthClientId || !oauthClientSecret)) { - toast.error($i18n.t('Please enter Client ID and Client Secret')); + ensureConnectionId(); + if (!id.trim()) { + toast.error($i18n.t('Enter a Connection ID to register.')); return; } @@ -147,9 +155,7 @@ if (res) { toast.warning( - $i18n.t( - 'Please save the connection to persist the OAuth client information and do not change the ID' - ) + $i18n.t('Save the connection to keep the OAuth details. Keep the Connection ID unchanged.') ); toast.success($i18n.t('Registration successful')); @@ -242,7 +248,7 @@ if (!file) return; const reader = new FileReader(); - reader.onload = (event) => { + reader.onload = async (event) => { const json = event.target.result; console.log('importHandler', json); @@ -282,6 +288,11 @@ accessGrants = data.config.access_grants ?? []; } + if (data.info?.id) { + await tick(); + id = data.info.id; + } + toast.success($i18n.t('Import successful')); } catch (error) { toast.error($i18n.t('Please select a valid JSON file')); @@ -329,6 +340,7 @@ const submitHandler = async () => { loading = true; + ensureConnectionId(); // remove trailing slash from url for non-MCP connections // MCP servers may require a trailing slash; stripping it can cause @@ -337,7 +349,11 @@ url = url.replace(/\/$/, ''); } if (id.includes(':') || id.includes('|')) { - toast.error($i18n.t('ID cannot contain ":" or "|" characters')); + toast.error( + type === 'mcp' + ? $i18n.t('Connection ID cannot contain ":" or "|" characters') + : $i18n.t('ID cannot contain ":" or "|" characters') + ); loading = false; return; } @@ -446,7 +462,7 @@ accessGrants = []; }; - const init = () => { + const init = async () => { forwardCookies = connection?.forward_cookies ?? false; if (connection) { type = connection?.type ?? 'openapi'; @@ -474,6 +490,11 @@ enable = connection.config?.enable ?? true; functionNameFilterList = connection.config?.function_name_filter_list ?? ''; accessGrants = connection.config?.access_grants ?? []; + + if (connection.info?.id) { + await tick(); + id = connection.info.id; + } } }; @@ -481,9 +502,9 @@ init(); } - onMount(() => { - init(); - }); + $: if (show && type === 'mcp' && !edit && !oauthClientInfo && name) { + id = slugify(name.trim()); + } @@ -594,13 +615,28 @@ {#if !direct}
- + {#if type === 'mcp'} + {$i18n.t('Connection ID')} + {:else} + {$i18n.t('ID')} + ({$i18n.t('optional')}) + {/if}
-
+ -
+
{/if} diff --git a/src/lib/i18n/locales/en-US/translation.json b/src/lib/i18n/locales/en-US/translation.json index 4724500c33..cd1d3ebd55 100644 --- a/src/lib/i18n/locales/en-US/translation.json +++ b/src/lib/i18n/locales/en-US/translation.json @@ -449,6 +449,8 @@ "Connected": "", "Connected ({{type}})": "", "Connection failed": "", + "Connection ID": "", + "Connection ID cannot contain \":\" or \"|\" characters": "", "Connection lost. Reconnecting...": "", "Connection successful": "", "Connection Type": "", @@ -747,6 +749,7 @@ "Enhance": "", "Enhance this note and update it.": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "", + "Enter a Connection ID to register.": "", "Enter {{role}} message here": "", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", @@ -1097,6 +1100,7 @@ "Generate an image": "", "Generate message pair": "", "Generate Message Pair": "", + "Generated from the name, or enter your own. Identifies this connection in Open WebUI, separately from the OAuth client ID.": "", "Generated Image": "", "Generated images will appear here": "", "Generating search query": "", @@ -1160,6 +1164,7 @@ "ID": "", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identifies this connection in Open WebUI, separately from the OAuth client ID.": "", "Identity audit": "", "Idle only": "", "Idle Timeout": "", @@ -1669,6 +1674,7 @@ "Please carefully review the following warnings:": "", "Please connect all required integrations before sending a message": "", "Please do not close the settings page while loading the model.": "", + "Please enter a Connection ID before authorizing OAuth.": "", "Please enter a message or attach a file.": "", "Please enter a prompt": "", "Please enter a valid ID": "", @@ -1849,6 +1855,7 @@ "Save & Update": "", "Save As Copy": "", "Save Chat": "", + "Save the connection to keep the OAuth details. Keep the Connection ID unchanged.": "", "Saved": "", "Saving...": "", "Schedule": "",