Scaffold Colibri Phase 1: colibri-probe DeepSeek cache smoke (Sam & Claude)

Greenfield cross-platform (FreeBSD/Linux) Rust crate per clawdie-ai doc/COLIBRI-CONTROLPLANE-PLAN.md. colibri-probe sends a byte-stable DeepSeek prefix twice and reports prompt_cache_hit_tokens as a clawdie.provider-smoke.result.v1 manifest; build-only/skipped without DEEPSEEK_API_KEY.

Stack: tokio + reqwest(rustls-tls, no OpenSSL) + serde + chrono. Builds clean on Linux (cargo build --release, 1m16s); rust-toolchain pinned to 1.95.0. FreeBSD (osa) build is the next lane.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Sam & Claude 2026-05-26 10:08:23 +02:00
commit cf7d25e83a
6 changed files with 1745 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

1483
Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

18
Cargo.toml Normal file
View file

@ -0,0 +1,18 @@
[package]
name = "colibri"
version = "0.0.1"
edition = "2021"
description = "Clawdie Colibri control plane — cross-platform (FreeBSD/Linux) Rust core"
license = "AGPL-3.0-only"
[[bin]]
name = "colibri-probe"
path = "src/main.rs"
[dependencies]
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
# rustls (not OpenSSL) keeps the TLS stack pure-Rust and FreeBSD-portable.
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
chrono = { version = "0.4", default-features = false, features = ["clock"] }

47
README.md Normal file
View file

@ -0,0 +1,47 @@
# Colibri
The Clawdie control plane core — a small, cross-platform (FreeBSD + Linux) Rust
daemon. It unifies a coordination model (agents-as-teammates, task board, team
skills) with a cache-first cost discipline (byte-stable prompt prefixes,
cache-hit metering), sitting on top of the existing Pi engine, watchdog, hostd
and Postgres.
Design + implementation path: see `doc/COLIBRI-CONTROLPLANE-PLAN.md` in
`clawdie-ai`.
## Phase 1 — `colibri-probe`
A falsifiable first build that proves three things at once:
1. Rust + `rustls` + `tokio` build cross-platform (Linux first, FreeBSD next).
2. A raw DeepSeek HTTPS call works.
3. DeepSeek **prefix caching** is real on our infra: send a byte-stable prefix
twice and observe `prompt_cache_hit_tokens > 0` on the second request.
It prints a `clawdie.provider-smoke.result.v1` manifest on stdout.
### Build (no key needed)
```sh
cargo build --release
```
### Run
```sh
# Build-only / skipped mode (no key): verifies the binary runs.
./target/release/colibri-probe
# Live cache probe:
DEEPSEEK_API_KEY=sk-... ./target/release/colibri-probe
```
Env overrides: `DEEPSEEK_MODEL` (default `deepseek-chat`, the DeepSeek API model
string — distinct from our internal `deepseek-v4-flash` alias),
`DEEPSEEK_ENDPOINT`, `COLIBRI_HOST`.
## FreeBSD note
Target `x86_64-unknown-freebsd` (Rust Tier-2). Install via `pkg install rust` or
rustup; the `rust-toolchain.toml` pins the channel for cross-host
reproducibility. TLS is `rustls` to avoid `openssl-sys` linking on FreeBSD.

2
rust-toolchain.toml Normal file
View file

@ -0,0 +1,2 @@
[toolchain]
channel = "1.95.0"

194
src/main.rs Normal file
View file

@ -0,0 +1,194 @@
//! colibri-probe — Phase 1 of the Colibri control plane.
//! See clawdie-ai `doc/COLIBRI-CONTROLPLANE-PLAN.md`.
//!
//! Proves three things at once:
//! 1. Rust + rustls + tokio build cross-platform (Linux now, FreeBSD next).
//! 2. A raw DeepSeek HTTPS call works.
//! 3. DeepSeek prefix caching is real on our infra: send a byte-stable prefix
//! twice and observe `prompt_cache_hit_tokens > 0` on the second request.
//!
//! Emits a `clawdie.provider-smoke.result.v1` manifest on stdout. Runs in
//! build-only/"skipped" mode when `DEEPSEEK_API_KEY` is unset.
use std::env;
use chrono::Utc;
use serde::{Deserialize, Serialize};
const RESULT_SCHEMA: &str = "clawdie.provider-smoke.result.v1";
const DEFAULT_ENDPOINT: &str = "https://api.deepseek.com/chat/completions";
// DeepSeek API model string (cache-capable). Distinct from our internal
// `deepseek-v4-flash` alias; override with DEEPSEEK_MODEL.
const DEFAULT_MODEL: &str = "deepseek-chat";
// Deliberately long and byte-stable. Reasonix discipline: the immutable region
// must not change between turns or the cache will not hit.
const STABLE_SYSTEM_PREFIX: &str = "You are Colibri, the Clawdie control-plane probe. \
Answer tersely. This system prefix is intentionally fixed byte-for-byte so that \
DeepSeek automatic prefix caching can engage across repeated requests. The Clawdie \
control plane partitions context into an immutable prefix, an append-only log, and \
volatile scratch; this probe exercises only the immutable prefix to measure \
cache-hit economics.";
#[derive(Debug, Serialize)]
struct ChatMessage<'a> {
role: &'a str,
content: &'a str,
}
#[derive(Debug, Serialize)]
struct ChatRequest<'a> {
model: &'a str,
messages: Vec<ChatMessage<'a>>,
stream: bool,
max_tokens: u32,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
struct Usage {
#[serde(default)]
prompt_tokens: u64,
#[serde(default)]
completion_tokens: u64,
#[serde(default)]
total_tokens: u64,
#[serde(default)]
prompt_cache_hit_tokens: u64,
#[serde(default)]
prompt_cache_miss_tokens: u64,
}
#[derive(Debug, Deserialize)]
struct ChatResponse {
#[serde(default)]
model: Option<String>,
usage: Option<Usage>,
}
#[derive(Debug, Serialize)]
struct SmokeResult {
schema: &'static str,
test_id: String,
host: String,
agent: String,
provider: String,
model: String,
started_at: String,
ended_at: String,
status: String,
warm_usage: Option<Usage>,
probe_usage: Option<Usage>,
cache_hit_tokens: u64,
cache_hit_observed: bool,
notes: Vec<String>,
}
async fn one_call(
client: &reqwest::Client,
endpoint: &str,
key: &str,
model: &str,
) -> Result<(Option<String>, Usage), Box<dyn std::error::Error>> {
let body = ChatRequest {
model,
messages: vec![
ChatMessage {
role: "system",
content: STABLE_SYSTEM_PREFIX,
},
ChatMessage {
role: "user",
content: "Reply with the single word: ok.",
},
],
stream: false,
max_tokens: 16,
};
let resp = client
.post(endpoint)
.bearer_auth(key)
.json(&body)
.send()
.await?
.error_for_status()?;
let parsed: ChatResponse = resp.json().await?;
Ok((parsed.model, parsed.usage.unwrap_or_default()))
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let host = env::var("COLIBRI_HOST")
.or_else(|_| env::var("HOSTNAME"))
.unwrap_or_else(|_| "domedog".to_string());
let endpoint =
env::var("DEEPSEEK_ENDPOINT").unwrap_or_else(|_| DEFAULT_ENDPOINT.to_string());
let model = env::var("DEEPSEEK_MODEL").unwrap_or_else(|_| DEFAULT_MODEL.to_string());
let mut result = SmokeResult {
schema: RESULT_SCHEMA,
test_id: format!("colibri-probe-{}", Utc::now().format("%Y%m%dT%H%M%SZ")),
host,
agent: "claude-domedog".to_string(),
provider: "deepseek".to_string(),
model: model.clone(),
started_at: Utc::now().to_rfc3339(),
ended_at: String::new(),
status: String::new(),
warm_usage: None,
probe_usage: None,
cache_hit_tokens: 0,
cache_hit_observed: false,
notes: Vec::new(),
};
match env::var("DEEPSEEK_API_KEY") {
Ok(key) if !key.trim().is_empty() => {
let client = reqwest::Client::builder()
.user_agent("colibri-probe/0.0.1")
.build()?;
// Warm the cache, then probe with a byte-identical prefix.
match one_call(&client, &endpoint, &key, &model).await {
Ok((m, warm)) => {
if let Some(m) = m {
result.model = m;
}
result.warm_usage = Some(warm);
match one_call(&client, &endpoint, &key, &model).await {
Ok((_, probe)) => {
result.cache_hit_tokens = probe.prompt_cache_hit_tokens;
result.cache_hit_observed = probe.prompt_cache_hit_tokens > 0;
result.probe_usage = Some(probe);
result.status = "ok".to_string();
result.notes.push(if result.cache_hit_observed {
"prefix cache HIT on second request".to_string()
} else {
"no cache hit observed — check prefix byte-stability / provider cache state".to_string()
});
}
Err(e) => {
result.status = "error".to_string();
result.notes.push(format!("probe call failed: {e}"));
}
}
}
Err(e) => {
result.status = "error".to_string();
result.notes.push(format!("warm call failed: {e}"));
}
}
}
_ => {
result.status = "skipped".to_string();
result
.notes
.push("DEEPSEEK_API_KEY unset/empty — build verified, live cache probe skipped".to_string());
}
}
result.ended_at = Utc::now().to_rfc3339();
println!("{}", serde_json::to_string_pretty(&result)?);
if result.status == "error" {
std::process::exit(1);
}
Ok(())
}