This allows storing the profile per thread, as well as moving the logic of which tools are enabled or not to the profile itself. This makes it much easier to switch between profiles, means there is less global state being changed on every profile change. Release Notes: - agent panel: allow saving the profile per thread --------- Co-authored-by: Ben Kunkle <ben.kunkle@gmail.com>
99 lines
3.5 KiB
Rust
99 lines
3.5 KiB
Rust
use std::sync::Arc;
|
|
|
|
use assistant_tool::{Tool, ToolSource};
|
|
use collections::HashMap;
|
|
use gpui::{App, Context, Entity, IntoElement, Render, Subscription, Window};
|
|
use language_model::{LanguageModel, LanguageModelToolSchemaFormat};
|
|
use ui::prelude::*;
|
|
|
|
use crate::{Thread, ThreadEvent};
|
|
|
|
pub struct IncompatibleToolsState {
|
|
cache: HashMap<LanguageModelToolSchemaFormat, Vec<Arc<dyn Tool>>>,
|
|
thread: Entity<Thread>,
|
|
_thread_subscription: Subscription,
|
|
}
|
|
|
|
impl IncompatibleToolsState {
|
|
pub fn new(thread: Entity<Thread>, cx: &mut Context<Self>) -> Self {
|
|
let _tool_working_set_subscription =
|
|
cx.subscribe(&thread, |this, _, event, _| match event {
|
|
ThreadEvent::ProfileChanged => {
|
|
this.cache.clear();
|
|
}
|
|
_ => {}
|
|
});
|
|
|
|
Self {
|
|
cache: HashMap::default(),
|
|
thread,
|
|
_thread_subscription: _tool_working_set_subscription,
|
|
}
|
|
}
|
|
|
|
pub fn incompatible_tools(
|
|
&mut self,
|
|
model: &Arc<dyn LanguageModel>,
|
|
cx: &App,
|
|
) -> &[Arc<dyn Tool>] {
|
|
self.cache
|
|
.entry(model.tool_input_format())
|
|
.or_insert_with(|| {
|
|
self.thread
|
|
.read(cx)
|
|
.profile()
|
|
.enabled_tools(cx)
|
|
.iter()
|
|
.filter(|tool| tool.input_schema(model.tool_input_format()).is_err())
|
|
.cloned()
|
|
.collect()
|
|
})
|
|
}
|
|
}
|
|
|
|
pub struct IncompatibleToolsTooltip {
|
|
pub incompatible_tools: Vec<Arc<dyn Tool>>,
|
|
}
|
|
|
|
impl Render for IncompatibleToolsTooltip {
|
|
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
|
ui::tooltip_container(window, cx, |container, _, cx| {
|
|
container
|
|
.w_72()
|
|
.child(Label::new("Incompatible Tools").size(LabelSize::Small))
|
|
.child(
|
|
Label::new(
|
|
"This model is incompatible with the following tools from your MCPs:",
|
|
)
|
|
.size(LabelSize::Small)
|
|
.color(Color::Muted),
|
|
)
|
|
.child(
|
|
v_flex()
|
|
.my_1p5()
|
|
.py_0p5()
|
|
.border_b_1()
|
|
.border_color(cx.theme().colors().border_variant)
|
|
.children(
|
|
self.incompatible_tools
|
|
.iter()
|
|
.map(|tool| h_flex().gap_4().child(Label::new(tool.name()).size(LabelSize::Small)).map(|parent|
|
|
match tool.source() {
|
|
ToolSource::Native => parent,
|
|
ToolSource::ContextServer { id } => parent.child(Label::new(id).size(LabelSize::Small).color(Color::Muted)),
|
|
}
|
|
)),
|
|
),
|
|
)
|
|
.child(Label::new("What To Do Instead").size(LabelSize::Small))
|
|
.child(
|
|
Label::new(
|
|
"Every other tool continues to work with this model, but to specifically use those, switch to another model.",
|
|
)
|
|
.size(LabelSize::Small)
|
|
.color(Color::Muted),
|
|
)
|
|
})
|
|
}
|
|
}
|