python: Fix ty binary path and required args (#38458)

Derek Nguyen and Cole Miller created

Closes #38347

Release Notes:

- Fixed path and args to ty lsp binary


When attempting to use the new ty lsp integration in the preview, I
noticed issues related to accessing the binary. After deleting the
downloaded archive and adding the following changes that:

- downloads the archive with the correct `AssetKind::TarGz`
- uses the correct path to the extracted binary
- adds the `server` argument to initialize the lsp (like ruff)

After the above changes the LSP starts correctly
```bash
2025-09-18T16:17:03-05:00 INFO  [lsp] starting language server process. binary path: "/Users/dereknguyen/Library/Application Support/Zed/languages/ty/ty-0.0.1-alpha.20/ty-aarch64-apple-darwin/ty", working directory: "/Users/dereknguyen/projects/test-project", args: ["server"]
```
<img width="206" height="98" alt="image"
src="https://github.com/user-attachments/assets/8fcf423f-40a0-4cd9-a79e-e09666323fe2"
/>

---------

Co-authored-by: Cole Miller <cole@zed.dev>

Change summary

crates/languages/src/python.rs | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)

Detailed changes

crates/languages/src/python.rs 🔗

@@ -100,7 +100,7 @@ pub struct TyLspAdapter {
 
 #[cfg(target_os = "macos")]
 impl TyLspAdapter {
-    const GITHUB_ASSET_KIND: AssetKind = AssetKind::Gz;
+    const GITHUB_ASSET_KIND: AssetKind = AssetKind::TarGz;
     const ARCH_SERVER_NAME: &str = "apple-darwin";
 }
 
@@ -216,15 +216,20 @@ impl LspInstaller for TyLspAdapter {
             digest: expected_digest,
         } = latest_version;
         let destination_path = container_dir.join(format!("ty-{name}"));
+
+        async_fs::create_dir_all(&destination_path).await?;
+
         let server_path = match Self::GITHUB_ASSET_KIND {
-            AssetKind::TarGz | AssetKind::Gz => destination_path.clone(), // Tar and gzip extract in place.
-            AssetKind::Zip => destination_path.clone().join("ty.exe"),    // zip contains a .exe
+            AssetKind::TarGz | AssetKind::Gz => destination_path
+                .join(Self::build_asset_name()?.0)
+                .join("ty"),
+            AssetKind::Zip => destination_path.clone().join("ty.exe"),
         };
 
         let binary = LanguageServerBinary {
             path: server_path.clone(),
             env: None,
-            arguments: Default::default(),
+            arguments: vec!["server".into()],
         };
 
         let metadata_path = destination_path.with_extension("metadata");
@@ -283,7 +288,7 @@ impl LspInstaller for TyLspAdapter {
         Ok(LanguageServerBinary {
             path: server_path,
             env: None,
-            arguments: Default::default(),
+            arguments: vec!["server".into()],
         })
     }
 
@@ -305,14 +310,16 @@ impl LspInstaller for TyLspAdapter {
 
             let path = last.context("no cached binary")?;
             let path = match TyLspAdapter::GITHUB_ASSET_KIND {
-                AssetKind::TarGz | AssetKind::Gz => path, // Tar and gzip extract in place.
-                AssetKind::Zip => path.join("ty.exe"),    // zip contains a .exe
+                AssetKind::TarGz | AssetKind::Gz => {
+                    path.join(Self::build_asset_name()?.0).join("ty")
+                }
+                AssetKind::Zip => path.join("ty.exe"),
             };
 
             anyhow::Ok(LanguageServerBinary {
                 path,
                 env: None,
-                arguments: Default::default(),
+                arguments: vec!["server".into()],
             })
         })
         .await