Closes #41478 Release Notes: - Fixed #41478 <img width="459" height="916" alt="Screenshot 2025-10-29 at 1 31 26 PM" src="https://github.com/user-attachments/assets/1d5b9fdf-9800-44e4-bdd5-f0964f93625f" /> > caused by using haiku 4.5 from the anthropic provider and then swapping to sonnet 3.7 through zed, doing this does mess with prompt caching but a model swap already invalidates that so it shouldn't have any cost impact on end users
91 lines
2.4 KiB
Rust
91 lines
2.4 KiB
Rust
use anyhow::Result;
|
|
use gpui::SharedString;
|
|
use handlebars::Handlebars;
|
|
use rust_embed::RustEmbed;
|
|
use serde::Serialize;
|
|
use std::sync::Arc;
|
|
|
|
#[derive(RustEmbed)]
|
|
#[folder = "src/templates"]
|
|
#[include = "*.hbs"]
|
|
struct Assets;
|
|
|
|
pub struct Templates(Handlebars<'static>);
|
|
|
|
impl Templates {
|
|
pub fn new() -> Arc<Self> {
|
|
let mut handlebars = Handlebars::new();
|
|
handlebars.set_strict_mode(true);
|
|
handlebars.register_helper("contains", Box::new(contains));
|
|
handlebars.register_embed_templates::<Assets>().unwrap();
|
|
Arc::new(Self(handlebars))
|
|
}
|
|
}
|
|
|
|
pub trait Template: Sized {
|
|
const TEMPLATE_NAME: &'static str;
|
|
|
|
fn render(&self, templates: &Templates) -> Result<String>
|
|
where
|
|
Self: Serialize + Sized,
|
|
{
|
|
Ok(templates.0.render(Self::TEMPLATE_NAME, self)?)
|
|
}
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
pub struct SystemPromptTemplate<'a> {
|
|
#[serde(flatten)]
|
|
pub project: &'a prompt_store::ProjectContext,
|
|
pub available_tools: Vec<SharedString>,
|
|
pub model_name: Option<String>,
|
|
}
|
|
|
|
impl Template for SystemPromptTemplate<'_> {
|
|
const TEMPLATE_NAME: &'static str = "system_prompt.hbs";
|
|
}
|
|
|
|
/// Handlebars helper for checking if an item is in a list
|
|
fn contains(
|
|
h: &handlebars::Helper,
|
|
_: &handlebars::Handlebars,
|
|
_: &handlebars::Context,
|
|
_: &mut handlebars::RenderContext,
|
|
out: &mut dyn handlebars::Output,
|
|
) -> handlebars::HelperResult {
|
|
let list = h
|
|
.param(0)
|
|
.and_then(|v| v.value().as_array())
|
|
.ok_or_else(|| {
|
|
handlebars::RenderError::new("contains: missing or invalid list parameter")
|
|
})?;
|
|
let query = h.param(1).map(|v| v.value()).ok_or_else(|| {
|
|
handlebars::RenderError::new("contains: missing or invalid query parameter")
|
|
})?;
|
|
|
|
if list.contains(query) {
|
|
out.write("true")?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_system_prompt_template() {
|
|
let project = prompt_store::ProjectContext::default();
|
|
let template = SystemPromptTemplate {
|
|
project: &project,
|
|
available_tools: vec!["echo".into()],
|
|
model_name: Some("test-model".to_string()),
|
|
};
|
|
let templates = Templates::new();
|
|
let rendered = template.render(&templates).unwrap();
|
|
assert!(rendered.contains("## Fixing Diagnostics"));
|
|
assert!(rendered.contains("test-model"));
|
|
}
|
|
}
|