makersclaw 0.8.0 → 0.8.2

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 (401) hide show
  1. package/README.md +9 -3
  2. package/package.json +1 -1
  3. package/r/activity-log.json +52 -0
  4. package/r/agent-changes.json +51 -0
  5. package/r/agent-chat.json +53 -0
  6. package/r/agent-column.json +85 -0
  7. package/r/agent-dock.json +57 -0
  8. package/r/agent-kit.json +49 -0
  9. package/r/agent-marks.json +49 -0
  10. package/r/agent-pane.json +93 -0
  11. package/r/ai-action.json +56 -0
  12. package/r/annotate.json +3 -3
  13. package/r/approval-request.json +2 -2
  14. package/r/approval.json +54 -0
  15. package/r/ask-bar.json +50 -0
  16. package/r/audio-player.json +2 -2
  17. package/r/auth-form.json +2 -2
  18. package/r/automation-editor.json +66 -0
  19. package/r/automation-list.json +57 -0
  20. package/r/automation-model.json +118 -0
  21. package/r/automations-screen.json +71 -0
  22. package/r/board.json +2 -2
  23. package/r/calendar-view.json +3 -3
  24. package/r/cart.json +2 -2
  25. package/r/chart.json +2 -2
  26. package/r/chat-pane.json +84 -0
  27. package/r/chat.json +2 -2
  28. package/r/code-editor.json +2 -2
  29. package/r/comment-box.json +3 -3
  30. package/r/connect-card.json +51 -0
  31. package/r/contact-section.json +2 -2
  32. package/r/core.json +13 -7
  33. package/r/cost.json +51 -0
  34. package/r/csv-import.json +3 -3
  35. package/r/data-picker.json +60 -0
  36. package/r/data-table.json +2 -2
  37. package/r/diagram.json +2 -2
  38. package/r/doc-editor.json +2 -2
  39. package/r/doc-page.json +3 -3
  40. package/r/email-render.json +2 -2
  41. package/r/faq.json +2 -2
  42. package/r/file-upload.json +2 -2
  43. package/r/first-run.json +63 -0
  44. package/r/fix-note.json +57 -0
  45. package/r/flow-canvas.json +2 -2
  46. package/r/flow-editor.json +79 -0
  47. package/r/footer.json +2 -2
  48. package/r/gantt.json +3 -3
  49. package/r/job-panel.json +2 -2
  50. package/r/json-editor.json +3 -3
  51. package/r/library-shelf.json +56 -0
  52. package/r/map.json +2 -2
  53. package/r/margin-notes.json +67 -0
  54. package/r/menubar.json +2 -2
  55. package/r/mind-map.json +3 -3
  56. package/r/navigation-menu.json +2 -2
  57. package/r/needs-you.json +55 -0
  58. package/r/order-detail.json +2 -2
  59. package/r/org-chart.json +3 -3
  60. package/r/pace-bar.json +69 -0
  61. package/r/page-builder.json +2 -2
  62. package/r/payment-methods.json +2 -2
  63. package/r/pdf-document.json +2 -2
  64. package/r/pdf-viewer.json +2 -2
  65. package/r/product-detail.json +2 -2
  66. package/r/product-grid.json +3 -3
  67. package/r/record-form.json +2 -2
  68. package/r/record-grid.json +52 -0
  69. package/r/record-notes.json +4 -4
  70. package/r/registry.json +4086 -1512
  71. package/r/run-history.json +52 -0
  72. package/r/run-view.json +80 -0
  73. package/r/schedule-card.json +54 -0
  74. package/r/schedule-engine.json +79 -0
  75. package/r/schedule-gantt.json +83 -0
  76. package/r/schedule-ruler.json +64 -0
  77. package/r/search-dialog.json +2 -2
  78. package/r/settings-list.json +2 -2
  79. package/r/setup-checklist.json +2 -2
  80. package/r/share-dialog.json +2 -2
  81. package/r/sidebar.json +2 -2
  82. package/r/signature-pad.json +2 -2
  83. package/r/sketch-canvas.json +2 -2
  84. package/r/source-receipt.json +52 -0
  85. package/r/spreadsheet.json +3 -3
  86. package/r/stat-cards.json +3 -3
  87. package/r/step-picker.json +53 -0
  88. package/r/step-settings.json +72 -0
  89. package/r/suggestion.json +58 -0
  90. package/r/sum-bar.json +64 -0
  91. package/r/task-list.json +3 -3
  92. package/r/task-model.json +2 -2
  93. package/r/testimonials.json +2 -2
  94. package/r/tier-map.json +67 -0
  95. package/r/time-grid.json +73 -0
  96. package/r/time-strip.json +64 -0
  97. package/r/top-bar.json +66 -0
  98. package/r/transaction-list.json +2 -2
  99. package/r/trigger-picker.json +61 -0
  100. package/r/whiteboard.json +3 -3
  101. package/r/workflow-view.json +55 -0
  102. package/registry/blocks/activity-log/README.md +112 -0
  103. package/registry/blocks/activity-log/activity-log.jsx +351 -0
  104. package/registry/blocks/activity-log/block.json +33 -0
  105. package/registry/blocks/activity-log/demo.jsx +48 -0
  106. package/registry/blocks/activity-log/index.js +4 -0
  107. package/registry/blocks/agent-changes/README.md +94 -0
  108. package/registry/blocks/agent-changes/agent-changes.jsx +118 -0
  109. package/registry/blocks/agent-changes/block.json +28 -0
  110. package/registry/blocks/agent-changes/demo.jsx +39 -0
  111. package/registry/blocks/agent-changes/index.js +3 -0
  112. package/registry/blocks/agent-chat/README.md +145 -0
  113. package/registry/blocks/agent-chat/agent-chat.jsx +415 -0
  114. package/registry/blocks/agent-chat/block.json +30 -0
  115. package/registry/blocks/agent-chat/demo.jsx +165 -0
  116. package/registry/blocks/agent-chat/index.js +3 -0
  117. package/registry/blocks/agent-column/README.md +197 -0
  118. package/registry/blocks/agent-column/agent-column.jsx +492 -0
  119. package/registry/blocks/agent-column/block.json +67 -0
  120. package/registry/blocks/agent-column/column-picker.jsx +163 -0
  121. package/registry/blocks/agent-column/demo.jsx +50 -0
  122. package/registry/blocks/agent-column/index.js +7 -0
  123. package/registry/blocks/agent-column/model.js +164 -0
  124. package/registry/blocks/agent-column/receipt.jsx +483 -0
  125. package/registry/blocks/agent-column/spreadsheet-type.jsx +24 -0
  126. package/registry/blocks/agent-dock/README.md +210 -0
  127. package/registry/blocks/agent-dock/agent-dock.jsx +356 -0
  128. package/registry/blocks/agent-dock/block.json +47 -0
  129. package/registry/blocks/agent-dock/demo.jsx +153 -0
  130. package/registry/blocks/agent-dock/dock-model.js +118 -0
  131. package/registry/blocks/agent-dock/index.js +5 -0
  132. package/registry/blocks/agent-kit/README.md +73 -0
  133. package/registry/blocks/agent-kit/agent-kit.jsx +86 -0
  134. package/registry/blocks/agent-kit/block.json +10 -0
  135. package/registry/blocks/agent-kit/demo.jsx +35 -0
  136. package/registry/blocks/agent-kit/index.js +3 -0
  137. package/registry/blocks/agent-marks/README.md +80 -0
  138. package/registry/blocks/agent-marks/agent-marks.jsx +133 -0
  139. package/registry/blocks/agent-marks/block.json +27 -0
  140. package/registry/blocks/agent-marks/demo.jsx +49 -0
  141. package/registry/blocks/agent-marks/index.js +3 -0
  142. package/registry/blocks/agent-pane/README.md +234 -0
  143. package/registry/blocks/agent-pane/agent-pane.jsx +246 -0
  144. package/registry/blocks/agent-pane/block.json +41 -0
  145. package/registry/blocks/agent-pane/composer.jsx +6 -0
  146. package/registry/blocks/agent-pane/demo.jsx +233 -0
  147. package/registry/blocks/agent-pane/dock-context.js +10 -0
  148. package/registry/blocks/agent-pane/index.js +4 -0
  149. package/registry/blocks/agent-pane/prose.jsx +84 -0
  150. package/registry/blocks/agent-pane/questions.jsx +134 -0
  151. package/registry/blocks/agent-pane/transcript.jsx +268 -0
  152. package/registry/blocks/agent-pane/work.jsx +368 -0
  153. package/registry/blocks/ai-action/README.md +94 -0
  154. package/registry/blocks/ai-action/ai-action.jsx +188 -0
  155. package/registry/blocks/ai-action/block.json +34 -0
  156. package/registry/blocks/ai-action/demo.jsx +93 -0
  157. package/registry/blocks/ai-action/index.js +3 -0
  158. package/registry/blocks/approval/README.md +145 -0
  159. package/registry/blocks/approval/approval.jsx +163 -0
  160. package/registry/blocks/approval/block.json +31 -0
  161. package/registry/blocks/approval/demo.jsx +121 -0
  162. package/registry/blocks/approval/index.js +3 -0
  163. package/registry/blocks/ask-bar/README.md +105 -0
  164. package/registry/blocks/ask-bar/ask-bar.jsx +166 -0
  165. package/registry/blocks/ask-bar/block.json +26 -0
  166. package/registry/blocks/ask-bar/demo.jsx +78 -0
  167. package/registry/blocks/ask-bar/index.js +3 -0
  168. package/registry/blocks/automation-editor/README.md +291 -0
  169. package/registry/blocks/automation-editor/automation-editor.jsx +656 -0
  170. package/registry/blocks/automation-editor/block.json +39 -0
  171. package/registry/blocks/automation-editor/demo.jsx +284 -0
  172. package/registry/blocks/automation-editor/index.js +4 -0
  173. package/registry/blocks/automation-editor/run-inputs.jsx +82 -0
  174. package/registry/blocks/automation-list/README.md +129 -0
  175. package/registry/blocks/automation-list/automation-list.jsx +476 -0
  176. package/registry/blocks/automation-list/block.json +35 -0
  177. package/registry/blocks/automation-list/demo.jsx +67 -0
  178. package/registry/blocks/automation-list/index.js +3 -0
  179. package/registry/blocks/automation-model/README.md +109 -0
  180. package/registry/blocks/automation-model/block.json +135 -0
  181. package/registry/blocks/automation-model/catalog.js +256 -0
  182. package/registry/blocks/automation-model/check.js +161 -0
  183. package/registry/blocks/automation-model/demo.jsx +42 -0
  184. package/registry/blocks/automation-model/edit.js +262 -0
  185. package/registry/blocks/automation-model/fixes.js +287 -0
  186. package/registry/blocks/automation-model/glyph.jsx +13 -0
  187. package/registry/blocks/automation-model/graph.js +410 -0
  188. package/registry/blocks/automation-model/index.js +33 -0
  189. package/registry/blocks/automation-model/overlay.js +175 -0
  190. package/registry/blocks/automation-model/parts.jsx +94 -0
  191. package/registry/blocks/automation-model/schedule.js +53 -0
  192. package/registry/blocks/automation-model/templates.js +128 -0
  193. package/registry/blocks/automation-model/values.js +29 -0
  194. package/registry/blocks/automation-model/words.js +439 -0
  195. package/registry/blocks/automations-screen/README.md +207 -0
  196. package/registry/blocks/automations-screen/automations-screen.jsx +452 -0
  197. package/registry/blocks/automations-screen/block.json +47 -0
  198. package/registry/blocks/automations-screen/demo.jsx +364 -0
  199. package/registry/blocks/automations-screen/index.js +4 -0
  200. package/registry/blocks/automations-screen/screen-model.js +129 -0
  201. package/registry/blocks/chat-pane/README.md +143 -0
  202. package/registry/blocks/chat-pane/block.json +48 -0
  203. package/registry/blocks/chat-pane/chat-attach.js +166 -0
  204. package/registry/blocks/chat-pane/chat-composer.jsx +195 -0
  205. package/registry/blocks/chat-pane/chat-context.js +17 -0
  206. package/registry/blocks/chat-pane/chat-model.js +43 -0
  207. package/registry/blocks/chat-pane/chat-pane.jsx +398 -0
  208. package/registry/blocks/chat-pane/chats-list.jsx +52 -0
  209. package/registry/blocks/chat-pane/demo.jsx +103 -0
  210. package/registry/blocks/chat-pane/index.js +9 -0
  211. package/registry/blocks/connect-card/README.md +99 -0
  212. package/registry/blocks/connect-card/block.json +10 -0
  213. package/registry/blocks/connect-card/connect-card.jsx +103 -0
  214. package/registry/blocks/connect-card/demo.jsx +49 -0
  215. package/registry/blocks/connect-card/index.js +3 -0
  216. package/registry/blocks/cost/README.md +115 -0
  217. package/registry/blocks/cost/block.json +10 -0
  218. package/registry/blocks/cost/cost.jsx +176 -0
  219. package/registry/blocks/cost/demo.jsx +66 -0
  220. package/registry/blocks/cost/index.js +3 -0
  221. package/registry/blocks/data-picker/README.md +81 -0
  222. package/registry/blocks/data-picker/block.json +38 -0
  223. package/registry/blocks/data-picker/data-picker.jsx +210 -0
  224. package/registry/blocks/data-picker/demo.jsx +34 -0
  225. package/registry/blocks/data-picker/fields.js +89 -0
  226. package/registry/blocks/data-picker/index.js +4 -0
  227. package/registry/blocks/data-table/demo.jsx +1 -1
  228. package/registry/blocks/first-run/README.md +118 -0
  229. package/registry/blocks/first-run/block.json +11 -0
  230. package/registry/blocks/first-run/demo.jsx +88 -0
  231. package/registry/blocks/first-run/first-run-model.js +51 -0
  232. package/registry/blocks/first-run/first-run.jsx +156 -0
  233. package/registry/blocks/first-run/index.js +5 -0
  234. package/registry/blocks/first-run/probe-rules.js +26 -0
  235. package/registry/blocks/fix-note/README.md +79 -0
  236. package/registry/blocks/fix-note/block.json +35 -0
  237. package/registry/blocks/fix-note/demo.jsx +30 -0
  238. package/registry/blocks/fix-note/fix-note.jsx +235 -0
  239. package/registry/blocks/fix-note/index.js +3 -0
  240. package/registry/blocks/flow-editor/README.md +108 -0
  241. package/registry/blocks/flow-editor/block.json +44 -0
  242. package/registry/blocks/flow-editor/demo.jsx +115 -0
  243. package/registry/blocks/flow-editor/flow-canvas.jsx +568 -0
  244. package/registry/blocks/flow-editor/flow-editor.jsx +154 -0
  245. package/registry/blocks/flow-editor/index.js +6 -0
  246. package/registry/blocks/flow-editor/minimap.jsx +78 -0
  247. package/registry/blocks/flow-editor/outline.jsx +134 -0
  248. package/registry/blocks/library-shelf/README.md +117 -0
  249. package/registry/blocks/library-shelf/block.json +28 -0
  250. package/registry/blocks/library-shelf/demo.jsx +68 -0
  251. package/registry/blocks/library-shelf/index.js +3 -0
  252. package/registry/blocks/library-shelf/library-shelf.jsx +211 -0
  253. package/registry/blocks/library-shelf/probe-rules.js +15 -0
  254. package/registry/blocks/margin-notes/README.md +222 -0
  255. package/registry/blocks/margin-notes/block.json +10 -0
  256. package/registry/blocks/margin-notes/demo.jsx +144 -0
  257. package/registry/blocks/margin-notes/index.js +20 -0
  258. package/registry/blocks/margin-notes/margin-model.js +224 -0
  259. package/registry/blocks/margin-notes/margin-notes.jsx +465 -0
  260. package/registry/blocks/needs-you/README.md +177 -0
  261. package/registry/blocks/needs-you/block.json +34 -0
  262. package/registry/blocks/needs-you/demo.jsx +143 -0
  263. package/registry/blocks/needs-you/index.js +3 -0
  264. package/registry/blocks/needs-you/needs-you.jsx +441 -0
  265. package/registry/blocks/pace-bar/README.md +230 -0
  266. package/registry/blocks/pace-bar/block.json +10 -0
  267. package/registry/blocks/pace-bar/demo.jsx +255 -0
  268. package/registry/blocks/pace-bar/index.js +22 -0
  269. package/registry/blocks/pace-bar/pace-bar.jsx +461 -0
  270. package/registry/blocks/pace-bar/pace-model.js +288 -0
  271. package/registry/blocks/record-grid/README.md +100 -0
  272. package/registry/blocks/record-grid/block.json +28 -0
  273. package/registry/blocks/record-grid/demo.jsx +43 -0
  274. package/registry/blocks/record-grid/index.js +3 -0
  275. package/registry/blocks/record-grid/record-grid.jsx +251 -0
  276. package/registry/blocks/run-history/README.md +138 -0
  277. package/registry/blocks/run-history/block.json +10 -0
  278. package/registry/blocks/run-history/demo.jsx +74 -0
  279. package/registry/blocks/run-history/index.js +3 -0
  280. package/registry/blocks/run-history/run-history.jsx +218 -0
  281. package/registry/blocks/run-view/README.md +174 -0
  282. package/registry/blocks/run-view/block.json +50 -0
  283. package/registry/blocks/run-view/demo.jsx +286 -0
  284. package/registry/blocks/run-view/index.js +5 -0
  285. package/registry/blocks/run-view/run-controls.jsx +266 -0
  286. package/registry/blocks/run-view/run-view.jsx +236 -0
  287. package/registry/blocks/run-view/runs-list.jsx +99 -0
  288. package/registry/blocks/schedule-card/README.md +121 -0
  289. package/registry/blocks/schedule-card/block.json +10 -0
  290. package/registry/blocks/schedule-card/demo.jsx +82 -0
  291. package/registry/blocks/schedule-card/index.js +3 -0
  292. package/registry/blocks/schedule-card/schedule-card.jsx +136 -0
  293. package/registry/blocks/schedule-engine/README.md +137 -0
  294. package/registry/blocks/schedule-engine/block.json +10 -0
  295. package/registry/blocks/schedule-engine/demo.jsx +82 -0
  296. package/registry/blocks/schedule-engine/engine.js +769 -0
  297. package/registry/blocks/schedule-engine/index.js +9 -0
  298. package/registry/blocks/schedule-engine/ops.js +71 -0
  299. package/registry/blocks/schedule-engine/place.js +294 -0
  300. package/registry/blocks/schedule-engine/tree.js +79 -0
  301. package/registry/blocks/schedule-engine/waits.js +80 -0
  302. package/registry/blocks/schedule-gantt/README.md +159 -0
  303. package/registry/blocks/schedule-gantt/block.json +10 -0
  304. package/registry/blocks/schedule-gantt/demo.jsx +223 -0
  305. package/registry/blocks/schedule-gantt/gantt-model.js +219 -0
  306. package/registry/blocks/schedule-gantt/geometry.js +176 -0
  307. package/registry/blocks/schedule-gantt/index.js +26 -0
  308. package/registry/blocks/schedule-gantt/schedule-gantt.jsx +882 -0
  309. package/registry/blocks/schedule-gantt/sheet.jsx +372 -0
  310. package/registry/blocks/schedule-gantt/track.jsx +190 -0
  311. package/registry/blocks/schedule-ruler/README.md +148 -0
  312. package/registry/blocks/schedule-ruler/block.json +10 -0
  313. package/registry/blocks/schedule-ruler/demo.jsx +181 -0
  314. package/registry/blocks/schedule-ruler/index.js +21 -0
  315. package/registry/blocks/schedule-ruler/ruler-model.js +239 -0
  316. package/registry/blocks/schedule-ruler/schedule-ruler.jsx +548 -0
  317. package/registry/blocks/source-receipt/README.md +97 -0
  318. package/registry/blocks/source-receipt/block.json +30 -0
  319. package/registry/blocks/source-receipt/demo.jsx +71 -0
  320. package/registry/blocks/source-receipt/index.js +3 -0
  321. package/registry/blocks/source-receipt/source-receipt.jsx +107 -0
  322. package/registry/blocks/spreadsheet/spreadsheet.jsx +15 -1
  323. package/registry/blocks/step-picker/README.md +78 -0
  324. package/registry/blocks/step-picker/block.json +31 -0
  325. package/registry/blocks/step-picker/demo.jsx +23 -0
  326. package/registry/blocks/step-picker/index.js +3 -0
  327. package/registry/blocks/step-picker/step-picker.jsx +144 -0
  328. package/registry/blocks/step-settings/README.md +100 -0
  329. package/registry/blocks/step-settings/block.json +44 -0
  330. package/registry/blocks/step-settings/demo.jsx +93 -0
  331. package/registry/blocks/step-settings/fields.jsx +58 -0
  332. package/registry/blocks/step-settings/flow-settings.jsx +115 -0
  333. package/registry/blocks/step-settings/index.js +5 -0
  334. package/registry/blocks/step-settings/step-settings.jsx +290 -0
  335. package/registry/blocks/suggestion/README.md +171 -0
  336. package/registry/blocks/suggestion/block.json +40 -0
  337. package/registry/blocks/suggestion/demo.jsx +91 -0
  338. package/registry/blocks/suggestion/index.js +3 -0
  339. package/registry/blocks/suggestion/suggestion.jsx +436 -0
  340. package/registry/blocks/sum-bar/README.md +122 -0
  341. package/registry/blocks/sum-bar/block.json +10 -0
  342. package/registry/blocks/sum-bar/demo.jsx +110 -0
  343. package/registry/blocks/sum-bar/index.js +5 -0
  344. package/registry/blocks/sum-bar/sum-bar.jsx +209 -0
  345. package/registry/blocks/sum-bar/sum-model.js +126 -0
  346. package/registry/blocks/tier-map/README.md +217 -0
  347. package/registry/blocks/tier-map/block.json +10 -0
  348. package/registry/blocks/tier-map/demo.jsx +222 -0
  349. package/registry/blocks/tier-map/index.js +24 -0
  350. package/registry/blocks/tier-map/tier-map.jsx +574 -0
  351. package/registry/blocks/tier-map/tier-model.js +318 -0
  352. package/registry/blocks/time-grid/README.md +305 -0
  353. package/registry/blocks/time-grid/block.json +10 -0
  354. package/registry/blocks/time-grid/demo.jsx +279 -0
  355. package/registry/blocks/time-grid/grid-model.js +322 -0
  356. package/registry/blocks/time-grid/index.js +25 -0
  357. package/registry/blocks/time-grid/time-grid.jsx +1325 -0
  358. package/registry/blocks/time-strip/README.md +141 -0
  359. package/registry/blocks/time-strip/block.json +10 -0
  360. package/registry/blocks/time-strip/demo.jsx +129 -0
  361. package/registry/blocks/time-strip/index.js +19 -0
  362. package/registry/blocks/time-strip/strip-model.js +178 -0
  363. package/registry/blocks/time-strip/time-strip.jsx +260 -0
  364. package/registry/blocks/top-bar/README.md +149 -0
  365. package/registry/blocks/top-bar/block.json +35 -0
  366. package/registry/blocks/top-bar/demo.jsx +78 -0
  367. package/registry/blocks/top-bar/index.js +5 -0
  368. package/registry/blocks/top-bar/probe-rules.js +74 -0
  369. package/registry/blocks/top-bar/top-bar-model.js +152 -0
  370. package/registry/blocks/top-bar/top-bar.jsx +244 -0
  371. package/registry/blocks/trigger-picker/README.md +98 -0
  372. package/registry/blocks/trigger-picker/block.json +38 -0
  373. package/registry/blocks/trigger-picker/demo.jsx +59 -0
  374. package/registry/blocks/trigger-picker/index.js +3 -0
  375. package/registry/blocks/trigger-picker/trigger-picker.jsx +374 -0
  376. package/registry/blocks/workflow-view/README.md +123 -0
  377. package/registry/blocks/workflow-view/block.json +10 -0
  378. package/registry/blocks/workflow-view/demo.jsx +90 -0
  379. package/registry/blocks/workflow-view/index.js +3 -0
  380. package/registry/blocks/workflow-view/workflow-view.jsx +203 -0
  381. package/src/install.mjs +77 -16
  382. package/src/registry.mjs +3 -0
  383. package/templates/next/browser/lib/data.js +6 -1
  384. package/templates/next/files/README.md +627 -24
  385. package/templates/next/files/check/automation-format.ts +2103 -0
  386. package/templates/next/files/check/automation-package.ts +142 -0
  387. package/templates/next/files/check/run.mjs +968 -9
  388. package/templates/next/files/components/ui/field.jsx +17 -4
  389. package/templates/next/files/components/ui/icon.jsx +13 -0
  390. package/templates/next/files/components/ui/index.js +2 -1
  391. package/templates/next/files/components/ui/layout.jsx +77 -2
  392. package/templates/next/files/components/ui/notice.jsx +70 -0
  393. package/templates/next/files/components/ui/page.jsx +124 -0
  394. package/templates/next/files/components/ui/stat.jsx +22 -7
  395. package/templates/next/files/components/ui/toast.jsx +6 -3
  396. package/templates/next/files/lib/automations.js +660 -0
  397. package/templates/next/files/lib/claw.js +241 -5
  398. package/templates/next/files/lib/door.js +92 -0
  399. package/templates/next/files/lib/hooks.js +1677 -8
  400. package/templates/next/files/lib/platform.js +529 -21
  401. package/templates/next/template.json +13 -3
