NAC_Blockchain/memory/tools/summary_generator.py

485 lines
17 KiB
Python

#!/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']}")