ALIV37TMXXHTQ3Q2HHHEXLOQDNUZVZ3NNO6WN46DQBPJELDXJOXAC (defcustom madrigal-log-buffer-name "*madrigal-log*""Name of the org buffer used for madrigal request logs.":type 'string)(defcustom madrigal-open-log-buffer t"When non-nil, open the madrigal log buffer when a request starts.":type 'boolean)(defcustom madrigal-log-include-reasoning t"When non-nil, include model reasoning in the madrigal org log.":type 'boolean)(defcustom madrigal-log-include-context t"When non-nil, include the full context window sent to the model in logs.":type 'boolean)(defcustom madrigal-log-start-collapsed t"When non-nil, keep the madrigal org log folded to top-level headings.":type 'boolean)
(defun madrigal--ensure-log-buffer ()(let ((buf (get-buffer-create madrigal-log-buffer-name)))(with-current-buffer buf(unless (derived-mode-p 'org-mode)(org-mode)))buf))(defun madrigal--log-refresh-visibility (buffer)(when madrigal-log-start-collapsed(with-current-buffer buffer(when (derived-mode-p 'org-mode)(save-excursion(org-overview))))))(defun madrigal--pp-string (obj)(with-temp-buffer(let ((print-length nil)(print-level nil))(pp obj (current-buffer))(buffer-string))))(defun madrigal--log-insert-example-block (text)(insert "#+begin_example\n")(insert (or text ""))(unless (or (string-empty-p (or text ""))(string-suffix-p "\n" text))(insert "\n"))(insert "#+end_example\n\n"))(defun madrigal--log-insert-src-block (obj)(let ((text (madrigal--pp-string obj)))(insert "#+begin_src emacs-lisp\n")(insert text)(unless (string-suffix-p "\n" text)(insert "\n"))(insert "#+end_src\n\n")))
(defun madrigal--log-new-request (agent-id source-buffer prompt-text context-text)(let* ((buf (madrigal--ensure-log-buffer))(stamp (format-time-string "%Y-%m-%d %H:%M:%S"))(path (with-current-buffer source-buffer(or buffer-file-name "(no file)")))(request-id (format "%s-%04d"(format-time-string "%Y%m%dT%H%M%S")(cl-incf madrigal--log-request-seq)))marker)(with-current-buffer buf(goto-char (point-max))(unless (bolp)(insert "\n"))(insert (format "* Request %s\n" stamp))(insert ":PROPERTIES:\n")(insert (format ":agent: %s\n" agent-id))(insert (format ":buffer: %s\n" (buffer-name source-buffer)))(insert (format ":path: %s\n" path))(insert (format ":request-id: %s\n" request-id))(insert ":END:\n\n")(insert "** User Prompt\n")(madrigal--log-insert-example-block prompt-text)(when madrigal-log-include-context(insert "** Context Window\n")(madrigal--log-insert-example-block context-text))(setq marker (copy-marker (point) t)))(puthash request-id marker madrigal--log-request-markers)(when madrigal-open-log-buffer(display-buffer buf))(madrigal--log-refresh-visibility buf)request-id))(defun madrigal--log-append-heading (request-id level heading)(let* ((buf (madrigal--ensure-log-buffer))(marker (gethash request-id madrigal--log-request-markers)))(with-current-buffer buf(save-excursion(goto-char (if (and marker (marker-buffer marker)) marker (point-max)))(insert (make-string level ?*) " " heading "\n")(setf marker (copy-marker (point) t))(puthash request-id marker madrigal--log-request-markers)))(madrigal--log-refresh-visibility buf)buf))(defun madrigal--log-append-example (request-id level heading text)(let ((buf (madrigal--log-append-heading request-id level heading)))(with-current-buffer buf(save-excursion(goto-char (gethash request-id madrigal--log-request-markers))(madrigal--log-insert-example-block text)(puthash request-id (copy-marker (point) t) madrigal--log-request-markers)))(madrigal--log-refresh-visibility buf)))(defun madrigal--log-append-obj (request-id level heading obj)(let ((buf (madrigal--log-append-heading request-id level heading)))(with-current-buffer buf(save-excursion(goto-char (gethash request-id madrigal--log-request-markers))(madrigal--log-insert-src-block obj)(puthash request-id (copy-marker (point) t) madrigal--log-request-markers)))(madrigal--log-refresh-visibility buf)))(defun madrigal--log-round (request-id round final)(when request-id(madrigal--log-append-heading request-id 2 (format "Round %d" round))(let ((reasoning (plist-get final :reasoning))(text (plist-get final :text))(tool-uses (plist-get final :tool-uses))(tool-results (plist-get final :tool-results)))(when (and madrigal-log-include-reasoning reasoning)(madrigal--log-append-example request-id 3 "Reasoning" (format "%s" reasoning)))(when (and text (> (length text) 0))(madrigal--log-append-example request-id 3 "Response" text))(when tool-uses(madrigal--log-append-obj request-id 3 "Tool Uses" tool-uses))(when tool-results(madrigal--log-append-obj request-id 3 "Tool Results" tool-results)))))(defun madrigal--log-error (request-id heading etype message)(when request-id(madrigal--log-append-heading request-id 2 heading)(madrigal--log-append-obj request-id 3 "Error"`((type . ,etype)(message . ,message)))))(defun madrigal--log-tool-op (request-id heading payload)(when request-id(madrigal--log-append-obj request-id 4 heading payload)))
("open_file"(let* ((path0 (or (madrigal--alist-get* 'path raw-op)(madrigal--alist-get* :path raw-op)))(create0 (or (madrigal--alist-get* 'create raw-op)
("open_file"(let* ((path0 (or (madrigal--alist-get* 'path raw-op)(madrigal--alist-get* :path raw-op)))(create0 (or (madrigal--alist-get* 'create raw-op)
("list_buffers"(let (names)(maphash (lambda (k _v) (push k names))(crdt--session-buffer-table madrigal--server-session))(setq row (append row (list (cons 'buffers (nreverse names)))))))("switch_buffer"(let* ((name0 (or (madrigal--alist-get* 'network_name raw-op)(madrigal--alist-get* :network_name raw-op)(madrigal--alist-get* 'buffer raw-op)
("list_buffers"(let (names)(maphash (lambda (k _v) (push k names))(crdt--session-buffer-table madrigal--server-session))(setq row (append row (list (cons 'buffers (nreverse names)))))))("switch_buffer"(let* ((name0 (or (madrigal--alist-get* 'network_name raw-op)(madrigal--alist-get* :network_name raw-op)(madrigal--alist-get* 'buffer raw-op)
("get_point"(with-current-buffer replica(setq row (append row(list (cons 'point (point))(cons 'region_active (and (use-region-p) t))(cons 'region_start (and (use-region-p) (region-beginning)))(cons 'region_end (and (use-region-p) (region-end))))))))("goto_char"(let* ((pos0 (or (madrigal--alist-get* 'pos raw-op)(madrigal--alist-get* :pos raw-op)))(pos (madrigal--require-integer
("get_point"(with-current-buffer replica(setq row (append row(list (cons 'point (point))(cons 'region_active (and (use-region-p) t))(cons 'region_start (and (use-region-p) (region-beginning)))(cons 'region_end (and (use-region-p) (region-end))))))))("goto_char"(let* ((pos0 (or (madrigal--alist-get* 'pos raw-op)(madrigal--alist-get* :pos raw-op)))(pos (madrigal--require-integer
("search_forward"(let* ((needle0 (or (madrigal--alist-get* 'needle raw-op)(madrigal--alist-get* :needle raw-op)))(count0 (or (madrigal--alist-get* 'count raw-op)
("search_forward"(let* ((needle0 (or (madrigal--alist-get* 'needle raw-op)(madrigal--alist-get* :needle raw-op)))(count0 (or (madrigal--alist-get* 'count raw-op)
(cons 'match_end (point))))))))("search_backward"(let* ((needle0 (or (madrigal--alist-get* 'needle raw-op)(madrigal--alist-get* :needle raw-op)))(count0 (or (madrigal--alist-get* 'count raw-op)
(cons 'match_end (point)))))))))("search_backward"(let* ((needle0 (or (madrigal--alist-get* 'needle raw-op)(madrigal--alist-get* :needle raw-op)))(count0 (or (madrigal--alist-get* 'count raw-op)
(cons 'match_end (+ found (length needle)))))))))("set_region"(let* ((start0 (or (madrigal--alist-get* 'start raw-op)(madrigal--alist-get* :start raw-op)))(end0 (or (madrigal--alist-get* 'end raw-op)
(cons 'match_end (+ found (length needle))))))))))("set_region"(let* ((start0 (or (madrigal--alist-get* 'start raw-op)(madrigal--alist-get* :start raw-op)))(end0 (or (madrigal--alist-get* 'end raw-op)
(cons 'point (with-current-buffer replica (point))))))))("clear_region"(madrigal--clear-region replica)(setq row (append row (list (cons 'region_active nil)))))("read_region"(let* ((start0 (or (madrigal--alist-get* 'start raw-op)(madrigal--alist-get* :start raw-op)))(end0 (or (madrigal--alist-get* 'end raw-op)
(cons 'point (with-current-buffer replica (point)))))))))("clear_region"(madrigal--clear-region replica)(setq row (append row (list (cons 'region_active nil)))))("read_region"(let* ((start0 (or (madrigal--alist-get* 'start raw-op)(madrigal--alist-get* :start raw-op)))(end0 (or (madrigal--alist-get* 'end raw-op)
("insert_text"(let* ((text0 (or (madrigal--alist-get* 'text raw-op)(madrigal--alist-get* :text raw-op)))(text (format "%s" (madrigal--resolve-ref text0 results))))
("insert_text"(let* ((text0 (or (madrigal--alist-get* 'text raw-op)(madrigal--alist-get* :text raw-op)))(text (format "%s" (madrigal--resolve-ref text0 results))))
("delete_selection"(with-current-buffer replica(pcase-let ((`(,s . ,e) (madrigal--region-bounds-required replica)))(delete-region s e)
("delete_selection"(with-current-buffer replica(pcase-let ((`(,s . ,e) (madrigal--region-bounds-required replica)))(delete-region s e)
("replace_selection"(let* ((text0 (or (madrigal--alist-get* 'text raw-op)(madrigal--alist-get* :text raw-op)))(text (format "%s" (madrigal--resolve-ref text0 results))))
("replace_selection"(let* ((text0 (or (madrigal--alist-get* 'text raw-op)(madrigal--alist-get* :text raw-op)))(text (format "%s" (madrigal--resolve-ref text0 results))))
("replace_match"(let* ((needle0 (or (madrigal--alist-get* 'needle raw-op)(madrigal--alist-get* :needle raw-op)))(text0 (or (madrigal--alist-get* 'text raw-op)
("replace_match"(let* ((needle0 (or (madrigal--alist-get* 'needle raw-op)(madrigal--alist-get* :needle raw-op)))(text0 (or (madrigal--alist-get* 'text raw-op)
(cons 'point (or last-pos (point)))))))))))("replace_in_selection"(let* ((bounds (madrigal--region-bounds-required replica))(old0 (or (madrigal--alist-get* 'old_text raw-op)(madrigal--alist-get* :old_text raw-op)))
(cons 'point (or last-pos (point))))))))))("replace_in_selection"(let* ((bounds (madrigal--region-bounds-required replica))(old0 (or (madrigal--alist-get* 'old_text raw-op)(madrigal--alist-get* :old_text raw-op)))
("save_buffer"(let ((server-buffer (madrigal--server-buffer-from-network-name network-name)))(unless (buffer-live-p server-buffer)(error "madrigal: no server buffer for %s" network-name))
("save_buffer"(let ((server-buffer (madrigal--server-buffer-from-network-name network-name)))(unless (buffer-live-p server-buffer)(error "madrigal: no server buffer for %s" network-name))
:function (lambda (ops)(madrigal--tool-exec-ops agent-id ops))))
:function (lambda (ops)(condition-case err(madrigal--tool-exec-ops agent-id ops request-id)(error(madrigal--log-tool-op request-id"exec_ops failure"`((error . ,(error-message-string err))))(signal (car err) (cdr err)))))))
(defun madrigal--run-model-loop (provider prompt rounds-left done)(if (<= rounds-left 0)(funcall done (list :status 'error :message "madrigal: max rounds reached"))(let* ((streaming-tool-use (madrigal--provider-capable-p 'streaming-tool-use))(streaming (madrigal--provider-capable-p 'streaming))(use-streaming (and streaming streaming-tool-use)))(if use-streaming(llm-chat-streaming
(defun madrigal--run-model-loop (provider prompt rounds-left done &optional request-id round)(let ((round-no (or round 1)))(if (<= rounds-left 0)(progn(madrigal--log-error request-id "Loop Error" 'max-rounds "madrigal: max rounds reached")(funcall done (list :status 'error :message "madrigal: max rounds reached")))(let* ((streaming-tool-use (madrigal--provider-capable-p 'streaming-tool-use))(streaming (madrigal--provider-capable-p 'streaming))(use-streaming (and streaming streaming-tool-use)))(if use-streaming(llm-chat-streamingprovider prompt(lambda (partial)(let ((txt (plist-get partial :text)))(when (and txt (> (length txt) 0))(message "madrigal: %s" (truncate-string-to-width txt 120 nil nil t)))))(lambda (final)(madrigal--log-round request-id round-no final)(if (plist-get final :tool-results)(madrigal--run-model-loop provider prompt (1- rounds-left) done request-id (1+ round-no))(funcall done (list :status 'ok :result final))))(lambda (etype emsg)(madrigal--log-error request-id (format "Round %d Error" round-no) etype emsg)(funcall done (list :status 'error :etype etype :message emsg)))t)(llm-chat-async
(madrigal--run-model-loop provider prompt (1- rounds-left) done)(funcall done (list :status 'ok :result final))))
(madrigal--run-model-loop provider prompt (1- rounds-left) done request-id (1+ round-no))(funcall done (list :status 'ok :result final :fallback 'non-streaming-tool-use))))
t)(llm-chat-asyncprovider prompt(lambda (final)(if (plist-get final :tool-results)(madrigal--run-model-loop provider prompt (1- rounds-left) done)(funcall done (list :status 'ok :result final :fallback 'non-streaming-tool-use))))(lambda (etype emsg)(funcall done (list :status 'error :etype etype :message emsg)))t)))))
t))))))
(let* ((_agent (madrigal--ensure-agent agent-id))(_shared (madrigal--ensure-shared-in-server (current-buffer)))
(let* ((source-buffer (current-buffer))(context-text (plist-get (madrigal--context-window) :text))(request-id (madrigal--log-new-request agent-id source-buffer prompt-text context-text))(_agent (madrigal--ensure-agent agent-id))(_shared (madrigal--ensure-shared-in-server source-buffer))
(madrigal--build-user-prompt prompt-text):context (madrigal--system-prompt):tools (list (madrigal--exec-ops-tool agent-id)))))
(madrigal--build-user-prompt prompt-text):context (madrigal--system-prompt):tools (list (madrigal--exec-ops-tool agent-id request-id)))))
madrigal-llm-providerpromptmadrigal-max-tool-rounds(lambda (status)(unwind-protect(pcase (plist-get status :status)('ok(let* ((res (plist-get status :result))(text (or (plist-get res :text) ""))(fallback (plist-get status :fallback)))(if fallback(message "madrigal: done (fallback %s). %s" fallback text)(message "madrigal: done. %s" text))))(_(message "madrigal: error (%s) %s"(or (plist-get status :etype) 'error)(or (plist-get status :message) "unknown"))))(madrigal--drop-agent agent-id))))))
madrigal-llm-providerpromptmadrigal-max-tool-rounds(lambda (status)(unwind-protect(pcase (plist-get status :status)('ok(let* ((res (plist-get status :result))(text (or (plist-get res :text) ""))(fallback (plist-get status :fallback)))(madrigal--log-append-heading request-id 2 "Outcome")(madrigal--log-append-obj request-id 3 "Status"`((status . ok)(fallback . ,fallback)(text . ,text)))(if fallback(message "madrigal: done (fallback %s). %s" fallback text)(message "madrigal: done. %s" text))))(_(madrigal--log-append-heading request-id 2 "Outcome")(madrigal--log-append-obj request-id 3 "Status"`((status . error)(type . ,(or (plist-get status :etype) 'error))(message . ,(or (plist-get status :message) "unknown"))))(message "madrigal: error (%s) %s"(or (plist-get status :etype) 'error)(or (plist-get status :message) "unknown"))))(madrigal--drop-agent agent-id)))request-id)))