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
@@ -9,6 +9,23 @@ from pydantic import BaseModel, ConfigDict, Field
9
9
  from ..enums import SharedMachinePermission
10
10
 
11
11
 
12
+ class SharedMachineCreateRequest(BaseModel):
13
+ """
14
+ Serializer for creating a new share.
15
+
16
+ Request model (no read-only fields).
17
+ """
18
+
19
+ model_config = ConfigDict(
20
+ validate_assignment=True,
21
+ extra="allow",
22
+ frozen=False,
23
+ )
24
+
25
+ expires_in_hours: int | None = Field(None, description='Hours until share expires (null = never)', ge=1, le=720)
26
+
27
+
28
+
12
29
  class SharedMachine(BaseModel):
13
30
  """
14
31
  Full shared machine details (for owners).
@@ -25,15 +42,15 @@ class SharedMachine(BaseModel):
25
42
  id: Any = ...
26
43
  share_token: Any = Field(description='Unique token for public access')
27
44
  share_url: Any = Field(description='Generate full share URL.')
28
- permission: SharedMachinePermission = Field(None, description='* `read_only` - Read Only')
45
+ permission: SharedMachinePermission | None = Field(None, description='* `read_only` - Read Only')
29
46
  machine: str = ...
30
47
  machine_name: Any = ...
31
48
  machine_hostname: Any = ...
32
49
  machine_status: Any = ...
33
50
  expires_at: str | None = Field(None, description='When this share expires (null = never)')
34
51
  views_count: int = ...
35
- last_viewed_at: Any | None = ...
36
- is_active: bool = Field(None, description='Can be deactivated without deleting')
52
+ last_viewed_at: Any | None = None
53
+ is_active: bool | None = Field(None, description='Can be deactivated without deleting')
37
54
  is_expired: bool = ...
38
55
  is_valid: bool = ...
39
56
  active_sessions_count: int = Field(description='Count active terminal sessions on this machine.')
@@ -42,9 +59,10 @@ class SharedMachine(BaseModel):
42
59
 
43
60
 
44
61
 
45
- class PaginatedSharedMachineListList(BaseModel):
62
+ class SharedMachineList(BaseModel):
46
63
  """
47
-
64
+ Lightweight serializer for listing shares.
65
+
48
66
  Response model (includes read-only fields).
49
67
  """
50
68
 
@@ -54,23 +72,24 @@ class PaginatedSharedMachineListList(BaseModel):
54
72
  frozen=False,
55
73
  )
56
74
 
57
- count: int = Field(description='Total number of items across all pages')
58
- page: int = Field(description='Current page number (1-based)')
59
- pages: int = Field(description='Total number of pages')
60
- page_size: int = Field(description='Number of items per page')
61
- has_next: bool = Field(description='Whether there is a next page')
62
- has_previous: bool = Field(description='Whether there is a previous page')
63
- next_page: int | None = Field(None, description='Next page number (null if no next page)')
64
- previous_page: int | None = Field(None, description='Previous page number (null if no previous page)')
65
- results: list[dict[str, Any]] = Field(description='Array of items for current page')
75
+ id: Any = ...
76
+ share_token: str = Field(description='Unique token for public access', max_length=64)
77
+ permission: SharedMachinePermission | None = Field(None, description='* `read_only` - Read Only')
78
+ machine: str = ...
79
+ machine_name: Any = ...
80
+ expires_at: str | None = Field(None, description='When this share expires (null = never)')
81
+ views_count: int | None = Field(None, ge=0, le=2147483647)
82
+ is_active: bool | None = Field(None, description='Can be deactivated without deleting')
83
+ is_expired: bool = ...
84
+ is_valid: bool = ...
85
+ created_at: Any = ...
66
86
 
67
87
 
68
88
 
69
- class SharedMachineCreateRequest(BaseModel):
89
+ class PaginatedSharedMachineListList(BaseModel):
70
90
  """
71
- Serializer for creating a new share.
72
-
73
- Request model (no read-only fields).
91
+
92
+ Response model (includes read-only fields).
74
93
  """
75
94
 
76
95
  model_config = ConfigDict(
@@ -79,7 +98,15 @@ class SharedMachineCreateRequest(BaseModel):
79
98
  frozen=False,
80
99
  )
81
100
 
82
- expires_in_hours: int | None = Field(None, description='Hours until share expires (null = never)', ge=1, le=720)
101
+ count: int = Field(description='Total number of items across all pages')
102
+ page: int = Field(description='Current page number (1-based)')
103
+ pages: int = Field(description='Total number of pages')
104
+ page_size: int = Field(description='Number of items per page')
105
+ has_next: bool = Field(description='Whether there is a next page')
106
+ has_previous: bool = Field(description='Whether there is a previous page')
107
+ next_page: int | None = Field(None, description='Next page number (null if no next page)')
108
+ previous_page: int | None = Field(None, description='Previous page number (null if no previous page)')
109
+ results: list[SharedMachineList] = Field(description='Array of items for current page')
83
110
 
84
111
 
85
112
 
@@ -21,19 +21,29 @@ class SyncMachinesMachineSharingAPI:
21
21
  """
