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]
+24 -33
View File
@@ -1,47 +1,38 @@
//! Filesystem probe for the spike. Keeps files open across messages.
use serde_json::{Value, json};
use std::collections::HashMap;
use std::io::{BufRead, Write};
//! Filesystem probe. Keeps files open across messages.
use sausage_actor::{Value, json, messages, reply};
use std::{collections::HashMap, io::Write};
fn main() {
let mut open: HashMap<String, std::fs::File> = HashMap::new();
let mut out = std::io::stdout().lock();
for line in std::io::stdin().lock().lines() {
let Ok(line) = line else { break };
let Ok(msg) = serde_json::from_str::<Value>(&line) else { continue };
let b = &msg["body"];
let path = b["path"].as_str().unwrap_or_default().to_string();
let r = |res: std::io::Result<Value>| match res {
Ok(v) => v,
Err(e) => json!({"type": "error", "error": e.to_string()}),
};
let reply = match b["type"].as_str() {
Some("shutdown") => break,
Some("write") => r(std::fs::write(&path, b["text"].as_str().unwrap_or_default()).map(|_| json!({"type": "ok"}))),
Some("open") => r((|| {
let mut f = std::fs::File::create(&path)?;
f.write_all(b["text"].as_str().unwrap_or_default().as_bytes())?;
open.insert(path.clone(), f);
let mut open = HashMap::<String, std::fs::File>::new();
for msg in messages() {
let b = &msg.body;
let path = b["path"].as_str().unwrap_or_default();
let r = |result: std::io::Result<Value>| result.unwrap_or_else(|e| json!({"type": "error", "error": e.to_string()}));
let response = match msg.kind() {
"write" => r(std::fs::write(path, b["text"].as_str().unwrap_or_default()).map(|_| json!({"type": "ok"}))),
"open" => r((|| {
let mut file = std::fs::File::create(path)?;
file.write_all(b["text"].as_str().unwrap_or_default().as_bytes())?;
open.insert(path.into(), file);
Ok(json!({"type": "ok", "open": true}))
})()),
Some("append") => r((|| {
let mut f = std::fs::OpenOptions::new().append(true).open(&path)?;
f.write_all(b["text"].as_str().unwrap_or_default().as_bytes())?;
open.insert(path.clone(), f);
"append" => r((|| {
let mut file = std::fs::OpenOptions::new().append(true).open(path)?;
file.write_all(b["text"].as_str().unwrap_or_default().as_bytes())?;
open.insert(path.into(), file);
Ok(json!({"type": "ok", "open": true}))
})()),
Some("close") => json!({"type": "ok", "closed": open.remove(&path).is_some()}),
Some("read") => r(std::fs::read_to_string(&path).map(|t| json!({"type": "content", "text": t}))),
Some("list") => r(std::fs::read_dir(&path).map(|rd| {
"close" => json!({"type": "ok", "closed": open.remove(path).is_some()}),
"read" => r(std::fs::read_to_string(path).map(|text| json!({"type": "content", "text": text}))),
"list" => r(std::fs::read_dir(path).map(|rd| {
let mut names: Vec<String> = rd.filter_map(|e| e.ok()).map(|e| e.file_name().to_string_lossy().to_string()).collect();
names.sort();
json!({"type": "entries", "names": names})
})),
Some("remove") => r(std::fs::remove_file(&path).map(|_| json!({"type": "ok"}))),
Some("crash") => panic!("asked to crash"),
"remove" => r(std::fs::remove_file(path).map(|_| json!({"type": "ok"}))),
"crash" => panic!("asked to crash"),
_ => json!({"type": "error", "error": "unknown message"}),
};
writeln!(out, "{}", json!({"to": msg["from"], "reply_to": msg["id"], "body": reply})).unwrap();
out.flush().unwrap();
let _ = reply(&msg, response);
}
}