Files
TrulyMEM-TrueHumanMEM-local/build/trulymem.spec
root b4456a9c5b 多用户系统 + Admin 角色权限 + Web/TUI 同步 + 构建集成
本轮实现功能:
1. 多用户隔离:每个用户独立 config.json + graph.db
2. TUI 登录页 + 旧版自动迁移(core/migrate.py)
3. Admin/User 角色体系(core/embedded_db.py)
4. Web 后台管理 API(userinfo + admin CRUD)
5. Web 设置页用户管理区(仅 admin 可见)
6. TUI 侧栏配置区权限同步(非 admin 隐藏 Web 服务设置)
7. Web 服务打包为独立二进制(trulymem-web)
8. 双入口 PyInstaller 构建脚本(TUI + Web)
9. 活动记录器(core/activity_recorder.py)
10. 静态页面模板(登录/设置/首次引导)
2026-04-28 10:37:57 +08:00

146 lines
4.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- 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 = []
# UI 样式
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))
# Prompt 模板
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))
# Web 静态文件
if os.path.exists(os.path.join(project_root, 'static')):
for root, dirs, files in os.walk(os.path.join(project_root, 'static')):
for f in files:
src = os.path.join(root, f)
dst = os.path.join('static', os.path.relpath(src, os.path.join(project_root, 'static')))
datas.append((src, dst))
# Web 模板
if os.path.exists(os.path.join(project_root, 'templates')):
for root, dirs, files in os.walk(os.path.join(project_root, 'templates')):
for f in files:
src = os.path.join(root, f)
dst = os.path.join('templates', os.path.relpath(src, os.path.join(project_root, 'templates')))
datas.append((src, dst))
# Web API 脚本(以便子进程模式回退使用)
web_api_src = os.path.join(project_root, 'web_api.py')
if os.path.exists(web_api_src):
datas.append((web_api_src, '.'))
# ——— TUI 主二进制 ———
a = Analysis(
['trulymem_entry.py'],
pathex=[project_root],
binaries=[],
datas=datas,
hiddenimports=[
'textual', 'textual.app', 'textual.widgets', 'textual.css',
'openai', 'openai._client',
'neo4j',
'sqlite3',
'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',
'core.server', 'core.client',
'core.migrate',
'ui', 'ui.app', 'ui.login_screen',
'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', 'ui.services.config_service',
'web_api',
'flask', 'flask_cors',
],
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,
)
# ——— Web 服务二进制trulymem-web———
web_a = Analysis(
['web_api.py'],
pathex=[project_root],
binaries=[],
datas=[
(os.path.join(project_root, 'templates'), 'templates'),
(os.path.join(project_root, 'static'), 'static'),
],
hiddenimports=[
'flask', 'flask_cors',
'core', 'core.server', 'core.client',
'core.embedded_db', 'core.activity_recorder',
'core.migrate',
],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)
web_pyz = PYZ(web_a.pure, block_cipher)
web_exe = EXE(
web_pyz,
web_a.scripts,
web_a.binaries,
web_a.datas,
[],
name='trulymem-web',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)