mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
fix(builder/monitor): Fix Graph export (#7556)
- fix(builder/monitor): Export `Graph` rather than `GraphMeta` - Fixes #7557 - refactor(builder): Split up `lib/autogpt_server_api` into multi-file module - Resolves #7555 - Rename `lib/autogpt_server_api` to `lib/autogpt-server-api` - Split up `lib/autogpt-server-api` into `/client`, `/types` - Move `ObjectSchema` from `lib/types` to `lib/autogpt-server-api/types` - Make definition of `Node['metadata']['position']` independent of `reactflow.XYPosition` - fix(builder/monitor): Strip secrets from graph on export - Resolves #7492 - Add `safeCopyGraph` function in `lib/autogpt-server-api/utils` - Use `safeCopyGraph` to strip secrets from graph on export in `/monitor` > `FlowInfo`
This commit is contained in:
committed by
GitHub
parent
d407fd101e
commit
ab0df04bfe
@@ -23,8 +23,13 @@ import {
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu"
|
||||
import AutoGPTServerAPI, {
|
||||
Graph,
|
||||
GraphMeta,
|
||||
NodeExecutionResult,
|
||||
safeCopyGraph,
|
||||
} from '@/lib/autogpt-server-api';
|
||||
import { ChevronDownIcon, ClockIcon, EnterIcon, ExitIcon, Pencil2Icon } from '@radix-ui/react-icons';
|
||||
import AutoGPTServerAPI, { GraphMeta, NodeExecutionResult } from '@/lib/autogpt_server_api';
|
||||
import { cn, exportAsJSONFile, hashString } from '@/lib/utils';
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button, buttonVariants } from "@/components/ui/button";
|
||||
@@ -400,8 +405,11 @@ const FlowInfo: React.FC<React.HTMLAttributes<HTMLDivElement> & {
|
||||
}> = ({ flow, flowRuns, flowVersion, ...props }) => {
|
||||
const api = new AutoGPTServerAPI();
|
||||
|
||||
const [flowVersions, setFlowVersions] = useState<GraphMeta[] | null>(null);
|
||||
const [flowVersions, setFlowVersions] = useState<Graph[] | null>(null);
|
||||
const [selectedVersion, setSelectedFlowVersion] = useState(flowVersion ?? "all");
|
||||
const selectedFlowVersion: Graph | undefined = flowVersions?.find(v => (
|
||||
v.version == (selectedVersion == "all" ? flow.version : selectedVersion)
|
||||
));
|
||||
|
||||
useEffect(() => {
|
||||
api.getGraphAllVersions(flow.id).then(result => setFlowVersions(result));
|
||||
@@ -449,7 +457,13 @@ const FlowInfo: React.FC<React.HTMLAttributes<HTMLDivElement> & {
|
||||
variant="outline"
|
||||
className="px-2.5"
|
||||
title="Export to a JSON-file"
|
||||
onClick={() => exportAsJSONFile(flow, `${flow.name}_v${flow.version}.json`)}
|
||||
onClick={async () => exportAsJSONFile(
|
||||
safeCopyGraph(
|
||||
flowVersions!.find(v => v.version == selectedFlowVersion!.version)!,
|
||||
await api.getBlocks(),
|
||||
),
|
||||
`${flow.name}_v${selectedFlowVersion!.version}.json`
|
||||
)}
|
||||
>
|
||||
<ExitIcon />
|
||||
</Button>
|
||||
@@ -457,11 +471,7 @@ const FlowInfo: React.FC<React.HTMLAttributes<HTMLDivElement> & {
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<FlowRunsStats
|
||||
flows={[
|
||||
selectedVersion != "all"
|
||||
? flowVersions?.find(v => v.version == selectedVersion)!
|
||||
: flow
|
||||
]}
|
||||
flows={[selectedFlowVersion ?? flow]}
|
||||
flowRuns={flowRuns.filter(r =>
|
||||
r.graphID == flow.id
|
||||
&& (selectedVersion == "all" || r.graphVersion == selectedVersion)
|
||||
|
||||
@@ -15,8 +15,7 @@ import ReactFlow, {
|
||||
import 'reactflow/dist/style.css';
|
||||
import CustomNode from './CustomNode';
|
||||
import './flow.css';
|
||||
import AutoGPTServerAPI, { Block, Graph } from '@/lib/autogpt_server_api';
|
||||
import { ObjectSchema } from '@/lib/types';
|
||||
import AutoGPTServerAPI, { Block, Graph, ObjectSchema } from '@/lib/autogpt-server-api';
|
||||
import { Button } from './ui/button';
|
||||
import { Input } from './ui/input';
|
||||
import { ChevronRight, ChevronLeft } from "lucide-react";
|
||||
|
||||
@@ -14,7 +14,7 @@ import { Input } from "@/components/ui/input"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Switch } from "@/components/ui/switch"
|
||||
import { Textarea } from "@/components/ui/textarea"
|
||||
import AutoGPTServerAPI, { Graph, GraphCreatable } from "@/lib/autogpt_server_api"
|
||||
import AutoGPTServerAPI, { Graph, GraphCreatable } from "@/lib/autogpt-server-api"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { EnterIcon } from "@radix-ui/react-icons"
|
||||
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
import { XYPosition } from "reactflow";
|
||||
import { ObjectSchema } from "./types";
|
||||
import {
|
||||
Block,
|
||||
Graph,
|
||||
GraphCreatable,
|
||||
GraphUpdateable,
|
||||
GraphMeta,
|
||||
GraphExecuteResponse,
|
||||
NodeExecutionResult,
|
||||
} from "./types"
|
||||
|
||||
export default class AutoGPTServerAPI {
|
||||
private baseUrl: string;
|
||||
@@ -196,96 +203,12 @@ export default class AutoGPTServerAPI {
|
||||
}
|
||||
}
|
||||
|
||||
/* Mirror of autogpt_server/data/block.py:Block */
|
||||
export type Block = {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: ObjectSchema;
|
||||
outputSchema: ObjectSchema;
|
||||
};
|
||||
|
||||
/* Mirror of autogpt_server/data/graph.py:Node */
|
||||
export type Node = {
|
||||
id: string;
|
||||
block_id: string;
|
||||
input_default: { [key: string]: any };
|
||||
input_nodes: Array<{ name: string, node_id: string }>;
|
||||
output_nodes: Array<{ name: string, node_id: string }>;
|
||||
metadata: {
|
||||
position: XYPosition;
|
||||
[key: string]: any;
|
||||
};
|
||||
};
|
||||
/* *** UTILITY TYPES *** */
|
||||
|
||||
/* Mirror of autogpt_server/data/graph.py:Link */
|
||||
export type Link = {
|
||||
id: string;
|
||||
source_id: string;
|
||||
sink_id: string;
|
||||
source_name: string;
|
||||
sink_name: string;
|
||||
}
|
||||
|
||||
export type LinkCreatable = Omit<Link, "id"> & {
|
||||
id?: string;
|
||||
}
|
||||
|
||||
/* Mirror of autogpt_server/data/graph.py:GraphMeta */
|
||||
export type GraphMeta = {
|
||||
id: string;
|
||||
version: number;
|
||||
is_active: boolean;
|
||||
is_template: boolean;
|
||||
name: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
/* Mirror of autogpt_server/data/graph.py:Graph */
|
||||
export type Graph = GraphMeta & {
|
||||
nodes: Array<Node>;
|
||||
links: Array<Link>;
|
||||
};
|
||||
|
||||
export type GraphUpdateable = Omit<
|
||||
Graph,
|
||||
"version" | "is_active" | "is_template" | "links"
|
||||
> & {
|
||||
version?: number;
|
||||
is_active?: boolean;
|
||||
is_template?: boolean;
|
||||
links: Array<LinkCreatable>;
|
||||
}
|
||||
|
||||
export type GraphCreatable = Omit<GraphUpdateable, "id"> & { id?: string }
|
||||
|
||||
export type GraphCreateRequestBody = {
|
||||
type GraphCreateRequestBody = {
|
||||
template_id: string;
|
||||
template_version: number;
|
||||
} | {
|
||||
graph: GraphCreatable;
|
||||
}
|
||||
|
||||
/* Derived from autogpt_server/executor/manager.py:ExecutionManager.add_execution */
|
||||
export type GraphExecuteResponse = {
|
||||
/* ID of the initiated run */
|
||||
id: string;
|
||||
/* List of node executions */
|
||||
executions: Array<{ id: string, node_id: string }>;
|
||||
};
|
||||
|
||||
/* Mirror of autogpt_server/data/execution.py:ExecutionResult */
|
||||
export type NodeExecutionResult = {
|
||||
graph_exec_id: string;
|
||||
node_exec_id: string;
|
||||
graph_id: string;
|
||||
graph_version: number;
|
||||
node_id: string;
|
||||
status: 'INCOMPLETE' | 'QUEUED' | 'RUNNING' | 'COMPLETED' | 'FAILED';
|
||||
input_data: { [key: string]: any };
|
||||
output_data: { [key: string]: Array<any> };
|
||||
add_time: Date;
|
||||
queue_time?: Date;
|
||||
start_time?: Date;
|
||||
end_time?: Date;
|
||||
};
|
||||
5
rnd/autogpt_builder/src/lib/autogpt-server-api/index.ts
Normal file
5
rnd/autogpt_builder/src/lib/autogpt-server-api/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import AutoGPTServerAPI from "./client";
|
||||
|
||||
export default AutoGPTServerAPI;
|
||||
export * from "./types";
|
||||
export * from "./utils";
|
||||
93
rnd/autogpt_builder/src/lib/autogpt-server-api/types.ts
Normal file
93
rnd/autogpt_builder/src/lib/autogpt-server-api/types.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
/* Mirror of autogpt_server/data/block.py:Block */
|
||||
export type Block = {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: ObjectSchema;
|
||||
outputSchema: ObjectSchema;
|
||||
};
|
||||
|
||||
export type ObjectSchema = {
|
||||
type: string;
|
||||
properties: { [key: string]: any };
|
||||
additionalProperties?: { type: string };
|
||||
required?: string[];
|
||||
};
|
||||
|
||||
/* Mirror of autogpt_server/data/graph.py:Node */
|
||||
export type Node = {
|
||||
id: string;
|
||||
block_id: string;
|
||||
input_default: { [key: string]: any };
|
||||
input_nodes: Array<{ name: string, node_id: string }>;
|
||||
output_nodes: Array<{ name: string, node_id: string }>;
|
||||
metadata: {
|
||||
position: { x: number; y: number; };
|
||||
[key: string]: any;
|
||||
};
|
||||
};
|
||||
|
||||
/* Mirror of autogpt_server/data/graph.py:Link */
|
||||
export type Link = {
|
||||
id: string;
|
||||
source_id: string;
|
||||
sink_id: string;
|
||||
source_name: string;
|
||||
sink_name: string;
|
||||
}
|
||||
|
||||
export type LinkCreatable = Omit<Link, "id"> & {
|
||||
id?: string;
|
||||
}
|
||||
|
||||
/* Mirror of autogpt_server/data/graph.py:GraphMeta */
|
||||
export type GraphMeta = {
|
||||
id: string;
|
||||
version: number;
|
||||
is_active: boolean;
|
||||
is_template: boolean;
|
||||
name: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
/* Mirror of autogpt_server/data/graph.py:Graph */
|
||||
export type Graph = GraphMeta & {
|
||||
nodes: Array<Node>;
|
||||
links: Array<Link>;
|
||||
};
|
||||
|
||||
export type GraphUpdateable = Omit<
|
||||
Graph,
|
||||
"version" | "is_active" | "is_template" | "links"
|
||||
> & {
|
||||
version?: number;
|
||||
is_active?: boolean;
|
||||
is_template?: boolean;
|
||||
links: Array<LinkCreatable>;
|
||||
}
|
||||
|
||||
export type GraphCreatable = Omit<GraphUpdateable, "id"> & { id?: string }
|
||||
|
||||
/* Derived from autogpt_server/executor/manager.py:ExecutionManager.add_execution */
|
||||
export type GraphExecuteResponse = {
|
||||
/** ID of the initiated run */
|
||||
id: string;
|
||||
/** List of node executions */
|
||||
executions: Array<{ id: string, node_id: string }>;
|
||||
};
|
||||
|
||||
/* Mirror of autogpt_server/data/execution.py:ExecutionResult */
|
||||
export type NodeExecutionResult = {
|
||||
graph_exec_id: string;
|
||||
node_exec_id: string;
|
||||
graph_id: string;
|
||||
graph_version: number;
|
||||
node_id: string;
|
||||
status: 'INCOMPLETE' | 'QUEUED' | 'RUNNING' | 'COMPLETED' | 'FAILED';
|
||||
input_data: { [key: string]: any };
|
||||
output_data: { [key: string]: Array<any> };
|
||||
add_time: Date;
|
||||
queue_time?: Date;
|
||||
start_time?: Date;
|
||||
end_time?: Date;
|
||||
};
|
||||
20
rnd/autogpt_builder/src/lib/autogpt-server-api/utils.ts
Normal file
20
rnd/autogpt_builder/src/lib/autogpt-server-api/utils.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Graph, Block, Node } from "./types";
|
||||
|
||||
/** Creates a copy of the graph with all secrets removed */
|
||||
export function safeCopyGraph(graph: Graph, block_defs: Block[]): Graph {
|
||||
return {
|
||||
...graph,
|
||||
nodes: graph.nodes.map(node => {
|
||||
const block = block_defs.find(b => b.id == node.block_id)!;
|
||||
return {
|
||||
...node,
|
||||
input_default: Object.keys(node.input_default)
|
||||
.filter(k => !block.inputSchema.properties[k].secret)
|
||||
.reduce((obj: Node['input_default'], key) => {
|
||||
obj[key] = node.input_default[key];
|
||||
return obj;
|
||||
}, {}),
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,3 @@
|
||||
export type ObjectSchema = {
|
||||
type: string;
|
||||
properties: { [key: string]: any };
|
||||
additionalProperties?: { type: string };
|
||||
required?: string[];
|
||||
};
|
||||
|
||||
export type BlockSchema = {
|
||||
type: string;
|
||||
properties: { [key: string]: any };
|
||||
|
||||
Reference in New Issue
Block a user