zrb 1.13.1__py3-none-any.whl → 1.21.33__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.
Files changed (117) hide show
  1. zrb/__init__.py +2 -6
  2. zrb/attr/type.py +10 -7
  3. zrb/builtin/__init__.py +2 -0
  4. zrb/builtin/git.py +12 -1
  5. zrb/builtin/group.py +31 -15
  6. zrb/builtin/http.py +7 -8
  7. zrb/builtin/llm/attachment.py +40 -0
  8. zrb/builtin/llm/chat_completion.py +287 -0
  9. zrb/builtin/llm/chat_session.py +130 -144
  10. zrb/builtin/llm/chat_session_cmd.py +288 -0
  11. zrb/builtin/llm/chat_trigger.py +78 -0
  12. zrb/builtin/llm/history.py +4 -4
  13. zrb/builtin/llm/llm_ask.py +218 -110
  14. zrb/builtin/llm/tool/api.py +74 -62
  15. zrb/builtin/llm/tool/cli.py +56 -21
  16. zrb/builtin/llm/tool/code.py +57 -47
  17. zrb/builtin/llm/tool/file.py +292 -255
  18. zrb/builtin/llm/tool/note.py +84 -0
  19. zrb/builtin/llm/tool/rag.py +25 -18
  20. zrb/builtin/llm/tool/search/__init__.py +1 -0
  21. zrb/builtin/llm/tool/search/brave.py +66 -0
  22. zrb/builtin/llm/tool/search/searxng.py +61 -0
  23. zrb/builtin/llm/tool/search/serpapi.py +61 -0
  24. zrb/builtin/llm/tool/sub_agent.py +53 -26
  25. zrb/builtin/llm/tool/web.py +94 -157
  26. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_util.py +7 -7
  27. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/add_module_util.py +5 -5
  28. zrb/builtin/project/add/fastapp/fastapp_util.py +1 -1
  29. zrb/builtin/searxng/config/settings.yml +5671 -0
  30. zrb/builtin/searxng/start.py +21 -0
  31. zrb/builtin/setup/latex/ubuntu.py +1 -0
  32. zrb/builtin/setup/ubuntu.py +1 -1
  33. zrb/builtin/shell/autocomplete/bash.py +4 -3
  34. zrb/builtin/shell/autocomplete/zsh.py +4 -3
  35. zrb/config/config.py +297 -79
  36. zrb/config/default_prompt/file_extractor_system_prompt.md +109 -9
  37. zrb/config/default_prompt/interactive_system_prompt.md +25 -28
  38. zrb/config/default_prompt/persona.md +1 -1
  39. zrb/config/default_prompt/repo_extractor_system_prompt.md +31 -31
  40. zrb/config/default_prompt/repo_summarizer_system_prompt.md +27 -8
  41. zrb/config/default_prompt/summarization_prompt.md +57 -16
  42. zrb/config/default_prompt/system_prompt.md +29 -25
  43. zrb/config/llm_config.py +129 -24
  44. zrb/config/llm_context/config.py +127 -90
  45. zrb/config/llm_context/config_parser.py +1 -7
  46. zrb/config/llm_context/workflow.py +81 -0
  47. zrb/config/llm_rate_limitter.py +100 -47
  48. zrb/context/any_shared_context.py +7 -1
  49. zrb/context/context.py +8 -2
  50. zrb/context/shared_context.py +6 -8
  51. zrb/group/any_group.py +12 -5
  52. zrb/group/group.py +67 -3
  53. zrb/input/any_input.py +5 -1
  54. zrb/input/base_input.py +18 -6
  55. zrb/input/option_input.py +13 -1
  56. zrb/input/text_input.py +7 -24
  57. zrb/runner/cli.py +21 -20
  58. zrb/runner/common_util.py +24 -19
  59. zrb/runner/web_route/task_input_api_route.py +5 -5
  60. zrb/runner/web_route/task_session_api_route.py +1 -4
  61. zrb/runner/web_util/user.py +7 -3
  62. zrb/session/any_session.py +12 -6
  63. zrb/session/session.py +39 -18
  64. zrb/task/any_task.py +24 -3
  65. zrb/task/base/context.py +17 -9
  66. zrb/task/base/execution.py +15 -8
  67. zrb/task/base/lifecycle.py +8 -4
  68. zrb/task/base/monitoring.py +12 -7
  69. zrb/task/base_task.py +69 -5
  70. zrb/task/base_trigger.py +12 -5
  71. zrb/task/llm/agent.py +130 -145
  72. zrb/task/llm/agent_runner.py +152 -0
  73. zrb/task/llm/config.py +45 -13
  74. zrb/task/llm/conversation_history.py +110 -29
  75. zrb/task/llm/conversation_history_model.py +4 -179
  76. zrb/task/llm/default_workflow/coding/workflow.md +41 -0
  77. zrb/task/llm/default_workflow/copywriting/workflow.md +68 -0
  78. zrb/task/llm/default_workflow/git/workflow.md +118 -0
  79. zrb/task/llm/default_workflow/golang/workflow.md +128 -0
  80. zrb/task/llm/default_workflow/html-css/workflow.md +135 -0
  81. zrb/task/llm/default_workflow/java/workflow.md +146 -0
  82. zrb/task/llm/default_workflow/javascript/workflow.md +158 -0
  83. zrb/task/llm/default_workflow/python/workflow.md +160 -0
  84. zrb/task/llm/default_workflow/researching/workflow.md +153 -0
  85. zrb/task/llm/default_workflow/rust/workflow.md +162 -0
  86. zrb/task/llm/default_workflow/shell/workflow.md +299 -0
  87. zrb/task/llm/file_replacement.py +206 -0
  88. zrb/task/llm/file_tool_model.py +57 -0
  89. zrb/task/llm/history_processor.py +206 -0
  90. zrb/task/llm/history_summarization.py +2 -192
  91. zrb/task/llm/print_node.py +192 -64
  92. zrb/task/llm/prompt.py +198 -153
  93. zrb/task/llm/subagent_conversation_history.py +41 -0
  94. zrb/task/llm/tool_confirmation_completer.py +41 -0
  95. zrb/task/llm/tool_wrapper.py +216 -55
  96. zrb/task/llm/workflow.py +76 -0
  97. zrb/task/llm_task.py +122 -70
  98. zrb/task/make_task.py +2 -3
  99. zrb/task/rsync_task.py +25 -10
  100. zrb/task/scheduler.py +4 -4
  101. zrb/util/attr.py +54 -39
  102. zrb/util/cli/markdown.py +12 -0
  103. zrb/util/cli/text.py +30 -0
  104. zrb/util/file.py +27 -11
  105. zrb/util/git.py +2 -2
  106. zrb/util/{llm/prompt.py → markdown.py} +2 -3
  107. zrb/util/string/conversion.py +1 -1
  108. zrb/util/truncate.py +23 -0
  109. zrb/util/yaml.py +204 -0
  110. zrb/xcom/xcom.py +10 -0
  111. {zrb-1.13.1.dist-info → zrb-1.21.33.dist-info}/METADATA +40 -20
  112. {zrb-1.13.1.dist-info → zrb-1.21.33.dist-info}/RECORD +114 -83
  113. {zrb-1.13.1.dist-info → zrb-1.21.33.dist-info}/WHEEL +1 -1
  114. zrb/task/llm/default_workflow/coding.md +0 -24
  115. zrb/task/llm/default_workflow/copywriting.md +0 -17
  116. zrb/task/llm/default_workflow/researching.md +0 -18
  117. {zrb-1.13.1.dist-info → zrb-1.21.33.dist-info}/entry_points.txt +0 -0
