zrb 1.21.29__py3-none-any.whl → 2.0.0a4__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/__init__.py +118 -129
- zrb/builtin/__init__.py +54 -2
- zrb/builtin/llm/chat.py +147 -0
- zrb/callback/callback.py +8 -1
- zrb/cmd/cmd_result.py +2 -1
- zrb/config/config.py +491 -280
- zrb/config/helper.py +84 -0
- zrb/config/web_auth_config.py +50 -35
- zrb/context/any_shared_context.py +13 -2
- zrb/context/context.py +31 -3
- zrb/context/print_fn.py +13 -0
- zrb/context/shared_context.py +14 -1
- zrb/input/option_input.py +30 -2
- zrb/llm/agent/__init__.py +9 -0
- zrb/llm/agent/agent.py +215 -0
- zrb/llm/agent/summarizer.py +20 -0
- zrb/llm/app/__init__.py +10 -0
- zrb/llm/app/completion.py +281 -0
- zrb/llm/app/confirmation/allow_tool.py +66 -0
- zrb/llm/app/confirmation/handler.py +178 -0
- zrb/llm/app/confirmation/replace_confirmation.py +77 -0
- zrb/llm/app/keybinding.py +34 -0
- zrb/llm/app/layout.py +117 -0
- zrb/llm/app/lexer.py +155 -0
- zrb/llm/app/redirection.py +28 -0
- zrb/llm/app/style.py +16 -0
- zrb/llm/app/ui.py +733 -0
- zrb/llm/config/__init__.py +4 -0
- zrb/llm/config/config.py +122 -0
- zrb/llm/config/limiter.py +247 -0
- zrb/llm/history_manager/__init__.py +4 -0
- zrb/llm/history_manager/any_history_manager.py +23 -0
- zrb/llm/history_manager/file_history_manager.py +91 -0
- zrb/llm/history_processor/summarizer.py +108 -0
- zrb/llm/note/__init__.py +3 -0
- zrb/llm/note/manager.py +122 -0
- zrb/llm/prompt/__init__.py +29 -0
- zrb/llm/prompt/claude_compatibility.py +92 -0
- zrb/llm/prompt/compose.py +55 -0
- zrb/llm/prompt/default.py +51 -0
- zrb/llm/prompt/markdown/mandate.md +23 -0
- zrb/llm/prompt/markdown/persona.md +3 -0
- zrb/llm/prompt/markdown/summarizer.md +21 -0
- zrb/llm/prompt/note.py +41 -0
- zrb/llm/prompt/system_context.py +46 -0
- zrb/llm/prompt/zrb.py +41 -0
- zrb/llm/skill/__init__.py +3 -0
- zrb/llm/skill/manager.py +86 -0
- zrb/llm/task/__init__.py +4 -0
- zrb/llm/task/llm_chat_task.py +316 -0
- zrb/llm/task/llm_task.py +245 -0
- zrb/llm/tool/__init__.py +39 -0
- zrb/llm/tool/bash.py +75 -0
- zrb/llm/tool/code.py +266 -0
- zrb/llm/tool/file.py +419 -0
- zrb/llm/tool/note.py +70 -0
- zrb/{builtin/llm → llm}/tool/rag.py +8 -5
- zrb/llm/tool/search/brave.py +53 -0
- zrb/llm/tool/search/searxng.py +47 -0
- zrb/llm/tool/search/serpapi.py +47 -0
- zrb/llm/tool/skill.py +19 -0
- zrb/llm/tool/sub_agent.py +70 -0
- zrb/llm/tool/web.py +97 -0
- zrb/llm/tool/zrb_task.py +66 -0
- zrb/llm/util/attachment.py +101 -0
- zrb/llm/util/prompt.py +104 -0
- zrb/llm/util/stream_response.py +178 -0
- zrb/session/any_session.py +0 -3
- zrb/session/session.py +1 -1
- zrb/task/base/context.py +25 -13
- zrb/task/base/execution.py +52 -47
- zrb/task/base/lifecycle.py +7 -4
- zrb/task/base_task.py +48 -49
- zrb/task/base_trigger.py +4 -1
- zrb/task/cmd_task.py +6 -0
- zrb/task/http_check.py +11 -5
- zrb/task/make_task.py +3 -0
- zrb/task/rsync_task.py +5 -0
- zrb/task/scaffolder.py +7 -4
- zrb/task/scheduler.py +3 -0
- zrb/task/tcp_check.py +6 -4
- zrb/util/ascii_art/art/bee.txt +17 -0
- zrb/util/ascii_art/art/cat.txt +9 -0
- zrb/util/ascii_art/art/ghost.txt +16 -0
- zrb/util/ascii_art/art/panda.txt +17 -0
- zrb/util/ascii_art/art/rose.txt +14 -0
- zrb/util/ascii_art/art/unicorn.txt +15 -0
- zrb/util/ascii_art/banner.py +92 -0
- zrb/util/cli/markdown.py +22 -2
- zrb/util/cmd/command.py +33 -10
- zrb/util/file.py +51 -32
- zrb/util/match.py +78 -0
- zrb/util/run.py +3 -3
- {zrb-1.21.29.dist-info → zrb-2.0.0a4.dist-info}/METADATA +9 -15
- {zrb-1.21.29.dist-info → zrb-2.0.0a4.dist-info}/RECORD +100 -128
- zrb/attr/__init__.py +0 -0
- zrb/builtin/llm/attachment.py +0 -40
- zrb/builtin/llm/chat_completion.py +0 -274
- zrb/builtin/llm/chat_session.py +0 -270
- zrb/builtin/llm/chat_session_cmd.py +0 -288
- zrb/builtin/llm/chat_trigger.py +0 -79
- zrb/builtin/llm/history.py +0 -71
- zrb/builtin/llm/input.py +0 -27
- zrb/builtin/llm/llm_ask.py +0 -269
- zrb/builtin/llm/previous-session.js +0 -21
- zrb/builtin/llm/tool/__init__.py +0 -0
- zrb/builtin/llm/tool/api.py +0 -75
- zrb/builtin/llm/tool/cli.py +0 -52
- zrb/builtin/llm/tool/code.py +0 -236
- zrb/builtin/llm/tool/file.py +0 -560
- zrb/builtin/llm/tool/note.py +0 -84
- zrb/builtin/llm/tool/sub_agent.py +0 -150
- zrb/builtin/llm/tool/web.py +0 -171
- zrb/builtin/project/__init__.py +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/__init__.py +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/service/__init__.py +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/__init__.py +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/__init__.py +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/__init__.py +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/__init__.py +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/__init__.py +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/__init__.py +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/__init__.py +0 -0
- zrb/builtin/project/create/__init__.py +0 -0
- zrb/builtin/shell/__init__.py +0 -0
- zrb/builtin/shell/autocomplete/__init__.py +0 -0
- zrb/callback/__init__.py +0 -0
- zrb/cmd/__init__.py +0 -0
- zrb/config/default_prompt/interactive_system_prompt.md +0 -29
- zrb/config/default_prompt/persona.md +0 -1
- zrb/config/default_prompt/summarization_prompt.md +0 -57
- zrb/config/default_prompt/system_prompt.md +0 -38
- zrb/config/llm_config.py +0 -339
- zrb/config/llm_context/config.py +0 -166
- zrb/config/llm_context/config_parser.py +0 -40
- zrb/config/llm_context/workflow.py +0 -81
- zrb/config/llm_rate_limitter.py +0 -190
- zrb/content_transformer/__init__.py +0 -0
- zrb/context/__init__.py +0 -0
- zrb/dot_dict/__init__.py +0 -0
- zrb/env/__init__.py +0 -0
- zrb/group/__init__.py +0 -0
- zrb/input/__init__.py +0 -0
- zrb/runner/__init__.py +0 -0
- zrb/runner/web_route/__init__.py +0 -0
- zrb/runner/web_route/home_page/__init__.py +0 -0
- zrb/session/__init__.py +0 -0
- zrb/session_state_log/__init__.py +0 -0
- zrb/session_state_logger/__init__.py +0 -0
- zrb/task/__init__.py +0 -0
- zrb/task/base/__init__.py +0 -0
- zrb/task/llm/__init__.py +0 -0
- zrb/task/llm/agent.py +0 -204
- zrb/task/llm/agent_runner.py +0 -152
- zrb/task/llm/config.py +0 -122
- zrb/task/llm/conversation_history.py +0 -209
- zrb/task/llm/conversation_history_model.py +0 -67
- zrb/task/llm/default_workflow/coding/workflow.md +0 -41
- zrb/task/llm/default_workflow/copywriting/workflow.md +0 -68
- zrb/task/llm/default_workflow/git/workflow.md +0 -118
- zrb/task/llm/default_workflow/golang/workflow.md +0 -128
- zrb/task/llm/default_workflow/html-css/workflow.md +0 -135
- zrb/task/llm/default_workflow/java/workflow.md +0 -146
- zrb/task/llm/default_workflow/javascript/workflow.md +0 -158
- zrb/task/llm/default_workflow/python/workflow.md +0 -160
- zrb/task/llm/default_workflow/researching/workflow.md +0 -153
- zrb/task/llm/default_workflow/rust/workflow.md +0 -162
- zrb/task/llm/default_workflow/shell/workflow.md +0 -299
- zrb/task/llm/error.py +0 -95
- zrb/task/llm/file_replacement.py +0 -206
- zrb/task/llm/file_tool_model.py +0 -57
- zrb/task/llm/history_processor.py +0 -206
- zrb/task/llm/history_summarization.py +0 -25
- zrb/task/llm/print_node.py +0 -221
- zrb/task/llm/prompt.py +0 -321
- zrb/task/llm/subagent_conversation_history.py +0 -41
- zrb/task/llm/tool_wrapper.py +0 -361
- zrb/task/llm/typing.py +0 -3
- zrb/task/llm/workflow.py +0 -76
- zrb/task/llm_task.py +0 -379
- zrb/task_status/__init__.py +0 -0
- zrb/util/__init__.py +0 -0
- zrb/util/cli/__init__.py +0 -0
- zrb/util/cmd/__init__.py +0 -0
- zrb/util/codemod/__init__.py +0 -0
- zrb/util/string/__init__.py +0 -0
- zrb/xcom/__init__.py +0 -0
- /zrb/{config/default_prompt/file_extractor_system_prompt.md → llm/prompt/markdown/file_extractor.md} +0 -0
- /zrb/{config/default_prompt/repo_extractor_system_prompt.md → llm/prompt/markdown/repo_extractor.md} +0 -0
- /zrb/{config/default_prompt/repo_summarizer_system_prompt.md → llm/prompt/markdown/repo_summarizer.md} +0 -0
- {zrb-1.21.29.dist-info → zrb-2.0.0a4.dist-info}/WHEEL +0 -0
- {zrb-1.21.29.dist-info → zrb-2.0.0a4.dist-info}/entry_points.txt +0 -0
zrb/builtin/llm/llm_ask.py
DELETED
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from collections.abc import Callable
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
4
|
-
|
|
5
|
-
from zrb.builtin.group import llm_group
|
|
6
|
-
from zrb.builtin.llm.attachment import get_media_type
|
|
7
|
-
from zrb.builtin.llm.chat_session import get_llm_ask_input_mapping, read_user_prompt
|
|
8
|
-
from zrb.builtin.llm.history import read_chat_conversation, write_chat_conversation
|
|
9
|
-
from zrb.builtin.llm.input import PreviousSessionInput
|
|
10
|
-
from zrb.builtin.llm.tool.api import (
|
|
11
|
-
create_get_current_location,
|
|
12
|
-
create_get_current_weather,
|
|
13
|
-
)
|
|
14
|
-
from zrb.builtin.llm.tool.cli import run_shell_command
|
|
15
|
-
from zrb.builtin.llm.tool.code import analyze_repo
|
|
16
|
-
from zrb.builtin.llm.tool.file import (
|
|
17
|
-
analyze_file,
|
|
18
|
-
list_files,
|
|
19
|
-
read_from_file,
|
|
20
|
-
replace_in_file,
|
|
21
|
-
search_files,
|
|
22
|
-
write_to_file,
|
|
23
|
-
)
|
|
24
|
-
from zrb.builtin.llm.tool.note import (
|
|
25
|
-
read_contextual_note,
|
|
26
|
-
read_long_term_note,
|
|
27
|
-
write_contextual_note,
|
|
28
|
-
write_long_term_note,
|
|
29
|
-
)
|
|
30
|
-
from zrb.builtin.llm.tool.web import (
|
|
31
|
-
create_search_internet_tool,
|
|
32
|
-
open_web_page,
|
|
33
|
-
)
|
|
34
|
-
from zrb.callback.callback import Callback
|
|
35
|
-
from zrb.config.config import CFG
|
|
36
|
-
from zrb.config.llm_config import llm_config
|
|
37
|
-
from zrb.context.any_context import AnyContext
|
|
38
|
-
from zrb.input.any_input import AnyInput
|
|
39
|
-
from zrb.input.bool_input import BoolInput
|
|
40
|
-
from zrb.input.str_input import StrInput
|
|
41
|
-
from zrb.input.text_input import TextInput
|
|
42
|
-
from zrb.task.base_trigger import BaseTrigger
|
|
43
|
-
from zrb.task.llm_task import LLMTask
|
|
44
|
-
from zrb.util.string.conversion import to_boolean
|
|
45
|
-
|
|
46
|
-
if TYPE_CHECKING:
|
|
47
|
-
from pydantic_ai import AbstractToolset, Tool, UserContent
|
|
48
|
-
|
|
49
|
-
ToolOrCallable = Tool | Callable
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def _get_toolset(ctx: AnyContext) -> list["AbstractToolset[None] | str"]:
|
|
53
|
-
cwd = os.getcwd()
|
|
54
|
-
toolsets = []
|
|
55
|
-
for config_path in [
|
|
56
|
-
os.path.join(cwd, "mcp_config.json"),
|
|
57
|
-
os.path.join(cwd, "mcp-config.json"),
|
|
58
|
-
]:
|
|
59
|
-
if os.path.isfile(config_path):
|
|
60
|
-
toolsets.append(config_path)
|
|
61
|
-
return toolsets
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def _get_tool(ctx: AnyContext) -> list["ToolOrCallable"]:
|
|
65
|
-
tools = [
|
|
66
|
-
read_long_term_note,
|
|
67
|
-
write_long_term_note,
|
|
68
|
-
read_contextual_note,
|
|
69
|
-
write_contextual_note,
|
|
70
|
-
]
|
|
71
|
-
if CFG.LLM_ALLOW_ANALYZE_REPO:
|
|
72
|
-
tools.append(analyze_repo)
|
|
73
|
-
if CFG.LLM_ALLOW_ANALYZE_FILE:
|
|
74
|
-
tools.append(analyze_file)
|
|
75
|
-
if CFG.LLM_ALLOW_ACCESS_LOCAL_FILE:
|
|
76
|
-
tools.append(search_files)
|
|
77
|
-
tools.append(list_files)
|
|
78
|
-
tools.append(read_from_file)
|
|
79
|
-
tools.append(replace_in_file)
|
|
80
|
-
tools.append(write_to_file)
|
|
81
|
-
if CFG.LLM_ALLOW_ACCESS_SHELL:
|
|
82
|
-
tools.append(run_shell_command)
|
|
83
|
-
if CFG.LLM_ALLOW_OPEN_WEB_PAGE:
|
|
84
|
-
tools.append(open_web_page)
|
|
85
|
-
if CFG.LLM_ALLOW_GET_CURRENT_LOCATION:
|
|
86
|
-
tools.append(create_get_current_location())
|
|
87
|
-
if CFG.LLM_ALLOW_GET_CURRENT_WEATHER:
|
|
88
|
-
tools.append(create_get_current_weather())
|
|
89
|
-
if CFG.SERPAPI_KEY != "" and CFG.LLM_ALLOW_SEARCH_INTERNET:
|
|
90
|
-
tools.append(create_search_internet_tool())
|
|
91
|
-
return tools
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
def _get_default_yolo_mode(ctx: AnyContext) -> str:
|
|
95
|
-
default_value = llm_config.default_yolo_mode
|
|
96
|
-
if isinstance(default_value, list):
|
|
97
|
-
return ",".join(default_value)
|
|
98
|
-
return f"{default_value}"
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
def _render_yolo_mode_input(ctx: AnyContext) -> list[str] | bool:
|
|
102
|
-
if ctx.input.yolo.strip() == "":
|
|
103
|
-
return []
|
|
104
|
-
elements = [element.strip() for element in ctx.input.yolo.split(",")]
|
|
105
|
-
if len(elements) == 1:
|
|
106
|
-
try:
|
|
107
|
-
return to_boolean(elements[0])
|
|
108
|
-
except Exception:
|
|
109
|
-
pass
|
|
110
|
-
return elements
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
def _render_attach_input(ctx: AnyContext) -> "list[UserContent]":
|
|
114
|
-
from pathlib import Path
|
|
115
|
-
|
|
116
|
-
from pydantic_ai import BinaryContent
|
|
117
|
-
|
|
118
|
-
attachment_paths: list[str] = [
|
|
119
|
-
attachment_path.strip()
|
|
120
|
-
for attachment_path in ctx.input.attach.split(",")
|
|
121
|
-
if attachment_path.strip() != ""
|
|
122
|
-
]
|
|
123
|
-
if len(attachment_paths) == 0:
|
|
124
|
-
return []
|
|
125
|
-
attachments = []
|
|
126
|
-
for attachment_path in attachment_paths:
|
|
127
|
-
attachment_path = os.path.abspath(os.path.expanduser(attachment_path))
|
|
128
|
-
media_type = get_media_type(attachment_path)
|
|
129
|
-
if media_type is None:
|
|
130
|
-
ctx.log_error(f"Cannot get media type of {attachment_path}")
|
|
131
|
-
continue
|
|
132
|
-
data = Path(attachment_path).read_bytes()
|
|
133
|
-
attachments.append(BinaryContent(data, media_type=media_type))
|
|
134
|
-
return attachments
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
def _get_inputs(require_message: bool = True) -> list[AnyInput | None]:
|
|
138
|
-
return [
|
|
139
|
-
StrInput(
|
|
140
|
-
"model",
|
|
141
|
-
description="LLM Model",
|
|
142
|
-
prompt="LLM Model",
|
|
143
|
-
default="",
|
|
144
|
-
allow_positional_parsing=False,
|
|
145
|
-
always_prompt=False,
|
|
146
|
-
allow_empty=True,
|
|
147
|
-
),
|
|
148
|
-
StrInput(
|
|
149
|
-
"base-url",
|
|
150
|
-
description="LLM API Base URL",
|
|
151
|
-
prompt="LLM API Base URL",
|
|
152
|
-
default="",
|
|
153
|
-
allow_positional_parsing=False,
|
|
154
|
-
always_prompt=False,
|
|
155
|
-
allow_empty=True,
|
|
156
|
-
),
|
|
157
|
-
StrInput(
|
|
158
|
-
"api-key",
|
|
159
|
-
description="LLM API Key",
|
|
160
|
-
prompt="LLM API Key",
|
|
161
|
-
default="",
|
|
162
|
-
allow_positional_parsing=False,
|
|
163
|
-
always_prompt=False,
|
|
164
|
-
allow_empty=True,
|
|
165
|
-
),
|
|
166
|
-
TextInput(
|
|
167
|
-
"system-prompt",
|
|
168
|
-
description="System prompt",
|
|
169
|
-
prompt="System prompt",
|
|
170
|
-
default="",
|
|
171
|
-
allow_positional_parsing=False,
|
|
172
|
-
always_prompt=False,
|
|
173
|
-
),
|
|
174
|
-
TextInput(
|
|
175
|
-
"workflows",
|
|
176
|
-
description="Workflows",
|
|
177
|
-
prompt="Workflows",
|
|
178
|
-
default=lambda ctx: ",".join(llm_config.default_workflows),
|
|
179
|
-
allow_positional_parsing=False,
|
|
180
|
-
always_prompt=False,
|
|
181
|
-
),
|
|
182
|
-
BoolInput(
|
|
183
|
-
"start-new",
|
|
184
|
-
description="Start new session (LLM Agent will forget past conversation)",
|
|
185
|
-
prompt="Start new session (LLM Agent will forget past conversation)",
|
|
186
|
-
default=False,
|
|
187
|
-
allow_positional_parsing=False,
|
|
188
|
-
always_prompt=False,
|
|
189
|
-
),
|
|
190
|
-
StrInput(
|
|
191
|
-
"yolo",
|
|
192
|
-
description="YOLO mode (LLM Agent will start in YOLO Mode)",
|
|
193
|
-
prompt="YOLO mode (LLM Agent will start in YOLO Mode)",
|
|
194
|
-
default=_get_default_yolo_mode,
|
|
195
|
-
allow_positional_parsing=False,
|
|
196
|
-
always_prompt=False,
|
|
197
|
-
),
|
|
198
|
-
TextInput(
|
|
199
|
-
"message",
|
|
200
|
-
description="User message",
|
|
201
|
-
prompt="Your message",
|
|
202
|
-
always_prompt=require_message,
|
|
203
|
-
allow_empty=not require_message,
|
|
204
|
-
),
|
|
205
|
-
StrInput(
|
|
206
|
-
name="attach",
|
|
207
|
-
description="Comma separated attachments",
|
|
208
|
-
default="",
|
|
209
|
-
allow_positional_parsing=False,
|
|
210
|
-
always_prompt=False,
|
|
211
|
-
),
|
|
212
|
-
PreviousSessionInput(
|
|
213
|
-
"previous-session",
|
|
214
|
-
description="Previous conversation session",
|
|
215
|
-
prompt="Previous conversation session (can be empty)",
|
|
216
|
-
allow_positional_parsing=False,
|
|
217
|
-
allow_empty=True,
|
|
218
|
-
always_prompt=False,
|
|
219
|
-
),
|
|
220
|
-
]
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
llm_ask = LLMTask(
|
|
224
|
-
name="llm-ask",
|
|
225
|
-
input=_get_inputs(True),
|
|
226
|
-
description="❓ Ask LLM",
|
|
227
|
-
model=lambda ctx: None if ctx.input.model.strip() == "" else ctx.input.model,
|
|
228
|
-
model_base_url=lambda ctx: (
|
|
229
|
-
None if ctx.input.base_url.strip() == "" else ctx.input.base_url
|
|
230
|
-
),
|
|
231
|
-
model_api_key=lambda ctx: (
|
|
232
|
-
None if ctx.input.api_key.strip() == "" else ctx.input.api_key
|
|
233
|
-
),
|
|
234
|
-
conversation_history_reader=read_chat_conversation,
|
|
235
|
-
conversation_history_writer=write_chat_conversation,
|
|
236
|
-
system_prompt=lambda ctx: (
|
|
237
|
-
None if ctx.input.system_prompt.strip() == "" else ctx.input.system_prompt
|
|
238
|
-
),
|
|
239
|
-
workflows=lambda ctx: (
|
|
240
|
-
None if ctx.input.workflows.strip() == "" else ctx.input.workflows.split(",")
|
|
241
|
-
),
|
|
242
|
-
attachment=_render_attach_input,
|
|
243
|
-
message="{ctx.input.message}",
|
|
244
|
-
tools=_get_tool,
|
|
245
|
-
toolsets=_get_toolset,
|
|
246
|
-
yolo_mode=_render_yolo_mode_input,
|
|
247
|
-
retries=0,
|
|
248
|
-
)
|
|
249
|
-
llm_group.add_task(llm_ask, alias="ask")
|
|
250
|
-
|
|
251
|
-
llm_group.add_task(
|
|
252
|
-
BaseTrigger(
|
|
253
|
-
name="llm-chat",
|
|
254
|
-
input=_get_inputs(False),
|
|
255
|
-
description="💬 Chat with LLM",
|
|
256
|
-
queue_name="ask_trigger",
|
|
257
|
-
action=read_user_prompt,
|
|
258
|
-
callback=Callback(
|
|
259
|
-
task=llm_ask,
|
|
260
|
-
input_mapping=get_llm_ask_input_mapping,
|
|
261
|
-
result_queue="ask_result",
|
|
262
|
-
error_queue="ask_error",
|
|
263
|
-
session_name_queue="ask_session_name",
|
|
264
|
-
),
|
|
265
|
-
retries=0,
|
|
266
|
-
cli_only=True,
|
|
267
|
-
),
|
|
268
|
-
alias="chat",
|
|
269
|
-
)
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
async function updatePreviousSession(event) {
|
|
2
|
-
const currentInput = event.target;
|
|
3
|
-
if (currentInput.name === "CURRENT_INPUT_NAME") {
|
|
4
|
-
return
|
|
5
|
-
}
|
|
6
|
-
const previousSessionInput = submitTaskForm.querySelector('[name="CURRENT_INPUT_NAME"]');
|
|
7
|
-
if (previousSessionInput) {
|
|
8
|
-
const currentSessionName = cfg.SESSION_NAME
|
|
9
|
-
previousSessionInput.value = currentSessionName;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
document.getElementById("submit-task-form").querySelectorAll("input[name], textarea[name]").forEach((element) => {
|
|
14
|
-
element.addEventListener("input", updatePreviousSession);
|
|
15
|
-
element.addEventListener("keyup", updatePreviousSession);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
document.getElementById("submit-task-form").querySelectorAll("select[name]").forEach((element) => {
|
|
19
|
-
element.addEventListener("change", updatePreviousSession);
|
|
20
|
-
});
|
|
21
|
-
|
zrb/builtin/llm/tool/__init__.py
DELETED
|
File without changes
|
zrb/builtin/llm/tool/api.py
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
from typing import Any, Callable, Literal
|
|
2
|
-
|
|
3
|
-
from zrb.config.llm_config import llm_config
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def create_get_current_location() -> Callable:
|
|
7
|
-
if llm_config.default_current_location_tool is not None:
|
|
8
|
-
return llm_config.default_current_location_tool
|
|
9
|
-
|
|
10
|
-
def get_current_location() -> dict[str, float]:
|
|
11
|
-
"""
|
|
12
|
-
Gets the user's current geographical location (latitude and longitude).
|
|
13
|
-
|
|
14
|
-
Example:
|
|
15
|
-
get_current_location() # Returns {'lat': 48.8584, 'lon': 2.2945}
|
|
16
|
-
|
|
17
|
-
Returns:
|
|
18
|
-
dict: Dictionary with 'lat' and 'lon' keys.
|
|
19
|
-
"""
|
|
20
|
-
import requests
|
|
21
|
-
|
|
22
|
-
try:
|
|
23
|
-
response = requests.get("http://ip-api.com/json?fields=lat,lon", timeout=5)
|
|
24
|
-
response.raise_for_status()
|
|
25
|
-
return dict(response.json())
|
|
26
|
-
except requests.RequestException as e:
|
|
27
|
-
raise requests.RequestException(f"Failed to get location: {e}")
|
|
28
|
-
|
|
29
|
-
return get_current_location
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def create_get_current_weather() -> Callable:
|
|
33
|
-
if llm_config.default_current_weather_tool is not None:
|
|
34
|
-
return llm_config.default_current_weather_tool
|
|
35
|
-
|
|
36
|
-
def get_current_weather(
|
|
37
|
-
latitude: float,
|
|
38
|
-
longitude: float,
|
|
39
|
-
temperature_unit: Literal["celsius", "fahrenheit"],
|
|
40
|
-
) -> dict[str, Any]:
|
|
41
|
-
"""
|
|
42
|
-
Gets current weather conditions for a given location.
|
|
43
|
-
|
|
44
|
-
Example:
|
|
45
|
-
get_current_weather(
|
|
46
|
-
latitude=34.0522, longitude=-118.2437, temperature_unit='fahrenheit'
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
Args:
|
|
50
|
-
latitude (float): Latitude of the location.
|
|
51
|
-
longitude (float): Longitude of the location.
|
|
52
|
-
temperature_unit (Literal): 'celsius' or 'fahrenheit'.
|
|
53
|
-
|
|
54
|
-
Returns:
|
|
55
|
-
dict: Detailed weather data.
|
|
56
|
-
"""
|
|
57
|
-
import requests
|
|
58
|
-
|
|
59
|
-
try:
|
|
60
|
-
response = requests.get(
|
|
61
|
-
"https://api.open-meteo.com/v1/forecast",
|
|
62
|
-
params={
|
|
63
|
-
"latitude": latitude,
|
|
64
|
-
"longitude": longitude,
|
|
65
|
-
"temperature_unit": temperature_unit,
|
|
66
|
-
"current_weather": True,
|
|
67
|
-
},
|
|
68
|
-
timeout=5,
|
|
69
|
-
)
|
|
70
|
-
response.raise_for_status()
|
|
71
|
-
return dict(response.json())
|
|
72
|
-
except requests.RequestException as e:
|
|
73
|
-
raise requests.RequestException(f"Failed to get weather data: {e}")
|
|
74
|
-
|
|
75
|
-
return get_current_weather
|
zrb/builtin/llm/tool/cli.py
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import subprocess
|
|
2
|
-
import sys
|
|
3
|
-
|
|
4
|
-
if sys.version_info >= (3, 12):
|
|
5
|
-
from typing import TypedDict
|
|
6
|
-
else:
|
|
7
|
-
from typing_extensions import TypedDict
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class ShellCommandResult(TypedDict):
|
|
11
|
-
"""
|
|
12
|
-
Result of shell command execution
|
|
13
|
-
|
|
14
|
-
Attributes:
|
|
15
|
-
return_code: The return code, 0 indicating no error
|
|
16
|
-
stdout: Standard output
|
|
17
|
-
stderr: Standard error
|
|
18
|
-
"""
|
|
19
|
-
|
|
20
|
-
return_code: int
|
|
21
|
-
stdout: str
|
|
22
|
-
stderr: str
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def run_shell_command(command: str) -> ShellCommandResult:
|
|
26
|
-
"""
|
|
27
|
-
Executes a non-interactive shell command on the user's machine.
|
|
28
|
-
|
|
29
|
-
CRITICAL: This tool runs with user-level permissions. Explain commands that modify
|
|
30
|
-
the system (e.g., `git`, `pip`) and ask for confirmation.
|
|
31
|
-
IMPORTANT: Long-running processes should be run in the background (e.g., `command &`).
|
|
32
|
-
|
|
33
|
-
Example:
|
|
34
|
-
run_shell_command(command='ls -l')
|
|
35
|
-
|
|
36
|
-
Args:
|
|
37
|
-
command (str): The exact shell command to be executed.
|
|
38
|
-
|
|
39
|
-
Returns:
|
|
40
|
-
dict: return_code, stdout, and stderr.
|
|
41
|
-
"""
|
|
42
|
-
result = subprocess.run(
|
|
43
|
-
command,
|
|
44
|
-
shell=True,
|
|
45
|
-
capture_output=True,
|
|
46
|
-
text=True,
|
|
47
|
-
)
|
|
48
|
-
return {
|
|
49
|
-
"return_code": result.returncode,
|
|
50
|
-
"stdout": result.stdout,
|
|
51
|
-
"stderr": result.stderr,
|
|
52
|
-
}
|
zrb/builtin/llm/tool/code.py
DELETED
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import os
|
|
3
|
-
|
|
4
|
-
from zrb.builtin.llm.tool.file import DEFAULT_EXCLUDED_PATTERNS, is_excluded
|
|
5
|
-
from zrb.builtin.llm.tool.sub_agent import create_sub_agent_tool
|
|
6
|
-
from zrb.config.config import CFG
|
|
7
|
-
from zrb.config.llm_rate_limitter import llm_rate_limitter
|
|
8
|
-
from zrb.context.any_context import AnyContext
|
|
9
|
-
from zrb.util.cli.style import stylize_faint
|
|
10
|
-
|
|
11
|
-
_DEFAULT_EXTENSIONS = [
|
|
12
|
-
"py",
|
|
13
|
-
"go",
|
|
14
|
-
"java",
|
|
15
|
-
"ts",
|
|
16
|
-
"js",
|
|
17
|
-
"rs",
|
|
18
|
-
"rb",
|
|
19
|
-
"php",
|
|
20
|
-
"sh",
|
|
21
|
-
"bash",
|
|
22
|
-
"c",
|
|
23
|
-
"cpp",
|
|
24
|
-
"h",
|
|
25
|
-
"hpp",
|
|
26
|
-
"cs",
|
|
27
|
-
"swift",
|
|
28
|
-
"kt",
|
|
29
|
-
"scala",
|
|
30
|
-
"m",
|
|
31
|
-
"pl",
|
|
32
|
-
"lua",
|
|
33
|
-
"sql",
|
|
34
|
-
"html",
|
|
35
|
-
"css",
|
|
36
|
-
"scss",
|
|
37
|
-
"less",
|
|
38
|
-
"json",
|
|
39
|
-
"yaml",
|
|
40
|
-
"yml",
|
|
41
|
-
"toml",
|
|
42
|
-
"ini",
|
|
43
|
-
"xml",
|
|
44
|
-
"md",
|
|
45
|
-
"rst",
|
|
46
|
-
"txt",
|
|
47
|
-
]
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
async def analyze_repo(
|
|
51
|
-
ctx: AnyContext,
|
|
52
|
-
path: str,
|
|
53
|
-
query: str,
|
|
54
|
-
extensions: list[str] = _DEFAULT_EXTENSIONS,
|
|
55
|
-
exclude_patterns: list[str] = DEFAULT_EXCLUDED_PATTERNS,
|
|
56
|
-
extraction_token_threshold: int | None = None,
|
|
57
|
-
summarization_token_threshold: int | None = None,
|
|
58
|
-
) -> str:
|
|
59
|
-
"""
|
|
60
|
-
Analyzes a code repository or directory to answer a specific query.
|
|
61
|
-
|
|
62
|
-
CRITICAL: The quality of analysis depends entirely on the query. Vague queries yield poor
|
|
63
|
-
results.
|
|
64
|
-
IMPORTANT: This tool can be slow and expensive on large repositories. Use judiciously.
|
|
65
|
-
|
|
66
|
-
Example:
|
|
67
|
-
analyze_repo(
|
|
68
|
-
path='src/my_project',
|
|
69
|
-
query='Summarize the main functionalities by analyzing Python files.',
|
|
70
|
-
extensions=['py']
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
Args:
|
|
74
|
-
ctx (AnyContext): The execution context.
|
|
75
|
-
path (str): Path to the directory or repository.
|
|
76
|
-
query (str): Clear and specific analysis question or goal.
|
|
77
|
-
extensions (list[str], optional): File extensions to include.
|
|
78
|
-
exclude_patterns (list[str], optional): Glob patterns to exclude.
|
|
79
|
-
extraction_token_threshold (int, optional): Token limit for extraction sub-agent.
|
|
80
|
-
summarization_token_threshold (int, optional): Token limit for summarization sub-agent.
|
|
81
|
-
|
|
82
|
-
Returns:
|
|
83
|
-
str: Detailed, markdown-formatted analysis and summary.
|
|
84
|
-
"""
|
|
85
|
-
if extraction_token_threshold is None:
|
|
86
|
-
extraction_token_threshold = CFG.LLM_REPO_ANALYSIS_EXTRACTION_TOKEN_THRESHOLD
|
|
87
|
-
if summarization_token_threshold is None:
|
|
88
|
-
summarization_token_threshold = (
|
|
89
|
-
CFG.LLM_REPO_ANALYSIS_SUMMARIZATION_TOKEN_THRESHOLD
|
|
90
|
-
)
|
|
91
|
-
abs_path = os.path.abspath(os.path.expanduser(path))
|
|
92
|
-
file_metadatas = _get_file_metadatas(abs_path, extensions, exclude_patterns)
|
|
93
|
-
ctx.print(stylize_faint(" 📝 Extraction"), plain=True)
|
|
94
|
-
extracted_infos = await _extract_info(
|
|
95
|
-
ctx,
|
|
96
|
-
file_metadatas=file_metadatas,
|
|
97
|
-
query=query,
|
|
98
|
-
token_limit=extraction_token_threshold,
|
|
99
|
-
)
|
|
100
|
-
if len(extracted_infos) == 0:
|
|
101
|
-
raise RuntimeError(
|
|
102
|
-
"No info can be extracted, adjust extensions or exclude_patterns."
|
|
103
|
-
)
|
|
104
|
-
if len(extracted_infos) == 1:
|
|
105
|
-
return extracted_infos[0]
|
|
106
|
-
summarized_infos = extracted_infos
|
|
107
|
-
while len(summarized_infos) > 1:
|
|
108
|
-
ctx.print(stylize_faint(" 📝 Summarization"), plain=True)
|
|
109
|
-
summarized_infos = await _summarize_info(
|
|
110
|
-
ctx,
|
|
111
|
-
extracted_infos=summarized_infos,
|
|
112
|
-
query=query,
|
|
113
|
-
token_limit=summarization_token_threshold,
|
|
114
|
-
)
|
|
115
|
-
return summarized_infos[0]
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
def _get_file_metadatas(
|
|
119
|
-
dir_path: str,
|
|
120
|
-
extensions: list[str],
|
|
121
|
-
exclude_patterns: list[str],
|
|
122
|
-
) -> list[dict[str, str]]:
|
|
123
|
-
metadata_list = []
|
|
124
|
-
for root, _, files in os.walk(dir_path):
|
|
125
|
-
files.sort()
|
|
126
|
-
for file in files:
|
|
127
|
-
if not any(file.endswith(f".{ext}") for ext in extensions):
|
|
128
|
-
continue
|
|
129
|
-
file_path = os.path.join(root, file)
|
|
130
|
-
try:
|
|
131
|
-
rel_path = os.path.relpath(file_path, dir_path)
|
|
132
|
-
if is_excluded(rel_path, exclude_patterns):
|
|
133
|
-
continue
|
|
134
|
-
with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
|
|
135
|
-
metadata_list.append({"path": rel_path, "content": f.read()})
|
|
136
|
-
except Exception as e:
|
|
137
|
-
print(f"Error reading file {file_path}: {e}")
|
|
138
|
-
metadata_list.sort(key=lambda m: m["path"])
|
|
139
|
-
return metadata_list
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
async def _extract_info(
|
|
143
|
-
ctx: AnyContext,
|
|
144
|
-
file_metadatas: list[dict[str, str]],
|
|
145
|
-
query: str,
|
|
146
|
-
token_limit: int,
|
|
147
|
-
) -> list[str]:
|
|
148
|
-
extract = create_sub_agent_tool(
|
|
149
|
-
tool_name="extract",
|
|
150
|
-
tool_description="extract",
|
|
151
|
-
system_prompt=CFG.LLM_REPO_EXTRACTOR_SYSTEM_PROMPT,
|
|
152
|
-
auto_summarize=False,
|
|
153
|
-
remember_history=False,
|
|
154
|
-
)
|
|
155
|
-
extracted_infos = []
|
|
156
|
-
content_buffer = []
|
|
157
|
-
current_token_count = 0
|
|
158
|
-
for metadata in file_metadatas:
|
|
159
|
-
path = metadata.get("path", "")
|
|
160
|
-
content = metadata.get("content", "")
|
|
161
|
-
file_obj = {"path": path, "content": content}
|
|
162
|
-
file_str = json.dumps(file_obj)
|
|
163
|
-
if current_token_count + llm_rate_limitter.count_token(file_str) > token_limit:
|
|
164
|
-
if content_buffer:
|
|
165
|
-
prompt = json.dumps(_create_extract_info_prompt(query, content_buffer))
|
|
166
|
-
extracted_info = await extract(
|
|
167
|
-
ctx, llm_rate_limitter.clip_prompt(prompt, token_limit)
|
|
168
|
-
)
|
|
169
|
-
extracted_infos.append(extracted_info)
|
|
170
|
-
content_buffer = [file_obj]
|
|
171
|
-
current_token_count = llm_rate_limitter.count_token(file_str)
|
|
172
|
-
else:
|
|
173
|
-
content_buffer.append(file_obj)
|
|
174
|
-
current_token_count += llm_rate_limitter.count_token(file_str)
|
|
175
|
-
# Process any remaining content in the buffer
|
|
176
|
-
if content_buffer:
|
|
177
|
-
prompt = json.dumps(_create_extract_info_prompt(query, content_buffer))
|
|
178
|
-
extracted_info = await extract(
|
|
179
|
-
ctx, llm_rate_limitter.clip_prompt(prompt, token_limit)
|
|
180
|
-
)
|
|
181
|
-
extracted_infos.append(extracted_info)
|
|
182
|
-
return extracted_infos
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
def _create_extract_info_prompt(query: str, content_buffer: list[dict]) -> dict:
|
|
186
|
-
return {
|
|
187
|
-
"main_assistant_query": query,
|
|
188
|
-
"files": content_buffer,
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
async def _summarize_info(
|
|
193
|
-
ctx: AnyContext,
|
|
194
|
-
extracted_infos: list[str],
|
|
195
|
-
query: str,
|
|
196
|
-
token_limit: int,
|
|
197
|
-
) -> list[str]:
|
|
198
|
-
summarize = create_sub_agent_tool(
|
|
199
|
-
tool_name="extract",
|
|
200
|
-
tool_description="extract",
|
|
201
|
-
system_prompt=CFG.LLM_REPO_SUMMARIZER_SYSTEM_PROMPT,
|
|
202
|
-
auto_summarize=False,
|
|
203
|
-
remember_history=False,
|
|
204
|
-
)
|
|
205
|
-
summarized_infos = []
|
|
206
|
-
content_buffer = ""
|
|
207
|
-
for extracted_info in extracted_infos:
|
|
208
|
-
new_prompt = content_buffer + extracted_info
|
|
209
|
-
if llm_rate_limitter.count_token(new_prompt) > token_limit:
|
|
210
|
-
if content_buffer:
|
|
211
|
-
prompt = json.dumps(
|
|
212
|
-
_create_summarize_info_prompt(query, content_buffer)
|
|
213
|
-
)
|
|
214
|
-
summarized_info = await summarize(
|
|
215
|
-
ctx, llm_rate_limitter.clip_prompt(prompt, token_limit)
|
|
216
|
-
)
|
|
217
|
-
summarized_infos.append(summarized_info)
|
|
218
|
-
content_buffer = extracted_info
|
|
219
|
-
else:
|
|
220
|
-
content_buffer += extracted_info + "\n"
|
|
221
|
-
|
|
222
|
-
# Process any remaining content in the buffer
|
|
223
|
-
if content_buffer:
|
|
224
|
-
prompt = json.dumps(_create_summarize_info_prompt(query, content_buffer))
|
|
225
|
-
summarized_info = await summarize(
|
|
226
|
-
ctx, llm_rate_limitter.clip_prompt(prompt, token_limit)
|
|
227
|
-
)
|
|
228
|
-
summarized_infos.append(summarized_info)
|
|
229
|
-
return summarized_infos
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
def _create_summarize_info_prompt(query: str, content_buffer: str) -> dict:
|
|
233
|
-
return {
|
|
234
|
-
"main_assistant_query": query,
|
|
235
|
-
"extracted_info": content_buffer,
|
|
236
|
-
}
|