makersclaw 0.7.0 → 0.8.1

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 (419) hide show
  1. package/README.md +17 -4
  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 +4 -4
  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 +5 -5
  26. package/r/chat-pane.json +84 -0
  27. package/r/chat.json +3 -3
  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 +18 -6
  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 +3 -3
  46. package/r/flow-editor.json +79 -0
  47. package/r/footer.json +3 -3
  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 +4 -4
  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 +4 -4
  60. package/r/pace-bar.json +69 -0
  61. package/r/page-builder.json +3 -3
  62. package/r/payment-methods.json +2 -2
  63. package/r/pdf-document.json +2 -2
  64. package/r/pdf-viewer.json +3 -3
  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 +4089 -1510
  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 +3 -3
  82. package/r/signature-pad.json +2 -2
  83. package/r/sketch-canvas.json +3 -3
  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 +4 -4
  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 +225 -0
  143. package/registry/blocks/agent-pane/agent-pane.jsx +244 -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/annotate/README.md +14 -11
  159. package/registry/blocks/approval/README.md +145 -0
  160. package/registry/blocks/approval/approval.jsx +163 -0
  161. package/registry/blocks/approval/block.json +31 -0
  162. package/registry/blocks/approval/demo.jsx +121 -0
  163. package/registry/blocks/approval/index.js +3 -0
  164. package/registry/blocks/ask-bar/README.md +105 -0
  165. package/registry/blocks/ask-bar/ask-bar.jsx +166 -0
  166. package/registry/blocks/ask-bar/block.json +26 -0
  167. package/registry/blocks/ask-bar/demo.jsx +78 -0
  168. package/registry/blocks/ask-bar/index.js +3 -0
  169. package/registry/blocks/automation-editor/README.md +291 -0
  170. package/registry/blocks/automation-editor/automation-editor.jsx +656 -0
  171. package/registry/blocks/automation-editor/block.json +39 -0
  172. package/registry/blocks/automation-editor/demo.jsx +284 -0
  173. package/registry/blocks/automation-editor/index.js +4 -0
  174. package/registry/blocks/automation-editor/run-inputs.jsx +82 -0
  175. package/registry/blocks/automation-list/README.md +129 -0
  176. package/registry/blocks/automation-list/automation-list.jsx +476 -0
  177. package/registry/blocks/automation-list/block.json +35 -0
  178. package/registry/blocks/automation-list/demo.jsx +67 -0
  179. package/registry/blocks/automation-list/index.js +3 -0
  180. package/registry/blocks/automation-model/README.md +109 -0
  181. package/registry/blocks/automation-model/block.json +135 -0
  182. package/registry/blocks/automation-model/catalog.js +256 -0
  183. package/registry/blocks/automation-model/check.js +161 -0
  184. package/registry/blocks/automation-model/demo.jsx +42 -0
  185. package/registry/blocks/automation-model/edit.js +262 -0
  186. package/registry/blocks/automation-model/fixes.js +287 -0
  187. package/registry/blocks/automation-model/glyph.jsx +13 -0
  188. package/registry/blocks/automation-model/graph.js +410 -0
  189. package/registry/blocks/automation-model/index.js +33 -0
  190. package/registry/blocks/automation-model/overlay.js +175 -0
  191. package/registry/blocks/automation-model/parts.jsx +94 -0
  192. package/registry/blocks/automation-model/schedule.js +53 -0
  193. package/registry/blocks/automation-model/templates.js +128 -0
  194. package/registry/blocks/automation-model/values.js +29 -0
  195. package/registry/blocks/automation-model/words.js +439 -0
  196. package/registry/blocks/automations-screen/README.md +207 -0
  197. package/registry/blocks/automations-screen/automations-screen.jsx +452 -0
  198. package/registry/blocks/automations-screen/block.json +47 -0
  199. package/registry/blocks/automations-screen/demo.jsx +364 -0
  200. package/registry/blocks/automations-screen/index.js +4 -0
  201. package/registry/blocks/automations-screen/screen-model.js +129 -0
  202. package/registry/blocks/chart/cartesian.jsx +1 -1
  203. package/registry/blocks/chart/core.jsx +33 -23
  204. package/registry/blocks/chart/pie.jsx +1 -1
  205. package/registry/blocks/chat/README.md +4 -1
  206. package/registry/blocks/chat/demo.jsx +2 -2
  207. package/registry/blocks/chat-pane/README.md +143 -0
  208. package/registry/blocks/chat-pane/block.json +48 -0
  209. package/registry/blocks/chat-pane/chat-attach.js +166 -0
  210. package/registry/blocks/chat-pane/chat-composer.jsx +195 -0
  211. package/registry/blocks/chat-pane/chat-context.js +17 -0
  212. package/registry/blocks/chat-pane/chat-model.js +43 -0
  213. package/registry/blocks/chat-pane/chat-pane.jsx +398 -0
  214. package/registry/blocks/chat-pane/chats-list.jsx +52 -0
  215. package/registry/blocks/chat-pane/demo.jsx +103 -0
  216. package/registry/blocks/chat-pane/index.js +9 -0
  217. package/registry/blocks/connect-card/README.md +99 -0
  218. package/registry/blocks/connect-card/block.json +10 -0
  219. package/registry/blocks/connect-card/connect-card.jsx +103 -0
  220. package/registry/blocks/connect-card/demo.jsx +49 -0
  221. package/registry/blocks/connect-card/index.js +3 -0
  222. package/registry/blocks/cost/README.md +115 -0
  223. package/registry/blocks/cost/block.json +10 -0
  224. package/registry/blocks/cost/cost.jsx +176 -0
  225. package/registry/blocks/cost/demo.jsx +66 -0
  226. package/registry/blocks/cost/index.js +3 -0
  227. package/registry/blocks/data-picker/README.md +81 -0
  228. package/registry/blocks/data-picker/block.json +38 -0
  229. package/registry/blocks/data-picker/data-picker.jsx +210 -0
  230. package/registry/blocks/data-picker/demo.jsx +34 -0
  231. package/registry/blocks/data-picker/fields.js +89 -0
  232. package/registry/blocks/data-picker/index.js +4 -0
  233. package/registry/blocks/data-table/demo.jsx +1 -1
  234. package/registry/blocks/first-run/README.md +118 -0
  235. package/registry/blocks/first-run/block.json +11 -0
  236. package/registry/blocks/first-run/demo.jsx +88 -0
  237. package/registry/blocks/first-run/first-run-model.js +51 -0
  238. package/registry/blocks/first-run/first-run.jsx +156 -0
  239. package/registry/blocks/first-run/index.js +5 -0
  240. package/registry/blocks/first-run/probe-rules.js +26 -0
  241. package/registry/blocks/fix-note/README.md +79 -0
  242. package/registry/blocks/fix-note/block.json +35 -0
  243. package/registry/blocks/fix-note/demo.jsx +30 -0
  244. package/registry/blocks/fix-note/fix-note.jsx +235 -0
  245. package/registry/blocks/fix-note/index.js +3 -0
  246. package/registry/blocks/flow-canvas/README.md +15 -8
  247. package/registry/blocks/flow-editor/README.md +108 -0
  248. package/registry/blocks/flow-editor/block.json +44 -0
  249. package/registry/blocks/flow-editor/demo.jsx +115 -0
  250. package/registry/blocks/flow-editor/flow-canvas.jsx +568 -0
  251. package/registry/blocks/flow-editor/flow-editor.jsx +154 -0
  252. package/registry/blocks/flow-editor/index.js +6 -0
  253. package/registry/blocks/flow-editor/minimap.jsx +78 -0
  254. package/registry/blocks/flow-editor/outline.jsx +134 -0
  255. package/registry/blocks/footer/README.md +3 -2
  256. package/registry/blocks/library-shelf/README.md +117 -0
  257. package/registry/blocks/library-shelf/block.json +28 -0
  258. package/registry/blocks/library-shelf/demo.jsx +68 -0
  259. package/registry/blocks/library-shelf/index.js +3 -0
  260. package/registry/blocks/library-shelf/library-shelf.jsx +211 -0
  261. package/registry/blocks/library-shelf/probe-rules.js +15 -0
  262. package/registry/blocks/margin-notes/README.md +222 -0
  263. package/registry/blocks/margin-notes/block.json +10 -0
  264. package/registry/blocks/margin-notes/demo.jsx +144 -0
  265. package/registry/blocks/margin-notes/index.js +20 -0
  266. package/registry/blocks/margin-notes/margin-model.js +224 -0
  267. package/registry/blocks/margin-notes/margin-notes.jsx +465 -0
  268. package/registry/blocks/mind-map/README.md +4 -2
  269. package/registry/blocks/needs-you/README.md +177 -0
  270. package/registry/blocks/needs-you/block.json +34 -0
  271. package/registry/blocks/needs-you/demo.jsx +143 -0
  272. package/registry/blocks/needs-you/index.js +3 -0
  273. package/registry/blocks/needs-you/needs-you.jsx +441 -0
  274. package/registry/blocks/org-chart/README.md +4 -2
  275. package/registry/blocks/pace-bar/README.md +230 -0
  276. package/registry/blocks/pace-bar/block.json +10 -0
  277. package/registry/blocks/pace-bar/demo.jsx +255 -0
  278. package/registry/blocks/pace-bar/index.js +22 -0
  279. package/registry/blocks/pace-bar/pace-bar.jsx +461 -0
  280. package/registry/blocks/pace-bar/pace-model.js +288 -0
  281. package/registry/blocks/page-builder/README.md +1 -1
  282. package/registry/blocks/page-builder/demo.jsx +3 -3
  283. package/registry/blocks/pdf-viewer/README.md +4 -1
  284. package/registry/blocks/record-grid/README.md +100 -0
  285. package/registry/blocks/record-grid/block.json +28 -0
  286. package/registry/blocks/record-grid/demo.jsx +43 -0
  287. package/registry/blocks/record-grid/index.js +3 -0
  288. package/registry/blocks/record-grid/record-grid.jsx +251 -0
  289. package/registry/blocks/run-history/README.md +138 -0
  290. package/registry/blocks/run-history/block.json +10 -0
  291. package/registry/blocks/run-history/demo.jsx +74 -0
  292. package/registry/blocks/run-history/index.js +3 -0
  293. package/registry/blocks/run-history/run-history.jsx +218 -0
  294. package/registry/blocks/run-view/README.md +174 -0
  295. package/registry/blocks/run-view/block.json +50 -0
  296. package/registry/blocks/run-view/demo.jsx +286 -0
  297. package/registry/blocks/run-view/index.js +5 -0
  298. package/registry/blocks/run-view/run-controls.jsx +266 -0
  299. package/registry/blocks/run-view/run-view.jsx +236 -0
  300. package/registry/blocks/run-view/runs-list.jsx +99 -0
  301. package/registry/blocks/schedule-card/README.md +121 -0
  302. package/registry/blocks/schedule-card/block.json +10 -0
  303. package/registry/blocks/schedule-card/demo.jsx +82 -0
  304. package/registry/blocks/schedule-card/index.js +3 -0
  305. package/registry/blocks/schedule-card/schedule-card.jsx +136 -0
  306. package/registry/blocks/schedule-engine/README.md +137 -0
  307. package/registry/blocks/schedule-engine/block.json +10 -0
  308. package/registry/blocks/schedule-engine/demo.jsx +82 -0
  309. package/registry/blocks/schedule-engine/engine.js +769 -0
  310. package/registry/blocks/schedule-engine/index.js +9 -0
  311. package/registry/blocks/schedule-engine/ops.js +71 -0
  312. package/registry/blocks/schedule-engine/place.js +294 -0
  313. package/registry/blocks/schedule-engine/tree.js +79 -0
  314. package/registry/blocks/schedule-engine/waits.js +80 -0
  315. package/registry/blocks/schedule-gantt/README.md +159 -0
  316. package/registry/blocks/schedule-gantt/block.json +10 -0
  317. package/registry/blocks/schedule-gantt/demo.jsx +223 -0
  318. package/registry/blocks/schedule-gantt/gantt-model.js +219 -0
  319. package/registry/blocks/schedule-gantt/geometry.js +176 -0
  320. package/registry/blocks/schedule-gantt/index.js +26 -0
  321. package/registry/blocks/schedule-gantt/schedule-gantt.jsx +882 -0
  322. package/registry/blocks/schedule-gantt/sheet.jsx +372 -0
  323. package/registry/blocks/schedule-gantt/track.jsx +190 -0
  324. package/registry/blocks/schedule-ruler/README.md +148 -0
  325. package/registry/blocks/schedule-ruler/block.json +10 -0
  326. package/registry/blocks/schedule-ruler/demo.jsx +181 -0
  327. package/registry/blocks/schedule-ruler/index.js +21 -0
  328. package/registry/blocks/schedule-ruler/ruler-model.js +239 -0
  329. package/registry/blocks/schedule-ruler/schedule-ruler.jsx +548 -0
  330. package/registry/blocks/sidebar/README.md +23 -13
  331. package/registry/blocks/sketch-canvas/README.md +15 -9
  332. package/registry/blocks/source-receipt/README.md +97 -0
  333. package/registry/blocks/source-receipt/block.json +30 -0
  334. package/registry/blocks/source-receipt/demo.jsx +71 -0
  335. package/registry/blocks/source-receipt/index.js +3 -0
  336. package/registry/blocks/source-receipt/source-receipt.jsx +107 -0
  337. package/registry/blocks/spreadsheet/spreadsheet.jsx +15 -1
  338. package/registry/blocks/step-picker/README.md +78 -0
  339. package/registry/blocks/step-picker/block.json +31 -0
  340. package/registry/blocks/step-picker/demo.jsx +23 -0
  341. package/registry/blocks/step-picker/index.js +3 -0
  342. package/registry/blocks/step-picker/step-picker.jsx +144 -0
  343. package/registry/blocks/step-settings/README.md +100 -0
  344. package/registry/blocks/step-settings/block.json +44 -0
  345. package/registry/blocks/step-settings/demo.jsx +93 -0
  346. package/registry/blocks/step-settings/fields.jsx +58 -0
  347. package/registry/blocks/step-settings/flow-settings.jsx +115 -0
  348. package/registry/blocks/step-settings/index.js +5 -0
  349. package/registry/blocks/step-settings/step-settings.jsx +290 -0
  350. package/registry/blocks/suggestion/README.md +171 -0
  351. package/registry/blocks/suggestion/block.json +40 -0
  352. package/registry/blocks/suggestion/demo.jsx +91 -0
  353. package/registry/blocks/suggestion/index.js +3 -0
  354. package/registry/blocks/suggestion/suggestion.jsx +436 -0
  355. package/registry/blocks/sum-bar/README.md +122 -0
  356. package/registry/blocks/sum-bar/block.json +10 -0
  357. package/registry/blocks/sum-bar/demo.jsx +110 -0
  358. package/registry/blocks/sum-bar/index.js +5 -0
  359. package/registry/blocks/sum-bar/sum-bar.jsx +209 -0
  360. package/registry/blocks/sum-bar/sum-model.js +126 -0
  361. package/registry/blocks/tier-map/README.md +217 -0
  362. package/registry/blocks/tier-map/block.json +10 -0
  363. package/registry/blocks/tier-map/demo.jsx +222 -0
  364. package/registry/blocks/tier-map/index.js +24 -0
  365. package/registry/blocks/tier-map/tier-map.jsx +574 -0
  366. package/registry/blocks/tier-map/tier-model.js +318 -0
  367. package/registry/blocks/time-grid/README.md +305 -0
  368. package/registry/blocks/time-grid/block.json +10 -0
  369. package/registry/blocks/time-grid/demo.jsx +279 -0
  370. package/registry/blocks/time-grid/grid-model.js +322 -0
  371. package/registry/blocks/time-grid/index.js +25 -0
  372. package/registry/blocks/time-grid/time-grid.jsx +1325 -0
  373. package/registry/blocks/time-strip/README.md +141 -0
  374. package/registry/blocks/time-strip/block.json +10 -0
  375. package/registry/blocks/time-strip/demo.jsx +129 -0
  376. package/registry/blocks/time-strip/index.js +19 -0
  377. package/registry/blocks/time-strip/strip-model.js +178 -0
  378. package/registry/blocks/time-strip/time-strip.jsx +260 -0
  379. package/registry/blocks/top-bar/README.md +149 -0
  380. package/registry/blocks/top-bar/block.json +35 -0
  381. package/registry/blocks/top-bar/demo.jsx +78 -0
  382. package/registry/blocks/top-bar/index.js +5 -0
  383. package/registry/blocks/top-bar/probe-rules.js +74 -0
  384. package/registry/blocks/top-bar/top-bar-model.js +152 -0
  385. package/registry/blocks/top-bar/top-bar.jsx +244 -0
  386. package/registry/blocks/trigger-picker/README.md +98 -0
  387. package/registry/blocks/trigger-picker/block.json +38 -0
  388. package/registry/blocks/trigger-picker/demo.jsx +59 -0
  389. package/registry/blocks/trigger-picker/index.js +3 -0
  390. package/registry/blocks/trigger-picker/trigger-picker.jsx +374 -0
  391. package/registry/blocks/whiteboard/README.md +20 -14
  392. package/registry/blocks/workflow-view/README.md +123 -0
  393. package/registry/blocks/workflow-view/block.json +10 -0
  394. package/registry/blocks/workflow-view/demo.jsx +90 -0
  395. package/registry/blocks/workflow-view/index.js +3 -0
  396. package/registry/blocks/workflow-view/workflow-view.jsx +203 -0
  397. package/src/cli.mjs +2 -2
  398. package/src/install.mjs +100 -22
  399. package/src/registry.mjs +37 -3
  400. package/templates/next/browser/lib/data.js +6 -1
  401. package/templates/next/files/README.md +909 -26
  402. package/templates/next/files/app/shell.jsx +54 -37
  403. package/templates/next/files/check/automation-format.ts +2103 -0
  404. package/templates/next/files/check/automation-package.ts +142 -0
  405. package/templates/next/files/check/run.mjs +1043 -12
  406. package/templates/next/files/components/ui/field.jsx +17 -4
  407. package/templates/next/files/components/ui/icon.jsx +13 -0
  408. package/templates/next/files/components/ui/index.js +3 -1
  409. package/templates/next/files/components/ui/layout.jsx +382 -0
  410. package/templates/next/files/components/ui/notice.jsx +70 -0
  411. package/templates/next/files/components/ui/page.jsx +124 -0
  412. package/templates/next/files/components/ui/stat.jsx +22 -7
  413. package/templates/next/files/components/ui/toast.jsx +6 -3
  414. package/templates/next/files/lib/automations.js +660 -0
  415. package/templates/next/files/lib/claw.js +244 -5
  416. package/templates/next/files/lib/door.js +92 -0
  417. package/templates/next/files/lib/hooks.js +1694 -6
  418. package/templates/next/files/lib/platform.js +611 -14
  419. package/templates/next/template.json +22 -3
