feat: rag-embedding-ai-chat (#1)
All checks were successful
CI / Format (push) Successful in 2s
CI / Clippy (push) Successful in 2m56s
CI / Security Audit (push) Successful in 1m25s
CI / Tests (push) Successful in 3m57s

Co-authored-by: Sharang Parnerkar <parnerkarsharang@gmail.com>
Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
2026-03-06 21:54:15 +00:00
parent db454867f3
commit 42cabf0582
61 changed files with 3868 additions and 307 deletions

View File

@@ -1,27 +1,202 @@
use dioxus::prelude::*;
use serde::{Deserialize, Serialize};
use compliance_core::models::SbomEntry;
// ── Local types (no bson dependency, WASM-safe) ──
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct VulnRefData {
pub id: String,
pub source: String,
pub severity: Option<String>,
pub url: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct SbomEntryData {
#[serde(rename = "_id", default)]
pub id: Option<serde_json::Value>,
pub repo_id: String,
pub name: String,
pub version: String,
pub package_manager: String,
pub license: Option<String>,
pub purl: Option<String>,
#[serde(default)]
pub known_vulnerabilities: Vec<VulnRefData>,
#[serde(default)]
pub created_at: Option<serde_json::Value>,
#[serde(default)]
pub updated_at: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct SbomListResponse {
pub data: Vec<SbomEntry>,
pub data: Vec<SbomEntryData>,
pub total: Option<u64>,
pub page: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct LicenseSummaryData {
pub license: String,
pub count: u64,
pub is_copyleft: bool,
pub packages: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct LicenseSummaryResponse {
pub data: Vec<LicenseSummaryData>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct SbomDiffEntryData {
pub name: String,
pub version: String,
pub package_manager: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct SbomVersionDiffData {
pub name: String,
pub package_manager: String,
pub version_a: String,
pub version_b: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct SbomDiffResultData {
pub only_in_a: Vec<SbomDiffEntryData>,
pub only_in_b: Vec<SbomDiffEntryData>,
pub version_changed: Vec<SbomVersionDiffData>,
pub common_count: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct SbomDiffResponse {
pub data: SbomDiffResultData,
}
// ── Server functions ──
#[server]
pub async fn fetch_sbom(page: u64) -> Result<SbomListResponse, ServerFnError> {
pub async fn fetch_sbom_filtered(
repo_id: Option<String>,
package_manager: Option<String>,
q: Option<String>,
has_vulns: Option<bool>,
license: Option<String>,
page: u64,
) -> Result<SbomListResponse, ServerFnError> {
let state: super::server_state::ServerState =
dioxus_fullstack::FullstackContext::extract().await?;
let url = format!("{}/api/v1/sbom?page={page}&limit=50", state.agent_api_url);
let mut params = vec![format!("page={page}"), "limit=50".to_string()];
if let Some(r) = &repo_id {
if !r.is_empty() {
params.push(format!("repo_id={r}"));
}
}
if let Some(pm) = &package_manager {
if !pm.is_empty() {
params.push(format!("package_manager={pm}"));
}
}
if let Some(q) = &q {
if !q.is_empty() {
params.push(format!("q={}", q.replace(' ', "%20")));
}
}
if let Some(hv) = has_vulns {
params.push(format!("has_vulns={hv}"));
}
if let Some(l) = &license {
if !l.is_empty() {
params.push(format!("license={}", l.replace(' ', "%20")));
}
}
let url = format!("{}/api/v1/sbom?{}", state.agent_api_url, params.join("&"));
let resp = reqwest::get(&url)
.await
.map_err(|e| ServerFnError::new(e.to_string()))?;
let body: SbomListResponse = resp
.json()
let text = resp
.text()
.await
.map_err(|e| ServerFnError::new(e.to_string()))?;
let body: SbomListResponse = serde_json::from_str(&text)
.map_err(|e| ServerFnError::new(format!("Parse error: {e} — body: {text}")))?;
Ok(body)
}
#[server]
pub async fn fetch_sbom_export(repo_id: String, format: String) -> Result<String, ServerFnError> {
let state: super::server_state::ServerState =
dioxus_fullstack::FullstackContext::extract().await?;
let url = format!(
"{}/api/v1/sbom/export?repo_id={}&format={}",
state.agent_api_url, repo_id, format
);
let resp = reqwest::get(&url)
.await
.map_err(|e| ServerFnError::new(e.to_string()))?;
let text = resp
.text()
.await
.map_err(|e| ServerFnError::new(e.to_string()))?;
Ok(text)
}
#[server]
pub async fn fetch_license_summary(
repo_id: Option<String>,
) -> Result<LicenseSummaryResponse, ServerFnError> {
let state: super::server_state::ServerState =
dioxus_fullstack::FullstackContext::extract().await?;
let mut url = format!("{}/api/v1/sbom/licenses", state.agent_api_url);
if let Some(r) = &repo_id {
if !r.is_empty() {
url = format!("{url}?repo_id={r}");
}
}
let resp = reqwest::get(&url)
.await
.map_err(|e| ServerFnError::new(e.to_string()))?;
let text = resp
.text()
.await
.map_err(|e| ServerFnError::new(e.to_string()))?;
let body: LicenseSummaryResponse = serde_json::from_str(&text)
.map_err(|e| ServerFnError::new(format!("Parse error: {e} — body: {text}")))?;
Ok(body)
}
#[server]
pub async fn fetch_sbom_diff(
repo_a: String,
repo_b: String,
) -> Result<SbomDiffResponse, ServerFnError> {
let state: super::server_state::ServerState =
dioxus_fullstack::FullstackContext::extract().await?;
let url = format!(
"{}/api/v1/sbom/diff?repo_a={}&repo_b={}",
state.agent_api_url, repo_a, repo_b
);
let resp = reqwest::get(&url)
.await
.map_err(|e| ServerFnError::new(e.to_string()))?;
let text = resp
.text()
.await
.map_err(|e| ServerFnError::new(e.to_string()))?;
let body: SbomDiffResponse = serde_json::from_str(&text)
.map_err(|e| ServerFnError::new(format!("Parse error: {e} — body: {text}")))?;
Ok(body)
}