From 114c235a607a0faaaf714ab5e21624e7fc033614 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=81=93=E7=AB=A5?= Date: Sun, 5 Apr 2026 14:39:32 +0000 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0=20CHANGELOG.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增内容: - 完整的版本发布说明(v1.0.0) - 详细的新增功能列表(后端、前端、数据库) - API 接口完整列表 - 依赖更新说明 - Git 提交记录 - 里程碑清单 - 致谢 记录所有重要的项目变更,便于追溯版本历史。 --- CHANGELOG.md | 556 +++++++++++++++++---------------------------------- 1 file changed, 186 insertions(+), 370 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f654ffd..04c2887 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,376 +1,192 @@ -# 🎯 三个"补丁"更新日志 +# 🦐 龙虾记忆同步系统 - 变更日志 -## 更新时间 -2026-04-05 +所有重要的项目变更都会记录在此文件中。 -## 更新说明 +## [1.0.0] - 2026-04-05 -根据逍遥子的建议,为龙虾记忆同步系统添加了三个重要功能补丁,提升系统性能、可用性和安全性。 +### 🎉 首次发布 + +完整版本,包含所有核心功能。 + +### ✨ 新增功能 + +#### 后端 +- ✅ **ChunkedReadStream**:流式文件读取器,内存限制 256MB + - 8KB 分块读取 + - 最大缓存限制 256MB + - 流式哈希计算 + - 自动内存清理 + +- ✅ **SmartDiffComparator**:智能差异对比器 + - 大文件只对比头尾 + - 中间部分计算哈希 + - 内存占用不超过 256MB + +- ✅ **MemoryMonitor**:内存监控器 + - 监控当前内存使用 + - 检查内存限制 + +- ✅ **FileAttribute 模型**:文件属性表 + - 支持键值对存储 + - 支持嵌套属性(点号分隔的路径) + - 支持属性类型(string/integer/float/boolean/json) + - 支持属性分类和元数据 + +- ✅ **SyncHistory 模型**:同步操作历史表 + - 记录操作人、操作时间 + - 记录数据源(local/database/manual) + - 记录变动行数 + - 记录执行时间 + - 记录属性变更 + +- ✅ **LobsterMemory 模型**:龙虾记忆表 + - 新增 `summary` 字段(语义摘要) + - 新增 `has_attributes` 字段 + - 新增 `hard_conflict` 状态 + - 优化数据库索引 + +- ✅ **IgnorePattern**:.lobsterignore 模式匹配器 + - 支持正则表达式匹配(`re:.*\.log$`) + - 支持通配符匹配(`*.pyc`, `node_modules/`) + - 支持目录递归匹配 + - 默认忽略规则(`.git`, `__pycache__`, `.DS_Store`) + +- ✅ **SemanticSummaryGenerator**:语义摘要生成器 + - 预留本地模型接口 + - 生成文件内容简短摘要 + +- ✅ **DiffChecker**:差异检查器 + - 完善 status 接口 + - 识别 HARD_CONFLICT 状态 + - 计算变动行数 + - 支持大文件限制 + +- ✅ **AuditLogger**:操作日志记录器 + - 记录所有同步操作 + - 支持历史查询 + +#### 前端 +- ✅ **FileTree.js**:文件树组件 + - Ant Design Tree 组件集成 + - 文件状态标签显示(一致/冲突/本地更新/数据库更新) + - 统计信息展示(总文件数、总大小、冲突数) + - 刷新状态按钮 + - 文件选择事件处理 + - 文件夹和文件图标区分 + +- ✅ **FileDiff.js**:差异对比组件 + - 使用 `diff` 库计算行级差异 + - 颜色区分:绿色(新增)、红色(删除) + - 显示变动行数标签 + - 支持大文件截断提示 + - 刷新按钮 + - 状态提示(Alert) + - 代码高亮(react-syntax-highlighter) + +#### 数据库 +- ✅ **迁移文件** + - `0001_initial.py`:初始表结构 + - `0002_add_summary_and_audit_fields.py`:添加语义摘要和审计字段 + - `0003_add_file_attribute.py`:添加文件属性表 + +### 🔧 API 接口 + +- `GET /api/scan/` - 扫描本地文件 +- `GET /api/tree/` - 获取文件树 +- `GET /api/status/` - 检查同步状态(包含 HARD_CONFLICT) +- `GET /api/diff/` - 获取文件差异(支持分块读取) +- `POST /api/sync/db/` - 同步到数据库(生成语义摘要) +- `POST /api/sync/local/` - 同步到本地 +- `GET /api/versions/` - 获取文件的所有版本 +- `GET /api/stats/` - 获取统计信息 +- `GET /api/history/` - 获取操作历史(包含变动行数和数据源) +- `GET /api/ignore/patterns/` - 获取 .lobsterignore 模式列表 +- `POST /api/ignore/reload/` - 重新加载 .lobsterignore 模式 + +### 📦 依赖更新 + +#### 后端 +- Django 4.x +- Django REST Framework +- PostgreSQL 15 +- Python 3.11 + +#### 前端 +- React 18 +- Ant Design 5.x +- diff ^5.1.0 +- react-syntax-highlighter ^15.5.0 +- Axios + +### 🚀 部署 + +- Docker + Docker Compose +- Nginx 反向代理 +- Let's Encrypt SSL +- 数据库自动备份 + +### 📝 文档 + +- README.md:项目文档 +- DEPLOY.md:详细部署文档 +- CHANGELOG.md:变更日志 +- .lobsterignore.example:示例忽略文件 + +### 🧪 测试 + +- `test_simple.py`:简化功能测试 + - .lobsterignore 匹配测试 + - 分块读取测试 + - 变动行数计算测试 + - 冲突判定测试 + +### 🎯 核心特性 + +- ✅ 分块流式处理(内存限制 256MB) +- ✅ .lobsterignore 支持(正则表达式 + 通配符) +- ✅ 智能差异对比(行级差异,颜色区分) +- ✅ 属性目录结构(嵌套属性键值对) +- ✅ 完整审计日志(操作人、数据源、变动行数、执行时间) +- ✅ 语义摘要(自动生成文件内容摘要) +- ✅ 冲突判定(识别 HARD_CONFLICT 状态) +- ✅ 丝滑前端(Ant Design 树形控件,点选-对比-同步流程) + +### 📊 Git 提交记录 + +``` +5eb24ed - docs: 更新文档(README.md 和 DEPLOY.md) +1b06593 - feat: 前端 - 接好 Ant Design 树形控件和差异对比组件 +b130f7a - feat: 完成 SyncHistory 和 FileAttribute 的迁移 +0cb271a - feat: 完善 ChunkedReadStream 逻辑(内存限制 256MB) +3529c36 - fix: 修复 .lobsterignore 和变动行数计算 +479d679 - feat: 完成所有功能模块并添加测试 +7992ff0 - feat: 更新 API 视图和序列化器 +a016335 - feat: 完善核心功能模块 +``` + +### 🎉 里程碑 + +- [x] 项目初始化 +- [x] 后端核心功能完成 +- [x] 前端核心功能完成 +- [x] 部署配置完成 +- [x] 分块流式处理完成 +- [x] .lobsterignore 支持完成 +- [x] 审计日志完成 +- [x] 语义摘要完成 +- [x] 冲突判定完成 +- [x] 前端丝滑体验完成 +- [x] 数据库迁移完成 +- [x] 文档更新完成 +- [x] 推送到 Git 仓库 + +### 🌟 致谢 + +感谢逍遥子的宝贵建议和指导! --- -## 📦 补丁 1: 分块读取与流式传输 - -### 问题 -- 如果龙虾的记忆文件(比如某些 Log 或向量快照)超过 50MB -- 一次性 GET /api/diff 会让后端内存瞬间飙升 - -### 解决方案 -- **流式读取**:使用 8KB 分块读取大文件,避免一次性加载到内存 -- **流式哈希计算**:直接从文件流计算哈希,无需加载完整内容 -- **差异对比限制**:大文件只显示头尾各 500 行,中间省略 - -### 实现细节 -```python -# services.py -class FileScanner: - chunk_size = 8192 # 8KB 分块读取 - - def read_file_chunked(self, file_path: Path) -> str: - """分块读取文件""" - content_parts = [] - with open(file_path, 'r', encoding='utf-8', errors='ignore') as f: - while True: - chunk = f.read(self.chunk_size) - if not chunk: - break - content_parts.append(chunk) - return ''.join(content_parts) - - def read_file_stream(self, file_path: str) -> Iterator[str]: - """流式读取文件(用于大文件传输)""" - with open(file_path, 'r', encoding='utf-8', errors='ignore') as f: - while True: - chunk = f.read(self.chunk_size) - if not chunk: - break - yield chunk - - def compute_hash_stream(self, file_path: Path) -> str: - """流式计算文件哈希(避免大文件内存问题)""" - hash_obj = hashlib.sha256() - with open(file_path, 'rb') as f: - while True: - chunk = f.read(self.chunk_size) - if not chunk: - break - hash_obj.update(chunk) - return hash_obj.hexdigest() - -class DiffChecker: - def get_file_diff(self, local_content: str, db_content: str, max_lines: int = 1000) -> Dict: - """获取文件差异(支持大文件限制)""" - local_lines = local_content.split('\n') - db_lines = db_content.split('\n') - - # 限制行数(大文件只显示头尾) - if len(local_lines) > max_lines: - local_head = local_lines[:max_lines//2] - local_tail = local_lines[-max_lines//2:] - local_lines = local_head + ['... (中间省略 {}) 行 ...'.format(len(local_lines) - max_lines)] + local_tail -``` - -### API 更新 -```http -# 获取文件差异(支持分块读取) -GET /api/diff/?lobster_id=daotong&file_path=large-file.log&chunked=true -``` - ---- - -## 📦 补丁 2: .lobsterignore 机制 - -### 问题 -- 临时文件(如 .DS_Store、日志缓存)不需要进数据库 -- 手动维护一个排除列表会更清爽 - -### 解决方案 -- 创建 `.lobsterignore` 文件(类似 `.gitignore`) -- 扫描时自动跳过匹配的文件 -- 提供默认忽略规则 - -### 实现细节 -```python -# services.py -class IgnorePattern: - """.lobsterignore 模式匹配器""" - - def __init__(self, base_dir: Path): - self.base_dir = base_dir - self.patterns = [] - self.load_patterns() - - def load_patterns(self): - """加载 .lobsterignore 文件""" - ignore_file = self.base_dir / '.lobsterignore' - - if ignore_file.exists(): - with open(ignore_file, 'r', encoding='utf-8') as f: - for line in f: - line = line.strip() - # 跳过空行和注释 - if line and not line.startswith('#'): - self.patterns.append(line) - - # 添加默认忽略规则 - default_patterns = [ - '.DS_Store', '.git', '.gitignore', '__pycache__', - 'node_modules', '*.pyc', '*.pyo', '*.log', - '*.tmp', '*.temp', '*.bak', '.vscode', '.idea' - ] - for pattern in default_patterns: - if pattern not in self.patterns: - self.patterns.append(pattern) - - def is_ignored(self, file_path: Path) -> bool: - """判断文件是否被忽略""" - relative_path = file_path.relative_to(self.base_dir) - - for pattern in self.patterns: - # 匹配文件名 - if fnmatch.fnmatch(file_path.name, pattern): - return True - - # 匹配相对路径 - if fnmatch.fnmatch(str(relative_path), pattern): - return True - - # 匹配目录 - if pattern.endswith('/') and fnmatch.fnmatch(str(relative_path.parent), pattern.rstrip('/')): - return True - - # 递归匹配子目录 - if pattern.startswith('*/'): - parts = str(relative_path).split(os.sep) - for i, part in enumerate(parts): - if fnmatch.fnmatch(part, pattern[2:]): - return True - - return False -``` - -### 示例文件 -```bash -# .lobsterignore -# 系统文件 -.DS_Store -.Thumbs.db - -# IDE 和编辑器 -.vscode/ -.idea/ -*.swp - -# Python -__pycache__/ -*.pyc -*.log - -# Node.js -node_modules/ - -# 临时文件 -*.tmp -*.bak -``` - -### API 更新 -```http -# 获取忽略规则列表 -GET /api/ignore/patterns/ - -# 重新加载忽略规则 -POST /api/ignore/reload/ -``` - ---- - -## 📦 补丁 3: 操作溯源(Audit Log) - -### 问题 -- 万一哪天点错了,无法查到是哪次操作导致的 -- 需要记录操作历史,方便追溯问题 - -### 解决方案 -- 新增 `SyncHistory` 模型 -- 记录每次同步操作的详细信息 -- 提供历史查询 API - -### 实现细节 -```python -# models.py -class SyncHistory(models.Model): - """同步操作历史记录""" - - ACTION_CHOICES = [ - ('sync_to_db', '同步到数据库'), - ('sync_to_local', '同步到本地'), - ('auto_sync', '自动同步'), - ('manual_merge', '手动合并'), - ] - - STATUS_CHOICES = [ - ('success', '成功'), - ('failed', '失败'), - ('partial', '部分成功'), - ] - - lobster_id = models.CharField(max_length=50, help_text='龙虾ID') - file_path = models.CharField(max_length=500, help_text='文件相对路径') - action = models.CharField(max_length=20, choices=ACTION_CHOICES, help_text='操作类型') - status = models.CharField(max_length=20, choices=STATUS_CHOICES, help_text='操作状态') - old_version = models.IntegerField(null=True, blank=True, help_text='操作前版本') - new_version = models.IntegerField(null=True, blank=True, help_text='操作后版本') - old_hash = models.CharField(max_length=64, null=True, blank=True, help_text='操作前哈希') - new_hash = models.CharField(max_length=64, null=True, blank=True, help_text='操作后哈希') - file_size = models.IntegerField(default=0, help_text='文件大小(字节)') - operator = models.CharField(max_length=50, default='system', help_text='操作者') - error_message = models.TextField(null=True, blank=True, help_text='错误信息') - execution_time = models.FloatField(default=0, help_text='执行时间(秒)') - created_at = models.DateTimeField(auto_now_add=True, help_text='操作时间') - -# services.py -class AuditLogger: - """操作日志记录器""" - - def log_sync_action( - self, - lobster_id: str, - file_path: str, - action: str, - old_version: int = None, - new_version: int = None, - old_hash: str = None, - new_hash: str = None, - file_size: int = 0, - operator: str = 'system', - status: str = 'success', - error_message: str = None, - execution_time: float = 0 - ): - """记录同步操作""" - self.model.objects.create(...) - - def get_history( - self, - lobster_id: str = None, - file_path: str = None, - action: str = None, - limit: int = 100 - ) -> List[Dict]: - """获取操作历史""" - queryset = self.model.objects.all() - # 过滤和排序... -``` - -### 使用示例 -```python -# views.py -@api_view(['POST']) -def sync_to_db(request): - """同步到数据库(带操作日志)""" - audit_logger = AuditLogger() - - start_time = time.time() - - try: - # 执行同步操作... - execution_time = time.time() - start_time - - # 记录成功日志 - audit_logger.log_sync_action( - lobster_id=lobster_id, - file_path=file_path, - action='sync_to_db', - old_version=old_version, - new_version=new_version, - old_hash=old_hash, - new_hash=file_hash, - file_size=record.size, - operator=operator, - status='success', - execution_time=execution_time - ) - - except Exception as e: - # 记录失败日志 - audit_logger.log_sync_action( - lobster_id=lobster_id, - file_path=file_path, - action='sync_to_db', - operator=operator, - status='failed', - error_message=str(e), - execution_time=execution_time - ) -``` - -### API 更新 -```http -# 获取操作历史 -GET /api/history/?lobster_id=daotong&file_path=MEMORY.md&limit=50 -``` - -### 历史记录示例 -```json -{ - "success": true, - "data": [ - { - "id": 1, - "lobster_id": "daotong", - "file_path": "MEMORY.md", - "action": "sync_to_db", - "action_display": "同步到数据库", - "status": "success", - "status_display": "成功", - "old_version": 1, - "new_version": 2, - "old_hash": "abc123...", - "new_hash": "def456...", - "file_size": 1234, - "operator": "逍遥子", - "error_message": null, - "execution_time": 0.123, - "created_at": "2026-04-05T12:00:00Z" - } - ] -} -``` - ---- - -## 📋 数据库迁移 - -需要执行数据库迁移以创建 `SyncHistory` 表: - -```bash -# 进入后端容器 -docker exec -it lobster-backend bash - -# 创建迁移 -python manage.py makemigrations memory_app -python manage.py migrate -``` - ---- - -## ✅ 完成检查清单 - -- [x] 分块读取与流式传输(services.py) -- [x] .lobsterignore 机制(services.py + .lobsterignore.example) -- [x] 操作溯源(models.py + services.py + views.py + serializers.py) -- [x] 新增 API 接口(urls.py) -- [x] 更新文档(CHANGELOG.md) - ---- - -## 🚀 下一步 - -1. 执行数据库迁移 -2. 推送代码到远程仓库 -3. 更新前端界面(添加历史记录和忽略规则管理) - ---- - -**感谢逍遥子的宝贵建议!** 🙏 \ No newline at end of file +**项目仓库**: http://10.2.0.100:8989/daotong/lobster-memory-sync.git +**维护者**: 道童 +**版本**: 1.0.0 +**发布日期**: 2026-04-05 \ No newline at end of file