#!/usr/bin/env python3 """ NAC Summary Generator 生成每日工作日志总结 """ import os import json import subprocess from datetime import datetime from pathlib import Path from activity_monitor import ActivityMonitor class SummaryGenerator: def __init__(self, workspace_path): """ 初始化日志总结生成器 Args: workspace_path: NAC工作区路径 """ self.workspace_path = Path(workspace_path) self.memory_path = self.workspace_path / 'memory' self.docs_path = self.workspace_path / 'docs' self.summaries_path = self.memory_path / 'summaries' # 创建必要的目录 self.summaries_path.mkdir(parents=True, exist_ok=True) self.docs_path.mkdir(parents=True, exist_ok=True) def collect_git_commits(self, project_path): """ 收集Git提交记录 Args: project_path: 项目路径 Returns: list: 提交记录列表 """ try: # 获取今日提交 result = subprocess.run( ['git', 'log', '--since=midnight', '--pretty=format:%h|%s|%an|%ad|%ae', '--date=iso', '--numstat'], cwd=project_path, capture_output=True, text=True, timeout=10 ) commits = [] current_commit = None for line in result.stdout.split('\n'): if '|' in line: # 提交信息行 parts = line.split('|') if len(parts) >= 4: if current_commit: commits.append(current_commit) current_commit = { 'hash': parts[0], 'message': parts[1], 'author': parts[2], 'date': parts[3], 'email': parts[4] if len(parts) > 4 else '', 'files': [], 'insertions': 0, 'deletions': 0 } elif line.strip() and current_commit: # 文件统计行 parts = line.split('\t') if len(parts) == 3: insertions = parts[0] if parts[0] != '-' else '0' deletions = parts[1] if parts[1] != '-' else '0' filepath = parts[2] current_commit['files'].append({ 'path': filepath, 'insertions': int(insertions), 'deletions': int(deletions) }) current_commit['insertions'] += int(insertions) current_commit['deletions'] += int(deletions) if current_commit: commits.append(current_commit) return commits except Exception as e: print(f"收集Git提交失败: {e}") return [] def collect_modified_files(self, project_path): """ 收集修改的文件 Args: project_path: 项目路径 Returns: list: 修改文件列表 """ try: # 获取未提交的修改 result = subprocess.run( ['git', 'status', '--porcelain'], cwd=project_path, capture_output=True, text=True, timeout=5 ) files = [] for line in result.stdout.strip().split('\n'): if line: status = line[:2].strip() filepath = line[3:].strip() files.append({ 'status': status, 'path': filepath }) return files except Exception as e: print(f"收集修改文件失败: {e}") return [] def collect_lint_checks(self): """ 收集Lint检查记录 Returns: list: Lint检查记录列表 """ today = datetime.now().strftime('%Y%m%d') lint_log_file = self.memory_path / 'logs' / f'lint_{today}.log' if not lint_log_file.exists(): return [] checks = [] with open(lint_log_file, 'r') as f: for line in f: try: check = json.loads(line) checks.append(check) except: continue return checks def collect_memory_records(self): """ 收集今日新增的记忆记录 Returns: dict: 记忆记录分类 """ today = datetime.now().strftime('%Y-%m-%d') records = { 'documents': [], 'problems': [], 'decisions': [] } # 收集文档记录 docs_path = self.memory_path / 'documents' if docs_path.exists(): for file in docs_path.glob('*.json'): if file.name == 'index.json': continue try: with open(file, 'r') as f: data = json.load(f) if data.get('created_date', '').startswith(today): records['documents'].append(data) except: continue # 收集问题记录 problems_path = self.memory_path / 'problems' if problems_path.exists(): for file in problems_path.glob('*.json'): if file.name == 'index.json': continue try: with open(file, 'r') as f: data = json.load(f) if data.get('created_date', '').startswith(today): records['problems'].append(data) except: continue # 收集决策记录 decisions_path = self.memory_path / 'decisions' if decisions_path.exists(): for file in decisions_path.glob('*.json'): if file.name == 'index.json': continue try: with open(file, 'r') as f: data = json.load(f) if data.get('created_date', '').startswith(today): records['decisions'].append(data) except: continue return records def generate_summary(self): """ 生成完整的日志总结 Returns: tuple: (summary_dict, markdown_report) """ today = datetime.now().strftime('%Y-%m-%d') today_id = datetime.now().strftime('%Y%m%d') # 收集所有数据 all_commits = [] all_modified_files = [] projects = ['nac-blockchain', 'nac-asset-onchain', 'nac-quantum-explorer'] for project in projects: project_path = self.workspace_path / project if project_path.exists(): commits = self.collect_git_commits(project_path) for commit in commits: commit['project'] = project all_commits.extend(commits) modified_files = self.collect_modified_files(project_path) for file in modified_files: file['project'] = project all_modified_files.extend(modified_files) lint_checks = self.collect_lint_checks() memory_records = self.collect_memory_records() # 计算统计信息 total_insertions = sum(c['insertions'] for c in all_commits) total_deletions = sum(c['deletions'] for c in all_commits) total_files_in_commits = sum(len(c['files']) for c in all_commits) # 生成总结 summary = { 'summary_id': f'SUMMARY_{today_id}', 'date': today, 'generated_at': datetime.now().isoformat(), 'activities': { 'git_commits': all_commits, 'modified_files': all_modified_files, 'lint_checks': lint_checks, 'memory_records': memory_records }, 'statistics': { 'total_commits': len(all_commits), 'total_files_modified': total_files_in_commits, 'total_lines_added': total_insertions, 'total_lines_deleted': total_deletions, 'lint_checks_count': len(lint_checks), 'new_documents': len(memory_records['documents']), 'new_problems': len(memory_records['problems']), 'new_decisions': len(memory_records['decisions']) } } # 生成Markdown报告 markdown = self.generate_markdown_report(summary) # 保存 self.save_summary(summary, markdown) return summary, markdown def generate_markdown_report(self, summary): """ 生成Markdown格式的报告 Args: summary: 总结数据 Returns: str: Markdown格式的报告 """ date = summary['date'] stats = summary['statistics'] activities = summary['activities'] # 开始生成报告 report = f"""# NAC工作日志 - {date} **生成时间**: {summary['generated_at']} **自动生成**: NAC Auto Summary v1.0 --- ## 📊 今日统计 - **Git提交**: {stats['total_commits']}次 - **文件修改**: {stats['total_files_modified']}个文件 - **代码变更**: +{stats['total_lines_added']} -{stats['total_lines_deleted']}行 - **Lint检查**: {stats['lint_checks_count']}次 - **新增文档**: {stats['new_documents']}个 - **新增问题**: {stats['new_problems']}个 - **新增决策**: {stats['new_decisions']}个 --- ## 📝 Git提交记录 """ if activities['git_commits']: for commit in activities['git_commits']: report += f"""### [{commit['project']}] {commit['message']} - **提交哈希**: `{commit['hash']}` - **作者**: {commit['author']} - **时间**: {commit['date']} - **变更**: +{commit['insertions']} -{commit['deletions']}行 - **文件**: {len(commit['files'])}个 """ if commit['files']: report += "**修改文件**:\n" for file in commit['files'][:10]: # 最多显示10个文件 report += f" - `{file['path']}` (+{file['insertions']} -{file['deletions']})\n" if len(commit['files']) > 10: report += f" - ... 还有 {len(commit['files']) - 10} 个文件\n" report += "\n" else: report += "今日无Git提交。\n\n" report += "---\n\n## 📂 未提交的修改\n\n" if activities['modified_files']: by_project = {} for file in activities['modified_files']: project = file['project'] if project not in by_project: by_project[project] = [] by_project[project].append(file) for project, files in by_project.items(): report += f"### {project}\n\n" for file in files[:20]: # 最多显示20个文件 status_map = { 'M': '修改', 'A': '新增', 'D': '删除', 'R': '重命名', '??': '未跟踪' } status_text = status_map.get(file['status'], file['status']) report += f"- [{status_text}] `{file['path']}`\n" if len(files) > 20: report += f"- ... 还有 {len(files) - 20} 个文件\n" report += "\n" else: report += "所有修改已提交。\n\n" report += "---\n\n## 🔍 NAC Lint检查记录\n\n" if activities['lint_checks']: report += f"今日共进行了 {len(activities['lint_checks'])} 次Lint检查。\n\n" # 这里可以添加更详细的Lint统计 else: report += "今日无Lint检查记录。\n\n" report += "---\n\n## 📚 新增记忆记录\n\n" memory = activities['memory_records'] if memory['documents']: report += "### 新增文档\n\n" for doc in memory['documents']: report += f"- **{doc.get('title', 'Untitled')}** (`{doc.get('doc_id', 'N/A')}`)\n" report += f" - {doc.get('summary', 'No summary')}\n" report += "\n" if memory['problems']: report += "### 新增问题\n\n" for problem in memory['problems']: report += f"- **{problem.get('title', 'Untitled')}** (`{problem.get('problem_id', 'N/A')}`)\n" report += f" - 状态: {problem.get('status', 'unknown')}\n" report += f" - {problem.get('description', 'No description')[:100]}...\n" report += "\n" if memory['decisions']: report += "### 新增决策\n\n" for decision in memory['decisions']: report += f"- **{decision.get('title', 'Untitled')}** (`{decision.get('decision_id', 'N/A')}`)\n" if 'decision' in decision and 'statement' in decision['decision']: report += f" - {decision['decision']['statement']}\n" report += "\n" if not any([memory['documents'], memory['problems'], memory['decisions']]): report += "今日无新增记忆记录。\n\n" report += """--- ## 🎯 总结 """ # 生成亮点 highlights = [] if stats['total_commits'] > 0: highlights.append(f"✅ 完成 {stats['total_commits']} 次代码提交") if stats['total_lines_added'] > 0: highlights.append(f"✅ 新增 {stats['total_lines_added']} 行代码") if stats['new_problems'] > 0: highlights.append(f"✅ 记录 {stats['new_problems']} 个问题和解决方案") if stats['new_documents'] > 0: highlights.append(f"✅ 阅读并记录 {stats['new_documents']} 个文档") if highlights: for highlight in highlights: report += f"{highlight} \n" else: report += "今日无重大进展。\n" report += "\n---\n\n" report += f"*本报告由NAC Auto Summary自动生成于 {summary['generated_at']}*\n" return report def save_summary(self, summary, markdown): """ 保存总结到文件 Args: summary: 总结数据(字典) markdown: Markdown报告 """ today_id = datetime.now().strftime('%Y%m%d') # 保存JSON json_path = self.summaries_path / f'SUMMARY_{today_id}.json' with open(json_path, 'w', encoding='utf-8') as f: json.dump(summary, f, indent=2, ensure_ascii=False) print(f"✅ JSON总结已保存: {json_path}") # 保存Markdown md_path = self.docs_path / f'Daily_Summary_{today_id}.md' with open(md_path, 'w', encoding='utf-8') as f: f.write(markdown) print(f"✅ Markdown报告已保存: {md_path}") return json_path, md_path if __name__ == '__main__': # 测试代码 import sys workspace = '/home/ubuntu/nac-workspace' if len(sys.argv) > 1: workspace = sys.argv[1] print(f"NAC Summary Generator") print(f"工作区: {workspace}") print() generator = SummaryGenerator(workspace) print("正在生成今日工作日志...") summary, markdown = generator.generate_summary() print("\n" + "="*60) print("日志生成完成!") print("="*60) print(f"\n统计信息:") print(f" Git提交: {summary['statistics']['total_commits']}") print(f" 代码变更: +{summary['statistics']['total_lines_added']} -{summary['statistics']['total_lines_deleted']}") print(f" 新增记忆: {summary['statistics']['new_documents'] + summary['statistics']['new_problems'] + summary['statistics']['new_decisions']}")