wit.rs

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