zrb/task/llm_task.py CHANGED
@@ -3,41 +3,46 @@ from collections.abc import Callable
3
3
  from typing import TYPE_CHECKING, Any
4
4
 
5
5
  from zrb.attr.type import BoolAttr, IntAttr, StrAttr, StrListAttr, fstring
6
- from zrb.config.llm_rate_limitter import LLMRateLimiter
6
+ from zrb.config.llm_rate_limitter import LLMRateLimitter
7
7
  from zrb.context.any_context import AnyContext
8
- from zrb.context.any_shared_context import AnySharedContext
9
8
  from zrb.env.any_env import AnyEnv
10
9
  from zrb.input.any_input import AnyInput
11
10
  from zrb.task.any_task import AnyTask
12
11
  from zrb.task.base_task import BaseTask
13
- from zrb.task.llm.agent import get_agent, run_agent_iteration
12
+ from zrb.task.llm.agent import get_agent
13
+ from zrb.task.llm.agent_runner import run_agent_iteration
14
14
  from zrb.task.llm.config import (
15
15
  get_model,
16
16
  get_model_settings,
17
+ get_yolo_mode,
17
18
  )
18
19
  from zrb.task.llm.conversation_history import (
20
+ inject_conversation_history_notes,
19
21
  read_conversation_history,
20
22
  write_conversation_history,
21
23
  )
