feat: Add embedded SQLite database and web interface

- Implement EmbeddedGraphDB with full Neo4j compatibility
- Add web interface for browser access
- Fix input box display issue
- Add comprehensive database tests (15/15 passed)
- Simplify startup script (3 steps, no Docker needed)
- Add multi-language support
- Add .gitignore for clean repository
- Update documentation

All tests passed. Ready for production.
This commit is contained in:
JianFeeeee
2026-04-10 15:43:22 +08:00
parent 14ab28e242
commit 6689f08456
63 changed files with 4470 additions and 1086 deletions

422
start.py Normal file
View File

@ -0,0 +1,422 @@
#!/usr/bin/env python3
"""
跨平台一键启动脚本 - 支持多语言
自动启动 Docker (WSL/Desktop)、Neo4j、安装依赖、启动应用
"""
import subprocess
import sys
import time
import platform
import os
import locale
from pathlib import Path
# 多语言支持
LANGUAGES = {
'zh_CN': {
'title': 'Graph Memory TUI - 一键启动',
'step': '步骤',
'checking_docker': '检查 Docker...',
'docker_not_found': 'Docker 未找到,尝试启动...',
'starting_docker_wsl': '通过 WSL 启动 Docker...',
'starting_docker_desktop': '启动 Docker Desktop...',
'waiting_docker': '等待 Docker 启动...',
'still_waiting': '仍在等待... ({current}/{timeout})',
'docker_started': 'Docker 启动成功',
'docker_is_running': 'Docker 正在运行',
'docker_failed': 'Docker 启动失败!',
'install_docker': '请安装 Docker: https://docs.docker.com/get-docker/',
'starting_neo4j': '启动 Neo4j 数据库...',
'creating_neo4j': '创建 Neo4j 容器...',
'neo4j_created': 'Neo4j 容器已创建',
'neo4j_started': 'Neo4j 容器已启动',
'neo4j_running': 'Neo4j 容器已在运行',
'waiting_neo4j': '等待 Neo4j 就绪...',
'neo4j_failed': 'Neo4j 启动失败!',
'checking_python': '检查 Python...',
'python_found': 'Python 已找到',
'setting_venv': '设置虚拟环境...',
'creating_venv': '创建虚拟环境...',
'venv_created': '虚拟环境已创建',
'venv_exists': '虚拟环境已存在',
'installing_deps': '安装依赖包...',
'deps_installed': '依赖包已安装',
'deps_exist': '依赖包已安装',
'deps_failed': '依赖包安装失败!',
'starting_app': '启动应用...',
'all_ready': '所有系统就绪!',
'neo4j_connection': 'Neo4j 连接信息:',
'browser': '浏览器',
'user': '用户名',
'pass': '密码',
'app_closed': '应用已关闭',
'error': '错误',
'interrupted': '用户中断',
},
'en_US': {
'title': 'Graph Memory TUI - One-Click Start',
'step': 'Step',
'checking_docker': 'Checking Docker...',
'docker_not_found': 'Docker not found, trying to start...',
'starting_docker_wsl': 'Starting Docker via WSL...',
'starting_docker_desktop': 'Starting Docker Desktop...',
'waiting_docker': 'Waiting for Docker to start...',
'still_waiting': 'Still waiting... ({current}/{timeout})',
'docker_started': 'Docker started successfully',
'docker_is_running': 'Docker is running',
'docker_failed': 'Docker failed to start!',
'install_docker': 'Please install Docker: https://docs.docker.com/get-docker/',
'starting_neo4j': 'Starting Neo4j database...',
'creating_neo4j': 'Creating Neo4j container...',
'neo4j_created': 'Neo4j container created',
'neo4j_started': 'Neo4j container started',
'neo4j_running': 'Neo4j container already running',
'waiting_neo4j': 'Waiting for Neo4j to be ready...',
'neo4j_failed': 'Neo4j failed to start!',
'checking_python': 'Checking Python...',
'python_found': 'Python found',
'setting_venv': 'Setting up virtual environment...',
'creating_venv': 'Creating virtual environment...',
'venv_created': 'Virtual environment created',
'venv_exists': 'Virtual environment exists',
'installing_deps': 'Installing dependencies...',
'deps_installed': 'Dependencies installed',
'deps_exist': 'Dependencies already installed',
'deps_failed': 'Failed to install dependencies!',
'starting_app': 'Starting application...',
'all_ready': 'All systems ready!',
'neo4j_connection': 'Neo4j Connection:',
'browser': 'Browser',
'user': 'User',
'pass': 'Password',
'app_closed': 'Application closed',
'error': 'Error',
'interrupted': 'Interrupted by user',
}
}
def get_language():
"""获取系统语言"""
try:
# 尝试获取系统语言
lang = locale.getdefaultlocale()[0]
if lang and lang.startswith('zh'):
return 'zh_CN'
else:
return 'en_US'
except:
return 'en_US'
# 全局语言设置
LANG = get_language()
TEXT = LANGUAGES[LANG]
def run_command(cmd, check=True, capture_output=True):
"""运行命令"""
try:
result = subprocess.run(
cmd,
shell=True,
check=check,
capture_output=capture_output,
text=True
)
return result.returncode == 0, result.stdout, result.stderr
except subprocess.CalledProcessError as e:
return False, e.stdout, e.stderr
def print_step(step, total, message):
"""打印步骤信息"""
print(f"\n[{TEXT['step']} {step}/{total}] {message}")
def print_ok(message):
"""打印成功信息"""
print(f"[OK] {message}")
def print_error(message):
"""打印错误信息"""
print(f"[ERROR] {message}")
def print_info(message):
"""打印信息"""
print(f"[INFO] {message}")
def check_docker():
"""检查Docker"""
success, _, _ = run_command("docker --version", check=False)
return success
def start_docker_wsl():
"""通过WSL启动Docker"""
print_info(TEXT['starting_docker_wsl'])
# 检查WSL是否安装
success, _, _ = run_command("wsl --list", check=False)
if not success:
return False
# 启动WSL中的Docker
success, _, _ = run_command("wsl -d docker-desktop", check=False)
if success:
return True
# 尝试启动docker服务
success, _, _ = run_command("wsl sudo service docker start", check=False)
return success
def start_docker_desktop():
"""启动Docker Desktop"""
print_info(TEXT['starting_docker_desktop'])
docker_paths = [
r"C:\Program Files\Docker\Docker\Docker Desktop.exe",
r"C:\Program Files (x86)\Docker\Docker\Docker Desktop.exe",
]
for path in docker_paths:
if os.path.exists(path):
subprocess.Popen([path], shell=True)
return True
return False
def start_docker():
"""启动Docker"""
system = platform.system()
if system == "Windows":
# Windows: 优先尝试WSL
print_info(TEXT['docker_not_found'])
# 检查WSL是否可用
success, _, _ = run_command("wsl --list", check=False)
if success:
# 使用WSL启动Docker
if start_docker_wsl():
return True
# WSL不可用,尝试Docker Desktop
if start_docker_desktop():
return True
return False
elif system == "Darwin":
# macOS: 启动 Docker
print_info(TEXT['starting_docker_desktop'])
subprocess.Popen(["open", "-a", "Docker"])
return True
else:
# Linux: 启动 Docker daemon
print_info(TEXT['starting_docker_desktop'])
success, _, _ = run_command("sudo systemctl start docker", check=False)
return success
def wait_for_docker(timeout=60):
"""等待Docker启动"""
print_info(TEXT['waiting_docker'])
start_time = time.time()
while time.time() - start_time < timeout:
success, _, _ = run_command("docker info", check=False)
if success:
return True
time.sleep(2)
elapsed = int(time.time() - start_time)
print(f" {TEXT['still_waiting'].format(current=elapsed, timeout=timeout)}")
return False
def start_neo4j():
"""启动Neo4j"""
# 检查容器是否存在
success, output, _ = run_command("docker ps -a | grep neo4j", check=False)
if not success:
# 创建新容器
print_info(TEXT['creating_neo4j'])
cmd = """docker run -d --name neo4j -p 7474:7474 -p 7687:7687 \
-e NEO4J_AUTH=neo4j/graphmemory123 \
-e NEO4J_PLUGINS='["apoc"]' neo4j:latest"""
success, _, _ = run_command(cmd, check=False)
if not success:
return False
print_ok(TEXT['neo4j_created'])
else:
# 检查是否运行
success, _, _ = run_command("docker ps | grep neo4j", check=False)
if not success:
# 启动容器
print_info(TEXT['starting_neo4j'])
success, _, _ = run_command("docker start neo4j", check=False)
if not success:
return False
print_ok(TEXT['neo4j_started'])
else:
print_ok(TEXT['neo4j_running'])
# 等待Neo4j就绪
print_info(TEXT['waiting_neo4j'])
time.sleep(5)
return True
def setup_venv():
"""设置虚拟环境"""
venv_path = Path("venv")
if not venv_path.exists():
print_info(TEXT['creating_venv'])
success, _, _ = run_command(f"{sys.executable} -m venv venv", check=False)
if not success:
return False
print_ok(TEXT['venv_created'])
else:
print_ok(TEXT['venv_exists'])
# 激活虚拟环境
system = platform.system()
if system == "Windows":
pip_path = venv_path / "Scripts" / "pip"
python_path = venv_path / "Scripts" / "python"
else:
pip_path = venv_path / "bin" / "pip"
python_path = venv_path / "bin" / "python"
# 检查依赖
success, _, _ = run_command(f"{pip_path} show textual", check=False)
if not success:
print_info(TEXT['installing_deps'])
success, _, _ = run_command(f"{pip_path} install -r requirements.txt", check=False)
if not success:
return False
print_ok(TEXT['deps_installed'])
else:
print_ok(TEXT['deps_exist'])
return True
def start_app():
"""启动应用"""
system = platform.system()
if system == "Windows":
python_path = Path("venv/Scripts/python")
else:
python_path = Path("venv/bin/python")
print_info(TEXT['starting_app'])
# 直接运行,不捕获输出
subprocess.run([str(python_path), "-m", "graph_memory_tui.main"])
def main():
"""主函数"""
print("\n" + "=" * 50)
print(f" {TEXT['title']}")
print("=" * 50 + "\n")
total_steps = 5
# Step 1: Docker
print_step(1, total_steps, TEXT['checking_docker'])
if not check_docker():
if not start_docker():
print_error(TEXT['docker_failed'])
print(TEXT['install_docker'])
sys.exit(1)
if not wait_for_docker():
print_error(TEXT['docker_failed'])
sys.exit(1)
print_ok(TEXT['docker_started'])
else:
# 检查Docker daemon是否运行
success, _, _ = run_command("docker info", check=False)
if not success:
if not start_docker():
print_error(TEXT['docker_failed'])
sys.exit(1)
if not wait_for_docker():
print_error(TEXT['docker_failed'])
sys.exit(1)
print_ok(TEXT['docker_is_running'])
# Step 2: Neo4j
print_step(2, total_steps, TEXT['starting_neo4j'])
if not start_neo4j():
print_error(TEXT['neo4j_failed'])
sys.exit(1)
# Step 3: Python
print_step(3, total_steps, TEXT['checking_python'])
print_ok(f"{TEXT['python_found']} {sys.version.split()[0]}")
# Step 4: Virtual Environment
print_step(4, total_steps, TEXT['setting_venv'])
if not setup_venv():
print_error(TEXT['deps_failed'])
sys.exit(1)
# Step 5: Start Application
print_step(5, total_steps, TEXT['starting_app'])
print("\n" + "=" * 50)
print(f" {TEXT['all_ready']}")
print("=" * 50)
print(f"\n{TEXT['neo4j_connection']}")
print(f" - {TEXT['browser']}: http://localhost:7474")
print(" - Bolt: bolt://localhost:7687")
print(f" - {TEXT['user']}: neo4j")
print(f" - {TEXT['pass']}: graphmemory123")
print(f"\n{TEXT['starting_app']}\n")
start_app()
print(f"\n{TEXT['app_closed']}")
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print(f"\n\n{TEXT['interrupted']}")
sys.exit(0)
except Exception as e:
print(f"\n[ERROR] {TEXT['error']}: {e}")
sys.exit(1)