///|
fn main {
let args = @env.args()
match args.get(1) {
Some(input) => println(responses_json_report(input))
None => run_demo()
}
}
///|
fn run_demo() -> Unit {
let trace = @src.Trace::new()
trace.call("read_file", "read-1", Some("inspect-config"))
trace.result("read_file", "read-1", Some("inspect-config"), Some(true))
trace.call("write_file", "write-1", Some("update-config"))
trace.result("write_file", "write-1", Some("update-config"), Some(true))
trace.write_complete("write_file", "write-1", Some("update-config"))
trace.write_complete("write_file", "write-1", Some("update-config"))
let policy = @src.EvaluationPolicy::new(1, Some(["read_file", "write_file"]))
let context = @src.PolicyContext::new("main/demo-policy", policy)
let violations = @src.evaluate_with_context(trace.events(), context)
if violations.length() != 1 || @src.violation_code(violations[0]) != "AGC004" {
println("unexpected contract evaluation")
abort("demo assertion failed")
}
let results = @src.evaluate_scenarios(
[@src.Scenario::new("duplicate-write", trace.events())],
1,
)
println("MoonAgentCheck runnable demo")
println(@src.evaluation_report_json(trace.events(), context))
println(@src.scenario_results_json(results))
println(@src.trace_metrics_json(@src.collect_metrics(trace.events())))
}
///|
fn json_string_field(item : Map[String, Json], key : String) -> String? {
match item.get(key) {
Some(Json::String(value)) => Some(value)
_ => None
}
}
///|
fn json_optional_string_field(
item : Map[String, Json],
key : String,
) -> String? {
match item.get(key) {
Some(Json::String(value)) => Some(value)
_ => None
}
}
///|
fn json_optional_bool_field(item : Map[String, Json], key : String) -> Bool? {
match item.get(key) {
Some(Json::True) => Some(true)
Some(Json::False) => Some(false)
_ => None
}
}
///|
fn responses_item_from_json(value : Json) -> @src.ResponsesItem {
match value {
Json::Object(item) => {
let item_type = json_string_field(item, "type")
match item_type {
Some("function_call") =>
@src.responses_function_call(
json_string_field(item, "response_id").unwrap_or(""),
json_optional_string_field(item, "operation_id"),
json_string_field(item, "call_id").unwrap_or(""),
json_string_field(item, "name").unwrap_or(""),
)
Some("function_call_output") => {
let call_id = json_string_field(item, "call_id").unwrap_or("")
match json_string_field(item, "status") {
Some("in_progress") =>
@src.responses_function_call_output(
call_id,
@src.responses_in_progress(),
json_optional_bool_field(item, "outcome"),
)
Some("completed") =>
@src.responses_function_call_output(
call_id,
@src.responses_completed(),
json_optional_bool_field(item, "outcome"),
)
Some("incomplete") =>
@src.responses_function_call_output(
call_id,
@src.responses_incomplete(),
json_optional_bool_field(item, "outcome"),
)
_ =>
@src.responses_non_tool_item(
"unsupported_function_call_output_status",
)
}
}
Some("message") => @src.responses_non_tool_item("message")
Some("reasoning") => @src.responses_non_tool_item("reasoning")
Some(other) => @src.responses_non_tool_item(other)
None => @src.responses_non_tool_item("missing_item_type")
}
}
_ => @src.responses_non_tool_item("invalid_item_shape")
}
}
///|
fn event_from_json(value : Json) -> Result[@src.Event, String] {
match value {
Json::Object(item) => {
let kind = json_string_field(item, "kind")
let tool = json_string_field(item, "tool")
let call_id = json_string_field(item, "call_id")
let operation_id = match item.get("operation_id") {
None | Some(Json::Null) => Ok(None)
Some(Json::String(value)) => Ok(Some(value))
Some(_) => Err("operation_id must be a string or null")
}
let ok = match item.get("ok") {
None | Some(Json::Null) => Ok(None)
Some(Json::True) => Ok(Some(true))
Some(Json::False) => Ok(Some(false))
Some(_) => Err("ok must be a boolean or null")
}
match (kind, tool, call_id, operation_id, ok) {
(Some(kind), Some(tool), Some(call_id), Ok(operation_id), Ok(ok)) =>
if kind == "call" || kind == "result" || kind == "write-complete" {
if tool == "" || call_id == "" {
Err("tool and call_id must be non-empty strings")
} else {
Ok(@src.Event::new(kind, tool, call_id, operation_id, ok))
}
} else {
Err("unsupported event kind")
}
(_, _, _, Err(message), _) => Err(message)
(_, _, _, _, Err(message)) => Err(message)
_ => Err("event needs string kind, tool, and call_id fields")
}
}
_ => Err("event must be a JSON object")
}
}
///|
fn event_array_from_json(
values : Array[Json],
) -> Result[Array[@src.Event], String] {
let events : Array[@src.Event] = []
let issues : Array[String] = []
for index, value in values {
match event_from_json(value) {
Ok(event) => events.push(event)
Err(message) => issues.push("event " + index.to_string() + ": " + message)
}
}
if issues.length() == 0 {
Ok(events)
} else {
Err(issues[0])
}
}
///|
fn request_max_retries(object : Map[String, Json]) -> Result[Int32, String] {
match object.get("max_retries") {
None => Ok(2)
Some(value) =>
try {
let retries : Int32 = @json.from_json(value)
if retries < 0 {
Err("max_retries must not be negative")
} else {
Ok(retries)
}
} catch {
_ => Err("max_retries must be an integer")
}
}
}
///|
fn request_tool_allowlist(
object : Map[String, Json],
) -> Result[Array[String]?, String] {
match object.get("tool_allowlist") {
None | Some(Json::Null) => Ok(None)
Some(Json::Array(values)) => {
let tools : Array[String] = []
let issues : Array[String] = []
for value in values {
match value {
Json::String(tool) => tools.push(tool)
_ => issues.push("tool_allowlist entries must be strings")
}
}
if issues.length() == 0 {
Ok(Some(tools))
} else {
Err(issues[0])
}
}
Some(_) => Err("tool_allowlist must be an array or null")
}
}
///|
fn event_json_report(value : Json) -> String {
match value {
Json::Object(object) =>
match object.get("events") {
Some(Json::Array(values)) =>
match event_array_from_json(values) {
Ok(events) =>
match
(request_max_retries(object), request_tool_allowlist(object)) {
(Ok(max_retries), Ok(tool_allowlist)) =>
@src.evaluation_report_json(
events,
@src.PolicyContext::new(
"cli/events-json",
@src.EvaluationPolicy::new(max_retries, tool_allowlist),
),
)
(Err(message), _) | (_, Err(message)) =>
input_error_report(message)
}
Err(message) => input_error_report(message)
}
_ => input_error_report("expected an events array")
}
_ => input_error_report("expected an event request object")
}
}
///|
fn input_error_report(message : String) -> String {
Json::object({
"adapter": Json::string("openai-responses-function-call"),
"passed": Json(false),
"input_error": Json(message),
}).stringify()
}
///|
pub fn responses_json_report(input : String) -> String {
try {
let parsed = @json.parse(input)
match parsed {
Json::Array(values) =>
@src.responses_evaluation_report_json(
values.map(responses_item_from_json),
@src.PolicyContext::new(
"cli/responses-json",
@src.EvaluationPolicy::new(1, None),
),
)
Json::Object(_) => event_json_report(parsed)
_ =>
input_error_report(
"expected a Responses item array or an event request object",
)
}
} catch {
_ => input_error_report("invalid JSON input")
}
}