diff --git a/core/embedded_db.py b/core/embedded_db.py index ec126ef..ba76cdc 100644 --- a/core/embedded_db.py +++ b/core/embedded_db.py @@ -71,6 +71,19 @@ class EmbeddedGraphDB: cursor.execute("CREATE INDEX IF NOT EXISTS idx_relation_type ON relations(relation_type)") cursor.execute("CREATE INDEX IF NOT EXISTS idx_relation_status ON relations(status)") + # 创建聊天记录表 + cursor.execute(""" + CREATE TABLE IF NOT EXISTS chat_records ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + role TEXT NOT NULL, + content TEXT NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) + """) + + # 创建聊天记录索引 + cursor.execute("CREATE INDEX IF NOT EXISTS idx_chat_created ON chat_records(created_at)") + self.conn.commit() def ensure_constraints(self): @@ -394,6 +407,44 @@ class EmbeddedGraphDB: "message": f"删除了 {deleted} 条关系" } + def save_chat_records(self, messages: list) -> Dict: + """保存聊天记录到数据库""" + cursor = self.conn.cursor() + + saved = 0 + for msg in messages: + role = msg.get("role") + content = msg.get("content") + if role and content: + cursor.execute( + "INSERT INTO chat_records (role, content) VALUES (?, ?)", + (role, content) + ) + saved += 1 + + self.conn.commit() + + cursor.execute(""" + DELETE FROM chat_records + WHERE id NOT IN ( + SELECT id FROM chat_records + ORDER BY id DESC + LIMIT 500 + ) + """) + self.conn.commit() + + return {"saved": saved} + + def get_chat_records(self, limit: int = 500) -> list: + """从数据库获取聊天记录""" + cursor = self.conn.cursor() + cursor.execute(""" + SELECT role, content FROM chat_records + ORDER BY id ASC LIMIT ? + """, (limit,)) + return [{"role": row[0], "content": row[1]} for row in cursor.fetchall()] + def close(self): """关闭数据库连接""" if self.conn: diff --git a/core/server.py b/core/server.py index c72cfaa..e5bd446 100644 --- a/core/server.py +++ b/core/server.py @@ -15,10 +15,8 @@ class PacketType(Enum): PROCESS_MESSAGE = "process_message" EXECUTE_TOOL = "execute_tool" GET_STATUS = "get_status" - GET_CONFIG = "get_config" - SET_CONFIG = "set_config" - GET_TOOL_LIMITS = "get_tool_limits" - SET_TOOL_LIMITS = "set_tool_limits" + GET_SETTINGS = "get_settings" # 合并:获取 api_config + tool_limits + SET_SETTINGS = "set_settings" # 合并:设置 api_config + tool_limits GET_HISTORY = "get_history" SAVE_HISTORY = "save_history" SHUTDOWN = "shutdown" @@ -160,14 +158,10 @@ class BackendServer: response_body = self._handle_execute_tool(packet.body) elif packet.type == PacketType.GET_STATUS: response_body = self._handle_get_status() - elif packet.type == PacketType.GET_CONFIG: - response_body = self._handle_get_config() - elif packet.type == PacketType.SET_CONFIG: - response_body = self._handle_set_config(packet.body) - elif packet.type == PacketType.GET_TOOL_LIMITS: - response_body = self._handle_get_tool_limits() - elif packet.type == PacketType.SET_TOOL_LIMITS: - response_body = self._handle_set_tool_limits(packet.body) + elif packet.type == PacketType.GET_SETTINGS: + response_body = self._handle_get_settings() + elif packet.type == PacketType.SET_SETTINGS: + response_body = self._handle_set_settings(packet.body) elif packet.type == PacketType.GET_HISTORY: response_body = self._handle_get_history() elif packet.type == PacketType.SAVE_HISTORY: @@ -197,6 +191,8 @@ class BackendServer: if not self._client: return {"success": False, "error": "API Key 未配置", "content": "请先配置 API Key"} + self._graph.save_chat_records([{"role": "user", "content": user_input}]) + self._tool_limiter.reset() messages_history = [{"role": "user", "content": user_input}] @@ -281,6 +277,8 @@ class BackendServer: content += f"\n\n部分工具调用被限制:\n{rejected_info}" content += f"\n\n工具调用统计:\n{self._tool_limiter.get_summary()}" + self._graph.save_chat_records([{"role": "assistant", "content": content}]) + return { "success": True, "content": content, @@ -309,45 +307,45 @@ class BackendServer: "client_initialized": self._client is not None } - def _handle_get_config(self) -> Dict: - return self._config.copy() + def _handle_get_settings(self) -> Dict: + return { + "api_config": self._config.copy(), + "tool_limits": self._tool_limits.copy() + } - def _handle_set_config(self, body: Dict) -> Dict: - api_key = body.get("api_key", "") - base_url = body.get("base_url", "https://api.deepseek.com") - model = body.get("model", "deepseek-chat") + def _handle_set_settings(self, body: Dict) -> Dict: + api_config = body.get("api_config", {}) + tool_limits = body.get("tool_limits", {}) + + api_key = api_config.get("api_key", "") + base_url = api_config.get("base_url", "https://api.deepseek.com") + model = api_config.get("model", "deepseek-chat") self.update_config(api_key, base_url, model) - self._save_config() - return {"status": "config_updated"} - - def _handle_get_tool_limits(self) -> Dict: - return self._tool_limits.copy() - - def _handle_set_tool_limits(self, body: Dict) -> Dict: + limits_keys = [ "persona_query_max", "persona_update_max", "task_query_max", "task_update_max", "memory_query_max", "memory_update_max" ] for key in limits_keys: - if key in body: - value = int(body[key]) + if key in tool_limits: + value = int(tool_limits[key]) if value < 1: return {"success": False, "error": f"{key} must be >= 1, got {value}"} self._tool_limits[key] = value self._tool_limiter = self._create_tool_limiter() - self._save_config() - return {"status": "tool_limits_updated", "limits": self._tool_limits.copy()} + return {"status": "settings_updated"} def _handle_get_history(self) -> Dict: - return {"history": self._message_history} + history = self._graph.get_chat_records(limit=500) + return {"history": history} def _handle_save_history(self, body: Dict) -> Dict: messages = body.get("messages", []) - self._message_history = messages + result = self._graph.save_chat_records(messages) return {"status": "history_saved"} def _send_response(self, request_id: str, response: PacketResponse) -> None: diff --git a/docs/en/api.md b/docs/en/api.md index 09d2ed6..35b6102 100644 --- a/docs/en/api.md +++ b/docs/en/api.md @@ -25,10 +25,8 @@ class PacketType(Enum): PROCESS_MESSAGE = "process_message" # Process message EXECUTE_TOOL = "execute_tool" # Execute tool GET_STATUS = "get_status" # Get status - GET_CONFIG = "get_config" # Get config - SET_CONFIG = "set_config" # Set config - GET_TOOL_LIMITS = "get_tool_limits" # Get tool limits - SET_TOOL_LIMITS = "set_tool_limits" # Set tool limits + GET_SETTINGS = "get_settings" # Get all settings (api_config + tool_limits) + SET_SETTINGS = "set_settings" # Set all settings (api_config + tool_limits) GET_HISTORY = "get_history" # Get history SAVE_HISTORY = "save_history" # Save history SHUTDOWN = "shutdown" # Shutdown service @@ -160,9 +158,9 @@ body = {} # No parameters --- -### 4. GET_CONFIG - Get Config +### 4. GET_SETTINGS - Get All Settings -Get current API configuration. +Get current API config and tool limits (all at once). **Request parameters:** ```python @@ -172,103 +170,82 @@ body = {} # No parameters **Response data:** ```python { - "api_key": str, # API Key - "base_url": str, # API Base URL - "model": str # Model name + "api_config": { + "api_key": str, # API Key + "base_url": str, # API Base URL + "model": str # Model name + }, + "tool_limits": { + "persona_query_max": int, # Persona graph query limit + "persona_update_max": int, # Persona graph update limit + "task_query_max": int, # Working memory query limit + "task_update_max": int, # Working memory update limit + "memory_query_max": int, # General memory query limit + "memory_update_max": int # General memory update limit + } } ``` +**Example:** +```python +result = client.get_settings() +api_config = result["data"]["api_config"] +tool_limits = result["data"]["tool_limits"] +``` + --- -### 5. SET_CONFIG - Set Config +### 5. SET_SETTINGS - Set All Settings -Update API configuration (API Key and Base URL). +Update API config and tool limits (all at once). **Request parameters:** ```python body = { - "api_key": str, # API Key - "base_url": str, # API Base URL (default: https://api.deepseek.com) - "model": str # Model name (default: deepseek-chat) + "api_config": { + "api_key": str, # API Key + "base_url": str, # API Base URL (default: https://api.deepseek.com) + "model": str # Model name (default: deepseek-chat) + }, + "tool_limits": { + "persona_query_max": int, # Persona query limit (≥1) + "persona_update_max": int, # Persona update limit (≥1) + "task_query_max": int, # Working memory query limit (≥1) + "task_update_max": int, # Working memory update limit (≥1) + "memory_query_max": int, # General memory query limit (≥1) + "memory_update_max": int # General memory update limit (≥1) + } } ``` **Response data:** ```python { - "status": "config_updated" -} -``` - ---- - -### 6. GET_TOOL_LIMITS - Get Tool Limits - -Get current AI reasoning tool call limits. - -**Request Parameters:** -```python -body = {} # No parameters -``` - -**Response Data:** -```python -{ - "persona_query_max": int, # Persona graph query limit - "persona_update_max": int, # Persona graph update limit - "task_query_max": int, # Working memory query limit - "task_update_max": int, # Working memory update limit - "memory_query_max": int, # General memory query limit - "memory_update_max": int # General memory update limit + "status": "settings_updated" } ``` **Example:** ```python -result = client.get_tool_limits() -print(result["data"]["persona_query_max"]) # 1 -``` - ---- - -### 7. SET_TOOL_LIMITS - Set Tool Limits - -Set AI reasoning tool call limits. - -**Request Parameters:** -```python -body = { - "persona_query_max": int, # Persona query limit (≥1) - "persona_update_max": int, # Persona update limit (≥1) - "task_query_max": int, # Working memory query limit (≥1) - "task_update_max": int, # Working memory update limit (≥1) - "memory_query_max": int, # General memory query limit (≥1) - "memory_update_max": int # General memory update limit (≥1) -} -``` - -**Response Data:** -```python -{ - "status": "tool_limits_updated", - "limits": {...} # Updated limits -} -``` - -**Example:** -```python -result = client.update_tool_limits( - persona_query_max=2, - task_query_max=5, - memory_query_max=30 +result = client.update_settings( + api_config={ + "api_key": "sk-xxxxx", + "base_url": "https://api.deepseek.com", + "model": "deepseek-chat" + }, + tool_limits={ + "persona_query_max": 2, + "task_query_max": 5, + "memory_query_max": 30 + } ) ``` --- -### 8. GET_HISTORY - Get Message History +### 6. GET_HISTORY - Get Message History -Get saved message history. +Get saved message history (from database, for UI display only, not used in model inference). **Request parameters:** ```python @@ -278,20 +255,25 @@ body = {} # No parameters **Response data:** ```python { - "history": list # Message history list + "history": list # Message history list [{"role": "user/assistant", "content": "..."}] } ``` +**Notes:** +- Message history is stored in database `chat_records` table +- Returns up to 500 most recent records +- History messages are only for UI display, not used in model inference + --- ### 7. SAVE_HISTORY - Save Message History -Save message history to memory. +Save message history to database (automatically saved after each message processing, user message and AI response saved separately). **Request parameters:** ```python body = { - "messages": list # Message list + "messages": list # Message list [{"role": "...", "content": "..."}] } ``` @@ -302,6 +284,12 @@ body = { } ``` +**Notes:** +- Messages are automatically saved to database `chat_records` table +- System automatically keeps only 500 most recent records, older records are deleted +- Each call to `PROCESS_MESSAGE` will automatically save user message and AI response +``` + --- ### 8. SHUTDOWN - Shutdown Service @@ -403,7 +391,10 @@ def send_message(): @app.route("/config", methods=["POST"]) def update_config(): data = request.json - result = client.update_config(data["api_key"], data.get("base_url")) + result = client.update_settings( + api_config=data.get("api_config", {}), + tool_limits=data.get("tool_limits", {}) + ) return jsonify(result) @app.route("/status", methods=["GET"]) @@ -434,8 +425,11 @@ async def handler(websocket): if msg_type == "message": result = client.process_message(data["content"]) - elif msg_type == "config": - result = client.update_config(data["api_key"], data.get("base_url")) + elif msg_type == "settings": + result = client.update_settings( + api_config=data.get("api_config", {}), + tool_limits=data.get("tool_limits", {}) + ) elif msg_type == "status": result = client.get_status() else: diff --git a/docs/zh/api.md b/docs/zh/api.md index fb8c7a3..e017dad 100644 --- a/docs/zh/api.md +++ b/docs/zh/api.md @@ -25,10 +25,8 @@ class PacketType(Enum): PROCESS_MESSAGE = "process_message" # 处理消息 EXECUTE_TOOL = "execute_tool" # 执行工具 GET_STATUS = "get_status" # 获取状态 - GET_CONFIG = "get_config" # 获取配置 - SET_CONFIG = "set_config" # 设置配置 - GET_TOOL_LIMITS = "get_tool_limits" # 获取工具限制 - SET_TOOL_LIMITS = "set_tool_limits" # 设置工具限制 + GET_SETTINGS = "get_settings" # 获取完整配置(api_config + tool_limits) + SET_SETTINGS = "set_settings" # 设置完整配置(api_config + tool_limits) GET_HISTORY = "get_history" # 获取历史 SAVE_HISTORY = "save_history" # 保存历史 SHUTDOWN = "shutdown" # 关闭服务 @@ -166,9 +164,9 @@ print(status["data"]["running"]) # True --- -### 4. GET_CONFIG - 获取配置 +### 4. GET_SETTINGS - 获取完整配置 -获取当前 API 配置。 +获取当前 API 配置和工具限制(一次获取全部)。 **请求参数:** ```python @@ -178,48 +176,82 @@ body = {} # 无参数 **响应数据:** ```python { - "api_key": str, # API Key - "base_url": str, # API Base URL - "model": str # 模型名称 + "api_config": { + "api_key": str, # API Key + "base_url": str, # API Base URL + "model": str # 模型名称 + }, + "tool_limits": { + "persona_query_max": int, # 人设图查询上限 + "persona_update_max": int, # 人设图修改上限 + "task_query_max": int, # 工作记忆查询上限 + "task_update_max": int, # 工作记忆修改上限 + "memory_query_max": int, # 一般记忆查询上限 + "memory_update_max": int # 一般记忆修改上限 + } } ``` +**示例:** +```python +result = client.get_settings() +api_config = result["data"]["api_config"] +tool_limits = result["data"]["tool_limits"] +``` + --- -### 5. SET_CONFIG - 设置配置 +### 5. SET_SETTINGS - 设置完整配置 -更新 API 配置(API Key 和 Base URL)。 +更新 API 配置和工具限制(一次设置全部)。 **请求参数:** ```python body = { - "api_key": str, # API Key - "base_url": str, # API Base URL (默认: https://api.deepseek.com) - "model": str # 模型名称 (默认: deepseek-chat) + "api_config": { + "api_key": str, # API Key + "base_url": str, # API Base URL (默认: https://api.deepseek.com) + "model": str # 模型名称 (默认: deepseek-chat) + }, + "tool_limits": { + "persona_query_max": int, # 人设图查询上限 (≥1) + "persona_update_max": int, # 人设图修改上限 (≥1) + "task_query_max": int, # 工作记忆查询上限 (≥1) + "task_update_max": int, # 工作记忆修改上限 (≥1) + "memory_query_max": int, # 一般记忆查询上限 (≥1) + "memory_update_max": int # 一般记忆修改上限 (≥1) + } } ``` **响应数据:** ```python { - "status": "config_updated" + "status": "settings_updated" } ``` **示例:** ```python -result = client.update_config( - api_key="sk-xxxxx", - base_url="https://api.deepseek.com", - model="deepseek-chat" +result = client.update_settings( + api_config={ + "api_key": "sk-xxxxx", + "base_url": "https://api.deepseek.com", + "model": "deepseek-chat" + }, + tool_limits={ + "persona_query_max": 2, + "task_query_max": 5, + "memory_query_max": 30 + } ) ``` --- -### 6. GET_TOOL_LIMITS - 获取工具限制 +### 6. GET_HISTORY - 获取消息历史 -获取当前 AI 推理时的工具调用限制配置。 +获取保存的消息历史(从数据库读取,用于UI显示,不参与模型推理)。 **请求参数:** ```python @@ -229,84 +261,25 @@ body = {} # 无参数 **响应数据:** ```python { - "persona_query_max": int, # 人设图查询上限 - "persona_update_max": int, # 人设图修改上限 - "task_query_max": int, # 工作记忆查询上限 - "task_update_max": int, # 工作记忆修改上限 - "memory_query_max": int, # 一般记忆查询上限 - "memory_update_max": int # 一般记忆修改上限 + "history": list # 消息历史列表 [{"role": "user/assistant", "content": "..."}] } ``` -**示例:** -```python -result = client.get_tool_limits() -print(result["data"]["persona_query_max"]) # 1 -``` - ---- - -### 7. SET_TOOL_LIMITS - 设置工具限制 - -设置 AI 推理时的工具调用限制。 - -**请求参数:** -```python -body = { - "persona_query_max": int, # 人设图查询上限 (≥1) - "persona_update_max": int, # 人设图修改上限 (≥1) - "task_query_max": int, # 工作记忆查询上限 (≥1) - "task_update_max": int, # 工作记忆修改上限 (≥1) - "memory_query_max": int, # 一般记忆查询上限 (≥1) - "memory_update_max": int # 一般记忆修改上限 (≥1) -} -``` - -**响应数据:** -```python -{ - "status": "tool_limits_updated", - "limits": {...} # 更新后的限制 -} -``` - -**示例:** -```python -result = client.update_tool_limits( - persona_query_max=2, - task_query_max=5, - memory_query_max=30 -) -``` - ---- - -### 8. GET_HISTORY - 获取消息历史 - -获取保存的消息历史。 - -**请求参数:** -```python -body = {} # 无参数 -``` - -**响应数据:** -```python -{ - "history": list # 消息历史列表 -} -``` +**说明:** +- 消息历史存储在数据库 `chat_records` 表中 +- 最多返回最近 500 条记录 +- 历史消息仅用于 UI 显示,不参与模型推理 --- ### 7. SAVE_HISTORY - 保存消息历史 -保存消息历史到内存。 +保存消息历史到数据库(每次处理消息后自动保存,用户消息和AI回复分别保存)。 **请求参数:** ```python body = { - "messages": list # 消息列表 + "messages": list # 消息列表 [{"role": "...", "content": "..."}] } ``` @@ -317,6 +290,11 @@ body = { } ``` +**说明:** +- 消息自动保存到数据库 `chat_records` 表 +- 系统自动限制最多保留 500 条记录,超出后自动删除旧记录 +- 每次调用 `PROCESS_MESSAGE` 时,会自动保存用户消息和AI回复 + --- ### 8. SHUTDOWN - 关闭服务 @@ -418,7 +396,10 @@ def send_message(): @app.route("/config", methods=["POST"]) def update_config(): data = request.json - result = client.update_config(data["api_key"], data.get("base_url")) + result = client.update_settings( + api_config=data.get("api_config", {}), + tool_limits=data.get("tool_limits", {}) + ) return jsonify(result) @app.route("/status", methods=["GET"]) @@ -449,8 +430,11 @@ async def handler(websocket): if msg_type == "message": result = client.process_message(data["content"]) - elif msg_type == "config": - result = client.update_config(data["api_key"], data.get("base_url")) + elif msg_type == "settings": + result = client.update_settings( + api_config=data.get("api_config", {}), + tool_limits=data.get("tool_limits", {}) + ) elif msg_type == "status": result = client.get_status() else: diff --git a/tests/test_core/test_embedded_db.py b/tests/test_core/test_embedded_db.py index 5f0640e..511a1c8 100644 --- a/tests/test_core/test_embedded_db.py +++ b/tests/test_core/test_embedded_db.py @@ -160,3 +160,41 @@ def test_close_and_context_manager(): finally: if os.path.exists(db_path): os.unlink(db_path) + + +def test_save_and_get_chat_records(db): + """测试聊天记录保存和读取""" + messages = [ + {"role": "user", "content": "你好"}, + {"role": "assistant", "content": "你好,有什么可以帮你?"} + ] + + result = db.save_chat_records(messages) + assert result["saved"] == 2 + + history = db.get_chat_records() + assert len(history) == 2 + assert history[0]["role"] == "user" + assert history[0]["content"] == "你好" + assert history[1]["role"] == "assistant" + + +def test_chat_records_limit_500(db): + """测试聊天记录限制500条""" + for i in range(600): + db.save_chat_records([{"role": "user", "content": f"消息{i}"}]) + + history = db.get_chat_records() + assert len(history) == 500 + + +def test_get_chat_records_default_limit(db): + """测试默认limit参数""" + for i in range(100): + db.save_chat_records([{"role": "user", "content": f"msg{i}"}]) + + history_50 = db.get_chat_records(limit=50) + assert len(history_50) == 50 + + history_default = db.get_chat_records() + assert len(history_default) == 100 diff --git a/ui/app.py b/ui/app.py index e8e0691..5b27cf4 100644 --- a/ui/app.py +++ b/ui/app.py @@ -37,20 +37,21 @@ class GraphMemoryApp(App): initial_config = AppConfig() if self._backend_client: - config_result = self._backend_client.get_config() - config_data = config_result.get("data", {}) - initial_config.api_key = config_data.get("api_key", "") - initial_config.base_url = config_data.get("base_url", "https://api.deepseek.com") - initial_config.model = config_data.get("model", "deepseek-chat") + settings_result = self._backend_client.get_settings() + settings_data = settings_result.get("data", {}) - limits_result = self._backend_client.get_tool_limits() - limits_data = limits_result.get("data", {}) - initial_config.persona_query_max = limits_data.get("persona_query_max", 1) - initial_config.persona_update_max = limits_data.get("persona_update_max", 1) - initial_config.task_query_max = limits_data.get("task_query_max", 4) - initial_config.task_update_max = limits_data.get("task_update_max", 2) - initial_config.memory_query_max = limits_data.get("memory_query_max", 20) - initial_config.memory_update_max = limits_data.get("memory_update_max", 10) + api_config = settings_data.get("api_config", {}) + initial_config.api_key = api_config.get("api_key", "") + initial_config.base_url = api_config.get("base_url", "https://api.deepseek.com") + initial_config.model = api_config.get("model", "deepseek-chat") + + tool_limits = settings_data.get("tool_limits", {}) + initial_config.persona_query_max = tool_limits.get("persona_query_max", 1) + initial_config.persona_update_max = tool_limits.get("persona_update_max", 1) + initial_config.task_query_max = tool_limits.get("task_query_max", 4) + initial_config.task_update_max = tool_limits.get("task_update_max", 2) + initial_config.memory_query_max = tool_limits.get("memory_query_max", 20) + initial_config.memory_update_max = tool_limits.get("memory_update_max", 10) yield LeftPanel() yield RightPanel(config=initial_config) @@ -73,7 +74,16 @@ class GraphMemoryApp(App): self._api_configured = data.get("config", {}).get("api_key", "") != "" status_bar.set_api_status(self._api_configured) - from .widgets.message_history import MessageHistory + if self._api_configured: + result = self._backend_client.get_history() + if result.get("success"): + history_data = result.get("data", {}) + chat_history = history_data.get("history", []) + history = self.query_one(MessageHistory) + for msg in chat_history: + message = Message(role=msg["role"], content=msg["content"]) + history.add_message(message) + history = self.query_one(MessageHistory) welcome = Message( role="assistant", @@ -184,48 +194,62 @@ class GraphMemoryApp(App): self.notify("后端未初始化,无法保存配置", title="错误", severity="error") return - config = event.config - - if event.is_tool_limits: - asyncio.create_task(self._update_tool_limits_async(config)) - else: - asyncio.create_task(self._update_config_async(config)) + asyncio.create_task(self._update_settings_async(event.config)) - async def _update_config_async(self, config) -> None: - """异步更新配置""" + async def _update_settings_async(self, config) -> None: from .widgets.status_bar import StatusBar from .widgets.config_section import ConfigSection status_bar = self.query_one(StatusBar) - api_key = config.api_key - base_url = config.base_url - model = getattr(config, 'model', 'deepseek-chat') + api_config = { + "api_key": config.api_key, + "base_url": config.base_url, + "model": getattr(config, 'model', 'deepseek-chat') + } + + tool_limits = { + "persona_query_max": config.persona_query_max, + "persona_update_max": config.persona_update_max, + "task_query_max": config.task_query_max, + "task_update_max": config.task_update_max, + "memory_query_max": config.memory_query_max, + "memory_update_max": config.memory_update_max, + } 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, model=model) + lambda: self._backend_client.update_settings( + api_config=api_config, + tool_limits=tool_limits + ) ) if result.get("success"): - self._api_configured = bool(api_key) + self._api_configured = bool(config.api_key) status_bar.set_api_status(self._api_configured) - # 从后端重新获取配置并刷新 UI - config_result = await asyncio.get_event_loop().run_in_executor( + settings_result = await asyncio.get_event_loop().run_in_executor( None, - lambda: self._backend_client.get_config() + lambda: self._backend_client.get_settings() ) - config_data = config_result.get("data", {}) + settings_data = settings_result.get("data", {}) - # 刷新输入框 try: config_section = self.query_one(ConfigSection) + api_cfg = settings_data.get("api_config", {}) + tool_lmts = settings_data.get("tool_limits", {}) config_section.set_config(AppConfig( - api_key=config_data.get("api_key", ""), - base_url=config_data.get("base_url", "https://api.deepseek.com"), - model=config_data.get("model", "deepseek-chat") + api_key=api_cfg.get("api_key", ""), + base_url=api_cfg.get("base_url", "https://api.deepseek.com"), + model=api_cfg.get("model", "deepseek-chat"), + persona_query_max=tool_lmts.get("persona_query_max", 1), + persona_update_max=tool_lmts.get("persona_update_max", 1), + task_query_max=tool_lmts.get("task_query_max", 4), + task_update_max=tool_lmts.get("task_update_max", 2), + memory_query_max=tool_lmts.get("memory_query_max", 20), + memory_update_max=tool_lmts.get("memory_update_max", 10), )) except Exception: pass @@ -234,31 +258,5 @@ class GraphMemoryApp(App): else: error = result.get("error", "未知错误") self.notify(f"❌ 配置失败: {error}", title="配置失败", severity="error") - except Exception as e: - self.notify(f"❌ 配置异常: {str(e)}", title="配置失败", severity="error") - - async def _update_tool_limits_async(self, config) -> 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_tool_limits( - persona_query_max=config.persona_query_max, - persona_update_max=config.persona_update_max, - task_query_max=config.task_query_max, - task_update_max=config.task_update_max, - memory_query_max=config.memory_query_max, - memory_update_max=config.memory_update_max, - ) - ) - - if result.get("success"): - 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") \ No newline at end of file