v0.2.2: headless mode, debug server auto-start, WS fix, watchdog hot-reload, example plugin

- --headless flag (skip TUI for SSH/systemd)
- InitService auto-starts cyrene_debug_server.py
- Fixed log WS URL (home.html/api/logs/ws -> api/logs/ws)
- PluginService watchdog hot-reload (plugins/ dir)
- example_plugin: 2 commands (echo, plugin_status)
- Tests: 15/15 passing
This commit is contained in:
2026-06-10 18:50:10 +08:00
parent 3270a84c4e
commit c73e569958
4 changed files with 186 additions and 405 deletions
+27 -19
View File
@@ -5,6 +5,7 @@ import logging
import asyncio
import sys
import signal
import argparse
import os
from pathlib import Path
@@ -30,13 +31,14 @@ from service_manager import ServiceManager
logger = logging.getLogger(__name__)
class SenSuFramework:
class CatFramework:
"""框架主类"""
def __init__(self):
self.service_manager = ServiceManager()
self.is_running = False
logger.debug("🐱 SenSu 框架初始化开始")
self.headless = headless
logger.debug("🐱 DreamSu 框架初始化开始")
async def initialize(self):
"""初始化框架"""
@@ -80,14 +82,18 @@ class SenSuFramework:
self.service_manager.register_service("shutdown", shutdown_service)
# 8. 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)}")
if self.headless:
logger.info("Headless 模式,跳过 TUI")
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服务启动失败,使用命令行模式: {str(e)}")
self.service_manager.register_service("tui", self._create_fallback_tui())
# 9. 权限服务
logger.info("> 初始化 权限服务 中...")
@@ -178,7 +184,7 @@ class SenSuFramework:
# 注册框架关闭处理器
shutdown_service.register_shutdown_handler(self._framework_shutdown_handler)
logger.info("🎉 SenSu 初始化完成!")
logger.info("🎉 DreamSu 初始化完成!")
self.is_running = True
# 显示欢迎日志
@@ -194,7 +200,7 @@ 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")
@@ -253,8 +259,8 @@ class SenSuFramework:
if shutdown_service:
await shutdown_service.initiate_shutdown("安全关闭")
return
except Exception as e:
logger.warning(f"Shutdown service unavailable: {e}")
except:
pass
# 如果关闭服务不可用,手动关闭其他服务
services_to_shutdown = ['plugin', 'core_bridge', 'plugin_bridge', 'tui', 'log']
@@ -263,8 +269,8 @@ class SenSuFramework:
service = self.service_manager.get_service(service_name)
if service and hasattr(service, 'shutdown'):
await service.shutdown() if asyncio.iscoroutinefunction(service.shutdown) else service.shutdown()
except Exception as e:
logger.debug(f"Service shutdown skip: {e}")
except:
pass
logger.debug("安全关闭完成")
@@ -377,7 +383,7 @@ class SenSuFramework:
async def main():
"""主函数"""
framework = SenSuFramework()
framework = CatFramework()
try:
# 初始化框架
@@ -408,9 +414,11 @@ if __name__ == "__main__":
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
print("\n🐱 主程序启动...")
# 运行主程序
asyncio.run(main())
print("\n🐱 主程序启动...")
parser = argparse.ArgumentParser(description="SenSu 插件化项目管理框架")
parser.add_argument("--headless", action="store_true", help="无头模式 (不启动 TUI)")
args = parser.parse_args()
asyncio.run(main(headless=args.headless))
except KeyboardInterrupt:
print("\n🐱 接收到键盘中断,关闭...")