rpaforge-core 0.3.0__py3-none-any.whl

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/__init__.py ADDED
@@ -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,8 @@
1
+ """RPAForge Bridge Server module."""
2
+
3
+ from rpaforge.bridge.server import main
4
+
5
+ if __name__ == "__main__":
6
+ import asyncio
7
+
8
+ asyncio.run(main())
@@ -0,0 +1,304 @@
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
+
55
+ @classmethod
56
+ def event_type(cls) -> str:
57
+ return EventType.LOG.value
58
+
59
+ def to_dict(self) -> dict[str, Any]:
60
+ result = super().to_dict()
61
+ result.update(
62
+ {
63
+ "level": self.level,
64
+ "message": self.message,
65
+ }
66
+ )
67
+ if self.source:
68
+ result["source"] = self.source
69
+ return result
70
+
71
+
72
+ @dataclass
73
+ class BreakpointHitEvent(BridgeEvent):
74
+ """Event when a breakpoint is hit."""
75
+
76
+ breakpoint_id: str = ""
77
+ file: str = ""
78
+ line: int = 0
79
+ condition: str | None = None
80
+
81
+ @classmethod
82
+ def event_type(cls) -> str:
83
+ return EventType.BREAKPOINT_HIT.value
84
+
85
+ def to_dict(self) -> dict[str, Any]:
86
+ result = super().to_dict()
87
+ result.update(
88
+ {
89
+ "breakpointId": self.breakpoint_id,
90
+ "file": self.file,
91
+ "line": self.line,
92
+ }
93
+ )
94
+ if self.condition:
95
+ result["condition"] = self.condition
96
+ return result
97
+
98
+
99
+ @dataclass
100
+ class ProcessStartedEvent(BridgeEvent):
101
+ """Event when a process starts."""
102
+
103
+ process_id: str = ""
104
+ name: str = ""
105
+
106
+ @classmethod
107
+ def event_type(cls) -> str:
108
+ return EventType.PROCESS_STARTED.value
109
+
110
+ def to_dict(self) -> dict[str, Any]:
111
+ result = super().to_dict()
112
+ result.update(
113
+ {
114
+ "processId": self.process_id,
115
+ "name": self.name,
116
+ }
117
+ )
118
+ return result
119
+
120
+
121
+ @dataclass
122
+ class ProcessFinishedEvent(BridgeEvent):
123
+ """Event when a process finishes."""
124
+
125
+ status: str = "pass"
126
+ duration: float = 0.0
127
+ message: str | None = None
128
+
129
+ @classmethod
130
+ def event_type(cls) -> str:
131
+ return EventType.PROCESS_FINISHED.value
132
+
133
+ def to_dict(self) -> dict[str, Any]:
134
+ result = super().to_dict()
135
+ result.update(
136
+ {
137
+ "status": self.status,
138
+ "duration": self.duration,
139
+ }
140
+ )
141
+ if self.message:
142
+ result["message"] = self.message
143
+ return result
144
+
145
+
146
+ @dataclass
147
+ class ProcessStoppedEvent(BridgeEvent):
148
+ """Event when a process is stopped/cancelled by user."""
149
+
150
+ reason: str = "user"
151
+
152
+ @classmethod
153
+ def event_type(cls) -> str:
154
+ return EventType.PROCESS_STOPPED.value
155
+
156
+ def to_dict(self) -> dict[str, Any]:
157
+ result = super().to_dict()
158
+ result["reason"] = self.reason
159
+ return result
160
+
161
+
162
+ @dataclass
163
+ class VariablesChangedEvent(BridgeEvent):
164
+ """Event when variables change."""
165
+
166
+ variables: list[dict[str, Any]] = field(default_factory=list)
167
+
168
+ @classmethod
169
+ def event_type(cls) -> str:
170
+ return EventType.VARIABLES_CHANGED.value
171
+
172
+ def to_dict(self) -> dict[str, Any]:
173
+ result = super().to_dict()
174
+ result["variables"] = self.variables
175
+ return result
176
+
177
+
178
+ @dataclass
179
+ class CallStackChangedEvent(BridgeEvent):
180
+ """Event when call stack changes."""
181
+
182
+ call_stack: list[dict[str, Any]] = field(default_factory=list)
183
+
184
+ @classmethod
185
+ def event_type(cls) -> str:
186
+ return EventType.CALL_STACK_CHANGED.value
187
+
188
+ def to_dict(self) -> dict[str, Any]:
189
+ result = super().to_dict()
190
+ result["callStack"] = self.call_stack
191
+ return result
192
+
193
+
194
+ @dataclass
195
+ class KeywordStartedEvent(BridgeEvent):
196
+ """Event when a keyword starts."""
197
+
198
+ name: str = ""
199
+ file: str = ""
200
+ line: int = 0
201
+ args: list[Any] = field(default_factory=list)
202
+
203
+ @classmethod
204
+ def event_type(cls) -> str:
205
+ return EventType.KEYWORD_STARTED.value
206
+
207
+ def to_dict(self) -> dict[str, Any]:
208
+ result = super().to_dict()
209
+ result.update(
210
+ {
211
+ "name": self.name,
212
+ "file": self.file,
213
+ "line": self.line,
214
+ "args": self.args,
215
+ }
216
+ )
217
+ return result
218
+
219
+
220
+ @dataclass
221
+ class KeywordFinishedEvent(BridgeEvent):
222
+ """Event when a keyword finishes."""
223
+
224
+ name: str = ""
225
+ status: str = "pass"
226
+ result: Any | None = None
227
+
228
+ @classmethod
229
+ def event_type(cls) -> str:
230
+ return EventType.KEYWORD_FINISHED.value
231
+
232
+ def to_dict(self) -> dict[str, Any]:
233
+ result = super().to_dict()
234
+ result.update(
235
+ {
236
+ "name": self.name,
237
+ "status": self.status,
238
+ }
239
+ )
240
+ if self.result is not None:
241
+ result["result"] = self.result
242
+ return result
243
+
244
+
245
+ @dataclass
246
+ class ErrorEvent(BridgeEvent):
247
+ """Event for errors."""
248
+
249
+ code: int = 0
250
+ message: str = ""
251
+ details: str | None = None
252
+
253
+ @classmethod
254
+ def event_type(cls) -> str:
255
+ return EventType.ERROR.value
256
+
257
+ def to_dict(self) -> dict[str, Any]:
258
+ result = super().to_dict()
259
+ result.update(
260
+ {
261
+ "code": self.code,
262
+ "message": self.message,
263
+ }
264
+ )
265
+ if self.details:
266
+ result["details"] = self.details
267
+ return result
268
+
269
+
270
+ @dataclass
271
+ class ProcessPausedEvent(BridgeEvent):
272
+ """Event when a process pauses at breakpoint or step."""
273
+
274
+ file: str | None = None
275
+ line: int | None = None
276
+ node_id: str | None = None
277
+ reason: str = "breakpoint"
278
+
279
+ @classmethod
280
+ def event_type(cls) -> str:
281
+ return EventType.PROCESS_PAUSED.value
282
+
283
+ def to_dict(self) -> dict[str, Any]:
284
+ result = super().to_dict()
285
+ result["reason"] = self.reason
286
+ if self.file is not None:
287
+ result["file"] = self.file
288
+ if self.line is not None:
289
+ result["line"] = self.line
290
+ if self.node_id is not None:
291
+ result["nodeId"] = self.node_id
292
+ return result
293
+
294
+
295
+ @dataclass
296
+ class ProcessResumedEvent(BridgeEvent):
297
+ """Event when a process resumes from pause."""
298
+
299
+ @classmethod
300
+ def event_type(cls) -> str:
301
+ return EventType.PROCESS_RESUMED.value
302
+
303
+ def to_dict(self) -> dict[str, Any]:
304
+ return super().to_dict()