1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//! Providers module - LLM adapters
//!
//! This module defines the `ModelProvider` trait and types. Provider implementations
//! are in the `enact-providers` crate to enable independent release cadence.
//!
//! Providers are thin HTTP adapters that translate between the `ModelProvider` trait
//! and external LLM APIs. They are replaceable and side-effect free outside HTTP calls.
//!
//! All retries, rate limiting, and quotas are enforced by the kernel, not by providers.
//!
//! ## CRITICAL: Provider Module Scope & Crate Boundaries
//!
//! **Crate Structure:**
//! - This module (`enact-core::providers`) contains only the trait and types
//! - Provider implementations are in `enact-providers` crate
//! - Dependency direction: `enact-providers` → `enact-core` (one-way, no circular deps)
//! - `enact-core` must NEVER depend on `enact-providers`
//!
//! **Import Boundaries:**
//! - `enact-providers` MUST NOT import from `enact_core::kernel`, `enact_core::flow`, or `enact_core::policy`
//! - Providers should only see:
//! - `ChatRequest` / `ChatResponse` (from `enact_core::providers`)
//! - `EmbeddingRequest` / `EmbeddingResponse` (from `enact_core::providers`)
//! - Tool schemas (read-only)
//! - HTTP helper utilities (in `enact-providers` itself)
//!
//! If providers import forbidden modules, they will slowly grow "smart" and
//! violate the "replaceable adapter" principle.
//!
//! **Enforcement**: If you find yourself needing kernel/flow/policy types in
//! provider code, you are violating this invariant. Move that logic to the kernel.
//!
//! ## Usage
//!
//! To use provider implementations, depend on `enact-providers`:
//!
//! ```toml
//! [dependencies]
//! enact-core = { workspace = true }
//! enact-providers = { workspace = true, features = ["provider-azure"] }
//! ```
//!
//! Then import:
//!
//! ```rust,ignore
//! use enact_core::providers::ModelProvider; // Trait from enact-core
//! use enact_providers::AzureOpenAI; // Implementation from enact-providers
//!
//! // Chat completion
//! let response = provider.chat(request).await?;
//!
//! // Embedding generation (if supported)
//! let embedding = provider.embed(embedding_request).await?;
//! ```
// Re-export trait and types
pub use r#trait::;