clerk-sdk 0.4.4__tar.gz → 0.4.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.
Files changed (74) hide show
  1. clerk_sdk-0.4.6/PKG-INFO +254 -0
  2. clerk_sdk-0.4.6/README.md +217 -0
  3. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/__init__.py +3 -0
  4. clerk_sdk-0.4.6/clerk/client.py +138 -0
  5. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/client_actor/model.py +13 -16
  6. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/ui_actions/actions.py +24 -24
  7. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/ui_actions/base.py +2 -2
  8. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/utils/logger.py +4 -1
  9. clerk_sdk-0.4.6/clerk_sdk.egg-info/PKG-INFO +254 -0
  10. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk_sdk.egg-info/SOURCES.txt +9 -1
  11. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/setup.py +2 -2
  12. clerk_sdk-0.4.6/tests/test_base.py +154 -0
  13. clerk_sdk-0.4.6/tests/test_client.py +164 -0
  14. clerk_sdk-0.4.6/tests/test_document_models.py +79 -0
  15. clerk_sdk-0.4.6/tests/test_exceptions.py +14 -0
  16. clerk_sdk-0.4.6/tests/test_file_models.py +26 -0
  17. clerk_sdk-0.4.6/tests/test_gui_automation.py +266 -0
  18. clerk_sdk-0.4.6/tests/test_task_decorator.py +76 -0
  19. clerk_sdk-0.4.6/tests/test_utils.py +29 -0
  20. clerk_sdk-0.4.4/PKG-INFO +0 -128
  21. clerk_sdk-0.4.4/README.md +0 -91
  22. clerk_sdk-0.4.4/clerk/client.py +0 -66
  23. clerk_sdk-0.4.4/clerk_sdk.egg-info/PKG-INFO +0 -128
  24. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/LICENSE +0 -0
  25. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/MANIFEST.in +0 -0
  26. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/base.py +0 -0
  27. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/decorator/__init__.py +0 -0
  28. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/decorator/models.py +0 -0
  29. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/decorator/task_decorator.py +0 -0
  30. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/exceptions/__init__.py +0 -0
  31. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/exceptions/exceptions.py +0 -0
  32. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/exceptions/remote_device.py +0 -0
  33. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/__init__.py +0 -0
  34. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/action_model/__init__.py +0 -0
  35. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/action_model/model.py +0 -0
  36. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/action_model/utils.py +0 -0
  37. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/client.py +0 -0
  38. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/client_actor/__init__.py +0 -0
  39. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/client_actor/client_actor.py +0 -0
  40. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/client_actor/exception.py +0 -0
  41. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/decorators/__init__.py +0 -0
  42. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/decorators/gui_automation.py +0 -0
  43. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/exceptions/__init__.py +0 -0
  44. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/exceptions/agent_manager.py +0 -0
  45. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/exceptions/modality/__init__.py +0 -0
  46. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/exceptions/modality/exc.py +0 -0
  47. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/exceptions/websocket.py +0 -0
  48. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/requirements.txt +0 -0
  49. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/ui_actions/__init__.py +0 -0
  50. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/ui_actions/support.py +0 -0
  51. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/ui_state_inspector/__init__.py +0 -0
  52. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/ui_state_inspector/gui_vision.py +0 -0
  53. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/ui_state_inspector/models.py +0 -0
  54. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/ui_state_machine/__init__.py +0 -0
  55. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/ui_state_machine/ai_recovery.py +0 -0
  56. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/ui_state_machine/decorators.py +0 -0
  57. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/ui_state_machine/exceptions.py +0 -0
  58. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/ui_state_machine/models.py +0 -0
  59. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/gui_automation/ui_state_machine/state_machine.py +0 -0
  60. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/models/__init__.py +0 -0
  61. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/models/document.py +0 -0
  62. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/models/document_statuses.py +0 -0
  63. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/models/file.py +0 -0
  64. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/models/remote_device.py +0 -0
  65. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/models/response_model.py +0 -0
  66. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/models/ui_operator.py +0 -0
  67. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/utils/__init__.py +0 -0
  68. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk/utils/save_artifact.py +0 -0
  69. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk_sdk.egg-info/dependency_links.txt +0 -0
  70. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk_sdk.egg-info/requires.txt +0 -0
  71. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/clerk_sdk.egg-info/top_level.txt +0 -0
  72. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/pyproject.toml +0 -0
  73. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/requirements.txt +0 -0
  74. {clerk_sdk-0.4.4 → clerk_sdk-0.4.6}/setup.cfg +0 -0
