Skip to main content

elizaos_plugin_code/actions/
edit_file.rs

1use async_trait::async_trait;
2use serde_json::Value;
3
4use crate::service::CoderService;
5use crate::{Action, ActionExample, ActionResult};
6
7pub struct EditFileAction;
8
9#[async_trait]
10impl Action for EditFileAction {
11    fn name(&self) -> &str {
12        "EDIT_FILE"
13    }
14
15    fn similes(&self) -> Vec<&str> {
16        vec!["REPLACE_IN_FILE", "PATCH_FILE", "MODIFY_FILE"]
17    }
18
19    fn description(&self) -> &str {
20        "Replace a substring in a file (single replacement)."
21    }
22
23    async fn validate(&self, _message: &Value, _state: &Value) -> bool {
24        true
25    }
26
27    async fn handler(
28        &self,
29        message: &Value,
30        state: &Value,
31        service: Option<&mut CoderService>,
32    ) -> ActionResult {
33        let Some(svc) = service else {
34            return ActionResult {
35                success: false,
36                text: "Coder service is not available.".to_string(),
37                data: None,
38                error: Some("missing_service".to_string()),
39            };
40        };
41
42        let filepath = state.get("filepath").and_then(|v| v.as_str()).unwrap_or("");
43        let old_str = state.get("old_str").and_then(|v| v.as_str()).unwrap_or("");
44        let new_str = state.get("new_str").and_then(|v| v.as_str()).unwrap_or("");
45
46        if filepath.trim().is_empty() || old_str.is_empty() {
47            return ActionResult {
48                success: false,
49                text: "Missing filepath or old_str.".to_string(),
50                data: None,
51                error: Some("missing_args".to_string()),
52            };
53        }
54
55        let conv = message
56            .get("room_id")
57            .and_then(|v| v.as_str())
58            .or_else(|| message.get("agent_id").and_then(|v| v.as_str()))
59            .unwrap_or("default");
60
61        match svc.edit_file(conv, filepath, old_str, new_str).await {
62            Ok(()) => ActionResult {
63                success: true,
64                text: format!("Edited {}", filepath),
65                data: None,
66                error: None,
67            },
68            Err(err) => ActionResult {
69                success: false,
70                text: err,
71                data: None,
72                error: Some("edit_failed".to_string()),
73            },
74        }
75    }
76
77    fn examples(&self) -> Vec<ActionExample> {
78        vec![ActionExample {
79            user_message: "edit file".to_string(),
80            agent_response: "Editing…".to_string(),
81        }]
82    }
83}