Skip to content

Commit

Permalink
feat(frontend): Add field extraction handle for block with object out…
Browse files Browse the repository at this point in the history
…put (#8900)

This addresses
#8741

We have quite a few blocks with (object) outputs. The only way to really
use these is to use a "Find In Dictionary" block to pick out that
property.

If the structure of the output object is known, we should expose the
properties of the object directly as sub-outputs. This will make a huge
difference in UX and make using these blocks much much easier.

### Changes 🏗️

Recursively flatten object fields into output node handles

<img width="637" alt="image"
src="https://github.com/user-attachments/assets/dac1f691-9866-4bb7-96b7-20fa6ddbb616">
<img width="773" alt="image"
src="https://github.com/user-attachments/assets/f8e7f97c-b245-40bd-b84f-2c044f5f9e23">


### Checklist 📋

#### For code changes:
- [ ] I have clearly listed my changes in the PR description
- [ ] I have made a test plan
- [ ] I have tested my changes according to the test plan:
  <!-- Put your test plan here: -->
  - [ ] ...

<details>
  <summary>Example test plan</summary>
  
  - [ ] Create from scratch and execute an agent with at least 3 blocks
- [ ] Import an agent from file upload, and confirm it executes
correctly
  - [ ] Upload agent to marketplace
- [ ] Import an agent from marketplace and confirm it executes correctly
  - [ ] Edit an agent from monitor, and confirm it executes correctly
</details>

#### For configuration changes:
- [ ] `.env.example` is updated or already compatible with my changes
- [ ] `docker-compose.yml` is updated or already compatible with my
changes
- [ ] I have included a list of my configuration changes in the PR
description (under **Changes**)

<details>
  <summary>Examples of configuration changes</summary>

  - Changing ports
  - Adding new services that need to communicate with each other
  - Secrets or environment variable changes
  - New or infrastructure changes such as databases
</details>

Co-authored-by: Nicholas Tindle <[email protected]>
  • Loading branch information
majdyz and ntindle authored Dec 9, 2024
1 parent e6d728b commit 79c0c31
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 12 deletions.
44 changes: 33 additions & 11 deletions autogpt_platform/frontend/src/components/CustomNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import InputModalComponent from "./InputModalComponent";
import OutputModalComponent from "./OutputModalComponent";
import {
BlockIORootSchema,
BlockIOSubSchema,
BlockIOStringSubSchema,
Category,
NodeExecutionResult,
Expand Down Expand Up @@ -167,17 +168,38 @@ export function CustomNode({
nodeType === BlockUIType.NOTE
)
return null;
const keys = Object.keys(schema.properties);
return keys.map((key) => (
<div key={key}>
<NodeHandle
keyName={key}
isConnected={isOutputHandleConnected(key)}
schema={schema.properties[key]}
side="right"
/>
</div>
));

const renderHandles = (
propSchema: { [key: string]: BlockIOSubSchema },
keyPrefix = "",
titlePrefix = "",
) => {
return Object.keys(propSchema).map((propKey) => {
const fieldSchema = propSchema[propKey];
const fieldTitle =
titlePrefix + (fieldSchema.title || beautifyString(propKey));

return (
<div key={propKey}>
<NodeHandle
title={fieldTitle}
keyName={`${keyPrefix}${propKey}`}
isConnected={isOutputHandleConnected(propKey)}
schema={fieldSchema}
side="right"
/>
{"properties" in fieldSchema &&
renderHandles(
fieldSchema.properties,
`${keyPrefix}${propKey}_#_`,
`${fieldTitle}.`,
)}
</div>
);
});
};

return renderHandles(schema.properties);
};

const generateInputHandles = (
Expand Down
4 changes: 3 additions & 1 deletion autogpt_platform/frontend/src/components/NodeHandle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type HandleProps = {
isConnected: boolean;
isRequired?: boolean;
side: "left" | "right";
title?: string;
};

const NodeHandle: FC<HandleProps> = ({
Expand All @@ -18,6 +19,7 @@ const NodeHandle: FC<HandleProps> = ({
isConnected,
isRequired,
side,
title,
}) => {
const typeName: Record<string, string> = {
string: "text",
Expand All @@ -34,7 +36,7 @@ const NodeHandle: FC<HandleProps> = ({
const label = (
<div className="flex flex-grow flex-row">
<span className="text-m green flex items-end pr-2 text-gray-900">
{schema.title || beautifyString(keyName.toLowerCase())}
{title || schema.title || beautifyString(keyName.toLowerCase())}
{isRequired ? "*" : ""}
</span>
<span className={`${typeClass} flex items-end`}>
Expand Down

0 comments on commit 79c0c31

Please sign in to comment.