Files
memory-gateway/memory_gateway/obsidian_review.py
2026-05-05 16:18:31 +08:00

78 lines
2.3 KiB
Python

"""Obsidian review draft writer."""
from __future__ import annotations
import re
from datetime import datetime, timezone
from pathlib import Path
from .config import get_config
from .schemas import MemoryRecord
def _slugify(value: str, fallback: str) -> str:
slug = re.sub(r"[^a-zA-Z0-9\u4e00-\u9fff_-]+", "-", value.lower()).strip("-")
slug = re.sub(r"-+", "-", slug)[:80].strip("-")
return slug or fallback
def write_review_draft(memory: MemoryRecord, reason: str, conflict_ids: list[str] | None = None) -> Path:
config = get_config()
review_dir = getattr(config.obsidian, "review_dir", "Reviews/Queue")
vault_path = Path(config.obsidian.vault_path)
target_dir = vault_path / review_dir
target_dir.mkdir(parents=True, exist_ok=True)
title = memory.summary or memory.content[:80] or memory.id
filename = f"{_slugify(title, memory.id)}-{memory.id}.md"
path = target_dir / filename
conflict_ids = conflict_ids or []
content = "\n".join(
[
"---",
"type: memory_review",
f"memory_id: {memory.id}",
f"user_id: {memory.user_id}",
f"agent_id: {memory.agent_id or ''}",
f"workspace_id: {memory.workspace_id or ''}",
f"namespace: {memory.namespace}",
f"visibility: {memory.visibility.value}",
f"importance: {memory.importance}",
f"confidence: {memory.confidence}",
f"reason: {reason}",
f"created_at: {datetime.now(timezone.utc).isoformat()}",
"tags:",
" - memory/review",
" - source/evermemos",
"---",
"",
f"# Memory Review - {title}",
"",
"## Candidate",
"",
memory.content,
"",
"## Summary",
"",
memory.summary or "",
"",
"## Proposed Action",
"",
"- [ ] Accept",
"- [ ] Edit",
"- [ ] Reject",
"- [ ] Merge",
"- [ ] Archive",
"",
"## Conflict IDs",
"",
"\n".join(f"- {memory_id}" for memory_id in conflict_ids) if conflict_ids else "- none",
"",
"## Notes",
"",
]
)
path.write_text(content, encoding="utf-8")
return path