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 kind: ContextKind,
21 pub text: SharedString,
22}
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
25pub enum ContextKind {
26 File,
27 Directory,
28 FetchedUrl,
29 Thread,
30}
31
32pub fn attach_context_to_message(
33 message: &mut LanguageModelRequestMessage,
34 context: impl IntoIterator<Item = Context>,
35) {
36 let mut file_context = String::new();
37 let mut directory_context = String::new();
38 let mut fetch_context = String::new();
39 let mut thread_context = String::new();
40
41 for context in context.into_iter() {
42 match context.kind {
43 ContextKind::File => {
44 file_context.push_str(&context.text);
45 file_context.push('\n');
46 }
47 ContextKind::Directory => {
48 directory_context.push_str(&context.text);
49 directory_context.push('\n');
50 }
51 ContextKind::FetchedUrl => {
52 fetch_context.push_str(&context.name);
53 fetch_context.push('\n');
54 fetch_context.push_str(&context.text);
55 fetch_context.push('\n');
56 }
57 ContextKind::Thread => {
58 thread_context.push_str(&context.name);
59 thread_context.push('\n');
60 thread_context.push_str(&context.text);
61 thread_context.push('\n');
62 }
63 }
64 }
65
66 let mut context_text = String::new();
67 if !file_context.is_empty() {
68 context_text.push_str("The following files are available:\n");
69 context_text.push_str(&file_context);
70 }
71
72 if !directory_context.is_empty() {
73 context_text.push_str("The following directories are available:\n");
74 context_text.push_str(&directory_context);
75 }
76
77 if !fetch_context.is_empty() {
78 context_text.push_str("The following fetched results are available\n");
79 context_text.push_str(&fetch_context);
80 }
81
82 if !thread_context.is_empty() {
83 context_text.push_str("The following previous conversation threads are available\n");
84 context_text.push_str(&thread_context);
85 }
86
87 if !context_text.is_empty() {
88 message.content.push(MessageContent::Text(context_text));
89 }
90}