Files
aether-tools-rs/README.md
T

151 lines
5.1 KiB
Markdown
Raw Normal View History

2026-07-09 17:05:13 -04:00
# 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:
```rust
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
```bash
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
```toml
[dependencies]
aether-atom = { path = "/home/cosmos/aether-atom" } # or git / crates.io
```
```rust
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.