Support structured custom location entries

This commit is contained in:
2026-06-27 13:36:39 +02:00
parent 17c6d34784
commit 194eb06465
4 changed files with 175 additions and 6 deletions
+67 -4
View File
@@ -268,12 +268,57 @@ def location_pool_names_for_preset(preset: str) -> list[str]:
return names
def custom_location_entries(custom_locations: str) -> list[dict[str, str]]:
entries: list[dict[str, str]] = []
def entry_prompt_text(value: Any) -> str:
if isinstance(value, dict):
return str(
value.get("prompt")
or value.get("template")
or value.get("text")
or value.get("description")
or value.get("name")
or ""
).strip()
return str(value or "").strip()
def json_line_entries(line: str, field_name: str) -> list[Any] | None:
line = line.strip()
if not line or line[0] not in "[{":
return None
try:
parsed = json.loads(line)
except json.JSONDecodeError as exc:
raise ValueError(f"Invalid JSON line in {field_name}: {exc}") from exc
if isinstance(parsed, list):
return parsed
return [parsed]
def normalize_custom_location_entry(value: Any) -> dict[str, Any]:
if isinstance(value, dict):
entry = dict(value)
prompt = entry_prompt_text(entry)
if not prompt:
raise ValueError(f"Custom location JSON entry is missing prompt/text/description/name: {value!r}")
entry["slug"] = _slug(str(entry.get("slug") or entry.get("name") or prompt))
entry["prompt"] = prompt
return entry
prompt = str(value or "").strip()
if not prompt:
raise ValueError("Custom location entry cannot be empty")
return {"slug": _slug(prompt), "prompt": prompt}
def custom_location_entries(custom_locations: str) -> list[dict[str, Any]]:
entries: list[dict[str, Any]] = []
for raw_line in str(custom_locations or "").splitlines():
line = raw_line.strip()
if not line or line.startswith("#"):
continue
json_entries = json_line_entries(line, "custom_locations")
if json_entries is not None:
entries.extend(normalize_custom_location_entry(entry) for entry in json_entries)
continue
slug = ""
prompt = line
if ":" in line:
@@ -389,12 +434,30 @@ def composition_pool_names_for_preset(preset: str) -> list[str]:
return names
def custom_composition_entries(custom_compositions: str) -> list[str]:
entries: list[str] = []
def normalize_custom_composition_entry(value: Any) -> Any:
if isinstance(value, dict):
entry = dict(value)
prompt = entry_prompt_text(entry)
if not prompt:
raise ValueError(f"Custom composition JSON entry is missing prompt/text/description/name: {value!r}")
entry["prompt"] = prompt
return entry
text = str(value or "").strip()
if not text:
raise ValueError("Custom composition entry cannot be empty")
return text
def custom_composition_entries(custom_compositions: str) -> list[Any]:
entries: list[Any] = []
for raw_line in str(custom_compositions or "").splitlines():
line = raw_line.strip()
if not line or line.startswith("#"):
continue
json_entries = json_line_entries(line, "custom_compositions")
if json_entries is not None:
entries.extend(normalize_custom_composition_entry(entry) for entry in json_entries)
continue
entries.append(line)
return entries