1use anyhow::Context as _;
2use assets::Assets;
3use assistant2::{tools::ProjectIndexTool, AssistantPanel};
4use assistant_tooling::ToolRegistry;
5use client::Client;
6use gpui::{actions, App, AppContext, KeyBinding, Task, View, WindowOptions};
7use language::LanguageRegistry;
8use project::Project;
9use semantic_index::{OpenAiEmbeddingModel, OpenAiEmbeddingProvider, SemanticIndex};
10use settings::{KeymapFile, DEFAULT_KEYMAP_PATH};
11use std::{
12 path::{Path, PathBuf},
13 sync::Arc,
14};
15use theme::LoadThemes;
16use ui::{div, prelude::*, Render};
17use util::{http::HttpClientWithUrl, ResultExt as _};
18
19actions!(example, [Quit]);
20
21fn main() {
22 let args: Vec<String> = std::env::args().collect();
23
24 env_logger::init();
25 App::new().with_assets(Assets).run(|cx| {
26 cx.bind_keys(Some(KeyBinding::new("cmd-q", Quit, None)));
27 cx.on_action(|_: &Quit, cx: &mut AppContext| {
28 cx.quit();
29 });
30
31 if args.len() < 2 {
32 eprintln!(
33 "Usage: cargo run --example assistant_example -p assistant2 -- <project_path>"
34 );
35 cx.quit();
36 return;
37 }
38
39 settings::init(cx);
40 language::init(cx);
41 Project::init_settings(cx);
42 editor::init(cx);
43 theme::init(LoadThemes::JustBase, cx);
44 Assets.load_fonts(cx).unwrap();
45 KeymapFile::load_asset(DEFAULT_KEYMAP_PATH, cx).unwrap();
46 client::init_settings(cx);
47 release_channel::init("0.130.0", cx);
48
49 let client = Client::production(cx);
50 {
51 let client = client.clone();
52 cx.spawn(|cx| async move { client.authenticate_and_connect(false, &cx).await })
53 .detach_and_log_err(cx);
54 }
55 assistant2::init(client.clone(), cx);
56
57 let language_registry = Arc::new(LanguageRegistry::new(
58 Task::ready(()),
59 cx.background_executor().clone(),
60 ));
61 let node_runtime = node_runtime::RealNodeRuntime::new(client.http_client());
62 languages::init(language_registry.clone(), node_runtime, cx);
63
64 let http = Arc::new(HttpClientWithUrl::new("http://localhost:11434"));
65
66 let api_key = std::env::var("OPENAI_API_KEY").expect("OPENAI_API_KEY not set");
67 let embedding_provider = OpenAiEmbeddingProvider::new(
68 http.clone(),
69 OpenAiEmbeddingModel::TextEmbedding3Small,
70 open_ai::OPEN_AI_API_URL.to_string(),
71 api_key,
72 );
73
74 cx.spawn(|mut cx| async move {
75 let mut semantic_index = SemanticIndex::new(
76 PathBuf::from("/tmp/semantic-index-db.mdb"),
77 Arc::new(embedding_provider),
78 &mut cx,
79 )
80 .await?;
81
82 let project_path = Path::new(&args[1]);
83 let project = Project::example([project_path], &mut cx).await;
84
85 cx.update(|cx| {
86 let fs = project.read(cx).fs().clone();
87
88 let project_index = semantic_index.project_index(project.clone(), cx);
89
90 cx.open_window(WindowOptions::default(), |cx| {
91 let mut tool_registry = ToolRegistry::new();
92 tool_registry
93 .register(ProjectIndexTool::new(project_index.clone(), fs.clone()), cx)
94 .context("failed to register ProjectIndexTool")
95 .log_err();
96
97 cx.new_view(|cx| Example::new(language_registry, Arc::new(tool_registry), cx))
98 });
99 cx.activate(true);
100 })
101 })
102 .detach_and_log_err(cx);
103 })
104}
105
106struct Example {
107 assistant_panel: View<AssistantPanel>,
108}
109
110impl Example {
111 fn new(
112 language_registry: Arc<LanguageRegistry>,
113 tool_registry: Arc<ToolRegistry>,
114 cx: &mut ViewContext<Self>,
115 ) -> Self {
116 Self {
117 assistant_panel: cx
118 .new_view(|cx| AssistantPanel::new(language_registry, tool_registry, cx)),
119 }
120 }
121}
122
123impl Render for Example {
124 fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl ui::prelude::IntoElement {
125 div().size_full().child(self.assistant_panel.clone())
126 }
127}