Skip to main content

kaizen/shell/
rules.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2use crate::core_loop::{AlertSeverity, RuleAction, rules, time};
3use crate::shell::cli::workspace_path;
4use crate::store::Store;
5use anyhow::{Result, anyhow};
6use std::path::Path;
7
8pub fn cmd_rules_create(
9    workspace: Option<&Path>,
10    name: &str,
11    filter: &str,
12    action: &str,
13    message: Option<String>,
14) -> Result<()> {
15    let rule = rules::create(
16        &open(workspace)?,
17        name,
18        filter,
19        parse_action(action, message)?,
20        time::now_ms(),
21    )?;
22    println!("created rule {} ยท {}", rule.id, rule.name);
23    Ok(())
24}
25
26pub fn cmd_rules_list(workspace: Option<&Path>, json: bool) -> Result<()> {
27    let rows = rules::list(&open(workspace)?)?;
28    if json {
29        println!("{}", serde_json::to_string_pretty(&rows)?);
30    } else {
31        rows.iter()
32            .for_each(|r| println!("{} enabled={} {}", r.id, r.enabled, r.name));
33    }
34    Ok(())
35}
36
37pub fn cmd_rules_run(
38    workspace: Option<&Path>,
39    since: Option<&str>,
40    dry_run: bool,
41    json: bool,
42) -> Result<()> {
43    let ws = workspace_path(workspace)?;
44    let store = Store::open(&crate::core::workspace::db_path(&ws)?)?;
45    let rows = rules::run_enabled(
46        &store,
47        &ws.to_string_lossy(),
48        time::parse_window(since, 7)?,
49        time::now_ms(),
50        dry_run,
51    )?;
52    if json {
53        println!("{}", serde_json::to_string_pretty(&rows)?);
54    } else {
55        rows.iter()
56            .for_each(|r| println!("{} hits={} actions={}", r.rule_id, r.hits, r.actions));
57    }
58    Ok(())
59}
60
61pub fn cmd_rules_enable(workspace: Option<&Path>, id: &str, enabled: bool) -> Result<()> {
62    rules::set_enabled(&open(workspace)?, id, enabled)?;
63    println!("{} rule {id}", if enabled { "enabled" } else { "disabled" });
64    Ok(())
65}
66
67fn open(workspace: Option<&Path>) -> Result<Store> {
68    let ws = workspace_path(workspace)?;
69    Store::open(&crate::core::workspace::db_path(&ws)?)
70}
71
72fn parse_action(raw: &str, message: Option<String>) -> Result<RuleAction> {
73    Ok(match raw {
74        "create_case" => RuleAction::CreateCase { label: message },
75        "queue_review" => RuleAction::QueueReview { title: message },
76        "emit_alert" => RuleAction::EmitAlert {
77            severity: AlertSeverity::Warning,
78        },
79        _ => {
80            return Err(anyhow!(
81                "action must be create_case, queue_review, or emit_alert"
82            ));
83        }
84    })
85}