@fieldwangai/agentflow 0.1.95 → 0.1.97
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 +61 -9
- package/builtin/web-ui/dist/assets/index-BPagP6GD.js +346 -0
- package/builtin/web-ui/dist/assets/index-DKaacU6h.css +1 -0
- package/builtin/web-ui/dist/index.html +2 -2
- package/package.json +1 -1
- package/builtin/web-ui/dist/assets/index-DV-QkHHi.css +0 -1
- package/builtin/web-ui/dist/assets/index-b0Rwi6Tw.js +0 -346
package/bin/lib/ui-server.mjs
CHANGED
|
@@ -3923,6 +3923,31 @@ function workspaceSafeNodeOutputRelPath(value) {
|
|
|
3923
3923
|
return clean;
|
|
3924
3924
|
}
|
|
3925
3925
|
|
|
3926
|
+
function workspaceDescribeNodeOutputsDir(nodeRunDir, maxEntries = 30) {
|
|
3927
|
+
const outputsDir = path.resolve(nodeRunDir || "", "outputs");
|
|
3928
|
+
if (!nodeRunDir || !fs.existsSync(outputsDir)) return "Current node outputs directory is missing.";
|
|
3929
|
+
const entries = [];
|
|
3930
|
+
const walk = (dir, rel = "") => {
|
|
3931
|
+
if (entries.length >= maxEntries) return;
|
|
3932
|
+
let children = [];
|
|
3933
|
+
try {
|
|
3934
|
+
children = fs.readdirSync(dir, { withFileTypes: true });
|
|
3935
|
+
} catch {
|
|
3936
|
+
return;
|
|
3937
|
+
}
|
|
3938
|
+
for (const child of children) {
|
|
3939
|
+
if (entries.length >= maxEntries) break;
|
|
3940
|
+
const childRel = rel ? path.posix.join(rel, child.name) : child.name;
|
|
3941
|
+
entries.push(child.isDirectory() ? `${childRel}/` : childRel);
|
|
3942
|
+
if (child.isDirectory()) walk(path.join(dir, child.name), childRel);
|
|
3943
|
+
}
|
|
3944
|
+
};
|
|
3945
|
+
walk(outputsDir);
|
|
3946
|
+
if (!entries.length) return "Current node outputs directory is empty.";
|
|
3947
|
+
const suffix = entries.length >= maxEntries ? `\n...showing first ${maxEntries} entries` : "";
|
|
3948
|
+
return `Current node outputs entries:\n${entries.map((entry) => `- outputs/${entry}`).join("\n")}${suffix}`;
|
|
3949
|
+
}
|
|
3950
|
+
|
|
3926
3951
|
function workspacePublishNodeOutputFile(runPackage, relPath) {
|
|
3927
3952
|
if (!String(relPath || "").trim()) return "";
|
|
3928
3953
|
const clean = workspaceSafeNodeOutputRelPath(relPath);
|
|
@@ -3939,6 +3964,7 @@ function workspacePublishNodeOutputFile(runPackage, relPath) {
|
|
|
3939
3964
|
throw new Error(
|
|
3940
3965
|
`Agent returned resultFile but did not create it under this node's outputs: ${clean}\n` +
|
|
3941
3966
|
`Expected file: ${src}\n` +
|
|
3967
|
+
`${workspaceDescribeNodeOutputsDir(nodeRunDir)}\n` +
|
|
3942
3968
|
`Write outputs using a relative path from the node cwd, or use AGENTFLOW_OUTPUTS_DIR.`
|
|
3943
3969
|
);
|
|
3944
3970
|
}
|
|
@@ -4160,6 +4186,8 @@ function workspaceOutputProtocolRequirements(graph, nodeId) {
|
|
|
4160
4186
|
"",
|
|
4161
4187
|
`请把${resultKindText}结果写入 \`${resultFile}\`。${resultGuidance}`,
|
|
4162
4188
|
`必须先在当前执行目录下创建 \`${resultFile}\`,不要写到绝对路径或其它 run 目录;然后再返回下面的 agentflow envelope。`,
|
|
4189
|
+
`只在最终回复里写 \`resultFile: ${resultFile}\` 不会创建文件;必须通过工具或脚本实际写入该文件。`,
|
|
4190
|
+
`返回前请确认 \`${resultFile}\` 已存在且非空(例如执行 \`test -s ${resultFile}\` 或等价检查);如果无法创建文件,不要返回成功 envelope。`,
|
|
4163
4191
|
downstreamInputRequirements ? `\n${downstreamInputRequirements}` : "",
|
|
4164
4192
|
...(slots.length ? [`额外输出:${slots.map((name) => `\`${name}\``).join("、")}。短值可写在 \`outParams\`,文件值写成 \`outParams.<name>File\`。`] : []),
|
|
4165
4193
|
"最终只输出下面的 agentflow envelope,不要输出解释、进度或其它文字:",
|
|
@@ -4347,13 +4375,17 @@ function workspaceCachedOutputValueExists(value, scopedRoot = "") {
|
|
|
4347
4375
|
}
|
|
4348
4376
|
|
|
4349
4377
|
function workspaceUpstreamText(graph, nodeId, outputs, scopedRoot = "") {
|
|
4378
|
+
const contentEdge = workspaceContentInputEdge(graph, nodeId);
|
|
4379
|
+
if (!contentEdge) return "";
|
|
4380
|
+
return workspaceOutputSlotValueForEdge(graph, outputs, contentEdge, scopedRoot);
|
|
4381
|
+
}
|
|
4382
|
+
|
|
4383
|
+
function workspaceContentInputEdge(graph, nodeId) {
|
|
4350
4384
|
const edges = Array.isArray(graph?.edges) ? graph.edges : [];
|
|
4351
4385
|
const incoming = edges
|
|
4352
4386
|
.filter((edge) => String(edge?.target || "") === String(nodeId))
|
|
4353
4387
|
.filter((edge) => !isWorkspaceSemanticInputSlot(workspaceTargetSlotForEdge(graph, edge)));
|
|
4354
|
-
|
|
4355
|
-
if (!contentEdge) return "";
|
|
4356
|
-
return workspaceOutputSlotValueForEdge(graph, outputs, contentEdge, scopedRoot);
|
|
4388
|
+
return incoming.find((edge) => String(edge?.targetHandle || "") === "input-1") || incoming[0] || null;
|
|
4357
4389
|
}
|
|
4358
4390
|
|
|
4359
4391
|
function workspaceHandleIndex(handle, prefix) {
|
|
@@ -6089,6 +6121,11 @@ async function runWorkspaceGraph(root, scopedRoot, payload, userCtx = {}, opts =
|
|
|
6089
6121
|
}
|
|
6090
6122
|
|
|
6091
6123
|
if (workspaceDisplayKind(defId)) {
|
|
6124
|
+
if (!workspaceContentInputEdge(graph, nodeId)) {
|
|
6125
|
+
emit({ type: "status", nodeId, line: "Display unchanged: no content input edge" });
|
|
6126
|
+
emit({ type: "node-done", nodeId, definitionId: defId, unchanged: true });
|
|
6127
|
+
continue;
|
|
6128
|
+
}
|
|
6092
6129
|
const content = workspaceUpstreamText(graph, nodeId, outputs, scopedRoot);
|
|
6093
6130
|
graph.instances[nodeId] = workspaceWriteDisplayContent(instance, content);
|
|
6094
6131
|
const updatedDisplays = publishNodeOutput(nodeId, content);
|
|
@@ -7048,6 +7085,24 @@ function prdWorkflowSafeStateId(value) {
|
|
|
7048
7085
|
.slice(0, 128) || "unknown";
|
|
7049
7086
|
}
|
|
7050
7087
|
|
|
7088
|
+
function prdWorkflowReviewIdFromRequest(tapdId, payload = {}, durability = "temporary") {
|
|
7089
|
+
if (durability === "temporary") return `r-${crypto.randomBytes(5).toString("hex")}`;
|
|
7090
|
+
const requested = String(payload.reviewId || payload.review_id || "").trim();
|
|
7091
|
+
if (!requested) return `review_${Date.now().toString(36)}_${crypto.randomBytes(4).toString("hex")}`;
|
|
7092
|
+
const safeRequested = prdWorkflowSafeStateId(requested);
|
|
7093
|
+
if (safeRequested.length <= 48) return safeRequested;
|
|
7094
|
+
const stage = String(payload.stage || payload.stageKey || payload.stage_key || "review").trim();
|
|
7095
|
+
const action = String(payload.action || payload.actionId || payload.action_id || "").trim();
|
|
7096
|
+
const issueKey = String(payload.issueKey || payload.issue_key || payload.issue || "").trim();
|
|
7097
|
+
const stageHead = prdWorkflowSafeStateId(stage.split(":")[0] || stage || "review").slice(0, 20);
|
|
7098
|
+
const digest = crypto
|
|
7099
|
+
.createHash("sha256")
|
|
7100
|
+
.update(JSON.stringify({ tapdId: String(tapdId || ""), requested, stage, action, issueKey }))
|
|
7101
|
+
.digest("hex")
|
|
7102
|
+
.slice(0, 10);
|
|
7103
|
+
return prdWorkflowSafeStateId(["review", tapdId, stageHead, digest].filter(Boolean).join("-")).slice(0, 64);
|
|
7104
|
+
}
|
|
7105
|
+
|
|
7051
7106
|
function prdWorkflowStatePath(scopedRoot, tapdId) {
|
|
7052
7107
|
const rootDir = scopedRoot || process.cwd();
|
|
7053
7108
|
return path.join(rootDir, ".workspace", "prd-flow", "workflow-state", `${prdWorkflowSafeStateId(tapdId)}.json`);
|
|
@@ -7436,13 +7491,10 @@ function prdWorkflowReviewHtml(title, markdown, meta = {}) {
|
|
|
7436
7491
|
function prdWorkflowCreateReview(scopedRoot, tapdId, payload = {}, urlBase = "") {
|
|
7437
7492
|
const content = String(payload.markdown || payload.content || payload.rawOutput || "").slice(0, 500000);
|
|
7438
7493
|
if (!content.trim()) throw new Error("Missing review markdown");
|
|
7439
|
-
const requestedReviewId = String(payload.reviewId || payload.review_id || "").trim();
|
|
7440
|
-
const reviewId = requestedReviewId
|
|
7441
|
-
? prdWorkflowSafeStateId(requestedReviewId)
|
|
7442
|
-
: `review_${Date.now().toString(36)}_${crypto.randomBytes(4).toString("hex")}`;
|
|
7443
|
-
const paths = prdWorkflowReviewPaths(scopedRoot, tapdId, reviewId);
|
|
7444
7494
|
const title = String(payload.title || payload.label || "PRD Workflow Review").trim().slice(0, 160) || "PRD Workflow Review";
|
|
7445
7495
|
const durability = String(payload.durability || (payload.durable === true || payload.permanent === true ? "durable" : "temporary")).trim().toLowerCase() || "temporary";
|
|
7496
|
+
const reviewId = prdWorkflowReviewIdFromRequest(tapdId, payload, durability);
|
|
7497
|
+
const paths = prdWorkflowReviewPaths(scopedRoot, tapdId, reviewId);
|
|
7446
7498
|
const ttlDaysRaw = Number(payload.ttlDays || payload.ttl_days || (durability === "temporary" ? 7 : 0));
|
|
7447
7499
|
const ttlDays = Number.isFinite(ttlDaysRaw) && ttlDaysRaw > 0 ? ttlDaysRaw : 0;
|
|
7448
7500
|
const createdAt = new Date();
|
|
@@ -10342,7 +10394,7 @@ export function startUiServer({
|
|
|
10342
10394
|
const review = prdWorkflowCreateReview(scopedRoot, tapdId, payload, serverPublicBaseUrl(req, host, uiPort, payload));
|
|
10343
10395
|
const query = new URLSearchParams();
|
|
10344
10396
|
if (flowId) query.set("flowId", flowId);
|
|
10345
|
-
if (flowSource) query.set("flowSource", flowSource);
|
|
10397
|
+
if (flowId && flowSource && flowSource !== "user") query.set("flowSource", flowSource);
|
|
10346
10398
|
if (archived) query.set("archived", "1");
|
|
10347
10399
|
const reviewUrl = query.toString() ? `${review.url}?${query.toString()}` : review.url;
|
|
10348
10400
|
const durability = review.durability || "temporary";
|