acp-sdk 0.12.3__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.12.3 → acp_sdk-1.0.0}/PKG-INFO +1 -1
- {acp_sdk-0.12.3 → 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.12.3 → acp_sdk-1.0.0}/src/acp_sdk/models/errors.py +5 -1
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/models/models.py +44 -10
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/server/agent.py +18 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/server/app.py +26 -2
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/server/server.py +25 -8
- {acp_sdk-0.12.3 → 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.12.3 → acp_sdk-1.0.0}/tests/unit/client/test_client.py +1 -1
- acp_sdk-0.12.3/tests/e2e/test_suites/test_discovery.py +0 -24
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/.gitignore +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/.python-version +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/README.md +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/docs/.gitignore +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/docs/Makefile +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/docs/conf.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/docs/index.rst +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/docs/make.bat +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/pytest.ini +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/__init__.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/client/__init__.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/client/client.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/client/types.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/client/utils.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/instrumentation.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/models/__init__.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/models/platform.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/models/schemas.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/models/types.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/py.typed +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/server/__init__.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/server/context.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/server/errors.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/server/executor.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/server/logging.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/server/resources.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/server/store/__init__.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/server/store/memory_store.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/server/store/postgresql_store.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/server/store/redis_store.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/server/store/store.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/server/store/utils.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/server/telemetry.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/server/types.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/server/utils.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/shared/__init__.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/shared/resources.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/src/acp_sdk/version.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/tests/conftest.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/tests/e2e/__init__.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/tests/e2e/config.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/tests/e2e/fixtures/__init__.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/tests/e2e/fixtures/client.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/tests/e2e/test_suites/__init__.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/tests/e2e/test_suites/test_runs.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/tests/e2e/test_suites/test_sessions.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/tests/unit/client/test_utils.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/tests/unit/models/__init__.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/tests/unit/models/test_models.py +0 -0
- {acp_sdk-0.12.3 → acp_sdk-1.0.0}/tests/unit/server/__init__.py +0 -0
- {acp_sdk-0.12.3 → 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,38 @@ 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
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class TrajectoryMetadata(BaseModel):
|
|
119
|
+
"""
|
|
120
|
+
Represents trajectory information for an agent's reasoning or tool execution
|
|
121
|
+
steps. This metadata helps track the agent's decision-making process and
|
|
122
|
+
provides transparency into how the agent arrived at its response.
|
|
123
|
+
|
|
124
|
+
TrajectoryMetadata can capture either:
|
|
125
|
+
1. A reasoning step with a message
|
|
126
|
+
2. A tool execution with tool name, input, and output
|
|
127
|
+
|
|
128
|
+
This information can be used for debugging, audit trails, and providing
|
|
129
|
+
users with insight into the agent's thought process.
|
|
130
|
+
|
|
131
|
+
Properties:
|
|
132
|
+
- message: A reasoning step or thought in the agent's decision process.
|
|
133
|
+
- tool_name: Name of the tool that was executed.
|
|
134
|
+
- tool_input: Input parameters passed to the tool.
|
|
135
|
+
- tool_output: Output or result returned by the tool.
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
kind: Literal["trajectory"] = "trajectory"
|
|
139
|
+
message: Optional[str] = None
|
|
140
|
+
tool_name: Optional[str] = None
|
|
141
|
+
tool_input: Optional[AnyModel] = None
|
|
142
|
+
tool_output: Optional[AnyModel] = None
|
|
119
143
|
|
|
120
144
|
|
|
121
145
|
class MessagePart(BaseModel):
|
|
@@ -127,7 +151,7 @@ class MessagePart(BaseModel):
|
|
|
127
151
|
|
|
128
152
|
model_config = ConfigDict(extra="allow")
|
|
129
153
|
|
|
130
|
-
metadata: Optional[CitationMetadata] = Field(discriminator="kind", default=None)
|
|
154
|
+
metadata: Optional[CitationMetadata | TrajectoryMetadata] = Field(discriminator="kind", default=None)
|
|
131
155
|
|
|
132
156
|
def model_post_init(self, __context: Any) -> None:
|
|
133
157
|
if self.content is not None and self.content_url is not None:
|
|
@@ -326,10 +350,20 @@ Event = Union[
|
|
|
326
350
|
]
|
|
327
351
|
|
|
328
352
|
|
|
353
|
+
class InputContentTypes(BaseModel):
|
|
354
|
+
types: list[str]
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
class OutputContentTypes(BaseModel):
|
|
358
|
+
types: list[str]
|
|
359
|
+
|
|
360
|
+
|
|
329
361
|
class AgentManifest(BaseModel):
|
|
330
362
|
name: str
|
|
331
363
|
description: str | None = None
|
|
332
364
|
metadata: Metadata = Metadata()
|
|
365
|
+
input_content_types: list[str] = Field(default_factory=lambda: ["*/*"])
|
|
366
|
+
output_content_types: list[str] = Field(default_factory=lambda: ["*/*"])
|
|
333
367
|
|
|
334
368
|
|
|
335
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,
|
|
@@ -331,14 +348,14 @@ class Server:
|
|
|
331
348
|
request_data = {
|
|
332
349
|
"location": f"http://{host}:{self.server.config.port}",
|
|
333
350
|
}
|
|
334
|
-
await async_request_with_retry(lambda client, data=request_data: client.get(f"{url}/api/v1/providers"))
|
|
335
351
|
try:
|
|
352
|
+
await async_request_with_retry(lambda client, data=request_data: client.get(f"{url}/api/v1/providers"))
|
|
336
353
|
await async_request_with_retry(
|
|
337
354
|
lambda client, data=request_data: client.post(
|
|
338
355
|
f"{url}/api/v1/providers", json=data, params={"auto_remove": True}
|
|
339
356
|
)
|
|
340
357
|
)
|
|
341
|
-
logger.
|
|
358
|
+
logger.debug("Agent registered to the beeai server.")
|
|
342
359
|
|
|
343
360
|
# check missing env keyes
|
|
344
361
|
envs_request = await async_request_with_retry(lambda client: client.get(f"{url}/api/v1/variables"))
|
|
@@ -361,17 +378,17 @@ class Server:
|
|
|
361
378
|
elif env.get("required"):
|
|
362
379
|
missing_keyes.append(env)
|
|
363
380
|
if len(missing_keyes):
|
|
364
|
-
logger.
|
|
381
|
+
logger.debug(f"Can not run agent, missing required env variables: {missing_keyes}")
|
|
365
382
|
raise Exception("Missing env variables")
|
|
366
383
|
|
|
367
384
|
except requests.exceptions.ConnectionError as e:
|
|
368
|
-
logger.
|
|
385
|
+
logger.debug(f"Can not reach server, check if running on {url} : {e}")
|
|
369
386
|
except (requests.exceptions.HTTPError, Exception) as e:
|
|
370
387
|
try:
|
|
371
388
|
error_message = e.response.json().get("detail")
|
|
372
389
|
if error_message:
|
|
373
|
-
logger.
|
|
390
|
+
logger.debug(f"Agent can not be registered to beeai server: {error_message}")
|
|
374
391
|
else:
|
|
375
|
-
logger.
|
|
392
|
+
logger.debug(f"Agent can not be registered to beeai server: {e}")
|
|
376
393
|
except Exception:
|
|
377
|
-
logger.
|
|
394
|
+
logger.debug(f"Agent can not be registered to beeai server: {e}")
|
|
@@ -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
|