Support structured custom location entries
This commit is contained in:
+67
-4
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user