Browse Source

Merge pull request #12606 from alpha-pet/feat-openapi-yaml-support

Feat: openapi yaml support
Tim Jaeryang Baek 2 months ago
parent
commit
6c9a4d6ce6
4 changed files with 41 additions and 11 deletions
  1. 9 2
      backend/open_webui/utils/tools.py
  2. 20 6
      package-lock.json
  3. 2 1
      package.json
  4. 10 2
      src/lib/apis/index.ts

+ 9 - 2
backend/open_webui/utils/tools.py

@@ -4,6 +4,7 @@ import re
 import inspect
 import aiohttp
 import asyncio
+import yaml
 
 from typing import Any, Awaitable, Callable, get_type_hints, Dict, List, Union, Optional
 from functools import update_wrapper, partial
@@ -398,9 +399,15 @@ async def get_tool_server_data(token: str, url: str) -> Dict[str, Any]:
                 if response.status != 200:
                     error_body = await response.json()
                     raise Exception(error_body)
-                res = await response.json()
+
+                # Check if URL ends with .yaml or .yml to determine format
+                if url.lower().endswith((".yaml", ".yml")):
+                    text_content = await response.text()
+                    res = yaml.safe_load(text_content)
+                else:
+                    res = await response.json()
     except Exception as err:
-        print("Error:", err)
+        log.exception(f"Could not fetch tool server spec from {url}")
         if isinstance(err, dict) and "detail" in err:
             error = err["detail"]
         else:

+ 20 - 6
package-lock.json

@@ -70,7 +70,8 @@
 				"turndown": "^7.2.0",
 				"undici": "^7.3.0",
 				"uuid": "^9.0.1",
-				"vite-plugin-static-copy": "^2.2.0"
+				"vite-plugin-static-copy": "^2.2.0",
+				"yaml": "^2.7.1"
 			},
 			"devDependencies": {
 				"@sveltejs/adapter-auto": "3.2.2",
@@ -9514,6 +9515,16 @@
 				"node": ">=10"
 			}
 		},
+		"node_modules/postcss-load-config/node_modules/yaml": {
+			"version": "1.10.2",
+			"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+			"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
+			"dev": true,
+			"license": "ISC",
+			"engines": {
+				"node": ">= 6"
+			}
+		},
 		"node_modules/postcss-safe-parser": {
 			"version": "6.0.0",
 			"resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz",
@@ -13031,12 +13042,15 @@
 			}
 		},
 		"node_modules/yaml": {
-			"version": "1.10.2",
-			"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
-			"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
-			"dev": true,
+			"version": "2.7.1",
+			"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz",
+			"integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==",
+			"license": "ISC",
+			"bin": {
+				"yaml": "bin.mjs"
+			},
 			"engines": {
-				"node": ">= 6"
+				"node": ">= 14"
 			}
 		},
 		"node_modules/yauzl": {

+ 2 - 1
package.json

@@ -113,7 +113,8 @@
 		"turndown": "^7.2.0",
 		"undici": "^7.3.0",
 		"uuid": "^9.0.1",
-		"vite-plugin-static-copy": "^2.2.0"
+		"vite-plugin-static-copy": "^2.2.0",
+		"yaml": "^2.7.1"
 	},
 	"engines": {
 		"node": ">=18.13.0 <=22.x.x",

+ 10 - 2
src/lib/apis/index.ts

@@ -2,6 +2,7 @@ import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants';
 import { convertOpenApiToToolPayload } from '$lib/utils';
 import { getOpenAIModelsDirect } from './openai';
 
+import { parse } from 'yaml';
 import { toast } from 'svelte-sonner';
 
 export const getModels = async (
@@ -271,8 +272,15 @@ export const getToolServerData = async (token: string, url: string) => {
 		}
 	})
 		.then(async (res) => {
-			if (!res.ok) throw await res.json();
-			return res.json();
+			// Check if URL ends with .yaml or .yml to determine format
+			if (url.toLowerCase().endsWith('.yaml') || url.toLowerCase().endsWith('.yml')) {
+				if (!res.ok) throw await res.text();
+				const text = await res.text();
+				return parse(text);
+			} else {
+				if (!res.ok) throw await res.json();
+				return res.json();
+			}
 		})
 		.catch((err) => {
 			console.log(err);