22
22
  url = f"/api/machines/machines/{id}/share/"
23
23
  response = self._client.post(url, json=data.model_dump(exclude_unset=True))
24
- response.raise_for_status()
24
+ if not response.is_success:
25
+ try:
26
+ error_body = response.json()
27
+ except Exception:
28
+ error_body = response.text
29
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
25
30
  return SharedMachine.model_validate(response.json())
26
31
 
27
32
 
28
- def machines_machines_shares_list(self, id: str, page: int | None = None, page_size: int | None = None) -> list[PaginatedSharedMachineListList]:
33
+ def machines_machines_shares_list(self, id: str, ordering: str | None = None, page: int | None = None, page_size: int | None = None, search: str | None = None) -> list[PaginatedSharedMachineListList]:
29
34
  """
30
35
  List active shares for machine
31
36
 
32
37
  Get all active share links for this machine
33
38
  """
34
39
  url = f"/api/machines/machines/{id}/shares/"
35
- 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})
36
- response.raise_for_status()
40
+ 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})
41
+ if not response.is_success:
42
+ try:
43
+ error_body = response.json()
44
+ except Exception:
45
+ error_body = response.text
46
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
37
47
  return PaginatedSharedMachineListList.model_validate(response.json())
38
48
 
39
49
 
@@ -46,6 +56,11 @@ class SyncMachinesMachineSharingAPI:
46
56
  """
47
57
  url = f"/api/machines/machines/{id}/unshare/"
48
58
  response = self._client.delete(url)
49
- response.raise_for_status()
59
+ if not response.is_success:
60
+ try:
61
+ error_body = response.json()
62
+ except Exception:
63
+ error_body = response.text
64
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
50
65
 
51
66
 
@@ -12,14 +12,19 @@ class MachinesMachinesAPI:
12
12
  """Initialize sub-client with shared httpx client."""
13
13
  self._client = client
14
14
 
15
- async def logs_list(self, page: int | None = None, page_size: int | None = None) -> list[PaginatedMachineLogList]:
15
+ async def logs_list(self, ordering: str | None = None, page: int | None = None, page_size: int | None = None, search: str | None = None) -> list[PaginatedMachineLogList]:
16
16
  """
17
17
  ViewSet for MachineLog operations. Read-only except for creation. Logs
18
18
  are created by agents.
19
19
  """
20
20
  url = "/api/machines/logs/"
21
- response = await 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})
22
- response.raise_for_status()
21
+ response = await 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})
22
+ if not response.is_success:
23
+ try:
24
+ error_body = response.json()
25
+ except Exception:
26
+ error_body = response.text
27
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
23
28
  return PaginatedMachineLogList.model_validate(response.json())
24
29
 
25
30
 
@@ -29,8 +34,13 @@ class MachinesMachinesAPI:
29
34
  are created by agents.
30
35
  """
31
36
  url = "/api/machines/logs/"
32
- response = await self._client.post(url, json=data.model_dump())
33
- response.raise_for_status()
37
+ response = await self._client.post(url, json=data.model_dump(exclude_unset=True))
38
+ if not response.is_success:
39
+ try:
40
+ error_body = response.json()
41
+ except Exception:
42
+ error_body = response.text
43
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
34
44
  return MachineLog.model_validate(response.json())
35
45
 
36
46
 
@@ -41,18 +51,28 @@ class MachinesMachinesAPI:
41
51
  """
42
52
  url = f"/api/machines/logs/{id}/"
43
53
  response = await self._client.get(url)
44
- response.raise_for_status()
54
+ if not response.is_success:
55
+ try:
56
+ error_body = response.json()
57
+ except Exception:
58
+ error_body = response.text
59
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
45
60
  return MachineLog.model_validate(response.json())
46
61
 
47
62
 
48
- async def machines_list(self, page: int | None = None, page_size: int | None = None) -> list[PaginatedMachineList]:
63
+ async def machines_list(self, ordering: str | None = None, page: int | None = None, page_size: int | None = None, search: str | None = None) -> list[PaginatedMachineList]:
49
64
  """
50
65
  ViewSet for Machine operations. Provides CRUD operations for remote
51
66
  machines with monitoring capabilities.
52
67
  """
53
68
  url = "/api/machines/machines/"
54
- response = await 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})
55
- response.raise_for_status()
69
+ response = await 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})
70
+ if not response.is_success:
71
+ try:
72
+ error_body = response.json()
73
+ except Exception:
74
+ error_body = response.text
75
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
56
76
  return PaginatedMachineList.model_validate(response.json())
57
77
 
58
78
 
@@ -62,8 +82,13 @@ class MachinesMachinesAPI:
62
82
  machines with monitoring capabilities.
63
83
  """
64
84
  url = "/api/machines/machines/"
