223 lines
7.1 KiB
Python
223 lines
7.1 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
NAC Auto Summary Daemon
|
||
后台守护进程,监控编译活动,45分钟无活动后自动生成日志
|
||
"""
|
||
|
||
import os
|
||
import sys
|
||
import time
|
||
import signal
|
||
import argparse
|
||
from datetime import datetime
|
||
from pathlib import Path
|
||
|
||
# 添加当前目录到Python路径
|
||
sys.path.insert(0, str(Path(__file__).parent))
|
||
|
||
from activity_monitor import ActivityMonitor
|
||
from summary_generator import SummaryGenerator
|
||
|
||
class AutoSummaryDaemon:
|
||
def __init__(self, workspace_path, idle_timeout=2700, check_interval=60):
|
||
"""
|
||
初始化守护进程
|
||
|
||
Args:
|
||
workspace_path: NAC工作区路径
|
||
idle_timeout: 空闲超时时间(秒),默认2700秒(45分钟)
|
||
check_interval: 检查间隔(秒),默认60秒
|
||
"""
|
||
self.workspace_path = Path(workspace_path)
|
||
self.idle_timeout = idle_timeout
|
||
self.check_interval = check_interval
|
||
self.running = True
|
||
self.summary_generated_today = False
|
||
|
||
# 初始化组件
|
||
self.monitor = ActivityMonitor(workspace_path, idle_timeout)
|
||
self.generator = SummaryGenerator(workspace_path)
|
||
|
||
# 日志文件
|
||
log_dir = self.workspace_path / 'memory' / 'logs'
|
||
log_dir.mkdir(parents=True, exist_ok=True)
|
||
self.log_file = log_dir / 'daemon.log'
|
||
|
||
def log(self, message):
|
||
"""
|
||
记录日志
|
||
|
||
Args:
|
||
message: 日志消息
|
||
"""
|
||
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||
log_message = f"[{timestamp}] {message}"
|
||
|
||
# 输出到控制台
|
||
print(log_message)
|
||
|
||
# 写入日志文件
|
||
with open(self.log_file, 'a') as f:
|
||
f.write(log_message + '\n')
|
||
|
||
def signal_handler(self, sig, frame):
|
||
"""
|
||
处理退出信号
|
||
|
||
Args:
|
||
sig: 信号编号
|
||
frame: 当前栈帧
|
||
"""
|
||
self.log(f"收到信号 {sig},正在停止守护进程...")
|
||
self.running = False
|
||
|
||
def check_new_day(self):
|
||
"""
|
||
检查是否进入新的一天
|
||
如果是新的一天,重置标志
|
||
"""
|
||
current_date = datetime.now().strftime('%Y-%m-%d')
|
||
last_check_file = self.workspace_path / 'memory' / 'logs' / 'last_summary_date.txt'
|
||
|
||
last_date = None
|
||
if last_check_file.exists():
|
||
with open(last_check_file, 'r') as f:
|
||
last_date = f.read().strip()
|
||
|
||
if last_date != current_date:
|
||
self.summary_generated_today = False
|
||
with open(last_check_file, 'w') as f:
|
||
f.write(current_date)
|
||
return True
|
||
|
||
return False
|
||
|
||
def generate_summary_if_needed(self):
|
||
"""
|
||
如果需要,生成日志总结
|
||
"""
|
||
# 检查是否进入新的一天
|
||
if self.check_new_day():
|
||
self.log("进入新的一天,重置总结标志")
|
||
|
||
# 检查是否已经生成过今日总结
|
||
if self.summary_generated_today:
|
||
return
|
||
|
||
# 检查是否空闲
|
||
if self.monitor.is_idle():
|
||
idle_minutes = int(self.monitor.get_idle_time() / 60)
|
||
self.log(f"检测到空闲 {idle_minutes} 分钟,开始生成今日工作日志...")
|
||
|
||
try:
|
||
summary, markdown = self.generator.generate_summary()
|
||
|
||
self.log("✅ 今日工作日志生成成功")
|
||
self.log(f" - Git提交: {summary['statistics']['total_commits']}")
|
||
self.log(f" - 代码变更: +{summary['statistics']['total_lines_added']} -{summary['statistics']['total_lines_deleted']}")
|
||
self.log(f" - 新增记忆: {summary['statistics']['new_documents'] + summary['statistics']['new_problems'] + summary['statistics']['new_decisions']}")
|
||
|
||
self.summary_generated_today = True
|
||
|
||
# 重置空闲计时器(避免重复生成)
|
||
self.monitor.reset_idle_timer()
|
||
|
||
except Exception as e:
|
||
self.log(f"❌ 生成日志失败: {e}")
|
||
import traceback
|
||
self.log(traceback.format_exc())
|
||
|
||
def run(self):
|
||
"""
|
||
运行守护进程
|
||
"""
|
||
# 注册信号处理器
|
||
signal.signal(signal.SIGINT, self.signal_handler)
|
||
signal.signal(signal.SIGTERM, self.signal_handler)
|
||
|
||
self.log("="*60)
|
||
self.log("NAC Auto Summary Daemon 已启动")
|
||
self.log(f"工作区: {self.workspace_path}")
|
||
self.log(f"空闲超时: {self.idle_timeout}秒 ({self.idle_timeout/60:.0f}分钟)")
|
||
self.log(f"检查间隔: {self.check_interval}秒")
|
||
self.log("="*60)
|
||
|
||
iteration = 0
|
||
|
||
while self.running:
|
||
try:
|
||
iteration += 1
|
||
|
||
# 扫描活动
|
||
self.monitor.scan_all_activities()
|
||
|
||
# 获取统计信息
|
||
stats = self.monitor.get_activity_statistics()
|
||
idle_time = self.monitor.get_idle_time()
|
||
idle_minutes = int(idle_time / 60)
|
||
|
||
# 每10次迭代输出一次状态(10分钟)
|
||
if iteration % 10 == 0:
|
||
self.log(f"状态: 空闲 {idle_minutes} 分钟 | 今日活动: {stats['total_activities']} | 提交: {stats['commits_count']}")
|
||
|
||
# 检查是否需要生成总结
|
||
self.generate_summary_if_needed()
|
||
|
||
# 等待下一次检查
|
||
time.sleep(self.check_interval)
|
||
|
||
except Exception as e:
|
||
self.log(f"❌ 运行出错: {e}")
|
||
import traceback
|
||
self.log(traceback.format_exc())
|
||
time.sleep(self.check_interval)
|
||
|
||
self.log("NAC Auto Summary Daemon 已停止")
|
||
|
||
|
||
def main():
|
||
"""主函数"""
|
||
parser = argparse.ArgumentParser(description='NAC Auto Summary Daemon')
|
||
parser.add_argument(
|
||
'--workspace',
|
||
default='/home/ubuntu/nac-workspace',
|
||
help='NAC工作区路径(默认: /home/ubuntu/nac-workspace)'
|
||
)
|
||
parser.add_argument(
|
||
'--timeout',
|
||
type=int,
|
||
default=2700,
|
||
help='空闲超时时间(秒,默认: 2700秒=45分钟)'
|
||
)
|
||
parser.add_argument(
|
||
'--interval',
|
||
type=int,
|
||
default=60,
|
||
help='检查间隔(秒,默认: 60秒)'
|
||
)
|
||
parser.add_argument(
|
||
'--test',
|
||
action='store_true',
|
||
help='测试模式(使用较短的超时时间)'
|
||
)
|
||
|
||
args = parser.parse_args()
|
||
|
||
# 测试模式:使用2分钟超时
|
||
if args.test:
|
||
args.timeout = 120
|
||
print("⚠️ 测试模式:空闲超时设置为2分钟")
|
||
|
||
# 创建并运行守护进程
|
||
daemon = AutoSummaryDaemon(
|
||
workspace_path=args.workspace,
|
||
idle_timeout=args.timeout,
|
||
check_interval=args.interval
|
||
)
|
||
|
||
daemon.run()
|
||
|
||
|
||
if __name__ == '__main__':
|
||
main()
|