@fieldwangai/agentflow 0.1.153 → 0.1.154

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.
Files changed (192) hide show
  1. package/README.md +16 -34
  2. package/README.zh-CN.md +14 -34
  3. package/agents/agentflow-node-executor-code.md +13 -3
  4. package/agents/agentflow-node-executor-planning.md +13 -3
  5. package/agents/agentflow-node-executor-requirement.md +13 -3
  6. package/agents/agentflow-node-executor-test.md +13 -3
  7. package/agents/agentflow-node-executor-ui.md +13 -3
  8. package/agents/agentflow-node-executor.md +13 -3
  9. package/agents/en/agentflow-node-executor.md +13 -3
  10. package/agents/zh/agentflow-node-executor.md +13 -3
  11. package/bin/agentflow.mjs +3 -3
  12. package/bin/lib/admin-builtin-pipelines.mjs +3 -2
  13. package/bin/lib/agent-runners.mjs +0 -929
  14. package/bin/lib/auth.mjs +2 -1
  15. package/bin/lib/catalog-agents.mjs +2 -1
  16. package/bin/lib/catalog-flows.mjs +165 -90
  17. package/bin/lib/composer-agent.mjs +3 -793
  18. package/bin/lib/composer-skill-router.mjs +3 -323
  19. package/bin/lib/exec-buffered.mjs +32 -0
  20. package/bin/lib/flow-dsl/cli.mjs +276 -0
  21. package/bin/lib/flow-dsl/codegen.mjs +358 -0
  22. package/bin/lib/flow-dsl/defs.mjs +103 -0
  23. package/bin/lib/flow-dsl/index.mjs +77 -0
  24. package/bin/lib/flow-dsl/ir.mjs +305 -0
  25. package/bin/lib/flow-dsl/layout.mjs +115 -0
  26. package/bin/lib/flow-dsl/legacy-yaml.mjs +268 -0
  27. package/bin/lib/flow-dsl/lint.mjs +241 -0
  28. package/bin/lib/flow-dsl/packages.mjs +251 -0
  29. package/bin/lib/flow-dsl/parser.mjs +444 -0
  30. package/bin/lib/flow-import.mjs +96 -26
  31. package/bin/lib/flow-write.mjs +48 -12
  32. package/bin/lib/help.mjs +8 -28
  33. package/bin/lib/html-escape.mjs +19 -0
  34. package/bin/lib/http-util.mjs +49 -0
  35. package/bin/lib/legacy-flow-execution.mjs +37 -0
  36. package/bin/lib/locales/en.json +1 -1
  37. package/bin/lib/locales/zh.json +1 -1
  38. package/bin/lib/main.mjs +152 -286
  39. package/bin/lib/marketplace.mjs +206 -61
  40. package/bin/lib/model-config.mjs +10 -0
  41. package/bin/lib/node-package-archive.mjs +240 -0
  42. package/bin/lib/node-package-bootstrap.mjs +72 -0
  43. package/bin/lib/node-package-manifest.mjs +174 -0
  44. package/bin/lib/paths.mjs +42 -19
  45. package/bin/lib/prd-workflow-routes.mjs +2949 -0
  46. package/bin/lib/prd-workflow-server.mjs +4884 -0
  47. package/bin/lib/run-events.mjs +0 -66
  48. package/bin/lib/schedule-config.mjs +4 -4
  49. package/bin/lib/skill-runtime.mjs +35 -0
  50. package/bin/lib/startup-storage-migrations.mjs +274 -0
  51. package/bin/lib/ui-server.mjs +1087 -18122
  52. package/bin/lib/user-env.mjs +16 -0
  53. package/bin/lib/workspace-auto-layout.mjs +234 -0
  54. package/bin/lib/workspace-flow-store.mjs +478 -0
  55. package/bin/lib/workspace-graph-merge.mjs +41 -34
  56. package/bin/lib/workspace-routes.mjs +3088 -0
  57. package/bin/lib/workspace-server.mjs +6199 -0
  58. package/bin/lib/workspace-state.mjs +331 -0
  59. package/bin/lib/workspace.mjs +2 -1
  60. package/builtin/nodes/agent_subAgent.md +1 -0
  61. package/builtin/nodes/control_agent_toBool.md +2 -0
  62. package/builtin/nodes/control_anyOne.md +2 -0
  63. package/builtin/nodes/control_cancelled.md +2 -0
  64. package/builtin/nodes/control_cd_workspace.md +5 -11
  65. package/builtin/nodes/control_delay.md +2 -0
  66. package/builtin/nodes/control_end.md +2 -0
  67. package/builtin/nodes/control_if.md +1 -0
  68. package/builtin/nodes/control_interval_loop.md +2 -0
  69. package/builtin/nodes/control_load_mcp.md +24 -0
  70. package/builtin/nodes/control_load_skills.md +8 -23
  71. package/builtin/nodes/control_start.md +2 -0
  72. package/builtin/nodes/control_toBool.md +2 -0
  73. package/builtin/nodes/control_user_workspace.md +2 -0
  74. package/builtin/nodes/control_wait_until.md +2 -0
  75. package/builtin/nodes/display_ascii.md +1 -0
  76. package/builtin/nodes/display_chart.md +1 -0
  77. package/builtin/nodes/display_html.md +1 -0
  78. package/builtin/nodes/display_image.md +1 -0
  79. package/builtin/nodes/display_markdown.md +1 -0
  80. package/builtin/nodes/display_mermaid.md +1 -0
  81. package/builtin/nodes/display_react_app.md +1 -0
  82. package/builtin/nodes/display_table.md +1 -0
  83. package/builtin/nodes/provide_bool.md +1 -0
  84. package/builtin/nodes/provide_file.md +1 -0
  85. package/builtin/nodes/provide_password.md +1 -0
  86. package/builtin/nodes/provide_str.md +1 -0
  87. package/builtin/nodes/tool_display_share_link.md +1 -0
  88. package/builtin/nodes/tool_get_env.md +2 -0
  89. package/builtin/nodes/tool_git_checkout.md +1 -0
  90. package/builtin/nodes/tool_git_worktree_load.md +1 -0
  91. package/builtin/nodes/tool_git_worktree_unload.md +1 -0
  92. package/builtin/nodes/tool_gitlab_create_mr.md +1 -0
  93. package/builtin/nodes/tool_jenkins_build.md +2 -0
  94. package/builtin/nodes/tool_load_key.md +2 -0
  95. package/builtin/nodes/tool_nodejs.md +17 -19
  96. package/builtin/nodes/tool_print.md +2 -0
  97. package/builtin/nodes/tool_save_key.md +2 -0
  98. package/builtin/nodes/tool_set_run_env.md +1 -0
  99. package/builtin/nodes/tool_user_ask.md +2 -0
  100. package/builtin/nodes/tool_user_check.md +2 -0
  101. package/builtin/nodes/tool_wecom_send_app_markdown.md +1 -0
  102. package/builtin/nodes/tool_wecom_send_group_markdown.md +1 -0
  103. package/builtin/nodes/workspace_one_click_task.md +44 -0
  104. package/builtin/nodes/workspace_run.md +16 -0
  105. package/builtin/nodes/workspace_scheduled_run.md +16 -0
  106. package/builtin/pipelines/module-migrate/scripts/gate.mjs +37 -0
  107. package/builtin/pipelines/module-migrate/scripts/static-check.mjs +82 -0
  108. package/builtin/pipelines/module-migrate/workspace.flow.js +172 -0
  109. package/builtin/pipelines/module-migrate/workspace.layout.json +134 -0
  110. package/builtin/pipelines/new/scripts/lint-flow.mjs +38 -0
  111. package/builtin/pipelines/new/workspace.flow.js +91 -0
  112. package/builtin/pipelines/new/workspace.layout.json +70 -0
  113. package/builtin/web-ui/dist/assets/{WorkflowAssistantThread-B9xslwI0.js → WorkflowAssistantThread-CKClwj96.js} +1 -1
  114. package/builtin/web-ui/dist/assets/index-BZ5KqLur.js +870 -0
  115. package/builtin/web-ui/dist/assets/index-CEXmmwM2.css +1 -0
  116. package/builtin/web-ui/dist/index.html +2 -2
  117. package/package.json +2 -1
  118. package/reference/flow-control-capabilities.md +77 -158
  119. package/reference/flow-layout.md +1 -1
  120. package/reference/flow-prompt-handler-check.md +2 -2
  121. package/skills/agentflow-author-flow/SKILL.md +1 -1
  122. package/skills/agentflow-cli/SKILL.md +139 -24
  123. package/skills/agentflow-cli/agents/openai.yaml +2 -2
  124. package/skills/agentflow-cli/scripts/agentflow-cli.mjs +654 -20
  125. package/skills/agentflow-cli/scripts/agentflow-runtime.mjs +97 -0
  126. package/skills/agentflow-flow-add-instances/SKILL.md +1 -1
  127. package/skills/agentflow-flow-dsl/SKILL.md +206 -0
  128. package/skills/agentflow-flow-dsl/agents/openai.yaml +4 -0
  129. package/skills/agentflow-flow-dsl/references/node-calls.md +39 -0
  130. package/skills/agentflow-flow-edit-node-fields/SKILL.md +1 -1
  131. package/skills/agentflow-flow-recipes/SKILL.md +7 -4
  132. package/skills/agentflow-flow-recipes/references/recipes.md +97 -43
  133. package/skills/agentflow-flow-sync-ui/SKILL.md +1 -1
  134. package/skills/agentflow-node-dsl/SKILL.md +212 -0
  135. package/skills/agentflow-node-dsl/agents/openai.yaml +4 -0
  136. package/skills/agentflow-node-reference/SKILL.md +2 -2
  137. package/skills/agentflow-node-reference/references/builtin-nodes.md +166 -115
  138. package/skills/agentflow-runtime-reference/references/runtime.md +1 -1
  139. package/skills/agentflow-workspace-ascii/SKILL.md +9 -16
  140. package/skills/agentflow-workspace-graph/SKILL.md +62 -48
  141. package/skills/agentflow-workspace-html/SKILL.md +7 -2
  142. package/skills/agentflow-workspace-image/SKILL.md +6 -2
  143. package/skills/agentflow-workspace-markdown/SKILL.md +14 -21
  144. package/skills/agentflow-workspace-mermaid/SKILL.md +8 -16
  145. package/bin/lib/api-runner.mjs +0 -387
  146. package/bin/lib/apply.mjs +0 -903
  147. package/bin/lib/composer-flow-instances.mjs +0 -68
  148. package/bin/lib/composer-flow-skeleton.mjs +0 -334
  149. package/bin/lib/composer-flow-validate.mjs +0 -47
  150. package/bin/lib/composer-model-router.mjs +0 -185
  151. package/bin/lib/composer-node-schema.mjs +0 -303
  152. package/bin/lib/composer-planner.mjs +0 -751
  153. package/bin/lib/composer-script-ops.mjs +0 -233
  154. package/bin/lib/flow-static-preview.mjs +0 -104
  155. package/bin/lib/hub-login.mjs +0 -54
  156. package/bin/lib/hub-publish.mjs +0 -159
  157. package/bin/lib/hub-remote.mjs +0 -189
  158. package/bin/lib/hub.mjs +0 -299
  159. package/bin/lib/jenkins.mjs +0 -380
  160. package/bin/lib/node-execute.mjs +0 -539
  161. package/bin/lib/normalize-node-tool-command.mjs +0 -97
  162. package/bin/lib/runtime-context.mjs +0 -243
  163. package/bin/lib/scheduler.mjs +0 -601
  164. package/bin/lib/ui-print.mjs +0 -94
  165. package/bin/pipeline/build-node-prompt.mjs +0 -271
  166. package/bin/pipeline/check-cache.mjs +0 -191
  167. package/bin/pipeline/check-flow.mjs +0 -543
  168. package/bin/pipeline/collect-nodes.mjs +0 -212
  169. package/bin/pipeline/compute-cache-md5.mjs +0 -177
  170. package/bin/pipeline/ensure-run-dir.mjs +0 -71
  171. package/bin/pipeline/gc.mjs +0 -129
  172. package/bin/pipeline/get-env.mjs +0 -59
  173. package/bin/pipeline/get-resolved-values.mjs +0 -344
  174. package/bin/pipeline/load-key.mjs +0 -62
  175. package/bin/pipeline/parse-flow.mjs +0 -708
  176. package/bin/pipeline/post-process-control-if.mjs +0 -23
  177. package/bin/pipeline/post-process-node.mjs +0 -490
  178. package/bin/pipeline/pre-process-node.mjs +0 -1430
  179. package/bin/pipeline/resolve-inputs.mjs +0 -201
  180. package/bin/pipeline/run-tool-nodejs.mjs +0 -167
  181. package/bin/pipeline/save-key.mjs +0 -93
  182. package/bin/pipeline/snapshot-prior-round.mjs +0 -70
  183. package/bin/pipeline/validate-for-ui.mjs +0 -234
  184. package/bin/pipeline/validate-script-output.mjs +0 -130
  185. package/bin/pipeline/write-result.mjs +0 -182
  186. package/builtin/pipelines/module-migrate/flow.yaml +0 -819
  187. package/builtin/pipelines/new/flow.yaml +0 -545
  188. package/builtin/pipelines/new/scripts/check-flow.mjs +0 -9
  189. package/builtin/pipelines/new/scripts/collect-nodes.mjs +0 -211
  190. package/builtin/web-ui/dist/assets/index-DZ328oSo.css +0 -1
  191. package/builtin/web-ui/dist/assets/index-DmUV7ZCL.js +0 -888
  192. package/skills/agentflow-node-authoring/SKILL.md +0 -57
