diff --git a/.github/workflows/assign-reviewers.yml b/.github/workflows/assign-reviewers.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a77f1812d06330b4635fe173583f0f1ce93e4e17
--- /dev/null
+++ b/.github/workflows/assign-reviewers.yml
@@ -0,0 +1,81 @@
+# Assign Reviewers — Smart team assignment based on diff weight
+#
+# Triggers on PR open and ready_for_review events. Checks out the coordinator
+# repo (zed-industries/codeowner-coordinator) to access the assignment script and rules,
+# then assigns the 1-2 most relevant teams as reviewers.
+#
+# NOTE: This file is stored in the codeowner-coordinator repo but must be deployed to
+# the zed repo at .github/workflows/assign-reviewers.yml. See INSTALL.md.
+#
+# AUTH NOTE: Uses a GitHub App (COORDINATOR_APP_ID + COORDINATOR_APP_PRIVATE_KEY)
+# for all API operations: cloning the private coordinator repo, requesting team
+# reviewers, and setting PR assignees. GITHUB_TOKEN is not used.
+
+name: Assign Reviewers
+
+on:
+ pull_request:
+ types: [opened, ready_for_review]
+
+# GITHUB_TOKEN is not used — all operations use the GitHub App token.
+# Declare minimal permissions so the default token has no write access.
+permissions: {}
+
+# Only run for PRs from within the org (not forks) — fork PRs don't have
+# write access to request team reviewers.
+jobs:
+ assign-reviewers:
+ if: >-
+ github.event.pull_request.head.repo.full_name == github.repository &&
+ github.event.pull_request.draft == false &&
+ contains(fromJSON('["MEMBER", "OWNER"]'), github.event.pull_request.author_association)
+ runs-on: ubuntu-latest
+ steps:
+ - name: Generate app token
+ id: app-token
+ uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
+ with:
+ app-id: ${{ vars.COORDINATOR_APP_ID }}
+ private-key: ${{ secrets.COORDINATOR_APP_PRIVATE_KEY }}
+ repositories: codeowner-coordinator,zed
+
+ - name: Checkout coordinator repo
+ uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
+ with:
+ repository: zed-industries/codeowner-coordinator
+ ref: main
+ path: codeowner-coordinator
+ token: ${{ steps.app-token.outputs.token }}
+ persist-credentials: false
+
+ - name: Setup Python
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+ with:
+ python-version: "3.11"
+
+ - name: Install dependencies
+ run: pip install pyyaml==6.0.3
+
+ - name: Assign reviewers
+ env:
+ GH_TOKEN: ${{ steps.app-token.outputs.token }}
+ PR_URL: ${{ github.event.pull_request.html_url }}
+ TARGET_REPO: ${{ github.repository }}
+ run: |
+ cd codeowner-coordinator
+ python .github/scripts/assign-reviewers.py \
+ --pr "$PR_URL" \
+ --apply \
+ --rules-file team-membership-rules.yml \
+ --repo "$TARGET_REPO" \
+ --org zed-industries \
+ --min-association member \
+ 2>&1 | tee /tmp/assign-reviewers-output.txt
+
+ - name: Upload output
+ if: always()
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ with:
+ name: assign-reviewers-output
+ path: /tmp/assign-reviewers-output.txt
+ retention-days: 30
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 740b33dd55790bd3cabfc75146d71854eca6375d..e7e7629825b5f487a3b00af525d36458eb91956c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -26,6 +26,8 @@ If you're looking for concrete ideas:
- [Triaged bugs with confirmed steps to reproduce](https://github.com/zed-industries/zed/issues?q=is%3Aissue%20state%3Aopen%20type%3ABug%20label%3Astate%3Areproducible).
- [Area labels](https://github.com/zed-industries/zed/labels?q=area%3A*) to browse bugs in a specific part of the product you care about (after clicking on an area label, add type:Bug to the search).
+If you're thinking about proposing or building a larger feature, read the [Zed Feature Process](./docs/src/development/feature-process.md) for how we think about feature design — what context to provide, what integration points to consider, and how to put together a strong proposal.
+
## Sending changes
The Zed culture values working code and synchronous conversations over long
diff --git a/Cargo.lock b/Cargo.lock
index f5fe136c8f62fb14b5ebd1e29b636e82a3193c38..964f5f764c48aaf535f5e2d9368b0816abf837d5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -38,7 +38,6 @@ dependencies = [
"sum_tree",
"task",
"telemetry",
- "tempfile",
"terminal",
"text",
"ui",
@@ -47,7 +46,6 @@ dependencies = [
"util",
"uuid",
"watch",
- "zlog",
]
[[package]]
@@ -81,7 +79,6 @@ dependencies = [
"fs",
"futures 0.3.31",
"gpui",
- "indoc",
"language",
"log",
"pretty_assertions",
@@ -110,7 +107,6 @@ dependencies = [
"language",
"project",
"proto",
- "release_channel",
"smallvec",
"ui",
"util",
@@ -216,11 +212,9 @@ dependencies = [
"task",
"telemetry",
"tempfile",
- "terminal",
"text",
"theme",
"thiserror 2.0.17",
- "tree-sitter-rust",
"ui",
"unindent",
"url",
@@ -228,7 +222,6 @@ dependencies = [
"uuid",
"watch",
"web_search",
- "worktree",
"zed_env_vars",
"zlog",
"zstd",
@@ -287,7 +280,6 @@ dependencies = [
"gpui_tokio",
"http_client",
"indoc",
- "language",
"language_model",
"libc",
"log",
@@ -321,7 +313,6 @@ dependencies = [
"gpui",
"language_model",
"log",
- "paths",
"project",
"regex",
"schemars",
@@ -354,7 +345,6 @@ dependencies = [
"buffer_diff",
"chrono",
"client",
- "clock",
"cloud_api_types",
"cloud_llm_client",
"collections",
@@ -400,9 +390,7 @@ dependencies = [
"prompt_store",
"proto",
"rand 0.9.2",
- "recent_projects",
"release_channel",
- "remote_connection",
"reqwest_client",
"rope",
"rules_library",
@@ -417,14 +405,12 @@ dependencies = [
"streaming_diff",
"task",
"telemetry",
- "tempfile",
"terminal",
"terminal_view",
"text",
"theme",
"time",
"time_format",
- "title_bar",
"tree-sitter-md",
"ui",
"ui_input",
@@ -673,17 +659,13 @@ dependencies = [
"anyhow",
"chrono",
"futures 0.3.31",
- "gpui",
- "gpui_tokio",
"http_client",
- "reqwest_client",
"schemars",
"serde",
"serde_json",
"settings",
"strum 0.27.2",
"thiserror 2.0.17",
- "tokio",
]
[[package]]
@@ -733,7 +715,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -895,7 +877,6 @@ dependencies = [
"futures 0.3.31",
"fuzzy",
"gpui",
- "indoc",
"itertools 0.14.0",
"language",
"language_model",
@@ -1130,7 +1111,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -1198,7 +1179,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -1228,7 +1209,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -2067,7 +2048,7 @@ dependencies = [
"regex",
"rustc-hash 2.1.1",
"shlex",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -2085,7 +2066,7 @@ dependencies = [
"regex",
"rustc-hash 2.1.1",
"shlex",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -2220,7 +2201,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustversion",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -2249,7 +2230,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -2322,7 +2303,6 @@ dependencies = [
"pretty_assertions",
"rand 0.9.2",
"rope",
- "serde_json",
"settings",
"sum_tree",
"text",
@@ -2399,7 +2379,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -2484,7 +2464,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -2506,7 +2486,6 @@ dependencies = [
"futures 0.3.31",
"gpui",
"gpui_tokio",
- "http_client",
"language",
"livekit_client",
"log",
@@ -2738,7 +2717,7 @@ dependencies = [
"quote",
"serde",
"serde_json",
- "syn 2.0.106",
+ "syn 2.0.117",
"tempfile",
"toml 0.8.23",
]
@@ -2967,7 +2946,7 @@ dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -3101,8 +3080,6 @@ name = "cloud_llm_client"
version = "0.1.0"
dependencies = [
"anyhow",
- "indoc",
- "pretty_assertions",
"serde",
"serde_json",
"strum 0.27.2",
@@ -3227,6 +3204,7 @@ dependencies = [
"serde",
"serde_json",
"text",
+ "zeta_prompt",
]
[[package]]
@@ -3234,15 +3212,11 @@ name = "collab"
version = "0.44.0"
dependencies = [
"agent",
- "agent-client-protocol",
- "agent_settings",
- "agent_ui",
"anyhow",
"assistant_slash_command",
"assistant_text_thread",
"async-trait",
"async-tungstenite",
- "audio",
"aws-config",
"aws-sdk-kinesis",
"aws-sdk-s3",
@@ -3258,10 +3232,8 @@ dependencies = [
"collab_ui",
"collections",
"command_palette_hooks",
- "context_server",
"ctor",
"dap",
- "dap-types",
"dap_adapters",
"dashmap",
"debugger_ui",
@@ -3278,7 +3250,6 @@ dependencies = [
"gpui_tokio",
"hex",
"http_client",
- "hyper 0.14.32",
"indoc",
"language",
"language_model",
@@ -3320,7 +3291,6 @@ dependencies = [
"text",
"theme",
"time",
- "title_bar",
"tokio",
"toml 0.8.23",
"tower 0.4.13",
@@ -3351,12 +3321,10 @@ dependencies = [
"futures 0.3.31",
"fuzzy",
"gpui",
- "http_client",
"log",
"menu",
"notifications",
"picker",
- "pretty_assertions",
"project",
"release_channel",
"rpc",
@@ -3369,7 +3337,6 @@ dependencies = [
"time",
"time_format",
"title_bar",
- "tree-sitter-md",
"ui",
"util",
"workspace",
@@ -3423,10 +3390,8 @@ dependencies = [
"client",
"collections",
"command_palette_hooks",
- "ctor",
"db",
"editor",
- "env_logger 0.11.8",
"fuzzy",
"go_to_line",
"gpui",
@@ -3437,7 +3402,6 @@ dependencies = [
"postage",
"project",
"serde",
- "serde_json",
"settings",
"telemetry",
"theme",
@@ -3645,24 +3609,29 @@ dependencies = [
"unicode-segmentation",
]
+[[package]]
+name = "convert_case"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "affbf0190ed2caf063e3def54ff444b449371d55c58e513a95ab98eca50adb49"
+dependencies = [
+ "unicode-segmentation",
+]
+
[[package]]
name = "copilot"
version = "0.1.0"
dependencies = [
"anyhow",
"async-std",
- "client",
- "clock",
"collections",
"command_palette_hooks",
"copilot_chat",
- "ctor",
"edit_prediction_types",
"editor",
"fs",
"futures 0.3.31",
"gpui",
- "http_client",
"icons",
"indoc",
"language",
@@ -3689,6 +3658,7 @@ dependencies = [
name = "copilot_chat"
version = "0.1.0"
dependencies = [
+ "anthropic",
"anyhow",
"collections",
"dirs 4.0.0",
@@ -4356,7 +4326,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
dependencies = [
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -4433,7 +4403,7 @@ dependencies = [
"proc-macro2",
"quote",
"scratch",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -4447,7 +4417,7 @@ dependencies = [
"indexmap",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -4465,7 +4435,7 @@ dependencies = [
"indexmap",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -4499,8 +4469,6 @@ dependencies = [
"smol",
"task",
"telemetry",
- "tree-sitter",
- "tree-sitter-go",
"util",
"zlog",
]
@@ -4562,7 +4530,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -4573,7 +4541,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
dependencies = [
"darling_core",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -4805,7 +4773,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -4827,7 +4795,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustc_version",
- "syn 2.0.106",
+ "syn 2.0.117",
"unicode-xid",
]
@@ -4837,7 +4805,7 @@ version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -4849,7 +4817,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -4871,7 +4839,6 @@ dependencies = [
"serde_json",
"settings",
"smol",
- "theme",
"ui",
"util",
"workspace",
@@ -4883,7 +4850,6 @@ name = "diagnostics"
version = "0.1.0"
dependencies = [
"anyhow",
- "client",
"collections",
"component",
"ctor",
@@ -5040,7 +5006,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -5103,7 +5069,7 @@ dependencies = [
"proc-macro2",
"quote",
"strum 0.27.2",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -5276,7 +5242,6 @@ dependencies = [
"thiserror 2.0.17",
"time",
"toml 0.8.23",
- "tree-sitter-rust",
"ui",
"util",
"uuid",
@@ -5374,7 +5339,6 @@ dependencies = [
"tree-sitter",
"util",
"zeta_prompt",
- "zlog",
]
[[package]]
@@ -5395,7 +5359,6 @@ dependencies = [
"anyhow",
"buffer_diff",
"client",
- "clock",
"cloud_llm_client",
"codestral",
"collections",
@@ -5412,18 +5375,12 @@ dependencies = [
"gpui",
"indoc",
"language",
- "language_model",
- "lsp",
"markdown",
"menu",
"multi_buffer",
"paths",
- "pretty_assertions",
"project",
"regex",
- "release_channel",
- "semver",
- "serde_json",
"settings",
"telemetry",
"text",
@@ -5434,7 +5391,6 @@ dependencies = [
"workspace",
"zed_actions",
"zeta_prompt",
- "zlog",
]
[[package]]
@@ -5463,7 +5419,6 @@ dependencies = [
"fuzzy",
"git",
"gpui",
- "http_client",
"indoc",
"itertools 0.14.0",
"language",
@@ -5478,6 +5433,8 @@ dependencies = [
"parking_lot",
"pretty_assertions",
"project",
+ "proptest",
+ "proptest-derive",
"rand 0.9.2",
"regex",
"release_channel",
@@ -5494,7 +5451,6 @@ dependencies = [
"sum_tree",
"task",
"telemetry",
- "tempfile",
"text",
"theme",
"time",
@@ -5654,7 +5610,7 @@ dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -5675,7 +5631,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -5740,7 +5696,7 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -5791,6 +5747,15 @@ dependencies = [
"libc",
]
+[[package]]
+name = "error-graph"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b920e777967421aa5f9bf34f842c0ab6ba19b3bdb4a082946093860f5858879"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "etagere"
version = "0.2.15"
@@ -5894,6 +5859,47 @@ dependencies = [
"watch",
]
+[[package]]
+name = "eval_cli"
+version = "0.1.0"
+dependencies = [
+ "acp_thread",
+ "agent",
+ "agent-client-protocol",
+ "agent_ui",
+ "anyhow",
+ "clap",
+ "client",
+ "ctrlc",
+ "debug_adapter_extension",
+ "env_logger 0.11.8",
+ "extension",
+ "feature_flags",
+ "fs",
+ "futures 0.3.31",
+ "gpui",
+ "gpui_platform",
+ "gpui_tokio",
+ "language",
+ "language_extension",
+ "language_model",
+ "language_models",
+ "languages",
+ "node_runtime",
+ "paths",
+ "project",
+ "prompt_store",
+ "release_channel",
+ "reqwest_client",
+ "serde",
+ "serde_json",
+ "settings",
+ "shellexpand 2.1.2",
+ "terminal_view",
+ "util",
+ "watch",
+]
+
[[package]]
name = "eval_utils"
version = "0.1.0"
@@ -6022,7 +6028,9 @@ dependencies = [
"serde",
"serde_json",
"serde_json_lenient",
+ "settings_content",
"snippet_provider",
+ "task",
"theme",
"tokio",
"toml 0.8.23",
@@ -6059,7 +6067,6 @@ dependencies = [
"parking_lot",
"paths",
"project",
- "rand 0.9.2",
"release_channel",
"remote",
"reqwest_client",
@@ -6119,6 +6126,12 @@ dependencies = [
"zed_actions",
]
+[[package]]
+name = "failspot"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c942e64b20ecd39933d5ff938ca4fdb6ef0d298cc3855b231179a5ef0b24948d"
+
[[package]]
name = "fallible-iterator"
version = "0.3.0"
@@ -6174,7 +6187,7 @@ checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -6209,7 +6222,6 @@ dependencies = [
name = "feedback"
version = "0.1.0"
dependencies = [
- "editor",
"gpui",
"system_specs",
"urlencoding",
@@ -6240,7 +6252,6 @@ dependencies = [
"futures 0.3.31",
"fuzzy",
"gpui",
- "language",
"menu",
"open_path_prompt",
"picker",
@@ -6473,7 +6484,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -6742,7 +6753,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -7153,7 +7164,7 @@ source = "git+https://github.com/zed-industries/gh-workflow?rev=c9eac0ed361583e1
dependencies = [
"heck 0.5.0",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -7226,7 +7237,6 @@ dependencies = [
"text",
"thiserror 2.0.17",
"time",
- "unindent",
"url",
"urlencoding",
"util",
@@ -7263,7 +7273,6 @@ dependencies = [
"menu",
"project",
"rand 0.9.2",
- "recent_projects",
"serde_json",
"settings",
"smallvec",
@@ -7314,7 +7323,6 @@ dependencies = [
"futures 0.3.31",
"fuzzy",
"git",
- "git_hosting_providers",
"gpui",
"indoc",
"itertools 0.14.0",
@@ -7402,7 +7410,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -7483,8 +7491,6 @@ dependencies = [
"settings",
"text",
"theme",
- "tree-sitter-rust",
- "tree-sitter-typescript",
"ui",
"util",
"workspace",
@@ -7503,9 +7509,9 @@ dependencies = [
[[package]]
name = "goblin"
-version = "0.8.2"
+version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b363a30c165f666402fe6a3024d3bec7ebc898f96a4a23bd1c99f8dbf3f4f47"
+checksum = "daa0a64d21a7eb230583b4c5f4e23b7e4e57974f96620f42a7e75e08ae66d745"
dependencies = [
"log",
"plain",
@@ -7615,8 +7621,8 @@ dependencies = [
"pin-project",
"pollster 0.4.0",
"postage",
- "pretty_assertions",
"profiling",
+ "proptest",
"rand 0.9.2",
"raw-window-handle",
"refineable",
@@ -7744,7 +7750,7 @@ dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -8172,7 +8178,7 @@ dependencies = [
"markup5ever 0.12.1",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -8630,7 +8636,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3"
dependencies = [
"byteorder-lite",
- "quick-error",
+ "quick-error 2.0.1",
]
[[package]]
@@ -8706,7 +8712,7 @@ checksum = "c727f80bfa4a6c6e2508d2f05b6f4bfce242030bd88ed15ae5331c5b5d30fba7"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -8801,7 +8807,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -8993,7 +8999,7 @@ checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -9415,7 +9421,6 @@ dependencies = [
"copilot_ui",
"credentials_provider",
"deepseek",
- "editor",
"extension",
"extension_host",
"fs",
@@ -9435,7 +9440,6 @@ dependencies = [
"open_router",
"partial-json-fixer",
"pretty_assertions",
- "project",
"release_channel",
"schemars",
"semver",
@@ -9563,7 +9567,6 @@ dependencies = [
"snippet",
"task",
"terminal",
- "text",
"theme",
"toml 0.8.23",
"tree-sitter",
@@ -9587,7 +9590,6 @@ dependencies = [
"unindent",
"url",
"util",
- "workspace",
]
[[package]]
@@ -9634,9 +9636,9 @@ checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8"
[[package]]
name = "libc"
-version = "0.2.177"
+version = "0.2.182"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
+checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
[[package]]
name = "libdbus-sys"
@@ -9941,7 +9943,6 @@ dependencies = [
"serde_json",
"serde_urlencoded",
"settings",
- "sha2",
"simplelog",
"smallvec",
"ui",
@@ -10205,6 +10206,7 @@ dependencies = [
"language",
"linkify",
"log",
+ "markdown",
"markup5ever_rcdom",
"mermaid-rs-renderer",
"pretty_assertions",
@@ -10263,7 +10265,7 @@ checksum = "ac84fd3f360fcc43dc5f5d186f02a94192761a080e8bc58621ad4d12296a58cf"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -10497,9 +10499,9 @@ dependencies = [
[[package]]
name = "minidump-common"
-version = "0.21.2"
+version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c4d14bcca0fd3ed165a03000480aaa364c6860c34e900cb2dafdf3b95340e77"
+checksum = "2e16d10087ae9e375bad7a40e8ef5504bc08e808ccc6019067ff9de42a84570f"
dependencies = [
"bitflags 2.10.0",
"debugid",
@@ -10512,14 +10514,16 @@ dependencies = [
[[package]]
name = "minidump-writer"
-version = "0.8.9"
+version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abcd9c8a1e6e1e9d56ce3627851f39a17ea83e17c96bc510f29d7e43d78a7d"
+checksum = "0e1fc14d6ded915b8e850801465e7096f77ed60bf87e4e85878d463720d9dc4d"
dependencies = [
"bitflags 2.10.0",
"byteorder",
"cfg-if",
"crash-context",
+ "error-graph",
+ "failspot",
"goblin",
"libc",
"log",
@@ -10527,18 +10531,20 @@ dependencies = [
"memmap2",
"memoffset",
"minidump-common",
- "nix 0.28.0",
+ "nix 0.29.0",
"procfs-core",
"scroll",
+ "serde",
+ "serde_json",
"tempfile",
- "thiserror 1.0.69",
+ "thiserror 2.0.17",
]
[[package]]
name = "minidumper"
-version = "0.8.3"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b4ebc9d1f8847ec1d078f78b35ed598e0ebefa1f242d5f83cd8d7f03960a7d1"
+checksum = "10d9254e42a48098d045472a5c0cb892007a42e25342eddbf2642f6978bf381a"
dependencies = [
"cfg-if",
"crash-context",
@@ -10548,7 +10554,7 @@ dependencies = [
"parking_lot",
"polling",
"scroll",
- "thiserror 1.0.69",
+ "thiserror 2.0.17",
"uds",
]
@@ -10681,7 +10687,6 @@ dependencies = [
"log",
"parking_lot",
"pretty_assertions",
- "project",
"rand 0.9.2",
"rope",
"serde",
@@ -10732,7 +10737,7 @@ dependencies = [
[[package]]
name = "naga"
version = "28.0.1"
-source = "git+https://github.com/zed-industries/wgpu?rev=9459e95113c5bd116b2cc2c87e8424b28059e17c#9459e95113c5bd116b2cc2c87e8424b28059e17c"
+source = "git+https://github.com/zed-industries/wgpu?rev=465557eccfe77c840a9b4936f1408da9503372c4#465557eccfe77c840a9b4936f1408da9503372c4"
dependencies = [
"arrayvec",
"bit-set",
@@ -10959,12 +10964,10 @@ dependencies = [
"anyhow",
"channel",
"client",
- "collections",
"component",
"db",
"gpui",
"rpc",
- "settings",
"sum_tree",
"time",
"ui",
@@ -11130,7 +11133,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -11213,7 +11216,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -11606,7 +11609,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -11635,7 +11638,7 @@ checksum = "969ccca8ffc4fb105bd131a228107d5c9dd89d9d627edf3295cbe979156f9712"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -11693,7 +11696,7 @@ dependencies = [
"proc-macro2",
"proc-macro2-diagnostics",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -11715,8 +11718,6 @@ dependencies = [
"settings",
"smol",
"theme",
- "tree-sitter-rust",
- "tree-sitter-typescript",
"ui",
"util",
"workspace",
@@ -11803,7 +11804,7 @@ dependencies = [
"by_address",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -12066,7 +12067,7 @@ dependencies = [
"pest_meta",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -12545,7 +12546,7 @@ dependencies = [
"phf_shared 0.11.3",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -12558,7 +12559,7 @@ dependencies = [
"phf_shared 0.12.1",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -12584,14 +12585,12 @@ name = "picker"
version = "0.1.0"
dependencies = [
"anyhow",
- "ctor",
"editor",
- "env_logger 0.11.8",
"gpui",
"menu",
"schemars",
"serde",
- "serde_json",
+ "settings",
"theme",
"ui",
"ui_input",
@@ -12622,7 +12621,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -12946,7 +12945,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -13010,7 +13009,7 @@ dependencies = [
"proc-macro-error-attr2",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -13030,19 +13029,20 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
"version_check",
"yansi",
]
[[package]]
name = "procfs-core"
-version = "0.16.0"
+version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d3554923a69f4ce04c4a754260c338f505ce22642d3830e049a399fc2059a29"
+checksum = "239df02d8349b06fc07398a3a1697b06418223b1c7725085e801e7c0fc6a12ec"
dependencies = [
"bitflags 2.10.0",
"hex",
+ "serde",
]
[[package]]
@@ -13061,7 +13061,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b"
dependencies = [
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -13080,8 +13080,6 @@ dependencies = [
"collections",
"context_server",
"dap",
- "dap_adapters",
- "db",
"encoding_rs",
"extension",
"fancy-regex",
@@ -13188,7 +13186,6 @@ dependencies = [
"pretty_assertions",
"project",
"rayon",
- "remote_connection",
"schemars",
"search",
"serde",
@@ -13270,6 +13267,47 @@ dependencies = [
"uuid",
]
+[[package]]
+name = "proptest"
+version = "1.10.0"
+source = "git+https://github.com/proptest-rs/proptest?rev=3dca198a8fef1b32e3a66f1e1897c955b4dc5b5b#3dca198a8fef1b32e3a66f1e1897c955b4dc5b5b"
+dependencies = [
+ "bit-set",
+ "bit-vec",
+ "bitflags 2.10.0",
+ "num-traits",
+ "proptest-macro",
+ "rand 0.9.2",
+ "rand_chacha 0.9.0",
+ "rand_xorshift",
+ "regex-syntax",
+ "rusty-fork",
+ "tempfile",
+ "unarray",
+]
+
+[[package]]
+name = "proptest-derive"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c57924a81864dddafba92e1bf92f9bf82f97096c44489548a60e888e1547549b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "proptest-macro"
+version = "0.5.0"
+source = "git+https://github.com/proptest-rs/proptest?rev=3dca198a8fef1b32e3a66f1e1897c955b4dc5b5b#3dca198a8fef1b32e3a66f1e1897c955b4dc5b5b"
+dependencies = [
+ "convert_case 0.11.0",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
[[package]]
name = "prost"
version = "0.9.0"
@@ -13327,7 +13365,7 @@ dependencies = [
"prost 0.12.6",
"prost-types 0.12.6",
"regex",
- "syn 2.0.106",
+ "syn 2.0.117",
"tempfile",
]
@@ -13354,7 +13392,7 @@ dependencies = [
"itertools 0.12.1",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -13381,11 +13419,9 @@ name = "proto"
version = "0.1.0"
dependencies = [
"anyhow",
- "collections",
"prost 0.9.0",
"prost-build 0.9.0",
"serde",
- "typed-path",
]
[[package]]
@@ -13522,6 +13558,12 @@ dependencies = [
"bytemuck",
]
+[[package]]
+name = "quick-error"
+version = "1.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
+
[[package]]
name = "quick-error"
version = "2.0.1"
@@ -13747,6 +13789,15 @@ dependencies = [
"rand_core 0.6.4",
]
+[[package]]
+name = "rand_xorshift"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a"
+dependencies = [
+ "rand_core 0.9.3",
+]
+
[[package]]
name = "random_choice"
version = "0.3.2"
@@ -13821,7 +13872,7 @@ dependencies = [
"avif-serialize",
"imgref",
"loop9",
- "quick-error",
+ "quick-error 2.0.1",
"rav1e",
"rayon",
"rgb",
@@ -13923,7 +13974,6 @@ dependencies = [
"anyhow",
"askpass",
"chrono",
- "dap",
"db",
"dev_container",
"editor",
@@ -14021,7 +14071,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -14172,7 +14222,6 @@ dependencies = [
"collections",
"crash-handler",
"crashes",
- "dap",
"dap_adapters",
"debug_adapter_extension",
"editor",
@@ -14204,7 +14253,6 @@ dependencies = [
"paths",
"pretty_assertions",
"project",
- "prompt_store",
"proto",
"rayon",
"release_channel",
@@ -14228,7 +14276,6 @@ dependencies = [
"uuid",
"watch",
"windows 0.61.3",
- "workspace",
"worktree",
"zlog",
]
@@ -14262,7 +14309,6 @@ dependencies = [
"collections",
"command_palette_hooks",
"editor",
- "env_logger 0.11.8",
"feature_flags",
"file_icons",
"futures 0.3.31",
@@ -14390,7 +14436,6 @@ dependencies = [
"anyhow",
"bytes 1.11.1",
"futures 0.3.31",
- "gpui",
"gpui_util",
"http_client",
"http_client_tls",
@@ -14435,20 +14480,6 @@ dependencies = [
"bytemuck",
]
-[[package]]
-name = "rich_text"
-version = "0.1.0"
-dependencies = [
- "futures 0.3.31",
- "gpui",
- "language",
- "linkify",
- "pulldown-cmark 0.13.0",
- "theme",
- "ui",
- "util",
-]
-
[[package]]
name = "ring"
version = "0.17.14"
@@ -14698,7 +14729,7 @@ dependencies = [
"proc-macro2",
"quote",
"rust-embed-utils",
- "syn 2.0.106",
+ "syn 2.0.117",
"walkdir",
]
@@ -14952,6 +14983,18 @@ version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+[[package]]
+name = "rusty-fork"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2"
+dependencies = [
+ "fnv",
+ "quick-error 1.2.3",
+ "tempfile",
+ "wait-timeout",
+]
+
[[package]]
name = "rustybuzz"
version = "0.20.1"
@@ -15071,7 +15114,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -15132,7 +15175,7 @@ checksum = "1783eabc414609e28a5ba76aee5ddd52199f7107a0b24c2e9746a1ecc34a683d"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -15161,7 +15204,7 @@ dependencies = [
"proc-macro-error2",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -15203,7 +15246,7 @@ dependencies = [
"proc-macro2",
"quote",
"sea-bae",
- "syn 2.0.106",
+ "syn 2.0.117",
"unicode-ident",
]
@@ -15252,7 +15295,6 @@ dependencies = [
"any_vec",
"anyhow",
"bitflags 2.10.0",
- "client",
"collections",
"editor",
"fs",
@@ -15388,7 +15430,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -15399,7 +15441,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -15457,7 +15499,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -15597,18 +15639,16 @@ version = "0.1.0"
dependencies = [
"quote",
"settings",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
name = "settings_profile_selector"
version = "0.1.0"
dependencies = [
- "client",
"editor",
"fuzzy",
"gpui",
- "language",
"menu",
"picker",
"project",
@@ -15627,9 +15667,7 @@ dependencies = [
"agent",
"agent_settings",
"anyhow",
- "assets",
"audio",
- "client",
"codestral",
"component",
"copilot",
@@ -15647,13 +15685,11 @@ dependencies = [
"language",
"log",
"menu",
- "node_runtime",
"paths",
"picker",
"platform_title_bar",
"pretty_assertions",
"project",
- "recent_projects",
"regex",
"release_channel",
"rodio",
@@ -15661,7 +15697,6 @@ dependencies = [
"search",
"serde",
"serde_json",
- "session",
"settings",
"shell_command_parser",
"strum 0.27.2",
@@ -15672,7 +15707,6 @@ dependencies = [
"util",
"workspace",
"zed_actions",
- "zlog",
]
[[package]]
@@ -15781,22 +15815,26 @@ name = "sidebar"
version = "0.1.0"
dependencies = [
"acp_thread",
+ "agent",
+ "agent-client-protocol",
"agent_ui",
+ "assistant_text_thread",
"chrono",
"editor",
"feature_flags",
"fs",
- "fuzzy",
"gpui",
- "picker",
+ "language_model",
+ "menu",
"project",
"recent_projects",
+ "serde_json",
"settings",
"theme",
"ui",
- "ui_input",
"util",
"workspace",
+ "zed_actions",
]
[[package]]
@@ -15968,7 +16006,7 @@ checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -16146,7 +16184,7 @@ version = "0.1.0"
dependencies = [
"sqlez",
"sqlformat",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -16223,7 +16261,7 @@ dependencies = [
"quote",
"sqlx-core",
"sqlx-macros-core",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -16246,7 +16284,7 @@ dependencies = [
"sqlx-mysql",
"sqlx-postgres",
"sqlx-sqlite",
- "syn 2.0.106",
+ "syn 2.0.117",
"tokio",
"url",
]
@@ -16405,7 +16443,7 @@ checksum = "172175341049678163e979d9107ca3508046d4d2a7c6682bee46ac541b17db69"
dependencies = [
"proc-macro-error2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -16548,7 +16586,7 @@ dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -16564,6 +16602,7 @@ dependencies = [
"arrayvec",
"ctor",
"log",
+ "proptest",
"rand 0.9.2",
"rayon",
"tracing",
@@ -16849,9 +16888,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.106"
+version = "2.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
dependencies = [
"proc-macro2",
"quote",
@@ -16890,7 +16929,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -17061,13 +17100,11 @@ dependencies = [
name = "tab_switcher"
version = "0.1.0"
dependencies = [
- "anyhow",
"collections",
"ctor",
"editor",
"fuzzy",
"gpui",
- "language",
"menu",
"picker",
"project",
@@ -17256,7 +17293,6 @@ dependencies = [
"release_channel",
"schemars",
"serde",
- "serde_json",
"settings",
"smol",
"sysinfo 0.37.2",
@@ -17288,7 +17324,6 @@ dependencies = [
"assistant_slash_command",
"async-recursion",
"breadcrumbs",
- "client",
"collections",
"db",
"dirs 4.0.0",
@@ -17301,7 +17336,6 @@ dependencies = [
"menu",
"pretty_assertions",
"project",
- "rand 0.9.2",
"regex",
"schemars",
"serde",
@@ -17326,7 +17360,6 @@ dependencies = [
"collections",
"ctor",
"gpui",
- "http_client",
"log",
"parking_lot",
"postage",
@@ -17440,7 +17473,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -17451,7 +17484,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -17472,7 +17505,7 @@ dependencies = [
"fax",
"flate2",
"half",
- "quick-error",
+ "quick-error 2.0.1",
"weezl",
"zune-jpeg",
]
@@ -17629,15 +17662,12 @@ dependencies = [
"chrono",
"client",
"cloud_api_types",
- "collections",
"db",
"feature_flags",
"git_ui",
"gpui",
- "http_client",
"notifications",
"platform_title_bar",
- "pretty_assertions",
"project",
"recent_projects",
"release_channel",
@@ -17651,7 +17681,6 @@ dependencies = [
"story",
"telemetry",
"theme",
- "tree-sitter-md",
"ui",
"util",
"windows 0.61.3",
@@ -17695,7 +17724,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -18033,7 +18062,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -18128,7 +18157,7 @@ checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -18481,12 +18510,6 @@ dependencies = [
"utf-8",
]
-[[package]]
-name = "typed-path"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c462d18470a2857aa657d338af5fa67170bb48bcc80a296710ce3b0802a32566"
-
[[package]]
name = "typeid"
version = "1.0.3"
@@ -18585,7 +18608,7 @@ version = "0.1.0"
dependencies = [
"component",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
"ui",
]
@@ -18602,6 +18625,12 @@ dependencies = [
"workspace",
]
+[[package]]
+name = "unarray"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94"
+
[[package]]
name = "unicase"
version = "2.8.1"
@@ -18807,7 +18836,6 @@ dependencies = [
"git2",
"globset",
"gpui_util",
- "indoc",
"itertools 0.14.0",
"libc",
"log",
@@ -18840,7 +18868,7 @@ version = "0.1.0"
dependencies = [
"perf",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -18952,7 +18980,6 @@ name = "vim"
version = "0.1.0"
dependencies = [
"anyhow",
- "assets",
"async-compat",
"async-trait",
"collections",
@@ -18992,7 +19019,6 @@ dependencies = [
"task",
"text",
"theme",
- "title_bar",
"tokio",
"ui",
"util",
@@ -19058,6 +19084,15 @@ dependencies = [
"serde",
]
+[[package]]
+name = "wait-timeout"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "waker-fn"
version = "1.2.0"
@@ -19187,7 +19222,7 @@ dependencies = [
"bumpalo",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
"wasm-bindgen-shared",
]
@@ -19483,7 +19518,7 @@ dependencies = [
"anyhow",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
"wasmtime-component-util",
"wasmtime-wit-bindgen",
"wit-parser 0.229.0",
@@ -19598,7 +19633,7 @@ checksum = "d0963c1438357a3d8c0efe152b4ef5259846c1cf8b864340270744fe5b3bae5e"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -19691,7 +19726,6 @@ dependencies = [
"futures 0.3.31",
"gpui",
"parking_lot",
- "rand 0.9.2",
"zlog",
]
@@ -19923,7 +19957,7 @@ checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3"
[[package]]
name = "wgpu"
version = "28.0.1"
-source = "git+https://github.com/zed-industries/wgpu?rev=9459e95113c5bd116b2cc2c87e8424b28059e17c#9459e95113c5bd116b2cc2c87e8424b28059e17c"
+source = "git+https://github.com/zed-industries/wgpu?rev=465557eccfe77c840a9b4936f1408da9503372c4#465557eccfe77c840a9b4936f1408da9503372c4"
dependencies = [
"arrayvec",
"bitflags 2.10.0",
@@ -19952,7 +19986,7 @@ dependencies = [
[[package]]
name = "wgpu-core"
version = "28.0.1"
-source = "git+https://github.com/zed-industries/wgpu?rev=9459e95113c5bd116b2cc2c87e8424b28059e17c#9459e95113c5bd116b2cc2c87e8424b28059e17c"
+source = "git+https://github.com/zed-industries/wgpu?rev=465557eccfe77c840a9b4936f1408da9503372c4#465557eccfe77c840a9b4936f1408da9503372c4"
dependencies = [
"arrayvec",
"bit-set",
@@ -19983,7 +20017,7 @@ dependencies = [
[[package]]
name = "wgpu-core-deps-apple"
version = "28.0.1"
-source = "git+https://github.com/zed-industries/wgpu?rev=9459e95113c5bd116b2cc2c87e8424b28059e17c#9459e95113c5bd116b2cc2c87e8424b28059e17c"
+source = "git+https://github.com/zed-industries/wgpu?rev=465557eccfe77c840a9b4936f1408da9503372c4#465557eccfe77c840a9b4936f1408da9503372c4"
dependencies = [
"wgpu-hal",
]
@@ -19991,7 +20025,7 @@ dependencies = [
[[package]]
name = "wgpu-core-deps-emscripten"
version = "28.0.1"
-source = "git+https://github.com/zed-industries/wgpu?rev=9459e95113c5bd116b2cc2c87e8424b28059e17c#9459e95113c5bd116b2cc2c87e8424b28059e17c"
+source = "git+https://github.com/zed-industries/wgpu?rev=465557eccfe77c840a9b4936f1408da9503372c4#465557eccfe77c840a9b4936f1408da9503372c4"
dependencies = [
"wgpu-hal",
]
@@ -19999,7 +20033,7 @@ dependencies = [
[[package]]
name = "wgpu-core-deps-windows-linux-android"
version = "28.0.1"
-source = "git+https://github.com/zed-industries/wgpu?rev=9459e95113c5bd116b2cc2c87e8424b28059e17c#9459e95113c5bd116b2cc2c87e8424b28059e17c"
+source = "git+https://github.com/zed-industries/wgpu?rev=465557eccfe77c840a9b4936f1408da9503372c4#465557eccfe77c840a9b4936f1408da9503372c4"
dependencies = [
"wgpu-hal",
]
@@ -20007,7 +20041,7 @@ dependencies = [
[[package]]
name = "wgpu-hal"
version = "28.0.1"
-source = "git+https://github.com/zed-industries/wgpu?rev=9459e95113c5bd116b2cc2c87e8424b28059e17c#9459e95113c5bd116b2cc2c87e8424b28059e17c"
+source = "git+https://github.com/zed-industries/wgpu?rev=465557eccfe77c840a9b4936f1408da9503372c4#465557eccfe77c840a9b4936f1408da9503372c4"
dependencies = [
"android_system_properties",
"arrayvec",
@@ -20054,7 +20088,7 @@ dependencies = [
[[package]]
name = "wgpu-types"
version = "28.0.1"
-source = "git+https://github.com/zed-industries/wgpu?rev=9459e95113c5bd116b2cc2c87e8424b28059e17c#9459e95113c5bd116b2cc2c87e8424b28059e17c"
+source = "git+https://github.com/zed-industries/wgpu?rev=465557eccfe77c840a9b4936f1408da9503372c4#465557eccfe77c840a9b4936f1408da9503372c4"
dependencies = [
"bitflags 2.10.0",
"bytemuck",
@@ -20136,7 +20170,7 @@ dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
"witx",
]
@@ -20148,7 +20182,7 @@ checksum = "d873bb5b59ca703b5e41562e96a4796d1af61bf4cf80bf8a7abda755a380ec1c"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
"wiggle-generate",
]
@@ -20371,7 +20405,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -20382,7 +20416,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -20393,7 +20427,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -20404,7 +20438,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -20415,7 +20449,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -20426,7 +20460,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -21064,7 +21098,7 @@ dependencies = [
"heck 0.5.0",
"indexmap",
"prettyplease",
- "syn 2.0.106",
+ "syn 2.0.117",
"wasm-metadata 0.227.1",
"wit-bindgen-core 0.41.0",
"wit-component 0.227.1",
@@ -21080,7 +21114,7 @@ dependencies = [
"heck 0.5.0",
"indexmap",
"prettyplease",
- "syn 2.0.106",
+ "syn 2.0.117",
"wasm-metadata 0.244.0",
"wit-bindgen-core 0.51.0",
"wit-component 0.244.0",
@@ -21095,7 +21129,7 @@ dependencies = [
"anyhow",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
"wit-bindgen-core 0.22.0",
"wit-bindgen-rust 0.22.0",
]
@@ -21110,7 +21144,7 @@ dependencies = [
"prettyplease",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
"wit-bindgen-core 0.41.0",
"wit-bindgen-rust 0.41.0",
]
@@ -21125,7 +21159,7 @@ dependencies = [
"prettyplease",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
"wit-bindgen-core 0.51.0",
"wit-bindgen-rust 0.51.0",
]
@@ -21283,7 +21317,6 @@ dependencies = [
"clock",
"collections",
"component",
- "dap",
"db",
"feature_flags",
"fs",
@@ -21336,9 +21369,7 @@ dependencies = [
"futures 0.3.31",
"fuzzy",
"git",
- "git2",
"gpui",
- "http_client",
"ignore",
"language",
"log",
@@ -21656,7 +21687,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
"synstructure",
]
@@ -21668,7 +21699,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
"synstructure",
]
@@ -21716,7 +21747,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
"zbus_names",
"zvariant",
"zvariant_utils",
@@ -21772,7 +21803,6 @@ dependencies = [
"copilot_ui",
"crashes",
"csv_preview",
- "dap",
"dap_adapters",
"db",
"debug_adapter_extension",
@@ -21882,8 +21912,6 @@ dependencies = [
"title_bar",
"toolchain_selector",
"tracing",
- "tree-sitter-md",
- "tree-sitter-rust",
"ui",
"ui_prompt",
"url",
@@ -22114,7 +22142,7 @@ checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -22134,7 +22162,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
"synstructure",
]
@@ -22155,7 +22183,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -22212,7 +22240,7 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
]
[[package]]
@@ -22374,7 +22402,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
- "syn 2.0.106",
+ "syn 2.0.117",
"zvariant_utils",
]
@@ -22387,6 +22415,6 @@ dependencies = [
"proc-macro2",
"quote",
"serde",
- "syn 2.0.106",
+ "syn 2.0.117",
"winnow",
]
diff --git a/Cargo.toml b/Cargo.toml
index b8e57bda7e46ea45451fedd6759268235c7d71ab..b6760fa917da7e051fd60a1375be49d516fcf113 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -66,6 +66,7 @@ members = [
"crates/encoding_selector",
"crates/etw_tracing",
"crates/eval",
+ "crates/eval_cli",
"crates/eval_utils",
"crates/explorer_command_injector",
"crates/extension",
@@ -158,7 +159,6 @@ members = [
"crates/remote_server",
"crates/repl",
"crates/reqwest_client",
- "crates/rich_text",
"crates/rope",
"crates/rpc",
"crates/rules_library",
@@ -595,7 +595,7 @@ lsp-types = { git = "https://github.com/zed-industries/lsp-types", rev = "a4f410
mach2 = "0.5"
markup5ever_rcdom = "0.3.0"
metal = "0.33"
-minidumper = "0.8"
+minidumper = "0.9"
moka = { version = "0.12.10", features = ["sync"] }
naga = { version = "28.0", features = ["wgsl-in"] }
nanoid = "0.4"
@@ -649,6 +649,9 @@ postage = { version = "0.5", features = ["futures-traits"] }
pretty_assertions = { version = "1.3.0", features = ["unstable"] }
proc-macro2 = "1.0.93"
profiling = "1"
+# replace this with main when #635 is merged
+proptest = { git = "https://github.com/proptest-rs/proptest", rev = "3dca198a8fef1b32e3a66f1e1897c955b4dc5b5b", features = ["attr-macro"] }
+proptest-derive = "0.8.0"
prost = "0.9"
prost-build = "0.9"
prost-types = "0.9"
@@ -779,7 +782,7 @@ wax = "0.7"
which = "6.0.0"
wasm-bindgen = "0.2.113"
web-time = "1.1.0"
-wgpu = { git = "https://github.com/zed-industries/wgpu", rev = "9459e95113c5bd116b2cc2c87e8424b28059e17c" }
+wgpu = { git = "https://github.com/zed-industries/wgpu", rev = "465557eccfe77c840a9b4936f1408da9503372c4" }
windows-core = "0.61"
yawc = "0.2.5"
zeroize = "1.8"
diff --git a/assets/icons/list_collapse.svg b/assets/icons/list_collapse.svg
index f18bc550b90228c2f689848b86cfc5bea3d6ff50..dbdb2aaa4537c25ba1867d4957c23819af425835 100644
--- a/assets/icons/list_collapse.svg
+++ b/assets/icons/list_collapse.svg
@@ -1 +1,7 @@
-
+
diff --git a/assets/icons/new_thread.svg b/assets/icons/new_thread.svg
new file mode 100644
index 0000000000000000000000000000000000000000..19b8fa25ea30ed47a57a5d5f83d62f2b4b56b61e
--- /dev/null
+++ b/assets/icons/new_thread.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/icons/open_folder.svg b/assets/icons/open_folder.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c4aa32b29cc1048fd4ecd8b1b4d32b68ae0a8ad3
--- /dev/null
+++ b/assets/icons/open_folder.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/keymaps/default-linux.json b/assets/keymaps/default-linux.json
index 7e01245ec62b2590a1c88fef5946b7d06463968d..cb5cef24c50f9f9ac637f3ac70adb24d37e56d61 100644
--- a/assets/keymaps/default-linux.json
+++ b/assets/keymaps/default-linux.json
@@ -258,6 +258,7 @@
"ctrl-shift-j": "agent::ToggleNavigationMenu",
"ctrl-alt-i": "agent::ToggleOptionsMenu",
"ctrl-alt-shift-n": "agent::ToggleNewThreadMenu",
+ "ctrl-alt-shift-t": "agent::ToggleStartThreadInSelector",
"shift-alt-escape": "agent::ExpandMessageEditor",
"ctrl->": "agent::AddSelectionToThread",
"ctrl-shift-e": "project_panel::ToggleFocus",
@@ -673,6 +674,9 @@
"use_key_equivalents": true,
"bindings": {
"ctrl-n": "multi_workspace::NewWorkspaceInWindow",
+ "left": "agents_sidebar::CollapseSelectedEntry",
+ "right": "agents_sidebar::ExpandSelectedEntry",
+ "enter": "menu::Confirm",
},
},
{
@@ -815,7 +819,7 @@
},
},
{
- "context": "!ContextEditor > Editor && mode == full",
+ "context": "!ContextEditor && !AcpThread > Editor && mode == full",
"bindings": {
"alt-enter": "editor::OpenExcerpts",
"shift-enter": "editor::ExpandExcerpts",
@@ -979,6 +983,7 @@
"ctrl-shift-enter": "git::Amend",
"ctrl-space": "git::StageAll",
"ctrl-shift-space": "git::UnstageAll",
+ "ctrl-k ctrl-r": "git::RestoreAndNext",
},
},
{
diff --git a/assets/keymaps/default-macos.json b/assets/keymaps/default-macos.json
index 43d6419575fc698110cd5a033c01127ac6543f9a..08fb63868be875f41f6c461354b46f1081a2026f 100644
--- a/assets/keymaps/default-macos.json
+++ b/assets/keymaps/default-macos.json
@@ -297,6 +297,7 @@
"cmd-shift-j": "agent::ToggleNavigationMenu",
"cmd-alt-m": "agent::ToggleOptionsMenu",
"cmd-alt-shift-n": "agent::ToggleNewThreadMenu",
+ "cmd-alt-shift-t": "agent::ToggleStartThreadInSelector",
"shift-alt-escape": "agent::ExpandMessageEditor",
"cmd->": "agent::AddSelectionToThread",
"cmd-shift-e": "project_panel::ToggleFocus",
@@ -741,6 +742,9 @@
"use_key_equivalents": true,
"bindings": {
"cmd-n": "multi_workspace::NewWorkspaceInWindow",
+ "left": "agents_sidebar::CollapseSelectedEntry",
+ "right": "agents_sidebar::ExpandSelectedEntry",
+ "enter": "menu::Confirm",
},
},
{
@@ -878,7 +882,7 @@
},
},
{
- "context": "!ContextEditor > Editor && mode == full",
+ "context": "!ContextEditor && !AcpThread > Editor && mode == full",
"use_key_equivalents": true,
"bindings": {
"alt-enter": "editor::OpenExcerpts",
@@ -1030,6 +1034,7 @@
"cmd-shift-enter": "git::Amend",
"cmd-ctrl-y": "git::StageAll",
"cmd-ctrl-shift-y": "git::UnstageAll",
+ "cmd-alt-z": "git::RestoreAndNext",
},
},
{
diff --git a/assets/keymaps/default-windows.json b/assets/keymaps/default-windows.json
index 22541368cecfc6a645e2b8b7ce55a6711491a012..600025e2069978f3020afb5cb978d05a53317682 100644
--- a/assets/keymaps/default-windows.json
+++ b/assets/keymaps/default-windows.json
@@ -259,6 +259,7 @@
"shift-alt-j": "agent::ToggleNavigationMenu",
"shift-alt-i": "agent::ToggleOptionsMenu",
"ctrl-shift-alt-n": "agent::ToggleNewThreadMenu",
+ "ctrl-shift-alt-t": "agent::ToggleStartThreadInSelector",
"shift-alt-escape": "agent::ExpandMessageEditor",
"ctrl-shift-.": "agent::AddSelectionToThread",
"ctrl-shift-e": "project_panel::ToggleFocus",
@@ -677,6 +678,9 @@
"use_key_equivalents": true,
"bindings": {
"ctrl-n": "multi_workspace::NewWorkspaceInWindow",
+ "left": "agents_sidebar::CollapseSelectedEntry",
+ "right": "agents_sidebar::ExpandSelectedEntry",
+ "enter": "menu::Confirm",
},
},
{
@@ -817,7 +821,7 @@
},
},
{
- "context": "!ContextEditor > Editor && mode == full",
+ "context": "!ContextEditor && !AcpThread > Editor && mode == full",
"use_key_equivalents": true,
"bindings": {
"alt-enter": "editor::OpenExcerpts",
@@ -980,6 +984,7 @@
"ctrl-shift-enter": "git::Amend",
"ctrl-space": "git::StageAll",
"ctrl-shift-space": "git::UnstageAll",
+ "ctrl-k ctrl-r": "git::RestoreAndNext",
},
},
{
diff --git a/assets/keymaps/linux/jetbrains.json b/assets/keymaps/linux/jetbrains.json
index bdf3949b3f9203220978ff599e0187513d6a976f..98d5cf93106f35e488ab70a60468fa2239cb08c0 100644
--- a/assets/keymaps/linux/jetbrains.json
+++ b/assets/keymaps/linux/jetbrains.json
@@ -81,6 +81,13 @@
"ctrl-\\": "assistant::InlineAssist",
},
},
+ {
+ "context": "Editor && mode == auto_height",
+ "bindings": {
+ "shift-enter": "editor::Newline",
+ "ctrl-shift-enter": "editor::NewlineBelow",
+ },
+ },
{
"context": "BufferSearchBar",
"bindings": {
diff --git a/assets/keymaps/macos/jetbrains.json b/assets/keymaps/macos/jetbrains.json
index c9106e4d49671f16917b1322824c2edfcd0e7700..8612e07c4719dfdbf67762c89505cc2da0cfa000 100644
--- a/assets/keymaps/macos/jetbrains.json
+++ b/assets/keymaps/macos/jetbrains.json
@@ -79,6 +79,13 @@
"cmd-\\": "assistant::InlineAssist",
},
},
+ {
+ "context": "Editor && mode == auto_height",
+ "bindings": {
+ "shift-enter": "editor::Newline",
+ "ctrl-shift-enter": "editor::NewlineBelow",
+ },
+ },
{
"context": "BufferSearchBar",
"bindings": {
diff --git a/crates/acp_thread/Cargo.toml b/crates/acp_thread/Cargo.toml
index fe47db0aab9917274d6ee7f74bb3bb4bedb3fab3..1c87abbfa21e3dc4b868203a09040b4356c0d1f9 100644
--- a/crates/acp_thread/Cargo.toml
+++ b/crates/acp_thread/Cargo.toml
@@ -61,7 +61,5 @@ indoc.workspace = true
parking_lot.workspace = true
project = { workspace = true, "features" = ["test-support"] }
rand.workspace = true
-tempfile.workspace = true
util.workspace = true
settings.workspace = true
-zlog.workspace = true
diff --git a/crates/acp_thread/src/acp_thread.rs b/crates/acp_thread/src/acp_thread.rs
index 1b9271918884dc020986577926d9578e3a6f049c..58252eaddca553eb1da4c960a829a88afb9eb497 100644
--- a/crates/acp_thread/src/acp_thread.rs
+++ b/crates/acp_thread/src/acp_thread.rs
@@ -952,8 +952,11 @@ struct RunningTurn {
}
pub struct AcpThread {
+ session_id: acp::SessionId,
+ cwd: Option,
parent_session_id: Option,
title: SharedString,
+ provisional_title: Option,
entries: Vec,
plan: Plan,
project: Entity,
@@ -962,7 +965,6 @@ pub struct AcpThread {
turn_id: u32,
running_turn: Option,
connection: Rc,
- session_id: acp::SessionId,
token_usage: Option,
prompt_capabilities: acp::PromptCapabilities,
_observe_prompt_capabilities: Task>,
@@ -1047,87 +1049,6 @@ pub enum TerminalProviderCommand {
},
}
-impl AcpThread {
- pub fn on_terminal_provider_event(
- &mut self,
- event: TerminalProviderEvent,
- cx: &mut Context,
- ) {
- match event {
- TerminalProviderEvent::Created {
- terminal_id,
- label,
- cwd,
- output_byte_limit,
- terminal,
- } => {
- let entity = self.register_terminal_created(
- terminal_id.clone(),
- label,
- cwd,
- output_byte_limit,
- terminal,
- cx,
- );
-
- if let Some(mut chunks) = self.pending_terminal_output.remove(&terminal_id) {
- for data in chunks.drain(..) {
- entity.update(cx, |term, cx| {
- term.inner().update(cx, |inner, cx| {
- inner.write_output(&data, cx);
- })
- });
- }
- }
-
- if let Some(_status) = self.pending_terminal_exit.remove(&terminal_id) {
- entity.update(cx, |_term, cx| {
- cx.notify();
- });
- }
-
- cx.notify();
- }
- TerminalProviderEvent::Output { terminal_id, data } => {
- if let Some(entity) = self.terminals.get(&terminal_id) {
- entity.update(cx, |term, cx| {
- term.inner().update(cx, |inner, cx| {
- inner.write_output(&data, cx);
- })
- });
- } else {
- self.pending_terminal_output
- .entry(terminal_id)
- .or_default()
- .push(data);
- }
- }
- TerminalProviderEvent::TitleChanged { terminal_id, title } => {
- if let Some(entity) = self.terminals.get(&terminal_id) {
- entity.update(cx, |term, cx| {
- term.inner().update(cx, |inner, cx| {
- inner.breadcrumb_text = title;
- cx.emit(::terminal::Event::BreadcrumbsChanged);
- })
- });
- }
- }
- TerminalProviderEvent::Exit {
- terminal_id,
- status,
- } => {
- if let Some(entity) = self.terminals.get(&terminal_id) {
- entity.update(cx, |_term, cx| {
- cx.notify();
- });
- } else {
- self.pending_terminal_exit.insert(terminal_id, status);
- }
- }
- }
- }
-}
-
#[derive(PartialEq, Eq, Debug)]
pub enum ThreadStatus {
Idle,
@@ -1174,6 +1095,7 @@ impl AcpThread {
pub fn new(
parent_session_id: Option,
title: impl Into,
+ cwd: Option,
connection: Rc,
project: Entity,
action_log: Entity,
@@ -1194,11 +1116,13 @@ impl AcpThread {
Self {
parent_session_id,
+ cwd,
action_log,
shared_buffers: Default::default(),
entries: Default::default(),
plan: Default::default(),
title: title.into(),
+ provisional_title: None,
project,
running_turn: None,
turn_id: 0,
@@ -1253,7 +1177,9 @@ impl AcpThread {
}
pub fn title(&self) -> SharedString {
- self.title.clone()
+ self.provisional_title
+ .clone()
+ .unwrap_or_else(|| self.title.clone())
}
pub fn entries(&self) -> &[AgentThreadEntry] {
@@ -1264,6 +1190,10 @@ impl AcpThread {
&self.session_id
}
+ pub fn cwd(&self) -> Option<&PathBuf> {
+ self.cwd.as_ref()
+ }
+
pub fn status(&self) -> ThreadStatus {
if self.running_turn.is_some() {
ThreadStatus::Generating
@@ -1505,16 +1435,29 @@ impl AcpThread {
}
pub fn set_title(&mut self, title: SharedString, cx: &mut Context) -> Task> {
+ let had_provisional = self.provisional_title.take().is_some();
if title != self.title {
self.title = title.clone();
cx.emit(AcpThreadEvent::TitleUpdated);
if let Some(set_title) = self.connection.set_title(&self.session_id, cx) {
return set_title.run(title, cx);
}
+ } else if had_provisional {
+ cx.emit(AcpThreadEvent::TitleUpdated);
}
Task::ready(Ok(()))
}
+ /// Sets a provisional display title without propagating back to the
+ /// underlying agent connection. This is used for quick preview titles
+ /// (e.g. first 20 chars of the user message) that should be shown
+ /// immediately but replaced once the LLM generates a proper title via
+ /// `set_title`.
+ pub fn set_provisional_title(&mut self, title: SharedString, cx: &mut Context) {
+ self.provisional_title = Some(title);
+ cx.emit(AcpThreadEvent::TitleUpdated);
+ }
+
pub fn subagent_spawned(&mut self, session_id: acp::SessionId, cx: &mut Context) {
cx.emit(AcpThreadEvent::SubagentSpawned(session_id));
}
@@ -2607,6 +2550,85 @@ impl AcpThread {
}
}
}
+
+ pub fn on_terminal_provider_event(
+ &mut self,
+ event: TerminalProviderEvent,
+ cx: &mut Context,
+ ) {
+ match event {
+ TerminalProviderEvent::Created {
+ terminal_id,
+ label,
+ cwd,
+ output_byte_limit,
+ terminal,
+ } => {
+ let entity = self.register_terminal_created(
+ terminal_id.clone(),
+ label,
+ cwd,
+ output_byte_limit,
+ terminal,
+ cx,
+ );
+
+ if let Some(mut chunks) = self.pending_terminal_output.remove(&terminal_id) {
+ for data in chunks.drain(..) {
+ entity.update(cx, |term, cx| {
+ term.inner().update(cx, |inner, cx| {
+ inner.write_output(&data, cx);
+ })
+ });
+ }
+ }
+
+ if let Some(_status) = self.pending_terminal_exit.remove(&terminal_id) {
+ entity.update(cx, |_term, cx| {
+ cx.notify();
+ });
+ }
+
+ cx.notify();
+ }
+ TerminalProviderEvent::Output { terminal_id, data } => {
+ if let Some(entity) = self.terminals.get(&terminal_id) {
+ entity.update(cx, |term, cx| {
+ term.inner().update(cx, |inner, cx| {
+ inner.write_output(&data, cx);
+ })
+ });
+ } else {
+ self.pending_terminal_output
+ .entry(terminal_id)
+ .or_default()
+ .push(data);
+ }
+ }
+ TerminalProviderEvent::TitleChanged { terminal_id, title } => {
+ if let Some(entity) = self.terminals.get(&terminal_id) {
+ entity.update(cx, |term, cx| {
+ term.inner().update(cx, |inner, cx| {
+ inner.breadcrumb_text = title;
+ cx.emit(::terminal::Event::BreadcrumbsChanged);
+ })
+ });
+ }
+ }
+ TerminalProviderEvent::Exit {
+ terminal_id,
+ status,
+ } => {
+ if let Some(entity) = self.terminals.get(&terminal_id) {
+ entity.update(cx, |_term, cx| {
+ cx.notify();
+ });
+ } else {
+ self.pending_terminal_exit.insert(terminal_id, status);
+ }
+ }
+ }
+ }
}
fn markdown_for_raw_output(
@@ -3916,6 +3938,7 @@ mod tests {
struct FakeAgentConnection {
auth_methods: Vec,
sessions: Arc>>>,
+ set_title_calls: Rc>>,
on_user_message: Option<
Rc<
dyn Fn(
@@ -3934,6 +3957,7 @@ mod tests {
auth_methods: Vec::new(),
on_user_message: None,
sessions: Arc::default(),
+ set_title_calls: Default::default(),
}
}
@@ -3969,7 +3993,7 @@ mod tests {
fn new_session(
self: Rc,
project: Entity,
- _cwd: &Path,
+ cwd: &Path,
cx: &mut App,
) -> Task>> {
let session_id = acp::SessionId::new(
@@ -3984,6 +4008,7 @@ mod tests {
AcpThread::new(
None,
"Test",
+ Some(cwd.to_path_buf()),
self.clone(),
project,
action_log,
@@ -4038,11 +4063,32 @@ mod tests {
}))
}
+ fn set_title(
+ &self,
+ _session_id: &acp::SessionId,
+ _cx: &App,
+ ) -> Option> {
+ Some(Rc::new(FakeAgentSessionSetTitle {
+ calls: self.set_title_calls.clone(),
+ }))
+ }
+
fn into_any(self: Rc) -> Rc {
self
}
}
+ struct FakeAgentSessionSetTitle {
+ calls: Rc>>,
+ }
+
+ impl AgentSessionSetTitle for FakeAgentSessionSetTitle {
+ fn run(&self, title: SharedString, _cx: &mut App) -> Task> {
+ self.calls.borrow_mut().push(title);
+ Task::ready(Ok(()))
+ }
+ }
+
struct FakeAgentSessionEditor {
_session_id: acp::SessionId,
}
@@ -4634,4 +4680,54 @@ mod tests {
);
});
}
+
+ #[gpui::test]
+ async fn test_provisional_title_replaced_by_real_title(cx: &mut TestAppContext) {
+ init_test(cx);
+
+ let fs = FakeFs::new(cx.executor());
+ let project = Project::test(fs, [], cx).await;
+ let connection = Rc::new(FakeAgentConnection::new());
+ let set_title_calls = connection.set_title_calls.clone();
+
+ let thread = cx
+ .update(|cx| connection.new_session(project, Path::new(path!("/test")), cx))
+ .await
+ .unwrap();
+
+ // Initial title is the default.
+ thread.read_with(cx, |thread, _| {
+ assert_eq!(thread.title().as_ref(), "Test");
+ });
+
+ // Setting a provisional title updates the display title.
+ thread.update(cx, |thread, cx| {
+ thread.set_provisional_title("Hello, can you help…".into(), cx);
+ });
+ thread.read_with(cx, |thread, _| {
+ assert_eq!(thread.title().as_ref(), "Hello, can you help…");
+ });
+
+ // The provisional title should NOT have propagated to the connection.
+ assert_eq!(
+ set_title_calls.borrow().len(),
+ 0,
+ "provisional title should not propagate to the connection"
+ );
+
+ // When the real title arrives via set_title, it replaces the
+ // provisional title and propagates to the connection.
+ let task = thread.update(cx, |thread, cx| {
+ thread.set_title("Helping with Rust question".into(), cx)
+ });
+ task.await.expect("set_title should succeed");
+ thread.read_with(cx, |thread, _| {
+ assert_eq!(thread.title().as_ref(), "Helping with Rust question");
+ });
+ assert_eq!(
+ set_title_calls.borrow().as_slice(),
+ &[SharedString::from("Helping with Rust question")],
+ "real title should propagate to the connection"
+ );
+ }
}
diff --git a/crates/acp_thread/src/connection.rs b/crates/acp_thread/src/connection.rs
index 0becded53762be7c96789b0d31191fd9cbc02bfe..644986bc15eccbe7d2be32ea5ad6e422db930541 100644
--- a/crates/acp_thread/src/connection.rs
+++ b/crates/acp_thread/src/connection.rs
@@ -45,9 +45,10 @@ pub trait AgentConnection {
/// Load an existing session by ID.
fn load_session(
self: Rc,
- _session: AgentSessionInfo,
+ _session_id: acp::SessionId,
_project: Entity,
_cwd: &Path,
+ _title: Option,
_cx: &mut App,
) -> Task>> {
Task::ready(Err(anyhow::Error::msg("Loading sessions is not supported")))
@@ -71,9 +72,10 @@ pub trait AgentConnection {
/// Resume an existing session by ID without replaying previous messages.
fn resume_session(
self: Rc,
- _session: AgentSessionInfo,
+ _session_id: acp::SessionId,
_project: Entity,
_cwd: &Path,
+ _title: Option,
_cx: &mut App,
) -> Task>> {
Task::ready(Err(anyhow::Error::msg(
@@ -496,6 +498,7 @@ mod test_support {
//! - `create_test_png_base64` for generating test images
use std::sync::Arc;
+ use std::sync::atomic::{AtomicUsize, Ordering};
use action_log::ActionLog;
use collections::HashMap;
@@ -618,15 +621,18 @@ mod test_support {
fn new_session(
self: Rc,
project: Entity,
- _cwd: &Path,
+ cwd: &Path,
cx: &mut gpui::App,
) -> Task>> {
- let session_id = acp::SessionId::new(self.sessions.lock().len().to_string());
+ static NEXT_SESSION_ID: AtomicUsize = AtomicUsize::new(0);
+ let session_id =
+ acp::SessionId::new(NEXT_SESSION_ID.fetch_add(1, Ordering::SeqCst).to_string());
let action_log = cx.new(|_| ActionLog::new(project.clone()));
let thread = cx.new(|cx| {
AcpThread::new(
None,
"Test",
+ Some(cwd.to_path_buf()),
self.clone(),
project,
action_log,
diff --git a/crates/action_log/Cargo.toml b/crates/action_log/Cargo.toml
index b1a1bf824fb770b8378e596fd0c799a7cf98b13d..5227a61651012279e83a3b6e3e68b1484acb0f66 100644
--- a/crates/action_log/Cargo.toml
+++ b/crates/action_log/Cargo.toml
@@ -37,7 +37,7 @@ collections = { workspace = true, features = ["test-support"] }
clock = { workspace = true, features = ["test-support"] }
ctor.workspace = true
gpui = { workspace = true, features = ["test-support"] }
-indoc.workspace = true
+
language = { workspace = true, features = ["test-support"] }
log.workspace = true
pretty_assertions.workspace = true
diff --git a/crates/activity_indicator/Cargo.toml b/crates/activity_indicator/Cargo.toml
index 99ae5b5b077a14c0909737d64935220698a007c7..ce53f23365d57666e25cac434935514fc4bd7e3f 100644
--- a/crates/activity_indicator/Cargo.toml
+++ b/crates/activity_indicator/Cargo.toml
@@ -30,4 +30,4 @@ workspace.workspace = true
[dev-dependencies]
editor = { workspace = true, features = ["test-support"] }
-release_channel.workspace = true
+
diff --git a/crates/agent/Cargo.toml b/crates/agent/Cargo.toml
index 9f563cf0b1b009a496d36a6f090b0f4b476433a7..fe2089d94dc2e3fc812f6cbe39c16c5cadc1a1f5 100644
--- a/crates/agent/Cargo.toml
+++ b/crates/agent/Cargo.toml
@@ -100,9 +100,9 @@ rand.workspace = true
reqwest_client.workspace = true
settings = { workspace = true, "features" = ["test-support"] }
tempfile.workspace = true
-terminal = { workspace = true, "features" = ["test-support"] }
+
theme = { workspace = true, "features" = ["test-support"] }
-tree-sitter-rust.workspace = true
+
unindent = { workspace = true }
-worktree = { workspace = true, "features" = ["test-support"] }
+
zlog.workspace = true
diff --git a/crates/agent/src/agent.rs b/crates/agent/src/agent.rs
index 5421538ca736028a4ea7290c09ef81036e055b81..d9ad55c7127983516dbb5fe0392ef135186b79f7 100644
--- a/crates/agent/src/agent.rs
+++ b/crates/agent/src/agent.rs
@@ -361,6 +361,7 @@ impl NativeAgent {
let mut acp_thread = acp_thread::AcpThread::new(
parent_session_id,
title,
+ None,
connection,
project.clone(),
action_log.clone(),
@@ -1277,13 +1278,14 @@ impl acp_thread::AgentConnection for NativeAgentConnection {
fn load_session(
self: Rc,
- session: AgentSessionInfo,
+ session_id: acp::SessionId,
_project: Entity,
_cwd: &Path,
+ _title: Option,
cx: &mut App,
) -> Task>> {
self.0
- .update(cx, |agent, cx| agent.open_thread(session.session_id, cx))
+ .update(cx, |agent, cx| agent.open_thread(session_id, cx))
}
fn supports_close_session(&self) -> bool {
@@ -1490,16 +1492,6 @@ impl NativeAgentSessionList {
}
}
- fn to_session_info(entry: DbThreadMetadata) -> AgentSessionInfo {
- AgentSessionInfo {
- session_id: entry.id,
- cwd: None,
- title: Some(entry.title),
- updated_at: Some(entry.updated_at),
- meta: None,
- }
- }
-
pub fn thread_store(&self) -> &Entity {
&self.thread_store
}
@@ -1515,7 +1507,7 @@ impl AgentSessionList for NativeAgentSessionList {
.thread_store
.read(cx)
.entries()
- .map(Self::to_session_info)
+ .map(|entry| AgentSessionInfo::from(&entry))
.collect();
Task::ready(Ok(AgentSessionListResponse::new(sessions)))
}
@@ -1639,6 +1631,16 @@ impl NativeThreadEnvironment {
agent.register_session(subagent_thread.clone(), cx)
})?;
+ let depth = current_depth + 1;
+
+ telemetry::event!(
+ "Subagent Started",
+ session = parent_thread_entity.read(cx).id().to_string(),
+ subagent_session = session_id.to_string(),
+ depth,
+ is_resumed = false,
+ );
+
self.prompt_subagent(session_id, subagent_thread, acp_thread)
}
@@ -1655,6 +1657,18 @@ impl NativeThreadEnvironment {
anyhow::Ok((session.thread.clone(), session.acp_thread.clone()))
})??;
+ let depth = subagent_thread.read(cx).depth();
+
+ if let Some(parent_thread_entity) = self.thread.upgrade() {
+ telemetry::event!(
+ "Subagent Started",
+ session = parent_thread_entity.read(cx).id().to_string(),
+ subagent_session = session_id.to_string(),
+ depth,
+ is_resumed = true,
+ );
+ }
+
self.prompt_subagent(session_id, subagent_thread, acp_thread)
}
diff --git a/crates/agent/src/db.rs b/crates/agent/src/db.rs
index 10ecb643b9a17dd6b02b47a416c526a662d12632..2c9b33e4efc4f22059e2914589ca6c635b51c0e5 100644
--- a/crates/agent/src/db.rs
+++ b/crates/agent/src/db.rs
@@ -32,11 +32,24 @@ pub struct DbThreadMetadata {
#[serde(alias = "summary")]
pub title: SharedString,
pub updated_at: DateTime,
+ pub created_at: Option>,
/// The workspace folder paths this thread was created against, sorted
/// lexicographically. Used for grouping threads by project in the sidebar.
pub folder_paths: PathList,
}
+impl From<&DbThreadMetadata> for acp_thread::AgentSessionInfo {
+ fn from(meta: &DbThreadMetadata) -> Self {
+ Self {
+ session_id: meta.id.clone(),
+ cwd: None,
+ title: Some(meta.title.clone()),
+ updated_at: Some(meta.updated_at),
+ meta: None,
+ }
+ }
+}
+
#[derive(Debug, Serialize, Deserialize)]
pub struct DbThread {
pub title: SharedString,
@@ -408,6 +421,17 @@ impl ThreadsDatabase {
s().ok();
}
+ if let Ok(mut s) = connection.exec(indoc! {"
+ ALTER TABLE threads ADD COLUMN created_at TEXT;
+ "})
+ {
+ if s().is_ok() {
+ connection.exec(indoc! {"
+ UPDATE threads SET created_at = updated_at WHERE created_at IS NULL
+ "})?()?;
+ }
+ }
+
let db = Self {
executor,
connection: Arc::new(Mutex::new(connection)),
@@ -458,8 +482,19 @@ impl ThreadsDatabase {
let data_type = DataType::Zstd;
let data = compressed;
- let mut insert = connection.exec_bound::<(Arc, Option>, Option, Option, String, String, DataType, Vec)>(indoc! {"
- INSERT OR REPLACE INTO threads (id, parent_id, folder_paths, folder_paths_order, summary, updated_at, data_type, data) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
+ let created_at = Utc::now().to_rfc3339();
+
+ let mut insert = connection.exec_bound::<(Arc, Option>, Option, Option, String, String, DataType, Vec, String)>(indoc! {"
+ INSERT INTO threads (id, parent_id, folder_paths, folder_paths_order, summary, updated_at, data_type, data, created_at)
+ VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)
+ ON CONFLICT(id) DO UPDATE SET
+ parent_id = excluded.parent_id,
+ folder_paths = excluded.folder_paths,
+ folder_paths_order = excluded.folder_paths_order,
+ summary = excluded.summary,
+ updated_at = excluded.updated_at,
+ data_type = excluded.data_type,
+ data = excluded.data
"})?;
insert((
@@ -471,6 +506,7 @@ impl ThreadsDatabase {
updated_at,
data_type,
data,
+ created_at,
))?;
Ok(())
@@ -483,14 +519,14 @@ impl ThreadsDatabase {
let connection = connection.lock();
let mut select = connection
- .select_bound::<(), (Arc, Option>, Option, Option, String, String)>(indoc! {"
- SELECT id, parent_id, folder_paths, folder_paths_order, summary, updated_at FROM threads ORDER BY updated_at DESC
+ .select_bound::<(), (Arc, Option>, Option, Option, String, String, Option)>(indoc! {"
+ SELECT id, parent_id, folder_paths, folder_paths_order, summary, updated_at, created_at FROM threads ORDER BY updated_at DESC, created_at DESC
"})?;
let rows = select(())?;
let mut threads = Vec::new();
- for (id, parent_id, folder_paths, folder_paths_order, summary, updated_at) in rows {
+ for (id, parent_id, folder_paths, folder_paths_order, summary, updated_at, created_at) in rows {
let folder_paths = folder_paths
.map(|paths| {
PathList::deserialize(&util::path_list::SerializedPathList {
@@ -499,11 +535,18 @@ impl ThreadsDatabase {
})
})
.unwrap_or_default();
+ let created_at = created_at
+ .as_deref()
+ .map(DateTime::parse_from_rfc3339)
+ .transpose()?
+ .map(|dt| dt.with_timezone(&Utc));
+
threads.push(DbThreadMetadata {
id: acp::SessionId::new(id),
parent_session_id: parent_id.map(acp::SessionId::new),
title: summary.into(),
updated_at: DateTime::parse_from_rfc3339(&updated_at)?.with_timezone(&Utc),
+ created_at,
folder_paths,
});
}
@@ -652,7 +695,7 @@ mod tests {
}
#[gpui::test]
- async fn test_list_threads_orders_by_updated_at(cx: &mut TestAppContext) {
+ async fn test_list_threads_orders_by_created_at(cx: &mut TestAppContext) {
let database = ThreadsDatabase::new(cx.executor()).unwrap();
let older_id = session_id("thread-a");
@@ -713,6 +756,10 @@ mod tests {
entries[0].updated_at,
Utc.with_ymd_and_hms(2024, 1, 2, 0, 0, 0).unwrap()
);
+ assert!(
+ entries[0].created_at.is_some(),
+ "created_at should be populated"
+ );
}
#[test]
diff --git a/crates/agent/src/edit_agent/evals.rs b/crates/agent/src/edit_agent/evals.rs
index 2e8818b101995b374cf8172547c45b55c27c6f26..e7b67e37bf4a8b71664a78b99b757c6985794ec6 100644
--- a/crates/agent/src/edit_agent/evals.rs
+++ b/crates/agent/src/edit_agent/evals.rs
@@ -1423,7 +1423,7 @@ impl EditAgentTest {
let client = Client::production(cx);
let user_store = cx.new(|cx| UserStore::new(client.clone(), cx));
settings::init(cx);
- language_model::init(client.clone(), cx);
+ language_model::init(user_store.clone(), client.clone(), cx);
language_models::init(user_store, client.clone(), cx);
});
diff --git a/crates/agent/src/tests/mod.rs b/crates/agent/src/tests/mod.rs
index 23ebe41d3c42654cb8fcdc0266009416686858aa..d33c80a435e84359976d4d8a9edb2bdebd66e0ff 100644
--- a/crates/agent/src/tests/mod.rs
+++ b/crates/agent/src/tests/mod.rs
@@ -3167,7 +3167,7 @@ async fn test_agent_connection(cx: &mut TestAppContext) {
let clock = Arc::new(clock::FakeSystemClock::new());
let client = Client::new(clock, http_client, cx);
let user_store = cx.new(|cx| UserStore::new(client.clone(), cx));
- language_model::init(client.clone(), cx);
+ language_model::init(user_store.clone(), client.clone(), cx);
language_models::init(user_store, client.clone(), cx);
LanguageModelRegistry::test(cx);
});
@@ -3605,6 +3605,113 @@ async fn test_send_max_retries_exceeded(cx: &mut TestAppContext) {
));
}
+#[gpui::test]
+async fn test_streaming_tool_completes_when_llm_stream_ends_without_final_input(
+ cx: &mut TestAppContext,
+) {
+ init_test(cx);
+ always_allow_tools(cx);
+
+ let ThreadTest { model, thread, .. } = setup(cx, TestModel::Fake).await;
+ let fake_model = model.as_fake();
+
+ thread.update(cx, |thread, _cx| {
+ thread.add_tool(StreamingEchoTool::new());
+ });
+
+ let _events = thread
+ .update(cx, |thread, cx| {
+ thread.send(UserMessageId::new(), ["Use the streaming_echo tool"], cx)
+ })
+ .unwrap();
+ cx.run_until_parked();
+
+ // Send a partial tool use (is_input_complete = false), simulating the LLM
+ // streaming input for a tool.
+ let tool_use = LanguageModelToolUse {
+ id: "tool_1".into(),
+ name: "streaming_echo".into(),
+ raw_input: r#"{"text": "partial"}"#.into(),
+ input: json!({"text": "partial"}),
+ is_input_complete: false,
+ thought_signature: None,
+ };
+ fake_model
+ .send_last_completion_stream_event(LanguageModelCompletionEvent::ToolUse(tool_use.clone()));
+ cx.run_until_parked();
+
+ // Send a stream error WITHOUT ever sending is_input_complete = true.
+ // Before the fix, this would deadlock: the tool waits for more partials
+ // (or cancellation), run_turn_internal waits for the tool, and the sender
+ // keeping the channel open lives inside RunningTurn.
+ fake_model.send_last_completion_stream_error(
+ LanguageModelCompletionError::UpstreamProviderError {
+ message: "Internal server error".to_string(),
+ status: http_client::StatusCode::INTERNAL_SERVER_ERROR,
+ retry_after: None,
+ },
+ );
+ fake_model.end_last_completion_stream();
+
+ // Advance past the retry delay so run_turn_internal retries.
+ cx.executor().advance_clock(Duration::from_secs(5));
+ cx.run_until_parked();
+
+ // The retry request should contain the streaming tool's error result,
+ // proving the tool terminated and its result was forwarded.
+ let completion = fake_model
+ .pending_completions()
+ .pop()
+ .expect("No running turn");
+ assert_eq!(
+ completion.messages[1..],
+ vec![
+ LanguageModelRequestMessage {
+ role: Role::User,
+ content: vec!["Use the streaming_echo tool".into()],
+ cache: false,
+ reasoning_details: None,
+ },
+ LanguageModelRequestMessage {
+ role: Role::Assistant,
+ content: vec![language_model::MessageContent::ToolUse(tool_use.clone())],
+ cache: false,
+ reasoning_details: None,
+ },
+ LanguageModelRequestMessage {
+ role: Role::User,
+ content: vec![language_model::MessageContent::ToolResult(
+ LanguageModelToolResult {
+ tool_use_id: tool_use.id.clone(),
+ tool_name: tool_use.name,
+ is_error: true,
+ content: "Failed to receive tool input: tool input was not fully received"
+ .into(),
+ output: Some(
+ "Failed to receive tool input: tool input was not fully received"
+ .into()
+ ),
+ }
+ )],
+ cache: true,
+ reasoning_details: None,
+ },
+ ]
+ );
+
+ // Finish the retry round so the turn completes cleanly.
+ fake_model.send_last_completion_stream_text_chunk("Done");
+ fake_model.end_last_completion_stream();
+ cx.run_until_parked();
+
+ thread.read_with(cx, |thread, _cx| {
+ assert!(
+ thread.is_turn_complete(),
+ "Thread should not be stuck; the turn should have completed",
+ );
+ });
+}
+
/// Filters out the stop events for asserting against in tests
fn stop_events(result_events: Vec>) -> Vec {
result_events
@@ -3660,7 +3767,9 @@ async fn setup(cx: &mut TestAppContext, model: TestModel) -> ThreadTest {
ToolRequiringPermission::NAME: true,
InfiniteTool::NAME: true,
CancellationAwareTool::NAME: true,
- (TerminalTool::NAME): true,
+ StreamingEchoTool::NAME: true,
+ StreamingFailingEchoTool::NAME: true,
+ TerminalTool::NAME: true,
}
}
}
@@ -3682,7 +3791,7 @@ async fn setup(cx: &mut TestAppContext, model: TestModel) -> ThreadTest {
cx.set_http_client(Arc::new(http_client));
let client = Client::production(cx);
let user_store = cx.new(|cx| UserStore::new(client.clone(), cx));
- language_model::init(client.clone(), cx);
+ language_model::init(user_store.clone(), client.clone(), cx);
language_models::init(user_store, client.clone(), cx);
}
};
@@ -6227,3 +6336,196 @@ async fn test_queued_message_ends_turn_at_boundary(cx: &mut TestAppContext) {
);
});
}
+
+#[gpui::test]
+async fn test_streaming_tool_error_breaks_stream_loop_immediately(cx: &mut TestAppContext) {
+ init_test(cx);
+ always_allow_tools(cx);
+
+ let ThreadTest { model, thread, .. } = setup(cx, TestModel::Fake).await;
+ let fake_model = model.as_fake();
+
+ thread.update(cx, |thread, _cx| {
+ thread.add_tool(StreamingFailingEchoTool {
+ receive_chunks_until_failure: 1,
+ });
+ });
+
+ let _events = thread
+ .update(cx, |thread, cx| {
+ thread.send(
+ UserMessageId::new(),
+ ["Use the streaming_failing_echo tool"],
+ cx,
+ )
+ })
+ .unwrap();
+ cx.run_until_parked();
+
+ let tool_use = LanguageModelToolUse {
+ id: "call_1".into(),
+ name: StreamingFailingEchoTool::NAME.into(),
+ raw_input: "hello".into(),
+ input: json!({}),
+ is_input_complete: false,
+ thought_signature: None,
+ };
+
+ fake_model
+ .send_last_completion_stream_event(LanguageModelCompletionEvent::ToolUse(tool_use.clone()));
+
+ cx.run_until_parked();
+
+ let completions = fake_model.pending_completions();
+ let last_completion = completions.last().unwrap();
+
+ assert_eq!(
+ last_completion.messages[1..],
+ vec![
+ LanguageModelRequestMessage {
+ role: Role::User,
+ content: vec!["Use the streaming_failing_echo tool".into()],
+ cache: false,
+ reasoning_details: None,
+ },
+ LanguageModelRequestMessage {
+ role: Role::Assistant,
+ content: vec![language_model::MessageContent::ToolUse(tool_use.clone())],
+ cache: false,
+ reasoning_details: None,
+ },
+ LanguageModelRequestMessage {
+ role: Role::User,
+ content: vec![language_model::MessageContent::ToolResult(
+ LanguageModelToolResult {
+ tool_use_id: tool_use.id.clone(),
+ tool_name: tool_use.name,
+ is_error: true,
+ content: "failed".into(),
+ output: Some("failed".into()),
+ }
+ )],
+ cache: true,
+ reasoning_details: None,
+ },
+ ]
+ );
+}
+
+#[gpui::test]
+async fn test_streaming_tool_error_waits_for_prior_tools_to_complete(cx: &mut TestAppContext) {
+ init_test(cx);
+ always_allow_tools(cx);
+
+ let ThreadTest { model, thread, .. } = setup(cx, TestModel::Fake).await;
+ let fake_model = model.as_fake();
+
+ let (complete_streaming_echo_tool_call_tx, complete_streaming_echo_tool_call_rx) =
+ oneshot::channel();
+
+ thread.update(cx, |thread, _cx| {
+ thread.add_tool(
+ StreamingEchoTool::new().with_wait_until_complete(complete_streaming_echo_tool_call_rx),
+ );
+ thread.add_tool(StreamingFailingEchoTool {
+ receive_chunks_until_failure: 1,
+ });
+ });
+
+ let _events = thread
+ .update(cx, |thread, cx| {
+ thread.send(
+ UserMessageId::new(),
+ ["Use the streaming_echo tool and the streaming_failing_echo tool"],
+ cx,
+ )
+ })
+ .unwrap();
+ cx.run_until_parked();
+
+ fake_model.send_last_completion_stream_event(LanguageModelCompletionEvent::ToolUse(
+ LanguageModelToolUse {
+ id: "call_1".into(),
+ name: StreamingEchoTool::NAME.into(),
+ raw_input: "hello".into(),
+ input: json!({ "text": "hello" }),
+ is_input_complete: false,
+ thought_signature: None,
+ },
+ ));
+ let first_tool_use = LanguageModelToolUse {
+ id: "call_1".into(),
+ name: StreamingEchoTool::NAME.into(),
+ raw_input: "hello world".into(),
+ input: json!({ "text": "hello world" }),
+ is_input_complete: true,
+ thought_signature: None,
+ };
+ fake_model.send_last_completion_stream_event(LanguageModelCompletionEvent::ToolUse(
+ first_tool_use.clone(),
+ ));
+ let second_tool_use = LanguageModelToolUse {
+ name: StreamingFailingEchoTool::NAME.into(),
+ raw_input: "hello".into(),
+ input: json!({ "text": "hello" }),
+ is_input_complete: false,
+ thought_signature: None,
+ id: "call_2".into(),
+ };
+ fake_model.send_last_completion_stream_event(LanguageModelCompletionEvent::ToolUse(
+ second_tool_use.clone(),
+ ));
+
+ cx.run_until_parked();
+
+ complete_streaming_echo_tool_call_tx.send(()).unwrap();
+
+ cx.run_until_parked();
+
+ let completions = fake_model.pending_completions();
+ let last_completion = completions.last().unwrap();
+
+ assert_eq!(
+ last_completion.messages[1..],
+ vec![
+ LanguageModelRequestMessage {
+ role: Role::User,
+ content: vec![
+ "Use the streaming_echo tool and the streaming_failing_echo tool".into()
+ ],
+ cache: false,
+ reasoning_details: None,
+ },
+ LanguageModelRequestMessage {
+ role: Role::Assistant,
+ content: vec![
+ language_model::MessageContent::ToolUse(first_tool_use.clone()),
+ language_model::MessageContent::ToolUse(second_tool_use.clone())
+ ],
+ cache: false,
+ reasoning_details: None,
+ },
+ LanguageModelRequestMessage {
+ role: Role::User,
+ content: vec![
+ language_model::MessageContent::ToolResult(LanguageModelToolResult {
+ tool_use_id: second_tool_use.id.clone(),
+ tool_name: second_tool_use.name,
+ is_error: true,
+ content: "failed".into(),
+ output: Some("failed".into()),
+ }),
+ language_model::MessageContent::ToolResult(LanguageModelToolResult {
+ tool_use_id: first_tool_use.id.clone(),
+ tool_name: first_tool_use.name,
+ is_error: false,
+ content: "hello world".into(),
+ output: Some("hello world".into()),
+ }),
+ ],
+ cache: true,
+ reasoning_details: None,
+ },
+ ]
+ );
+}
diff --git a/crates/agent/src/tests/test_tools.rs b/crates/agent/src/tests/test_tools.rs
index e0794ee322cdf2c77c37d1d22f30ec77c5642d24..f36549a6c42f9e810c7794d8ec683613b6ae6933 100644
--- a/crates/agent/src/tests/test_tools.rs
+++ b/crates/agent/src/tests/test_tools.rs
@@ -2,9 +2,130 @@ use super::*;
use agent_settings::AgentSettings;
use gpui::{App, SharedString, Task};
use std::future;
+use std::sync::Mutex;
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;
+/// A streaming tool that echoes its input, used to test streaming tool
+/// lifecycle (e.g. partial delivery and cleanup when the LLM stream ends
+/// before `is_input_complete`).
+#[derive(JsonSchema, Serialize, Deserialize)]
+pub struct StreamingEchoToolInput {
+ /// The text to echo.
+ pub text: String,
+}
+
+pub struct StreamingEchoTool {
+ wait_until_complete_rx: Mutex