Merge remote-tracking branch 'origin/test'
This commit is contained in:
@ -469,10 +469,15 @@ class BackendServer:
|
|||||||
base_url = api_config.get("base_url", self._config.get("base_url", "https://api.deepseek.com"))
|
base_url = api_config.get("base_url", self._config.get("base_url", "https://api.deepseek.com"))
|
||||||
model = api_config.get("model", self._config.get("model", "deepseek-v4-flash"))
|
model = api_config.get("model", self._config.get("model", "deepseek-v4-flash"))
|
||||||
self.update_config(api_key, base_url, model)
|
self.update_config(api_key, base_url, model)
|
||||||
# 通用配置字段(如 message_timeout)
|
# 通用配置字段(如 message_timeout, enable_web, enable_tui, web_port)
|
||||||
for key in ["message_timeout"]:
|
for key in ["message_timeout", "enable_web", "enable_tui", "web_port"]:
|
||||||
if key in api_config:
|
if key in api_config:
|
||||||
self._config[key] = int(api_config[key])
|
if key == "web_port":
|
||||||
|
self._config[key] = int(api_config[key])
|
||||||
|
elif key in ["enable_web", "enable_tui"]:
|
||||||
|
self._config[key] = bool(api_config[key])
|
||||||
|
else:
|
||||||
|
self._config[key] = int(api_config[key])
|
||||||
|
|
||||||
limits_keys = [
|
limits_keys = [
|
||||||
"persona_update_max",
|
"persona_update_max",
|
||||||
|
|||||||
14
ui/app.py
14
ui/app.py
@ -69,8 +69,9 @@ class GraphMemoryApp(App):
|
|||||||
from core.migrate import need_migration, is_migrated
|
from core.migrate import need_migration, is_migrated
|
||||||
|
|
||||||
# 检查是否需要登录
|
# 检查是否需要登录
|
||||||
migrated = is_migrated()
|
# 如果已迁移,需要登录验证用户
|
||||||
need_login = migrated or not need_migration()
|
# 如果需要迁移,显示迁移登录界面
|
||||||
|
need_login = is_migrated() or need_migration()
|
||||||
|
|
||||||
if need_login and not self.login_user:
|
if need_login and not self.login_user:
|
||||||
# 显示登录界面
|
# 显示登录界面
|
||||||
@ -84,6 +85,10 @@ class GraphMemoryApp(App):
|
|||||||
"""登录成功后调用"""
|
"""登录成功后调用"""
|
||||||
self.login_user = username
|
self.login_user = username
|
||||||
self.login_user_info = user_info
|
self.login_user_info = user_info
|
||||||
|
|
||||||
|
# 关闭登录界面
|
||||||
|
self.pop_screen()
|
||||||
|
|
||||||
# 更新 config section 的 admin 权限
|
# 更新 config section 的 admin 权限
|
||||||
from .widgets.config_section import ConfigSection
|
from .widgets.config_section import ConfigSection
|
||||||
try:
|
try:
|
||||||
@ -295,7 +300,10 @@ class GraphMemoryApp(App):
|
|||||||
api_config = {
|
api_config = {
|
||||||
"api_key": config.api_key,
|
"api_key": config.api_key,
|
||||||
"base_url": config.base_url,
|
"base_url": config.base_url,
|
||||||
"model": getattr(config, 'model', 'deepseek-v4-flash')
|
"model": getattr(config, 'model', 'deepseek-v4-flash'),
|
||||||
|
"enable_web": getattr(config, 'enable_web', False),
|
||||||
|
"enable_tui": getattr(config, 'enable_tui', True),
|
||||||
|
"web_port": getattr(config, 'web_port', 4096),
|
||||||
}
|
}
|
||||||
|
|
||||||
tool_limits = {
|
tool_limits = {
|
||||||
|
|||||||
@ -61,6 +61,45 @@ ConfigSection Input {
|
|||||||
color: $text;
|
color: $text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConfigSection Checkbox {
|
||||||
|
margin: 1 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Admin sections */
|
||||||
|
#admin-web-login-section,
|
||||||
|
#admin-web-service-section,
|
||||||
|
#admin-tui-service-section {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Login Screen */
|
||||||
|
#login_container,
|
||||||
|
#migration_container {
|
||||||
|
width: 60;
|
||||||
|
height: auto;
|
||||||
|
padding: 2;
|
||||||
|
background: $surface;
|
||||||
|
border: solid $primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
#login_title,
|
||||||
|
#migration_title {
|
||||||
|
color: $primary;
|
||||||
|
text-style: bold;
|
||||||
|
margin: 0 0 1 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#migration_subtitle {
|
||||||
|
color: $text-muted;
|
||||||
|
margin: 0 0 1 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#login_message,
|
||||||
|
#migration_message {
|
||||||
|
color: $warning;
|
||||||
|
margin: 1 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Other Components */
|
/* Other Components */
|
||||||
OperationLog {
|
OperationLog {
|
||||||
background: $surface-darken-1;
|
background: $surface-darken-1;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
"""配置区组件"""
|
"""配置区组件"""
|
||||||
|
|
||||||
from textual.containers import Vertical
|
from textual.containers import Vertical
|
||||||
from textual.widgets import Static, Input, Button
|
from textual.widgets import Static, Input, Button, Checkbox
|
||||||
from textual.app import ComposeResult
|
from textual.app import ComposeResult
|
||||||
from textual.message import Message
|
from textual.message import Message
|
||||||
from ..models.config import AppConfig
|
from ..models.config import AppConfig
|
||||||
@ -15,7 +15,7 @@ class ConfigSection(Vertical):
|
|||||||
self.is_tool_limits = is_tool_limits
|
self.is_tool_limits = is_tool_limits
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
def __init__(self, config: AppConfig | None = None, is_admin: bool = True, **kwargs):
|
def __init__(self, config: AppConfig | None = None, is_admin: bool = False, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self._config = config or AppConfig()
|
self._config = config or AppConfig()
|
||||||
self._is_admin = is_admin
|
self._is_admin = is_admin
|
||||||
@ -133,7 +133,6 @@ class ConfigSection(Vertical):
|
|||||||
ws_hint.can_focus = False
|
ws_hint.can_focus = False
|
||||||
yield ws_hint
|
yield ws_hint
|
||||||
|
|
||||||
from textual.widgets import Checkbox
|
|
||||||
yield Checkbox(
|
yield Checkbox(
|
||||||
"启用 Web 服务",
|
"启用 Web 服务",
|
||||||
value=self._config.enable_web,
|
value=self._config.enable_web,
|
||||||
@ -150,10 +149,30 @@ class ConfigSection(Vertical):
|
|||||||
type="integer"
|
type="integer"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 默认隐藏 admin 区域,等 login 后决定是否显示
|
sep4 = Static("", classes="config-sep")
|
||||||
self._apply_admin_visibility()
|
sep4.can_focus = False
|
||||||
|
yield sep4
|
||||||
|
|
||||||
|
# TUI 服务控制 — 仅 admin 可见
|
||||||
|
with Vertical(id="admin-tui-service-section"):
|
||||||
|
tui_title = Static("━━ TUI 服务 ━━", classes="config-title")
|
||||||
|
tui_title.can_focus = False
|
||||||
|
yield tui_title
|
||||||
|
|
||||||
|
tui_hint = Static("控制终端文本界面是否允许连接", classes="config-hint")
|
||||||
|
tui_hint.can_focus = False
|
||||||
|
yield tui_hint
|
||||||
|
|
||||||
|
yield Checkbox(
|
||||||
|
"启用 TUI 服务",
|
||||||
|
value=self._config.enable_tui,
|
||||||
|
id="enable-tui-checkbox"
|
||||||
|
)
|
||||||
|
|
||||||
def on_mount(self) -> None:
|
def on_mount(self) -> None:
|
||||||
|
# 应用管理员区域的可见性
|
||||||
|
self._apply_admin_visibility()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
api_key = self.query_one("#api-key-input", Input)
|
api_key = self.query_one("#api-key-input", Input)
|
||||||
model = self.query_one("#model-input", Input)
|
model = self.query_one("#model-input", Input)
|
||||||
@ -175,17 +194,30 @@ class ConfigSection(Vertical):
|
|||||||
web_user.tab_index = 7
|
web_user.tab_index = 7
|
||||||
web_pwd.tab_index = 8
|
web_pwd.tab_index = 8
|
||||||
|
|
||||||
from textual.widgets import Checkbox
|
|
||||||
web_port = self.query_one("#web-port-input", Input)
|
web_port = self.query_one("#web-port-input", Input)
|
||||||
try:
|
|
||||||
web_checkbox = self.query_one("#enable-web-checkbox", Checkbox)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
web_port.tab_index = 9
|
web_port.tab_index = 9
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def on_input_submitted(self, event: Input.Submitted) -> None:
|
def on_checkbox_changed(self, event: Checkbox.Changed) -> None:
|
||||||
|
"""处理复选框状态变化"""
|
||||||
|
try:
|
||||||
|
# Web 服务开关
|
||||||
|
if event.checkbox.id == "enable-web-checkbox":
|
||||||
|
self._update_config_from_ui()
|
||||||
|
# 发送配置更新消息
|
||||||
|
self.post_message(self.ConfigChanged(self._config, is_tool_limits=False))
|
||||||
|
|
||||||
|
# TUI 服务开关
|
||||||
|
elif event.checkbox.id == "enable-tui-checkbox":
|
||||||
|
self._update_config_from_ui()
|
||||||
|
# 发送配置更新消息
|
||||||
|
self.post_message(self.ConfigChanged(self._config, is_tool_limits=False))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _update_config_from_ui(self) -> None:
|
||||||
|
"""从UI组件更新配置对象"""
|
||||||
try:
|
try:
|
||||||
api_key_input = self.query_one("#api-key-input", Input)
|
api_key_input = self.query_one("#api-key-input", Input)
|
||||||
model_input = self.query_one("#model-input", Input)
|
model_input = self.query_one("#model-input", Input)
|
||||||
@ -199,9 +231,15 @@ class ConfigSection(Vertical):
|
|||||||
web_username = self.query_one("#web-username-input", Input)
|
web_username = self.query_one("#web-username-input", Input)
|
||||||
web_password = self.query_one("#web-password-input", Input)
|
web_password = self.query_one("#web-password-input", Input)
|
||||||
|
|
||||||
from textual.widgets import Checkbox
|
|
||||||
web_checkbox = self.query_one("#enable-web-checkbox", Checkbox)
|
web_checkbox = self.query_one("#enable-web-checkbox", Checkbox)
|
||||||
web_port_input = self.query_one("#web-port-input", Input)
|
web_port_input = self.query_one("#web-port-input", Input)
|
||||||
|
|
||||||
|
# TUI checkbox 可能不存在(非管理员)
|
||||||
|
tui_checkbox = None
|
||||||
|
try:
|
||||||
|
tui_checkbox = self.query_one("#enable-tui-checkbox", Checkbox)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
self._config = AppConfig(
|
self._config = AppConfig(
|
||||||
api_key=api_key_input.value,
|
api_key=api_key_input.value,
|
||||||
@ -215,7 +253,14 @@ class ConfigSection(Vertical):
|
|||||||
web_password=web_password.value,
|
web_password=web_password.value,
|
||||||
enable_web=web_checkbox.value,
|
enable_web=web_checkbox.value,
|
||||||
web_port=int(web_port_input.value) if web_port_input.value else 4096,
|
web_port=int(web_port_input.value) if web_port_input.value else 4096,
|
||||||
|
enable_tui=tui_checkbox.value if tui_checkbox else True,
|
||||||
)
|
)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_input_submitted(self, event: Input.Submitted) -> None:
|
||||||
|
try:
|
||||||
|
self._update_config_from_ui()
|
||||||
|
|
||||||
# 先发送 API 配置更新(is_tool_limits=False)
|
# 先发送 API 配置更新(is_tool_limits=False)
|
||||||
self.post_message(self.ConfigChanged(self._config, is_tool_limits=False))
|
self.post_message(self.ConfigChanged(self._config, is_tool_limits=False))
|
||||||
@ -241,6 +286,11 @@ class ConfigSection(Vertical):
|
|||||||
service_section.styles.display = "block" if self._is_admin else "none"
|
service_section.styles.display = "block" if self._is_admin else "none"
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
try:
|
||||||
|
tui_section = self.query_one("#admin-tui-service-section")
|
||||||
|
tui_section.styles.display = "block" if self._is_admin else "none"
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
def get_config(self) -> AppConfig:
|
def get_config(self) -> AppConfig:
|
||||||
return self._config
|
return self._config
|
||||||
@ -264,11 +314,16 @@ class ConfigSection(Vertical):
|
|||||||
self.query_one("#web-username-input", Input).value = config.web_username
|
self.query_one("#web-username-input", Input).value = config.web_username
|
||||||
self.query_one("#web-password-input", Input).value = config.web_password
|
self.query_one("#web-password-input", Input).value = config.web_password
|
||||||
|
|
||||||
from textual.widgets import Checkbox
|
|
||||||
try:
|
try:
|
||||||
self.query_one("#enable-web-checkbox", Checkbox).value = config.enable_web
|
self.query_one("#enable-web-checkbox", Checkbox).value = config.enable_web
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
self.query_one("#web-port-input", Input).value = str(config.web_port)
|
self.query_one("#web-port-input", Input).value = str(config.web_port)
|
||||||
|
|
||||||
|
# TUI checkbox
|
||||||
|
try:
|
||||||
|
self.query_one("#enable-tui-checkbox", Checkbox).value = config.enable_tui
|
||||||
|
except:
|
||||||
|
pass
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|||||||
Reference in New Issue
Block a user