mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-20 02:47:34 +03:00
added initial working status in inline assistant prompt
This commit is contained in:
parent
933c21f3d3
commit
ec1b4e6f85
@ -290,7 +290,7 @@ impl EmbeddingProvider for OpenAIEmbeddings {
|
||||
|
||||
let mut request_number = 0;
|
||||
let mut rate_limiting = false;
|
||||
let mut request_timeout: u64 = 15;
|
||||
let mut request_timeout: u64 = 30;
|
||||
let mut response: Response<AsyncBody>;
|
||||
while request_number < MAX_RETRIES {
|
||||
response = self
|
||||
|
@ -24,10 +24,10 @@ use futures::StreamExt;
|
||||
use gpui::{
|
||||
actions,
|
||||
elements::{
|
||||
ChildView, Component, Empty, Flex, Label, MouseEventHandler, ParentElement, SafeStylable,
|
||||
Stack, Svg, Text, UniformList, UniformListState,
|
||||
ChildView, Component, Empty, Flex, Label, LabelStyle, MouseEventHandler, ParentElement,
|
||||
SafeStylable, Stack, Svg, Text, UniformList, UniformListState,
|
||||
},
|
||||
fonts::HighlightStyle,
|
||||
fonts::{HighlightStyle, TextStyle},
|
||||
geometry::vector::{vec2f, Vector2F},
|
||||
platform::{CursorStyle, MouseButton, PromptLevel},
|
||||
Action, AnyElement, AppContext, AsyncAppContext, ClipboardItem, Element, Entity, ModelContext,
|
||||
@ -37,7 +37,7 @@ use gpui::{
|
||||
use language::{language_settings::SoftWrap, Buffer, LanguageRegistry, ToOffset as _};
|
||||
use project::Project;
|
||||
use search::BufferSearchBar;
|
||||
use semantic_index::SemanticIndex;
|
||||
use semantic_index::{SemanticIndex, SemanticIndexStatus};
|
||||
use settings::SettingsStore;
|
||||
use std::{
|
||||
cell::{Cell, RefCell},
|
||||
@ -2756,6 +2756,7 @@ struct InlineAssistant {
|
||||
semantic_index: Option<ModelHandle<SemanticIndex>>,
|
||||
semantic_permissioned: Option<bool>,
|
||||
project: ModelHandle<Project>,
|
||||
maintain_rate_limit: Option<Task<()>>,
|
||||
}
|
||||
|
||||
impl Entity for InlineAssistant {
|
||||
@ -2772,67 +2773,65 @@ impl View for InlineAssistant {
|
||||
let theme = theme::current(cx);
|
||||
|
||||
Flex::row()
|
||||
.with_child(
|
||||
Flex::row()
|
||||
.with_child(
|
||||
Button::action(ToggleIncludeConversation)
|
||||
.with_tooltip("Include Conversation", theme.tooltip.clone())
|
||||
.with_children([Flex::row()
|
||||
.with_child(
|
||||
Button::action(ToggleIncludeConversation)
|
||||
.with_tooltip("Include Conversation", theme.tooltip.clone())
|
||||
.with_id(self.id)
|
||||
.with_contents(theme::components::svg::Svg::new("icons/ai.svg"))
|
||||
.toggleable(self.include_conversation)
|
||||
.with_style(theme.assistant.inline.include_conversation.clone())
|
||||
.element()
|
||||
.aligned(),
|
||||
)
|
||||
.with_children(if SemanticIndex::enabled(cx) {
|
||||
Some(
|
||||
Button::action(ToggleRetrieveContext)
|
||||
.with_tooltip("Retrieve Context", theme.tooltip.clone())
|
||||
.with_id(self.id)
|
||||
.with_contents(theme::components::svg::Svg::new("icons/ai.svg"))
|
||||
.toggleable(self.include_conversation)
|
||||
.with_style(theme.assistant.inline.include_conversation.clone())
|
||||
.with_contents(theme::components::svg::Svg::new(
|
||||
"icons/magnifying_glass.svg",
|
||||
))
|
||||
.toggleable(self.retrieve_context)
|
||||
.with_style(theme.assistant.inline.retrieve_context.clone())
|
||||
.element()
|
||||
.aligned(),
|
||||
)
|
||||
.with_children(if SemanticIndex::enabled(cx) {
|
||||
Some(
|
||||
Button::action(ToggleRetrieveContext)
|
||||
.with_tooltip("Retrieve Context", theme.tooltip.clone())
|
||||
.with_id(self.id)
|
||||
.with_contents(theme::components::svg::Svg::new(
|
||||
"icons/magnifying_glass.svg",
|
||||
))
|
||||
.toggleable(self.retrieve_context)
|
||||
.with_style(theme.assistant.inline.retrieve_context.clone())
|
||||
.element()
|
||||
.aligned(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.with_children(if let Some(error) = self.codegen.read(cx).error() {
|
||||
Some(
|
||||
Svg::new("icons/error.svg")
|
||||
.with_color(theme.assistant.error_icon.color)
|
||||
.constrained()
|
||||
.with_width(theme.assistant.error_icon.width)
|
||||
.contained()
|
||||
.with_style(theme.assistant.error_icon.container)
|
||||
.with_tooltip::<ErrorIcon>(
|
||||
self.id,
|
||||
error.to_string(),
|
||||
None,
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
)
|
||||
.aligned(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.aligned()
|
||||
.constrained()
|
||||
.dynamically({
|
||||
let measurements = self.measurements.clone();
|
||||
move |constraint, _, _| {
|
||||
let measurements = measurements.get();
|
||||
SizeConstraint {
|
||||
min: vec2f(measurements.gutter_width, constraint.min.y()),
|
||||
max: vec2f(measurements.gutter_width, constraint.max.y()),
|
||||
}
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.with_children(if let Some(error) = self.codegen.read(cx).error() {
|
||||
Some(
|
||||
Svg::new("icons/error.svg")
|
||||
.with_color(theme.assistant.error_icon.color)
|
||||
.constrained()
|
||||
.with_width(theme.assistant.error_icon.width)
|
||||
.contained()
|
||||
.with_style(theme.assistant.error_icon.container)
|
||||
.with_tooltip::<ErrorIcon>(
|
||||
self.id,
|
||||
error.to_string(),
|
||||
None,
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
)
|
||||
.aligned(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.aligned()
|
||||
.constrained()
|
||||
.dynamically({
|
||||
let measurements = self.measurements.clone();
|
||||
move |constraint, _, _| {
|
||||
let measurements = measurements.get();
|
||||
SizeConstraint {
|
||||
min: vec2f(measurements.gutter_width, constraint.min.y()),
|
||||
max: vec2f(measurements.gutter_width, constraint.max.y()),
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
})])
|
||||
.with_child(Empty::new().constrained().dynamically({
|
||||
let measurements = self.measurements.clone();
|
||||
move |constraint, _, _| {
|
||||
@ -2855,6 +2854,19 @@ impl View for InlineAssistant {
|
||||
.left()
|
||||
.flex(1., true),
|
||||
)
|
||||
.with_children(if self.retrieve_context {
|
||||
Some(
|
||||
Flex::row()
|
||||
.with_child(Label::new(
|
||||
self.retrieve_context_status(cx),
|
||||
theme.assistant.inline.context_status.text.clone(),
|
||||
))
|
||||
.flex(1., true)
|
||||
.aligned(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.contained()
|
||||
.with_style(theme.assistant.inline.container)
|
||||
.into_any()
|
||||
@ -2896,11 +2908,15 @@ impl InlineAssistant {
|
||||
editor.set_placeholder_text(placeholder, cx);
|
||||
editor
|
||||
});
|
||||
let subscriptions = vec![
|
||||
let mut subscriptions = vec![
|
||||
cx.observe(&codegen, Self::handle_codegen_changed),
|
||||
cx.subscribe(&prompt_editor, Self::handle_prompt_editor_events),
|
||||
];
|
||||
|
||||
if let Some(semantic_index) = semantic_index.clone() {
|
||||
subscriptions.push(cx.observe(&semantic_index, Self::semantic_index_changed));
|
||||
}
|
||||
|
||||
Self {
|
||||
id,
|
||||
prompt_editor,
|
||||
@ -2918,6 +2934,7 @@ impl InlineAssistant {
|
||||
semantic_permissioned: None,
|
||||
semantic_index,
|
||||
project,
|
||||
maintain_rate_limit: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -2947,6 +2964,34 @@ impl InlineAssistant {
|
||||
}
|
||||
}
|
||||
|
||||
fn semantic_index_changed(
|
||||
&mut self,
|
||||
semantic_index: ModelHandle<SemanticIndex>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
let project = self.project.clone();
|
||||
let status = semantic_index.read(cx).status(&project);
|
||||
match status {
|
||||
SemanticIndexStatus::Indexing {
|
||||
rate_limit_expiry: Some(_),
|
||||
..
|
||||
} => {
|
||||
if self.maintain_rate_limit.is_none() {
|
||||
self.maintain_rate_limit = Some(cx.spawn(|this, mut cx| async move {
|
||||
loop {
|
||||
cx.background().timer(Duration::from_secs(1)).await;
|
||||
this.update(&mut cx, |_, cx| cx.notify()).log_err();
|
||||
}
|
||||
}));
|
||||
}
|
||||
return;
|
||||
}
|
||||
_ => {
|
||||
self.maintain_rate_limit = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_codegen_changed(&mut self, _: ModelHandle<Codegen>, cx: &mut ViewContext<Self>) {
|
||||
let is_read_only = !self.codegen.read(cx).idle();
|
||||
self.prompt_editor.update(cx, |editor, cx| {
|
||||
@ -3044,16 +3089,7 @@ impl InlineAssistant {
|
||||
cx.emit(InlineAssistantEvent::RetrieveContextToggled {
|
||||
retrieve_context: this.retrieve_context,
|
||||
});
|
||||
|
||||
if this.retrieve_context {
|
||||
let context_status = this.retrieve_context_status(cx);
|
||||
if let Some(workspace) = this.workspace.upgrade(cx) {
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
workspace.show_toast(Toast::new(0, context_status), cx)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.index_project(project, cx).log_err();
|
||||
cx.notify();
|
||||
})?;
|
||||
|
||||
@ -3062,6 +3098,18 @@ impl InlineAssistant {
|
||||
.detach_and_log_err(cx);
|
||||
}
|
||||
|
||||
fn index_project(
|
||||
&self,
|
||||
project: ModelHandle<Project>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> anyhow::Result<()> {
|
||||
if let Some(semantic_index) = self.semantic_index.clone() {
|
||||
let _ = semantic_index.update(cx, |index, cx| index.index_project(project, cx));
|
||||
}
|
||||
|
||||
anyhow::Ok(())
|
||||
}
|
||||
|
||||
fn retrieve_context_status(&self, cx: &mut ViewContext<Self>) -> String {
|
||||
let project = self.project.clone();
|
||||
if let Some(semantic_index) = self.semantic_index.clone() {
|
||||
@ -3072,23 +3120,23 @@ impl InlineAssistant {
|
||||
"Not Authenticated!\nPlease ensure you have an `OPENAI_API_KEY` in your environment variables.".to_string()
|
||||
}
|
||||
semantic_index::SemanticIndexStatus::Indexed => {
|
||||
"Indexing for Context Retrieval Complete!".to_string()
|
||||
"Indexing Complete!".to_string()
|
||||
}
|
||||
semantic_index::SemanticIndexStatus::Indexing { remaining_files, rate_limit_expiry } => {
|
||||
|
||||
let mut status = format!("Indexing for Context Retrieval...\nRemaining files to index: {remaining_files}");
|
||||
let mut status = format!("Remaining files to index for Context Retrieval: {remaining_files}");
|
||||
|
||||
if let Some(rate_limit_expiry) = rate_limit_expiry {
|
||||
let remaining_seconds =
|
||||
rate_limit_expiry.duration_since(Instant::now());
|
||||
if remaining_seconds > Duration::from_secs(0) {
|
||||
writeln!(status, "Rate limit resets in {}s", remaining_seconds.as_secs()).unwrap();
|
||||
write!(status, " (rate limit resets in {}s)", remaining_seconds.as_secs()).unwrap();
|
||||
}
|
||||
}
|
||||
status
|
||||
}
|
||||
_ => {
|
||||
"Indexing for Context Retrieval...\nRemaining files to index: 48".to_string()
|
||||
semantic_index::SemanticIndexStatus::NotIndexed => {
|
||||
"Not Indexed for Context Retrieval".to_string()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1191,6 +1191,7 @@ pub struct InlineAssistantStyle {
|
||||
pub pending_edit_background: Color,
|
||||
pub include_conversation: ToggleIconButtonStyle,
|
||||
pub retrieve_context: ToggleIconButtonStyle,
|
||||
pub context_status: ContainedText,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||
|
@ -79,6 +79,9 @@ export default function assistant(): any {
|
||||
},
|
||||
},
|
||||
pending_edit_background: background(theme.highest, "positive"),
|
||||
context_status: {
|
||||
...text(theme.highest, "mono", "disabled", { size: "sm" }),
|
||||
},
|
||||
retrieve_context: toggleable({
|
||||
base: interactive({
|
||||
base: {
|
||||
|
Loading…
Reference in New Issue
Block a user