acp: Fix MessageEditor::set_message
for sent messages (#36715)
The `PromptCapabilities` introduced in previous PRs were only getting set on the main message editor and not for the editors in user messages. This caused a bug where mentions would disappear after resending the message, and for the completion provider to be limited to files. Release Notes: - N/A
This commit is contained in:
parent
3d80be6267
commit
14a50e2b23
3 changed files with 35 additions and 24 deletions
|
@ -1,7 +1,7 @@
|
||||||
use std::ops::Range;
|
use std::{cell::Cell, ops::Range, rc::Rc};
|
||||||
|
|
||||||
use acp_thread::{AcpThread, AgentThreadEntry};
|
use acp_thread::{AcpThread, AgentThreadEntry};
|
||||||
use agent_client_protocol::ToolCallId;
|
use agent_client_protocol::{PromptCapabilities, ToolCallId};
|
||||||
use agent2::HistoryStore;
|
use agent2::HistoryStore;
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use editor::{Editor, EditorMode, MinimapVisibility};
|
use editor::{Editor, EditorMode, MinimapVisibility};
|
||||||
|
@ -27,6 +27,7 @@ pub struct EntryViewState {
|
||||||
prompt_store: Option<Entity<PromptStore>>,
|
prompt_store: Option<Entity<PromptStore>>,
|
||||||
entries: Vec<Entry>,
|
entries: Vec<Entry>,
|
||||||
prevent_slash_commands: bool,
|
prevent_slash_commands: bool,
|
||||||
|
prompt_capabilities: Rc<Cell<PromptCapabilities>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EntryViewState {
|
impl EntryViewState {
|
||||||
|
@ -35,6 +36,7 @@ impl EntryViewState {
|
||||||
project: Entity<Project>,
|
project: Entity<Project>,
|
||||||
history_store: Entity<HistoryStore>,
|
history_store: Entity<HistoryStore>,
|
||||||
prompt_store: Option<Entity<PromptStore>>,
|
prompt_store: Option<Entity<PromptStore>>,
|
||||||
|
prompt_capabilities: Rc<Cell<PromptCapabilities>>,
|
||||||
prevent_slash_commands: bool,
|
prevent_slash_commands: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -44,6 +46,7 @@ impl EntryViewState {
|
||||||
prompt_store,
|
prompt_store,
|
||||||
entries: Vec::new(),
|
entries: Vec::new(),
|
||||||
prevent_slash_commands,
|
prevent_slash_commands,
|
||||||
|
prompt_capabilities,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,6 +84,7 @@ impl EntryViewState {
|
||||||
self.project.clone(),
|
self.project.clone(),
|
||||||
self.history_store.clone(),
|
self.history_store.clone(),
|
||||||
self.prompt_store.clone(),
|
self.prompt_store.clone(),
|
||||||
|
self.prompt_capabilities.clone(),
|
||||||
"Edit message - @ to include context",
|
"Edit message - @ to include context",
|
||||||
self.prevent_slash_commands,
|
self.prevent_slash_commands,
|
||||||
editor::EditorMode::AutoHeight {
|
editor::EditorMode::AutoHeight {
|
||||||
|
@ -403,6 +407,7 @@ mod tests {
|
||||||
project.clone(),
|
project.clone(),
|
||||||
history_store,
|
history_store,
|
||||||
None,
|
None,
|
||||||
|
Default::default(),
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
|
@ -87,6 +87,7 @@ impl MessageEditor {
|
||||||
project: Entity<Project>,
|
project: Entity<Project>,
|
||||||
history_store: Entity<HistoryStore>,
|
history_store: Entity<HistoryStore>,
|
||||||
prompt_store: Option<Entity<PromptStore>>,
|
prompt_store: Option<Entity<PromptStore>>,
|
||||||
|
prompt_capabilities: Rc<Cell<acp::PromptCapabilities>>,
|
||||||
placeholder: impl Into<Arc<str>>,
|
placeholder: impl Into<Arc<str>>,
|
||||||
prevent_slash_commands: bool,
|
prevent_slash_commands: bool,
|
||||||
mode: EditorMode,
|
mode: EditorMode,
|
||||||
|
@ -100,7 +101,6 @@ impl MessageEditor {
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
let prompt_capabilities = Rc::new(Cell::new(acp::PromptCapabilities::default()));
|
|
||||||
let completion_provider = ContextPickerCompletionProvider::new(
|
let completion_provider = ContextPickerCompletionProvider::new(
|
||||||
cx.weak_entity(),
|
cx.weak_entity(),
|
||||||
workspace.clone(),
|
workspace.clone(),
|
||||||
|
@ -203,10 +203,6 @@ impl MessageEditor {
|
||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_prompt_capabilities(&mut self, capabilities: acp::PromptCapabilities) {
|
|
||||||
self.prompt_capabilities.set(capabilities);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(crate) fn editor(&self) -> &Entity<Editor> {
|
pub(crate) fn editor(&self) -> &Entity<Editor> {
|
||||||
&self.editor
|
&self.editor
|
||||||
|
@ -1095,15 +1091,21 @@ impl MessageEditor {
|
||||||
mentions.push((start..end, mention_uri, resource.text));
|
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) => {
|
acp::ContentBlock::Image(content) => {
|
||||||
let start = text.len();
|
let start = text.len();
|
||||||
text.push_str("image");
|
text.push_str("image");
|
||||||
let end = text.len();
|
let end = text.len();
|
||||||
images.push((start..end, content));
|
images.push((start..end, content));
|
||||||
}
|
}
|
||||||
acp::ContentBlock::Audio(_)
|
acp::ContentBlock::Audio(_) | acp::ContentBlock::Resource(_) => {}
|
||||||
| acp::ContentBlock::Resource(_)
|
|
||||||
| acp::ContentBlock::ResourceLink(_) => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1850,7 +1852,7 @@ impl Addon for MessageEditorAddon {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
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 acp_thread::MentionUri;
|
||||||
use agent_client_protocol as acp;
|
use agent_client_protocol as acp;
|
||||||
|
@ -1896,6 +1898,7 @@ mod tests {
|
||||||
project.clone(),
|
project.clone(),
|
||||||
history_store.clone(),
|
history_store.clone(),
|
||||||
None,
|
None,
|
||||||
|
Default::default(),
|
||||||
"Test",
|
"Test",
|
||||||
false,
|
false,
|
||||||
EditorMode::AutoHeight {
|
EditorMode::AutoHeight {
|
||||||
|
@ -2086,6 +2089,7 @@ mod tests {
|
||||||
|
|
||||||
let context_store = cx.new(|cx| ContextStore::fake(project.clone(), cx));
|
let context_store = cx.new(|cx| ContextStore::fake(project.clone(), cx));
|
||||||
let history_store = cx.new(|cx| HistoryStore::new(context_store, 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 (message_editor, editor) = workspace.update_in(&mut cx, |workspace, window, cx| {
|
||||||
let workspace_handle = cx.weak_entity();
|
let workspace_handle = cx.weak_entity();
|
||||||
|
@ -2095,6 +2099,7 @@ mod tests {
|
||||||
project.clone(),
|
project.clone(),
|
||||||
history_store.clone(),
|
history_store.clone(),
|
||||||
None,
|
None,
|
||||||
|
prompt_capabilities.clone(),
|
||||||
"Test",
|
"Test",
|
||||||
false,
|
false,
|
||||||
EditorMode::AutoHeight {
|
EditorMode::AutoHeight {
|
||||||
|
@ -2139,13 +2144,10 @@ mod tests {
|
||||||
editor.set_text("", window, cx);
|
editor.set_text("", window, cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
message_editor.update(&mut cx, |editor, _cx| {
|
prompt_capabilities.set(acp::PromptCapabilities {
|
||||||
// Enable all prompt capabilities
|
image: true,
|
||||||
editor.set_prompt_capabilities(acp::PromptCapabilities {
|
audio: true,
|
||||||
image: true,
|
embedded_context: true,
|
||||||
audio: true,
|
|
||||||
embedded_context: true,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
cx.simulate_input("Lorem ");
|
cx.simulate_input("Lorem ");
|
||||||
|
|
|
@ -5,7 +5,7 @@ use acp_thread::{
|
||||||
};
|
};
|
||||||
use acp_thread::{AgentConnection, Plan};
|
use acp_thread::{AgentConnection, Plan};
|
||||||
use action_log::ActionLog;
|
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_servers::{AgentServer, ClaudeCode};
|
||||||
use agent_settings::{AgentProfileId, AgentSettings, CompletionMode, NotifyWhenAgentWaiting};
|
use agent_settings::{AgentProfileId, AgentSettings, CompletionMode, NotifyWhenAgentWaiting};
|
||||||
use agent2::{DbThreadMetadata, HistoryEntry, HistoryEntryId, HistoryStore};
|
use agent2::{DbThreadMetadata, HistoryEntry, HistoryEntryId, HistoryStore};
|
||||||
|
@ -34,6 +34,7 @@ use project::{Project, ProjectEntryId};
|
||||||
use prompt_store::{PromptId, PromptStore};
|
use prompt_store::{PromptId, PromptStore};
|
||||||
use rope::Point;
|
use rope::Point;
|
||||||
use settings::{Settings as _, SettingsStore};
|
use settings::{Settings as _, SettingsStore};
|
||||||
|
use std::cell::Cell;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use std::{collections::BTreeMap, rc::Rc, time::Duration};
|
use std::{collections::BTreeMap, rc::Rc, time::Duration};
|
||||||
|
@ -271,6 +272,7 @@ pub struct AcpThreadView {
|
||||||
plan_expanded: bool,
|
plan_expanded: bool,
|
||||||
editor_expanded: bool,
|
editor_expanded: bool,
|
||||||
editing_message: Option<usize>,
|
editing_message: Option<usize>,
|
||||||
|
prompt_capabilities: Rc<Cell<PromptCapabilities>>,
|
||||||
_cancel_task: Option<Task<()>>,
|
_cancel_task: Option<Task<()>>,
|
||||||
_subscriptions: [Subscription; 3],
|
_subscriptions: [Subscription; 3],
|
||||||
}
|
}
|
||||||
|
@ -306,6 +308,7 @@ impl AcpThreadView {
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let prompt_capabilities = Rc::new(Cell::new(acp::PromptCapabilities::default()));
|
||||||
let prevent_slash_commands = agent.clone().downcast::<ClaudeCode>().is_some();
|
let prevent_slash_commands = agent.clone().downcast::<ClaudeCode>().is_some();
|
||||||
let message_editor = cx.new(|cx| {
|
let message_editor = cx.new(|cx| {
|
||||||
let mut editor = MessageEditor::new(
|
let mut editor = MessageEditor::new(
|
||||||
|
@ -313,6 +316,7 @@ impl AcpThreadView {
|
||||||
project.clone(),
|
project.clone(),
|
||||||
history_store.clone(),
|
history_store.clone(),
|
||||||
prompt_store.clone(),
|
prompt_store.clone(),
|
||||||
|
prompt_capabilities.clone(),
|
||||||
"Message the agent — @ to include context",
|
"Message the agent — @ to include context",
|
||||||
prevent_slash_commands,
|
prevent_slash_commands,
|
||||||
editor::EditorMode::AutoHeight {
|
editor::EditorMode::AutoHeight {
|
||||||
|
@ -336,6 +340,7 @@ impl AcpThreadView {
|
||||||
project.clone(),
|
project.clone(),
|
||||||
history_store.clone(),
|
history_store.clone(),
|
||||||
prompt_store.clone(),
|
prompt_store.clone(),
|
||||||
|
prompt_capabilities.clone(),
|
||||||
prevent_slash_commands,
|
prevent_slash_commands,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
@ -371,6 +376,7 @@ impl AcpThreadView {
|
||||||
editor_expanded: false,
|
editor_expanded: false,
|
||||||
history_store,
|
history_store,
|
||||||
hovered_recent_history_item: None,
|
hovered_recent_history_item: None,
|
||||||
|
prompt_capabilities,
|
||||||
_subscriptions: subscriptions,
|
_subscriptions: subscriptions,
|
||||||
_cancel_task: None,
|
_cancel_task: None,
|
||||||
}
|
}
|
||||||
|
@ -448,6 +454,9 @@ impl AcpThreadView {
|
||||||
Ok(thread) => {
|
Ok(thread) => {
|
||||||
let action_log = thread.read(cx).action_log().clone();
|
let action_log = thread.read(cx).action_log().clone();
|
||||||
|
|
||||||
|
this.prompt_capabilities
|
||||||
|
.set(connection.prompt_capabilities());
|
||||||
|
|
||||||
let count = thread.read(cx).entries().len();
|
let count = thread.read(cx).entries().len();
|
||||||
this.list_state.splice(0..0, count);
|
this.list_state.splice(0..0, count);
|
||||||
this.entry_view_state.update(cx, |view_state, cx| {
|
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();
|
cx.notify();
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue