use thiserror::Error;
use super::input::BufferTokensInput;
#[derive(Debug, Error, Clone, PartialEq)]
pub enum OmConfigError {
#[error("invalid observation.message_tokens: must be > 0")]
InvalidObservationMessageTokens,
#[error("invalid reflection.observation_tokens: must be > 0")]
InvalidReflectionObservationTokens,
#[error("invalid observation.bufferTokens ratio: must be in (0, 1)")]
InvalidObservationBufferTokensRatio,
#[error("invalid observation.bufferTokens absolute: must be > 0")]
InvalidObservationBufferTokensAbsolute,
#[error("observation.bufferTokens must resolve below message threshold")]
ObservationBufferTokensAtOrAboveThreshold,
#[error("invalid observation.bufferActivation: must be in (0, 1]")]
InvalidObservationBufferActivation,
#[error("invalid reflection.bufferActivation: must be in (0, 1]")]
InvalidReflectionBufferActivation,
#[error("invalid observation.blockAfter: must resolve >= message threshold")]
InvalidObservationBlockAfter,
#[error("invalid reflection.blockAfter: must resolve >= reflection threshold")]
InvalidReflectionBlockAfter,
#[error("invalid observation.maxTokensPerBatch: must be > 0")]
InvalidObservationMaxTokensPerBatch,
#[error(
"resource scope does not support async buffering; disable via observation.bufferTokens=Disabled"
)]
ResourceScopeAsyncBufferingUnsupported,
#[error(
"shareTokenBudget requires async buffering disabled via observation.bufferTokens=Disabled"
)]
ShareTokenBudgetRequiresAsyncDisabled,
}
pub(super) fn validate_observation_message_tokens(value: u32) -> Result<u32, OmConfigError> {
if value == 0 {
Err(OmConfigError::InvalidObservationMessageTokens)
} else {
Ok(value)
}
}
pub(super) fn validate_reflection_observation_tokens(value: u32) -> Result<u32, OmConfigError> {
if value == 0 {
Err(OmConfigError::InvalidReflectionObservationTokens)
} else {
Ok(value)
}
}
pub(super) fn validate_observation_max_tokens_per_batch(value: u32) -> Result<u32, OmConfigError> {
if value == 0 {
Err(OmConfigError::InvalidObservationMaxTokensPerBatch)
} else {
Ok(value)
}
}
pub(super) fn resolve_buffer_tokens(
raw: BufferTokensInput,
message_tokens: u32,
) -> Result<u32, OmConfigError> {
match raw {
BufferTokensInput::Disabled => Ok(0),
BufferTokensInput::Absolute(value) => {
if value == 0 {
return Err(OmConfigError::InvalidObservationBufferTokensAbsolute);
}
Ok(value)
}
BufferTokensInput::Ratio(value) => {
if !(value > 0.0 && value < 1.0) {
return Err(OmConfigError::InvalidObservationBufferTokensRatio);
}
let computed = ((message_tokens as f64) * value).round() as u32;
if computed == 0 {
return Err(OmConfigError::InvalidObservationBufferTokensAbsolute);
}
Ok(computed)
}
}
}
pub(super) fn resolve_block_after(
raw: f32,
threshold: u32,
invalid_error: OmConfigError,
) -> Result<u32, OmConfigError> {
if !raw.is_finite() {
return Err(invalid_error);
}
if (1.0..2.0).contains(&raw) {
return Ok(((threshold as f64) * f64::from(raw)).round() as u32);
}
if raw >= 2.0 {
return Ok(raw.round() as u32);
}
Err(invalid_error)
}
pub(super) fn validate_observation_activation(value: Option<f32>) -> Result<(), OmConfigError> {
if value.is_some_and(|activation| !(activation > 0.0 && activation <= 1.0)) {
return Err(OmConfigError::InvalidObservationBufferActivation);
}
Ok(())
}
pub(super) fn validate_reflection_activation(value: Option<f32>) -> Result<(), OmConfigError> {
if value.is_some_and(|activation| !(activation > 0.0 && activation <= 1.0)) {
return Err(OmConfigError::InvalidReflectionBufferActivation);
}
Ok(())
}