production runtime and mock removal

This commit is contained in:
inman committed 2026-08-17 23:44:14 +08:00
1 parent 2ef3da7af5
commit 6480e503eb
55 files changed
+581 -540

No files matched your search

+23 -53
View File
@@ -8,11 +8,11 @@ import {
buildEvolinkImagePayload,
extractEvolinkResultUrls,
getEffectiveImageEngine,
getEvolinkImageConfig,
getEvolinkImageSettings,
getEvolinkTaskId,
mapEvolinkStatus,
queryEvolinkTask,
shouldMockEvolinkApi,
submitEvolinkImageTask,
type ImageCreationEngine,
type EvolinkTaskResponse
@@ -24,11 +24,10 @@ import {
updateGenerationJob
} from "@/lib/server/data-store";
import { chargeGenerationJob, quoteGenerationCharge } from "@/lib/server/billing-service";
import { createMockImageBuffer } from "@/lib/server/mock-image";
import { importRemoteImageAsAsset, saveGeneratedAsset } from "@/lib/server/storage";
import { importRemoteImageAsAsset } from "@/lib/server/storage";
import { DEFAULT_OWNER_ID, toAbsoluteUrl } from "@/lib/server/runtime";
import type { BillingJobCharge, EnabledImageCapability, GenerationJob, UsageContext, VisualTaskQueryResponse } from "@/lib/types";
import { queryVisualTask, shouldMockVisualApi, submitVisualTask } from "@/lib/volcengine/visual-client";
import { getVisualClientConfig, queryVisualTask, submitVisualTask } from "@/lib/volcengine/visual-client";
import {
bailianResultUrls,
bailianStatus,
@@ -36,7 +35,6 @@ import {
buildBailianImagePayload,
getBailianConfig,
queryBailianTask,
shouldMockBailian,
submitBailianTask
} from "@/lib/bailian/client";
@@ -69,15 +67,15 @@ type PreparedImageGeneration = {
normalizedUrls: string[];
engine: ImageCreationEngine;
providerPayload: Record<string, unknown>;
missingBailianKey: boolean;
provider: "mock" | "bailian" | "evolink" | "volcengine-visual";
missingProviderCredentials: boolean;
provider: "bailian" | "evolink" | "volcengine-visual";
reqKey: string;
requestPayload: Record<string, unknown>;
};
export async function quoteImageGeneration(input: SubmitImageJobInput, origin: string): Promise<BillingJobCharge | undefined> {
const prepared = prepareImageGeneration(input, origin);
if (prepared.missingBailianKey) return undefined;
if (prepared.missingProviderCredentials) return undefined;
return quoteGenerationCharge({
provider: prepared.provider,
capability: input.capability,
@@ -91,8 +89,8 @@ export async function quoteImageGeneration(input: SubmitImageJobInput, origin: s
export async function submitImageJob(input: SubmitImageJobInput, origin: string): Promise<GenerationJob> {
const prepared = prepareImageGeneration(input, origin);
const { ownerId, normalizedUrls, providerPayload, missingBailianKey, provider, reqKey, requestPayload } = prepared;
const billing = missingBailianKey ? undefined : await quoteGenerationCharge({
const { ownerId, normalizedUrls, providerPayload, missingProviderCredentials, engine, provider, reqKey, requestPayload } = prepared;
const billing = missingProviderCredentials ? undefined : await quoteGenerationCharge({
provider,
capability: input.capability,
reqKey,
@@ -106,13 +104,13 @@ export async function submitImageJob(input: SubmitImageJobInput, origin: string)
capability: input.capability,
provider,
reqKey,
status: missingBailianKey ? "failed" : "queued",
status: missingProviderCredentials ? "failed" : "queued",
prompt: input.prompt,
inputAssetIds: input.inputAssetIds || [],
inputUrls: normalizedUrls,
outputAssetIds: [],
requestPayload,
error: missingBailianKey ? { message: "缺少 BAILIAN_API_KEY,请先在设置页配置阿里云百炼 API Key。", retryable: true } : undefined,
error: missingProviderCredentials ? { message: missingProviderMessage(engine), retryable: true } : undefined,
retryOf: input.retryOf,
idempotencyKey: input.idempotencyKey,
idempotencyFingerprint: input.idempotencyFingerprint,
@@ -149,16 +147,25 @@ function prepareImageGeneration(input: SubmitImageJobInput, origin: string): Pre
? buildEvolinkImagePayload(input.capability, { ...input, imageUrls: normalizedUrls })
: buildJimengPayload(input.capability, capability.reqKey, { ...input, imageUrls: normalizedUrls });
const bailianConfig = getBailianConfig();
const mock = engine === "bailian" ? shouldMockBailian() : engine === "evolink" ? shouldMockEvolinkApi() : shouldMockVisualApi();
const missingBailianKey = engine === "bailian" && !mock && !bailianConfig.apiKey;
const missingProviderCredentials = engine === "bailian"
? !bailianConfig.apiKey
: engine === "evolink"
? !getEvolinkImageConfig()
: !getVisualClientConfig();
const reqKey = engine === "bailian" ? bailianConfig.imageModel : engine === "evolink" ? getEvolinkImageSettings().model : capability.reqKey;
const provider = mock ? "mock" : engine === "bailian" ? "bailian" : engine === "evolink" ? "evolink" : "volcengine-visual";
const provider = engine === "bailian" ? "bailian" : engine === "evolink" ? "evolink" : "volcengine-visual";
const requestPayload = {
engine,
input,
providerPayload
};
return { ownerId, normalizedUrls, engine, providerPayload, missingBailianKey, provider, reqKey, requestPayload };
return { ownerId, normalizedUrls, engine, providerPayload, missingProviderCredentials, provider, reqKey, requestPayload };
}
function missingProviderMessage(engine: ImageCreationEngine) {
if (engine === "bailian") return "缺少 BAILIAN_API_KEY 或 DASHSCOPE_API_KEY,请先配置阿里云百炼凭据。";
if (engine === "evolink") return "缺少 EVOLINK_API_KEY,请先配置 EvoLink 凭据。";
return "缺少 VOLCENGINE_ACCESS_KEY_ID 或 VOLCENGINE_SECRET_ACCESS_KEY,请先配置即梦凭据。";
}
export async function advanceImageJob(jobId: string, origin: string): Promise<GenerationJob> {
@@ -166,7 +173,6 @@ export async function advanceImageJob(jobId: string, origin: string): Promise<Ge
if (!job) throw new Error(`Generation job not found: ${jobId}`);
if (["succeeded", "failed", "expired", "cancelled"].includes(job.status)) return job;
if (job.billing?.status === "pending") job = await chargeGenerationJob(job);
if (job.provider === "mock") return completeMockJob(job, origin);
if (!job.providerTaskId) return dispatchImageJob(job);
return syncImageJob(job.id, origin);
}
@@ -235,7 +241,6 @@ export async function syncImageJob(jobId: string, origin: string): Promise<Gener
const job = await getGenerationJob(jobId);
if (!job) throw new Error(`Generation job not found: ${jobId}`);
if (["succeeded", "failed", "expired", "cancelled"].includes(job.status)) return job;
if (job.provider === "mock") return completeMockJob(job, origin);
if (!job.providerTaskId) return job;
if (job.provider === "evolink") {
@@ -427,41 +432,6 @@ export async function retryImageJob(
}, origin);
}
async function completeMockJob(job: GenerationJob, origin: string): Promise<GenerationJob> {
if (job.status === "succeeded" && job.outputAssetIds.length > 0) return job;
const requestInput = (job.requestPayload.input || {}) as SubmitImageJobInput;
const buffer = createMockImageBuffer({
title: "智念AIGC生成结果",
prompt: job.prompt || requestInput.prompt,
capability: job.capability
});
const asset = await saveGeneratedAsset({
ownerId: job.ownerId,
bytes: buffer,
fileName: `${job.capability.replace(/\W+/g, "-")}-${job.id}.svg`,
contentType: "image/svg+xml",
origin,
source: sourceForCapability(job.capability),
capability: job.capability,
jobId: job.id,
tags: assetTagsForJob(job),
metadata: {
mock: true
}
});
return updateGenerationJob(job.id, {
status: "succeeded",
outputAssetIds: [asset.id],
responsePayload: {
mock: true,
data: {
status: "done",
image_urls: [asset.url]
}
}
});
}
function sourceForCapability(_capability: string): "generated" {
return "generated";
}