acp-sdk 0.0.5__tar.gz → 0.1.0rc5__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.0.5 → acp_sdk-0.1.0rc5}/.gitignore +39 -3
- acp_sdk-0.1.0rc5/.python-version +1 -0
- acp_sdk-0.1.0rc5/PKG-INFO +78 -0
- acp_sdk-0.1.0rc5/README.md +59 -0
- acp_sdk-0.1.0rc5/examples/clients/advanced.py +21 -0
- acp_sdk-0.1.0rc5/examples/clients/simple.py +17 -0
- acp_sdk-0.1.0rc5/examples/clients/stream.py +14 -0
- acp_sdk-0.1.0rc5/examples/servers/awaiting.py +23 -0
- acp_sdk-0.1.0rc5/examples/servers/echo.py +22 -0
- acp_sdk-0.1.0rc5/examples/servers/multi-echo.py +59 -0
- acp_sdk-0.1.0rc5/pyproject.toml +38 -0
- acp_sdk-0.1.0rc5/src/acp_sdk/__init__.py +1 -0
- acp_sdk-0.1.0rc5/src/acp_sdk/client/__init__.py +1 -0
- acp_sdk-0.1.0rc5/src/acp_sdk/client/client.py +139 -0
- acp_sdk-0.1.0rc5/src/acp_sdk/models/__init__.py +3 -0
- acp_sdk-0.1.0rc5/src/acp_sdk/models/errors.py +23 -0
- acp_sdk-0.1.0rc5/src/acp_sdk/models/models.py +181 -0
- acp_sdk-0.1.0rc5/src/acp_sdk/models/schemas.py +39 -0
- acp_sdk-0.1.0rc5/src/acp_sdk/server/__init__.py +6 -0
- acp_sdk-0.1.0rc5/src/acp_sdk/server/agent.py +105 -0
- acp_sdk-0.1.0rc5/src/acp_sdk/server/app.py +161 -0
- acp_sdk-0.1.0rc5/src/acp_sdk/server/bundle.py +131 -0
- acp_sdk-0.1.0rc5/src/acp_sdk/server/context.py +33 -0
- acp_sdk-0.1.0rc5/src/acp_sdk/server/errors.py +54 -0
- acp_sdk-0.1.0rc5/src/acp_sdk/server/logging.py +16 -0
- acp_sdk-0.1.0rc5/src/acp_sdk/server/server.py +120 -0
- acp_sdk-0.1.0rc5/src/acp_sdk/server/telemetry.py +52 -0
- acp_sdk-0.1.0rc5/src/acp_sdk/server/types.py +6 -0
- acp_sdk-0.1.0rc5/src/acp_sdk/server/utils.py +14 -0
- acp_sdk-0.0.5/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
- acp_sdk-0.0.5/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- acp_sdk-0.0.5/.github/workflows/check-lock.yml +0 -25
- acp_sdk-0.0.5/.github/workflows/main-checks.yml +0 -13
- acp_sdk-0.0.5/.github/workflows/publish-pypi.yml +0 -55
- acp_sdk-0.0.5/.github/workflows/pull-request-checks.yml +0 -8
- acp_sdk-0.0.5/.github/workflows/shared.yml +0 -69
- acp_sdk-0.0.5/.pre-commit-config.yaml +0 -24
- acp_sdk-0.0.5/CLAUDE.md +0 -114
- acp_sdk-0.0.5/CODE_OF_CONDUCT.md +0 -128
- acp_sdk-0.0.5/CONTRIBUTING.md +0 -66
- acp_sdk-0.0.5/LICENSE +0 -22
- acp_sdk-0.0.5/PKG-INFO +0 -46
- acp_sdk-0.0.5/README.md +0 -9
- acp_sdk-0.0.5/RELEASE.md +0 -15
- acp_sdk-0.0.5/SECURITY.md +0 -14
- acp_sdk-0.0.5/examples/README.md +0 -5
- acp_sdk-0.0.5/examples/clients/simple-chatbot/.python-version +0 -1
- acp_sdk-0.0.5/examples/clients/simple-chatbot/README.MD +0 -110
- acp_sdk-0.0.5/examples/clients/simple-chatbot/mcp_simple_chatbot/.env.example +0 -1
- acp_sdk-0.0.5/examples/clients/simple-chatbot/mcp_simple_chatbot/main.py +0 -429
- acp_sdk-0.0.5/examples/clients/simple-chatbot/mcp_simple_chatbot/requirements.txt +0 -4
- acp_sdk-0.0.5/examples/clients/simple-chatbot/mcp_simple_chatbot/servers_config.json +0 -12
- acp_sdk-0.0.5/examples/clients/simple-chatbot/mcp_simple_chatbot/test.db +0 -0
- acp_sdk-0.0.5/examples/clients/simple-chatbot/pyproject.toml +0 -48
- acp_sdk-0.0.5/examples/clients/simple-chatbot/uv.lock +0 -555
- acp_sdk-0.0.5/examples/highlevel/agents.py +0 -26
- acp_sdk-0.0.5/examples/highlevel/complex_inputs.py +0 -30
- acp_sdk-0.0.5/examples/highlevel/desktop.py +0 -25
- acp_sdk-0.0.5/examples/highlevel/echo.py +0 -30
- acp_sdk-0.0.5/examples/highlevel/memory.py +0 -349
- acp_sdk-0.0.5/examples/highlevel/parameter_descriptions.py +0 -21
- acp_sdk-0.0.5/examples/highlevel/readme-quickstart.py +0 -18
- acp_sdk-0.0.5/examples/highlevel/screenshot.py +0 -29
- acp_sdk-0.0.5/examples/highlevel/simple_echo.py +0 -14
- acp_sdk-0.0.5/examples/highlevel/text_me.py +0 -72
- acp_sdk-0.0.5/examples/highlevel/unicode_example.py +0 -64
- acp_sdk-0.0.5/examples/servers/simple-prompt/.python-version +0 -1
- acp_sdk-0.0.5/examples/servers/simple-prompt/README.md +0 -55
- acp_sdk-0.0.5/examples/servers/simple-prompt/mcp_simple_prompt/__init__.py +0 -1
- acp_sdk-0.0.5/examples/servers/simple-prompt/mcp_simple_prompt/__main__.py +0 -5
- acp_sdk-0.0.5/examples/servers/simple-prompt/mcp_simple_prompt/server.py +0 -127
- acp_sdk-0.0.5/examples/servers/simple-prompt/pyproject.toml +0 -47
- acp_sdk-0.0.5/examples/servers/simple-resource/.python-version +0 -1
- acp_sdk-0.0.5/examples/servers/simple-resource/README.md +0 -48
- acp_sdk-0.0.5/examples/servers/simple-resource/mcp_simple_resource/__init__.py +0 -1
- acp_sdk-0.0.5/examples/servers/simple-resource/mcp_simple_resource/__main__.py +0 -5
- acp_sdk-0.0.5/examples/servers/simple-resource/mcp_simple_resource/server.py +0 -84
- acp_sdk-0.0.5/examples/servers/simple-resource/pyproject.toml +0 -47
- acp_sdk-0.0.5/examples/servers/simple-tool/.python-version +0 -1
- acp_sdk-0.0.5/examples/servers/simple-tool/README.md +0 -48
- acp_sdk-0.0.5/examples/servers/simple-tool/mcp_simple_tool/__init__.py +0 -1
- acp_sdk-0.0.5/examples/servers/simple-tool/mcp_simple_tool/__main__.py +0 -5
- acp_sdk-0.0.5/examples/servers/simple-tool/mcp_simple_tool/server.py +0 -97
- acp_sdk-0.0.5/examples/servers/simple-tool/pyproject.toml +0 -47
- acp_sdk-0.0.5/pyproject.toml +0 -76
- acp_sdk-0.0.5/src/acp/__init__.py +0 -138
- acp_sdk-0.0.5/src/acp/cli/__init__.py +0 -6
- acp_sdk-0.0.5/src/acp/cli/claude.py +0 -139
- acp_sdk-0.0.5/src/acp/cli/cli.py +0 -471
- acp_sdk-0.0.5/src/acp/client/__init__.py +0 -0
- acp_sdk-0.0.5/src/acp/client/__main__.py +0 -79
- acp_sdk-0.0.5/src/acp/client/session.py +0 -372
- acp_sdk-0.0.5/src/acp/client/sse.py +0 -142
- acp_sdk-0.0.5/src/acp/client/stdio.py +0 -153
- acp_sdk-0.0.5/src/acp/server/__init__.py +0 -3
- acp_sdk-0.0.5/src/acp/server/__main__.py +0 -50
- acp_sdk-0.0.5/src/acp/server/highlevel/__init__.py +0 -9
- acp_sdk-0.0.5/src/acp/server/highlevel/agents/__init__.py +0 -5
- acp_sdk-0.0.5/src/acp/server/highlevel/agents/agent_manager.py +0 -110
- acp_sdk-0.0.5/src/acp/server/highlevel/agents/base.py +0 -20
- acp_sdk-0.0.5/src/acp/server/highlevel/agents/templates.py +0 -21
- acp_sdk-0.0.5/src/acp/server/highlevel/context.py +0 -185
- acp_sdk-0.0.5/src/acp/server/highlevel/exceptions.py +0 -25
- acp_sdk-0.0.5/src/acp/server/highlevel/prompts/__init__.py +0 -4
- acp_sdk-0.0.5/src/acp/server/highlevel/prompts/base.py +0 -167
- acp_sdk-0.0.5/src/acp/server/highlevel/prompts/manager.py +0 -50
- acp_sdk-0.0.5/src/acp/server/highlevel/prompts/prompt_manager.py +0 -33
- acp_sdk-0.0.5/src/acp/server/highlevel/resources/__init__.py +0 -23
- acp_sdk-0.0.5/src/acp/server/highlevel/resources/base.py +0 -48
- acp_sdk-0.0.5/src/acp/server/highlevel/resources/resource_manager.py +0 -94
- acp_sdk-0.0.5/src/acp/server/highlevel/resources/templates.py +0 -80
- acp_sdk-0.0.5/src/acp/server/highlevel/resources/types.py +0 -185
- acp_sdk-0.0.5/src/acp/server/highlevel/server.py +0 -705
- acp_sdk-0.0.5/src/acp/server/highlevel/tools/__init__.py +0 -4
- acp_sdk-0.0.5/src/acp/server/highlevel/tools/base.py +0 -83
- acp_sdk-0.0.5/src/acp/server/highlevel/tools/tool_manager.py +0 -53
- acp_sdk-0.0.5/src/acp/server/highlevel/utilities/__init__.py +0 -1
- acp_sdk-0.0.5/src/acp/server/highlevel/utilities/func_metadata.py +0 -210
- acp_sdk-0.0.5/src/acp/server/highlevel/utilities/logging.py +0 -43
- acp_sdk-0.0.5/src/acp/server/highlevel/utilities/types.py +0 -54
- acp_sdk-0.0.5/src/acp/server/lowlevel/__init__.py +0 -3
- acp_sdk-0.0.5/src/acp/server/lowlevel/helper_types.py +0 -9
- acp_sdk-0.0.5/src/acp/server/lowlevel/server.py +0 -643
- acp_sdk-0.0.5/src/acp/server/models.py +0 -17
- acp_sdk-0.0.5/src/acp/server/session.py +0 -315
- acp_sdk-0.0.5/src/acp/server/sse.py +0 -175
- acp_sdk-0.0.5/src/acp/server/stdio.py +0 -83
- acp_sdk-0.0.5/src/acp/server/websocket.py +0 -61
- acp_sdk-0.0.5/src/acp/shared/__init__.py +0 -0
- acp_sdk-0.0.5/src/acp/shared/context.py +0 -14
- acp_sdk-0.0.5/src/acp/shared/exceptions.py +0 -14
- acp_sdk-0.0.5/src/acp/shared/memory.py +0 -87
- acp_sdk-0.0.5/src/acp/shared/progress.py +0 -40
- acp_sdk-0.0.5/src/acp/shared/session.py +0 -413
- acp_sdk-0.0.5/src/acp/shared/version.py +0 -3
- acp_sdk-0.0.5/src/acp/types.py +0 -1258
- acp_sdk-0.0.5/tasks.toml +0 -67
- acp_sdk-0.0.5/tests/__init__.py +0 -0
- acp_sdk-0.0.5/tests/client/__init__.py +0 -0
- acp_sdk-0.0.5/tests/client/test_config.py +0 -52
- acp_sdk-0.0.5/tests/client/test_session.py +0 -100
- acp_sdk-0.0.5/tests/client/test_stdio.py +0 -38
- acp_sdk-0.0.5/tests/conftest.py +0 -6
- acp_sdk-0.0.5/tests/issues/test_100_tool_listing.py +0 -35
- acp_sdk-0.0.5/tests/issues/test_129_resource_templates.py +0 -44
- acp_sdk-0.0.5/tests/issues/test_141_resource_templates.py +0 -118
- acp_sdk-0.0.5/tests/issues/test_152_resource_mime_type.py +0 -146
- acp_sdk-0.0.5/tests/issues/test_176_progress_token.py +0 -46
- acp_sdk-0.0.5/tests/issues/test_88_random_error.py +0 -111
- acp_sdk-0.0.5/tests/server/__init__.py +0 -0
- acp_sdk-0.0.5/tests/server/fastmcp/__init__.py +0 -0
- acp_sdk-0.0.5/tests/server/fastmcp/prompts/__init__.py +0 -0
- acp_sdk-0.0.5/tests/server/fastmcp/prompts/test_base.py +0 -206
- acp_sdk-0.0.5/tests/server/fastmcp/prompts/test_manager.py +0 -112
- acp_sdk-0.0.5/tests/server/fastmcp/resources/__init__.py +0 -0
- acp_sdk-0.0.5/tests/server/fastmcp/resources/test_file_resources.py +0 -119
- acp_sdk-0.0.5/tests/server/fastmcp/resources/test_function_resources.py +0 -138
- acp_sdk-0.0.5/tests/server/fastmcp/resources/test_resource_manager.py +0 -141
- acp_sdk-0.0.5/tests/server/fastmcp/resources/test_resource_template.py +0 -188
- acp_sdk-0.0.5/tests/server/fastmcp/resources/test_resources.py +0 -101
- acp_sdk-0.0.5/tests/server/fastmcp/servers/__init__.py +0 -0
- acp_sdk-0.0.5/tests/server/fastmcp/servers/test_file_server.py +0 -123
- acp_sdk-0.0.5/tests/server/fastmcp/test_func_metadata.py +0 -401
- acp_sdk-0.0.5/tests/server/fastmcp/test_parameter_descriptions.py +0 -30
- acp_sdk-0.0.5/tests/server/fastmcp/test_server.py +0 -743
- acp_sdk-0.0.5/tests/server/fastmcp/test_tool_manager.py +0 -322
- acp_sdk-0.0.5/tests/server/test_read_resource.py +0 -109
- acp_sdk-0.0.5/tests/server/test_session.py +0 -101
- acp_sdk-0.0.5/tests/server/test_stdio.py +0 -68
- acp_sdk-0.0.5/tests/shared/test_memory.py +0 -47
- acp_sdk-0.0.5/tests/shared/test_session.py +0 -127
- acp_sdk-0.0.5/tests/shared/test_sse.py +0 -254
- acp_sdk-0.0.5/tests/test_examples.py +0 -72
- acp_sdk-0.0.5/tests/test_types.py +0 -32
- {acp_sdk-0.0.5/src/acp → acp_sdk-0.1.0rc5/src/acp_sdk}/py.typed +0 -0
@@ -1,5 +1,40 @@
|
|
1
|
+
### NextJS template
|
2
|
+
# dependencies
|
3
|
+
node_modules
|
4
|
+
/.pnp
|
5
|
+
.pnp.js
|
6
|
+
|
7
|
+
# testing
|
8
|
+
/coverage
|
9
|
+
|
10
|
+
# next.js
|
11
|
+
/.next/
|
12
|
+
/out/
|
13
|
+
|
14
|
+
# production
|
15
|
+
/build
|
16
|
+
|
17
|
+
# misc
|
1
18
|
.DS_Store
|
19
|
+
*.pem
|
20
|
+
|
21
|
+
# debug
|
22
|
+
npm-debug.log*
|
23
|
+
yarn-debug.log*
|
24
|
+
yarn-error.log*
|
25
|
+
.pnpm-debug.log*
|
26
|
+
|
27
|
+
# local env files
|
28
|
+
.env*.local
|
29
|
+
|
30
|
+
# vercel
|
31
|
+
.vercel
|
32
|
+
|
33
|
+
# typescript
|
34
|
+
*.tsbuildinfo
|
35
|
+
next-env.d.ts
|
2
36
|
|
37
|
+
### Python template
|
3
38
|
# Byte-compiled / optimized / DLL files
|
4
39
|
__pycache__/
|
5
40
|
*.py[cod]
|
@@ -13,6 +48,7 @@ __pycache__/
|
|
13
48
|
build/
|
14
49
|
develop-eggs/
|
15
50
|
dist/
|
51
|
+
dist-py/
|
16
52
|
downloads/
|
17
53
|
eggs/
|
18
54
|
.eggs/
|
@@ -161,7 +197,7 @@ cython_debug/
|
|
161
197
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
162
198
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
163
199
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
164
|
-
|
200
|
+
.idea/
|
165
201
|
|
166
|
-
#
|
167
|
-
.
|
202
|
+
# Mise
|
203
|
+
mise.local.toml
|
@@ -0,0 +1 @@
|
|
1
|
+
3.11
|
@@ -0,0 +1,78 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: acp-sdk
|
3
|
+
Version: 0.1.0rc5
|
4
|
+
Summary: Agent Communication Protocol SDK
|
5
|
+
Requires-Python: <4.0,>=3.11
|
6
|
+
Requires-Dist: opentelemetry-api>=1.31.1
|
7
|
+
Requires-Dist: pydantic>=2.11.1
|
8
|
+
Provides-Extra: client
|
9
|
+
Requires-Dist: httpx-sse>=0.4.0; extra == 'client'
|
10
|
+
Requires-Dist: httpx>=0.28.1; extra == 'client'
|
11
|
+
Requires-Dist: opentelemetry-instrumentation-httpx>=0.52b1; extra == 'client'
|
12
|
+
Provides-Extra: server
|
13
|
+
Requires-Dist: fastapi[standard]>=0.115.8; extra == 'server'
|
14
|
+
Requires-Dist: janus>=2.0.0; extra == 'server'
|
15
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.31.1; extra == 'server'
|
16
|
+
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.52b1; extra == 'server'
|
17
|
+
Requires-Dist: opentelemetry-sdk>=1.31.1; extra == 'server'
|
18
|
+
Description-Content-Type: text/markdown
|
19
|
+
|
20
|
+
# Agent Communication Protocol SDK for Python
|
21
|
+
|
22
|
+
Agent Communication Protocol SDK for Python provides allows developers to serve and consume agents over the Agent Communication Protocol.
|
23
|
+
|
24
|
+
## Prerequisites
|
25
|
+
|
26
|
+
✅ Python >= 3.11
|
27
|
+
|
28
|
+
## Installation
|
29
|
+
|
30
|
+
Install to use client:
|
31
|
+
|
32
|
+
```shell
|
33
|
+
pip install acp-sdk[client]
|
34
|
+
```
|
35
|
+
|
36
|
+
Install to use server:
|
37
|
+
|
38
|
+
```shell
|
39
|
+
pip install acp-sdk[server]
|
40
|
+
```
|
41
|
+
|
42
|
+
## Overview
|
43
|
+
|
44
|
+
### Client
|
45
|
+
|
46
|
+
The `client` submodule exposes [httpx]() based client with simple methods for communication over ACP.
|
47
|
+
|
48
|
+
```python
|
49
|
+
async with Client(base_url="http://localhost:8000") as client:
|
50
|
+
run = await client.run_sync(agent="echo", input=Message(TextMessagePart(content="Howdy!")))
|
51
|
+
print(run.output)
|
52
|
+
```
|
53
|
+
|
54
|
+
### Server
|
55
|
+
|
56
|
+
The `server` submodule exposes [fastapi] application factory that makes it easy to expose any agent over ACP.
|
57
|
+
|
58
|
+
```python
|
59
|
+
class EchoAgent(Agent):
|
60
|
+
@property
|
61
|
+
def name(self) -> str:
|
62
|
+
return "echo"
|
63
|
+
|
64
|
+
@property
|
65
|
+
def description(self) -> str:
|
66
|
+
return "Echoes everything"
|
67
|
+
|
68
|
+
async def run(self, input: Message, *, context: Context) -> AsyncGenerator[Message | Await, AwaitResume]:
|
69
|
+
for part in input:
|
70
|
+
await asyncio.sleep(0.5)
|
71
|
+
yield {"thought": "I should echo everyting"}
|
72
|
+
yield Message(part)
|
73
|
+
|
74
|
+
|
75
|
+
serve(EchoAgent())
|
76
|
+
```
|
77
|
+
|
78
|
+
➡️ Explore more in our [examples library](/python/examples).
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# Agent Communication Protocol SDK for Python
|
2
|
+
|
3
|
+
Agent Communication Protocol SDK for Python provides allows developers to serve and consume agents over the Agent Communication Protocol.
|
4
|
+
|
5
|
+
## Prerequisites
|
6
|
+
|
7
|
+
✅ Python >= 3.11
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Install to use client:
|
12
|
+
|
13
|
+
```shell
|
14
|
+
pip install acp-sdk[client]
|
15
|
+
```
|
16
|
+
|
17
|
+
Install to use server:
|
18
|
+
|
19
|
+
```shell
|
20
|
+
pip install acp-sdk[server]
|
21
|
+
```
|
22
|
+
|
23
|
+
## Overview
|
24
|
+
|
25
|
+
### Client
|
26
|
+
|
27
|
+
The `client` submodule exposes [httpx]() based client with simple methods for communication over ACP.
|
28
|
+
|
29
|
+
```python
|
30
|
+
async with Client(base_url="http://localhost:8000") as client:
|
31
|
+
run = await client.run_sync(agent="echo", input=Message(TextMessagePart(content="Howdy!")))
|
32
|
+
print(run.output)
|
33
|
+
```
|
34
|
+
|
35
|
+
### Server
|
36
|
+
|
37
|
+
The `server` submodule exposes [fastapi] application factory that makes it easy to expose any agent over ACP.
|
38
|
+
|
39
|
+
```python
|
40
|
+
class EchoAgent(Agent):
|
41
|
+
@property
|
42
|
+
def name(self) -> str:
|
43
|
+
return "echo"
|
44
|
+
|
45
|
+
@property
|
46
|
+
def description(self) -> str:
|
47
|
+
return "Echoes everything"
|
48
|
+
|
49
|
+
async def run(self, input: Message, *, context: Context) -> AsyncGenerator[Message | Await, AwaitResume]:
|
50
|
+
for part in input:
|
51
|
+
await asyncio.sleep(0.5)
|
52
|
+
yield {"thought": "I should echo everyting"}
|
53
|
+
yield Message(part)
|
54
|
+
|
55
|
+
|
56
|
+
serve(EchoAgent())
|
57
|
+
```
|
58
|
+
|
59
|
+
➡️ Explore more in our [examples library](/python/examples).
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import asyncio
|
2
|
+
|
3
|
+
import httpx
|
4
|
+
from acp_sdk.client.client import Client
|
5
|
+
from acp_sdk.models import Message, TextMessagePart
|
6
|
+
|
7
|
+
|
8
|
+
async def example() -> None:
|
9
|
+
async with Client(
|
10
|
+
client=httpx.AsyncClient(
|
11
|
+
base_url="http://localhost:8000",
|
12
|
+
auth=httpx.BasicAuth(username="username", password="password"),
|
13
|
+
# Additional client configuration
|
14
|
+
)
|
15
|
+
) as client:
|
16
|
+
run = await client.run_sync(agent="echo", input=Message(TextMessagePart(content="Howdy!")))
|
17
|
+
print(run.output)
|
18
|
+
|
19
|
+
|
20
|
+
if __name__ == "__main__":
|
21
|
+
asyncio.run(example())
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import asyncio
|
2
|
+
|
3
|
+
from acp_sdk.client import Client
|
4
|
+
from acp_sdk.models import (
|
5
|
+
Message,
|
6
|
+
TextMessagePart,
|
7
|
+
)
|
8
|
+
|
9
|
+
|
10
|
+
async def example() -> None:
|
11
|
+
async with Client(base_url="http://localhost:8000") as client:
|
12
|
+
run = await client.run_sync(agent="echo", input=Message(TextMessagePart(content="Howdy!")))
|
13
|
+
print(run.output)
|
14
|
+
|
15
|
+
|
16
|
+
if __name__ == "__main__":
|
17
|
+
asyncio.run(example())
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import asyncio
|
2
|
+
|
3
|
+
from acp_sdk.client import Client
|
4
|
+
from acp_sdk.models import Message, TextMessagePart
|
5
|
+
|
6
|
+
|
7
|
+
async def example() -> None:
|
8
|
+
async with Client(base_url="http://localhost:8000") as client:
|
9
|
+
async for event in client.run_stream(agent="echo", input=Message(TextMessagePart(content="Howdy!"))):
|
10
|
+
print(event)
|
11
|
+
|
12
|
+
|
13
|
+
if __name__ == "__main__":
|
14
|
+
asyncio.run(example())
|
@@ -0,0 +1,23 @@
|
|
1
|
+
from collections.abc import AsyncGenerator
|
2
|
+
from typing import Any
|
3
|
+
|
4
|
+
from acp_sdk.models import (
|
5
|
+
Await,
|
6
|
+
AwaitResume,
|
7
|
+
Message,
|
8
|
+
TextMessagePart,
|
9
|
+
)
|
10
|
+
from acp_sdk.server import Context, Server
|
11
|
+
|
12
|
+
server = Server()
|
13
|
+
|
14
|
+
|
15
|
+
@server.agent()
|
16
|
+
async def awaiting(input: Message, context: Context) -> AsyncGenerator[Message | Await | Any, AwaitResume]:
|
17
|
+
"""Greets and awaits for more data"""
|
18
|
+
yield Message(TextMessagePart(content="Hello!"))
|
19
|
+
data = yield Await()
|
20
|
+
yield Message(TextMessagePart(content=f"Thanks for {data}"))
|
21
|
+
|
22
|
+
|
23
|
+
server.run()
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import asyncio
|
2
|
+
from collections.abc import AsyncGenerator
|
3
|
+
|
4
|
+
from acp_sdk.models import (
|
5
|
+
Message,
|
6
|
+
)
|
7
|
+
from acp_sdk.server import Context, RunYield, RunYieldResume, Server
|
8
|
+
|
9
|
+
server = Server()
|
10
|
+
|
11
|
+
|
12
|
+
@server.agent()
|
13
|
+
async def echo(input: Message, context: Context) -> AsyncGenerator[RunYield, RunYieldResume]:
|
14
|
+
"""Echoes everything"""
|
15
|
+
for part in input:
|
16
|
+
await asyncio.sleep(0.5)
|
17
|
+
yield {"thought": "I should echo everyting"}
|
18
|
+
await asyncio.sleep(0.5)
|
19
|
+
yield Message(part)
|
20
|
+
|
21
|
+
|
22
|
+
server.run()
|
@@ -0,0 +1,59 @@
|
|
1
|
+
from collections.abc import AsyncGenerator, Generator
|
2
|
+
|
3
|
+
from acp_sdk.models import (
|
4
|
+
Message,
|
5
|
+
)
|
6
|
+
from acp_sdk.server import Agent, Context, RunYield, RunYieldResume, Server
|
7
|
+
|
8
|
+
# This example showcases several ways to create echo agent using decoratos.
|
9
|
+
|
10
|
+
server = Server()
|
11
|
+
|
12
|
+
|
13
|
+
@server.agent()
|
14
|
+
async def async_gen_echo(input: Message, context: Context) -> AsyncGenerator[RunYield, RunYieldResume]:
|
15
|
+
"""Echoes everything"""
|
16
|
+
yield {"thought": "I should echo everyting"}
|
17
|
+
yield input
|
18
|
+
|
19
|
+
|
20
|
+
@server.agent()
|
21
|
+
async def async_echo(input: Message, context: Context) -> RunYield:
|
22
|
+
"""Echoes everything"""
|
23
|
+
await context.yield_async({"thought": "I should echo everyting"})
|
24
|
+
return input
|
25
|
+
|
26
|
+
|
27
|
+
@server.agent()
|
28
|
+
def gen_echo(input: Message, context: Context) -> Generator[RunYield, RunYieldResume]:
|
29
|
+
"""Echoes everything"""
|
30
|
+
yield {"thought": "I should echo everyting"}
|
31
|
+
return input
|
32
|
+
|
33
|
+
|
34
|
+
@server.agent()
|
35
|
+
def sync_echo(input: Message, context: Context) -> RunYield:
|
36
|
+
"""Echoes everything"""
|
37
|
+
context.yield_sync({"thought": "I should echo everyting"})
|
38
|
+
return input
|
39
|
+
|
40
|
+
|
41
|
+
class EchoAgent(Agent):
|
42
|
+
@property
|
43
|
+
def name(self) -> str:
|
44
|
+
return "class_echo"
|
45
|
+
|
46
|
+
@property
|
47
|
+
def description(self) -> str:
|
48
|
+
return "Echoes everything"
|
49
|
+
|
50
|
+
async def run(self, input: Message, context: Context) -> AsyncGenerator[RunYield, RunYieldResume]:
|
51
|
+
"""Echoes everything"""
|
52
|
+
yield {"thought": "I should echo everyting"}
|
53
|
+
yield input
|
54
|
+
|
55
|
+
|
56
|
+
server.register(EchoAgent())
|
57
|
+
|
58
|
+
|
59
|
+
server.run()
|
@@ -0,0 +1,38 @@
|
|
1
|
+
[project]
|
2
|
+
name = "acp-sdk"
|
3
|
+
version = "0.1.0rc5"
|
4
|
+
description = "Agent Communication Protocol SDK"
|
5
|
+
readme = "README.md"
|
6
|
+
authors = []
|
7
|
+
requires-python = ">=3.11, <4.0"
|
8
|
+
dependencies = ["opentelemetry-api>=1.31.1", "pydantic>=2.11.1"]
|
9
|
+
|
10
|
+
[project.optional-dependencies]
|
11
|
+
client = [
|
12
|
+
"httpx>=0.28.1",
|
13
|
+
"httpx-sse>=0.4.0",
|
14
|
+
"opentelemetry-instrumentation-httpx>=0.52b1",
|
15
|
+
]
|
16
|
+
server = [
|
17
|
+
"fastapi[standard]>=0.115.8",
|
18
|
+
"opentelemetry-exporter-otlp-proto-http>=1.31.1",
|
19
|
+
"opentelemetry-instrumentation-fastapi>=0.52b1",
|
20
|
+
"opentelemetry-sdk>=1.31.1",
|
21
|
+
"janus>=2.0.0",
|
22
|
+
]
|
23
|
+
|
24
|
+
[tool.uv]
|
25
|
+
dev-dependencies = [
|
26
|
+
"httpx>=0.28.1",
|
27
|
+
"httpx-sse>=0.4.0",
|
28
|
+
"opentelemetry-instrumentation-httpx>=0.52b1",
|
29
|
+
"fastapi[standard]>=0.115.8",
|
30
|
+
"opentelemetry-exporter-otlp-proto-http>=1.31.1",
|
31
|
+
"opentelemetry-instrumentation-fastapi>=0.52b1",
|
32
|
+
"opentelemetry-sdk>=1.31.1",
|
33
|
+
"janus>=2.0.0",
|
34
|
+
]
|
35
|
+
|
36
|
+
[build-system]
|
37
|
+
requires = ["hatchling"]
|
38
|
+
build-backend = "hatchling.build"
|
@@ -0,0 +1 @@
|
|
1
|
+
from acp_sdk.models import * # noqa: F403
|
@@ -0,0 +1 @@
|
|
1
|
+
from acp_sdk.client.client import Client as Client
|
@@ -0,0 +1,139 @@
|
|
1
|
+
from collections.abc import AsyncIterator
|
2
|
+
from types import TracebackType
|
3
|
+
from typing import Self
|
4
|
+
|
5
|
+
import httpx
|
6
|
+
from httpx_sse import EventSource, aconnect_sse
|
7
|
+
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
|
8
|
+
from pydantic import TypeAdapter
|
9
|
+
|
10
|
+
from acp_sdk.models import (
|
11
|
+
ACPError,
|
12
|
+
Agent,
|
13
|
+
AgentName,
|
14
|
+
AgentReadResponse,
|
15
|
+
AgentsListResponse,
|
16
|
+
AwaitResume,
|
17
|
+
Error,
|
18
|
+
Message,
|
19
|
+
Run,
|
20
|
+
RunCancelResponse,
|
21
|
+
RunCreateRequest,
|
22
|
+
RunCreateResponse,
|
23
|
+
RunEvent,
|
24
|
+
RunId,
|
25
|
+
RunMode,
|
26
|
+
RunResumeRequest,
|
27
|
+
RunResumeResponse,
|
28
|
+
)
|
29
|
+
|
30
|
+
|
31
|
+
class Client:
|
32
|
+
def __init__(self, *, base_url: httpx.URL | str = "", client: httpx.AsyncClient | None = None) -> None:
|
33
|
+
self.base_url = base_url
|
34
|
+
|
35
|
+
self._client = self._init_client(client)
|
36
|
+
|
37
|
+
def _init_client(self, client: httpx.AsyncClient | None = None) -> httpx.AsyncClient:
|
38
|
+
client = client or httpx.AsyncClient(base_url=self.base_url)
|
39
|
+
HTTPXClientInstrumentor.instrument_client(client)
|
40
|
+
return client
|
41
|
+
|
42
|
+
async def __aenter__(self) -> Self:
|
43
|
+
await self._client.__aenter__()
|
44
|
+
return self
|
45
|
+
|
46
|
+
async def __aexit__(
|
47
|
+
self,
|
48
|
+
exc_type: type[BaseException] | None = None,
|
49
|
+
exc_value: BaseException | None = None,
|
50
|
+
traceback: TracebackType | None = None,
|
51
|
+
) -> None:
|
52
|
+
await self._client.__aexit__(exc_type, exc_value, traceback)
|
53
|
+
|
54
|
+
async def agents(self) -> AsyncIterator[Agent]:
|
55
|
+
response = await self._client.get("/agents")
|
56
|
+
self._raise_error(response)
|
57
|
+
for agent in AgentsListResponse.model_validate(response.json()).agents:
|
58
|
+
yield agent
|
59
|
+
|
60
|
+
async def agent(self, *, name: AgentName) -> Agent:
|
61
|
+
response = await self._client.get(f"/agents/{name}")
|
62
|
+
self._raise_error(response)
|
63
|
+
return AgentReadResponse.model_validate(response.json())
|
64
|
+
|
65
|
+
async def run_sync(self, *, agent: AgentName, input: Message) -> Run:
|
66
|
+
response = await self._client.post(
|
67
|
+
"/runs",
|
68
|
+
json=RunCreateRequest(agent_name=agent, input=input, mode=RunMode.SYNC).model_dump(),
|
69
|
+
)
|
70
|
+
self._raise_error(response)
|
71
|
+
return RunCreateResponse.model_validate(response.json())
|
72
|
+
|
73
|
+
async def run_async(self, *, agent: AgentName, input: Message) -> Run:
|
74
|
+
response = await self._client.post(
|
75
|
+
"/runs",
|
76
|
+
json=RunCreateRequest(agent_name=agent, input=input, mode=RunMode.ASYNC).model_dump(),
|
77
|
+
)
|
78
|
+
self._raise_error(response)
|
79
|
+
return RunCreateResponse.model_validate(response.json())
|
80
|
+
|
81
|
+
async def run_stream(self, *, agent: AgentName, input: Message) -> AsyncIterator[RunEvent]:
|
82
|
+
async with aconnect_sse(
|
83
|
+
self._client,
|
84
|
+
"POST",
|
85
|
+
"/runs",
|
86
|
+
json=RunCreateRequest(agent_name=agent, input=input, mode=RunMode.STREAM).model_dump(),
|
87
|
+
) as event_source:
|
88
|
+
async for event in self._validate_stream(event_source):
|
89
|
+
yield event
|
90
|
+
|
91
|
+
async def run_status(self, *, run_id: RunId) -> Run:
|
92
|
+
response = await self._client.get(f"/runs/{run_id}")
|
93
|
+
self._raise_error(response)
|
94
|
+
return Run.model_validate(response.json())
|
95
|
+
|
96
|
+
async def run_cancel(self, *, run_id: RunId) -> Run:
|
97
|
+
response = await self._client.post(f"/runs/{run_id}/cancel")
|
98
|
+
self._raise_error(response)
|
99
|
+
return RunCancelResponse.model_validate(response.json())
|
100
|
+
|
101
|
+
async def run_resume_sync(self, *, run_id: RunId, await_: AwaitResume) -> Run:
|
102
|
+
response = await self._client.post(
|
103
|
+
f"/runs/{run_id}",
|
104
|
+
json=RunResumeRequest(await_=await_, mode=RunMode.SYNC).model_dump(),
|
105
|
+
)
|
106
|
+
self._raise_error(response)
|
107
|
+
return RunResumeResponse.model_validate(response.json())
|
108
|
+
|
109
|
+
async def run_resume_async(self, *, run_id: RunId, await_: AwaitResume) -> Run:
|
110
|
+
response = await self._client.post(
|
111
|
+
f"/runs/{run_id}",
|
112
|
+
json=RunResumeRequest(await_=await_, mode=RunMode.ASYNC).model_dump(),
|
113
|
+
)
|
114
|
+
self._raise_error(response)
|
115
|
+
return RunResumeResponse.model_validate(response.json())
|
116
|
+
|
117
|
+
async def run_resume_stream(self, *, run_id: RunId, await_: AwaitResume) -> AsyncIterator[RunEvent]:
|
118
|
+
async with aconnect_sse(
|
119
|
+
self._client,
|
120
|
+
"POST",
|
121
|
+
f"/runs/{run_id}",
|
122
|
+
json=RunResumeRequest(await_=await_, mode=RunMode.STREAM).model_dump(),
|
123
|
+
) as event_source:
|
124
|
+
async for event in self._validate_stream(event_source):
|
125
|
+
yield event
|
126
|
+
|
127
|
+
async def _validate_stream(
|
128
|
+
self,
|
129
|
+
event_source: EventSource,
|
130
|
+
) -> AsyncIterator[RunEvent]:
|
131
|
+
async for event in event_source.aiter_sse():
|
132
|
+
event = TypeAdapter(RunEvent).validate_json(event.data)
|
133
|
+
yield event
|
134
|
+
|
135
|
+
def _raise_error(self, response: httpx.Response) -> None:
|
136
|
+
try:
|
137
|
+
response.raise_for_status()
|
138
|
+
except httpx.HTTPError:
|
139
|
+
raise ACPError(Error.model_validate(response.json()))
|
@@ -0,0 +1,23 @@
|
|
1
|
+
from enum import Enum
|
2
|
+
|
3
|
+
from pydantic import BaseModel
|
4
|
+
|
5
|
+
|
6
|
+
class ErrorCode(str, Enum):
|
7
|
+
SERVER_ERROR = "server_error"
|
8
|
+
INVALID_INPUT = "invalid_input"
|
9
|
+
NOT_FOUND = "not_found"
|
10
|
+
|
11
|
+
|
12
|
+
class Error(BaseModel):
|
13
|
+
code: ErrorCode
|
14
|
+
message: str
|
15
|
+
|
16
|
+
|
17
|
+
class ACPError(Exception):
|
18
|
+
def __init__(self, error: Error) -> None:
|
19
|
+
super().__init__()
|
20
|
+
self.error = error
|
21
|
+
|
22
|
+
def __str__(self) -> str:
|
23
|
+
return str(self.error.message)
|