docs/design/acp-model-route-identity.md
Qwen Code currently exposes ACP model IDs as modelId(authType). Two configured models with the same model ID and auth type but different baseUrl values therefore collapse to one ACP selector. Clients cannot identify the active row or round-trip a selection to the intended endpoint.
Core already treats (authType, modelId, configured baseUrl) as the registry identity. The loss happens only when that identity crosses the ACP boundary. The configured value must remain separate from the resolved endpoint because provider defaults can fill baseUrl after registration.
Build ACP model options from the existing configured-model list:
modelId(authType) when it is unique. This preserves existing IDs for the normal case.qwen-route:v1:<digest> selector derived from non-secret model metadata and the public endpoint identity (credentials, query, and fragment removed).ModelInfo.name and provider metadata for display. The route ID is an opaque machine selector.Core exposes the original optional registry baseUrl alongside the resolved display endpoint. The same option builder supplies ACP session models, config options, live provider status, and daemon workspace provider status so every client sees the same ID while the server retains the exact registry discriminator.
On session/set_model, Qwen Code resolves the selector against the current configured-model list before switching. It passes the resolved baseUrl to Core, then persists only the canonical settings values:
model.name: actual model IDmodel.baseUrl: configured registry endpoint, or an empty tombstone for an implicit defaultsecurity.auth.selectedType: actual auth typeThe opaque selector is never written to settings.json.
modelId remains a string.modelId(authType) requests remain accepted. If such an ID is ambiguous, existing first-match behavior is preserved for compatibility; newly advertised selectors are exact.baseUrl, persists canonical settings, and notifies clients with its opaque selector.