Skip to content

Commit 435558c

Browse files
authored
Include editor context in issue and PR prompts (#410)
1 parent d966e42 commit 435558c

2 files changed

Lines changed: 96 additions & 20 deletions

File tree

ai-code-github.el

Lines changed: 64 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
(require 'magit)
1212
(require 'ai-code-input)
1313
(require 'ai-code-prompt-mode)
14+
(require 'which-func nil t)
15+
1416

1517
(declare-function ai-code-read-string "ai-code-input")
1618
(declare-function ai-code--insert-prompt "ai-code-prompt-mode" (prompt-text))
@@ -24,6 +26,11 @@
2426
(declare-function ai-code--generate-branch-or-commit-diff "ai-code-git" (diff-params diff-file))
2527
(declare-function ai-code--open-diff-file "ai-code-git" (diff-file))
2628
(declare-function ai-code--explain-code-change "ai-code-discussion" (&optional review-source))
29+
(declare-function ai-code--get-context-files-string "ai-code-utils" ())
30+
(declare-function ai-code--format-repo-context-info "ai-code-utils" ())
31+
(declare-function ai-code--get-region-location-info "ai-code-discussion" (region-beginning region-end))
32+
(declare-function which-function "which-func" ())
33+
2734

2835
(defcustom ai-code-default-review-source nil
2936
"Default review source for pull request and issue analysis.
@@ -167,11 +174,13 @@ Feedback Check Steps:
167174
4. No need to make code change. Provide analysis only."
168175
pr-url source-instruction)))
169176

170-
(defun ai-code--build-issue-investigation-init-prompt (review-source issue-url)
171-
"Build issue investigation prompt for REVIEW-SOURCE with ISSUE-URL."
172-
(let ((source-instruction
173-
(ai-code--pull-or-review-source-instruction review-source 'investigate-issue)))
174-
(format "Investigate issue: %s
177+
(defun ai-code--build-issue-investigation-init-prompt (review-source issue-url &optional include-context)
178+
"Build issue investigation prompt for REVIEW-SOURCE with ISSUE-URL.
179+
If INCLUDE-CONTEXT is non-nil, append current editor context to the prompt."
180+
(let* ((source-instruction
181+
(ai-code--pull-or-review-source-instruction review-source 'investigate-issue))
182+
(prompt
183+
(format "Investigate issue: %s
175184
176185
%s
177186
@@ -180,7 +189,37 @@ Issue Investigation Steps:
180189
2. Analyze relevant code in this repository as context and identify likely root causes.
181190
3. Provide concrete insights on how to fix it, including likely files or areas to change.
182191
4. No need to make code change. Provide analysis only."
183-
issue-url source-instruction)))
192+
issue-url source-instruction)))
193+
(if (and include-context (or buffer-file-name (use-region-p)))
194+
(let* ((region-text (when (use-region-p)
195+
(buffer-substring-no-properties (region-beginning) (region-end))))
196+
(region-location-info (when region-text
197+
(ai-code--get-region-location-info
198+
(region-beginning)
199+
(region-end))))
200+
(function-name (which-function))
201+
(files-context-string (ai-code--get-context-files-string))
202+
(repo-context-string (ai-code--format-repo-context-info))
203+
(context-blocks nil))
204+
(push (if buffer-file-name
205+
(format "Current file: %s" buffer-file-name)
206+
(format "Current buffer: %s" (buffer-name)))
207+
context-blocks)
208+
(when function-name
209+
(push (format "Function: %s" function-name) context-blocks))
210+
(when region-text
211+
(push (concat "Selected region:\n"
212+
(when region-location-info
213+
(concat region-location-info "\n"))
214+
region-text)
215+
context-blocks))
216+
(when (and files-context-string (not (string-empty-p files-context-string)))
217+
(push files-context-string context-blocks))
218+
(when (and repo-context-string (not (string-empty-p repo-context-string)))
219+
(push repo-context-string context-blocks))
220+
(concat prompt "\n\nLocal Context:\n"
221+
(mapconcat #'identity (nreverse context-blocks) "\n\n")))
222+
prompt)))
184223

185224
(defun ai-code--build-pr-description-init-prompt (review-source pr-url)
186225
"Build PR description prompt for REVIEW-SOURCE with PR-URL."
@@ -285,11 +324,12 @@ Signal a helpful error when difftastic is unavailable."
285324
"Create the pull request using the backend's PR creation capability. "
286325
"Do not treat this as a PR review flow before the PR exists."))))
287326

288-
(defun ai-code--build-pr-init-prompt (review-source target-url review-mode)
289-
"Build initial prompt for REVIEW-SOURCE, TARGET-URL and REVIEW-MODE."
327+
(defun ai-code--build-pr-init-prompt (review-source target-url review-mode &optional include-context)
328+
"Build initial prompt for REVIEW-SOURCE, TARGET-URL and REVIEW-MODE.
329+
If INCLUDE-CONTEXT is non-nil, append current editor context to the prompt."
290330
(pcase review-mode
291331
('investigate-issue
292-
(ai-code--build-issue-investigation-init-prompt review-source target-url))
332+
(ai-code--build-issue-investigation-init-prompt review-source target-url include-context))
293333
('check-feedback
294334
(ai-code--build-pr-feedback-check-init-prompt review-source target-url))
295335
('review-ci-checks
@@ -301,8 +341,9 @@ Signal a helpful error when difftastic is unavailable."
301341
(_
302342
(ai-code--build-pr-review-init-prompt review-source target-url))))
303343

304-
(defun ai-code--pull-or-review-pr-with-source (review-source)
305-
"Prompt for a mode and send a prompt for REVIEW-SOURCE to AI."
344+
(defun ai-code--pull-or-review-pr-with-source (review-source &optional arg)
345+
"Prompt for a mode and send a prompt for REVIEW-SOURCE to AI.
346+
ARG is the optional prefix argument to force including context."
306347
(require 'ai-code-git nil t)
307348
(let* ((review-mode (ai-code--pull-or-review-pr-mode-choice)))
308349
(cond
@@ -337,8 +378,13 @@ Signal a helpful error when difftastic is unavailable."
337378
review-source current-branch target-branch pr-title)))
338379
(let* ((url-prompt (ai-code--pull-or-review-url-prompt review-mode))
339380
(region-url (ai-code--extract-url-from-region))
340-
(target-url (ai-code-read-string url-prompt region-url)))
341-
(ai-code--build-pr-init-prompt review-source target-url review-mode))))
381+
(target-url (ai-code-read-string url-prompt region-url))
382+
(has-context (or buffer-file-name (use-region-p)))
383+
(include-context (and (eq review-mode 'investigate-issue)
384+
has-context
385+
(or arg
386+
(y-or-n-p "Include active buffer and editor context? ")))))
387+
(ai-code--build-pr-init-prompt review-source target-url review-mode include-context))))
342388
(prompt-label (if (eq review-mode 'send-current-branch-pr)
343389
"Enter PR creation prompt: "
344390
"Enter review prompt: ")))
@@ -384,11 +430,12 @@ Works with GitHub, GitLab, Bitbucket, and other Git hosting services."
384430
(message "Opened web commit: %s" commit-url))
385431
(message "Unable to determine repository web URL"))))
386432

387-
(defun ai-code-pull-or-review-diff-file ()
433+
(defun ai-code-pull-or-review-diff-file (&optional arg)
388434
"Review a diff file with AI Code or choose a PR review workflow.
389435
If current buffer is a .diff file, ask AI Code to review it.
390-
Otherwise, prompt for a review source and analysis mode."
391-
(interactive)
436+
Otherwise, prompt for a review source and analysis mode.
437+
ARG is the optional prefix argument to force including context."
438+
(interactive "P")
392439
(if (and buffer-file-name (string-match-p "\\.diff$" buffer-file-name))
393440
(let* ((file-name (file-name-nondirectory buffer-file-name))
394441
(init-prompt (format "Code review for %s. Use relevant file in repository as context.
@@ -406,7 +453,7 @@ Provide overall assessment.
406453
(unless ai-code-default-review-source
407454
(ai-code--message-review-source-config-hint))
408455
(let ((review-source (ai-code--pull-or-review-action-choice)))
409-
(ai-code--pull-or-review-pr-with-source review-source))))
456+
(ai-code--pull-or-review-pr-with-source review-source arg))))
410457

411458
(provide 'ai-code-github)
412459

test/test_ai-code-github.el

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Return (CAPTURED-PROMPT DIFF-CALLED)."
3030
(setq completing-read-results (cdr completing-read-results))
3131
selected)))
3232
((symbol-function 'ai-code-read-string)
33-
(lambda (prompt &optional initial-input _candidate-list)
33+
(lambda (prompt &optional initial-input &rest _args)
3434
(if (string-match-p "URL:" prompt)
3535
pr-url
3636
initial-input)))
@@ -94,7 +94,7 @@ Return (CAPTURED-PROMPT DIFF-CALLED)."
9494
((symbol-function 'ai-code--pull-or-review-action-choice)
9595
(lambda () 'github-mcp))
9696
((symbol-function 'ai-code--pull-or-review-pr-with-source)
97-
(lambda (_review-source)
97+
(lambda (_review-source &rest _args)
9898
nil)))
9999
(with-temp-buffer
100100
(ai-code-pull-or-review-diff-file))
@@ -108,7 +108,7 @@ Return (CAPTURED-PROMPT DIFF-CALLED)."
108108
(lambda (&rest _args)
109109
(setq message-called t)))
110110
((symbol-function 'ai-code--pull-or-review-pr-with-source)
111-
(lambda (_review-source)
111+
(lambda (_review-source &rest _args)
112112
nil)))
113113
(with-temp-buffer
114114
(ai-code-pull-or-review-diff-file))
@@ -421,6 +421,35 @@ Return (CAPTURED-PROMPT DIFF-CALLED)."
421421
(should (string-match-p "conflict" (downcase captured-prompt)))
422422
(should-not diff-called)))
423423

424+
(ert-deftest ai-code-test-pull-or-review-diff-file-investigate-issue-with-context ()
425+
"Test that investigate issue mode can include current file context when y-or-n-p is true."
426+
(let* ((captured-prompt nil)
427+
(completing-read-results '("Use GitHub MCP server" "Investigate issue")))
428+
(with-temp-buffer
429+
(setq buffer-file-name "/path/to/my-source-file.el")
430+
(insert "defun hello-world ()")
431+
(cl-letf (((symbol-function 'completing-read)
432+
(lambda (&rest _args)
433+
(let ((selected (car completing-read-results)))
434+
(setq completing-read-results (cdr completing-read-results))
435+
selected)))
436+
((symbol-function 'ai-code-read-string)
437+
(lambda (prompt &optional initial-input &rest _args)
438+
(if (string-match-p "URL:" prompt)
439+
"https://github.com/acme/demo/issues/42"
440+
initial-input)))
441+
((symbol-function 'ai-code--insert-prompt)
442+
(lambda (prompt) (setq captured-prompt prompt)))
443+
((symbol-function 'y-or-n-p)
444+
(lambda (prompt)
445+
(should (string-match-p "Include active buffer and editor context" prompt))
446+
t))
447+
((symbol-function 'ai-code--git-root) (lambda () "/path/to/")))
448+
(ai-code-pull-or-review-diff-file)))
449+
(should (string-match-p "Investigate issue: https://github.com/acme/demo/issues/42" captured-prompt))
450+
(should (string-match-p "Local Context:" captured-prompt))
451+
(should (string-match-p "Current file: /path/to/my-source-file.el" captured-prompt))))
452+
424453
(provide 'test_ai-code-github)
425454

426455
;;; test_ai-code-github.el ends here

0 commit comments

Comments
 (0)