rpaforge-core 0.3.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.
- rpaforge_core-0.3.6/PKG-INFO +90 -0
- rpaforge_core-0.3.6/README.md +60 -0
- rpaforge_core-0.3.6/pyproject.toml +53 -0
- rpaforge_core-0.3.6/setup.cfg +4 -0
- rpaforge_core-0.3.6/src/rpaforge/__init__.py +23 -0
- rpaforge_core-0.3.6/src/rpaforge/bridge/__init__.py +57 -0
- rpaforge_core-0.3.6/src/rpaforge/bridge/__main__.py +8 -0
- rpaforge_core-0.3.6/src/rpaforge/bridge/events.py +308 -0
- rpaforge_core-0.3.6/src/rpaforge/bridge/handlers/__init__.py +180 -0
- rpaforge_core-0.3.6/src/rpaforge/bridge/handlers/codegen.py +302 -0
- rpaforge_core-0.3.6/src/rpaforge/bridge/handlers/debugger.py +176 -0
- rpaforge_core-0.3.6/src/rpaforge/bridge/handlers/desktopui_spy.py +182 -0
- rpaforge_core-0.3.6/src/rpaforge/bridge/handlers/lifecycle.py +350 -0
- rpaforge_core-0.3.6/src/rpaforge/bridge/handlers/shared.py +102 -0
- rpaforge_core-0.3.6/src/rpaforge/bridge/handlers/webui_spy.py +70 -0
- rpaforge_core-0.3.6/src/rpaforge/bridge/handlers.py +11 -0
- rpaforge_core-0.3.6/src/rpaforge/bridge/protocol.py +160 -0
- rpaforge_core-0.3.6/src/rpaforge/bridge/server.py +339 -0
- rpaforge_core-0.3.6/src/rpaforge/codegen/__init__.py +18 -0
- rpaforge_core-0.3.6/src/rpaforge/codegen/python_generator.py +897 -0
- rpaforge_core-0.3.6/src/rpaforge/core/__init__.py +47 -0
- rpaforge_core-0.3.6/src/rpaforge/core/activity.py +359 -0
- rpaforge_core-0.3.6/src/rpaforge/core/checkpoint.py +294 -0
- rpaforge_core-0.3.6/src/rpaforge/core/diagram_converter.py +293 -0
- rpaforge_core-0.3.6/src/rpaforge/core/execution.py +314 -0
- rpaforge_core-0.3.6/src/rpaforge/core/executor.py +754 -0
- rpaforge_core-0.3.6/src/rpaforge/core/interfaces.py +73 -0
- rpaforge_core-0.3.6/src/rpaforge/core/models.py +35 -0
- rpaforge_core-0.3.6/src/rpaforge/core/runner.py +538 -0
- rpaforge_core-0.3.6/src/rpaforge/core/safe_evaluator.py +328 -0
- rpaforge_core-0.3.6/src/rpaforge/core/subprocess_executor.py +221 -0
- rpaforge_core-0.3.6/src/rpaforge/core/validation.py +183 -0
- rpaforge_core-0.3.6/src/rpaforge/core/validator.py +498 -0
- rpaforge_core-0.3.6/src/rpaforge/engine/__init__.py +53 -0
- rpaforge_core-0.3.6/src/rpaforge/i18n.py +77 -0
- rpaforge_core-0.3.6/src/rpaforge/utils/__init__.py +12 -0
- rpaforge_core-0.3.6/src/rpaforge/utils/ipc.py +229 -0
- rpaforge_core-0.3.6/src/rpaforge/utils/translator.py +68 -0
- rpaforge_core-0.3.6/src/rpaforge/version.py +1 -0
- rpaforge_core-0.3.6/src/rpaforge_core.egg-info/PKG-INFO +90 -0
- rpaforge_core-0.3.6/src/rpaforge_core.egg-info/SOURCES.txt +57 -0
- rpaforge_core-0.3.6/src/rpaforge_core.egg-info/dependency_links.txt +1 -0
- rpaforge_core-0.3.6/src/rpaforge_core.egg-info/requires.txt +11 -0
- rpaforge_core-0.3.6/src/rpaforge_core.egg-info/top_level.txt +1 -0
- rpaforge_core-0.3.6/tests/test_bridge.py +265 -0
- rpaforge_core-0.3.6/tests/test_bridge_lifecycle.py +188 -0
- rpaforge_core-0.3.6/tests/test_bridge_server.py +449 -0
- rpaforge_core-0.3.6/tests/test_cancellation_integration.py +207 -0
- rpaforge_core-0.3.6/tests/test_checkpoint.py +419 -0
- rpaforge_core-0.3.6/tests/test_circuit_breaker.py +116 -0
- rpaforge_core-0.3.6/tests/test_codegen.py +764 -0
- rpaforge_core-0.3.6/tests/test_codegen_security.py +96 -0
- rpaforge_core-0.3.6/tests/test_debugger_integration.py +314 -0
- rpaforge_core-0.3.6/tests/test_diagram_converter.py +58 -0
- rpaforge_core-0.3.6/tests/test_engine.py +243 -0
- rpaforge_core-0.3.6/tests/test_safe_eval_security.py +21 -0
- rpaforge_core-0.3.6/tests/test_safe_evaluator.py +1014 -0
- rpaforge_core-0.3.6/tests/test_subprocess_executor.py +166 -0
- rpaforge_core-0.3.6/tests/test_validator.py +649 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rpaforge-core
|
|
3
|
+
Version: 0.3.6
|
|
4
|
+
Summary: Native Python execution engine
|
|
5
|
+
Author: RPAForge Contributors
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/chelslava/rpaforge
|
|
8
|
+
Project-URL: Repository, https://github.com/chelslava/rpaforge.git
|
|
9
|
+
Project-URL: Issues, https://github.com/chelslava/rpaforge/issues
|
|
10
|
+
Keywords: rpa,automation,debugger,execution-engine
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
Requires-Dist: psutil>=5.9.0
|
|
22
|
+
Provides-Extra: subprocess
|
|
23
|
+
Requires-Dist: psutil>=5.9; extra == "subprocess"
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
27
|
+
Requires-Dist: ruff>=0.15.0; extra == "dev"
|
|
28
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
29
|
+
Requires-Dist: psutil>=5.9; extra == "dev"
|
|
30
|
+
|
|
31
|
+
[🇷🇺 Русский](README.ru.md)
|
|
32
|
+
|
|
33
|
+
# RPAForge Core
|
|
34
|
+
|
|
35
|
+
[](https://badge.fury.io/py/rpaforge-core)
|
|
36
|
+
[](https://pypi.org/project/rpaforge-core/)
|
|
37
|
+
[](LICENSE)
|
|
38
|
+
|
|
39
|
+
Core engine for RPAForge — native Python execution with full debugging, recording, and IPC bridge capabilities.
|
|
40
|
+
|
|
41
|
+
## Installation
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install rpaforge-core
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Usage
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from rpaforge import StudioEngine
|
|
51
|
+
from rpaforge_libraries.DesktopUI import DesktopUI
|
|
52
|
+
|
|
53
|
+
engine = StudioEngine()
|
|
54
|
+
engine.executor.register_library("DesktopUI", DesktopUI())
|
|
55
|
+
|
|
56
|
+
builder = engine.create_process("Notepad Automation")
|
|
57
|
+
builder.add_task("Open and Type", [
|
|
58
|
+
("DesktopUI.Open Application", {"executable": "notepad.exe"}),
|
|
59
|
+
("DesktopUI.Wait For Window", {"title": "Notepad", "timeout": "10s"}),
|
|
60
|
+
("DesktopUI.Input Text", {"text": "Hello from RPAForge!"}),
|
|
61
|
+
("DesktopUI.Close Window", {}),
|
|
62
|
+
])
|
|
63
|
+
|
|
64
|
+
result = engine.run(builder.build())
|
|
65
|
+
print(f"Status: {result.status}")
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Features
|
|
69
|
+
|
|
70
|
+
- **Engine**: Native Python execution with topology validation and code generation
|
|
71
|
+
- **Debugger**: Breakpoints, step over/into/out, variable inspection, call stack
|
|
72
|
+
- **Recorder**: Record user actions to automation diagrams
|
|
73
|
+
- **IPC Bridge**: Asyncio JSON-RPC server for Electron ↔ Python communication
|
|
74
|
+
|
|
75
|
+
## Development
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Install in development mode
|
|
79
|
+
pip install -e .
|
|
80
|
+
|
|
81
|
+
# Run tests
|
|
82
|
+
pytest tests/ -v
|
|
83
|
+
|
|
84
|
+
# Format code
|
|
85
|
+
ruff format src/
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## License
|
|
89
|
+
|
|
90
|
+
Apache License 2.0
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
[🇷🇺 Русский](README.ru.md)
|
|
2
|
+
|
|
3
|
+
# RPAForge Core
|
|
4
|
+
|
|
5
|
+
[](https://badge.fury.io/py/rpaforge-core)
|
|
6
|
+
[](https://pypi.org/project/rpaforge-core/)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
Core engine for RPAForge — native Python execution with full debugging, recording, and IPC bridge capabilities.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install rpaforge-core
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from rpaforge import StudioEngine
|
|
21
|
+
from rpaforge_libraries.DesktopUI import DesktopUI
|
|
22
|
+
|
|
23
|
+
engine = StudioEngine()
|
|
24
|
+
engine.executor.register_library("DesktopUI", DesktopUI())
|
|
25
|
+
|
|
26
|
+
builder = engine.create_process("Notepad Automation")
|
|
27
|
+
builder.add_task("Open and Type", [
|
|
28
|
+
("DesktopUI.Open Application", {"executable": "notepad.exe"}),
|
|
29
|
+
("DesktopUI.Wait For Window", {"title": "Notepad", "timeout": "10s"}),
|
|
30
|
+
("DesktopUI.Input Text", {"text": "Hello from RPAForge!"}),
|
|
31
|
+
("DesktopUI.Close Window", {}),
|
|
32
|
+
])
|
|
33
|
+
|
|
34
|
+
result = engine.run(builder.build())
|
|
35
|
+
print(f"Status: {result.status}")
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
- **Engine**: Native Python execution with topology validation and code generation
|
|
41
|
+
- **Debugger**: Breakpoints, step over/into/out, variable inspection, call stack
|
|
42
|
+
- **Recorder**: Record user actions to automation diagrams
|
|
43
|
+
- **IPC Bridge**: Asyncio JSON-RPC server for Electron ↔ Python communication
|
|
44
|
+
|
|
45
|
+
## Development
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Install in development mode
|
|
49
|
+
pip install -e .
|
|
50
|
+
|
|
51
|
+
# Run tests
|
|
52
|
+
pytest tests/ -v
|
|
53
|
+
|
|
54
|
+
# Format code
|
|
55
|
+
ruff format src/
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## License
|
|
59
|
+
|
|
60
|
+
Apache License 2.0
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "rpaforge-core"
|
|
7
|
+
version = "0.3.6"
|
|
8
|
+
description = "Native Python execution engine"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "Apache-2.0"}
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "RPAForge Contributors"}
|
|
14
|
+
]
|
|
15
|
+
keywords = [
|
|
16
|
+
"rpa",
|
|
17
|
+
"automation",
|
|
18
|
+
"debugger",
|
|
19
|
+
"execution-engine",
|
|
20
|
+
]
|
|
21
|
+
classifiers = [
|
|
22
|
+
"Development Status :: 3 - Alpha",
|
|
23
|
+
"License :: OSI Approved :: Apache Software License",
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"Programming Language :: Python :: 3.10",
|
|
26
|
+
"Programming Language :: Python :: 3.11",
|
|
27
|
+
"Programming Language :: Python :: 3.12",
|
|
28
|
+
"Programming Language :: Python :: 3.13",
|
|
29
|
+
"Typing :: Typed",
|
|
30
|
+
]
|
|
31
|
+
dependencies = [
|
|
32
|
+
"psutil>=5.9.0",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[project.optional-dependencies]
|
|
36
|
+
subprocess = [
|
|
37
|
+
"psutil>=5.9",
|
|
38
|
+
]
|
|
39
|
+
dev = [
|
|
40
|
+
"pytest>=8.0",
|
|
41
|
+
"pytest-cov>=4.0",
|
|
42
|
+
"ruff>=0.15.0",
|
|
43
|
+
"mypy>=1.0",
|
|
44
|
+
"psutil>=5.9",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[project.urls]
|
|
48
|
+
Homepage = "https://github.com/chelslava/rpaforge"
|
|
49
|
+
Repository = "https://github.com/chelslava/rpaforge.git"
|
|
50
|
+
Issues = "https://github.com/chelslava/rpaforge/issues"
|
|
51
|
+
|
|
52
|
+
[tool.setuptools.packages.find]
|
|
53
|
+
where = ["src"]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""
|
|
2
|
+
RPAForge Core - Open Source RPA Studio Engine.
|
|
3
|
+
|
|
4
|
+
Native Python execution engine without Robot Framework dependencies.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from rpaforge.bridge import BridgeServer
|
|
8
|
+
from rpaforge.codegen import CodeGenerator
|
|
9
|
+
from rpaforge.core.runner import (
|
|
10
|
+
Breakpoint,
|
|
11
|
+
ProcessRunner,
|
|
12
|
+
RunnerState,
|
|
13
|
+
StudioEngine,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"StudioEngine",
|
|
18
|
+
"ProcessRunner",
|
|
19
|
+
"Breakpoint",
|
|
20
|
+
"RunnerState",
|
|
21
|
+
"BridgeServer",
|
|
22
|
+
"CodeGenerator",
|
|
23
|
+
]
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""
|
|
2
|
+
RPAForge Bridge Module.
|
|
3
|
+
|
|
4
|
+
IPC communication between Electron UI and Python Engine.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from rpaforge.bridge.events import (
|
|
10
|
+
BreakpointHitEvent,
|
|
11
|
+
BridgeEvent,
|
|
12
|
+
CallStackChangedEvent,
|
|
13
|
+
ErrorEvent,
|
|
14
|
+
EventType,
|
|
15
|
+
KeywordFinishedEvent,
|
|
16
|
+
KeywordStartedEvent,
|
|
17
|
+
LogEvent,
|
|
18
|
+
ProcessFinishedEvent,
|
|
19
|
+
ProcessPausedEvent,
|
|
20
|
+
ProcessResumedEvent,
|
|
21
|
+
ProcessStartedEvent,
|
|
22
|
+
VariablesChangedEvent,
|
|
23
|
+
)
|
|
24
|
+
from rpaforge.bridge.handlers import BridgeHandlers
|
|
25
|
+
from rpaforge.bridge.protocol import (
|
|
26
|
+
JSONRPCError,
|
|
27
|
+
JSONRPCErrorCode,
|
|
28
|
+
JSONRPCNotification,
|
|
29
|
+
JSONRPCRequest,
|
|
30
|
+
JSONRPCResponse,
|
|
31
|
+
parse_message,
|
|
32
|
+
)
|
|
33
|
+
from rpaforge.bridge.server import BridgeServer
|
|
34
|
+
|
|
35
|
+
__all__ = [
|
|
36
|
+
"BridgeServer",
|
|
37
|
+
"BridgeHandlers",
|
|
38
|
+
"BridgeEvent",
|
|
39
|
+
"EventType",
|
|
40
|
+
"LogEvent",
|
|
41
|
+
"BreakpointHitEvent",
|
|
42
|
+
"ProcessStartedEvent",
|
|
43
|
+
"ProcessFinishedEvent",
|
|
44
|
+
"ProcessPausedEvent",
|
|
45
|
+
"ProcessResumedEvent",
|
|
46
|
+
"VariablesChangedEvent",
|
|
47
|
+
"CallStackChangedEvent",
|
|
48
|
+
"KeywordStartedEvent",
|
|
49
|
+
"KeywordFinishedEvent",
|
|
50
|
+
"ErrorEvent",
|
|
51
|
+
"JSONRPCRequest",
|
|
52
|
+
"JSONRPCResponse",
|
|
53
|
+
"JSONRPCNotification",
|
|
54
|
+
"JSONRPCError",
|
|
55
|
+
"JSONRPCErrorCode",
|
|
56
|
+
"parse_message",
|
|
57
|
+
]
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
"""
|
|
2
|
+
RPAForge Bridge Events.
|
|
3
|
+
|
|
4
|
+
Event types for IPC communication between Python engine and UI.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from dataclasses import dataclass, field
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
from enum import Enum
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class EventType(str, Enum):
|
|
16
|
+
"""Types of events that can be emitted."""
|
|
17
|
+
|
|
18
|
+
LOG = "log"
|
|
19
|
+
BREAKPOINT_HIT = "breakpointHit"
|
|
20
|
+
PROCESS_STARTED = "processStarted"
|
|
21
|
+
PROCESS_FINISHED = "processFinished"
|
|
22
|
+
PROCESS_STOPPED = "processStopped"
|
|
23
|
+
PROCESS_PAUSED = "processPaused"
|
|
24
|
+
PROCESS_RESUMED = "processResumed"
|
|
25
|
+
VARIABLES_CHANGED = "variablesChanged"
|
|
26
|
+
CALL_STACK_CHANGED = "callStackChanged"
|
|
27
|
+
KEYWORD_STARTED = "keywordStarted"
|
|
28
|
+
KEYWORD_FINISHED = "keywordFinished"
|
|
29
|
+
ERROR = "error"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass
|
|
33
|
+
class BridgeEvent:
|
|
34
|
+
"""Base class for bridge events."""
|
|
35
|
+
|
|
36
|
+
timestamp: datetime = field(default_factory=datetime.now)
|
|
37
|
+
|
|
38
|
+
def to_dict(self) -> dict[str, Any]:
|
|
39
|
+
return {"type": self.event_type(), "timestamp": self.timestamp.isoformat()}
|
|
40
|
+
|
|
41
|
+
@classmethod
|
|
42
|
+
def event_type(cls) -> str:
|
|
43
|
+
"""Return the event type string."""
|
|
44
|
+
return "event"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass
|
|
48
|
+
class LogEvent(BridgeEvent):
|
|
49
|
+
"""Event for log messages."""
|
|
50
|
+
|
|
51
|
+
level: str = "info"
|
|
52
|
+
message: str = ""
|
|
53
|
+
source: str | None = None
|
|
54
|
+
run_id: str = ""
|
|
55
|
+
|
|
56
|
+
@classmethod
|
|
57
|
+
def event_type(cls) -> str:
|
|
58
|
+
return EventType.LOG.value
|
|
59
|
+
|
|
60
|
+
def to_dict(self) -> dict[str, Any]:
|
|
61
|
+
result = super().to_dict()
|
|
62
|
+
result.update(
|
|
63
|
+
{
|
|
64
|
+
"level": self.level,
|
|
65
|
+
"message": self.message,
|
|
66
|
+
"runId": self.run_id,
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
if self.source:
|
|
70
|
+
result["source"] = self.source
|
|
71
|
+
return result
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@dataclass
|
|
75
|
+
class BreakpointHitEvent(BridgeEvent):
|
|
76
|
+
"""Event when a breakpoint is hit."""
|
|
77
|
+
|
|
78
|
+
breakpoint_id: str = ""
|
|
79
|
+
file: str = ""
|
|
80
|
+
line: int = 0
|
|
81
|
+
condition: str | None = None
|
|
82
|
+
|
|
83
|
+
@classmethod
|
|
84
|
+
def event_type(cls) -> str:
|
|
85
|
+
return EventType.BREAKPOINT_HIT.value
|
|
86
|
+
|
|
87
|
+
def to_dict(self) -> dict[str, Any]:
|
|
88
|
+
result = super().to_dict()
|
|
89
|
+
result.update(
|
|
90
|
+
{
|
|
91
|
+
"breakpointId": self.breakpoint_id,
|
|
92
|
+
"file": self.file,
|
|
93
|
+
"line": self.line,
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
if self.condition:
|
|
97
|
+
result["condition"] = self.condition
|
|
98
|
+
return result
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@dataclass
|
|
102
|
+
class ProcessStartedEvent(BridgeEvent):
|
|
103
|
+
"""Event when a process starts."""
|
|
104
|
+
|
|
105
|
+
process_id: str = ""
|
|
106
|
+
name: str = ""
|
|
107
|
+
run_id: str = ""
|
|
108
|
+
|
|
109
|
+
@classmethod
|
|
110
|
+
def event_type(cls) -> str:
|
|
111
|
+
return EventType.PROCESS_STARTED.value
|
|
112
|
+
|
|
113
|
+
def to_dict(self) -> dict[str, Any]:
|
|
114
|
+
result = super().to_dict()
|
|
115
|
+
result.update(
|
|
116
|
+
{
|
|
117
|
+
"processId": self.process_id,
|
|
118
|
+
"name": self.name,
|
|
119
|
+
"runId": self.run_id,
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
return result
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@dataclass
|
|
126
|
+
class ProcessFinishedEvent(BridgeEvent):
|
|
127
|
+
"""Event when a process finishes."""
|
|
128
|
+
|
|
129
|
+
status: str = "pass"
|
|
130
|
+
duration: float = 0.0
|
|
131
|
+
message: str | None = None
|
|
132
|
+
|
|
133
|
+
@classmethod
|
|
134
|
+
def event_type(cls) -> str:
|
|
135
|
+
return EventType.PROCESS_FINISHED.value
|
|
136
|
+
|
|
137
|
+
def to_dict(self) -> dict[str, Any]:
|
|
138
|
+
result = super().to_dict()
|
|
139
|
+
result.update(
|
|
140
|
+
{
|
|
141
|
+
"status": self.status,
|
|
142
|
+
"duration": self.duration,
|
|
143
|
+
}
|
|
144
|
+
)
|
|
145
|
+
if self.message:
|
|
146
|
+
result["message"] = self.message
|
|
147
|
+
return result
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
@dataclass
|
|
151
|
+
class ProcessStoppedEvent(BridgeEvent):
|
|
152
|
+
"""Event when a process is stopped/cancelled by user."""
|
|
153
|
+
|
|
154
|
+
reason: str = "user"
|
|
155
|
+
|
|
156
|
+
@classmethod
|
|
157
|
+
def event_type(cls) -> str:
|
|
158
|
+
return EventType.PROCESS_STOPPED.value
|
|
159
|
+
|
|
160
|
+
def to_dict(self) -> dict[str, Any]:
|
|
161
|
+
result = super().to_dict()
|
|
162
|
+
result["reason"] = self.reason
|
|
163
|
+
return result
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@dataclass
|
|
167
|
+
class VariablesChangedEvent(BridgeEvent):
|
|
168
|
+
"""Event when variables change."""
|
|
169
|
+
|
|
170
|
+
variables: list[dict[str, Any]] = field(default_factory=list)
|
|
171
|
+
|
|
172
|
+
@classmethod
|
|
173
|
+
def event_type(cls) -> str:
|
|
174
|
+
return EventType.VARIABLES_CHANGED.value
|
|
175
|
+
|
|
176
|
+
def to_dict(self) -> dict[str, Any]:
|
|
177
|
+
result = super().to_dict()
|
|
178
|
+
result["variables"] = self.variables
|
|
179
|
+
return result
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
@dataclass
|
|
183
|
+
class CallStackChangedEvent(BridgeEvent):
|
|
184
|
+
"""Event when call stack changes."""
|
|
185
|
+
|
|
186
|
+
call_stack: list[dict[str, Any]] = field(default_factory=list)
|
|
187
|
+
|
|
188
|
+
@classmethod
|
|
189
|
+
def event_type(cls) -> str:
|
|
190
|
+
return EventType.CALL_STACK_CHANGED.value
|
|
191
|
+
|
|
192
|
+
def to_dict(self) -> dict[str, Any]:
|
|
193
|
+
result = super().to_dict()
|
|
194
|
+
result["callStack"] = self.call_stack
|
|
195
|
+
return result
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
@dataclass
|
|
199
|
+
class KeywordStartedEvent(BridgeEvent):
|
|
200
|
+
"""Event when a keyword starts."""
|
|
201
|
+
|
|
202
|
+
name: str = ""
|
|
203
|
+
file: str = ""
|
|
204
|
+
line: int = 0
|
|
205
|
+
args: list[Any] = field(default_factory=list)
|
|
206
|
+
|
|
207
|
+
@classmethod
|
|
208
|
+
def event_type(cls) -> str:
|
|
209
|
+
return EventType.KEYWORD_STARTED.value
|
|
210
|
+
|
|
211
|
+
def to_dict(self) -> dict[str, Any]:
|
|
212
|
+
result = super().to_dict()
|
|
213
|
+
result.update(
|
|
214
|
+
{
|
|
215
|
+
"name": self.name,
|
|
216
|
+
"file": self.file,
|
|
217
|
+
"line": self.line,
|
|
218
|
+
"args": self.args,
|
|
219
|
+
}
|
|
220
|
+
)
|
|
221
|
+
return result
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
@dataclass
|
|
225
|
+
class KeywordFinishedEvent(BridgeEvent):
|
|
226
|
+
"""Event when a keyword finishes."""
|
|
227
|
+
|
|
228
|
+
name: str = ""
|
|
229
|
+
status: str = "pass"
|
|
230
|
+
result: Any | None = None
|
|
231
|
+
|
|
232
|
+
@classmethod
|
|
233
|
+
def event_type(cls) -> str:
|
|
234
|
+
return EventType.KEYWORD_FINISHED.value
|
|
235
|
+
|
|
236
|
+
def to_dict(self) -> dict[str, Any]:
|
|
237
|
+
result = super().to_dict()
|
|
238
|
+
result.update(
|
|
239
|
+
{
|
|
240
|
+
"name": self.name,
|
|
241
|
+
"status": self.status,
|
|
242
|
+
}
|
|
243
|
+
)
|
|
244
|
+
if self.result is not None:
|
|
245
|
+
result["result"] = self.result
|
|
246
|
+
return result
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
@dataclass
|
|
250
|
+
class ErrorEvent(BridgeEvent):
|
|
251
|
+
"""Event for errors."""
|
|
252
|
+
|
|
253
|
+
code: int = 0
|
|
254
|
+
message: str = ""
|
|
255
|
+
details: str | None = None
|
|
256
|
+
|
|
257
|
+
@classmethod
|
|
258
|
+
def event_type(cls) -> str:
|
|
259
|
+
return EventType.ERROR.value
|
|
260
|
+
|
|
261
|
+
def to_dict(self) -> dict[str, Any]:
|
|
262
|
+
result = super().to_dict()
|
|
263
|
+
result.update(
|
|
264
|
+
{
|
|
265
|
+
"code": self.code,
|
|
266
|
+
"message": self.message,
|
|
267
|
+
}
|
|
268
|
+
)
|
|
269
|
+
if self.details:
|
|
270
|
+
result["details"] = self.details
|
|
271
|
+
return result
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
@dataclass
|
|
275
|
+
class ProcessPausedEvent(BridgeEvent):
|
|
276
|
+
"""Event when a process pauses at breakpoint or step."""
|
|
277
|
+
|
|
278
|
+
file: str | None = None
|
|
279
|
+
line: int | None = None
|
|
280
|
+
node_id: str | None = None
|
|
281
|
+
reason: str = "breakpoint"
|
|
282
|
+
|
|
283
|
+
@classmethod
|
|
284
|
+
def event_type(cls) -> str:
|
|
285
|
+
return EventType.PROCESS_PAUSED.value
|
|
286
|
+
|
|
287
|
+
def to_dict(self) -> dict[str, Any]:
|
|
288
|
+
result = super().to_dict()
|
|
289
|
+
result["reason"] = self.reason
|
|
290
|
+
if self.file is not None:
|
|
291
|
+
result["file"] = self.file
|
|
292
|
+
if self.line is not None:
|
|
293
|
+
result["line"] = self.line
|
|
294
|
+
if self.node_id is not None:
|
|
295
|
+
result["nodeId"] = self.node_id
|
|
296
|
+
return result
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
@dataclass
|
|
300
|
+
class ProcessResumedEvent(BridgeEvent):
|
|
301
|
+
"""Event when a process resumes from pause."""
|
|
302
|
+
|
|
303
|
+
@classmethod
|
|
304
|
+
def event_type(cls) -> str:
|
|
305
|
+
return EventType.PROCESS_RESUMED.value
|
|
306
|
+
|
|
307
|
+
def to_dict(self) -> dict[str, Any]:
|
|
308
|
+
return super().to_dict()
|