branch: externals/llm
commit 2146ba3803a75ecf96ea75bd045a89be127cdcfa
Author: r0man <ro...@burningswell.com>
Commit: GitHub <nore...@github.com>

    Change some function names and make most of them private (#42)
    
    * Change some function names and make most of them private
    
    * Add note that plz-media-type and plz-event-source are vendored
    
    * Mention plz-media-type and plz-event-source are part of Emacs
---
 plz-event-source.el | 112 ++++++++++++++++++++++++++--------------------------
 plz-media-type.el   |  77 +++++++++++++++++++++---------------
 2 files changed, 100 insertions(+), 89 deletions(-)

diff --git a/plz-event-source.el b/plz-event-source.el
index d9a71a34e1..f54ed85a5c 100644
--- a/plz-event-source.el
+++ b/plz-event-source.el
@@ -11,6 +11,11 @@
 
 ;; This file is part of GNU Emacs.
 
+;; It is temporarily vendored within the llm library.  Please DO NOT
+;; depend on it!  It is subject to change.  Once we think this package
+;; is stable, we will release it to GNU ELPA.  If no serious issues
+;; are found, we plan to do this in Q4 of 2024.
+
 ;;; License:
 
 ;; This program is free software; you can redistribute it and/or modify
@@ -109,31 +114,31 @@
     :type integer))
   "The server sent event stream parser.")
 
-(defconst plz-event-source--end-of-line-regexp
+(defconst plz-event-source-parser--end-of-line-regexp
   (rx (or "\r\n" "\n" "\r"))
   "Regular expression matching the end of a line.")
 
-(defconst plz-event-source--line-regexp
+(defconst plz-event-source-parser--line-regexp
   (rx (* not-newline) (or "\r\n" "\n" "\r"))
   "Regular expression matching a line of the event source stream.")
 
-(defun plz-event-source--parse-bom (line)
+(defun plz-event-source-parser--parse-bom (line)
   "Parse the Byte Order Mark (BOM) from LINE."
   (if (string-prefix-p "\uFEFF" line)
       (substring line 1)
     line))
 
-(defun plz-event-source--looking-at-line-p ()
+(defun plz-event-source-parser--looking-at-line-p ()
   "Return non-nil if the current line matches the event source line regexp."
-  (looking-at plz-event-source--line-regexp))
+  (looking-at plz-event-source-parser--line-regexp))
 
-(defun plz-event-source--parse-line ()
+(defun plz-event-source-parser--parse-line ()
   "Return non-nil if the current line matches the event source line regexp."
-  (when (looking-at plz-event-source--line-regexp)
+  (when (looking-at plz-event-source-parser--line-regexp)
     (string-trim-right (delete-and-extract-region (match-beginning 0) 
(match-end 0))
-                       plz-event-source--end-of-line-regexp)))
+                       plz-event-source-parser--end-of-line-regexp)))
 
-(defun plz-event-source--dispatch-event (parser)
+(defun plz-event-source-parser--dispatch-event (parser)
   "Dispatch an event from PARSER to registered listeners."
   (with-slots (data-buffer event-type-buffer events last-event-id 
last-event-id-buffer) parser
     (setf last-event-id last-event-id-buffer)
@@ -155,46 +160,39 @@
           (setf events (cons event events))
           event)))))
 
