use serde::{Deserialize, Serialize};
use crate::domain::{EvidenceSpan, IndexKind, IndexState};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FileIndexRoot {
pub scope_id: String,
pub root_id: String,
pub root_path: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FileIndexEntry {
pub scope_id: String,
pub root_id: String,
pub path: String,
pub relative_path: String,
pub file_name: String,
pub extension: Option<String>,
pub parent_dir: String,
pub size_bytes: u64,
pub modified_at_ms: u64,
pub fingerprint: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FileIndexRootUpdate {
pub root: FileIndexRoot,
pub entries: Vec<FileIndexEntry>,
pub processed_content_paths: std::collections::BTreeSet<String>,
pub content_entries: Vec<FileContentEntry>,
pub scan_error_count: usize,
pub truncated: bool,
pub content_truncated: bool,
pub content_read_error_count: usize,
pub last_error: Option<String>,
pub now_ms: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FileIndexRootStatus {
pub scope_id: String,
pub root_id: String,
pub root_path: String,
pub indexed_file_count: usize,
pub missing_file_count: usize,
pub scan_error_count: usize,
pub truncated: bool,
#[serde(default)]
pub content_truncated: bool,
#[serde(default)]
pub content_read_error_count: usize,
pub indexed_content_count: usize,
pub skipped_content_count: usize,
pub unchanged_content_count: usize,
pub stale_content_cursor_count: usize,
pub last_indexed_at_ms: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_error: Option<String>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct FileIndexScanSummary {
pub root_count: usize,
pub indexed_file_count: usize,
pub missing_file_count: usize,
pub indexed_content_count: usize,
pub skipped_content_count: usize,
pub unchanged_content_count: usize,
pub stale_content_cursor_count: usize,
pub scan_error_count: usize,
pub content_read_error_count: usize,
pub truncated_root_count: usize,
pub roots: Vec<FileIndexRootStatus>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FileSearchRequest {
pub query: String,
pub source_scope: Option<String>,
pub root_id: Option<String>,
pub limit: usize,
pub timeout_ms: u64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FileSearchHit {
pub scope_id: String,
pub root_id: String,
pub path: String,
pub relative_path: String,
pub file_name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub extension: Option<String>,
pub parent_dir: String,
pub size_bytes: u64,
pub modified_at_ms: u64,
pub status: String,
pub rank: usize,
pub score: f64,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FileContentChunk {
pub chunk_index: usize,
pub start_byte: u32,
pub end_byte: u32,
pub start_line: u32,
pub end_line: u32,
pub content: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FileContentEntry {
pub scope_id: String,
pub root_id: String,
pub path: String,
pub relative_path: String,
pub fingerprint: String,
pub content_hash: String,
pub indexed_at_ms: u64,
pub graph_version: u64,
pub chunks: Vec<FileContentChunk>,
pub skipped_reason: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FileContentReadModelCursor {
pub kind: IndexKind,
pub source_scope: String,
pub root_id: String,
pub path: String,
pub content_hash: String,
pub indexed_graph_version: u64,
pub state: IndexState,
#[serde(skip_serializing_if = "Option::is_none")]
pub stale_reason: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FileKnowledgeFactCandidate {
pub candidate_id: String,
pub kind: String,
pub subject: String,
pub predicate: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<String>,
pub confidence_basis_points: u16,
pub status: String,
pub source_scope: String,
pub source_path: String,
pub span: EvidenceSpan,
pub fingerprint: String,
pub freshness_cursor: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FileContentSearchRequest {
pub query: String,
pub source_scope: Option<String>,
pub root_id: Option<String>,
pub authorized_roots: Vec<FileIndexRoot>,
pub limit: usize,
pub timeout_ms: u64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FileContentSearchHit {
pub scope_id: String,
pub root_id: String,
pub path: String,
pub relative_path: String,
pub chunk_id: String,
pub content_role: String,
pub excerpt: String,
pub span: EvidenceSpan,
pub fingerprint: String,
pub content_hash: String,
pub indexed_at_ms: u64,
pub graph_version: u64,
pub indexed_graph_version: u64,
pub freshness_cursor: String,
pub rank: usize,
pub score: f64,
pub ranking_signals: Vec<String>,
pub fact_candidates: Vec<FileKnowledgeFactCandidate>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct FileIndexDiagnostics {
pub root_count: usize,
pub indexed_file_count: usize,
pub missing_file_count: usize,
pub indexed_content_count: usize,
pub skipped_content_count: usize,
pub unchanged_content_count: usize,
pub stale_content_cursor_count: usize,
pub scan_error_count: usize,
pub content_read_error_count: usize,
pub truncated_root_count: usize,
pub roots: Vec<FileIndexRootStatus>,
pub content_cursors: Vec<FileContentReadModelCursor>,
}