Expand description
Provider plane.
Every provider is a command template. That single decision is what
makes BYOK support free: Claude Code, Ollama, a Grok CLI, an OpenAI-
compatible endpoint driven by curl, an MCP server over stdio — all of
them are “a program you can run with a prompt”. Adding a provider is a
config edit, never a Rust change and never a rebuild.
Two behaviours matter for correctness rather than convenience:
- Cascade with availability checks. A tier resolves to an ordered list of providers; the first one whose binary exists and whose required environment is present serves the call. Cheap tiers carry the mechanical work, strong tiers carry judgment.
- Secrets stay out of the record.
requires_envnames keys that must exist. Values are never read, never substituted into a logged command line, and never written to the ledger.
Structs§
Enums§
Functions§
- availability
- Is this provider usable right now?
- digest
- Cheap, dependency-free digest for prompt provenance. Not cryptographic — its only job is to let the ledger say “this is the same prompt as before” without storing the prompt twice.
- dispatch
- Walk the cascade for a tier and invoke the first provider that is both available and succeeds. Returns the response plus the ids that were skipped so the ledger can record why.
- estimate_
tokens - Rough token count when a provider reports nothing usable.
- invoke
- Invoke one specific provider.
- parse_
usage - Pull a token count out of provider output using its configured regex.
- render
- Substitute the supported placeholders into a template.
- starter_
providers - Sensible starting providers for a fresh config. Emitted by
loopsmith initso a new loop has a working cascade on day one; every one of them is just a command, so unavailable ones are skipped rather than fatal. - which
- Command lookup. Re-exported so existing callers keep this path; the
implementation moved to
loopsmith-utilonce it turned out to have been written three times across the workspace, in three states of correctness. Resolve a command the way a shell would: absolute paths (and anything containing a separator) are checked directly, bare names are resolved againstPATH.