fix: seed outfit factory config

This commit is contained in:
2026-06-23 17:51:46 +08:00
parent cad8b61bcf
commit f033943db0
8 changed files with 233 additions and 12 deletions
+87 -3
View File
@@ -130,6 +130,88 @@ def _seed_factory_config_if_missing(filename):
return False
def _factory_config_path(filename):
"""Return the packaged factory config path under the program root."""
from services.file_service import get_app_dir
return get_app_dir() / "config" / filename
def _load_json_file(path):
with open(str(path), encoding="utf-8-sig") as f:
return json.load(f)
def _model_list_from_data(data):
models = data.get("models") if isinstance(data, dict) else data
return models if isinstance(models, list) else None
def _model_name(model):
if not isinstance(model, dict):
return ""
return str(model.get("name", "")).strip()
def _append_missing_title_model(models_file):
"""Append the configured title model from factory ai_models.json if missing.
Existing user models and API keys are never overwritten. This only handles
the upgrade case where a user already has ai_models.json but lacks the new
app_config.title_model entry (docs/11 §6.1).
"""
title_model_name = str(load_config().get("title_model", "")).strip()
if not title_model_name or not models_file.exists():
return False
try:
user_data = _load_json_file(models_file)
except (json.JSONDecodeError, ValueError, OSError) as exc:
logger.warning("AI models file unreadable (%s): %s", exc, models_file)
return False
user_models = _model_list_from_data(user_data)
if user_models is None:
logger.warning("AI models file has no model list: %s", models_file)
return False
if any(_model_name(model) == title_model_name for model in user_models):
return False
factory_file = _factory_config_path(_AI_MODELS_FILENAME)
if not factory_file.exists():
logger.info("Factory AI models template not found: %s", factory_file)
return False
try:
factory_data = _load_json_file(factory_file)
except (json.JSONDecodeError, ValueError, OSError) as exc:
logger.warning("Factory AI models template unreadable (%s): %s", exc, factory_file)
return False
factory_models = _model_list_from_data(factory_data) or []
title_model = None
for model in factory_models:
if _model_name(model) == title_model_name:
title_model = dict(model)
break
if title_model is None:
logger.info(
"Factory AI models template has no title model named %s: %s",
title_model_name,
factory_file,
)
return False
try:
user_models.append(title_model)
with open(str(models_file), "w", encoding="utf-8") as f:
json.dump(user_data, f, ensure_ascii=False, indent=2)
logger.info("Appended missing title model %s to %s", title_model_name, models_file)
return True
except OSError as exc:
logger.warning("Failed to append title model to %s: %s", models_file, exc)
return False
def load_ai_models():
"""Load AI model configs from ai_models.json.
@@ -140,17 +222,17 @@ def load_ai_models():
from services.file_service import get_config_path
_seed_factory_config_if_missing(_AI_MODELS_FILENAME)
models_file = get_config_path(_AI_MODELS_FILENAME)
_append_missing_title_model(models_file)
if not models_file.exists():
logger.info("AI models file not found: %s", models_file)
return []
try:
with open(str(models_file), encoding="utf-8-sig") as f:
data = json.load(f)
data = _load_json_file(models_file)
except (json.JSONDecodeError, ValueError, OSError) as exc:
logger.warning("AI models file unreadable (%s): %s", exc, models_file)
return []
models = data.get("models") if isinstance(data, dict) else data
models = _model_list_from_data(data)
if not isinstance(models, list):
logger.warning("AI models file has no model list: %s", models_file)
return []
@@ -160,6 +242,7 @@ def load_ai_models():
def load_outfit_prompt():
"""Return the saved outfit prompt template, or the built-in default."""
from services.file_service import get_config_path
_seed_factory_config_if_missing(_OUTFIT_PROMPT_FILENAME)
prompt_file = get_config_path(_OUTFIT_PROMPT_FILENAME)
if not prompt_file.exists():
return DEFAULT_OUTFIT_PROMPT
@@ -187,6 +270,7 @@ def save_outfit_prompt(text):
def load_title_prompt():
"""Return the saved 标题生成提示词, or the built-in default (docs/11 §17.3)."""
from services.file_service import get_config_path
_seed_factory_config_if_missing(_TITLE_PROMPT_FILENAME)
prompt_file = get_config_path(_TITLE_PROMPT_FILENAME)
if not prompt_file.exists():
return DEFAULT_TITLE_PROMPT