@@ -220,8 +220,8 @@ describe("geminiInteractionsToCompletionRequest", () => {
220220 const result = geminiInteractionsToCompletionRequest ( {
221221 model : "gemini-2.5-flash" ,
222222 input : [
223- { role : "user" , parts : [ { type : "text" , text : "hi" } ] } ,
224- { role : "model" , parts : [ { type : "text" , text : "hello" } ] } ,
223+ { role : "user" , content : [ { type : "text" , text : "hi" } ] } ,
224+ { role : "model" , content : [ { type : "text" , text : "hello" } ] } ,
225225 ] ,
226226 } ) ;
227227 expect ( result . messages ) . toEqual ( [
@@ -247,7 +247,7 @@ describe("geminiInteractionsToCompletionRequest", () => {
247247 input : [
248248 {
249249 role : "user" ,
250- parts : [
250+ content : [
251251 {
252252 type : "function_result" ,
253253 call_id : "call_abc" ,
@@ -339,7 +339,7 @@ describe("geminiInteractionsToCompletionRequest", () => {
339339 input : [
340340 {
341341 role : "model" ,
342- parts : [
342+ content : [
343343 { type : "text" , text : "Calling tool..." } ,
344344 {
345345 type : "function_call" ,
@@ -367,12 +367,12 @@ describe("geminiInteractionsToCompletionRequest", () => {
367367 expect ( result . stream ) . toBe ( false ) ;
368368 } ) ;
369369
370- it ( "handles Turn with empty parts array — user/assistant produce empty-content message" , ( ) => {
370+ it ( "handles Turn with empty content array — user/assistant produce empty-content message" , ( ) => {
371371 const result = geminiInteractionsToCompletionRequest ( {
372372 model : "gemini-2.5-flash" ,
373373 input : [
374- { role : "user" , parts : [ ] } ,
375- { role : "model" , parts : [ ] } ,
374+ { role : "user" , content : [ ] } ,
375+ { role : "model" , content : [ ] } ,
376376 ] ,
377377 } ) ;
378378 expect ( result . messages ) . toEqual ( [
@@ -381,15 +381,15 @@ describe("geminiInteractionsToCompletionRequest", () => {
381381 ] ) ;
382382 } ) ;
383383
384- it ( "handles Turn with empty parts array — non-user/non-assistant role is skipped" , ( ) => {
384+ it ( "handles Turn with empty content array — non-user/non-assistant role is skipped" , ( ) => {
385385 const result = geminiInteractionsToCompletionRequest ( {
386386 model : "gemini-2.5-flash" ,
387387 input : [
388- { role : "system" , parts : [ ] } ,
389- { role : "user" , parts : [ { type : "text" , text : "hi" } ] } ,
388+ { role : "system" , content : [ ] } ,
389+ { role : "user" , content : [ { type : "text" , text : "hi" } ] } ,
390390 ] ,
391391 } ) ;
392- // The system turn with empty parts is skipped; only the user turn is kept
392+ // The system turn with empty content is skipped; only the user turn is kept
393393 expect ( result . messages ) . toEqual ( [ { role : "user" , content : "hi" } ] ) ;
394394 } ) ;
395395
@@ -399,7 +399,7 @@ describe("geminiInteractionsToCompletionRequest", () => {
399399 input : [
400400 {
401401 role : "user" ,
402- parts : [
402+ content : [
403403 {
404404 type : "function_result" ,
405405 call_id : "call_str" ,
@@ -414,6 +414,85 @@ describe("geminiInteractionsToCompletionRequest", () => {
414414 expect ( result . messages [ 0 ] . content ) . toBe ( "plain string result" ) ;
415415 expect ( result . messages [ 0 ] . tool_call_id ) . toBe ( "call_str" ) ;
416416 } ) ;
417+
418+ // ─── Legacy parts fallback tests ──────────────────────────────────────
419+
420+ it ( "handles Turn[] with legacy parts field for text (backwards compat)" , ( ) => {
421+ const result = geminiInteractionsToCompletionRequest ( {
422+ model : "gemini-2.5-flash" ,
423+ input : [
424+ { role : "user" , parts : [ { type : "text" , text : "hi from parts" } ] } ,
425+ { role : "model" , parts : [ { type : "text" , text : "hello from parts" } ] } ,
426+ ] ,
427+ } ) ;
428+ expect ( result . messages ) . toEqual ( [
429+ { role : "user" , content : "hi from parts" } ,
430+ { role : "assistant" , content : "hello from parts" } ,
431+ ] ) ;
432+ } ) ;
433+
434+ it ( "handles Turn[] with legacy parts field for function_call (backwards compat)" , ( ) => {
435+ const result = geminiInteractionsToCompletionRequest ( {
436+ model : "gemini-2.5-flash" ,
437+ input : [
438+ {
439+ role : "model" ,
440+ parts : [
441+ {
442+ type : "function_call" ,
443+ name : "legacy_tool" ,
444+ id : "call_legacy" ,
445+ arguments : { key : "value" } ,
446+ } ,
447+ ] ,
448+ } ,
449+ ] ,
450+ } ) ;
451+ expect ( result . messages ) . toHaveLength ( 1 ) ;
452+ expect ( result . messages [ 0 ] . role ) . toBe ( "assistant" ) ;
453+ expect ( result . messages [ 0 ] . tool_calls ) . toHaveLength ( 1 ) ;
454+ expect ( result . messages [ 0 ] . tool_calls ! [ 0 ] . function . name ) . toBe ( "legacy_tool" ) ;
455+ expect ( result . messages [ 0 ] . tool_calls ! [ 0 ] . id ) . toBe ( "call_legacy" ) ;
456+ } ) ;
457+
458+ it ( "handles Turn[] with legacy parts field for function_result (backwards compat)" , ( ) => {
459+ const result = geminiInteractionsToCompletionRequest ( {
460+ model : "gemini-2.5-flash" ,
461+ input : [
462+ {
463+ role : "user" ,
464+ parts : [
465+ {
466+ type : "function_result" ,
467+ call_id : "call_legacy_result" ,
468+ output : { status : "ok" } ,
469+ } ,
470+ ] ,
471+ } ,
472+ ] ,
473+ } ) ;
474+ expect ( result . messages ) . toHaveLength ( 1 ) ;
475+ expect ( result . messages [ 0 ] . role ) . toBe ( "tool" ) ;
476+ expect ( result . messages [ 0 ] . content ) . toBe ( '{"status":"ok"}' ) ;
477+ expect ( result . messages [ 0 ] . tool_call_id ) . toBe ( "call_legacy_result" ) ;
478+ } ) ;
479+
480+ // ─── content vs parts preference test ─────────────────────────────────
481+
482+ it ( "prefers content over parts when both are present on a Turn" , ( ) => {
483+ const result = geminiInteractionsToCompletionRequest ( {
484+ model : "gemini-2.5-flash" ,
485+ input : [
486+ {
487+ role : "user" ,
488+ content : [ { type : "text" , text : "from-content" } ] ,
489+ parts : [ { type : "text" , text : "from-parts" } ] ,
490+ } ,
491+ ] ,
492+ } ) ;
493+ expect ( result . messages ) . toHaveLength ( 1 ) ;
494+ expect ( result . messages [ 0 ] . content ) . toBe ( "from-content" ) ;
495+ } ) ;
417496} ) ;
418497
419498// ─── Unit tests: response builders ──────────────────────────────────────
@@ -928,7 +1007,7 @@ describe("Gemini Interactions — fixture matching", () => {
9281007 input : [
9291008 {
9301009 role : "user" ,
931- parts : [
1010+ content : [
9321011 {
9331012 type : "function_result" ,
9341013 call_id : "call_abc" ,
0 commit comments