Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(frontend): Broken UI caused by lack of error propagation on Run #8575

Merged
merged 1 commit into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions autogpt_platform/backend/backend/data/graph.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import asyncio
import logging
import uuid
from collections import defaultdict
from datetime import datetime, timezone
from typing import Any, Literal

Expand Down Expand Up @@ -203,15 +204,19 @@ def validate_graph(self, for_run: bool = False):
def sanitize(name):
return name.split("_#_")[0].split("_@_")[0].split("_$_")[0]

# Nodes: required fields are filled or connected, except for InputBlock.
input_links = defaultdict(list)
for link in self.links:
input_links[link.sink_id].append(link)

# Nodes: required fields are filled or connected
for node in self.nodes:
block = get_block(node.block_id)
if block is None:
raise ValueError(f"Invalid block {node.block_id} for node #{node.id}")

provided_inputs = set(
[sanitize(name) for name in node.input_default]
+ [sanitize(link.sink_name) for link in node.input_links]
+ [sanitize(link.sink_name) for link in input_links.get(node.id, [])]
)
for name in block.input_schema.get_required_fields():
if name not in provided_inputs and (
Expand Down
5 changes: 4 additions & 1 deletion autogpt_platform/frontend/src/components/CustomNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -626,10 +626,13 @@ export function CustomNode({

<div className="flex w-full flex-col">
<div className="flex flex-row items-center justify-between">
<div className="font-roboto px-3 text-lg font-semibold">
<div className="font-roboto flex items-center px-3 text-lg font-semibold">
{beautifyString(
data.blockType?.replace(/Block$/, "") || data.title,
)}
<div className="px-2 text-xs text-gray-500">
#{id.split("-")[0]}
</div>
</div>
</div>
{blockCost && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,9 +352,14 @@ const NodeKeyValueInput: FC<{
const defaultEntries = new Map(
Object.entries(entries ?? schema.default ?? {}),
);
const prefix = `${selfKey}_#_`;
connections
.filter((c) => c.targetHandle.startsWith(prefix) && c.target === nodeId)
.map((c) => c.targetHandle.slice(prefix.length))
.forEach((k) => !defaultEntries.has(k) && defaultEntries.set(k, ""));
majdyz marked this conversation as resolved.
Show resolved Hide resolved

return Array.from(defaultEntries, ([key, value]) => ({ key, value }));
}, [entries, schema.default]);
}, [entries, schema.default, connections, nodeId, selfKey]);

const [keyValuePairs, setKeyValuePairs] = useState<
{ key: string; value: string | number | null }[]
Expand Down Expand Up @@ -497,6 +502,18 @@ const NodeArrayInput: FC<{
displayName,
}) => {
entries ??= schema.default ?? [];

const prefix = `${selfKey}_$_`;
connections
.filter((c) => c.targetHandle.startsWith(prefix) && c.target === nodeId)
majdyz marked this conversation as resolved.
Show resolved Hide resolved
.map((c) => parseInt(c.targetHandle.slice(prefix.length)))
.filter((c) => !isNaN(c))
.forEach(
(c) =>
entries.length <= c &&
entries.push(...Array(c - entries.length + 1).fill("")),
);

const isItemObject = "items" in schema && "properties" in schema.items!;
const error =
typeof errors[selfKey] === "string" ? errors[selfKey] : undefined;
Expand Down
44 changes: 27 additions & 17 deletions autogpt_platform/frontend/src/hooks/useAgentGraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,16 @@ export default function useAgentGraph(
},
);
})
.catch(() => setSaveRunRequest({ request: "run", state: "error" }));
.catch((error) => {
const errorMessage =
error instanceof Error ? error.message : String(error);
toast({
variant: "destructive",
title: "Error saving agent",
description: errorMessage,
});
setSaveRunRequest({ request: "run", state: "error" });
});

processedUpdates.current = processedUpdates.current = [];
}
Expand All @@ -510,6 +519,7 @@ export default function useAgentGraph(
}
}, [
api,
toast,
saveRunRequest,
savedAgent,
nodesSyncedWithSavedAgent,
Expand Down Expand Up @@ -590,8 +600,7 @@ export default function useAgentGraph(
[availableNodes],
);

const _saveAgent = (
() =>
const _saveAgent = useCallback(
async (asTemplate: boolean = false) => {
//FIXME frontend ids should be resolved better (e.g. returned from the server)
// currently this relays on block_id and position
Expand Down Expand Up @@ -745,8 +754,20 @@ export default function useAgentGraph(
},
}));
});
}
)();
},
[
api,
nodes,
edges,
pathname,
router,
searchParams,
savedAgent,
agentName,
agentDescription,
prepareNodeInputData,
],
);

const saveAgent = useCallback(
async (asTemplate: boolean = false) => {
Expand All @@ -763,18 +784,7 @@ export default function useAgentGraph(
});
}
},
[
api,
nodes,
edges,
pathname,
router,
searchParams,
savedAgent,
agentName,
agentDescription,
prepareNodeInputData,
],
[_saveAgent, toast],
);

const requestSave = useCallback(
Expand Down
Loading