) {}
+
+ fn assert(&mut self) {}
+}
+
+pub fn eval(
+ iterations: usize,
+ expected_pass_ratio: f32,
+ mut processor: P,
+ evalf: impl Fn() -> EvalOutput + Send + Sync + 'static,
+) where
+ P: EvalOutputProcessor,
+{
+ let mut evaluated_count = 0;
+ let mut failed_count = 0;
+ let evalf = Arc::new(evalf);
+ report_progress(evaluated_count, failed_count, iterations);
+
+ let (tx, rx) = mpsc::channel();
+
+ let executor = gpui::background_executor();
+ let semaphore = Arc::new(smol::lock::Semaphore::new(32));
+ let evalf = Arc::new(evalf);
+ // Warm the cache once
+ let first_output = evalf();
+ tx.send(first_output).ok();
+
+ for _ in 1..iterations {
+ let tx = tx.clone();
+ let semaphore = semaphore.clone();
+ let evalf = evalf.clone();
+ executor
+ .spawn(async move {
+ let _guard = semaphore.acquire().await;
+ let output = evalf();
+ tx.send(output).ok();
+ })
+ .detach();
+ }
+ drop(tx);
+
+ let mut failed_evals = Vec::new();
+ let mut errored_evals = HashMap::new();
+ while let Ok(output) = rx.recv() {
+ processor.process(&output);
+
+ match output.outcome {
+ OutcomeKind::Passed => {}
+ OutcomeKind::Failed => {
+ failed_count += 1;
+ failed_evals.push(output);
+ }
+ OutcomeKind::Error => {
+ failed_count += 1;
+ *errored_evals.entry(output.data).or_insert(0) += 1;
+ }
+ }
+
+ evaluated_count += 1;
+ report_progress(evaluated_count, failed_count, iterations);
+ }
+
+ let actual_pass_ratio = (iterations - failed_count) as f32 / iterations as f32;
+ println!("Actual pass ratio: {}\n", actual_pass_ratio);
+ if actual_pass_ratio < expected_pass_ratio {
+ for (error, count) in errored_evals {
+ println!("Eval errored {} times. Error: {}", count, error);
+ }
+
+ for failed in failed_evals {
+ println!("Eval failed");
+ println!("{}", failed.data);
+ }
+
+ panic!(
+ "Actual pass ratio: {}\nExpected pass ratio: {}",
+ actual_pass_ratio, expected_pass_ratio
+ );
+ }
+
+ processor.assert();
+}
diff --git a/crates/extension_api/Cargo.toml b/crates/extension_api/Cargo.toml
index 318a0024bf4d9bae76af888b6668d7c21f37f804..829455e62912883bea85f429a1a8917e6360d0fb 100644
--- a/crates/extension_api/Cargo.toml
+++ b/crates/extension_api/Cargo.toml
@@ -1,12 +1,13 @@
[package]
name = "zed_extension_api"
-version = "0.7.0"
+version = "0.8.0"
description = "APIs for creating Zed extensions in Rust"
repository = "https://github.com/zed-industries/zed"
documentation = "https://docs.rs/zed_extension_api"
keywords = ["zed", "extension"]
edition.workspace = true
-publish = true
+# Change back to `true` when we're ready to publish v0.8.0.
+publish = false
license = "Apache-2.0"
[lints]
diff --git a/crates/extension_api/src/extension_api.rs b/crates/extension_api/src/extension_api.rs
index daafb63c278cacca0a9275d8e4e9db22cef209d0..ac0827cd014d77b582aaf7db2da8fbc55a05f957 100644
--- a/crates/extension_api/src/extension_api.rs
+++ b/crates/extension_api/src/extension_api.rs
@@ -274,10 +274,6 @@ pub trait Extension: Send + Sync {
Err("`run_dap_locator` not implemented".to_string())
}
- // =========================================================================
- // Language Model Provider Methods
- // =========================================================================
-
/// Returns information about language model providers offered by this extension.
fn llm_providers(&self) -> Vec {
Vec::new()
@@ -427,7 +423,7 @@ mod wit {
wit_bindgen::generate!({
skip: ["init-extension"],
- path: "./wit/since_v0.7.0",
+ path: "./wit/since_v0.8.0",
});
}
@@ -612,10 +608,6 @@ impl wit::Guest for Component {
extension().run_dap_locator(locator_name, build_task)
}
- // =========================================================================
- // Language Model Provider Methods
- // =========================================================================
-
fn llm_providers() -> Vec {
extension().llm_providers()
}
diff --git a/crates/extension_api/wit/since_v0.8.0/common.wit b/crates/extension_api/wit/since_v0.8.0/common.wit
new file mode 100644
index 0000000000000000000000000000000000000000..139e7ba0ca4d1cc5ac78ccd23673ca749d6e46b2
--- /dev/null
+++ b/crates/extension_api/wit/since_v0.8.0/common.wit
@@ -0,0 +1,12 @@
+interface common {
+ /// A (half-open) range (`[start, end)`).
+ record range {
+ /// The start of the range (inclusive).
+ start: u32,
+ /// The end of the range (exclusive).
+ end: u32,
+ }
+
+ /// A list of environment variables.
+ type env-vars = list>;
+}
diff --git a/crates/extension_api/wit/since_v0.8.0/context-server.wit b/crates/extension_api/wit/since_v0.8.0/context-server.wit
new file mode 100644
index 0000000000000000000000000000000000000000..7234e0e6d0f6d444e92a056a92f6c90c7dc053b4
--- /dev/null
+++ b/crates/extension_api/wit/since_v0.8.0/context-server.wit
@@ -0,0 +1,11 @@
+interface context-server {
+ /// Configuration for context server setup and installation.
+ record context-server-configuration {
+ /// Installation instructions in Markdown format.
+ installation-instructions: string,
+ /// JSON schema for settings validation.
+ settings-schema: string,
+ /// Default settings template.
+ default-settings: string,
+ }
+}
diff --git a/crates/extension_api/wit/since_v0.8.0/dap.wit b/crates/extension_api/wit/since_v0.8.0/dap.wit
new file mode 100644
index 0000000000000000000000000000000000000000..693befe02f9c313455facd4839572528c3408fd1
--- /dev/null
+++ b/crates/extension_api/wit/since_v0.8.0/dap.wit
@@ -0,0 +1,123 @@
+interface dap {
+ use common.{env-vars};
+
+ /// Resolves a specified TcpArgumentsTemplate into TcpArguments
+ resolve-tcp-template: func(template: tcp-arguments-template) -> result;
+
+ record launch-request {
+ program: string,
+ cwd: option,
+ args: list,
+ envs: env-vars,
+ }
+
+ record attach-request {
+ process-id: option,
+ }
+
+ variant debug-request {
+ launch(launch-request),
+ attach(attach-request)
+ }
+
+ record tcp-arguments {
+ port: u16,
+ host: u32,
+ timeout: option,
+ }
+
+ record tcp-arguments-template {
+ port: option,
+ host: option,
+ timeout: option,
+ }
+
+ /// Debug Config is the "highest-level" configuration for a debug session.
+ /// It comes from a new process modal UI; thus, it is essentially debug-adapter-agnostic.
+ /// It is expected of the extension to translate this generic configuration into something that can be debugged by the adapter (debug scenario).
+ record debug-config {
+ /// Name of the debug task
+ label: string,
+ /// The debug adapter to use
+ adapter: string,
+ request: debug-request,
+ stop-on-entry: option,
+ }
+
+ record task-template {
+ /// Human readable name of the task to display in the UI.
+ label: string,
+ /// Executable command to spawn.
+ command: string,
+ args: list,
+ env: env-vars,
+ cwd: option,
+ }
+
+ /// A task template with substituted task variables.
+ type resolved-task = task-template;
+
+ /// A task template for building a debug target.
+ type build-task-template = task-template;
+
+ variant build-task-definition {
+ by-name(string),
+ template(build-task-definition-template-payload )
+ }
+ record build-task-definition-template-payload {
+ locator-name: option,
+ template: build-task-template
+ }
+
+ /// Debug Scenario is the user-facing configuration type (used in debug.json). It is still concerned with what to debug and not necessarily how to do it (except for any
+ /// debug-adapter-specific configuration options).
+ record debug-scenario {
+ /// Unsubstituted label for the task.DebugAdapterBinary
+ label: string,
+ /// Name of the Debug Adapter this configuration is intended for.
+ adapter: string,
+ /// An optional build step to be ran prior to starting a debug session. Build steps are used by Zed's locators to locate the executable to debug.
+ build: option,
+ /// JSON-encoded configuration for a given debug adapter.
+ config: string,
+ /// TCP connection parameters (if they were specified by user)
+ tcp-connection: option,
+ }
+
+ enum start-debugging-request-arguments-request {
+ launch,
+ attach,
+ }
+
+ record debug-task-definition {
+ /// Unsubstituted label for the task.DebugAdapterBinary
+ label: string,
+ /// Name of the Debug Adapter this configuration is intended for.
+ adapter: string,
+ /// JSON-encoded configuration for a given debug adapter.
+ config: string,
+ /// TCP connection parameters (if they were specified by user)
+ tcp-connection: option,
+ }
+
+ record start-debugging-request-arguments {
+ /// JSON-encoded configuration for a given debug adapter. It is specific to each debug adapter.
+ /// `configuration` will have it's Zed variable references substituted prior to being passed to the debug adapter.
+ configuration: string,
+ request: start-debugging-request-arguments-request,
+ }
+
+ /// The lowest-level representation of a debug session, which specifies:
+ /// - How to start a debug adapter process
+ /// - How to start a debug session with it (using DAP protocol)
+ /// for a given debug scenario.
+ record debug-adapter-binary {
+ command: option,
+ arguments: list,
+ envs: env-vars,
+ cwd: option,
+ /// Zed will use TCP transport if `connection` is specified.
+ connection: option,
+ request-args: start-debugging-request-arguments
+ }
+}
diff --git a/crates/extension_api/wit/since_v0.8.0/extension.wit b/crates/extension_api/wit/since_v0.8.0/extension.wit
new file mode 100644
index 0000000000000000000000000000000000000000..92979a8780039776853fa250be2afdb204ae5d55
--- /dev/null
+++ b/crates/extension_api/wit/since_v0.8.0/extension.wit
@@ -0,0 +1,252 @@
+package zed:extension;
+
+world extension {
+ import context-server;
+ import dap;
+ import github;
+ import http-client;
+ import platform;
+ import process;
+ import nodejs;
+ import llm-provider;
+
+ use common.{env-vars, range};
+ use context-server.{context-server-configuration};
+ use dap.{attach-request, build-task-template, debug-config, debug-adapter-binary, debug-task-definition, debug-request, debug-scenario, launch-request, resolved-task, start-debugging-request-arguments-request};
+ use lsp.{completion, symbol};
+ use process.{command};
+ use slash-command.{slash-command, slash-command-argument-completion, slash-command-output};
+ use llm-provider.{
+ provider-info, model-info, completion-request,
+ credential-type, cache-configuration, completion-event, token-usage
+ };
+
+ /// Initializes the extension.
+ export init-extension: func();
+
+ /// The type of a downloaded file.
+ enum downloaded-file-type {
+ /// A gzipped file (`.gz`).
+ gzip,
+ /// A gzipped tar archive (`.tar.gz`).
+ gzip-tar,
+ /// A ZIP file (`.zip`).
+ zip,
+ /// An uncompressed file.
+ uncompressed,
+ }
+
+ /// The installation status for a language server.
+ variant language-server-installation-status {
+ /// The language server has no installation status.
+ none,
+ /// The language server is being downloaded.
+ downloading,
+ /// The language server is checking for updates.
+ checking-for-update,
+ /// The language server installation failed for specified reason.
+ failed(string),
+ }
+
+ record settings-location {
+ worktree-id: u64,
+ path: string,
+ }
+
+ import get-settings: func(path: option, category: string, key: option) -> result;
+
+ /// Downloads a file from the given URL and saves it to the given path within the extension's
+ /// working directory.
+ ///
+ /// The file will be extracted according to the given file type.
+ import download-file: func(url: string, file-path: string, file-type: downloaded-file-type) -> result<_, string>;
+
+ /// Makes the file at the given path executable.
+ import make-file-executable: func(filepath: string) -> result<_, string>;
+
+ /// Updates the installation status for the given language server.
+ import set-language-server-installation-status: func(language-server-name: string, status: language-server-installation-status);
+
+ /// A Zed worktree.
+ resource worktree {
+ /// Returns the ID of the worktree.
+ id: func() -> u64;
+ /// Returns the root path of the worktree.
+ root-path: func() -> string;
+ /// Returns the textual contents of the specified file in the worktree.
+ read-text-file: func(path: string) -> result;
+ /// Returns the path to the given binary name, if one is present on the `$PATH`.
+ which: func(binary-name: string) -> option;
+ /// Returns the current shell environment.
+ shell-env: func() -> env-vars;
+ }
+
+ /// A Zed project.
+ resource project {
+ /// Returns the IDs of all of the worktrees in this project.
+ worktree-ids: func() -> list;
+ }
+
+ /// A key-value store.
+ resource key-value-store {
+ /// Inserts an entry under the specified key.
+ insert: func(key: string, value: string) -> result<_, string>;
+ }
+
+ /// Returns the command used to start up the language server.
+ export language-server-command: func(language-server-id: string, worktree: borrow) -> result;
+
+ /// Returns the initialization options to pass to the language server on startup.
+ ///
+ /// The initialization options are represented as a JSON string.
+ export language-server-initialization-options: func(language-server-id: string, worktree: borrow) -> result