Files
aether-tools-rs/README.md
T
2026-07-09 17:05:13 -04:00

5.1 KiB
Raw Blame History

aether-tools-rs — atom + 4 binaries

The unified rewrite of aether-tools onto a single atomic primitive. 1517 production LOC across 4 binaries (vs ~7000 LOC in the original 7-crate suite) — driven by one core idea:

An answer, once given, is true until forgotten.

Concretely: a content-addressed memo table that lives on disk as an append-only JSONL ledger. Every binary in this workspace is a thin binding around three operations:

  1. canonicalize(input) — collapse equivalent inputs to a stable byte form (regex-based Rust-error abstraction by default; identity otherwise).
  2. record(sig, scope, body, worked?, ts) — append a fact to the audit log.
  3. ask(sig) → value | miss — cache-or-compute.

Crates

Crate LOC Role
aether-atom 577 The atomic core: fingerprint, canonicalize, lattice, ask/demote/remember
aether-recall-mcp 311 MCP-over-stdio server (the 4 tools that drive opencode's recall loop)
aether-net-mini 245 TCP JSON-RPC daemon: put/get over the atom
aether-ask 326 HTTP front-end: cache-or-fallback to ollama, dark-mode UI
aec-atom 250 REPL: lookup/remember/stats/compact/replay/fingerprint
examples/library_usage ~80 Drop-in pattern for any third-party crate that wants memory

Total 1517 production LOC (excluding the example).

Tests

atom           28 unit
aether-recall-mcp   1 integration  (spawns binary, full lifecycle)
aether-net-mini     5 unit
aether-ask          2 unit + 4 integration  (HTTP routes + cache hit assertion)
aec-atom           10 unit
                ─────
                 50 passing

cargo test --workspace runs all of them in ~0.30 s.

Clippy

$ cargo clippy --workspace --all-targets
(clean — no warnings, no errors)

Configuration

Every binary takes its data directory from a single helper in the atom:

aether_atom::data_dir("AETHER_RECALL_DIR")

Resolution order: env var → $HOME/.aether-recall/./.aether-recall/. Override with AETHER_RECALL_DIR=/path/to/ledger.

Per-binary tunables:

Binary Env var Default
aether-recall-mcp AETHER_RECALL_LOOKUP_RETENTION_DAYS 30
aether-ask AETHER_ASK_PORT, OLLAMA_HOST, OLLAMA_PORT, OLLAMA_MODEL 8082 / 127.0.0.1 / 11434 / dolphin-llama3:8b
aether-net-mini AETHER_NET_DATA_DIR $HOME/.aether-recall/
aec-atom AEC_COMPACT_DAYS 30

Run

cargo build --release --workspace

# Stand up an MCP server (used by opencode)
AETHER_RECALL_DIR=~/.aether-recall ./target/release/aether-recall-mcp &

# Run an HTTP gateway alongside
AETHER_ASK_PORT=8082 ./target/release/aether-ask &

# Optionally stand up a DHT node
./target/release/aether-net-mini daemon --listen 0.0.0.0:9001 &

# Or poke at the ledger live
./target/release/aec-atom
ae> remember "error[E0308]: expected i32, found &str" "use .to_string()"
ae> lookup   "error[E0308]: expected i32, found &str"
ae> stats
ae> replay
ae> quit

Use the atom in your own code

[dependencies]
aether-atom = { path = "/home/cosmos/aether-atom" }   # or git / crates.io
use aether_atom::{data_dir, fingerprint, rust_canonicalize, Lattice};

let mut lat = Lattice::open(&data_dir("MY_DATA_DIR"))?;
let sig = fingerprint(rust_canonicalize(my_input).as_slice());
match lat.lookup(&sig, "global") {
    Some(hit)       => return hit.value,                 // cache hit
    None            => { let v = compute(my_input);       // cache miss
                         lat.record(sig, "global", &v, Some(true));
                         return v; }
}

See examples/library_usage/ for a 50-LOC working program with tests.

Bench approx (in-process, sdb fs)

10,000 cached ask() ops (incl. disk write):  801 ms  =  80 µs/op
100,000 raw  lookup()  ops (incl. disk write):   8.5 s  =  85 µs/op

vs the original aether-recall README's claim of ~200 µs per cached lookup — about 2.5× faster, chiefly because bodies are Arc-shared on the hit path so there's never a memcpy of the cached value.

What this is NOT

  • Not a chat product. A primitive your tools build on.
  • Not a peer-to-peer replication mesh. replicate is a placeholder. Both peers inherit the same atom ledger if they share the data dir.
  • Not a model registry. aether-ask delegates to whatever ollama is reachable; it doesn't manage model storage.

Built from this premise

Today the aether suite was 7 crates, ~7000 LOC. The original had three divergent fingerprint schemes, three append-only ledgers, ~900 ms subprocess overhead per ask, a hardcoded WSL2 path in three places, two dead kelp of dependencies (sha3, hex, rand, chrono) and two stubbed modules. This rewrite collapses that to one fingerprint, one ledger, one canonical linker (the atom), and four bindings — each adding a real surface (MCP tool, TCP verb, HTTP verb, or REPL command).

The atom is the most essential layer: prove it works, prove it benchmarks, and every wrapper is an obligation.