use std::path::PathBuf;
use serde::{Deserialize, Serialize};
use ts_rs::TS;
use crate::finding::FindingRecord;
use crate::trace::AgentTraceRecord;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TS)]
pub struct HealthResponse {
pub status: String,
pub version: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TS)]
pub struct SetupStatusResponse {
pub complete: bool,
pub config_path: String,
pub ai_runtime: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional)]
pub ai_provider: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional)]
pub ai_model: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional)]
pub ai_api_base: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional, type = "number | null")]
pub default_run_budget_usd_micros: Option<i64>,
pub sandbox_backend: String,
pub sandbox_enabled: bool,
pub sandbox_allow_network: bool,
pub ui_listen_addr: String,
pub ui_open_browser: bool,
pub log_level: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional)]
pub state_dir: Option<String>,
pub max_parallel_scans: u32,
pub scan_timeout_secs: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TS)]
pub struct SetupRequest {
pub ai_runtime: String,
#[serde(default)]
#[ts(optional)]
pub anthropic_api_key: Option<String>,
#[serde(default)]
#[ts(optional)]
pub local_llm_url: Option<String>,
#[serde(default)]
#[ts(optional)]
pub local_llm_token: Option<String>,
#[serde(default)]
#[ts(optional, type = "number | null")]
pub default_run_budget_usd_micros: Option<i64>,
pub sandbox_backend: String,
#[serde(default)]
pub i_own_this: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TS)]
pub struct DoctorRequest {
pub ai_runtime: String,
#[serde(default)]
#[ts(optional)]
pub anthropic_api_key: Option<String>,
#[serde(default)]
#[ts(optional)]
pub local_llm_url: Option<String>,
#[serde(default)]
#[ts(optional)]
pub local_llm_token: Option<String>,
pub sandbox_backend: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TS)]
pub struct DoctorCheck {
pub name: String,
pub passed: bool,
pub message: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TS)]
pub struct DoctorResponse {
pub checks: Vec<DoctorCheck>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TS)]
pub struct BundleManifest {
pub finding_id: String,
#[ts(type = "string")]
pub bundle_path: PathBuf,
pub sha256: String,
#[ts(type = "number")]
pub byte_size: u64,
pub artifacts: Vec<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, TS)]
#[serde(rename_all = "lowercase")]
pub enum FindingDiffStatus {
New,
Regressed,
Closed,
Unchanged,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TS)]
pub struct FindingWithDiff {
#[serde(flatten)]
pub record: FindingRecord,
pub diff_status: FindingDiffStatus,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TS)]
pub struct RunFindingsResponse {
pub run_id: String,
#[ts(type = "string | null")]
pub prior_run_id: Option<String>,
pub items: Vec<FindingWithDiff>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, TS)]
#[serde(rename_all = "snake_case")]
pub enum QuarantineKind {
Finding,
Candidate,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TS)]
pub struct QuarantineItem {
pub kind: QuarantineKind,
pub id: String,
pub run_id: String,
pub repo: String,
pub path: String,
#[ts(type = "number | null")]
pub line: Option<i64>,
pub cap: String,
pub rule: Option<String>,
pub severity: Option<String>,
pub finding_origin: Option<String>,
pub prompt_version: Option<String>,
pub attack_provenance: Option<String>,
pub rationale: Option<String>,
pub verdict_blob: Option<String>,
#[ts(type = "number | null")]
pub last_seen: Option<i64>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TS)]
pub struct AgentTraceRow {
pub id: String,
pub finding_id: Option<String>,
pub task_kind: String,
pub runtime_name: String,
pub model: String,
pub prompt_version: Option<String>,
pub conversation_jsonl_path: Option<String>,
#[ts(type = "number")]
pub tokens_in: i64,
#[ts(type = "number")]
pub tokens_out: i64,
#[ts(type = "number")]
pub cost_usd_micros: i64,
#[ts(type = "number")]
pub cache_hits: i64,
#[ts(type = "number")]
pub cache_misses: i64,
#[ts(type = "number | null")]
pub duration_ms: Option<i64>,
#[ts(type = "number")]
pub started_at: i64,
#[ts(type = "number | null")]
pub finished_at: Option<i64>,
}
impl From<AgentTraceRecord> for AgentTraceRow {
fn from(r: AgentTraceRecord) -> Self {
Self {
id: r.id,
finding_id: r.finding_id,
task_kind: r.task_kind,
runtime_name: r.runtime_name,
model: r.model,
prompt_version: r.prompt_version,
conversation_jsonl_path: r.conversation_jsonl_path,
tokens_in: r.tokens_in,
tokens_out: r.tokens_out,
cost_usd_micros: r.cost_usd_micros,
cache_hits: r.cache_hits,
cache_misses: r.cache_misses,
duration_ms: r.duration_ms,
started_at: r.started_at,
finished_at: r.finished_at,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, TS)]
#[serde(rename_all = "lowercase")]
pub enum ReplayEventKind {
Start,
Stdout,
Stderr,
End,
Error,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TS)]
pub struct ReplayEvent {
pub kind: ReplayEventKind,
pub data: String,
}