gptel: More flexible callbacks

* gptel.el (gptel--url-get-response,
gptel-api-key-from-auth-source): `gptel--url-get-response' accepts
a callback argument that can be used to do something besides
inserting the response into the current buffer.

* gptel-curl.el (gptel-curl--sentinel, gptel-curl-get-response):
`gptel-curl--sentinel' now accepts a callback argument that can be
used to do something besides inserting the response into the
current buffer.

These changes are in preparation for more specific functionality,
like showing the response as a message, or replacing the prompt
with the response etc.
This commit is contained in:
Karthik Chikmagalur 2023-03-31 19:37:25 -07:00
parent c2ad1c004d
commit f7ba368c38
2 changed files with 19 additions and 8 deletions

View file

@ -60,13 +60,16 @@ PROMPTS is the data to send, TOKEN is a unique identifier."
(nreverse (cons url args))))
;;;###autoload
(defun gptel-curl-get-response (info)
(defun gptel-curl-get-response (info &optional callback)
"Retrieve response to prompt in INFO.
INFO is a plist with the following keys:
- :prompt (the prompt being sent)
- :gptel-buffer (the gptel buffer)
- :insert-marker (marker at which to insert the response)."
- :insert-marker (marker at which to insert the response).
Call CALLBACK with the response and INFO afterwards. If omitted
the response is inserted into the current buffer after point."
(with-current-buffer (generate-new-buffer "*gptel-curl*")
(let* ((token (md5 (format "%s%s%s%s"
(random) (emacs-pid) (user-full-name)
@ -76,7 +79,9 @@ INFO is a plist with the following keys:
"curl" args)))
(set-process-query-on-exit-flag process nil)
(setf (alist-get process gptel-curl--process-alist)
(nconc (list :token token) info))
(nconc (list :token token
:callback (or callback #'gptel--insert-response))
info))
(set-process-sentinel process #'gptel-curl--sentinel))))
(defun gptel-curl--sentinel (process status)
@ -90,10 +95,11 @@ PROCESS and STATUS are process parameters."
(if-let* (((eq (process-status process) 'exit))
(proc-info (alist-get process gptel-curl--process-alist))
(proc-token (plist-get proc-info :token))
(proc-callback (plist-get proc-info :callback))
(response (gptel-curl--parse-response proc-buf proc-token)))
(gptel--insert-response response proc-info)
(funcall proc-callback response proc-info)
;; Failed
(gptel--insert-response (list :content nil :status status) proc-info))
(funcall proc-callback (list :content nil :status status) proc-info))
(setf (alist-get process gptel-curl--process-alist nil 'remove) nil)
(kill-buffer proc-buf)))

View file

@ -207,6 +207,7 @@ By default, \"openai.com\" is used as HOST and \"apikey\" as USER."
secret)
(user-error "No `gptel-api-key' found in the auth source")))
;; FIXME Should we utf-8 encode the api-key here?
(defun gptel--api-key ()
"Get api key from `gptel-api-key'."
(pcase gptel-api-key
@ -382,13 +383,16 @@ BUFFER is the interaction buffer for ChatGPT."
('org-mode (gptel--convert-markdown->org content))
(_ content)))
(defun gptel--url-get-response (info)
(defun gptel--url-get-response (info &optional callback)
"Fetch response to prompt in INFO from ChatGPT.
INFO is a plist with the following keys:
- :prompt (the prompt being sent)
- :gptel-buffer (the gptel buffer)
- :insert-marker (marker at which to insert the response)."
- :insert-marker (marker at which to insert the response).
Call CALLBACK with the response and INFO afterwards. If omitted
the response is inserted into the current buffer after point."
(let* ((inhibit-message t)
(message-log-max nil)
(url-request-method "POST")
@ -403,7 +407,8 @@ INFO is a plist with the following keys:
(lambda (_)
(let ((response
(gptel--url-parse-response (current-buffer))))
(gptel--insert-response response info)
(funcall (or callback #'gptel--insert-response)
response info)
(kill-buffer)))
nil t nil)))