diff --git a/crates/challenge-sdk-wasm/src/error.rs b/crates/challenge-sdk-wasm/src/error.rs new file mode 100644 index 00000000..54f22a11 --- /dev/null +++ b/crates/challenge-sdk-wasm/src/error.rs @@ -0,0 +1,35 @@ +use alloc::boxed::Box; +use alloc::format; +use alloc::string::String; +use core::fmt; + +#[derive(Debug)] +pub enum ChallengeError { + Evaluation(String), + Validation(String), + Network(String), + Timeout(String), + Serialization(String), + Storage(String), + Internal(String), +} + +impl fmt::Display for ChallengeError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ChallengeError::Evaluation(msg) => write!(f, "Evaluation error: {}", msg), + ChallengeError::Validation(msg) => write!(f, "Validation error: {}", msg), + ChallengeError::Network(msg) => write!(f, "Network error: {}", msg), + ChallengeError::Timeout(msg) => write!(f, "Timeout: {}", msg), + ChallengeError::Serialization(msg) => write!(f, "Serialization error: {}", msg), + ChallengeError::Storage(msg) => write!(f, "Storage error: {}", msg), + ChallengeError::Internal(msg) => write!(f, "Internal error: {}", msg), + } + } +} + +impl From> for ChallengeError { + fn from(err: Box) -> Self { + ChallengeError::Serialization(format!("{}", err)) + } +} diff --git a/crates/challenge-sdk-wasm/src/host_functions.rs b/crates/challenge-sdk-wasm/src/host_functions.rs index 03f67414..73ebcbca 100644 --- a/crates/challenge-sdk-wasm/src/host_functions.rs +++ b/crates/challenge-sdk-wasm/src/host_functions.rs @@ -1,11 +1,16 @@ +use alloc::format; use alloc::vec; use alloc::vec::Vec; +use crate::error::ChallengeError; +use crate::types::{HttpRequest, HttpResponse}; + #[link(wasm_import_module = "platform_network")] extern "C" { fn http_get(req_ptr: i32, req_len: i32, resp_ptr: i32, resp_len: i32) -> i32; fn http_post(req_ptr: i32, req_len: i32, resp_ptr: i32, resp_len: i32, extra: i32) -> i32; fn dns_resolve(req_ptr: i32, req_len: i32, resp_ptr: i32) -> i32; + fn log_message(level: i32, msg_ptr: i32, msg_len: i32); } #[link(wasm_import_module = "platform_storage")] @@ -14,6 +19,11 @@ extern "C" { fn storage_set(key_ptr: i32, key_len: i32, value_ptr: i32, value_len: i32) -> i32; } +#[link(wasm_import_module = "platform_time")] +extern "C" { + fn get_timestamp() -> i64; +} + #[link(wasm_import_module = "platform_terminal")] extern "C" { fn terminal_exec(cmd_ptr: i32, cmd_len: i32, result_ptr: i32, result_len: i32) -> i32; @@ -106,6 +116,31 @@ pub fn host_storage_set(key: &[u8], value: &[u8]) -> Result<(), i32> { Ok(()) } +pub fn host_log(level: u8, message: &str) { + unsafe { + log_message(level as i32, message.as_ptr() as i32, message.len() as i32); + } +} + +pub fn host_get_timestamp() -> i64 { + unsafe { get_timestamp() } +} + +pub fn typed_http_get(request: &HttpRequest) -> Result { + let encoded = bincode::serialize(request).map_err(ChallengeError::from)?; + let raw = host_http_get(&encoded) + .map_err(|code| ChallengeError::Network(format!("http_get failed with code {}", code)))?; + bincode::deserialize(&raw).map_err(ChallengeError::from) +} + +pub fn typed_http_post(request: &HttpRequest) -> Result { + let encoded = bincode::serialize(request).map_err(ChallengeError::from)?; + let body = &request.body; + let raw = host_http_post(&encoded, body) + .map_err(|code| ChallengeError::Network(format!("http_post failed with code {}", code)))?; + bincode::deserialize(&raw).map_err(ChallengeError::from) +} + pub fn host_terminal_exec(request: &[u8]) -> Result, i32> { let mut result_buf = vec![0u8; 262144]; let status = unsafe { diff --git a/crates/challenge-sdk-wasm/src/lib.rs b/crates/challenge-sdk-wasm/src/lib.rs index 82e16686..c3a943fe 100644 --- a/crates/challenge-sdk-wasm/src/lib.rs +++ b/crates/challenge-sdk-wasm/src/lib.rs @@ -3,12 +3,16 @@ extern crate alloc; pub mod alloc_impl; +pub mod error; pub mod host_functions; pub mod term_types; pub mod types; +pub use error::ChallengeError; pub use term_types::*; -pub use types::{EvaluationInput, EvaluationOutput}; +pub use types::{ + DetailedScore, EvaluationInput, EvaluationOutput, HttpRequest, HttpResponse, TaskResult, +}; pub trait Challenge { fn name(&self) -> &'static str; diff --git a/crates/challenge-sdk-wasm/src/types.rs b/crates/challenge-sdk-wasm/src/types.rs index 7036a615..9338cddd 100644 --- a/crates/challenge-sdk-wasm/src/types.rs +++ b/crates/challenge-sdk-wasm/src/types.rs @@ -7,6 +7,11 @@ pub struct EvaluationInput { pub agent_data: Vec, pub challenge_id: String, pub params: Vec, + pub submission_id: Option, + pub participant_id: Option, + pub epoch: Option, + pub metadata: Vec, + pub task_definitions: Vec, pub task_definition: Option>, pub environment_config: Option>, } @@ -43,3 +48,33 @@ impl EvaluationOutput { self } } + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct HttpRequest { + pub url: String, + pub method: String, + pub headers: Vec<(String, String)>, + pub body: Vec, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct HttpResponse { + pub status_code: u16, + pub headers: Vec<(String, String)>, + pub body: Vec, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct TaskResult { + pub passed: bool, + pub name: String, + pub message: String, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct DetailedScore { + pub score: f64, + pub tasks_passed: u32, + pub tasks_total: u32, + pub task_results: Vec, +} diff --git a/crates/wasm-runtime-interface/src/bridge.rs b/crates/wasm-runtime-interface/src/bridge.rs index d7cc69d0..6c1708ed 100644 --- a/crates/wasm-runtime-interface/src/bridge.rs +++ b/crates/wasm-runtime-interface/src/bridge.rs @@ -76,6 +76,11 @@ pub fn request_to_input( agent_data, challenge_id: challenge_id.to_string(), params, + submission_id: None, + participant_id: None, + epoch: None, + metadata: Vec::new(), + task_definitions: Vec::new(), task_definition: None, environment_config: None, }) @@ -162,6 +167,11 @@ mod tests { agent_data: vec![1, 2, 3], challenge_id: "test".into(), params: vec![4, 5, 6], + submission_id: None, + participant_id: None, + epoch: None, + metadata: Vec::new(), + task_definitions: Vec::new(), task_definition: None, environment_config: None, };