Files
memind/mindspace-image-generation.mjs
T

80 lines
2.6 KiB
JavaScript

import crypto from 'node:crypto';
const PURPOSES = {
inline_image: { presetId: 'memind_square_illustration', filename: 'inline-image.webp' },
hero: { presetId: 'memind_dark_hero', filename: 'hero.webp' },
card_cover: { presetId: 'memind_card_cover', filename: 'card-cover.webp' },
feed_cover: { presetId: 'memind_feed_cover_source', filename: 'feed-cover.webp' },
};
export function createMindSpaceImageGenerationService({
configService,
assetService,
imageMakeClient,
logger = console,
} = {}) {
async function generate({
userId,
purpose,
prompt,
negativePrompt = '',
consumerRef = '',
idempotencyKey,
} = {}) {
const spec = PURPOSES[purpose];
if (!spec) {
return { ok: false, fallback: true, code: 'unsupported_purpose', message: '不支持的图片生成用途' };
}
if (!configService?.resolveImageGenerationPurpose) {
return { ok: false, fallback: true, code: 'gateway_unavailable', message: '图片生成能力未启用' };
}
const gate = await configService.resolveImageGenerationPurpose(purpose);
if (!gate.ok) return { ...gate, fallback: true };
if (!imageMakeClient || !assetService?.createChatAsset) {
return { ok: false, fallback: true, code: 'runtime_unavailable', message: '图片生成服务未配置' };
}
try {
const generated = await imageMakeClient.generateImage({
prompt,
negativePrompt,
presetId: gate.presetId ?? spec.presetId,
consumerRef,
idempotencyKey: idempotencyKey || `imgreq_${crypto.randomUUID()}`,
});
const asset = await assetService.createChatAsset(userId, {
categoryCode: 'public',
buffer: generated.buffer,
filename: spec.filename,
displayName: spec.filename,
sourceType: 'image_make',
});
await imageMakeClient.acknowledge(generated.jobId, asset.id).catch((error) => {
logger.warn?.('[image_make] acknowledge failed; TTL cleanup will apply:', error?.message ?? error);
});
return {
ok: true,
purpose,
jobId: generated.jobId,
asset,
source: {
mimeType: generated.mimeType,
width: generated.width,
height: generated.height,
sha256: generated.sha256,
},
};
} catch (error) {
logger.warn?.('[image_make] generation failed; existing flow remains active:', error?.message ?? error);
return {
ok: false,
fallback: true,
code: error?.code ?? 'image_make_unavailable',
message: '图片生成暂不可用,已保留原有流程',
};
}
}
return { purposes: Object.keys(PURPOSES), generate };
}