mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
Allow running of agents from the monitor page
This commit is contained in:
@@ -1,7 +1,3 @@
|
||||
export default function HealthPage() {
|
||||
return (
|
||||
<div>
|
||||
Yay im healthy
|
||||
</div>
|
||||
);
|
||||
return <div>Yay im healthy</div>;
|
||||
}
|
||||
|
||||
@@ -98,8 +98,8 @@ export const AgentImportForm: React.FC<
|
||||
is_active: !values.importAsTemplate,
|
||||
};
|
||||
|
||||
(api.createGraph(payload)
|
||||
)
|
||||
api
|
||||
.createGraph(payload)
|
||||
.then((response) => {
|
||||
const qID = "flowID";
|
||||
window.location.href = `/build?${qID}=${response.id}`;
|
||||
|
||||
@@ -55,7 +55,6 @@ export const SaveControl = ({
|
||||
onSave();
|
||||
}, [onSave]);
|
||||
|
||||
|
||||
const { toast } = useToast();
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
import Link from "next/link";
|
||||
import { ArrowLeft, Download } from "lucide-react";
|
||||
import { ArrowLeft, Download, Calendar, Tag } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import AutoGPTServerAPI, { GraphCreatable } from "@/lib/autogpt-server-api";
|
||||
import "@xyflow/react/dist/style.css";
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import React, { useEffect, useMemo, useState, useCallback } from "react";
|
||||
import AutoGPTServerAPI, {
|
||||
Graph,
|
||||
GraphMeta,
|
||||
safeCopyGraph,
|
||||
BlockUIType,
|
||||
BlockIORootSchema,
|
||||
} from "@/lib/autogpt-server-api";
|
||||
import { FlowRun } from "@/lib/types";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
@@ -18,9 +20,9 @@ import {
|
||||
import { Button, buttonVariants } from "@/components/ui/button";
|
||||
import { ClockIcon, ExitIcon, Pencil2Icon } from "@radix-ui/react-icons";
|
||||
import Link from "next/link";
|
||||
import { exportAsJSONFile } from "@/lib/utils";
|
||||
import { exportAsJSONFile, filterBlocksByType } from "@/lib/utils";
|
||||
import { FlowRunsStats } from "@/components/monitor/index";
|
||||
import { Trash2Icon } from "lucide-react";
|
||||
import { Trash2Icon, Timer } from "lucide-react";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -29,6 +31,10 @@ import {
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
} from "@/components/ui/dialog";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import { CronScheduler } from "@/components/cronScheduler";
|
||||
import RunnerInputUI from "@/components/runner-ui/RunnerInputUI";
|
||||
import useAgentGraph from "@/hooks/useAgentGraph";
|
||||
|
||||
export const FlowInfo: React.FC<
|
||||
React.HTMLAttributes<HTMLDivElement> & {
|
||||
@@ -38,7 +44,30 @@ export const FlowInfo: React.FC<
|
||||
refresh: () => void;
|
||||
}
|
||||
> = ({ flow, flowRuns, flowVersion, refresh, ...props }) => {
|
||||
const {
|
||||
agentName,
|
||||
setAgentName,
|
||||
agentDescription,
|
||||
setAgentDescription,
|
||||
savedAgent,
|
||||
availableNodes,
|
||||
availableFlows,
|
||||
getOutputType,
|
||||
requestSave,
|
||||
requestSaveAndRun,
|
||||
requestStopRun,
|
||||
scheduleRunner,
|
||||
isRunning,
|
||||
isScheduling,
|
||||
setIsScheduling,
|
||||
nodes,
|
||||
setNodes,
|
||||
edges,
|
||||
setEdges,
|
||||
} = useAgentGraph(flow.id, false);
|
||||
|
||||
const api = useMemo(() => new AutoGPTServerAPI(), []);
|
||||
const { toast } = useToast();
|
||||
|
||||
const [flowVersions, setFlowVersions] = useState<Graph[] | null>(null);
|
||||
const [selectedVersion, setSelectedFlowVersion] = useState(
|
||||
@@ -50,11 +79,103 @@ export const FlowInfo: React.FC<
|
||||
);
|
||||
|
||||
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||
const [openCron, setOpenCron] = useState(false);
|
||||
const [isRunnerInputOpen, setIsRunnerInputOpen] = useState(false);
|
||||
const isDisabled = !selectedFlowVersion;
|
||||
|
||||
const getBlockInputsAndOutputs = useCallback(() => {
|
||||
const inputBlocks = filterBlocksByType(
|
||||
nodes,
|
||||
(node) => node.data.uiType === BlockUIType.INPUT,
|
||||
);
|
||||
|
||||
const outputBlocks = filterBlocksByType(
|
||||
nodes,
|
||||
(node) => node.data.uiType === BlockUIType.OUTPUT,
|
||||
);
|
||||
|
||||
const inputs = inputBlocks.map((node) => ({
|
||||
id: node.id,
|
||||
type: "input" as const,
|
||||
inputSchema: node.data.inputSchema as BlockIORootSchema,
|
||||
hardcodedValues: {
|
||||
name: (node.data.hardcodedValues as any).name || "",
|
||||
description: (node.data.hardcodedValues as any).description || "",
|
||||
value: (node.data.hardcodedValues as any).value,
|
||||
placeholder_values:
|
||||
(node.data.hardcodedValues as any).placeholder_values || [],
|
||||
limit_to_placeholder_values:
|
||||
(node.data.hardcodedValues as any).limit_to_placeholder_values ||
|
||||
false,
|
||||
},
|
||||
}));
|
||||
|
||||
const outputs = outputBlocks.map((node) => ({
|
||||
id: node.id,
|
||||
type: "output" as const,
|
||||
hardcodedValues: {
|
||||
name: (node.data.hardcodedValues as any).name || "Output",
|
||||
description:
|
||||
(node.data.hardcodedValues as any).description ||
|
||||
"Output from the agent",
|
||||
value: (node.data.hardcodedValues as any).value,
|
||||
},
|
||||
result: (node.data.executionResults as any)?.at(-1)?.data?.output,
|
||||
}));
|
||||
|
||||
return { inputs, outputs };
|
||||
}, [nodes]);
|
||||
|
||||
const handleScheduleButton = () => {
|
||||
if (!selectedFlowVersion) {
|
||||
toast({
|
||||
title: "Please select a flow version before scheduling",
|
||||
duration: 2000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
setOpenCron(true);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
api.getGraphAllVersions(flow.id).then((result) => setFlowVersions(result));
|
||||
}, [flow.id, api]);
|
||||
|
||||
const openRunnerInput = () => setIsRunnerInputOpen(true);
|
||||
|
||||
const runOrOpenInput = () => {
|
||||
const { inputs } = getBlockInputsAndOutputs();
|
||||
if (inputs.length > 0) {
|
||||
openRunnerInput();
|
||||
} else {
|
||||
requestSaveAndRun();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
(nodeId: string, field: string, value: string) => {
|
||||
setNodes((nds) =>
|
||||
nds.map((node) => {
|
||||
if (node.id === nodeId) {
|
||||
return {
|
||||
...node,
|
||||
data: {
|
||||
...node.data,
|
||||
hardcodedValues: {
|
||||
...(node.data.hardcodedValues as any),
|
||||
[field]: value,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
return node;
|
||||
}),
|
||||
);
|
||||
},
|
||||
[setNodes],
|
||||
);
|
||||
|
||||
return (
|
||||
<Card {...props}>
|
||||
<CardHeader className="flex-row justify-between space-x-3 space-y-0">
|
||||
@@ -62,9 +183,6 @@ export const FlowInfo: React.FC<
|
||||
<CardTitle>
|
||||
{flow.name} <span className="font-light">v{flow.version}</span>
|
||||
</CardTitle>
|
||||
<p className="mt-2">
|
||||
Agent ID: <code>{flow.id}</code>
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-start space-x-2">
|
||||
{(flowVersions?.length ?? 0) > 1 && (
|
||||
@@ -130,6 +248,15 @@ export const FlowInfo: React.FC<
|
||||
>
|
||||
<ExitIcon className="mr-2" /> Export
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
className="bg-purple-500 text-white hover:bg-purple-700"
|
||||
onClick={isRunning ? requestStopRun : runOrOpenInput}
|
||||
disabled={isDisabled}
|
||||
title={!isRunning ? "Run Agent" : "Stop Agent"}
|
||||
>
|
||||
{isRunning ? "Stop Agent" : "Run Agent"}
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setIsDeleteModalOpen(true)}
|
||||
@@ -179,6 +306,20 @@ export const FlowInfo: React.FC<
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
<RunnerInputUI
|
||||
isOpen={isRunnerInputOpen}
|
||||
onClose={() => setIsRunnerInputOpen(false)}
|
||||
blockInputs={getBlockInputsAndOutputs().inputs}
|
||||
onInputChange={handleInputChange}
|
||||
onRun={() => {
|
||||
setIsRunnerInputOpen(false);
|
||||
requestSaveAndRun();
|
||||
}}
|
||||
isRunning={isRunning}
|
||||
scheduledInput={false}
|
||||
isScheduling={false}
|
||||
onSchedule={async () => {}} // Fixed type error by making async
|
||||
/>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -97,12 +97,7 @@ export const FlowRunInfo: React.FC<
|
||||
<CardTitle>
|
||||
{flow.name} <span className="font-light">v{flow.version}</span>
|
||||
</CardTitle>
|
||||
<p className="mt-2">
|
||||
Agent ID: <code>{flow.id}</code>
|
||||
</p>
|
||||
<p className="mt-1">
|
||||
Run ID: <code>{flowRun.id}</code>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
<div className="flex space-x-2">
|
||||
{flowRun.status === "running" && (
|
||||
@@ -122,6 +117,12 @@ export const FlowRunInfo: React.FC<
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="hidden">
|
||||
<strong>Agent ID:</strong> <code>{flow.id}</code>
|
||||
</p>
|
||||
<p className="hidden">
|
||||
<strong>Run ID:</strong> <code>{flowRun.id}</code>
|
||||
</p>
|
||||
<div>
|
||||
<strong>Status:</strong>{" "}
|
||||
<FlowRunStatusBadge status={flowRun.status} />
|
||||
@@ -138,6 +139,7 @@ export const FlowRunInfo: React.FC<
|
||||
<strong>Duration (run time):</strong> {flowRun.duration} (
|
||||
{flowRun.totalRunTime}) seconds
|
||||
</p>
|
||||
|
||||
</CardContent>
|
||||
</Card>
|
||||
<RunnerOutputUI
|
||||
|
||||
@@ -24,7 +24,10 @@ import { GraphMeta } from "@/lib/autogpt-server-api";
|
||||
|
||||
const ajv = new Ajv({ strict: false, allErrors: true });
|
||||
|
||||
export default function useAgentGraph(flowID?: string, passDataToBeads?: boolean) {
|
||||
export default function useAgentGraph(
|
||||
flowID?: string,
|
||||
passDataToBeads?: boolean,
|
||||
) {
|
||||
const { toast } = useToast();
|
||||
const [router, searchParams, pathname] = [
|
||||
useRouter(),
|
||||
@@ -637,200 +640,189 @@ export default function useAgentGraph(flowID?: string, passDataToBeads?: boolean
|
||||
[availableNodes],
|
||||
);
|
||||
|
||||
const _saveAgent = useCallback(
|
||||
async () => {
|
||||
//FIXME frontend ids should be resolved better (e.g. returned from the server)
|
||||
// currently this relays on block_id and position
|
||||
const blockIdToNodeIdMap: Record<string, string> = {};
|
||||
const _saveAgent = useCallback(async () => {
|
||||
//FIXME frontend ids should be resolved better (e.g. returned from the server)
|
||||
// currently this relays on block_id and position
|
||||
const blockIdToNodeIdMap: Record<string, string> = {};
|
||||
|
||||
nodes.forEach((node) => {
|
||||
const key = `${node.data.block_id}_${node.position.x}_${node.position.y}`;
|
||||
blockIdToNodeIdMap[key] = node.id;
|
||||
});
|
||||
nodes.forEach((node) => {
|
||||
const key = `${node.data.block_id}_${node.position.x}_${node.position.y}`;
|
||||
blockIdToNodeIdMap[key] = node.id;
|
||||
});
|
||||
|
||||
const formattedNodes = nodes.map((node) => {
|
||||
const inputDefault = prepareNodeInputData(node);
|
||||
const inputNodes = edges
|
||||
.filter((edge) => edge.target === node.id)
|
||||
.map((edge) => ({
|
||||
name: edge.targetHandle || "",
|
||||
node_id: edge.source,
|
||||
}));
|
||||
|
||||
const outputNodes = edges
|
||||
.filter((edge) => edge.source === node.id)
|
||||
.map((edge) => ({
|
||||
name: edge.sourceHandle || "",
|
||||
node_id: edge.target,
|
||||
}));
|
||||
|
||||
return {
|
||||
id: node.id,
|
||||
block_id: node.data.block_id,
|
||||
input_default: inputDefault,
|
||||
input_nodes: inputNodes,
|
||||
output_nodes: outputNodes,
|
||||
data: {
|
||||
...node.data,
|
||||
hardcodedValues: removeEmptyStringsAndNulls(
|
||||
node.data.hardcodedValues,
|
||||
),
|
||||
},
|
||||
metadata: { position: node.position },
|
||||
};
|
||||
});
|
||||
|
||||
const links = edges.map((edge) => ({
|
||||
source_id: edge.source,
|
||||
sink_id: edge.target,
|
||||
source_name: edge.sourceHandle || "",
|
||||
sink_name: edge.targetHandle || "",
|
||||
}));
|
||||
|
||||
const payload = {
|
||||
id: savedAgent?.id!,
|
||||
name: agentName || `New Agent ${new Date().toISOString()}`,
|
||||
description: agentDescription || "",
|
||||
nodes: formattedNodes,
|
||||
links: links,
|
||||
};
|
||||
|
||||
// To avoid saving the same graph, we compare the payload with the saved agent.
|
||||
// Differences in IDs are ignored.
|
||||
const comparedPayload = {
|
||||
...(({ id, ...rest }) => rest)(payload),
|
||||
nodes: payload.nodes.map(
|
||||
({ id, data, input_nodes, output_nodes, ...rest }) => rest,
|
||||
),
|
||||
links: payload.links.map(({ source_id, sink_id, ...rest }) => rest),
|
||||
};
|
||||
const comparedSavedAgent = {
|
||||
name: savedAgent?.name,
|
||||
description: savedAgent?.description,
|
||||
nodes: savedAgent?.nodes.map((v) => ({
|
||||
block_id: v.block_id,
|
||||
input_default: v.input_default,
|
||||
metadata: v.metadata,
|
||||
})),
|
||||
links: savedAgent?.links.map((v) => ({
|
||||
sink_name: v.sink_name,
|
||||
source_name: v.source_name,
|
||||
})),
|
||||
};
|
||||
|
||||
let newSavedAgent = null;
|
||||
if (savedAgent && deepEquals(comparedPayload, comparedSavedAgent)) {
|
||||
console.warn("No need to save: Graph is the same as version on server");
|
||||
newSavedAgent = savedAgent;
|
||||
} else {
|
||||
console.debug(
|
||||
"Saving new Graph version; old vs new:",
|
||||
comparedPayload,
|
||||
payload,
|
||||
);
|
||||
setNodesSyncedWithSavedAgent(false);
|
||||
|
||||
newSavedAgent = savedAgent
|
||||
? await api.updateGraph(savedAgent.id, payload)
|
||||
: await api.createGraph(payload);
|
||||
|
||||
console.debug("Response from the API:", newSavedAgent);
|
||||
}
|
||||
|
||||
// Route the URL to the new flow ID if it's a new agent.
|
||||
if (!savedAgent) {
|
||||
const path = new URLSearchParams(searchParams);
|
||||
path.set("flowID", newSavedAgent.id);
|
||||
router.push(`${pathname}?${path.toString()}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the node IDs on the frontend
|
||||
setSavedAgent(newSavedAgent);
|
||||
setNodes((prev) => {
|
||||
return newSavedAgent.nodes
|
||||
.map((backendNode) => {
|
||||
const key = `${backendNode.block_id}_${backendNode.metadata.position.x}_${backendNode.metadata.position.y}`;
|
||||
const frontendNodeId = blockIdToNodeIdMap[key];
|
||||
const frontendNode = prev.find(
|
||||
(node) => node.id === frontendNodeId,
|
||||
);
|
||||
|
||||
return frontendNode
|
||||
? {
|
||||
...frontendNode,
|
||||
position: backendNode.metadata.position,
|
||||
data: {
|
||||
...frontendNode.data,
|
||||
hardcodedValues: removeEmptyStringsAndNulls(
|
||||
frontendNode.data.hardcodedValues,
|
||||
),
|
||||
status: undefined,
|
||||
backend_id: backendNode.id,
|
||||
webhookId: backendNode.webhook_id,
|
||||
executionResults: [],
|
||||
},
|
||||
}
|
||||
: null;
|
||||
})
|
||||
.filter((node) => node !== null);
|
||||
});
|
||||
// Reset bead count
|
||||
setEdges((edges) => {
|
||||
return edges.map((edge) => ({
|
||||
...edge,
|
||||
data: {
|
||||
...edge.data,
|
||||
edgeColor: edge.data?.edgeColor!,
|
||||
beadUp: 0,
|
||||
beadDown: 0,
|
||||
beadData: [],
|
||||
},
|
||||
const formattedNodes = nodes.map((node) => {
|
||||
const inputDefault = prepareNodeInputData(node);
|
||||
const inputNodes = edges
|
||||
.filter((edge) => edge.target === node.id)
|
||||
.map((edge) => ({
|
||||
name: edge.targetHandle || "",
|
||||
node_id: edge.source,
|
||||
}));
|
||||
});
|
||||
},
|
||||
[
|
||||
api,
|
||||
nodes,
|
||||
edges,
|
||||
pathname,
|
||||
router,
|
||||
searchParams,
|
||||
savedAgent,
|
||||
agentName,
|
||||
agentDescription,
|
||||
prepareNodeInputData,
|
||||
],
|
||||
);
|
||||
|
||||
const saveAgent = useCallback(
|
||||
async () => {
|
||||
try {
|
||||
await _saveAgent();
|
||||
} catch (error) {
|
||||
const errorMessage =
|
||||
error instanceof Error ? error.message : String(error);
|
||||
console.error("Error saving agent", error);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error saving agent",
|
||||
description: errorMessage,
|
||||
});
|
||||
}
|
||||
},
|
||||
[_saveAgent, toast],
|
||||
);
|
||||
const outputNodes = edges
|
||||
.filter((edge) => edge.source === node.id)
|
||||
.map((edge) => ({
|
||||
name: edge.sourceHandle || "",
|
||||
node_id: edge.target,
|
||||
}));
|
||||
|
||||
const requestSave = useCallback(
|
||||
() => {
|
||||
saveAgent();
|
||||
setSaveRunRequest({
|
||||
request: "save",
|
||||
state: "saving",
|
||||
return {
|
||||
id: node.id,
|
||||
block_id: node.data.block_id,
|
||||
input_default: inputDefault,
|
||||
input_nodes: inputNodes,
|
||||
output_nodes: outputNodes,
|
||||
data: {
|
||||
...node.data,
|
||||
hardcodedValues: removeEmptyStringsAndNulls(
|
||||
node.data.hardcodedValues,
|
||||
),
|
||||
},
|
||||
metadata: { position: node.position },
|
||||
};
|
||||
});
|
||||
|
||||
const links = edges.map((edge) => ({
|
||||
source_id: edge.source,
|
||||
sink_id: edge.target,
|
||||
source_name: edge.sourceHandle || "",
|
||||
sink_name: edge.targetHandle || "",
|
||||
}));
|
||||
|
||||
const payload = {
|
||||
id: savedAgent?.id!,
|
||||
name: agentName || `New Agent ${new Date().toISOString()}`,
|
||||
description: agentDescription || "",
|
||||
nodes: formattedNodes,
|
||||
links: links,
|
||||
};
|
||||
|
||||
// To avoid saving the same graph, we compare the payload with the saved agent.
|
||||
// Differences in IDs are ignored.
|
||||
const comparedPayload = {
|
||||
...(({ id, ...rest }) => rest)(payload),
|
||||
nodes: payload.nodes.map(
|
||||
({ id, data, input_nodes, output_nodes, ...rest }) => rest,
|
||||
),
|
||||
links: payload.links.map(({ source_id, sink_id, ...rest }) => rest),
|
||||
};
|
||||
const comparedSavedAgent = {
|
||||
name: savedAgent?.name,
|
||||
description: savedAgent?.description,
|
||||
nodes: savedAgent?.nodes.map((v) => ({
|
||||
block_id: v.block_id,
|
||||
input_default: v.input_default,
|
||||
metadata: v.metadata,
|
||||
})),
|
||||
links: savedAgent?.links.map((v) => ({
|
||||
sink_name: v.sink_name,
|
||||
source_name: v.source_name,
|
||||
})),
|
||||
};
|
||||
|
||||
let newSavedAgent = null;
|
||||
if (savedAgent && deepEquals(comparedPayload, comparedSavedAgent)) {
|
||||
console.warn("No need to save: Graph is the same as version on server");
|
||||
newSavedAgent = savedAgent;
|
||||
} else {
|
||||
console.debug(
|
||||
"Saving new Graph version; old vs new:",
|
||||
comparedPayload,
|
||||
payload,
|
||||
);
|
||||
setNodesSyncedWithSavedAgent(false);
|
||||
|
||||
newSavedAgent = savedAgent
|
||||
? await api.updateGraph(savedAgent.id, payload)
|
||||
: await api.createGraph(payload);
|
||||
|
||||
console.debug("Response from the API:", newSavedAgent);
|
||||
}
|
||||
|
||||
// Route the URL to the new flow ID if it's a new agent.
|
||||
if (!savedAgent) {
|
||||
const path = new URLSearchParams(searchParams);
|
||||
path.set("flowID", newSavedAgent.id);
|
||||
router.push(`${pathname}?${path.toString()}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the node IDs on the frontend
|
||||
setSavedAgent(newSavedAgent);
|
||||
setNodes((prev) => {
|
||||
return newSavedAgent.nodes
|
||||
.map((backendNode) => {
|
||||
const key = `${backendNode.block_id}_${backendNode.metadata.position.x}_${backendNode.metadata.position.y}`;
|
||||
const frontendNodeId = blockIdToNodeIdMap[key];
|
||||
const frontendNode = prev.find((node) => node.id === frontendNodeId);
|
||||
|
||||
return frontendNode
|
||||
? {
|
||||
...frontendNode,
|
||||
position: backendNode.metadata.position,
|
||||
data: {
|
||||
...frontendNode.data,
|
||||
hardcodedValues: removeEmptyStringsAndNulls(
|
||||
frontendNode.data.hardcodedValues,
|
||||
),
|
||||
status: undefined,
|
||||
backend_id: backendNode.id,
|
||||
webhookId: backendNode.webhook_id,
|
||||
executionResults: [],
|
||||
},
|
||||
}
|
||||
: null;
|
||||
})
|
||||
.filter((node) => node !== null);
|
||||
});
|
||||
// Reset bead count
|
||||
setEdges((edges) => {
|
||||
return edges.map((edge) => ({
|
||||
...edge,
|
||||
data: {
|
||||
...edge.data,
|
||||
edgeColor: edge.data?.edgeColor!,
|
||||
beadUp: 0,
|
||||
beadDown: 0,
|
||||
beadData: [],
|
||||
},
|
||||
}));
|
||||
});
|
||||
}, [
|
||||
api,
|
||||
nodes,
|
||||
edges,
|
||||
pathname,
|
||||
router,
|
||||
searchParams,
|
||||
savedAgent,
|
||||
agentName,
|
||||
agentDescription,
|
||||
prepareNodeInputData,
|
||||
]);
|
||||
|
||||
const saveAgent = useCallback(async () => {
|
||||
try {
|
||||
await _saveAgent();
|
||||
} catch (error) {
|
||||
const errorMessage =
|
||||
error instanceof Error ? error.message : String(error);
|
||||
console.error("Error saving agent", error);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error saving agent",
|
||||
description: errorMessage,
|
||||
});
|
||||
},
|
||||
[saveAgent],
|
||||
);
|
||||
}
|
||||
}, [_saveAgent, toast]);
|
||||
|
||||
const requestSave = useCallback(() => {
|
||||
saveAgent();
|
||||
setSaveRunRequest({
|
||||
request: "save",
|
||||
state: "saving",
|
||||
});
|
||||
}, [saveAgent]);
|
||||
|
||||
const requestSaveAndRun = useCallback(() => {
|
||||
saveAgent();
|
||||
|
||||
@@ -104,23 +104,18 @@ export default class BaseAutoGPTServerAPI {
|
||||
return this._get(`/graphs/${id}`, query);
|
||||
}
|
||||
|
||||
|
||||
getGraphAllVersions(id: string): Promise<Graph[]> {
|
||||
return this._get(`/graphs/${id}/versions`);
|
||||
}
|
||||
|
||||
|
||||
createGraph(graphCreateBody: GraphCreatable): Promise<Graph>;
|
||||
|
||||
createGraph(
|
||||
graphID: GraphCreatable | string,
|
||||
): Promise<Graph> {
|
||||
createGraph(graphID: GraphCreatable | string): Promise<Graph> {
|
||||
let requestBody = { graph: graphID } as GraphCreateRequestBody;
|
||||
|
||||
return this._request("POST", "/graphs", requestBody);
|
||||
}
|
||||
|
||||
|
||||
updateGraph(id: string, graph: GraphUpdateable): Promise<Graph> {
|
||||
return this._request("PUT", `/graphs/${id}`, graph);
|
||||
}
|
||||
@@ -615,11 +610,11 @@ export default class BaseAutoGPTServerAPI {
|
||||
callCount == 0
|
||||
? this.sendWebSocketMessage(method, data, callCount + 1)
|
||||
: setTimeout(
|
||||
() => {
|
||||
this.sendWebSocketMessage(method, data, callCount + 1);
|
||||
},
|
||||
2 ** (callCount - 1) * 1000,
|
||||
);
|
||||
() => {
|
||||
this.sendWebSocketMessage(method, data, callCount + 1);
|
||||
},
|
||||
2 ** (callCount - 1) * 1000,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,11 +221,7 @@ export type Graph = GraphMeta & {
|
||||
|
||||
export type GraphUpdateable = Omit<
|
||||
Graph,
|
||||
| "version"
|
||||
| "is_active"
|
||||
| "links"
|
||||
| "input_schema"
|
||||
| "output_schema"
|
||||
"version" | "is_active" | "links" | "input_schema" | "output_schema"
|
||||
> & {
|
||||
version?: number;
|
||||
is_active?: boolean;
|
||||
|
||||
Reference in New Issue
Block a user