@@ -0,0 +1,254 @@
1
+ Metadata-Version: 2.4
2
+ Name: clerk-sdk
3
+ Version: 0.4.6
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
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
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
+ Requires-Dist: backoff<3.0.0,>=2.0.0
16
+ Requires-Dist: requests<3.0.0,>=2.32.3
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"
23
+ 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
37
+
38
+ # Clerk Python SDK
39
+
40
+ A production-ready Python client for the Clerk API. The SDK wraps Clerk's REST endpoints, rich document models, automation helpers, and structured task decorators so that your applications can create, update, and process Clerk documents with minimal boilerplate.
41
+
42
+ ## Table of Contents
43
+ - [Overview](#overview)
44
+ - [Key Features](#key-features)
45
+ - [Requirements](#requirements)
46
+ - [Installation](#installation)
47
+ - [Configuration](#configuration)
48
+ - [Quick Start](#quick-start)
49
+ - [Instantiate a Client](#instantiate-a-client)
50
+ - [Fetch Documents](#fetch-documents)
51
+ - [Upload a Document](#upload-a-document)
52
+ - [Update Structured Data](#update-structured-data)
53
+ - [Work with Files](#work-with-files)
54
+ - [Automation Utilities](#automation-utilities)
55
+ - [Task Decorator](#task-decorator)
56
+ - [GUI Automation Toolkit](#gui-automation-toolkit)
57
+ - [Error Handling](#error-handling)
58
+ - [Development Workflow](#development-workflow)
59
+ - [Contributing](#contributing)
60
+ - [License](#license)
61
+
62
+ ## Overview
63
+ The Clerk SDK centers around the `Clerk` client (`clerk.client.Clerk`), which extends a resilient `BaseClerk` transport layer with automatic retries and typed responses. Models under `clerk.models` provide Pydantic-powered validation for documents, files, and API payloads, ensuring type safety across network boundaries. Additional modules cover automated task execution via the `clerk.decorator` package and UI workflows under `clerk.gui_automation`.
64
+
65
+ ## Key Features
66
+ - **Document lifecycle management** – Create, fetch, list, and update Clerk documents with first-class models.
67
+ - **File handling** – Upload binary files or parsed base64 payloads and attach them to documents.
68
+ - **Robust networking** – Automatic retries for transient HTTP issues, configurable base URLs, and bearer authentication out of the box.
69
+ - **Structured task execution** – Decorators for running Clerk tasks locally or inside worker environments with consistent pickle-based I/O.
70
+ - **GUI automations** – Utilities for orchestrating low-level UI actions, state machines, and operator interactions when human-in-the-loop steps are required.
71
+
72
+ ## Requirements
73
+ - Python 3.10+
74
+ - Dependencies listed in [`requirements.txt`](requirements.txt), including `pydantic` and `backoff`.
75
+
76
+ ## Installation
77
+ Install the SDK from PyPI:
78
+
79
+ ```bash
80
+ pip install clerk-sdk
81
+ ```
82
+
83
+ For local development inside this repository, install the dependencies in editable mode:
84
+
85
+ ```bash
86
+ pip install -e .[dev]
87
+ ```
88
+
89
+ ## Configuration
90
+ The client reads configuration from keyword arguments or environment variables.
91
+
92
+ | Setting | Environment Variable | Description |
93
+ | --- | --- | --- |
94
+ | API key | `CLERK_API_KEY` | Required secret used for bearer authentication. |
95
+ | Base URL | `CLERK_BASE_URL` | Optional override of the default API host (`https://api.clerk-app.com`). |
96
+
97
+ ```bash
98
+ export CLERK_API_KEY="sk_live_123"
99
+ export CLERK_BASE_URL="https://staging.clerk-app.com" # optional
100
+ ```
101
+
102
+ You can also pass the API key directly when instantiating `Clerk`:
103
+
104
+ ```python
105
+ from clerk import Clerk
106
+
107
+ client = Clerk(api_key="sk_live_123")
108
+ ```
109
+
110
+ ## Quick Start
111
+ The following snippets demonstrate the core document operations supported by the SDK.
112
+
113
+ ### Instantiate a Client
114
+ ```python
115
+ from clerk import Clerk
116
+
117
+ client = Clerk(api_key="sk_live_123")
118
+ ```
119
+
120
+ ### Fetch Documents
121
+ Retrieve a single document by its identifier or list documents with query filters.
122
+
123
+ ```python
124
+ from clerk.models.document import GetDocumentsRequest
125
+
126
+ # Single document
127
+ invoice = client.get_document(document_id="doc_123")
128
+ print(invoice.title, invoice.status)
129
+
130
+ # Query multiple documents
131
+ request = GetDocumentsRequest(project_id="proj_456", limit=25)
132
+ documents = client.get_documents(request)
133
+ for doc in documents:
134
+ print(doc.id, doc.status)
135
+ ```
136
+
137
+ ### Upload a Document
138
+ Use `UploadDocumentRequest` to send metadata and file attachments. Files can be supplied as paths or `ParsedFile` instances.
139
+
140
+ ```python
141
+ from clerk.models.document import UploadDocumentRequest
142
+
143
+ upload_request = UploadDocumentRequest(
144
+ project_id="proj_456",
145
+ message_subject="Invoice 2024-01",
146
+ files=["/path/to/invoice.pdf"],
147
+ input_structured_data={"customer_id": "cust_789"},
148
+ )
149
+
150
+ created = client.upload_document(upload_request)
151
+ print(f"Created document: {created.id}")
152
+ ```
153
+
154
+ ### Update Structured Data
155
+ Patch a document's structured payload without re-uploading files.
156
+
157
+ ```python
158
+ updated = client.update_document_structured_data(
159
+ document_id="doc_123",
160
+ updated_structured_data={"status": "processed", "processed_by": "automation"},
161
+ )
162
+ print(updated.structured_data)
163
+ ```
164
+
165
+ ### Work with Files
166
+ Retrieve parsed file metadata or attach additional files to existing documents.
167
+
168
+ ```python
169
+ from clerk.models.file import UploadFile
170
+
171
+ # List associated files
172
+ files = client.get_files_document(document_id="doc_123")
173
+ for file in files:
174
+ print(file.name, file.mimetype)
175
+
176
+ # Append output files
177
+ client.add_files_to_document(
178
+ document_id="doc_123",
179
+ type="output",
180
+ files=[
181
+ UploadFile(name="summary.txt", mimetype="text/plain", content=b"Processed")
182
+ ],
183
+ )
184
+ ```
185
+
186
+ ## Custom Code Utilities
187
+ ### Task Decorator
188
+ The `@clerk_code` decorator standardizes how Clerk tasks load inputs and persist outputs when executed by the Clerk workflow. It automatically reads a pickled `ClerkCodePayload` from `/app/data/input/input.pkl`, executes your function, and writes the result (or an `ApplicationException`) to `/app/data/output/output.pkl`.
189
+
190
+ ```python
191
+ from clerk.decorator import clerk_code
192
+ from clerk.decorator.models import ClerkCodePayload, Document
193
+
194
+ @clerk_code()
195
+ def handle_document(payload: ClerkCodePayload) -> ClerkCodePayload:
196
+ document: Document = payload.document
197
+ payload.structured_data = payload.structured_data or {}
198
+ payload.structured_data["status"] = f"Processed {document.id}"
199
+ return payload
200
+
201
+ if __name__ == "__main__":
202
+ handle_document() # Auto-loads from pickle files when payload is omitted
203
+ ```
204
+
205
+ For unit testing, you can bypass the pickle integration by passing an explicit payload instance:
206
+
207
+ ```python
208
+ from datetime import datetime
209
+ from clerk.decorator.models import ClerkCodePayload, Document
210
+ from clerk.models.document_statuses import DocumentStatuses
211
+
212
+ sample_payload = ClerkCodePayload(
213
+ document=Document(
214
+ id="doc_123",
215
+ project_id="proj_456",
216
+ title="Sample",
217
+ upload_date=datetime.utcnow(),
218
+ status=DocumentStatuses.draft,
219
+ created_at=datetime.utcnow(),
220
+ updated_at=datetime.utcnow(),
221
+ ),
222
+ structured_data={},
223
+ )
224
+ result = handle_document(sample_payload)
225
+ assert "Processed" in result.structured_data["status"]
226
+ ```
227
+
228
+ > **Note:** Refer to `tests/test_task_decorator.py` for additional usage examples covering error propagation and pickle round-trips.
229
+
230
+ ### GUI Automation Toolkit
231
+ The `clerk.gui_automation` package contains models, actions, and state machines for orchestrating UI interactions. Highlights include:
232
+
233
+ - `BaseAction` and concrete actions for cursor movement, clicks, and keyboard input.
234
+ - `ActionModel` builders that translate payloads into executable UI sequences.
235
+ - State machine primitives (`ui_state_machine`) to coordinate multi-step automations.
236
+ - Helpers for safely reading files, validating anchors, and converting payload flags.
237
+
238
+ These utilities are designed to be composed with your own automation runners or integrated into Clerk tasks. Review the tests in `tests/test_gui_automation.py` for patterns on stubbing operator clients and verifying payload transformations.
239
+
240
+ ## Error Handling
241
+ All network helpers raise `requests` exceptions for HTTP errors. When using the task decorator, runtime failures are wrapped in `ApplicationException` objects that capture the exception type, message, and traceback for easier debugging. Deserialize the returned payload or inspect the pickle output to handle errors gracefully.
242
+
243
+ ## Development Workflow
244
+ 1. **Clone the repository** and install dependencies with `pip install -e .[dev]`.
245
+ 2. **Run the test suite** using `pytest`. The CI workflow executes these tests before packaging releases.
246
+ 3. **Add type-safe models** or extend the client in `clerk/client.py` and `clerk/models` as needed.
247
+ 4. **Contribute automations** under `clerk/gui_automation` by following the established action/state machine patterns.
248
+ 5. **Commit and open a pull request** once tests pass and documentation is updated.
249
+
250
+ ## Contributing
251
+ Contributions are welcome! Please open an issue to discuss substantial changes, follow the existing code style (Pydantic models, typed functions, and pytest fixtures), and ensure the test suite passes before submitting a pull request.
252
+
253
+ ## License
254
+ This project is licensed under the MIT License. See [LICENSE](LICENSE) for details.
@@ -0,0 +1,217 @@
1
+ # Clerk Python SDK
2
+
3
+ A production-ready Python client for the Clerk API. The SDK wraps Clerk's REST endpoints, rich document models, automation helpers, and structured task decorators so that your applications can create, update, and process Clerk documents with minimal boilerplate.
4
+
5
+ ## Table of Contents
6
+ - [Overview](#overview)
7
+ - [Key Features](#key-features)
8
+ - [Requirements](#requirements)
9
+ - [Installation](#installation)
10
+ - [Configuration](#configuration)
11
+ - [Quick Start](#quick-start)
12
+ - [Instantiate a Client](#instantiate-a-client)
13
+ - [Fetch Documents](#fetch-documents)
14
+ - [Upload a Document](#upload-a-document)
15
+ - [Update Structured Data](#update-structured-data)
16
+ - [Work with Files](#work-with-files)
17
+ - [Automation Utilities](#automation-utilities)
18
+ - [Task Decorator](#task-decorator)
19
+ - [GUI Automation Toolkit](#gui-automation-toolkit)
20
+ - [Error Handling](#error-handling)
21
+ - [Development Workflow](#development-workflow)
22
+ - [Contributing](#contributing)
23
+ - [License](#license)
24
+
25
+ ## Overview
26
+ The Clerk SDK centers around the `Clerk` client (`clerk.client.Clerk`), which extends a resilient `BaseClerk` transport layer with automatic retries and typed responses. Models under `clerk.models` provide Pydantic-powered validation for documents, files, and API payloads, ensuring type safety across network boundaries. Additional modules cover automated task execution via the `clerk.decorator` package and UI workflows under `clerk.gui_automation`.
27
+
28
+ ## Key Features
29
+ - **Document lifecycle management** – Create, fetch, list, and update Clerk documents with first-class models.
30
+ - **File handling** – Upload binary files or parsed base64 payloads and attach them to documents.
31
+ - **Robust networking** – Automatic retries for transient HTTP issues, configurable base URLs, and bearer authentication out of the box.
32
+ - **Structured task execution** – Decorators for running Clerk tasks locally or inside worker environments with consistent pickle-based I/O.
33
+ - **GUI automations** – Utilities for orchestrating low-level UI actions, state machines, and operator interactions when human-in-the-loop steps are required.
34
+
35
+ ## Requirements
36
+ - Python 3.10+
37
+ - Dependencies listed in [`requirements.txt`](requirements.txt), including `pydantic` and `backoff`.
38
+
39
+ ## Installation
40
+ Install the SDK from PyPI:
41
+
42
+ ```bash
43
+ pip install clerk-sdk
44
+ ```
45
+
46
+ For local development inside this repository, install the dependencies in editable mode:
47
+
48
+ ```bash
49
+ pip install -e .[dev]
50
+ ```
51
+
52
+ ## Configuration
53
+ The client reads configuration from keyword arguments or environment variables.
54
+
55
+ | Setting | Environment Variable | Description |
56
+ | --- | --- | --- |
57
+ | API key | `CLERK_API_KEY` | Required secret used for bearer authentication. |
58
+ | Base URL | `CLERK_BASE_URL` | Optional override of the default API host (`https://api.clerk-app.com`). |
59
+
60
+ ```bash
61
+ export CLERK_API_KEY="sk_live_123"
62
+ export CLERK_BASE_URL="https://staging.clerk-app.com" # optional
63
+ ```
64
+
65
+ You can also pass the API key directly when instantiating `Clerk`:
66
+
67
+ ```python
68
+ from clerk import Clerk
69
+
70
+ client = Clerk(api_key="sk_live_123")
71
+ ```
72
+
73
+ ## Quick Start
74
+ The following snippets demonstrate the core document operations supported by the SDK.
75
+
76
+ ### Instantiate a Client
77
+ ```python
78
+ from clerk import Clerk
79
+
80
+ client = Clerk(api_key="sk_live_123")
81
+ ```
82
+
83
+ ### Fetch Documents
84
+ Retrieve a single document by its identifier or list documents with query filters.
85
+
86
+ ```python
87
+ from clerk.models.document import GetDocumentsRequest
88
+
89
+ # Single document
90
+ invoice = client.get_document(document_id="doc_123")
91
+ print(invoice.title, invoice.status)
92
+
93
+ # Query multiple documents
94
+ request = GetDocumentsRequest(project_id="proj_456", limit=25)
95
+ documents = client.get_documents(request)
96
+ for doc in documents:
97
+ print(doc.id, doc.status)
98
+ ```
99
+
100
+ ### Upload a Document
101
+ Use `UploadDocumentRequest` to send metadata and file attachments. Files can be supplied as paths or `ParsedFile` instances.
102
+
103
+ ```python
104
+ from clerk.models.document import UploadDocumentRequest
105
+
106
+ upload_request = UploadDocumentRequest(
107
+ project_id="proj_456",
108
+ message_subject="Invoice 2024-01",
109
+ files=["/path/to/invoice.pdf"],
110
+ input_structured_data={"customer_id": "cust_789"},
111
+ )
112
+
113
+ created = client.upload_document(upload_request)
114
+ print(f"Created document: {created.id}")
115
+ ```
116
+
117
+ ### Update Structured Data
118
+ Patch a document's structured payload without re-uploading files.
119
+
120
+ ```python
121
+ updated = client.update_document_structured_data(
122
+ document_id="doc_123",
123
+ updated_structured_data={"status": "processed", "processed_by": "automation"},
124
+ )
125
+ print(updated.structured_data)
126
+ ```
127
+
128
+ ### Work with Files
129
+ Retrieve parsed file metadata or attach additional files to existing documents.
130
+
131
+ ```python
132
+ from clerk.models.file import UploadFile
133
+
134
+ # List associated files
135
+ files = client.get_files_document(document_id="doc_123")
136
+ for file in files:
137
+ print(file.name, file.mimetype)
138
+
139
+ # Append output files
140
+ client.add_files_to_document(
141
+ document_id="doc_123",
142
+ type="output",
143
+ files=[
144
+ UploadFile(name="summary.txt", mimetype="text/plain", content=b"Processed")
145
+ ],
146
+ )
147
+ ```
148
+
149
+ ## Custom Code Utilities
150
+ ### Task Decorator
151
+ The `@clerk_code` decorator standardizes how Clerk tasks load inputs and persist outputs when executed by the Clerk workflow. It automatically reads a pickled `ClerkCodePayload` from `/app/data/input/input.pkl`, executes your function, and writes the result (or an `ApplicationException`) to `/app/data/output/output.pkl`.
152
+
153
+ ```python
154
+ from clerk.decorator import clerk_code
155
+ from clerk.decorator.models import ClerkCodePayload, Document
156
+
157
+ @clerk_code()
158
+ def handle_document(payload: ClerkCodePayload) -> ClerkCodePayload:
159
+ document: Document = payload.document
160
+ payload.structured_data = payload.structured_data or {}
161
+ payload.structured_data["status"] = f"Processed {document.id}"
162
+ return payload
163
+
164
+ if __name__ == "__main__":
165
+ handle_document() # Auto-loads from pickle files when payload is omitted
166
+ ```
167
+
168
+ For unit testing, you can bypass the pickle integration by passing an explicit payload instance:
169
+
170
+ ```python
171
+ from datetime import datetime
172
+ from clerk.decorator.models import ClerkCodePayload, Document
173
+ from clerk.models.document_statuses import DocumentStatuses
174
+
175
+ sample_payload = ClerkCodePayload(
176
+ document=Document(
177
+ id="doc_123",
178
+ project_id="proj_456",
179
+ title="Sample",
180
+ upload_date=datetime.utcnow(),
181
+ status=DocumentStatuses.draft,
182
+ created_at=datetime.utcnow(),
183
+ updated_at=datetime.utcnow(),
184
+ ),
185
+ structured_data={},
186
+ )
187
+ result = handle_document(sample_payload)
188
+ assert "Processed" in result.structured_data["status"]
189
+ ```
190
+
191
+ > **Note:** Refer to `tests/test_task_decorator.py` for additional usage examples covering error propagation and pickle round-trips.
192
+
193
+ ### GUI Automation Toolkit
194
+ The `clerk.gui_automation` package contains models, actions, and state machines for orchestrating UI interactions. Highlights include:
195
+
196
+ - `BaseAction` and concrete actions for cursor movement, clicks, and keyboard input.
197
+ - `ActionModel` builders that translate payloads into executable UI sequences.
198
+ - State machine primitives (`ui_state_machine`) to coordinate multi-step automations.
199
+ - Helpers for safely reading files, validating anchors, and converting payload flags.
200
+
201
+ These utilities are designed to be composed with your own automation runners or integrated into Clerk tasks. Review the tests in `tests/test_gui_automation.py` for patterns on stubbing operator clients and verifying payload transformations.
202
+
203
+ ## Error Handling
204
+ All network helpers raise `requests` exceptions for HTTP errors. When using the task decorator, runtime failures are wrapped in `ApplicationException` objects that capture the exception type, message, and traceback for easier debugging. Deserialize the returned payload or inspect the pickle output to handle errors gracefully.
205
+
206
+ ## Development Workflow
207
+ 1. **Clone the repository** and install dependencies with `pip install -e .[dev]`.
208
+ 2. **Run the test suite** using `pytest`. The CI workflow executes these tests before packaging releases.
209
+ 3. **Add type-safe models** or extend the client in `clerk/client.py` and `clerk/models` as needed.
210
+ 4. **Contribute automations** under `clerk/gui_automation` by following the established action/state machine patterns.
211
+ 5. **Commit and open a pull request** once tests pass and documentation is updated.
212
+
213
+ ## Contributing
214
+ Contributions are welcome! Please open an issue to discuss substantial changes, follow the existing code style (Pydantic models, typed functions, and pytest fixtures), and ensure the test suite passes before submitting a pull request.
215
+
216
+ ## License
217
+ This project is licensed under the MIT License. See [LICENSE](LICENSE) for details.
@@ -1 +1,4 @@
1
1
  from .client import Clerk
2
+
3
+
4
+ __version__ = "0.4.6"
@@ -0,0 +1,138 @@
1
+ from typing import Any, Dict, List, Literal
2
+
3
+ from clerk.base import BaseClerk
4
+ from clerk.models.document import Document, GetDocumentsRequest, UploadDocumentRequest
5
+ from .models.file import ParsedFile, UploadFile
6
+
7
+
8
+ class Clerk(BaseClerk):
9
+
10
+ def upload_document(self, request: UploadDocumentRequest) -> Document:
11
+ endpoint = "/document"
12
+ res = self.post_request(
13
+ endpoint=endpoint, data=request.data, files=request.files_
14
+ )
15
+ return Document(**res.data[0])
16
+
17
+ def cancel_document_run(self, document_id: str) -> Document:
18
+ endpoint = f"/document/{document_id}/cancel"
19
+ res = self.post_request(endpoint=endpoint)
20
+ return Document(**res.data[0])
21
+
22
+ def update_document_structured_data(
23
+ self, document_id: str, updated_structured_data: Dict[str, Any]
24
+ ) -> Document:
25
+ endpoint = f"/document/{document_id}"
26
+ payload = dict(structured_data=updated_structured_data)
27
+ res = self.put_request(endpoint, json=payload)
28
+
29
+ return Document(**res.data[0])
30
+
31
+ def get_document(self, document_id: str) -> Document:
32
+ endpoint = f"/document/{document_id}"
33
+ res = self.get_request(endpoint=endpoint)
34
+ return Document(**res.data[0])
35
+
36
+ def get_documents(self, request: GetDocumentsRequest) -> List[Document]:
37
+ if not any(
38
+ [
39
+ request.organization_id,
40
+ request.project_id,
41
+ request.start_date,
42
+ request.end_date,
43
+ request.query,
44
+ request.include_statuses,
45
+ ]
46
+ ):
47
+ raise ValueError(
48
+ "At least one query parameter (organization_id, project_id, start_date, end_date, query, or include_statuses) must be provided."
49
+ )
50
+
51
+ endpoint = f"/documents"
52
+ params = request.model_dump(mode="json")
53
+ res = self.get_request(endpoint, params=params)
54
+
55
+ return [Document(**d) for d in res.data]
56
+
57
+ def get_files_document(self, document_id: str) -> List[ParsedFile]:
58
+ endpoint = f"/document/{document_id}/files"
59
+ res = self.get_request(endpoint=endpoint)
60
+ return [ParsedFile(**d) for d in res.data]
61
+
62
+ def add_files_to_document(
63
+ self,
64
+ document_id: str,
65
+ type: Literal["input", "output"],
66
+ files: List[UploadFile],
67
+ ):
68
+ endpoint = f"/document/{document_id}/files/upload"
69
+ params = {"type": type}
70
+ files_data = [f.to_multipart_format() for f in files]
71
+ self.post_request(endpoint, params=params, files=files_data)
72
+
73
+
74
+ class ClerkDocument(BaseClerk):
75
+ endpoint: str = "/document"
76
+
77
+ def upload_document(self, request: UploadDocumentRequest) -> Document:
78
+ endpoint = "/document"
79
+ res = self.post_request(
80
+ endpoint=endpoint, data=request.data, files=request.files_
81
+ )
82
+ return Document(**res.data[0])
83
+
84
+ def cancel_document_run(self, document_id: str) -> Document:
85
+ endpoint = f"/document/{document_id}/cancel"
86
+ res = self.post_request(endpoint=endpoint)
87
+ return Document(**res.data[0])
88
+
89
+ def update_document_structured_data(
90
+ self, document_id: str, updated_structured_data: Dict[str, Any]
91
+ ) -> Document:
92
+ endpoint = f"/document/{document_id}"
93
+ payload = dict(structured_data=updated_structured_data)
94
+ res = self.put_request(endpoint, json=payload)
95
+
96
+ return Document(**res.data[0])
97
+
98
+ def get_document(self, document_id: str) -> Document:
99
+ endpoint = f"/document/{document_id}"
100
+ res = self.get_request(endpoint=endpoint)
101
+ return Document(**res.data[0])
102
+
103
+ def get_documents(self, request: GetDocumentsRequest) -> List[Document]:
104
+ if not any(
105
+ [
106
+ request.organization_id,
107
+ request.project_id,
108
+ request.start_date,
109
+ request.end_date,
110
+ request.query,
111
+ request.include_statuses,
112
+ ]
113
+ ):
114
+ raise ValueError(
115
+ "At least one query parameter (organization_id, project_id, start_date, end_date, query, or include_statuses) must be provided."
116
+ )
117
+
118
+ endpoint = f"/documents"
119
+ params = request.model_dump(mode="json")
120
+ res = self.get_request(endpoint, params=params)
121
+
122
+ return [Document(**d) for d in res.data]
123
+
124
+ def get_files_document(self, document_id: str) -> List[ParsedFile]:
125
+ endpoint = f"/document/{document_id}/files"
126
+ res = self.get_request(endpoint=endpoint)
127
+ return [ParsedFile(**d) for d in res.data]
128
+
129
+ def add_files_to_document(
130
+ self,
131
+ document_id: str,
132
+ type: Literal["input", "output"],
133
+ files: List[UploadFile],
134
+ ):
135
+ endpoint = f"/document/{document_id}/files/upload"
136
+ params = {"type": type}
137
+ files_data = [f.to_multipart_format() for f in files]
138
+ self.post_request(endpoint, params=params, files=files_data)
@@ -1,22 +1,20 @@
1
- from typing import Any, List, Literal, Optional, TypeAlias, Union
1
+ from typing import Any, List, Literal, Optional, Union
2
2
  from pydantic import BaseModel, Field
3
3
  from enum import Enum
4
4
 
5
- from clerk.gui_automation.ui_actions.base import ActionTypes
6
5
 
7
-
8
- # ActionTypes = Literal[
9
- # "left_click",
10
- # "right_click",
11
- # "middle_click",
12
- # "double_click",
13
- # "send_keys",
14
- # "press_keys",
15
- # "hot_keys",
16
- # "paste_text",
17
- # "get_text",
18
- # "scroll",
19
- # ]
6
+ ActionTypes = Literal[
7
+ "left_click",
8
+ "right_click",
9
+ "middle_click",
10
+ "double_click",
11
+ "send_keys",
12
+ "press_keys",
13
+ "hot_keys",
14
+ "paste_text",
15
+ "get_text",
16
+ "scroll",
17
+ ]
20
18
 
21
19
 
22
20
  class ActionStates(Enum):
@@ -79,7 +77,6 @@ class WindowExecutePayload(BaseModel):
79
77
  "close_window",
80
78
  "activate_window",
81
79
  ]
82
-
83
80
  window_name: str
84
81
  timeout: int = Field(default=10)
85
82