feat: bootstrap commercial AI drama platform
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { createServer } from "node:http";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { mkdir, rm } from "node:fs/promises";
|
||||
import { resolve } from "node:path";
|
||||
import { dbGet, dbRun } from "../server/db.mjs";
|
||||
|
||||
const api = process.env.AI_DRAMA_API_BASE || "http://127.0.0.1:8787";
|
||||
const projectRoot = resolve(import.meta.dirname, "..");
|
||||
const scope = { "x-organization-id": "org-studio-lab", "x-workspace-id": "ws-local-aidrama", "x-project-id": "thunder-mouth" };
|
||||
const fixtureRelative = "storage/jobs/api-media-smoke/fixture.mp4";
|
||||
const fixtureAbsolute = resolve(projectRoot, fixtureRelative);
|
||||
|
||||
async function request(path, options = {}) {
|
||||
const response = await fetch(`${api}${path}`, { ...options, headers: { "content-type": "application/json", ...(options.headers || {}) } });
|
||||
const payload = await response.json().catch(() => ({}));
|
||||
return { response, payload };
|
||||
}
|
||||
|
||||
const login = await request("/api/auth/login", { method: "POST", body: JSON.stringify({ email: "producer@local.test", password: "Demo@123456" }) });
|
||||
assert.equal(login.response.ok, true, "media API smoke login must pass");
|
||||
const headers = { authorization: `Bearer ${login.payload.session.token}`, ...scope };
|
||||
const connector = dbGet("SELECT * FROM model_connectors WHERE id = 'owned-i2v'");
|
||||
const originalConnector = { endpoint: connector.endpoint, status: connector.status, errorMessage: connector.error_message };
|
||||
const server = createServer(async (req, res) => {
|
||||
if (req.method !== "POST") { res.writeHead(405); res.end(); return; }
|
||||
const jobId = req.headers["x-ai-drama-job-id"];
|
||||
assert.ok(jobId, "adapter request must carry job id");
|
||||
const outputRelative = `storage/jobs/${jobId}/output.mp4`;
|
||||
await mkdir(resolve(projectRoot, `storage/jobs/${jobId}`), { recursive: true });
|
||||
execFileSync("cp", [fixtureAbsolute, resolve(projectRoot, outputRelative)]);
|
||||
res.writeHead(200, { "content-type": "application/json" });
|
||||
res.end(JSON.stringify({ outputPath: outputRelative, mimeType: "video/mp4", provider: "local-smoke" }));
|
||||
});
|
||||
await new Promise((resolveListen) => server.listen(0, "127.0.0.1", resolveListen));
|
||||
const address = server.address();
|
||||
const endpoint = `http://127.0.0.1:${address.port}/generate`;
|
||||
const createdJobIds = [];
|
||||
|
||||
try {
|
||||
await mkdir(resolve(projectRoot, "storage/jobs/api-media-smoke"), { recursive: true });
|
||||
execFileSync("ffmpeg", ["-y", "-v", "error", "-f", "lavfi", "-i", "color=c=0x8b3d59:s=320x568:d=1", "-c:v", "libx264", "-pix_fmt", "yuv420p", fixtureAbsolute], { stdio: "pipe" });
|
||||
dbRun("UPDATE model_connectors SET endpoint = ?, status = 'ready', error_message = '', updated_at = ? WHERE id = 'owned-i2v'", [endpoint, new Date().toISOString()]);
|
||||
const created = await request("/api/jobs", { method: "POST", headers, body: JSON.stringify({ adapter: "owned-i2v", kind: "视频片段", shotId: "shot-01", output: "storage/jobs/api-media-smoke/request-output.mp4" }) });
|
||||
assert.equal(created.response.ok, true, `job create failed: ${created.payload.detail || ""}`);
|
||||
const jobId = created.payload.job.id;
|
||||
createdJobIds.push(jobId);
|
||||
const run = await request(`/api/jobs/${encodeURIComponent(jobId)}/run`, { method: "POST", headers, body: "{}" });
|
||||
assert.equal(run.response.ok, true, `job run failed: ${run.payload.detail || ""}`);
|
||||
assert.equal(run.payload.job.status, "completed", "HTTP generation job must complete");
|
||||
assert.equal(run.payload.job.result.artifacts?.[0]?.status, "inspected", "completed job must return inspected media evidence");
|
||||
assert.ok(run.payload.job.result.artifacts?.[0]?.sha256, "completed job must return SHA-256 evidence");
|
||||
const artifacts = await request(`/api/production/media-artifacts?jobId=${encodeURIComponent(jobId)}`, { headers });
|
||||
assert.equal(artifacts.response.ok, true, "media artifact API must be readable");
|
||||
assert.equal(artifacts.payload.artifacts?.[0]?.job_id, jobId, "artifact must be linked to the generation job");
|
||||
console.log(`api media smoke passed: ${jobId} -> ${artifacts.payload.artifacts[0].last_frame_path}`);
|
||||
} finally {
|
||||
for (const jobId of createdJobIds) {
|
||||
dbRun("DELETE FROM media_artifacts WHERE job_id = ?", [jobId]);
|
||||
dbRun("DELETE FROM generation_jobs WHERE id = ?", [jobId]);
|
||||
await rm(resolve(projectRoot, `storage/jobs/${jobId}`), { recursive: true, force: true });
|
||||
}
|
||||
dbRun("UPDATE model_connectors SET endpoint = ?, status = ?, error_message = ?, updated_at = ? WHERE id = 'owned-i2v'", [originalConnector.endpoint, originalConnector.status, originalConnector.errorMessage, new Date().toISOString()]);
|
||||
await new Promise((resolveClose) => server.close(resolveClose));
|
||||
await rm(resolve(projectRoot, "storage/jobs/api-media-smoke"), { recursive: true, force: true });
|
||||
}
|
||||
Reference in New Issue
Block a user