From a980d39e3062212aaac74b455be4f4243a146e5e Mon Sep 17 00:00:00 2001 From: leavesster <11785335+leavesster@users.noreply.github.com> Date: Fri, 18 Jul 2025 16:05:30 +0800 Subject: [PATCH 1/6] feat: run block add strict parameter --- oocana/oocana/context.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/oocana/oocana/context.py b/oocana/oocana/context.py index 0f14c096..c6bc2ff2 100644 --- a/oocana/oocana/context.py +++ b/oocana/oocana/context.py @@ -679,12 +679,13 @@ def response_callback(payload: Dict[str, Any]): return await f - def run_block(self, block: str, *, inputs: Dict[str, Any], additional_inputs_def: list[HandleDefDict] | None = None, additional_outputs_def: list[HandleDefDict] | None = None) -> RunResponse: + def run_block(self, block: str, *, inputs: Dict[str, Any], additional_inputs_def: list[HandleDefDict] | None = None, additional_outputs_def: list[HandleDefDict] | None = None, strict: bool = False) -> RunResponse: """ :param block: the id of the block to run. format: `self::` or `::`. :param inputs: the inputs of the block. if the block has no inputs, this parameter can be dict. If the inputs missing some required inputs, the response's finish future will send {"error": "error message" }. :param additional_inputs_def: additional inputs definitions, this is a list of dicts, each dict should contain the handle(required), description, json_schema, kind, nullable and is_additional fields. This is used to define additional inputs that are not defined in the block schema. :param additional_outputs_def: additional outputs definitions, this is a list of dicts, each dict should contain the handle(required), description, json_schema, kind, nullable and is_additional fields. This is used to define additional outputs that are not defined in the block schema. + :param strict: if True, oocana will use input_def's json_schema(only when it exists) to validate the inputs are not valid, otherwise it will run with the inputs as they are. :return: a RunResponse object, which contains the event callbacks and output callbacks. You can use the `add_event_callback` and `add_output_callback` methods to register callbacks for the events and outputs of the block. You can also use the `finish` method to wait for the block to finish and get the result. Notice do not call any context.send_message or context.report_progress or context.preview and other context methods(which will send message) directly in the callbacks, it may cause deadlock. @@ -721,6 +722,7 @@ def run_block(self, block: str, *, inputs: Dict[str, Any], additional_inputs_def "additional_outputs_def": additional_outputs_def, }, "stacks": self.__block_info.stacks, + "strict": strict, "request_id": request_id, }) From 7bef94286b6a6921d311eb31bd058d7e175f2620 Mon Sep 17 00:00:00 2001 From: leavesster <11785335+leavesster@users.noreply.github.com> Date: Fri, 18 Jul 2025 16:12:37 +0800 Subject: [PATCH 2/6] test: check run block strict schema check --- flow-examples/blocks/inputs/__init__.py | 7 +++++++ flow-examples/blocks/inputs/block.oo.yaml | 15 +++++++++++++++ flow-examples/flows/run-block/a/main.py | 5 +++++ 3 files changed, 27 insertions(+) create mode 100644 flow-examples/blocks/inputs/__init__.py create mode 100644 flow-examples/blocks/inputs/block.oo.yaml diff --git a/flow-examples/blocks/inputs/__init__.py b/flow-examples/blocks/inputs/__init__.py new file mode 100644 index 00000000..65b413b9 --- /dev/null +++ b/flow-examples/blocks/inputs/__init__.py @@ -0,0 +1,7 @@ +from oocana import Context + +def main(params, context: Context): + return { + "nullable_output": params.get("nullable_input"), + "default_output": params.get("default_input") + } \ No newline at end of file diff --git a/flow-examples/blocks/inputs/block.oo.yaml b/flow-examples/blocks/inputs/block.oo.yaml new file mode 100644 index 00000000..de5d46f7 --- /dev/null +++ b/flow-examples/blocks/inputs/block.oo.yaml @@ -0,0 +1,15 @@ +executor: + name: python + options: + entry: __init__.py +inputs_def: + - handle: nullable_input + nullable: true + - handle: default_input + value: "default_value" + - handle: schema_input + json_schema: + type: "string" +outputs_def: + - handle: nullable_output + - handle: default_output \ No newline at end of file diff --git a/flow-examples/flows/run-block/a/main.py b/flow-examples/flows/run-block/a/main.py index c9141db4..5c9ce942 100644 --- a/flow-examples/flows/run-block/a/main.py +++ b/flow-examples/flows/run-block/a/main.py @@ -12,4 +12,9 @@ async def main(inputs, context: Context): res = await run_res.finish() assert res.get("error") is not None + + run_res = context.run_block("self::inputs", inputs={"schema_input": 111, "nullable_input": None, "default_input": "default_value"}) + res = await run_res.finish() + assert res.get("error") is not None + return {"a": "a"} \ No newline at end of file From 61e6e1d452efa3b7d2ad69a503760615e436403b Mon Sep 17 00:00:00 2001 From: leavesster <11785335+leavesster@users.noreply.github.com> Date: Fri, 18 Jul 2025 16:20:11 +0800 Subject: [PATCH 3/6] test: add nullable and default value test case check --- flow-examples/flows/run-block/a/main.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/flow-examples/flows/run-block/a/main.py b/flow-examples/flows/run-block/a/main.py index 5c9ce942..9c9ab7de 100644 --- a/flow-examples/flows/run-block/a/main.py +++ b/flow-examples/flows/run-block/a/main.py @@ -17,4 +17,8 @@ async def main(inputs, context: Context): res = await run_res.finish() assert res.get("error") is not None + run_res = context.run_block("self::inputs", inputs={"schema_input": "aaa"}) + res = await run_res.finish() + assert res.get("error") is None + return {"a": "a"} \ No newline at end of file From 755c55f412d829acccb88aabe43a35a57f07d4b7 Mon Sep 17 00:00:00 2001 From: leavesster <11785335+leavesster@users.noreply.github.com> Date: Fri, 18 Jul 2025 16:35:12 +0800 Subject: [PATCH 4/6] test: run with strict --- flow-examples/flows/run-block/a/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flow-examples/flows/run-block/a/main.py b/flow-examples/flows/run-block/a/main.py index 9c9ab7de..537df256 100644 --- a/flow-examples/flows/run-block/a/main.py +++ b/flow-examples/flows/run-block/a/main.py @@ -13,7 +13,7 @@ async def main(inputs, context: Context): assert res.get("error") is not None - run_res = context.run_block("self::inputs", inputs={"schema_input": 111, "nullable_input": None, "default_input": "default_value"}) + run_res = context.run_block("self::inputs", inputs={"schema_input": 111, "nullable_input": None, "default_input": "default_value"}, strict=True) res = await run_res.finish() assert res.get("error") is not None From 5d08c072b303bd53bef48c7d4bc74000faf978dd Mon Sep 17 00:00:00 2001 From: leavesster <11785335+leavesster@users.noreply.github.com> Date: Fri, 18 Jul 2025 16:56:10 +0800 Subject: [PATCH 5/6] test: add assert message --- flow-examples/flows/run-block/a/main.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flow-examples/flows/run-block/a/main.py b/flow-examples/flows/run-block/a/main.py index 537df256..1e625a28 100644 --- a/flow-examples/flows/run-block/a/main.py +++ b/flow-examples/flows/run-block/a/main.py @@ -6,19 +6,19 @@ async def main(inputs, context: Context): run_res.add_event_callback(lambda payload: print("event callback", payload)) run_res.add_output_callback(lambda handle, value: print("output callback", handle, value)) res = await run_res.finish() - assert res.get("error") is None + assert res.get("error") is None, "Expected no error, got: {}".format(res.get("error")) run_res = context.run_block("blk_bccc", inputs={"my_input": "111"}) res = await run_res.finish() - assert res.get("error") is not None + assert res.get("error") is not None, "Expected error, got: {}".format(res.get("error")) run_res = context.run_block("self::inputs", inputs={"schema_input": 111, "nullable_input": None, "default_input": "default_value"}, strict=True) res = await run_res.finish() - assert res.get("error") is not None + assert res.get("error") is not None, "Expected error, got: {}".format(res.get("error")) run_res = context.run_block("self::inputs", inputs={"schema_input": "aaa"}) res = await run_res.finish() - assert res.get("error") is None + assert res.get("error") is None, "Expected no error, got: {}".format(res.get("error")) return {"a": "a"} \ No newline at end of file From 4f51affe59cc27d91df59abb8c22a96b12f64b9a Mon Sep 17 00:00:00 2001 From: leavesster <11785335+leavesster@users.noreply.github.com> Date: Fri, 18 Jul 2025 17:52:53 +0800 Subject: [PATCH 6/6] docs: update docs --- oocana/oocana/context.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/oocana/oocana/context.py b/oocana/oocana/context.py index c6bc2ff2..356e2c3b 100644 --- a/oocana/oocana/context.py +++ b/oocana/oocana/context.py @@ -682,10 +682,14 @@ def response_callback(payload: Dict[str, Any]): def run_block(self, block: str, *, inputs: Dict[str, Any], additional_inputs_def: list[HandleDefDict] | None = None, additional_outputs_def: list[HandleDefDict] | None = None, strict: bool = False) -> RunResponse: """ :param block: the id of the block to run. format: `self::` or `::`. - :param inputs: the inputs of the block. if the block has no inputs, this parameter can be dict. If the inputs missing some required inputs, the response's finish future will send {"error": "error message" }. + :param inputs: the inputs of the block. if the block has no inputs, this parameter can be dict. + If the inputs missing some required inputs, the response's finish future will send {"error": "" }. + some missing inputs will be filled: + 1. with the default value if the block's input_def has a default value (which is defined in the value field). + 2. input_def's nullable is true, the missing input will be filled with Null. :param additional_inputs_def: additional inputs definitions, this is a list of dicts, each dict should contain the handle(required), description, json_schema, kind, nullable and is_additional fields. This is used to define additional inputs that are not defined in the block schema. :param additional_outputs_def: additional outputs definitions, this is a list of dicts, each dict should contain the handle(required), description, json_schema, kind, nullable and is_additional fields. This is used to define additional outputs that are not defined in the block schema. - :param strict: if True, oocana will use input_def's json_schema(only when it exists) to validate the inputs are not valid, otherwise it will run with the inputs as they are. + :param strict: if True, oocana will use input_def's json_schema(only when it exists) to validate the inputs and if they are not valid oocana will reject to run this block, return error message. otherwise it will run with the inputs as they are. :return: a RunResponse object, which contains the event callbacks and output callbacks. You can use the `add_event_callback` and `add_output_callback` methods to register callbacks for the events and outputs of the block. You can also use the `finish` method to wait for the block to finish and get the result. Notice do not call any context.send_message or context.report_progress or context.preview and other context methods(which will send message) directly in the callbacks, it may cause deadlock.