Skip to main content

yoagent_state/
observer.rs

1use crate::{ArtifactRef, NodeId, PatchId, ProjectRef, StateOp};
2use serde_json::json;
3use std::path::Path;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct ChangedFile {
7    pub path: String,
8    pub status: String,
9}
10
11pub fn parse_git_name_status(raw: &str) -> Vec<ChangedFile> {
12    raw.lines()
13        .filter_map(|line| {
14            let mut parts = line.split_whitespace();
15            let status = parts.next()?;
16            let path = parts.next()?;
17            Some(ChangedFile {
18                path: path.to_string(),
19                status: status.to_string(),
20            })
21        })
22        .collect()
23}
24
25pub fn diff_artifact(
26    diff_path: impl AsRef<Path>,
27    summary: impl Into<String>,
28    base_commit: impl Into<String>,
29    files: &[ChangedFile],
30) -> ArtifactRef {
31    ArtifactRef::new(
32        "git.diff",
33        format!("file://{}", diff_path.as_ref().display()),
34    )
35    .with_summary(summary)
36    .with_metadata(json!({
37        "base_commit": base_commit.into(),
38        "files_changed": files.iter().map(|file| &file.path).collect::<Vec<_>>(),
39    }))
40}
41
42pub fn project_ref(
43    repo: impl Into<String>,
44    branch: Option<String>,
45    commit: Option<String>,
46    worktree: Option<String>,
47) -> ProjectRef {
48    ProjectRef {
49        repo: repo.into(),
50        branch,
51        commit,
52        worktree,
53    }
54}
55
56pub fn changed_file_ops(patch_id: PatchId, files: &[ChangedFile]) -> Vec<StateOp> {
57    let patch_node_id = NodeId::new(patch_id.0);
58    let mut ops = Vec::new();
59    for file in files {
60        let file_id = NodeId::new(format!("file:{}", file.path));
61        ops.push(StateOp::CreateNode {
62            id: file_id.clone(),
63            kind: "file".to_string(),
64            props: json!({ "path": file.path, "status": file.status }),
65        });
66        ops.push(StateOp::CreateRelation {
67            from: patch_node_id.clone(),
68            rel: "modifies".to_string(),
69            to: file_id,
70            props: json!({ "status": file.status }),
71        });
72    }
73    ops
74}