zrb 1.13.1__py3-none-any.whl → 1.21.17__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.
- zrb/__init__.py +2 -6
- zrb/attr/type.py +8 -8
- zrb/builtin/__init__.py +2 -0
- zrb/builtin/group.py +31 -15
- zrb/builtin/http.py +7 -8
- zrb/builtin/llm/attachment.py +40 -0
- zrb/builtin/llm/chat_session.py +130 -144
- zrb/builtin/llm/chat_session_cmd.py +226 -0
- zrb/builtin/llm/chat_trigger.py +73 -0
- zrb/builtin/llm/history.py +4 -4
- zrb/builtin/llm/llm_ask.py +218 -110
- zrb/builtin/llm/tool/api.py +74 -62
- zrb/builtin/llm/tool/cli.py +35 -16
- zrb/builtin/llm/tool/code.py +49 -47
- zrb/builtin/llm/tool/file.py +262 -251
- zrb/builtin/llm/tool/note.py +84 -0
- zrb/builtin/llm/tool/rag.py +25 -18
- zrb/builtin/llm/tool/sub_agent.py +29 -22
- zrb/builtin/llm/tool/web.py +135 -143
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_util.py +7 -7
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/add_module_util.py +5 -5
- zrb/builtin/project/add/fastapp/fastapp_util.py +1 -1
- zrb/builtin/searxng/config/settings.yml +5671 -0
- zrb/builtin/searxng/start.py +21 -0
- zrb/builtin/setup/latex/ubuntu.py +1 -0
- zrb/builtin/setup/ubuntu.py +1 -1
- zrb/builtin/shell/autocomplete/bash.py +4 -3
- zrb/builtin/shell/autocomplete/zsh.py +4 -3
- zrb/config/config.py +255 -78
- zrb/config/default_prompt/file_extractor_system_prompt.md +109 -9
- zrb/config/default_prompt/interactive_system_prompt.md +24 -30
- zrb/config/default_prompt/persona.md +1 -1
- zrb/config/default_prompt/repo_extractor_system_prompt.md +31 -31
- zrb/config/default_prompt/repo_summarizer_system_prompt.md +27 -8
- zrb/config/default_prompt/summarization_prompt.md +8 -13
- zrb/config/default_prompt/system_prompt.md +36 -30
- zrb/config/llm_config.py +129 -24
- zrb/config/llm_context/config.py +127 -90
- zrb/config/llm_context/config_parser.py +1 -7
- zrb/config/llm_context/workflow.py +81 -0
- zrb/config/llm_rate_limitter.py +89 -45
- zrb/context/any_shared_context.py +7 -1
- zrb/context/context.py +8 -2
- zrb/context/shared_context.py +6 -8
- zrb/group/any_group.py +12 -5
- zrb/group/group.py +67 -3
- zrb/input/any_input.py +5 -1
- zrb/input/base_input.py +18 -6
- zrb/input/text_input.py +7 -24
- zrb/runner/cli.py +21 -20
- zrb/runner/common_util.py +24 -19
- zrb/runner/web_route/task_input_api_route.py +5 -5
- zrb/runner/web_route/task_session_api_route.py +1 -4
- zrb/runner/web_util/user.py +7 -3
- zrb/session/any_session.py +12 -6
- zrb/session/session.py +39 -18
- zrb/task/any_task.py +24 -3
- zrb/task/base/context.py +17 -9
- zrb/task/base/execution.py +15 -8
- zrb/task/base/lifecycle.py +8 -4
- zrb/task/base/monitoring.py +12 -7
- zrb/task/base_task.py +69 -5
- zrb/task/base_trigger.py +12 -5
- zrb/task/llm/agent.py +138 -52
- zrb/task/llm/config.py +45 -13
- zrb/task/llm/conversation_history.py +76 -6
- zrb/task/llm/conversation_history_model.py +0 -168
- zrb/task/llm/default_workflow/coding/workflow.md +41 -0
- zrb/task/llm/default_workflow/copywriting/workflow.md +68 -0
- zrb/task/llm/default_workflow/git/workflow.md +118 -0
- zrb/task/llm/default_workflow/golang/workflow.md +128 -0
- zrb/task/llm/default_workflow/html-css/workflow.md +135 -0
- zrb/task/llm/default_workflow/java/workflow.md +146 -0
- zrb/task/llm/default_workflow/javascript/workflow.md +158 -0
- zrb/task/llm/default_workflow/python/workflow.md +160 -0
- zrb/task/llm/default_workflow/researching/workflow.md +153 -0
- zrb/task/llm/default_workflow/rust/workflow.md +162 -0
- zrb/task/llm/default_workflow/shell/workflow.md +299 -0
- zrb/task/llm/file_replacement.py +206 -0
- zrb/task/llm/file_tool_model.py +57 -0
- zrb/task/llm/history_summarization.py +22 -35
- zrb/task/llm/history_summarization_tool.py +24 -0
- zrb/task/llm/print_node.py +182 -63
- zrb/task/llm/prompt.py +213 -153
- zrb/task/llm/tool_wrapper.py +210 -53
- zrb/task/llm/workflow.py +76 -0
- zrb/task/llm_task.py +98 -47
- zrb/task/make_task.py +2 -3
- zrb/task/rsync_task.py +25 -10
- zrb/task/scheduler.py +4 -4
- zrb/util/attr.py +50 -40
- zrb/util/cli/markdown.py +12 -0
- zrb/util/cli/text.py +30 -0
- zrb/util/file.py +27 -11
- zrb/util/{llm/prompt.py → markdown.py} +2 -3
- zrb/util/string/conversion.py +1 -1
- zrb/util/truncate.py +23 -0
- zrb/util/yaml.py +204 -0
- {zrb-1.13.1.dist-info → zrb-1.21.17.dist-info}/METADATA +40 -20
- {zrb-1.13.1.dist-info → zrb-1.21.17.dist-info}/RECORD +102 -79
- {zrb-1.13.1.dist-info → zrb-1.21.17.dist-info}/WHEEL +1 -1
- zrb/task/llm/default_workflow/coding.md +0 -24
- zrb/task/llm/default_workflow/copywriting.md +0 -17
- zrb/task/llm/default_workflow/researching.md +0 -18
- {zrb-1.13.1.dist-info → zrb-1.21.17.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from zrb.builtin.group import searxng_group
|
|
4
|
+
from zrb.config.config import CFG
|
|
5
|
+
from zrb.input.int_input import IntInput
|
|
6
|
+
from zrb.task.cmd_task import CmdTask
|
|
7
|
+
from zrb.task.http_check import HttpCheck
|
|
8
|
+
|
|
9
|
+
start_searxng = searxng_group.add_task(
|
|
10
|
+
CmdTask(
|
|
11
|
+
name="start-searxng",
|
|
12
|
+
input=IntInput(name="port", default=CFG.SEARXNG_PORT),
|
|
13
|
+
cwd=os.path.dirname(__file__),
|
|
14
|
+
cmd="docker run --rm -p {ctx.input.port}:8080 -v ./config/:/etc/searxng/ docker.io/searxng/searxng:latest -d", # noqa
|
|
15
|
+
readiness_check=HttpCheck(
|
|
16
|
+
"check-searxng",
|
|
17
|
+
url="http://localhost:{ctx.input.port}",
|
|
18
|
+
),
|
|
19
|
+
),
|
|
20
|
+
alias="start",
|
|
21
|
+
)
|
zrb/builtin/setup/ubuntu.py
CHANGED
|
@@ -22,7 +22,7 @@ setup_ubuntu = setup_group.add_task(
|
|
|
22
22
|
description="🐧 Setup ubuntu",
|
|
23
23
|
cmd=[
|
|
24
24
|
"sudo apt install -y \\",
|
|
25
|
-
"build-essential
|
|
25
|
+
"build-essential libssl-dev zlib1g-dev \\"
|
|
26
26
|
"libbz2-dev libreadline-dev libsqlite3-dev libpq-dev python3-dev \\",
|
|
27
27
|
"llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev \\",
|
|
28
28
|
"liblzma-dev python3-openssl libblas-dev liblapack-dev rustc \\",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from zrb.builtin.group import shell_autocomplete_group
|
|
2
|
-
from zrb.
|
|
2
|
+
from zrb.config.config import CFG
|
|
3
|
+
from zrb.context.context import AnyContext
|
|
3
4
|
from zrb.task.make_task import make_task
|
|
4
5
|
|
|
5
6
|
_COMPLETION_SCRIPT = """
|
|
@@ -36,5 +37,5 @@ complete -F _zrb_complete zrb
|
|
|
36
37
|
group=shell_autocomplete_group,
|
|
37
38
|
alias="bash",
|
|
38
39
|
)
|
|
39
|
-
def make_bash_autocomplete(ctx:
|
|
40
|
-
return _COMPLETION_SCRIPT
|
|
40
|
+
def make_bash_autocomplete(ctx: AnyContext):
|
|
41
|
+
return _COMPLETION_SCRIPT.replace("zrb", CFG.ROOT_GROUP_NAME)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from zrb.builtin.group import shell_autocomplete_group
|
|
2
|
-
from zrb.
|
|
2
|
+
from zrb.config.config import CFG
|
|
3
|
+
from zrb.context.context import AnyContext
|
|
3
4
|
from zrb.task.make_task import make_task
|
|
4
5
|
|
|
5
6
|
_COMPLETION_SCRIPT = """
|
|
@@ -33,5 +34,5 @@ compdef _zrb_complete zrb
|
|
|
33
34
|
group=shell_autocomplete_group,
|
|
34
35
|
alias="zsh",
|
|
35
36
|
)
|
|
36
|
-
def make_zsh_autocomplete(ctx:
|
|
37
|
-
return _COMPLETION_SCRIPT
|
|
37
|
+
def make_zsh_autocomplete(ctx: AnyContext):
|
|
38
|
+
return _COMPLETION_SCRIPT.replace("zrb", CFG.ROOT_GROUP_NAME)
|
zrb/config/config.py
CHANGED
|
@@ -24,6 +24,13 @@ class Config:
|
|
|
24
24
|
def __init__(self):
|
|
25
25
|
self.__internal_default_prompt: dict[str, str] = {}
|
|
26
26
|
|
|
27
|
+
@property
|
|
28
|
+
def ENV_PREFIX(self) -> str:
|
|
29
|
+
return os.getenv("_ZRB_ENV_PREFIX", "ZRB")
|
|
30
|
+
|
|
31
|
+
def _getenv(self, env_name: str, default: str = "") -> str:
|
|
32
|
+
return os.getenv(f"{self.ENV_PREFIX}_{env_name}", default)
|
|
33
|
+
|
|
27
34
|
def _get_internal_default_prompt(self, name: str) -> str:
|
|
28
35
|
if name not in self.__internal_default_prompt:
|
|
29
36
|
file_path = os.path.join(
|
|
@@ -39,7 +46,7 @@ class Config:
|
|
|
39
46
|
|
|
40
47
|
@property
|
|
41
48
|
def DEFAULT_SHELL(self) -> str:
|
|
42
|
-
return
|
|
49
|
+
return self._getenv("SHELL", self._get_current_shell())
|
|
43
50
|
|
|
44
51
|
def _get_current_shell(self) -> str:
|
|
45
52
|
if platform.system() == "Windows":
|
|
@@ -51,11 +58,43 @@ class Config:
|
|
|
51
58
|
|
|
52
59
|
@property
|
|
53
60
|
def DEFAULT_EDITOR(self) -> str:
|
|
54
|
-
return
|
|
61
|
+
return self._getenv("EDITOR", "nano")
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def DEFAULT_DIFF_EDIT_COMMAND_TPL(self) -> str:
|
|
65
|
+
return self._getenv("DIFF_EDIT_COMMAND", self._get_default_diff_edit_command())
|
|
66
|
+
|
|
67
|
+
def _get_default_diff_edit_command(self) -> str:
|
|
68
|
+
editor = self.DEFAULT_EDITOR
|
|
69
|
+
if editor in [
|
|
70
|
+
"code",
|
|
71
|
+
"vscode",
|
|
72
|
+
"vscodium",
|
|
73
|
+
"windsurf",
|
|
74
|
+
"cursor",
|
|
75
|
+
"zed",
|
|
76
|
+
"zeditor",
|
|
77
|
+
"agy",
|
|
78
|
+
]:
|
|
79
|
+
return f"{editor} --wait --diff {{old}} {{new}}"
|
|
80
|
+
if editor == "emacs":
|
|
81
|
+
return 'emacs --eval \'(ediff-files "{old}" "{new}")\''
|
|
82
|
+
if editor in ["nvim", "vim"]:
|
|
83
|
+
return (
|
|
84
|
+
f"{editor} -d {{old}} {{new}} "
|
|
85
|
+
"-i NONE "
|
|
86
|
+
'-c "wincmd h | set readonly | wincmd l" '
|
|
87
|
+
'-c "highlight DiffAdd cterm=bold ctermbg=22 guibg=#005f00 | highlight DiffChange cterm=bold ctermbg=24 guibg=#005f87 | highlight DiffText ctermbg=21 guibg=#0000af | highlight DiffDelete ctermbg=52 guibg=#5f0000" ' # noqa
|
|
88
|
+
'-c "set showtabline=2 | set tabline=[Instructions]\\ :wqa(save\\ &\\ quit)\\ \\|\\ i/esc(toggle\\ edit\\ mode)" ' # noqa
|
|
89
|
+
'-c "wincmd h | setlocal statusline=OLD\\ FILE" '
|
|
90
|
+
'-c "wincmd l | setlocal statusline=%#StatusBold#NEW\\ FILE\\ :wqa(save\\ &\\ quit)\\ \\|\\ i/esc(toggle\\ edit\\ mode)" ' # noqa
|
|
91
|
+
'-c "autocmd BufWritePost * wqa"'
|
|
92
|
+
)
|
|
93
|
+
return 'vimdiff {old} {new} +"setlocal ro" +"wincmd l" +"autocmd BufWritePost <buffer> qa"' # noqa
|
|
55
94
|
|
|
56
95
|
@property
|
|
57
96
|
def INIT_MODULES(self) -> list[str]:
|
|
58
|
-
init_modules_str =
|
|
97
|
+
init_modules_str = self._getenv("INIT_MODULES", "")
|
|
59
98
|
if init_modules_str != "":
|
|
60
99
|
return [
|
|
61
100
|
module.strip()
|
|
@@ -66,15 +105,15 @@ class Config:
|
|
|
66
105
|
|
|
67
106
|
@property
|
|
68
107
|
def ROOT_GROUP_NAME(self) -> str:
|
|
69
|
-
return
|
|
108
|
+
return self._getenv("ROOT_GROUP_NAME", "zrb")
|
|
70
109
|
|
|
71
110
|
@property
|
|
72
111
|
def ROOT_GROUP_DESCRIPTION(self) -> str:
|
|
73
|
-
return
|
|
112
|
+
return self._getenv("ROOT_GROUP_DESCRIPTION", "Your Automation Powerhouse")
|
|
74
113
|
|
|
75
114
|
@property
|
|
76
115
|
def INIT_SCRIPTS(self) -> list[str]:
|
|
77
|
-
init_scripts_str =
|
|
116
|
+
init_scripts_str = self._getenv("INIT_SCRIPTS", "")
|
|
78
117
|
if init_scripts_str != "":
|
|
79
118
|
return [
|
|
80
119
|
script.strip()
|
|
@@ -85,16 +124,17 @@ class Config:
|
|
|
85
124
|
|
|
86
125
|
@property
|
|
87
126
|
def INIT_FILE_NAME(self) -> str:
|
|
88
|
-
return
|
|
127
|
+
return self._getenv("INIT_FILE_NAME", "zrb_init.py")
|
|
89
128
|
|
|
90
129
|
@property
|
|
91
130
|
def LOGGING_LEVEL(self) -> int:
|
|
92
|
-
return self._get_log_level(
|
|
131
|
+
return self._get_log_level(self._getenv("LOGGING_LEVEL", "WARNING"))
|
|
93
132
|
|
|
94
133
|
def _get_log_level(self, level: str) -> int:
|
|
95
134
|
level = level.upper()
|
|
96
135
|
log_levels = {
|
|
97
136
|
"CRITICAL": logging.CRITICAL, # 50
|
|
137
|
+
"FATAL": logging.CRITICAL, # 50
|
|
98
138
|
"ERROR": logging.ERROR, # 40
|
|
99
139
|
"WARN": logging.WARNING, # 30
|
|
100
140
|
"WARNING": logging.WARNING, # 30
|
|
@@ -108,11 +148,11 @@ class Config:
|
|
|
108
148
|
|
|
109
149
|
@property
|
|
110
150
|
def LOAD_BUILTIN(self) -> bool:
|
|
111
|
-
return to_boolean(
|
|
151
|
+
return to_boolean(self._getenv("LOAD_BUILTIN", "1"))
|
|
112
152
|
|
|
113
153
|
@property
|
|
114
154
|
def WARN_UNRECOMMENDED_COMMAND(self) -> bool:
|
|
115
|
-
return to_boolean(
|
|
155
|
+
return to_boolean(self._getenv("WARN_UNRECOMMENDED_COMMAND", "1"))
|
|
116
156
|
|
|
117
157
|
@property
|
|
118
158
|
def SESSION_LOG_DIR(self) -> str:
|
|
@@ -122,15 +162,15 @@ class Config:
|
|
|
122
162
|
|
|
123
163
|
@property
|
|
124
164
|
def TODO_DIR(self) -> str:
|
|
125
|
-
return
|
|
165
|
+
return self._getenv("TODO_DIR", os.path.expanduser(os.path.join("~", "todo")))
|
|
126
166
|
|
|
127
167
|
@property
|
|
128
168
|
def TODO_VISUAL_FILTER(self) -> str:
|
|
129
|
-
return
|
|
169
|
+
return self._getenv("TODO_FILTER", "")
|
|
130
170
|
|
|
131
171
|
@property
|
|
132
172
|
def TODO_RETENTION(self) -> str:
|
|
133
|
-
return
|
|
173
|
+
return self._getenv("TODO_RETENTION", "2w")
|
|
134
174
|
|
|
135
175
|
@property
|
|
136
176
|
def VERSION(self) -> str:
|
|
@@ -141,7 +181,7 @@ class Config:
|
|
|
141
181
|
|
|
142
182
|
@property
|
|
143
183
|
def WEB_CSS_PATH(self) -> list[str]:
|
|
144
|
-
web_css_path_str =
|
|
184
|
+
web_css_path_str = self._getenv("WEB_CSS_PATH", "")
|
|
145
185
|
if web_css_path_str != "":
|
|
146
186
|
return [
|
|
147
187
|
path.strip()
|
|
@@ -152,7 +192,7 @@ class Config:
|
|
|
152
192
|
|
|
153
193
|
@property
|
|
154
194
|
def WEB_JS_PATH(self) -> list[str]:
|
|
155
|
-
web_js_path_str =
|
|
195
|
+
web_js_path_str = self._getenv("WEB_JS_PATH", "")
|
|
156
196
|
if web_js_path_str != "":
|
|
157
197
|
return [
|
|
158
198
|
path.strip()
|
|
@@ -163,103 +203,140 @@ class Config:
|
|
|
163
203
|
|
|
164
204
|
@property
|
|
165
205
|
def WEB_FAVICON_PATH(self) -> str:
|
|
166
|
-
return
|
|
206
|
+
return self._getenv("WEB_FAVICON_PATH", "/static/favicon-32x32.png")
|
|
167
207
|
|
|
168
208
|
@property
|
|
169
209
|
def WEB_COLOR(self) -> str:
|
|
170
|
-
return
|
|
210
|
+
return self._getenv("WEB_COLOR", "")
|
|
171
211
|
|
|
172
212
|
@property
|
|
173
213
|
def WEB_HTTP_PORT(self) -> int:
|
|
174
|
-
return int(
|
|
214
|
+
return int(self._getenv("WEB_HTTP_PORT", "21213"))
|
|
175
215
|
|
|
176
216
|
@property
|
|
177
217
|
def WEB_GUEST_USERNAME(self) -> str:
|
|
178
|
-
return
|
|
218
|
+
return self._getenv("WEB_GUEST_USERNAME", "user")
|
|
179
219
|
|
|
180
220
|
@property
|
|
181
221
|
def WEB_SUPER_ADMIN_USERNAME(self) -> str:
|
|
182
|
-
return
|
|
222
|
+
return self._getenv("WEB_SUPER_ADMIN_USERNAME", "admin")
|
|
183
223
|
|
|
184
224
|
@property
|
|
185
225
|
def WEB_SUPER_ADMIN_PASSWORD(self) -> str:
|
|
186
|
-
return
|
|
226
|
+
return self._getenv("WEB_SUPER_ADMIN_PASSWORD", "admin")
|
|
187
227
|
|
|
188
228
|
@property
|
|
189
229
|
def WEB_ACCESS_TOKEN_COOKIE_NAME(self) -> str:
|
|
190
|
-
return
|
|
230
|
+
return self._getenv("WEB_ACCESS_TOKEN_COOKIE_NAME", "access_token")
|
|
191
231
|
|
|
192
232
|
@property
|
|
193
233
|
def WEB_REFRESH_TOKEN_COOKIE_NAME(self) -> str:
|
|
194
|
-
return
|
|
234
|
+
return self._getenv("WEB_REFRESH_TOKEN_COOKIE_NAME", "refresh_token")
|
|
195
235
|
|
|
196
236
|
@property
|
|
197
237
|
def WEB_SECRET_KEY(self) -> str:
|
|
198
|
-
return
|
|
238
|
+
return self._getenv("WEB_SECRET", "zrb")
|
|
199
239
|
|
|
200
240
|
@property
|
|
201
241
|
def WEB_ENABLE_AUTH(self) -> bool:
|
|
202
|
-
return to_boolean(
|
|
242
|
+
return to_boolean(self._getenv("WEB_ENABLE_AUTH", "0"))
|
|
203
243
|
|
|
204
244
|
@property
|
|
205
245
|
def WEB_AUTH_ACCESS_TOKEN_EXPIRE_MINUTES(self) -> int:
|
|
206
|
-
return int(
|
|
246
|
+
return int(self._getenv("WEB_ACCESS_TOKEN_EXPIRE_MINUTES", "30"))
|
|
207
247
|
|
|
208
248
|
@property
|
|
209
249
|
def WEB_AUTH_REFRESH_TOKEN_EXPIRE_MINUTES(self) -> int:
|
|
210
|
-
return int(
|
|
250
|
+
return int(self._getenv("WEB_REFRESH_TOKEN_EXPIRE_MINUTES", "60"))
|
|
211
251
|
|
|
212
252
|
@property
|
|
213
253
|
def WEB_TITLE(self) -> str:
|
|
214
|
-
return
|
|
254
|
+
return self._getenv("WEB_TITLE", "Zrb")
|
|
215
255
|
|
|
216
256
|
@property
|
|
217
257
|
def WEB_JARGON(self) -> str:
|
|
218
|
-
return
|
|
258
|
+
return self._getenv("WEB_JARGON", "Your Automation PowerHouse")
|
|
219
259
|
|
|
220
260
|
@property
|
|
221
261
|
def WEB_HOMEPAGE_INTRO(self) -> str:
|
|
222
|
-
return
|
|
262
|
+
return self._getenv("WEB_HOMEPAGE_INTRO", "Welcome to Zrb Web Interface")
|
|
223
263
|
|
|
224
264
|
@property
|
|
225
265
|
def LLM_MODEL(self) -> str | None:
|
|
226
|
-
|
|
266
|
+
value = self._getenv("LLM_MODEL")
|
|
267
|
+
return None if value == "" else value
|
|
227
268
|
|
|
228
269
|
@property
|
|
229
270
|
def LLM_BASE_URL(self) -> str | None:
|
|
230
|
-
|
|
271
|
+
value = self._getenv("LLM_BASE_URL")
|
|
272
|
+
return None if value == "" else value
|
|
231
273
|
|
|
232
274
|
@property
|
|
233
275
|
def LLM_API_KEY(self) -> str | None:
|
|
234
|
-
|
|
276
|
+
value = self._getenv("LLM_API_KEY")
|
|
277
|
+
return None if value == "" else value
|
|
278
|
+
|
|
279
|
+
@property
|
|
280
|
+
def LLM_MODEL_SMALL(self) -> str | None:
|
|
281
|
+
value = self._getenv("LLM_MODEL_SMALL")
|
|
282
|
+
return None if value == "" else value
|
|
283
|
+
|
|
284
|
+
@property
|
|
285
|
+
def LLM_BASE_URL_SMALL(self) -> str | None:
|
|
286
|
+
value = self._getenv("LLM_BASE_URL_SMALL")
|
|
287
|
+
return None if value == "" else value
|
|
288
|
+
|
|
289
|
+
@property
|
|
290
|
+
def LLM_API_KEY_SMALL(self) -> str | None:
|
|
291
|
+
value = self._getenv("LLM_API_KEY_SMALL")
|
|
292
|
+
return None if value == "" else value
|
|
235
293
|
|
|
236
294
|
@property
|
|
237
295
|
def LLM_SYSTEM_PROMPT(self) -> str | None:
|
|
238
|
-
|
|
296
|
+
value = self._getenv("LLM_SYSTEM_PROMPT")
|
|
297
|
+
return None if value == "" else value
|
|
239
298
|
|
|
240
299
|
@property
|
|
241
300
|
def LLM_INTERACTIVE_SYSTEM_PROMPT(self) -> str | None:
|
|
242
|
-
|
|
301
|
+
value = self._getenv("LLM_INTERACTIVE_SYSTEM_PROMPT")
|
|
302
|
+
return None if value == "" else value
|
|
243
303
|
|
|
244
304
|
@property
|
|
245
305
|
def LLM_PERSONA(self) -> str | None:
|
|
246
|
-
|
|
306
|
+
value = self._getenv("LLM_PERSONA")
|
|
307
|
+
return None if value == "" else value
|
|
247
308
|
|
|
248
309
|
@property
|
|
249
|
-
def
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
310
|
+
def LLM_WORKFLOWS(self) -> list[str]:
|
|
311
|
+
"""Get a list of LLM workflows from environment variables."""
|
|
312
|
+
workflows = []
|
|
313
|
+
for workflow in self._getenv("LLM_WORKFLOWS", "").split(","):
|
|
314
|
+
workflow = workflow.strip()
|
|
315
|
+
if workflow != "":
|
|
316
|
+
workflows.append(workflow)
|
|
317
|
+
return workflows
|
|
318
|
+
|
|
319
|
+
@property
|
|
320
|
+
def LLM_BUILTIN_WORKFLOW_PATHS(self) -> list[str]:
|
|
321
|
+
"""Get a list of additional builtin workflow paths from environment variables."""
|
|
322
|
+
builtin_workflow_paths_str = self._getenv("LLM_BUILTIN_WORKFLOW_PATHS", "")
|
|
323
|
+
if builtin_workflow_paths_str != "":
|
|
324
|
+
return [
|
|
325
|
+
path.strip()
|
|
326
|
+
for path in builtin_workflow_paths_str.split(":")
|
|
327
|
+
if path.strip() != ""
|
|
328
|
+
]
|
|
329
|
+
return []
|
|
255
330
|
|
|
256
331
|
@property
|
|
257
332
|
def LLM_SPECIAL_INSTRUCTION_PROMPT(self) -> str | None:
|
|
258
|
-
|
|
333
|
+
value = self._getenv("LLM_SPECIAL_INSTRUCTION_PROMPT")
|
|
334
|
+
return None if value == "" else value
|
|
259
335
|
|
|
260
336
|
@property
|
|
261
337
|
def LLM_SUMMARIZATION_PROMPT(self) -> str | None:
|
|
262
|
-
|
|
338
|
+
value = self._getenv("LLM_SUMMARIZATION_PROMPT")
|
|
339
|
+
return None if value == "" else value
|
|
263
340
|
|
|
264
341
|
@property
|
|
265
342
|
def LLM_MAX_REQUESTS_PER_MINUTE(self) -> int:
|
|
@@ -267,7 +344,7 @@ class Config:
|
|
|
267
344
|
Maximum number of LLM requests allowed per minute.
|
|
268
345
|
Default is conservative to accommodate free-tier LLM providers.
|
|
269
346
|
"""
|
|
270
|
-
return int(
|
|
347
|
+
return int(self._getenv("LLM_MAX_REQUESTS_PER_MINUTE", "60"))
|
|
271
348
|
|
|
272
349
|
@property
|
|
273
350
|
def LLM_MAX_TOKENS_PER_MINUTE(self) -> int:
|
|
@@ -275,122 +352,222 @@ class Config:
|
|
|
275
352
|
Maximum number of LLM tokens allowed per minute.
|
|
276
353
|
Default is conservative to accommodate free-tier LLM providers.
|
|
277
354
|
"""
|
|
278
|
-
return int(
|
|
355
|
+
return int(self._getenv("LLM_MAX_TOKENS_PER_MINUTE", "100000"))
|
|
279
356
|
|
|
280
357
|
@property
|
|
281
358
|
def LLM_MAX_TOKENS_PER_REQUEST(self) -> int:
|
|
282
359
|
"""Maximum number of tokens allowed per individual LLM request."""
|
|
283
|
-
return int(
|
|
360
|
+
return int(self._getenv("LLM_MAX_TOKENS_PER_REQUEST", "100000"))
|
|
361
|
+
|
|
362
|
+
@property
|
|
363
|
+
def LLM_MAX_TOKENS_PER_TOOL_CALL_RESULT(self) -> int:
|
|
364
|
+
"""Maximum number of tokens allowed per tool call result."""
|
|
365
|
+
return int(self._getenv("LLM_MAX_TOKENS_PER_TOOL_CALL_RESULT", "75000"))
|
|
284
366
|
|
|
285
367
|
@property
|
|
286
368
|
def LLM_THROTTLE_SLEEP(self) -> float:
|
|
287
369
|
"""Number of seconds to sleep when throttling is required."""
|
|
288
|
-
return float(
|
|
370
|
+
return float(self._getenv("LLM_THROTTLE_SLEEP", "5.0"))
|
|
289
371
|
|
|
290
372
|
@property
|
|
291
|
-
def LLM_YOLO_MODE(self) -> bool:
|
|
292
|
-
|
|
373
|
+
def LLM_YOLO_MODE(self) -> bool | list[str]:
|
|
374
|
+
str_val = self._getenv("LLM_YOLO_MODE", "false")
|
|
375
|
+
try:
|
|
376
|
+
return to_boolean(str_val)
|
|
377
|
+
except Exception:
|
|
378
|
+
return [val.strip() for val in str_val.split(",") if val.strip() != ""]
|
|
293
379
|
|
|
294
380
|
@property
|
|
295
381
|
def LLM_SUMMARIZE_HISTORY(self) -> bool:
|
|
296
|
-
return to_boolean(
|
|
382
|
+
return to_boolean(self._getenv("LLM_SUMMARIZE_HISTORY", "true"))
|
|
297
383
|
|
|
298
384
|
@property
|
|
299
385
|
def LLM_HISTORY_SUMMARIZATION_TOKEN_THRESHOLD(self) -> int:
|
|
300
|
-
|
|
386
|
+
threshold = int(
|
|
387
|
+
self._getenv("LLM_HISTORY_SUMMARIZATION_TOKEN_THRESHOLD", "20000")
|
|
388
|
+
)
|
|
389
|
+
return self._limit_token_threshold(threshold)
|
|
301
390
|
|
|
302
391
|
@property
|
|
303
392
|
def LLM_REPO_ANALYSIS_EXTRACTION_TOKEN_THRESHOLD(self) -> int:
|
|
304
|
-
|
|
393
|
+
threshold = int(
|
|
394
|
+
self._getenv("LLM_REPO_ANALYSIS_EXTRACTION_TOKEN_LIMIT", "50000")
|
|
395
|
+
)
|
|
396
|
+
return self._limit_token_threshold(threshold)
|
|
305
397
|
|
|
306
398
|
@property
|
|
307
399
|
def LLM_REPO_ANALYSIS_SUMMARIZATION_TOKEN_THRESHOLD(self) -> int:
|
|
308
|
-
|
|
309
|
-
|
|
400
|
+
threshold = int(
|
|
401
|
+
self._getenv("LLM_REPO_ANALYSIS_SUMMARIZATION_TOKEN_LIMIT", "20000")
|
|
402
|
+
)
|
|
403
|
+
min(
|
|
404
|
+
threshold,
|
|
405
|
+
self.LLM_MAX_TOKENS_PER_MINUTE // 2,
|
|
406
|
+
self.LLM_MAX_TOKENS_PER_REQUEST // 2,
|
|
310
407
|
)
|
|
408
|
+
return self._limit_token_threshold(threshold)
|
|
311
409
|
|
|
312
410
|
@property
|
|
313
411
|
def LLM_FILE_ANALYSIS_TOKEN_LIMIT(self) -> int:
|
|
314
|
-
|
|
412
|
+
threshold = int(self._getenv("LLM_FILE_ANALYSIS_TOKEN_LIMIT", "50000"))
|
|
413
|
+
return self._limit_token_threshold(threshold)
|
|
414
|
+
|
|
415
|
+
def _limit_token_threshold(self, threshold: int) -> int:
|
|
416
|
+
return min(
|
|
417
|
+
threshold,
|
|
418
|
+
self.LLM_MAX_TOKENS_PER_MINUTE // 2,
|
|
419
|
+
self.LLM_MAX_TOKENS_PER_REQUEST // 2,
|
|
420
|
+
)
|
|
315
421
|
|
|
316
422
|
@property
|
|
317
423
|
def LLM_FILE_EXTRACTOR_SYSTEM_PROMPT(self) -> str:
|
|
318
|
-
return
|
|
319
|
-
"
|
|
424
|
+
return self._getenv(
|
|
425
|
+
"LLM_FILE_EXTRACTOR_SYSTEM_PROMPT",
|
|
320
426
|
self._get_internal_default_prompt("file_extractor_system_prompt"),
|
|
321
427
|
)
|
|
322
428
|
|
|
323
429
|
@property
|
|
324
430
|
def LLM_REPO_EXTRACTOR_SYSTEM_PROMPT(self) -> str:
|
|
325
|
-
return
|
|
326
|
-
"
|
|
431
|
+
return self._getenv(
|
|
432
|
+
"LLM_REPO_EXTRACTOR_SYSTEM_PROMPT",
|
|
327
433
|
self._get_internal_default_prompt("repo_extractor_system_prompt"),
|
|
328
434
|
)
|
|
329
435
|
|
|
330
436
|
@property
|
|
331
437
|
def LLM_REPO_SUMMARIZER_SYSTEM_PROMPT(self) -> str:
|
|
332
|
-
return
|
|
333
|
-
"
|
|
438
|
+
return self._getenv(
|
|
439
|
+
"LLM_REPO_SUMMARIZER_SYSTEM_PROMPT",
|
|
334
440
|
self._get_internal_default_prompt("repo_summarizer_system_prompt"),
|
|
335
441
|
)
|
|
336
442
|
|
|
337
443
|
@property
|
|
338
444
|
def LLM_HISTORY_DIR(self) -> str:
|
|
339
|
-
return
|
|
340
|
-
"
|
|
445
|
+
return self._getenv(
|
|
446
|
+
"LLM_HISTORY_DIR",
|
|
341
447
|
os.path.expanduser(os.path.join("~", ".zrb-llm-history")),
|
|
342
448
|
)
|
|
343
449
|
|
|
344
450
|
@property
|
|
345
451
|
def LLM_ALLOW_ACCESS_LOCAL_FILE(self) -> bool:
|
|
346
|
-
return to_boolean(
|
|
452
|
+
return to_boolean(self._getenv("LLM_ALLOW_ACCESS_LOCAL_FILE", "1"))
|
|
453
|
+
|
|
454
|
+
@property
|
|
455
|
+
def LLM_ALLOW_ANALYZE_FILE(self) -> bool:
|
|
456
|
+
return to_boolean(self._getenv("LLM_ALLOW_ANALYZE_LOCAL_FILE", "1"))
|
|
457
|
+
|
|
458
|
+
@property
|
|
459
|
+
def LLM_ALLOW_ANALYZE_REPO(self) -> bool:
|
|
460
|
+
return to_boolean(self._getenv("LLM_ALLOW_ANALYZE_REPO", "1"))
|
|
347
461
|
|
|
348
462
|
@property
|
|
349
463
|
def LLM_ALLOW_ACCESS_SHELL(self) -> bool:
|
|
350
|
-
return to_boolean(
|
|
464
|
+
return to_boolean(self._getenv("LLM_ALLOW_ACCESS_SHELL", "1"))
|
|
351
465
|
|
|
352
466
|
@property
|
|
353
|
-
def
|
|
354
|
-
return to_boolean(
|
|
467
|
+
def LLM_ALLOW_OPEN_WEB_PAGE(self) -> bool:
|
|
468
|
+
return to_boolean(self._getenv("LLM_ALLOW_OPEN_WEB_PAGE", "1"))
|
|
355
469
|
|
|
356
470
|
@property
|
|
357
|
-
def
|
|
358
|
-
return
|
|
471
|
+
def LLM_ALLOW_SEARCH_INTERNET(self) -> bool:
|
|
472
|
+
return to_boolean(self._getenv("LLM_ALLOW_SEARCH_INTERNET", "1"))
|
|
359
473
|
|
|
360
474
|
@property
|
|
361
|
-
def
|
|
362
|
-
return
|
|
475
|
+
def LLM_ALLOW_GET_CURRENT_LOCATION(self) -> bool:
|
|
476
|
+
return to_boolean(self._getenv("LLM_ALLOW_GET_CURRENT_LOCATION", "1"))
|
|
477
|
+
|
|
478
|
+
@property
|
|
479
|
+
def LLM_ALLOW_GET_CURRENT_WEATHER(self) -> bool:
|
|
480
|
+
return to_boolean(self._getenv("LLM_ALLOW_GET_CURRENT_WEATHER", "1"))
|
|
481
|
+
|
|
482
|
+
@property
|
|
483
|
+
def RAG_EMBEDDING_API_KEY(self) -> str | None:
|
|
484
|
+
value = self._getenv("RAG_EMBEDDING_API_KEY")
|
|
485
|
+
return None if value == "" else value
|
|
486
|
+
|
|
487
|
+
@property
|
|
488
|
+
def RAG_EMBEDDING_BASE_URL(self) -> str | None:
|
|
489
|
+
value = self._getenv("RAG_EMBEDDING_BASE_URL")
|
|
490
|
+
return None if value == "" else value
|
|
363
491
|
|
|
364
492
|
@property
|
|
365
493
|
def RAG_EMBEDDING_MODEL(self) -> str:
|
|
366
|
-
return
|
|
494
|
+
return self._getenv("RAG_EMBEDDING_MODEL", "text-embedding-ada-002")
|
|
367
495
|
|
|
368
496
|
@property
|
|
369
497
|
def RAG_CHUNK_SIZE(self) -> int:
|
|
370
|
-
return int(
|
|
498
|
+
return int(self._getenv("RAG_CHUNK_SIZE", "1024"))
|
|
371
499
|
|
|
372
500
|
@property
|
|
373
501
|
def RAG_OVERLAP(self) -> int:
|
|
374
|
-
return int(
|
|
502
|
+
return int(self._getenv("RAG_OVERLAP", "128"))
|
|
375
503
|
|
|
376
504
|
@property
|
|
377
505
|
def RAG_MAX_RESULT_COUNT(self) -> int:
|
|
378
|
-
return int(
|
|
506
|
+
return int(self._getenv("RAG_MAX_RESULT_COUNT", "5"))
|
|
507
|
+
|
|
508
|
+
@property
|
|
509
|
+
def SEARCH_INTERNET_METHOD(self) -> str:
|
|
510
|
+
"""Either serpapi or searxng"""
|
|
511
|
+
return self._getenv("SEARCH_INTERNET_METHOD", "serpapi")
|
|
512
|
+
|
|
513
|
+
@property
|
|
514
|
+
def BRAVE_API_KEY(self) -> str:
|
|
515
|
+
return os.getenv("BRAVE_API_KEY", "")
|
|
516
|
+
|
|
517
|
+
@property
|
|
518
|
+
def BRAVE_API_SAFE(self) -> str:
|
|
519
|
+
return self._getenv("BRAVE_API_SAFE", "off")
|
|
520
|
+
|
|
521
|
+
@property
|
|
522
|
+
def BRAVE_API_LANG(self) -> str:
|
|
523
|
+
return self._getenv("BRAVE_API_LANG", "en")
|
|
379
524
|
|
|
380
525
|
@property
|
|
381
526
|
def SERPAPI_KEY(self) -> str:
|
|
382
527
|
return os.getenv("SERPAPI_KEY", "")
|
|
383
528
|
|
|
529
|
+
@property
|
|
530
|
+
def SERPAPI_SAFE(self) -> str:
|
|
531
|
+
return self._getenv("SERPAPI_SAFE", "off")
|
|
532
|
+
|
|
533
|
+
@property
|
|
534
|
+
def SERPAPI_LANG(self) -> str:
|
|
535
|
+
return self._getenv("SERPAPI_LANG", "en")
|
|
536
|
+
|
|
537
|
+
@property
|
|
538
|
+
def SEARXNG_PORT(self) -> int:
|
|
539
|
+
return int(self._getenv("SEARXNG_PORT", "8080"))
|
|
540
|
+
|
|
541
|
+
@property
|
|
542
|
+
def SEARXNG_BASE_URL(self) -> str:
|
|
543
|
+
return self._getenv("SEARXNG_BASE_URL", f"http://localhost:{self.SEARXNG_PORT}")
|
|
544
|
+
|
|
545
|
+
@property
|
|
546
|
+
def SEARXNG_SAFE(self) -> int:
|
|
547
|
+
return int(self._getenv("SEARXNG_SAFE", "0"))
|
|
548
|
+
|
|
549
|
+
@property
|
|
550
|
+
def SEARXNG_LANG(self) -> str:
|
|
551
|
+
return self._getenv("SEARXNG_LANG", "en")
|
|
552
|
+
|
|
384
553
|
@property
|
|
385
554
|
def BANNER(self) -> str:
|
|
386
555
|
return fstring_format(
|
|
387
|
-
|
|
556
|
+
self._getenv("BANNER", _DEFAULT_BANNER),
|
|
388
557
|
{"VERSION": self.VERSION},
|
|
389
558
|
)
|
|
390
559
|
|
|
391
560
|
@property
|
|
392
561
|
def LLM_CONTEXT_FILE(self) -> str:
|
|
393
|
-
return
|
|
562
|
+
return self._getenv("LLM_CONTEXT_FILE", "ZRB.md")
|
|
563
|
+
|
|
564
|
+
@property
|
|
565
|
+
def USE_TIKTOKEN(self) -> bool:
|
|
566
|
+
return to_boolean(self._getenv("USE_TIKTOKEN", "true"))
|
|
567
|
+
|
|
568
|
+
@property
|
|
569
|
+
def TIKTOKEN_ENCODING_NAME(self) -> str:
|
|
570
|
+
return self._getenv("TIKTOKEN_ENCODING_NAME", "cl100k_base")
|
|
394
571
|
|
|
395
572
|
|
|
396
573
|
CFG = Config()
|