This repository has been archived on 2026-08-20. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
el-retired/engram/engrams/engram-sync/src/client.rs
T
Will Anderson 909c1577f1 rename crates/ to engrams/, bindings/ to receptors/
- crates/ → engrams/ (Rust engrams live here)
- bindings/ → receptors/ (cross-language access points into the graph)
- Cargo.toml workspace paths updated
2026-04-29 03:27:33 -05:00

123 lines
4.0 KiB
Rust

/// HTTP client for talking to a remote Engram peer.
///
/// All peer-to-peer communication goes through this client.
/// Authentication is via `Authorization: Bearer {api_key}` on every request.
use crate::types::{Peer, SerializableActivatedNode, SyncDelta};
use anyhow::Context;
use uuid::Uuid;
pub struct SyncClient {
peer: Peer,
http: reqwest::Client,
our_id: Uuid,
}
impl SyncClient {
pub fn new(peer: Peer, our_id: Uuid) -> Self {
let http = reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(30))
.build()
.expect("failed to build reqwest client");
Self { peer, http, our_id }
}
/// Pull a delta from the remote peer containing everything since `since` (Unix ms).
///
/// GET {address}/sync/delta?since={since}&peer_id={our_id}
pub async fn pull_delta(&self, since: i64) -> anyhow::Result<SyncDelta> {
let url = format!(
"{}/sync/delta?since={}&peer_id={}",
self.peer.address, since, self.our_id
);
let resp = self
.http
.get(&url)
.header("Authorization", format!("Bearer {}", self.peer.api_key))
.send()
.await
.context("pull_delta: request failed")?;
if !resp.status().is_success() {
let status = resp.status();
let body = resp.text().await.unwrap_or_default();
anyhow::bail!("pull_delta: peer returned {}: {}", status, body);
}
resp.json::<SyncDelta>()
.await
.context("pull_delta: failed to decode response")
}
/// Push our delta to the remote peer.
///
/// POST {address}/sync/push
pub async fn push_delta(&self, delta: &SyncDelta) -> anyhow::Result<()> {
let url = format!("{}/sync/push", self.peer.address);
let resp = self
.http
.post(&url)
.header("Authorization", format!("Bearer {}", self.peer.api_key))
.json(delta)
.send()
.await
.context("push_delta: request failed")?;
if !resp.status().is_success() {
let status = resp.status();
let body = resp.text().await.unwrap_or_default();
anyhow::bail!("push_delta: peer returned {}: {}", status, body);
}
Ok(())
}
/// Fan spreading activation out to a remote peer.
///
/// POST {address}/swarm/activate — the remote peer runs activation locally
/// (include_peers=false so it does not fan out further, preventing cycles).
pub async fn remote_activate(
&self,
seeds: &[Uuid],
query_embedding: &[f32],
max_depth: u8,
limit: usize,
) -> anyhow::Result<Vec<SerializableActivatedNode>> {
use crate::types::SwarmActivateRequest;
let url = format!("{}/swarm/activate", self.peer.address);
let req = SwarmActivateRequest {
seeds: seeds.to_vec(),
query_embedding: query_embedding.to_vec(),
max_depth,
limit,
include_peers: false, // no further fan-out — prevents cycles
};
let resp = self
.http
.post(&url)
.header("Authorization", format!("Bearer {}", self.peer.api_key))
.json(&req)
.send()
.await
.context("remote_activate: request failed")?;
if !resp.status().is_success() {
let status = resp.status();
let body = resp.text().await.unwrap_or_default();
anyhow::bail!("remote_activate: peer returned {}: {}", status, body);
}
// The remote returns a SwarmActivateResponse; we only want local_results
let response: crate::types::SwarmActivateResponse = resp
.json()
.await
.context("remote_activate: failed to decode response")?;
Ok(response.local_results)
}
pub fn peer(&self) -> &Peer {
&self.peer
}
}