678110d9e9
Multi-stage Dockerfile builds the React frontend then serves everything from a single Python container. settings.json persists via a named volume. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
75 lines
1.7 KiB
Python
75 lines
1.7 KiB
Python
import json
|
|
import os
|
|
import secrets
|
|
from datetime import datetime, timezone
|
|
from pathlib import Path
|
|
|
|
SETTINGS_PATH = Path(os.environ.get("SETTINGS_PATH", Path(__file__).parent.parent / "settings.json"))
|
|
|
|
|
|
def _now():
|
|
return datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
|
|
|
|
|
|
def _read():
|
|
if not SETTINGS_PATH.exists():
|
|
return {"openai_api_key": "", "presets": []}
|
|
return json.loads(SETTINGS_PATH.read_text(encoding="utf-8"))
|
|
|
|
|
|
def _write(data):
|
|
tmp = SETTINGS_PATH.with_suffix(".tmp")
|
|
tmp.write_text(json.dumps(data, indent=2), encoding="utf-8")
|
|
tmp.replace(SETTINGS_PATH)
|
|
|
|
|
|
def list_presets():
|
|
return _read()["presets"]
|
|
|
|
|
|
def create_preset(name, description, template, variables):
|
|
data = _read()
|
|
preset = {
|
|
"id": secrets.token_hex(4),
|
|
"name": name,
|
|
"description": description,
|
|
"template": template,
|
|
"variables": variables,
|
|
"created_at": _now(),
|
|
"updated_at": _now(),
|
|
}
|
|
data["presets"].append(preset)
|
|
_write(data)
|
|
return preset
|
|
|
|
|
|
def update_preset(preset_id, fields):
|
|
data = _read()
|
|
for p in data["presets"]:
|
|
if p["id"] == preset_id:
|
|
p.update(fields)
|
|
p["updated_at"] = _now()
|
|
_write(data)
|
|
return p
|
|
return None
|
|
|
|
|
|
def delete_preset(preset_id):
|
|
data = _read()
|
|
before = len(data["presets"])
|
|
data["presets"] = [p for p in data["presets"] if p["id"] != preset_id]
|
|
if len(data["presets"]) == before:
|
|
return False
|
|
_write(data)
|
|
return True
|
|
|
|
|
|
def get_openai_key():
|
|
return _read().get("openai_api_key", "")
|
|
|
|
|
|
def set_openai_key(key: str):
|
|
data = _read()
|
|
data["openai_api_key"] = key
|
|
_write(data)
|