clerk-sdk 0.4.16.dev0__py3-none-any.whl → 0.5.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.
@@ -0,0 +1,52 @@
1
+ from typing import Dict
2
+
3
+ from clerk.decorator import clerk_code
4
+ from clerk.decorator.models import ClerkCodePayload
5
+ from clerk.gui_automation.decorators import gui_automation
6
+ from clerk.gui_automation.ui_state_machine import ScreenPilot, SuccessfulCompletion
7
+ from clerk.utils import logger
8
+
9
+ from src.gui.states import *
10
+ from src.gui.transitions import *
11
+ from src.gui.rollbacks import *
12
+ from src.schema import StructuredData # use `clerk schema fetch` to update the schema
13
+
14
+ @clerk_code()
15
+ @gui_automation()
16
+ def main(payload: ClerkCodePayload):
17
+ """Main program"""
18
+
19
+ data = StructuredData.model_validate(payload.structured_data)
20
+ logger.info("Custom code started")
21
+
22
+ def goal_function(current_state: str, process_variables: StructuredData) -> None:
23
+ """
24
+ Goal function for the state machine.
25
+ Args:
26
+ current_state (str): The current state of the state machine
27
+ (you can provide additional arguments as needed, e.g. order: dict)
28
+ Raises:
29
+ ScreenPilotOutcome: The outcome of the state machine
30
+ """
31
+ if True: # Use an actual condition based on state and/or process variables to complete the automation
32
+ raise SuccessfulCompletion()
33
+
34
+ ai_recovery_instructions = "\\n - ".join(
35
+ [
36
+ "Instructions on how to deal with possible issues using Clerk UI Actions.",
37
+ ]
38
+ )
39
+
40
+ ScreenPilot.configure(ai_recovery_instructions=ai_recovery_instructions)
41
+ exit_reason = ScreenPilot.run(
42
+ goal_function, process_variables=process_variables, doc_id=payload.document.id
43
+ )
44
+
45
+
46
+ logger.info("Custom code completed")
47
+ payload.structured_data = data.model_dump() # Return variables to Clerk
48
+ return payload
49
+
50
+
51
+ if __name__ == "__main__":
52
+ main()
@@ -0,0 +1,17 @@
1
+ """
2
+ # Instructions
3
+
4
+ Use this file to define rollback procedures for ScreenPilot. Rollbacks behave like transitions, but are triggered in rollback mode when exceptions occur.
5
+
6
+ # Example
7
+ ```python
8
+ @rollback("State1", "State2")
9
+ def perform_rollback():
10
+ # Perform necessary actions to revert from State1 to State2
11
+ # Optionally, save a screenshot or log information
12
+ raise RollbackCompleted()
13
+ ```
14
+
15
+ """
16
+
17
+ from clerk.gui_automation.ui_state_machine import rollback, RollbackCompleted
@@ -0,0 +1,15 @@
1
+ """
2
+ # Instructions
3
+
4
+ Use this file to define the various states of ScreenPilot's UI state machine. Each state represents a distinct screen or condition in the GUI automation process.
5
+
6
+ # Example
7
+ ```python
8
+
9
+ @state(start_allowed=False, end_allowed=False)
10
+ class InvoiceReview:
11
+ description = "Detailed description of the Invoice Review state."
12
+
13
+ """
14
+
15
+ from clerk.gui_automation.ui_state_machine import state
@@ -0,0 +1,26 @@
1
+ """
2
+ # Instructions
3
+
4
+ Use this file to define transitions between different states in ScreenPilot's UI state machine. Each transition represents a change from one state to another.
5
+
6
+ # Example: regular transition
7
+ ```python
8
+ @transition("StateA", "StateB")
9
+ def go_to_state_b() -> None:
10
+ # Actions to perform during the transition from StateA to StateB
11
+ pass
12
+ ```
13
+
14
+ # Example: conditional transition
15
+ ```python
16
+ def condition() -> bool:
17
+ return True # or some condition logic
18
+
19
+ @transition("StateA", "StateB", condition=condition)
20
+ def conditional_transition() -> None:
21
+ # Actions to perform during the conditional transition from StateA to StateB
22
+ pass
23
+ ```
24
+ """
25
+
26
+ from clerk.gui_automation.ui_state_machine import transition
@@ -0,0 +1,2 @@
1
+ networkx >=3.5.0, <4.0.0
2
+ websockets >= 15.0.1
@@ -11,7 +11,23 @@ from ..action_model.model import (
11
11
  import os
12
12
 
13
13
  ModalityType = Union[Literal["icon"], Literal["text"]]
14
- TARGET_IMAGES_PATH = os.path.join(os.getcwd(), "targets")
14
+
15
+
16
+ def _find_child_dir(dir_name: str, root_dir: str) -> str:
17
+ """
18
+ Recursively search for a directory starting from current working directory.
19
+ Returns the first match found, or falls back to cwd/dir_name if none found.
20
+ """
21
+ # Walk through the directory tree starting from cwd
22
+ for root, dirs, _ in os.walk(root_dir):
23
+ if dir_name in dirs:
24
+ return os.path.join(root, dir_name)
25
+
26
+ # Fallback to default path if no targets directory found
27
+ return os.path.join(root_dir, dir_name)
28
+
29
+
30
+ TARGET_IMAGES_PATH = _find_child_dir("targets", root_dir=os.getcwd())
15
31
 
16
32
 
17
33
  def to_full_img_path(img: Union[str, ImageB64]) -> str:
@@ -0,0 +1,79 @@
1
+ # ScreenPilot
2
+
3
+ ScreenPilot is a state machine meant for operating UIs.
4
+ - Accepts a state evaluation function and a goal function
5
+ - Runs in a loop ("run" method) until the goal function returns True
6
+ - Handles logging, error handling and attempts recovery on errors
7
+ - The states and transitions are added to a directional multi-graph
8
+ - "run" method performs anti-patter detection (repeated transitions, unplanned transitions) and exits on encountering them
9
+ - Known states and transitions are provided with the respective decorators
10
+
11
+
12
+ ## Instructions
13
+
14
+ - Use 'BusinessException' class to raise business exceptions
15
+ - Evaluate the exit_reason returned by the run method to execution outcomes
16
+ - Provide custom instructions to AI recovery to handle the UI's quirks
17
+
18
+ ## Usage example
19
+
20
+ ```python
21
+ from f_one_core_utilities.ui_actions import Vision, ScreenPilot, state, transition, rollback, BusinessException, complete_ui_automation
22
+ from f_one_core_utilities.ui_actions import LeftClick, SendKeys, PressKeys
23
+ from f_one_core_utilities.camunda import raise_error, return_and_wait, raise_incident
24
+
25
+ # Import states, transitions and rollbacks for them to be registered
26
+ from .states import *
27
+ from .transitions import *
28
+ from .rollbacks import *
29
+
30
+ # Configure states and transitions
31
+
32
+ @state(end_allowed=False)
33
+ class WindowOpen:
34
+ description = "Window is open"
35
+
36
+ @state(start_allowed=False)
37
+ class WindowClosed:
38
+ description = "Window is closed"
39
+
40
+ @transition(from_state="WindowOpen", to_state="WindowClosed", condition=lambda payload: payload.message == "Closed")
41
+ def close_window(payload):
42
+ # 'payload' is the order object passed to the run method
43
+ SendKeys(keys=f"{payload.message}").do()
44
+ LeftClick(target="Close").do()
45
+
46
+ # Define rollbacks which will be triggered in case of runtime errors
47
+ @rollback("WindowClosed", "WindowOpen")
48
+ def teardown_app():
49
+ PressKeys(keys="Alt+F4").do()
50
+
51
+ # Provide a goal function
52
+
53
+ def goal_function(current_state: str, **kwargs) -> None:
54
+ """
55
+ Goal function for the state machine.
56
+ Args:
57
+ current_state (str): The current state of the state machine
58
+ **kwargs: (you can provide additional arguments as needed, e.g. order: dict)
59
+ Returns:
60
+ None
61
+ """
62
+ if current_state == "WindowClosed":
63
+ complete_ui_automation("Window closed")
64
+ else:
65
+ raise BusinessException("Window not closed")
66
+
67
+ ScreenPilot.configure(
68
+ ai_recovery_instructions = "If the popup appears, click OK and interrupt the process",
69
+ )
70
+
71
+ # payload is a kwarg that will be propagated to all transitions and the goal function
72
+ exit_reason = ScreenPilot.run(goal_function, payload=process_variables)
73
+
74
+ # Exit status and messages can be used for graceful error handling
75
+ if isinstance(exit_reason, BusinessException):
76
+ raise_error(message="Window still open", bpmn_error="WindowOpen")
77
+ elif isinstance(exit_reason, SuccessfulCompletion):
78
+ process_variables.billable = True
79
+ ```
@@ -1,39 +1,26 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clerk-sdk
3
- Version: 0.4.16.dev0
3
+ Version: 0.5.0
4
4
  Summary: Library for interacting with Clerk
5
- Home-page: https://github.com/F-ONE-Group/clerk_pypi
6
- Author: F-ONE Group
7
- Author-email: admin@f-one.group
8
- Classifier: Programming Language :: Python :: 3
5
+ Project-URL: Homepage, https://github.com/F-ONE-Group/clerk_pypi
6
+ Author-email: F-One <contact@f-one.group>
7
+ License-File: LICENSE
9
8
  Classifier: License :: OSI Approved :: MIT License
10
9
  Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3
11
11
  Requires-Python: >=3.11
12
- Description-Content-Type: text/markdown
13
- License-File: LICENSE
14
- Requires-Dist: pydantic<3.0.0,>=2.0.0
15
12
  Requires-Dist: backoff<3.0.0,>=2.0.0
13
+ Requires-Dist: pydantic<3.0.0,>=2.0.0
14
+ Requires-Dist: python-dotenv>=1.0.0
16
15
  Requires-Dist: requests<3.0.0,>=2.32.3
16
+ Requires-Dist: rich>=14.2.0
17
17
  Provides-Extra: all
18
- Requires-Dist: pydantic<3.0.0,>=2.0.0; extra == "all"
19
- Requires-Dist: backoff<3.0.0,>=2.0.0; extra == "all"
20
- Requires-Dist: requests<3.0.0,>=2.32.3; extra == "all"
21
- Requires-Dist: networkx<4.0.0,>=3.5.0; extra == "all"
22
- Requires-Dist: websockets>=15.0.1; extra == "all"
18
+ Requires-Dist: networkx<4.0.0,>=3.5.0; extra == 'all'
19
+ Requires-Dist: websockets>=15.0.1; extra == 'all'
23
20
  Provides-Extra: gui-automation
24
- Requires-Dist: networkx<4.0.0,>=3.5.0; extra == "gui-automation"
25
- Requires-Dist: websockets>=15.0.1; extra == "gui-automation"
26
- Dynamic: author
27
- Dynamic: author-email
28
- Dynamic: classifier
29
- Dynamic: description
30
- Dynamic: description-content-type
31
- Dynamic: home-page
32
- Dynamic: license-file
33
- Dynamic: provides-extra
34
- Dynamic: requires-dist
35
- Dynamic: requires-python
36
- Dynamic: summary
21
+ Requires-Dist: networkx<4.0.0,>=3.5.0; extra == 'gui-automation'
22
+ Requires-Dist: websockets>=15.0.1; extra == 'gui-automation'
23
+ Description-Content-Type: text/markdown
37
24
 
38
25
  # Clerk Python SDK
39
26
 
@@ -1,14 +1,26 @@
1
- clerk/__init__.py,sha256=6KE-7b4AAmpoWge6Ecko_0Spe4J7BC3YRdmmlEmsUFQ,56
1
+ clerk/__init__.py,sha256=nmWUTp7gU2NpHDC4lwMx1k9CfI0znjuMuMgFNkrjad4,50
2
2
  clerk/base.py,sha256=lbFTdpdDfsmYIQUFH93S1aw0-L6GNJwAcubW1tdMFX4,3967
3
- clerk/client.py,sha256=RdOvC23WK9ZtIXDOYaoSFk9debh3UTmstBXjAswAH6E,4981
3
+ clerk/client.py,sha256=m4d_DEpmTCPGP8gm3idREhcVzlvHDdvLrdbTc6J9AGk,5191
4
4
  clerk/decorator/__init__.py,sha256=yGGcS17VsZ7cZ-hVGCm3I3vGDJMiJIAqmDGzriIi0DI,65
5
5
  clerk/decorator/models.py,sha256=nFMdVSG3nJ4hrEXs9YbI_GgjHbVjhSWZokOCzUh-lqQ,521
6
6
  clerk/decorator/task_decorator.py,sha256=H8caRvNvvl-IRwyREP66gBGVM-SpQJ1W7oAFImO-6Jw,3769
7
+ clerk/development/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ clerk/development/cli.py,sha256=-2VwjWiGHypxrOSCpFMXSAuJKvLfBqeCmaOXsUAOraE,3431
9
+ clerk/development/init_project.py,sha256=pjEQKkpqStA-Z21sc4jswhIcOxJ3xgrxHLalNOsCiBU,10665
10
+ clerk/development/gui/test_session.py,sha256=Lal3Q4kw9e-QXshE2v5zaV7aSWm4ilaWKyZzeHfAOJ4,10554
11
+ clerk/development/schema/fetch_schema.py,sha256=jIGO2ZFvgVnFz5_pw1C2Nf48OR1skZEf7fTyOLJAg5A,12046
12
+ clerk/development/templates/exceptions.py.template,sha256=BN9MhFhH435WX3e6HTd7bmakOD6Kh24bDPDMHBrArvQ,446
13
+ clerk/development/templates/main_basic.py.template,sha256=9Cs5BC8FK2uFbxYEJfyHfpzbSz9tq2Q47XdUncbL0rM,550
14
+ clerk/development/templates/main_gui.py.template,sha256=e06QKs54DAVUWtz7xiDq1IKnAPNA5ecmnBuKlk9wC30,1796
15
+ clerk/development/templates/rollbacks.py.template,sha256=VeCVJhEwqol9LwRL5OfxIQUSOadbhGYYWrqjuqxO1bM,486
16
+ clerk/development/templates/states.py.template,sha256=d0OjZTdP8DNMt4YE0PIBPQ8jSpgll4u31s6n9aSJ1Mw,404
17
+ clerk/development/templates/transitions.py.template,sha256=PtkBbRxbEzqTqRa7zNDxrk8I1UhrithhBSKaO9r65uA,728
7
18
  clerk/exceptions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
19
  clerk/exceptions/exceptions.py,sha256=gSCma06b6W6c0NrA2rhzd5YjFhZGa6caShX07lo-_3E,1291
9
20
  clerk/exceptions/remote_device.py,sha256=R0Vfmk8ejibEFeV29A8Vqst2YA6yxdqEX9lP5wWubgM,134
10
21
  clerk/gui_automation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
22
  clerk/gui_automation/client.py,sha256=lLIim3i9PkdPlt5vmV4u2GoqQ571PHy7EvmRtTBv-JQ,5516
23
+ clerk/gui_automation/requirements.txt,sha256=FpktaUbpvdMPCUArx5FgvTjJQxt2g6IN3zu2XpkfrFo,45
12
24
  clerk/gui_automation/action_model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
25
  clerk/gui_automation/action_model/model.py,sha256=yzaCyEMOH3YMkPBf6IwUMuu69-xyf78HzmthiewgWQY,3811
14
26
  clerk/gui_automation/action_model/utils.py,sha256=xzFxgN-bTK6HKGS7J-esQZ-ePj_yG72T-2ZVhcWvKjw,798
@@ -25,11 +37,12 @@ clerk/gui_automation/exceptions/modality/__init__.py,sha256=47DEQpj8HBSa-_TImW-5
25
37
  clerk/gui_automation/exceptions/modality/exc.py,sha256=P-dMuCTyVZYD3pbGpCf_1SYEgaETn13c51pmfbsXr5k,1436
26
38
  clerk/gui_automation/ui_actions/__init__.py,sha256=-EDQ5375HXrvG3sfFY7zOPC405YcBL6xXRACm2p-YyI,23
27
39
  clerk/gui_automation/ui_actions/actions.py,sha256=r_gVnAOGfv7XZyli8b8ru0nsMqn_JiTAMTNvgVf8T1I,28789
28
- clerk/gui_automation/ui_actions/base.py,sha256=oaUI3vIOoDwP_HdLu2GIG46-aMv0_Zv-PljMgSFeNmk,7329
40
+ clerk/gui_automation/ui_actions/base.py,sha256=EXwjmX2gfksoWBGV6hW7MPkBSiSSK0X0DU6TZZvdo-o,7862
29
41
  clerk/gui_automation/ui_actions/support.py,sha256=Ulb8DBfwnrBMaYoMLDgldEy9V--NDUSdhIYXpuODZoU,5772
30
42
  clerk/gui_automation/ui_state_inspector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
43
  clerk/gui_automation/ui_state_inspector/gui_vision.py,sha256=Pk5nuFZnp_zNbqSOtndSmgqb6PLeADJfnC-eRIJMDZk,7736
32
44
  clerk/gui_automation/ui_state_inspector/models.py,sha256=qEbdrWGglOJH8QaOKoYp8ZKQMjnGk4JufpgYuTWoQ10,6082
45
+ clerk/gui_automation/ui_state_machine/Readme.md,sha256=8_cOu7zSSpIRNCY4C2DCwVlBvbQwmbiRff1VbH4yLek,2916
33
46
  clerk/gui_automation/ui_state_machine/__init__.py,sha256=bTPZsPJkDLCwP2mdtBj4fU7C7ekOh0b-VPRKFEV3bPo,301
34
47
  clerk/gui_automation/ui_state_machine/ai_recovery.py,sha256=aw6a7QCioZdcqf11yTxQg-ZnXAlXa5nPXi_cOBAuoG4,3871
35
48
  clerk/gui_automation/ui_state_machine/decorators.py,sha256=gBOpIusjsXlA7FEiszDCFKTS6vXx3LBNMz_SQJNkMWg,2134
@@ -45,8 +58,8 @@ clerk/models/ui_operator.py,sha256=mKTJUFZgv7PeEt5oys28HVZxHOJsofmRQOcRpqj0dbU,2
45
58
  clerk/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
59
  clerk/utils/logger.py,sha256=NrMIlJfVmRjjRw_N_Jngkl0qqv7btXUbg5wxcRmFEH4,3800
47
60
  clerk/utils/save_artifact.py,sha256=94aYkYNVGcSUaSWZmdjiY6Oc-3yCKb2XWCZ56IAXQqk,1158
48
- clerk_sdk-0.4.16.dev0.dist-info/licenses/LICENSE,sha256=GTVQl3vH6ht70wJXKC0yMT8CmXKHxv_YyO_utAgm7EA,1065
49
- clerk_sdk-0.4.16.dev0.dist-info/METADATA,sha256=U8QlEn0ANQxSkmowBLby6M8IJL-BKHkXxkQ5BL6lLhc,9942
50
- clerk_sdk-0.4.16.dev0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
51
- clerk_sdk-0.4.16.dev0.dist-info/top_level.txt,sha256=99eQiU6d05_-f41tmSFanfI_SIJeAdh7u9m3LNSfcv4,6
52
- clerk_sdk-0.4.16.dev0.dist-info/RECORD,,
61
+ clerk_sdk-0.5.0.dist-info/METADATA,sha256=wQkyLiNEMYSq7VZHGb9xr3teZ9BZsh4l-cUtOy37tj4,9597
62
+ clerk_sdk-0.5.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
63
+ clerk_sdk-0.5.0.dist-info/entry_points.txt,sha256=VoUmW07sRRSioms5pqQ4A6CYxNEyhGA93GtyBlB_wGw,53
64
+ clerk_sdk-0.5.0.dist-info/licenses/LICENSE,sha256=GTVQl3vH6ht70wJXKC0yMT8CmXKHxv_YyO_utAgm7EA,1065
65
+ clerk_sdk-0.5.0.dist-info/RECORD,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ clerk = clerk.development.cli:main
@@ -1 +0,0 @@
1
- clerk