Files
mnote/scripts/lib/control-plane-dev-seed.js
T

251 lines
7.0 KiB
JavaScript

"use strict";
const assert = require("node:assert/strict");
async function postDevSeed(requestContext, baseUrl, seeds, timeoutMs) {
const normalizedBaseUrl = baseUrl.replace(/\/+$/, "");
const response = await requestContext.fetch(`${normalizedBaseUrl}/api/dev/seed`, {
method: "POST",
headers: { "content-type": "application/json" },
data: { seeds },
timeout: timeoutMs,
});
const text = await response.text();
let payload = null;
try {
payload = text ? JSON.parse(text) : null;
} catch {
payload = text;
}
if (!response.ok()) {
const details = typeof payload === "string" ? payload : JSON.stringify(payload);
if (response.status() === 403 && payload && payload.code === "dev_seed_disabled") {
throw new Error(
[
`/api/dev/seed 未启用(base=${normalizedBaseUrl})。`,
"依赖 seed 的 smoke 必须使用 `npm run dev:hot` 启动;dev:hot 默认开启 MNOTE_WEB_ALLOW_DEV_FIXTURES=1。",
"若复用 desktop:hot,请使用 `MNOTE_WEB_ALLOW_DEV_FIXTURES=1 npm run desktop:hot`。",
"修改 scripts/dev-hot.js 或启动环境后必须重启 dev:hot 主进程,cargo-watch 不会刷新 Node 启动环境。",
].join(" "),
);
}
assert.fail(`/api/dev/seed 失败: ${response.status()} ${details}`);
}
return payload;
}
async function setupWorkspaceAccess(requestContext, baseUrl, options) {
const actorId = options.actorId;
const rootPath = options.rootPath || options.root;
const rootUri = options.rootUri || `file://${rootPath}`;
return postDevSeed(
requestContext,
baseUrl,
[
{
kind: "setupWorkspace",
user_id: actorId,
email: options.email || `${actorId}@example.com`,
username: options.username || actorId,
display_name: options.displayName || actorId,
role: options.role || "user",
workspace_id: options.workspaceId,
workspace_name: options.workspaceName || "MNote Smoke Workspace",
root_uri: rootUri,
root_path: rootPath,
source_kind: options.sourceKind || "local_folder",
permission: options.permission || "write",
capabilities: options.capabilities || ["ai"],
grant_source: options.grantSource || "smoke",
grant_created_by: options.grantCreatedBy || actorId,
},
],
options.timeoutMs,
);
}
async function seedAiRuntime(requestContext, baseUrl, options) {
return postDevSeed(
requestContext,
baseUrl,
[
{
kind: "seedAiRuntime",
id: options.id,
user_id: options.userId,
workspace_id: options.workspaceId,
document_id: options.documentId,
session_id: options.sessionId,
run_id: options.runId,
title: options.title,
profile: options.profile || "reasonix",
acp_runtime: options.acpRuntime || options.profile || "reasonix",
trace_id: options.traceId,
status: options.status || "running",
runtime_json: options.runtimeJson || {},
payload_json: options.payloadJson || {},
events: (options.events || []).map((event) => ({
id: event.id,
eventType: event.eventType || event.event_type,
payloadJson: event.payloadJson || event.payload_json || {},
})),
},
],
options.timeoutMs,
);
}
async function seedAiPolicy(requestContext, baseUrl, options) {
return postDevSeed(
requestContext,
baseUrl,
[
{
kind: "seedAiPolicy",
id: options.id,
user_id: options.userId,
workspace_id: options.workspaceId,
allowed_roots_json: options.allowedRootsJson || [],
model_policy_json: options.modelPolicyJson || {},
quota_json: options.quotaJson || {},
},
],
options.timeoutMs,
);
}
async function clearRuntimeEvents(requestContext, baseUrl, options) {
return postDevSeed(
requestContext,
baseUrl,
[
{
kind: "clearRuntimeEvents",
user_id: options.userId,
run_id: options.runId,
},
],
options.timeoutMs,
);
}
async function getAiRuntimeRun(requestContext, baseUrl, options) {
const payload = await postDevSeed(
requestContext,
baseUrl,
[
{
kind: "getAiRuntimeRun",
user_id: options.userId,
run_id: options.runId,
},
],
options.timeoutMs,
);
return payload.results && payload.results[0] ? payload.results[0].run : null;
}
async function listAiRuntimeRuns(requestContext, baseUrl, options) {
const payload = await postDevSeed(
requestContext,
baseUrl,
[
{
kind: "listAiRuntimeRuns",
user_id: options.userId,
workspace_id: options.workspaceId,
document_id: options.documentId,
session_id: options.sessionId,
limit: options.limit,
},
],
options.timeoutMs,
);
return payload.results && payload.results[0] ? payload.results[0].runs || [] : [];
}
async function listAiRuntimeEvents(requestContext, baseUrl, options) {
const payload = await postDevSeed(
requestContext,
baseUrl,
[
{
kind: "listAiRuntimeEvents",
user_id: options.userId,
run_id: options.runId,
limit: options.limit,
event_type: options.eventType,
},
],
options.timeoutMs,
);
return payload.results && payload.results[0] ? payload.results[0].events || [] : [];
}
async function countAiRuntimeEvents(requestContext, baseUrl, options) {
const payload = await postDevSeed(
requestContext,
baseUrl,
[
{
kind: "countAiRuntimeEvents",
user_id: options.userId,
run_id: options.runId,
event_type: options.eventType,
},
],
options.timeoutMs,
);
return Number(payload.results && payload.results[0] ? payload.results[0].count : 0);
}
async function findExternalConversationBinding(requestContext, baseUrl, options) {
const payload = await postDevSeed(
requestContext,
baseUrl,
[
{
kind: "findExternalConversationBinding",
user_id: options.userId,
workspace_id: options.workspaceId,
mnote_session_id: options.mnoteSessionId,
provider: options.provider,
},
],
options.timeoutMs,
);
return payload.results && payload.results[0] ? payload.results[0].binding : null;
}
async function listExternalConversationBindings(requestContext, baseUrl, options) {
const payload = await postDevSeed(
requestContext,
baseUrl,
[
{
kind: "listExternalConversationBindings",
user_id: options.userId,
workspace_id: options.workspaceId,
mnote_session_id: options.mnoteSessionId,
limit: options.limit,
},
],
options.timeoutMs,
);
return payload.results && payload.results[0] ? payload.results[0].bindings || [] : [];
}
module.exports = {
postDevSeed,
setupWorkspaceAccess,
seedAiRuntime,
seedAiPolicy,
clearRuntimeEvents,
getAiRuntimeRun,
listAiRuntimeRuns,
listAiRuntimeEvents,
countAiRuntimeEvents,
findExternalConversationBinding,
listExternalConversationBindings,
};