embedded_scope.rs

 1use editor::MultiBuffer;
 2use gpui::{AppContext, Model, ModelContext, Subscription};
 3
 4use crate::{assistant_panel::Conversation, LanguageModelRequestMessage, Role};
 5
 6#[derive(Default)]
 7pub struct EmbeddedScope {
 8    active_buffer: Option<Model<MultiBuffer>>,
 9    active_buffer_enabled: bool,
10    active_buffer_subscription: Option<Subscription>,
11}
12
13impl EmbeddedScope {
14    pub fn new() -> Self {
15        Self {
16            active_buffer: None,
17            active_buffer_enabled: true,
18            active_buffer_subscription: None,
19        }
20    }
21
22    pub fn set_active_buffer(
23        &mut self,
24        buffer: Option<Model<MultiBuffer>>,
25        cx: &mut ModelContext<Conversation>,
26    ) {
27        self.active_buffer_subscription.take();
28
29        if let Some(active_buffer) = buffer.clone() {
30            self.active_buffer_subscription =
31                Some(cx.subscribe(&active_buffer, |conversation, _, e, cx| {
32                    if let multi_buffer::Event::Edited { .. } = e {
33                        conversation.count_remaining_tokens(cx)
34                    }
35                }));
36        }
37
38        self.active_buffer = buffer;
39    }
40
41    pub fn active_buffer(&self) -> Option<&Model<MultiBuffer>> {
42        self.active_buffer.as_ref()
43    }
44
45    pub fn active_buffer_enabled(&self) -> bool {
46        self.active_buffer_enabled
47    }
48
49    pub fn set_active_buffer_enabled(&mut self, enabled: bool) {
50        self.active_buffer_enabled = enabled;
51    }
52
53    /// Provide a message for the language model based on the active buffer.
54    pub fn message(&self, cx: &AppContext) -> Option<LanguageModelRequestMessage> {
55        if !self.active_buffer_enabled {
56            return None;
57        }
58
59        let active_buffer = self.active_buffer.as_ref()?;
60        let buffer = active_buffer.read(cx);
61
62        if let Some(singleton) = buffer.as_singleton() {
63            let singleton = singleton.read(cx);
64
65            let filename = singleton
66                .file()
67                .map(|file| file.path().to_string_lossy())
68                .unwrap_or("Untitled".into());
69
70            let text = singleton.text();
71
72            let language = singleton
73                .language()
74                .map(|l| {
75                    let name = l.code_fence_block_name();
76                    name.to_string()
77                })
78                .unwrap_or_default();
79
80            let markdown =
81                format!("User's active file `{filename}`:\n\n```{language}\n{text}```\n\n");
82
83            return Some(LanguageModelRequestMessage {
84                role: Role::System,
85                content: markdown,
86            });
87        }
88
89        None
90    }
91}