Skip to content

Commit 0b6942b

Browse files
aeroxydanilo-leal
authored andcommitted
agent_ui: Add delete button for compatible API-based LLM providers (zed-industries#41739)
Discussion: zed-industries#41736 Release Notes: - agent panel: Added the ability to remove OpenAI-compatible LLM providers directly from the UI. --------- Co-authored-by: Danilo Leal <[email protected]>
1 parent 42b99f4 commit 0b6942b

File tree

1 file changed

+83
-4
lines changed

1 file changed

+83
-4
lines changed

crates/agent_ui/src/agent_configuration.rs

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,18 @@ use language::LanguageRegistry;
2323
use language_model::{
2424
LanguageModelProvider, LanguageModelProviderId, LanguageModelRegistry, ZED_CLOUD_PROVIDER_ID,
2525
};
26+
use language_models::AllLanguageModelSettings;
2627
use notifications::status_toast::{StatusToast, ToastIcon};
2728
use project::{
2829
agent_server_store::{AgentServerStore, CLAUDE_CODE_NAME, CODEX_NAME, GEMINI_NAME},
2930
context_server_store::{ContextServerConfiguration, ContextServerStatus, ContextServerStore},
3031
};
3132
use rope::Rope;
32-
use settings::{SettingsStore, update_settings_file};
33+
use settings::{Settings, SettingsStore, update_settings_file};
3334
use ui::{
34-
Chip, CommonAnimationExt, ContextMenu, Disclosure, Divider, DividerColor, ElevationIndex,
35-
Indicator, PopoverMenu, Switch, SwitchColor, Tooltip, WithScrollbar, prelude::*,
35+
Button, ButtonStyle, Chip, CommonAnimationExt, ContextMenu, Disclosure, Divider, DividerColor,
36+
ElevationIndex, IconName, IconPosition, IconSize, Indicator, LabelSize, PopoverMenu, Switch,
37+
SwitchColor, Tooltip, WithScrollbar, prelude::*,
3638
};
3739
use util::ResultExt as _;
3840
use workspace::{Workspace, create_and_open_local_file};
@@ -304,10 +306,76 @@ impl AgentConfiguration {
304306
}
305307
})),
306308
)
307-
}),
309+
})
310+
.when(
311+
is_expanded && is_removable_provider(&provider.id(), cx),
312+
|this| {
313+
this.child(
314+
Button::new(
315+
SharedString::from(format!("delete-provider-{provider_id}")),
316+
"Remove Provider",
317+
)
318+
.full_width()
319+
.style(ButtonStyle::Outlined)
320+
.icon_position(IconPosition::Start)
321+
.icon(IconName::Trash)
322+
.icon_size(IconSize::Small)
323+
.icon_color(Color::Muted)
324+
.label_size(LabelSize::Small)
325+
.on_click(cx.listener({
326+
let provider = provider.clone();
327+
move |this, _event, window, cx| {
328+
this.delete_provider(provider.clone(), window, cx);
329+
}
330+
})),
331+
)
332+
},
333+
),
308334
)
309335
}
310336

337+
fn delete_provider(
338+
&mut self,
339+
provider: Arc<dyn LanguageModelProvider>,
340+
window: &mut Window,
341+
cx: &mut Context<Self>,
342+
) {
343+
let fs = self.fs.clone();
344+
let provider_id = provider.id();
345+
346+
cx.spawn_in(window, async move |_, cx| {
347+
cx.update(|_window, cx| {
348+
update_settings_file(fs.clone(), cx, {
349+
let provider_id = provider_id.clone();
350+
move |settings, _| {
351+
if let Some(ref mut openai_compatible) = settings
352+
.language_models
353+
.as_mut()
354+
.and_then(|lm| lm.openai_compatible.as_mut())
355+
{
356+
let key_to_remove: Arc<str> = Arc::from(provider_id.0.as_ref());
357+
openai_compatible.remove(&key_to_remove);
358+
}
359+
}
360+
});
361+
})
362+
.log_err();
363+
364+
cx.update(|_window, cx| {
365+
LanguageModelRegistry::global(cx).update(cx, {
366+
let provider_id = provider_id.clone();
367+
move |registry, cx| {
368+
registry.unregister_provider(provider_id, cx);
369+
}
370+
})
371+
})
372+
.log_err();
373+
374+
anyhow::Ok(())
375+
})
376+
.detach_and_log_err(cx);
377+
}
378+
311379
fn render_provider_configuration_section(
312380
&mut self,
313381
cx: &mut Context<Self>,
@@ -1225,3 +1293,14 @@ fn find_text_in_buffer(
12251293
None
12261294
}
12271295
}
1296+
1297+
// OpenAI-compatible providers are user-configured and can be removed,
1298+
// whereas built-in providers (like Anthropic, OpenAI, Google, etc.) can't.
1299+
//
1300+
// If in the future we have more "API-compatible-type" of providers,
1301+
// they should be included here as removable providers.
1302+
fn is_removable_provider(provider_id: &LanguageModelProviderId, cx: &App) -> bool {
1303+
AllLanguageModelSettings::get_global(cx)
1304+
.openai_compatible
1305+
.contains_key(provider_id.0.as_ref())
1306+
}

0 commit comments

Comments
 (0)