134 lines
6.0 KiB
JavaScript
134 lines
6.0 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
|
|
const repoRoot = path.resolve(import.meta.dirname, '..');
|
|
|
|
const {
|
|
YUANJIE_IMAGE_MODEL_TEMPLATES,
|
|
buildYuanjieSubmit,
|
|
} = await import('../src/lib/yuanjie-image-model-templates.ts');
|
|
const {
|
|
YUANJIE_VIDEO_MODEL_TEMPLATES,
|
|
buildYuanjieVideoSubmit,
|
|
} = await import('../src/lib/yuanjie-video-model-templates.ts');
|
|
const {
|
|
getYuanjieSystemApiCapabilitiesFallback,
|
|
} = await import('../src/lib/yuanjie-system-manifest.ts');
|
|
|
|
async function runTest(name, fn) {
|
|
try {
|
|
await fn();
|
|
console.log(`PASS ${name}`);
|
|
} catch (error) {
|
|
console.error(`FAIL ${name}`);
|
|
console.error(error);
|
|
process.exitCode = 1;
|
|
}
|
|
}
|
|
|
|
function read(relativePath) {
|
|
return fs.readFileSync(path.join(repoRoot, relativePath), 'utf8');
|
|
}
|
|
|
|
function imageTemplate(modelName) {
|
|
const template = YUANJIE_IMAGE_MODEL_TEMPLATES.find(item => item.modelName === modelName);
|
|
assert.ok(template, `missing image template ${modelName}`);
|
|
return buildYuanjieSubmit(template);
|
|
}
|
|
|
|
function videoTemplate(modelName) {
|
|
const template = YUANJIE_VIDEO_MODEL_TEMPLATES.find(item => item.modelName === modelName);
|
|
assert.ok(template, `missing video template ${modelName}`);
|
|
return buildYuanjieVideoSubmit(template);
|
|
}
|
|
|
|
await runTest('image-to-image route passes all reference images into Manifest execution', () => {
|
|
const source = read('src/app/api/generate/image/route.ts');
|
|
|
|
assert.match(source, /extraImages/);
|
|
assert.match(source, /const referenceImages = normalizeReferenceImages\(image,\s*undefined,\s*extraImages\)/s);
|
|
assert.match(source, /inputImages:\s*referenceImages,/);
|
|
assert.doesNotMatch(source, /inputImages:\s*image \? \[image\] : \[\]/);
|
|
});
|
|
|
|
await runTest('yuanjie GPT Image 2 uses public image reference URLs for edit/image-to-image', () => {
|
|
const submit = imageTemplate('gpt-image-2');
|
|
assert.equal(submit.body?.params?.images, '$inputImages.urls');
|
|
assert.equal(submit.body?.images, '$inputImages.urls');
|
|
assert.equal(submit.body?.base64Array, '$inputImages.urls');
|
|
});
|
|
|
|
await runTest('manifest executor exposes normalized public input image URLs to templates', () => {
|
|
const source = read('src/lib/user-api-manifest-executor.ts');
|
|
|
|
assert.match(source, /inputImageUrls\?: string\[\]/);
|
|
assert.match(source, /inputImages:\s*\{\s*dataUrls:\s*input\.inputImages \|\| \[\],\s*urls:\s*input\.inputImageUrls \|\| input\.inputImages \|\| \[\],/s);
|
|
assert.match(source, /resolveManifestInputImageReferences\(input\.inputImages \|\| \[\]\)/);
|
|
});
|
|
|
|
await runTest('yuanjie video templates map documented reference fields and mode fields', () => {
|
|
assert.equal(videoTemplate('sora-2').body?.params?.input_reference, '$inputImages.urls.0');
|
|
assert.equal(videoTemplate('wan2.6-cankaosheng').body?.params?.reference_urls, '$inputImages.urls');
|
|
assert.equal(videoTemplate('wan2.6-shouzheng').body?.params?.img_url, '$inputImages.urls.0');
|
|
assert.equal(videoTemplate('kling-v3-omni-shouweizhen').body?.params?.image, '$inputImages.urls.0');
|
|
assert.equal(videoTemplate('kling-v3-omni-shouweizhen').body?.params?.image_tail, '$inputImages.urls.1');
|
|
assert.equal(videoTemplate('happyhorse-r2v').body?.params?.ratio, '$params.aspect_ratio');
|
|
assert.equal(videoTemplate('grok-video-3').body?.params?.size, '$params.resolution');
|
|
assert.equal(videoTemplate('veo3.1').body?.params?.generation_mode, '$params.quality');
|
|
assert.equal(videoTemplate('veo3.1').body?.params?.enhance_prompt, true);
|
|
assert.equal(videoTemplate('veo3.1').body?.params?.enable_upsample, false);
|
|
});
|
|
|
|
await runTest('yuanjie HappyHorse text-to-video uses documented media params and output task id path', () => {
|
|
const submit = videoTemplate('happyhorse-t2v');
|
|
const bodyKeys = Object.keys(submit.body || {}).sort();
|
|
assert.deepEqual(bodyKeys, ['model', 'params', 'prompt']);
|
|
assert.equal(submit.body?.model, '$profile.model');
|
|
assert.equal(submit.body?.prompt, '$prompt');
|
|
assert.equal(submit.body?.params?.resolution, '$params.resolution');
|
|
assert.equal(submit.body?.params?.ratio, '$params.aspect_ratio');
|
|
assert.equal(submit.body?.params?.duration, '$params.duration');
|
|
assert.equal(submit.body?.params?.aspect_ratio, undefined);
|
|
assert.deepEqual(Object.keys(submit.body?.params || {}).sort(), ['duration', 'ratio', 'resolution']);
|
|
assert.match(submit.taskIdPath || '', /output\.task_id/);
|
|
});
|
|
|
|
await runTest('yuanjie system API rows without manifest still expose built-in video capabilities', () => {
|
|
const capabilities = getYuanjieSystemApiCapabilitiesFallback({
|
|
provider: '元界 AI',
|
|
type: 'video',
|
|
model_name: 'happyhorse-t2v',
|
|
model_group: 'default',
|
|
});
|
|
assert.ok(capabilities, 'expected built-in capabilities for HappyHorse text-to-video');
|
|
assert.deepEqual(capabilities.resolutions?.map(item => item.value), ['720P', '1080P']);
|
|
assert.deepEqual(capabilities.aspectRatios?.map(item => item.value), ['16:9', '9:16', '1:1', '4:3', '3:4']);
|
|
assert.deepEqual(capabilities.durations?.map(item => item.value), ['3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15']);
|
|
|
|
const mozheCapabilities = getYuanjieSystemApiCapabilitiesFallback({
|
|
provider: 'mozheAPI',
|
|
type: 'video',
|
|
model_name: 'happyhorse-t2v',
|
|
model_group: 'default',
|
|
});
|
|
assert.equal(mozheCapabilities, undefined);
|
|
});
|
|
|
|
await runTest('system default polling candidates repair stale yuanjie manifests before generation', () => {
|
|
const source = read('src/lib/server-api-config.ts');
|
|
const pollingFunction = source.match(/export async function resolveSystemApiPollingCandidates[\s\S]*?^}/m)?.[0] || '';
|
|
|
|
assert.match(pollingFunction, /ensureYuanjieSystemApiManifest\(client,\s*row\)/);
|
|
assert.match(pollingFunction, /yuanjieManifest\?\.manifestPath/);
|
|
assert.match(pollingFunction, /yuanjieManifest\?\.apiUrl/);
|
|
});
|
|
|
|
await runTest('video route passes negative prompt through Manifest params for providers that document it', () => {
|
|
const source = read('src/app/api/generate/video/route.ts');
|
|
|
|
assert.match(source, /negative_prompt:\s*negativePrompt,/);
|
|
});
|
|
|
|
if (process.exitCode) process.exit(process.exitCode);
|