@fieldwangai/agentflow 0.1.156 → 0.1.157

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.
@@ -36,7 +36,7 @@ import { WorkspaceFlowParseError } from "./workspace-flow-store.mjs";
36
36
  import { mergeWorkspaceGraphs, workspaceDesignRevision, workspaceRuntimeRevision } from "./workspace-graph-merge.mjs";
37
37
  import { DEFAULT_WORKSPACE_PREVIEW_TTL_MS, createWorkspacePreviewId, normalizeWorkspacePreviewTtlMs, readWorkspacePreviewMetadata, workspaceSharedPreviewFlowDir, writeWorkspacePreviewMetadata } from "./workspace-preview.mjs";
38
38
  import { appendWorkspaceRunLogEvent, createWorkspaceRunLogSession, finishWorkspaceRunLogSession, listWorkspaceRunLogs, readWorkspaceRunLogEvents } from "./workspace-run-logs.mjs";
39
- import { activeWorkspaceRuns, appendWorkspaceRunFinished, appendWorkspaceRunStarted, hydrateWorkspaceGraphForRuntime, isReadonlyBuiltinFlowSource, isTransientAgentNetworkError, isValidFlowSourceRead, isWorkspaceRunAbortError, listWorkspaceScheduleStatusesForFlow, mergeWorkspacePersistentNodeRefs, mergeWorkspaceRunGraph, normalizeWorkspaceEntry, readWorkspaceConversations, readWorkspaceFiles, readWorkspaceGraph, resolveWorkspaceFilePath, resolveWorkspaceScopeRoot, runWorkspaceGraph, sleepMs, syncWorkspaceSchedulesForGraph, workspaceActiveRunsForScope, workspaceCollaborationEventKey, workspaceCollaborationSequences, workspaceCollaborationSubscribers, workspaceCollaborationSummaryWithUsers, workspaceDesignPath, workspaceDownloadContentDisposition, workspaceFindActiveRunConflict, workspaceGraphAsSource, workspaceOptimizeRunImplementations, workspaceRepoUrlWithCredential, workspaceRunControl, workspaceRunEntryKey, workspaceRunKey, workspaceRunPlan, workspaceRunPlanNodeIds, workspaceRunTouchedNodeIds, workspaceRuntimeNodeLabel, workspaceScopedUserContext, workspaceSearchGuardrailsBlock, workspaceUnwrapOutputEnvelopeForDisplay, workspacesPath, writeWorkspaceConversations, writeWorkspaceGraph } from "./workspace-server.mjs";
39
+ import { activeWorkspaceRuns, appendWorkspaceRunFinished, appendWorkspaceRunStarted, hydrateWorkspaceGraphForRuntime, isReadonlyBuiltinFlowSource, isTransientAgentNetworkError, isValidFlowSourceRead, isWorkspaceRunAbortError, listWorkspaceScheduleStatusesForFlow, mergeWorkspacePersistentNodeRefs, mergeWorkspaceRunGraph, normalizeWorkspaceEntry, readWorkspaceConversations, readWorkspaceFiles, readWorkspaceGraph, removeWorkspaceDeferredRun, resolveWorkspaceFilePath, resolveWorkspaceScopeRoot, runWorkspaceGraph, sleepMs, syncWorkspaceSchedulesForGraph, upsertWorkspaceDeferredRun, workspaceActiveRunsForScope, workspaceCollaborationEventKey, workspaceCollaborationSequences, workspaceCollaborationSubscribers, workspaceCollaborationSummaryWithUsers, workspaceDeferredRunsForScope, workspaceDesignPath, workspaceDownloadContentDisposition, workspaceFindActiveRunConflict, workspaceGraphAsSource, workspaceOptimizeRunImplementations, workspaceRepoUrlWithCredential, workspaceRunControl, workspaceRunEntryKey, workspaceRunKey, workspaceRunPlan, workspaceRunPlanNodeIds, workspaceRunTouchedNodeIds, workspaceRuntimeNodeLabel, workspaceScopedUserContext, workspaceSearchGuardrailsBlock, workspaceUnwrapOutputEnvelopeForDisplay, workspacesPath, writeWorkspaceConversations, writeWorkspaceGraph } from "./workspace-server.mjs";
40
40
  import { getWorkspaceTree } from "./workspace-tree.mjs";
