use std::collections::BTreeMap;
use std::sync::Arc;
use std::time::Duration;
use serde::{Deserialize, Serialize};
use crate::harness::store::StoreRegistry;
use crate::language::types::{Blueprint, Origin};
use crate::registry::CapabilityRegistry;
pub const RESERVED_VARIABLES: &[&str] =
&["context", "state", "messages", "history", "run", "answer"];
pub const RESERVED_FUNCTIONS: &[&str] = &[
"model_query",
"model_query_batched",
"agent_query",
"agent_query_batched",
"graph_run",
"graph_run_batched",
"graph_define",
"graph_validate",
"graph_compile",
"graph_diff",
"graph_register",
"tool_call",
"tool_call_batched",
"emit",
"show_vars",
"answer",
];
pub fn reserved_names() -> impl Iterator<Item = &'static str> {
RESERVED_VARIABLES
.iter()
.copied()
.chain(RESERVED_FUNCTIONS.iter().copied())
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ReplPolicy {
pub max_operations: u64,
pub max_iterations: usize,
pub max_script_bytes: usize,
pub max_output_bytes: usize,
pub max_model_calls: usize,
pub max_tool_calls: usize,
pub max_graph_calls: usize,
pub max_graph_definitions: usize,
pub max_depth: usize,
pub timeout: Option<Duration>,
pub max_concurrency: usize,
pub generated_graphs_require_review: bool,
}
impl Default for ReplPolicy {
fn default() -> Self {
Self {
max_operations: 1_000_000,
max_iterations: 16,
max_script_bytes: 64 * 1024,
max_output_bytes: 256 * 1024,
max_model_calls: 64,
max_tool_calls: 128,
max_graph_calls: 32,
max_graph_definitions: 8,
max_depth: 8,
timeout: Some(Duration::from_secs(30)),
max_concurrency: 4,
generated_graphs_require_review: true,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "type", content = "value")]
pub enum ReplValue {
Unit,
Bool(bool),
Int(i64),
Float(f64),
String(String),
Array(Vec<ReplValue>),
Map(BTreeMap<String, ReplValue>),
}
impl ReplValue {
pub fn to_json(&self) -> serde_json::Value {
match self {
ReplValue::Unit => serde_json::Value::Null,
ReplValue::Bool(b) => serde_json::Value::Bool(*b),
ReplValue::Int(i) => serde_json::Value::from(*i),
ReplValue::Float(f) => serde_json::Number::from_f64(*f)
.map(serde_json::Value::Number)
.unwrap_or(serde_json::Value::Null),
ReplValue::String(s) => serde_json::Value::String(s.clone()),
ReplValue::Array(items) => {
serde_json::Value::Array(items.iter().map(ReplValue::to_json).collect())
}
ReplValue::Map(map) => serde_json::Value::Object(
map.iter().map(|(k, v)| (k.clone(), v.to_json())).collect(),
),
}
}
pub fn byte_len(&self) -> usize {
serde_json::to_string(&self.to_json())
.map(|s| s.len())
.unwrap_or(0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ReplCallKind {
Model,
Tool,
Graph,
Agent,
Emit,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ReplCallRecord {
pub call_id: crate::harness::ids::CallId,
pub kind: ReplCallKind,
pub name: String,
pub detail: serde_json::Value,
pub elapsed: Duration,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ReplResult {
pub stdout: String,
pub value: Option<ReplValue>,
pub variables_changed: Vec<String>,
pub calls: Vec<ReplCallRecord>,
pub final_answer: Option<String>,
pub elapsed: Duration,
}
#[derive(Debug, Clone)]
pub struct GraphBlueprintHandle {
pub name: String,
pub source: String,
pub blueprint: Blueprint,
pub origin: Origin,
pub compiled: bool,
pub requires_review: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct LanguageCompiler {
pub provenance_label: String,
}
impl Default for LanguageCompiler {
fn default() -> Self {
Self {
provenance_label: "ragsh-generated".to_string(),
}
}
}
pub struct ReplCapabilities<State = ()>
where
State: Send + Sync,
{
pub registry: Arc<CapabilityRegistry<State>>,
pub stores: StoreRegistry,
pub language: Option<LanguageCompiler>,
}
impl<State: Send + Sync> ReplCapabilities<State> {
pub fn new(registry: Arc<CapabilityRegistry<State>>) -> Self {
Self {
registry,
stores: StoreRegistry::new(),
language: None,
}
}
pub fn with_language(mut self, language: LanguageCompiler) -> Self {
self.language = Some(language);
self
}
pub fn with_stores(mut self, stores: StoreRegistry) -> Self {
self.stores = stores;
self
}
pub fn models(&self) -> Vec<String> {
self.registry.names(crate::registry::ComponentKind::Model)
}
pub fn tools(&self) -> Vec<String> {
self.registry.names(crate::registry::ComponentKind::Tool)
}
pub fn graphs(&self) -> Vec<String> {
self.registry.names(crate::registry::ComponentKind::Graph)
}
pub fn agents(&self) -> Vec<String> {
self.registry.names(crate::registry::ComponentKind::Agent)
}
}
impl<State: Send + Sync> Default for ReplCapabilities<State> {
fn default() -> Self {
Self::new(Arc::new(CapabilityRegistry::new()))
}
}