from pathlib import Path from datetime import datetime import re import yaml def slug(text): text = re.sub(r"[^\w\s-]", "", text.lower(), flags=re.UNICODE) return re.sub(r"[\s_-]+", "-", text).strip("-") or "chat" def chat_path(directory, title): directory.mkdir(parents=True, exist_ok=True) path = directory / f"{datetime.now():%Y-%m-%d}-{slug(title)}.md" number = 2 while path.exists(): path = directory / f"{datetime.now():%Y-%m-%d}-{slug(title)}-{number}.md" number += 1 return path def save(path, title, messages, model): meta = { "title": title, "created": datetime.now().astimezone().isoformat(), "model": model, } out = [ "---", yaml.safe_dump(meta, allow_unicode=True, sort_keys=False).strip(), "---", "", ] for message in messages: role = "You" if message["role"] == "user" else "AI" out += [f"## {role}", "", message["content"].rstrip(), ""] path.write_text("\n".join(out), encoding="utf-8") def load(path): text = path.read_text(encoding="utf-8") title = path.stem if text.startswith("---"): _, meta, body = text.split("---", 2) title = (yaml.safe_load(meta) or {}).get("title", title) text = body messages = [] role = None buffer = [] for line in text.splitlines(): if line == "## You": if role: messages.append({"role": role, "content": "\n".join(buffer).strip()}) role, buffer = "user", [] elif line == "## AI": if role: messages.append({"role": role, "content": "\n".join(buffer).strip()}) role, buffer = "assistant", [] elif role: buffer.append(line) if role: messages.append({"role": role, "content": "\n".join(buffer).strip()}) return title, [m for m in messages if m["content"]]