simplex 1.0.0__py3-none-any.whl → 1.0.8__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.

Potentially problematic release.


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

@@ -0,0 +1,333 @@
1
+ """
2
+ WorkflowSession class for managing Simplex workflow sessions.
3
+
4
+ This module provides the WorkflowSession class which represents an active
5
+ workflow session and provides methods for interacting with it.
6
+ """
7
+
8
+ from typing import Any, Dict, List, Optional
9
+
10
+ from simplex.errors import SimplexError, WorkflowError
11
+ from simplex.http_client import HttpClient
12
+ from simplex.types import AgenticResponse, RunAgentResponse
13
+
14
+
15
+ class WorkflowSession:
16
+ """
17
+ Represents an active workflow session.
18
+
19
+ A WorkflowSession provides methods for interacting with a running workflow,
20
+ including navigation, agent execution, and session management. It can be used
21
+ as a context manager for automatic cleanup.
22
+
23
+ Example:
24
+ >>> with client.create_workflow_session(name="test", url="https://example.com") as session:
25
+ ... session.goto("https://example.com/login")
26
+ ... session.run_agent("Login Agent", variables={"username": "user"})
27
+ ... # Session automatically closed when exiting the with block
28
+
29
+ Attributes:
30
+ session_id: Unique identifier for this session
31
+ workflow_id: ID of the workflow
32
+ livestream_url: URL to view the live browser session
33
+ connect_url: URL to connect to the session
34
+ vnc_url: URL for VNC access
35
+ """
36
+
37
+ def __init__(
38
+ self,
39
+ http_client: HttpClient,
40
+ session_data: Dict[str, str]
41
+ ):
42
+ """
43
+ Initialize a WorkflowSession.
44
+
45
+ Args:
46
+ http_client: HTTP client for making API requests
47
+ session_data: Dictionary containing session information
48
+ """
49
+ self._http_client = http_client
50
+ self.session_id = session_data['sessionId']
51
+ self.workflow_id = session_data['workflowId']
52
+ self.livestream_url = session_data['livestreamUrl']
53
+ self.connect_url = session_data['connectUrl']
54
+ self.vnc_url = session_data['vncUrl']
55
+ self._closed = False
56
+
57
+ def __enter__(self) -> 'WorkflowSession':
58
+ """
59
+ Enter the context manager.
60
+
61
+ Returns:
62
+ This session instance
63
+ """
64
+ return self
65
+
66
+ def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
67
+ """
68
+ Exit the context manager and close the session.
69
+
70
+ Args:
71
+ exc_type: Exception type if an exception occurred
72
+ exc_val: Exception value if an exception occurred
73
+ exc_tb: Exception traceback if an exception occurred
74
+ """
75
+ self.close()
76
+
77
+ def goto(self, url: str) -> Dict[str, Any]:
78
+ """
79
+ Navigate to a specific URL within the session.
80
+
81
+ Args:
82
+ url: The URL to navigate to
83
+
84
+ Returns:
85
+ Response from the navigation action
86
+
87
+ Raises:
88
+ WorkflowError: If navigation fails
89
+ """
90
+ if self._closed:
91
+ raise WorkflowError("Cannot navigate - session is closed", session_id=self.session_id)
92
+
93
+ try:
94
+ response = self._http_client.post(
95
+ '/agentic',
96
+ data={
97
+ 'task': f'Navigate to {url}',
98
+ 'session_id': self.session_id,
99
+ 'max_steps': 1
100
+ }
101
+ )
102
+
103
+ if not response.get('succeeded'):
104
+ raise WorkflowError(
105
+ f"Failed to navigate to {url}: {response.get('error', 'Unknown error')}",
106
+ session_id=self.session_id
107
+ )
108
+
109
+ return response
110
+ except SimplexError:
111
+ raise
112
+ except Exception as e:
113
+ raise WorkflowError(
114
+ f"Failed to navigate to {url}: {str(e)}",
115
+ session_id=self.session_id
116
+ )
117
+
118
+ def agentic(
119
+ self,
120
+ task: str,
121
+ max_steps: Optional[int] = None,
122
+ actions_to_exclude: Optional[List[str]] = None,
123
+ variables: Optional[Dict[str, Any]] = None
124
+ ) -> AgenticResponse:
125
+ """
126
+ Execute an agentic task within this session.
127
+
128
+ This method allows you to give natural language instructions to an agent
129
+ that will execute them within the browser session.
130
+
131
+ Args:
132
+ task: Natural language description of what to do
133
+ max_steps: Maximum number of steps the agent can take (optional)
134
+ actions_to_exclude: List of action types to exclude (optional)
135
+ variables: Dictionary of variables to use in the task (optional)
136
+
137
+ Returns:
138
+ Response containing task results
139
+
140
+ Raises:
141
+ WorkflowError: If the task fails
142
+
143
+ Example:
144
+ >>> session.agentic("Click the login button and enter credentials")
145
+ """
146
+ if self._closed:
147
+ raise WorkflowError("Cannot execute task - session is closed", session_id=self.session_id)
148
+
149
+ import json
150
+
151
+ request_data = {
152
+ 'task': task,
153
+ 'session_id': self.session_id
154
+ }
155
+
156
+ if max_steps is not None:
157
+ request_data['max_steps'] = max_steps
158
+
159
+ if actions_to_exclude:
160
+ request_data['actions_to_exclude'] = actions_to_exclude
161
+
162
+ if variables:
163
+ request_data['variables'] = json.dumps(variables)
164
+
165
+ try:
166
+ response = self._http_client.post('/agentic', data=request_data)
167
+
168
+ if not response.get('succeeded') and response.get('error'):
169
+ raise SimplexError(
170
+ f"Agent task failed: {response['error']}",
171
+ status_code=500,
172
+ data={'session_id': self.session_id, 'task': task}
173
+ )
174
+
175
+ return response
176
+ except SimplexError:
177
+ raise
178
+ except Exception as e:
179
+ raise SimplexError(
180
+ f"Failed to run agent task: {str(e)}",
181
+ status_code=500,
182
+ data={'session_id': self.session_id, 'task': task}
183
+ )
184
+
185
+ def run_agent(
186
+ self,
187
+ agent_name: str,
188
+ variables: Optional[Dict[str, Any]] = None
189
+ ) -> RunAgentResponse:
190
+ """
191
+ Run a named agent within this session.
192
+
193
+ Named agents are pre-configured agents that can be executed by name.
194
+
195
+ Args:
196
+ agent_name: Name of the agent to run
197
+ variables: Dictionary of variables to pass to the agent (optional)
198
+
199
+ Returns:
200
+ Response containing agent execution results
201
+
202
+ Raises:
203
+ SimplexError: If the agent execution fails
204
+
205
+ Example:
206
+ >>> session.run_agent("Login Agent", variables={"username": "user@example.com"})
207
+ """
208
+ if self._closed:
209
+ raise WorkflowError("Cannot run agent - session is closed", session_id=self.session_id)
210
+
211
+ request_data = {
212
+ 'agent_name': agent_name,
213
+ 'session_id': self.session_id
214
+ }
215
+
216
+ if variables:
217
+ request_data['variables'] = variables
218
+
219
+ try:
220
+ response = self._http_client.post('/run_agent', data=request_data)
221
+
222
+ if not response.get('succeeded'):
223
+ raise SimplexError(
224
+ f"Agent run failed for {agent_name}",
225
+ status_code=500,
226
+ data={'agent_name': agent_name, 'session_id': self.session_id}
227
+ )
228
+
229
+ return response
230
+ except SimplexError:
231
+ raise
232
+ except Exception as e:
233
+ raise SimplexError(
234
+ f"Failed to run agent: {str(e)}",
235
+ status_code=500,
236
+ data={'agent_name': agent_name, 'session_id': self.session_id}
237
+ )
238
+
239
+ def start_capture(self) -> Dict[str, bool]:
240
+ """
241
+ Start capture mode for this session.
242
+
243
+ Capture mode records browser actions for later playback.
244
+
245
+ Returns:
246
+ Response indicating success
247
+
248
+ Raises:
249
+ WorkflowError: If starting capture mode fails
250
+ """
251
+ if self._closed:
252
+ raise WorkflowError("Cannot start capture - session is closed", session_id=self.session_id)
253
+
254
+ try:
255
+ response = self._http_client.post(
256
+ '/start_capture_mode',
257
+ data={'session_id': self.session_id}
258
+ )
259
+ return response
260
+ except Exception as e:
261
+ raise WorkflowError(
262
+ f"Failed to start capture mode: {str(e)}",
263
+ session_id=self.session_id
264
+ )
265
+
266
+ def stop_capture(self) -> Dict[str, bool]:
267
+ """
268
+ Stop capture mode for this session.
269
+
270
+ Returns:
271
+ Response indicating success
272
+
273
+ Raises:
274
+ WorkflowError: If stopping capture mode fails
275
+ """
276
+ if self._closed:
277
+ raise WorkflowError("Cannot stop capture - session is closed", session_id=self.session_id)
278
+
279
+ try:
280
+ response = self._http_client.post(
281
+ '/stop_capture_mode',
282
+ data={'session_id': self.session_id}
283
+ )
284
+ return response
285
+ except Exception as e:
286
+ raise WorkflowError(
287
+ f"Failed to stop capture mode: {str(e)}",
288
+ session_id=self.session_id
289
+ )
290
+
291
+ def close(self) -> Dict[str, Any]:
292
+ """
293
+ Close this workflow session.
294
+
295
+ This releases resources associated with the session. Once closed,
296
+ the session cannot be used for further operations.
297
+
298
+ Returns:
299
+ Response from closing the session
300
+
301
+ Raises:
302
+ WorkflowError: If closing the session fails
303
+ """
304
+ if self._closed:
305
+ return {'succeeded': True, 'message': 'Session already closed'}
306
+
307
+ try:
308
+ response = self._http_client.post(
309
+ '/close_workflow_session',
310
+ data={'session_id': self.session_id}
311
+ )
312
+ self._closed = True
313
+ return response
314
+ except Exception as e:
315
+ raise WorkflowError(
316
+ f"Failed to close workflow session: {str(e)}",
317
+ session_id=self.session_id
318
+ )
319
+
320
+ @property
321
+ def is_closed(self) -> bool:
322
+ """
323
+ Check if the session is closed.
324
+
325
+ Returns:
326
+ True if the session is closed, False otherwise
327
+ """
328
+ return self._closed
329
+
330
+ def __repr__(self) -> str:
331
+ """Return a string representation of the session."""
332
+ status = "closed" if self._closed else "open"
333
+ return f"WorkflowSession(session_id='{self.session_id}', status='{status}')"
simplex/types.py ADDED
@@ -0,0 +1,276 @@
1
+ """
2
+ Type definitions for the Simplex SDK.
3
+
4
+ This module contains TypedDict classes and type aliases used throughout the SDK
5
+ for type hinting and documentation purposes.
6
+ """
7
+
8
+ from typing import Any, Dict, List, Optional, TypedDict
9
+
10
+
11
+ class SimplexClientOptions(TypedDict, total=False):
12
+ """
13
+ Configuration options for the SimplexClient.
14
+
15
+ Attributes:
16
+ api_key: Your Simplex API key (required)
17
+ timeout: Request timeout in seconds (default: 30)
18
+ max_retries: Maximum number of retry attempts (default: 3)
19
+ retry_delay: Delay between retries in seconds (default: 1)
20
+ """
21
+ api_key: str
22
+ timeout: int
23
+ max_retries: int
24
+ retry_delay: int
25
+
26
+
27
+ # Type alias for workflow variables
28
+ WorkflowVariables = Dict[str, Any]
29
+
30
+
31
+ class RunWorkflowRequest(TypedDict, total=False):
32
+ """
33
+ Request parameters for running a workflow.
34
+
35
+ Attributes:
36
+ workflow_id: The ID of the workflow to run (required)
37
+ metadata: Optional metadata string to attach to the workflow run
38
+ webhook_url: Optional webhook URL for status updates
39
+ variables: Dictionary of variables to pass to the workflow
40
+ """
41
+ workflow_id: str
42
+ metadata: str
43
+ webhook_url: str
44
+ variables: WorkflowVariables
45
+
46
+
47
+ class RunWorkflowResponse(TypedDict):
48
+ """
49
+ Response from running a workflow.
50
+
51
+ Attributes:
52
+ succeeded: Whether the workflow started successfully
53
+ message: Human-readable status message
54
+ session_id: Unique identifier for this workflow session
55
+ vnc_url: URL for VNC access to the workflow session
56
+ """
57
+ succeeded: bool
58
+ message: str
59
+ session_id: str
60
+ vnc_url: str
61
+
62
+
63
+ class WorkflowAction(TypedDict):
64
+ """
65
+ Represents a single action taken during workflow execution.
66
+
67
+ Attributes:
68
+ action: The type of action performed
69
+ params: Parameters passed to the action
70
+ result: Result returned by the action
71
+ timestamp: ISO 8601 timestamp when the action occurred
72
+ """
73
+ action: str
74
+ params: Any
75
+ result: Any
76
+ timestamp: str
77
+
78
+
79
+ class WorkflowStatusResponse(TypedDict):
80
+ """
81
+ Response from checking workflow status.
82
+
83
+ Attributes:
84
+ succeeded: Whether the status check succeeded
85
+ completed: Whether the workflow has completed execution
86
+ results: List of actions taken during workflow execution
87
+ total_actions: Total number of actions performed
88
+ session_id: The session ID being checked
89
+ completed_at: ISO 8601 timestamp of completion (if completed)
90
+ """
91
+ succeeded: bool
92
+ completed: bool
93
+ results: List[WorkflowAction]
94
+ total_actions: int
95
+ session_id: str
96
+ completed_at: Optional[str]
97
+
98
+
99
+ class CreateWorkflowSessionRequest(TypedDict, total=False):
100
+ """
101
+ Request parameters for creating a workflow session.
102
+
103
+ Attributes:
104
+ workflow_name: Name for the workflow (required)
105
+ url: Starting URL for the workflow (required)
106
+ proxies: Whether to use proxies (default: False)
107
+ session_data: Optional JSON string of session data
108
+ """
109
+ workflow_name: str
110
+ url: str
111
+ proxies: bool
112
+ session_data: str
113
+
114
+
115
+ class CreateWorkflowSessionResponse(TypedDict):
116
+ """
117
+ Response from creating a workflow session.
118
+
119
+ Attributes:
120
+ session_id: Unique identifier for the session
121
+ workflow_id: ID of the created workflow
122
+ livestream_url: URL to view the live browser session
123
+ connect_url: URL to connect to the session
124
+ vnc_url: URL for VNC access
125
+ """
126
+ session_id: str
127
+ workflow_id: str
128
+ livestream_url: str
129
+ connect_url: str
130
+ vnc_url: str
131
+
132
+
133
+ class AgenticRequest(TypedDict, total=False):
134
+ """
135
+ Request parameters for running an agentic task.
136
+
137
+ Attributes:
138
+ task: Natural language description of the task (required)
139
+ session_id: Session to run the task in (required)
140
+ max_steps: Maximum number of steps to take (optional)
141
+ actions_to_exclude: List of action types to exclude (optional)
142
+ variables: JSON string of variables for the task (optional)
143
+ """
144
+ task: str
145
+ session_id: str
146
+ max_steps: int
147
+ actions_to_exclude: List[str]
148
+ variables: str
149
+
150
+
151
+ class AgenticResponse(TypedDict):
152
+ """
153
+ Response from running an agentic task.
154
+
155
+ Attributes:
156
+ succeeded: Whether the task completed successfully
157
+ result: Result data from the task
158
+ error: Error message if the task failed
159
+ """
160
+ succeeded: bool
161
+ result: Any
162
+ error: Optional[str]
163
+
164
+
165
+ class RunAgentRequest(TypedDict, total=False):
166
+ """
167
+ Request parameters for running a named agent.
168
+
169
+ Attributes:
170
+ agent_name: Name of the agent to run (required)
171
+ session_id: Session to run the agent in (required)
172
+ variables: Dictionary of variables to pass to the agent
173
+ """
174
+ agent_name: str
175
+ session_id: str
176
+ variables: Dict[str, Any]
177
+
178
+
179
+ class RunAgentResponse(TypedDict):
180
+ """
181
+ Response from running a named agent.
182
+
183
+ Attributes:
184
+ succeeded: Whether the agent completed successfully
185
+ session_id: The session ID where the agent ran
186
+ agent_name: Name of the agent that ran
187
+ result: Result data from the agent
188
+ """
189
+ succeeded: bool
190
+ session_id: str
191
+ agent_name: str
192
+ result: Any
193
+
194
+
195
+ class GetSessionStoreResponse(TypedDict):
196
+ """
197
+ Response from getting session store data.
198
+
199
+ Attributes:
200
+ succeeded: Whether the request succeeded
201
+ session_store: Dictionary containing session data
202
+ error: Error message if the request failed
203
+ """
204
+ succeeded: bool
205
+ session_store: Optional[Dict[str, Any]]
206
+ error: Optional[str]
207
+
208
+
209
+ class DownloadSessionFilesRequest(TypedDict, total=False):
210
+ """
211
+ Request parameters for downloading session files.
212
+
213
+ Attributes:
214
+ session_id: Session to download files from (required)
215
+ filename: Optional specific filename to download
216
+ """
217
+ session_id: str
218
+ filename: str
219
+
220
+
221
+ class DownloadSessionFilesErrorResponse(TypedDict):
222
+ """
223
+ Error response from downloading session files.
224
+
225
+ Attributes:
226
+ succeeded: Always False for error responses
227
+ error: Error message describing what went wrong
228
+ """
229
+ succeeded: bool
230
+ error: str
231
+
232
+
233
+ class TwoFactorConfig(TypedDict, total=False):
234
+ """
235
+ Configuration for 2FA authentication.
236
+
237
+ Attributes:
238
+ seed: The 2FA seed/secret (required)
239
+ name: Optional name for this 2FA config
240
+ partial_url: Optional partial URL to match for auto-detection
241
+ """
242
+ seed: str
243
+ name: str
244
+ partial_url: str
245
+
246
+
247
+ class Add2FAConfigRequest(TypedDict, total=False):
248
+ """
249
+ Request parameters for adding a 2FA configuration.
250
+
251
+ Attributes:
252
+ seed: The 2FA seed/secret (required)
253
+ name: Optional name for this 2FA config
254
+ partial_url: Optional partial URL to match for auto-detection
255
+ """
256
+ seed: str
257
+ name: str
258
+ partial_url: str
259
+
260
+
261
+ class Add2FAConfigResponse(TypedDict):
262
+ """
263
+ Response from adding a 2FA configuration.
264
+
265
+ Attributes:
266
+ succeeded: Whether the config was added successfully
267
+ added_config: The configuration that was added
268
+ total_configs: Total number of 2FA configs after adding
269
+ all_configs: List of all 2FA configurations
270
+ error: Error message if the request failed
271
+ """
272
+ succeeded: bool
273
+ added_config: Optional[Any]
274
+ total_configs: Optional[int]
275
+ all_configs: Optional[List[Any]]
276
+ error: Optional[str]