diff --git a/Cargo.lock b/Cargo.lock index 12090c7da99d5678e43c2ec00fc5e762622deffc..a6f92205fdf177f0e03db4e00307c38defb56ada 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7560,9 +7560,6 @@ name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -dependencies = [ - "unicode-segmentation", -] [[package]] name = "heck" @@ -15051,13 +15048,6 @@ version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" -[[package]] -name = "slash_commands_example" -version = "0.1.0" -dependencies = [ - "zed_extension_api 0.1.0", -] - [[package]] name = "slotmap" version = "1.0.7" @@ -18382,15 +18372,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-encoder" -version = "0.201.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9c7d2731df60006819b013f64ccc2019691deccf6e11a1804bc850cd6748f1a" -dependencies = [ - "leb128", -] - [[package]] name = "wasm-encoder" version = "0.221.3" @@ -18411,22 +18392,6 @@ dependencies = [ "wasmparser 0.227.1", ] -[[package]] -name = "wasm-metadata" -version = "0.201.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fd83062c17b9f4985d438603cde0a5e8c5c8198201a6937f778b607924c7da2" -dependencies = [ - "anyhow", - "indexmap", - "serde", - "serde_derive", - "serde_json", - "spdx", - "wasm-encoder 0.201.0", - "wasmparser 0.201.0", -] - [[package]] name = "wasm-metadata" version = "0.227.1" @@ -18459,17 +18424,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wasmparser" -version = "0.201.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84e5df6dba6c0d7fafc63a450f1738451ed7a0b52295d83e868218fa286bf708" -dependencies = [ - "bitflags 2.9.4", - "indexmap", - "semver", -] - [[package]] name = "wasmparser" version = "0.221.3" @@ -19864,25 +19818,14 @@ dependencies = [ "winapi", ] -[[package]] -name = "wit-bindgen" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "288f992ea30e6b5c531b52cdd5f3be81c148554b09ea416f058d16556ba92c27" -dependencies = [ - "bitflags 2.9.4", - "wit-bindgen-rt 0.22.0", - "wit-bindgen-rust-macro 0.22.0", -] - [[package]] name = "wit-bindgen" version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10fb6648689b3929d56bbc7eb1acf70c9a42a29eb5358c67c10f54dbd5d695de" dependencies = [ - "wit-bindgen-rt 0.41.0", - "wit-bindgen-rust-macro 0.41.0", + "wit-bindgen-rt", + "wit-bindgen-rust-macro", ] [[package]] @@ -19891,16 +19834,6 @@ version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" -[[package]] -name = "wit-bindgen-core" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e85e72719ffbccf279359ad071497e47eb0675fe22106dea4ed2d8a7fcb60ba4" -dependencies = [ - "anyhow", - "wit-parser 0.201.0", -] - [[package]] name = "wit-bindgen-core" version = "0.41.0" @@ -19912,12 +19845,6 @@ dependencies = [ "wit-parser 0.227.1", ] -[[package]] -name = "wit-bindgen-rt" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb8738270f32a2d6739973cbbb7c1b6dd8959ce515578a6e19165853272ee64" - [[package]] name = "wit-bindgen-rt" version = "0.41.0" @@ -19929,20 +19856,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "wit-bindgen-rust" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a39a15d1ae2077688213611209849cad40e9e5cccf6e61951a425850677ff3" -dependencies = [ - "anyhow", - "heck 0.4.1", - "indexmap", - "wasm-metadata 0.201.0", - "wit-bindgen-core 0.22.0", - "wit-component 0.201.0", -] - [[package]] name = "wit-bindgen-rust" version = "0.41.0" @@ -19954,23 +19867,9 @@ dependencies = [ "indexmap", "prettyplease", "syn 2.0.106", - "wasm-metadata 0.227.1", - "wit-bindgen-core 0.41.0", - "wit-component 0.227.1", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d376d3ae5850526dfd00d937faea0d81a06fa18f7ac1e26f386d760f241a8f4b" -dependencies = [ - "anyhow", - "proc-macro2", - "quote", - "syn 2.0.106", - "wit-bindgen-core 0.22.0", - "wit-bindgen-rust 0.22.0", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", ] [[package]] @@ -19984,27 +19883,8 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.106", - "wit-bindgen-core 0.41.0", - "wit-bindgen-rust 0.41.0", -] - -[[package]] -name = "wit-component" -version = "0.201.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "421c0c848a0660a8c22e2fd217929a0191f14476b68962afd2af89fd22e39825" -dependencies = [ - "anyhow", - "bitflags 2.9.4", - "indexmap", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder 0.201.0", - "wasm-metadata 0.201.0", - "wasmparser 0.201.0", - "wit-parser 0.201.0", + "wit-bindgen-core", + "wit-bindgen-rust", ] [[package]] @@ -20021,29 +19901,11 @@ dependencies = [ "serde_derive", "serde_json", "wasm-encoder 0.227.1", - "wasm-metadata 0.227.1", + "wasm-metadata", "wasmparser 0.227.1", "wit-parser 0.227.1", ] -[[package]] -name = "wit-parser" -version = "0.201.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196d3ecfc4b759a8573bf86a9b3f8996b304b3732e4c7de81655f875f6efdca6" -dependencies = [ - "anyhow", - "id-arena", - "indexmap", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser 0.201.0", -] - [[package]] name = "wit-parser" version = "0.221.3" @@ -20797,28 +20659,6 @@ dependencies = [ "gpui", ] -[[package]] -name = "zed_extension_api" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "594fd10dd0f2f853eb243e2425e7c95938cef49adb81d9602921d002c5e6d9d9" -dependencies = [ - "serde", - "serde_json", - "wit-bindgen 0.22.0", -] - -[[package]] -name = "zed_extension_api" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0729d50b4ca0a7e28e590bbe32e3ca0194d97ef654961451a424c661a366fca0" -dependencies = [ - "serde", - "serde_json", - "wit-bindgen 0.41.0", -] - [[package]] name = "zed_extension_api" version = "0.8.0" @@ -20828,34 +20668,6 @@ dependencies = [ "wit-bindgen 0.41.0", ] -[[package]] -name = "zed_glsl" -version = "0.1.0" -dependencies = [ - "zed_extension_api 0.1.0", -] - -[[package]] -name = "zed_html" -version = "0.3.0" -dependencies = [ - "zed_extension_api 0.7.0", -] - -[[package]] -name = "zed_proto" -version = "0.3.0" -dependencies = [ - "zed_extension_api 0.7.0", -] - -[[package]] -name = "zed_test_extension" -version = "0.1.0" -dependencies = [ - "zed_extension_api 0.8.0", -] - [[package]] name = "zeno" version = "0.3.3" diff --git a/Cargo.toml b/Cargo.toml index 903d17fc3378519d3e632f63c1a1a0e08e6513cb..76f52fa6b63047d0a490c15679195dab9c2736fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -208,16 +208,6 @@ members = [ "crates/ztracing", "crates/ztracing_macro", - # - # Extensions - # - - "extensions/glsl", - "extensions/html", - "extensions/proto", - "extensions/slash-commands-example", - "extensions/test-extension", - # # Tooling # diff --git a/assets/settings/default.json b/assets/settings/default.json index 39a5f26b6201ad4a0b765c2f19b387fd4fc9c855..2912d4ce4aa5c2ac11660b71d542572c7f03f3a7 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -1728,12 +1728,7 @@ // If you don't want any of these extensions, add this field to your settings // and change the value to `false`. "auto_install_extensions": { - "html": true, - "copilot-chat": true, - "anthropic": true, "google-ai": true, - "openai": true, - "openrouter": true, }, // The capabilities granted to extensions. // diff --git a/extensions/anthropic/Cargo.lock b/extensions/anthropic/Cargo.lock deleted file mode 100644 index 8bd00ffdbe329273c2731d58f6f6b56f9a6d529a..0000000000000000000000000000000000000000 --- a/extensions/anthropic/Cargo.lock +++ /dev/null @@ -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 = "anthropic" -version = "0.1.0" -dependencies = [ - "serde", - "serde_json", - "zed_extension_api", -] - -[[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 = "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", -] diff --git a/extensions/anthropic/Cargo.toml b/extensions/anthropic/Cargo.toml deleted file mode 100644 index 25dfe72b0e92ca10a2537be2d5f94173a2921acf..0000000000000000000000000000000000000000 --- a/extensions/anthropic/Cargo.toml +++ /dev/null @@ -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" diff --git a/extensions/anthropic/LICENSE-APACHE b/extensions/anthropic/LICENSE-APACHE deleted file mode 120000 index 1cd601d0a3affae83854be02a0afdec3b7a9ec4d..0000000000000000000000000000000000000000 --- a/extensions/anthropic/LICENSE-APACHE +++ /dev/null @@ -1 +0,0 @@ -../../LICENSE-APACHE \ No newline at end of file diff --git a/extensions/anthropic/extension.toml b/extensions/anthropic/extension.toml deleted file mode 100644 index 3e8b2b32e3f0c38ba7eafded3f9aa756288df693..0000000000000000000000000000000000000000 --- a/extensions/anthropic/extension.toml +++ /dev/null @@ -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_vars = ["ANTHROPIC_API_KEY"] diff --git a/extensions/anthropic/icons/anthropic.svg b/extensions/anthropic/icons/anthropic.svg deleted file mode 100644 index 75c1a7e0014e7dd7bbd573d44fe6854e0c0760a3..0000000000000000000000000000000000000000 --- a/extensions/anthropic/icons/anthropic.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/extensions/anthropic/src/anthropic.rs b/extensions/anthropic/src/anthropic.rs deleted file mode 100644 index 385f4ae44999bec785d50b23495186c71cd78e7b..0000000000000000000000000000000000000000 --- a/extensions/anthropic/src/anthropic.rs +++ /dev/null @@ -1,1129 +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>, - next_stream_id: Mutex, -} - -struct StreamState { - response_stream: Option, - buffer: String, - started: bool, - current_tool_use: Option, - stop_reason: Option, - pending_signature: Option, -} - -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, - beta_headers: Option<&'static str>, - supports_caching: bool, -} - -const MODELS: &[ModelDefinition] = &[ - // Claude Opus 4.5 - 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, - beta_headers: Some("fine-grained-tool-streaming-2025-05-14"), - supports_caching: true, - }, - 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, - beta_headers: Some("fine-grained-tool-streaming-2025-05-14"), - supports_caching: true, - }, - // Claude Opus 4.1 - ModelDefinition { - real_id: "claude-opus-4-1-20250805", - display_name: "Claude Opus 4.1", - max_tokens: 200_000, - max_output_tokens: 8_192, - supports_images: true, - supports_thinking: false, - is_default: false, - is_default_fast: false, - beta_headers: Some("fine-grained-tool-streaming-2025-05-14"), - supports_caching: true, - }, - ModelDefinition { - real_id: "claude-opus-4-1-20250805", - display_name: "Claude Opus 4.1 Thinking", - max_tokens: 200_000, - max_output_tokens: 8_192, - supports_images: true, - supports_thinking: true, - is_default: false, - is_default_fast: false, - beta_headers: Some("fine-grained-tool-streaming-2025-05-14"), - supports_caching: true, - }, - // Claude Opus 4 - ModelDefinition { - real_id: "claude-opus-4-20250514", - display_name: "Claude Opus 4", - max_tokens: 200_000, - max_output_tokens: 8_192, - supports_images: true, - supports_thinking: false, - is_default: false, - is_default_fast: false, - beta_headers: Some("fine-grained-tool-streaming-2025-05-14"), - supports_caching: true, - }, - ModelDefinition { - real_id: "claude-opus-4-20250514", - display_name: "Claude Opus 4 Thinking", - max_tokens: 200_000, - max_output_tokens: 8_192, - supports_images: true, - supports_thinking: true, - is_default: false, - is_default_fast: false, - beta_headers: Some("fine-grained-tool-streaming-2025-05-14"), - supports_caching: true, - }, - // Claude Sonnet 4.5 - 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, - beta_headers: Some("fine-grained-tool-streaming-2025-05-14"), - supports_caching: true, - }, - 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, - beta_headers: Some("fine-grained-tool-streaming-2025-05-14"), - supports_caching: true, - }, - // Claude Sonnet 4 - 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, - beta_headers: Some("fine-grained-tool-streaming-2025-05-14"), - supports_caching: true, - }, - 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, - beta_headers: Some("fine-grained-tool-streaming-2025-05-14"), - supports_caching: true, - }, - // Claude 3.7 Sonnet - ModelDefinition { - real_id: "claude-3-7-sonnet-latest", - display_name: "Claude 3.7 Sonnet", - max_tokens: 200_000, - max_output_tokens: 8_192, - supports_images: true, - supports_thinking: false, - is_default: false, - is_default_fast: false, - beta_headers: Some( - "token-efficient-tools-2025-02-19,fine-grained-tool-streaming-2025-05-14", - ), - supports_caching: true, - }, - ModelDefinition { - real_id: "claude-3-7-sonnet-latest", - display_name: "Claude 3.7 Sonnet Thinking", - max_tokens: 200_000, - max_output_tokens: 8_192, - supports_images: true, - supports_thinking: true, - is_default: false, - is_default_fast: false, - beta_headers: Some( - "token-efficient-tools-2025-02-19,fine-grained-tool-streaming-2025-05-14", - ), - supports_caching: true, - }, - // Claude 3.5 Sonnet - 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, - beta_headers: None, - supports_caching: true, - }, - // Claude Haiku 4.5 - 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, - beta_headers: None, - supports_caching: 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, - beta_headers: None, - supports_caching: true, - }, - // Claude 3.5 Haiku - 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, - beta_headers: None, - supports_caching: true, - }, - // Claude 3 Opus - ModelDefinition { - real_id: "claude-3-opus-latest", - display_name: "Claude 3 Opus", - max_tokens: 200_000, - max_output_tokens: 4_096, - supports_images: true, - supports_thinking: false, - is_default: false, - is_default_fast: false, - beta_headers: None, - supports_caching: false, - }, - // Claude 3 Sonnet - ModelDefinition { - real_id: "claude-3-sonnet-20240229", - display_name: "Claude 3 Sonnet", - max_tokens: 200_000, - max_output_tokens: 4_096, - supports_images: true, - supports_thinking: false, - is_default: false, - is_default_fast: false, - beta_headers: None, - supports_caching: false, - }, - // Claude 3 Haiku - ModelDefinition { - real_id: "claude-3-haiku-20240307", - display_name: "Claude 3 Haiku", - max_tokens: 200_000, - max_output_tokens: 4_096, - supports_images: true, - supports_thinking: false, - is_default: false, - is_default_fast: false, - beta_headers: None, - supports_caching: true, - }, -]; - -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, Clone)] -struct CacheControl { - #[serde(rename = "type")] - cache_type: &'static str, -} - -const EPHEMERAL_CACHE: CacheControl = CacheControl { - cache_type: "ephemeral", -}; - -#[derive(Serialize)] -struct AnthropicRequest { - model: String, - max_tokens: u64, - messages: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - system: Option, - #[serde(skip_serializing_if = "Option::is_none")] - thinking: Option, - #[serde(skip_serializing_if = "Vec::is_empty")] - tools: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - tool_choice: Option, - #[serde(skip_serializing_if = "Vec::is_empty")] - stop_sequences: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - temperature: Option, - stream: bool, -} - -#[derive(Serialize)] -#[serde(untagged)] -enum AnthropicSystemContent { - String(String), - Blocks(Vec), -} - -#[derive(Serialize)] -struct AnthropicSystemBlock { - #[serde(rename = "type")] - block_type: &'static str, - text: String, - #[serde(skip_serializing_if = "Option::is_none")] - cache_control: Option, -} - -#[derive(Serialize)] -struct AnthropicThinking { - #[serde(rename = "type")] - thinking_type: String, - #[serde(skip_serializing_if = "Option::is_none")] - budget_tokens: Option, -} - -#[derive(Serialize)] -struct AnthropicMessage { - role: String, - content: Vec, -} - -#[derive(Serialize, Clone)] -#[serde(tag = "type")] -enum AnthropicContent { - #[serde(rename = "text")] - Text { - text: String, - #[serde(skip_serializing_if = "Option::is_none")] - cache_control: Option, - }, - #[serde(rename = "thinking")] - Thinking { - thinking: String, - signature: String, - #[serde(skip_serializing_if = "Option::is_none")] - cache_control: Option, - }, - #[serde(rename = "redacted_thinking")] - RedactedThinking { data: String }, - #[serde(rename = "image")] - Image { - source: AnthropicImageSource, - #[serde(skip_serializing_if = "Option::is_none")] - cache_control: Option, - }, - #[serde(rename = "tool_use")] - ToolUse { - id: String, - name: String, - input: serde_json::Value, - #[serde(skip_serializing_if = "Option::is_none")] - cache_control: Option, - }, - #[serde(rename = "tool_result")] - ToolResult { - tool_use_id: String, - is_error: bool, - content: AnthropicToolResultContent, - #[serde(skip_serializing_if = "Option::is_none")] - cache_control: Option, - }, -} - -#[derive(Serialize, Clone)] -#[serde(untagged)] -enum AnthropicToolResultContent { - Plain(String), - Multipart(Vec), -} - -#[derive(Serialize, Clone)] -#[serde(tag = "type", rename_all = "lowercase")] -enum AnthropicToolResultPart { - Text { text: String }, - Image { source: AnthropicImageSource }, -} - -#[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, - #[serde(skip_serializing_if = "Option::is_none")] - cache_control: Option, -} - -#[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, -} - -#[derive(Deserialize, Debug, Default)] -struct AnthropicUsage { - #[serde(default)] - input_tokens: Option, - #[serde(default)] - output_tokens: Option, - #[serde(default)] - cache_creation_input_tokens: Option, - #[serde(default)] - cache_read_input_tokens: Option, -} - -#[derive(Deserialize, Debug)] -struct AnthropicApiError { - #[serde(rename = "type")] - #[allow(dead_code)] - error_type: String, - message: String, -} - -fn detect_media_type(data: &str) -> String { - if let Some(decoded) = base64_decode_first_bytes(data, 12) { - if decoded.starts_with(&[0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]) { - return "image/png".to_string(); - } - if decoded.starts_with(&[0xFF, 0xD8, 0xFF]) { - return "image/jpeg".to_string(); - } - if decoded.starts_with(&[0x47, 0x49, 0x46, 0x38]) { - return "image/gif".to_string(); - } - if decoded.len() >= 12 && &decoded[0..4] == b"RIFF" && &decoded[8..12] == b"WEBP" { - return "image/webp".to_string(); - } - } - "image/png".to_string() -} - -fn base64_decode_first_bytes(data: &str, num_bytes: usize) -> Option> { - let chars_needed = ((num_bytes + 2) / 3) * 4; - let prefix: String = data.chars().take(chars_needed).collect(); - - const BASE64_TABLE: &[u8; 64] = - b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - fn decode_char(c: char) -> Option { - if c == '=' { - return Some(0); - } - BASE64_TABLE - .iter() - .position(|&b| b == c as u8) - .map(|p| p as u8) - } - - let chars: Vec = prefix.chars().filter(|c| !c.is_whitespace()).collect(); - if chars.len() < 4 { - return None; - } - - let mut result = Vec::new(); - for chunk in chars.chunks(4) { - if chunk.len() < 4 { - break; - } - let a = decode_char(chunk[0])?; - let b = decode_char(chunk[1])?; - let c = decode_char(chunk[2])?; - let d = decode_char(chunk[3])?; - - result.push((a << 2) | (b >> 4)); - if chunk[2] != '=' { - result.push((b << 4) | (c >> 2)); - } - if chunk[3] != '=' { - result.push((c << 6) | d); - } - - if result.len() >= num_bytes { - break; - } - } - - Some(result) -} - -fn convert_request( - model_id: &str, - request: &LlmCompletionRequest, - enable_caching: bool, -) -> Result { - let model_def = - get_model_definition(model_id).ok_or_else(|| format!("Unknown model: {}", model_id))?; - - let mut messages: Vec = Vec::new(); - let mut system_message = String::new(); - let mut system_should_cache = false; - - 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); - } - } - if msg.cache { - system_should_cache = true; - } - } - LlmMessageRole::User => { - let mut contents: Vec = Vec::new(); - - for content in &msg.content { - match content { - LlmMessageContent::Text(text) => { - if !text.is_empty() { - contents.push(AnthropicContent::Text { - text: text.clone(), - cache_control: None, - }); - } - } - LlmMessageContent::Image(img) => { - let media_type = detect_media_type(&img.source); - contents.push(AnthropicContent::Image { - source: AnthropicImageSource { - source_type: "base64".to_string(), - media_type, - data: img.source.clone(), - }, - cache_control: None, - }); - } - LlmMessageContent::ToolResult(result) => { - let content = match &result.content { - LlmToolResultContent::Text(t) => { - AnthropicToolResultContent::Plain(t.clone()) - } - LlmToolResultContent::Image(img) => { - let media_type = detect_media_type(&img.source); - AnthropicToolResultContent::Multipart(vec![ - AnthropicToolResultPart::Image { - source: AnthropicImageSource { - source_type: "base64".to_string(), - media_type, - data: img.source.clone(), - }, - }, - ]) - } - }; - contents.push(AnthropicContent::ToolResult { - tool_use_id: result.tool_use_id.clone(), - is_error: result.is_error, - content, - cache_control: None, - }); - } - _ => {} - } - } - - if !contents.is_empty() { - if enable_caching && msg.cache { - if let Some(last) = contents.last_mut() { - set_cache_control(last); - } - } - messages.push(AnthropicMessage { - role: "user".to_string(), - content: contents, - }); - } - } - LlmMessageRole::Assistant => { - let mut contents: Vec = Vec::new(); - - for content in &msg.content { - match content { - LlmMessageContent::Text(text) => { - if !text.is_empty() { - contents.push(AnthropicContent::Text { - text: text.clone(), - cache_control: None, - }); - } - } - 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, - cache_control: None, - }); - } - LlmMessageContent::Thinking(thinking) => { - if !thinking.text.is_empty() { - contents.push(AnthropicContent::Thinking { - thinking: thinking.text.clone(), - signature: thinking.signature.clone().unwrap_or_default(), - cache_control: None, - }); - } - } - LlmMessageContent::RedactedThinking(data) => { - if !data.is_empty() { - contents.push(AnthropicContent::RedactedThinking { - data: data.clone(), - }); - } - } - _ => {} - } - } - - if !contents.is_empty() { - if enable_caching && msg.cache { - if let Some(last) = contents.last_mut() { - set_cache_control(last); - } - } - messages.push(AnthropicMessage { - role: "assistant".to_string(), - content: contents, - }); - } - } - } - } - - let mut tools: Vec = 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())), - cache_control: None, - }) - .collect(); - - if enable_caching && !tools.is_empty() { - if let Some(last_tool) = tools.last_mut() { - last_tool.cache_control = Some(EPHEMERAL_CACHE); - } - } - - 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 - }; - - let system = if system_message.is_empty() { - None - } else if enable_caching && system_should_cache { - Some(AnthropicSystemContent::Blocks(vec![AnthropicSystemBlock { - block_type: "text", - text: system_message, - cache_control: Some(EPHEMERAL_CACHE), - }])) - } else { - Some(AnthropicSystemContent::String(system_message)) - }; - - Ok(AnthropicRequest { - model: model_def.real_id.to_string(), - max_tokens: model_def.max_output_tokens, - messages, - system, - thinking, - tools, - tool_choice, - stop_sequences: request.stop_sequences.clone(), - temperature: request.temperature, - stream: true, - }) -} - -fn set_cache_control(content: &mut AnthropicContent) { - match content { - AnthropicContent::Text { cache_control, .. } => { - *cache_control = Some(EPHEMERAL_CACHE); - } - AnthropicContent::Thinking { cache_control, .. } => { - *cache_control = Some(EPHEMERAL_CACHE); - } - AnthropicContent::Image { cache_control, .. } => { - *cache_control = Some(EPHEMERAL_CACHE); - } - AnthropicContent::ToolUse { cache_control, .. } => { - *cache_control = Some(EPHEMERAL_CACHE); - } - AnthropicContent::ToolResult { cache_control, .. } => { - *cache_control = Some(EPHEMERAL_CACHE); - } - AnthropicContent::RedactedThinking { .. } => {} - } -} - -fn parse_sse_line(line: &str) -> Option { - 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 { - vec![LlmProviderInfo { - id: "anthropic".into(), - name: "Anthropic".into(), - icon: Some("icons/anthropic.svg".into()), - }] - } - - fn llm_provider_models(&self, _provider_id: &str) -> Result, 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 { - Some( - "[Create an API key](https://console.anthropic.com/settings/keys) to use Anthropic as your LLM provider.".to_string(), - ) - } - - fn llm_provider_reset_credentials(&mut self, _provider_id: &str) -> Result<(), String> { - llm_delete_credential("anthropic") - } - - fn llm_cache_configuration( - &self, - _provider_id: &str, - model_id: &str, - ) -> Option { - let model_def = get_model_definition(model_id)?; - if model_def.supports_caching { - Some(LlmCacheConfiguration { - max_cache_anchors: 4, - should_cache_tool_definitions: true, - min_total_token_count: 2048, - }) - } else { - None - } - } - - fn llm_stream_completion_start( - &mut self, - _provider_id: &str, - model_id: &str, - request: &LlmCompletionRequest, - ) -> Result { - 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 model_def = - get_model_definition(model_id).ok_or_else(|| format!("Unknown model: {}", model_id))?; - - let enable_caching = model_def.supports_caching; - let anthropic_request = convert_request(model_id, request, enable_caching)?; - - let body = serde_json::to_vec(&anthropic_request) - .map_err(|e| format!("Failed to serialize request: {}", e))?; - - let mut 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()), - ]; - - if let Some(beta) = model_def.beta_headers { - headers.push(("anthropic-beta".to_string(), beta.to_string())); - } - - let http_request = HttpRequest { - method: HttpMethod::Post, - url: "https://api.anthropic.com/v1/messages".to_string(), - headers, - 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, 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, - is_input_complete: true, - 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, - "refusal" => LlmStopReason::Refusal, - _ => 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); diff --git a/extensions/copilot-chat/Cargo.lock b/extensions/copilot-chat/Cargo.lock deleted file mode 100644 index 4b78fda143f8ec61e473fc96b312c56aa88d564a..0000000000000000000000000000000000000000 --- a/extensions/copilot-chat/Cargo.lock +++ /dev/null @@ -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", -] diff --git a/extensions/copilot-chat/Cargo.toml b/extensions/copilot-chat/Cargo.toml deleted file mode 100644 index 189c1db9fc37b9aa8357e25b91468b57c7312f7a..0000000000000000000000000000000000000000 --- a/extensions/copilot-chat/Cargo.toml +++ /dev/null @@ -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" diff --git a/extensions/copilot-chat/LICENSE-APACHE b/extensions/copilot-chat/LICENSE-APACHE deleted file mode 120000 index 1cd601d0a3affae83854be02a0afdec3b7a9ec4d..0000000000000000000000000000000000000000 --- a/extensions/copilot-chat/LICENSE-APACHE +++ /dev/null @@ -1 +0,0 @@ -../../LICENSE-APACHE \ No newline at end of file diff --git a/extensions/copilot-chat/extension.toml b/extensions/copilot-chat/extension.toml deleted file mode 100644 index 66d27aeb9240be87e28b61dfda15bd7706e8464f..0000000000000000000000000000000000000000 --- a/extensions/copilot-chat/extension.toml +++ /dev/null @@ -1,15 +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" -icon = "icons/copilot.svg" - -[language_model_providers.copilot-chat.auth.oauth] -sign_in_button_label = "Sign in to use GitHub Copilot" -sign_in_button_icon = "github" \ No newline at end of file diff --git a/extensions/copilot-chat/icons/copilot.svg b/extensions/copilot-chat/icons/copilot.svg deleted file mode 100644 index 2584cd631006c10ea9535408657fd881f0748249..0000000000000000000000000000000000000000 --- a/extensions/copilot-chat/icons/copilot.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/extensions/copilot-chat/src/copilot_chat.rs b/extensions/copilot-chat/src/copilot_chat.rs deleted file mode 100644 index d286b2f776318b81572a41b724d646dcc21d0230..0000000000000000000000000000000000000000 --- a/extensions/copilot-chat/src/copilot_chat.rs +++ /dev/null @@ -1,975 +0,0 @@ -use std::collections::HashMap; -use std::sync::Mutex; -use std::thread; -use std::time::Duration; - -use serde::{Deserialize, Serialize}; -use zed_extension_api::http_client::{HttpMethod, HttpRequest, HttpResponseStream, RedirectPolicy}; -use zed_extension_api::{self as zed, *}; - -const GITHUB_DEVICE_CODE_URL: &str = "https://github.com/login/device/code"; -const GITHUB_ACCESS_TOKEN_URL: &str = "https://github.com/login/oauth/access_token"; -const GITHUB_COPILOT_TOKEN_URL: &str = "https://api.github.com/copilot_internal/v2/token"; -const GITHUB_COPILOT_CLIENT_ID: &str = "Iv1.b507a08c87ecfe98"; - -struct DeviceFlowState { - device_code: String, - interval: u64, - expires_in: u64, -} - -#[derive(Clone)] -struct ApiToken { - api_key: String, - api_endpoint: String, -} - -#[derive(Clone, Deserialize)] -struct CopilotModel { - id: String, - name: String, - #[serde(default)] - is_chat_default: bool, - #[serde(default)] - is_chat_fallback: bool, - #[serde(default)] - model_picker_enabled: bool, - #[serde(default)] - capabilities: ModelCapabilities, - #[serde(default)] - policy: Option, -} - -#[derive(Clone, Default, Deserialize)] -struct ModelCapabilities { - #[serde(default)] - family: String, - #[serde(default)] - limits: ModelLimits, - #[serde(default)] - supports: ModelSupportedFeatures, - #[serde(rename = "type", default)] - model_type: String, -} - -#[derive(Clone, Default, Deserialize)] -struct ModelLimits { - #[serde(default)] - max_context_window_tokens: u64, - #[serde(default)] - max_output_tokens: u64, -} - -#[derive(Clone, Default, Deserialize)] -struct ModelSupportedFeatures { - #[serde(default)] - streaming: bool, - #[serde(default)] - tool_calls: bool, - #[serde(default)] - vision: bool, -} - -#[derive(Clone, Deserialize)] -struct ModelPolicy { - state: String, -} - -struct CopilotChatProvider { - streams: Mutex>, - next_stream_id: Mutex, - device_flow_state: Mutex>, - api_token: Mutex>, - cached_models: Mutex>>, -} - -struct StreamState { - response_stream: Option, - buffer: String, - started: bool, - tool_calls: HashMap, - tool_calls_emitted: bool, -} - -#[derive(Clone, Default)] -struct AccumulatedToolCall { - id: String, - name: String, - arguments: String, -} - -#[derive(Serialize)] -struct OpenAiRequest { - model: String, - messages: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - max_tokens: Option, - #[serde(skip_serializing_if = "Vec::is_empty")] - tools: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - tool_choice: Option, - #[serde(skip_serializing_if = "Vec::is_empty")] - stop: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - temperature: Option, - stream: bool, - #[serde(skip_serializing_if = "Option::is_none")] - stream_options: Option, -} - -#[derive(Serialize)] -struct StreamOptions { - include_usage: bool, -} - -#[derive(Serialize)] -struct OpenAiMessage { - role: String, - #[serde(skip_serializing_if = "Option::is_none")] - content: Option, - #[serde(skip_serializing_if = "Option::is_none")] - tool_calls: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - tool_call_id: Option, -} - -#[derive(Serialize, Clone)] -#[serde(untagged)] -enum OpenAiContent { - Text(String), - Parts(Vec), -} - -#[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, - #[serde(default)] - usage: Option, -} - -#[derive(Deserialize, Debug)] -struct OpenAiStreamChoice { - delta: OpenAiDelta, - finish_reason: Option, -} - -#[derive(Deserialize, Debug, Default)] -struct OpenAiDelta { - #[serde(default)] - content: Option, - #[serde(default)] - tool_calls: Option>, -} - -#[derive(Deserialize, Debug)] -struct OpenAiToolCallDelta { - index: usize, - #[serde(default)] - id: Option, - #[serde(default)] - function: Option, -} - -#[derive(Deserialize, Debug, Default)] -struct OpenAiFunctionDelta { - #[serde(default)] - name: Option, - #[serde(default)] - arguments: Option, -} - -#[derive(Deserialize, Debug)] -struct OpenAiUsage { - prompt_tokens: u64, - completion_tokens: u64, -} - -fn convert_request( - model_id: &str, - request: &LlmCompletionRequest, -) -> Result { - let mut messages: Vec = 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 = Vec::new(); - let mut tool_result_messages: Vec = 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 = 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 = 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 max_tokens = request.max_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 { - 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), - device_flow_state: Mutex::new(None), - api_token: Mutex::new(None), - cached_models: Mutex::new(None), - } - } - - fn llm_providers(&self) -> Vec { - 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, String> { - // Try to get models from cache first - if let Some(models) = self.cached_models.lock().unwrap().as_ref() { - return Ok(convert_models_to_llm_info(models)); - } - - // Need to fetch models - requires authentication - let oauth_token = match llm_get_credential("copilot-chat") { - Some(token) => token, - None => return Ok(Vec::new()), // Not authenticated, return empty - }; - - // Get API token - let api_token = self.get_api_token(&oauth_token)?; - - // Fetch models from API - let models = self.fetch_models(&api_token)?; - - // Cache the models - *self.cached_models.lock().unwrap() = Some(models.clone()); - - Ok(convert_models_to_llm_info(&models)) - } - - 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 { - Some( - "To use Copilot Chat, sign in with your GitHub account. This requires an active [GitHub Copilot subscription](https://github.com/features/copilot).".to_string(), - ) - } - - fn llm_provider_start_device_flow_sign_in( - &mut self, - _provider_id: &str, - ) -> Result { - // Step 1: Request device and user verification codes - let device_code_response = llm_oauth_send_http_request(&HttpRequest { - method: HttpMethod::Post, - url: GITHUB_DEVICE_CODE_URL.to_string(), - headers: vec![ - ("Accept".to_string(), "application/json".to_string()), - ( - "Content-Type".to_string(), - "application/x-www-form-urlencoded".to_string(), - ), - ], - body: Some( - format!("client_id={}&scope=read:user", GITHUB_COPILOT_CLIENT_ID).into_bytes(), - ), - redirect_policy: RedirectPolicy::NoFollow, - })?; - - if device_code_response.status != 200 { - return Err(format!( - "Failed to get device code: HTTP {}", - device_code_response.status - )); - } - - #[derive(Deserialize)] - struct DeviceCodeResponse { - device_code: String, - user_code: String, - verification_uri: String, - #[serde(default)] - verification_uri_complete: Option, - expires_in: u64, - interval: u64, - } - - let device_info: DeviceCodeResponse = serde_json::from_slice(&device_code_response.body) - .map_err(|e| format!("Failed to parse device code response: {}", e))?; - - // Store device flow state for polling - *self.device_flow_state.lock().unwrap() = Some(DeviceFlowState { - device_code: device_info.device_code, - interval: device_info.interval, - expires_in: device_info.expires_in, - }); - - // Step 2: Construct verification URL - // Use verification_uri_complete if available (has code pre-filled), otherwise construct URL - let verification_url = device_info.verification_uri_complete.unwrap_or_else(|| { - format!( - "{}?user_code={}", - device_info.verification_uri, &device_info.user_code - ) - }); - - // Return prompt info for the host to display in the modal - Ok(LlmDeviceFlowPromptInfo { - user_code: device_info.user_code, - verification_url, - headline: "Use GitHub Copilot in Zed.".to_string(), - description: "Using Copilot requires an active subscription on GitHub.".to_string(), - connect_button_label: "Connect to GitHub".to_string(), - success_headline: "Copilot Enabled!".to_string(), - success_message: - "You can update your settings or sign out from the Copilot menu in the status bar." - .to_string(), - }) - } - - fn llm_provider_poll_device_flow_sign_in(&mut self, _provider_id: &str) -> Result<(), String> { - let state = self - .device_flow_state - .lock() - .unwrap() - .take() - .ok_or("No device flow in progress")?; - - let poll_interval = Duration::from_secs(state.interval.max(5)); - let max_attempts = (state.expires_in / state.interval.max(5)) as usize; - - for _ in 0..max_attempts { - thread::sleep(poll_interval); - - let token_response = llm_oauth_send_http_request(&HttpRequest { - method: HttpMethod::Post, - url: GITHUB_ACCESS_TOKEN_URL.to_string(), - headers: vec![ - ("Accept".to_string(), "application/json".to_string()), - ( - "Content-Type".to_string(), - "application/x-www-form-urlencoded".to_string(), - ), - ], - body: Some( - format!( - "client_id={}&device_code={}&grant_type=urn:ietf:params:oauth:grant-type:device_code", - GITHUB_COPILOT_CLIENT_ID, state.device_code - ) - .into_bytes(), - ), - redirect_policy: RedirectPolicy::NoFollow, - })?; - - #[derive(Deserialize)] - struct TokenResponse { - access_token: Option, - error: Option, - error_description: Option, - } - - let token_json: TokenResponse = serde_json::from_slice(&token_response.body) - .map_err(|e| format!("Failed to parse token response: {}", e))?; - - if let Some(access_token) = token_json.access_token { - llm_store_credential("copilot-chat", &access_token)?; - return Ok(()); - } - - if let Some(error) = &token_json.error { - match error.as_str() { - "authorization_pending" => { - // User hasn't authorized yet, keep polling - continue; - } - "slow_down" => { - // Need to slow down polling - thread::sleep(Duration::from_secs(5)); - continue; - } - "expired_token" => { - return Err("Device code expired. Please try again.".to_string()); - } - "access_denied" => { - return Err("Authorization was denied.".to_string()); - } - _ => { - let description = token_json.error_description.unwrap_or_default(); - return Err(format!("OAuth error: {} - {}", error, description)); - } - } - } - } - - Err("Authorization timed out. Please try again.".to_string()) - } - - fn llm_provider_reset_credentials(&mut self, _provider_id: &str) -> Result<(), String> { - // Clear cached API token and models - *self.api_token.lock().unwrap() = None; - *self.cached_models.lock().unwrap() = None; - llm_delete_credential("copilot-chat") - } - - fn llm_stream_completion_start( - &mut self, - _provider_id: &str, - model_id: &str, - request: &LlmCompletionRequest, - ) -> Result { - let oauth_token = llm_get_credential("copilot-chat").ok_or_else(|| { - "No token configured. Please add your GitHub Copilot token in settings.".to_string() - })?; - - // Get or refresh API token - let api_token = self.get_api_token(&oauth_token)?; - - 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 completions_url = format!("{}/chat/completions", api_token.api_endpoint); - - let http_request = HttpRequest { - method: HttpMethod::Post, - url: completions_url, - headers: vec![ - ("Content-Type".to_string(), "application/json".to_string()), - ( - "Authorization".to_string(), - format!("Bearer {}", api_token.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, 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, - is_input_complete: true, - 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); - } -} - -impl CopilotChatProvider { - fn get_api_token(&self, oauth_token: &str) -> Result { - // Check if we have a cached token - if let Some(token) = self.api_token.lock().unwrap().clone() { - return Ok(token); - } - - // Request a new API token - let http_request = HttpRequest { - method: HttpMethod::Get, - url: GITHUB_COPILOT_TOKEN_URL.to_string(), - headers: vec![ - ( - "Authorization".to_string(), - format!("token {}", oauth_token), - ), - ("Accept".to_string(), "application/json".to_string()), - ], - body: None, - redirect_policy: RedirectPolicy::FollowAll, - }; - - let response = http_request - .fetch() - .map_err(|e| format!("Failed to request API token: {}", e))?; - - #[derive(Deserialize)] - struct ApiTokenResponse { - token: String, - endpoints: ApiEndpoints, - } - - #[derive(Deserialize)] - struct ApiEndpoints { - api: String, - } - - let token_response: ApiTokenResponse = - serde_json::from_slice(&response.body).map_err(|e| { - format!( - "Failed to parse API token response: {} - body: {}", - e, - String::from_utf8_lossy(&response.body) - ) - })?; - - let api_token = ApiToken { - api_key: token_response.token, - api_endpoint: token_response.endpoints.api, - }; - - // Cache the token - *self.api_token.lock().unwrap() = Some(api_token.clone()); - - Ok(api_token) - } - - fn fetch_models(&self, api_token: &ApiToken) -> Result, String> { - let models_url = format!("{}/models", api_token.api_endpoint); - - let http_request = HttpRequest { - method: HttpMethod::Get, - url: models_url, - headers: vec![ - ( - "Authorization".to_string(), - format!("Bearer {}", api_token.api_key), - ), - ("Content-Type".to_string(), "application/json".to_string()), - ( - "Copilot-Integration-Id".to_string(), - "vscode-chat".to_string(), - ), - ("Editor-Version".to_string(), "Zed/1.0.0".to_string()), - ("x-github-api-version".to_string(), "2025-05-01".to_string()), - ], - body: None, - redirect_policy: RedirectPolicy::FollowAll, - }; - - let response = http_request - .fetch() - .map_err(|e| format!("Failed to fetch models: {}", e))?; - - #[derive(Deserialize)] - struct ModelsResponse { - data: Vec, - } - - let models_response: ModelsResponse = - serde_json::from_slice(&response.body).map_err(|e| { - format!( - "Failed to parse models response: {} - body: {}", - e, - String::from_utf8_lossy(&response.body) - ) - })?; - - // Filter models like the built-in Copilot Chat does - let mut models: Vec = models_response - .data - .into_iter() - .filter(|model| { - model.model_picker_enabled - && model.capabilities.model_type == "chat" - && model - .policy - .as_ref() - .map(|p| p.state == "enabled") - .unwrap_or(true) - }) - .collect(); - - // Sort so default model is first - if let Some(pos) = models.iter().position(|m| m.is_chat_default) { - let default_model = models.remove(pos); - models.insert(0, default_model); - } - - Ok(models) - } -} - -fn convert_models_to_llm_info(models: &[CopilotModel]) -> Vec { - models - .iter() - .map(|m| { - let max_tokens = if m.capabilities.limits.max_context_window_tokens > 0 { - m.capabilities.limits.max_context_window_tokens - } else { - 128_000 // Default fallback - }; - let max_output = if m.capabilities.limits.max_output_tokens > 0 { - Some(m.capabilities.limits.max_output_tokens) - } else { - None - }; - - LlmModelInfo { - id: m.id.clone(), - name: m.name.clone(), - max_token_count: max_tokens, - max_output_tokens: max_output, - capabilities: LlmModelCapabilities { - supports_images: m.capabilities.supports.vision, - supports_tools: m.capabilities.supports.tool_calls, - supports_tool_choice_auto: m.capabilities.supports.tool_calls, - supports_tool_choice_any: m.capabilities.supports.tool_calls, - supports_tool_choice_none: m.capabilities.supports.tool_calls, - supports_thinking: false, - tool_input_format: LlmToolInputFormat::JsonSchema, - }, - is_default: m.is_chat_default, - is_default_fast: m.is_chat_fallback, - } - }) - .collect() -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_device_flow_request_body() { - let body = format!("client_id={}&scope=read:user", GITHUB_COPILOT_CLIENT_ID); - assert!(body.contains("client_id=Iv1.b507a08c87ecfe98")); - assert!(body.contains("scope=read:user")); - } - - #[test] - fn test_token_poll_request_body() { - let device_code = "test_device_code_123"; - let body = format!( - "client_id={}&device_code={}&grant_type=urn:ietf:params:oauth:grant-type:device_code", - GITHUB_COPILOT_CLIENT_ID, device_code - ); - assert!(body.contains("client_id=Iv1.b507a08c87ecfe98")); - assert!(body.contains("device_code=test_device_code_123")); - assert!(body.contains("grant_type=urn:ietf:params:oauth:grant-type:device_code")); - } -} - -zed::register_extension!(CopilotChatProvider); diff --git a/extensions/glsl/Cargo.toml b/extensions/glsl/Cargo.toml deleted file mode 100644 index 6dddeea35813c662e57ae5f5c16f89fe921fc223..0000000000000000000000000000000000000000 --- a/extensions/glsl/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "zed_glsl" -version = "0.1.0" -edition.workspace = true -publish.workspace = true -license = "Apache-2.0" - -[lints] -workspace = true - -[lib] -path = "src/glsl.rs" -crate-type = ["cdylib"] - -[dependencies] -zed_extension_api = "0.1.0" diff --git a/extensions/glsl/LICENSE-APACHE b/extensions/glsl/LICENSE-APACHE deleted file mode 120000 index 1cd601d0a3affae83854be02a0afdec3b7a9ec4d..0000000000000000000000000000000000000000 --- a/extensions/glsl/LICENSE-APACHE +++ /dev/null @@ -1 +0,0 @@ -../../LICENSE-APACHE \ No newline at end of file diff --git a/extensions/glsl/extension.toml b/extensions/glsl/extension.toml deleted file mode 100644 index 7cf9e218c80dd39b2f4f1eb3d0fe75d6de8615f1..0000000000000000000000000000000000000000 --- a/extensions/glsl/extension.toml +++ /dev/null @@ -1,15 +0,0 @@ -id = "glsl" -name = "GLSL" -description = "GLSL support." -version = "0.1.0" -schema_version = 1 -authors = ["Mikayla Maki "] -repository = "https://github.com/zed-industries/zed" - -[language_servers.glsl_analyzer] -name = "GLSL Analyzer LSP" -language = "GLSL" - -[grammars.glsl] -repository = "https://github.com/theHamsta/tree-sitter-glsl" -commit = "31064ce53385150f894a6c72d61b94076adf640a" diff --git a/extensions/glsl/languages/glsl/config.toml b/extensions/glsl/languages/glsl/config.toml deleted file mode 100644 index 0c71419c91e40f4b5fc65c10c882ac5c542a080c..0000000000000000000000000000000000000000 --- a/extensions/glsl/languages/glsl/config.toml +++ /dev/null @@ -1,20 +0,0 @@ -name = "GLSL" -grammar = "glsl" -path_suffixes = [ - # Traditional rasterization pipeline shaders - "vert", "frag", "tesc", "tese", "geom", - # Compute shaders - "comp", - # Ray tracing pipeline shaders - "rgen", "rint", "rahit", "rchit", "rmiss", "rcall", - # Other - "glsl" - ] -first_line_pattern = '^#version \d+' -line_comments = ["// "] -block_comment = { start = "/* ", prefix = "* ", end = "*/", tab_size = 1 } -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, -] diff --git a/extensions/glsl/languages/glsl/highlights.scm b/extensions/glsl/languages/glsl/highlights.scm deleted file mode 100644 index 09f94d4fb587963254c9bc31ec25b66a0e1e4323..0000000000000000000000000000000000000000 --- a/extensions/glsl/languages/glsl/highlights.scm +++ /dev/null @@ -1,117 +0,0 @@ -"break" @keyword -"case" @keyword -"const" @keyword -"continue" @keyword -"default" @keyword -"do" @keyword -"else" @keyword -"enum" @keyword -"extern" @keyword -"for" @keyword -"if" @keyword -"inline" @keyword -"return" @keyword -"sizeof" @keyword -"static" @keyword -"struct" @keyword -"switch" @keyword -"typedef" @keyword -"union" @keyword -"volatile" @keyword -"while" @keyword - -"#define" @keyword -"#elif" @keyword -"#else" @keyword -"#endif" @keyword -"#if" @keyword -"#ifdef" @keyword -"#ifndef" @keyword -"#include" @keyword -(preproc_directive) @keyword - -"--" @operator -"-" @operator -"-=" @operator -"->" @operator -"=" @operator -"!=" @operator -"*" @operator -"&" @operator -"&&" @operator -"+" @operator -"++" @operator -"+=" @operator -"<" @operator -"==" @operator -">" @operator -"||" @operator - -"." @delimiter -";" @delimiter - -(string_literal) @string -(system_lib_string) @string - -(null) @constant -(number_literal) @number -(char_literal) @number - -(identifier) @variable - -(field_identifier) @property -(statement_identifier) @label -(type_identifier) @type -(primitive_type) @type -(sized_type_specifier) @type - -(call_expression - function: (identifier) @function) -(call_expression - function: (field_expression - field: (field_identifier) @function)) -(function_declarator - declarator: (identifier) @function) -(preproc_function_def - name: (identifier) @function.special) - -((identifier) @constant - (#match? @constant "^[A-Z][A-Z\\d_]*$")) - -(comment) @comment - -[ - "in" - "out" - "inout" - "uniform" - "shared" - "layout" - "attribute" - "varying" - "buffer" - "coherent" - "readonly" - "writeonly" - "precision" - "highp" - "mediump" - "lowp" - "centroid" - "sample" - "patch" - "smooth" - "flat" - "noperspective" - "invariant" - "precise" -] @type.qualifier - -"subroutine" @keyword.function - -(extension_storage_class) @storageclass - -( - (identifier) @variable.builtin - (#match? @variable.builtin "^gl_") -) diff --git a/extensions/glsl/src/glsl.rs b/extensions/glsl/src/glsl.rs deleted file mode 100644 index 77865564cc1efead12327715aa77c5a0df2965af..0000000000000000000000000000000000000000 --- a/extensions/glsl/src/glsl.rs +++ /dev/null @@ -1,131 +0,0 @@ -use std::fs; -use zed::settings::LspSettings; -use zed_extension_api::{self as zed, LanguageServerId, Result, serde_json}; - -struct GlslExtension { - cached_binary_path: Option, -} - -impl GlslExtension { - fn language_server_binary_path( - &mut self, - language_server_id: &LanguageServerId, - worktree: &zed::Worktree, - ) -> Result { - if let Some(path) = worktree.which("glsl_analyzer") { - return Ok(path); - } - - if let Some(path) = &self.cached_binary_path - && fs::metadata(path).is_ok_and(|stat| stat.is_file()) - { - return Ok(path.clone()); - } - - zed::set_language_server_installation_status( - language_server_id, - &zed::LanguageServerInstallationStatus::CheckingForUpdate, - ); - let release = zed::latest_github_release( - "nolanderc/glsl_analyzer", - zed::GithubReleaseOptions { - require_assets: true, - pre_release: false, - }, - )?; - - let (platform, arch) = zed::current_platform(); - let asset_name = format!( - "{arch}-{os}.zip", - arch = match arch { - zed::Architecture::Aarch64 => "aarch64", - zed::Architecture::X86 => "x86", - zed::Architecture::X8664 => "x86_64", - }, - os = match platform { - zed::Os::Mac => "macos", - zed::Os::Linux => "linux-musl", - zed::Os::Windows => "windows", - } - ); - - let asset = release - .assets - .iter() - .find(|asset| asset.name == asset_name) - .ok_or_else(|| format!("no asset found matching {:?}", asset_name))?; - - let version_dir = format!("glsl_analyzer-{}", release.version); - fs::create_dir_all(&version_dir) - .map_err(|err| format!("failed to create directory '{version_dir}': {err}"))?; - let binary_path = format!("{version_dir}/bin/glsl_analyzer"); - - if !fs::metadata(&binary_path).is_ok_and(|stat| stat.is_file()) { - zed::set_language_server_installation_status( - language_server_id, - &zed::LanguageServerInstallationStatus::Downloading, - ); - - zed::download_file( - &asset.download_url, - &version_dir, - match platform { - zed::Os::Mac | zed::Os::Linux => zed::DownloadedFileType::Zip, - zed::Os::Windows => zed::DownloadedFileType::Zip, - }, - ) - .map_err(|e| format!("failed to download file: {e}"))?; - - zed::make_file_executable(&binary_path)?; - - let entries = - fs::read_dir(".").map_err(|e| format!("failed to list working directory {e}"))?; - for entry in entries { - let entry = entry.map_err(|e| format!("failed to load directory entry {e}"))?; - if entry.file_name().to_str() != Some(&version_dir) { - fs::remove_dir_all(entry.path()).ok(); - } - } - } - - self.cached_binary_path = Some(binary_path.clone()); - Ok(binary_path) - } -} - -impl zed::Extension for GlslExtension { - fn new() -> Self { - Self { - cached_binary_path: None, - } - } - - fn language_server_command( - &mut self, - language_server_id: &zed::LanguageServerId, - worktree: &zed::Worktree, - ) -> Result { - Ok(zed::Command { - command: self.language_server_binary_path(language_server_id, worktree)?, - args: vec![], - env: Default::default(), - }) - } - - fn language_server_workspace_configuration( - &mut self, - _language_server_id: &zed::LanguageServerId, - worktree: &zed::Worktree, - ) -> Result> { - let settings = LspSettings::for_worktree("glsl_analyzer", worktree) - .ok() - .and_then(|lsp_settings| lsp_settings.settings) - .unwrap_or_default(); - - Ok(Some(serde_json::json!({ - "glsl_analyzer": settings - }))) - } -} - -zed::register_extension!(GlslExtension); diff --git a/extensions/html/Cargo.toml b/extensions/html/Cargo.toml deleted file mode 100644 index 2c89f86cb450b7ea8476bffdff003a94b137d213..0000000000000000000000000000000000000000 --- a/extensions/html/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "zed_html" -version = "0.3.0" -edition.workspace = true -publish.workspace = true -license = "Apache-2.0" - -[lints] -workspace = true - -[lib] -path = "src/html.rs" -crate-type = ["cdylib"] - -[dependencies] -zed_extension_api = "0.7.0" diff --git a/extensions/html/LICENSE-APACHE b/extensions/html/LICENSE-APACHE deleted file mode 120000 index 1cd601d0a3affae83854be02a0afdec3b7a9ec4d..0000000000000000000000000000000000000000 --- a/extensions/html/LICENSE-APACHE +++ /dev/null @@ -1 +0,0 @@ -../../LICENSE-APACHE \ No newline at end of file diff --git a/extensions/html/extension.toml b/extensions/html/extension.toml deleted file mode 100644 index 68ab0e4b9d3f56fca17cbd518d5990edc2ec711a..0000000000000000000000000000000000000000 --- a/extensions/html/extension.toml +++ /dev/null @@ -1,19 +0,0 @@ -id = "html" -name = "HTML" -description = "HTML support." -version = "0.3.0" -schema_version = 1 -authors = ["Isaac Clayton "] -repository = "https://github.com/zed-industries/zed" - -[language_servers.vscode-html-language-server] -name = "vscode-html-language-server" -language = "HTML" - -[language_servers.vscode-html-language-server.language_ids] -"HTML" = "html" -"CSS" = "css" - -[grammars.html] -repository = "https://github.com/tree-sitter/tree-sitter-html" -commit = "bfa075d83c6b97cd48440b3829ab8d24a2319809" diff --git a/extensions/html/languages/html/brackets.scm b/extensions/html/languages/html/brackets.scm deleted file mode 100644 index 53d6a6bb234e28db21581906ea42e6384f872c9a..0000000000000000000000000000000000000000 --- a/extensions/html/languages/html/brackets.scm +++ /dev/null @@ -1,5 +0,0 @@ -("<" @open "/>" @close) -("" @close) -("<" @open ">" @close) -(("\"" @open "\"" @close) (#set! rainbow.exclude)) -((element (start_tag) @open (end_tag) @close) (#set! newline.only) (#set! rainbow.exclude)) diff --git a/extensions/html/languages/html/config.toml b/extensions/html/languages/html/config.toml deleted file mode 100644 index fc7d5571981e99fdb8bde68441821f07a1a94889..0000000000000000000000000000000000000000 --- a/extensions/html/languages/html/config.toml +++ /dev/null @@ -1,19 +0,0 @@ -name = "HTML" -grammar = "html" -path_suffixes = ["html", "htm", "shtml"] -autoclose_before = ">})" -block_comment = { start = "", tab_size = 0 } -wrap_characters = { start_prefix = "<", start_suffix = ">", end_prefix = "" } -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, - { start = "\"", end = "\"", close = true, newline = false, not_in = ["comment", "string"] }, - { start = "<", end = ">", close = false, newline = true, not_in = ["comment", "string"] }, - { start = "!--", end = " --", close = true, newline = false, not_in = ["comment", "string"] }, -] -completion_query_characters = ["-"] -prettier_parser_name = "html" - -[overrides.default] -linked_edit_characters = ["-"] diff --git a/extensions/html/languages/html/highlights.scm b/extensions/html/languages/html/highlights.scm deleted file mode 100644 index 1cc0601b764554c37ac28a45e988997b267b32fc..0000000000000000000000000000000000000000 --- a/extensions/html/languages/html/highlights.scm +++ /dev/null @@ -1,19 +0,0 @@ -(tag_name) @tag -(doctype) @tag.doctype -(attribute_name) @attribute -[ - "\"" - "'" - (attribute_value) -] @string -(comment) @comment - -"=" @punctuation.delimiter.html - -[ - "<" - ">" - "" -] @punctuation.bracket.html diff --git a/extensions/html/languages/html/indents.scm b/extensions/html/languages/html/indents.scm deleted file mode 100644 index 436663dba3e1993c84e151f09c581844fdcb977a..0000000000000000000000000000000000000000 --- a/extensions/html/languages/html/indents.scm +++ /dev/null @@ -1,6 +0,0 @@ -(start_tag ">" @end) @indent -(self_closing_tag "/>" @end) @indent - -(element - (start_tag) @start - (end_tag)? @end) @indent diff --git a/extensions/html/languages/html/injections.scm b/extensions/html/languages/html/injections.scm deleted file mode 100644 index 525b3efe29dca541afc8829dd41ff217f48439c3..0000000000000000000000000000000000000000 --- a/extensions/html/languages/html/injections.scm +++ /dev/null @@ -1,21 +0,0 @@ -((comment) @injection.content - (#set! injection.language "comment") -) - -(script_element - (raw_text) @injection.content - (#set! injection.language "javascript")) - -(style_element - (raw_text) @injection.content - (#set! injection.language "css")) - -(attribute - (attribute_name) @_attribute_name (#match? @_attribute_name "^style$") - (quoted_attribute_value (attribute_value) @injection.content) - (#set! injection.language "css")) - -(attribute - (attribute_name) @_attribute_name (#match? @_attribute_name "^on[a-z]+$") - (quoted_attribute_value (attribute_value) @injection.content) - (#set! injection.language "javascript")) diff --git a/extensions/html/languages/html/outline.scm b/extensions/html/languages/html/outline.scm deleted file mode 100644 index e7f9dc4fab01b89e68a2b668425fc7655b7d275e..0000000000000000000000000000000000000000 --- a/extensions/html/languages/html/outline.scm +++ /dev/null @@ -1,5 +0,0 @@ -(comment) @annotation - -(element - (start_tag - (tag_name) @name)) @item diff --git a/extensions/html/languages/html/overrides.scm b/extensions/html/languages/html/overrides.scm deleted file mode 100644 index 434f610e70242be8589a9f58cc7fd4704d5d9296..0000000000000000000000000000000000000000 --- a/extensions/html/languages/html/overrides.scm +++ /dev/null @@ -1,7 +0,0 @@ -(comment) @comment -(quoted_attribute_value) @string - -[ - (start_tag) - (end_tag) -] @default diff --git a/extensions/html/src/html.rs b/extensions/html/src/html.rs deleted file mode 100644 index 337689ebddd427769ab985ad82512f76b601e67c..0000000000000000000000000000000000000000 --- a/extensions/html/src/html.rs +++ /dev/null @@ -1,115 +0,0 @@ -use std::{env, fs}; -use zed::settings::LspSettings; -use zed_extension_api::{self as zed, LanguageServerId, Result, serde_json::json}; - -const BINARY_NAME: &str = "vscode-html-language-server"; -const SERVER_PATH: &str = - "node_modules/@zed-industries/vscode-langservers-extracted/bin/vscode-html-language-server"; -const PACKAGE_NAME: &str = "@zed-industries/vscode-langservers-extracted"; - -struct HtmlExtension { - cached_binary_path: Option, -} - -impl HtmlExtension { - fn server_exists(&self) -> bool { - fs::metadata(SERVER_PATH).is_ok_and(|stat| stat.is_file()) - } - - fn server_script_path(&mut self, language_server_id: &LanguageServerId) -> Result { - let server_exists = self.server_exists(); - if self.cached_binary_path.is_some() && server_exists { - return Ok(SERVER_PATH.to_string()); - } - - zed::set_language_server_installation_status( - language_server_id, - &zed::LanguageServerInstallationStatus::CheckingForUpdate, - ); - let version = zed::npm_package_latest_version(PACKAGE_NAME)?; - - if !server_exists - || zed::npm_package_installed_version(PACKAGE_NAME)?.as_ref() != Some(&version) - { - zed::set_language_server_installation_status( - language_server_id, - &zed::LanguageServerInstallationStatus::Downloading, - ); - let result = zed::npm_install_package(PACKAGE_NAME, &version); - match result { - Ok(()) => { - if !self.server_exists() { - Err(format!( - "installed package '{PACKAGE_NAME}' did not contain expected path '{SERVER_PATH}'", - ))?; - } - } - Err(error) => { - if !self.server_exists() { - Err(error)?; - } - } - } - } - Ok(SERVER_PATH.to_string()) - } -} - -impl zed::Extension for HtmlExtension { - fn new() -> Self { - Self { - cached_binary_path: None, - } - } - - fn language_server_command( - &mut self, - language_server_id: &LanguageServerId, - worktree: &zed::Worktree, - ) -> Result { - let server_path = if let Some(path) = worktree.which(BINARY_NAME) { - return Ok(zed::Command { - command: path, - args: vec!["--stdio".to_string()], - env: Default::default(), - }); - } else { - let server_path = self.server_script_path(language_server_id)?; - env::current_dir() - .unwrap() - .join(&server_path) - .to_string_lossy() - .to_string() - }; - self.cached_binary_path = Some(server_path.clone()); - - Ok(zed::Command { - command: zed::node_binary_path()?, - args: vec![server_path, "--stdio".to_string()], - env: Default::default(), - }) - } - - fn language_server_workspace_configuration( - &mut self, - server_id: &LanguageServerId, - worktree: &zed::Worktree, - ) -> Result> { - let settings = LspSettings::for_worktree(server_id.as_ref(), worktree) - .ok() - .and_then(|lsp_settings| lsp_settings.settings) - .unwrap_or_default(); - Ok(Some(settings)) - } - - fn language_server_initialization_options( - &mut self, - _server_id: &LanguageServerId, - _worktree: &zed_extension_api::Worktree, - ) -> Result> { - let initialization_options = json!({"provideFormatter": true }); - Ok(Some(initialization_options)) - } -} - -zed::register_extension!(HtmlExtension); diff --git a/extensions/openai/Cargo.lock b/extensions/openai/Cargo.lock deleted file mode 100644 index d39408412cb4c17689687f581b32e7a339329572..0000000000000000000000000000000000000000 --- a/extensions/openai/Cargo.lock +++ /dev/null @@ -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 = "openai" -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", -] diff --git a/extensions/openai/Cargo.toml b/extensions/openai/Cargo.toml deleted file mode 100644 index f81809e426ef69b80ce079cbb9f45c0d1a1fe989..0000000000000000000000000000000000000000 --- a/extensions/openai/Cargo.toml +++ /dev/null @@ -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" diff --git a/extensions/openai/LICENSE-APACHE b/extensions/openai/LICENSE-APACHE deleted file mode 120000 index 1cd601d0a3affae83854be02a0afdec3b7a9ec4d..0000000000000000000000000000000000000000 --- a/extensions/openai/LICENSE-APACHE +++ /dev/null @@ -1 +0,0 @@ -../../LICENSE-APACHE \ No newline at end of file diff --git a/extensions/openai/extension.toml b/extensions/openai/extension.toml deleted file mode 100644 index dd185853699198d27ea1a9f55bedd86b74ce7b4c..0000000000000000000000000000000000000000 --- a/extensions/openai/extension.toml +++ /dev/null @@ -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_vars = ["OPENAI_API_KEY"] diff --git a/extensions/openai/icons/openai.svg b/extensions/openai/icons/openai.svg deleted file mode 100644 index e45ac315a011853a9e9343171659b7623017fb31..0000000000000000000000000000000000000000 --- a/extensions/openai/icons/openai.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/extensions/openai/src/openai.rs b/extensions/openai/src/openai.rs deleted file mode 100644 index 107b00786abc1a29d900e006cf706796dc2f664c..0000000000000000000000000000000000000000 --- a/extensions/openai/src/openai.rs +++ /dev/null @@ -1,682 +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>, - next_stream_id: Mutex, -} - -struct StreamState { - response_stream: Option, - buffer: String, - started: bool, - tool_calls: HashMap, - 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, - 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, - #[serde(skip_serializing_if = "Option::is_none")] - tools: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - tool_choice: Option, - #[serde(skip_serializing_if = "Option::is_none")] - temperature: Option, - #[serde(skip_serializing_if = "Option::is_none")] - max_tokens: Option, - #[serde(skip_serializing_if = "Vec::is_empty")] - stop: Vec, - stream: bool, - stream_options: Option, -} - -#[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 }, - #[serde(rename = "assistant")] - Assistant { - #[serde(skip_serializing_if = "Option::is_none")] - content: Option, - #[serde(skip_serializing_if = "Option::is_none")] - tool_calls: Option>, - }, - #[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, - #[serde(default)] - usage: Option, -} - -#[derive(Deserialize, Debug)] -struct OpenAiChoice { - delta: OpenAiDelta, - finish_reason: Option, -} - -#[derive(Deserialize, Debug, Default)] -struct OpenAiDelta { - #[serde(default)] - content: Option, - #[serde(default)] - tool_calls: Option>, -} - -#[derive(Deserialize, Debug)] -struct OpenAiToolCallDelta { - index: usize, - #[serde(default)] - id: Option, - #[serde(default)] - function: Option, -} - -#[derive(Deserialize, Debug)] -struct OpenAiFunctionDelta { - #[serde(default)] - name: Option, - #[serde(default)] - arguments: Option, -} - -#[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 { - 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::>() - .join("\n"); - if !text.is_empty() { - messages.push(OpenAiMessage::System { content: text }); - } - } - LlmMessageRole::User => { - let parts: Vec = 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 = None; - let mut tool_calls: Vec = 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> = 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 { - 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 { - vec![LlmProviderInfo { - id: "openai".into(), - name: "OpenAI".into(), - icon: Some("icons/openai.svg".into()), - }] - } - - fn llm_provider_models(&self, _provider_id: &str) -> Result, 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 { - Some( - "[Create an API key](https://platform.openai.com/api-keys) to use OpenAI as your LLM provider.".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 { - 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, 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, - is_input_complete: true, - 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 = 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, - is_input_complete: true, - 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); diff --git a/extensions/openrouter/Cargo.lock b/extensions/openrouter/Cargo.lock deleted file mode 100644 index bca363a0a925d5fb9639a93b524b75c602fcd233..0000000000000000000000000000000000000000 --- a/extensions/openrouter/Cargo.lock +++ /dev/null @@ -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 = "openrouter" -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", -] diff --git a/extensions/openrouter/Cargo.toml b/extensions/openrouter/Cargo.toml deleted file mode 100644 index 69be1d15fc9850777abb42805dfcaccca10b64b3..0000000000000000000000000000000000000000 --- a/extensions/openrouter/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "openrouter" -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" \ No newline at end of file diff --git a/extensions/openrouter/LICENSE-APACHE b/extensions/openrouter/LICENSE-APACHE deleted file mode 120000 index 1cd601d0a3affae83854be02a0afdec3b7a9ec4d..0000000000000000000000000000000000000000 --- a/extensions/openrouter/LICENSE-APACHE +++ /dev/null @@ -1 +0,0 @@ -../../LICENSE-APACHE \ No newline at end of file diff --git a/extensions/openrouter/extension.toml b/extensions/openrouter/extension.toml deleted file mode 100644 index d77bcbc4576f5b89e729111bcce00b30e4c69a99..0000000000000000000000000000000000000000 --- a/extensions/openrouter/extension.toml +++ /dev/null @@ -1,13 +0,0 @@ -id = "openrouter" -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.openrouter] -name = "OpenRouter" - -[language_model_providers.openrouter.auth] -env_vars = ["OPENROUTER_API_KEY"] diff --git a/extensions/openrouter/icons/openrouter.svg b/extensions/openrouter/icons/openrouter.svg deleted file mode 100644 index b6f5164e0b385f26e7b22a12253d18200dbff24e..0000000000000000000000000000000000000000 --- a/extensions/openrouter/icons/openrouter.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/extensions/openrouter/src/open_router.rs b/extensions/openrouter/src/open_router.rs deleted file mode 100644 index db3d00403c522572c134856b8472be6f1f0b9b5d..0000000000000000000000000000000000000000 --- a/extensions/openrouter/src/open_router.rs +++ /dev/null @@ -1,750 +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>, - next_stream_id: Mutex, -} - -struct StreamState { - response_stream: Option, - buffer: String, - started: bool, - tool_calls: HashMap, - 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, - 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, - #[serde(skip_serializing_if = "Option::is_none")] - max_tokens: Option, - #[serde(skip_serializing_if = "Vec::is_empty")] - tools: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - tool_choice: Option, - #[serde(skip_serializing_if = "Vec::is_empty")] - stop: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - temperature: Option, - stream: bool, -} - -#[derive(Serialize)] -struct OpenRouterMessage { - role: String, - #[serde(skip_serializing_if = "Option::is_none")] - content: Option, - #[serde(skip_serializing_if = "Option::is_none")] - tool_calls: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - tool_call_id: Option, -} - -#[derive(Serialize, Clone)] -#[serde(untagged)] -enum OpenRouterContent { - Text(String), - Parts(Vec), -} - -#[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, - #[serde(default)] - usage: Option, -} - -#[derive(Deserialize, Debug)] -struct OpenRouterStreamChoice { - delta: OpenRouterDelta, - finish_reason: Option, -} - -#[derive(Deserialize, Debug, Default)] -struct OpenRouterDelta { - #[serde(default)] - content: Option, - #[serde(default)] - tool_calls: Option>, -} - -#[derive(Deserialize, Debug)] -struct OpenRouterToolCallDelta { - index: usize, - #[serde(default)] - id: Option, - #[serde(default)] - function: Option, -} - -#[derive(Deserialize, Debug, Default)] -struct OpenRouterFunctionDelta { - #[serde(default)] - name: Option, - #[serde(default)] - arguments: Option, -} - -#[derive(Deserialize, Debug)] -struct OpenRouterUsage { - prompt_tokens: u64, - completion_tokens: u64, -} - -fn convert_request( - model_id: &str, - request: &LlmCompletionRequest, -) -> Result { - let mut messages: Vec = 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 = Vec::new(); - let mut tool_result_messages: Vec = 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 = 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 = 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 { - 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 { - vec![LlmProviderInfo { - id: "openrouter".into(), - name: "OpenRouter".into(), - icon: Some("icons/openrouter.svg".into()), - }] - } - - fn llm_provider_models(&self, _provider_id: &str) -> Result, 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 { - Some( - "[Create an API key](https://openrouter.ai/keys) to use OpenRouter as your LLM provider.".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 { - 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, 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, - is_input_complete: true, - 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); diff --git a/extensions/proto/Cargo.toml b/extensions/proto/Cargo.toml deleted file mode 100644 index c3606f668aa01d7a8baa20d54d073a7004a6f8c0..0000000000000000000000000000000000000000 --- a/extensions/proto/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "zed_proto" -version = "0.3.0" -edition.workspace = true -publish.workspace = true -license = "Apache-2.0" - -[lints] -workspace = true - -[lib] -path = "src/proto.rs" -crate-type = ["cdylib"] - -[dependencies] -zed_extension_api = "0.7.0" diff --git a/extensions/proto/LICENSE-APACHE b/extensions/proto/LICENSE-APACHE deleted file mode 120000 index 1cd601d0a3affae83854be02a0afdec3b7a9ec4d..0000000000000000000000000000000000000000 --- a/extensions/proto/LICENSE-APACHE +++ /dev/null @@ -1 +0,0 @@ -../../LICENSE-APACHE \ No newline at end of file diff --git a/extensions/proto/extension.toml b/extensions/proto/extension.toml deleted file mode 100644 index 13c4054eef083e131ab311b1ec6e5a63aff545d8..0000000000000000000000000000000000000000 --- a/extensions/proto/extension.toml +++ /dev/null @@ -1,24 +0,0 @@ -id = "proto" -name = "Proto" -description = "Protocol Buffers support." -version = "0.3.0" -schema_version = 1 -authors = ["Zed Industries "] -repository = "https://github.com/zed-industries/zed" - -[grammars.proto] -repository = "https://github.com/coder3101/tree-sitter-proto" -commit = "a6caac94b5aa36b322b5b70040d5b67132f109d0" - - -[language_servers.buf] -name = "Buf" -languages = ["Proto"] - -[language_servers.protobuf-language-server] -name = "Protobuf Language Server" -languages = ["Proto"] - -[language_servers.protols] -name = "Protols" -languages = ["Proto"] diff --git a/extensions/proto/languages/proto/config.toml b/extensions/proto/languages/proto/config.toml deleted file mode 100644 index 6d25c23da5dfaaf9c4baf36bba916d7d4d001b8e..0000000000000000000000000000000000000000 --- a/extensions/proto/languages/proto/config.toml +++ /dev/null @@ -1,13 +0,0 @@ -name = "Proto" -grammar = "proto" -path_suffixes = ["proto"] -line_comments = ["// "] -autoclose_before = ";:.,=}])>" -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, - { start = "\"", end = "\"", close = true, newline = false, not_in = ["comment", "string"] }, - { start = "'", end = "'", close = true, newline = false, not_in = ["comment", "string"] }, - { start = "/*", end = " */", close = true, newline = false, not_in = ["comment", "string"] }, -] diff --git a/extensions/proto/languages/proto/highlights.scm b/extensions/proto/languages/proto/highlights.scm deleted file mode 100644 index 5d0a513bee1ca4597c649fbe8e6ca31a00fe9dff..0000000000000000000000000000000000000000 --- a/extensions/proto/languages/proto/highlights.scm +++ /dev/null @@ -1,61 +0,0 @@ -[ - "syntax" - "package" - "option" - "optional" - "import" - "service" - "rpc" - "returns" - "message" - "enum" - "oneof" - "repeated" - "reserved" - "to" -] @keyword - -[ - (key_type) - (type) - (message_name) - (enum_name) - (service_name) - (rpc_name) - (message_or_enum_type) -] @type - -(enum_field - (identifier) @constant) - -[ - (string) - "\"proto3\"" -] @string - -(int_lit) @number - -[ - (true) - (false) -] @boolean - -(comment) @comment - -[ - "(" - ")" - "[" - "]" - "{" - "}" - "<" - ">" -] @punctuation.bracket - -[ - ";" - "," -] @punctuation.delimiter - -"=" @operator diff --git a/extensions/proto/languages/proto/indents.scm b/extensions/proto/languages/proto/indents.scm deleted file mode 100644 index acb44a5e1e617cc0d735228af022129c0b39d561..0000000000000000000000000000000000000000 --- a/extensions/proto/languages/proto/indents.scm +++ /dev/null @@ -1,3 +0,0 @@ -(_ "{" "}" @end) @indent -(_ "[" "]" @end) @indent -(_ "(" ")" @end) @indent diff --git a/extensions/proto/languages/proto/outline.scm b/extensions/proto/languages/proto/outline.scm deleted file mode 100644 index f90b1bae33effade920bf8f2c76d7f2d187f1d8e..0000000000000000000000000000000000000000 --- a/extensions/proto/languages/proto/outline.scm +++ /dev/null @@ -1,19 +0,0 @@ -(message - "message" @context - (message_name - (identifier) @name)) @item - -(service - "service" @context - (service_name - (identifier) @name)) @item - -(rpc - "rpc" @context - (rpc_name - (identifier) @name)) @item - -(enum - "enum" @context - (enum_name - (identifier) @name)) @item diff --git a/extensions/proto/languages/proto/textobjects.scm b/extensions/proto/languages/proto/textobjects.scm deleted file mode 100644 index 90ea84282da39df8a2023108c367c3ef76a0ef9a..0000000000000000000000000000000000000000 --- a/extensions/proto/languages/proto/textobjects.scm +++ /dev/null @@ -1,18 +0,0 @@ -(message (message_body - "{" - (_)* @class.inside - "}")) @class.around -(enum (enum_body - "{" - (_)* @class.inside - "}")) @class.around -(service - "service" - (_) - "{" - (_)* @class.inside - "}") @class.around - -(rpc) @function.around - -(comment)+ @comment.around diff --git a/extensions/proto/src/language_servers.rs b/extensions/proto/src/language_servers.rs deleted file mode 100644 index 47a5e72d8aadf5d0286667148f0a7dd95fea10ba..0000000000000000000000000000000000000000 --- a/extensions/proto/src/language_servers.rs +++ /dev/null @@ -1,8 +0,0 @@ -mod buf; -mod protobuf_language_server; -mod protols; -mod util; - -pub(crate) use buf::*; -pub(crate) use protobuf_language_server::*; -pub(crate) use protols::*; diff --git a/extensions/proto/src/language_servers/buf.rs b/extensions/proto/src/language_servers/buf.rs deleted file mode 100644 index 92106298d3d1deb6ed2b0f4194ab09321fa09552..0000000000000000000000000000000000000000 --- a/extensions/proto/src/language_servers/buf.rs +++ /dev/null @@ -1,114 +0,0 @@ -use std::fs; - -use zed_extension_api::{ - self as zed, Architecture, DownloadedFileType, GithubReleaseOptions, Os, Result, - settings::LspSettings, -}; - -use crate::language_servers::util; - -pub(crate) struct BufLsp { - cached_binary_path: Option, -} - -impl BufLsp { - pub(crate) const SERVER_NAME: &str = "buf"; - - pub(crate) fn new() -> Self { - BufLsp { - cached_binary_path: None, - } - } - - pub(crate) fn language_server_binary( - &mut self, - worktree: &zed::Worktree, - ) -> Result { - let binary_settings = LspSettings::for_worktree(Self::SERVER_NAME, worktree) - .ok() - .and_then(|lsp_settings| lsp_settings.binary); - - let args = binary_settings - .as_ref() - .and_then(|binary_settings| binary_settings.arguments.clone()) - .unwrap_or_else(|| ["lsp", "serve"].map(ToOwned::to_owned).into()); - - if let Some(path) = binary_settings.and_then(|binary_settings| binary_settings.path) { - return Ok(zed::Command { - command: path, - args, - env: Default::default(), - }); - } else if let Some(path) = self.cached_binary_path.clone() { - return Ok(zed::Command { - command: path, - args, - env: Default::default(), - }); - } else if let Some(path) = worktree.which(Self::SERVER_NAME) { - self.cached_binary_path = Some(path.clone()); - return Ok(zed::Command { - command: path, - args, - env: Default::default(), - }); - } - - let latest_release = zed::latest_github_release( - "bufbuild/buf", - GithubReleaseOptions { - require_assets: true, - pre_release: false, - }, - )?; - - let (os, arch) = zed::current_platform(); - - let release_suffix = match (os, arch) { - (Os::Mac, Architecture::Aarch64) => "Darwin-arm64", - (Os::Mac, Architecture::X8664) => "Darwin-x86_64", - (Os::Linux, Architecture::Aarch64) => "Linux-aarch64", - (Os::Linux, Architecture::X8664) => "Linux-x86_64", - (Os::Windows, Architecture::Aarch64) => "Windows-arm64.exe", - (Os::Windows, Architecture::X8664) => "Windows-x86_64.exe", - _ => { - return Err("Platform and architecture not supported by buf CLI".to_string()); - } - }; - - let release_name = format!("buf-{release_suffix}"); - - let version_dir = format!("{}-{}", Self::SERVER_NAME, latest_release.version); - fs::create_dir_all(&version_dir).map_err(|_| "Could not create directory")?; - - let binary_path = format!("{version_dir}/buf"); - - let download_target = latest_release - .assets - .into_iter() - .find(|asset| asset.name == release_name) - .ok_or_else(|| { - format!( - "Could not find asset with name {} in buf CLI release", - &release_name - ) - })?; - - zed::download_file( - &download_target.download_url, - &binary_path, - DownloadedFileType::Uncompressed, - )?; - zed::make_file_executable(&binary_path)?; - - util::remove_outdated_versions(Self::SERVER_NAME, &version_dir)?; - - self.cached_binary_path = Some(binary_path.clone()); - - Ok(zed::Command { - command: binary_path, - args, - env: Default::default(), - }) - } -} diff --git a/extensions/proto/src/language_servers/protobuf_language_server.rs b/extensions/proto/src/language_servers/protobuf_language_server.rs deleted file mode 100644 index f4b13077f73182dd0c30486ee274ade26ec1e40e..0000000000000000000000000000000000000000 --- a/extensions/proto/src/language_servers/protobuf_language_server.rs +++ /dev/null @@ -1,52 +0,0 @@ -use zed_extension_api::{self as zed, Result, settings::LspSettings}; - -pub(crate) struct ProtobufLanguageServer { - cached_binary_path: Option, -} - -impl ProtobufLanguageServer { - pub(crate) const SERVER_NAME: &str = "protobuf-language-server"; - - pub(crate) fn new() -> Self { - ProtobufLanguageServer { - cached_binary_path: None, - } - } - - pub(crate) fn language_server_binary( - &mut self, - worktree: &zed::Worktree, - ) -> Result { - let binary_settings = LspSettings::for_worktree(Self::SERVER_NAME, worktree) - .ok() - .and_then(|lsp_settings| lsp_settings.binary); - - let args = binary_settings - .as_ref() - .and_then(|binary_settings| binary_settings.arguments.clone()) - .unwrap_or_else(|| vec!["-logs".into(), "".into()]); - - if let Some(path) = binary_settings.and_then(|binary_settings| binary_settings.path) { - Ok(zed::Command { - command: path, - args, - env: Default::default(), - }) - } else if let Some(path) = self.cached_binary_path.clone() { - Ok(zed::Command { - command: path, - args, - env: Default::default(), - }) - } else if let Some(path) = worktree.which(Self::SERVER_NAME) { - self.cached_binary_path = Some(path.clone()); - Ok(zed::Command { - command: path, - args, - env: Default::default(), - }) - } else { - Err(format!("{} not found in PATH", Self::SERVER_NAME)) - } - } -} diff --git a/extensions/proto/src/language_servers/protols.rs b/extensions/proto/src/language_servers/protols.rs deleted file mode 100644 index 90d365eae7d99ccb27d60f774ed700b47323d8d0..0000000000000000000000000000000000000000 --- a/extensions/proto/src/language_servers/protols.rs +++ /dev/null @@ -1,113 +0,0 @@ -use zed_extension_api::{ - self as zed, Architecture, DownloadedFileType, GithubReleaseOptions, Os, Result, - settings::LspSettings, -}; - -use crate::language_servers::util; - -pub(crate) struct ProtoLs { - cached_binary_path: Option, -} - -impl ProtoLs { - pub(crate) const SERVER_NAME: &str = "protols"; - - pub(crate) fn new() -> Self { - ProtoLs { - cached_binary_path: None, - } - } - - pub(crate) fn language_server_binary( - &mut self, - worktree: &zed::Worktree, - ) -> Result { - let binary_settings = LspSettings::for_worktree(Self::SERVER_NAME, worktree) - .ok() - .and_then(|lsp_settings| lsp_settings.binary); - - let args = binary_settings - .as_ref() - .and_then(|binary_settings| binary_settings.arguments.clone()) - .unwrap_or_default(); - - let env = worktree.shell_env(); - - if let Some(path) = binary_settings.and_then(|binary_settings| binary_settings.path) { - return Ok(zed::Command { - command: path, - args, - env, - }); - } else if let Some(path) = self.cached_binary_path.clone() { - return Ok(zed::Command { - command: path, - args, - env, - }); - } else if let Some(path) = worktree.which(Self::SERVER_NAME) { - self.cached_binary_path = Some(path.clone()); - return Ok(zed::Command { - command: path, - args, - env, - }); - } - - let latest_release = zed::latest_github_release( - "coder3101/protols", - GithubReleaseOptions { - require_assets: true, - pre_release: false, - }, - )?; - - let (os, arch) = zed::current_platform(); - - let release_suffix = match (os, arch) { - (Os::Mac, Architecture::Aarch64) => "aarch64-apple-darwin.tar.gz", - (Os::Mac, Architecture::X8664) => "x86_64-apple-darwin.tar.gz", - (Os::Linux, Architecture::Aarch64) => "aarch64-unknown-linux-gnu.tar.gz", - (Os::Linux, Architecture::X8664) => "x86_64-unknown-linux-gnu.tar.gz", - (Os::Windows, Architecture::X8664) => "x86_64-pc-windows-msvc.zip", - _ => { - return Err("Platform and architecture not supported by Protols".to_string()); - } - }; - - let release_name = format!("protols-{release_suffix}"); - - let file_type = if os == Os::Windows { - DownloadedFileType::Zip - } else { - DownloadedFileType::GzipTar - }; - - let version_dir = format!("{}-{}", Self::SERVER_NAME, latest_release.version); - let binary_path = format!("{version_dir}/protols"); - - let download_target = latest_release - .assets - .into_iter() - .find(|asset| asset.name == release_name) - .ok_or_else(|| { - format!( - "Could not find asset with name {} in Protols release", - &release_name - ) - })?; - - zed::download_file(&download_target.download_url, &version_dir, file_type)?; - zed::make_file_executable(&binary_path)?; - - util::remove_outdated_versions(Self::SERVER_NAME, &version_dir)?; - - self.cached_binary_path = Some(binary_path.clone()); - - Ok(zed::Command { - command: binary_path, - args, - env, - }) - } -} diff --git a/extensions/proto/src/language_servers/util.rs b/extensions/proto/src/language_servers/util.rs deleted file mode 100644 index 3036c9bc3aaf9cc3fccd462fe0ad70aa31892012..0000000000000000000000000000000000000000 --- a/extensions/proto/src/language_servers/util.rs +++ /dev/null @@ -1,19 +0,0 @@ -use std::fs; - -use zed_extension_api::Result; - -pub(super) fn remove_outdated_versions( - language_server_id: &'static str, - version_dir: &str, -) -> Result<()> { - let entries = fs::read_dir(".").map_err(|e| format!("failed to list working directory {e}"))?; - for entry in entries { - let entry = entry.map_err(|e| format!("failed to load directory entry {e}"))?; - if entry.file_name().to_str().is_none_or(|file_name| { - file_name.starts_with(language_server_id) && file_name != version_dir - }) { - fs::remove_dir_all(entry.path()).ok(); - } - } - Ok(()) -} diff --git a/extensions/proto/src/proto.rs b/extensions/proto/src/proto.rs deleted file mode 100644 index 07e0ccedcee287f037576db56d5a9d7958ea83f9..0000000000000000000000000000000000000000 --- a/extensions/proto/src/proto.rs +++ /dev/null @@ -1,66 +0,0 @@ -use zed_extension_api::{self as zed, Result, settings::LspSettings}; - -use crate::language_servers::{BufLsp, ProtoLs, ProtobufLanguageServer}; - -mod language_servers; - -struct ProtobufExtension { - protobuf_language_server: Option, - protols: Option, - buf_lsp: Option, -} - -impl zed::Extension for ProtobufExtension { - fn new() -> Self { - Self { - protobuf_language_server: None, - protols: None, - buf_lsp: None, - } - } - - fn language_server_command( - &mut self, - language_server_id: &zed_extension_api::LanguageServerId, - worktree: &zed_extension_api::Worktree, - ) -> zed_extension_api::Result { - match language_server_id.as_ref() { - ProtobufLanguageServer::SERVER_NAME => self - .protobuf_language_server - .get_or_insert_with(ProtobufLanguageServer::new) - .language_server_binary(worktree), - - ProtoLs::SERVER_NAME => self - .protols - .get_or_insert_with(ProtoLs::new) - .language_server_binary(worktree), - - BufLsp::SERVER_NAME => self - .buf_lsp - .get_or_insert_with(BufLsp::new) - .language_server_binary(worktree), - - _ => Err(format!("Unknown language server ID {}", language_server_id)), - } - } - - fn language_server_workspace_configuration( - &mut self, - server_id: &zed::LanguageServerId, - worktree: &zed::Worktree, - ) -> Result> { - LspSettings::for_worktree(server_id.as_ref(), worktree) - .map(|lsp_settings| lsp_settings.settings) - } - - fn language_server_initialization_options( - &mut self, - server_id: &zed::LanguageServerId, - worktree: &zed::Worktree, - ) -> Result> { - LspSettings::for_worktree(server_id.as_ref(), worktree) - .map(|lsp_settings| lsp_settings.initialization_options) - } -} - -zed::register_extension!(ProtobufExtension); diff --git a/extensions/slash-commands-example/Cargo.toml b/extensions/slash-commands-example/Cargo.toml deleted file mode 100644 index 03b22af254ab3190f2dbfca04976c89b9a37e995..0000000000000000000000000000000000000000 --- a/extensions/slash-commands-example/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "slash_commands_example" -version = "0.1.0" -edition.workspace = true -publish.workspace = true -license = "Apache-2.0" - -[lints] -workspace = true - -[lib] -path = "src/slash_commands_example.rs" -crate-type = ["cdylib"] - -[dependencies] -zed_extension_api = "0.1.0" diff --git a/extensions/slash-commands-example/LICENSE-APACHE b/extensions/slash-commands-example/LICENSE-APACHE deleted file mode 120000 index 1cd601d0a3affae83854be02a0afdec3b7a9ec4d..0000000000000000000000000000000000000000 --- a/extensions/slash-commands-example/LICENSE-APACHE +++ /dev/null @@ -1 +0,0 @@ -../../LICENSE-APACHE \ No newline at end of file diff --git a/extensions/slash-commands-example/README.md b/extensions/slash-commands-example/README.md deleted file mode 100644 index 8c16a4e168a3334d3197090837eeaf21c956b3c3..0000000000000000000000000000000000000000 --- a/extensions/slash-commands-example/README.md +++ /dev/null @@ -1,84 +0,0 @@ -# Slash Commands Example Extension - -This is an example extension showcasing how to write slash commands. - -See: [Extensions: Slash Commands](https://zed.dev/docs/extensions/slash-commands) in the Zed Docs. - -## Pre-requisites - -[Install Rust Toolchain](https://www.rust-lang.org/tools/install): - -```sh -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -``` - -## Setup - -```sh -git clone https://github.com/zed-industries/zed.git -cp -RL zed/extensions/slash-commands-example . - -cd slash-commands-example/ - -# Update Cargo.toml to make it standalone -cat > Cargo.toml << EOF -[package] -name = "slash_commands_example" -version = "0.1.0" -edition = "2021" -license = "Apache-2.0" - -[lib] -path = "src/slash_commands_example.rs" -crate-type = ["cdylib"] - -[dependencies] -zed_extension_api = "0.1.0" -EOF - -curl -O https://raw.githubusercontent.com/rust-lang/rust/master/LICENSE-APACHE -echo "# Zed Slash Commands Example Extension" > README.md -echo "Cargo.lock" > .gitignore -echo "target/" >> .gitignore -echo "*.wasm" >> .gitignore - -git init -git add . -git commit -m "Initial commit" - -cd .. -mv slash-commands-example MY-SUPER-COOL-ZED-EXTENSION -zed $_ -``` - -## Installation - -1. Open the command palette (`cmd-shift-p` or `ctrl-shift-p`). -2. Launch `zed: install dev extension` -3. Select the extension folder created above - -## Test - -Open the assistant and type `/echo` and `/pick-one` at the beginning of a line. - -## Customization - -Open the `extensions.toml` file and set the `id`, `name`, `description`, `authors` and `repository` fields. - -Rename `slash-commands-example.rs` you'll also have to update `Cargo.toml` - -## Rebuild - -Rebuild to see these changes reflected: - -1. Open Zed Extensions (`cmd-shift-x` or `ctrl-shift-x`). -2. Click `Rebuild` next to your Dev Extension (formerly "Slash Command Example") - -## Troubleshooting / Logs - -- [zed.dev docs: Troubleshooting](https://zed.dev/docs/troubleshooting) - -## Documentation - -- [zed.dev docs: Extensions: Developing Extensions](https://zed.dev/docs/extensions/developing-extensions) -- [zed.dev docs: Extensions: Slash Commands](https://zed.dev/docs/extensions/slash-commands) diff --git a/extensions/slash-commands-example/extension.toml b/extensions/slash-commands-example/extension.toml deleted file mode 100644 index 888c776d0111bdc5f99e87967f0cff6e0c91b2b3..0000000000000000000000000000000000000000 --- a/extensions/slash-commands-example/extension.toml +++ /dev/null @@ -1,15 +0,0 @@ -id = "slash-commands-example" -name = "Slash Commands Example" -description = "An example extension showcasing slash commands." -version = "0.1.0" -schema_version = 1 -authors = ["Zed Industries "] -repository = "https://github.com/zed-industries/zed" - -[slash_commands.echo] -description = "echoes the provided input" -requires_argument = true - -[slash_commands.pick-one] -description = "pick one of three options" -requires_argument = true diff --git a/extensions/slash-commands-example/src/slash_commands_example.rs b/extensions/slash-commands-example/src/slash_commands_example.rs deleted file mode 100644 index 5b170d63ee38c4dd173ddc2856c858755150490e..0000000000000000000000000000000000000000 --- a/extensions/slash-commands-example/src/slash_commands_example.rs +++ /dev/null @@ -1,90 +0,0 @@ -use zed_extension_api::{ - self as zed, SlashCommand, SlashCommandArgumentCompletion, SlashCommandOutput, - SlashCommandOutputSection, Worktree, -}; - -struct SlashCommandsExampleExtension; - -impl zed::Extension for SlashCommandsExampleExtension { - fn new() -> Self { - SlashCommandsExampleExtension - } - - fn complete_slash_command_argument( - &self, - command: SlashCommand, - _args: Vec, - ) -> Result, String> { - match command.name.as_str() { - "echo" => Ok(vec![]), - "pick-one" => Ok(vec![ - SlashCommandArgumentCompletion { - label: "Option One".to_string(), - new_text: "option-1".to_string(), - run_command: true, - }, - SlashCommandArgumentCompletion { - label: "Option Two".to_string(), - new_text: "option-2".to_string(), - run_command: true, - }, - SlashCommandArgumentCompletion { - label: "Option Three".to_string(), - new_text: "option-3".to_string(), - run_command: true, - }, - ]), - command => Err(format!("unknown slash command: \"{command}\"")), - } - } - - fn run_slash_command( - &self, - command: SlashCommand, - args: Vec, - _worktree: Option<&Worktree>, - ) -> Result { - match command.name.as_str() { - "echo" => { - if args.is_empty() { - return Err("nothing to echo".to_string()); - } - - let text = args.join(" "); - - Ok(SlashCommandOutput { - sections: vec![SlashCommandOutputSection { - range: (0..text.len()).into(), - label: "Echo".to_string(), - }], - text, - }) - } - "pick-one" => { - let Some(selection) = args.first() else { - return Err("no option selected".to_string()); - }; - - match selection.as_str() { - "option-1" | "option-2" | "option-3" => {} - invalid_option => { - return Err(format!("{invalid_option} is not a valid option")); - } - } - - let text = format!("You chose {selection}."); - - Ok(SlashCommandOutput { - sections: vec![SlashCommandOutputSection { - range: (0..text.len()).into(), - label: format!("Pick One: {selection}"), - }], - text, - }) - } - command => Err(format!("unknown slash command: \"{command}\"")), - } - } -} - -zed::register_extension!(SlashCommandsExampleExtension); diff --git a/extensions/test-extension/Cargo.toml b/extensions/test-extension/Cargo.toml deleted file mode 100644 index 7d2412b98f3829a97e9cae7e59883a0e3ebb068d..0000000000000000000000000000000000000000 --- a/extensions/test-extension/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "zed_test_extension" -version = "0.1.0" -edition.workspace = true -publish.workspace = true -license = "Apache-2.0" - -[lints] -workspace = true - -[lib] -path = "src/test_extension.rs" -crate-type = ["cdylib"] - -[dependencies] -zed_extension_api = { path = "../../crates/extension_api" } diff --git a/extensions/test-extension/LICENSE-APACHE b/extensions/test-extension/LICENSE-APACHE deleted file mode 120000 index 1cd601d0a3affae83854be02a0afdec3b7a9ec4d..0000000000000000000000000000000000000000 --- a/extensions/test-extension/LICENSE-APACHE +++ /dev/null @@ -1 +0,0 @@ -../../LICENSE-APACHE \ No newline at end of file diff --git a/extensions/test-extension/README.md b/extensions/test-extension/README.md deleted file mode 100644 index 5941f23ec46716bc4bed992ca00bda500cda366a..0000000000000000000000000000000000000000 --- a/extensions/test-extension/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Test Extension - -This is a test extension that we use in the tests for the `extension` crate. - -Originally based off the Gleam extension. diff --git a/extensions/test-extension/extension.toml b/extensions/test-extension/extension.toml deleted file mode 100644 index 0cb5afac7f7031c7f2eb9db2fbbcef9d2e107b68..0000000000000000000000000000000000000000 --- a/extensions/test-extension/extension.toml +++ /dev/null @@ -1,25 +0,0 @@ -id = "test-extension" -name = "Test Extension" -description = "An extension for use in tests." -version = "0.1.0" -schema_version = 1 -authors = ["Marshall Bowers "] -repository = "https://github.com/zed-industries/zed" - -[language_servers.gleam] -name = "Gleam LSP" -language = "Gleam" - -[grammars.gleam] -repository = "https://github.com/gleam-lang/tree-sitter-gleam" -commit = "8432ffe32ccd360534837256747beb5b1c82fca1" - -[[capabilities]] -kind = "process:exec" -command = "echo" -args = ["hello from a child process!"] - -[[capabilities]] -kind = "process:exec" -command = "cmd" -args = ["/C", "echo", "hello from a child process!"] diff --git a/extensions/test-extension/languages/gleam/config.toml b/extensions/test-extension/languages/gleam/config.toml deleted file mode 100644 index 51874945e2de6b520a83f76c9302d1d95c824980..0000000000000000000000000000000000000000 --- a/extensions/test-extension/languages/gleam/config.toml +++ /dev/null @@ -1,12 +0,0 @@ -name = "Gleam" -grammar = "gleam" -path_suffixes = ["gleam"] -line_comments = ["// ", "/// "] -autoclose_before = ";:.,=}])>" -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, - { start = "\"", end = "\"", close = true, newline = false, not_in = ["string", "comment"] }, -] -tab_size = 2 diff --git a/extensions/test-extension/languages/gleam/highlights.scm b/extensions/test-extension/languages/gleam/highlights.scm deleted file mode 100644 index 4b85b88d0151a1bfe9018f0c526497261d6e1801..0000000000000000000000000000000000000000 --- a/extensions/test-extension/languages/gleam/highlights.scm +++ /dev/null @@ -1,130 +0,0 @@ -; Comments -(module_comment) @comment -(statement_comment) @comment -(comment) @comment - -; Constants -(constant - name: (identifier) @constant) - -; Variables -(identifier) @variable -(discard) @comment.unused - -; Modules -(module) @module -(import alias: (identifier) @module) -(remote_type_identifier - module: (identifier) @module) -(remote_constructor_name - module: (identifier) @module) -((field_access - record: (identifier) @module - field: (label) @function) - (#is-not? local)) - -; Functions -(unqualified_import (identifier) @function) -(unqualified_import "type" (type_identifier) @type) -(unqualified_import (type_identifier) @constructor) -(function - name: (identifier) @function) -(external_function - name: (identifier) @function) -(function_parameter - name: (identifier) @variable.parameter) -((function_call - function: (identifier) @function) - (#is-not? local)) -((binary_expression - operator: "|>" - right: (identifier) @function) - (#is-not? local)) - -; "Properties" -; Assumed to be intended to refer to a name for a field; something that comes -; before ":" or after "." -; e.g. record field names, tuple indices, names for named arguments, etc -(label) @property -(tuple_access - index: (integer) @property) - -; Attributes -(attribute - "@" @attribute - name: (identifier) @attribute) - -(attribute_value (identifier) @constant) - -; Type names -(remote_type_identifier) @type -(type_identifier) @type - -; Data constructors -(constructor_name) @constructor - -; Literals -(string) @string -((escape_sequence) @warning - ; Deprecated in v0.33.0-rc2: - (#eq? @warning "\\e")) -(escape_sequence) @string.escape -(bit_string_segment_option) @function.builtin -(integer) @number -(float) @number - -; Reserved identifiers -; TODO: when tree-sitter supports `#any-of?` in the Rust bindings, -; refactor this to use `#any-of?` rather than `#match?` -((identifier) @warning - (#match? @warning "^(auto|delegate|derive|else|implement|macro|test|echo)$")) - -; Keywords -[ - (visibility_modifier) ; "pub" - (opacity_modifier) ; "opaque" - "as" - "assert" - "case" - "const" - ; DEPRECATED: 'external' was removed in v0.30. - "external" - "fn" - "if" - "import" - "let" - "panic" - "todo" - "type" - "use" -] @keyword - -; Operators -(binary_expression - operator: _ @operator) -(boolean_negation "!" @operator) -(integer_negation "-" @operator) - -; Punctuation -[ - "(" - ")" - "[" - "]" - "{" - "}" - "<<" - ">>" -] @punctuation.bracket -[ - "." - "," - ;; Controversial -- maybe some are operators? - ":" - "#" - "=" - "->" - ".." - "-" - "<-" -] @punctuation.delimiter diff --git a/extensions/test-extension/languages/gleam/indents.scm b/extensions/test-extension/languages/gleam/indents.scm deleted file mode 100644 index 112b414aa45f277138d0c681851129a608ee96e0..0000000000000000000000000000000000000000 --- a/extensions/test-extension/languages/gleam/indents.scm +++ /dev/null @@ -1,3 +0,0 @@ -(_ "[" "]" @end) @indent -(_ "{" "}" @end) @indent -(_ "(" ")" @end) @indent diff --git a/extensions/test-extension/languages/gleam/outline.scm b/extensions/test-extension/languages/gleam/outline.scm deleted file mode 100644 index 5df7a6af800e8e3c9f0b00834576f2e059bd12b0..0000000000000000000000000000000000000000 --- a/extensions/test-extension/languages/gleam/outline.scm +++ /dev/null @@ -1,31 +0,0 @@ -(external_type - (visibility_modifier)? @context - "type" @context - (type_name) @name) @item - -(type_definition - (visibility_modifier)? @context - (opacity_modifier)? @context - "type" @context - (type_name) @name) @item - -(data_constructor - (constructor_name) @name) @item - -(data_constructor_argument - (label) @name) @item - -(type_alias - (visibility_modifier)? @context - "type" @context - (type_name) @name) @item - -(function - (visibility_modifier)? @context - "fn" @context - name: (_) @name) @item - -(constant - (visibility_modifier)? @context - "const" @context - name: (_) @name) @item diff --git a/extensions/test-extension/src/test_extension.rs b/extensions/test-extension/src/test_extension.rs deleted file mode 100644 index 0b96f470386fcc08a62b487cc36a448c4514854b..0000000000000000000000000000000000000000 --- a/extensions/test-extension/src/test_extension.rs +++ /dev/null @@ -1,209 +0,0 @@ -use std::fs; -use zed::lsp::CompletionKind; -use zed::{CodeLabel, CodeLabelSpan, LanguageServerId}; -use zed_extension_api::process::Command; -use zed_extension_api::{self as zed, Result}; - -struct TestExtension { - cached_binary_path: Option, -} - -impl TestExtension { - fn language_server_binary_path( - &mut self, - language_server_id: &LanguageServerId, - _worktree: &zed::Worktree, - ) -> Result { - let (platform, arch) = zed::current_platform(); - - let current_dir = std::env::current_dir().unwrap(); - println!("current_dir: {}", current_dir.display()); - assert_eq!( - current_dir.file_name().unwrap().to_str().unwrap(), - "test-extension" - ); - - fs::create_dir_all(current_dir.join("dir-created-with-abs-path")).unwrap(); - fs::create_dir_all("./dir-created-with-rel-path").unwrap(); - fs::write("file-created-with-rel-path", b"contents 1").unwrap(); - fs::write( - current_dir.join("file-created-with-abs-path"), - b"contents 2", - ) - .unwrap(); - assert_eq!( - fs::read("file-created-with-rel-path").unwrap(), - b"contents 1" - ); - assert_eq!( - fs::read("file-created-with-abs-path").unwrap(), - b"contents 2" - ); - - let command = match platform { - zed::Os::Linux | zed::Os::Mac => Command::new("echo"), - zed::Os::Windows => Command::new("cmd").args(["/C", "echo"]), - }; - let output = command.arg("hello from a child process!").output()?; - println!( - "command output: {}", - String::from_utf8_lossy(&output.stdout).trim() - ); - - if let Some(path) = &self.cached_binary_path - && fs::metadata(path).is_ok_and(|stat| stat.is_file()) - { - return Ok(path.clone()); - } - - zed::set_language_server_installation_status( - language_server_id, - &zed::LanguageServerInstallationStatus::CheckingForUpdate, - ); - let release = zed::latest_github_release( - "gleam-lang/gleam", - zed::GithubReleaseOptions { - require_assets: true, - pre_release: false, - }, - )?; - - let ext = "tar.gz"; - let download_type = zed::DownloadedFileType::GzipTar; - - // Do this if you want to actually run this extension - - // the actual asset is a .zip. But the integration test is simpler - // if every platform uses .tar.gz. - // - // ext = "zip"; - // download_type = zed::DownloadedFileType::Zip; - - let asset_name = format!( - "gleam-{version}-{arch}-{os}.{ext}", - version = release.version, - arch = match arch { - zed::Architecture::Aarch64 => "aarch64", - zed::Architecture::X86 => "x86", - zed::Architecture::X8664 => "x86_64", - }, - os = match platform { - zed::Os::Mac => "apple-darwin", - zed::Os::Linux => "unknown-linux-musl", - zed::Os::Windows => "pc-windows-msvc", - }, - ); - - let asset = release - .assets - .iter() - .find(|asset| asset.name == asset_name) - .ok_or_else(|| format!("no asset found matching {:?}", asset_name))?; - - let version_dir = format!("gleam-{}", release.version); - let binary_path = format!("{version_dir}/gleam"); - - if !fs::metadata(&binary_path).is_ok_and(|stat| stat.is_file()) { - zed::set_language_server_installation_status( - language_server_id, - &zed::LanguageServerInstallationStatus::Downloading, - ); - - zed::download_file(&asset.download_url, &version_dir, download_type) - .map_err(|e| format!("failed to download file: {e}"))?; - - zed::set_language_server_installation_status( - language_server_id, - &zed::LanguageServerInstallationStatus::None, - ); - - let entries = - fs::read_dir(".").map_err(|e| format!("failed to list working directory {e}"))?; - for entry in entries { - let entry = entry.map_err(|e| format!("failed to load directory entry {e}"))?; - let filename = entry.file_name(); - let filename = filename.to_str().unwrap(); - if filename.starts_with("gleam-") && filename != version_dir { - fs::remove_dir_all(entry.path()).ok(); - } - } - } - - self.cached_binary_path = Some(binary_path.clone()); - Ok(binary_path) - } -} - -impl zed::Extension for TestExtension { - fn new() -> Self { - Self { - cached_binary_path: None, - } - } - - fn language_server_command( - &mut self, - language_server_id: &LanguageServerId, - worktree: &zed::Worktree, - ) -> Result { - Ok(zed::Command { - command: self.language_server_binary_path(language_server_id, worktree)?, - args: vec!["lsp".to_string()], - env: Default::default(), - }) - } - - fn label_for_completion( - &self, - _language_server_id: &LanguageServerId, - completion: zed::lsp::Completion, - ) -> Option { - let name = &completion.label; - let ty = strip_newlines_from_detail(&completion.detail?); - let let_binding = "let a"; - let colon = ": "; - let assignment = " = "; - let call = match completion.kind? { - CompletionKind::Function | CompletionKind::Constructor => "()", - _ => "", - }; - let code = format!("{let_binding}{colon}{ty}{assignment}{name}{call}"); - - Some(CodeLabel { - spans: vec![ - CodeLabelSpan::code_range({ - let start = let_binding.len() + colon.len() + ty.len() + assignment.len(); - start..start + name.len() - }), - CodeLabelSpan::code_range({ - let start = let_binding.len(); - start..start + colon.len() - }), - CodeLabelSpan::code_range({ - let start = let_binding.len() + colon.len(); - start..start + ty.len() - }), - ], - filter_range: (0..name.len()).into(), - code, - }) - } -} - -zed::register_extension!(TestExtension); - -/// Removes newlines from the completion detail. -/// -/// The Gleam LSP can return types containing newlines, which causes formatting -/// issues within the Zed completions menu. -fn strip_newlines_from_detail(detail: &str) -> String { - let without_newlines = detail - .replace("->\n ", "-> ") - .replace("\n ", "") - .replace(",\n", ""); - - let comma_delimited_parts = without_newlines.split(','); - comma_delimited_parts - .map(|part| part.trim()) - .collect::>() - .join(", ") -} diff --git a/extensions/workflows/bump_version.yml b/extensions/workflows/bump_version.yml deleted file mode 100644 index 7f4318dcf54ad8c9360ae622354530b2b54c6a03..0000000000000000000000000000000000000000 --- a/extensions/workflows/bump_version.yml +++ /dev/null @@ -1,52 +0,0 @@ -# Generated from xtask::workflows::extensions::bump_version within the Zed repository. -# Rebuild with `cargo xtask workflows`. -name: extensions::bump_version -on: - pull_request: - types: - - labeled - push: - branches: - - main - paths-ignore: - - .github/** - workflow_dispatch: {} -jobs: - determine_bump_type: - runs-on: namespace-profile-16x32-ubuntu-2204 - steps: - - id: get-bump-type - name: extensions::bump_version::get_bump_type - run: | - if [ "$HAS_MAJOR_LABEL" = "true" ]; then - bump_type="major" - elif [ "$HAS_MINOR_LABEL" = "true" ]; then - bump_type="minor" - else - bump_type="patch" - fi - echo "bump_type=$bump_type" >> $GITHUB_OUTPUT - shell: bash -euxo pipefail {0} - env: - HAS_MAJOR_LABEL: |- - ${{ (github.event.action == 'labeled' && github.event.label.name == 'major') || - (github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'major')) }} - HAS_MINOR_LABEL: |- - ${{ (github.event.action == 'labeled' && github.event.label.name == 'minor') || - (github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'minor')) }} - outputs: - bump_type: ${{ steps.get-bump-type.outputs.bump_type }} - call_bump_version: - needs: - - determine_bump_type - if: github.event.action != 'labeled' || needs.determine_bump_type.outputs.bump_type != 'patch' - uses: zed-industries/zed/.github/workflows/extension_bump.yml@main - secrets: - app-id: ${{ secrets.ZED_ZIPPY_APP_ID }} - app-secret: ${{ secrets.ZED_ZIPPY_APP_PRIVATE_KEY }} - with: - bump-type: ${{ needs.determine_bump_type.outputs.bump_type }} - force-bump: true -concurrency: - group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}labels - cancel-in-progress: true diff --git a/extensions/workflows/release_version.yml b/extensions/workflows/release_version.yml deleted file mode 100644 index f752931917292110580a74198d3e1231098539db..0000000000000000000000000000000000000000 --- a/extensions/workflows/release_version.yml +++ /dev/null @@ -1,13 +0,0 @@ -# Generated from xtask::workflows::extensions::release_version within the Zed repository. -# Rebuild with `cargo xtask workflows`. -name: extensions::release_version -on: - push: - tags: - - v** -jobs: - call_release_version: - uses: zed-industries/zed/.github/workflows/extension_release.yml@main - secrets: - app-id: ${{ secrets.ZED_ZIPPY_APP_ID }} - app-secret: ${{ secrets.ZED_ZIPPY_APP_PRIVATE_KEY }} diff --git a/extensions/workflows/run_tests.yml b/extensions/workflows/run_tests.yml deleted file mode 100644 index 81ba76c483479ed827f0a91181557a2387b40722..0000000000000000000000000000000000000000 --- a/extensions/workflows/run_tests.yml +++ /dev/null @@ -1,16 +0,0 @@ -# Generated from xtask::workflows::extensions::run_tests within the Zed repository. -# Rebuild with `cargo xtask workflows`. -name: extensions::run_tests -on: - pull_request: - branches: - - '**' - push: - branches: - - main -jobs: - call_extension_tests: - uses: zed-industries/zed/.github/workflows/extension_tests.yml@main -concurrency: - group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}pr - cancel-in-progress: true