@@ -111,3 +111,19 @@ export function resolveUserEnvValue(key, userId) {
111
111
  const fromConfig = getFromConfig(readJsonObject(configPath), keyStr);
112
112
  return fromConfig !== undefined ? fromConfig : "";
113
113
  }
114
+
115
+ /**
116
+ * 子进程环境:进程自身的 env + 该用户配置的 env + 调用方补的 extra。
117
+ *
118
+ * `AGENTFLOW_USER_ID` 放最后,防止用户在自己的 env 里把它改成别人。
119
+ * @param {{ userId?: string }} [userCtx]
120
+ * @param {Record<string, string>} [extra]
121
+ */
122
+ export function runtimeEnvForUser(userCtx = {}, extra = {}) {
123
+ return {
124
+ ...process.env,
125
+ ...readMergedEnvObject(userCtx.userId),
126
+ ...extra,
127
+ AGENTFLOW_USER_ID: userCtx.userId || "",
128
+ };
129
+ }
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Workspace graph 的确定性自动排版。
3
+ *
4
+ * 这是 CLI 和 Web UI 共用的纯函数:不读文件、不依赖 Node API,也不修改传入对象。
5
+ * DSL 只描述流程语义,坐标由这里生成,避免模型手写一堆既脆弱又难维护的数字。
6
+ */
7
+
8
+ const HORIZONTAL_GAP = 160;
9
+ const VERTICAL_GAP = 72;
10
+ const ORIGIN_X = 120;
11
+ const MAIN_Y = 360;
12
+ const COLLISION_MARGIN = 28;
13
+
14
+ function finite(value, fallback) {
15
+ return Number.isFinite(Number(value)) ? Number(value) : fallback;
16
+ }
17
+
18
+ function nodeSize(graph, id) {
19
+ const saved = graph?.ui?.nodeSizes?.[id];
20
+ if (saved && Number.isFinite(saved.width) && Number.isFinite(saved.height)) {
21
+ return { width: Math.max(80, saved.width), height: Math.max(60, saved.height) };
22
+ }
23
+ const definitionId = String(graph?.instances?.[id]?.definitionId || "");
24
+ if (definitionId === "workspace_run" || definitionId === "workspace_scheduled_run") {
25
+ return { width: 256, height: 156 };
26
+ }
27
+ if (definitionId.startsWith("provide_")) return { width: 220, height: 110 };
28
+ if (definitionId.startsWith("display_")) return { width: 496, height: 160 };
29
+ return { width: 260, height: 150 };
30
+ }
31
+
32
+ function handleIndex(handle) {
33
+ const matched = /-(\d+)$/.exec(String(handle || ""));
34
+ return matched ? Number(matched[1]) : 0;
35
+ }
36
+
37
+ function edgeIsControl(graph, edge) {
38
+ const source = graph?.instances?.[edge.source];
39
+ const target = graph?.instances?.[edge.target];
40
+ const output = Array.isArray(source?.output) ? source.output[handleIndex(edge.sourceHandle)] : null;
41
+ const input = Array.isArray(target?.input) ? target.input[handleIndex(edge.targetHandle)] : null;
42
+ return output?.type === "node" || input?.type === "node";
43
+ }
44
+
45
+ function orderedNodeIds(graph) {
46
+ const ids = [];
47
+ const seen = new Set();
48
+ const add = (value) => {
49
+ const id = String(value || "");
50
+ if (!id || seen.has(id)) return;
51
+ seen.add(id);
52
+ ids.push(id);
53
+ };
54
+ for (const id of Object.keys(graph?.instances || {})) add(id);
55
+ for (const edge of graph?.edges || []) {
56
+ add(edge?.source);
57
+ add(edge?.target);
58
+ }
59
+ return ids;
60
+ }
61
+
62
+ /** 所有语义边参与分层;同一对节点的控制线和数据线只计一次。 */
63
+ function graphLayers(graph, ids, order) {
64
+ const known = new Set(ids);
65
+ const outgoing = new Map(ids.map((id) => [id, new Set()]));
66
+ const indegree = new Map(ids.map((id) => [id, 0]));
67
+ for (const edge of graph?.edges || []) {
68
+ const source = String(edge?.source || "");
69
+ const target = String(edge?.target || "");
70
+ if (!known.has(source) || !known.has(target) || source === target || outgoing.get(source).has(target)) continue;
71
+ outgoing.get(source).add(target);
72
+ indegree.set(target, indegree.get(target) + 1);
73
+ }
74
+
75
+ const byOrder = (a, b) => order.get(a) - order.get(b);
76
+ const queue = ids.filter((id) => indegree.get(id) === 0).sort(byOrder);
77
+ const depth = new Map(ids.map((id) => [id, 0]));
78
+ const visited = new Set();
79
+ while (queue.length) {
80
+ const id = queue.shift();
81
+ visited.add(id);
82
+ for (const next of [...outgoing.get(id)].sort(byOrder)) {
83
+ depth.set(next, Math.max(depth.get(next), depth.get(id) + 1));
84
+ indegree.set(next, indegree.get(next) - 1);
85
+ if (indegree.get(next) === 0) {
86
+ queue.push(next);
87
+ queue.sort(byOrder);
88
+ }
89
+ }
90
+ }
91
+
92
+ // lint 会拒绝环;这里仍要保证坏图能打开。环里的节点依声明顺序放到后续列。
93
+ let cycleDepth = Math.max(0, ...depth.values());
94
+ for (const id of ids) {
95
+ if (visited.has(id)) continue;
96
+ cycleDepth += 1;
97
+ depth.set(id, cycleDepth);
98
+ }
99
+ return depth;
100
+ }
101
+
102
+ function stackAt(ids, startY, graph, positions) {
103
+ let y = startY;
104
+ for (const id of ids) {
105
+ positions[id] = { ...positions[id], y };
106
+ y += nodeSize(graph, id).height + VERTICAL_GAP;
107
+ }
108
+ return y;
109
+ }
110
+
111
+ function desiredPositions(graph) {
112
+ const ids = orderedNodeIds(graph);
113
+ const order = new Map(ids.map((id, index) => [id, index]));
114
+ const depth = graphLayers(graph, ids, order);
115
+ const controlIds = new Set();
116
+ for (const edge of graph?.edges || []) {
117
+ if (!edgeIsControl(graph, edge)) continue;
118
+ controlIds.add(String(edge.source));
119
+ controlIds.add(String(edge.target));
120
+ }
121
+ for (const id of ids) {
122
+ const definitionId = String(graph?.instances?.[id]?.definitionId || "");
123
+ if (definitionId === "workspace_run" || definitionId === "workspace_scheduled_run") controlIds.add(id);
124
+ }
125
+
126
+ const columns = new Map();
127
+ for (const id of ids) {
128
+ const d = depth.get(id) || 0;
129
+ if (!columns.has(d)) columns.set(d, []);
130
+ columns.get(d).push(id);
131
+ }
132
+ const depths = [...columns.keys()].sort((a, b) => a - b);
133
+ const positions = {};
134
+ let baseY = MAIN_Y;
135
+ for (const column of columns.values()) {
136
+ const main = column.filter((id) => controlIds.has(id));
137
+ const above = column.filter((id) => !controlIds.has(id)
138
+ && !String(graph?.instances?.[id]?.definitionId || "").startsWith("display_"));
139
+ const aboveHeight = above.reduce((sum, id) => sum + nodeSize(graph, id).height, 0)
140
+ + Math.max(0, above.length - 1) * VERTICAL_GAP;
141
+ if (main.length) baseY = Math.max(baseY, aboveHeight + VERTICAL_GAP + 80);
142
+ else {
143
+ const totalHeight = column.reduce((sum, id) => sum + nodeSize(graph, id).height, 0)
144
+ + Math.max(0, column.length - 1) * VERTICAL_GAP;
145
+ baseY = Math.max(baseY, totalHeight / 2 + 80);
146
+ }
147
+ }
148
+ let x = ORIGIN_X;
149
+ for (const d of depths) {
150
+ const column = columns.get(d).sort((a, b) => order.get(a) - order.get(b));
151
+ const main = column.filter((id) => controlIds.has(id));
152
+ const above = column.filter((id) => !controlIds.has(id)
153
+ && !String(graph?.instances?.[id]?.definitionId || "").startsWith("display_"));
154
+ const below = column.filter((id) => !controlIds.has(id) && !above.includes(id));
155
+ for (const id of column) positions[id] = { x, y: baseY };
156
+
157
+ if (main.length) {
158
+ const mainStart = baseY;
159
+ const mainEnd = stackAt(main, mainStart, graph, positions);
160
+
161
+ const aboveHeight = above.reduce((sum, id) => sum + nodeSize(graph, id).height, 0)
162
+ + Math.max(0, above.length - 1) * VERTICAL_GAP;
163
+ stackAt(above, mainStart - VERTICAL_GAP - aboveHeight, graph, positions);
164
+ stackAt(below, mainEnd, graph, positions);
165
+ } else {
166
+ const all = [...above, ...below];
167
+ const height = all.reduce((sum, id) => sum + nodeSize(graph, id).height, 0)
168
+ + Math.max(0, all.length - 1) * VERTICAL_GAP;
169
+ stackAt(all, baseY - height / 2, graph, positions);
170
+ }
171
+
172
+ const width = Math.max(...column.map((id) => nodeSize(graph, id).width), 0);
173
+ x += width + HORIZONTAL_GAP;
174
+ }
175
+ return positions;
176
+ }
177
+
178
+ function validPosition(value) {
179
+ return value && Number.isFinite(value.x) && Number.isFinite(value.y);
180
+ }
181
+
182
+ function overlaps(a, b) {
183
+ return a.x < b.x + b.width + COLLISION_MARGIN
184
+ && a.x + a.width + COLLISION_MARGIN > b.x
185
+ && a.y < b.y + b.height + COLLISION_MARGIN
186
+ && a.y + a.height + COLLISION_MARGIN > b.y;
187
+ }
188
+
189
+ /**
190
+ * 返回完整 nodePositions。默认保留人工拖过的坐标,只给新节点补位置;`preserveExisting:false`
191
+ * 则整图重排。已有坐标可能不在实例表里,原样保留,避免意外破坏 UI 扩展数据。
192
+ */
193
+ export function layoutWorkspaceNodePositions(graph, { preserveExisting = true } = {}) {
194
+ const desired = desiredPositions(graph || {});
195
+ const existing = graph?.ui?.nodePositions && typeof graph.ui.nodePositions === "object"
196
+ ? graph.ui.nodePositions
197
+ : {};
198
+ const result = preserveExisting ? { ...existing } : {};
199
+ const occupied = [];
200
+
201
+ if (preserveExisting) {
202
+ for (const [id, position] of Object.entries(existing)) {
203
+ if (!validPosition(position)) continue;
204
+ const size = nodeSize(graph, id);
205
+ occupied.push({ id, x: position.x, y: position.y, ...size });
206
+ }
207
+ }
208
+
209
+ for (const id of orderedNodeIds(graph || {})) {
210
+ if (preserveExisting && validPosition(existing[id])) continue;
211
+ const size = nodeSize(graph, id);
212
+ const position = { x: finite(desired[id]?.x, ORIGIN_X), y: finite(desired[id]?.y, MAIN_Y) };
213
+ let candidate = { id, ...position, ...size };
214
+ while (occupied.some((other) => overlaps(candidate, other))) {
215
+ position.y += size.height + VERTICAL_GAP;
216
+ candidate = { id, ...position, ...size };
217
+ }
218
+ result[id] = position;
219
+ occupied.push(candidate);
220
+ }
221
+ return result;
222
+ }
223
+
224
+ export function applyWorkspaceAutoLayout(graph, options = {}) {
225
+ const source = graph && typeof graph === "object" ? graph : {};
226
+ const ui = source.ui && typeof source.ui === "object" ? source.ui : {};
227
+ return {
228
+ ...source,
229
+ ui: {
230
+ ...ui,
231
+ nodePositions: layoutWorkspaceNodePositions(source, options),
232
+ },
233
+ };
234
+ }