zrb 1.15.2__py3-none-any.whl → 1.15.3__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.
@@ -34,7 +34,7 @@ async def read_user_prompt(ctx: AnyContext) -> str:
34
34
  # Get user input based on mode
35
35
  if not multiline_mode:
36
36
  ctx.print("💬 >>", plain=True)
37
- user_input = await _read_next_line(is_tty, reader, ctx)
37
+ user_input = await _read_next_line(reader, ctx)
38
38
  if not multiline_mode:
39
39
  ctx.print("", plain=True)
40
40
  # Handle user input
@@ -111,6 +111,7 @@ def _show_info(ctx: AnyContext):
111
111
  ),
112
112
  plain=True,
113
113
  )
114
+ ctx.print("", plain=True)
114
115
 
115
116
 
116
117
  def _show_command(command: str, description: str) -> str:
@@ -157,9 +158,11 @@ async def _setup_input_reader(is_interactive: bool):
157
158
  return reader
158
159
 
159
160
 
160
- async def _read_next_line(is_interactive: bool, reader, ctx: AnyContext) -> str:
161
+ async def _read_next_line(reader, ctx: AnyContext) -> str:
161
162
  """Reads one line of input using the provided reader."""
162
- if is_interactive:
163
+ from prompt_toolkit import PromptSession
164
+
165
+ if isinstance(reader, PromptSession):
163
166
  return await reader.prompt_async()
164
167
 
165
168
  line_bytes = await reader.readline()
@@ -19,10 +19,10 @@ async def print_node(print_func: Callable, agent_run: Any, node: Any):
19
19
  )
20
20
 
21
21
  if Agent.is_user_prompt_node(node):
22
- print_func(stylize_faint("🔠 Receiving input..."))
22
+ print_func(stylize_faint(" 🔠 Receiving input..."))
23
23
  elif Agent.is_model_request_node(node):
24
24
  # A model request node => We can stream tokens from the model's request
25
- print_func(stylize_faint("🧠 Processing..."))
25
+ print_func(stylize_faint(" 🧠 Processing..."))
26
26
  # Reference: https://ai.pydantic.dev/agents/#streaming
27
27
  async with node.stream(agent_run.ctx) as request_stream:
28
28
  is_streaming = False
@@ -30,9 +30,8 @@ async def print_node(print_func: Callable, agent_run: Any, node: Any):
30
30
  if isinstance(event, PartStartEvent) and event.part:
31
31
  if is_streaming:
32
32
  print_func("")
33
- print_func(
34
- stylize_faint(f" Starting part {event.index}: {event.part}"),
35
- )
33
+ content = _get_event_part_content(event)
34
+ print_func(stylize_faint(f" {content}"), end="")
36
35
  is_streaming = False
37
36
  elif isinstance(event, PartDeltaEvent):