-(defun plz-event-source--process-event (parser field value)
+(defun plz-event-source-parser--process-event (parser field value)
   "Process the FIELD and VALUE from PARSER as a event."
   (ignore field)
   (with-slots (event-type-buffer) parser
     (setf event-type-buffer value)))
 
-(defun plz-event-source--process-data (parser field value)
+(defun plz-event-source-parser--process-data (parser field value)
   "Process the FIELD and VALUE from PARSER as data."
   (ignore field)
   (with-slots (data-buffer) parser
     (setf data-buffer (concat data-buffer value "\n"))))
 
-(defun plz-event-source--process-id (parser field value)
+(defun plz-event-source-parser--process-id (parser field value)
   "Process the FIELD and VALUE from PARSER as event id."
   (ignore field)
   (unless (string-match "\u0000" value)
     (with-slots (last-event-id-buffer) parser
       (setf last-event-id-buffer value))))
 
-(defun plz-event-source--process-retry (parser field value)
-  "Process the FIELD and VALUE from PARSER as event id."
-  (ignore parser)
-  (message "TODO: Process retry for field %s and value %s." field value))
-
 (defun plz-event-source--process-field (parser field value)
   "Process the FIELD and VALUE from PARSER."
   (cond ((equal "event" field)
-         (plz-event-source--process-event parser field value))
+         (plz-event-source-parser--process-event parser field value))
         ((equal "data" field)
-         (plz-event-source--process-data parser field value))
+         (plz-event-source-parser--process-data parser field value))
         ((equal "id" field)
-         (plz-event-source--process-id parser field value))
-        ((equal "retry" field)
-         (plz-event-source--process-retry parser field value))))
+         (plz-event-source-parser--process-id parser field value))))
 
-(defun plz-event-source--process-line (parser line)
+(defun plz-event-source-parser--process-line (parser line)
   "Parse a LINE of the event stream PARSER and dispatch events."
   (cond ((string-prefix-p ":" line))
         ((string-blank-p line)
-         (plz-event-source--dispatch-event parser))
+         (plz-event-source-parser--dispatch-event parser))
         ((string-match ":" line)
          (let ((field (substring line 0 (match-beginning 0)))
                (value (substring line (match-end 0))))
@@ -204,33 +202,40 @@
                                               value))))
         (t (plz-event-source--process-field parser line ""))))
 
-(defun plz-event-source-parse-line (parser)
+(defun plz-event-source-parser--insert (parser string)
+  "Insert STRING into the buffer of the event PARSER."
+  (with-slots (buffer events position) parser
+    (with-current-buffer (get-buffer buffer)
+      (insert string)
+      (while (plz-event-source-parser-parse-line parser))
+      events)))
+
+(defun plz-event-source-parser--end-of-headers ()
+  "Return the end of headers position in the current buffer."
+  (save-excursion
+    (goto-char (point-min))
+    (re-search-forward plz-http-end-of-headers-regexp nil t)
+    (point)))
+
+(defun plz-event-source-parser-parse-line (parser)
   "Parse a line from the event stream in the PARSER buffer."
   (with-slots (buffer position) parser
     (with-current-buffer buffer
       (save-excursion
         (goto-char position)
-        (when-let (line (plz-event-source--parse-line))
+        (when-let (line (plz-event-source-parser--parse-line))
           (setf position (point))
-          (plz-event-source--process-line parser line)
+          (plz-event-source-parser--process-line parser line)
           line)))))
 
-(defun plz-event-source-parse-stream (parser)
+(defun plz-event-source-parser-parse (parser)
   "Parse the event stream in the the PARSER buffer."
   (with-slots (buffer handlers) parser
     (with-current-buffer (get-buffer buffer)
       (goto-char (point-min))
       (while (not (eobp))
-        (when-let (line (plz-event-source--parse-line))
-          (plz-event-source--process-line parser line))))))
-
-(defun plz-event-source-parser-insert (parser string)
-  "Insert STRING into the buffer of the event PARSER."
-  (with-slots (buffer events position) parser
-    (with-current-buffer (get-buffer buffer)
-      (insert string)
-      (while (plz-event-source-parse-line parser))
-      events)))
+        (when-let (line (plz-event-source-parser--parse-line))
+          (plz-event-source-parser--process-line parser line))))))
 
 ;; Event Source
 
@@ -267,7 +272,7 @@
 (cl-defgeneric plz-event-source-close (source)
   "Close the event SOURCE.")
 
-(cl-defgeneric plz-event-source-insert (source data)
+(cl-defgeneric plz-event-source--insert (source data)
   "Insert DATA into the event SOURCE buffer, parse and dispatch events.")
 
 (defun plz-event-source-add-listener (source type listener)
@@ -285,7 +290,7 @@
                                  handlers))
     source))
 
-(defun plz-event-source-dispatch-event (source event)
+(defun plz-event-source--dispatch-event (source event)
   "Dispatch the EVENT to the listeners of event SOURCE."
   (with-slots (handlers) source
     (dolist (pair handlers)
@@ -299,10 +304,10 @@
                               (list (cdr pair) event))
           (timer-activate timer))))))
 
