cmdop 0.1.25__py3-none-any.whl → 0.1.26__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.
- cmdop/__init__.py +9 -4
- cmdop/_generated/rpc_messages/browser_pb2.py +138 -138
- cmdop/_generated/rpc_messages/browser_pb2.pyi +6 -2
- cmdop/api/generated/machines/__init__.py +1 -1
- cmdop/api/generated/machines/enums.py +0 -112
- cmdop/api/generated/machines/machines__api__machine_sharing/client.py +21 -6
- cmdop/api/generated/machines/machines__api__machine_sharing/models.py +46 -19
- cmdop/api/generated/machines/machines__api__machine_sharing/sync_client.py +20 -5
- cmdop/api/generated/machines/machines__api__machines/client.py +90 -25
- cmdop/api/generated/machines/machines__api__machines/models.py +143 -125
- cmdop/api/generated/machines/machines__api__machines/sync_client.py +84 -19
- cmdop/api/generated/machines/schema.json +72 -0
- cmdop/api/generated/system/__init__.py +1 -1
- cmdop/api/generated/system/enums.py +0 -52
- cmdop/api/generated/system/schema.json +54 -0
- cmdop/api/generated/system/system__api__oauth/client.py +42 -12
- cmdop/api/generated/system/system__api__oauth/models.py +111 -85
- cmdop/api/generated/system/system__api__oauth/sync_client.py +38 -8
- cmdop/api/generated/system/system__api__system/client.py +98 -23
- cmdop/api/generated/system/system__api__system/models.py +83 -83
- cmdop/api/generated/system/system__api__system/sync_client.py +94 -19
- cmdop/api/generated/workspaces/__init__.py +1 -1
- cmdop/api/generated/workspaces/enums.py +0 -137
- cmdop/api/generated/workspaces/schema.json +47 -0
- cmdop/api/generated/workspaces/workspaces__api__workspaces/client.py +156 -41
- cmdop/api/generated/workspaces/workspaces__api__workspaces/models.py +126 -85
- cmdop/api/generated/workspaces/workspaces__api__workspaces/sync_client.py +145 -29
- cmdop/helpers/__init__.py +0 -4
- cmdop/services/browser/service/sync.py +4 -0
- {cmdop-0.1.25.dist-info → cmdop-0.1.26.dist-info}/METADATA +24 -14
- {cmdop-0.1.25.dist-info → cmdop-0.1.26.dist-info}/RECORD +33 -35
- cmdop/helpers/cleaner.py +0 -53
- cmdop/helpers/formatting.py +0 -15
- {cmdop-0.1.25.dist-info → cmdop-0.1.26.dist-info}/WHEEL +0 -0
- {cmdop-0.1.25.dist-info → cmdop-0.1.26.dist-info}/licenses/LICENSE +0 -0
|
@@ -12,15 +12,20 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
12
12
|
"""Initialize sync sub-client with shared httpx client."""
|
|
13
13
|
self._client = client
|
|
14
14
|
|
|
15
|
-
def invitations_list(self, page: int | None = None, page_size: int | None = None) -> list[PaginatedWorkspaceInvitationList]:
|
|
15
|
+
def invitations_list(self, ordering: str | None = None, page: int | None = None, page_size: int | None = None, search: str | None = None) -> list[PaginatedWorkspaceInvitationList]:
|
|
16
16
|
"""
|
|
17
17
|
List invitations
|
|
18
18
|
|
|
19
19
|
List all pending invitations for workspaces you manage
|
|
20
20
|
"""
|
|
21
21
|
url = "/api/workspaces/invitations/"
|
|
22
|
-
response = self._client.get(url, params={"page": page if page is not None else None, "page_size": page_size if page_size is not None else None})
|
|
23
|
-
response.
|
|
22
|
+
response = self._client.get(url, params={"ordering": ordering if ordering is not None else None, "page": page if page is not None else None, "page_size": page_size if page_size is not None else None, "search": search if search is not None else None})
|
|
23
|
+
if not response.is_success:
|
|
24
|
+
try:
|
|
25
|
+
error_body = response.json()
|
|
26
|
+
except Exception:
|
|
27
|
+
error_body = response.text
|
|
28
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
24
29
|
return PaginatedWorkspaceInvitationList.model_validate(response.json())
|
|
25
30
|
|
|
26
31
|
|
|
@@ -32,7 +37,12 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
32
37
|
"""
|
|
33
38
|
url = "/api/workspaces/invitations/"
|
|
34
39
|
response = self._client.post(url, json=data.model_dump(exclude_unset=True))
|
|
35
|
-
response.
|
|
40
|
+
if not response.is_success:
|
|
41
|
+
try:
|
|
42
|
+
error_body = response.json()
|
|
43
|
+
except Exception:
|
|
44
|
+
error_body = response.text
|
|
45
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
36
46
|
return WorkspaceInvitation.model_validate(response.json())
|
|
37
47
|
|
|
38
48
|
|
|
@@ -44,7 +54,12 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
44
54
|
"""
|
|
45
55
|
url = f"/api/workspaces/invitations/{id}/"
|
|
46
56
|
response = self._client.get(url)
|
|
47
|
-
response.
|
|
57
|
+
if not response.is_success:
|
|
58
|
+
try:
|
|
59
|
+
error_body = response.json()
|
|
60
|
+
except Exception:
|
|
61
|
+
error_body = response.text
|
|
62
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
48
63
|
return WorkspaceInvitation.model_validate(response.json())
|
|
49
64
|
|
|
50
65
|
|
|
@@ -56,7 +71,12 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
56
71
|
"""
|
|
57
72
|
url = f"/api/workspaces/invitations/{id}/"
|
|
58
73
|
response = self._client.delete(url)
|
|
59
|
-
response.
|
|
74
|
+
if not response.is_success:
|
|
75
|
+
try:
|
|
76
|
+
error_body = response.json()
|
|
77
|
+
except Exception:
|
|
78
|
+
error_body = response.text
|
|
79
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
60
80
|
|
|
61
81
|
|
|
62
82
|
def invitations_resend_create(self, id: str, data: WorkspaceInvitationRequest) -> WorkspaceInvitation:
|
|
@@ -67,7 +87,12 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
67
87
|
"""
|
|
68
88
|
url = f"/api/workspaces/invitations/{id}/resend/"
|
|
69
89
|
response = self._client.post(url, json=data.model_dump(exclude_unset=True))
|
|
70
|
-
response.
|
|
90
|
+
if not response.is_success:
|
|
91
|
+
try:
|
|
92
|
+
error_body = response.json()
|
|
93
|
+
except Exception:
|
|
94
|
+
error_body = response.text
|
|
95
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
71
96
|
return WorkspaceInvitation.model_validate(response.json())
|
|
72
97
|
|
|
73
98
|
|
|
@@ -79,7 +104,12 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
79
104
|
"""
|
|
80
105
|
url = "/api/workspaces/invitations/accept/"
|
|
81
106
|
response = self._client.post(url, json=data.model_dump(exclude_unset=True))
|
|
82
|
-
response.
|
|
107
|
+
if not response.is_success:
|
|
108
|
+
try:
|
|
109
|
+
error_body = response.json()
|
|
110
|
+
except Exception:
|
|
111
|
+
error_body = response.text
|
|
112
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
83
113
|
|
|
84
114
|
|
|
85
115
|
def invitations_decline_create(self, data: WorkspaceInvitationAcceptRequest) -> None:
|
|
@@ -90,7 +120,12 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
90
120
|
"""
|
|
91
121
|
url = "/api/workspaces/invitations/decline/"
|
|
92
122
|
response = self._client.post(url, json=data.model_dump(exclude_unset=True))
|
|
93
|
-
response.
|
|
123
|
+
if not response.is_success:
|
|
124
|
+
try:
|
|
125
|
+
error_body = response.json()
|
|
126
|
+
except Exception:
|
|
127
|
+
error_body = response.text
|
|
128
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
94
129
|
|
|
95
130
|
|
|
96
131
|
def invitations_details_retrieve(self, token: str) -> WorkspaceInvitationPublic:
|
|
@@ -101,17 +136,27 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
101
136
|
"""
|
|
102
137
|
url = f"/api/workspaces/invitations/details/{token}/"
|
|
103
138
|
response = self._client.get(url)
|
|
104
|
-
response.
|
|
139
|
+
if not response.is_success:
|
|
140
|
+
try:
|
|
141
|
+
error_body = response.json()
|
|
142
|
+
except Exception:
|
|
143
|
+
error_body = response.text
|
|
144
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
105
145
|
return WorkspaceInvitationPublic.model_validate(response.json())
|
|
106
146
|
|
|
107
147
|
|
|
108
|
-
def members_list(self, page: int | None = None, page_size: int | None = None, role: str | None = None, search: str | None = None) -> list[PaginatedWorkspaceMemberList]:
|
|
148
|
+
def members_list(self, ordering: str | None = None, page: int | None = None, page_size: int | None = None, role: str | None = None, search: str | None = None) -> list[PaginatedWorkspaceMemberList]:
|
|
109
149
|
"""
|
|
110
150
|
List workspace members with optional search and role filters.
|
|
111
151
|
"""
|
|
112
152
|
url = "/api/workspaces/members/"
|
|
113
|
-
response = self._client.get(url, params={"page": page if page is not None else None, "page_size": page_size if page_size is not None else None, "role": role if role is not None else None, "search": search if search is not None else None})
|
|
114
|
-
response.
|
|
153
|
+
response = self._client.get(url, params={"ordering": ordering if ordering is not None else None, "page": page if page is not None else None, "page_size": page_size if page_size is not None else None, "role": role if role is not None else None, "search": search if search is not None else None})
|
|
154
|
+
if not response.is_success:
|
|
155
|
+
try:
|
|
156
|
+
error_body = response.json()
|
|
157
|
+
except Exception:
|
|
158
|
+
error_body = response.text
|
|
159
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
115
160
|
return PaginatedWorkspaceMemberList.model_validate(response.json())
|
|
116
161
|
|
|
117
162
|
|
|
@@ -122,7 +167,12 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
122
167
|
"""
|
|
123
168
|
url = "/api/workspaces/members/"
|
|
124
169
|
response = self._client.post(url, json=data.model_dump(exclude_unset=True))
|
|
125
|
-
response.
|
|
170
|
+
if not response.is_success:
|
|
171
|
+
try:
|
|
172
|
+
error_body = response.json()
|
|
173
|
+
except Exception:
|
|
174
|
+
error_body = response.text
|
|
175
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
126
176
|
return WorkspaceMember.model_validate(response.json())
|
|
127
177
|
|
|
128
178
|
|
|
@@ -133,7 +183,12 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
133
183
|
"""
|
|
134
184
|
url = f"/api/workspaces/members/{id}/"
|
|
135
185
|
response = self._client.get(url)
|
|
136
|
-
response.
|
|
186
|
+
if not response.is_success:
|
|
187
|
+
try:
|
|
188
|
+
error_body = response.json()
|
|
189
|
+
except Exception:
|
|
190
|
+
error_body = response.text
|
|
191
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
137
192
|
return WorkspaceMember.model_validate(response.json())
|
|
138
193
|
|
|
139
194
|
|
|
@@ -144,7 +199,12 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
144
199
|
"""
|
|
145
200
|
url = f"/api/workspaces/members/{id}/"
|
|
146
201
|
response = self._client.put(url, json=data.model_dump(exclude_unset=True))
|
|
147
|
-
response.
|
|
202
|
+
if not response.is_success:
|
|
203
|
+
try:
|
|
204
|
+
error_body = response.json()
|
|
205
|
+
except Exception:
|
|
206
|
+
error_body = response.text
|
|
207
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
148
208
|
return WorkspaceMember.model_validate(response.json())
|
|
149
209
|
|
|
150
210
|
|
|
@@ -155,7 +215,12 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
155
215
|
"""
|
|
156
216
|
url = f"/api/workspaces/members/{id}/"
|
|
157
217
|
response = self._client.patch(url, json=data.model_dump(exclude_unset=True) if data is not None else None)
|
|
158
|
-
response.
|
|
218
|
+
if not response.is_success:
|
|
219
|
+
try:
|
|
220
|
+
error_body = response.json()
|
|
221
|
+
except Exception:
|
|
222
|
+
error_body = response.text
|
|
223
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
159
224
|
return WorkspaceMember.model_validate(response.json())
|
|
160
225
|
|
|
161
226
|
|
|
@@ -166,7 +231,12 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
166
231
|
"""
|
|
167
232
|
url = f"/api/workspaces/members/{id}/"
|
|
168
233
|
response = self._client.delete(url)
|
|
169
|
-
response.
|
|
234
|
+
if not response.is_success:
|
|
235
|
+
try:
|
|
236
|
+
error_body = response.json()
|
|
237
|
+
except Exception:
|
|
238
|
+
error_body = response.text
|
|
239
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
170
240
|
|
|
171
241
|
|
|
172
242
|
def members_update_role_create(self, id: str, data: WorkspaceMemberRequest) -> WorkspaceMember:
|
|
@@ -177,18 +247,29 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
177
247
|
"""
|
|
178
248
|
url = f"/api/workspaces/members/{id}/update-role/"
|
|
179
249
|
response = self._client.post(url, json=data.model_dump(exclude_unset=True))
|
|
180
|
-
response.
|
|
250
|
+
if not response.is_success:
|
|
251
|
+
try:
|
|
252
|
+
error_body = response.json()
|
|
253
|
+
except Exception:
|
|
254
|
+
error_body = response.text
|
|
255
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
181
256
|
return WorkspaceMember.model_validate(response.json())
|
|
182
257
|
|
|
183
258
|
|
|
184
|
-
def workspaces_list(self) ->
|
|
259
|
+
def workspaces_list(self, ordering: str | None = None, search: str | None = None) -> list[Workspace]:
|
|
185
260
|
"""
|
|
186
261
|
ViewSet for Workspace operations. Provides CRUD operations for
|
|
187
262
|
workspaces with team/personal modes.
|
|
188
263
|
"""
|
|
189
264
|
url = "/api/workspaces/workspaces/"
|
|
190
|
-
response = self._client.get(url)
|
|
191
|
-
response.
|
|
265
|
+
response = self._client.get(url, params={"ordering": ordering if ordering is not None else None, "search": search if search is not None else None})
|
|
266
|
+
if not response.is_success:
|
|
267
|
+
try:
|
|
268
|
+
error_body = response.json()
|
|
269
|
+
except Exception:
|
|
270
|
+
error_body = response.text
|
|
271
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
272
|
+
return [Workspace.model_validate(item) for item in response.json()]
|
|
192
273
|
|
|
193
274
|
|
|
194
275
|
def workspaces_create(self, data: WorkspaceCreateRequest) -> Workspace:
|
|
@@ -199,7 +280,12 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
199
280
|
"""
|
|
200
281
|
url = "/api/workspaces/workspaces/"
|
|
201
282
|
response = self._client.post(url, json=data.model_dump(exclude_unset=True))
|
|
202
|
-
response.
|
|
283
|
+
if not response.is_success:
|
|
284
|
+
try:
|
|
285
|
+
error_body = response.json()
|
|
286
|
+
except Exception:
|
|
287
|
+
error_body = response.text
|
|
288
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
203
289
|
return Workspace.model_validate(response.json())
|
|
204
290
|
|
|
205
291
|
|
|
@@ -210,7 +296,12 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
210
296
|
"""
|
|
211
297
|
url = f"/api/workspaces/workspaces/{id}/"
|
|
212
298
|
response = self._client.get(url)
|
|
213
|
-
response.
|
|
299
|
+
if not response.is_success:
|
|
300
|
+
try:
|
|
301
|
+
error_body = response.json()
|
|
302
|
+
except Exception:
|
|
303
|
+
error_body = response.text
|
|
304
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
214
305
|
return Workspace.model_validate(response.json())
|
|
215
306
|
|
|
216
307
|
|
|
@@ -221,7 +312,12 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
221
312
|
"""
|
|
222
313
|
url = f"/api/workspaces/workspaces/{id}/"
|
|
223
314
|
response = self._client.put(url, json=data.model_dump(exclude_unset=True))
|
|
224
|
-
response.
|
|
315
|
+
if not response.is_success:
|
|
316
|
+
try:
|
|
317
|
+
error_body = response.json()
|
|
318
|
+
except Exception:
|
|
319
|
+
error_body = response.text
|
|
320
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
225
321
|
return Workspace.model_validate(response.json())
|
|
226
322
|
|
|
227
323
|
|
|
@@ -232,7 +328,12 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
232
328
|
"""
|
|
233
329
|
url = f"/api/workspaces/workspaces/{id}/"
|
|
234
330
|
response = self._client.patch(url, json=data.model_dump(exclude_unset=True) if data is not None else None)
|
|
235
|
-
response.
|
|
331
|
+
if not response.is_success:
|
|
332
|
+
try:
|
|
333
|
+
error_body = response.json()
|
|
334
|
+
except Exception:
|
|
335
|
+
error_body = response.text
|
|
336
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
236
337
|
return Workspace.model_validate(response.json())
|
|
237
338
|
|
|
238
339
|
|
|
@@ -243,7 +344,12 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
243
344
|
"""
|
|
244
345
|
url = f"/api/workspaces/workspaces/{id}/"
|
|
245
346
|
response = self._client.delete(url)
|
|
246
|
-
response.
|
|
347
|
+
if not response.is_success:
|
|
348
|
+
try:
|
|
349
|
+
error_body = response.json()
|
|
350
|
+
except Exception:
|
|
351
|
+
error_body = response.text
|
|
352
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
247
353
|
|
|
248
354
|
|
|
249
355
|
def workspaces_members_retrieve(self, id: str) -> None:
|
|
@@ -254,7 +360,12 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
254
360
|
"""
|
|
255
361
|
url = f"/api/workspaces/workspaces/{id}/members/"
|
|
256
362
|
response = self._client.get(url)
|
|
257
|
-
response.
|
|
363
|
+
if not response.is_success:
|
|
364
|
+
try:
|
|
365
|
+
error_body = response.json()
|
|
366
|
+
except Exception:
|
|
367
|
+
error_body = response.text
|
|
368
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
258
369
|
|
|
259
370
|
|
|
260
371
|
def workspaces_stats_retrieve(self, id: str) -> None:
|
|
@@ -265,6 +376,11 @@ class SyncWorkspacesWorkspacesAPI:
|
|
|
265
376
|
"""
|
|
266
377
|
url = f"/api/workspaces/workspaces/{id}/stats/"
|
|
267
378
|
response = self._client.get(url)
|
|
268
|
-
response.
|
|
379
|
+
if not response.is_success:
|
|
380
|
+
try:
|
|
381
|
+
error_body = response.json()
|
|
382
|
+
except Exception:
|
|
383
|
+
error_body = response.text
|
|
384
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
269
385
|
|
|
270
386
|
|
cmdop/helpers/__init__.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
"""CMDOP SDK helpers."""
|
|
2
2
|
|
|
3
|
-
from cmdop.helpers.formatting import json_to_toon
|
|
4
|
-
from cmdop.helpers.cleaner import JsonCleaner
|
|
5
3
|
from cmdop.helpers.network_analyzer import (
|
|
6
4
|
NetworkAnalyzer,
|
|
7
5
|
NetworkSnapshot,
|
|
@@ -9,8 +7,6 @@ from cmdop.helpers.network_analyzer import (
|
|
|
9
7
|
)
|
|
10
8
|
|
|
11
9
|
__all__ = [
|
|
12
|
-
"json_to_toon",
|
|
13
|
-
"JsonCleaner",
|
|
14
10
|
"NetworkAnalyzer",
|
|
15
11
|
"NetworkSnapshot",
|
|
16
12
|
"RequestSnapshot",
|
|
@@ -45,6 +45,8 @@ class BrowserService(BaseService, BaseServiceMixin):
|
|
|
45
45
|
headless: bool = False,
|
|
46
46
|
width: int = 1280,
|
|
47
47
|
height: int = 800,
|
|
48
|
+
block_images: bool = False,
|
|
49
|
+
block_media: bool = False,
|
|
48
50
|
) -> "BrowserSession":
|
|
49
51
|
from cmdop._generated.rpc_messages.browser_pb2 import BrowserCreateSessionRequest
|
|
50
52
|
from cmdop.services.browser.session import BrowserSession
|
|
@@ -56,6 +58,8 @@ class BrowserService(BaseService, BaseServiceMixin):
|
|
|
56
58
|
headless=headless,
|
|
57
59
|
width=width,
|
|
58
60
|
height=height,
|
|
61
|
+
block_images=block_images,
|
|
62
|
+
block_media=block_media,
|
|
59
63
|
)
|
|
60
64
|
response = self._call_sync(self._get_stub.BrowserCreateSession, request)
|
|
61
65
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cmdop
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.26
|
|
4
4
|
Summary: Python SDK for CMDOP agent interaction
|
|
5
5
|
Project-URL: Homepage, https://cmdop.com
|
|
6
6
|
Project-URL: Documentation, https://cmdop.com
|
|
@@ -19,17 +19,14 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
19
19
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
20
|
Classifier: Typing :: Typed
|
|
21
21
|
Requires-Python: >=3.10
|
|
22
|
-
Requires-Dist: beautifulsoup4>=4.12.0
|
|
23
22
|
Requires-Dist: grpcio>=1.60.0
|
|
24
23
|
Requires-Dist: httpx>=0.27.0
|
|
25
|
-
Requires-Dist: lxml>=5.0.0
|
|
26
24
|
Requires-Dist: protobuf>=4.25.0
|
|
27
25
|
Requires-Dist: pydantic-settings>=2.0.0
|
|
28
26
|
Requires-Dist: pydantic>=2.5.0
|
|
29
27
|
Requires-Dist: rich>=13.0.0
|
|
30
28
|
Requires-Dist: toon-python>=0.1.2
|
|
31
29
|
Provides-Extra: dev
|
|
32
|
-
Requires-Dist: beautifulsoup4>=4.12.0; extra == 'dev'
|
|
33
30
|
Requires-Dist: grpcio-tools>=1.60.0; extra == 'dev'
|
|
34
31
|
Requires-Dist: mypy>=1.8.0; extra == 'dev'
|
|
35
32
|
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
@@ -91,8 +88,28 @@ with client.browser.create_session(headless=False) as s:
|
|
|
91
88
|
s.get_page_info() # Full page info
|
|
92
89
|
s.get_cookies()
|
|
93
90
|
s.set_cookies([...])
|
|
91
|
+
|
|
92
|
+
# Fast mode: block images and media for faster page loads
|
|
93
|
+
with client.browser.create_session(
|
|
94
|
+
block_images=True,
|
|
95
|
+
block_media=True,
|
|
96
|
+
) as s:
|
|
97
|
+
s.navigate("https://shop.com/catalog")
|
|
98
|
+
items = s.dom.extract(".product-title")
|
|
94
99
|
```
|
|
95
100
|
|
|
101
|
+
**`create_session` parameters:**
|
|
102
|
+
| Parameter | Default | Description |
|
|
103
|
+
|-----------|---------|-------------|
|
|
104
|
+
| `start_url` | `None` | Initial URL to navigate to |
|
|
105
|
+
| `provider` | `"camoufox"` | Browser provider (`"camoufox"` or `"rod"`) |
|
|
106
|
+
| `profile_id` | `None` | Profile ID for session persistence (cookies, localStorage) |
|
|
107
|
+
| `headless` | `False` | Run browser without UI |
|
|
108
|
+
| `width` | `1280` | Viewport width |
|
|
109
|
+
| `height` | `800` | Viewport height |
|
|
110
|
+
| `block_images` | `False` | Disable loading images (set at launch, cannot change at runtime) |
|
|
111
|
+
| `block_media` | `False` | Disable loading audio/video (set at launch, cannot change at runtime) |
|
|
112
|
+
|
|
96
113
|
**WaitUntil options:**
|
|
97
114
|
| Value | Description |
|
|
98
115
|
|-------|-------------|
|
|
@@ -143,8 +160,6 @@ s.timing.timeout(fn, 10, cleanup) # Run with timeout
|
|
|
143
160
|
```python
|
|
144
161
|
s.dom.html(".container") # Get HTML
|
|
145
162
|
s.dom.text(".title") # Get text
|
|
146
|
-
s.dom.soup(".items") # → SoupWrapper (chainable BS4)
|
|
147
|
-
s.dom.parse(html_string) # → BeautifulSoup
|
|
148
163
|
s.dom.extract(".items", "href") # Get attr list
|
|
149
164
|
s.dom.select("#country", "US") # Dropdown select
|
|
150
165
|
s.dom.close_modal() # Close dialogs/popups
|
|
@@ -302,18 +317,13 @@ class Product(SDKBaseModel):
|
|
|
302
317
|
products = Product.from_list(raw["items"]) # Auto dedupe + filter
|
|
303
318
|
```
|
|
304
319
|
|
|
305
|
-
##
|
|
320
|
+
## Logging
|
|
306
321
|
|
|
307
322
|
```python
|
|
308
|
-
from cmdop import get_logger
|
|
323
|
+
from cmdop import get_logger
|
|
309
324
|
|
|
310
|
-
# Logging (rich console + file)
|
|
311
325
|
log = get_logger(__name__)
|
|
312
|
-
log.info("Starting")
|
|
313
|
-
|
|
314
|
-
# TOON format (30-50% token savings)
|
|
315
|
-
toon = json_to_toon({"name": "Alice", "age": 25})
|
|
316
|
-
# → "name: Alice\nage: 25"
|
|
326
|
+
log.info("Starting") # Rich console + file output
|
|
317
327
|
```
|
|
318
328
|
|
|
319
329
|
## Requirements
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
cmdop/__init__.py,sha256=
|
|
1
|
+
cmdop/__init__.py,sha256=YoLf9cziSSoOYsiDoTLlGpm5kV8kTptdMl4e4ccK4xc,5271
|
|
2
2
|
cmdop/client.py,sha256=nTotStZPBfYN3TrHH-OlEJMSVAXskYMQRkocsFmyaBY,14601
|
|
3
3
|
cmdop/config.py,sha256=vpw1aGCyS4NKlZyzVur81Lt06QmN3FnscZji0bypUi0,4398
|
|
4
4
|
cmdop/discovery.py,sha256=HNxSOa5tSuG7ppfFs21XdviW5ucjpRswVPguhX5j8Dg,7479
|
|
@@ -80,8 +80,8 @@ cmdop/_generated/rpc_messages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
|
|
|
80
80
|
cmdop/_generated/rpc_messages/agent_pb2.py,sha256=1KCs4kwuuTwZm9Y8ql7t6Jjsutuepbq85E6DGVDWa84,3393
|
|
81
81
|
cmdop/_generated/rpc_messages/agent_pb2.pyi,sha256=F7gy0PQlJ4cRQCli7U4v5A87-Lsw2_x0nV4hFXG1qj0,3866
|
|
82
82
|
cmdop/_generated/rpc_messages/agent_pb2_grpc.py,sha256=ABbaG1eMcaWPZKdPoom2F-IjjVqjYNMDOjMp8X6QLHE,898
|
|
83
|
-
cmdop/_generated/rpc_messages/browser_pb2.py,sha256=
|
|
84
|
-
cmdop/_generated/rpc_messages/browser_pb2.pyi,sha256=
|
|
83
|
+
cmdop/_generated/rpc_messages/browser_pb2.py,sha256=B5aagQMy78DbXbKnFWvnTjo9PRbEcDflNlp6dQSnmTw,24944
|
|
84
|
+
cmdop/_generated/rpc_messages/browser_pb2.pyi,sha256=8C54gxuY7VDkw9iS_TY662AJAfn-tSPuNnFRRyqHQYo,38206
|
|
85
85
|
cmdop/_generated/rpc_messages/browser_pb2_grpc.py,sha256=P8F8QYLT_kedGq7AXj37Us2hFQOaevdfYMHl0tTdY48,900
|
|
86
86
|
cmdop/_generated/rpc_messages/device_pb2.py,sha256=nKj7axhR-FVSQoQUd4ENXpc5PU_UCjSlExajLIoeZY8,2435
|
|
87
87
|
cmdop/_generated/rpc_messages/device_pb2.pyi,sha256=u5oLfTHuOSpYwMiVe2tw0vVQLLFvYgK3lxw-Vky1ZkA,1974
|
|
@@ -109,50 +109,48 @@ cmdop/_generated/rpc_messages/terminal_pb2.pyi,sha256=j4_WhvUJOf115rohC7dxljrqDP
|
|
|
109
109
|
cmdop/_generated/rpc_messages/terminal_pb2_grpc.py,sha256=8k9MxEHVhlxJzOxwKWhhbLzTw8LM1RDvuR6EtaEujD0,901
|
|
110
110
|
cmdop/api/__init__.py,sha256=pCJvQs5L1HBjDBxJ6O3jmnxgsIvPcCAH_X_qLRKKRsA,298
|
|
111
111
|
cmdop/api/generated/__init__.py,sha256=CSM3sK6tqDyEvwmCgk3o6skF3HYSqjcwE1NOmy5LJc0,51
|
|
112
|
-
cmdop/api/generated/machines/__init__.py,sha256=
|
|
112
|
+
cmdop/api/generated/machines/__init__.py,sha256=XAKW6tOdln44bAXVpX9tWfvu49eaFHCagYO7vvuzhKU,6324
|
|
113
113
|
cmdop/api/generated/machines/client.py,sha256=D9A81YhTh3kD9OL5uwrwmSWtZkO85rkIpDoW7Bb-lu0,2488
|
|
114
|
-
cmdop/api/generated/machines/enums.py,sha256=
|
|
114
|
+
cmdop/api/generated/machines/enums.py,sha256=QGF8W57cPdoYEiBZ6cog2qQeEfOSW3QLnoEaBmANB_Y,1106
|
|
115
115
|
cmdop/api/generated/machines/logger.py,sha256=K-HR1NHAou-rgjEasPAqdjeVWmqtbnRXUXp5jLdTBI4,7657
|
|
116
116
|
cmdop/api/generated/machines/retry.py,sha256=M8s4OiWZDcnjPa300zkgJ2Ws7vHfx4qF-WQZ9MSVM8s,8186
|
|
117
|
-
cmdop/api/generated/machines/schema.json,sha256=
|
|
117
|
+
cmdop/api/generated/machines/schema.json,sha256=ovqkZp33ftTxP2ECJUNduulm0rRNZZd3vKRE7HPtWkU,80333
|
|
118
118
|
cmdop/api/generated/machines/sync_client.py,sha256=jgPMpXiA6fVMNRHEiHjDNegUJm1NaY_2D_gQ146Q8Y8,1755
|
|
119
119
|
cmdop/api/generated/machines/machines__api__machine_sharing/__init__.py,sha256=PjOOszrj630iP32zMKuphxhxV-QFXrPrLsasi9BFepU,161
|
|
120
|
-
cmdop/api/generated/machines/machines__api__machine_sharing/client.py,sha256=
|
|
121
|
-
cmdop/api/generated/machines/machines__api__machine_sharing/models.py,sha256=
|
|
122
|
-
cmdop/api/generated/machines/machines__api__machine_sharing/sync_client.py,sha256=
|
|
120
|
+
cmdop/api/generated/machines/machines__api__machine_sharing/client.py,sha256=BX3Ls48X1pONVmhh31f6dM8kKXYt6tgiK573o2-7_Ww,2788
|
|
121
|
+
cmdop/api/generated/machines/machines__api__machine_sharing/models.py,sha256=u9tdUqHli_rtkYbuVXJ3xoqSZcM5LOkkUYVgkjwsiaQ,3524
|
|
122
|
+
cmdop/api/generated/machines/machines__api__machine_sharing/sync_client.py,sha256=BLXf9zMAwRYwPKgsNM6FNfjAMpU2jadDmBAYtH2UTcQ,2748
|
|
123
123
|
cmdop/api/generated/machines/machines__api__machines/__init__.py,sha256=1etKMhHggOodMXQkvCDbCjN1zVzB5Y7CUCoJpJRxLlc,149
|
|
124
|
-
cmdop/api/generated/machines/machines__api__machines/client.py,sha256=
|
|
125
|
-
cmdop/api/generated/machines/machines__api__machines/models.py,sha256=
|
|
126
|
-
cmdop/api/generated/machines/machines__api__machines/sync_client.py,sha256=
|
|
127
|
-
cmdop/api/generated/system/__init__.py,sha256=
|
|
124
|
+
cmdop/api/generated/machines/machines__api__machines/client.py,sha256=gWSbenXxYxO2DRFzaqK17WMmmtjwJfuxutBFAeBSnY4,10138
|
|
125
|
+
cmdop/api/generated/machines/machines__api__machines/models.py,sha256=TfQgghJQMfsQp-vKDzTB71HEs9iYeNLUwEIKKvoDrbo,13096
|
|
126
|
+
cmdop/api/generated/machines/machines__api__machines/sync_client.py,sha256=ibxV_HTW4k0g_NotQWmQk1ZmXY6wOKu2XUR4WQ1S5QE,9938
|
|
127
|
+
cmdop/api/generated/system/__init__.py,sha256=S1X9spyeW4v7mW5vuRaqz0ZJ-X4_JOyHZvR2tUoUPCA,6240
|
|
128
128
|
cmdop/api/generated/system/client.py,sha256=Yj8e-lv0hqndI-VMQPP0TS1qms5-Eh0wBW9nwaLbjSM,2426
|
|
129
|
-
cmdop/api/generated/system/enums.py,sha256=
|
|
129
|
+
cmdop/api/generated/system/enums.py,sha256=EAAsq7wAqipxaQC5L3M7vQ4dLNYF1KfryF4JYQrWZcw,1780
|
|
130
130
|
cmdop/api/generated/system/logger.py,sha256=K-HR1NHAou-rgjEasPAqdjeVWmqtbnRXUXp5jLdTBI4,7657
|
|
131
131
|
cmdop/api/generated/system/retry.py,sha256=M8s4OiWZDcnjPa300zkgJ2Ws7vHfx4qF-WQZ9MSVM8s,8186
|
|
132
|
-
cmdop/api/generated/system/schema.json,sha256=
|
|
132
|
+
cmdop/api/generated/system/schema.json,sha256=8KxHH21gza-nT1VwSaStg3azl-yLSeLJmJT24bk5gxU,74984
|
|
133
133
|
cmdop/api/generated/system/sync_client.py,sha256=OeAh7i-6V4om8osgo3voBWYs4smTR0_linU5Vh7TBrk,1693
|
|
134
134
|
cmdop/api/generated/system/system__api__oauth/__init__.py,sha256=YMOwaanZUsG250b7y9fvn9lP44dJuxCLZls1lFzoG8o,139
|
|
135
|
-
cmdop/api/generated/system/system__api__oauth/client.py,sha256=
|
|
136
|
-
cmdop/api/generated/system/system__api__oauth/models.py,sha256=
|
|
137
|
-
cmdop/api/generated/system/system__api__oauth/sync_client.py,sha256=
|
|
135
|
+
cmdop/api/generated/system/system__api__oauth/client.py,sha256=Hy30CczkvvSIxoRpHZdO6usPeCZQItLW2BPuqgcdHaU,4697
|
|
136
|
+
cmdop/api/generated/system/system__api__oauth/models.py,sha256=YBxb0cc3veN5048b_uy3piYvZ2bY8h6sKQhvaT1JLVc,8576
|
|
137
|
+
cmdop/api/generated/system/system__api__oauth/sync_client.py,sha256=73PIWkike_6GYZ8o_MMcwWcgebkBNr6Yo2uB2Cd2Rh4,4621
|
|
138
138
|
cmdop/api/generated/system/system__api__system/__init__.py,sha256=1j6Q3xUSvNVqCCCqeeKyfkil35W26QEb3U0a0vXbsnY,141
|
|
139
|
-
cmdop/api/generated/system/system__api__system/client.py,sha256=
|
|
140
|
-
cmdop/api/generated/system/system__api__system/models.py,sha256=
|
|
141
|
-
cmdop/api/generated/system/system__api__system/sync_client.py,sha256=
|
|
142
|
-
cmdop/api/generated/workspaces/__init__.py,sha256=
|
|
139
|
+
cmdop/api/generated/system/system__api__system/client.py,sha256=InwAqbXcrzu_sgIwl9PYxs4zwWFYgNZ2Eza4iIsdtEc,10667
|
|
140
|
+
cmdop/api/generated/system/system__api__system/models.py,sha256=uGYvD9gtEsOOcn6iPw9FpDh9jjv8R-pPFOilgyfvt3Q,6606
|
|
141
|
+
cmdop/api/generated/system/system__api__system/sync_client.py,sha256=fMxzZhL-c29Y-DJpu35a9ax0ZV1Ykl0nN_JNOrzceG0,10443
|
|
142
|
+
cmdop/api/generated/workspaces/__init__.py,sha256=apDTq9jO5ONzGe2REahC9RkRNu0rztBRj-_t8YYSQUA,6157
|
|
143
143
|
cmdop/api/generated/workspaces/client.py,sha256=Qz5pVLl75AnIP3vOM776JopXOiKa8Dr_Dg_E-OtE9J8,2354
|
|
144
|
-
cmdop/api/generated/workspaces/enums.py,sha256=
|
|
144
|
+
cmdop/api/generated/workspaces/enums.py,sha256=HLStAxzOH6kiAaBWa3RkYSpXOubO3ufsAAzJxVINfDw,1473
|
|
145
145
|
cmdop/api/generated/workspaces/logger.py,sha256=K-HR1NHAou-rgjEasPAqdjeVWmqtbnRXUXp5jLdTBI4,7657
|
|
146
146
|
cmdop/api/generated/workspaces/retry.py,sha256=M8s4OiWZDcnjPa300zkgJ2Ws7vHfx4qF-WQZ9MSVM8s,8186
|
|
147
|
-
cmdop/api/generated/workspaces/schema.json,sha256=
|
|
147
|
+
cmdop/api/generated/workspaces/schema.json,sha256=gwEyJhG1SwwRvoOjmYE3LisZCeQdIxcBYsoq1ZEwTZg,69590
|
|
148
148
|
cmdop/api/generated/workspaces/sync_client.py,sha256=TUOpviPXdEmpR8sqGAz1r75FFVYzuaVjmhJtJ3s8-d8,1601
|
|
149
149
|
cmdop/api/generated/workspaces/workspaces__api__workspaces/__init__.py,sha256=WoUZ62g6b2qhM4X2f8iGMjHHAD1FwqvhJTMBRp3Ryrg,157
|
|
150
|
-
cmdop/api/generated/workspaces/workspaces__api__workspaces/client.py,sha256=
|
|
151
|
-
cmdop/api/generated/workspaces/workspaces__api__workspaces/models.py,sha256=
|
|
152
|
-
cmdop/api/generated/workspaces/workspaces__api__workspaces/sync_client.py,sha256=
|
|
153
|
-
cmdop/helpers/__init__.py,sha256=
|
|
154
|
-
cmdop/helpers/cleaner.py,sha256=3XWB3KpRSMgJ1Go0G7rE9bgDGy1bshk9PtWWB6pL7AU,1792
|
|
155
|
-
cmdop/helpers/formatting.py,sha256=lLYUEyzZLUSXq2xHB2w3i72QoP_baHjtFpP-7mb-V-s,341
|
|
150
|
+
cmdop/api/generated/workspaces/workspaces__api__workspaces/client.py,sha256=RcBOR3WCicf5xSjsZApJ9oQ3a0PGpZD6z-2R0IbxRHQ,16547
|
|
151
|
+
cmdop/api/generated/workspaces/workspaces__api__workspaces/models.py,sha256=KCmK-CUuODGIqREu3WBlKKic9SElk7MY3OkD8zNVS78,10230
|
|
152
|
+
cmdop/api/generated/workspaces/workspaces__api__workspaces/sync_client.py,sha256=BKpMmMYzGw6pmDItC_TpJ_mvuI1zmDppXObWncWszE4,16147
|
|
153
|
+
cmdop/helpers/__init__.py,sha256=EGoWhmQojGlwic4oISx7pwFq5WDSfdNh9hhTxzwdkbs,220
|
|
156
154
|
cmdop/helpers/network_analyzer.py,sha256=ZiTRv39S_kTAppTVbq97DYLExS2WsDLCxf_N4rtnkf0,13025
|
|
157
155
|
cmdop/models/__init__.py,sha256=W6P1oo6JkUAeVEV59HzFT646hXM0pk_obXHfHbX4tAc,1594
|
|
158
156
|
cmdop/models/agent.py,sha256=Z1QDfr1-DTFVl5oPvbH2ZUBLXPHUlitiCRfG7y_OzYg,5495
|
|
@@ -189,7 +187,7 @@ cmdop/services/browser/js/scroll.py,sha256=yiOMAaR8ac8jCiWgNCVIt1pUGxdvktMUtzv-A
|
|
|
189
187
|
cmdop/services/browser/service/__init__.py,sha256=AZH_r2FsxLfJGCVBaaAPw3dTGaUlgIFdlYd_RR8KxSg,100
|
|
190
188
|
cmdop/services/browser/service/_helpers.py,sha256=w8foDUGZcD4HyF5eyLZUFxbx_fctAFsYRovvsksi3l4,1584
|
|
191
189
|
cmdop/services/browser/service/aio.py,sha256=0E2D4igQb3YzAakdXsRMt8PEd0rFxI2gXfimwq_6nzk,767
|
|
192
|
-
cmdop/services/browser/service/sync.py,sha256=
|
|
190
|
+
cmdop/services/browser/service/sync.py,sha256=rEDuzg2IN1ZJtvrAmW5ps7Dt2IfWTtzIpQMz8cXp4Bs,23243
|
|
193
191
|
cmdop/streaming/__init__.py,sha256=kG9UlJRqv8ndcwKMzWUddPlZT61pFO_Uf_c08A_8TxA,877
|
|
194
192
|
cmdop/streaming/base.py,sha256=r7Q2QlRxgULzs9vlSGcOC_fwAQ_cF3Z3M7WsPQtxG5I,2990
|
|
195
193
|
cmdop/streaming/handlers.py,sha256=FDEhADmCEFRbifvr9dU1X3C-K_96noz89Bl3tuDa_rQ,2616
|
|
@@ -200,7 +198,7 @@ cmdop/transport/base.py,sha256=2pkV8i9epgp_21dyReCfX47abRUrnALm0W5BXb-Fuz0,5571
|
|
|
200
198
|
cmdop/transport/discovery.py,sha256=rcGAuVrR1l6jwcP0dqZxVhX1NsFK7sRHygFMCLmmUbA,10673
|
|
201
199
|
cmdop/transport/local.py,sha256=ob6tWVxSdKwblHSMK8CkgjyuSdQoAeWgy5OAUd5ZNuE,7411
|
|
202
200
|
cmdop/transport/remote.py,sha256=FNVqus9wOv7LlxKarXjLmSyvJiHwhvPbNDOPv1IQkmE,4329
|
|
203
|
-
cmdop-0.1.
|
|
204
|
-
cmdop-0.1.
|
|
205
|
-
cmdop-0.1.
|
|
206
|
-
cmdop-0.1.
|
|
201
|
+
cmdop-0.1.26.dist-info/METADATA,sha256=yoBVrJGRJhJNBV9OYfng50ZlGxTjZABBVuInKSMBxDU,9790
|
|
202
|
+
cmdop-0.1.26.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
203
|
+
cmdop-0.1.26.dist-info/licenses/LICENSE,sha256=6hyzbI1QVXW6B-XT7PaQ6UG9lns11Y_nnap8uUKGUqo,1062
|
|
204
|
+
cmdop-0.1.26.dist-info/RECORD,,
|
cmdop/helpers/cleaner.py
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
"""JSON cleaning utilities for LLM consumption."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from typing import Any
|
|
6
|
-
|
|
7
|
-
from toon_python import encode as toon_encode
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class JsonCleaner:
|
|
11
|
-
"""
|
|
12
|
-
Clean JSON and convert to TOON format for LLM.
|
|
13
|
-
|
|
14
|
-
Usage:
|
|
15
|
-
cleaner = JsonCleaner(noise_keys={"Photos", "images"})
|
|
16
|
-
toon_text = cleaner.to_toon(data)
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
DEFAULT_NOISE_KEYS = frozenset({
|
|
20
|
-
"statusItemTypes",
|
|
21
|
-
"attributes",
|
|
22
|
-
"ordering",
|
|
23
|
-
"updatedDate",
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
def __init__(self, noise_keys: set[str] | None = None):
|
|
27
|
-
self.noise_keys = self.DEFAULT_NOISE_KEYS | (noise_keys or set())
|
|
28
|
-
|
|
29
|
-
def compact(self, data: Any) -> Any:
|
|
30
|
-
"""Remove nulls, empty values, noise keys. Simplify {code,title}->title."""
|
|
31
|
-
def _process(obj: Any) -> Any:
|
|
32
|
-
if isinstance(obj, dict):
|
|
33
|
-
# Simplify {code, title} pattern
|
|
34
|
-
keys = set(obj.keys())
|
|
35
|
-
if keys <= {"code", "title", "description"} and "title" in keys:
|
|
36
|
-
return obj.get("title") or obj.get("code")
|
|
37
|
-
# Clean dict
|
|
38
|
-
result = {}
|
|
39
|
-
for k, v in obj.items():
|
|
40
|
-
if k in self.noise_keys:
|
|
41
|
-
continue
|
|
42
|
-
cleaned = _process(v)
|
|
43
|
-
if cleaned is not None and cleaned != "" and cleaned != [] and cleaned != {}:
|
|
44
|
-
result[k] = cleaned
|
|
45
|
-
return result
|
|
46
|
-
elif isinstance(obj, list):
|
|
47
|
-
return [_process(item) for item in obj if _process(item) not in (None, "", [], {})]
|
|
48
|
-
return obj
|
|
49
|
-
return _process(data)
|
|
50
|
-
|
|
51
|
-
def to_toon(self, data: Any) -> str:
|
|
52
|
-
"""Compact and convert to TOON format."""
|
|
53
|
-
return toon_encode(self.compact(data))
|
cmdop/helpers/formatting.py
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"""JSON formatting utilities."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from toon_python import encode as toon_encode
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def json_to_toon(data: dict | list) -> str:
|
|
9
|
-
"""
|
|
10
|
-
Convert JSON to TOON format (saves 30-50% tokens).
|
|
11
|
-
|
|
12
|
-
Example:
|
|
13
|
-
{"name": "Alice", "age": 25} → "name: Alice\\nage: 25"
|
|
14
|
-
"""
|
|
15
|
-
return toon_encode(data)
|
|
File without changes
|
|
File without changes
|