active_thread.rs

  1use agent::{ActiveThread, ContextStore, MessageSegment, TextThreadStore, ThreadStore};
  2use anyhow::{Result, anyhow};
  3use assistant_tool::ToolWorkingSet;
  4use gpui::{AppContext, AsyncApp, Entity, Task, WeakEntity};
  5use indoc::indoc;
  6use languages::LanguageRegistry;
  7use project::Project;
  8use prompt_store::PromptBuilder;
  9use std::sync::Arc;
 10use ui::{App, Window};
 11use workspace::Workspace;
 12
 13pub fn load_preview_thread_store(
 14    workspace: WeakEntity<Workspace>,
 15    project: Entity<Project>,
 16    cx: &mut AsyncApp,
 17) -> Task<Result<Entity<ThreadStore>>> {
 18    workspace
 19        .update(cx, |_, cx| {
 20            ThreadStore::load(
 21                project.clone(),
 22                cx.new(|_| ToolWorkingSet::default()),
 23                None,
 24                Arc::new(PromptBuilder::new(None).unwrap()),
 25                cx,
 26            )
 27        })
 28        .unwrap_or(Task::ready(Err(anyhow!("workspace dropped"))))
 29}
 30
 31pub fn load_preview_text_thread_store(
 32    workspace: WeakEntity<Workspace>,
 33    project: Entity<Project>,
 34    cx: &mut AsyncApp,
 35) -> Task<Result<Entity<TextThreadStore>>> {
 36    workspace
 37        .update(cx, |_, cx| {
 38            TextThreadStore::new(
 39                project.clone(),
 40                Arc::new(PromptBuilder::new(None).unwrap()),
 41                Default::default(),
 42                cx,
 43            )
 44        })
 45        .unwrap_or(Task::ready(Err(anyhow!("workspace dropped"))))
 46}
 47
 48pub fn static_active_thread(
 49    workspace: WeakEntity<Workspace>,
 50    project: Entity<Project>,
 51    language_registry: Arc<LanguageRegistry>,
 52    thread_store: Entity<ThreadStore>,
 53    text_thread_store: Entity<TextThreadStore>,
 54    window: &mut Window,
 55    cx: &mut App,
 56) -> Entity<ActiveThread> {
 57    let context_store =
 58        cx.new(|_| ContextStore::new(project.downgrade(), Some(thread_store.downgrade())));
 59
 60    let thread = thread_store.update(cx, |thread_store, cx| thread_store.create_thread(cx));
 61    thread.update(cx, |thread, cx| {
 62        thread.insert_assistant_message(vec![
 63            MessageSegment::Text(indoc! {"
 64                I'll help you fix the lifetime error in your `cx.spawn` call. When working with async operations in GPUI, there are specific patterns to follow for proper lifetime management.
 65
 66                Let's look at what's happening in your code:
 67
 68                ---
 69
 70                Let's check the current state of the active_thread.rs file to understand what might have changed:
 71
 72                ---
 73
 74                Looking at the implementation of `load_preview_thread_store` and understanding GPUI's async patterns, here's the issue:
 75
 76                1. `load_preview_thread_store` returns a `Task<anyhow::Result<Entity<ThreadStore>>>`, which means it's already a task.
 77                2. When you call this function inside another `spawn` call, you're nesting tasks incorrectly.
 78
 79                Here's the correct way to implement this:
 80
 81                ---
 82
 83                The problem is in how you're setting up the async closure and trying to reference variables like `window` and `language_registry` that aren't accessible in that scope.
 84
 85                Here's how to fix it:
 86            "}.to_string()),
 87        ], cx);
 88    });
 89    cx.new(|cx| {
 90        ActiveThread::new(
 91            thread,
 92            thread_store,
 93            text_thread_store,
 94            context_store,
 95            language_registry,
 96            workspace.clone(),
 97            window,
 98            cx,
 99        )
100    })
101}