Skip to main content

assay_core/agentic/
mod.rs

1// crates/assay-core/src/agentic/mod.rs
2// A reusable "Agentic Contract" builder that turns Diagnostics into:
3// - suggested_actions (commands to run)
4// - suggested_patches (JSON Patch ops, machine-applicable)
5//
6// This is intentionally conservative + deterministic.
7
8use serde::{Deserialize, Serialize};
9use serde_json::Value as JsonValue;
10use std::path::PathBuf;
11
12use crate::errors::diagnostic::Diagnostic;
13
14mod builder;
15mod policy_helpers;
16
17#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
18#[serde(rename_all = "lowercase")]
19pub enum RiskLevel {
20    Low,
21    Medium,
22    High,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct SuggestedAction {
27    pub id: String,
28    pub title: String,
29    pub risk: RiskLevel,
30    pub command: Vec<String>,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct SuggestedPatch {
35    pub id: String,
36    pub title: String,
37    pub risk: RiskLevel,
38    pub file: String, // path relative to cwd (or absolute)
39    pub ops: Vec<JsonPatchOp>,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
43#[serde(tag = "op", rename_all = "lowercase")]
44pub enum JsonPatchOp {
45    Add { path: String, value: JsonValue },
46    Remove { path: String },
47    Replace { path: String, value: JsonValue },
48    Move { from: String, path: String },
49}
50
51/// Context for Agentic suggestions.
52///
53/// This provides the "world view" needed to generate relevant fixes,
54/// such as where the policy file is located or what the assay config path is.
55pub struct AgenticCtx {
56    /// Optional: path to the *policy* file (policy.yaml).
57    /// If not set, we fall back to diagnostics.context.policy_file or "policy.yaml".
58    pub policy_path: Option<PathBuf>,
59
60    /// Optional: path to the *assay config* file (assay.yaml).
61    /// If not set, we fall back to diagnostics.context.config_file or "assay.yaml".
62    pub config_path: Option<PathBuf>,
63}
64
65/// Main entrypoint: build suggestions for any diagnostics list.
66///
67/// Analyzes a list of `Diagnostic` items and generates:
68/// 1. `SuggestedAction`: High-level commands (e.g., `assay fix`, `mkdir`).
69/// 2. `SuggestedPatch`: Concrete JSON Patch operations to apply to files.
70///
71/// The generation is deterministic and stateless (except for reading files referenced in context).
72pub fn build_suggestions(
73    diags: &[Diagnostic],
74    ctx: &AgenticCtx,
75) -> (Vec<SuggestedAction>, Vec<SuggestedPatch>) {
76    builder::build_suggestions_impl(diags, ctx)
77}
78
79#[cfg(test)]
80mod tests;