22
24
  from zrb.task.llm.conversation_history_model import ConversationHistory
23
- from zrb.task.llm.history_summarization import maybe_summarize_history
25
+ from zrb.task.llm.history_summarization import get_history_summarization_token_threshold
24
26
  from zrb.task.llm.prompt import (
27
+ get_attachments,
25
28
  get_summarization_system_prompt,
26
29
  get_system_and_user_prompt,
27
30
  get_user_message,
28
31
  )
32
+ from zrb.task.llm.subagent_conversation_history import (
33
+ extract_subagent_conversation_history_from_ctx,
34
+ inject_subagent_conversation_history_into_ctx,
35
+ )
36
+ from zrb.task.llm.workflow import load_workflow
29
37
  from zrb.util.cli.style import stylize_faint
30
38
  from zrb.xcom.xcom import Xcom
31
39
 
32
40
  if TYPE_CHECKING:
33
- from pydantic_ai import Agent, Tool
41
+ from pydantic_ai import AbstractToolset, Agent, Tool, UserContent
34
42
  from pydantic_ai.models import Model
35
43
  from pydantic_ai.settings import ModelSettings
36
- from pydantic_ai.toolsets import AbstractToolset
37
44
 
38
45
  ToolOrCallable = Tool | Callable
39
- else:
40
- ToolOrCallable = Any
41
46
 
42
47
 
43
48
  class LLMTask(BaseTask):
@@ -50,60 +55,75 @@ class LLMTask(BaseTask):
50
55
  cli_only: bool = False,
51
56
  input: list[AnyInput | None] | AnyInput | None = None,
52
57
  env: list[AnyEnv | None] | AnyEnv | None = None,
53
- model: (
54
- "Callable[[AnySharedContext], Model | str | fstring] | Model | None"
55
- ) = None,
58
+ model: "Callable[[AnyContext], Model | str | fstring | None] | Model | None" = None,
56
59
  render_model: bool = True,
57
- model_base_url: StrAttr | None = None,
60
+ model_base_url: "Callable[[AnyContext], str | None] | str | None" = None,
58
61
  render_model_base_url: bool = True,
59
- model_api_key: StrAttr | None = None,
62
+ model_api_key: "Callable[[AnyContext], str | None] | str | None" = None,
60
63
  render_model_api_key: bool = True,
61
64
  model_settings: (
62
- "ModelSettings | Callable[[AnySharedContext], ModelSettings] | None"
65
+ "ModelSettings | Callable[[AnyContext], ModelSettings] | None"
66
+ ) = None,
67
+ small_model: (
68
+ "Callable[[AnyContext], Model | str | fstring] | Model | None"
63
69
  ) = None,
64
- agent: "Agent | Callable[[AnySharedContext], Agent] | None" = None,
65
- persona: StrAttr | None = None,
70
+ render_small_model: bool = True,
71
+ small_model_base_url: StrAttr | None = None,
72
+ render_small_model_base_url: bool = True,
73
+ small_model_api_key: StrAttr | None = None,
74
+ render_small_model_api_key: bool = True,
75
+ small_model_settings: (
76
+ "ModelSettings | Callable[[AnyContext], ModelSettings] | None"
77
+ ) = None,
78
+ persona: "Callable[[AnyContext], str | None] | str | None" = None,
66
79
  render_persona: bool = False,
67
- system_prompt: StrAttr | None = None,
80
+ system_prompt: "Callable[[AnyContext], str | None] | str | None" = None,
68
81
  render_system_prompt: bool = False,
69
- special_instruction_prompt: StrAttr | None = None,
82
+ special_instruction_prompt: "Callable[[AnyContext], str | None] | str | None" = None,
70
83
  render_special_instruction_prompt: bool = False,
71
- modes: StrListAttr | None = None,
72
- render_modes: bool = True,
84
+ workflows: StrListAttr | None = None,
85
+ render_workflows: bool = True,
73
86
  message: StrAttr | None = None,
