steer_tools/tools/
edit.rs1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3use thiserror::Error;
4
5use crate::ToolSpec;
6use crate::error::{ToolExecutionError, WorkspaceOpError};
7use crate::result::{EditResult, MultiEditResult};
8
9pub const EDIT_TOOL_NAME: &str = "edit_file";
10
11pub struct EditToolSpec;
12
13impl ToolSpec for EditToolSpec {
14 type Params = EditParams;
15 type Result = EditResult;
16 type Error = EditError;
17
18 const NAME: &'static str = EDIT_TOOL_NAME;
19 const DISPLAY_NAME: &'static str = "Edit File";
20
21 fn execution_error(error: Self::Error) -> ToolExecutionError {
22 ToolExecutionError::Edit(error)
23 }
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Error)]
27#[serde(tag = "code", content = "details", rename_all = "snake_case")]
28pub enum EditFailure {
29 #[error("file not found: {file_path}")]
30 FileNotFound { file_path: String },
31
32 #[error(
33 "edit #{edit_index} has an empty old_string; use write_file to create or overwrite files"
34 )]
35 EmptyOldString { edit_index: usize },
36
37 #[error("string not found for edit #{edit_index} in file {file_path}")]
38 StringNotFound {
39 file_path: String,
40 edit_index: usize,
41 },
42
43 #[error(
44 "found {occurrences} matches for edit #{edit_index} in file {file_path}; old_string must match exactly once"
45 )]
46 NonUniqueMatch {
47 file_path: String,
48 edit_index: usize,
49 occurrences: usize,
50 },
51}
52
53#[derive(Deserialize, Serialize, Debug, JsonSchema, Clone, Error)]
54#[serde(tag = "code", content = "details", rename_all = "snake_case")]
55pub enum EditError {
56 #[error("{0}")]
57 Workspace(WorkspaceOpError),
58
59 #[error("{0}")]
60 EditFailure(EditFailure),
61}
62
63#[derive(Deserialize, Serialize, Debug, JsonSchema, Clone)]
64pub struct SingleEditOperation {
65 pub old_string: String,
67 pub new_string: String,
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
72pub struct EditParams {
73 pub file_path: String,
75 pub old_string: String,
77 pub new_string: String,
79}
80
81pub mod multi_edit {
82 use super::{
83 Deserialize, EditFailure, Error, JsonSchema, MultiEditResult, Serialize,
84 SingleEditOperation, ToolExecutionError, ToolSpec, WorkspaceOpError,
85 };
86
87 pub const MULTI_EDIT_TOOL_NAME: &str = "multi_edit";
88
89 pub struct MultiEditToolSpec;
90
91 impl ToolSpec for MultiEditToolSpec {
92 type Params = MultiEditParams;
93 type Result = MultiEditResult;
94 type Error = MultiEditError;
95
96 const NAME: &'static str = MULTI_EDIT_TOOL_NAME;
97 const DISPLAY_NAME: &'static str = "Multi Edit";
98
99 fn execution_error(error: Self::Error) -> ToolExecutionError {
100 ToolExecutionError::MultiEdit(error)
101 }
102 }
103
104 #[derive(Deserialize, Serialize, Debug, JsonSchema, Clone, Error)]
105 #[serde(tag = "code", content = "details", rename_all = "snake_case")]
106 pub enum MultiEditError {
107 #[error("{0}")]
108 Workspace(WorkspaceOpError),
109
110 #[error("{0}")]
111 EditFailure(EditFailure),
112 }
113
114 #[derive(Deserialize, Serialize, Debug, JsonSchema)]
115 pub struct MultiEditParams {
116 pub file_path: String,
118 pub edits: Vec<SingleEditOperation>,
120 }
121}