41
41
  import busboy from "busboy";
42
42
  import crypto from "crypto";
@@ -1885,11 +1885,12 @@ async function workspaceRoutes(req, res, ctx) {
1885
1885
  const setActiveChild = (child, childOptions = {}) => {
1886
1886
  runControl.setChild(child, childOptions);
1887
1887
  };
1888
+ let runDeferred = false;
1888
1889
  const clearActiveRun = (status = "finished") => {
1889
1890
  runControl.finish(status);
1890
1891
  if (activeWorkspaceRuns.get(runKey) === runEntry) activeWorkspaceRuns.delete(runKey);
1891
1892
  broadcastWorkspaceCollaborationEvent(userCtx, scoped.flowSource, scoped.flowId, scoped.archived, {
1892
- type: "run.finished",
1893
+ type: status === "waiting" ? "run.waiting" : "run.finished",
1893
1894
  status,
1894
1895
  runId,
1895
1896
  runNodeId,
@@ -1912,6 +1913,7 @@ async function workspaceRoutes(req, res, ctx) {
1912
1913
  onEvent: writeEvent,
1913
1914
  signal: controller.signal,
1914
1915
  onActiveChild: setActiveChild,
1916
+ runId,
1915
1917
  });
1916
1918
  const currentGraph = readWorkspaceGraph(scoped.root, root).graph;
1917
1919
  const touchedIds = workspaceRunTouchedNodeIds(result);
@@ -1921,6 +1923,33 @@ async function workspaceRoutes(req, res, ctx) {
1921
1923
  const collaborationEventType = revision === workspaceDesignRevision(currentGraph)
1922
1924
  ? "runtime.committed"
1923
1925
  : "graph.committed";
1926
+ if (result.deferred) {
1927
+ runDeferred = true;
1928
+ const waiting = upsertWorkspaceDeferredRun(runEntry, result.deferred);
1929
+ broadcastWorkspaceCollaborationEvent(userCtx, scoped.flowSource, scoped.flowId, scoped.archived, {
1930
+ type: collaborationEventType,
1931
+ revision,
1932
+ runtimeRevision,
1933
+ actorId: userCtx.userId || "",
1934
+ source: "run",
1935
+ });
1936
+ writeEvent({
1937
+ type: "waiting",
1938
+ ok: true,
1939
+ deferred: true,
1940
+ path: graphPath,
1941
+ graph: committed.graph,
1942
+ revision,
1943
+ runtimeRevision,
1944
+ runId,
1945
+ runNodeId,
1946
+ plannedNodeIds,
1947
+ touchedNodeIds: Array.from(touchedIds),
1948
+ ...waiting,
1949
+ });
1950
+ res.end();
1951
+ return;
1952
+ }
1924
1953
  const endedAt = Date.now();
1925
1954
  appendWorkspaceRunFinished({
1926
1955
  ...runEntry,
@@ -1972,7 +2001,7 @@ async function workspaceRoutes(req, res, ctx) {
1972
2001
  }
1973
2002
  res.end();
1974
2003
  } finally {
1975
- clearActiveRun(controller.signal.aborted ? "stopped" : "finished");
2004
+ clearActiveRun(controller.signal.aborted ? "stopped" : runDeferred ? "waiting" : "finished");
1976
2005
  }
1977
2006
  return;
1978
2007
  }
@@ -1981,6 +2010,7 @@ async function workspaceRoutes(req, res, ctx) {
1981
2010
  signal: controller.signal,
1982
2011
  onActiveChild: setActiveChild,
1983
2012
  onEvent: (event) => appendWorkspaceRunLogEvent(runLog.runId, event),
2013
+ runId,
1984
2014
  });
1985
2015
  const currentGraph = readWorkspaceGraph(scoped.root, root).graph;
1986
2016
  const touchedIds = workspaceRunTouchedNodeIds(result);
@@ -1990,6 +2020,31 @@ async function workspaceRoutes(req, res, ctx) {
1990
2020
  const collaborationEventType = revision === workspaceDesignRevision(currentGraph)
1991
2021
  ? "runtime.committed"
1992
2022
  : "graph.committed";
2023
+ if (result.deferred) {
2024
+ runDeferred = true;
2025
+ const waiting = upsertWorkspaceDeferredRun(runEntry, result.deferred);
2026
+ broadcastWorkspaceCollaborationEvent(userCtx, scoped.flowSource, scoped.flowId, scoped.archived, {
2027
+ type: collaborationEventType,
2028
+ revision,
2029
+ runtimeRevision,
2030
+ actorId: userCtx.userId || "",
2031
+ source: "run",
2032
+ });
2033
+ json(res, 200, {
2034
+ ok: true,
2035
+ path: graphPath,
2036
+ ...result,
2037
+ deferred: true,
2038
+ graph: committed.graph,
2039
+ revision,
2040
+ runtimeRevision,
2041
+ runId,
2042
+ plannedNodeIds,
2043
+ touchedNodeIds: Array.from(touchedIds),
2044
+ waiting,
2045
+ });
2046
+ return;
2047
+ }
1993
2048
  const endedAt = Date.now();
1994
2049
  appendWorkspaceRunFinished({
1995
2050
  ...runEntry,
@@ -2040,7 +2095,7 @@ async function workspaceRoutes(req, res, ctx) {
2040
2095
  throw e;
2041
2096
  }
2042
2097
  } finally {
2043
- clearActiveRun(controller.signal.aborted ? "stopped" : "finished");
2098
+ clearActiveRun(controller.signal.aborted ? "stopped" : runDeferred ? "waiting" : "finished");
2044
2099
  }
2045
2100
  } catch (e) {
2046
2101
  json(res, 500, { error: (e && e.message) || String(e) });
@@ -2138,11 +2193,15 @@ async function workspaceRoutes(req, res, ctx) {
2138
2193
  return;
2139
2194
  }
2140
2195
  const scopeKey = workspaceRunKey(workspaceScopedUserContext(scoped, userCtx), flowSource, flowId);
2141
- const entries = workspaceActiveRunsForScope(scopeKey).map(([, entry]) => entry);
2196
+ const activeEntries = workspaceActiveRunsForScope(scopeKey).map(([, entry]) => entry);
2197
+ const activeRunIds = new Set(activeEntries.map((entry) => String(entry?.runId || "")));
2198
+ const deferredEntries = workspaceDeferredRunsForScope(scopeKey)
2199
+ .filter((entry) => !activeRunIds.has(String(entry?.runId || "")));
2200
+ const entries = [...activeEntries, ...deferredEntries];
2142
2201
  const entry = entries[0] || null;
2143
2202
  json(res, 200, {
2144
2203
  running: entries.length > 0,
2145
- state: entry?.runControl?.state || (entries.length > 0 ? "running" : "idle"),
2204
+ state: entry?.runControl?.state || entry?.status || (entries.length > 0 ? "running" : "idle"),
2146
2205
  flowId,
2147
2206
  flowSource,
2148
2207
  runNodeId: entry?.runNodeId || "",
@@ -2155,7 +2214,15 @@ async function workspaceRoutes(req, res, ctx) {
2155
2214
  startedAt: item?.startedAt || null,
2156
2215
  plannedNodeIds: Array.isArray(item?.plannedNodeIds) ? item.plannedNodeIds : [],
2157
2216
  scheduled: item?.scheduled === true,
2158
- state: item?.runControl?.state || "running",
2217
+ state: item?.runControl?.state || item?.status || "running",
2218
+ waitingNodeId: item?.nodeId || "",
2219
+ phase: item?.phase || "",
2220
+ jenkinsStatus: item?.jenkinsStatus || "",
2221
+ message: item?.message || "",
2222
+ buildNumber: item?.buildNumber || "",
2223
+ url: item?.url || "",
2224
+ qrUrl: item?.qrUrl || "",
2225
+ wakeAt: item?.wakeAt || "",
2159
2226
  })),
2160
2227
  });
2161
2228
  return;
@@ -2189,7 +2256,7 @@ async function workspaceRoutes(req, res, ctx) {
2189
2256
  json(res, 403, { error: "Workspace collaboration run permission denied" });
2190
2257
  return;
2191
2258
  }
2192
- const scopeKey = workspaceRunKey(userCtx, flowSource, flowId);
2259
+ const scopeKey = workspaceRunKey(workspaceScopedUserContext(scoped, userCtx), flowSource, flowId);
2193
2260
  const runId = String(payload.runId || payload.runSessionId || "").trim();
2194
2261
  const runNodeId = String(payload.runNodeId || "").trim();
2195
2262
  const entries = workspaceActiveRunsForScope(scopeKey);
@@ -2198,7 +2265,44 @@ async function workspaceRoutes(req, res, ctx) {
2198
2265
  || (!runId && !runNodeId && entries.length === 1 ? entries[0] : null);
2199
2266
  const entry = match?.[1] || null;
2200
2267
  if (!entry) {
2201
- json(res, 404, { error: "该 Workspace 未在运行" });
2268
+ const deferredEntries = workspaceDeferredRunsForScope(scopeKey);
2269
+ const deferred = deferredEntries.find((item) => runId && String(item?.runId || "") === runId)
2270
+ || deferredEntries.find((item) => runNodeId && String(item?.runNodeId || "") === runNodeId)
2271
+ || (!runId && !runNodeId && deferredEntries.length === 1 ? deferredEntries[0] : null);
2272
+ if (!deferred) {
2273
+ json(res, 404, { error: "该 Workspace 未在运行" });
2274
+ return;
2275
+ }
2276
+ removeWorkspaceDeferredRun(deferred.key);
2277
+ const endedAt = Date.now();
2278
+ appendWorkspaceRunLogEvent(deferred.runId, {
2279
+ type: "stop-completed",
2280
+ runNodeId: deferred.runNodeId || "",
2281
+ monitoringOnly: true,
2282
+ ts: endedAt,
2283
+ });
2284
+ appendWorkspaceRunFinished({
2285
+ ...deferred,
2286
+ endedAt,
2287
+ durationMs: Math.max(0, endedAt - Number(deferred.startedAt || endedAt)),
2288
+ }, "stopped");
2289
+ finishWorkspaceRunLogSession(deferred.runId, "stopped", {
2290
+ endedAt,
2291
+ durationMs: Math.max(0, endedAt - Number(deferred.startedAt || endedAt)),
2292
+ runNodeId: deferred.runNodeId || "",
2293
+ });
2294
+ broadcastWorkspaceCollaborationEvent(userCtx, scoped.flowSource, scoped.flowId, scoped.archived, {
2295
+ type: "run.finished",
2296
+ status: "stopped",
2297
+ runId: deferred.runId,
2298
+ runNodeId: deferred.runNodeId || "",
2299
+ actorId: userCtx.userId || "",
2300
+ });
2301
+ json(res, 200, {
2302
+ ok: true,
2303
+ stopped: true,
2304
+ monitoringOnly: true,
2305
+ });
2202
2306
  return;
2203
2307
  }
2204
2308
  appendWorkspaceRunLogEvent(entry.runId, {