Files
kb/engine/kb/staging.py
T
steve bb78f4ea80 Fix 500 error on notes with slashes in title, bump engine to 3.2.1
Sanitize / and \ in note titles and filenames when writing to the
staging directory — a title like "/reset skill" was interpreted as a
path separator, causing a FileNotFoundError and a 500 from the jobs
endpoint. Also add PRAGMA busy_timeout=5000 to SQLite connections to
prevent immediate failure under concurrent write load.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 16:12:58 +01:00

50 lines
1.6 KiB
Python

"""Staging area for files awaiting ingestion."""
import logging
import uuid
from pathlib import Path
logger = logging.getLogger("kb.staging")
def stage_file(staging_dir: Path, filename: str, content: bytes) -> Path:
"""Write raw bytes to a uniquely-named file in the staging directory.
The staged file is named ``{uuid}_{filename}`` to avoid collisions.
Returns:
The path to the newly created staged file.
"""
staging_dir.mkdir(parents=True, exist_ok=True)
safe_filename = filename.replace("/", "_").replace("\\", "_")
dest = staging_dir / f"{uuid.uuid4()}_{safe_filename}"
dest.write_bytes(content)
logger.debug("Staged file: %s (%d bytes)", dest, len(content))
return dest
def stage_note(staging_dir: Path, title: str, text: str) -> Path:
"""Write a text note to the staging directory.
The staged file is named ``{uuid}_{title}.note``.
Returns:
The path to the newly created staged note file.
"""
staging_dir.mkdir(parents=True, exist_ok=True)
safe_title = title.replace("/", "_").replace("\\", "_")
dest = staging_dir / f"{uuid.uuid4()}_{safe_title}.note"
dest.write_text(text, encoding="utf-8")
logger.debug("Staged note: %s (%d chars)", dest, len(text))
return dest
def cleanup(path: Path) -> None:
"""Delete a staged file if it exists. Logs a warning on failure."""
try:
if path.exists():
path.unlink()
logger.debug("Cleaned up staged file: %s", path)
except OSError as exc:
logger.warning("Failed to clean up staged file %s: %s", path, exc)