acp-sdk 0.6.0__py3-none-any.whl → 0.7.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- acp_sdk/client/client.py +5 -28
- acp_sdk/client/types.py +3 -0
- acp_sdk/client/utils.py +24 -0
- acp_sdk/models/models.py +1 -1
- acp_sdk/models/schemas.py +1 -1
- acp_sdk/server/agent.py +14 -14
- acp_sdk/server/app.py +1 -1
- acp_sdk/server/bundle.py +10 -10
- acp_sdk/server/session.py +2 -2
- {acp_sdk-0.6.0.dist-info → acp_sdk-0.7.1.dist-info}/METADATA +4 -4
- {acp_sdk-0.6.0.dist-info → acp_sdk-0.7.1.dist-info}/RECORD +12 -10
- {acp_sdk-0.6.0.dist-info → acp_sdk-0.7.1.dist-info}/WHEEL +0 -0
acp_sdk/client/client.py
CHANGED
@@ -11,6 +11,8 @@ from httpx_sse import EventSource, aconnect_sse
|
|
11
11
|
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
|
12
12
|
from pydantic import TypeAdapter
|
13
13
|
|
14
|
+
from acp_sdk.client.types import Input
|
15
|
+
from acp_sdk.client.utils import input_to_messages
|
14
16
|
from acp_sdk.instrumentation import get_tracer
|
15
17
|
from acp_sdk.models import (
|
16
18
|
ACPError,
|
@@ -21,7 +23,6 @@ from acp_sdk.models import (
|
|
21
23
|
AwaitResume,
|
22
24
|
Error,
|
23
25
|
Event,
|
24
|
-
Message,
|
25
26
|
Run,
|
26
27
|
RunCancelResponse,
|
27
28
|
RunCreatedEvent,
|
@@ -33,9 +34,6 @@ from acp_sdk.models import (
|
|
33
34
|
RunResumeResponse,
|
34
35
|
SessionId,
|
35
36
|
)
|
36
|
-
from acp_sdk.models.models import MessagePart
|
37
|
-
|
38
|
-
Input = list[Message] | Message | list[MessagePart] | MessagePart | list[str] | str
|
39
37
|
|
40
38
|
|
41
39
|
class Client:
|
@@ -127,7 +125,7 @@ class Client:
|
|
127
125
|
"/runs",
|
128
126
|
content=RunCreateRequest(
|
129
127
|
agent_name=agent,
|
130
|
-
|
128
|
+
input=input_to_messages(input),
|
131
129
|
mode=RunMode.SYNC,
|
132
130
|
session_id=self._session_id,
|
133
131
|
).model_dump_json(),
|
@@ -142,7 +140,7 @@ class Client:
|
|
142
140
|
"/runs",
|
143
141
|
content=RunCreateRequest(
|
144
142
|
agent_name=agent,
|
145
|
-
|
143
|
+
input=input_to_messages(input),
|
146
144
|
mode=RunMode.ASYNC,
|
147
145
|
session_id=self._session_id,
|
148
146
|
).model_dump_json(),
|
@@ -159,7 +157,7 @@ class Client:
|
|
159
157
|
"/runs",
|
160
158
|
content=RunCreateRequest(
|
161
159
|
agent_name=agent,
|
162
|
-
|
160
|
+
input=input_to_messages(input),
|
163
161
|
mode=RunMode.STREAM,
|
164
162
|
session_id=self._session_id,
|
165
163
|
).model_dump_json(),
|
@@ -227,24 +225,3 @@ class Client:
|
|
227
225
|
|
228
226
|
def _set_session(self, run: Run) -> None:
|
229
227
|
self._session_id = run.session_id
|
230
|
-
|
231
|
-
def _unify_inputs(self, input: Input) -> list[Message]:
|
232
|
-
if isinstance(input, list):
|
233
|
-
if len(input) == 0:
|
234
|
-
return []
|
235
|
-
if all(isinstance(item, Message) for item in input):
|
236
|
-
return input
|
237
|
-
elif all(isinstance(item, MessagePart) for item in input):
|
238
|
-
return [Message(parts=input)]
|
239
|
-
elif all(isinstance(item, str) for item in input):
|
240
|
-
return [Message(parts=[MessagePart(content=content) for content in input])]
|
241
|
-
else:
|
242
|
-
raise RuntimeError("List with mixed types is not supported")
|
243
|
-
else:
|
244
|
-
if isinstance(input, str):
|
245
|
-
input = MessagePart(content=input)
|
246
|
-
if isinstance(input, MessagePart):
|
247
|
-
input = Message(parts=[input])
|
248
|
-
if isinstance(input, Message):
|
249
|
-
input = [input]
|
250
|
-
return input
|
acp_sdk/client/types.py
ADDED
acp_sdk/client/utils.py
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
from acp_sdk.client.types import Input
|
2
|
+
from acp_sdk.models.models import Message, MessagePart
|
3
|
+
|
4
|
+
|
5
|
+
def input_to_messages(input: Input) -> list[Message]:
|
6
|
+
if isinstance(input, list):
|
7
|
+
if len(input) == 0:
|
8
|
+
return []
|
9
|
+
if all(isinstance(item, Message) for item in input):
|
10
|
+
return input
|
11
|
+
elif all(isinstance(item, MessagePart) for item in input):
|
12
|
+
return [Message(parts=input)]
|
13
|
+
elif all(isinstance(item, str) for item in input):
|
14
|
+
return [Message(parts=[MessagePart(content=content) for content in input])]
|
15
|
+
else:
|
16
|
+
raise TypeError("List with mixed types is not supported")
|
17
|
+
else:
|
18
|
+
if isinstance(input, str):
|
19
|
+
input = MessagePart(content=input)
|
20
|
+
if isinstance(input, MessagePart):
|
21
|
+
input = Message(parts=[input])
|
22
|
+
if isinstance(input, Message):
|
23
|
+
input = [input]
|
24
|
+
return input
|
acp_sdk/models/models.py
CHANGED
acp_sdk/models/schemas.py
CHANGED
acp_sdk/server/agent.py
CHANGED
@@ -32,14 +32,14 @@ class Agent(abc.ABC):
|
|
32
32
|
|
33
33
|
@abc.abstractmethod
|
34
34
|
def run(
|
35
|
-
self,
|
35
|
+
self, input: list[Message], context: Context
|
36
36
|
) -> (
|
37
37
|
AsyncGenerator[RunYield, RunYieldResume] | Generator[RunYield, RunYieldResume] | Coroutine[RunYield] | RunYield
|
38
38
|
):
|
39
39
|
pass
|
40
40
|
|
41
41
|
async def execute(
|
42
|
-
self,
|
42
|
+
self, input: list[Message], session_id: SessionId | None, executor: ThreadPoolExecutor
|
43
43
|
) -> AsyncGenerator[RunYield, RunYieldResume]:
|
44
44
|
yield_queue: janus.Queue[RunYield] = janus.Queue()
|
45
45
|
yield_resume_queue: janus.Queue[RunYieldResume] = janus.Queue()
|
@@ -49,13 +49,13 @@ class Agent(abc.ABC):
|
|
49
49
|
)
|
50
50
|
|
51
51
|
if inspect.isasyncgenfunction(self.run):
|
52
|
-
run = asyncio.create_task(self._run_async_gen(
|
52
|
+
run = asyncio.create_task(self._run_async_gen(input, context))
|
53
53
|
elif inspect.iscoroutinefunction(self.run):
|
54
|
-
run = asyncio.create_task(self._run_coro(
|
54
|
+
run = asyncio.create_task(self._run_coro(input, context))
|
55
55
|
elif inspect.isgeneratorfunction(self.run):
|
56
|
-
run = asyncio.get_running_loop().run_in_executor(executor, self._run_gen,
|
56
|
+
run = asyncio.get_running_loop().run_in_executor(executor, self._run_gen, input, context)
|
57
57
|
else:
|
58
|
-
run = asyncio.get_running_loop().run_in_executor(executor, self._run_func,
|
58
|
+
run = asyncio.get_running_loop().run_in_executor(executor, self._run_func, input, context)
|
59
59
|
|
60
60
|
try:
|
61
61
|
while True:
|
@@ -66,7 +66,7 @@ class Agent(abc.ABC):
|
|
66
66
|
finally:
|
67
67
|
await run # Raise exceptions
|
68
68
|
|
69
|
-
async def _run_async_gen(self, input: Message, context: Context) -> None:
|
69
|
+
async def _run_async_gen(self, input: list[Message], context: Context) -> None:
|
70
70
|
try:
|
71
71
|
gen: AsyncGenerator[RunYield, RunYieldResume] = self.run(input, context)
|
72
72
|
value = None
|
@@ -77,13 +77,13 @@ class Agent(abc.ABC):
|
|
77
77
|
finally:
|
78
78
|
context.shutdown()
|
79
79
|
|
80
|
-
async def _run_coro(self, input: Message, context: Context) -> None:
|
80
|
+
async def _run_coro(self, input: list[Message], context: Context) -> None:
|
81
81
|
try:
|
82
82
|
await context.yield_async(await self.run(input, context))
|
83
83
|
finally:
|
84
84
|
context.shutdown()
|
85
85
|
|
86
|
-
def _run_gen(self, input: Message, context: Context) -> None:
|
86
|
+
def _run_gen(self, input: list[Message], context: Context) -> None:
|
87
87
|
try:
|
88
88
|
gen: Generator[RunYield, RunYieldResume] = self.run(input, context)
|
89
89
|
value = None
|
@@ -94,7 +94,7 @@ class Agent(abc.ABC):
|
|
94
94
|
finally:
|
95
95
|
context.shutdown()
|
96
96
|
|
97
|
-
def _run_func(self, input: Message, context: Context) -> None:
|
97
|
+
def _run_func(self, input: list[Message], context: Context) -> None:
|
98
98
|
try:
|
99
99
|
context.yield_sync(self.run(input, context))
|
100
100
|
finally:
|
@@ -139,7 +139,7 @@ def agent(
|
|
139
139
|
if inspect.isasyncgenfunction(fn):
|
140
140
|
|
141
141
|
class AsyncGenDecoratorAgent(DecoratorAgentBase):
|
142
|
-
async def run(self, input: Message, context: Context) -> AsyncGenerator[RunYield, RunYieldResume]:
|
142
|
+
async def run(self, input: list[Message], context: Context) -> AsyncGenerator[RunYield, RunYieldResume]:
|
143
143
|
try:
|
144
144
|
gen: AsyncGenerator[RunYield, RunYieldResume] = (
|
145
145
|
fn(input, context) if has_context_param else fn(input)
|
@@ -154,21 +154,21 @@ def agent(
|
|
154
154
|
elif inspect.iscoroutinefunction(fn):
|
155
155
|
|
156
156
|
class CoroDecoratorAgent(DecoratorAgentBase):
|
157
|
-
async def run(self, input: Message, context: Context) -> Coroutine[RunYield]:
|
157
|
+
async def run(self, input: list[Message], context: Context) -> Coroutine[RunYield]:
|
158
158
|
return await (fn(input, context) if has_context_param else fn(input))
|
159
159
|
|
160
160
|
agent = CoroDecoratorAgent()
|
161
161
|
elif inspect.isgeneratorfunction(fn):
|
162
162
|
|
163
163
|
class GenDecoratorAgent(DecoratorAgentBase):
|
164
|
-
def run(self, input: Message, context: Context) -> Generator[RunYield, RunYieldResume]:
|
164
|
+
def run(self, input: list[Message], context: Context) -> Generator[RunYield, RunYieldResume]:
|
165
165
|
yield from (fn(input, context) if has_context_param else fn(input))
|
166
166
|
|
167
167
|
agent = GenDecoratorAgent()
|
168
168
|
else:
|
169
169
|
|
170
170
|
class FuncDecoratorAgent(DecoratorAgentBase):
|
171
|
-
def run(self, input: Message, context: Context) -> RunYield:
|
171
|
+
def run(self, input: list[Message], context: Context) -> RunYield:
|
172
172
|
return fn(input, context) if has_context_param else fn(input)
|
173
173
|
|
174
174
|
agent = FuncDecoratorAgent()
|
acp_sdk/server/app.py
CHANGED
@@ -105,7 +105,7 @@ def create_app(*agents: Agent, run_limit: int = 1000, run_ttl: timedelta = timed
|
|
105
105
|
bundle = RunBundle(
|
106
106
|
agent=agent,
|
107
107
|
run=Run(agent_name=agent.name, session_id=session.id),
|
108
|
-
|
108
|
+
input=request.input,
|
109
109
|
history=list(session.history()),
|
110
110
|
executor=executor,
|
111
111
|
)
|
acp_sdk/server/bundle.py
CHANGED
@@ -35,11 +35,11 @@ from acp_sdk.server.logging import logger
|
|
35
35
|
|
36
36
|
class RunBundle:
|
37
37
|
def __init__(
|
38
|
-
self, *, agent: Agent, run: Run,
|
38
|
+
self, *, agent: Agent, run: Run, input: list[Message], history: list[Message], executor: ThreadPoolExecutor
|
39
39
|
) -> None:
|
40
40
|
self.agent = agent
|
41
41
|
self.run = run
|
42
|
-
self.
|
42
|
+
self.input = input
|
43
43
|
self.history = history
|
44
44
|
|
45
45
|
self.stream_queue: asyncio.Queue[Event] = asyncio.Queue()
|
@@ -47,7 +47,7 @@ class RunBundle:
|
|
47
47
|
self.await_queue: asyncio.Queue[AwaitResume] = asyncio.Queue(maxsize=1)
|
48
48
|
self.await_or_terminate_event = asyncio.Event()
|
49
49
|
|
50
|
-
self.task = asyncio.create_task(self._execute(
|
50
|
+
self.task = asyncio.create_task(self._execute(input, executor=executor))
|
51
51
|
|
52
52
|
async def stream(self) -> AsyncGenerator[Event]:
|
53
53
|
while True:
|
@@ -83,7 +83,7 @@ class RunBundle:
|
|
83
83
|
async def join(self) -> None:
|
84
84
|
await self.await_or_terminate_event.wait()
|
85
85
|
|
86
|
-
async def _execute(self,
|
86
|
+
async def _execute(self, input: list[Message], *, executor: ThreadPoolExecutor) -> None:
|
87
87
|
with get_tracer().start_as_current_span("run"):
|
88
88
|
run_logger = logging.LoggerAdapter(logger, {"run_id": str(self.run.run_id)})
|
89
89
|
|
@@ -92,14 +92,14 @@ class RunBundle:
|
|
92
92
|
async def flush_message() -> None:
|
93
93
|
nonlocal in_message
|
94
94
|
if in_message:
|
95
|
-
await self.emit(MessageCompletedEvent(message=self.run.
|
95
|
+
await self.emit(MessageCompletedEvent(message=self.run.output[-1]))
|
96
96
|
in_message = False
|
97
97
|
|
98
98
|
try:
|
99
99
|
await self.emit(RunCreatedEvent(run=self.run))
|
100
100
|
|
101
101
|
generator = self.agent.execute(
|
102
|
-
|
102
|
+
input=self.history + input, session_id=self.run.session_id, executor=executor
|
103
103
|
)
|
104
104
|
run_logger.info("Run started")
|
105
105
|
|
@@ -114,14 +114,14 @@ class RunBundle:
|
|
114
114
|
if isinstance(next, str):
|
115
115
|
next = MessagePart(content=next)
|
116
116
|
if not in_message:
|
117
|
-
self.run.
|
117
|
+
self.run.output.append(Message(parts=[]))
|
118
118
|
in_message = True
|
119
|
-
await self.emit(MessageCreatedEvent(message=self.run.
|
120
|
-
self.run.
|
119
|
+
await self.emit(MessageCreatedEvent(message=self.run.output[-1]))
|
120
|
+
self.run.output[-1].parts.append(next)
|
121
121
|
await self.emit(MessagePartEvent(part=next))
|
122
122
|
elif isinstance(next, Message):
|
123
123
|
await flush_message()
|
124
|
-
self.run.
|
124
|
+
self.run.output.append(next)
|
125
125
|
await self.emit(MessageCreatedEvent(message=next))
|
126
126
|
for part in next.parts:
|
127
127
|
await self.emit(MessagePartEvent(part=part))
|
acp_sdk/server/session.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: acp-sdk
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.7.1
|
4
4
|
Summary: Agent Communication Protocol SDK
|
5
5
|
Author: IBM Corp.
|
6
6
|
Maintainer-email: Tomas Pilar <thomas7pilar@gmail.com>
|
@@ -44,9 +44,9 @@ Register an agent and run the server:
|
|
44
44
|
server = Server()
|
45
45
|
|
46
46
|
@server.agent()
|
47
|
-
async def echo(
|
47
|
+
async def echo(input: list[Message]):
|
48
48
|
"""Echoes everything"""
|
49
|
-
for message in
|
49
|
+
for message in input:
|
50
50
|
yield message
|
51
51
|
|
52
52
|
server.run(port=8000)
|
@@ -56,7 +56,7 @@ From another process, connect to the server and run the agent:
|
|
56
56
|
|
57
57
|
```py
|
58
58
|
async with Client(base_url="http://localhost:8000") as client:
|
59
|
-
run = await client.run_sync(agent="echo",
|
59
|
+
run = await client.run_sync(agent="echo", input=[Message(parts=[MessagePart(content="Howdy!")])])
|
60
60
|
print(run)
|
61
61
|
|
62
62
|
```
|
@@ -3,23 +3,25 @@ acp_sdk/instrumentation.py,sha256=JqSyvILN3sGAfOZrmckQq4-M_4_5alyPn95DK0o5lfA,16
|
|
3
3
|
acp_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
acp_sdk/version.py,sha256=Niy83rgvigB4hL_rR-O4ySvI7dj6xnqkyOe_JTymi9s,73
|
5
5
|
acp_sdk/client/__init__.py,sha256=Bca1DORrswxzZsrR2aUFpATuNG2xNSmYvF1Z2WJaVbc,51
|
6
|
-
acp_sdk/client/client.py,sha256=
|
6
|
+
acp_sdk/client/client.py,sha256=uIHlnB5TR9qe2yqWgQoSQBmdXZhMmsmmygxuhtnL6ew,8336
|
7
|
+
acp_sdk/client/types.py,sha256=_H6zYt-2OHOOYRtssRnbDIiwmgsl2-KIXc9lb-mJLFA,133
|
8
|
+
acp_sdk/client/utils.py,sha256=2jhJyrPJmVFRoDJh0q_JMqOMlC3IxCh-6HXed-PIZS8,924
|
7
9
|
acp_sdk/models/__init__.py,sha256=numSDBDT1QHx7n_Y3Deb5VOvKWcUBxbOEaMwQBSRHxc,151
|
8
10
|
acp_sdk/models/errors.py,sha256=rEyaMVvQuBi7fwWe_d0PGGySYsD3FZTluQ-SkC0yhAs,444
|
9
|
-
acp_sdk/models/models.py,sha256=
|
10
|
-
acp_sdk/models/schemas.py,sha256=
|
11
|
+
acp_sdk/models/models.py,sha256=rQpc5eFSyDK_ALBXSjg6dTRNA6B0UFY3ssECY_1oIDc,6538
|
12
|
+
acp_sdk/models/schemas.py,sha256=OQ2bEfwFFZ1D9mhpgzfPBCcnPNvbl4qRfCWChH2wCro,644
|
11
13
|
acp_sdk/server/__init__.py,sha256=mxBBBFaZuMEUENRMLwp1XZkuLeT9QghcFmNvjnqvAAU,377
|
12
|
-
acp_sdk/server/agent.py,sha256=
|
13
|
-
acp_sdk/server/app.py,sha256=
|
14
|
-
acp_sdk/server/bundle.py,sha256=
|
14
|
+
acp_sdk/server/agent.py,sha256=wvwpi83osmW7zQWxVnzyVMXIvzOswAfhKWHscVIldhA,6245
|
15
|
+
acp_sdk/server/app.py,sha256=IocQBnXn1K6MP7aUvGSTD3TfVCKy9DGRZA3liYlfdYk,6599
|
16
|
+
acp_sdk/server/bundle.py,sha256=P3DfmzQOewsK8jr8yG8_RsGSrXQI4PsZCQbspVxKlus,6552
|
15
17
|
acp_sdk/server/context.py,sha256=MgnLV6qcDIhc_0BjW7r4Jj1tHts4ZuwpdTGIBnz2Mgo,1036
|
16
18
|
acp_sdk/server/errors.py,sha256=GSO8yYIqEeX8Y4Lz86ks35dMTHiQiXuOrLYYx0eXsbI,2110
|
17
19
|
acp_sdk/server/logging.py,sha256=Oc8yZigCsuDnHHPsarRzu0RX3NKaLEgpELM2yovGKDI,411
|
18
20
|
acp_sdk/server/server.py,sha256=6mIVyURgJvcZCPad1CV8TcgHC2mqyEFCGgGATGyP34Q,5548
|
19
|
-
acp_sdk/server/session.py,sha256=
|
21
|
+
acp_sdk/server/session.py,sha256=fCRPHc2sQrz4G0n25I1S4LB7mI1wo0yYQJ1V9WRWH3g,627
|
20
22
|
acp_sdk/server/telemetry.py,sha256=1BUxNg-xL_Vqgs27PDWNc3HikrQW2lidAtT_FKlp_Qk,1833
|
21
23
|
acp_sdk/server/types.py,sha256=teBNRWSks8XP1SCQKGEtbNWQahVD3RAOPnysTxcQPxI,292
|
22
24
|
acp_sdk/server/utils.py,sha256=EfrF9VCyVk3AM_ao-BIB9EzGbfTrh4V2Bz-VFr6f6Sg,351
|
23
|
-
acp_sdk-0.
|
24
|
-
acp_sdk-0.
|
25
|
-
acp_sdk-0.
|
25
|
+
acp_sdk-0.7.1.dist-info/METADATA,sha256=akqHFFa6cRGdqOTalPhM_lO9f9LGyaMRotTocAjRw9E,1651
|
26
|
+
acp_sdk-0.7.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
27
|
+
acp_sdk-0.7.1.dist-info/RECORD,,
|
File without changes
|