@fieldwangai/agentflow 0.1.48 → 0.1.49
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/ui-server.mjs +220 -0
- package/builtin/web-ui/dist/assets/index-CAAH9i1Q.js +238 -0
- package/builtin/web-ui/dist/assets/index-CItfpMNC.css +1 -0
- package/builtin/web-ui/dist/index.html +2 -2
- package/package.json +1 -1
- package/builtin/web-ui/dist/assets/index-7Z7k_tUT.css +0 -1
- package/builtin/web-ui/dist/assets/index-BBDerZ_i.js +0 -222
package/bin/lib/ui-server.mjs
CHANGED
|
@@ -1279,6 +1279,108 @@ function readWorkspaceGraph(workspaceRoot) {
|
|
|
1279
1279
|
};
|
|
1280
1280
|
}
|
|
1281
1281
|
|
|
1282
|
+
const DISPLAY_SHARE_FILENAME = "display-shares.json";
|
|
1283
|
+
|
|
1284
|
+
function displaySharesPath() {
|
|
1285
|
+
return path.join(getAgentflowDataRoot(), DISPLAY_SHARE_FILENAME);
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
function readDisplayShares() {
|
|
1289
|
+
const file = displaySharesPath();
|
|
1290
|
+
if (!fs.existsSync(file)) return {};
|
|
1291
|
+
const raw = fs.readFileSync(file, "utf-8");
|
|
1292
|
+
if (!raw.trim()) return {};
|
|
1293
|
+
const parsed = JSON.parse(raw);
|
|
1294
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
function writeDisplayShares(shares) {
|
|
1298
|
+
const file = displaySharesPath();
|
|
1299
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
1300
|
+
fs.writeFileSync(file, JSON.stringify(shares && typeof shares === "object" ? shares : {}, null, 2) + "\n", "utf-8");
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
function createDisplayShareId() {
|
|
1304
|
+
return crypto.randomBytes(12).toString("base64url");
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
function normalizeDisplayShareNodeIds(ids, graph) {
|
|
1308
|
+
const out = [];
|
|
1309
|
+
const seen = new Set();
|
|
1310
|
+
const instances = graph?.instances && typeof graph.instances === "object" ? graph.instances : {};
|
|
1311
|
+
for (const rawId of Array.isArray(ids) ? ids : []) {
|
|
1312
|
+
const id = String(rawId || "").trim();
|
|
1313
|
+
if (!id || seen.has(id)) continue;
|
|
1314
|
+
const instance = instances[id];
|
|
1315
|
+
if (!workspaceDisplayKind(instance?.definitionId)) continue;
|
|
1316
|
+
seen.add(id);
|
|
1317
|
+
out.push(id);
|
|
1318
|
+
}
|
|
1319
|
+
return out;
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
function publicDisplayPayloadFromShare(root, share) {
|
|
1323
|
+
const scoped = resolveWorkspaceScopeRoot(root, {
|
|
1324
|
+
flowId: share.flowId || "",
|
|
1325
|
+
flowSource: share.flowSource || "user",
|
|
1326
|
+
archived: share.archived === true,
|
|
1327
|
+
}, { userId: share.userId || "" });
|
|
1328
|
+
if (scoped.error) return { error: scoped.error };
|
|
1329
|
+
const { graph } = readWorkspaceGraph(scoped.root);
|
|
1330
|
+
const nodeIds = normalizeDisplayShareNodeIds(share.nodeIds, graph);
|
|
1331
|
+
const instances = graph.instances || {};
|
|
1332
|
+
const displayPage = graph.ui && typeof graph.ui === "object" && graph.ui.displayPage && typeof graph.ui.displayPage === "object"
|
|
1333
|
+
? graph.ui.displayPage
|
|
1334
|
+
: {};
|
|
1335
|
+
const displayPageSizes = displayPage.nodeSizes && typeof displayPage.nodeSizes === "object" ? displayPage.nodeSizes : {};
|
|
1336
|
+
const displayPagePositions = displayPage.nodePositions && typeof displayPage.nodePositions === "object" ? displayPage.nodePositions : {};
|
|
1337
|
+
const displayPageViewport = displayPage.viewport && typeof displayPage.viewport === "object"
|
|
1338
|
+
? displayPage.viewport
|
|
1339
|
+
: null;
|
|
1340
|
+
const workspaceSizes = graph.ui && typeof graph.ui === "object" && graph.ui.nodeSizes && typeof graph.ui.nodeSizes === "object"
|
|
1341
|
+
? graph.ui.nodeSizes
|
|
1342
|
+
: {};
|
|
1343
|
+
const workspacePositions = graph.ui && typeof graph.ui === "object" && graph.ui.nodePositions && typeof graph.ui.nodePositions === "object"
|
|
1344
|
+
? graph.ui.nodePositions
|
|
1345
|
+
: {};
|
|
1346
|
+
const nodes = nodeIds.map((id) => {
|
|
1347
|
+
const instance = instances[id] || {};
|
|
1348
|
+
const definitionId = String(instance.definitionId || "");
|
|
1349
|
+
return {
|
|
1350
|
+
id,
|
|
1351
|
+
definitionId,
|
|
1352
|
+
kind: workspaceDisplayKind(definitionId),
|
|
1353
|
+
label: String(instance.label || instance.displayName || id),
|
|
1354
|
+
body: String(instance.body || ""),
|
|
1355
|
+
inputs: Array.isArray(instance.input) ? instance.input : [],
|
|
1356
|
+
outputs: Array.isArray(instance.output) ? instance.output : [],
|
|
1357
|
+
size: displayPageSizes[id] || workspaceSizes[id] || null,
|
|
1358
|
+
position: displayPagePositions[id] || workspacePositions[id] || null,
|
|
1359
|
+
};
|
|
1360
|
+
});
|
|
1361
|
+
return {
|
|
1362
|
+
ok: true,
|
|
1363
|
+
share: {
|
|
1364
|
+
id: share.id,
|
|
1365
|
+
title: share.title || "AgentFlow Display",
|
|
1366
|
+
layout: share.layout || "gallery",
|
|
1367
|
+
flowId: share.flowId || "",
|
|
1368
|
+
flowSource: share.flowSource || "user",
|
|
1369
|
+
archived: share.archived === true,
|
|
1370
|
+
nodeIds,
|
|
1371
|
+
viewport: displayPageViewport &&
|
|
1372
|
+
Number.isFinite(Number(displayPageViewport.x)) &&
|
|
1373
|
+
Number.isFinite(Number(displayPageViewport.y)) &&
|
|
1374
|
+
Number.isFinite(Number(displayPageViewport.zoom))
|
|
1375
|
+
? { x: Number(displayPageViewport.x), y: Number(displayPageViewport.y), zoom: Number(displayPageViewport.zoom) }
|
|
1376
|
+
: null,
|
|
1377
|
+
createdAt: share.createdAt || "",
|
|
1378
|
+
updatedAt: share.updatedAt || "",
|
|
1379
|
+
},
|
|
1380
|
+
nodes,
|
|
1381
|
+
};
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1282
1384
|
function normalizeWorkspaceGraphPayload(payload) {
|
|
1283
1385
|
const graph = payload?.graph && typeof payload.graph === "object" ? payload.graph : payload;
|
|
1284
1386
|
return {
|
|
@@ -3139,6 +3241,75 @@ export function startUiServer({
|
|
|
3139
3241
|
|
|
3140
3242
|
const authUser = getAuthUserFromRequest(req);
|
|
3141
3243
|
const userCtx = authUser ? { userId: authUser.userId } : {};
|
|
3244
|
+
if (req.method === "GET" && url.pathname === "/api/display/share") {
|
|
3245
|
+
try {
|
|
3246
|
+
const id = String(url.searchParams.get("id") || "").trim();
|
|
3247
|
+
if (!id) {
|
|
3248
|
+
json(res, 400, { error: "Missing display share id" });
|
|
3249
|
+
return;
|
|
3250
|
+
}
|
|
3251
|
+
const share = readDisplayShares()[id];
|
|
3252
|
+
if (!share) {
|
|
3253
|
+
json(res, 404, { error: "Display share not found" });
|
|
3254
|
+
return;
|
|
3255
|
+
}
|
|
3256
|
+
const payload = publicDisplayPayloadFromShare(root, share);
|
|
3257
|
+
if (payload.error) {
|
|
3258
|
+
json(res, 404, { error: payload.error });
|
|
3259
|
+
return;
|
|
3260
|
+
}
|
|
3261
|
+
json(res, 200, payload);
|
|
3262
|
+
} catch (e) {
|
|
3263
|
+
json(res, 500, { error: (e && e.message) || String(e) });
|
|
3264
|
+
}
|
|
3265
|
+
return;
|
|
3266
|
+
}
|
|
3267
|
+
|
|
3268
|
+
if (req.method === "GET" && url.pathname === "/api/display/file/raw") {
|
|
3269
|
+
try {
|
|
3270
|
+
const id = String(url.searchParams.get("id") || "").trim();
|
|
3271
|
+
if (!id) {
|
|
3272
|
+
json(res, 400, { error: "Missing display share id" });
|
|
3273
|
+
return;
|
|
3274
|
+
}
|
|
3275
|
+
const share = readDisplayShares()[id];
|
|
3276
|
+
if (!share) {
|
|
3277
|
+
json(res, 404, { error: "Display share not found" });
|
|
3278
|
+
return;
|
|
3279
|
+
}
|
|
3280
|
+
const scoped = resolveWorkspaceScopeRoot(root, {
|
|
3281
|
+
flowId: share.flowId || "",
|
|
3282
|
+
flowSource: share.flowSource || "user",
|
|
3283
|
+
archived: share.archived === true,
|
|
3284
|
+
}, { userId: share.userId || "" });
|
|
3285
|
+
if (scoped.error) {
|
|
3286
|
+
json(res, 404, { error: scoped.error });
|
|
3287
|
+
return;
|
|
3288
|
+
}
|
|
3289
|
+
const { abs, rel } = resolveWorkspaceFilePath(scoped.root, url.searchParams.get("path") || "");
|
|
3290
|
+
if (!fs.existsSync(abs) || !fs.statSync(abs).isFile()) {
|
|
3291
|
+
json(res, 404, { error: "File not found" });
|
|
3292
|
+
return;
|
|
3293
|
+
}
|
|
3294
|
+
const ext = path.extname(abs).toLowerCase();
|
|
3295
|
+
const type = MIME[ext] || "application/octet-stream";
|
|
3296
|
+
const data = fs.readFileSync(abs);
|
|
3297
|
+
const headers = {
|
|
3298
|
+
"Content-Type": type,
|
|
3299
|
+
"Content-Length": data.length,
|
|
3300
|
+
"Cache-Control": "public, max-age=300",
|
|
3301
|
+
};
|
|
3302
|
+
if (url.searchParams.get("download") === "1") {
|
|
3303
|
+
headers["Content-Disposition"] = workspaceDownloadContentDisposition(rel);
|
|
3304
|
+
}
|
|
3305
|
+
res.writeHead(200, headers);
|
|
3306
|
+
res.end(data);
|
|
3307
|
+
} catch (e) {
|
|
3308
|
+
json(res, /traversal/i.test(String(e.message || e)) ? 403 : 500, { error: (e && e.message) || String(e) });
|
|
3309
|
+
}
|
|
3310
|
+
return;
|
|
3311
|
+
}
|
|
3312
|
+
|
|
3142
3313
|
if (url.pathname.startsWith("/api/") && !authUser) {
|
|
3143
3314
|
json(res, 401, { error: "Authentication required", setupRequired: authSetupRequired() });
|
|
3144
3315
|
return;
|
|
@@ -3511,6 +3682,55 @@ export function startUiServer({
|
|
|
3511
3682
|
return;
|
|
3512
3683
|
}
|
|
3513
3684
|
|
|
3685
|
+
if (req.method === "POST" && url.pathname === "/api/display/share") {
|
|
3686
|
+
let payload;
|
|
3687
|
+
try {
|
|
3688
|
+
payload = JSON.parse(await readBody(req));
|
|
3689
|
+
} catch {
|
|
3690
|
+
json(res, 400, { error: "Invalid JSON body" });
|
|
3691
|
+
return;
|
|
3692
|
+
}
|
|
3693
|
+
try {
|
|
3694
|
+
const scoped = resolveWorkspaceScopeRoot(root, {
|
|
3695
|
+
flowId: payload.flowId || "",
|
|
3696
|
+
flowSource: payload.flowSource || "user",
|
|
3697
|
+
archived: payload.archived === true || payload.flowArchived === true,
|
|
3698
|
+
}, userCtx);
|
|
3699
|
+
if (scoped.error) {
|
|
3700
|
+
json(res, 400, { error: scoped.error });
|
|
3701
|
+
return;
|
|
3702
|
+
}
|
|
3703
|
+
const { graph } = readWorkspaceGraph(scoped.root);
|
|
3704
|
+
const nodeIds = normalizeDisplayShareNodeIds(payload.nodeIds, graph);
|
|
3705
|
+
if (nodeIds.length === 0) {
|
|
3706
|
+
json(res, 400, { error: "请选择至少一个 display 节点" });
|
|
3707
|
+
return;
|
|
3708
|
+
}
|
|
3709
|
+
const shares = readDisplayShares();
|
|
3710
|
+
let id = createDisplayShareId();
|
|
3711
|
+
while (shares[id]) id = createDisplayShareId();
|
|
3712
|
+
const now = new Date().toISOString();
|
|
3713
|
+
const share = {
|
|
3714
|
+
id,
|
|
3715
|
+
userId: authUser.userId,
|
|
3716
|
+
flowId: scoped.flowId || "",
|
|
3717
|
+
flowSource: scoped.flowSource || "user",
|
|
3718
|
+
archived: scoped.archived === true,
|
|
3719
|
+
title: String(payload.title || "").trim() || "AgentFlow Display",
|
|
3720
|
+
layout: ["canvas", "gallery", "slides", "document"].includes(String(payload.layout || "")) ? String(payload.layout) : "canvas",
|
|
3721
|
+
nodeIds,
|
|
3722
|
+
createdAt: now,
|
|
3723
|
+
updatedAt: now,
|
|
3724
|
+
};
|
|
3725
|
+
shares[id] = share;
|
|
3726
|
+
writeDisplayShares(shares);
|
|
3727
|
+
json(res, 200, { ok: true, share, url: `/display/${encodeURIComponent(id)}` });
|
|
3728
|
+
} catch (e) {
|
|
3729
|
+
json(res, 500, { error: (e && e.message) || String(e) });
|
|
3730
|
+
}
|
|
3731
|
+
return;
|
|
3732
|
+
}
|
|
3733
|
+
|
|
3514
3734
|
if (req.method === "POST" && url.pathname === "/api/workspace/graph") {
|
|
3515
3735
|
let payload;
|
|
3516
3736
|
try {
|