mirror of
https://gitcode.com/JianFeeeee/TrulyMEM-TrueHumanMEM.git
synced 2026-10-03 16:04:06 +00:00
fix: multiple UI and API issues
- Fix tool calls format for DeepSeek API (add type field) - Fix config event handler name - Fix message history display (preserve all messages) - Fix right panel width and scrolling - Add async config update to prevent UI freeze - Add prompt caching with singleton pattern - Update build scripts with complete hidden imports
This commit is contained in:
78
ui/app.py
78
ui/app.py
@ -26,6 +26,7 @@ class GraphMemoryApp(App):
|
||||
super().__init__(**kwargs)
|
||||
self._backend_server = backend_server
|
||||
self._backend_client = BackendClient(backend_server) if backend_server else None
|
||||
self._api_configured = False
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
from .widgets.left_panel import LeftPanel
|
||||
@ -36,21 +37,26 @@ class GraphMemoryApp(App):
|
||||
yield StatusBar()
|
||||
|
||||
def on_mount(self) -> None:
|
||||
from .widgets.status_bar import StatusBar
|
||||
status_bar = self.query_one(StatusBar)
|
||||
|
||||
if not self._backend_server:
|
||||
from .widgets.message_history import MessageHistory
|
||||
history = self.query_one(MessageHistory)
|
||||
error = Message(role="assistant", content="后端未初始化")
|
||||
history.add_message(error)
|
||||
status_bar.set_api_status(False)
|
||||
return
|
||||
|
||||
status = self._backend_client.get_status()
|
||||
api_configured = status.get("config", {}).get("api_key", "") != ""
|
||||
self._api_configured = status.get("config", {}).get("api_key", "") != ""
|
||||
status_bar.set_api_status(self._api_configured)
|
||||
|
||||
from .widgets.message_history import MessageHistory
|
||||
history = self.query_one(MessageHistory)
|
||||
welcome = Message(
|
||||
role="assistant",
|
||||
content=f"系统就绪\nAPI Key: {'已配置' if api_configured else '未配置'}\n\n输入消息开始对话"
|
||||
content=f"系统就绪\nAPI Key: {'已配置' if self._api_configured else '未配置'}\n\n输入消息开始对话"
|
||||
)
|
||||
history.add_message(welcome)
|
||||
|
||||
@ -78,48 +84,82 @@ class GraphMemoryApp(App):
|
||||
|
||||
def on_input_box_send_message(self, event) -> None:
|
||||
if not self._backend_client:
|
||||
self.notify("后端未初始化", title="错误", severity="error")
|
||||
return
|
||||
|
||||
if not self._api_configured:
|
||||
self.notify("请先配置 API Key (按 F2 打开侧边栏)", title="提示", severity="warning")
|
||||
return
|
||||
|
||||
user_input = event.content
|
||||
from .widgets.message_history import MessageHistory
|
||||
from .widgets.status_bar import StatusBar
|
||||
|
||||
history = self.query_one(MessageHistory)
|
||||
status_bar = self.query_one(StatusBar)
|
||||
|
||||
history.add_message(Message(role="user", content=user_input))
|
||||
history.add_message(Message(role="assistant", content="处理中..."))
|
||||
history.add_message(Message(role="assistant", content="⏳ 正在处理..."))
|
||||
status_bar.set_processing(True)
|
||||
|
||||
asyncio.create_task(self._process(user_input))
|
||||
|
||||
async def _process(self, user_input: str) -> None:
|
||||
from .widgets.message_history import MessageHistory
|
||||
from .widgets.status_bar import StatusBar
|
||||
|
||||
history = self.query_one(MessageHistory)
|
||||
status_bar = self.query_one(StatusBar)
|
||||
|
||||
try:
|
||||
result = await asyncio.get_event_loop().run_in_executor(
|
||||
None,
|
||||
lambda: self._backend_client.send_message(user_input)
|
||||
)
|
||||
|
||||
from .widgets.message_history import MessageHistory
|
||||
history = self.query_one(MessageHistory)
|
||||
history.clear_messages()
|
||||
|
||||
history.add_message(Message(role="user", content=user_input))
|
||||
|
||||
# 更新"处理中"消息为实际回复
|
||||
if result.get("success"):
|
||||
content = result.get("content", "(无回复)")
|
||||
history.add_message(Message(role="assistant", content=content))
|
||||
history.update_latest_message(content)
|
||||
else:
|
||||
error = result.get("error", "未知错误")
|
||||
history.add_message(Message(role="assistant", content=f"错误: {error}"))
|
||||
history.update_latest_message(f"❌ 错误: {error}")
|
||||
|
||||
except Exception as e:
|
||||
from .widgets.message_history import MessageHistory
|
||||
history = self.query_one(MessageHistory)
|
||||
history.add_message(Message(role="assistant", content=f"错误: {str(e)}"))
|
||||
history.update_latest_message(f"❌ 异常: {str(e)}")
|
||||
finally:
|
||||
status_bar.set_processing(False)
|
||||
|
||||
def on_config_changed(self, event) -> None:
|
||||
def on_config_section_config_changed(self, event) -> None:
|
||||
"""处理配置变更事件"""
|
||||
if not self._backend_client:
|
||||
self.notify("后端未初始化,无法保存配置", title="错误", severity="error")
|
||||
return
|
||||
|
||||
api_key = event.api_key
|
||||
base_url = event.base_url
|
||||
config = event.config
|
||||
api_key = config.api_key
|
||||
base_url = config.base_url
|
||||
|
||||
result = self._backend_client.update_config(api_key=api_key, base_url=base_url)
|
||||
self.notify("配置已保存" if result.get("success") else "配置失败", title="配置")
|
||||
# 异步更新配置,避免阻塞UI
|
||||
asyncio.create_task(self._update_config_async(api_key, base_url))
|
||||
|
||||
async def _update_config_async(self, api_key: str, base_url: str) -> None:
|
||||
"""异步更新配置"""
|
||||
from .widgets.status_bar import StatusBar
|
||||
status_bar = self.query_one(StatusBar)
|
||||
|
||||
try:
|
||||
result = await asyncio.get_event_loop().run_in_executor(
|
||||
None,
|
||||
lambda: self._backend_client.update_config(api_key=api_key, base_url=base_url)
|
||||
)
|
||||
|
||||
if result.get("success"):
|
||||
self._api_configured = bool(api_key)
|
||||
status_bar.set_api_status(self._api_configured)
|
||||
self.notify("✅ 配置已保存并生效", title="配置成功", severity="information")
|
||||
else:
|
||||
error = result.get("error", "未知错误")
|
||||
self.notify(f"❌ 配置失败: {error}", title="配置失败", severity="error")
|
||||
except Exception as e:
|
||||
self.notify(f"❌ 配置异常: {str(e)}", title="配置失败", severity="error")
|
||||
@ -22,15 +22,14 @@ LeftPanel {
|
||||
}
|
||||
|
||||
RightPanel {
|
||||
width: 70;
|
||||
width: 35;
|
||||
dock: right;
|
||||
background: $panel;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
RightPanel ScrollableContainer {
|
||||
height: 1fr;
|
||||
overflow-y: auto;
|
||||
height: 100%;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
StatusBar {
|
||||
|
||||
@ -35,7 +35,7 @@ class RightPanel(Container):
|
||||
self.styles.width = 0
|
||||
self.styles.display = "none"
|
||||
else:
|
||||
self.styles.width = 70
|
||||
self.styles.width = 35
|
||||
self.styles.display = "block"
|
||||
|
||||
def is_collapsed(self) -> bool:
|
||||
|
||||
@ -15,8 +15,10 @@ class StatusBar(Static):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self._shortcuts = "F1:帮助 F2:侧边栏 F3:工具详情 F4:查询 F5:清屏 F6:退出"
|
||||
self._shortcuts = "F1:帮助 F2:侧边栏 F3:工具详情 F5:清屏 F6:退出"
|
||||
self._license_info = "本项目由jianf设计,以GPLv3形式开源"
|
||||
self._api_status = "未配置"
|
||||
self._processing = False
|
||||
|
||||
def on_mount(self) -> None:
|
||||
"""组件挂载时"""
|
||||
@ -24,4 +26,16 @@ class StatusBar(Static):
|
||||
|
||||
def _update_display(self) -> None:
|
||||
"""更新显示"""
|
||||
self.update(f"{self._license_info} | {self._shortcuts}")
|
||||
status_icon = "●" if self._api_status == "已配置" else "○"
|
||||
processing_indicator = " [处理中...]" if self._processing else ""
|
||||
self.update(f"{status_icon} API: {self._api_status}{processing_indicator} | {self._license_info} | {self._shortcuts}")
|
||||
|
||||
def set_api_status(self, configured: bool) -> None:
|
||||
"""设置API状态"""
|
||||
self._api_status = "已配置" if configured else "未配置"
|
||||
self._update_display()
|
||||
|
||||
def set_processing(self, processing: bool) -> None:
|
||||
"""设置处理状态"""
|
||||
self._processing = processing
|
||||
self._update_display()
|
||||
|
||||
Reference in New Issue
Block a user