@fieldwangai/agentflow 0.1.51 → 0.1.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/lib/auth.mjs +4 -3
- package/bin/lib/ui-server.mjs +33 -2
- package/builtin/web-ui/dist/assets/index-C2La4Klr.js +238 -0
- package/builtin/web-ui/dist/assets/{index-CP_UFJ5h.css → index-DlZeY5p1.css} +1 -1
- package/builtin/web-ui/dist/index.html +2 -2
- package/package.json +1 -1
- package/builtin/web-ui/dist/assets/index-SEPc5aI2.js +0 -238
package/bin/lib/auth.mjs
CHANGED
|
@@ -152,6 +152,7 @@ function userAllowlistMatchSet(users) {
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
export function isAuthUserAllowed(user) {
|
|
155
|
+
if (user?.isAdmin) return true;
|
|
155
156
|
const allowlist = readUserAllowlist();
|
|
156
157
|
if (!allowlist.enabled) return true;
|
|
157
158
|
const allowed = userAllowlistMatchSet(allowlist.users);
|
|
@@ -266,15 +267,15 @@ export function loginOrCreateUser(username, password) {
|
|
|
266
267
|
if (!userId) {
|
|
267
268
|
return { ok: false, error: "用户名须以字母开头,仅可使用字母、数字、下划线与连字符,最多 64 字符" };
|
|
268
269
|
}
|
|
269
|
-
if (!isAuthUserAllowed({ userId, username: String(username || "").trim() })) {
|
|
270
|
-
return { ok: false, forbidden: true, error: "用户不在白名单中,请联系管理员开通访问权限" };
|
|
271
|
-
}
|
|
272
270
|
const pwd = String(password || "");
|
|
273
271
|
if (pwd.length < 4) return { ok: false, error: "密码至少 4 位" };
|
|
274
272
|
|
|
275
273
|
const users = readAuthUsers();
|
|
276
274
|
const firstUser = Object.keys(users).length === 0;
|
|
277
275
|
let user = users[userId];
|
|
276
|
+
if (!isAuthUserAllowed({ userId, username: String(username || "").trim(), isAdmin: Boolean(user?.isAdmin) })) {
|
|
277
|
+
return { ok: false, forbidden: true, error: "用户不在白名单中,请联系管理员开通访问权限" };
|
|
278
|
+
}
|
|
278
279
|
if (!user) {
|
|
279
280
|
const hashed = hashPassword(pwd);
|
|
280
281
|
user = {
|
package/bin/lib/ui-server.mjs
CHANGED
|
@@ -1327,11 +1327,16 @@ function publicDisplayPayloadFromShare(root, share) {
|
|
|
1327
1327
|
}, { userId: share.userId || "" });
|
|
1328
1328
|
if (scoped.error) return { error: scoped.error };
|
|
1329
1329
|
const { graph } = readWorkspaceGraph(scoped.root);
|
|
1330
|
-
const nodeIds = normalizeDisplayShareNodeIds(share.nodeIds, graph);
|
|
1331
1330
|
const instances = graph.instances || {};
|
|
1332
1331
|
const displayPage = graph.ui && typeof graph.ui === "object" && graph.ui.displayPage && typeof graph.ui.displayPage === "object"
|
|
1333
1332
|
? graph.ui.displayPage
|
|
1334
1333
|
: {};
|
|
1334
|
+
const sharedNodeIds = normalizeDisplayShareNodeIds(share.nodeIds, graph);
|
|
1335
|
+
const hasDisplayPageNodeIds = Array.isArray(displayPage.nodeIds);
|
|
1336
|
+
const displayPageNodeIds = normalizeDisplayShareNodeIds(displayPage.nodeIds, graph);
|
|
1337
|
+
const nodeIds = share.layout === "canvas" && hasDisplayPageNodeIds
|
|
1338
|
+
? displayPageNodeIds
|
|
1339
|
+
: sharedNodeIds;
|
|
1335
1340
|
const displayPageSizes = displayPage.nodeSizes && typeof displayPage.nodeSizes === "object" ? displayPage.nodeSizes : {};
|
|
1336
1341
|
const displayPagePositions = displayPage.nodePositions && typeof displayPage.nodePositions === "object" ? displayPage.nodePositions : {};
|
|
1337
1342
|
const displayPageViewport = displayPage.viewport && typeof displayPage.viewport === "object"
|
|
@@ -1596,11 +1601,15 @@ function workspaceSourceSlotForEdge(graph, edge) {
|
|
|
1596
1601
|
function workspaceOutputSlotValueForEdge(graph, outputs, edge) {
|
|
1597
1602
|
const sourceId = String(edge?.source || "");
|
|
1598
1603
|
const slot = workspaceSourceSlotForEdge(graph, edge);
|
|
1604
|
+
const out = outputs.get(sourceId);
|
|
1605
|
+
const sourceIndex = workspaceHandleIndex(edge?.sourceHandle, "output");
|
|
1606
|
+
const slotName = String(slot?.name || "").trim();
|
|
1607
|
+
const isPrimaryOutput = !slot || slotName === "result" || slotName === "content" || sourceIndex === 0;
|
|
1608
|
+
if (isPrimaryOutput && out != null && String(out).trim()) return String(out);
|
|
1599
1609
|
if (slot && String(slot?.type || "") !== "node") {
|
|
1600
1610
|
const value = workspaceSlotValue(slot);
|
|
1601
1611
|
if (value.trim()) return value;
|
|
1602
1612
|
}
|
|
1603
|
-
const out = outputs.get(sourceId);
|
|
1604
1613
|
if (out != null && String(out).trim()) return String(out);
|
|
1605
1614
|
const instances = graph?.instances && typeof graph.instances === "object" ? graph.instances : {};
|
|
1606
1615
|
return workspaceInstanceText(instances[sourceId]);
|
|
@@ -2017,6 +2026,26 @@ function workspaceDownstreamDisplayRequirements(graph, nodeId) {
|
|
|
2017
2026
|
].join("\n");
|
|
2018
2027
|
}
|
|
2019
2028
|
|
|
2029
|
+
function workspaceNodeScopeGuardrails(graph, nodeId, inputValues = {}) {
|
|
2030
|
+
const edges = Array.isArray(graph?.edges) ? graph.edges : [];
|
|
2031
|
+
const directInputEdges = edges
|
|
2032
|
+
.filter((edge) => String(edge?.target || "") === String(nodeId))
|
|
2033
|
+
.filter((edge) => !isWorkspaceSemanticInputSlot(workspaceTargetSlotForEdge(graph, edge)));
|
|
2034
|
+
const upstreamNodeIds = Array.from(new Set(directInputEdges.map((edge) => String(edge?.source || "").trim()).filter(Boolean)));
|
|
2035
|
+
const inputNames = Object.keys(inputValues || {}).filter(Boolean);
|
|
2036
|
+
return [
|
|
2037
|
+
"## 当前节点上下文边界",
|
|
2038
|
+
"",
|
|
2039
|
+
"你只负责执行当前节点;`上游上下文`、已解析输入槽和节点任务就是本节点的业务上下文边界。",
|
|
2040
|
+
upstreamNodeIds.length ? `当前直接上游节点:${upstreamNodeIds.map((id) => `\`${id}\``).join("、")}。` : "当前没有直接业务上游节点。",
|
|
2041
|
+
inputNames.length ? `当前已解析输入槽:${inputNames.map((name) => `\`${name}\``).join("、")}。` : "当前没有已解析的具名业务输入槽。",
|
|
2042
|
+
"不要为了理解本节点而读取或搜索整张 workspace、`workspace.graph.json`、正式 `flow.yaml`、历史 run/log 或其它未连接节点。",
|
|
2043
|
+
"不要把下游展示节点已有内容、下游错误信息、其它分支节点内容当作本节点输入;下游输出要求只用于决定最终 JSON 的字段和格式。",
|
|
2044
|
+
"只有当当前节点任务文本或上游输入明确要求读取/修改 `workspace.graph.json`、`flow.yaml` 或某个具体文件路径时,才可以打开对应文件。",
|
|
2045
|
+
"如果完成任务所需信息不在当前节点任务、输入槽或上游上下文中,应明确说明缺少哪个上游输入,而不是扫描整张 workspace 猜测。",
|
|
2046
|
+
].join("\n");
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2020
2049
|
function workspaceOutputProtocolRequirements(graph, nodeId) {
|
|
2021
2050
|
const instance = graph?.instances?.[nodeId] || {};
|
|
2022
2051
|
const outputSlots = Array.isArray(instance.output) ? instance.output : [];
|
|
@@ -2350,11 +2379,13 @@ function workspaceNodePrompt(graph, nodeId, upstreamText, skillsBlock, mcpBlock
|
|
|
2350
2379
|
const instance = graph.instances[nodeId] || {};
|
|
2351
2380
|
const body = workspaceResolveBodyPlaceholders(instance.body || "", inputValues).trim();
|
|
2352
2381
|
const label = String(instance.label || nodeId).trim();
|
|
2382
|
+
const scopeGuardrails = workspaceNodeScopeGuardrails(graph, nodeId, inputValues);
|
|
2353
2383
|
const downstreamRequirements = workspaceDownstreamDisplayRequirements(graph, nodeId);
|
|
2354
2384
|
const outputProtocolRequirements = workspaceOutputProtocolRequirements(graph, nodeId);
|
|
2355
2385
|
return [
|
|
2356
2386
|
"你正在执行 AgentFlow Workspace 画布中的一个临时节点。",
|
|
2357
2387
|
"按 Workspace 输出协议返回该节点要传给下游展示/后续节点的数据。",
|
|
2388
|
+
scopeGuardrails,
|
|
2358
2389
|
workspaceSearchGuardrailsBlock(),
|
|
2359
2390
|
skillsBlock ? `\n## Available Skills\n\n${skillsBlock}` : "",
|
|
2360
2391
|
mcpBlock ? `\n## Available MCP\n\n${mcpBlock}` : "",
|