use std::collections::HashMap;
use crate::api::registry::{ExecutionIntercept, Guardrail, Intercept};
use crate::api::runtime::{
EventSubscriberFn, LlmConditionalFn, LlmExecutionFn, LlmRequestInterceptFn,
LlmSanitizeRequestFn, LlmSanitizeResponseFn, LlmStreamExecutionFn, ToolConditionalFn,
ToolExecutionFn, ToolInterceptFn, ToolSanitizeFn,
};
use crate::registry::SortedRegistry;
pub(crate) struct ScopeLocalRegistries {
pub(crate) tool_sanitize_request_guardrails: SortedRegistry<Guardrail<ToolSanitizeFn>>,
pub(crate) tool_sanitize_response_guardrails: SortedRegistry<Guardrail<ToolSanitizeFn>>,
pub(crate) tool_conditional_execution_guardrails: SortedRegistry<Guardrail<ToolConditionalFn>>,
pub(crate) tool_request_intercepts: SortedRegistry<Intercept<ToolInterceptFn>>,
pub(crate) tool_execution_intercepts: SortedRegistry<ExecutionIntercept<ToolExecutionFn>>,
pub(crate) llm_sanitize_request_guardrails: SortedRegistry<Guardrail<LlmSanitizeRequestFn>>,
pub(crate) llm_sanitize_response_guardrails: SortedRegistry<Guardrail<LlmSanitizeResponseFn>>,
pub(crate) llm_conditional_execution_guardrails: SortedRegistry<Guardrail<LlmConditionalFn>>,
pub(crate) llm_request_intercepts: SortedRegistry<Intercept<LlmRequestInterceptFn>>,
pub(crate) llm_execution_intercepts: SortedRegistry<ExecutionIntercept<LlmExecutionFn>>,
pub(crate) llm_stream_execution_intercepts:
SortedRegistry<ExecutionIntercept<LlmStreamExecutionFn>>,
pub(crate) event_subscribers: HashMap<String, EventSubscriberFn>,
}
impl ScopeLocalRegistries {
pub(crate) fn new() -> Self {
Self {
tool_sanitize_request_guardrails: SortedRegistry::new(),
tool_sanitize_response_guardrails: SortedRegistry::new(),
tool_conditional_execution_guardrails: SortedRegistry::new(),
tool_request_intercepts: SortedRegistry::new(),
tool_execution_intercepts: SortedRegistry::new(),
llm_sanitize_request_guardrails: SortedRegistry::new(),
llm_sanitize_response_guardrails: SortedRegistry::new(),
llm_conditional_execution_guardrails: SortedRegistry::new(),
llm_request_intercepts: SortedRegistry::new(),
llm_execution_intercepts: SortedRegistry::new(),
llm_stream_execution_intercepts: SortedRegistry::new(),
event_subscribers: HashMap::new(),
}
}
}
impl Default for ScopeLocalRegistries {
fn default() -> Self {
Self::new()
}
}
pub(crate) fn merge_guardrail_entries<'a, F>(
global: &'a SortedRegistry<Guardrail<F>>,
scope_locals: &'a [&'a SortedRegistry<Guardrail<F>>],
) -> Vec<&'a Guardrail<F>> {
let mut all = Vec::new();
all.extend(global.sorted_values());
for registry in scope_locals {
all.extend(registry.sorted_values());
}
all.sort_by_key(|entry| entry.priority);
all
}
pub(crate) fn merge_intercept_entries<'a, F>(
global: &'a SortedRegistry<Intercept<F>>,
scope_locals: &'a [&'a SortedRegistry<Intercept<F>>],
) -> Vec<&'a Intercept<F>> {
let mut all = Vec::new();
all.extend(global.sorted_values());
for registry in scope_locals {
all.extend(registry.sorted_values());
}
all.sort_by_key(|entry| entry.priority);
all
}
pub(crate) fn merge_execution_intercept_callables<F: Clone>(
global: &SortedRegistry<ExecutionIntercept<F>>,
scope_locals: &[&SortedRegistry<ExecutionIntercept<F>>],
) -> Vec<(F, i32)> {
let mut all = Vec::new();
for entry in global.sorted_values() {
all.push((entry.payload.clone(), entry.priority));
}
for registry in scope_locals {
for entry in registry.sorted_values() {
all.push((entry.payload.clone(), entry.priority));
}
}
all.sort_by_key(|(_, priority)| *priority);
all
}