Reshapes setup around how a multi-model proxy is actually used: one config entry per server/provider, then one endpoint per model added by hand, with the model chosen from what that provider advertises right now. Setup (async_step_user): - Adds a Name field. With one entry per provider the title matters, and it was hardcoded to "ChatGPT" regardless of where the entry pointed. Blank falls back to the endpoint host via url_util.title_from_base_url. Deliberately absent from the reauth schema (now split out as STEP_REAUTH_DATA_SCHEMA): that step writes its input back into entry.data via data_updates, so a name field there would persist the title as connection data on every key rotation. - Stops auto-creating four subentries. conversation/ai_task_data/stt/tts were all created up front carrying RECOMMENDED_* options, which pin OpenAI model names (gpt-4o-mini-tts, gpt-4o-mini-transcribe). Against a third-party endpoint those entities are dead on arrival -- the reported symptom was an install that "loads bits, it's all janky". - Drops _async_abort_entries_match, so several entries may point at one server (one per provider-side key, for instance). Upstream aborts with already_configured on matching url+key. Model discovery (new model_list.py, kept out of the vendored files like url_util.py): - async_fetch_model_ids asks the endpoint's GET /v1/models. It calls with_options(max_retries=0), because this runs while the user waits on a dialog and the SDK otherwise retries with backoff -- visible in the test run as repeated "Retrying request to /models" and a suite that went from 5s to minutes. - Returns [] on any OpenAIError, and model_field() then yields a plain text field instead of a dropdown, so an endpoint that serves /v1/responses but not /v1/models is still configurable by hand. The dropdown sets custom_value=True for the same reason (LiteLLM wildcard routes). - Wired into all four types: conversation and ai_task_data on the additional step, stt (which hardcoded OpenAI's three transcribe models) and tts on init. TTS had no model field at all -- it silently used gpt-4o-mini-tts. A new endpoint now starts with "recommended" unticked. Ticked, the flow ends on the first step and never shows a model field, which is why the model looked unpickable; reconfigure still keeps whatever was saved. The model field stays on the additional step rather than moving to init. The init position reads better, but 71 ported tests drive the model through the additional step, several from parametrized option dicts that no mechanical edit could relocate. Rewriting the only regression net against upstream to save one click was the wrong trade. Also: the setup description no longer says "your OpenAI API key", and instructions_url pointed at a README anchor (#generate-an-api-key) that does not exist -- now #configuration. strings.json re-verified against core's RE_URL: 0 violations. Local: 167 passed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NxJYWgGJtCw13qUHZtG8ki
334 lines
13 KiB
JSON
334 lines
13 KiB
JSON
{
|
|
"config": {
|
|
"abort": {
|
|
"already_configured": "Service is already configured",
|
|
"reauth_successful": "Re-authentication was successful"
|
|
},
|
|
"error": {
|
|
"cannot_connect": "Failed to connect",
|
|
"credentials_in_url": "The base URL must not contain a username or password. Put authentication in the API key field instead.",
|
|
"invalid_auth": "Invalid authentication",
|
|
"invalid_base_url": "That does not look like a valid http(s) URL.",
|
|
"unknown": "Unexpected error"
|
|
},
|
|
"step": {
|
|
"reauth_confirm": {
|
|
"data": {
|
|
"api_key": "API key",
|
|
"base_url": "API base URL"
|
|
},
|
|
"data_description": {
|
|
"api_key": "The API key for this endpoint. Leave blank if it does not require authentication.",
|
|
"base_url": "The base URL of the OpenAI-compatible API, including any version path such as /v1. The endpoint must implement the Responses API."
|
|
},
|
|
"description": "Reauthentication required. Please enter your updated API key and confirm the API base URL."
|
|
},
|
|
"user": {
|
|
"data": {
|
|
"api_key": "API key",
|
|
"base_url": "API base URL",
|
|
"name": "Name"
|
|
},
|
|
"data_description": {
|
|
"api_key": "The API key for this endpoint. Leave blank if it does not require authentication.",
|
|
"base_url": "The base URL of the OpenAI-compatible API, including any version path such as /v1. The endpoint must implement the Responses API.",
|
|
"name": "A label for this provider, for example LiteLLM. Defaults to the endpoint's host."
|
|
},
|
|
"description": "Connect to an OpenAI-compatible API. One entry per server or provider; you add endpoints for individual models afterwards. See the [setup notes]({instructions_url}) for what the endpoint has to support."
|
|
}
|
|
}
|
|
},
|
|
"config_subentries": {
|
|
"ai_task_data": {
|
|
"abort": {
|
|
"entry_not_loaded": "Cannot add things while the configuration is disabled.",
|
|
"reconfigure_successful": "Reconfiguration was successful"
|
|
},
|
|
"entry_type": "AI task",
|
|
"error": {
|
|
"code_interpreter_minimal_reasoning": "Code interpreter is not supported with minimal reasoning effort",
|
|
"model_not_supported": "This model is not supported, please select a different model",
|
|
"web_search_minimal_reasoning": "Web search is currently not supported with minimal reasoning effort"
|
|
},
|
|
"initiate_flow": {
|
|
"reconfigure": "Reconfigure AI task",
|
|
"user": "Add AI task"
|
|
},
|
|
"step": {
|
|
"additional": {
|
|
"data": {
|
|
"chat_model": "Model",
|
|
"max_tokens": "Maximum tokens to return in response",
|
|
"store_responses": "Store requests and responses in OpenAI",
|
|
"temperature": "Temperature",
|
|
"top_p": "Top P"
|
|
},
|
|
"data_description": {
|
|
"store_responses": "If enabled, requests and responses are stored by OpenAI and visible in your OpenAI dashboard logs"
|
|
},
|
|
"title": "Additional settings"
|
|
},
|
|
"init": {
|
|
"data": {
|
|
"name": "Name",
|
|
"recommended": "Recommended model settings"
|
|
}
|
|
},
|
|
"model": {
|
|
"data": {
|
|
"code_interpreter": "Enable code interpreter tool",
|
|
"image_model": "Image generation model",
|
|
"inline_citations": "Include links in web search results",
|
|
"pro_mode": "Pro mode",
|
|
"reasoning_effort": "Reasoning effort",
|
|
"reasoning_summary": "Reasoning summary",
|
|
"search_context_size": "Search context size",
|
|
"service_tier": "Service tier",
|
|
"user_location": "Include home location",
|
|
"web_search": "Enable web search"
|
|
},
|
|
"data_description": {
|
|
"code_interpreter": "This tool, also known as the python tool to the model, allows it to run code to answer questions",
|
|
"image_model": "The model to use when generating images",
|
|
"inline_citations": "If disabled, additional prompt is added to ask the model to not include source citations",
|
|
"pro_mode": "Perform more model work to improve reliability on difficult tasks and return a single final answer",
|
|
"reasoning_effort": "How many reasoning tokens the model should generate before creating a response to the prompt",
|
|
"reasoning_summary": "Controls the length and detail of reasoning summaries provided by the model",
|
|
"search_context_size": "High level guidance for the amount of context window space to use for the search",
|
|
"service_tier": "Controls the cost and response time",
|
|
"user_location": "Refine search results based on geography",
|
|
"web_search": "Allow the model to search the web for the latest information before generating a response"
|
|
},
|
|
"title": "Model-specific options"
|
|
}
|
|
}
|
|
},
|
|
"conversation": {
|
|
"abort": {
|
|
"entry_not_loaded": "Cannot add things while the configuration is disabled.",
|
|
"reconfigure_successful": "Reconfiguration was successful"
|
|
},
|
|
"entry_type": "Conversation agent",
|
|
"error": {
|
|
"code_interpreter_minimal_reasoning": "Code interpreter is not supported with minimal reasoning effort",
|
|
"model_not_supported": "This model is not supported, please select a different model",
|
|
"web_search_minimal_reasoning": "Web search is currently not supported with minimal reasoning effort"
|
|
},
|
|
"initiate_flow": {
|
|
"reconfigure": "Reconfigure conversation agent",
|
|
"user": "Add conversation agent"
|
|
},
|
|
"step": {
|
|
"additional": {
|
|
"data": {
|
|
"chat_model": "Model",
|
|
"max_tokens": "Maximum tokens to return in response",
|
|
"store_responses": "Store requests and responses in OpenAI",
|
|
"temperature": "Temperature",
|
|
"top_p": "Top P"
|
|
},
|
|
"data_description": {
|
|
"store_responses": "If enabled, requests and responses are stored by OpenAI and visible in your OpenAI dashboard logs"
|
|
},
|
|
"title": "Additional settings"
|
|
},
|
|
"init": {
|
|
"data": {
|
|
"llm_hass_api": "Control Home Assistant",
|
|
"name": "Name",
|
|
"prompt": "Instructions",
|
|
"recommended": "Recommended model settings"
|
|
},
|
|
"data_description": {
|
|
"prompt": "Instruct how the LLM should respond. This can be a template."
|
|
}
|
|
},
|
|
"model": {
|
|
"data": {
|
|
"code_interpreter": "Enable code interpreter tool",
|
|
"image_model": "Image generation model",
|
|
"inline_citations": "Include links in web search results",
|
|
"pro_mode": "Pro mode",
|
|
"reasoning_effort": "Reasoning effort",
|
|
"reasoning_summary": "Reasoning summary",
|
|
"search_context_size": "Search context size",
|
|
"service_tier": "Service tier",
|
|
"user_location": "Include home location",
|
|
"web_search": "Enable web search"
|
|
},
|
|
"data_description": {
|
|
"code_interpreter": "This tool, also known as the python tool to the model, allows it to run code to answer questions",
|
|
"image_model": "The model to use when generating images",
|
|
"inline_citations": "If disabled, additional prompt is added to ask the model to not include source citations",
|
|
"pro_mode": "Perform more model work to improve reliability on difficult tasks and return a single final answer",
|
|
"reasoning_effort": "How many reasoning tokens the model should generate before creating a response to the prompt",
|
|
"reasoning_summary": "Controls the length and detail of reasoning summaries provided by the model",
|
|
"search_context_size": "High level guidance for the amount of context window space to use for the search",
|
|
"service_tier": "Controls the cost and response time",
|
|
"user_location": "Refine search results based on geography",
|
|
"web_search": "Allow the model to search the web for the latest information before generating a response"
|
|
},
|
|
"title": "Model-specific options"
|
|
}
|
|
}
|
|
},
|
|
"stt": {
|
|
"abort": {
|
|
"entry_not_loaded": "Cannot add things while the configuration is disabled.",
|
|
"reconfigure_successful": "Reconfiguration was successful"
|
|
},
|
|
"entry_type": "Speech-to-text",
|
|
"initiate_flow": {
|
|
"reconfigure": "Reconfigure speech-to-text service",
|
|
"user": "Add speech-to-text service"
|
|
},
|
|
"step": {
|
|
"init": {
|
|
"data": {
|
|
"chat_model": "Model",
|
|
"name": "Name",
|
|
"prompt": "Instructions"
|
|
},
|
|
"data_description": {
|
|
"chat_model": "The model to use to transcribe speech.",
|
|
"prompt": "Use this prompt to improve the quality of the transcripts. Translate to the pipeline language for best results. See the documentation for more details."
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"tts": {
|
|
"abort": {
|
|
"entry_not_loaded": "Cannot add things while the configuration is disabled.",
|
|
"reconfigure_successful": "Reconfiguration was successful"
|
|
},
|
|
"entry_type": "Text-to-speech",
|
|
"initiate_flow": {
|
|
"reconfigure": "Reconfigure text-to-speech service",
|
|
"user": "Add text-to-speech service"
|
|
},
|
|
"step": {
|
|
"init": {
|
|
"data": {
|
|
"name": "Name",
|
|
"prompt": "Instructions",
|
|
"tts_speed": "Speed"
|
|
},
|
|
"data_description": {
|
|
"prompt": "Control aspects of speech, including accent, emotional range, intonation, impressions, speed of speech, tone, whispering, and more",
|
|
"tts_speed": "Speed of the generated speech"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"exceptions": {
|
|
"invalid_config_entry": {
|
|
"message": "Invalid config entry provided. Got {config_entry}"
|
|
}
|
|
},
|
|
"issues": {
|
|
"deprecated_generate_content": {
|
|
"description": "Action 'openai_compatible.generate_content' is deprecated and will be removed in the 2026.9.0 release. Please use the 'ai_task.generate_data' action instead",
|
|
"title": "Deprecated 'generate_content' action"
|
|
},
|
|
"deprecated_generate_image": {
|
|
"description": "Action 'openai_compatible.generate_image' is deprecated and will be removed in the 2026.9.0 release. Please use the 'ai_task.generate_image' action instead",
|
|
"title": "Deprecated 'generate_image' action"
|
|
},
|
|
"organization_verification_required": {
|
|
"description": "Your organization must be verified to use this model. Please go to {platform_settings} and select Verify Organization. If you just verified, it can take up to 15 minutes for access to propagate.",
|
|
"title": "Organization verification required"
|
|
}
|
|
},
|
|
"selector": {
|
|
"reasoning_effort": {
|
|
"options": {
|
|
"high": "High",
|
|
"low": "Low",
|
|
"max": "Max",
|
|
"medium": "Medium",
|
|
"minimal": "Minimal",
|
|
"none": "None",
|
|
"xhigh": "X-High"
|
|
}
|
|
},
|
|
"reasoning_summary": {
|
|
"options": {
|
|
"auto": "Auto",
|
|
"concise": "Concise",
|
|
"detailed": "Detailed",
|
|
"off": "Off"
|
|
}
|
|
},
|
|
"search_context_size": {
|
|
"options": {
|
|
"high": "High",
|
|
"low": "Low",
|
|
"medium": "Medium"
|
|
}
|
|
},
|
|
"service_tier": {
|
|
"options": {
|
|
"auto": "Auto",
|
|
"default": "Standard",
|
|
"flex": "Flex",
|
|
"priority": "Priority"
|
|
}
|
|
},
|
|
"verbosity": {
|
|
"options": {
|
|
"high": "High",
|
|
"low": "Low",
|
|
"medium": "Medium"
|
|
}
|
|
}
|
|
},
|
|
"services": {
|
|
"generate_content": {
|
|
"description": "Sends a conversational query to ChatGPT including any attached image or PDF files (deprecated)",
|
|
"fields": {
|
|
"config_entry": {
|
|
"description": "The config entry to use for this action",
|
|
"name": "Config entry"
|
|
},
|
|
"filenames": {
|
|
"description": "List of files to upload",
|
|
"name": "Files"
|
|
},
|
|
"prompt": {
|
|
"description": "The prompt to send",
|
|
"name": "Prompt"
|
|
}
|
|
},
|
|
"name": "Generate content (deprecated)"
|
|
},
|
|
"generate_image": {
|
|
"description": "Turns a prompt into an image (deprecated)",
|
|
"fields": {
|
|
"config_entry": {
|
|
"description": "The config entry to use for this action",
|
|
"name": "Config entry"
|
|
},
|
|
"prompt": {
|
|
"description": "The text to turn into an image",
|
|
"example": "A photo of a dog",
|
|
"name": "Prompt"
|
|
},
|
|
"quality": {
|
|
"description": "The quality of the image that will be generated",
|
|
"name": "Quality"
|
|
},
|
|
"size": {
|
|
"description": "The size of the image to generate",
|
|
"name": "Size"
|
|
},
|
|
"style": {
|
|
"description": "The style of the generated image",
|
|
"name": "Style"
|
|
}
|
|
},
|
|
"name": "Generate image (deprecated)"
|
|
}
|
|
}
|
|
}
|