use super::*;
const RULE: &str = "untyped-tool-handler-result";
#[test]
fn a_handler_returning_a_freeform_dict_is_reported() {
let diagnostics = lint_source(
"pub fn build(tools: any) -> any {\n\
\x20 return tool_define(tools, \"apply\", \"applies\", {\n\
\x20 handler: { args -> {ok: false, error: \"blocked\"} },\n\
\x20 parameters: {},\n\
\x20 })\n\
}\n",
);
assert!(
has_rule(&diagnostics, RULE),
"expected an untyped handler-result diagnostic: {diagnostics:?}"
);
}
#[test]
fn an_explicit_return_of_a_dict_is_reported() {
let diagnostics = lint_source(
"pub fn build(tools: any) -> any {\n\
\x20 return tool_define(tools, \"apply\", \"applies\", {\n\
\x20 handler: fn(args: dict) {\n\
\x20 if args.dry_run { return {ok: true} }\n\
\x20 return {ok: false}\n\
\x20 },\n\
\x20 parameters: {},\n\
\x20 })\n\
}\n",
);
let hits = diagnostics.iter().filter(|d| d.rule == RULE).count();
assert_eq!(hits, 2, "both returns should be reported: {diagnostics:?}");
}
#[test]
fn a_handler_returning_a_typed_struct_is_not_reported() {
let diagnostics = lint_source(
"struct ApplyOutcome { ok: bool }\n\
pub fn build(tools: any) -> any {\n\
\x20 return tool_define(tools, \"apply\", \"applies\", {\n\
\x20 handler: { args -> ApplyOutcome{ok: false} },\n\
\x20 parameters: {},\n\
\x20 })\n\
}\n",
);
assert!(
!has_rule(&diagnostics, RULE),
"a typed struct return must not be reported: {diagnostics:?}"
);
}
#[test]
fn an_ordinary_function_returning_a_dict_is_not_reported() {
let diagnostics = lint_source(
"pub fn summarize(args: dict) -> dict {\n\
\x20 return {ok: true, count: 2}\n\
}\n",
);
assert!(
!has_rule(&diagnostics, RULE),
"only tool handlers are in scope: {diagnostics:?}"
);
}
#[test]
fn a_handler_returning_the_typed_result_envelope_is_not_reported() {
let diagnostics = lint_source(
"pub fn build(tools: any) -> any {\n\
\x20 return tool_define(tools, \"search\", \"searches\", {\n\
\x20 handler: { args ->\n\
\x20 return {\n\
\x20 schema: \"harn.agent_tool_handler_result.v1\",\n\
\x20 text: \"3 matches\",\n\
\x20 data: {matches: 3},\n\
\x20 }\n\
\x20 },\n\
\x20 parameters: {},\n\
\x20 })\n\
}\n",
);
assert_eq!(
diagnostics.iter().filter(|d| d.rule == RULE).count(),
0,
"the typed result envelope must not be reported: {diagnostics:?}"
);
}
#[test]
fn a_dict_naming_a_different_schema_is_still_reported() {
let diagnostics = lint_source(
"pub fn build(tools: any) -> any {\n\
\x20 return tool_define(tools, \"search\", \"searches\", {\n\
\x20 handler: { args -> {schema: \"something.else.v1\", ok: false} },\n\
\x20 parameters: {},\n\
\x20 })\n\
}\n",
);
assert!(
has_rule(&diagnostics, RULE),
"only the handler-result envelope is exempt: {diagnostics:?}"
);
}
#[test]
fn the_exempt_schema_is_the_runtime_owner_string() {
assert_eq!(
harn_vm::llm::AGENT_TOOL_HANDLER_RESULT_SCHEMA,
"harn.agent_tool_handler_result.v1"
);
}