codescout/cli/
artifact_augment.rs1use crate::librarian::tools::Tool;
4use anyhow::{Context, Result};
5use clap::Args;
6use serde_json::Value;
7
8use crate::cli::{open_ctx, CommonOpts};
9
10#[derive(Debug, Args)]
11pub struct AugmentArgs {
12 pub id: String,
14 #[arg(long)]
16 pub prompt: Option<String>,
17 #[arg(long = "prompt-file")]
19 pub prompt_file: Option<std::path::PathBuf>,
20 #[arg(long)]
22 pub params: Option<String>,
23 #[arg(long = "params-schema")]
25 pub params_schema: Option<String>,
26 #[arg(long = "render-template")]
28 pub render_template: Option<String>,
29 #[arg(long)]
31 pub merge: bool,
32 #[arg(long = "append-mode")]
34 pub append_mode: bool,
35 #[arg(long = "history-cap")]
37 pub history_cap: Option<usize>,
38 #[arg(long)]
40 pub project: Option<std::path::PathBuf>,
41 #[arg(long)]
43 pub json: bool,
44 #[arg(long = "no-color")]
46 pub no_color: bool,
47}
48
49pub async fn run(args: AugmentArgs) -> Result<()> {
50 let common = CommonOpts {
51 project: args.project.clone(),
52 json: args.json,
53 no_color: args.no_color,
54 };
55 let output = common.output();
56 let ctx = open_ctx(&common).await?;
57
58 let prompt = match (args.prompt.as_ref(), args.prompt_file.as_ref()) {
60 (Some(p), None) => Some(crate::cli::read_at_or_stdin(p)?),
61 (None, Some(path)) => Some(
62 std::fs::read_to_string(path).with_context(|| format!("reading {}", path.display()))?,
63 ),
64 (Some(_), Some(_)) => {
65 return Err(anyhow::anyhow!(
66 "pass at most one of --prompt or --prompt-file"
67 ));
68 }
69 (None, None) => None,
70 };
71
72 if !args.merge && prompt.is_none() {
73 return Err(anyhow::anyhow!(
74 "--prompt (or --prompt-file) is required unless --merge is passed"
75 ));
76 }
77
78 let mut tool_args = serde_json::Map::new();
79 tool_args.insert("id".into(), Value::String(args.id.clone()));
80 if let Some(p) = prompt {
81 tool_args.insert("prompt".into(), Value::String(p));
82 }
83 if let Some(params) = &args.params {
84 let raw = crate::cli::read_at_or_stdin(params)?;
85 let parsed: Value = serde_json::from_str(&raw).context("--params is not valid JSON")?;
86 tool_args.insert("params".into(), parsed);
87 }
88 if let Some(s) = &args.params_schema {
89 let raw = crate::cli::read_at_or_stdin(s)?;
90 let parsed: Value =
91 serde_json::from_str(&raw).context("--params-schema is not valid JSON")?;
92 tool_args.insert("params_schema".into(), parsed);
93 }
94 if let Some(t) = &args.render_template {
95 tool_args.insert(
96 "render_template".into(),
97 Value::String(crate::cli::read_at_or_stdin(t)?),
98 );
99 }
100 if args.merge {
101 tool_args.insert("merge".into(), Value::Bool(true));
102 }
103 if args.append_mode {
104 tool_args.insert("append_mode".into(), Value::Bool(true));
105 }
106 if let Some(cap) = args.history_cap {
107 tool_args.insert("history_cap".into(), Value::Number(cap.into()));
108 }
109
110 let tool = crate::librarian::tools::augment::ArtifactAugment;
113 let v = tool.call(&ctx, Value::Object(tool_args)).await?;
114 crate::cli::format::print(&v, &output)?;
115 Ok(())
116}