chore: refactor session naming into provider (#3678)

This commit is contained in:
Angela Ning
2025-07-28 16:07:33 -04:00
committed by GitHub
parent 7e98329093
commit 67399de10f
2 changed files with 46 additions and 40 deletions
+43
View File
@@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize};
use super::errors::ProviderError;
use crate::message::Message;
use crate::model::ModelConfig;
use crate::utils::safe_truncate;
use rmcp::model::Tool;
use utoipa::ToSchema;
@@ -338,6 +339,48 @@ pub trait Provider: Send + Sync {
self.get_model_config().model_name
}
}
/// Generate a session name/description based on the conversation history
/// This method can be overridden by providers to implement custom session naming strategies.
/// The default implementation creates a prompt asking for a concise description in 4 words or less.
async fn generate_session_name(&self, messages: &[Message]) -> Result<String, ProviderError> {
// Create a prompt for a concise description
let mut description_prompt = "Based on the conversation so far, provide a concise description of this session in 4 words or less. This will be used for finding the session later in a UI with limited space - reply *ONLY* with the description".to_string();
// Get context from the first 3 user messages
let context: Vec<String> = messages
.iter()
.filter(|m| m.role == rmcp::model::Role::User)
.take(3)
.map(|m| m.as_concat_text())
.collect();
if !context.is_empty() {
description_prompt = format!(
"Here are the first few user messages:\n{}\n\n{}",
context.join("\n"),
description_prompt
);
}
let message = Message::user().with_text(&description_prompt);
let result = self
.complete(
"Reply with only a description in four words or less",
&[message],
&[],
)
.await?;
let description = result.0.as_concat_text();
let sanitized_description = if description.chars().count() > 100 {
safe_truncate(&description, 100)
} else {
description
};
Ok(sanitized_description)
}
}
/// A message stream yields partial text content but complete tool calls, all within the Message object
+3 -40
View File
@@ -1294,52 +1294,15 @@ pub async fn generate_description_with_schedule_id(
));
}
// Create a special message asking for a 3-word description
let mut description_prompt = "Based on the conversation so far, provide a concise description of this session in 4 words or less. This will be used for finding the session later in a UI with limited space - reply *ONLY* with the description".to_string();
// get context from messages so far, limiting each message to 300 chars for security
let context: Vec<String> = messages
.iter()
.filter(|m| m.role == rmcp::model::Role::User)
.take(3) // Use up to first 3 user messages for context
.map(|m| {
let text = m.as_concat_text();
safe_truncate(&text, 300)
})
.collect();
if !context.is_empty() {
description_prompt = format!(
"Here are the first few user messages:\n{}\n\n{}",
context.join("\n"),
description_prompt
);
}
// Generate the description with error handling
let message = Message::user().with_text(&description_prompt);
let result = provider
.complete(
"Reply with only a description in four words or less",
&[message],
&[],
)
// Use the provider's session naming capability
let sanitized_description = provider
.generate_session_name(messages)
.await
.map_err(|e| {
tracing::error!("Failed to generate session description: {}", e);
anyhow::anyhow!("Failed to generate session description")
})?;
let description = result.0.as_concat_text();
// Validate description length for security
let sanitized_description = if description.chars().count() > 100 {
tracing::warn!("Generated description too long, truncating");
safe_truncate(&description, 100)
} else {
description
};
// Create metadata with proper working_dir or read existing and update
let mut metadata = if secure_path.exists() {
read_metadata(&secure_path)?