magi-code 0.96.1

Repository-aware CLI coding agent for terminal work
Documentation
use super::*;

pub(super) fn resolve_output_schema_for_task(
    task: &SubagentTask,
    config: &SubagentRunConfig,
) -> Option<Value> {
    let identity = task.identity.as_deref()?;
    let schema_ref = config
        .profiles
        .get(identity)
        .and_then(|profile| profile.output_schema.as_ref())
        .cloned()
        .or_else(|| {
            output_schema::default_phase_for_identity(identity)
                .map(SubagentOutputSchemaRef::Builtin)
        })?;
    output_schema::schema_for_ref(&schema_ref)
}

pub(super) fn validate_schema_bound_output(
    schema: &Value,
    output_text: &str,
) -> Result<Value, Vec<SchemaValidationError>> {
    // ponytail: final-message isolation is unavailable here; schema-bound children must emit no assistant prose before final raw JSON. Upgrade path: expose final assistant message segments from AgentRunOutput.
    let trimmed = output_text.trim();
    let instance = serde_json::from_str::<Value>(trimmed).map_err(|error| {
        vec![SchemaValidationError {
            instance_path: String::new(),
            schema_path: String::new(),
            message: format!("output must be one JSON object: {error}"),
        }]
    })?;
    if !instance.is_object() {
        return Err(vec![SchemaValidationError {
            instance_path: String::new(),
            schema_path: String::new(),
            message: "output must be one JSON object".to_string(),
        }]);
    }
    output_schema::validate_instance(schema, &instance)?;
    Ok(instance)
}

pub(super) fn schema_validation_feedback_prompt(
    attempt: u64,
    max_retries: u64,
    errors: &[SchemaValidationError],
) -> String {
    json!({
        "schema_validation_error": true,
        "attempt": attempt,
        "max_retries": max_retries,
        "errors": redact_schema_validation_errors(errors),
        "instruction": "Return only a JSON object matching the required output_schema. Do not include markdown or prose."
    })
    .to_string()
}

pub(super) fn schema_validation_exhausted_error(errors: &[SchemaValidationError]) -> String {
    json!({
        "schema_validation_error": true,
        "exhausted": true,
        "errors": redact_schema_validation_errors(errors),
        "instruction": "Subagent did not return JSON matching the required output_schema before retry exhaustion."
    })
    .to_string()
}

fn redact_schema_validation_errors(errors: &[SchemaValidationError]) -> Vec<SchemaValidationError> {
    errors
        .iter()
        .map(|error| SchemaValidationError {
            instance_path: redact_sensitive_text(&error.instance_path),
            schema_path: redact_sensitive_text(&error.schema_path),
            message: redact_sensitive_text(&error.message),
        })
        .collect()
}