Function: eca-process--make-filter
eca-process--make-filter is a natively compiled function defined in
eca-process.el.
Signature
(eca-process--make-filter HANDLE-MSG)
Documentation
Return a process filter function that parse JSON-RPC from stdout.
HANDLE-MSG is called for each complete message parsed.
The returned closure captures parsing state across invocations so that
messages larger than a single OS pipe read (e.g. large write_file
tool calls with full diffs) are reassembled correctly.
Source Code
;; Defined in /nix/store/jklqzw6pzz6j4jrbv8wy0iwgi7jlrbld-emacs-packages-deps/share/emacs/site-lisp/elpa/eca-20260928.1827/eca-process.el
(defun eca-process--make-filter (handle-msg)
"Return a process filter function that parse JSON-RPC from stdout.
HANDLE-MSG is called for each complete message parsed.
The returned closure captures parsing state across invocations so that
messages larger than a single OS pipe read (e.g. large `write_file'
tool calls with full diffs) are reassembled correctly."
(let (;; Persistent state across filter invocations:
(leftovers nil)
(body-length nil)
(body-received 0)
(body nil))
(lambda (_proc raw-output)
(let ((gc-cons-threshold (max gc-cons-threshold eca-min-gc-cons-threshold))
chunk)
(setf chunk (if (s-blank? leftovers)
(encode-coding-string raw-output 'utf-8-unix t)
(concat leftovers (encode-coding-string raw-output 'utf-8-unix t))))
(setf leftovers nil)
(let (messages)
(while (not (s-blank? chunk))
(if (not body-length)
;; Read headers
(if-let* ((body-sep-pos (string-match-p "\r\n\r\n" chunk)))
;; We've got all the headers, handle them all at once:
(setf body-length (let* ((headers (mapcar #'eca-process--parse-header
(split-string
(substring-no-properties chunk
(or (string-match-p "Content-Length" chunk)
(error "Unable to find Content-Length header"))
body-sep-pos)
"\r\n")))
(content-length (cdr (assoc "Content-Length" headers))))
(if content-length
(string-to-number content-length)
;; This usually means either the server or our parser is
;; screwed up with a previous Content-Length
(error "No Content-Length header")))
body-received 0
body nil
chunk (substring-no-properties chunk (+ body-sep-pos 4)))
;; Haven't found the end of the headers yet. Save everything
;; for when the next chunk arrives and await further input.
(setf leftovers chunk
chunk nil))
(let* ((chunk-length (string-bytes chunk))
(left-to-receive (- body-length body-received))
(this-body (if (< left-to-receive chunk-length)
(prog1 (substring-no-properties chunk 0 left-to-receive)
(setf chunk (substring-no-properties chunk left-to-receive)))
(prog1 chunk
(setf chunk nil))))
(body-bytes (string-bytes this-body)))
(push this-body body)
(setf body-received (+ body-received body-bytes))
(when (>= chunk-length left-to-receive)
(condition-case err
(with-temp-buffer
(apply #'insert
(nreverse
(prog1 body
(setf body-length nil
body-received 0
body nil))))
(decode-coding-region (point-min)
(point-max)
'utf-8)
(goto-char (point-min))
(push (eca-api--json-read-buffer) messages))
(error
(setf body-length nil
body-received 0
body nil)
(eca-warn "Failed to parse the following chunk:\n'''\n%s\n'''\nwith message %s"
(concat leftovers raw-output)
err)))))))
(mapc handle-msg
(nreverse messages)))))))