bctx_cloud_core/client/
sync.rs1#[cfg(not(feature = "cloud-server"))]
2use anyhow::bail;
3use anyhow::Result;
4use serde::{Deserialize, Serialize};
5use vault::fact::MemoFact;
6
7#[derive(Debug, Serialize, Deserialize)]
8pub struct SyncPushPayload {
9 pub project_hash: String,
10 pub facts: Vec<MemoFact>,
11 pub client_version: String,
12}
13
14#[derive(Debug, Serialize, Deserialize)]
15pub struct SyncPullResponse {
16 pub facts: Vec<MemoFact>,
17 pub server_version: u64,
18}
19
20#[derive(Debug, Serialize, Deserialize)]
21pub struct SyncPushResponse {
22 pub accepted: usize,
23 pub merged: usize,
24 pub server_version: u64,
25}
26
27#[cfg(feature = "cloud-server")]
29pub async fn push_vault(
30 endpoint: &str,
31 token: &str,
32 project_hash: &str,
33 facts: Vec<MemoFact>,
34) -> Result<SyncPushResponse> {
35 let payload = SyncPushPayload {
36 project_hash: project_hash.to_string(),
37 facts,
38 client_version: env!("CARGO_PKG_VERSION").to_string(),
39 };
40 let resp = reqwest::Client::builder()
41 .timeout(std::time::Duration::from_secs(15))
42 .connect_timeout(std::time::Duration::from_secs(8))
43 .build()?
44 .post(format!("{endpoint}/sync/vault"))
45 .bearer_auth(token)
46 .json(&payload)
47 .send()
48 .await?
49 .error_for_status()?
50 .json::<SyncPushResponse>()
51 .await?;
52 Ok(resp)
53}
54
55#[cfg(not(feature = "cloud-server"))]
56pub async fn push_vault(
57 _endpoint: &str,
58 _token: &str,
59 _project_hash: &str,
60 _facts: Vec<MemoFact>,
61) -> Result<SyncPushResponse> {
62 bail!("cloud-server feature not enabled")
63}
64
65#[cfg(feature = "cloud-server")]
67pub async fn pull_vault(
68 endpoint: &str,
69 token: &str,
70 project_hash: &str,
71) -> Result<SyncPullResponse> {
72 let resp = reqwest::Client::builder()
73 .timeout(std::time::Duration::from_secs(15))
74 .connect_timeout(std::time::Duration::from_secs(8))
75 .build()?
76 .get(format!("{endpoint}/sync/vault/{project_hash}"))
77 .bearer_auth(token)
78 .send()
79 .await?
80 .error_for_status()?
81 .json::<SyncPullResponse>()
82 .await?;
83 Ok(resp)
84}
85
86#[cfg(not(feature = "cloud-server"))]
87pub async fn pull_vault(
88 _endpoint: &str,
89 _token: &str,
90 _project_hash: &str,
91) -> Result<SyncPullResponse> {
92 bail!("cloud-server feature not enabled")
93}
94
95#[cfg(feature = "cloud-server")]
99pub fn push_signals_bg(
100 endpoint: String,
101 token: String,
102 tokens_sent: i64,
103 tokens_saved: i64,
104 skill: String,
105) -> std::thread::JoinHandle<()> {
106 std::thread::spawn(move || {
107 let rt = tokio::runtime::Builder::new_current_thread()
108 .enable_all()
109 .build();
110 if let Ok(rt) = rt {
111 let _ = rt.block_on(async {
112 let client = reqwest::Client::builder()
113 .timeout(std::time::Duration::from_secs(8))
114 .connect_timeout(std::time::Duration::from_secs(5))
115 .build()
116 .unwrap_or_default();
117 client
118 .post(format!("{endpoint}/sync/signals"))
119 .bearer_auth(&token)
120 .json(&serde_json::json!({
121 "tokens_sent": tokens_sent,
122 "tokens_saved": tokens_saved,
123 "skill": skill,
124 }))
125 .send()
126 .await
127 });
128 }
129 })
130}
131
132#[cfg(not(feature = "cloud-server"))]
133pub fn push_signals_bg(
134 _endpoint: String,
135 _token: String,
136 _tokens_sent: i64,
137 _tokens_saved: i64,
138 _skill: String,
139) -> std::thread::JoinHandle<()> {
140 std::thread::spawn(|| {})
141}