/
/
/
1"""Constants for the AI Radio plugin."""
2
3from __future__ import annotations
4
5from typing import Any
6
7CONF_AI_ENGINE = "ai_engine"
8CONF_TTS_ENGINE = "tts_engine"
9CONF_TIMEZONE = "timezone"
10CONF_WEATHER_CITY = "weather_city"
11CONF_WEATHER_COUNTRY = "weather_country"
12
13# providers load concurrently, so the plugin supplying the engines may still be
14# loading when AI Radio initializes: wait this long for it before giving up
15ENGINE_DISCOVERY_TIMEOUT = 30
16
17# grace period for an engine that disappears while AI Radio is loaded. Generous enough
18# to sit out a Home Assistant restart, so a running show is not torn down for it
19ENGINE_RECHECK_GRACE = 300
20
21# how long to wait before reloading after an engine stayed missing, matching the
22# cadence the load path uses for its own retries
23ENGINE_RETRY_DELAY = 120
24
25TRANSLATION_OWNER = "provider.ai_radio"
26
27DEFAULT_LLM_INSTRUCTIONS = (
28 "Host personality: warm, sharp, music-literate, and slightly premium "
29 "without sounding formal. Program instructions: write for spoken delivery, "
30 "keep segments concise, avoid bullet-point phrasing, avoid clichés, "
31 "mention concrete details when available, and maintain a believable "
32 "radio flow between sections."
33)
34DEFAULT_WEATHER_PROVIDER = "open_meteo"
35DEFAULT_WEATHER_TIMEOUT_SECONDS = 20
36DEFAULT_MAX_CONCURRENT_RUNS = 1
37MAX_FINISHED_SESSIONS = 20
38
39# a show whose playback never starts within this window is declared failed
40SHOW_START_TIMEOUT_SECONDS = 300
41
42# last-resort guards so a wedged engine fails the clip instead of hanging the session.
43# Kept above the deadlines the engines apply themselves (120s in the OpenAI-compatible
44# providers), so their own, more specific error is the one that surfaces.
45AI_QUERY_TIMEOUT_SECONDS = 180
46TTS_QUERY_TIMEOUT_SECONDS = 180
47
48SUPPORTED_FEATURES: set[Any] = set()
49EMPTY_SECTION_ID = "EMPTY_SECTION"
50VALID_WEB_SEARCH_MODES = {"disabled", "allow", "force"}
51WEB_SEARCH_MODE_RANK = {"disabled": 0, "allow": 1, "force": 2}
52
53# QueueItem.extra_attributes keys carrying a clip's pending render state. Scalars only â
54# extra_attributes is serialized to clients and persisted with the queue.
55ATTR_SESSION_ID = "ai_radio_session_id"
56ATTR_STATION_ID = "ai_radio_station_id"
57ATTR_PROMPT = "ai_radio_prompt"
58ATTR_MAX_CHARS = "ai_radio_max_chars"
59ATTR_WEB_SEARCH_MODE = "ai_radio_web_search_mode"
60ATTR_RENDERED_TEXT = "ai_radio_rendered_text"
61
62# placeholders resolved at render time rather than at plan time, so the aired script
63# reflects the moment it plays
64DEFERRED_PLACEHOLDERS = frozenset({"<timestamp>", "<weather_hourly>", "<weather_daily>"})
65
66# HA drops a tts_proxy token 60s after its last use at the lowest configurable time_memory
67CLIP_STREAMDETAILS_EXPIRATION = 60
68