@@ -3,6 +3,7 @@ import path from "node:path";
33import { resolveApiKeyForProvider } from "openclaw/plugin-sdk/provider-auth-runtime" ;
44import {
55 createProviderOperationDeadline ,
6+ executeProviderOperationWithRetry ,
67 resolveProviderOperationTimeoutMs ,
78 waitProviderOperationPollInterval ,
89} from "openclaw/plugin-sdk/provider-http" ;
@@ -161,9 +162,15 @@ async function downloadGeneratedVideo(params: {
161162 rootDir : tempDir ,
162163 path : fileName ,
163164 write : async ( downloadPath ) => {
164- await params . client . files . download ( {
165- file : params . file as never ,
166- downloadPath,
165+ await executeProviderOperationWithRetry ( {
166+ provider : "google" ,
167+ stage : "download" ,
168+ operation : async ( ) => {
169+ await params . client . files . download ( {
170+ file : params . file as never ,
171+ downloadPath,
172+ } ) ;
173+ } ,
167174 } ) ;
168175 } ,
169176 } ) ;
@@ -230,27 +237,33 @@ async function downloadGeneratedVideoFromUri(params: {
230237 if ( ! downloadUrl ) {
231238 return undefined ;
232239 }
233- const { response, release } = await fetchWithSsrFGuard ( {
234- url : downloadUrl ,
240+ return await executeProviderOperationWithRetry ( {
241+ provider : "google" ,
242+ stage : "download" ,
243+ operation : async ( ) => {
244+ const { response, release } = await fetchWithSsrFGuard ( {
245+ url : downloadUrl ,
246+ } ) ;
247+ try {
248+ if ( ! response . ok ) {
249+ throw new Error (
250+ `Failed to download Google generated video: ${ response . status } ${ response . statusText } ` ,
251+ ) ;
252+ }
253+ const buffer = Buffer . from ( await response . arrayBuffer ( ) ) ;
254+ return {
255+ buffer,
256+ mimeType :
257+ normalizeOptionalString ( response . headers . get ( "content-type" ) ) ||
258+ normalizeOptionalString ( params . mimeType ) ||
259+ "video/mp4" ,
260+ fileName : `video-${ params . index + 1 } .mp4` ,
261+ } ;
262+ } finally {
263+ await release ( ) ;
264+ }
265+ } ,
235266 } ) ;
236- try {
237- if ( ! response . ok ) {
238- throw new Error (
239- `Failed to download Google generated video: ${ response . status } ${ response . statusText } ` ,
240- ) ;
241- }
242- const buffer = Buffer . from ( await response . arrayBuffer ( ) ) ;
243- return {
244- buffer,
245- mimeType :
246- normalizeOptionalString ( response . headers . get ( "content-type" ) ) ||
247- normalizeOptionalString ( params . mimeType ) ||
248- "video/mp4" ,
249- fileName : `video-${ params . index + 1 } .mp4` ,
250- } ;
251- } finally {
252- await release ( ) ;
253- }
254267}
255268
256269function extractGoogleApiErrorCode ( error : unknown ) : number | undefined {
@@ -284,39 +297,52 @@ async function requestGoogleVideoJson(params: {
284297 method : "GET" | "POST" ;
285298 headers : Record < string , string > ;
286299 deadline : ReturnType < typeof createProviderOperationDeadline > ;
300+ stage : "create" | "poll" ;
287301 body ?: unknown ;
288302} ) : Promise < unknown > {
289- const controller = new AbortController ( ) ;
290- const timeout = setTimeout (
291- ( ) => controller . abort ( ) ,
292- resolveProviderOperationTimeoutMs ( {
293- deadline : params . deadline ,
294- defaultTimeoutMs : DEFAULT_TIMEOUT_MS ,
295- } ) ,
296- ) ;
297- try {
298- const { response, release } = await fetchWithSsrFGuard ( {
299- url : params . url ,
300- init : {
301- method : params . method ,
302- headers : params . headers ,
303- ...( params . body === undefined ? { } : { body : JSON . stringify ( params . body ) } ) ,
304- } ,
305- signal : controller . signal ,
306- } ) ;
307- try {
308- const text = await response . text ( ) ;
309- const payload = text ? ( JSON . parse ( text ) as unknown ) : { } ;
310- if ( ! response . ok ) {
311- throw new Error ( typeof payload === "string" ? payload : JSON . stringify ( payload ?? null ) ) ;
303+ return await executeProviderOperationWithRetry ( {
304+ provider : "google" ,
305+ stage : params . stage ,
306+ operation : async ( ) => {
307+ const controller = new AbortController ( ) ;
308+ const timeout = setTimeout (
309+ ( ) => {
310+ const error = new Error ( "request timed out" ) ;
311+ error . name = "TimeoutError" ;
312+ controller . abort ( error ) ;
313+ } ,
314+ resolveProviderOperationTimeoutMs ( {
315+ deadline : params . deadline ,
316+ defaultTimeoutMs : DEFAULT_TIMEOUT_MS ,
317+ } ) ,
318+ ) ;
319+ try {
320+ const { response, release } = await fetchWithSsrFGuard ( {
321+ url : params . url ,
322+ init : {
323+ method : params . method ,
324+ headers : params . headers ,
325+ ...( params . body === undefined ? { } : { body : JSON . stringify ( params . body ) } ) ,
326+ } ,
327+ signal : controller . signal ,
328+ } ) ;
329+ try {
330+ const text = await response . text ( ) ;
331+ const payload = text ? ( JSON . parse ( text ) as unknown ) : { } ;
332+ if ( ! response . ok ) {
333+ throw new Error (
334+ typeof payload === "string" ? payload : JSON . stringify ( payload ?? null ) ,
335+ ) ;
336+ }
337+ return payload ;
338+ } finally {
339+ await release ( ) ;
340+ }
341+ } finally {
342+ clearTimeout ( timeout ) ;
312343 }
313- return payload ;
314- } finally {
315- await release ( ) ;
316- }
317- } finally {
318- clearTimeout ( timeout ) ;
319- }
344+ } ,
345+ } ) ;
320346}
321347
322348async function generateGoogleVideoViaRest ( params : {
@@ -334,6 +360,7 @@ async function generateGoogleVideoViaRest(params: {
334360 method : "POST" ,
335361 headers : params . headers ,
336362 deadline : params . deadline ,
363+ stage : "create" ,
337364 body : {
338365 instances : [ { prompt : params . prompt } ] ,
339366 parameters : {
@@ -363,6 +390,7 @@ async function generateGoogleVideoViaRest(params: {
363390 method : "GET" ,
364391 headers : params . headers ,
365392 deadline : params . deadline ,
393+ stage : "poll" ,
366394 } ) ;
367395 }
368396 const error = ( operation as { error ?: unknown } ) . error ;
@@ -462,7 +490,11 @@ export function buildGoogleVideoGenerationProvider(): VideoGenerationProvider {
462490 }
463491 await waitProviderOperationPollInterval ( { deadline, pollIntervalMs : POLL_INTERVAL_MS } ) ;
464492 resolveProviderOperationTimeoutMs ( { deadline, defaultTimeoutMs : DEFAULT_TIMEOUT_MS } ) ;
465- sdkOperation = await client . operations . getVideosOperation ( { operation : sdkOperation } ) ;
493+ sdkOperation = await executeProviderOperationWithRetry ( {
494+ provider : "google" ,
495+ stage : "poll" ,
496+ operation : ( ) => client . operations . getVideosOperation ( { operation : sdkOperation } ) ,
497+ } ) ;
466498 }
467499 operation = sdkOperation ;
468500 }
0 commit comments