acp-sdk 0.13.0__tar.gz → 1.0.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.
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/PKG-INFO +1 -1
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/pyproject.toml +1 -1
- acp_sdk-1.0.0/src/acp_sdk/models/common.py +5 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/models/errors.py +5 -1
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/models/models.py +16 -9
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/server/agent.py +18 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/server/app.py +26 -2
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/server/server.py +18 -1
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/tests/e2e/fixtures/server.py +4 -1
- acp_sdk-1.0.0/tests/e2e/test_suites/test_discovery.py +42 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/tests/unit/client/test_client.py +1 -1
- acp_sdk-0.13.0/tests/e2e/test_suites/test_discovery.py +0 -24
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/.gitignore +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/.python-version +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/README.md +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/docs/.gitignore +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/docs/Makefile +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/docs/conf.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/docs/index.rst +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/docs/make.bat +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/pytest.ini +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/__init__.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/client/__init__.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/client/client.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/client/types.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/client/utils.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/instrumentation.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/models/__init__.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/models/platform.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/models/schemas.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/models/types.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/py.typed +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/server/__init__.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/server/context.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/server/errors.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/server/executor.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/server/logging.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/server/resources.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/server/store/__init__.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/server/store/memory_store.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/server/store/postgresql_store.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/server/store/redis_store.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/server/store/store.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/server/store/utils.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/server/telemetry.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/server/types.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/server/utils.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/shared/__init__.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/shared/resources.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/src/acp_sdk/version.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/tests/conftest.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/tests/e2e/__init__.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/tests/e2e/config.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/tests/e2e/fixtures/__init__.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/tests/e2e/fixtures/client.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/tests/e2e/test_suites/__init__.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/tests/e2e/test_suites/test_runs.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/tests/e2e/test_suites/test_sessions.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/tests/unit/client/test_utils.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/tests/unit/models/__init__.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/tests/unit/models/test_models.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/tests/unit/server/__init__.py +0 -0
- {acp_sdk-0.13.0 → acp_sdk-1.0.0}/tests/unit/server/test_server.py +0 -0
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
|
+
from typing import Optional
|
|
2
3
|
|
|
3
4
|
from pydantic import BaseModel
|
|
4
5
|
|
|
6
|
+
from acp_sdk.models.common import AnyModel
|
|
7
|
+
|
|
5
8
|
|
|
6
9
|
class ErrorCode(str, Enum):
|
|
7
10
|
SERVER_ERROR = "server_error"
|
|
@@ -10,8 +13,9 @@ class ErrorCode(str, Enum):
|
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
class Error(BaseModel):
|
|
13
|
-
code: ErrorCode
|
|
16
|
+
code: ErrorCode | str # Allow arbitrary string for backwards compatibility
|
|
14
17
|
message: str
|
|
18
|
+
data: Optional[AnyModel] = None
|
|
15
19
|
|
|
16
20
|
|
|
17
21
|
class ACPError(Exception):
|
|
@@ -8,16 +8,13 @@ from typing import Any, Literal, Optional, Union
|
|
|
8
8
|
from pydantic import AnyUrl, BaseModel, ConfigDict, Field
|
|
9
9
|
from pydantic.json_schema import SkipJsonSchema
|
|
10
10
|
|
|
11
|
+
from acp_sdk.models.common import AnyModel
|
|
11
12
|
from acp_sdk.models.errors import ACPError, Error
|
|
12
13
|
from acp_sdk.models.platform import PlatformUIAnnotation
|
|
13
14
|
from acp_sdk.models.types import AgentName, ResourceUrl, RunId, SessionId
|
|
14
15
|
from acp_sdk.shared import ResourceLoader, ResourceStore
|
|
15
16
|
|
|
16
17
|
|
|
17
|
-
class AnyModel(BaseModel):
|
|
18
|
-
model_config = ConfigDict(extra="allow")
|
|
19
|
-
|
|
20
|
-
|
|
21
18
|
class Author(BaseModel):
|
|
22
19
|
name: str
|
|
23
20
|
email: str | None = None
|
|
@@ -111,11 +108,11 @@ class CitationMetadata(BaseModel):
|
|
|
111
108
|
"""
|
|
112
109
|
|
|
113
110
|
kind: Literal["citation"] = "citation"
|
|
114
|
-
start_index: Optional[int]
|
|
115
|
-
end_index: Optional[int]
|
|
116
|
-
url: Optional[str]
|
|
117
|
-
title: Optional[str]
|
|
118
|
-
description: Optional[str]
|
|
111
|
+
start_index: Optional[int] = None
|
|
112
|
+
end_index: Optional[int] = None
|
|
113
|
+
url: Optional[str] = None
|
|
114
|
+
title: Optional[str] = None
|
|
115
|
+
description: Optional[str] = None
|
|
119
116
|
|
|
120
117
|
|
|
121
118
|
class TrajectoryMetadata(BaseModel):
|
|
@@ -353,10 +350,20 @@ Event = Union[
|
|
|
353
350
|
]
|
|
354
351
|
|
|
355
352
|
|
|
353
|
+
class InputContentTypes(BaseModel):
|
|
354
|
+
types: list[str]
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
class OutputContentTypes(BaseModel):
|
|
358
|
+
types: list[str]
|
|
359
|
+
|
|
360
|
+
|
|
356
361
|
class AgentManifest(BaseModel):
|
|
357
362
|
name: str
|
|
358
363
|
description: str | None = None
|
|
359
364
|
metadata: Metadata = Metadata()
|
|
365
|
+
input_content_types: list[str] = Field(default_factory=lambda: ["*/*"])
|
|
366
|
+
output_content_types: list[str] = Field(default_factory=lambda: ["*/*"])
|
|
360
367
|
|
|
361
368
|
|
|
362
369
|
class Session(BaseModel):
|
|
@@ -17,6 +17,14 @@ class AgentManifest(abc.ABC):
|
|
|
17
17
|
def description(self) -> str:
|
|
18
18
|
return ""
|
|
19
19
|
|
|
20
|
+
@property
|
|
21
|
+
def input_content_types(self) -> list[str]:
|
|
22
|
+
return []
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def output_content_types(self) -> list[str]:
|
|
26
|
+
return []
|
|
27
|
+
|
|
20
28
|
@property
|
|
21
29
|
def metadata(self) -> Metadata:
|
|
22
30
|
return Metadata()
|
|
@@ -38,6 +46,8 @@ def agent(
|
|
|
38
46
|
description: str | None = None,
|
|
39
47
|
*,
|
|
40
48
|
metadata: Metadata | None = None,
|
|
49
|
+
input_content_types: list[str] | None = None,
|
|
50
|
+
output_content_types: list[str] | None = None,
|
|
41
51
|
) -> Callable[[Callable], AgentManifest]:
|
|
42
52
|
"""Decorator to create an agent."""
|
|
43
53
|
|
|
@@ -67,6 +77,14 @@ def agent(
|
|
|
67
77
|
def metadata(self) -> Metadata:
|
|
68
78
|
return metadata or Metadata()
|
|
69
79
|
|
|
80
|
+
@property
|
|
81
|
+
def input_content_types(self) -> list[str]:
|
|
82
|
+
return input_content_types or ["*/*"]
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def output_content_types(self) -> list[str]:
|
|
86
|
+
return output_content_types or ["*/*"]
|
|
87
|
+
|
|
70
88
|
agent: AgentManifest
|
|
71
89
|
if inspect.isasyncgenfunction(fn):
|
|
72
90
|
|
|
@@ -13,6 +13,7 @@ from fastapi.encoders import jsonable_encoder
|
|
|
13
13
|
from fastapi.middleware.cors import CORSMiddleware
|
|
14
14
|
from fastapi.responses import JSONResponse, StreamingResponse
|
|
15
15
|
from obstore.exceptions import NotFoundError
|
|
16
|
+
from pydantic import AnyHttpUrl, ValidationError
|
|
16
17
|
|
|
17
18
|
from acp_sdk.models import (
|
|
18
19
|
ACPError,
|
|
@@ -67,6 +68,7 @@ def create_app(
|
|
|
67
68
|
resource_store: ResourceStore | None = None,
|
|
68
69
|
resource_loader: ResourceLoader | None = None,
|
|
69
70
|
forward_resources: bool = True,
|
|
71
|
+
forward_base_url: AnyHttpUrl | str | None = None,
|
|
70
72
|
lifespan: Lifespan[AppType] | None = None,
|
|
71
73
|
dependencies: list[Depends] | None = None,
|
|
72
74
|
) -> FastAPI:
|
|
@@ -76,6 +78,12 @@ def create_app(
|
|
|
76
78
|
):
|
|
77
79
|
raise ValueError("Resource forwarding must be enabled when resource store does not support HTTP URLs")
|
|
78
80
|
|
|
81
|
+
if isinstance(forward_base_url, str):
|
|
82
|
+
try:
|
|
83
|
+
forward_base_url = AnyHttpUrl(forward_base_url)
|
|
84
|
+
except ValidationError:
|
|
85
|
+
raise ValueError("forward_base_url must be a valid http(s) url")
|
|
86
|
+
|
|
79
87
|
executor: ThreadPoolExecutor
|
|
80
88
|
client = httpx.AsyncClient()
|
|
81
89
|
|
|
@@ -141,7 +149,13 @@ def create_app(
|
|
|
141
149
|
async def list_agents() -> AgentsListResponse:
|
|
142
150
|
return AgentsListResponse(
|
|
143
151
|
agents=[
|
|
144
|
-
AgentModel(
|
|
152
|
+
AgentModel(
|
|
153
|
+
name=agent.name,
|
|
154
|
+
description=agent.description,
|
|
155
|
+
metadata=agent.metadata,
|
|
156
|
+
input_content_types=agent.input_content_types,
|
|
157
|
+
output_content_types=agent.output_content_types,
|
|
158
|
+
)
|
|
145
159
|
for agent in agents.values()
|
|
146
160
|
]
|
|
147
161
|
)
|
|
@@ -149,7 +163,13 @@ def create_app(
|
|
|
149
163
|
@app.get("/agents/{name}")
|
|
150
164
|
async def read_agent(name: AgentName) -> AgentReadResponse:
|
|
151
165
|
agent = find_agent(name)
|
|
152
|
-
return AgentModel(
|
|
166
|
+
return AgentModel(
|
|
167
|
+
name=agent.name,
|
|
168
|
+
description=agent.description,
|
|
169
|
+
metadata=agent.metadata,
|
|
170
|
+
input_content_types=agent.input_content_types,
|
|
171
|
+
output_content_types=agent.output_content_types,
|
|
172
|
+
)
|
|
153
173
|
|
|
154
174
|
@app.get("/ping")
|
|
155
175
|
async def ping() -> PingResponse:
|
|
@@ -165,6 +185,10 @@ def create_app(
|
|
|
165
185
|
def create_resource_url_forwarded(id: ResourceId) -> ResourceUrl:
|
|
166
186
|
if not forward_resources:
|
|
167
187
|
raise RuntimeError("Resource forwarding disabled")
|
|
188
|
+
if forward_base_url:
|
|
189
|
+
return ResourceUrl(
|
|
190
|
+
url=str(app.url_path_for("get_resource", resource_id=id).make_absolute_url(str(forward_base_url)))
|
|
191
|
+
)
|
|
168
192
|
return ResourceUrl(url=str(req.url_for("get_resource", resource_id=id)))
|
|
169
193
|
|
|
170
194
|
async def create_resource_url(id: ResourceId) -> ResourceUrl:
|
|
@@ -9,6 +9,7 @@ import requests
|
|
|
9
9
|
import uvicorn
|
|
10
10
|
import uvicorn.config
|
|
11
11
|
from fastapi import FastAPI
|
|
12
|
+
from pydantic import AnyHttpUrl
|
|
12
13
|
|
|
13
14
|
from acp_sdk.models import Metadata
|
|
14
15
|
from acp_sdk.server.agent import AgentManifest
|
|
@@ -31,13 +32,21 @@ class Server:
|
|
|
31
32
|
self,
|
|
32
33
|
name: str | None = None,
|
|
33
34
|
description: str | None = None,
|
|
35
|
+
input_content_types: list[str] | None = None,
|
|
36
|
+
output_content_types: list[str] | None = None,
|
|
34
37
|
*,
|
|
35
38
|
metadata: Metadata | None = None,
|
|
36
39
|
) -> Callable:
|
|
37
40
|
"""Decorator to register an agent."""
|
|
38
41
|
|
|
39
42
|
def decorator(fn: Callable) -> Callable:
|
|
40
|
-
agent = agent_decorator(
|
|
43
|
+
agent = agent_decorator(
|
|
44
|
+
name=name,
|
|
45
|
+
description=description,
|
|
46
|
+
metadata=metadata,
|
|
47
|
+
input_content_types=input_content_types,
|
|
48
|
+
output_content_types=output_content_types,
|
|
49
|
+
)(fn)
|
|
41
50
|
self.register(agent)
|
|
42
51
|
return fn
|
|
43
52
|
|
|
@@ -59,6 +68,8 @@ class Server:
|
|
|
59
68
|
store: Store | None = None,
|
|
60
69
|
resource_store: ResourceStore | None = None,
|
|
61
70
|
resource_loader: ResourceLoader | None = None,
|
|
71
|
+
forward_resources: bool = True,
|
|
72
|
+
forward_base_url: AnyHttpUrl | str | None = None,
|
|
62
73
|
host: str = "127.0.0.1",
|
|
63
74
|
port: int = 8000,
|
|
64
75
|
uds: str | None = None,
|
|
@@ -127,6 +138,8 @@ class Server:
|
|
|
127
138
|
store=store,
|
|
128
139
|
resource_loader=resource_loader,
|
|
129
140
|
resource_store=resource_store,
|
|
141
|
+
forward_resources=forward_resources,
|
|
142
|
+
forward_base_url=forward_base_url,
|
|
130
143
|
)
|
|
131
144
|
|
|
132
145
|
if configure_logger:
|
|
@@ -196,6 +209,8 @@ class Server:
|
|
|
196
209
|
store: Store | None = None,
|
|
197
210
|
resource_store: ResourceStore | None = None,
|
|
198
211
|
resource_loader: ResourceLoader | None = None,
|
|
212
|
+
forward_resources: bool = True,
|
|
213
|
+
forward_base_url: AnyHttpUrl | str | None = None,
|
|
199
214
|
host: str = "127.0.0.1",
|
|
200
215
|
port: int = 8000,
|
|
201
216
|
uds: str | None = None,
|
|
@@ -256,6 +271,8 @@ class Server:
|
|
|
256
271
|
store=store,
|
|
257
272
|
resource_store=resource_store,
|
|
258
273
|
resource_loader=resource_loader,
|
|
274
|
+
forward_resources=forward_resources,
|
|
275
|
+
forward_base_url=forward_base_url,
|
|
259
276
|
host=host,
|
|
260
277
|
port=port,
|
|
261
278
|
uds=uds,
|
|
@@ -112,7 +112,10 @@ def server(request: pytest.FixtureRequest, store: Store) -> Generator[None]:
|
|
|
112
112
|
|
|
113
113
|
yield MessagePart(content=str(context.session.id), content_type="text/plain")
|
|
114
114
|
|
|
115
|
-
@server.agent(
|
|
115
|
+
@server.agent(
|
|
116
|
+
input_content_types=["text/plain", "application/json"],
|
|
117
|
+
output_content_types=["text/html", "application/json", "application/javascript", "text/css"],
|
|
118
|
+
)
|
|
116
119
|
async def mime_types(input: list[Message], context: Context) -> AsyncIterator[Message]:
|
|
117
120
|
yield MessagePart(content="<h1>HTML Content</h1>", content_type="text/html")
|
|
118
121
|
yield MessagePart(content='{"key": "value"}', content_type="application/json")
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from acp_sdk.client import Client
|
|
3
|
+
from acp_sdk.models import AgentManifest
|
|
4
|
+
from acp_sdk.server import Server
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@pytest.mark.asyncio
|
|
8
|
+
async def test_ping(server: Server, client: Client) -> None:
|
|
9
|
+
await client.ping()
|
|
10
|
+
assert True
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.mark.asyncio
|
|
14
|
+
async def test_agents_list(server: Server, client: Client) -> None:
|
|
15
|
+
async for agent in client.agents():
|
|
16
|
+
assert isinstance(agent, AgentManifest)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@pytest.mark.asyncio
|
|
20
|
+
async def test_agents_manifest(server: Server, client: Client) -> None:
|
|
21
|
+
agent_name = "echo"
|
|
22
|
+
agent = await client.agent(name=agent_name)
|
|
23
|
+
assert isinstance(agent, AgentManifest)
|
|
24
|
+
assert agent.name == agent_name
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@pytest.mark.asyncio
|
|
28
|
+
async def test_input_content_types(server: Server, client: Client) -> None:
|
|
29
|
+
agent_name = "mime_types"
|
|
30
|
+
agent = await client.agent(name=agent_name)
|
|
31
|
+
assert isinstance(agent, AgentManifest)
|
|
32
|
+
assert agent.name == agent_name
|
|
33
|
+
assert agent.input_content_types == ["text/plain", "application/json"]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@pytest.mark.asyncio
|
|
37
|
+
async def test_output_content_types(server: Server, client: Client) -> None:
|
|
38
|
+
agent_name = "mime_types"
|
|
39
|
+
agent = await client.agent(name=agent_name)
|
|
40
|
+
assert isinstance(agent, AgentManifest)
|
|
41
|
+
assert agent.name == agent_name
|
|
42
|
+
assert agent.output_content_types == ["text/html", "application/json", "application/javascript", "text/css"]
|
|
@@ -19,7 +19,7 @@ from acp_sdk.models import (
|
|
|
19
19
|
)
|
|
20
20
|
from pytest_httpx import HTTPXMock
|
|
21
21
|
|
|
22
|
-
mock_agent = AgentManifest(name="mock")
|
|
22
|
+
mock_agent = AgentManifest(name="mock", input_content_types=[], output_content_types=[])
|
|
23
23
|
mock_agents = [mock_agent]
|
|
24
24
|
mock_session = Session()
|
|
25
25
|
mock_run = Run(
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
from acp_sdk.client import Client
|
|
3
|
-
from acp_sdk.models import AgentManifest
|
|
4
|
-
from acp_sdk.server import Server
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
@pytest.mark.asyncio
|
|
8
|
-
async def test_ping(server: Server, client: Client) -> None:
|
|
9
|
-
await client.ping()
|
|
10
|
-
assert True
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@pytest.mark.asyncio
|
|
14
|
-
async def test_agents_list(server: Server, client: Client) -> None:
|
|
15
|
-
async for agent in client.agents():
|
|
16
|
-
assert isinstance(agent, AgentManifest)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
@pytest.mark.asyncio
|
|
20
|
-
async def test_agents_manifest(server: Server, client: Client) -> None:
|
|
21
|
-
agent_name = "echo"
|
|
22
|
-
agent = await client.agent(name=agent_name)
|
|
23
|
-
assert isinstance(agent, AgentManifest)
|
|
24
|
-
assert agent.name == agent_name
|
|
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
|