From f7ba368c38e0a8d9a67f7cf158741b41288a2cb9 Mon Sep 17 00:00:00 2001 From: Karthik Chikmagalur Date: Fri, 31 Mar 2023 19:37:25 -0700 Subject: [PATCH] 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. --- gptel-curl.el | 16 +++++++++++----- gptel.el | 11 ++++++++--- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/gptel-curl.el b/gptel-curl.el index a4a3629..6aec3ff 100644 --- a/gptel-curl.el +++ b/gptel-curl.el @@ -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))) diff --git a/gptel.el b/gptel.el index 8993f24..7f634b2 100644 --- a/gptel.el +++ b/gptel.el @@ -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)))