diff --git a/build/build_linux.sh b/build/build_linux.sh deleted file mode 100755 index 9992439..0000000 --- a/build/build_linux.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/bin/bash -set -e - -echo "===== Building TrulyMEM for Linux =====" - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" -cd "$PROJECT_ROOT" - -echo "Project root: $PROJECT_ROOT" - -if ! command -v python3 &> /dev/null; then - echo "Error: python3 not found" - exit 1 -fi - -# 创建并激活虚拟环境 -VENV_DIR="$PROJECT_ROOT/.venv_build" - -echo "Creating virtual environment: $VENV_DIR" -python3 -m venv "$VENV_DIR" - -echo "Activating virtual environment..." -source "$VENV_DIR/bin/activate" - -echo "Upgrading pip in virtual environment..." -pip install --upgrade pip - -echo "Installing dependencies in virtual environment..." -pip install -r requirements.txt - -echo "Cleaning previous builds..." -rm -rf build/dist build/__pycache__ 2>/dev/null || true - -echo "Running PyInstaller..." -python -m PyInstaller trulymem_entry.py \ - --clean \ - --onefile \ - --console \ - --name TrulyMEM \ - --add-data "ui/styles:ui/styles" \ - --add-data "core/prompts/templates:core/prompts/templates" \ - --hidden-import textual \ - --hidden-import textual.app \ - --hidden-import textual.widgets \ - --hidden-import textual.css \ - --hidden-import openai \ - --hidden-import openai._client \ - --hidden-import neo4j \ - --hidden-import sqlite3 \ - --hidden-import core \ - --hidden-import core.embedded_db \ - --hidden-import core.graph_client \ - --hidden-import core.tool_executor \ - --hidden-import core.tool_limiter \ - --hidden-import core.tools \ - --hidden-import core.tools.memory_tools \ - --hidden-import core.prompts \ - --hidden-import core.prompts.prompt_manager \ - --hidden-import ui \ - --hidden-import ui.app \ - --hidden-import ui.models \ - --hidden-import ui.models.message \ - --hidden-import ui.models.config \ - --hidden-import ui.models.log_entry \ - --hidden-import ui.widgets \ - --hidden-import ui.handlers \ - --hidden-import ui.services \ - --hidden-import ui.services.config_manager \ - --hidden-import ui.services.config_service \ - --collect-all textual \ - --noconfirm - -echo "===== Build Complete =====" -echo "Binary: dist/TrulyMEM" -ls -la dist/ - -# 清理虚拟环境 -echo "Cleaning up virtual environment..." -deactivate -rm -rf "$VENV_DIR" - -echo "Build finished successfully!" \ No newline at end of file diff --git a/build/build_macos.sh b/build/build_macos.sh deleted file mode 100644 index 69afd97..0000000 --- a/build/build_macos.sh +++ /dev/null @@ -1,90 +0,0 @@ -#!/bin/bash -set -e - -echo "===== Building TrulyMEM for macOS =====" - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" -cd "$PROJECT_ROOT" - -echo "Project root: $PROJECT_ROOT" - -if ! command -v python3 &> /dev/null; then - echo "Error: python3 not found" - exit 1 -fi - -# 创建并激活虚拟环境 -VENV_DIR="$PROJECT_ROOT/.venv_build" - -echo "Creating virtual environment: $VENV_DIR" -python3 -m venv "$VENV_DIR" - -echo "Activating virtual environment..." -source "$VENV_DIR/bin/activate" - -echo "Upgrading pip in virtual environment..." -pip install --upgrade pip - -echo "Installing dependencies in virtual environment..." -pip install -r requirements.txt - -echo "Generating ICNS icon..." -if [ -d "pic/TrulyMEM.iconset" ]; then - iconutil -c icns pic/TrulyMEM.iconset -o pic/TrulyMEM.icns - echo "ICNS icon generated: pic/TrulyMEM.icns" -fi - -echo "Cleaning previous builds..." -rm -rf build/dist build/__pycache__ 2>/dev/null || true - -echo "Running PyInstaller..." -python -m PyInstaller trulymem_entry.py \ - --clean \ - --onefile \ - --console \ - --name TrulyMEM \ - --icon "pic/TrulyMEM.icns" \ - --add-data "ui/styles:ui/styles" \ - --add-data "core/prompts/templates:core/prompts/templates" \ - --hidden-import textual \ - --hidden-import textual.app \ - --hidden-import textual.widgets \ - --hidden-import textual.css \ - --hidden-import openai \ - --hidden-import openai._client \ - --hidden-import neo4j \ - --hidden-import sqlite3 \ - --hidden-import core \ - --hidden-import core.embedded_db \ - --hidden-import core.graph_client \ - --hidden-import core.tool_executor \ - --hidden-import core.tool_limiter \ - --hidden-import core.tools \ - --hidden-import core.tools.memory_tools \ - --hidden-import core.prompts \ - --hidden-import core.prompts.prompt_manager \ - --hidden-import ui \ - --hidden-import ui.app \ - --hidden-import ui.models \ - --hidden-import ui.models.message \ - --hidden-import ui.models.config \ - --hidden-import ui.models.log_entry \ - --hidden-import ui.widgets \ - --hidden-import ui.handlers \ - --hidden-import ui.services \ - --hidden-import ui.services.config_manager \ - --hidden-import ui.services.config_service \ - --collect-all textual \ - --noconfirm - -echo "===== Build Complete =====" -echo "Binary: dist/TrulyMEM" -ls -la dist/ - -# 清理虚拟环境 -echo "Cleaning up virtual environment..." -deactivate -rm -rf "$VENV_DIR" - -echo "Build finished successfully!" \ No newline at end of file diff --git a/build/build_windows.bat b/build/build_windows.bat deleted file mode 100644 index bc49619..0000000 --- a/build/build_windows.bat +++ /dev/null @@ -1,60 +0,0 @@ -@echo off -echo ===== Building TrulyMEM for Windows ===== - -REM 切换到脚本所在目录的上一级目录(项目根目录) -cd /d "%~dp0.." -echo Project root: %CD% - -python --version >nul 2>&1 -if errorlevel 1 ( - echo Error: python not found - exit /b 1 -) - -echo Installing dependencies... -pip install -r requirements.txt - -echo Running PyInstaller... -python -m PyInstaller trulymem_entry.py ^ - --clean ^ - --onefile ^ - --console ^ - --name TrulyMEM ^ - --icon "pic/TrulyMEM.ico" ^ - --add-data "ui/styles;ui/styles" ^ - --add-data "core/prompts/templates;core/prompts/templates" ^ - --hidden-import textual ^ - --hidden-import textual.app ^ - --hidden-import textual.widgets ^ - --hidden-import textual.css ^ - --hidden-import openai ^ - --hidden-import openai._client ^ - --hidden-import neo4j ^ - --hidden-import sqlite3 ^ - --hidden-import core ^ - --hidden-import core.embedded_db ^ - --hidden-import core.graph_client ^ - --hidden-import core.tool_executor ^ - --hidden-import core.tool_limiter ^ - --hidden-import core.tools ^ - --hidden-import core.tools.memory_tools ^ - --hidden-import core.prompts ^ - --hidden-import core.prompts.prompt_manager ^ - --hidden-import ui ^ - --hidden-import ui.app ^ - --hidden-import ui.models ^ - --hidden-import ui.models.message ^ - --hidden-import ui.models.config ^ - --hidden-import ui.models.log_entry ^ - --hidden-import ui.widgets ^ - --hidden-import ui.handlers ^ - --hidden-import ui.services ^ - --hidden-import ui.services.config_manager ^ - --hidden-import ui.services.config_service ^ - --collect-all textual ^ - --noconfirm - -echo ===== Build Complete ===== -echo Binary: dist\TrulyMEM.exe -dir dist\TrulyMEM.exe -pause \ No newline at end of file diff --git a/build/trulymem.spec b/build/trulymem.spec deleted file mode 100644 index 810ca53..0000000 --- a/build/trulymem.spec +++ /dev/null @@ -1,92 +0,0 @@ -# -*- mode: python ; coding: utf-8 -*- -import os -import sys - -block_cipher = None - -project_root = os.path.dirname(os.path.abspath(SPEC)) -sys.path.insert(0, project_root) - -datas = [] -if os.path.exists(os.path.join(project_root, 'ui', 'styles')): - for root, dirs, files in os.walk(os.path.join(project_root, 'ui', 'styles')): - for f in files: - src = os.path.join(root, f) - dst = os.path.join('ui', 'styles', os.path.relpath(src, os.path.join(project_root, 'ui', 'styles'))) - datas.append((src, dst)) - -if os.path.exists(os.path.join(project_root, 'core', 'prompts', 'templates')): - for root, dirs, files in os.walk(os.path.join(project_root, 'core', 'prompts', 'templates')): - for f in files: - src = os.path.join(root, f) - dst = os.path.join('core', 'prompts', 'templates', os.path.relpath(src, os.path.join(project_root, 'core', 'prompts', 'templates'))) - datas.append((src, dst)) - -a = Analysis( - ['trulymem_entry.py'], - pathex=[], - binaries=[], - datas=datas, - hiddenimports=[ - 'textual', - 'textual.app', - 'textual.widgets', - 'textual.css', - 'openai', - 'openai._client', - 'neo4j', - 'sqlite3', - 'graph_memory_tui', - 'core', - 'core.embedded_db', - 'core.graph_client', - 'core.tool_executor', - 'core.tool_limiter', - 'core.tools', - 'core.tools.memory_tools', - 'core.prompts', - 'core.prompts.prompt_manager', - 'ui', - 'ui.app', - 'ui.models', - 'ui.models.message', - 'ui.models.config', - 'ui.models.log_entry', - 'ui.widgets', - 'ui.widgets.left_panel', - 'ui.widgets.right_panel', - 'ui.widgets.input_box', - 'ui.widgets.message_history', - 'ui.widgets.status_bar', - 'ui.handlers', - 'ui.services', - 'ui.services.config_manager', - ], - hookspath=[], - hooksconfig={}, - runtime_hooks=[], - excludes=[], - noarchive=False, - optimize=0, -) -pyz = PYZ(a.pure, block_cipher) -exe = EXE( - pyz, - a.scripts, - a.binaries, - a.datas, - [], - name='TrulyMEM', - debug=False, - bootloader_ignore_signals=False, - strip=False, - upx=True, - upx_exclude=[], - runtime_tmpdir=None, - console=True, - disable_windowed_traceback=False, - argv_emulation=False, - target_arch=None, - codesign_identity=None, - entitlements_file=None, -) \ No newline at end of file diff --git a/core/graph_client.py b/core/graph_client.py index 706ff75..657a712 100644 --- a/core/graph_client.py +++ b/core/graph_client.py @@ -304,6 +304,16 @@ class GraphMemoryClient: """图记忆客户端""" def __init__(self, api_key: str, base_url: str, graph, model: str = "deepseek-chat"): + # 清理可能存在的错误代理环境变量 + import os + proxy_vars = ['http_proxy', 'https_proxy', 'HTTP_PROXY', 'HTTPS_PROXY', 'all_proxy', 'ALL_PROXY'] + for var in proxy_vars: + if var in os.environ: + value = os.environ[var] + # 如果代理URL没有scheme前缀,添加http:// + if value and not value.startswith(('http://', 'https://', 'socks5://', 'socks4://')): + os.environ[var] = f'http://{value}' + self.client = OpenAI(api_key=api_key, base_url=base_url) self.graph = graph self.tools = TOOLS diff --git a/ui/app.py b/ui/app.py index 3d794ff..c9094f3 100644 --- a/ui/app.py +++ b/ui/app.py @@ -128,6 +128,9 @@ class GraphMemoryApp(App): async def _process(self, user_input: str) -> None: from .widgets.message_history import MessageHistory from .widgets.status_bar import StatusBar + from .widgets.right_panel import RightPanel + from .models.log_entry import LogEntry + from datetime import datetime history = self.query_one(MessageHistory) status_bar = self.query_one(StatusBar) @@ -138,8 +141,29 @@ class GraphMemoryApp(App): ) if result.get("success"): - content = result.get("content", "(无回复)") + # 响应结构: {"success": True, "data": {"content": "...", "tool_calls": [...], ...}, "error": None} + data = result.get("data", {}) + content = data.get("content", "(无回复)") history.update_latest_message(content) + + # 处理工具调用信息,更新操作日志 + tool_calls = data.get("tool_calls", []) + if tool_calls: + try: + right_panel = self.query_one(RightPanel) + operation_log = right_panel.get_operation_log() + + for tool_call in tool_calls: + entry = LogEntry( + timestamp=datetime.now(), + tool_name=tool_call.get("name", "unknown"), + arguments=tool_call.get("arguments", {}), + result=str(tool_call.get("result", "")), + duration=0.0 # 后端没有返回耗时信息 + ) + operation_log.add_log(entry) + except Exception: + pass # 忽略操作日志更新失败 else: error = result.get("error", "未知错误") history.update_latest_message(f"❌ 错误: {error}") diff --git a/ui/widgets/config_section.py b/ui/widgets/config_section.py index 19f5ec6..7a20f8e 100644 --- a/ui/widgets/config_section.py +++ b/ui/widgets/config_section.py @@ -141,6 +141,9 @@ class ConfigSection(Vertical): memory_update_max=int(memory_update.value or 10), ) + # 先发送 API 配置更新(is_tool_limits=False) + self.post_message(self.ConfigChanged(self._config, is_tool_limits=False)) + # 再发送工具限制更新(is_tool_limits=True) self.post_message(self.ConfigChanged(self._config, is_tool_limits=True)) except Exception: pass