SDK sausage-actor; examples and agent on the SDK; agent without limits

- sausage-actor: Message, messages(), send/reply/publish, async Inbox
- agent: append-only /data/history.jsonl, no caps on history, steps, waits,
  tool output, or reads; max_tokens only when configured (Anthropic: 32000)
This commit is contained in:
2026-10-15 11:17:14 +01:00
parent c9d9864743
commit 7f76eab161
22 changed files with 607 additions and 518 deletions
+3 -1
View File
@@ -4,4 +4,6 @@ version = "0.1.0"
edition = "2024"
[dependencies]
serde_json = "1"
sausage-actor = { version = "0.1", path = "../../sdk" }
[workspace]
+32 -39
View File
@@ -1,45 +1,38 @@
//! {"type":"bench","target":"echo","n":1000}: ping-pong with the target, one
//! message at a time, and report the round-trip times.
use serde_json::{Value, json};
use std::io::{BufRead, Write};
//! Ping-pong with a target and report the round-trip times.
use sausage_actor::{json, messages, reply, send};
use std::time::Instant;
fn main() {
let mut out = std::io::stdout().lock();
let mut lines = std::io::stdin().lock().lines();
while let Some(Ok(line)) = lines.next() {
let Ok(msg) = serde_json::from_str::<Value>(&line) else { continue };
match msg["body"]["type"].as_str() {
Some("shutdown") => break,
Some("bench") => {
let target = msg["body"]["target"].as_str().unwrap_or("echo").to_string();
let n = msg["body"]["n"].as_u64().unwrap_or(1000);
let mut times = Vec::new();
let started = Instant::now();
for i in 0..n {
let t = Instant::now();
writeln!(out, "{}", json!({"to": target, "id": i, "body": {"type": "ping", "i": i}})).unwrap();
out.flush().unwrap();
// Wait for the reply.
loop {
let Some(Ok(l)) = lines.next() else { return };
let Ok(r) = serde_json::from_str::<Value>(&l) else { continue };
if r["reply_to"].as_str().is_some_and(|s| s.ends_with(&format!("/{i}"))) {
break;
}
}
times.push(t.elapsed().as_micros() as u64);
}
let total = started.elapsed().as_secs_f64();
times.sort();
let p = |q: f64| times[((times.len() as f64 - 1.0) * q) as usize];
let reply = json!({"type": "bench_result", "n": n, "total_s": total,
"msgs_per_s": (n as f64 / total).round(),
"p50_us": p(0.5), "p90_us": p(0.9), "p99_us": p(0.99), "max_us": p(1.0)});
writeln!(out, "{}", json!({"to": msg["from"], "reply_to": msg["id"], "body": reply})).unwrap();
out.flush().unwrap();
}
_ => {}
let mut inbox = messages();
while let Some(message) = inbox.next() {
if message.kind() != "bench" {
continue;
}
let target = message.body["target"].as_str().unwrap_or("echo");
let n = message.body["n"].as_u64().unwrap_or(1000);
let mut times = Vec::new();
let started = Instant::now();
for i in 0..n {
let t = Instant::now();
let id = send(target, json!({"type": "ping", "i": i}));
loop {
let Some(reply) = inbox.next() else { return };
if reply.reply_to.as_deref() == Some(id.as_str()) {
break;
}
}
times.push(t.elapsed().as_micros() as u64);
}
let total = started.elapsed().as_secs_f64();
times.sort();
let p = |q: f64| times[((times.len() as f64 - 1.0) * q) as usize];
let _ = reply(
&message,
json!({
"type": "bench_result", "n": n, "total_s": total,
"msgs_per_s": (n as f64 / total).round(),
"p50_us": p(0.5), "p90_us": p(0.9), "p99_us": p(0.99), "max_us": p(1.0)
}),
);
}
}