feat(config): resolve ephemeral prompt from display.personality
Keep agent.system_prompt user-owned; named personalities resolve as an ephemeral overlay via display.personality. Co-authored-by: kyssta-exe <kyssta-exe@users.noreply.github.com> Co-authored-by: EMT5320 <1908937833@qq.com>
This commit is contained in:
parent
99fa93035d
commit
da6f0030ab
|
|
@ -2929,6 +2929,49 @@ def cfg_get(cfg: Optional[Dict[str, Any]], *keys: str, default: Any = None) -> A
|
|||
return node
|
||||
|
||||
|
||||
_NEUTRAL_PERSONALITY_NAMES = frozenset({"", "none", "default", "neutral"})
|
||||
|
||||
|
||||
def _prompt_text(value: Any) -> str:
|
||||
"""Normalize config prompt values from YAML before handing them to AIAgent."""
|
||||
if value is None:
|
||||
return ""
|
||||
if isinstance(value, str):
|
||||
return value.strip()
|
||||
if isinstance(value, list):
|
||||
return "\n".join(str(item).strip() for item in value if str(item).strip())
|
||||
return str(value).strip()
|
||||
|
||||
|
||||
def render_personality_prompt(value: Any) -> str:
|
||||
"""Render a string or structured personality definition to a prompt."""
|
||||
if isinstance(value, dict):
|
||||
parts = [value.get("system_prompt", "")]
|
||||
if value.get("tone"):
|
||||
parts.append(f'Tone: {value["tone"]}')
|
||||
if value.get("style"):
|
||||
parts.append(f'Style: {value["style"]}')
|
||||
return "\n".join(str(part).strip() for part in parts if str(part).strip())
|
||||
return _prompt_text(value)
|
||||
|
||||
|
||||
def resolve_ephemeral_system_prompt_from_config(cfg: Optional[Dict[str, Any]]) -> str:
|
||||
"""Resolve the session overlay from config.yaml.
|
||||
|
||||
``display.personality`` is the selected named personality and wins when set.
|
||||
Otherwise fall back to the user-owned ``agent.system_prompt``. Callers should
|
||||
still prefer ``HERMES_EPHEMERAL_SYSTEM_PROMPT`` when that env var is set.
|
||||
"""
|
||||
name = str(cfg_get(cfg, "display", "personality", default="") or "").strip().lower()
|
||||
personalities = cfg_get(cfg, "agent", "personalities", default={}) or {}
|
||||
if (
|
||||
name not in _NEUTRAL_PERSONALITY_NAMES
|
||||
and isinstance(personalities, dict)
|
||||
and name in personalities
|
||||
):
|
||||
return render_personality_prompt(personalities[name])
|
||||
return _prompt_text(cfg_get(cfg, "agent", "system_prompt", default=""))
|
||||
|
||||
|
||||
def read_raw_config() -> Dict[str, Any]:
|
||||
"""Read ~/.hermes/config.yaml as-is, without merging defaults or migrating.
|
||||
|
|
|
|||
Loading…
Reference in New Issue