feat(room): inject repository details into AI system prompt on mention
When a user mentions a repository in room chat, extract the repo name from @[repo:name:label] brackets, look up the full repo model from the database, and inject its details (name, description, default branch, visibility) into the AI message context. Works independently of embed_service availability.
This commit is contained in:
parent
d72019e39f
commit
adbc0705db
@ -605,19 +605,37 @@ impl ChatService {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(embed_service) = &self.embed_service {
|
||||
for mention in &request.mention {
|
||||
match mention {
|
||||
Mention::Repo(repo) => {
|
||||
for mention in &request.mention {
|
||||
match mention {
|
||||
Mention::Repo(repo) => {
|
||||
// Inject repo details into system prompt so AI knows the repo context
|
||||
let mut parts = vec![
|
||||
format!("Name: {}", repo.repo_name),
|
||||
format!("ID: {}", repo.id),
|
||||
];
|
||||
if let Some(ref desc) = repo.description {
|
||||
parts.push(format!("Description: {}", desc));
|
||||
}
|
||||
parts.push(format!("Default branch: {}", repo.default_branch));
|
||||
parts.push(format!("Private: {}", if repo.is_private { "yes" } else { "no" }));
|
||||
parts.push(format!("Created: {}", repo.created_at.format("%Y-%m-%d")));
|
||||
messages.push(ChatRequestMessage::system(format!(
|
||||
"Mentioned repository:\n{}",
|
||||
parts.join("\n")
|
||||
)));
|
||||
|
||||
// Vector search for related issues and repos (enhancement, optional)
|
||||
if let Some(embed_service) = &self.embed_service {
|
||||
let query = format!(
|
||||
"{} {}",
|
||||
repo.repo_name,
|
||||
repo.description.as_deref().unwrap_or_default()
|
||||
);
|
||||
match embed_service.search_issues(&query, 5).await {
|
||||
Ok(issues) if !issues.is_empty() => {
|
||||
if let Ok(issues) = embed_service.search_issues(&query, 5).await {
|
||||
if !issues.is_empty() {
|
||||
let context = format!(
|
||||
"Related issues:\n{}",
|
||||
"Related issues for repo {}:\n{}",
|
||||
repo.repo_name,
|
||||
issues
|
||||
.iter()
|
||||
.map(|i| format!("- {}", i.payload.text))
|
||||
@ -626,15 +644,11 @@ impl ChatService {
|
||||
);
|
||||
messages.push(ChatRequestMessage::system(context));
|
||||
}
|
||||
Err(e) => {
|
||||
let _ = e;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
match embed_service.search_repos(&query, 3).await {
|
||||
Ok(repos) if !repos.is_empty() => {
|
||||
if let Ok(repos) = embed_service.search_repos(&query, 3).await {
|
||||
if !repos.is_empty() {
|
||||
let context = format!(
|
||||
"Related repositories:\n{}",
|
||||
"Similar repositories:\n{}",
|
||||
repos
|
||||
.iter()
|
||||
.map(|r| format!("- {}", r.payload.text))
|
||||
@ -643,28 +657,24 @@ impl ChatService {
|
||||
);
|
||||
messages.push(ChatRequestMessage::system(context));
|
||||
}
|
||||
Err(e) => {
|
||||
let _ = e;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Mention::User(user) => {
|
||||
let mut profile_parts = vec![format!("Username: {}", user.username)];
|
||||
if let Some(ref display_name) = user.display_name {
|
||||
profile_parts.push(format!("Display name: {}", display_name));
|
||||
}
|
||||
if let Some(ref org) = user.organization {
|
||||
profile_parts.push(format!("Organization: {}", org));
|
||||
}
|
||||
if let Some(ref website) = user.website_url {
|
||||
profile_parts.push(format!("Website: {}", website));
|
||||
}
|
||||
messages.push(ChatRequestMessage::system(format!(
|
||||
"Mentioned user profile:\n{}",
|
||||
profile_parts.join("\n")
|
||||
)));
|
||||
}
|
||||
Mention::User(user) => {
|
||||
let mut profile_parts = vec![format!("Username: {}", user.username)];
|
||||
if let Some(ref display_name) = user.display_name {
|
||||
profile_parts.push(format!("Display name: {}", display_name));
|
||||
}
|
||||
if let Some(ref org) = user.organization {
|
||||
profile_parts.push(format!("Organization: {}", org));
|
||||
}
|
||||
if let Some(ref website) = user.website_url {
|
||||
profile_parts.push(format!("Website: {}", website));
|
||||
}
|
||||
messages.push(ChatRequestMessage::system(format!(
|
||||
"Mentioned user profile:\n{}",
|
||||
profile_parts.join("\n")
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
use db::database::AppDatabase;
|
||||
use models::repos::repo;
|
||||
use models::rooms::room_ai;
|
||||
use models::rooms::room_message::{Column as RmCol, Entity as RoomMessage};
|
||||
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, QueryOrder, QuerySelect};
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::patterns::mention_bracket_re;
|
||||
use crate::error::RoomError;
|
||||
|
||||
pub async fn get_room_history(
|
||||
@ -57,6 +59,34 @@ pub async fn get_room_ai_config(
|
||||
Ok(ai_config)
|
||||
}
|
||||
|
||||
pub async fn extract_mention_context(_content: &str) -> Vec<agent::chat::Mention> {
|
||||
Vec::new()
|
||||
pub async fn extract_mention_context(
|
||||
db: &AppDatabase,
|
||||
project_id: Uuid,
|
||||
content: &str,
|
||||
) -> Vec<agent::chat::Mention> {
|
||||
let mut mentions: Vec<agent::chat::Mention> = Vec::new();
|
||||
let mut seen_repos: Vec<String> = Vec::new();
|
||||
|
||||
for cap in mention_bracket_re().captures_iter(content) {
|
||||
if let (Some(type_m), Some(id_m)) = (cap.get(1), cap.get(2)) {
|
||||
if type_m.as_str() == "repo" {
|
||||
let repo_name = id_m.as_str().trim().to_string();
|
||||
if repo_name.is_empty() || seen_repos.contains(&repo_name) {
|
||||
continue;
|
||||
}
|
||||
seen_repos.push(repo_name.clone());
|
||||
|
||||
if let Ok(Some(repo_model)) = repo::Entity::find()
|
||||
.filter(repo::Column::Project.eq(project_id))
|
||||
.filter(repo::Column::RepoName.eq(&repo_name))
|
||||
.one(db)
|
||||
.await
|
||||
{
|
||||
mentions.push(agent::chat::Mention::Repo(repo_model));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mentions
|
||||
}
|
||||
|
||||
@ -374,7 +374,7 @@ impl RoomService {
|
||||
.collect();
|
||||
let user_names = self.get_user_names(&user_ids).await;
|
||||
|
||||
let mentions = history::extract_mention_context(&content).await;
|
||||
let mentions = history::extract_mention_context(&self.db, room.project, &content).await;
|
||||
|
||||
let request = AiRequest {
|
||||
db: self.db.clone(),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user