mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-30 03:00:41 -04:00
refactor(backend): Clean up Library & Store DB schema (#9774)
Distilled from #9541 to reduce the scope of that PR. - Part of #9307 - ❗ Blocks #9786 - ❗ Blocks #9541 ### Changes 🏗️ - Fix `LibraryAgent` schema (for #9786) - Fix relationships between `LibraryAgent`, `AgentGraph`, and `AgentPreset` - Impose uniqueness constraint on `LibraryAgent` - Rename things that are called `agent` that actually refer to a `graph`/`agentGraph` - Fix singular/plural forms in DB schema - Simplify reference names of closely related objects (e.g. `AgentGraph.AgentGraphExecutions` -> `AgentGraph.Executions`) - Eliminate use of `# type: ignore` in DB statements - Add `typed` and `typed_cast` utilities to `backend.util.type` ### Checklist 📋 #### For code changes: - [x] I have clearly listed my changes in the PR description - [x] I have made a test plan - [x] I have tested my changes according to the test plan: - [x] CI static type checking (with all risky `# type: ignore` removed) - [x] Check that column references in views are updated
This commit is contained in:
committed by
GitHub
parent
70890dee43
commit
353396110c
@@ -82,16 +82,16 @@ export default function AgentRunsPage(): React.ReactElement {
|
||||
api.getLibraryAgent(agentID).then((agent) => {
|
||||
setAgent(agent);
|
||||
|
||||
getGraphVersion(agent.agent_id, agent.agent_version).then(
|
||||
getGraphVersion(agent.graph_id, agent.graph_version).then(
|
||||
(_graph) =>
|
||||
(graph && graph.version == _graph.version) || setGraph(_graph),
|
||||
);
|
||||
api.getGraphExecutions(agent.agent_id).then((agentRuns) => {
|
||||
api.getGraphExecutions(agent.graph_id).then((agentRuns) => {
|
||||
setAgentRuns(agentRuns);
|
||||
|
||||
// Preload the corresponding graph versions
|
||||
new Set(agentRuns.map((run) => run.graph_version)).forEach((version) =>
|
||||
getGraphVersion(agent.agent_id, version),
|
||||
getGraphVersion(agent.graph_id, version),
|
||||
);
|
||||
|
||||
if (!selectedView.id && isFirstLoad && agentRuns.length > 0) {
|
||||
@@ -109,7 +109,7 @@ export default function AgentRunsPage(): React.ReactElement {
|
||||
});
|
||||
if (selectedView.type == "run" && selectedView.id && agent) {
|
||||
api
|
||||
.getGraphExecutionInfo(agent.agent_id, selectedView.id)
|
||||
.getGraphExecutionInfo(agent.graph_id, selectedView.id)
|
||||
.then(setSelectedRun);
|
||||
}
|
||||
}, [api, agentID, getGraphVersion, graph, selectedView, isFirstLoad, agent]);
|
||||
@@ -123,7 +123,7 @@ export default function AgentRunsPage(): React.ReactElement {
|
||||
if (!agent) return;
|
||||
|
||||
// Subscribe to all executions for this agent
|
||||
api.subscribeToGraphExecutions(agent.agent_id);
|
||||
api.subscribeToGraphExecutions(agent.graph_id);
|
||||
}, [api, agent]);
|
||||
|
||||
// Handle execution updates
|
||||
@@ -162,7 +162,7 @@ export default function AgentRunsPage(): React.ReactElement {
|
||||
|
||||
// Ensure corresponding graph version is available before rendering I/O
|
||||
api
|
||||
.getGraphExecutionInfo(agent.agent_id, selectedView.id)
|
||||
.getGraphExecutionInfo(agent.graph_id, selectedView.id)
|
||||
.then(async (run) => {
|
||||
await getGraphVersion(run.graph_id, run.graph_version);
|
||||
setSelectedRun(run);
|
||||
@@ -175,7 +175,7 @@ export default function AgentRunsPage(): React.ReactElement {
|
||||
|
||||
// TODO: filter in backend - https://github.com/Significant-Gravitas/AutoGPT/issues/9183
|
||||
setSchedules(
|
||||
(await api.listSchedules()).filter((s) => s.graph_id == agent.agent_id),
|
||||
(await api.listSchedules()).filter((s) => s.graph_id == agent.graph_id),
|
||||
);
|
||||
}, [api, agent]);
|
||||
|
||||
@@ -214,7 +214,7 @@ export default function AgentRunsPage(): React.ReactElement {
|
||||
agent &&
|
||||
// Export sanitized graph from backend
|
||||
api
|
||||
.getGraph(agent.agent_id, agent.agent_version, true)
|
||||
.getGraph(agent.graph_id, agent.graph_version, true)
|
||||
.then((graph) =>
|
||||
exportAsJSONFile(graph, `${graph.name}_v${graph.version}.json`),
|
||||
),
|
||||
@@ -227,7 +227,7 @@ export default function AgentRunsPage(): React.ReactElement {
|
||||
? [
|
||||
{
|
||||
label: "Open graph in builder",
|
||||
href: `/build?flowID=${agent.agent_id}&flowVersion=${agent.agent_version}`,
|
||||
href: `/build?flowID=${agent.graph_id}&flowVersion=${agent.graph_version}`,
|
||||
},
|
||||
{ label: "Export agent to file", callback: downloadGraph },
|
||||
]
|
||||
|
||||
@@ -98,7 +98,7 @@ const Monitor = () => {
|
||||
flows={flows}
|
||||
executions={[
|
||||
...(selectedFlow
|
||||
? executions.filter((v) => v.graph_id == selectedFlow.agent_id)
|
||||
? executions.filter((v) => v.graph_id == selectedFlow.graph_id)
|
||||
: executions),
|
||||
].sort((a, b) => b.started_at.getTime() - a.started_at.getTime())}
|
||||
selectedRun={selectedRun}
|
||||
@@ -108,7 +108,7 @@ const Monitor = () => {
|
||||
<FlowRunInfo
|
||||
agent={
|
||||
selectedFlow ||
|
||||
flows.find((f) => f.agent_id == selectedRun.graph_id)!
|
||||
flows.find((f) => f.graph_id == selectedRun.graph_id)!
|
||||
}
|
||||
execution={selectedRun}
|
||||
className={column3}
|
||||
@@ -118,7 +118,7 @@ const Monitor = () => {
|
||||
<FlowInfo
|
||||
flow={selectedFlow}
|
||||
executions={executions.filter(
|
||||
(e) => e.graph_id == selectedFlow.agent_id,
|
||||
(e) => e.graph_id == selectedFlow.graph_id,
|
||||
)}
|
||||
className={column3}
|
||||
refresh={() => {
|
||||
|
||||
@@ -84,7 +84,7 @@ export default function AgentRunsSelectorList({
|
||||
>
|
||||
<span>Scheduled</span>
|
||||
<span className="text-neutral-600">
|
||||
{schedules.filter((s) => s.graph_id === agent.agent_id).length}
|
||||
{schedules.filter((s) => s.graph_id === agent.graph_id).length}
|
||||
</span>
|
||||
</Badge>
|
||||
</div>
|
||||
@@ -127,7 +127,7 @@ export default function AgentRunsSelectorList({
|
||||
/>
|
||||
))
|
||||
: schedules
|
||||
.filter((schedule) => schedule.graph_id === agent.agent_id)
|
||||
.filter((schedule) => schedule.graph_id === agent.graph_id)
|
||||
.map((schedule) => (
|
||||
<AgentRunSummaryCard
|
||||
className="h-28 w-72 lg:h-32 xl:w-80"
|
||||
|
||||
@@ -8,7 +8,7 @@ export default function LibraryAgentCard({
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
agent_id,
|
||||
graph_id: agent_id,
|
||||
can_access_graph,
|
||||
creator_image_url,
|
||||
image_url,
|
||||
|
||||
@@ -109,7 +109,7 @@ export const AgentFlowList = ({
|
||||
lastRun: GraphExecutionMeta | null = null;
|
||||
if (executions) {
|
||||
const _flowRuns = executions.filter(
|
||||
(r) => r.graph_id == flow.agent_id,
|
||||
(r) => r.graph_id == flow.graph_id,
|
||||
);
|
||||
runCount = _flowRuns.length;
|
||||
lastRun =
|
||||
|
||||
@@ -49,7 +49,7 @@ export const FlowInfo: React.FC<
|
||||
}
|
||||
> = ({ flow, executions, flowVersion, refresh, ...props }) => {
|
||||
const { requestSaveAndRun, requestStopRun, isRunning, nodes, setNodes } =
|
||||
useAgentGraph(flow.agent_id, flow.agent_version, undefined, false);
|
||||
useAgentGraph(flow.graph_id, flow.graph_version, undefined, false);
|
||||
|
||||
const api = useBackendAPI();
|
||||
const { toast } = useToast();
|
||||
@@ -61,7 +61,7 @@ export const FlowInfo: React.FC<
|
||||
const selectedFlowVersion: Graph | undefined = flowVersions?.find(
|
||||
(v) =>
|
||||
v.version ==
|
||||
(selectedVersion == "all" ? flow.agent_version : selectedVersion),
|
||||
(selectedVersion == "all" ? flow.graph_version : selectedVersion),
|
||||
);
|
||||
|
||||
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||
@@ -110,9 +110,9 @@ export const FlowInfo: React.FC<
|
||||
|
||||
useEffect(() => {
|
||||
api
|
||||
.getGraphAllVersions(flow.agent_id)
|
||||
.getGraphAllVersions(flow.graph_id)
|
||||
.then((result) => setFlowVersions(result));
|
||||
}, [flow.agent_id, api]);
|
||||
}, [flow.graph_id, api]);
|
||||
|
||||
const openRunnerInput = () => setIsRunnerInputOpen(true);
|
||||
|
||||
@@ -152,7 +152,7 @@ export const FlowInfo: React.FC<
|
||||
<Card {...props}>
|
||||
<CardHeader className="">
|
||||
<CardTitle>
|
||||
{flow.name} <span className="font-light">v{flow.agent_version}</span>
|
||||
{flow.name} <span className="font-light">v{flow.graph_version}</span>
|
||||
</CardTitle>
|
||||
<div className="flex flex-col space-y-2 py-6">
|
||||
{(flowVersions?.length ?? 0) > 1 && (
|
||||
@@ -195,7 +195,7 @@ export const FlowInfo: React.FC<
|
||||
{flow.can_access_graph && (
|
||||
<Link
|
||||
className={buttonVariants({ variant: "default" })}
|
||||
href={`/build?flowID=${flow.agent_id}&flowVersion=${flow.agent_version}`}
|
||||
href={`/build?flowID=${flow.graph_id}&flowVersion=${flow.graph_version}`}
|
||||
>
|
||||
<Pencil2Icon className="mr-2" />
|
||||
Open in Builder
|
||||
@@ -209,7 +209,7 @@ export const FlowInfo: React.FC<
|
||||
data-testid="export-button"
|
||||
onClick={() =>
|
||||
api
|
||||
.getGraph(flow.agent_id, selectedFlowVersion!.version, true)
|
||||
.getGraph(flow.graph_id, selectedFlowVersion!.version, true)
|
||||
.then((graph) =>
|
||||
exportAsJSONFile(
|
||||
graph,
|
||||
@@ -248,7 +248,7 @@ export const FlowInfo: React.FC<
|
||||
flows={[flow]}
|
||||
executions={executions.filter(
|
||||
(execution) =>
|
||||
execution.graph_id == flow.agent_id &&
|
||||
execution.graph_id == flow.graph_id &&
|
||||
(selectedVersion == "all" ||
|
||||
execution.graph_version == selectedVersion),
|
||||
)}
|
||||
|
||||
@@ -26,9 +26,9 @@ export const FlowRunInfo: React.FC<
|
||||
const api = useBackendAPI();
|
||||
|
||||
const fetchBlockResults = useCallback(async () => {
|
||||
const graph = await api.getGraph(agent.agent_id, agent.agent_version);
|
||||
const graph = await api.getGraph(agent.graph_id, agent.graph_version);
|
||||
const graphExecution = await api.getGraphExecutionInfo(
|
||||
agent.agent_id,
|
||||
agent.graph_id,
|
||||
execution.id,
|
||||
);
|
||||
|
||||
@@ -49,7 +49,7 @@ export const FlowRunInfo: React.FC<
|
||||
),
|
||||
),
|
||||
);
|
||||
}, [api, agent.agent_id, agent.agent_version, execution.id]);
|
||||
}, [api, agent.graph_id, agent.graph_version, execution.id]);
|
||||
|
||||
// Fetch graph and execution data
|
||||
useEffect(() => {
|
||||
@@ -57,15 +57,15 @@ export const FlowRunInfo: React.FC<
|
||||
fetchBlockResults();
|
||||
}, [isOutputOpen, fetchBlockResults]);
|
||||
|
||||
if (execution.graph_id != agent.agent_id) {
|
||||
if (execution.graph_id != agent.graph_id) {
|
||||
throw new Error(
|
||||
`FlowRunInfo can't be used with non-matching execution.graph_id and flow.id`,
|
||||
);
|
||||
}
|
||||
|
||||
const handleStopRun = useCallback(() => {
|
||||
api.stopGraphExecution(agent.agent_id, execution.id);
|
||||
}, [api, agent.agent_id, execution.id]);
|
||||
api.stopGraphExecution(agent.graph_id, execution.id);
|
||||
}, [api, agent.graph_id, execution.id]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -98,7 +98,7 @@ export const FlowRunInfo: React.FC<
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="hidden">
|
||||
<strong>Agent ID:</strong> <code>{agent.agent_id}</code>
|
||||
<strong>Agent ID:</strong> <code>{agent.graph_id}</code>
|
||||
</p>
|
||||
<p className="hidden">
|
||||
<strong>Run ID:</strong> <code>{execution.id}</code>
|
||||
|
||||
@@ -48,7 +48,7 @@ export const FlowRunsList: React.FC<{
|
||||
<TableCell>
|
||||
<TextRenderer
|
||||
value={
|
||||
flows.find((f) => f.agent_id == execution.graph_id)?.name
|
||||
flows.find((f) => f.graph_id == execution.graph_id)?.name
|
||||
}
|
||||
truncateLengthLimit={30}
|
||||
/>
|
||||
|
||||
@@ -64,7 +64,7 @@ export const FlowRunsTimeline = ({
|
||||
time: number;
|
||||
_duration: number;
|
||||
} = payload[0].payload;
|
||||
const flow = flows.find((f) => f.agent_id === data.graph_id);
|
||||
const flow = flows.find((f) => f.graph_id === data.graph_id);
|
||||
return (
|
||||
<Card className="p-2 text-xs leading-normal">
|
||||
<p>
|
||||
@@ -98,7 +98,7 @@ export const FlowRunsTimeline = ({
|
||||
<Scatter
|
||||
key={flow.id}
|
||||
data={executions
|
||||
.filter((e) => e.graph_id == flow.agent_id)
|
||||
.filter((e) => e.graph_id == flow.graph_id)
|
||||
.map((e) => ({
|
||||
...e,
|
||||
time:
|
||||
|
||||
@@ -90,8 +90,8 @@ export const SchedulesTable = ({
|
||||
const handleAgentSelect = (agentId: string) => {
|
||||
setSelectedAgent(agentId);
|
||||
const agent = agents.find((a) => a.id === agentId);
|
||||
setMaxVersion(agent!.agent_version);
|
||||
setSelectedVersion(agent!.agent_version);
|
||||
setMaxVersion(agent!.graph_version);
|
||||
setSelectedVersion(agent!.graph_version);
|
||||
};
|
||||
|
||||
const handleVersionSelect = (version: string) => {
|
||||
@@ -120,7 +120,7 @@ export const SchedulesTable = ({
|
||||
try {
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
router.push(
|
||||
`/build?flowID=${agent.agent_id}&flowVersion=${agent.agent_version}&open_scheduling=true`,
|
||||
`/build?flowID=${agent.graph_id}&flowVersion=${agent.graph_version}&open_scheduling=true`,
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Navigation error:", error);
|
||||
@@ -184,7 +184,7 @@ export const SchedulesTable = ({
|
||||
</SelectTrigger>
|
||||
<SelectContent className="text-xs">
|
||||
{agents.map((agent) => (
|
||||
<SelectItem key={agent.id} value={agent.agent_id}>
|
||||
<SelectItem key={agent.id} value={agent.graph_id}>
|
||||
{agent.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
@@ -237,7 +237,7 @@ export const SchedulesTable = ({
|
||||
filteredAndSortedSchedules.map((schedule) => (
|
||||
<TableRow key={schedule.id}>
|
||||
<TableCell className="font-medium">
|
||||
{agents.find((a) => a.agent_id === schedule.graph_id)
|
||||
{agents.find((a) => a.graph_id === schedule.graph_id)
|
||||
?.name || schedule.graph_id}
|
||||
</TableCell>
|
||||
<TableCell>{schedule.graph_version}</TableCell>
|
||||
|
||||
@@ -356,8 +356,8 @@ export type NodeExecutionResult = {
|
||||
/* Mirror of backend/server/v2/library/model.py:LibraryAgent */
|
||||
export type LibraryAgent = {
|
||||
id: LibraryAgentID;
|
||||
agent_id: GraphID;
|
||||
agent_version: number;
|
||||
graph_id: GraphID;
|
||||
graph_version: number;
|
||||
image_url?: string;
|
||||
creator_name: string;
|
||||
creator_image_url: string;
|
||||
@@ -393,8 +393,8 @@ export interface LibraryAgentResponse {
|
||||
export interface LibraryAgentPreset {
|
||||
id: string;
|
||||
updated_at: Date;
|
||||
agent_id: string;
|
||||
agent_version: number;
|
||||
graph_id: GraphID;
|
||||
graph_version: number;
|
||||
name: string;
|
||||
description: string;
|
||||
is_active: boolean;
|
||||
@@ -414,8 +414,8 @@ export interface CreateLibraryAgentPresetRequest {
|
||||
name: string;
|
||||
description: string;
|
||||
inputs: { [key: string]: any };
|
||||
agent_id: string;
|
||||
agent_version: number;
|
||||
graph_id: GraphID;
|
||||
graph_version: number;
|
||||
is_active: boolean;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user