@fieldwangai/agentflow 0.1.67 → 0.1.68
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 +81 -10
- package/builtin/web-ui/dist/assets/{index-BFZ6_IPB.css → index-B7EYZmUN.css} +1 -1
- package/builtin/web-ui/dist/assets/index-D3NG6W8U.js +264 -0
- package/builtin/web-ui/dist/index.html +2 -2
- package/package.json +1 -1
- package/builtin/web-ui/dist/assets/index-BD8MsiMa.js +0 -264
package/bin/lib/ui-server.mjs
CHANGED
|
@@ -97,6 +97,7 @@ import {
|
|
|
97
97
|
isAuthUserAllowed,
|
|
98
98
|
loginOrCreateUser,
|
|
99
99
|
logoutRequest,
|
|
100
|
+
readAuthUsers,
|
|
100
101
|
readUserAllowlist,
|
|
101
102
|
writeUserAllowlist,
|
|
102
103
|
} from "./auth.mjs";
|
|
@@ -257,8 +258,38 @@ function createFeedbackItem(payload, user) {
|
|
|
257
258
|
};
|
|
258
259
|
}
|
|
259
260
|
|
|
260
|
-
function skillCollectionsAbs(
|
|
261
|
-
return path.join(
|
|
261
|
+
function skillCollectionsAbs() {
|
|
262
|
+
return path.join(getAgentflowDataRoot(), "admin", SKILL_COLLECTIONS_FILENAME);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function legacyAdminSkillCollectionPaths() {
|
|
266
|
+
const users = readAuthUsers();
|
|
267
|
+
return Object.entries(users || {})
|
|
268
|
+
.filter(([, user]) => user?.isAdmin)
|
|
269
|
+
.map(([userId, user]) => path.join(getAgentflowUserDataRoot(user.userId || userId), SKILL_COLLECTIONS_FILENAME));
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function readSkillCollectionFile(filePath) {
|
|
273
|
+
try {
|
|
274
|
+
if (!fs.existsSync(filePath)) return null;
|
|
275
|
+
const data = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
276
|
+
return data && typeof data === "object" && !Array.isArray(data) ? data : null;
|
|
277
|
+
} catch {
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function mergeSkillCollectionConfigs(configs = []) {
|
|
283
|
+
const merged = [];
|
|
284
|
+
const seen = new Set();
|
|
285
|
+
for (const config of configs) {
|
|
286
|
+
for (const collection of normalizeSkillCollectionConfig(config).collections) {
|
|
287
|
+
if (!collection.id || seen.has(collection.id)) continue;
|
|
288
|
+
seen.add(collection.id);
|
|
289
|
+
merged.push(collection);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return { version: 1, collections: merged };
|
|
262
293
|
}
|
|
263
294
|
|
|
264
295
|
function slugifySkillCollectionId(name, fallback = "collection") {
|
|
@@ -382,8 +413,12 @@ function withBuiltinSkillCollections(config, availableSkills = []) {
|
|
|
382
413
|
function readSkillCollectionConfig(userCtx = {}, availableSkills = []) {
|
|
383
414
|
const p = skillCollectionsAbs(userCtx);
|
|
384
415
|
try {
|
|
385
|
-
|
|
386
|
-
return withBuiltinSkillCollections(
|
|
416
|
+
const globalConfig = readSkillCollectionFile(p);
|
|
417
|
+
if (globalConfig) return withBuiltinSkillCollections(globalConfig, availableSkills);
|
|
418
|
+
const legacyConfigs = legacyAdminSkillCollectionPaths()
|
|
419
|
+
.map((legacyPath) => readSkillCollectionFile(legacyPath))
|
|
420
|
+
.filter(Boolean);
|
|
421
|
+
return withBuiltinSkillCollections(mergeSkillCollectionConfigs(legacyConfigs), availableSkills);
|
|
387
422
|
} catch {
|
|
388
423
|
return withBuiltinSkillCollections({}, availableSkills);
|
|
389
424
|
}
|
|
@@ -1408,6 +1443,7 @@ function readWorkspaceGraph(workspaceRoot) {
|
|
|
1408
1443
|
}
|
|
1409
1444
|
|
|
1410
1445
|
const DISPLAY_SHARE_FILENAME = "display-shares.json";
|
|
1446
|
+
const DISPLAY_SHARE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
1411
1447
|
|
|
1412
1448
|
function displaySharesPath() {
|
|
1413
1449
|
return path.join(getAgentflowDataRoot(), DISPLAY_SHARE_FILENAME);
|
|
@@ -1432,6 +1468,26 @@ function createDisplayShareId() {
|
|
|
1432
1468
|
return crypto.randomBytes(12).toString("base64url");
|
|
1433
1469
|
}
|
|
1434
1470
|
|
|
1471
|
+
function displayShareExpiresAt(now = new Date()) {
|
|
1472
|
+
const time = now instanceof Date ? now.getTime() : Date.now();
|
|
1473
|
+
return new Date(time + DISPLAY_SHARE_TTL_MS).toISOString();
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
function isDisplayShareExpired(share) {
|
|
1477
|
+
const expiresAt = Date.parse(String(share?.expiresAt || ""));
|
|
1478
|
+
return Number.isFinite(expiresAt) && expiresAt <= Date.now();
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
function getDisplayShareOrExpired(id) {
|
|
1482
|
+
const shares = readDisplayShares();
|
|
1483
|
+
const share = shares[id];
|
|
1484
|
+
if (!share) return { shares, share: null, expired: false };
|
|
1485
|
+
if (!isDisplayShareExpired(share)) return { shares, share, expired: false };
|
|
1486
|
+
delete shares[id];
|
|
1487
|
+
writeDisplayShares(shares);
|
|
1488
|
+
return { shares, share: null, expired: true };
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1435
1491
|
function normalizeDisplayShareNodeIds(ids, graph) {
|
|
1436
1492
|
const out = [];
|
|
1437
1493
|
const seen = new Set();
|
|
@@ -1519,6 +1575,7 @@ function publicDisplayPayloadFromShare(root, share) {
|
|
|
1519
1575
|
: null,
|
|
1520
1576
|
createdAt: share.createdAt || "",
|
|
1521
1577
|
updatedAt: share.updatedAt || "",
|
|
1578
|
+
expiresAt: share.expiresAt || "",
|
|
1522
1579
|
},
|
|
1523
1580
|
nodes,
|
|
1524
1581
|
};
|
|
@@ -3927,9 +3984,9 @@ export function startUiServer({
|
|
|
3927
3984
|
json(res, 400, { error: "Missing display share id" });
|
|
3928
3985
|
return;
|
|
3929
3986
|
}
|
|
3930
|
-
const share =
|
|
3987
|
+
const { share, expired } = getDisplayShareOrExpired(id);
|
|
3931
3988
|
if (!share) {
|
|
3932
|
-
json(res, 404, { error: "Display share not found" });
|
|
3989
|
+
json(res, expired ? 410 : 404, { error: expired ? "Display share has expired" : "Display share not found" });
|
|
3933
3990
|
return;
|
|
3934
3991
|
}
|
|
3935
3992
|
const payload = publicDisplayPayloadFromShare(root, share);
|
|
@@ -3951,9 +4008,9 @@ export function startUiServer({
|
|
|
3951
4008
|
json(res, 400, { error: "Missing display share id" });
|
|
3952
4009
|
return;
|
|
3953
4010
|
}
|
|
3954
|
-
const share =
|
|
4011
|
+
const { share, expired } = getDisplayShareOrExpired(id);
|
|
3955
4012
|
if (!share) {
|
|
3956
|
-
json(res, 404, { error: "Display share not found" });
|
|
4013
|
+
json(res, expired ? 410 : 404, { error: expired ? "Display share has expired" : "Display share not found" });
|
|
3957
4014
|
return;
|
|
3958
4015
|
}
|
|
3959
4016
|
const scoped = resolveWorkspaceScopeRoot(root, {
|
|
@@ -4394,7 +4451,8 @@ export function startUiServer({
|
|
|
4394
4451
|
const shares = readDisplayShares();
|
|
4395
4452
|
let id = createDisplayShareId();
|
|
4396
4453
|
while (shares[id]) id = createDisplayShareId();
|
|
4397
|
-
const
|
|
4454
|
+
const nowDate = new Date();
|
|
4455
|
+
const now = nowDate.toISOString();
|
|
4398
4456
|
const share = {
|
|
4399
4457
|
id,
|
|
4400
4458
|
userId: authUser.userId,
|
|
@@ -4402,10 +4460,11 @@ export function startUiServer({
|
|
|
4402
4460
|
flowSource: scoped.flowSource || "user",
|
|
4403
4461
|
archived: scoped.archived === true,
|
|
4404
4462
|
title: String(payload.title || "").trim() || "AgentFlow Display",
|
|
4405
|
-
layout: ["canvas", "gallery", "slides", "document"].includes(String(payload.layout || "")) ? String(payload.layout) : "canvas",
|
|
4463
|
+
layout: ["canvas", "gallery", "slides", "document", "single"].includes(String(payload.layout || "")) ? String(payload.layout) : "canvas",
|
|
4406
4464
|
nodeIds,
|
|
4407
4465
|
createdAt: now,
|
|
4408
4466
|
updatedAt: now,
|
|
4467
|
+
expiresAt: displayShareExpiresAt(nowDate),
|
|
4409
4468
|
};
|
|
4410
4469
|
shares[id] = share;
|
|
4411
4470
|
writeDisplayShares(shares);
|
|
@@ -5481,6 +5540,10 @@ export function startUiServer({
|
|
|
5481
5540
|
json(res, 400, { error: "Missing skill slug or collection" });
|
|
5482
5541
|
return;
|
|
5483
5542
|
}
|
|
5543
|
+
if (payload?.collection && !authUser?.isAdmin) {
|
|
5544
|
+
json(res, 403, { error: "Admin required" });
|
|
5545
|
+
return;
|
|
5546
|
+
}
|
|
5484
5547
|
const beforeSkills = payload?.collection ? listComposerSkills(PACKAGE_ROOT, root) : [];
|
|
5485
5548
|
const result = await runSkillhub(args, { cwd: root, timeoutMs: 180_000, maxBuffer: 4 * 1024 * 1024 });
|
|
5486
5549
|
if (!result.ok) {
|
|
@@ -5510,6 +5573,10 @@ export function startUiServer({
|
|
|
5510
5573
|
json(res, 400, { error: "Missing skill slug or collection" });
|
|
5511
5574
|
return;
|
|
5512
5575
|
}
|
|
5576
|
+
if (payload?.collection && !authUser?.isAdmin) {
|
|
5577
|
+
json(res, 403, { error: "Admin required" });
|
|
5578
|
+
return;
|
|
5579
|
+
}
|
|
5513
5580
|
const result = await runSkillhub(args, { cwd: root, timeoutMs: 120_000, maxBuffer: 4 * 1024 * 1024 });
|
|
5514
5581
|
if (!result.ok) {
|
|
5515
5582
|
json(res, 500, { error: result.error, stdout: result.stdout });
|
|
@@ -6499,6 +6566,10 @@ finishedAt: "${new Date().toISOString()}"
|
|
|
6499
6566
|
}
|
|
6500
6567
|
|
|
6501
6568
|
if (req.method === "POST" && url.pathname === "/api/skill-collections") {
|
|
6569
|
+
if (!authUser?.isAdmin) {
|
|
6570
|
+
json(res, 403, { error: "Admin required" });
|
|
6571
|
+
return;
|
|
6572
|
+
}
|
|
6502
6573
|
let payload;
|
|
6503
6574
|
try {
|
|
6504
6575
|
payload = JSON.parse(await readBody(req));
|