diff options
| author | Vineet Kumar <git@vineetk.net> | 2026-05-25 13:25:29 -0400 |
|---|---|---|
| committer | Vineet Kumar <git@vineetk.net> | 2026-05-25 13:25:29 -0400 |
| commit | 008cb42c3cd44c2220944966dfd9095edf12b98e (patch) | |
| tree | 63a1194d6b3b7ad866715edd86e8ac97b13d9d74 /llm-tools-hl.el | |
| parent | b052ec7ded67ba5f187b00291aa58cc38856c826 (diff) | |
start working on hashline diff applying
Diffstat (limited to 'llm-tools-hl.el')
| -rw-r--r-- | llm-tools-hl.el | 59 |
1 files changed, 40 insertions, 19 deletions
diff --git a/llm-tools-hl.el b/llm-tools-hl.el index 3072ffc..b4ca40a 100644 --- a/llm-tools-hl.el +++ b/llm-tools-hl.el | |||
| @@ -99,12 +99,6 @@ Each element is a line number and two-character hash, like `1vx'." | |||
| 99 | (let ((lines (llm-tools--hl-file-lines file))) | 99 | (let ((lines (llm-tools--hl-file-lines file))) |
| 100 | (llm-tools--hl-hash (elt lines (1- n))))) | 100 | (llm-tools--hl-hash (elt lines (1- n))))) |
| 101 | 101 | ||
| 102 | ;; before applying patch, first read the file to see if there were any changes | ||
| 103 | ;; if the llm's replacement text's hashlines do not match current hashlines, reject the request | ||
| 104 | ;; maybe if it just shifted a little bit (since the anchor is line number and hash of the line's content), there can be some kind of autohealing? | ||
| 105 | ;; rather, the llm would not format it like the reads. it's just going to provide text according to what the anchors it gives say | ||
| 106 | ;; so I just need to verify if the anchors didn't change | ||
| 107 | |||
| 108 | ;;;; Diff Parsing | 102 | ;;;; Diff Parsing |
| 109 | (defun llm-tools--split-patch-sections (patch) | 103 | (defun llm-tools--split-patch-sections (patch) |
| 110 | "Return a list of (FILENAME . REST) cons cells from PATCH. | 104 | "Return a list of (FILENAME . REST) cons cells from PATCH. |
| @@ -149,7 +143,7 @@ the operations in that file's sections. Each anchor is a string like | |||
| 149 | (string-lines (cdr patch)))))))) | 143 | (string-lines (cdr patch)))))))) |
| 150 | sections)))) | 144 | sections)))) |
| 151 | 145 | ||
| 152 | (defun llm-tools--hl-verify (patch) | 146 | (defun llm-tools--hl-verify-anchors (patch) |
| 153 | "Verify that all anchors in PATCH match the current file contents. | 147 | "Verify that all anchors in PATCH match the current file contents. |
| 154 | Returns a list of booleans, one per file, indicating whether every | 148 | Returns a list of booleans, one per file, indicating whether every |
| 155 | anchor in that file's patch sections still matches the corresponding | 149 | anchor in that file's patch sections still matches the corresponding |
| @@ -163,6 +157,42 @@ line in the on-disk file." | |||
| 163 | (cons file (cl-subsetp anchors hl :test #'equal)))) | 157 | (cons file (cl-subsetp anchors hl :test #'equal)))) |
| 164 | patch-anchors))) | 158 | patch-anchors))) |
| 165 | 159 | ||
| 160 | (defun llm-tools--hl-verify (patch) | ||
| 161 | "Verify if the files in PATCH need to be re-read. | ||
| 162 | Returns a string message that states which files need to be re-read. | ||
| 163 | Empty string means no files need to be re-read." | ||
| 164 | (string-join | ||
| 165 | (delete-dups | ||
| 166 | (remq nil | ||
| 167 | (mapcar (lambda (elem) | ||
| 168 | (unless (cdr elem) | ||
| 169 | (format "%s had incorrect anchors. Use the 'read_file' tool to get correct anchors." | ||
| 170 | (car elem)))) | ||
| 171 | (llm-tools--hl-verify-anchors patch)))) | ||
| 172 | "\n")) | ||
| 173 | |||
| 174 | (defun llm-tools--hl-parse-section (section) | ||
| 175 | "Parses operation and optional payload from SECTION." | ||
| 176 | ) | ||
| 177 | |||
| 178 | (defun llm-tools--hl-apply (patch) | ||
| 179 | "TODO rewrite docstring. Applies a patch." | ||
| 180 | ;; when performing each operation, I need to make sure that the line | ||
| 181 | ;; numbers of subsequent operations in same file also get updated. | ||
| 182 | (let ((sections (split-patch-sections patch))) | ||
| 183 | (llm-tools--hl-parse sections))) | ||
| 184 | |||
| 185 | (defun llm-tools--hl-edit (patch) | ||
| 186 | "TODO write better docstring. First verifies if any files in PATCH needs | ||
| 187 | to be re-read. Then, applies the changes in PATCH. If any files need to | ||
| 188 | be re-read, the edit operation is cancelled for all files." | ||
| 189 | (let ((msg (llm-tools--hl-verify patch))) | ||
| 190 | (if (string= msg "") | ||
| 191 | (progn | ||
| 192 | (llm-tools--hl-apply patch) | ||
| 193 | (format "Finished applying patch.")) | ||
| 194 | (format "%s" msg)))) | ||
| 195 | |||
| 166 | (let* ((patch "\ | 196 | (let* ((patch "\ |
| 167 | # Replace one line (the payload must re-emit the original indentation) | 197 | # Replace one line (the payload must re-emit the original indentation) |
| 168 | @@ mod.ts | 198 | @@ mod.ts |
| @@ -190,22 +220,13 @@ line in the on-disk file." | |||
| 190 | ~export const done = true; | 220 | ~export const done = true; |
| 191 | 221 | ||
| 192 | # Delete a line | 222 | # Delete a line |
| 193 | @@ test.el | 223 | @@ mod.ts |
| 194 | - 5ff..5ff | 224 | - 5ff..5ff |
| 195 | 225 | ||
| 196 | # Blank a line (replace with LF) | 226 | # Blank a line (replace with LF) |
| 197 | @@ mod.ts | 227 | @@ mod.ts |
| 198 | = 5bb..5bb | 228 | = 5ff..5ff |
| 199 | ")) | 229 | ")) |
| 200 | (string-join | 230 | (llm-tools--hl-apply patch)) |
| 201 | (delete-dups | ||
| 202 | (remq nil | ||
| 203 | (mapcar (lambda (elem) | ||
| 204 | (unless (cdr elem) | ||
| 205 | (format "%s had incorrect anchors. Use the 'read_file' tool to get correct anchors." | ||
| 206 | (car elem)))) | ||
| 207 | (llm-tools--hl-verify patch)))) | ||
| 208 | "\n")) | ||
| 209 | 231 | ||
| 210 | (provide 'llm-tools-hl) | 232 | (provide 'llm-tools-hl) |
| 211 | |||
