MCPcopy Create free account
hub / github.com/GongShichen/LuminaCode / ValidateInput

Method ValidateInput

tools/builtin.go:166–225  ·  view source on GitHub ↗
(execCtx ExecutionContext, input any)

Source from the content-addressed store, hash-verified

164}
165
166func (t *EditFileTool) ValidateInput(execCtx ExecutionContext, input any) (bool, string) {
167 in := deref[EditFileInput](input)
168 path := resolveToolPath(execCtx, in.FilePath)
169 if ok, msg := checkAllowedWriteRoots(path, execCtx["allowed_write_roots"]); !ok {
170 return false, formatEditError(editFileNotFound, msg)
171 }
172 if in.OldString == in.NewString {
173 return false, formatEditError(editNoOp, "old_string and new_string must be different.")
174 }
175 info, err := os.Stat(path)
176 if err != nil {
177 hint := ""
178 if !filepath.IsAbs(in.FilePath) {
179 hint = " (path is relative — use absolute paths)"
180 }
181 return false, formatEditError(editFileNotFound, fmt.Sprintf("File not found: %s%s", in.FilePath, hint))
182 }
183 if !info.Mode().IsRegular() {
184 return false, formatEditError(editFileNotFound, fmt.Sprintf("Not a file: %s", in.FilePath))
185 }
186 if strings.EqualFold(filepath.Ext(path), ".ipynb") {
187 return false, formatEditError(editNotebookRedirect, fmt.Sprintf("Notebook files must use notebook_edit tool: %s", in.FilePath))
188 }
189 if in.OldString != "" && !truthy(execCtx["skip_read_before_edit"]) {
190 owner, _ := execCtx["parent_state"].(readFileStateOwner)
191 if owner == nil {
192 return false, formatEditError(editUnreadFile, "File has not been read yet. Read it first before editing.")
193 }
194 fileState, ok := owner.GetReadFileState(path)
195 if !ok {
196 fileState, ok = owner.GetReadFileState(in.FilePath)
197 }
198 if !ok {
199 return false, formatEditError(editUnreadFile, "File has not been read yet. Read it first before editing.")
200 }
201 if fileState.IsPartialView {
202 return false, formatEditError(editUnreadFile, "File was only partially read. Re-read the full file before editing.")
203 }
204 currentMTime := fileMTime(path)
205 if currentMTime > fileState.TimeStamp {
206 if runtime.GOOS == "windows" {
207 data, err := os.ReadFile(path)
208 if err != nil {
209 return false, formatEditError(editStaleRead, "File has been modified since it was last read. Re-read the file before editing.")
210 }
211 currentContent := strings.ReplaceAll(decodeToolBytes(data), "\r\n", "\n")
212 cachedContent := strings.ReplaceAll(fileState.Content, "\r\n", "\n")
213 if currentContent == cachedContent {
214 fileState.TimeStamp = currentMTime
215 owner.SetReadFileState(path, fileState)
216 } else {
217 return false, formatEditError(editStaleRead, "File has been modified since it was last read. Re-read the file before editing.")
218 }
219 } else {
220 return false, formatEditError(editStaleRead, "File has been modified since it was last read. Re-read the file before editing.")
221 }
222 }
223 }

Callers

nothing calls this directly

Calls 8

resolveToolPathFunction · 0.85
checkAllowedWriteRootsFunction · 0.85
formatEditErrorFunction · 0.85
fileMTimeFunction · 0.85
decodeToolBytesFunction · 0.85
truthyFunction · 0.70
GetReadFileStateMethod · 0.65
SetReadFileStateMethod · 0.65

Tested by

no test coverage detected