1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Serialize};
4
5use crate::{
6 domain::{
7 CodeFeatureFlagGraph, CodeFeatureFlagRequest, CodeImpactPathGroups, CodeImpactRequest,
8 CodeIndexCheckpoint, CodeIndexSummary, CodeIndexTaskQueueStatus, CodeIndexTaskRecord,
9 CodeRepositoryRegistration, CodeRepositoryRemovalSummary, CodeRepositoryReport,
10 CodeRepositoryScopePreview, CodeRepositorySelector, CodeRepositorySet,
11 CodeRepositorySetAddMemberRequest, CodeRepositorySetCreateRequest, CodeRepositorySetMember,
12 CodeRepositorySetQueryHit, CodeRepositorySetQueryRequest, CodeRepositorySetRefreshSummary,
13 CodeRepositorySetRefreshTaskRecord, CodeRepositorySetRemoveMemberRequest,
14 CodeRepositorySetStatus, CodeRepositoryStatus, CodeRepositoryTotals, CodeRetrievalHit,
15 CodeRetrievalRequest, CodeScopeRetentionSummary, CommitReceipt, ConfidenceScore,
16 EvidenceExtractionMetadata, EvidenceModality, EvidenceSpan, ExtractionDiagnostic,
17 FactStatus, FreshnessPolicy, FusionDiagnostics, GraphVersionRange, IndexKind, IndexStatus,
18 LayoutRegion, ProposalConflictRecord, ProposalRecord, ProposalState, RerankDiagnostics,
19 RetrievalBackendStatus, RetrievalBudgetUsed, RetrievalHit, RetrievalMode,
20 RetrievedContextPack, ServiceDefinitionPlan, ServiceOperatorStatus, SoftwareBuildTarget,
21 SoftwareComponent, SoftwareDependencyUsage, SoftwareDesignElement, SoftwareFile,
22 SoftwareGlobalRequest, SoftwareGlobalStatus, SoftwareIacResource, SoftwareRelationship,
23 SoftwareSdkUsage, SoftwareTopic, WorkerKind, WorkerStatus, WorkerTaskRecord,
24 },
25 storage::{GraphInspection, IndexCursor, IndexRefreshDiagnostics},
26};
27
28use super::{
29 AgentProtocolStatus, ApiMetadata, CodeRepositoryFreshnessDiagnostics,
30 FileIndexFreshnessDiagnostics, RuntimeStatus,
31};
32
33pub const GRAPH_CANVAS_DEFAULT_LIMIT: usize = 250;
34pub const GRAPH_CANVAS_MAX_LIMIT: usize = 1000;
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
38#[serde(rename_all = "snake_case")]
39pub enum GraphCanvasKind {
40 Knowledge,
41 Code,
42 Mixed,
43}
44
45impl GraphCanvasKind {
46 pub fn parse(value: &str) -> Result<Self, String> {
48 match value {
49 "knowledge" => Ok(Self::Knowledge),
50 "code" => Ok(Self::Code),
51 "mixed" => Ok(Self::Mixed),
52 _ => Err(format!("unsupported graph canvas kind '{value}'")),
53 }
54 }
55
56 pub const fn as_str(self) -> &'static str {
58 match self {
59 Self::Knowledge => "knowledge",
60 Self::Code => "code",
61 Self::Mixed => "mixed",
62 }
63 }
64}
65
66#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
68pub struct GraphCanvasRequest {
69 pub kind: GraphCanvasKind,
70 #[serde(skip_serializing_if = "Option::is_none")]
71 pub source_scope: Option<String>,
72 #[serde(skip_serializing_if = "Option::is_none")]
73 pub query: Option<String>,
74 pub limit: usize,
75}
76
77#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
79pub struct GraphCanvasNode {
80 pub id: String,
81 pub kind: String,
82 pub label: String,
83 #[serde(skip_serializing_if = "Option::is_none")]
84 pub subtitle: Option<String>,
85 #[serde(skip_serializing_if = "Option::is_none")]
86 pub source_scope: Option<String>,
87 pub graph_version: u64,
88 pub weight: u32,
89 #[serde(skip_serializing_if = "Option::is_none")]
90 pub status: Option<String>,
91 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
92 pub details: BTreeMap<String, String>,
93}
94
95#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
97pub struct GraphCanvasEdge {
98 pub id: String,
99 pub kind: String,
100 pub source: String,
101 pub target: String,
102 pub label: String,
103 pub graph_version: u64,
104 #[serde(skip_serializing_if = "Option::is_none")]
105 pub confidence_basis_points: Option<u16>,
106 #[serde(skip_serializing_if = "Option::is_none")]
107 pub evidence_count: Option<usize>,
108 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
109 pub details: BTreeMap<String, String>,
110}
111
112#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
114pub struct GraphCanvasSummary {
115 pub kind: GraphCanvasKind,
116 pub node_count: usize,
117 pub edge_count: usize,
118 pub truncated: bool,
119 pub available_kinds: Vec<String>,
120}
121
122#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
124pub struct GraphCanvasResponse {
125 pub metadata: ApiMetadata,
126 pub nodes: Vec<GraphCanvasNode>,
127 pub edges: Vec<GraphCanvasEdge>,
128 pub summary: GraphCanvasSummary,
129}
130
131#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
133pub struct IngestEvidence {
134 #[serde(skip_serializing_if = "Option::is_none")]
135 pub id: Option<String>,
136 #[serde(skip_serializing_if = "Option::is_none")]
137 pub source_path: Option<String>,
138 #[serde(skip_serializing_if = "Option::is_none")]
139 pub span: Option<EvidenceSpan>,
140 #[serde(skip_serializing_if = "Option::is_none")]
141 pub confidence: Option<ConfidenceScore>,
142 #[serde(skip_serializing_if = "Option::is_none")]
143 pub status: Option<FactStatus>,
144 pub content: String,
145 #[serde(default)]
146 pub entity_labels: Vec<String>,
147 #[serde(default, skip_serializing_if = "Option::is_none")]
148 pub extraction: Option<IngestEvidenceExtraction>,
149}
150
151#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
153pub struct IngestEvidenceExtraction {
154 pub modality: EvidenceModality,
155 #[serde(skip_serializing_if = "Option::is_none")]
156 pub source_uri: Option<String>,
157 #[serde(skip_serializing_if = "Option::is_none")]
158 pub source_hash: Option<String>,
159 #[serde(skip_serializing_if = "Option::is_none")]
160 pub media_hash: Option<String>,
161 #[serde(skip_serializing_if = "Option::is_none")]
162 pub extractor: Option<String>,
163 #[serde(skip_serializing_if = "Option::is_none")]
164 pub extractor_version: Option<String>,
165 #[serde(skip_serializing_if = "Option::is_none")]
166 pub observed_at: Option<String>,
167 #[serde(skip_serializing_if = "Option::is_none")]
168 pub parent_evidence_id: Option<String>,
169 #[serde(skip_serializing_if = "Option::is_none")]
170 pub layout_region: Option<LayoutRegion>,
171 #[serde(skip_serializing_if = "Option::is_none")]
172 pub embedding_model: Option<String>,
173 #[serde(skip_serializing_if = "Option::is_none")]
174 pub embedding_dimension: Option<u16>,
175 #[serde(skip_serializing_if = "Option::is_none")]
176 pub diagnostic: Option<ExtractionDiagnostic>,
177}
178
179impl IngestEvidenceExtraction {
180 pub fn into_domain_metadata(self) -> EvidenceExtractionMetadata {
182 EvidenceExtractionMetadata {
183 modality: self.modality,
184 source_uri: self.source_uri,
185 source_hash: self.source_hash,
186 media_hash: self.media_hash,
187 extractor: self.extractor,
188 extractor_version: self.extractor_version,
189 observed_at: self.observed_at,
190 parent_evidence_id: self.parent_evidence_id,
191 layout_region: self.layout_region,
192 embedding_model: self.embedding_model,
193 embedding_dimension: self.embedding_dimension,
194 diagnostic: self
195 .diagnostic
196 .unwrap_or_else(|| EvidenceExtractionMetadata::text_span().diagnostic),
197 }
198 }
199}
200
201#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
203pub struct IngestRelation {
204 pub id: String,
205 pub source_entity_label: String,
206 pub relation_type: String,
207 pub target_entity_label: String,
208 #[serde(default)]
209 pub evidence_ids: Vec<String>,
210 #[serde(skip_serializing_if = "Option::is_none")]
211 pub confidence: Option<ConfidenceScore>,
212 #[serde(skip_serializing_if = "Option::is_none")]
213 pub status: Option<FactStatus>,
214 #[serde(skip_serializing_if = "Option::is_none")]
215 pub version_range: Option<GraphVersionRange>,
216}
217
218#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
220pub struct IngestClaim {
221 pub id: String,
222 pub subject_entity_label: String,
223 pub predicate: String,
224 pub object: String,
225 #[serde(default)]
226 pub evidence_ids: Vec<String>,
227 #[serde(skip_serializing_if = "Option::is_none")]
228 pub confidence: Option<ConfidenceScore>,
229 #[serde(skip_serializing_if = "Option::is_none")]
230 pub status: Option<FactStatus>,
231 #[serde(skip_serializing_if = "Option::is_none")]
232 pub version_range: Option<GraphVersionRange>,
233}
234
235#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
237pub struct IngestEvent {
238 pub id: String,
239 pub event_type: String,
240 #[serde(default)]
241 pub entity_labels: Vec<String>,
242 #[serde(skip_serializing_if = "Option::is_none")]
243 pub occurred_at: Option<String>,
244 #[serde(default)]
245 pub evidence_ids: Vec<String>,
246 #[serde(skip_serializing_if = "Option::is_none")]
247 pub confidence: Option<ConfidenceScore>,
248 #[serde(skip_serializing_if = "Option::is_none")]
249 pub status: Option<FactStatus>,
250 #[serde(skip_serializing_if = "Option::is_none")]
251 pub version_range: Option<GraphVersionRange>,
252}
253
254#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
256pub struct IngestRequest {
257 pub source_scope: String,
258 #[serde(default)]
259 pub evidence: Vec<IngestEvidence>,
260 #[serde(default)]
261 pub relations: Vec<IngestRelation>,
262 #[serde(default)]
263 pub claims: Vec<IngestClaim>,
264 #[serde(default)]
265 pub events: Vec<IngestEvent>,
266}
267
268#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
270pub struct IngestResponse {
271 pub metadata: ApiMetadata,
272 pub receipt: CommitReceipt,
273 pub indexes: Vec<IndexStatus>,
274 #[serde(skip_serializing_if = "Option::is_none")]
275 pub index_refresh_error: Option<String>,
276}
277
278#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
280pub struct MultimodalExtractionRequest {
281 pub source_scope: String,
282 pub parent_evidence_id: String,
283 pub derived_evidence: Vec<IngestEvidence>,
284}
285
286#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
288pub struct MultimodalExtractionResponse {
289 pub metadata: ApiMetadata,
290 pub parent_evidence_id: String,
291 pub derived_evidence_count: usize,
292 pub receipt: CommitReceipt,
293 pub indexes: Vec<IndexStatus>,
294 #[serde(skip_serializing_if = "Option::is_none")]
295 pub index_refresh_error: Option<String>,
296}
297
298#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
300pub struct HybridRetrievalRequest {
301 pub query: String,
302 #[serde(skip_serializing_if = "Option::is_none")]
303 pub source_scope: Option<String>,
304 pub limit: usize,
305 pub freshness: FreshnessPolicy,
306}
307
308impl HybridRetrievalRequest {
309 pub fn new(query: impl Into<String>) -> Self {
311 Self {
312 query: query.into(),
313 source_scope: None,
314 limit: 10,
315 freshness: FreshnessPolicy::default(),
316 }
317 }
318}
319
320#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
322pub struct HybridRetrievalResponse {
323 pub metadata: ApiMetadata,
324 pub context_pack: RetrievedContextPack,
325 pub retrieval_mode: RetrievalMode,
326 #[serde(skip_serializing_if = "Option::is_none")]
327 pub source_scope: Option<String>,
328 pub freshness: FreshnessPolicy,
329 pub results: Vec<RetrievalHit>,
330 pub fusion: FusionDiagnostics,
331 pub rerank: RerankDiagnostics,
332 #[serde(default, skip_serializing_if = "Vec::is_empty")]
333 pub backend_statuses: Vec<RetrievalBackendStatus>,
334 pub truncated: bool,
335 pub budget_used: RetrievalBudgetUsed,
336 #[serde(skip_serializing_if = "Option::is_none")]
337 pub degraded_reason: Option<String>,
338 pub indexes: Vec<IndexStatus>,
339 #[serde(default)]
340 pub index_cursors: Vec<IndexCursor>,
341 #[serde(default)]
342 pub index_refresh: IndexRefreshDiagnostics,
343}
344
345#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
347pub struct GraphInspectionRequest {
348 #[serde(skip_serializing_if = "Option::is_none")]
349 pub source_scope: Option<String>,
350}
351
352#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
354pub struct GraphInspectionResponse {
355 pub metadata: ApiMetadata,
356 pub graph: GraphInspection,
357 pub repository_code_totals: CodeRepositoryTotals,
358}
359
360#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
362pub struct IndexRefreshRequest {
363 #[serde(default)]
364 pub kinds: Vec<IndexKind>,
365}
366
367#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
369pub struct IndexRefreshResponse {
370 pub metadata: ApiMetadata,
371 pub indexes: Vec<IndexStatus>,
372 pub index_cursors: Vec<IndexCursor>,
373 pub diagnostics: IndexRefreshDiagnostics,
374}
375
376#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
378pub struct FileIndexRequest {
379 #[serde(skip_serializing_if = "Option::is_none")]
380 pub source_scope: Option<String>,
381 #[serde(default)]
382 pub roots: Vec<String>,
383}
384
385#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
387pub struct FileIndexResponse {
388 pub metadata: ApiMetadata,
389 pub summary: crate::storage::FileIndexScanSummary,
390}
391
392#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
394pub struct FileQueryRequest {
395 pub query: String,
396 #[serde(skip_serializing_if = "Option::is_none")]
397 pub source_scope: Option<String>,
398 #[serde(skip_serializing_if = "Option::is_none")]
399 pub root_id: Option<String>,
400 pub limit: usize,
401 #[serde(default)]
402 pub freshness_policy: FreshnessPolicy,
403}
404
405#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
407pub struct FileQueryResponse {
408 pub metadata: ApiMetadata,
409 pub query: String,
410 #[serde(skip_serializing_if = "Option::is_none")]
411 pub source_scope: Option<String>,
412 #[serde(skip_serializing_if = "Option::is_none")]
413 pub root_id: Option<String>,
414 #[serde(default = "FileIndexFreshnessDiagnostics::legacy_unknown")]
415 pub freshness: FileIndexFreshnessDiagnostics,
416 pub results: Vec<crate::storage::FileSearchHit>,
417 pub truncated: bool,
418 pub duration_ms: u64,
419 #[serde(skip_serializing_if = "Option::is_none")]
420 pub degraded_reason: Option<String>,
421}
422
423#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
425pub struct ServiceStatusResponse {
426 pub metadata: ApiMetadata,
427 pub service_name: String,
428 pub mode: String,
429 pub background_enabled: bool,
430 pub silent_updates_enabled: bool,
431 pub service_definition_path: String,
432 pub storage: StorageTopologyDiagnostics,
433 pub index_refresh: IndexRefreshDiagnostics,
434 pub file_index: crate::storage::FileIndexDiagnostics,
435 pub agent_protocols: AgentProtocolStatus,
436 pub operator: ServiceOperatorStatus,
437 pub workers: Vec<WorkerStatus>,
438 pub code_index_workers: CodeIndexWorkerStatus,
439 pub proposal_backlog: usize,
440 pub audit_sink: AuditSinkStatus,
441 #[serde(default = "super::watcher_diagnostics::WatcherDiagnostics::default_disabled")]
442 pub watcher: super::watcher_diagnostics::WatcherDiagnostics,
443}
444
445#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
447pub struct StorageTopologyDiagnostics {
448 pub topology: String,
449 pub control_database_path: String,
450 #[serde(skip_serializing_if = "Option::is_none")]
451 pub repository_shards_dir: Option<String>,
452 pub shard_catalog_active: bool,
453 pub active_shard_count: usize,
454 pub staged_shard_count: usize,
455 pub missing_shard_count: usize,
456 pub runtime_state_paths: Vec<String>,
457 pub shards: Vec<StorageShardDiagnostics>,
458 #[serde(skip_serializing_if = "Option::is_none")]
459 pub degraded_reason: Option<String>,
460}
461
462#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
464pub struct StorageShardDiagnostics {
465 pub repository_id: String,
466 pub state: String,
467 pub shard_locator: String,
468 pub resolved_path: String,
469 pub source_scope_count: usize,
470 pub exists: bool,
471 pub updated_at_ms: u64,
472 #[serde(skip_serializing_if = "Option::is_none")]
473 pub degraded_reason: Option<String>,
474}
475
476#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
478pub struct StorageTopologyResponse {
479 pub metadata: ApiMetadata,
480 pub storage: StorageTopologyDiagnostics,
481}
482
483#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
485pub struct CodeIndexWorkerStatus {
486 pub configured_worker_count: usize,
487 pub active_worker_slots: usize,
488 pub queue_depth: usize,
489 pub queued_task_count: usize,
490 pub running_task_count: usize,
491 pub retrying_task_count: usize,
492 pub dead_letter_task_count: usize,
493 pub running_lease_count: usize,
494 #[serde(skip_serializing_if = "Option::is_none")]
495 pub last_error: Option<String>,
496}
497
498impl CodeIndexWorkerStatus {
499 pub fn from_queue(configured_worker_count: usize, queue: CodeIndexTaskQueueStatus) -> Self {
501 let queue_depth = queue
502 .queued_task_count
503 .saturating_add(queue.retrying_task_count);
504
505 Self {
506 configured_worker_count,
507 active_worker_slots: configured_worker_count.saturating_sub(queue.running_task_count),
508 queue_depth,
509 queued_task_count: queue.queued_task_count,
510 running_task_count: queue.running_task_count,
511 retrying_task_count: queue.retrying_task_count,
512 dead_letter_task_count: queue.dead_letter_task_count,
513 running_lease_count: queue.running_lease_count,
514 last_error: queue.last_error,
515 }
516 }
517}
518
519#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
521pub struct AuditSinkStatus {
522 pub durable: bool,
523 pub event_count: usize,
524 #[serde(skip_serializing_if = "Option::is_none")]
525 pub last_error: Option<String>,
526}
527
528#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
530pub struct WorkerStatusRequest {
531 #[serde(skip_serializing_if = "Option::is_none")]
532 pub kind: Option<WorkerKind>,
533}
534
535#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
537pub struct WorkerStatusResponse {
538 pub metadata: ApiMetadata,
539 pub workers: Vec<WorkerStatus>,
540}
541
542#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
544pub struct WorkerRunRequest {
545 #[serde(skip_serializing_if = "Option::is_none")]
546 pub kind: Option<WorkerKind>,
547}
548
549#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
551pub struct WorkerRunResponse {
552 pub metadata: ApiMetadata,
553 #[serde(skip_serializing_if = "Option::is_none")]
554 pub task: Option<WorkerTaskRecord>,
555 #[serde(default)]
556 pub proposals: Vec<ProposalRecord>,
557 pub workers: Vec<WorkerStatus>,
558 #[serde(skip_serializing_if = "Option::is_none")]
559 pub degraded_reason: Option<String>,
560}
561
562#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
564pub struct CodeIndexWorkerRunRequest {
565 #[serde(skip_serializing_if = "Option::is_none")]
566 pub task_id: Option<String>,
567}
568
569#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
571pub struct CodeIndexWorkerRunResponse {
572 pub metadata: ApiMetadata,
573 pub worker_kind: String,
574 pub claimed: bool,
575 #[serde(skip_serializing_if = "Option::is_none")]
576 pub task: Option<CodeIndexTaskRecord>,
577}
578
579#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
581pub struct ProposalListApiRequest {
582 #[serde(skip_serializing_if = "Option::is_none")]
583 pub state: Option<ProposalState>,
584 pub limit: usize,
585}
586
587#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
589pub struct ProposalListResponse {
590 pub metadata: ApiMetadata,
591 pub proposals: Vec<ProposalRecord>,
592}
593
594#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
596pub struct ProposalShowResponse {
597 pub metadata: ApiMetadata,
598 pub proposal: ProposalRecord,
599 pub conflicts: Vec<ProposalConflictRecord>,
600 pub payload: serde_json::Value,
601}
602
603#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
605pub struct ProposalDecisionApiRequest {
606 pub actor: String,
607 #[serde(skip_serializing_if = "Option::is_none")]
608 pub reason: Option<String>,
609}
610
611#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
613pub struct ProposalDecisionResponse {
614 pub metadata: ApiMetadata,
615 pub proposal: ProposalRecord,
616 #[serde(skip_serializing_if = "Option::is_none")]
617 pub receipt: Option<CommitReceipt>,
618 #[serde(skip_serializing_if = "Option::is_none")]
619 pub index_refresh_error: Option<String>,
620}
621
622#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
624pub struct AuditQueryApiRequest {
625 #[serde(skip_serializing_if = "Option::is_none")]
626 pub operation: Option<String>,
627 pub limit: usize,
628}
629
630#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
632pub struct AuditQueryResponse {
633 pub metadata: ApiMetadata,
634 pub events: Vec<crate::domain::AuditEventRecord>,
635}
636
637#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
639pub struct ServiceDefinitionWriteResponse {
640 pub metadata: ApiMetadata,
641 pub plan: ServiceDefinitionPlan,
642 pub written: bool,
643}
644
645#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
647pub struct ServiceOperatorResponse {
648 pub metadata: ApiMetadata,
649 pub operator: ServiceOperatorStatus,
650}
651
652#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
654pub struct ServiceRecoveryReport {
655 pub metadata: ApiMetadata,
656 pub graph_version: u64,
657 pub stale_index_kinds: Vec<IndexKind>,
658 pub refreshed_index_kinds: Vec<IndexKind>,
659 pub index_lag_max: u64,
660 pub task_queue_depth: usize,
661 pub dead_letter_count: usize,
662 pub heartbeat_state: String,
663}
664
665#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
667pub struct HealthResponse {
668 pub metadata: ApiMetadata,
669 pub healthy: bool,
670 #[serde(skip_serializing_if = "Option::is_none")]
671 pub degraded_reason: Option<String>,
672 pub storage: StorageTopologyDiagnostics,
673 pub graph: GraphInspection,
674 pub repository_code_totals: CodeRepositoryTotals,
675 pub indexes: Vec<IndexStatus>,
676 pub index_cursors: Vec<IndexCursor>,
677 pub index_refresh: IndexRefreshDiagnostics,
678 pub file_index: crate::storage::FileIndexDiagnostics,
679 pub runtime: RuntimeStatus,
680}
681
682#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
684pub struct EmbeddingProviderProbeResponse {
685 pub metadata: ApiMetadata,
686 pub ok: bool,
687 pub provider: Option<String>,
688 pub model: String,
689 pub dimension: u32,
690 #[serde(skip_serializing_if = "Option::is_none")]
691 pub latency_ms: Option<u64>,
692 #[serde(skip_serializing_if = "Option::is_none")]
693 pub error_code: Option<String>,
694 #[serde(skip_serializing_if = "Option::is_none")]
695 pub error_message: Option<String>,
696 #[serde(skip_serializing_if = "Option::is_none")]
697 pub retryable: Option<bool>,
698}
699
700#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
702pub struct CodeRepositoryRegisterRequest {
703 pub root_path: String,
704 #[serde(default)]
705 pub alias: String,
706 #[serde(default)]
707 pub path_filters: Vec<String>,
708 #[serde(default)]
709 pub language_filters: Vec<String>,
710}
711
712#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
714pub struct CodeRepositoryRegisterResponse {
715 pub metadata: ApiMetadata,
716 pub registration: CodeRepositoryRegistration,
717 pub status: CodeRepositoryStatus,
718}
719
720#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
722pub struct CodeRepositoryRemoveResponse {
723 pub metadata: ApiMetadata,
724 pub removed_status: CodeRepositoryStatus,
725 pub summary: CodeRepositoryRemovalSummary,
726}
727
728#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
730pub struct CodeRepositoryIndexResponse {
731 pub metadata: ApiMetadata,
732 pub scope: CodeRepositoryScopeMetadata,
733 pub summary: CodeIndexSummary,
734 pub status: CodeRepositoryStatus,
735}
736
737#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
739pub struct CodeRepositoryIndexStartResponse {
740 pub metadata: ApiMetadata,
741 pub scope: CodeRepositoryScopeMetadata,
742 #[serde(skip_serializing_if = "Option::is_none")]
743 pub summary: Option<CodeIndexSummary>,
744 pub status: CodeRepositoryStatus,
745 #[serde(skip_serializing_if = "Option::is_none")]
746 pub task: Option<CodeIndexTaskRecord>,
747 #[serde(skip_serializing_if = "Option::is_none")]
748 pub checkpoint: Option<CodeIndexCheckpoint>,
749}
750
751#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
753pub struct CodeRepositoryIndexResetResponse {
754 pub metadata: ApiMetadata,
755 pub status: CodeRepositoryStatus,
756 pub reset_task_count: usize,
757 pub reset_tasks: Vec<CodeIndexTaskRecord>,
758 #[serde(skip_serializing_if = "Option::is_none")]
759 pub active_task: Option<CodeIndexTaskRecord>,
760 #[serde(skip_serializing_if = "Option::is_none")]
761 pub checkpoint: Option<CodeIndexCheckpoint>,
762 pub retention: CodeScopeRetentionSummary,
763}
764
765#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
767pub struct CodeRepositoryScopePreviewResponse {
768 pub metadata: ApiMetadata,
769 pub scope: CodeRepositoryScopeMetadata,
770 pub preview: CodeRepositoryScopePreview,
771}
772
773#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
775pub struct CodeRepositoryScopeMetadata {
776 pub scope_id: String,
777 pub repository_id: String,
778 pub alias: String,
779 pub requested_ref: String,
780 pub resolved_commit_sha: String,
781 pub tree_hash: String,
782 pub path_filters: Vec<String>,
783 pub language_filters: Vec<String>,
784 pub index_versions: Vec<String>,
785 pub stale: bool,
786}
787
788impl CodeRepositoryScopeMetadata {
789 pub fn from_status(
791 status: &CodeRepositoryStatus,
792 selector: &CodeRepositorySelector,
793 requested_ref: impl Into<String>,
794 ) -> Self {
795 Self {
796 scope_id: status.last_indexed_scope_id.clone().unwrap_or_default(),
797 repository_id: status.repository_id.clone(),
798 alias: status.alias.clone(),
799 requested_ref: requested_ref.into(),
800 resolved_commit_sha: status.last_indexed_commit.clone().unwrap_or_default(),
801 tree_hash: status.tree_hash.clone().unwrap_or_default(),
802 path_filters: merged_filters(&status.path_filters, &selector.path_filters),
803 language_filters: merged_filters(&status.language_filters, &selector.language_filters),
804 index_versions: vec![format!(
805 "code:{}:{}",
806 status
807 .last_indexed_scope_id
808 .as_deref()
809 .unwrap_or("unscoped"),
810 status.tree_hash.as_deref().unwrap_or("unindexed")
811 )],
812 stale: status.stale,
813 }
814 }
815
816 pub fn from_index_task(task: &CodeIndexTaskRecord, requested_ref: impl Into<String>) -> Self {
818 Self {
819 scope_id: task.source_scope.clone(),
820 repository_id: task.repository_id.clone(),
821 alias: task.alias.clone(),
822 requested_ref: requested_ref.into(),
823 resolved_commit_sha: task.resolved_commit_sha.clone(),
824 tree_hash: task.tree_hash.clone(),
825 path_filters: task.path_filters.clone(),
826 language_filters: task.language_filters.clone(),
827 index_versions: vec![format!("code:{}:{}", task.source_scope, task.tree_hash)],
828 stale: true,
829 }
830 }
831}
832
833#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
835pub struct CodeRepositoryQueryResponse {
836 pub metadata: ApiMetadata,
837 pub scope: CodeRepositoryScopeMetadata,
838 #[serde(default = "CodeRepositoryFreshnessDiagnostics::legacy_unknown")]
839 pub freshness: CodeRepositoryFreshnessDiagnostics,
840 pub request: CodeRetrievalRequest,
841 pub results: Vec<CodeRetrievalHit>,
842 #[serde(skip_serializing_if = "Option::is_none")]
843 pub degraded_reason: Option<String>,
844}
845
846#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
848pub struct CodeRepositoryFeatureFlagsResponse {
849 pub metadata: ApiMetadata,
850 pub scope: CodeRepositoryScopeMetadata,
851 #[serde(default = "CodeRepositoryFreshnessDiagnostics::legacy_unknown")]
852 pub freshness: CodeRepositoryFreshnessDiagnostics,
853 pub request: CodeFeatureFlagRequest,
854 pub flags: Vec<CodeFeatureFlagGraph>,
855 #[serde(skip_serializing_if = "Option::is_none")]
856 pub degraded_reason: Option<String>,
857}
858
859#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
861pub struct CodeRepositoryImpactResponse {
862 pub metadata: ApiMetadata,
863 pub scope: CodeRepositoryScopeMetadata,
864 pub request: CodeImpactRequest,
865 pub path_groups: CodeImpactPathGroups,
866 pub results: Vec<CodeRetrievalHit>,
867}
868
869#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
871pub struct CodeRepositoryStatusResponse {
872 pub metadata: ApiMetadata,
873 pub status: CodeRepositoryStatus,
874 #[serde(skip_serializing_if = "Option::is_none")]
875 pub active_task: Option<CodeIndexTaskRecord>,
876 #[serde(skip_serializing_if = "Option::is_none")]
877 pub checkpoint: Option<CodeIndexCheckpoint>,
878 pub retention: CodeScopeRetentionSummary,
879}
880
881#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
883pub struct CodeRepositoryReportResponse {
884 pub metadata: ApiMetadata,
885 pub scope: CodeRepositoryScopeMetadata,
886 pub report: CodeRepositoryReport,
887}
888
889#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
891pub struct SoftwareGlobalResponse {
892 pub metadata: ApiMetadata,
893 pub scope: CodeRepositoryScopeMetadata,
894 pub request: SoftwareGlobalRequest,
895 pub status: SoftwareGlobalStatus,
896 pub components: Vec<SoftwareComponent>,
897 pub dependency_usages: Vec<SoftwareDependencyUsage>,
898 pub sdk_usages: Vec<SoftwareSdkUsage>,
899 pub files: Vec<SoftwareFile>,
900 pub topics: Vec<SoftwareTopic>,
901 pub relationships: Vec<SoftwareRelationship>,
902 pub build_targets: Vec<SoftwareBuildTarget>,
903 pub iac_resources: Vec<SoftwareIacResource>,
904 pub design_elements: Vec<SoftwareDesignElement>,
905}
906
907#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
909pub struct CodeRepositorySetCreateResponse {
910 pub metadata: ApiMetadata,
911 pub request: CodeRepositorySetCreateRequest,
912 pub repository_set: CodeRepositorySet,
913}
914
915#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
917pub struct CodeRepositorySetAddResponse {
918 pub metadata: ApiMetadata,
919 pub request: CodeRepositorySetAddMemberRequest,
920 pub member: CodeRepositorySetMember,
921 pub status: CodeRepositorySetStatus,
922}
923
924#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
926pub struct CodeRepositorySetRemoveResponse {
927 pub metadata: ApiMetadata,
928 pub request: CodeRepositorySetRemoveMemberRequest,
929 pub member: CodeRepositorySetMember,
930 pub status: CodeRepositorySetStatus,
931}
932
933#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
935pub struct CodeRepositorySetQueryResponse {
936 pub metadata: ApiMetadata,
937 pub request: CodeRepositorySetQueryRequest,
938 pub status: CodeRepositorySetStatus,
939 pub results: Vec<CodeRepositorySetQueryHit>,
940 pub truncated: bool,
941 #[serde(skip_serializing_if = "Option::is_none")]
942 pub degraded_reason: Option<String>,
943}
944
945#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
947pub struct CodeRepositorySetStatusResponse {
948 pub metadata: ApiMetadata,
949 pub status: CodeRepositorySetStatus,
950}
951
952#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
954pub struct CodeRepositorySetRefreshResponse {
955 pub metadata: ApiMetadata,
956 pub status: CodeRepositorySetStatus,
957 #[serde(skip_serializing_if = "Option::is_none")]
958 pub summary: Option<CodeRepositorySetRefreshSummary>,
959 #[serde(skip_serializing_if = "Option::is_none")]
960 pub task: Option<CodeRepositorySetRefreshTaskRecord>,
961}
962
963fn merged_filters(base: &[String], request: &[String]) -> Vec<String> {
964 let mut merged = Vec::new();
965 for value in base.iter().chain(request.iter()) {
966 if !merged.contains(value) {
967 merged.push(value.clone());
968 }
969 }
970
971 merged
972}