branch: externals/ellama
commit b2a904de47696e7279239778e6587e5842a16b7f
Author: Sergey Kostyaev <[email protected]>
Commit: Sergey Kostyaev <[email protected]>
Scroll agent status reports
Scroll the chat buffer after inserting visible plan-and-act status reports
and render the saved status summary in those reports. Add coverage for plan
update report scrolling and for tool result insertions continuing to trigger
the shared streaming scroll helper.
---
ellama-tools.el | 5 ++++-
tests/test-ellama-tools.el | 42 ++++++++++++++++++++++++++++++++++++++++++
tests/test-ellama.el | 24 ++++++++++++++++++++++++
3 files changed, 70 insertions(+), 1 deletion(-)
diff --git a/ellama-tools.el b/ellama-tools.el
index 1a97a8369d..fb97a0261d 100644
--- a/ellama-tools.el
+++ b/ellama-tools.el
@@ -4009,13 +4009,15 @@ TEMPLATE-BASE, ROLE and ARGUMENTS are used for template
rendering and hints."
(insert (ellama-get-nick-prefix-for-mode)
" Ellama Agent " title ":\n"
(or body "")
- "\n\n")))))
+ "\n\n")
+ (ellama--scroll buffer (point))))))
(defun ellama-tools--agent-insert-state (session buffer title)
"Insert SESSION plan-and-act state into BUFFER with TITLE."
(when-let* ((state (ellama-tools--agent-state session)))
(let ((plan (ellama-tools--agent-render-plan state))
(phase (plist-get state :phase))
+ (status (plist-get state :status))
(result (plist-get state :result))
(blocked (plist-get state :blocked)))
(ellama-tools--agent-insert-note
@@ -4024,6 +4026,7 @@ TEMPLATE-BASE, ROLE and ARGUMENTS are used for template
rendering and hints."
(string-join
(delq nil
(list (format "Phase: %s" phase)
+ (when status (format "Status: %s" status))
(unless (string-empty-p plan) plan)
(when blocked (format "Blocked: %s" blocked))
(when result (format "Result: %s" result))))
diff --git a/tests/test-ellama-tools.el b/tests/test-ellama-tools.el
index e058e753e1..cae711ca63 100644
--- a/tests/test-ellama-tools.el
+++ b/tests/test-ellama-tools.el
@@ -3108,6 +3108,48 @@ Return list with result and prompt."
(when (buffer-live-p buffer)
(kill-buffer buffer)))))
+(ert-deftest test-ellama-agent-update-plan-scrolls-report ()
+ (ellama-test--ensure-local-ellama-tools)
+ (let* ((buffer (generate-new-buffer " *ellama-agent-update-test*"))
+ (session (make-ellama-session
+ :id "agent-update"
+ :extra (list :uid "agent-update-uid"
+ :agent-loop
+ (list :phase 'acting
+ :plan (list (list :id 1
+ :title "Inspect"
+ :status 'pending))
+ :completed nil))))
+ (scroll-call nil))
+ (unwind-protect
+ (progn
+ (with-current-buffer buffer
+ (org-mode))
+ (cl-letf (((symbol-function 'ellama-get-session-buffer)
+ (lambda (id)
+ (and (member id '("agent-update"
+ "agent-update-uid"))
+ buffer)))
+ ((symbol-function 'ellama--scroll)
+ (lambda (&optional scroll-buffer point)
+ (setq scroll-call (list scroll-buffer point)))))
+ (let ((ellama-tools--current-session session))
+ (should (equal
+ (ellama-tools-agent-update-plan-tool
+ "- [X] Inspect\n- [ ] Implement"
+ "Inspection done")
+ "Plan updated.")))
+ (should (eq (car scroll-call) buffer))
+ (with-current-buffer buffer
+ (should (string-match-p "Ellama Agent Status:"
+ (buffer-string)))
+ (should (string-match-p "Status: Inspection done"
+ (buffer-string)))
+ (should (string-match-p "- \\[X\\] Inspect"
+ (buffer-string))))))
+ (when (buffer-live-p buffer)
+ (kill-buffer buffer)))))
+
(ert-deftest test-ellama-agent-error-callback-continues-and-compacts-on-repeat
()
(ellama-test--ensure-local-ellama-tools)
(let* ((buffer (generate-new-buffer " *ellama-agent-error-test*"))
diff --git a/tests/test-ellama.el b/tests/test-ellama.el
index 230a3e452a..85dae8e33c 100644
--- a/tests/test-ellama.el
+++ b/tests/test-ellama.el
@@ -320,6 +320,30 @@ STYLE controls partial message shape. Default value is
`word-leading'."
'((read_file . "\"one\\ntwo\"")))
"read_file\n one\n two")))
+(ert-deftest test-ellama-handle-partial-scrolls-tool-results ()
+ (let ((buffer (generate-new-buffer " *ellama-tool-results-test*"))
+ (reasoning-buffer (generate-new-buffer "
*ellama-tool-reasoning-test*"))
+ (ellama-auto-scroll t)
+ (scroll-call nil))
+ (unwind-protect
+ (progn
+ (cl-letf (((symbol-function 'ellama--scroll)
+ (lambda (&optional scroll-buffer point)
+ (setq scroll-call (list scroll-buffer point)))))
+ (let ((insert-text (ellama--insert buffer nil #'identity)))
+ (funcall
+ (ellama--handle-partial insert-text #'ignore reasoning-buffer)
+ '(:tool-results ((read_file . "\"one\\ntwo\""))))))
+ (should (eq (car scroll-call) buffer))
+ (should (markerp (cadr scroll-call)))
+ (with-current-buffer buffer
+ (should (string-match-p "read_file" (buffer-string)))
+ (should (string-match-p "one" (buffer-string)))))
+ (when (buffer-live-p buffer)
+ (kill-buffer buffer))
+ (when (buffer-live-p reasoning-buffer)
+ (kill-buffer reasoning-buffer)))))
+
(ert-deftest test-ellama-default-stream-filter-translates-org-think ()
(with-temp-buffer
(org-mode)