Skip to content

Commit bdc91e5

Browse files
committed
gptel-gemini: Support thoughtSignature in tool calls
1 parent 73144b7 commit bdc91e5

File tree

2 files changed

+30
-13
lines changed

2 files changed

+30
-13
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@
3838
ring redirection now correctly captures the full response from the
3939
LLM, including pre- and post-tool-call text.
4040

41+
- ~gptel-gemini~: Add support for =thoughtSignature= in tool calls.
42+
This allows capturing reasoning output that accompanies tool use in
43+
Gemini models.
44+
4145
** Notable bug fixes
4246

4347
- Function-valued system messages/directives are now evaluated in the

gptel-gemini.el

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ list."
8080
(cl-loop
8181
for part across parts
8282
for tx = (plist-get part :text)
83+
for sig = (plist-get part :thoughtSignature)
8384
if (and tx (not (eq tx :null)))
8485
if (plist-get part :thought)
8586
do (unless (plist-get info :reasoning-block)
@@ -90,7 +91,11 @@ list."
9091
(plist-put info :reasoning-block t))
9192
and collect tx into content-strs end
9293
else if (plist-get part :functionCall)
93-
collect (copy-sequence it) into tool-use
94+
collect (let ((fc (copy-sequence it)))
95+
;; Store thoughtSignature in the tool-use plist
96+
(if sig (plist-put fc :thoughtSignature sig)
97+
fc))
98+
into tool-use
9499
finally do ;Add text and tool-calls to prompts list
95100
(when (or tool-use include-text)
96101
(let* ((data (plist-get info :data))
@@ -109,7 +114,11 @@ list."
109114
(plist-put info :tool-use
110115
(nconc (plist-get info :tool-use) tool-use)))
111116
finally return
112-
(and content-strs (apply #'concat content-strs)))))
117+
(if-let ((response-content (apply #'concat content-strs)))
118+
(if sig
119+
;; Store thoughtSignature as a text property on the response text
120+
(propertize response-content 'gptel-gemini-thought-signature sig)
121+
response-content)))))
113122

114123
(cl-defmethod gptel--request-data ((backend gptel-gemini) prompts)
115124
"JSON encode PROMPTS for sending to Gemini."
@@ -262,8 +271,8 @@ See generic implementation for full documentation."
262271
full-prompt))
263272
(`(tool . ,call)
264273
(push (list :role "model"
265-
:parts (vector `(:functionCall ( :name ,(plist-get call :name)
266-
:args ,(plist-get call :args)))))
274+
:parts `[(:functionCall (:name ,(plist-get call :name)
275+
:args ,(plist-get call :args)))])
267276
full-prompt)
268277
(push (gptel--parse-tool-results backend (list (cdr entry))) full-prompt))))
269278
(nreverse full-prompt))
@@ -272,7 +281,7 @@ See generic implementation for full documentation."
272281
if text
273282
if role
274283
collect (list :role "user" :parts `[(:text ,text)]) into prompts
275-
else collect (list :role "model" :parts `(:text ,text)) into prompts
284+
else collect (list :role "model" :parts `[(:text ,text)]) into prompts
276285
finally return prompts)))
277286

278287
(cl-defmethod gptel--parse-buffer ((backend gptel-gemini) &optional max-entries)
@@ -284,24 +293,28 @@ See generic implementation for full documentation."
284293
(not (= (point) prev-pt)))
285294
(pcase (get-char-property (point) 'gptel)
286295
('response
287-
(when-let* ((content (gptel--trim-prefixes
288-
(buffer-substring-no-properties (point) prev-pt))))
289-
(push (list :role "model" :parts (list :text content)) prompts)))
296+
(when-let* ((content (gptel--trim-prefixes (buffer-substring-no-properties (point) prev-pt)))
297+
(part (list :text content)))
298+
(when-let ((sig (get-text-property (point) 'gptel-gemini-thought-signature)))
299+
;; Retrieve thoughtSignature from text property, if present
300+
(plist-put part :thoughtSignature sig))
301+
(push (list :role "model" :parts (vector part)) prompts)))
290302
(`(tool . ,_id)
291303
(save-excursion
292304
(condition-case nil
293305
(let* ((tool-call (read (current-buffer)))
294306
(name (plist-get tool-call :name))
295-
(arguments (plist-get tool-call :args)))
307+
(arguments (plist-get tool-call :args))
308+
(sig (plist-get tool-call :thoughtSignature))
309+
(fc `(:functionCall (:name ,name :args ,arguments))))
310+
;; Retrieve thoughtSignature from tool call plist
311+
(when sig (plist-put fc :thoughtSignature sig))
296312
(plist-put tool-call :result
297313
(string-trim (buffer-substring-no-properties
298314
(point) prev-pt)))
299315
(push (gptel--parse-tool-results backend (list tool-call))
300316
prompts)
301-
(push (list :role "model"
302-
:parts
303-
(vector `(:functionCall ( :name ,name
304-
:args ,arguments))))
317+
(push (list :role "model" :parts (vector fc))
305318
prompts))
306319
((end-of-file invalid-read-syntax)
307320
(message (format "Could not parse tool-call on line %s"

0 commit comments

Comments
 (0)