@fieldwangai/agentflow 0.1.162 → 0.1.163
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/flow-dsl/codegen.mjs +23 -2
- package/bin/lib/flow-dsl/lint.mjs +44 -0
- package/bin/lib/flow-dsl/parser.mjs +68 -1
- package/bin/lib/marketplace-usage.mjs +218 -0
- package/bin/lib/marketplace.mjs +183 -3
- package/bin/lib/node-package-manifest.mjs +1 -1
- package/bin/lib/spaces.mjs +200 -0
- package/bin/lib/ui-server.mjs +251 -67
- package/bin/lib/workspace-routes.mjs +189 -2
- package/bin/lib/workspace-server.mjs +367 -30
- package/bin/lib/workspace-state.mjs +2 -1
- package/builtin/nodes/agent_subAgent.md +5 -1
- package/builtin/nodes/context_bundle.md +44 -0
- package/builtin/nodes/context_knowledge.md +29 -0
- package/builtin/nodes/context_skills.md +29 -0
- package/builtin/nodes/context_workspace.md +36 -0
- package/builtin/nodes/control_while.md +7 -0
- package/builtin/nodes/tool_git_worktree_load.md +4 -3
- package/builtin/web-ui/dist/assets/{WorkflowAssistantThread-CTrXOZ00.js → WorkflowAssistantThread-DmhIgoD7.js} +1 -1
- package/builtin/web-ui/dist/assets/index-CI9J6Unt.js +873 -0
- package/builtin/web-ui/dist/assets/index-DY5vE7v1.css +1 -0
- package/builtin/web-ui/dist/index.html +2 -2
- package/package.json +1 -1
- package/shared/slot-types.js +1 -0
- package/skills/agentflow-cli/SKILL.md +50 -3
- package/skills/agentflow-cli/runtime/bin/lib/skill-runtime.mjs +120 -6
- package/skills/agentflow-cli/runtime/builtin/nodes/agent_subAgent.md +5 -1
- package/skills/agentflow-cli/runtime/builtin/nodes/context_bundle.md +44 -0
- package/skills/agentflow-cli/runtime/builtin/nodes/context_knowledge.md +29 -0
- package/skills/agentflow-cli/runtime/builtin/nodes/context_skills.md +29 -0
- package/skills/agentflow-cli/runtime/builtin/nodes/context_workspace.md +36 -0
- package/skills/agentflow-cli/runtime/builtin/nodes/control_while.md +7 -0
- package/skills/agentflow-cli/runtime/builtin/nodes/tool_git_worktree_load.md +4 -3
- package/skills/agentflow-cli/runtime/package.json +1 -1
- package/skills/agentflow-cli/scripts/agentflow-cli.mjs +64 -0
- package/skills/agentflow-flow-dsl/SKILL.md +48 -2
- package/skills/agentflow-flow-dsl/references/node-calls.md +6 -2
- package/skills/agentflow-flow-dsl/references/subflow-authoring.md +34 -7
- package/skills/agentflow-node-reference/references/builtin-nodes.md +37 -5
- package/builtin/web-ui/dist/assets/index-5uJFccdX.css +0 -1
- package/builtin/web-ui/dist/assets/index-BeUfNQRL.js +0 -873
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
@keyframes af-app-loading-slide { from { transform: translateX(-115%); } to { transform: translateX(250%); } }
|
|
31
31
|
@media (prefers-reduced-motion: reduce) { .af-app-loading__track span { width: 100%; animation: none; } }
|
|
32
32
|
</style>
|
|
33
|
-
<script type="module" crossorigin src="/assets/index-
|
|
34
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
33
|
+
<script type="module" crossorigin src="/assets/index-CI9J6Unt.js"></script>
|
|
34
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DY5vE7v1.css">
|
|
35
35
|
</head>
|
|
36
36
|
<body>
|
|
37
37
|
<div id="root">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fieldwangai/agentflow",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.163",
|
|
4
4
|
"description": "Orchestration system for long-running complex agent tasks using Cursor, OpenCode, Claude Code, or Codex as execution backends",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "bin/agentflow.mjs",
|
package/shared/slot-types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: agentflow-cli
|
|
3
|
-
description: Direct AgentFlow operation through a bundled browser-authorized CLI, without MCP or npm. Use when Codex needs to authorize AgentFlow access, create, update, run, or publish temporary Workspace drafts; search
|
|
3
|
+
description: Direct AgentFlow operation through a bundled browser-authorized CLI, without MCP or npm. Use when Codex needs to authorize AgentFlow access, create, update, run, or publish temporary Workspace drafts; search usage-ranked Marketplace Flow templates and nodes; publish, install, privatize, or synchronize versioned resources; pull or publish portable Workspace DSL flows; manage scheduled runs; upload read-only previews; run or inspect Workspace graphs; or read logs and display outputs through AgentFlow HTTP APIs.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# AgentFlow CLI
|
|
@@ -152,7 +152,8 @@ node <skill-dir>/scripts/agentflow-cli.mjs node-package-install \
|
|
|
152
152
|
```
|
|
153
153
|
|
|
154
154
|
Before authoring a new code node, search the remote catalog. The result is structured JSON with the
|
|
155
|
-
exact import specifier, input/output slots, content hash,
|
|
155
|
+
exact import specifier, input/output slots, content hash, visibility, install hint, and server-owned
|
|
156
|
+
`useCount` / `installCount` / `uniqueUserCount` statistics:
|
|
156
157
|
|
|
157
158
|
```bash
|
|
158
159
|
node <skill-dir>/scripts/agentflow-cli.mjs node-package-search --query "read csv"
|
|
@@ -161,6 +162,52 @@ node <skill-dir>/scripts/agentflow-cli.mjs node-package-search --query "read csv
|
|
|
161
162
|
Prefer an existing suitable exact version. Install it and import its returned `specifier`; create a
|
|
162
163
|
new local package only when no result meets the requested behavior.
|
|
163
164
|
|
|
165
|
+
## Marketplace resources
|
|
166
|
+
|
|
167
|
+
List complete runnable Flow templates or node packages. Results are public resources by default,
|
|
168
|
+
ordered by `useCount DESC`, and always include the usage statistics in their JSON records:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
node <skill-dir>/scripts/agentflow-cli.mjs marketplace-list --kind flow
|
|
172
|
+
node <skill-dir>/scripts/agentflow-cli.mjs marketplace-list --kind node --query "用户校验"
|
|
173
|
+
node <skill-dir>/scripts/agentflow-cli.mjs marketplace-list --kind flow --owned
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
`--owned` includes the current user's private resources. Creating or testing a Draft never exposes
|
|
177
|
+
it. Publishing to the Marketplace is a separate explicit operation; it defaults to public, strips
|
|
178
|
+
runtime state, and disables Scheduled Run entries in the immutable template snapshot:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
node <skill-dir>/scripts/agentflow-cli.mjs marketplace-flow-publish \
|
|
182
|
+
--flow-id user-import-validation \
|
|
183
|
+
--flow-source user \
|
|
184
|
+
--version 1.0.0 \
|
|
185
|
+
--visibility public
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Install a public or owned private template into the caller's personal space. Installation creates a
|
|
189
|
+
copy, records its Marketplace origin for later successful-run accounting, and keeps scheduling
|
|
190
|
+
disabled until the installer explicitly enables it:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
node <skill-dir>/scripts/agentflow-cli.mjs marketplace-flow-install \
|
|
194
|
+
--flow user-import-validation@1.0.0 \
|
|
195
|
+
--flow-id my-user-import-validation
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Owners can stop discovery and new installation without deleting already installed copies:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
node <skill-dir>/scripts/agentflow-cli.mjs marketplace-visibility \
|
|
202
|
+
--kind flow \
|
|
203
|
+
--resource user-import-validation@1.0.0 \
|
|
204
|
+
--visibility private
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
The same command supports `--kind node`. Never infer Marketplace publication from ordinary
|
|
208
|
+
`publish-flow`: that command writes an editable personal/workspace/team Flow, while
|
|
209
|
+
`marketplace-flow-publish` creates a reusable immutable template.
|
|
210
|
+
|
|
164
211
|
When a Flow already declares its dependencies, do not install packages one by one. Synchronize the
|
|
165
212
|
whole Flow from its versioned imports:
|
|
166
213
|
|
|
@@ -409,7 +456,7 @@ The only admin write exception is audited version-membership repair. Read its st
|
|
|
409
456
|
|
|
410
457
|
1. Check authorization with `config`. If missing, use `auth start`, give the URL to the user, then
|
|
411
458
|
run `auth complete` only after the user approves it.
|
|
412
|
-
2. Use `list-workspace` or `list-flows` to discover Flow/Pipeline targets only. Use `node-package-search` before creating a new
|
|
459
|
+
2. Use `list-workspace` or `list-flows` to discover Flow/Pipeline targets only. Use `marketplace-list` or `node-package-search` before creating a new Flow/node; both expose usage counts for comparison. Use `publish-flow` only after a local Flow has passed validation and the user has confirmed the preview, and use `marketplace-flow-publish` only after the user explicitly wants a reusable Marketplace snapshot.
|
|
413
460
|
3. For a new user-authored Flow, prefer `draft-create` → `draft-run`/`draft-update` → explicit user confirmation → `draft-publish`. Keep `workspace-preview` for read-only sharing.
|
|
414
461
|
4. Use `run` to start a published flow. If the task needs the generated page/text, inspect returned `displayOutputs` or call `display-outputs`.
|
|
415
462
|
5. Use `status`, `list-run-by-workspace`, and `logs` when a run is active, failed, or needs debugging. Use `schedule-list` after every schedule mutation or scheduled publish.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Generated by scripts/build-agentflow-cli-skill-runtime.mjs for AgentFlow 0.1.
|
|
1
|
+
// Generated by scripts/build-agentflow-cli-skill-runtime.mjs for AgentFlow 0.1.162.
|
|
2
2
|
var __create = Object.create;
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -1859,9 +1859,10 @@ function isDisplayDefinition(definitionId) {
|
|
|
1859
1859
|
function isSemanticInputSlot(slot) {
|
|
1860
1860
|
const name = String(slot?.name || "");
|
|
1861
1861
|
const type2 = String(slot?.type || "");
|
|
1862
|
-
return type2 === "node" || name === "prev" || name === "next" || CONTEXT_SLOT_NAMES.has(name);
|
|
1862
|
+
return type2 === "node" || type2 === "context" || name === "prev" || name === "next" || CONTEXT_SLOT_NAMES.has(name);
|
|
1863
1863
|
}
|
|
1864
1864
|
var CONTEXT_SLOT_NAMES = /* @__PURE__ */ new Set([
|
|
1865
|
+
"context",
|
|
1865
1866
|
"skillsContext",
|
|
1866
1867
|
"mcpContext",
|
|
1867
1868
|
"knowledgeContext",
|
|
@@ -10650,7 +10651,7 @@ function normalizeNodeUiForSlots(value, inputs = [], outputs = []) {
|
|
|
10650
10651
|
|
|
10651
10652
|
// bin/lib/node-package-manifest.mjs
|
|
10652
10653
|
var NODE_PACKAGE_ENTRY = "index.mjs";
|
|
10653
|
-
var SLOT_TYPES = /* @__PURE__ */ new Set(["text", "file", "bool", "node", "image", "json"]);
|
|
10654
|
+
var SLOT_TYPES = /* @__PURE__ */ new Set(["text", "file", "bool", "node", "image", "json", "context"]);
|
|
10654
10655
|
function staticEval(node, where) {
|
|
10655
10656
|
if (!node) throw new Error(`${where}: \u7A7A\u8868\u8FBE\u5F0F`);
|
|
10656
10657
|
switch (node.type) {
|
|
@@ -12561,7 +12562,7 @@ function generateFlowSource(ir, opts = {}) {
|
|
|
12561
12562
|
taken.add(name);
|
|
12562
12563
|
return name;
|
|
12563
12564
|
};
|
|
12564
|
-
const flowApiRoots = ["agent", "control", "display", "file", "flow", "provide", "tool", "workspace"];
|
|
12565
|
+
const flowApiRoots = ["agent", "context", "control", "display", "file", "flow", "provide", "tool", "workspace"];
|
|
12565
12566
|
const flowApiBinding = new Map(flowApiRoots.map((root) => [root, uniqueName(root, `${root}Api`)]));
|
|
12566
12567
|
const apiCall = (name) => {
|
|
12567
12568
|
const [root, ...tail] = String(name || "").split(".");
|
|
@@ -12654,6 +12655,12 @@ function generateFlowSource(ir, opts = {}) {
|
|
|
12654
12655
|
const pinValue = (id, name, value) => {
|
|
12655
12656
|
const text = String(value);
|
|
12656
12657
|
if (slotTypeOf(id, name) === "bool" && (text === "true" || text === "false")) return text;
|
|
12658
|
+
if (slotTypeOf(id, name) === "json") {
|
|
12659
|
+
try {
|
|
12660
|
+
return JSON.stringify(JSON.parse(text), null, 2);
|
|
12661
|
+
} catch {
|
|
12662
|
+
}
|
|
12663
|
+
}
|
|
12657
12664
|
return textArg(id, name, text);
|
|
12658
12665
|
};
|
|
12659
12666
|
function pinsObject(id, folds = /* @__PURE__ */ new Map()) {
|
|
@@ -12670,7 +12677,17 @@ function generateFlowSource(ir, opts = {}) {
|
|
|
12670
12677
|
const key = isIdentifier(name) ? name : JSON.stringify(name);
|
|
12671
12678
|
if (wired.has(name)) {
|
|
12672
12679
|
const x2 = wired.get(name);
|
|
12673
|
-
|
|
12680
|
+
const sourceDefinitionId = N[x2.from]?.definitionId;
|
|
12681
|
+
const bundleAlias = node.definitionId === "context_bundle" ? { knowledgeContext: "knowledge", skillsContext: "skills", workspaceContext: "workspace", mcpContext: "mcp" }[name] || "" : "";
|
|
12682
|
+
const contextResourceOutput = {
|
|
12683
|
+
context_knowledge: "knowledgeContext",
|
|
12684
|
+
context_skills: "skillsContext",
|
|
12685
|
+
context_workspace: "workspaceContext"
|
|
12686
|
+
}[sourceDefinitionId] || "";
|
|
12687
|
+
const directContextBundle = name === "context" && sourceDefinitionId === "context_bundle" && x2.fromSlot === "context";
|
|
12688
|
+
const renderedKey = bundleAlias || key;
|
|
12689
|
+
const renderedValue = directContextBundle || bundleAlias && contextResourceOutput === name && x2.fromSlot === name ? x2.from : outVar.get(`${x2.from}|${x2.fromSlot}`) || `${x2.from}.${x2.fromSlot}`;
|
|
12690
|
+
lines.push(`${renderedKey}: ${renderedValue}`);
|
|
12674
12691
|
continue;
|
|
12675
12692
|
}
|
|
12676
12693
|
if (node.inputs[name] !== void 0) {
|
|
@@ -13196,6 +13213,36 @@ function parseFlowSource(source, opts = {}) {
|
|
|
13196
13213
|
}
|
|
13197
13214
|
return null;
|
|
13198
13215
|
}
|
|
13216
|
+
function staticJsonOf(node) {
|
|
13217
|
+
if (!node) return { ok: false, value: null };
|
|
13218
|
+
if (node.type === "Literal") return { ok: true, value: node.value };
|
|
13219
|
+
if (node.type === "UnaryExpression" && (node.operator === "-" || node.operator === "+") && node.argument.type === "Literal" && typeof node.argument.value === "number") {
|
|
13220
|
+
return { ok: true, value: node.operator === "-" ? -node.argument.value : node.argument.value };
|
|
13221
|
+
}
|
|
13222
|
+
if (node.type === "TemplateLiteral" && node.expressions.length === 0) {
|
|
13223
|
+
return { ok: true, value: node.quasis[0].value.cooked };
|
|
13224
|
+
}
|
|
13225
|
+
if (node.type === "ArrayExpression") {
|
|
13226
|
+
const value = [];
|
|
13227
|
+
for (const item of node.elements) {
|
|
13228
|
+
const parsed = staticJsonOf(item);
|
|
13229
|
+
if (!parsed.ok) return { ok: false, value: null };
|
|
13230
|
+
value.push(parsed.value);
|
|
13231
|
+
}
|
|
13232
|
+
return { ok: true, value };
|
|
13233
|
+
}
|
|
13234
|
+
if (node.type === "ObjectExpression") {
|
|
13235
|
+
const value = {};
|
|
13236
|
+
for (const prop of node.properties) {
|
|
13237
|
+
if (prop.type !== "Property" || prop.computed || prop.kind !== "init") return { ok: false, value: null };
|
|
13238
|
+
const parsed = staticJsonOf(prop.value);
|
|
13239
|
+
if (!parsed.ok) return { ok: false, value: null };
|
|
13240
|
+
value[String(prop.key.name ?? prop.key.value ?? "")] = parsed.value;
|
|
13241
|
+
}
|
|
13242
|
+
return { ok: true, value };
|
|
13243
|
+
}
|
|
13244
|
+
return { ok: false, value: null };
|
|
13245
|
+
}
|
|
13199
13246
|
const packageOf = /* @__PURE__ */ new Map();
|
|
13200
13247
|
for (const stmt of ast.body) {
|
|
13201
13248
|
if (stmt.type !== "ImportDeclaration") continue;
|
|
@@ -13264,6 +13311,8 @@ function parseFlowSource(source, opts = {}) {
|
|
|
13264
13311
|
const def = definitionOf(definitionId);
|
|
13265
13312
|
const defInputs = new Set(def.input.map((s) => s.name));
|
|
13266
13313
|
const defOutputs = new Set(def.output.map((s) => s.name));
|
|
13314
|
+
const inputType = new Map(def.input.map((s) => [s.name, String(s.type || "text")]));
|
|
13315
|
+
const outputType = new Map(def.output.map((s) => [s.name, String(s.type || "text")]));
|
|
13267
13316
|
const node = nodes[id];
|
|
13268
13317
|
if (!obj || obj.type !== "ObjectExpression") return;
|
|
13269
13318
|
for (const prop of obj.properties) {
|
|
@@ -13275,8 +13324,23 @@ function parseFlowSource(source, opts = {}) {
|
|
|
13275
13324
|
unresolvedAt(prop, `${id}: \u5F15\u811A\u540D\u4E0D\u80FD\u662F\u52A8\u6001\u8868\u8FBE\u5F0F`);
|
|
13276
13325
|
continue;
|
|
13277
13326
|
}
|
|
13278
|
-
const
|
|
13327
|
+
const rawKey = prop.key.name ?? prop.key.value;
|
|
13328
|
+
const key = definitionId === "context_bundle" ? { knowledge: "knowledgeContext", skills: "skillsContext", workspace: "workspaceContext", mcp: "mcpContext" }[rawKey] || rawKey : rawKey;
|
|
13279
13329
|
const isCustom = !STD_SLOTS.has(key) && !defInputs.has(key);
|
|
13330
|
+
if (prop.value.type === "Identifier" && nodes[prop.value.name]) {
|
|
13331
|
+
const sourceDefinitionId = nodes[prop.value.name].definitionId;
|
|
13332
|
+
const contextOutput = {
|
|
13333
|
+
context_knowledge: "knowledgeContext",
|
|
13334
|
+
context_skills: "skillsContext",
|
|
13335
|
+
context_workspace: "workspaceContext",
|
|
13336
|
+
context_bundle: "context"
|
|
13337
|
+
}[sourceDefinitionId];
|
|
13338
|
+
if (contextOutput && (definitionId === "context_bundle" && key === contextOutput || key === "context" && sourceDefinitionId === "context_bundle")) {
|
|
13339
|
+
edges.push(`${prop.value.name}|${contextOutput}|${id}|${key}`);
|
|
13340
|
+
if (isCustom) node.extraIn.push(key);
|
|
13341
|
+
continue;
|
|
13342
|
+
}
|
|
13343
|
+
}
|
|
13280
13344
|
const member = memberPath(prop.value);
|
|
13281
13345
|
if (member) {
|
|
13282
13346
|
edges.push(`${member[0]}|${member[1]}|${id}|${key}`);
|
|
@@ -13294,6 +13358,15 @@ function parseFlowSource(source, opts = {}) {
|
|
|
13294
13358
|
continue;
|
|
13295
13359
|
}
|
|
13296
13360
|
const text = stringOf(prop.value);
|
|
13361
|
+
if (text === null && (inputType.get(key) === "json" || outputType.get(key) === "json")) {
|
|
13362
|
+
const parsed = staticJsonOf(prop.value);
|
|
13363
|
+
if (parsed.ok) {
|
|
13364
|
+
if (defOutputs.has(key) && !defInputs.has(key)) node.outputs[key] = JSON.stringify(parsed.value);
|
|
13365
|
+
else node.inputs[key] = JSON.stringify(parsed.value);
|
|
13366
|
+
if (isCustom) node.extraIn.push(key);
|
|
13367
|
+
continue;
|
|
13368
|
+
}
|
|
13369
|
+
}
|
|
13297
13370
|
if (text === null) {
|
|
13298
13371
|
unresolvedAt(prop, `${id}.${key}: \u5F15\u811A\u503C\u65E2\u4E0D\u662F\u4E0A\u6E38\u5F15\u7528\u4E5F\u4E0D\u662F\u5B57\u9762\u91CF`);
|
|
13299
13372
|
continue;
|
|
@@ -14177,6 +14250,7 @@ var SLOT_TYPE_COLORS = Object.freeze({
|
|
|
14177
14250
|
node: "#ff9800",
|
|
14178
14251
|
bool: "#9c27b0",
|
|
14179
14252
|
json: "#00bcd4",
|
|
14253
|
+
context: "#7c5cff",
|
|
14180
14254
|
image: "#ec407a",
|
|
14181
14255
|
any: "#9e9e9e"
|
|
14182
14256
|
});
|
|
@@ -14225,6 +14299,15 @@ function declaredSlotType(node, kind, name) {
|
|
|
14225
14299
|
if (kind === "input" && node?.inputTypes?.[name]) return String(node.inputTypes[name]);
|
|
14226
14300
|
return "";
|
|
14227
14301
|
}
|
|
14302
|
+
function parseJsonInput(node, name) {
|
|
14303
|
+
const raw = String(node?.inputs?.[name] || "").trim();
|
|
14304
|
+
if (!raw) return { value: null, error: "\u4E3A\u7A7A" };
|
|
14305
|
+
try {
|
|
14306
|
+
return { value: JSON.parse(raw), error: "" };
|
|
14307
|
+
} catch (error) {
|
|
14308
|
+
return { value: null, error: error.message };
|
|
14309
|
+
}
|
|
14310
|
+
}
|
|
14228
14311
|
function walk(node, visit) {
|
|
14229
14312
|
if (!node || typeof node !== "object") return;
|
|
14230
14313
|
if (node.type) visit(node);
|
|
@@ -14325,6 +14408,29 @@ function lintFlowDir(flowDir, opts = {}) {
|
|
|
14325
14408
|
if (definitionId === "control_subflow_call" && !subflows[node.attrs?.subflowId]) {
|
|
14326
14409
|
errors.push(`${id}: \u5F15\u7528\u7684\u5B50\u6D41\u7A0B ${node.attrs?.subflowId || "(empty)"} \u4E0D\u5B58\u5728`);
|
|
14327
14410
|
}
|
|
14411
|
+
if (definitionId === "context_knowledge") {
|
|
14412
|
+
const parsed = parseJsonInput(node, "workspaceIds");
|
|
14413
|
+
if (parsed.error) errors.push(`${id}: context.knowledge workspaceIds \u5FC5\u987B\u662F JSON \u6570\u7EC4\uFF08${parsed.error}\uFF09`);
|
|
14414
|
+
else if (!Array.isArray(parsed.value) || parsed.value.length === 0) errors.push(`${id}: context.knowledge \u81F3\u5C11\u9009\u62E9\u4E00\u4E2A Workspace ID`);
|
|
14415
|
+
else if (parsed.value.some((value) => typeof value !== "string" || !String(value).trim())) errors.push(`${id}: context.knowledge workspaceIds \u53EA\u80FD\u5305\u542B\u975E\u7A7A\u5B57\u7B26\u4E32 ID`);
|
|
14416
|
+
}
|
|
14417
|
+
if (definitionId === "context_skills") {
|
|
14418
|
+
const parsed = parseJsonInput(node, "skills");
|
|
14419
|
+
if (parsed.error) errors.push(`${id}: context.skills skills \u5FC5\u987B\u662F JSON \u6570\u7EC4\uFF08${parsed.error}\uFF09`);
|
|
14420
|
+
else if (!Array.isArray(parsed.value) || parsed.value.length === 0) errors.push(`${id}: context.skills \u81F3\u5C11\u58F0\u660E\u4E00\u4E2A skill`);
|
|
14421
|
+
}
|
|
14422
|
+
if (definitionId === "context_workspace") {
|
|
14423
|
+
const workspaceId = String(node.inputs?.workspaceId || "current").trim();
|
|
14424
|
+
const access = String(node.inputs?.access || "read-write").trim().toLowerCase();
|
|
14425
|
+
if (!workspaceId) errors.push(`${id}: context.workspace workspaceId \u4E0D\u80FD\u4E3A\u7A7A`);
|
|
14426
|
+
if (!["read-only", "read-write"].includes(access)) errors.push(`${id}: context.workspace access \u53EA\u80FD\u662F read-only \u6216 read-write`);
|
|
14427
|
+
}
|
|
14428
|
+
if (definitionId === "context_bundle") {
|
|
14429
|
+
const incoming = ir.edges.filter((edge) => edge.split("|")[2] === id && edge.split("|")[3] !== "prev");
|
|
14430
|
+
if (!incoming.length) errors.push(`${id}: context.bundle \u81F3\u5C11\u8FDE\u63A5\u4E00\u4E2A Context \u8D44\u6E90`);
|
|
14431
|
+
const literal3 = Object.entries(node.inputs || {}).filter(([, value]) => String(value || "").trim());
|
|
14432
|
+
if (literal3.length) errors.push(`${id}: context.bundle \u53EA\u80FD\u8FDE\u63A5\u8D44\u6E90\u8282\u70B9\uFF0C\u4E0D\u80FD\u5185\u5D4C Context \u6B63\u6587`);
|
|
14433
|
+
}
|
|
14328
14434
|
if (definitionId === "control_while") {
|
|
14329
14435
|
const conditionId = String(node.attrs?.conditionSubflowId || "");
|
|
14330
14436
|
const bodyId = String(node.attrs?.bodySubflowId || "");
|
|
@@ -14352,9 +14458,11 @@ function lintFlowDir(flowDir, opts = {}) {
|
|
|
14352
14458
|
}
|
|
14353
14459
|
if (body && !body.outputs?.state) errors.push(`${id}: Body \u5B50\u6D41\u7A0B ${bodyId} \u7F3A\u5C11\u8F93\u51FA state`);
|
|
14354
14460
|
for (const [contract, name, expected] of [
|
|
14461
|
+
[condition?.inputs, "context", "context"],
|
|
14355
14462
|
[condition?.inputs, "state", "json"],
|
|
14356
14463
|
[condition?.inputs, "iteration", "text"],
|
|
14357
14464
|
[condition?.outputs, "decision", "text"],
|
|
14465
|
+
[body?.inputs, "context", "context"],
|
|
14358
14466
|
[body?.inputs, "state", "json"],
|
|
14359
14467
|
[body?.inputs, "iteration", "text"],
|
|
14360
14468
|
[body?.inputs, "idempotencyKey", "text"],
|
|
@@ -14386,6 +14494,12 @@ function lintFlowDir(flowDir, opts = {}) {
|
|
|
14386
14494
|
for (const slot of node.extraIn) if (!defIn.has(slot)) errors.push(`${id}[${definitionId}]: \u4E0D\u5B58\u5728\u7684\u8F93\u5165\u69FD "${slot}"`);
|
|
14387
14495
|
for (const slot of node.extraOut) if (!defOut.has(slot)) errors.push(`${id}[${definitionId}]: \u4E0D\u5B58\u5728\u7684\u8F93\u51FA\u69FD "${slot}"`);
|
|
14388
14496
|
}
|
|
14497
|
+
if (definitionId === "agent_subAgent") {
|
|
14498
|
+
const incomingNames = new Set(ir.edges.map((edge) => edge.split("|")).filter((parts) => parts[2] === id).map((parts) => parts[3]));
|
|
14499
|
+
if (incomingNames.has("context") && ["knowledgeContext", "skillsContext", "workspaceContext", "mcpContext"].some((name) => incomingNames.has(name))) {
|
|
14500
|
+
warnings.push(`${id}: \u5DF2\u8FDE\u63A5 context Bundle\uFF0C\u4E0D\u8981\u518D\u91CD\u590D\u8FDE\u63A5\u65E7 Context \u6587\u672C\u5F15\u811A`);
|
|
14501
|
+
}
|
|
14502
|
+
}
|
|
14389
14503
|
}
|
|
14390
14504
|
const inputSeen = /* @__PURE__ */ new Map();
|
|
14391
14505
|
const adjacency = /* @__PURE__ */ new Map();
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
---
|
|
2
2
|
# 内置节点:子 Agent
|
|
3
3
|
runtime: native
|
|
4
|
-
description: 利用子 Agent
|
|
4
|
+
description: 利用子 Agent 执行任务;新流程优先接收一个强类型 context Bundle。knowledgeContext、workspaceContext、skillsContext、mcpContext 保留为旧流程兼容引脚。
|
|
5
5
|
displayName: 子 Agent
|
|
6
6
|
input:
|
|
7
7
|
- type: node
|
|
8
8
|
name: prev
|
|
9
9
|
default: ""
|
|
10
|
+
- type: context
|
|
11
|
+
name: context
|
|
12
|
+
default: ""
|
|
13
|
+
showOnNode: true
|
|
10
14
|
- type: text
|
|
11
15
|
name: workspaceContext
|
|
12
16
|
default: ""
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Built-in node: Context Bundle
|
|
3
|
+
runtime: native
|
|
4
|
+
type: provide
|
|
5
|
+
description: Compose knowledge, skills, workspace, and MCP resources into one strongly typed Context value that can cross Agent, Subflow, and While boundaries.
|
|
6
|
+
displayName: Context Bundle
|
|
7
|
+
ui:
|
|
8
|
+
card:
|
|
9
|
+
template: context-resource
|
|
10
|
+
icon: hub
|
|
11
|
+
tone: purple
|
|
12
|
+
sections:
|
|
13
|
+
- type: context
|
|
14
|
+
label: Context resources
|
|
15
|
+
inputs:
|
|
16
|
+
- name: knowledgeContext
|
|
17
|
+
label: Knowledge
|
|
18
|
+
- name: skillsContext
|
|
19
|
+
label: Skills
|
|
20
|
+
- name: workspaceContext
|
|
21
|
+
label: Workspace
|
|
22
|
+
- name: mcpContext
|
|
23
|
+
label: MCP
|
|
24
|
+
input:
|
|
25
|
+
- type: text
|
|
26
|
+
name: knowledgeContext
|
|
27
|
+
default: ""
|
|
28
|
+
- type: text
|
|
29
|
+
name: skillsContext
|
|
30
|
+
default: ""
|
|
31
|
+
- type: text
|
|
32
|
+
name: workspaceContext
|
|
33
|
+
default: ""
|
|
34
|
+
- type: text
|
|
35
|
+
name: mcpContext
|
|
36
|
+
default: ""
|
|
37
|
+
output:
|
|
38
|
+
- type: context
|
|
39
|
+
name: context
|
|
40
|
+
default: ""
|
|
41
|
+
required: true
|
|
42
|
+
showOnNode: true
|
|
43
|
+
---
|
|
44
|
+
Compose Context resources without putting their content or credentials into the business data flow.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Built-in node: Knowledge Context Resource
|
|
3
|
+
runtime: native
|
|
4
|
+
type: provide
|
|
5
|
+
description: Select one or more read-only knowledge sources by their authenticated Workspace catalog IDs. The runtime resolves IDs from the same catalog as GET /api/workspaces; paths and credentials are not stored in Flow DSL.
|
|
6
|
+
displayName: Knowledge Context
|
|
7
|
+
ui:
|
|
8
|
+
card:
|
|
9
|
+
template: context-resource
|
|
10
|
+
icon: menu_book
|
|
11
|
+
tone: cyan
|
|
12
|
+
sections:
|
|
13
|
+
- type: binding
|
|
14
|
+
label: Workspace IDs
|
|
15
|
+
input: workspaceIds
|
|
16
|
+
input:
|
|
17
|
+
- type: json
|
|
18
|
+
name: workspaceIds
|
|
19
|
+
default: "[]"
|
|
20
|
+
required: true
|
|
21
|
+
showOnNode: false
|
|
22
|
+
output:
|
|
23
|
+
- type: text
|
|
24
|
+
name: knowledgeContext
|
|
25
|
+
default: ""
|
|
26
|
+
required: true
|
|
27
|
+
showOnNode: true
|
|
28
|
+
---
|
|
29
|
+
Resolve authenticated Workspace catalog IDs into read-only knowledge sources for downstream Context consumers.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Built-in node: Skills Context Resource
|
|
3
|
+
runtime: native
|
|
4
|
+
type: provide
|
|
5
|
+
description: Declare versioned skills as a reusable Context resource. This is a data resource and does not participate in the prev/next control chain.
|
|
6
|
+
displayName: Skills Context
|
|
7
|
+
ui:
|
|
8
|
+
card:
|
|
9
|
+
template: context-resource
|
|
10
|
+
icon: extension
|
|
11
|
+
tone: purple
|
|
12
|
+
sections:
|
|
13
|
+
- type: binding
|
|
14
|
+
label: Skills
|
|
15
|
+
input: skills
|
|
16
|
+
input:
|
|
17
|
+
- type: json
|
|
18
|
+
name: skills
|
|
19
|
+
default: "[]"
|
|
20
|
+
required: true
|
|
21
|
+
showOnNode: false
|
|
22
|
+
output:
|
|
23
|
+
- type: text
|
|
24
|
+
name: skillsContext
|
|
25
|
+
default: ""
|
|
26
|
+
required: true
|
|
27
|
+
showOnNode: true
|
|
28
|
+
---
|
|
29
|
+
Load the declared skills for downstream Context consumers.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Built-in node: Workspace Context Resource
|
|
3
|
+
runtime: native
|
|
4
|
+
type: provide
|
|
5
|
+
description: Bind one authenticated Workspace catalog entry as execution context. The Flow stores only workspaceId; paths and credentials remain runtime-owned.
|
|
6
|
+
displayName: Workspace Context
|
|
7
|
+
ui:
|
|
8
|
+
card:
|
|
9
|
+
template: context-resource
|
|
10
|
+
icon: folder_open
|
|
11
|
+
tone: green
|
|
12
|
+
sections:
|
|
13
|
+
- type: binding
|
|
14
|
+
label: Workspace ID
|
|
15
|
+
input: workspaceId
|
|
16
|
+
- type: binding
|
|
17
|
+
label: Access
|
|
18
|
+
input: access
|
|
19
|
+
input:
|
|
20
|
+
- type: text
|
|
21
|
+
name: workspaceId
|
|
22
|
+
default: current
|
|
23
|
+
required: true
|
|
24
|
+
showOnNode: false
|
|
25
|
+
- type: text
|
|
26
|
+
name: access
|
|
27
|
+
default: read-write
|
|
28
|
+
showOnNode: false
|
|
29
|
+
output:
|
|
30
|
+
- type: text
|
|
31
|
+
name: workspaceContext
|
|
32
|
+
default: ""
|
|
33
|
+
required: true
|
|
34
|
+
showOnNode: true
|
|
35
|
+
---
|
|
36
|
+
Resolve the runtime-owned Workspace catalog entry for downstream Context consumers.
|
|
@@ -8,6 +8,9 @@ description: |
|
|
|
8
8
|
|
|
9
9
|
Preferred DSL form:
|
|
10
10
|
`control.while("Advance", { state, maxIterations, timeout }, conditionFlow, bodyFlow)`.
|
|
11
|
+
An optional typed `context` input is captured once before iteration and forwarded only to
|
|
12
|
+
Condition/Body subflows that explicitly declare `flow.input("context", "context")`. Context is
|
|
13
|
+
never copied into business state, history, or checkpoints.
|
|
11
14
|
Condition must accept `state` and `iteration`, and return `decision` plus optional `summary`.
|
|
12
15
|
Only `continue` invokes Body. Body must accept `state`, `iteration`, and `idempotencyKey`, and
|
|
13
16
|
return the next `state` plus optional `summary`. `wait`, `done`, and `fail` skip Body.
|
|
@@ -83,6 +86,10 @@ input:
|
|
|
83
86
|
- type: node
|
|
84
87
|
name: prev
|
|
85
88
|
default: ""
|
|
89
|
+
- type: context
|
|
90
|
+
name: context
|
|
91
|
+
default: ""
|
|
92
|
+
showOnNode: true
|
|
86
93
|
- type: json
|
|
87
94
|
name: state
|
|
88
95
|
default: "null"
|
|
@@ -7,9 +7,10 @@ description: |
|
|
|
7
7
|
- `repoPath` is required unless `gitContext.repoPath` is connected.
|
|
8
8
|
- `workspaceContext` is required so the node can preserve the previous execution context.
|
|
9
9
|
- `branch` is optional. When empty, AgentFlow creates a detached worktree at the current HEAD.
|
|
10
|
-
- `worktreePath` is optional. When empty, AgentFlow creates a
|
|
11
|
-
- A
|
|
12
|
-
-
|
|
10
|
+
- `worktreePath` is optional. When empty, AgentFlow creates a managed execution worktree under `.workspace/agentflow/run-workspaces/`, separate from node temp files and durable `outputs/` artifacts.
|
|
11
|
+
- A `wait` checkpoint retains the execution worktree. The next run reuses the retained output path so loop state and code changes remain available while resuming.
|
|
12
|
+
- On terminal completion or stop, AgentFlow removes clean managed worktrees. Dirty worktrees are preserved with a warning instead of being force-deleted.
|
|
13
|
+
- Existing registered worktrees under the current flow workspace are managed by the same lifecycle policy.
|
|
13
14
|
- Existing registered worktrees outside the current flow workspace are reused and not removed automatically unless this run created them.
|
|
14
15
|
- Existing worktree paths are reused only when they are registered by `git worktree list` for the given repo.
|
|
15
16
|
- `pruneMissing` defaults to true. When Git has a registered worktree whose directory is missing, AgentFlow runs `git worktree prune` before adding it again.
|
|
@@ -78,6 +78,10 @@ Commands:
|
|
|
78
78
|
node-package-publish --file <nodePackageDir>
|
|
79
79
|
node-package-install --node <id>@<version> [--workspace-root <dir>]
|
|
80
80
|
node-package-sync --flow <flowDir|workspace.flow.js> [--workspace-root <dir>]
|
|
81
|
+
marketplace-list [--kind flow|node] [--owned] [--query <text>]
|
|
82
|
+
marketplace-flow-publish --flow-id <id> [--flow-source user] [--version 1.0.0] [--visibility public|private]
|
|
83
|
+
marketplace-flow-install --flow <id>@<version> [--flow-id <targetId>]
|
|
84
|
+
marketplace-visibility --kind flow|node --resource <id>@<version> --visibility public|private
|
|
81
85
|
pull-flow --flow-id <id> [--flow-source user] [--output <flowDir>] [--workspace-root <dir>] [--replace]
|
|
82
86
|
publish-flow --flow-id <id> --file <flowDir|workspace.flow.js|flow.yaml> [--target-space personal|workspace|team] [--schedule enabled|disabled|preserve] [--with-dependencies] [--replace]
|
|
83
87
|
get-graph --flow-id <id> [--flow-source user]
|
|
@@ -371,6 +375,11 @@ function searchNodePackageCatalog(nodes, queryText, limitValue) {
|
|
|
371
375
|
inputs: node.inputs || node.input || [],
|
|
372
376
|
outputs: node.outputs || node.output || [],
|
|
373
377
|
contentSha256: node.contentSha256 || "",
|
|
378
|
+
visibility: node.visibility || "public",
|
|
379
|
+
useCount: Number(node.useCount || 0),
|
|
380
|
+
installCount: Number(node.installCount || 0),
|
|
381
|
+
uniqueUserCount: Number(node.uniqueUserCount || 0),
|
|
382
|
+
lastUsedAt: node.lastUsedAt || "",
|
|
374
383
|
installCommand: `node-package-install --node ${node.id}@${node.version}`,
|
|
375
384
|
}));
|
|
376
385
|
}
|
|
@@ -1152,6 +1161,61 @@ async function main() {
|
|
|
1152
1161
|
return;
|
|
1153
1162
|
}
|
|
1154
1163
|
|
|
1164
|
+
if (command === "marketplace-list") {
|
|
1165
|
+
const kind = String(option(args, "kind") || "flow").trim().toLowerCase();
|
|
1166
|
+
if (kind !== "flow" && kind !== "node") throw new Error("--kind must be flow or node.");
|
|
1167
|
+
const result = await httpJson(args, `/api/marketplace/resources${query({
|
|
1168
|
+
kind,
|
|
1169
|
+
scope: args.owned === true ? "owned" : "",
|
|
1170
|
+
q: option(args, "query") || option(args, "q"),
|
|
1171
|
+
sort: "useCount",
|
|
1172
|
+
order: "desc",
|
|
1173
|
+
})}`);
|
|
1174
|
+
printJson(result);
|
|
1175
|
+
return;
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
if (command === "marketplace-flow-publish") {
|
|
1179
|
+
const flowId = requireFlowId(args);
|
|
1180
|
+
const visibility = String(option(args, "visibility") || "public").trim().toLowerCase();
|
|
1181
|
+
if (visibility !== "public" && visibility !== "private") throw new Error("--visibility must be public or private.");
|
|
1182
|
+
printJson(await httpJson(args, "/api/marketplace/flows/publish", {
|
|
1183
|
+
method: "POST",
|
|
1184
|
+
body: {
|
|
1185
|
+
flowId,
|
|
1186
|
+
flowSource: option(args, "flow-source") || "user",
|
|
1187
|
+
id: option(args, "marketplace-id") || flowId,
|
|
1188
|
+
displayName: option(args, "display-name") || flowId,
|
|
1189
|
+
description: option(args, "description") || "",
|
|
1190
|
+
version: option(args, "version") || "1.0.0",
|
|
1191
|
+
visibility,
|
|
1192
|
+
},
|
|
1193
|
+
}));
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
if (command === "marketplace-flow-install") {
|
|
1198
|
+
const spec = parseNodePackageSpec(option(args, "flow"));
|
|
1199
|
+
printJson(await httpJson(args, "/api/marketplace/flows/install", {
|
|
1200
|
+
method: "POST",
|
|
1201
|
+
body: { id: spec.id, version: spec.version, flowId: option(args, "flow-id") || spec.id },
|
|
1202
|
+
}));
|
|
1203
|
+
return;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
if (command === "marketplace-visibility") {
|
|
1207
|
+
const kind = String(option(args, "kind") || "").trim().toLowerCase();
|
|
1208
|
+
if (kind !== "flow" && kind !== "node") throw new Error("--kind must be flow or node.");
|
|
1209
|
+
const spec = parseNodePackageSpec(option(args, "resource"));
|
|
1210
|
+
const visibility = String(option(args, "visibility") || "").trim().toLowerCase();
|
|
1211
|
+
if (visibility !== "public" && visibility !== "private") throw new Error("--visibility must be public or private.");
|
|
1212
|
+
printJson(await httpJson(args, "/api/marketplace/visibility", {
|
|
1213
|
+
method: "PATCH",
|
|
1214
|
+
body: { kind, id: spec.id, version: spec.version, visibility },
|
|
1215
|
+
}));
|
|
1216
|
+
return;
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1155
1219
|
if (command === "pull-flow") {
|
|
1156
1220
|
const result = await pullFlow(args);
|
|
1157
1221
|
printJson(result);
|