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 {
|
for mention in &request.mention {
|
||||||
match mention {
|
match mention {
|
||||||
Mention::Repo(repo) => {
|
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!(
|
let query = format!(
|
||||||
"{} {}",
|
"{} {}",
|
||||||
repo.repo_name,
|
repo.repo_name,
|
||||||
repo.description.as_deref().unwrap_or_default()
|
repo.description.as_deref().unwrap_or_default()
|
||||||
);
|
);
|
||||||
match embed_service.search_issues(&query, 5).await {
|
if let Ok(issues) = embed_service.search_issues(&query, 5).await {
|
||||||
Ok(issues) if !issues.is_empty() => {
|
if !issues.is_empty() {
|
||||||
let context = format!(
|
let context = format!(
|
||||||
"Related issues:\n{}",
|
"Related issues for repo {}:\n{}",
|
||||||
|
repo.repo_name,
|
||||||
issues
|
issues
|
||||||
.iter()
|
.iter()
|
||||||
.map(|i| format!("- {}", i.payload.text))
|
.map(|i| format!("- {}", i.payload.text))
|
||||||
@ -626,15 +644,11 @@ impl ChatService {
|
|||||||
);
|
);
|
||||||
messages.push(ChatRequestMessage::system(context));
|
messages.push(ChatRequestMessage::system(context));
|
||||||
}
|
}
|
||||||
Err(e) => {
|
|
||||||
let _ = e;
|
|
||||||
}
|
}
|
||||||
_ => {}
|
if let Ok(repos) = embed_service.search_repos(&query, 3).await {
|
||||||
}
|
if !repos.is_empty() {
|
||||||
match embed_service.search_repos(&query, 3).await {
|
|
||||||
Ok(repos) if !repos.is_empty() => {
|
|
||||||
let context = format!(
|
let context = format!(
|
||||||
"Related repositories:\n{}",
|
"Similar repositories:\n{}",
|
||||||
repos
|
repos
|
||||||
.iter()
|
.iter()
|
||||||
.map(|r| format!("- {}", r.payload.text))
|
.map(|r| format!("- {}", r.payload.text))
|
||||||
@ -643,10 +657,7 @@ impl ChatService {
|
|||||||
);
|
);
|
||||||
messages.push(ChatRequestMessage::system(context));
|
messages.push(ChatRequestMessage::system(context));
|
||||||
}
|
}
|
||||||
Err(e) => {
|
|
||||||
let _ = e;
|
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Mention::User(user) => {
|
Mention::User(user) => {
|
||||||
@ -667,7 +678,6 @@ impl ChatService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let skill_contexts = self.build_skill_context(request).await;
|
let skill_contexts = self.build_skill_context(request).await;
|
||||||
for ctx in skill_contexts {
|
for ctx in skill_contexts {
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
use db::database::AppDatabase;
|
use db::database::AppDatabase;
|
||||||
|
use models::repos::repo;
|
||||||
use models::rooms::room_ai;
|
use models::rooms::room_ai;
|
||||||
use models::rooms::room_message::{Column as RmCol, Entity as RoomMessage};
|
use models::rooms::room_message::{Column as RmCol, Entity as RoomMessage};
|
||||||
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, QueryOrder, QuerySelect};
|
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, QueryOrder, QuerySelect};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use super::patterns::mention_bracket_re;
|
||||||
use crate::error::RoomError;
|
use crate::error::RoomError;
|
||||||
|
|
||||||
pub async fn get_room_history(
|
pub async fn get_room_history(
|
||||||
@ -57,6 +59,34 @@ pub async fn get_room_ai_config(
|
|||||||
Ok(ai_config)
|
Ok(ai_config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn extract_mention_context(_content: &str) -> Vec<agent::chat::Mention> {
|
pub async fn extract_mention_context(
|
||||||
Vec::new()
|
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();
|
.collect();
|
||||||
let user_names = self.get_user_names(&user_ids).await;
|
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 {
|
let request = AiRequest {
|
||||||
db: self.db.clone(),
|
db: self.db.clone(),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user