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.
Files changed (35) hide show
  1. cmdop/__init__.py +9 -4
  2. cmdop/_generated/rpc_messages/browser_pb2.py +138 -138
  3. cmdop/_generated/rpc_messages/browser_pb2.pyi +6 -2
  4. cmdop/api/generated/machines/__init__.py +1 -1
  5. cmdop/api/generated/machines/enums.py +0 -112
  6. cmdop/api/generated/machines/machines__api__machine_sharing/client.py +21 -6
  7. cmdop/api/generated/machines/machines__api__machine_sharing/models.py +46 -19
  8. cmdop/api/generated/machines/machines__api__machine_sharing/sync_client.py +20 -5
  9. cmdop/api/generated/machines/machines__api__machines/client.py +90 -25
  10. cmdop/api/generated/machines/machines__api__machines/models.py +143 -125
  11. cmdop/api/generated/machines/machines__api__machines/sync_client.py +84 -19
  12. cmdop/api/generated/machines/schema.json +72 -0
  13. cmdop/api/generated/system/__init__.py +1 -1
  14. cmdop/api/generated/system/enums.py +0 -52
  15. cmdop/api/generated/system/schema.json +54 -0
  16. cmdop/api/generated/system/system__api__oauth/client.py +42 -12
  17. cmdop/api/generated/system/system__api__oauth/models.py +111 -85
  18. cmdop/api/generated/system/system__api__oauth/sync_client.py +38 -8
  19. cmdop/api/generated/system/system__api__system/client.py +98 -23
  20. cmdop/api/generated/system/system__api__system/models.py +83 -83
  21. cmdop/api/generated/system/system__api__system/sync_client.py +94 -19
  22. cmdop/api/generated/workspaces/__init__.py +1 -1
  23. cmdop/api/generated/workspaces/enums.py +0 -137
  24. cmdop/api/generated/workspaces/schema.json +47 -0
  25. cmdop/api/generated/workspaces/workspaces__api__workspaces/client.py +156 -41
  26. cmdop/api/generated/workspaces/workspaces__api__workspaces/models.py +126 -85
  27. cmdop/api/generated/workspaces/workspaces__api__workspaces/sync_client.py +145 -29
  28. cmdop/helpers/__init__.py +0 -4
  29. cmdop/services/browser/service/sync.py +4 -0
  30. {cmdop-0.1.25.dist-info → cmdop-0.1.26.dist-info}/METADATA +24 -14
  31. {cmdop-0.1.25.dist-info → cmdop-0.1.26.dist-info}/RECORD +33 -35
  32. cmdop/helpers/cleaner.py +0 -53
  33. cmdop/helpers/formatting.py +0 -15
  34. {cmdop-0.1.25.dist-info → cmdop-0.1.26.dist-info}/WHEEL +0 -0
  35. {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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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) -> None:
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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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.raise_for_status()
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.25
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
- ## Utilities
320
+ ## Logging
306
321
 
