1use 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, 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 Input = CreateBufferInput;
36 type Output = ();
37 type View = CreateBufferView;
38
39 fn name(&self) -> String {
40 "create_buffer".to_string()
41 }
42
43 fn description(&self) -> String {
44 "Create a new buffer in the current codebase".to_string()
45 }
46
47 fn execute(&self, input: &Self::Input, cx: &mut WindowContext) -> Task<Result<Self::Output>> {
48 cx.spawn({
49 let workspace = self.workspace.clone();
50 let project = self.project.clone();
51 let text = input.text.clone();
52 let language_name = input.language.clone();
53 |mut cx| async move {
54 let language = cx
55 .update(|cx| {
56 project
57 .read(cx)
58 .languages()
59 .language_for_name(&language_name)
60 })?
61 .await?;
62
63 let buffer = cx
64 .update(|cx| project.update(cx, |project, cx| project.create_buffer(cx)))?
65 .await?;
66
67 buffer.update(&mut cx, |buffer, cx| {
68 buffer.edit([(0..0, text)], None, cx);
69 buffer.set_language(Some(language), cx)
70 })?;
71
72 workspace
73 .update(&mut cx, |workspace, cx| {
74 workspace.add_item_to_active_pane(
75 Box::new(
76 cx.new_view(|cx| Editor::for_buffer(buffer, Some(project), cx)),
77 ),
78 None,
79 cx,
80 );
81 })
82 .log_err();
83
84 Ok(())
85 }
86 })
87 }
88
89 fn output_view(
90 input: Self::Input,
91 output: Result<Self::Output>,
92 cx: &mut WindowContext,
93 ) -> View<Self::View> {
94 cx.new_view(|_cx| CreateBufferView {
95 language: input.language,
96 output,
97 })
98 }
99}
100
101pub struct CreateBufferView {
102 language: String,
103 output: Result<()>,
104}
105
106impl Render for CreateBufferView {
107 fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
108 div().child("Opening a buffer")
109 }
110}
111
112impl ToolOutput for CreateBufferView {
113 fn generate(&self, _: &mut ProjectContext, _: &mut WindowContext) -> String {
114 match &self.output {
115 Ok(_) => format!("Created a new {} buffer", self.language),
116 Err(err) => format!("Failed to create buffer: {err:?}"),
117 }
118 }
119}