Add support for changing the Codestral endpoint (#41116)

pedrxd and Bennet Bo Fenner created

```json
  "edit_predictions": {
    "codestral": {
      "api_url": "https://codestral.mistral.ai",
      "model": "codestral-latest",
      "max_tokens": 150
    }
  },
```

Release Notes:

- Added support for changing the Codestral endpoint. This was discussed
at #34371.

---------

Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>

Change summary

crates/codestral/src/codestral.rs                | 10 +++++++++-
crates/language/src/language_settings.rs         |  3 +++
crates/settings/src/settings_content/language.rs |  5 +++++
3 files changed, 17 insertions(+), 1 deletion(-)

Detailed changes

crates/codestral/src/codestral.rs 🔗

@@ -79,6 +79,7 @@ impl CodestralCompletionProvider {
         suffix: String,
         model: String,
         max_tokens: Option<u32>,
+        api_url: String,
     ) -> Result<String> {
         let start_time = Instant::now();
 
@@ -111,7 +112,7 @@ impl CodestralCompletionProvider {
 
         let http_request = http_client::Request::builder()
             .method(http_client::Method::POST)
-            .uri(format!("{}/v1/fim/completions", CODESTRAL_API_URL))
+            .uri(format!("{}/v1/fim/completions", api_url))
             .header("Content-Type", "application/json")
             .header("Authorization", format!("Bearer {}", api_key))
             .body(http_client::AsyncBody::from(request_body))?;
@@ -211,6 +212,12 @@ impl EditPredictionProvider for CodestralCompletionProvider {
             .clone()
             .unwrap_or_else(|| "codestral-latest".to_string());
         let max_tokens = settings.edit_predictions.codestral.max_tokens;
+        let api_url = settings
+            .edit_predictions
+            .codestral
+            .api_url
+            .clone()
+            .unwrap_or_else(|| CODESTRAL_API_URL.to_string());
 
         self.pending_request = Some(cx.spawn(async move |this, cx| {
             if debounce {
@@ -242,6 +249,7 @@ impl EditPredictionProvider for CodestralCompletionProvider {
                 suffix,
                 model,
                 max_tokens,
+                api_url,
             )
             .await
             {

crates/language/src/language_settings.rs 🔗

@@ -420,6 +420,8 @@ pub struct CodestralSettings {
     pub model: Option<String>,
     /// Maximum tokens to generate.
     pub max_tokens: Option<u32>,
+    /// Custom API URL to use for Codestral.
+    pub api_url: Option<String>,
 }
 
 impl AllLanguageSettings {
@@ -636,6 +638,7 @@ impl settings::Settings for AllLanguageSettings {
         let codestral_settings = CodestralSettings {
             model: codestral.model,
             max_tokens: codestral.max_tokens,
+            api_url: codestral.api_url,
         };
 
         let enabled_in_text_threads = edit_predictions.enabled_in_text_threads.unwrap();

crates/settings/src/settings_content/language.rs 🔗

@@ -142,6 +142,11 @@ pub struct CodestralSettingsContent {
     /// Default: 150
     #[serde(default)]
     pub max_tokens: Option<u32>,
+    /// Api URL to use for completions.
+    ///
+    /// Default: "https://codestral.mistral.ai"
+    #[serde(default)]
+    pub api_url: Option<String>,
 }
 
 /// The mode in which edit predictions should be displayed.