Skip to main content

linkrs_wire/
vector.rs

1//! Vector protocol DTOs.
2//!
3//! Transport-independent request/response shapes for vector search and
4//! payload index management, shared between the server handlers and CLI
5//! clients. Generic payload/filter types come from `linkrs-core::core::vector`
6//! so the wire layer never depends on the storage engine.
7
8use serde::{Deserialize, Serialize};
9
10pub use linkrs_core::vector::{Payload, PayloadSchemaType, PayloadSelector, VectorFilter};
11
12/// Vector search request.
13#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
14pub struct VectorSearchRequest {
15    pub collection: String,
16    pub vector: Vec<f32>,
17    pub top_k: usize,
18    #[serde(default)]
19    pub filter: Option<VectorFilter>,
20    #[serde(default)]
21    pub with_payload: Option<bool>,
22    #[serde(default)]
23    pub with_vector: Option<bool>,
24    /// Returned-payload field projection (include / exclude lists).
25    #[serde(default)]
26    pub payload_selector: Option<PayloadSelector>,
27}
28
29/// Vector search response.
30#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
31pub struct VectorSearchResponse {
32    pub results: Vec<VectorSearchResult>,
33}
34
35/// One scored hit of a [`VectorSearchResponse`].
36#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
37pub struct VectorSearchResult {
38    pub id: String,
39    /// "Higher is better" similarity score, normalized across backends.
40    pub score: f32,
41    #[serde(default)]
42    #[schema(value_type = utoipa::openapi::Object)]
43    pub payload: Option<Payload>,
44    #[serde(default)]
45    pub vector: Option<Vec<f32>>,
46}
47
48/// Create a payload field index on a collection.
49#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
50pub struct CreatePayloadIndexRequest {
51    pub collection: String,
52    pub field: String,
53    pub schema_type: PayloadSchemaType,
54}
55
56/// Delete the payload field index on a collection's field.
57#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
58pub struct DeletePayloadIndexRequest {
59    pub collection: String,
60    pub field: String,
61}
62
63/// One declared payload index of [`ListPayloadIndexesResponse`].
64#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
65pub struct PayloadIndexInfo {
66    pub field: String,
67    pub schema_type: PayloadSchemaType,
68}
69
70/// All declared payload indexes of one collection.
71#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
72pub struct ListPayloadIndexesResponse {
73    pub collection: String,
74    pub indexes: Vec<PayloadIndexInfo>,
75}
76
77/// Rebuild a vector index request.
78///
79/// The rebuild runs asynchronously: the handler returns a rebuild id
80/// immediately and the caller polls the rebuild status endpoint.
81#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
82pub struct RebuildVectorIndexRequest {
83    /// Space (namespace) ID
84    pub space_id: u64,
85    /// Tag (vertex type) name
86    pub tag_name: String,
87    /// Field name
88    pub field_name: String,
89}
90
91/// Rebuild a vector index response (accepted async task).
92#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
93pub struct RebuildVectorIndexResponse {
94    /// Async rebuild task id for status polling
95    pub rebuild_id: String,
96    /// Initial task status (`running`)
97    pub status: String,
98    /// Space (namespace) ID
99    pub space_id: u64,
100    /// Tag (vertex type) name
101    pub tag_name: String,
102    /// Field name
103    pub field_name: String,
104}
105
106/// Vector rebuild task status.
107#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
108pub struct VectorRebuildStatusResponse {
109    /// Async rebuild task id
110    pub rebuild_id: String,
111    /// Task status (`running`, `completed`, `failed`)
112    pub status: String,
113    /// Current rebuild phase, if known
114    #[serde(default)]
115    pub phase: Option<String>,
116    /// Outbox generation used by this rebuild attempt, if known
117    #[serde(default)]
118    pub generation: Option<u64>,
119    /// Vertex snapshots scanned from primary storage
120    #[serde(default)]
121    pub vectors_scanned: u64,
122    /// Point operations applied (backfill + replay)
123    #[serde(default)]
124    pub vectors_applied: u64,
125    /// Snapshots skipped as unrepresentable
126    #[serde(default)]
127    pub vectors_skipped: u64,
128    /// Failure reason, if failed
129    #[serde(default)]
130    pub error: Option<String>,
131}
132
133/// Clear a vector index request.
134///
135/// Explicit destructive operation: drops all indexed points without
136/// backfill. Requires `force = true`.
137#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
138pub struct ClearVectorIndexRequest {
139    /// Space (namespace) ID
140    pub space_id: u64,
141    /// Tag (vertex type) name
142    pub tag_name: String,
143    /// Field name
144    pub field_name: String,
145    /// Explicit confirmation of the destructive clear
146    pub force: bool,
147}
148
149/// Clear a vector index response.
150#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
151pub struct ClearVectorIndexResponse {
152    /// Always true on success
153    pub ok: bool,
154    /// Space (namespace) ID
155    pub space_id: u64,
156    /// Tag (vertex type) name
157    pub tag_name: String,
158    /// Field name
159    pub field_name: String,
160}