gptel: API agnostic response error handling
* 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.
This commit is contained in:
parent
3308449761
commit
0109d0d1c0
2 changed files with 39 additions and 18 deletions
|
@ -155,6 +155,9 @@ PROCESS and _STATUS are process parameters."
|
||||||
(clone-buffer "*gptel-error*" 'show)))
|
(clone-buffer "*gptel-error*" 'show)))
|
||||||
(let* ((info (alist-get process gptel-curl--process-alist))
|
(let* ((info (alist-get process gptel-curl--process-alist))
|
||||||
(gptel-buffer (plist-get info :buffer))
|
(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))
|
(tracking-marker (plist-get info :tracking-marker))
|
||||||
(start-marker (plist-get info :position))
|
(start-marker (plist-get info :position))
|
||||||
(http-status (plist-get info :http-status))
|
(http-status (plist-get info :http-status))
|
||||||
|
@ -177,14 +180,16 @@ PROCESS and _STATUS are process parameters."
|
||||||
(json-object-type 'plist)
|
(json-object-type 'plist)
|
||||||
(response (progn (goto-char header-size)
|
(response (progn (goto-char header-size)
|
||||||
(condition-case nil (json-read)
|
(condition-case nil (json-read)
|
||||||
(json-readtable-error 'json-read-error)))))
|
(json-readtable-error 'json-read-error))))
|
||||||
|
(error-data (plist-get response :error)))
|
||||||
(cond
|
(cond
|
||||||
((plist-get response :error)
|
(error-data
|
||||||
(let* ((error-plist (plist-get response :error))
|
(if (stringp error-data)
|
||||||
(error-msg (plist-get error-plist :message))
|
(message "%s error: (%s) %s" backend-name http-msg error-data)
|
||||||
(error-type (plist-get error-plist :type)))
|
(when-let ((error-msg (plist-get error-data :message)))
|
||||||
(message "ChatGPT error: (%s) %s" http-msg error-msg)
|
(message "%s error: (%s) %s" backend-name http-msg error-msg))
|
||||||
(setq http-msg (concat "(" http-msg ") " (string-trim error-type)))))
|
(when-let ((error-type (plist-get error-data :type)))
|
||||||
|
(setq http-msg (concat "(" http-msg ") " (string-trim error-type))))))
|
||||||
((eq response 'json-read-error)
|
((eq response 'json-read-error)
|
||||||
(message "ChatGPT error (%s): Malformed JSON in response." http-msg))
|
(message "ChatGPT error (%s): Malformed JSON in response." http-msg))
|
||||||
(t (message "ChatGPT error (%s): Could not parse HTTP response." http-msg)))))
|
(t (message "ChatGPT error (%s): Could not parse HTTP response." http-msg)))))
|
||||||
|
@ -339,10 +344,19 @@ buffer."
|
||||||
(funcall parser nil response proc-info))
|
(funcall parser nil response proc-info))
|
||||||
http-msg))
|
http-msg))
|
||||||
((plist-get response :error)
|
((plist-get response :error)
|
||||||
(let* ((error-plist (plist-get response :error))
|
(let* ((error-data (plist-get response :error))
|
||||||
(error-msg (plist-get error-plist :message))
|
(error-msg (plist-get error-data :message))
|
||||||
(error-type (plist-get error-plist :type)))
|
(error-type (plist-get error-data :type))
|
||||||
(list nil (concat "(" http-msg ") " (string-trim error-type)) error-msg)))
|
(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)
|
((eq response 'json-read-error)
|
||||||
(list nil (concat "(" http-msg ") Malformed JSON in response.")
|
(list nil (concat "(" http-msg ") Malformed JSON in response.")
|
||||||
"Malformed JSON in response"))
|
"Malformed JSON in response"))
|
||||||
|
|
21
gptel.el
21
gptel.el
|
@ -855,7 +855,7 @@ the response is inserted into the current buffer after point."
|
||||||
(url-retrieve (gptel-backend-url gptel-backend)
|
(url-retrieve (gptel-backend-url gptel-backend)
|
||||||
(lambda (_)
|
(lambda (_)
|
||||||
(pcase-let ((`(,response ,http-msg ,error)
|
(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)
|
(plist-put info :status http-msg)
|
||||||
(when error (plist-put info :error error))
|
(when error (plist-put info :error error))
|
||||||
(funcall (or callback #'gptel--insert-response)
|
(funcall (or callback #'gptel--insert-response)
|
||||||
|
@ -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.
|
PROC-INFO is a plist with process information and other context.
|
||||||
See `gptel-curl--get-response' for its contents.")
|
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."
|
"Parse response in RESPONSE-BUFFER."
|
||||||
(when (buffer-live-p response-buffer)
|
(when (buffer-live-p response-buffer)
|
||||||
(when gptel--debug
|
(when gptel--debug
|
||||||
|
@ -892,14 +892,21 @@ See `gptel-curl--get-response' for its contents.")
|
||||||
(json-readtable-error 'json-read-error))))))
|
(json-readtable-error 'json-read-error))))))
|
||||||
(cond
|
(cond
|
||||||
((string-match-p "200 OK" http-msg)
|
((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)))
|
'(:buffer response-buffer)))
|
||||||
http-msg))
|
http-msg))
|
||||||
((plist-get response :error)
|
((plist-get response :error)
|
||||||
(let* ((error-plist (plist-get response :error))
|
(let* ((error-data (plist-get response :error))
|
||||||
(error-msg (plist-get error-plist :message))
|
(error-msg (plist-get error-data :message))
|
||||||
(error-type (plist-get error-plist :type)))
|
(error-type (plist-get error-data :type))
|
||||||
(list nil (concat "(" http-msg ") " error-type) error-msg)))
|
(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)
|
((eq response 'json-read-error)
|
||||||
(list nil (concat "(" http-msg ") Malformed JSON in 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.")
|
(t (list nil (concat "(" http-msg ") Could not parse HTTP response.")
|
||||||
|
|
Loading…
Add table
Reference in a new issue