1use assistant_context_editor::SavedContextMetadata;
2use chrono::{DateTime, Utc};
3use gpui::{Entity, prelude::*};
4
5use crate::thread_store::{SerializedThreadMetadata, ThreadStore};
6
7#[derive(Debug)]
8pub enum HistoryEntry {
9 Thread(SerializedThreadMetadata),
10 Context(SavedContextMetadata),
11}
12
13impl HistoryEntry {
14 pub fn updated_at(&self) -> DateTime<Utc> {
15 match self {
16 HistoryEntry::Thread(thread) => thread.updated_at,
17 HistoryEntry::Context(context) => context.mtime.to_utc(),
18 }
19 }
20}
21
22pub struct HistoryStore {
23 thread_store: Entity<ThreadStore>,
24 context_store: Entity<assistant_context_editor::ContextStore>,
25 _subscriptions: Vec<gpui::Subscription>,
26}
27
28impl HistoryStore {
29 pub fn new(
30 thread_store: Entity<ThreadStore>,
31 context_store: Entity<assistant_context_editor::ContextStore>,
32 cx: &mut Context<Self>,
33 ) -> Self {
34 let subscriptions = vec![
35 cx.observe(&thread_store, |_, _, cx| cx.notify()),
36 cx.observe(&context_store, |_, _, cx| cx.notify()),
37 ];
38
39 Self {
40 thread_store,
41 context_store,
42 _subscriptions: subscriptions,
43 }
44 }
45
46 pub fn entries(&self, cx: &mut Context<Self>) -> Vec<HistoryEntry> {
47 let mut history_entries = Vec::new();
48
49 #[cfg(debug_assertions)]
50 if std::env::var("ZED_SIMULATE_NO_THREAD_HISTORY").is_ok() {
51 return history_entries;
52 }
53
54 for thread in self
55 .thread_store
56 .update(cx, |this, _cx| this.reverse_chronological_threads())
57 {
58 history_entries.push(HistoryEntry::Thread(thread));
59 }
60
61 for context in self.context_store.update(cx, |this, _cx| this.contexts()) {
62 history_entries.push(HistoryEntry::Context(context));
63 }
64
65 history_entries.sort_unstable_by_key(|entry| std::cmp::Reverse(entry.updated_at()));
66 history_entries
67 }
68
69 pub fn recent_entries(&self, limit: usize, cx: &mut Context<Self>) -> Vec<HistoryEntry> {
70 self.entries(cx).into_iter().take(limit).collect()
71 }
72}