create_buffer.rs

  1use anyhow::{anyhow, Result};
  2use assistant_tooling::{LanguageModelTool, ProjectContext, ToolOutput};
  3use editor::Editor;
  4use gpui::{prelude::*, Model, Task, View, WeakView};
  5use project::Project;
  6use schemars::JsonSchema;
  7use serde::Deserialize;
  8use ui::prelude::*;
  9use util::ResultExt;
 10use workspace::Workspace;
 11
 12pub struct CreateBufferTool {
 13    workspace: WeakView<Workspace>,
 14    project: Model<Project>,
 15}
 16
 17impl CreateBufferTool {
 18    pub fn new(workspace: WeakView<Workspace>, project: Model<Project>) -> Self {
 19        Self { workspace, project }
 20    }
 21}
 22
 23#[derive(Debug, Clone, Deserialize, JsonSchema)]
 24pub struct CreateBufferInput {
 25    /// The contents of the buffer.
 26    text: String,
 27
 28    /// The name of the language to use for the buffer.
 29    ///
 30    /// This should be a human-readable name, like "Rust", "JavaScript", or "Python".
 31    language: String,
 32}
 33
 34impl LanguageModelTool for CreateBufferTool {
 35    type View = CreateBufferView;
 36
 37    fn name(&self) -> String {
 38        "create_buffer".to_string()
 39    }
 40
 41    fn description(&self) -> String {
 42        "Create a new buffer in the current codebase".to_string()
 43    }
 44
 45    fn view(&self, cx: &mut WindowContext) -> View<Self::View> {
 46        cx.new_view(|_cx| CreateBufferView {
 47            workspace: self.workspace.clone(),
 48            project: self.project.clone(),
 49            input: None,
 50            error: None,
 51        })
 52    }
 53}
 54
 55pub struct CreateBufferView {
 56    workspace: WeakView<Workspace>,
 57    project: Model<Project>,
 58    input: Option<CreateBufferInput>,
 59    error: Option<anyhow::Error>,
 60}
 61
 62impl Render for CreateBufferView {
 63    fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
 64        div().child("Opening a buffer")
 65    }
 66}
 67
 68impl ToolOutput for CreateBufferView {
 69    type Input = CreateBufferInput;
 70
 71    type SerializedState = ();
 72
 73    fn generate(&self, _project: &mut ProjectContext, _cx: &mut ViewContext<Self>) -> String {
 74        let Some(input) = self.input.as_ref() else {
 75            return "No input".to_string();
 76        };
 77
 78        match &self.error {
 79            None => format!("Created a new {} buffer", input.language),
 80            Some(err) => format!("Failed to create buffer: {err:?}"),
 81        }
 82    }
 83
 84    fn set_input(&mut self, input: Self::Input, _cx: &mut ViewContext<Self>) {
 85        self.input = Some(input);
 86    }
 87
 88    fn execute(&mut self, cx: &mut ViewContext<Self>) -> Task<Result<()>> {
 89        cx.spawn({
 90            let workspace = self.workspace.clone();
 91            let project = self.project.clone();
 92            let input = self.input.clone();
 93            |_this, mut cx| async move {
 94                let input = input.ok_or_else(|| anyhow!("no input"))?;
 95
 96                let text = input.text.clone();
 97                let language_name = input.language.clone();
 98                let language = cx
 99                    .update(|cx| {
100                        project
101                            .read(cx)
102                            .languages()
103                            .language_for_name(&language_name)
104                    })?
105                    .await?;
106
107                let buffer = cx
108                    .update(|cx| project.update(cx, |project, cx| project.create_buffer(cx)))?
109                    .await?;
110
111                buffer.update(&mut cx, |buffer, cx| {
112                    buffer.edit([(0..0, text)], None, cx);
113                    buffer.set_language(Some(language), cx)
114                })?;
115
116                workspace
117                    .update(&mut cx, |workspace, cx| {
118                        workspace.add_item_to_active_pane(
119                            Box::new(
120                                cx.new_view(|cx| Editor::for_buffer(buffer, Some(project), cx)),
121                            ),
122                            None,
123                            cx,
124                        );
125                    })
126                    .log_err();
127
128                Ok(())
129            }
130        })
131    }
132
133    fn serialize(&self, _cx: &mut ViewContext<Self>) -> Self::SerializedState {
134        ()
135    }
136
137    fn deserialize(
138        &mut self,
139        _output: Self::SerializedState,
140        _cx: &mut ViewContext<Self>,
141    ) -> Result<()> {
142        Ok(())
143    }
144}