islo 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
islo-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,82 @@
1
+ Metadata-Version: 2.3
2
+ Name: islo
3
+ Version: 0.1.0
4
+ Summary: Typed Python SDK for the Islo Web API
5
+ Keywords: islo,sdk,openapi,api-client
6
+ Author: Islo Labs
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.14
15
+ Classifier: Typing :: Typed
16
+ Requires-Dist: httpx>=0.23.0,<0.29.0
17
+ Requires-Dist: pydantic[email]>=2.0.0
18
+ Requires-Python: >=3.10
19
+ Project-URL: Homepage, https://github.com/islo-labs/islo-sdk
20
+ Project-URL: Repository, https://github.com/islo-labs/islo-sdk
21
+ Project-URL: Issues, https://github.com/islo-labs/islo-sdk/issues
22
+ Description-Content-Type: text/markdown
23
+
24
+ # islo
25
+
26
+ Typed Python SDK for the [Islo](https://islo.dev) API.
27
+
28
+ ## Install
29
+
30
+ ```sh
31
+ pip install islo
32
+ ```
33
+
34
+ ## Usage
35
+
36
+ ```python
37
+ from islo import Islo
38
+
39
+ client = Islo(api_key="sk-...")
40
+
41
+ # List sandboxes
42
+ sandboxes = client.sandboxes.list(limit=20)
43
+
44
+ # Create a sandbox
45
+ from islo.models import SandboxCreate, SandboxSpec
46
+
47
+ sandbox = client.sandboxes.create(body=SandboxCreate(
48
+ name="my-sandbox",
49
+ spec=SandboxSpec(cpu=2, memory=4096),
50
+ ))
51
+
52
+ # Get a sandbox
53
+ sandbox = client.sandboxes.get("my-sandbox")
54
+
55
+ # Execute a command
56
+ from islo.models import ExecRequest
57
+
58
+ result = client.sandboxes.exec("my-sandbox", body=ExecRequest(
59
+ command=["echo", "hello"],
60
+ ))
61
+
62
+ # Delete
63
+ client.sandboxes.delete("my-sandbox")
64
+ ```
65
+
66
+ ## Resources
67
+
68
+ | Resource | Methods |
69
+ |---|---|
70
+ | `client.sandboxes` | `list`, `create`, `get`, `delete`, `stop`, `exec`, `exec_stream`, `promote_cache`, `list_agent_sessions`, `get_agent_session_events`, `list_exec_sessions`, `get_exec_session_logs` |
71
+ | `client.tenants` | `list`, `create`, `get_settings`, `update_settings`, `get_subscription` |
72
+ | `client.users` | `get`, `invite`, `update`, `authorize` |
73
+ | `client.shares` | `list`, `create`, `revoke` |
74
+ | `client.integrations` | `list`, `list_providers`, `get_status`, `disconnect` |
75
+ | `client.usage` | `sandbox_usage`, `summary` |
76
+ | `client.certificate_authority` | `create_certificate`, `get_public_key` |
77
+
78
+ ## Regenerate
79
+
80
+ ```sh
81
+ just sync
82
+ ```
islo-0.1.0/README.md ADDED
@@ -0,0 +1,59 @@
1
+ # islo
2
+
3
+ Typed Python SDK for the [Islo](https://islo.dev) API.
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ pip install islo
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```python
14
+ from islo import Islo
15
+
16
+ client = Islo(api_key="sk-...")
17
+
18
+ # List sandboxes
19
+ sandboxes = client.sandboxes.list(limit=20)
20
+
21
+ # Create a sandbox
22
+ from islo.models import SandboxCreate, SandboxSpec
23
+
24
+ sandbox = client.sandboxes.create(body=SandboxCreate(
25
+ name="my-sandbox",
26
+ spec=SandboxSpec(cpu=2, memory=4096),
27
+ ))
28
+
29
+ # Get a sandbox
30
+ sandbox = client.sandboxes.get("my-sandbox")
31
+
32
+ # Execute a command
33
+ from islo.models import ExecRequest
34
+
35
+ result = client.sandboxes.exec("my-sandbox", body=ExecRequest(
36
+ command=["echo", "hello"],
37
+ ))
38
+
39
+ # Delete
40
+ client.sandboxes.delete("my-sandbox")
41
+ ```
42
+
43
+ ## Resources
44
+
45
+ | Resource | Methods |
46
+ |---|---|
47
+ | `client.sandboxes` | `list`, `create`, `get`, `delete`, `stop`, `exec`, `exec_stream`, `promote_cache`, `list_agent_sessions`, `get_agent_session_events`, `list_exec_sessions`, `get_exec_session_logs` |
48
+ | `client.tenants` | `list`, `create`, `get_settings`, `update_settings`, `get_subscription` |
49
+ | `client.users` | `get`, `invite`, `update`, `authorize` |
50
+ | `client.shares` | `list`, `create`, `revoke` |
51
+ | `client.integrations` | `list`, `list_providers`, `get_status`, `disconnect` |
52
+ | `client.usage` | `sandbox_usage`, `summary` |
53
+ | `client.certificate_authority` | `create_certificate`, `get_public_key` |
54
+
55
+ ## Regenerate
56
+
57
+ ```sh
58
+ just sync
59
+ ```
@@ -0,0 +1,26 @@
1
+ """Islo Python SDK."""
2
+
3
+ from islo._client import AsyncIslo, Islo
4
+ from islo._exceptions import (
5
+ APIStatusError,
6
+ AuthenticationError,
7
+ InternalServerError,
8
+ IsloError,
9
+ NotFoundError,
10
+ PermissionDeniedError,
11
+ RateLimitError,
12
+ UnprocessableEntityError,
13
+ )
14
+
15
+ __all__ = [
16
+ "AsyncIslo",
17
+ "Islo",
18
+ "IsloError",
19
+ "APIStatusError",
20
+ "AuthenticationError",
21
+ "PermissionDeniedError",
22
+ "NotFoundError",
23
+ "UnprocessableEntityError",
24
+ "RateLimitError",
25
+ "InternalServerError",
26
+ ]
File without changes
@@ -0,0 +1,19 @@
1
+ from __future__ import annotations
2
+
3
+ from islo._base import AsyncAPIResource, SyncAPIResource
4
+ from islo.models import (
5
+ TokenRequest,
6
+ TokenResponse,
7
+ )
8
+
9
+
10
+ class Auth(SyncAPIResource):
11
+ def exchange_token(self, *, body: TokenRequest) -> TokenResponse:
12
+ """Exchange an access key for a session token."""
13
+ return self._request("POST", "/auth/token", json_body=body, response_model=TokenResponse)
14
+
15
+
16
+ class AsyncAuth(AsyncAPIResource):
17
+ async def exchange_token(self, *, body: TokenRequest) -> TokenResponse:
18
+ """Exchange an access key for a session token."""
19
+ return await self._request("POST", "/auth/token", json_body=body, response_model=TokenResponse)
@@ -0,0 +1,30 @@
1
+ from __future__ import annotations
2
+
3
+ from islo._base import AsyncAPIResource, SyncAPIResource
4
+ from islo.models import (
5
+ CAPublicKeyResponse,
6
+ SSHCertificateRequest,
7
+ SSHCertificateResponse,
8
+ )
9
+
10
+
11
+ class CertificateAuthority(SyncAPIResource):
12
+ def create_certificate(self, *, body: SSHCertificateRequest) -> SSHCertificateResponse:
13
+ """Issue SSH certificate"""
14
+ return self._request("POST", "/certificate-authority/", json_body=body, response_model=SSHCertificateResponse)
15
+
16
+ def get_public_key(self) -> CAPublicKeyResponse:
17
+ """Get CA public key"""
18
+ return self._request("GET", "/certificate-authority/public-key", response_model=CAPublicKeyResponse)
19
+
20
+
21
+ class AsyncCertificateAuthority(AsyncAPIResource):
22
+ async def create_certificate(self, *, body: SSHCertificateRequest) -> SSHCertificateResponse:
23
+ """Issue SSH certificate"""
24
+ return await self._request(
25
+ "POST", "/certificate-authority/", json_body=body, response_model=SSHCertificateResponse
26
+ )
27
+
28
+ async def get_public_key(self) -> CAPublicKeyResponse:
29
+ """Get CA public key"""
30
+ return await self._request("GET", "/certificate-authority/public-key", response_model=CAPublicKeyResponse)
@@ -0,0 +1,46 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from islo._base import AsyncAPIResource, SyncAPIResource
6
+ from islo.models import (
7
+ IntegrationDetailResponse,
8
+ IntegrationListResponse,
9
+ IntegrationProvidersResponse,
10
+ )
11
+
12
+
13
+ class Integrations(SyncAPIResource):
14
+ def list(self) -> IntegrationListResponse:
15
+ """List User Integrations"""
16
+ return self._request("GET", "/integrations", response_model=IntegrationListResponse)
17
+
18
+ def list_providers(self) -> IntegrationProvidersResponse:
19
+ """List Providers"""
20
+ return self._request("GET", "/integrations/providers", response_model=IntegrationProvidersResponse)
21
+
22
+ def disconnect(self, provider: str, *, level: str | None = "user") -> Any:
23
+ """Disconnect Integration"""
24
+ return self._request("DELETE", f"/integrations/{provider}", params={"level": level})
25
+
26
+ def get_status(self, provider: str) -> IntegrationDetailResponse:
27
+ """Get Integration Status"""
28
+ return self._request("GET", f"/integrations/{provider}", response_model=IntegrationDetailResponse)
29
+
30
+
31
+ class AsyncIntegrations(AsyncAPIResource):
32
+ async def list(self) -> IntegrationListResponse:
33
+ """List User Integrations"""
34
+ return await self._request("GET", "/integrations", response_model=IntegrationListResponse)
35
+
36
+ async def list_providers(self) -> IntegrationProvidersResponse:
37
+ """List Providers"""
38
+ return await self._request("GET", "/integrations/providers", response_model=IntegrationProvidersResponse)
39
+
40
+ async def disconnect(self, provider: str, *, level: str | None = "user") -> Any:
41
+ """Disconnect Integration"""
42
+ return await self._request("DELETE", f"/integrations/{provider}", params={"level": level})
43
+
44
+ async def get_status(self, provider: str) -> IntegrationDetailResponse:
45
+ """Get Integration Status"""
46
+ return await self._request("GET", f"/integrations/{provider}", response_model=IntegrationDetailResponse)
@@ -0,0 +1,18 @@
1
+ from __future__ import annotations
2
+
3
+ from islo._base import AsyncAPIResource, SyncAPIResource
4
+ from islo.models import (
5
+ ModelPricingResponse,
6
+ )
7
+
8
+
9
+ class Models(SyncAPIResource):
10
+ def get_pricing(self) -> ModelPricingResponse:
11
+ """Get model pricing"""
12
+ return self._request("GET", "/models/pricing", response_model=ModelPricingResponse)
13
+
14
+
15
+ class AsyncModels(AsyncAPIResource):
16
+ async def get_pricing(self) -> ModelPricingResponse:
17
+ """Get model pricing"""
18
+ return await self._request("GET", "/models/pricing", response_model=ModelPricingResponse)
@@ -0,0 +1,256 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from islo._base import AsyncAPIResource, SyncAPIResource
6
+ from islo.models import (
7
+ AgentSessionEventResponse,
8
+ AgentSessionResponse,
9
+ ExecLogsResponse,
10
+ ExecRequest,
11
+ ExecResponse,
12
+ ExecSessionResponse,
13
+ PaginatedSandboxResponse,
14
+ SandboxCreate,
15
+ SandboxResponse,
16
+ SyncExecRequest,
17
+ SyncExecResponse,
18
+ )
19
+
20
+
21
+ class Sandboxes(SyncAPIResource):
22
+ def list(
23
+ self,
24
+ *,
25
+ search: str | None = None,
26
+ status: str | None = None,
27
+ date_from: str | None = None,
28
+ date_to: str | None = None,
29
+ created_by: str | None = None,
30
+ limit: int | None = 50,
31
+ offset: int | None = 0,
32
+ ) -> PaginatedSandboxResponse:
33
+ """List sandboxes"""
34
+ return self._request(
35
+ "GET",
36
+ "/sandboxes/",
37
+ params={
38
+ "search": search,
39
+ "status": status,
40
+ "date_from": date_from,
41
+ "date_to": date_to,
42
+ "created_by": created_by,
43
+ "limit": limit,
44
+ "offset": offset,
45
+ },
46
+ response_model=PaginatedSandboxResponse,
47
+ )
48
+
49
+ def create(self, *, body: SandboxCreate) -> SandboxResponse:
50
+ """Create sandbox"""
51
+ return self._request("POST", "/sandboxes/", json_body=body, response_model=SandboxResponse)
52
+
53
+ def list_agent_sessions(
54
+ self, sandbox_id: str, *, since: str | None = None, include_subagents: bool | None = False
55
+ ) -> list[AgentSessionResponse]:
56
+ """List agent sessions"""
57
+ return self._request(
58
+ "GET",
59
+ f"/sandboxes/{sandbox_id}/agent-sessions",
60
+ params={"since": since, "include_subagents": include_subagents},
61
+ )
62
+
63
+ def get_agent_session_events(
64
+ self,
65
+ sandbox_id: str,
66
+ session_name: str,
67
+ *,
68
+ session_path: str | None = None,
69
+ include_descendants: bool | None = True,
70
+ limit: int | None = 500,
71
+ offset: int | None = 0,
72
+ since: str | None = None,
73
+ ) -> list[AgentSessionEventResponse]:
74
+ """Get agent session events"""
75
+ return self._request(
76
+ "GET",
77
+ f"/sandboxes/{sandbox_id}/agent-sessions/{session_name}/events",
78
+ params={
79
+ "session_path": session_path,
80
+ "include_descendants": include_descendants,
81
+ "limit": limit,
82
+ "offset": offset,
83
+ "since": since,
84
+ },
85
+ )
86
+
87
+ def list_exec_sessions(self, sandbox_id: str, *, since: str | None = None) -> list[ExecSessionResponse]:
88
+ """List exec sessions"""
89
+ return self._request("GET", f"/sandboxes/{sandbox_id}/exec-sessions", params={"since": since})
90
+
91
+ def get_exec_session_asciinema(self, sandbox_id: str, exec_id: str, *, limit: int | None = 2000) -> Any:
92
+ """Get exec session as asciinema cast"""
93
+ return self._request(
94
+ "GET", f"/sandboxes/{sandbox_id}/exec-sessions/{exec_id}/asciinema", params={"limit": limit}
95
+ )
96
+
97
+ def get_exec_session_logs(
98
+ self, sandbox_id: str, exec_id: str, *, limit: int | None = 2000, since: str | None = None
99
+ ) -> ExecLogsResponse:
100
+ """Get exec session logs"""
101
+ return self._request(
102
+ "GET",
103
+ f"/sandboxes/{sandbox_id}/exec-sessions/{exec_id}/logs",
104
+ params={"limit": limit, "since": since},
105
+ response_model=ExecLogsResponse,
106
+ )
107
+
108
+ def delete(self, sandbox_name: str) -> Any:
109
+ """Remove sandbox"""
110
+ return self._request("DELETE", f"/sandboxes/{sandbox_name}")
111
+
112
+ def get(self, sandbox_name: str) -> SandboxResponse:
113
+ """Get sandbox"""
114
+ return self._request("GET", f"/sandboxes/{sandbox_name}", response_model=SandboxResponse)
115
+
116
+ def exec(self, sandbox_name: str, *, body: ExecRequest) -> ExecResponse:
117
+ """Execute command"""
118
+ return self._request("POST", f"/sandboxes/{sandbox_name}/exec", json_body=body, response_model=ExecResponse)
119
+
120
+ def exec_stream(self, sandbox_name: str, *, body: ExecRequest) -> Any:
121
+ """Execute command with streaming"""
122
+ return self._request("POST", f"/sandboxes/{sandbox_name}/exec/stream", json_body=body)
123
+
124
+ def promote_cache(self, sandbox_name: str) -> Any:
125
+ """Promote cache"""
126
+ return self._request("POST", f"/sandboxes/{sandbox_name}/promote-cache")
127
+
128
+ def stop(self, sandbox_name: str) -> Any:
129
+ """Stop sandbox"""
130
+ return self._request("POST", f"/sandboxes/{sandbox_name}/stop")
131
+
132
+ def exec_sync(self, sandbox_name: str, *, body: SyncExecRequest) -> SyncExecResponse:
133
+ """Execute a command synchronously and return stdout/stderr/exit_code."""
134
+ return self._request(
135
+ "POST", f"/sandboxes/{sandbox_name}/exec/sync", json_body=body, response_model=SyncExecResponse
136
+ )
137
+
138
+
139
+ class AsyncSandboxes(AsyncAPIResource):
140
+ async def list(
141
+ self,
142
+ *,
143
+ search: str | None = None,
144
+ status: str | None = None,
145
+ date_from: str | None = None,
146
+ date_to: str | None = None,
147
+ created_by: str | None = None,
148
+ limit: int | None = 50,
149
+ offset: int | None = 0,
150
+ ) -> PaginatedSandboxResponse:
151
+ """List sandboxes"""
152
+ return await self._request(
153
+ "GET",
154
+ "/sandboxes/",
155
+ params={
156
+ "search": search,
157
+ "status": status,
158
+ "date_from": date_from,
159
+ "date_to": date_to,
160
+ "created_by": created_by,
161
+ "limit": limit,
162
+ "offset": offset,
163
+ },
164
+ response_model=PaginatedSandboxResponse,
165
+ )
166
+
167
+ async def create(self, *, body: SandboxCreate) -> SandboxResponse:
168
+ """Create sandbox"""
169
+ return await self._request("POST", "/sandboxes/", json_body=body, response_model=SandboxResponse)
170
+
171
+ async def list_agent_sessions(
172
+ self, sandbox_id: str, *, since: str | None = None, include_subagents: bool | None = False
173
+ ) -> list[AgentSessionResponse]:
174
+ """List agent sessions"""
175
+ return await self._request(
176
+ "GET",
177
+ f"/sandboxes/{sandbox_id}/agent-sessions",
178
+ params={"since": since, "include_subagents": include_subagents},
179
+ )
180
+
181
+ async def get_agent_session_events(
182
+ self,
183
+ sandbox_id: str,
184
+ session_name: str,
185
+ *,
186
+ session_path: str | None = None,
187
+ include_descendants: bool | None = True,
188
+ limit: int | None = 500,
189
+ offset: int | None = 0,
190
+ since: str | None = None,
191
+ ) -> list[AgentSessionEventResponse]:
192
+ """Get agent session events"""
193
+ return await self._request(
194
+ "GET",
195
+ f"/sandboxes/{sandbox_id}/agent-sessions/{session_name}/events",
196
+ params={
197
+ "session_path": session_path,
198
+ "include_descendants": include_descendants,
199
+ "limit": limit,
200
+ "offset": offset,
201
+ "since": since,
202
+ },
203
+ )
204
+
205
+ async def list_exec_sessions(self, sandbox_id: str, *, since: str | None = None) -> list[ExecSessionResponse]:
206
+ """List exec sessions"""
207
+ return await self._request("GET", f"/sandboxes/{sandbox_id}/exec-sessions", params={"since": since})
208
+
209
+ async def get_exec_session_asciinema(self, sandbox_id: str, exec_id: str, *, limit: int | None = 2000) -> Any:
210
+ """Get exec session as asciinema cast"""
211
+ return await self._request(
212
+ "GET", f"/sandboxes/{sandbox_id}/exec-sessions/{exec_id}/asciinema", params={"limit": limit}
213
+ )
214
+
215
+ async def get_exec_session_logs(
216
+ self, sandbox_id: str, exec_id: str, *, limit: int | None = 2000, since: str | None = None
217
+ ) -> ExecLogsResponse:
218
+ """Get exec session logs"""
219
+ return await self._request(
220
+ "GET",
221
+ f"/sandboxes/{sandbox_id}/exec-sessions/{exec_id}/logs",
222
+ params={"limit": limit, "since": since},
223
+ response_model=ExecLogsResponse,
224
+ )
225
+
226
+ async def delete(self, sandbox_name: str) -> Any:
227
+ """Remove sandbox"""
228
+ return await self._request("DELETE", f"/sandboxes/{sandbox_name}")
229
+
230
+ async def get(self, sandbox_name: str) -> SandboxResponse:
231
+ """Get sandbox"""
232
+ return await self._request("GET", f"/sandboxes/{sandbox_name}", response_model=SandboxResponse)
233
+
234
+ async def exec(self, sandbox_name: str, *, body: ExecRequest) -> ExecResponse:
235
+ """Execute command"""
236
+ return await self._request(
237
+ "POST", f"/sandboxes/{sandbox_name}/exec", json_body=body, response_model=ExecResponse
238
+ )
239
+
240
+ async def exec_stream(self, sandbox_name: str, *, body: ExecRequest) -> Any:
241
+ """Execute command with streaming"""
242
+ return await self._request("POST", f"/sandboxes/{sandbox_name}/exec/stream", json_body=body)
243
+
244
+ async def promote_cache(self, sandbox_name: str) -> Any:
245
+ """Promote cache"""
246
+ return await self._request("POST", f"/sandboxes/{sandbox_name}/promote-cache")
247
+
248
+ async def stop(self, sandbox_name: str) -> Any:
249
+ """Stop sandbox"""
250
+ return await self._request("POST", f"/sandboxes/{sandbox_name}/stop")
251
+
252
+ async def exec_sync(self, sandbox_name: str, *, body: SyncExecRequest) -> SyncExecResponse:
253
+ """Execute a command synchronously and return stdout/stderr/exit_code."""
254
+ return await self._request(
255
+ "POST", f"/sandboxes/{sandbox_name}/exec/sync", json_body=body, response_model=SyncExecResponse
256
+ )
@@ -0,0 +1,39 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from islo._base import AsyncAPIResource, SyncAPIResource
6
+ from islo.models import (
7
+ CreateShareRequest,
8
+ ShareResponse,
9
+ )
10
+
11
+
12
+ class Shares(SyncAPIResource):
13
+ def list(self, sandbox_name: str) -> list[ShareResponse]:
14
+ """List shares"""
15
+ return self._request("GET", f"/sandboxes/{sandbox_name}/shares")
16
+
17
+ def create(self, sandbox_name: str, *, body: CreateShareRequest) -> ShareResponse:
18
+ """Create share"""
19
+ return self._request("POST", f"/sandboxes/{sandbox_name}/shares", json_body=body, response_model=ShareResponse)
20
+
21
+ def revoke(self, sandbox_name: str, share_id: str) -> Any:
22
+ """Revoke share"""
23
+ return self._request("DELETE", f"/sandboxes/{sandbox_name}/shares/{share_id}")
24
+
25
+
26
+ class AsyncShares(AsyncAPIResource):
27
+ async def list(self, sandbox_name: str) -> list[ShareResponse]:
28
+ """List shares"""
29
+ return await self._request("GET", f"/sandboxes/{sandbox_name}/shares")
30
+
31
+ async def create(self, sandbox_name: str, *, body: CreateShareRequest) -> ShareResponse:
32
+ """Create share"""
33
+ return await self._request(
34
+ "POST", f"/sandboxes/{sandbox_name}/shares", json_body=body, response_model=ShareResponse
35
+ )
36
+
37
+ async def revoke(self, sandbox_name: str, share_id: str) -> Any:
38
+ """Revoke share"""
39
+ return await self._request("DELETE", f"/sandboxes/{sandbox_name}/shares/{share_id}")
@@ -0,0 +1,56 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from islo._base import AsyncAPIResource, SyncAPIResource
6
+ from islo.models import (
7
+ CreateTenant,
8
+ PublicSubscription,
9
+ PublicTenant,
10
+ TenantSettingsResponse,
11
+ TenantSettingsUpdate,
12
+ )
13
+
14
+
15
+ class Tenants(SyncAPIResource):
16
+ def list(self) -> list[PublicTenant]:
17
+ """Get All Tenants"""
18
+ return self._request("GET", "/tenants/")
19
+
20
+ def create(self, *, body: CreateTenant) -> Any:
21
+ """Create Tenant"""
22
+ return self._request("POST", "/tenants/", json_body=body)
23
+
24
+ def get_settings(self) -> TenantSettingsResponse:
25
+ """Get Settings"""
26
+ return self._request("GET", "/tenants/settings", response_model=TenantSettingsResponse)
27
+
28
+ def update_settings(self, *, body: TenantSettingsUpdate) -> TenantSettingsResponse:
29
+ """Update Settings"""
30
+ return self._request("PATCH", "/tenants/settings", json_body=body, response_model=TenantSettingsResponse)
31
+
32
+ def get_subscription(self) -> PublicSubscription:
33
+ """Get Subscription"""
34
+ return self._request("GET", "/tenants/subscription", response_model=PublicSubscription)
35
+
36
+
37
+ class AsyncTenants(AsyncAPIResource):
38
+ async def list(self) -> list[PublicTenant]:
39
+ """Get All Tenants"""
40
+ return await self._request("GET", "/tenants/")
41
+
42
+ async def create(self, *, body: CreateTenant) -> Any:
43
+ """Create Tenant"""
44
+ return await self._request("POST", "/tenants/", json_body=body)
45
+
46
+ async def get_settings(self) -> TenantSettingsResponse:
47
+ """Get Settings"""
48
+ return await self._request("GET", "/tenants/settings", response_model=TenantSettingsResponse)
49
+
50
+ async def update_settings(self, *, body: TenantSettingsUpdate) -> TenantSettingsResponse:
51
+ """Update Settings"""
52
+ return await self._request("PATCH", "/tenants/settings", json_body=body, response_model=TenantSettingsResponse)
53
+
54
+ async def get_subscription(self) -> PublicSubscription:
55
+ """Get Subscription"""
56
+ return await self._request("GET", "/tenants/subscription", response_model=PublicSubscription)
@@ -0,0 +1,31 @@
1
+ from __future__ import annotations
2
+
3
+ from islo._base import AsyncAPIResource, SyncAPIResource
4
+ from islo.models import (
5
+ SandboxUsageDetail,
6
+ UsageSummary,
7
+ )
8
+
9
+
10
+ class Usage(SyncAPIResource):
11
+ def sandbox_usage(self, *, start: str | None = None, end: str | None = None) -> list[SandboxUsageDetail]:
12
+ """Get detailed usage per sandbox for the authenticated tenant"""
13
+ return self._request("GET", "/usage/me/sandboxes", params={"start": start, "end": end})
14
+
15
+ def summary(self, *, start: str | None = None, end: str | None = None) -> UsageSummary:
16
+ """Get usage summary for the authenticated tenant"""
17
+ return self._request(
18
+ "GET", "/usage/me/summary", params={"start": start, "end": end}, response_model=UsageSummary
19
+ )
20
+
21
+
22
+ class AsyncUsage(AsyncAPIResource):
23
+ async def sandbox_usage(self, *, start: str | None = None, end: str | None = None) -> list[SandboxUsageDetail]:
24
+ """Get detailed usage per sandbox for the authenticated tenant"""
25
+ return await self._request("GET", "/usage/me/sandboxes", params={"start": start, "end": end})
26
+
27
+ async def summary(self, *, start: str | None = None, end: str | None = None) -> UsageSummary:
28
+ """Get usage summary for the authenticated tenant"""
29
+ return await self._request(
30
+ "GET", "/usage/me/summary", params={"start": start, "end": end}, response_model=UsageSummary
31
+ )