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:
ZhenYi 2026-04-26 23:58:52 +08:00
parent d72019e39f
commit adbc0705db
3 changed files with 76 additions and 36 deletions

View File

@ -605,19 +605,37 @@ impl ChatService {
}
}
if let Some(embed_service) = &self.embed_service {
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,10 +657,7 @@ impl ChatService {
);
messages.push(ChatRequestMessage::system(context));
}
Err(e) => {
let _ = e;
}
_ => {}
}
}
Mention::User(user) => {
@ -667,7 +678,6 @@ impl ChatService {
}
}
}
}
let skill_contexts = self.build_skill_context(request).await;
for ctx in skill_contexts {

View File

@ -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
}

View File

@ -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(),