feat: upgrade to rmcp 0.12.0 and sacp 10.0.0 by removing SSE transport (#6304)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
+14
-30
@@ -3147,45 +3147,18 @@
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"description": "Server-sent events client with a URI endpoint",
|
||||
"description": "SSE transport is no longer supported - kept only for config file compatibility",
|
||||
"required": [
|
||||
"name",
|
||||
"description",
|
||||
"uri",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"available_tools": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"bundled": {
|
||||
"type": "boolean",
|
||||
"nullable": true
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"env_keys": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"$ref": "#/components/schemas/Envs"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name used to identify this extension"
|
||||
},
|
||||
"timeout": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"nullable": true,
|
||||
"minimum": 0
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
@@ -3194,7 +3167,8 @@
|
||||
]
|
||||
},
|
||||
"uri": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3551,6 +3525,12 @@
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ExtensionEntry"
|
||||
}
|
||||
},
|
||||
"warnings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -4523,6 +4503,10 @@
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"_meta": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
Generated
+10
-30
@@ -325,7 +325,6 @@
|
||||
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
"@babel/generator": "^7.28.5",
|
||||
@@ -695,7 +694,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
@@ -739,7 +737,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -1179,7 +1176,6 @@
|
||||
"integrity": "sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.1",
|
||||
"fs-extra": "^9.0.1",
|
||||
@@ -2728,7 +2724,6 @@
|
||||
"integrity": "sha512-yl43JD/86CIj3Mz5mvvLJqAOfIup7ncxfJ0Btnl0/v5TouVUyeEdcpknfgc+yMevS/48oH9WAkkw93m7otLb/A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@inquirer/checkbox": "^3.0.1",
|
||||
"@inquirer/confirm": "^4.0.1",
|
||||
@@ -6133,7 +6128,8 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
|
||||
"integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@types/babel__core": {
|
||||
"version": "7.20.5",
|
||||
@@ -6421,7 +6417,6 @@
|
||||
"integrity": "sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~7.16.0"
|
||||
}
|
||||
@@ -6463,7 +6458,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz",
|
||||
"integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"csstype": "^3.2.2"
|
||||
}
|
||||
@@ -6474,7 +6468,6 @@
|
||||
"integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"@types/react": "^19.2.0"
|
||||
}
|
||||
@@ -6609,7 +6602,6 @@
|
||||
"integrity": "sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.48.1",
|
||||
"@typescript-eslint/types": "8.48.1",
|
||||
@@ -7005,7 +6997,6 @@
|
||||
"integrity": "sha512-sxSyJMaKp45zI0u+lHrPuZM1ZJQ8FaVD35k+UxVrha1yyvQ+TZuUYllUixwvQXlB7ixoDc7skf3lQPopZIvaQw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@vitest/utils": "4.0.15",
|
||||
"fflate": "^0.8.2",
|
||||
@@ -7254,7 +7245,6 @@
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -7899,7 +7889,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"baseline-browser-mapping": "^2.8.19",
|
||||
"caniuse-lite": "^1.0.30001751",
|
||||
@@ -9187,7 +9176,8 @@
|
||||
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
|
||||
"integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/dom-helpers": {
|
||||
"version": "5.2.1",
|
||||
@@ -9245,7 +9235,6 @@
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@electron/get": "^2.0.0",
|
||||
"@types/node": "^22.7.7",
|
||||
@@ -10260,7 +10249,6 @@
|
||||
"integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.8.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
@@ -10720,7 +10708,6 @@
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
|
||||
"integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"accepts": "^2.0.0",
|
||||
"body-parser": "^2.2.1",
|
||||
@@ -13017,7 +13004,6 @@
|
||||
"integrity": "sha512-454TI39PeRDW1LgpyLPyURtB4Zx1tklSr6+OFOipsxGUH1WMTvk6C65JQdrj455+DP2uJ1+veBEHTGFKWVLFoA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@acemir/cssom": "^0.9.23",
|
||||
"@asamuzakjp/dom-selector": "^6.7.4",
|
||||
@@ -14261,6 +14247,7 @@
|
||||
"integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"lz-string": "bin/bin.js"
|
||||
}
|
||||
@@ -14281,7 +14268,6 @@
|
||||
"integrity": "sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.28.5",
|
||||
"@babel/types": "^7.28.5",
|
||||
@@ -16661,7 +16647,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.11",
|
||||
"picocolors": "^1.1.1",
|
||||
@@ -16763,6 +16748,7 @@
|
||||
"integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1",
|
||||
"ansi-styles": "^5.0.0",
|
||||
@@ -16778,6 +16764,7 @@
|
||||
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
@@ -17133,7 +17120,6 @@
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
|
||||
"integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -17143,7 +17129,6 @@
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz",
|
||||
"integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"scheduler": "^0.27.0"
|
||||
},
|
||||
@@ -17165,7 +17150,8 @@
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/react-markdown": {
|
||||
"version": "10.1.0",
|
||||
@@ -18146,7 +18132,6 @@
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
@@ -19073,8 +19058,7 @@
|
||||
"version": "4.1.17",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.17.tgz",
|
||||
"integrity": "sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tailwindcss-animate": {
|
||||
"version": "1.0.7",
|
||||
@@ -19604,7 +19588,6 @@
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -20019,7 +20002,6 @@
|
||||
"integrity": "sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.5.0",
|
||||
@@ -20110,7 +20092,6 @@
|
||||
"integrity": "sha512-n1RxDp8UJm6N0IbJLQo+yzLZ2sQCDyl1o0LeugbPWf8+8Fttp29GghsQBjYJVmWq3gBFfe9Hs1spR44vovn2wA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@vitest/expect": "4.0.15",
|
||||
"@vitest/mocker": "4.0.15",
|
||||
@@ -20796,7 +20777,6 @@
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
||||
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
|
||||
@@ -230,18 +230,10 @@ export type ErrorResponse = {
|
||||
* Represents the different types of MCP extensions that can be added to the manager
|
||||
*/
|
||||
export type ExtensionConfig = {
|
||||
available_tools?: Array<string>;
|
||||
bundled?: boolean | null;
|
||||
description: string;
|
||||
env_keys?: Array<string>;
|
||||
envs?: Envs;
|
||||
/**
|
||||
* The name used to identify this extension
|
||||
*/
|
||||
name: string;
|
||||
timeout?: number | null;
|
||||
type: 'sse';
|
||||
uri: string;
|
||||
uri?: string | null;
|
||||
} | {
|
||||
args: Array<string>;
|
||||
available_tools?: Array<string>;
|
||||
@@ -351,6 +343,7 @@ export type ExtensionQuery = {
|
||||
|
||||
export type ExtensionResponse = {
|
||||
extensions: Array<ExtensionEntry>;
|
||||
warnings?: Array<string>;
|
||||
};
|
||||
|
||||
export type FrontendToolRequest = {
|
||||
@@ -667,6 +660,9 @@ export type RawImageContent = {
|
||||
};
|
||||
|
||||
export type RawResource = {
|
||||
_meta?: {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
description?: string;
|
||||
icons?: Array<Icon>;
|
||||
mimeType?: string;
|
||||
|
||||
@@ -31,6 +31,7 @@ interface ConfigContextType {
|
||||
config: ConfigResponse['config'];
|
||||
providersList: ProviderDetails[];
|
||||
extensionsList: FixedExtensionEntry[];
|
||||
extensionWarnings: string[];
|
||||
upsert: (key: string, value: unknown, is_secret: boolean) => Promise<void>;
|
||||
read: (key: string, is_secret: boolean) => Promise<unknown>;
|
||||
remove: (key: string, is_secret: boolean) => Promise<void>;
|
||||
@@ -62,6 +63,7 @@ export const ConfigProvider: React.FC<ConfigProviderProps> = ({ children }) => {
|
||||
const [config, setConfig] = useState<ConfigResponse['config']>({});
|
||||
const [providersList, setProvidersList] = useState<ProviderDetails[]>([]);
|
||||
const [extensionsList, setExtensionsList] = useState<FixedExtensionEntry[]>([]);
|
||||
const [extensionWarnings, setExtensionWarnings] = useState<string[]>([]);
|
||||
|
||||
const reloadConfig = useCallback(async () => {
|
||||
const response = await readAllConfig();
|
||||
@@ -116,6 +118,7 @@ export const ConfigProvider: React.FC<ConfigProviderProps> = ({ children }) => {
|
||||
|
||||
const extensionResponse: ExtensionResponse = result.data!;
|
||||
setExtensionsList(extensionResponse.extensions);
|
||||
setExtensionWarnings(extensionResponse.warnings || []);
|
||||
return extensionResponse.extensions;
|
||||
}, [extensionsList]);
|
||||
|
||||
@@ -216,6 +219,7 @@ export const ConfigProvider: React.FC<ConfigProviderProps> = ({ children }) => {
|
||||
try {
|
||||
const extensionsResponse = await apiGetExtensions();
|
||||
setExtensionsList(extensionsResponse.data?.extensions || []);
|
||||
setExtensionWarnings(extensionsResponse.data?.warnings || []);
|
||||
} catch (error) {
|
||||
console.error('Failed to load extensions:', error);
|
||||
}
|
||||
@@ -244,6 +248,7 @@ export const ConfigProvider: React.FC<ConfigProviderProps> = ({ children }) => {
|
||||
config,
|
||||
providersList,
|
||||
extensionsList,
|
||||
extensionWarnings,
|
||||
upsert,
|
||||
read,
|
||||
remove,
|
||||
@@ -260,6 +265,7 @@ export const ConfigProvider: React.FC<ConfigProviderProps> = ({ children }) => {
|
||||
config,
|
||||
providersList,
|
||||
extensionsList,
|
||||
extensionWarnings,
|
||||
upsert,
|
||||
read,
|
||||
remove,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useState, useCallback, useMemo } from 'react';
|
||||
import { Button } from '../../ui/button';
|
||||
import { Plus } from 'lucide-react';
|
||||
import { Plus, AlertTriangle } from 'lucide-react';
|
||||
import { GPSIcon } from '../../ui/icons';
|
||||
import { useConfig, FixedExtensionEntry } from '../../ConfigContext';
|
||||
import ExtensionList from './subcomponents/ExtensionList';
|
||||
@@ -38,7 +38,7 @@ export default function ExtensionsSection({
|
||||
onModalClose,
|
||||
searchTerm = '',
|
||||
}: ExtensionSectionProps) {
|
||||
const { getExtensions, addExtension, removeExtension, extensionsList } = useConfig();
|
||||
const { getExtensions, addExtension, removeExtension, extensionsList, extensionWarnings } = useConfig();
|
||||
const [selectedExtension, setSelectedExtension] = useState<FixedExtensionEntry | null>(null);
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [isAddModalOpen, setIsAddModalOpen] = useState(false);
|
||||
@@ -234,6 +234,22 @@ export default function ExtensionsSection({
|
||||
return (
|
||||
<section id="extensions">
|
||||
<div className="">
|
||||
{/* Unsupported extension warnings */}
|
||||
{extensionWarnings.length > 0 && (
|
||||
<div className="mb-4 p-3 bg-yellow-500/10 border border-yellow-500/30 rounded-lg">
|
||||
<div className="flex items-start gap-2">
|
||||
<AlertTriangle className="h-5 w-5 text-yellow-500 flex-shrink-0 mt-0.5" />
|
||||
<div className="text-sm text-yellow-500">
|
||||
{extensionWarnings.map((warning, index) => (
|
||||
<p key={index} className={index > 0 ? 'mt-1' : ''}>
|
||||
{warning}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<ExtensionList
|
||||
extensions={extensions}
|
||||
onToggle={handleExtensionToggle}
|
||||
|
||||
@@ -10,7 +10,7 @@ type BundledExtension = {
|
||||
display_name?: string;
|
||||
description: string;
|
||||
enabled: boolean;
|
||||
type: 'builtin' | 'stdio' | 'sse';
|
||||
type: 'builtin' | 'stdio' | 'streamable_http';
|
||||
cmd?: string;
|
||||
args?: string[];
|
||||
uri?: string;
|
||||
@@ -80,7 +80,7 @@ export async function syncBundledExtensions(
|
||||
bundled: true,
|
||||
};
|
||||
break;
|
||||
case 'sse':
|
||||
case 'streamable_http':
|
||||
extConfig = {
|
||||
type: bundledExt.type,
|
||||
name: bundledExt.name,
|
||||
|
||||
@@ -64,21 +64,6 @@ function getStdioConfig(
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an extension config for SSE from the deeplink URL
|
||||
*/
|
||||
function getSseConfig(remoteUrl: string, name: string, description: string, timeout: number) {
|
||||
const config: ExtensionConfig = {
|
||||
name,
|
||||
type: 'sse',
|
||||
uri: remoteUrl,
|
||||
description,
|
||||
timeout: timeout,
|
||||
};
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an extension config for Streamable HTTP from the deeplink URL
|
||||
*/
|
||||
@@ -150,9 +135,6 @@ export async function addExtensionFromDeepLink(
|
||||
|
||||
const cmd = parsedUrl.searchParams.get('cmd');
|
||||
const remoteUrl = parsedUrl.searchParams.get('url');
|
||||
// Support both 'transport' and 'type' parameters for consistency
|
||||
const transportType =
|
||||
parsedUrl.searchParams.get('transport') || parsedUrl.searchParams.get('type') || 'sse'; // Default to SSE for backward compatibility
|
||||
|
||||
const headerParams = parsedUrl.searchParams.getAll('header');
|
||||
const headers =
|
||||
@@ -178,9 +160,7 @@ export async function addExtensionFromDeepLink(
|
||||
: undefined;
|
||||
|
||||
const baseConfig = remoteUrl
|
||||
? transportType === 'streamable_http'
|
||||
? getStreamableHttpConfig(remoteUrl, name, description || '', timeout, headers, envs)
|
||||
: getSseConfig(remoteUrl, name, description || '', timeout)
|
||||
? getStreamableHttpConfig(remoteUrl, name, description || '', timeout, headers, envs)
|
||||
: getStdioConfig(cmd!, parsedUrl, name, description || '', timeout);
|
||||
|
||||
const config = {
|
||||
|
||||
@@ -48,10 +48,10 @@ export default function ExtensionInfoFields({
|
||||
label:
|
||||
type === 'stdio'
|
||||
? 'STDIO'
|
||||
: type === 'sse'
|
||||
? 'SSE'
|
||||
: type === 'streamable_http'
|
||||
? 'HTTP'
|
||||
: type === 'streamable_http'
|
||||
? 'HTTP'
|
||||
: type === 'sse'
|
||||
? 'SSE (unsupported)'
|
||||
: type.toUpperCase(),
|
||||
}}
|
||||
onChange={(newValue: unknown) => {
|
||||
@@ -62,7 +62,6 @@ export default function ExtensionInfoFields({
|
||||
}}
|
||||
options={[
|
||||
{ value: 'stdio', label: 'Standard IO (STDIO)' },
|
||||
{ value: 'sse', label: 'Server-Sent Events (SSE)' },
|
||||
{ value: 'streamable_http', label: 'Streamable HTTP' },
|
||||
]}
|
||||
isSearchable={false}
|
||||
|
||||
@@ -79,31 +79,6 @@ describe('Extension Utils', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should convert sse extension to form data', () => {
|
||||
const extension: FixedExtensionEntry = {
|
||||
type: 'sse',
|
||||
name: 'sse-extension',
|
||||
description: 'SSE description',
|
||||
uri: 'http://localhost:8080/events',
|
||||
enabled: false,
|
||||
env_keys: ['TOKEN'],
|
||||
};
|
||||
|
||||
const formData = extensionToFormData(extension);
|
||||
|
||||
expect(formData).toEqual({
|
||||
name: 'sse-extension',
|
||||
description: 'SSE description',
|
||||
type: 'sse',
|
||||
cmd: undefined,
|
||||
endpoint: 'http://localhost:8080/events',
|
||||
enabled: false,
|
||||
timeout: undefined,
|
||||
envVars: [{ key: 'TOKEN', value: '••••••••', isEdited: false }],
|
||||
headers: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('should convert streamable_http extension to form data', () => {
|
||||
const extension: FixedExtensionEntry = {
|
||||
type: 'streamable_http',
|
||||
@@ -214,31 +189,6 @@ describe('Extension Utils', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should create sse extension config', () => {
|
||||
const formData = {
|
||||
name: 'test-sse',
|
||||
description: 'Test SSE extension',
|
||||
type: 'sse' as const,
|
||||
cmd: '',
|
||||
endpoint: 'http://localhost:8080/events',
|
||||
enabled: true,
|
||||
timeout: 600,
|
||||
envVars: [{ key: 'TOKEN', value: 'abc123', isEdited: true }],
|
||||
headers: [],
|
||||
};
|
||||
|
||||
const config = createExtensionConfig(formData);
|
||||
|
||||
expect(config).toEqual({
|
||||
type: 'sse',
|
||||
name: 'test-sse',
|
||||
description: 'Test SSE extension',
|
||||
timeout: 600,
|
||||
uri: 'http://localhost:8080/events',
|
||||
env_keys: ['TOKEN'],
|
||||
});
|
||||
});
|
||||
|
||||
it('should create streamable_http extension config', () => {
|
||||
const formData = {
|
||||
name: 'test-http',
|
||||
|
||||
@@ -55,8 +55,7 @@ export function getDefaultFormData(): ExtensionFormData {
|
||||
|
||||
export function extensionToFormData(extension: FixedExtensionEntry): ExtensionFormData {
|
||||
// Type guard: Check if 'envs' property exists for this variant
|
||||
const hasEnvs =
|
||||
extension.type === 'sse' || extension.type === 'streamable_http' || extension.type === 'stdio';
|
||||
const hasEnvs = extension.type === 'streamable_http' || extension.type === 'stdio';
|
||||
|
||||
// Handle both envs (legacy) and env_keys (new secrets)
|
||||
let envVars = [];
|
||||
@@ -106,7 +105,9 @@ export function extensionToFormData(extension: FixedExtensionEntry): ExtensionFo
|
||||
: extension.type,
|
||||
cmd: extension.type === 'stdio' ? combineCmdAndArgs(extension.cmd, extension.args) : undefined,
|
||||
endpoint:
|
||||
extension.type === 'sse' || extension.type === 'streamable_http' ? extension.uri : undefined,
|
||||
extension.type === 'streamable_http' || extension.type === 'sse'
|
||||
? (extension.uri ?? undefined)
|
||||
: undefined,
|
||||
enabled: extension.enabled,
|
||||
timeout: 'timeout' in extension ? (extension.timeout ?? undefined) : undefined,
|
||||
envVars,
|
||||
@@ -134,15 +135,6 @@ export function createExtensionConfig(formData: ExtensionFormData): ExtensionCon
|
||||
timeout: formData.timeout,
|
||||
...(env_keys.length > 0 ? { env_keys } : {}),
|
||||
};
|
||||
} else if (formData.type === 'sse') {
|
||||
return {
|
||||
type: 'sse',
|
||||
name: formData.name,
|
||||
description: formData.description,
|
||||
timeout: formData.timeout,
|
||||
uri: formData.endpoint || '',
|
||||
...(env_keys.length > 0 ? { env_keys } : {}),
|
||||
};
|
||||
} else if (formData.type === 'streamable_http') {
|
||||
// Extract headers
|
||||
const headers = formData.headers
|
||||
|
||||
@@ -106,6 +106,19 @@ export const initializeSystem = async (
|
||||
const extensionLoadingPromises = enabledExtensions.map(async (extensionConfig) => {
|
||||
const extensionName = extensionConfig.name;
|
||||
|
||||
// SSE is unsupported - fail immediately without calling the backend
|
||||
if (extensionConfig.type === 'sse') {
|
||||
const errMsg = 'SSE is unsupported, migrate to streamable_http';
|
||||
extensionStatuses.set(extensionName, {
|
||||
name: extensionName,
|
||||
status: 'error',
|
||||
error: errMsg,
|
||||
recoverHints: createExtensionRecoverHints(errMsg),
|
||||
});
|
||||
updateToast();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await addToAgentOnStartup({
|
||||
extensionConfig,
|
||||
|
||||
Reference in New Issue
Block a user