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::{AgentProtocolStatus, ApiMetadata, CodeRepositoryFreshnessDiagnostics, 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 #[serde(default)]
337 pub index_cursors: Vec<IndexCursor>,
338 #[serde(default)]
339 pub index_refresh: IndexRefreshDiagnostics,
340}
341
342#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
344pub struct GraphInspectionRequest {
345 #[serde(skip_serializing_if = "Option::is_none")]
346 pub source_scope: Option<String>,
347}
348
349#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
351pub struct GraphInspectionResponse {
352 pub metadata: ApiMetadata,
353 pub graph: GraphInspection,
354 pub repository_code_totals: CodeRepositoryTotals,
355}
356
357#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
359pub struct IndexRefreshRequest {
360 #[serde(default)]
361 pub kinds: Vec<IndexKind>,
362}
363
364#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
366pub struct IndexRefreshResponse {
367 pub metadata: ApiMetadata,
368 pub indexes: Vec<IndexStatus>,
369 pub index_cursors: Vec<IndexCursor>,
370 pub diagnostics: IndexRefreshDiagnostics,
371}
372
373#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
375pub struct ServiceStatusResponse {
376 pub metadata: ApiMetadata,
377 pub service_name: String,
378 pub mode: String,
379 pub background_enabled: bool,
380 pub silent_updates_enabled: bool,
381 pub service_definition_path: String,
382 pub storage: StorageTopologyDiagnostics,
383 pub index_refresh: IndexRefreshDiagnostics,
384 pub file_index: crate::storage::FileIndexDiagnostics,
385 pub agent_protocols: AgentProtocolStatus,
386 pub operator: ServiceOperatorStatus,
387 pub workers: Vec<WorkerStatus>,
388 pub code_index_workers: CodeIndexWorkerStatus,
389 pub proposal_backlog: usize,
390 pub audit_sink: AuditSinkStatus,
391 #[serde(default = "super::watcher_diagnostics::WatcherDiagnostics::default_disabled")]
392 pub watcher: super::watcher_diagnostics::WatcherDiagnostics,
393}
394
395#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
397pub struct StorageTopologyDiagnostics {
398 pub topology: String,
399 pub control_database_path: String,
400 #[serde(skip_serializing_if = "Option::is_none")]
401 pub repository_shards_dir: Option<String>,
402 pub shard_catalog_active: bool,
403 pub active_shard_count: usize,
404 pub staged_shard_count: usize,
405 pub missing_shard_count: usize,
406 pub runtime_state_paths: Vec<String>,
407 pub shards: Vec<StorageShardDiagnostics>,
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 StorageShardDiagnostics {
415 pub repository_id: String,
416 pub state: String,
417 pub shard_locator: String,
418 pub resolved_path: String,
419 pub source_scope_count: usize,
420 pub exists: bool,
421 pub updated_at_ms: u64,
422 #[serde(skip_serializing_if = "Option::is_none")]
423 pub degraded_reason: Option<String>,
424}
425
426#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
428pub struct StorageTopologyResponse {
429 pub metadata: ApiMetadata,
430 pub storage: StorageTopologyDiagnostics,
431}
432
433#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
435pub struct CodeIndexWorkerStatus {
436 pub configured_worker_count: usize,
437 pub active_worker_slots: usize,
438 pub queue_depth: usize,
439 pub queued_task_count: usize,
440 pub running_task_count: usize,
441 pub retrying_task_count: usize,
442 pub dead_letter_task_count: usize,
443 pub running_lease_count: usize,
444 #[serde(skip_serializing_if = "Option::is_none")]
445 pub last_error: Option<String>,
446}
447
448impl CodeIndexWorkerStatus {
449 pub fn from_queue(configured_worker_count: usize, queue: CodeIndexTaskQueueStatus) -> Self {
451 let queue_depth = queue
452 .queued_task_count
453 .saturating_add(queue.retrying_task_count);
454
455 Self {
456 configured_worker_count,
457 active_worker_slots: configured_worker_count.saturating_sub(queue.running_task_count),
458 queue_depth,
459 queued_task_count: queue.queued_task_count,
460 running_task_count: queue.running_task_count,
461 retrying_task_count: queue.retrying_task_count,
462 dead_letter_task_count: queue.dead_letter_task_count,
463 running_lease_count: queue.running_lease_count,
464 last_error: queue.last_error,
465 }
466 }
467}
468
469#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
471pub struct AuditSinkStatus {
472 pub durable: bool,
473 pub event_count: usize,
474 #[serde(skip_serializing_if = "Option::is_none")]
475 pub last_error: Option<String>,
476}
477
478#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
480pub struct WorkerStatusRequest {
481 #[serde(skip_serializing_if = "Option::is_none")]
482 pub kind: Option<WorkerKind>,
483}
484
485#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
487pub struct WorkerStatusResponse {
488 pub metadata: ApiMetadata,
489 pub workers: Vec<WorkerStatus>,
490}
491
492#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
494pub struct WorkerRunRequest {
495 #[serde(skip_serializing_if = "Option::is_none")]
496 pub kind: Option<WorkerKind>,
497}
498
499#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
501pub struct WorkerRunResponse {
502 pub metadata: ApiMetadata,
503 #[serde(skip_serializing_if = "Option::is_none")]
504 pub task: Option<WorkerTaskRecord>,
505 #[serde(default)]
506 pub proposals: Vec<ProposalRecord>,
507 pub workers: Vec<WorkerStatus>,
508 #[serde(skip_serializing_if = "Option::is_none")]
509 pub degraded_reason: Option<String>,
510}
511
512#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
514pub struct CodeIndexWorkerRunRequest {
515 #[serde(skip_serializing_if = "Option::is_none")]
516 pub task_id: Option<String>,
517}
518
519#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
521pub struct CodeIndexWorkerRunResponse {
522 pub metadata: ApiMetadata,
523 pub worker_kind: String,
524 pub claimed: bool,
525 #[serde(skip_serializing_if = "Option::is_none")]
526 pub task: Option<CodeIndexTaskRecord>,
527}
528
529#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
531pub struct ProposalListApiRequest {
532 #[serde(skip_serializing_if = "Option::is_none")]
533 pub state: Option<ProposalState>,
534 pub limit: usize,
535}
536
537#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
539pub struct ProposalListResponse {
540 pub metadata: ApiMetadata,
541 pub proposals: Vec<ProposalRecord>,
542}
543
544#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
546pub struct ProposalShowResponse {
547 pub metadata: ApiMetadata,
548 pub proposal: ProposalRecord,
549 pub conflicts: Vec<ProposalConflictRecord>,
550 pub payload: serde_json::Value,
551}
552
553#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
555pub struct ProposalDecisionApiRequest {
556 pub actor: String,
557 #[serde(skip_serializing_if = "Option::is_none")]
558 pub reason: Option<String>,
559}
560
561#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
563pub struct ProposalDecisionResponse {
564 pub metadata: ApiMetadata,
565 pub proposal: ProposalRecord,
566 #[serde(skip_serializing_if = "Option::is_none")]
567 pub receipt: Option<CommitReceipt>,
568 #[serde(skip_serializing_if = "Option::is_none")]
569 pub index_refresh_error: Option<String>,
570}
571
572#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
574pub struct AuditQueryApiRequest {
575 #[serde(skip_serializing_if = "Option::is_none")]
576 pub operation: Option<String>,
577 pub limit: usize,
578}
579
580#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
582pub struct AuditQueryResponse {
583 pub metadata: ApiMetadata,
584 pub events: Vec<crate::domain::AuditEventRecord>,
585}
586
587#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
589pub struct ServiceDefinitionWriteResponse {
590 pub metadata: ApiMetadata,
591 pub plan: ServiceDefinitionPlan,
592 pub written: bool,
593}
594
595#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
597pub struct ServiceOperatorResponse {
598 pub metadata: ApiMetadata,
599 pub operator: ServiceOperatorStatus,
600}
601
602#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
604pub struct ServiceRecoveryReport {
605 pub metadata: ApiMetadata,
606 pub graph_version: u64,
607 pub stale_index_kinds: Vec<IndexKind>,
608 pub refreshed_index_kinds: Vec<IndexKind>,
609 pub index_lag_max: u64,
610 pub task_queue_depth: usize,
611 pub dead_letter_count: usize,
612 pub heartbeat_state: String,
613}
614
615#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
617pub struct HealthResponse {
618 pub metadata: ApiMetadata,
619 pub healthy: bool,
620 #[serde(skip_serializing_if = "Option::is_none")]
621 pub degraded_reason: Option<String>,
622 pub storage: StorageTopologyDiagnostics,
623 pub graph: GraphInspection,
624 pub repository_code_totals: CodeRepositoryTotals,
625 pub indexes: Vec<IndexStatus>,
626 pub index_cursors: Vec<IndexCursor>,
627 pub index_refresh: IndexRefreshDiagnostics,
628 pub file_index: crate::storage::FileIndexDiagnostics,
629 pub runtime: RuntimeStatus,
630}
631
632#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
634pub struct EmbeddingProviderProbeResponse {
635 pub metadata: ApiMetadata,
636 pub ok: bool,
637 pub provider: Option<String>,
638 pub model: String,
639 pub dimension: u32,
640 #[serde(skip_serializing_if = "Option::is_none")]
641 pub latency_ms: Option<u64>,
642 #[serde(skip_serializing_if = "Option::is_none")]
643 pub error_code: Option<String>,
644 #[serde(skip_serializing_if = "Option::is_none")]
645 pub error_message: Option<String>,
646 #[serde(skip_serializing_if = "Option::is_none")]
647 pub retryable: Option<bool>,
648}
649
650#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
652pub struct CodeRepositoryRegisterRequest {
653 pub root_path: String,
654 #[serde(default)]
655 pub alias: String,
656 #[serde(default)]
657 pub path_filters: Vec<String>,
658 #[serde(default)]
659 pub language_filters: Vec<String>,
660}
661
662#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
664pub struct CodeRepositoryRegisterResponse {
665 pub metadata: ApiMetadata,
666 pub registration: CodeRepositoryRegistration,
667 pub status: CodeRepositoryStatus,
668}
669
670#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
672pub struct CodeRepositoryRemoveResponse {
673 pub metadata: ApiMetadata,
674 pub removed_status: CodeRepositoryStatus,
675 pub summary: CodeRepositoryRemovalSummary,
676}
677
678#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
680pub struct CodeRepositoryIndexResponse {
681 pub metadata: ApiMetadata,
682 pub scope: CodeRepositoryScopeMetadata,
683 pub summary: CodeIndexSummary,
684 pub status: CodeRepositoryStatus,
685}
686
687#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
689pub struct CodeRepositoryIndexStartResponse {
690 pub metadata: ApiMetadata,
691 pub scope: CodeRepositoryScopeMetadata,
692 #[serde(skip_serializing_if = "Option::is_none")]
693 pub summary: Option<CodeIndexSummary>,
694 pub status: CodeRepositoryStatus,
695 #[serde(skip_serializing_if = "Option::is_none")]
696 pub task: Option<CodeIndexTaskRecord>,
697 #[serde(skip_serializing_if = "Option::is_none")]
698 pub checkpoint: Option<CodeIndexCheckpoint>,
699}
700
701#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
703pub struct CodeRepositoryIndexResetResponse {
704 pub metadata: ApiMetadata,
705 pub status: CodeRepositoryStatus,
706 pub reset_task_count: usize,
707 pub reset_tasks: Vec<CodeIndexTaskRecord>,
708 #[serde(skip_serializing_if = "Option::is_none")]
709 pub active_task: Option<CodeIndexTaskRecord>,
710 #[serde(skip_serializing_if = "Option::is_none")]
711 pub checkpoint: Option<CodeIndexCheckpoint>,
712 pub retention: CodeScopeRetentionSummary,
713}
714
715#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
717pub struct CodeRepositoryScopePreviewResponse {
718 pub metadata: ApiMetadata,
719 pub scope: CodeRepositoryScopeMetadata,
720 pub preview: CodeRepositoryScopePreview,
721}
722
723#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
725pub struct CodeRepositoryScopeMetadata {
726 pub scope_id: String,
727 pub repository_id: String,
728 pub alias: String,
729 pub requested_ref: String,
730 pub resolved_commit_sha: String,
731 pub tree_hash: String,
732 pub path_filters: Vec<String>,
733 pub language_filters: Vec<String>,
734 #[serde(default)]
735 pub indexed_file_count: usize,
736 pub index_versions: Vec<String>,
737 pub stale: bool,
738}
739
740impl CodeRepositoryScopeMetadata {
741 pub fn from_status(
743 status: &CodeRepositoryStatus,
744 selector: &CodeRepositorySelector,
745 requested_ref: impl Into<String>,
746 ) -> Self {
747 Self {
748 scope_id: status.last_indexed_scope_id.clone().unwrap_or_default(),
749 repository_id: status.repository_id.clone(),
750 alias: status.alias.clone(),
751 requested_ref: requested_ref.into(),
752 resolved_commit_sha: status.last_indexed_commit.clone().unwrap_or_default(),
753 tree_hash: status.tree_hash.clone().unwrap_or_default(),
754 path_filters: merged_filters(&status.path_filters, &selector.path_filters),
755 language_filters: merged_filters(&status.language_filters, &selector.language_filters),
756 indexed_file_count: status.indexed_file_count,
757 index_versions: vec![format!(
758 "code:{}:{}",
759 status
760 .last_indexed_scope_id
761 .as_deref()
762 .unwrap_or("unscoped"),
763 status.tree_hash.as_deref().unwrap_or("unindexed")
764 )],
765 stale: status.stale,
766 }
767 }
768
769 pub fn from_index_task(task: &CodeIndexTaskRecord, requested_ref: impl Into<String>) -> Self {
771 Self {
772 scope_id: task.source_scope.clone(),
773 repository_id: task.repository_id.clone(),
774 alias: task.alias.clone(),
775 requested_ref: requested_ref.into(),
776 resolved_commit_sha: task.resolved_commit_sha.clone(),
777 tree_hash: task.tree_hash.clone(),
778 path_filters: task.path_filters.clone(),
779 language_filters: task.language_filters.clone(),
780 indexed_file_count: 0,
781 index_versions: vec![format!("code:{}:{}", task.source_scope, task.tree_hash)],
782 stale: true,
783 }
784 }
785}
786
787#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
789pub struct CodeRepositoryQueryResponse {
790 pub metadata: ApiMetadata,
791 pub scope: CodeRepositoryScopeMetadata,
792 #[serde(default = "CodeRepositoryFreshnessDiagnostics::legacy_unknown")]
793 pub freshness: CodeRepositoryFreshnessDiagnostics,
794 pub request: CodeRetrievalRequest,
795 pub results: Vec<CodeRetrievalHit>,
796 #[serde(skip_serializing_if = "Option::is_none")]
797 pub degraded_reason: Option<String>,
798}
799
800#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
802pub struct CodeRepositoryFeatureFlagsResponse {
803 pub metadata: ApiMetadata,
804 pub scope: CodeRepositoryScopeMetadata,
805 #[serde(default = "CodeRepositoryFreshnessDiagnostics::legacy_unknown")]
806 pub freshness: CodeRepositoryFreshnessDiagnostics,
807 pub request: CodeFeatureFlagRequest,
808 pub flags: Vec<CodeFeatureFlagGraph>,
809 #[serde(skip_serializing_if = "Option::is_none")]
810 pub degraded_reason: Option<String>,
811}
812
813#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
815pub struct CodeRepositoryImpactResponse {
816 pub metadata: ApiMetadata,
817 pub scope: CodeRepositoryScopeMetadata,
818 pub request: CodeImpactRequest,
819 pub path_groups: CodeImpactPathGroups,
820 pub results: Vec<CodeRetrievalHit>,
821}
822
823#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
825pub struct CodeRepositoryStatusResponse {
826 pub metadata: ApiMetadata,
827 pub status: CodeRepositoryStatus,
828 #[serde(skip_serializing_if = "Option::is_none")]
829 pub active_task: Option<CodeIndexTaskRecord>,
830 #[serde(skip_serializing_if = "Option::is_none")]
831 pub checkpoint: Option<CodeIndexCheckpoint>,
832 pub retention: CodeScopeRetentionSummary,
833}
834
835#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
837pub struct CodeRepositoryReportResponse {
838 pub metadata: ApiMetadata,
839 pub scope: CodeRepositoryScopeMetadata,
840 pub report: CodeRepositoryReport,
841}
842
843#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
845pub struct SoftwareGlobalResponse {
846 pub metadata: ApiMetadata,
847 pub scope: CodeRepositoryScopeMetadata,
848 pub request: SoftwareGlobalRequest,
849 pub status: SoftwareGlobalStatus,
850 pub components: Vec<SoftwareComponent>,
851 pub dependency_usages: Vec<SoftwareDependencyUsage>,
852 pub sdk_usages: Vec<SoftwareSdkUsage>,
853 pub files: Vec<SoftwareFile>,
854 pub topics: Vec<SoftwareTopic>,
855 pub relationships: Vec<SoftwareRelationship>,
856 pub build_targets: Vec<SoftwareBuildTarget>,
857 pub iac_resources: Vec<SoftwareIacResource>,
858 pub design_elements: Vec<SoftwareDesignElement>,
859}
860
861#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
863pub struct CodeRepositorySetCreateResponse {
864 pub metadata: ApiMetadata,
865 pub request: CodeRepositorySetCreateRequest,
866 pub repository_set: CodeRepositorySet,
867}
868
869#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
871pub struct CodeRepositorySetAddResponse {
872 pub metadata: ApiMetadata,
873 pub request: CodeRepositorySetAddMemberRequest,
874 pub member: CodeRepositorySetMember,
875 pub status: CodeRepositorySetStatus,
876}
877
878#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
880pub struct CodeRepositorySetRemoveResponse {
881 pub metadata: ApiMetadata,
882 pub request: CodeRepositorySetRemoveMemberRequest,
883 pub member: CodeRepositorySetMember,
884 pub status: CodeRepositorySetStatus,
885}
886
887#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
889pub struct CodeRepositorySetQueryResponse {
890 pub metadata: ApiMetadata,
891 pub request: CodeRepositorySetQueryRequest,
892 pub status: CodeRepositorySetStatus,
893 pub results: Vec<CodeRepositorySetQueryHit>,
894 pub truncated: bool,
895 #[serde(skip_serializing_if = "Option::is_none")]
896 pub degraded_reason: Option<String>,
897}
898
899#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
901pub struct CodeRepositorySetStatusResponse {
902 pub metadata: ApiMetadata,
903 pub status: CodeRepositorySetStatus,
904}
905
906#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
908pub struct CodeRepositorySetRefreshResponse {
909 pub metadata: ApiMetadata,
910 pub status: CodeRepositorySetStatus,
911 #[serde(skip_serializing_if = "Option::is_none")]
912 pub summary: Option<CodeRepositorySetRefreshSummary>,
913 #[serde(skip_serializing_if = "Option::is_none")]
914 pub task: Option<CodeRepositorySetRefreshTaskRecord>,
915}
916
917fn merged_filters(base: &[String], request: &[String]) -> Vec<String> {
918 let mut merged = Vec::new();
919 for value in base.iter().chain(request.iter()) {
920 if !merged.contains(value) {
921 merged.push(value.clone());
922 }
923 }
924
925 merged
926}