Skip to content

gptel having issue correctly parsing array data when calling tools. #924

@beacoder

Description

@beacoder

Please update gptel first -- errors are often fixed by the time they're reported.

  • I have updated gptel to the latest commit and tested that the issue still exists

Bug Description

I have defined an edit_file tool as below, most of the time, when I try to use gptel to edit file.
when the tool got invoked, the args are (nil nil).

(gptel-make-tool
 :function #'my-gptel--edit_file
 :name "edit_file"
 :description "Edit file with a list of edits, each edit contains a line-number,
a old-string and a new-string, new-string will replace the old-string at the specified line."
 :args (list '(:name "file-path"
                     :type string
                     :description "The full path of the file to edit")
             '(:name "file-edits"
                     :type array
                     :items (:type object
                                   :properties
                                   (:line_number
                                    (:type integer :description "The line number of the file where edit starts.")
                                    :old_string
                                    (:type string :description "The old-string to be replaced.")
                                    :new_string
                                    (:type string :description "The new-string to replace old-string.")))
                     :description "The list of edits to apply on the file"))
 :category "filesystem")

(defun my-gptel--edit_file (file-path file-edits)
  "In FILE-PATH, apply FILE-EDITS with pattern matching and replacing."
  (if (and file-path (not (string= file-path "")) file-edits)
      (with-current-buffer (get-buffer-create "*edit-file*")
        (insert-file-contents (expand-file-name file-path))
        (let ((inhibit-read-only t)
              (case-fold-search nil)
              (file-name (expand-file-name file-path))
              (edit-success nil))
          ;; apply changes
          (dolist (file-edit (seq-into file-edits 'list))
            (when-let ((line-number (plist-get file-edit :line_number))
                       (old-string (plist-get file-edit :old_string))
                       (new-string (plist-get file-edit :new_string))
                       (is-valid-old-string (not (string= old-string ""))))
              (goto-char (point-min))
              (forward-line (1- line-number))
              (when (search-forward old-string nil t)
                (replace-match new-string t t)
                (setq edit-success t))))
          ;; return result to gptel
          (if edit-success
              (progn
                ;; show diffs
                (ediff-buffers (find-file-noselect file-name) (current-buffer))
                (format "Successfully edited %s" file-name))
            (format "Failed to edited %s" file-name))))
    (format "Failed to edited %s" file-path)))

Backend

None

Steps to Reproduce

define the tool use the code as I provided.
then use gptel to select the edit_file and read_file as well.
then use prompt to ask gptel to make some modification to any file.
then edit_file tool will be called, and you will see most of the time, the args will be (nil nil).

Additional Context

GNU Emacs 30.1 (build 1, x86_64-pc-linux-gnu, X toolkit, Xaw scroll bars) of 2025-03-03

(defun my-gptel--read_file(filepath)
  (with-temp-message (format "Reading file: %s" filepath)
    (with-temp-buffer
      (insert-file-contents (expand-file-name filepath))
      (buffer-string))))

(gptel-make-tool
 :function #'my-gptel--read_file
 :name "read_file"
 :description "Read and display the contents of a file."
 :args (list '(:name "filepath"
                     :type string
                     :description "Path to the file to read.  Supports relative paths and ~."))
 :category "filesystem")

Backtrace

Log Information

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingwaitingWaiting for a response from another party.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions