feat: add client mode with streaming support
Add client mode enabling the keep CLI to connect to a remote keep server over HTTP. Local plugins (compression, meta, filters) run on the client; the server stores/retrieves binary blobs. Architecture: - Client save uses 3-thread streaming pipeline: reader thread (stdin → tee/stdout → hash → compress), OS pipe, streamer thread (pipe → chunked HTTP POST). Memory usage is O(PIPESIZE) regardless of data size. - Server accepts compress=false, meta=false, decompress=false query params for granular control of server-side processing. - Streaming body handling on server via async channel → sync reader bridge (ChannelReader). Key additions: - src/client.rs: KeepClient with post_stream() for chunked upload - src/modes/client/: save, get, list, info, delete, diff, status - --client-url / KEEP_CLIENT_URL configuration - --client-password / KEEP_CLIENT_PASSWORD for auth - os_pipe dependency for zero-copy pipe streaming Co-Authored-By: andrew/openrouter/hunter-alpha <noreply@opencode.ai>
This commit is contained in:
@@ -153,6 +153,12 @@ pub struct CompressionPluginConfig {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct ClientConfig {
|
||||
pub url: Option<String>,
|
||||
pub password: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
#[cfg_attr(feature = "server", derive(utoipa::ToSchema))]
|
||||
pub struct MetaPluginConfig {
|
||||
@@ -184,6 +190,12 @@ pub struct Settings {
|
||||
pub server: Option<ServerConfig>,
|
||||
pub compression_plugin: Option<CompressionPluginConfig>,
|
||||
pub meta_plugins: Option<Vec<MetaPluginConfig>>,
|
||||
pub client: Option<ClientConfig>,
|
||||
// Non-serializable fields populated from CLI args
|
||||
#[serde(skip)]
|
||||
pub client_url: Option<String>,
|
||||
#[serde(skip)]
|
||||
pub client_password: Option<String>,
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
@@ -394,6 +406,21 @@ impl Settings {
|
||||
settings.dir = default_dir;
|
||||
}
|
||||
|
||||
// Populate client settings from CLI args and config
|
||||
#[cfg(feature = "client")]
|
||||
{
|
||||
settings.client_url = args
|
||||
.options
|
||||
.client_url
|
||||
.clone()
|
||||
.or_else(|| settings.client.as_ref().and_then(|c| c.url.clone()));
|
||||
settings.client_password = args
|
||||
.options
|
||||
.client_password
|
||||
.clone()
|
||||
.or_else(|| settings.client.as_ref().and_then(|c| c.password.clone()));
|
||||
}
|
||||
|
||||
debug!("CONFIG: Final settings: {settings:?}");
|
||||
Ok(settings)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user