-(defun plz-event-source-dispatch-events (source events)
+(defun plz-event-source--dispatch-events (source events)
   "Dispatch the EVENTS to the listeners of event SOURCE."
   (dolist (event (reverse events))
-    (plz-event-source-dispatch-event source event)))
+    (plz-event-source--dispatch-event source event)))
 
 (defun plz-event-source--response-in-buffer-p ()
   "Return non-nil the if point is looking at a HTTP response."
@@ -310,13 +315,6 @@
     (goto-char (point-min))
     (re-search-forward plz-http-end-of-headers-regexp nil t)))
 
-(defun plz-event-source-parser--end-of-headers ()
-  "Return the end of headers position in the current buffer."
-  (save-excursion
-    (goto-char (point-min))
-    (re-search-forward plz-http-end-of-headers-regexp nil t)
-    (point)))
-
 ;; Buffer event source
 
 (defclass plz-event-source-buffer (plz-event-source)
@@ -330,12 +328,12 @@
     :type (or null plz-event-source-parser)))
   "A server sent event source using curl for HTTP.")
 
-(cl-defmethod plz-event-source-insert ((source plz-event-source-buffer) 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)
+    (plz-event-source-parser--insert parser data)
     (with-slots (events) parser
-      (plz-event-source-dispatch-events source events)
+      (plz-event-source--dispatch-events source events)
       (setf events nil))))
 
 (defun plz-event-source--buffer-start-position ()
@@ -355,7 +353,7 @@
                       :buffer buffer
                       :position (plz-event-source--buffer-start-position)))
         (setf ready-state 'open)
-        (plz-event-source-dispatch-event source event)
+        (plz-event-source--dispatch-event source event)
         source))))
 
 (cl-defmethod plz-event-source-close ((source plz-event-source-buffer))
@@ -363,7 +361,7 @@
   (with-slots (buffer ready-state) source
     (let ((event (plz-event-source-event :type 'close)))
       (setf ready-state 'closed)
-      (plz-event-source-dispatch-event source event)
+      (plz-event-source--dispatch-event source event)
       source)))
 
 (defclass plz-event-source-http (plz-event-source)
@@ -436,7 +434,7 @@ ELSE callbacks will always be set to nil.")
   (let* ((source plz-event-source--current)
          (event (plz-event-source-event :type 'error :data error)))
     (plz-event-source-close source)
-    (plz-event-source-dispatch-event source event)
+    (plz-event-source--dispatch-event source event)
     error))
 
 (cl-defmethod plz-media-type-process ((media-type 
plz-event-source:text/event-stream) process chunk)
@@ -464,8 +462,8 @@ ELSE callbacks will always be set to nil.")
                                      (t pair))))
                                 (oref media-type events))))))
       (setq-local plz-event-source--current source)))
