Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T02:58:53.470Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

extension.rs

222 lines · 7.0 KB · rust
1mod capabilities;
2pub mod extension_builder;
3mod extension_events;
4mod extension_host_proxy;
5mod extension_manifest;
6mod types;
7
8use std::path::{Path, PathBuf};
9use std::sync::Arc;
10
11use ::lsp::LanguageServerName;
12use anyhow::{Context as _, Result, bail};
13use async_trait::async_trait;
14use gpui::{App, Task};
15use language::LanguageName;
16use semver::Version;
17use task::{SpawnInTerminal, ZedDebugConfig};
18use util::rel_path::RelPath;
19
20pub use crate::capabilities::*;
21pub use crate::extension_events::*;
22pub use crate::extension_host_proxy::*;
23pub use crate::extension_manifest::*;
24pub use crate::types::*;
25
26/// Initializes the `extension` crate.
27pub fn init(cx: &mut App) {
28    extension_events::init(cx);
29    ExtensionHostProxy::default_global(cx);
30}
31
32#[async_trait]
33pub trait WorktreeDelegate: Send + Sync + 'static {
34    fn id(&self) -> u64;
35    fn root_path(&self) -> String;
36    async fn read_text_file(&self, path: &RelPath) -> Result<String>;
37    async fn which(&self, binary_name: String) -> Option<String>;
38    async fn shell_env(&self) -> Vec<(String, String)>;
39}
40
41pub trait ProjectDelegate: Send + Sync + 'static {
42    fn worktree_ids(&self) -> Vec<u64>;
43}
44
45pub trait KeyValueStoreDelegate: Send + Sync + 'static {
46    fn insert(&self, key: String, docs: String) -> Task<Result<()>>;
47}
48
49#[async_trait]
50pub trait Extension: Send + Sync + 'static {
51    /// Returns the [`ExtensionManifest`] for this extension.
52    fn manifest(&self) -> Arc<ExtensionManifest>;
53
54    /// Returns the path to this extension's working directory.
55    fn work_dir(&self) -> Arc<Path>;
56
57    /// Returns a path relative to this extension's working directory.
58    fn path_from_extension(&self, path: &Path) -> PathBuf {
59        path::normalize_path(&self.work_dir().join(path))
60    }
61
62    async fn language_server_command(
63        &self,
64        language_server_id: LanguageServerName,
65        language_name: LanguageName,
66        worktree: Arc<dyn WorktreeDelegate>,
67    ) -> Result<Command>;
68
69    async fn language_server_initialization_options(
70        &self,
71        language_server_id: LanguageServerName,
72        language_name: LanguageName,
73        worktree: Arc<dyn WorktreeDelegate>,
74    ) -> Result<Option<String>>;
75
76    async fn language_server_workspace_configuration(
77        &self,
78        language_server_id: LanguageServerName,
79        worktree: Arc<dyn WorktreeDelegate>,
80    ) -> Result<Option<String>>;
81
82    async fn language_server_initialization_options_schema(
83        &self,
84        language_server_id: LanguageServerName,
85        worktree: Arc<dyn WorktreeDelegate>,
86    ) -> Result<Option<String>>;
87
88    async fn language_server_workspace_configuration_schema(
89        &self,
90        language_server_id: LanguageServerName,
91        worktree: Arc<dyn WorktreeDelegate>,
92    ) -> Result<Option<String>>;
93
94    async fn language_server_additional_initialization_options(
95        &self,
96        language_server_id: LanguageServerName,
97        target_language_server_id: LanguageServerName,
98        worktree: Arc<dyn WorktreeDelegate>,
99    ) -> Result<Option<String>>;
100
101    async fn language_server_additional_workspace_configuration(
102        &self,
103        language_server_id: LanguageServerName,
104        target_language_server_id: LanguageServerName,
105        worktree: Arc<dyn WorktreeDelegate>,
106    ) -> Result<Option<String>>;
107
108    async fn labels_for_completions(
109        &self,
110        language_server_id: LanguageServerName,
111        completions: Vec<Completion>,
112    ) -> Result<Vec<Option<CodeLabel>>>;
113
114    async fn labels_for_symbols(
115        &self,
116        language_server_id: LanguageServerName,
117        symbols: Vec<Symbol>,
118    ) -> Result<Vec<Option<CodeLabel>>>;
119
120    async fn complete_slash_command_argument(
121        &self,
122        command: SlashCommand,
123        arguments: Vec<String>,
124    ) -> Result<Vec<SlashCommandArgumentCompletion>>;
125
126    async fn run_slash_command(
127        &self,
128        command: SlashCommand,
129        arguments: Vec<String>,
130        worktree: Option<Arc<dyn WorktreeDelegate>>,
131    ) -> Result<SlashCommandOutput>;
132
133    async fn context_server_command(
134        &self,
135        context_server_id: Arc<str>,
136        project: Arc<dyn ProjectDelegate>,
137    ) -> Result<Command>;
138
139    async fn context_server_configuration(
140        &self,
141        context_server_id: Arc<str>,
142        project: Arc<dyn ProjectDelegate>,
143    ) -> Result<Option<ContextServerConfiguration>>;
144
145    async fn suggest_docs_packages(&self, provider: Arc<str>) -> Result<Vec<String>>;
146
147    async fn index_docs(
148        &self,
149        provider: Arc<str>,
150        package_name: Arc<str>,
151        kv_store: Arc<dyn KeyValueStoreDelegate>,
152    ) -> Result<()>;
153
154    async fn get_dap_binary(
155        &self,
156        dap_name: Arc<str>,
157        config: DebugTaskDefinition,
158        user_installed_path: Option<PathBuf>,
159        worktree: Arc<dyn WorktreeDelegate>,
160    ) -> Result<DebugAdapterBinary>;
161
162    async fn dap_request_kind(
163        &self,
164        dap_name: Arc<str>,
165        config: serde_json::Value,
166    ) -> Result<StartDebuggingRequestArgumentsRequest>;
167
168    async fn dap_config_to_scenario(&self, config: ZedDebugConfig) -> Result<DebugScenario>;
169
170    async fn dap_locator_create_scenario(
171        &self,
172        locator_name: String,
173        build_config_template: BuildTaskTemplate,
174        resolved_label: String,
175        debug_adapter_name: String,
176    ) -> Result<Option<DebugScenario>>;
177    async fn run_dap_locator(
178        &self,
179        locator_name: String,
180        config: SpawnInTerminal,
181    ) -> Result<DebugRequest>;
182}
183
184pub fn parse_wasm_extension_version(extension_id: &str, wasm_bytes: &[u8]) -> Result<Version> {
185    let mut version = None;
186
187    for part in wasmparser::Parser::new(0).parse_all(wasm_bytes) {
188        if let wasmparser::Payload::CustomSection(s) =
189            part.context("error parsing wasm extension")?
190            && s.name() == "zed:api-version"
191        {
192            version = parse_wasm_extension_version_custom_section(s.data());
193            if version.is_none() {
194                bail!(
195                    "extension {} has invalid zed:api-version section: {:?}",
196                    extension_id,
197                    s.data()
198                );
199            }
200        }
201    }
202
203    // The reason we wait until we're done parsing all of the Wasm bytes to return the version
204    // is to work around a panic that can happen inside of Wasmtime when the bytes are invalid.
205    //
206    // By parsing the entirety of the Wasm bytes before we return, we're able to detect this problem
207    // earlier as an `Err` rather than as a panic.
208    version.with_context(|| format!("extension {extension_id} has no zed:api-version section"))
209}
210
211fn parse_wasm_extension_version_custom_section(data: &[u8]) -> Option<Version> {
212    if data.len() == 6 {
213        Some(Version::new(
214            u16::from_be_bytes([data[0], data[1]]) as _,
215            u16::from_be_bytes([data[2], data[3]]) as _,
216            u16::from_be_bytes([data[4], data[5]]) as _,
217        ))
218    } else {
219        None
220    }
221}
222
Served at tenant.openagents/omega Member data and write actions are omitted.