Merge branch 'main' of gitcode.com:JianFeeeee/TrulyMEM-TrueHumanMEM

This commit is contained in:
valuelesser
2026-04-14 23:55:02 +08:00
7 changed files with 38 additions and 326 deletions

View File

@ -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!"

View File

@ -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!"

View File

@ -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

View File

@ -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,
)

View File

@ -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

View File

@ -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}")

View File

@ -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