blade-agent-kit 0.4.1__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.
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"""Minimal REST client for Blade Agent (v1: no Socket.IO)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class BladeAgentClient:
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
base_url: str,
|
|
14
|
+
*,
|
|
15
|
+
token: str | None = None,
|
|
16
|
+
timeout: float = 60.0,
|
|
17
|
+
) -> None:
|
|
18
|
+
self._base = base_url.rstrip("/")
|
|
19
|
+
self._token = token
|
|
20
|
+
self._timeout = timeout
|
|
21
|
+
|
|
22
|
+
def _headers(self) -> dict[str, str]:
|
|
23
|
+
h: dict[str, str] = {"Accept": "application/json"}
|
|
24
|
+
if self._token:
|
|
25
|
+
h["Authorization"] = f"Bearer {self._token}"
|
|
26
|
+
return h
|
|
27
|
+
|
|
28
|
+
def _client(self) -> httpx.Client:
|
|
29
|
+
return httpx.Client(
|
|
30
|
+
base_url=self._base,
|
|
31
|
+
timeout=self._timeout,
|
|
32
|
+
headers=self._headers(),
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
def health(self) -> dict[str, Any]:
|
|
36
|
+
with self._client() as c:
|
|
37
|
+
r = c.get("/api/health")
|
|
38
|
+
r.raise_for_status()
|
|
39
|
+
return r.json()
|
|
40
|
+
|
|
41
|
+
def list_sessions(
|
|
42
|
+
self,
|
|
43
|
+
*,
|
|
44
|
+
limit: int = 100,
|
|
45
|
+
offset: int = 0,
|
|
46
|
+
template_id_prefix: str | None = None,
|
|
47
|
+
q: str | None = None,
|
|
48
|
+
) -> list[dict[str, Any]]:
|
|
49
|
+
"""Return session items from paginated GET /api/sessions."""
|
|
50
|
+
params: dict[str, Any] = {"limit": limit, "offset": offset}
|
|
51
|
+
if template_id_prefix:
|
|
52
|
+
params["template_id_prefix"] = template_id_prefix
|
|
53
|
+
if q:
|
|
54
|
+
params["q"] = q.strip()
|
|
55
|
+
with self._client() as c:
|
|
56
|
+
r = c.get("/api/sessions", params=params)
|
|
57
|
+
r.raise_for_status()
|
|
58
|
+
payload = r.json()
|
|
59
|
+
if isinstance(payload, list):
|
|
60
|
+
return payload
|
|
61
|
+
if isinstance(payload, dict):
|
|
62
|
+
items = payload.get("items")
|
|
63
|
+
if isinstance(items, list):
|
|
64
|
+
return items
|
|
65
|
+
raise TypeError(f"unexpected /api/sessions response: {type(payload).__name__}")
|
|
66
|
+
|
|
67
|
+
def list_sessions_page(
|
|
68
|
+
self,
|
|
69
|
+
*,
|
|
70
|
+
limit: int = 20,
|
|
71
|
+
offset: int = 0,
|
|
72
|
+
template_id_prefix: str | None = None,
|
|
73
|
+
q: str | None = None,
|
|
74
|
+
) -> dict[str, Any]:
|
|
75
|
+
"""Return full paginated payload: items, total, limit, offset."""
|
|
76
|
+
params: dict[str, Any] = {"limit": limit, "offset": offset}
|
|
77
|
+
if template_id_prefix:
|
|
78
|
+
params["template_id_prefix"] = template_id_prefix
|
|
79
|
+
if q:
|
|
80
|
+
params["q"] = q.strip()
|
|
81
|
+
with self._client() as c:
|
|
82
|
+
r = c.get("/api/sessions", params=params)
|
|
83
|
+
r.raise_for_status()
|
|
84
|
+
payload = r.json()
|
|
85
|
+
if not isinstance(payload, dict):
|
|
86
|
+
raise TypeError(f"unexpected /api/sessions response: {type(payload).__name__}")
|
|
87
|
+
return payload
|
|
88
|
+
|
|
89
|
+
def get_session(self, session_id: str) -> dict[str, Any]:
|
|
90
|
+
with self._client() as c:
|
|
91
|
+
r = c.get(f"/api/sessions/{session_id}")
|
|
92
|
+
r.raise_for_status()
|
|
93
|
+
return r.json()
|
|
94
|
+
|
|
95
|
+
def get_history(self, session_id: str) -> dict[str, Any]:
|
|
96
|
+
with self._client() as c:
|
|
97
|
+
r = c.get(f"/api/sessions/{session_id}/history")
|
|
98
|
+
r.raise_for_status()
|
|
99
|
+
return r.json()
|
|
100
|
+
|
|
101
|
+
def create_session(self, intent: str = "") -> dict[str, Any]:
|
|
102
|
+
with self._client() as c:
|
|
103
|
+
r = c.post("/api/sessions", json={"intent": intent})
|
|
104
|
+
r.raise_for_status()
|
|
105
|
+
return r.json()
|
|
106
|
+
|
|
107
|
+
def delete_session(self, session_id: str) -> dict[str, Any]:
|
|
108
|
+
with self._client() as c:
|
|
109
|
+
r = c.delete(f"/api/sessions/{session_id}")
|
|
110
|
+
r.raise_for_status()
|
|
111
|
+
return r.json()
|
|
112
|
+
|
|
113
|
+
def list_dir(self, session_id: str, dir_path: str = ".") -> list[dict[str, Any]]:
|
|
114
|
+
with self._client() as c:
|
|
115
|
+
r = c.get(f"/api/sessions/{session_id}/ls/{_encode_ls_path(dir_path)}")
|
|
116
|
+
r.raise_for_status()
|
|
117
|
+
return r.json()
|
|
118
|
+
|
|
119
|
+
def get_checkpoints(self, session_id: str) -> dict[str, Any]:
|
|
120
|
+
with self._client() as c:
|
|
121
|
+
r = c.get(f"/api/sessions/{session_id}/checkpoints")
|
|
122
|
+
r.raise_for_status()
|
|
123
|
+
return r.json()
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _encode_ls_path(dir_path: str) -> str:
|
|
127
|
+
"""Encode path for GET /api/sessions/{id}/ls/{dir_path}.
|
|
128
|
+
|
|
129
|
+
Root ``.`` must be sent as ``%2E``: ``/ls/.`` is normalized to ``/ls`` by HTTP
|
|
130
|
+
clients and does not match the server route (404). Aligns with browser
|
|
131
|
+
``encodeURIComponent`` for nested paths (``/`` → ``%2F``).
|
|
132
|
+
"""
|
|
133
|
+
from urllib.parse import quote
|
|
134
|
+
|
|
135
|
+
normalized = (dir_path or ".").strip()
|
|
136
|
+
if normalized == ".":
|
|
137
|
+
return "%2E"
|
|
138
|
+
return quote(normalized, safe="")
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
blade_agent_kit/__init__.py,sha256=IdRFOMy_fUi_ZMRe3vZo5YVUgJVTG0bUG3_Ev5HnrkY,84
|
|
2
|
+
blade_agent_kit/client.py,sha256=NeY6l8-qIWTYRjNZH8Q8l42T-DFCAC5-diPIhXCOnnM,4577
|
|
3
|
+
blade_agent_kit-0.4.1.dist-info/METADATA,sha256=PtFlmaFud_iFcZxTOBVOx4vVlCC418diPqQozI6MqnI,195
|
|
4
|
+
blade_agent_kit-0.4.1.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
5
|
+
blade_agent_kit-0.4.1.dist-info/RECORD,,
|