[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/llm 29d7c3f6b8 55/71: Update media type and event sourc
From: |
ELPA Syncer |
Subject: |
[elpa] externals/llm 29d7c3f6b8 55/71: Update media type and event source packages |
Date: |
Fri, 17 May 2024 00:58:48 -0400 (EDT) |
branch: externals/llm
commit 29d7c3f6b87cc7ddafbc8e047abfe1517e4f56c1
Author: Roman Scherer <roman@burningswell.com>
Commit: Roman Scherer <roman@burningswell.com>
Update media type and event source packages
This PR updates the media type and event source packages. There
- I moved the decoding from the process filter to the media type. Not
everything should be decoded, e.g. binary data, and some media types
have a default encoding (text/event-stream is always UTF-8 for
example).
- The plz-media-type:text/event-stream got renamed to
plz-event-source:text/event-stream to reflect the package in which it
is defined.
- Fixed some lint issues in the event source package
---
llm-request-plz.el | 2 +-
plz-event-source.el | 40 ++++++++++++++++--------------
plz-media-type.el | 71 ++++++++++++++++++++++++++++++++++++-----------------
3 files changed, 71 insertions(+), 42 deletions(-)
diff --git a/llm-request-plz.el b/llm-request-plz.el
index 82755484f1..ea733f8a31 100644
--- a/llm-request-plz.el
+++ b/llm-request-plz.el
@@ -250,7 +250,7 @@ This is required.
:timeout timeout
:media-type
(cons 'text/event-stream
- (plz-media-type:text/event-stream
+ (plz-event-source:text/event-stream
;; Convert so that each event handler gets
the body, not the
;; `plz-response' itself.
:events (mapcar
diff --git a/plz-event-source.el b/plz-event-source.el
index 4f2cad0d23..e0a4b83a9b 100644
--- a/plz-event-source.el
+++ b/plz-event-source.el
@@ -312,7 +312,7 @@
;; Buffer event source
-(defclass plz-buffer-event-source (plz-event-source)
+(defclass plz-event-source-buffer (plz-event-source)
((buffer
:initarg :buffer
:documentation "The event source buffer."
@@ -323,7 +323,7 @@
:type (or null plz-event-source-parser)))
"A server sent event source using curl for HTTP.")
-(cl-defmethod plz-event-source-insert ((source plz-buffer-event-source) data)
+(cl-defmethod plz-event-source-insert ((source plz-event-source-buffer) data)
"Insert DATA into the event SOURCE buffer, parse and dispatch events."
(with-slots (parser) source
(plz-event-source-parser-insert parser data)
@@ -338,7 +338,7 @@
(re-search-forward plz-http-end-of-headers-regexp nil t)
(point)))
-(cl-defmethod plz-event-source-open ((source plz-buffer-event-source))
+(cl-defmethod plz-event-source-open ((source plz-event-source-buffer))
"Open a connection to the URL of the event SOURCE."
(with-slots (buffer errors options ready-state parser) source
(with-current-buffer (get-buffer-create buffer)
@@ -351,7 +351,7 @@
(plz-event-source-dispatch-event source event)
source))))
-(cl-defmethod plz-event-source-close ((source plz-buffer-event-source))
+(cl-defmethod plz-event-source-close ((source plz-event-source-buffer))
"Close the connection of the event SOURCE."
(with-slots (buffer ready-state) source
(let ((event (plz-event-source-event :type 'close)))
@@ -359,7 +359,7 @@
(plz-event-source-dispatch-event source event)
source)))
-(defclass plz-http-event-source (plz-event-source)
+(defclass plz-event-source-http (plz-event-source)
((process
:initarg :process
:documentation "The process of the event source."
@@ -373,10 +373,10 @@
(defun plz-event-source--media-types (source)
"Return the media types of the event SOURCE."
(with-slots (handlers) source
- (let ((media-type (plz-media-type:text/event-stream :events handlers)))
+ (let ((media-type (plz-event-source:text/event-stream :events handlers)))
(cons (cons 'text/event-stream media-type) plz-media-types))))
-(cl-defmethod plz-event-source-open ((source plz-http-event-source))
+(cl-defmethod plz-event-source-open ((source plz-event-source-http))
"Open a connection to the URL of the event SOURCE."
(with-slots (errors options process ready-state response url) source
(setf ready-state 'connecting)
@@ -395,7 +395,7 @@
(setf ready-state 'closed))))
source))
-(cl-defmethod plz-event-source-close ((source plz-http-event-source))
+(cl-defmethod plz-event-source-close ((source plz-event-source-http))
"Close the connection of the event SOURCE."
(with-slots (process ready-state) source
(delete-process process)
@@ -403,27 +403,28 @@
;; Content Type: text/event-stream
-(defclass plz-media-type:text/event-stream
(plz-media-type:application/octet-stream)
- ((type :initform 'text)
+(defclass plz-event-source:text/event-stream
(plz-media-type:application/octet-stream)
+ ((coding-system :initform 'utf-8)
+ (type :initform 'text)
(subtype :initform 'event-stream)
(events :documentation "Association list from event type to handler."
:initarg :events
:initform nil
:type list))
- "A media type class that handles the processing of HTTP responses
+ "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.")
+body slot of the plz-response structure 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.")
-(cl-defmethod plz-media-type-else ((_ plz-media-type:text/event-stream) error)
+(cl-defmethod plz-media-type-else ((_ plz-event-source:text/event-stream)
error)
"Transform the ERROR into a format suitable for MEDIA-TYPE."
(let* ((source plz-event-source--current)
(event (plz-event-source-event :type 'error :data error)))
@@ -431,14 +432,14 @@ callbacks will always be set to nil.")
(plz-event-source-dispatch-event source event)
error))
-(cl-defmethod plz-media-type-process ((media-type
plz-media-type:text/event-stream) process chunk)
+(cl-defmethod plz-media-type-process ((media-type
plz-event-source:text/event-stream) process chunk)
"Process the CHUNK according to MEDIA-TYPE using PROCESS."
(unless plz-event-source--current
(let* ((response (make-plz-response
:status (plz-response-status chunk)
:headers (plz-response-headers chunk)))
(source (plz-event-source-open
- (plz-buffer-event-source
+ (plz-event-source-buffer
:buffer (buffer-name (process-buffer process))
:handlers (seq-map
(lambda (pair)
@@ -456,10 +457,11 @@ callbacks will always be set to nil.")
(t pair))))
(oref media-type events))))))
(setq-local plz-event-source--current source)))
- (plz-event-source-insert plz-event-source--current (plz-response-body chunk))
- (set-marker (process-mark process) (point)))
+ (let ((body (plz-media-type-decode-string media-type (plz-response-body
chunk))))
+ (plz-event-source-insert plz-event-source--current body)
+ (set-marker (process-mark process) (point))))
-(cl-defmethod plz-media-type-then ((media-type
plz-media-type:text/event-stream) response)
+(cl-defmethod plz-media-type-then ((media-type
plz-event-source:text/event-stream) response)
"Transform the RESPONSE into a format suitable for MEDIA-TYPE."
(plz-event-source-close plz-event-source--current)
(cl-call-next-method media-type response)
diff --git a/plz-media-type.el b/plz-media-type.el
index 4216cba7b9..b350a8f641 100644
--- a/plz-media-type.el
+++ b/plz-media-type.el
@@ -52,23 +52,32 @@
cause)
(defclass plz-media-type ()
- ((type
+ ((coding-system
+ :documentation "The coding system to use for the media type."
+ :initarg :coding-system
+ :initform nil
+ :type (or null symbol))
+ (type
:documentation "The media type."
:initarg :type
:type symbol)
(subtype
:documentation "The media subtype."
:initarg :subtype
- :subtype symbol)
+ :type symbol)
(parameters
:documentation "The parameters of the media type."
:initarg :parameters
:initform nil
- :subtype list))
+ :type 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.")
+processing of streaming and non-streaming HTTP responses. The
+response will be decoded with the coding-system of the charset
+parameter in the content type header, or the coding-sytem of the
+media type. If the coding system of a media type is nil, the
+response will not be decoded.")
(defun plz-media-type-charset (media-type)
"Return the character set of the MEDIA-TYPE."
@@ -77,7 +86,9 @@ processing of streaming and non-streaming HTTP responses.")
(defun plz-media-type-coding-system (media-type)
"Return the coding system of the MEDIA-TYPE."
- (coding-system-from-name (or (plz-media-type-charset media-type) "UTF-8")))
+ (if-let (charset (plz-media-type-charset media-type))
+ (coding-system-from-name charset)
+ (oref media-type coding-system)))
(defun plz-media-type-name (media-type)
"Return the name of the MEDIA-TYPE as a string."
@@ -134,10 +145,17 @@ an alist of parameters."
(alist-get t media-types)
(plz-media-type:application/octet-stream)))
-(defun plz-media-type--of-response (media-types response)
+(defun plz-media-type-of-response (media-types response)
"Lookup the content type of RESPONSE in MEDIA-TYPES."
(let ((media-type (plz-media-type--content-type response)))
- (clone (plz-media--type-find media-types media-type))))
+ (clone (plz-media--type-find media-types media-type)
+ :parameters (oref media-type parameters))))
+
+(defun plz-media-type-decode-string (media-type string)
+ "Decode the STRING according to the MEDIA-TYPE."
+ (if-let (coding-system (plz-media-type-coding-system media-type))
+ (decode-coding-string string coding-system)
+ string))
(defvar-local plz-media-type--current nil
"The media type of the process buffer.")
@@ -161,10 +179,8 @@ CHUNK is a part of the HTTP body."
(with-current-buffer (process-buffer process)
(let ((moving (= (point) (process-mark process))))
(if-let (media-type plz-media-type--current)
- (let ((coding-system (plz-media-type-coding-system media-type))
- (response plz-media-type--response))
- (setf (plz-response-body response)
- (decode-coding-string chunk coding-system))
+ (let ((response plz-media-type--response))
+ (setf (plz-response-body response) chunk)
(plz-media-type-process media-type process response))
(progn
(save-excursion
@@ -176,8 +192,7 @@ CHUNK is a part of the HTTP body."
(let ((body-start (point)))
(goto-char (point-min))
(let* ((response (prog1 (plz--response) (widen)))
- (media-type (plz-media-type--of-response media-types
response))
- (coding-system (plz-media-type-coding-system
media-type)))
+ (media-type (plz-media-type-of-response media-types
response)))
(setq-local plz-media-type--current media-type)
(setq-local plz-media-type--response
(make-plz-response
@@ -186,8 +201,7 @@ CHUNK is a part of the HTTP body."
: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))
+ (setf (plz-response-body response) body)
(delete-region body-start (point-max))
(set-marker (process-mark process) (point))
(plz-media-type-process media-type process
response))))))))
@@ -224,13 +238,14 @@ body. It is used as the default media type processor.")
(ignore media-type)
(save-excursion
(goto-char (process-mark process))
- (insert (plz-response-body chunk))
+ (insert (plz-media-type-decode-string media-type (plz-response-body
chunk)))
(set-marker (process-mark process) (point))))
;; Content Type: application/json
(defclass plz-media-type:application/json
(plz-media-type:application/octet-stream)
- ((subtype :initform 'json)
+ ((coding-system :initform 'utf-8)
+ (subtype :initform 'json)
(array-type
:documentation "Specifies which Lisp type is used to represent arrays. It
can be
`array' (the default) or `list'."
@@ -347,7 +362,6 @@ will always be set to nil.")
((media-type plz-media-type:application/json-array) response)
"Transform the RESPONSE into a format suitable for MEDIA-TYPE."
(ignore media-type)
- (plz-media-type:application/json-array--parse-stream media-type)
(setf (plz-response-body response) nil)
response)
@@ -401,14 +415,15 @@ will always be set to nil.")
(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)
+ (ignore 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))
+ ((coding-system :initform 'utf-8)
+ (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
@@ -428,7 +443,7 @@ function.")
(defclass plz-media-type:text/html (plz-media-type:application/xml)
((type :initform 'text)
- (subtype :initform 'xml))
+ (subtype :initform 'html))
"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
@@ -436,11 +451,23 @@ body of the plz-response structure is set to the result
of parsing
the HTTP response body with the `libxml-parse-html-region'
function.")
+(defclass plz-media-type:text/xml (plz-media-type:application/xml)
+ ((coding-system :initform 'us-ascii)
+ (type :initform 'text)
+ (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))
(application/octet-stream . ,(plz-media-type:application/octet-stream))
(application/xml . ,(plz-media-type:application/xml))
(text/html . ,(plz-media-type:text/html))
+ (text/xml . ,(plz-media-type:text/xml))
(t . ,(plz-media-type:application/octet-stream)))
"Association list from media type to content type.")
@@ -452,7 +479,7 @@ function.")
(cond
((plz-error-response plzerror)
(let ((response (plz-error-response plzerror)))
- (if-let (media-type (plz-media-type--of-response media-types
response))
+ (if-let (media-type (plz-media-type-of-response media-types
response))
(list msg (with-temp-buffer
(when-let (body (plz-response-body response))
(insert body)
- [elpa] externals/llm 385ce9cdac 32/71: Use the streaming endpoint for the Vertex provider, (continued)
- [elpa] externals/llm 385ce9cdac 32/71: Use the streaming endpoint for the Vertex provider, ELPA Syncer, 2024/05/17
- [elpa] externals/llm 1fb8511867 36/71: Use media type only in the llm-request-plz-async call, ELPA Syncer, 2024/05/17
- [elpa] externals/llm 5623482527 37/71: Fix error handling in Gemini and Vertex provider, ELPA Syncer, 2024/05/17
- [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 <=
- [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, 2024/05/17
- [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