@fieldwangai/agentflow 0.1.106 → 0.1.107
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/agent-runners.mjs +5 -0
- package/bin/lib/composer-agent.mjs +3 -0
- package/bin/lib/prd-workflow-collaboration.mjs +69 -0
- package/bin/lib/ui-server.mjs +612 -52
- package/bin/lib/workflow-report.mjs +431 -0
- package/builtin/web-ui/dist/assets/index-BZMWrBdo.css +1 -0
- package/builtin/web-ui/dist/assets/index-Ds1YW25U.js +348 -0
- package/builtin/web-ui/dist/index.html +2 -2
- package/package.json +1 -1
- package/skills/agentflow-cli/SKILL.md +72 -1
- package/skills/agentflow-cli/agents/openai.yaml +2 -2
- package/skills/agentflow-cli/scripts/agentflow-cli.mjs +83 -0
- package/builtin/web-ui/dist/assets/index-CC1ceU6X.css +0 -1
- package/builtin/web-ui/dist/assets/index-CkfM-0Xz.js +0 -348
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0"
|
|
16
16
|
rel="stylesheet"
|
|
17
17
|
/>
|
|
18
|
-
<script type="module" crossorigin src="/assets/index-
|
|
19
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
18
|
+
<script type="module" crossorigin src="/assets/index-Ds1YW25U.js"></script>
|
|
19
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BZMWrBdo.css">
|
|
20
20
|
</head>
|
|
21
21
|
<body>
|
|
22
22
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fieldwangai/agentflow",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.107",
|
|
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",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: agentflow-cli
|
|
3
|
-
description: Direct AgentFlow platform operation through a bundled token-backed CLI, without MCP. Use when Codex needs to list AgentFlow workspaces or flows, start
|
|
3
|
+
description: Direct AgentFlow platform operation through a bundled token-backed CLI, without MCP. Use when Codex needs to list AgentFlow workspaces or flows, start or inspect runs, fetch display outputs, or read and report Workflow actions, artifacts, and global state through AgentFlow HTTP APIs using AGENTFLOW_TOKEN from env or .env. Default AgentFlow base URL is http://ai.mengma.bigo.inner/.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# AgentFlow CLI
|
|
@@ -118,16 +118,87 @@ Extract display outputs from a flow:
|
|
|
118
118
|
node skills/agentflow-cli/scripts/agentflow-cli.mjs display-outputs --flow-id TestNodes --flow-source user
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
+
Read the current materialized Workflow before making an incremental update:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
node skills/agentflow-cli/scripts/agentflow-cli.mjs workflow-get \
|
|
125
|
+
--workflow tapd:1015046 \
|
|
126
|
+
--runtime-only
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Report an action, its artifacts, and/or a global-state patch:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
node skills/agentflow-cli/scripts/agentflow-cli.mjs workflow-report \
|
|
133
|
+
--workflow tapd:1015046 \
|
|
134
|
+
--file workflow-report.json \
|
|
135
|
+
--expected-revision 'runtime:replace-with-current-revision' \
|
|
136
|
+
--idempotency-key 'implementation-finished:android:issue-2:v1'
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`workflow-report.json` uses one general model. Include at least one of `action`, `artifacts`, or `globalState`:
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"action": {
|
|
144
|
+
"key": "implementation-finished",
|
|
145
|
+
"title": "实现完成",
|
|
146
|
+
"detail": "Remote Config 拉取频控已实现",
|
|
147
|
+
"status": "done",
|
|
148
|
+
"group": "development",
|
|
149
|
+
"scope": "firebase-remote-config-fetch-control-android",
|
|
150
|
+
"platform": "android",
|
|
151
|
+
"issueKey": "issue-2",
|
|
152
|
+
"tags": ["remote-config"]
|
|
153
|
+
},
|
|
154
|
+
"artifacts": [
|
|
155
|
+
{
|
|
156
|
+
"key": "implementation-mr",
|
|
157
|
+
"type": "gitlab-mr",
|
|
158
|
+
"title": "Android 实现 MR",
|
|
159
|
+
"url": "https://git.example.test/group/project/-/merge_requests/123",
|
|
160
|
+
"scope": "action",
|
|
161
|
+
"status": "ready"
|
|
162
|
+
}
|
|
163
|
+
],
|
|
164
|
+
"globalState": {
|
|
165
|
+
"mode": "merge",
|
|
166
|
+
"patch": {
|
|
167
|
+
"status": { "label": "开发中" },
|
|
168
|
+
"sections": {
|
|
169
|
+
"android": {
|
|
170
|
+
"title": "Android",
|
|
171
|
+
"fields": {
|
|
172
|
+
"owner": { "label": "负责人", "type": "user", "value": "alice" },
|
|
173
|
+
"tags": { "label": "Tag", "type": "chips", "value": ["remote-config"] },
|
|
174
|
+
"rules": { "label": "实现规则", "type": "list", "value": ["仅允许国家注册 listener"] }
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
"remove": []
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Artifact `scope` is `action` or `global`. Action-scoped artifacts appear with the timeline action; global artifacts appear in the related-artifacts area. Use stable `key` values so later reports update an existing item instead of duplicating it.
|
|
185
|
+
|
|
186
|
+
Supported global-state field types are `text`, `user`, `chips`, `list`, and `link`. The model does not require Android/iOS sections; section and field keys are application-defined.
|
|
187
|
+
|
|
121
188
|
## Workflow
|
|
122
189
|
|
|
123
190
|
1. Check token availability with `config`.
|
|
124
191
|
2. Use `list-workspace` or `list-flows` to discover targets.
|
|
125
192
|
3. Use `run` to start the flow. If the task needs the generated page/text, inspect returned `displayOutputs` or call `display-outputs`.
|
|
126
193
|
4. Use `status`, `list-run-by-workspace`, and `logs` when a run is active, failed, or needs debugging.
|
|
194
|
+
5. Before changing Workflow global state, call `workflow-get` and retain `snapshot.runtimeRevision`.
|
|
195
|
+
6. Merge the intended semantic change into the current state; do not replace unrelated fields.
|
|
196
|
+
7. Call `workflow-report` with `--expected-revision` and a stable `--idempotency-key`. If the API returns a revision conflict, fetch again, re-apply the intended patch, and retry once with a new revision.
|
|
127
197
|
|
|
128
198
|
## Failure Handling
|
|
129
199
|
|
|
130
200
|
- If the CLI says the token is missing, ask the user to set `AGENTFLOW_TOKEN` in env or `.env`.
|
|
131
201
|
- If the API returns 401/403, do not retry with a printed token. Ask the user to refresh the token.
|
|
132
202
|
- If `run` fails because a flow is already running, call `status` and `list-run-by-workspace` before retrying.
|
|
203
|
+
- If `workflow-report` returns a revision conflict, do not blindly overwrite remote state. Read the returned snapshot or call `workflow-get`, merge the intended fields, and retry with its revision.
|
|
133
204
|
- If local debugging is needed, override `AGENTFLOW_BASE_URL`; otherwise keep the default internal URL.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "AgentFlow CLI"
|
|
3
|
-
short_description: "
|
|
4
|
-
default_prompt: "Use
|
|
3
|
+
short_description: "Run flows and report Workflow state through AgentFlow APIs"
|
|
4
|
+
default_prompt: "Use $agentflow-cli to operate AgentFlow and report Workflow actions, artifacts, or global state with the bundled token-backed CLI."
|
|
@@ -40,6 +40,8 @@ Commands:
|
|
|
40
40
|
logs --run-id <id>
|
|
41
41
|
display-outputs --flow-id <id> [--flow-source user]
|
|
42
42
|
sync-workspace --workspace <id>
|
|
43
|
+
workflow-get --workflow tapd:<id> [--flow-id <id>] [--runtime-only]
|
|
44
|
+
workflow-report --workflow tapd:<id> --file <report.json> [--expected-revision <revision>]
|
|
43
45
|
`;
|
|
44
46
|
}
|
|
45
47
|
|
|
@@ -227,6 +229,51 @@ function requireFlowId(args) {
|
|
|
227
229
|
return flowId;
|
|
228
230
|
}
|
|
229
231
|
|
|
232
|
+
function parseWorkflowReference(value) {
|
|
233
|
+
const text = String(value || "").trim();
|
|
234
|
+
if (!text) return null;
|
|
235
|
+
const separator = text.indexOf(":");
|
|
236
|
+
if (separator <= 0 || separator === text.length - 1) {
|
|
237
|
+
throw new Error(`Invalid workflow reference "${text}". Expected namespace:id, for example tapd:1015046.`);
|
|
238
|
+
}
|
|
239
|
+
const namespace = text.slice(0, separator).trim().toLowerCase();
|
|
240
|
+
const id = text.slice(separator + 1).trim();
|
|
241
|
+
if (!namespace || !id) {
|
|
242
|
+
throw new Error(`Invalid workflow reference "${text}". Expected namespace:id.`);
|
|
243
|
+
}
|
|
244
|
+
return { namespace, id, key: `${namespace}:${id}` };
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function workflowReferenceFromArgs(args, required = true) {
|
|
248
|
+
const explicit = option(args, "workflow");
|
|
249
|
+
if (explicit) return parseWorkflowReference(explicit);
|
|
250
|
+
const tapdId = option(args, "tapd-id") || option(args, "tapd");
|
|
251
|
+
if (tapdId) return { namespace: "tapd", id: tapdId, key: `tapd:${tapdId}` };
|
|
252
|
+
if (required) throw new Error("Missing --workflow namespace:id.");
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function readJsonFile(filePath) {
|
|
257
|
+
const requested = String(filePath || "").trim();
|
|
258
|
+
if (!requested) throw new Error("Missing --file <report.json>.");
|
|
259
|
+
const resolved = path.resolve(requested);
|
|
260
|
+
let source;
|
|
261
|
+
try {
|
|
262
|
+
source = fs.readFileSync(resolved, "utf8");
|
|
263
|
+
} catch (error) {
|
|
264
|
+
throw new Error(`Cannot read JSON file ${resolved}: ${error?.message || String(error)}`);
|
|
265
|
+
}
|
|
266
|
+
try {
|
|
267
|
+
const value = JSON.parse(source);
|
|
268
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
269
|
+
throw new Error("top-level value must be an object");
|
|
270
|
+
}
|
|
271
|
+
return value;
|
|
272
|
+
} catch (error) {
|
|
273
|
+
throw new Error(`Invalid JSON file ${resolved}: ${error?.message || String(error)}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
230
277
|
async function main() {
|
|
231
278
|
loadEnvFiles();
|
|
232
279
|
const args = parseArgv(process.argv.slice(2));
|
|
@@ -332,6 +379,42 @@ async function main() {
|
|
|
332
379
|
return;
|
|
333
380
|
}
|
|
334
381
|
|
|
382
|
+
if (command === "workflow-get") {
|
|
383
|
+
const workflow = workflowReferenceFromArgs(args);
|
|
384
|
+
if (workflow.namespace !== "tapd") {
|
|
385
|
+
throw new Error(`Unsupported workflow namespace: ${workflow.namespace}`);
|
|
386
|
+
}
|
|
387
|
+
const flowId = option(args, "flow-id") || option(args, "flow");
|
|
388
|
+
const flowSource = option(args, "flow-source") || "user";
|
|
389
|
+
const runtimeOnly = args["runtime-only"] === true || args.cached === true ? "1" : "";
|
|
390
|
+
printJson(await httpJson(args, `/api/workflows/state${query({
|
|
391
|
+
workflow: workflow.key,
|
|
392
|
+
flowId,
|
|
393
|
+
flowSource,
|
|
394
|
+
runtimeOnly,
|
|
395
|
+
})}`));
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (command === "workflow-report") {
|
|
400
|
+
const body = readJsonFile(option(args, "file"));
|
|
401
|
+
const workflow = workflowReferenceFromArgs(args, false) || parseWorkflowReference(body?.workflow?.key || "");
|
|
402
|
+
if (!workflow && !(body?.workflow?.namespace && body?.workflow?.id)) {
|
|
403
|
+
throw new Error("Missing workflow reference. Pass --workflow namespace:id or include workflow.namespace and workflow.id in the JSON file.");
|
|
404
|
+
}
|
|
405
|
+
if (workflow) body.workflow = workflow;
|
|
406
|
+
const expectedRevision = option(args, "expected-revision");
|
|
407
|
+
const idempotencyKey = option(args, "idempotency-key");
|
|
408
|
+
const flowId = option(args, "flow-id") || option(args, "flow");
|
|
409
|
+
const flowSource = option(args, "flow-source");
|
|
410
|
+
if (expectedRevision) body.expectedRevision = expectedRevision;
|
|
411
|
+
if (idempotencyKey) body.idempotencyKey = idempotencyKey;
|
|
412
|
+
if (flowId) body.flowId = flowId;
|
|
413
|
+
if (flowSource) body.flowSource = flowSource;
|
|
414
|
+
printJson(await httpJson(args, "/api/workflows/report", { method: "POST", body }));
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
|
|
335
418
|
throw new Error(`Unknown command: ${command}\n\n${usage()}`);
|
|
336
419
|
}
|
|
337
420
|
|