diff --git a/ai-code.el b/ai-code.el index df40c7c..4fe9e9b 100644 --- a/ai-code.el +++ b/ai-code.el @@ -221,7 +221,26 @@ ARG is the prefix argument." (string-match-p "\\S-" clipboard-context)) (concat "\n\nClipboard context:\n" clipboard-context))))) - (ai-code--insert-prompt final-prompt))))) + (ai-code--insert-prompt final-prompt))))) + +(defconst ai-code-session-checkpoint-prompt + (concat + "Please stop and output a CHECKPOINT:\n" + "- Goal\n" + "- Files changed\n" + "- Current hypothesis\n" + "- Tests/build result\n" + "- Blockers\n" + "- Recommended next action\n" + "Do not continue editing after this checkpoint") + "Prompt sent by `ai-code-session-checkpoint'.") + +;;;###autoload +(defun ai-code-session-checkpoint () + "Ask the active AI session to summarize its current state and stop editing." + (interactive) + (ai-code-cli-send-command ai-code-session-checkpoint-prompt) + (ai-code-cli-switch-to-buffer)) (defun ai-code--emacs-runtime-debug-prompt (description eval-available-p) "Return an Emacs runtime debugging prompt from DESCRIPTION. @@ -420,6 +439,7 @@ Shows the current backend label to the right." (transient-define-group ai-code--menu-other-tools (ai-code--infix-toggle-auto-follow-up) ("." "Init projectile and gtags" ai-code-init-project) + ("P" "AI session checkpoint" ai-code-session-checkpoint) ("e" "Debug exception (C-u: clipboard)" ai-code-investigate-exception) ("f" "Fix Flycheck errors in scope" ai-code-flycheck-fix-errors-in-scope) ("k" "Copy Cur File Name (C-u: full)" ai-code-copy-buffer-file-name-to-clipboard) diff --git a/test/test_ai-code.el b/test/test_ai-code.el index 4f39989..94e72c6 100644 --- a/test/test_ai-code.el +++ b/test/test_ai-code.el @@ -185,6 +185,31 @@ (should (equal (plist-get (cdr suffix) :description) "Debug Emacs runtime")))) +(ert-deftest ai-code-test-session-checkpoint-sends-fixed-checkpoint-prompt () + "Test that session checkpoint sends the expected fixed prompt." + (let (sent-command switched) + (cl-letf (((symbol-function 'ai-code-cli-send-command) + (lambda (&rest args) + (setq sent-command (car args)))) + ((symbol-function 'ai-code-cli-switch-to-buffer) + (lambda (&rest _args) + (setq switched t)))) + (ai-code-session-checkpoint)) + (should + (equal sent-command + "Please stop and output a CHECKPOINT:\n- Goal\n- Files changed\n- Current hypothesis\n- Tests/build result\n- Blockers\n- Recommended next action\nDo not continue editing after this checkpoint")) + (should switched))) + +(ert-deftest ai-code-test-menu-other-tools-includes-session-checkpoint-entry () + "Test that the Other Tools menu exposes AI session checkpoint." + (let* ((suffix (transient-get-suffix 'ai-code--menu-other-tools "P")) + (definition (cdr suffix))) + (should suffix) + (should (eq (plist-get definition :command) + 'ai-code-session-checkpoint)) + (should (equal (plist-get definition :description) + "AI session checkpoint")))) + (ert-deftest ai-code-test-menu-prefix-command-default-layout () "Test that the default menu layout uses the original transient." (let ((ai-code-menu-layout 'default))