use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum GuardrailVerdictWire {
Accept,
Update {
content: String,
},
Deny {
code: String,
message: String,
details: Option<String>,
},
}
pub(crate) fn call_evaluate(
store: &mut wasmtime::Store<crate::host_state::HostState>,
instance: &wasmtime::component::Instance,
func_idx: &wasmtime::component::ComponentExportIndex,
input_json: &str,
) -> Result<GuardrailVerdictWire, crate::RuntimeError> {
use crate::host_bindings::design_v03::exports::greentic::extension_design0_3_0::guardrail as gr;
#[derive(Deserialize)]
struct InputDto {
direction: String,
content: String,
agent_id: String,
session_id: String,
tenant_id: String,
env_id: String,
context: Option<String>,
}
let dto: InputDto =
serde_json::from_str(input_json).map_err(|e| crate::RuntimeError::Wasmtime(e.into()))?;
let direction = match dto.direction.as_str() {
"outbound" => gr::Direction::Outbound,
_ => gr::Direction::Inbound,
};
let input = gr::GuardrailInput {
direction,
content: dto.content,
agent_id: dto.agent_id,
session_id: dto.session_id,
tenant_id: dto.tenant_id,
env_id: dto.env_id,
context: dto.context,
};
let func = instance
.get_typed_func::<(gr::GuardrailInput,), (gr::Verdict,)>(&mut *store, func_idx)
.map_err(|e| crate::RuntimeError::Wasmtime(e.into()))?;
let (verdict,) = func
.call(&mut *store, (input,))
.map_err(|e| crate::RuntimeError::Wasmtime(e.into()))?;
Ok(map_verdict(verdict))
}
fn map_verdict(
verdict: crate::host_bindings::design_v03::exports::greentic::extension_design0_3_0::guardrail::Verdict,
) -> GuardrailVerdictWire {
use crate::host_bindings::design_v03::exports::greentic::extension_design0_3_0::guardrail::Verdict;
match verdict {
Verdict::Accept => GuardrailVerdictWire::Accept,
Verdict::Update(content) => GuardrailVerdictWire::Update { content },
Verdict::Deny(info) => GuardrailVerdictWire::Deny {
code: info.code,
message: info.message,
details: info.details,
},
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn verdict_wire_round_trips() {
let verdict = GuardrailVerdictWire::Update {
content: "x".into(),
};
let serialised = serde_json::to_string(&verdict).unwrap();
assert_eq!(serialised, r#"{"kind":"update","content":"x"}"#);
let deserialised: GuardrailVerdictWire = serde_json::from_str(&serialised).unwrap();
assert_eq!(deserialised, verdict);
}
#[test]
fn deny_wire_round_trips() {
let verdict = GuardrailVerdictWire::Deny {
code: "permission_denied".into(),
message: "no".into(),
details: None,
};
let serialised = serde_json::to_string(&verdict).unwrap();
let deserialised: GuardrailVerdictWire = serde_json::from_str(&serialised).unwrap();
assert_eq!(deserialised, verdict);
}
#[test]
fn accept_wire_round_trips() {
let verdict = GuardrailVerdictWire::Accept;
let serialised = serde_json::to_string(&verdict).unwrap();
assert_eq!(serialised, r#"{"kind":"accept"}"#);
let deserialised: GuardrailVerdictWire = serde_json::from_str(&serialised).unwrap();
assert_eq!(deserialised, verdict);
}
}