Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T03:43:00.117Z 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

wit.rs

1282 lines · 47.4 KB · rust
1mod since_v0_0_1;
2mod since_v0_0_4;
3mod since_v0_0_6;
4mod since_v0_1_0;
5mod since_v0_2_0;
6mod since_v0_3_0;
7mod since_v0_4_0;
8mod since_v0_5_0;
9mod since_v0_6_0;
10mod since_v0_8_0;
11use dap::DebugRequest;
12use extension::{DebugTaskDefinition, KeyValueStoreDelegate, WorktreeDelegate};
13use gpui::BackgroundExecutor;
14use language::LanguageName;
15use lsp::LanguageServerName;
16use release_channel::ReleaseChannel;
17use task::{DebugScenario, SpawnInTerminal, TaskTemplate, ZedDebugConfig};
18
19use latest::dap::StartDebuggingRequestArgumentsRequest;
20
21use super::{WasmState, wasm_engine};
22use anyhow::{Context as _, Result, anyhow};
23use semver::Version;
24use since_v0_8_0 as latest;
25use std::{ops::RangeInclusive, path::PathBuf, sync::Arc};
26use wasmtime::{
27    Store,
28    component::{Component, Linker, Resource},
29};
30
31#[cfg(test)]
32pub use latest::CodeLabelSpanLiteral;
33pub use latest::{
34    CodeLabel, CodeLabelSpan, Command, DebugAdapterBinary, ExtensionProject, Range, SlashCommand,
35    zed::extension::context_server::ContextServerConfiguration,
36    zed::extension::lsp::{
37        Completion, CompletionKind, CompletionLabelDetails, InsertTextFormat, Symbol, SymbolKind,
38    },
39    zed::extension::slash_command::{SlashCommandArgumentCompletion, SlashCommandOutput},
40};
41pub use since_v0_0_4::LanguageServerConfig;
42
43pub fn new_linker(
44    executor: &BackgroundExecutor,
45    f: impl FnOnce(&mut Linker<WasmState>) -> Result<()>,
46) -> Linker<WasmState> {
47    let mut linker = Linker::new(&wasm_engine(executor));
48    wasmtime_wasi::p2::add_to_linker_async(&mut linker).unwrap();
49    f(&mut linker).unwrap();
50    linker
51}
52
53/// Returns whether the given Wasm API version is supported by the Wasm host.
54pub fn is_supported_wasm_api_version(release_channel: ReleaseChannel, version: Version) -> bool {
55    wasm_api_version_range(release_channel).contains(&version)
56}
57
58/// Returns the Wasm API version range that is supported by the Wasm host.
59#[inline(always)]
60pub fn wasm_api_version_range(release_channel: ReleaseChannel) -> RangeInclusive<Version> {
61    // Note: The release channel can be used to stage a new version of the extension API.
62    let _ = release_channel;
63
64    let max_version = match release_channel {
65        ReleaseChannel::Dev | ReleaseChannel::Nightly => latest::MAX_VERSION,
66        ReleaseChannel::Stable | ReleaseChannel::Preview => since_v0_6_0::MAX_VERSION,
67    };
68
69    since_v0_0_1::MIN_VERSION..=max_version
70}
71
72/// Authorizes access to use unreleased versions of the Wasm API, based on the provided [`ReleaseChannel`].
73///
74/// Note: If there isn't currently an unreleased Wasm API version this function may be unused. Don't delete it!
75pub fn authorize_access_to_unreleased_wasm_api_version(
76    release_channel: ReleaseChannel,
77) -> Result<()> {
78    let allow_unreleased_version = match release_channel {
79        ReleaseChannel::Dev | ReleaseChannel::Nightly => true,
80        ReleaseChannel::Stable | ReleaseChannel::Preview => {
81            // We always allow the latest in tests so that the extension tests pass on release branches.
82            cfg!(any(test, feature = "test-support"))
83        }
84    };
85
86    anyhow::ensure!(
87        allow_unreleased_version,
88        "unreleased versions of the extension API can only be used on development builds of Omega"
89    );
90
91    Ok(())
92}
93
94pub enum Extension {
95    V0_8_0(since_v0_8_0::Extension),
96    V0_6_0(since_v0_6_0::Extension),
97    V0_5_0(since_v0_5_0::Extension),
98    V0_4_0(since_v0_4_0::Extension),
99    V0_3_0(since_v0_3_0::Extension),
100    V0_2_0(since_v0_2_0::Extension),
101    V0_1_0(since_v0_1_0::Extension),
102    V0_0_6(since_v0_0_6::Extension),
103    V0_0_4(since_v0_0_4::Extension),
104    V0_0_1(since_v0_0_1::Extension),
105}
106
107impl Extension {
108    pub async fn instantiate_async(
109        executor: &BackgroundExecutor,
110        store: &mut Store<WasmState>,
111        release_channel: ReleaseChannel,
112        version: Version,
113        component: &Component,
114    ) -> Result<Self> {
115        // Note: The release channel can be used to stage a new version of the extension API.
116        let _ = release_channel;
117
118        if version >= latest::MIN_VERSION {
119            authorize_access_to_unreleased_wasm_api_version(release_channel)?;
120
121            let extension =
122                latest::Extension::instantiate_async(store, component, latest::linker(executor))
123                    .await
124                    .context("failed to instantiate wasm extension")?;
125            Ok(Self::V0_8_0(extension))
126        } else if version >= since_v0_6_0::MIN_VERSION {
127            let extension = since_v0_6_0::Extension::instantiate_async(
128                store,
129                component,
130                since_v0_6_0::linker(executor),
131            )
132            .await
133            .context("failed to instantiate wasm extension")?;
134            Ok(Self::V0_6_0(extension))
135        } else if version >= since_v0_5_0::MIN_VERSION {
136            let extension = since_v0_5_0::Extension::instantiate_async(
137                store,
138                component,
139                since_v0_5_0::linker(executor),
140            )
141            .await
142            .context("failed to instantiate wasm extension")?;
143            Ok(Self::V0_5_0(extension))
144        } else if version >= since_v0_4_0::MIN_VERSION {
145            let extension = since_v0_4_0::Extension::instantiate_async(
146                store,
147                component,
148                since_v0_4_0::linker(executor),
149            )
150            .await
151            .context("failed to instantiate wasm extension")?;
152            Ok(Self::V0_4_0(extension))
153        } else if version >= since_v0_3_0::MIN_VERSION {
154            let extension = since_v0_3_0::Extension::instantiate_async(
155                store,
156                component,
157                since_v0_3_0::linker(executor),
158            )
159            .await
160            .context("failed to instantiate wasm extension")?;
161            Ok(Self::V0_3_0(extension))
162        } else if version >= since_v0_2_0::MIN_VERSION {
163            let extension = since_v0_2_0::Extension::instantiate_async(
164                store,
165                component,
166                since_v0_2_0::linker(executor),
167            )
168            .await
169            .context("failed to instantiate wasm extension")?;
170            Ok(Self::V0_2_0(extension))
171        } else if version >= since_v0_1_0::MIN_VERSION {
172            let extension = since_v0_1_0::Extension::instantiate_async(
173                store,
174                component,
175                since_v0_1_0::linker(executor),
176            )
177            .await
178            .context("failed to instantiate wasm extension")?;
179            Ok(Self::V0_1_0(extension))
180        } else if version >= since_v0_0_6::MIN_VERSION {
181            let extension = since_v0_0_6::Extension::instantiate_async(
182                store,
183                component,
184                since_v0_0_6::linker(executor),
185            )
186            .await
187            .context("failed to instantiate wasm extension")?;
188            Ok(Self::V0_0_6(extension))
189        } else if version >= since_v0_0_4::MIN_VERSION {
190            let extension = since_v0_0_4::Extension::instantiate_async(
191                store,
192                component,
193                since_v0_0_4::linker(executor),
194            )
195            .await
196            .context("failed to instantiate wasm extension")?;
197            Ok(Self::V0_0_4(extension))
198        } else {
199            let extension = since_v0_0_1::Extension::instantiate_async(
200                store,
201                component,
202                since_v0_0_1::linker(executor),
203            )
204            .await
205            .context("failed to instantiate wasm extension")?;
206            Ok(Self::V0_0_1(extension))
207        }
208    }
209
210    pub async fn call_init_extension(&self, store: &mut Store<WasmState>) -> Result<()> {
211        match self {
212            Extension::V0_8_0(ext) => ext.call_init_extension(store).await,
213            Extension::V0_6_0(ext) => ext.call_init_extension(store).await,
214            Extension::V0_5_0(ext) => ext.call_init_extension(store).await,
215            Extension::V0_4_0(ext) => ext.call_init_extension(store).await,
216            Extension::V0_3_0(ext) => ext.call_init_extension(store).await,
217            Extension::V0_2_0(ext) => ext.call_init_extension(store).await,
218            Extension::V0_1_0(ext) => ext.call_init_extension(store).await,
219            Extension::V0_0_6(ext) => ext.call_init_extension(store).await,
220            Extension::V0_0_4(ext) => ext.call_init_extension(store).await,
221            Extension::V0_0_1(ext) => ext.call_init_extension(store).await,
222        }
223    }
224
225    pub async fn call_language_server_command(
226        &self,
227        store: &mut Store<WasmState>,
228        language_server_id: &LanguageServerName,
229        language_name: &LanguageName,
230        resource: Resource<Arc<dyn WorktreeDelegate>>,
231    ) -> Result<Result<Command, String>> {
232        match self {
233            Extension::V0_8_0(ext) => {
234                ext.call_language_server_command(store, &language_server_id.0, resource)
235                    .await
236            }
237            Extension::V0_6_0(ext) => {
238                ext.call_language_server_command(store, &language_server_id.0, resource)
239                    .await
240            }
241            Extension::V0_5_0(ext) => {
242                ext.call_language_server_command(store, &language_server_id.0, resource)
243                    .await
244            }
245            Extension::V0_4_0(ext) => {
246                ext.call_language_server_command(store, &language_server_id.0, resource)
247                    .await
248            }
249            Extension::V0_3_0(ext) => {
250                ext.call_language_server_command(store, &language_server_id.0, resource)
251                    .await
252            }
253            Extension::V0_2_0(ext) => Ok(ext
254                .call_language_server_command(store, &language_server_id.0, resource)
255                .await?
256                .map(|command| command.into())),
257            Extension::V0_1_0(ext) => Ok(ext
258                .call_language_server_command(store, &language_server_id.0, resource)
259                .await?
260                .map(|command| command.into())),
261            Extension::V0_0_6(ext) => Ok(ext
262                .call_language_server_command(store, &language_server_id.0, resource)
263                .await?
264                .map(|command| command.into())),
265            Extension::V0_0_4(ext) => Ok(ext
266                .call_language_server_command(
267                    store,
268                    &LanguageServerConfig {
269                        name: language_server_id.0.to_string(),
270                        language_name: language_name.to_string(),
271                    },
272                    resource,
273                )
274                .await?
275                .map(|command| command.into())),
276            Extension::V0_0_1(ext) => Ok(ext
277                .call_language_server_command(
278                    store,
279                    &LanguageServerConfig {
280                        name: language_server_id.0.to_string(),
281                        language_name: language_name.to_string(),
282                    }
283                    .into(),
284                    resource,
285                )
286                .await?
287                .map(|command| command.into())),
288        }
289    }
290
291    pub async fn call_language_server_initialization_options(
292        &self,
293        store: &mut Store<WasmState>,
294        language_server_id: &LanguageServerName,
295        language_name: &LanguageName,
296        resource: Resource<Arc<dyn WorktreeDelegate>>,
297    ) -> Result<Result<Option<String>, String>> {
298        match self {
299            Extension::V0_8_0(ext) => {
300                ext.call_language_server_initialization_options(
301                    store,
302                    &language_server_id.0,
303                    resource,
304                )
305                .await
306            }
307            Extension::V0_6_0(ext) => {
308                ext.call_language_server_initialization_options(
309                    store,
310                    &language_server_id.0,
311                    resource,
312                )
313                .await
314            }
315            Extension::V0_5_0(ext) => {
316                ext.call_language_server_initialization_options(
317                    store,
318                    &language_server_id.0,
319                    resource,
320                )
321                .await
322            }
323            Extension::V0_4_0(ext) => {
324                ext.call_language_server_initialization_options(
325                    store,
326                    &language_server_id.0,
327                    resource,
328                )
329                .await
330            }
331            Extension::V0_3_0(ext) => {
332                ext.call_language_server_initialization_options(
333                    store,
334                    &language_server_id.0,
335                    resource,
336                )
337                .await
338            }
339            Extension::V0_2_0(ext) => {
340                ext.call_language_server_initialization_options(
341                    store,
342                    &language_server_id.0,
343                    resource,
344                )
345                .await
346            }
347            Extension::V0_1_0(ext) => {
348                ext.call_language_server_initialization_options(
349                    store,
350                    &language_server_id.0,
351                    resource,
352                )
353                .await
354            }
355            Extension::V0_0_6(ext) => {
356                ext.call_language_server_initialization_options(
357                    store,
358                    &language_server_id.0,
359                    resource,
360                )
361                .await
362            }
363            Extension::V0_0_4(ext) => {
364                ext.call_language_server_initialization_options(
365                    store,
366                    &LanguageServerConfig {
367                        name: language_server_id.0.to_string(),
368                        language_name: language_name.to_string(),
369                    },
370                    resource,
371                )
372                .await
373            }
374            Extension::V0_0_1(ext) => {
375                ext.call_language_server_initialization_options(
376                    store,
377                    &LanguageServerConfig {
378                        name: language_server_id.0.to_string(),
379                        language_name: language_name.to_string(),
380                    }
381                    .into(),
382                    resource,
383                )
384                .await
385            }
386        }
387    }
388
389    pub async fn call_language_server_workspace_configuration(
390        &self,
391        store: &mut Store<WasmState>,
392        language_server_id: &LanguageServerName,
393        resource: Resource<Arc<dyn WorktreeDelegate>>,
394    ) -> Result<Result<Option<String>, String>> {
395        match self {
396            Extension::V0_8_0(ext) => {
397                ext.call_language_server_workspace_configuration(
398                    store,
399                    &language_server_id.0,
400                    resource,
401                )
402                .await
403            }
404            Extension::V0_6_0(ext) => {
405                ext.call_language_server_workspace_configuration(
406                    store,
407                    &language_server_id.0,
408                    resource,
409                )
410                .await
411            }
412            Extension::V0_5_0(ext) => {
413                ext.call_language_server_workspace_configuration(
414                    store,
415                    &language_server_id.0,
416                    resource,
417                )
418                .await
419            }
420            Extension::V0_4_0(ext) => {
421                ext.call_language_server_workspace_configuration(
422                    store,
423                    &language_server_id.0,
424                    resource,
425                )
426                .await
427            }
428            Extension::V0_3_0(ext) => {
429                ext.call_language_server_workspace_configuration(
430                    store,
431                    &language_server_id.0,
432                    resource,
433                )
434                .await
435            }
436            Extension::V0_2_0(ext) => {
437                ext.call_language_server_workspace_configuration(
438                    store,
439                    &language_server_id.0,
440                    resource,
441                )
442                .await
443            }
444            Extension::V0_1_0(ext) => {
445                ext.call_language_server_workspace_configuration(
446                    store,
447                    &language_server_id.0,
448                    resource,
449                )
450                .await
451            }
452            Extension::V0_0_6(ext) => {
453                ext.call_language_server_workspace_configuration(
454                    store,
455                    &language_server_id.0,
456                    resource,
457                )
458                .await
459            }
460            Extension::V0_0_4(_) | Extension::V0_0_1(_) => Ok(Ok(None)),
461        }
462    }
463
464    pub async fn call_language_server_initialization_options_schema(
465        &self,
466        store: &mut Store<WasmState>,
467        language_server_id: &LanguageServerName,
468        resource: Resource<Arc<dyn WorktreeDelegate>>,
469    ) -> Result<Option<String>> {
470        match self {
471            Extension::V0_8_0(ext) => {
472                ext.call_language_server_initialization_options_schema(
473                    store,
474                    &language_server_id.0,
475                    resource,
476                )
477                .await
478            }
479            Extension::V0_6_0(_)
480            | Extension::V0_5_0(_)
481            | Extension::V0_4_0(_)
482            | Extension::V0_3_0(_)
483            | Extension::V0_2_0(_)
484            | Extension::V0_1_0(_)
485            | Extension::V0_0_6(_)
486            | Extension::V0_0_4(_)
487            | Extension::V0_0_1(_) => Ok(None),
488        }
489    }
490
491    pub async fn call_language_server_workspace_configuration_schema(
492        &self,
493        store: &mut Store<WasmState>,
494        language_server_id: &LanguageServerName,
495        resource: Resource<Arc<dyn WorktreeDelegate>>,
496    ) -> Result<Option<String>> {
497        match self {
498            Extension::V0_8_0(ext) => {
499                ext.call_language_server_workspace_configuration_schema(
500                    store,
501                    &language_server_id.0,
502                    resource,
503                )
504                .await
505            }
506            Extension::V0_6_0(_)
507            | Extension::V0_5_0(_)
508            | Extension::V0_4_0(_)
509            | Extension::V0_3_0(_)
510            | Extension::V0_2_0(_)
511            | Extension::V0_1_0(_)
512            | Extension::V0_0_6(_)
513            | Extension::V0_0_4(_)
514            | Extension::V0_0_1(_) => Ok(None),
515        }
516    }
517
518    pub async fn call_language_server_additional_initialization_options(
519        &self,
520        store: &mut Store<WasmState>,
521        language_server_id: &LanguageServerName,
522        target_language_server_id: &LanguageServerName,
523        resource: Resource<Arc<dyn WorktreeDelegate>>,
524    ) -> Result<Result<Option<String>, String>> {
525        match self {
526            Extension::V0_8_0(ext) => {
527                ext.call_language_server_additional_initialization_options(
528                    store,
529                    &language_server_id.0,
530                    &target_language_server_id.0,
531                    resource,
532                )
533                .await
534            }
535            Extension::V0_6_0(ext) => {
536                ext.call_language_server_additional_initialization_options(
537                    store,
538                    &language_server_id.0,
539                    &target_language_server_id.0,
540                    resource,
541                )
542                .await
543            }
544            Extension::V0_5_0(ext) => {
545                ext.call_language_server_additional_initialization_options(
546                    store,
547                    &language_server_id.0,
548                    &target_language_server_id.0,
549                    resource,
550                )
551                .await
552            }
553            Extension::V0_4_0(ext) => {
554                ext.call_language_server_additional_initialization_options(
555                    store,
556                    &language_server_id.0,
557                    &target_language_server_id.0,
558                    resource,
559                )
560                .await
561            }
562            Extension::V0_3_0(_)
563            | Extension::V0_2_0(_)
564            | Extension::V0_1_0(_)
565            | Extension::V0_0_6(_)
566            | Extension::V0_0_4(_)
567            | Extension::V0_0_1(_) => Ok(Ok(None)),
568        }
569    }
570
571    pub async fn call_language_server_additional_workspace_configuration(
572        &self,
573        store: &mut Store<WasmState>,
574        language_server_id: &LanguageServerName,
575        target_language_server_id: &LanguageServerName,
576        resource: Resource<Arc<dyn WorktreeDelegate>>,
577    ) -> Result<Result<Option<String>, String>> {
578        match self {
579            Extension::V0_8_0(ext) => {
580                ext.call_language_server_additional_workspace_configuration(
581                    store,
582                    &language_server_id.0,
583                    &target_language_server_id.0,
584                    resource,
585                )
586                .await
587            }
588            Extension::V0_6_0(ext) => {
589                ext.call_language_server_additional_workspace_configuration(
590                    store,
591                    &language_server_id.0,
592                    &target_language_server_id.0,
593                    resource,
594                )
595                .await
596            }
597            Extension::V0_5_0(ext) => {
598                ext.call_language_server_additional_workspace_configuration(
599                    store,
600                    &language_server_id.0,
601                    &target_language_server_id.0,
602                    resource,
603                )
604                .await
605            }
606            Extension::V0_4_0(ext) => {
607                ext.call_language_server_additional_workspace_configuration(
608                    store,
609                    &language_server_id.0,
610                    &target_language_server_id.0,
611                    resource,
612                )
613                .await
614            }
615            Extension::V0_3_0(_)
616            | Extension::V0_2_0(_)
617            | Extension::V0_1_0(_)
618            | Extension::V0_0_6(_)
619            | Extension::V0_0_4(_)
620            | Extension::V0_0_1(_) => Ok(Ok(None)),
621        }
622    }
623
624    pub async fn call_labels_for_completions(
625        &self,
626        store: &mut Store<WasmState>,
627        language_server_id: &LanguageServerName,
628        completions: Vec<latest::Completion>,
629    ) -> Result<Result<Vec<Option<CodeLabel>>, String>> {
630        match self {
631            Extension::V0_8_0(ext) => {
632                ext.call_labels_for_completions(store, &language_server_id.0, &completions)
633                    .await
634            }
635            Extension::V0_6_0(ext) => Ok(ext
636                .call_labels_for_completions(
637                    store,
638                    &language_server_id.0,
639                    &completions.into_iter().map(Into::into).collect::<Vec<_>>(),
640                )
641                .await?
642                .map(|labels| {
643                    labels
644                        .into_iter()
645                        .map(|label| label.map(Into::into))
646                        .collect()
647                })),
648            Extension::V0_5_0(ext) => Ok(ext
649                .call_labels_for_completions(
650                    store,
651                    &language_server_id.0,
652                    &completions.into_iter().map(Into::into).collect::<Vec<_>>(),
653                )
654                .await?
655                .map(|labels| {
656                    labels
657                        .into_iter()
658                        .map(|label| label.map(Into::into))
659                        .collect()
660                })),
661            Extension::V0_4_0(ext) => Ok(ext
662                .call_labels_for_completions(
663                    store,
664                    &language_server_id.0,
665                    &completions.into_iter().map(Into::into).collect::<Vec<_>>(),
666                )
667                .await?
668                .map(|labels| {
669                    labels
670                        .into_iter()
671                        .map(|label| label.map(Into::into))
672                        .collect()
673                })),
674            Extension::V0_3_0(ext) => Ok(ext
675                .call_labels_for_completions(
676                    store,
677                    &language_server_id.0,
678                    &completions.into_iter().map(Into::into).collect::<Vec<_>>(),
679                )
680                .await?
681                .map(|labels| {
682                    labels
683                        .into_iter()
684                        .map(|label| label.map(Into::into))
685                        .collect()
686                })),
687            Extension::V0_2_0(ext) => Ok(ext
688                .call_labels_for_completions(
689                    store,
690                    &language_server_id.0,
691                    &completions.into_iter().map(Into::into).collect::<Vec<_>>(),
692                )
693                .await?
694                .map(|labels| {
695                    labels
696                        .into_iter()
697                        .map(|label| label.map(Into::into))
698                        .collect()
699                })),
700            Extension::V0_1_0(ext) => Ok(ext
701                .call_labels_for_completions(
702                    store,
703                    &language_server_id.0,
704                    &completions.into_iter().map(Into::into).collect::<Vec<_>>(),
705                )
706                .await?
707                .map(|labels| {
708                    labels
709                        .into_iter()
710                        .map(|label| label.map(Into::into))
711                        .collect()
712                })),
713            Extension::V0_0_6(ext) => Ok(ext
714                .call_labels_for_completions(
715                    store,
716                    &language_server_id.0,
717                    &completions.into_iter().map(Into::into).collect::<Vec<_>>(),
718                )
719                .await?
720                .map(|labels| {
721                    labels
722                        .into_iter()
723                        .map(|label| label.map(Into::into))
724                        .collect()
725                })),
726            Extension::V0_0_1(_) | Extension::V0_0_4(_) => Ok(Ok(Vec::new())),
727        }
728    }
729
730    pub async fn call_labels_for_symbols(
731        &self,
732        store: &mut Store<WasmState>,
733        language_server_id: &LanguageServerName,
734        symbols: Vec<latest::Symbol>,
735    ) -> Result<Result<Vec<Option<CodeLabel>>, String>> {
736        match self {
737            Extension::V0_8_0(ext) => {
738                ext.call_labels_for_symbols(store, &language_server_id.0, &symbols)
739                    .await
740            }
741            Extension::V0_6_0(ext) => Ok(ext
742                .call_labels_for_symbols(
743                    store,
744                    &language_server_id.0,
745                    &symbols.into_iter().map(Into::into).collect::<Vec<_>>(),
746                )
747                .await?
748                .map(|labels| {
749                    labels
750                        .into_iter()
751                        .map(|label| label.map(Into::into))
752                        .collect()
753                })),
754            Extension::V0_5_0(ext) => Ok(ext
755                .call_labels_for_symbols(
756                    store,
757                    &language_server_id.0,
758                    &symbols.into_iter().map(Into::into).collect::<Vec<_>>(),
759                )
760                .await?
761                .map(|labels| {
762                    labels
763                        .into_iter()
764                        .map(|label| label.map(Into::into))
765                        .collect()
766                })),
767            Extension::V0_4_0(ext) => Ok(ext
768                .call_labels_for_symbols(
769                    store,
770                    &language_server_id.0,
771                    &symbols.into_iter().map(Into::into).collect::<Vec<_>>(),
772                )
773                .await?
774                .map(|labels| {
775                    labels
776                        .into_iter()
777                        .map(|label| label.map(Into::into))
778                        .collect()
779                })),
780            Extension::V0_3_0(ext) => Ok(ext
781                .call_labels_for_symbols(
782                    store,
783                    &language_server_id.0,
784                    &symbols.into_iter().map(Into::into).collect::<Vec<_>>(),
785                )
786                .await?
787                .map(|labels| {
788                    labels
789                        .into_iter()
790                        .map(|label| label.map(Into::into))
791                        .collect()
792                })),
793            Extension::V0_2_0(ext) => Ok(ext
794                .call_labels_for_symbols(
795                    store,
796                    &language_server_id.0,
797                    &symbols.into_iter().map(Into::into).collect::<Vec<_>>(),
798                )
799                .await?
800                .map(|labels| {
801                    labels
802                        .into_iter()
803                        .map(|label| label.map(Into::into))
804                        .collect()
805                })),
806            Extension::V0_1_0(ext) => Ok(ext
807                .call_labels_for_symbols(
808                    store,
809                    &language_server_id.0,
810                    &symbols.into_iter().map(Into::into).collect::<Vec<_>>(),
811                )
812                .await?
813                .map(|labels| {
814                    labels
815                        .into_iter()
816                        .map(|label| label.map(Into::into))
817                        .collect()
818                })),
819            Extension::V0_0_6(ext) => Ok(ext
820                .call_labels_for_symbols(
821                    store,
822                    &language_server_id.0,
823                    &symbols.into_iter().map(Into::into).collect::<Vec<_>>(),
824                )
825                .await?
826                .map(|labels| {
827                    labels
828                        .into_iter()
829                        .map(|label| label.map(Into::into))
830                        .collect()
831                })),
832            Extension::V0_0_1(_) | Extension::V0_0_4(_) => Ok(Ok(Vec::new())),
833        }
834    }
835
836    pub async fn call_complete_slash_command_argument(
837        &self,
838        store: &mut Store<WasmState>,
839        command: &SlashCommand,
840        arguments: &[String],
841    ) -> Result<Result<Vec<SlashCommandArgumentCompletion>, String>> {
842        match self {
843            Extension::V0_8_0(ext) => {
844                ext.call_complete_slash_command_argument(store, command, arguments)
845                    .await
846            }
847            Extension::V0_6_0(ext) => {
848                ext.call_complete_slash_command_argument(store, command, arguments)
849                    .await
850            }
851            Extension::V0_5_0(ext) => {
852                ext.call_complete_slash_command_argument(store, command, arguments)
853                    .await
854            }
855            Extension::V0_4_0(ext) => {
856                ext.call_complete_slash_command_argument(store, command, arguments)
857                    .await
858            }
859            Extension::V0_3_0(ext) => {
860                ext.call_complete_slash_command_argument(store, command, arguments)
861                    .await
862            }
863            Extension::V0_2_0(ext) => {
864                ext.call_complete_slash_command_argument(store, command, arguments)
865                    .await
866            }
867            Extension::V0_1_0(ext) => {
868                ext.call_complete_slash_command_argument(store, command, arguments)
869                    .await
870            }
871            Extension::V0_0_1(_) | Extension::V0_0_4(_) | Extension::V0_0_6(_) => {
872                Ok(Ok(Vec::new()))
873            }
874        }
875    }
876
877    pub async fn call_run_slash_command(
878        &self,
879        store: &mut Store<WasmState>,
880        command: &SlashCommand,
881        arguments: &[String],
882        resource: Option<Resource<Arc<dyn WorktreeDelegate>>>,
883    ) -> Result<Result<SlashCommandOutput, String>> {
884        match self {
885            Extension::V0_8_0(ext) => {
886                ext.call_run_slash_command(store, command, arguments, resource)
887                    .await
888            }
889            Extension::V0_6_0(ext) => {
890                ext.call_run_slash_command(store, command, arguments, resource)
891                    .await
892            }
893            Extension::V0_5_0(ext) => {
894                ext.call_run_slash_command(store, command, arguments, resource)
895                    .await
896            }
897            Extension::V0_4_0(ext) => {
898                ext.call_run_slash_command(store, command, arguments, resource)
899                    .await
900            }
901            Extension::V0_3_0(ext) => {
902                ext.call_run_slash_command(store, command, arguments, resource)
903                    .await
904            }
905            Extension::V0_2_0(ext) => {
906                ext.call_run_slash_command(store, command, arguments, resource)
907                    .await
908            }
909            Extension::V0_1_0(ext) => {
910                ext.call_run_slash_command(store, command, arguments, resource)
911                    .await
912            }
913            Extension::V0_0_1(_) | Extension::V0_0_4(_) | Extension::V0_0_6(_) => {
914                anyhow::bail!("`run_slash_command` not available prior to v0.1.0");
915            }
916        }
917    }
918
919    pub async fn call_context_server_command(
920        &self,
921        store: &mut Store<WasmState>,
922        context_server_id: Arc<str>,
923        project: Resource<ExtensionProject>,
924    ) -> Result<Result<Command, String>> {
925        match self {
926            Extension::V0_8_0(ext) => {
927                ext.call_context_server_command(store, &context_server_id, project)
928                    .await
929            }
930            Extension::V0_6_0(ext) => {
931                ext.call_context_server_command(store, &context_server_id, project)
932                    .await
933            }
934            Extension::V0_5_0(ext) => {
935                ext.call_context_server_command(store, &context_server_id, project)
936                    .await
937            }
938            Extension::V0_4_0(ext) => {
939                ext.call_context_server_command(store, &context_server_id, project)
940                    .await
941            }
942            Extension::V0_3_0(ext) => {
943                ext.call_context_server_command(store, &context_server_id, project)
944                    .await
945            }
946            Extension::V0_2_0(ext) => Ok(ext
947                .call_context_server_command(store, &context_server_id, project)
948                .await?
949                .map(Into::into)),
950            Extension::V0_0_1(_)
951            | Extension::V0_0_4(_)
952            | Extension::V0_0_6(_)
953            | Extension::V0_1_0(_) => {
954                anyhow::bail!("`context_server_command` not available prior to v0.2.0");
955            }
956        }
957    }
958
959    pub async fn call_context_server_configuration(
960        &self,
961        store: &mut Store<WasmState>,
962        context_server_id: Arc<str>,
963        project: Resource<ExtensionProject>,
964    ) -> Result<Result<Option<ContextServerConfiguration>, String>> {
965        match self {
966            Extension::V0_8_0(ext) => {
967                ext.call_context_server_configuration(store, &context_server_id, project)
968                    .await
969            }
970            Extension::V0_6_0(ext) => {
971                ext.call_context_server_configuration(store, &context_server_id, project)
972                    .await
973            }
974            Extension::V0_5_0(ext) => {
975                ext.call_context_server_configuration(store, &context_server_id, project)
976                    .await
977            }
978            Extension::V0_0_1(_)
979            | Extension::V0_0_4(_)
980            | Extension::V0_0_6(_)
981            | Extension::V0_1_0(_)
982            | Extension::V0_2_0(_)
983            | Extension::V0_3_0(_)
984            | Extension::V0_4_0(_) => {
985                anyhow::bail!("`context_server_configuration` not available prior to v0.5.0");
986            }
987        }
988    }
989
990    pub async fn call_suggest_docs_packages(
991        &self,
992        store: &mut Store<WasmState>,
993        provider: &str,
994    ) -> Result<Result<Vec<String>, String>> {
995        match self {
996            Extension::V0_8_0(ext) => ext.call_suggest_docs_packages(store, provider).await,
997            Extension::V0_6_0(ext) => ext.call_suggest_docs_packages(store, provider).await,
998            Extension::V0_5_0(ext) => ext.call_suggest_docs_packages(store, provider).await,
999            Extension::V0_4_0(ext) => ext.call_suggest_docs_packages(store, provider).await,
1000            Extension::V0_3_0(ext) => ext.call_suggest_docs_packages(store, provider).await,
1001            Extension::V0_2_0(ext) => ext.call_suggest_docs_packages(store, provider).await,
1002            Extension::V0_1_0(ext) => ext.call_suggest_docs_packages(store, provider).await,
1003            Extension::V0_0_1(_) | Extension::V0_0_4(_) | Extension::V0_0_6(_) => {
1004                anyhow::bail!("`suggest_docs_packages` not available prior to v0.1.0");
1005            }
1006        }
1007    }
1008
1009    pub async fn call_index_docs(
1010        &self,
1011        store: &mut Store<WasmState>,
1012        provider: &str,
1013        package_name: &str,
1014        kv_store: Resource<Arc<dyn KeyValueStoreDelegate>>,
1015    ) -> Result<Result<(), String>> {
1016        match self {
1017            Extension::V0_8_0(ext) => {
1018                ext.call_index_docs(store, provider, package_name, kv_store)
1019                    .await
1020            }
1021            Extension::V0_6_0(ext) => {
1022                ext.call_index_docs(store, provider, package_name, kv_store)
1023                    .await
1024            }
1025            Extension::V0_5_0(ext) => {
1026                ext.call_index_docs(store, provider, package_name, kv_store)
1027                    .await
1028            }
1029            Extension::V0_4_0(ext) => {
1030                ext.call_index_docs(store, provider, package_name, kv_store)
1031                    .await
1032            }
1033            Extension::V0_3_0(ext) => {
1034                ext.call_index_docs(store, provider, package_name, kv_store)
1035                    .await
1036            }
1037            Extension::V0_2_0(ext) => {
1038                ext.call_index_docs(store, provider, package_name, kv_store)
1039                    .await
1040            }
1041            Extension::V0_1_0(ext) => {
1042                ext.call_index_docs(store, provider, package_name, kv_store)
1043                    .await
1044            }
1045            Extension::V0_0_1(_) | Extension::V0_0_4(_) | Extension::V0_0_6(_) => {
1046                anyhow::bail!("`index_docs` not available prior to v0.1.0");
1047            }
1048        }
1049    }
1050
1051    pub async fn call_get_dap_binary(
1052        &self,
1053        store: &mut Store<WasmState>,
1054        adapter_name: Arc<str>,
1055        task: DebugTaskDefinition,
1056        user_installed_path: Option<PathBuf>,
1057        resource: Resource<Arc<dyn WorktreeDelegate>>,
1058    ) -> Result<Result<DebugAdapterBinary, String>> {
1059        match self {
1060            Extension::V0_8_0(ext) => {
1061                let dap_binary = ext
1062                    .call_get_dap_binary(
1063                        store,
1064                        &adapter_name,
1065                        &task.try_into()?,
1066                        user_installed_path.as_ref().and_then(|p| p.to_str()),
1067                        resource,
1068                    )
1069                    .await?
1070                    .map_err(|e| anyhow!("{e:?}"))?;
1071
1072                Ok(Ok(dap_binary))
1073            }
1074            Extension::V0_6_0(ext) => {
1075                let task: latest::DebugTaskDefinition = task.try_into()?;
1076                let dap_binary = ext
1077                    .call_get_dap_binary(
1078                        store,
1079                        &adapter_name,
1080                        &task.into(),
1081                        user_installed_path.as_ref().and_then(|p| p.to_str()),
1082                        resource,
1083                    )
1084                    .await?
1085                    .map_err(|e| anyhow!("{e:?}"))?;
1086
1087                Ok(Ok(dap_binary.into()))
1088            }
1089            Extension::V0_5_0(_)
1090            | Extension::V0_4_0(_)
1091            | Extension::V0_3_0(_)
1092            | Extension::V0_2_0(_)
1093            | Extension::V0_1_0(_)
1094            | Extension::V0_0_6(_)
1095            | Extension::V0_0_4(_)
1096            | Extension::V0_0_1(_) => {
1097                anyhow::bail!("`get_dap_binary` not available prior to v0.6.0");
1098            }
1099        }
1100    }
1101
1102    pub async fn call_dap_request_kind(
1103        &self,
1104        store: &mut Store<WasmState>,
1105        adapter_name: Arc<str>,
1106        config: serde_json::Value,
1107    ) -> Result<Result<StartDebuggingRequestArgumentsRequest, String>> {
1108        match self {
1109            Extension::V0_8_0(ext) => {
1110                let config =
1111                    serde_json::to_string(&config).context("Adapter config is not a valid JSON")?;
1112                let dap_binary = ext
1113                    .call_dap_request_kind(store, &adapter_name, &config)
1114                    .await?
1115                    .map_err(|e| anyhow!("{e:?}"))?;
1116
1117                Ok(Ok(dap_binary))
1118            }
1119            Extension::V0_6_0(ext) => {
1120                let config =
1121                    serde_json::to_string(&config).context("Adapter config is not a valid JSON")?;
1122                let dap_binary = ext
1123                    .call_dap_request_kind(store, &adapter_name, &config)
1124                    .await?
1125                    .map_err(|e| anyhow!("{e:?}"))?;
1126
1127                Ok(Ok(dap_binary.into()))
1128            }
1129            Extension::V0_5_0(_)
1130            | Extension::V0_4_0(_)
1131            | Extension::V0_3_0(_)
1132            | Extension::V0_2_0(_)
1133            | Extension::V0_1_0(_)
1134            | Extension::V0_0_6(_)
1135            | Extension::V0_0_4(_)
1136            | Extension::V0_0_1(_) => {
1137                anyhow::bail!("`dap_request_kind` not available prior to v0.6.0");
1138            }
1139        }
1140    }
1141
1142    pub async fn call_dap_config_to_scenario(
1143        &self,
1144        store: &mut Store<WasmState>,
1145        config: ZedDebugConfig,
1146    ) -> Result<Result<DebugScenario, String>> {
1147        match self {
1148            Extension::V0_8_0(ext) => {
1149                let config = config.into();
1150                let dap_binary = ext
1151                    .call_dap_config_to_scenario(store, &config)
1152                    .await?
1153                    .map_err(|e| anyhow!("{e:?}"))?;
1154
1155                Ok(Ok(dap_binary.try_into()?))
1156            }
1157            Extension::V0_6_0(ext) => {
1158                let config: latest::DebugConfig = config.into();
1159                let dap_binary = ext
1160                    .call_dap_config_to_scenario(store, &config.into())
1161                    .await?
1162                    .map_err(|e| anyhow!("{e:?}"))?;
1163
1164                let dap_binary: latest::DebugScenario = dap_binary.into();
1165                Ok(Ok(dap_binary.try_into()?))
1166            }
1167            Extension::V0_5_0(_)
1168            | Extension::V0_4_0(_)
1169            | Extension::V0_3_0(_)
1170            | Extension::V0_2_0(_)
1171            | Extension::V0_1_0(_)
1172            | Extension::V0_0_6(_)
1173            | Extension::V0_0_4(_)
1174            | Extension::V0_0_1(_) => {
1175                anyhow::bail!("`dap_config_to_scenario` not available prior to v0.6.0");
1176            }
1177        }
1178    }
1179
1180    pub async fn call_dap_locator_create_scenario(
1181        &self,
1182        store: &mut Store<WasmState>,
1183        locator_name: String,
1184        build_config_template: TaskTemplate,
1185        resolved_label: String,
1186        debug_adapter_name: String,
1187    ) -> Result<Option<DebugScenario>> {
1188        match self {
1189            Extension::V0_8_0(ext) => {
1190                let build_config_template = build_config_template.into();
1191                let dap_binary = ext
1192                    .call_dap_locator_create_scenario(
1193                        store,
1194                        &locator_name,
1195                        &build_config_template,
1196                        &resolved_label,
1197                        &debug_adapter_name,
1198                    )
1199                    .await?;
1200
1201                Ok(dap_binary.map(TryInto::try_into).transpose()?)
1202            }
1203            Extension::V0_6_0(ext) => {
1204                let build_config_template: latest::dap::TaskTemplate = build_config_template.into();
1205                let dap_binary = ext
1206                    .call_dap_locator_create_scenario(
1207                        store,
1208                        &locator_name,
1209                        &build_config_template.into(),
1210                        &resolved_label,
1211                        &debug_adapter_name,
1212                    )
1213                    .await?;
1214
1215                Ok(dap_binary
1216                    .map(|s| latest::DebugScenario::from(s).try_into())
1217                    .transpose()?)
1218            }
1219            Extension::V0_5_0(_)
1220            | Extension::V0_4_0(_)
1221            | Extension::V0_3_0(_)
1222            | Extension::V0_2_0(_)
1223            | Extension::V0_1_0(_)
1224            | Extension::V0_0_6(_)
1225            | Extension::V0_0_4(_)
1226            | Extension::V0_0_1(_) => {
1227                anyhow::bail!("`dap_locator_create_scenario` not available prior to v0.6.0");
1228            }
1229        }
1230    }
1231
1232    pub async fn call_run_dap_locator(
1233        &self,
1234        store: &mut Store<WasmState>,
1235        locator_name: String,
1236        resolved_build_task: SpawnInTerminal,
1237    ) -> Result<Result<DebugRequest, String>> {
1238        match self {
1239            Extension::V0_8_0(ext) => {
1240                let build_config_template = resolved_build_task.try_into()?;
1241                let dap_request = ext
1242                    .call_run_dap_locator(store, &locator_name, &build_config_template)
1243                    .await?
1244                    .map_err(|e| anyhow!("{e:?}"))?;
1245
1246                Ok(Ok(dap_request.into()))
1247            }
1248            Extension::V0_6_0(ext) => {
1249                let build_config_template: latest::dap::TaskTemplate =
1250                    resolved_build_task.try_into()?;
1251                let dap_request = ext
1252                    .call_run_dap_locator(store, &locator_name, &build_config_template.into())
1253                    .await?
1254                    .map_err(|e| anyhow!("{e:?}"))?;
1255
1256                let dap_request: latest::DebugRequest = dap_request.into();
1257                Ok(Ok(dap_request.into()))
1258            }
1259            Extension::V0_5_0(_)
1260            | Extension::V0_4_0(_)
1261            | Extension::V0_3_0(_)
1262            | Extension::V0_2_0(_)
1263            | Extension::V0_1_0(_)
1264            | Extension::V0_0_6(_)
1265            | Extension::V0_0_4(_)
1266            | Extension::V0_0_1(_) => {
1267                anyhow::bail!("`run_dap_locator` not available prior to v0.6.0");
1268            }
1269        }
1270    }
1271}
1272
1273trait ToWasmtimeResult<T> {
1274    fn to_wasmtime_result(self) -> wasmtime::Result<Result<T, String>>;
1275}
1276
1277impl<T> ToWasmtimeResult<T> for Result<T> {
1278    fn to_wasmtime_result(self) -> wasmtime::Result<Result<T, String>> {
1279        Ok(self.map_err(|error| format!("{error:?}")))
1280    }
1281}
1282
Served at tenant.openagents/omega Member data and write actions are omitted.