mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-12 09:41:11 +00:00
refactor: dedupe vydra provider request helpers
This commit is contained in:
@@ -1,21 +1,14 @@
|
||||
import type { ImageGenerationProvider } from "openclaw/plugin-sdk/image-generation";
|
||||
import { isProviderApiKeyConfigured } from "openclaw/plugin-sdk/provider-auth";
|
||||
import { resolveApiKeyForProvider } from "openclaw/plugin-sdk/provider-auth-runtime";
|
||||
import { assertOkOrThrowHttpError, postJsonRequest } from "openclaw/plugin-sdk/provider-http";
|
||||
import {
|
||||
assertOkOrThrowHttpError,
|
||||
postJsonRequest,
|
||||
resolveProviderHttpRequestConfig,
|
||||
} from "openclaw/plugin-sdk/provider-http";
|
||||
import {
|
||||
DEFAULT_VYDRA_BASE_URL,
|
||||
DEFAULT_VYDRA_IMAGE_MODEL,
|
||||
downloadVydraAsset,
|
||||
extractVydraResultUrls,
|
||||
resolveVydraBaseUrlFromConfig,
|
||||
resolveVydraErrorMessage,
|
||||
resolveCompletedVydraPayload,
|
||||
resolveVydraResponseJobId,
|
||||
resolveVydraResponseStatus,
|
||||
waitForVydraJob,
|
||||
resolveVydraRequestContext,
|
||||
} from "./shared.js";
|
||||
|
||||
export function buildVydraImageGenerationProvider(): ImageGenerationProvider {
|
||||
@@ -55,29 +48,12 @@ export function buildVydraImageGenerationProvider(): ImageGenerationProvider {
|
||||
throw new Error("Vydra image generation supports at most one image per request.");
|
||||
}
|
||||
|
||||
const auth = await resolveApiKeyForProvider({
|
||||
provider: "vydra",
|
||||
cfg: req.cfg,
|
||||
agentDir: req.agentDir,
|
||||
store: req.authStore,
|
||||
});
|
||||
if (!auth.apiKey) {
|
||||
throw new Error("Vydra API key missing");
|
||||
}
|
||||
|
||||
const fetchFn = fetch;
|
||||
const { baseUrl, allowPrivateNetwork, headers, dispatcherPolicy } =
|
||||
resolveProviderHttpRequestConfig({
|
||||
baseUrl: resolveVydraBaseUrlFromConfig(req.cfg),
|
||||
defaultBaseUrl: DEFAULT_VYDRA_BASE_URL,
|
||||
allowPrivateNetwork: false,
|
||||
defaultHeaders: {
|
||||
Authorization: `Bearer ${auth.apiKey}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
provider: "vydra",
|
||||
const { fetchFn, baseUrl, allowPrivateNetwork, headers, dispatcherPolicy } =
|
||||
await resolveVydraRequestContext({
|
||||
cfg: req.cfg,
|
||||
agentDir: req.agentDir,
|
||||
authStore: req.authStore,
|
||||
capability: "image",
|
||||
transport: "http",
|
||||
});
|
||||
|
||||
const model = req.model?.trim() || DEFAULT_VYDRA_IMAGE_MODEL;
|
||||
@@ -97,27 +73,15 @@ export function buildVydraImageGenerationProvider(): ImageGenerationProvider {
|
||||
try {
|
||||
await assertOkOrThrowHttpError(response, "Vydra image generation failed");
|
||||
const submitted = await response.json();
|
||||
const completedPayload =
|
||||
resolveVydraResponseStatus(submitted) === "completed" ||
|
||||
extractVydraResultUrls(submitted, "image").length > 0
|
||||
? submitted
|
||||
: await (() => {
|
||||
const jobId = resolveVydraResponseJobId(submitted);
|
||||
if (!jobId) {
|
||||
throw new Error(
|
||||
resolveVydraErrorMessage(submitted) ??
|
||||
"Vydra image generation response missing job id",
|
||||
);
|
||||
}
|
||||
return waitForVydraJob({
|
||||
baseUrl,
|
||||
jobId,
|
||||
headers,
|
||||
timeoutMs: req.timeoutMs,
|
||||
fetchFn,
|
||||
kind: "image",
|
||||
});
|
||||
})();
|
||||
const completedPayload = await resolveCompletedVydraPayload({
|
||||
submitted,
|
||||
baseUrl,
|
||||
headers,
|
||||
timeoutMs: req.timeoutMs,
|
||||
fetchFn,
|
||||
kind: "image",
|
||||
missingJobIdMessage: "Vydra image generation response missing job id",
|
||||
});
|
||||
const imageUrl = extractVydraResultUrls(completedPayload, "image")[0];
|
||||
if (!imageUrl) {
|
||||
throw new Error("Vydra image generation completed without an image URL");
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
import { assertOkOrThrowHttpError, fetchWithTimeout } from "openclaw/plugin-sdk/provider-http";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { resolveApiKeyForProvider } from "openclaw/plugin-sdk/provider-auth-runtime";
|
||||
import {
|
||||
assertOkOrThrowHttpError,
|
||||
fetchWithTimeout,
|
||||
resolveProviderHttpRequestConfig,
|
||||
} from "openclaw/plugin-sdk/provider-http";
|
||||
import type { AuthStoreDataV1 } from "openclaw/plugin-sdk/provider-types";
|
||||
|
||||
export const DEFAULT_VYDRA_BASE_URL = "https://www.vydra.ai/api/v1";
|
||||
export const DEFAULT_VYDRA_IMAGE_MODEL = "grok-imagine";
|
||||
@@ -74,6 +81,50 @@ export function resolveVydraBaseUrlFromConfig(cfg: unknown): string {
|
||||
return normalizeVydraBaseUrl(trimToUndefined(vydra?.baseUrl));
|
||||
}
|
||||
|
||||
export async function resolveVydraRequestContext(params: {
|
||||
cfg: OpenClawConfig;
|
||||
agentDir?: string;
|
||||
authStore?: AuthStoreDataV1;
|
||||
capability: "image" | "video";
|
||||
}): Promise<{
|
||||
fetchFn: typeof fetch;
|
||||
baseUrl: string;
|
||||
allowPrivateNetwork: boolean;
|
||||
headers: Headers;
|
||||
dispatcherPolicy: ReturnType<typeof resolveProviderHttpRequestConfig>["dispatcherPolicy"];
|
||||
}> {
|
||||
const auth = await resolveApiKeyForProvider({
|
||||
provider: "vydra",
|
||||
cfg: params.cfg,
|
||||
agentDir: params.agentDir,
|
||||
store: params.authStore,
|
||||
});
|
||||
if (!auth.apiKey) {
|
||||
throw new Error("Vydra API key missing");
|
||||
}
|
||||
const fetchFn = fetch;
|
||||
const { baseUrl, allowPrivateNetwork, headers, dispatcherPolicy } =
|
||||
resolveProviderHttpRequestConfig({
|
||||
baseUrl: resolveVydraBaseUrlFromConfig(params.cfg),
|
||||
defaultBaseUrl: DEFAULT_VYDRA_BASE_URL,
|
||||
allowPrivateNetwork: false,
|
||||
defaultHeaders: {
|
||||
Authorization: `Bearer ${auth.apiKey}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
provider: "vydra",
|
||||
capability: params.capability,
|
||||
transport: "http",
|
||||
});
|
||||
return {
|
||||
fetchFn,
|
||||
baseUrl,
|
||||
allowPrivateNetwork,
|
||||
headers,
|
||||
dispatcherPolicy,
|
||||
};
|
||||
}
|
||||
|
||||
export function resolveVydraResponseJobId(payload: unknown): string | undefined {
|
||||
const object = asObject(payload) as VydraJobPayload | undefined;
|
||||
return trimToUndefined(object?.jobId) ?? trimToUndefined(object?.id);
|
||||
@@ -216,3 +267,32 @@ export async function waitForVydraJob(params: {
|
||||
}
|
||||
throw new Error(`Vydra job ${params.jobId} did not finish in time`);
|
||||
}
|
||||
|
||||
export async function resolveCompletedVydraPayload(params: {
|
||||
submitted: unknown;
|
||||
baseUrl: string;
|
||||
headers: Headers;
|
||||
timeoutMs?: number;
|
||||
fetchFn: typeof fetch;
|
||||
kind: VydraMediaKind;
|
||||
missingJobIdMessage: string;
|
||||
}): Promise<unknown> {
|
||||
if (
|
||||
resolveVydraResponseStatus(params.submitted) === "completed" ||
|
||||
extractVydraResultUrls(params.submitted, params.kind).length > 0
|
||||
) {
|
||||
return params.submitted;
|
||||
}
|
||||
const jobId = resolveVydraResponseJobId(params.submitted);
|
||||
if (!jobId) {
|
||||
throw new Error(resolveVydraErrorMessage(params.submitted) ?? params.missingJobIdMessage);
|
||||
}
|
||||
return waitForVydraJob({
|
||||
baseUrl: params.baseUrl,
|
||||
jobId,
|
||||
headers: params.headers,
|
||||
timeoutMs: params.timeoutMs,
|
||||
fetchFn: params.fetchFn,
|
||||
kind: params.kind,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,21 +1,14 @@
|
||||
import { isProviderApiKeyConfigured } from "openclaw/plugin-sdk/provider-auth";
|
||||
import { resolveApiKeyForProvider } from "openclaw/plugin-sdk/provider-auth-runtime";
|
||||
import {
|
||||
assertOkOrThrowHttpError,
|
||||
postJsonRequest,
|
||||
resolveProviderHttpRequestConfig,
|
||||
} from "openclaw/plugin-sdk/provider-http";
|
||||
import { assertOkOrThrowHttpError, postJsonRequest } from "openclaw/plugin-sdk/provider-http";
|
||||
import type { VideoGenerationProvider } from "openclaw/plugin-sdk/video-generation";
|
||||
import {
|
||||
DEFAULT_VYDRA_BASE_URL,
|
||||
DEFAULT_VYDRA_VIDEO_MODEL,
|
||||
downloadVydraAsset,
|
||||
extractVydraResultUrls,
|
||||
resolveVydraBaseUrlFromConfig,
|
||||
resolveVydraErrorMessage,
|
||||
resolveCompletedVydraPayload,
|
||||
resolveVydraResponseJobId,
|
||||
resolveVydraResponseStatus,
|
||||
waitForVydraJob,
|
||||
resolveVydraRequestContext,
|
||||
} from "./shared.js";
|
||||
|
||||
const VYDRA_KLING_MODEL = "kling";
|
||||
@@ -80,29 +73,12 @@ export function buildVydraVideoGenerationProvider(): VideoGenerationProvider {
|
||||
throw new Error("Vydra video generation does not support video reference inputs.");
|
||||
}
|
||||
|
||||
const auth = await resolveApiKeyForProvider({
|
||||
provider: "vydra",
|
||||
cfg: req.cfg,
|
||||
agentDir: req.agentDir,
|
||||
store: req.authStore,
|
||||
});
|
||||
if (!auth.apiKey) {
|
||||
throw new Error("Vydra API key missing");
|
||||
}
|
||||
|
||||
const fetchFn = fetch;
|
||||
const { baseUrl, allowPrivateNetwork, headers, dispatcherPolicy } =
|
||||
resolveProviderHttpRequestConfig({
|
||||
baseUrl: resolveVydraBaseUrlFromConfig(req.cfg),
|
||||
defaultBaseUrl: DEFAULT_VYDRA_BASE_URL,
|
||||
allowPrivateNetwork: false,
|
||||
defaultHeaders: {
|
||||
Authorization: `Bearer ${auth.apiKey}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
provider: "vydra",
|
||||
const { fetchFn, baseUrl, allowPrivateNetwork, headers, dispatcherPolicy } =
|
||||
await resolveVydraRequestContext({
|
||||
cfg: req.cfg,
|
||||
agentDir: req.agentDir,
|
||||
authStore: req.authStore,
|
||||
capability: "video",
|
||||
transport: "http",
|
||||
});
|
||||
const { model, body } = resolveVydraVideoRequestBody(req);
|
||||
const { response, release } = await postJsonRequest({
|
||||
@@ -118,27 +94,15 @@ export function buildVydraVideoGenerationProvider(): VideoGenerationProvider {
|
||||
try {
|
||||
await assertOkOrThrowHttpError(response, "Vydra video generation failed");
|
||||
const submitted = await response.json();
|
||||
const completedPayload =
|
||||
resolveVydraResponseStatus(submitted) === "completed" ||
|
||||
extractVydraResultUrls(submitted, "video").length > 0
|
||||
? submitted
|
||||
: await (() => {
|
||||
const jobId = resolveVydraResponseJobId(submitted);
|
||||
if (!jobId) {
|
||||
throw new Error(
|
||||
resolveVydraErrorMessage(submitted) ??
|
||||
"Vydra video generation response missing job id",
|
||||
);
|
||||
}
|
||||
return waitForVydraJob({
|
||||
baseUrl,
|
||||
jobId,
|
||||
headers,
|
||||
timeoutMs: req.timeoutMs,
|
||||
fetchFn,
|
||||
kind: "video",
|
||||
});
|
||||
})();
|
||||
const completedPayload = await resolveCompletedVydraPayload({
|
||||
submitted,
|
||||
baseUrl,
|
||||
headers,
|
||||
timeoutMs: req.timeoutMs,
|
||||
fetchFn,
|
||||
kind: "video",
|
||||
missingJobIdMessage: "Vydra video generation response missing job id",
|
||||
});
|
||||
const videoUrl = extractVydraResultUrls(completedPayload, "video")[0];
|
||||
if (!videoUrl) {
|
||||
throw new Error("Vydra video generation completed without a video URL");
|
||||
|
||||
Reference in New Issue
Block a user