Remove builtin extensions for now

Richard Feldman created

Change summary

extensions/anthropic/Cargo.lock              | 823 ---------------------
extensions/anthropic/Cargo.toml              |  17 
extensions/anthropic/extension.toml          |  13 
extensions/anthropic/icons/anthropic.svg     |  11 
extensions/anthropic/src/anthropic.rs        | 803 ---------------------
extensions/copilot_chat/Cargo.lock           | 823 ---------------------
extensions/copilot_chat/Cargo.toml           |  17 
extensions/copilot_chat/extension.toml       |  13 
extensions/copilot_chat/icons/copilot.svg    |   9 
extensions/copilot_chat/src/copilot_chat.rs  | 696 ------------------
extensions/google-ai/Cargo.lock              | 823 ---------------------
extensions/google-ai/Cargo.toml              |  17 
extensions/google-ai/extension.toml          |  13 
extensions/google-ai/icons/google-ai.svg     |   3 
extensions/google-ai/src/google_ai.rs        | 840 ----------------------
extensions/open_router/Cargo.lock            | 823 ---------------------
extensions/open_router/Cargo.toml            |  17 
extensions/open_router/extension.toml        |  13 
extensions/open_router/icons/open-router.svg |   8 
extensions/open_router/src/open_router.rs    | 830 ---------------------
extensions/openai/Cargo.lock                 | 823 ---------------------
extensions/openai/Cargo.toml                 |  17 
extensions/openai/extension.toml             |  13 
extensions/openai/icons/openai.svg           |   1 
extensions/openai/src/openai.rs              | 727 -------------------
25 files changed, 8,193 deletions(-)

Detailed changes

extensions/anthropic/Cargo.lock 🔗

