Skip to main content

Module recovery

Module recovery 

Source
Expand description

The validate-and-retry loop around a generating model.

Prompted generation is not schema-constrained, so a model will sometimes return a surface that does not hold together: a child id it never defined, a missing root, a loop. That is recoverable — the validator says exactly what is wrong in words the model can act on, so the fix is to hand the errors back and ask again.

generate_with_recovery runs that loop up to MAX_A2UI_ATTEMPTS times, appending the formatted errors to the prompt between attempts and reporting each step under the A2UI_RECOVERY_ACTIVITY_TYPE activity type so a caller can show progress rather than a stall.

The loop is synchronous and takes the model as a closure, so it imposes no async runtime: wrap a blocking call directly, or drive an async client with whatever executor the host already uses.

use ag_ui_a2ui::catalog::Catalog;
use ag_ui_a2ui::toolkit::recovery::{generate_with_recovery, RecoveryOptions};

fn response(components: &str) -> String {
    format!(
        r#"<a2ui-json>[
             {{"version":"v0.9","createSurface":{{"surfaceId":"s","catalogId":"c"}}}},
             {{"version":"v0.9","updateComponents":{{"surfaceId":"s","components":{components}}}}}
           ]</a2ui-json>"#
    )
}

let catalog = Catalog::basic();
let mut attempt = 0;
let outcome = generate_with_recovery(
    "build a greeting card",
    &catalog,
    &RecoveryOptions::default(),
    |prompt, _n| {
        attempt += 1;
        Ok(if attempt == 1 {
            // First try references a component that was never defined.
            assert!(!prompt.contains("Correction required"));
            response(r#"[{"id":"root","component":"Card","child":"missing"}]"#)
        } else {
            // The retry prompt now carries the validator's complaint.
            assert!(prompt.contains("unresolved_child"));
            response(r#"[{"id":"root","component":"Text","text":"hi"}]"#)
        })
    },
    |_activity| {},
)
.unwrap();

assert_eq!(outcome.attempts, 2);
assert_eq!(outcome.components.len(), 1);

Structs§

RecoveredSurface
A surface that survived validation.
RecoveryActivity
What happened on one attempt.
RecoveryOptions
How the recovery loop should behave.

Enums§

RecoveryStatus
How one attempt ended.

Functions§

generate_with_recovery
Generates a surface, retrying with the validator’s complaints on failure.