assistant: Normalize line endings for prompts loaded from templates (#16808)

张小白 created

Closes #16804

Similar to #15708, when reading prompts from a template, both Windows
and Linux might end up with `CRLF (\r\n)` line endings, which can result
in a panic.

Release Notes:

- N/A

Change summary

crates/assistant/src/prompts.rs | 5 +++--
crates/text/src/text.rs         | 8 ++++++++
2 files changed, 11 insertions(+), 2 deletions(-)

Detailed changes

crates/assistant/src/prompts.rs 🔗

@@ -8,6 +8,7 @@ use language::BufferSnapshot;
 use parking_lot::Mutex;
 use serde::Serialize;
 use std::{ops::Range, path::PathBuf, sync::Arc, time::Duration};
+use text::LineEnding;
 use util::ResultExt;
 
 #[derive(Serialize)]
@@ -191,8 +192,8 @@ impl PromptBuilder {
             if let Some(id) = path.split('/').last().and_then(|s| s.strip_suffix(".hbs")) {
                 if let Some(prompt) = Assets.load(path.as_ref()).log_err().flatten() {
                     log::info!("Registering built-in prompt template: {}", id);
-                    handlebars
-                        .register_template_string(id, String::from_utf8_lossy(prompt.as_ref()))?
+                    let prompt = String::from_utf8_lossy(prompt.as_ref());
+                    handlebars.register_template_string(id, LineEnding::normalize_cow(prompt))?
                 }
             }
         }

crates/text/src/text.rs 🔗

@@ -3041,4 +3041,12 @@ impl LineEnding {
             text
         }
     }
+
+    pub fn normalize_cow(text: Cow<str>) -> Cow<str> {
+        if let Cow::Owned(replaced) = LINE_SEPARATORS_REGEX.replace_all(&text, "\n") {
+            replaced.into()
+        } else {
+            text
+        }
+    }
 }