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.thread_store.update(cx, |this, _cx| this.threads()) {
55 history_entries.push(HistoryEntry::Thread(thread));
56 }
57
58 for context in self.context_store.update(cx, |this, _cx| this.contexts()) {
59 history_entries.push(HistoryEntry::Context(context));
60 }
61
62 history_entries.sort_unstable_by_key(|entry| std::cmp::Reverse(entry.updated_at()));
63 history_entries
64 }
65
66 pub fn recent_entries(&self, limit: usize, cx: &mut Context<Self>) -> Vec<HistoryEntry> {
67 self.entries(cx).into_iter().take(limit).collect()
68 }
69}