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 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
- inputs=self._unify_inputs(input),
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
- inputs=self._unify_inputs(input),
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
- inputs=self._unify_inputs(input),
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
@@ -0,0 +1,3 @@
1
+ from acp_sdk.models import Message, MessagePart
2
+
3
+ Input = list[Message] | Message | list[MessagePart] | MessagePart | list[str] | str
@@ -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
@@ -177,7 +177,7 @@ class Run(BaseModel):
177
177
  session_id: SessionId | None = None
178
178
  status: RunStatus = RunStatus.CREATED
179
179
  await_request: AwaitRequest | None = None
180
- outputs: list[Message] = []
180
+ output: list[Message] = []
181
181
  error: Error | None = None
182
182
 
183
183
 
acp_sdk/models/schemas.py CHANGED
@@ -14,7 +14,7 @@ class AgentReadResponse(Agent):
14
14
  class RunCreateRequest(BaseModel):
15
15
  agent_name: AgentName
16
16
  session_id: SessionId | None = None
17
- inputs: list[Message]
17
+ input: list[Message]
18
18
  mode: RunMode = RunMode.SYNC
19
19
 
20
20
 
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, inputs: list[Message], context: Context
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, inputs: list[Message], session_id: SessionId | None, executor: ThreadPoolExecutor
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(inputs, context))
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(inputs, context))
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, inputs, context)
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, inputs, context)
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
- inputs=request.inputs,
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, inputs: list[Message], history: list[Message], executor: ThreadPoolExecutor
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.inputs = inputs
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(inputs, executor=executor))
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, inputs: list[Message], *, executor: ThreadPoolExecutor) -> None:
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.outputs[-1]))
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
- inputs=self.history + inputs, session_id=self.run.session_id, executor=executor
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.outputs.append(Message(parts=[]))
117
+ self.run.output.append(Message(parts=[]))
118
118
  in_message = True
119
- await self.emit(MessageCreatedEvent(message=self.run.outputs[-1]))
120
- self.run.outputs[-1].parts.append(next)
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.outputs.append(next)
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
@@ -17,5 +17,5 @@ class Session:
17
17
  def history(self) -> Iterator[Message]:
18
18
  for bundle in self.bundles:
19
19
  if bundle.run.status == RunStatus.COMPLETED:
20
- yield from bundle.inputs
21
- yield from bundle.run.outputs
20
+ yield from bundle.input
21
+ yield from bundle.run.output
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: acp-sdk
3
- Version: 0.6.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(inputs: list[Message]):
47
+ async def echo(input: list[Message]):
48
48
  """Echoes everything"""
49
- for message in inputs:
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", inputs=[Message(parts=[MessagePart(content="Howdy!")])])
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=CtH8dBEEKLjhPqCvxhEOPGnmNMMYsG22AH0OC5pWbpE,9310
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=eOoOfftPKbTaLlqZlE4gE1ZwDkrQ_FdRiDx4wSJILP4,6539
10
- acp_sdk/models/schemas.py,sha256=Kj7drJSR8d-N3KHzu_qTnLdagrMtAyhid5swluuhHTw,645
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=DhcPDPDL9jpDST40K_bInvDXfpF1cwxIhqXzu8z0blU,6203
13
- acp_sdk/server/app.py,sha256=YcW5kEwmRER9LKRsLt2vNqFso4_nnbWabdjiN-4_0-0,6601
14
- acp_sdk/server/bundle.py,sha256=nLxQMUCSVzlmEgSUYRunnpD3jO2yE2w1XVvKW6NOTPE,6564
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=0cDr924HC5x2bBNbK9NSKVHAt5A_mi5dK8P4jP_ugq0,629
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.6.0.dist-info/METADATA,sha256=K2qABevuRD1ydsvoqniFrrNVu_abbf5I3IQDS7TuAUM,1654
24
- acp_sdk-0.6.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
25
- acp_sdk-0.6.0.dist-info/RECORD,,
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,,