87
+ attachment: "UserContent | list[UserContent] | Callable[[AnyContext], UserContent | list[UserContent]] | None" = None, # noqa
74
88
  render_message: bool = True,
75
89
  tools: (
76
- list["ToolOrCallable"]
77
- | Callable[[AnySharedContext], list["ToolOrCallable"]]
90
+ list["ToolOrCallable"] | Callable[[AnyContext], list["ToolOrCallable"]]
78
91
  ) = [],
79
92
  toolsets: (
80
- list["AbstractToolset[Agent]"] | Callable[[AnySharedContext], list["Tool"]]
93
+ list["AbstractToolset[None] | str"]
94
+ | Callable[[AnyContext], list["AbstractToolset[None] | str"]]
81
95
  ) = [],
82
96
  conversation_history: (
83
97
  ConversationHistory
84
- | Callable[[AnySharedContext], ConversationHistory | dict | list]
98
+ | Callable[[AnyContext], ConversationHistory | dict | list]
85
99
  | dict
86
100
  | list
87
101
  ) = ConversationHistory(),
88
102
  conversation_history_reader: (
89
- Callable[[AnySharedContext], ConversationHistory | dict | list | None]
90
- | None
103
+ Callable[[AnyContext], ConversationHistory | dict | list | None] | None
91
104
  ) = None,
92
105
  conversation_history_writer: (
93
- Callable[[AnySharedContext, ConversationHistory], None] | None
106
+ Callable[[AnyContext, ConversationHistory], None] | None
94
107
  ) = None,
95
108
  conversation_history_file: StrAttr | None = None,
96
109
  render_history_file: bool = True,
97
110
  summarize_history: BoolAttr | None = None,
98
111
  render_summarize_history: bool = True,
99
- summarization_prompt: StrAttr | None = None,
112
+ summarization_prompt: "Callable[[AnyContext], str | None] | str | None" = None,
100
113
  render_summarization_prompt: bool = False,
101
114
  history_summarization_token_threshold: IntAttr | None = None,
102
115
  render_history_summarization_token_threshold: bool = True,
103
- rate_limitter: LLMRateLimiter | None = None,
104
- execute_condition: bool | str | Callable[[AnySharedContext], bool] = True,
116
+ rate_limitter: LLMRateLimitter | None = None,
117
+ execute_condition: bool | str | Callable[[AnyContext], bool] = True,
105
118
  retries: int = 2,
106
119
  retry_period: float = 0,
120
+ yolo_mode: (
121
+ Callable[[AnyContext], list[str] | bool | None]
122
+ | StrListAttr
123
+ | BoolAttr
124
+ | None
125
+ ) = None,
126
+ render_yolo_mode: bool = True,
107
127
  readiness_check: list[AnyTask] | AnyTask | None = None,
108
128
  readiness_check_delay: float = 0.5,
109
129
  readiness_check_period: float = 5,
@@ -114,9 +134,6 @@ class LLMTask(BaseTask):
114
134
  upstream: list[AnyTask] | AnyTask | None = None,
115
135
  fallback: list[AnyTask] | AnyTask | None = None,
116
136
  successor: list[AnyTask] | AnyTask | None = None,
117
- conversation_context: (
118
- dict[str, Any] | Callable[[AnySharedContext], dict[str, Any]] | None
119
- ) = None,
120
137
  ):
