|
56 | 56 | This is used in gptel context buffers." |
57 | 57 | :group 'gptel) |
58 | 58 |
|
59 | | -(defcustom gptel-context-wrap-function #'gptel-context--wrap-default |
60 | | - "Function to format the context string sent with the gptel request. |
| 59 | +(defvar gptel-context-wrap-function nil |
| 60 | + "Function to format the context string sent with the gptel request.") |
| 61 | +(make-obsolete-variable |
| 62 | + 'gptel-context-wrap-function |
| 63 | + "Custom functions for wrapping context are no longer supported by gptel.\ |
| 64 | + See `gptel-context--wrap-in-buffer' for details." |
| 65 | + "0.9.9") |
61 | 66 |
|
62 | | -This function receives two argument, the message to wrap with the |
63 | | -context, and an alist of contexts organized by buffer. It should |
64 | | -return a string containing the message and the context, formatted as |
65 | | -necessary. |
| 67 | +(defcustom gptel-context-string-function #'gptel-context--string |
| 68 | + "Function to prepare the context string sent with the gptel request. |
66 | 69 |
|
67 | | -The message is either the system message or the last user prompt, |
68 | | -as configured by `gptel-use-context'. |
| 70 | +This function can be synchronous or asynchronous, and receives one or |
| 71 | +two arguments respectively. |
69 | 72 |
|
70 | | -The alist of contexts is structured as follows: |
| 73 | +Synchronous: An alist of contexts with buffers or files (the context |
| 74 | +alist). |
| 75 | +Asynchronous: A callback to call with the result, and the context alist. |
| 76 | +
|
| 77 | +The context alist is structured as follows: |
71 | 78 |
|
72 | 79 | ((buffer1 . (overlay1 overlay2) |
73 | 80 | (\"path/to/file\") |
@@ -301,25 +308,57 @@ ADVANCE controls the overlay boundary behavior." |
301 | 308 | overlay)) |
302 | 309 |
|
303 | 310 | ;;;###autoload |
304 | | -(defun gptel-context--wrap (message) |
305 | | - "Wrap MESSAGE with context string." |
306 | | - (funcall gptel-context-wrap-function |
307 | | - message (gptel-context--collect))) |
308 | | - |
309 | | -(defun gptel-context--wrap-default (message contexts) |
310 | | - "Add CONTEXTS to MESSAGE. |
311 | | -
|
312 | | -MESSAGE is usually either the system message or the user prompt. |
313 | | -The accumulated context from CONTEXTS is appended or prepended to |
314 | | -it, respectively." |
315 | | - ;; Append context before/after system message. |
316 | | - (let ((context-string (gptel-context--string contexts))) |
317 | | - (if (> (length context-string) 0) |
318 | | - (pcase-exhaustive gptel-use-context |
319 | | - ('system (concat message "\n\n" context-string)) |
320 | | - ('user (concat context-string "\n\n" message)) |
321 | | - ('nil message)) |
322 | | - message))) |
| 311 | +(defun gptel-context--wrap (callback data-buf) |
| 312 | + "Add request context to DATA-BUF and run CALLBACK. |
| 313 | +
|
| 314 | +DATA-BUF is the buffer where the request prompt is constructed." |
| 315 | + (if (= (car (func-arity gptel-context-string-function)) 2) |
| 316 | + (funcall gptel-context-string-function |
| 317 | + (lambda (c) (with-current-buffer data-buf |
| 318 | + (gptel-context--wrap-in-buffer c)) |
| 319 | + (funcall callback)) |
| 320 | + (gptel-context--collect)) |
| 321 | + (with-current-buffer data-buf |
| 322 | + (thread-last (gptel-context--collect) |
| 323 | + (funcall gptel-context-string-function) |
| 324 | + (gptel-context--wrap-in-buffer))) |
| 325 | + (funcall callback))) |
| 326 | + |
| 327 | +(defun gptel-context--wrap-in-buffer (context-string &optional method) |
| 328 | + "Inject CONTEXT-STRING to current buffer using METHOD. |
| 329 | +
|
| 330 | +METHOD is either system or user, and defaults to `gptel-use-context'. |
| 331 | +This modifies the buffer." |
| 332 | + (when (length> context-string 0) |
| 333 | + (pcase (or method gptel-use-context) |
| 334 | + ('system |
| 335 | + (if (gptel--model-capable-p 'nosystem) |
| 336 | + (gptel-context--wrap-in-buffer context-string 'user) |
| 337 | + (if gptel--system-message |
| 338 | + (cl-etypecase gptel--system-message |
| 339 | + (string |
| 340 | + (setq gptel--system-message |
| 341 | + (concat gptel--system-message "\n\n" context-string))) |
| 342 | + (function |
| 343 | + (setq gptel--system-message |
| 344 | + (gptel--parse-directive gptel--system-message 'raw)) |
| 345 | + (gptel-context--wrap-in-buffer context-string)) |
| 346 | + (list |
| 347 | + (setq gptel--system-message ;cons a new list to avoid mutation |
| 348 | + (cons (concat (car gptel--system-message) "\n\n" context-string) |
| 349 | + (cdr gptel--system-message))))) |
| 350 | + (setq gptel--system-message context-string)))) |
| 351 | + ('user |
| 352 | + (goto-char (point-max)) |
| 353 | + (text-property-search-backward 'gptel nil t) |
| 354 | + (and gptel-mode |
| 355 | + (looking-at |
| 356 | + (concat "[\n[:blank:]]*" |
| 357 | + (and-let* ((prefix (gptel-prompt-prefix-string)) |
| 358 | + ((not (string-empty-p prefix)))) |
| 359 | + (concat "\\(?:" (regexp-quote prefix) "\\)?")))) |
| 360 | + (delete-region (match-beginning 0) (match-end 0))) |
| 361 | + (insert "\n" context-string "\n\n"))))) |
323 | 362 |
|
324 | 363 | (defun gptel-context--collect-media (&optional contexts) |
325 | 364 | "Collect media CONTEXTS. |
|
0 commit comments