@@ -0,0 +1,439 @@
1
+ // The automation blocks' words: a schedule, a time, a cost, a health, a
2
+ // run's outcome, each in the plain way a person reads them.
3
+ //
4
+ // Pure; the clock and the zone come in as arguments so a test can read
5
+ // them. A time is shown in the automation's own zone: a 07:00 schedule
6
+ // says 07:00 whoever is looking (an app once said "07:00" for a wake that
7
+ // ran at 06:00 UTC; this file is why it cannot again).
8
+
9
+ /* ---- a schedule in words (five-field cron) ------------------------------- */
10
+
11
+ const andList = (names) => {
12
+ const unique = [...new Set(names)];
13
+ if (unique.length <= 1) return unique[0] ?? "";
14
+ return `${unique.slice(0, -1).join(", ")} and ${unique[unique.length - 1]}`;
15
+ };
16
+
17
+ const DAY_NAMES = ["Sundays", "Mondays", "Tuesdays", "Wednesdays", "Thursdays", "Fridays", "Saturdays"];
18
+ const MONTH_NAMES = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
19
+ const pad2 = (n) => String(n).padStart(2, "0");
20
+ const clock = (h, m) => `${pad2(h)}:${pad2(m)}`;
21
+ const capital = (s) => (s ? s[0].toUpperCase() + s.slice(1) : s);
22
+
23
+ function ordinal(n) {
24
+ const last2 = n % 100;
25
+ if (last2 >= 11 && last2 <= 13) return `${n}th`;
26
+ return `${n}${["th", "st", "nd", "rd"][n % 10] ?? "th"}`;
27
+ }
28
+
29
+ /** A field's numbers: a literal, a list, ranges inside the list, or a `*` /
30
+ * `a-b` step. Sorted, each once; null when a piece is anything else or out
31
+ * of [min, max]. */
32
+ function fieldValues(field, min, max) {
33
+ const out = new Set();
34
+ for (const piece of field.split(",")) {
35
+ const m = /^(?:(\*)|(\d{1,2})(?:-(\d{1,2}))?)(?:\/(\d{1,2}))?$/.exec(piece);
36
+ if (!m) return null;
37
+ const step = m[4] ? Number(m[4]) : 1;
38
+ if (step < 1) return null;
39
+ const from = m[1] ? min : Number(m[2]);
40
+ const to = m[1] ? max : m[3] !== undefined ? Number(m[3]) : m[4] ? max : from;
41
+ if (from < min || to > max || from > to) return null;
42
+ for (let v = from; v <= to; v += step) out.add(v);
43
+ }
44
+ return [...out].sort((a, b) => a - b);
45
+ }
46
+
47
+ function daysPhrase(dow) {
48
+ if (dow === "*") return "";
49
+ const values = fieldValues(dow, 0, 7);
50
+ if (!values) return null;
51
+ const days = [...new Set(values.map((d) => d % 7))];
52
+ const key = [...days].sort((a, b) => a - b).join(",");
53
+ if (days.length === 7) return "";
54
+ if (key === "1,2,3,4,5") return "weekdays";
55
+ if (key === "0,6") return "weekends";
56
+ const mondayFirst = days.sort((a, b) => ((a + 6) % 7) - ((b + 6) % 7));
57
+ return andList(mondayFirst.map((d) => DAY_NAMES[d]));
58
+ }
59
+
60
+ /** The cron as a sentence ("Weekdays at 07:00", "Every 15 minutes"), or
61
+ * null when it is not one of the shapes read here. A cron that names both
62
+ * days of the month and days of the week is null: cron runs it on EITHER,
63
+ * which no short sentence says honestly. */
64
+ export function cronWords(cron) {
65
+ const fields = String(cron ?? "").trim().split(/\s+/);
66
+ if (fields.length !== 5) return null;
67
+ const [m, h, dom, mon, dow] = fields;
68
+ const minute = /^\d{1,2}$/.test(m) && Number(m) < 60 ? Number(m) : null;
69
+ const hours = /^\d{1,2}(,\d{1,2})*$/.test(h) ? fieldValues(h, 0, 23) : null;
70
+ const times = minute !== null && hours ? andList(hours.map((x) => clock(x, minute))) : null;
71
+
72
+ if (dom !== "*" || mon !== "*") {
73
+ if (dow !== "*" || !times) return null;
74
+ const days = dom === "*" ? null : fieldValues(dom, 1, 31);
75
+ const months = mon === "*" ? null : fieldValues(mon, 1, 12);
76
+ if ((dom !== "*" && !days) || (mon !== "*" && !months)) return null;
77
+ const monthWords = months ? andList(months.map((x) => MONTH_NAMES[x - 1])) : null;
78
+ if (!days) return `At ${times} every day in ${monthWords}`;
79
+ return `At ${times} on the ${andList(days.map(ordinal))} of ${monthWords ?? "each month"}`;
80
+ }
81
+
82
+ const days = daysPhrase(dow);
83
+ if (days === null) return null;
84
+ const withDays = (body) => (days ? `${capital(days)}, ${body}` : capital(body));
85
+ const everyMin = /^\*\/(\d{1,2})$/.exec(m);
86
+ if (everyMin && h === "*") {
87
+ const n = Number(everyMin[1]);
88
+ if (n < 1 || n > 59) return null;
89
+ return withDays(n === 1 ? "every minute" : `every ${n} minutes`);
90
+ }
91
+ if (m === "*" && h === "*") return withDays("every minute");
92
+ if (minute === null) return null;
93
+ const past = minute ? ` at :${pad2(minute)}` : "";
94
+ if (h === "*") return withDays(`every hour${past}`);
95
+ const everyH = /^\*\/(\d{1,2})$/.exec(h);
96
+ if (everyH) {
97
+ const n = Number(everyH[1]);
98
+ if (n < 1 || n > 23) return null;
99
+ return withDays(n === 1 ? `every hour${past}` : `every ${n} hours${past}`);
100
+ }
101
+ const range = /^(\d{1,2})-(\d{1,2})(?:\/(\d{1,2}))?$/.exec(h);
102
+ if (range) {
103
+ const [a, b] = [Number(range[1]), Number(range[2])];
104
+ const step = range[3] ? Number(range[3]) : 1;
105
+ if (a > 23 || b > 23 || a >= b || step < 1 || step > 23) return null;
106
+ const every = step === 1 ? "every hour" : `every ${step} hours`;
107
+ return withDays(`${every}, ${clock(a, minute)}–${clock(b, minute)}`);
108
+ }
109
+ if (!times) return null;
110
+ return days ? `${capital(days)} at ${times}` : `Every day at ${times}`;
111
+ }
112
+
113
+ /* ---- triggers ------------------------------------------------------------ */
114
+
115
+ /** A name the platform writes with underscores or dots, as a person says it
116
+ * ("add_people" is "add people"). */
117
+ const plain = (name) => String(name ?? "").replace(/[._-]+/g, " ").replace(/\s+/g, " ").trim().toLowerCase();
118
+
119
+ /** The kinds a record trigger names, as a person says them: "a contact",
120
+ * "a contact or a deal", "a record" when it names none. */
121
+ function kindsWords(kinds) {
122
+ const names = (Array.isArray(kinds) ? kinds : []).map(plain).filter(Boolean);
123
+ if (names.length === 0) return "a record";
124
+ return names.map((n) => `a ${n}`).join(" or ");
125
+ }
126
+
127
+ /** "Weekdays at 07:00" / "By hand" / "When “rows.imported” is sent". The zone
128
+ * is named only when it is not the team's own. */
129
+ export function triggerWords(trigger) {
130
+ if (!trigger || trigger.type === "manual") return "By hand";
131
+ switch (trigger.type) {
132
+ case "schedule": {
133
+ if (typeof trigger.cron !== "string") return "By hand";
134
+ const said = cronWords(trigger.cron) ?? trigger.cron;
135
+ const zone = typeof trigger.tz === "string" && trigger.tz !== "team" ? trigger.tz : null;
136
+ return zone ? `${said} (${zone})` : said;
137
+ }
138
+ case "event":
139
+ return trigger.topic ? `When “${trigger.topic}” is sent${trigger.app ? ` by ${trigger.app}` : ""}` : "When an event is sent";
140
+ case "action":
141
+ return trigger.action ? `When ${plain(trigger.action)} finishes${trigger.app ? ` in ${trigger.app}` : ""}` : "When an app action finishes";
142
+ case "record": {
143
+ const ops = Array.isArray(trigger.ops) && trigger.ops.length === 1 ? (trigger.ops[0] === "create" ? "added" : "changed") : "added or changed";
144
+ return `When ${kindsWords(trigger.kinds)} is ${ops}${trigger.app ? ` in ${trigger.app}` : ""}`;
145
+ }
146
+ case "webhook":
147
+ return "When its web address is called";
148
+ case "automation": {
149
+ const when = trigger.when === "failed" ? "fails" : trigger.when === "any" ? "ends" : "finishes";
150
+ return trigger.key ? `When “${trigger.key}” ${when}` : "When another automation finishes";
151
+ }
152
+ default:
153
+ return "By hand";
154
+ }
155
+ }
156
+
157
+ /** What a delete asks first, in plain words: what it does to this one. */
158
+ export function deleteWords(name, status) {
159
+ return `Deletes "${name}". Its runs stay in history.${status === "on" ? " It is switched on, so deleting also switches it off." : ""}`;
160
+ }
161
+
162
+ /** A trigger type, as a person says it. */
163
+ export function triggerTypeWords(type) {
164
+ switch (type) {
165
+ case "schedule":
166
+ return "On schedule";
167
+ case "manual":
168
+ return "By hand";
169
+ case "event":
170
+ return "By an event";
171
+ case "action":
172
+ return "By an app action";
173
+ case "record":
174
+ return "By a record";
175
+ case "webhook":
176
+ return "By a web address";
177
+ case "automation":
178
+ return "By another automation";
179
+ default:
180
+ return String(type ?? "");
181
+ }
182
+ }
183
+
184
+ /* ---- times --------------------------------------------------------------- */
185
+
186
+ function zoneOr(tz) {
187
+ try {
188
+ new Intl.DateTimeFormat("en", { timeZone: tz });
189
+ return tz;
190
+ } catch {
191
+ return "UTC";
192
+ }
193
+ }
194
+
195
+ /** "Tue 07:00" for the next run, in the automation's zone; "Today 07:00"
196
+ * and "Tomorrow 07:00" when it is that close. */
197
+ export function clockWords(iso, tz, now = new Date()) {
198
+ if (!iso) return null;
199
+ const at = new Date(iso);
200
+ if (Number.isNaN(at.getTime())) return null;
201
+ const zone = zoneOr(tz);
202
+ const dayKey = (d) => new Intl.DateTimeFormat("en-CA", { timeZone: zone, year: "numeric", month: "2-digit", day: "2-digit" }).format(d);
203
+ const time = new Intl.DateTimeFormat("en-GB", { timeZone: zone, hour: "2-digit", minute: "2-digit", hour12: false }).format(at);
204
+ const today = dayKey(now);
205
+ const that = dayKey(at);
206
+ if (that === today) return `Today ${time}`;
207
+ if (that === dayKey(new Date(now.getTime() + 86_400_000))) return `Tomorrow ${time}`;
208
+ const weekday = new Intl.DateTimeFormat("en-GB", { timeZone: zone, weekday: "short" }).format(at);
209
+ const within = at.getTime() - now.getTime() < 6 * 86_400_000 && at.getTime() > now.getTime();
210
+ if (within) return `${weekday} ${time}`;
211
+ const date = new Intl.DateTimeFormat("en-GB", { timeZone: zone, day: "numeric", month: "short" }).format(at);
212
+ return `${date} ${time}`;
213
+ }
214
+
215
+ /** "3m ago", "yesterday", "5d ago". */
216
+ export function agoWords(iso, now = new Date()) {
217
+ if (!iso) return null;
218
+ const t = new Date(iso).getTime();
219
+ if (Number.isNaN(t)) return null;
220
+ const s = (now.getTime() - t) / 1000;
221
+ if (s < 60) return "just now";
222
+ if (s < 3600) return `${Math.floor(s / 60)}m ago`;
223
+ if (s < 86_400) return `${Math.floor(s / 3600)}h ago`;
224
+ if (s < 172_800) return "yesterday";
225
+ return `${Math.floor(s / 86_400)}d ago`;
226
+ }
227
+
228
+ /** "42 s", "3 min 10 s". */
229
+ export function durationWords(from, to) {
230
+ if (!from || !to) return null;
231
+ const ms = new Date(to).getTime() - new Date(from).getTime();
232
+ if (!Number.isFinite(ms) || ms < 0) return null;
233
+ const s = Math.round(ms / 1000);
234
+ if (s < 1) return "under a second";
235
+ if (s < 60) return `${s} s`;
236
+ const m = Math.floor(s / 60);
237
+ if (m < 60) return `${m} min${s % 60 ? ` ${s % 60} s` : ""}`;
238
+ return `${Math.floor(m / 60)} h ${m % 60} min`;
239
+ }
240
+
241
+ /* ---- money --------------------------------------------------------------- */
242
+
243
+ /** One decimal only when there is one: 3 is "3", 2.4 is "2.4", 29000 is
244
+ * "29,000". */
245
+ export const formatCreditAmount = (credits) => Number(credits).toLocaleString("en-US", { minimumFractionDigits: 0, maximumFractionDigits: 1 });
246
+
247
+ /** "free" for nothing, else "2.4 cr". */
248
+ export function creditsWords(value) {
249
+ const n = typeof value === "string" ? Number(value) : (value ?? 0);
250
+ if (!Number.isFinite(n) || n <= 0) return "free";
251
+ return `${formatCreditAmount(Math.round(n * 10) / 10)} cr`;
252
+ }
253
+
254
+ /** The price tag of each metered step, by step id, from a run's estimate
255
+ * ({ steps: [{ id, credits, credits_max }] }): the figure a run is
256
+ * expected to spend there (a loop's inner step: across its passes). */
257
+ export function priceMap(estimate) {
258
+ const out = new Map();
259
+ for (const s of estimate?.steps ?? []) {
260
+ const prior = out.get(s.id);
261
+ out.set(s.id, { credits: (prior?.credits ?? 0) + s.credits, max: (prior?.max ?? 0) + s.credits_max });
262
+ }
263
+ return out;
264
+ }
265
+
266
+ /* ---- health and outcomes ------------------------------------------------- */
267
+
268
+ /** A run's status as a tone and a word: { tone: green|blue|amber|red|grey,
269
+ * text }. Never a status code. */
270
+ export function runStatusWords(status, dry = false) {
271
+ if (dry) {
272
+ switch (status) {
273
+ case "done":
274
+ return { tone: "green", text: "Test passed" };
275
+ case "failed":
276
+ return { tone: "red", text: "Test failed" };
277
+ case "stopped":
278
+ case "needs_you":
279
+ return { tone: "amber", text: "Test stopped" };
280
+ case "running":
281
+ case "queued":
282
+ return { tone: "blue", text: "Testing" };
283
+ default:
284
+ break;
285
+ }
286
+ }
287
+ switch (status) {
288
+ case "done":
289
+ return { tone: "green", text: "Done" };
290
+ case "running":
291
+ return { tone: "blue", text: "Running" };
292
+ case "queued":
293
+ return { tone: "blue", text: "Starting" };
294
+ case "waiting":
295
+ return { tone: "amber", text: "Waiting" };
296
+ case "needs_you":
297
+ return { tone: "amber", text: "Needs its owner" };
298
+ case "failed":
299
+ return { tone: "red", text: "Failed" };
300
+ case "stopped":
301
+ return { tone: "grey", text: "Stopped" };
302
+ default:
303
+ return { tone: "grey", text: String(status ?? "") };
304
+ }
305
+ }
306
+
307
+ /** What a test run says a step would have done: the platform's own words
308
+ * when the viewer may read them, else a plain line. Never an id. */
309
+ export function wouldWords(row) {
310
+ const w = row?.output?.would;
311
+ const words = w && typeof w.words === "string" ? w.words.trim() : "";
312
+ return words || "Would run.";
313
+ }
314
+
315
+ /** A test run, in one or two plain sentences: "Test passed: nothing was sent
316
+ * or changed. 3 steps would have run." `detail` is a run's account
317
+ * ({ run }). Null for a run that was not a test. */
318
+ export function testWords(detail) {
319
+ const run = detail?.run;
320
+ if (!run || run.dry !== true) return null;
321
+ const would = Number(run.result?.dry?.simulated ?? 0);
322
+ const count = Number.isFinite(would) && would > 0 ? would : 0;
323
+ if (run.status === "done") {
324
+ const tail = count === 0 ? "No step needed to change anything." : `${count} ${count === 1 ? "step" : "steps"} would have run.`;
325
+ return `Test passed: nothing was sent or changed. ${tail}`;
326
+ }
327
+ if (run.status === "failed") {
328
+ const why = run.error && typeof run.error.words === "string" ? run.error.words.trim() : "";
329
+ return why ? `Test failed. ${why}` : "Test failed.";
330
+ }
331
+ if (run.status === "stopped" || run.status === "needs_you" || run.status === "waiting") {
332
+ const why = run.error && typeof run.error.words === "string" ? run.error.words.trim() : "";
333
+ return why ? `Test stopped: ${why.charAt(0).toLowerCase()}${why.slice(1)}` : run.status === "stopped" ? "Test stopped." : "Test stopped: it needs something first.";
334
+ }
335
+ if (run.status === "running" || run.status === "queued") return "Testing: reading your real data, changing nothing.";
336
+ return null;
337
+ }
338
+
339
+ /** The list's health word for an automation row: how it is doing now. */
340
+ export function healthOf(a) {
341
+ if (a.status === "needs_owner") return { tone: "amber", text: "Needs an owner" };
342
+ if (a.status === "draft" || a.live_version === null || a.live_version === undefined) return { tone: "grey", text: "Not live yet" };
343
+ if (a.status === "off") return { tone: "grey", text: "Off" };
344
+ if ((a.active_runs ?? 0) > 0) return { tone: "blue", text: "Running" };
345
+ const last = a.last_run;
346
+ if (!last) return { tone: "grey", text: "Has not run yet" };
347
+ if (last.status === "failed") return { tone: "red", text: "Last run failed" };
348
+ if (last.status === "needs_you") return { tone: "amber", text: "Needs its owner" };
349
+ if (last.status === "waiting") return { tone: "amber", text: "Waiting" };
350
+ return { tone: "green", text: "Healthy" };
351
+ }
352
+
353
+ export function nodeStateWords(state) {
354
+ switch (state) {
355
+ case "done":
356
+ return "Done";
357
+ case "running":
358
+ return "Running";
359
+ case "failed":
360
+ return "Failed";
361
+ case "fixed":
362
+ return "Fixed by the agent";
363
+ case "would":
364
+ return "Would run";
365
+ case "waiting":
366
+ return "Waiting";
367
+ case "skipped":
368
+ return "Skipped";
369
+ case "unknown":
370
+ return "Needs a look";
371
+ case "notreached":
372
+ return "Not reached";
373
+ default:
374
+ return "";
375
+ }
376
+ }
377
+
378
+ /** The list's one line of where an automation lives: the team's, or an
379
+ * app's. `appName(id)` names an app, or null. */
380
+ export function originWords(a, appName) {
381
+ if (a.owner_kind === "app" && a.app_id) return appName?.(a.app_id) ?? "An app";
382
+ return "Team";
383
+ }
384
+
385
+ /** "Run 7 · 3m ago · Done": a run, in one line. */
386
+ export function runLine(run, n) {
387
+ const status = runStatusWords(run.status, run.dry === true).text;
388
+ return `${run.is_test ? "Test " : "Run "}${n} · ${agoWords(run.created_at) ?? "just now"} · ${status}`;
389
+ }
390
+
391
+ /* ---- the list's and the runs' counts ------------------------------------- */
392
+
393
+ /** What the list's one line counts: what is on, what failed, what waits for
394
+ * its owner, and which runs next. */
395
+ export function summaryOf(rows, now = new Date()) {
396
+ let on = 0;
397
+ let failing = 0;
398
+ let needs = 0;
399
+ let next = null;
400
+ for (const r of rows ?? []) {
401
+ if (r.status === "on") on += 1;
402
+ if (r.last_run?.status === "failed") failing += 1;
403
+ if (r.status === "needs_owner" || r.last_run?.status === "needs_you") needs += 1;
404
+ if (r.status === "on" && r.next_run_at && new Date(r.next_run_at) > now && (!next || r.next_run_at < next.next_run_at)) next = r;
405
+ }
406
+ return { on, failing, needs, next };
407
+ }
408
+
409
+ /** A run still going or waiting on someone. */
410
+ export const ACTIVE = new Set(["queued", "running", "waiting", "needs_you"]);
411
+
412
+ /** An automation's runs, counted: what finished, what failed, what is
413
+ * going, and what it cost. */
414
+ export function overviewOf(runs) {
415
+ let done = 0;
416
+ let failed = 0;
417
+ let active = 0;
418
+ let credits = 0;
419
+ for (const r of runs ?? []) {
420
+ if (r.status === "done") done += 1;
421
+ else if (r.status === "failed") failed += 1;
422
+ else if (ACTIVE.has(r.status)) active += 1;
423
+ const c = typeof r.credits === "string" ? Number(r.credits) : r.credits;
424
+ if (Number.isFinite(c)) credits += c;
425
+ }
426
+ return { done, failed, active, credits };
427
+ }
428
+
429
+ /** The report a run left, as short lines (a number or a word each). */
430
+ export function reportLines(result) {
431
+ if (!result) return [];
432
+ const out = [];
433
+ for (const [k, v] of Object.entries(result)) {
434
+ if (out.length >= 8) break;
435
+ if (v === null || v === undefined) continue;
436
+ if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") out.push({ label: k.replace(/_/g, " "), value: String(v) });
437
+ }
438
+ return out;
439
+ }
@@ -0,0 +1,207 @@
1
+ # AutomationsScreen
2
+
3
+ The whole Automations page of an app, as ONE block. It answers "how do I give
4
+ my app an Automations page?" with one component and a handful of props, so a
5
+ fix to the page reaches every app through `update` and no app carries a copy.
6
+
7
+ The places a member goes:
8
+
9
+ - **The list** — each automation as a row that opens whole, an on/off switch,
10
+ **New automation** (the starting points, **Describe it**), the week's
11
+ **allowance shown once** above the rows, and two slots under them: jobs that
12
+ run **on request** and the app's own **extras**.
13
+ - **New** — a new automation in the editor, from a starting point or blank. It
14
+ is not saved until **Create**.
15
+ - **One automation** — its flow on a canvas, edited, tested, kept and switched
16
+ on; its **Runs**; and any tabs the app adds.
17
+ - **One run** — step by step, with the run's controls (pause, retry, skip…)
18
+ and the agent's fixes.
19
+
20
+ It composes `automation-list`, `automation-editor`, `run-view` and `cost`, and
21
+ decides only what they leave open:
22
+
23
+ - **Which place is showing, and how it travels in a page address.** The place
24
+ is `{ automation, tab, run, start }`; `placeFromParams` and `paramsOfPlace`
25
+ turn it into and out of the query string. Hold it yourself (`place` +
26
+ `onPlace`) or leave it to the block.
27
+ - **Back to where the member WAS.** Back from an automation is the list with
28
+ the words that were in its search box. Back from a run is the Runs tab it was
29
+ opened from (or the flow, when it was opened from a test).
30
+ - **What each editor is handed**: the platform's `triggers`, the automation's
31
+ `selfKey`, its webhook (`hook`, `onRotateHook`), its `tests`, `compareTo`
32
+ (what "What changed" compares an agent's draft with), the app's declared
33
+ `actions`, and the save with `baseVersion` (a save names the version the copy
34
+ began on, so an agent's newer draft is never buried).
35
+ - **A delete that asks first and can be undone.** The row's menu and the
36
+ editor's menu ask (`Deletes "<name>". Its runs stay in history.`); then a
37
+ toast says what was deleted, which automations followed it and will no longer
38
+ start, and offers **Undo** for a few seconds.
39
+ - **Describe it** — to the platform (`onDescribe="platform"`), or handed on to
40
+ the agent beside the page (`onDescribe={(ask) => …}`).
41
+ - **The app's older schedule.** A row from before the engine (`source:
42
+ "legacy"`) opens read-only, with a line saying why.
43
+
44
+ ```jsx
45
+ import { AutomationsScreen, placeFromParams, paramsOfPlace } from "../components/blocks/automations-screen"; // a Makersclaw app
46
+ import { AutomationsScreen, placeFromParams, paramsOfPlace } from "@/components/makersclaw/blocks/automations-screen"; // a shadcn project
47
+ ```
48
+
49
+ `makersclaw add automations-screen` lays `automation-list`, `automation-editor`,
50
+ `run-view`, `cost` and `automation-model` (and what they need) with it. A
51
+ client component. It fills its parent's height (give it a parent with one, or a
52
+ `frame`), and each block inside decides its own layout from its own width.
53
+
54
+ ## Props
55
+
56
+ ### Required
57
+
58
+ - `hooks` — the engine's hooks and doors, from `lib/hooks`: `{ useAutomations,
59
+ useAutomation, useAutomationRun, deleteAutomation, restoreAutomation }`. A
60
+ block may not import `lib/`, so they come in here. The first three are
61
+ required (without them the block draws a plain notice naming what is
62
+ missing); the two doors are optional (without `deleteAutomation` there is no
63
+ Delete; without `restoreAutomation` no Undo). Pass a module-level object so
64
+ it is the same on every render.
65
+
66
+ ### Where it is
67
+
68
+ - `place`, `onPlace(place)` — the place, controlled. Leave both out and the
69
+ block holds it. `place` is `{ automation: null | "new" | <id>, tab: "flow" |
70
+ "runs" | <an extra tab's key>, run: <run id> | null, start: <starting point
71
+ id> | null }`; anything missing is the list. Always called back with a
72
+ complete place.
73
+ - `placeFromParams(searchParams)` → a place. Takes a `URLSearchParams`, a
74
+ `useSearchParams()` result or a function name → value; reads `automation`,
75
+ `tab`, `run`, `start`.
76
+ - `paramsOfPlace(place)` → the query parameters of a place, only what is set
77
+ (the list is `{}`); spread them into your own: `{ view: "automations",
78
+ ...paramsOfPlace(place) }`.
79
+ - `query`, `onQueryChange(text)` — the list's search box. Held by the block
80
+ unless you pass them (to keep it across a reload, say).
81
+
82
+ ### The list
83
+
84
+ - `title` ("Automations"), `intro` — the list's heading and its line.
85
+ - `allowance` — `{ used, of, words? }`: the week's credits, drawn once above
86
+ the list as a meter (`cost`'s `Allowance`). From `useJobs().budget`
87
+ (`week_used_credits`, `week_cap_credits`). `null` (default): none. `words` is
88
+ your own line ("4,180 of 10,000 credits this week").
89
+ - `onRequest`, `extras` — nodes, or functions `({ automations }) => node`, drawn
90
+ under the rows once they have loaded (`onRequest` first). `onRequest` is for
91
+ jobs a press or an ask starts and no schedule runs; `extras` is anything else
92
+ of the app's.
93
+ - `starts` — the app's own starting points: `[{ id, name, blurb, glyph, needs,
94
+ build(takenKeys) → a whole definition }]`, offered first under New. The
95
+ platform's come after them (or, where it has none, the template's five).
96
+ - `onDescribe` — `"platform"` (the platform drafts it, one model call, and the
97
+ new automation opens), a function `(ask) => Promise<{ ok: true } | { ok:
98
+ false, error }>` (the sentence is handed on, to an agent beside the page say;
99
+ the box empties), or nothing (no Describe it). `describePrice` (the words on
100
+ the Draft it button; `""` for none), `describeChips`.
101
+ - `onToggled(row, on)` — async, after a switch was saved. Keep a setting of the
102
+ app's own in step with it; a throw is shown above the rows.
103
+ - `canToggle`, `canCreate`, `canDelete` — all true by default.
104
+ - `now` — the clock, for a test.
105
+
106
+ ### One automation
107
+
108
+ - `actions` — the app's declared actions, for the action step: `[{ name,
109
+ description }]` (`manifest.actions` without those marked `agent: false`).
110
+ - `apps`, `runnable`, `ownedByApp` (default true) — as the editor's.
111
+ - `extraTabs` — tabs the app adds beside Flow and Runs: `[{ key, label,
112
+ when?(automation) → bool, render({ automation, definition, tab, runId, go })
113
+ → node }]`. `when` decides which automations get the tab (omit: all). `flow`
114
+ and `runs` are not yours.
115
+ - `aboveOne` — a node, or `({ automation, definition, tab, runId, run, go }) =>
116
+ node`: drawn above an automation (a connection it needs, a notice).
117
+ - `afterRun` — the same, under a run (the app's own account of it). `run` is the
118
+ run.
119
+ - `legacyWords` — the line over a read-only older schedule (`false`: none).
120
+ - Run again, in a run: after a test it is a test; after a real run it is a real
121
+ run (it spends, and it acts). The run-view block says which on the button.
122
+ - `onFocus({ selected, unsaved, baseVersion })` — the editor's, for an agent
123
+ pane beside the page that must know what the member is looking at.
124
+ - `every` — how often the hooks look again, in ms (default theirs: 30 s, 5 s
125
+ while one runs). Lower it while an agent beside the page works.
126
+
127
+ ### The frame
128
+
129
+ - `frame({ crumb, label, fill, children })` — a plain function (no hooks in it)
130
+ that wraps each place in the app's chrome and returns it. `crumb` is
131
+ `[{ label, href?, onPress? }]`: the ancestors (with `onPress`, and `href` when
132
+ you give `hrefOf`) then the page you are on. `label` names the content region;
133
+ `fill` is true where the body owns its own scrolling (the editor, a run).
134
+ **The first crumb is always the list itself** (the block's `title`; on the
135
+ list it is the only crumb), and its `onPress` goes back to the list with
136
+ the member's search kept: use `onPress` when it is there, `href` only when
137
+ you gave `hrefOf`. An app that draws its own root crumb ("Morning checks"
138
+ above the page) drops that first one: `crumb.slice(1)`. Default: the kit's `AppLayout` filling its parent. An app draws its top bar
139
+ here and returns `<AppLayout …>`:
140
+
141
+ ```jsx
142
+ frame={({ crumb, label, fill, children }) => (
143
+ <>
144
+ <TopBar icon="zap" crumb={crumb.map((c) => ({ label: c.label, href: c.href }))} />
145
+ <AppLayout contentLabel={label} contentMode={fill ? "fill" : undefined}>{children}</AppLayout>
146
+ </>
147
+ )}
148
+ ```
149
+ - `hrefOf(place)` → a string. When given, ancestor crumbs carry an `href`.
150
+ - `unavailableWords` — the line where this Makersclaw has no engine yet.
151
+
152
+ ## Example
153
+
154
+ The whole page of an app whose address carries the place:
155
+
156
+ ```jsx
157
+ "use client";
158
+ import { useRouter, useSearchParams } from "next/navigation";
159
+ import { useAutomation, useAutomationRun, useAutomations, deleteAutomation, restoreAutomation, useJobs } from "../lib/hooks";
160
+ import { AutomationsScreen, paramsOfPlace, placeFromParams } from "../components/blocks/automations-screen";
161
+ import manifest from "../makersclaw.json";
162
+
163
+ const HOOKS = { useAutomations, useAutomation, useAutomationRun, deleteAutomation, restoreAutomation };
164
+ const ACTIONS = (manifest.actions ?? []).filter((a) => a.agent !== false).map((a) => ({ name: a.name, description: a.description }));
165
+
166
+ export default function Automations() {
167
+ const router = useRouter();
168
+ const sp = useSearchParams();
169
+ const { budget } = useJobs();
170
+ return (
171
+ <AutomationsScreen
172
+ hooks={HOOKS}
173
+ place={placeFromParams(sp)}
174
+ onPlace={(place) => router.push(`/s/today?${new URLSearchParams({ view: "automations", ...paramsOfPlace(place) })}`, { scroll: false })}
175
+ actions={ACTIONS}
176
+ allowance={budget ? { used: budget.week_used_credits, of: budget.week_cap_credits } : null}
177
+ onDescribe="platform"
178
+ onRequest={<p className="text-sm text-muted-foreground">The first read starts when a mailbox connects.</p>}
179
+ />
180
+ );
181
+ }
182
+ ```
183
+
184
+ ## States
185
+
186
+ Drawn in the demo (a state picker and a width picker for 1280, 800, 368 and
187
+ 320 px): many automations (one with a very long name), one, none (the first-run
188
+ screen with starting points and Describe it), loading (a skeleton, never the
189
+ first-run screen), the list failing to load (a notice with Try again), a
190
+ platform without the engine, an app's older read-only schedule, an automation
191
+ that will not open or is gone (a line and a way back), a run that will not open,
192
+ a test run, a run opened from the Runs tab, an app tab, a delete with its
193
+ Undo, and a delete the platform refuses (an app's own job).
194
+
195
+ ## Who may do what
196
+
197
+ The platform decides; a hidden button is never the guard. Any member who opens
198
+ the app edits and runs its automations. A delete is the owner's or an admin's;
199
+ a refusal comes back in the platform's own words and is shown as it is.
200
+
201
+ ## Never
202
+
203
+ - Never import `lib/` here: the hooks are the `hooks` prop.
204
+ - Never a run that starts on its own: a run starts only on Test run or Run again.
205
+ - Never a second Allowance: it is drawn once, on the list.
206
+ - Never the raw words of a failure: a list that cannot load says so in one plain
207
+ sentence; the blocks inside show the platform's plain words.