use anyhow::Result;
use clap::Args;
use serde_json::{Value, json};
use crate::cli::CliOutput;
use crate::config::AppConfig;
#[derive(Args, Debug, Clone)]
pub struct IngestMultistepArgs {
#[arg(long, value_name = "TEXT")]
pub content: String,
#[arg(long, value_name = "NS")]
pub namespace: Option<String>,
#[arg(long = "pipeline-variant", value_name = "VARIANT")]
pub pipeline_variant: Option<String>,
#[arg(long)]
pub json: bool,
}
pub fn cmd_ingest_multistep(
args: &IngestMultistepArgs,
app_config: &AppConfig,
out: &mut CliOutput<'_>,
) -> Result<()> {
let mut params = json!({"content": args.content});
if let Some(ns) = &args.namespace {
params["namespace"] = json!(ns);
}
if let Some(v) = &args.pipeline_variant {
params["pipeline_variant"] = json!(v);
}
let feature_tier = app_config.effective_tier(None);
let envelope = crate::mcp::handle_ingest_multistep(¶ms, None, feature_tier)
.map_err(|e| anyhow::anyhow!("ingest-multistep: {e}"))?;
if args.json {
writeln!(out.stdout, "{}", serde_json::to_string(&envelope)?)?;
return Ok(());
}
if let Some(locked) = envelope
.get(crate::models::field_names::TIER_LOCKED)
.and_then(Value::as_str)
{
writeln!(out.stdout, "ingest-multistep: tier-locked: {locked}")?;
} else {
let variant = envelope
.get("variant")
.and_then(Value::as_str)
.unwrap_or("?");
writeln!(out.stdout, "ingest-multistep: variant={variant}")?;
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::cli::test_utils::TestEnv;
#[test]
fn ingest_multistep_cli_tier_locked_when_no_llm() {
let mut env = TestEnv::fresh();
let cfg = AppConfig::default();
let args = IngestMultistepArgs {
content: "hello".into(),
namespace: None,
pipeline_variant: None,
json: true,
};
{
let mut out = env.output();
cmd_ingest_multistep(&args, &cfg, &mut out).expect("ok");
}
let stdout = env.stdout_str();
let envelope: Value = serde_json::from_str(stdout.trim()).expect("parse envelope");
assert!(envelope.get("tier-locked").is_some());
}
#[test]
fn ingest_multistep_cli_empty_content_returns_err() {
let mut env = TestEnv::fresh();
let cfg = AppConfig::default();
let args = IngestMultistepArgs {
content: String::new(),
namespace: None,
pipeline_variant: None,
json: true,
};
let mut out = env.output();
let err = cmd_ingest_multistep(&args, &cfg, &mut out).expect_err("must fail");
assert!(err.to_string().contains("ingest-multistep"), "got: {err}");
}
#[test]
fn ingest_multistep_cli_text_output_tier_locked_with_params() {
let mut env = TestEnv::fresh();
let cfg = AppConfig::default();
let args = IngestMultistepArgs {
content: "hello world".into(),
namespace: Some("proj".into()),
pipeline_variant: Some("four_step".into()),
json: false,
};
{
let mut out = env.output();
cmd_ingest_multistep(&args, &cfg, &mut out).expect("ok");
}
assert!(env.stdout_str().contains("ingest-multistep: tier-locked:"));
}
}