zrb 1.5.16__py3-none-any.whl → 1.6.0__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 +65 -74
- 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 +10 -1
- zrb/task/llm/print_node.py +5 -6
- zrb/task/llm_task.py +1 -1
- zrb/util/git_subtree.py +1 -1
- {zrb-1.5.16.dist-info → zrb-1.6.0.dist-info}/METADATA +1 -1
- {zrb-1.5.16.dist-info → zrb-1.6.0.dist-info}/RECORD +45 -42
- zrb/builtin/llm/llm_chat.py +0 -124
- {zrb-1.5.16.dist-info → zrb-1.6.0.dist-info}/WHEEL +0 -0
- {zrb-1.5.16.dist-info → zrb-1.6.0.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.
|
@@ -65,72 +64,30 @@ class LLMConfig:
|
|
65
64
|
default_enrich_context: bool | None = None,
|
66
65
|
default_context_enrichment_threshold: int | None = None,
|
67
66
|
):
|
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
|
-
)
|
67
|
+
self._default_model_name = default_model_name
|
68
|
+
self._default_model_base_url = default_base_url
|
69
|
+
self._default_model_api_key = default_api_key
|
70
|
+
self._default_persona = default_persona
|
71
|
+
self._default_system_prompt = default_system_prompt
|
72
|
+
self._default_special_instruction_prompt = default_special_instruction_prompt
|
73
|
+
self._default_summarization_prompt = default_summarization_prompt
|
74
|
+
self._default_context_enrichment_prompt = default_context_enrichment_prompt
|
75
|
+
self._default_summarize_history = default_summarize_history
|
113
76
|
self._default_history_summarization_threshold = (
|
114
77
|
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
78
|
)
|
79
|
+
self._default_enrich_context = default_enrich_context
|
123
80
|
self._default_context_enrichment_threshold = (
|
124
81
|
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
82
|
)
|
128
83
|
self._default_provider = None
|
129
84
|
self._default_model = None
|
130
85
|
|
131
86
|
def _get_model_name(self) -> str | None:
|
132
87
|
return (
|
133
|
-
self._default_model_name
|
88
|
+
self._default_model_name
|
89
|
+
if self._default_model_name is not None
|
90
|
+
else CFG.LLM_MODEL
|
134
91
|
)
|
135
92
|
|
136
93
|
def get_default_model_provider(self) -> Provider | str:
|
@@ -146,35 +103,53 @@ class LLMConfig:
|
|
146
103
|
|
147
104
|
def get_default_system_prompt(self) -> str:
|
148
105
|
return (
|
149
|
-
|
150
|
-
if self._default_system_prompt is None
|
151
|
-
else
|
106
|
+
self._default_system_prompt
|
107
|
+
if self._default_system_prompt is not None
|
108
|
+
else (
|
109
|
+
CFG.LLM_SYSTEM_PROMPT
|
110
|
+
if CFG.LLM_SYSTEM_PROMPT is not None
|
111
|
+
else DEFAULT_SYSTEM_PROMPT
|
112
|
+
)
|
152
113
|
)
|
153
114
|
|
154
115
|
def get_default_persona(self) -> str:
|
155
116
|
return (
|
156
|
-
|
117
|
+
self._default_persona
|
118
|
+
if self._default_persona is not None
|
119
|
+
else (CFG.LLM_PERSONA if CFG.LLM_PERSONA is not None else DEFAULT_PERSONA)
|
157
120
|
)
|
158
121
|
|
159
122
|
def get_default_special_instruction_prompt(self) -> str:
|
160
123
|
return (
|
161
|
-
|
162
|
-
if self._default_special_instruction_prompt is None
|
163
|
-
else
|
124
|
+
self._default_special_instruction_prompt
|
125
|
+
if self._default_special_instruction_prompt is not None
|
126
|
+
else (
|
127
|
+
CFG.LLM_SPECIAL_INSTRUCTION_PROMPT
|
128
|
+
if CFG.LLM_SPECIAL_INSTRUCTION_PROMPT is not None
|
129
|
+
else DEFAULT_SPECIAL_INSTRUCTION_PROMPT
|
130
|
+
)
|
164
131
|
)
|
165
132
|
|
166
133
|
def get_default_summarization_prompt(self) -> str:
|
167
134
|
return (
|
168
|
-
|
169
|
-
if self._default_summarization_prompt is None
|
170
|
-
else
|
135
|
+
self._default_summarization_prompt
|
136
|
+
if self._default_summarization_prompt is not None
|
137
|
+
else (
|
138
|
+
CFG.LLM_SUMMARIZATION_PROMPT
|
139
|
+
if CFG.LLM_SUMMARIZATION_PROMPT is not None
|
140
|
+
else DEFAULT_SUMMARIZATION_PROMPT
|
141
|
+
)
|
171
142
|
)
|
172
143
|
|
173
144
|
def get_default_context_enrichment_prompt(self) -> str:
|
174
145
|
return (
|
175
|
-
|
176
|
-
if self._default_context_enrichment_prompt is None
|
177
|
-
else
|
146
|
+
self._default_context_enrichment_prompt
|
147
|
+
if self._default_context_enrichment_prompt is not None
|
148
|
+
else (
|
149
|
+
CFG.LLM_CONTEXT_ENRICHMENT_PROMPT
|
150
|
+
if CFG.LLM_CONTEXT_ENRICHMENT_PROMPT is not None
|
151
|
+
else DEFAULT_CONTEXT_ENRICHMENT_PROMPT
|
152
|
+
)
|
178
153
|
)
|
179
154
|
|
180
155
|
def get_default_model(self) -> Model | str | None:
|
@@ -191,16 +166,32 @@ class LLMConfig:
|
|
191
166
|
)
|
192
167
|
|
193
168
|
def get_default_summarize_history(self) -> bool:
|
194
|
-
return
|
169
|
+
return (
|
170
|
+
self._default_summarize_history
|
171
|
+
if self._default_summarize_history is not None
|
172
|
+
else CFG.LLM_SUMMARIZE_HISTORY
|
173
|
+
)
|
195
174
|
|
196
175
|
def get_default_history_summarization_threshold(self) -> int:
|
197
|
-
return
|
176
|
+
return (
|
177
|
+
self._default_history_summarization_threshold
|
178
|
+
if self._default_history_summarization_threshold is not None
|
179
|
+
else CFG.LLM_HISTORY_SUMMARIZATION_THRESHOLD
|
180
|
+
)
|
198
181
|
|
199
182
|
def get_default_enrich_context(self) -> bool:
|
200
|
-
return
|
183
|
+
return (
|
184
|
+
self._default_enrich_context
|
185
|
+
if self._default_enrich_context is not None
|
186
|
+
else CFG.LLM_ENRICH_CONTEXT
|
187
|
+
)
|
201
188
|
|
202
189
|
def get_default_context_enrichment_threshold(self) -> int:
|
203
|
-
return
|
190
|
+
return (
|
191
|
+
self._default_context_enrichment_threshold
|
192
|
+
if self._default_context_enrichment_threshold is not None
|
193
|
+
else CFG.LLM_CONTEXT_ENRICHMENT_THRESHOLD
|
194
|
+
)
|
204
195
|
|
205
196
|
def set_default_persona(self, persona: str):
|
206
197
|
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
|
)
|