feat: rag-embedding-ai-chat #1

Merged
sharang merged 4 commits from feature/rag-embedding-ai-chat into main 2026-03-06 21:54:16 +00:00
17 changed files with 73 additions and 44 deletions
Showing only changes of commit ea2a9e8a1d - Show all commits

View File

@@ -307,8 +307,7 @@ pub async fn delete_repository(
Extension(agent): AgentExt,
Path(id): Path<String>,
) -> Result<Json<serde_json::Value>, StatusCode> {
let oid =
mongodb::bson::oid::ObjectId::parse_str(&id).map_err(|_| StatusCode::BAD_REQUEST)?;
let oid = mongodb::bson::oid::ObjectId::parse_str(&id).map_err(|_| StatusCode::BAD_REQUEST)?;
let db = &agent.db;
// Delete the repository
@@ -333,10 +332,7 @@ pub async fn delete_repository(
.await;
let _ = db.graph_nodes().delete_many(doc! { "repo_id": &id }).await;
let _ = db.graph_edges().delete_many(doc! { "repo_id": &id }).await;
let _ = db
.graph_builds()
.delete_many(doc! { "repo_id": &id })
.await;
let _ = db.graph_builds().delete_many(doc! { "repo_id": &id }).await;
let _ = db
.impact_analyses()
.delete_many(doc! { "repo_id": &id })

View File

@@ -244,6 +244,7 @@ pub struct DastFinding {
}
impl DastFinding {
#[allow(clippy::too_many_arguments)]
pub fn new(
scan_run_id: String,
target_id: String,

View File

@@ -20,6 +20,12 @@ pub struct Toasts {
next_id: Signal<usize>,
}
impl Default for Toasts {
fn default() -> Self {
Self::new()
}
}
impl Toasts {
pub fn new() -> Self {
Self {

View File

@@ -65,10 +65,7 @@ pub async fn add_repository(
pub async fn delete_repository(repo_id: String) -> Result<(), ServerFnError> {
let state: super::server_state::ServerState =
dioxus_fullstack::FullstackContext::extract().await?;
let url = format!(
"{}/api/v1/repositories/{repo_id}",
state.agent_api_url
);
let url = format!("{}/api/v1/repositories/{repo_id}", state.agent_api_url);
let client = reqwest::Client::new();
let resp = client

View File

@@ -2,7 +2,6 @@ use dioxus::prelude::*;
use crate::app::Route;
use crate::components::page_header::PageHeader;
use crate::infrastructure::chat::fetch_embedding_status;
use crate::infrastructure::repositories::fetch_repositories;
#[component]

View File

@@ -49,7 +49,7 @@ pub fn DastFindingsPage() -> Element {
}
td {
Link {
to: Route::DastFindingDetailPage { id: id },
to: Route::DastFindingDetailPage { id },
"{finding.get(\"title\").and_then(|v| v.as_str()).unwrap_or(\"-\")}"
}
}

View File

@@ -27,13 +27,13 @@ pub fn GraphExplorerPage(repo_id: String) -> Element {
let mut inspector_open = use_signal(|| false);
// Search state
let mut search_query = use_signal(|| String::new());
let mut search_results = use_signal(|| Vec::<serde_json::Value>::new());
let mut file_filter = use_signal(|| String::new());
let mut search_query = use_signal(String::new);
let mut search_results = use_signal(Vec::<serde_json::Value>::new);
let mut file_filter = use_signal(String::new);
// Store serialized graph JSON in signals so use_effect can react to them
let mut nodes_json = use_signal(|| String::new());
let mut edges_json = use_signal(|| String::new());
let mut nodes_json = use_signal(String::new);
let mut edges_json = use_signal(String::new);
let mut graph_ready = use_signal(|| false);
// When resource resolves, serialize the data into signals
@@ -404,7 +404,7 @@ pub fn GraphExplorerPage(repo_id: String) -> Element {
} else if node_count > 0 {
// Data exists but nodes array was empty (shouldn't happen)
div { class: "loading", "Loading graph visualization..." }
} else if matches!(&*graph_data.read(), None) {
} else if (*graph_data.read()).is_none() {
div { class: "loading", "Loading graph data..." }
} else {
div { class: "graph-empty-state",

View File

@@ -95,8 +95,10 @@ impl WebCrawler {
let document = Html::parse_document(&body);
// Extract links
let link_selector = Selector::parse("a[href]")
.unwrap_or_else(|_| Selector::parse("a").expect("valid selector"));
let link_selector = match Selector::parse("a[href]") {
Ok(s) => s,
Err(_) => continue,
};
for element in document.select(&link_selector) {
if let Some(href) = element.value().attr("href") {
if let Some(absolute_url) = self.resolve_url(&base, &url, href) {
@@ -110,10 +112,14 @@ impl WebCrawler {
}
// Extract forms
let form_selector = Selector::parse("form")
.unwrap_or_else(|_| Selector::parse("form").expect("valid selector"));
let input_selector = Selector::parse("input, select, textarea")
.unwrap_or_else(|_| Selector::parse("input").expect("valid selector"));
let form_selector = match Selector::parse("form") {
Ok(s) => s,
Err(_) => continue,
};
let input_selector = match Selector::parse("input, select, textarea") {
Ok(s) => s,
Err(_) => continue,
};
for form in document.select(&form_selector) {
let action = form.value().attr("action").unwrap_or("");

View File

@@ -121,10 +121,10 @@ impl ReconAgent {
let body_lower = body.to_lowercase();
for (tech, pattern) in &patterns {
if body_lower.contains(&pattern.to_lowercase()) {
if !result.technologies.contains(&tech.to_string()) {
result.technologies.push(tech.to_string());
}
if body_lower.contains(&pattern.to_lowercase())
&& !result.technologies.contains(&tech.to_string())
{
result.technologies.push(tech.to_string());
}
}
}

View File

@@ -109,8 +109,8 @@ pub fn detect_communities(code_graph: &CodeGraph) -> u32 {
let mut comm_remap: HashMap<u32, u32> = HashMap::new();
let mut next_id: u32 = 0;
for &c in community.values() {
if !comm_remap.contains_key(&c) {
comm_remap.insert(c, next_id);
if let std::collections::hash_map::Entry::Vacant(e) = comm_remap.entry(c) {
e.insert(next_id);
next_id += 1;
}
}
@@ -137,8 +137,7 @@ pub fn detect_communities(code_graph: &CodeGraph) -> u32 {
/// Apply community assignments back to code nodes
pub fn apply_communities(code_graph: &mut CodeGraph) -> u32 {
let count = detect_communities_with_assignment(code_graph);
count
detect_communities_with_assignment(code_graph)
}
/// Detect communities and write assignments into the nodes
@@ -235,8 +234,8 @@ fn detect_communities_with_assignment(code_graph: &mut CodeGraph) -> u32 {
let mut comm_remap: HashMap<u32, u32> = HashMap::new();
let mut next_id: u32 = 0;
for &c in community.values() {
if !comm_remap.contains_key(&c) {
comm_remap.insert(c, next_id);
if let std::collections::hash_map::Entry::Vacant(e) = comm_remap.entry(c) {
e.insert(next_id);
next_id += 1;
}
}

View File

@@ -96,17 +96,15 @@ impl EmbeddingStore {
};
if status == EmbeddingBuildStatus::Completed || status == EmbeddingBuildStatus::Failed {
update
.get_document_mut("$set")
.unwrap()
.insert("completed_at", mongodb::bson::DateTime::now());
if let Ok(set_doc) = update.get_document_mut("$set") {
set_doc.insert("completed_at", mongodb::bson::DateTime::now());
}
}
if let Some(msg) = error_message {
update
.get_document_mut("$set")
.unwrap()
.insert("error_message", msg);
if let Ok(set_doc) = update.get_document_mut("$set") {
set_doc.insert("error_message", msg);
}
}
self.builds

View File

@@ -133,10 +133,10 @@ impl GraphEngine {
}
/// Try to resolve an edge target to a known node
fn resolve_edge_target<'a>(
fn resolve_edge_target(
&self,
target: &str,
node_map: &'a HashMap<String, NodeIndex>,
node_map: &HashMap<String, NodeIndex>,
) -> Option<NodeIndex> {
// Direct match
if let Some(idx) = node_map.get(target) {

View File

@@ -1,3 +1,6 @@
#![allow(clippy::only_used_in_recursion)]
#![allow(clippy::too_many_arguments)]
pub mod graph;
pub mod parsers;
pub mod search;

View File

@@ -7,6 +7,12 @@ use tree_sitter::{Node, Parser};
pub struct JavaScriptParser;
impl Default for JavaScriptParser {
fn default() -> Self {
Self::new()
}
}
impl JavaScriptParser {
pub fn new() -> Self {
Self

View File

@@ -7,6 +7,12 @@ use tree_sitter::{Node, Parser};
pub struct PythonParser;
impl Default for PythonParser {
fn default() -> Self {
Self::new()
}
}
impl PythonParser {
pub fn new() -> Self {
Self

View File

@@ -7,6 +7,12 @@ use tree_sitter::{Node, Parser};
pub struct RustParser;
impl Default for RustParser {
fn default() -> Self {
Self::new()
}
}
impl RustParser {
pub fn new() -> Self {
Self

View File

@@ -7,6 +7,12 @@ use tree_sitter::{Node, Parser};
pub struct TypeScriptParser;
impl Default for TypeScriptParser {
fn default() -> Self {
Self::new()
}
}
impl TypeScriptParser {
pub fn new() -> Self {
Self