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