diff --git a/README.org b/README.org index cf30820..f94b764 100644 --- a/README.org +++ b/README.org @@ -118,13 +118,12 @@ Stuff, headers, etc. ;; All documentation regarding these functions is in the README.org file. ;; Repository: https://git.bajsicki.com/phil/gptel-org-tools -;;; Code: +;;; Code:) #+end_src ** The tools *** Emacs These tools are primarily concerned with Emacs, Emacs Lisp, and files-or-buffers. - **** eval Dangerous, but occasionally useful for pure chaos and amusement... I would like to say. But in actuality, especially with the 'smarter' models, they can surprise with the varied approaches they have to problem-solving. @@ -134,6 +133,7 @@ E.g. can't find the right ~org-ql-select~ query? Let's use an eldritch abominati Highly not recommended, but sometimes an LLM can pull a rabbit out of pure entropy. #+begin_src elisp :tangle no +(add-to-list 'gptel-tools (gptel-make-tool :function (lambda (elisp) (unless (stringp elisp) (error "elisp code must be a string")) @@ -145,7 +145,7 @@ Highly not recommended, but sometimes an LLM can pull a rabbit out of pure entro :args (list '(:name "eval" :type string :description "The Emacs Lisp code to evaluate.")) - :category "emacs") + :category "emacs")) #+end_src **** list-buffers @@ -155,6 +155,7 @@ The rationale behind using ~ibuffer~ is the same as with dired. They both displa Seems to be one of the most reliable tools in the basket... mostly because #+begin_src elisp +(add-to-list 'gptel-tools (gptel-make-tool :function (lambda (arg) (with-temp-buffer @@ -168,7 +169,7 @@ Seems to be one of the most reliable tools in the basket... mostly because :type string :description "Does nothing." :optional t)) - :category "emacs") + :category "emacs")) #+end_src **** dired See above, same reasoning. There's very little reason to use the ~directory-files~ function for this (as in another tool I saw.) The reason is, ~directory-files~ doesn't provide nearly as much information about the items in that directory. Not even a distinction between files and directories. @@ -180,6 +181,7 @@ Be sure to customize the function to point to your org directory, if you wish. I #+end_comment #+begin_src elisp +(add-to-list 'gptel-tools (gptel-make-tool :function (lambda (dir) (with-temp-buffer @@ -193,11 +195,12 @@ Be sure to customize the function to point to your org directory, if you wish. I :type string :description "Directory path" :optional t)) - :category "filesystem") + :category "filesystem")) #+end_src **** find-buffer-visiting #+begin_src elisp +(add-to-list 'gptel-tools (gptel-make-tool :function (lambda (filename) (bufferp (find-buffer-visiting (expand-file-name filename)))) @@ -206,11 +209,12 @@ Be sure to customize the function to point to your org directory, if you wish. I :args (list '(:name "filename" :type string :description "The filename to compare to open buffers.")) - :category "org-mode") + :category "org-mode")) #+end_src **** find-file-noselect Continuation from above. Open a file into a buffer for processing. Onec it's found by dired-list. #+begin_src elisp +(add-to-list 'gptel-tools (gptel-make-tool :function (lambda (file) (find-file-noselect file)) @@ -219,7 +223,57 @@ Continuation from above. Open a file into a buffer for processing. Onec it's fou :args (list '(:name "file" :type string :description "Path to file..")) - :category "filesystem") + :category "filesystem")) +#+end_src +**** read-file-contents +This reads file contents, +#+begin_src elisp +(add-to-list 'gptel-tools + (gptel-make-tool + :function (lambda (filename) + (with-temp-buffer + (insert-file-contents (expand-file-name filename)) + (buffer-string))) + :name "read-file-contents" + :description "Read and return the contents of a specified file." + :args (list '(:name "filename" + :type string + :description "The filename to read.")) + :category "org-mode")) +#+end_src +**** describe-variable +#+begin_src elisp +(add-to-list 'gptel-tools + (gptel-make-tool + :function (lambda (var) + (let ((symbol (intern var))) + (if (boundp symbol) + (prin1-to-string (symbol-value symbol)) + (format "Variable %s is not bound." var)))) + :name "describe-variable" + :description "See variable contents" + :args (list '(:name "var" + :type string + :description "Variable name")) + :category "emacs")) +#+end_src + +**** describe-function +#+begin_src elisp +(add-to-list 'gptel-tools + (gptel-make-tool + :function (lambda (fun) + (let ((symbol (intern fun))) + (if (fboundp symbol) + (prin1-to-string (documentation symbol 'function)) + (format "Function %s is not defined." fun)))) + :name "describe-function" + :description "See function description" + :args (list '(:name "fun" + :type string + :description "Function name" + :optional t)) + :category "emacs")) #+end_src *** Org-mode @@ -252,7 +306,7 @@ Pretty simple, does what it says on the tin. It gets all the tags from the =buff This is not, by any means, sufficient, but I do tag people and specific events frequently enough that it helps save on the context window. #+begin_src elisp -(defun gptel-org-tools-org-extract-tags (buffer) +(defun gptel-org-tools--org-extract-tags (buffer) (interactive "bBuffer: ") (with-current-buffer buffer (let ((tags '())) @@ -265,14 +319,15 @@ This is not, by any means, sufficient, but I do tag people and specific events f (push tag tags)))))) (sort (-uniq tags) #'string<)))) +(add-to-list 'gptel-tools (gptel-make-tool - :function #'gptel-org-tools-org-extract-tags + :function #'gptel-org-tools--org-extract-tags :name "org-extract-tags" :description "Extract all unique tags from an org-mode buffer" :args (list '(:name "buffer" :type string :description "The Org buffer to extract tags from.")) - :category "org-mode") + :category "org-mode")) #+end_src **** org-extract-headings But what if there's no tags related to the topic? @@ -281,7 +336,7 @@ Then we need to pull /some/ information from the buffer, without dragging the en Therefore, headings. A reasonable amount of information, and still keeping the signal-to-noise ratio pretty decent. #+begin_src elisp -(defun gptel-org-tools-org-extract-headings (buffer) +(defun gptel-org-tools--org-extract-headings (buffer) (interactive "bBuffer: ") (with-current-buffer buffer (org-map-entries @@ -291,14 +346,15 @@ Therefore, headings. A reasonable amount of information, and still keeping the s t 'file))) +(add-to-list 'gptel-tools (gptel-make-tool - :function #'gptel-org-tools-org-extract-headings + :function #'gptel-org-tools--org-extract-headings :name "org-extract-headings" :description "Extract all headings from an org-mode buffer" :args (list '(:name "buffer" :type string :description "The Org buffer to extract headings from.")) - :category "org-mode") + :category "org-mode")) #+end_src **** org-ql-select @@ -311,7 +367,7 @@ My current goal is to replace this monstrosity with individual functions for eac But in the interim, this works. Kind of. #+begin_src elisp -(defun gptel-org-tools-org-ql-select (buf query) +(defun gptel-org-tools--org-ql-select (buf query) (org-ql-select (get-buffer buf) (if (stringp query) @@ -325,8 +381,9 @@ But in the interim, this works. Kind of. (outline-next-heading) (line-beginning-position))))))) +(add-to-list 'gptel-tools (gptel-make-tool - :function #'gptel-org-tools-org-ql-select + :function #'gptel-org-tools--org-ql-select :name "org-ql-select" :description "Run org-ql-select against buffer with query. Using filename fails." :args (list '(:name "buffer" @@ -335,7 +392,7 @@ But in the interim, this works. Kind of. '(:name "query" :type string :description "The query to pass into org-ql-select. See org-ql documentation for syntax. Usually `(tags \"tag1\" \"tag2\")` is sufficient. Possible predicates: `tags` (finds both local and inherited tags), `tags-local` (finds only local tags), `rifle` (matches against both heading and body text). This is a sexp, not a string.")) - :category "org") + :category "org")) #+end_src **** Somewhat working tools ***** org-ql-select-dates @@ -344,7 +401,7 @@ My journal is a single file, with a hierarchy like so: #+begin_src org :tangle no ,* [YYYY] ,** [YYYY-MM] -,*** [YYYY-MM-DD Day HH:MM] +,*** [YYYY-MM-DD Day HH:MM]) #+end_src I wanted to make sure that if I asked about a time period, the LLM would be able to pull at least roughly around the right time from my journal, without blowing out its context window. @@ -359,7 +416,7 @@ But, any customizations to tweak this is left to the user, as everyone has their #+begin_src elisp -(defun gptel-org-tools-org-ql-select-dates (buf date) +(defun gptel-org-tools--org-ql-select-dates (buf date) (interactive "fBuffer: \nsDate (YYYY or YYYY-MM): ") (org-ql-select (get-buffer buf) @@ -370,8 +427,9 @@ But, any customizations to tweak this is left to the user, as everyone has their (org-end-of-subtree))))) +(add-to-list 'gptel-tools (gptel-make-tool - :function #'gptel-org-tools-org-ql-select-dates + :function #'gptel-org-tools--org-ql-select-dates :name "org-ql-select-dates" :description "Extract org subtree by date in YYYY or YYYY-MM format" :args (list '(:name "buffer" @@ -380,13 +438,14 @@ But, any customizations to tweak this is left to the user, as everyone has their '(:name "date" :type string :description "Date in YYYY or YYYY-MM format. Can add multiple like so: \"YYYY-MM\" \"YYYY-MM\"")) - :category "org") + :category "org")) #+end_src ***** org-agenda-fortnight This is still work in progress, the idea is to have the LLM check my calendar and see what my plans are. I have not had time to really dig into this yet. It works, in principle, but I haven't been able to find a use for it yet. The real challenge is in building a context where the tools integrate with each-other in a way that makes sense. For now, this exists. #+begin_src elisp +(add-to-list 'gptel-tools (gptel-make-tool :function (lambda (days) (with-temp-buffer @@ -399,7 +458,7 @@ It works, in principle, but I haven't been able to find a use for it yet. The re :args (list '(:name "days" :type integer :description "The number of days to look ahead. Default: 14")) - :category "org") + :category "org")) #+end_src **** Completely WIP tools The following tools are still very much WIP, and I think they're self-explanatory enough. They have /NOT/ been tested in any way, shape, form, or capacity. @@ -409,7 +468,7 @@ The following tools are still very much WIP, and I think they're self-explanator ***** org-ql-select-headings Retrieve the headings where the heading matches query.. #+begin_src elisp -(defun gptel-org-tools-org-ql-select-headings (buf query) +(defun gptel-org-tools--org-ql-select-headings (buf query) (org-ql-select (get-buffer buf) `(heading ,query) @@ -420,8 +479,9 @@ Retrieve the headings where the heading matches query.. (line-end-position)))))) +(add-to-list 'gptel-tools (gptel-make-tool - :function #'gptel-org-tools-org-ql-select-headings + :function #'gptel-org-tools--org-ql-select-headings :name "org-ql-select-headings" :description "Retreive matching headings from buffer using org-ql-select. Matches only against heading. Using filename fails." :args (list '(:name "buffer" @@ -430,13 +490,13 @@ Retrieve the headings where the heading matches query.. '(:name "query" :type string :description "The string to pass into org-ql-select-headings. This is a bare string. Example: \"searchterm\"")) - :category "org-ql") + :category "org-ql")) #+end_src ***** org-ql-select-headings-rifle Retrieve all the headings where either heading or content matches query. #+begin_src elisp -(defun gptel-org-tools-org-ql-select-headings-rifle (buf query) +(defun gptel-org-tools--org-ql-select-headings-rifle (buf query) (org-ql-select (get-buffer buf) `(rifle ,query) @@ -447,8 +507,9 @@ Retrieve all the headings where either heading or content matches query. (line-end-position)))))) - (gptel-make-tool - :function #'gptel-org-tools-org-ql-select-headings-rifle + (add-to-list 'gptel-tools +(gptel-make-tool + :function #'gptel-org-tools--org-ql-select-headings-rifle :name "org-ql-select-headings-rifle" :description "Retreive headings from buffer using org-ql-select. Matches against both heading and content. Using filename fails." :args (list '(:name "buffer" @@ -457,13 +518,13 @@ Retrieve all the headings where either heading or content matches query. '(:name "query" :type string :description "The string to pass into org-ql-select-headings-rifle. This is a bare string. Example: \"searchterm\"")) - :category "org-ql") + :category "org-ql")) #+end_src ***** org-ql-select-tags-local This pulls all the headings (and their contents) when they match tags (without inheritance.) #+begin_src elisp -(defun gptel-org-tools-org-ql-select-tags-local (buf query) +(defun gptel-org-tools--org-ql-select-tags-local (buf query) (org-ql-select (get-buffer buf) `(tags-local ,query) @@ -476,8 +537,9 @@ This pulls all the headings (and their contents) when they match tags (without i (line-beginning-position))))))) +(add-to-list 'gptel-tools (gptel-make-tool - :function #'gptel-org-tools-org-ql-select-tags-local + :function #'gptel-org-tools--org-ql-select-tags-local :name "org-ql-select-tags-local" :description "Run org-ql-select-tags-local against buffer with query. No tag inheritance." :args (list '(:name "buffer" @@ -486,13 +548,13 @@ This pulls all the headings (and their contents) when they match tags (without i '(:name "query" :type string :description "The tags to match entry headings against. Example: \"tag1\" \"tag2\"")) - :category "org-ql") + :category "org-ql")) #+end_src ***** org-ql-select-tags This pulls all the headings (and their contents) when they match tags (with inheritance; if a parent entry has the tag, descendant entries do, too.) #+begin_src elisp -(defun gptel-org-tools-org-ql-select-tags (buf query) +(defun gptel-org-tools--org-ql-select-tags (buf query) (org-ql-select (get-buffer buf) `(tags ,query) @@ -505,8 +567,9 @@ This pulls all the headings (and their contents) when they match tags (with inhe (line-beginning-position))))))) +(add-to-list 'gptel-tools (gptel-make-tool - :function #'gptel-org-tools-org-ql-select-tags + :function #'gptel-org-tools--org-ql-select-tags :name "org-ql-select-tags" :description "Run org-ql-select-tags against buffer with query. Supports tag inheritance." :args (list '(:name "buffer" @@ -515,13 +578,13 @@ This pulls all the headings (and their contents) when they match tags (with inhe '(:name "query" :type string :description "The tags to match entry headings against. Example: \"tag1\" \"tag2\"")) - :category "org-ql") + :category "org-ql")) #+end_src ***** org-ql-select-rifle And, the "grab everything that matches" tool. #+begin_src elisp -(defun gptel-org-tools-org-ql-select-rifle (buf query) +(defun gptel-org-tools--org-ql-select-rifle (buf query) (org-ql-select (get-buffer buf) `(rifle ,query) @@ -533,8 +596,9 @@ And, the "grab everything that matches" tool. (outline-next-heading) (line-beginning-position))))))) +(add-to-list 'gptel-tools (gptel-make-tool - :function #'gptel-org-tools-org-ql-select-rifle + :function #'gptel-org-tools--org-ql-select-rifle :name "org-ql-select-rifle" :description "Run org-ql-select-rifle against buffer with query." :args (list '(:name "buffer" @@ -543,7 +607,7 @@ And, the "grab everything that matches" tool. '(:name "query" :type string :description "The strings to match entry headings and content against. Example: \"tag1\" \"tag2\"")) - :category "org-ql") + :category "org-ql")) #+end_src diff --git a/gptel-org-tools.el b/gptel-org-tools.el index f61ee1b..a5845ef 100644 --- a/gptel-org-tools.el +++ b/gptel-org-tools.el @@ -32,8 +32,9 @@ ;; All documentation regarding these functions is in the README.org file. ;; Repository: https://git.bajsicki.com/phil/gptel-org-tools -;;; Code: +;;; Code:) +(add-to-list 'gptel-tools (gptel-make-tool :function (lambda (arg) (with-temp-buffer @@ -47,8 +48,9 @@ :type string :description "Does nothing." :optional t)) - :category "emacs") + :category "emacs")) +(add-to-list 'gptel-tools (gptel-make-tool :function (lambda (dir) (with-temp-buffer @@ -62,8 +64,9 @@ :type string :description "Directory path" :optional t)) - :category "filesystem") + :category "filesystem")) +(add-to-list 'gptel-tools (gptel-make-tool :function (lambda (filename) (bufferp (find-buffer-visiting (expand-file-name filename)))) @@ -72,8 +75,9 @@ :args (list '(:name "filename" :type string :description "The filename to compare to open buffers.")) - :category "org-mode") + :category "org-mode")) +(add-to-list 'gptel-tools (gptel-make-tool :function (lambda (file) (find-file-noselect file)) @@ -82,9 +86,51 @@ :args (list '(:name "file" :type string :description "Path to file..")) - :category "filesystem") + :category "filesystem")) -(defun gptel-org-tools-org-extract-tags (buffer) +(add-to-list 'gptel-tools + (gptel-make-tool + :function (lambda (filename) + (with-temp-buffer + (insert-file-contents (expand-file-name filename)) + (buffer-string))) + :name "read-file-contents" + :description "Read and return the contents of a specified file." + :args (list '(:name "filename" + :type string + :description "The filename to read.")) + :category "org-mode")) + +(add-to-list 'gptel-tools + (gptel-make-tool + :function (lambda (var) + (let ((symbol (intern var))) + (if (boundp symbol) + (prin1-to-string (symbol-value symbol)) + (format "Variable %s is not bound." var)))) + :name "describe-variable" + :description "See variable contents" + :args (list '(:name "var" + :type string + :description "Variable name")) + :category "emacs")) + +(add-to-list 'gptel-tools + (gptel-make-tool + :function (lambda (fun) + (let ((symbol (intern fun))) + (if (fboundp symbol) + (prin1-to-string (documentation symbol 'function)) + (format "Function %s is not defined." fun)))) + :name "describe-function" + :description "See function description" + :args (list '(:name "fun" + :type string + :description "Function name" + :optional t)) + :category "emacs")) + +(defun gptel-org-tools--org-extract-tags (buffer) (interactive "bBuffer: ") (with-current-buffer buffer (let ((tags '())) @@ -97,16 +143,17 @@ (push tag tags)))))) (sort (-uniq tags) #'string<)))) +(add-to-list 'gptel-tools (gptel-make-tool - :function #'gptel-org-tools-org-extract-tags + :function #'gptel-org-tools--org-extract-tags :name "org-extract-tags" :description "Extract all unique tags from an org-mode buffer" :args (list '(:name "buffer" :type string :description "The Org buffer to extract tags from.")) - :category "org-mode") + :category "org-mode")) -(defun gptel-org-tools-org-extract-headings (buffer) +(defun gptel-org-tools--org-extract-headings (buffer) (interactive "bBuffer: ") (with-current-buffer buffer (org-map-entries @@ -116,16 +163,17 @@ t 'file))) +(add-to-list 'gptel-tools (gptel-make-tool - :function #'gptel-org-tools-org-extract-headings + :function #'gptel-org-tools--org-extract-headings :name "org-extract-headings" :description "Extract all headings from an org-mode buffer" :args (list '(:name "buffer" :type string :description "The Org buffer to extract headings from.")) - :category "org-mode") + :category "org-mode")) -(defun gptel-org-tools-org-ql-select (buf query) +(defun gptel-org-tools--org-ql-select (buf query) (org-ql-select (get-buffer buf) (if (stringp query) @@ -139,8 +187,9 @@ (outline-next-heading) (line-beginning-position))))))) +(add-to-list 'gptel-tools (gptel-make-tool - :function #'gptel-org-tools-org-ql-select + :function #'gptel-org-tools--org-ql-select :name "org-ql-select" :description "Run org-ql-select against buffer with query. Using filename fails." :args (list '(:name "buffer" @@ -149,9 +198,9 @@ '(:name "query" :type string :description "The query to pass into org-ql-select. See org-ql documentation for syntax. Usually `(tags \"tag1\" \"tag2\")` is sufficient. Possible predicates: `tags` (finds both local and inherited tags), `tags-local` (finds only local tags), `rifle` (matches against both heading and body text). This is a sexp, not a string.")) - :category "org") + :category "org")) -(defun gptel-org-tools-org-ql-select-dates (buf date) +(defun gptel-org-tools--org-ql-select-dates (buf date) (interactive "fBuffer: \nsDate (YYYY or YYYY-MM): ") (org-ql-select (get-buffer buf) @@ -162,8 +211,9 @@ (org-end-of-subtree))))) +(add-to-list 'gptel-tools (gptel-make-tool - :function #'gptel-org-tools-org-ql-select-dates + :function #'gptel-org-tools--org-ql-select-dates :name "org-ql-select-dates" :description "Extract org subtree by date in YYYY or YYYY-MM format" :args (list '(:name "buffer" @@ -172,8 +222,9 @@ '(:name "date" :type string :description "Date in YYYY or YYYY-MM format. Can add multiple like so: \"YYYY-MM\" \"YYYY-MM\"")) - :category "org") + :category "org")) +(add-to-list 'gptel-tools (gptel-make-tool :function (lambda (days) (with-temp-buffer @@ -186,9 +237,9 @@ :args (list '(:name "days" :type integer :description "The number of days to look ahead. Default: 14")) - :category "org") + :category "org")) -(defun gptel-org-tools-org-ql-select-headings (buf query) +(defun gptel-org-tools--org-ql-select-headings (buf query) (org-ql-select (get-buffer buf) `(heading ,query) @@ -199,8 +250,9 @@ (line-end-position)))))) +(add-to-list 'gptel-tools (gptel-make-tool - :function #'gptel-org-tools-org-ql-select-headings + :function #'gptel-org-tools--org-ql-select-headings :name "org-ql-select-headings" :description "Retreive matching headings from buffer using org-ql-select. Matches only against heading. Using filename fails." :args (list '(:name "buffer" @@ -209,9 +261,9 @@ '(:name "query" :type string :description "The string to pass into org-ql-select-headings. This is a bare string. Example: \"searchterm\"")) - :category "org-ql") + :category "org-ql")) -(defun gptel-org-tools-org-ql-select-headings-rifle (buf query) +(defun gptel-org-tools--org-ql-select-headings-rifle (buf query) (org-ql-select (get-buffer buf) `(rifle ,query) @@ -222,8 +274,9 @@ (line-end-position)))))) - (gptel-make-tool - :function #'gptel-org-tools-org-ql-select-headings-rifle + (add-to-list 'gptel-tools +(gptel-make-tool + :function #'gptel-org-tools--org-ql-select-headings-rifle :name "org-ql-select-headings-rifle" :description "Retreive headings from buffer using org-ql-select. Matches against both heading and content. Using filename fails." :args (list '(:name "buffer" @@ -232,9 +285,9 @@ '(:name "query" :type string :description "The string to pass into org-ql-select-headings-rifle. This is a bare string. Example: \"searchterm\"")) - :category "org-ql") + :category "org-ql")) -(defun gptel-org-tools-org-ql-select-tags-local (buf query) +(defun gptel-org-tools--org-ql-select-tags-local (buf query) (org-ql-select (get-buffer buf) `(tags-local ,query) @@ -247,8 +300,9 @@ (line-beginning-position))))))) +(add-to-list 'gptel-tools (gptel-make-tool - :function #'gptel-org-tools-org-ql-select-tags-local + :function #'gptel-org-tools--org-ql-select-tags-local :name "org-ql-select-tags-local" :description "Run org-ql-select-tags-local against buffer with query. No tag inheritance." :args (list '(:name "buffer" @@ -257,9 +311,9 @@ '(:name "query" :type string :description "The tags to match entry headings against. Example: \"tag1\" \"tag2\"")) - :category "org-ql") + :category "org-ql")) -(defun gptel-org-tools-org-ql-select-tags (buf query) +(defun gptel-org-tools--org-ql-select-tags (buf query) (org-ql-select (get-buffer buf) `(tags ,query) @@ -272,8 +326,9 @@ (line-beginning-position))))))) +(add-to-list 'gptel-tools (gptel-make-tool - :function #'gptel-org-tools-org-ql-select-tags + :function #'gptel-org-tools--org-ql-select-tags :name "org-ql-select-tags" :description "Run org-ql-select-tags against buffer with query. Supports tag inheritance." :args (list '(:name "buffer" @@ -282,9 +337,9 @@ '(:name "query" :type string :description "The tags to match entry headings against. Example: \"tag1\" \"tag2\"")) - :category "org-ql") + :category "org-ql")) -(defun gptel-org-tools-org-ql-select-rifle (buf query) +(defun gptel-org-tools--org-ql-select-rifle (buf query) (org-ql-select (get-buffer buf) `(rifle ,query) @@ -296,8 +351,9 @@ (outline-next-heading) (line-beginning-position))))))) +(add-to-list 'gptel-tools (gptel-make-tool - :function #'gptel-org-tools-org-ql-select-rifle + :function #'gptel-org-tools--org-ql-select-rifle :name "org-ql-select-rifle" :description "Run org-ql-select-rifle against buffer with query." :args (list '(:name "buffer" @@ -306,7 +362,7 @@ '(:name "query" :type string :description "The strings to match entry headings and content against. Example: \"tag1\" \"tag2\"")) - :category "org-ql") + :category "org-ql")) (provide 'gptel-org-tools) ;;; gptel-org-tools.el ends here