#![recursion_limit = "256"]
use harn_vm::value::VmError;
fn run(source: &str) -> Result<String, String> {
harn_vm::reset_thread_local_state();
let chunk = harn_vm::compile_source(source)?;
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.map_err(|e| e.to_string())?;
rt.block_on(async {
let local = tokio::task::LocalSet::new();
local
.run_until(async {
let mut vm = harn_vm::Vm::new();
harn_vm::register_vm_stdlib(&mut vm);
vm.execute(&chunk)
.await
.map_err(|e: VmError| format!("{e:?}"))?;
Ok(vm.output().to_string())
})
.await
})
}
fn lines(source: &str) -> Result<Vec<String>, String> {
run(source).map(|raw| {
raw.lines()
.filter_map(|l| l.strip_prefix("[harn] ").map(str::to_string))
.collect()
})
}
fn resolve_snippet(provider: &str, model: &str, requested: &str) -> String {
let requested = if requested.is_empty() {
"auto"
} else {
requested
};
let opts =
format!(r#"{{model: "{model}", provider: "{provider}", tool_format: "{requested}"}}"#);
format!(
r#"
import {{ agent_tool_format_resolution, agent_tool_format }} from "std/agent/options"
pipeline main(task) {{
let r = agent_tool_format_resolution({opts})
log("tool_format=" + to_string(r.tool_format))
log("source=" + to_string(r.source))
log("effective=" + to_string(agent_tool_format({opts})))
}}
"#
)
}
enum Outcome {
Rejected(String),
Accepted { tool_format: String },
}
fn resolve(provider: &str, model: &str, requested: &str) -> Outcome {
match lines(&resolve_snippet(provider, model, requested)) {
Err(err) => Outcome::Rejected(err),
Ok(out) => Outcome::Accepted {
tool_format: accepted_field(&out, "tool_format"),
},
}
}
fn accepted_field(out: &[String], key: &str) -> String {
out.iter()
.find_map(|l| l.strip_prefix(&format!("{key}=")))
.unwrap_or("")
.to_string()
}
const REQUESTED_FORMATS: &[&str] = &[
"auto", "", "native", "text", "NATIVE", " text ", "json", "nativ", "tool_use", "xml", ];
const REAL_CELLS: &[(&str, &str)] = &[
("anthropic", "claude-sonnet-4-6"),
("ollama", "devstral-small-2:24b"),
("llamacpp", "qwen3.6-35b-a3b-ud-q4-k-xl"),
];
fn is_invalid_token(requested: &str) -> bool {
let norm = requested.trim().to_lowercase();
!matches!(norm.as_str(), "" | "auto" | "native" | "text" | "json")
}
fn is_text_channel(requested: &str) -> bool {
matches!(requested.trim().to_lowercase().as_str(), "text" | "json")
}
#[test]
fn requested_format_axis_rejects_or_resolves_concretely() {
for &(provider, model) in REAL_CELLS {
let (native_ok, text_ok, parity) = capability_facts(provider, model);
for &requested in REQUESTED_FORMATS {
let outcome = resolve(provider, model, requested);
let label = format!("{provider}:{model} requested={requested:?} (parity={parity})");
let norm = requested.trim().to_lowercase();
let requests_impossible_side =
(norm == "native" && !native_ok) || (is_text_channel(&norm) && !text_ok);
if is_invalid_token(requested) {
match outcome {
Outcome::Rejected(err) => assert!(
err.contains("tool_format"),
"{label}: rejection should name tool_format; got {err}"
),
Outcome::Accepted { tool_format, .. } => panic!(
"{label}: invalid token silently accepted as {tool_format:?} \
(reject-or-work-well violation)"
),
}
} else if requests_impossible_side {
match outcome {
Outcome::Rejected(_) => {}
Outcome::Accepted { tool_format, .. } => panic!(
"{label}: requested an impossible side but was accepted as \
{tool_format:?} (silent half-support)"
),
}
} else {
match outcome {
Outcome::Rejected(err) => {
panic!("{label}: serviceable request unexpectedly rejected: {err}")
}
Outcome::Accepted { tool_format, .. } => assert!(
tool_format == "native" || tool_format == "text" || tool_format == "json",
"{label}: accepted but resolved to non-concrete {tool_format:?}"
),
}
}
}
}
}
fn capability_facts(provider: &str, model: &str) -> (bool, bool, String) {
let src = format!(
r#"
pipeline main(task) {{
let c = provider_capabilities("{provider}", "{model}")
log("native=" + to_string(c.native_tools))
log("text=" + to_string(c.text_tool_wire_format_supported))
log("parity=" + to_string(c.tool_mode_parity))
}}
"#
);
let out = lines(&src).expect("capability lookup");
(
accepted_field(&out, "native") == "true",
accepted_field(&out, "text") == "true",
accepted_field(&out, "parity"),
)
}
#[test]
fn accepted_format_is_consistent_with_capability_matrix() {
for &(provider, model) in REAL_CELLS {
let (native_ok, text_ok, parity) = capability_facts(provider, model);
if text_ok && !native_ok {
if let Outcome::Accepted { tool_format, .. } = resolve(provider, model, "text") {
assert_eq!(
tool_format, "text",
"{provider}:{model}: text-capable model dropped explicit text request"
);
} else {
panic!("{provider}:{model}: text-capable model rejected a text request");
}
if let Outcome::Accepted { tool_format, .. } = resolve(provider, model, "auto") {
assert_eq!(
tool_format, "json",
"{provider}:{model}: auto resolved to {tool_format:?} on a text-only model; \
expected the global json default (parity={parity})"
);
}
}
if native_ok {
if let Outcome::Accepted { tool_format, .. } = resolve(provider, model, "native") {
assert_eq!(
tool_format, "native",
"{provider}:{model}: native-capable model dropped explicit native request"
);
} else {
panic!("{provider}:{model}: native-capable model rejected a native request");
}
}
}
}
fn resolve_with_parity_and_override(
model: &str,
parity: &str,
native_tools: bool,
requested: &str,
) -> Outcome {
resolve_with_parity_impl(model, parity, native_tools, requested, true)
}
fn resolve_with_parity(model: &str, parity: &str, native_tools: bool, requested: &str) -> Outcome {
resolve_with_parity_impl(model, parity, native_tools, requested, false)
}
fn resolve_with_parity_impl(
model: &str,
parity: &str,
native_tools: bool,
requested: &str,
with_override: bool,
) -> Outcome {
let preferred = if native_tools { "native" } else { "text" };
let install = format!(
r#"
[[provider.bootcamp]]
model_match = "{model}*"
native_tools = {native_tools}
preferred_tool_format = "{preferred}"
text_tool_wire_format_supported = true
tool_mode_parity = "{parity}"
"#
);
let override_line = if with_override {
r#"tool_format_override_reason: "probe: deliberately forcing the marked-impossible side","#
} else {
""
};
let src = format!(
r#"
import {{ agent_tool_format_resolution }} from "std/agent/options"
pipeline main(task) {{
provider_capabilities_install({install:?})
let r = agent_tool_format_resolution({{
model: "{model}",
provider: "bootcamp",
tool_format: "{requested}",
{override_line}
}})
log("tool_format=" + to_string(r.tool_format))
log("source=" + to_string(r.source))
provider_capabilities_clear()
}}
"#
);
match lines(&src) {
Err(err) => Outcome::Rejected(err),
Ok(out) => Outcome::Accepted {
tool_format: accepted_field(&out, "tool_format"),
},
}
}
#[test]
fn native_only_parity_rejects_text_request() {
match resolve_with_parity("bootcamp-native-only-model", "native_only", true, "text") {
Outcome::Rejected(err) => assert!(
err.contains("text") && err.contains("native_only"),
"expected native_only rejection naming text; got {err}"
),
Outcome::Accepted { tool_format, .. } => panic!(
"native_only model accepted text request as {tool_format:?} \
(silent half-support)"
),
}
match resolve_with_parity("bootcamp-native-only-model", "native_only", true, "native") {
Outcome::Accepted { tool_format, .. } => assert_eq!(tool_format, "native"),
Outcome::Rejected(err) => panic!("native_only model rejected its own native side: {err}"),
}
}
#[test]
fn text_only_parity_rejects_native_request() {
match resolve_with_parity("bootcamp-text-only-model", "text_only", false, "native") {
Outcome::Rejected(err) => assert!(
err.contains("native") && err.contains("text_only"),
"expected text_only rejection naming native; got {err}"
),
Outcome::Accepted { tool_format, .. } => panic!(
"text_only model accepted native request as {tool_format:?} \
(silent half-support)"
),
}
match resolve_with_parity("bootcamp-text-only-model", "text_only", false, "text") {
Outcome::Accepted { tool_format, .. } => assert_eq!(tool_format, "text"),
Outcome::Rejected(err) => panic!("text_only model rejected its own text side: {err}"),
}
}
#[test]
fn json_is_a_text_channel_format_for_parity() {
match resolve_with_parity("bootcamp-native-only-json", "native_only", true, "json") {
Outcome::Rejected(err) => assert!(
err.contains("json") && err.contains("native_only"),
"expected native_only rejection naming json; got {err}"
),
Outcome::Accepted { tool_format, .. } => panic!(
"native_only model accepted json (a text-channel format) as {tool_format:?} \
(silent half-support)"
),
}
match resolve_with_parity("bootcamp-text-only-json", "text_only", false, "json") {
Outcome::Accepted { tool_format, .. } => assert_eq!(
tool_format, "json",
"text_only model should accept json, a text-channel format"
),
Outcome::Rejected(err) => panic!("text_only model rejected json (text channel): {err}"),
}
}
#[test]
fn unpinned_text_channel_model_defaults_to_json() {
let install = r#"
[[provider.bootcamp]]
model_match = "bootcamp-unpinned-text*"
native_tools = false
text_tool_wire_format_supported = true
"#;
let src = format!(
r#"
import {{ agent_tool_format_resolution, agent_tool_format }} from "std/agent/options"
pipeline main(task) {{
provider_capabilities_install({install:?})
let auto = agent_tool_format_resolution({{
model: "bootcamp-unpinned-text-1",
provider: "bootcamp",
tool_format: "auto",
}})
log("auto=" + to_string(auto.tool_format))
// An omitted tool_format must agree with the explicit `auto` sentinel.
log("effective=" + to_string(agent_tool_format({{
model: "bootcamp-unpinned-text-1",
provider: "bootcamp",
}})))
provider_capabilities_clear()
}}
"#
);
let out = lines(&src).expect("unpinned-text-channel resolution");
assert_eq!(
accepted_field(&out, "auto"),
"json",
"an unpinned text-channel model must default to json, not heredoc text"
);
assert_eq!(
accepted_field(&out, "effective"),
"json",
"omitted tool_format must resolve to the same json default as explicit auto"
);
}
#[test]
fn override_reason_forces_marked_impossible_side() {
match resolve_with_parity_and_override(
"bootcamp-text-only-forced",
"text_only",
false,
"native",
) {
Outcome::Accepted { tool_format, .. } => assert_eq!(
tool_format, "native",
"override reason should force the requested native side on a text_only model"
),
Outcome::Rejected(err) => {
panic!("override reason failed to unlock the forced native side: {err}")
}
}
match resolve_with_parity_and_override(
"bootcamp-native-only-forced",
"native_only",
true,
"text",
) {
Outcome::Accepted { tool_format, .. } => assert_eq!(tool_format, "text"),
Outcome::Rejected(err) => {
panic!("override reason failed to unlock the forced text side: {err}")
}
}
}
#[test]
fn unreliable_parity_steers_to_safe_channel_without_rejecting() {
match resolve_with_parity(
"bootcamp-native-unreliable-model",
"native_unreliable",
true,
"native",
) {
Outcome::Accepted { tool_format, .. } => assert_eq!(
tool_format, "json",
"native_unreliable must steer an explicit native pin to the safe text channel"
),
Outcome::Rejected(err) => {
panic!("native_unreliable wrongly hard-rejected the recoverable side: {err}")
}
}
}
#[test]
fn explicit_and_catalog_paths_agree_on_servable_cells() {
for &(provider, model) in REAL_CELLS {
let (native_ok, text_ok, _) = capability_facts(provider, model);
let auto = match resolve(provider, model, "auto") {
Outcome::Accepted { tool_format, .. } => tool_format,
Outcome::Rejected(err) => panic!("{provider}:{model}: auto resolution failed: {err}"),
};
if !auto.is_empty() {
let explicit = match resolve(provider, model, &auto) {
Outcome::Accepted { tool_format, .. } => tool_format,
Outcome::Rejected(err) => {
panic!("{provider}:{model}: explicit {auto:?} rejected though auto chose it: {err}")
}
};
assert_eq!(
auto, explicit,
"{provider}:{model}: auto and explicit disagree ({auto} vs {explicit})"
);
let servable = match auto.as_str() {
"native" => native_ok,
"text" | "json" => text_ok,
_ => false,
};
assert!(
servable,
"{provider}:{model}: auto chose {auto:?} which the matrix marks unservable"
);
}
}
}