@fieldwangai/agentflow 0.1.68 → 0.1.69
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/admin-storage-config.mjs +93 -0
- package/bin/lib/marketplace.mjs +55 -3
- package/bin/lib/paths.mjs +43 -5
- package/bin/lib/ui-server.mjs +894 -25
- package/builtin/nodes/tool_git_checkout.md +1 -1
- package/builtin/nodes/tool_git_worktree_load.md +2 -1
- package/builtin/web-ui/dist/assets/index-CCvxfovU.css +1 -0
- package/builtin/web-ui/dist/assets/index-DvdPaPBL.js +296 -0
- package/builtin/web-ui/dist/index.html +2 -2
- package/package.json +1 -1
- package/builtin/web-ui/dist/assets/index-B7EYZmUN.css +0 -1
- package/builtin/web-ui/dist/assets/index-D3NG6W8U.js +0 -264
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import os from "os";
|
|
3
|
+
import path from "path";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
AGENTFLOW_HOME_CONFIG_PATH,
|
|
7
|
+
expandAgentflowHomePath,
|
|
8
|
+
getAgentflowDataRoot,
|
|
9
|
+
getAgentflowDataRootOverride,
|
|
10
|
+
writeAgentflowDataRootOverride,
|
|
11
|
+
} from "./paths.mjs";
|
|
12
|
+
|
|
13
|
+
function defaultAgentflowDataRoot() {
|
|
14
|
+
return path.join(os.homedir(), "agentflow");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function pathInside(parent, candidate) {
|
|
18
|
+
const base = path.resolve(parent);
|
|
19
|
+
const target = path.resolve(candidate);
|
|
20
|
+
return target === base || target.startsWith(base + path.sep);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function normalizeDataRoot(raw) {
|
|
24
|
+
const dataRoot = expandAgentflowHomePath(raw);
|
|
25
|
+
if (dataRoot && !path.isAbsolute(dataRoot)) {
|
|
26
|
+
throw new Error("dataRoot must be an absolute path");
|
|
27
|
+
}
|
|
28
|
+
return dataRoot;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function copyEntry(src, dest) {
|
|
32
|
+
const stat = fs.lstatSync(src);
|
|
33
|
+
if (stat.isSymbolicLink()) {
|
|
34
|
+
if (!fs.existsSync(dest)) fs.symlinkSync(fs.readlinkSync(src), dest);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (stat.isDirectory()) {
|
|
38
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
39
|
+
for (const name of fs.readdirSync(src)) {
|
|
40
|
+
copyEntry(path.join(src, name), path.join(dest, name));
|
|
41
|
+
}
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
45
|
+
fs.copyFileSync(src, dest);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function migrateDataRoot(oldRoot, newRoot) {
|
|
49
|
+
const from = path.resolve(oldRoot);
|
|
50
|
+
const to = path.resolve(newRoot);
|
|
51
|
+
if (from === to) return { migrated: false, copied: false };
|
|
52
|
+
if (pathInside(from, to)) {
|
|
53
|
+
throw new Error("dataRoot target cannot be inside the current data root");
|
|
54
|
+
}
|
|
55
|
+
if (pathInside(to, from)) {
|
|
56
|
+
throw new Error("dataRoot target cannot be a parent of the current data root");
|
|
57
|
+
}
|
|
58
|
+
fs.mkdirSync(to, { recursive: true });
|
|
59
|
+
if (!fs.existsSync(from)) return { migrated: true, copied: false };
|
|
60
|
+
for (const name of fs.readdirSync(from)) {
|
|
61
|
+
copyEntry(path.join(from, name), path.join(to, name));
|
|
62
|
+
}
|
|
63
|
+
return { migrated: true, copied: true };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function readAdminStorageConfig() {
|
|
67
|
+
const envDataRoot = normalizeDataRoot(process.env.AGENTFLOW_HOME || "");
|
|
68
|
+
const configuredDataRoot = getAgentflowDataRootOverride();
|
|
69
|
+
return {
|
|
70
|
+
version: 1,
|
|
71
|
+
dataRoot: getAgentflowDataRoot(),
|
|
72
|
+
configuredDataRoot,
|
|
73
|
+
defaultDataRoot: defaultAgentflowDataRoot(),
|
|
74
|
+
envDataRoot,
|
|
75
|
+
envLocked: Boolean(envDataRoot),
|
|
76
|
+
configPath: AGENTFLOW_HOME_CONFIG_PATH,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function writeAdminStorageConfig(config = {}) {
|
|
81
|
+
const current = readAdminStorageConfig();
|
|
82
|
+
if (current.envLocked) {
|
|
83
|
+
throw new Error("AGENTFLOW_HOME is set; update the environment variable instead of Admin Settings");
|
|
84
|
+
}
|
|
85
|
+
const nextRoot = normalizeDataRoot(config.dataRoot ?? "");
|
|
86
|
+
if (!nextRoot) throw new Error("dataRoot is required");
|
|
87
|
+
const migration = migrateDataRoot(current.dataRoot, nextRoot);
|
|
88
|
+
writeAgentflowDataRootOverride(nextRoot);
|
|
89
|
+
return {
|
|
90
|
+
...readAdminStorageConfig(),
|
|
91
|
+
migration,
|
|
92
|
+
};
|
|
93
|
+
}
|
package/bin/lib/marketplace.mjs
CHANGED
|
@@ -708,6 +708,47 @@ function buildPackagedRuntimeFromScript(command, destDir, opts = {}) {
|
|
|
708
708
|
};
|
|
709
709
|
}
|
|
710
710
|
|
|
711
|
+
function safePackageRefPath(raw) {
|
|
712
|
+
const text = String(raw || "").trim().replace(/^["']|["']$/g, "").replace(/\\/g, "/");
|
|
713
|
+
if (!text || path.isAbsolute(text) || text.includes("\n") || text.includes("\r")) return "";
|
|
714
|
+
const normalized = path.posix.normalize(text).replace(/^\/+/, "");
|
|
715
|
+
if (!normalized || normalized === "." || normalized.startsWith("../") || normalized.includes("/../")) return "";
|
|
716
|
+
return normalized;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
function packageNodeReferenceFiles(destDir, opts = {}) {
|
|
720
|
+
const flowDir = opts.flowDir ? path.resolve(opts.flowDir) : "";
|
|
721
|
+
const packagedFiles = [];
|
|
722
|
+
const result = {};
|
|
723
|
+
const copyRef = (rawRef, targetRel, key) => {
|
|
724
|
+
const clean = safePackageRefPath(rawRef);
|
|
725
|
+
if (!clean || !flowDir) return "";
|
|
726
|
+
const source = path.resolve(flowDir, ...clean.split("/"));
|
|
727
|
+
if (!isInsideDir(source, flowDir) || !fs.existsSync(source) || !fs.statSync(source).isFile()) return "";
|
|
728
|
+
const rel = targetRel.replace(/\\/g, "/");
|
|
729
|
+
const abs = path.join(destDir, rel);
|
|
730
|
+
fs.mkdirSync(path.dirname(abs), { recursive: true });
|
|
731
|
+
fs.copyFileSync(source, abs);
|
|
732
|
+
packagedFiles.push({ from: source, to: rel, role: key });
|
|
733
|
+
result[key] = rel;
|
|
734
|
+
return rel;
|
|
735
|
+
};
|
|
736
|
+
const scriptRef = copyRef(opts.scriptRef, `scripts/${path.basename(safePackageRefPath(opts.scriptRef) || "script.mjs")}`, "scriptRef");
|
|
737
|
+
const implementationRef = copyRef(opts.implementationRef, "implementation.md", "implementationRef");
|
|
738
|
+
let scriptRuntime = null;
|
|
739
|
+
if (scriptRef) {
|
|
740
|
+
const abs = path.join(destDir, scriptRef);
|
|
741
|
+
scriptRuntime = {
|
|
742
|
+
type: "tool_nodejs",
|
|
743
|
+
language: scriptLanguageFor("", scriptRef),
|
|
744
|
+
entry: scriptRef,
|
|
745
|
+
args: [],
|
|
746
|
+
};
|
|
747
|
+
if (!fs.existsSync(abs)) scriptRuntime = null;
|
|
748
|
+
}
|
|
749
|
+
return { ...result, packagedFiles, scriptRuntime };
|
|
750
|
+
}
|
|
751
|
+
|
|
711
752
|
export function publishNodeFromInstance(workspaceRoot, payload = {}, options = {}) {
|
|
712
753
|
const label = String(payload.label || payload.instanceId || "node").trim();
|
|
713
754
|
const id = safePackageId(payload.id || payload.packageId || label);
|
|
@@ -732,6 +773,9 @@ export function publishNodeFromInstance(workspaceRoot, payload = {}, options = {
|
|
|
732
773
|
...(slot.showOnNode != null ? { showOnNode: Boolean(slot.showOnNode) } : {}),
|
|
733
774
|
}));
|
|
734
775
|
const script = String(payload.script || "").trim();
|
|
776
|
+
const scriptRef = String(payload.scriptRef || "").trim();
|
|
777
|
+
const implementationRef = String(payload.implementationRef || "").trim();
|
|
778
|
+
const implementationMode = String(payload.implementationMode || "").trim();
|
|
735
779
|
const body = String(payload.body || "").trim();
|
|
736
780
|
const description = String(payload.description || body || `Published from node ${label}`).trim();
|
|
737
781
|
const dest = path.join(workspacePackageRoot(workspaceRoot), "nodes", id, version);
|
|
@@ -744,13 +788,18 @@ export function publishNodeFromInstance(workspaceRoot, payload = {}, options = {
|
|
|
744
788
|
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
745
789
|
fs.rmSync(dest, { recursive: true, force: true });
|
|
746
790
|
fs.mkdirSync(dest, { recursive: true });
|
|
791
|
+
const packagedRefs = packageNodeReferenceFiles(dest, {
|
|
792
|
+
flowDir: options.flowDir || payload.flowDir,
|
|
793
|
+
scriptRef,
|
|
794
|
+
implementationRef,
|
|
795
|
+
});
|
|
747
796
|
const packagedScript = script
|
|
748
797
|
? buildPackagedRuntimeFromScript(script, dest, {
|
|
749
798
|
flowDir: options.flowDir || payload.flowDir,
|
|
750
799
|
workspaceRoot,
|
|
751
800
|
})
|
|
752
801
|
: null;
|
|
753
|
-
const runtime = packagedScript?.runtime || (
|
|
802
|
+
const runtime = packagedScript?.runtime || packagedRefs.scriptRuntime || (
|
|
754
803
|
script
|
|
755
804
|
? {
|
|
756
805
|
type: "tool_nodejs",
|
|
@@ -775,7 +824,10 @@ export function publishNodeFromInstance(workspaceRoot, payload = {}, options = {
|
|
|
775
824
|
createdAt: existingManifest?.createdAt || now,
|
|
776
825
|
updatedAt: now,
|
|
777
826
|
};
|
|
778
|
-
if (
|
|
827
|
+
if (packagedRefs.implementationRef) manifest.implementationRef = packagedRefs.implementationRef;
|
|
828
|
+
if (implementationMode) manifest.implementationMode = implementationMode;
|
|
829
|
+
const packagedFiles = [...(packagedScript?.packagedFiles || []), ...(packagedRefs.packagedFiles || [])];
|
|
830
|
+
if (packagedFiles.length) manifest.packagedFiles = packagedFiles;
|
|
779
831
|
fs.writeFileSync(path.join(dest, NODE_MANIFEST), yaml.dump(manifest, { lineWidth: -1 }), "utf-8");
|
|
780
832
|
fs.writeFileSync(
|
|
781
833
|
path.join(dest, "README.md"),
|
|
@@ -791,7 +843,7 @@ export function publishNodeFromInstance(workspaceRoot, payload = {}, options = {
|
|
|
791
843
|
definitionId: `marketplace:${id}@${version}`,
|
|
792
844
|
baseDefinitionId: manifest.baseDefinitionId,
|
|
793
845
|
marketplaceDefinitionId: `marketplace:${id}@${version}`,
|
|
794
|
-
packagedFiles
|
|
846
|
+
packagedFiles,
|
|
795
847
|
};
|
|
796
848
|
}
|
|
797
849
|
|
package/bin/lib/paths.mjs
CHANGED
|
@@ -20,17 +20,55 @@ export const PACKAGE_AGENTS_DIR = path.join(PACKAGE_ROOT, "agents");
|
|
|
20
20
|
export const PACKAGE_AGENTS_JSON = path.join(PACKAGE_AGENTS_DIR, "agents.json");
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
-
* 用户级 AgentFlow 数据根目录:`AGENTFLOW_HOME` 或 `~/agentflow`。
|
|
23
|
+
* 用户级 AgentFlow 数据根目录:`AGENTFLOW_HOME`、`~/.agentflow/config.json:dataRoot` 或 `~/agentflow`。
|
|
24
24
|
* 与项目根 workspaceRoot 分离;run、pipelines、agents 等均落盘于此。
|
|
25
25
|
*/
|
|
26
|
+
export const AGENTFLOW_CONFIG_DIR = path.join(os.homedir(), ".agentflow");
|
|
27
|
+
export const AGENTFLOW_HOME_CONFIG_PATH = path.join(AGENTFLOW_CONFIG_DIR, "config.json");
|
|
28
|
+
|
|
29
|
+
export function expandAgentflowHomePath(rawPath) {
|
|
30
|
+
let raw = String(rawPath || "").trim();
|
|
31
|
+
if (!raw) return "";
|
|
32
|
+
if (raw === "~") raw = os.homedir();
|
|
33
|
+
else if (raw.startsWith("~/")) raw = path.join(os.homedir(), raw.slice(2));
|
|
34
|
+
return path.resolve(raw);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function readAgentflowHomeConfig() {
|
|
38
|
+
try {
|
|
39
|
+
if (!fs.existsSync(AGENTFLOW_HOME_CONFIG_PATH)) return {};
|
|
40
|
+
const parsed = JSON.parse(fs.readFileSync(AGENTFLOW_HOME_CONFIG_PATH, "utf-8"));
|
|
41
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
42
|
+
} catch {
|
|
43
|
+
return {};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function getAgentflowDataRootOverride() {
|
|
48
|
+
const config = readAgentflowHomeConfig();
|
|
49
|
+
return expandAgentflowHomePath(config.dataRoot || "");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function writeAgentflowDataRootOverride(dataRoot) {
|
|
53
|
+
const nextRoot = expandAgentflowHomePath(dataRoot);
|
|
54
|
+
if (nextRoot && !path.isAbsolute(nextRoot)) {
|
|
55
|
+
throw new Error("dataRoot must be an absolute path");
|
|
56
|
+
}
|
|
57
|
+
const current = readAgentflowHomeConfig();
|
|
58
|
+
const next = { ...current, dataRoot: nextRoot };
|
|
59
|
+
if (!nextRoot) delete next.dataRoot;
|
|
60
|
+
fs.mkdirSync(path.dirname(AGENTFLOW_HOME_CONFIG_PATH), { recursive: true });
|
|
61
|
+
fs.writeFileSync(AGENTFLOW_HOME_CONFIG_PATH, JSON.stringify(next, null, 2) + "\n", "utf-8");
|
|
62
|
+
return nextRoot;
|
|
63
|
+
}
|
|
64
|
+
|
|
26
65
|
export function getAgentflowDataRoot() {
|
|
27
66
|
const env = process.env.AGENTFLOW_HOME;
|
|
28
67
|
if (env != null && String(env).trim() !== "") {
|
|
29
|
-
|
|
30
|
-
if (raw === "~") raw = os.homedir();
|
|
31
|
-
else if (raw.startsWith("~/")) raw = path.join(os.homedir(), raw.slice(2));
|
|
32
|
-
return path.resolve(raw);
|
|
68
|
+
return expandAgentflowHomePath(env);
|
|
33
69
|
}
|
|
70
|
+
const configured = getAgentflowDataRootOverride();
|
|
71
|
+
if (configured) return configured;
|
|
34
72
|
return path.join(os.homedir(), "agentflow");
|
|
35
73
|
}
|
|
36
74
|
|