38
37
  if isinstance(event.delta, TextPartDelta) or isinstance(
@@ -52,14 +51,14 @@ async def print_node(print_func: Callable, agent_run: Any, node: Any):
52
51
  if is_streaming:
53
52
  print_func("")
54
53
  print_func(
55
- stylize_faint(f" Result: tool_name={event.tool_name}"),
54
+ stylize_faint(f" Result: tool_name={event.tool_name}"),
56
55
  )
57
56
  is_streaming = False
58
57
  if is_streaming:
59
58
  print_func("")
60
59
  elif Agent.is_call_tools_node(node):
61
60
  # A handle-response node => The model returned some data, potentially calls a tool
62
- print_func(stylize_faint("🧰 Calling Tool..."))
61
+ print_func(stylize_faint(" 🧰 Calling Tool..."))
63
62
  async with node.stream(agent_run.ctx) as handle_stream:
64
63
  async for event in handle_stream:
65
64
  if isinstance(event, FunctionToolCallEvent):
@@ -79,16 +78,24 @@ async def print_node(print_func: Callable, agent_run: Any, node: Any):
79
78
  del event.part.args["_dummy"]
80
79
  print_func(
81
80
  stylize_faint(
82
- f" {event.part.tool_call_id} | "
81
+ f" {event.part.tool_call_id} | "
83
82
  f"Call {event.part.tool_name} {event.part.args}"
84
83
  )
85
84
  )
86
85
  elif isinstance(event, FunctionToolResultEvent):
87
86
  print_func(
88
87
  stylize_faint(
89
- f" {event.tool_call_id} | {event.result.content}"
88
+ f" {event.tool_call_id} | {event.result.content}"
90
89
  )
91
90
  )
92
91
  elif Agent.is_end_node(node):
93
92
  # Once an End node is reached, the agent run is complete
94
- print_func(stylize_faint("✅ Completed..."))
93
+ print_func(stylize_faint(" ✅ Completed..."))
94
+
95
+
96
+ def _get_event_part_content(event: Any) -> str:
97
+ if not hasattr(event, "part"):
98
+ return f"{event}"
99
+ if not hasattr(event.part, "content"):
100
+ return f"{event.part}"
101
+ return getattr(event.part, "content")
zrb/task/llm/prompt.py CHANGED
@@ -93,28 +93,54 @@ def get_workflow_prompt(
93
93
  modes_attr: StrListAttr | None,
94
94
  render_modes: bool,
95
95
  ) -> str:
96
- modes = get_modes(ctx, modes_attr, render_modes)
96
+ builtin_workflow_dir = os.path.join(os.path.dirname(__file__), "default_workflow")
97
+ modes = set(get_modes(ctx, modes_attr, render_modes))
98
+
97
99
  # Get user-defined workflows
98
100
  workflows = {
99
101
  workflow_name.strip().lower(): content
100
102
  for workflow_name, content in llm_context_config.get_workflows().items()
101
103
  if workflow_name.strip().lower() in modes
102
104
  }
103
- # Get requested builtin-workflow names
105
+
106
+ # Get available builtin workflow names from the file system
107
+ available_builtin_workflow_names = set()
108
+ try:
109
+ for filename in os.listdir(builtin_workflow_dir):
110
+ if filename.endswith(".md"):
111
+ available_builtin_workflow_names.add(filename[:-3].lower())
112
+ except FileNotFoundError:
113
+ # Handle case where the directory might not exist
114
+ ctx.log_error(
115
+ f"Warning: Default workflow directory not found at {builtin_workflow_dir}"
116
+ )
117
+ except Exception as e:
118
+ # Catch other potential errors during directory listing
119
+ ctx.log_error(f"Error listing default workflows: {e}")
120
+
121
+ # Determine which builtin workflows are requested and not already loaded
104
122
  requested_builtin_workflow_names = [
105
- workflow_name.lower()
106
- for workflow_name in ("coding", "copywriting", "researching")
107
- if workflow_name.lower() in modes and workflow_name.lower() not in workflows
123
+ workflow_name
124
+ for workflow_name in available_builtin_workflow_names
125
+ if workflow_name in modes and workflow_name not in workflows
108
126
  ]
109
- # add builtin-workflows if requested
127
+
128
+ # Add builtin-workflows if requested
110
129
  if len(requested_builtin_workflow_names) > 0:
111
- dir_path = os.path.dirname(__file__)
112
130
  for workflow_name in requested_builtin_workflow_names:
113
131
  workflow_file_path = os.path.join(
114
- dir_path, "default_workflow", f"{workflow_name}.md"
132
+ builtin_workflow_dir, f"{workflow_name}.md"
115
133
  )
116
- with open(workflow_file_path, "r") as f:
117
- workflows[workflow_name] = f.read()
134
+ try:
135
+ with open(workflow_file_path, "r") as f:
136
+ workflows[workflow_name] = f.read()
137
+ except FileNotFoundError:
138
+ ctx.log_error(
139
+ f"Warning: Builtin workflow file not found: {workflow_file_path}"
140
+ )
141
+ except Exception as e:
142
+ ctx.log_error(f"Error reading builtin workflow {workflow_name}: {e}")
143
+
118
144
  return "\n".join(
119
145
  [
120
146
  make_prompt_section(header.capitalize(), content)
@@ -123,7 +123,7 @@ def _create_wrapper(
123
123
 
124
124
 
125
125
  async def _ask_for_approval(
126
- ctx: AnyContext, func: Callable, args: list[Any], kwargs: dict[Any]
126
+ ctx: AnyContext, func: Callable, args: list[Any], kwargs: dict[str, Any]
127
127
  ) -> tuple[bool, str]:
128
128
  func_name = get_callable_name(func)
129
129
  normalized_args = [stylize_green(_truncate_arg(arg)) for arg in args]
@@ -139,9 +139,11 @@ async def _ask_for_approval(
139
139
  )
140
140
  while True:
141
141
  ctx.print(
142
- f"✅ >> Allow to run tool: {func_call_str} (Yes | No, <reason>)", plain=True
142
+ f"\n✅ >> Allow to run tool: {func_call_str} (Yes | No, <reason>) ",
143
+ plain=True,
143
144
  )
144
145
  user_input = await _read_line()
146
+ ctx.print("", plain=True)
145
147
  user_responses = [val.strip() for val in user_input.split(",", maxsplit=1)]
146
148
  while len(user_responses) < 2:
147
149
  user_responses.append("")
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.")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: zrb
3
- Version: 1.15.2
3
+ Version: 1.15.3
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
@@ -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=syMOQzAGcRmxs7ctrBkfvAZ7-IhxnywuxuyeoBMteEs,10464
12
+ zrb/builtin/llm/chat_session.py,sha256=gAn04kxT7YmqFCqxamFhV2W3Duq5z8z6jYaOmVxa5yc,10529
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
@@ -355,11 +355,11 @@ zrb/task/llm/default_workflow/copywriting.md,sha256=xSO7GeDolwGxiuz6kXsK2GKGpwp8
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
357
  zrb/task/llm/history_summarization.py,sha256=YaK3BR7gJVi9f8G5loosNAaO4y7K3ck_4bJ9GuOChXk,8028
358
- zrb/task/llm/print_node.py,sha256=Z6J1n024MkYIeO4xGnDHmUHk9yTjJRVZRxAC5schE7w,4242
359
- zrb/task/llm/prompt.py,sha256=amFd0UdXDToYgjOwOFDe62EOg81VvjHvdp9omX1NIgg,10530
360
- zrb/task/llm/tool_wrapper.py,sha256=kmpixQUFq4Hxj9VMgaaoZd8juzTFou9hIGjU7gZENYs,8297
358
+ zrb/task/llm/print_node.py,sha256=BlIccGqMeKSLI7QGCVKtmUyi4-B64Mn4wzWj1Dbtl4o,4467
359
+ zrb/task/llm/prompt.py,sha256=FGXWYHecWtrNNkPnjg-uhnkqp7fYt8V91-AjFM_5fpA,11550
360
+ zrb/task/llm/tool_wrapper.py,sha256=AevU5cY8ztBE-HS27XBefouvP7JK44rau7z0e79vOWo,8352
361
361
  zrb/task/llm/typing.py,sha256=c8VAuPBw_4A3DxfYdydkgedaP-LU61W9_wj3m3CAX1E,58
362
- zrb/task/llm_task.py,sha256=1yPs9z8nhA9txMJVQZf3N4e-n6wys0nZ9Qk1lOx8PLg,14448
362
+ zrb/task/llm_task.py,sha256=aIo4pHaV2LV4E5E0aCDry7pwKKAvb78Saq5vgEc6t9Q,14449
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
@@ -406,7 +406,7 @@ zrb/util/todo.py,sha256=r9_KYF2-hLKMNjsp6AFK9zivykMrywd-kJ4bCwfdafI,19323
406
406
  zrb/util/todo_model.py,sha256=hhzAX-uFl5rsg7iVX1ULlJOfBtblwQ_ieNUxBWfc-Os,1670
407
407
  zrb/xcom/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
408
408
  zrb/xcom/xcom.py,sha256=o79rxR9wphnShrcIushA0Qt71d_p3ZTxjNf7x9hJB78,1571
409
- zrb-1.15.2.dist-info/METADATA,sha256=DGTvAoTQ6gl-buYjg9juPnZha4qwYckW6-7UmfG_0pY,9807
410
- zrb-1.15.2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
411
- zrb-1.15.2.dist-info/entry_points.txt,sha256=-Pg3ElWPfnaSM-XvXqCxEAa-wfVI6BEgcs386s8C8v8,46
412
- zrb-1.15.2.dist-info/RECORD,,
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,,
File without changes