zrb 1.5.3__py3-none-any.whl → 1.5.4__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.
zrb/task/base_task.py CHANGED
@@ -1,6 +1,6 @@
1
1
  import asyncio
2
2
  import os
3
- from collections.abc import Callable
3
+ from collections.abc import Callable, Coroutine
4
4
  from typing import Any
5
5
 
6
6
  from zrb.attr.type import BoolAttr, fstring
@@ -64,7 +64,7 @@ class BaseTask(AnyTask):
64
64
  def __repr__(self):
65
65
  return f"<{self.__class__.__name__} name={self._name}>"
66
66
 
67
- def __rshift__(self, other: AnyTask | list[AnyTask]) -> AnyTask:
67
+ def __rshift__(self, other: AnyTask | list[AnyTask]) -> AnyTask | list[AnyTask]:
68
68
  try:
69
69
  if isinstance(other, AnyTask):
70
70
  other.append_upstream(self)
@@ -123,7 +123,9 @@ class BaseTask(AnyTask):
123
123
  return [task_input for task_input in inputs if task_input is not None]
124
124
 
125
125
  def __combine_inputs(
126
- self, inputs: list[AnyInput], other_inputs: list[AnyInput] | AnyInput
126
+ self,
127
+ inputs: list[AnyInput],
128
+ other_inputs: list[AnyInput | None] | AnyInput | None,
127
129
  ):
128
130
  input_names = [task_input.name for task_input in inputs]
129
131
  if isinstance(other_inputs, AnyInput):
@@ -429,7 +431,7 @@ class BaseTask(AnyTask):
429
431
  session.get_task_status(self).reset()
430
432
  # defer this action
431
433
  ctx.log_info("Running")
432
- action_coro = asyncio.create_task(
434
+ action_coro: Coroutine = asyncio.create_task(
433
435
  run_async(self.__exec_action_and_retry(session))
434
436
  )
435
437
  session.defer_action(self, action_coro)
zrb/task/llm_task.py CHANGED
@@ -1,4 +1,3 @@
1
- import copy
2
1
  import functools
3
2
  import inspect
4
3
  import json
@@ -9,6 +8,7 @@ from typing import Any
9
8
 
10
9
  from openai import APIError
11
10
  from pydantic_ai import Agent, Tool
11
+ from pydantic_ai.mcp import MCPServer
12
12
  from pydantic_ai.messages import (
13
13
  FinalResultEvent,
14
14
  FunctionToolCallEvent,
@@ -54,9 +54,9 @@ class LLMTask(BaseTask):
54
54
  Callable[[AnySharedContext], Model | str | fstring] | Model | None
55
55
  ) = None,
56
56
  render_model: bool = True,
57
- model_base_url: StrAttr = None,
57
+ model_base_url: StrAttr | None = None,
58
58
  render_model_base_url: bool = True,
59
- model_api_key: StrAttr = None,
59
+ model_api_key: StrAttr | None = None,
60
60
  render_model_api_key: bool = True,
61
61
  model_settings: (
62
62
  ModelSettings | Callable[[AnySharedContext], ModelSettings] | None
@@ -68,6 +68,9 @@ class LLMTask(BaseTask):
68
68
  tools: (
69
69
  list[ToolOrCallable] | Callable[[AnySharedContext], list[ToolOrCallable]]
70
70
  ) = [],
71
+ mcp_servers: (
72
+ list[MCPServer] | Callable[[AnySharedContext], list[MCPServer]]
73
+ ) = [],
71
74
  conversation_history: (
72
75
  ListOfDict | Callable[[AnySharedContext], ListOfDict]
73
76
  ) = [],
@@ -127,6 +130,8 @@ class LLMTask(BaseTask):
127
130
  self._message = message
128
131
  self._tools = tools
129
132
  self._additional_tools: list[ToolOrCallable] = []
133
+ self._mcp_servers = mcp_servers
134
+ self._additional_mcp_servers: list[MCPServer] = []
130
135
  self._conversation_history = conversation_history
131
136
  self._conversation_history_reader = conversation_history_reader
132
137
  self._conversation_history_writer = conversation_history_writer
@@ -137,32 +142,36 @@ class LLMTask(BaseTask):
137
142
  def add_tool(self, tool: ToolOrCallable):
138
143
  self._additional_tools.append(tool)
139
144
 
145
+ def add_mcp_server(self, mcp_server: MCPServer):
146
+ self._additional_mcp_servers.append(mcp_server)
147
+
140
148
  async def _exec_action(self, ctx: AnyContext) -> Any:
141
149
  history = await self._read_conversation_history(ctx)
142
150
  user_prompt = self._get_message(ctx)
143
151
  agent = self._get_agent(ctx)
144
152
  try:
145
- async with agent.iter(
146
- user_prompt=user_prompt,
147
- message_history=ModelMessagesTypeAdapter.validate_python(history),
148
- ) as agent_run:
149
- async for node in agent_run:
150
- # Each node represents a step in the agent's execution
151
- # Reference: https://ai.pydantic.dev/agents/#streaming
152
- try:
153
- await self._print_node(ctx, agent_run, node)
154
- except APIError as e:
155
- # Extract detailed error information from the response
156
- error_details = _extract_api_error_details(e)
157
- ctx.log_error(f"API Error: {error_details}")
158
- raise
159
- except Exception as e:
160
- ctx.log_error(f"Error processing node: {str(e)}")
161
- ctx.log_error(f"Error type: {type(e).__name__}")
162
- raise
163
- new_history = json.loads(agent_run.result.all_messages_json())
164
- await self._write_conversation_history(ctx, new_history)
165
- return agent_run.result.data
153
+ async with agent.run_mcp_servers():
154
+ async with agent.iter(
155
+ user_prompt=user_prompt,
156
+ message_history=ModelMessagesTypeAdapter.validate_python(history),
157
+ ) as agent_run:
158
+ async for node in agent_run:
159
+ # Each node represents a step in the agent's execution
160
+ # Reference: https://ai.pydantic.dev/agents/#streaming
161
+ try:
162
+ await self._print_node(ctx, agent_run, node)
163
+ except APIError as e:
164
+ # Extract detailed error information from the response
165
+ error_details = _extract_api_error_details(e)
166
+ ctx.log_error(f"API Error: {error_details}")
167
+ raise
168
+ except Exception as e:
169
+ ctx.log_error(f"Error processing node: {str(e)}")
170
+ ctx.log_error(f"Error type: {type(e).__name__}")
171
+ raise
172
+ new_history = json.loads(agent_run.result.all_messages_json())
173
+ await self._write_conversation_history(ctx, new_history)
174
+ return agent_run.result.data
166
175
  except Exception as e:
167
176
  ctx.log_error(f"Error in agent execution: {str(e)}")
168
177
  raise
@@ -277,10 +286,15 @@ class LLMTask(BaseTask):
277
286
  tool if isinstance(tool, Tool) else Tool(_wrap_tool(tool), takes_ctx=False)
278
287
  for tool in tools_or_callables
279
288
  ]
289
+ mcp_servers = list(
290
+ self._mcp_servers(ctx) if callable(self._mcp_servers) else self._mcp_servers
291
+ )
292
+ mcp_servers.extend(self._additional_mcp_servers)
280
293
  return Agent(
281
294
  self._get_model(ctx),
282
295
  system_prompt=self._get_system_prompt(ctx),
283
296
  tools=tools,
297
+ mcp_servers=mcp_servers,
284
298
  model_settings=self._get_model_settings(ctx),
285
299
  retries=3,
286
300
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: zrb
3
- Version: 1.5.3
3
+ Version: 1.5.4
4
4
  Summary: Your Automation Powerhouse
5
5
  Home-page: https://github.com/state-alchemists/zrb
6
6
  License: AGPL-3.0-or-later
@@ -26,7 +26,7 @@ Requires-Dist: openai (>=1.70.0,<2.0.0) ; extra == "rag" or extra == "all"
26
26
  Requires-Dist: pdfplumber (>=0.11.6,<0.12.0) ; extra == "rag" or extra == "all"
27
27
  Requires-Dist: playwright (>=1.51.0,<2.0.0) ; extra == "playwright" or extra == "all"
28
28
  Requires-Dist: psutil (>=7.0.0,<8.0.0)
29
- Requires-Dist: pydantic-ai (>=0.0.49,<0.0.50)
29
+ Requires-Dist: pydantic-ai (>=0.0.52,<0.0.53)
30
30
  Requires-Dist: python-dotenv (>=1.1.0,<2.0.0)
31
31
  Requires-Dist: python-jose[cryptography] (>=3.4.0,<4.0.0)
32
32
  Requires-Dist: requests (>=2.32.3,<3.0.0)
@@ -296,11 +296,11 @@ zrb/session_state_logger/file_session_state_logger.py,sha256=1ue7-Bcwg4wlLn2G_7A
296
296
  zrb/session_state_logger/session_state_logger_factory.py,sha256=wXf2DVmeRmx399MFYYty6uNcPZMcf7iayHBYCLGlhfc,189
297
297
  zrb/task/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
298
298
  zrb/task/any_task.py,sha256=9rCdKe-Sayr34Han9AsbhRxFpkbk6Rteg1DOyETulwQ,4917
299
- zrb/task/base_task.py,sha256=SQRf37bylS586KwyW0eYDe9JZ5Hl18FP8kScHae6y3A,21251
299
+ zrb/task/base_task.py,sha256=H1D2KyJ9qK0GIPJ4kYyvfRe7fseJibmLVGjj8iRuLs4,21320
300
300
  zrb/task/base_trigger.py,sha256=jC722rDvodaBLeNaFghkTyv1u0QXrK6BLZUUqcmBJ7Q,4581
301
301
  zrb/task/cmd_task.py,sha256=pUKRSR4DZKjbmluB6vi7cxqyhxOLfJ2czSpYeQbiDvo,10705
302
302
  zrb/task/http_check.py,sha256=Gf5rOB2Se2EdizuN9rp65HpGmfZkGc-clIAlHmPVehs,2565
303
- zrb/task/llm_task.py,sha256=di9lYvcwd3uCPe9KzbDsXNy2ZJT49DmIIuYUS_bd8DY,19942
303
+ zrb/task/llm_task.py,sha256=L5VFRJBgcYuucBtF3fTemjD0E-8fzA40HHeCm8T56CQ,20659
304
304
  zrb/task/make_task.py,sha256=PD3b_aYazthS8LHeJsLAhwKDEgdurQZpymJDKeN60u0,2265
305
305
  zrb/task/rsync_task.py,sha256=GSL9144bmp6F0EckT6m-2a1xG25AzrrWYzH4k3SVUKM,6370
306
306
  zrb/task/scaffolder.py,sha256=rME18w1HJUHXgi9eTYXx_T2G4JdqDYzBoNOkdOOo5-o,6806
@@ -341,7 +341,7 @@ zrb/util/string/name.py,sha256=8picJfUBXNpdh64GNaHv3om23QHhUZux7DguFLrXHp8,1163
341
341
  zrb/util/todo.py,sha256=1nDdwPc22oFoK_1ZTXyf3638Bg6sqE2yp_U4_-frHoc,16015
342
342
  zrb/xcom/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
343
343
  zrb/xcom/xcom.py,sha256=o79rxR9wphnShrcIushA0Qt71d_p3ZTxjNf7x9hJB78,1571
344
- zrb-1.5.3.dist-info/METADATA,sha256=didD-AcEFyUlwOfXEyLCebJewXMt8hLRmLL1zp5HDZE,8470
345
- zrb-1.5.3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
346
- zrb-1.5.3.dist-info/entry_points.txt,sha256=-Pg3ElWPfnaSM-XvXqCxEAa-wfVI6BEgcs386s8C8v8,46
347
- zrb-1.5.3.dist-info/RECORD,,
344
+ zrb-1.5.4.dist-info/METADATA,sha256=OeBW0SVw6MmYpkFACsrADLiJctonRhH9ZVQPKzgrjAI,8470
345
+ zrb-1.5.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
346
+ zrb-1.5.4.dist-info/entry_points.txt,sha256=-Pg3ElWPfnaSM-XvXqCxEAa-wfVI6BEgcs386s8C8v8,46
347
+ zrb-1.5.4.dist-info/RECORD,,
File without changes