Expand description
Keel as a Rust front end.
Rust has no import hook to hang a zero-code-change promise off of (that’s
a dynamic-language trick python/keel/node/keel use), so the Rust
front end keeps the “one optional attribute” ceiling (dx-spec.md
invariant 1) instead: call init once from your own main, then mark
the calls you want policy-driven resilience on.
Two seams:
wrap(re-exported fromkeel-macros) —#[keel::wrap(target = "...")]on a freeasync fnroutes its body through the engine’s cache → rate → breaker → timeout → retry chain. See the macro’s own docs (crates/keel-macros/src/lib.rs) for the exact v1 scope (explicit target only,Cloneparameters, no generics/methods).KeelMiddleware— areqwest_middleware::Middlewarefor HTTP clients built onreqwest. See its module docs for the exact v1 scope (exact-host targets, no glob/llm:mapping, no body-hash caching).
Both share one process-wide keel_core::Engine, configured from
<cwd>/keel.toml (or Level 0 defaults if absent) — mirrors
python/keel’s install_keel/node/keel’s installKeel, minus the
import-hook and adapter-detection machinery neither seam needs here.
Deferred (see the session gap brief’s explicit descoping): no
cargo-keel subcommand, no syn-based static scanner
(crates/keel-cli/src/scan/rust.rs), no keel init --rust wiring. A
Rust project adds this crate itself and calls init; keel doctor/keel init do not yet know Rust projects exist. This is real,
tracked architectural debt, not an oversight — flagged for
prioritization rather than assumed to be next.
Published name vs. import name. This crate is published to
crates.io as keelrun (plain keel is taken — see
docs/naming-decision.md), but every #[keel::wrap]/::keel::… path
generated by the macro is hardcoded to the identifier keel, matching
the product’s one-attribute promise (dx-spec.md invariant 1). Add the
dependency with an explicit rename so the two agree:
[dependencies]
keel = { package = "keelrun", version = "0.1" }(equivalently, cargo add keelrun --rename keel). This mirrors how this
workspace’s own crates already depend on keelrun-core as keel-core —
not a workaround, the intended way to add this crate.
Structs§
- Keel
Middleware - A
Middlewarethat wraps every request in the keel-core Engine chain. Owns a clonedreqwest::Clientto send attempts itself (module docs explain why:Next/Extensionscannot cross intokeel_core::Engine::execute’s effect closure under#[async_trait]’sSend-boxing requirement).
Enums§
- Error
- The error a
#[keel::wrap]-wrapped function orcrate::KeelMiddlewaresurfaces.
Functions§
- init
- Initialize Keel from
<current_dir>/keel.toml(or Level 0 defaults if absent). Idempotent — a second call is a no-op (mirrorspython/keel’s/node/keel’s idempotentinstall_keel/installKeel). - init_
from - As
init, loadingkeel.tomlfromdirinstead of the current directory (multi-root setups; tests). - is_
initialized - True once an
Enginehas been installed, whether by an explicitinit/init_fromcall or lazily by the first wrapped call/ middleware invocation. - report
- Deterministic per-target metrics/discovery report (JSON), forwarded from
the underlying
keel_core::Engine::report.
Attribute Macros§
- wrap
#[keel::wrap(target = "...", idempotent = true)].