use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ExecutionMode {
InSandbox,
OutSandbox,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SpaceAccessMode {
ReadOnly,
ReadWrite,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SandboxPlacement {
Computer(String),
ProviderPool(String),
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct SandboxMountSpec {
pub alias: String,
pub space_id: String,
pub mode: SpaceAccessMode,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub path_prefix: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct WorkspaceSpec {
pub provider: String,
pub placement: SandboxPlacement,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub template_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub template_version: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub image_snapshot_id: Option<String>,
#[serde(default)]
pub mounts: Vec<SandboxMountSpec>,
pub ttl_ms: u64,
#[serde(default)]
pub profile: BTreeMap<String, String>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct AgentSpec {
pub entrypoint: String,
#[serde(default)]
pub env: BTreeMap<String, String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct ExecutionSpec {
pub mode: ExecutionMode,
pub workspace: WorkspaceSpec,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub agent: Option<AgentSpec>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum TraceLevel {
Driver,
Runtime,
}
impl TraceLevel {
pub const fn satisfies(self, required: Self) -> bool {
(self as u8) >= (required as u8)
}
pub const fn as_str(self) -> &'static str {
match self {
Self::Driver => "driver",
Self::Runtime => "runtime",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct EvalTurn {
pub user: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct VerifyCommand {
pub name: String,
pub command: String,
#[serde(default)]
pub expected_exit_code: i32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct EvalBudget {
pub timeout_ms: u64,
pub max_output_bytes: usize,
pub max_cost_micros: u64,
}
impl Default for EvalBudget {
fn default() -> Self {
Self {
timeout_ms: 300_000,
max_output_bytes: 8 * 1024 * 1024,
max_cost_micros: 0,
}
}
}
#[cfg(test)]
mod tests {
use super::TraceLevel;
#[test]
fn runtime_trace_satisfies_driver_requirement_but_not_the_reverse() {
assert!(TraceLevel::Runtime.satisfies(TraceLevel::Driver));
assert!(TraceLevel::Runtime.satisfies(TraceLevel::Runtime));
assert!(TraceLevel::Driver.satisfies(TraceLevel::Driver));
assert!(!TraceLevel::Driver.satisfies(TraceLevel::Runtime));
}
}