@@ -1,823 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 4
-
-[[package]]
-name = "adler2"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
-
-[[package]]
-name = "anyhow"
-version = "1.0.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
-
-[[package]]
-name = "auditable-serde"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c7bf8143dfc3c0258df908843e169b5cc5fcf76c7718bd66135ef4a9cd558c5"
-dependencies = [
- "semver",
- "serde",
- "serde_json",
- "topological-sort",
-]
-
-[[package]]
-name = "bitflags"
-version = "2.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
-
-[[package]]
-name = "cfg-if"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
-
-[[package]]
-name = "crc32fast"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "displaydoc"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "equivalent"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
-
-[[package]]
-name = "fanthropic"
-version = "0.1.0"
-dependencies = [
- "serde",
- "serde_json",
- "zed_extension_api",
-]
-
-[[package]]
-name = "flate2"
-version = "1.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb"
-dependencies = [
- "crc32fast",
- "miniz_oxide",
-]
-
-[[package]]
-name = "foldhash"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
-
-[[package]]
-name = "form_urlencoded"
-version = "1.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
-dependencies = [
- "percent-encoding",
-]
-
-[[package]]
-name = "futures"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-executor",
- "futures-io",
- "futures-sink",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-channel"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
-dependencies = [
- "futures-core",
- "futures-sink",
-]
-
-[[package]]
-name = "futures-core"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
-
-[[package]]
-name = "futures-executor"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
-dependencies = [
- "futures-core",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-io"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
-
-[[package]]
-name = "futures-macro"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "futures-sink"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
-
-[[package]]
-name = "futures-task"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
-
-[[package]]
-name = "futures-util"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-io",
- "futures-macro",
- "futures-sink",
- "futures-task",
- "memchr",
- "pin-project-lite",
- "pin-utils",
- "slab",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.15.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
-dependencies = [
- "foldhash",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.16.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
-
-[[package]]
-name = "heck"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
-
-[[package]]
-name = "icu_collections"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
-dependencies = [
- "displaydoc",
- "potential_utf",
- "yoke",
- "zerofrom",
- "zerovec",
-]
-
-[[package]]
-name = "icu_locale_core"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
-dependencies = [
- "displaydoc",
- "litemap",
- "tinystr",
- "writeable",
- "zerovec",
-]
-
-[[package]]
-name = "icu_normalizer"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599"
-dependencies = [
- "icu_collections",
- "icu_normalizer_data",
- "icu_properties",
- "icu_provider",
- "smallvec",
- "zerovec",
-]
-
-[[package]]
-name = "icu_normalizer_data"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a"
-
-[[package]]
-name = "icu_properties"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99"
-dependencies = [
- "icu_collections",
- "icu_locale_core",
- "icu_properties_data",
- "icu_provider",
- "zerotrie",
- "zerovec",
-]
-
-[[package]]
-name = "icu_properties_data"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899"
-
-[[package]]
-name = "icu_provider"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
-dependencies = [
- "displaydoc",
- "icu_locale_core",
- "writeable",
- "yoke",
- "zerofrom",
- "zerotrie",
- "zerovec",
-]
-
-[[package]]
-name = "id-arena"
-version = "2.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
-
-[[package]]
-name = "idna"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
-dependencies = [
- "idna_adapter",
- "smallvec",
- "utf8_iter",
-]
-
-[[package]]
-name = "idna_adapter"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
-dependencies = [
- "icu_normalizer",
- "icu_properties",
-]
-
-[[package]]
-name = "indexmap"
-version = "2.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2"
-dependencies = [
- "equivalent",
- "hashbrown 0.16.1",
- "serde",
- "serde_core",
-]
-
-[[package]]
-name = "itoa"
-version = "1.0.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
-
-[[package]]
-name = "leb128fmt"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
-
-[[package]]
-name = "litemap"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
-
-[[package]]
-name = "log"
-version = "0.4.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
-
-[[package]]
-name = "memchr"
-version = "2.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
-
-[[package]]
-name = "miniz_oxide"
-version = "0.8.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
-dependencies = [
- "adler2",
- "simd-adler32",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.21.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
-
-[[package]]
-name = "percent-encoding"
-version = "2.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
-
-[[package]]
-name = "pin-project-lite"
-version = "0.2.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
-
-[[package]]
-name = "pin-utils"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
-
-[[package]]
-name = "potential_utf"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77"
-dependencies = [
- "zerovec",
-]
-
-[[package]]
-name = "prettyplease"
-version = "0.2.37"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
-dependencies = [
- "proc-macro2",
- "syn",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.103"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.42"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "ryu"
-version = "1.0.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
-
-[[package]]
-name = "semver"
-version = "1.0.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
-dependencies = [
- "serde",
- "serde_core",
-]
-
-[[package]]
-name = "serde"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
-dependencies = [
- "serde_core",
- "serde_derive",
-]
-
-[[package]]
-name = "serde_core"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "serde_json"
-version = "1.0.145"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
-dependencies = [
- "itoa",
- "memchr",
- "ryu",
- "serde",
- "serde_core",
-]
-
-[[package]]
-name = "simd-adler32"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
-
-[[package]]
-name = "slab"
-version = "0.4.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
-
-[[package]]
-name = "smallvec"
-version = "1.15.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
-
-[[package]]
-name = "spdx"
-version = "0.10.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3e17e880bafaeb362a7b751ec46bdc5b61445a188f80e0606e68167cd540fa3"
-dependencies = [
- "smallvec",
-]
-
-[[package]]
-name = "stable_deref_trait"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
-
-[[package]]
-name = "syn"
-version = "2.0.111"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "synstructure"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "tinystr"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
-dependencies = [
- "displaydoc",
- "zerovec",
-]
-
-[[package]]
-name = "topological-sort"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d"
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
-
-[[package]]
-name = "unicode-xid"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
-
-[[package]]
-name = "url"
-version = "2.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b"
-dependencies = [
- "form_urlencoded",
- "idna",
- "percent-encoding",
- "serde",
-]
-
-[[package]]
-name = "utf8_iter"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
-
-[[package]]
-name = "wasm-encoder"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80bb72f02e7fbf07183443b27b0f3d4144abf8c114189f2e088ed95b696a7822"
-dependencies = [
- "leb128fmt",
- "wasmparser",
-]
-
-[[package]]
-name = "wasm-metadata"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce1ef0faabbbba6674e97a56bee857ccddf942785a336c8b47b42373c922a91d"
-dependencies = [
- "anyhow",
- "auditable-serde",
- "flate2",
- "indexmap",
- "serde",
- "serde_derive",
- "serde_json",
- "spdx",
- "url",
- "wasm-encoder",
- "wasmparser",
-]
-
-[[package]]
-name = "wasmparser"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f51cad774fb3c9461ab9bccc9c62dfb7388397b5deda31bf40e8108ccd678b2"
-dependencies = [
- "bitflags",
- "hashbrown 0.15.5",
- "indexmap",
- "semver",
-]
-
-[[package]]
-name = "wit-bindgen"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10fb6648689b3929d56bbc7eb1acf70c9a42a29eb5358c67c10f54dbd5d695de"
-dependencies = [
- "wit-bindgen-rt",
- "wit-bindgen-rust-macro",
-]
-
-[[package]]
-name = "wit-bindgen-core"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92fa781d4f2ff6d3f27f3cc9b74a73327b31ca0dc4a3ef25a0ce2983e0e5af9b"
-dependencies = [
- "anyhow",
- "heck",
- "wit-parser",
-]
-
-[[package]]
-name = "wit-bindgen-rt"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4db52a11d4dfb0a59f194c064055794ee6564eb1ced88c25da2cf76e50c5621"
-dependencies = [
- "bitflags",
- "futures",
- "once_cell",
-]
-
-[[package]]
-name = "wit-bindgen-rust"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d0809dc5ba19e2e98661bf32fc0addc5a3ca5bf3a6a7083aa6ba484085ff3ce"
-dependencies = [
- "anyhow",
- "heck",
- "indexmap",
- "prettyplease",
- "syn",
- "wasm-metadata",
- "wit-bindgen-core",
- "wit-component",
-]
-
-[[package]]
-name = "wit-bindgen-rust-macro"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad19eec017904e04c60719592a803ee5da76cb51c81e3f6fbf9457f59db49799"
-dependencies = [
- "anyhow",
- "prettyplease",
- "proc-macro2",
- "quote",
- "syn",
- "wit-bindgen-core",
- "wit-bindgen-rust",
-]
-
-[[package]]
-name = "wit-component"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "635c3adc595422cbf2341a17fb73a319669cc8d33deed3a48368a841df86b676"
-dependencies = [
- "anyhow",
- "bitflags",
- "indexmap",
- "log",
- "serde",
- "serde_derive",
- "serde_json",
- "wasm-encoder",
- "wasm-metadata",
- "wasmparser",
- "wit-parser",
-]
-
-[[package]]
-name = "wit-parser"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddf445ed5157046e4baf56f9138c124a0824d4d1657e7204d71886ad8ce2fc11"
-dependencies = [
- "anyhow",
- "id-arena",
- "indexmap",
- "log",
- "semver",
- "serde",
- "serde_derive",
- "serde_json",
- "unicode-xid",
- "wasmparser",
-]
-
-[[package]]
-name = "writeable"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
-
-[[package]]
-name = "yoke"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
-dependencies = [
- "stable_deref_trait",
- "yoke-derive",
- "zerofrom",
-]
-
-[[package]]
-name = "yoke-derive"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
-name = "zed_extension_api"
-version = "0.7.0"
-dependencies = [
- "serde",
- "serde_json",
- "wit-bindgen",
-]
-
-[[package]]
-name = "zerofrom"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
-dependencies = [
- "zerofrom-derive",
-]
-
-[[package]]
-name = "zerofrom-derive"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
-name = "zerotrie"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
-dependencies = [
- "displaydoc",
- "yoke",
- "zerofrom",
-]
-
-[[package]]
-name = "zerovec"
-version = "0.11.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
-dependencies = [
- "yoke",
- "zerofrom",
- "zerovec-derive",
-]
-
-[[package]]
-name = "zerovec-derive"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]

extensions/anthropic/Cargo.toml 🔗

@@ -1,17 +0,0 @@
-[package]
-name = "anthropic"
-version = "0.1.0"
-edition = "2021"
-publish = false
-license = "Apache-2.0"
-
-[workspace]
-
-[lib]
-path = "src/anthropic.rs"
-crate-type = ["cdylib"]
-
-[dependencies]
-zed_extension_api = { path = "../../crates/extension_api" }
-serde = { version = "1.0", features = ["derive"] }
-serde_json = "1.0"

extensions/anthropic/extension.toml 🔗

@@ -1,13 +0,0 @@
-id = "anthropic"
-name = "Anthropic"
-description = "Anthropic Claude LLM provider for Zed."
-version = "0.1.0"
-schema_version = 1
-authors = ["Zed Team"]
-repository = "https://github.com/zed-industries/zed"
-
-[language_model_providers.anthropic]
-name = "Anthropic"
-
-[language_model_providers.anthropic.auth]
-env_var = "ANTHROPIC_API_KEY"

extensions/anthropic/icons/anthropic.svg 🔗

@@ -1,11 +0,0 @@
-<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
-<g clip-path="url(#clip0_1896_18)">
-<path d="M11.094 3.09999H8.952L12.858 12.9H15L11.094 3.09999Z" fill="black"/>
-<path d="M4.906 3.09999L1 12.9H3.184L3.98284 10.842H8.06915L8.868 12.9H11.052L7.146 3.09999H4.906ZM4.68928 9.02199L6.026 5.57799L7.3627 9.02199H4.68928Z" fill="black"/>
-</g>
-<defs>
-<clipPath id="clip0_1896_18">
-<rect width="14" height="9.8" fill="white" transform="translate(1 3.09999)"/>
-</clipPath>
-</defs>
-</svg>

extensions/anthropic/src/anthropic.rs 🔗

@@ -1,803 +0,0 @@
-use std::collections::HashMap;
-use std::sync::Mutex;
-
-use serde::{Deserialize, Serialize};
-use zed_extension_api::http_client::{HttpMethod, HttpRequest, HttpResponseStream, RedirectPolicy};
-use zed_extension_api::{self as zed, *};
-
-struct AnthropicProvider {
-    streams: Mutex<HashMap<String, StreamState>>,
-    next_stream_id: Mutex<u64>,
-}
-
-struct StreamState {
-    response_stream: Option<HttpResponseStream>,
-    buffer: String,
-    started: bool,
-    current_tool_use: Option<ToolUseState>,
-    stop_reason: Option<LlmStopReason>,
-    pending_signature: Option<String>,
-}
-
-struct ToolUseState {
-    id: String,
-    name: String,
-    input_json: String,
-}
-
-struct ModelDefinition {
-    real_id: &'static str,
-    display_name: &'static str,
-    max_tokens: u64,
-    max_output_tokens: u64,
-    supports_images: bool,
-    supports_thinking: bool,
-    is_default: bool,
-    is_default_fast: bool,
-}
-
-const MODELS: &[ModelDefinition] = &[
-    ModelDefinition {
-        real_id: "claude-opus-4-5-20251101",
-        display_name: "Claude Opus 4.5",
-        max_tokens: 200_000,
-        max_output_tokens: 8_192,
-        supports_images: true,
-        supports_thinking: false,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        real_id: "claude-opus-4-5-20251101",
-        display_name: "Claude Opus 4.5 Thinking",
-        max_tokens: 200_000,
-        max_output_tokens: 8_192,
-        supports_images: true,
-        supports_thinking: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        real_id: "claude-sonnet-4-5-20250929",
-        display_name: "Claude Sonnet 4.5",
-        max_tokens: 200_000,
-        max_output_tokens: 8_192,
-        supports_images: true,
-        supports_thinking: false,
-        is_default: true,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        real_id: "claude-sonnet-4-5-20250929",
-        display_name: "Claude Sonnet 4.5 Thinking",
-        max_tokens: 200_000,
-        max_output_tokens: 8_192,
-        supports_images: true,
-        supports_thinking: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        real_id: "claude-sonnet-4-20250514",
-        display_name: "Claude Sonnet 4",
-        max_tokens: 200_000,
-        max_output_tokens: 8_192,
-        supports_images: true,
-        supports_thinking: false,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        real_id: "claude-sonnet-4-20250514",
-        display_name: "Claude Sonnet 4 Thinking",
-        max_tokens: 200_000,
-        max_output_tokens: 8_192,
-        supports_images: true,
-        supports_thinking: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        real_id: "claude-haiku-4-5-20251001",
-        display_name: "Claude Haiku 4.5",
-        max_tokens: 200_000,
-        max_output_tokens: 64_000,
-        supports_images: true,
-        supports_thinking: false,
-        is_default: false,
-        is_default_fast: true,
-    },
-    ModelDefinition {
-        real_id: "claude-haiku-4-5-20251001",
-        display_name: "Claude Haiku 4.5 Thinking",
-        max_tokens: 200_000,
-        max_output_tokens: 64_000,
-        supports_images: true,
-        supports_thinking: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        real_id: "claude-3-5-sonnet-latest",
-        display_name: "Claude 3.5 Sonnet",
-        max_tokens: 200_000,
-        max_output_tokens: 8_192,
-        supports_images: true,
-        supports_thinking: false,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        real_id: "claude-3-5-haiku-latest",
-        display_name: "Claude 3.5 Haiku",
-        max_tokens: 200_000,
-        max_output_tokens: 8_192,
-        supports_images: true,
-        supports_thinking: false,
-        is_default: false,
-        is_default_fast: false,
-    },
-];
-
-fn get_model_definition(display_name: &str) -> Option<&'static ModelDefinition> {
-    MODELS.iter().find(|m| m.display_name == display_name)
-}
-
-// Anthropic API Request Types
-
-#[derive(Serialize)]
-struct AnthropicRequest {
-    model: String,
-    max_tokens: u64,
-    messages: Vec<AnthropicMessage>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    system: Option<String>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    thinking: Option<AnthropicThinking>,
-    #[serde(skip_serializing_if = "Vec::is_empty")]
-    tools: Vec<AnthropicTool>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    tool_choice: Option<AnthropicToolChoice>,
-    #[serde(skip_serializing_if = "Vec::is_empty")]
-    stop_sequences: Vec<String>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    temperature: Option<f32>,
-    stream: bool,
-}
-
-#[derive(Serialize)]
-struct AnthropicThinking {
-    #[serde(rename = "type")]
-    thinking_type: String,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    budget_tokens: Option<u32>,
-}
-
-#[derive(Serialize)]
-struct AnthropicMessage {
-    role: String,
-    content: Vec<AnthropicContent>,
-}
-
-#[derive(Serialize, Clone)]
-#[serde(tag = "type")]
-enum AnthropicContent {
-    #[serde(rename = "text")]
-    Text { text: String },
-    #[serde(rename = "thinking")]
-    Thinking { thinking: String, signature: String },
-    #[serde(rename = "redacted_thinking")]
-    RedactedThinking { data: String },
-    #[serde(rename = "image")]
-    Image { source: AnthropicImageSource },
-    #[serde(rename = "tool_use")]
-    ToolUse {
-        id: String,
-        name: String,
-        input: serde_json::Value,
-    },
-    #[serde(rename = "tool_result")]
-    ToolResult {
-        tool_use_id: String,
-        is_error: bool,
-        content: String,
-    },
-}
-
-#[derive(Serialize, Clone)]
-struct AnthropicImageSource {
-    #[serde(rename = "type")]
-    source_type: String,
-    media_type: String,
-    data: String,
-}
-
-#[derive(Serialize)]
-struct AnthropicTool {
-    name: String,
-    description: String,
-    input_schema: serde_json::Value,
-}
-
-#[derive(Serialize)]
-#[serde(tag = "type", rename_all = "lowercase")]
-enum AnthropicToolChoice {
-    Auto,
-    Any,
-    None,
-}
-
-// Anthropic API Response Types
-
-#[derive(Deserialize, Debug)]
-#[serde(tag = "type")]
-#[allow(dead_code)]
-enum AnthropicEvent {
-    #[serde(rename = "message_start")]
-    MessageStart { message: AnthropicMessageResponse },
-    #[serde(rename = "content_block_start")]
-    ContentBlockStart {
-        index: usize,
-        content_block: AnthropicContentBlock,
-    },
-    #[serde(rename = "content_block_delta")]
-    ContentBlockDelta { index: usize, delta: AnthropicDelta },
-    #[serde(rename = "content_block_stop")]
-    ContentBlockStop { index: usize },
-    #[serde(rename = "message_delta")]
-    MessageDelta {
-        delta: AnthropicMessageDelta,
-        usage: AnthropicUsage,
-    },
-    #[serde(rename = "message_stop")]
-    MessageStop,
-    #[serde(rename = "ping")]
-    Ping,
-    #[serde(rename = "error")]
-    Error { error: AnthropicApiError },
-}
-
-#[derive(Deserialize, Debug)]
-struct AnthropicMessageResponse {
-    #[allow(dead_code)]
-    id: String,
-    #[allow(dead_code)]
-    role: String,
-    #[serde(default)]
-    usage: AnthropicUsage,
-}
-
-#[derive(Deserialize, Debug)]
-#[serde(tag = "type")]
-enum AnthropicContentBlock {
-    #[serde(rename = "text")]
-    Text { text: String },
-    #[serde(rename = "thinking")]
-    Thinking { thinking: String },
-    #[serde(rename = "redacted_thinking")]
-    RedactedThinking { data: String },
-    #[serde(rename = "tool_use")]
-    ToolUse { id: String, name: String },
-}
-
-#[derive(Deserialize, Debug)]
-#[serde(tag = "type")]
-enum AnthropicDelta {
-    #[serde(rename = "text_delta")]
-    TextDelta { text: String },
-    #[serde(rename = "thinking_delta")]
-    ThinkingDelta { thinking: String },
-    #[serde(rename = "signature_delta")]
-    SignatureDelta { signature: String },
-    #[serde(rename = "input_json_delta")]
-    InputJsonDelta { partial_json: String },
-}
-
-#[derive(Deserialize, Debug)]
-struct AnthropicMessageDelta {
-    stop_reason: Option<String>,
-}
-
-#[derive(Deserialize, Debug, Default)]
-struct AnthropicUsage {
-    #[serde(default)]
-    input_tokens: Option<u64>,
-    #[serde(default)]
-    output_tokens: Option<u64>,
-    #[serde(default)]
-    cache_creation_input_tokens: Option<u64>,
-    #[serde(default)]
-    cache_read_input_tokens: Option<u64>,
-}
-
-#[derive(Deserialize, Debug)]
-struct AnthropicApiError {
-    #[serde(rename = "type")]
-    #[allow(dead_code)]
-    error_type: String,
-    message: String,
-}
-
-fn convert_request(
-    model_id: &str,
-    request: &LlmCompletionRequest,
-) -> Result<AnthropicRequest, String> {
-    let model_def =
-        get_model_definition(model_id).ok_or_else(|| format!("Unknown model: {}", model_id))?;
-
-    let mut messages: Vec<AnthropicMessage> = Vec::new();
-    let mut system_message = String::new();
-
-    for msg in &request.messages {
-        match msg.role {
-            LlmMessageRole::System => {
-                for content in &msg.content {
-                    if let LlmMessageContent::Text(text) = content {
-                        if !system_message.is_empty() {
-                            system_message.push('\n');
-                        }
-                        system_message.push_str(text);
-                    }
-                }
-            }
-            LlmMessageRole::User => {
-                let mut contents: Vec<AnthropicContent> = Vec::new();
-
-                for content in &msg.content {
-                    match content {
-                        LlmMessageContent::Text(text) => {
-                            if !text.is_empty() {
-                                contents.push(AnthropicContent::Text { text: text.clone() });
-                            }
-                        }
-                        LlmMessageContent::Image(img) => {
-                            contents.push(AnthropicContent::Image {
-                                source: AnthropicImageSource {
-                                    source_type: "base64".to_string(),
-                                    media_type: "image/png".to_string(),
-                                    data: img.source.clone(),
-                                },
-                            });
-                        }
-                        LlmMessageContent::ToolResult(result) => {
-                            let content_text = match &result.content {
-                                LlmToolResultContent::Text(t) => t.clone(),
-                                LlmToolResultContent::Image(_) => "[Image]".to_string(),
-                            };
-                            contents.push(AnthropicContent::ToolResult {
-                                tool_use_id: result.tool_use_id.clone(),
-                                is_error: result.is_error,
-                                content: content_text,
-                            });
-                        }
-                        _ => {}
-                    }
-                }
-
-                if !contents.is_empty() {
-                    messages.push(AnthropicMessage {
-                        role: "user".to_string(),
-                        content: contents,
-                    });
-                }
-            }
-            LlmMessageRole::Assistant => {
-                let mut contents: Vec<AnthropicContent> = Vec::new();
-
-                for content in &msg.content {
-                    match content {
-                        LlmMessageContent::Text(text) => {
-                            if !text.is_empty() {
-                                contents.push(AnthropicContent::Text { text: text.clone() });
-                            }
-                        }
-                        LlmMessageContent::ToolUse(tool_use) => {
-                            let input: serde_json::Value =
-                                serde_json::from_str(&tool_use.input).unwrap_or_default();
-                            contents.push(AnthropicContent::ToolUse {
-                                id: tool_use.id.clone(),
-                                name: tool_use.name.clone(),
-                                input,
-                            });
-                        }
-                        LlmMessageContent::Thinking(thinking) => {
-                            if !thinking.text.is_empty() {
-                                contents.push(AnthropicContent::Thinking {
-                                    thinking: thinking.text.clone(),
-                                    signature: thinking.signature.clone().unwrap_or_default(),
-                                });
-                            }
-                        }
-                        LlmMessageContent::RedactedThinking(data) => {
-                            if !data.is_empty() {
-                                contents.push(AnthropicContent::RedactedThinking {
-                                    data: data.clone(),
-                                });
-                            }
-                        }
-                        _ => {}
-                    }
-                }
-
-                if !contents.is_empty() {
-                    messages.push(AnthropicMessage {
-                        role: "assistant".to_string(),
-                        content: contents,
-                    });
-                }
-            }
-        }
-    }
-
-    let tools: Vec<AnthropicTool> = request
-        .tools
-        .iter()
-        .map(|t| AnthropicTool {
-            name: t.name.clone(),
-            description: t.description.clone(),
-            input_schema: serde_json::from_str(&t.input_schema)
-                .unwrap_or(serde_json::Value::Object(Default::default())),
-        })
-        .collect();
-
-    let tool_choice = request.tool_choice.as_ref().map(|tc| match tc {
-        LlmToolChoice::Auto => AnthropicToolChoice::Auto,
-        LlmToolChoice::Any => AnthropicToolChoice::Any,
-        LlmToolChoice::None => AnthropicToolChoice::None,
-    });
-
-    let thinking = if model_def.supports_thinking && request.thinking_allowed {
-        Some(AnthropicThinking {
-            thinking_type: "enabled".to_string(),
-            budget_tokens: Some(4096),
-        })
-    } else {
-        None
-    };
-
-    Ok(AnthropicRequest {
-        model: model_def.real_id.to_string(),
-        max_tokens: model_def.max_output_tokens,
-        messages,
-        system: if system_message.is_empty() {
-            None
-        } else {
-            Some(system_message)
-        },
-        thinking,
-        tools,
-        tool_choice,
-        stop_sequences: request.stop_sequences.clone(),
-        temperature: request.temperature,
-        stream: true,
-    })
-}
-
-fn parse_sse_line(line: &str) -> Option<AnthropicEvent> {
-    let data = line.strip_prefix("data: ")?;
-    serde_json::from_str(data).ok()
-}
-
-impl zed::Extension for AnthropicProvider {
-    fn new() -> Self {
-        Self {
-            streams: Mutex::new(HashMap::new()),
-            next_stream_id: Mutex::new(0),
-        }
-    }
-
-    fn llm_providers(&self) -> Vec<LlmProviderInfo> {
-        vec![LlmProviderInfo {
-            id: "anthropic".into(),
-            name: "Anthropic".into(),
-            icon: Some("icons/anthropic.svg".into()),
-        }]
-    }
-
-    fn llm_provider_models(&self, _provider_id: &str) -> Result<Vec<LlmModelInfo>, String> {
-        Ok(MODELS
-            .iter()
-            .map(|m| LlmModelInfo {
-                id: m.display_name.to_string(),
-                name: m.display_name.to_string(),
-                max_token_count: m.max_tokens,
-                max_output_tokens: Some(m.max_output_tokens),
-                capabilities: LlmModelCapabilities {
-                    supports_images: m.supports_images,
-                    supports_tools: true,
-                    supports_tool_choice_auto: true,
-                    supports_tool_choice_any: true,
-                    supports_tool_choice_none: true,
-                    supports_thinking: m.supports_thinking,
-                    tool_input_format: LlmToolInputFormat::JsonSchema,
-                },
-                is_default: m.is_default,
-                is_default_fast: m.is_default_fast,
-            })
-            .collect())
-    }
-
-    fn llm_provider_is_authenticated(&self, _provider_id: &str) -> bool {
-        llm_get_credential("anthropic").is_some()
-    }
-
-    fn llm_provider_settings_markdown(&self, _provider_id: &str) -> Option<String> {
-        Some(
-            r#"# Anthropic Setup
-
-Welcome to **Anthropic**! This extension provides access to Claude models.
-
-## Configuration
-
-Enter your Anthropic API key below. You can get your API key at [console.anthropic.com](https://console.anthropic.com/).
-
-## Available Models
-
-| Display Name | Real Model | Context | Output |
-|--------------|------------|---------|--------|
-| Claude Opus 4.5 | claude-opus-4-5 | 200K | 8K |
-| Claude Opus 4.5 Thinking | claude-opus-4-5 | 200K | 8K |
-| Claude Sonnet 4.5 | claude-sonnet-4-5 | 200K | 8K |
-| Claude Sonnet 4.5 Thinking | claude-sonnet-4-5 | 200K | 8K |
-| Claude Sonnet 4 | claude-sonnet-4 | 200K | 8K |
-| Claude Sonnet 4 Thinking | claude-sonnet-4 | 200K | 8K |
-| Claude Haiku 4.5 | claude-haiku-4-5 | 200K | 64K |
-| Claude Haiku 4.5 Thinking | claude-haiku-4-5 | 200K | 64K |
-| Claude 3.5 Sonnet | claude-3-5-sonnet | 200K | 8K |
-| Claude 3.5 Haiku | claude-3-5-haiku | 200K | 8K |
-
-## Features
-
-- ✅ Full streaming support
-- ✅ Tool/function calling
-- ✅ Vision (image inputs)
-- ✅ Extended thinking support
-- ✅ All Claude models
-
-## Pricing
-
-Uses your Anthropic API credits. See [Anthropic pricing](https://www.anthropic.com/pricing) for details.
-"#
-            .to_string(),
-        )
-    }
-
-    fn llm_provider_authenticate(&mut self, _provider_id: &str) -> Result<(), String> {
-        let provided = llm_request_credential(
-            "anthropic",
-            LlmCredentialType::ApiKey,
-            "Anthropic API Key",
-            "sk-ant-...",
-        )?;
-        if provided {
-            Ok(())
-        } else {
-            Err("Authentication cancelled".to_string())
-        }
-    }
-
-    fn llm_provider_reset_credentials(&mut self, _provider_id: &str) -> Result<(), String> {
-        llm_delete_credential("anthropic")
-    }
-
-    fn llm_stream_completion_start(
-        &mut self,
-        _provider_id: &str,
-        model_id: &str,
-        request: &LlmCompletionRequest,
-    ) -> Result<String, String> {
-        let api_key = llm_get_credential("anthropic").ok_or_else(|| {
-            "No API key configured. Please add your Anthropic API key in settings.".to_string()
-        })?;
-
-        let anthropic_request = convert_request(model_id, request)?;
-
-        let body = serde_json::to_vec(&anthropic_request)
-            .map_err(|e| format!("Failed to serialize request: {}", e))?;
-
-        let http_request = HttpRequest {
-            method: HttpMethod::Post,
-            url: "https://api.anthropic.com/v1/messages".to_string(),
-            headers: vec![
-                ("Content-Type".to_string(), "application/json".to_string()),
-                ("x-api-key".to_string(), api_key),
-                ("anthropic-version".to_string(), "2023-06-01".to_string()),
-            ],
-            body: Some(body),
-            redirect_policy: RedirectPolicy::FollowAll,
-        };
-
-        let response_stream = http_request
-            .fetch_stream()
-            .map_err(|e| format!("HTTP request failed: {}", e))?;
-
-        let stream_id = {
-            let mut id_counter = self.next_stream_id.lock().unwrap();
-            let id = format!("anthropic-stream-{}", *id_counter);
-            *id_counter += 1;
-            id
-        };
-
-        self.streams.lock().unwrap().insert(
-            stream_id.clone(),
-            StreamState {
-                response_stream: Some(response_stream),
-                buffer: String::new(),
-                started: false,
-                current_tool_use: None,
-                stop_reason: None,
-                pending_signature: None,
-            },
-        );
-
-        Ok(stream_id)
-    }
-
-    fn llm_stream_completion_next(
-        &mut self,
-        stream_id: &str,
-    ) -> Result<Option<LlmCompletionEvent>, String> {
-        let mut streams = self.streams.lock().unwrap();
-        let state = streams
-            .get_mut(stream_id)
-            .ok_or_else(|| format!("Unknown stream: {}", stream_id))?;
-
-        if !state.started {
-            state.started = true;
-            return Ok(Some(LlmCompletionEvent::Started));
-        }
-
-        let response_stream = state
-            .response_stream
-            .as_mut()
-            .ok_or_else(|| "Stream already closed".to_string())?;
-
-        loop {
-            if let Some(newline_pos) = state.buffer.find('\n') {
-                let line = state.buffer[..newline_pos].to_string();
-                state.buffer = state.buffer[newline_pos + 1..].to_string();
-
-                if line.trim().is_empty() || line.starts_with("event:") {
-                    continue;
-                }
-
-                if let Some(event) = parse_sse_line(&line) {
-                    match event {
-                        AnthropicEvent::MessageStart { message } => {
-                            if let (Some(input), Some(output)) =
-                                (message.usage.input_tokens, message.usage.output_tokens)
-                            {
-                                return Ok(Some(LlmCompletionEvent::Usage(LlmTokenUsage {
-                                    input_tokens: input,
-                                    output_tokens: output,
-                                    cache_creation_input_tokens: message
-                                        .usage
-                                        .cache_creation_input_tokens,
-                                    cache_read_input_tokens: message.usage.cache_read_input_tokens,
-                                })));
-                            }
-                        }
-                        AnthropicEvent::ContentBlockStart { content_block, .. } => {
-                            match content_block {
-                                AnthropicContentBlock::Text { text } => {
-                                    if !text.is_empty() {
-                                        return Ok(Some(LlmCompletionEvent::Text(text)));
-                                    }
-                                }
-                                AnthropicContentBlock::Thinking { thinking } => {
-                                    return Ok(Some(LlmCompletionEvent::Thinking(
-                                        LlmThinkingContent {
-                                            text: thinking,
-                                            signature: None,
-                                        },
-                                    )));
-                                }
-                                AnthropicContentBlock::RedactedThinking { data } => {
-                                    return Ok(Some(LlmCompletionEvent::RedactedThinking(data)));
-                                }
-                                AnthropicContentBlock::ToolUse { id, name } => {
-                                    state.current_tool_use = Some(ToolUseState {
-                                        id,
-                                        name,
-                                        input_json: String::new(),
-                                    });
-                                }
-                            }
-                        }
-                        AnthropicEvent::ContentBlockDelta { delta, .. } => match delta {
-                            AnthropicDelta::TextDelta { text } => {
-                                if !text.is_empty() {
-                                    return Ok(Some(LlmCompletionEvent::Text(text)));
-                                }
-                            }
-                            AnthropicDelta::ThinkingDelta { thinking } => {
-                                return Ok(Some(LlmCompletionEvent::Thinking(
-                                    LlmThinkingContent {
-                                        text: thinking,
-                                        signature: None,
-                                    },
-                                )));
-                            }
-                            AnthropicDelta::SignatureDelta { signature } => {
-                                state.pending_signature = Some(signature.clone());
-                                return Ok(Some(LlmCompletionEvent::Thinking(
-                                    LlmThinkingContent {
-                                        text: String::new(),
-                                        signature: Some(signature),
-                                    },
-                                )));
-                            }
-                            AnthropicDelta::InputJsonDelta { partial_json } => {
-                                if let Some(ref mut tool_use) = state.current_tool_use {
-                                    tool_use.input_json.push_str(&partial_json);
-                                }
-                            }
-                        },
-                        AnthropicEvent::ContentBlockStop { .. } => {
-                            if let Some(tool_use) = state.current_tool_use.take() {
-                                return Ok(Some(LlmCompletionEvent::ToolUse(LlmToolUse {
-                                    id: tool_use.id,
-                                    name: tool_use.name,
-                                    input: tool_use.input_json,
-                                    thought_signature: state.pending_signature.take(),
-                                })));
-                            }
-                        }
-                        AnthropicEvent::MessageDelta { delta, usage } => {
-                            if let Some(reason) = delta.stop_reason {
-                                state.stop_reason = Some(match reason.as_str() {
-                                    "end_turn" => LlmStopReason::EndTurn,
-                                    "max_tokens" => LlmStopReason::MaxTokens,
-                                    "tool_use" => LlmStopReason::ToolUse,
-                                    _ => LlmStopReason::EndTurn,
-                                });
-                            }
-                            if let Some(output) = usage.output_tokens {
-                                return Ok(Some(LlmCompletionEvent::Usage(LlmTokenUsage {
-                                    input_tokens: usage.input_tokens.unwrap_or(0),
-                                    output_tokens: output,
-                                    cache_creation_input_tokens: usage.cache_creation_input_tokens,
-                                    cache_read_input_tokens: usage.cache_read_input_tokens,
-                                })));
-                            }
-                        }
-                        AnthropicEvent::MessageStop => {
-                            if let Some(stop_reason) = state.stop_reason.take() {
-                                return Ok(Some(LlmCompletionEvent::Stop(stop_reason)));
-                            }
-                            return Ok(Some(LlmCompletionEvent::Stop(LlmStopReason::EndTurn)));
-                        }
-                        AnthropicEvent::Ping => {}
-                        AnthropicEvent::Error { error } => {
-                            return Err(format!("API error: {}", error.message));
-                        }
-                    }
-                }
-
-                continue;
-            }
-
-            match response_stream.next_chunk() {
-                Ok(Some(chunk)) => {
-                    let text = String::from_utf8_lossy(&chunk);
-                    state.buffer.push_str(&text);
-                }
-                Ok(None) => {
-                    if let Some(stop_reason) = state.stop_reason.take() {
-                        return Ok(Some(LlmCompletionEvent::Stop(stop_reason)));
-                    }
-                    return Ok(None);
-                }
-                Err(e) => {
-                    return Err(format!("Stream error: {}", e));
-                }
-            }
-        }
-    }
-
-    fn llm_stream_completion_close(&mut self, stream_id: &str) {
-        self.streams.lock().unwrap().remove(stream_id);
-    }
-}
-
-zed::register_extension!(AnthropicProvider);

extensions/copilot_chat/Cargo.lock 🔗

@@ -1,823 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 4
-
-[[package]]
-name = "adler2"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
-
-[[package]]
-name = "anyhow"
-version = "1.0.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
-
-[[package]]
-name = "auditable-serde"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c7bf8143dfc3c0258df908843e169b5cc5fcf76c7718bd66135ef4a9cd558c5"
-dependencies = [
- "semver",
- "serde",
- "serde_json",
- "topological-sort",
-]
-
-[[package]]
-name = "bitflags"
-version = "2.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
-
-[[package]]
-name = "cfg-if"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
-
-[[package]]
-name = "copilot_chat"
-version = "0.1.0"
-dependencies = [
- "serde",
- "serde_json",
- "zed_extension_api",
-]
-
-[[package]]
-name = "crc32fast"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "displaydoc"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "equivalent"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
-
-[[package]]
-name = "flate2"
-version = "1.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb"
-dependencies = [
- "crc32fast",
- "miniz_oxide",
-]
-
-[[package]]
-name = "foldhash"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
-
-[[package]]
-name = "form_urlencoded"
-version = "1.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
-dependencies = [
- "percent-encoding",
-]
-
-[[package]]
-name = "futures"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-executor",
- "futures-io",
- "futures-sink",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-channel"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
-dependencies = [
- "futures-core",
- "futures-sink",
-]
-
-[[package]]
-name = "futures-core"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
-
-[[package]]
-name = "futures-executor"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
-dependencies = [
- "futures-core",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-io"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
-
-[[package]]
-name = "futures-macro"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "futures-sink"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
-
-[[package]]
-name = "futures-task"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
-
-[[package]]
-name = "futures-util"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-io",
- "futures-macro",
- "futures-sink",
- "futures-task",
- "memchr",
- "pin-project-lite",
- "pin-utils",
- "slab",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.15.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
-dependencies = [
- "foldhash",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.16.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
-
-[[package]]
-name = "heck"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
-
-[[package]]
-name = "icu_collections"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
-dependencies = [
- "displaydoc",
- "potential_utf",
- "yoke",
- "zerofrom",
- "zerovec",
-]
-
-[[package]]
-name = "icu_locale_core"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
-dependencies = [
- "displaydoc",
- "litemap",
- "tinystr",
- "writeable",
- "zerovec",
-]
-
-[[package]]
-name = "icu_normalizer"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599"
-dependencies = [
- "icu_collections",
- "icu_normalizer_data",
- "icu_properties",
- "icu_provider",
- "smallvec",
- "zerovec",
-]
-
-[[package]]
-name = "icu_normalizer_data"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a"
-
-[[package]]
-name = "icu_properties"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99"
-dependencies = [
- "icu_collections",
- "icu_locale_core",
- "icu_properties_data",
- "icu_provider",
- "zerotrie",
- "zerovec",
-]
-
-[[package]]
-name = "icu_properties_data"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899"
-
-[[package]]
-name = "icu_provider"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
-dependencies = [
- "displaydoc",
- "icu_locale_core",
- "writeable",
- "yoke",
- "zerofrom",
- "zerotrie",
- "zerovec",
-]
-
-[[package]]
-name = "id-arena"
-version = "2.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
-
-[[package]]
-name = "idna"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
-dependencies = [
- "idna_adapter",
- "smallvec",
- "utf8_iter",
-]
-
-[[package]]
-name = "idna_adapter"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
-dependencies = [
- "icu_normalizer",
- "icu_properties",
-]
-
-[[package]]
-name = "indexmap"
-version = "2.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2"
-dependencies = [
- "equivalent",
- "hashbrown 0.16.1",
- "serde",
- "serde_core",
-]
-
-[[package]]
-name = "itoa"
-version = "1.0.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
-
-[[package]]
-name = "leb128fmt"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
-
-[[package]]
-name = "litemap"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
-
-[[package]]
-name = "log"
-version = "0.4.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
-
-[[package]]
-name = "memchr"
-version = "2.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
-
-[[package]]
-name = "miniz_oxide"
-version = "0.8.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
-dependencies = [
- "adler2",
- "simd-adler32",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.21.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
-
-[[package]]
-name = "percent-encoding"
-version = "2.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
-
-[[package]]
-name = "pin-project-lite"
-version = "0.2.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
-
-[[package]]
-name = "pin-utils"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
-
-[[package]]
-name = "potential_utf"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77"
-dependencies = [
- "zerovec",
-]
-
-[[package]]
-name = "prettyplease"
-version = "0.2.37"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
-dependencies = [
- "proc-macro2",
- "syn",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.103"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.42"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "ryu"
-version = "1.0.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
-
-[[package]]
-name = "semver"
-version = "1.0.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
-dependencies = [
- "serde",
- "serde_core",
-]
-
-[[package]]
-name = "serde"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
-dependencies = [
- "serde_core",
- "serde_derive",
-]
-
-[[package]]
-name = "serde_core"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "serde_json"
-version = "1.0.145"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
-dependencies = [
- "itoa",
- "memchr",
- "ryu",
- "serde",
- "serde_core",
-]
-
-[[package]]
-name = "simd-adler32"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
-
-[[package]]
-name = "slab"
-version = "0.4.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
-
-[[package]]
-name = "smallvec"
-version = "1.15.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
-
-[[package]]
-name = "spdx"
-version = "0.10.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3e17e880bafaeb362a7b751ec46bdc5b61445a188f80e0606e68167cd540fa3"
-dependencies = [
- "smallvec",
-]
-
-[[package]]
-name = "stable_deref_trait"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
-
-[[package]]
-name = "syn"
-version = "2.0.111"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "synstructure"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "tinystr"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
-dependencies = [
- "displaydoc",
- "zerovec",
-]
-
-[[package]]
-name = "topological-sort"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d"
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
-
-[[package]]
-name = "unicode-xid"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
-
-[[package]]
-name = "url"
-version = "2.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b"
-dependencies = [
- "form_urlencoded",
- "idna",
- "percent-encoding",
- "serde",
-]
-
-[[package]]
-name = "utf8_iter"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
-
-[[package]]
-name = "wasm-encoder"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80bb72f02e7fbf07183443b27b0f3d4144abf8c114189f2e088ed95b696a7822"
-dependencies = [
- "leb128fmt",
- "wasmparser",
-]
-
-[[package]]
-name = "wasm-metadata"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce1ef0faabbbba6674e97a56bee857ccddf942785a336c8b47b42373c922a91d"
-dependencies = [
- "anyhow",
- "auditable-serde",
- "flate2",
- "indexmap",
- "serde",
- "serde_derive",
- "serde_json",
- "spdx",
- "url",
- "wasm-encoder",
- "wasmparser",
-]
-
-[[package]]
-name = "wasmparser"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f51cad774fb3c9461ab9bccc9c62dfb7388397b5deda31bf40e8108ccd678b2"
-dependencies = [
- "bitflags",
- "hashbrown 0.15.5",
- "indexmap",
- "semver",
-]
-
-[[package]]
-name = "wit-bindgen"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10fb6648689b3929d56bbc7eb1acf70c9a42a29eb5358c67c10f54dbd5d695de"
-dependencies = [
- "wit-bindgen-rt",
- "wit-bindgen-rust-macro",
-]
-
-[[package]]
-name = "wit-bindgen-core"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92fa781d4f2ff6d3f27f3cc9b74a73327b31ca0dc4a3ef25a0ce2983e0e5af9b"
-dependencies = [
- "anyhow",
- "heck",
- "wit-parser",
-]
-
-[[package]]
-name = "wit-bindgen-rt"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4db52a11d4dfb0a59f194c064055794ee6564eb1ced88c25da2cf76e50c5621"
-dependencies = [
- "bitflags",
- "futures",
- "once_cell",
-]
-
-[[package]]
-name = "wit-bindgen-rust"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d0809dc5ba19e2e98661bf32fc0addc5a3ca5bf3a6a7083aa6ba484085ff3ce"
-dependencies = [
- "anyhow",
- "heck",
- "indexmap",
- "prettyplease",
- "syn",
- "wasm-metadata",
- "wit-bindgen-core",
- "wit-component",
-]
-
-[[package]]
-name = "wit-bindgen-rust-macro"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad19eec017904e04c60719592a803ee5da76cb51c81e3f6fbf9457f59db49799"
-dependencies = [
- "anyhow",
- "prettyplease",
- "proc-macro2",
- "quote",
- "syn",
- "wit-bindgen-core",
- "wit-bindgen-rust",
-]
-
-[[package]]
-name = "wit-component"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "635c3adc595422cbf2341a17fb73a319669cc8d33deed3a48368a841df86b676"
-dependencies = [
- "anyhow",
- "bitflags",
- "indexmap",
- "log",
- "serde",
- "serde_derive",
- "serde_json",
- "wasm-encoder",
- "wasm-metadata",
- "wasmparser",
- "wit-parser",
-]
-
-[[package]]
-name = "wit-parser"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddf445ed5157046e4baf56f9138c124a0824d4d1657e7204d71886ad8ce2fc11"
-dependencies = [
- "anyhow",
- "id-arena",
- "indexmap",
- "log",
- "semver",
- "serde",
- "serde_derive",
- "serde_json",
- "unicode-xid",
- "wasmparser",
-]
-
-[[package]]
-name = "writeable"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
-
-[[package]]
-name = "yoke"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
-dependencies = [
- "stable_deref_trait",
- "yoke-derive",
- "zerofrom",
-]
-
-[[package]]
-name = "yoke-derive"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
-name = "zed_extension_api"
-version = "0.8.0"
-dependencies = [
- "serde",
- "serde_json",
- "wit-bindgen",
-]
-
-[[package]]
-name = "zerofrom"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
-dependencies = [
- "zerofrom-derive",
-]
-
-[[package]]
-name = "zerofrom-derive"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
-name = "zerotrie"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
-dependencies = [
- "displaydoc",
- "yoke",
- "zerofrom",
-]
-
-[[package]]
-name = "zerovec"
-version = "0.11.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
-dependencies = [
- "yoke",
- "zerofrom",
- "zerovec-derive",
-]
-
-[[package]]
-name = "zerovec-derive"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]

extensions/copilot_chat/Cargo.toml 🔗

@@ -1,17 +0,0 @@
-[package]
-name = "copilot_chat"
-version = "0.1.0"
-edition = "2021"
-publish = false
-license = "Apache-2.0"
-
-[workspace]
-
-[lib]
-path = "src/copilot_chat.rs"
-crate-type = ["cdylib"]
-
-[dependencies]
-zed_extension_api = { path = "../../crates/extension_api" }
-serde = { version = "1.0", features = ["derive"] }
-serde_json = "1.0"

extensions/copilot_chat/extension.toml 🔗

@@ -1,13 +0,0 @@
-id = "copilot_chat"
-name = "Copilot Chat"
-description = "GitHub Copilot Chat LLM provider for Zed."
-version = "0.1.0"
-schema_version = 1
-authors = ["Zed Team"]
-repository = "https://github.com/zed-industries/zed"
-
-[language_model_providers.copilot_chat]
-name = "Copilot Chat"
-
-[language_model_providers.copilot_chat.auth]
-env_var = "GH_COPILOT_TOKEN"

extensions/copilot_chat/icons/copilot.svg 🔗

@@ -1,9 +0,0 @@
-<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path fill-rule="evenodd" clip-rule="evenodd" d="M6.44643 8.76593C6.83106 8.76593 7.14286 9.0793 7.14286 9.46588V10.9825C7.14286 11.369 6.83106 11.6824 6.44643 11.6824C6.06181 11.6824 5.75 11.369 5.75 10.9825V9.46588C5.75 9.0793 6.06181 8.76593 6.44643 8.76593Z" fill="black"/>
-<path fill-rule="evenodd" clip-rule="evenodd" d="M9.57168 8.76593C9.95631 8.76593 10.2681 9.0793 10.2681 9.46588V10.9825C10.2681 11.369 9.95631 11.6824 9.57168 11.6824C9.18705 11.6824 8.87524 11.369 8.87524 10.9825V9.46588C8.87524 9.0793 9.18705 8.76593 9.57168 8.76593Z" fill="black"/>
-<path d="M7.99976 4.17853C7.99976 6.67853 5.83695 7.28202 4.30332 7.28202C2.76971 7.28202 2.44604 6.1547 2.44604 4.76409C2.44604 3.37347 3.68929 2.24615 5.2229 2.24615C6.75651 2.24615 7.99976 2.78791 7.99976 4.17853Z" fill="black" fill-opacity="0.5" stroke="black" stroke-width="1.2"/>
-<path d="M8 4.17853C8 6.67853 10.1628 7.28202 11.6965 7.28202C13.2301 7.28202 13.5537 6.1547 13.5537 4.76409C13.5537 3.37347 12.3105 2.24615 10.7769 2.24615C9.24325 2.24615 8 2.78791 8 4.17853Z" fill="black" fill-opacity="0.5" stroke="black" stroke-width="1.2"/>
-<path d="M12.5894 6.875C12.5894 6.875 13.3413 7.35585 13.7144 8.08398C14.0876 8.81212 14.0894 10.4985 13.7144 11.1064C13.3395 11.7143 12.8931 12.1429 11.7637 12.7543C10.6344 13.3657 9.143 13.7321 9.143 13.7321H6.85728C6.85728 13.7321 5.37513 13.4107 4.23656 12.7543C3.09798 12.0978 2.55371 11.6786 2.28585 11.1064C2.01799 10.5342 1.92871 8.85715 2.28585 8.08398C2.64299 7.31081 3.42871 6.875 3.42871 6.875" stroke="black" stroke-width="1.2" stroke-linejoin="round"/>
-<path d="M11.9375 12.6016V7.33636L13.9052 7.99224V10.9255L11.9375 12.6016Z" fill="black" fill-opacity="0.75"/>
-<path d="M4.01793 12.6016V7.33636L2.05029 7.99224V10.9255L4.01793 12.6016Z" fill="black" fill-opacity="0.75"/>
-</svg>

extensions/copilot_chat/src/copilot_chat.rs 🔗

@@ -1,696 +0,0 @@
-use std::collections::HashMap;
-use std::sync::Mutex;
-
-use serde::{Deserialize, Serialize};
-use zed_extension_api::http_client::{HttpMethod, HttpRequest, HttpResponseStream, RedirectPolicy};
-use zed_extension_api::{self as zed, *};
-
-struct CopilotChatProvider {
-    streams: Mutex<HashMap<String, StreamState>>,
-    next_stream_id: Mutex<u64>,
-}
-
-struct StreamState {
-    response_stream: Option<HttpResponseStream>,
-    buffer: String,
-    started: bool,
-    tool_calls: HashMap<usize, AccumulatedToolCall>,
-    tool_calls_emitted: bool,
-}
-
-#[derive(Clone, Default)]
-struct AccumulatedToolCall {
-    id: String,
-    name: String,
-    arguments: String,
-}
-
-struct ModelDefinition {
-    id: &'static str,
-    display_name: &'static str,
-    max_tokens: u64,
-    max_output_tokens: Option<u64>,
-    supports_images: bool,
-    is_default: bool,
-    is_default_fast: bool,
-}
-
-const MODELS: &[ModelDefinition] = &[
-    ModelDefinition {
-        id: "gpt-4o",
-        display_name: "GPT-4o",
-        max_tokens: 128_000,
-        max_output_tokens: Some(16_384),
-        supports_images: true,
-        is_default: true,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        id: "gpt-4o-mini",
-        display_name: "GPT-4o Mini",
-        max_tokens: 128_000,
-        max_output_tokens: Some(16_384),
-        supports_images: true,
-        is_default: false,
-        is_default_fast: true,
-    },
-    ModelDefinition {
-        id: "gpt-4.1",
-        display_name: "GPT-4.1",
-        max_tokens: 1_000_000,
-        max_output_tokens: Some(32_768),
-        supports_images: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        id: "o1",
-        display_name: "o1",
-        max_tokens: 200_000,
-        max_output_tokens: Some(100_000),
-        supports_images: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        id: "o3-mini",
-        display_name: "o3-mini",
-        max_tokens: 200_000,
-        max_output_tokens: Some(100_000),
-        supports_images: false,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        id: "claude-3.5-sonnet",
-        display_name: "Claude 3.5 Sonnet",
-        max_tokens: 200_000,
-        max_output_tokens: Some(8_192),
-        supports_images: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        id: "claude-3.7-sonnet",
-        display_name: "Claude 3.7 Sonnet",
-        max_tokens: 200_000,
-        max_output_tokens: Some(8_192),
-        supports_images: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        id: "gemini-2.0-flash-001",
-        display_name: "Gemini 2.0 Flash",
-        max_tokens: 1_000_000,
-        max_output_tokens: Some(8_192),
-        supports_images: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-];
-
-fn get_model_definition(model_id: &str) -> Option<&'static ModelDefinition> {
-    MODELS.iter().find(|m| m.id == model_id)
-}
-
-#[derive(Serialize)]
-struct OpenAiRequest {
-    model: String,
-    messages: Vec<OpenAiMessage>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    max_tokens: Option<u64>,
-    #[serde(skip_serializing_if = "Vec::is_empty")]
-    tools: Vec<OpenAiTool>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    tool_choice: Option<String>,
-    #[serde(skip_serializing_if = "Vec::is_empty")]
-    stop: Vec<String>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    temperature: Option<f32>,
-    stream: bool,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    stream_options: Option<StreamOptions>,
-}
-
-#[derive(Serialize)]
-struct StreamOptions {
-    include_usage: bool,
-}
-
-#[derive(Serialize)]
-struct OpenAiMessage {
-    role: String,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    content: Option<OpenAiContent>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    tool_calls: Option<Vec<OpenAiToolCall>>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    tool_call_id: Option<String>,
-}
-
-#[derive(Serialize, Clone)]
-#[serde(untagged)]
-enum OpenAiContent {
-    Text(String),
-    Parts(Vec<OpenAiContentPart>),
-}
-
-#[derive(Serialize, Clone)]
-#[serde(tag = "type")]
-enum OpenAiContentPart {
-    #[serde(rename = "text")]
-    Text { text: String },
-    #[serde(rename = "image_url")]
-    ImageUrl { image_url: ImageUrl },
-}
-
-#[derive(Serialize, Clone)]
-struct ImageUrl {
-    url: String,
-}
-
-#[derive(Serialize, Clone)]
-struct OpenAiToolCall {
-    id: String,
-    #[serde(rename = "type")]
-    call_type: String,
-    function: OpenAiFunctionCall,
-}
-
-#[derive(Serialize, Clone)]
-struct OpenAiFunctionCall {
-    name: String,
-    arguments: String,
-}
-
-#[derive(Serialize)]
-struct OpenAiTool {
-    #[serde(rename = "type")]
-    tool_type: String,
-    function: OpenAiFunctionDef,
-}
-
-#[derive(Serialize)]
-struct OpenAiFunctionDef {
-    name: String,
-    description: String,
-    parameters: serde_json::Value,
-}
-
-#[derive(Deserialize, Debug)]
-struct OpenAiStreamResponse {
-    choices: Vec<OpenAiStreamChoice>,
-    #[serde(default)]
-    usage: Option<OpenAiUsage>,
-}
-
-#[derive(Deserialize, Debug)]
-struct OpenAiStreamChoice {
-    delta: OpenAiDelta,
-    finish_reason: Option<String>,
-}
-
-#[derive(Deserialize, Debug, Default)]
-struct OpenAiDelta {
-    #[serde(default)]
-    content: Option<String>,
-    #[serde(default)]
-    tool_calls: Option<Vec<OpenAiToolCallDelta>>,
-}
-
-#[derive(Deserialize, Debug)]
-struct OpenAiToolCallDelta {
-    index: usize,
-    #[serde(default)]
-    id: Option<String>,
-    #[serde(default)]
-    function: Option<OpenAiFunctionDelta>,
-}
-
-#[derive(Deserialize, Debug, Default)]
-struct OpenAiFunctionDelta {
-    #[serde(default)]
-    name: Option<String>,
-    #[serde(default)]
-    arguments: Option<String>,
-}
-
-#[derive(Deserialize, Debug)]
-struct OpenAiUsage {
-    prompt_tokens: u64,
-    completion_tokens: u64,
-}
-
-fn convert_request(
-    model_id: &str,
-    request: &LlmCompletionRequest,
-) -> Result<OpenAiRequest, String> {
-    let mut messages: Vec<OpenAiMessage> = Vec::new();
-
-    for msg in &request.messages {
-        match msg.role {
-            LlmMessageRole::System => {
-                let mut text_content = String::new();
-                for content in &msg.content {
-                    if let LlmMessageContent::Text(text) = content {
-                        if !text_content.is_empty() {
-                            text_content.push('\n');
-                        }
-                        text_content.push_str(text);
-                    }
-                }
-                if !text_content.is_empty() {
-                    messages.push(OpenAiMessage {
-                        role: "system".to_string(),
-                        content: Some(OpenAiContent::Text(text_content)),
-                        tool_calls: None,
-                        tool_call_id: None,
-                    });
-                }
-            }
-            LlmMessageRole::User => {
-                let mut parts: Vec<OpenAiContentPart> = Vec::new();
-                let mut tool_result_messages: Vec<OpenAiMessage> = Vec::new();
-
-                for content in &msg.content {
-                    match content {
-                        LlmMessageContent::Text(text) => {
-                            if !text.is_empty() {
-                                parts.push(OpenAiContentPart::Text { text: text.clone() });
-                            }
-                        }
-                        LlmMessageContent::Image(img) => {
-                            let data_url = format!("data:image/png;base64,{}", img.source);
-                            parts.push(OpenAiContentPart::ImageUrl {
-                                image_url: ImageUrl { url: data_url },
-                            });
-                        }
-                        LlmMessageContent::ToolResult(result) => {
-                            let content_text = match &result.content {
-                                LlmToolResultContent::Text(t) => t.clone(),
-                                LlmToolResultContent::Image(_) => "[Image]".to_string(),
-                            };
-                            tool_result_messages.push(OpenAiMessage {
-                                role: "tool".to_string(),
-                                content: Some(OpenAiContent::Text(content_text)),
-                                tool_calls: None,
-                                tool_call_id: Some(result.tool_use_id.clone()),
-                            });
-                        }
-                        _ => {}
-                    }
-                }
-
-                if !parts.is_empty() {
-                    let content = if parts.len() == 1 {
-                        if let OpenAiContentPart::Text { text } = &parts[0] {
-                            OpenAiContent::Text(text.clone())
-                        } else {
-                            OpenAiContent::Parts(parts)
-                        }
-                    } else {
-                        OpenAiContent::Parts(parts)
-                    };
-
-                    messages.push(OpenAiMessage {
-                        role: "user".to_string(),
-                        content: Some(content),
-                        tool_calls: None,
-                        tool_call_id: None,
-                    });
-                }
-
-                messages.extend(tool_result_messages);
-            }
-            LlmMessageRole::Assistant => {
-                let mut text_content = String::new();
-                let mut tool_calls: Vec<OpenAiToolCall> = Vec::new();
-
-                for content in &msg.content {
-                    match content {
-                        LlmMessageContent::Text(text) => {
-                            if !text.is_empty() {
-                                if !text_content.is_empty() {
-                                    text_content.push('\n');
-                                }
-                                text_content.push_str(text);
-                            }
-                        }
-                        LlmMessageContent::ToolUse(tool_use) => {
-                            tool_calls.push(OpenAiToolCall {
-                                id: tool_use.id.clone(),
-                                call_type: "function".to_string(),
-                                function: OpenAiFunctionCall {
-                                    name: tool_use.name.clone(),
-                                    arguments: tool_use.input.clone(),
-                                },
-                            });
-                        }
-                        _ => {}
-                    }
-                }
-
-                messages.push(OpenAiMessage {
-                    role: "assistant".to_string(),
-                    content: if text_content.is_empty() {
-                        None
-                    } else {
-                        Some(OpenAiContent::Text(text_content))
-                    },
-                    tool_calls: if tool_calls.is_empty() {
-                        None
-                    } else {
-                        Some(tool_calls)
-                    },
-                    tool_call_id: None,
-                });
-            }
-        }
-    }
-
-    let tools: Vec<OpenAiTool> = request
-        .tools
-        .iter()
-        .map(|t| OpenAiTool {
-            tool_type: "function".to_string(),
-            function: OpenAiFunctionDef {
-                name: t.name.clone(),
-                description: t.description.clone(),
-                parameters: serde_json::from_str(&t.input_schema)
-                    .unwrap_or(serde_json::Value::Object(Default::default())),
-            },
-        })
-        .collect();
-
-    let tool_choice = request.tool_choice.as_ref().map(|tc| match tc {
-        LlmToolChoice::Auto => "auto".to_string(),
-        LlmToolChoice::Any => "required".to_string(),
-        LlmToolChoice::None => "none".to_string(),
-    });
-
-    let model_def = get_model_definition(model_id);
-    let max_tokens = request
-        .max_tokens
-        .or(model_def.and_then(|m| m.max_output_tokens));
-
-    Ok(OpenAiRequest {
-        model: model_id.to_string(),
-        messages,
-        max_tokens,
-        tools,
-        tool_choice,
-        stop: request.stop_sequences.clone(),
-        temperature: request.temperature,
-        stream: true,
-        stream_options: Some(StreamOptions {
-            include_usage: true,
-        }),
-    })
-}
-
-fn parse_sse_line(line: &str) -> Option<OpenAiStreamResponse> {
-    let data = line.strip_prefix("data: ")?;
-    if data.trim() == "[DONE]" {
-        return None;
-    }
-    serde_json::from_str(data).ok()
-}
-
-impl zed::Extension for CopilotChatProvider {
-    fn new() -> Self {
-        Self {
-            streams: Mutex::new(HashMap::new()),
-            next_stream_id: Mutex::new(0),
-        }
-    }
-
-    fn llm_providers(&self) -> Vec<LlmProviderInfo> {
-        vec![LlmProviderInfo {
-            id: "copilot_chat".into(),
-            name: "Copilot Chat".into(),
-            icon: Some("icons/copilot.svg".into()),
-        }]
-    }
-
-    fn llm_provider_models(&self, _provider_id: &str) -> Result<Vec<LlmModelInfo>, String> {
-        Ok(MODELS
-            .iter()
-            .map(|m| LlmModelInfo {
-                id: m.id.to_string(),
-                name: m.display_name.to_string(),
-                max_token_count: m.max_tokens,
-                max_output_tokens: m.max_output_tokens,
-                capabilities: LlmModelCapabilities {
-                    supports_images: m.supports_images,
-                    supports_tools: true,
-                    supports_tool_choice_auto: true,
-                    supports_tool_choice_any: true,
-                    supports_tool_choice_none: true,
-                    supports_thinking: false,
-                    tool_input_format: LlmToolInputFormat::JsonSchema,
-                },
-                is_default: m.is_default,
-                is_default_fast: m.is_default_fast,
-            })
-            .collect())
-    }
-
-    fn llm_provider_is_authenticated(&self, _provider_id: &str) -> bool {
-        llm_get_credential("copilot_chat").is_some()
-    }
-
-    fn llm_provider_settings_markdown(&self, _provider_id: &str) -> Option<String> {
-        Some(
-            r#"# Copilot Chat Setup
-
-Welcome to **Copilot Chat**! This extension provides access to GitHub Copilot's chat models.
-
-## Configuration
-
-Enter your GitHub Copilot token below. You need an active GitHub Copilot subscription.
-
-To get your token:
-1. Ensure you have a GitHub Copilot subscription
-2. Generate a token from your GitHub Copilot settings
-
-## Available Models
-
-| Model | Context | Output |
-|-------|---------|--------|
-| GPT-4o | 128K | 16K |
-| GPT-4o Mini | 128K | 16K |
-| GPT-4.1 | 1M | 32K |
-| o1 | 200K | 100K |
-| o3-mini | 200K | 100K |
-| Claude 3.5 Sonnet | 200K | 8K |
-| Claude 3.7 Sonnet | 200K | 8K |
-| Gemini 2.0 Flash | 1M | 8K |
-
-## Features
-
-- ✅ Full streaming support
-- ✅ Tool/function calling
-- ✅ Vision (image inputs)
-- ✅ Multiple model providers via Copilot
-
-## Note
-
-This extension requires an active GitHub Copilot subscription.
-"#
-            .to_string(),
-        )
-    }
-
-    fn llm_provider_authenticate(&mut self, _provider_id: &str) -> Result<(), String> {
-        let provided = llm_request_credential(
-            "copilot_chat",
-            LlmCredentialType::ApiKey,
-            "GitHub Copilot Token",
-            "ghu_...",
-        )?;
-        if provided {
-            Ok(())
-        } else {
-            Err("Authentication cancelled".to_string())
-        }
-    }
-
-    fn llm_provider_reset_credentials(&mut self, _provider_id: &str) -> Result<(), String> {
-        llm_delete_credential("copilot_chat")
-    }
-
-    fn llm_stream_completion_start(
-        &mut self,
-        _provider_id: &str,
-        model_id: &str,
-        request: &LlmCompletionRequest,
-    ) -> Result<String, String> {
-        let api_key = llm_get_credential("copilot_chat").ok_or_else(|| {
-            "No token configured. Please add your GitHub Copilot token in settings.".to_string()
-        })?;
-
-        let openai_request = convert_request(model_id, request)?;
-
-        let body = serde_json::to_vec(&openai_request)
-            .map_err(|e| format!("Failed to serialize request: {}", e))?;
-
-        let http_request = HttpRequest {
-            method: HttpMethod::Post,
-            url: "https://api.githubcopilot.com/chat/completions".to_string(),
-            headers: vec![
-                ("Content-Type".to_string(), "application/json".to_string()),
-                ("Authorization".to_string(), format!("Bearer {}", api_key)),
-                (
-                    "Copilot-Integration-Id".to_string(),
-                    "vscode-chat".to_string(),
-                ),
-                ("Editor-Version".to_string(), "Zed/1.0.0".to_string()),
-            ],
-            body: Some(body),
-            redirect_policy: RedirectPolicy::FollowAll,
-        };
-
-        let response_stream = http_request
-            .fetch_stream()
-            .map_err(|e| format!("HTTP request failed: {}", e))?;
-
-        let stream_id = {
-            let mut id_counter = self.next_stream_id.lock().unwrap();
-            let id = format!("copilot-stream-{}", *id_counter);
-            *id_counter += 1;
-            id
-        };
-
-        self.streams.lock().unwrap().insert(
-            stream_id.clone(),
-            StreamState {
-                response_stream: Some(response_stream),
-                buffer: String::new(),
-                started: false,
-                tool_calls: HashMap::new(),
-                tool_calls_emitted: false,
-            },
-        );
-
-        Ok(stream_id)
-    }
-
-    fn llm_stream_completion_next(
-        &mut self,
-        stream_id: &str,
-    ) -> Result<Option<LlmCompletionEvent>, String> {
-        let mut streams = self.streams.lock().unwrap();
-        let state = streams
-            .get_mut(stream_id)
-            .ok_or_else(|| format!("Unknown stream: {}", stream_id))?;
-
-        if !state.started {
-            state.started = true;
-            return Ok(Some(LlmCompletionEvent::Started));
-        }
-
-        let response_stream = state
-            .response_stream
-            .as_mut()
-            .ok_or_else(|| "Stream already closed".to_string())?;
-
-        loop {
-            if let Some(newline_pos) = state.buffer.find('\n') {
-                let line = state.buffer[..newline_pos].to_string();
-                state.buffer = state.buffer[newline_pos + 1..].to_string();
-
-                if line.trim().is_empty() {
-                    continue;
-                }
-
-                if let Some(response) = parse_sse_line(&line) {
-                    if let Some(choice) = response.choices.first() {
-                        if let Some(content) = &choice.delta.content {
-                            if !content.is_empty() {
-                                return Ok(Some(LlmCompletionEvent::Text(content.clone())));
-                            }
-                        }
-
-                        if let Some(tool_calls) = &choice.delta.tool_calls {
-                            for tc in tool_calls {
-                                let entry = state
-                                    .tool_calls
-                                    .entry(tc.index)
-                                    .or_insert_with(AccumulatedToolCall::default);
-
-                                if let Some(id) = &tc.id {
-                                    entry.id = id.clone();
-                                }
-                                if let Some(func) = &tc.function {
-                                    if let Some(name) = &func.name {
-                                        entry.name = name.clone();
-                                    }
-                                    if let Some(args) = &func.arguments {
-                                        entry.arguments.push_str(args);
-                                    }
-                                }
-                            }
-                        }
-
-                        if let Some(finish_reason) = &choice.finish_reason {
-                            if !state.tool_calls.is_empty() && !state.tool_calls_emitted {
-                                state.tool_calls_emitted = true;
-                                let mut tool_calls: Vec<_> = state.tool_calls.drain().collect();
-                                tool_calls.sort_by_key(|(idx, _)| *idx);
-
-                                if let Some((_, tc)) = tool_calls.into_iter().next() {
-                                    return Ok(Some(LlmCompletionEvent::ToolUse(LlmToolUse {
-                                        id: tc.id,
-                                        name: tc.name,
-                                        input: tc.arguments,
-                                        thought_signature: None,
-                                    })));
-                                }
-                            }
-
-                            let stop_reason = match finish_reason.as_str() {
-                                "stop" => LlmStopReason::EndTurn,
-                                "length" => LlmStopReason::MaxTokens,
-                                "tool_calls" => LlmStopReason::ToolUse,
-                                "content_filter" => LlmStopReason::Refusal,
-                                _ => LlmStopReason::EndTurn,
-                            };
-                            return Ok(Some(LlmCompletionEvent::Stop(stop_reason)));
-                        }
-                    }
-
-                    if let Some(usage) = response.usage {
-                        return Ok(Some(LlmCompletionEvent::Usage(LlmTokenUsage {
-                            input_tokens: usage.prompt_tokens,
-                            output_tokens: usage.completion_tokens,
-                            cache_creation_input_tokens: None,
-                            cache_read_input_tokens: None,
-                        })));
-                    }
-                }
-
-                continue;
-            }
-
-            match response_stream.next_chunk() {
-                Ok(Some(chunk)) => {
-                    let text = String::from_utf8_lossy(&chunk);
-                    state.buffer.push_str(&text);
-                }
-                Ok(None) => {
-                    return Ok(None);
-                }
-                Err(e) => {
-                    return Err(format!("Stream error: {}", e));
-                }
-            }
-        }
-    }
-
-    fn llm_stream_completion_close(&mut self, stream_id: &str) {
-        self.streams.lock().unwrap().remove(stream_id);
-    }
-}
-
-zed::register_extension!(CopilotChatProvider);

extensions/google-ai/Cargo.lock 🔗

@@ -1,823 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 4
-
-[[package]]
-name = "adler2"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
-
-[[package]]
-name = "anyhow"
-version = "1.0.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
-
-[[package]]
-name = "auditable-serde"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c7bf8143dfc3c0258df908843e169b5cc5fcf76c7718bd66135ef4a9cd558c5"
-dependencies = [
- "semver",
- "serde",
- "serde_json",
- "topological-sort",
-]
-
-[[package]]
-name = "bitflags"
-version = "2.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
-
-[[package]]
-name = "cfg-if"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
-
-[[package]]
-name = "crc32fast"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "displaydoc"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "equivalent"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
-
-[[package]]
-name = "flate2"
-version = "1.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb"
-dependencies = [
- "crc32fast",
- "miniz_oxide",
-]
-
-[[package]]
-name = "foldhash"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
-
-[[package]]
-name = "foogle"
-version = "0.1.0"
-dependencies = [
- "serde",
- "serde_json",
- "zed_extension_api",
-]
-
-[[package]]
-name = "form_urlencoded"
-version = "1.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
-dependencies = [
- "percent-encoding",
-]
-
-[[package]]
-name = "futures"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-executor",
- "futures-io",
- "futures-sink",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-channel"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
-dependencies = [
- "futures-core",
- "futures-sink",
-]
-
-[[package]]
-name = "futures-core"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
-
-[[package]]
-name = "futures-executor"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
-dependencies = [
- "futures-core",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-io"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
-
-[[package]]
-name = "futures-macro"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "futures-sink"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
-
-[[package]]
-name = "futures-task"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
-
-[[package]]
-name = "futures-util"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-io",
- "futures-macro",
- "futures-sink",
- "futures-task",
- "memchr",
- "pin-project-lite",
- "pin-utils",
- "slab",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.15.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
-dependencies = [
- "foldhash",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.16.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
-
-[[package]]
-name = "heck"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
-
-[[package]]
-name = "icu_collections"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
-dependencies = [
- "displaydoc",
- "potential_utf",
- "yoke",
- "zerofrom",
- "zerovec",
-]
-
-[[package]]
-name = "icu_locale_core"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
-dependencies = [
- "displaydoc",
- "litemap",
- "tinystr",
- "writeable",
- "zerovec",
-]
-
-[[package]]
-name = "icu_normalizer"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599"
-dependencies = [
- "icu_collections",
- "icu_normalizer_data",
- "icu_properties",
- "icu_provider",
- "smallvec",
- "zerovec",
-]
-
-[[package]]
-name = "icu_normalizer_data"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a"
-
-[[package]]
-name = "icu_properties"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99"
-dependencies = [
- "icu_collections",
- "icu_locale_core",
- "icu_properties_data",
- "icu_provider",
- "zerotrie",
- "zerovec",
-]
-
-[[package]]
-name = "icu_properties_data"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899"
-
-[[package]]
-name = "icu_provider"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
-dependencies = [
- "displaydoc",
- "icu_locale_core",
- "writeable",
- "yoke",
- "zerofrom",
- "zerotrie",
- "zerovec",
-]
-
-[[package]]
-name = "id-arena"
-version = "2.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
-
-[[package]]
-name = "idna"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
-dependencies = [
- "idna_adapter",
- "smallvec",
- "utf8_iter",
-]
-
-[[package]]
-name = "idna_adapter"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
-dependencies = [
- "icu_normalizer",
- "icu_properties",
-]
-
-[[package]]
-name = "indexmap"
-version = "2.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2"
-dependencies = [
- "equivalent",
- "hashbrown 0.16.1",
- "serde",
- "serde_core",
-]
-
-[[package]]
-name = "itoa"
-version = "1.0.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
-
-[[package]]
-name = "leb128fmt"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
-
-[[package]]
-name = "litemap"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
-
-[[package]]
-name = "log"
-version = "0.4.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
-
-[[package]]
-name = "memchr"
-version = "2.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
-
-[[package]]
-name = "miniz_oxide"
-version = "0.8.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
-dependencies = [
- "adler2",
- "simd-adler32",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.21.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
-
-[[package]]
-name = "percent-encoding"
-version = "2.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
-
-[[package]]
-name = "pin-project-lite"
-version = "0.2.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
-
-[[package]]
-name = "pin-utils"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
-
-[[package]]
-name = "potential_utf"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77"
-dependencies = [
- "zerovec",
-]
-
-[[package]]
-name = "prettyplease"
-version = "0.2.37"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
-dependencies = [
- "proc-macro2",
- "syn",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.103"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.42"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "ryu"
-version = "1.0.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
-
-[[package]]
-name = "semver"
-version = "1.0.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
-dependencies = [
- "serde",
- "serde_core",
-]
-
-[[package]]
-name = "serde"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
-dependencies = [
- "serde_core",
- "serde_derive",
-]
-
-[[package]]
-name = "serde_core"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "serde_json"
-version = "1.0.145"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
-dependencies = [
- "itoa",
- "memchr",
- "ryu",
- "serde",
- "serde_core",
-]
-
-[[package]]
-name = "simd-adler32"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
-
-[[package]]
-name = "slab"
-version = "0.4.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
-
-[[package]]
-name = "smallvec"
-version = "1.15.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
-
-[[package]]
-name = "spdx"
-version = "0.10.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3e17e880bafaeb362a7b751ec46bdc5b61445a188f80e0606e68167cd540fa3"
-dependencies = [
- "smallvec",
-]
-
-[[package]]
-name = "stable_deref_trait"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
-
-[[package]]
-name = "syn"
-version = "2.0.111"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "synstructure"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "tinystr"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
-dependencies = [
- "displaydoc",
- "zerovec",
-]
-
-[[package]]
-name = "topological-sort"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d"
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
-
-[[package]]
-name = "unicode-xid"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
-
-[[package]]
-name = "url"
-version = "2.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b"
-dependencies = [
- "form_urlencoded",
- "idna",
- "percent-encoding",
- "serde",
-]
-
-[[package]]
-name = "utf8_iter"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
-
-[[package]]
-name = "wasm-encoder"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80bb72f02e7fbf07183443b27b0f3d4144abf8c114189f2e088ed95b696a7822"
-dependencies = [
- "leb128fmt",
- "wasmparser",
-]
-
-[[package]]
-name = "wasm-metadata"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce1ef0faabbbba6674e97a56bee857ccddf942785a336c8b47b42373c922a91d"
-dependencies = [
- "anyhow",
- "auditable-serde",
- "flate2",
- "indexmap",
- "serde",
- "serde_derive",
- "serde_json",
- "spdx",
- "url",
- "wasm-encoder",
- "wasmparser",
-]
-
-[[package]]
-name = "wasmparser"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f51cad774fb3c9461ab9bccc9c62dfb7388397b5deda31bf40e8108ccd678b2"
-dependencies = [
- "bitflags",
- "hashbrown 0.15.5",
- "indexmap",
- "semver",
-]
-
-[[package]]
-name = "wit-bindgen"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10fb6648689b3929d56bbc7eb1acf70c9a42a29eb5358c67c10f54dbd5d695de"
-dependencies = [
- "wit-bindgen-rt",
- "wit-bindgen-rust-macro",
-]
-
-[[package]]
-name = "wit-bindgen-core"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92fa781d4f2ff6d3f27f3cc9b74a73327b31ca0dc4a3ef25a0ce2983e0e5af9b"
-dependencies = [
- "anyhow",
- "heck",
- "wit-parser",
-]
-
-[[package]]
-name = "wit-bindgen-rt"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4db52a11d4dfb0a59f194c064055794ee6564eb1ced88c25da2cf76e50c5621"
-dependencies = [
- "bitflags",
- "futures",
- "once_cell",
-]
-
-[[package]]
-name = "wit-bindgen-rust"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d0809dc5ba19e2e98661bf32fc0addc5a3ca5bf3a6a7083aa6ba484085ff3ce"
-dependencies = [
- "anyhow",
- "heck",
- "indexmap",
- "prettyplease",
- "syn",
- "wasm-metadata",
- "wit-bindgen-core",
- "wit-component",
-]
-
-[[package]]
-name = "wit-bindgen-rust-macro"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad19eec017904e04c60719592a803ee5da76cb51c81e3f6fbf9457f59db49799"
-dependencies = [
- "anyhow",
- "prettyplease",
- "proc-macro2",
- "quote",
- "syn",
- "wit-bindgen-core",
- "wit-bindgen-rust",
-]
-
-[[package]]
-name = "wit-component"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "635c3adc595422cbf2341a17fb73a319669cc8d33deed3a48368a841df86b676"
-dependencies = [
- "anyhow",
- "bitflags",
- "indexmap",
- "log",
- "serde",
- "serde_derive",
- "serde_json",
- "wasm-encoder",
- "wasm-metadata",
- "wasmparser",
- "wit-parser",
-]
-
-[[package]]
-name = "wit-parser"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddf445ed5157046e4baf56f9138c124a0824d4d1657e7204d71886ad8ce2fc11"
-dependencies = [
- "anyhow",
- "id-arena",
- "indexmap",
- "log",
- "semver",
- "serde",
- "serde_derive",
- "serde_json",
- "unicode-xid",
- "wasmparser",
-]
-
-[[package]]
-name = "writeable"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
-
-[[package]]
-name = "yoke"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
-dependencies = [
- "stable_deref_trait",
- "yoke-derive",
- "zerofrom",
-]
-
-[[package]]
-name = "yoke-derive"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
-name = "zed_extension_api"
-version = "0.7.0"
-dependencies = [
- "serde",
- "serde_json",
- "wit-bindgen",
-]
-
-[[package]]
-name = "zerofrom"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
-dependencies = [
- "zerofrom-derive",
-]
-
-[[package]]
-name = "zerofrom-derive"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
-name = "zerotrie"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
-dependencies = [
- "displaydoc",
- "yoke",
- "zerofrom",
-]
-
-[[package]]
-name = "zerovec"
-version = "0.11.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
-dependencies = [
- "yoke",
- "zerofrom",
- "zerovec-derive",
-]
-
-[[package]]
-name = "zerovec-derive"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]

extensions/google-ai/Cargo.toml 🔗

@@ -1,17 +0,0 @@
-[package]
-name = "google-ai"
-version = "0.1.0"
-edition = "2021"
-publish = false
-license = "Apache-2.0"
-
-[workspace]
-
-[lib]
-path = "src/google_ai.rs"
-crate-type = ["cdylib"]
-
-[dependencies]
-zed_extension_api = { path = "../../crates/extension_api" }
-serde = { version = "1.0", features = ["derive"] }
-serde_json = "1.0"

extensions/google-ai/extension.toml 🔗

@@ -1,13 +0,0 @@
-id = "google-ai"
-name = "Google AI"
-description = "Google Gemini LLM provider for Zed."
-version = "0.1.0"
-schema_version = 1
-authors = ["Zed Team"]
-repository = "https://github.com/zed-industries/zed"
-
-[language_model_providers.google-ai]
-name = "Google AI"
-
-[language_model_providers.google-ai.auth]
-env_var = "GEMINI_API_KEY"

extensions/google-ai/icons/google-ai.svg 🔗

@@ -1,3 +0,0 @@
-<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M7.44 12.27C7.81333 13.1217 8 14.0317 8 15C8 14.0317 8.18083 13.1217 8.5425 12.27C8.91583 11.4183 9.4175 10.6775 10.0475 10.0475C10.6775 9.4175 11.4183 8.92167 12.27 8.56C13.1217 8.18667 14.0317 8 15 8C14.0317 8 13.1217 7.81917 12.27 7.4575C11.4411 7.1001 10.6871 6.5895 10.0475 5.9525C9.4105 5.31293 8.8999 4.55891 8.5425 3.73C8.18083 2.87833 8 1.96833 8 1C8 1.96833 7.81333 2.87833 7.44 3.73C7.07833 4.58167 6.5825 5.3225 5.9525 5.9525C5.31293 6.5895 4.55891 7.1001 3.73 7.4575C2.87833 7.81917 1.96833 8 1 8C1.96833 8 2.87833 8.18667 3.73 8.56C4.58167 8.92167 5.3225 9.4175 5.9525 10.0475C6.5825 10.6775 7.07833 11.4183 7.44 12.27Z" fill="black"/>
-</svg>

extensions/google-ai/src/google_ai.rs 🔗

@@ -1,840 +0,0 @@
-use std::collections::HashMap;
-use std::sync::atomic::{AtomicU64, Ordering};
-use std::sync::Mutex;
-
-use serde::{Deserialize, Serialize};
-use zed_extension_api::http_client::{HttpMethod, HttpRequest, HttpResponseStream, RedirectPolicy};
-use zed_extension_api::{self as zed, *};
-
-static TOOL_CALL_COUNTER: AtomicU64 = AtomicU64::new(0);
-
-struct GoogleAiProvider {
-    streams: Mutex<HashMap<String, StreamState>>,
-    next_stream_id: Mutex<u64>,
-}
-
-struct StreamState {
-    response_stream: Option<HttpResponseStream>,
-    buffer: String,
-    started: bool,
-    stop_reason: Option<LlmStopReason>,
-    wants_tool_use: bool,
-}
-
-struct ModelDefinition {
-    real_id: &'static str,
-    display_name: &'static str,
-    max_tokens: u64,
-    max_output_tokens: Option<u64>,
-    supports_images: bool,
-    supports_thinking: bool,
-    is_default: bool,
-    is_default_fast: bool,
-}
-
-const MODELS: &[ModelDefinition] = &[
-    ModelDefinition {
-        real_id: "gemini-2.5-flash-lite",
-        display_name: "Gemini 2.5 Flash-Lite",
-        max_tokens: 1_048_576,
-        max_output_tokens: Some(65_536),
-        supports_images: true,
-        supports_thinking: true,
-        is_default: false,
-        is_default_fast: true,
-    },
-    ModelDefinition {
-        real_id: "gemini-2.5-flash",
-        display_name: "Gemini 2.5 Flash",
-        max_tokens: 1_048_576,
-        max_output_tokens: Some(65_536),
-        supports_images: true,
-        supports_thinking: true,
-        is_default: true,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        real_id: "gemini-2.5-pro",
-        display_name: "Gemini 2.5 Pro",
-        max_tokens: 1_048_576,
-        max_output_tokens: Some(65_536),
-        supports_images: true,
-        supports_thinking: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        real_id: "gemini-3-pro-preview",
-        display_name: "Gemini 3 Pro",
-        max_tokens: 1_048_576,
-        max_output_tokens: Some(65_536),
-        supports_images: true,
-        supports_thinking: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-];
-
-fn get_real_model_id(display_name: &str) -> Option<&'static str> {
-    MODELS
-        .iter()
-        .find(|m| m.display_name == display_name)
-        .map(|m| m.real_id)
-}
-
-fn get_model_supports_thinking(display_name: &str) -> bool {
-    MODELS
-        .iter()
-        .find(|m| m.display_name == display_name)
-        .map(|m| m.supports_thinking)
-        .unwrap_or(false)
-}
-
-/// Adapts a JSON schema to be compatible with Google's API subset.
-/// Google only supports a specific subset of JSON Schema fields.
-/// See: https://ai.google.dev/api/caching#Schema
-fn adapt_schema_for_google(json: &mut serde_json::Value) {
-    adapt_schema_for_google_impl(json, true);
-}
-
-fn adapt_schema_for_google_impl(json: &mut serde_json::Value, is_schema: bool) {
-    if let serde_json::Value::Object(obj) = json {
-        // Google's Schema only supports these fields:
-        // type, format, title, description, nullable, enum, maxItems, minItems,
-        // properties, required, minProperties, maxProperties, minLength, maxLength,
-        // pattern, example, anyOf, propertyOrdering, default, items, minimum, maximum
-        const ALLOWED_KEYS: &[&str] = &[
-            "type",
-            "format",
-            "title",
-            "description",
-            "nullable",
-            "enum",
-            "maxItems",
-            "minItems",
-            "properties",
-            "required",
-            "minProperties",
-            "maxProperties",
-            "minLength",
-            "maxLength",
-            "pattern",
-            "example",
-            "anyOf",
-            "propertyOrdering",
-            "default",
-            "items",
-            "minimum",
-            "maximum",
-        ];
-
-        // Convert oneOf to anyOf before filtering keys
-        if let Some(one_of) = obj.remove("oneOf") {
-            obj.insert("anyOf".to_string(), one_of);
-        }
-
-        // If type is an array (e.g., ["string", "null"]), take just the first type
-        if let Some(type_field) = obj.get_mut("type") {
-            if let serde_json::Value::Array(types) = type_field {
-                if let Some(first_type) = types.first().cloned() {
-                    *type_field = first_type;
-                }
-            }
-        }
-
-        // Only filter keys if this is a schema object, not a properties map
-        if is_schema {
-            obj.retain(|key, _| ALLOWED_KEYS.contains(&key.as_str()));
-        }
-
-        // Recursively process nested values
-        // "properties" contains a map of property names -> schemas
-        // "items" and "anyOf" contain schemas directly
-        for (key, value) in obj.iter_mut() {
-            if key == "properties" {
-                // properties is a map of property_name -> schema
-                if let serde_json::Value::Object(props) = value {
-                    for (_, prop_schema) in props.iter_mut() {
-                        adapt_schema_for_google_impl(prop_schema, true);
-                    }
-                }
-            } else if key == "items" {
-                // items is a schema
-                adapt_schema_for_google_impl(value, true);
-            } else if key == "anyOf" {
-                // anyOf is an array of schemas
-                if let serde_json::Value::Array(arr) = value {
-                    for item in arr.iter_mut() {
-                        adapt_schema_for_google_impl(item, true);
-                    }
-                }
-            }
-        }
-    } else if let serde_json::Value::Array(arr) = json {
-        for item in arr.iter_mut() {
-            adapt_schema_for_google_impl(item, true);
-        }
-    }
-}
-
-#[derive(Serialize)]
-#[serde(rename_all = "camelCase")]
-struct GoogleRequest {
-    contents: Vec<GoogleContent>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    system_instruction: Option<GoogleSystemInstruction>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    generation_config: Option<GoogleGenerationConfig>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    tools: Option<Vec<GoogleTool>>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    tool_config: Option<GoogleToolConfig>,
-}
-
-#[derive(Serialize)]
-#[serde(rename_all = "camelCase")]
-struct GoogleSystemInstruction {
-    parts: Vec<GooglePart>,
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-#[serde(rename_all = "camelCase")]
-struct GoogleContent {
-    parts: Vec<GooglePart>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    role: Option<String>,
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-#[serde(untagged)]
-enum GooglePart {
-    Text(GoogleTextPart),
-    InlineData(GoogleInlineDataPart),
-    FunctionCall(GoogleFunctionCallPart),
-    FunctionResponse(GoogleFunctionResponsePart),
-    Thought(GoogleThoughtPart),
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-#[serde(rename_all = "camelCase")]
-struct GoogleTextPart {
-    text: String,
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-#[serde(rename_all = "camelCase")]
-struct GoogleInlineDataPart {
-    inline_data: GoogleBlob,
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-#[serde(rename_all = "camelCase")]
-struct GoogleBlob {
-    mime_type: String,
-    data: String,
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-#[serde(rename_all = "camelCase")]
-struct GoogleFunctionCallPart {
-    function_call: GoogleFunctionCall,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    thought_signature: Option<String>,
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-#[serde(rename_all = "camelCase")]
-struct GoogleFunctionCall {
-    name: String,
-    args: serde_json::Value,
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-#[serde(rename_all = "camelCase")]
-struct GoogleFunctionResponsePart {
-    function_response: GoogleFunctionResponse,
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-#[serde(rename_all = "camelCase")]
-struct GoogleFunctionResponse {
-    name: String,
-    response: serde_json::Value,
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-#[serde(rename_all = "camelCase")]
-struct GoogleThoughtPart {
-    thought: bool,
-    thought_signature: String,
-}
-
-#[derive(Serialize)]
-#[serde(rename_all = "camelCase")]
-struct GoogleGenerationConfig {
-    #[serde(skip_serializing_if = "Option::is_none")]
-    candidate_count: Option<usize>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    stop_sequences: Option<Vec<String>>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    max_output_tokens: Option<usize>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    temperature: Option<f64>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    thinking_config: Option<GoogleThinkingConfig>,
-}
-
-#[derive(Serialize)]
-#[serde(rename_all = "camelCase")]
-struct GoogleThinkingConfig {
-    thinking_budget: u32,
-}
-
-#[derive(Serialize)]
-#[serde(rename_all = "camelCase")]
-struct GoogleTool {
-    function_declarations: Vec<GoogleFunctionDeclaration>,
-}
-
-#[derive(Serialize)]
-#[serde(rename_all = "camelCase")]
-struct GoogleFunctionDeclaration {
-    name: String,
-    description: String,
-    parameters: serde_json::Value,
-}
-
-#[derive(Serialize)]
-#[serde(rename_all = "camelCase")]
-struct GoogleToolConfig {
-    function_calling_config: GoogleFunctionCallingConfig,
-}
-
-#[derive(Serialize)]
-#[serde(rename_all = "camelCase")]
-struct GoogleFunctionCallingConfig {
-    mode: String,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    allowed_function_names: Option<Vec<String>>,
-}
-
-#[derive(Deserialize, Debug)]
-#[serde(rename_all = "camelCase")]
-struct GoogleStreamResponse {
-    #[serde(default)]
-    candidates: Vec<GoogleCandidate>,
-    #[serde(default)]
-    usage_metadata: Option<GoogleUsageMetadata>,
-}
-
-#[derive(Deserialize, Debug)]
-#[serde(rename_all = "camelCase")]
-struct GoogleCandidate {
-    #[serde(default)]
-    content: Option<GoogleContent>,
-    #[serde(default)]
-    finish_reason: Option<String>,
-}
-
-#[derive(Deserialize, Debug)]
-#[serde(rename_all = "camelCase")]
-struct GoogleUsageMetadata {
-    #[serde(default)]
-    prompt_token_count: u64,
-    #[serde(default)]
-    candidates_token_count: u64,
-}
-
-fn convert_request(
-    model_id: &str,
-    request: &LlmCompletionRequest,
-) -> Result<(GoogleRequest, String), String> {
-    let real_model_id =
-        get_real_model_id(model_id).ok_or_else(|| format!("Unknown model: {}", model_id))?;
-
-    let supports_thinking = get_model_supports_thinking(model_id);
-
-    let mut contents: Vec<GoogleContent> = Vec::new();
-    let mut system_parts: Vec<GooglePart> = Vec::new();
-
-    for msg in &request.messages {
-        match msg.role {
-            LlmMessageRole::System => {
-                for content in &msg.content {
-                    if let LlmMessageContent::Text(text) = content {
-                        if !text.is_empty() {
-                            system_parts
-                                .push(GooglePart::Text(GoogleTextPart { text: text.clone() }));
-                        }
-                    }
-                }
-            }
-            LlmMessageRole::User => {
-                let mut parts: Vec<GooglePart> = Vec::new();
-
-                for content in &msg.content {
-                    match content {
-                        LlmMessageContent::Text(text) => {
-                            if !text.is_empty() {
-                                parts.push(GooglePart::Text(GoogleTextPart { text: text.clone() }));
-                            }
-                        }
-                        LlmMessageContent::Image(img) => {
-                            parts.push(GooglePart::InlineData(GoogleInlineDataPart {
-                                inline_data: GoogleBlob {
-                                    mime_type: "image/png".to_string(),
-                                    data: img.source.clone(),
-                                },
-                            }));
-                        }
-                        LlmMessageContent::ToolResult(result) => {
-                            let response_value = match &result.content {
-                                LlmToolResultContent::Text(t) => {
-                                    serde_json::json!({ "output": t })
-                                }
-                                LlmToolResultContent::Image(_) => {
-                                    serde_json::json!({ "output": "Tool responded with an image" })
-                                }
-                            };
-                            parts.push(GooglePart::FunctionResponse(GoogleFunctionResponsePart {
-                                function_response: GoogleFunctionResponse {
-                                    name: result.tool_name.clone(),
-                                    response: response_value,
-                                },
-                            }));
-                        }
-                        _ => {}
-                    }
-                }
-
-                if !parts.is_empty() {
-                    contents.push(GoogleContent {
-                        parts,
-                        role: Some("user".to_string()),
-                    });
-                }
-            }
-            LlmMessageRole::Assistant => {
-                let mut parts: Vec<GooglePart> = Vec::new();
-
-                for content in &msg.content {
-                    match content {
-                        LlmMessageContent::Text(text) => {
-                            if !text.is_empty() {
-                                parts.push(GooglePart::Text(GoogleTextPart { text: text.clone() }));
-                            }
-                        }
-                        LlmMessageContent::ToolUse(tool_use) => {
-                            let thought_signature =
-                                tool_use.thought_signature.clone().filter(|s| !s.is_empty());
-
-                            let args: serde_json::Value =
-                                serde_json::from_str(&tool_use.input).unwrap_or_default();
-
-                            parts.push(GooglePart::FunctionCall(GoogleFunctionCallPart {
-                                function_call: GoogleFunctionCall {
-                                    name: tool_use.name.clone(),
-                                    args,
-                                },
-                                thought_signature,
-                            }));
-                        }
-                        LlmMessageContent::Thinking(thinking) => {
-                            if let Some(ref signature) = thinking.signature {
-                                if !signature.is_empty() {
-                                    parts.push(GooglePart::Thought(GoogleThoughtPart {
-                                        thought: true,
-                                        thought_signature: signature.clone(),
-                                    }));
-                                }
-                            }
-                        }
-                        _ => {}
-                    }
-                }
-
-                if !parts.is_empty() {
-                    contents.push(GoogleContent {
-                        parts,
-                        role: Some("model".to_string()),
-                    });
-                }
-            }
-        }
-    }
-
-    let system_instruction = if system_parts.is_empty() {
-        None
-    } else {
-        Some(GoogleSystemInstruction {
-            parts: system_parts,
-        })
-    };
-
-    let tools: Option<Vec<GoogleTool>> = if request.tools.is_empty() {
-        None
-    } else {
-        let declarations: Vec<GoogleFunctionDeclaration> = request
-            .tools
-            .iter()
-            .map(|t| {
-                let mut parameters: serde_json::Value = serde_json::from_str(&t.input_schema)
-                    .unwrap_or(serde_json::Value::Object(Default::default()));
-                adapt_schema_for_google(&mut parameters);
-                GoogleFunctionDeclaration {
-                    name: t.name.clone(),
-                    description: t.description.clone(),
-                    parameters,
-                }
-            })
-            .collect();
-        Some(vec![GoogleTool {
-            function_declarations: declarations,
-        }])
-    };
-
-    let tool_config = request.tool_choice.as_ref().map(|tc| {
-        let mode = match tc {
-            LlmToolChoice::Auto => "AUTO",
-            LlmToolChoice::Any => "ANY",
-            LlmToolChoice::None => "NONE",
-        };
-        GoogleToolConfig {
-            function_calling_config: GoogleFunctionCallingConfig {
-                mode: mode.to_string(),
-                allowed_function_names: None,
-            },
-        }
-    });
-
-    let thinking_config = if supports_thinking && request.thinking_allowed {
-        Some(GoogleThinkingConfig {
-            thinking_budget: 8192,
-        })
-    } else {
-        None
-    };
-
-    let generation_config = Some(GoogleGenerationConfig {
-        candidate_count: Some(1),
-        stop_sequences: if request.stop_sequences.is_empty() {
-            None
-        } else {
-            Some(request.stop_sequences.clone())
-        },
-        max_output_tokens: None,
-        temperature: request.temperature.map(|t| t as f64).or(Some(1.0)),
-        thinking_config,
-    });
-
-    Ok((
-        GoogleRequest {
-            contents,
-            system_instruction,
-            generation_config,
-            tools,
-            tool_config,
-        },
-        real_model_id.to_string(),
-    ))
-}
-
-fn parse_stream_line(line: &str) -> Option<GoogleStreamResponse> {
-    let trimmed = line.trim();
-    if trimmed.is_empty() || trimmed == "[" || trimmed == "]" || trimmed == "," {
-        return None;
-    }
-
-    let json_str = trimmed.strip_prefix("data: ").unwrap_or(trimmed);
-    let json_str = json_str.trim_start_matches(',').trim();
-
-    if json_str.is_empty() {
-        return None;
-    }
-
-    serde_json::from_str(json_str).ok()
-}
-
-impl zed::Extension for GoogleAiProvider {
-    fn new() -> Self {
-        Self {
-            streams: Mutex::new(HashMap::new()),
-            next_stream_id: Mutex::new(0),
-        }
-    }
-
-    fn llm_providers(&self) -> Vec<LlmProviderInfo> {
-        vec![LlmProviderInfo {
-            id: "google-ai".into(),
-            name: "Google AI".into(),
-            icon: Some("icons/google-ai.svg".into()),
-        }]
-    }
-
-    fn llm_provider_models(&self, _provider_id: &str) -> Result<Vec<LlmModelInfo>, String> {
-        Ok(MODELS
-            .iter()
-            .map(|m| LlmModelInfo {
-                id: m.display_name.to_string(),
-                name: m.display_name.to_string(),
-                max_token_count: m.max_tokens,
-                max_output_tokens: m.max_output_tokens,
-                capabilities: LlmModelCapabilities {
-                    supports_images: m.supports_images,
-                    supports_tools: true,
-                    supports_tool_choice_auto: true,
-                    supports_tool_choice_any: true,
-                    supports_tool_choice_none: true,
-                    supports_thinking: m.supports_thinking,
-                    tool_input_format: LlmToolInputFormat::JsonSchema,
-                },
-                is_default: m.is_default,
-                is_default_fast: m.is_default_fast,
-            })
-            .collect())
-    }
-
-    fn llm_provider_is_authenticated(&self, _provider_id: &str) -> bool {
-        llm_get_credential("google-ai").is_some()
-    }
-
-    fn llm_provider_settings_markdown(&self, _provider_id: &str) -> Option<String> {
-        Some(
-            r#"# Google AI Setup
-
-Welcome to **Google AI**! This extension provides access to Google Gemini models.
-
-## Configuration
-
-Enter your Google AI API key below. You can get your API key at [aistudio.google.com/apikey](https://aistudio.google.com/apikey).
-
-## Available Models
-
-| Display Name | Real Model | Context | Output |
-|--------------|------------|---------|--------|
-| Gemini 2.5 Flash-Lite | gemini-2.5-flash-lite | 1M | 65K |
-| Gemini 2.5 Flash | gemini-2.5-flash | 1M | 65K |
-| Gemini 2.5 Pro | gemini-2.5-pro | 1M | 65K |
-| Gemini 3 Pro | gemini-3-pro-preview | 1M | 65K |
-
-## Features
-
-- ✅ Full streaming support
-- ✅ Tool/function calling with thought signatures
-- ✅ Vision (image inputs)
-- ✅ Extended thinking support
-- ✅ All Gemini models
-
-## Pricing
-
-Uses your Google AI API credits. See [Google AI pricing](https://ai.google.dev/pricing) for details.
-"#
-            .to_string(),
-        )
-    }
-
-    fn llm_provider_authenticate(&mut self, _provider_id: &str) -> Result<(), String> {
-        let provided = llm_request_credential(
-            "google-ai",
-            LlmCredentialType::ApiKey,
-            "Google AI API Key",
-            "AIza...",
-        )?;
-        if provided {
-            Ok(())
-        } else {
-            Err("Authentication cancelled".to_string())
-        }
-    }
-
-    fn llm_provider_reset_credentials(&mut self, _provider_id: &str) -> Result<(), String> {
-        llm_delete_credential("google-ai")
-    }
-
-    fn llm_stream_completion_start(
-        &mut self,
-        _provider_id: &str,
-        model_id: &str,
-        request: &LlmCompletionRequest,
-    ) -> Result<String, String> {
-        let api_key = llm_get_credential("google-ai").ok_or_else(|| {
-            "No API key configured. Please add your Google AI API key in settings.".to_string()
-        })?;
-
-        let (google_request, real_model_id) = convert_request(model_id, request)?;
-
-        let body = serde_json::to_vec(&google_request)
-            .map_err(|e| format!("Failed to serialize request: {}", e))?;
-
-        let url = format!(
-            "https://generativelanguage.googleapis.com/v1beta/models/{}:streamGenerateContent?alt=sse&key={}",
-            real_model_id, api_key
-        );
-
-        let http_request = HttpRequest {
-            method: HttpMethod::Post,
-            url,
-            headers: vec![("Content-Type".to_string(), "application/json".to_string())],
-            body: Some(body),
-            redirect_policy: RedirectPolicy::FollowAll,
-        };
-
-        let response_stream = http_request
-            .fetch_stream()
-            .map_err(|e| format!("HTTP request failed: {}", e))?;
-
-        let stream_id = {
-            let mut id_counter = self.next_stream_id.lock().unwrap();
-            let id = format!("google-ai-stream-{}", *id_counter);
-            *id_counter += 1;
-            id
-        };
-
-        self.streams.lock().unwrap().insert(
-            stream_id.clone(),
-            StreamState {
-                response_stream: Some(response_stream),
-                buffer: String::new(),
-                started: false,
-                stop_reason: None,
-                wants_tool_use: false,
-            },
-        );
-
-        Ok(stream_id)
-    }
-
-    fn llm_stream_completion_next(
-        &mut self,
-        stream_id: &str,
-    ) -> Result<Option<LlmCompletionEvent>, String> {
-        let mut streams = self.streams.lock().unwrap();
-        let state = streams
-            .get_mut(stream_id)
-            .ok_or_else(|| format!("Unknown stream: {}", stream_id))?;
-
-        if !state.started {
-            state.started = true;
-            return Ok(Some(LlmCompletionEvent::Started));
-        }
-
-        let response_stream = state
-            .response_stream
-            .as_mut()
-            .ok_or_else(|| "Stream already closed".to_string())?;
-
-        loop {
-            if let Some(newline_pos) = state.buffer.find('\n') {
-                let line = state.buffer[..newline_pos].to_string();
-                state.buffer = state.buffer[newline_pos + 1..].to_string();
-
-                if let Some(response) = parse_stream_line(&line) {
-                    for candidate in response.candidates {
-                        if let Some(finish_reason) = &candidate.finish_reason {
-                            state.stop_reason = Some(match finish_reason.as_str() {
-                                "STOP" => {
-                                    if state.wants_tool_use {
-                                        LlmStopReason::ToolUse
-                                    } else {
-                                        LlmStopReason::EndTurn
-                                    }
-                                }
-                                "MAX_TOKENS" => LlmStopReason::MaxTokens,
-                                "SAFETY" => LlmStopReason::Refusal,
-                                _ => LlmStopReason::EndTurn,
-                            });
-                        }
-
-                        if let Some(content) = candidate.content {
-                            for part in content.parts {
-                                match part {
-                                    GooglePart::Text(text_part) => {
-                                        if !text_part.text.is_empty() {
-                                            return Ok(Some(LlmCompletionEvent::Text(
-                                                text_part.text,
-                                            )));
-                                        }
-                                    }
-                                    GooglePart::FunctionCall(fc_part) => {
-                                        state.wants_tool_use = true;
-                                        let next_tool_id =
-                                            TOOL_CALL_COUNTER.fetch_add(1, Ordering::SeqCst);
-                                        let id = format!(
-                                            "{}-{}",
-                                            fc_part.function_call.name, next_tool_id
-                                        );
-
-                                        let thought_signature =
-                                            fc_part.thought_signature.filter(|s| !s.is_empty());
-
-                                        return Ok(Some(LlmCompletionEvent::ToolUse(LlmToolUse {
-                                            id,
-                                            name: fc_part.function_call.name,
-                                            input: fc_part.function_call.args.to_string(),
-                                            thought_signature,
-                                        })));
-                                    }
-                                    GooglePart::Thought(thought_part) => {
-                                        return Ok(Some(LlmCompletionEvent::Thinking(
-                                            LlmThinkingContent {
-                                                text: "(Encrypted thought)".to_string(),
-                                                signature: Some(thought_part.thought_signature),
-                                            },
-                                        )));
-                                    }
-                                    _ => {}
-                                }
-                            }
-                        }
-                    }
-
-                    if let Some(usage) = response.usage_metadata {
-                        return Ok(Some(LlmCompletionEvent::Usage(LlmTokenUsage {
-                            input_tokens: usage.prompt_token_count,
-                            output_tokens: usage.candidates_token_count,
-                            cache_creation_input_tokens: None,
-                            cache_read_input_tokens: None,
-                        })));
-                    }
-                }
-
-                continue;
-            }
-
-            match response_stream.next_chunk() {
-                Ok(Some(chunk)) => {
-                    let text = String::from_utf8_lossy(&chunk);
-                    state.buffer.push_str(&text);
-                }
-                Ok(None) => {
-                    // Stream ended - check if we have a stop reason
-                    if let Some(stop_reason) = state.stop_reason.take() {
-                        return Ok(Some(LlmCompletionEvent::Stop(stop_reason)));
-                    }
-
-                    // No stop reason - this is unexpected. Check if buffer contains error info
-                    let mut error_msg = String::from("Stream ended unexpectedly.");
-
-                    // Try to parse remaining buffer as potential error response
-                    if !state.buffer.is_empty() {
-                        error_msg.push_str(&format!(
-                            "\nRemaining buffer: {}",
-                            &state.buffer[..state.buffer.len().min(1000)]
-                        ));
-                    }
-
-                    return Err(error_msg);
-                }
-                Err(e) => {
-                    return Err(format!("Stream error: {}", e));
-                }
-            }
-        }
-    }
-
-    fn llm_stream_completion_close(&mut self, stream_id: &str) {
-        self.streams.lock().unwrap().remove(stream_id);
-    }
-}
-
-zed::register_extension!(GoogleAiProvider);

extensions/open_router/Cargo.lock 🔗

@@ -1,823 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 4
-
-[[package]]
-name = "adler2"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
-
-[[package]]
-name = "anyhow"
-version = "1.0.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
-
-[[package]]
-name = "auditable-serde"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c7bf8143dfc3c0258df908843e169b5cc5fcf76c7718bd66135ef4a9cd558c5"
-dependencies = [
- "semver",
- "serde",
- "serde_json",
- "topological-sort",
-]
-
-[[package]]
-name = "bitflags"
-version = "2.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
-
-[[package]]
-name = "cfg-if"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
-
-[[package]]
-name = "crc32fast"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "displaydoc"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "equivalent"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
-
-[[package]]
-name = "flate2"
-version = "1.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb"
-dependencies = [
- "crc32fast",
- "miniz_oxide",
-]
-
-[[package]]
-name = "foldhash"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
-
-[[package]]
-name = "form_urlencoded"
-version = "1.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
-dependencies = [
- "percent-encoding",
-]
-
-[[package]]
-name = "futures"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-executor",
- "futures-io",
- "futures-sink",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-channel"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
-dependencies = [
- "futures-core",
- "futures-sink",
-]
-
-[[package]]
-name = "futures-core"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
-
-[[package]]
-name = "futures-executor"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
-dependencies = [
- "futures-core",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-io"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
-
-[[package]]
-name = "futures-macro"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "futures-sink"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
-
-[[package]]
-name = "futures-task"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
-
-[[package]]
-name = "futures-util"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-io",
- "futures-macro",
- "futures-sink",
- "futures-task",
- "memchr",
- "pin-project-lite",
- "pin-utils",
- "slab",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.15.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
-dependencies = [
- "foldhash",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.16.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
-
-[[package]]
-name = "heck"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
-
-[[package]]
-name = "icu_collections"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
-dependencies = [
- "displaydoc",
- "potential_utf",
- "yoke",
- "zerofrom",
- "zerovec",
-]
-
-[[package]]
-name = "icu_locale_core"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
-dependencies = [
- "displaydoc",
- "litemap",
- "tinystr",
- "writeable",
- "zerovec",
-]
-
-[[package]]
-name = "icu_normalizer"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599"
-dependencies = [
- "icu_collections",
- "icu_normalizer_data",
- "icu_properties",
- "icu_provider",
- "smallvec",
- "zerovec",
-]
-
-[[package]]
-name = "icu_normalizer_data"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a"
-
-[[package]]
-name = "icu_properties"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99"
-dependencies = [
- "icu_collections",
- "icu_locale_core",
- "icu_properties_data",
- "icu_provider",
- "zerotrie",
- "zerovec",
-]
-
-[[package]]
-name = "icu_properties_data"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899"
-
-[[package]]
-name = "icu_provider"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
-dependencies = [
- "displaydoc",
- "icu_locale_core",
- "writeable",
- "yoke",
- "zerofrom",
- "zerotrie",
- "zerovec",
-]
-
-[[package]]
-name = "id-arena"
-version = "2.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
-
-[[package]]
-name = "idna"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
-dependencies = [
- "idna_adapter",
- "smallvec",
- "utf8_iter",
-]
-
-[[package]]
-name = "idna_adapter"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
-dependencies = [
- "icu_normalizer",
- "icu_properties",
-]
-
-[[package]]
-name = "indexmap"
-version = "2.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2"
-dependencies = [
- "equivalent",
- "hashbrown 0.16.1",
- "serde",
- "serde_core",
-]
-
-[[package]]
-name = "itoa"
-version = "1.0.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
-
-[[package]]
-name = "leb128fmt"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
-
-[[package]]
-name = "litemap"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
-
-[[package]]
-name = "log"
-version = "0.4.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
-
-[[package]]
-name = "memchr"
-version = "2.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
-
-[[package]]
-name = "miniz_oxide"
-version = "0.8.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
-dependencies = [
- "adler2",
- "simd-adler32",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.21.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
-
-[[package]]
-name = "open_router"
-version = "0.1.0"
-dependencies = [
- "serde",
- "serde_json",
- "zed_extension_api",
-]
-
-[[package]]
-name = "percent-encoding"
-version = "2.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
-
-[[package]]
-name = "pin-project-lite"
-version = "0.2.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
-
-[[package]]
-name = "pin-utils"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
-
-[[package]]
-name = "potential_utf"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77"
-dependencies = [
- "zerovec",
-]
-
-[[package]]
-name = "prettyplease"
-version = "0.2.37"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
-dependencies = [
- "proc-macro2",
- "syn",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.103"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.42"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "ryu"
-version = "1.0.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
-
-[[package]]
-name = "semver"
-version = "1.0.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
-dependencies = [
- "serde",
- "serde_core",
-]
-
-[[package]]
-name = "serde"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
-dependencies = [
- "serde_core",
- "serde_derive",
-]
-
-[[package]]
-name = "serde_core"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "serde_json"
-version = "1.0.145"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
-dependencies = [
- "itoa",
- "memchr",
- "ryu",
- "serde",
- "serde_core",
-]
-
-[[package]]
-name = "simd-adler32"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
-
-[[package]]
-name = "slab"
-version = "0.4.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
-
-[[package]]
-name = "smallvec"
-version = "1.15.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
-
-[[package]]
-name = "spdx"
-version = "0.10.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3e17e880bafaeb362a7b751ec46bdc5b61445a188f80e0606e68167cd540fa3"
-dependencies = [
- "smallvec",
-]
-
-[[package]]
-name = "stable_deref_trait"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
-
-[[package]]
-name = "syn"
-version = "2.0.111"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "synstructure"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "tinystr"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
-dependencies = [
- "displaydoc",
- "zerovec",
-]
-
-[[package]]
-name = "topological-sort"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d"
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
-
-[[package]]
-name = "unicode-xid"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
-
-[[package]]
-name = "url"
-version = "2.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b"
-dependencies = [
- "form_urlencoded",
- "idna",
- "percent-encoding",
- "serde",
-]
-
-[[package]]
-name = "utf8_iter"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
-
-[[package]]
-name = "wasm-encoder"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80bb72f02e7fbf07183443b27b0f3d4144abf8c114189f2e088ed95b696a7822"
-dependencies = [
- "leb128fmt",
- "wasmparser",
-]
-
-[[package]]
-name = "wasm-metadata"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce1ef0faabbbba6674e97a56bee857ccddf942785a336c8b47b42373c922a91d"
-dependencies = [
- "anyhow",
- "auditable-serde",
- "flate2",
- "indexmap",
- "serde",
- "serde_derive",
- "serde_json",
- "spdx",
- "url",
- "wasm-encoder",
- "wasmparser",
-]
-
-[[package]]
-name = "wasmparser"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f51cad774fb3c9461ab9bccc9c62dfb7388397b5deda31bf40e8108ccd678b2"
-dependencies = [
- "bitflags",
- "hashbrown 0.15.5",
- "indexmap",
- "semver",
-]
-
-[[package]]
-name = "wit-bindgen"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10fb6648689b3929d56bbc7eb1acf70c9a42a29eb5358c67c10f54dbd5d695de"
-dependencies = [
- "wit-bindgen-rt",
- "wit-bindgen-rust-macro",
-]
-
-[[package]]
-name = "wit-bindgen-core"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92fa781d4f2ff6d3f27f3cc9b74a73327b31ca0dc4a3ef25a0ce2983e0e5af9b"
-dependencies = [
- "anyhow",
- "heck",
- "wit-parser",
-]
-
-[[package]]
-name = "wit-bindgen-rt"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4db52a11d4dfb0a59f194c064055794ee6564eb1ced88c25da2cf76e50c5621"
-dependencies = [
- "bitflags",
- "futures",
- "once_cell",
-]
-
-[[package]]
-name = "wit-bindgen-rust"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d0809dc5ba19e2e98661bf32fc0addc5a3ca5bf3a6a7083aa6ba484085ff3ce"
-dependencies = [
- "anyhow",
- "heck",
- "indexmap",
- "prettyplease",
- "syn",
- "wasm-metadata",
- "wit-bindgen-core",
- "wit-component",
-]
-
-[[package]]
-name = "wit-bindgen-rust-macro"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad19eec017904e04c60719592a803ee5da76cb51c81e3f6fbf9457f59db49799"
-dependencies = [
- "anyhow",
- "prettyplease",
- "proc-macro2",
- "quote",
- "syn",
- "wit-bindgen-core",
- "wit-bindgen-rust",
-]
-
-[[package]]
-name = "wit-component"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "635c3adc595422cbf2341a17fb73a319669cc8d33deed3a48368a841df86b676"
-dependencies = [
- "anyhow",
- "bitflags",
- "indexmap",
- "log",
- "serde",
- "serde_derive",
- "serde_json",
- "wasm-encoder",
- "wasm-metadata",
- "wasmparser",
- "wit-parser",
-]
-
-[[package]]
-name = "wit-parser"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddf445ed5157046e4baf56f9138c124a0824d4d1657e7204d71886ad8ce2fc11"
-dependencies = [
- "anyhow",
- "id-arena",
- "indexmap",
- "log",
- "semver",
- "serde",
- "serde_derive",
- "serde_json",
- "unicode-xid",
- "wasmparser",
-]
-
-[[package]]
-name = "writeable"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
-
-[[package]]
-name = "yoke"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
-dependencies = [
- "stable_deref_trait",
- "yoke-derive",
- "zerofrom",
-]
-
-[[package]]
-name = "yoke-derive"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
-name = "zed_extension_api"
-version = "0.8.0"
-dependencies = [
- "serde",
- "serde_json",
- "wit-bindgen",
-]
-
-[[package]]
-name = "zerofrom"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
-dependencies = [
- "zerofrom-derive",
-]
-
-[[package]]
-name = "zerofrom-derive"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
-name = "zerotrie"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
-dependencies = [
- "displaydoc",
- "yoke",
- "zerofrom",
-]
-
-[[package]]
-name = "zerovec"
-version = "0.11.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
-dependencies = [
- "yoke",
- "zerofrom",
- "zerovec-derive",
-]
-
-[[package]]
-name = "zerovec-derive"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]

extensions/open_router/Cargo.toml 🔗

@@ -1,17 +0,0 @@
-[package]
-name = "open_router"
-version = "0.1.0"
-edition = "2021"
-publish = false
-license = "Apache-2.0"
-
-[workspace]
-
-[lib]
-path = "src/open_router.rs"
-crate-type = ["cdylib"]
-
-[dependencies]
-zed_extension_api = { path = "../../crates/extension_api" }
-serde = { version = "1.0", features = ["derive"] }
-serde_json = "1.0"

extensions/open_router/extension.toml 🔗

@@ -1,13 +0,0 @@
-id = "open_router"
-name = "OpenRouter"
-description = "OpenRouter LLM provider - access multiple AI models through a unified API."
-version = "0.1.0"
-schema_version = 1
-authors = ["Zed Team"]
-repository = "https://github.com/zed-industries/zed"
-
-[language_model_providers.open_router]
-name = "OpenRouter"
-
-[language_model_providers.open_router.auth]
-env_var = "OPENROUTER_API_KEY"

extensions/open_router/icons/open-router.svg 🔗

@@ -1,8 +0,0 @@
-<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M2.54131 7.78012C2.89456 7.78012 4.25937 7.47507 4.96588 7.07512C5.67239 6.67517 5.67239 6.67517 7.13135 5.63951C8.97897 4.32817 10.2858 4.76729 12.4272 4.76729" fill="black"/>
-<path d="M2.54131 7.78012C2.89456 7.78012 4.25937 7.47507 4.96588 7.07512C5.67239 6.67517 5.67239 6.67517 7.13135 5.63951C8.97897 4.32817 10.2858 4.76729 12.4272 4.76729" stroke="black" stroke-width="2.8125"/>
-<path d="M14.4985 4.7801L10.8793 6.86949V2.6907L14.4985 4.7801Z" fill="black" stroke="black"/>
-<path d="M2.47052 7.78088C2.82377 7.78088 4.18859 8.08593 4.8951 8.48588C5.60161 8.88583 5.6016 8.88583 7.06057 9.92149C8.90819 11.2328 10.2142 10.7937 12.3564 10.7937" fill="black"/>
-<path d="M2.47052 7.78088C2.82377 7.78088 4.18859 8.08593 4.8951 8.48588C5.60161 8.88583 5.6016 8.88583 7.06057 9.92149C8.90819 11.2328 10.2142 10.7937 12.3564 10.7937" stroke="black" stroke-width="2.8125"/>
-<path d="M14.4277 10.7809L10.8085 8.6915V12.8703L14.4277 10.7809Z" fill="black" stroke="black"/>
-</svg>

extensions/open_router/src/open_router.rs 🔗

@@ -1,830 +0,0 @@
-use std::collections::HashMap;
-use std::sync::Mutex;
-
-use serde::{Deserialize, Serialize};
-use zed_extension_api::http_client::{HttpMethod, HttpRequest, HttpResponseStream, RedirectPolicy};
-use zed_extension_api::{self as zed, *};
-
-struct OpenRouterProvider {
-    streams: Mutex<HashMap<String, StreamState>>,
-    next_stream_id: Mutex<u64>,
-}
-
-struct StreamState {
-    response_stream: Option<HttpResponseStream>,
-    buffer: String,
-    started: bool,
-    tool_calls: HashMap<usize, AccumulatedToolCall>,
-    tool_calls_emitted: bool,
-}
-
-#[derive(Clone, Default)]
-struct AccumulatedToolCall {
-    id: String,
-    name: String,
-    arguments: String,
-}
-
-struct ModelDefinition {
-    id: &'static str,
-    display_name: &'static str,
-    max_tokens: u64,
-    max_output_tokens: Option<u64>,
-    supports_images: bool,
-    supports_tools: bool,
-    is_default: bool,
-    is_default_fast: bool,
-}
-
-const MODELS: &[ModelDefinition] = &[
-    // Anthropic Models
-    ModelDefinition {
-        id: "anthropic/claude-sonnet-4",
-        display_name: "Claude Sonnet 4",
-        max_tokens: 200_000,
-        max_output_tokens: Some(8_192),
-        supports_images: true,
-        supports_tools: true,
-        is_default: true,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        id: "anthropic/claude-opus-4",
-        display_name: "Claude Opus 4",
-        max_tokens: 200_000,
-        max_output_tokens: Some(8_192),
-        supports_images: true,
-        supports_tools: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        id: "anthropic/claude-haiku-4",
-        display_name: "Claude Haiku 4",
-        max_tokens: 200_000,
-        max_output_tokens: Some(8_192),
-        supports_images: true,
-        supports_tools: true,
-        is_default: false,
-        is_default_fast: true,
-    },
-    ModelDefinition {
-        id: "anthropic/claude-3.5-sonnet",
-        display_name: "Claude 3.5 Sonnet",
-        max_tokens: 200_000,
-        max_output_tokens: Some(8_192),
-        supports_images: true,
-        supports_tools: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    // OpenAI Models
-    ModelDefinition {
-        id: "openai/gpt-4o",
-        display_name: "GPT-4o",
-        max_tokens: 128_000,
-        max_output_tokens: Some(16_384),
-        supports_images: true,
-        supports_tools: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        id: "openai/gpt-4o-mini",
-        display_name: "GPT-4o Mini",
-        max_tokens: 128_000,
-        max_output_tokens: Some(16_384),
-        supports_images: true,
-        supports_tools: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        id: "openai/o1",
-        display_name: "o1",
-        max_tokens: 200_000,
-        max_output_tokens: Some(100_000),
-        supports_images: true,
-        supports_tools: false,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        id: "openai/o3-mini",
-        display_name: "o3-mini",
-        max_tokens: 200_000,
-        max_output_tokens: Some(100_000),
-        supports_images: false,
-        supports_tools: false,
-        is_default: false,
-        is_default_fast: false,
-    },
-    // Google Models
-    ModelDefinition {
-        id: "google/gemini-2.0-flash-001",
-        display_name: "Gemini 2.0 Flash",
-        max_tokens: 1_000_000,
-        max_output_tokens: Some(8_192),
-        supports_images: true,
-        supports_tools: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        id: "google/gemini-2.5-pro-preview",
-        display_name: "Gemini 2.5 Pro",
-        max_tokens: 1_000_000,
-        max_output_tokens: Some(8_192),
-        supports_images: true,
-        supports_tools: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    // Meta Models
-    ModelDefinition {
-        id: "meta-llama/llama-3.3-70b-instruct",
-        display_name: "Llama 3.3 70B",
-        max_tokens: 128_000,
-        max_output_tokens: Some(4_096),
-        supports_images: false,
-        supports_tools: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        id: "meta-llama/llama-4-maverick",
-        display_name: "Llama 4 Maverick",
-        max_tokens: 128_000,
-        max_output_tokens: Some(4_096),
-        supports_images: true,
-        supports_tools: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    // Mistral Models
-    ModelDefinition {
-        id: "mistralai/mistral-large-2411",
-        display_name: "Mistral Large",
-        max_tokens: 128_000,
-        max_output_tokens: Some(4_096),
-        supports_images: false,
-        supports_tools: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        id: "mistralai/codestral-latest",
-        display_name: "Codestral",
-        max_tokens: 32_000,
-        max_output_tokens: Some(4_096),
-        supports_images: false,
-        supports_tools: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    // DeepSeek Models
-    ModelDefinition {
-        id: "deepseek/deepseek-chat-v3-0324",
-        display_name: "DeepSeek V3",
-        max_tokens: 64_000,
-        max_output_tokens: Some(8_192),
-        supports_images: false,
-        supports_tools: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        id: "deepseek/deepseek-r1",
-        display_name: "DeepSeek R1",
-        max_tokens: 64_000,
-        max_output_tokens: Some(8_192),
-        supports_images: false,
-        supports_tools: false,
-        is_default: false,
-        is_default_fast: false,
-    },
-    // Qwen Models
-    ModelDefinition {
-        id: "qwen/qwen3-235b-a22b",
-        display_name: "Qwen 3 235B",
-        max_tokens: 40_000,
-        max_output_tokens: Some(8_192),
-        supports_images: false,
-        supports_tools: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-];
-
-fn get_model_definition(model_id: &str) -> Option<&'static ModelDefinition> {
-    MODELS.iter().find(|m| m.id == model_id)
-}
-
-#[derive(Serialize)]
-struct OpenRouterRequest {
-    model: String,
-    messages: Vec<OpenRouterMessage>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    max_tokens: Option<u64>,
-    #[serde(skip_serializing_if = "Vec::is_empty")]
-    tools: Vec<OpenRouterTool>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    tool_choice: Option<String>,
-    #[serde(skip_serializing_if = "Vec::is_empty")]
-    stop: Vec<String>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    temperature: Option<f32>,
-    stream: bool,
-}
-
-#[derive(Serialize)]
-struct OpenRouterMessage {
-    role: String,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    content: Option<OpenRouterContent>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    tool_calls: Option<Vec<OpenRouterToolCall>>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    tool_call_id: Option<String>,
-}
-
-#[derive(Serialize, Clone)]
-#[serde(untagged)]
-enum OpenRouterContent {
-    Text(String),
-    Parts(Vec<OpenRouterContentPart>),
-}
-
-#[derive(Serialize, Clone)]
-#[serde(tag = "type")]
-enum OpenRouterContentPart {
-    #[serde(rename = "text")]
-    Text { text: String },
-    #[serde(rename = "image_url")]
-    ImageUrl { image_url: ImageUrl },
-}
-
-#[derive(Serialize, Clone)]
-struct ImageUrl {
-    url: String,
-}
-
-#[derive(Serialize, Clone)]
-struct OpenRouterToolCall {
-    id: String,
-    #[serde(rename = "type")]
-    call_type: String,
-    function: OpenRouterFunctionCall,
-}
-
-#[derive(Serialize, Clone)]
-struct OpenRouterFunctionCall {
-    name: String,
-    arguments: String,
-}
-
-#[derive(Serialize)]
-struct OpenRouterTool {
-    #[serde(rename = "type")]
-    tool_type: String,
-    function: OpenRouterFunctionDef,
-}
-
-#[derive(Serialize)]
-struct OpenRouterFunctionDef {
-    name: String,
-    description: String,
-    parameters: serde_json::Value,
-}
-
-#[derive(Deserialize, Debug)]
-struct OpenRouterStreamResponse {
-    choices: Vec<OpenRouterStreamChoice>,
-    #[serde(default)]
-    usage: Option<OpenRouterUsage>,
-}
-
-#[derive(Deserialize, Debug)]
-struct OpenRouterStreamChoice {
-    delta: OpenRouterDelta,
-    finish_reason: Option<String>,
-}
-
-#[derive(Deserialize, Debug, Default)]
-struct OpenRouterDelta {
-    #[serde(default)]
-    content: Option<String>,
-    #[serde(default)]
-    tool_calls: Option<Vec<OpenRouterToolCallDelta>>,
-}
-
-#[derive(Deserialize, Debug)]
-struct OpenRouterToolCallDelta {
-    index: usize,
-    #[serde(default)]
-    id: Option<String>,
-    #[serde(default)]
-    function: Option<OpenRouterFunctionDelta>,
-}
-
-#[derive(Deserialize, Debug, Default)]
-struct OpenRouterFunctionDelta {
-    #[serde(default)]
-    name: Option<String>,
-    #[serde(default)]
-    arguments: Option<String>,
-}
-
-#[derive(Deserialize, Debug)]
-struct OpenRouterUsage {
-    prompt_tokens: u64,
-    completion_tokens: u64,
-}
-
-fn convert_request(
-    model_id: &str,
-    request: &LlmCompletionRequest,
-) -> Result<OpenRouterRequest, String> {
-    let mut messages: Vec<OpenRouterMessage> = Vec::new();
-
-    for msg in &request.messages {
-        match msg.role {
-            LlmMessageRole::System => {
-                let mut text_content = String::new();
-                for content in &msg.content {
-                    if let LlmMessageContent::Text(text) = content {
-                        if !text_content.is_empty() {
-                            text_content.push('\n');
-                        }
-                        text_content.push_str(text);
-                    }
-                }
-                if !text_content.is_empty() {
-                    messages.push(OpenRouterMessage {
-                        role: "system".to_string(),
-                        content: Some(OpenRouterContent::Text(text_content)),
-                        tool_calls: None,
-                        tool_call_id: None,
-                    });
-                }
-            }
-            LlmMessageRole::User => {
-                let mut parts: Vec<OpenRouterContentPart> = Vec::new();
-                let mut tool_result_messages: Vec<OpenRouterMessage> = Vec::new();
-
-                for content in &msg.content {
-                    match content {
-                        LlmMessageContent::Text(text) => {
-                            if !text.is_empty() {
-                                parts.push(OpenRouterContentPart::Text { text: text.clone() });
-                            }
-                        }
-                        LlmMessageContent::Image(img) => {
-                            let data_url = format!("data:image/png;base64,{}", img.source);
-                            parts.push(OpenRouterContentPart::ImageUrl {
-                                image_url: ImageUrl { url: data_url },
-                            });
-                        }
-                        LlmMessageContent::ToolResult(result) => {
-                            let content_text = match &result.content {
-                                LlmToolResultContent::Text(t) => t.clone(),
-                                LlmToolResultContent::Image(_) => "[Image]".to_string(),
-                            };
-                            tool_result_messages.push(OpenRouterMessage {
-                                role: "tool".to_string(),
-                                content: Some(OpenRouterContent::Text(content_text)),
-                                tool_calls: None,
-                                tool_call_id: Some(result.tool_use_id.clone()),
-                            });
-                        }
-                        _ => {}
-                    }
-                }
-
-                if !parts.is_empty() {
-                    let content = if parts.len() == 1 {
-                        if let OpenRouterContentPart::Text { text } = &parts[0] {
-                            OpenRouterContent::Text(text.clone())
-                        } else {
-                            OpenRouterContent::Parts(parts)
-                        }
-                    } else {
-                        OpenRouterContent::Parts(parts)
-                    };
-
-                    messages.push(OpenRouterMessage {
-                        role: "user".to_string(),
-                        content: Some(content),
-                        tool_calls: None,
-                        tool_call_id: None,
-                    });
-                }
-
-                messages.extend(tool_result_messages);
-            }
-            LlmMessageRole::Assistant => {
-                let mut text_content = String::new();
-                let mut tool_calls: Vec<OpenRouterToolCall> = Vec::new();
-
-                for content in &msg.content {
-                    match content {
-                        LlmMessageContent::Text(text) => {
-                            if !text.is_empty() {
-                                if !text_content.is_empty() {
-                                    text_content.push('\n');
-                                }
-                                text_content.push_str(text);
-                            }
-                        }
-                        LlmMessageContent::ToolUse(tool_use) => {
-                            tool_calls.push(OpenRouterToolCall {
-                                id: tool_use.id.clone(),
-                                call_type: "function".to_string(),
-                                function: OpenRouterFunctionCall {
-                                    name: tool_use.name.clone(),
-                                    arguments: tool_use.input.clone(),
-                                },
-                            });
-                        }
-                        _ => {}
-                    }
-                }
-
-                messages.push(OpenRouterMessage {
-                    role: "assistant".to_string(),
-                    content: if text_content.is_empty() {
-                        None
-                    } else {
-                        Some(OpenRouterContent::Text(text_content))
-                    },
-                    tool_calls: if tool_calls.is_empty() {
-                        None
-                    } else {
-                        Some(tool_calls)
-                    },
-                    tool_call_id: None,
-                });
-            }
-        }
-    }
-
-    let model_def = get_model_definition(model_id);
-    let supports_tools = model_def.map(|m| m.supports_tools).unwrap_or(true);
-
-    let tools: Vec<OpenRouterTool> = if supports_tools {
-        request
-            .tools
-            .iter()
-            .map(|t| OpenRouterTool {
-                tool_type: "function".to_string(),
-                function: OpenRouterFunctionDef {
-                    name: t.name.clone(),
-                    description: t.description.clone(),
-                    parameters: serde_json::from_str(&t.input_schema)
-                        .unwrap_or(serde_json::Value::Object(Default::default())),
-                },
-            })
-            .collect()
-    } else {
-        Vec::new()
-    };
-
-    let tool_choice = if supports_tools {
-        request.tool_choice.as_ref().map(|tc| match tc {
-            LlmToolChoice::Auto => "auto".to_string(),
-            LlmToolChoice::Any => "required".to_string(),
-            LlmToolChoice::None => "none".to_string(),
-        })
-    } else {
-        None
-    };
-
-    let max_tokens = request
-        .max_tokens
-        .or(model_def.and_then(|m| m.max_output_tokens));
-
-    Ok(OpenRouterRequest {
-        model: model_id.to_string(),
-        messages,
-        max_tokens,
-        tools,
-        tool_choice,
-        stop: request.stop_sequences.clone(),
-        temperature: request.temperature,
-        stream: true,
-    })
-}
-
-fn parse_sse_line(line: &str) -> Option<OpenRouterStreamResponse> {
-    let data = line.strip_prefix("data: ")?;
-    if data.trim() == "[DONE]" {
-        return None;
-    }
-    serde_json::from_str(data).ok()
-}
-
-impl zed::Extension for OpenRouterProvider {
-    fn new() -> Self {
-        Self {
-            streams: Mutex::new(HashMap::new()),
-            next_stream_id: Mutex::new(0),
-        }
-    }
-
-    fn llm_providers(&self) -> Vec<LlmProviderInfo> {
-        vec![LlmProviderInfo {
-            id: "open_router".into(),
-            name: "OpenRouter".into(),
-            icon: Some("icons/open-router.svg".into()),
-        }]
-    }
-
-    fn llm_provider_models(&self, _provider_id: &str) -> Result<Vec<LlmModelInfo>, String> {
-        Ok(MODELS
-            .iter()
-            .map(|m| LlmModelInfo {
-                id: m.id.to_string(),
-                name: m.display_name.to_string(),
-                max_token_count: m.max_tokens,
-                max_output_tokens: m.max_output_tokens,
-                capabilities: LlmModelCapabilities {
-                    supports_images: m.supports_images,
-                    supports_tools: m.supports_tools,
-                    supports_tool_choice_auto: m.supports_tools,
-                    supports_tool_choice_any: m.supports_tools,
-                    supports_tool_choice_none: m.supports_tools,
-                    supports_thinking: false,
-                    tool_input_format: LlmToolInputFormat::JsonSchema,
-                },
-                is_default: m.is_default,
-                is_default_fast: m.is_default_fast,
-            })
-            .collect())
-    }
-
-    fn llm_provider_is_authenticated(&self, _provider_id: &str) -> bool {
-        llm_get_credential("open_router").is_some()
-    }
-
-    fn llm_provider_settings_markdown(&self, _provider_id: &str) -> Option<String> {
-        Some(
-            r#"# OpenRouter Setup
-
-Welcome to **OpenRouter**! Access multiple AI models through a single API.
-
-## Configuration
-
-Enter your OpenRouter API key below. Get your API key at [openrouter.ai/keys](https://openrouter.ai/keys).
-
-## Available Models
-
-### Anthropic
-| Model | Context | Output |
-|-------|---------|--------|
-| Claude Sonnet 4 | 200K | 8K |
-| Claude Opus 4 | 200K | 8K |
-| Claude Haiku 4 | 200K | 8K |
-| Claude 3.5 Sonnet | 200K | 8K |
-
-### OpenAI
-| Model | Context | Output |
-|-------|---------|--------|
-| GPT-4o | 128K | 16K |
-| GPT-4o Mini | 128K | 16K |
-| o1 | 200K | 100K |
-| o3-mini | 200K | 100K |
-
-### Google
-| Model | Context | Output |
-|-------|---------|--------|
-| Gemini 2.0 Flash | 1M | 8K |
-| Gemini 2.5 Pro | 1M | 8K |
-
-### Meta
-| Model | Context | Output |
-|-------|---------|--------|
-| Llama 3.3 70B | 128K | 4K |
-| Llama 4 Maverick | 128K | 4K |
-
-### Mistral
-| Model | Context | Output |
-|-------|---------|--------|
-| Mistral Large | 128K | 4K |
-| Codestral | 32K | 4K |
-
-### DeepSeek
-| Model | Context | Output |
-|-------|---------|--------|
-| DeepSeek V3 | 64K | 8K |
-| DeepSeek R1 | 64K | 8K |
-
-### Qwen
-| Model | Context | Output |
-|-------|---------|--------|
-| Qwen 3 235B | 40K | 8K |
-
-## Features
-
-- ✅ Full streaming support
-- ✅ Tool/function calling (model dependent)
-- ✅ Vision (model dependent)
-- ✅ Access to 200+ models
-- ✅ Unified billing
-
-## Pricing
-
-Pay-per-use based on model. See [openrouter.ai/models](https://openrouter.ai/models) for pricing.
-"#
-            .to_string(),
-        )
-    }
-
-    fn llm_provider_authenticate(&mut self, _provider_id: &str) -> Result<(), String> {
-        let provided = llm_request_credential(
-            "open_router",
-            LlmCredentialType::ApiKey,
-            "OpenRouter API Key",
-            "sk-or-v1-...",
-        )?;
-        if provided {
-            Ok(())
-        } else {
-            Err("Authentication cancelled".to_string())
-        }
-    }
-
-    fn llm_provider_reset_credentials(&mut self, _provider_id: &str) -> Result<(), String> {
-        llm_delete_credential("open_router")
-    }
-
-    fn llm_stream_completion_start(
-        &mut self,
-        _provider_id: &str,
-        model_id: &str,
-        request: &LlmCompletionRequest,
-    ) -> Result<String, String> {
-        let api_key = llm_get_credential("open_router").ok_or_else(|| {
-            "No API key configured. Please add your OpenRouter API key in settings.".to_string()
-        })?;
-
-        let openrouter_request = convert_request(model_id, request)?;
-
-        let body = serde_json::to_vec(&openrouter_request)
-            .map_err(|e| format!("Failed to serialize request: {}", e))?;
-
-        let http_request = HttpRequest {
-            method: HttpMethod::Post,
-            url: "https://openrouter.ai/api/v1/chat/completions".to_string(),
-            headers: vec![
-                ("Content-Type".to_string(), "application/json".to_string()),
-                ("Authorization".to_string(), format!("Bearer {}", api_key)),
-                ("HTTP-Referer".to_string(), "https://zed.dev".to_string()),
-                ("X-Title".to_string(), "Zed Editor".to_string()),
-            ],
-            body: Some(body),
-            redirect_policy: RedirectPolicy::FollowAll,
-        };
-
-        let response_stream = http_request
-            .fetch_stream()
-            .map_err(|e| format!("HTTP request failed: {}", e))?;
-
-        let stream_id = {
-            let mut id_counter = self.next_stream_id.lock().unwrap();
-            let id = format!("openrouter-stream-{}", *id_counter);
-            *id_counter += 1;
-            id
-        };
-
-        self.streams.lock().unwrap().insert(
-            stream_id.clone(),
-            StreamState {
-                response_stream: Some(response_stream),
-                buffer: String::new(),
-                started: false,
-                tool_calls: HashMap::new(),
-                tool_calls_emitted: false,
-            },
-        );
-
-        Ok(stream_id)
-    }
-
-    fn llm_stream_completion_next(
-        &mut self,
-        stream_id: &str,
-    ) -> Result<Option<LlmCompletionEvent>, String> {
-        let mut streams = self.streams.lock().unwrap();
-        let state = streams
-            .get_mut(stream_id)
-            .ok_or_else(|| format!("Unknown stream: {}", stream_id))?;
-
-        if !state.started {
-            state.started = true;
-            return Ok(Some(LlmCompletionEvent::Started));
-        }
-
-        let response_stream = state
-            .response_stream
-            .as_mut()
-            .ok_or_else(|| "Stream already closed".to_string())?;
-
-        loop {
-            if let Some(newline_pos) = state.buffer.find('\n') {
-                let line = state.buffer[..newline_pos].to_string();
-                state.buffer = state.buffer[newline_pos + 1..].to_string();
-
-                if line.trim().is_empty() {
-                    continue;
-                }
-
-                if let Some(response) = parse_sse_line(&line) {
-                    if let Some(choice) = response.choices.first() {
-                        if let Some(content) = &choice.delta.content {
-                            if !content.is_empty() {
-                                return Ok(Some(LlmCompletionEvent::Text(content.clone())));
-                            }
-                        }
-
-                        if let Some(tool_calls) = &choice.delta.tool_calls {
-                            for tc in tool_calls {
-                                let entry = state
-                                    .tool_calls
-                                    .entry(tc.index)
-                                    .or_insert_with(AccumulatedToolCall::default);
-
-                                if let Some(id) = &tc.id {
-                                    entry.id = id.clone();
-                                }
-                                if let Some(func) = &tc.function {
-                                    if let Some(name) = &func.name {
-                                        entry.name = name.clone();
-                                    }
-                                    if let Some(args) = &func.arguments {
-                                        entry.arguments.push_str(args);
-                                    }
-                                }
-                            }
-                        }
-
-                        if let Some(finish_reason) = &choice.finish_reason {
-                            if !state.tool_calls.is_empty() && !state.tool_calls_emitted {
-                                state.tool_calls_emitted = true;
-                                let mut tool_calls: Vec<_> = state.tool_calls.drain().collect();
-                                tool_calls.sort_by_key(|(idx, _)| *idx);
-
-                                if let Some((_, tc)) = tool_calls.into_iter().next() {
-                                    return Ok(Some(LlmCompletionEvent::ToolUse(LlmToolUse {
-                                        id: tc.id,
-                                        name: tc.name,
-                                        input: tc.arguments,
-                                        thought_signature: None,
-                                    })));
-                                }
-                            }
-
-                            let stop_reason = match finish_reason.as_str() {
-                                "stop" => LlmStopReason::EndTurn,
-                                "length" => LlmStopReason::MaxTokens,
-                                "tool_calls" => LlmStopReason::ToolUse,
-                                "content_filter" => LlmStopReason::Refusal,
-                                _ => LlmStopReason::EndTurn,
-                            };
-                            return Ok(Some(LlmCompletionEvent::Stop(stop_reason)));
-                        }
-                    }
-
-                    if let Some(usage) = response.usage {
-                        return Ok(Some(LlmCompletionEvent::Usage(LlmTokenUsage {
-                            input_tokens: usage.prompt_tokens,
-                            output_tokens: usage.completion_tokens,
-                            cache_creation_input_tokens: None,
-                            cache_read_input_tokens: None,
-                        })));
-                    }
-                }
-
-                continue;
-            }
-
-            match response_stream.next_chunk() {
-                Ok(Some(chunk)) => {
-                    let text = String::from_utf8_lossy(&chunk);
-                    state.buffer.push_str(&text);
-                }
-                Ok(None) => {
-                    return Ok(None);
-                }
-                Err(e) => {
-                    return Err(format!("Stream error: {}", e));
-                }
-            }
-        }
-    }
-
-    fn llm_stream_completion_close(&mut self, stream_id: &str) {
-        self.streams.lock().unwrap().remove(stream_id);
-    }
-}
-
-zed::register_extension!(OpenRouterProvider);

extensions/openai/Cargo.lock 🔗

@@ -1,823 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 4
-
-[[package]]
-name = "adler2"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
-
-[[package]]
-name = "anyhow"
-version = "1.0.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
-
-[[package]]
-name = "auditable-serde"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c7bf8143dfc3c0258df908843e169b5cc5fcf76c7718bd66135ef4a9cd558c5"
-dependencies = [
- "semver",
- "serde",
- "serde_json",
- "topological-sort",
-]
-
-[[package]]
-name = "bitflags"
-version = "2.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
-
-[[package]]
-name = "cfg-if"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
-
-[[package]]
-name = "crc32fast"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "displaydoc"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "equivalent"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
-
-[[package]]
-name = "flate2"
-version = "1.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb"
-dependencies = [
- "crc32fast",
- "miniz_oxide",
-]
-
-[[package]]
-name = "foldhash"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
-
-[[package]]
-name = "fopenai"
-version = "0.1.0"
-dependencies = [
- "serde",
- "serde_json",
- "zed_extension_api",
-]
-
-[[package]]
-name = "form_urlencoded"
-version = "1.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
-dependencies = [
- "percent-encoding",
-]
-
-[[package]]
-name = "futures"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-executor",
- "futures-io",
- "futures-sink",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-channel"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
-dependencies = [
- "futures-core",
- "futures-sink",
-]
-
-[[package]]
-name = "futures-core"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
-
-[[package]]
-name = "futures-executor"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
-dependencies = [
- "futures-core",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-io"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
-
-[[package]]
-name = "futures-macro"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "futures-sink"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
-
-[[package]]
-name = "futures-task"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
-
-[[package]]
-name = "futures-util"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-io",
- "futures-macro",
- "futures-sink",
- "futures-task",
- "memchr",
- "pin-project-lite",
- "pin-utils",
- "slab",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.15.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
-dependencies = [
- "foldhash",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.16.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
-
-[[package]]
-name = "heck"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
-
-[[package]]
-name = "icu_collections"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
-dependencies = [
- "displaydoc",
- "potential_utf",
- "yoke",
- "zerofrom",
- "zerovec",
-]
-
-[[package]]
-name = "icu_locale_core"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
-dependencies = [
- "displaydoc",
- "litemap",
- "tinystr",
- "writeable",
- "zerovec",
-]
-
-[[package]]
-name = "icu_normalizer"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599"
-dependencies = [
- "icu_collections",
- "icu_normalizer_data",
- "icu_properties",
- "icu_provider",
- "smallvec",
- "zerovec",
-]
-
-[[package]]
-name = "icu_normalizer_data"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a"
-
-[[package]]
-name = "icu_properties"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99"
-dependencies = [
- "icu_collections",
- "icu_locale_core",
- "icu_properties_data",
- "icu_provider",
- "zerotrie",
- "zerovec",
-]
-
-[[package]]
-name = "icu_properties_data"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899"
-
-[[package]]
-name = "icu_provider"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
-dependencies = [
- "displaydoc",
- "icu_locale_core",
- "writeable",
- "yoke",
- "zerofrom",
- "zerotrie",
- "zerovec",
-]
-
-[[package]]
-name = "id-arena"
-version = "2.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
-
-[[package]]
-name = "idna"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
-dependencies = [
- "idna_adapter",
- "smallvec",
- "utf8_iter",
-]
-
-[[package]]
-name = "idna_adapter"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
-dependencies = [
- "icu_normalizer",
- "icu_properties",
-]
-
-[[package]]
-name = "indexmap"
-version = "2.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2"
-dependencies = [
- "equivalent",
- "hashbrown 0.16.1",
- "serde",
- "serde_core",
-]
-
-[[package]]
-name = "itoa"
-version = "1.0.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
-
-[[package]]
-name = "leb128fmt"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
-
-[[package]]
-name = "litemap"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
-
-[[package]]
-name = "log"
-version = "0.4.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
-
-[[package]]
-name = "memchr"
-version = "2.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
-
-[[package]]
-name = "miniz_oxide"
-version = "0.8.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
-dependencies = [
- "adler2",
- "simd-adler32",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.21.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
-
-[[package]]
-name = "percent-encoding"
-version = "2.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
-
-[[package]]
-name = "pin-project-lite"
-version = "0.2.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
-
-[[package]]
-name = "pin-utils"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
-
-[[package]]
-name = "potential_utf"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77"
-dependencies = [
- "zerovec",
-]
-
-[[package]]
-name = "prettyplease"
-version = "0.2.37"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
-dependencies = [
- "proc-macro2",
- "syn",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.103"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.42"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "ryu"
-version = "1.0.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
-
-[[package]]
-name = "semver"
-version = "1.0.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
-dependencies = [
- "serde",
- "serde_core",
-]
-
-[[package]]
-name = "serde"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
-dependencies = [
- "serde_core",
- "serde_derive",
-]
-
-[[package]]
-name = "serde_core"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "serde_json"
-version = "1.0.145"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
-dependencies = [
- "itoa",
- "memchr",
- "ryu",
- "serde",
- "serde_core",
-]
-
-[[package]]
-name = "simd-adler32"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
-
-[[package]]
-name = "slab"
-version = "0.4.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
-
-[[package]]
-name = "smallvec"
-version = "1.15.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
-
-[[package]]
-name = "spdx"
-version = "0.10.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3e17e880bafaeb362a7b751ec46bdc5b61445a188f80e0606e68167cd540fa3"
-dependencies = [
- "smallvec",
-]
-
-[[package]]
-name = "stable_deref_trait"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
-
-[[package]]
-name = "syn"
-version = "2.0.111"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "synstructure"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "tinystr"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
-dependencies = [
- "displaydoc",
- "zerovec",
-]
-
-[[package]]
-name = "topological-sort"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d"
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
-
-[[package]]
-name = "unicode-xid"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
-
-[[package]]
-name = "url"
-version = "2.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b"
-dependencies = [
- "form_urlencoded",
- "idna",
- "percent-encoding",
- "serde",
-]
-
-[[package]]
-name = "utf8_iter"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
-
-[[package]]
-name = "wasm-encoder"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80bb72f02e7fbf07183443b27b0f3d4144abf8c114189f2e088ed95b696a7822"
-dependencies = [
- "leb128fmt",
- "wasmparser",
-]
-
-[[package]]
-name = "wasm-metadata"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce1ef0faabbbba6674e97a56bee857ccddf942785a336c8b47b42373c922a91d"
-dependencies = [
- "anyhow",
- "auditable-serde",
- "flate2",
- "indexmap",
- "serde",
- "serde_derive",
- "serde_json",
- "spdx",
- "url",
- "wasm-encoder",
- "wasmparser",
-]
-
-[[package]]
-name = "wasmparser"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f51cad774fb3c9461ab9bccc9c62dfb7388397b5deda31bf40e8108ccd678b2"
-dependencies = [
- "bitflags",
- "hashbrown 0.15.5",
- "indexmap",
- "semver",
-]
-
-[[package]]
-name = "wit-bindgen"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10fb6648689b3929d56bbc7eb1acf70c9a42a29eb5358c67c10f54dbd5d695de"
-dependencies = [
- "wit-bindgen-rt",
- "wit-bindgen-rust-macro",
-]
-
-[[package]]
-name = "wit-bindgen-core"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92fa781d4f2ff6d3f27f3cc9b74a73327b31ca0dc4a3ef25a0ce2983e0e5af9b"
-dependencies = [
- "anyhow",
- "heck",
- "wit-parser",
-]
-
-[[package]]
-name = "wit-bindgen-rt"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4db52a11d4dfb0a59f194c064055794ee6564eb1ced88c25da2cf76e50c5621"
-dependencies = [
- "bitflags",
- "futures",
- "once_cell",
-]
-
-[[package]]
-name = "wit-bindgen-rust"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d0809dc5ba19e2e98661bf32fc0addc5a3ca5bf3a6a7083aa6ba484085ff3ce"
-dependencies = [
- "anyhow",
- "heck",
- "indexmap",
- "prettyplease",
- "syn",
- "wasm-metadata",
- "wit-bindgen-core",
- "wit-component",
-]
-
-[[package]]
-name = "wit-bindgen-rust-macro"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad19eec017904e04c60719592a803ee5da76cb51c81e3f6fbf9457f59db49799"
-dependencies = [
- "anyhow",
- "prettyplease",
- "proc-macro2",
- "quote",
- "syn",
- "wit-bindgen-core",
- "wit-bindgen-rust",
-]
-
-[[package]]
-name = "wit-component"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "635c3adc595422cbf2341a17fb73a319669cc8d33deed3a48368a841df86b676"
-dependencies = [
- "anyhow",
- "bitflags",
- "indexmap",
- "log",
- "serde",
- "serde_derive",
- "serde_json",
- "wasm-encoder",
- "wasm-metadata",
- "wasmparser",
- "wit-parser",
-]
-
-[[package]]
-name = "wit-parser"
-version = "0.227.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddf445ed5157046e4baf56f9138c124a0824d4d1657e7204d71886ad8ce2fc11"
-dependencies = [
- "anyhow",
- "id-arena",
- "indexmap",
- "log",
- "semver",
- "serde",
- "serde_derive",
- "serde_json",
- "unicode-xid",
- "wasmparser",
-]
-
-[[package]]
-name = "writeable"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
-
-[[package]]
-name = "yoke"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
-dependencies = [
- "stable_deref_trait",
- "yoke-derive",
- "zerofrom",
-]
-
-[[package]]
-name = "yoke-derive"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
-name = "zed_extension_api"
-version = "0.7.0"
-dependencies = [
- "serde",
- "serde_json",
- "wit-bindgen",
-]
-
-[[package]]
-name = "zerofrom"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
-dependencies = [
- "zerofrom-derive",
-]
-
-[[package]]
-name = "zerofrom-derive"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
-name = "zerotrie"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
-dependencies = [
- "displaydoc",
- "yoke",
- "zerofrom",
-]
-
-[[package]]
-name = "zerovec"
-version = "0.11.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
-dependencies = [
- "yoke",
- "zerofrom",
- "zerovec-derive",
-]
-
-[[package]]
-name = "zerovec-derive"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]

extensions/openai/Cargo.toml 🔗

@@ -1,17 +0,0 @@
-[package]
-name = "openai"
-version = "0.1.0"
-edition = "2021"
-publish = false
-license = "Apache-2.0"
-
-[workspace]
-
-[lib]
-path = "src/openai.rs"
-crate-type = ["cdylib"]
-
-[dependencies]
-zed_extension_api = { path = "../../crates/extension_api" }
-serde = { version = "1.0", features = ["derive"] }
-serde_json = "1.0"

extensions/openai/extension.toml 🔗

@@ -1,13 +0,0 @@
-id = "openai"
-name = "OpenAI"
-description = "OpenAI GPT LLM provider for Zed."
-version = "0.1.0"
-schema_version = 1
-authors = ["Zed Team"]
-repository = "https://github.com/zed-industries/zed"
-
-[language_model_providers.openai]
-name = "OpenAI"
-
-[language_model_providers.openai.auth]
-env_var = "OPENAI_API_KEY"

extensions/openai/src/openai.rs 🔗

@@ -1,727 +0,0 @@
-use std::collections::HashMap;
-use std::sync::Mutex;
-
-use serde::{Deserialize, Serialize};
-use zed_extension_api::http_client::{HttpMethod, HttpRequest, HttpResponseStream, RedirectPolicy};
-use zed_extension_api::{self as zed, *};
-
-struct OpenAiProvider {
-    streams: Mutex<HashMap<String, StreamState>>,
-    next_stream_id: Mutex<u64>,
-}
-
-struct StreamState {
-    response_stream: Option<HttpResponseStream>,
-    buffer: String,
-    started: bool,
-    tool_calls: HashMap<usize, AccumulatedToolCall>,
-    tool_calls_emitted: bool,
-}
-
-#[derive(Clone, Default)]
-struct AccumulatedToolCall {
-    id: String,
-    name: String,
-    arguments: String,
-}
-
-struct ModelDefinition {
-    real_id: &'static str,
-    display_name: &'static str,
-    max_tokens: u64,
-    max_output_tokens: Option<u64>,
-    supports_images: bool,
-    is_default: bool,
-    is_default_fast: bool,
-}
-
-const MODELS: &[ModelDefinition] = &[
-    ModelDefinition {
-        real_id: "gpt-4o",
-        display_name: "GPT-4o",
-        max_tokens: 128_000,
-        max_output_tokens: Some(16_384),
-        supports_images: true,
-        is_default: true,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        real_id: "gpt-4o-mini",
-        display_name: "GPT-4o-mini",
-        max_tokens: 128_000,
-        max_output_tokens: Some(16_384),
-        supports_images: true,
-        is_default: false,
-        is_default_fast: true,
-    },
-    ModelDefinition {
-        real_id: "gpt-4.1",
-        display_name: "GPT-4.1",
-        max_tokens: 1_047_576,
-        max_output_tokens: Some(32_768),
-        supports_images: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        real_id: "gpt-4.1-mini",
-        display_name: "GPT-4.1-mini",
-        max_tokens: 1_047_576,
-        max_output_tokens: Some(32_768),
-        supports_images: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        real_id: "gpt-4.1-nano",
-        display_name: "GPT-4.1-nano",
-        max_tokens: 1_047_576,
-        max_output_tokens: Some(32_768),
-        supports_images: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        real_id: "gpt-5",
-        display_name: "GPT-5",
-        max_tokens: 272_000,
-        max_output_tokens: Some(32_768),
-        supports_images: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        real_id: "gpt-5-mini",
-        display_name: "GPT-5-mini",
-        max_tokens: 272_000,
-        max_output_tokens: Some(32_768),
-        supports_images: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        real_id: "o1",
-        display_name: "o1",
-        max_tokens: 200_000,
-        max_output_tokens: Some(100_000),
-        supports_images: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        real_id: "o3",
-        display_name: "o3",
-        max_tokens: 200_000,
-        max_output_tokens: Some(100_000),
-        supports_images: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        real_id: "o3-mini",
-        display_name: "o3-mini",
-        max_tokens: 200_000,
-        max_output_tokens: Some(100_000),
-        supports_images: false,
-        is_default: false,
-        is_default_fast: false,
-    },
-    ModelDefinition {
-        real_id: "o4-mini",
-        display_name: "o4-mini",
-        max_tokens: 200_000,
-        max_output_tokens: Some(100_000),
-        supports_images: true,
-        is_default: false,
-        is_default_fast: false,
-    },
-];
-
-fn get_real_model_id(display_name: &str) -> Option<&'static str> {
-    MODELS
-        .iter()
-        .find(|m| m.display_name == display_name)
-        .map(|m| m.real_id)
-}
-
-#[derive(Serialize)]
-struct OpenAiRequest {
-    model: String,
-    messages: Vec<OpenAiMessage>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    tools: Option<Vec<OpenAiTool>>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    tool_choice: Option<String>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    temperature: Option<f32>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    max_tokens: Option<u64>,
-    #[serde(skip_serializing_if = "Vec::is_empty")]
-    stop: Vec<String>,
-    stream: bool,
-    stream_options: Option<StreamOptions>,
-}
-
-#[derive(Serialize)]
-struct StreamOptions {
-    include_usage: bool,
-}
-
-#[derive(Serialize)]
-#[serde(tag = "role")]
-enum OpenAiMessage {
-    #[serde(rename = "system")]
-    System { content: String },
-    #[serde(rename = "user")]
-    User { content: Vec<OpenAiContentPart> },
-    #[serde(rename = "assistant")]
-    Assistant {
-        #[serde(skip_serializing_if = "Option::is_none")]
-        content: Option<String>,
-        #[serde(skip_serializing_if = "Option::is_none")]
-        tool_calls: Option<Vec<OpenAiToolCall>>,
-    },
-    #[serde(rename = "tool")]
-    Tool {
-        tool_call_id: String,
-        content: String,
-    },
-}
-
-#[derive(Serialize)]
-#[serde(tag = "type")]
-enum OpenAiContentPart {
-    #[serde(rename = "text")]
-    Text { text: String },
-    #[serde(rename = "image_url")]
-    ImageUrl { image_url: ImageUrl },
-}
-
-#[derive(Serialize)]
-struct ImageUrl {
-    url: String,
-}
-
-#[derive(Serialize, Deserialize, Clone)]
-struct OpenAiToolCall {
-    id: String,
-    #[serde(rename = "type")]
-    call_type: String,
-    function: OpenAiFunctionCall,
-}
-
-#[derive(Serialize, Deserialize, Clone)]
-struct OpenAiFunctionCall {
-    name: String,
-    arguments: String,
-}
-
-#[derive(Serialize)]
-struct OpenAiTool {
-    #[serde(rename = "type")]
-    tool_type: String,
-    function: OpenAiFunctionDef,
-}
-
-#[derive(Serialize)]
-struct OpenAiFunctionDef {
-    name: String,
-    description: String,
-    parameters: serde_json::Value,
-}
-
-#[derive(Deserialize, Debug)]
-struct OpenAiStreamEvent {
-    choices: Vec<OpenAiChoice>,
-    #[serde(default)]
-    usage: Option<OpenAiUsage>,
-}
-
-#[derive(Deserialize, Debug)]
-struct OpenAiChoice {
-    delta: OpenAiDelta,
-    finish_reason: Option<String>,
-}
-
-#[derive(Deserialize, Debug, Default)]
-struct OpenAiDelta {
-    #[serde(default)]
-    content: Option<String>,
-    #[serde(default)]
-    tool_calls: Option<Vec<OpenAiToolCallDelta>>,
-}
-
-#[derive(Deserialize, Debug)]
-struct OpenAiToolCallDelta {
-    index: usize,
-    #[serde(default)]
-    id: Option<String>,
-    #[serde(default)]
-    function: Option<OpenAiFunctionDelta>,
-}
-
-#[derive(Deserialize, Debug)]
-struct OpenAiFunctionDelta {
-    #[serde(default)]
-    name: Option<String>,
-    #[serde(default)]
-    arguments: Option<String>,
-}
-
-#[derive(Deserialize, Debug)]
-struct OpenAiUsage {
-    prompt_tokens: u64,
-    completion_tokens: u64,
-}
-
-#[allow(dead_code)]
-#[derive(Deserialize, Debug)]
-struct OpenAiError {
-    error: OpenAiErrorDetail,
-}
-
-#[allow(dead_code)]
-#[derive(Deserialize, Debug)]
-struct OpenAiErrorDetail {
-    message: String,
-}
-
-fn convert_request(
-    model_id: &str,
-    request: &LlmCompletionRequest,
-) -> Result<OpenAiRequest, String> {
-    let real_model_id =
-        get_real_model_id(model_id).ok_or_else(|| format!("Unknown model: {}", model_id))?;
-
-    let mut messages = Vec::new();
-
-    for msg in &request.messages {
-        match msg.role {
-            LlmMessageRole::System => {
-                let text: String = msg
-                    .content
-                    .iter()
-                    .filter_map(|c| match c {
-                        LlmMessageContent::Text(t) => Some(t.as_str()),
-                        _ => None,
-                    })
-                    .collect::<Vec<_>>()
-                    .join("\n");
-                if !text.is_empty() {
-                    messages.push(OpenAiMessage::System { content: text });
-                }
-            }
-            LlmMessageRole::User => {
-                let parts: Vec<OpenAiContentPart> = msg
-                    .content
-                    .iter()
-                    .filter_map(|c| match c {
-                        LlmMessageContent::Text(t) => {
-                            Some(OpenAiContentPart::Text { text: t.clone() })
-                        }
-                        LlmMessageContent::Image(img) => Some(OpenAiContentPart::ImageUrl {
-                            image_url: ImageUrl {
-                                url: format!("data:image/png;base64,{}", img.source),
-                            },
-                        }),
-                        LlmMessageContent::ToolResult(_) => None,
-                        _ => None,
-                    })
-                    .collect();
-
-                for content in &msg.content {
-                    if let LlmMessageContent::ToolResult(result) = content {
-                        let content_text = match &result.content {
-                            LlmToolResultContent::Text(t) => t.clone(),
-                            LlmToolResultContent::Image(_) => "[Image]".to_string(),
-                        };
-                        messages.push(OpenAiMessage::Tool {
-                            tool_call_id: result.tool_use_id.clone(),
-                            content: content_text,
-                        });
-                    }
-                }
-
-                if !parts.is_empty() {
-                    messages.push(OpenAiMessage::User { content: parts });
-                }
-            }
-            LlmMessageRole::Assistant => {
-                let mut content_text: Option<String> = None;
-                let mut tool_calls: Vec<OpenAiToolCall> = Vec::new();
-
-                for c in &msg.content {
-                    match c {
-                        LlmMessageContent::Text(t) => {
-                            content_text = Some(t.clone());
-                        }
-                        LlmMessageContent::ToolUse(tool_use) => {
-                            tool_calls.push(OpenAiToolCall {
-                                id: tool_use.id.clone(),
-                                call_type: "function".to_string(),
-                                function: OpenAiFunctionCall {
-                                    name: tool_use.name.clone(),
-                                    arguments: tool_use.input.clone(),
-                                },
-                            });
-                        }
-                        _ => {}
-                    }
-                }
-
-                messages.push(OpenAiMessage::Assistant {
-                    content: content_text,
-                    tool_calls: if tool_calls.is_empty() {
-                        None
-                    } else {
-                        Some(tool_calls)
-                    },
-                });
-            }
-        }
-    }
-
-    let tools: Option<Vec<OpenAiTool>> = if request.tools.is_empty() {
-        None
-    } else {
-        Some(
-            request
-                .tools
-                .iter()
-                .map(|t| OpenAiTool {
-                    tool_type: "function".to_string(),
-                    function: OpenAiFunctionDef {
-                        name: t.name.clone(),
-                        description: t.description.clone(),
-                        parameters: serde_json::from_str(&t.input_schema)
-                            .unwrap_or(serde_json::Value::Object(Default::default())),
-                    },
-                })
-                .collect(),
-        )
-    };
-
-    let tool_choice = request.tool_choice.as_ref().map(|tc| match tc {
-        LlmToolChoice::Auto => "auto".to_string(),
-        LlmToolChoice::Any => "required".to_string(),
-        LlmToolChoice::None => "none".to_string(),
-    });
-
-    Ok(OpenAiRequest {
-        model: real_model_id.to_string(),
-        messages,
-        tools,
-        tool_choice,
-        temperature: request.temperature,
-        max_tokens: request.max_tokens,
-        stop: request.stop_sequences.clone(),
-        stream: true,
-        stream_options: Some(StreamOptions {
-            include_usage: true,
-        }),
-    })
-}
-
-fn parse_sse_line(line: &str) -> Option<OpenAiStreamEvent> {
-    if let Some(data) = line.strip_prefix("data: ") {
-        if data == "[DONE]" {
-            return None;
-        }
-        serde_json::from_str(data).ok()
-    } else {
-        None
-    }
-}
-
-impl zed::Extension for OpenAiProvider {
-    fn new() -> Self {
-        Self {
-            streams: Mutex::new(HashMap::new()),
-            next_stream_id: Mutex::new(0),
-        }
-    }
-
-    fn llm_providers(&self) -> Vec<LlmProviderInfo> {
-        vec![LlmProviderInfo {
-            id: "openai".into(),
-            name: "OpenAI".into(),
-            icon: Some("icons/openai.svg".into()),
-        }]
-    }
-
-    fn llm_provider_models(&self, _provider_id: &str) -> Result<Vec<LlmModelInfo>, String> {
-        Ok(MODELS
-            .iter()
-            .map(|m| LlmModelInfo {
-                id: m.display_name.to_string(),
-                name: m.display_name.to_string(),
-                max_token_count: m.max_tokens,
-                max_output_tokens: m.max_output_tokens,
-                capabilities: LlmModelCapabilities {
-                    supports_images: m.supports_images,
-                    supports_tools: true,
-                    supports_tool_choice_auto: true,
-                    supports_tool_choice_any: true,
-                    supports_tool_choice_none: true,
-                    supports_thinking: false,
-                    tool_input_format: LlmToolInputFormat::JsonSchema,
-                },
-                is_default: m.is_default,
-                is_default_fast: m.is_default_fast,
-            })
-            .collect())
-    }
-
-    fn llm_provider_is_authenticated(&self, _provider_id: &str) -> bool {
-        llm_get_credential("openai").is_some()
-    }
-
-    fn llm_provider_settings_markdown(&self, _provider_id: &str) -> Option<String> {
-        Some(
-            r#"# OpenAI Setup
-
-Welcome to **OpenAI**! This extension provides access to OpenAI GPT models.
-
-## Configuration
-
-Enter your OpenAI API key below. You can find your API key at [platform.openai.com/api-keys](https://platform.openai.com/api-keys).
-
-## Available Models
-
-| Display Name | Real Model | Context | Output |
-|--------------|------------|---------|--------|
-| GPT-4o | gpt-4o | 128K | 16K |
-| GPT-4o-mini | gpt-4o-mini | 128K | 16K |
-| GPT-4.1 | gpt-4.1 | 1M | 32K |
-| GPT-4.1-mini | gpt-4.1-mini | 1M | 32K |
-| GPT-5 | gpt-5 | 272K | 32K |
-| GPT-5-mini | gpt-5-mini | 272K | 32K |
-| o1 | o1 | 200K | 100K |
-| o3 | o3 | 200K | 100K |
-| o3-mini | o3-mini | 200K | 100K |
-
-## Features
-
-- ✅ Full streaming support
-- ✅ Tool/function calling
-- ✅ Vision (image inputs)
-- ✅ All OpenAI models
-
-## Pricing
-
-Uses your OpenAI API credits. See [OpenAI pricing](https://openai.com/pricing) for details.
-"#
-            .to_string(),
-        )
-    }
-
-    fn llm_provider_authenticate(&mut self, _provider_id: &str) -> Result<(), String> {
-        let provided = llm_request_credential(
-            "openai",
-            LlmCredentialType::ApiKey,
-            "OpenAI API Key",
-            "sk-...",
-        )?;
-        if provided {
-            Ok(())
-        } else {
-            Err("Authentication cancelled".to_string())
-        }
-    }
-
-    fn llm_provider_reset_credentials(&mut self, _provider_id: &str) -> Result<(), String> {
-        llm_delete_credential("openai")
-    }
-
-    fn llm_stream_completion_start(
-        &mut self,
-        _provider_id: &str,
-        model_id: &str,
-        request: &LlmCompletionRequest,
-    ) -> Result<String, String> {
-        let api_key = llm_get_credential("openai").ok_or_else(|| {
-            "No API key configured. Please add your OpenAI API key in settings.".to_string()
-        })?;
-
-        let openai_request = convert_request(model_id, request)?;
-
-        let body = serde_json::to_vec(&openai_request)
-            .map_err(|e| format!("Failed to serialize request: {}", e))?;
-
-        let http_request = HttpRequest {
-            method: HttpMethod::Post,
-            url: "https://api.openai.com/v1/chat/completions".to_string(),
-            headers: vec![
-                ("Content-Type".to_string(), "application/json".to_string()),
-                ("Authorization".to_string(), format!("Bearer {}", api_key)),
-            ],
-            body: Some(body),
-            redirect_policy: RedirectPolicy::FollowAll,
-        };
-
-        let response_stream = http_request
-            .fetch_stream()
-            .map_err(|e| format!("HTTP request failed: {}", e))?;
-
-        let stream_id = {
-            let mut id_counter = self.next_stream_id.lock().unwrap();
-            let id = format!("openai-stream-{}", *id_counter);
-            *id_counter += 1;
-            id
-        };
-
-        self.streams.lock().unwrap().insert(
-            stream_id.clone(),
-            StreamState {
-                response_stream: Some(response_stream),
-                buffer: String::new(),
-                started: false,
-                tool_calls: HashMap::new(),
-                tool_calls_emitted: false,
-            },
-        );
-
-        Ok(stream_id)
-    }
-
-    fn llm_stream_completion_next(
-        &mut self,
-        stream_id: &str,
-    ) -> Result<Option<LlmCompletionEvent>, String> {
-        let mut streams = self.streams.lock().unwrap();
-        let state = streams
-            .get_mut(stream_id)
-            .ok_or_else(|| format!("Unknown stream: {}", stream_id))?;
-
-        if !state.started {
-            state.started = true;
-            return Ok(Some(LlmCompletionEvent::Started));
-        }
-
-        let response_stream = state
-            .response_stream
-            .as_mut()
-            .ok_or_else(|| "Stream already closed".to_string())?;
-
-        loop {
-            if let Some(newline_pos) = state.buffer.find('\n') {
-                let line = state.buffer[..newline_pos].trim().to_string();
-                state.buffer = state.buffer[newline_pos + 1..].to_string();
-
-                if line.is_empty() {
-                    continue;
-                }
-
-                if let Some(event) = parse_sse_line(&line) {
-                    if let Some(choice) = event.choices.first() {
-                        if let Some(tool_calls) = &choice.delta.tool_calls {
-                            for tc in tool_calls {
-                                let entry = state.tool_calls.entry(tc.index).or_default();
-
-                                if let Some(id) = &tc.id {
-                                    entry.id = id.clone();
-                                }
-
-                                if let Some(func) = &tc.function {
-                                    if let Some(name) = &func.name {
-                                        entry.name = name.clone();
-                                    }
-                                    if let Some(args) = &func.arguments {
-                                        entry.arguments.push_str(args);
-                                    }
-                                }
-                            }
-                        }
-
-                        if let Some(reason) = &choice.finish_reason {
-                            if reason == "tool_calls" && !state.tool_calls_emitted {
-                                state.tool_calls_emitted = true;
-                                if let Some((&index, _)) = state.tool_calls.iter().next() {
-                                    if let Some(tool_call) = state.tool_calls.remove(&index) {
-                                        return Ok(Some(LlmCompletionEvent::ToolUse(LlmToolUse {
-                                            id: tool_call.id,
-                                            name: tool_call.name,
-                                            input: tool_call.arguments,
-                                            thought_signature: None,
-                                        })));
-                                    }
-                                }
-                            }
-
-                            let stop_reason = match reason.as_str() {
-                                "stop" => LlmStopReason::EndTurn,
-                                "length" => LlmStopReason::MaxTokens,
-                                "tool_calls" => LlmStopReason::ToolUse,
-                                "content_filter" => LlmStopReason::Refusal,
-                                _ => LlmStopReason::EndTurn,
-                            };
-
-                            if let Some(usage) = event.usage {
-                                return Ok(Some(LlmCompletionEvent::Usage(LlmTokenUsage {
-                                    input_tokens: usage.prompt_tokens,
-                                    output_tokens: usage.completion_tokens,
-                                    cache_creation_input_tokens: None,
-                                    cache_read_input_tokens: None,
-                                })));
-                            }
-
-                            return Ok(Some(LlmCompletionEvent::Stop(stop_reason)));
-                        }
-
-                        if let Some(content) = &choice.delta.content {
-                            if !content.is_empty() {
-                                return Ok(Some(LlmCompletionEvent::Text(content.clone())));
-                            }
-                        }
-                    }
-
-                    if event.choices.is_empty() {
-                        if let Some(usage) = event.usage {
-                            return Ok(Some(LlmCompletionEvent::Usage(LlmTokenUsage {
-                                input_tokens: usage.prompt_tokens,
-                                output_tokens: usage.completion_tokens,
-                                cache_creation_input_tokens: None,
-                                cache_read_input_tokens: None,
-                            })));
-                        }
-                    }
-                }
-
-                continue;
-            }
-
-            match response_stream.next_chunk() {
-                Ok(Some(chunk)) => {
-                    let text = String::from_utf8_lossy(&chunk);
-                    state.buffer.push_str(&text);
-                }
-                Ok(None) => {
-                    if !state.tool_calls.is_empty() && !state.tool_calls_emitted {
-                        state.tool_calls_emitted = true;
-                        let keys: Vec<usize> = state.tool_calls.keys().copied().collect();
-                        if let Some(&key) = keys.first() {
-                            if let Some(tool_call) = state.tool_calls.remove(&key) {
-                                return Ok(Some(LlmCompletionEvent::ToolUse(LlmToolUse {
-                                    id: tool_call.id,
-                                    name: tool_call.name,
-                                    input: tool_call.arguments,
-                                    thought_signature: None,
-                                })));
-                            }
-                        }
-                    }
-                    return Ok(None);
-                }
-                Err(e) => {
-                    return Err(format!("Stream error: {}", e));
-                }
-            }
-        }
-    }
-
-    fn llm_stream_completion_close(&mut self, stream_id: &str) {
-        self.streams.lock().unwrap().remove(stream_id);
-    }
-}
-
-zed::register_extension!(OpenAiProvider);