forge-provider-session
Provider session model, policy, and runtime routing for the Forge SDK
Provider session model, policy, and runtime routing for the Forge SDK
Package contract
| Field | Value |
|---|---|
| Language | rust |
| Source version | 0.2.0 |
| Manifest | forge-rs/crates/forge-provider-session/Cargo.toml |
| Source files | 4 |
| Evidence | Source reference; registry publication and runtime conformance are separate checks |
Import boundary
use forge_provider_session;Use a source checkout or your verified private registry. Manifest coordinates identify the package; they do not establish that a public registry release exists.
Crate boundary
The following entries are taken from src/lib.rs. Feature conditions in the exact source still apply.
pub mod error;
pub mod policy;
pub mod session;
pub use error::{ProviderSessionError, ProviderSessionResult};
pub use policy::{
PolicyDecision, PolicyEngine, ProviderType, SessionPolicy, SessionPolicyBuilder,
TaskRoutingRule,
};
pub use session::{
ProviderSession, SessionConfig, SessionId, SessionManager, SessionState, SwapOutcome,
};Source reference
Download package reference JSON. Each original source file and generated declaration artifact has its own SHA-256 digest. Function bodies and constant values are omitted from downloads. These are source declaration inventories, not compiler-resolved rustdoc, TypeDoc, DocC, or Dokka output. Private modules can contain public declarations that are not reachable through the package boundary; consult the entry point before importing.
error.rs
Read declaration text · 2 declaration entries
#[derive(Debug, Error)]
pub enum ProviderSessionError {
/// The requested provider is not allowed by the active session policy.
#[error(
"provider '{provider_ref}' is not allowed by session policy '{policy_name}': {reason}"
)]
ProviderNotAllowed {
/// The provider reference that was denied.
provider_ref: String,
/// The name of the policy that denied the request.
policy_name: String,
/// Human-readable explanation of why the provider was denied.
reason: String,
},
/// A session was not found for the given ID.
#[error("session '{session_id}' not found in session manager")]
SessionNotFound {
/// The session ID that was looked up.
session_id: String,
},
/// An invalid session state transition was attempted.
#[error("invalid session transition from {from:?} to {to:?}: {reason}")]
InvalidSessionTransition {
/// The current session state.
from: super::session::SessionState,
/// The attempted target state.
to: super::session::SessionState,
/// Human-readable explanation of why the transition is invalid.
reason: String,
},
/// A session has expired and cannot be used.
#[error("session '{session_id}' expired at {expired_at}; create a new session")]
SessionExpired {
/// The expired session ID.
session_id: String,
/// When the session expired (ISO 8601).
expired_at: String,
},
/// A runtime provider swap was attempted but the policy forbids it.
#[error(
"runtime provider swap from '{from_provider}' to '{to_provider}' denied by policy '{policy_name}': runtime swapping is disabled"
)]
RuntimeSwapDenied {
/// The current provider.
from_provider: String,
/// The requested new provider.
to_provider: String,
/// The policy that denied the swap.
policy_name: String,
},
/// No default provider is configured in the session policy.
#[error("no default provider configured in session policy '{policy_name}'; set a default_provider in the SessionPolicy")]
NoDefaultProvider {
/// The policy that lacks a default provider.
policy_name: String,
},
/// The session policy is invalid.
#[error("invalid session policy: {reason}")]
InvalidPolicy {
/// What is wrong with the policy.
reason: String,
},
/// A Forge core error occurred.
#[error("forge core error: {0}")]
ForgeCore(#[from] forge_core::error::ForgeError),
}
pub type ProviderSessionResult<T> = Result<T, ProviderSessionError>;lib.rs
Read declaration text · 6 declaration entries
pub mod error;
pub mod policy;
pub mod session;
pub use error::{ProviderSessionError, ProviderSessionResult};
pub use policy::{
PolicyDecision, PolicyEngine, ProviderType, SessionPolicy, SessionPolicyBuilder,
TaskRoutingRule,
};
pub use session::{
ProviderSession, SessionConfig, SessionId, SessionManager, SessionState, SwapOutcome,
};policy.rs
Read declaration text · 32 declaration entries
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ProviderType {
/// Direct model provider (Anthropic, OpenAI, Google, etc.).
DirectModel,
/// Local model provider (Ollama, llama.cpp, etc.).
Local,
/// Routed through a gateway (Foundry, OpenRouter, etc.).
Routed,
/// Coding subscription provider (Claude Code, Codex, etc.).
CodingSubscription,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct TaskRoutingRule {
/// If set, this rule only matches the given task mode.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub task_mode: Option<TaskMode>,
/// If set, this rule only matches the given domain string.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub domain: Option<String>,
/// The provider to use when this rule matches.
pub provider_ref: String
}
pub fn matches_mode(&self, mode: &TaskMode) -> bool;
pub fn matches_domain(&self, domain: &str) -> bool;
pub fn matches(&self, task_mode: Option<&TaskMode>, domain: Option<&str>) -> bool;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SessionPolicy {
}
pub fn builder() -> SessionPolicyBuilder;
pub fn name(&self) -> &str;
pub fn default_provider(&self) -> Option<&str>;
pub fn is_provider_allowed(&self, provider_ref: &str) -> bool;
pub fn allow_runtime_swap(&self) -> bool;
pub fn session_ttl_seconds(&self) -> Option<u64>;
pub fn task_routing_rules(&self) -> &[TaskRoutingRule];
pub fn allowed_providers(&self) -> &[String];
pub fn open(name: impl Into<String>) -> Self;
#[derive(Debug, Default)]
pub struct SessionPolicyBuilder {
}
pub fn new() -> Self;
pub fn name(mut self, name: impl Into<String>) -> Self;
pub fn default_provider(mut self, provider_ref: impl Into<String>) -> Self;
pub fn allowed_provider(mut self, provider_ref: impl Into<String>) -> Self;
pub fn task_route(mut self, rule: TaskRoutingRule) -> Self;
pub fn allow_runtime_swap(mut self, allowed: bool) -> Self;
pub fn session_ttl_seconds(mut self, ttl: u64) -> Self;
pub fn build(self) -> ProviderSessionResult<SessionPolicy>;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PolicyDecision {
/// The selected provider reference.
pub provider_ref: String,
/// Human-readable explanation of why this provider was selected.
pub reason: String,
/// Whether runtime swapping is allowed under the current policy.
pub runtime_swap_allowed: bool
}
pub struct PolicyEngine {
}
pub fn new(policy: SessionPolicy) -> Self;
pub fn policy(&self) -> &SessionPolicy;
pub fn evaluate_default(&self) -> PolicyDecision;
pub fn evaluate(&self, task_mode: Option<&TaskMode>, domain: Option<&str>) -> PolicyDecision;
pub fn check_provider_allowed(&self, provider_ref: &str) -> ProviderSessionResult<()>;
pub fn check_runtime_swap_allowed(
&self,
from_provider: &str,
to_provider: &str,
) -> ProviderSessionResult<()>;session.rs
Read declaration text · 42 declaration entries
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct SessionId(String);
pub fn new() -> Self;
pub fn from_string(id: impl Into<String>) -> Self;
pub fn as_str(&self) -> &str;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SessionState {
/// Session has been created but not yet activated.
Created,
/// Session is active and accepting requests.
Active,
/// Session is temporarily paused (e.g., agent idle).
Paused,
/// Session is mid-swap to a different provider.
Switching,
/// Session has expired due to TTL or provider timeout.
Expired,
/// Session has been cleanly closed.
Closed,
}
pub fn can_transition_to(&self, target: SessionState) -> bool;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SessionConfig {
/// The agent that owns this session.
pub agent_id: String,
/// The initial provider to bind to.
pub initial_provider_ref: String,
/// Session TTL in seconds (overrides policy TTL if set).
pub ttl_seconds: Option<u64>,
/// Arbitrary metadata attached to the session.
pub metadata: HashMap<String, String>
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProviderSession {
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProviderSwapRecord {
/// The provider that was replaced.
pub from_provider: String,
/// The provider that replaced it.
pub to_provider: String,
/// When the swap occurred.
pub swapped_at: DateTime<Utc>,
/// Why the swap was initiated.
pub reason: String
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SwapOutcome {
/// The provider that was replaced.
pub previous_provider: String,
/// The new active provider.
pub new_provider: String,
/// Total number of swaps in this session's lifetime.
pub swap_count: usize
}
pub fn new(config: SessionConfig) -> Self;
pub fn id(&self) -> &SessionId;
pub fn agent_id(&self) -> &str;
pub fn provider_ref(&self) -> &str;
pub fn state(&self) -> SessionState;
pub fn created_at(&self) -> DateTime<Utc>;
pub fn last_active_at(&self) -> DateTime<Utc>;
pub fn expires_at(&self) -> Option<DateTime<Utc>>;
pub fn total_requests(&self) -> u64;
pub fn total_input_tokens(&self) -> u64;
pub fn total_output_tokens(&self) -> u64;
pub fn provider_history(&self) -> &[ProviderSwapRecord];
pub fn is_expired(&self) -> bool;
pub fn transition_to(&mut self, target: SessionState) -> ProviderSessionResult<()>;
pub fn activate(&mut self) -> ProviderSessionResult<()>;
pub fn record_request(&mut self, input_tokens: u64, output_tokens: u64);
pub fn swap_provider(
&mut self,
new_provider: impl Into<String>,
reason: impl Into<String>,
) -> ProviderSessionResult<SwapOutcome>;
pub fn close(&mut self) -> ProviderSessionResult<()>;
pub struct SessionManager {
}
pub fn new(engine: PolicyEngine) -> Self;
pub fn engine(&self) -> &PolicyEngine;
pub fn create_session(&mut self, config: SessionConfig) -> ProviderSessionResult<SessionId>;
pub fn create_default_session(
&mut self,
agent_id: impl Into<String>,
) -> ProviderSessionResult<SessionId>;
pub fn create_routed_session(
&mut self,
agent_id: impl Into<String>,
task_mode: Option<&TaskMode>,
domain: Option<&str>,
) -> ProviderSessionResult<(SessionId, PolicyDecision)>;
pub fn get_session(&self, session_id: &str) -> Option<&ProviderSession>;
pub fn get_session_mut(&mut self, session_id: &str) -> Option<&mut ProviderSession>;
pub fn activate_session(&mut self, session_id: &str) -> ProviderSessionResult<()>;
pub fn swap_provider(
&mut self,
session_id: &str,
new_provider: &str,
reason: &str,
) -> ProviderSessionResult<SwapOutcome>;
pub fn close_session(&mut self, session_id: &str) -> ProviderSessionResult<()>;
pub fn active_session_ids(&self) -> Vec<&str>;
pub fn session_count(&self) -> usize;
pub fn gc_sessions(&mut self) -> usize;