Fix panic when re-editing old message with creases (#32017)
Co-authored-by: Cole Miller <m@cole-miller.net> Release Notes: - agent: Fixed a panic when re-editing old messages --------- Co-authored-by: Cole Miller <m@cole-miller.net> Co-authored-by: Cole Miller <cole@zed.dev>
This commit is contained in:
parent
4aabba6cf6
commit
03357f3f7b
3 changed files with 93 additions and 4 deletions
|
@ -3,7 +3,7 @@ use crate::context::{AgentContextHandle, RULES_ICON};
|
||||||
use crate::context_picker::{ContextPicker, MentionLink};
|
use crate::context_picker::{ContextPicker, MentionLink};
|
||||||
use crate::context_store::ContextStore;
|
use crate::context_store::ContextStore;
|
||||||
use crate::context_strip::{ContextStrip, ContextStripEvent, SuggestContextKind};
|
use crate::context_strip::{ContextStrip, ContextStripEvent, SuggestContextKind};
|
||||||
use crate::message_editor::insert_message_creases;
|
use crate::message_editor::{extract_message_creases, insert_message_creases};
|
||||||
use crate::thread::{
|
use crate::thread::{
|
||||||
LastRestoreCheckpoint, MessageCrease, MessageId, MessageSegment, Thread, ThreadError,
|
LastRestoreCheckpoint, MessageCrease, MessageId, MessageSegment, Thread, ThreadError,
|
||||||
ThreadEvent, ThreadFeedback, ThreadSummary,
|
ThreadEvent, ThreadFeedback, ThreadSummary,
|
||||||
|
@ -1586,6 +1586,8 @@ impl ActiveThread {
|
||||||
|
|
||||||
let edited_text = state.editor.read(cx).text(cx);
|
let edited_text = state.editor.read(cx).text(cx);
|
||||||
|
|
||||||
|
let creases = state.editor.update(cx, extract_message_creases);
|
||||||
|
|
||||||
let new_context = self
|
let new_context = self
|
||||||
.context_store
|
.context_store
|
||||||
.read(cx)
|
.read(cx)
|
||||||
|
@ -1610,6 +1612,7 @@ impl ActiveThread {
|
||||||
message_id,
|
message_id,
|
||||||
Role::User,
|
Role::User,
|
||||||
vec![MessageSegment::Text(edited_text)],
|
vec![MessageSegment::Text(edited_text)],
|
||||||
|
creases,
|
||||||
Some(context.loaded_context),
|
Some(context.loaded_context),
|
||||||
checkpoint.ok(),
|
checkpoint.ok(),
|
||||||
cx,
|
cx,
|
||||||
|
@ -3677,10 +3680,13 @@ fn open_editor_at_position(
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use assistant_tool::{ToolRegistry, ToolWorkingSet};
|
use assistant_tool::{ToolRegistry, ToolWorkingSet};
|
||||||
use editor::EditorSettings;
|
use editor::{EditorSettings, display_map::CreaseMetadata};
|
||||||
use fs::FakeFs;
|
use fs::FakeFs;
|
||||||
use gpui::{AppContext, TestAppContext, VisualTestContext};
|
use gpui::{AppContext, TestAppContext, VisualTestContext};
|
||||||
use language_model::{LanguageModel, fake_provider::FakeLanguageModel};
|
use language_model::{
|
||||||
|
ConfiguredModel, LanguageModel, LanguageModelRegistry,
|
||||||
|
fake_provider::{FakeLanguageModel, FakeLanguageModelProvider},
|
||||||
|
};
|
||||||
use project::Project;
|
use project::Project;
|
||||||
use prompt_store::PromptBuilder;
|
use prompt_store::PromptBuilder;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
@ -3741,6 +3747,87 @@ mod tests {
|
||||||
assert!(!cx.read(|cx| workspace.read(cx).is_being_followed(CollaboratorId::Agent)));
|
assert!(!cx.read(|cx| workspace.read(cx).is_being_followed(CollaboratorId::Agent)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_reinserting_creases_for_edited_message(cx: &mut TestAppContext) {
|
||||||
|
init_test_settings(cx);
|
||||||
|
|
||||||
|
let project = create_test_project(cx, json!({})).await;
|
||||||
|
|
||||||
|
let (cx, active_thread, _, thread, model) =
|
||||||
|
setup_test_environment(cx, project.clone()).await;
|
||||||
|
cx.update(|_, cx| {
|
||||||
|
LanguageModelRegistry::global(cx).update(cx, |registry, cx| {
|
||||||
|
registry.set_default_model(
|
||||||
|
Some(ConfiguredModel {
|
||||||
|
provider: Arc::new(FakeLanguageModelProvider),
|
||||||
|
model,
|
||||||
|
}),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
let creases = vec![MessageCrease {
|
||||||
|
range: 14..22,
|
||||||
|
metadata: CreaseMetadata {
|
||||||
|
icon_path: "icon".into(),
|
||||||
|
label: "foo.txt".into(),
|
||||||
|
},
|
||||||
|
context: None,
|
||||||
|
}];
|
||||||
|
|
||||||
|
let message = thread.update(cx, |thread, cx| {
|
||||||
|
let message_id = thread.insert_user_message(
|
||||||
|
"Tell me about @foo.txt",
|
||||||
|
ContextLoadResult::default(),
|
||||||
|
None,
|
||||||
|
creases,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
thread.message(message_id).cloned().unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
|
active_thread.update_in(cx, |active_thread, window, cx| {
|
||||||
|
active_thread.start_editing_message(
|
||||||
|
message.id,
|
||||||
|
message.segments.as_slice(),
|
||||||
|
message.creases.as_slice(),
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
let editor = active_thread
|
||||||
|
.editing_message
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.1
|
||||||
|
.editor
|
||||||
|
.clone();
|
||||||
|
editor.update(cx, |editor, cx| editor.edit([(0..13, "modified")], cx));
|
||||||
|
active_thread.confirm_editing_message(&Default::default(), window, cx);
|
||||||
|
});
|
||||||
|
cx.run_until_parked();
|
||||||
|
|
||||||
|
let message = thread.update(cx, |thread, _| thread.message(message.id).cloned().unwrap());
|
||||||
|
active_thread.update_in(cx, |active_thread, window, cx| {
|
||||||
|
active_thread.start_editing_message(
|
||||||
|
message.id,
|
||||||
|
message.segments.as_slice(),
|
||||||
|
message.creases.as_slice(),
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
let editor = active_thread
|
||||||
|
.editing_message
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.1
|
||||||
|
.editor
|
||||||
|
.clone();
|
||||||
|
let text = editor.update(cx, |editor, cx| editor.text(cx));
|
||||||
|
assert_eq!(text, "modified @foo.txt");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn init_test_settings(cx: &mut TestAppContext) {
|
fn init_test_settings(cx: &mut TestAppContext) {
|
||||||
cx.update(|cx| {
|
cx.update(|cx| {
|
||||||
let settings_store = SettingsStore::test(cx);
|
let settings_store = SettingsStore::test(cx);
|
||||||
|
|
|
@ -1032,6 +1032,7 @@ impl Thread {
|
||||||
id: MessageId,
|
id: MessageId,
|
||||||
new_role: Role,
|
new_role: Role,
|
||||||
new_segments: Vec<MessageSegment>,
|
new_segments: Vec<MessageSegment>,
|
||||||
|
creases: Vec<MessageCrease>,
|
||||||
loaded_context: Option<LoadedContext>,
|
loaded_context: Option<LoadedContext>,
|
||||||
checkpoint: Option<GitStoreCheckpoint>,
|
checkpoint: Option<GitStoreCheckpoint>,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
|
@ -1041,6 +1042,7 @@ impl Thread {
|
||||||
};
|
};
|
||||||
message.role = new_role;
|
message.role = new_role;
|
||||||
message.segments = new_segments;
|
message.segments = new_segments;
|
||||||
|
message.creases = creases;
|
||||||
if let Some(context) = loaded_context {
|
if let Some(context) = loaded_context {
|
||||||
message.loaded_context = context;
|
message.loaded_context = context;
|
||||||
}
|
}
|
||||||
|
|
|
@ -264,7 +264,7 @@ Given an externally-ran web server (e.g. with `npx serve` or `npx live-server`)
|
||||||
## Breakpoints
|
## Breakpoints
|
||||||
|
|
||||||
To set a breakpoint, simply click next to the line number in the editor gutter.
|
To set a breakpoint, simply click next to the line number in the editor gutter.
|
||||||
Breakpoints can be tweaked dependending on your needs; to access additional options of a given breakpoint, right-click on the breakpoint icon in the gutter and select the desired option.
|
Breakpoints can be tweaked depending on your needs; to access additional options of a given breakpoint, right-click on the breakpoint icon in the gutter and select the desired option.
|
||||||
At present, you can:
|
At present, you can:
|
||||||
|
|
||||||
- Add a log to a breakpoint, which will output a log message whenever that breakpoint is hit.
|
- Add a log to a breakpoint, which will output a log message whenever that breakpoint is hit.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue