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.
- zrb/__init__.py +2 -6
- zrb/attr/type.py +10 -7
- zrb/builtin/__init__.py +2 -0
- zrb/builtin/git.py +12 -1
- zrb/builtin/group.py +31 -15
- zrb/builtin/http.py +7 -8
- zrb/builtin/llm/attachment.py +40 -0
- zrb/builtin/llm/chat_completion.py +287 -0
- zrb/builtin/llm/chat_session.py +130 -144
- zrb/builtin/llm/chat_session_cmd.py +288 -0
- zrb/builtin/llm/chat_trigger.py +78 -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 +56 -21
- zrb/builtin/llm/tool/code.py +57 -47
- zrb/builtin/llm/tool/file.py +292 -255
- zrb/builtin/llm/tool/note.py +84 -0
- zrb/builtin/llm/tool/rag.py +25 -18
- zrb/builtin/llm/tool/search/__init__.py +1 -0
- zrb/builtin/llm/tool/search/brave.py +66 -0
- zrb/builtin/llm/tool/search/searxng.py +61 -0
- zrb/builtin/llm/tool/search/serpapi.py +61 -0
- zrb/builtin/llm/tool/sub_agent.py +53 -26
- zrb/builtin/llm/tool/web.py +94 -157
- 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 +297 -79
- zrb/config/default_prompt/file_extractor_system_prompt.md +109 -9
- zrb/config/default_prompt/interactive_system_prompt.md +25 -28
- 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 +57 -16
- zrb/config/default_prompt/system_prompt.md +29 -25
- 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 +100 -47
- 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/option_input.py +13 -1
- 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 +130 -145
- zrb/task/llm/agent_runner.py +152 -0
- zrb/task/llm/config.py +45 -13
- zrb/task/llm/conversation_history.py +110 -29
- zrb/task/llm/conversation_history_model.py +4 -179
- 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_processor.py +206 -0
- zrb/task/llm/history_summarization.py +2 -192
- zrb/task/llm/print_node.py +192 -64
- zrb/task/llm/prompt.py +198 -153
- zrb/task/llm/subagent_conversation_history.py +41 -0
- zrb/task/llm/tool_confirmation_completer.py +41 -0
- zrb/task/llm/tool_wrapper.py +216 -55
- zrb/task/llm/workflow.py +76 -0
- zrb/task/llm_task.py +122 -70
- zrb/task/make_task.py +2 -3
- zrb/task/rsync_task.py +25 -10
- zrb/task/scheduler.py +4 -4
- zrb/util/attr.py +54 -39
- zrb/util/cli/markdown.py +12 -0
- zrb/util/cli/text.py +30 -0
- zrb/util/file.py +27 -11
- zrb/util/git.py +2 -2
- 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/xcom/xcom.py +10 -0
- {zrb-1.13.1.dist-info → zrb-1.21.33.dist-info}/METADATA +40 -20
- {zrb-1.13.1.dist-info → zrb-1.21.33.dist-info}/RECORD +114 -83
- {zrb-1.13.1.dist-info → zrb-1.21.33.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.33.dist-info}/entry_points.txt +0 -0
zrb/config/config.py
CHANGED
|
@@ -24,6 +24,18 @@ 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 | list[str], default: str = "") -> str:
|
|
32
|
+
env_name_list = env_name if isinstance(env_name, list) else [env_name]
|
|
33
|
+
for env_name in env_name_list:
|
|
34
|
+
value = os.getenv(f"{self.ENV_PREFIX}_{env_name}", None)
|
|
35
|
+
if value is not None:
|
|
36
|
+
return value
|
|
37
|
+
return default
|
|
38
|
+
|
|
27
39
|
def _get_internal_default_prompt(self, name: str) -> str:
|
|
28
40
|
if name not in self.__internal_default_prompt:
|
|
29
41
|
file_path = os.path.join(
|
|
@@ -39,7 +51,7 @@ class Config:
|
|
|
39
51
|
|
|
40
52
|
@property
|
|
41
53
|
def DEFAULT_SHELL(self) -> str:
|
|
42
|
-
return
|
|
54
|
+
return self._getenv("SHELL", self._get_current_shell())
|
|
43
55
|
|
|
44
56
|
def _get_current_shell(self) -> str:
|
|
45
57
|
if platform.system() == "Windows":
|
|
@@ -51,11 +63,43 @@ class Config:
|
|
|
51
63
|
|
|
52
64
|
@property
|
|
53
65
|
def DEFAULT_EDITOR(self) -> str:
|
|
54
|
-
return
|
|
66
|
+
return self._getenv("EDITOR", "nano")
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def DEFAULT_DIFF_EDIT_COMMAND_TPL(self) -> str:
|
|
70
|
+
return self._getenv("DIFF_EDIT_COMMAND", self._get_default_diff_edit_command())
|
|
71
|
+
|
|
72
|
+
def _get_default_diff_edit_command(self) -> str:
|
|
73
|
+
editor = self.DEFAULT_EDITOR
|
|
74
|
+
if editor in [
|
|
75
|
+
"code",
|
|
76
|
+
"vscode",
|
|
77
|
+
"vscodium",
|
|
78
|
+
"windsurf",
|
|
79
|
+
"cursor",
|
|
80
|
+
"zed",
|
|
81
|
+
"zeditor",
|
|
82
|
+
"agy",
|
|
83
|
+
]:
|
|
84
|
+
return f"{editor} --wait --diff {{old}} {{new}}"
|
|
85
|
+
if editor == "emacs":
|
|
86
|
+
return 'emacs --eval \'(ediff-files "{old}" "{new}")\''
|
|
87
|
+
if editor in ["nvim", "vim"]:
|
|
88
|
+
return (
|
|
89
|
+
f"{editor} -d {{old}} {{new}} "
|
|
90
|
+
"-i NONE "
|
|
91
|
+
'-c "wincmd h | set readonly | wincmd l" '
|
|
92
|
+
'-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
|
|
93
|
+
'-c "set showtabline=2 | set tabline=[Instructions]\\ :wqa(save\\ &\\ quit)\\ \\|\\ i/esc(toggle\\ edit\\ mode)" ' # noqa
|
|
94
|
+
'-c "wincmd h | setlocal statusline=OLD\\ FILE" '
|
|
95
|
+
'-c "wincmd l | setlocal statusline=%#StatusBold#NEW\\ FILE\\ :wqa(save\\ &\\ quit)\\ \\|\\ i/esc(toggle\\ edit\\ mode)" ' # noqa
|
|
96
|
+
'-c "autocmd BufWritePost * wqa"'
|
|
97
|
+
)
|
|
98
|
+
return 'vimdiff {old} {new} +"setlocal ro" +"wincmd l" +"autocmd BufWritePost <buffer> qa"' # noqa
|
|
55
99
|
|
|
56
100
|
@property
|
|
57
101
|
def INIT_MODULES(self) -> list[str]:
|
|
58
|
-
init_modules_str =
|
|
102
|
+
init_modules_str = self._getenv("INIT_MODULES", "")
|
|
59
103
|
if init_modules_str != "":
|
|
60
104
|
return [
|
|
61
105
|
module.strip()
|
|
@@ -66,15 +110,15 @@ class Config:
|
|
|
66
110
|
|
|
67
111
|
@property
|
|
68
112
|
def ROOT_GROUP_NAME(self) -> str:
|
|
69
|
-
return
|
|
113
|
+
return self._getenv("ROOT_GROUP_NAME", "zrb")
|
|
70
114
|
|
|
71
115
|
@property
|
|
72
116
|
def ROOT_GROUP_DESCRIPTION(self) -> str:
|
|
73
|
-
return
|
|
117
|
+
return self._getenv("ROOT_GROUP_DESCRIPTION", "Your Automation Powerhouse")
|
|
74
118
|
|
|
75
119
|
@property
|
|
76
120
|
def INIT_SCRIPTS(self) -> list[str]:
|
|
77
|
-
init_scripts_str =
|
|
121
|
+
init_scripts_str = self._getenv("INIT_SCRIPTS", "")
|
|
78
122
|
if init_scripts_str != "":
|
|
79
123
|
return [
|
|
80
124
|
script.strip()
|
|
@@ -85,16 +129,17 @@ class Config:
|
|
|
85
129
|
|
|
86
130
|
@property
|
|
87
131
|
def INIT_FILE_NAME(self) -> str:
|
|
88
|
-
return
|
|
132
|
+
return self._getenv("INIT_FILE_NAME", "zrb_init.py")
|
|
89
133
|
|
|
90
134
|
@property
|
|
91
135
|
def LOGGING_LEVEL(self) -> int:
|
|
92
|
-
return self._get_log_level(
|
|
136
|
+
return self._get_log_level(self._getenv("LOGGING_LEVEL", "WARNING"))
|
|
93
137
|
|
|
94
138
|
def _get_log_level(self, level: str) -> int:
|
|
95
139
|
level = level.upper()
|
|
96
140
|
log_levels = {
|
|
97
141
|
"CRITICAL": logging.CRITICAL, # 50
|
|
142
|
+
"FATAL": logging.CRITICAL, # 50
|
|
98
143
|
"ERROR": logging.ERROR, # 40
|
|
99
144
|
"WARN": logging.WARNING, # 30
|
|
100
145
|
"WARNING": logging.WARNING, # 30
|
|
@@ -108,11 +153,11 @@ class Config:
|
|
|
108
153
|
|
|
109
154
|
@property
|
|
110
155
|
def LOAD_BUILTIN(self) -> bool:
|
|
111
|
-
return to_boolean(
|
|
156
|
+
return to_boolean(self._getenv("LOAD_BUILTIN", "1"))
|
|
112
157
|
|
|
113
158
|
@property
|
|
114
159
|
def WARN_UNRECOMMENDED_COMMAND(self) -> bool:
|
|
115
|
-
return to_boolean(
|
|
160
|
+
return to_boolean(self._getenv("WARN_UNRECOMMENDED_COMMAND", "1"))
|
|
116
161
|
|
|
117
162
|
@property
|
|
118
163
|
def SESSION_LOG_DIR(self) -> str:
|
|
@@ -122,15 +167,15 @@ class Config:
|
|
|
122
167
|
|
|
123
168
|
@property
|
|
124
169
|
def TODO_DIR(self) -> str:
|
|
125
|
-
return
|
|
170
|
+
return self._getenv("TODO_DIR", os.path.expanduser(os.path.join("~", "todo")))
|
|
126
171
|
|
|
127
172
|
@property
|
|
128
173
|
def TODO_VISUAL_FILTER(self) -> str:
|
|
129
|
-
return
|
|
174
|
+
return self._getenv("TODO_FILTER", "")
|
|
130
175
|
|
|
131
176
|
@property
|
|
132
177
|
def TODO_RETENTION(self) -> str:
|
|
133
|
-
return
|
|
178
|
+
return self._getenv("TODO_RETENTION", "2w")
|
|
134
179
|
|
|
135
180
|
@property
|
|
136
181
|
def VERSION(self) -> str:
|
|
@@ -141,7 +186,7 @@ class Config:
|
|
|
141
186
|
|
|
142
187
|
@property
|
|
143
188
|
def WEB_CSS_PATH(self) -> list[str]:
|
|
144
|
-
web_css_path_str =
|
|
189
|
+
web_css_path_str = self._getenv("WEB_CSS_PATH", "")
|
|
145
190
|
if web_css_path_str != "":
|
|
146
191
|
return [
|
|
147
192
|
path.strip()
|
|
@@ -152,7 +197,7 @@ class Config:
|
|
|
152
197
|
|
|
153
198
|
@property
|
|
154
199
|
def WEB_JS_PATH(self) -> list[str]:
|
|
155
|
-
web_js_path_str =
|
|
200
|
+
web_js_path_str = self._getenv("WEB_JS_PATH", "")
|
|
156
201
|
if web_js_path_str != "":
|
|
157
202
|
return [
|
|
158
203
|
path.strip()
|
|
@@ -163,103 +208,146 @@ class Config:
|
|
|
163
208
|
|
|
164
209
|
@property
|
|
165
210
|
def WEB_FAVICON_PATH(self) -> str:
|
|
166
|
-
return
|
|
211
|
+
return self._getenv("WEB_FAVICON_PATH", "/static/favicon-32x32.png")
|
|
167
212
|
|
|
168
213
|
@property
|
|
169
214
|
def WEB_COLOR(self) -> str:
|
|
170
|
-
return
|
|
215
|
+
return self._getenv("WEB_COLOR", "")
|
|
171
216
|
|
|
172
217
|
@property
|
|
173
218
|
def WEB_HTTP_PORT(self) -> int:
|
|
174
|
-
return int(
|
|
219
|
+
return int(self._getenv("WEB_HTTP_PORT", "21213"))
|
|
175
220
|
|
|
176
221
|
@property
|
|
177
222
|
def WEB_GUEST_USERNAME(self) -> str:
|
|
178
|
-
return
|
|
223
|
+
return self._getenv("WEB_GUEST_USERNAME", "user")
|
|
179
224
|
|
|
180
225
|
@property
|
|
181
226
|
def WEB_SUPER_ADMIN_USERNAME(self) -> str:
|
|
182
|
-
return
|
|
227
|
+
return self._getenv("WEB_SUPER_ADMIN_USERNAME", "admin")
|
|
183
228
|
|
|
184
229
|
@property
|
|
185
230
|
def WEB_SUPER_ADMIN_PASSWORD(self) -> str:
|
|
186
|
-
return
|
|
231
|
+
return self._getenv("WEB_SUPER_ADMIN_PASSWORD", "admin")
|
|
187
232
|
|
|
188
233
|
@property
|
|
189
234
|
def WEB_ACCESS_TOKEN_COOKIE_NAME(self) -> str:
|
|
190
|
-
return
|
|
235
|
+
return self._getenv("WEB_ACCESS_TOKEN_COOKIE_NAME", "access_token")
|
|
191
236
|
|
|
192
237
|
@property
|
|
193
238
|
def WEB_REFRESH_TOKEN_COOKIE_NAME(self) -> str:
|
|
194
|
-
return
|
|
239
|
+
return self._getenv("WEB_REFRESH_TOKEN_COOKIE_NAME", "refresh_token")
|
|
195
240
|
|
|
196
241
|
@property
|
|
197
242
|
def WEB_SECRET_KEY(self) -> str:
|
|
198
|
-
return
|
|
243
|
+
return self._getenv("WEB_SECRET", "zrb")
|
|
199
244
|
|
|
200
245
|
@property
|
|
201
246
|
def WEB_ENABLE_AUTH(self) -> bool:
|
|
202
|
-
return to_boolean(
|
|
247
|
+
return to_boolean(self._getenv("WEB_ENABLE_AUTH", "0"))
|
|
203
248
|
|
|
204
249
|
@property
|
|
205
250
|
def WEB_AUTH_ACCESS_TOKEN_EXPIRE_MINUTES(self) -> int:
|
|
206
|
-
return int(
|
|
251
|
+
return int(self._getenv("WEB_ACCESS_TOKEN_EXPIRE_MINUTES", "30"))
|
|
207
252
|
|
|
208
253
|
@property
|
|
209
254
|
def WEB_AUTH_REFRESH_TOKEN_EXPIRE_MINUTES(self) -> int:
|
|
210
|
-
return int(
|
|
255
|
+
return int(self._getenv("WEB_REFRESH_TOKEN_EXPIRE_MINUTES", "60"))
|
|
211
256
|
|
|
212
257
|
@property
|
|
213
258
|
def WEB_TITLE(self) -> str:
|
|
214
|
-
return
|
|
259
|
+
return self._getenv("WEB_TITLE", "Zrb")
|
|
215
260
|
|
|
216
261
|
@property
|
|
217
262
|
def WEB_JARGON(self) -> str:
|
|
218
|
-
return
|
|
263
|
+
return self._getenv("WEB_JARGON", "Your Automation PowerHouse")
|
|
219
264
|
|
|
220
265
|
@property
|
|
221
266
|
def WEB_HOMEPAGE_INTRO(self) -> str:
|
|
222
|
-
return
|
|
267
|
+
return self._getenv("WEB_HOMEPAGE_INTRO", "Welcome to Zrb Web Interface")
|
|
223
268
|
|
|
224
269
|
@property
|
|
225
270
|
def LLM_MODEL(self) -> str | None:
|
|
226
|
-
|
|
271
|
+
value = self._getenv("LLM_MODEL")
|
|
272
|
+
return None if value == "" else value
|
|
227
273
|
|
|
228
274
|
@property
|
|
229
275
|
def LLM_BASE_URL(self) -> str | None:
|
|
230
|
-
|
|
276
|
+
value = self._getenv("LLM_BASE_URL")
|
|
277
|
+
return None if value == "" else value
|
|
231
278
|
|
|
232
279
|
@property
|
|
233
280
|
def LLM_API_KEY(self) -> str | None:
|
|
234
|
-
|
|
281
|
+
value = self._getenv("LLM_API_KEY")
|
|
282
|
+
return None if value == "" else value
|
|
283
|
+
|
|
284
|
+
@property
|
|
285
|
+
def LLM_MODEL_SMALL(self) -> str | None:
|
|
286
|
+
value = self._getenv("LLM_MODEL_SMALL")
|
|
287
|
+
return None if value == "" else value
|
|
288
|
+
|
|
289
|
+
@property
|
|
290
|
+
def LLM_BASE_URL_SMALL(self) -> str | None:
|
|
291
|
+
value = self._getenv("LLM_BASE_URL_SMALL")
|
|
292
|
+
return None if value == "" else value
|
|
293
|
+
|
|
294
|
+
@property
|
|
295
|
+
def LLM_API_KEY_SMALL(self) -> str | None:
|
|
296
|
+
value = self._getenv("LLM_API_KEY_SMALL")
|
|
297
|
+
return None if value == "" else value
|
|
235
298
|
|
|
236
299
|
@property
|
|
237
300
|
def LLM_SYSTEM_PROMPT(self) -> str | None:
|
|
238
|
-
|
|
301
|
+
value = self._getenv("LLM_SYSTEM_PROMPT")
|
|
302
|
+
return None if value == "" else value
|
|
239
303
|
|
|
240
304
|
@property
|
|
241
305
|
def LLM_INTERACTIVE_SYSTEM_PROMPT(self) -> str | None:
|
|
242
|
-
|
|
306
|
+
value = self._getenv("LLM_INTERACTIVE_SYSTEM_PROMPT")
|
|
307
|
+
return None if value == "" else value
|
|
243
308
|
|
|
244
309
|
@property
|
|
245
310
|
def LLM_PERSONA(self) -> str | None:
|
|
246
|
-
|
|
311
|
+
value = self._getenv("LLM_PERSONA")
|
|
312
|
+
return None if value == "" else value
|
|
247
313
|
|
|
248
314
|
@property
|
|
249
|
-
def
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
315
|
+
def LLM_WORKFLOWS(self) -> list[str]:
|
|
316
|
+
"""Get a list of LLM workflows from environment variables."""
|
|
317
|
+
workflows = []
|
|
318
|
+
for workflow in self._getenv("LLM_WORKFLOWS", "").split(","):
|
|
319
|
+
workflow = workflow.strip()
|
|
320
|
+
if workflow != "":
|
|
321
|
+
workflows.append(workflow)
|
|
322
|
+
return workflows
|
|
323
|
+
|
|
324
|
+
@property
|
|
325
|
+
def LLM_BUILTIN_WORKFLOW_PATHS(self) -> list[str]:
|
|
326
|
+
"""Get a list of additional builtin workflow paths from environment variables."""
|
|
327
|
+
builtin_workflow_paths_str = self._getenv(
|
|
328
|
+
["LLM_BUILTIN_WORFKLOW_PATH", "LLM_BUILTIN_WORKFLOW_PATHS"], ""
|
|
329
|
+
)
|
|
330
|
+
if builtin_workflow_paths_str != "":
|
|
331
|
+
return [
|
|
332
|
+
path.strip()
|
|
333
|
+
for path in builtin_workflow_paths_str.split(":")
|
|
334
|
+
if path.strip() != ""
|
|
335
|
+
]
|
|
336
|
+
return []
|
|
255
337
|
|
|
256
338
|
@property
|
|
257
339
|
def LLM_SPECIAL_INSTRUCTION_PROMPT(self) -> str | None:
|
|
258
|
-
|
|
340
|
+
value = self._getenv("LLM_SPECIAL_INSTRUCTION_PROMPT")
|
|
341
|
+
return None if value == "" else value
|
|
259
342
|
|
|
260
343
|
@property
|
|
261
344
|
def LLM_SUMMARIZATION_PROMPT(self) -> str | None:
|
|
262
|
-
|
|
345
|
+
value = self._getenv("LLM_SUMMARIZATION_PROMPT")
|
|
346
|
+
return None if value == "" else value
|
|
347
|
+
|
|
348
|
+
@property
|
|
349
|
+
def LLM_SHOW_TOOL_CALL_RESULT(self) -> bool:
|
|
350
|
+
return to_boolean(self._getenv("LLM_SHOW_TOOL_CALL_RESULT", "false"))
|
|
263
351
|
|
|
264
352
|
@property
|
|
265
353
|
def LLM_MAX_REQUESTS_PER_MINUTE(self) -> int:
|
|
@@ -267,7 +355,11 @@ class Config:
|
|
|
267
355
|
Maximum number of LLM requests allowed per minute.
|
|
268
356
|
Default is conservative to accommodate free-tier LLM providers.
|
|
269
357
|
"""
|
|
270
|
-
return int(
|
|
358
|
+
return int(
|
|
359
|
+
self._getenv(
|
|
360
|
+
["LLM_MAX_REQUEST_PER_MINUTE", "LLM_MAX_REQUESTS_PER_MINUTE"], "60"
|
|
361
|
+
)
|
|
362
|
+
)
|
|
271
363
|
|
|
272
364
|
@property
|
|
273
365
|
def LLM_MAX_TOKENS_PER_MINUTE(self) -> int:
|
|
@@ -275,122 +367,248 @@ class Config:
|
|
|
275
367
|
Maximum number of LLM tokens allowed per minute.
|
|
276
368
|
Default is conservative to accommodate free-tier LLM providers.
|
|
277
369
|
"""
|
|
278
|
-
return int(
|
|
370
|
+
return int(
|
|
371
|
+
self._getenv(
|
|
372
|
+
["LLM_MAX_TOKEN_PER_MINUTE", "LLM_MAX_TOKENS_PER_MINUTE"], "100000"
|
|
373
|
+
)
|
|
374
|
+
)
|
|
279
375
|
|
|
280
376
|
@property
|
|
281
377
|
def LLM_MAX_TOKENS_PER_REQUEST(self) -> int:
|
|
282
378
|
"""Maximum number of tokens allowed per individual LLM request."""
|
|
283
|
-
return int(
|
|
379
|
+
return int(
|
|
380
|
+
self._getenv(
|
|
381
|
+
["LLM_MAX_TOKEN_PER_REQUEST", "LLM_MAX_TOKENS_PER_REQUEST"], "120000"
|
|
382
|
+
)
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
@property
|
|
386
|
+
def LLM_MAX_TOKENS_PER_TOOL_CALL_RESULT(self) -> int:
|
|
387
|
+
"""Maximum number of tokens allowed per tool call result."""
|
|
388
|
+
return int(
|
|
389
|
+
self._getenv(
|
|
390
|
+
[
|
|
391
|
+
"LLM_MAX_TOKEN_PER_TOOL_CALL_RESULT",
|
|
392
|
+
"LLM_MAX_TOKENS_PER_TOOL_CALL_RESULT",
|
|
393
|
+
],
|
|
394
|
+
str(self._get_max_threshold(0.4)),
|
|
395
|
+
)
|
|
396
|
+
)
|
|
284
397
|
|
|
285
398
|
@property
|
|
286
399
|
def LLM_THROTTLE_SLEEP(self) -> float:
|
|
287
400
|
"""Number of seconds to sleep when throttling is required."""
|
|
288
|
-
return float(
|
|
401
|
+
return float(self._getenv("LLM_THROTTLE_SLEEP", "5.0"))
|
|
289
402
|
|
|
290
403
|
@property
|
|
291
|
-
def LLM_YOLO_MODE(self) -> bool:
|
|
292
|
-
|
|
404
|
+
def LLM_YOLO_MODE(self) -> bool | list[str]:
|
|
405
|
+
str_val = self._getenv("LLM_YOLO_MODE", "false")
|
|
406
|
+
try:
|
|
407
|
+
return to_boolean(str_val)
|
|
408
|
+
except Exception:
|
|
409
|
+
return [val.strip() for val in str_val.split(",") if val.strip() != ""]
|
|
293
410
|
|
|
294
411
|
@property
|
|
295
412
|
def LLM_SUMMARIZE_HISTORY(self) -> bool:
|
|
296
|
-
return to_boolean(
|
|
413
|
+
return to_boolean(self._getenv("LLM_SUMMARIZE_HISTORY", "true"))
|
|
297
414
|
|
|
298
415
|
@property
|
|
299
416
|
def LLM_HISTORY_SUMMARIZATION_TOKEN_THRESHOLD(self) -> int:
|
|
300
|
-
|
|
417
|
+
threshold = int(
|
|
418
|
+
self._getenv(
|
|
419
|
+
"LLM_HISTORY_SUMMARIZATION_TOKEN_THRESHOLD",
|
|
420
|
+
str(self._get_max_threshold(0.6)),
|
|
421
|
+
)
|
|
422
|
+
)
|
|
423
|
+
return self._limit_token_threshold(threshold, 0.6)
|
|
301
424
|
|
|
302
425
|
@property
|
|
303
426
|
def LLM_REPO_ANALYSIS_EXTRACTION_TOKEN_THRESHOLD(self) -> int:
|
|
304
|
-
|
|
427
|
+
threshold = int(
|
|
428
|
+
self._getenv(
|
|
429
|
+
"LLM_REPO_ANALYSIS_EXTRACTION_TOKEN_THRESHOLD",
|
|
430
|
+
str(self._get_max_threshold(0.4)),
|
|
431
|
+
)
|
|
432
|
+
)
|
|
433
|
+
return self._limit_token_threshold(threshold, 0.4)
|
|
305
434
|
|
|
306
435
|
@property
|
|
307
436
|
def LLM_REPO_ANALYSIS_SUMMARIZATION_TOKEN_THRESHOLD(self) -> int:
|
|
308
|
-
|
|
309
|
-
|
|
437
|
+
threshold = int(
|
|
438
|
+
self._getenv(
|
|
439
|
+
"LLM_REPO_ANALYSIS_SUMMARIZATION_TOKEN_THRESHOLD",
|
|
440
|
+
str(self._get_max_threshold(0.4)),
|
|
441
|
+
)
|
|
310
442
|
)
|
|
443
|
+
return self._limit_token_threshold(threshold, 0.4)
|
|
311
444
|
|
|
312
445
|
@property
|
|
313
|
-
def
|
|
314
|
-
|
|
446
|
+
def LLM_FILE_ANALYSIS_TOKEN_THRESHOLD(self) -> int:
|
|
447
|
+
threshold = int(
|
|
448
|
+
self._getenv(
|
|
449
|
+
"LLM_FILE_ANALYSIS_TOKEN_THRESHOLD", str(self._get_max_threshold(0.4))
|
|
450
|
+
)
|
|
451
|
+
)
|
|
452
|
+
return self._limit_token_threshold(threshold, 0.4)
|
|
453
|
+
|
|
454
|
+
def _limit_token_threshold(self, threshold: int, factor: float) -> int:
|
|
455
|
+
return min(threshold, self._get_max_threshold(factor))
|
|
456
|
+
|
|
457
|
+
def _get_max_threshold(self, factor: float) -> int:
|
|
458
|
+
return round(
|
|
459
|
+
factor
|
|
460
|
+
* min(self.LLM_MAX_TOKENS_PER_MINUTE, self.LLM_MAX_TOKENS_PER_REQUEST)
|
|
461
|
+
)
|
|
315
462
|
|
|
316
463
|
@property
|
|
317
464
|
def LLM_FILE_EXTRACTOR_SYSTEM_PROMPT(self) -> str:
|
|
318
|
-
return
|
|
319
|
-
"
|
|
465
|
+
return self._getenv(
|
|
466
|
+
"LLM_FILE_EXTRACTOR_SYSTEM_PROMPT",
|
|
320
467
|
self._get_internal_default_prompt("file_extractor_system_prompt"),
|
|
321
468
|
)
|
|
322
469
|
|
|
323
470
|
@property
|
|
324
471
|
def LLM_REPO_EXTRACTOR_SYSTEM_PROMPT(self) -> str:
|
|
325
|
-
return
|
|
326
|
-
"
|
|
472
|
+
return self._getenv(
|
|
473
|
+
"LLM_REPO_EXTRACTOR_SYSTEM_PROMPT",
|
|
327
474
|
self._get_internal_default_prompt("repo_extractor_system_prompt"),
|
|
328
475
|
)
|
|
329
476
|
|
|
330
477
|
@property
|
|
331
478
|
def LLM_REPO_SUMMARIZER_SYSTEM_PROMPT(self) -> str:
|
|
332
|
-
return
|
|
333
|
-
"
|
|
479
|
+
return self._getenv(
|
|
480
|
+
"LLM_REPO_SUMMARIZER_SYSTEM_PROMPT",
|
|
334
481
|
self._get_internal_default_prompt("repo_summarizer_system_prompt"),
|
|
335
482
|
)
|
|
336
483
|
|
|
337
484
|
@property
|
|
338
485
|
def LLM_HISTORY_DIR(self) -> str:
|
|
339
|
-
return
|
|
340
|
-
"
|
|
486
|
+
return self._getenv(
|
|
487
|
+
"LLM_HISTORY_DIR",
|
|
341
488
|
os.path.expanduser(os.path.join("~", ".zrb-llm-history")),
|
|
342
489
|
)
|
|
343
490
|
|
|
344
491
|
@property
|
|
345
492
|
def LLM_ALLOW_ACCESS_LOCAL_FILE(self) -> bool:
|
|
346
|
-
return to_boolean(
|
|
493
|
+
return to_boolean(self._getenv("LLM_ALLOW_ACCESS_LOCAL_FILE", "1"))
|
|
494
|
+
|
|
495
|
+
@property
|
|
496
|
+
def LLM_ALLOW_ANALYZE_FILE(self) -> bool:
|
|
497
|
+
return to_boolean(self._getenv("LLM_ALLOW_ANALYZE_LOCAL_FILE", "1"))
|
|
498
|
+
|
|
499
|
+
@property
|
|
500
|
+
def LLM_ALLOW_ANALYZE_REPO(self) -> bool:
|
|
501
|
+
return to_boolean(self._getenv("LLM_ALLOW_ANALYZE_REPO", "1"))
|
|
347
502
|
|
|
348
503
|
@property
|
|
349
504
|
def LLM_ALLOW_ACCESS_SHELL(self) -> bool:
|
|
350
|
-
return to_boolean(
|
|
505
|
+
return to_boolean(self._getenv("LLM_ALLOW_ACCESS_SHELL", "1"))
|
|
351
506
|
|
|
352
507
|
@property
|
|
353
|
-
def
|
|
354
|
-
return to_boolean(
|
|
508
|
+
def LLM_ALLOW_OPEN_WEB_PAGE(self) -> bool:
|
|
509
|
+
return to_boolean(self._getenv("LLM_ALLOW_OPEN_WEB_PAGE", "1"))
|
|
355
510
|
|
|
356
511
|
@property
|
|
357
|
-
def
|
|
358
|
-
return
|
|
512
|
+
def LLM_ALLOW_SEARCH_INTERNET(self) -> bool:
|
|
513
|
+
return to_boolean(self._getenv("LLM_ALLOW_SEARCH_INTERNET", "1"))
|
|
359
514
|
|
|
360
515
|
@property
|
|
361
|
-
def
|
|
362
|
-
return
|
|
516
|
+
def LLM_ALLOW_GET_CURRENT_LOCATION(self) -> bool:
|
|
517
|
+
return to_boolean(self._getenv("LLM_ALLOW_GET_CURRENT_LOCATION", "1"))
|
|
518
|
+
|
|
519
|
+
@property
|
|
520
|
+
def LLM_ALLOW_GET_CURRENT_WEATHER(self) -> bool:
|
|
521
|
+
return to_boolean(self._getenv("LLM_ALLOW_GET_CURRENT_WEATHER", "1"))
|
|
522
|
+
|
|
523
|
+
@property
|
|
524
|
+
def RAG_EMBEDDING_API_KEY(self) -> str | None:
|
|
525
|
+
value = self._getenv("RAG_EMBEDDING_API_KEY")
|
|
526
|
+
return None if value == "" else value
|
|
527
|
+
|
|
528
|
+
@property
|
|
529
|
+
def RAG_EMBEDDING_BASE_URL(self) -> str | None:
|
|
530
|
+
value = self._getenv("RAG_EMBEDDING_BASE_URL")
|
|
531
|
+
return None if value == "" else value
|
|
363
532
|
|
|
364
533
|
@property
|
|
365
534
|
def RAG_EMBEDDING_MODEL(self) -> str:
|
|
366
|
-
return
|
|
535
|
+
return self._getenv("RAG_EMBEDDING_MODEL", "text-embedding-ada-002")
|
|
367
536
|
|
|
368
537
|
@property
|
|
369
538
|
def RAG_CHUNK_SIZE(self) -> int:
|
|
370
|
-
return int(
|
|
539
|
+
return int(self._getenv("RAG_CHUNK_SIZE", "1024"))
|
|
371
540
|
|
|
372
541
|
@property
|
|
373
542
|
def RAG_OVERLAP(self) -> int:
|
|
374
|
-
return int(
|
|
543
|
+
return int(self._getenv("RAG_OVERLAP", "128"))
|
|
375
544
|
|
|
376
545
|
@property
|
|
377
546
|
def RAG_MAX_RESULT_COUNT(self) -> int:
|
|
378
|
-
return int(
|
|
547
|
+
return int(self._getenv("RAG_MAX_RESULT_COUNT", "5"))
|
|
548
|
+
|
|
549
|
+
@property
|
|
550
|
+
def SEARCH_INTERNET_METHOD(self) -> str:
|
|
551
|
+
"""Either serpapi or searxng"""
|
|
552
|
+
return self._getenv("SEARCH_INTERNET_METHOD", "serpapi")
|
|
553
|
+
|
|
554
|
+
@property
|
|
555
|
+
def BRAVE_API_KEY(self) -> str:
|
|
556
|
+
return os.getenv("BRAVE_API_KEY", "")
|
|
557
|
+
|
|
558
|
+
@property
|
|
559
|
+
def BRAVE_API_SAFE(self) -> str:
|
|
560
|
+
return self._getenv("BRAVE_API_SAFE", "off")
|
|
561
|
+
|
|
562
|
+
@property
|
|
563
|
+
def BRAVE_API_LANG(self) -> str:
|
|
564
|
+
return self._getenv("BRAVE_API_LANG", "en")
|
|
379
565
|
|
|
380
566
|
@property
|
|
381
567
|
def SERPAPI_KEY(self) -> str:
|
|
382
568
|
return os.getenv("SERPAPI_KEY", "")
|
|
383
569
|
|
|
570
|
+
@property
|
|
571
|
+
def SERPAPI_SAFE(self) -> str:
|
|
572
|
+
return self._getenv("SERPAPI_SAFE", "off")
|
|
573
|
+
|
|
574
|
+
@property
|
|
575
|
+
def SERPAPI_LANG(self) -> str:
|
|
576
|
+
return self._getenv("SERPAPI_LANG", "en")
|
|
577
|
+
|
|
578
|
+
@property
|
|
579
|
+
def SEARXNG_PORT(self) -> int:
|
|
580
|
+
return int(self._getenv("SEARXNG_PORT", "8080"))
|
|
581
|
+
|
|
582
|
+
@property
|
|
583
|
+
def SEARXNG_BASE_URL(self) -> str:
|
|
584
|
+
return self._getenv("SEARXNG_BASE_URL", f"http://localhost:{self.SEARXNG_PORT}")
|
|
585
|
+
|
|
586
|
+
@property
|
|
587
|
+
def SEARXNG_SAFE(self) -> int:
|
|
588
|
+
return int(self._getenv("SEARXNG_SAFE", "0"))
|
|
589
|
+
|
|
590
|
+
@property
|
|
591
|
+
def SEARXNG_LANG(self) -> str:
|
|
592
|
+
return self._getenv("SEARXNG_LANG", "en")
|
|
593
|
+
|
|
384
594
|
@property
|
|
385
595
|
def BANNER(self) -> str:
|
|
386
596
|
return fstring_format(
|
|
387
|
-
|
|
597
|
+
self._getenv("BANNER", _DEFAULT_BANNER),
|
|
388
598
|
{"VERSION": self.VERSION},
|
|
389
599
|
)
|
|
390
600
|
|
|
391
601
|
@property
|
|
392
602
|
def LLM_CONTEXT_FILE(self) -> str:
|
|
393
|
-
return
|
|
603
|
+
return self._getenv("LLM_CONTEXT_FILE", "ZRB.md")
|
|
604
|
+
|
|
605
|
+
@property
|
|
606
|
+
def USE_TIKTOKEN(self) -> bool:
|
|
607
|
+
return to_boolean(self._getenv("USE_TIKTOKEN", "true"))
|
|
608
|
+
|
|
609
|
+
@property
|
|
610
|
+
def TIKTOKEN_ENCODING_NAME(self) -> str:
|
|
611
|
+
return self._getenv("TIKTOKEN_ENCODING_NAME", "cl100k_base")
|
|
394
612
|
|
|
395
613
|
|
|
396
614
|
CFG = Config()
|