@@ -70,8 +70,12 @@ pub(crate) async fn run_agent(
7070 Some ( binding. model_name . clone ( ) )
7171 }
7272 } ) ;
73+ let model_binding_id = active_model_binding
74+ . as_ref ( )
75+ . map ( |binding| binding. binding_id . clone ( ) ) ;
7376 let model = active_model_binding
74- . map ( |binding| binding. model_slug )
77+ . as_ref ( )
78+ . map ( |binding| binding. model_slug . clone ( ) )
7579 . unwrap_or ( model) ;
7680
7781 tracing:: info!( "starting interactive tui" ) ;
@@ -81,6 +85,7 @@ pub(crate) async fn run_agent(
8185 session_id : initial_session_id,
8286 model,
8387 request_model,
88+ model_binding_id,
8489 provider : wire_api,
8590 thinking_selection : model_thinking_selection,
8691 permission_preset,
@@ -143,9 +148,9 @@ fn saved_model_entries(app_config: &AppConfig) -> Vec<SavedModelEntry> {
143148 let stored_config = & app_config. provider ;
144149 let mut entries = stored_config
145150 . model_bindings
146- . values ( )
147- . filter ( |binding| binding. enabled )
148- . filter_map ( |binding| {
151+ . iter ( )
152+ . filter ( |( _ , binding) | binding. enabled )
153+ . filter_map ( |( binding_id , binding) | {
149154 let provider = stored_config. providers . get ( & binding. provider ) ?;
150155 let request_model = if binding. model_name == binding. model_slug {
151156 None
@@ -156,46 +161,62 @@ fn saved_model_entries(app_config: &AppConfig) -> Vec<SavedModelEntry> {
156161 . display_name
157162 . clone ( )
158163 . or_else ( || request_model. clone ( ) ) ;
164+ let provider_name = provider
165+ . name
166+ . trim ( )
167+ . is_empty ( )
168+ . then ( || binding. provider . clone ( ) )
169+ . unwrap_or_else ( || provider. name . clone ( ) ) ;
159170 Some ( SavedModelEntry {
171+ binding_id : Some ( binding_id. clone ( ) ) ,
160172 model : binding. model_slug . clone ( ) ,
161173 request_model,
162174 display_name,
175+ provider_id : Some ( binding. provider . clone ( ) ) ,
176+ provider_name : Some ( provider_name) ,
163177 wire_api : binding. invocation_method ,
164178 base_url : provider. base_url . clone ( ) ,
165179 api_key : None ,
166180 } )
167181 } )
168182 . collect :: < Vec < _ > > ( ) ;
169183
170- entries. extend (
171- stored_config
172- . model_providers
173- . values ( )
174- . flat_map ( |provider_config| {
175- // Older config entries may not have persisted `wire_api`; keep them
176- // on the historical OpenAI-compatible chat-completions default.
177- let wire_api = provider_config
178- . wire_api
179- . unwrap_or ( ProviderWireApi :: OpenAIChatCompletions ) ;
180- provider_config
181- . models
182- . iter ( )
183- . map ( move |model| SavedModelEntry {
184- model : model. model . clone ( ) ,
185- request_model : None ,
186- display_name : None ,
187- wire_api,
188- base_url : model
189- . base_url
190- . clone ( )
191- . or_else ( || provider_config. base_url . clone ( ) ) ,
192- api_key : model
193- . api_key
194- . clone ( )
195- . or_else ( || provider_config. api_key . clone ( ) ) ,
196- } )
197- } ) ,
198- ) ;
184+ entries. extend ( stored_config. model_providers . iter ( ) . flat_map (
185+ |( provider_id, provider_config) | {
186+ // Older config entries may not have persisted `wire_api`; keep them
187+ // on the historical OpenAI-compatible chat-completions default.
188+ let wire_api = provider_config
189+ . wire_api
190+ . unwrap_or ( ProviderWireApi :: OpenAIChatCompletions ) ;
191+ let provider_name = provider_config
192+ . name
193+ . as_deref ( )
194+ . map ( str:: trim)
195+ . filter ( |name| !name. is_empty ( ) )
196+ . map ( ToOwned :: to_owned)
197+ . unwrap_or_else ( || provider_id. clone ( ) ) ;
198+ provider_config
199+ . models
200+ . iter ( )
201+ . map ( move |model| SavedModelEntry {
202+ binding_id : None ,
203+ model : model. model . clone ( ) ,
204+ request_model : None ,
205+ display_name : None ,
206+ provider_id : Some ( provider_id. clone ( ) ) ,
207+ provider_name : Some ( provider_name. clone ( ) ) ,
208+ wire_api,
209+ base_url : model
210+ . base_url
211+ . clone ( )
212+ . or_else ( || provider_config. base_url . clone ( ) ) ,
213+ api_key : model
214+ . api_key
215+ . clone ( )
216+ . or_else ( || provider_config. api_key . clone ( ) ) ,
217+ } )
218+ } ,
219+ ) ) ;
199220 entries
200221}
201222
@@ -421,17 +442,23 @@ mod tests {
421442 saved_model_entries( & app_config) ,
422443 vec![
423444 SavedModelEntry {
445+ binding_id: Some ( "openai" . to_string( ) ) ,
424446 model: "provider-defaults" . to_string( ) ,
425447 request_model: None ,
426448 display_name: None ,
449+ provider_id: Some ( "openai" . to_string( ) ) ,
450+ provider_name: Some ( "openai" . to_string( ) ) ,
427451 wire_api: ProviderWireApi :: OpenAIResponses ,
428452 base_url: Some ( "https://provider.example" . to_string( ) ) ,
429453 api_key: None ,
430454 } ,
431455 SavedModelEntry {
456+ binding_id: None ,
432457 model: "model-overrides" . to_string( ) ,
433458 request_model: None ,
434459 display_name: None ,
460+ provider_id: Some ( "legacy" . to_string( ) ) ,
461+ provider_name: Some ( "legacy" . to_string( ) ) ,
435462 wire_api: ProviderWireApi :: OpenAIResponses ,
436463 base_url: Some ( "https://model.example" . to_string( ) ) ,
437464 api_key: Some ( "model-key" . to_string( ) ) ,
@@ -469,9 +496,12 @@ mod tests {
469496 assert_eq ! (
470497 saved_model_entries( & app_config) ,
471498 vec![ SavedModelEntry {
499+ binding_id: Some ( "deepseek" . to_string( ) ) ,
472500 model: "deepseek-v4-flash" . to_string( ) ,
473501 request_model: Some ( "DeepSeek-V4-Flash" . to_string( ) ) ,
474502 display_name: Some ( "DeepSeek-V4-Flash" . to_string( ) ) ,
503+ provider_id: Some ( "deepseek" . to_string( ) ) ,
504+ provider_name: Some ( "deepseek" . to_string( ) ) ,
475505 wire_api: ProviderWireApi :: OpenAIChatCompletions ,
476506 base_url: Some ( "https://api.deepseek.com" . to_string( ) ) ,
477507 api_key: None ,
@@ -498,9 +528,12 @@ mod tests {
498528 assert_eq ! (
499529 saved_model_entries( & app_config) ,
500530 vec![ SavedModelEntry {
531+ binding_id: None ,
501532 model: "default-wire-api" . to_string( ) ,
502533 request_model: None ,
503534 display_name: None ,
535+ provider_id: Some ( "openai" . to_string( ) ) ,
536+ provider_name: Some ( "openai" . to_string( ) ) ,
504537 wire_api: ProviderWireApi :: OpenAIChatCompletions ,
505538 base_url: None ,
506539 api_key: None ,
0 commit comments