1use std::sync::atomic::AtomicBool;
2use std::sync::Arc;
3
4use anyhow::Result;
5use assistant_slash_command::{
6 ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
7 SlashCommandResult,
8};
9use gpui::{Task, WeakView};
10use language::{BufferSnapshot, LspAdapterDelegate};
11use ui::prelude::*;
12use workspace::Workspace;
13
14use crate::prompts::PromptBuilder;
15
16pub(crate) struct WorkflowSlashCommand {
17 prompt_builder: Arc<PromptBuilder>,
18}
19
20impl WorkflowSlashCommand {
21 pub const NAME: &'static str = "workflow";
22
23 pub fn new(prompt_builder: Arc<PromptBuilder>) -> Self {
24 Self { prompt_builder }
25 }
26}
27
28impl SlashCommand for WorkflowSlashCommand {
29 fn name(&self) -> String {
30 Self::NAME.into()
31 }
32
33 fn description(&self) -> String {
34 "Insert prompt to opt into the edit workflow".into()
35 }
36
37 fn menu_text(&self) -> String {
38 self.description()
39 }
40
41 fn requires_argument(&self) -> bool {
42 false
43 }
44
45 fn complete_argument(
46 self: Arc<Self>,
47 _arguments: &[String],
48 _cancel: Arc<AtomicBool>,
49 _workspace: Option<WeakView<Workspace>>,
50 _cx: &mut WindowContext,
51 ) -> Task<Result<Vec<ArgumentCompletion>>> {
52 Task::ready(Ok(Vec::new()))
53 }
54
55 fn run(
56 self: Arc<Self>,
57 _arguments: &[String],
58 _context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
59 _context_buffer: BufferSnapshot,
60 _workspace: WeakView<Workspace>,
61 _delegate: Option<Arc<dyn LspAdapterDelegate>>,
62 cx: &mut WindowContext,
63 ) -> Task<SlashCommandResult> {
64 let prompt_builder = self.prompt_builder.clone();
65 cx.spawn(|_cx| async move {
66 let text = prompt_builder.generate_workflow_prompt()?;
67 let range = 0..text.len();
68
69 Ok(SlashCommandOutput {
70 text,
71 sections: vec![SlashCommandOutputSection {
72 range,
73 icon: IconName::Route,
74 label: "Workflow".into(),
75 metadata: None,
76 }],
77 run_commands_in_text: false,
78 }
79 .to_event_stream())
80 })
81 }
82}