converge_knowledge/grpc/
client.rs1use super::knowledge_service_client::KnowledgeServiceClient as ProtoClient;
4use super::*;
5use crate::error::{Error, Result};
6
7use tonic::transport::Channel;
8
9pub struct KnowledgeClient {
11 client: ProtoClient<Channel>,
12}
13
14impl KnowledgeClient {
15 pub async fn connect(addr: impl Into<String>) -> Result<Self> {
17 let addr = addr.into();
18 let client = ProtoClient::connect(addr)
19 .await
20 .map_err(|e| Error::storage(format!("Failed to connect: {}", e)))?;
21
22 Ok(Self { client })
23 }
24
25 pub async fn add_entry(
27 &mut self,
28 title: impl Into<String>,
29 content: impl Into<String>,
30 ) -> Result<String> {
31 let request = AddEntryRequest {
32 title: title.into(),
33 content: content.into(),
34 category: None,
35 tags: Vec::new(),
36 source: None,
37 metadata: std::collections::HashMap::new(),
38 };
39
40 let response = self
41 .client
42 .add_entry(request)
43 .await
44 .map_err(|e| Error::storage(e.to_string()))?
45 .into_inner();
46
47 if response.success {
48 Ok(response.id)
49 } else {
50 Err(Error::storage(
51 response
52 .error
53 .unwrap_or_else(|| "Unknown error".to_string()),
54 ))
55 }
56 }
57
58 pub async fn add_entry_full(&mut self, request: AddEntryRequest) -> Result<String> {
60 let response = self
61 .client
62 .add_entry(request)
63 .await
64 .map_err(|e| Error::storage(e.to_string()))?
65 .into_inner();
66
67 if response.success {
68 Ok(response.id)
69 } else {
70 Err(Error::storage(
71 response
72 .error
73 .unwrap_or_else(|| "Unknown error".to_string()),
74 ))
75 }
76 }
77
78 pub async fn add_entries(&mut self, entries: Vec<AddEntryRequest>) -> Result<Vec<String>> {
80 let request = AddEntriesRequest { entries };
81
82 let response = self
83 .client
84 .add_entries(request)
85 .await
86 .map_err(|e| Error::storage(e.to_string()))?
87 .into_inner();
88
89 if response.success {
90 Ok(response.ids)
91 } else {
92 Err(Error::storage(
93 response
94 .error
95 .unwrap_or_else(|| "Unknown error".to_string()),
96 ))
97 }
98 }
99
100 pub async fn get_entry(&mut self, id: impl Into<String>) -> Result<Option<KnowledgeEntry>> {
102 let request = GetEntryRequest { id: id.into() };
103
104 let response = self
105 .client
106 .get_entry(request)
107 .await
108 .map_err(|e| Error::storage(e.to_string()))?
109 .into_inner();
110
111 if response.found {
112 Ok(response.entry)
113 } else {
114 Ok(None)
115 }
116 }
117
118 pub async fn update_entry(&mut self, request: UpdateEntryRequest) -> Result<()> {
120 let response = self
121 .client
122 .update_entry(request)
123 .await
124 .map_err(|e| Error::storage(e.to_string()))?
125 .into_inner();
126
127 if response.success {
128 Ok(())
129 } else {
130 Err(Error::storage(
131 response
132 .error
133 .unwrap_or_else(|| "Unknown error".to_string()),
134 ))
135 }
136 }
137
138 pub async fn delete_entry(&mut self, id: impl Into<String>) -> Result<()> {
140 let request = DeleteEntryRequest { id: id.into() };
141
142 let response = self
143 .client
144 .delete_entry(request)
145 .await
146 .map_err(|e| Error::storage(e.to_string()))?
147 .into_inner();
148
149 if response.success {
150 Ok(())
151 } else {
152 Err(Error::storage(
153 response
154 .error
155 .unwrap_or_else(|| "Unknown error".to_string()),
156 ))
157 }
158 }
159
160 pub async fn search(
162 &mut self,
163 query: impl Into<String>,
164 limit: u32,
165 ) -> Result<Vec<SearchResult>> {
166 let request = SearchRequest {
167 query: query.into(),
168 limit,
169 min_similarity: 0.0,
170 category: None,
171 tags: Vec::new(),
172 use_learning: true,
173 include_related: false,
174 diversity: 0.0,
175 hybrid: false,
176 keyword_weight: 0.3,
177 };
178
179 let response = self
180 .client
181 .search(request)
182 .await
183 .map_err(|e| Error::storage(e.to_string()))?
184 .into_inner();
185
186 Ok(response.results)
187 }
188
189 pub async fn search_full(&mut self, request: SearchRequest) -> Result<SearchResponse> {
191 let response = self
192 .client
193 .search(request)
194 .await
195 .map_err(|e| Error::storage(e.to_string()))?
196 .into_inner();
197
198 Ok(response)
199 }
200
201 pub async fn record_feedback(
203 &mut self,
204 entry_id: impl Into<String>,
205 positive: bool,
206 ) -> Result<()> {
207 let request = FeedbackRequest {
208 entry_id: entry_id.into(),
209 positive,
210 query_context: None,
211 };
212
213 let response = self
214 .client
215 .record_feedback(request)
216 .await
217 .map_err(|e| Error::storage(e.to_string()))?
218 .into_inner();
219
220 if response.success {
221 Ok(())
222 } else {
223 Err(Error::storage("Failed to record feedback"))
224 }
225 }
226
227 pub async fn get_related(
229 &mut self,
230 id: impl Into<String>,
231 limit: u32,
232 ) -> Result<Vec<KnowledgeEntry>> {
233 let request = GetRelatedRequest {
234 id: id.into(),
235 limit,
236 };
237
238 let response = self
239 .client
240 .get_related(request)
241 .await
242 .map_err(|e| Error::storage(e.to_string()))?
243 .into_inner();
244
245 Ok(response.entries)
246 }
247
248 pub async fn link_entries(
250 &mut self,
251 id1: impl Into<String>,
252 id2: impl Into<String>,
253 ) -> Result<()> {
254 let request = LinkEntriesRequest {
255 id1: id1.into(),
256 id2: id2.into(),
257 };
258
259 let response = self
260 .client
261 .link_entries(request)
262 .await
263 .map_err(|e| Error::storage(e.to_string()))?
264 .into_inner();
265
266 if response.success {
267 Ok(())
268 } else {
269 Err(Error::storage(
270 response
271 .error
272 .unwrap_or_else(|| "Unknown error".to_string()),
273 ))
274 }
275 }
276
277 pub async fn get_stats(&mut self) -> Result<GetStatsResponse> {
279 let response = self
280 .client
281 .get_stats(GetStatsRequest {})
282 .await
283 .map_err(|e| Error::storage(e.to_string()))?
284 .into_inner();
285
286 Ok(response)
287 }
288
289 pub async fn health(&mut self) -> Result<HealthResponse> {
291 let response = self
292 .client
293 .health(HealthRequest {})
294 .await
295 .map_err(|e| Error::storage(e.to_string()))?
296 .into_inner();
297
298 Ok(response)
299 }
300}