Skip to content

Commit cc41e33

Browse files
Copilottninja
andauthored
Support resuming AI sessions from a selected UUID (#332)
* Initial plan * Support UUID region for resume args Agent-Logs-Url: https://github.com/tninja/ai-code-interface.el/sessions/a9aabab7-19c7-4e4e-892c-1f1e4a4d8cff Co-authored-by: tninja <714625+tninja@users.noreply.github.com> * Polish resume UUID detection tests Agent-Logs-Url: https://github.com/tninja/ai-code-interface.el/sessions/a9aabab7-19c7-4e4e-892c-1f1e4a4d8cff Co-authored-by: tninja <714625+tninja@users.noreply.github.com> * Refine resume UUID test names Agent-Logs-Url: https://github.com/tninja/ai-code-interface.el/sessions/a9aabab7-19c7-4e4e-892c-1f1e4a4d8cff Co-authored-by: tninja <714625+tninja@users.noreply.github.com> * Clarify resume UUID matching logic Agent-Logs-Url: https://github.com/tninja/ai-code-interface.el/sessions/a9aabab7-19c7-4e4e-892c-1f1e4a4d8cff Co-authored-by: tninja <714625+tninja@users.noreply.github.com> * Format resume arg resolution cleanly Agent-Logs-Url: https://github.com/tninja/ai-code-interface.el/sessions/a9aabab7-19c7-4e4e-892c-1f1e4a4d8cff Co-authored-by: tninja <714625+tninja@users.noreply.github.com> * Finalize resume UUID prompt support Agent-Logs-Url: https://github.com/tninja/ai-code-interface.el/sessions/a9aabab7-19c7-4e4e-892c-1f1e4a4d8cff Co-authored-by: tninja <714625+tninja@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: tninja <714625+tninja@users.noreply.github.com>
1 parent 6291f36 commit cc41e33

2 files changed

Lines changed: 112 additions & 5 deletions

File tree

ai-code-backends-infra.el

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
(require 'cl-lib)
1919
(require 'project)
20+
(require 'subr-x)
2021
(require 'ai-code-session-link)
2122
;; Terminal-specific implementations live in dedicated modules so this
2223
;; file can stay focused on shared session orchestration.
@@ -145,6 +146,22 @@ being sent for the response completion.")
145146
(defvar ai-code-cli-args-history nil
146147
"History list for CLI args prompts.")
147148

149+
(defconst ai-code-backends-infra--uuid-regexp
150+
"[[:xdigit:]]\\{8\\}-[[:xdigit:]]\\{4\\}-[[:xdigit:]]\\{4\\}-[[:xdigit:]]\\{4\\}-[[:xdigit:]]\\{12\\}"
151+
"Regexp matching the general UUID 8-4-4-4-12 text structure.
152+
This validates the textual shape, but not UUID version or variant bits.")
153+
154+
(defun ai-code-backends-infra--selected-session-id ()
155+
"Return the active region text when it contains a UUID session id."
156+
(when (use-region-p)
157+
(let ((candidate
158+
(string-trim
159+
(buffer-substring-no-properties (region-beginning) (region-end)))))
160+
(when (string-match-p
161+
(concat "\\`" ai-code-backends-infra--uuid-regexp "\\'")
162+
candidate)
163+
candidate))))
164+
148165
(defcustom ai-code-backends-infra-idle-delay 5.0
149166
"Delay in seconds of inactivity before considering response complete.
150167
After this period of terminal inactivity, a notification may be sent
@@ -854,12 +871,27 @@ If FORCE-PROMPT is nil and there are no existing instances, return \"default\"."
854871
(defun ai-code-backends-infra--resolve-start-command (program switches arg &optional prompt-label)
855872
"Build command string for PROGRAM and SWITCHES.
856873
When ARG is non-nil, prompt for CLI args using SWITCHES as default input.
857-
PROMPT-LABEL is used in the minibuffer prompt."
858-
(let* ((default-args (mapconcat #'identity switches " "))
874+
PROMPT-LABEL is used in the minibuffer prompt.
875+
When resuming and the active region contains a UUID, prompt as though ARG
876+
were non-nil and append that UUID to the default CLI args."
877+
(let* ((found-resume-switch
878+
(cl-some (lambda (switch)
879+
(member switch '("resume" "--resume")))
880+
switches))
881+
(selected-session-id
882+
(and (null arg)
883+
found-resume-switch
884+
(ai-code-backends-infra--selected-session-id)))
885+
(prompt-p (or arg selected-session-id))
886+
(default-args (mapconcat #'identity
887+
(append switches
888+
(and selected-session-id
889+
(list selected-session-id)))
890+
" "))
859891
(prompt (format "%s args: " (or prompt-label "CLI")))
860-
(prompt-args (when arg
861-
(read-string prompt default-args 'ai-code-cli-args-history)))
862-
(resolved-args (if arg
892+
(prompt-args (when prompt-p
893+
(read-string prompt default-args 'ai-code-cli-args-history)))
894+
(resolved-args (if prompt-p
863895
(split-string-shell-command prompt-args)
864896
switches))
865897
(command (mapconcat #'identity

test/test_ai-code-backends-infra.el

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
(defvar ghostel--copy-mode-active)
2222
(defvar ghostel--process)
2323

24+
(defconst test-ai-code-backends-infra-valid-uuid
25+
"123e4567-e89b-12d3-a456-426614174000"
26+
"UUID fixture used by resume command resolution tests.")
27+
2428
(ert-deftest test-ai-code-backends-infra-output-meaningful-p-noise ()
2529
"Ensure terminal noise is not considered meaningful output."
2630
(should-not (ai-code-backends-infra--output-meaningful-p nil))
@@ -63,6 +67,77 @@
6367
(should (re-search-forward
6468
"^(defcustom ai-code-backends-infra-eat-preserve-position\\_>" nil t))))
6569

70+
(ert-deftest test-ai-code-backends-infra--resume-double-dash-prefills-uuid ()
71+
"A selected UUID should make `--resume' prompt with that id appended."
72+
(let ((uuid test-ai-code-backends-infra-valid-uuid)
73+
seen-prompt
74+
seen-initial
75+
seen-history
76+
result)
77+
(with-temp-buffer
78+
(transient-mark-mode 1)
79+
(insert uuid)
80+
(goto-char (point-min))
81+
(set-mark (point))
82+
(goto-char (point-max))
83+
(activate-mark)
84+
(cl-letf (((symbol-function 'read-string)
85+
(lambda (prompt &optional initial-input history &rest _args)
86+
(setq seen-prompt prompt
87+
seen-initial initial-input
88+
seen-history history)
89+
initial-input)))
90+
(setq result
91+
(ai-code-backends-infra--resolve-start-command
92+
"claude" '("--resume") nil "Claude"))))
93+
(should (equal seen-prompt "Claude args: "))
94+
(should (equal seen-initial (format "--resume %s" uuid)))
95+
(should (eq seen-history 'ai-code-cli-args-history))
96+
(should (equal (plist-get result :args) `("--resume" ,uuid)))
97+
(should (equal (plist-get result :command)
98+
(format "claude --resume %s" uuid)))))
99+
100+
(ert-deftest test-ai-code-backends-infra--resume-subcommand-prefills-uuid ()
101+
"A selected UUID should make `resume' prompt with that id appended."
102+
(let ((uuid test-ai-code-backends-infra-valid-uuid)
103+
seen-initial
104+
result)
105+
(with-temp-buffer
106+
(transient-mark-mode 1)
107+
(insert uuid)
108+
(goto-char (point-min))
109+
(set-mark (point))
110+
(goto-char (point-max))
111+
(activate-mark)
112+
(cl-letf (((symbol-function 'read-string)
113+
(lambda (_prompt &optional initial-input _history &rest _args)
114+
(setq seen-initial initial-input)
115+
initial-input)))
116+
(setq result
117+
(ai-code-backends-infra--resolve-start-command
118+
"codex" '("resume") nil "Codex"))))
119+
(should (equal seen-initial (format "resume %s" uuid)))
120+
(should (equal (plist-get result :args) `("resume" ,uuid)))
121+
(should (equal (plist-get result :command)
122+
(format "codex resume %s" uuid)))))
123+
124+
(ert-deftest test-ai-code-backends-infra--resume-ignores-non-uuid ()
125+
"A non-UUID region should not trigger resume prompting."
126+
(with-temp-buffer
127+
(transient-mark-mode 1)
128+
(insert "not-a-session-id")
129+
(goto-char (point-min))
130+
(set-mark (point))
131+
(goto-char (point-max))
132+
(activate-mark)
133+
(cl-letf (((symbol-function 'read-string)
134+
(lambda (&rest _args)
135+
(ert-fail "non-UUID selection should not prompt"))))
136+
(let ((result (ai-code-backends-infra--resolve-start-command
137+
"claude" '("--resume") nil "Claude")))
138+
(should (equal (plist-get result :args) '("--resume")))
139+
(should (equal (plist-get result :command) "claude --resume"))))))
140+
66141
(ert-deftest test-ai-code-backends-infra-buffer-user-visible-p ()
67142
"Return non-nil only when buffer has a visible window."
68143
(with-temp-buffer

0 commit comments

Comments
 (0)