gptel-org: Move session save/restore code for Org
* gptel.el (gptel--restore-backend, gptel--save-state, gptel--restore-state): Move the Org-specific code for saving and restoring state to gptel-org. * gptel-org.el (gptel-org--entry-properties, gptel-org--save-state, gptel-org--restore-state): Org-specific code for saving and restoring state using Org properties, moved from gptel-org.
This commit is contained in:
parent
2982ede17d
commit
8dbcbbb908
2 changed files with 117 additions and 59 deletions
99
gptel-org.el
99
gptel-org.el
|
@ -161,7 +161,106 @@ value of `gptel-org-branching-context', which see."
|
||||||
;; Create prompt the usual way
|
;; Create prompt the usual way
|
||||||
(gptel--parse-buffer gptel-backend max-entries))))
|
(gptel--parse-buffer gptel-backend max-entries))))
|
||||||
|
|
||||||
|
|
||||||
|
;;; Saving and restoring state
|
||||||
|
(defun gptel-org--entry-properties (&optional pt)
|
||||||
|
"Find gptel configuration properties stored in the current heading."
|
||||||
|
(pcase-let
|
||||||
|
((`(,system ,backend ,model ,temperature ,tokens)
|
||||||
|
(mapcar
|
||||||
|
(lambda (prop) (org-entry-get (or pt (point)) prop 'selective))
|
||||||
|
'("GPTEL_SYSTEM" "GPTEL_BACKEND" "GPTEL_MODEL"
|
||||||
|
"GPTEL_TEMPERATURE" "GPTEL_MAX_TOKENS"))))
|
||||||
|
(when system
|
||||||
|
(setq system (string-replace "\\n" "\n" system)))
|
||||||
|
(when backend
|
||||||
|
(setq backend (alist-get backend gptel--known-backends
|
||||||
|
nil nil #'equal)))
|
||||||
|
(when temperature
|
||||||
|
(setq temperature (gptel--numberize temperature)))
|
||||||
|
(when tokens (setq tokens (gptel--numberize tokens)))
|
||||||
|
(list system backend model temperature tokens)))
|
||||||
|
|
||||||
|
;; (pcase-let ((`(,gptel--system-message ,gptel-backend
|
||||||
|
;; ,gptel-model ,gptel-temperature)
|
||||||
|
;; (if (derived-mode-p 'org-mode)
|
||||||
|
;; (progn (require 'gptel-org)
|
||||||
|
;; (gptel-org--entry-properties))
|
||||||
|
;; `(,gptel--system-message ,gptel-backend
|
||||||
|
;; ,gptel-model ,gptel-temperature)))))
|
||||||
|
|
||||||
|
(defun gptel-org--restore-state ()
|
||||||
|
"Restore gptel state for Org buffers when turning on `gptel-mode'."
|
||||||
|
(save-restriction
|
||||||
|
(widen)
|
||||||
|
(condition-case status
|
||||||
|
(progn
|
||||||
|
(when-let ((bounds (org-entry-get (point-min) "GPTEL_BOUNDS")))
|
||||||
|
(mapc (pcase-lambda (`(,beg . ,end))
|
||||||
|
(put-text-property beg end 'gptel 'response))
|
||||||
|
(read bounds)))
|
||||||
|
(pcase-let ((`(,system ,backend ,model ,temperature ,tokens)
|
||||||
|
(gptel-org--entry-properties (point-min))))
|
||||||
|
(when system (setq-local gptel--system-message system))
|
||||||
|
(if backend (setq-local gptel-backend backend)
|
||||||
|
(message
|
||||||
|
(substitute-command-keys
|
||||||
|
(concat
|
||||||
|
"Could not activate gptel backend \"%s\"! "
|
||||||
|
"Switch backends with \\[universal-argument] \\[gptel-send]"
|
||||||
|
" before using gptel."))
|
||||||
|
backend))
|
||||||
|
(when model (setq-local gptel-model model))
|
||||||
|
(when temperature (setq-local gptel-temperature temperature))
|
||||||
|
(when tokens (setq-local gptel-max-tokens tokens))))
|
||||||
|
(:success (message "gptel chat restored."))
|
||||||
|
(error (message "Could not restore gptel state, sorry! Error: %s" status)))))
|
||||||
|
|
||||||
|
(defun gptel-org-set-properties (pt &optional msg)
|
||||||
|
"Store the active gptel configuration under the current heading.
|
||||||
|
|
||||||
|
The active gptel configuration includes the current system
|
||||||
|
message, language model and provider (backend), and additional
|
||||||
|
settings when applicable.
|
||||||
|
|
||||||
|
PT is the cursor position by default. If MSG is
|
||||||
|
non-nil (default), display a message afterwards."
|
||||||
|
(interactive (list (point) t))
|
||||||
|
(org-entry-put pt "GPTEL_MODEL" gptel-model)
|
||||||
|
(org-entry-put pt "GPTEL_BACKEND" (gptel-backend-name gptel-backend))
|
||||||
|
(unless (equal (default-value 'gptel-temperature) gptel-temperature)
|
||||||
|
(org-entry-put pt "GPTEL_TEMPERATURE"
|
||||||
|
(number-to-string gptel-temperature)))
|
||||||
|
(unless (string= (default-value 'gptel--system-message)
|
||||||
|
gptel--system-message)
|
||||||
|
(org-entry-put pt "GPTEL_SYSTEM"
|
||||||
|
(string-replace "\n" "\\n" gptel--system-message)))
|
||||||
|
(when gptel-max-tokens
|
||||||
|
(org-entry-put
|
||||||
|
pt "GPTEL_MAX_TOKENS" (number-to-string gptel-max-tokens)))
|
||||||
|
(when msg
|
||||||
|
(message "Added gptel configuration to current headline.")))
|
||||||
|
|
||||||
|
(defun gptel-org--save-state ()
|
||||||
|
"Write the gptel state to the Org buffer as Org properties."
|
||||||
|
(org-with-wide-buffer
|
||||||
|
(goto-char (point-min))
|
||||||
|
(when (org-at-heading-p)
|
||||||
|
(org-open-line 1))
|
||||||
|
(gptel-org-set-properties (point-min))
|
||||||
|
;; Save response boundaries
|
||||||
|
(letrec ((write-bounds
|
||||||
|
(lambda (attempts)
|
||||||
|
(let* ((bounds (gptel--get-buffer-bounds))
|
||||||
|
(offset (caar bounds))
|
||||||
|
(offset-marker (set-marker (make-marker) offset)))
|
||||||
|
(org-entry-put (point-min) "GPTEL_BOUNDS"
|
||||||
|
(prin1-to-string (gptel--get-buffer-bounds)))
|
||||||
|
(when (and (not (= (marker-position offset-marker) offset))
|
||||||
|
(> attempts 0))
|
||||||
|
(funcall write-bounds (1- attempts)))))))
|
||||||
|
(funcall write-bounds 6))))
|
||||||
|
|
||||||
|
|
||||||
(provide 'gptel-org)
|
(provide 'gptel-org)
|
||||||
;;; gptel-org.el ends here
|
;;; gptel-org.el ends here
|
||||||
|
|
77
gptel.el
77
gptel.el
|
@ -652,48 +652,33 @@ Valid JSON unless NO-JSON is t."
|
||||||
|
|
||||||
;; Saving and restoring state
|
;; Saving and restoring state
|
||||||
|
|
||||||
(defun gptel--restore-backend (name)
|
(declare-function gptel-org--restore-state "gptel-org")
|
||||||
"Activate gptel backend with NAME in current buffer.
|
(declare-function gptel-org--save-state "gptel-org")
|
||||||
|
|
||||||
If no backend with this name exists, inform the user. Intended
|
|
||||||
for when gptel restores chat metadata."
|
|
||||||
(when name
|
|
||||||
(if-let ((backend (alist-get name gptel--known-backends
|
|
||||||
nil nil #'equal)))
|
|
||||||
(setq-local gptel-backend backend)
|
|
||||||
(message
|
|
||||||
(substitute-command-keys
|
|
||||||
"Could not activate gptel backend \"%s\"! Switch backends with \\[universal-argument] \\[gptel-send] before using gptel.")
|
|
||||||
name))))
|
|
||||||
|
|
||||||
(defun gptel--restore-state ()
|
(defun gptel--restore-state ()
|
||||||
"Restore gptel state when turning on `gptel-mode'."
|
"Restore gptel state when turning on `gptel-mode'."
|
||||||
(when (buffer-file-name)
|
(when (buffer-file-name)
|
||||||
(pcase major-mode
|
(pcase major-mode
|
||||||
('org-mode
|
('org-mode
|
||||||
(save-restriction
|
(require 'gptel-org)
|
||||||
(widen)
|
(gptel-org--restore-state))
|
||||||
(condition-case-unless-debug nil
|
|
||||||
(progn
|
|
||||||
(when-let ((bounds (org-entry-get (point-min) "GPTEL_BOUNDS")))
|
|
||||||
(mapc (pcase-lambda (`(,beg . ,end))
|
|
||||||
(put-text-property beg end 'gptel 'response))
|
|
||||||
(read bounds))
|
|
||||||
(message "gptel chat restored."))
|
|
||||||
(when-let ((model (org-entry-get (point-min) "GPTEL_MODEL")))
|
|
||||||
(setq-local gptel-model model))
|
|
||||||
(gptel--restore-backend (org-entry-get (point-min) "GPTEL_BACKEND"))
|
|
||||||
(when-let ((system (org-entry-get (point-min) "GPTEL_SYSTEM")))
|
|
||||||
(setq-local gptel--system-message (string-replace "\\n" "\n" system)))
|
|
||||||
(when-let ((temp (org-entry-get (point-min) "GPTEL_TEMPERATURE")))
|
|
||||||
(setq-local gptel-temperature (gptel--numberize temp))))
|
|
||||||
(error (message "Could not restore gptel state, sorry!")))))
|
|
||||||
(_ (when gptel--bounds
|
(_ (when gptel--bounds
|
||||||
(mapc (pcase-lambda (`(,beg . ,end))
|
(mapc (pcase-lambda (`(,beg . ,end))
|
||||||
(put-text-property beg end 'gptel 'response))
|
(put-text-property beg end 'gptel 'response))
|
||||||
gptel--bounds)
|
gptel--bounds)
|
||||||
(message "gptel chat restored."))
|
(message "gptel chat restored."))
|
||||||
(gptel--restore-backend gptel--backend-name)))))
|
(when gptel--backend-name
|
||||||
|
(if-let ((backend (alist-get
|
||||||
|
gptel--backend-name gptel--known-backends
|
||||||
|
nil nil #'equal)))
|
||||||
|
(setq-local gptel-backend backend)
|
||||||
|
(message
|
||||||
|
(substitute-command-keys
|
||||||
|
(concat
|
||||||
|
"Could not activate gptel backend \"%s\"! "
|
||||||
|
"Switch backends with \\[universal-argument] \\[gptel-send]"
|
||||||
|
" before using gptel."))
|
||||||
|
gptel--backend-name)))))))
|
||||||
|
|
||||||
(defun gptel--save-state ()
|
(defun gptel--save-state ()
|
||||||
"Write the gptel state to the buffer.
|
"Write the gptel state to the buffer.
|
||||||
|
@ -703,34 +688,8 @@ restore a chat session, turn on `gptel-mode' after opening the
|
||||||
file."
|
file."
|
||||||
(pcase major-mode
|
(pcase major-mode
|
||||||
('org-mode
|
('org-mode
|
||||||
(org-with-wide-buffer
|
(require 'gptel-org)
|
||||||
(goto-char (point-min))
|
(gptel-org--save-state))
|
||||||
(when (org-at-heading-p)
|
|
||||||
(org-open-line 1))
|
|
||||||
(org-entry-put (point-min) "GPTEL_MODEL" gptel-model)
|
|
||||||
(org-entry-put (point-min) "GPTEL_BACKEND" (gptel-backend-name gptel-backend))
|
|
||||||
(unless (equal (default-value 'gptel-temperature) gptel-temperature)
|
|
||||||
(org-entry-put (point-min) "GPTEL_TEMPERATURE"
|
|
||||||
(number-to-string gptel-temperature)))
|
|
||||||
(unless (string= (default-value 'gptel--system-message)
|
|
||||||
gptel--system-message)
|
|
||||||
(org-entry-put (point-min) "GPTEL_SYSTEM"
|
|
||||||
(string-replace "\n" "\\n" gptel--system-message)))
|
|
||||||
(when gptel-max-tokens
|
|
||||||
(org-entry-put
|
|
||||||
(point-min) "GPTEL_MAX_TOKENS" gptel-max-tokens))
|
|
||||||
;; Save response boundaries
|
|
||||||
(letrec ((write-bounds
|
|
||||||
(lambda (attempts)
|
|
||||||
(let* ((bounds (gptel--get-buffer-bounds))
|
|
||||||
(offset (caar bounds))
|
|
||||||
(offset-marker (set-marker (make-marker) offset)))
|
|
||||||
(org-entry-put (point-min) "GPTEL_BOUNDS"
|
|
||||||
(prin1-to-string (gptel--get-buffer-bounds)))
|
|
||||||
(when (and (not (= (marker-position offset-marker) offset))
|
|
||||||
(> attempts 0))
|
|
||||||
(funcall write-bounds (1- attempts)))))))
|
|
||||||
(funcall write-bounds 6))))
|
|
||||||
(_ (let ((print-escape-newlines t))
|
(_ (let ((print-escape-newlines t))
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(save-restriction
|
(save-restriction
|
||||||
|
|
Loading…
Add table
Reference in a new issue