use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
use crate::{
domain::{
CodeFeatureFlagGraph, CodeFeatureFlagRequest, CodeImpactPathGroups, CodeImpactRequest,
CodeIndexCheckpoint, CodeIndexSummary, CodeIndexTaskQueueStatus, CodeIndexTaskRecord,
CodeRepositoryRegistration, CodeRepositoryRemovalSummary, CodeRepositoryReport,
CodeRepositoryScopePreview, CodeRepositorySelector, CodeRepositorySet,
CodeRepositorySetAddMemberRequest, CodeRepositorySetCreateRequest, CodeRepositorySetMember,
CodeRepositorySetQueryHit, CodeRepositorySetQueryRequest, CodeRepositorySetRefreshSummary,
CodeRepositorySetRefreshTaskRecord, CodeRepositorySetRemoveMemberRequest,
CodeRepositorySetStatus, CodeRepositoryStatus, CodeRepositoryTotals, CodeRetrievalHit,
CodeRetrievalRequest, CodeScopeRetentionSummary, CommitReceipt, ConfidenceScore,
EvidenceExtractionMetadata, EvidenceModality, EvidenceSpan, ExtractionDiagnostic,
FactStatus, FreshnessPolicy, FusionDiagnostics, GraphVersionRange, IndexKind, IndexStatus,
LayoutRegion, ProposalConflictRecord, ProposalRecord, ProposalState, RerankDiagnostics,
RetrievalBackendStatus, RetrievalBudgetUsed, RetrievalHit, RetrievalMode,
RetrievedContextPack, ServiceDefinitionPlan, ServiceOperatorStatus, SoftwareBuildTarget,
SoftwareComponent, SoftwareDependencyUsage, SoftwareDesignElement, SoftwareFile,
SoftwareGlobalRequest, SoftwareGlobalStatus, SoftwareIacResource, SoftwareRelationship,
SoftwareSdkUsage, SoftwareTopic, WorkerKind, WorkerStatus, WorkerTaskRecord,
},
storage::{GraphInspection, IndexCursor, IndexRefreshDiagnostics},
};
use super::{
AgentProtocolStatus, ApiMetadata, CodeRepositoryFreshnessDiagnostics,
FileIndexFreshnessDiagnostics, RuntimeStatus,
};
pub const GRAPH_CANVAS_DEFAULT_LIMIT: usize = 250;
pub const GRAPH_CANVAS_MAX_LIMIT: usize = 1000;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum GraphCanvasKind {
Knowledge,
Code,
Mixed,
}
impl GraphCanvasKind {
pub fn parse(value: &str) -> Result<Self, String> {
match value {
"knowledge" => Ok(Self::Knowledge),
"code" => Ok(Self::Code),
"mixed" => Ok(Self::Mixed),
_ => Err(format!("unsupported graph canvas kind '{value}'")),
}
}
pub const fn as_str(self) -> &'static str {
match self {
Self::Knowledge => "knowledge",
Self::Code => "code",
Self::Mixed => "mixed",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct GraphCanvasRequest {
pub kind: GraphCanvasKind,
#[serde(skip_serializing_if = "Option::is_none")]
pub source_scope: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub query: Option<String>,
pub limit: usize,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct GraphCanvasNode {
pub id: String,
pub kind: String,
pub label: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub subtitle: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub source_scope: Option<String>,
pub graph_version: u64,
pub weight: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub details: BTreeMap<String, String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct GraphCanvasEdge {
pub id: String,
pub kind: String,
pub source: String,
pub target: String,
pub label: String,
pub graph_version: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub confidence_basis_points: Option<u16>,
#[serde(skip_serializing_if = "Option::is_none")]
pub evidence_count: Option<usize>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub details: BTreeMap<String, String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct GraphCanvasSummary {
pub kind: GraphCanvasKind,
pub node_count: usize,
pub edge_count: usize,
pub truncated: bool,
pub available_kinds: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct GraphCanvasResponse {
pub metadata: ApiMetadata,
pub nodes: Vec<GraphCanvasNode>,
pub edges: Vec<GraphCanvasEdge>,
pub summary: GraphCanvasSummary,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct IngestEvidence {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub source_path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub span: Option<EvidenceSpan>,
#[serde(skip_serializing_if = "Option::is_none")]
pub confidence: Option<ConfidenceScore>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<FactStatus>,
pub content: String,
#[serde(default)]
pub entity_labels: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extraction: Option<IngestEvidenceExtraction>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct IngestEvidenceExtraction {
pub modality: EvidenceModality,
#[serde(skip_serializing_if = "Option::is_none")]
pub source_uri: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub source_hash: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub media_hash: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub extractor: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub extractor_version: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub observed_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parent_evidence_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub layout_region: Option<LayoutRegion>,
#[serde(skip_serializing_if = "Option::is_none")]
pub embedding_model: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub embedding_dimension: Option<u16>,
#[serde(skip_serializing_if = "Option::is_none")]
pub diagnostic: Option<ExtractionDiagnostic>,
}
impl IngestEvidenceExtraction {
pub fn into_domain_metadata(self) -> EvidenceExtractionMetadata {
EvidenceExtractionMetadata {
modality: self.modality,
source_uri: self.source_uri,
source_hash: self.source_hash,
media_hash: self.media_hash,
extractor: self.extractor,
extractor_version: self.extractor_version,
observed_at: self.observed_at,
parent_evidence_id: self.parent_evidence_id,
layout_region: self.layout_region,
embedding_model: self.embedding_model,
embedding_dimension: self.embedding_dimension,
diagnostic: self
.diagnostic
.unwrap_or_else(|| EvidenceExtractionMetadata::text_span().diagnostic),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct IngestRelation {
pub id: String,
pub source_entity_label: String,
pub relation_type: String,
pub target_entity_label: String,
#[serde(default)]
pub evidence_ids: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub confidence: Option<ConfidenceScore>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<FactStatus>,
#[serde(skip_serializing_if = "Option::is_none")]
pub version_range: Option<GraphVersionRange>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct IngestClaim {
pub id: String,
pub subject_entity_label: String,
pub predicate: String,
pub object: String,
#[serde(default)]
pub evidence_ids: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub confidence: Option<ConfidenceScore>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<FactStatus>,
#[serde(skip_serializing_if = "Option::is_none")]
pub version_range: Option<GraphVersionRange>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct IngestEvent {
pub id: String,
pub event_type: String,
#[serde(default)]
pub entity_labels: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub occurred_at: Option<String>,
#[serde(default)]
pub evidence_ids: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub confidence: Option<ConfidenceScore>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<FactStatus>,
#[serde(skip_serializing_if = "Option::is_none")]
pub version_range: Option<GraphVersionRange>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct IngestRequest {
pub source_scope: String,
#[serde(default)]
pub evidence: Vec<IngestEvidence>,
#[serde(default)]
pub relations: Vec<IngestRelation>,
#[serde(default)]
pub claims: Vec<IngestClaim>,
#[serde(default)]
pub events: Vec<IngestEvent>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct IngestResponse {
pub metadata: ApiMetadata,
pub receipt: CommitReceipt,
pub indexes: Vec<IndexStatus>,
#[serde(skip_serializing_if = "Option::is_none")]
pub index_refresh_error: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct MultimodalExtractionRequest {
pub source_scope: String,
pub parent_evidence_id: String,
pub derived_evidence: Vec<IngestEvidence>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct MultimodalExtractionResponse {
pub metadata: ApiMetadata,
pub parent_evidence_id: String,
pub derived_evidence_count: usize,
pub receipt: CommitReceipt,
pub indexes: Vec<IndexStatus>,
#[serde(skip_serializing_if = "Option::is_none")]
pub index_refresh_error: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct HybridRetrievalRequest {
pub query: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub source_scope: Option<String>,
pub limit: usize,
pub freshness: FreshnessPolicy,
}
impl HybridRetrievalRequest {
pub fn new(query: impl Into<String>) -> Self {
Self {
query: query.into(),
source_scope: None,
limit: 10,
freshness: FreshnessPolicy::default(),
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct HybridRetrievalResponse {
pub metadata: ApiMetadata,
pub context_pack: RetrievedContextPack,
pub retrieval_mode: RetrievalMode,
#[serde(skip_serializing_if = "Option::is_none")]
pub source_scope: Option<String>,
pub freshness: FreshnessPolicy,
pub results: Vec<RetrievalHit>,
pub fusion: FusionDiagnostics,
pub rerank: RerankDiagnostics,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub backend_statuses: Vec<RetrievalBackendStatus>,
pub truncated: bool,
pub budget_used: RetrievalBudgetUsed,
#[serde(skip_serializing_if = "Option::is_none")]
pub degraded_reason: Option<String>,
pub indexes: Vec<IndexStatus>,
#[serde(default)]
pub index_cursors: Vec<IndexCursor>,
#[serde(default)]
pub index_refresh: IndexRefreshDiagnostics,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct GraphInspectionRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub source_scope: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct GraphInspectionResponse {
pub metadata: ApiMetadata,
pub graph: GraphInspection,
pub repository_code_totals: CodeRepositoryTotals,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct IndexRefreshRequest {
#[serde(default)]
pub kinds: Vec<IndexKind>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct IndexRefreshResponse {
pub metadata: ApiMetadata,
pub indexes: Vec<IndexStatus>,
pub index_cursors: Vec<IndexCursor>,
pub diagnostics: IndexRefreshDiagnostics,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FileIndexRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub source_scope: Option<String>,
#[serde(default)]
pub roots: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FileIndexResponse {
pub metadata: ApiMetadata,
pub summary: crate::storage::FileIndexScanSummary,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FileQueryRequest {
pub query: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub source_scope: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub root_id: Option<String>,
pub limit: usize,
#[serde(default)]
pub freshness_policy: FreshnessPolicy,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FileQueryResponse {
pub metadata: ApiMetadata,
pub query: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub source_scope: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub root_id: Option<String>,
#[serde(default = "FileIndexFreshnessDiagnostics::legacy_unknown")]
pub freshness: FileIndexFreshnessDiagnostics,
pub results: Vec<crate::storage::FileSearchHit>,
pub truncated: bool,
pub duration_ms: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub degraded_reason: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ServiceStatusResponse {
pub metadata: ApiMetadata,
pub service_name: String,
pub mode: String,
pub background_enabled: bool,
pub silent_updates_enabled: bool,
pub service_definition_path: String,
pub storage: StorageTopologyDiagnostics,
pub index_refresh: IndexRefreshDiagnostics,
pub file_index: crate::storage::FileIndexDiagnostics,
pub agent_protocols: AgentProtocolStatus,
pub operator: ServiceOperatorStatus,
pub workers: Vec<WorkerStatus>,
pub code_index_workers: CodeIndexWorkerStatus,
pub proposal_backlog: usize,
pub audit_sink: AuditSinkStatus,
#[serde(default = "super::watcher_diagnostics::WatcherDiagnostics::default_disabled")]
pub watcher: super::watcher_diagnostics::WatcherDiagnostics,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct StorageTopologyDiagnostics {
pub topology: String,
pub control_database_path: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub repository_shards_dir: Option<String>,
pub shard_catalog_active: bool,
pub active_shard_count: usize,
pub staged_shard_count: usize,
pub missing_shard_count: usize,
pub runtime_state_paths: Vec<String>,
pub shards: Vec<StorageShardDiagnostics>,
#[serde(skip_serializing_if = "Option::is_none")]
pub degraded_reason: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct StorageShardDiagnostics {
pub repository_id: String,
pub state: String,
pub shard_locator: String,
pub resolved_path: String,
pub source_scope_count: usize,
pub exists: bool,
pub updated_at_ms: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub degraded_reason: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct StorageTopologyResponse {
pub metadata: ApiMetadata,
pub storage: StorageTopologyDiagnostics,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodeIndexWorkerStatus {
pub configured_worker_count: usize,
pub active_worker_slots: usize,
pub queue_depth: usize,
pub queued_task_count: usize,
pub running_task_count: usize,
pub retrying_task_count: usize,
pub dead_letter_task_count: usize,
pub running_lease_count: usize,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_error: Option<String>,
}
impl CodeIndexWorkerStatus {
pub fn from_queue(configured_worker_count: usize, queue: CodeIndexTaskQueueStatus) -> Self {
let queue_depth = queue
.queued_task_count
.saturating_add(queue.retrying_task_count);
Self {
configured_worker_count,
active_worker_slots: configured_worker_count.saturating_sub(queue.running_task_count),
queue_depth,
queued_task_count: queue.queued_task_count,
running_task_count: queue.running_task_count,
retrying_task_count: queue.retrying_task_count,
dead_letter_task_count: queue.dead_letter_task_count,
running_lease_count: queue.running_lease_count,
last_error: queue.last_error,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AuditSinkStatus {
pub durable: bool,
pub event_count: usize,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_error: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct WorkerStatusRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub kind: Option<WorkerKind>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct WorkerStatusResponse {
pub metadata: ApiMetadata,
pub workers: Vec<WorkerStatus>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct WorkerRunRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub kind: Option<WorkerKind>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct WorkerRunResponse {
pub metadata: ApiMetadata,
#[serde(skip_serializing_if = "Option::is_none")]
pub task: Option<WorkerTaskRecord>,
#[serde(default)]
pub proposals: Vec<ProposalRecord>,
pub workers: Vec<WorkerStatus>,
#[serde(skip_serializing_if = "Option::is_none")]
pub degraded_reason: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodeIndexWorkerRunRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub task_id: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodeIndexWorkerRunResponse {
pub metadata: ApiMetadata,
pub worker_kind: String,
pub claimed: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub task: Option<CodeIndexTaskRecord>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ProposalListApiRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub state: Option<ProposalState>,
pub limit: usize,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ProposalListResponse {
pub metadata: ApiMetadata,
pub proposals: Vec<ProposalRecord>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ProposalShowResponse {
pub metadata: ApiMetadata,
pub proposal: ProposalRecord,
pub conflicts: Vec<ProposalConflictRecord>,
pub payload: serde_json::Value,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ProposalDecisionApiRequest {
pub actor: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub reason: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ProposalDecisionResponse {
pub metadata: ApiMetadata,
pub proposal: ProposalRecord,
#[serde(skip_serializing_if = "Option::is_none")]
pub receipt: Option<CommitReceipt>,
#[serde(skip_serializing_if = "Option::is_none")]
pub index_refresh_error: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AuditQueryApiRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub operation: Option<String>,
pub limit: usize,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AuditQueryResponse {
pub metadata: ApiMetadata,
pub events: Vec<crate::domain::AuditEventRecord>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ServiceDefinitionWriteResponse {
pub metadata: ApiMetadata,
pub plan: ServiceDefinitionPlan,
pub written: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ServiceOperatorResponse {
pub metadata: ApiMetadata,
pub operator: ServiceOperatorStatus,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ServiceRecoveryReport {
pub metadata: ApiMetadata,
pub graph_version: u64,
pub stale_index_kinds: Vec<IndexKind>,
pub refreshed_index_kinds: Vec<IndexKind>,
pub index_lag_max: u64,
pub task_queue_depth: usize,
pub dead_letter_count: usize,
pub heartbeat_state: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct HealthResponse {
pub metadata: ApiMetadata,
pub healthy: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub degraded_reason: Option<String>,
pub storage: StorageTopologyDiagnostics,
pub graph: GraphInspection,
pub repository_code_totals: CodeRepositoryTotals,
pub indexes: Vec<IndexStatus>,
pub index_cursors: Vec<IndexCursor>,
pub index_refresh: IndexRefreshDiagnostics,
pub file_index: crate::storage::FileIndexDiagnostics,
pub runtime: RuntimeStatus,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct EmbeddingProviderProbeResponse {
pub metadata: ApiMetadata,
pub ok: bool,
pub provider: Option<String>,
pub model: String,
pub dimension: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub latency_ms: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error_code: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error_message: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub retryable: Option<bool>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodeRepositoryRegisterRequest {
pub root_path: String,
#[serde(default)]
pub alias: String,
#[serde(default)]
pub path_filters: Vec<String>,
#[serde(default)]
pub language_filters: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodeRepositoryRegisterResponse {
pub metadata: ApiMetadata,
pub registration: CodeRepositoryRegistration,
pub status: CodeRepositoryStatus,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodeRepositoryRemoveResponse {
pub metadata: ApiMetadata,
pub removed_status: CodeRepositoryStatus,
pub summary: CodeRepositoryRemovalSummary,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodeRepositoryIndexResponse {
pub metadata: ApiMetadata,
pub scope: CodeRepositoryScopeMetadata,
pub summary: CodeIndexSummary,
pub status: CodeRepositoryStatus,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodeRepositoryIndexStartResponse {
pub metadata: ApiMetadata,
pub scope: CodeRepositoryScopeMetadata,
#[serde(skip_serializing_if = "Option::is_none")]
pub summary: Option<CodeIndexSummary>,
pub status: CodeRepositoryStatus,
#[serde(skip_serializing_if = "Option::is_none")]
pub task: Option<CodeIndexTaskRecord>,
#[serde(skip_serializing_if = "Option::is_none")]
pub checkpoint: Option<CodeIndexCheckpoint>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodeRepositoryIndexResetResponse {
pub metadata: ApiMetadata,
pub status: CodeRepositoryStatus,
pub reset_task_count: usize,
pub reset_tasks: Vec<CodeIndexTaskRecord>,
#[serde(skip_serializing_if = "Option::is_none")]
pub active_task: Option<CodeIndexTaskRecord>,
#[serde(skip_serializing_if = "Option::is_none")]
pub checkpoint: Option<CodeIndexCheckpoint>,
pub retention: CodeScopeRetentionSummary,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodeRepositoryScopePreviewResponse {
pub metadata: ApiMetadata,
pub scope: CodeRepositoryScopeMetadata,
pub preview: CodeRepositoryScopePreview,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodeRepositoryScopeMetadata {
pub scope_id: String,
pub repository_id: String,
pub alias: String,
pub requested_ref: String,
pub resolved_commit_sha: String,
pub tree_hash: String,
pub path_filters: Vec<String>,
pub language_filters: Vec<String>,
#[serde(default)]
pub indexed_file_count: usize,
pub index_versions: Vec<String>,
pub stale: bool,
}
impl CodeRepositoryScopeMetadata {
pub fn from_status(
status: &CodeRepositoryStatus,
selector: &CodeRepositorySelector,
requested_ref: impl Into<String>,
) -> Self {
Self {
scope_id: status.last_indexed_scope_id.clone().unwrap_or_default(),
repository_id: status.repository_id.clone(),
alias: status.alias.clone(),
requested_ref: requested_ref.into(),
resolved_commit_sha: status.last_indexed_commit.clone().unwrap_or_default(),
tree_hash: status.tree_hash.clone().unwrap_or_default(),
path_filters: merged_filters(&status.path_filters, &selector.path_filters),
language_filters: merged_filters(&status.language_filters, &selector.language_filters),
indexed_file_count: status.indexed_file_count,
index_versions: vec![format!(
"code:{}:{}",
status
.last_indexed_scope_id
.as_deref()
.unwrap_or("unscoped"),
status.tree_hash.as_deref().unwrap_or("unindexed")
)],
stale: status.stale,
}
}
pub fn from_index_task(task: &CodeIndexTaskRecord, requested_ref: impl Into<String>) -> Self {
Self {
scope_id: task.source_scope.clone(),
repository_id: task.repository_id.clone(),
alias: task.alias.clone(),
requested_ref: requested_ref.into(),
resolved_commit_sha: task.resolved_commit_sha.clone(),
tree_hash: task.tree_hash.clone(),
path_filters: task.path_filters.clone(),
language_filters: task.language_filters.clone(),
indexed_file_count: 0,
index_versions: vec![format!("code:{}:{}", task.source_scope, task.tree_hash)],
stale: true,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CodeRepositoryQueryResponse {
pub metadata: ApiMetadata,
pub scope: CodeRepositoryScopeMetadata,
#[serde(default = "CodeRepositoryFreshnessDiagnostics::legacy_unknown")]
pub freshness: CodeRepositoryFreshnessDiagnostics,
pub request: CodeRetrievalRequest,
pub results: Vec<CodeRetrievalHit>,
#[serde(skip_serializing_if = "Option::is_none")]
pub degraded_reason: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CodeRepositoryFeatureFlagsResponse {
pub metadata: ApiMetadata,
pub scope: CodeRepositoryScopeMetadata,
#[serde(default = "CodeRepositoryFreshnessDiagnostics::legacy_unknown")]
pub freshness: CodeRepositoryFreshnessDiagnostics,
pub request: CodeFeatureFlagRequest,
pub flags: Vec<CodeFeatureFlagGraph>,
#[serde(skip_serializing_if = "Option::is_none")]
pub degraded_reason: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CodeRepositoryImpactResponse {
pub metadata: ApiMetadata,
pub scope: CodeRepositoryScopeMetadata,
pub request: CodeImpactRequest,
pub path_groups: CodeImpactPathGroups,
pub results: Vec<CodeRetrievalHit>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodeRepositoryStatusResponse {
pub metadata: ApiMetadata,
pub status: CodeRepositoryStatus,
#[serde(skip_serializing_if = "Option::is_none")]
pub active_task: Option<CodeIndexTaskRecord>,
#[serde(skip_serializing_if = "Option::is_none")]
pub checkpoint: Option<CodeIndexCheckpoint>,
pub retention: CodeScopeRetentionSummary,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CodeRepositoryReportResponse {
pub metadata: ApiMetadata,
pub scope: CodeRepositoryScopeMetadata,
pub report: CodeRepositoryReport,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SoftwareGlobalResponse {
pub metadata: ApiMetadata,
pub scope: CodeRepositoryScopeMetadata,
pub request: SoftwareGlobalRequest,
pub status: SoftwareGlobalStatus,
pub components: Vec<SoftwareComponent>,
pub dependency_usages: Vec<SoftwareDependencyUsage>,
pub sdk_usages: Vec<SoftwareSdkUsage>,
pub files: Vec<SoftwareFile>,
pub topics: Vec<SoftwareTopic>,
pub relationships: Vec<SoftwareRelationship>,
pub build_targets: Vec<SoftwareBuildTarget>,
pub iac_resources: Vec<SoftwareIacResource>,
pub design_elements: Vec<SoftwareDesignElement>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodeRepositorySetCreateResponse {
pub metadata: ApiMetadata,
pub request: CodeRepositorySetCreateRequest,
pub repository_set: CodeRepositorySet,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodeRepositorySetAddResponse {
pub metadata: ApiMetadata,
pub request: CodeRepositorySetAddMemberRequest,
pub member: CodeRepositorySetMember,
pub status: CodeRepositorySetStatus,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodeRepositorySetRemoveResponse {
pub metadata: ApiMetadata,
pub request: CodeRepositorySetRemoveMemberRequest,
pub member: CodeRepositorySetMember,
pub status: CodeRepositorySetStatus,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CodeRepositorySetQueryResponse {
pub metadata: ApiMetadata,
pub request: CodeRepositorySetQueryRequest,
pub status: CodeRepositorySetStatus,
pub results: Vec<CodeRepositorySetQueryHit>,
pub truncated: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub degraded_reason: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodeRepositorySetStatusResponse {
pub metadata: ApiMetadata,
pub status: CodeRepositorySetStatus,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodeRepositorySetRefreshResponse {
pub metadata: ApiMetadata,
pub status: CodeRepositorySetStatus,
#[serde(skip_serializing_if = "Option::is_none")]
pub summary: Option<CodeRepositorySetRefreshSummary>,
#[serde(skip_serializing_if = "Option::is_none")]
pub task: Option<CodeRepositorySetRefreshTaskRecord>,
}
fn merged_filters(base: &[String], request: &[String]) -> Vec<String> {
let mut merged = Vec::new();
for value in base.iter().chain(request.iter()) {
if !merged.contains(value) {
merged.push(value.clone());
}
}
merged
}