litellm/litellm-rust/AGENTS.md
yujonglee 705bd84523
refactor(rust): share provider constants via llms-types and restructure AGENTS.md (#45850)
* wip

* refactor(rust): share Bedrock paths and Converse/Invoke wire types via llms-types

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(rust): share Vertex AI locations, base URL and rawPredict paths via llms-types

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(rust): give every llms-types format and provider its own folder

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(rust): keep single-adapter projections in llms

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(rust): restructure llms and llms-types AGENTS.md into rules and references

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(rust): keep provider mod.rs files as re-export entrypoints

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(rust): split llms and llms-types AGENTS.md rules into topic sections

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(rust): move llms-types tests inline and default the workspace to inline tests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(rust): move llms tests inline beside the code they cover

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(rust): cover every provider format with AGENTS.md and keep each upstream URL in one file

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci: drop the check_rust_agents_md step

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: regenerate greptile files.json for the new AGENTS.md files

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(rust): make every llms-types mod.rs a re-export entrypoint and drop check_rust_agents_md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(rust): register Messages providers in one match and drop the nested AGENTS.md list

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 16:53:35 -07:00

4.1 KiB

Rust workspace rules

For diagnostic tracing changes, follow .agents/skills/rust-tracing/SKILL.md

For string-valued enums and their Serde conversions, follow .agents/skills/rust-string-enums/SKILL.md

For fieldless enums, derive strum::VariantArray and use VARIANTS instead of a hand-listed ALL array. Derive Strum string conversions instead of hand-written variant-to-string matches

Use the derived conversions directly (<&'static str>::from(x) / .into(), str::parse) with no as_str/parse wrapper that only delegates, and spell each variant with explicit #[strum(serialize = "...")] instead of serialize_all

Test placement

  • Never create a tests.rs (or test.rs) file under src/, and never #[path = "tests.rs"] mod tests;
  • Tests live inline by default, in a #[cfg(test)] mod tests { ... } at the bottom of the file that owns the code under test, whether or not they touch private items
  • crates/<crate>/tests/ is only for tests that drive several modules together end to end, such as a full request through a route. A test of one type or function never goes there
  • A helper shared by several inline test modules goes in a #[cfg(test)] mod test_support; at the crate root, and only once a second module needs it
  • A test for another crate's item belongs in that crate, not in a downstream one
  • Never set autotests = false or hand-list [[test]] targets. Every file directly under tests/ is discovered by cargo, and a shared helper goes in tests/<name>/mod.rs or tests/<subject>/support.rs so it is not picked up as a test crate of its own

Test fixtures and cases

Use #[rstest] for new and updated tests and #[fixture] for reusable setup, injected through typed test arguments. Express input variations as named #[case::name(...)] cases instead of loops or duplicated tests so each failure identifies its case. Keep behavior assertions in the test body and fixtures focused on setup. Use the workspace rstest dependency

  • Never loop over inputs (for, .iter().for_each, .all) inside a test body. Give each input its own #[case::name(...)], or use #[values(...)] for a cross product
  • Exception: a test pinning a Rust table against a repo-owned data file (for example include_str! of a JSON config) may iterate that file's entries

Error definitions

  • A crate's errors live in src/error.rs, defined with thiserror, and re-exported from lib.rs
  • Put message templates in the variant's #[error(...)] declaration. Callers pass only the small typed arguments needed to fill them, never Error::Variant(format!(...)) or a preformatted message. Keep the smallest set of neutral variants that callers need to distinguish. Different wording or providers do not justify new variants
  • Default to one top-level Error enum per crate, with one variant per failure mode and a #[error(...)] message on each. A failure mode is something a caller handles differently (phase, status code, retry, a message Python parity pins exactly). Failures no caller tells apart share one variant and differ only in its message
  • Keep shared error enums minimal and provider-neutral. Provider names, credential types, configuration fields, and setup guidance belong in caller-supplied data, not dedicated variants or hardcoded shared messages. Reuse a variant for the same failure mode across providers, such as MissingApiBase { provider: "Azure", guidance: "..." }. An exact parity message does not justify a provider-specific variant when caller-supplied context can preserve it
  • Wrap a lower-level error as a variant with #[from] or #[source] instead of flattening it to a string
  • Exception: split into separate types when different functions fail in disjoint ways, especially when different callers see them. A shared enum would force every caller to match variants its function can never return
  • Name a split type after what went wrong (a unit struct is fine for a single failure mode), not after the function that returns it