use anyhow::Result;
use clap::{Args, Subcommand};
use serde_json::Value;
use crate::cli::{open_ctx, CommonOpts};
#[derive(Debug, Subcommand)]
pub enum Verb {
List(ListArgs),
Create(CreateArgs),
}
#[derive(Debug, Args)]
pub struct ListArgs {
#[arg(long = "artifact-id")]
pub artifact_id: String,
#[arg(long)]
pub kinds: Option<String>,
#[arg(long)]
pub since: Option<i64>,
#[arg(long)]
pub until: Option<i64>,
#[arg(long, default_value_t = 50)]
pub limit: usize,
#[arg(long)]
pub project: Option<std::path::PathBuf>,
#[arg(long)]
pub json: bool,
#[arg(long = "no-color")]
pub no_color: bool,
}
pub async fn dispatch(verb: Verb) -> Result<()> {
match verb {
Verb::List(args) => run_list(args).await,
Verb::Create(args) => run_create(args).await,
}
}
async fn run_list(args: ListArgs) -> Result<()> {
let common = CommonOpts {
project: args.project.clone(),
json: args.json,
no_color: args.no_color,
};
let output = common.output();
let ctx = open_ctx(&common).await?;
let mut tool_args = serde_json::Map::new();
tool_args.insert("action".into(), Value::String("list".into()));
tool_args.insert(
"artifact_id".into(),
Value::String(args.artifact_id.clone()),
);
if let Some(k) = &args.kinds {
let list: Vec<Value> = k
.split(',')
.map(|s| Value::String(s.trim().into()))
.collect();
tool_args.insert("kinds".into(), Value::Array(list));
}
if let Some(s) = args.since {
tool_args.insert("since".into(), Value::Number(s.into()));
}
if let Some(u) = args.until {
tool_args.insert("until".into(), Value::Number(u.into()));
}
tool_args.insert("limit".into(), Value::Number(args.limit.into()));
let v = crate::librarian::tools::timeline::call(&ctx, Value::Object(tool_args)).await?;
crate::cli::format::print(&v, &output)?;
Ok(())
}
#[derive(Debug, Args)]
pub struct CreateArgs {
#[arg(long = "artifact-id")]
pub artifact_id: String,
#[arg(long)]
pub kind: String,
#[arg(long)]
pub payload: Option<String>,
#[arg(long)]
pub author: Option<String>,
#[arg(long = "anchor-commit")]
pub anchor_commit: Option<String>,
#[arg(long = "head-commit")]
pub head_commit: Option<String>,
#[arg(long = "parent-event-id")]
pub parent_event_id: Option<String>,
#[arg(long = "resolves-intent-event-id")]
pub resolves_intent_event_id: Option<String>,
#[arg(long = "also-mutates")]
pub also_mutates: Option<String>,
#[arg(long = "source-uri")]
pub source_uri: Option<String>,
#[arg(long = "source-kind")]
pub source_kind: Option<String>,
#[arg(long)]
pub project: Option<std::path::PathBuf>,
#[arg(long)]
pub json: bool,
#[arg(long = "no-color")]
pub no_color: bool,
}
async fn run_create(args: CreateArgs) -> Result<()> {
use anyhow::Context;
let common = CommonOpts {
project: args.project.clone(),
json: args.json,
no_color: args.no_color,
};
let output = common.output();
let ctx = open_ctx(&common).await?;
let mut tool_args = serde_json::Map::new();
tool_args.insert(
"artifact_id".into(),
Value::String(args.artifact_id.clone()),
);
tool_args.insert("kind".into(), Value::String(args.kind.clone()));
let payload_value: Value = if let Some(p) = &args.payload {
let raw = crate::cli::read_at_or_stdin(p)?;
serde_json::from_str(&raw).context("--payload is not valid JSON")?
} else {
Value::Object(serde_json::Map::new())
};
tool_args.insert("payload".into(), payload_value);
if let Some(a) = &args.author {
tool_args.insert("author".into(), Value::String(a.clone()));
}
if let Some(c) = &args.anchor_commit {
tool_args.insert("anchor_commit".into(), Value::String(c.clone()));
}
if let Some(c) = &args.head_commit {
tool_args.insert("head_commit".into(), Value::String(c.clone()));
}
if let Some(p) = &args.parent_event_id {
tool_args.insert("parent_event_id".into(), Value::String(p.clone()));
}
if let Some(p) = &args.resolves_intent_event_id {
tool_args.insert("resolves_intent_event_id".into(), Value::String(p.clone()));
}
if let Some(m) = &args.also_mutates {
let list: Vec<Value> = m
.split(',')
.filter(|s| !s.trim().is_empty())
.map(|s| Value::String(s.trim().into()))
.collect();
tool_args.insert("also_mutates".into(), Value::Array(list));
}
match (&args.source_uri, &args.source_kind) {
(Some(uri), Some(kind)) => {
tool_args.insert(
"source".into(),
serde_json::json!({
"uri": uri,
"kind": kind,
}),
);
}
(None, None) => {}
_ => {
return Err(anyhow::anyhow!(
"--source-uri and --source-kind must be passed together"
));
}
}
let v = crate::librarian::tools::event_create::call(&ctx, Value::Object(tool_args)).await?;
crate::cli::format::print(&v, &output)?;
Ok(())
}