@@ -240,3 +240,146 @@ func extractGeminiUsageMetadata(geminiResponse *GenerateContentResponse) (int, i
240240 }
241241 return inputTokens , outputTokens , totalTokens
242242}
243+
244+ // ==================== SDK RESPONSE CONVERTERS ====================
245+ // These functions convert Bifrost batch responses to Google GenAI SDK format.
246+
247+ // ToGeminiJobState converts Bifrost batch status to Gemini SDK job state.
248+ func ToGeminiJobState (status schemas.BatchStatus ) string {
249+ switch status {
250+ case schemas .BatchStatusValidating :
251+ return GeminiJobStatePending
252+ case schemas .BatchStatusInProgress :
253+ return GeminiJobStateRunning
254+ case schemas .BatchStatusFinalizing :
255+ return GeminiJobStateRunning
256+ case schemas .BatchStatusCompleted :
257+ return GeminiJobStateSucceeded
258+ case schemas .BatchStatusFailed :
259+ return GeminiJobStateFailed
260+ case schemas .BatchStatusCancelling :
261+ return GeminiJobStateCancelling
262+ case schemas .BatchStatusCancelled :
263+ return GeminiJobStateCancelled
264+ case schemas .BatchStatusExpired :
265+ return GeminiJobStateFailed
266+ default :
267+ return GeminiJobStatePending
268+ }
269+ }
270+
271+ // ToGeminiBatchJobResponse converts a BifrostBatchCreateResponse to Gemini SDK format.
272+ func ToGeminiBatchJobResponse (resp * schemas.BifrostBatchCreateResponse ) * GeminiBatchJobResponseSDK {
273+ if resp == nil {
274+ return nil
275+ }
276+
277+ result := & GeminiBatchJobResponseSDK {
278+ Name : resp .ID ,
279+ State : ToGeminiJobState (resp .Status ),
280+ }
281+
282+ // Add metadata if available
283+ if resp .CreatedAt > 0 {
284+ result .Metadata = & GeminiBatchMetadata {
285+ Name : resp .ID ,
286+ State : ToGeminiJobState (resp .Status ),
287+ CreateTime : time .Unix (resp .CreatedAt , 0 ).Format (time .RFC3339 ),
288+ BatchStats : & GeminiBatchStats {
289+ RequestCount : resp .RequestCounts .Total ,
290+ PendingRequestCount : resp .RequestCounts .Total - resp .RequestCounts .Completed ,
291+ SuccessfulRequestCount : resp .RequestCounts .Completed - resp .RequestCounts .Failed ,
292+ },
293+ }
294+ }
295+
296+ return result
297+ }
298+
299+ // ToGeminiBatchRetrieveResponse converts a BifrostBatchRetrieveResponse to Gemini SDK format.
300+ func ToGeminiBatchRetrieveResponse (resp * schemas.BifrostBatchRetrieveResponse ) * GeminiBatchJobResponseSDK {
301+ if resp == nil {
302+ return nil
303+ }
304+
305+ result := & GeminiBatchJobResponseSDK {
306+ Name : resp .ID ,
307+ State : ToGeminiJobState (resp .Status ),
308+ }
309+
310+ // Add metadata
311+ result .Metadata = & GeminiBatchMetadata {
312+ Name : resp .ID ,
313+ State : ToGeminiJobState (resp .Status ),
314+ CreateTime : time .Unix (resp .CreatedAt , 0 ).Format (time .RFC3339 ),
315+ BatchStats : & GeminiBatchStats {
316+ RequestCount : resp .RequestCounts .Total ,
317+ PendingRequestCount : resp .RequestCounts .Total - resp .RequestCounts .Completed ,
318+ SuccessfulRequestCount : resp .RequestCounts .Completed - resp .RequestCounts .Failed ,
319+ },
320+ }
321+
322+ if resp .CompletedAt != nil {
323+ result .Metadata .EndTime = time .Unix (* resp .CompletedAt , 0 ).Format (time .RFC3339 )
324+ }
325+
326+ // Add output file info if available
327+ if resp .OutputFileID != nil {
328+ result .Dest = & GeminiBatchDest {
329+ FileName : * resp .OutputFileID ,
330+ }
331+ }
332+
333+ return result
334+ }
335+
336+ // ToGeminiBatchListResponse converts a BifrostBatchListResponse to Gemini SDK format.
337+ func ToGeminiBatchListResponse (resp * schemas.BifrostBatchListResponse ) * GeminiBatchListResponseSDK {
338+ if resp == nil {
339+ return nil
340+ }
341+
342+ jobs := make ([]GeminiBatchJobResponseSDK , 0 , len (resp .Data ))
343+ for _ , batch := range resp .Data {
344+ job := GeminiBatchJobResponseSDK {
345+ Name : batch .ID ,
346+ State : ToGeminiJobState (batch .Status ),
347+ }
348+
349+ // Add metadata
350+ job .Metadata = & GeminiBatchMetadata {
351+ Name : batch .ID ,
352+ State : ToGeminiJobState (batch .Status ),
353+ CreateTime : time .Unix (batch .CreatedAt , 0 ).Format (time .RFC3339 ),
354+ BatchStats : & GeminiBatchStats {
355+ RequestCount : batch .RequestCounts .Total ,
356+ PendingRequestCount : batch .RequestCounts .Total - batch .RequestCounts .Completed ,
357+ SuccessfulRequestCount : batch .RequestCounts .Completed - batch .RequestCounts .Failed ,
358+ },
359+ }
360+
361+ jobs = append (jobs , job )
362+ }
363+
364+ result := & GeminiBatchListResponseSDK {
365+ BatchJobs : jobs ,
366+ }
367+
368+ if resp .NextCursor != nil {
369+ result .NextPageToken = * resp .NextCursor
370+ }
371+
372+ return result
373+ }
374+
375+ // ToGeminiBatchCancelResponse converts a BifrostBatchCancelResponse to Gemini SDK format.
376+ func ToGeminiBatchCancelResponse (resp * schemas.BifrostBatchCancelResponse ) * GeminiBatchJobResponseSDK {
377+ if resp == nil {
378+ return nil
379+ }
380+
381+ return & GeminiBatchJobResponseSDK {
382+ Name : resp .ID ,
383+ State : ToGeminiJobState (resp .Status ),
384+ }
385+ }
0 commit comments