context.rs

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