daimon-sdk 0.4.7__tar.gz → 0.4.8__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: daimon-sdk
3
- Version: 0.4.7
3
+ Version: 0.4.8
4
4
  Summary: Typed async Python SDK for daimon MCP services.
5
5
  Author: processd contributors
6
6
  License: MIT
@@ -113,6 +113,7 @@ print(read.file.content)
113
113
  - `await manager.health()`
114
114
  - `await manager.capacity()`
115
115
  - `await manager.create_sandbox()`
116
+ - `await manager.list_sandboxes(labels=..., states=...)`
116
117
  - `await manager.find_sandbox(labels={"thread_id": thread_id})`
117
118
  - `await manager.find_or_create_sandbox(labels={"thread_id": thread_id})`
118
119
  - `await manager.get_sandbox(id)`
@@ -99,6 +99,7 @@ print(read.file.content)
99
99
  - `await manager.health()`
100
100
  - `await manager.capacity()`
101
101
  - `await manager.create_sandbox()`
102
+ - `await manager.list_sandboxes(labels=..., states=...)`
102
103
  - `await manager.find_sandbox(labels={"thread_id": thread_id})`
103
104
  - `await manager.find_or_create_sandbox(labels={"thread_id": thread_id})`
104
105
  - `await manager.get_sandbox(id)`
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "daimon-sdk"
7
- version = "0.4.7"
7
+ version = "0.4.8"
8
8
  description = "Typed async Python SDK for daimon MCP services."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -63,9 +63,10 @@ class ManagerHTTPTransport:
63
63
  method: str,
64
64
  path: str,
65
65
  *,
66
+ params: dict[str, Any] | None = None,
66
67
  body: dict[str, Any] | None = None,
67
68
  ) -> dict[str, Any]:
68
- response = await self.request(method, path, json=body)
69
+ response = await self.request(method, path, params=params, json=body)
69
70
  payload = response.json()
70
71
  if not isinstance(payload, dict):
71
72
  raise DaimonConnectionError(f"manager response was not a JSON object: {payload!r}")
@@ -241,6 +242,27 @@ class DaimonManagerClient:
241
242
  info = self._sandbox_info(await self._transport.json("POST", "/sandboxes"))
242
243
  return DaimonSandbox(self, info, timeout_s=self.timeout_s)
243
244
 
245
+ async def list_sandboxes(
246
+ self,
247
+ *,
248
+ labels: dict[str, str] | None = None,
249
+ states: list[str] | tuple[str, ...] | None = None,
250
+ ) -> list[SandboxInfo]:
251
+ params: dict[str, Any] = {}
252
+ if states:
253
+ params["state"] = list(states)
254
+ for key, value in (labels or {}).items():
255
+ params[f"label.{key}"] = value
256
+ payload = await self._transport.json(
257
+ "GET",
258
+ "/sandboxes",
259
+ params=params or None,
260
+ )
261
+ sandboxes = payload.get("sandboxes")
262
+ if not isinstance(sandboxes, list):
263
+ raise DaimonConnectionError("manager response missing sandboxes list")
264
+ return [self._sandbox_info(dict(item)) for item in sandboxes]
265
+
244
266
  async def find_or_create_sandbox(
245
267
  self,
246
268
  *,
@@ -337,6 +337,43 @@ async def test_daimon_sandbox_lifecycle_updates_info_and_closes_client() -> None
337
337
  assert sandbox.info.ttl_seconds == 0
338
338
 
339
339
 
340
+ @pytest.mark.asyncio
341
+ async def test_manager_list_sandboxes_gets_filtered_sandbox_list(monkeypatch) -> None:
342
+ from daimon_sdk.manager import DaimonManagerClient
343
+
344
+ captured: dict[str, object] = {}
345
+ second = dict(SANDBOX_PAYLOAD)
346
+ second["id"] = "sandbox-2"
347
+ second["state"] = "stopped"
348
+
349
+ async def fake_json(method: str, path: str, *, params=None, body=None):
350
+ captured["method"] = method
351
+ captured["path"] = path
352
+ captured["params"] = params
353
+ captured["body"] = body
354
+ return {"sandboxes": [dict(SANDBOX_PAYLOAD), second]}
355
+
356
+ manager = DaimonManagerClient("http://127.0.0.1:18080")
357
+ monkeypatch.setattr(manager._transport, "json", fake_json)
358
+
359
+ sandboxes = await manager.list_sandboxes(
360
+ labels={"thread_id": "thread-a"},
361
+ states=["running", "stopped"],
362
+ )
363
+
364
+ assert [sandbox.id for sandbox in sandboxes] == ["sandbox-1", "sandbox-2"]
365
+ assert sandboxes[1].state == "stopped"
366
+ assert captured == {
367
+ "method": "GET",
368
+ "path": "/sandboxes",
369
+ "params": {
370
+ "state": ["running", "stopped"],
371
+ "label.thread_id": "thread-a",
372
+ },
373
+ "body": None,
374
+ }
375
+
376
+
340
377
  @pytest.mark.asyncio
341
378
  async def test_manager_find_sandbox_posts_labels(monkeypatch) -> None:
342
379
  from daimon_sdk.manager import DaimonManagerClient, DaimonSandbox
@@ -254,7 +254,7 @@ wheels = [
254
254
 
255
255
  [[package]]
256
256
  name = "daimon-sdk"
257
- version = "0.4.7"
257
+ version = "0.4.8"
258
258
  source = { editable = "." }
259
259
  dependencies = [
260
260
  { name = "fastmcp" },
File without changes
File without changes
File without changes
File without changes
File without changes