context.rs

 1use gpui::SharedString;
 2use language_model::{LanguageModelRequestMessage, MessageContent};
 3use serde::{Deserialize, Serialize};
 4use util::post_inc;
 5
 6#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Serialize, Deserialize)]
 7pub struct ContextId(pub(crate) usize);
 8
 9impl ContextId {
10    pub fn post_inc(&mut self) -> Self {
11        Self(post_inc(&mut self.0))
12    }
13}
14
15/// Some context attached to a message in a thread.
16#[derive(Debug, Clone)]
17pub struct Context {
18    pub id: ContextId,
19    pub name: SharedString,
20    pub parent: Option<SharedString>,
21    pub tooltip: Option<SharedString>,
22    pub kind: ContextKind,
23    pub text: SharedString,
24}
25
26#[derive(Debug, Clone, PartialEq, Eq, Hash)]
27pub enum ContextKind {
28    File,
29    Directory,
30    FetchedUrl,
31    Thread,
32}
33
34pub fn attach_context_to_message(
35    message: &mut LanguageModelRequestMessage,
36    context: impl IntoIterator<Item = Context>,
37) {
38    let mut file_context = String::new();
39    let mut directory_context = String::new();
40    let mut fetch_context = String::new();
41    let mut thread_context = String::new();
42
43    for context in context.into_iter() {
44        match context.kind {
45            ContextKind::File { .. } => {
46                file_context.push_str(&context.text);
47                file_context.push('\n');
48            }
49            ContextKind::Directory => {
50                directory_context.push_str(&context.text);
51                directory_context.push('\n');
52            }
53            ContextKind::FetchedUrl => {
54                fetch_context.push_str(&context.name);
55                fetch_context.push('\n');
56                fetch_context.push_str(&context.text);
57                fetch_context.push('\n');
58            }
59            ContextKind::Thread => {
60                thread_context.push_str(&context.name);
61                thread_context.push('\n');
62                thread_context.push_str(&context.text);
63                thread_context.push('\n');
64            }
65        }
66    }
67
68    let mut context_text = String::new();
69    if !file_context.is_empty() {
70        context_text.push_str("The following files are available:\n");
71        context_text.push_str(&file_context);
72    }
73
74    if !directory_context.is_empty() {
75        context_text.push_str("The following directories are available:\n");
76        context_text.push_str(&directory_context);
77    }
78
79    if !fetch_context.is_empty() {
80        context_text.push_str("The following fetched results are available\n");
81        context_text.push_str(&fetch_context);
82    }
83
84    if !thread_context.is_empty() {
85        context_text.push_str("The following previous conversation threads are available\n");
86        context_text.push_str(&thread_context);
87    }
88
89    if !context_text.is_empty() {
90        message.content.push(MessageContent::Text(context_text));
91    }
92}