feat(edit): 编辑上报细节优化

This commit is contained in:
2026-10-06 18:30:05 +08:00
parent e20cd7547f
commit 79b310efe7
92 changed files with 2764 additions and 368 deletions
+70 -3
View File
@@ -3,7 +3,7 @@ import { test } from 'node:test';
import sharp from 'sharp';
import { GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';
import { createMediaAiEditRequestSchema } from '@atlas/contracts';
import { classifyAiEditFailure, normalizeAiEditOutput, pinnedLookup, providerImageResult, runMediaAiEdit } from '../src/media-ai-edit.ts';
import { classifyAiEditFailure, downloadProviderTaskImage, normalizeAiEditOutput, pinnedLookup, providerImageResult, runMediaAiEdit } from '../src/media-ai-edit.ts';
import { buildMediaAiPrompt } from '../src/media-ai-prompt.ts';
const productId = '733d0d73-3d39-4a98-ac0a-5c0e521d8998';
@@ -57,7 +57,60 @@ test('固定 DNS 回调按 Node 的 all 选项返回地址列表或单个地址'
});
});
test('异步供应商任务分两次 Outbox 推进,并把结果登记为独立素材', async () => {
test('同源 Pcore 任务取图使用配置地址,不发送密钥且禁止重定向', async () => {
const oldFetch = globalThis.fetch;
const oldBase = process.env.PCORE_BASE_URL;
const oldKey = process.env.PCORE_API_KEY;
process.env.PCORE_BASE_URL = 'https://pcore.ai';
process.env.PCORE_API_KEY = 'test-key';
let requests = 0;
globalThis.fetch = async (url, init) => {
requests += 1;
assert.equal(url, 'https://pcore.ai/v1/images/content/provider-123/0');
assert.equal(init.redirect, 'error');
assert.equal(init.headers, undefined);
assert.ok(init.signal);
return new Response('image');
};
try {
assert.deepEqual(await downloadProviderTaskImage('https://pcore.ai/v1/images/content/provider-123/0', 'provider-123'), Buffer.from('image'));
for (const url of [
'https://pcore.ai/v1/images/content/another-task/0',
'https://pcore.ai/v1/images/content/provider-123/1',
'https://pcore.ai/v1/images/content/provider-123%2F0/0',
'https://pcore.ai/v1/images/content/provider-123/0?url=http://localhost',
'https://pcore.ai/v1/images/content/provider-123/0#fragment',
'https://user:password@pcore.ai/v1/images/content/provider-123/0',
'https://pcore.ai/v1/images/edits/provider-123',
'https://127.0.0.1/v1/images/content/provider-123/0',
'http://pcore.ai/v1/images/content/provider-123/0',
]) await assert.rejects(downloadProviderTaskImage(url, 'provider-123'), /结果地址不安全/);
assert.equal(requests, 1, '非当前任务或非安全地址不能进入供应商内容请求');
await assert.rejects(downloadProviderTaskImage('https://pcore.ai/v1/images/content/../0', '..'), /结果地址不安全/);
globalThis.fetch = async () => new Response(null, { status: 302, headers: { Location: 'https://127.0.0.1/' } });
await assert.rejects(downloadProviderTaskImage('https://pcore.ai/v1/images/content/provider-123/0', 'provider-123'), /HTTP 302/);
globalThis.fetch = async () => new Response('oversize', { headers: { 'Content-Length': String(26 * 1024 * 1024) } });
await assert.rejects(downloadProviderTaskImage('https://pcore.ai/v1/images/content/provider-123/0', 'provider-123'), /超过处理上限/);
globalThis.fetch = async () => new Response(new ReadableStream({ start(controller) {
controller.enqueue(new Uint8Array(25 * 1024 * 1024));
controller.enqueue(new Uint8Array(1));
controller.close();
} }));
await assert.rejects(downloadProviderTaskImage('https://pcore.ai/v1/images/content/provider-123/0', 'provider-123'), /超过处理上限/);
globalThis.fetch = async () => { throw new TypeError('fetch failed'); };
await assert.rejects(downloadProviderTaskImage('https://pcore.ai/v1/images/content/provider-123/0', 'provider-123'), (error) => {
assert.equal(classifyAiEditFailure(error).source, 'pcore');
assert.equal(error.message, 'Pcore 结果下载连接失败');
return true;
});
} finally {
globalThis.fetch = oldFetch;
if (oldBase === undefined) delete process.env.PCORE_BASE_URL; else process.env.PCORE_BASE_URL = oldBase;
if (oldKey === undefined) delete process.env.PCORE_API_KEY; else process.env.PCORE_API_KEY = oldKey;
}
});
test('异步供应商任务登记独立素材,完成结果兼容 base64 和同源图片接口', async () => {
const sourceId = '664d0d73-3d39-4a98-ac0a-5c0e521d8998';
const referenceId = '6ebfe347-bc77-4270-8213-b2021271c6b2';
const outputId = '113d0d73-3d39-4a98-ac0a-5c0e521d8998';
@@ -101,6 +154,7 @@ test('异步供应商任务分两次 Outbox 推进,并把结果登记为独立
process.env.PCORE_BASE_URL = 'https://pcore.ai/v1';
process.env.PCORE_API_KEY = 'test-key';
let requests = 0;
let useContentUrl = false;
globalThis.fetch = async (url, init) => {
requests += 1;
if (init.method === 'POST') {
@@ -119,8 +173,15 @@ test('异步供应商任务分两次 Outbox 推进,并把结果登记为独立
assert.equal(body.mask, undefined);
return Response.json({ task_id: 'provider-123' });
}
if (url === 'https://pcore.ai/v1/images/content/provider-123/0') {
assert.equal(init.headers, undefined);
assert.equal(init.redirect, 'error');
return new Response(generated);
}
assert.equal(url, 'https://pcore.ai/v1/images/edits/provider-123');
return Response.json({ status: 'completed', data: [{ b64_json: generated.toString('base64') }] });
return Response.json({ status: 'completed', data: [useContentUrl
? { b64_json: '', url: 'https://pcore.ai/v1/images/content/provider-123/0' }
: { b64_json: generated.toString('base64') }] });
};
try {
const job = { workspaceId: '30cf54b7-06a3-4e5f-a5fc-d74165115094', payload: { edit_id: editId } };
@@ -133,6 +194,12 @@ test('异步供应商任务分两次 Outbox 推进,并把结果登记为独立
assert.equal(stored.length, 1);
assert.equal(stored[0].ContentType, 'image/jpeg');
assert.equal(requests, 2);
task.status = 'running';
useContentUrl = true;
await runMediaAiEdit(database, storage, job);
assert.equal(task.status, 'succeeded');
assert.equal(stored.length, 2);
assert.equal(requests, 4, '已保存任务只查询状态和取图,不重新提交生成');
} finally {
globalThis.fetch = oldFetch;
if (oldBase === undefined) delete process.env.PCORE_BASE_URL; else process.env.PCORE_BASE_URL = oldBase;