zrb 1.15.19__py3-none-any.whl → 1.15.21__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.
@@ -32,6 +32,26 @@ from zrb.task.base_trigger import BaseTrigger
32
32
  from zrb.task.llm_task import LLMTask
33
33
  from zrb.util.string.conversion import to_boolean
34
34
 
35
+
36
+ def _get_default_yolo_mode(ctx: AnyContext) -> str:
37
+ default_value = llm_config.default_yolo_mode
38
+ if isinstance(default_value, list):
39
+ return ",".join(default_value)
40
+ return f"{default_value}"
41
+
42
+
43
+ def _render_yolo_mode_input(ctx: AnyContext) -> list[str] | bool | None:
44
+ if ctx.input.yolo.strip() == "":
45
+ return None
46
+ elements = ctx.input.yolo.split(",")
47
+ if len(elements) == 0:
48
+ try:
49
+ return to_boolean(elements[0])
50
+ except Exception:
51
+ pass
52
+ return elements
53
+
54
+
35
55
  _llm_ask_inputs = [
36
56
  StrInput(
37
57
  "model",
@@ -88,7 +108,7 @@ _llm_ask_inputs = [
88
108
  "yolo",
89
109
  description="YOLO mode (LLM Agent will start in YOLO Mode)",
90
110
  prompt="YOLO mode (LLM Agent will start in YOLO Mode)",
91
- default=lambda ctx: llm_config.default_yolo_mode,
111
+ default=_get_default_yolo_mode,
92
112
  allow_positional_parsing=False,
93
113
  always_prompt=False,
94
114
  ),
@@ -103,19 +123,6 @@ _llm_ask_inputs = [
103
123
  ),
104
124
  ]
105
125
 
106
-
107
- def _render_yolo_mode_input(ctx: AnyContext) -> list[str] | bool | None:
108
- if ctx.input.yolo.strip() == "":
109
- return None
110
- elements = ctx.input.yolo.split(",")
111
- if len(elements) == 0:
112
- try:
113
- return to_boolean(elements[0])
114
- except Exception:
115
- pass
116
- return elements
117
-
118
-
119
126
  llm_ask: LLMTask = llm_group.add_task(
120
127
  LLMTask(
121
128
  name="llm-ask",
@@ -1,8 +1,7 @@
1
- import json
2
1
  from typing import Literal
3
2
 
4
3
 
5
- def get_current_location() -> str:
4
+ def get_current_location() -> dict[str, float]:
6
5
  """
7
6
  Fetches the user's current geographical location based on their IP address.
8
7
 
@@ -11,8 +10,9 @@ def get_current_location() -> str:
11
10
  answered.
12
11
 
13
12
  Returns:
14
- str: A JSON string containing the 'lat' and 'lon' of the current
15
- location. Example: '{"lat": 48.8584, "lon": 2.2945}'
13
+ dict[str, float]: A dictionary containing the 'lat' and 'lon' of the current
14
+ location.
15
+ Example: {"lat": 48.8584, "lon": 2.2945}
16
16
  Raises:
17
17
  requests.RequestException: If the API request to the location service
18
18
  fails.
@@ -22,7 +22,7 @@ def get_current_location() -> str:
22
22
  try:
23
23
  response = requests.get("http://ip-api.com/json?fields=lat,lon", timeout=5)
24
24
  response.raise_for_status()
25
- return json.dumps(response.json())
25
+ return dict(response.json())
26
26
  except requests.RequestException as e:
27
27
  raise requests.RequestException(f"Failed to get location: {e}") from None
28
28
 
@@ -46,7 +46,7 @@ def get_current_weather(
46
46
  for the temperature reading.
47
47
 
48
48
  Returns:
49
- str: A JSON string containing detailed weather data, including
49
+ dict[str, Any]: A dictionary containing detailed weather data, including
50
50
  temperature, wind speed, and weather code.
51
51
  Raises:
52
52
  requests.RequestException: If the API request to the weather service
@@ -66,6 +66,6 @@ def get_current_weather(
66
66
  timeout=5,
67
67
  )
68
68
  response.raise_for_status()
69
- return json.dumps(response.json())
69
+ return dict(response.json())
70
70
  except requests.RequestException as e:
71
71
  raise requests.RequestException(f"Failed to get weather data: {e}") from None
@@ -1,4 +1,3 @@
1
- import json
2
1
  import subprocess
3
2
 
4
3
 
@@ -19,7 +18,7 @@ def run_shell_command(command: str) -> str:
19
18
  command (str): The exact shell command to execute.
20
19
 
21
20
  Returns:
22
- str: A JSON string containing return code, standard output (stdout),
21
+ dict[str, Any]: A dictionary containing return code, standard output (stdout),
23
22
  and standard error (stderr) from the command.
24
23
  Example: {"return_code": 0, "stdout": "ok", "stderr": ""}
25
24
  """
@@ -29,10 +28,8 @@ def run_shell_command(command: str) -> str:
29
28
  capture_output=True,
30
29
  text=True,
31
30
  )
32
- return json.dumps(
33
- {
34
- "return_code": result.returncode,
35
- "stdout": result.stdout,
36
- "stderr": result.stderr,
37
- }
38
- )
31
+ return {
32
+ "return_code": result.returncode,
33
+ "stdout": result.stdout,
34
+ "stderr": result.stderr,
35
+ }
@@ -223,35 +223,42 @@ def read_from_file(
223
223
  end_line: Optional[int] = None,
224
224
  ) -> str:
225
225
  """
226
- Reads the content of a file, optionally from a specific start line to an
227
- end line.
228
-
229
- This tool is essential for inspecting file contents. It can read both text
230
- and PDF files. The returned content is prefixed with line numbers, which is
231
- crucial for providing context when you need to modify the file later with
232
- the `apply_diff` tool.
233
-
234
- Use this tool to:
235
- - Examine the source code of a file.
236
- - Read configuration files.
237
- - Check the contents of a document.
238
-
239
- Args:
240
- path (str): The path to the file to read.
241
- start_line (int, optional): The 1-based line number to start reading
242
- from. If omitted, reading starts from the beginning of the file.
243
- end_line (int, optional): The 1-based line number to stop reading at
244
- (inclusive). If omitted, reads to the end of the file.
245
-
246
- Returns:
247
- str: A JSON object containing the file path, the requested content
248
- with line numbers, the start and end lines, and the total number
249
- of lines in the file.
250
- Example: '{"path": "src/main.py", "content": "1| import os\n2|
251
- 3| print(\"Hello, World!\")", "start_line": 1, "end_line": 3,
252
- "total_lines": 3}'
253
- Raises:
254
- FileNotFoundError: If the specified file does not exist.
226
+ Reads the content of a file, optionally from a specific start line to an
227
+ end line.
228
+
229
+ This tool is essential for inspecting file contents. It can read both text
230
+ and PDF files. The returned content is prefixed with line numbers, which is
231
+ crucial for providing context when you need to modify the file later with
232
+ the `apply_diff` tool.
233
+
234
+ Use this tool to:
235
+ - Examine the source code of a file.
236
+ - Read configuration files.
237
+ - Check the contents of a document.
238
+
239
+ Args:
240
+ path (str): The path to the file to read.
241
+ start_line (int, optional): The 1-based line number to start reading
242
+ from. If omitted, reading starts from the beginning of the file.
243
+ end_line (int, optional): The 1-based line number to stop reading at
244
+ (inclusive). If omitted, reads to the end of the file.
245
+
246
+ Returns:
247
+ str: A JSON string containing the file path, the requested content
248
+ with line numbers, the start and end lines, and the total number
249
+ of lines in the file.
250
+ Example:
251
+ ```
252
+ {
253
+ "path": "src/main.py",
254
+ "content": "1| import os\n2|3| print(\"Hello, World!\")",
255
+ "start_line": 1,
256
+ "end_line": 3,
257
+ "total_lines": 3
258
+ }
259
+ ```
260
+ Raises:
261
+ FileNotFoundError: If the specified file does not exist.
255
262
  """
256
263
 
257
264
  abs_path = os.path.abspath(os.path.expanduser(path))
@@ -309,7 +316,7 @@ def write_to_file(
309
316
  Do not use partial content or omit any lines.
310
317
 
311
318
  Returns:
312
- str: A JSON object indicating success or failure.
319
+ dict[str, Any]: A dictionary indicating success or failure.
313
320
  Example: '{"success": true, "path": "new_file.txt"}'
314
321
  """
315
322
  try:
@@ -319,8 +326,7 @@ def write_to_file(
319
326
  if directory and not os.path.exists(directory):
320
327
  os.makedirs(directory, exist_ok=True)
321
328
  write_file(abs_path, content)
322
- result_data = {"success": True, "path": path}
323
- return json.dumps(result_data)
329
+ return {"success": True, "path": path}
324
330
  except (OSError, IOError) as e:
325
331
  raise OSError(f"Error writing file {path}: {e}")
326
332
  except Exception as e:
@@ -352,7 +358,7 @@ def search_files(
352
358
  hidden files and directories. Defaults to True.
353
359
 
354
360
  Returns:
355
- str: A JSON object containing a summary of the search and a list of
361
+ dict[str, Any]: A dictionary containing a summary of the search and a list of
356
362
  results. Each result includes the file path and a list of matches,
357
363
  with each match showing the line number, line content, and a few
358
364
  lines of context from before and after the match.
@@ -404,9 +410,7 @@ def search_files(
404
410
  f"Found {match_count} matches in {file_match_count} files "
405
411
  f"(searched {searched_file_count} files)."
406
412
  )
407
- return json.dumps(
408
- search_results
409
- ) # No need for pretty printing for LLM consumption
413
+ return search_results
410
414
  except (OSError, IOError) as e:
411
415
  raise OSError(f"Error searching files in {path}: {e}")
412
416
  except Exception as e:
@@ -467,7 +471,7 @@ def replace_in_file(
467
471
  new_string (str): The new string that will replace the `old_string`.
468
472
 
469
473
  Returns:
470
- str: A JSON object indicating the success or failure of the operation.
474
+ dict[str, Any]: A dictionary indicating the success or failure of the operation.
471
475
  Raises:
472
476
  FileNotFoundError: If the specified file does not exist.
473
477
  ValueError: If the `old_string` is not found in the file.
@@ -481,7 +485,7 @@ def replace_in_file(
481
485
  raise ValueError(f"old_string not found in file: {path}")
482
486
  new_content = content.replace(old_string, new_string, 1)
483
487
  write_file(abs_path, new_content)
484
- return json.dumps({"success": True, "path": path})
488
+ return {"success": True, "path": path}
485
489
  except ValueError as e:
486
490
  raise e
487
491
  except (OSError, IOError) as e:
@@ -564,11 +568,10 @@ def read_many_files(paths: list[str]) -> str:
564
568
  if you are unsure about the exact file locations.
565
569
 
566
570
  Returns:
567
- str: A JSON object where keys are the file paths and values are their
568
- corresponding contents, prefixed with line numbers. If a file
569
- cannot be read, its value will be an error message.
570
- Example: '{"results": {"src/api.py": "1| import ...",
571
- "config.yaml": "1| key: value"}}'
571
+ dict[str, str]: a dictionary where keys are the file paths and values
572
+ are their corresponding contents, prefixed with line numbers.
573
+ If a file cannot be read, its value will be an error message.
574
+ Example: {"src/api.py": "1| import ...", "config.yaml": "1| key: value"}
572
575
  """
573
576
  results = {}
574
577
  for path in paths:
@@ -580,7 +583,7 @@ def read_many_files(paths: list[str]) -> str:
580
583
  results[path] = content
581
584
  except Exception as e:
582
585
  results[path] = f"Error reading file: {e}"
583
- return json.dumps({"results": results})
586
+ return results
584
587
 
585
588
 
586
589
  def write_many_files(files: list[FileToWrite]) -> str:
@@ -601,10 +604,10 @@ def write_many_files(files: list[FileToWrite]) -> str:
601
604
  containing a 'path' and the complete 'content'.
602
605
 
603
606
  Returns:
604
- str: A JSON object summarizing the operation, listing successfully
607
+ str: A dictionary summarizing the operation, listing successfully
605
608
  written files and any files that failed, along with corresponding
606
609
  error messages.
607
- Example: '{"success": ["file1.py", "file2.txt"], "errors": {}}'
610
+ Example: {"success": ["file1.py", "file2.txt"], "errors": {}}
608
611
  """
609
612
  success = []
610
613
  errors = {}
@@ -623,4 +626,4 @@ def write_many_files(files: list[FileToWrite]) -> str:
623
626
  success.append(path)
624
627
  except Exception as e:
625
628
  errors[path] = f"Error writing file: {e}"
626
- return json.dumps({"success": success, "errors": errors})
629
+ return {"success": success, "errors": errors}
@@ -201,7 +201,7 @@ def create_rag_from_directory(
201
201
  query_embeddings=query_vector,
202
202
  n_results=max_result_count_val,
203
203
  )
204
- return json.dumps(results)
204
+ return dict(results)
205
205
 
206
206
  retrieve.__name__ = tool_name
207
207
  retrieve.__doc__ = dedent(
@@ -210,7 +210,7 @@ def create_rag_from_directory(
210
210
  Args:
211
211
  query (str): The user query to search for in documents.
212
212
  Returns:
213
- str: JSON string with search results: {{"ids": [...], "documents": [...], ...}}
213
+ str: dictionary with search results: {{"ids": [...], "documents": [...], ...}}
214
214
  """
215
215
  ).strip()
216
216
  return retrieve
@@ -2,6 +2,8 @@ import json
2
2
  from collections.abc import Callable
3
3
  from urllib.parse import urljoin
4
4
 
5
+ _DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" # noqa
6
+
5
7
 
6
8
  async def open_web_page(url: str) -> str:
7
9
  """
@@ -18,7 +20,7 @@ async def open_web_page(url: str) -> str:
18
20
  "https://example.com/article").
19
21
 
20
22
  Returns:
21
- str: A JSON object containing the page's content in Markdown format
23
+ str: A JSON string containing the page's content in Markdown format
22
24
  and a list of all absolute links found on the page.
23
25
  """
24
26
  html_content, links = await _fetch_page_content(url)
@@ -47,22 +49,22 @@ def create_search_internet_tool(serp_api_key: str) -> Callable[[str, int], str]:
47
49
  """
48
50
  Performs an internet search using Google and returns a summary of the results.
49
51
 
50
- Use this tool to find information on the web, answer general knowledge questions, or research topics.
52
+ Use this tool to find information on the web, answer general knowledge questions,
53
+ or research topics.
51
54
 
52
55
  Args:
53
56
  query (str): The search query.
54
57
  num_results (int, optional): The desired number of search results. Defaults to 10.
55
58
 
56
59
  Returns:
57
- str: A formatted string summarizing the search results, including titles, links, and snippets.
60
+ str: A formatted string summarizing the search results,
61
+ including titles, links, and snippets.
58
62
  """
59
63
  import requests
60
64
 
61
65
  response = requests.get(
62
66
  "https://serpapi.com/search",
63
- headers={
64
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
65
- },
67
+ headers={"User-Agent": _DEFAULT_USER_AGENT},
66
68
  params={
67
69
  "q": query,
68
70
  "num": num_results,
@@ -73,7 +75,7 @@ def create_search_internet_tool(serp_api_key: str) -> Callable[[str, int], str]:
73
75
  )
74
76
  if response.status_code != 200:
75
77
  raise Exception(
76
- f"Error: Unable to retrieve search results (status code: {response.status_code})"
78
+ f"Error: Unable to retrieve search results (status code: {response.status_code})" # noqa
77
79
  )
78
80
  return response.json()
79
81
 
@@ -100,9 +102,7 @@ def search_wikipedia(query: str) -> str:
100
102
  params = {"action": "query", "list": "search", "srsearch": query, "format": "json"}
101
103
  response = requests.get(
102
104
  "https://en.wikipedia.org/w/api.php",
103
- headers={
104
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
105
- },
105
+ headers={"User-Agent": _DEFAULT_USER_AGENT},
106
106
  params=params,
107
107
  )
108
108
  return response.json()
@@ -131,9 +131,7 @@ def search_arxiv(query: str, num_results: int = 10) -> str:
131
131
  params = {"search_query": f"all:{query}", "start": 0, "max_results": num_results}
132
132
  response = requests.get(
133
133
  "http://export.arxiv.org/api/query",
134
- headers={
135
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
136
- },
134
+ headers={"User-Agent": _DEFAULT_USER_AGENT},
137
135
  params=params,
138
136
  )
139
137
  return response.content
@@ -141,14 +139,13 @@ def search_arxiv(query: str, num_results: int = 10) -> str:
141
139
 
142
140
  async def _fetch_page_content(url: str) -> tuple[str, list[str]]:
143
141
  """Fetches the HTML content and all absolute links from a URL."""
144
- user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
145
142
  try:
146
143
  from playwright.async_api import async_playwright
147
144
 
148
145
  async with async_playwright() as p:
149
146
  browser = await p.chromium.launch(headless=True)
150
147
  page = await browser.new_page()
151
- await page.set_extra_http_headers({"User-Agent": user_agent})
148
+ await page.set_extra_http_headers({"User-Agent": _DEFAULT_USER_AGENT})
152
149
  try:
153
150
  await page.goto(url, wait_until="networkidle", timeout=30000)
154
151
  await page.wait_for_load_state("domcontentloaded")
@@ -176,7 +173,7 @@ async def _fetch_page_content(url: str) -> tuple[str, list[str]]:
176
173
  import requests
177
174
  from bs4 import BeautifulSoup
178
175
 
179
- response = requests.get(url, headers={"User-Agent": user_agent})
176
+ response = requests.get(url, headers={"User-Agent": _DEFAULT_USER_AGENT})
180
177
  if response.status_code != 200:
181
178
  raise Exception(
182
179
  f"Unable to retrieve page content. Status code: {response.status_code}"
@@ -191,7 +191,7 @@ def _get_event_part_args(event: Any) -> Any:
191
191
 
192
192
 
193
193
  def _truncate_kwargs(kwargs: dict[str, Any]) -> dict[str, Any]:
194
- return {key: _truncate_arg(val) for key, val in kwargs.items() if key != "_dummy"}
194
+ return {key: _truncate_arg(val) for key, val in kwargs.items()}
195
195
 
196
196
 
197
197
  def _truncate_arg(arg: str, length: int = 19) -> str:
@@ -108,11 +108,6 @@ def _create_wrapper(
108
108
  # Inject the captured ctx into kwargs. This will overwrite if the LLM
109
109
  # somehow provided it.
110
110
  kwargs[any_context_param_name] = ctx
111
- # If the dummy argument was added for schema generation and is present in kwargs,
112
- # remove it before calling the original function, unless the original function
113
- # actually expects a parameter named '_dummy'.
114
- if "_dummy" in kwargs and "_dummy" not in original_sig.parameters:
115
- del kwargs["_dummy"]
116
111
  try:
117
112
  if not ctx.is_web_mode and ctx.is_tty:
118
113
  if (
@@ -247,22 +242,4 @@ def _adjust_signature(
247
242
  if not _is_annotated_with_context(param.annotation, RunContext)
248
243
  and not _is_annotated_with_context(param.annotation, AnyContext)
249
244
  ]
250
-
251
- # If after removing context parameters, there are no parameters left,
252
- # and the original function took no args, keep the dummy.
253
- # If after removing context parameters, there are no parameters left,
254
- # but the original function *did* take args (only context), then the schema
255
- # should have no parameters.
256
- if not params_for_schema and takes_no_args:
257
- # Keep the dummy if the original function truly had no parameters
258
- new_sig = inspect.Signature(
259
- parameters=[
260
- inspect.Parameter(
261
- "_dummy", inspect.Parameter.POSITIONAL_OR_KEYWORD, default=None
262
- )
263
- ]
264
- )
265
- else:
266
- new_sig = inspect.Signature(parameters=params_for_schema)
267
-
268
- wrapper.__signature__ = new_sig
245
+ wrapper.__signature__ = inspect.Signature(parameters=params_for_schema)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: zrb
3
- Version: 1.15.19
3
+ Version: 1.15.21
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
@@ -12,16 +12,16 @@ zrb/builtin/jwt.py,sha256=3M5uaQhJZbKQLjTUft1OwPz_JxtmK-xtkjxWjciOQho,2859
12
12
  zrb/builtin/llm/chat_session.py,sha256=p0giSVYuQMQ5H1hbQzl7cMb49XZqWG0SF7X-ixB5EBU,10203
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
- zrb/builtin/llm/llm_ask.py,sha256=BuZdQKw4oXCdZyFYr-pKKMKGMG3XDQKa9aaCGOoSsHM,6015
15
+ zrb/builtin/llm/llm_ask.py,sha256=XtnSZoBvwHqnBUi8R0rt8VDfnBmWgwFlDuuo1WA1W_w,6209
16
16
  zrb/builtin/llm/previous-session.js,sha256=xMKZvJoAbrwiyHS0OoPrWuaKxWYLoyR5sguePIoCjTY,816
17
17
  zrb/builtin/llm/tool/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- zrb/builtin/llm/tool/api.py,sha256=vMEiZhhTZ3o2jRBxWcJ62b0M85wd_w4W0X4Hx23NXto,2380
19
- zrb/builtin/llm/tool/cli.py,sha256=8rugrKaNPEatHjr7nN4OIRLRT2TcF-oylEZGbLI9Brs,1254
18
+ zrb/builtin/llm/tool/api.py,sha256=T8NGhBe59sQiu8LfdPOIBmsTNMXWFEKaPPSY9bolsQ8,2401
19
+ zrb/builtin/llm/tool/cli.py,sha256=GCGB8GMFjvVcH0Ac-bD44VG6Bj3mQSuIcNHAwJbx4Ts,1210
20
20
  zrb/builtin/llm/tool/code.py,sha256=fr9FbmtfwizQTyTztvuvwAb9MD_auRZhPZfoJVBlKT4,8777
21
- zrb/builtin/llm/tool/file.py,sha256=eXFGGFxxpdpWGVw0svyQNQc03I5M7wotSsA_HjkXw7c,23670
22
- zrb/builtin/llm/tool/rag.py,sha256=Ab8_ZljnG_zfkwxPezImvorshuz3Fi4CmSzNOtU1a-g,9770
21
+ zrb/builtin/llm/tool/file.py,sha256=FPPvKUZY-w1XEa7EN6D6X4VQoQNQ9ggGWLj-xJt-Ysc,23524
22
+ zrb/builtin/llm/tool/rag.py,sha256=n4ATdr-2gCzPb7LnaBSD_TuAG4TUXKhE9ElKrSDHvFc,9763
23
23
  zrb/builtin/llm/tool/sub_agent.py,sha256=qJTJ2GSH-2Cma2QyHEJm8l_VuDHMHwhAWGls217YA6A,5078
24
- zrb/builtin/llm/tool/web.py,sha256=Hc9ikgBWZMgLB2O5lX-P9k8jvNSZeyUufqHXa_n_v4I,7653
24
+ zrb/builtin/llm/tool/web.py,sha256=2FgmiM2LIQfvMMoswidj9hVMav_t8QPG1LiyedL66dw,7349
25
25
  zrb/builtin/md5.py,sha256=690RV2LbW7wQeTFxY-lmmqTSVEEZv3XZbjEUW1Q3XpE,1480
26
26
  zrb/builtin/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
27
  zrb/builtin/project/add/fastapp/fastapp_input.py,sha256=MKlWR_LxWhM_DcULCtLfL_IjTxpDnDBkn9KIqNmajFs,310
@@ -356,9 +356,9 @@ zrb/task/llm/default_workflow/researching.md,sha256=KD-aYHFHir6Ti-4FsBBtGwiI0seS
356
356
  zrb/task/llm/error.py,sha256=QR-nIohS6pBpC_16cWR-fw7Mevo1sNYAiXMBsh_CJDE,4157
357
357
  zrb/task/llm/history_summarization.py,sha256=UIT8bpdT3hy1xn559waDLFWZlNtIqdIpIvRGcZEpHm0,8057
358
358
  zrb/task/llm/history_summarization_tool.py,sha256=Wazi4WMr3k1WJ1v7QgjAPbuY1JdBpHUsTWGt3DSTsLc,1706
359
- zrb/task/llm/print_node.py,sha256=si619OvCUZJYTUSUpoOqVAgLSu1BGw-dlBq02MSD7FE,8096
359
+ zrb/task/llm/print_node.py,sha256=TG8i3MrAkIj3cLkU9_fSX-u49jlTdU8t9FpHGI_VtoM,8077
360
360
  zrb/task/llm/prompt.py,sha256=FGXWYHecWtrNNkPnjg-uhnkqp7fYt8V91-AjFM_5fpA,11550
361
- zrb/task/llm/tool_wrapper.py,sha256=AsRzVAZtuAMsutLHGetpsPPncu6pcd4LrwxYRZxsp7c,9933
361
+ zrb/task/llm/tool_wrapper.py,sha256=o_CccStYSiEI28nlvgcBEu9VcPefRE1JyPb16_cVFIg,8887
362
362
  zrb/task/llm/typing.py,sha256=c8VAuPBw_4A3DxfYdydkgedaP-LU61W9_wj3m3CAX1E,58
363
363
  zrb/task/llm_task.py,sha256=OxJ9QpqjEyeOI1_zqzNZHtQlRHi0ANOvL9FYaWLzO3Y,14913
364
364
  zrb/task/make_task.py,sha256=PD3b_aYazthS8LHeJsLAhwKDEgdurQZpymJDKeN60u0,2265
@@ -409,7 +409,7 @@ zrb/util/todo_model.py,sha256=hhzAX-uFl5rsg7iVX1ULlJOfBtblwQ_ieNUxBWfc-Os,1670
409
409
  zrb/util/truncate.py,sha256=eSzmjBpc1Qod3lM3M73snNbDOcARHukW_tq36dWdPvc,921
410
410
  zrb/xcom/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
411
411
  zrb/xcom/xcom.py,sha256=o79rxR9wphnShrcIushA0Qt71d_p3ZTxjNf7x9hJB78,1571
412
- zrb-1.15.19.dist-info/METADATA,sha256=xqYaEjMc-itju0TLC9dhhS5WWIHa9nEzYDrJyPcnpns,9892
413
- zrb-1.15.19.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
414
- zrb-1.15.19.dist-info/entry_points.txt,sha256=-Pg3ElWPfnaSM-XvXqCxEAa-wfVI6BEgcs386s8C8v8,46
415
- zrb-1.15.19.dist-info/RECORD,,
412
+ zrb-1.15.21.dist-info/METADATA,sha256=RPXozcJ63UcRxsaQWJlBGjuhGUuAPwXVgJ1o3VKMS7E,9892
413
+ zrb-1.15.21.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
414
+ zrb-1.15.21.dist-info/entry_points.txt,sha256=-Pg3ElWPfnaSM-XvXqCxEAa-wfVI6BEgcs386s8C8v8,46
415
+ zrb-1.15.21.dist-info/RECORD,,
File without changes