2026-07-03 13:24:20 +08:00
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
|
const assert = require("node:assert/strict");
|
|
|
|
|
|
|
|
|
|
async function postDevSeed(requestContext, baseUrl, seeds, timeoutMs) {
|
2026-07-11 20:39:18 +08:00
|
|
|
const normalizedBaseUrl = baseUrl.replace(/\/+$/, "");
|
|
|
|
|
const response = await requestContext.fetch(`${normalizedBaseUrl}/api/dev/seed`, {
|
2026-07-03 13:24:20 +08:00
|
|
|
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;
|
|
|
|
|
}
|
2026-07-11 20:39:18 +08:00
|
|
|
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。",
|
2026-07-28 17:04:27 +08:00
|
|
|
"若直接跑 mnote-web 而未走 dev:hot,请显式 `MNOTE_WEB_ALLOW_DEV_FIXTURES=1`。",
|
2026-07-11 20:39:18 +08:00
|
|
|
"修改 scripts/dev-hot.js 或启动环境后必须重启 dev:hot 主进程,cargo-watch 不会刷新 Node 启动环境。",
|
|
|
|
|
].join(" "),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
assert.fail(`/api/dev/seed 失败: ${response.status()} ${details}`);
|
|
|
|
|
}
|
2026-07-03 13:24:20 +08:00
|
|
|
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",
|
2026-07-10 10:54:34 +08:00
|
|
|
user_id: actorId,
|
2026-07-03 13:24:20 +08:00
|
|
|
email: options.email || `${actorId}@example.com`,
|
|
|
|
|
username: options.username || actorId,
|
2026-07-10 10:54:34 +08:00
|
|
|
display_name: options.displayName || actorId,
|
2026-07-03 13:24:20 +08:00
|
|
|
role: options.role || "user",
|
2026-07-10 10:54:34 +08:00
|
|
|
workspace_id: options.workspaceId,
|
|
|
|
|
workspace_name: options.workspaceName || "MNote Smoke Workspace",
|
|
|
|
|
root_uri: rootUri,
|
|
|
|
|
root_path: rootPath,
|
|
|
|
|
source_kind: options.sourceKind || "local_folder",
|
2026-07-03 13:24:20 +08:00
|
|
|
permission: options.permission || "write",
|
|
|
|
|
capabilities: options.capabilities || ["ai"],
|
2026-07-10 10:54:34 +08:00
|
|
|
grant_source: options.grantSource || "smoke",
|
|
|
|
|
grant_created_by: options.grantCreatedBy || actorId,
|
2026-07-03 13:24:20 +08:00
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
options.timeoutMs,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function seedAiRuntime(requestContext, baseUrl, options) {
|
|
|
|
|
return postDevSeed(
|
|
|
|
|
requestContext,
|
|
|
|
|
baseUrl,
|
|
|
|
|
[
|
|
|
|
|
{
|
|
|
|
|
kind: "seedAiRuntime",
|
|
|
|
|
id: options.id,
|
2026-07-10 10:54:34 +08:00
|
|
|
user_id: options.userId,
|
|
|
|
|
workspace_id: options.workspaceId,
|
|
|
|
|
document_id: options.documentId,
|
|
|
|
|
session_id: options.sessionId,
|
|
|
|
|
run_id: options.runId,
|
2026-07-03 13:24:20 +08:00
|
|
|
title: options.title,
|
2026-07-29 01:49:53 +08:00
|
|
|
profile: options.profile || "pi",
|
|
|
|
|
acp_runtime: options.acpRuntime || options.profile || "pi",
|
2026-07-10 10:54:34 +08:00
|
|
|
trace_id: options.traceId,
|
2026-07-03 13:24:20 +08:00
|
|
|
status: options.status || "running",
|
2026-07-10 10:54:34 +08:00
|
|
|
runtime_json: options.runtimeJson || {},
|
|
|
|
|
payload_json: options.payloadJson || {},
|
|
|
|
|
events: (options.events || []).map((event) => ({
|
|
|
|
|
id: event.id,
|
2026-07-11 20:39:18 +08:00
|
|
|
eventType: event.eventType || event.event_type,
|
|
|
|
|
payloadJson: event.payloadJson || event.payload_json || {},
|
2026-07-10 10:54:34 +08:00
|
|
|
})),
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
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 || {},
|
2026-07-03 13:24:20 +08:00
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
options.timeoutMs,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function clearRuntimeEvents(requestContext, baseUrl, options) {
|
|
|
|
|
return postDevSeed(
|
|
|
|
|
requestContext,
|
|
|
|
|
baseUrl,
|
|
|
|
|
[
|
|
|
|
|
{
|
|
|
|
|
kind: "clearRuntimeEvents",
|
2026-07-10 10:54:34 +08:00
|
|
|
user_id: options.userId,
|
|
|
|
|
run_id: options.runId,
|
2026-07-03 13:24:20 +08:00
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
options.timeoutMs,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function getAiRuntimeRun(requestContext, baseUrl, options) {
|
|
|
|
|
const payload = await postDevSeed(
|
|
|
|
|
requestContext,
|
|
|
|
|
baseUrl,
|
|
|
|
|
[
|
|
|
|
|
{
|
|
|
|
|
kind: "getAiRuntimeRun",
|
2026-07-10 10:54:34 +08:00
|
|
|
user_id: options.userId,
|
|
|
|
|
run_id: options.runId,
|
2026-07-03 13:24:20 +08:00
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
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",
|
2026-07-10 10:54:34 +08:00
|
|
|
user_id: options.userId,
|
|
|
|
|
workspace_id: options.workspaceId,
|
|
|
|
|
document_id: options.documentId,
|
|
|
|
|
session_id: options.sessionId,
|
2026-07-03 13:24:20 +08:00
|
|
|
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",
|
2026-07-10 10:54:34 +08:00
|
|
|
user_id: options.userId,
|
|
|
|
|
run_id: options.runId,
|
2026-07-03 13:24:20 +08:00
|
|
|
limit: options.limit,
|
2026-07-10 10:54:34 +08:00
|
|
|
event_type: options.eventType,
|
2026-07-03 13:24:20 +08:00
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
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",
|
2026-07-10 10:54:34 +08:00
|
|
|
user_id: options.userId,
|
|
|
|
|
run_id: options.runId,
|
|
|
|
|
event_type: options.eventType,
|
2026-07-03 13:24:20 +08:00
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
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",
|
2026-07-10 10:54:34 +08:00
|
|
|
user_id: options.userId,
|
|
|
|
|
workspace_id: options.workspaceId,
|
|
|
|
|
mnote_session_id: options.mnoteSessionId,
|
2026-07-03 13:24:20 +08:00
|
|
|
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",
|
2026-07-10 10:54:34 +08:00
|
|
|
user_id: options.userId,
|
|
|
|
|
workspace_id: options.workspaceId,
|
|
|
|
|
mnote_session_id: options.mnoteSessionId,
|
2026-07-03 13:24:20 +08:00
|
|
|
limit: options.limit,
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
options.timeoutMs,
|
|
|
|
|
);
|
|
|
|
|
return payload.results && payload.results[0] ? payload.results[0].bindings || [] : [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
|
postDevSeed,
|
|
|
|
|
setupWorkspaceAccess,
|
|
|
|
|
seedAiRuntime,
|
2026-07-10 10:54:34 +08:00
|
|
|
seedAiPolicy,
|
2026-07-03 13:24:20 +08:00
|
|
|
clearRuntimeEvents,
|
|
|
|
|
getAiRuntimeRun,
|
|
|
|
|
listAiRuntimeRuns,
|
|
|
|
|
listAiRuntimeEvents,
|
|
|
|
|
countAiRuntimeEvents,
|
|
|
|
|
findExternalConversationBinding,
|
|
|
|
|
listExternalConversationBindings,
|
|
|
|
|
};
|