121
138
  super().__init__(
122
139
  name=name,
@@ -146,24 +163,30 @@ class LLMTask(BaseTask):
146
163
  self._model_api_key = model_api_key
147
164
  self._render_model_api_key = render_model_api_key
148
165
  self._model_settings = model_settings
149
- self._agent = agent
166
+ self._small_model = small_model
167
+ self._render_small_model = render_small_model
168
+ self._small_model_base_url = small_model_base_url
169
+ self._render_small_model_base_url = render_small_model_base_url
170
+ self._small_model_api_key = small_model_api_key
171
+ self._render_small_model_api_key = render_small_model_api_key
172
+ self._small_model_settings = small_model_settings
150
173
  self._persona = persona
151
174
  self._render_persona = render_persona
152
175
  self._system_prompt = system_prompt
153
176
  self._render_system_prompt = render_system_prompt
154
177
  self._special_instruction_prompt = special_instruction_prompt
155
178
  self._render_special_instruction_prompt = render_special_instruction_prompt
156
- self._modes = modes
157
- self._render_modes = render_modes
179
+ self._workflows = workflows
180
+ self._render_workflows = render_workflows
158
181
  self._message = message
159
182
  self._render_message = render_message
160
183
  self._summarization_prompt = summarization_prompt
161
184
  self._render_summarization_prompt = render_summarization_prompt
162
185
  self._tools = tools
163
186
  self._rate_limitter = rate_limitter
164
- self._additional_tools: list["ToolOrCallable"] = []
187
+ self._additional_tools: list["ToolOrCallable"] = [load_workflow]
165
188
  self._toolsets = toolsets
166
- self._additional_toolsets: list["AbstractToolset[Agent]"] = []
189
+ self._additional_toolsets: list["AbstractToolset[None] | str"] = []
167
190
  self._conversation_history = conversation_history
168
191
  self._conversation_history_reader = conversation_history_reader
169
192
  self._conversation_history_writer = conversation_history_writer
@@ -178,19 +201,21 @@ class LLMTask(BaseTask):
178
201
  render_history_summarization_token_threshold
179
202
  )
180
203
  self._max_call_iteration = max_call_iteration
181
- self._conversation_context = conversation_context
204
+ self._yolo_mode = yolo_mode
205
+ self._render_yolo_mode = render_yolo_mode
206
+ self._attachment = attachment
182
207
 
183
- def add_tool(self, *tool: ToolOrCallable):
208
+ def add_tool(self, *tool: "ToolOrCallable"):
184
209
  self.append_tool(*tool)
185
210
 
186
- def append_tool(self, *tool: ToolOrCallable):
211
+ def append_tool(self, *tool: "ToolOrCallable"):
187
212
  for single_tool in tool:
188
213
  self._additional_tools.append(single_tool)
189
214
 
190
- def add_toolset(self, *toolset: "AbstractToolset[Agent]"):
215
+ def add_toolset(self, *toolset: "AbstractToolset[None] | str"):
191
216
  self.append_toolset(*toolset)
192
217
 
193
- def append_toolset(self, *toolset: "AbstractToolset[Agent]"):
218
+ def append_toolset(self, *toolset: "AbstractToolset[None] | str"):
194
219
  for single_toolset in toolset:
195
220
  self._additional_toolsets.append(single_toolset)
196
221
 
@@ -202,6 +227,12 @@ class LLMTask(BaseTask):
202
227
  ):
203
228
  self._history_summarization_token_threshold = summarization_token_threshold
204
229
 
230
+ def set_workflows(self, workflows: StrListAttr):
231
+ self._workflows = workflows
232
+
233
+ def set_yolo_mode(self, yolo_mode: StrListAttr | BoolAttr):
234
+ self._yolo_mode = yolo_mode
235
+
205
236
  async def _exec_action(self, ctx: AnyContext) -> Any:
206
237
  # Get dependent configurations first
207
238
  model_settings = get_model_settings(ctx, self._model_settings)
@@ -214,12 +245,18 @@ class LLMTask(BaseTask):
214
245
  model_api_key_attr=self._model_api_key,
215
246
  render_model_api_key=self._render_model_api_key,
216
247
  )
248
+ yolo_mode = get_yolo_mode(
249
+ ctx=ctx,
250
+ yolo_mode_attr=self._yolo_mode,
251
+ render_yolo_mode=self._render_yolo_mode,
252
+ )
217
253
  summarization_prompt = get_summarization_system_prompt(
218
254
  ctx=ctx,
219
255
  summarization_prompt_attr=self._summarization_prompt,
220
256
  render_summarization_prompt=self._render_summarization_prompt,
221
257
  )
222
258
  user_message = get_user_message(ctx, self._message, self._render_message)
259
+ attachments = get_attachments(ctx, self._attachment)
223
260
  # 1. Prepare initial state (read history from previous session)
224
261
  conversation_history = await read_conversation_history(
225
262
  ctx=ctx,
@@ -228,9 +265,10 @@ class LLMTask(BaseTask):
228
265
  render_history_file=self._render_history_file,
229
266
  conversation_history_attr=self._conversation_history,
230
267
  )
231
- conversation_history.fetch_newest_notes()
268
+ inject_conversation_history_notes(conversation_history)
269
+ inject_subagent_conversation_history_into_ctx(ctx, conversation_history)
232
270
  # 2. Get system prompt and user prompt
