chore: refactor session naming into provider (#3678)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)?
|
||||
|
||||
Reference in New Issue
Block a user