Detailed changes
@@ -1,7 +1,7 @@
-use std::ops::Range;
+use std::{cell::Cell, ops::Range, rc::Rc};
use acp_thread::{AcpThread, AgentThreadEntry};
-use agent_client_protocol::ToolCallId;
+use agent_client_protocol::{PromptCapabilities, ToolCallId};
use agent2::HistoryStore;
use collections::HashMap;
use editor::{Editor, EditorMode, MinimapVisibility};
@@ -27,6 +27,7 @@ pub struct EntryViewState {
prompt_store: Option<Entity<PromptStore>>,
entries: Vec<Entry>,
prevent_slash_commands: bool,
+ prompt_capabilities: Rc<Cell<PromptCapabilities>>,
}
impl EntryViewState {
@@ -35,6 +36,7 @@ impl EntryViewState {
project: Entity<Project>,
history_store: Entity<HistoryStore>,
prompt_store: Option<Entity<PromptStore>>,
+ prompt_capabilities: Rc<Cell<PromptCapabilities>>,
prevent_slash_commands: bool,
) -> Self {
Self {
@@ -44,6 +46,7 @@ impl EntryViewState {
prompt_store,
entries: Vec::new(),
prevent_slash_commands,
+ prompt_capabilities,
}
}
@@ -81,6 +84,7 @@ impl EntryViewState {
self.project.clone(),
self.history_store.clone(),
self.prompt_store.clone(),
+ self.prompt_capabilities.clone(),
"Edit message - @ to include context",
self.prevent_slash_commands,
editor::EditorMode::AutoHeight {
@@ -403,6 +407,7 @@ mod tests {
project.clone(),
history_store,
None,
+ Default::default(),
false,
)
});
@@ -87,6 +87,7 @@ impl MessageEditor {
project: Entity<Project>,
history_store: Entity<HistoryStore>,
prompt_store: Option<Entity<PromptStore>>,
+ prompt_capabilities: Rc<Cell<acp::PromptCapabilities>>,
placeholder: impl Into<Arc<str>>,
prevent_slash_commands: bool,
mode: EditorMode,
@@ -100,7 +101,6 @@ impl MessageEditor {
},
None,
);
- let prompt_capabilities = Rc::new(Cell::new(acp::PromptCapabilities::default()));
let completion_provider = ContextPickerCompletionProvider::new(
cx.weak_entity(),
workspace.clone(),
@@ -203,10 +203,6 @@ impl MessageEditor {
.detach();
}
- pub fn set_prompt_capabilities(&mut self, capabilities: acp::PromptCapabilities) {
- self.prompt_capabilities.set(capabilities);
- }
-
#[cfg(test)]
pub(crate) fn editor(&self) -> &Entity<Editor> {
&self.editor
@@ -1095,15 +1091,21 @@ impl MessageEditor {
mentions.push((start..end, mention_uri, resource.text));
}
}
+ acp::ContentBlock::ResourceLink(resource) => {
+ if let Some(mention_uri) = MentionUri::parse(&resource.uri).log_err() {
+ let start = text.len();
+ write!(&mut text, "{}", mention_uri.as_link()).ok();
+ let end = text.len();
+ mentions.push((start..end, mention_uri, resource.uri));
+ }
+ }
acp::ContentBlock::Image(content) => {
let start = text.len();
text.push_str("image");
let end = text.len();
images.push((start..end, content));
}
- acp::ContentBlock::Audio(_)
- | acp::ContentBlock::Resource(_)
- | acp::ContentBlock::ResourceLink(_) => {}
+ acp::ContentBlock::Audio(_) | acp::ContentBlock::Resource(_) => {}
}
}
@@ -1850,7 +1852,7 @@ impl Addon for MessageEditorAddon {
#[cfg(test)]
mod tests {
- use std::{ops::Range, path::Path, sync::Arc};
+ use std::{cell::Cell, ops::Range, path::Path, rc::Rc, sync::Arc};
use acp_thread::MentionUri;
use agent_client_protocol as acp;
@@ -1896,6 +1898,7 @@ mod tests {
project.clone(),
history_store.clone(),
None,
+ Default::default(),
"Test",
false,
EditorMode::AutoHeight {
@@ -2086,6 +2089,7 @@ mod tests {
let context_store = cx.new(|cx| ContextStore::fake(project.clone(), cx));
let history_store = cx.new(|cx| HistoryStore::new(context_store, cx));
+ let prompt_capabilities = Rc::new(Cell::new(acp::PromptCapabilities::default()));
let (message_editor, editor) = workspace.update_in(&mut cx, |workspace, window, cx| {
let workspace_handle = cx.weak_entity();
@@ -2095,6 +2099,7 @@ mod tests {
project.clone(),
history_store.clone(),
None,
+ prompt_capabilities.clone(),
"Test",
false,
EditorMode::AutoHeight {
@@ -2139,13 +2144,10 @@ mod tests {
editor.set_text("", window, cx);
});
- message_editor.update(&mut cx, |editor, _cx| {
- // Enable all prompt capabilities
- editor.set_prompt_capabilities(acp::PromptCapabilities {
- image: true,
- audio: true,
- embedded_context: true,
- });
+ prompt_capabilities.set(acp::PromptCapabilities {
+ image: true,
+ audio: true,
+ embedded_context: true,
});
cx.simulate_input("Lorem ");
@@ -5,7 +5,7 @@ use acp_thread::{
};
use acp_thread::{AgentConnection, Plan};
use action_log::ActionLog;
-use agent_client_protocol::{self as acp};
+use agent_client_protocol::{self as acp, PromptCapabilities};
use agent_servers::{AgentServer, ClaudeCode};
use agent_settings::{AgentProfileId, AgentSettings, CompletionMode, NotifyWhenAgentWaiting};
use agent2::{DbThreadMetadata, HistoryEntry, HistoryEntryId, HistoryStore};
@@ -34,6 +34,7 @@ use project::{Project, ProjectEntryId};
use prompt_store::{PromptId, PromptStore};
use rope::Point;
use settings::{Settings as _, SettingsStore};
+use std::cell::Cell;
use std::sync::Arc;
use std::time::Instant;
use std::{collections::BTreeMap, rc::Rc, time::Duration};
@@ -271,6 +272,7 @@ pub struct AcpThreadView {
plan_expanded: bool,
editor_expanded: bool,
editing_message: Option<usize>,
+ prompt_capabilities: Rc<Cell<PromptCapabilities>>,
_cancel_task: Option<Task<()>>,
_subscriptions: [Subscription; 3],
}
@@ -306,6 +308,7 @@ impl AcpThreadView {
window: &mut Window,
cx: &mut Context<Self>,
) -> Self {
+ let prompt_capabilities = Rc::new(Cell::new(acp::PromptCapabilities::default()));
let prevent_slash_commands = agent.clone().downcast::<ClaudeCode>().is_some();
let message_editor = cx.new(|cx| {
let mut editor = MessageEditor::new(
@@ -313,6 +316,7 @@ impl AcpThreadView {
project.clone(),
history_store.clone(),
prompt_store.clone(),
+ prompt_capabilities.clone(),
"Message the agent — @ to include context",
prevent_slash_commands,
editor::EditorMode::AutoHeight {
@@ -336,6 +340,7 @@ impl AcpThreadView {
project.clone(),
history_store.clone(),
prompt_store.clone(),
+ prompt_capabilities.clone(),
prevent_slash_commands,
)
});
@@ -371,6 +376,7 @@ impl AcpThreadView {
editor_expanded: false,
history_store,
hovered_recent_history_item: None,
+ prompt_capabilities,
_subscriptions: subscriptions,
_cancel_task: None,
}
@@ -448,6 +454,9 @@ impl AcpThreadView {
Ok(thread) => {
let action_log = thread.read(cx).action_log().clone();
+ this.prompt_capabilities
+ .set(connection.prompt_capabilities());
+
let count = thread.read(cx).entries().len();
this.list_state.splice(0..0, count);
this.entry_view_state.update(cx, |view_state, cx| {
@@ -523,11 +532,6 @@ impl AcpThreadView {
})
});
- this.message_editor.update(cx, |message_editor, _cx| {
- message_editor
- .set_prompt_capabilities(connection.prompt_capabilities());
- });
-
cx.notify();
}
Err(err) => {