65
- response = await self._client.post(url, json=data.model_dump())
66
- response.raise_for_status()
85
+ response = await self._client.post(url, json=data.model_dump(exclude_unset=True))
86
+ if not response.is_success:
87
+ try:
88
+ error_body = response.json()
89
+ except Exception:
90
+ error_body = response.text
91
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
67
92
  return MachineCreate.model_validate(response.json())
68
93
 
69
94
 
@@ -74,7 +99,12 @@ class MachinesMachinesAPI:
74
99
  """
75
100
  url = f"/api/machines/machines/{id}/"
76
101
  response = await self._client.get(url)
77
- response.raise_for_status()
102
+ if not response.is_success:
103
+ try:
104
+ error_body = response.json()
105
+ except Exception:
106
+ error_body = response.text
107
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
78
108
  return Machine.model_validate(response.json())
79
109
 
80
110
 
@@ -84,8 +114,13 @@ class MachinesMachinesAPI:
84
114
  machines with monitoring capabilities.
85
115
  """
86
116
  url = f"/api/machines/machines/{id}/"
87
- response = await self._client.put(url, json=data.model_dump())
88
- response.raise_for_status()
117
+ response = await self._client.put(url, json=data.model_dump(exclude_unset=True))
118
+ if not response.is_success:
119
+ try:
120
+ error_body = response.json()
121
+ except Exception:
122
+ error_body = response.text
123
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
89
124
  return Machine.model_validate(response.json())
90
125
 
91
126
 
@@ -95,8 +130,13 @@ class MachinesMachinesAPI:
95
130
  machines with monitoring capabilities.
96
131
  """
97
132
  url = f"/api/machines/machines/{id}/"
98
- response = await self._client.patch(url, json=data.model_dump() if data is not None else None)
99
- response.raise_for_status()
133
+ response = await self._client.patch(url, json=data.model_dump(exclude_unset=True) if data is not None else None)
134
+ if not response.is_success:
135
+ try:
136
+ error_body = response.json()
137
+ except Exception:
138
+ error_body = response.text
139
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
100
140
  return Machine.model_validate(response.json())
101
141
 
102
142
 
@@ -107,19 +147,29 @@ class MachinesMachinesAPI:
107
147
  """
108
148
  url = f"/api/machines/machines/{id}/"
109
149
  response = await self._client.delete(url)
110
- response.raise_for_status()
150
+ if not response.is_success:
151
+ try:
152
+ error_body = response.json()
153
+ except Exception:
154
+ error_body = response.text
155
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
111
156
  return None
112
157
 
113
158
 
114
- async def machines_logs_list(self, id: str, level: str | None = None, limit: int | None = None, page: int | None = None, page_size: int | None = None) -> list[PaginatedMachineLogList]:
159
+ async def machines_logs_list(self, id: str, level: str | None = None, limit: int | None = None, ordering: str | None = None, page: int | None = None, page_size: int | None = None, search: str | None = None) -> list[PaginatedMachineLogList]:
115
160
  """
116
161
  Get machine logs
117
162
 
118
163
  Get logs for this machine.
119
164
  """
120
165
  url = f"/api/machines/machines/{id}/logs/"
121
- response = await self._client.get(url, params={"level": level if level is not None else None, "limit": limit if limit 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})
122
- response.raise_for_status()
166
+ response = await self._client.get(url, params={"level": level if level is not None else None, "limit": limit if limit is not None else None, "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})
167
+ if not response.is_success:
168
+ try:
169
+ error_body = response.json()
170
+ except Exception:
171
+ error_body = response.text
172
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
123
173
  return PaginatedMachineLogList.model_validate(response.json())
124
174
 
125
175
 
@@ -130,8 +180,13 @@ class MachinesMachinesAPI:
130
180
  Regenerate machine agent token.
131
181
  """
132
182
  url = f"/api/machines/machines/{id}/regenerate-token/"
133
- response = await self._client.post(url, json=data.model_dump())
134
- response.raise_for_status()
183
+ response = await self._client.post(url, json=data.model_dump(exclude_unset=True))
184
+ if not response.is_success:
185
+ try:
186
+ error_body = response.json()
187
+ except Exception:
188
+ error_body = response.text
189
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
135
190
  return None
136
191
 
137
192
 
@@ -143,7 +198,12 @@ class MachinesMachinesAPI:
143
198
  """
144
199
  url = f"/api/machines/machines/{id}/stats/"
145
200
  response = await self._client.get(url)
146
- response.raise_for_status()
201
+ if not response.is_success:
202
+ try:
203
+ error_body = response.json()
204
+ except Exception:
205
+ error_body = response.text
206
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
147
207
  return None
148
208
 
149
209
 
@@ -154,8 +214,13 @@ class MachinesMachinesAPI:
154
214
  Update machine metrics (called by agent).
155
215
  """
156
216
  url = f"/api/machines/machines/{id}/update-metrics/"
157
- response = await self._client.post(url, json=data.model_dump())
158
- response.raise_for_status()
217
+ response = await self._client.post(url, json=data.model_dump(exclude_unset=True))
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 Machine.model_validate(response.json())
160
225
 
161
226