233
- system_prompt, user_message = get_system_and_user_prompt(
271
+ system_prompt, user_prompt = get_system_and_user_prompt(
234
272
  ctx=ctx,
235
273
  user_message=user_message,
236
274
  persona_attr=self._persona,
@@ -239,47 +277,59 @@ class LLMTask(BaseTask):
239
277
  render_system_prompt=self._render_system_prompt,
240
278
  special_instruction_prompt_attr=self._special_instruction_prompt,
241
279
  render_special_instruction_prompt=self._render_special_instruction_prompt,
242
- modes_attr=self._modes,
243
- render_modes=self._render_modes,
280
+ workflows_attr=self._workflows,
281
+ render_workflows=self._render_workflows,
244
282
  conversation_history=conversation_history,
245
283
  )
246
- # 3. Get the agent instance
284
+ # 3. Summarization
285
+ small_model = get_model(
286
+ ctx=ctx,
287
+ model_attr=self._small_model,
288
+ render_model=self._render_small_model,
289
+ model_base_url_attr=self._small_model_base_url,
290
+ render_model_base_url=self._render_small_model_base_url,
291
+ model_api_key_attr=self._small_model_api_key,
292
+ render_model_api_key=self._render_small_model_api_key,
293
+ )
294
+ small_model_settings = get_model_settings(ctx, self._small_model_settings)
295
+ summarization_token_threshold = get_history_summarization_token_threshold(
296
+ ctx,
297
+ self._history_summarization_token_threshold,
298
+ self._render_history_summarization_token_threshold,
299
+ )
300
+ # 4. Get the agent instance
301
+ ctx.log_info(f"SYSTEM PROMPT:\n{system_prompt}")
302
+ ctx.log_info(f"USER PROMPT:\n{user_prompt}")
247
303
  agent = get_agent(
248
304
  ctx=ctx,
249
- agent_attr=self._agent,
250
305
  model=model,
306
+ rate_limitter=self._rate_limitter,
251
307
  system_prompt=system_prompt,
252
308
  model_settings=model_settings,
253
309
  tools_attr=self._tools,
254
310
  additional_tools=self._additional_tools,
255
311
  toolsets_attr=self._toolsets,
256
312
  additional_toolsets=self._additional_toolsets,
313
+ yolo_mode=yolo_mode,
314
+ summarization_model=small_model,
315
+ summarization_model_settings=small_model_settings,
316
+ summarization_system_prompt=summarization_prompt,
317
+ summarization_retries=2, # TODO: make this a property
318
+ summarization_token_threshold=summarization_token_threshold,
319
+ history_processors=[], # TODO: make this a property
257
320
  )
258
- # 4. Run the agent iteration and save the results/history
321
+ # 5. Run the agent iteration and save the results/history
259
322
  result = await self._execute_agent(
260
- ctx,
261
- agent,
262
- user_message,
263
- conversation_history,
264
- )
265
- # 5. Summarize
266
- conversation_history = await maybe_summarize_history(
267
323
  ctx=ctx,
324
+ agent=agent,
325
+ user_prompt=user_prompt,
326
+ attachments=attachments,
268
327
  conversation_history=conversation_history,
269
- should_summarize_history_attr=self._should_summarize_history,
270
- render_summarize_history=self._render_summarize_history,
271
- history_summarization_token_threshold_attr=(
272
- self._history_summarization_token_threshold
273
- ),
274
- render_history_summarization_token_threshold=(
275
- self._render_history_summarization_token_threshold
276
- ),
277
- model=model,
278
- model_settings=model_settings,
279
- summarization_prompt=summarization_prompt,
280
- rate_limitter=self._rate_limitter,
281
328
  )
282
329
  # 6. Write conversation history
330
+ conversation_history.subagent_history = (
331
+ extract_subagent_conversation_history_from_ctx(ctx)
332
+ )
283
333
  await write_conversation_history(
284
334
  ctx=ctx,
285
335
  history_data=conversation_history,
@@ -294,6 +344,7 @@ class LLMTask(BaseTask):
294
344
  ctx: AnyContext,
295
345
  agent: "Agent",
296
346
  user_prompt: str,
347
+ attachments: "list[UserContent]",
297
348
  conversation_history: ConversationHistory,
298
349
  ) -> Any:
299
350
  """Executes the agent, processes results, and saves history."""
@@ -302,6 +353,7 @@ class LLMTask(BaseTask):
302
353
  ctx=ctx,
303
354
  agent=agent,
304
355
  user_prompt=user_prompt,
356
+ attachments=attachments,
305
357
  history_list=conversation_history.history,
306
358
  rate_limitter=self._rate_limitter,
307
359
  )
