erdo 0.1.4__tar.gz → 0.1.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of erdo might be problematic. Click here for more details.

Files changed (69) hide show
  1. erdo-0.1.6/CLAUDE.md +246 -0
  2. {erdo-0.1.4 → erdo-0.1.6}/PKG-INFO +4 -1
  3. erdo-0.1.6/VERSION +1 -0
  4. {erdo-0.1.4 → erdo-0.1.6}/erdo/__init__.py +13 -13
  5. {erdo-0.1.4 → erdo-0.1.6}/erdo/_generated/actions/__init__.py +3 -1
  6. erdo-0.1.6/erdo/_generated/actions/analysis.py +179 -0
  7. {erdo-0.1.4 → erdo-0.1.6}/erdo/_generated/actions/bot.py +61 -5
  8. {erdo-0.1.4 → erdo-0.1.6}/erdo/_generated/actions/codeexec.py +53 -28
  9. {erdo-0.1.4 → erdo-0.1.6}/erdo/_generated/actions/llm.py +44 -5
  10. erdo-0.1.6/erdo/_generated/actions/memory.py +447 -0
  11. erdo-0.1.6/erdo/_generated/actions/pdfextractor.py +97 -0
  12. {erdo-0.1.4 → erdo-0.1.6}/erdo/_generated/actions/resource_definitions.py +114 -12
  13. erdo-0.1.6/erdo/_generated/actions/sqlexec.py +86 -0
  14. {erdo-0.1.4 → erdo-0.1.6}/erdo/_generated/actions/utils.py +178 -56
  15. {erdo-0.1.4 → erdo-0.1.6}/erdo/_generated/actions/webparser.py +15 -5
  16. {erdo-0.1.4 → erdo-0.1.6}/erdo/_generated/actions/websearch.py +15 -5
  17. {erdo-0.1.4 → erdo-0.1.6}/erdo/_generated/condition/__init__.py +137 -127
  18. {erdo-0.1.4 → erdo-0.1.6}/erdo/_generated/internal_actions.py +14 -2
  19. {erdo-0.1.4 → erdo-0.1.6}/erdo/_generated/types.py +92 -48
  20. {erdo-0.1.4 → erdo-0.1.6}/erdo/actions/__init__.py +8 -8
  21. erdo-0.1.6/erdo/bot_permissions.py +266 -0
  22. erdo-0.1.6/erdo/config/__init__.py +5 -0
  23. erdo-0.1.6/erdo/config/config.py +140 -0
  24. erdo-0.1.6/erdo/invoke/__init__.py +10 -0
  25. erdo-0.1.6/erdo/invoke/client.py +213 -0
  26. erdo-0.1.6/erdo/invoke/invoke.py +244 -0
  27. erdo-0.1.6/erdo/sync/__init__.py +17 -0
  28. erdo-0.1.6/erdo/sync/client.py +95 -0
  29. erdo-0.1.6/erdo/sync/extractor.py +482 -0
  30. erdo-0.1.6/erdo/sync/sync.py +327 -0
  31. {erdo-0.1.4 → erdo-0.1.6}/erdo/types.py +516 -18
  32. erdo-0.1.6/examples/bot_permissions_example.py +115 -0
  33. erdo-0.1.6/examples/simple_echo_agent.py +31 -0
  34. erdo-0.1.6/examples/test_agent.py +26 -0
  35. erdo-0.1.6/examples/test_echo_agent.py +39 -0
  36. {erdo-0.1.4 → erdo-0.1.6}/pyproject.toml +3 -0
  37. erdo-0.1.6/test_bot_permissions.py +50 -0
  38. erdo-0.1.6/uv.lock +1003 -0
  39. erdo-0.1.4/VERSION +0 -1
  40. erdo-0.1.4/erdo/_generated/actions/analysis.py +0 -67
  41. erdo-0.1.4/erdo/_generated/actions/memory.py +0 -252
  42. {erdo-0.1.4 → erdo-0.1.6}/.github/workflows/ci.yml +0 -0
  43. {erdo-0.1.4 → erdo-0.1.6}/.github/workflows/publish.yml +0 -0
  44. {erdo-0.1.4 → erdo-0.1.6}/.gitignore +0 -0
  45. {erdo-0.1.4 → erdo-0.1.6}/LICENSE +0 -0
  46. {erdo-0.1.4 → erdo-0.1.6}/MANIFEST.in +0 -0
  47. {erdo-0.1.4 → erdo-0.1.6}/PYPI_SETUP.md +0 -0
  48. {erdo-0.1.4 → erdo-0.1.6}/README.md +0 -0
  49. {erdo-0.1.4 → erdo-0.1.6}/erdo/_generated/__init__.py +0 -0
  50. {erdo-0.1.4 → erdo-0.1.6}/erdo/_generated/internal.py +0 -0
  51. {erdo-0.1.4 → erdo-0.1.6}/erdo/_generated/parameters.py +0 -0
  52. {erdo-0.1.4 → erdo-0.1.6}/erdo/_generated/secrets.py +0 -0
  53. {erdo-0.1.4 → erdo-0.1.6}/erdo/_generated/template_functions.py +0 -0
  54. {erdo-0.1.4 → erdo-0.1.6}/erdo/cli_entry.py +0 -0
  55. {erdo-0.1.4 → erdo-0.1.6}/erdo/conditions/__init__.py +0 -0
  56. {erdo-0.1.4 → erdo-0.1.6}/erdo/install_cli.py +0 -0
  57. {erdo-0.1.4 → erdo-0.1.6}/erdo/integrations.py +0 -0
  58. {erdo-0.1.4 → erdo-0.1.6}/erdo/py.typed +0 -0
  59. {erdo-0.1.4 → erdo-0.1.6}/erdo/state.py +0 -0
  60. {erdo-0.1.4 → erdo-0.1.6}/erdo/template.py +0 -0
  61. {erdo-0.1.4 → erdo-0.1.6}/examples/agent_centric_example.py +0 -0
  62. {erdo-0.1.4 → erdo-0.1.6}/examples/analysis_files/analysis_result.json +0 -0
  63. {erdo-0.1.4 → erdo-0.1.6}/examples/analysis_files/analyze.py +0 -0
  64. {erdo-0.1.4 → erdo-0.1.6}/examples/analysis_files/utils.py +0 -0
  65. {erdo-0.1.4 → erdo-0.1.6}/examples/state_example.py +0 -0
  66. {erdo-0.1.4 → erdo-0.1.6}/examples/test_data.json +0 -0
  67. {erdo-0.1.4 → erdo-0.1.6}/setup.py +0 -0
  68. {erdo-0.1.4 → erdo-0.1.6}/tests/__init__.py +0 -0
  69. {erdo-0.1.4 → erdo-0.1.6}/tests/test_basic.py +0 -0
