@@ -7,7 +7,6 @@ package gemini
77
88import (
99 "bytes"
10- "encoding/json"
1110 "fmt"
1211
1312 "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini/common"
@@ -135,41 +134,31 @@ func ConvertGeminiRequestToAntigravity(_ string, inputRawJSON []byte, _ bool) []
135134
136135// FunctionCallGroup represents a group of function calls and their responses
137136type FunctionCallGroup struct {
138- ModelContent map [string ]interface {}
139- FunctionCalls []gjson.Result
140137 ResponsesNeeded int
141138}
142139
143- // parseFunctionResponse attempts to unmarshal a function response part.
144- // Falls back to gjson extraction if standard json.Unmarshal fails.
145- func parseFunctionResponse (response gjson.Result ) map [string ]interface {} {
146- var responseMap map [string ]interface {}
147- err := json .Unmarshal ([]byte (response .Raw ), & responseMap )
148- if err == nil {
149- return responseMap
140+ // parseFunctionResponseRaw attempts to normalize a function response part into a JSON object string.
141+ // Falls back to a minimal "functionResponse" object when parsing fails.
142+ func parseFunctionResponseRaw (response gjson.Result ) string {
143+ if response .IsObject () && gjson .Valid (response .Raw ) {
144+ return response .Raw
150145 }
151146
152- log .Debugf ("unmarshal function response failed, using fallback: %v" , err )
147+ log .Debugf ("parse function response failed, using fallback" )
153148 funcResp := response .Get ("functionResponse" )
154149 if funcResp .Exists () {
155- fr := map [string ]interface {}{
156- "name" : funcResp .Get ("name" ).String (),
157- "response" : map [string ]interface {}{
158- "result" : funcResp .Get ("response" ).String (),
159- },
160- }
150+ fr := `{"functionResponse":{"name":"","response":{"result":""}}}`
151+ fr , _ = sjson .Set (fr , "functionResponse.name" , funcResp .Get ("name" ).String ())
152+ fr , _ = sjson .Set (fr , "functionResponse.response.result" , funcResp .Get ("response" ).String ())
161153 if id := funcResp .Get ("id" ).String (); id != "" {
162- fr [ " id"] = id
154+ fr , _ = sjson . Set ( fr , "functionResponse. id", id )
163155 }
164- return map [ string ] interface {}{ "functionResponse" : fr }
156+ return fr
165157 }
166158
167- return map [string ]interface {}{
168- "functionResponse" : map [string ]interface {}{
169- "name" : "unknown" ,
170- "response" : map [string ]interface {}{"result" : response .String ()},
171- },
172- }
159+ fr := `{"functionResponse":{"name":"unknown","response":{"result":""}}}`
160+ fr , _ = sjson .Set (fr , "functionResponse.response.result" , response .String ())
161+ return fr
173162}
174163
175164// fixCLIToolResponse performs sophisticated tool response format conversion and grouping.
@@ -196,7 +185,7 @@ func fixCLIToolResponse(input string) (string, error) {
196185 }
197186
198187 // Initialize data structures for processing and grouping
199- var newContents [] interface {} // Final processed contents array
188+ contentsWrapper := `{"contents":[]}`
200189 var pendingGroups []* FunctionCallGroup // Groups awaiting completion with responses
201190 var collectedResponses []gjson.Result // Standalone responses to be matched
202191
@@ -228,17 +217,16 @@ func fixCLIToolResponse(input string) (string, error) {
228217 collectedResponses = collectedResponses [group .ResponsesNeeded :]
229218
230219 // Create merged function response content
231- var responseParts [] interface {}
220+ functionResponseContent := `{"parts":[],"role":"function"}`
232221 for _ , response := range groupResponses {
233- responseParts = append (responseParts , parseFunctionResponse (response ))
222+ partRaw := parseFunctionResponseRaw (response )
223+ if partRaw != "" {
224+ functionResponseContent , _ = sjson .SetRaw (functionResponseContent , "parts.-1" , partRaw )
225+ }
234226 }
235227
236- if len (responseParts ) > 0 {
237- functionResponseContent := map [string ]interface {}{
238- "parts" : responseParts ,
239- "role" : "function" ,
240- }
241- newContents = append (newContents , functionResponseContent )
228+ if gjson .Get (functionResponseContent , "parts.#" ).Int () > 0 {
229+ contentsWrapper , _ = sjson .SetRaw (contentsWrapper , "contents.-1" , functionResponseContent )
242230 }
243231
244232 // Remove this group as it's been satisfied
@@ -252,50 +240,42 @@ func fixCLIToolResponse(input string) (string, error) {
252240
253241 // If this is a model with function calls, create a new group
254242 if role == "model" {
255- var functionCallsInThisModel []gjson. Result
243+ functionCallsCount := 0
256244 parts .ForEach (func (_ , part gjson.Result ) bool {
257245 if part .Get ("functionCall" ).Exists () {
258- functionCallsInThisModel = append ( functionCallsInThisModel , part )
246+ functionCallsCount ++
259247 }
260248 return true
261249 })
262250
263- if len ( functionCallsInThisModel ) > 0 {
251+ if functionCallsCount > 0 {
264252 // Add the model content
265- var contentMap map [string ]interface {}
266- errUnmarshal := json .Unmarshal ([]byte (value .Raw ), & contentMap )
267- if errUnmarshal != nil {
268- log .Warnf ("failed to unmarshal model content: %v\n " , errUnmarshal )
253+ if ! value .IsObject () {
254+ log .Warnf ("failed to parse model content" )
269255 return true
270256 }
271- newContents = append ( newContents , contentMap )
257+ contentsWrapper , _ = sjson . SetRaw ( contentsWrapper , "contents.-1" , value . Raw )
272258
273259 // Create a new group for tracking responses
274260 group := & FunctionCallGroup {
275- ModelContent : contentMap ,
276- FunctionCalls : functionCallsInThisModel ,
277- ResponsesNeeded : len (functionCallsInThisModel ),
261+ ResponsesNeeded : functionCallsCount ,
278262 }
279263 pendingGroups = append (pendingGroups , group )
280264 } else {
281265 // Regular model content without function calls
282- var contentMap map [string ]interface {}
283- errUnmarshal := json .Unmarshal ([]byte (value .Raw ), & contentMap )
284- if errUnmarshal != nil {
285- log .Warnf ("failed to unmarshal content: %v\n " , errUnmarshal )
266+ if ! value .IsObject () {
267+ log .Warnf ("failed to parse content" )
286268 return true
287269 }
288- newContents = append ( newContents , contentMap )
270+ contentsWrapper , _ = sjson . SetRaw ( contentsWrapper , "contents.-1" , value . Raw )
289271 }
290272 } else {
291273 // Non-model content (user, etc.)
292- var contentMap map [string ]interface {}
293- errUnmarshal := json .Unmarshal ([]byte (value .Raw ), & contentMap )
294- if errUnmarshal != nil {
295- log .Warnf ("failed to unmarshal content: %v\n " , errUnmarshal )
274+ if ! value .IsObject () {
275+ log .Warnf ("failed to parse content" )
296276 return true
297277 }
298- newContents = append ( newContents , contentMap )
278+ contentsWrapper , _ = sjson . SetRaw ( contentsWrapper , "contents.-1" , value . Raw )
299279 }
300280
301281 return true
@@ -307,25 +287,23 @@ func fixCLIToolResponse(input string) (string, error) {
307287 groupResponses := collectedResponses [:group .ResponsesNeeded ]
308288 collectedResponses = collectedResponses [group .ResponsesNeeded :]
309289
310- var responseParts [] interface {}
290+ functionResponseContent := `{"parts":[],"role":"function"}`
311291 for _ , response := range groupResponses {
312- responseParts = append (responseParts , parseFunctionResponse (response ))
292+ partRaw := parseFunctionResponseRaw (response )
293+ if partRaw != "" {
294+ functionResponseContent , _ = sjson .SetRaw (functionResponseContent , "parts.-1" , partRaw )
295+ }
313296 }
314297
315- if len (responseParts ) > 0 {
316- functionResponseContent := map [string ]interface {}{
317- "parts" : responseParts ,
318- "role" : "function" ,
319- }
320- newContents = append (newContents , functionResponseContent )
298+ if gjson .Get (functionResponseContent , "parts.#" ).Int () > 0 {
299+ contentsWrapper , _ = sjson .SetRaw (contentsWrapper , "contents.-1" , functionResponseContent )
321300 }
322301 }
323302 }
324303
325304 // Update the original JSON with the new contents
326305 result := input
327- newContentsJSON , _ := json .Marshal (newContents )
328- result , _ = sjson .Set (result , "request.contents" , json .RawMessage (newContentsJSON ))
306+ result , _ = sjson .SetRaw (result , "request.contents" , gjson .Get (contentsWrapper , "contents" ).Raw )
329307
330308 return result , nil
331309}
0 commit comments