@@ -313,7 +365,7 @@ class LLMTask(BaseTask):
313
365
  ctx.xcom[xcom_usage_key] = Xcom([])
314
366
  usage = agent_run.result.usage()
315
367
  ctx.xcom[xcom_usage_key].push(usage)
316
- ctx.print(stylize_faint(f"💸 Token: {usage}"), plain=True)
368
+ ctx.print(stylize_faint(f" 💸 Token: {usage}"), plain=True)
317
369
  return agent_run.result.output
318
370
  else:
319
371
  ctx.log_warning("Agent run did not produce a result.")
zrb/task/make_task.py CHANGED
@@ -2,7 +2,6 @@ from collections.abc import Callable
2
2
  from typing import Any
3
3
 
4
4
  from zrb.context.any_context import AnyContext
5
- from zrb.context.any_shared_context import AnySharedContext
6
5
  from zrb.env.any_env import AnyEnv
7
6
  from zrb.group.any_group import AnyGroup
8
7
  from zrb.input.any_input import AnyInput
@@ -18,7 +17,7 @@ def make_task(
18
17
  cli_only: bool = False,
19
18
  input: list[AnyInput | None] | AnyInput | None = None,
20
19
  env: list[AnyEnv | None] | AnyEnv | None = None,
21
- execute_condition: bool | str | Callable[[AnySharedContext], bool] = True,
20
+ execute_condition: bool | str | Callable[[AnyContext], bool] = True,
22
21
  retries: int = 2,
23
22
  retry_period: float = 0,
24
23
  readiness_check: list[AnyTask] | AnyTask | None = None,
@@ -33,7 +32,7 @@ def make_task(
33
32
  group: AnyGroup | None = None,
34
33
  alias: str | None = None,
35
34
  ) -> Callable[[Callable[[AnyContext], Any]], AnyTask]:
36
- def _make_task(fn: Callable[[AnyContext], Any]) -> BaseTask:
35
+ def _make_task(fn: Callable[[AnyContext], Any]) -> AnyTask:
37
36
  task = BaseTask(
38
37
  name=name,
39
38
  color=color,
zrb/task/rsync_task.py CHANGED
@@ -1,6 +1,4 @@
1
- from collections.abc import Callable
2
-
3
- from zrb.attr.type import IntAttr, StrAttr
1
+ from zrb.attr.type import BoolAttr, IntAttr, StrAttr
4
2
  from zrb.context.any_context import AnyContext
5
3
  from zrb.env.any_env import AnyEnv
6
4
  from zrb.input.any_input import AnyInput
@@ -17,8 +15,8 @@ class RsyncTask(CmdTask):
17
15
  icon: str | None = None,
18
16
  description: str | None = None,
19
17
  cli_only: bool = False,
20
- input: list[AnyInput] | AnyInput | None = None,
21
- env: list[AnyEnv] | AnyEnv | None = None,
18
+ input: list[AnyInput | None] | AnyInput | None = None,
19
+ env: list[AnyEnv | None] | AnyEnv | None = None,
22
20
  shell: StrAttr | None = None,
23
21
  auto_render_shell: bool = True,
24
22
  remote_host: StrAttr | None = None,
@@ -39,12 +37,14 @@ class RsyncTask(CmdTask):
39
37
  render_local_source_path: bool = True,
40
38
  local_destination_path: StrAttr | None = None,
41
39
  render_local_destination_path: bool = True,
40
+ exclude_from: StrAttr | None = None,
41
+ render_exclude_from: bool = True,
42
42
  cwd: str | None = None,
43
43
  render_cwd: bool = True,
44
44
  plain_print: bool = False,
45
45
  max_output_line: int = 1000,
46
46
  max_error_line: int = 1000,
47
- execute_condition: bool | str | Callable[[AnyContext], bool] = True,
47
+ execute_condition: BoolAttr = True,
48
48
  retries: int = 2,
49
49
  retry_period: float = 0,
50
50
  readiness_check: list[AnyTask] | AnyTask | None = None,
@@ -93,6 +93,8 @@ class RsyncTask(CmdTask):
93
93
  self._render_local_source_path = render_local_source_path
94
94
  self._local_destination_path = local_destination_path
95
95
  self._render_local_destination_path = render_local_destination_path
96
+ self._exclude_from = exclude_from
97
+ self._render_exclude_from = render_exclude_from
96
98
 
97
99
  def _get_source_path(self, ctx: AnyContext) -> str:
98
100
  local_source_path = self._get_local_source_path(ctx)
@@ -144,16 +146,29 @@ class RsyncTask(CmdTask):
144
146
  auto_render=self._render_local_destination_path,
145
147
  )
146
148
 
149
+ def _get_exclude_from_param(self, ctx: AnyContext) -> str:
150
+ exclude_from = get_str_attr(
151
+ ctx,
152
+ self._exclude_from,
153
+ "",
154
+ auto_render=self._render_exclude_from,
155
+ ).strip()
156
+ if exclude_from == "":
157
+ return ""
158
+ return f"--exclude-from='{exclude_from}'"
159
+
147
160
  def _get_cmd_script(self, ctx: AnyContext) -> str:
148
161
  port = self._get_remote_port(ctx)
149
162
  password = self._get_remote_password(ctx)
150
163
  key = self._get_remote_ssh_key(ctx)
151
164
  src = self._get_source_path(ctx)
152
165
  dst = self._get_destination_path(ctx)
166
+ exclude_from = self._get_exclude_from_param(ctx)
167
+ exclude_from_with_space = f"{exclude_from} " if exclude_from != "" else ""
153
168
  if key != "" and password != "":
154
- return f'sshpass -p "$_ZRB_SSH_PASSWORD" rsync --mkpath -avz -e "ssh -i {key} -p {port}" {src} {dst}' # noqa
169
+ return f'sshpass -p "$_ZRB_SSH_PASSWORD" rsync --mkpath -avz -e "ssh -i {key} -p {port}" {exclude_from_with_space}{src} {dst}' # noqa
155
170
  if key != "":
156
- return f'rsync --mkpath -avz -e "ssh -i {key} -p {port}" {src} {dst}'
171
+ return f'rsync --mkpath -avz -e "ssh -i {key} -p {port}" {exclude_from_with_space}{src} {dst}' # noqa
157
172
  if password != "":
158
- return f'sshpass -p "$_ZRB_SSH_PASSWORD" rsync --mkpath -avz -e "ssh -p {port}" {src} {dst}' # noqa
159
- return f'rsync --mkpath -avz -e "ssh -p {port}" {src} {dst}'
173
+ return f'sshpass -p "$_ZRB_SSH_PASSWORD" rsync --mkpath -avz -e "ssh -p {port}" {exclude_from_with_space}{src} {dst}' # noqa
174
+ return f'rsync --mkpath -avz -e "ssh -p {port}" {exclude_from_with_space}{src} {dst}'
zrb/task/scheduler.py CHANGED
@@ -24,8 +24,8 @@ class Scheduler(BaseTrigger):
24
24
  cli_only: bool = False,
25
25
  input: list[AnyInput | None] | AnyInput | None = None,
26
26
  env: list[AnyEnv | None] | AnyEnv | None = None,
27
- schedule: StrAttr = None,
28
- execute_condition: bool | str | Callable[[AnySharedContext], bool] = True,
27
+ schedule: StrAttr | None = None,
28
+ execute_condition: bool | str | Callable[[AnyContext], bool] = True,
29
29
  queue_name: fstring | None = None,
30
30
  callback: list[AnyCallback] | AnyCallback = [],
31
31
  retries: int = 2,
@@ -76,6 +76,6 @@ class Scheduler(BaseTrigger):
76
76
  ctx.print(f"Current time: {now}")
77
77
  if match_cron(cron_pattern, now):
78
78
  ctx.print(f"Matching {now} with pattern: {cron_pattern}")
79
- xcom = self.get_exchange_xcom(ctx.session)
80
- xcom.push(now)
79
+ if ctx.session is not None:
80
+ self.push_exchange_xcom(ctx.session, now)
81
81
  await asyncio.sleep(60)