307
322
  ```python
308
- from cmdop import get_logger, json_to_toon
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=JAH5EagCk6WJ2i-OiE7QofeEi9LjaaHbvECewfdvOsg,5200
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=2yuoDnRYtAq34NOg4xFPVo0jz0Tr1ulatT8Qe6Ibty8,24851
84
- cmdop/_generated/rpc_messages/browser_pb2.pyi,sha256=HXQxtegycSDNrHXaxCnMKqukb2Na4dJTCUAg413c31k,37988
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=NdA_9poY2_A5y8v9fxMMKPH0mYGkX2lm64uPr431dEE,6520
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=Y06kqx1omOdsWxL4yu9fGTbR7Gw6sc5AYoitKFqsZ3g,2826
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=6JXrBqMNN0J4suw4cxB51vNH1hGDgB4s7Joy3D3LUX0,77537
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=quCDCMeQ1HiOsQCvJ4T0ZAhNKsYx0jAV2poigYYOsIo,1825
121
- cmdop/api/generated/machines/machines__api__machine_sharing/models.py,sha256=_Sd3GiwU9o92krdI_DiQpmrQF9zrXRQShxEIPLNrhd4,2648
122
- cmdop/api/generated/machines/machines__api__machine_sharing/sync_client.py,sha256=AZlNVP9dWlmwiAWh1nBXaemydNS4W5oiAD4mLOMb0zA,1803
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=8M0YpoVxoXIAW5iLN5jQ4DtwVAi8BUA1YAb9YvgqcrE,6151
125
- cmdop/api/generated/machines/machines__api__machines/models.py,sha256=jyaOgjVztvUOIIH_f1sRE8FXCLyf0c3fLD-3U2VrhDE,12431
126
- cmdop/api/generated/machines/machines__api__machines/sync_client.py,sha256=czd1zl8WHRAZK02_iah4WH_EU0xOI21P3VcJhXTsRKg,6059
127
- cmdop/api/generated/system/__init__.py,sha256=UX383p3FuXevXTTs00vZx2aAMej8lyMNoPnOHxQnhQ8,6328
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=7VRPn5sv4FhxP8pfuQ2Fxdfw8E0ftsznbtUJMqZ827o,2908
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=DGNRz1B_qPbtWr55p--E8TMEQKR6zibBqS8SIw1OGk8,72887
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=4WsT6aZSHHBbUd6M0earh7LUMYj1-3p1VfBqXBj4uTw,2897
136
- cmdop/api/generated/system/system__api__oauth/models.py,sha256=1U9WLXglrJ9hX39AtLtfXowM5Tug7vK7AjSPaU5dViE,7655
137
- cmdop/api/generated/system/system__api__oauth/sync_client.py,sha256=_Vhf7mQFJYZhXs4Mecc_j2uCG0YlKlx3bmUab33vvpU,2893
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=NeJv_UqamxzUl9SqtOrLcfYhjLt972vX2WKpzFuZweI,6356
140
- cmdop/api/generated/system/system__api__system/models.py,sha256=kRjQNKvxcUgCPMcBHFgja0dOH7RjUpSBPBUwEEJqG0s,6689
141
- cmdop/api/generated/system/system__api__system/sync_client.py,sha256=6SDYprhBODpy9VUTF3dzfRB6VP1QJGj4znM-Ruv489Q,6204
142
- cmdop/api/generated/workspaces/__init__.py,sha256=Cw14Dr40RxsmNiePOK0cJ1dsK_p6BXlYOmHEsT1NoxA,6443
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=jJyJR4bJ4ddPfehYg0a099q0S_IrnrtD4UIkHDF3Juc,3513
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=S0z1e4nf6c0pQjjf8vLExBIlihu8v7p8khUa9r6m7jw,67776
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=A1c5s8FJQ7vJRjReO7QQ8D6tPN-6PudxQXLYP6EGE2I,9861
151
- cmdop/api/generated/workspaces/workspaces__api__workspaces/models.py,sha256=3UFJFLWWQs_jzSmFstJ5T1lsaVp9TYSb1u6YFFq5RSk,9501
152
- cmdop/api/generated/workspaces/workspaces__api__workspaces/sync_client.py,sha256=KfWxpSjZyfZLjonHRFwk0a1eUmOZHuky4ZySo11wTWg,9639
153
- cmdop/helpers/__init__.py,sha256=fxzHT-O9D4HbvSU4qcQ9Ce3Q0Y5dZV-nQHVuoMpahCw,355
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=40CIqdUAR-ZVFfQJVgUWVgGq3j7mgcpGs1SRe8zXjmI,23096
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.25.dist-info/METADATA,sha256=zU53FzmNQTtobkEzWTWOnYCYiB80P6sER5Ovmq0WcoU,9284
204
- cmdop-0.1.25.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
205
- cmdop-0.1.25.dist-info/licenses/LICENSE,sha256=6hyzbI1QVXW6B-XT7PaQ6UG9lns11Y_nnap8uUKGUqo,1062
206
- cmdop-0.1.25.dist-info/RECORD,,
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))
@@ -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