gumloop 0.3.1__tar.gz → 0.3.2__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.
- {gumloop-0.3.1 → gumloop-0.3.2}/PKG-INFO +1 -1
- {gumloop-0.3.1 → gumloop-0.3.2}/pyproject.toml +1 -1
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/__init__.py +1 -1
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/_http.py +2 -2
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/cli/commands/sessions.py +93 -0
- gumloop-0.3.2/src/gumloop/resources/agents.py +183 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/resources/sessions.py +62 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/types.py +71 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/cli/test_sessions.py +27 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/sdk/test_agents.py +100 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/sdk/test_sessions.py +43 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/uv.lock +2 -2
- gumloop-0.3.1/src/gumloop/resources/agents.py +0 -101
- {gumloop-0.3.1 → gumloop-0.3.2}/.env.example +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/.gitignore +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/.pre-commit-config.yaml +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/.python-version +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/LICENSE +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/README.md +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/scripts/check +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/scripts/fmt +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/scripts/sdk_examples.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/_client.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/cli/__init__.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/cli/commands/__init__.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/cli/commands/_args_input.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/cli/commands/_downloads.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/cli/commands/agents.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/cli/commands/artifacts.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/cli/commands/auth.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/cli/commands/chat.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/cli/commands/mcp.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/cli/commands/skills.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/cli/console.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/cli/context.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/cli/credentials.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/cli/errors.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/cli/main.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/cli/oauth.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/errors.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/oauth.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/py.typed +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/resources/__init__.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/resources/artifacts.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/resources/chat.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/resources/mcp.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/resources/skills.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/resources/teams.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/spec/__init__.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/spec/_compat.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/src/gumloop/spec/_extensions.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/__init__.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/cli/__init__.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/cli/conftest.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/cli/test_agents.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/cli/test_args_input.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/cli/test_artifacts.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/cli/test_chat.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/cli/test_context.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/cli/test_credentials.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/cli/test_login.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/cli/test_main.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/cli/test_mcp.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/cli/test_skills.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/conftest.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/integration/conftest.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/integration/test_live.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/sdk/__init__.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/sdk/conftest.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/sdk/helpers.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/sdk/test_artifacts.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/sdk/test_chat.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/sdk/test_client.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/sdk/test_mcp.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/sdk/test_oauth.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/sdk/test_skills.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/sdk/test_teams.py +0 -0
- {gumloop-0.3.1 → gumloop-0.3.2}/tests/test_client.py +0 -0
|
@@ -184,7 +184,7 @@ class HttpClient:
|
|
|
184
184
|
yield response_model.model_validate_json(event.data)
|
|
185
185
|
except ValidationError:
|
|
186
186
|
# Server-side mid-stream error frames or schema-drift events
|
|
187
|
-
# land here.
|
|
187
|
+
# land here.
|
|
188
188
|
logger.debug("dropped non-%s SSE: %s", response_model.__name__, event.data)
|
|
189
189
|
continue
|
|
190
190
|
|
|
@@ -320,7 +320,7 @@ class AsyncHttpClient:
|
|
|
320
320
|
yield response_model.model_validate_json(event.data)
|
|
321
321
|
except ValidationError:
|
|
322
322
|
# Server-side mid-stream error frames or schema-drift events
|
|
323
|
-
# land here.
|
|
323
|
+
# land here.
|
|
324
324
|
logger.debug("dropped non-%s SSE: %s", response_model.__name__, event.data)
|
|
325
325
|
continue
|
|
326
326
|
|
|
@@ -93,6 +93,99 @@ def create_session(
|
|
|
93
93
|
console.print(f" [{m.role or ''}] {content[:200]}", markup=False, highlight=False)
|
|
94
94
|
|
|
95
95
|
|
|
96
|
+
@sessions_app.command(
|
|
97
|
+
"list",
|
|
98
|
+
epilog=(
|
|
99
|
+
"Examples:\n"
|
|
100
|
+
" gumloop sessions list agent_abc --state completed --limit 50 --json\n"
|
|
101
|
+
" gumloop sessions list agent_abc --search 'invoice' --sort oldest\n"
|
|
102
|
+
" gumloop sessions list agent_abc --type api --creator user_123"
|
|
103
|
+
),
|
|
104
|
+
)
|
|
105
|
+
def list_sessions(
|
|
106
|
+
ctx: typer.Context,
|
|
107
|
+
agent_id: Annotated[str, typer.Argument(help="Agent id whose sessions should be listed.")],
|
|
108
|
+
search: Annotated[
|
|
109
|
+
str | None,
|
|
110
|
+
typer.Option("--search", help="Search session name and content."),
|
|
111
|
+
] = None,
|
|
112
|
+
state: Annotated[
|
|
113
|
+
str | None,
|
|
114
|
+
typer.Option("--state", help="Filter by state (e.g. completed, failed, processing, idle)."),
|
|
115
|
+
] = None,
|
|
116
|
+
type_filter: Annotated[
|
|
117
|
+
str | None,
|
|
118
|
+
typer.Option("--type", help="Filter by session type (e.g. api, chat, slack)."),
|
|
119
|
+
] = None,
|
|
120
|
+
creator: Annotated[
|
|
121
|
+
str | None,
|
|
122
|
+
typer.Option("--creator", help="Filter by creator user id."),
|
|
123
|
+
] = None,
|
|
124
|
+
trigger_id: Annotated[
|
|
125
|
+
str | None,
|
|
126
|
+
typer.Option("--trigger-id", help="Filter by originating trigger id."),
|
|
127
|
+
] = None,
|
|
128
|
+
sort_order: Annotated[
|
|
129
|
+
str | None,
|
|
130
|
+
typer.Option("--sort", help="Sort order (e.g. newest, oldest, credits_desc, name_asc)."),
|
|
131
|
+
] = None,
|
|
132
|
+
limit: Annotated[
|
|
133
|
+
int | None,
|
|
134
|
+
typer.Option("--limit", help="Maximum number of sessions to return."),
|
|
135
|
+
] = None,
|
|
136
|
+
cursor: Annotated[
|
|
137
|
+
str | None,
|
|
138
|
+
typer.Option("--cursor", help="Pagination cursor from a previous list call."),
|
|
139
|
+
] = None,
|
|
140
|
+
json_output: Annotated[
|
|
141
|
+
bool,
|
|
142
|
+
typer.Option("--json", help="Print the raw SDK response as JSON."),
|
|
143
|
+
] = False,
|
|
144
|
+
) -> None:
|
|
145
|
+
"""List an agent's sessions with search, filters, and sort."""
|
|
146
|
+
cli: CliContext = ctx.obj
|
|
147
|
+
try:
|
|
148
|
+
response = cli.call_with_refresh(
|
|
149
|
+
lambda client: client.sessions.list(
|
|
150
|
+
agent_id,
|
|
151
|
+
search=search,
|
|
152
|
+
state=state,
|
|
153
|
+
type=type_filter,
|
|
154
|
+
creator_user_id=creator,
|
|
155
|
+
trigger_id=trigger_id,
|
|
156
|
+
sort_order=sort_order,
|
|
157
|
+
page_size=limit,
|
|
158
|
+
cursor=cursor,
|
|
159
|
+
)
|
|
160
|
+
)
|
|
161
|
+
except GumloopError as error:
|
|
162
|
+
exit_with_error(error, json_output=json_output)
|
|
163
|
+
|
|
164
|
+
if json_output:
|
|
165
|
+
print_json(response)
|
|
166
|
+
return
|
|
167
|
+
|
|
168
|
+
if not response.sessions:
|
|
169
|
+
console.print("No sessions found.")
|
|
170
|
+
else:
|
|
171
|
+
console.print("ID", "STATE", "TYPE", "NAME", "CREATED", sep="\t", soft_wrap=True)
|
|
172
|
+
for session in response.sessions:
|
|
173
|
+
console.print(
|
|
174
|
+
session.id,
|
|
175
|
+
session.state or "",
|
|
176
|
+
session.type or "",
|
|
177
|
+
session.name or "",
|
|
178
|
+
session.created_at or "",
|
|
179
|
+
sep="\t",
|
|
180
|
+
soft_wrap=True,
|
|
181
|
+
markup=False,
|
|
182
|
+
highlight=False,
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
if response.next_cursor:
|
|
186
|
+
console.print(f"\n[dim]Next cursor:[/dim] {escape_markup(response.next_cursor)}")
|
|
187
|
+
|
|
188
|
+
|
|
96
189
|
@sessions_app.command("get", epilog="Example:\n gumloop sessions get session_abc --json")
|
|
97
190
|
def get_session(
|
|
98
191
|
ctx: typer.Context,
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from gumloop._http import AsyncHttpClient
|
|
7
|
+
from gumloop._http import HttpClient
|
|
8
|
+
from gumloop.types import AgentCreateRequest
|
|
9
|
+
from gumloop.types import AgentListResponse
|
|
10
|
+
from gumloop.types import AgentResponse
|
|
11
|
+
from gumloop.types import AgentUpdateRequest
|
|
12
|
+
from gumloop.types import EvaluationConfigResponse
|
|
13
|
+
from gumloop.types import EvaluationConfigUpdateRequest
|
|
14
|
+
from gumloop.types import EvaluationResultListResponse
|
|
15
|
+
from gumloop.types import EvaluationResultResponse
|
|
16
|
+
from gumloop.types import ModelListResponse
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Agents:
|
|
20
|
+
def __init__(self, client: HttpClient) -> None:
|
|
21
|
+
self._client = client
|
|
22
|
+
|
|
23
|
+
def list(
|
|
24
|
+
self,
|
|
25
|
+
*,
|
|
26
|
+
search: str | None = None,
|
|
27
|
+
team_id: str | None = None,
|
|
28
|
+
**kwargs: Any,
|
|
29
|
+
) -> AgentListResponse:
|
|
30
|
+
return AgentListResponse.model_validate(
|
|
31
|
+
self._client.get("agents", params={"search": search, "team_id": team_id, **kwargs})
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
def create(
|
|
35
|
+
self,
|
|
36
|
+
request: AgentCreateRequest | Mapping[str, Any] | None = None,
|
|
37
|
+
**kwargs: Any,
|
|
38
|
+
) -> AgentResponse:
|
|
39
|
+
return AgentResponse.model_validate(
|
|
40
|
+
self._client.post("agents", json=AgentCreateRequest.build(request, **kwargs))
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
def retrieve(self, agent_id: str) -> AgentResponse:
|
|
44
|
+
return AgentResponse.model_validate(self._client.get(f"agents/{agent_id}"))
|
|
45
|
+
|
|
46
|
+
def update(
|
|
47
|
+
self,
|
|
48
|
+
agent_id: str,
|
|
49
|
+
request: AgentUpdateRequest | Mapping[str, Any] | None = None,
|
|
50
|
+
**kwargs: Any,
|
|
51
|
+
) -> AgentResponse:
|
|
52
|
+
return AgentResponse.model_validate(
|
|
53
|
+
self._client.patch(f"agents/{agent_id}", json=AgentUpdateRequest.build(request, **kwargs))
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
def get_evaluation_config(self, agent_id: str) -> EvaluationConfigResponse:
|
|
57
|
+
return EvaluationConfigResponse.model_validate(self._client.get(f"agents/{agent_id}/evaluation-config"))
|
|
58
|
+
|
|
59
|
+
def update_evaluation_config(
|
|
60
|
+
self,
|
|
61
|
+
agent_id: str,
|
|
62
|
+
request: EvaluationConfigUpdateRequest | Mapping[str, Any] | None = None,
|
|
63
|
+
**kwargs: Any,
|
|
64
|
+
) -> EvaluationConfigResponse:
|
|
65
|
+
"""Partially update the evaluation config. Only the fields you send are changed;
|
|
66
|
+
omitted fields keep their current value. A provided list (criteria/tags/
|
|
67
|
+
data_points) replaces that list wholesale."""
|
|
68
|
+
return EvaluationConfigResponse.model_validate(
|
|
69
|
+
self._client.patch(
|
|
70
|
+
f"agents/{agent_id}/evaluation-config",
|
|
71
|
+
json=EvaluationConfigUpdateRequest.build(request, **kwargs),
|
|
72
|
+
)
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
def list_evaluations(
|
|
76
|
+
self,
|
|
77
|
+
agent_id: str,
|
|
78
|
+
*,
|
|
79
|
+
grade: str | None = None,
|
|
80
|
+
page_size: int | None = None,
|
|
81
|
+
cursor: str | None = None,
|
|
82
|
+
**kwargs: Any,
|
|
83
|
+
) -> EvaluationResultListResponse:
|
|
84
|
+
return EvaluationResultListResponse.model_validate(
|
|
85
|
+
self._client.get(
|
|
86
|
+
f"agents/{agent_id}/evaluations",
|
|
87
|
+
params={"grade": grade, "page_size": page_size, "cursor": cursor, **kwargs},
|
|
88
|
+
)
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
def get_evaluation(self, agent_id: str, evaluation_id: str) -> EvaluationResultResponse:
|
|
92
|
+
return EvaluationResultResponse.model_validate(
|
|
93
|
+
self._client.get(f"agents/{agent_id}/evaluations/{evaluation_id}")
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class Models:
|
|
98
|
+
def __init__(self, client: HttpClient) -> None:
|
|
99
|
+
self._client = client
|
|
100
|
+
|
|
101
|
+
def list(self, **kwargs: Any) -> ModelListResponse:
|
|
102
|
+
return ModelListResponse.model_validate(self._client.get("models", params=kwargs))
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class AsyncAgents:
|
|
106
|
+
def __init__(self, client: AsyncHttpClient) -> None:
|
|
107
|
+
self._client = client
|
|
108
|
+
|
|
109
|
+
async def list(
|
|
110
|
+
self,
|
|
111
|
+
*,
|
|
112
|
+
search: str | None = None,
|
|
113
|
+
team_id: str | None = None,
|
|
114
|
+
**kwargs: Any,
|
|
115
|
+
) -> AgentListResponse:
|
|
116
|
+
data = await self._client.get("agents", params={"search": search, "team_id": team_id, **kwargs})
|
|
117
|
+
return AgentListResponse.model_validate(data)
|
|
118
|
+
|
|
119
|
+
async def create(
|
|
120
|
+
self,
|
|
121
|
+
request: AgentCreateRequest | Mapping[str, Any] | None = None,
|
|
122
|
+
**kwargs: Any,
|
|
123
|
+
) -> AgentResponse:
|
|
124
|
+
data = await self._client.post("agents", json=AgentCreateRequest.build(request, **kwargs))
|
|
125
|
+
return AgentResponse.model_validate(data)
|
|
126
|
+
|
|
127
|
+
async def retrieve(self, agent_id: str) -> AgentResponse:
|
|
128
|
+
return AgentResponse.model_validate(await self._client.get(f"agents/{agent_id}"))
|
|
129
|
+
|
|
130
|
+
async def update(
|
|
131
|
+
self,
|
|
132
|
+
agent_id: str,
|
|
133
|
+
request: AgentUpdateRequest | Mapping[str, Any] | None = None,
|
|
134
|
+
**kwargs: Any,
|
|
135
|
+
) -> AgentResponse:
|
|
136
|
+
data = await self._client.patch(f"agents/{agent_id}", json=AgentUpdateRequest.build(request, **kwargs))
|
|
137
|
+
return AgentResponse.model_validate(data)
|
|
138
|
+
|
|
139
|
+
async def get_evaluation_config(self, agent_id: str) -> EvaluationConfigResponse:
|
|
140
|
+
data = await self._client.get(f"agents/{agent_id}/evaluation-config")
|
|
141
|
+
return EvaluationConfigResponse.model_validate(data)
|
|
142
|
+
|
|
143
|
+
async def update_evaluation_config(
|
|
144
|
+
self,
|
|
145
|
+
agent_id: str,
|
|
146
|
+
request: EvaluationConfigUpdateRequest | Mapping[str, Any] | None = None,
|
|
147
|
+
**kwargs: Any,
|
|
148
|
+
) -> EvaluationConfigResponse:
|
|
149
|
+
"""Partially update the evaluation config. Only the fields you send are changed;
|
|
150
|
+
omitted fields keep their current value. A provided list (criteria/tags/
|
|
151
|
+
data_points) replaces that list wholesale."""
|
|
152
|
+
data = await self._client.patch(
|
|
153
|
+
f"agents/{agent_id}/evaluation-config",
|
|
154
|
+
json=EvaluationConfigUpdateRequest.build(request, **kwargs),
|
|
155
|
+
)
|
|
156
|
+
return EvaluationConfigResponse.model_validate(data)
|
|
157
|
+
|
|
158
|
+
async def list_evaluations(
|
|
159
|
+
self,
|
|
160
|
+
agent_id: str,
|
|
161
|
+
*,
|
|
162
|
+
grade: str | None = None,
|
|
163
|
+
page_size: int | None = None,
|
|
164
|
+
cursor: str | None = None,
|
|
165
|
+
**kwargs: Any,
|
|
166
|
+
) -> EvaluationResultListResponse:
|
|
167
|
+
data = await self._client.get(
|
|
168
|
+
f"agents/{agent_id}/evaluations",
|
|
169
|
+
params={"grade": grade, "page_size": page_size, "cursor": cursor, **kwargs},
|
|
170
|
+
)
|
|
171
|
+
return EvaluationResultListResponse.model_validate(data)
|
|
172
|
+
|
|
173
|
+
async def get_evaluation(self, agent_id: str, evaluation_id: str) -> EvaluationResultResponse:
|
|
174
|
+
data = await self._client.get(f"agents/{agent_id}/evaluations/{evaluation_id}")
|
|
175
|
+
return EvaluationResultResponse.model_validate(data)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class AsyncModels:
|
|
179
|
+
def __init__(self, client: AsyncHttpClient) -> None:
|
|
180
|
+
self._client = client
|
|
181
|
+
|
|
182
|
+
async def list(self, **kwargs: Any) -> ModelListResponse:
|
|
183
|
+
return ModelListResponse.model_validate(await self._client.get("models", params=kwargs))
|
|
@@ -11,6 +11,7 @@ from gumloop._http import AsyncHttpClient
|
|
|
11
11
|
from gumloop._http import HttpClient
|
|
12
12
|
from gumloop.types import SessionContinueRequest
|
|
13
13
|
from gumloop.types import SessionCreateRequest
|
|
14
|
+
from gumloop.types import SessionListResponse
|
|
14
15
|
from gumloop.types import SessionResponse
|
|
15
16
|
from gumloop.types import StreamEvent
|
|
16
17
|
|
|
@@ -19,6 +20,37 @@ class Sessions:
|
|
|
19
20
|
def __init__(self, client: HttpClient) -> None:
|
|
20
21
|
self._client = client
|
|
21
22
|
|
|
23
|
+
def list(
|
|
24
|
+
self,
|
|
25
|
+
agent_id: str,
|
|
26
|
+
*,
|
|
27
|
+
search: str | None = None,
|
|
28
|
+
state: str | None = None,
|
|
29
|
+
type: str | None = None,
|
|
30
|
+
creator_user_id: str | None = None,
|
|
31
|
+
trigger_id: str | None = None,
|
|
32
|
+
sort_order: str | None = None,
|
|
33
|
+
page_size: int | None = None,
|
|
34
|
+
cursor: str | None = None,
|
|
35
|
+
**kwargs: Any,
|
|
36
|
+
) -> SessionListResponse:
|
|
37
|
+
return SessionListResponse.model_validate(
|
|
38
|
+
self._client.get(
|
|
39
|
+
f"agents/{agent_id}/sessions",
|
|
40
|
+
params={
|
|
41
|
+
"search": search,
|
|
42
|
+
"state": state,
|
|
43
|
+
"type": type,
|
|
44
|
+
"creator_user_id": creator_user_id,
|
|
45
|
+
"trigger_id": trigger_id,
|
|
46
|
+
"sort_order": sort_order,
|
|
47
|
+
"page_size": page_size,
|
|
48
|
+
"cursor": cursor,
|
|
49
|
+
**kwargs,
|
|
50
|
+
},
|
|
51
|
+
)
|
|
52
|
+
)
|
|
53
|
+
|
|
22
54
|
@overload
|
|
23
55
|
def create(
|
|
24
56
|
self,
|
|
@@ -117,6 +149,36 @@ class AsyncSessions:
|
|
|
117
149
|
def __init__(self, client: AsyncHttpClient) -> None:
|
|
118
150
|
self._client = client
|
|
119
151
|
|
|
152
|
+
async def list(
|
|
153
|
+
self,
|
|
154
|
+
agent_id: str,
|
|
155
|
+
*,
|
|
156
|
+
search: str | None = None,
|
|
157
|
+
state: str | None = None,
|
|
158
|
+
type: str | None = None,
|
|
159
|
+
creator_user_id: str | None = None,
|
|
160
|
+
trigger_id: str | None = None,
|
|
161
|
+
sort_order: str | None = None,
|
|
162
|
+
page_size: int | None = None,
|
|
163
|
+
cursor: str | None = None,
|
|
164
|
+
**kwargs: Any,
|
|
165
|
+
) -> SessionListResponse:
|
|
166
|
+
data = await self._client.get(
|
|
167
|
+
f"agents/{agent_id}/sessions",
|
|
168
|
+
params={
|
|
169
|
+
"search": search,
|
|
170
|
+
"state": state,
|
|
171
|
+
"type": type,
|
|
172
|
+
"creator_user_id": creator_user_id,
|
|
173
|
+
"trigger_id": trigger_id,
|
|
174
|
+
"sort_order": sort_order,
|
|
175
|
+
"page_size": page_size,
|
|
176
|
+
"cursor": cursor,
|
|
177
|
+
**kwargs,
|
|
178
|
+
},
|
|
179
|
+
)
|
|
180
|
+
return SessionListResponse.model_validate(data)
|
|
181
|
+
|
|
120
182
|
@overload
|
|
121
183
|
async def create(
|
|
122
184
|
self,
|
|
@@ -4,6 +4,7 @@ import json
|
|
|
4
4
|
from typing import Any
|
|
5
5
|
from typing import Literal
|
|
6
6
|
|
|
7
|
+
from pydantic import AliasChoices
|
|
7
8
|
from pydantic import BaseModel
|
|
8
9
|
from pydantic import ConfigDict
|
|
9
10
|
from pydantic import Field
|
|
@@ -152,6 +153,8 @@ class MessagePayload(_Model):
|
|
|
152
153
|
class Session(_Model):
|
|
153
154
|
id: str
|
|
154
155
|
agent_id: str
|
|
156
|
+
name: str | None = None
|
|
157
|
+
type: str | None = None
|
|
155
158
|
state: str | None = None
|
|
156
159
|
messages: list[MessagePayload] = Field(default_factory=list)
|
|
157
160
|
created_at: str | None = None
|
|
@@ -169,6 +172,11 @@ class SessionResponse(_Model):
|
|
|
169
172
|
queue_position: int | None = None
|
|
170
173
|
|
|
171
174
|
|
|
175
|
+
class SessionListResponse(_Model):
|
|
176
|
+
sessions: list[Session] = Field(default_factory=list)
|
|
177
|
+
next_cursor: str | None = None
|
|
178
|
+
|
|
179
|
+
|
|
172
180
|
class StreamEvent(_Model):
|
|
173
181
|
type: str | None = None
|
|
174
182
|
data: Any = None
|
|
@@ -426,3 +434,66 @@ class McpPromptResponse(_Model):
|
|
|
426
434
|
name: str | None = None
|
|
427
435
|
description: str | None = None
|
|
428
436
|
messages: list[McpPromptMessage] = Field(default_factory=list)
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
# ---------------------------------------------------------------------------
|
|
440
|
+
# Evaluation types
|
|
441
|
+
# ---------------------------------------------------------------------------
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
class EvaluationConfig(_Model):
|
|
445
|
+
agent_id: str
|
|
446
|
+
enabled: bool = False
|
|
447
|
+
is_active: bool = True
|
|
448
|
+
model_name: str | None = None
|
|
449
|
+
frequency: str | None = None
|
|
450
|
+
language: str | None = None
|
|
451
|
+
include_auto_tags: bool = False
|
|
452
|
+
interaction_types: list[Any] = Field(default_factory=list)
|
|
453
|
+
criteria: list[Any] = Field(default_factory=list)
|
|
454
|
+
tags: list[Any] = Field(default_factory=list)
|
|
455
|
+
data_points: list[Any] = Field(default_factory=list)
|
|
456
|
+
sentiment: dict[str, Any] | None = None
|
|
457
|
+
updated_ts: str | None = None
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
class EvaluationConfigResponse(_Model):
|
|
461
|
+
config: EvaluationConfig
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
class EvaluationConfigUpdateRequest(_Model):
|
|
465
|
+
enabled: bool | None = None
|
|
466
|
+
model_name: str | None = None
|
|
467
|
+
frequency: str | None = None
|
|
468
|
+
language: str | None = None
|
|
469
|
+
include_auto_tags: bool | None = None
|
|
470
|
+
interaction_types: list[Any] | None = None
|
|
471
|
+
criteria: list[Any] | None = None
|
|
472
|
+
tags: list[Any] | None = None
|
|
473
|
+
data_points: list[Any] | None = None
|
|
474
|
+
sentiment: dict[str, Any] | None = None
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
class EvaluationResult(_Model):
|
|
478
|
+
evaluation_id: str
|
|
479
|
+
session_id: str = Field(validation_alias=AliasChoices("interaction_id", "session_id"))
|
|
480
|
+
agent_id: str
|
|
481
|
+
created_ts: str | None = None
|
|
482
|
+
# "completed" | "failed"; grade/call_successful are null when failed.
|
|
483
|
+
status: str | None = None
|
|
484
|
+
grade: str | None = None
|
|
485
|
+
call_successful: str | None = None
|
|
486
|
+
sentiment: str | None = None
|
|
487
|
+
summary: str | None = None
|
|
488
|
+
criteria_results: list[Any] = Field(default_factory=list)
|
|
489
|
+
data_results: list[Any] = Field(default_factory=list)
|
|
490
|
+
applied_tags: list[Any] = Field(default_factory=list)
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
class EvaluationResultResponse(_Model):
|
|
494
|
+
evaluation: EvaluationResult | None = None
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
class EvaluationResultListResponse(_Model):
|
|
498
|
+
evaluations: list[EvaluationResult] = Field(default_factory=list)
|
|
499
|
+
next_cursor: str | None = None
|
|
@@ -59,6 +59,33 @@ def test_sessions_create_rejects_both_input_and_input_stdin(cli_runner: CliRunne
|
|
|
59
59
|
assert result.exit_code != 0
|
|
60
60
|
|
|
61
61
|
|
|
62
|
+
@respx.mock
|
|
63
|
+
def test_sessions_list_forwards_filters(cli_runner: CliRunner) -> None:
|
|
64
|
+
route = respx.get(f"{API_BASE}/agents/agent_abc/sessions").mock(
|
|
65
|
+
return_value=httpx.Response(
|
|
66
|
+
200,
|
|
67
|
+
json={
|
|
68
|
+
"sessions": [{"id": "session_xyz", "agent_id": "agent_abc", "state": "completed"}],
|
|
69
|
+
"next_cursor": None,
|
|
70
|
+
},
|
|
71
|
+
)
|
|
72
|
+
)
|
|
73
|
+
save_credentials(Credentials(api_key="key"))
|
|
74
|
+
|
|
75
|
+
result = cli_runner.invoke(
|
|
76
|
+
app,
|
|
77
|
+
["sessions", "list", "agent_abc", "--state", "completed", "--search", "x", "--sort", "oldest", "--limit", "5"],
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
assert result.exit_code == 0, result.output
|
|
81
|
+
assert "session_xyz" in result.output
|
|
82
|
+
params = route.calls[0].request.url.params
|
|
83
|
+
assert params["state"] == "completed"
|
|
84
|
+
assert params["search"] == "x"
|
|
85
|
+
assert params["sort_order"] == "oldest"
|
|
86
|
+
assert params["page_size"] == "5"
|
|
87
|
+
|
|
88
|
+
|
|
62
89
|
@respx.mock
|
|
63
90
|
def test_sessions_get_calls_per_session_endpoint(cli_runner: CliRunner) -> None:
|
|
64
91
|
respx.get(f"{API_BASE}/sessions/session_xyz").mock(
|
|
@@ -100,6 +100,106 @@ def test_models_list(client: Gumloop) -> None:
|
|
|
100
100
|
assert client.models.list().model_groups[0]["id"] == "auto"
|
|
101
101
|
|
|
102
102
|
|
|
103
|
+
@respx.mock
|
|
104
|
+
def test_agents_get_evaluation_config(client: Gumloop) -> None:
|
|
105
|
+
respx.get(f"{API_BASE}/agents/agent_123/evaluation-config").mock(
|
|
106
|
+
return_value=httpx.Response(200, json={"config": {"agent_id": "agent_123", "enabled": False}})
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
result = client.agents.get_evaluation_config("agent_123")
|
|
110
|
+
|
|
111
|
+
assert result.config.agent_id == "agent_123"
|
|
112
|
+
assert result.config.enabled is False
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@respx.mock
|
|
116
|
+
def test_agents_update_evaluation_config_patches_only_sent_fields(client: Gumloop) -> None:
|
|
117
|
+
route = respx.patch(f"{API_BASE}/agents/agent_123/evaluation-config").mock(
|
|
118
|
+
return_value=httpx.Response(200, json={"config": {"agent_id": "agent_123", "enabled": True}})
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
result = client.agents.update_evaluation_config("agent_123", enabled=True)
|
|
122
|
+
|
|
123
|
+
assert result.config.enabled is True
|
|
124
|
+
# PATCH merge: only the field we set goes on the wire — omitted fields aren't
|
|
125
|
+
# cleared client-side (the backend preserves them).
|
|
126
|
+
assert request_json(route.calls[0].request) == {"enabled": True}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@respx.mock
|
|
130
|
+
def test_agents_list_evaluations_sends_filters(client: Gumloop) -> None:
|
|
131
|
+
route = respx.get(f"{API_BASE}/agents/agent_123/evaluations").mock(
|
|
132
|
+
return_value=httpx.Response(
|
|
133
|
+
200,
|
|
134
|
+
json={
|
|
135
|
+
"evaluations": [{"evaluation_id": "eval_1", "interaction_id": "i1", "agent_id": "agent_123"}],
|
|
136
|
+
"next_cursor": "cursor_2",
|
|
137
|
+
},
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
result = client.agents.list_evaluations("agent_123", grade="needs_review", page_size=10, cursor="cursor_1")
|
|
142
|
+
|
|
143
|
+
assert result.evaluations[0].evaluation_id == "eval_1"
|
|
144
|
+
assert result.next_cursor == "cursor_2"
|
|
145
|
+
params = route.calls[0].request.url.params
|
|
146
|
+
assert params["grade"] == "needs_review"
|
|
147
|
+
assert params["page_size"] == "10"
|
|
148
|
+
assert params["cursor"] == "cursor_1"
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
@respx.mock
|
|
152
|
+
def test_agents_get_evaluation(client: Gumloop) -> None:
|
|
153
|
+
respx.get(f"{API_BASE}/agents/agent_123/evaluations/eval_1").mock(
|
|
154
|
+
return_value=httpx.Response(
|
|
155
|
+
200,
|
|
156
|
+
json={
|
|
157
|
+
"evaluation": {
|
|
158
|
+
"evaluation_id": "eval_1",
|
|
159
|
+
"interaction_id": "i1",
|
|
160
|
+
"agent_id": "agent_123",
|
|
161
|
+
"status": "completed",
|
|
162
|
+
"grade": "pass",
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
)
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
result = client.agents.get_evaluation("agent_123", "eval_1")
|
|
169
|
+
|
|
170
|
+
assert result.evaluation is not None
|
|
171
|
+
assert result.evaluation.evaluation_id == "eval_1"
|
|
172
|
+
assert result.evaluation.status == "completed"
|
|
173
|
+
assert result.evaluation.grade == "pass"
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
@respx.mock
|
|
177
|
+
def test_async_agents_evaluation_methods() -> None:
|
|
178
|
+
respx.get(f"{API_BASE}/agents/agent_123/evaluation-config").mock(
|
|
179
|
+
return_value=httpx.Response(200, json={"config": {"agent_id": "agent_123"}})
|
|
180
|
+
)
|
|
181
|
+
respx.patch(f"{API_BASE}/agents/agent_123/evaluation-config").mock(
|
|
182
|
+
return_value=httpx.Response(200, json={"config": {"agent_id": "agent_123", "enabled": True}})
|
|
183
|
+
)
|
|
184
|
+
respx.get(f"{API_BASE}/agents/agent_123/evaluations").mock(
|
|
185
|
+
return_value=httpx.Response(200, json={"evaluations": []})
|
|
186
|
+
)
|
|
187
|
+
respx.get(f"{API_BASE}/agents/agent_123/evaluations/eval_1").mock(
|
|
188
|
+
return_value=httpx.Response(
|
|
189
|
+
200, json={"evaluation": {"evaluation_id": "eval_1", "interaction_id": "i1", "agent_id": "agent_123"}}
|
|
190
|
+
)
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
async def run() -> None:
|
|
194
|
+
async with AsyncGumloop(access_token="token") as client:
|
|
195
|
+
assert (await client.agents.get_evaluation_config("agent_123")).config.agent_id == "agent_123"
|
|
196
|
+
assert (await client.agents.update_evaluation_config("agent_123", enabled=True)).config.enabled is True
|
|
197
|
+
assert (await client.agents.list_evaluations("agent_123")).evaluations == []
|
|
198
|
+
assert (await client.agents.get_evaluation("agent_123", "eval_1")).evaluation.evaluation_id == "eval_1"
|
|
199
|
+
|
|
200
|
+
asyncio.run(run())
|
|
201
|
+
|
|
202
|
+
|
|
103
203
|
@respx.mock
|
|
104
204
|
def test_async_agents_models_and_user_methods() -> None:
|
|
105
205
|
respx.get(f"{API_BASE}/agents").mock(return_value=httpx.Response(200, json={"agents": []}))
|
|
@@ -82,6 +82,44 @@ def test_sessions_retrieve_send_and_cancel_routes(client: Gumloop) -> None:
|
|
|
82
82
|
assert request_json(cancel_route.calls[0].request) == {}
|
|
83
83
|
|
|
84
84
|
|
|
85
|
+
@respx.mock
|
|
86
|
+
def test_sessions_list_forwards_filters_and_returns_envelope(client: Gumloop) -> None:
|
|
87
|
+
route = respx.get(f"{API_BASE}/agents/agent_123/sessions").mock(
|
|
88
|
+
return_value=httpx.Response(
|
|
89
|
+
200,
|
|
90
|
+
json={
|
|
91
|
+
"sessions": [
|
|
92
|
+
{"id": "session_123", "agent_id": "agent_123", "name": "Run", "type": "api", "state": "completed"}
|
|
93
|
+
],
|
|
94
|
+
"next_cursor": "next",
|
|
95
|
+
},
|
|
96
|
+
)
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
result = client.sessions.list(
|
|
100
|
+
"agent_123",
|
|
101
|
+
search="invoice",
|
|
102
|
+
state="completed",
|
|
103
|
+
type="api",
|
|
104
|
+
sort_order="oldest",
|
|
105
|
+
page_size=10,
|
|
106
|
+
cursor="prev",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
assert [s.id for s in result.sessions] == ["session_123"]
|
|
110
|
+
assert result.sessions[0].type == "api"
|
|
111
|
+
assert result.next_cursor == "next"
|
|
112
|
+
params = route.calls[0].request.url.params
|
|
113
|
+
assert params["search"] == "invoice"
|
|
114
|
+
assert params["state"] == "completed"
|
|
115
|
+
assert params["type"] == "api"
|
|
116
|
+
assert params["sort_order"] == "oldest"
|
|
117
|
+
assert params["page_size"] == "10"
|
|
118
|
+
assert params["cursor"] == "prev"
|
|
119
|
+
assert "creator_user_id" not in params
|
|
120
|
+
assert "trigger_id" not in params
|
|
121
|
+
|
|
122
|
+
|
|
85
123
|
def test_sessions_send_requires_input_or_message() -> None:
|
|
86
124
|
client = Gumloop(access_token="token")
|
|
87
125
|
|
|
@@ -163,6 +201,9 @@ def test_async_sessions_methods() -> None:
|
|
|
163
201
|
200, json={"session": {"id": "session_123", "agent_id": "agent_123", "state": "cancelled"}}
|
|
164
202
|
)
|
|
165
203
|
)
|
|
204
|
+
respx.get(f"{API_BASE}/agents/agent_123/sessions").mock(
|
|
205
|
+
return_value=httpx.Response(200, json={"sessions": [{"id": "session_123", "agent_id": "agent_123"}]})
|
|
206
|
+
)
|
|
166
207
|
|
|
167
208
|
async def run() -> None:
|
|
168
209
|
async with AsyncGumloop(access_token="token") as client:
|
|
@@ -170,6 +211,8 @@ def test_async_sessions_methods() -> None:
|
|
|
170
211
|
assert (await client.sessions.retrieve("session_123")).session.id == "session_123"
|
|
171
212
|
assert (await client.sessions.send("session_123", input="Hello")).session.id == "session_123"
|
|
172
213
|
assert (await client.sessions.cancel("session_123")).session.id == "session_123"
|
|
214
|
+
listed = await client.sessions.list("agent_123", state="completed")
|
|
215
|
+
assert [s.id for s in listed.sessions] == ["session_123"]
|
|
173
216
|
|
|
174
217
|
asyncio.run(run())
|
|
175
218
|
|
|
@@ -328,7 +328,7 @@ name = "exceptiongroup"
|
|
|
328
328
|
version = "1.3.1"
|
|
329
329
|
source = { registry = "https://pypi.org/simple" }
|
|
330
330
|
dependencies = [
|
|
331
|
-
{ name = "typing-extensions"
|
|
331
|
+
{ name = "typing-extensions" },
|
|
332
332
|
]
|
|
333
333
|
sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
|
|
334
334
|
wheels = [
|
|
@@ -355,7 +355,7 @@ wheels = [
|
|
|
355
355
|
|
|
356
356
|
[[package]]
|
|
357
357
|
name = "gumloop"
|
|
358
|
-
version = "0.3.
|
|
358
|
+
version = "0.3.2"
|
|
359
359
|
source = { editable = "." }
|
|
360
360
|
dependencies = [
|
|
361
361
|
{ name = "httpx" },
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from collections.abc import Mapping
|
|
4
|
-
from typing import Any
|
|
5
|
-
|
|
6
|
-
from gumloop._http import AsyncHttpClient
|
|
7
|
-
from gumloop._http import HttpClient
|
|
8
|
-
from gumloop.types import AgentCreateRequest
|
|
9
|
-
from gumloop.types import AgentListResponse
|
|
10
|
-
from gumloop.types import AgentResponse
|
|
11
|
-
from gumloop.types import AgentUpdateRequest
|
|
12
|
-
from gumloop.types import ModelListResponse
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class Agents:
|
|
16
|
-
def __init__(self, client: HttpClient) -> None:
|
|
17
|
-
self._client = client
|
|
18
|
-
|
|
19
|
-
def list(
|
|
20
|
-
self,
|
|
21
|
-
*,
|
|
22
|
-
search: str | None = None,
|
|
23
|
-
team_id: str | None = None,
|
|
24
|
-
**kwargs: Any,
|
|
25
|
-
) -> AgentListResponse:
|
|
26
|
-
return AgentListResponse.model_validate(
|
|
27
|
-
self._client.get("agents", params={"search": search, "team_id": team_id, **kwargs})
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
def create(
|
|
31
|
-
self,
|
|
32
|
-
request: AgentCreateRequest | Mapping[str, Any] | None = None,
|
|
33
|
-
**kwargs: Any,
|
|
34
|
-
) -> AgentResponse:
|
|
35
|
-
return AgentResponse.model_validate(
|
|
36
|
-
self._client.post("agents", json=AgentCreateRequest.build(request, **kwargs))
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
def retrieve(self, agent_id: str) -> AgentResponse:
|
|
40
|
-
return AgentResponse.model_validate(self._client.get(f"agents/{agent_id}"))
|
|
41
|
-
|
|
42
|
-
def update(
|
|
43
|
-
self,
|
|
44
|
-
agent_id: str,
|
|
45
|
-
request: AgentUpdateRequest | Mapping[str, Any] | None = None,
|
|
46
|
-
**kwargs: Any,
|
|
47
|
-
) -> AgentResponse:
|
|
48
|
-
return AgentResponse.model_validate(
|
|
49
|
-
self._client.patch(f"agents/{agent_id}", json=AgentUpdateRequest.build(request, **kwargs))
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
class Models:
|
|
54
|
-
def __init__(self, client: HttpClient) -> None:
|
|
55
|
-
self._client = client
|
|
56
|
-
|
|
57
|
-
def list(self, **kwargs: Any) -> ModelListResponse:
|
|
58
|
-
return ModelListResponse.model_validate(self._client.get("models", params=kwargs))
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
class AsyncAgents:
|
|
62
|
-
def __init__(self, client: AsyncHttpClient) -> None:
|
|
63
|
-
self._client = client
|
|
64
|
-
|
|
65
|
-
async def list(
|
|
66
|
-
self,
|
|
67
|
-
*,
|
|
68
|
-
search: str | None = None,
|
|
69
|
-
team_id: str | None = None,
|
|
70
|
-
**kwargs: Any,
|
|
71
|
-
) -> AgentListResponse:
|
|
72
|
-
data = await self._client.get("agents", params={"search": search, "team_id": team_id, **kwargs})
|
|
73
|
-
return AgentListResponse.model_validate(data)
|
|
74
|
-
|
|
75
|
-
async def create(
|
|
76
|
-
self,
|
|
77
|
-
request: AgentCreateRequest | Mapping[str, Any] | None = None,
|
|
78
|
-
**kwargs: Any,
|
|
79
|
-
) -> AgentResponse:
|
|
80
|
-
data = await self._client.post("agents", json=AgentCreateRequest.build(request, **kwargs))
|
|
81
|
-
return AgentResponse.model_validate(data)
|
|
82
|
-
|
|
83
|
-
async def retrieve(self, agent_id: str) -> AgentResponse:
|
|
84
|
-
return AgentResponse.model_validate(await self._client.get(f"agents/{agent_id}"))
|
|
85
|
-
|
|
86
|
-
async def update(
|
|
87
|
-
self,
|
|
88
|
-
agent_id: str,
|
|
89
|
-
request: AgentUpdateRequest | Mapping[str, Any] | None = None,
|
|
90
|
-
**kwargs: Any,
|
|
91
|
-
) -> AgentResponse:
|
|
92
|
-
data = await self._client.patch(f"agents/{agent_id}", json=AgentUpdateRequest.build(request, **kwargs))
|
|
93
|
-
return AgentResponse.model_validate(data)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
class AsyncModels:
|
|
97
|
-
def __init__(self, client: AsyncHttpClient) -> None:
|
|
98
|
-
self._client = client
|
|
99
|
-
|
|
100
|
-
async def list(self, **kwargs: Any) -> ModelListResponse:
|
|
101
|
-
return ModelListResponse.model_validate(await self._client.get("models", params=kwargs))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|