From 8366cd0b525f9646300cfe349799d413e42b8d7d Mon Sep 17 00:00:00 2001 From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com> Date: Wed, 23 Apr 2025 15:43:33 -0300 Subject: [PATCH] agent: Render diffs for the edit file tool (#29234) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR implements the `ToolCard` for the edit file tool, which allow us to display an editor with a diff in the thread view with the changes performed by the model. - [x] Fix buffer sometimes displaying empty - [x] Stop buffer from scrolling together with the thread - [x] Fix multibuffer header sometimes appearing - [x] Fix buffer height issue - [x] Implement "full height" expand button - [x] Add "Jump To File" functionality - [x] Polish and refine styles Release Notes: - agent: Added diff preview cards in the thread view for edits performed by the agent. --------- Co-authored-by: João Marcos Co-authored-by: Richard Feldman Co-authored-by: Agus Zubiaga Co-authored-by: Conrad Irwin --- Cargo.lock | 402 ++++++++++----- crates/agent/src/active_thread.rs | 98 ++-- crates/agent/src/assistant_panel.rs | 9 +- crates/agent/src/message_editor.rs | 10 +- crates/agent/src/thread.rs | 45 +- crates/assistant_tool/Cargo.toml | 1 + crates/assistant_tool/src/assistant_tool.rs | 22 +- crates/assistant_tools/Cargo.toml | 3 + crates/assistant_tools/src/batch_tool.rs | 7 +- .../assistant_tools/src/code_action_tool.rs | 3 +- .../assistant_tools/src/code_symbols_tool.rs | 3 +- crates/assistant_tools/src/contents_tool.rs | 3 +- crates/assistant_tools/src/copy_path_tool.rs | 2 + .../src/create_directory_tool.rs | 2 + .../assistant_tools/src/create_file_tool.rs | 2 + .../assistant_tools/src/delete_path_tool.rs | 3 +- .../assistant_tools/src/diagnostics_tool.rs | 3 +- crates/assistant_tools/src/edit_file_tool.rs | 465 ++++++++++++++++-- crates/assistant_tools/src/fetch_tool.rs | 3 +- crates/assistant_tools/src/grep_tool.rs | 5 +- .../src/list_directory_tool.rs | 3 +- crates/assistant_tools/src/move_path_tool.rs | 3 +- crates/assistant_tools/src/now_tool.rs | 3 +- crates/assistant_tools/src/open_tool.rs | 3 +- .../assistant_tools/src/path_search_tool.rs | 3 +- crates/assistant_tools/src/read_file_tool.rs | 14 +- crates/assistant_tools/src/rename_tool.rs | 3 +- .../assistant_tools/src/symbol_info_tool.rs | 3 +- crates/assistant_tools/src/terminal_tool.rs | 3 +- crates/assistant_tools/src/thinking_tool.rs | 3 +- crates/assistant_tools/src/web_search_tool.rs | 34 +- .../context_server/src/context_server_tool.rs | 3 +- crates/editor/src/editor.rs | 17 + crates/editor/src/editor_tests.rs | 1 + crates/editor/src/element.rs | 23 +- crates/eval/src/example.rs | 2 +- crates/gpui/src/app/entity_map.rs | 34 +- crates/task/src/vscode_debug_format.rs | 1 - crates/vim/Cargo.toml | 2 +- tooling/workspace-hack/Cargo.toml | 70 +-- 40 files changed, 1003 insertions(+), 316 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0c415bdb8c..4881cb020a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -232,13 +232,13 @@ checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b" [[package]] name = "ammonia" -version = "4.0.0" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab99eae5ee58501ab236beb6f20f6ca39be615267b014899c89b2f0bc18a459" +checksum = "3ada2ee439075a3e70b6992fce18ac4e407cd05aea9ca3f75d2c0b0c20bbb364" dependencies = [ - "html5ever", + "cssparser", + "html5ever 0.31.0", "maplit", - "once_cell", "tendril", "url", ] @@ -432,7 +432,7 @@ dependencies = [ "enumflags2", "futures-channel", "futures-util", - "rand 0.9.0", + "rand 0.9.1", "serde", "serde_repr", "url", @@ -693,6 +693,7 @@ dependencies = [ "settings", "text", "util", + "workspace", "workspace-hack", ] @@ -702,11 +703,13 @@ version = "0.1.0" dependencies = [ "anyhow", "assistant_tool", + "buffer_diff", "chrono", "client", "clock", "collections", "component", + "editor", "futures 0.3.31", "gpui", "html_to_markdown", @@ -1306,9 +1309,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.28.0" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f7720b74ed28ca77f90769a71fd8c637a0137f6fae4ae947e1050229cff57f" +checksum = "bfa9b6986f250236c27e5a204062434a773a13243d2ffc2955f37bdba4c5c6a1" dependencies = [ "bindgen 0.69.5", "cc", @@ -1602,7 +1605,7 @@ dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", "aws-smithy-types", - "h2 0.4.8", + "h2 0.4.9", "http 0.2.12", "http 1.3.1", "http-body 0.4.6", @@ -2107,9 +2110,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389a099b34312839e16420d499a9cad9650541715937ffbdd40d36f49e77eeb3" +checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" dependencies = [ "arrayref", "arrayvec", @@ -2203,9 +2206,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.11.3" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" +checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" dependencies = [ "memchr", "regex-automata 0.4.9", @@ -2421,9 +2424,9 @@ dependencies = [ [[package]] name = "cap-fs-ext" -version = "3.4.3" +version = "3.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6323b9baffb4d6d9c65bfef3129db62b1391f7fb953fe67c0d7cb0804feb77b" +checksum = "e41cc18551193fe8fa6f15c1e3c799bc5ec9e2cfbfaa8ed46f37013e3e6c173c" dependencies = [ "cap-primitives", "cap-std", @@ -2433,21 +2436,21 @@ dependencies = [ [[package]] name = "cap-net-ext" -version = "3.4.3" +version = "3.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66022e5e076ea27041a05ebd4349022e2133e6f4977974dffd54ceb7b982e871" +checksum = "9f83833816c66c986e913b22ac887cec216ea09301802054316fc5301809702c" dependencies = [ "cap-primitives", "cap-std", - "rustix 0.38.44", + "rustix 1.0.5", "smallvec", ] [[package]] name = "cap-primitives" -version = "3.4.3" +version = "3.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50ad0183a9659850877cefe8f5b87d564b2dd1fe78b18945813687f29c0a6878" +checksum = "0a1e394ed14f39f8bc26f59d4c0c010dbe7f0a1b9bafff451b1f98b67c8af62a" dependencies = [ "ambient-authority", "fs-set-times", @@ -2455,16 +2458,17 @@ dependencies = [ "io-lifetimes", "ipnet", "maybe-owned", - "rustix 0.38.44", + "rustix 1.0.5", + "rustix-linux-procfs", "windows-sys 0.59.0", "winx", ] [[package]] name = "cap-rand" -version = "3.4.3" +version = "3.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab78a9f6301e70c0fe5df7328adbcb9228277fdb7bab36f312fc072f505e38c2" +checksum = "0acb89ccf798a28683f00089d0630dfaceec087234eae0d308c05ddeaa941b40" dependencies = [ "ambient-authority", "rand 0.8.5", @@ -2472,27 +2476,27 @@ dependencies = [ [[package]] name = "cap-std" -version = "3.4.3" +version = "3.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c41814365b796ed12688026cb90a1e03236a84ccf009628f9c43c8aa3af250a" +checksum = "07c0355ca583dd58f176c3c12489d684163861ede3c9efa6fd8bba314c984189" dependencies = [ "cap-primitives", "io-extras", "io-lifetimes", - "rustix 0.38.44", + "rustix 1.0.5", ] [[package]] name = "cap-time-ext" -version = "3.4.3" +version = "3.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb57b71bb69b97c638ec38b477e9b33fa1c1cff0e437dd55d15c117cf17ed5dc" +checksum = "491af520b8770085daa0466978c75db90368c71896523f2464214e38359b1a5b" dependencies = [ "ambient-authority", "cap-primitives", "iana-time-zone", "once_cell", - "rustix 0.38.44", + "rustix 1.0.5", "winx", ] @@ -2564,9 +2568,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.18" +version = "1.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c" +checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362" dependencies = [ "jobserver", "libc", @@ -2727,9 +2731,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.36" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2df961d8c8a0d08aa9945718ccf584145eee3f3aa06cddbeac12933781102e04" +checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" dependencies = [ "clap_builder", "clap_derive", @@ -2737,9 +2741,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.36" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "132dbda40fb6753878316a489d5a1242a8ef2f0d9e47ba01c951ea8aa7d013a5" +checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" dependencies = [ "anstream", "anstyle", @@ -3822,9 +3826,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.14" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] @@ -3903,10 +3907,33 @@ dependencies = [ ] [[package]] -name = "ctor" -version = "0.4.1" +name = "cssparser" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e9666f4a9a948d4f1dff0c08a4512b0f7c86414b23960104c243c10d79f4c3" +checksum = "4e901edd733a1472f944a45116df3f846f54d37e67e68640ac8bb69689aca2aa" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn 2.0.100", +] + +[[package]] +name = "ctor" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4735f265ba6a1188052ca32d461028a7d1125868be18e287e756019da7607b5" dependencies = [ "ctor-proc-macro", "dtor", @@ -3936,9 +3963,9 @@ checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" [[package]] name = "cxx" -version = "1.0.153" +version = "1.0.157" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b4ab2681454aacfe7ce296ebc6df86791009f237f8020b0c752e8b245ba7c1d" +checksum = "3d6354e975ea4ec28033ec3a36fa9baa1a02e3eb22ad740eeb4929370d4f5ba8" dependencies = [ "cc", "cxxbridge-cmd", @@ -3950,9 +3977,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.153" +version = "1.0.157" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e431f7ba795550f2b11c32509b3b35927d899f0ad13a1d1e030a317a08facbe" +checksum = "8b4400e26ea4b99417e4263b1ce2d8452404d750ba0809a7bd043072593d430d" dependencies = [ "cc", "codespan-reporting 0.12.0", @@ -3964,9 +3991,9 @@ dependencies = [ [[package]] name = "cxxbridge-cmd" -version = "1.0.153" +version = "1.0.157" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cbc41933767955d04c2a90151806029b93df5fd8b682ba22a967433347480a9" +checksum = "31860c98f69fc14da5742c5deaf78983e846c7b27804ca8c8319e32eef421bde" dependencies = [ "clap", "codespan-reporting 0.12.0", @@ -3977,15 +4004,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.153" +version = "1.0.157" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9133547634329a5b76e5f58d1e53c16d627699bbcd421b9007796311165f9667" +checksum = "b0402a66013f3b8d3d9f2d7c9994656cc81e671054822b0728d7454d9231892f" [[package]] name = "cxxbridge-macro" -version = "1.0.153" +version = "1.0.157" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e89d77ad5fd6066a3d42d94de3f72a2f23f95006da808177624429b5183596" +checksum = "64c0b38f32d68f3324a981645ee39b2d686af36d03c98a386df3716108c9feae" dependencies = [ "proc-macro2", "quote", @@ -4124,9 +4151,9 @@ checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" [[package]] name = "data-encoding" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "data-url" @@ -4252,9 +4279,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid", "pem-rfc7468", @@ -4263,9 +4290,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.4.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cfac68e08048ae1883171632c2aef3ebc555621ae56fbccce1cbf22dd7f058" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", "serde", @@ -4408,6 +4435,15 @@ dependencies = [ "dirs-sys 0.4.1", ] +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys 0.5.0", +] + [[package]] name = "dirs-sys" version = "0.3.7" @@ -4415,7 +4451,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", - "redox_users", + "redox_users 0.4.6", "winapi", ] @@ -4427,10 +4463,22 @@ checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", "option-ext", - "redox_users", + "redox_users 0.4.6", "windows-sys 0.48.0", ] +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users 0.5.0", + "windows-sys 0.59.0", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -4520,10 +4568,25 @@ dependencies = [ ] [[package]] -name = "dtor" -version = "0.0.5" +name = "dtoa" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222ef136a1c687d4aa0395c175f2c4586e379924c352fd02f7870cf7de783c23" +checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "dtor" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97cbdf2ad6846025e8e25df05171abfb30e3ababa12ee0a0e44b9bbe570633a8" dependencies = [ "dtor-proc-macro", ] @@ -4560,9 +4623,9 @@ checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" [[package]] name = "ec4rs" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf65d056c7da9c971c2847ce250fd1f0f9659d5718845c3ec0ad95f5668352c" +checksum = "3b31a881d38439026e3d5dd938ab20328d36e23caca8fd5981c42e4b677f5842" [[package]] name = "ecdsa" @@ -6246,9 +6309,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2" +checksum = "75249d144030531f8dee69fe9cea04d3edf809a017ae445e2abdff6629e86633" dependencies = [ "atomic-waker", "bytes 1.10.1", @@ -6265,9 +6328,9 @@ dependencies = [ [[package]] name = "half" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7db2ff139bba50379da6aa0766b52fdcb62cb5b263009b09ed58ba604e14bbd1" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" dependencies = [ "cfg-if", "crunchy", @@ -6520,18 +6583,30 @@ checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" dependencies = [ "log", "mac", - "markup5ever", + "markup5ever 0.12.1", "proc-macro2", "quote", "syn 2.0.100", ] +[[package]] +name = "html5ever" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953cbbe631aae7fc0a112702ad5d3aaf09da38beaf45ea84610d6e1c358f569c" +dependencies = [ + "log", + "mac", + "markup5ever 0.16.1", + "match_token", +] + [[package]] name = "html_to_markdown" version = "0.1.0" dependencies = [ "anyhow", - "html5ever", + "html5ever 0.27.0", "indoc", "markup5ever_rcdom", "pretty_assertions", @@ -6704,7 +6779,7 @@ dependencies = [ "bytes 1.10.1", "futures-channel", "futures-util", - "h2 0.4.8", + "h2 0.4.9", "http 1.3.1", "http-body 1.0.1", "httparse", @@ -7086,9 +7161,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -7387,9 +7462,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" -version = "0.2.5" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c102670231191d07d37a35af3eb77f1f0dbf7a71be51a962dcd57ea607be7260" +checksum = "5a064218214dc6a10fbae5ec5fa888d80c45d611aba169222fc272072bf7aef6" dependencies = [ "jiff-static", "log", @@ -7400,9 +7475,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.5" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cdde31a9d349f1b1f51a0b3714a5940ac022976f4b49485fc04be052b183b4c" +checksum = "199b7932d97e325aff3a7030e141eafe7f2c6268e1d1b24859b753a627f45254" dependencies = [ "proc-macro2", "quote", @@ -7969,7 +8044,7 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.9.0", "libc", - "redox_syscall 0.5.10", + "redox_syscall 0.5.11", ] [[package]] @@ -8064,9 +8139,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "litemap" @@ -8110,7 +8185,7 @@ dependencies = [ "parking_lot", "pbjson-types", "prost 0.12.6", - "rand 0.9.0", + "rand 0.9.1", "reqwest 0.11.27", "scopeguard", "serde", @@ -8447,18 +8522,40 @@ dependencies = [ "tendril", ] +[[package]] +name = "markup5ever" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a8096766c229e8c88a3900c9b44b7e06aa7f7343cc229158c3e58ef8f9973a" +dependencies = [ + "log", + "tendril", + "web_atoms", +] + [[package]] name = "markup5ever_rcdom" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edaa21ab3701bfee5099ade5f7e1f84553fd19228cf332f13cd6e964bf59be18" dependencies = [ - "html5ever", - "markup5ever", + "html5ever 0.27.0", + "markup5ever 0.12.1", "tendril", "xml5ever", ] +[[package]] +name = "match_token" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + [[package]] name = "matchers" version = "0.1.0" @@ -8657,9 +8754,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", "simd-adler32", @@ -9181,7 +9278,7 @@ dependencies = [ [[package]] name = "nvim-rs" version = "0.9.2" -source = "git+https://github.com/KillTheMule/nvim-rs?branch=master#764dd270c642f77f10f3e19d05cc178a6cbe69f3" +source = "git+https://github.com/KillTheMule/nvim-rs?rev=764dd270c642f77f10f3e19d05cc178a6cbe69f3#764dd270c642f77f10f3e19d05cc178a6cbe69f3" dependencies = [ "async-trait", "futures 0.3.31", @@ -9512,7 +9609,7 @@ dependencies = [ "num", "num-bigint-dig", "pbkdf2 0.12.2", - "rand 0.9.0", + "rand 0.9.1", "serde", "sha2", "subtle", @@ -9832,7 +9929,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.10", + "redox_syscall 0.5.11", "smallvec", "windows-targets 0.52.6", ] @@ -10560,7 +10657,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" dependencies = [ - "der 0.7.9", + "der 0.7.10", "pkcs8 0.10.2", "spki 0.7.3", ] @@ -10581,7 +10678,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.9", + "der 0.7.10", "spki 0.7.3", ] @@ -10763,9 +10860,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.31" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5316f57387668042f561aae71480de936257848f9c43ce528e311d89a07cadeb" +checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6" dependencies = [ "proc-macro2", "syn 2.0.100", @@ -11315,7 +11412,7 @@ checksum = "b820744eb4dc9b57a3398183639c511b5a26d2ed702cedd3febaa1393caa22cc" dependencies = [ "bytes 1.10.1", "getrandom 0.3.2", - "rand 0.9.0", + "rand 0.9.1", "ring", "rustc-hash 2.1.1", "rustls 0.23.26", @@ -11388,13 +11485,12 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", - "zerocopy 0.8.24", ] [[package]] @@ -11506,9 +11602,9 @@ dependencies = [ [[package]] name = "ravif" -version = "0.11.11" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2413fd96bd0ea5cdeeb37eaf446a22e6ed7b981d792828721e74ded1980a45c6" +checksum = "d6a5f31fcf7500f9401fea858ea4ab5525c99f2322cfcee732c0e6c74208c0c6" dependencies = [ "avif-serialize", "imgref", @@ -11616,9 +11712,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" dependencies = [ "bitflags 2.9.0", ] @@ -11634,6 +11730,17 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "redox_users" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +dependencies = [ + "getrandom 0.2.15", + "libredox", + "thiserror 2.0.12", +] + [[package]] name = "refineable" version = "0.1.0" @@ -11913,7 +12020,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2 0.4.8", + "h2 0.4.9", "http 1.3.1", "http-body 1.0.1", "http-body-util", @@ -11971,9 +12078,9 @@ dependencies = [ [[package]] name = "resvg" -version = "0.45.0" +version = "0.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd43d1c474e9dadf09a8fdf22d713ba668b499b5117b9b9079500224e26b5b29" +checksum = "a8928798c0a55e03c9ca6c4c6846f76377427d2c1e1f7e6de3c06ae57942df43" dependencies = [ "log", "pico-args", @@ -12182,7 +12289,7 @@ dependencies = [ "ring", "serde", "serde_json", - "shellexpand 3.1.0", + "shellexpand 3.1.1", "smol", "uuid", "zeromq", @@ -12190,9 +12297,9 @@ dependencies = [ [[package]] name = "rust-embed" -version = "8.6.0" +version = "8.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b3aba5104622db5c9fc61098de54708feb732e7763d7faa2fa625899f00bf6f" +checksum = "e5fbc0ee50fcb99af7cebb442e5df7b5b45e9460ffa3f8f549cd26b862bec49d" dependencies = [ "rust-embed-impl", "rust-embed-utils", @@ -12201,9 +12308,9 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "8.6.0" +version = "8.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f198c73be048d2c5aa8e12f7960ad08443e56fd39cc26336719fdb4ea0ebaae" +checksum = "6bf418c9a2e3f6663ca38b8a7134cc2c2167c9d69688860e8961e3faa731702e" dependencies = [ "proc-macro2", "quote", @@ -12214,9 +12321,9 @@ dependencies = [ [[package]] name = "rust-embed-utils" -version = "8.6.0" +version = "8.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a2fcdc9f40c8dc2922842ca9add611ad19f332227fc651d015881ad1552bd9a" +checksum = "08d55b95147fe01265d06b3955db798bdaed52e60e2211c41137701b3aba8e21" dependencies = [ "globset", "sha2", @@ -12277,7 +12384,6 @@ dependencies = [ "itoa", "libc", "linux-raw-sys 0.4.15", - "once_cell", "windows-sys 0.59.0", ] @@ -12290,10 +12396,20 @@ dependencies = [ "bitflags 2.9.0", "errno 0.3.11", "libc", - "linux-raw-sys 0.9.3", + "linux-raw-sys 0.9.4", "windows-sys 0.59.0", ] +[[package]] +name = "rustix-linux-procfs" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fc84bf7e9aa16c4f2c758f27412dc9841341e16aa682d9c7ac308fe3ee12056" +dependencies = [ + "once_cell", + "rustix 1.0.5", +] + [[package]] name = "rustix-openpty" version = "0.1.1" @@ -12688,9 +12804,9 @@ dependencies = [ [[package]] name = "sea-query" -version = "0.32.3" +version = "0.32.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5a24d8b9fcd2674a6c878a3d871f4f1380c6c43cc3718728ac96864d888458e" +checksum = "d99447c24da0cded00089e2021e1624af90878c65f7534319448d01da3df869d" dependencies = [ "bigdecimal", "chrono", @@ -12805,9 +12921,9 @@ dependencies = [ [[package]] name = "self_cell" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2fdfc24bc566f839a2da4c4295b82db7d25a24253867d5c64355abb5799bdbe" +checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749" [[package]] name = "semantic_index" @@ -13112,11 +13228,11 @@ dependencies = [ [[package]] name = "shellexpand" -version = "3.1.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da03fa3b94cc19e3ebfc88c4229c49d8f08cdbd1228870a45f0ffdf84988e14b" +checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb" dependencies = [ - "dirs 5.0.1", + "dirs 6.0.0", ] [[package]] @@ -13137,9 +13253,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ "libc", ] @@ -13260,9 +13376,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" dependencies = [ "serde", ] @@ -13409,7 +13525,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der 0.7.9", + "der 0.7.10", ] [[package]] @@ -13974,9 +14090,9 @@ dependencies = [ [[package]] name = "svg_fmt" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce5d813d71d82c4cbc1742135004e4a79fd870214c155443451c139c9470a0aa" +checksum = "0193cc4331cfd2f3d2011ef287590868599a2f33c3e69bc22c1a3d3acf9e02fb" [[package]] name = "svgtypes" @@ -15429,7 +15545,7 @@ dependencies = [ "http 1.3.1", "httparse", "log", - "rand 0.9.0", + "rand 0.9.1", "rustls 0.23.26", "rustls-pki-types", "sha1", @@ -15667,9 +15783,9 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] name = "usvg" -version = "0.45.0" +version = "0.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ac8e0e3e4696253dc06167990b3fe9a2668ab66270adf949a464db4088cb354" +checksum = "80be9b06fbae3b8b303400ab20778c80bbaf338f563afe567cf3c9eea17b47ef" dependencies = [ "base64 0.22.1", "data-url", @@ -16614,6 +16730,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web_atoms" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "954c5a41f2bcb7314344079d0891505458cc2f4b422bdea1d5bfbe6d1a04903b" +dependencies = [ + "phf", + "phf_codegen", + "string_cache", + "string_cache_codegen", +] + [[package]] name = "web_search" version = "0.1.0" @@ -16749,7 +16877,7 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7" dependencies = [ - "redox_syscall 0.5.10", + "redox_syscall 0.5.11", "wasite", ] @@ -16889,16 +17017,17 @@ dependencies = [ [[package]] name = "windows-capture" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6001b777f61cafce437201de46a019ed7f4afed3b669f02e5ce4e0759164cb3e" +checksum = "59d10b4be8b907c7055bc7270dd68d2b920978ffacc1599dcb563a79f0e68d16" dependencies = [ "clap", "ctrlc", "parking_lot", "rayon", - "thiserror 1.0.69", - "windows 0.58.0", + "thiserror 2.0.12", + "windows 0.61.1", + "windows-future", ] [[package]] @@ -17334,9 +17463,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" +checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" dependencies = [ "memchr", ] @@ -17783,6 +17912,7 @@ dependencies = [ "libc", "libsqlite3-sys", "linux-raw-sys 0.4.15", + "linux-raw-sys 0.9.4", "log", "lyon", "lyon_path", @@ -17809,7 +17939,7 @@ dependencies = [ "prost-types 0.9.0", "quote", "rand 0.8.5", - "rand 0.9.0", + "rand 0.9.1", "rand_core 0.6.4", "regex", "regex-automata 0.4.9", @@ -18060,7 +18190,7 @@ checksum = "9bbb26405d8e919bc1547a5aa9abc95cbfa438f04844f5fdd9dc7596b748bf69" dependencies = [ "log", "mac", - "markup5ever", + "markup5ever 0.12.1", ] [[package]] diff --git a/crates/agent/src/active_thread.rs b/crates/agent/src/active_thread.rs index 51181a0d57..596b127569 100644 --- a/crates/agent/src/active_thread.rs +++ b/crates/agent/src/active_thread.rs @@ -433,47 +433,39 @@ fn render_markdown_code_block( workspace .update(cx, { |workspace, cx| { - if let Some(project_path) = workspace + let Some(project_path) = workspace .project() .read(cx) .find_project_path(&path_range.path, cx) - { - let target = path_range.range.as_ref().map(|range| { - Point::new( - // Line number is 1-based - range.start.line.saturating_sub(1), - range.start.col.unwrap_or(0), - ) - }); - let open_task = workspace.open_path( - project_path, - None, - true, - window, - cx, - ); - window - .spawn(cx, async move |cx| { - let item = open_task.await?; - if let Some(target) = target { - if let Some(active_editor) = - item.downcast::() - { - active_editor - .downgrade() - .update_in(cx, |editor, window, cx| { - editor - .go_to_singleton_buffer_point( - target, window, cx, - ); - }) - .log_err(); - } - } - anyhow::Ok(()) - }) - .detach_and_log_err(cx); - } + else { + return; + }; + let Some(target) = path_range.range.as_ref().map(|range| { + Point::new( + // Line number is 1-based + range.start.line.saturating_sub(1), + range.start.col.unwrap_or(0), + ) + }) else { + return; + }; + let open_task = + workspace.open_path(project_path, None, true, window, cx); + window + .spawn(cx, async move |cx| { + let item = open_task.await?; + if let Some(active_editor) = item.downcast::() { + active_editor + .update_in(cx, |editor, window, cx| { + editor.go_to_singleton_buffer_point( + target, window, cx, + ); + }) + .ok(); + } + anyhow::Ok(()) + }) + .detach_and_log_err(cx); } }) .ok(); @@ -807,10 +799,11 @@ impl ActiveThread { self.thread.read(cx).summary_or_default() } - pub fn cancel_last_completion(&mut self, cx: &mut App) -> bool { + pub fn cancel_last_completion(&mut self, window: &mut Window, cx: &mut App) -> bool { self.last_error.take(); - self.thread - .update(cx, |thread, cx| thread.cancel_last_completion(cx)) + self.thread.update(cx, |thread, cx| { + thread.cancel_last_completion(Some(window.window_handle()), cx) + }) } pub fn last_error(&self) -> Option { @@ -1314,7 +1307,7 @@ impl ActiveThread { fn confirm_editing_message( &mut self, _: &menu::Confirm, - _: &mut Window, + window: &mut Window, cx: &mut Context, ) { let Some((message_id, state)) = self.editing_message.take() else { @@ -1344,7 +1337,7 @@ impl ActiveThread { self.thread.update(cx, |thread, cx| { thread.advance_prompt_id(); - thread.send_to_model(model.model, cx) + thread.send_to_model(model.model, Some(window.window_handle()), cx); }); cx.notify(); } @@ -1850,11 +1843,9 @@ impl ActiveThread { .gap_2() .children(message_content) .when(has_tool_uses, |parent| { - parent.children( - tool_uses - .into_iter() - .map(|tool_use| self.render_tool_use(tool_use, window, cx)), - ) + parent.children(tool_uses.into_iter().map(|tool_use| { + self.render_tool_use(tool_use, window, workspace.clone(), cx) + })) }), Role::System => div().id(("message-container", ix)).py_1().px_2().child( v_flex() @@ -2447,10 +2438,11 @@ impl ActiveThread { &self, tool_use: ToolUse, window: &mut Window, + workspace: WeakEntity, cx: &mut Context, ) -> impl IntoElement + use<> { if let Some(card) = self.thread.read(cx).card_for_tool(&tool_use.id) { - return card.render(&tool_use.status, window, cx); + return card.render(&tool_use.status, window, workspace, cx); } let is_open = self @@ -3047,7 +3039,7 @@ impl ActiveThread { &mut self, tool_use_id: LanguageModelToolUseId, _: &ClickEvent, - _window: &mut Window, + window: &mut Window, cx: &mut Context, ) { if let Some(PendingToolUseStatus::NeedsConfirmation(c)) = self @@ -3063,6 +3055,7 @@ impl ActiveThread { c.input.clone(), &c.messages, c.tool.clone(), + Some(window.window_handle()), cx, ); }); @@ -3074,11 +3067,12 @@ impl ActiveThread { tool_use_id: LanguageModelToolUseId, tool_name: Arc, _: &ClickEvent, - _window: &mut Window, + window: &mut Window, cx: &mut Context, ) { + let window_handle = window.window_handle(); self.thread.update(cx, |thread, cx| { - thread.deny_tool_use(tool_use_id, tool_name, cx); + thread.deny_tool_use(tool_use_id, tool_name, Some(window_handle), cx); }); } diff --git a/crates/agent/src/assistant_panel.rs b/crates/agent/src/assistant_panel.rs index f63bb4824e..a3f6fb56e7 100644 --- a/crates/agent/src/assistant_panel.rs +++ b/crates/agent/src/assistant_panel.rs @@ -356,14 +356,9 @@ impl AssistantPanel { &self.thread_store } - fn cancel( - &mut self, - _: &editor::actions::Cancel, - _window: &mut Window, - cx: &mut Context, - ) { + fn cancel(&mut self, _: &editor::actions::Cancel, window: &mut Window, cx: &mut Context) { self.thread - .update(cx, |thread, cx| thread.cancel_last_completion(cx)); + .update(cx, |thread, cx| thread.cancel_last_completion(window, cx)); } fn new_thread(&mut self, action: &NewThread, window: &mut Window, cx: &mut Context) { diff --git a/crates/agent/src/message_editor.rs b/crates/agent/src/message_editor.rs index 14f7e6de40..05599b536b 100644 --- a/crates/agent/src/message_editor.rs +++ b/crates/agent/src/message_editor.rs @@ -195,6 +195,7 @@ impl MessageEditor { editor.set_mode(EditorMode::Full { scale_ui_elements_with_buffer_font_size: false, show_active_line_background: false, + sized_by_content: false, }) } else { editor.set_mode(EditorMode::AutoHeight { @@ -277,6 +278,7 @@ impl MessageEditor { let context_store = self.context_store.clone(); let git_store = self.project.read(cx).git_store().clone(); let checkpoint = git_store.update(cx, |git_store, cx| git_store.checkpoint(cx)); + let window_handle = window.window_handle(); cx.spawn(async move |this, cx| { let checkpoint = checkpoint.await.ok(); @@ -333,7 +335,7 @@ impl MessageEditor { thread .update(cx, |thread, cx| { thread.advance_prompt_id(); - thread.send_to_model(model, cx); + thread.send_to_model(model, Some(window_handle), cx); }) .log_err(); }) @@ -341,9 +343,9 @@ impl MessageEditor { } fn stop_current_and_send_new_message(&mut self, window: &mut Window, cx: &mut Context) { - let cancelled = self - .thread - .update(cx, |thread, cx| thread.cancel_last_completion(cx)); + let cancelled = self.thread.update(cx, |thread, cx| { + thread.cancel_last_completion(Some(window.window_handle()), cx) + }); if cancelled { self.set_editor_is_expanded(false, cx); diff --git a/crates/agent/src/thread.rs b/crates/agent/src/thread.rs index 65c8690c09..5cbe49c8bc 100644 --- a/crates/agent/src/thread.rs +++ b/crates/agent/src/thread.rs @@ -13,7 +13,9 @@ use feature_flags::{self, FeatureFlagAppExt}; use futures::future::Shared; use futures::{FutureExt, StreamExt as _}; use git::repository::DiffType; -use gpui::{App, AppContext, Context, Entity, EventEmitter, SharedString, Task, WeakEntity}; +use gpui::{ + AnyWindowHandle, App, AppContext, Context, Entity, EventEmitter, SharedString, Task, WeakEntity, +}; use language_model::{ ConfiguredModel, LanguageModel, LanguageModelCompletionEvent, LanguageModelId, LanguageModelImage, LanguageModelKnownError, LanguageModelRegistry, LanguageModelRequest, @@ -951,7 +953,12 @@ impl Thread { self.remaining_turns = remaining_turns; } - pub fn send_to_model(&mut self, model: Arc, cx: &mut Context) { + pub fn send_to_model( + &mut self, + model: Arc, + window: Option, + cx: &mut Context, + ) { if self.remaining_turns == 0 { return; } @@ -982,7 +989,7 @@ impl Thread { }; } - self.stream_completion(request, model, cx); + self.stream_completion(request, model, window, cx); } pub fn used_tools_since_last_user_message(&self) -> bool { @@ -1201,6 +1208,7 @@ impl Thread { &mut self, request: LanguageModelRequest, model: Arc, + window: Option, cx: &mut Context, ) { let pending_completion_id = post_inc(&mut self.completion_count); @@ -1382,7 +1390,7 @@ impl Thread { match result.as_ref() { Ok(stop_reason) => match stop_reason { StopReason::ToolUse => { - let tool_uses = thread.use_pending_tools(cx); + let tool_uses = thread.use_pending_tools(window, cx); cx.emit(ThreadEvent::UsePendingTools { tool_uses }); } StopReason::EndTurn => {} @@ -1427,7 +1435,7 @@ impl Thread { })); } - thread.cancel_last_completion(cx); + thread.cancel_last_completion(window, cx); } } cx.emit(ThreadEvent::Stopped(result.map_err(Arc::new))); @@ -1596,7 +1604,11 @@ impl Thread { ) } - pub fn use_pending_tools(&mut self, cx: &mut Context) -> Vec { + pub fn use_pending_tools( + &mut self, + window: Option, + cx: &mut Context, + ) -> Vec { self.auto_capture_telemetry(cx); let request = self.to_completion_request(cx); let messages = Arc::new(request.messages); @@ -1628,6 +1640,7 @@ impl Thread { tool_use.input.clone(), &messages, tool, + window, cx, ); } @@ -1644,9 +1657,10 @@ impl Thread { input: serde_json::Value, messages: &[LanguageModelRequestMessage], tool: Arc, + window: Option, cx: &mut Context, ) { - let task = self.spawn_tool_use(tool_use_id.clone(), messages, input, tool, cx); + let task = self.spawn_tool_use(tool_use_id.clone(), messages, input, tool, window, cx); self.tool_use .run_pending_tool(tool_use_id, ui_text.into(), task); } @@ -1657,6 +1671,7 @@ impl Thread { messages: &[LanguageModelRequestMessage], input: serde_json::Value, tool: Arc, + window: Option, cx: &mut Context, ) -> Task<()> { let tool_name: Arc = tool.name().into(); @@ -1669,6 +1684,7 @@ impl Thread { messages, self.project.clone(), self.action_log.clone(), + window, cx, ) }; @@ -1691,7 +1707,7 @@ impl Thread { output, cx, ); - thread.tool_finished(tool_use_id, pending_tool_use, false, cx); + thread.tool_finished(tool_use_id, pending_tool_use, false, window, cx); }) .ok(); } @@ -1703,6 +1719,7 @@ impl Thread { tool_use_id: LanguageModelToolUseId, pending_tool_use: Option, canceled: bool, + window: Option, cx: &mut Context, ) { if self.all_tools_finished() { @@ -1710,7 +1727,7 @@ impl Thread { if let Some(ConfiguredModel { model, .. }) = model_registry.default_model() { self.attach_tool_results(cx); if !canceled { - self.send_to_model(model, cx); + self.send_to_model(model, window, cx); } } } @@ -1732,7 +1749,11 @@ impl Thread { /// Cancels the last pending completion, if there are any pending. /// /// Returns whether a completion was canceled. - pub fn cancel_last_completion(&mut self, cx: &mut Context) -> bool { + pub fn cancel_last_completion( + &mut self, + window: Option, + cx: &mut Context, + ) -> bool { let canceled = if self.pending_completions.pop().is_some() { true } else { @@ -1743,6 +1764,7 @@ impl Thread { pending_tool_use.id.clone(), Some(pending_tool_use), true, + window, cx, ); } @@ -2199,6 +2221,7 @@ impl Thread { &mut self, tool_use_id: LanguageModelToolUseId, tool_name: Arc, + window: Option, cx: &mut Context, ) { let err = Err(anyhow::anyhow!( @@ -2207,7 +2230,7 @@ impl Thread { self.tool_use .insert_tool_output(tool_use_id.clone(), tool_name, err, cx); - self.tool_finished(tool_use_id.clone(), None, true, cx); + self.tool_finished(tool_use_id.clone(), None, true, window, cx); } } diff --git a/crates/assistant_tool/Cargo.toml b/crates/assistant_tool/Cargo.toml index 9a819d9d81..f19586397d 100644 --- a/crates/assistant_tool/Cargo.toml +++ b/crates/assistant_tool/Cargo.toml @@ -28,6 +28,7 @@ serde.workspace = true serde_json.workspace = true text.workspace = true util.workspace = true +workspace.workspace = true workspace-hack.workspace = true [dev-dependencies] diff --git a/crates/assistant_tool/src/assistant_tool.rs b/crates/assistant_tool/src/assistant_tool.rs index c3e277c783..a706f48926 100644 --- a/crates/assistant_tool/src/assistant_tool.rs +++ b/crates/assistant_tool/src/assistant_tool.rs @@ -10,14 +10,16 @@ use std::sync::Arc; use anyhow::Result; use gpui::AnyElement; +use gpui::AnyWindowHandle; use gpui::Context; use gpui::IntoElement; use gpui::Window; -use gpui::{App, Entity, SharedString, Task}; +use gpui::{App, Entity, SharedString, Task, WeakEntity}; use icons::IconName; use language_model::LanguageModelRequestMessage; use language_model::LanguageModelToolSchemaFormat; use project::Project; +use workspace::Workspace; pub use crate::action_log::*; pub use crate::tool_registry::*; @@ -65,6 +67,7 @@ pub trait ToolCard: 'static + Sized { &mut self, status: &ToolUseStatus, window: &mut Window, + workspace: WeakEntity, cx: &mut Context, ) -> impl IntoElement; } @@ -76,6 +79,7 @@ pub struct AnyToolCard { entity: gpui::AnyEntity, status: &ToolUseStatus, window: &mut Window, + workspace: WeakEntity, cx: &mut App, ) -> AnyElement, } @@ -86,11 +90,14 @@ impl From> for AnyToolCard { entity: gpui::AnyEntity, status: &ToolUseStatus, window: &mut Window, + workspace: WeakEntity, cx: &mut App, ) -> AnyElement { let entity = entity.downcast::().unwrap(); entity.update(cx, |entity, cx| { - entity.render(status, window, cx).into_any_element() + entity + .render(status, window, workspace, cx) + .into_any_element() }) } @@ -102,8 +109,14 @@ impl From> for AnyToolCard { } impl AnyToolCard { - pub fn render(&self, status: &ToolUseStatus, window: &mut Window, cx: &mut App) -> AnyElement { - (self.render)(self.entity.clone(), status, window, cx) + pub fn render( + &self, + status: &ToolUseStatus, + window: &mut Window, + workspace: WeakEntity, + cx: &mut App, + ) -> AnyElement { + (self.render)(self.entity.clone(), status, window, workspace, cx) } } @@ -163,6 +176,7 @@ pub trait Tool: 'static + Send + Sync { messages: &[LanguageModelRequestMessage], project: Entity, action_log: Entity, + window: Option, cx: &mut App, ) -> ToolResult; } diff --git a/crates/assistant_tools/Cargo.toml b/crates/assistant_tools/Cargo.toml index 26ddb53d8f..59d2048b86 100644 --- a/crates/assistant_tools/Cargo.toml +++ b/crates/assistant_tools/Cargo.toml @@ -14,9 +14,11 @@ path = "src/assistant_tools.rs" [dependencies] anyhow.workspace = true assistant_tool.workspace = true +buffer_diff.workspace = true chrono.workspace = true collections.workspace = true component.workspace = true +editor.workspace = true futures.workspace = true gpui.workspace = true html_to_markdown.workspace = true @@ -35,6 +37,7 @@ serde_json.workspace = true ui.workspace = true util.workspace = true web_search.workspace = true +workspace.workspace = true workspace-hack.workspace = true worktree.workspace = true zed_llm_client.workspace = true diff --git a/crates/assistant_tools/src/batch_tool.rs b/crates/assistant_tools/src/batch_tool.rs index 6e4caf4a10..08f2067ca3 100644 --- a/crates/assistant_tools/src/batch_tool.rs +++ b/crates/assistant_tools/src/batch_tool.rs @@ -2,7 +2,7 @@ use crate::schema::json_schema_for; use anyhow::{Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult, ToolWorkingSet}; use futures::future::join_all; -use gpui::{App, AppContext, Entity, Task}; +use gpui::{AnyWindowHandle, App, AppContext, Entity, Task}; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; use project::Project; use schemars::JsonSchema; @@ -218,6 +218,7 @@ impl Tool for BatchTool { messages: &[LanguageModelRequestMessage], project: Entity, action_log: Entity, + window: Option, cx: &mut App, ) -> ToolResult { let input = match serde_json::from_value::(input) { @@ -258,7 +259,9 @@ impl Tool for BatchTool { let action_log = action_log.clone(); let messages = messages.clone(); let tool_result = cx - .update(|cx| tool.run(invocation.input, &messages, project, action_log, cx)) + .update(|cx| { + tool.run(invocation.input, &messages, project, action_log, window, cx) + }) .map_err(|err| anyhow!("Failed to start tool '{}': {}", tool_name, err))?; tasks.push(tool_result.output); diff --git a/crates/assistant_tools/src/code_action_tool.rs b/crates/assistant_tools/src/code_action_tool.rs index 65a820817f..c03c85de95 100644 --- a/crates/assistant_tools/src/code_action_tool.rs +++ b/crates/assistant_tools/src/code_action_tool.rs @@ -1,6 +1,6 @@ use anyhow::{Context as _, Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult}; -use gpui::{App, Entity, Task}; +use gpui::{AnyWindowHandle, App, Entity, Task}; use language::{self, Anchor, Buffer, ToPointUtf16}; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; use project::{self, LspAction, Project}; @@ -140,6 +140,7 @@ impl Tool for CodeActionTool { _messages: &[LanguageModelRequestMessage], project: Entity, action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { let input = match serde_json::from_value::(input) { diff --git a/crates/assistant_tools/src/code_symbols_tool.rs b/crates/assistant_tools/src/code_symbols_tool.rs index 87592d58d7..f5b1b8bb97 100644 --- a/crates/assistant_tools/src/code_symbols_tool.rs +++ b/crates/assistant_tools/src/code_symbols_tool.rs @@ -6,7 +6,7 @@ use crate::schema::json_schema_for; use anyhow::{Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult}; use collections::IndexMap; -use gpui::{App, AsyncApp, Entity, Task}; +use gpui::{AnyWindowHandle, App, AsyncApp, Entity, Task}; use language::{OutlineItem, ParseStatus, Point}; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; use project::{Project, Symbol}; @@ -128,6 +128,7 @@ impl Tool for CodeSymbolsTool { _messages: &[LanguageModelRequestMessage], project: Entity, action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { let input = match serde_json::from_value::(input) { diff --git a/crates/assistant_tools/src/contents_tool.rs b/crates/assistant_tools/src/contents_tool.rs index 37fedc3e57..4cbeab1c41 100644 --- a/crates/assistant_tools/src/contents_tool.rs +++ b/crates/assistant_tools/src/contents_tool.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use crate::{code_symbols_tool::file_outline, schema::json_schema_for}; use anyhow::{Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult}; -use gpui::{App, Entity, Task}; +use gpui::{AnyWindowHandle, App, Entity, Task}; use itertools::Itertools; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; use project::Project; @@ -102,6 +102,7 @@ impl Tool for ContentsTool { _messages: &[LanguageModelRequestMessage], project: Entity, action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { let input = match serde_json::from_value::(input) { diff --git a/crates/assistant_tools/src/copy_path_tool.rs b/crates/assistant_tools/src/copy_path_tool.rs index 1b3e10fe84..4d94b82203 100644 --- a/crates/assistant_tools/src/copy_path_tool.rs +++ b/crates/assistant_tools/src/copy_path_tool.rs @@ -1,6 +1,7 @@ use crate::schema::json_schema_for; use anyhow::{Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult}; +use gpui::AnyWindowHandle; use gpui::{App, AppContext, Entity, Task}; use language_model::LanguageModelRequestMessage; use language_model::LanguageModelToolSchemaFormat; @@ -76,6 +77,7 @@ impl Tool for CopyPathTool { _messages: &[LanguageModelRequestMessage], project: Entity, _action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { let input = match serde_json::from_value::(input) { diff --git a/crates/assistant_tools/src/create_directory_tool.rs b/crates/assistant_tools/src/create_directory_tool.rs index b094ba3769..bbf3ff346b 100644 --- a/crates/assistant_tools/src/create_directory_tool.rs +++ b/crates/assistant_tools/src/create_directory_tool.rs @@ -1,6 +1,7 @@ use crate::schema::json_schema_for; use anyhow::{Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult}; +use gpui::AnyWindowHandle; use gpui::{App, Entity, Task}; use language_model::LanguageModelRequestMessage; use language_model::LanguageModelToolSchemaFormat; @@ -67,6 +68,7 @@ impl Tool for CreateDirectoryTool { _messages: &[LanguageModelRequestMessage], project: Entity, _action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { let input = match serde_json::from_value::(input) { diff --git a/crates/assistant_tools/src/create_file_tool.rs b/crates/assistant_tools/src/create_file_tool.rs index 442ccf19a9..158991bf6d 100644 --- a/crates/assistant_tools/src/create_file_tool.rs +++ b/crates/assistant_tools/src/create_file_tool.rs @@ -1,6 +1,7 @@ use crate::schema::json_schema_for; use anyhow::{Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult}; +use gpui::AnyWindowHandle; use gpui::{App, Entity, Task}; use language_model::LanguageModelRequestMessage; use language_model::LanguageModelToolSchemaFormat; @@ -89,6 +90,7 @@ impl Tool for CreateFileTool { _messages: &[LanguageModelRequestMessage], project: Entity, action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { let input = match serde_json::from_value::(input) { diff --git a/crates/assistant_tools/src/delete_path_tool.rs b/crates/assistant_tools/src/delete_path_tool.rs index c7d70da69d..fcac081e9c 100644 --- a/crates/assistant_tools/src/delete_path_tool.rs +++ b/crates/assistant_tools/src/delete_path_tool.rs @@ -2,7 +2,7 @@ use crate::schema::json_schema_for; use anyhow::{Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult}; use futures::{SinkExt, StreamExt, channel::mpsc}; -use gpui::{App, AppContext, Entity, Task}; +use gpui::{AnyWindowHandle, App, AppContext, Entity, Task}; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; use project::{Project, ProjectPath}; use schemars::JsonSchema; @@ -62,6 +62,7 @@ impl Tool for DeletePathTool { _messages: &[LanguageModelRequestMessage], project: Entity, action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { let path_str = match serde_json::from_value::(input) { diff --git a/crates/assistant_tools/src/diagnostics_tool.rs b/crates/assistant_tools/src/diagnostics_tool.rs index 882544b026..8fdfd58a59 100644 --- a/crates/assistant_tools/src/diagnostics_tool.rs +++ b/crates/assistant_tools/src/diagnostics_tool.rs @@ -1,7 +1,7 @@ use crate::schema::json_schema_for; use anyhow::{Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult}; -use gpui::{App, Entity, Task}; +use gpui::{AnyWindowHandle, App, Entity, Task}; use language::{DiagnosticSeverity, OffsetRangeExt}; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; use project::Project; @@ -82,6 +82,7 @@ impl Tool for DiagnosticsTool { _messages: &[LanguageModelRequestMessage], project: Entity, action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { match serde_json::from_value::(input) diff --git a/crates/assistant_tools/src/edit_file_tool.rs b/crates/assistant_tools/src/edit_file_tool.rs index 11d5bbaa33..f683bd3898 100644 --- a/crates/assistant_tools/src/edit_file_tool.rs +++ b/crates/assistant_tools/src/edit_file_tool.rs @@ -1,15 +1,28 @@ -use crate::{replace::replace_with_flexible_indent, schema::json_schema_for}; +use crate::{ + replace::{replace_exact, replace_with_flexible_indent}, + schema::json_schema_for, +}; use anyhow::{Context as _, Result, anyhow}; -use assistant_tool::{ActionLog, Tool, ToolResult}; -use gpui::{App, AppContext, AsyncApp, Entity, Task}; +use assistant_tool::{ActionLog, AnyToolCard, Tool, ToolCard, ToolResult, ToolUseStatus}; +use buffer_diff::{BufferDiff, BufferDiffSnapshot}; +use editor::{Editor, EditorMode, MultiBuffer, PathKey}; +use gpui::{ + AnyWindowHandle, App, AppContext, AsyncApp, Context, Entity, EntityId, Task, WeakEntity, +}; +use language::{ + Anchor, Buffer, Capability, LanguageRegistry, LineEnding, OffsetRangeExt, Rope, TextBuffer, +}; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; use project::Project; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use std::{path::PathBuf, sync::Arc}; -use ui::IconName; - -use crate::replace::replace_exact; +use std::{ + path::{Path, PathBuf}, + sync::Arc, +}; +use ui::{Disclosure, Tooltip, Window, prelude::*}; +use util::ResultExt; +use workspace::Workspace; #[derive(Debug, Serialize, Deserialize, JsonSchema)] pub struct EditFileToolInput { @@ -113,6 +126,7 @@ impl Tool for EditFileTool { _messages: &[LanguageModelRequestMessage], project: Entity, action_log: Entity, + window: Option, cx: &mut App, ) -> ToolResult { let input = match serde_json::from_value::(input) { @@ -120,7 +134,18 @@ impl Tool for EditFileTool { Err(err) => return Task::ready(Err(anyhow!(err))).into(), }; - cx.spawn(async move |cx: &mut AsyncApp| { + let card = window.and_then(|window| { + window + .update(cx, |_, window, cx| { + cx.new(|cx| { + EditFileToolCard::new(input.path.clone(), project.clone(), window, cx) + }) + }) + .ok() + }); + + let card_clone = card.clone(); + let task = cx.spawn(async move |cx: &mut AsyncApp| { let project_path = project.read_with(cx, |project, cx| { project .find_project_path(&input.path, cx) @@ -128,26 +153,38 @@ impl Tool for EditFileTool { })??; let buffer = project - .update(cx, |project, cx| project.open_buffer(project_path, cx))? + .update(cx, |project, cx| { + project.open_buffer(project_path.clone(), cx) + })? .await?; let snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot())?; if input.old_string.is_empty() { - return Err(anyhow!("`old_string` cannot be empty. Use a different tool if you want to create a file.")); + return Err(anyhow!( + "`old_string` can't be empty, use another tool if you want to create a file." + )); } if input.old_string == input.new_string { - return Err(anyhow!("The `old_string` and `new_string` are identical, so no changes would be made.")); + return Err(anyhow!( + "The `old_string` and `new_string` are identical, so no changes would be made." + )); } let result = cx .background_spawn(async move { // Try to match exactly let diff = replace_exact(&input.old_string, &input.new_string, &snapshot) - .await - // If that fails, try being flexible about indentation - .or_else(|| replace_with_flexible_indent(&input.old_string, &input.new_string, &snapshot))?; + .await + // If that fails, try being flexible about indentation + .or_else(|| { + replace_with_flexible_indent( + &input.old_string, + &input.new_string, + &snapshot, + ) + })?; if diff.edits.is_empty() { return None; @@ -177,41 +214,409 @@ impl Tool for EditFileTool { } })?; - return Err(err) + return Err(err); }; let snapshot = cx.update(|cx| { - action_log.update(cx, |log, cx| { - log.track_buffer(buffer.clone(), cx) - }); + action_log.update(cx, |log, cx| log.track_buffer(buffer.clone(), cx)); + let snapshot = buffer.update(cx, |buffer, cx| { buffer.finalize_last_transaction(); buffer.apply_diff(diff, cx); buffer.finalize_last_transaction(); buffer.snapshot() }); - action_log.update(cx, |log, cx| { - log.buffer_edited(buffer.clone(), cx) - }); + action_log.update(cx, |log, cx| log.buffer_edited(buffer.clone(), cx)); snapshot })?; - project.update( cx, |project, cx| { - project.save_buffer(buffer, cx) - })?.await?; + project + .update(cx, |project, cx| project.save_buffer(buffer, cx))? + .await?; - let diff_str = cx.background_spawn(async move { - let new_text = snapshot.text(); - language::unified_diff(&old_text, &new_text) - }).await; + let new_text = snapshot.text(); + let diff_str = cx + .background_spawn({ + let old_text = old_text.clone(); + let new_text = new_text.clone(); + async move { language::unified_diff(&old_text, &new_text) } + }) + .await; + if let Some(card) = card_clone { + card.update(cx, |card, cx| { + card.set_diff(project_path.path.clone(), old_text, new_text, cx); + }) + .log_err(); + } - Ok(format!("Edited {}:\n\n```diff\n{}\n```", input.path.display(), diff_str)) + Ok(format!( + "Edited {}:\n\n```diff\n{}\n```", + input.path.display(), + diff_str + )) + }); - }).into() + ToolResult { + output: task, + card: card.map(AnyToolCard::from), + } } } +pub struct EditFileToolCard { + path: PathBuf, + editor: Entity, + multibuffer: Entity, + project: Entity, + diff_task: Option>>, + preview_expanded: bool, + full_height_expanded: bool, + editor_unique_id: EntityId, +} + +impl EditFileToolCard { + fn new(path: PathBuf, project: Entity, window: &mut Window, cx: &mut App) -> Self { + let multibuffer = cx.new(|_| MultiBuffer::without_headers(Capability::ReadOnly)); + let editor = cx.new(|cx| { + let mut editor = Editor::new( + EditorMode::Full { + scale_ui_elements_with_buffer_font_size: false, + show_active_line_background: false, + sized_by_content: true, + }, + multibuffer.clone(), + Some(project.clone()), + window, + cx, + ); + editor.set_show_scrollbars(false, cx); + editor.set_show_gutter(false, cx); + editor.disable_inline_diagnostics(); + editor.disable_scrolling(cx); + editor.disable_expand_excerpt_buttons(cx); + editor.set_show_breakpoints(false, cx); + editor.set_show_code_actions(false, cx); + editor.set_show_git_diff_gutter(false, cx); + editor.set_expand_all_diff_hunks(cx); + editor + }); + Self { + editor_unique_id: editor.entity_id(), + path, + project, + editor, + multibuffer, + diff_task: None, + preview_expanded: true, + full_height_expanded: false, + } + } + + fn set_diff( + &mut self, + path: Arc, + old_text: String, + new_text: String, + cx: &mut Context, + ) { + let language_registry = self.project.read(cx).languages().clone(); + self.diff_task = Some(cx.spawn(async move |this, cx| { + let buffer = build_buffer(new_text, path.clone(), &language_registry, cx).await?; + let buffer_diff = build_buffer_diff(old_text, &buffer, &language_registry, cx).await?; + + this.update(cx, |this, cx| { + this.multibuffer.update(cx, |multibuffer, cx| { + let snapshot = buffer.read(cx).snapshot(); + let diff = buffer_diff.read(cx); + let diff_hunk_ranges = diff + .hunks_intersecting_range(Anchor::MIN..Anchor::MAX, &snapshot, cx) + .map(|diff_hunk| diff_hunk.buffer_range.to_point(&snapshot)) + .collect::>(); + let (_, is_newly_added) = multibuffer.set_excerpts_for_path( + PathKey::for_buffer(&buffer, cx), + buffer, + diff_hunk_ranges, + editor::DEFAULT_MULTIBUFFER_CONTEXT, + cx, + ); + debug_assert!(is_newly_added); + multibuffer.add_diff(buffer_diff, cx); + }); + cx.notify(); + }) + })); + } +} + +impl ToolCard for EditFileToolCard { + fn render( + &mut self, + status: &ToolUseStatus, + window: &mut Window, + workspace: WeakEntity, + cx: &mut Context, + ) -> impl IntoElement { + let failed = matches!(status, ToolUseStatus::Error(_)); + + let path_label_button = h_flex() + .id(("edit-tool-path-label-button", self.editor_unique_id)) + .w_full() + .max_w_full() + .px_1() + .gap_0p5() + .cursor_pointer() + .rounded_sm() + .opacity(0.8) + .hover(|label| { + label + .opacity(1.) + .bg(cx.theme().colors().element_hover.opacity(0.5)) + }) + .tooltip(Tooltip::text("Jump to File")) + .child( + h_flex() + .child( + Icon::new(IconName::Pencil) + .size(IconSize::XSmall) + .color(Color::Muted), + ) + .child( + div() + .text_size(rems(0.8125)) + .child(self.path.display().to_string()) + .ml_1p5() + .mr_0p5(), + ) + .child( + Icon::new(IconName::ArrowUpRight) + .size(IconSize::XSmall) + .color(Color::Ignored), + ), + ) + .on_click({ + let path = self.path.clone(); + let workspace = workspace.clone(); + move |_, window, cx| { + workspace + .update(cx, { + |workspace, cx| { + let Some(project_path) = + workspace.project().read(cx).find_project_path(&path, cx) + else { + return; + }; + let open_task = + workspace.open_path(project_path, None, true, window, cx); + window + .spawn(cx, async move |cx| { + let item = open_task.await?; + if let Some(active_editor) = item.downcast::() { + active_editor + .update_in(cx, |editor, window, cx| { + editor.go_to_singleton_buffer_point( + language::Point::new(0, 0), + window, + cx, + ); + }) + .log_err(); + } + anyhow::Ok(()) + }) + .detach_and_log_err(cx); + } + }) + .ok(); + } + }) + .into_any_element(); + + let codeblock_header_bg = cx + .theme() + .colors() + .element_background + .blend(cx.theme().colors().editor_foreground.opacity(0.025)); + + let codeblock_header = h_flex() + .flex_none() + .p_1() + .gap_1() + .justify_between() + .rounded_t_md() + .when(!failed, |header| header.bg(codeblock_header_bg)) + .child(path_label_button) + .map(|container| { + if failed { + container.child( + Icon::new(IconName::Close) + .size(IconSize::Small) + .color(Color::Error), + ) + } else { + container.child( + Disclosure::new( + ("edit-file-disclosure", self.editor_unique_id), + self.preview_expanded, + ) + .opened_icon(IconName::ChevronUp) + .closed_icon(IconName::ChevronDown) + .on_click(cx.listener( + move |this, _event, _window, _cx| { + this.preview_expanded = !this.preview_expanded; + }, + )), + ) + } + }); + + let editor = self.editor.update(cx, |editor, cx| { + editor.render(window, cx).into_any_element() + }); + + let (full_height_icon, full_height_tooltip_label) = if self.full_height_expanded { + (IconName::ChevronUp, "Collapse Code Block") + } else { + (IconName::ChevronDown, "Expand Code Block") + }; + + let gradient_overlay = div() + .absolute() + .bottom_0() + .left_0() + .w_full() + .h_2_5() + .rounded_b_lg() + .bg(gpui::linear_gradient( + 0., + gpui::linear_color_stop(cx.theme().colors().editor_background, 0.), + gpui::linear_color_stop(cx.theme().colors().editor_background.opacity(0.), 1.), + )); + + let border_color = cx.theme().colors().border.opacity(0.6); + + v_flex() + .mb_2() + .border_1() + .when(failed, |card| card.border_dashed()) + .border_color(border_color) + .rounded_lg() + .overflow_hidden() + .child(codeblock_header) + .when(!failed && self.preview_expanded, |card| { + card.child( + v_flex() + .relative() + .overflow_hidden() + .border_t_1() + .border_color(border_color) + .bg(cx.theme().colors().editor_background) + .map(|editor_container| { + if self.full_height_expanded { + editor_container.h_full() + } else { + editor_container.max_h_64() + } + }) + .child(div().pl_1().child(editor)) + .when(!self.full_height_expanded, |editor_container| { + editor_container.child(gradient_overlay) + }), + ) + }) + .when(!failed && self.preview_expanded, |card| { + card.child( + h_flex() + .id(("edit-tool-card-inner-hflex", self.editor_unique_id)) + .flex_none() + .cursor_pointer() + .h_5() + .justify_center() + .rounded_b_md() + .border_t_1() + .border_color(border_color) + .bg(cx.theme().colors().editor_background) + .hover(|style| style.bg(cx.theme().colors().element_hover.opacity(0.1))) + .child( + Icon::new(full_height_icon) + .size(IconSize::Small) + .color(Color::Muted), + ) + .tooltip(Tooltip::text(full_height_tooltip_label)) + .on_click(cx.listener(move |this, _event, _window, _cx| { + this.full_height_expanded = !this.full_height_expanded; + })), + ) + }) + } +} + +async fn build_buffer( + mut text: String, + path: Arc, + language_registry: &Arc, + cx: &mut AsyncApp, +) -> Result> { + let line_ending = LineEnding::detect(&text); + LineEnding::normalize(&mut text); + let text = Rope::from(text); + let language = cx + .update(|_cx| language_registry.language_for_file_path(&path))? + .await + .ok(); + let buffer = cx.new(|cx| { + let buffer = TextBuffer::new_normalized( + 0, + cx.entity_id().as_non_zero_u64().into(), + line_ending, + text, + ); + let mut buffer = Buffer::build(buffer, None, Capability::ReadWrite); + buffer.set_language(language, cx); + buffer + })?; + Ok(buffer) +} + +async fn build_buffer_diff( + mut old_text: String, + buffer: &Entity, + language_registry: &Arc, + cx: &mut AsyncApp, +) -> Result> { + LineEnding::normalize(&mut old_text); + + let buffer = cx.update(|cx| buffer.read(cx).snapshot())?; + + let base_buffer = cx + .update(|cx| { + Buffer::build_snapshot( + old_text.clone().into(), + buffer.language().cloned(), + Some(language_registry.clone()), + cx, + ) + })? + .await; + + let diff_snapshot = cx + .update(|cx| { + BufferDiffSnapshot::new_with_base_buffer( + buffer.text.clone(), + Some(old_text.into()), + base_buffer, + cx, + ) + })? + .await; + + cx.new(|cx| { + let mut diff = BufferDiff::new(&buffer.text, cx); + diff.set_snapshot(diff_snapshot, &buffer.text, cx); + diff + }) +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/assistant_tools/src/fetch_tool.rs b/crates/assistant_tools/src/fetch_tool.rs index 9dcc5afa1b..f37cd16748 100644 --- a/crates/assistant_tools/src/fetch_tool.rs +++ b/crates/assistant_tools/src/fetch_tool.rs @@ -6,7 +6,7 @@ use crate::schema::json_schema_for; use anyhow::{Context as _, Result, anyhow, bail}; use assistant_tool::{ActionLog, Tool, ToolResult}; use futures::AsyncReadExt as _; -use gpui::{App, AppContext as _, Entity, Task}; +use gpui::{AnyWindowHandle, App, AppContext as _, Entity, Task}; use html_to_markdown::{TagHandler, convert_html_to_markdown, markdown}; use http_client::{AsyncBody, HttpClientWithUrl}; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; @@ -145,6 +145,7 @@ impl Tool for FetchTool { _messages: &[LanguageModelRequestMessage], _project: Entity, _action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { let input = match serde_json::from_value::(input) { diff --git a/crates/assistant_tools/src/grep_tool.rs b/crates/assistant_tools/src/grep_tool.rs index 45f3cacf7b..32d612c54f 100644 --- a/crates/assistant_tools/src/grep_tool.rs +++ b/crates/assistant_tools/src/grep_tool.rs @@ -2,7 +2,7 @@ use crate::schema::json_schema_for; use anyhow::{Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult}; use futures::StreamExt; -use gpui::{App, Entity, Task}; +use gpui::{AnyWindowHandle, App, Entity, Task}; use language::OffsetRangeExt; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; use project::{ @@ -96,6 +96,7 @@ impl Tool for GrepTool { _messages: &[LanguageModelRequestMessage], project: Entity, _action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { const CONTEXT_LINES: u32 = 2; @@ -405,7 +406,7 @@ mod tests { ) -> String { let tool = Arc::new(GrepTool); let action_log = cx.new(|_cx| ActionLog::new(project.clone())); - let task = cx.update(|cx| tool.run(input, &[], project, action_log, cx)); + let task = cx.update(|cx| tool.run(input, &[], project, action_log, None, cx)); match task.output.await { Ok(result) => result, diff --git a/crates/assistant_tools/src/list_directory_tool.rs b/crates/assistant_tools/src/list_directory_tool.rs index ef0c2838e8..7b3e2a38ff 100644 --- a/crates/assistant_tools/src/list_directory_tool.rs +++ b/crates/assistant_tools/src/list_directory_tool.rs @@ -1,7 +1,7 @@ use crate::schema::json_schema_for; use anyhow::{Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult}; -use gpui::{App, Entity, Task}; +use gpui::{AnyWindowHandle, App, Entity, Task}; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; use project::Project; use schemars::JsonSchema; @@ -76,6 +76,7 @@ impl Tool for ListDirectoryTool { _messages: &[LanguageModelRequestMessage], project: Entity, _action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { let input = match serde_json::from_value::(input) { diff --git a/crates/assistant_tools/src/move_path_tool.rs b/crates/assistant_tools/src/move_path_tool.rs index a0d7875bfb..b024ed3147 100644 --- a/crates/assistant_tools/src/move_path_tool.rs +++ b/crates/assistant_tools/src/move_path_tool.rs @@ -1,7 +1,7 @@ use crate::schema::json_schema_for; use anyhow::{Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult}; -use gpui::{App, AppContext, Entity, Task}; +use gpui::{AnyWindowHandle, App, AppContext, Entity, Task}; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; use project::Project; use schemars::JsonSchema; @@ -89,6 +89,7 @@ impl Tool for MovePathTool { _messages: &[LanguageModelRequestMessage], project: Entity, _action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { let input = match serde_json::from_value::(input) { diff --git a/crates/assistant_tools/src/now_tool.rs b/crates/assistant_tools/src/now_tool.rs index 71b57d8dc8..46d009715f 100644 --- a/crates/assistant_tools/src/now_tool.rs +++ b/crates/assistant_tools/src/now_tool.rs @@ -4,7 +4,7 @@ use crate::schema::json_schema_for; use anyhow::{Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult}; use chrono::{Local, Utc}; -use gpui::{App, Entity, Task}; +use gpui::{AnyWindowHandle, App, Entity, Task}; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; use project::Project; use schemars::JsonSchema; @@ -59,6 +59,7 @@ impl Tool for NowTool { _messages: &[LanguageModelRequestMessage], _project: Entity, _action_log: Entity, + _window: Option, _cx: &mut App, ) -> ToolResult { let input: NowToolInput = match serde_json::from_value(input) { diff --git a/crates/assistant_tools/src/open_tool.rs b/crates/assistant_tools/src/open_tool.rs index 1ac242fddc..19d5cce023 100644 --- a/crates/assistant_tools/src/open_tool.rs +++ b/crates/assistant_tools/src/open_tool.rs @@ -1,7 +1,7 @@ use crate::schema::json_schema_for; use anyhow::{Context as _, Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult}; -use gpui::{App, AppContext, Entity, Task}; +use gpui::{AnyWindowHandle, App, AppContext, Entity, Task}; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; use project::Project; use schemars::JsonSchema; @@ -52,6 +52,7 @@ impl Tool for OpenTool { _messages: &[LanguageModelRequestMessage], _project: Entity, _action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { let input: OpenToolInput = match serde_json::from_value(input) { diff --git a/crates/assistant_tools/src/path_search_tool.rs b/crates/assistant_tools/src/path_search_tool.rs index ea19cb1dee..694d89cd30 100644 --- a/crates/assistant_tools/src/path_search_tool.rs +++ b/crates/assistant_tools/src/path_search_tool.rs @@ -1,7 +1,7 @@ use crate::schema::json_schema_for; use anyhow::{Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult}; -use gpui::{App, AppContext, Entity, Task}; +use gpui::{AnyWindowHandle, App, AppContext, Entity, Task}; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; use project::Project; use schemars::JsonSchema; @@ -70,6 +70,7 @@ impl Tool for PathSearchTool { _messages: &[LanguageModelRequestMessage], project: Entity, _action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { let (offset, glob) = match serde_json::from_value::(input) { diff --git a/crates/assistant_tools/src/read_file_tool.rs b/crates/assistant_tools/src/read_file_tool.rs index 6d90f48f66..f81b4fe209 100644 --- a/crates/assistant_tools/src/read_file_tool.rs +++ b/crates/assistant_tools/src/read_file_tool.rs @@ -1,7 +1,8 @@ use crate::{code_symbols_tool::file_outline, schema::json_schema_for}; use anyhow::{Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult}; -use gpui::{App, Entity, Task}; +use gpui::{AnyWindowHandle, App, Entity, Task}; + use indoc::formatdoc; use itertools::Itertools; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; @@ -87,6 +88,7 @@ impl Tool for ReadFileTool { _messages: &[LanguageModelRequestMessage], project: Entity, action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { let input = match serde_json::from_value::(input) { @@ -193,7 +195,7 @@ mod test { "path": "root/nonexistent_file.txt" }); Arc::new(ReadFileTool) - .run(input, &[], project.clone(), action_log, cx) + .run(input, &[], project.clone(), action_log, None, cx) .output }) .await; @@ -223,7 +225,7 @@ mod test { "path": "root/small_file.txt" }); Arc::new(ReadFileTool) - .run(input, &[], project.clone(), action_log, cx) + .run(input, &[], project.clone(), action_log, None, cx) .output }) .await; @@ -253,7 +255,7 @@ mod test { "path": "root/large_file.rs" }); Arc::new(ReadFileTool) - .run(input, &[], project.clone(), action_log.clone(), cx) + .run(input, &[], project.clone(), action_log.clone(), None, cx) .output }) .await; @@ -277,7 +279,7 @@ mod test { "offset": 1 }); Arc::new(ReadFileTool) - .run(input, &[], project.clone(), action_log, cx) + .run(input, &[], project.clone(), action_log, None, cx) .output }) .await; @@ -323,7 +325,7 @@ mod test { "end_line": 4 }); Arc::new(ReadFileTool) - .run(input, &[], project.clone(), action_log, cx) + .run(input, &[], project.clone(), action_log, None, cx) .output }) .await; diff --git a/crates/assistant_tools/src/rename_tool.rs b/crates/assistant_tools/src/rename_tool.rs index d2189f6b16..b713f31040 100644 --- a/crates/assistant_tools/src/rename_tool.rs +++ b/crates/assistant_tools/src/rename_tool.rs @@ -1,6 +1,6 @@ use anyhow::{Context as _, Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult}; -use gpui::{App, Entity, Task}; +use gpui::{AnyWindowHandle, App, Entity, Task}; use language::{self, Buffer, ToPointUtf16}; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; use project::Project; @@ -87,6 +87,7 @@ impl Tool for RenameTool { _messages: &[LanguageModelRequestMessage], project: Entity, action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { let input = match serde_json::from_value::(input) { diff --git a/crates/assistant_tools/src/symbol_info_tool.rs b/crates/assistant_tools/src/symbol_info_tool.rs index b3798935ec..c59b3820fe 100644 --- a/crates/assistant_tools/src/symbol_info_tool.rs +++ b/crates/assistant_tools/src/symbol_info_tool.rs @@ -1,6 +1,6 @@ use anyhow::{Context as _, Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult}; -use gpui::{App, AsyncApp, Entity, Task}; +use gpui::{AnyWindowHandle, App, AsyncApp, Entity, Task}; use language::{self, Anchor, Buffer, BufferSnapshot, Location, Point, ToPoint, ToPointUtf16}; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; use project::Project; @@ -121,6 +121,7 @@ impl Tool for SymbolInfoTool { _messages: &[LanguageModelRequestMessage], project: Entity, action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { let input = match serde_json::from_value::(input) { diff --git a/crates/assistant_tools/src/terminal_tool.rs b/crates/assistant_tools/src/terminal_tool.rs index 4f7343492e..d777d5cb0e 100644 --- a/crates/assistant_tools/src/terminal_tool.rs +++ b/crates/assistant_tools/src/terminal_tool.rs @@ -3,7 +3,7 @@ use anyhow::{Context as _, Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult}; use futures::io::BufReader; use futures::{AsyncBufReadExt, AsyncReadExt, FutureExt}; -use gpui::{App, AppContext, Entity, Task}; +use gpui::{AnyWindowHandle, App, AppContext, Entity, Task}; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; use project::Project; use schemars::JsonSchema; @@ -78,6 +78,7 @@ impl Tool for TerminalTool { _messages: &[LanguageModelRequestMessage], project: Entity, _action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { let input: TerminalToolInput = match serde_json::from_value(input) { diff --git a/crates/assistant_tools/src/thinking_tool.rs b/crates/assistant_tools/src/thinking_tool.rs index dc4e752158..fc6946d4d7 100644 --- a/crates/assistant_tools/src/thinking_tool.rs +++ b/crates/assistant_tools/src/thinking_tool.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use crate::schema::json_schema_for; use anyhow::{Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolResult}; -use gpui::{App, Entity, Task}; +use gpui::{AnyWindowHandle, App, Entity, Task}; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; use project::Project; use schemars::JsonSchema; @@ -50,6 +50,7 @@ impl Tool for ThinkingTool { _messages: &[LanguageModelRequestMessage], _project: Entity, _action_log: Entity, + _window: Option, _cx: &mut App, ) -> ToolResult { // This tool just "thinks out loud" and doesn't perform any actions. diff --git a/crates/assistant_tools/src/web_search_tool.rs b/crates/assistant_tools/src/web_search_tool.rs index b64b9a78c7..db33c0cacf 100644 --- a/crates/assistant_tools/src/web_search_tool.rs +++ b/crates/assistant_tools/src/web_search_tool.rs @@ -5,13 +5,16 @@ use crate::ui::ToolCallCardHeader; use anyhow::{Context as _, Result, anyhow}; use assistant_tool::{ActionLog, Tool, ToolCard, ToolResult, ToolUseStatus}; use futures::{Future, FutureExt, TryFutureExt}; -use gpui::{App, AppContext, Context, Entity, IntoElement, Task, Window}; +use gpui::{ + AnyWindowHandle, App, AppContext, Context, Entity, IntoElement, Task, WeakEntity, Window, +}; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; use project::Project; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use ui::{IconName, Tooltip, prelude::*}; use web_search::WebSearchRegistry; +use workspace::Workspace; use zed_llm_client::{WebSearchCitation, WebSearchResponse}; #[derive(Debug, Serialize, Deserialize, JsonSchema)] @@ -54,6 +57,7 @@ impl Tool for WebSearchTool { _messages: &[LanguageModelRequestMessage], _project: Entity, _action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { let input = match serde_json::from_value::(input) { @@ -111,6 +115,7 @@ impl ToolCard for WebSearchToolCard { &mut self, _status: &ToolUseStatus, _window: &mut Window, + _workspace: WeakEntity, cx: &mut Context, ) -> impl IntoElement { let header = match self.response.as_ref() { @@ -220,8 +225,13 @@ impl Component for WebSearchTool { div() .size_full() .child(in_progress_search.update(cx, |tool, cx| { - tool.render(&ToolUseStatus::Pending, window, cx) - .into_any_element() + tool.render( + &ToolUseStatus::Pending, + window, + WeakEntity::new_invalid(), + cx, + ) + .into_any_element() })) .into_any_element(), ), @@ -230,8 +240,13 @@ impl Component for WebSearchTool { div() .size_full() .child(successful_search.update(cx, |tool, cx| { - tool.render(&ToolUseStatus::Finished("".into()), window, cx) - .into_any_element() + tool.render( + &ToolUseStatus::Finished("".into()), + window, + WeakEntity::new_invalid(), + cx, + ) + .into_any_element() })) .into_any_element(), ), @@ -240,8 +255,13 @@ impl Component for WebSearchTool { div() .size_full() .child(error_search.update(cx, |tool, cx| { - tool.render(&ToolUseStatus::Error("".into()), window, cx) - .into_any_element() + tool.render( + &ToolUseStatus::Error("".into()), + window, + WeakEntity::new_invalid(), + cx, + ) + .into_any_element() })) .into_any_element(), ), diff --git a/crates/context_server/src/context_server_tool.rs b/crates/context_server/src/context_server_tool.rs index 2d03986a39..93422e87d8 100644 --- a/crates/context_server/src/context_server_tool.rs +++ b/crates/context_server/src/context_server_tool.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use anyhow::{Result, anyhow, bail}; use assistant_tool::{ActionLog, Tool, ToolResult, ToolSource}; -use gpui::{App, Entity, Task}; +use gpui::{AnyWindowHandle, App, Entity, Task}; use icons::IconName; use language_model::{LanguageModelRequestMessage, LanguageModelToolSchemaFormat}; use project::Project; @@ -77,6 +77,7 @@ impl Tool for ContextServerTool { _messages: &[LanguageModelRequestMessage], _project: Entity, _action_log: Entity, + _window: Option, cx: &mut App, ) -> ToolResult { if let Some(server) = self.server_manager.read(cx).get_server(&self.server_id) { diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index e6d817ab38..ee501da679 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -433,6 +433,8 @@ pub enum EditorMode { scale_ui_elements_with_buffer_font_size: bool, /// When set to `true`, the editor will render a background for the active line. show_active_line_background: bool, + /// When set to `true`, the editor's height will be determined by its content. + sized_by_content: bool, }, } @@ -441,6 +443,7 @@ impl EditorMode { Self::Full { scale_ui_elements_with_buffer_font_size: true, show_active_line_background: true, + sized_by_content: false, } } @@ -798,6 +801,8 @@ pub struct Editor { show_breadcrumbs: bool, show_gutter: bool, show_scrollbars: bool, + disable_scrolling: bool, + disable_expand_excerpt_buttons: bool, show_line_numbers: Option, use_relative_line_numbers: Option, show_git_diff_gutter: Option, @@ -1589,11 +1594,13 @@ impl Editor { blink_manager: blink_manager.clone(), show_local_selections: true, show_scrollbars: true, + disable_scrolling: true, mode, show_breadcrumbs: EditorSettings::get_global(cx).toolbar.breadcrumbs, show_gutter: mode.is_full(), show_line_numbers: None, use_relative_line_numbers: None, + disable_expand_excerpt_buttons: false, show_git_diff_gutter: None, show_code_actions: None, show_runnables: None, @@ -16175,11 +16182,21 @@ impl Editor { cx.notify(); } + pub fn disable_scrolling(&mut self, cx: &mut Context) { + self.disable_scrolling = true; + cx.notify(); + } + pub fn set_show_line_numbers(&mut self, show_line_numbers: bool, cx: &mut Context) { self.show_line_numbers = Some(show_line_numbers); cx.notify(); } + pub fn disable_expand_excerpt_buttons(&mut self, cx: &mut Context) { + self.disable_expand_excerpt_buttons = true; + cx.notify(); + } + pub fn set_show_git_diff_gutter(&mut self, show_git_diff_gutter: bool, cx: &mut Context) { self.show_git_diff_gutter = Some(show_git_diff_gutter); cx.notify(); diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 98ab760537..b2bb08b72f 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -10419,6 +10419,7 @@ async fn test_completion_in_multibuffer_with_replace_range(cx: &mut TestAppConte EditorMode::Full { scale_ui_elements_with_buffer_font_size: false, show_active_line_background: false, + sized_by_content: false, }, multi_buffer.clone(), Some(project.clone()), diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 1649e0a694..b3adfebd78 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -2184,6 +2184,10 @@ impl EditorElement { window: &mut Window, cx: &mut App, ) -> Vec)>> { + if self.editor.read(cx).disable_expand_excerpt_buttons { + return vec![]; + } + let editor_font_size = self.style.text.font_size.to_pixels(window.rem_size()) * 1.2; let scroll_top = scroll_position.y * line_height; @@ -5537,7 +5541,9 @@ impl EditorElement { } fn paint_mouse_listeners(&mut self, layout: &EditorLayout, window: &mut Window, cx: &mut App) { - self.paint_scroll_wheel_listener(layout, window, cx); + if !self.editor.read(cx).disable_scrolling { + self.paint_scroll_wheel_listener(layout, window, cx); + } window.on_mouse_event({ let position_map = layout.position_map.clone(); @@ -6588,10 +6594,21 @@ impl Element for EditorElement { }, ) } - EditorMode::Full { .. } => { + EditorMode::Full { + sized_by_content, .. + } => { let mut style = Style::default(); style.size.width = relative(1.).into(); - style.size.height = relative(1.).into(); + if sized_by_content { + let snapshot = editor.snapshot(window, cx); + let line_height = + self.style.text.line_height_in_pixels(window.rem_size()); + let scroll_height = + (snapshot.max_point().row().next_row().0 as f32) * line_height; + style.size.height = scroll_height.into(); + } else { + style.size.height = relative(1.).into(); + } window.request_layout(style, None, cx) } }; diff --git a/crates/eval/src/example.rs b/crates/eval/src/example.rs index 445057ebe0..84515bf45d 100644 --- a/crates/eval/src/example.rs +++ b/crates/eval/src/example.rs @@ -278,7 +278,7 @@ impl ExampleContext { let message_count_before = self.app.update_entity(&self.agent_thread, |thread, cx| { thread.set_remaining_turns(iterations); - thread.send_to_model(model, cx); + thread.send_to_model(model, None, cx); thread.messages().len() })?; diff --git a/crates/gpui/src/app/entity_map.rs b/crates/gpui/src/app/entity_map.rs index fead30842d..a32b6085ad 100644 --- a/crates/gpui/src/app/entity_map.rs +++ b/crates/gpui/src/app/entity_map.rs @@ -15,7 +15,7 @@ use std::{ num::NonZeroU64, sync::{ Arc, Weak, - atomic::{AtomicUsize, Ordering::SeqCst}, + atomic::{AtomicU64, AtomicUsize, Ordering::SeqCst}, }, thread::panicking, }; @@ -572,6 +572,30 @@ impl AnyWeakEntity { ) } } + + /// Creates a weak entity that can never be upgraded. + pub fn new_invalid() -> Self { + /// To hold the invariant that all ids are unique, and considering that slotmap + /// increases their IDs from `0`, we can decrease ours from `u64::MAX` so these + /// two will never conflict (u64 is way too large). + static UNIQUE_NON_CONFLICTING_ID_GENERATOR: AtomicU64 = AtomicU64::new(u64::MAX); + let entity_id = UNIQUE_NON_CONFLICTING_ID_GENERATOR.fetch_sub(1, SeqCst); + + Self { + // Safety: + // Docs say this is safe but can be unspecified if slotmap changes the representation + // after `1.0.7`, that said, providing a valid entity_id here is not necessary as long + // as we guarantee that that `entity_id` is never used if `entity_ref_counts` equals + // to `Weak::new()` (that is, it's unable to upgrade), that is the invariant that + // actually needs to be hold true. + // + // And there is no sane reason to read an entity slot if `entity_ref_counts` can't be + // read in the first place, so we're good! + entity_id: entity_id.into(), + entity_type: TypeId::of::<()>(), + entity_ref_counts: Weak::new(), + } + } } impl std::fmt::Debug for AnyWeakEntity { @@ -707,6 +731,14 @@ impl WeakEntity { .map(|this| cx.read_entity(&this, read)), ) } + + /// Create a new weak entity that can never be upgraded. + pub fn new_invalid() -> Self { + Self { + any_entity: AnyWeakEntity::new_invalid(), + entity_type: PhantomData, + } + } } impl Hash for WeakEntity { diff --git a/crates/task/src/vscode_debug_format.rs b/crates/task/src/vscode_debug_format.rs index cecb8629a5..734064912f 100644 --- a/crates/task/src/vscode_debug_format.rs +++ b/crates/task/src/vscode_debug_format.rs @@ -83,7 +83,6 @@ impl VsCodeDebugTaskDefinition { } } -/// blah #[derive(Clone, Debug, Deserialize, PartialEq)] #[serde(rename_all = "camelCase")] pub struct VsCodeDebugTaskFile { diff --git a/crates/vim/Cargo.toml b/crates/vim/Cargo.toml index 2f4ccccaf8..9fb5c46564 100644 --- a/crates/vim/Cargo.toml +++ b/crates/vim/Cargo.toml @@ -30,7 +30,7 @@ itertools.workspace = true language.workspace = true log.workspace = true multi_buffer.workspace = true -nvim-rs = { git = "https://github.com/KillTheMule/nvim-rs", branch = "master", features = ["use_tokio"], optional = true } +nvim-rs = { git = "https://github.com/KillTheMule/nvim-rs", rev = "764dd270c642f77f10f3e19d05cc178a6cbe69f3", features = ["use_tokio"], optional = true } picker.workspace = true project.workspace = true regex.workspace = true diff --git a/tooling/workspace-hack/Cargo.toml b/tooling/workspace-hack/Cargo.toml index c7a2529172..fcb0d9bd63 100644 --- a/tooling/workspace-hack/Cargo.toml +++ b/tooling/workspace-hack/Cargo.toml @@ -90,7 +90,7 @@ regex = { version = "1" } regex-automata = { version = "0.4" } regex-syntax = { version = "0.8" } rust_decimal = { version = "1", default-features = false, features = ["maths", "serde", "std"] } -rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", features = ["fs", "net"] } +rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", default-features = false, features = ["fs", "net", "std"] } rustls = { version = "0.23", features = ["ring"] } rustls-webpki = { version = "0.103", default-features = false, features = ["aws-lc-rs", "ring", "std"] } sea-orm = { version = "1", features = ["runtime-tokio-rustls", "sqlx-postgres", "sqlx-sqlite"] } @@ -205,7 +205,7 @@ regex = { version = "1" } regex-automata = { version = "0.4" } regex-syntax = { version = "0.8" } rust_decimal = { version = "1", default-features = false, features = ["maths", "serde", "std"] } -rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", features = ["fs", "net"] } +rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", default-features = false, features = ["fs", "net", "std"] } rustls = { version = "0.23", features = ["ring"] } rustls-webpki = { version = "0.103", default-features = false, features = ["aws-lc-rs", "ring", "std"] } sea-orm = { version = "1", features = ["runtime-tokio-rustls", "sqlx-postgres", "sqlx-sqlite"] } @@ -258,8 +258,8 @@ naga = { version = "23", features = ["msl-out", "wgsl-in"] } nix = { version = "0.29", features = ["fs", "pthread", "signal"] } object = { version = "0.36", default-features = false, features = ["archive", "read_core", "unaligned", "write"] } ring = { version = "0.17", features = ["std"] } -rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", default-features = false, features = ["event", "mm", "param", "pipe", "process", "procfs", "termios", "time"] } -rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "termios", "time"] } +rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", features = ["event", "mm", "param", "pipe", "process", "termios", "time"] } +rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "net", "process", "termios", "time"] } scopeguard = { version = "1" } security-framework = { version = "3", features = ["OSX_10_14"] } security-framework-sys = { version = "2", features = ["OSX_10_14"] } @@ -283,8 +283,8 @@ nix = { version = "0.29", features = ["fs", "pthread", "signal"] } object = { version = "0.36", default-features = false, features = ["archive", "read_core", "unaligned", "write"] } proc-macro2 = { version = "1", default-features = false, features = ["span-locations"] } ring = { version = "0.17", features = ["std"] } -rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", default-features = false, features = ["event", "mm", "param", "pipe", "process", "procfs", "termios", "time"] } -rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "termios", "time"] } +rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", features = ["event", "mm", "param", "pipe", "process", "termios", "time"] } +rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "net", "process", "termios", "time"] } scopeguard = { version = "1" } security-framework = { version = "3", features = ["OSX_10_14"] } security-framework-sys = { version = "2", features = ["OSX_10_14"] } @@ -306,8 +306,8 @@ naga = { version = "23", features = ["msl-out", "wgsl-in"] } nix = { version = "0.29", features = ["fs", "pthread", "signal"] } object = { version = "0.36", default-features = false, features = ["archive", "read_core", "unaligned", "write"] } ring = { version = "0.17", features = ["std"] } -rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", default-features = false, features = ["event", "mm", "param", "pipe", "process", "procfs", "termios", "time"] } -rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "termios", "time"] } +rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", features = ["event", "mm", "param", "pipe", "process", "termios", "time"] } +rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "net", "process", "termios", "time"] } scopeguard = { version = "1" } security-framework = { version = "3", features = ["OSX_10_14"] } security-framework-sys = { version = "2", features = ["OSX_10_14"] } @@ -331,8 +331,8 @@ nix = { version = "0.29", features = ["fs", "pthread", "signal"] } object = { version = "0.36", default-features = false, features = ["archive", "read_core", "unaligned", "write"] } proc-macro2 = { version = "1", default-features = false, features = ["span-locations"] } ring = { version = "0.17", features = ["std"] } -rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", default-features = false, features = ["event", "mm", "param", "pipe", "process", "procfs", "termios", "time"] } -rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "termios", "time"] } +rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", features = ["event", "mm", "param", "pipe", "process", "termios", "time"] } +rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "net", "process", "termios", "time"] } scopeguard = { version = "1" } security-framework = { version = "3", features = ["OSX_10_14"] } security-framework-sys = { version = "2", features = ["OSX_10_14"] } @@ -356,7 +356,8 @@ gimli = { version = "0.31", default-features = false, features = ["read", "std", hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "native-tokio", "ring", "tls12"] } inout = { version = "0.1", default-features = false, features = ["block-padding"] } itertools-5ef9efb8ec2df382 = { package = "itertools", version = "0.12" } -linux-raw-sys = { version = "0.4", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "system", "xdp"] } +linux-raw-sys-274715c4dabd11b0 = { package = "linux-raw-sys", version = "0.9", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "xdp"] } +linux-raw-sys-9fbad63c4bcf4a8f = { package = "linux-raw-sys", version = "0.4", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "system", "xdp"] } mio = { version = "1", features = ["net", "os-ext"] } naga = { version = "23", features = ["spv-out", "wgsl-in"] } nix = { version = "0.29", features = ["fs", "pthread", "signal", "socket", "uio", "user"] } @@ -367,8 +368,8 @@ proc-macro2 = { version = "1", features = ["span-locations"] } quote = { version = "1" } rand-274715c4dabd11b0 = { package = "rand", version = "0.9" } ring = { version = "0.17", features = ["std"] } -rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", default-features = false, features = ["event", "mm", "param", "pipe", "process", "procfs", "pty", "shm", "stdio", "system", "termios", "time"] } -rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "termios", "time"] } +rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", features = ["event", "mm", "param", "pipe", "process", "pty", "shm", "stdio", "system", "termios", "time"] } +rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "net", "process", "termios", "time"] } scopeguard = { version = "1" } smallvec = { version = "1", default-features = false, features = ["write"] } syn-f595c2ba2a3f28df = { package = "syn", version = "2", features = ["extra-traits", "fold", "full", "visit", "visit-mut"] } @@ -396,7 +397,8 @@ gimli = { version = "0.31", default-features = false, features = ["read", "std", hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "native-tokio", "ring", "tls12"] } inout = { version = "0.1", default-features = false, features = ["block-padding"] } itertools-5ef9efb8ec2df382 = { package = "itertools", version = "0.12" } -linux-raw-sys = { version = "0.4", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "system", "xdp"] } +linux-raw-sys-274715c4dabd11b0 = { package = "linux-raw-sys", version = "0.9", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "xdp"] } +linux-raw-sys-9fbad63c4bcf4a8f = { package = "linux-raw-sys", version = "0.4", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "system", "xdp"] } mio = { version = "1", features = ["net", "os-ext"] } naga = { version = "23", features = ["spv-out", "wgsl-in"] } nix = { version = "0.29", features = ["fs", "pthread", "signal", "socket", "uio", "user"] } @@ -406,8 +408,8 @@ object = { version = "0.36", default-features = false, features = ["archive", "r proc-macro2 = { version = "1", default-features = false, features = ["span-locations"] } rand-274715c4dabd11b0 = { package = "rand", version = "0.9" } ring = { version = "0.17", features = ["std"] } -rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", default-features = false, features = ["event", "mm", "param", "pipe", "process", "procfs", "pty", "shm", "stdio", "system", "termios", "time"] } -rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "termios", "time"] } +rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", features = ["event", "mm", "param", "pipe", "process", "pty", "shm", "stdio", "system", "termios", "time"] } +rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "net", "process", "termios", "time"] } scopeguard = { version = "1" } smallvec = { version = "1", default-features = false, features = ["write"] } tokio-rustls = { version = "0.26", default-features = false, features = ["ring"] } @@ -434,7 +436,8 @@ gimli = { version = "0.31", default-features = false, features = ["read", "std", hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "native-tokio", "ring", "tls12"] } inout = { version = "0.1", default-features = false, features = ["block-padding"] } itertools-5ef9efb8ec2df382 = { package = "itertools", version = "0.12" } -linux-raw-sys = { version = "0.4", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "system", "xdp"] } +linux-raw-sys-274715c4dabd11b0 = { package = "linux-raw-sys", version = "0.9", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "xdp"] } +linux-raw-sys-9fbad63c4bcf4a8f = { package = "linux-raw-sys", version = "0.4", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "system", "xdp"] } mio = { version = "1", features = ["net", "os-ext"] } naga = { version = "23", features = ["spv-out", "wgsl-in"] } nix = { version = "0.29", features = ["fs", "pthread", "signal", "socket", "uio", "user"] } @@ -445,8 +448,8 @@ proc-macro2 = { version = "1", features = ["span-locations"] } quote = { version = "1" } rand-274715c4dabd11b0 = { package = "rand", version = "0.9" } ring = { version = "0.17", features = ["std"] } -rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", default-features = false, features = ["event", "mm", "param", "pipe", "process", "procfs", "pty", "shm", "stdio", "system", "termios", "time"] } -rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "termios", "time"] } +rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", features = ["event", "mm", "param", "pipe", "process", "pty", "shm", "stdio", "system", "termios", "time"] } +rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "net", "process", "termios", "time"] } scopeguard = { version = "1" } smallvec = { version = "1", default-features = false, features = ["write"] } syn-f595c2ba2a3f28df = { package = "syn", version = "2", features = ["extra-traits", "fold", "full", "visit", "visit-mut"] } @@ -474,7 +477,8 @@ gimli = { version = "0.31", default-features = false, features = ["read", "std", hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "native-tokio", "ring", "tls12"] } inout = { version = "0.1", default-features = false, features = ["block-padding"] } itertools-5ef9efb8ec2df382 = { package = "itertools", version = "0.12" } -linux-raw-sys = { version = "0.4", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "system", "xdp"] } +linux-raw-sys-274715c4dabd11b0 = { package = "linux-raw-sys", version = "0.9", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "xdp"] } +linux-raw-sys-9fbad63c4bcf4a8f = { package = "linux-raw-sys", version = "0.4", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "system", "xdp"] } mio = { version = "1", features = ["net", "os-ext"] } naga = { version = "23", features = ["spv-out", "wgsl-in"] } nix = { version = "0.29", features = ["fs", "pthread", "signal", "socket", "uio", "user"] } @@ -484,8 +488,8 @@ object = { version = "0.36", default-features = false, features = ["archive", "r proc-macro2 = { version = "1", default-features = false, features = ["span-locations"] } rand-274715c4dabd11b0 = { package = "rand", version = "0.9" } ring = { version = "0.17", features = ["std"] } -rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", default-features = false, features = ["event", "mm", "param", "pipe", "process", "procfs", "pty", "shm", "stdio", "system", "termios", "time"] } -rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "termios", "time"] } +rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", features = ["event", "mm", "param", "pipe", "process", "pty", "shm", "stdio", "system", "termios", "time"] } +rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "net", "process", "termios", "time"] } scopeguard = { version = "1" } smallvec = { version = "1", default-features = false, features = ["write"] } tokio-rustls = { version = "0.26", default-features = false, features = ["ring"] } @@ -506,7 +510,7 @@ hyper-rustls = { version = "0.27", default-features = false, features = ["http1" itertools-5ef9efb8ec2df382 = { package = "itertools", version = "0.12" } naga = { version = "23", features = ["spv-out", "wgsl-in"] } ring = { version = "0.17", features = ["std"] } -rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", default-features = false, features = ["event"] } +rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", features = ["event"] } scopeguard = { version = "1" } tokio-rustls = { version = "0.26", default-features = false, features = ["ring"] } tokio-socks = { version = "0.5", features = ["futures-io"] } @@ -514,7 +518,7 @@ tokio-stream = { version = "0.1", features = ["fs"] } winapi = { version = "0.3", default-features = false, features = ["cfg", "consoleapi", "errhandlingapi", "evntrace", "fileapi", "handleapi", "in6addr", "inaddr", "knownfolders", "minwinbase", "ntsecapi", "objbase", "processenv", "processthreadsapi", "shlobj", "std", "sysinfoapi", "winbase", "windef", "winerror", "winioctl"] } windows-core = { version = "0.61" } windows-numerics = { version = "0.2" } -windows-sys-73dcd821b1037cfd = { package = "windows-sys", version = "0.59", features = ["Wdk_Foundation", "Wdk_Storage_FileSystem", "Win32_NetworkManagement_IpHelper", "Win32_Networking_WinSock", "Win32_Security_Authentication_Identity", "Win32_Security_Credentials", "Win32_Security_Cryptography", "Win32_Storage_FileSystem", "Win32_System_Com", "Win32_System_Console", "Win32_System_Diagnostics_Debug", "Win32_System_IO", "Win32_System_Ioctl", "Win32_System_Kernel", "Win32_System_LibraryLoader", "Win32_System_Memory", "Win32_System_Performance", "Win32_System_Pipes", "Win32_System_Registry", "Win32_System_SystemInformation", "Win32_System_SystemServices", "Win32_System_Threading", "Win32_System_Time", "Win32_System_WindowsProgramming", "Win32_UI_Input_KeyboardAndMouse", "Win32_UI_Shell", "Win32_UI_WindowsAndMessaging"] } +windows-sys-73dcd821b1037cfd = { package = "windows-sys", version = "0.59", features = ["Wdk_Foundation", "Wdk_Storage_FileSystem", "Win32_Globalization", "Win32_NetworkManagement_IpHelper", "Win32_Networking_WinSock", "Win32_Security_Authentication_Identity", "Win32_Security_Credentials", "Win32_Security_Cryptography", "Win32_Storage_FileSystem", "Win32_System_Com", "Win32_System_Console", "Win32_System_Diagnostics_Debug", "Win32_System_IO", "Win32_System_Ioctl", "Win32_System_Kernel", "Win32_System_LibraryLoader", "Win32_System_Memory", "Win32_System_Performance", "Win32_System_Pipes", "Win32_System_Registry", "Win32_System_SystemInformation", "Win32_System_SystemServices", "Win32_System_Threading", "Win32_System_Time", "Win32_System_WindowsProgramming", "Win32_UI_Input_KeyboardAndMouse", "Win32_UI_Shell", "Win32_UI_WindowsAndMessaging"] } windows-sys-b21d60becc0929df = { package = "windows-sys", version = "0.52", features = ["Wdk_Foundation", "Wdk_Storage_FileSystem", "Wdk_System_IO", "Win32_Foundation", "Win32_Networking_WinSock", "Win32_Security", "Win32_Storage_FileSystem", "Win32_System_Console", "Win32_System_IO", "Win32_System_Pipes", "Win32_System_SystemServices", "Win32_System_Threading", "Win32_System_WindowsProgramming"] } windows-sys-c8eced492e86ede7 = { package = "windows-sys", version = "0.48", features = ["Win32_Foundation", "Win32_Globalization", "Win32_Networking_WinSock", "Win32_Security", "Win32_Storage_FileSystem", "Win32_System_Com", "Win32_System_Diagnostics_Debug", "Win32_System_IO", "Win32_System_Pipes", "Win32_System_Registry", "Win32_System_Threading", "Win32_System_Time", "Win32_UI_Shell"] } @@ -529,7 +533,7 @@ itertools-5ef9efb8ec2df382 = { package = "itertools", version = "0.12" } naga = { version = "23", features = ["spv-out", "wgsl-in"] } proc-macro2 = { version = "1", default-features = false, features = ["span-locations"] } ring = { version = "0.17", features = ["std"] } -rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", default-features = false, features = ["event"] } +rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", features = ["event"] } scopeguard = { version = "1" } tokio-rustls = { version = "0.26", default-features = false, features = ["ring"] } tokio-socks = { version = "0.5", features = ["futures-io"] } @@ -537,7 +541,7 @@ tokio-stream = { version = "0.1", features = ["fs"] } winapi = { version = "0.3", default-features = false, features = ["cfg", "consoleapi", "errhandlingapi", "evntrace", "fileapi", "handleapi", "in6addr", "inaddr", "knownfolders", "minwinbase", "ntsecapi", "objbase", "processenv", "processthreadsapi", "shlobj", "std", "sysinfoapi", "winbase", "windef", "winerror", "winioctl"] } windows-core = { version = "0.61" } windows-numerics = { version = "0.2" } -windows-sys-73dcd821b1037cfd = { package = "windows-sys", version = "0.59", features = ["Wdk_Foundation", "Wdk_Storage_FileSystem", "Win32_NetworkManagement_IpHelper", "Win32_Networking_WinSock", "Win32_Security_Authentication_Identity", "Win32_Security_Credentials", "Win32_Security_Cryptography", "Win32_Storage_FileSystem", "Win32_System_Com", "Win32_System_Console", "Win32_System_Diagnostics_Debug", "Win32_System_IO", "Win32_System_Ioctl", "Win32_System_Kernel", "Win32_System_LibraryLoader", "Win32_System_Memory", "Win32_System_Performance", "Win32_System_Pipes", "Win32_System_Registry", "Win32_System_SystemInformation", "Win32_System_SystemServices", "Win32_System_Threading", "Win32_System_Time", "Win32_System_WindowsProgramming", "Win32_UI_Input_KeyboardAndMouse", "Win32_UI_Shell", "Win32_UI_WindowsAndMessaging"] } +windows-sys-73dcd821b1037cfd = { package = "windows-sys", version = "0.59", features = ["Wdk_Foundation", "Wdk_Storage_FileSystem", "Win32_Globalization", "Win32_NetworkManagement_IpHelper", "Win32_Networking_WinSock", "Win32_Security_Authentication_Identity", "Win32_Security_Credentials", "Win32_Security_Cryptography", "Win32_Storage_FileSystem", "Win32_System_Com", "Win32_System_Console", "Win32_System_Diagnostics_Debug", "Win32_System_IO", "Win32_System_Ioctl", "Win32_System_Kernel", "Win32_System_LibraryLoader", "Win32_System_Memory", "Win32_System_Performance", "Win32_System_Pipes", "Win32_System_Registry", "Win32_System_SystemInformation", "Win32_System_SystemServices", "Win32_System_Threading", "Win32_System_Time", "Win32_System_WindowsProgramming", "Win32_UI_Input_KeyboardAndMouse", "Win32_UI_Shell", "Win32_UI_WindowsAndMessaging"] } windows-sys-b21d60becc0929df = { package = "windows-sys", version = "0.52", features = ["Wdk_Foundation", "Wdk_Storage_FileSystem", "Wdk_System_IO", "Win32_Foundation", "Win32_Networking_WinSock", "Win32_Security", "Win32_Storage_FileSystem", "Win32_System_Console", "Win32_System_IO", "Win32_System_Pipes", "Win32_System_SystemServices", "Win32_System_Threading", "Win32_System_WindowsProgramming"] } windows-sys-c8eced492e86ede7 = { package = "windows-sys", version = "0.48", features = ["Win32_Foundation", "Win32_Globalization", "Win32_Networking_WinSock", "Win32_Security", "Win32_Storage_FileSystem", "Win32_System_Com", "Win32_System_Diagnostics_Debug", "Win32_System_IO", "Win32_System_Pipes", "Win32_System_Registry", "Win32_System_Threading", "Win32_System_Time", "Win32_UI_Shell"] } @@ -557,7 +561,8 @@ gimli = { version = "0.31", default-features = false, features = ["read", "std", hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "native-tokio", "ring", "tls12"] } inout = { version = "0.1", default-features = false, features = ["block-padding"] } itertools-5ef9efb8ec2df382 = { package = "itertools", version = "0.12" } -linux-raw-sys = { version = "0.4", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "system", "xdp"] } +linux-raw-sys-274715c4dabd11b0 = { package = "linux-raw-sys", version = "0.9", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "xdp"] } +linux-raw-sys-9fbad63c4bcf4a8f = { package = "linux-raw-sys", version = "0.4", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "system", "xdp"] } mio = { version = "1", features = ["net", "os-ext"] } naga = { version = "23", features = ["spv-out", "wgsl-in"] } nix = { version = "0.29", features = ["fs", "pthread", "signal", "socket", "uio", "user"] } @@ -568,8 +573,8 @@ proc-macro2 = { version = "1", features = ["span-locations"] } quote = { version = "1" } rand-274715c4dabd11b0 = { package = "rand", version = "0.9" } ring = { version = "0.17", features = ["std"] } -rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", default-features = false, features = ["event", "mm", "param", "pipe", "process", "procfs", "pty", "shm", "stdio", "system", "termios", "time"] } -rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "termios", "time"] } +rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", features = ["event", "mm", "param", "pipe", "process", "pty", "shm", "stdio", "system", "termios", "time"] } +rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "net", "process", "termios", "time"] } scopeguard = { version = "1" } smallvec = { version = "1", default-features = false, features = ["write"] } syn-f595c2ba2a3f28df = { package = "syn", version = "2", features = ["extra-traits", "fold", "full", "visit", "visit-mut"] } @@ -597,7 +602,8 @@ gimli = { version = "0.31", default-features = false, features = ["read", "std", hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "native-tokio", "ring", "tls12"] } inout = { version = "0.1", default-features = false, features = ["block-padding"] } itertools-5ef9efb8ec2df382 = { package = "itertools", version = "0.12" } -linux-raw-sys = { version = "0.4", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "system", "xdp"] } +linux-raw-sys-274715c4dabd11b0 = { package = "linux-raw-sys", version = "0.9", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "xdp"] } +linux-raw-sys-9fbad63c4bcf4a8f = { package = "linux-raw-sys", version = "0.4", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "system", "xdp"] } mio = { version = "1", features = ["net", "os-ext"] } naga = { version = "23", features = ["spv-out", "wgsl-in"] } nix = { version = "0.29", features = ["fs", "pthread", "signal", "socket", "uio", "user"] } @@ -607,8 +613,8 @@ object = { version = "0.36", default-features = false, features = ["archive", "r proc-macro2 = { version = "1", default-features = false, features = ["span-locations"] } rand-274715c4dabd11b0 = { package = "rand", version = "0.9" } ring = { version = "0.17", features = ["std"] } -rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", default-features = false, features = ["event", "mm", "param", "pipe", "process", "procfs", "pty", "shm", "stdio", "system", "termios", "time"] } -rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "termios", "time"] } +rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", features = ["event", "mm", "param", "pipe", "process", "pty", "shm", "stdio", "system", "termios", "time"] } +rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "net", "process", "termios", "time"] } scopeguard = { version = "1" } smallvec = { version = "1", default-features = false, features = ["write"] } tokio-rustls = { version = "0.26", default-features = false, features = ["ring"] }