mirror of
https://github.com/lobehub/lobe-chat.git
synced 2026-06-14 03:30:19 +00:00
3415df3715
* ♻️ refactor: remove @lobehub/chat-plugin-sdk dependency Plugins have been deprecated. This removes the SDK entirely: - Define built-in ToolManifest, ToolManifestSettings, ToolErrorType types - Delete src/features/PluginsUI/ (plugin iframe rendering) - Delete src/store/tool/slices/oldStore/ (deprecated plugin store) - Delete src/server/services/pluginGateway/ (plugin gateway) - Delete src/app/(backend)/webapi/plugin/gateway/ (plugin API route) - Migrate all ~50 files from SDK imports to @lobechat/types - Remove @lobehub/chat-plugin-sdk, @lobehub/chat-plugins-gateway deps - Remove @swagger-api/apidom-reference override and patch Fixes LOBE-6655 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 🐛 fix: add missing getInstalledPlugins mock in customPlugin test Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 🔧 chore: increase Vercel build memory limit to 8192MB The 6144MB limit was causing OOM during Vite SPA chunk rendering. Aligned with other build commands that already use 8192MB. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ♻️ refactor: unify default tool type to builtin and fix CustomRender - Remove `invokeDefaultTypePlugin` — default type now falls through to builtin in both server and client execution paths - Fix `CustomRender` to actually render builtin tool components via `getBuiltinRender` instead of always returning null - Increase SPA build memory limit from 7168MB to 8192MB to fix OOM Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ♻️ refactor: remove legacy plugin gateway and type-specific invocations - Delete `runPluginApi`, `internal_callPluginApi`, `invokeMarkdownTypePlugin`, `invokeStandaloneTypePlugin` - Remove plugin gateway endpoint (`/webapi/plugin/gateway`) from URL config - Remove special `builtin → default` runtimeType mapping in plugin model - Clean up unused imports and related tests Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 🐛 fix: add 'builtin' to runtimeType union to fix type error Use ToolManifestType instead of inline union for runtimeType fields so that 'builtin' is included as a valid type. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
146 lines
4.8 KiB
TypeScript
146 lines
4.8 KiB
TypeScript
import { type ToolManifest } from '@lobechat/types';
|
|
|
|
import { safeParseJSON } from '@/utils/safeParseJSON';
|
|
|
|
// (McpConfig, McpServers, ParsedMcpInput interface definitions remain unchanged)
|
|
interface McpConfig {
|
|
args?: string[];
|
|
command?: string;
|
|
url?: string;
|
|
}
|
|
|
|
interface McpServers {
|
|
[key: string]: McpConfig;
|
|
}
|
|
|
|
interface ParsedMcpInput {
|
|
manifest?: ToolManifest;
|
|
mcpServers?: McpServers;
|
|
}
|
|
|
|
// Removed DuplicateIdentifier
|
|
export enum McpParseErrorCode {
|
|
EmptyMcpServers = 'EmptyMcpServers',
|
|
InvalidJsonStructure = 'InvalidJsonStructure',
|
|
InvalidMcpStructure = 'InvalidMcpStructure',
|
|
ManifestNotSupported = 'ManifestNotSupported',
|
|
}
|
|
|
|
// Removed isDuplicate
|
|
interface ParseSuccessResult {
|
|
identifier: string;
|
|
mcpConfig: McpConfig & { type: 'stdio' | 'http' };
|
|
status: 'success';
|
|
}
|
|
|
|
interface ParseErrorResult {
|
|
errorCode: McpParseErrorCode;
|
|
// identifier field may still be useful for displaying the user-input ID when structure errors occur
|
|
identifier?: string;
|
|
status: 'error';
|
|
}
|
|
|
|
interface ParseNoOpResult {
|
|
status: 'noop';
|
|
}
|
|
|
|
export type ParseResult = ParseSuccessResult | ParseErrorResult | ParseNoOpResult;
|
|
|
|
export const parseMcpInput = (value: string): ParseResult => {
|
|
const parsedJson = safeParseJSON<ParsedMcpInput | McpServers>(value);
|
|
|
|
if (parsedJson && typeof parsedJson === 'object' && !Array.isArray(parsedJson)) {
|
|
// 1. Check for the nested "mcpServers" structure
|
|
if (
|
|
'mcpServers' in parsedJson &&
|
|
typeof parsedJson.mcpServers === 'object' &&
|
|
parsedJson.mcpServers !== null
|
|
) {
|
|
const mcpKeys = Object.keys(parsedJson.mcpServers);
|
|
|
|
if (mcpKeys.length > 0) {
|
|
const identifier = mcpKeys[0];
|
|
// @ts-expect-error type mismatch
|
|
const mcpConfig = parsedJson.mcpServers[identifier];
|
|
|
|
if (mcpConfig && typeof mcpConfig === 'object' && !Array.isArray(mcpConfig)) {
|
|
let resultMcpConfig: McpConfig & { type?: 'stdio' | 'http' };
|
|
|
|
if (mcpConfig.command && Array.isArray(mcpConfig.args)) {
|
|
resultMcpConfig = { ...mcpConfig, type: 'stdio' };
|
|
} else if (mcpConfig.url) {
|
|
resultMcpConfig = { type: 'http', url: mcpConfig.url };
|
|
} else {
|
|
return {
|
|
errorCode: McpParseErrorCode.InvalidMcpStructure,
|
|
identifier,
|
|
status: 'error',
|
|
};
|
|
}
|
|
|
|
return {
|
|
identifier,
|
|
mcpConfig: resultMcpConfig as McpConfig & { type: 'stdio' | 'http' },
|
|
status: 'success',
|
|
};
|
|
}
|
|
// mcpConfig is invalid or not an object
|
|
return {
|
|
errorCode: McpParseErrorCode.InvalidMcpStructure,
|
|
identifier,
|
|
status: 'error',
|
|
};
|
|
} else {
|
|
// mcpServers object is empty
|
|
return { errorCode: McpParseErrorCode.EmptyMcpServers, status: 'error' };
|
|
}
|
|
}
|
|
// 3. Check for the flat structure (identifier as top-level key)
|
|
else {
|
|
const topLevelKeys = Object.keys(parsedJson);
|
|
|
|
// Allow exactly one top-level key which is the identifier
|
|
if (topLevelKeys.length === 1) {
|
|
const identifier = topLevelKeys[0];
|
|
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
const mcpConfig = (parsedJson as any)[identifier];
|
|
|
|
if (mcpConfig && typeof mcpConfig === 'object' && !Array.isArray(mcpConfig)) {
|
|
let resultMcpConfig: McpConfig & { type?: 'stdio' | 'http' };
|
|
|
|
// Explicitly check properties of mcpConfig
|
|
if (mcpConfig.command && Array.isArray(mcpConfig.args)) {
|
|
resultMcpConfig = { ...mcpConfig, type: 'stdio' };
|
|
} else if (mcpConfig.url) {
|
|
// For the flat structure, ensure only 'url' is included for http type
|
|
resultMcpConfig = { type: 'http', url: mcpConfig.url };
|
|
} else {
|
|
// Invalid structure within the identifier's value
|
|
return {
|
|
errorCode: McpParseErrorCode.InvalidMcpStructure,
|
|
identifier, // We have the identifier here
|
|
status: 'error',
|
|
};
|
|
}
|
|
|
|
// Structure parsed successfully
|
|
return {
|
|
identifier,
|
|
mcpConfig: resultMcpConfig as McpConfig & { type: 'stdio' | 'http' },
|
|
status: 'success',
|
|
};
|
|
} else {
|
|
// The value associated with the single key is not a valid config object
|
|
return { errorCode: McpParseErrorCode.InvalidMcpStructure, identifier, status: 'error' };
|
|
}
|
|
} else {
|
|
// Neither mcpServers nor manifest, and not a single top-level key structure
|
|
return { errorCode: McpParseErrorCode.InvalidJsonStructure, status: 'error' };
|
|
}
|
|
}
|
|
}
|
|
|
|
// Input is not a valid JSON object or failed safeParseJSON
|
|
return { status: 'noop' }; // Or potentially InvalidJsonStructure if safeParse failed but wasn't null/undefined?
|
|
};
|