1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Serialize};
4
5use crate::{
6 domain::{
7 CodeFeatureFlagGraph, CodeFeatureFlagRequest, CodeImpactPathGroups, CodeImpactRequest,
8 CodeIndexCheckpoint, CodeIndexSummary, CodeIndexTaskRecord, CodeRepositoryRegistration,
9 CodeRepositoryReport, CodeRepositoryScopePreview, CodeRepositorySelector,
10 CodeRepositorySet, CodeRepositorySetAddMemberRequest, CodeRepositorySetCreateRequest,
11 CodeRepositorySetMember, CodeRepositorySetQueryHit, CodeRepositorySetQueryRequest,
12 CodeRepositorySetRefreshSummary, CodeRepositorySetRefreshTaskRecord,
13 CodeRepositorySetRemoveMemberRequest, CodeRepositorySetStatus, CodeRepositoryStatus,
14 CodeRepositoryTotals, CodeRetrievalHit, CodeRetrievalRequest, CodeScopeRetentionSummary,
15 CommitReceipt, ConfidenceScore, EvidenceExtractionMetadata, EvidenceModality, EvidenceSpan,
16 ExtractionDiagnostic, FactStatus, FreshnessPolicy, FusionDiagnostics, GraphVersionRange,
17 IndexKind, IndexStatus, LayoutRegion, ProposalConflictRecord, ProposalRecord,
18 ProposalState, RerankDiagnostics, RetrievalBackendStatus, RetrievalBudgetUsed,
19 RetrievalHit, RetrievalMode, RetrievedContextPack, ServiceDefinitionPlan,
20 ServiceManagerAction, ServiceOperatorStatus, SoftwareBuildTarget, SoftwareComponent,
21 SoftwareDependencyUsage, SoftwareDesignElement, SoftwareFile, SoftwareGlobalRequest,
22 SoftwareGlobalStatus, SoftwareIacResource, SoftwareRelationship, SoftwareSdkUsage,
23 SoftwareTopic, WorkerKind, WorkerStatus, WorkerTaskRecord,
24 },
25 storage::{GraphInspection, IndexCursor, IndexRefreshDiagnostics},
26};
27
28use super::{AgentProtocolStatus, ApiMetadata, RuntimeStatus};
29
30pub const GRAPH_CANVAS_DEFAULT_LIMIT: usize = 250;
31pub const GRAPH_CANVAS_MAX_LIMIT: usize = 1000;
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
35#[serde(rename_all = "snake_case")]
36pub enum GraphCanvasKind {
37 Knowledge,
38 Code,
39 Mixed,
40}
41
42impl GraphCanvasKind {
43 pub fn parse(value: &str) -> Result<Self, String> {
45 match value {
46 "knowledge" => Ok(Self::Knowledge),
47 "code" => Ok(Self::Code),
48 "mixed" => Ok(Self::Mixed),
49 _ => Err(format!("unsupported graph canvas kind '{value}'")),
50 }
51 }
52
53 pub const fn as_str(self) -> &'static str {
55 match self {
56 Self::Knowledge => "knowledge",
57 Self::Code => "code",
58 Self::Mixed => "mixed",
59 }
60 }
61}
62
63#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
65pub struct GraphCanvasRequest {
66 pub kind: GraphCanvasKind,
67 #[serde(skip_serializing_if = "Option::is_none")]
68 pub source_scope: Option<String>,
69 #[serde(skip_serializing_if = "Option::is_none")]
70 pub query: Option<String>,
71 pub limit: usize,
72}
73
74#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
76pub struct GraphCanvasNode {
77 pub id: String,
78 pub kind: String,
79 pub label: String,
80 #[serde(skip_serializing_if = "Option::is_none")]
81 pub subtitle: Option<String>,
82 #[serde(skip_serializing_if = "Option::is_none")]
83 pub source_scope: Option<String>,
84 pub graph_version: u64,
85 pub weight: u32,
86 #[serde(skip_serializing_if = "Option::is_none")]
87 pub status: Option<String>,
88 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
89 pub details: BTreeMap<String, String>,
90}
91
92#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
94pub struct GraphCanvasEdge {
95 pub id: String,
96 pub kind: String,
97 pub source: String,
98 pub target: String,
99 pub label: String,
100 pub graph_version: u64,
101 #[serde(skip_serializing_if = "Option::is_none")]
102 pub confidence_basis_points: Option<u16>,
103 #[serde(skip_serializing_if = "Option::is_none")]
104 pub evidence_count: Option<usize>,
105 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
106 pub details: BTreeMap<String, String>,
107}
108
109#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
111pub struct GraphCanvasSummary {
112 pub kind: GraphCanvasKind,
113 pub node_count: usize,
114 pub edge_count: usize,
115 pub truncated: bool,
116 pub available_kinds: Vec<String>,
117}
118
119#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
121pub struct GraphCanvasResponse {
122 pub metadata: ApiMetadata,
123 pub nodes: Vec<GraphCanvasNode>,
124 pub edges: Vec<GraphCanvasEdge>,
125 pub summary: GraphCanvasSummary,
126}
127
128#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
130pub struct IngestEvidence {
131 #[serde(skip_serializing_if = "Option::is_none")]
132 pub id: Option<String>,
133 #[serde(skip_serializing_if = "Option::is_none")]
134 pub source_path: Option<String>,
135 #[serde(skip_serializing_if = "Option::is_none")]
136 pub span: Option<EvidenceSpan>,
137 #[serde(skip_serializing_if = "Option::is_none")]
138 pub confidence: Option<ConfidenceScore>,
139 #[serde(skip_serializing_if = "Option::is_none")]
140 pub status: Option<FactStatus>,
141 pub content: String,
142 #[serde(default)]
143 pub entity_labels: Vec<String>,
144 #[serde(default, skip_serializing_if = "Option::is_none")]
145 pub extraction: Option<IngestEvidenceExtraction>,
146}
147
148#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
150pub struct IngestEvidenceExtraction {
151 pub modality: EvidenceModality,
152 #[serde(skip_serializing_if = "Option::is_none")]
153 pub source_uri: Option<String>,
154 #[serde(skip_serializing_if = "Option::is_none")]
155 pub source_hash: Option<String>,
156 #[serde(skip_serializing_if = "Option::is_none")]
157 pub media_hash: Option<String>,
158 #[serde(skip_serializing_if = "Option::is_none")]
159 pub extractor: Option<String>,
160 #[serde(skip_serializing_if = "Option::is_none")]
161 pub extractor_version: Option<String>,
162 #[serde(skip_serializing_if = "Option::is_none")]
163 pub observed_at: Option<String>,
164 #[serde(skip_serializing_if = "Option::is_none")]
165 pub parent_evidence_id: Option<String>,
166 #[serde(skip_serializing_if = "Option::is_none")]
167 pub layout_region: Option<LayoutRegion>,
168 #[serde(skip_serializing_if = "Option::is_none")]
169 pub embedding_model: Option<String>,
170 #[serde(skip_serializing_if = "Option::is_none")]
171 pub embedding_dimension: Option<u16>,
172 #[serde(skip_serializing_if = "Option::is_none")]
173 pub diagnostic: Option<ExtractionDiagnostic>,
174}
175
176impl IngestEvidenceExtraction {
177 pub fn into_domain_metadata(self) -> EvidenceExtractionMetadata {
179 EvidenceExtractionMetadata {
180 modality: self.modality,
181 source_uri: self.source_uri,
182 source_hash: self.source_hash,
183 media_hash: self.media_hash,
184 extractor: self.extractor,
185 extractor_version: self.extractor_version,
186 observed_at: self.observed_at,
187 parent_evidence_id: self.parent_evidence_id,
188 layout_region: self.layout_region,
189 embedding_model: self.embedding_model,
190 embedding_dimension: self.embedding_dimension,
191 diagnostic: self
192 .diagnostic
193 .unwrap_or_else(|| EvidenceExtractionMetadata::text_span().diagnostic),
194 }
195 }
196}
197
198#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
200pub struct IngestRelation {
201 pub id: String,
202 pub source_entity_label: String,
203 pub relation_type: String,
204 pub target_entity_label: String,
205 #[serde(default)]
206 pub evidence_ids: Vec<String>,
207 #[serde(skip_serializing_if = "Option::is_none")]
208 pub confidence: Option<ConfidenceScore>,
209 #[serde(skip_serializing_if = "Option::is_none")]
210 pub status: Option<FactStatus>,
211 #[serde(skip_serializing_if = "Option::is_none")]
212 pub version_range: Option<GraphVersionRange>,
213}
214
215#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
217pub struct IngestClaim {
218 pub id: String,
219 pub subject_entity_label: String,
220 pub predicate: String,
221 pub object: String,
222 #[serde(default)]
223 pub evidence_ids: Vec<String>,
224 #[serde(skip_serializing_if = "Option::is_none")]
225 pub confidence: Option<ConfidenceScore>,
226 #[serde(skip_serializing_if = "Option::is_none")]
227 pub status: Option<FactStatus>,
228 #[serde(skip_serializing_if = "Option::is_none")]
229 pub version_range: Option<GraphVersionRange>,
230}
231
232#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
234pub struct IngestEvent {
235 pub id: String,
236 pub event_type: String,
237 #[serde(default)]
238 pub entity_labels: Vec<String>,
239 #[serde(skip_serializing_if = "Option::is_none")]
240 pub occurred_at: Option<String>,
241 #[serde(default)]
242 pub evidence_ids: Vec<String>,
243 #[serde(skip_serializing_if = "Option::is_none")]
244 pub confidence: Option<ConfidenceScore>,
245 #[serde(skip_serializing_if = "Option::is_none")]
246 pub status: Option<FactStatus>,
247 #[serde(skip_serializing_if = "Option::is_none")]
248 pub version_range: Option<GraphVersionRange>,
249}
250
251#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
253pub struct IngestRequest {
254 pub source_scope: String,
255 #[serde(default)]
256 pub evidence: Vec<IngestEvidence>,
257 #[serde(default)]
258 pub relations: Vec<IngestRelation>,
259 #[serde(default)]
260 pub claims: Vec<IngestClaim>,
261 #[serde(default)]
262 pub events: Vec<IngestEvent>,
263}
264
265#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
267pub struct IngestResponse {
268 pub metadata: ApiMetadata,
269 pub receipt: CommitReceipt,
270 pub indexes: Vec<IndexStatus>,
271 #[serde(skip_serializing_if = "Option::is_none")]
272 pub index_refresh_error: Option<String>,
273}
274
275#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
277pub struct MultimodalExtractionRequest {
278 pub source_scope: String,
279 pub parent_evidence_id: String,
280 pub derived_evidence: Vec<IngestEvidence>,
281}
282
283#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
285pub struct MultimodalExtractionResponse {
286 pub metadata: ApiMetadata,
287 pub parent_evidence_id: String,
288 pub derived_evidence_count: usize,
289 pub receipt: CommitReceipt,
290 pub indexes: Vec<IndexStatus>,
291 #[serde(skip_serializing_if = "Option::is_none")]
292 pub index_refresh_error: Option<String>,
293}
294
295#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
297pub struct HybridRetrievalRequest {
298 pub query: String,
299 #[serde(skip_serializing_if = "Option::is_none")]
300 pub source_scope: Option<String>,
301 pub limit: usize,
302 pub freshness: FreshnessPolicy,
303}
304
305impl HybridRetrievalRequest {
306 pub fn new(query: impl Into<String>) -> Self {
308 Self {
309 query: query.into(),
310 source_scope: None,
311 limit: 10,
312 freshness: FreshnessPolicy::default(),
313 }
314 }
315}
316
317#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
319pub struct HybridRetrievalResponse {
320 pub metadata: ApiMetadata,
321 pub context_pack: RetrievedContextPack,
322 pub retrieval_mode: RetrievalMode,
323 #[serde(skip_serializing_if = "Option::is_none")]
324 pub source_scope: Option<String>,
325 pub freshness: FreshnessPolicy,
326 pub results: Vec<RetrievalHit>,
327 pub fusion: FusionDiagnostics,
328 pub rerank: RerankDiagnostics,
329 #[serde(default, skip_serializing_if = "Vec::is_empty")]
330 pub backend_statuses: Vec<RetrievalBackendStatus>,
331 pub truncated: bool,
332 pub budget_used: RetrievalBudgetUsed,
333 #[serde(skip_serializing_if = "Option::is_none")]
334 pub degraded_reason: Option<String>,
335 pub indexes: Vec<IndexStatus>,
336}
337
338#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
340pub struct GraphInspectionRequest {
341 #[serde(skip_serializing_if = "Option::is_none")]
342 pub source_scope: Option<String>,
343}
344
345#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
347pub struct GraphInspectionResponse {
348 pub metadata: ApiMetadata,
349 pub graph: GraphInspection,
350 pub repository_code_totals: CodeRepositoryTotals,
351}
352
353#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
355pub struct IndexRefreshRequest {
356 #[serde(default)]
357 pub kinds: Vec<IndexKind>,
358}
359
360#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
362pub struct IndexRefreshResponse {
363 pub metadata: ApiMetadata,
364 pub indexes: Vec<IndexStatus>,
365 pub index_cursors: Vec<IndexCursor>,
366 pub diagnostics: IndexRefreshDiagnostics,
367}
368
369#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
371pub struct FileIndexRequest {
372 #[serde(skip_serializing_if = "Option::is_none")]
373 pub source_scope: Option<String>,
374 #[serde(default)]
375 pub roots: Vec<String>,
376}
377
378#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
380pub struct FileIndexResponse {
381 pub metadata: ApiMetadata,
382 pub summary: crate::storage::FileIndexScanSummary,
383}
384
385#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
387pub struct FileQueryRequest {
388 pub query: String,
389 #[serde(skip_serializing_if = "Option::is_none")]
390 pub source_scope: Option<String>,
391 #[serde(skip_serializing_if = "Option::is_none")]
392 pub root_id: Option<String>,
393 pub limit: usize,
394}
395
396#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
398pub struct FileQueryResponse {
399 pub metadata: ApiMetadata,
400 pub query: String,
401 #[serde(skip_serializing_if = "Option::is_none")]
402 pub source_scope: Option<String>,
403 #[serde(skip_serializing_if = "Option::is_none")]
404 pub root_id: Option<String>,
405 pub results: Vec<crate::storage::FileSearchHit>,
406 pub truncated: bool,
407 pub duration_ms: u64,
408 #[serde(skip_serializing_if = "Option::is_none")]
409 pub degraded_reason: Option<String>,
410}
411
412#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
414pub struct ServiceStatusResponse {
415 pub metadata: ApiMetadata,
416 pub service_name: String,
417 pub mode: String,
418 pub background_enabled: bool,
419 pub silent_updates_enabled: bool,
420 pub service_definition_path: String,
421 pub index_refresh: IndexRefreshDiagnostics,
422 pub file_index: crate::storage::FileIndexDiagnostics,
423 pub agent_protocols: AgentProtocolStatus,
424 pub operator: ServiceOperatorStatus,
425 pub workers: Vec<WorkerStatus>,
426 pub proposal_backlog: usize,
427 pub audit_sink: AuditSinkStatus,
428}
429
430#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
432pub struct AuditSinkStatus {
433 pub durable: bool,
434 pub event_count: usize,
435 #[serde(skip_serializing_if = "Option::is_none")]
436 pub last_error: Option<String>,
437}
438
439#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
441pub struct WorkerStatusRequest {
442 #[serde(skip_serializing_if = "Option::is_none")]
443 pub kind: Option<WorkerKind>,
444}
445
446#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
448pub struct WorkerStatusResponse {
449 pub metadata: ApiMetadata,
450 pub workers: Vec<WorkerStatus>,
451}
452
453#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
455pub struct WorkerRunRequest {
456 #[serde(skip_serializing_if = "Option::is_none")]
457 pub kind: Option<WorkerKind>,
458}
459
460#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
462pub struct WorkerRunResponse {
463 pub metadata: ApiMetadata,
464 #[serde(skip_serializing_if = "Option::is_none")]
465 pub task: Option<WorkerTaskRecord>,
466 #[serde(default)]
467 pub proposals: Vec<ProposalRecord>,
468 pub workers: Vec<WorkerStatus>,
469 #[serde(skip_serializing_if = "Option::is_none")]
470 pub degraded_reason: Option<String>,
471}
472
473#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
475pub struct ProposalListApiRequest {
476 #[serde(skip_serializing_if = "Option::is_none")]
477 pub state: Option<ProposalState>,
478 pub limit: usize,
479}
480
481#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
483pub struct ProposalListResponse {
484 pub metadata: ApiMetadata,
485 pub proposals: Vec<ProposalRecord>,
486}
487
488#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
490pub struct ProposalShowResponse {
491 pub metadata: ApiMetadata,
492 pub proposal: ProposalRecord,
493 pub conflicts: Vec<ProposalConflictRecord>,
494 pub payload: serde_json::Value,
495}
496
497#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
499pub struct ProposalDecisionApiRequest {
500 pub actor: String,
501 #[serde(skip_serializing_if = "Option::is_none")]
502 pub reason: Option<String>,
503}
504
505#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
507pub struct ProposalDecisionResponse {
508 pub metadata: ApiMetadata,
509 pub proposal: ProposalRecord,
510 #[serde(skip_serializing_if = "Option::is_none")]
511 pub receipt: Option<CommitReceipt>,
512 #[serde(skip_serializing_if = "Option::is_none")]
513 pub index_refresh_error: Option<String>,
514}
515
516#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
518pub struct AuditQueryApiRequest {
519 #[serde(skip_serializing_if = "Option::is_none")]
520 pub operation: Option<String>,
521 pub limit: usize,
522}
523
524#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
526pub struct AuditQueryResponse {
527 pub metadata: ApiMetadata,
528 pub events: Vec<crate::domain::AuditEventRecord>,
529}
530
531#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
533pub struct ServicePlanRequest {
534 pub action: ServiceManagerAction,
535}
536
537#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
539pub struct ServicePlanResponse {
540 pub metadata: ApiMetadata,
541 pub plan: ServiceDefinitionPlan,
542}
543
544#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
546pub struct ServiceDefinitionWriteResponse {
547 pub metadata: ApiMetadata,
548 pub plan: ServiceDefinitionPlan,
549 pub written: bool,
550}
551
552#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
554pub struct ServiceOperatorResponse {
555 pub metadata: ApiMetadata,
556 pub operator: ServiceOperatorStatus,
557}
558
559#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
561pub struct ServiceRecoveryReport {
562 pub metadata: ApiMetadata,
563 pub graph_version: u64,
564 pub stale_index_kinds: Vec<IndexKind>,
565 pub refreshed_index_kinds: Vec<IndexKind>,
566 pub index_lag_max: u64,
567 pub task_queue_depth: usize,
568 pub dead_letter_count: usize,
569 pub heartbeat_state: String,
570}
571
572#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
574pub struct HealthResponse {
575 pub metadata: ApiMetadata,
576 pub healthy: bool,
577 #[serde(skip_serializing_if = "Option::is_none")]
578 pub degraded_reason: Option<String>,
579 pub graph: GraphInspection,
580 pub repository_code_totals: CodeRepositoryTotals,
581 pub indexes: Vec<IndexStatus>,
582 pub index_cursors: Vec<IndexCursor>,
583 pub index_refresh: IndexRefreshDiagnostics,
584 pub file_index: crate::storage::FileIndexDiagnostics,
585 pub runtime: RuntimeStatus,
586}
587
588#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
590pub struct EmbeddingProviderProbeResponse {
591 pub metadata: ApiMetadata,
592 pub ok: bool,
593 pub provider: Option<String>,
594 pub model: String,
595 pub dimension: u32,
596 #[serde(skip_serializing_if = "Option::is_none")]
597 pub latency_ms: Option<u64>,
598 #[serde(skip_serializing_if = "Option::is_none")]
599 pub error_code: Option<String>,
600 #[serde(skip_serializing_if = "Option::is_none")]
601 pub error_message: Option<String>,
602 #[serde(skip_serializing_if = "Option::is_none")]
603 pub retryable: Option<bool>,
604}
605
606#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
608pub struct CodeRepositoryRegisterRequest {
609 pub root_path: String,
610 #[serde(default)]
611 pub alias: String,
612 #[serde(default)]
613 pub path_filters: Vec<String>,
614 #[serde(default)]
615 pub language_filters: Vec<String>,
616}
617
618#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
620pub struct CodeRepositoryRegisterResponse {
621 pub metadata: ApiMetadata,
622 pub registration: CodeRepositoryRegistration,
623 pub status: CodeRepositoryStatus,
624}
625
626#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
628pub struct CodeRepositoryIndexResponse {
629 pub metadata: ApiMetadata,
630 pub scope: CodeRepositoryScopeMetadata,
631 pub summary: CodeIndexSummary,
632 pub status: CodeRepositoryStatus,
633}
634
635#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
637pub struct CodeRepositoryIndexStartResponse {
638 pub metadata: ApiMetadata,
639 pub scope: CodeRepositoryScopeMetadata,
640 #[serde(skip_serializing_if = "Option::is_none")]
641 pub summary: Option<CodeIndexSummary>,
642 pub status: CodeRepositoryStatus,
643 #[serde(skip_serializing_if = "Option::is_none")]
644 pub task: Option<CodeIndexTaskRecord>,
645 #[serde(skip_serializing_if = "Option::is_none")]
646 pub checkpoint: Option<CodeIndexCheckpoint>,
647}
648
649#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
651pub struct CodeRepositoryScopePreviewResponse {
652 pub metadata: ApiMetadata,
653 pub scope: CodeRepositoryScopeMetadata,
654 pub preview: CodeRepositoryScopePreview,
655}
656
657#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
659pub struct CodeRepositoryScopeMetadata {
660 pub scope_id: String,
661 pub repository_id: String,
662 pub alias: String,
663 pub requested_ref: String,
664 pub resolved_commit_sha: String,
665 pub tree_hash: String,
666 pub path_filters: Vec<String>,
667 pub language_filters: Vec<String>,
668 pub index_versions: Vec<String>,
669 pub stale: bool,
670}
671
672impl CodeRepositoryScopeMetadata {
673 pub fn from_status(
675 status: &CodeRepositoryStatus,
676 selector: &CodeRepositorySelector,
677 requested_ref: impl Into<String>,
678 ) -> Self {
679 Self {
680 scope_id: status.last_indexed_scope_id.clone().unwrap_or_default(),
681 repository_id: status.repository_id.clone(),
682 alias: status.alias.clone(),
683 requested_ref: requested_ref.into(),
684 resolved_commit_sha: status.last_indexed_commit.clone().unwrap_or_default(),
685 tree_hash: status.tree_hash.clone().unwrap_or_default(),
686 path_filters: merged_filters(&status.path_filters, &selector.path_filters),
687 language_filters: merged_filters(&status.language_filters, &selector.language_filters),
688 index_versions: vec![format!(
689 "code:{}:{}",
690 status
691 .last_indexed_scope_id
692 .as_deref()
693 .unwrap_or("unscoped"),
694 status.tree_hash.as_deref().unwrap_or("unindexed")
695 )],
696 stale: status.stale,
697 }
698 }
699
700 pub fn from_index_task(task: &CodeIndexTaskRecord, requested_ref: impl Into<String>) -> Self {
702 Self {
703 scope_id: task.source_scope.clone(),
704 repository_id: task.repository_id.clone(),
705 alias: task.alias.clone(),
706 requested_ref: requested_ref.into(),
707 resolved_commit_sha: task.resolved_commit_sha.clone(),
708 tree_hash: task.tree_hash.clone(),
709 path_filters: task.path_filters.clone(),
710 language_filters: task.language_filters.clone(),
711 index_versions: vec![format!("code:{}:{}", task.source_scope, task.tree_hash)],
712 stale: true,
713 }
714 }
715}
716
717#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
719pub struct CodeRepositoryQueryResponse {
720 pub metadata: ApiMetadata,
721 pub scope: CodeRepositoryScopeMetadata,
722 pub request: CodeRetrievalRequest,
723 pub results: Vec<CodeRetrievalHit>,
724 #[serde(skip_serializing_if = "Option::is_none")]
725 pub degraded_reason: Option<String>,
726}
727
728#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
730pub struct CodeRepositoryFeatureFlagsResponse {
731 pub metadata: ApiMetadata,
732 pub scope: CodeRepositoryScopeMetadata,
733 pub request: CodeFeatureFlagRequest,
734 pub flags: Vec<CodeFeatureFlagGraph>,
735 #[serde(skip_serializing_if = "Option::is_none")]
736 pub degraded_reason: Option<String>,
737}
738
739#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
741pub struct CodeRepositoryImpactResponse {
742 pub metadata: ApiMetadata,
743 pub scope: CodeRepositoryScopeMetadata,
744 pub request: CodeImpactRequest,
745 pub path_groups: CodeImpactPathGroups,
746 pub results: Vec<CodeRetrievalHit>,
747}
748
749#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
751pub struct CodeRepositoryStatusResponse {
752 pub metadata: ApiMetadata,
753 pub status: CodeRepositoryStatus,
754 #[serde(skip_serializing_if = "Option::is_none")]
755 pub active_task: Option<CodeIndexTaskRecord>,
756 #[serde(skip_serializing_if = "Option::is_none")]
757 pub checkpoint: Option<CodeIndexCheckpoint>,
758 pub retention: CodeScopeRetentionSummary,
759}
760
761#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
763pub struct CodeRepositoryReportResponse {
764 pub metadata: ApiMetadata,
765 pub scope: CodeRepositoryScopeMetadata,
766 pub report: CodeRepositoryReport,
767}
768
769#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
771pub struct SoftwareGlobalResponse {
772 pub metadata: ApiMetadata,
773 pub scope: CodeRepositoryScopeMetadata,
774 pub request: SoftwareGlobalRequest,
775 pub status: SoftwareGlobalStatus,
776 pub components: Vec<SoftwareComponent>,
777 pub dependency_usages: Vec<SoftwareDependencyUsage>,
778 pub sdk_usages: Vec<SoftwareSdkUsage>,
779 pub files: Vec<SoftwareFile>,
780 pub topics: Vec<SoftwareTopic>,
781 pub relationships: Vec<SoftwareRelationship>,
782 pub build_targets: Vec<SoftwareBuildTarget>,
783 pub iac_resources: Vec<SoftwareIacResource>,
784 pub design_elements: Vec<SoftwareDesignElement>,
785}
786
787#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
789pub struct CodeRepositorySetCreateResponse {
790 pub metadata: ApiMetadata,
791 pub request: CodeRepositorySetCreateRequest,
792 pub repository_set: CodeRepositorySet,
793}
794
795#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
797pub struct CodeRepositorySetAddResponse {
798 pub metadata: ApiMetadata,
799 pub request: CodeRepositorySetAddMemberRequest,
800 pub member: CodeRepositorySetMember,
801 pub status: CodeRepositorySetStatus,
802}
803
804#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
806pub struct CodeRepositorySetRemoveResponse {
807 pub metadata: ApiMetadata,
808 pub request: CodeRepositorySetRemoveMemberRequest,
809 pub member: CodeRepositorySetMember,
810 pub status: CodeRepositorySetStatus,
811}
812
813#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
815pub struct CodeRepositorySetQueryResponse {
816 pub metadata: ApiMetadata,
817 pub request: CodeRepositorySetQueryRequest,
818 pub status: CodeRepositorySetStatus,
819 pub results: Vec<CodeRepositorySetQueryHit>,
820 pub truncated: bool,
821 #[serde(skip_serializing_if = "Option::is_none")]
822 pub degraded_reason: Option<String>,
823}
824
825#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
827pub struct CodeRepositorySetStatusResponse {
828 pub metadata: ApiMetadata,
829 pub status: CodeRepositorySetStatus,
830}
831
832#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
834pub struct CodeRepositorySetRefreshResponse {
835 pub metadata: ApiMetadata,
836 pub status: CodeRepositorySetStatus,
837 #[serde(skip_serializing_if = "Option::is_none")]
838 pub summary: Option<CodeRepositorySetRefreshSummary>,
839 #[serde(skip_serializing_if = "Option::is_none")]
840 pub task: Option<CodeRepositorySetRefreshTaskRecord>,
841}
842
843fn merged_filters(base: &[String], request: &[String]) -> Vec<String> {
844 let mut merged = Vec::new();
845 for value in base.iter().chain(request.iter()) {
846 if !merged.contains(value) {
847 merged.push(value.clone());
848 }
849 }
850
851 merged
852}