feat: bootstrap commercial AI drama platform
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { createServer } from "node:http";
|
||||
import { withTransaction, dbRun } from "../server/db.mjs";
|
||||
|
||||
const api = process.env.AI_DRAMA_API_BASE || "http://127.0.0.1:8787";
|
||||
const runnerPort = Number(process.env.AI_DRAMA_SMOKE_MODEL_PORT || 8792);
|
||||
const scope = {
|
||||
"x-organization-id": "org-studio-lab",
|
||||
"x-workspace-id": "ws-local-aidrama",
|
||||
"x-project-id": "thunder-mouth"
|
||||
};
|
||||
|
||||
async function request(path, headers = {}, options = {}) {
|
||||
const response = await fetch(`${api}${path}`, {
|
||||
...options,
|
||||
headers: { "content-type": "application/json", ...headers, ...(options.headers || {}) }
|
||||
});
|
||||
const payload = await response.json().catch(() => ({}));
|
||||
return { response, payload };
|
||||
}
|
||||
|
||||
async function login(email) {
|
||||
const result = await request("/api/auth/login", {}, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ email, password: "Demo@123456" })
|
||||
});
|
||||
assert.equal(result.response.ok, true, `${email} 登录失败`);
|
||||
return { authorization: `Bearer ${result.payload.session.token}` };
|
||||
}
|
||||
|
||||
const runner = createServer((req, res) => {
|
||||
if (req.url === "/v1/health") {
|
||||
res.writeHead(200, { "content-type": "application/json" });
|
||||
res.end(JSON.stringify({ status: "ok" }));
|
||||
return;
|
||||
}
|
||||
res.writeHead(404, { "content-type": "application/json" });
|
||||
res.end(JSON.stringify({ error: "not_found" }));
|
||||
});
|
||||
|
||||
await new Promise((resolve) => runner.listen(runnerPort, "127.0.0.1", resolve));
|
||||
let modelId = "";
|
||||
try {
|
||||
const owner = { ...(await login("producer@local.test")), ...scope };
|
||||
const writer = { ...(await login("writer@local.test")), ...scope };
|
||||
|
||||
const writerModels = await request("/api/platform/models", writer);
|
||||
assert.equal(writerModels.response.status, 403, "普通用户不应访问模型中台");
|
||||
|
||||
const publicLocal = await request("/api/platform/models/register", owner, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ label: "smoke invalid local", endpoint: "https://example.com/v1", kind: "http-json", capability: ["image"], costMode: "local" })
|
||||
});
|
||||
assert.equal(publicLocal.response.status, 403, "local 连接器指向公网时必须被拒绝");
|
||||
assert.equal(publicLocal.payload.error, "local_only_endpoint_required", "local 公网地址错误码不正确");
|
||||
|
||||
const externalWithoutApproval = await request("/api/platform/models/register", owner, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ label: "smoke invalid external", endpoint: "https://example.com/v1", kind: "openai-compatible", capability: ["image"], costMode: "mixed", approvalRequired: false })
|
||||
});
|
||||
assert.equal(externalWithoutApproval.response.status, 400, "混合连接器未开启审批时必须被拒绝");
|
||||
assert.equal(externalWithoutApproval.payload.error, "external_connector_approval_required", "外部审批错误码不正确");
|
||||
|
||||
const created = await request("/api/platform/models/register", owner, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
label: `Smoke Editable Runner ${Date.now()}`,
|
||||
endpoint: `http://127.0.0.1:${runnerPort}/v1`,
|
||||
kind: "http-json",
|
||||
capability: ["text-to-image", "single-frame"],
|
||||
costMode: "local",
|
||||
protocol: { healthRoute: "health" }
|
||||
})
|
||||
});
|
||||
assert.equal(created.response.status, 201, "本地自定义 Runner 注册失败");
|
||||
modelId = created.payload.model.id;
|
||||
assert.equal(created.payload.model.approvalRequired, false, "本地连接器不应被强制标记为外部审批");
|
||||
|
||||
const edited = await request(`/api/platform/models/${encodeURIComponent(modelId)}`, owner, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify({ label: "Smoke Edited Local Runner", capability: ["text-to-image", "single-frame", "continuity-lock"], protocol: { healthRoute: "health" } })
|
||||
});
|
||||
assert.equal(edited.response.ok, true, "本地连接器编辑失败");
|
||||
assert.equal(edited.payload.model.label, "Smoke Edited Local Runner", "连接器名称编辑未保存");
|
||||
assert.ok(edited.payload.model.capability.includes("continuity-lock"), "连接器能力标签编辑未保存");
|
||||
|
||||
const invalidEditEndpoint = await request(`/api/platform/models/${encodeURIComponent(modelId)}`, owner, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify({ endpoint: "https://example.com/v1", costMode: "local" })
|
||||
});
|
||||
assert.equal(invalidEditEndpoint.response.status, 403, "编辑时 local 公网地址必须被拒绝");
|
||||
|
||||
const invalidEditApproval = await request(`/api/platform/models/${encodeURIComponent(modelId)}`, owner, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify({ endpoint: "https://example.com/v1", costMode: "mixed", approvalRequired: false })
|
||||
});
|
||||
assert.equal(invalidEditApproval.response.status, 400, "编辑时 mixed 未审批必须被拒绝");
|
||||
|
||||
const probed = await request(`/api/platform/models/${encodeURIComponent(modelId)}/probe`, owner, { method: "POST", body: "{}" });
|
||||
assert.equal(probed.response.ok, true, `本地连接器探活失败:${JSON.stringify(probed.payload)}`);
|
||||
assert.equal(probed.payload.model.status, "ready", "本地连接器探活后必须进入 ready");
|
||||
|
||||
console.log(`model connector smoke passed: RBAC, local-only, approval gate, edit, probe (${modelId})`);
|
||||
} finally {
|
||||
await new Promise((resolve) => runner.close(resolve));
|
||||
if (modelId) {
|
||||
withTransaction(() => {
|
||||
dbRun("DELETE FROM model_connectors WHERE id = ?", [modelId]);
|
||||
dbRun("DELETE FROM audit_logs WHERE target_id = ?", [modelId]);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user