harn-vm 0.10.63

Async bytecode virtual machine for the Harn programming language
Documentation
use crate::value::{VmError, VmValue};

fn field(dict: &VmValue, key: &str) -> Option<String> {
    dict.as_dict()
        .and_then(|map| map.get(key))
        .map(VmValue::display)
}

#[test]
fn provider_stream_failure_preserves_typed_liveness_fields() {
    let failure = VmError::ProviderStreamFailure(Box::new(crate::value::ProviderStreamFailure {
        provider: "openai".to_string(),
        phase: crate::value::ProviderStreamPhase::Streaming,
        reason: crate::value::ProviderStreamFailureReason::Deadline,
        deadline: Some(crate::value::ProviderStreamDeadline::Idle),
        partial: true,
        detail: "idle deadline elapsed".to_string(),
    }));

    let dict = super::call::build_llm_error_dict(&failure, "openai", "test-model");

    assert_eq!(field(&dict, "category").as_deref(), Some("timeout"));
    assert_eq!(field(&dict, "kind").as_deref(), Some("transient"));
    assert_eq!(field(&dict, "source").as_deref(), Some("provider_stream"));
    assert_eq!(field(&dict, "phase").as_deref(), Some("streaming"));
    assert_eq!(field(&dict, "deadline").as_deref(), Some("idle"));
    assert_eq!(field(&dict, "partial").as_deref(), Some("true"));
}

#[test]
fn preserves_route_recorded_by_a_routing_failure() {
    let thrown = VmError::Thrown(VmValue::dict([
        ("kind", VmValue::String(arcstr::ArcStr::from("terminal"))),
        (
            "reason",
            VmValue::String(arcstr::ArcStr::from("provider_exhausted")),
        ),
        (
            "provider",
            VmValue::String(arcstr::ArcStr::from("backup-provider")),
        ),
        (
            "model",
            VmValue::String(arcstr::ArcStr::from("escalated-model")),
        ),
    ]));

    let dict = super::call::build_llm_error_dict(&thrown, "base-provider", "base-model");

    assert_eq!(field(&dict, "provider").as_deref(), Some("backup-provider"));
    assert_eq!(field(&dict, "model").as_deref(), Some("escalated-model"));
}

#[test]
fn fills_route_when_the_failure_did_not_record_one() {
    let thrown = VmError::Thrown(VmValue::dict([(
        "reason",
        VmValue::String(arcstr::ArcStr::from("timeout")),
    )]));

    let dict = super::call::build_llm_error_dict(&thrown, "base-provider", "base-model");

    assert_eq!(field(&dict, "provider").as_deref(), Some("base-provider"));
    assert_eq!(field(&dict, "model").as_deref(), Some("base-model"));
}

#[test]
fn no_single_route_failure_is_not_backfilled_with_the_base_route() {
    let thrown = VmError::Thrown(VmValue::dict([
        (
            "reason",
            VmValue::String(arcstr::ArcStr::from("provider_exhausted")),
        ),
        ("no_single_route", VmValue::Bool(true)),
    ]));

    let dict = super::call::build_llm_error_dict(&thrown, "base-provider", "base-model");

    assert!(
        field(&dict, "provider").is_none(),
        "composite failure must not be backfilled with the base provider"
    );
    assert!(
        field(&dict, "model").is_none(),
        "composite failure must not be backfilled with the base model"
    );
}