fix(versioning): 压缩继承版本控制并忽略系统目录

This commit is contained in:
JOJO 2026-04-11 17:02:39 +08:00
parent 0ba2763696
commit eba36c46da
2 changed files with 80 additions and 12 deletions

View File

@ -27,6 +27,7 @@ class VersioningPaths:
class ConversationVersioningManager:
"""Manage hidden git snapshots bound to a conversation."""
SYSTEM_AUTO_DIRS = ("compact_result", "skills", "user_upload")
def __init__(self, project_path: Path | str, data_dir: Path | str, conversation_id: str):
self.project_path = Path(project_path).expanduser().resolve()
@ -81,10 +82,6 @@ class ConversationVersioningManager:
def _ensure_exclude_paths(self) -> None:
"""Avoid recursive tracking if save root is inside work tree."""
try:
rel_save = self.paths.save_root.relative_to(self.project_path)
except ValueError:
return
info_exclude = self.paths.git_dir / "info" / "exclude"
info_exclude.parent.mkdir(parents=True, exist_ok=True)
existing = ""
@ -93,18 +90,46 @@ class ConversationVersioningManager:
existing = info_exclude.read_text(encoding="utf-8", errors="ignore")
except OSError:
existing = ""
existing_lines = set(existing.splitlines())
lines_to_add: List[str] = []
try:
rel_save = self.paths.save_root.relative_to(self.project_path)
marker = str(rel_save).replace("\\", "/").rstrip("/")
if not marker:
if marker:
lines_to_add.append(f"{marker}/")
except ValueError:
pass
for dirname in self.SYSTEM_AUTO_DIRS:
clean = str(dirname or "").strip().strip("/").replace("\\", "/")
if not clean:
continue
# 同时忽略根目录与任意层级同名目录
lines_to_add.append(f"/{clean}/")
lines_to_add.append(f"{clean}/")
pending = [line for line in lines_to_add if line not in existing_lines]
if not pending:
return
line = f"{marker}/"
if line not in existing.splitlines():
with info_exclude.open("a", encoding="utf-8") as fh:
if existing and not existing.endswith("\n"):
fh.write("\n")
fh.write(line + "\n")
pending.insert(0, "")
with info_exclude.open("a", encoding="utf-8") as fh:
fh.write("\n".join(pending) + "\n")
def _drop_ignored_from_index(self) -> None:
"""
Ensure ignored system directories are not kept as tracked files in hidden git index.
"""
for dirname in self.SYSTEM_AUTO_DIRS:
clean = str(dirname or "").strip().strip("/").replace("\\", "/")
if not clean:
continue
self._run_git(["rm", "-r", "--cached", "--ignore-unmatch", "--", clean], check=False)
def _stage_all(self) -> None:
self._ensure_exclude_paths()
self._drop_ignored_from_index()
# Stage everything under work tree; exclusions are handled via info/exclude.
self._run_git(["add", "-A", "--", "."])

View File

@ -6,6 +6,8 @@ from datetime import datetime
from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple
from modules.versioning_manager import ConversationVersioningManager
SUMMARY_PROMPT = (
"由于当前对话过长,系统正在自动压缩。请你基于已有上下文输出一份可继续执行的工作总结,要求:\n"
@ -249,6 +251,8 @@ async def run_deep_compression(
return {"success": False, "error": "对话正在压缩中", "in_progress": True}
old_title = conv_data.get("title") or "未命名"
source_versioning = metadata.get("versioning") if isinstance(metadata.get("versioning"), dict) else {}
source_versioning_enabled = bool(source_versioning.get("enabled"))
compression_count = int(metadata.get("compression_count", 0) or 0)
previous_records = _normalize_deep_compression_records(metadata)
previous_max_count = max([int(item.get("count") or 0) for item in previous_records], default=0)
@ -337,6 +341,45 @@ async def run_deep_compression(
"last_deep_compression_record": current_record,
},
)
if source_versioning_enabled:
try:
vm = ConversationVersioningManager(
project_path=workspace.project_path,
data_dir=workspace.data_dir,
conversation_id=new_conv_id,
)
vm_meta = vm.set_enabled(enabled=True, mode="overwrite")
new_conv_data = cm.conversation_manager.load_conversation(new_conv_id) or {}
snapshot_payload = {
"conversation_id": new_conv_id,
"title": new_conv_data.get("title"),
"metadata": new_conv_data.get("metadata") or {},
"messages": new_conv_data.get("messages") or [],
"message_index": -1,
"run_status": "initial",
}
init_result = vm.ensure_initial_checkpoint(
workspace_path=str(workspace.project_path),
conversation_snapshot=snapshot_payload,
)
init_row = init_result.get("row") or {}
last_commit = init_row.get("commit") or vm_meta.get("last_commit")
cm.conversation_manager.update_conversation_metadata(
new_conv_id,
{
"versioning": {
"enabled": True,
"mode": "overwrite",
"updated_at": datetime.now().isoformat(),
"last_commit": last_commit,
"last_input_seq": int(vm_meta.get("last_input_seq") or 0),
}
},
)
except Exception:
pass
cm.conversation_manager.update_conversation_title(new_conv_id, f"{old_title}对话 压缩后")
web_terminal.load_conversation(new_conv_id)
guide_message = _build_guide_message(