feat: refactor API key configuration and enhance application initialization
- Renamed `check_environment` to `check_api_key_configured` for clarity, simplifying the API key validation logic. - Removed the blocking behavior of the API key check during application startup, allowing the app to run while providing a prompt for configuration. - Updated `LocalAgentApp` to accept an `api_configured` parameter, enabling conditional messaging for API key setup. - Enhanced the `SandboxRunner` to support backup management and improved execution result handling with detailed metrics. - Integrated data governance strategies into the `HistoryManager`, ensuring compliance and improved data management. - Added privacy settings and metrics tracking across various components to enhance user experience and application safety.
This commit is contained in:
150
build.py
Normal file
150
build.py
Normal file
@@ -0,0 +1,150 @@
|
||||
"""
|
||||
LocalAgent 打包脚本
|
||||
使用 PyInstaller 将项目打包成 Windows 可执行文件
|
||||
|
||||
使用方法:
|
||||
python build.py
|
||||
|
||||
打包完成后,可执行文件位于 dist/LocalAgent/ 目录下
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
# 项目根目录
|
||||
PROJECT_ROOT = Path(__file__).parent
|
||||
|
||||
def clean_build():
|
||||
"""清理之前的构建文件"""
|
||||
dirs_to_clean = ['build', 'dist']
|
||||
files_to_clean = ['LocalAgent.spec']
|
||||
|
||||
for dir_name in dirs_to_clean:
|
||||
dir_path = PROJECT_ROOT / dir_name
|
||||
if dir_path.exists():
|
||||
print(f"清理目录: {dir_path}")
|
||||
shutil.rmtree(dir_path)
|
||||
|
||||
for file_name in files_to_clean:
|
||||
file_path = PROJECT_ROOT / file_name
|
||||
if file_path.exists():
|
||||
print(f"清理文件: {file_path}")
|
||||
file_path.unlink()
|
||||
|
||||
def build_exe():
|
||||
"""使用 PyInstaller 打包"""
|
||||
|
||||
# PyInstaller 参数
|
||||
args = [
|
||||
'pyinstaller',
|
||||
'--name=LocalAgent', # 程序名称
|
||||
'--windowed', # 不显示控制台窗口(GUI 程序)
|
||||
# '--console', # 如果需要看到控制台输出,用这个替换上面的
|
||||
'--onedir', # 打包成目录(比 onefile 启动更快)
|
||||
# '--onefile', # 如果想打包成单个 exe,用这个替换上面的
|
||||
'--noconfirm', # 覆盖已有文件
|
||||
'--clean', # 清理临时文件
|
||||
|
||||
# 添加数据文件
|
||||
'--add-data=.env.example;.', # 配置模板
|
||||
|
||||
# 隐藏导入(PyInstaller 可能检测不到的模块)
|
||||
'--hidden-import=PIL',
|
||||
'--hidden-import=PIL.Image',
|
||||
'--hidden-import=openpyxl',
|
||||
'--hidden-import=docx',
|
||||
'--hidden-import=PyPDF2',
|
||||
'--hidden-import=chardet',
|
||||
'--hidden-import=dotenv',
|
||||
'--hidden-import=requests',
|
||||
'--hidden-import=tkinter',
|
||||
'--hidden-import=tkinter.ttk',
|
||||
'--hidden-import=tkinter.scrolledtext',
|
||||
'--hidden-import=tkinter.messagebox',
|
||||
'--hidden-import=tkinter.colorchooser',
|
||||
|
||||
# 排除不需要的模块(减小体积)
|
||||
'--exclude-module=matplotlib',
|
||||
'--exclude-module=numpy',
|
||||
'--exclude-module=pandas',
|
||||
'--exclude-module=scipy',
|
||||
'--exclude-module=torch',
|
||||
'--exclude-module=tensorflow',
|
||||
|
||||
# 入口文件
|
||||
'main.py'
|
||||
]
|
||||
|
||||
print("=" * 50)
|
||||
print("开始打包 LocalAgent...")
|
||||
print("=" * 50)
|
||||
print(f"命令: {' '.join(args)}")
|
||||
print()
|
||||
|
||||
# 执行打包
|
||||
result = subprocess.run(args, cwd=PROJECT_ROOT)
|
||||
|
||||
if result.returncode == 0:
|
||||
print()
|
||||
print("=" * 50)
|
||||
print("✅ 打包成功!")
|
||||
print("=" * 50)
|
||||
print()
|
||||
print(f"可执行文件位置: {PROJECT_ROOT / 'dist' / 'LocalAgent'}")
|
||||
print()
|
||||
print("使用说明:")
|
||||
print("1. 进入 dist/LocalAgent 目录")
|
||||
print("2. 复制 .env.example 为 .env 并配置 API Key")
|
||||
print("3. 运行 LocalAgent.exe")
|
||||
print()
|
||||
print("注意: 首次运行会自动创建 workspace 目录")
|
||||
|
||||
# 创建 workspace 目录结构
|
||||
dist_dir = PROJECT_ROOT / 'dist' / 'LocalAgent'
|
||||
if dist_dir.exists():
|
||||
workspace = dist_dir / 'workspace'
|
||||
(workspace / 'input').mkdir(parents=True, exist_ok=True)
|
||||
(workspace / 'output').mkdir(parents=True, exist_ok=True)
|
||||
(workspace / 'logs').mkdir(parents=True, exist_ok=True)
|
||||
(workspace / 'codes').mkdir(parents=True, exist_ok=True)
|
||||
print("已创建 workspace 目录结构")
|
||||
|
||||
# 复制 .env.example
|
||||
env_example = PROJECT_ROOT / '.env.example'
|
||||
if env_example.exists():
|
||||
shutil.copy(env_example, dist_dir / '.env.example')
|
||||
print("已复制 .env.example")
|
||||
else:
|
||||
print()
|
||||
print("=" * 50)
|
||||
print("❌ 打包失败!")
|
||||
print("=" * 50)
|
||||
print("请检查错误信息")
|
||||
|
||||
return result.returncode
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
# 检查 PyInstaller 是否安装
|
||||
try:
|
||||
import PyInstaller
|
||||
print(f"PyInstaller 版本: {PyInstaller.__version__}")
|
||||
except ImportError:
|
||||
print("错误: 未安装 PyInstaller")
|
||||
print("请运行: pip install pyinstaller")
|
||||
sys.exit(1)
|
||||
|
||||
# 询问是否清理
|
||||
response = input("是否清理之前的构建文件? (y/n) [y]: ").strip().lower()
|
||||
if response != 'n':
|
||||
clean_build()
|
||||
|
||||
# 执行打包
|
||||
return build_exe()
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
||||
Reference in New Issue
Block a user