[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/llm b438ae7a72 46/71: Merge pull request #35 from r0man
From: |
ELPA Syncer |
Subject: |
[elpa] externals/llm b438ae7a72 46/71: Merge pull request #35 from r0man/plz |
Date: |
Fri, 17 May 2024 00:58:47 -0400 (EDT) |
branch: externals/llm
commit b438ae7a72e7304941a6f15df469aa8c3492a0a5
Merge: 1fb8511867 ccfe066654
Author: Andrew Hyatt <ahyatt@gmail.com>
Commit: GitHub <noreply@github.com>
Merge pull request #35 from r0man/plz
Error handling & JSON parsing
---
llm-gemini.el | 17 ++--
llm-ollama.el | 17 ++--
llm-openai.el | 2 -
llm-request-plz.el | 53 +++++-------
llm-vertex.el | 17 ++--
plz-event-source.el | 11 ++-
plz-media-type.el | 240 +++++++++++++++++++++++++++++++++++++---------------
plz.el | 1 +
8 files changed, 228 insertions(+), 130 deletions(-)
diff --git a/llm-gemini.el b/llm-gemini.el
index 9915601b30..7e86b3b112 100644
--- a/llm-gemini.el
+++ b/llm-gemini.el
@@ -65,7 +65,6 @@ You can get this at https://makersuite.google.com/app/apikey."
(let ((buf (current-buffer)))
(llm-request-plz-async (llm-gemini--embedding-url provider)
:data (llm-gemini--embedding-request provider
string)
- :media-type '(application/json)
:on-success (lambda (data)
(llm-request-callback-in-buffer
buf vector-callback
(llm-gemini--embedding-response-handler data)))
@@ -112,7 +111,6 @@ If STREAMING-P is non-nil, use the streaming endpoint."
(let ((buf (current-buffer)))
(llm-request-plz-async (llm-gemini--chat-url provider nil)
:data (llm-gemini--chat-request prompt)
- :media-type '(application/json)
:on-success (lambda (data)
(llm-request-callback-in-buffer
buf response-callback
@@ -131,12 +129,15 @@ If STREAMING-P is non-nil, use the streaming endpoint."
(llm-gemini--chat-url provider t)
:data (llm-gemini--chat-request prompt)
:on-element (lambda (element)
- (when-let ((response (llm-vertex--get-chat-response
element)))
- (if (stringp response)
- (when (> (length response) 0)
- (setq streamed-text (concat streamed-text response))
- (llm-request-callback-in-buffer buf
partial-callback streamed-text))
- (setq function-call response))))
+ (if (alist-get 'error element)
+ (llm-request-callback-in-buffer buf error-callback
'error
+
(llm-vertex--error-message element))
+ (when-let ((response (llm-vertex--get-chat-response
element)))
+ (if (stringp response)
+ (when (> (length response) 0)
+ (setq streamed-text (concat streamed-text
response))
+ (llm-request-callback-in-buffer buf
partial-callback streamed-text))
+ (setq function-call response)))))
:on-success (lambda (data)
(llm-request-callback-in-buffer
buf response-callback
diff --git a/llm-ollama.el b/llm-ollama.el
index e36701ff25..0a80e9955f 100644
--- a/llm-ollama.el
+++ b/llm-ollama.el
@@ -86,7 +86,6 @@ PROVIDER is the llm-ollama provider."
(let ((buf (current-buffer)))
(llm-request-plz-async (llm-ollama--url provider "embeddings")
:data (llm-ollama--embedding-request provider
string)
- :media-type '(application/json)
:on-success (lambda (data)
(llm-request-callback-in-buffer
buf vector-callback
(llm-ollama--embedding-extract-response data)))
@@ -148,18 +147,16 @@ STREAMING is a boolean to control whether to stream the
response."
(llm-request-plz-async
(llm-ollama--url provider "chat")
:data (llm-ollama--chat-request provider prompt nil)
- :media-type '(application/json)
:timeout llm-ollama-chat-timeout
:on-success (lambda (data)
- (let ((output (llm-ollama--get-response data)))
- (llm-provider-utils-append-to-prompt prompt data)
- (llm-request-plz-callback-in-buffer buf response-callback
output)))
- :on-error (lambda (_ data)
- (let ((errdata (cdr (assoc 'error data))))
+ (let ((response (llm-ollama--get-response data)))
+ (llm-provider-utils-append-to-prompt prompt response)
+ (llm-request-plz-callback-in-buffer buf response-callback
response)))
+ :on-error (lambda (code data)
+ (let ((error-message (cdr (assoc 'error data))))
(llm-request-plz-callback-in-buffer buf error-callback
'error
(format "Problem
calling Ollama: %s message: %s"
- (cdr (assoc
'type errdata))
- (cdr (assoc
'message errdata)))))))))
+ code
error-message)))))))
(cl-defmethod llm-chat-streaming ((provider llm-ollama) prompt
partial-callback response-callback error-callback)
(let ((buf (current-buffer))
@@ -179,7 +176,7 @@ STREAMING is a boolean to control whether to stream the
response."
:on-error (lambda (_ _)
;; The problem with ollama is that it doesn't
;; seem to have an error response.
- (llm-request-callback-in-buffer buf error-callback "Unknown
error calling ollama")))))
+ (llm-request-callback-in-buffer buf error-callback 'error
"Unknown error calling ollama")))))
(cl-defmethod llm-name ((provider llm-ollama))
(llm-ollama-chat-model provider))
diff --git a/llm-openai.el b/llm-openai.el
index 28396ce045..e444824262 100644
--- a/llm-openai.el
+++ b/llm-openai.el
@@ -116,7 +116,6 @@ This is just the key, if it exists."
(llm-openai--check-key provider)
(let ((buf (current-buffer)))
(llm-request-plz-async (llm-openai--url provider "embeddings")
- :media-type '(application/json)
:headers (llm-openai--headers provider)
:data (llm-openai--embedding-request
(llm-openai-embedding-model provider) string)
:on-success (lambda (data)
@@ -229,7 +228,6 @@ PROMPT is the prompt that needs to be updated with the
response."
(let ((buf (current-buffer)))
(llm-request-plz-async
(llm-openai--url provider "chat/completions")
- :media-type '(application/json)
:headers (llm-openai--headers provider)
:data (llm-openai--chat-request (llm-openai-chat-model provider) prompt)
:on-success (lambda (data)
diff --git a/llm-request-plz.el b/llm-request-plz.el
index a9cf9f63e9..fa7a9e5284 100644
--- a/llm-request-plz.el
+++ b/llm-request-plz.el
@@ -27,7 +27,7 @@
(require 'rx)
(require 'url-http)
-(defcustom llm-request-plz-timeout 60
+(defcustom llm-request-plz-timeout (* 2 60)
"The number of seconds to wait for a response from a HTTP server.
Request timings are depending on the request. Requests that need
@@ -101,19 +101,24 @@ code and the HTTP body of the error response.
For Curl errors, ON-ERROR will be called with the exit code of
the curl process and an error message."
- (cond ((plz-error-response error)
- (let ((response (plz-error-response error)))
- (funcall on-error
- (plz-response-status response)
- (plz-response-body response))))
+ (cond ((plz-media-type-filter-error-p error)
+ (let ((cause (plz-media-type-filter-error-cause error))
+ (response (plz-error-response error)))
+ ;; TODO: What do we want to pass to callers here?
+ (funcall on-error 'filter-error cause)))
((plz-error-curl-error error)
(let ((curl-error (plz-error-curl-error error)))
(funcall on-error
(car curl-error)
(cdr curl-error))))
+ ((plz-error-response error)
+ (when-let ((response (plz-error-response error))
+ (status (plz-response-status response))
+ (body (plz-response-body response)))
+ (funcall on-error status body)))
(t (user-error "Unexpected error: %s" error))))
-(cl-defun llm-request-plz-async (url &key headers data on-success
on-success-raw media-type
+(cl-defun llm-request-plz-async (url &key headers data on-success media-type
on-error timeout)
"Make a request to URL.
Nothing will be returned.
@@ -131,30 +136,21 @@ and required otherwise.
ON-ERROR will be called with the error code and a response-body.
This is required.
-MEDIA-TYPE is a required argument that sets a media type, useful
-for streaming formats. It is expected that this is only used by
-other methods in this file.
-
-ON-SUCCESS-RAW, if set, will be called in the buffer with the
-response body, and expect the response content. This is an
-optional argument, and mostly useful for streaming. If not set,
-the buffer is turned into JSON and passed to ON-SUCCESS."
- (unless media-type
- (error "MEDIA-TYPE is required in llm-request-plz-async"))
+MEDIA-TYPE is an optional argument that adds or overrides a media
+type, useful for streaming formats. It is expected that this is
+only used by other methods in this file."
(plz-media-type-request
'post url
- :as `(media-types ,(cons media-type plz-media-types))
+ :as `(media-types ,(if media-type
+ (cons media-type plz-media-types)
+ plz-media-types))
:body (when data
(encode-coding-string (json-encode data) 'utf-8))
:headers (append headers
'(("Content-Type" . "application/json")))
:then (lambda (response)
- (let ((response (plz-response-body response)))
- (when on-success-raw
- (funcall on-success-raw response))
- (when on-success
- (funcall on-success (when (and response (> (length response)
0))
- (json-read-from-string response))))))
+ (when on-success
+ (funcall on-success (plz-response-body response))))
:else (lambda (error)
(when on-error
(llm-request-plz--handle-error error on-error)))
@@ -184,9 +180,7 @@ This is required.
:headers headers
:data data
:on-error on-error
- ;; Have to use :on-success-raw because :on-success
will try to
- ;; convert to JSON, and this already should be JSON.
- :on-success-raw on-success
+ :on-success on-success
:timeout timeout
:media-type
(cons 'application/json
@@ -216,10 +210,7 @@ This is required.
:headers headers
:data data
:on-error on-error
- ;; Have to use :on-success-raw because :on-success
will try to
- ;; convert to JSON, and this already should be JSON.
- :on-success-raw (lambda (resp)
- (funcall on-success
(plz-response-body resp)))
+ :on-success on-success
:timeout timeout
:media-type
(cons 'application/x-ndjson
diff --git a/llm-vertex.el b/llm-vertex.el
index ec16a2462d..3ee7083f0e 100644
--- a/llm-vertex.el
+++ b/llm-vertex.el
@@ -130,7 +130,6 @@ KEY-GENTIME keeps track of when the key was generated,
because the key must be r
(llm-vertex--embedding-url provider)
:headers `(("Authorization" . ,(format "Bearer %s" (llm-vertex-key
provider))))
:data `(("instances" . [(("content" . ,string))]))
- :media-type '(application/json)
:on-success (lambda (data)
(llm-request-callback-in-buffer
buf vector-callback
(llm-vertex--embedding-extract-response data)))
@@ -302,7 +301,6 @@ If STREAMING is non-nil, use the URL for the streaming API."
(llm-vertex--chat-url provider)
:headers `(("Authorization" . ,(format "Bearer %s" (llm-vertex-key
provider))))
:data (llm-vertex--chat-request prompt)
- :media-type '(application/json)
:on-success (lambda (data)
(llm-request-callback-in-buffer
buf response-callback
@@ -322,12 +320,15 @@ If STREAMING is non-nil, use the URL for the streaming
API."
:headers `(("Authorization" . ,(format "Bearer %s" (llm-vertex-key
provider))))
:data (llm-vertex--chat-request prompt)
:on-element (lambda (element)
- (when-let ((response (llm-vertex--get-chat-response
element)))
- (if (stringp response)
- (when (> (length response) 0)
- (setq streamed-text (concat streamed-text response))
- (llm-request-callback-in-buffer buf
partial-callback streamed-text))
- (setq function-call response))))
+ (if (alist-get 'error element)
+ (llm-request-callback-in-buffer buf error-callback
'error
+
(llm-vertex--error-message element))
+ (when-let ((response (llm-vertex--get-chat-response
element)))
+ (if (stringp response)
+ (when (> (length response) 0)
+ (setq streamed-text (concat streamed-text
response))
+ (llm-request-callback-in-buffer buf
partial-callback streamed-text))
+ (setq function-call response)))))
:on-success (lambda (data)
(llm-request-callback-in-buffer
buf response-callback
diff --git a/plz-event-source.el b/plz-event-source.el
index c6861f7deb..b522cf0c1b 100644
--- a/plz-event-source.el
+++ b/plz-event-source.el
@@ -405,7 +405,16 @@
(events :documentation "Association list from event type to handler."
:initarg :events
:initform nil
- :type list)))
+ :type list))
+ "A media type class that handles the processing of HTTP responses
+in the server sent events format. The HTTP response is processed
+in a streaming way. The :events slot of the class can be set to
+an association list from event type symbol to a handler function.
+Whenever a new event is parsed and emitted the handler for the
+corresponding event type will be called with two arguments, an
+instance of the underlying event source class and an event. The
+body slot of the plz-response struct passed to the THEN and ELSE
+callbacks will always be set to nil.")
(defvar-local plz-event-source--current nil
"The event source of the current buffer.")
diff --git a/plz-media-type.el b/plz-media-type.el
index 23008e49c7..c20855487d 100644
--- a/plz-media-type.el
+++ b/plz-media-type.el
@@ -4,6 +4,10 @@
;; Author: r0man <roman@burningswell.com>
;; Maintainer: r0man <roman@burningswell.com>
+;; URL: https://github.com/r0man/plz-media-type.el
+;; Version: 0.1-pre
+;; Package-Requires: ((emacs "26.3"))
+;; Keywords: comm, network, http
;; This file is part of GNU Emacs.
@@ -24,7 +28,13 @@
;;; Commentary:
-;; This file handles content type.
+;; This library provides enhanced handling of MIME types for HTTP
+;; requests within Emacs. It utilizes the 'plz' library for
+;; networking calls, extending it to process responses based on the
+;; Content-Type header. This library defines various classes and
+;; methods for parsing and processing standard MIME types, including
+;; JSON, XML, HTML, and binary data. It allows for extensible
+;; processing of additional types through subclassing.
;;; Code:
@@ -34,6 +44,13 @@
(require 'eieio)
(require 'plz)
+(define-error 'plz-media-type-filter-error
+ "plz-media-type: Error in process filter"
+ 'plz-error)
+
+(cl-defstruct (plz-media-type-filter-error (:include plz-error))
+ cause)
+
(defclass plz-media-type ()
((type
:documentation "The media type."
@@ -47,7 +64,11 @@
:documentation "The parameters of the media type."
:initarg :parameters
:initform nil
- :subtype list)))
+ :subtype list))
+ "A class that hold information about the type, subtype and
+parameters of a media type. It is meant to be sub-classed to
+handle the processing of different media types and supports the
+processing of streaming and non-streaming HTTP responses.")
(defun plz-media-type-charset (media-type)
"Return the character set of the MEDIA-TYPE."
@@ -158,15 +179,18 @@ CHUNK is a part of the HTTP body."
(media-type (plz-media-type--of-response media-types
response))
(coding-system (plz-media-type-coding-system
media-type)))
(setq-local plz-media-type--current media-type)
+ (setq-local plz-media-type--response
+ (make-plz-response
+ :headers (plz-response-headers response)
+ :status (plz-response-status response)
+ :version (plz-response-version response)))
(when-let (body (plz-response-body response))
(when (> (length body) 0)
(setf (plz-response-body response)
(decode-coding-string body coding-system))
(delete-region body-start (point-max))
(set-marker (process-mark process) (point))
- (plz-media-type-process media-type process response)))
- (setf (plz-response-body response) nil)
- (setq-local plz-media-type--response response))))))
+ (plz-media-type-process media-type process
response))))))))
(when moving
(goto-char (process-mark process)))))))
@@ -174,13 +198,17 @@ CHUNK is a part of the HTTP body."
(defclass plz-media-type:application/octet-stream (plz-media-type)
((type :initform 'application)
- (subtype :initform 'octet-stream)))
+ (subtype :initform 'octet-stream))
+ "Media type class that handles the processing of octet stream
+HTTP responses. The media type sets the body slot of the
+plz-response structure to the unmodified value of the HTTP response
+body. It is used as the default media type processor.")
(cl-defmethod plz-media-type-else ((media-type
plz-media-type:application/octet-stream) error)
"Transform the ERROR into a format suitable for MEDIA-TYPE."
- (let ((response (plz-error-response error)))
- (setf (plz-error-response error) (plz-media-type-then media-type response))
- error))
+ (when-let (response (plz-error-response error))
+ (setf (plz-error-response error) (plz-media-type-then media-type
response)))
+ error)
(cl-defmethod plz-media-type-then ((media-type
plz-media-type:application/octet-stream) response)
"Transform the RESPONSE into a format suitable for MEDIA-TYPE."
@@ -221,7 +249,15 @@ defaults to `nil`."
be `hash-table', `alist' (the default) or `plist'."
:initarg :object-type
:initform 'alist
- :type symbol)))
+ :type symbol))
+ "Media type class that handles the processing of HTTP responses
+in the JSON format. The HTTP response is processed in a
+non-streaming way. After the response has been received, the
+body of the plz-response structure is set to the result of parsing
+the HTTP response body with the `json-parse-buffer' function.
+The arguments to the `json-parse-buffer' can be customized by
+making an instance of this class and setting its slots
+accordingly.")
(defun plz-media-type--parse-json-object (media-type)
"Parse the JSON object in the current buffer according to MEDIA-TYPE."
@@ -240,9 +276,17 @@ be `hash-table', `alist' (the default) or `plist'."
(defclass plz-media-type:application/json-array
(plz-media-type:application/json)
((handler
- :documentation "A function that will be called for each object in the JSON
array."
+ :documentation "Function that will be called for each object in the JSON
array."
:initarg :handler
- :type (or function symbol))))
+ :type (or function symbol)))
+ "Media type class that handles the processing of HTTP responses
+in a JSON format that assumes that the object at the top level is
+an array. The HTTP response is processed in a streaming way.
+Each object in the top level array will be parsed with the
+`json-parse-buffer' function. The function in the :handler slot
+will be called each time a new object arrives. The body slot of
+the plz-response structure passed to the THEN and ELSE callbacks
+will always be set to nil.")
(defun plz-media-type:application/json-array--parse-next (media-type)
"Parse a single line of the newline delimited JSON MEDIA-TYPE."
@@ -306,10 +350,18 @@ be `hash-table', `alist' (the default) or `plist'."
(defclass plz-media-type:application/x-ndjson (plz-media-type:application/json)
((subtype :initform 'x-ndjson)
(handler
- :documentation "A function that will be called for each line that contains
a JSON object."
+ :documentation "Function that will be called for each line that contains a
JSON object."
:initarg :handler
:initform nil
- :type (or function null symbol))))
+ :type (or function null symbol)))
+ "Media type class that handles the processing of HTTP responses
+in a JSON format that assumes that the object at the top level is
+an array. The HTTP response is processed in a streaming way.
+Each object in the top level array will be parsed with the
+`json-parse-buffer' function. The function in the :handler slot
+will be called each time a new object arrives. The body slot of
+the plz-response structure passed to the THEN and ELSE callbacks
+will always be set to nil.")
(defconst plz-media-type:application/x-ndjson--line-regexp
(rx (* not-newline) (or "\r\n" "\n" "\r"))
@@ -342,24 +394,38 @@ be `hash-table', `alist' (the default) or `plist'."
(cl-defmethod plz-media-type-then ((media-type
plz-media-type:application/x-ndjson) response)
"Transform the RESPONSE into a format suitable for MEDIA-TYPE."
(plz-media-type:application/x-ndjson--parse-stream media-type)
+ (setf (plz-response-body response) nil)
response)
;; Content Type: application/xml
(defclass plz-media-type:application/xml
(plz-media-type:application/octet-stream)
- ((subtype :initform 'xml)))
+ ((subtype :initform 'xml))
+ "Media type class that handles the processing of HTTP responses
+in the XML format. The HTTP response is processed in a
+non-streaming way. After the response has been received, the
+body of the plz-response structure is set to the result of parsing
+the HTTP response body with the `libxml-parse-html-region'
+function.")
(cl-defmethod plz-media-type-then ((media-type plz-media-type:application/xml)
response)
"Transform the RESPONSE into a format suitable for MEDIA-TYPE."
(with-slots (array-type false-object null-object object-type) media-type
- (setf (plz-response-body response) (libxml-parse-html-region))
+ (setf (plz-response-body response)
+ (libxml-parse-html-region (point-min) (point-max) nil))
response))
;; Content Type: text/html
(defclass plz-media-type:text/html (plz-media-type:application/xml)
((type :initform 'text)
- (subtype :initform 'xml)))
+ (subtype :initform 'xml))
+ "Media type class that handles the processing of HTTP responses
+in the HTML format. The HTTP response is processed in a
+non-streaming way. After the response has been received, the
+body of the plz-response structure is set to the result of parsing
+the HTTP response body with the `libxml-parse-html-region'
+function.")
(defvar plz-media-types
`((application/json . ,(plz-media-type:application/json))
@@ -367,7 +433,7 @@ be `hash-table', `alist' (the default) or `plist'."
(application/xml . ,(plz-media-type:application/xml))
(text/html . ,(plz-media-type:text/html))
(t . ,(plz-media-type:application/octet-stream)))
- "Alist from media type to content type.")
+ "Association list from media type to content type.")
(defun plz-media-type--handle-sync-http-error (error media-types)
"Handle the synchronous HTTP ERROR using MEDIA-TYPES."
@@ -387,9 +453,15 @@ be `hash-table', `alist' (the default) or `plist'."
(defun plz-media-type--handle-sync-error (error media-types)
"Handle the synchronous ERROR using MEDIA-TYPES."
- (if (eq 'plz-http-error (car error))
- (plz-media-type--handle-sync-http-error error media-types)
- (signal (car error) (cdr error))))
+ (cond
+ ((plz-media-type-filter-error-p error)
+ (signal 'plz-media-type-filter-error
+ (list (plz-media-type-filter-error-message error)
+ (plz-media-type-filter-error-response error)
+ (plz-media-type-filter-error-cause error))))
+ ((eq 'plz-http-error (car error))
+ (plz-media-type--handle-sync-http-error error media-types))
+ (t (signal (car error) (cdr error)))))
(cl-defun plz-media-type-request
(method
@@ -435,11 +507,26 @@ It may be:
non-existent file; if it exists, it will not be overwritten,
and an error will be signaled.
-- `(stream :through PROCESS-FILTER)' to asynchronously stream the
- HTTP response. PROCESS-FILTER is an Emacs process filter
- function, and must accept two arguments: the curl process
- sending the request and a chunk of the HTTP body, which was
- just received.
+- `(media-types MEDIA-TYPES)' to handle the processing of the
+ response based on the Content-Type header. MEDIA-TYPES is an
+ association list from a content type symbol to an instance of a
+ `plz-media-type' class. The `plz-media-types' variable is
+ bound to an association list and can be used to handle some
+ commonly used formats such as JSON, HTML, XML. This list can
+ be used as a basis and is meant to be extended by users. If no
+ media type was found for a content type, it will be handled by
+ the default octet stream media type. When this option is used,
+ the THEN callback will always receive a plz-response structure as
+ argument, and the ELSE callback always a plz-error structure. The
+ plz-response structure will always have the status and header
+ slots set. The body slot depends on the media type
+ implementation. In the case for JSON, HTML, XML it will
+ contain the decoded response body. When receiving JSON for
+ example, it will be an Emacs Lisp association list. For
+ streaming responses like text/event-stream it will be set to
+ nil, and the events of the server sent events specification
+ will be dispatched to the handlers registered with the media
+ type instance.
- A function, which is called in the response buffer with it
narrowed to the response body (suitable for, e.g. `json-read').
@@ -493,51 +580,64 @@ not.
(if-let (media-types (pcase as
(`(media-types ,media-types)
media-types)))
- (condition-case error
- (let* ((buffer)
- (plz-curl-default-args (cons "--no-buffer"
plz-curl-default-args))
- (result (plz method url
- :as 'buffer
- :body body
- :body-type body-type
- :connect-timeout connect-timeout
- :decode decode
- :else (lambda (error)
- (setq buffer (current-buffer))
- (when (or (functionp else) (symbolp else))
- (funcall else (plz-media-type-else
- plz-media-type--current
- error))))
- :finally (lambda ()
- (unwind-protect
- (when (functionp finally)
- (funcall finally))
- (when (buffer-live-p buffer)
- (kill-buffer buffer))))
- :headers headers
- :noquery noquery
- :process-filter (lambda (process chunk)
- (plz-media-type-process-filter
process media-types chunk))
- :timeout timeout
- :then (if (symbolp then)
- then
- (lambda (_)
+ (let ((buffer) (filter-error))
+ (condition-case error
+ (let* ((plz-curl-default-args (cons "--no-buffer"
plz-curl-default-args))
+ (result (plz method url
+ :as 'buffer
+ :body body
+ :body-type body-type
+ :connect-timeout connect-timeout
+ :decode decode
+ :else (lambda (error)
(setq buffer (current-buffer))
- (when (or (functionp then) (symbolp then))
- (funcall then (plz-media-type-then
- plz-media-type--current
-
plz-media-type--response))))))))
- (cond ((bufferp result)
- (unwind-protect
- (with-current-buffer result
- (plz-media-type-then plz-media-type--current
plz-media-type--response))
- (when (buffer-live-p result)
- (kill-buffer result))))
- ((processp result)
- result)
- (t (user-error "Unexpected response: %s" result))))
- ;; TODO: How to kill the buffer for sync requests that raise an error?
- (plz-error (plz-media-type--handle-sync-error error media-types)))
+ (when (or (functionp else) (symbolp else))
+ (funcall else (or filter-error
+ (plz-media-type-else
+
plz-media-type--current
+ error)))))
+ :finally (lambda ()
+ (unwind-protect
+ (when (functionp finally)
+ (funcall finally))
+ (when (buffer-live-p buffer)
+ (kill-buffer buffer))))
+ :headers headers
+ :noquery noquery
+ :process-filter (lambda (process chunk)
+ (condition-case cause
+
(plz-media-type-process-filter process media-types chunk)
+ (error
+ (let ((buffer
(process-buffer process)))
+ (setq filter-error
+
(make-plz-media-type-filter-error
+ :cause cause
+ :message (format
"error in process filter: %S" cause)
+ :response (when
(buffer-live-p buffer)
+
(with-current-buffer buffer
+
plz-media-type--response))))
+ (delete-process
process)))))
+ :timeout timeout
+ :then (if (symbolp then)
+ then
+ (lambda (_)
+ (setq buffer (current-buffer))
+ (when (or (functionp then) (symbolp
then))
+ (funcall then (plz-media-type-then
+ plz-media-type--current
+
plz-media-type--response))))))))
+ (cond ((bufferp result)
+ (unwind-protect
+ (with-current-buffer result
+ (plz-media-type-then plz-media-type--current
plz-media-type--response))
+ (when (buffer-live-p result)
+ (kill-buffer result))))
+ ((processp result)
+ result)
+ (t (user-error "Unexpected response: %s" result))))
+ ;; TODO: How to kill the buffer for sync requests that raise an
error?
+ (plz-error
+ (plz-media-type--handle-sync-error (or filter-error error)
media-types))))
(apply #'plz (append (list method url) rest))))
;;;; Footer
diff --git a/plz.el b/plz.el
index 69072063c7..3a9271bca6 100644
--- a/plz.el
+++ b/plz.el
@@ -755,6 +755,7 @@ argument passed to `plz--sentinel', which see."
(pcase-exhaustive status
((or 0 "finished\n")
;; Curl exited normally: check HTTP status code.
+ (widen)
(goto-char (point-min))
(plz--skip-proxy-headers)
(while (plz--skip-redirect-headers))
- [elpa] externals/llm 669456cba5 43/71: Fix Ollama error handling and appending to prompt, (continued)
- [elpa] externals/llm 669456cba5 43/71: Fix Ollama error handling and appending to prompt, ELPA Syncer, 2024/05/17
- [elpa] externals/llm c26bf648a8 44/71: Increase llm-request-plz-timeout to 2 minutes, ELPA Syncer, 2024/05/17
- [elpa] externals/llm 9a9b0de0df 52/71: Add llm-request-plz-connect-timeout, ELPA Syncer, 2024/05/17
- [elpa] externals/llm 5145074ba0 57/71: Merge branch 'main' into plz, ELPA Syncer, 2024/05/17
- [elpa] externals/llm dda5d1f2d0 62/71: Call handler functions only with the event object, ELPA Syncer, 2024/05/17
- [elpa] externals/llm 2146ba3803 64/71: Change some function names and make most of them private (#42), ELPA Syncer, 2024/05/17
- [elpa] externals/llm 3a2d6962f3 67/71: Whitespace fixes, ELPA Syncer, 2024/05/17
- [elpa] externals/llm 29d7c3f6b8 55/71: Update media type and event source packages, ELPA Syncer, 2024/05/17
- [elpa] externals/llm 0f25d08218 66/71: Merge branch 'plz', ELPA Syncer, 2024/05/17
- [elpa] externals/llm 478afbcb41 71/71: Fix byte compilation errors, ELPA Syncer, 2024/05/17
- [elpa] externals/llm b438ae7a72 46/71: Merge pull request #35 from r0man/plz,
ELPA Syncer <=
- [elpa] externals/llm 7b2c89f087 41/71: Remove invalid media type usage and on-success-raw callback, ELPA Syncer, 2024/05/17
- [elpa] externals/llm ccfe066654 45/71: Widen before parsing the response, ELPA Syncer, 2024/05/17
- [elpa] externals/llm 9d215d7ba2 58/71: Enable handling errors on streaming, and add requires, ELPA Syncer, 2024/05/17
- [elpa] externals/llm 0fec127d01 60/71: Don't always return "Unknown error" in llm-chat-async, ELPA Syncer, 2024/05/17
- [elpa] externals/llm 6408551c40 70/71: Add NEWS entry for the plz migration, ELPA Syncer, 2024/05/17
- [elpa] externals/llm 7cb3dd4891 47/71: Merge branch 'main' into plz, ELPA Syncer, 2024/05/17
- [elpa] externals/llm 57cf82e4af 50/71: Update plz-media-type.el, ELPA Syncer, 2024/05/17
- [elpa] externals/llm 759f689fae 56/71: Merge pull request #40 from r0man/plz, ELPA Syncer, 2024/05/17
- [elpa] externals/llm 6054da6b58 65/71: Plz (#46), ELPA Syncer, 2024/05/17
- [elpa] externals/llm 54f38fef5b 63/71: Merge pull request #41 from r0man/plz-timer, ELPA Syncer, 2024/05/17