erdo-0.1.6/CLAUDE.md ADDED
@@ -0,0 +1,246 @@
1
+ # Erdo Python SDK Development
2
+
3
+ This is the Python SDK for Erdo, providing the API for defining AI agents, steps, and actions.
4
+
5
+ **📚 Critical Documentation:**
6
+ - **[../SDK_DEVELOPMENT.md](../SDK_DEVELOPMENT.md)** - **READ THIS FIRST** - Virtual environment gotchas, testing changes end-to-end, debugging data flow issues
7
+
8
+ ## Quick Start
9
+
10
+ ### After Making Changes
11
+
12
+ **CRITICAL**: After modifying the SDK, you MUST update all virtual environments that use it:
13
+
14
+ ```bash
15
+ # Update the SDK's own venv
16
+ cd erdo-python-sdk
17
+ uv pip install -e .
18
+
19
+ # Update the agents venv (used by CLI)
20
+ cd ../erdo-agents
21
+ uv pip install -e ../erdo-python-sdk
22
+
23
+ # Verify the correct version is loaded
24
+ uv run python3 -c "import erdo; print(erdo.__file__)"
25
+ # Should show: /Users/niall/work/erdo/erdo-python-sdk/erdo/__init__.py
26
+ # NOT: erdo-agents/.venv/lib/python3.XX/site-packages/erdo/__init__.py
27
+ ```
28
+
29
+ **Why this matters**: The CLI uses `uv run python3` which runs in the `erdo-agents/.venv` virtual environment. If you don't update the venv, the CLI will use the old published PyPI version of the SDK, not your local changes.
30
+
31
+ ### Testing Your Changes
32
+
33
+ 1. **Test Python SDK directly**:
34
+ ```bash
35
+ cd erdo-python-sdk
36
+ uv run python3 -c "
37
+ from erdo import Agent
38
+ from erdo.actions import utils
39
+ agent = Agent(key='test.test', name='Test', description='Test')
40
+ step = agent.step(utils.echo(data='hello'))
41
+ print(step.to_dict())
42
+ "
43
+ ```
44
+
45
+ 2. **Test CLI integration**:
46
+ ```bash
47
+ cd ../erdo-cli
48
+ ./erdo test /path/to/test_agent.py
49
+ ./erdo sync-agent /path/to/test_agent.py --dry-run
50
+ ```
51
+
52
+ 3. **Test backend integration**:
53
+ ```bash
54
+ # Sync to a running backend and check logs
55
+ ./erdo sync-agent /path/to/test_agent.py
56
+ ```
57
+
58
+ ## Project Structure
59
+
60
+ ```
61
+ erdo-python-sdk/
62
+ ├── erdo/
63
+ │ ├── __init__.py # Main exports (Agent, Step, etc.)
64
+ │ ├── types.py # Core types (Step, Agent, StepMetadata, etc.)
65
+ │ ├── actions/ # Action modules (utils, codeexec, llm, etc.)
66
+ │ └── _generated/ # Generated types (DO NOT EDIT MANUALLY)
67
+ │ └── types.py # Run 'erdo gen-client' to regenerate
68
+ ├── tests/ # Unit tests
69
+ └── pyproject.toml # Package configuration
70
+ ```
71
+
72
+ ## Key Files
73
+
74
+ ### `erdo/types.py`
75
+ Contains the core SDK types:
76
+ - `Agent` - Top-level agent definition
77
+ - `Step` - Individual workflow step
78
+ - `StepMetadata` - Base class for step configuration
79
+ - `ResultHandler` - Result handler configuration
80
+ - Enums: `OutputVisibility`, `OutputContentType`, `ParameterHydrationBehaviour`
81
+
82
+ **Important**: When adding or modifying fields:
83
+ 1. Update the Pydantic model definition
84
+ 2. Update the `to_dict()` method if custom serialization is needed
85
+ 3. Filter out None values for optional fields with defaults
86
+
87
+ ### `erdo/_generated/types.py`
88
+ Auto-generated from the OpenAPI schema. **DO NOT EDIT MANUALLY**.
89
+
90
+ To regenerate:
91
+ ```bash
92
+ cd ../erdo-cli
93
+ ./erdo gen-client
94
+ ```
95
+
96
+ ## Important Concepts
97
+
98
+ ### Using step_metadata in Result Handlers
99
+
100
+ When creating steps in result handlers via `.on()`, you can configure step properties using `step_metadata`:
101
+
102
+ ```python
103
+ step.on(IsSuccess(),
104
+ utils.parse_json(
105
+ json_data="{{output}}",
106
+ step_metadata=StepMetadata(
107
+ key="parse_result",
108
+ output_behavior={"data": OutputBehaviorType.MERGE}
109
+ )
110
+ )
111
+ )
112
+ ```
113
+
114
+ **How it works**:
115
+ 1. Action param classes (EchoParams, ParseJsonParams, etc.) have a `step_metadata` field
116
+ 2. When passed to an action, the metadata is stored on the action object
117
+ 3. `Step.on()` extracts the metadata and merges it into the Step configuration
118
+ 4. The `_extract_step_config_from_action()` helper handles the extraction
119
+
120
+ **Important**: The `step_metadata` parameter is specifically for use in action calls. It allows you to configure step properties (key, output_behavior, execution_mode, visibility, etc.) when the step is created from an action.
121
+
122
+ ### Field Naming: American vs British Spelling
123
+
124
+ The Python SDK uses American spelling (`output_behavior`) but the Go backend expects British spelling (`output_behaviour`). The `Step.to_dict()` method automatically handles this conversion during serialization:
125
+
126
+ ```python
127
+ # In Step.to_dict():
128
+ if "output_behavior" in result:
129
+ result["output_behaviour"] = result.pop("output_behavior")
130
+ ```
131
+
132
+ This ensures agents sync correctly to the backend.
133
+
134
+ ## Common Development Tasks
135
+
136
+ ### Adding a New Field to Step
137
+
138
+ Example: Adding a new optional field `my_field`:
139
+
140
+ 1. **Update `types.py`**:
141
+ ```python
142
+ class StepMetadata(BaseModel):
143
+ # ... existing fields ...
144
+ my_field: Optional[str] = None
145
+ ```
146
+
147
+ 2. **Update `to_dict()` method** (if the field should be omitted when None):
148
+ ```python
149
+ def to_dict(self) -> Dict[str, Any]:
150
+ result = self.model_dump(exclude={'agent', 'result_handler', 'action', 'depends_on'})
151
+
152
+ # Filter out None optional fields
153
+ if result.get("my_field") is None:
154
+ result.pop("my_field", None)
155
+
156
+ return result
157
+ ```
158
+
159
+ 3. **Update the backend**:
160
+ - Add to `erdo-common/types/bot.go` - `Step` struct
161
+ - Add to `erdo/backend/bot/db/migrations/` - Database migration
162
+ - Run `sqlc generate` in backend
163
+
164
+ 4. **Test**:
165
+ ```bash
166
+ # Update venvs
167
+ cd erdo-python-sdk && uv pip install -e .
168
+ cd ../erdo-agents && uv pip install -e ../erdo-python-sdk
169
+
170
+ # Test
171
+ cd ../erdo-cli
172
+ ./erdo test /path/to/test_agent.py
173
+ ```
174
+
175
+ ### Changing Field Types
176
+
177
+ Example: Changing from `field: SomeEnum = SomeEnum.NONE` to `field: Optional[SomeEnum] = None`:
178
+
179
+ **See [../SDK_DEVELOPMENT.md](../SDK_DEVELOPMENT.md#type-changes-checklist)** for the complete checklist.
180
+
181
+ Key steps:
182
+ 1. Change Python SDK type definition
183
+ 2. Update `to_dict()` to filter None values
184
+ 3. Update Go common types (value → pointer)
185
+ 4. Update Go backend code handling the field
186
+ 5. Update CLI export/sync code
187
+ 6. Update all venvs
188
+ 7. Test end-to-end
189
+
190
+ ## Debugging
191
+
192
+ ### Virtual Environment Issues
193
+
194
+ **Problem**: Changes not appearing when testing
195
+
196
+ ```bash
197
+ # Check which SDK is loaded
198
+ uv run python3 -c "import erdo; print(erdo.__file__)"
199
+
200
+ # If it shows .venv/lib/python3.XX/site-packages/erdo
201
+ # Then reinstall in editable mode:
202
+ uv pip install -e /Users/niall/work/erdo/erdo-python-sdk
203
+ ```
204
+
205
+ ### Field Serialization Issues
206
+
207
+ **Problem**: Field showing wrong value in database
208
+
209
+ ```python
210
+ # Debug the to_dict() output
211
+ from erdo import Agent
212
+ from erdo.actions import utils
213
+ agent = Agent(key='test.test', name='Test', description='Test')
214
+ step = agent.step(utils.echo(data='hello'))
215
+
216
+ # Check attribute
217
+ print(f"step.my_field: {step.my_field}")
218
+
219
+ # Check model_dump
220
+ dump = step.model_dump(exclude={'agent', 'action'})
221
+ print(f"model_dump: {dump.get('my_field')}")
222
+
223
+ # Check to_dict
224
+ step_dict = step.to_dict()
225
+ print(f"to_dict: {'my_field' in step_dict}")
226
+ ```
227
+
228
+ ## Testing
229
+
230
+ ```bash
231
+ # Run unit tests
232
+ cd erdo-python-sdk
233
+ uv run pytest tests/
234
+
235
+ # Run specific test
236
+ uv run pytest tests/test_types.py::test_step_creation
237
+
238
+ # Test import
239
+ uv run python3 -c "from erdo import Agent; print('OK')"
240
+ ```
241
+
242
+ ## Related Documentation
243
+
244
+ - [../SDK_DEVELOPMENT.md](../SDK_DEVELOPMENT.md) - Comprehensive guide for SDK development
245
+ - [../erdo/CLAUDE.md](../erdo/CLAUDE.md) - Backend development guide
246
+ - [../erdo-cli/CLAUDE.md](../erdo-cli/CLAUDE.md) - CLI development guide
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: erdo
3
- Version: 0.1.4
3
+ Version: 0.1.6
4
4
  Summary: Python SDK for building workflow automation agents with Erdo
5
5
  Project-URL: Homepage, https://erdo.ai
6
6
  Project-URL: Documentation, https://docs.erdo.ai
@@ -23,6 +23,7 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
23
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
24
  Requires-Python: >=3.9
25
25
  Requires-Dist: pydantic>=2.0.0
26
+ Requires-Dist: requests>=2.31.0
26
27
  Requires-Dist: typing-extensions>=4.0.0
27
28
  Provides-Extra: dev
28
29
  Requires-Dist: black>=23.0.0; extra == 'dev'
@@ -31,6 +32,8 @@ Requires-Dist: isort>=5.0.0; extra == 'dev'
31
32
  Requires-Dist: mypy>=1.0.0; extra == 'dev'
32
33
  Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
33
34
  Requires-Dist: pytest>=7.0.0; extra == 'dev'
35
+ Requires-Dist: types-pyyaml>=6.0.0; extra == 'dev'
36
+ Requires-Dist: types-requests>=2.31.0; extra == 'dev'
34
37
  Description-Content-Type: text/markdown
35
38
 
36
39
  # Erdo Agent SDK
erdo-0.1.6/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.6
@@ -4,32 +4,32 @@
4
4
 
5
5
  # Import all condition functions from generated condition module
6
6
  from ._generated.condition import * # noqa: F403,F401
7
- from ._generated.condition import __all__ as condition_all
8
7
 
9
- # Import all generated types first
8
+ # Import all generated types automatically
10
9
  from ._generated.types import * # noqa: F403,F401
11
- from ._generated.types import __all__ as generated_all
12
10
 
13
11
  # Import state object for template support
14
12
  from .state import state # noqa: F401
15
13
 
16
- # Import all handwritten SDK classes last (override generated ones)
17
- from .types import * # noqa: F403,F401 # type: ignore[assignment]
18
- from .types import __all__ as handwritten_all
14
+ # Import all handwritten SDK classes automatically
15
+ from .types import * # noqa: F403,F401
19
16
 
20
17
  __version__ = "0.1.0"
21
18
 
22
- # Build __all__ dynamically by combining all available types
23
- __all__ = []
19
+ # Add all condition functions automatically
20
+ from ._generated.condition import __all__ as condition_all # noqa: E402
24
21
 
25
- # Add generated types first
26
- __all__.extend(generated_all)
22
+ # Add all generated types automatically
23
+ from ._generated.types import __all__ as generated_all # noqa: E402
27
24
 
28
- # Add all condition functions
29
- __all__.extend(condition_all)
25
+ # Add handwritten SDK classes
26
+ from .types import __all__ as handwritten_all # noqa: E402
30
27
 
31
- # Add handwritten SDK classes (may override generated ones in __all__)
28
+ # Build __all__ dynamically by combining all available types
29
+ __all__ = []
32
30
  __all__.extend(handwritten_all)
31
+ __all__.extend(generated_all)
32
+ __all__.extend(condition_all)
33
33
 
34
34
  # Add state to __all__ for explicit import
35
35
  __all__.append("state")
@@ -16,17 +16,19 @@ from . import codeexec # noqa: F401
16
16
  from . import llm # noqa: F401
17
17
  from . import memory # noqa: F401
18
18
  from . import resource_definitions # noqa: F401
19
+ from . import sqlexec # noqa: F401
19
20
  from . import utils # noqa: F401
20
21
  from . import webparser # noqa: F401
21
22
  from . import websearch # noqa: F401
22
- from .analysis import * # noqa: F403,F401
23
23
 
24
24
  # Import all functions from service modules
25
+ from .analysis import * # noqa: F403,F401
25
26
  from .bot import * # noqa: F403,F401
26
27
  from .codeexec import * # noqa: F403,F401
27
28
  from .llm import * # noqa: F403,F401
28
29
  from .memory import * # noqa: F403,F401
29
30
  from .resource_definitions import * # noqa: F403,F401
31
+ from .sqlexec import * # noqa: F403,F401
30
32
  from .utils import * # noqa: F403,F401
31
33
  from .webparser import * # noqa: F403,F401
32
34
  from .websearch import * # noqa: F403,F401
@@ -0,0 +1,179 @@
1
+ """
2
+ Analysis actions for creating and managing data analysis service functions.
3
+ Auto-generated - DO NOT EDIT.
4
+
5
+ Provides type-safe action definitions for analysis service.
6
+ Actual execution happens in the Go backend after syncing.
7
+ """
8
+
9
+ from typing import Any, List, Optional, Union
10
+
11
+ from pydantic import BaseModel
12
+
13
+ from erdo.template import TemplateString
14
+
15
+
16
+ class BaseActionParams(BaseModel):
17
+ """Base class for all action parameter classes.
18
+
19
+ Provides common fields that all actions support:
20
+ - name: The action type identifier
21
+ - step_metadata: Optional configuration for the step created from this action
22
+ """
23
+
24
+ name: str
25
+ step_metadata: Optional[Any] = None
26
+
27
+
28
+ class CreateAnalysisParams(BaseActionParams):
29
+ """Create an analysis for a dataset, resource, or dataset-resource combination parameters"""
30
+
31
+ name: str = "analysis.create_analysis" # Action type for roundtrip compatibility
32
+ analysis: Optional[Any] = None # analysis parameter
33
+ dataset_id: Optional[Union[str, TemplateString]] = None # dataset_id parameter
34
+ resource_id: Optional[Union[str, TemplateString]] = None # resource_id parameter
35
+
36
+
37
+ class AnalyzeCsvParams(BaseActionParams):
38
+ """Analyze CSV file using Go-based CSV analyzer (fast, no Python needed) parameters"""
39
+
40
+ name: str = "analysis.analyze_csv" # Action type for roundtrip compatibility
41
+ file: Optional[Any] = None # file parameter
42
+ columns: Optional[Any] = None # columns parameter
43
+ rows: Optional[Any] = None # rows parameter
44
+ encryption_key: Optional[Union[str, TemplateString]] = (
45
+ None # encryption_key parameter
46
+ )
47
+
48
+
49
+ class AnalyzeExcelParams(BaseActionParams):
50
+ """Analyze Excel file using Go-based Excel analyzer (fast, no Python needed) parameters"""
51
+
52
+ name: str = "analysis.analyze_excel" # Action type for roundtrip compatibility
53
+ file: Optional[Any] = None # file parameter
54
+ encryption_key: Optional[Union[str, TemplateString]] = (
55
+ None # encryption_key parameter
56
+ )
57
+
58
+
59
+ class CreateAnalysisResult(BaseModel):
60
+ """Create an analysis for a dataset, resource, or dataset-resource combination result type
61
+
62
+ Result schema for analysis.create_analysis action.
63
+ """
64
+
65
+ analysis: Any
66
+ insights: Optional[List[str]]
67
+ recommendations: Optional[List[str]]
68
+
69
+
70
+ class AnalyzeCsvResult(BaseModel):
71
+ """Analyze CSV file using Go-based CSV analyzer (fast, no Python needed) result type
72
+
73
+ Result schema for analysis.analyze_csv action.
74
+ """
75
+
76
+ summary: str
77
+ details: Any
78
+ dataset_file_name: str
79
+
80
+
81
+ class AnalyzeExcelResult(BaseModel):
82
+ """Analyze Excel file using Go-based Excel analyzer (fast, no Python needed) result type
83
+
84
+ Result schema for analysis.analyze_excel action.
85
+ """
86
+
87
+ summary: str
88
+ details: Any
89
+ dataset_file_name: str
90
+
91
+
92
+ def create_analysis(
93
+ analysis: Optional[Any] = None,
94
+ dataset_id: Optional[Union[str, TemplateString]] = None,
95
+ resource_id: Optional[Union[str, TemplateString]] = None,
96
+ **params: Any,
97
+ ) -> CreateAnalysisParams:
98
+ """Create an analysis for a dataset, resource, or dataset-resource combination
99
+
100
+ Args:
101
+ analysis: analysis parameter
102
+ dataset_id: dataset_id parameter
103
+ resource_id: resource_id parameter
104
+
105
+ Returns:
106
+ CreateAnalysisParams: Type-safe parameter object
107
+ """
108
+ param_dict = {
109
+ "analysis": analysis,
110
+ "dataset_id": dataset_id,
111
+ "resource_id": resource_id,
112
+ }
113
+ # Remove None values for optional parameters
114
+ param_dict = {k: v for k, v in param_dict.items() if v is not None}
115
+ param_dict.update(params)
116
+ params_obj = CreateAnalysisParams(**param_dict)
117
+ return params_obj
118
+
119
+
120
+ def analyze_csv(
121
+ file: Optional[Any] = None,
122
+ columns: Optional[Any] = None,
123
+ rows: Optional[Any] = None,
124
+ encryption_key: Optional[Union[str, TemplateString]] = None,
125
+ **params: Any,
126
+ ) -> AnalyzeCsvParams:
127
+ """Analyze CSV file using Go-based CSV analyzer (fast, no Python needed)
128
+
129
+ Args:
130
+ file: file parameter
131
+ columns: columns parameter
132
+ rows: rows parameter
133
+ encryption_key: encryption_key parameter
134
+
135
+ Returns:
136
+ AnalyzeCsvParams: Type-safe parameter object
137
+ """
138
+ param_dict = {
139
+ "file": file,
140
+ "columns": columns,
141
+ "rows": rows,
142
+ "encryption_key": encryption_key,
143
+ }
144
+ # Remove None values for optional parameters
145
+ param_dict = {k: v for k, v in param_dict.items() if v is not None}
146
+ param_dict.update(params)
147
+ params_obj = AnalyzeCsvParams(**param_dict)
148
+ return params_obj
149
+
150
+
151
+ def analyze_excel(
152
+ file: Optional[Any] = None,
153
+ encryption_key: Optional[Union[str, TemplateString]] = None,
154
+ **params: Any,
155
+ ) -> AnalyzeExcelParams:
156
+ """Analyze Excel file using Go-based Excel analyzer (fast, no Python needed)
157
+
158
+ Args:
159
+ file: file parameter
160
+ encryption_key: encryption_key parameter
161
+
162
+ Returns:
163
+ AnalyzeExcelParams: Type-safe parameter object
164
+ """
165
+ param_dict = {
166
+ "file": file,
167
+ "encryption_key": encryption_key,
168
+ }
169
+ # Remove None values for optional parameters
170
+ param_dict = {k: v for k, v in param_dict.items() if v is not None}
171
+ param_dict.update(params)
172
+ params_obj = AnalyzeExcelParams(**param_dict)
173
+ return params_obj
174
+
175
+
176
+ # Associate parameter classes with their result types
177
+ CreateAnalysisParams._result = CreateAnalysisResult
178
+ AnalyzeCsvParams._result = AnalyzeCsvResult
179
+ AnalyzeExcelParams._result = AnalyzeExcelResult
@@ -17,10 +17,50 @@ from erdo.template import TemplateString
17
17
  from erdo.types import StepMetadata
18
18
 
19
19
 
20
- class InvokeParams(BaseModel):
20
+ class InvokeResult(BaseModel):
21
+ """Bot invoke result type
22
+
23
+ Result schema for bot.invoke action.
24
+ """
25
+
26
+ result: Any # The bot invocation result
27
+ messages: list # Messages from the bot invocation
28
+ resources: list # Resources created/used during invocation
29
+ final_state: Any # Final state after invocation
30
+
31
+
32
+ class AskResult(BaseModel):
33
+ """Bot ask result type
34
+
35
+ Result schema for bot.ask action.
36
+ """
37
+
38
+ success: bool # Whether the question was successfully processed
39
+ response: Optional[str] = None # The bot's response to the question
40
+ bot_id: Optional[str] = None # ID of the bot that answered
41
+ invocation_id: Optional[str] = None # ID of the invocation
42
+ error: Optional[str] = None # Error message if ask failed
43
+
44
+
45
+ class BaseActionParams(BaseModel):
46
+ """Base class for all action parameter classes.
47
+
48
+ Provides common fields that all actions support:
49
+ - name: The action type identifier
50
+ - step_metadata: Optional configuration for the step created from this action
51
+ """
52
+
53
+ name: str
54
+ step_metadata: Optional[Any] = None
55
+
56
+
57
+ class InvokeParams(BaseActionParams):
21
58
  """Invoke a bot with specified parameters and return the result parameters"""
22
59
 
23
60
  name: str = "bot.invoke" # Action type for roundtrip compatibility
61
+ bot_key: Optional[Union[str, TemplateString]] = (
62
+ None # bot_key parameter (unique bot identifier like "erdo.security-checker")
63
+ )
24
64
  bot_name: Optional[Union[str, TemplateString]] = (
25
65
  None # bot_name parameter (backend expects this, not bot_id)
26
66
  )
@@ -38,7 +78,7 @@ class InvokeParams(BaseModel):
38
78
  )
