mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-19 12:24:46 +08:00
improve: add abort btn to abort the mcp add request. (#284)
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { Loader2 } from "lucide-react";
|
import { Loader2 } from "lucide-react";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useRef, useState } from "react";
|
||||||
|
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import {
|
import {
|
||||||
@@ -34,6 +34,8 @@ export function AddMCPServerDialog({
|
|||||||
const [validationError, setValidationError] = useState<string | null>("");
|
const [validationError, setValidationError] = useState<string | null>("");
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [processing, setProcessing] = useState(false);
|
const [processing, setProcessing] = useState(false);
|
||||||
|
const abortControllerRef = useRef<AbortController | null>(null);
|
||||||
|
|
||||||
const handleChange = useCallback((value: string) => {
|
const handleChange = useCallback((value: string) => {
|
||||||
setInput(value);
|
setInput(value);
|
||||||
if (!value.trim()) {
|
if (!value.trim()) {
|
||||||
@@ -74,7 +76,9 @@ export function AddMCPServerDialog({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleAdd = useCallback(async () => {
|
const handleAdd = useCallback(async () => {
|
||||||
|
abortControllerRef.current = new AbortController();
|
||||||
const config = MCPConfigSchema.parse(JSON.parse(input));
|
const config = MCPConfigSchema.parse(JSON.parse(input));
|
||||||
setInput(JSON.stringify(config, null, 2));
|
setInput(JSON.stringify(config, null, 2));
|
||||||
const addingServers: SimpleMCPServerMetadata[] = [];
|
const addingServers: SimpleMCPServerMetadata[] = [];
|
||||||
@@ -105,7 +109,7 @@ export function AddMCPServerDialog({
|
|||||||
setError(null);
|
setError(null);
|
||||||
for (const server of addingServers) {
|
for (const server of addingServers) {
|
||||||
processingServer = server.name;
|
processingServer = server.name;
|
||||||
const metadata = await queryMCPServerMetadata(server);
|
const metadata = await queryMCPServerMetadata(server, abortControllerRef.current.signal);
|
||||||
results.push({ ...metadata, name: server.name, enabled: true });
|
results.push({ ...metadata, name: server.name, enabled: true });
|
||||||
}
|
}
|
||||||
if (results.length > 0) {
|
if (results.length > 0) {
|
||||||
@@ -115,12 +119,23 @@ export function AddMCPServerDialog({
|
|||||||
setOpen(false);
|
setOpen(false);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
setError(`Failed to add server: ${processingServer}`);
|
if (e instanceof Error && e.name === 'AbortError') {
|
||||||
|
setError(`Request was cancelled`);
|
||||||
|
} else {
|
||||||
|
setError(`Failed to add server: ${processingServer}`);
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
setProcessing(false);
|
setProcessing(false);
|
||||||
|
abortControllerRef.current = null;
|
||||||
}
|
}
|
||||||
}, [input, onAdd]);
|
}, [input, onAdd]);
|
||||||
|
|
||||||
|
const handleAbort = () => {
|
||||||
|
if (abortControllerRef.current) {
|
||||||
|
abortControllerRef.current.abort();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={setOpen}>
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
@@ -165,6 +180,11 @@ export function AddMCPServerDialog({
|
|||||||
{processing && <Loader2 className="animate-spin" />}
|
{processing && <Loader2 className="animate-spin" />}
|
||||||
Add
|
Add
|
||||||
</Button>
|
</Button>
|
||||||
|
{
|
||||||
|
processing && (
|
||||||
|
<Button variant="destructive" onClick={handleAbort}>Abort</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
|
|||||||
@@ -5,13 +5,14 @@ import type { SimpleMCPServerMetadata } from "../mcp";
|
|||||||
|
|
||||||
import { resolveServiceURL } from "./resolve-service-url";
|
import { resolveServiceURL } from "./resolve-service-url";
|
||||||
|
|
||||||
export async function queryMCPServerMetadata(config: SimpleMCPServerMetadata) {
|
export async function queryMCPServerMetadata(config: SimpleMCPServerMetadata, signal?: AbortSignal) {
|
||||||
const response = await fetch(resolveServiceURL("mcp/server/metadata"), {
|
const response = await fetch(resolveServiceURL("mcp/server/metadata"), {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify(config),
|
body: JSON.stringify(config),
|
||||||
|
signal,
|
||||||
});
|
});
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
|||||||
Reference in New Issue
Block a user