clerk-sdk 0.2.0__tar.gz → 0.2.2__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.
Files changed (58) hide show
  1. {clerk_sdk-0.2.0/clerk_sdk.egg-info → clerk_sdk-0.2.2}/PKG-INFO +1 -1
  2. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/client.py +4 -0
  3. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/client_actor/client_actor.py +1 -3
  4. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/decorators/gui_automation.py +35 -9
  5. clerk_sdk-0.2.2/clerk/gui_automation/exceptions/agent_manager.py +6 -0
  6. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/ui_actions/support.py +2 -1
  7. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/utils/logger.py +7 -1
  8. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/utils/save_artifact.py +2 -0
  9. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2/clerk_sdk.egg-info}/PKG-INFO +1 -1
  10. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk_sdk.egg-info/SOURCES.txt +1 -0
  11. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/setup.py +1 -1
  12. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/LICENSE +0 -0
  13. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/MANIFEST.in +0 -0
  14. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/README.md +0 -0
  15. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/__init__.py +0 -0
  16. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/base.py +0 -0
  17. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/client.py +0 -0
  18. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/decorator/__init__.py +0 -0
  19. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/decorator/models.py +0 -0
  20. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/decorator/task_decorator.py +0 -0
  21. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/__init__.py +0 -0
  22. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/action_model/__init__.py +0 -0
  23. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/action_model/model.py +0 -0
  24. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/action_model/utils.py +0 -0
  25. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/client_actor/__init__.py +0 -0
  26. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/client_actor/exception.py +0 -0
  27. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/client_actor/model.py +0 -0
  28. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/decorators/__init__.py +0 -0
  29. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/exceptions/__init__.py +0 -0
  30. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/exceptions/modality/__init__.py +0 -0
  31. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/exceptions/modality/exc.py +0 -0
  32. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/exceptions/websocket.py +0 -0
  33. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/requirements.txt +0 -0
  34. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/ui_actions/__init__.py +0 -0
  35. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/ui_actions/actions.py +0 -0
  36. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/ui_actions/base.py +0 -0
  37. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/ui_state_inspector/__init__.py +0 -0
  38. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/ui_state_inspector/gui_vision.py +0 -0
  39. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/ui_state_inspector/models.py +0 -0
  40. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/ui_state_machine/__init__.py +0 -0
  41. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/ui_state_machine/ai_recovery.py +0 -0
  42. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/ui_state_machine/decorators.py +0 -0
  43. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/ui_state_machine/exceptions.py +0 -0
  44. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/ui_state_machine/models.py +0 -0
  45. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/gui_automation/ui_state_machine/state_machine.py +0 -0
  46. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/models/__init__.py +0 -0
  47. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/models/document.py +0 -0
  48. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/models/document_statuses.py +0 -0
  49. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/models/file.py +0 -0
  50. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/models/remote_device.py +0 -0
  51. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/models/response_model.py +0 -0
  52. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk/utils/__init__.py +0 -0
  53. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk_sdk.egg-info/dependency_links.txt +0 -0
  54. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk_sdk.egg-info/requires.txt +0 -0
  55. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/clerk_sdk.egg-info/top_level.txt +0 -0
  56. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/pyproject.toml +0 -0
  57. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/requirements.txt +0 -0
  58. {clerk_sdk-0.2.0 → clerk_sdk-0.2.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clerk-sdk
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Library for interacting with Clerk
5
5
  Home-page: https://github.com/F-ONE-Group/clerk_pypi
6
6
  Author: F-ONE Group
@@ -3,6 +3,7 @@ from typing import Dict, List, Optional
3
3
  from pydantic import BaseModel
4
4
  from clerk.base import BaseClerk
5
5
  from clerk.gui_automation.action_model.model import Coords
6
+ from clerk.gui_automation.exceptions.agent_manager import NoClientsAvailable
6
7
  from clerk.gui_automation.ui_state_inspector.models import (
7
8
  ActionString,
8
9
  BaseState,
@@ -22,6 +23,9 @@ class RPAClerk(BaseClerk):
22
23
  endpoint=endpoint, json={"group_name": group_name, "run_id": run_id}
23
24
  )
24
25
 
26
+ if res.data[0] is None:
27
+ raise NoClientsAvailable()
28
+
25
29
  return RemoteDevice(**res.data[0])
26
30
 
27
31
  def deallocate_remote_device(
@@ -68,9 +68,7 @@ async def _get_screen_async() -> str:
68
68
  payload = {
69
69
  "proc_inst_id": os.getenv("PROC_ID"),
70
70
  "client_name": os.getenv("REMOTE_DEVICE_NAME"),
71
- "headless": (
72
- True if os.getenv("HEADLESS", "True").lower() == "true" else False
73
- ),
71
+ "headless": True,
74
72
  "action": {"action_type": "screenshot"},
75
73
  }
76
74
  try:
@@ -1,15 +1,20 @@
1
1
  import asyncio
2
2
  import functools
3
- import logging
4
3
  import os
4
+ import time
5
5
  from typing import Callable, Union
6
6
 
7
7
  from websockets.asyncio.client import connect, ClientConnection
8
8
  from websockets.protocol import State
9
9
 
10
10
  from clerk.gui_automation.client import RPAClerk
11
+ from clerk.gui_automation.exceptions.agent_manager import (
12
+ ClientAvailabilityTimeout,
13
+ NoClientsAvailable,
14
+ )
11
15
  from clerk.models.remote_device import RemoteDevice
12
16
  from clerk.decorator.models import ClerkCodePayload
17
+ from clerk.utils import logger
13
18
  from ..exceptions.websocket import WebSocketConnectionFailed
14
19
 
15
20
 
@@ -19,22 +24,43 @@ global_ws: Union[ClientConnection, None] = None
19
24
  clerk_client = RPAClerk()
20
25
  wss_uri = "wss://agent-manager.f-one.group/action"
21
26
 
27
+ CLIENT_TIMEOUT_MINS = 1
28
+ MAX_CLIENT_AVAILABILITY_RETRIES = 60
29
+
22
30
 
23
31
  def _allocate_remote_device(
24
32
  clerk_client: RPAClerk, group_name: str, run_id: str
25
33
  ) -> RemoteDevice:
26
- remote_device = clerk_client.allocate_remote_device(
27
- group_name=group_name, run_id=run_id
28
- )
29
- os.environ["REMOTE_DEVICE_ID"] = remote_device.id
30
- os.environ["REMOTE_DEVICE_NAME"] = remote_device.name
31
- return remote_device
34
+ remote_device = None
35
+ retries = 0
36
+
37
+ while True:
38
+ try:
39
+ remote_device = clerk_client.allocate_remote_device(
40
+ group_name=group_name, run_id=run_id
41
+ )
42
+ os.environ["REMOTE_DEVICE_ID"] = remote_device.id
43
+ os.environ["REMOTE_DEVICE_NAME"] = remote_device.name
44
+ logger.debug(f"Remote device allocated: {remote_device.name}")
45
+ return remote_device
46
+
47
+ except NoClientsAvailable:
48
+ logger.warning(
49
+ f"No clients are available for {group_name} group. Initiating a {CLIENT_TIMEOUT_MINS} minute wait. Retry count: {retries}"
50
+ )
51
+ retries += 1
52
+ if retries == MAX_CLIENT_AVAILABILITY_RETRIES:
53
+ raise ClientAvailabilityTimeout(
54
+ f"No clients available for {group_name} group after {CLIENT_TIMEOUT_MINS*MAX_CLIENT_AVAILABILITY_RETRIES} minutes"
55
+ )
56
+ time.sleep(CLIENT_TIMEOUT_MINS * 60)
32
57
 
33
58
 
34
59
  def _deallocate_target(
35
60
  clerk_client: RPAClerk, remote_device: RemoteDevice, run_id: str
36
61
  ):
37
62
  clerk_client.deallocate_remote_device(remote_device=remote_device, run_id=run_id)
63
+ logger.debug("Remote device deallocated")
38
64
  os.environ.pop("REMOTE_DEVICE_ID", None)
39
65
  os.environ.pop("REMOTE_DEVICE_NAME", None)
40
66
 
@@ -82,7 +108,7 @@ def gui_automation():
82
108
  global_ws = event_loop.run_until_complete(task)
83
109
 
84
110
  if global_ws and global_ws.state is State.OPEN:
85
- logging.debug("WebSocket connection established.")
111
+ logger.debug("WebSocket connection established.")
86
112
  func_ret = func(payload, *args, **kwargs)
87
113
  else:
88
114
  global_ws = None
@@ -97,7 +123,7 @@ def gui_automation():
97
123
  if global_ws and global_ws.state is State.OPEN:
98
124
  close_task = event_loop.create_task(close_ws_connection(global_ws))
99
125
  event_loop.run_until_complete(close_task)
100
- print("WebSocket connection closed.")
126
+ logger.debug("WebSocket connection closed.")
101
127
 
102
128
  event_loop.run_until_complete(event_loop.shutdown_asyncgens())
103
129
  event_loop.close()
@@ -0,0 +1,6 @@
1
+ class NoClientsAvailable(Exception):
2
+ pass
3
+
4
+
5
+ class ClientAvailabilityTimeout(Exception):
6
+ pass
@@ -1,4 +1,5 @@
1
1
  import os
2
+ import base64
2
3
  from typing import Optional
3
4
  from backoff._typing import Details
4
5
 
@@ -48,7 +49,7 @@ def save_screenshot(filename: str, sub_folder: Optional[str] = None) -> str:
48
49
  screen_b64: str = get_screen()
49
50
  return save_artifact(
50
51
  filename=filename,
51
- file_bytes=screen_b64.encode("utf-8"),
52
+ file_bytes=base64.b64decode(screen_b64),
52
53
  subfolder=sub_folder,
53
54
  )
54
55
 
@@ -4,7 +4,7 @@ import logging
4
4
  import sys
5
5
 
6
6
  if sys.platform == "win32":
7
- base_path = os.path.join(os.getcwd(), "data", "output", "artifacts")
7
+ base_path = os.path.join(os.getcwd(), "data", "artifacts")
8
8
  else:
9
9
  base_path = "/app/data/artifacts"
10
10
 
@@ -100,7 +100,13 @@ def _log(level: str, message: str):
100
100
  formatter = logging.Formatter(format)
101
101
  fh.setFormatter(formatter)
102
102
  logger.addHandler(fh)
103
+ # → console handler (same formatter)
104
+ sh = logging.StreamHandler(sys.stdout)
105
+ sh.setFormatter(formatter)
106
+ logger.addHandler(sh)
107
+
103
108
  logger.setLevel(logging.DEBUG)
109
+ logger.propagate = False # keep root logger from printing duplicates
104
110
 
105
111
  # Log the message based on the level
106
112
  if level.lower() == "info":
@@ -1,5 +1,6 @@
1
1
  import os
2
2
  from typing import Optional
3
+ from clerk.utils import logger
3
4
 
4
5
 
5
6
  def save_artifact(
@@ -32,4 +33,5 @@ def save_artifact(
32
33
  with open(file_path, "wb") as f:
33
34
  f.write(file_bytes)
34
35
 
36
+ logger.debug(f"Artifact successfully saved at: {file_path}")
35
37
  return file_path
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clerk-sdk
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Library for interacting with Clerk
5
5
  Home-page: https://github.com/F-ONE-Group/clerk_pypi
6
6
  Author: F-ONE Group
@@ -23,6 +23,7 @@ clerk/gui_automation/client_actor/model.py
23
23
  clerk/gui_automation/decorators/__init__.py
24
24
  clerk/gui_automation/decorators/gui_automation.py
25
25
  clerk/gui_automation/exceptions/__init__.py
26
+ clerk/gui_automation/exceptions/agent_manager.py
26
27
  clerk/gui_automation/exceptions/websocket.py
27
28
  clerk/gui_automation/exceptions/modality/__init__.py
28
29
  clerk/gui_automation/exceptions/modality/exc.py
@@ -13,7 +13,7 @@ gui_requirements = get_requirements("./clerk/gui_automation")
13
13
 
14
14
  setup(
15
15
  name="clerk-sdk",
16
- version="0.2.0",
16
+ version="0.2.2",
17
17
  description="Library for interacting with Clerk",
18
18
  long_description=open("README.md").read(),
19
19
  long_description_content_type="text/markdown",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes