zrb 1.15.3__py3-none-any.whl → 1.15.5__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.
@@ -10,6 +10,7 @@ import sys
10
10
 
11
11
  from zrb.config.llm_config import llm_config
12
12
  from zrb.context.any_context import AnyContext
13
+ from zrb.util.cli.markdown import render_markdown
13
14
  from zrb.util.cli.style import stylize_blue, stylize_bold_yellow, stylize_faint
14
15
  from zrb.util.string.conversion import to_boolean
15
16
 
@@ -200,27 +201,13 @@ async def _trigger_ask_and_wait_for_result(
200
201
  ctx, user_prompt, modes, yolo_mode, previous_session_name, start_new
201
202
  )
202
203
  result = await _wait_ask_result(ctx)
203
- md_result = _render_markdown(result) if result is not None else ""
204
+ md_result = render_markdown(result) if result is not None else ""
204
205
  ctx.print("\n🤖 >>", plain=True)
205
206
  ctx.print(md_result, plain=True)
206
207
  ctx.print("", plain=True)
207
208
  return result
208
209
 
209
210
 
210
- def _render_markdown(markdown_text: str) -> str:
211
- """
212
- Renders Markdown to a string, ensuring link URLs are visible.
213
- """
214
- from rich.console import Console
215
- from rich.markdown import Markdown
216
-
217
- console = Console()
218
- markdown = Markdown(markdown_text, hyperlinks=False)
219
- with console.capture() as capture:
220
- console.print(markdown)
221
- return capture.get()
222
-
223
-
224
211
  def get_llm_ask_input_mapping(callback_ctx: AnyContext):
225
212
  """
226
213
  Generates the input mapping for the LLM ask task from the callback context.
@@ -6,6 +6,7 @@ from zrb.builtin.llm.tool.sub_agent import create_sub_agent_tool
6
6
  from zrb.config.config import CFG
7
7
  from zrb.config.llm_rate_limitter import llm_rate_limitter
8
8
  from zrb.context.any_context import AnyContext
9
+ from zrb.util.cli.style import stylize_faint
9
10
 
10
11
  _DEFAULT_EXTENSIONS = [
11
12
  "py",
@@ -112,7 +113,7 @@ async def analyze_repo(
112
113
  )
113
114
  abs_path = os.path.abspath(os.path.expanduser(path))
114
115
  file_metadatas = _get_file_metadatas(abs_path, extensions, exclude_patterns)
115
- ctx.print("Extraction")
116
+ ctx.print(stylize_faint(" 📝 Extraction"), plain=True)
116
117
  extracted_infos = await _extract_info(
117
118
  ctx,
118
119
  file_metadatas=file_metadatas,
@@ -121,10 +122,10 @@ async def analyze_repo(
121
122
  )
122
123
  if len(extracted_infos) == 1:
123
124
  return extracted_infos[0]
124
- ctx.print("Summarization")
125
+ ctx.print(stylize_faint(" 📝 Summarization"), plain=True)
125
126
  summarized_infos = extracted_infos
126
127
  while len(summarized_infos) > 1:
127
- ctx.print("Summarization")
128
+ ctx.print(stylize_faint(" 📝 Summarization"), plain=True)
128
129
  summarized_infos = await _summarize_info(
129
130
  ctx,
130
131
  extracted_infos=summarized_infos,
@@ -26,6 +26,7 @@ def create_sub_agent_tool(
26
26
  tools: "list[ToolOrCallable]" = [],
27
27
  toolsets: list["AbstractToolset[Agent]"] = [],
28
28
  is_yolo_mode: bool | None = None,
29
+ log_indent_level: int = 2,
29
30
  ) -> Callable[[AnyContext, str], Coroutine[Any, Any, str]]:
30
31
  """
31
32
  Creates a "tool that is another AI agent," capable of handling complex,
@@ -110,6 +111,7 @@ def create_sub_agent_tool(
110
111
  user_prompt=query,
111
112
  attachments=[],
112
113
  history_list=[],
114
+ log_indent_level=log_indent_level,
113
115
  )
114
116
 
115
117
  # Return the sub-agent's final message content
zrb/task/llm/agent.py CHANGED
@@ -129,6 +129,7 @@ async def run_agent_iteration(
129
129
  history_list: ListOfDict | None = None,
130
130
  rate_limitter: LLMRateLimiter | None = None,
131
131
  max_retry: int = 2,
132
+ log_indent_level: int = 0,
132
133
  ) -> "AgentRun":
133
134
  """
134
135
  Runs a single iteration of the agent execution loop.
@@ -159,6 +160,7 @@ async def run_agent_iteration(
159
160
  rate_limitter=(
160
161
  llm_rate_limitter if rate_limitter is None else rate_limitter
161
162
  ),
163
+ log_indent_level=log_indent_level,
162
164
  )
163
165
  except BaseException:
164
166
  attempt += 1
@@ -174,6 +176,7 @@ async def _run_single_agent_iteration(
174
176
  attachments: "list[UserContent]",
175
177
  history_list: ListOfDict,
176
178
  rate_limitter: LLMRateLimiter,
179
+ log_indent_level: int,
177
180
  ) -> "AgentRun":
178
181
  from openai import APIError
179
182
  from pydantic_ai.messages import ModelMessagesTypeAdapter
@@ -196,7 +199,9 @@ async def _run_single_agent_iteration(
196
199
  # Each node represents a step in the agent's execution
197
200
  # Reference: https://ai.pydantic.dev/agents/#streaming
198
201
  try:
199
- await print_node(_get_plain_printer(ctx), agent_run, node)
202
+ await print_node(
203
+ _get_plain_printer(ctx), agent_run, node, log_indent_level
204
+ )
200
205
  except APIError as e:
201
206
  # Extract detailed error information from the response
202
207
  error_details = extract_api_error_details(e)
@@ -88,7 +88,7 @@ async def summarize_history(
88
88
  conversation_history: ConversationHistory,
89
89
  rate_limitter: LLMRateLimiter | None = None,
90
90
  retries: int = 3,
91
- ) -> str:
91
+ ) -> ConversationHistory:
92
92
  """Runs an LLM call to update the conversation summary."""
93
93
  from pydantic_ai import Agent
94
94
 
@@ -152,7 +152,7 @@ async def summarize_history(
152
152
  ],
153
153
  )
154
154
  try:
155
- ctx.print(stylize_faint("📝 Summarize Conversation >>>"), plain=True)
155
+ ctx.print(stylize_faint(" 📝 Rollup Conversation"), plain=True)
156
156
  summary_run = await run_agent_iteration(
157
157
  ctx=ctx,
158
158
  agent=summarization_agent,
@@ -160,10 +160,13 @@ async def summarize_history(
160
160
  attachments=[],
161
161
  history_list=[],
162
162
  rate_limitter=rate_limitter,
163
+ log_indent_level=2,
163
164
  )
164
165
  if summary_run and summary_run.result and summary_run.result.output:
165
166
  usage = summary_run.result.usage()
166
- ctx.print(stylize_faint(f"📝 Summarization Token: {usage}"), plain=True)
167
+ ctx.print(
168
+ stylize_faint(f" 📝 Rollup Conversation Token: {usage}"), plain=True
169
+ )
167
170
  ctx.print(plain=True)
168
171
  ctx.log_info("History summarized and updated.")
169
172
  else:
@@ -1,10 +1,13 @@
1
+ import json
1
2
  from collections.abc import Callable
2
3
  from typing import Any
3
4
 
4
5
  from zrb.util.cli.style import stylize_faint
5
6
 
6
7
 
7
- async def print_node(print_func: Callable, agent_run: Any, node: Any):
8
+ async def print_node(
9
+ print_func: Callable, agent_run: Any, node: Any, log_indent_level: int = 0
10
+ ):
8
11
  """Prints the details of an agent execution node using a provided print function."""
9
12
  from pydantic_ai import Agent
10
13
  from pydantic_ai.messages import (
@@ -19,10 +22,10 @@ async def print_node(print_func: Callable, agent_run: Any, node: Any):
19
22
  )
20
23
 
21
24
  if Agent.is_user_prompt_node(node):
22
- print_func(stylize_faint(" 🔠 Receiving input..."))
25
+ print_func(_format_header("🔠 Receiving input...", log_indent_level))
23
26
  elif Agent.is_model_request_node(node):
24
27
  # A model request node => We can stream tokens from the model's request
25
- print_func(stylize_faint(" 🧠 Processing..."))
28
+ print_func(_format_header("🧠 Processing...", log_indent_level))
26
29
  # Reference: https://ai.pydantic.dev/agents/#streaming
27
30
  async with node.stream(agent_run.ctx) as request_stream:
28
31
  is_streaming = False
@@ -31,66 +34,137 @@ async def print_node(print_func: Callable, agent_run: Any, node: Any):
31
34
  if is_streaming:
32
35
  print_func("")
33
36
  content = _get_event_part_content(event)
34
- print_func(stylize_faint(f" {content}"), end="")
35
- is_streaming = False
37
+ print_func(_format_content(content, log_indent_level), end="")
38
+ is_streaming = True
36
39
  elif isinstance(event, PartDeltaEvent):
37
40
  if isinstance(event.delta, TextPartDelta) or isinstance(
38
41
  event.delta, ThinkingPartDelta
39
42
  ):
43
+ content_delta = event.delta.content_delta
40
44
  print_func(
41
- stylize_faint(f"{event.delta.content_delta}"),
45
+ _format_stream_content(content_delta, log_indent_level),
42
46
  end="",
43
47
  )
44
48
  elif isinstance(event.delta, ToolCallPartDelta):
49
+ args_delta = event.delta.args_delta
45
50
  print_func(
46
- stylize_faint(f"{event.delta.args_delta}"),
47
- end="",
51
+ _format_stream_content(args_delta, log_indent_level), end=""
48
52
  )
49
53
  is_streaming = True
50
54
  elif isinstance(event, FinalResultEvent) and event.tool_name:
51
55
  if is_streaming:
52
56
  print_func("")
57
+ tool_name = event.tool_name
53
58
  print_func(
54
- stylize_faint(f" Result: tool_name={event.tool_name}"),
59
+ _format_content(
60
+ f"Result: tool_name={tool_name}", log_indent_level
61
+ )
55
62
  )
56
63
  is_streaming = False
57
64
  if is_streaming:
58
65
  print_func("")
59
66
  elif Agent.is_call_tools_node(node):
60
67
  # A handle-response node => The model returned some data, potentially calls a tool
61
- print_func(stylize_faint(" 🧰 Calling Tool..."))
68
+ print_func(_format_header("🧰 Calling Tool...", log_indent_level))
62
69
  async with node.stream(agent_run.ctx) as handle_stream:
63
70
  async for event in handle_stream:
64
71
  if isinstance(event, FunctionToolCallEvent):
65
- # Handle empty arguments across different providers
66
- if event.part.args == "" or event.part.args is None:
67
- event.part.args = {}
68
- elif isinstance(
69
- event.part.args, str
70
- ) and event.part.args.strip() in ["null", "{}"]:
71
- # Some providers might send "null" or "{}" as a string
72
- event.part.args = {}
73
- # Handle dummy property if present (from our schema sanitization)
74
- if (
75
- isinstance(event.part.args, dict)
76
- and "_dummy" in event.part.args
77
- ):
78
- del event.part.args["_dummy"]
72
+ args = _get_event_part_args(event)
73
+ call_id = event.part.tool_call_id
74
+ tool_name = event.part.tool_name
79
75
  print_func(
80
- stylize_faint(
81
- f" {event.part.tool_call_id} | "
82
- f"Call {event.part.tool_name} {event.part.args}"
76
+ _format_content(
77
+ f"{call_id} | Call {tool_name} {args}", log_indent_level
83
78
  )
84
79
  )
85
80
  elif isinstance(event, FunctionToolResultEvent):
81
+ call_id = event.tool_call_id
82
+ result_content = event.result.content
86
83
  print_func(
87
- stylize_faint(
88
- f" {event.tool_call_id} | {event.result.content}"
84
+ _format_content(
85
+ f"{call_id} | {result_content}", log_indent_level
89
86
  )
90
87
  )
91
88
  elif Agent.is_end_node(node):
92
89
  # Once an End node is reached, the agent run is complete
93
- print_func(stylize_faint(" ✅ Completed..."))
90
+ print_func(_format_header("✅ Completed...", log_indent_level))
91
+
92
+
93
+ def _format_header(text: str, log_indent_level: int = 0) -> str:
94
+ return _format(
95
+ text,
96
+ base_indent=2,
97
+ first_indent=0,
98
+ indent=0,
99
+ log_indent_level=log_indent_level,
100
+ )
101
+
102
+
103
+ def _format_content(text: str, log_indent_level: int = 0) -> str:
104
+ return _format(
105
+ text,
106
+ base_indent=2,
107
+ first_indent=3,
108
+ indent=3,
109
+ log_indent_level=log_indent_level,
110
+ )
111
+
112
+
113
+ def _format_stream_content(text: str, log_indent_level: int = 0) -> str:
114
+ return _format(
115
+ text,
116
+ base_indent=2,
117
+ indent=3,
118
+ log_indent_level=log_indent_level,
119
+ is_stream=True,
120
+ )
121
+
122
+
123
+ def _format(
124
+ text: str,
125
+ base_indent: int = 0,
126
+ first_indent: int = 0,
127
+ indent: int = 0,
128
+ log_indent_level: int = 0,
129
+ is_stream: bool = False,
130
+ ) -> str:
131
+ line_prefix = (base_indent * (log_indent_level + 1) + indent) * " "
132
+ processed_text = text.replace("\n", f"\n{line_prefix}")
133
+ if is_stream:
134
+ return stylize_faint(processed_text)
135
+ first_line_prefix = (base_indent * (log_indent_level + 1) + first_indent) * " "
136
+ return stylize_faint(f"{first_line_prefix}{processed_text}")
137
+
138
+
139
+ def _get_event_part_args(event: Any) -> Any:
140
+ # Handle empty arguments across different providers
141
+ if event.part.args == "" or event.part.args is None:
142
+ return {}
143
+ if isinstance(event.part.args, str):
144
+ # Some providers might send "null" or "{}" as a string
145
+ if event.part.args.strip() in ["null", "{}"]:
146
+ return {}
147
+ try:
148
+ obj = json.loads(event.part.args)
149
+ if isinstance(obj, dict):
150
+ return _truncate_kwargs(obj)
151
+ except json.JSONDecodeError:
152
+ pass
153
+ # Handle dummy property if present (from our schema sanitization)
154
+ if isinstance(event.part.args, dict):
155
+ return _truncate_kwargs(event.part.args)
156
+ print(type(event.part.args))
157
+ return event.part.args
158
+
159
+
160
+ def _truncate_kwargs(kwargs: dict[str, Any]) -> dict[str, Any]:
161
+ return {key: _truncate_arg(val) for key, val in kwargs.items() if key != "_dummy"}
162
+
163
+
164
+ def _truncate_arg(arg: str, length: int = 19) -> str:
165
+ if isinstance(arg, str) and len(arg) > length:
166
+ return f"{arg[:length-4]} ..."
167
+ return arg
94
168
 
95
169
 
96
170
  def _get_event_part_content(event: Any) -> str:
@@ -8,6 +8,7 @@ from typing import TYPE_CHECKING, Any
8
8
  from zrb.context.any_context import AnyContext
9
9
  from zrb.task.llm.error import ToolExecutionError
10
10
  from zrb.util.callable import get_callable_name
11
+ from zrb.util.cli.markdown import render_markdown
11
12
  from zrb.util.cli.style import (
12
13
  stylize_blue,
13
14
  stylize_error,
@@ -110,6 +111,8 @@ def _create_wrapper(
110
111
  if not approval:
111
112
  raise ValueError(f"User disapproving: {reason}")
112
113
  return await run_async(func(*args, **kwargs))
114
+ except KeyboardInterrupt as e:
115
+ raise e
113
116
  except Exception as e:
114
117
  error_model = ToolExecutionError(
115
118
  tool_name=func.__name__,
@@ -126,22 +129,16 @@ async def _ask_for_approval(
126
129
  ctx: AnyContext, func: Callable, args: list[Any], kwargs: dict[str, Any]
127
130
  ) -> tuple[bool, str]:
128
131
  func_name = get_callable_name(func)
129
- normalized_args = [stylize_green(_truncate_arg(arg)) for arg in args]
130
- normalized_kwargs = []
131
- for key, val in kwargs.items():
132
- truncated_val = _truncate_arg(f"{val}")
133
- normalized_kwargs.append(
134
- f"{stylize_yellow(key)}={stylize_green(truncated_val)}"
135
- )
136
- func_param_str = ",".join(normalized_args + normalized_kwargs)
137
- func_call_str = (
138
- f"{stylize_blue(func_name + '(')}{func_param_str}{stylize_blue(')')}"
132
+ func_call_str = _get_func_call_str(func, args, kwargs)
133
+ func_detail_param = _get_detail_func_param(args, kwargs)
134
+ confirmation_message = render_markdown(
135
+ f"Allow to run `{func_name}`? (`Yes` | `No, <reason>`)"
136
+ )
137
+ complete_confirmation_message = (
138
+ f"\n✅ >> {func_call_str}" f"\n{func_detail_param}" f"\n{confirmation_message}"
139
139
  )
140
140
  while True:
141
- ctx.print(
142
- f"\n✅ >> Allow to run tool: {func_call_str} (Yes | No, <reason>) ",
143
- plain=True,
144
- )
141
+ ctx.print(complete_confirmation_message, plain=True)
145
142
  user_input = await _read_line()
146
143
  ctx.print("", plain=True)
147
144
  user_responses = [val.strip() for val in user_input.split(",", maxsplit=1)]
@@ -169,10 +166,44 @@ async def _ask_for_approval(
169
166
  continue
170
167
 
171
168
 
169
+ def _get_detail_func_param(args: list[Any], kwargs: dict[str, Any]) -> str:
170
+ markdown = "\n".join(
171
+ [_get_func_param_item(key, val) for key, val in kwargs.items()]
172
+ )
173
+ return render_markdown(markdown)
174
+
175
+
176
+ def _get_func_param_item(key: str, val: Any) -> str:
177
+ upper_key = key.upper()
178
+ val_str = f"{val}"
179
+ val_parts = val_str.split("\n")
180
+ if len(val_parts) == 1:
181
+ return f"- {upper_key} `{val}`"
182
+ lines = [f"- {upper_key}", " ```"]
183
+ for val_part in val_parts:
184
+ lines.append(f" {val_part}")
185
+ lines.append(" ```")
186
+ return "\n".join(lines)
187
+
188
+
189
+ def _get_func_call_str(func: Callable, args: list[Any], kwargs: dict[str, Any]) -> str:
190
+ func_name = get_callable_name(func)
191
+ normalized_args = [stylize_green(_truncate_arg(arg)) for arg in args]
192
+ normalized_kwargs = []
193
+ for key, val in kwargs.items():
194
+ truncated_val = _truncate_arg(f"{val}")
195
+ normalized_kwargs.append(
196
+ f"{stylize_yellow(key)}={stylize_green(truncated_val)}"
197
+ )
198
+ func_param_str = ", ".join(normalized_args + normalized_kwargs)
199
+ return f"{stylize_blue(func_name + '(')}{func_param_str}{stylize_blue(')')}"
200
+
201
+
172
202
  def _truncate_arg(arg: str, length: int = 19) -> str:
173
- if len(arg) > length:
174
- return f"{arg[:length-4]} ..."
175
- return arg
203
+ normalized_arg = arg.replace("\n", "\\n")
204
+ if len(normalized_arg) > length:
205
+ return f"{normalized_arg[:length-4]} ..."
206
+ return normalized_arg
176
207
 
177
208
 
178
209
  async def _read_line():
zrb/task/llm_task.py CHANGED
@@ -331,7 +331,7 @@ class LLMTask(BaseTask):
331
331
  ctx.xcom[xcom_usage_key] = Xcom([])
332
332
  usage = agent_run.result.usage()
333
333
  ctx.xcom[xcom_usage_key].push(usage)
334
- ctx.print(stylize_faint(f" 💸 Token: {usage}"), plain=True)
334
+ ctx.print(stylize_faint(f" 💸 Token: {usage}"), plain=True)
335
335
  return agent_run.result.output
336
336
  else:
337
337
  ctx.log_warning("Agent run did not produce a result.")
@@ -0,0 +1,12 @@
1
+ def render_markdown(markdown_text: str) -> str:
2
+ """
3
+ Renders Markdown to a string, ensuring link URLs are visible.
4
+ """
5
+ from rich.console import Console
6
+ from rich.markdown import Markdown
7
+
8
+ console = Console()
9
+ markdown = Markdown(markdown_text, hyperlinks=False)
10
+ with console.capture() as capture:
11
+ console.print(markdown)
12
+ return capture.get()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: zrb
3
- Version: 1.15.3
3
+ Version: 1.15.5
4
4
  Summary: Your Automation Powerhouse
5
5
  License: AGPL-3.0-or-later
6
6
  Keywords: Automation,Task Runner,Code Generator,Monorepo,Low Code
@@ -16,21 +16,19 @@ Classifier: Programming Language :: Python :: 3.13
16
16
  Provides-Extra: all
17
17
  Provides-Extra: playwright
18
18
  Provides-Extra: rag
19
- Requires-Dist: beautifulsoup4 (>=4.13.3,<5.0.0)
20
- Requires-Dist: black (>=25.1.0,<25.2.0)
19
+ Requires-Dist: beautifulsoup4 (>=4.13.4,<5.0.0)
20
+ Requires-Dist: black (>=25.1.0,<26.0.0)
21
21
  Requires-Dist: chromadb (>=0.6.3,<0.7.0) ; extra == "rag" or extra == "all"
22
22
  Requires-Dist: fastapi[standard] (>=0.116.1,<0.117.0)
23
- Requires-Dist: isort (>=6.0.1,<6.1.0)
24
- Requires-Dist: libcst (>=1.7.0,<2.0.0)
23
+ Requires-Dist: isort (>=6.0.1,<7.0.0)
24
+ Requires-Dist: libcst (>=1.8.2,<2.0.0)
25
25
  Requires-Dist: markdownify (>=1.2.0,<2.0.0)
26
- Requires-Dist: openai (>=1.99.7)
27
- Requires-Dist: pdfplumber (>=0.11.6,<0.12.0)
28
- Requires-Dist: playwright (>=1.53.0,<2.0.0) ; extra == "playwright" or extra == "all"
26
+ Requires-Dist: pdfplumber (>=0.11.7,<0.12.0)
27
+ Requires-Dist: playwright (>=1.54.0,<2.0.0) ; extra == "playwright" or extra == "all"
29
28
  Requires-Dist: psutil (>=7.0.0,<8.0.0)
30
- Requires-Dist: pydantic-ai-slim[anthropic,bedrock,cli,cohere,google,groq,huggingface,mcp,mistral,openai,vertexai] (>=0.7.0,<0.8.0)
31
- Requires-Dist: pyjwt (>=2.10.1,<3.0.0)
29
+ Requires-Dist: pydantic-ai-slim[anthropic,bedrock,cli,cohere,google,groq,huggingface,mcp,mistral,openai,vertexai] (>=0.7.4,<0.8.0)
32
30
  Requires-Dist: python-dotenv (>=1.1.1,<2.0.0)
33
- Requires-Dist: python-jose[cryptography] (>=3.4.0,<4.0.0)
31
+ Requires-Dist: python-jose[cryptography] (>=3.5.0,<4.0.0)
34
32
  Requires-Dist: requests (>=2.32.4,<3.0.0)
35
33
  Requires-Dist: tiktoken (>=0.8.0,<0.9.0)
36
34
  Requires-Dist: ulid-py (>=1.1.0,<2.0.0)
@@ -9,7 +9,7 @@ zrb/builtin/git_subtree.py,sha256=7BKwOkVTWDrR0DXXQ4iJyHqeR6sV5VYRt8y_rEB0EHg,35
9
9
  zrb/builtin/group.py,sha256=t008xLM4_fgbjfZrPoi_fQAnSHIo6MOiQSCHBO4GDYU,2379
10
10
  zrb/builtin/http.py,sha256=L6RE73c65wWwG5iHFN-tpOhyh56KsrgVskDd3c3YXtk,4246
11
11
  zrb/builtin/jwt.py,sha256=3M5uaQhJZbKQLjTUft1OwPz_JxtmK-xtkjxWjciOQho,2859
12
- zrb/builtin/llm/chat_session.py,sha256=gAn04kxT7YmqFCqxamFhV2W3Duq5z8z6jYaOmVxa5yc,10529
12
+ zrb/builtin/llm/chat_session.py,sha256=FnZAhrAHQ8tUgB1ejZby4p_v53c8HwsaMoVvqJWKELw,10191
13
13
  zrb/builtin/llm/history.py,sha256=LDOrL0p7r_AHLa5L8Dp7bHNsOALugmJd7OguXRWGnm4,3087
14
14
  zrb/builtin/llm/input.py,sha256=Nw-26uTWp2QhUgKJcP_IMHmtk-b542CCSQ_vCOjhvhM,877
15
15
  zrb/builtin/llm/llm_ask.py,sha256=03d1-2jh7NS0VP3eNl9wCdrUzud98i6zFUXW5NNu3_o,5597
@@ -17,10 +17,10 @@ zrb/builtin/llm/previous-session.js,sha256=xMKZvJoAbrwiyHS0OoPrWuaKxWYLoyR5sgueP
17
17
  zrb/builtin/llm/tool/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  zrb/builtin/llm/tool/api.py,sha256=vMEiZhhTZ3o2jRBxWcJ62b0M85wd_w4W0X4Hx23NXto,2380
19
19
  zrb/builtin/llm/tool/cli.py,sha256=8rugrKaNPEatHjr7nN4OIRLRT2TcF-oylEZGbLI9Brs,1254
20
- zrb/builtin/llm/tool/code.py,sha256=rK-QbuCIkJyZA1YwHwTkpN4-DdtVDXGHogLqWck2MBc,8695
20
+ zrb/builtin/llm/tool/code.py,sha256=BACeH0tGhTdDo0rZ7sTAP6oRaLi9cS7gdEigXiTd0Jg,8842
21
21
  zrb/builtin/llm/tool/file.py,sha256=eXFGGFxxpdpWGVw0svyQNQc03I5M7wotSsA_HjkXw7c,23670
22
22
  zrb/builtin/llm/tool/rag.py,sha256=Ab8_ZljnG_zfkwxPezImvorshuz3Fi4CmSzNOtU1a-g,9770
23
- zrb/builtin/llm/tool/sub_agent.py,sha256=R-GxcwjAixKboj5MKK3mHfZmGUQspuTMq498U6_ucQg,5008
23
+ zrb/builtin/llm/tool/sub_agent.py,sha256=hsR-5iozcgE0f-3J7VLP189JqsW6lE2h-x_1YW6pVAo,5086
24
24
  zrb/builtin/llm/tool/web.py,sha256=zNQWDNOz_MyyzhncBeV5E_9XijQxTFVp6BSzz_e5tBI,7261
25
25
  zrb/builtin/md5.py,sha256=690RV2LbW7wQeTFxY-lmmqTSVEEZv3XZbjEUW1Q3XpE,1480
26
26
  zrb/builtin/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -346,7 +346,7 @@ zrb/task/base_trigger.py,sha256=WSGcmBcGAZw8EzUXfmCjqJQkz8GEmi1RzogpF6A1V4s,6902
346
346
  zrb/task/cmd_task.py,sha256=myM8WZm6NrUD-Wv0Vb5sTOrutrAVZLt5LVsSBKwX6SM,10860
347
347
  zrb/task/http_check.py,sha256=Gf5rOB2Se2EdizuN9rp65HpGmfZkGc-clIAlHmPVehs,2565
348
348
  zrb/task/llm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
349
- zrb/task/llm/agent.py,sha256=DyGPPndidemXkYWrfgsGW8uC26mghuqbAv2G1ETjqAA,8472
349
+ zrb/task/llm/agent.py,sha256=miQMF7NMFsPEuAp5gTh1kAAEGxgYfLb4uoDU7FL83Go,8645
350
350
  zrb/task/llm/config.py,sha256=n1SPmwab09K2i1sL_OCwrEOWHI0Owx_hvWelg3Dreus,3781
351
351
  zrb/task/llm/conversation_history.py,sha256=B_PDWYL_q66s0xwWBzMSomqPN6u3gkXlIeXBD5A0Apg,4416
352
352
  zrb/task/llm/conversation_history_model.py,sha256=DJ0KDBB0BriQuE5ugC_q0aSHhjNIBcfjUk1f0S_3I9U,9245
@@ -354,12 +354,12 @@ zrb/task/llm/default_workflow/coding.md,sha256=2uythvPsnBpYfIhiIH1cCinQXX0i0yUqs
354
354
  zrb/task/llm/default_workflow/copywriting.md,sha256=xSO7GeDolwGxiuz6kXsK2GKGpwp8UgtG0yRqTmill_s,1999
355
355
  zrb/task/llm/default_workflow/researching.md,sha256=KD-aYHFHir6Ti-4FsBBtGwiI0seSVgleYbKJZi_POXA,2139
356
356
  zrb/task/llm/error.py,sha256=QR-nIohS6pBpC_16cWR-fw7Mevo1sNYAiXMBsh_CJDE,4157
357
- zrb/task/llm/history_summarization.py,sha256=YaK3BR7gJVi9f8G5loosNAaO4y7K3ck_4bJ9GuOChXk,8028
358
- zrb/task/llm/print_node.py,sha256=BlIccGqMeKSLI7QGCVKtmUyi4-B64Mn4wzWj1Dbtl4o,4467
357
+ zrb/task/llm/history_summarization.py,sha256=uW8JxCPks0RjTmCsr8AzrVnqenw4vi_WyVprOqMgAOk,8109
358
+ zrb/task/llm/print_node.py,sha256=Sd8ovTO6KKI9hllZf5TxRXog7QGCne1A1E83jnrH_kg,6526
359
359
  zrb/task/llm/prompt.py,sha256=FGXWYHecWtrNNkPnjg-uhnkqp7fYt8V91-AjFM_5fpA,11550
360
- zrb/task/llm/tool_wrapper.py,sha256=AevU5cY8ztBE-HS27XBefouvP7JK44rau7z0e79vOWo,8352
360
+ zrb/task/llm/tool_wrapper.py,sha256=76h5fcPL3hlXlwYk2aqLqyKPJO1rABUGkBEAGAnWyfQ,9531
361
361
  zrb/task/llm/typing.py,sha256=c8VAuPBw_4A3DxfYdydkgedaP-LU61W9_wj3m3CAX1E,58
362
- zrb/task/llm_task.py,sha256=aIo4pHaV2LV4E5E0aCDry7pwKKAvb78Saq5vgEc6t9Q,14449
362
+ zrb/task/llm_task.py,sha256=aweruBmC09RCKNGmiwLo7WVSttCUH2h2RkSfgUGvRFo,14450
363
363
  zrb/task/make_task.py,sha256=PD3b_aYazthS8LHeJsLAhwKDEgdurQZpymJDKeN60u0,2265
364
364
  zrb/task/rsync_task.py,sha256=WfqNSaicJgYWpunNU34eYxXDqHDHOftuDHyWJKjqwg0,6365
365
365
  zrb/task/scaffolder.py,sha256=rME18w1HJUHXgi9eTYXx_T2G4JdqDYzBoNOkdOOo5-o,6806
@@ -372,6 +372,7 @@ zrb/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
372
372
  zrb/util/attr.py,sha256=5GlYSmVAzbcSFjNDXiqqHqNMR6NWjJ6bUHZXdE35mj8,5359
373
373
  zrb/util/callable.py,sha256=b6OFXbCXp2twow3wh2E_h5hNHLs2pXaLfGQz4iVyiQc,771
374
374
  zrb/util/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
375
+ zrb/util/cli/markdown.py,sha256=Uhuw8XR-jAG9AG3oNK8VHJpYOdU40Q_8yVN74uu0RJ8,384
375
376
  zrb/util/cli/style.py,sha256=D_548KG1gXEirQGdkAVTc81vBdCeInXtnG1gV1yabBA,6655
376
377
  zrb/util/cli/subcommand.py,sha256=umTZIlrL-9g-qc_eRRgdaQgK-whvXK1roFfvnbuY7NQ,1753
377
378
  zrb/util/cmd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -406,7 +407,7 @@ zrb/util/todo.py,sha256=r9_KYF2-hLKMNjsp6AFK9zivykMrywd-kJ4bCwfdafI,19323
406
407
  zrb/util/todo_model.py,sha256=hhzAX-uFl5rsg7iVX1ULlJOfBtblwQ_ieNUxBWfc-Os,1670
407
408
  zrb/xcom/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
408
409
  zrb/xcom/xcom.py,sha256=o79rxR9wphnShrcIushA0Qt71d_p3ZTxjNf7x9hJB78,1571
409
- zrb-1.15.3.dist-info/METADATA,sha256=dvXTlDqIDrLqzZarWVexy1OLJ-W2ufWqptdARc1DBig,9807
410
- zrb-1.15.3.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
411
- zrb-1.15.3.dist-info/entry_points.txt,sha256=-Pg3ElWPfnaSM-XvXqCxEAa-wfVI6BEgcs386s8C8v8,46
412
- zrb-1.15.3.dist-info/RECORD,,
410
+ zrb-1.15.5.dist-info/METADATA,sha256=NkG_9a5y03ASTFHhYSwdi1ksrh0I1aA9fXI1y871PXI,9735
411
+ zrb-1.15.5.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
412
+ zrb-1.15.5.dist-info/entry_points.txt,sha256=-Pg3ElWPfnaSM-XvXqCxEAa-wfVI6BEgcs386s8C8v8,46
413
+ zrb-1.15.5.dist-info/RECORD,,
File without changes