acontext 0.0.14__py3-none-any.whl → 0.0.17__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.
- acontext/agent/__init__.py +10 -0
- acontext/agent/disk.py +106 -0
- acontext/agent/skill.py +148 -0
- acontext/async_client.py +4 -0
- acontext/client.py +4 -0
- acontext/resources/__init__.py +8 -0
- acontext/resources/async_disks.py +11 -3
- acontext/resources/async_sessions.py +36 -16
- acontext/resources/async_skills.py +150 -0
- acontext/resources/async_spaces.py +12 -2
- acontext/resources/async_users.py +57 -0
- acontext/resources/disks.py +92 -3
- acontext/resources/sessions.py +17 -0
- acontext/resources/skills.py +146 -0
- acontext/resources/spaces.py +12 -2
- acontext/resources/users.py +57 -0
- acontext/types/__init__.py +25 -1
- acontext/types/common.py +11 -0
- acontext/types/disk.py +3 -7
- acontext/types/session.py +31 -15
- acontext/types/skill.py +69 -0
- acontext/types/space.py +1 -0
- acontext/types/user.py +36 -0
- {acontext-0.0.14.dist-info → acontext-0.0.17.dist-info}/METADATA +1 -1
- acontext-0.0.17.dist-info/RECORD +41 -0
- {acontext-0.0.14.dist-info → acontext-0.0.17.dist-info}/WHEEL +1 -1
- acontext-0.0.14.dist-info/RECORD +0 -33
|
@@ -23,6 +23,7 @@ class AsyncSpacesAPI:
|
|
|
23
23
|
async def list(
|
|
24
24
|
self,
|
|
25
25
|
*,
|
|
26
|
+
user: str | None = None,
|
|
26
27
|
limit: int | None = None,
|
|
27
28
|
cursor: str | None = None,
|
|
28
29
|
time_desc: bool | None = None,
|
|
@@ -30,6 +31,7 @@ class AsyncSpacesAPI:
|
|
|
30
31
|
"""List all spaces in the project.
|
|
31
32
|
|
|
32
33
|
Args:
|
|
34
|
+
user: Filter by user identifier. Defaults to None.
|
|
33
35
|
limit: Maximum number of spaces to return. Defaults to None.
|
|
34
36
|
cursor: Cursor for pagination. Defaults to None.
|
|
35
37
|
time_desc: Order by created_at descending if True, ascending if False. Defaults to None.
|
|
@@ -37,20 +39,28 @@ class AsyncSpacesAPI:
|
|
|
37
39
|
Returns:
|
|
38
40
|
ListSpacesOutput containing the list of spaces and pagination information.
|
|
39
41
|
"""
|
|
40
|
-
params = build_params(limit=limit, cursor=cursor, time_desc=time_desc)
|
|
42
|
+
params = build_params(user=user, limit=limit, cursor=cursor, time_desc=time_desc)
|
|
41
43
|
data = await self._requester.request("GET", "/space", params=params or None)
|
|
42
44
|
return ListSpacesOutput.model_validate(data)
|
|
43
45
|
|
|
44
|
-
async def create(
|
|
46
|
+
async def create(
|
|
47
|
+
self,
|
|
48
|
+
*,
|
|
49
|
+
user: str | None = None,
|
|
50
|
+
configs: Mapping[str, Any] | None = None,
|
|
51
|
+
) -> Space:
|
|
45
52
|
"""Create a new space.
|
|
46
53
|
|
|
47
54
|
Args:
|
|
55
|
+
user: Optional user identifier string. Defaults to None.
|
|
48
56
|
configs: Optional space configuration dictionary. Defaults to None.
|
|
49
57
|
|
|
50
58
|
Returns:
|
|
51
59
|
The created Space object.
|
|
52
60
|
"""
|
|
53
61
|
payload: dict[str, Any] = {}
|
|
62
|
+
if user is not None:
|
|
63
|
+
payload["user"] = user
|
|
54
64
|
if configs is not None:
|
|
55
65
|
payload["configs"] = configs
|
|
56
66
|
data = await self._requester.request("POST", "/space", json_data=payload)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""
|
|
2
|
+
User management endpoints (async).
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from urllib.parse import quote
|
|
6
|
+
|
|
7
|
+
from .._utils import build_params
|
|
8
|
+
from ..client_types import AsyncRequesterProtocol
|
|
9
|
+
from ..types.user import GetUserResourcesOutput, ListUsersOutput
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AsyncUsersAPI:
|
|
13
|
+
def __init__(self, requester: AsyncRequesterProtocol) -> None:
|
|
14
|
+
self._requester = requester
|
|
15
|
+
|
|
16
|
+
async def list(
|
|
17
|
+
self,
|
|
18
|
+
*,
|
|
19
|
+
limit: int | None = None,
|
|
20
|
+
cursor: str | None = None,
|
|
21
|
+
time_desc: bool | None = None,
|
|
22
|
+
) -> ListUsersOutput:
|
|
23
|
+
"""List all users in the project.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
limit: Maximum number of users to return. If not provided or 0, all users will be returned. Defaults to None.
|
|
27
|
+
cursor: Cursor for pagination. Defaults to None.
|
|
28
|
+
time_desc: Order by created_at descending if True, ascending if False. Defaults to None.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
ListUsersOutput containing the list of users and pagination information.
|
|
32
|
+
"""
|
|
33
|
+
params = build_params(limit=limit, cursor=cursor, time_desc=time_desc)
|
|
34
|
+
data = await self._requester.request("GET", "/user/ls", params=params or None)
|
|
35
|
+
return ListUsersOutput.model_validate(data)
|
|
36
|
+
|
|
37
|
+
async def get_resources(self, identifier: str) -> GetUserResourcesOutput:
|
|
38
|
+
"""Get resource counts for a user.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
identifier: The user identifier string.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
GetUserResourcesOutput containing counts for Spaces, Sessions, Disks, and Skills.
|
|
45
|
+
"""
|
|
46
|
+
data = await self._requester.request(
|
|
47
|
+
"GET", f"/user/{quote(identifier, safe='')}/resources"
|
|
48
|
+
)
|
|
49
|
+
return GetUserResourcesOutput.model_validate(data)
|
|
50
|
+
|
|
51
|
+
async def delete(self, identifier: str) -> None:
|
|
52
|
+
"""Delete a user and cascade delete all associated resources (Space, Session, Disk, Skill).
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
identifier: The user identifier string.
|
|
56
|
+
"""
|
|
57
|
+
await self._requester.request("DELETE", f"/user/{quote(identifier, safe='')}")
|
acontext/resources/disks.py
CHANGED
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
Disk and artifact endpoints.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
5
7
|
import json
|
|
6
8
|
from collections.abc import Mapping
|
|
7
9
|
from typing import Any, BinaryIO, cast
|
|
8
10
|
|
|
11
|
+
from pydantic import TypeAdapter
|
|
12
|
+
|
|
9
13
|
from .._utils import build_params
|
|
10
14
|
from ..client_types import RequesterProtocol
|
|
11
15
|
from ..types.disk import (
|
|
@@ -27,6 +31,7 @@ class DisksAPI:
|
|
|
27
31
|
def list(
|
|
28
32
|
self,
|
|
29
33
|
*,
|
|
34
|
+
user: str | None = None,
|
|
30
35
|
limit: int | None = None,
|
|
31
36
|
cursor: str | None = None,
|
|
32
37
|
time_desc: bool | None = None,
|
|
@@ -34,6 +39,7 @@ class DisksAPI:
|
|
|
34
39
|
"""List all disks in the project.
|
|
35
40
|
|
|
36
41
|
Args:
|
|
42
|
+
user: Filter by user identifier. Defaults to None.
|
|
37
43
|
limit: Maximum number of disks to return. Defaults to None.
|
|
38
44
|
cursor: Cursor for pagination. Defaults to None.
|
|
39
45
|
time_desc: Order by created_at descending if True, ascending if False. Defaults to None.
|
|
@@ -41,17 +47,23 @@ class DisksAPI:
|
|
|
41
47
|
Returns:
|
|
42
48
|
ListDisksOutput containing the list of disks and pagination information.
|
|
43
49
|
"""
|
|
44
|
-
params = build_params(limit=limit, cursor=cursor, time_desc=time_desc)
|
|
50
|
+
params = build_params(user=user, limit=limit, cursor=cursor, time_desc=time_desc)
|
|
45
51
|
data = self._requester.request("GET", "/disk", params=params or None)
|
|
46
52
|
return ListDisksOutput.model_validate(data)
|
|
47
53
|
|
|
48
|
-
def create(self) -> Disk:
|
|
54
|
+
def create(self, *, user: str | None = None) -> Disk:
|
|
49
55
|
"""Create a new disk.
|
|
50
56
|
|
|
57
|
+
Args:
|
|
58
|
+
user: Optional user identifier string. Defaults to None.
|
|
59
|
+
|
|
51
60
|
Returns:
|
|
52
61
|
The created Disk object.
|
|
53
62
|
"""
|
|
54
|
-
|
|
63
|
+
payload: dict[str, Any] = {}
|
|
64
|
+
if user is not None:
|
|
65
|
+
payload["user"] = user
|
|
66
|
+
data = self._requester.request("POST", "/disk", json_data=payload or None)
|
|
55
67
|
return Disk.model_validate(data)
|
|
56
68
|
|
|
57
69
|
def delete(self, disk_id: str) -> None:
|
|
@@ -187,8 +199,85 @@ class DiskArtifactsAPI:
|
|
|
187
199
|
*,
|
|
188
200
|
path: str | None = None,
|
|
189
201
|
) -> ListArtifactsResp:
|
|
202
|
+
"""List artifacts in a disk at a specific path.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
disk_id: The UUID of the disk.
|
|
206
|
+
path: Directory path to list. Defaults to None (root).
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
ListArtifactsResp containing the list of artifacts.
|
|
210
|
+
"""
|
|
190
211
|
params: dict[str, Any] = {}
|
|
191
212
|
if path is not None:
|
|
192
213
|
params["path"] = path
|
|
193
214
|
data = self._requester.request("GET", f"/disk/{disk_id}/artifact/ls", params=params or None)
|
|
194
215
|
return ListArtifactsResp.model_validate(data)
|
|
216
|
+
|
|
217
|
+
def grep_artifacts(
|
|
218
|
+
self,
|
|
219
|
+
disk_id: str,
|
|
220
|
+
*,
|
|
221
|
+
query: str,
|
|
222
|
+
limit: int = 100,
|
|
223
|
+
) -> list[Artifact]:
|
|
224
|
+
"""Search artifact content using regex pattern.
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
disk_id: The disk ID to search in
|
|
228
|
+
query: Regex pattern to search for in file content
|
|
229
|
+
limit: Maximum number of results (default 100, max 1000)
|
|
230
|
+
|
|
231
|
+
Returns:
|
|
232
|
+
List of matching artifacts
|
|
233
|
+
|
|
234
|
+
Example:
|
|
235
|
+
```python
|
|
236
|
+
# Search for TODO comments in code
|
|
237
|
+
results = client.disks.artifacts.grep_artifacts(
|
|
238
|
+
disk_id="disk-uuid",
|
|
239
|
+
query="TODO.*bug"
|
|
240
|
+
)
|
|
241
|
+
```
|
|
242
|
+
"""
|
|
243
|
+
params = build_params(query=query, limit=limit)
|
|
244
|
+
data = self._requester.request(
|
|
245
|
+
"GET",
|
|
246
|
+
f"/disk/{disk_id}/artifact/grep",
|
|
247
|
+
params=params
|
|
248
|
+
)
|
|
249
|
+
return TypeAdapter(list[Artifact]).validate_python(data)
|
|
250
|
+
|
|
251
|
+
def glob_artifacts(
|
|
252
|
+
self,
|
|
253
|
+
disk_id: str,
|
|
254
|
+
*,
|
|
255
|
+
query: str,
|
|
256
|
+
limit: int = 100,
|
|
257
|
+
) -> list[Artifact]:
|
|
258
|
+
"""Search artifact paths using glob pattern.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
disk_id: The disk ID to search in
|
|
262
|
+
query: Glob pattern (e.g., '**/*.py', '*.txt')
|
|
263
|
+
limit: Maximum number of results (default 100, max 1000)
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
List of matching artifacts
|
|
267
|
+
|
|
268
|
+
Example:
|
|
269
|
+
```python
|
|
270
|
+
# Find all Python files
|
|
271
|
+
results = client.disks.artifacts.glob_artifacts(
|
|
272
|
+
disk_id="disk-uuid",
|
|
273
|
+
query="**/*.py"
|
|
274
|
+
)
|
|
275
|
+
```
|
|
276
|
+
"""
|
|
277
|
+
params = build_params(query=query, limit=limit)
|
|
278
|
+
data = self._requester.request(
|
|
279
|
+
"GET",
|
|
280
|
+
f"/disk/{disk_id}/artifact/glob",
|
|
281
|
+
params=params
|
|
282
|
+
)
|
|
283
|
+
return TypeAdapter(list[Artifact]).validate_python(data)
|
acontext/resources/sessions.py
CHANGED
|
@@ -37,6 +37,7 @@ class SessionsAPI:
|
|
|
37
37
|
def list(
|
|
38
38
|
self,
|
|
39
39
|
*,
|
|
40
|
+
user: str | None = None,
|
|
40
41
|
space_id: str | None = None,
|
|
41
42
|
not_connected: bool | None = None,
|
|
42
43
|
limit: int | None = None,
|
|
@@ -46,6 +47,7 @@ class SessionsAPI:
|
|
|
46
47
|
"""List all sessions in the project.
|
|
47
48
|
|
|
48
49
|
Args:
|
|
50
|
+
user: Filter by user identifier. Defaults to None.
|
|
49
51
|
space_id: Filter sessions by space ID. Defaults to None.
|
|
50
52
|
not_connected: Filter sessions that are not connected to a space. Defaults to None.
|
|
51
53
|
limit: Maximum number of sessions to return. Defaults to None.
|
|
@@ -56,6 +58,8 @@ class SessionsAPI:
|
|
|
56
58
|
ListSessionsOutput containing the list of sessions and pagination information.
|
|
57
59
|
"""
|
|
58
60
|
params: dict[str, Any] = {}
|
|
61
|
+
if user:
|
|
62
|
+
params["user"] = user
|
|
59
63
|
if space_id:
|
|
60
64
|
params["space_id"] = space_id
|
|
61
65
|
params.update(
|
|
@@ -72,6 +76,7 @@ class SessionsAPI:
|
|
|
72
76
|
def create(
|
|
73
77
|
self,
|
|
74
78
|
*,
|
|
79
|
+
user: str | None = None,
|
|
75
80
|
space_id: str | None = None,
|
|
76
81
|
disable_task_tracking: bool | None = None,
|
|
77
82
|
configs: Mapping[str, Any] | None = None,
|
|
@@ -79,6 +84,7 @@ class SessionsAPI:
|
|
|
79
84
|
"""Create a new session.
|
|
80
85
|
|
|
81
86
|
Args:
|
|
87
|
+
user: Optional user identifier string. Defaults to None.
|
|
82
88
|
space_id: Optional space ID to associate with the session. Defaults to None.
|
|
83
89
|
disable_task_tracking: Whether to disable task tracking for this session. Defaults to None (server default: False).
|
|
84
90
|
configs: Optional session configuration dictionary. Defaults to None.
|
|
@@ -87,6 +93,8 @@ class SessionsAPI:
|
|
|
87
93
|
The created Session object.
|
|
88
94
|
"""
|
|
89
95
|
payload: dict[str, Any] = {}
|
|
96
|
+
if user:
|
|
97
|
+
payload["user"] = user
|
|
90
98
|
if space_id:
|
|
91
99
|
payload["space_id"] = space_id
|
|
92
100
|
if disable_task_tracking is not None:
|
|
@@ -271,6 +279,7 @@ class SessionsAPI:
|
|
|
271
279
|
format: Literal["acontext", "openai", "anthropic", "gemini"] = "openai",
|
|
272
280
|
time_desc: bool | None = None,
|
|
273
281
|
edit_strategies: Optional[List[EditStrategy]] = None,
|
|
282
|
+
pin_editing_strategies_at_message: str | None = None,
|
|
274
283
|
) -> GetMessagesOutput:
|
|
275
284
|
"""Get messages for a session.
|
|
276
285
|
|
|
@@ -287,6 +296,12 @@ class SessionsAPI:
|
|
|
287
296
|
- Remove tool results: [{"type": "remove_tool_result", "params": {"keep_recent_n_tool_results": 3}}]
|
|
288
297
|
- Token limit: [{"type": "token_limit", "params": {"limit_tokens": 20000}}]
|
|
289
298
|
Defaults to None.
|
|
299
|
+
pin_editing_strategies_at_message: Message ID to pin editing strategies at.
|
|
300
|
+
When provided, strategies are only applied to messages up to and including
|
|
301
|
+
this message ID, keeping subsequent messages unchanged. This helps maintain
|
|
302
|
+
prompt cache stability by preserving a stable prefix. The response includes
|
|
303
|
+
edit_at_message_id indicating where strategies were applied. Pass this value
|
|
304
|
+
in subsequent requests to maintain cache hits. Defaults to None.
|
|
290
305
|
|
|
291
306
|
Returns:
|
|
292
307
|
GetMessagesOutput containing the list of messages and pagination information.
|
|
@@ -304,6 +319,8 @@ class SessionsAPI:
|
|
|
304
319
|
)
|
|
305
320
|
if edit_strategies is not None:
|
|
306
321
|
params["edit_strategies"] = json.dumps(edit_strategies)
|
|
322
|
+
if pin_editing_strategies_at_message is not None:
|
|
323
|
+
params["pin_editing_strategies_at_message"] = pin_editing_strategies_at_message
|
|
307
324
|
data = self._requester.request(
|
|
308
325
|
"GET", f"/session/{session_id}/messages", params=params or None
|
|
309
326
|
)
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Skills endpoints.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from collections.abc import Mapping
|
|
7
|
+
from typing import Any, BinaryIO, cast
|
|
8
|
+
|
|
9
|
+
from .._utils import build_params
|
|
10
|
+
from ..client_types import RequesterProtocol
|
|
11
|
+
from ..types.skill import (
|
|
12
|
+
GetSkillFileResp,
|
|
13
|
+
ListSkillsOutput,
|
|
14
|
+
Skill,
|
|
15
|
+
SkillCatalogItem,
|
|
16
|
+
_ListSkillsResponse,
|
|
17
|
+
)
|
|
18
|
+
from ..uploads import FileUpload, normalize_file_upload
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class SkillsAPI:
|
|
22
|
+
def __init__(self, requester: RequesterProtocol) -> None:
|
|
23
|
+
self._requester = requester
|
|
24
|
+
|
|
25
|
+
def create(
|
|
26
|
+
self,
|
|
27
|
+
*,
|
|
28
|
+
file: FileUpload
|
|
29
|
+
| tuple[str, BinaryIO | bytes]
|
|
30
|
+
| tuple[str, BinaryIO | bytes, str],
|
|
31
|
+
user: str | None = None,
|
|
32
|
+
meta: Mapping[str, Any] | None = None,
|
|
33
|
+
) -> Skill:
|
|
34
|
+
"""Create a new skill by uploading a ZIP file.
|
|
35
|
+
|
|
36
|
+
The ZIP file must contain a SKILL.md file (case-insensitive) with YAML format
|
|
37
|
+
containing 'name' and 'description' fields.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
file: The ZIP file to upload (FileUpload object or tuple format).
|
|
41
|
+
user: Optional user identifier string. Defaults to None.
|
|
42
|
+
meta: Custom metadata as JSON-serializable dict, defaults to None.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Skill containing the created skill information.
|
|
46
|
+
"""
|
|
47
|
+
upload = normalize_file_upload(file)
|
|
48
|
+
files = {"file": upload.as_httpx()}
|
|
49
|
+
form: dict[str, Any] = {}
|
|
50
|
+
if user is not None:
|
|
51
|
+
form["user"] = user
|
|
52
|
+
if meta is not None:
|
|
53
|
+
form["meta"] = json.dumps(cast(Mapping[str, Any], meta))
|
|
54
|
+
data = self._requester.request(
|
|
55
|
+
"POST",
|
|
56
|
+
"/agent_skills",
|
|
57
|
+
data=form or None,
|
|
58
|
+
files=files,
|
|
59
|
+
)
|
|
60
|
+
return Skill.model_validate(data)
|
|
61
|
+
|
|
62
|
+
def list_catalog(
|
|
63
|
+
self,
|
|
64
|
+
*,
|
|
65
|
+
user: str | None = None,
|
|
66
|
+
limit: int | None = None,
|
|
67
|
+
cursor: str | None = None,
|
|
68
|
+
time_desc: bool | None = None,
|
|
69
|
+
) -> ListSkillsOutput:
|
|
70
|
+
"""Get a catalog of skills (names and descriptions only) with pagination.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
user: Filter by user identifier. Defaults to None.
|
|
74
|
+
limit: Maximum number of skills per page (defaults to 100, max 200).
|
|
75
|
+
cursor: Cursor for pagination to fetch the next page (optional).
|
|
76
|
+
time_desc: Order by created_at descending if True, ascending if False (defaults to False).
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
ListSkillsOutput containing skills with name and description for the current page,
|
|
80
|
+
along with pagination information (next_cursor and has_more).
|
|
81
|
+
"""
|
|
82
|
+
effective_limit = limit if limit is not None else 100
|
|
83
|
+
params = build_params(user=user, limit=effective_limit, cursor=cursor, time_desc=time_desc)
|
|
84
|
+
data = self._requester.request("GET", "/agent_skills", params=params or None)
|
|
85
|
+
api_response = _ListSkillsResponse.model_validate(data)
|
|
86
|
+
|
|
87
|
+
# Convert to catalog format (name and description only)
|
|
88
|
+
return ListSkillsOutput(
|
|
89
|
+
items=[
|
|
90
|
+
SkillCatalogItem(name=skill.name, description=skill.description)
|
|
91
|
+
for skill in api_response.items
|
|
92
|
+
],
|
|
93
|
+
next_cursor=api_response.next_cursor,
|
|
94
|
+
has_more=api_response.has_more,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
def get_by_name(self, name: str) -> Skill:
|
|
98
|
+
"""Get a skill by its name.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
name: The name of the skill (unique within project).
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
Skill containing the skill information.
|
|
105
|
+
"""
|
|
106
|
+
params = {"name": name}
|
|
107
|
+
data = self._requester.request("GET", "/agent_skills/by_name", params=params)
|
|
108
|
+
return Skill.model_validate(data)
|
|
109
|
+
|
|
110
|
+
def delete(self, skill_id: str) -> None:
|
|
111
|
+
"""Delete a skill by its ID.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
skill_id: The UUID of the skill to delete.
|
|
115
|
+
"""
|
|
116
|
+
self._requester.request("DELETE", f"/agent_skills/{skill_id}")
|
|
117
|
+
|
|
118
|
+
def get_file_by_name(
|
|
119
|
+
self,
|
|
120
|
+
*,
|
|
121
|
+
skill_name: str,
|
|
122
|
+
file_path: str,
|
|
123
|
+
expire: int | None = None,
|
|
124
|
+
) -> GetSkillFileResp:
|
|
125
|
+
"""Get a file from a skill by name.
|
|
126
|
+
|
|
127
|
+
The backend automatically returns content for parseable text files, or a presigned URL
|
|
128
|
+
for non-parseable files (binary, images, etc.).
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
skill_name: The name of the skill.
|
|
132
|
+
file_path: Relative path to the file within the skill (e.g., 'scripts/extract_text.json').
|
|
133
|
+
expire: URL expiration time in seconds. Defaults to 900 (15 minutes).
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
GetSkillFileResp containing the file path, MIME type, and either content or URL.
|
|
137
|
+
"""
|
|
138
|
+
endpoint = f"/agent_skills/by_name/{skill_name}/file"
|
|
139
|
+
|
|
140
|
+
params = {"file_path": file_path}
|
|
141
|
+
if expire is not None:
|
|
142
|
+
params["expire"] = expire
|
|
143
|
+
|
|
144
|
+
data = self._requester.request("GET", endpoint, params=params)
|
|
145
|
+
return GetSkillFileResp.model_validate(data)
|
|
146
|
+
|
acontext/resources/spaces.py
CHANGED
|
@@ -23,6 +23,7 @@ class SpacesAPI:
|
|
|
23
23
|
def list(
|
|
24
24
|
self,
|
|
25
25
|
*,
|
|
26
|
+
user: str | None = None,
|
|
26
27
|
limit: int | None = None,
|
|
27
28
|
cursor: str | None = None,
|
|
28
29
|
time_desc: bool | None = None,
|
|
@@ -30,6 +31,7 @@ class SpacesAPI:
|
|
|
30
31
|
"""List all spaces in the project.
|
|
31
32
|
|
|
32
33
|
Args:
|
|
34
|
+
user: Filter by user identifier. Defaults to None.
|
|
33
35
|
limit: Maximum number of spaces to return. Defaults to None.
|
|
34
36
|
cursor: Cursor for pagination. Defaults to None.
|
|
35
37
|
time_desc: Order by created_at descending if True, ascending if False. Defaults to None.
|
|
@@ -37,20 +39,28 @@ class SpacesAPI:
|
|
|
37
39
|
Returns:
|
|
38
40
|
ListSpacesOutput containing the list of spaces and pagination information.
|
|
39
41
|
"""
|
|
40
|
-
params = build_params(limit=limit, cursor=cursor, time_desc=time_desc)
|
|
42
|
+
params = build_params(user=user, limit=limit, cursor=cursor, time_desc=time_desc)
|
|
41
43
|
data = self._requester.request("GET", "/space", params=params or None)
|
|
42
44
|
return ListSpacesOutput.model_validate(data)
|
|
43
45
|
|
|
44
|
-
def create(
|
|
46
|
+
def create(
|
|
47
|
+
self,
|
|
48
|
+
*,
|
|
49
|
+
user: str | None = None,
|
|
50
|
+
configs: Mapping[str, Any] | None = None,
|
|
51
|
+
) -> Space:
|
|
45
52
|
"""Create a new space.
|
|
46
53
|
|
|
47
54
|
Args:
|
|
55
|
+
user: Optional user identifier string. Defaults to None.
|
|
48
56
|
configs: Optional space configuration dictionary. Defaults to None.
|
|
49
57
|
|
|
50
58
|
Returns:
|
|
51
59
|
The created Space object.
|
|
52
60
|
"""
|
|
53
61
|
payload: dict[str, Any] = {}
|
|
62
|
+
if user is not None:
|
|
63
|
+
payload["user"] = user
|
|
54
64
|
if configs is not None:
|
|
55
65
|
payload["configs"] = configs
|
|
56
66
|
data = self._requester.request("POST", "/space", json_data=payload)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""
|
|
2
|
+
User management endpoints.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from urllib.parse import quote
|
|
6
|
+
|
|
7
|
+
from .._utils import build_params
|
|
8
|
+
from ..client_types import RequesterProtocol
|
|
9
|
+
from ..types.user import GetUserResourcesOutput, ListUsersOutput
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class UsersAPI:
|
|
13
|
+
def __init__(self, requester: RequesterProtocol) -> None:
|
|
14
|
+
self._requester = requester
|
|
15
|
+
|
|
16
|
+
def list(
|
|
17
|
+
self,
|
|
18
|
+
*,
|
|
19
|
+
limit: int | None = None,
|
|
20
|
+
cursor: str | None = None,
|
|
21
|
+
time_desc: bool | None = None,
|
|
22
|
+
) -> ListUsersOutput:
|
|
23
|
+
"""List all users in the project.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
limit: Maximum number of users to return. If not provided or 0, all users will be returned. Defaults to None.
|
|
27
|
+
cursor: Cursor for pagination. Defaults to None.
|
|
28
|
+
time_desc: Order by created_at descending if True, ascending if False. Defaults to None.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
ListUsersOutput containing the list of users and pagination information.
|
|
32
|
+
"""
|
|
33
|
+
params = build_params(limit=limit, cursor=cursor, time_desc=time_desc)
|
|
34
|
+
data = self._requester.request("GET", "/user/ls", params=params or None)
|
|
35
|
+
return ListUsersOutput.model_validate(data)
|
|
36
|
+
|
|
37
|
+
def get_resources(self, identifier: str) -> GetUserResourcesOutput:
|
|
38
|
+
"""Get resource counts for a user.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
identifier: The user identifier string.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
GetUserResourcesOutput containing counts for Spaces, Sessions, Disks, and Skills.
|
|
45
|
+
"""
|
|
46
|
+
data = self._requester.request(
|
|
47
|
+
"GET", f"/user/{quote(identifier, safe='')}/resources"
|
|
48
|
+
)
|
|
49
|
+
return GetUserResourcesOutput.model_validate(data)
|
|
50
|
+
|
|
51
|
+
def delete(self, identifier: str) -> None:
|
|
52
|
+
"""Delete a user and cascade delete all associated resources (Space, Session, Disk, Skill).
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
identifier: The user identifier string.
|
|
56
|
+
"""
|
|
57
|
+
self._requester.request("DELETE", f"/user/{quote(identifier, safe='')}")
|
acontext/types/__init__.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"""Type definitions for API responses."""
|
|
2
2
|
|
|
3
|
+
from .common import FileContent
|
|
3
4
|
from .disk import (
|
|
4
5
|
Artifact,
|
|
5
6
|
Disk,
|
|
6
|
-
FileContent,
|
|
7
7
|
GetArtifactResp,
|
|
8
8
|
ListArtifactsResp,
|
|
9
9
|
ListDisksOutput,
|
|
@@ -38,6 +38,19 @@ from .tool import (
|
|
|
38
38
|
ToolReferenceData,
|
|
39
39
|
ToolRenameItem,
|
|
40
40
|
)
|
|
41
|
+
from .skill import (
|
|
42
|
+
FileInfo,
|
|
43
|
+
GetSkillFileResp,
|
|
44
|
+
ListSkillsOutput,
|
|
45
|
+
Skill,
|
|
46
|
+
SkillCatalogItem,
|
|
47
|
+
)
|
|
48
|
+
from .user import (
|
|
49
|
+
GetUserResourcesOutput,
|
|
50
|
+
ListUsersOutput,
|
|
51
|
+
User,
|
|
52
|
+
UserResourceCounts,
|
|
53
|
+
)
|
|
41
54
|
|
|
42
55
|
__all__ = [
|
|
43
56
|
# Disk types
|
|
@@ -75,4 +88,15 @@ __all__ = [
|
|
|
75
88
|
"InsertBlockResponse",
|
|
76
89
|
"ToolReferenceData",
|
|
77
90
|
"ToolRenameItem",
|
|
91
|
+
# Skill types
|
|
92
|
+
"FileInfo",
|
|
93
|
+
"Skill",
|
|
94
|
+
"SkillCatalogItem",
|
|
95
|
+
"ListSkillsOutput",
|
|
96
|
+
"GetSkillFileResp",
|
|
97
|
+
# User types
|
|
98
|
+
"GetUserResourcesOutput",
|
|
99
|
+
"ListUsersOutput",
|
|
100
|
+
"User",
|
|
101
|
+
"UserResourceCounts",
|
|
78
102
|
]
|
acontext/types/common.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""Common type definitions shared across modules."""
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class FileContent(BaseModel):
|
|
7
|
+
"""Parsed file content model."""
|
|
8
|
+
|
|
9
|
+
type: str = Field(..., description="File content type: 'text', 'json', 'csv', or 'code'")
|
|
10
|
+
raw: str = Field(..., description="Raw text content of the file")
|
|
11
|
+
|
acontext/types/disk.py
CHANGED
|
@@ -4,12 +4,15 @@ from typing import Any
|
|
|
4
4
|
|
|
5
5
|
from pydantic import BaseModel, Field
|
|
6
6
|
|
|
7
|
+
from .common import FileContent
|
|
8
|
+
|
|
7
9
|
|
|
8
10
|
class Disk(BaseModel):
|
|
9
11
|
"""Disk model representing a disk resource."""
|
|
10
12
|
|
|
11
13
|
id: str = Field(..., description="Disk UUID")
|
|
12
14
|
project_id: str = Field(..., description="Project UUID")
|
|
15
|
+
user_id: str | None = Field(None, description="User UUID")
|
|
13
16
|
created_at: str = Field(..., description="ISO 8601 formatted creation timestamp")
|
|
14
17
|
updated_at: str = Field(..., description="ISO 8601 formatted update timestamp")
|
|
15
18
|
|
|
@@ -36,13 +39,6 @@ class Artifact(BaseModel):
|
|
|
36
39
|
updated_at: str = Field(..., description="ISO 8601 formatted update timestamp")
|
|
37
40
|
|
|
38
41
|
|
|
39
|
-
class FileContent(BaseModel):
|
|
40
|
-
"""Parsed file content model."""
|
|
41
|
-
|
|
42
|
-
type: str = Field(..., description="File content type: 'text', 'json', 'csv', or 'code'")
|
|
43
|
-
raw: str = Field(..., description="Raw text content of the file")
|
|
44
|
-
|
|
45
|
-
|
|
46
42
|
class GetArtifactResp(BaseModel):
|
|
47
43
|
"""Response model for getting an artifact."""
|
|
48
44
|
|