| environment_variables=[], | environment_variables=[], | ||||
| conversation_variables=[], | conversation_variables=[], | ||||
| ) | ) | ||||
| variable_pool.add(["code", "123", "args1"], 1) | |||||
| variable_pool.add(["code", "123", "args2"], 2) | |||||
| variable_pool.add(["code", "args1"], 1) | |||||
| variable_pool.add(["code", "args2"], 2) | |||||
| node = CodeNode( | node = CodeNode( | ||||
| id=str(uuid.uuid4()), | id=str(uuid.uuid4()), | ||||
| "variables": [ | "variables": [ | ||||
| { | { | ||||
| "variable": "args1", | "variable": "args1", | ||||
| "value_selector": ["1", "123", "args1"], | |||||
| "value_selector": ["1", "args1"], | |||||
| }, | }, | ||||
| {"variable": "args2", "value_selector": ["1", "123", "args2"]}, | |||||
| {"variable": "args2", "value_selector": ["1", "args2"]}, | |||||
| ], | ], | ||||
| "answer": "123", | "answer": "123", | ||||
| "code_language": "python3", | "code_language": "python3", | ||||
| } | } | ||||
| node = init_code_node(code_config) | node = init_code_node(code_config) | ||||
| node.graph_runtime_state.variable_pool.add(["1", "123", "args1"], 1) | |||||
| node.graph_runtime_state.variable_pool.add(["1", "123", "args2"], 2) | |||||
| node.graph_runtime_state.variable_pool.add(["1", "args1"], 1) | |||||
| node.graph_runtime_state.variable_pool.add(["1", "args2"], 2) | |||||
| # execute node | # execute node | ||||
| result = node._run() | result = node._run() | ||||
| "variables": [ | "variables": [ | ||||
| { | { | ||||
| "variable": "args1", | "variable": "args1", | ||||
| "value_selector": ["1", "123", "args1"], | |||||
| "value_selector": ["1", "args1"], | |||||
| }, | }, | ||||
| {"variable": "args2", "value_selector": ["1", "123", "args2"]}, | |||||
| {"variable": "args2", "value_selector": ["1", "args2"]}, | |||||
| ], | ], | ||||
| "answer": "123", | "answer": "123", | ||||
| "code_language": "python3", | "code_language": "python3", | ||||
| } | } | ||||
| node = init_code_node(code_config) | node = init_code_node(code_config) | ||||
| node.graph_runtime_state.variable_pool.add(["1", "123", "args1"], 1) | |||||
| node.graph_runtime_state.variable_pool.add(["1", "123", "args2"], 2) | |||||
| node.graph_runtime_state.variable_pool.add(["1", "args1"], 1) | |||||
| node.graph_runtime_state.variable_pool.add(["1", "args2"], 2) | |||||
| # execute node | # execute node | ||||
| result = node._run() | result = node._run() | ||||
| "variables": [ | "variables": [ | ||||
| { | { | ||||
| "variable": "args1", | "variable": "args1", | ||||
| "value_selector": ["1", "123", "args1"], | |||||
| "value_selector": ["1", "args1"], | |||||
| }, | }, | ||||
| {"variable": "args2", "value_selector": ["1", "123", "args2"]}, | |||||
| {"variable": "args2", "value_selector": ["1", "args2"]}, | |||||
| ], | ], | ||||
| "answer": "123", | "answer": "123", | ||||
| "code_language": "python3", | "code_language": "python3", | ||||
| "variables": [ | "variables": [ | ||||
| { | { | ||||
| "variable": "args1", | "variable": "args1", | ||||
| "value_selector": ["1", "123", "args1"], | |||||
| "value_selector": ["1", "args1"], | |||||
| }, | }, | ||||
| {"variable": "args2", "value_selector": ["1", "123", "args2"]}, | |||||
| {"variable": "args2", "value_selector": ["1", "args2"]}, | |||||
| ], | ], | ||||
| "answer": "123", | "answer": "123", | ||||
| "code_language": "python3", | "code_language": "python3", |
| environment_variables=[], | environment_variables=[], | ||||
| conversation_variables=[], | conversation_variables=[], | ||||
| ) | ) | ||||
| variable_pool.add(["a", "b123", "args1"], 1) | |||||
| variable_pool.add(["a", "b123", "args2"], 2) | |||||
| variable_pool.add(["a", "args1"], 1) | |||||
| variable_pool.add(["a", "args2"], 2) | |||||
| node = HttpRequestNode( | node = HttpRequestNode( | ||||
| id=str(uuid.uuid4()), | id=str(uuid.uuid4()), | ||||
| "title": "http", | "title": "http", | ||||
| "desc": "", | "desc": "", | ||||
| "method": "get", | "method": "get", | ||||
| "url": "http://example.com/{{#a.b123.args2#}}", | |||||
| "url": "http://example.com/{{#a.args2#}}", | |||||
| "authorization": { | "authorization": { | ||||
| "type": "api-key", | "type": "api-key", | ||||
| "config": { | "config": { | ||||
| "header": "api-key", | "header": "api-key", | ||||
| }, | }, | ||||
| }, | }, | ||||
| "headers": "X-Header:123\nX-Header2:{{#a.b123.args2#}}", | |||||
| "params": "A:b\nTemplate:{{#a.b123.args2#}}", | |||||
| "headers": "X-Header:123\nX-Header2:{{#a.args2#}}", | |||||
| "params": "A:b\nTemplate:{{#a.args2#}}", | |||||
| "body": None, | "body": None, | ||||
| }, | }, | ||||
| } | } | ||||
| { | { | ||||
| "key": "", | "key": "", | ||||
| "type": "text", | "type": "text", | ||||
| "value": '{"a": "{{#a.b123.args1#}}"}', | |||||
| "value": '{"a": "{{#a.args1#}}"}', | |||||
| }, | }, | ||||
| ], | ], | ||||
| }, | }, | ||||
| { | { | ||||
| "key": "a", | "key": "a", | ||||
| "type": "text", | "type": "text", | ||||
| "value": "{{#a.b123.args1#}}", | |||||
| "value": "{{#a.args1#}}", | |||||
| }, | }, | ||||
| { | { | ||||
| "key": "b", | "key": "b", | ||||
| "type": "text", | "type": "text", | ||||
| "value": "{{#a.b123.args2#}}", | |||||
| "value": "{{#a.args2#}}", | |||||
| }, | }, | ||||
| ], | ], | ||||
| }, | }, | ||||
| { | { | ||||
| "key": "a", | "key": "a", | ||||
| "type": "text", | "type": "text", | ||||
| "value": "{{#a.b123.args1#}}", | |||||
| "value": "{{#a.args1#}}", | |||||
| }, | }, | ||||
| { | { | ||||
| "key": "b", | "key": "b", | ||||
| "type": "text", | "type": "text", | ||||
| "value": "{{#a.b123.args2#}}", | |||||
| "value": "{{#a.args2#}}", | |||||
| }, | }, | ||||
| ], | ], | ||||
| }, | }, | ||||
| assert 'form-data; name="Redirect"\r\n\r\nhttp://example6.com' in result.process_data.get("request", "") | assert 'form-data; name="Redirect"\r\n\r\nhttp://example6.com' in result.process_data.get("request", "") | ||||
| # resp = result.outputs | # resp = result.outputs | ||||
| # assert "http://example3.com" == resp.get("headers", {}).get("referer") | # assert "http://example3.com" == resp.get("headers", {}).get("referer") | ||||
| @pytest.mark.parametrize("setup_http_mock", [["none"]], indirect=True) | |||||
| def test_nested_object_variable_selector(setup_http_mock): | |||||
| """Test variable selector functionality with nested object properties.""" | |||||
| # Create independent test setup without affecting other tests | |||||
| graph_config = { | |||||
| "edges": [ | |||||
| { | |||||
| "id": "start-source-next-target", | |||||
| "source": "start", | |||||
| "target": "1", | |||||
| }, | |||||
| ], | |||||
| "nodes": [ | |||||
| {"data": {"type": "start"}, "id": "start"}, | |||||
| { | |||||
| "id": "1", | |||||
| "data": { | |||||
| "title": "http", | |||||
| "desc": "", | |||||
| "method": "get", | |||||
| "url": "http://example.com/{{#a.args2#}}/{{#a.args3.nested#}}", | |||||
| "authorization": { | |||||
| "type": "api-key", | |||||
| "config": { | |||||
| "type": "basic", | |||||
| "api_key": "ak-xxx", | |||||
| "header": "api-key", | |||||
| }, | |||||
| }, | |||||
| "headers": "X-Header:{{#a.args3.nested#}}", | |||||
| "params": "nested_param:{{#a.args3.nested#}}", | |||||
| "body": None, | |||||
| }, | |||||
| }, | |||||
| ], | |||||
| } | |||||
| graph = Graph.init(graph_config=graph_config) | |||||
| init_params = GraphInitParams( | |||||
| tenant_id="1", | |||||
| app_id="1", | |||||
| workflow_type=WorkflowType.WORKFLOW, | |||||
| workflow_id="1", | |||||
| graph_config=graph_config, | |||||
| user_id="1", | |||||
| user_from=UserFrom.ACCOUNT, | |||||
| invoke_from=InvokeFrom.DEBUGGER, | |||||
| call_depth=0, | |||||
| ) | |||||
| # Create independent variable pool for this test only | |||||
| variable_pool = VariablePool( | |||||
| system_variables=SystemVariable(user_id="aaa", files=[]), | |||||
| user_inputs={}, | |||||
| environment_variables=[], | |||||
| conversation_variables=[], | |||||
| ) | |||||
| variable_pool.add(["a", "args1"], 1) | |||||
| variable_pool.add(["a", "args2"], 2) | |||||
| variable_pool.add(["a", "args3"], {"nested": "nested_value"}) # Only for this test | |||||
| node = HttpRequestNode( | |||||
| id=str(uuid.uuid4()), | |||||
| graph_init_params=init_params, | |||||
| graph=graph, | |||||
| graph_runtime_state=GraphRuntimeState(variable_pool=variable_pool, start_at=time.perf_counter()), | |||||
| config=graph_config["nodes"][1], | |||||
| ) | |||||
| # Initialize node data | |||||
| if "data" in graph_config["nodes"][1]: | |||||
| node.init_node_data(graph_config["nodes"][1]["data"]) | |||||
| result = node._run() | |||||
| assert result.process_data is not None | |||||
| data = result.process_data.get("request", "") | |||||
| # Verify nested object property is correctly resolved | |||||
| assert "/2/nested_value" in data # URL path should contain resolved nested value | |||||
| assert "X-Header: nested_value" in data # Header should contain nested value | |||||
| assert "nested_param=nested_value" in data # Param should contain nested value |
| environment_variables=[], | environment_variables=[], | ||||
| conversation_variables=[], | conversation_variables=[], | ||||
| ) | ) | ||||
| variable_pool.add(["a", "b123", "args1"], 1) | |||||
| variable_pool.add(["a", "b123", "args2"], 2) | |||||
| variable_pool.add(["a", "args1"], 1) | |||||
| variable_pool.add(["a", "args2"], 2) | |||||
| node = ParameterExtractorNode( | node = ParameterExtractorNode( | ||||
| id=str(uuid.uuid4()), | id=str(uuid.uuid4()), |
| "variables": [ | "variables": [ | ||||
| { | { | ||||
| "variable": "args1", | "variable": "args1", | ||||
| "value_selector": ["1", "123", "args1"], | |||||
| "value_selector": ["1", "args1"], | |||||
| }, | }, | ||||
| {"variable": "args2", "value_selector": ["1", "123", "args2"]}, | |||||
| {"variable": "args2", "value_selector": ["1", "args2"]}, | |||||
| ], | ], | ||||
| "template": code, | "template": code, | ||||
| }, | }, | ||||
| environment_variables=[], | environment_variables=[], | ||||
| conversation_variables=[], | conversation_variables=[], | ||||
| ) | ) | ||||
| variable_pool.add(["1", "123", "args1"], 1) | |||||
| variable_pool.add(["1", "123", "args2"], 3) | |||||
| variable_pool.add(["1", "args1"], 1) | |||||
| variable_pool.add(["1", "args2"], 3) | |||||
| node = TemplateTransformNode( | node = TemplateTransformNode( | ||||
| id=str(uuid.uuid4()), | id=str(uuid.uuid4()), |
| ToolParameterConfigurationManager.decrypt_tool_parameters = MagicMock(return_value={"format": "%Y-%m-%d %H:%M:%S"}) | ToolParameterConfigurationManager.decrypt_tool_parameters = MagicMock(return_value={"format": "%Y-%m-%d %H:%M:%S"}) | ||||
| node.graph_runtime_state.variable_pool.add(["1", "123", "args1"], "1+1") | |||||
| node.graph_runtime_state.variable_pool.add(["1", "args1"], "1+1") | |||||
| # execute node | # execute node | ||||
| result = node._run() | result = node._run() |