Files
NianAIGC/lib/volcengine/visual-client.ts
2026-05-29 10:26:02 +08:00

85 lines
2.8 KiB
TypeScript

import type { VisualTaskQueryResponse, VisualTaskSubmitResponse } from "@/lib/types";
import { signVolcengineRequest } from "@/lib/volcengine/signature";
export type VisualClientConfig = {
accessKeyId: string;
secretAccessKey: string;
region: string;
service: string;
endpoint: string;
};
export function getVisualClientConfig(): VisualClientConfig | null {
const accessKeyId = process.env.VOLCENGINE_ACCESS_KEY_ID;
const secretAccessKey = process.env.VOLCENGINE_SECRET_ACCESS_KEY;
if (!accessKeyId || !secretAccessKey) return null;
return {
accessKeyId,
secretAccessKey,
region: process.env.VOLCENGINE_REGION || "cn-north-1",
service: process.env.VOLCENGINE_SERVICE || "cv",
endpoint: process.env.VOLCENGINE_VISUAL_ENDPOINT || "https://visual.volcengineapi.com"
};
}
export function shouldMockVisualApi(): boolean {
const flag = process.env.JIMENG_VISUAL_MOCK || "auto";
if (flag === "1" || flag === "true") return true;
if (flag === "0" || flag === "false") return false;
return getVisualClientConfig() === null;
}
export async function submitVisualTask(
payload: Record<string, unknown>,
config = getVisualClientConfig()
): Promise<VisualTaskSubmitResponse> {
if (!config) throw new Error("Volcengine Visual credentials are not configured.");
return callVisualApi<VisualTaskSubmitResponse>("CVSync2AsyncSubmitTask", payload, config);
}
export async function queryVisualTask(
payload: Record<string, unknown>,
config = getVisualClientConfig()
): Promise<VisualTaskQueryResponse> {
if (!config) throw new Error("Volcengine Visual credentials are not configured.");
return callVisualApi<VisualTaskQueryResponse>("CVSync2AsyncGetResult", payload, config);
}
async function callVisualApi<T>(
action: "CVSync2AsyncSubmitTask" | "CVSync2AsyncGetResult",
payload: Record<string, unknown>,
config: VisualClientConfig
): Promise<T> {
const body = JSON.stringify(payload);
const signed = signVolcengineRequest({
method: "POST",
endpoint: config.endpoint,
query: {
Action: action,
Version: "2022-08-31"
},
body,
accessKeyId: config.accessKeyId,
secretAccessKey: config.secretAccessKey,
region: config.region,
service: config.service
});
const response = await fetch(signed.url, {
method: "POST",
headers: signed.headers,
body
});
const text = await response.text();
let json: unknown;
try {
json = JSON.parse(text);
} catch {
throw new Error(`Volcengine Visual returned non-JSON response: ${response.status} ${text.slice(0, 240)}`);
}
if (!response.ok) {
const message = typeof json === "object" && json && "message" in json ? String(json.message) : text;
throw new Error(`Volcengine Visual HTTP ${response.status}: ${message}`);
}
return json as T;
}