zeph-core 0.22.3

Core agent loop, configuration, context builder, metrics, and vault for Zeph
Documentation
// SPDX-FileCopyrightText: 2026 Andrei G <bug-ops>
// SPDX-License-Identifier: MIT OR Apache-2.0

//! Proposer stage: extract factual assertions from an assistant response.

use std::time::Duration;

use serde::Deserialize;
use zeph_llm::any::AnyProvider;

use super::parser::{chat_json, chat_json_error_outcome};
use super::prompts::{PROPOSER_SYSTEM, proposer_user};
use super::types::{Assertion, StageOutcome};

#[derive(Debug, Deserialize)]
struct ProposerOutput {
    assertions: Vec<Assertion>,
}

/// Call the Proposer and return extracted assertions plus stage diagnostics.
///
/// Clamps the result to `max_assertions`. Returns an empty vec on parse failure
/// with the outcome capturing the error detail.
pub async fn run_proposer(
    provider: &AnyProvider,
    response: &str,
    max_assertions: usize,
    per_call_timeout: Duration,
) -> (Vec<Assertion>, u64, StageOutcome, u32) {
    let user = proposer_user(max_assertions, response);
    match chat_json::<ProposerOutput>(provider, PROPOSER_SYSTEM, &user, per_call_timeout).await {
        Ok((mut out, tokens, attempt)) => {
            out.assertions.truncate(max_assertions);
            let retries = attempt.saturating_sub(1);
            (out.assertions, tokens, StageOutcome::Ok, retries)
        }
        Err(e) => chat_json_error_outcome(e),
    }
}