-  (let ((body (plz-media-type-decode-string media-type (plz-response-body 
chunk))))
-    (plz-event-source-insert plz-event-source--current body)
+  (let ((body (plz-media-type-decode-coding-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-event-source:text/event-stream) response)
diff --git a/plz-media-type.el b/plz-media-type.el
index 07ce937447..0421cb48cf 100644
--- a/plz-media-type.el
+++ b/plz-media-type.el
@@ -11,6 +11,11 @@
 
 ;; This file is part of GNU Emacs.
 
+;; It is temporarily vendored within the llm library.  Please DO NOT
+;; depend on it!  It is subject to change.  Once we think this package
+;; is stable, we will release it to GNU ELPA.  If no serious issues
+;; are found, we plan to do this in Q4 of 2024.
+
 ;;; License:
 
 ;; This program is free software; you can redistribute it and/or modify
@@ -72,6 +77,19 @@ 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.")
 
+(cl-defgeneric plz-media-type-else (media-type error)
+  "Transform and handle the ERROR according to MEDIA-TYPE.")
+
+(cl-defgeneric plz-media-type-then (media-type response)
+  "Transform and handle the RESPONSE according to MEDIA-TYPE.")
+
+(cl-defgeneric plz-media-type-process (media-type process chunk)
+  "Process the CHUNK according to MEDIA-TYPE using PROCESS.")
+
+(cl-defmethod plz-media-type-else ((_ (eql nil)) error)
+  "Transform and handle the ERROR according to MEDIA-TYPE."
+  error)
+
 (defun plz-media-type-charset (media-type)
   "Return the character set of the MEDIA-TYPE."
   (with-slots (parameters) media-type
@@ -83,6 +101,12 @@ response will not be decoded.")
       (coding-system-from-name charset)
     (oref media-type coding-system)))
 
+(defun plz-media-type-decode-coding-string (media-type string)
+  "Decode STRING which is encoded in the coding system of MEDIA-TYPE."
+  (if-let (coding-system (plz-media-type-coding-system media-type))
+      (decode-coding-string string coding-system)
+    string))
+
 (defun plz-media-type-name (media-type)
   "Return the name of the MEDIA-TYPE as a string."
   (with-slots (type subtype) media-type
@@ -92,24 +116,14 @@ response will not be decoded.")
   "Return the name of the MEDIA-TYPE as a symbol."
   (intern (plz-media-type-name media-type)))
 
-(cl-defgeneric plz-media-type-else (media-type error)
-  "Transform the ERROR into a format suitable for MEDIA-TYPE.")
-
-(cl-defgeneric plz-media-type-then (media-type response)
-  "Transform the RESPONSE into a format suitable for MEDIA-TYPE.")
-
-(cl-defgeneric plz-media-type-process (media-type process chunk)
-  "Process the CHUNK according to MEDIA-TYPE using PROCESS.")
-
-(cl-defmethod plz-media-type-else ((_ (eql nil)) error)
-  "Transform the ERROR into a format suitable for MEDIA-TYPE."
-  error)
-
-(defun plz-media-type-parse (header)
-  "Parse the Content-Type HEADER.
+(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)
+           :parameters (oref media-type parameters))))
 
-Return a cons cell where the car is the MIME type, and the cdr is
-an alist of parameters."
+(defun plz-media-type--parse (header)
+  "Parse the Content-Type HEADER and return a `plz-media-type' instance."
   (unless (or (null header) (string-blank-p header))
     (let* ((components (split-string header ";"))
            (mime-type (string-trim (car components)))
@@ -130,26 +144,14 @@ an alist of parameters."
   "Return the content type header of RESPONSE, or nil if it's not set."
   (let ((headers (plz-response-headers response)))
     (when-let (header (cdr (assoc 'content-type headers)))
-      (plz-media-type-parse header))))
+      (plz-media-type--parse header))))
 
-(defun plz-media--type-find (media-types media-type)
+(defun plz-media-type--find (media-types media-type)
   "Lookup the MEDIA-TYPE in MEDIA-TYPES."
   (or (alist-get (plz-media-type-symbol media-type) media-types)
       (alist-get t media-types)
       (plz-media-type:application/octet-stream)))
 
-(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)
-           :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.")
 
@@ -264,7 +266,7 @@ body.  It is used as the default media type processor.")
   (ignore media-type)
   (save-excursion
     (goto-char (process-mark process))
-    (insert (plz-media-type-decode-string media-type (plz-response-body 
chunk)))
+    (insert (plz-media-type-decode-coding-string media-type (plz-response-body 
chunk)))
     (set-marker (process-mark process) (point))))
 
 ;; Content Type: application/json
@@ -543,6 +545,17 @@ parsing the HTTP response body with the
      (then 'sync)
      (timeout plz-timeout))
   "Request METHOD from URL with curl.
+
+This function works in a similar way as the `plz' function, with
+the additional functionality of handling streaming and
+non-streaming media types with the :as (media-types MEDIA-TYPES)
+option.  Setting a process :filter by the user is not supported.
+Instead this function will always install its own process filter
+that will process the response until the HTTP headers arrived.
+Once the headers arrived it will hand over control to a media
+type based on the content type header of the response.  The media
+type is responsible for processing the HTTP body.
+
 Return the curl process object or, for a synchronous request, the
 selected result.
 

Reply via email to