Move HA user agent routing to options
This commit is contained in:
@@ -2,20 +2,14 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
from typing import Any
|
||||
|
||||
DEFAULT_CHAT_AGENT_ID = "tetra-home"
|
||||
SYSTEM_HA_USER_ID = "system"
|
||||
|
||||
HA_USER_AGENT_MAP: dict[str, str] = {
|
||||
# TODO: Move this user-to-agent map into config entry options.
|
||||
"bd3f666f43f941e886ef007a794eefe8": "main",
|
||||
"1d2be9a622584cf0abb1c243d12a9959": "family-krzysztof",
|
||||
"eca5887898544556840878ab37a35fbc": "family-ewa",
|
||||
"2f5bf9f09478400082380bf7f26966d9": "family-tosia",
|
||||
"f613d90efe8b4afea63c4a5a7ef7b559": "family-domi",
|
||||
}
|
||||
DEFAULT_HA_USER_AGENT_MAP: dict[str, str] = {}
|
||||
|
||||
|
||||
def normalize_optional_text(value: Any) -> str | None:
|
||||
@@ -34,12 +28,55 @@ def normalize_ha_user_id(value: Any) -> str:
|
||||
def resolve_agent_id(
|
||||
ha_user_id: str | None,
|
||||
explicit_agent_id: str | None = None,
|
||||
user_agent_map: Any = None,
|
||||
fallback_agent_id: str | None = None,
|
||||
) -> str:
|
||||
"""Resolve the OpenClaw agent for a Home Assistant user."""
|
||||
if explicit_agent_id:
|
||||
return explicit_agent_id
|
||||
normalized_user_id = normalize_ha_user_id(ha_user_id)
|
||||
return HA_USER_AGENT_MAP.get(normalized_user_id, DEFAULT_CHAT_AGENT_ID)
|
||||
try:
|
||||
routing_map = parse_user_agent_map(user_agent_map)
|
||||
except ValueError:
|
||||
routing_map = dict(DEFAULT_HA_USER_AGENT_MAP)
|
||||
fallback = normalize_optional_text(fallback_agent_id) or DEFAULT_CHAT_AGENT_ID
|
||||
return routing_map.get(normalized_user_id, fallback)
|
||||
|
||||
|
||||
def parse_user_agent_map(value: Any = None) -> dict[str, str]:
|
||||
"""Parse a HA-user-id to OpenClaw-agent-id mapping from options."""
|
||||
if value is None:
|
||||
return dict(DEFAULT_HA_USER_AGENT_MAP)
|
||||
|
||||
if isinstance(value, str):
|
||||
cleaned = value.strip()
|
||||
if not cleaned:
|
||||
return {}
|
||||
try:
|
||||
value = json.loads(cleaned)
|
||||
except json.JSONDecodeError as err:
|
||||
raise ValueError("User agent map must be a JSON object") from err
|
||||
|
||||
if not isinstance(value, dict):
|
||||
raise ValueError("User agent map must be a JSON object")
|
||||
|
||||
parsed: dict[str, str] = {}
|
||||
for raw_user_id, raw_agent_id in value.items():
|
||||
user_id = normalize_optional_text(raw_user_id)
|
||||
agent_id = normalize_optional_text(raw_agent_id)
|
||||
if user_id and agent_id:
|
||||
parsed[user_id] = agent_id
|
||||
return parsed
|
||||
|
||||
|
||||
def serialize_user_agent_map(value: Any = None) -> str:
|
||||
"""Serialize a user-agent routing map for config entry options."""
|
||||
return json.dumps(
|
||||
parse_user_agent_map(value),
|
||||
ensure_ascii=False,
|
||||
indent=2,
|
||||
sort_keys=True,
|
||||
)
|
||||
|
||||
|
||||
def resolve_model_override(value: Any) -> str | None:
|
||||
|
||||
Reference in New Issue
Block a user