Add ERT tests, CI workflow, and shared command helpers#1
Conversation
Reviewer's GuideAdds an ERT-based test suite and GitHub Actions CI for the cursor-agent Emacs package, introduces shared helpers for running CLI commands in compilation buffers with ANSI color handling and installation checks, and refines readiness/auth checks and docs to support the new workflow. Class diagram for cursor-agent command helpers and list commandsclassDiagram
class CursorAgentModule {
+cursor-agent-interactive(initial-prompt)
+cursor-agent-process-region(start end)
+cursor-agent-resume(chat-id)
+cursor-agent-list-sessions()
+cursor-agent-status()
+cursor-agent-list-models()
+cursor-agent-mcp-list()
+cursor-agent-login()
+cursor-agent-installed-p()
+cursor-agent-ready-p()
+cursor-agent-open-readme()
-cursor-agent--run-command-in-compilation-buffer(command buffer-name header-text)
-cursor-agent--run-list-command(command buffer-name header-text)
-cursor-agent--install-sentinel(buffer-name)
}
class CursorAgentCLI {
+ls
+status
+models
+mcp_list
+login
}
CursorAgentModule ..> CursorAgentCLI : uses
CursorAgentModule ..> CursorAgentModule : cursor-agent--run-list-command uses cursor-agent-installed-p
CursorAgentModule ..> CursorAgentModule : cursor-agent--run-list-command uses cursor-agent--run-command-in-compilation-buffer
CursorAgentModule ..> CursorAgentModule : cursor-agent-list-sessions uses cursor-agent--run-list-command
CursorAgentModule ..> CursorAgentModule : cursor-agent-status uses cursor-agent--run-list-command
CursorAgentModule ..> CursorAgentModule : cursor-agent-list-models uses cursor-agent--run-list-command
CursorAgentModule ..> CursorAgentModule : cursor-agent-mcp-list uses cursor-agent--run-list-command
CursorAgentModule ..> CursorAgentModule : cursor-agent-interactive uses cursor-agent--run-command-in-compilation-buffer
CursorAgentModule ..> CursorAgentModule : cursor-agent-process-region uses cursor-agent--run-command-in-compilation-buffer
CursorAgentModule ..> CursorAgentModule : cursor-agent-ready-p uses cursor-agent-installed-p
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 2 issues, and left some high level feedback:
- The four commands that list sessions/status/models/MCP now share nearly identical logic for setting up the buffer, mode, and async shell command; consider factoring this into a small helper to avoid duplication and keep future changes to the behavior in one place.
- The new safety check in
cursor-agent-verify-setupusesfboundponcursor-agent-installed-p; if this function is guaranteed to exist whenevercursor-agentis loaded, you might prefer failing earlier via arequireor simplifying the check to avoid raising a runtime error in normal usage. - In the tests, mocking core functions like
executable-findandshell-command-to-stringwithfsetcan have surprising global side effects (especially under parallel test execution); consider usingcl-letforletfto temporarily rebind these functions in a more scoped way.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The four commands that list sessions/status/models/MCP now share nearly identical logic for setting up the buffer, mode, and async shell command; consider factoring this into a small helper to avoid duplication and keep future changes to the behavior in one place.
- The new safety check in `cursor-agent-verify-setup` uses `fboundp` on `cursor-agent-installed-p`; if this function is guaranteed to exist whenever `cursor-agent` is loaded, you might prefer failing earlier via a `require` or simplifying the check to avoid raising a runtime error in normal usage.
- In the tests, mocking core functions like `executable-find` and `shell-command-to-string` with `fset` can have surprising global side effects (especially under parallel test execution); consider using `cl-letf` or `letf` to temporarily rebind these functions in a more scoped way.
## Individual Comments
### Comment 1
<location> `cursor-agent.el:459-461` </location>
<code_context>
+ (with-current-buffer (get-buffer-create buffer-name)
+ (erase-buffer)
+ (insert "Test content")
+ (compilation-mode))
+ (should (buffer-live-p (get-buffer buffer-name)))
+ (should (eq major-mode 'compilation-mode)))
</code_context>
<issue_to_address>
**issue (bug_risk):** Using `compilation-mode` with `async-shell-command` likely won’t run `compilation-filter-hook`, so ANSI color handling may not work as expected.
Because `async-shell-command` installs `shell-command--command-output-filter` instead of `compilation-filter`, `compilation-filter-hook` is never run and ANSI escape sequences will not be processed. To ensure `compilation-mode`’s hooks (including ANSI handling) actually apply, consider using `compilation-start` instead of `async-shell-command`, or explicitly set the process filter to `compilation-filter`. The same pattern shows up in the status/models/MCP commands and likely needs a shared fix.
</issue_to_address>
### Comment 2
<location> `README.md:353` </location>
<code_context>
+M-x ert RET cursor-agent-test-.* RET
+```
+
+Or from command line:
+
+```bash
</code_context>
<issue_to_address>
**nitpick (typo):** Consider changing "from command line" to "from the command line" for grammatical correctness.
Rephrase this line to: `Or from the command line:` to improve grammar and readability.
```suggestion
Or from the command line:
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
- Add comprehensive ERT test suite for cursor-agent - Add testing section to README - Update .gitignore for test artifacts
- Add GitHub Actions workflow for Emacs testing - Support manual workflow triggering - Configure linting and compilation checks - Use purcell/setup-emacs and leotaku/elisp-check actions
- Factor out shared logic for list commands into helper function - Fix ANSI color handling by using compilation-filter - Add installation check for list commands - Improve error handling for list-sessions command
bdfe591 to
eaf9365
Compare
|
@sourcery-ai summary |
|
@sourcery-ai review |
|
@sourcery-ai title |
There was a problem hiding this comment.
Hey - I've found 3 issues, and left some high level feedback:
- For
cursor-agent-login, consider reusingcursor-agent--run-command-in-compilation-bufferto avoid duplicating the async command +compilation-filtersetup and keep behavior consistent with the other command entry points. - The switch of the list-style commands (
cursor-agent-list-sessions,cursor-agent-status,cursor-agent-list-models,cursor-agent-mcp-list) from synchronousshell-command-to-stringwithspecial-modeto asynchronouscompilation-modechanges both timing and buffer keybindings; it may be worth confirming this UX change is intentional or gating it behind a user option.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- For `cursor-agent-login`, consider reusing `cursor-agent--run-command-in-compilation-buffer` to avoid duplicating the async command + `compilation-filter` setup and keep behavior consistent with the other command entry points.
- The switch of the list-style commands (`cursor-agent-list-sessions`, `cursor-agent-status`, `cursor-agent-list-models`, `cursor-agent-mcp-list`) from synchronous `shell-command-to-string` with `special-mode` to asynchronous `compilation-mode` changes both timing and buffer keybindings; it may be worth confirming this UX change is intentional or gating it behind a user option.
## Individual Comments
### Comment 1
<location> `cursor-agent.el:132-141` </location>
<code_context>
+ (setq cursor-agent-authenticated-p nil)
+ nil))))
+
+(defun cursor-agent--run-command-in-compilation-buffer (command buffer-name header-text)
+ "Run COMMAND in a compilation buffer with proper ANSI color handling.
+COMMAND is the shell command to execute.
+BUFFER-NAME is the name of the buffer to use.
+HEADER-TEXT is the text to insert at the start of the buffer.
+Sets the process filter to compilation-filter to ensure ANSI colors are handled."
+ (let ((buffer (get-buffer-create buffer-name)))
+ (with-current-buffer buffer
+ (erase-buffer)
+ (when header-text
+ (insert header-text))
+ (compilation-mode))
+ ;; Use async-shell-command but set the filter to compilation-filter
+ ;; to ensure compilation-filter-hook runs, which handles ANSI color codes
+ (let ((process (async-shell-command command buffer-name)))
+ (when process
+ (set-process-filter process 'compilation-filter)))
</code_context>
<issue_to_address>
**suggestion:** Consider reusing this helper in `cursor-agent-login` to avoid duplicating process/filter setup logic.
The same process start + `compilation-mode` + `set-process-filter` sequence exists in `cursor-agent-login`. Calling `cursor-agent--run-command-in-compilation-buffer` from there (after any login-specific preamble) would centralize the async/ANSI handling and keep future behavior changes in one place.
Suggested implementation:
```
(defun cursor-agent-login ()
"Login to Cursor Agent."
(interactive)
(let* ((buffer-name "*Cursor Agent Login*")
(header-text (concat
"Cursor Agent Login\n\n"
"Follow the instructions in this buffer to log in.\n\n")))
(cursor-agent--run-command-in-compilation-buffer
"cursor-agent login"
buffer-name
header-text)))
```
1. If the actual implementation of `cursor-agent-login` differs from the SEARCH block above (e.g., different buffer name, different header text, extra checks like `cursor-agent-installed-p` or environment validation), adjust the replacement to preserve that existing behavior while delegating the process setup to `cursor-agent--run-command-in-compilation-buffer`.
2. Ensure that any login-specific preamble (such as additional `insert` calls, instructions, or state setup) is incorporated into the `header-text` argument before calling `cursor-agent--run-command-in-compilation-buffer`, or executed just before that call in the function body.
3. If `cursor-agent-login` previously used a different shell command (e.g., included flags or environment variables), update the `"cursor-agent login"` string accordingly to match the original command.
</issue_to_address>
### Comment 2
<location> `cursor-agent.el:151-160` </location>
<code_context>
+ (set-process-filter process 'compilation-filter)))
+ (pop-to-buffer buffer-name)))
+
+(defun cursor-agent--run-list-command (command buffer-name header-text)
+ "Helper function to run a list command with installation check.
+COMMAND is the shell command to execute.
+BUFFER-NAME is the name of the buffer to use.
+HEADER-TEXT is the text to insert at the start of the buffer.
+Checks if cursor-agent is installed before running the command."
+ (unless (cursor-agent-installed-p)
+ (if (y-or-n-p "Cursor Agent CLI not found. Would you like to install it now? ")
+ (cursor-agent-install)
+ (user-error "Cursor Agent CLI not found. Run 'M-x cursor-agent-install' to install")))
+ (cursor-agent--run-command-in-compilation-buffer
+ command
+ buffer-name
+ header-text))
(defun cursor-agent--local-bin-in-path-p ()
</code_context>
<issue_to_address>
**question:** Listing commands no longer put buffers into `special-mode`, which changes interaction semantics.
These commands now yield buffers in `compilation-mode` instead of `special-mode`, so they’ve lost the previous read-only/navigation/quit behavior. If ANSI handling is the main reason for this change, consider re-enabling a read-only mode (e.g. `special-mode`) after the process completes, or explicitly marking the buffer read-only, so the prior interaction model is preserved while still using `compilation-filter`.
</issue_to_address>
### Comment 3
<location> `cursor-agent.el:609` </location>
<code_context>
(view-mode)
(message "Press 'q' to quit view mode"))
- (user-error "README.md not found. Please ensure the package is properly installed"))))
+ (user-error "README.md not found. Please ensure the package is properly installed")))))
(provide 'cursor-agent)
</code_context>
<issue_to_address>
**issue (bug_risk):** There appears to be one extra closing parenthesis at the end of `cursor-agent-open-readme`.
This extra `)` will unbalance the surrounding forms and prevent the file from reading/byte-compiling. The closing parens here should match the previous version (remove one `)`).
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| (view-mode) | ||
| (message "Press 'q' to quit view mode")) | ||
| (user-error "README.md not found. Please ensure the package is properly installed")))) | ||
| (user-error "README.md not found. Please ensure the package is properly installed"))))) |
There was a problem hiding this comment.
issue (bug_risk): There appears to be one extra closing parenthesis at the end of cursor-agent-open-readme.
This extra ) will unbalance the surrounding forms and prevent the file from reading/byte-compiling. The closing parens here should match the previous version (remove one )).
- Add Doom Emacs / Straight subsection: autoload behavior (run cursor-agent-install once to expose all commands) and warning not to unload/reload in config (recursive load). - Use backtick quoting in docstrings: 'agent', 'agent models', 'text'/'json'/'stream-json'.
…talled, check-auth and login - cursor-agent-auto-install: nil/ask/auto/skip/once for install checks - cursor-agent-list-commands-use-special-mode: list buffers switch to special-mode after completion (default t) - cursor-agent--ensure-installed: central helper for install checks; commands (interactive, resume, login, shell-mode, update, run-list-command, verify-setup) use it - cursor-agent--run-command-in-compilation-buffer: optional use-special-mode, process sentinel to switch to special-mode and set read-only; robust handling of async-shell-command return (process vs window) - cursor-agent--run-list-command: pass use-special-mode to run-command - cursor-agent-install: y-or-n-p confirm before installing - cursor-agent-verify-setup: respect cursor-agent-auto-install and skip; fix (not installed) message branch - cursor-agent-check-auth: (interactive), messages for OK/WARNING/ERROR, match "Logged in" in status; (let* ...) - cursor-agent-login: use cursor-agent--run-command-in-compilation-buffer, sentinel to run cursor-agent-check-auth after login
…first) - Known issues: Doom/Straight commands unavailable until first use (run cursor-agent-install once); do not unload/reload in after! (recursive load) - Doom Method 2: use after! only for setq and keybindings; link to Known issues - Doom Method 3: :build (:not compile), do not unload/reload, run cursor-agent-install once with :local-repo - Doom Emacs Tips: after! only for setq/keybindings, not unload/load
- Added entry for the GitHub Actions local runner (/bin/act) to .gitignore - Retained existing rule to ignore all log files (*.log)
Summary by Sourcery
Add automated testing and CI for the cursor-agent Emacs package and refactor command execution helpers for better ANSI-aware output handling.
New Features:
Enhancements:
CI: