2026-03-31 04:31:47 +00:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
from typing import Any, Dict, List
|
|
|
|
|
|
2026-04-13 08:36:58 +00:00
|
|
|
from core.settings import (
|
|
|
|
|
AGENT_MD_TEMPLATES_FILE,
|
|
|
|
|
BUNDLED_AGENT_MD_TEMPLATES_FILE,
|
|
|
|
|
BUNDLED_TOPIC_PRESETS_TEMPLATES_FILE,
|
|
|
|
|
TOPIC_PRESETS_TEMPLATES_FILE,
|
|
|
|
|
)
|
2026-03-31 04:31:47 +00:00
|
|
|
|
|
|
|
|
TEMPLATE_KEYS = ("agents_md", "soul_md", "user_md", "tools_md", "identity_md")
|
|
|
|
|
|
|
|
|
|
|
2026-04-13 08:36:58 +00:00
|
|
|
def _load_json_object(path: str, fallback_path: str = "") -> Dict[str, Any]:
|
2026-03-31 04:31:47 +00:00
|
|
|
import json
|
|
|
|
|
|
2026-04-13 08:36:58 +00:00
|
|
|
for candidate in [path, fallback_path]:
|
|
|
|
|
candidate = str(candidate or "").strip()
|
|
|
|
|
if not candidate:
|
|
|
|
|
continue
|
|
|
|
|
try:
|
|
|
|
|
with open(candidate, "r", encoding="utf-8") as file:
|
|
|
|
|
data = json.load(file)
|
|
|
|
|
if isinstance(data, dict):
|
|
|
|
|
return data
|
|
|
|
|
except Exception:
|
|
|
|
|
continue
|
2026-03-31 04:31:47 +00:00
|
|
|
return {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _normalize_md_text(value: Any) -> str:
|
|
|
|
|
return str(value or "").replace("\r\n", "\n").strip()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _write_json_atomic(path: str, payload: Dict[str, Any]) -> None:
|
|
|
|
|
import json
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
|
|
os.makedirs(os.path.dirname(path), exist_ok=True)
|
|
|
|
|
tmp_path = f"{path}.tmp"
|
|
|
|
|
with open(tmp_path, "w", encoding="utf-8") as file:
|
|
|
|
|
json.dump(payload, file, ensure_ascii=False, indent=2)
|
|
|
|
|
os.replace(tmp_path, path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_agent_md_templates() -> Dict[str, str]:
|
2026-04-13 08:36:58 +00:00
|
|
|
raw = _load_json_object(str(AGENT_MD_TEMPLATES_FILE), str(BUNDLED_AGENT_MD_TEMPLATES_FILE))
|
2026-03-31 04:31:47 +00:00
|
|
|
return {key: _normalize_md_text(raw.get(key)) for key in TEMPLATE_KEYS}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_topic_presets() -> Dict[str, Any]:
|
2026-04-13 08:36:58 +00:00
|
|
|
raw = _load_json_object(str(TOPIC_PRESETS_TEMPLATES_FILE), str(BUNDLED_TOPIC_PRESETS_TEMPLATES_FILE))
|
2026-03-31 04:31:47 +00:00
|
|
|
presets = raw.get("presets")
|
|
|
|
|
if not isinstance(presets, list):
|
|
|
|
|
return {"presets": []}
|
|
|
|
|
return {"presets": [dict(row) for row in presets if isinstance(row, dict)]}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def update_agent_md_templates(raw: Dict[str, Any]) -> Dict[str, str]:
|
|
|
|
|
payload = {key: _normalize_md_text(raw.get(key)) for key in TEMPLATE_KEYS}
|
|
|
|
|
_write_json_atomic(str(AGENT_MD_TEMPLATES_FILE), payload)
|
|
|
|
|
return payload
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def update_topic_presets(raw: Dict[str, Any]) -> Dict[str, Any]:
|
|
|
|
|
presets = raw.get("presets") if isinstance(raw, dict) else None
|
|
|
|
|
if presets is None:
|
|
|
|
|
payload: Dict[str, List[Dict[str, Any]]] = {"presets": []}
|
|
|
|
|
elif isinstance(presets, list):
|
|
|
|
|
payload = {"presets": [dict(row) for row in presets if isinstance(row, dict)]}
|
|
|
|
|
else:
|
|
|
|
|
raise ValueError("topic_presets.presets must be an array")
|
|
|
|
|
_write_json_atomic(str(TOPIC_PRESETS_TEMPLATES_FILE), payload)
|
|
|
|
|
return payload
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_agent_template_value(key: str) -> str:
|
|
|
|
|
return get_agent_md_templates().get(key, "")
|