Phase 1: ProjectEngine + PyEnvManager + project management WebUI

- New: services/project_engine.py (async subprocess manager)
- New: services/pyenv_manager.py (Python version + venv + git clone)
- New: services/web_panel/routes/projects.py (5 REST endpoints)
- New: static/web_panel/pages/projects.html (WebUI)
- Tests: 28/28 passing, API verified (GET /api/projects)
- Docs: Phase1_Progress.md (local)
This commit is contained in:
2026-06-10 20:41:24 +08:00
parent 7e762b68fe
commit 8dbf628dd6
11 changed files with 1012 additions and 35 deletions
+39 -32
View File
@@ -5,7 +5,9 @@ import logging
import asyncio
import sys
import signal
import argparse
from services.project_engine import ProjectEngine
from services.pyenv_manager import PyEnvManager
from services.web_panel.routes import projects
import os
from pathlib import Path
@@ -31,15 +33,13 @@ from service_manager import ServiceManager
logger = logging.getLogger(__name__)
class SenSuFramework:
class CatFramework:
"""框架主类"""
def __init__(self, headless=False):
def __init__(self):
self.service_manager = ServiceManager()
self.headless = headless
self.is_running = False
self.headless = headless
logger.debug("🐱 SenSu 框架初始化开始")
logger.debug("🐱 DreamSu 框架初始化开始")
async def initialize(self):
"""初始化框架"""
@@ -83,18 +83,16 @@ class SenSuFramework:
self.service_manager.register_service("shutdown", shutdown_service)
# 8. TUI服务
if self.headless:
logger.info("Headless: skip TUI")
try:
tui_service = TuiService(base_config, log_service, command_service)
await tui_service.start()
self.service_manager.register_service("tui", tui_service)
logger.info("TUI服务启动成功")
except Exception as e:
logger.warning(f"TUI服务启动失败,使用命令行模式: {str(e)}")
self.service_manager.register_service("tui", self._create_fallback_tui())
else:
try:
tui_service = TuiService(base_config, log_service, command_service)
await tui_service.start()
self.service_manager.register_service("tui", tui_service)
logger.info("TUI服务启动成功")
except Exception as e:
logger.warning(f"TUI服务启动失败: {e}")
self.service_manager.register_service("tui", self._create_fallback_tui())
# 9. 权限服务
logger.info("> 初始化 权限服务 中...")
permission_service = PermissionService(base_config, self.service_manager.get_service("tui"), core_bridge)
permission_started = await permission_service.start()
@@ -158,9 +156,8 @@ class SenSuFramework:
logger.info("✅ 互联网服务启动成功")
# 显示服务信息
logger.info("🌐 服务地址:")
logger.info(" http://{0}:{1}".format(internet_service.http_host, internet_service.http_port))
logger.info(f"🔍 健康检查: http://{internet_service.http_host}:{internet_service.http_port}/health")
logger.info(f"🌐 服务地址: http://{internet_service.http_host}:{internet_service.http_port}")
logger.info(f"🔍 健康检查: http://{internet_service.http_host}:{internet_service.http_port}/health")
else:
logger.warning("⚠️ 网络服务已启动但端口未响应")
else:
@@ -184,6 +181,19 @@ class SenSuFramework:
# 注册框架关闭处理器
shutdown_service.register_shutdown_handler(self._framework_shutdown_handler)
# 11.7 项目引擎
try:
logger.info("> 初始化 项目引擎 中...")
project_engine = ProjectEngine(self.service_manager)
await project_engine.start()
self.service_manager.register_service("project_engine", project_engine)
pe_mgr = PyEnvManager("data/projects")
self.service_manager.register_service("pyenv", pe_mgr)
# project routes registered by web_panel manager (before router freeze)
logger.info("✅ 项目引擎就绪")
except Exception as e:
logger.warning(f"项目引擎初始化跳过: {e}")
logger.info("🎉 SenSu 初始化完成!")
self.is_running = True
@@ -200,16 +210,16 @@ class SenSuFramework:
# 显示欢迎消息
tui_service = self.service_manager.get_service("tui")
if hasattr(tui_service, 'show_message'):
tui_service.show_message("🐱 SenSu 框架 已就绪!\n", "info")
tui_service.show_message("🐱 DreamSu 框架 已就绪!\n", "info")
tui_service.show_message("====================================\n", "info")
tui_service.show_message("🐱 SenSu 已就绪!", "info")
tui_service.show_message(f"当前 SenSu 版本号 {version}", "info")
tui_service.show_message(f"当前日志级别 {logLevel}\n", "info")
tui_service.show_message("====================================\n", "info")
tui_service.show_message(f"当前API配置地址", "debug")
tui_service.show_message(f"地址: http://{internet_service.http_host}:{internet_service.http_port}", "debug")
tui_service.show_message(f"地址:http://{internet_service.http_host}:{internet_service.http_port}", "debug")
tui_service.show_message("====================================\n", "debug")
tui_service.show_message(f"🌐 Web 面板配置地址: http://{internet_service.http_host}:{internet_service.http_port}{panel_path}", "info")
tui_service.show_message(f"🌐 Web 面板配置地址: http://{internet_service.http_host}:{internet_service.http_port}{panel_path}", "info")
else:
print("🐱 SenSu 已就绪!输入 'help' 查看可用命令")
@@ -223,7 +233,7 @@ class SenSuFramework:
def _create_fallback_tui(self):
"""创建回退的TUI服务(命令行模式)"""
class FallbackTuiService:
def __init__(self, headless=False):
def __init__(self):
self.is_running = True
def show_message(self, message: str, msg_type: str = "info", persistent: bool = False):
@@ -381,9 +391,9 @@ class SenSuFramework:
logger.error(f"关闭框架时出错: {str(e)}", exc_info=True)
await self._safe_shutdown()
async def main(headless=False):
async def main():
"""主函数"""
framework = SenSuFramework(headless=headless)
framework = CatFramework()
try:
# 初始化框架
@@ -404,7 +414,6 @@ if __name__ == "__main__":
try:
# 设置更详细的异常处理
import signal
def signal_handler(signum, frame):
"""信号处理"""
@@ -415,11 +424,9 @@ if __name__ == "__main__":
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
print("\n🐱 主程序启动...")
parser = argparse.ArgumentParser(description="SenSu")
parser.add_argument("--headless", action="store_true")
args = parser.parse_args()
asyncio.run(main(headless=args.headless))
print("\n🐱 主程序启动...")
# 运行主程序
asyncio.run(main())
except KeyboardInterrupt:
print("\n🐱 接收到键盘中断,关闭...")