Skip to content

Commit

Permalink
gptel: API agnostic response error handling
Browse files Browse the repository at this point in the history
* gptel.el (gptel--url-get-response, gptel--url-parse-response):

- When the query fails, the error message format (in the JSON)
differs between APIs.  Ultimately it may be required to dispatch
error handling via a generic function, but for now: try to make
the error handling API agnostic.

- Mention the backend name in the error message.  Pass the backend
to the (non-streaming response) parsers to be able to do this.

* gptel-curl.el (gptel-curl--stream-cleanup,
gptel-curl--parse-response):  Same changes.
  • Loading branch information
karthink committed Nov 8, 2023
1 parent 3308449 commit 0109d0d
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 18 deletions.
36 changes: 25 additions & 11 deletions gptel-curl.el
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ PROCESS and _STATUS are process parameters."
(clone-buffer "*gptel-error*" 'show)))
(let* ((info (alist-get process gptel-curl--process-alist))
(gptel-buffer (plist-get info :buffer))
(backend-name
(gptel-backend-name
(buffer-local-value 'gptel-backend gptel-buffer)))
(tracking-marker (plist-get info :tracking-marker))
(start-marker (plist-get info :position))
(http-status (plist-get info :http-status))
Expand All @@ -177,14 +180,16 @@ PROCESS and _STATUS are process parameters."
(json-object-type 'plist)
(response (progn (goto-char header-size)
(condition-case nil (json-read)
(json-readtable-error 'json-read-error)))))
(json-readtable-error 'json-read-error))))
(error-data (plist-get response :error)))
(cond
((plist-get response :error)
(let* ((error-plist (plist-get response :error))
(error-msg (plist-get error-plist :message))
(error-type (plist-get error-plist :type)))
(message "ChatGPT error: (%s) %s" http-msg error-msg)
(setq http-msg (concat "(" http-msg ") " (string-trim error-type)))))
(error-data
(if (stringp error-data)
(message "%s error: (%s) %s" backend-name http-msg error-data)
(when-let ((error-msg (plist-get error-data :message)))
(message "%s error: (%s) %s" backend-name http-msg error-msg))
(when-let ((error-type (plist-get error-data :type)))
(setq http-msg (concat "(" http-msg ") " (string-trim error-type))))))
((eq response 'json-read-error)
(message "ChatGPT error (%s): Malformed JSON in response." http-msg))
(t (message "ChatGPT error (%s): Could not parse HTTP response." http-msg)))))
Expand Down Expand Up @@ -339,10 +344,19 @@ buffer."
(funcall parser nil response proc-info))
http-msg))
((plist-get response :error)
(let* ((error-plist (plist-get response :error))
(error-msg (plist-get error-plist :message))
(error-type (plist-get error-plist :type)))
(list nil (concat "(" http-msg ") " (string-trim error-type)) error-msg)))
(let* ((error-data (plist-get response :error))
(error-msg (plist-get error-data :message))
(error-type (plist-get error-data :type))
(backend-name
(gptel-backend-name
(buffer-local-value 'gptel-backend (plist-get proc-info :buffer)))))
(if (stringp error-data)
(progn (message "%s error: (%s) %s" backend-name http-msg error-data)
(setq error-msg (string-trim error-data)))
(when (stringp error-msg)
(message "%s error: (%s) %s" backend-name http-msg (string-trim error-msg)))
(when error-type (setq http-msg (concat "(" http-msg ") " (string-trim error-type)))))
(list nil (concat "(" http-msg ") " (or error-msg "")))))
((eq response 'json-read-error)
(list nil (concat "(" http-msg ") Malformed JSON in response.")
"Malformed JSON in response"))
Expand Down
21 changes: 14 additions & 7 deletions gptel.el
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,7 @@ the response is inserted into the current buffer after point."
(url-retrieve (gptel-backend-url gptel-backend)
(lambda (_)
(pcase-let ((`(,response ,http-msg ,error)
(gptel--url-parse-response (current-buffer))))
(gptel--url-parse-response backend (current-buffer))))
(plist-put info :status http-msg)
(when error (plist-put info :error error))
(funcall (or callback #'gptel--insert-response)
Expand All @@ -873,7 +873,7 @@ RESPONSE is the parsed JSON of the response, as a plist.
PROC-INFO is a plist with process information and other context.
See `gptel-curl--get-response' for its contents.")

(defun gptel--url-parse-response (response-buffer)
(defun gptel--url-parse-response (backend response-buffer)
"Parse response in RESPONSE-BUFFER."
(when (buffer-live-p response-buffer)
(when gptel--debug
Expand All @@ -892,14 +892,21 @@ See `gptel-curl--get-response' for its contents.")
(json-readtable-error 'json-read-error))))))
(cond
((string-match-p "200 OK" http-msg)
(list (string-trim (gptel--parse-response gptel-backend response
(list (string-trim (gptel--parse-response backend response
'(:buffer response-buffer)))
http-msg))
((plist-get response :error)
(let* ((error-plist (plist-get response :error))
(error-msg (plist-get error-plist :message))
(error-type (plist-get error-plist :type)))
(list nil (concat "(" http-msg ") " error-type) error-msg)))
(let* ((error-data (plist-get response :error))
(error-msg (plist-get error-data :message))
(error-type (plist-get error-data :type))
(backend-name (gptel-backend-name backend)))
(if (stringp error-data)
(progn (message "%s error: (%s) %s" backend-name http-msg error-data)
(setq error-msg (string-trim error-data)))
(when (stringp error-msg)
(message "%s error: (%s) %s" backend-name http-msg (string-trim error-msg)))
(when error-type (setq http-msg (concat "(" http-msg ") " (string-trim error-type)))))
(list nil (concat "(" http-msg ") " (or error-msg "")))))
((eq response 'json-read-error)
(list nil (concat "(" http-msg ") Malformed JSON in response.") "json-read-error"))
(t (list nil (concat "(" http-msg ") Could not parse HTTP response.")
Expand Down

0 comments on commit 0109d0d

Please sign in to comment.