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]); }); } }