Compare commits

...

2 Commits

Author SHA1 Message Date
Zamil Majdy
ec7470a8c7 fix(platform): Fix timer & step-through block 2024-10-24 15:22:14 +07:00
Zamil Majdy
8ac0c04beb fix(platform): Fix timer & step-through block 2024-10-24 15:17:53 +07:00
5 changed files with 52 additions and 27 deletions

View File

@@ -2,13 +2,28 @@ from typing import Any
from backend.data.block import Block, BlockCategory, BlockOutput, BlockSchema from backend.data.block import Block, BlockCategory, BlockOutput, BlockSchema
from backend.data.model import SchemaField from backend.data.model import SchemaField
from backend.util.json import json
class StepThroughItemsBlock(Block): class StepThroughItemsBlock(Block):
class Input(BlockSchema): class Input(BlockSchema):
items: list | dict = SchemaField( items: list = SchemaField(
advanced=False,
description="The list or dictionary of items to iterate over", description="The list or dictionary of items to iterate over",
placeholder="[1, 2, 3, 4, 5] or {'key1': 'value1', 'key2': 'value2'}", placeholder="[1, 2, 3, 4, 5] or {'key1': 'value1', 'key2': 'value2'}",
default=[],
)
items_object: dict = SchemaField(
advanced=False,
description="The list or dictionary of items to iterate over",
placeholder="[1, 2, 3, 4, 5] or {'key1': 'value1', 'key2': 'value2'}",
default={},
)
items_str: str = SchemaField(
advanced=False,
description="The list or dictionary of items to iterate over",
placeholder="[1, 2, 3, 4, 5] or {'key1': 'value1', 'key2': 'value2'}",
default="",
) )
class Output(BlockSchema): class Output(BlockSchema):
@@ -39,14 +54,20 @@ class StepThroughItemsBlock(Block):
) )
def run(self, input_data: Input, **kwargs) -> BlockOutput: def run(self, input_data: Input, **kwargs) -> BlockOutput:
items = input_data.items for data in [input_data.items, input_data.items_object, input_data.items_str]:
if isinstance(items, dict): if not data:
# If items is a dictionary, iterate over its values continue
for item in items.values(): if isinstance(data, str):
yield "item", item items = json.loads(data)
yield "key", item else:
else: items = data
# If items is a list, iterate over the list if isinstance(items, dict):
for index, item in enumerate(items): # If items is a dictionary, iterate over its values
yield "item", item for item in items.values():
yield "key", index yield "item", item
yield "key", item
else:
# If items is a list, iterate over the list
for index, item in enumerate(items):
yield "item", item
yield "key", index

View File

@@ -139,23 +139,26 @@ class GetCurrentDateAndTimeBlock(Block):
class CountdownTimerBlock(Block): class CountdownTimerBlock(Block):
class Input(BlockSchema): class Input(BlockSchema):
input_message: Any = SchemaField( input_data: Any = SchemaField(
advanced=False,
description="Message to output after the timer finishes", description="Message to output after the timer finishes",
default="timer finished", default="timer finished",
) )
seconds: Union[int, str] = SchemaField( seconds: Union[int, str] = SchemaField(
description="Duration in seconds", default=0 advanced=False, description="Duration in seconds", default=0
) )
minutes: Union[int, str] = SchemaField( minutes: Union[int, str] = SchemaField(
description="Duration in minutes", default=0 advanced=False, description="Duration in minutes", default=0
)
hours: Union[int, str] = SchemaField(
advanced=False, description="Duration in hours", default=0
)
days: Union[int, str] = SchemaField(
advanced=False, description="Duration in days", default=0
) )
hours: Union[int, str] = SchemaField(description="Duration in hours", default=0)
days: Union[int, str] = SchemaField(description="Duration in days", default=0)
class Output(BlockSchema): class Output(BlockSchema):
output_message: str = SchemaField( output_data: Any = SchemaField(description="Message after the timer finishes")
description="Message after the timer finishes"
)
def __init__(self): def __init__(self):
super().__init__( super().__init__(
@@ -166,11 +169,11 @@ class CountdownTimerBlock(Block):
output_schema=CountdownTimerBlock.Output, output_schema=CountdownTimerBlock.Output,
test_input=[ test_input=[
{"seconds": 1}, {"seconds": 1},
{"input_message": "Custom message"}, {"input_data": "Custom message"},
], ],
test_output=[ test_output=[
("output_message", "timer finished"), ("output_data", "timer finished"),
("output_message", "Custom message"), ("output_data", "Custom message"),
], ],
) )
@@ -183,4 +186,4 @@ class CountdownTimerBlock(Block):
total_seconds = seconds + minutes * 60 + hours * 3600 + days * 86400 total_seconds = seconds + minutes * 60 + hours * 3600 + days * 86400
time.sleep(total_seconds) time.sleep(total_seconds)
yield "output_message", input_data.input_message yield "output_data", input_data.input_data

View File

@@ -148,7 +148,7 @@ def execute_node(
input_data_str = json.dumps(input_data) input_data_str = json.dumps(input_data)
input_size = len(input_data_str) input_size = len(input_data_str)
log_metadata.info("Executed node with input", input=input_data_str) log_metadata.info("Executed node with input", input=input_data_str)
update_execution(ExecutionStatus.RUNNING) exec_res = update_execution(ExecutionStatus.RUNNING)
extra_exec_kwargs = {} extra_exec_kwargs = {}
# Last-minute fetch credentials + acquire a system-wide read-write lock to prevent # Last-minute fetch credentials + acquire a system-wide read-write lock to prevent
@@ -173,6 +173,8 @@ def execute_node(
output_size += len(json.dumps(output_data)) output_size += len(json.dumps(output_data))
log_metadata.info("Node produced output", output_name=output_data) log_metadata.info("Node produced output", output_name=output_data)
db_client.upsert_execution_output(node_exec_id, output_name, output_data) db_client.upsert_execution_output(node_exec_id, output_name, output_data)
exec_res.output_data.setdefault(output_name, []).append(output_data)
db_client.send_execution_update(exec_res.model_dump())
for execution in _enqueue_next_nodes( for execution in _enqueue_next_nodes(
db_client=db_client, db_client=db_client,

View File

@@ -507,7 +507,6 @@ const NodeArrayInput: FC<{
typeof errors[selfKey] === "string" ? errors[selfKey] : undefined; typeof errors[selfKey] === "string" ? errors[selfKey] : undefined;
return ( return (
<div className={cn(className, "flex flex-col")}> <div className={cn(className, "flex flex-col")}>
{displayName && <strong>{displayName}</strong>}
{entries.map((entry: any, index: number) => { {entries.map((entry: any, index: number) => {
const entryKey = `${selfKey}_$_${index}`; const entryKey = `${selfKey}_$_${index}`;
const isConnected = const isConnected =

View File

@@ -117,7 +117,7 @@ export default function useAgentGraph(
if (!outputSchema) return "unknown"; if (!outputSchema) return "unknown";
const outputHandle = outputSchema.properties[handleId]; const outputHandle = outputSchema.properties[handleId];
if (!("type" in outputHandle)) return "unknown"; if (!outputHandle || !("type" in outputHandle)) return "unknown";
return outputHandle.type; return outputHandle.type;
}, },
[], [],