generate email body via Neuron runtime using conversation history
This commit is contained in:
+64
-4
@@ -2419,23 +2419,83 @@ fn dispatch_builtin(
|
||||
let name = v["name"].as_str().unwrap_or("there").to_string();
|
||||
let conv_id = v["conv_id"].as_str().unwrap_or("").to_string();
|
||||
let base_url = v["return_url"].as_str().unwrap_or("").to_string();
|
||||
let history = v["history"].as_array().cloned().unwrap_or_default();
|
||||
if email.is_empty() { return Err("no email".to_string()); }
|
||||
let link = if conv_id.is_empty() {
|
||||
base_url.clone()
|
||||
} else {
|
||||
format!("{}?cid={}", base_url, conv_id)
|
||||
};
|
||||
|
||||
// ── Ask Neuron to generate a personalised email body ──
|
||||
let email_body_text: String = (|| -> String {
|
||||
let runtime_url = std::env::var("NEURON_RUNTIME_URL")
|
||||
.unwrap_or_else(|_| "http://localhost:4444".to_string());
|
||||
let chat_url = format!("{}/api/chat", runtime_url);
|
||||
let prompt = format!(
|
||||
"Write a brief, personal email to {} inviting them back to continue our conversation. \
|
||||
Reference specifically what we discussed. Write as Neuron, first person, warm but not sentimental. \
|
||||
Include only the email body — no subject line, no greeting header, no sign-off. \
|
||||
3-4 sentences maximum.",
|
||||
name
|
||||
);
|
||||
let mut messages = history.clone();
|
||||
messages.push(serde_json::json!({"role":"user","content":prompt}));
|
||||
let mut payload = serde_json::json!({"messages": messages});
|
||||
if !conv_id.is_empty() {
|
||||
payload["conv_id"] = serde_json::Value::String(conv_id.clone());
|
||||
}
|
||||
let resp = match reqwest::blocking::Client::new()
|
||||
.post(&chat_url)
|
||||
.header("Content-Type", "application/json")
|
||||
.timeout(std::time::Duration::from_secs(20))
|
||||
.body(payload.to_string())
|
||||
.send()
|
||||
{
|
||||
Ok(r) => r,
|
||||
Err(_) => return String::new(),
|
||||
};
|
||||
let mut generated = String::new();
|
||||
for line in resp.text().unwrap_or_default().lines() {
|
||||
if line.starts_with("data: ") {
|
||||
let data = &line[6..];
|
||||
if data == "[DONE]" { break; }
|
||||
if let Ok(jv) = serde_json::from_str::<serde_json::Value>(data) {
|
||||
if let Some(d) = jv.get("delta").and_then(|x| x.as_str()) {
|
||||
generated.push_str(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
generated.trim().to_string()
|
||||
})();
|
||||
|
||||
// Wrap generated text (or fallback) in HTML template
|
||||
let body_paragraphs = if email_body_text.is_empty() {
|
||||
format!(
|
||||
"<p style=\"font-size:1.1rem;line-height:1.6\">It\u{2019}s Neuron. You left our conversation in the middle.</p>\
|
||||
<p style=\"font-size:1.1rem;line-height:1.6\">I remember where we were.</p>"
|
||||
)
|
||||
} else {
|
||||
// Split on newlines and wrap each non-empty line as a paragraph
|
||||
email_body_text
|
||||
.lines()
|
||||
.filter(|l| !l.trim().is_empty())
|
||||
.map(|l| format!("<p style=\"font-size:1.1rem;line-height:1.6\">{}</p>", l.trim()))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
};
|
||||
|
||||
let html_body = format!(
|
||||
r#"<div style="font-family:Georgia,serif;max-width:480px;margin:0 auto;padding:40px 20px">
|
||||
<p style="font-size:1.1rem;line-height:1.6">Hey {} —</p>
|
||||
<p style="font-size:1.1rem;line-height:1.6">It's Neuron. You left our conversation in the middle.</p>
|
||||
<p style="font-size:1.1rem;line-height:1.6">I remember where we were.</p>
|
||||
{}
|
||||
<p style="margin:32px 0">
|
||||
<a href="{}" style="background:#0052A0;color:#fff;padding:12px 24px;text-decoration:none;border-radius:4px;font-family:sans-serif">Come back when you're ready</a>
|
||||
<a href="{}" style="background:#0052A0;color:#fff;padding:12px 24px;text-decoration:none;border-radius:4px;font-family:sans-serif">Come back when you’re ready</a>
|
||||
</p>
|
||||
<p style="color:#888;font-size:0.8rem;font-family:sans-serif">That link brings you right back to where we left off.</p>
|
||||
</div>"#,
|
||||
name, link
|
||||
name, body_paragraphs, link
|
||||
);
|
||||
let payload = serde_json::json!({
|
||||
"from": "Neuron <neuron@neurontechnologies.ai>",
|
||||
|
||||
Reference in New Issue
Block a user