use serde::{Deserialize, Serialize};
use std::collections::HashMap;
pub use akribes_types::ast::{TypeField, TypeRef};
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Project {
pub id: i64,
pub name: String,
pub created_at: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Script {
pub id: i64,
pub project_id: i64,
pub name: String,
pub created_at: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ScriptVersion {
pub id: i64,
pub script_id: i64,
pub source: String,
pub label: Option<String>,
pub published_by: Option<String>,
pub created_at: String,
}
#[derive(Deserialize, Clone, Debug)]
pub(crate) struct PublishResponse {
pub version: ScriptVersion,
#[serde(default)]
pub rebased: Option<Vec<RebaseEntry>>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct RebaseEntry {
pub kind: String,
pub count: usize,
}
#[derive(Clone, Debug)]
pub struct PublishOutcome {
pub version: ScriptVersion,
pub rebased: Option<Vec<RebaseEntry>>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ScriptChannel {
pub id: i64,
pub script_id: i64,
pub name: String,
pub version_id: Option<i64>,
pub updated_at: Option<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Draft {
pub source: String,
#[serde(deserialize_with = "draft_de::deserialize_inputs")]
pub inputs: Vec<(String, String)>,
#[serde(default)]
pub type_defs: serde_json::Value,
}
mod draft_de {
use serde::de::Error as _;
use serde::{Deserialize, Deserializer};
pub(super) fn deserialize_inputs<'de, D>(d: D) -> Result<Vec<(String, String)>, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
#[serde(untagged)]
enum InputEntry {
Tuple(String, String),
Object(InputObject),
}
#[derive(Deserialize)]
struct InputObject {
name: String,
#[serde(alias = "type")]
ty: serde_json::Value,
#[serde(default)]
#[allow(dead_code)]
docs: Option<String>,
}
let raw: Vec<InputEntry> = Vec::deserialize(d)?;
raw.into_iter()
.map(|e| match e {
InputEntry::Tuple(name, ty) => Ok((name, ty)),
InputEntry::Object(o) => {
let display = type_display(&o.ty).ok_or_else(|| {
D::Error::custom(format!(
"input '{}' has unexpected `ty` shape: {}",
o.name, o.ty
))
})?;
Ok((o.name, display))
}
})
.collect()
}
fn type_display(v: &serde_json::Value) -> Option<String> {
if let Some(s) = v.as_str() {
return Some(s.to_string());
}
let obj = v.as_object()?;
if let Some(arr) = obj.get("variants").and_then(|v| v.as_array()) {
let arms: Vec<String> = arr.iter().filter_map(type_display).collect();
if arms.len() == arr.len() {
return Some(arms.join(" | "));
}
}
if let Some(arr) = obj.get("choices").and_then(|v| v.as_array()) {
let arms: Vec<String> = arr
.iter()
.filter_map(|c| c.as_str().map(|s| format!("\"{s}\"")))
.collect();
if arms.len() == arr.len() {
return Some(arms.join(" | "));
}
}
let name = obj.get("name").and_then(|n| n.as_str())?;
if let Some(inner) = obj
.get("inner")
.and_then(|i| if i.is_null() { None } else { Some(i) })
{
if let Some(inner_display) = type_display(inner) {
return Some(format!("{name}[{inner_display}]"));
}
}
Some(name.to_string())
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct LatestVersion {
pub id: i64,
pub script_id: i64,
pub source: String,
pub label: Option<String>,
pub published_by: Option<String>,
pub created_at: String,
#[serde(default)]
pub inputs: Vec<(String, String)>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ConvertResult {
pub markdown: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub document_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub filename: Option<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(untagged)]
pub enum S3DocumentRef {
Presigned { presigned_url: String },
Credentials {
bucket: String,
key: String,
#[serde(skip_serializing_if = "Option::is_none")]
region: Option<String>,
access_key_id: String,
secret_access_key: String,
#[serde(skip_serializing_if = "Option::is_none")]
session_token: Option<String>,
},
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct DocumentRef {
pub document_id: String,
pub filename: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct DocumentMeta {
pub id: String,
pub filename: String,
pub content_type: String,
pub size_bytes: i64,
pub content_hash: String,
pub conversion_status: String,
pub conversion_error: Option<String>,
pub created_at: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct RunResult {
pub execution_id: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ExecutionStatus {
pub id: String,
pub project_id: i64,
pub script_name: String,
pub status: String,
pub started_at: Option<String>,
pub finished_at: Option<String>,
pub version_id: Option<i64>,
pub channel: Option<String>,
pub error: Option<String>,
pub error_kind: Option<String>,
pub result: Option<serde_json::Value>,
pub documents: Option<serde_json::Value>,
pub triggered_by: Option<String>,
#[serde(default)]
pub input_tokens: i64,
#[serde(default)]
pub output_tokens: i64,
#[serde(default)]
pub tool_tokens: i64,
pub cost_usd: Option<f64>,
#[serde(default)]
pub result_type: Option<TypeRef>,
#[serde(default)]
pub type_defs: Option<serde_json::Value>,
#[serde(default)]
pub parent_execution_id: Option<String>,
#[serde(default)]
pub parent_node_id: Option<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ExecutionOutput {
pub status: String,
pub error: Option<String>,
pub error_kind: Option<String>,
pub result: Option<serde_json::Value>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ExecutionChildSummary {
pub id: String,
pub parent_node_id: Option<String>,
pub status: String,
pub started_at: Option<String>,
pub finished_at: Option<String>,
pub script_name: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ExecutionTaskSummary {
pub task_name: String,
pub model: Option<String>,
pub provider: Option<String>,
pub input_tokens: i64,
pub output_tokens: i64,
pub cached_input_tokens: i64,
pub cache_write_input_tokens: i64,
pub cost_usd: Option<f64>,
pub duration_ms: Option<i64>,
pub attempt: i32,
pub finished_at: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ExecutionTasksResponse {
pub execution_id: String,
pub tasks: Vec<ExecutionTaskSummary>,
}
pub use akribes_types::event::{EngineEvent, TokenUsage};
pub(crate) fn engine_event_type_name(evt: &EngineEvent) -> &'static str {
match evt {
EngineEvent::Log(_) => "Log",
EngineEvent::LogLevel { .. } => "LogLevel",
EngineEvent::StateUpdate(..) => "StateUpdate",
EngineEvent::WorkflowStart(_) => "WorkflowStart",
EngineEvent::TaskStart(..) => "TaskStart",
EngineEvent::TaskPrompt(..) => "TaskPrompt",
EngineEvent::TaskEnd { .. } => "TaskEnd",
EngineEvent::AgentOutput { .. } => "AgentOutput",
EngineEvent::AgentReasoning { .. } => "AgentReasoning",
EngineEvent::Suspended { .. } => "Suspended",
EngineEvent::Resumed { .. } => "Resumed",
EngineEvent::WorkflowEnd(akribes_types::event::WorkflowEndPayload { value: _, .. }) => {
"WorkflowEnd"
}
EngineEvent::Error { .. } => "Error",
EngineEvent::NodeStart(..) => "NodeStart",
EngineEvent::NodeEnd { .. } => "NodeEnd",
EngineEvent::Breakpoint { .. } => "Breakpoint",
EngineEvent::BreakpointResumed { .. } => "BreakpointResumed",
EngineEvent::ToolCallStart { .. } => "ToolCallStart",
EngineEvent::ToolCallEnd { .. } => "ToolCallEnd",
EngineEvent::McpServerDegraded { .. } => "McpServerDegraded",
EngineEvent::McpServerRecovered { .. } => "McpServerRecovered",
EngineEvent::ToolApprovalPending { .. } => "ToolApprovalPending",
EngineEvent::ToolApprovalResolved { .. } => "ToolApprovalResolved",
EngineEvent::ToolApprovalSkipped { .. } => "ToolApprovalSkipped",
EngineEvent::ToolReplayUncertain { .. } => "ToolReplayUncertain",
EngineEvent::LLMReplayCacheHit { .. } => "LLMReplayCacheHit",
EngineEvent::VerificationStart { .. } => "VerificationStart",
EngineEvent::VerificationResult { .. } => "VerificationResult",
EngineEvent::ValidationFailure { .. } => "ValidationFailure",
EngineEvent::SubScript { .. } => "SubScript",
EngineEvent::CachePlanned { .. } => "CachePlanned",
EngineEvent::LoopStart { .. } => "LoopStart",
EngineEvent::LoopTurn { .. } => "LoopTurn",
EngineEvent::LoopEnd { .. } => "LoopEnd",
EngineEvent::ContextCompacted { .. } => "ContextCompacted",
EngineEvent::ContextOverflow { .. } => "ContextOverflow",
EngineEvent::TaskCacheHit { .. } => "TaskCacheHit",
EngineEvent::LLMResponse { .. } => "LLMResponse",
EngineEvent::SubScriptSpawned { .. } => "SubScriptSpawned",
EngineEvent::SubScriptResult { .. } => "SubScriptResult",
EngineEvent::CheckpointResolution { .. } => "CheckpointResolution",
EngineEvent::RuntimeStart { .. } => "RuntimeStart",
EngineEvent::RuntimeStdout { .. } => "RuntimeStdout",
EngineEvent::RuntimeStderr { .. } => "RuntimeStderr",
EngineEvent::RuntimeEnd { .. } => "RuntimeEnd",
EngineEvent::RuntimeError { .. } => "RuntimeError",
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ExecutionEvents {
pub execution_id: String,
pub status: String,
pub complete: bool,
pub events: Vec<EngineEvent>,
#[serde(default)]
pub next_after_id: Option<i64>,
#[serde(default)]
pub has_more: bool,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct VersionCost {
pub version_id: Option<i64>,
pub executions: i64,
pub avg_cost_usd: f64,
pub total_cost_usd: f64,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ProjectCost {
pub project_id: i64,
pub total_executions: i64,
pub total_cost_usd: f64,
pub avg_cost_usd: f64,
pub total_input_tokens: i64,
pub total_output_tokens: i64,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct CostAggregation {
pub total_executions: i64,
pub total_cost_usd: f64,
pub avg_cost_usd: f64,
pub total_input_tokens: i64,
pub total_output_tokens: i64,
#[serde(default)]
pub total_tool_tokens: i64,
#[serde(default)]
pub by_version: Vec<VersionCost>,
}
pub type ScriptCost = CostAggregation;
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct GraphNode {
pub id: usize,
pub op_type: String,
pub op_name: Option<String>,
pub target_var: Option<String>,
pub reads: Vec<String>,
pub line: usize,
pub col: usize,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct GraphEdge {
pub from: usize,
pub to: usize,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct GraphResponse {
pub nodes: Vec<GraphNode>,
pub edges: Vec<GraphEdge>,
}
pub type ScriptGraph = GraphResponse;
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(tag = "type", content = "payload")]
pub enum RegistryEvent {
ProjectCreated(Project),
ProjectUpdated(Project),
ProjectDeleted(i64),
ScriptCreated {
project_id: i64,
script: Script,
},
ScriptUpdated {
project_id: i64,
script_name: String,
version_id: i64,
#[serde(default)]
channel: Option<String>,
},
ScriptDeleted {
project_id: i64,
script_name: String,
},
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(tag = "type", content = "payload")]
pub enum BenchEvent {
RunStarted {
project_id: i64,
script_name: String,
run: BenchRun,
},
ResultRecorded {
project_id: i64,
script_name: String,
run_id: i64,
result: BenchResult,
},
RunFinished {
project_id: i64,
script_name: String,
run: BenchRun,
},
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(tag = "type", content = "payload")]
pub enum HubEvent {
Execution {
project_id: i64,
script_name: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
execution_id: Option<String>,
event: EngineEvent,
#[serde(default, skip_serializing_if = "Option::is_none")]
seq: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
at: Option<String>,
},
Registry(RegistryEvent),
Bench(BenchEvent),
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct PutDraftResponse {
#[serde(default)]
pub schema_warnings: Vec<ContractWarning>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ContractWarning {
pub client_id: String,
pub client_name: String,
pub channel: String,
pub mismatch: SchemaMismatch,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct DryRunResult {
pub dry_run: bool,
pub would_break: i64,
pub breaking_interests: Vec<BreakingInterest>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct BreakingInterest {
pub client_id: String,
pub client_name: String,
pub channel: String,
pub lifetime: String,
pub mismatch: SchemaMismatch,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ClientInfo {
pub id: String,
pub name: String,
pub last_seen: String,
#[serde(default)]
pub scripts: Vec<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ClientInterest {
pub script_name: String,
pub inputs: HashMap<String, String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub channel: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub lifetime: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub strict: Option<bool>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct RegisteredInterest {
pub script_name: String,
pub channel: String,
pub bound_version_id: Option<i64>,
#[serde(default)]
pub input_schema: Vec<(String, String)>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct RegisterClientResponse {
#[serde(default)]
pub interests: Vec<RegisteredInterest>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct SchemaMismatch {
#[serde(default)]
pub missing: Vec<(String, String)>,
#[serde(default)]
pub wrong_type: Vec<(String, String, String)>,
#[serde(default)]
pub extra: Vec<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ContractLockInfo {
pub id: i64,
pub client_id: String,
pub client_name: String,
pub script_name: String,
pub channel: String,
pub bound_version_id: Option<i64>,
pub lifetime: String,
pub drifted: bool,
pub created_by: Option<String>,
pub created_at: String,
pub input_schema: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct TokenScopes {
pub projects: ProjectScope,
pub role: TokenRole,
#[serde(skip_serializing_if = "Option::is_none")]
pub scripts: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub executions: Option<Vec<String>>,
#[serde(default)]
pub can_mint: bool,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub features: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub org_id: Option<i64>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(untagged)]
pub enum ProjectScope {
Wildcard(WildcardMarker),
Specific(Vec<i64>),
}
#[derive(Clone, Debug)]
pub struct WildcardMarker;
impl Serialize for WildcardMarker {
fn serialize<S: serde::Serializer>(
&self,
serializer: S,
) -> std::result::Result<S::Ok, S::Error> {
serializer.serialize_str("*")
}
}
impl<'de> Deserialize<'de> for WildcardMarker {
fn deserialize<D: serde::Deserializer<'de>>(
deserializer: D,
) -> std::result::Result<Self, D::Error> {
let s = String::deserialize(deserializer)?;
if s == "*" {
Ok(WildcardMarker)
} else {
Err(serde::de::Error::custom("expected \"*\""))
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "lowercase")]
pub enum TokenRole {
Admin,
Editor,
Viewer,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct TokenInfo {
pub id: String,
pub label: String,
pub user_email: Option<String>,
pub scopes: TokenScopes,
pub minted_by: String,
pub expires_at: String,
pub revoked: bool,
pub created_at: String,
pub last_used_at: Option<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct MintTokenResponse {
pub token: String,
pub token_id: String,
pub expires_at: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct MintTokenRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub user_email: Option<String>,
pub scopes: TokenScopes,
pub expires_in: i64,
pub label: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct RevokeByEmailResponse {
pub revoked: i64,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct AdhocRunResult {
pub execution_id: String,
pub project_id: i64,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "lowercase")]
pub enum McpOrigin {
Env,
Script,
Db,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct McpServerSummary {
pub alias: String,
pub url: String,
pub origin: McpOrigin,
pub is_registry: bool,
pub status: String,
pub tool_count: i64,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct McpToolSummary {
pub qualified_name: String,
pub server_alias: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
pub input_schema: serde_json::Value,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct McpHealth {
pub status: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub last_error: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub last_check_at: Option<String>,
}
#[derive(Deserialize, Clone, Debug)]
pub(crate) struct SandboxProjectIdResponse {
pub project_id: i64,
}
#[derive(Serialize)]
pub(crate) struct RegisterRequest {
pub id: String,
pub name: String,
pub interests: Vec<ClientInterest>,
}
#[derive(Serialize)]
pub(crate) struct HeartbeatRequest {
pub client_id: String,
}
#[derive(Serialize, Default)]
pub(crate) struct RunRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub inputs: Option<HashMap<String, serde_json::Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub triggered_by: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub breakpoint_lines: Option<Vec<usize>>,
}
#[derive(Serialize)]
pub(crate) struct CreateProjectRequest<'a> {
pub name: &'a str,
}
#[derive(Serialize)]
pub(crate) struct UpdateProjectRequest<'a> {
pub name: &'a str,
}
#[derive(Serialize)]
pub(crate) struct CreateScriptBody<'a> {
pub source: &'a str,
}
#[derive(Serialize)]
pub(crate) struct RenameScriptRequest<'a> {
pub new_name: &'a str,
}
#[derive(Serialize)]
pub(crate) struct MoveScriptRequest {
pub target_project_id: i64,
}
#[derive(Serialize)]
pub(crate) struct ReorderRequest {
pub order: Vec<i64>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct McpRefreshResult {
pub refreshed: bool,
pub alias: String,
pub tool_count: usize,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct McpDriftResult {
pub drifted: bool,
#[serde(default)]
pub added: Vec<String>,
#[serde(default)]
pub removed: Vec<String>,
#[serde(default)]
pub reason: Option<String>,
}
#[derive(Serialize)]
pub(crate) struct PutDraftRequest<'a> {
pub source: &'a str,
}
#[derive(Serialize, Default)]
pub(crate) struct PublishRequest {
pub channels: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub label: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub published_by: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub force: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub dry_run: Option<bool>,
}
#[derive(Serialize)]
pub(crate) struct CreateChannelRequest<'a> {
pub name: &'a str,
}
#[derive(Serialize)]
pub(crate) struct MoveChannelRequest {
pub version_id: i64,
#[serde(skip_serializing_if = "Option::is_none")]
pub force: Option<bool>,
}
#[derive(Serialize)]
pub(crate) struct RebindLockRequest {
pub version_id: Option<i64>,
}
#[derive(Serialize)]
pub(crate) struct AdhocRunRequest<'a> {
pub source: &'a str,
#[serde(skip_serializing_if = "Option::is_none")]
pub inputs: Option<HashMap<String, serde_json::Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub breakpoint_lines: Option<Vec<usize>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub channel: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub triggered_by: Option<&'a str>,
}
#[derive(Serialize)]
pub(crate) struct ResumeRequest {
pub token: String,
pub data: serde_json::Value,
}
#[derive(Serialize)]
pub(crate) struct RunWithS3Request {
pub inputs: HashMap<String, S3DocumentRef>,
#[serde(skip_serializing_if = "Option::is_none")]
pub channel: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub triggered_by: Option<String>,
}
#[derive(Serialize, Default)]
pub(crate) struct RunFromRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub inputs: Option<HashMap<String, serde_json::Value>>,
pub seed_env: HashMap<String, serde_json::Value>,
pub skip_node_ids: Vec<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub triggered_by: Option<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ConversionStatus {
Text,
Ready,
Converting,
Pending,
Failed,
#[serde(other)]
Unknown,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct UploadResult {
pub document_id: String,
pub filename: String,
pub content_hash: String,
pub conversion_status: ConversionStatus,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct IngestProgress {
pub done: u32,
pub total: u32,
}
#[derive(Deserialize)]
#[serde(tag = "state", rename_all = "snake_case")]
pub(crate) enum ProgressResponseWire {
Converting { done_pages: u32, total_pages: u32 },
Idle,
}
#[derive(Clone, Debug)]
pub enum ClaimOutcome {
Hit(UploadResult),
Miss,
}
#[derive(Serialize)]
pub(crate) struct ClaimRequest<'a> {
pub content_hash: &'a str,
pub filename: &'a str,
}
#[derive(Deserialize)]
#[serde(tag = "status", rename_all = "snake_case")]
pub(crate) enum ClaimResponseWire {
Hit {
document_id: String,
filename: String,
content_hash: String,
conversion_status: ConversionStatus,
},
Miss,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Bench {
pub id: i64,
pub script_id: i64,
#[serde(default)]
pub judge_script_id: Option<i64>,
pub judge_channel: String,
pub config: serde_json::Value,
pub created_at: String,
pub updated_at: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ProjectBenchSummary {
pub bench_id: i64,
pub script_id: i64,
pub script_name: String,
#[serde(default)]
pub judge_script_id: Option<i64>,
#[serde(default)]
pub judge_script_name: Option<String>,
pub judge_channel: String,
pub case_count: i64,
#[serde(default)]
pub latest_run_id: Option<i64>,
#[serde(default)]
pub latest_run_status: Option<String>,
#[serde(default)]
pub latest_run_channel: Option<String>,
#[serde(default)]
pub latest_run_workflow_version_id: Option<i64>,
#[serde(default)]
pub latest_run_at: Option<String>,
#[serde(default)]
pub latest_run_mean_score: Option<f64>,
#[serde(default)]
pub latest_run_cost_usd: Option<f64>,
pub updated_at: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct BenchRun {
pub id: i64,
pub bench_id: i64,
pub channel: String,
pub workflow_version_id: i64,
pub judge_version_id: i64,
pub status: String,
#[serde(default)]
pub triggered_by: Option<String>,
pub triggered_at: String,
#[serde(default)]
pub completed_at: Option<String>,
#[serde(default)]
pub total_cost_usd: f64,
#[serde(default)]
pub total_cases: i32,
#[serde(default)]
pub cache_hit_cases: i32,
#[serde(default)]
pub notes: Option<String>,
#[serde(default)]
pub mcp_session_id: Option<String>,
#[serde(default)]
pub case_filter: Option<Vec<String>>,
#[serde(default)]
pub mean_headline_score: Option<f64>,
#[serde(default)]
pub ok_cases: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub status_breakdown: Option<std::collections::HashMap<String, i64>>,
#[serde(default)]
pub judge_script_name: Option<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct BenchResult {
pub id: i64,
pub bench_run_id: i64,
pub case_id: String,
#[serde(default)]
pub workflow_execution_id: Option<String>,
#[serde(default)]
pub judge_execution_id: Option<String>,
#[serde(default)]
pub score: Option<serde_json::Value>,
#[serde(default)]
pub headline_score: Option<f64>,
pub status: String,
#[serde(default)]
pub cost_usd: f64,
#[serde(default)]
pub duration_ms: Option<i32>,
#[serde(default)]
pub cache_hit: bool,
#[serde(default)]
pub input_hash: Option<String>,
#[serde(default)]
pub error: Option<String>,
pub created_at: String,
#[serde(default)]
pub workflow_output: Option<serde_json::Value>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct BenchCase {
pub id: String,
pub project_id: i64,
pub script_name: String,
#[serde(default)]
pub bench_id: Option<i64>,
pub kind: String,
pub frozen: bool,
#[serde(default)]
pub case_name: Option<String>,
#[serde(default)]
pub inputs: Option<serde_json::Value>,
#[serde(default)]
pub expected_output: Option<serde_json::Value>,
#[serde(default)]
pub ground_truth: Option<serde_json::Value>,
#[serde(default)]
pub input_hash: Option<String>,
pub created_at: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct CompareCase {
pub case_id: String,
pub case_label: String,
#[serde(default)]
pub score_a: Option<f64>,
#[serde(default)]
pub score_b: Option<f64>,
#[serde(default)]
pub delta: Option<f64>,
pub flag: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct CompareAggregate {
pub mean_score_delta: f64,
pub cost_delta_usd: f64,
pub n_regressed: i32,
pub n_improved: i32,
pub n_unchanged: i32,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct CompareReport {
pub run_a_id: i64,
pub run_b_id: i64,
pub aggregate: CompareAggregate,
pub per_case: Vec<CompareCase>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct DriftedCase {
pub case_id: String,
pub label: String,
pub what_broke: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct DriftReport {
pub drifted: Vec<DriftedCase>,
#[serde(default)]
pub script_version_id: Option<i64>,
#[serde(default)]
pub published_at: Option<String>,
#[serde(default)]
pub published_by: Option<String>,
pub summary: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct BenchRunTagSessionResponse {
pub tagged: bool,
pub run_id: i64,
pub mcp_session_id: String,
}
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct CreateOrUpdateBenchRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub judge_script_id: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub judge_channel: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub config: Option<serde_json::Value>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct CreateBenchCaseRequest {
pub inputs: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub expected_output: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ground_truth: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct PatchBenchCaseRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub inputs: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expected_output: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ground_truth: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct PromoteCaseEdits {
#[serde(skip_serializing_if = "Option::is_none")]
pub inputs: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expected_output: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ground_truth: Option<serde_json::Value>,
}
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct PromoteExecutionRequest {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub edits: Option<PromoteCaseEdits>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct TriggerBenchRunRequest {
pub channel: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub notes: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub case_ids: Option<Vec<String>>,
}
#[derive(Clone, Debug)]
pub enum BenchRunEvent {
Result(Box<BenchResult>),
Lagged { dropped: u64 },
Terminal { status: String },
}