zrb 1.8.10__py3-none-any.whl → 1.21.29__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 +126 -113
- zrb/__main__.py +1 -1
- zrb/attr/type.py +10 -7
- zrb/builtin/__init__.py +2 -50
- 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 +274 -0
- zrb/builtin/llm/chat_session.py +152 -85
- zrb/builtin/llm/chat_session_cmd.py +288 -0
- zrb/builtin/llm/chat_trigger.py +79 -0
- zrb/builtin/llm/history.py +7 -9
- zrb/builtin/llm/llm_ask.py +221 -98
- zrb/builtin/llm/tool/api.py +74 -52
- zrb/builtin/llm/tool/cli.py +46 -17
- zrb/builtin/llm/tool/code.py +71 -90
- zrb/builtin/llm/tool/file.py +301 -241
- zrb/builtin/llm/tool/note.py +84 -0
- zrb/builtin/llm/tool/rag.py +38 -8
- zrb/builtin/llm/tool/sub_agent.py +67 -50
- zrb/builtin/llm/tool/web.py +146 -122
- 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/builtin/todo.py +13 -2
- zrb/config/config.py +614 -0
- zrb/config/default_prompt/file_extractor_system_prompt.md +112 -0
- zrb/config/default_prompt/interactive_system_prompt.md +29 -0
- zrb/config/default_prompt/persona.md +1 -0
- zrb/config/default_prompt/repo_extractor_system_prompt.md +112 -0
- zrb/config/default_prompt/repo_summarizer_system_prompt.md +29 -0
- zrb/config/default_prompt/summarization_prompt.md +57 -0
- zrb/config/default_prompt/system_prompt.md +38 -0
- zrb/config/llm_config.py +339 -0
- zrb/config/llm_context/config.py +166 -0
- zrb/config/llm_context/config_parser.py +40 -0
- zrb/config/llm_context/workflow.py +81 -0
- zrb/config/llm_rate_limitter.py +190 -0
- zrb/{runner → config}/web_auth_config.py +17 -22
- zrb/context/any_shared_context.py +17 -1
- zrb/context/context.py +16 -2
- zrb/context/shared_context.py +18 -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 +8 -25
- zrb/runner/cli.py +25 -23
- zrb/runner/common_util.py +24 -19
- zrb/runner/web_app.py +3 -3
- zrb/runner/web_route/docs_route.py +1 -1
- zrb/runner/web_route/error_page/serve_default_404.py +1 -1
- zrb/runner/web_route/error_page/show_error_page.py +1 -1
- zrb/runner/web_route/home_page/home_page_route.py +2 -2
- zrb/runner/web_route/login_api_route.py +1 -1
- zrb/runner/web_route/login_page/login_page_route.py +2 -2
- zrb/runner/web_route/logout_api_route.py +1 -1
- zrb/runner/web_route/logout_page/logout_page_route.py +2 -2
- zrb/runner/web_route/node_page/group/show_group_page.py +1 -1
- zrb/runner/web_route/node_page/node_page_route.py +1 -1
- zrb/runner/web_route/node_page/task/show_task_page.py +1 -1
- zrb/runner/web_route/refresh_token_api_route.py +1 -1
- zrb/runner/web_route/static/static_route.py +1 -1
- zrb/runner/web_route/task_input_api_route.py +6 -6
- zrb/runner/web_route/task_session_api_route.py +20 -12
- zrb/runner/web_util/cookie.py +1 -1
- zrb/runner/web_util/token.py +1 -1
- zrb/runner/web_util/user.py +8 -4
- zrb/session/any_session.py +24 -17
- zrb/session/session.py +50 -25
- zrb/session_state_logger/any_session_state_logger.py +9 -4
- zrb/session_state_logger/file_session_state_logger.py +16 -6
- zrb/session_state_logger/session_state_logger_factory.py +1 -1
- zrb/task/any_task.py +30 -9
- 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/cmd_task.py +1 -1
- zrb/task/llm/agent.py +154 -161
- zrb/task/llm/agent_runner.py +152 -0
- zrb/task/llm/config.py +47 -18
- zrb/task/llm/conversation_history.py +209 -0
- zrb/task/llm/conversation_history_model.py +67 -0
- 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/error.py +24 -10
- 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 +11 -166
- zrb/task/llm/print_node.py +193 -69
- zrb/task/llm/prompt.py +242 -45
- zrb/task/llm/subagent_conversation_history.py +41 -0
- zrb/task/llm/tool_wrapper.py +260 -57
- zrb/task/llm/workflow.py +76 -0
- zrb/task/llm_task.py +182 -171
- zrb/task/make_task.py +2 -3
- zrb/task/rsync_task.py +26 -11
- zrb/task/scheduler.py +4 -4
- zrb/util/attr.py +54 -39
- zrb/util/callable.py +23 -0
- zrb/util/cli/markdown.py +12 -0
- zrb/util/cli/text.py +30 -0
- zrb/util/file.py +29 -11
- zrb/util/git.py +8 -11
- zrb/util/git_diff_model.py +10 -0
- zrb/util/git_subtree.py +9 -14
- zrb/util/git_subtree_model.py +32 -0
- zrb/util/init_path.py +1 -1
- zrb/util/markdown.py +62 -0
- zrb/util/string/conversion.py +2 -2
- zrb/util/todo.py +17 -50
- zrb/util/todo_model.py +46 -0
- zrb/util/truncate.py +23 -0
- zrb/util/yaml.py +204 -0
- zrb/xcom/xcom.py +10 -0
- zrb-1.21.29.dist-info/METADATA +270 -0
- {zrb-1.8.10.dist-info → zrb-1.21.29.dist-info}/RECORD +140 -98
- {zrb-1.8.10.dist-info → zrb-1.21.29.dist-info}/WHEEL +1 -1
- zrb/config.py +0 -335
- zrb/llm_config.py +0 -411
- zrb/llm_rate_limitter.py +0 -125
- zrb/task/llm/context.py +0 -102
- zrb/task/llm/context_enrichment.py +0 -199
- zrb/task/llm/history.py +0 -211
- zrb-1.8.10.dist-info/METADATA +0 -264
- {zrb-1.8.10.dist-info → zrb-1.21.29.dist-info}/entry_points.txt +0 -0
zrb/config/config.py
ADDED
|
@@ -0,0 +1,614 @@
|
|
|
1
|
+
import importlib.metadata as metadata
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
import platform
|
|
5
|
+
|
|
6
|
+
from zrb.util.string.conversion import to_boolean
|
|
7
|
+
from zrb.util.string.format import fstring_format
|
|
8
|
+
|
|
9
|
+
_DEFAULT_BANNER = """
|
|
10
|
+
bb
|
|
11
|
+
zzzzz rr rr bb
|
|
12
|
+
zz rrr r bbbbbb
|
|
13
|
+
zz rr bb bb
|
|
14
|
+
zzzzz rr bbbbbb {VERSION} Janggala
|
|
15
|
+
_ _ . . . _ . _ . . .
|
|
16
|
+
Your Automation Powerhouse
|
|
17
|
+
☕ Donate at: https://stalchmst.com
|
|
18
|
+
🐙 Submit issues/PR at: https://github.com/state-alchemists/zrb
|
|
19
|
+
🐤 Follow us at: https://twitter.com/zarubastalchmst
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Config:
|
|
24
|
+
def __init__(self):
|
|
25
|
+
self.__internal_default_prompt: dict[str, str] = {}
|
|
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
|
+
|
|
39
|
+
def _get_internal_default_prompt(self, name: str) -> str:
|
|
40
|
+
if name not in self.__internal_default_prompt:
|
|
41
|
+
file_path = os.path.join(
|
|
42
|
+
os.path.dirname(__file__), "default_prompt", f"{name}.md"
|
|
43
|
+
)
|
|
44
|
+
with open(file_path, "r") as f:
|
|
45
|
+
self.__internal_default_prompt[name] = f.read().strip()
|
|
46
|
+
return self.__internal_default_prompt[name]
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def LOGGER(self) -> logging.Logger:
|
|
50
|
+
return logging.getLogger()
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def DEFAULT_SHELL(self) -> str:
|
|
54
|
+
return self._getenv("SHELL", self._get_current_shell())
|
|
55
|
+
|
|
56
|
+
def _get_current_shell(self) -> str:
|
|
57
|
+
if platform.system() == "Windows":
|
|
58
|
+
return "PowerShell"
|
|
59
|
+
current_shell = os.getenv("SHELL", "")
|
|
60
|
+
if current_shell.endswith("zsh"):
|
|
61
|
+
return "zsh"
|
|
62
|
+
return "bash"
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def DEFAULT_EDITOR(self) -> str:
|
|
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
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def INIT_MODULES(self) -> list[str]:
|
|
102
|
+
init_modules_str = self._getenv("INIT_MODULES", "")
|
|
103
|
+
if init_modules_str != "":
|
|
104
|
+
return [
|
|
105
|
+
module.strip()
|
|
106
|
+
for module in init_modules_str.split(":")
|
|
107
|
+
if module.strip() != ""
|
|
108
|
+
]
|
|
109
|
+
return []
|
|
110
|
+
|
|
111
|
+
@property
|
|
112
|
+
def ROOT_GROUP_NAME(self) -> str:
|
|
113
|
+
return self._getenv("ROOT_GROUP_NAME", "zrb")
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def ROOT_GROUP_DESCRIPTION(self) -> str:
|
|
117
|
+
return self._getenv("ROOT_GROUP_DESCRIPTION", "Your Automation Powerhouse")
|
|
118
|
+
|
|
119
|
+
@property
|
|
120
|
+
def INIT_SCRIPTS(self) -> list[str]:
|
|
121
|
+
init_scripts_str = self._getenv("INIT_SCRIPTS", "")
|
|
122
|
+
if init_scripts_str != "":
|
|
123
|
+
return [
|
|
124
|
+
script.strip()
|
|
125
|
+
for script in init_scripts_str.split(":")
|
|
126
|
+
if script.strip() != ""
|
|
127
|
+
]
|
|
128
|
+
return []
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def INIT_FILE_NAME(self) -> str:
|
|
132
|
+
return self._getenv("INIT_FILE_NAME", "zrb_init.py")
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def LOGGING_LEVEL(self) -> int:
|
|
136
|
+
return self._get_log_level(self._getenv("LOGGING_LEVEL", "WARNING"))
|
|
137
|
+
|
|
138
|
+
def _get_log_level(self, level: str) -> int:
|
|
139
|
+
level = level.upper()
|
|
140
|
+
log_levels = {
|
|
141
|
+
"CRITICAL": logging.CRITICAL, # 50
|
|
142
|
+
"FATAL": logging.CRITICAL, # 50
|
|
143
|
+
"ERROR": logging.ERROR, # 40
|
|
144
|
+
"WARN": logging.WARNING, # 30
|
|
145
|
+
"WARNING": logging.WARNING, # 30
|
|
146
|
+
"INFO": logging.INFO, # 20
|
|
147
|
+
"DEBUG": logging.DEBUG, # 10
|
|
148
|
+
"NOTSET": logging.NOTSET, # 0
|
|
149
|
+
}
|
|
150
|
+
if level in log_levels:
|
|
151
|
+
return log_levels[level]
|
|
152
|
+
return logging.WARNING
|
|
153
|
+
|
|
154
|
+
@property
|
|
155
|
+
def LOAD_BUILTIN(self) -> bool:
|
|
156
|
+
return to_boolean(self._getenv("LOAD_BUILTIN", "1"))
|
|
157
|
+
|
|
158
|
+
@property
|
|
159
|
+
def WARN_UNRECOMMENDED_COMMAND(self) -> bool:
|
|
160
|
+
return to_boolean(self._getenv("WARN_UNRECOMMENDED_COMMAND", "1"))
|
|
161
|
+
|
|
162
|
+
@property
|
|
163
|
+
def SESSION_LOG_DIR(self) -> str:
|
|
164
|
+
return os.getenv(
|
|
165
|
+
"ZRB_SESSION_LOG_DIR", os.path.expanduser(os.path.join("~", ".zrb-session"))
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
@property
|
|
169
|
+
def TODO_DIR(self) -> str:
|
|
170
|
+
return self._getenv("TODO_DIR", os.path.expanduser(os.path.join("~", "todo")))
|
|
171
|
+
|
|
172
|
+
@property
|
|
173
|
+
def TODO_VISUAL_FILTER(self) -> str:
|
|
174
|
+
return self._getenv("TODO_FILTER", "")
|
|
175
|
+
|
|
176
|
+
@property
|
|
177
|
+
def TODO_RETENTION(self) -> str:
|
|
178
|
+
return self._getenv("TODO_RETENTION", "2w")
|
|
179
|
+
|
|
180
|
+
@property
|
|
181
|
+
def VERSION(self) -> str:
|
|
182
|
+
custom_version = os.getenv("_ZRB_CUSTOM_VERSION", "")
|
|
183
|
+
if custom_version != "":
|
|
184
|
+
return custom_version
|
|
185
|
+
return metadata.version("zrb")
|
|
186
|
+
|
|
187
|
+
@property
|
|
188
|
+
def WEB_CSS_PATH(self) -> list[str]:
|
|
189
|
+
web_css_path_str = self._getenv("WEB_CSS_PATH", "")
|
|
190
|
+
if web_css_path_str != "":
|
|
191
|
+
return [
|
|
192
|
+
path.strip()
|
|
193
|
+
for path in web_css_path_str.split(":")
|
|
194
|
+
if path.strip() != ""
|
|
195
|
+
]
|
|
196
|
+
return []
|
|
197
|
+
|
|
198
|
+
@property
|
|
199
|
+
def WEB_JS_PATH(self) -> list[str]:
|
|
200
|
+
web_js_path_str = self._getenv("WEB_JS_PATH", "")
|
|
201
|
+
if web_js_path_str != "":
|
|
202
|
+
return [
|
|
203
|
+
path.strip()
|
|
204
|
+
for path in web_js_path_str.split(":")
|
|
205
|
+
if path.strip() != ""
|
|
206
|
+
]
|
|
207
|
+
return []
|
|
208
|
+
|
|
209
|
+
@property
|
|
210
|
+
def WEB_FAVICON_PATH(self) -> str:
|
|
211
|
+
return self._getenv("WEB_FAVICON_PATH", "/static/favicon-32x32.png")
|
|
212
|
+
|
|
213
|
+
@property
|
|
214
|
+
def WEB_COLOR(self) -> str:
|
|
215
|
+
return self._getenv("WEB_COLOR", "")
|
|
216
|
+
|
|
217
|
+
@property
|
|
218
|
+
def WEB_HTTP_PORT(self) -> int:
|
|
219
|
+
return int(self._getenv("WEB_HTTP_PORT", "21213"))
|
|
220
|
+
|
|
221
|
+
@property
|
|
222
|
+
def WEB_GUEST_USERNAME(self) -> str:
|
|
223
|
+
return self._getenv("WEB_GUEST_USERNAME", "user")
|
|
224
|
+
|
|
225
|
+
@property
|
|
226
|
+
def WEB_SUPER_ADMIN_USERNAME(self) -> str:
|
|
227
|
+
return self._getenv("WEB_SUPER_ADMIN_USERNAME", "admin")
|
|
228
|
+
|
|
229
|
+
@property
|
|
230
|
+
def WEB_SUPER_ADMIN_PASSWORD(self) -> str:
|
|
231
|
+
return self._getenv("WEB_SUPER_ADMIN_PASSWORD", "admin")
|
|
232
|
+
|
|
233
|
+
@property
|
|
234
|
+
def WEB_ACCESS_TOKEN_COOKIE_NAME(self) -> str:
|
|
235
|
+
return self._getenv("WEB_ACCESS_TOKEN_COOKIE_NAME", "access_token")
|
|
236
|
+
|
|
237
|
+
@property
|
|
238
|
+
def WEB_REFRESH_TOKEN_COOKIE_NAME(self) -> str:
|
|
239
|
+
return self._getenv("WEB_REFRESH_TOKEN_COOKIE_NAME", "refresh_token")
|
|
240
|
+
|
|
241
|
+
@property
|
|
242
|
+
def WEB_SECRET_KEY(self) -> str:
|
|
243
|
+
return self._getenv("WEB_SECRET", "zrb")
|
|
244
|
+
|
|
245
|
+
@property
|
|
246
|
+
def WEB_ENABLE_AUTH(self) -> bool:
|
|
247
|
+
return to_boolean(self._getenv("WEB_ENABLE_AUTH", "0"))
|
|
248
|
+
|
|
249
|
+
@property
|
|
250
|
+
def WEB_AUTH_ACCESS_TOKEN_EXPIRE_MINUTES(self) -> int:
|
|
251
|
+
return int(self._getenv("WEB_ACCESS_TOKEN_EXPIRE_MINUTES", "30"))
|
|
252
|
+
|
|
253
|
+
@property
|
|
254
|
+
def WEB_AUTH_REFRESH_TOKEN_EXPIRE_MINUTES(self) -> int:
|
|
255
|
+
return int(self._getenv("WEB_REFRESH_TOKEN_EXPIRE_MINUTES", "60"))
|
|
256
|
+
|
|
257
|
+
@property
|
|
258
|
+
def WEB_TITLE(self) -> str:
|
|
259
|
+
return self._getenv("WEB_TITLE", "Zrb")
|
|
260
|
+
|
|
261
|
+
@property
|
|
262
|
+
def WEB_JARGON(self) -> str:
|
|
263
|
+
return self._getenv("WEB_JARGON", "Your Automation PowerHouse")
|
|
264
|
+
|
|
265
|
+
@property
|
|
266
|
+
def WEB_HOMEPAGE_INTRO(self) -> str:
|
|
267
|
+
return self._getenv("WEB_HOMEPAGE_INTRO", "Welcome to Zrb Web Interface")
|
|
268
|
+
|
|
269
|
+
@property
|
|
270
|
+
def LLM_MODEL(self) -> str | None:
|
|
271
|
+
value = self._getenv("LLM_MODEL")
|
|
272
|
+
return None if value == "" else value
|
|
273
|
+
|
|
274
|
+
@property
|
|
275
|
+
def LLM_BASE_URL(self) -> str | None:
|
|
276
|
+
value = self._getenv("LLM_BASE_URL")
|
|
277
|
+
return None if value == "" else value
|
|
278
|
+
|
|
279
|
+
@property
|
|
280
|
+
def LLM_API_KEY(self) -> str | None:
|
|
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
|
|
298
|
+
|
|
299
|
+
@property
|
|
300
|
+
def LLM_SYSTEM_PROMPT(self) -> str | None:
|
|
301
|
+
value = self._getenv("LLM_SYSTEM_PROMPT")
|
|
302
|
+
return None if value == "" else value
|
|
303
|
+
|
|
304
|
+
@property
|
|
305
|
+
def LLM_INTERACTIVE_SYSTEM_PROMPT(self) -> str | None:
|
|
306
|
+
value = self._getenv("LLM_INTERACTIVE_SYSTEM_PROMPT")
|
|
307
|
+
return None if value == "" else value
|
|
308
|
+
|
|
309
|
+
@property
|
|
310
|
+
def LLM_PERSONA(self) -> str | None:
|
|
311
|
+
value = self._getenv("LLM_PERSONA")
|
|
312
|
+
return None if value == "" else value
|
|
313
|
+
|
|
314
|
+
@property
|
|
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 []
|
|
337
|
+
|
|
338
|
+
@property
|
|
339
|
+
def LLM_SPECIAL_INSTRUCTION_PROMPT(self) -> str | None:
|
|
340
|
+
value = self._getenv("LLM_SPECIAL_INSTRUCTION_PROMPT")
|
|
341
|
+
return None if value == "" else value
|
|
342
|
+
|
|
343
|
+
@property
|
|
344
|
+
def LLM_SUMMARIZATION_PROMPT(self) -> str | None:
|
|
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"))
|
|
351
|
+
|
|
352
|
+
@property
|
|
353
|
+
def LLM_MAX_REQUESTS_PER_MINUTE(self) -> int:
|
|
354
|
+
"""
|
|
355
|
+
Maximum number of LLM requests allowed per minute.
|
|
356
|
+
Default is conservative to accommodate free-tier LLM providers.
|
|
357
|
+
"""
|
|
358
|
+
return int(
|
|
359
|
+
self._getenv(
|
|
360
|
+
["LLM_MAX_REQUEST_PER_MINUTE", "LLM_MAX_REQUESTS_PER_MINUTE"], "60"
|
|
361
|
+
)
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
@property
|
|
365
|
+
def LLM_MAX_TOKENS_PER_MINUTE(self) -> int:
|
|
366
|
+
"""
|
|
367
|
+
Maximum number of LLM tokens allowed per minute.
|
|
368
|
+
Default is conservative to accommodate free-tier LLM providers.
|
|
369
|
+
"""
|
|
370
|
+
return int(
|
|
371
|
+
self._getenv(
|
|
372
|
+
["LLM_MAX_TOKEN_PER_MINUTE", "LLM_MAX_TOKENS_PER_MINUTE"], "100000"
|
|
373
|
+
)
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
@property
|
|
377
|
+
def LLM_MAX_TOKENS_PER_REQUEST(self) -> int:
|
|
378
|
+
"""Maximum number of tokens allowed per individual LLM request."""
|
|
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
|
+
)
|
|
397
|
+
|
|
398
|
+
@property
|
|
399
|
+
def LLM_THROTTLE_SLEEP(self) -> float:
|
|
400
|
+
"""Number of seconds to sleep when throttling is required."""
|
|
401
|
+
return float(self._getenv("LLM_THROTTLE_SLEEP", "5.0"))
|
|
402
|
+
|
|
403
|
+
@property
|
|
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() != ""]
|
|
410
|
+
|
|
411
|
+
@property
|
|
412
|
+
def LLM_SUMMARIZE_HISTORY(self) -> bool:
|
|
413
|
+
return to_boolean(self._getenv("LLM_SUMMARIZE_HISTORY", "true"))
|
|
414
|
+
|
|
415
|
+
@property
|
|
416
|
+
def LLM_HISTORY_SUMMARIZATION_TOKEN_THRESHOLD(self) -> int:
|
|
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)
|
|
424
|
+
|
|
425
|
+
@property
|
|
426
|
+
def LLM_REPO_ANALYSIS_EXTRACTION_TOKEN_THRESHOLD(self) -> int:
|
|
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)
|
|
434
|
+
|
|
435
|
+
@property
|
|
436
|
+
def LLM_REPO_ANALYSIS_SUMMARIZATION_TOKEN_THRESHOLD(self) -> int:
|
|
437
|
+
threshold = int(
|
|
438
|
+
self._getenv(
|
|
439
|
+
"LLM_REPO_ANALYSIS_SUMMARIZATION_TOKEN_THRESHOLD",
|
|
440
|
+
str(self._get_max_threshold(0.4)),
|
|
441
|
+
)
|
|
442
|
+
)
|
|
443
|
+
return self._limit_token_threshold(threshold, 0.4)
|
|
444
|
+
|
|
445
|
+
@property
|
|
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
|
+
)
|
|
462
|
+
|
|
463
|
+
@property
|
|
464
|
+
def LLM_FILE_EXTRACTOR_SYSTEM_PROMPT(self) -> str:
|
|
465
|
+
return self._getenv(
|
|
466
|
+
"LLM_FILE_EXTRACTOR_SYSTEM_PROMPT",
|
|
467
|
+
self._get_internal_default_prompt("file_extractor_system_prompt"),
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
@property
|
|
471
|
+
def LLM_REPO_EXTRACTOR_SYSTEM_PROMPT(self) -> str:
|
|
472
|
+
return self._getenv(
|
|
473
|
+
"LLM_REPO_EXTRACTOR_SYSTEM_PROMPT",
|
|
474
|
+
self._get_internal_default_prompt("repo_extractor_system_prompt"),
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
@property
|
|
478
|
+
def LLM_REPO_SUMMARIZER_SYSTEM_PROMPT(self) -> str:
|
|
479
|
+
return self._getenv(
|
|
480
|
+
"LLM_REPO_SUMMARIZER_SYSTEM_PROMPT",
|
|
481
|
+
self._get_internal_default_prompt("repo_summarizer_system_prompt"),
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
@property
|
|
485
|
+
def LLM_HISTORY_DIR(self) -> str:
|
|
486
|
+
return self._getenv(
|
|
487
|
+
"LLM_HISTORY_DIR",
|
|
488
|
+
os.path.expanduser(os.path.join("~", ".zrb-llm-history")),
|
|
489
|
+
)
|
|
490
|
+
|
|
491
|
+
@property
|
|
492
|
+
def LLM_ALLOW_ACCESS_LOCAL_FILE(self) -> bool:
|
|
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"))
|
|
502
|
+
|
|
503
|
+
@property
|
|
504
|
+
def LLM_ALLOW_ACCESS_SHELL(self) -> bool:
|
|
505
|
+
return to_boolean(self._getenv("LLM_ALLOW_ACCESS_SHELL", "1"))
|
|
506
|
+
|
|
507
|
+
@property
|
|
508
|
+
def LLM_ALLOW_OPEN_WEB_PAGE(self) -> bool:
|
|
509
|
+
return to_boolean(self._getenv("LLM_ALLOW_OPEN_WEB_PAGE", "1"))
|
|
510
|
+
|
|
511
|
+
@property
|
|
512
|
+
def LLM_ALLOW_SEARCH_INTERNET(self) -> bool:
|
|
513
|
+
return to_boolean(self._getenv("LLM_ALLOW_SEARCH_INTERNET", "1"))
|
|
514
|
+
|
|
515
|
+
@property
|
|
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
|
|
532
|
+
|
|
533
|
+
@property
|
|
534
|
+
def RAG_EMBEDDING_MODEL(self) -> str:
|
|
535
|
+
return self._getenv("RAG_EMBEDDING_MODEL", "text-embedding-ada-002")
|
|
536
|
+
|
|
537
|
+
@property
|
|
538
|
+
def RAG_CHUNK_SIZE(self) -> int:
|
|
539
|
+
return int(self._getenv("RAG_CHUNK_SIZE", "1024"))
|
|
540
|
+
|
|
541
|
+
@property
|
|
542
|
+
def RAG_OVERLAP(self) -> int:
|
|
543
|
+
return int(self._getenv("RAG_OVERLAP", "128"))
|
|
544
|
+
|
|
545
|
+
@property
|
|
546
|
+
def RAG_MAX_RESULT_COUNT(self) -> 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")
|
|
565
|
+
|
|
566
|
+
@property
|
|
567
|
+
def SERPAPI_KEY(self) -> str:
|
|
568
|
+
return os.getenv("SERPAPI_KEY", "")
|
|
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
|
+
|
|
594
|
+
@property
|
|
595
|
+
def BANNER(self) -> str:
|
|
596
|
+
return fstring_format(
|
|
597
|
+
self._getenv("BANNER", _DEFAULT_BANNER),
|
|
598
|
+
{"VERSION": self.VERSION},
|
|
599
|
+
)
|
|
600
|
+
|
|
601
|
+
@property
|
|
602
|
+
def LLM_CONTEXT_FILE(self) -> str:
|
|
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")
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
CFG = Config()
|