feat: ask for the model on the first screen of the endpoint flow
The model field was one screen too late. Reported directly: "this is where I would have expected to see the model dropdown", on the AI Task init step that showed only Name and the recommended checkbox. - CONF_CHAT_MODEL moves from async_step_additional to async_step_init for conversation and ai_task_data, so all four endpoint types now ask on the first screen. stt and tts already did. - UNSUPPORTED_MODELS is validated there too, since the recommended path creates the subentry from that step and would otherwise skip the check. - model_list.default_model() picks what to preselect: RECOMMENDED_CHAT_MODEL only when the provider actually serves it (or discovery returned nothing), otherwise the first advertised model. Offering a stranger's gpt-4o-mini to a LiteLLM user preselects a model that fails on first use. This is the trade I got wrong last commit. I kept the field on the second step to avoid touching 71 ported tests, having judged them unfixable mechanically. They were not: the 71 were ~13 functions under parametrize, and test_subentry_switching's data is already a list of per-step dicts, so moving a model between steps is moving a key between two dicts. Two scripted passes moved 14 of them; 5 needed reasoning about (an error that now surfaces on init rather than the next step, and four cases whose expected data gains the now-always-recorded model). async_fetch_model_ids now also catches non-OpenAIError exceptions. Found via a ported test whose client is a MagicMock: the TypeError from awaiting it escaped and broke the whole form. A real proxy returning a payload the SDK cannot parse would do the same, and this runs inside a dialog with a working free-text fallback, so nothing it raises justifies taking the form down. Also fixes a string that was simply false on a third-party provider, again reported from the UI: "Store requests and responses in OpenAI" / "stored by OpenAI and visible in your OpenAI dashboard logs". It now describes the Responses API store flag and says support varies. Swept the other 43 OpenAI-mentioning strings while there -- the rest are [%key:...%] self-references or this fork's own action names, and no other option text makes a claim about who stores the data. Local: 170 passed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NxJYWgGJtCw13qUHZtG8ki
This commit is contained in:
1 parent
030822c845
commit
6a599e092a
7 files changed
+128
-91
No files matched your search
@@ -73,6 +73,20 @@ async def test_fetch_survives_an_endpoint_that_will_not_list(error: Exception) -
|
||||
assert await async_fetch_model_ids(_client(error=error)) == []
|
||||
|
||||
|
||||
async def test_fetch_survives_a_non_openai_error() -> None:
|
||||
"""Discovery must never break the form it runs inside.
|
||||
|
||||
A proxy can return a payload the SDK cannot parse, or a client can be
|
||||
wired in a way that raises something other than an OpenAIError; either way
|
||||
the dropdown should degrade to a text box, not take the dialog down.
|
||||
"""
|
||||
client = MagicMock()
|
||||
client.with_options.return_value = client
|
||||
client.models.list = MagicMock(return_value="not awaitable")
|
||||
|
||||
assert await async_fetch_model_ids(client) == []
|
||||
|
||||
|
||||
async def test_field_is_a_dropdown_that_still_accepts_a_typed_name() -> None:
|
||||
"""A proxy may serve a model it does not advertise, so allow free text."""
|
||||
field = model_field(["claude-sonnet", "gpt-4o-mini"])
|
||||
|
||||
Reference in new issue
Block a user