@@ -0,0 +1,410 @@
1
+ // The canvas's layout: an automation (a trigger and a tree of steps)
2
+ // turned into boxes and curved connectors, left to right.
3
+ //
4
+ // Pure. No React, no DOM, no measuring: every size is a constant, so the
5
+ // same definition always gives the same picture and a test can read it.
6
+ //
7
+ // What the picture says:
8
+ // - the trigger at the left, then the steps, a connector with a + between
9
+ // any two of them, and a + bubble where a path ends;
10
+ // - a condition is a router: its branches are labelled paths, one above
11
+ // the other, and they meet again at a small join dot where the next
12
+ // step carries on. A branch that ends in a Stop never meets it;
13
+ // - "for each" is a dashed box around its steps, with a door in and a
14
+ // door out; collapsed it is one card that lists them.
15
+ //
16
+ // The format has no cycles and no free joins, so a branch can only rejoin
17
+ // where its condition ends. That is what keeps this a layout, not a
18
+ // graph-drawing problem.
19
+ //
20
+ // Every connector knows its `slot`: the place in the definition a step
21
+ // inserted there would land (edit.js insertStep).
22
+
23
+ import { KINDS, stepSub, stepTitle, triggerTitle } from "./catalog";
24
+
25
+ /* ---- sizes -------------------------------------------------------------- */
26
+
27
+ export const T = 72; // a step's tile
28
+ const PITCH = 196; // one step's column: the tile, its label, room for a connector
29
+ const LABEL_BELOW = 76; // the title and the quiet line under a tile
30
+ const ABOVE_TILE = 22; // a badge and a step number above it
31
+ const JOIN_W = 52; // the column a join dot takes
32
+ const MIN_BRANCH = 110; // an empty branch is still a path
33
+ const BRANCH_GAP = 30;
34
+ const LOOP_PAD_L = 44;
35
+ const LOOP_PAD_R = 44;
36
+ const LOOP_PAD_T = 46;
37
+ const LOOP_PAD_B = 22;
38
+ const LOOP_LEAD = 28; // before the box's door
39
+ const LOOP_MIN_INNER = 150;
40
+ const PORT = 14;
41
+ const END = 28; // the + bubble at a path's end
42
+ const END_GAP = 64;
43
+ const CARD_W = 232;
44
+ export const MARGIN = 90;
45
+ /** The label under a tile is this wide, centred on the tile. */
46
+ export const LABEL_W = 156;
47
+
48
+ /* ---- small helpers ------------------------------------------------------ */
49
+
50
+ const emptyFrag = () => ({ nodes: [], edges: [], groups: [], entry: null, tails: [], w: 0, above: 0, below: 0 });
51
+
52
+ function shift(f, dx, dy) {
53
+ for (const n of f.nodes) {
54
+ n.x += dx;
55
+ n.y += dy;
56
+ }
57
+ for (const g of f.groups) {
58
+ g.x += dx;
59
+ g.y += dy;
60
+ }
61
+ return f;
62
+ }
63
+
64
+ function absorb(into, f) {
65
+ into.nodes.push(...f.nodes);
66
+ into.edges.push(...f.edges);
67
+ into.groups.push(...f.groups);
68
+ }
69
+
70
+ let edgeCounter = 0;
71
+ function edge(from, to, t, plus = true) {
72
+ edgeCounter += 1;
73
+ return { id: `e${edgeCounter}:${from}>${to}`, from, to, label: t.label, branch: t.branch, slot: t.slot, plus: plus && t.slot !== null };
74
+ }
75
+
76
+ export const sameSlot = (a, b) => a.index === b.index && JSON.stringify(a.list) === JSON.stringify(b.list);
77
+
78
+ /* ---- steps -------------------------------------------------------------- */
79
+
80
+ function leaf(step, num) {
81
+ const info = KINDS[step.kind] ?? KINDS.action;
82
+ return {
83
+ id: step.id,
84
+ type: "step",
85
+ stepId: step.id,
86
+ kind: step.kind,
87
+ x: (PITCH - T) / 2,
88
+ y: -T / 2,
89
+ w: T,
90
+ h: T,
91
+ title: stepTitle(step),
92
+ sub: stepSub(step),
93
+ tone: info.tone,
94
+ mark: info.mark,
95
+ num,
96
+ };
97
+ }
98
+
99
+ function stepFrag(step, ref, index, hasNext, ctx) {
100
+ const after = { list: ref, index: index + 1 };
101
+ if (step.kind === "condition") return conditionFrag(step, ref, index, hasNext, ctx);
102
+ if (step.kind === "loop") return loopFrag(step, ref, index, ctx);
103
+ const f = emptyFrag();
104
+ f.nodes.push(leaf(step, ctx.next()));
105
+ f.entry = step.id;
106
+ // A Stop ends its path: nothing follows it.
107
+ f.tails = step.kind === "stop" ? [] : [{ from: step.id, slot: after }];
108
+ f.w = PITCH;
109
+ f.above = T / 2 + ABOVE_TILE;
110
+ f.below = T / 2 + LABEL_BELOW;
111
+ return f;
112
+ }
113
+
114
+ function seq(steps, ref, ctx) {
115
+ const out = emptyFrag();
116
+ let prev = [];
117
+ let x = 0;
118
+ steps.forEach((step, i) => {
119
+ const f = shift(stepFrag(step, ref, i, i < steps.length - 1, ctx), x, 0);
120
+ absorb(out, f);
121
+ if (i === 0) out.entry = f.entry;
122
+ else if (f.entry) for (const t of prev) out.edges.push(edge(t.from, f.entry, t, true));
123
+ prev = f.tails;
124
+ x += f.w;
125
+ out.above = Math.max(out.above, f.above);
126
+ out.below = Math.max(out.below, f.below);
127
+ });
128
+ out.tails = prev;
129
+ out.w = x;
130
+ return out;
131
+ }
132
+
133
+ function conditionFrag(step, ref, index, hasNext, ctx) {
134
+ const f = emptyFrag();
135
+ f.nodes.push(leaf(step, ctx.next()));
136
+ f.entry = step.id;
137
+ const branches = [
138
+ { key: "then", label: "Yes", list: step.then ?? [], ref: { at: "then", step: step.id } },
139
+ { key: "else", label: "No", list: step.else ?? [], ref: { at: "else", step: step.id } },
140
+ ];
141
+ const built = branches.map((b) => ({ b, frag: seq(b.list, b.ref, ctx) }));
142
+ const wb = Math.max(MIN_BRANCH, ...built.map((x) => x.frag.w));
143
+
144
+ // Stack the branches: the first above the main line, the second below it.
145
+ const [first, second] = built;
146
+ const line0 = -(BRANCH_GAP / 2 + first.frag.below);
147
+ const line1 = BRANCH_GAP / 2 + second.frag.above;
148
+ const lines = [line0, line1];
149
+
150
+ const joinId = `${step.id}:join`;
151
+ const tails = [];
152
+ built.forEach(({ b, frag }, k) => {
153
+ const start = { from: step.id, label: b.label, branch: b.key, slot: { list: b.ref, index: 0 } };
154
+ if (frag.entry) {
155
+ shift(frag, PITCH, lines[k]);
156
+ absorb(f, frag);
157
+ f.edges.push(edge(step.id, frag.entry, start, true));
158
+ tails.push(...frag.tails);
159
+ } else {
160
+ tails.push(start);
161
+ }
162
+ });
163
+
164
+ const width = PITCH + wb;
165
+ if (hasNext) {
166
+ f.nodes.push({
167
+ id: joinId,
168
+ type: "join",
169
+ stepId: step.id,
170
+ kind: null,
171
+ x: width + JOIN_W / 2 - 7,
172
+ y: -7,
173
+ w: 14,
174
+ h: 14,
175
+ title: "",
176
+ sub: "",
177
+ tone: "plain",
178
+ num: 0,
179
+ });
180
+ for (const t of tails) f.edges.push(edge(t.from, joinId, t, true));
181
+ f.tails = [{ from: joinId, slot: { list: ref, index: index + 1 } }];
182
+ f.w = width + JOIN_W;
183
+ } else {
184
+ f.tails = tails;
185
+ f.w = width + 20;
186
+ }
187
+ f.above = Math.max(T / 2 + ABOVE_TILE, -line0 + first.frag.above);
188
+ f.below = Math.max(T / 2 + LABEL_BELOW, line1 + second.frag.below);
189
+ return f;
190
+ }
191
+
192
+ function loopFrag(step, ref, index, ctx) {
193
+ const f = emptyFrag();
194
+ const after = { list: ref, index: index + 1 };
195
+ const num = ctx.next();
196
+ const info = KINDS.loop;
197
+ const inId = `${step.id}:in`;
198
+ const outId = `${step.id}:out`;
199
+ const innerRef = { at: "loop", step: step.id };
200
+ const title = stepTitle(step);
201
+ const sub = stepSub(step);
202
+ const inside = step.steps ?? [];
203
+
204
+ if (ctx.collapsed.has(step.id)) {
205
+ // One card that lists what is inside.
206
+ const items = inside.map((s) => ({ id: s.id, title: stepTitle(s) }));
207
+ const h = 64 + Math.max(1, items.length) * 32;
208
+ f.nodes.push({
209
+ id: step.id,
210
+ type: "card",
211
+ stepId: step.id,
212
+ kind: "loop",
213
+ x: LOOP_LEAD,
214
+ y: -h / 2,
215
+ w: CARD_W,
216
+ h,
217
+ title,
218
+ sub,
219
+ tone: info.tone,
220
+ num,
221
+ items,
222
+ });
223
+ f.entry = step.id;
224
+ f.tails = [{ from: step.id, slot: after }];
225
+ f.w = LOOP_LEAD + CARD_W + 36;
226
+ f.above = h / 2 + 12;
227
+ f.below = h / 2 + 12;
228
+ return f;
229
+ }
230
+
231
+ const inner = seq(inside, innerRef, ctx);
232
+ const empty = inside.length === 0;
233
+ const innerW = empty ? LOOP_MIN_INNER : Math.max(LOOP_MIN_INNER, inner.w);
234
+ const above = empty ? T / 2 + ABOVE_TILE : inner.above;
235
+ const below = empty ? T / 2 + 12 : inner.below;
236
+ const w = LOOP_PAD_L + innerW + LOOP_PAD_R;
237
+ const h = above + below + LOOP_PAD_T + LOOP_PAD_B;
238
+ f.groups.push({ id: step.id, stepId: step.id, x: LOOP_LEAD, y: -(above + LOOP_PAD_T), w, h, title, sub });
239
+ const port = (id, x) => ({
240
+ id,
241
+ type: "port",
242
+ stepId: step.id,
243
+ kind: "loop",
244
+ x: x - PORT / 2,
245
+ y: -PORT / 2,
246
+ w: PORT,
247
+ h: PORT,
248
+ title: "",
249
+ sub: "",
250
+ tone: info.tone,
251
+ num: 0,
252
+ });
253
+ f.nodes.push(port(inId, LOOP_LEAD), port(outId, LOOP_LEAD + w));
254
+ f.entry = inId;
255
+ if (!empty && inner.entry) {
256
+ shift(inner, LOOP_LEAD + LOOP_PAD_L, 0);
257
+ absorb(f, inner);
258
+ f.edges.push(edge(inId, inner.entry, { slot: { list: innerRef, index: 0 } }, true));
259
+ for (const t of inner.tails) f.edges.push(edge(t.from, outId, t, true));
260
+ } else {
261
+ f.edges.push(edge(inId, outId, { slot: { list: innerRef, index: 0 } }, true));
262
+ }
263
+ f.tails = [{ from: outId, slot: after }];
264
+ f.w = LOOP_LEAD + w + 36;
265
+ f.above = above + LOOP_PAD_T + 6;
266
+ f.below = below + LOOP_PAD_B + 6;
267
+ return f;
268
+ }
269
+
270
+ /* ---- the whole picture --------------------------------------------------- */
271
+
272
+ /**
273
+ * layoutAutomation(def, { triggerWords, collapsed })
274
+ * → { nodes, edges, groups, bounds }
275
+ * `triggerWords` is the trigger in words ("Weekdays at 07:00"); `collapsed`
276
+ * a Set of loop step ids drawn as one card.
277
+ */
278
+ export function layoutAutomation(def, opts = {}) {
279
+ edgeCounter = 0;
280
+ let counter = 0;
281
+ const ctx = { collapsed: opts.collapsed ?? new Set(), next: () => (counter += 1) };
282
+ const trig = def.trigger ?? { type: "manual" };
283
+
284
+ const f = emptyFrag();
285
+ f.nodes.push({
286
+ id: "trigger",
287
+ type: "trigger",
288
+ stepId: null,
289
+ kind: "trigger",
290
+ x: (PITCH - T) / 2,
291
+ y: -T / 2,
292
+ w: T,
293
+ h: T,
294
+ title: triggerTitle(trig.type),
295
+ sub: opts.triggerWords ?? (trig.type === "schedule" ? trig.cron : "Run it when you press Run"),
296
+ tone: "plain",
297
+ num: 0,
298
+ triggerType: trig.type,
299
+ });
300
+ const body = shift(seq(def.steps ?? [], { at: "root" }, ctx), PITCH, 0);
301
+ absorb(f, body);
302
+ const root = { list: { at: "root" }, index: 0 };
303
+ let tails;
304
+ if (body.entry) {
305
+ f.edges.push(edge("trigger", body.entry, { slot: root }, true));
306
+ tails = body.tails;
307
+ } else {
308
+ tails = [{ from: "trigger", slot: root }];
309
+ }
310
+
311
+ // A + bubble at the end of every path that goes on.
312
+ const byId = new Map(f.nodes.map((n) => [n.id, n]));
313
+ tails.forEach((t, i) => {
314
+ const src = byId.get(t.from);
315
+ if (!src) return;
316
+ const id = `end:${i}`;
317
+ f.nodes.push({
318
+ id,
319
+ type: "end",
320
+ stepId: null,
321
+ kind: null,
322
+ x: src.x + src.w + END_GAP,
323
+ y: src.y + src.h / 2 - END / 2,
324
+ w: END,
325
+ h: END,
326
+ title: body.entry ? "Add a step" : "Add the first step",
327
+ sub: "",
328
+ tone: "plain",
329
+ num: 0,
330
+ slot: t.slot,
331
+ });
332
+ f.edges.push(edge(t.from, id, t, false));
333
+ });
334
+
335
+ return { nodes: f.nodes, edges: f.edges, groups: f.groups, bounds: boundsOf(f.nodes, f.groups) };
336
+ }
337
+
338
+ function boundsOf(nodes, groups) {
339
+ let x0 = Infinity;
340
+ let y0 = Infinity;
341
+ let x1 = -Infinity;
342
+ let y1 = -Infinity;
343
+ for (const n of nodes) {
344
+ // A tile's label hangs below it and is wider than the tile.
345
+ const labelled = n.type === "step" || n.type === "trigger";
346
+ const nx0 = labelled ? n.x - (PITCH - T) / 2 : n.x;
347
+ const nx1 = labelled ? n.x + n.w + (PITCH - T) / 2 : n.x + n.w;
348
+ const ny1 = labelled ? n.y + n.h + LABEL_BELOW : n.y + n.h;
349
+ x0 = Math.min(x0, nx0);
350
+ y0 = Math.min(y0, n.y - (labelled ? ABOVE_TILE : 0));
351
+ x1 = Math.max(x1, nx1);
352
+ y1 = Math.max(y1, ny1);
353
+ }
354
+ for (const g of groups) {
355
+ x0 = Math.min(x0, g.x);
356
+ y0 = Math.min(y0, g.y);
357
+ x1 = Math.max(x1, g.x + g.w);
358
+ y1 = Math.max(y1, g.y + g.h);
359
+ }
360
+ if (!Number.isFinite(x0)) return { x: 0, y: 0, w: 0, h: 0 };
361
+ return { x: x0 - MARGIN, y: y0 - MARGIN, w: x1 - x0 + MARGIN * 2, h: y1 - y0 + MARGIN * 2 };
362
+ }
363
+
364
+ /* ---- connectors ---------------------------------------------------------- */
365
+
366
+ /** A connector from one node's right side to another's left side:
367
+ * { d, mid, start, end, at(t) }. `mid` is where the + sits. */
368
+ export function curveBetween(a, b) {
369
+ const x1 = a.x + a.w;
370
+ const y1 = a.y + a.h / 2;
371
+ const x2 = b.x;
372
+ const y2 = b.y + b.h / 2;
373
+ const start = { x: x1, y: y1 };
374
+ const end = { x: x2, y: y2 };
375
+ const mid = { x: (x1 + x2) / 2, y: (y1 + y2) / 2 };
376
+ if (Math.abs(y2 - y1) < 1 || x2 <= x1) {
377
+ return { d: `M ${x1} ${y1} L ${x2} ${y2}`, mid, start, end, at: (t) => ({ x: x1 + (x2 - x1) * t, y: y1 + (y2 - y1) * t }) };
378
+ }
379
+ const dx = Math.max(48, (x2 - x1) * 0.5);
380
+ const c1 = { x: x1 + dx, y: y1 };
381
+ const c2 = { x: x2 - dx, y: y2 };
382
+ const at = (t) => {
383
+ const u = 1 - t;
384
+ return {
385
+ x: u * u * u * x1 + 3 * u * u * t * c1.x + 3 * u * t * t * c2.x + t * t * t * x2,
386
+ y: u * u * u * y1 + 3 * u * u * t * c1.y + 3 * u * t * t * c2.y + t * t * t * y2,
387
+ };
388
+ };
389
+ return { d: `M ${x1} ${y1} C ${c1.x} ${c1.y}, ${c2.x} ${c2.y}, ${x2} ${y2}`, mid, start, end, at };
390
+ }
391
+
392
+ /** The nodes by id, for connectors. */
393
+ export function nodeIndex(layout) {
394
+ return new Map(layout.nodes.map((n) => [n.id, n]));
395
+ }
396
+
397
+ /** The selectable nodes in reading order (left to right, top to bottom):
398
+ * the keyboard's walk through the canvas. */
399
+ export function readingOrder(layout) {
400
+ return layout.nodes
401
+ .filter((n) => n.type === "step" || n.type === "trigger" || n.type === "card")
402
+ .sort((a, b) => a.x - b.x || a.y - b.y);
403
+ }
404
+
405
+ /** What the end of a path is called, for a screen reader. */
406
+ export function slotWords(slot) {
407
+ if (slot.list.at === "root") return slot.index === 0 ? "at the start" : "in the main path";
408
+ if (slot.list.at === "loop") return `inside ${slot.list.step}`;
409
+ return `in the ${slot.list.at === "then" ? "yes" : "no"} path of ${slot.list.step}`;
410
+ }
@@ -0,0 +1,33 @@
1
+ // The AutomationModel block — `makersclaw add automation-model`. The pure
2
+ // part of the automation blocks: the step catalog, the layout, the edits,
3
+ // what a run did, the words. Fixed: the other automation blocks require it.
4
+ export { GLYPH_ICON, GROUP_LABELS, GROUP_ORDER, KINDS, RUNNABLE, TRIGGER_TITLES, humanize, isRunnable, newStep, paletteGroups, stepSub, stepTitle, triggerGlyph, triggerTitle, uniqueStepId } from "./catalog";
5
+ export { Glyph } from "./glyph";
6
+ export { Chip, Dot, PanelSection, RunPicker, SidePanel } from "./parts";
7
+ export { LABEL_W, MARGIN, T, curveBetween, layoutAutomation, nodeIndex, readingOrder, sameSlot, slotWords } from "./graph";
8
+ export {
9
+ addStep,
10
+ allStepIds,
11
+ availableBefore,
12
+ blankAutomation,
13
+ canonicalJson,
14
+ duplicateStep,
15
+ findStep,
16
+ innerCount,
17
+ insertStep,
18
+ keyFromName,
19
+ locate,
20
+ nudgeStep,
21
+ removeStep,
22
+ slotAfter,
23
+ slotAtEnd,
24
+ stepIdForPath,
25
+ updateStep,
26
+ } from "./edit";
27
+ export { latestRows, overlayOf, summarizeSteps } from "./overlay";
28
+ export { ACTIVE, agoWords, clockWords, creditsWords, cronWords, deleteWords, durationWords, formatCreditAmount, healthOf, nodeStateWords, originWords, overviewOf, priceMap, reportLines, runLine, runStatusWords, summaryOf, testWords, triggerTypeWords, triggerWords, wouldWords } from "./words";
29
+ export { WEEKDAYS, cronFromParts, parseTime, partsFromCron, timeText } from "./schedule";
30
+ export { textToValue, valueToText } from "./values";
31
+ export { checkAutomation, flaggedSteps, issuesFor, issuesFromProblems, plainWords } from "./check";
32
+ export { STARTING_POINTS, startsFromPlatform } from "./templates";
33
+ export { CONTROL_DONE, CONTROL_REFUSED, RETRY_FROM, agentDraftOf, changeLines, changeLinesBetween, controlsOf, draftOfStep, fixTag, latestVersionOf, newerVersionWords, retryFromOf } from "./fixes";
@@ -0,0 +1,175 @@
1
+ // What a run did, read off the canvas's layout.
2
+ //
3
+ // A run is a list of step rows, one per attempt per place a step ran; a
4
+ // step inside a loop has a row for every pass (`loop[3]/step`). The
5
+ // canvas draws a definition, not a run, so this file lines the two up:
6
+ // for every node, how it went; for every connector, whether the run went
7
+ // along it.
8
+ //
9
+ // Pure; no React. The rule that matters: the path taken is lit and the
10
+ // paths not taken are dimmed, so a run reads as one route through the
11
+ // flow.
12
+ //
13
+ // A step row: { path, step_id, kind?, attempt, status, started_at,
14
+ // ended_at, credits, error: { code, words } | null, input?, output?,
15
+ // fix?: { by: agent | member, kind, status?, before?, after?, why?, credits?,
16
+ // effect?: read | write | send, undo? } | null }.
17
+ // status: running | done | failed | skipped | waiting | unknown.
18
+ // A TEST run (a dry run) reads real data and changes nothing: a step that
19
+ // stood in for itself carries `simulated: true` (and `output.would` when the
20
+ // viewer may read data), a step that needs what a simulated step would have
21
+ // made carries `unchecked: true`.
22
+
23
+ import { wouldWords } from "./words";
24
+
25
+ const num = (v) => {
26
+ const n = typeof v === "string" ? Number(v) : (v ?? 0);
27
+ return Number.isFinite(n) ? n : 0;
28
+ };
29
+
30
+ /** The strongest state wins: a step that failed on one item failed. */
31
+ const RANK = { failed: 8, unknown: 7, running: 6, waiting: 5, fixed: 4, would: 3, done: 2, skipped: 1, notreached: 0 };
32
+
33
+ /** The latest attempt of every place a step ran. */
34
+ export function latestRows(rows) {
35
+ const byPath = new Map();
36
+ for (const r of rows ?? []) {
37
+ const prior = byPath.get(r.path);
38
+ if (!prior || r.attempt > prior.attempt) byPath.set(r.path, r);
39
+ }
40
+ return [...byPath.values()];
41
+ }
42
+
43
+ // A step the AGENT fixed wears the fixed mark; a person's own edit of the
44
+ // run's data is a step that is done, with the edit noted on it. A step that
45
+ // stood in for itself in a test run is "would": it would have run, it did not.
46
+ const stateOf = (row) => {
47
+ if (row.status === "done" && row.simulated === true) return "would";
48
+ return row.status === "done" && row.fix && row.fix.by !== "member" ? "fixed" : row.status;
49
+ };
50
+
51
+ /** Per step id: { stepId, state, passes, credits, words, would, unchecked,
52
+ * fix, started_at, ended_at, rows }. `would` is what the step would have
53
+ * done, in words, when its state is "would" (else null); `unchecked` is true
54
+ * when a pass of it could not be checked in a test run. */
55
+ export function summarizeSteps(rows) {
56
+ const out = new Map();
57
+ for (const row of latestRows(rows)) {
58
+ const state = stateOf(row);
59
+ const prior = out.get(row.step_id);
60
+ const words = row.error && typeof row.error.words === "string" ? row.error.words : null;
61
+ if (!prior) {
62
+ out.set(row.step_id, {
63
+ stepId: row.step_id,
64
+ state,
65
+ passes: 1,
66
+ credits: num(row.credits),
67
+ words: state === "failed" || state === "unknown" ? words : null,
68
+ would: state === "would" ? wouldWords(row) : null,
69
+ unchecked: row.unchecked === true,
70
+ fix: row.fix ?? null,
71
+ started_at: row.started_at ?? null,
72
+ ended_at: row.ended_at ?? null,
73
+ rows: [row],
74
+ });
75
+ continue;
76
+ }
77
+ prior.passes += 1;
78
+ prior.credits += num(row.credits);
79
+ prior.rows.push(row);
80
+ if (row.unchecked === true) prior.unchecked = true;
81
+ if (RANK[state] > RANK[prior.state]) {
82
+ prior.state = state;
83
+ prior.words = state === "failed" || state === "unknown" ? words : prior.words;
84
+ }
85
+ if (state === "would" && prior.state === "would" && !prior.would) prior.would = wouldWords(row);
86
+ if (row.fix && !prior.fix) prior.fix = row.fix;
87
+ if (row.started_at && (!prior.started_at || row.started_at < prior.started_at)) prior.started_at = row.started_at;
88
+ if (row.ended_at && (!prior.ended_at || row.ended_at > prior.ended_at)) prior.ended_at = row.ended_at;
89
+ }
90
+ return out;
91
+ }
92
+
93
+ /** Which way a condition went: its own output when the member may read it,
94
+ * else whichever branch the run went into. */
95
+ function branchTaken(cond, summary, layout) {
96
+ const own = summary.get(cond.id);
97
+ const out = own?.rows[0]?.output;
98
+ if (out && (out.taken === "then" || out.taken === "else")) return out.taken;
99
+ const target = (key) => {
100
+ const to = layout.edges.find((e) => e.from === cond.id && e.branch === key)?.to;
101
+ return to ? layout.nodes.find((n) => n.id === to) : undefined;
102
+ };
103
+ const isBody = (n) => !!n && (n.type === "step" || n.type === "card" || n.type === "port");
104
+ const entered = (n) => isBody(n) && (n.type === "port" ? summary.has(n.stepId ?? "") : summary.has(n.id));
105
+ const [yes, no] = [target("then"), target("else")];
106
+ if (entered(yes)) return "then";
107
+ if (entered(no)) return "else";
108
+ // A branch with nothing in it leaves no trace: if the condition finished
109
+ // and the other branch was never entered, the run went down the empty one.
110
+ if (own && (own.state === "done" || own.state === "fixed")) {
111
+ if (isBody(yes) && !isBody(no)) return "else";
112
+ if (isBody(no) && !isBody(yes)) return "then";
113
+ }
114
+ return null;
115
+ }
116
+
117
+ /**
118
+ * overlayOf(layout, rows, runStatus)
119
+ * → { summary, nodes, edges, taken }
120
+ * `nodes` by node id: done | would | running | failed | fixed | waiting | skipped |
121
+ * unknown | notreached. `edges` by connector id: taken | running | dim.
122
+ * `taken` by condition id: "then" | "else".
123
+ */
124
+ export function overlayOf(layout, rows, runStatus) {
125
+ const summary = summarizeSteps(rows);
126
+ const nodes = new Map();
127
+ const edges = new Map();
128
+ const taken = new Map();
129
+ const reached = new Set(["trigger"]);
130
+
131
+ nodes.set("trigger", (rows ?? []).length || runStatus ? "done" : "notreached");
132
+ // A loop's box wears its loop's state.
133
+ for (const g of layout.groups) nodes.set(g.id, summary.get(g.stepId)?.state ?? "notreached");
134
+ for (const n of layout.nodes) {
135
+ if (n.type === "step" || n.type === "card") {
136
+ const s = summary.get(n.id);
137
+ nodes.set(n.id, s ? s.state : "notreached");
138
+ if (s) reached.add(n.id);
139
+ }
140
+ // A loop's doors: in when it started, out once it came through.
141
+ if (n.type === "port" && n.stepId) {
142
+ const s = summary.get(n.stepId);
143
+ const isOut = n.id.endsWith(":out");
144
+ if (s && (!isOut || s.state === "done" || s.state === "fixed")) reached.add(n.id);
145
+ }
146
+ }
147
+ for (const n of layout.nodes) {
148
+ if (n.type === "step" && n.kind === "condition") {
149
+ const b = branchTaken(n, summary, layout);
150
+ if (b) taken.set(n.id, b);
151
+ }
152
+ }
153
+
154
+ const byId = new Map(layout.nodes.map((n) => [n.id, n]));
155
+ const decide = (e) => {
156
+ if (!reached.has(e.from)) return "dim";
157
+ if (e.branch && taken.get(e.from) !== e.branch) return "dim";
158
+ const to = byId.get(e.to);
159
+ if (!to || to.type === "end") return "dim";
160
+ if (to.type === "join") return "taken";
161
+ if (!reached.has(e.to)) return "dim";
162
+ return summary.get(e.to)?.state === "running" ? "running" : "taken";
163
+ };
164
+ // A join is reached once a connector into it was taken; a few passes
165
+ // settle the one level of joins a condition makes.
166
+ for (let round = 0; round < 3; round += 1) {
167
+ for (const e of layout.edges) {
168
+ const state = decide(e);
169
+ edges.set(e.id, state);
170
+ const to = byId.get(e.to);
171
+ if (to?.type === "join" && state === "taken") reached.add(to.id);
172
+ }
173
+ }
174
+ return { summary, nodes, edges, taken };
175
+ }