@fieldwangai/agentflow 0.1.54 → 0.1.55
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.
|
@@ -274,7 +274,7 @@ export function listNodesJson(workspaceRoot, flowId, flowSource, opts = {}) {
|
|
|
274
274
|
addFromDir(PACKAGE_BUILTIN_NODES_DIR, "project");
|
|
275
275
|
addFromDir(path.join(root, LEGACY_NODES_DIR), "project");
|
|
276
276
|
addFromDir(path.join(root, PROJECT_NODES_DIR), "project");
|
|
277
|
-
for (const manifest of listMarketplaceNodes(root, marketplaceFlowData)) {
|
|
277
|
+
for (const manifest of listMarketplaceNodes(root, marketplaceFlowData, opts)) {
|
|
278
278
|
let type = "agent";
|
|
279
279
|
const runtimeType = String(manifest.baseDefinitionId || manifest.runtime?.type || manifest.type || "").toLowerCase();
|
|
280
280
|
if (runtimeType.startsWith("control")) type = "control";
|
|
@@ -524,7 +524,7 @@ export function readNodeJson(workspaceRoot, nodeId, flowId, flowSource, opts = {
|
|
|
524
524
|
} catch (_) {}
|
|
525
525
|
}
|
|
526
526
|
}
|
|
527
|
-
const resolved = resolveMarketplaceNodePackage(root, flowDir, nodeId, opts.flowData || null);
|
|
527
|
+
const resolved = resolveMarketplaceNodePackage(root, flowDir, nodeId, opts.flowData || null, opts);
|
|
528
528
|
if (!resolved) return { error: "Node not found: " + nodeId };
|
|
529
529
|
const readmePath = path.join(resolved.packageDir, "README.md");
|
|
530
530
|
let type = "agent";
|
|
@@ -751,7 +751,7 @@ function resolveNodeFileScope(workspaceRoot, nodeId, flowId, flowSource, opts =
|
|
|
751
751
|
} catch (_) {}
|
|
752
752
|
}
|
|
753
753
|
}
|
|
754
|
-
const resolved = resolveMarketplaceNodePackage(workspaceRoot, flowDir, nodeId, flowData);
|
|
754
|
+
const resolved = resolveMarketplaceNodePackage(workspaceRoot, flowDir, nodeId, flowData, opts);
|
|
755
755
|
if (!resolved) return null;
|
|
756
756
|
return { baseDir: resolved.packageDir, allowAllFiles: true, primaryFilePath: path.join(resolved.packageDir, "node.yaml"), manifest: resolved };
|
|
757
757
|
}
|
package/bin/lib/marketplace.mjs
CHANGED
|
@@ -109,6 +109,17 @@ function normalizeManifest(raw, packageDir, source = "workspace") {
|
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
function manifestOwnerUserId(manifest) {
|
|
113
|
+
return String(manifest?.ownerUserId || manifest?.createdBy || "").trim();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function canAccessMarketplaceNode(manifest, opts = {}) {
|
|
117
|
+
const requestedUserId = String(opts.userId || "").trim();
|
|
118
|
+
if (!requestedUserId) return true;
|
|
119
|
+
if ((manifest?.source || "marketplace") !== "marketplace") return true;
|
|
120
|
+
return manifestOwnerUserId(manifest) === requestedUserId;
|
|
121
|
+
}
|
|
122
|
+
|
|
112
123
|
function sortVersionsDesc(versions) {
|
|
113
124
|
return [...versions].sort((a, b) => b.localeCompare(a, undefined, { numeric: true, sensitivity: "base" }));
|
|
114
125
|
}
|
|
@@ -297,12 +308,13 @@ function collectionDeps(flowData) {
|
|
|
297
308
|
return deps && Array.isArray(deps.collections) ? deps.collections : [];
|
|
298
309
|
}
|
|
299
310
|
|
|
300
|
-
export function resolveMarketplaceNodePackage(workspaceRoot, flowDir, definitionId, flowData = null) {
|
|
311
|
+
export function resolveMarketplaceNodePackage(workspaceRoot, flowDir, definitionId, flowData = null, opts = {}) {
|
|
301
312
|
const parsed = parseMarketplaceDefinitionId(definitionId);
|
|
302
313
|
if (!parsed) return null;
|
|
303
314
|
const id = parsed.id;
|
|
304
315
|
const requestedVersion = parsed.version || dependencyVersion(flowData, id) || lockVersion(flowDir, id);
|
|
305
316
|
let packageDir = findNodePackageDir(workspaceRoot, id, requestedVersion);
|
|
317
|
+
let packageSource = "marketplace";
|
|
306
318
|
|
|
307
319
|
if (!packageDir) {
|
|
308
320
|
for (const dir of iterCollectionNodeDirs(workspaceRoot, collectionDeps(flowData))) {
|
|
@@ -311,13 +323,15 @@ export function resolveMarketplaceNodePackage(workspaceRoot, flowDir, definition
|
|
|
311
323
|
if (!manifest || manifest.id !== id) continue;
|
|
312
324
|
if (requestedVersion && manifest.version !== requestedVersion) continue;
|
|
313
325
|
packageDir = dir;
|
|
326
|
+
packageSource = "collection";
|
|
314
327
|
break;
|
|
315
328
|
}
|
|
316
329
|
}
|
|
317
330
|
|
|
318
331
|
if (!packageDir) return null;
|
|
319
|
-
const manifest = normalizeManifest(readYamlObject(path.join(packageDir, NODE_MANIFEST)), packageDir);
|
|
332
|
+
const manifest = normalizeManifest(readYamlObject(path.join(packageDir, NODE_MANIFEST)), packageDir, packageSource);
|
|
320
333
|
if (!manifest) return null;
|
|
334
|
+
if (!canAccessMarketplaceNode(manifest, opts)) return null;
|
|
321
335
|
return {
|
|
322
336
|
...manifest,
|
|
323
337
|
requestedDefinitionId: definitionId,
|
|
@@ -325,13 +339,14 @@ export function resolveMarketplaceNodePackage(workspaceRoot, flowDir, definition
|
|
|
325
339
|
};
|
|
326
340
|
}
|
|
327
341
|
|
|
328
|
-
export function listMarketplaceNodes(workspaceRoot, flowData = null) {
|
|
342
|
+
export function listMarketplaceNodes(workspaceRoot, flowData = null, opts = {}) {
|
|
329
343
|
const root = workspacePackageRoot(workspaceRoot);
|
|
330
344
|
const out = [];
|
|
331
345
|
const seen = new Set();
|
|
332
346
|
const addManifest = (dir, source = "marketplace") => {
|
|
333
347
|
const manifest = normalizeManifest(readYamlObject(path.join(dir, NODE_MANIFEST)), dir, source);
|
|
334
348
|
if (!manifest) return;
|
|
349
|
+
if (!canAccessMarketplaceNode(manifest, opts)) return;
|
|
335
350
|
const key = `${manifest.id}@${manifest.version}`;
|
|
336
351
|
if (seen.has(key)) return;
|
|
337
352
|
seen.add(key);
|
|
@@ -357,7 +372,7 @@ export function listMarketplaceNodes(workspaceRoot, flowData = null) {
|
|
|
357
372
|
|
|
358
373
|
export function listMarketplacePackages(workspaceRoot, opts = {}) {
|
|
359
374
|
const root = workspacePackageRoot(workspaceRoot);
|
|
360
|
-
const nodes = listMarketplaceNodes(workspaceRoot).map((n) => ({
|
|
375
|
+
const nodes = listMarketplaceNodes(workspaceRoot, null, opts).map((n) => ({
|
|
361
376
|
id: n.id,
|
|
362
377
|
version: n.version,
|
|
363
378
|
definitionId: n.definitionId,
|
|
@@ -434,9 +449,15 @@ export function listMarketplaceFlowSnippets(workspaceRoot, opts = {}) {
|
|
|
434
449
|
export function deleteMarketplaceNodePackage(workspaceRoot, id, version, opts = {}) {
|
|
435
450
|
const packageDir = resolveWorkspaceNodePackageDir(workspaceRoot, id, version);
|
|
436
451
|
if (!packageDir) return { ok: false, error: "Invalid marketplace node id or version" };
|
|
437
|
-
|
|
452
|
+
const manifestPath = path.join(packageDir, NODE_MANIFEST);
|
|
453
|
+
if (!fs.existsSync(manifestPath)) {
|
|
438
454
|
return { ok: false, error: `Marketplace node package not found: ${id}@${version}` };
|
|
439
455
|
}
|
|
456
|
+
const manifest = normalizeManifest(readYamlObject(manifestPath), packageDir, "marketplace");
|
|
457
|
+
const requestedUserId = String(opts.userId || "").trim();
|
|
458
|
+
if (!requestedUserId || !manifest || manifestOwnerUserId(manifest) !== requestedUserId) {
|
|
459
|
+
return { ok: false, error: "Marketplace node permission denied" };
|
|
460
|
+
}
|
|
440
461
|
const usage = listMarketplaceNodeUsages(workspaceRoot, id, version, opts);
|
|
441
462
|
if (usage.length > 0) {
|
|
442
463
|
return { ok: false, error: "Marketplace node is still used by flows", usage };
|
|
@@ -478,12 +499,12 @@ export function deleteMarketplaceFlowSnippetPackage(workspaceRoot, id, version,
|
|
|
478
499
|
return { ok: true, id, version, packageDir };
|
|
479
500
|
}
|
|
480
501
|
|
|
481
|
-
export function writeFlowMarketplaceLock(workspaceRoot, flowDir, flowData) {
|
|
502
|
+
export function writeFlowMarketplaceLock(workspaceRoot, flowDir, flowData, opts = {}) {
|
|
482
503
|
if (!flowData || !flowData.instances || typeof flowData.instances !== "object") return null;
|
|
483
504
|
const nodes = {};
|
|
484
505
|
for (const inst of Object.values(flowData.instances)) {
|
|
485
506
|
const defId = inst && (inst.marketplaceRef || inst.definitionId);
|
|
486
|
-
const resolved = resolveMarketplaceNodePackage(workspaceRoot, flowDir, defId, flowData);
|
|
507
|
+
const resolved = resolveMarketplaceNodePackage(workspaceRoot, flowDir, defId, flowData, opts);
|
|
487
508
|
if (!resolved) continue;
|
|
488
509
|
nodes[resolved.id] = {
|
|
489
510
|
version: resolved.version,
|
|
@@ -674,6 +695,8 @@ export function publishNodeFromInstance(workspaceRoot, payload = {}, options = {
|
|
|
674
695
|
const version = normalizeVersion(payload.version || "1.0.0");
|
|
675
696
|
const sourceDefinitionId = String(payload.definitionId || "").trim();
|
|
676
697
|
if (!id) return { ok: false, error: "Invalid package id" };
|
|
698
|
+
const ownerUserId = String(options.userId || "").trim();
|
|
699
|
+
if (!ownerUserId) return { ok: false, error: "Authentication required" };
|
|
677
700
|
|
|
678
701
|
const inputs = normalizeSlotList(payload.inputs || payload.input).map((slot) => ({
|
|
679
702
|
type: slot.type,
|
|
@@ -693,6 +716,12 @@ export function publishNodeFromInstance(workspaceRoot, payload = {}, options = {
|
|
|
693
716
|
const body = String(payload.body || "").trim();
|
|
694
717
|
const description = String(payload.description || body || `Published from node ${label}`).trim();
|
|
695
718
|
const dest = path.join(workspacePackageRoot(workspaceRoot), "nodes", id, version);
|
|
719
|
+
const existingManifest = readYamlObject(path.join(dest, NODE_MANIFEST));
|
|
720
|
+
if (existingManifest) {
|
|
721
|
+
const existingOwner = manifestOwnerUserId(existingManifest);
|
|
722
|
+
if (existingOwner !== ownerUserId) return { ok: false, error: "Marketplace node permission denied" };
|
|
723
|
+
}
|
|
724
|
+
const now = new Date().toISOString();
|
|
696
725
|
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
697
726
|
fs.rmSync(dest, { recursive: true, force: true });
|
|
698
727
|
fs.mkdirSync(dest, { recursive: true });
|
|
@@ -722,6 +751,10 @@ export function publishNodeFromInstance(workspaceRoot, payload = {}, options = {
|
|
|
722
751
|
runtime,
|
|
723
752
|
inputs,
|
|
724
753
|
outputs,
|
|
754
|
+
ownerUserId,
|
|
755
|
+
createdBy: ownerUserId,
|
|
756
|
+
createdAt: existingManifest?.createdAt || now,
|
|
757
|
+
updatedAt: now,
|
|
725
758
|
};
|
|
726
759
|
if (packagedScript?.packagedFiles?.length) manifest.packagedFiles = packagedScript.packagedFiles;
|
|
727
760
|
fs.writeFileSync(path.join(dest, NODE_MANIFEST), yaml.dump(manifest, { lineWidth: -1 }), "utf-8");
|
|
@@ -803,10 +836,10 @@ export function publishFlowSnippet(workspaceRoot, payload = {}, opts = {}) {
|
|
|
803
836
|
return { ok: true, id, version, packageDir: dest, snippet: manifest.snippet };
|
|
804
837
|
}
|
|
805
838
|
|
|
806
|
-
export function installFlowDependency(workspaceRoot, flowDir, spec) {
|
|
839
|
+
export function installFlowDependency(workspaceRoot, flowDir, spec, opts = {}) {
|
|
807
840
|
const parsed = parseMarketplaceDefinitionId(spec.startsWith("marketplace:") ? spec : `marketplace:${spec}`);
|
|
808
841
|
if (!parsed) return { ok: false, error: `Invalid marketplace node spec: ${spec}` };
|
|
809
|
-
const resolved = resolveMarketplaceNodePackage(workspaceRoot, flowDir, `marketplace:${parsed.id}${parsed.version ? `@${parsed.version}` : ""}`, { dependencies: {} });
|
|
842
|
+
const resolved = resolveMarketplaceNodePackage(workspaceRoot, flowDir, `marketplace:${parsed.id}${parsed.version ? `@${parsed.version}` : ""}`, { dependencies: {} }, opts);
|
|
810
843
|
if (!resolved) return { ok: false, error: `Marketplace node not found: ${spec}` };
|
|
811
844
|
|
|
812
845
|
const flowYamlPath = path.join(flowDir, "flow.yaml");
|
|
@@ -818,6 +851,6 @@ export function installFlowDependency(workspaceRoot, flowDir, spec) {
|
|
|
818
851
|
if (!exists) nodes.push({ id: resolved.id, version: resolved.version });
|
|
819
852
|
data.dependencies = { ...deps, nodes };
|
|
820
853
|
fs.writeFileSync(flowYamlPath, yaml.dump(data, { lineWidth: -1 }), "utf-8");
|
|
821
|
-
writeFlowMarketplaceLock(workspaceRoot, flowDir, data);
|
|
854
|
+
writeFlowMarketplaceLock(workspaceRoot, flowDir, data, opts);
|
|
822
855
|
return { ok: true, id: resolved.id, version: resolved.version, definitionId: `marketplace:${resolved.id}@${resolved.version}` };
|
|
823
856
|
}
|
package/bin/lib/ui-server.mjs
CHANGED
|
@@ -4911,7 +4911,7 @@ export function startUiServer({
|
|
|
4911
4911
|
json(res, 400, { error: resolved.error || "Could not resolve flow directory" });
|
|
4912
4912
|
return;
|
|
4913
4913
|
}
|
|
4914
|
-
const result = installFlowDependency(root, resolved.flowDir, nodeSpec);
|
|
4914
|
+
const result = installFlowDependency(root, resolved.flowDir, nodeSpec, userCtx);
|
|
4915
4915
|
json(res, result.ok ? 200 : 400, result);
|
|
4916
4916
|
} catch (e) {
|
|
4917
4917
|
json(res, 500, { ok: false, error: (e && e.message) || String(e) });
|
|
@@ -4935,7 +4935,7 @@ export function startUiServer({
|
|
|
4935
4935
|
const resolved = resolveFlowDirForWrite(root, flowId, flowSource, userCtx);
|
|
4936
4936
|
if (!resolved.error && resolved.flowDir) flowDir = resolved.flowDir;
|
|
4937
4937
|
}
|
|
4938
|
-
const result = publishNodeFromInstance(root, payload || {}, { flowDir });
|
|
4938
|
+
const result = publishNodeFromInstance(root, payload || {}, { flowDir, ...userCtx });
|
|
4939
4939
|
json(res, result.ok ? 200 : 400, result);
|
|
4940
4940
|
} catch (e) {
|
|
4941
4941
|
json(res, 500, { ok: false, error: (e && e.message) || String(e) });
|