

















@@ -3,6 +3,7 @@ import path from "node:path";
33import { resolveApiKeyForProvider } from "openclaw/plugin-sdk/provider-auth-runtime";
44import {
55createProviderOperationDeadline,
6+executeProviderOperationWithRetry,
67resolveProviderOperationTimeoutMs,
78waitProviderOperationPollInterval,
89} from "openclaw/plugin-sdk/provider-http";
@@ -161,9 +162,15 @@ async function downloadGeneratedVideo(params: {
161162rootDir: tempDir,
162163path: fileName,
163164write: 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: {
230237if (!downloadUrl) {
231238return 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}
255268256269function extractGoogleApiErrorCode(error: unknown): number | undefined {
@@ -284,39 +297,52 @@ async function requestGoogleVideoJson(params: {
284297method: "GET" | "POST";
285298headers: Record<string, string>;
286299deadline: ReturnType<typeof createProviderOperationDeadline>;
300+stage: "create" | "poll";
287301body?: 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}
321347322348async function generateGoogleVideoViaRest(params: {
@@ -334,6 +360,7 @@ async function generateGoogleVideoViaRest(params: {
334360method: "POST",
335361headers: params.headers,
336362deadline: params.deadline,
363+stage: "create",
337364body: {
338365instances: [{ prompt: params.prompt }],
339366parameters: {
@@ -363,6 +390,7 @@ async function generateGoogleVideoViaRest(params: {
363390method: "GET",
364391headers: params.headers,
365392deadline: params.deadline,
393+stage: "poll",
366394});
367395}
368396const error = (operation as { error?: unknown }).error;
@@ -462,7 +490,11 @@ export function buildGoogleVideoGenerationProvider(): VideoGenerationProvider {
462490}
463491await waitProviderOperationPollInterval({ deadline, pollIntervalMs: POLL_INTERVAL_MS });
464492resolveProviderOperationTimeoutMs({ 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}
467499operation = sdkOperation;
468500}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。