Allow /workflow and step resolution prompts to be overridden (#15892)
This will help us as we hit issues with the /workflow and step resolution. We can override the baked-in prompts and make tweaks, then import our refinements back into the source tree when we're ready. Release Notes: - N/A
This commit is contained in:
@@ -25,6 +25,7 @@ use language_model::{
|
||||
LanguageModelId, LanguageModelProviderId, LanguageModelRegistry, LanguageModelResponseMessage,
|
||||
};
|
||||
pub(crate) use model_selector::*;
|
||||
pub use prompts::PromptBuilder;
|
||||
use semantic_index::{CloudEmbeddingProvider, SemanticIndex};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use settings::{update_settings_file, Settings, SettingsStore};
|
||||
@@ -163,7 +164,7 @@ impl Assistant {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(fs: Arc<dyn Fs>, client: Arc<Client>, cx: &mut AppContext) {
|
||||
pub fn init(fs: Arc<dyn Fs>, client: Arc<Client>, cx: &mut AppContext) -> Arc<PromptBuilder> {
|
||||
cx.set_global(Assistant::default());
|
||||
AssistantSettings::register(cx);
|
||||
|
||||
@@ -196,19 +197,25 @@ pub fn init(fs: Arc<dyn Fs>, client: Arc<Client>, cx: &mut AppContext) {
|
||||
prompt_library::init(cx);
|
||||
init_language_model_settings(cx);
|
||||
assistant_slash_command::init(cx);
|
||||
register_slash_commands(cx);
|
||||
assistant_panel::init(cx);
|
||||
|
||||
if let Some(prompt_builder) = prompts::PromptBuilder::new(Some((fs.clone(), cx))).log_err() {
|
||||
let prompt_builder = Arc::new(prompt_builder);
|
||||
inline_assistant::init(
|
||||
fs.clone(),
|
||||
prompt_builder.clone(),
|
||||
client.telemetry().clone(),
|
||||
cx,
|
||||
);
|
||||
terminal_inline_assistant::init(fs.clone(), prompt_builder, client.telemetry().clone(), cx);
|
||||
}
|
||||
let prompt_builder = prompts::PromptBuilder::new(Some((fs.clone(), cx)))
|
||||
.log_err()
|
||||
.map(Arc::new)
|
||||
.unwrap_or_else(|| Arc::new(prompts::PromptBuilder::new(None).unwrap()));
|
||||
register_slash_commands(Some(prompt_builder.clone()), cx);
|
||||
inline_assistant::init(
|
||||
fs.clone(),
|
||||
prompt_builder.clone(),
|
||||
client.telemetry().clone(),
|
||||
cx,
|
||||
);
|
||||
terminal_inline_assistant::init(
|
||||
fs.clone(),
|
||||
prompt_builder.clone(),
|
||||
client.telemetry().clone(),
|
||||
cx,
|
||||
);
|
||||
IndexedDocsRegistry::init_global(cx);
|
||||
|
||||
CommandPaletteFilter::update_global(cx, |filter, _cx| {
|
||||
@@ -226,6 +233,8 @@ pub fn init(fs: Arc<dyn Fs>, client: Arc<Client>, cx: &mut AppContext) {
|
||||
});
|
||||
})
|
||||
.detach();
|
||||
|
||||
prompt_builder
|
||||
}
|
||||
|
||||
fn init_language_model_settings(cx: &mut AppContext) {
|
||||
@@ -256,7 +265,7 @@ fn update_active_language_model_from_settings(cx: &mut AppContext) {
|
||||
});
|
||||
}
|
||||
|
||||
fn register_slash_commands(cx: &mut AppContext) {
|
||||
fn register_slash_commands(prompt_builder: Option<Arc<PromptBuilder>>, cx: &mut AppContext) {
|
||||
let slash_command_registry = SlashCommandRegistry::global(cx);
|
||||
slash_command_registry.register_command(file_command::FileSlashCommand, true);
|
||||
slash_command_registry.register_command(active_command::ActiveSlashCommand, true);
|
||||
@@ -270,7 +279,12 @@ fn register_slash_commands(cx: &mut AppContext) {
|
||||
slash_command_registry.register_command(now_command::NowSlashCommand, true);
|
||||
slash_command_registry.register_command(diagnostics_command::DiagnosticsSlashCommand, true);
|
||||
slash_command_registry.register_command(docs_command::DocsSlashCommand, true);
|
||||
slash_command_registry.register_command(workflow_command::WorkflowSlashCommand, true);
|
||||
if let Some(prompt_builder) = prompt_builder {
|
||||
slash_command_registry.register_command(
|
||||
workflow_command::WorkflowSlashCommand::new(prompt_builder),
|
||||
true,
|
||||
);
|
||||
}
|
||||
slash_command_registry.register_command(fetch_command::FetchSlashCommand, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::{
|
||||
assistant_settings::{AssistantDockPosition, AssistantSettings},
|
||||
humanize_token_count,
|
||||
prompt_library::open_prompt_library,
|
||||
prompts::PromptBuilder,
|
||||
slash_command::{
|
||||
default_command::DefaultSlashCommand,
|
||||
docs_command::{DocsSlashCommand, DocsSlashCommandArgs},
|
||||
@@ -315,14 +316,17 @@ impl PickerDelegate for SavedContextPickerDelegate {
|
||||
impl AssistantPanel {
|
||||
pub fn load(
|
||||
workspace: WeakView<Workspace>,
|
||||
prompt_builder: Arc<PromptBuilder>,
|
||||
cx: AsyncWindowContext,
|
||||
) -> Task<Result<View<Self>>> {
|
||||
cx.spawn(|mut cx| async move {
|
||||
let context_store = workspace
|
||||
.update(&mut cx, |workspace, cx| {
|
||||
ContextStore::new(workspace.project().clone(), cx)
|
||||
let project = workspace.project().clone();
|
||||
ContextStore::new(project, prompt_builder.clone(), cx)
|
||||
})?
|
||||
.await?;
|
||||
|
||||
workspace.update(&mut cx, |workspace, cx| {
|
||||
// TODO: deserialize state.
|
||||
cx.new_view(|cx| Self::new(workspace, context_store, cx))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
prompt_library::PromptStore, slash_command::SlashCommandLine, AssistantPanel, InitialInsertion,
|
||||
prompts::PromptBuilder, slash_command::SlashCommandLine, AssistantPanel, InitialInsertion,
|
||||
InlineAssistId, InlineAssistant, MessageId, MessageStatus,
|
||||
};
|
||||
use anyhow::{anyhow, Context as _, Result};
|
||||
@@ -611,6 +611,7 @@ pub struct Context {
|
||||
language_registry: Arc<LanguageRegistry>,
|
||||
workflow_steps: Vec<WorkflowStep>,
|
||||
project: Option<Model<Project>>,
|
||||
prompt_builder: Arc<PromptBuilder>,
|
||||
}
|
||||
|
||||
impl EventEmitter<ContextEvent> for Context {}
|
||||
@@ -620,6 +621,7 @@ impl Context {
|
||||
language_registry: Arc<LanguageRegistry>,
|
||||
project: Option<Model<Project>>,
|
||||
telemetry: Option<Arc<Telemetry>>,
|
||||
prompt_builder: Arc<PromptBuilder>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Self {
|
||||
Self::new(
|
||||
@@ -627,17 +629,20 @@ impl Context {
|
||||
ReplicaId::default(),
|
||||
language::Capability::ReadWrite,
|
||||
language_registry,
|
||||
prompt_builder,
|
||||
project,
|
||||
telemetry,
|
||||
cx,
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
id: ContextId,
|
||||
replica_id: ReplicaId,
|
||||
capability: language::Capability,
|
||||
language_registry: Arc<LanguageRegistry>,
|
||||
prompt_builder: Arc<PromptBuilder>,
|
||||
project: Option<Model<Project>>,
|
||||
telemetry: Option<Arc<Telemetry>>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
@@ -680,6 +685,7 @@ impl Context {
|
||||
project,
|
||||
language_registry,
|
||||
workflow_steps: Vec::new(),
|
||||
prompt_builder,
|
||||
};
|
||||
|
||||
let first_message_id = MessageId(clock::Lamport {
|
||||
@@ -749,6 +755,7 @@ impl Context {
|
||||
saved_context: SavedContext,
|
||||
path: PathBuf,
|
||||
language_registry: Arc<LanguageRegistry>,
|
||||
prompt_builder: Arc<PromptBuilder>,
|
||||
project: Option<Model<Project>>,
|
||||
telemetry: Option<Arc<Telemetry>>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
@@ -759,6 +766,7 @@ impl Context {
|
||||
ReplicaId::default(),
|
||||
language::Capability::ReadWrite,
|
||||
language_registry,
|
||||
prompt_builder,
|
||||
project,
|
||||
telemetry,
|
||||
cx,
|
||||
@@ -1246,9 +1254,9 @@ impl Context {
|
||||
|
||||
cx.spawn(|this, mut cx| {
|
||||
async move {
|
||||
let prompt_store = cx.update(|cx| PromptStore::global(cx))?.await?;
|
||||
|
||||
let mut prompt = prompt_store.step_resolution_prompt()?;
|
||||
let mut prompt = this.update(&mut cx, |this, _| {
|
||||
this.prompt_builder.generate_step_resolution_prompt()
|
||||
})??;
|
||||
prompt.push_str(&step_text);
|
||||
|
||||
request.messages.push(LanguageModelRequestMessage {
|
||||
@@ -2448,8 +2456,9 @@ mod tests {
|
||||
cx.set_global(settings_store);
|
||||
assistant_panel::init(cx);
|
||||
let registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
|
||||
|
||||
let context = cx.new_model(|cx| Context::local(registry, None, None, cx));
|
||||
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
|
||||
let context =
|
||||
cx.new_model(|cx| Context::local(registry, None, None, prompt_builder.clone(), cx));
|
||||
let buffer = context.read(cx).buffer.clone();
|
||||
|
||||
let message_1 = context.read(cx).message_anchors[0].clone();
|
||||
@@ -2580,7 +2589,9 @@ mod tests {
|
||||
assistant_panel::init(cx);
|
||||
let registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
|
||||
|
||||
let context = cx.new_model(|cx| Context::local(registry, None, None, cx));
|
||||
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
|
||||
let context =
|
||||
cx.new_model(|cx| Context::local(registry, None, None, prompt_builder.clone(), cx));
|
||||
let buffer = context.read(cx).buffer.clone();
|
||||
|
||||
let message_1 = context.read(cx).message_anchors[0].clone();
|
||||
@@ -2673,7 +2684,9 @@ mod tests {
|
||||
cx.set_global(settings_store);
|
||||
assistant_panel::init(cx);
|
||||
let registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
|
||||
let context = cx.new_model(|cx| Context::local(registry, None, None, cx));
|
||||
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
|
||||
let context =
|
||||
cx.new_model(|cx| Context::local(registry, None, None, prompt_builder.clone(), cx));
|
||||
let buffer = context.read(cx).buffer.clone();
|
||||
|
||||
let message_1 = context.read(cx).message_anchors[0].clone();
|
||||
@@ -2778,7 +2791,10 @@ mod tests {
|
||||
slash_command_registry.register_command(active_command::ActiveSlashCommand, false);
|
||||
|
||||
let registry = Arc::new(LanguageRegistry::test(cx.executor()));
|
||||
let context = cx.new_model(|cx| Context::local(registry.clone(), None, None, cx));
|
||||
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
|
||||
let context = cx.new_model(|cx| {
|
||||
Context::local(registry.clone(), None, None, prompt_builder.clone(), cx)
|
||||
});
|
||||
|
||||
let output_ranges = Rc::new(RefCell::new(HashSet::default()));
|
||||
context.update(cx, |_, cx| {
|
||||
@@ -2905,7 +2921,16 @@ mod tests {
|
||||
let registry = Arc::new(LanguageRegistry::test(cx.executor()));
|
||||
|
||||
// Create a new context
|
||||
let context = cx.new_model(|cx| Context::local(registry.clone(), Some(project), None, cx));
|
||||
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
|
||||
let context = cx.new_model(|cx| {
|
||||
Context::local(
|
||||
registry.clone(),
|
||||
Some(project),
|
||||
None,
|
||||
prompt_builder.clone(),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
let buffer = context.read_with(cx, |context, _| context.buffer.clone());
|
||||
|
||||
// Simulate user input
|
||||
@@ -3070,7 +3095,10 @@ mod tests {
|
||||
cx.update(LanguageModelRegistry::test);
|
||||
cx.update(assistant_panel::init);
|
||||
let registry = Arc::new(LanguageRegistry::test(cx.executor()));
|
||||
let context = cx.new_model(|cx| Context::local(registry.clone(), None, None, cx));
|
||||
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
|
||||
let context = cx.new_model(|cx| {
|
||||
Context::local(registry.clone(), None, None, prompt_builder.clone(), cx)
|
||||
});
|
||||
let buffer = context.read_with(cx, |context, _| context.buffer.clone());
|
||||
let message_0 = context.read_with(cx, |context, _| context.message_anchors[0].id);
|
||||
let message_1 = context.update(cx, |context, cx| {
|
||||
@@ -3109,6 +3137,7 @@ mod tests {
|
||||
serialized_context,
|
||||
Default::default(),
|
||||
registry.clone(),
|
||||
prompt_builder.clone(),
|
||||
None,
|
||||
None,
|
||||
cx,
|
||||
@@ -3158,6 +3187,7 @@ mod tests {
|
||||
|
||||
let num_peers = rng.gen_range(min_peers..=max_peers);
|
||||
let context_id = ContextId::new();
|
||||
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
|
||||
for i in 0..num_peers {
|
||||
let context = cx.new_model(|cx| {
|
||||
Context::new(
|
||||
@@ -3165,6 +3195,7 @@ mod tests {
|
||||
i as ReplicaId,
|
||||
language::Capability::ReadWrite,
|
||||
registry.clone(),
|
||||
prompt_builder.clone(),
|
||||
None,
|
||||
None,
|
||||
cx,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
Context, ContextEvent, ContextId, ContextOperation, ContextVersion, SavedContext,
|
||||
SavedContextMetadata,
|
||||
prompts::PromptBuilder, Context, ContextEvent, ContextId, ContextOperation, ContextVersion,
|
||||
SavedContext, SavedContextMetadata,
|
||||
};
|
||||
use anyhow::{anyhow, Context as _, Result};
|
||||
use client::{proto, telemetry::Telemetry, Client, TypedEnvelope};
|
||||
@@ -52,6 +52,7 @@ pub struct ContextStore {
|
||||
project_is_shared: bool,
|
||||
client_subscription: Option<client::Subscription>,
|
||||
_project_subscriptions: Vec<gpui::Subscription>,
|
||||
prompt_builder: Arc<PromptBuilder>,
|
||||
}
|
||||
|
||||
pub enum ContextStoreEvent {
|
||||
@@ -82,7 +83,11 @@ impl ContextHandle {
|
||||
}
|
||||
|
||||
impl ContextStore {
|
||||
pub fn new(project: Model<Project>, cx: &mut AppContext) -> Task<Result<Model<Self>>> {
|
||||
pub fn new(
|
||||
project: Model<Project>,
|
||||
prompt_builder: Arc<PromptBuilder>,
|
||||
cx: &mut AppContext,
|
||||
) -> Task<Result<Model<Self>>> {
|
||||
let fs = project.read(cx).fs().clone();
|
||||
let languages = project.read(cx).languages().clone();
|
||||
let telemetry = project.read(cx).client().telemetry().clone();
|
||||
@@ -117,6 +122,7 @@ impl ContextStore {
|
||||
project_is_shared: false,
|
||||
client: project.read(cx).client(),
|
||||
project: project.clone(),
|
||||
prompt_builder,
|
||||
};
|
||||
this.handle_project_changed(project, cx);
|
||||
this.synchronize_contexts(cx);
|
||||
@@ -334,6 +340,7 @@ impl ContextStore {
|
||||
self.languages.clone(),
|
||||
Some(self.project.clone()),
|
||||
Some(self.telemetry.clone()),
|
||||
self.prompt_builder.clone(),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
@@ -358,6 +365,7 @@ impl ContextStore {
|
||||
let language_registry = self.languages.clone();
|
||||
let project = self.project.clone();
|
||||
let telemetry = self.telemetry.clone();
|
||||
let prompt_builder = self.prompt_builder.clone();
|
||||
let request = self.client.request(proto::CreateContext { project_id });
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let response = request.await?;
|
||||
@@ -369,6 +377,7 @@ impl ContextStore {
|
||||
replica_id,
|
||||
capability,
|
||||
language_registry,
|
||||
prompt_builder,
|
||||
Some(project),
|
||||
Some(telemetry),
|
||||
cx,
|
||||
@@ -417,6 +426,7 @@ impl ContextStore {
|
||||
SavedContext::from_json(&saved_context)
|
||||
}
|
||||
});
|
||||
let prompt_builder = self.prompt_builder.clone();
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let saved_context = load.await?;
|
||||
@@ -425,6 +435,7 @@ impl ContextStore {
|
||||
saved_context,
|
||||
path.clone(),
|
||||
languages,
|
||||
prompt_builder,
|
||||
Some(project),
|
||||
Some(telemetry),
|
||||
cx,
|
||||
@@ -493,6 +504,7 @@ impl ContextStore {
|
||||
project_id,
|
||||
context_id: context_id.to_proto(),
|
||||
});
|
||||
let prompt_builder = self.prompt_builder.clone();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let response = request.await?;
|
||||
let context_proto = response.context.context("invalid context")?;
|
||||
@@ -502,6 +514,7 @@ impl ContextStore {
|
||||
replica_id,
|
||||
capability,
|
||||
language_registry,
|
||||
prompt_builder,
|
||||
Some(project),
|
||||
Some(telemetry),
|
||||
cx,
|
||||
|
||||
@@ -2,7 +2,6 @@ use crate::{
|
||||
slash_command::SlashCommandCompletionProvider, AssistantPanel, InlineAssist, InlineAssistant,
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use assets::Assets;
|
||||
use chrono::{DateTime, Utc};
|
||||
use collections::{HashMap, HashSet};
|
||||
use editor::{actions::Tab, CurrentLineHighlight, Editor, EditorElement, EditorEvent, EditorStyle};
|
||||
@@ -12,8 +11,8 @@ use futures::{
|
||||
};
|
||||
use fuzzy::StringMatchCandidate;
|
||||
use gpui::{
|
||||
actions, point, size, transparent_black, AppContext, AssetSource, BackgroundExecutor, Bounds,
|
||||
EventEmitter, Global, HighlightStyle, PromptLevel, ReadGlobal, Subscription, Task, TextStyle,
|
||||
actions, point, size, transparent_black, AppContext, BackgroundExecutor, Bounds, EventEmitter,
|
||||
Global, HighlightStyle, PromptLevel, ReadGlobal, Subscription, Task, TextStyle,
|
||||
TitlebarOptions, UpdateGlobal, View, WindowBounds, WindowHandle, WindowOptions,
|
||||
};
|
||||
use heed::{
|
||||
@@ -1466,17 +1465,6 @@ impl PromptStore {
|
||||
fn first(&self) -> Option<PromptMetadata> {
|
||||
self.metadata_cache.read().metadata.first().cloned()
|
||||
}
|
||||
|
||||
pub fn step_resolution_prompt(&self) -> Result<String> {
|
||||
let path = "prompts/step_resolution.md";
|
||||
|
||||
Ok(String::from_utf8(
|
||||
Assets
|
||||
.load(path)?
|
||||
.ok_or_else(|| anyhow!("{path} not found"))?
|
||||
.to_vec(),
|
||||
)?)
|
||||
}
|
||||
}
|
||||
|
||||
/// Wraps a shared future to a prompt store so it can be assigned as a context global.
|
||||
|
||||
@@ -125,22 +125,20 @@ impl PromptBuilder {
|
||||
}
|
||||
|
||||
fn register_templates(handlebars: &mut Handlebars) -> Result<(), Box<TemplateError>> {
|
||||
let content_prompt = Assets::get("prompts/content_prompt.hbs")
|
||||
.expect("Content prompt template not found")
|
||||
.data;
|
||||
let terminal_assistant_prompt = Assets::get("prompts/terminal_assistant_prompt.hbs")
|
||||
.expect("Terminal assistant prompt template not found")
|
||||
.data;
|
||||
let mut register_template = |id: &str| {
|
||||
let prompt = Assets::get(&format!("prompts/{}.hbs", id))
|
||||
.unwrap_or_else(|| panic!("{} prompt template not found", id))
|
||||
.data;
|
||||
handlebars
|
||||
.register_template_string(id, String::from_utf8_lossy(&prompt))
|
||||
.map_err(Box::new)
|
||||
};
|
||||
|
||||
register_template("content_prompt")?;
|
||||
register_template("terminal_assistant_prompt")?;
|
||||
register_template("edit_workflow")?;
|
||||
register_template("step_resolution")?;
|
||||
|
||||
handlebars
|
||||
.register_template_string("content_prompt", String::from_utf8_lossy(&content_prompt))
|
||||
.map_err(Box::new)?;
|
||||
handlebars
|
||||
.register_template_string(
|
||||
"terminal_assistant_prompt",
|
||||
String::from_utf8_lossy(&terminal_assistant_prompt),
|
||||
)
|
||||
.map_err(Box::new)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -236,4 +234,12 @@ impl PromptBuilder {
|
||||
.lock()
|
||||
.render("terminal_assistant_prompt", &context)
|
||||
}
|
||||
|
||||
pub fn generate_workflow_prompt(&self) -> Result<String, RenderError> {
|
||||
self.handlebars.lock().render("edit_workflow", &())
|
||||
}
|
||||
|
||||
pub fn generate_step_resolution_prompt(&self) -> Result<String, RenderError> {
|
||||
self.handlebars.lock().render("step_resolution", &())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,27 @@
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use crate::prompts::PromptBuilder;
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::{Context as _, Result};
|
||||
use assets::Assets;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
|
||||
use anyhow::Result;
|
||||
use assistant_slash_command::{
|
||||
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
|
||||
};
|
||||
use gpui::{AppContext, AssetSource, Task, WeakView};
|
||||
use gpui::{AppContext, Task, WeakView};
|
||||
use language::LspAdapterDelegate;
|
||||
use text::LineEnding;
|
||||
use ui::prelude::*;
|
||||
|
||||
use workspace::Workspace;
|
||||
|
||||
pub(crate) struct WorkflowSlashCommand;
|
||||
pub(crate) struct WorkflowSlashCommand {
|
||||
prompt_builder: Arc<PromptBuilder>,
|
||||
}
|
||||
|
||||
impl WorkflowSlashCommand {
|
||||
pub fn new(prompt_builder: Arc<PromptBuilder>) -> Self {
|
||||
Self { prompt_builder }
|
||||
}
|
||||
}
|
||||
|
||||
impl SlashCommand for WorkflowSlashCommand {
|
||||
fn name(&self) -> String {
|
||||
@@ -46,26 +55,22 @@ impl SlashCommand for WorkflowSlashCommand {
|
||||
_argument: Option<&str>,
|
||||
_workspace: WeakView<Workspace>,
|
||||
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
|
||||
_cx: &mut WindowContext,
|
||||
cx: &mut WindowContext,
|
||||
) -> Task<Result<SlashCommandOutput>> {
|
||||
let mut text = match Assets
|
||||
.load("prompts/edit_workflow.md")
|
||||
.and_then(|prompt| prompt.context("prompts/edit_workflow.md not found"))
|
||||
{
|
||||
Ok(prompt) => String::from_utf8_lossy(&prompt).into_owned(),
|
||||
Err(error) => return Task::ready(Err(error)),
|
||||
};
|
||||
LineEnding::normalize(&mut text);
|
||||
let range = 0..text.len();
|
||||
let prompt_builder = self.prompt_builder.clone();
|
||||
cx.spawn(|_cx| async move {
|
||||
let text = prompt_builder.generate_workflow_prompt()?;
|
||||
let range = 0..text.len();
|
||||
|
||||
Task::ready(Ok(SlashCommandOutput {
|
||||
text,
|
||||
sections: vec![SlashCommandOutputSection {
|
||||
range,
|
||||
icon: IconName::Route,
|
||||
label: "Workflow".into(),
|
||||
}],
|
||||
run_commands_in_text: false,
|
||||
}))
|
||||
Ok(SlashCommandOutput {
|
||||
text,
|
||||
sections: vec![SlashCommandOutputSection {
|
||||
range,
|
||||
icon: IconName::Route,
|
||||
label: "Workflow".into(),
|
||||
}],
|
||||
run_commands_in_text: false,
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user