@@ -280,6 +280,98 @@ By default, \"openai.com\" is used as HOST and \"apikey\" as USER."
280
280
(propertize msg 'face face))
281
281
(force-mode-line-update )))
282
282
283
+ (cl-defun gptel-request
284
+ (&optional prompt &key callback
285
+ (buffer (current-buffer ))
286
+ position context
287
+ (system gptel--system-message))
288
+ " Request a response from ChatGPT for PROMPT.
289
+
290
+ If PROMPT is
291
+ - a string, it is used to create a full prompt suitable for
292
+ sending to ChatGPT.
293
+ - nil but region is active, the region contents are used.
294
+ - nil, the current buffer's contents up to (point) are used.
295
+ Previous responses from ChatGPT are identified as responses.
296
+ - A list of plists, it is used as is.
297
+
298
+ Keyword arguments:
299
+
300
+ CALLBACK, if supplied, is a function of two arguments, called
301
+ with the RESPONSE (a string) and the CONTEXT (a plist):
302
+
303
+ (callback RESPONSE INFO)
304
+
305
+ RESPONSE is nil if there was no response or an error.
306
+
307
+ The INFO plist has (at least) the following keys:
308
+ :prompt - The full prompt that was sent with the request
309
+ :position - marker at the point the request was sent.
310
+ :buffer - The buffer current when the request was sent.
311
+ :status - Short string describing the result of the request
312
+
313
+ Example of a callback that messages the user with the response
314
+ and info:
315
+
316
+ (lambda (response info)
317
+ (if response
318
+ (let ((posn (marker-position (plist-get info :position)))
319
+ (buf (buffer-name (plist-get info :buffer))))
320
+ (message \" Response for request from %S at %d: %s\"
321
+ buf posn response))
322
+ (message \" gptel-request failed with message: %s\"
323
+ (plist-get info :status))))
324
+
325
+ Or, for just the response:
326
+
327
+ (lambda (response _)
328
+ ;; Do something with response
329
+ (message (rot13-string response)))
330
+
331
+ If CALLBACK is omitted, the response is inserted at the point the
332
+ request was sent.
333
+
334
+ BUFFER is the buffer the request belongs to. If omitted the
335
+ current buffer is recorded.
336
+
337
+ POSITION is a buffer position (integer or marker). If omitted,
338
+ the value of (point) or (region-end) is recorded, depending on
339
+ whether the region is active.
340
+
341
+ CONTEXT is any additional data needed for the callback to run. It
342
+ is included in the INFO argument to the callback.
343
+
344
+ SYSTEM is the system message (chat directive) sent to ChatGPT. If
345
+ omitted, the value of `gptel--system-message' for the current
346
+ buffer is used.
347
+
348
+ Model parameters can be let-bound around calls to this function."
349
+ (let* ((gptel-stream nil )
350
+ (start-marker
351
+ (cond
352
+ ((null position)
353
+ (if (use-region-p )
354
+ (set-marker (make-marker ) (region-end ))
355
+ (point-marker )))
356
+ ((markerp position) position)
357
+ ((integerp position)
358
+ (set-marker (make-marker ) position buffer))))
359
+ (full-prompt
360
+ (cond
361
+ ((null prompt) (gptel--create-prompt start-marker))
362
+ ((stringp prompt)
363
+ `((:role " system" :content , system )
364
+ (:role " user" :content , prompt )))
365
+ ((consp prompt) prompt)))
366
+ (info (list :prompt full-prompt
367
+ :buffer buffer
368
+ :position start-marker)))
369
+ (when context (plist-put info :context context))
370
+ (funcall
371
+ (if gptel-use-curl
372
+ #'gptel-curl-get-response #'gptel--url-get-response )
373
+ info callback)))
374
+
283
375
; ; TODO: Handle read-only buffers. Should we spawn a new buffer automatically?
284
376
; ; TODO: Handle multiple requests(#15). (Only one request from one buffer at a time?)
285
377
; ; TODO: Since we capture a marker for the insertion location, `gptel-buffer' no
0 commit comments