Move Perplexity extension to dedicated repository (#34070)

Peter Tripp created

Move Perplexity extension to:
https://github.com/zed-extensions/perplexity

Release Notes:

- N/A

Change summary

.config/hakari.toml                     |   1 
Cargo.lock                              |   8 -
Cargo.toml                              |   1 
extensions/perplexity/Cargo.toml        |  17 --
extensions/perplexity/LICENSE-APACHE    |   1 
extensions/perplexity/README.md         |  43 -------
extensions/perplexity/extension.toml    |  12 --
extensions/perplexity/src/perplexity.rs | 158 ---------------------------
8 files changed, 241 deletions(-)

Detailed changes

.config/hakari.toml 🔗

@@ -33,7 +33,6 @@ workspace-members = [
     "zed_emmet",
     "zed_glsl",
     "zed_html",
-    "perplexity",
     "zed_proto",
     "zed_ruff",
     "slash_commands_example",

Cargo.lock 🔗

@@ -11350,14 +11350,6 @@ version = "2.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
 
-[[package]]
-name = "perplexity"
-version = "0.1.0"
-dependencies = [
- "serde",
- "zed_extension_api 0.6.0",
-]
-
 [[package]]
 name = "pest"
 version = "2.8.0"

Cargo.toml 🔗

@@ -189,7 +189,6 @@ members = [
     "extensions/emmet",
     "extensions/glsl",
     "extensions/html",
-    "extensions/perplexity",
     "extensions/proto",
     "extensions/ruff",
     "extensions/slash-commands-example",

extensions/perplexity/Cargo.toml 🔗

@@ -1,17 +0,0 @@
-[package]
-name = "perplexity"
-version = "0.1.0"
-edition.workspace = true
-publish.workspace = true
-license = "Apache-2.0"
-
-[lib]
-path = "src/perplexity.rs"
-crate-type = ["cdylib"]
-
-[lints]
-workspace = true
-
-[dependencies]
-serde = "1"
-zed_extension_api = { path = "../../crates/extension_api" }

extensions/perplexity/README.md 🔗

@@ -1,43 +0,0 @@
-# Zed Perplexity Extension
-
-This example extension adds the `/perplexity` [slash command](https://zed.dev/docs/assistant/commands) to the Zed AI assistant.
-
-## Usage
-
-Open the AI Assistant panel (`cmd-r` or `ctrl-r`) and enter:
-
-```
-/perplexity What's the weather in Boulder, CO tomorrow evening?
-```
-
-## Development Setup
-
-1. Install the Rust toolchain and clone the zed repo:
-
-   ```
-   curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
-
-   mkdir -p ~/code
-   cd ~/code
-   git clone https://github.com/zed-industries/zed
-   ```
-
-1. Open Zed
-1. Open Zed Extensions (`cmd-shift-x` / `ctrl-shift-x`)
-1. Click "Install Dev Extension"
-1. Navigate to the "extensions/perplexity" folder inside the zed git repo.
-1. Ensure your `PERPLEXITY_API_KEY` environment variable is set (instructions below)
-
-   ```sh
-   env | grep PERPLEXITY_API_KEY
-   ```
-
-1. Quit and relaunch Zed
-
-## PERPLEXITY_API_KEY
-
-This extension requires a Perplexity API key to be available via the `PERPLEXITY_API_KEY` environment variable.
-
-To obtain a Perplexity.ai API token, login to your Perplexity.ai account and go [Settings->API](https://www.perplexity.ai/settings/api) and under "API Keys" click "Generate". This will require you to have [Perplexity Pro](https://www.perplexity.ai/pro) or to buy API credits. By default the extension uses `llama-3.1-sonar-small-128k-online`, currently cheapest model available which is roughly half a penny per request + a penny per 50,000 tokens. So most requests will cost less than $0.01 USD.
-
-Take your API key and add it to your environment by adding `export PERPLEXITY_API_KEY="pplx-0123456789abcdef..."` to your `~/.zshrc` or `~/.bashrc`. Reload close and reopen your terminal session. Check with `env |grep PERPLEXITY_API_KEY`.

extensions/perplexity/extension.toml 🔗

@@ -1,12 +0,0 @@
-id = "perplexity"
-name = "Perplexity"
-version = "0.1.0"
-description = "Ask questions to Perplexity AI directly from Zed"
-authors = ["Zed Industries <support@zed.dev>"]
-repository = "https://github.com/zed-industries/zed"
-schema_version = 1
-
-[slash_commands.perplexity]
-description = "Ask a question to Perplexity AI"
-requires_argument = true
-tooltip_text = "Ask Perplexity"

extensions/perplexity/src/perplexity.rs 🔗

@@ -1,158 +0,0 @@
-use zed::{
-    http_client::HttpMethod,
-    http_client::HttpRequest,
-    serde_json::{self, json},
-};
-use zed_extension_api::{self as zed, Result, http_client::RedirectPolicy};
-
-struct Perplexity;
-
-impl zed::Extension for Perplexity {
-    fn new() -> Self {
-        Self
-    }
-
-    fn run_slash_command(
-        &self,
-        command: zed::SlashCommand,
-        argument: Vec<String>,
-        worktree: Option<&zed::Worktree>,
-    ) -> zed::Result<zed::SlashCommandOutput> {
-        // Check if the command is 'perplexity'
-        if command.name != "perplexity" {
-            return Err("Invalid command. Expected 'perplexity'.".into());
-        }
-
-        let worktree = worktree.ok_or("Worktree is required")?;
-        // Join arguments with space as the query
-        let query = argument.join(" ");
-        if query.is_empty() {
-            return Ok(zed::SlashCommandOutput {
-                text: "Error: Query not provided. Please enter a question or topic.".to_string(),
-                sections: vec![],
-            });
-        }
-
-        // Get the API key from the environment
-        let env_vars = worktree.shell_env();
-        let api_key = env_vars
-            .iter()
-            .find(|(key, _)| key == "PERPLEXITY_API_KEY")
-            .map(|(_, value)| value.clone())
-            .ok_or("PERPLEXITY_API_KEY not found in environment")?;
-
-        // Prepare the request
-        let request = HttpRequest {
-            method: HttpMethod::Post,
-            url: "https://api.perplexity.ai/chat/completions".to_string(),
-            headers: vec![
-                ("Authorization".to_string(), format!("Bearer {}", api_key)),
-                ("Content-Type".to_string(), "application/json".to_string()),
-            ],
-            body: Some(
-                serde_json::to_vec(&json!({
-                    "model": "llama-3.1-sonar-small-128k-online",
-                    "messages": [{"role": "user", "content": query}],
-                    "stream": true,
-                }))
-                .unwrap(),
-            ),
-            redirect_policy: RedirectPolicy::FollowAll,
-        };
-
-        // Make the HTTP request
-        match zed::http_client::fetch_stream(&request) {
-            Ok(stream) => {
-                let mut full_content = String::new();
-                let mut buffer = String::new();
-                while let Ok(Some(chunk)) = stream.next_chunk() {
-                    buffer.push_str(&String::from_utf8_lossy(&chunk));
-                    for line in buffer.lines() {
-                        if let Some(json) = line.strip_prefix("data: ") {
-                            if let Ok(event) = serde_json::from_str::<StreamEvent>(json) {
-                                if let Some(choice) = event.choices.first() {
-                                    full_content.push_str(&choice.delta.content);
-                                }
-                            }
-                        }
-                    }
-                    buffer.clear();
-                }
-                Ok(zed::SlashCommandOutput {
-                    text: full_content,
-                    sections: vec![],
-                })
-            }
-            Err(e) => Ok(zed::SlashCommandOutput {
-                text: format!("API request failed. Error: {}. API Key: {}", e, api_key),
-                sections: vec![],
-            }),
-        }
-    }
-
-    fn complete_slash_command_argument(
-        &self,
-        _command: zed::SlashCommand,
-        query: Vec<String>,
-    ) -> zed::Result<Vec<zed::SlashCommandArgumentCompletion>> {
-        let suggestions = vec!["How do I develop a Zed extension?"];
-        let query = query.join(" ").to_lowercase();
-
-        Ok(suggestions
-            .into_iter()
-            .filter(|suggestion| suggestion.to_lowercase().contains(&query))
-            .map(|suggestion| zed::SlashCommandArgumentCompletion {
-                label: suggestion.to_string(),
-                new_text: suggestion.to_string(),
-                run_command: true,
-            })
-            .collect())
-    }
-
-    fn language_server_command(
-        &mut self,
-        _language_server_id: &zed_extension_api::LanguageServerId,
-        _worktree: &zed_extension_api::Worktree,
-    ) -> Result<zed_extension_api::Command> {
-        Err("Not implemented".into())
-    }
-}
-
-#[derive(serde::Deserialize)]
-struct StreamEvent {
-    id: String,
-    model: String,
-    created: u64,
-    usage: Usage,
-    object: String,
-    choices: Vec<Choice>,
-}
-
-#[derive(serde::Deserialize)]
-struct Usage {
-    prompt_tokens: u32,
-    completion_tokens: u32,
-    total_tokens: u32,
-}
-
-#[derive(serde::Deserialize)]
-struct Choice {
-    index: u32,
-    finish_reason: Option<String>,
-    message: Message,
-    delta: Delta,
-}
-
-#[derive(serde::Deserialize)]
-struct Message {
-    role: String,
-    content: String,
-}
-
-#[derive(serde::Deserialize)]
-struct Delta {
-    role: String,
-    content: String,
-}
-
-zed::register_extension!(Perplexity);