;;; ... -*- lexical-binding: t -*- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; AI support ;;; ;;; Sets up LLM assistants (use-package aidermacs :bind (("C-c a" . drkp/aidermacs-transient-here)) :custom (aidermacs-program "~/scripts/aider-wrapper") (aidermacs-backend 'vterm) ;; Multiline input: Shift-RET inserts a newline; RET sends (both backends) (aidermacs-comint-multiline-newline-key "S-") (aidermacs-vterm-multiline-newline-key "S-") (aidermacs-show-diff-after-change nil) ;TODO: skip only on tramp (aidermacs-auto-commits nil) :init ;; 1) Choose backend at spawn time (no lexical let-binding!) (add-hook 'aidermacs-before-run-backend-hook (lambda () (setq aidermacs-backend (if (file-remote-p default-directory) 'comint 'vterm)))) ;; 2) Helpers to find the session and wait until it's ready (defun drkp/aidermacs--session-buffer () (when (fboundp 'aidermacs-get-buffer-name) (get-buffer (aidermacs-get-buffer-name)))) (defun drkp/aidermacs--session-live-p () (when-let* ((buf (drkp/aidermacs--session-buffer)) (proc (get-buffer-process buf))) (and (buffer-live-p buf) (process-live-p proc)))) (defun drkp/aidermacs--wait-ready (&optional timeout) (let ((deadline (+ (float-time) (or timeout 3.0)))) (while (and (not (drkp/aidermacs--session-live-p)) (< (float-time) deadline)) (sleep-for 0.05))) (drkp/aidermacs--session-live-p)) ;; 3) Start a session if needed, but DO NOT change current buffer/window (defun drkp/aidermacs--ensure-session () (unless (drkp/aidermacs--session-live-p) (cond ((fboundp 'aidermacs-run) (call-interactively #'aidermacs-run)) ((fboundp 'aidermacs-run-in-current-dir) (call-interactively #'aidermacs-run-in-current-dir)) (t (user-error "No Aidermacs start command found")))) (drkp/aidermacs--wait-ready 3.0)) ;; 4) Make all “send” paths run from the session buffer, so output goes to it (dolist (fn '(aidermacs-send-text aidermacs-send-command aidermacs--send-command)) (when (fboundp fn) (advice-add fn :around (lambda (orig &rest args) (if-let ((buf (drkp/aidermacs--session-buffer))) (with-current-buffer buf (apply orig args)) (apply orig args)))))) ;; 5) Entry point: ensure session, keep focus HERE, then open the transient (defun drkp/aidermacs-transient-here () "Ensure Aidermacs session exists, then pop the transient from the current buffer. Keeps point/region here so context actions (c/e) use THIS buffer’s region." (interactive) (drkp/aidermacs--ensure-session) (call-interactively #'aidermacs-transient-menu)) (defun drkp:setenv-openai-apikey () (setenv "OPENAI_API_KEY" (if-let* ((secret (plist-get (car (auth-source-search :host "api.openai.com" :user "apikey" :require '(:secret))) :secret))) (if (functionp secret) (encode-coding-string (funcall secret) 'utf-8) secret) (user-error "No `gptel-api-key' found in the auth source")))) (add-hook 'aidermacs-before-run-backend-hook #'drkp:setenv-openai-apikey)) (use-package gptel)