mirror of
https://github.com/johndoe6345789/AutoMetabuilder.git
synced 2026-04-24 13:54:59 +00:00
Add comprehensive tests and documentation for workflow plugins
Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com>
This commit is contained in:
822
backend/autometabuilder/workflow/plugins/README.md
Normal file
822
backend/autometabuilder/workflow/plugins/README.md
Normal file
@@ -0,0 +1,822 @@
|
||||
# Workflow Plugins Documentation
|
||||
|
||||
This document describes all available workflow plugins for building declarative n8n-style workflows.
|
||||
|
||||
## Categories
|
||||
|
||||
- [Core Plugins](#core-plugins) - AI and context management
|
||||
- [Tool Plugins](#tool-plugins) - File system and SDLC operations
|
||||
- [Logic Plugins](#logic-plugins) - Boolean logic and comparisons
|
||||
- [List Plugins](#list-plugins) - Collection operations
|
||||
- [Dictionary Plugins](#dictionary-plugins) - Object/map operations
|
||||
- [String Plugins](#string-plugins) - Text manipulation
|
||||
- [Math Plugins](#math-plugins) - Arithmetic operations
|
||||
- [Conversion Plugins](#conversion-plugins) - Type conversions
|
||||
- [Control Flow Plugins](#control-flow-plugins) - Branching and switching
|
||||
- [Variable Plugins](#variable-plugins) - State management
|
||||
- [Backend Plugins](#backend-plugins) - System initialization
|
||||
- [Utility Plugins](#utility-plugins) - General utilities
|
||||
|
||||
---
|
||||
|
||||
## Core Plugins
|
||||
|
||||
### `core.load_context`
|
||||
Load SDLC context (roadmap, issues, PRs) from GitHub.
|
||||
|
||||
**Outputs:**
|
||||
- `context` - String containing SDLC context
|
||||
|
||||
### `core.seed_messages`
|
||||
Initialize empty message array for AI conversation.
|
||||
|
||||
**Outputs:**
|
||||
- `messages` - Empty array
|
||||
|
||||
### `core.append_context_message`
|
||||
Add context to messages array.
|
||||
|
||||
**Inputs:**
|
||||
- `messages` - Message array
|
||||
- `context` - Context text
|
||||
|
||||
**Outputs:**
|
||||
- `messages` - Updated array
|
||||
|
||||
### `core.append_user_instruction`
|
||||
Add user instruction to messages.
|
||||
|
||||
**Inputs:**
|
||||
- `messages` - Message array
|
||||
|
||||
**Outputs:**
|
||||
- `messages` - Updated array
|
||||
|
||||
### `core.ai_request`
|
||||
Make AI request with messages.
|
||||
|
||||
**Inputs:**
|
||||
- `messages` - Message array
|
||||
|
||||
**Outputs:**
|
||||
- `response` - AI response message
|
||||
- `has_tool_calls` - Boolean
|
||||
- `tool_calls_count` - Number
|
||||
|
||||
### `core.run_tool_calls`
|
||||
Execute tool calls from AI response.
|
||||
|
||||
**Inputs:**
|
||||
- `response` - AI response message
|
||||
|
||||
**Outputs:**
|
||||
- `tool_results` - Array of results
|
||||
|
||||
### `core.append_tool_results`
|
||||
Add tool results to messages.
|
||||
|
||||
**Inputs:**
|
||||
- `messages` - Message array
|
||||
- `tool_results` - Tool results array
|
||||
|
||||
**Outputs:**
|
||||
- `messages` - Updated array
|
||||
|
||||
---
|
||||
|
||||
## Tool Plugins
|
||||
|
||||
### `tools.list_files`
|
||||
List files in directory.
|
||||
|
||||
**Inputs:**
|
||||
- `path` - Directory path
|
||||
|
||||
**Outputs:**
|
||||
- `files` - Array of file paths
|
||||
|
||||
### `tools.read_file`
|
||||
Read file contents.
|
||||
|
||||
**Inputs:**
|
||||
- `path` - File path
|
||||
|
||||
**Outputs:**
|
||||
- `content` - File content
|
||||
|
||||
### `tools.run_tests`
|
||||
Execute test suite.
|
||||
|
||||
**Outputs:**
|
||||
- `success` - Boolean
|
||||
- `output` - Test output
|
||||
|
||||
### `tools.run_lint`
|
||||
Run linter.
|
||||
|
||||
**Outputs:**
|
||||
- `success` - Boolean
|
||||
- `output` - Lint output
|
||||
|
||||
### `tools.create_branch`
|
||||
Create Git branch.
|
||||
|
||||
**Inputs:**
|
||||
- `branch_name` - Branch name
|
||||
|
||||
**Outputs:**
|
||||
- `success` - Boolean
|
||||
|
||||
### `tools.create_pull_request`
|
||||
Create GitHub pull request.
|
||||
|
||||
**Inputs:**
|
||||
- `title` - PR title
|
||||
- `body` - PR description
|
||||
|
||||
**Outputs:**
|
||||
- `pr_number` - PR number
|
||||
|
||||
---
|
||||
|
||||
## Logic Plugins
|
||||
|
||||
### `logic.and`
|
||||
Logical AND operation.
|
||||
|
||||
**Inputs:**
|
||||
- `values` - Array of boolean values
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Boolean (all values are true)
|
||||
|
||||
### `logic.or`
|
||||
Logical OR operation.
|
||||
|
||||
**Inputs:**
|
||||
- `values` - Array of boolean values
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Boolean (any value is true)
|
||||
|
||||
### `logic.xor`
|
||||
Logical XOR operation.
|
||||
|
||||
**Inputs:**
|
||||
- `a` - First boolean
|
||||
- `b` - Second boolean
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Boolean (exactly one is true)
|
||||
|
||||
### `logic.equals`
|
||||
Equality comparison.
|
||||
|
||||
**Inputs:**
|
||||
- `a` - First value
|
||||
- `b` - Second value
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Boolean (a == b)
|
||||
|
||||
### `logic.gt`
|
||||
Greater than comparison.
|
||||
|
||||
**Inputs:**
|
||||
- `a` - First value
|
||||
- `b` - Second value
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Boolean (a > b)
|
||||
|
||||
### `logic.lt`
|
||||
Less than comparison.
|
||||
|
||||
**Inputs:**
|
||||
- `a` - First value
|
||||
- `b` - Second value
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Boolean (a < b)
|
||||
|
||||
### `logic.gte`
|
||||
Greater than or equal comparison.
|
||||
|
||||
**Inputs:**
|
||||
- `a` - First value
|
||||
- `b` - Second value
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Boolean (a >= b)
|
||||
|
||||
### `logic.lte`
|
||||
Less than or equal comparison.
|
||||
|
||||
**Inputs:**
|
||||
- `a` - First value
|
||||
- `b` - Second value
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Boolean (a <= b)
|
||||
|
||||
### `logic.in`
|
||||
Membership test.
|
||||
|
||||
**Inputs:**
|
||||
- `value` - Value to find
|
||||
- `collection` - Array or string
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Boolean (value in collection)
|
||||
|
||||
---
|
||||
|
||||
## List Plugins
|
||||
|
||||
### `list.find`
|
||||
Find first item matching condition.
|
||||
|
||||
**Inputs:**
|
||||
- `items` - Array of objects
|
||||
- `key` - Property name
|
||||
- `value` - Value to match
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Found item or null
|
||||
- `found` - Boolean
|
||||
|
||||
### `list.some`
|
||||
Check if any item matches.
|
||||
|
||||
**Inputs:**
|
||||
- `items` - Array
|
||||
- `key` - Optional property name
|
||||
- `value` - Optional value to match
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Boolean
|
||||
|
||||
### `list.every`
|
||||
Check if all items match.
|
||||
|
||||
**Inputs:**
|
||||
- `items` - Array
|
||||
- `key` - Optional property name
|
||||
- `value` - Optional value to match
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Boolean
|
||||
|
||||
### `list.concat`
|
||||
Concatenate multiple lists.
|
||||
|
||||
**Inputs:**
|
||||
- `lists` - Array of arrays
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Concatenated array
|
||||
|
||||
### `list.slice`
|
||||
Extract slice from list.
|
||||
|
||||
**Inputs:**
|
||||
- `items` - Array
|
||||
- `start` - Start index (default: 0)
|
||||
- `end` - End index (optional)
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Sliced array
|
||||
|
||||
### `list.sort`
|
||||
Sort list.
|
||||
|
||||
**Inputs:**
|
||||
- `items` - Array
|
||||
- `key` - Optional sort key
|
||||
- `reverse` - Boolean (default: false)
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Sorted array
|
||||
|
||||
### `list.length`
|
||||
Get list length.
|
||||
|
||||
**Inputs:**
|
||||
- `items` - Array
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Number (length)
|
||||
|
||||
---
|
||||
|
||||
## Dictionary Plugins
|
||||
|
||||
### `dict.get`
|
||||
Get value from dictionary.
|
||||
|
||||
**Inputs:**
|
||||
- `object` - Dictionary
|
||||
- `key` - Key name
|
||||
- `default` - Default value (optional)
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Value
|
||||
- `found` - Boolean
|
||||
|
||||
### `dict.set`
|
||||
Set value in dictionary.
|
||||
|
||||
**Inputs:**
|
||||
- `object` - Dictionary
|
||||
- `key` - Key name
|
||||
- `value` - Value to set
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Updated dictionary
|
||||
|
||||
### `dict.merge`
|
||||
Merge multiple dictionaries.
|
||||
|
||||
**Inputs:**
|
||||
- `objects` - Array of dictionaries
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Merged dictionary
|
||||
|
||||
### `dict.keys`
|
||||
Get dictionary keys.
|
||||
|
||||
**Inputs:**
|
||||
- `object` - Dictionary
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Array of keys
|
||||
|
||||
### `dict.values`
|
||||
Get dictionary values.
|
||||
|
||||
**Inputs:**
|
||||
- `object` - Dictionary
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Array of values
|
||||
|
||||
### `dict.items`
|
||||
Get dictionary items as [key, value] pairs.
|
||||
|
||||
**Inputs:**
|
||||
- `object` - Dictionary
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Array of [key, value] arrays
|
||||
|
||||
---
|
||||
|
||||
## String Plugins
|
||||
|
||||
### `string.concat`
|
||||
Concatenate strings.
|
||||
|
||||
**Inputs:**
|
||||
- `strings` - Array of strings
|
||||
- `separator` - Separator string (default: "")
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Concatenated string
|
||||
|
||||
### `string.split`
|
||||
Split string.
|
||||
|
||||
**Inputs:**
|
||||
- `text` - Input string
|
||||
- `separator` - Split separator (default: " ")
|
||||
- `max_splits` - Max splits (optional)
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Array of strings
|
||||
|
||||
### `string.replace`
|
||||
Replace occurrences in string.
|
||||
|
||||
**Inputs:**
|
||||
- `text` - Input string
|
||||
- `old` - String to replace
|
||||
- `new` - Replacement string
|
||||
- `count` - Max replacements (default: -1 for all)
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Modified string
|
||||
|
||||
### `string.trim`
|
||||
Trim whitespace.
|
||||
|
||||
**Inputs:**
|
||||
- `text` - Input string
|
||||
- `mode` - "both", "start", or "end" (default: "both")
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Trimmed string
|
||||
|
||||
### `string.upper`
|
||||
Convert to uppercase.
|
||||
|
||||
**Inputs:**
|
||||
- `text` - Input string
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Uppercase string
|
||||
|
||||
### `string.lower`
|
||||
Convert to lowercase.
|
||||
|
||||
**Inputs:**
|
||||
- `text` - Input string
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Lowercase string
|
||||
|
||||
### `string.format`
|
||||
Format string with variables.
|
||||
|
||||
**Inputs:**
|
||||
- `template` - Template string with {placeholders}
|
||||
- `variables` - Dictionary of variables
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Formatted string
|
||||
|
||||
### `string.length`
|
||||
Get string length.
|
||||
|
||||
**Inputs:**
|
||||
- `text` - Input string
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Number (length)
|
||||
|
||||
---
|
||||
|
||||
## Math Plugins
|
||||
|
||||
### `math.add`
|
||||
Add numbers.
|
||||
|
||||
**Inputs:**
|
||||
- `numbers` - Array of numbers
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Sum
|
||||
|
||||
### `math.subtract`
|
||||
Subtract numbers.
|
||||
|
||||
**Inputs:**
|
||||
- `a` - Minuend
|
||||
- `b` - Subtrahend
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Difference (a - b)
|
||||
|
||||
### `math.multiply`
|
||||
Multiply numbers.
|
||||
|
||||
**Inputs:**
|
||||
- `numbers` - Array of numbers
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Product
|
||||
|
||||
### `math.divide`
|
||||
Divide numbers.
|
||||
|
||||
**Inputs:**
|
||||
- `a` - Dividend
|
||||
- `b` - Divisor
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Quotient (a / b)
|
||||
|
||||
### `math.modulo`
|
||||
Modulo operation.
|
||||
|
||||
**Inputs:**
|
||||
- `a` - Dividend
|
||||
- `b` - Divisor
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Remainder (a % b)
|
||||
|
||||
### `math.power`
|
||||
Power operation.
|
||||
|
||||
**Inputs:**
|
||||
- `a` - Base
|
||||
- `b` - Exponent
|
||||
|
||||
**Outputs:**
|
||||
- `result` - a^b
|
||||
|
||||
### `math.min`
|
||||
Find minimum value.
|
||||
|
||||
**Inputs:**
|
||||
- `numbers` - Array of numbers
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Minimum value
|
||||
|
||||
### `math.max`
|
||||
Find maximum value.
|
||||
|
||||
**Inputs:**
|
||||
- `numbers` - Array of numbers
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Maximum value
|
||||
|
||||
### `math.abs`
|
||||
Absolute value.
|
||||
|
||||
**Inputs:**
|
||||
- `value` - Number
|
||||
|
||||
**Outputs:**
|
||||
- `result` - |value|
|
||||
|
||||
### `math.round`
|
||||
Round number.
|
||||
|
||||
**Inputs:**
|
||||
- `value` - Number
|
||||
- `precision` - Decimal places (default: 0)
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Rounded number
|
||||
|
||||
---
|
||||
|
||||
## Conversion Plugins
|
||||
|
||||
### `convert.to_string`
|
||||
Convert to string.
|
||||
|
||||
**Inputs:**
|
||||
- `value` - Any value
|
||||
|
||||
**Outputs:**
|
||||
- `result` - String
|
||||
|
||||
### `convert.to_number`
|
||||
Convert to number.
|
||||
|
||||
**Inputs:**
|
||||
- `value` - String or number
|
||||
- `default` - Default value (default: 0)
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Number
|
||||
|
||||
### `convert.to_boolean`
|
||||
Convert to boolean.
|
||||
|
||||
**Inputs:**
|
||||
- `value` - Any value
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Boolean
|
||||
|
||||
### `convert.to_list`
|
||||
Convert to list.
|
||||
|
||||
**Inputs:**
|
||||
- `value` - Any value
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Array
|
||||
|
||||
### `convert.to_dict`
|
||||
Convert to dictionary.
|
||||
|
||||
**Inputs:**
|
||||
- `value` - List of [key, value] pairs or dict
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Dictionary
|
||||
|
||||
### `convert.parse_json`
|
||||
Parse JSON string.
|
||||
|
||||
**Inputs:**
|
||||
- `text` - JSON string
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Parsed object
|
||||
|
||||
### `convert.to_json`
|
||||
Convert to JSON string.
|
||||
|
||||
**Inputs:**
|
||||
- `value` - Any value
|
||||
- `indent` - Indentation (optional)
|
||||
|
||||
**Outputs:**
|
||||
- `result` - JSON string
|
||||
|
||||
---
|
||||
|
||||
## Control Flow Plugins
|
||||
|
||||
### `control.switch`
|
||||
Switch/case statement.
|
||||
|
||||
**Inputs:**
|
||||
- `value` - Value to match
|
||||
- `cases` - Dictionary of case values
|
||||
- `default` - Default value (optional)
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Matched case value
|
||||
- `matched` - Boolean
|
||||
|
||||
### `utils.branch_condition`
|
||||
Branch based on condition.
|
||||
|
||||
**Inputs:**
|
||||
- `condition` - Boolean
|
||||
|
||||
**Outputs:**
|
||||
- Routes to output 0 (true) or 1 (false)
|
||||
|
||||
---
|
||||
|
||||
## Variable Plugins
|
||||
|
||||
### `var.get`
|
||||
Get variable from workflow store.
|
||||
|
||||
**Inputs:**
|
||||
- `key` - Variable name
|
||||
- `default` - Default value (optional)
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Variable value
|
||||
- `exists` - Boolean
|
||||
|
||||
### `var.set`
|
||||
Set variable in workflow store.
|
||||
|
||||
**Inputs:**
|
||||
- `key` - Variable name
|
||||
- `value` - Value to set
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Set value
|
||||
- `key` - Variable name
|
||||
|
||||
### `var.delete`
|
||||
Delete variable from workflow store.
|
||||
|
||||
**Inputs:**
|
||||
- `key` - Variable name
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Boolean (success)
|
||||
- `deleted` - Boolean
|
||||
|
||||
### `var.exists`
|
||||
Check if variable exists.
|
||||
|
||||
**Inputs:**
|
||||
- `key` - Variable name
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Boolean
|
||||
|
||||
---
|
||||
|
||||
## Backend Plugins
|
||||
|
||||
### `backend.create_github`
|
||||
Initialize GitHub client.
|
||||
|
||||
**Outputs:**
|
||||
- `result` - GitHub client
|
||||
- `initialized` - Boolean
|
||||
|
||||
### `backend.create_openai`
|
||||
Initialize OpenAI client.
|
||||
|
||||
**Outputs:**
|
||||
- `result` - OpenAI client
|
||||
- `initialized` - Boolean
|
||||
|
||||
### `backend.load_metadata`
|
||||
Load metadata.json.
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Metadata dictionary
|
||||
|
||||
### `backend.load_messages`
|
||||
Load translation messages.
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Messages dictionary
|
||||
|
||||
### `backend.load_tools`
|
||||
Load tool definitions.
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Tools array
|
||||
|
||||
### `backend.load_prompt`
|
||||
Load prompt.yml.
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Prompt dictionary
|
||||
|
||||
### `backend.build_tool_map`
|
||||
Build tool registry map.
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Tool map dictionary
|
||||
|
||||
### `backend.load_plugins`
|
||||
Load and register plugins.
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Boolean (success)
|
||||
|
||||
---
|
||||
|
||||
## Utility Plugins
|
||||
|
||||
### `utils.filter_list`
|
||||
Filter list by condition.
|
||||
|
||||
**Inputs:**
|
||||
- `items` - Array
|
||||
- `mode` - Filter mode
|
||||
- `pattern` - Pattern/condition
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Filtered array
|
||||
|
||||
### `utils.map_list`
|
||||
Map/transform list items.
|
||||
|
||||
**Inputs:**
|
||||
- `items` - Array
|
||||
- `transform` - Transformation
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Transformed array
|
||||
|
||||
### `utils.reduce_list`
|
||||
Reduce list to single value.
|
||||
|
||||
**Inputs:**
|
||||
- `items` - Array
|
||||
- `separator` - Join separator
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Reduced value
|
||||
|
||||
### `utils.not`
|
||||
Logical NOT operation.
|
||||
|
||||
**Inputs:**
|
||||
- `value` - Boolean value
|
||||
|
||||
**Outputs:**
|
||||
- `result` - Negated boolean
|
||||
|
||||
---
|
||||
|
||||
## Variable Binding
|
||||
|
||||
All plugins support variable binding using `$variable_name` syntax in inputs. Variables are stored in the workflow runtime store and can be accessed across nodes.
|
||||
|
||||
Example:
|
||||
```json
|
||||
{
|
||||
"parameters": {
|
||||
"text": "$user_input",
|
||||
"template": "Hello {name}!",
|
||||
"variables": {
|
||||
"name": "$user_name"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
Plugins may return an `error` field in their output when an error occurs. Check for this field to handle errors gracefully in your workflow.
|
||||
|
||||
Example:
|
||||
```json
|
||||
{
|
||||
"result": null,
|
||||
"error": "Division by zero"
|
||||
}
|
||||
```
|
||||
319
backend/tests/test_workflow_plugins.py
Normal file
319
backend/tests/test_workflow_plugins.py
Normal file
@@ -0,0 +1,319 @@
|
||||
"""Test new workflow plugins for software development primitives."""
|
||||
from autometabuilder.workflow.plugin_registry import PluginRegistry, load_plugin_map
|
||||
from autometabuilder.workflow.runtime import WorkflowRuntime
|
||||
import logging
|
||||
|
||||
|
||||
class MockLogger:
|
||||
"""Mock logger for testing."""
|
||||
def info(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def debug(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def error(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
|
||||
def create_test_runtime():
|
||||
"""Create a test runtime with empty context."""
|
||||
logger = MockLogger()
|
||||
return WorkflowRuntime(context={}, store={}, tool_runner=None, logger=logger)
|
||||
|
||||
|
||||
def test_plugin_map_loads_all_new_plugins():
|
||||
"""Test that plugin map includes all new plugins."""
|
||||
plugin_map = load_plugin_map()
|
||||
|
||||
# Test logic plugins
|
||||
assert "logic.and" in plugin_map
|
||||
assert "logic.or" in plugin_map
|
||||
assert "logic.xor" in plugin_map
|
||||
assert "logic.equals" in plugin_map
|
||||
assert "logic.gt" in plugin_map
|
||||
assert "logic.lt" in plugin_map
|
||||
|
||||
# Test list plugins
|
||||
assert "list.find" in plugin_map
|
||||
assert "list.some" in plugin_map
|
||||
assert "list.every" in plugin_map
|
||||
assert "list.concat" in plugin_map
|
||||
assert "list.slice" in plugin_map
|
||||
assert "list.sort" in plugin_map
|
||||
assert "list.length" in plugin_map
|
||||
|
||||
# Test dict plugins
|
||||
assert "dict.get" in plugin_map
|
||||
assert "dict.set" in plugin_map
|
||||
assert "dict.merge" in plugin_map
|
||||
|
||||
# Test string plugins
|
||||
assert "string.concat" in plugin_map
|
||||
assert "string.split" in plugin_map
|
||||
assert "string.upper" in plugin_map
|
||||
assert "string.lower" in plugin_map
|
||||
|
||||
# Test math plugins
|
||||
assert "math.add" in plugin_map
|
||||
assert "math.subtract" in plugin_map
|
||||
assert "math.multiply" in plugin_map
|
||||
assert "math.divide" in plugin_map
|
||||
|
||||
# Test conversion plugins
|
||||
assert "convert.to_string" in plugin_map
|
||||
assert "convert.to_number" in plugin_map
|
||||
assert "convert.parse_json" in plugin_map
|
||||
assert "convert.to_json" in plugin_map
|
||||
|
||||
# Test control flow plugins
|
||||
assert "control.switch" in plugin_map
|
||||
|
||||
# Test variable plugins
|
||||
assert "var.get" in plugin_map
|
||||
assert "var.set" in plugin_map
|
||||
|
||||
# Test backend plugins
|
||||
assert "backend.load_metadata" in plugin_map
|
||||
assert "backend.load_messages" in plugin_map
|
||||
|
||||
|
||||
def test_logic_and_plugin():
|
||||
"""Test logic.and plugin."""
|
||||
plugin_map = load_plugin_map()
|
||||
registry = PluginRegistry(plugin_map)
|
||||
runtime = create_test_runtime()
|
||||
|
||||
plugin = registry.get("logic.and")
|
||||
assert plugin is not None
|
||||
|
||||
result = plugin(runtime, {"values": [True, True, True]})
|
||||
assert result["result"] is True
|
||||
|
||||
result = plugin(runtime, {"values": [True, False, True]})
|
||||
assert result["result"] is False
|
||||
|
||||
|
||||
def test_logic_or_plugin():
|
||||
"""Test logic.or plugin."""
|
||||
plugin_map = load_plugin_map()
|
||||
registry = PluginRegistry(plugin_map)
|
||||
runtime = create_test_runtime()
|
||||
|
||||
plugin = registry.get("logic.or")
|
||||
assert plugin is not None
|
||||
|
||||
result = plugin(runtime, {"values": [False, False, True]})
|
||||
assert result["result"] is True
|
||||
|
||||
result = plugin(runtime, {"values": [False, False, False]})
|
||||
assert result["result"] is False
|
||||
|
||||
|
||||
def test_logic_equals_plugin():
|
||||
"""Test logic.equals plugin."""
|
||||
plugin_map = load_plugin_map()
|
||||
registry = PluginRegistry(plugin_map)
|
||||
runtime = create_test_runtime()
|
||||
|
||||
plugin = registry.get("logic.equals")
|
||||
assert plugin is not None
|
||||
|
||||
result = plugin(runtime, {"a": 5, "b": 5})
|
||||
assert result["result"] is True
|
||||
|
||||
result = plugin(runtime, {"a": 5, "b": 10})
|
||||
assert result["result"] is False
|
||||
|
||||
|
||||
def test_math_add_plugin():
|
||||
"""Test math.add plugin."""
|
||||
plugin_map = load_plugin_map()
|
||||
registry = PluginRegistry(plugin_map)
|
||||
runtime = create_test_runtime()
|
||||
|
||||
plugin = registry.get("math.add")
|
||||
assert plugin is not None
|
||||
|
||||
result = plugin(runtime, {"numbers": [1, 2, 3, 4, 5]})
|
||||
assert result["result"] == 15
|
||||
|
||||
|
||||
def test_math_multiply_plugin():
|
||||
"""Test math.multiply plugin."""
|
||||
plugin_map = load_plugin_map()
|
||||
registry = PluginRegistry(plugin_map)
|
||||
runtime = create_test_runtime()
|
||||
|
||||
plugin = registry.get("math.multiply")
|
||||
assert plugin is not None
|
||||
|
||||
result = plugin(runtime, {"numbers": [2, 3, 4]})
|
||||
assert result["result"] == 24
|
||||
|
||||
|
||||
def test_string_concat_plugin():
|
||||
"""Test string.concat plugin."""
|
||||
plugin_map = load_plugin_map()
|
||||
registry = PluginRegistry(plugin_map)
|
||||
runtime = create_test_runtime()
|
||||
|
||||
plugin = registry.get("string.concat")
|
||||
assert plugin is not None
|
||||
|
||||
result = plugin(runtime, {"strings": ["Hello", "World"], "separator": " "})
|
||||
assert result["result"] == "Hello World"
|
||||
|
||||
|
||||
def test_string_upper_plugin():
|
||||
"""Test string.upper plugin."""
|
||||
plugin_map = load_plugin_map()
|
||||
registry = PluginRegistry(plugin_map)
|
||||
runtime = create_test_runtime()
|
||||
|
||||
plugin = registry.get("string.upper")
|
||||
assert plugin is not None
|
||||
|
||||
result = plugin(runtime, {"text": "hello"})
|
||||
assert result["result"] == "HELLO"
|
||||
|
||||
|
||||
def test_list_length_plugin():
|
||||
"""Test list.length plugin."""
|
||||
plugin_map = load_plugin_map()
|
||||
registry = PluginRegistry(plugin_map)
|
||||
runtime = create_test_runtime()
|
||||
|
||||
plugin = registry.get("list.length")
|
||||
assert plugin is not None
|
||||
|
||||
result = plugin(runtime, {"items": [1, 2, 3, 4, 5]})
|
||||
assert result["result"] == 5
|
||||
|
||||
|
||||
def test_list_concat_plugin():
|
||||
"""Test list.concat plugin."""
|
||||
plugin_map = load_plugin_map()
|
||||
registry = PluginRegistry(plugin_map)
|
||||
runtime = create_test_runtime()
|
||||
|
||||
plugin = registry.get("list.concat")
|
||||
assert plugin is not None
|
||||
|
||||
result = plugin(runtime, {"lists": [[1, 2], [3, 4], [5, 6]]})
|
||||
assert result["result"] == [1, 2, 3, 4, 5, 6]
|
||||
|
||||
|
||||
def test_dict_get_plugin():
|
||||
"""Test dict.get plugin."""
|
||||
plugin_map = load_plugin_map()
|
||||
registry = PluginRegistry(plugin_map)
|
||||
runtime = create_test_runtime()
|
||||
|
||||
plugin = registry.get("dict.get")
|
||||
assert plugin is not None
|
||||
|
||||
result = plugin(runtime, {"object": {"name": "John", "age": 30}, "key": "name"})
|
||||
assert result["result"] == "John"
|
||||
assert result["found"] is True
|
||||
|
||||
result = plugin(runtime, {"object": {"name": "John"}, "key": "missing", "default": "N/A"})
|
||||
assert result["result"] == "N/A"
|
||||
assert result["found"] is False
|
||||
|
||||
|
||||
def test_dict_set_plugin():
|
||||
"""Test dict.set plugin."""
|
||||
plugin_map = load_plugin_map()
|
||||
registry = PluginRegistry(plugin_map)
|
||||
runtime = create_test_runtime()
|
||||
|
||||
plugin = registry.get("dict.set")
|
||||
assert plugin is not None
|
||||
|
||||
result = plugin(runtime, {"object": {"a": 1}, "key": "b", "value": 2})
|
||||
assert result["result"] == {"a": 1, "b": 2}
|
||||
|
||||
|
||||
def test_var_get_set_plugin():
|
||||
"""Test var.get and var.set plugins."""
|
||||
plugin_map = load_plugin_map()
|
||||
registry = PluginRegistry(plugin_map)
|
||||
runtime = create_test_runtime()
|
||||
|
||||
set_plugin = registry.get("var.set")
|
||||
get_plugin = registry.get("var.get")
|
||||
|
||||
assert set_plugin is not None
|
||||
assert get_plugin is not None
|
||||
|
||||
# Set a variable
|
||||
set_result = set_plugin(runtime, {"key": "test_var", "value": 42})
|
||||
assert set_result["result"] == 42
|
||||
|
||||
# Get the variable
|
||||
get_result = get_plugin(runtime, {"key": "test_var"})
|
||||
assert get_result["result"] == 42
|
||||
assert get_result["exists"] is True
|
||||
|
||||
|
||||
def test_convert_to_json_and_parse():
|
||||
"""Test JSON conversion plugins."""
|
||||
plugin_map = load_plugin_map()
|
||||
registry = PluginRegistry(plugin_map)
|
||||
runtime = create_test_runtime()
|
||||
|
||||
to_json = registry.get("convert.to_json")
|
||||
parse_json = registry.get("convert.parse_json")
|
||||
|
||||
assert to_json is not None
|
||||
assert parse_json is not None
|
||||
|
||||
# Convert to JSON
|
||||
data = {"name": "Test", "value": 123}
|
||||
json_result = to_json(runtime, {"value": data})
|
||||
json_str = json_result["result"]
|
||||
|
||||
# Parse JSON back
|
||||
parse_result = parse_json(runtime, {"text": json_str})
|
||||
assert parse_result["result"] == data
|
||||
|
||||
|
||||
def test_convert_to_number():
|
||||
"""Test number conversion."""
|
||||
plugin_map = load_plugin_map()
|
||||
registry = PluginRegistry(plugin_map)
|
||||
runtime = create_test_runtime()
|
||||
|
||||
plugin = registry.get("convert.to_number")
|
||||
assert plugin is not None
|
||||
|
||||
result = plugin(runtime, {"value": "42"})
|
||||
assert result["result"] == 42
|
||||
|
||||
result = plugin(runtime, {"value": "3.14"})
|
||||
assert result["result"] == 3.14
|
||||
|
||||
|
||||
def test_control_switch():
|
||||
"""Test control.switch plugin."""
|
||||
plugin_map = load_plugin_map()
|
||||
registry = PluginRegistry(plugin_map)
|
||||
runtime = create_test_runtime()
|
||||
|
||||
plugin = registry.get("control.switch")
|
||||
assert plugin is not None
|
||||
|
||||
cases = {
|
||||
"option1": "Result 1",
|
||||
"option2": "Result 2",
|
||||
"option3": "Result 3"
|
||||
}
|
||||
|
||||
result = plugin(runtime, {"value": "option2", "cases": cases})
|
||||
assert result["result"] == "Result 2"
|
||||
assert result["matched"] is True
|
||||
|
||||
result = plugin(runtime, {"value": "unknown", "cases": cases, "default": "Default"})
|
||||
assert result["result"] == "Default"
|
||||
assert result["matched"] is False
|
||||
Reference in New Issue
Block a user