Add initial web editor app, CLI scripts, and test scaffolding.
This introduces the FastAPI editor implementation and related project setup so the app can be run and validated locally. Made-with: Cursor
This commit is contained in:
57
lib/helpers.py
Normal file
57
lib/helpers.py
Normal file
@@ -0,0 +1,57 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime, timezone
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
def utc_now_iso() -> str:
|
||||
"""Return current UTC time in ISO-8601 format."""
|
||||
return datetime.now(timezone.utc).isoformat()
|
||||
|
||||
|
||||
def log(message: str) -> None:
|
||||
"""Print a timestamped log line."""
|
||||
print(f"[{utc_now_iso()}] {message}")
|
||||
|
||||
|
||||
def get_workspace_root(current_file: str | Path) -> Path:
|
||||
"""Infer workspace root from a script path inside code/."""
|
||||
current = Path(current_file).resolve()
|
||||
return current.parents[1]
|
||||
|
||||
|
||||
def get_prompt_dir(workspace_root: Path, prompt_folder: str) -> Path:
|
||||
"""Resolve prompts/<prompt_folder> directory safely."""
|
||||
folder = prompt_folder.strip().strip("/")
|
||||
if not folder:
|
||||
raise ValueError("Prompt folder argument is empty")
|
||||
target = (workspace_root / "prompts" / folder).resolve()
|
||||
prompts_root = (workspace_root / "prompts").resolve()
|
||||
if prompts_root not in target.parents and target != prompts_root:
|
||||
raise ValueError("Prompt folder escapes prompts root")
|
||||
if not target.exists() or not target.is_dir():
|
||||
raise FileNotFoundError(f"Prompt folder not found: {target}")
|
||||
return target
|
||||
|
||||
|
||||
def read_prompt_texts(prompt_dir: Path) -> dict[str, str]:
|
||||
"""Read all .txt files from prompt directory."""
|
||||
result: dict[str, str] = {}
|
||||
for txt_file in sorted(prompt_dir.glob("*.txt")):
|
||||
result[txt_file.name] = txt_file.read_text(encoding="utf-8")
|
||||
return result
|
||||
|
||||
|
||||
def read_json(path: Path, default: Any = None) -> Any:
|
||||
"""Read JSON file; return default when missing."""
|
||||
if not path.exists():
|
||||
return default
|
||||
return json.loads(path.read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
def write_json(path: Path, data: Any) -> None:
|
||||
"""Write JSON with stable formatting."""
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(json.dumps(data, indent=2, sort_keys=True), encoding="utf-8")
|
||||
Reference in New Issue
Block a user