zrb 1.21.9__py3-none-any.whl → 1.21.31__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.
Potentially problematic release.
This version of zrb might be problematic. Click here for more details.
- zrb/attr/type.py +10 -7
- zrb/builtin/git.py +12 -1
- zrb/builtin/llm/chat_completion.py +287 -0
- zrb/builtin/llm/chat_session_cmd.py +90 -28
- zrb/builtin/llm/chat_trigger.py +6 -1
- zrb/builtin/llm/history.py +4 -4
- zrb/builtin/llm/tool/cli.py +25 -13
- zrb/builtin/llm/tool/code.py +9 -2
- zrb/builtin/llm/tool/file.py +42 -81
- zrb/builtin/llm/tool/note.py +36 -16
- zrb/builtin/llm/tool/search/__init__.py +1 -0
- zrb/builtin/llm/tool/search/brave.py +60 -0
- zrb/builtin/llm/tool/search/searxng.py +55 -0
- zrb/builtin/llm/tool/search/serpapi.py +55 -0
- zrb/builtin/llm/tool/sub_agent.py +30 -10
- zrb/builtin/llm/tool/web.py +12 -72
- zrb/config/config.py +108 -13
- zrb/config/default_prompt/interactive_system_prompt.md +1 -1
- zrb/config/default_prompt/summarization_prompt.md +54 -8
- zrb/config/default_prompt/system_prompt.md +1 -1
- zrb/config/llm_rate_limitter.py +24 -5
- zrb/input/option_input.py +13 -1
- zrb/task/llm/agent.py +42 -144
- zrb/task/llm/agent_runner.py +152 -0
- zrb/task/llm/config.py +7 -5
- zrb/task/llm/conversation_history.py +35 -24
- zrb/task/llm/conversation_history_model.py +4 -11
- zrb/task/llm/default_workflow/coding/workflow.md +2 -3
- zrb/task/llm/file_replacement.py +206 -0
- zrb/task/llm/file_tool_model.py +57 -0
- zrb/task/llm/history_processor.py +206 -0
- zrb/task/llm/history_summarization.py +2 -179
- zrb/task/llm/print_node.py +14 -5
- zrb/task/llm/prompt.py +7 -18
- zrb/task/llm/subagent_conversation_history.py +41 -0
- zrb/task/llm/tool_confirmation_completer.py +41 -0
- zrb/task/llm/tool_wrapper.py +26 -12
- zrb/task/llm_task.py +55 -47
- zrb/util/attr.py +17 -10
- zrb/util/cli/text.py +6 -4
- zrb/util/git.py +2 -2
- zrb/util/yaml.py +1 -0
- zrb/xcom/xcom.py +10 -0
- {zrb-1.21.9.dist-info → zrb-1.21.31.dist-info}/METADATA +5 -5
- {zrb-1.21.9.dist-info → zrb-1.21.31.dist-info}/RECORD +47 -37
- zrb/task/llm/history_summarization_tool.py +0 -24
- {zrb-1.21.9.dist-info → zrb-1.21.31.dist-info}/WHEEL +0 -0
- {zrb-1.21.9.dist-info → zrb-1.21.31.dist-info}/entry_points.txt +0 -0
zrb/task/llm/prompt.py
CHANGED
|
@@ -115,11 +115,11 @@ def _construct_system_prompt(
|
|
|
115
115
|
),
|
|
116
116
|
),
|
|
117
117
|
make_markdown_section(
|
|
118
|
-
"🧠 Long Term Note",
|
|
118
|
+
"🧠 Long Term Note Content",
|
|
119
119
|
conversation_history.long_term_note,
|
|
120
120
|
),
|
|
121
121
|
make_markdown_section(
|
|
122
|
-
"📝 Contextual Note",
|
|
122
|
+
"📝 Contextual Note Content",
|
|
123
123
|
conversation_history.contextual_note,
|
|
124
124
|
),
|
|
125
125
|
make_markdown_section(
|
|
@@ -129,21 +129,6 @@ def _construct_system_prompt(
|
|
|
129
129
|
]
|
|
130
130
|
),
|
|
131
131
|
),
|
|
132
|
-
make_markdown_section(
|
|
133
|
-
"💬 PAST CONVERSATION",
|
|
134
|
-
"\n".join(
|
|
135
|
-
[
|
|
136
|
-
make_markdown_section(
|
|
137
|
-
"Narrative Summary",
|
|
138
|
-
conversation_history.past_conversation_summary,
|
|
139
|
-
),
|
|
140
|
-
make_markdown_section(
|
|
141
|
-
"Past Transcript",
|
|
142
|
-
conversation_history.past_conversation_transcript,
|
|
143
|
-
),
|
|
144
|
-
]
|
|
145
|
-
),
|
|
146
|
-
),
|
|
147
132
|
]
|
|
148
133
|
)
|
|
149
134
|
|
|
@@ -230,7 +215,11 @@ def _get_workflow_prompt(
|
|
|
230
215
|
make_markdown_section(
|
|
231
216
|
workflow_name.capitalize(),
|
|
232
217
|
(
|
|
233
|
-
|
|
218
|
+
(
|
|
219
|
+
"> Workflow status: Automatically Loaded/Activated.\n"
|
|
220
|
+
f"> Workflow location: `{workflow.path}`\n"
|
|
221
|
+
"{workflow.content}"
|
|
222
|
+
)
|
|
234
223
|
if select_active_workflow
|
|
235
224
|
else f"Workflow name: {workflow_name}\n{workflow.description}"
|
|
236
225
|
),
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from zrb.context.any_context import AnyContext
|
|
2
|
+
from zrb.task.llm.conversation_history_model import ConversationHistory
|
|
3
|
+
from zrb.task.llm.typing import ListOfDict
|
|
4
|
+
from zrb.xcom.xcom import Xcom
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def inject_subagent_conversation_history_into_ctx(
|
|
8
|
+
ctx: AnyContext, conversation_history: ConversationHistory
|
|
9
|
+
):
|
|
10
|
+
subagent_messages_xcom = _get_global_subagent_history_xcom(ctx)
|
|
11
|
+
existing_subagent_history = subagent_messages_xcom.get({})
|
|
12
|
+
subagent_messages_xcom.set(
|
|
13
|
+
{**existing_subagent_history, **conversation_history.subagent_history}
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def extract_subagent_conversation_history_from_ctx(
|
|
18
|
+
ctx: AnyContext,
|
|
19
|
+
) -> dict[str, ListOfDict]:
|
|
20
|
+
subagent_messsages_xcom = _get_global_subagent_history_xcom(ctx)
|
|
21
|
+
return subagent_messsages_xcom.get({})
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_ctx_subagent_history(ctx: AnyContext, subagent_name: str) -> ListOfDict:
|
|
25
|
+
subagent_history = extract_subagent_conversation_history_from_ctx(ctx)
|
|
26
|
+
return subagent_history.get(subagent_name, [])
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def set_ctx_subagent_history(ctx: AnyContext, subagent_name: str, messages: ListOfDict):
|
|
30
|
+
subagent_history = extract_subagent_conversation_history_from_ctx(ctx)
|
|
31
|
+
subagent_history[subagent_name] = messages
|
|
32
|
+
subagent_messages_xcom = _get_global_subagent_history_xcom(ctx)
|
|
33
|
+
subagent_messages_xcom.set(subagent_history)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _get_global_subagent_history_xcom(ctx: AnyContext) -> Xcom:
|
|
37
|
+
if "_global_subagents" not in ctx.xcom:
|
|
38
|
+
ctx.xcom["_global_subagents"] = Xcom([{}])
|
|
39
|
+
if not isinstance(ctx.xcom["_global_subagents"], Xcom):
|
|
40
|
+
raise ValueError("ctx.xcom._global_subagents must be an Xcom")
|
|
41
|
+
return ctx.xcom["_global_subagents"]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
if TYPE_CHECKING:
|
|
4
|
+
from prompt_toolkit.completion import Completer
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_tool_confirmation_completer(
|
|
8
|
+
options: list[str], meta_dict: dict[str, str]
|
|
9
|
+
) -> "Completer":
|
|
10
|
+
from prompt_toolkit.completion import Completer, Completion
|
|
11
|
+
|
|
12
|
+
class ToolConfirmationCompleter(Completer):
|
|
13
|
+
"""Custom completer for tool confirmation that doesn't auto-complete partial words."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, options, meta_dict):
|
|
16
|
+
self.options = options
|
|
17
|
+
self.meta_dict = meta_dict
|
|
18
|
+
|
|
19
|
+
def get_completions(self, document, complete_event):
|
|
20
|
+
text = document.text.strip()
|
|
21
|
+
# 1. Input is empty, OR
|
|
22
|
+
# 2. Input exactly matches the beginning of an option
|
|
23
|
+
if text == "":
|
|
24
|
+
# Show all options when nothing is typed
|
|
25
|
+
for option in self.options:
|
|
26
|
+
yield Completion(
|
|
27
|
+
option,
|
|
28
|
+
start_position=0,
|
|
29
|
+
display_meta=self.meta_dict.get(option, ""),
|
|
30
|
+
)
|
|
31
|
+
return
|
|
32
|
+
# Only complete if text exactly matches the beginning of an option
|
|
33
|
+
for option in self.options:
|
|
34
|
+
if option.startswith(text):
|
|
35
|
+
yield Completion(
|
|
36
|
+
option,
|
|
37
|
+
start_position=-len(text),
|
|
38
|
+
display_meta=self.meta_dict.get(option, ""),
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
return ToolConfirmationCompleter(options, meta_dict)
|
zrb/task/llm/tool_wrapper.py
CHANGED
|
@@ -10,11 +10,12 @@ from zrb.config.config import CFG
|
|
|
10
10
|
from zrb.config.llm_rate_limitter import llm_rate_limitter
|
|
11
11
|
from zrb.context.any_context import AnyContext
|
|
12
12
|
from zrb.task.llm.error import ToolExecutionError
|
|
13
|
+
from zrb.task.llm.file_replacement import edit_replacement, is_single_path_replacement
|
|
14
|
+
from zrb.task.llm.tool_confirmation_completer import get_tool_confirmation_completer
|
|
13
15
|
from zrb.util.callable import get_callable_name
|
|
14
16
|
from zrb.util.cli.markdown import render_markdown
|
|
15
17
|
from zrb.util.cli.style import (
|
|
16
18
|
stylize_blue,
|
|
17
|
-
stylize_error,
|
|
18
19
|
stylize_faint,
|
|
19
20
|
stylize_green,
|
|
20
21
|
stylize_yellow,
|
|
@@ -184,7 +185,7 @@ async def _handle_user_response(
|
|
|
184
185
|
]
|
|
185
186
|
)
|
|
186
187
|
ctx.print(complete_confirmation_message, plain=True)
|
|
187
|
-
user_response = await _read_line()
|
|
188
|
+
user_response = await _read_line(args, kwargs)
|
|
188
189
|
ctx.print("", plain=True)
|
|
189
190
|
new_kwargs, is_edited = _get_edited_kwargs(ctx, user_response, kwargs)
|
|
190
191
|
if is_edited:
|
|
@@ -214,10 +215,19 @@ def _get_edited_kwargs(
|
|
|
214
215
|
key_parts = key.split(".")
|
|
215
216
|
if len(key_parts) > 0 and key_parts[0] not in kwargs:
|
|
216
217
|
return kwargs, True
|
|
218
|
+
# Handle replacement edit
|
|
219
|
+
if len(kwargs) == 1:
|
|
220
|
+
kwarg_key = list(kwargs.keys())[0]
|
|
221
|
+
if is_single_path_replacement(kwargs[kwarg_key]) and (
|
|
222
|
+
key == "" or key == kwarg_key
|
|
223
|
+
):
|
|
224
|
+
kwargs[kwarg_key], edited = edit_replacement(kwargs[kwarg_key])
|
|
225
|
+
return kwargs, True
|
|
226
|
+
# Handle other kind of edit
|
|
217
227
|
old_val_str = yaml_dump(kwargs, key)
|
|
218
228
|
if val_str == "":
|
|
219
229
|
val_str = edit_text(
|
|
220
|
-
prompt_message=f"# {key}",
|
|
230
|
+
prompt_message=f"# {key}" if key != "" else "",
|
|
221
231
|
value=old_val_str,
|
|
222
232
|
editor=CFG.DEFAULT_EDITOR,
|
|
223
233
|
extension=".yaml",
|
|
@@ -240,13 +250,7 @@ def _get_user_approval_and_reason(
|
|
|
240
250
|
try:
|
|
241
251
|
approved = True if approval_str.strip() == "" else to_boolean(approval_str)
|
|
242
252
|
if not approved and reason == "":
|
|
243
|
-
|
|
244
|
-
stylize_error(
|
|
245
|
-
f"You must specify rejection reason (i.e., No, <why>) for {func_call_str}" # noqa
|
|
246
|
-
),
|
|
247
|
-
plain=True,
|
|
248
|
-
)
|
|
249
|
-
return None
|
|
253
|
+
reason = "User disapproving the tool execution"
|
|
250
254
|
return approved, reason
|
|
251
255
|
except Exception:
|
|
252
256
|
return False, user_response
|
|
@@ -290,11 +294,21 @@ def _truncate_arg(arg: str, length: int = 19) -> str:
|
|
|
290
294
|
return normalized_arg
|
|
291
295
|
|
|
292
296
|
|
|
293
|
-
async def _read_line():
|
|
297
|
+
async def _read_line(args: list[Any] | tuple[Any], kwargs: dict[str, Any]):
|
|
294
298
|
from prompt_toolkit import PromptSession
|
|
295
299
|
|
|
300
|
+
options = ["yes", "no", "edit"]
|
|
301
|
+
meta_dict = {
|
|
302
|
+
"yes": "Approve the execution",
|
|
303
|
+
"no": "Disapprove the execution",
|
|
304
|
+
"edit": "Edit tool execution parameters",
|
|
305
|
+
}
|
|
306
|
+
for key in kwargs:
|
|
307
|
+
options.append(f"edit {key}")
|
|
308
|
+
meta_dict[f"edit {key}"] = f"Edit tool execution parameter: {key}"
|
|
309
|
+
completer = get_tool_confirmation_completer(options, meta_dict)
|
|
296
310
|
reader = PromptSession()
|
|
297
|
-
return await reader.prompt_async()
|
|
311
|
+
return await reader.prompt_async(completer=completer)
|
|
298
312
|
|
|
299
313
|
|
|
300
314
|
def _adjust_signature(wrapper: Callable, original_sig: inspect.Signature):
|
zrb/task/llm_task.py
CHANGED
|
@@ -3,13 +3,14 @@ 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
|
|
6
|
+
from zrb.config.llm_rate_limitter import LLMRateLimitter
|
|
7
7
|
from zrb.context.any_context import AnyContext
|
|
8
8
|
from zrb.env.any_env import AnyEnv
|
|
9
9
|
from zrb.input.any_input import AnyInput
|
|
10
10
|
from zrb.task.any_task import AnyTask
|
|
11
11
|
from zrb.task.base_task import BaseTask
|
|
12
|
-
from zrb.task.llm.agent import get_agent
|
|
12
|
+
from zrb.task.llm.agent import get_agent
|
|
13
|
+
from zrb.task.llm.agent_runner import run_agent_iteration
|
|
13
14
|
from zrb.task.llm.config import (
|
|
14
15
|
get_model,
|
|
15
16
|
get_model_settings,
|
|
@@ -21,13 +22,17 @@ from zrb.task.llm.conversation_history import (
|
|
|
21
22
|
write_conversation_history,
|
|
22
23
|
)
|
|
23
24
|
from zrb.task.llm.conversation_history_model import ConversationHistory
|
|
24
|
-
from zrb.task.llm.history_summarization import
|
|
25
|
+
from zrb.task.llm.history_summarization import get_history_summarization_token_threshold
|
|
25
26
|
from zrb.task.llm.prompt import (
|
|
26
27
|
get_attachments,
|
|
27
28
|
get_summarization_system_prompt,
|
|
28
29
|
get_system_and_user_prompt,
|
|
29
30
|
get_user_message,
|
|
30
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
|
+
)
|
|
31
36
|
from zrb.task.llm.workflow import load_workflow
|
|
32
37
|
from zrb.util.cli.style import stylize_faint
|
|
33
38
|
from zrb.xcom.xcom import Xcom
|
|
@@ -50,11 +55,11 @@ 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: "Callable[[AnyContext], Model | str | fstring] | Model | None" = None,
|
|
58
|
+
model: "Callable[[AnyContext], Model | str | fstring | None] | Model | None" = None,
|
|
54
59
|
render_model: bool = True,
|
|
55
|
-
model_base_url:
|
|
60
|
+
model_base_url: "Callable[[AnyContext], str | None] | str | None" = None,
|
|
56
61
|
render_model_base_url: bool = True,
|
|
57
|
-
model_api_key:
|
|
62
|
+
model_api_key: "Callable[[AnyContext], str | None] | str | None" = None,
|
|
58
63
|
render_model_api_key: bool = True,
|
|
59
64
|
model_settings: (
|
|
60
65
|
"ModelSettings | Callable[[AnyContext], ModelSettings] | None"
|
|
@@ -70,16 +75,16 @@ class LLMTask(BaseTask):
|
|
|
70
75
|
small_model_settings: (
|
|
71
76
|
"ModelSettings | Callable[[AnyContext], ModelSettings] | None"
|
|
72
77
|
) = None,
|
|
73
|
-
persona:
|
|
78
|
+
persona: "Callable[[AnyContext], str | None] | str | None" = None,
|
|
74
79
|
render_persona: bool = False,
|
|
75
|
-
system_prompt:
|
|
80
|
+
system_prompt: "Callable[[AnyContext], str | None] | str | None" = None,
|
|
76
81
|
render_system_prompt: bool = False,
|
|
77
|
-
special_instruction_prompt:
|
|
82
|
+
special_instruction_prompt: "Callable[[AnyContext], str | None] | str | None" = None,
|
|
78
83
|
render_special_instruction_prompt: bool = False,
|
|
79
84
|
workflows: StrListAttr | None = None,
|
|
80
85
|
render_workflows: bool = True,
|
|
81
86
|
message: StrAttr | None = None,
|
|
82
|
-
attachment: "UserContent | list[UserContent] | Callable[[AnyContext], UserContent | list[UserContent]] | None" = None,
|
|
87
|
+
attachment: "UserContent | list[UserContent] | Callable[[AnyContext], UserContent | list[UserContent]] | None" = None, # noqa
|
|
83
88
|
render_message: bool = True,
|
|
84
89
|
tools: (
|
|
85
90
|
list["ToolOrCallable"] | Callable[[AnyContext], list["ToolOrCallable"]]
|
|
@@ -104,19 +109,22 @@ class LLMTask(BaseTask):
|
|
|
104
109
|
render_history_file: bool = True,
|
|
105
110
|
summarize_history: BoolAttr | None = None,
|
|
106
111
|
render_summarize_history: bool = True,
|
|
107
|
-
summarization_prompt:
|
|
112
|
+
summarization_prompt: "Callable[[AnyContext], str | None] | str | None" = None,
|
|
108
113
|
render_summarization_prompt: bool = False,
|
|
109
114
|
history_summarization_token_threshold: IntAttr | None = None,
|
|
110
115
|
render_history_summarization_token_threshold: bool = True,
|
|
111
|
-
rate_limitter:
|
|
116
|
+
rate_limitter: LLMRateLimitter | None = None,
|
|
112
117
|
execute_condition: bool | str | Callable[[AnyContext], bool] = True,
|
|
113
118
|
retries: int = 2,
|
|
114
119
|
retry_period: float = 0,
|
|
115
|
-
yolo_mode:
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
120
|
+
yolo_mode: (
|
|
121
|
+
Callable[[AnyContext], list[str] | bool | None]
|
|
122
|
+
| StrListAttr
|
|
123
|
+
| BoolAttr
|
|
124
|
+
| None
|
|
119
125
|
) = None,
|
|
126
|
+
render_yolo_mode: bool = True,
|
|
127
|
+
readiness_check: list[AnyTask] | AnyTask | None = None,
|
|
120
128
|
readiness_check_delay: float = 0.5,
|
|
121
129
|
readiness_check_period: float = 5,
|
|
122
130
|
readiness_failure_threshold: int = 1,
|
|
@@ -262,6 +270,7 @@ class LLMTask(BaseTask):
|
|
|
262
270
|
conversation_history_attr=self._conversation_history,
|
|
263
271
|
)
|
|
264
272
|
inject_conversation_history_notes(conversation_history)
|
|
273
|
+
inject_subagent_conversation_history_into_ctx(ctx, conversation_history)
|
|
265
274
|
# 2. Get system prompt and user prompt
|
|
266
275
|
system_prompt, user_prompt = get_system_and_user_prompt(
|
|
267
276
|
ctx=ctx,
|
|
@@ -276,12 +285,29 @@ class LLMTask(BaseTask):
|
|
|
276
285
|
render_workflows=self._render_workflows,
|
|
277
286
|
conversation_history=conversation_history,
|
|
278
287
|
)
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
288
|
+
# 3. Summarization
|
|
289
|
+
small_model = get_model(
|
|
290
|
+
ctx=ctx,
|
|
291
|
+
model_attr=self._small_model,
|
|
292
|
+
render_model=self._render_small_model,
|
|
293
|
+
model_base_url_attr=self._small_model_base_url,
|
|
294
|
+
render_model_base_url=self._render_small_model_base_url,
|
|
295
|
+
model_api_key_attr=self._small_model_api_key,
|
|
296
|
+
render_model_api_key=self._render_small_model_api_key,
|
|
297
|
+
)
|
|
298
|
+
small_model_settings = get_model_settings(ctx, self._small_model_settings)
|
|
299
|
+
summarization_token_threshold = get_history_summarization_token_threshold(
|
|
300
|
+
ctx,
|
|
301
|
+
self._history_summarization_token_threshold,
|
|
302
|
+
self._render_history_summarization_token_threshold,
|
|
303
|
+
)
|
|
304
|
+
# 4. Get the agent instance
|
|
305
|
+
ctx.log_info(f"SYSTEM PROMPT:\n{system_prompt}")
|
|
306
|
+
ctx.log_info(f"USER PROMPT:\n{user_prompt}")
|
|
282
307
|
agent = get_agent(
|
|
283
308
|
ctx=ctx,
|
|
284
309
|
model=model,
|
|
310
|
+
rate_limitter=self._rate_limitter,
|
|
285
311
|
system_prompt=system_prompt,
|
|
286
312
|
model_settings=model_settings,
|
|
287
313
|
tools_attr=self._tools,
|
|
@@ -289,8 +315,14 @@ class LLMTask(BaseTask):
|
|
|
289
315
|
toolsets_attr=self._toolsets,
|
|
290
316
|
additional_toolsets=self._additional_toolsets,
|
|
291
317
|
yolo_mode=yolo_mode,
|
|
318
|
+
summarization_model=small_model,
|
|
319
|
+
summarization_model_settings=small_model_settings,
|
|
320
|
+
summarization_system_prompt=summarization_prompt,
|
|
321
|
+
summarization_retries=2, # TODO: make this a property
|
|
322
|
+
summarization_token_threshold=summarization_token_threshold,
|
|
323
|
+
history_processors=[], # TODO: make this a property
|
|
292
324
|
)
|
|
293
|
-
#
|
|
325
|
+
# 5. Run the agent iteration and save the results/history
|
|
294
326
|
result = await self._execute_agent(
|
|
295
327
|
ctx=ctx,
|
|
296
328
|
agent=agent,
|
|
@@ -298,34 +330,10 @@ class LLMTask(BaseTask):
|
|
|
298
330
|
attachments=attachments,
|
|
299
331
|
conversation_history=conversation_history,
|
|
300
332
|
)
|
|
301
|
-
# 5. Summarize
|
|
302
|
-
small_model = get_model(
|
|
303
|
-
ctx=ctx,
|
|
304
|
-
model_attr=self._small_model,
|
|
305
|
-
render_model=self._render_small_model,
|
|
306
|
-
model_base_url_attr=self._small_model_base_url,
|
|
307
|
-
render_model_base_url=self._render_small_model_base_url,
|
|
308
|
-
model_api_key_attr=self._small_model_api_key,
|
|
309
|
-
render_model_api_key=self._render_small_model_api_key,
|
|
310
|
-
)
|
|
311
|
-
small_model_settings = get_model_settings(ctx, self._small_model_settings)
|
|
312
|
-
conversation_history = await maybe_summarize_history(
|
|
313
|
-
ctx=ctx,
|
|
314
|
-
conversation_history=conversation_history,
|
|
315
|
-
should_summarize_history_attr=self._should_summarize_history,
|
|
316
|
-
render_summarize_history=self._render_summarize_history,
|
|
317
|
-
history_summarization_token_threshold_attr=(
|
|
318
|
-
self._history_summarization_token_threshold
|
|
319
|
-
),
|
|
320
|
-
render_history_summarization_token_threshold=(
|
|
321
|
-
self._render_history_summarization_token_threshold
|
|
322
|
-
),
|
|
323
|
-
model=small_model,
|
|
324
|
-
model_settings=small_model_settings,
|
|
325
|
-
summarization_prompt=summarization_prompt,
|
|
326
|
-
rate_limitter=self._rate_limitter,
|
|
327
|
-
)
|
|
328
333
|
# 6. Write conversation history
|
|
334
|
+
conversation_history.subagent_history = (
|
|
335
|
+
extract_subagent_conversation_history_from_ctx(ctx)
|
|
336
|
+
)
|
|
329
337
|
await write_conversation_history(
|
|
330
338
|
ctx=ctx,
|
|
331
339
|
history_data=conversation_history,
|
zrb/util/attr.py
CHANGED
|
@@ -10,11 +10,14 @@ from zrb.attr.type import (
|
|
|
10
10
|
StrListAttr,
|
|
11
11
|
)
|
|
12
12
|
from zrb.context.any_context import AnyContext
|
|
13
|
+
from zrb.context.any_shared_context import AnySharedContext
|
|
13
14
|
from zrb.util.string.conversion import to_boolean
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
def get_str_list_attr(
|
|
17
|
-
ctx: AnyContext
|
|
18
|
+
ctx: AnyContext | AnySharedContext,
|
|
19
|
+
attr: StrListAttr | None,
|
|
20
|
+
auto_render: bool = True,
|
|
18
21
|
) -> list[str]:
|
|
19
22
|
"""
|
|
20
23
|
Retrieve a list of strings from shared context attributes.
|
|
@@ -35,7 +38,9 @@ def get_str_list_attr(
|
|
|
35
38
|
|
|
36
39
|
|
|
37
40
|
def get_str_dict_attr(
|
|
38
|
-
ctx: AnyContext
|
|
41
|
+
ctx: AnyContext | AnySharedContext,
|
|
42
|
+
attr: StrDictAttr | None,
|
|
43
|
+
auto_render: bool = True,
|
|
39
44
|
) -> dict[str, Any]:
|
|
40
45
|
"""
|
|
41
46
|
Retrieve a dictionary of strings from shared context attributes.
|
|
@@ -56,7 +61,7 @@ def get_str_dict_attr(
|
|
|
56
61
|
|
|
57
62
|
|
|
58
63
|
def get_str_attr(
|
|
59
|
-
ctx: AnyContext,
|
|
64
|
+
ctx: AnyContext | AnySharedContext,
|
|
60
65
|
attr: StrAttr | None,
|
|
61
66
|
default: StrAttr = "",
|
|
62
67
|
auto_render: bool = True,
|
|
@@ -74,13 +79,15 @@ def get_str_attr(
|
|
|
74
79
|
str: The string attribute value.
|
|
75
80
|
"""
|
|
76
81
|
val = get_attr(ctx, attr, default, auto_render)
|
|
77
|
-
if
|
|
78
|
-
return
|
|
79
|
-
|
|
82
|
+
if isinstance(val, str):
|
|
83
|
+
return val
|
|
84
|
+
if val is None:
|
|
85
|
+
return ""
|
|
86
|
+
return str(val)
|
|
80
87
|
|
|
81
88
|
|
|
82
89
|
def get_bool_attr(
|
|
83
|
-
ctx: AnyContext,
|
|
90
|
+
ctx: AnyContext | AnySharedContext,
|
|
84
91
|
attr: BoolAttr | None,
|
|
85
92
|
default: BoolAttr = False,
|
|
86
93
|
auto_render: bool = True,
|
|
@@ -106,7 +113,7 @@ def get_bool_attr(
|
|
|
106
113
|
|
|
107
114
|
|
|
108
115
|
def get_int_attr(
|
|
109
|
-
ctx: AnyContext,
|
|
116
|
+
ctx: AnyContext | AnySharedContext,
|
|
110
117
|
attr: IntAttr | None,
|
|
111
118
|
default: IntAttr = 0,
|
|
112
119
|
auto_render: bool = True,
|
|
@@ -132,7 +139,7 @@ def get_int_attr(
|
|
|
132
139
|
|
|
133
140
|
|
|
134
141
|
def get_float_attr(
|
|
135
|
-
ctx: AnyContext,
|
|
142
|
+
ctx: AnyContext | AnySharedContext,
|
|
136
143
|
attr: FloatAttr | None,
|
|
137
144
|
default: FloatAttr = 0.0,
|
|
138
145
|
auto_render: bool = True,
|
|
@@ -158,7 +165,7 @@ def get_float_attr(
|
|
|
158
165
|
|
|
159
166
|
|
|
160
167
|
def get_attr(
|
|
161
|
-
ctx: AnyContext,
|
|
168
|
+
ctx: AnyContext | AnySharedContext,
|
|
162
169
|
attr: AnyAttr,
|
|
163
170
|
default: AnyAttr,
|
|
164
171
|
auto_render: bool = True,
|
zrb/util/cli/text.py
CHANGED
|
@@ -11,10 +11,11 @@ def edit_text(
|
|
|
11
11
|
editor: str = "vi",
|
|
12
12
|
extension: str = ".txt",
|
|
13
13
|
) -> str:
|
|
14
|
-
prompt_message_eol = f"{prompt_message}\n"
|
|
15
14
|
with tempfile.NamedTemporaryFile(delete=False, suffix=extension) as temp_file:
|
|
16
15
|
temp_file_name = temp_file.name
|
|
17
|
-
|
|
16
|
+
if prompt_message.strip() != "":
|
|
17
|
+
prompt_message_eol = f"{prompt_message}\n"
|
|
18
|
+
temp_file.write(prompt_message_eol.encode())
|
|
18
19
|
# Pre-fill with default content
|
|
19
20
|
if value:
|
|
20
21
|
temp_file.write(value.encode())
|
|
@@ -22,7 +23,8 @@ def edit_text(
|
|
|
22
23
|
subprocess.call([editor, temp_file_name])
|
|
23
24
|
# Read the edited content
|
|
24
25
|
edited_content = read_file(temp_file_name)
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
if prompt_message.strip() != "":
|
|
27
|
+
parts = [text.strip() for text in edited_content.split(prompt_message, 1)]
|
|
28
|
+
edited_content = "\n".join(parts).lstrip()
|
|
27
29
|
os.remove(temp_file_name)
|
|
28
30
|
return edited_content
|
zrb/util/git.py
CHANGED
|
@@ -131,7 +131,7 @@ async def get_branches(
|
|
|
131
131
|
Exception: If the git command returns a non-zero exit code.
|
|
132
132
|
"""
|
|
133
133
|
cmd_result, exit_code = await run_command(
|
|
134
|
-
cmd=["git", "
|
|
134
|
+
cmd=["git", "branch"],
|
|
135
135
|
cwd=repo_dir,
|
|
136
136
|
print_method=print_method,
|
|
137
137
|
)
|
|
@@ -160,7 +160,7 @@ async def delete_branch(
|
|
|
160
160
|
Exception: If the git command returns a non-zero exit code.
|
|
161
161
|
"""
|
|
162
162
|
cmd_result, exit_code = await run_command(
|
|
163
|
-
cmd=["git", "branch", "-
|
|
163
|
+
cmd=["git", "branch", "-d", branch_name],
|
|
164
164
|
cwd=repo_dir,
|
|
165
165
|
print_method=print_method,
|
|
166
166
|
)
|
zrb/util/yaml.py
CHANGED
zrb/xcom/xcom.py
CHANGED
|
@@ -34,6 +34,16 @@ class Xcom(deque):
|
|
|
34
34
|
else:
|
|
35
35
|
raise IndexError("Xcom is empty")
|
|
36
36
|
|
|
37
|
+
def get(self, default_value: Any = None) -> Any:
|
|
38
|
+
if len(self) > 0:
|
|
39
|
+
return self[0]
|
|
40
|
+
return default_value
|
|
41
|
+
|
|
42
|
+
def set(self, new_value: Any):
|
|
43
|
+
self.push(new_value)
|
|
44
|
+
while len(self) > 1:
|
|
45
|
+
self.pop()
|
|
46
|
+
|
|
37
47
|
def add_push_callback(self, callback: Callable[[], Any]):
|
|
38
48
|
if not hasattr(self, "push_callbacks"):
|
|
39
49
|
self.push_callbacks: list[Callable[[], Any]] = []
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: zrb
|
|
3
|
-
Version: 1.21.
|
|
3
|
+
Version: 1.21.31
|
|
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
|
|
@@ -30,22 +30,22 @@ Requires-Dist: black (>=25.11.0,<26.0.0)
|
|
|
30
30
|
Requires-Dist: boto3 (>=1.40.14) ; extra == "bedrock"
|
|
31
31
|
Requires-Dist: chromadb (>=1.3.5,<2.0.0) ; extra == "rag" or extra == "all"
|
|
32
32
|
Requires-Dist: cohere (>=5.18.0) ; extra == "cohere" or extra == "all"
|
|
33
|
-
Requires-Dist: fastapi[standard] (>=0.
|
|
33
|
+
Requires-Dist: fastapi[standard] (>=0.123.9,<0.124.0)
|
|
34
34
|
Requires-Dist: google-auth (>=2.36.0) ; extra == "vertexai" or extra == "all"
|
|
35
35
|
Requires-Dist: google-genai (>=1.51.0) ; extra == "google" or extra == "all"
|
|
36
36
|
Requires-Dist: groq (>=0.25.0) ; extra == "groq" or extra == "all"
|
|
37
|
-
Requires-Dist: huggingface-hub[inference] (>=0.33.5) ; extra == "huggingface"
|
|
37
|
+
Requires-Dist: huggingface-hub[inference] (>=0.33.5,<1.0.0) ; extra == "huggingface"
|
|
38
38
|
Requires-Dist: isort (>=7.0.0,<8.0.0)
|
|
39
39
|
Requires-Dist: libcst (>=1.8.6,<2.0.0)
|
|
40
40
|
Requires-Dist: markdownify (>=1.2.2,<2.0.0)
|
|
41
41
|
Requires-Dist: mcp (>1.18.0)
|
|
42
42
|
Requires-Dist: mistralai (>=1.9.10) ; extra == "mistral"
|
|
43
|
-
Requires-Dist: openai (>=2.
|
|
43
|
+
Requires-Dist: openai (>=2.11.0)
|
|
44
44
|
Requires-Dist: pdfplumber (>=0.11.7,<0.12.0)
|
|
45
45
|
Requires-Dist: playwright (>=1.56.0,<2.0.0) ; extra == "playwright" or extra == "all"
|
|
46
46
|
Requires-Dist: prompt-toolkit (>=3)
|
|
47
47
|
Requires-Dist: psutil (>=7.0.0,<8.0.0)
|
|
48
|
-
Requires-Dist: pydantic-ai-slim (>=1.
|
|
48
|
+
Requires-Dist: pydantic-ai-slim (>=1.32.0,<1.33.0)
|
|
49
49
|
Requires-Dist: pyjwt (>=2.10.1,<3.0.0)
|
|
50
50
|
Requires-Dist: python-dotenv (>=1.1.1,<2.0.0)
|
|
51
51
|
Requires-Dist: python-jose[cryptography] (>=3.5.0,<4.0.0)
|