485 lines
17 KiB
Python
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']}")
|