39
79
 
40
80
 
41
- class AskParams(BaseModel):
81
+ class AskParams(BaseActionParams):
42
82
  """Ask a bot a question and get a response parameters"""
43
83
 
44
84
  name: str = "bot.ask" # Action type for roundtrip compatibility
@@ -51,6 +91,7 @@ class AskParams(BaseModel):
51
91
 
52
92
 
53
93
  def invoke(
94
+ bot_key: Optional[Union[str, TemplateString]] = None,
54
95
  bot_name: Optional[Union[str, TemplateString]] = None,
55
96
  parameters: Optional[Union[Dict[str, Any], TemplateString]] = None,
56
97
  bot_output_visibility_behaviour: Optional[Union[str, TemplateString]] = None,
@@ -61,11 +102,12 @@ def invoke(
61
102
  ) -> InvokeParams:
62
103
  """Invoke a bot with specified parameters and return the result
63
104
 
64
- The bot.invoke action expects bot_name (not bot_id) as the parameter.
65
- The backend will look up the bot by name and convert to bot_id internally.
105
+ The bot.invoke action expects bot_key or bot_name as the parameter.
106
+ The backend will look up the bot and convert to bot_id internally.
66
107
 
67
108
  Args:
68
- bot_name: Name of the bot to invoke
109
+ bot_key: Unique key of the bot to invoke (e.g., "erdo.security-checker")
110
+ bot_name: Name of the bot to invoke (alternative to bot_key)
69
111
  parameters: Parameters to pass to the bot
70
112
  bot_output_visibility_behaviour: Output visibility behaviour
71
113
  transparent: Whether the invocation is transparent
@@ -75,6 +117,7 @@ def invoke(
75
117
  InvokeParams: Type-safe parameter object
76
118
  """
77
119
  params_dict = {
120
+ "bot_key": bot_key,
78
121
  "bot_name": bot_name,
79
122
  "parameters": parameters,
80
123
  "bot_output_visibility_behaviour": bot_output_visibility_behaviour,
@@ -86,6 +129,10 @@ def invoke(
86
129
  params_dict = {k: v for k, v in params_dict.items() if v is not None}
87
130
  params_dict.update(params)
88
131
 
132
+ # Include step_metadata in params_dict since it's a field on BaseActionParams
133
+ if step_metadata is not None:
134
+ params_dict["step_metadata"] = step_metadata
135
+
89
136
  # Use normal constructor for proper validation
90
137
  return InvokeParams(**params_dict)
91
138
 
@@ -120,5 +167,14 @@ def ask(
120
167
  params_dict = {k: v for k, v in params_dict.items() if v is not None}
121
168
  params_dict.update(params)
122
169
 
170
+ # Include step_metadata in params_dict since it's a field on BaseActionParams
171
+ if step_metadata is not None:
172
+ params_dict["step_metadata"] = step_metadata
173
+
123
174
  # Use normal constructor for proper validation
124
175
  return AskParams(**params_dict)
176
+
177
+
178
+ # Associate parameter classes with their result types
179
+ InvokeParams._result = InvokeResult
180
+ AskParams._result = AskResult