mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 06:14:59 +00:00
Add full Python workflow execution engine with: Core Executor: - engine.py: WorkflowEngine for running n8n configs - n8n_executor.py: N8N-style workflow execution with connections - node_executor.py: Individual node execution with plugin dispatch - loop_executor.py: Loop node execution with iteration control - execution_order.py: Topological sort for node ordering Schema & Validation: - n8n_schema.py: N8N workflow schema types and validation - n8n_converter.py: Legacy to n8n schema conversion Plugin System: - plugin_loader.py: Dynamic plugin loading - plugin_registry.py: Plugin discovery and registration - plugin_map.json: 116 plugin type mappings Runtime & Context: - runtime.py: Workflow runtime container - input_resolver.py: Binding and coercion resolution - value_helpers.py: Value normalization helpers - workflow_context_builder.py: Runtime context assembly - workflow_config_loader.py: Configuration loading - workflow_engine_builder.py: Engine assembly with dependencies Utilities: - tool_calls_handler.py: LLM tool call handling - tool_runner.py: Tool execution with logging - notification_helpers.py: Slack/Discord notifications - workflow_adapter.py: N8N format handling - workflow_graph.py: Node/edge graph for visualization Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
30 lines
1.0 KiB
Python
30 lines
1.0 KiB
Python
"""Run tools with logging and filtering."""
|
|
|
|
|
|
class ToolRunner:
|
|
"""Run tool callables with shared logging."""
|
|
def __init__(self, tool_map: dict, msgs: dict, logger):
|
|
self.tool_map = tool_map
|
|
self.msgs = msgs
|
|
self.logger = logger
|
|
|
|
def call(self, tool_name: str, **kwargs):
|
|
"""Call a named tool with filtered kwargs."""
|
|
tool = self.tool_map.get(tool_name)
|
|
if not tool:
|
|
msg = self.msgs.get(
|
|
"error_tool_not_found",
|
|
"Tool {name} not found or unavailable."
|
|
).format(name=tool_name)
|
|
self.logger.error(msg)
|
|
return msg
|
|
|
|
filtered_kwargs = {k: v for k, v in kwargs.items() if v is not None}
|
|
try:
|
|
result = tool(**filtered_kwargs)
|
|
return result if result is not None else "Success"
|
|
except Exception as error: # pylint: disable=broad-exception-caught
|
|
error_msg = f"Error executing {tool_name}: {error}"
|
|
self.logger.error(error_msg)
|
|
return error_msg
|