zrb 1.5.17__py3-none-any.whl → 1.6.1__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 -2
- zrb/__main__.py +12 -12
- zrb/builtin/__init__.py +2 -2
- zrb/builtin/llm/chat_session.py +202 -0
- zrb/builtin/llm/history.py +6 -6
- zrb/builtin/llm/llm_ask.py +142 -0
- zrb/builtin/llm/tool/rag.py +39 -23
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/default/script.js +1 -1
- zrb/builtin/todo.py +21 -19
- zrb/callback/any_callback.py +1 -1
- zrb/callback/callback.py +69 -7
- zrb/config.py +261 -91
- zrb/context/shared_context.py +4 -2
- zrb/input/text_input.py +9 -6
- zrb/llm_config.py +73 -79
- zrb/runner/cli.py +13 -4
- zrb/runner/web_app.py +3 -3
- zrb/runner/web_config/config_factory.py +11 -22
- zrb/runner/web_route/error_page/show_error_page.py +16 -6
- zrb/runner/web_route/home_page/home_page_route.py +23 -7
- zrb/runner/web_route/home_page/view.html +19 -33
- zrb/runner/web_route/login_page/login_page_route.py +14 -4
- zrb/runner/web_route/login_page/view.html +33 -51
- zrb/runner/web_route/logout_page/logout_page_route.py +15 -5
- zrb/runner/web_route/logout_page/view.html +23 -41
- zrb/runner/web_route/node_page/group/show_group_page.py +26 -10
- zrb/runner/web_route/node_page/group/view.html +22 -37
- zrb/runner/web_route/node_page/task/show_task_page.py +34 -19
- zrb/runner/web_route/node_page/task/view.html +74 -88
- zrb/runner/web_route/static/global_template.html +27 -0
- zrb/runner/web_route/static/resources/common.css +21 -0
- zrb/runner/web_route/static/resources/common.js +28 -0
- zrb/runner/web_route/task_session_api_route.py +3 -1
- zrb/session_state_logger/session_state_logger_factory.py +2 -2
- zrb/task/base_task.py +4 -1
- zrb/task/base_trigger.py +47 -2
- zrb/task/cmd_task.py +3 -3
- zrb/task/llm/agent.py +11 -3
- zrb/task/llm/context.py +1 -3
- zrb/task/llm/context_enrichment.py +21 -15
- zrb/task/llm/history.py +32 -63
- zrb/task/llm/history_summarization.py +19 -19
- zrb/task/llm/print_node.py +5 -6
- zrb/task/llm/prompt.py +0 -27
- zrb/task/llm_task.py +22 -18
- {zrb-1.5.17.dist-info → zrb-1.6.1.dist-info}/METADATA +1 -1
- {zrb-1.5.17.dist-info → zrb-1.6.1.dist-info}/RECORD +49 -46
- zrb/builtin/llm/llm_chat.py +0 -124
- {zrb-1.5.17.dist-info → zrb-1.6.1.dist-info}/WHEEL +0 -0
- {zrb-1.5.17.dist-info → zrb-1.6.1.dist-info}/entry_points.txt +0 -0
zrb/llm_config.py
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
import os
|
2
1
|
from typing import TYPE_CHECKING, Any
|
3
2
|
|
4
3
|
if TYPE_CHECKING:
|
@@ -8,7 +7,7 @@ else:
|
|
8
7
|
Model = Any
|
9
8
|
Provider = Any
|
10
9
|
|
11
|
-
from zrb.
|
10
|
+
from zrb.config import CFG
|
12
11
|
|
13
12
|
DEFAULT_SYSTEM_PROMPT = """
|
14
13
|
You have access to tools.
|
@@ -27,9 +26,10 @@ You are an expert in various fields including technology, science, history, and
|
|
27
26
|
|
28
27
|
# Concise summarization focused on preserving critical context for continuity.
|
29
28
|
DEFAULT_SUMMARIZATION_PROMPT = """
|
30
|
-
You are a summarization assistant.
|
31
|
-
|
32
|
-
|
29
|
+
You are a summarization assistant.
|
30
|
+
Your goal is to help main assistant to continue the conversation by creating an updated,
|
31
|
+
concise summary integrating the previous summary (if any) with the new conversation history.
|
32
|
+
Preserve ALL critical context needed for the main assistant
|
33
33
|
to continue the task effectively. This includes key facts, decisions, tool usage
|
34
34
|
results, and essential background. Do not omit details that would force the main
|
35
35
|
assistant to re-gather information.
|
@@ -38,11 +38,13 @@ Output *only* the updated summary text.
|
|
38
38
|
|
39
39
|
DEFAULT_CONTEXT_ENRICHMENT_PROMPT = """
|
40
40
|
You are an information extraction assistant.
|
41
|
+
Your goal is to help main assistant to continue the conversation by extracting
|
42
|
+
important informations.
|
41
43
|
Analyze the conversation history and current context to extract key facts like
|
42
44
|
user_name, user_roles, preferences, goals, etc.
|
43
45
|
Return only a JSON object containing a single key "response", whose value is
|
44
|
-
another JSON object with these details.
|
45
|
-
If
|
46
|
+
another JSON object with these details (i.e., {"response": {"context_name": "value"}}).
|
47
|
+
If no context can be extracted, return {"response": {}}.
|
46
48
|
""".strip()
|
47
49
|
|
48
50
|
DEFAULT_SPECIAL_INSTRUCTION_PROMPT = "" # Default to empty
|
@@ -65,72 +67,30 @@ class LLMConfig:
|
|
65
67
|
default_enrich_context: bool | None = None,
|
66
68
|
default_context_enrichment_threshold: int | None = None,
|
67
69
|
):
|
68
|
-
self._default_model_name =
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
self.
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
)
|
78
|
-
self._default_model_api_key = (
|
79
|
-
default_api_key
|
80
|
-
if default_api_key is not None
|
81
|
-
else os.getenv("ZRB_LLM_API_KEY", None)
|
82
|
-
)
|
83
|
-
self._default_system_prompt = (
|
84
|
-
default_system_prompt
|
85
|
-
if default_system_prompt is not None
|
86
|
-
else os.getenv("ZRB_LLM_SYSTEM_PROMPT", None)
|
87
|
-
)
|
88
|
-
self._default_persona = (
|
89
|
-
default_persona
|
90
|
-
if default_persona is not None
|
91
|
-
else os.getenv("ZRB_LLM_PERSONA", None)
|
92
|
-
)
|
93
|
-
self._default_special_instruction_prompt = (
|
94
|
-
default_special_instruction_prompt
|
95
|
-
if default_special_instruction_prompt is not None
|
96
|
-
else os.getenv("ZRB_LLM_SPECIAL_INSTRUCTION_PROMPT", None)
|
97
|
-
)
|
98
|
-
self._default_summarization_prompt = (
|
99
|
-
default_summarization_prompt
|
100
|
-
if default_summarization_prompt is not None
|
101
|
-
else os.getenv("ZRB_LLM_SUMMARIZATION_PROMPT", None)
|
102
|
-
)
|
103
|
-
self._default_context_enrichment_prompt = (
|
104
|
-
default_context_enrichment_prompt
|
105
|
-
if default_context_enrichment_prompt is not None
|
106
|
-
else os.getenv("ZRB_LLM_CONTEXT_ENRICHMENT_PROMPT", None)
|
107
|
-
)
|
108
|
-
self._default_summarize_history = (
|
109
|
-
default_summarize_history
|
110
|
-
if default_summarize_history is not None
|
111
|
-
else to_boolean(os.getenv("ZRB_LLM_SUMMARIZE_HISTORY", "true"))
|
112
|
-
)
|
70
|
+
self._default_model_name = default_model_name
|
71
|
+
self._default_model_base_url = default_base_url
|
72
|
+
self._default_model_api_key = default_api_key
|
73
|
+
self._default_persona = default_persona
|
74
|
+
self._default_system_prompt = default_system_prompt
|
75
|
+
self._default_special_instruction_prompt = default_special_instruction_prompt
|
76
|
+
self._default_summarization_prompt = default_summarization_prompt
|
77
|
+
self._default_context_enrichment_prompt = default_context_enrichment_prompt
|
78
|
+
self._default_summarize_history = default_summarize_history
|
113
79
|
self._default_history_summarization_threshold = (
|
114
80
|
default_history_summarization_threshold
|
115
|
-
if default_history_summarization_threshold is not None
|
116
|
-
else int(os.getenv("ZRB_LLM_HISTORY_SUMMARIZATION_THRESHOLD", "5"))
|
117
|
-
)
|
118
|
-
self._default_enrich_context = (
|
119
|
-
default_enrich_context
|
120
|
-
if default_enrich_context is not None
|
121
|
-
else to_boolean(os.getenv("ZRB_LLM_ENRICH_CONTEXT", "true"))
|
122
81
|
)
|
82
|
+
self._default_enrich_context = default_enrich_context
|
123
83
|
self._default_context_enrichment_threshold = (
|
124
84
|
default_context_enrichment_threshold
|
125
|
-
if default_context_enrichment_threshold is not None
|
126
|
-
else int(os.getenv("ZRB_LLM_CONTEXT_ENRICHMENT_THRESHOLD", "5"))
|
127
85
|
)
|
128
86
|
self._default_provider = None
|
129
87
|
self._default_model = None
|
130
88
|
|
131
89
|
def _get_model_name(self) -> str | None:
|
132
90
|
return (
|
133
|
-
self._default_model_name
|
91
|
+
self._default_model_name
|
92
|
+
if self._default_model_name is not None
|
93
|
+
else CFG.LLM_MODEL
|
134
94
|
)
|
135
95
|
|
136
96
|
def get_default_model_provider(self) -> Provider | str:
|
@@ -146,35 +106,53 @@ class LLMConfig:
|
|
146
106
|
|
147
107
|
def get_default_system_prompt(self) -> str:
|
148
108
|
return (
|
149
|
-
|
150
|
-
if self._default_system_prompt is None
|
151
|
-
else
|
109
|
+
self._default_system_prompt
|
110
|
+
if self._default_system_prompt is not None
|
111
|
+
else (
|
112
|
+
CFG.LLM_SYSTEM_PROMPT
|
113
|
+
if CFG.LLM_SYSTEM_PROMPT is not None
|
114
|
+
else DEFAULT_SYSTEM_PROMPT
|
115
|
+
)
|
152
116
|
)
|
153
117
|
|
154
118
|
def get_default_persona(self) -> str:
|
155
119
|
return (
|
156
|
-
|
120
|
+
self._default_persona
|
121
|
+
if self._default_persona is not None
|
122
|
+
else (CFG.LLM_PERSONA if CFG.LLM_PERSONA is not None else DEFAULT_PERSONA)
|
157
123
|
)
|
158
124
|
|
159
125
|
def get_default_special_instruction_prompt(self) -> str:
|
160
126
|
return (
|
161
|
-
|
162
|
-
if self._default_special_instruction_prompt is None
|
163
|
-
else
|
127
|
+
self._default_special_instruction_prompt
|
128
|
+
if self._default_special_instruction_prompt is not None
|
129
|
+
else (
|
130
|
+
CFG.LLM_SPECIAL_INSTRUCTION_PROMPT
|
131
|
+
if CFG.LLM_SPECIAL_INSTRUCTION_PROMPT is not None
|
132
|
+
else DEFAULT_SPECIAL_INSTRUCTION_PROMPT
|
133
|
+
)
|
164
134
|
)
|
165
135
|
|
166
136
|
def get_default_summarization_prompt(self) -> str:
|
167
137
|
return (
|
168
|
-
|
169
|
-
if self._default_summarization_prompt is None
|
170
|
-
else
|
138
|
+
self._default_summarization_prompt
|
139
|
+
if self._default_summarization_prompt is not None
|
140
|
+
else (
|
141
|
+
CFG.LLM_SUMMARIZATION_PROMPT
|
142
|
+
if CFG.LLM_SUMMARIZATION_PROMPT is not None
|
143
|
+
else DEFAULT_SUMMARIZATION_PROMPT
|
144
|
+
)
|
171
145
|
)
|
172
146
|
|
173
147
|
def get_default_context_enrichment_prompt(self) -> str:
|
174
148
|
return (
|
175
|
-
|
176
|
-
if self._default_context_enrichment_prompt is None
|
177
|
-
else
|
149
|
+
self._default_context_enrichment_prompt
|
150
|
+
if self._default_context_enrichment_prompt is not None
|
151
|
+
else (
|
152
|
+
CFG.LLM_CONTEXT_ENRICHMENT_PROMPT
|
153
|
+
if CFG.LLM_CONTEXT_ENRICHMENT_PROMPT is not None
|
154
|
+
else DEFAULT_CONTEXT_ENRICHMENT_PROMPT
|
155
|
+
)
|
178
156
|
)
|
179
157
|
|
180
158
|
def get_default_model(self) -> Model | str | None:
|
@@ -191,16 +169,32 @@ class LLMConfig:
|
|
191
169
|
)
|
192
170
|
|
193
171
|
def get_default_summarize_history(self) -> bool:
|
194
|
-
return
|
172
|
+
return (
|
173
|
+
self._default_summarize_history
|
174
|
+
if self._default_summarize_history is not None
|
175
|
+
else CFG.LLM_SUMMARIZE_HISTORY
|
176
|
+
)
|
195
177
|
|
196
178
|
def get_default_history_summarization_threshold(self) -> int:
|
197
|
-
return
|
179
|
+
return (
|
180
|
+
self._default_history_summarization_threshold
|
181
|
+
if self._default_history_summarization_threshold is not None
|
182
|
+
else CFG.LLM_HISTORY_SUMMARIZATION_THRESHOLD
|
183
|
+
)
|
198
184
|
|
199
185
|
def get_default_enrich_context(self) -> bool:
|
200
|
-
return
|
186
|
+
return (
|
187
|
+
self._default_enrich_context
|
188
|
+
if self._default_enrich_context is not None
|
189
|
+
else CFG.LLM_ENRICH_CONTEXT
|
190
|
+
)
|
201
191
|
|
202
192
|
def get_default_context_enrichment_threshold(self) -> int:
|
203
|
-
return
|
193
|
+
return (
|
194
|
+
self._default_context_enrichment_threshold
|
195
|
+
if self._default_context_enrichment_threshold is not None
|
196
|
+
else CFG.LLM_CONTEXT_ENRICHMENT_THRESHOLD
|
197
|
+
)
|
204
198
|
|
205
199
|
def set_default_persona(self, persona: str):
|
206
200
|
self._default_persona = persona
|
zrb/runner/cli.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import sys
|
2
2
|
from typing import Any
|
3
3
|
|
4
|
-
from zrb.config import
|
4
|
+
from zrb.config import CFG
|
5
5
|
from zrb.context.any_context import AnyContext
|
6
6
|
from zrb.context.shared_context import SharedContext
|
7
7
|
from zrb.group.any_group import AnyGroup
|
@@ -23,6 +23,13 @@ from zrb.util.string.conversion import double_quote
|
|
23
23
|
|
24
24
|
|
25
25
|
class Cli(Group):
|
26
|
+
|
27
|
+
@property
|
28
|
+
def banner(self) -> str:
|
29
|
+
if self._banner is None:
|
30
|
+
return CFG.BANNER
|
31
|
+
return self._banner
|
32
|
+
|
26
33
|
def run(self, args: list[str] = []):
|
27
34
|
kwargs, args = self._extract_kwargs_from_args(args)
|
28
35
|
node, node_path, args = extract_node_from_args(self, args)
|
@@ -147,14 +154,14 @@ class Cli(Group):
|
|
147
154
|
return kwargs, residual_args
|
148
155
|
|
149
156
|
|
150
|
-
cli = Cli(name="zrb", description="Your Automation Powerhouse"
|
157
|
+
cli = Cli(name="zrb", description="Your Automation Powerhouse")
|
151
158
|
|
152
159
|
|
153
160
|
@make_task(
|
154
161
|
name="version", description="🌟 Get current Zrb version", retries=0, group=cli
|
155
162
|
)
|
156
163
|
def get_version(_: AnyContext):
|
157
|
-
return VERSION
|
164
|
+
return CFG.VERSION
|
158
165
|
|
159
166
|
|
160
167
|
server_group = cli.add_group(
|
@@ -174,5 +181,7 @@ async def start_server(_: AnyContext):
|
|
174
181
|
from uvicorn import Config, Server
|
175
182
|
|
176
183
|
app = create_web_app(cli, web_config, session_state_logger)
|
177
|
-
server = Server(
|
184
|
+
server = Server(
|
185
|
+
Config(app=app, host="0.0.0.0", port=CFG.WEB_HTTP_PORT, loop="asyncio")
|
186
|
+
)
|
178
187
|
await server.serve()
|
zrb/runner/web_app.py
CHANGED
@@ -2,7 +2,7 @@ import asyncio
|
|
2
2
|
import sys
|
3
3
|
from typing import TYPE_CHECKING
|
4
4
|
|
5
|
-
from zrb.config import
|
5
|
+
from zrb.config import CFG
|
6
6
|
from zrb.group.any_group import AnyGroup
|
7
7
|
from zrb.runner.web_config.config import WebConfig
|
8
8
|
from zrb.runner.web_route.docs_route import serve_docs
|
@@ -37,7 +37,7 @@ def create_web_app(
|
|
37
37
|
|
38
38
|
@asynccontextmanager
|
39
39
|
async def lifespan(app: FastAPI):
|
40
|
-
for line in BANNER.split("\n") + [
|
40
|
+
for line in CFG.BANNER.split("\n") + [
|
41
41
|
f"Zrb Server running on http://localhost:{web_config.port}"
|
42
42
|
]:
|
43
43
|
print(line, file=sys.stderr)
|
@@ -48,7 +48,7 @@ def create_web_app(
|
|
48
48
|
|
49
49
|
app = FastAPI(
|
50
50
|
title="Zrb",
|
51
|
-
version=VERSION,
|
51
|
+
version=CFG.VERSION,
|
52
52
|
summary="Your Automation Powerhouse",
|
53
53
|
lifespan=lifespan,
|
54
54
|
docs_url=None,
|
@@ -1,26 +1,15 @@
|
|
1
|
-
from zrb.config import
|
2
|
-
WEB_ACCESS_TOKEN_COOKIE_NAME,
|
3
|
-
WEB_AUTH_ACCESS_TOKEN_EXPIRE_MINUTES,
|
4
|
-
WEB_AUTH_REFRESH_TOKEN_EXPIRE_MINUTES,
|
5
|
-
WEB_ENABLE_AUTH,
|
6
|
-
WEB_GUEST_USERNAME,
|
7
|
-
WEB_HTTP_PORT,
|
8
|
-
WEB_REFRESH_TOKEN_COOKIE_NAME,
|
9
|
-
WEB_SECRET_KEY,
|
10
|
-
WEB_SUPER_ADMIN_PASSWORD,
|
11
|
-
WEB_SUPER_ADMIN_USERNAME,
|
12
|
-
)
|
1
|
+
from zrb.config import CFG
|
13
2
|
from zrb.runner.web_config.config import WebConfig
|
14
3
|
|
15
4
|
web_config = WebConfig(
|
16
|
-
port=WEB_HTTP_PORT,
|
17
|
-
secret_key=WEB_SECRET_KEY,
|
18
|
-
access_token_expire_minutes=WEB_AUTH_ACCESS_TOKEN_EXPIRE_MINUTES,
|
19
|
-
refresh_token_expire_minutes=WEB_AUTH_REFRESH_TOKEN_EXPIRE_MINUTES,
|
20
|
-
access_token_cookie_name=WEB_ACCESS_TOKEN_COOKIE_NAME,
|
21
|
-
refresh_token_cookie_name=WEB_REFRESH_TOKEN_COOKIE_NAME,
|
22
|
-
enable_auth=WEB_ENABLE_AUTH,
|
23
|
-
super_admin_username=WEB_SUPER_ADMIN_USERNAME,
|
24
|
-
super_admin_password=WEB_SUPER_ADMIN_PASSWORD,
|
25
|
-
guest_username=WEB_GUEST_USERNAME,
|
5
|
+
port=CFG.WEB_HTTP_PORT,
|
6
|
+
secret_key=CFG.WEB_SECRET_KEY,
|
7
|
+
access_token_expire_minutes=CFG.WEB_AUTH_ACCESS_TOKEN_EXPIRE_MINUTES,
|
8
|
+
refresh_token_expire_minutes=CFG.WEB_AUTH_REFRESH_TOKEN_EXPIRE_MINUTES,
|
9
|
+
access_token_cookie_name=CFG.WEB_ACCESS_TOKEN_COOKIE_NAME,
|
10
|
+
refresh_token_cookie_name=CFG.WEB_REFRESH_TOKEN_COOKIE_NAME,
|
11
|
+
enable_auth=CFG.WEB_ENABLE_AUTH,
|
12
|
+
super_admin_username=CFG.WEB_SUPER_ADMIN_USERNAME,
|
13
|
+
super_admin_password=CFG.WEB_SUPER_ADMIN_PASSWORD,
|
14
|
+
guest_username=CFG.WEB_GUEST_USERNAME,
|
26
15
|
)
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import os
|
2
2
|
|
3
|
+
from zrb.config import CFG
|
3
4
|
from zrb.group.any_group import AnyGroup
|
4
5
|
from zrb.runner.web_schema.user import User
|
5
6
|
from zrb.runner.web_util.html import get_html_auth_link
|
@@ -11,17 +12,26 @@ def show_error_page(user: User, root_group: AnyGroup, status_code: int, message:
|
|
11
12
|
from fastapi.responses import HTMLResponse
|
12
13
|
|
13
14
|
_DIR = os.path.dirname(__file__)
|
15
|
+
_GLOBAL_TEMPLATE = read_file(
|
16
|
+
os.path.join(os.path.dirname(_DIR), "static", "global_template.html")
|
17
|
+
)
|
14
18
|
_VIEW_TEMPLATE = read_file(os.path.join(_DIR, "view.html"))
|
15
19
|
auth_link = get_html_auth_link(user)
|
16
20
|
return HTMLResponse(
|
17
21
|
fstring_format(
|
18
|
-
|
22
|
+
_GLOBAL_TEMPLATE,
|
19
23
|
{
|
20
|
-
"
|
21
|
-
"
|
22
|
-
|
23
|
-
|
24
|
-
|
24
|
+
"web_title": CFG.WEB_TITLE,
|
25
|
+
"content": fstring_format(
|
26
|
+
_VIEW_TEMPLATE,
|
27
|
+
{
|
28
|
+
"name": root_group.name,
|
29
|
+
"description": root_group.description,
|
30
|
+
"auth_link": auth_link,
|
31
|
+
"error_status_code": status_code,
|
32
|
+
"error_message": message,
|
33
|
+
},
|
34
|
+
),
|
25
35
|
},
|
26
36
|
),
|
27
37
|
status_code=status_code,
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import os
|
2
2
|
from typing import TYPE_CHECKING
|
3
3
|
|
4
|
+
from zrb.config import CFG
|
4
5
|
from zrb.group.any_group import AnyGroup
|
5
6
|
from zrb.runner.web_config.config import WebConfig
|
6
7
|
from zrb.runner.web_util.html import (
|
@@ -30,22 +31,37 @@ def serve_home_page(
|
|
30
31
|
@app.get("/ui", response_class=HTMLResponse, include_in_schema=False)
|
31
32
|
@app.get("/ui/", response_class=HTMLResponse, include_in_schema=False)
|
32
33
|
async def home_page_ui(request: Request) -> HTMLResponse:
|
33
|
-
|
34
34
|
_DIR = os.path.dirname(__file__)
|
35
|
+
_GLOBAL_TEMPLATE = read_file(
|
36
|
+
os.path.join(os.path.dirname(_DIR), "static", "global_template.html")
|
37
|
+
)
|
35
38
|
_VIEW_TEMPLATE = read_file(os.path.join(_DIR, "view.html"))
|
39
|
+
web_title = CFG.WEB_TITLE if CFG.WEB_TITLE.strip() != "" else root_group.name
|
40
|
+
web_jargon = (
|
41
|
+
CFG.WEB_JARGON if CFG.WEB_JARGON.strip() != "" else root_group.description
|
42
|
+
)
|
36
43
|
user = await get_user_from_request(web_config, request)
|
37
44
|
group_info = get_html_subgroup_info(user, "/ui/", root_group)
|
38
45
|
task_info = get_html_subtask_info(user, "/ui/", root_group)
|
39
46
|
auth_link = get_html_auth_link(user)
|
40
47
|
return HTMLResponse(
|
41
48
|
fstring_format(
|
42
|
-
|
49
|
+
_GLOBAL_TEMPLATE,
|
43
50
|
{
|
44
|
-
"
|
45
|
-
"
|
46
|
-
|
47
|
-
|
48
|
-
|
51
|
+
"web_title": web_title,
|
52
|
+
"content": fstring_format(
|
53
|
+
_VIEW_TEMPLATE,
|
54
|
+
{
|
55
|
+
"web_title": web_title,
|
56
|
+
"web_jargon": web_jargon,
|
57
|
+
"web_homepage_intro": CFG.WEB_HOMEPAGE_INTRO,
|
58
|
+
"group_info": group_info,
|
59
|
+
"task_info": task_info,
|
60
|
+
"name": root_group.name,
|
61
|
+
"description": root_group.description,
|
62
|
+
"auth_link": auth_link,
|
63
|
+
},
|
64
|
+
),
|
49
65
|
},
|
50
66
|
)
|
51
67
|
)
|
@@ -1,33 +1,19 @@
|
|
1
|
-
|
2
|
-
<
|
3
|
-
|
4
|
-
<
|
5
|
-
<
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
</ul>
|
21
|
-
<ul>
|
22
|
-
<li>{auth_link}</li>
|
23
|
-
</ul>
|
24
|
-
</nav>
|
25
|
-
</hgroup>
|
26
|
-
</header>
|
27
|
-
<main class="container">
|
28
|
-
{group_info}
|
29
|
-
{task_info}
|
30
|
-
</main>
|
31
|
-
</body>
|
32
|
-
<script src="/refresh-token.js"></script>
|
33
|
-
</html>
|
1
|
+
<header class="container">
|
2
|
+
<hgroup>
|
3
|
+
<h1>{web_title}</h1>
|
4
|
+
<p>{web_jargon}</p>
|
5
|
+
<nav>
|
6
|
+
<ul>
|
7
|
+
<li><a href="/docs">💻 API Documentation</a></li>
|
8
|
+
</ul>
|
9
|
+
<ul>
|
10
|
+
<li>{auth_link}</li>
|
11
|
+
</ul>
|
12
|
+
</nav>
|
13
|
+
</hgroup>
|
14
|
+
</header>
|
15
|
+
<main class="container">
|
16
|
+
<p>{web_homepage_intro}</p>
|
17
|
+
{group_info}
|
18
|
+
{task_info}
|
19
|
+
</main>
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import os
|
2
2
|
from typing import TYPE_CHECKING
|
3
3
|
|
4
|
+
from zrb.config import CFG
|
4
5
|
from zrb.group.any_group import AnyGroup
|
5
6
|
from zrb.runner.web_config.config import WebConfig
|
6
7
|
from zrb.runner.web_util.html import get_html_auth_link
|
@@ -24,16 +25,25 @@ def serve_login_page(
|
|
24
25
|
@app.get("/login", response_class=HTMLResponse, include_in_schema=False)
|
25
26
|
async def login(request: Request) -> HTMLResponse:
|
26
27
|
_DIR = os.path.dirname(__file__)
|
28
|
+
_GLOBAL_TEMPLATE = read_file(
|
29
|
+
os.path.join(os.path.dirname(_DIR), "static", "global_template.html")
|
30
|
+
)
|
27
31
|
_VIEW_TEMPLATE = read_file(os.path.join(_DIR, "view.html"))
|
28
32
|
user = await get_user_from_request(web_config, request)
|
29
33
|
auth_link = get_html_auth_link(user)
|
30
34
|
return HTMLResponse(
|
31
35
|
fstring_format(
|
32
|
-
|
36
|
+
_GLOBAL_TEMPLATE,
|
33
37
|
{
|
34
|
-
"
|
35
|
-
"
|
36
|
-
|
38
|
+
"web_title": CFG.WEB_TITLE,
|
39
|
+
"content": fstring_format(
|
40
|
+
_VIEW_TEMPLATE,
|
41
|
+
{
|
42
|
+
"name": root_group.name,
|
43
|
+
"description": root_group.description,
|
44
|
+
"auth_link": auth_link,
|
45
|
+
},
|
46
|
+
),
|
37
47
|
},
|
38
48
|
)
|
39
49
|
)
|
@@ -1,51 +1,33 @@
|
|
1
|
-
|
2
|
-
<
|
3
|
-
|
4
|
-
<
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
</
|
13
|
-
|
14
|
-
<
|
15
|
-
|
16
|
-
<
|
17
|
-
<
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
</
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
</label>
|
35
|
-
<label for="password">
|
36
|
-
Password
|
37
|
-
<input type="password" id="password" name="password" placeholder="Enter your password" required />
|
38
|
-
</label>
|
39
|
-
<div class="button-group">
|
40
|
-
<button class="primary">🔑 Login</button>
|
41
|
-
<button class="secondary" onclick="window.history.back()">🔙 Cancel</button>
|
42
|
-
</div>
|
43
|
-
</form>
|
44
|
-
<p id="error-message"></p>
|
45
|
-
</article>
|
46
|
-
</main>
|
47
|
-
<script src="/static/login/event.js"></script>
|
48
|
-
<script src="/refresh-token.js"></script>
|
49
|
-
</body>
|
50
|
-
|
51
|
-
</html>
|
1
|
+
<header class="container">
|
2
|
+
<hgroup>
|
3
|
+
<h1>{name}</h1>
|
4
|
+
<p>{description}</p>
|
5
|
+
<nav>
|
6
|
+
<ul>
|
7
|
+
<li><a href="/">🏠 Home</a></li>
|
8
|
+
<li><a href="/docs">💻 API Documentation</a></li>
|
9
|
+
</ul>
|
10
|
+
</nav>
|
11
|
+
</hgroup>
|
12
|
+
</header>
|
13
|
+
<main class="container">
|
14
|
+
<article>
|
15
|
+
<h1>Login</h1>
|
16
|
+
<form id="login-form" onsubmit="login(event)">
|
17
|
+
<label for="username">
|
18
|
+
Username
|
19
|
+
<input type="text" id="username" name="username" placeholder="Enter your username" required />
|
20
|
+
</label>
|
21
|
+
<label for="password">
|
22
|
+
Password
|
23
|
+
<input type="password" id="password" name="password" placeholder="Enter your password" required />
|
24
|
+
</label>
|
25
|
+
<div class="button-group">
|
26
|
+
<button class="primary">🔑 Login</button>
|
27
|
+
<button class="secondary" onclick="window.history.back()">🔙 Cancel</button>
|
28
|
+
</div>
|
29
|
+
</form>
|
30
|
+
<p id="error-message"></p>
|
31
|
+
</article>
|
32
|
+
</main>
|
33
|
+
<script src="/static/login/event.js"></script>
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import os
|
2
2
|
from typing import TYPE_CHECKING
|
3
3
|
|
4
|
+
from zrb.config import CFG
|
4
5
|
from zrb.group.any_group import AnyGroup
|
5
6
|
from zrb.runner.web_config.config import WebConfig
|
6
7
|
from zrb.runner.web_util.html import get_html_auth_link
|
@@ -24,17 +25,26 @@ def serve_logout_page(
|
|
24
25
|
@app.get("/logout", response_class=HTMLResponse, include_in_schema=False)
|
25
26
|
async def logout(request: Request) -> HTMLResponse:
|
26
27
|
_DIR = os.path.dirname(__file__)
|
28
|
+
_GLOBAL_TEMPLATE = read_file(
|
29
|
+
os.path.join(os.path.dirname(_DIR), "static", "global_template.html")
|
30
|
+
)
|
27
31
|
_VIEW_TEMPLATE = read_file(os.path.join(_DIR, "view.html"))
|
28
32
|
user = await get_user_from_request(web_config, request)
|
29
33
|
auth_link = get_html_auth_link(user)
|
30
34
|
return HTMLResponse(
|
31
35
|
fstring_format(
|
32
|
-
|
36
|
+
_GLOBAL_TEMPLATE,
|
33
37
|
{
|
34
|
-
"
|
35
|
-
"
|
36
|
-
|
37
|
-
|
38
|
+
"web_title": CFG.WEB_TITLE,
|
39
|
+
"content": fstring_format(
|
40
|
+
_VIEW_TEMPLATE,
|
41
|
+
{
|
42
|
+
"name": root_group.name,
|
43
|
+
"description": root_group.description,
|
44
|
+
"auth_link": auth_link,
|
45
|
+
"user": user,
|
46
|
+
},
|
47
|
+
),
|
38
48
|
},
|
39
49
|
)
|
40
50
|
)
|