1use super::frames::{
6 ClientFrame, SecretEntryDto, deserialize_frame, serialize_frame, ServerFrame, ServerFrameType,
7 ServerPayload,
8};
9use anyhow::Result;
10use futures_util::SinkExt;
11use tokio_tungstenite::tungstenite::Message;
12
13pub async fn send_frame<S>(writer: &mut S, frame: &ServerFrame) -> Result<()>
16where
17 S: SinkExt<Message> + Unpin,
18{
19 let bytes = serialize_frame(frame).map_err(|e| anyhow::anyhow!("serialize failed: {}", e))?;
20 writer
21 .send(Message::Binary(bytes.into()))
22 .await
23 .map_err(|_e| anyhow::anyhow!("send failed"))
24}
25
26pub fn parse_client_frame(bytes: &[u8]) -> Result<ClientFrame> {
28 deserialize_frame(bytes).map_err(|e| anyhow::anyhow!("parse failed: {}", e))
29}
30
31pub async fn send_hello<S>(
33 writer: &mut S,
34 agent: &str,
35 settings_dir: &str,
36 vault_locked: bool,
37 provider: Option<&str>,
38 model: Option<&str>,
39) -> Result<()>
40where
41 S: SinkExt<Message> + Unpin,
42{
43 let frame = ServerFrame {
44 frame_type: ServerFrameType::Hello,
45 payload: ServerPayload::Hello {
46 agent: agent.into(),
47 settings_dir: settings_dir.into(),
48 vault_locked,
49 provider: provider.map(|s| s.into()),
50 model: model.map(|s| s.into()),
51 },
52 };
53 send_frame(writer, &frame).await
54}
55
56pub async fn send_auth_challenge<S>(writer: &mut S, method: &str) -> Result<()>
58where
59 S: SinkExt<Message> + Unpin,
60{
61 let frame = ServerFrame {
62 frame_type: ServerFrameType::AuthChallenge,
63 payload: ServerPayload::AuthChallenge {
64 method: method.into(),
65 },
66 };
67 send_frame(writer, &frame).await
68}
69
70pub async fn send_auth_result<S>(
72 writer: &mut S,
73 ok: bool,
74 message: Option<&str>,
75 retry: Option<bool>,
76) -> Result<()>
77where
78 S: SinkExt<Message> + Unpin,
79{
80 let frame = ServerFrame {
81 frame_type: ServerFrameType::AuthResult,
82 payload: ServerPayload::AuthResult {
83 ok,
84 message: message.map(|s| s.into()),
85 retry,
86 },
87 };
88 send_frame(writer, &frame).await
89}
90
91pub async fn send_error<S>(writer: &mut S, message: &str) -> Result<()>
93where
94 S: SinkExt<Message> + Unpin,
95{
96 let frame = ServerFrame {
97 frame_type: ServerFrameType::Error,
98 payload: ServerPayload::Error {
99 ok: false,
100 message: message.into(),
101 },
102 };
103 send_frame(writer, &frame).await
104}
105
106pub async fn send_info<S>(writer: &mut S, message: &str) -> Result<()>
108where
109 S: SinkExt<Message> + Unpin,
110{
111 let frame = ServerFrame {
112 frame_type: ServerFrameType::Info,
113 payload: ServerPayload::Info {
114 message: message.into(),
115 },
116 };
117 send_frame(writer, &frame).await
118}
119
120pub async fn send_status<S>(
122 writer: &mut S,
123 status: super::frames::StatusType,
124 detail: &str,
125) -> Result<()>
126where
127 S: SinkExt<Message> + Unpin,
128{
129 let frame = ServerFrame {
130 frame_type: ServerFrameType::Status,
131 payload: ServerPayload::Status {
132 status,
133 detail: detail.into(),
134 },
135 };
136 send_frame(writer, &frame).await
137}
138
139pub async fn send_vault_unlocked<S>(writer: &mut S, ok: bool, message: Option<&str>) -> Result<()>
141where
142 S: SinkExt<Message> + Unpin,
143{
144 let frame = ServerFrame {
145 frame_type: ServerFrameType::VaultUnlocked,
146 payload: ServerPayload::VaultUnlocked {
147 ok,
148 message: message.map(|s| s.into()),
149 },
150 };
151 send_frame(writer, &frame).await
152}
153
154pub async fn send_secrets_list_result<S>(
156 writer: &mut S,
157 ok: bool,
158 entries: Vec<SecretEntryDto>,
159) -> Result<()>
160where
161 S: SinkExt<Message> + Unpin,
162{
163 let frame = ServerFrame {
164 frame_type: ServerFrameType::SecretsListResult,
165 payload: ServerPayload::SecretsListResult { ok, entries },
166 };
167 send_frame(writer, &frame).await
168}
169
170pub async fn send_secrets_store_result<S>(
172 writer: &mut S,
173 ok: bool,
174 message: &str,
175) -> Result<()>
176where
177 S: SinkExt<Message> + Unpin,
178{
179 let frame = ServerFrame {
180 frame_type: ServerFrameType::SecretsStoreResult,
181 payload: ServerPayload::SecretsStoreResult {
182 ok,
183 message: message.into(),
184 },
185 };
186 send_frame(writer, &frame).await
187}
188
189pub async fn send_secrets_get_result<S>(
191 writer: &mut S,
192 ok: bool,
193 key: &str,
194 value: Option<&str>,
195 message: Option<&str>,
196) -> Result<()>
197where
198 S: SinkExt<Message> + Unpin,
199{
200 let frame = ServerFrame {
201 frame_type: ServerFrameType::SecretsGetResult,
202 payload: ServerPayload::SecretsGetResult {
203 ok,
204 key: key.into(),
205 value: value.map(|s| s.into()),
206 message: message.map(|s| s.into()),
207 },
208 };
209 send_frame(writer, &frame).await
210}
211
212pub async fn send_secrets_delete_result<S>(
214 writer: &mut S,
215 ok: bool,
216 message: Option<&str>,
217) -> Result<()>
218where
219 S: SinkExt<Message> + Unpin,
220{
221 let frame = ServerFrame {
222 frame_type: ServerFrameType::SecretsDeleteResult,
223 payload: ServerPayload::SecretsDeleteResult {
224 ok,
225 message: message.map(|s| s.into()),
226 },
227 };
228 send_frame(writer, &frame).await
229}
230
231pub async fn send_secrets_peek_result<S>(
233 writer: &mut S,
234 ok: bool,
235 fields: Vec<(String, String)>,
236 message: Option<&str>,
237) -> Result<()>
238where
239 S: SinkExt<Message> + Unpin,
240{
241 let frame = ServerFrame {
242 frame_type: ServerFrameType::SecretsPeekResult,
243 payload: ServerPayload::SecretsPeekResult {
244 ok,
245 fields,
246 message: message.map(|s| s.into()),
247 },
248 };
249 send_frame(writer, &frame).await
250}
251
252pub async fn send_secrets_set_policy_result<S>(
254 writer: &mut S,
255 ok: bool,
256 message: Option<&str>,
257) -> Result<()>
258where
259 S: SinkExt<Message> + Unpin,
260{
261 let frame = ServerFrame {
262 frame_type: ServerFrameType::SecretsSetPolicyResult,
263 payload: ServerPayload::SecretsSetPolicyResult {
264 ok,
265 message: message.map(|s| s.into()),
266 },
267 };
268 send_frame(writer, &frame).await
269}
270
271pub async fn send_secrets_set_disabled_result<S>(
273 writer: &mut S,
274 ok: bool,
275 message: Option<&str>,
276) -> Result<()>
277where
278 S: SinkExt<Message> + Unpin,
279{
280 let frame = ServerFrame {
281 frame_type: ServerFrameType::SecretsSetDisabledResult,
282 payload: ServerPayload::SecretsSetDisabledResult {
283 ok,
284 message: message.map(|s| s.into()),
285 },
286 };
287 send_frame(writer, &frame).await
288}
289
290pub async fn send_secrets_delete_credential_result<S>(
292 writer: &mut S,
293 ok: bool,
294 message: Option<&str>,
295) -> Result<()>
296where
297 S: SinkExt<Message> + Unpin,
298{
299 let frame = ServerFrame {
300 frame_type: ServerFrameType::SecretsDeleteCredentialResult,
301 payload: ServerPayload::SecretsDeleteCredentialResult {
302 ok,
303 message: message.map(|s| s.into()),
304 },
305 };
306 send_frame(writer, &frame).await
307}
308
309pub async fn send_secrets_has_totp_result<S>(writer: &mut S, has_totp: bool) -> Result<()>
311where
312 S: SinkExt<Message> + Unpin,
313{
314 let frame = ServerFrame {
315 frame_type: ServerFrameType::SecretsHasTotpResult,
316 payload: ServerPayload::SecretsHasTotpResult { has_totp },
317 };
318 send_frame(writer, &frame).await
319}
320
321pub async fn send_secrets_setup_totp_result<S>(
323 writer: &mut S,
324 ok: bool,
325 uri: Option<&str>,
326 message: Option<&str>,
327) -> Result<()>
328where
329 S: SinkExt<Message> + Unpin,
330{
331 let frame = ServerFrame {
332 frame_type: ServerFrameType::SecretsSetupTotpResult,
333 payload: ServerPayload::SecretsSetupTotpResult {
334 ok,
335 uri: uri.map(|s| s.into()),
336 message: message.map(|s| s.into()),
337 },
338 };
339 send_frame(writer, &frame).await
340}
341
342pub async fn send_secrets_verify_totp_result<S>(
344 writer: &mut S,
345 ok: bool,
346 message: Option<&str>,
347) -> Result<()>
348where
349 S: SinkExt<Message> + Unpin,
350{
351 let frame = ServerFrame {
352 frame_type: ServerFrameType::SecretsVerifyTotpResult,
353 payload: ServerPayload::SecretsVerifyTotpResult {
354 ok,
355 message: message.map(|s| s.into()),
356 },
357 };
358 send_frame(writer, &frame).await
359}
360
361pub async fn send_secrets_remove_totp_result<S>(
363 writer: &mut S,
364 ok: bool,
365 message: Option<&str>,
366) -> Result<()>
367where
368 S: SinkExt<Message> + Unpin,
369{
370 let frame = ServerFrame {
371 frame_type: ServerFrameType::SecretsRemoveTotpResult,
372 payload: ServerPayload::SecretsRemoveTotpResult {
373 ok,
374 message: message.map(|s| s.into()),
375 },
376 };
377 send_frame(writer, &frame).await
378}
379
380pub async fn send_reload_result<S>(
382 writer: &mut S,
383 ok: bool,
384 provider: &str,
385 model: &str,
386 message: Option<&str>,
387) -> Result<()>
388where
389 S: SinkExt<Message> + Unpin,
390{
391 let frame = ServerFrame {
392 frame_type: ServerFrameType::ReloadResult,
393 payload: ServerPayload::ReloadResult {
394 ok,
395 provider: provider.into(),
396 model: model.into(),
397 message: message.map(|s| s.into()),
398 },
399 };
400 send_frame(writer, &frame).await
401}
402
403pub async fn send_chunk<S>(writer: &mut S, delta: &str) -> Result<()>
405where
406 S: SinkExt<Message> + Unpin,
407{
408 let frame = ServerFrame {
409 frame_type: ServerFrameType::Chunk,
410 payload: ServerPayload::Chunk {
411 delta: delta.into(),
412 },
413 };
414 send_frame(writer, &frame).await
415}
416
417pub async fn send_response_done<S>(writer: &mut S, ok: bool) -> Result<()>
419where
420 S: SinkExt<Message> + Unpin,
421{
422 let frame = ServerFrame {
423 frame_type: ServerFrameType::ResponseDone,
424 payload: ServerPayload::ResponseDone { ok },
425 };
426 send_frame(writer, &frame).await
427}
428
429pub async fn send_stream_start<S>(writer: &mut S) -> Result<()>
431where
432 S: SinkExt<Message> + Unpin,
433{
434 let frame = ServerFrame {
435 frame_type: ServerFrameType::StreamStart,
436 payload: ServerPayload::StreamStart,
437 };
438 send_frame(writer, &frame).await
439}
440
441pub async fn send_tool_call<S>(
443 writer: &mut S,
444 id: &str,
445 name: &str,
446 arguments: &str,
447) -> Result<()>
448where
449 S: SinkExt<Message> + Unpin,
450{
451 let frame = ServerFrame {
452 frame_type: ServerFrameType::ToolCall,
453 payload: ServerPayload::ToolCall {
454 id: id.into(),
455 name: name.into(),
456 arguments: arguments.into(),
457 },
458 };
459 send_frame(writer, &frame).await
460}
461
462pub async fn send_tool_result<S>(
464 writer: &mut S,
465 id: &str,
466 name: &str,
467 result: &str,
468 is_error: bool,
469) -> Result<()>
470where
471 S: SinkExt<Message> + Unpin,
472{
473 let frame = ServerFrame {
474 frame_type: ServerFrameType::ToolResult,
475 payload: ServerPayload::ToolResult {
476 id: id.into(),
477 name: name.into(),
478 result: result.into(),
479 is_error,
480 },
481 };
482 send_frame(writer, &frame).await
483}
484
485pub async fn send_tool_approval_request<S>(
487 writer: &mut S,
488 id: &str,
489 name: &str,
490 arguments: &str,
491) -> Result<()>
492where
493 S: SinkExt<Message> + Unpin,
494{
495 let frame = ServerFrame {
496 frame_type: ServerFrameType::ToolApprovalRequest,
497 payload: ServerPayload::ToolApprovalRequest {
498 id: id.into(),
499 name: name.into(),
500 arguments: arguments.into(),
501 },
502 };
503 send_frame(writer, &frame).await
504}
505
506pub async fn send_user_prompt_request<S>(
508 writer: &mut S,
509 id: &str,
510 prompt: &crate::user_prompt_types::UserPrompt,
511) -> Result<()>
512where
513 S: SinkExt<Message> + Unpin,
514{
515 let frame = ServerFrame {
516 frame_type: ServerFrameType::UserPromptRequest,
517 payload: ServerPayload::UserPromptRequest {
518 id: id.into(),
519 prompt: prompt.clone(),
520 },
521 };
522 send_frame(writer, &frame).await
523}