makersclaw 0.8.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 (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 +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/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 +1627 -8
  400. package/templates/next/files/lib/platform.js +529 -21
  401. package/templates/next/template.json +13 -3
@@ -0,0 +1,286 @@
1
+ "use client";
2
+
3
+ // RunView and RunsList over pretend runs — the gallery's and the smoke
4
+ // test's surface. Not installed into apps. Pick a run: one that took the
5
+ // Yes path and finished (the agent fixed a step and drafted a change to keep
6
+ // or drop; a person changed another step's data), a test run (dashed pencil cards, the strip), one that failed in the
7
+ // loop, and four that are not over: stuck at a step (try again, skip, change
8
+ // its data), cut off in a send, held at its limit (raise it), and paused.
9
+ // Press a step of a run that is over for "Retry from this step"; in the first
10
+ // run it first answers that something already sent, and asks once.
11
+ // The controls answer from memory. Press a card for the step's account. A
12
+ // width picker shows 1280, 800, 368 and 320 px of the block's own width.
13
+ import { useState } from "react";
14
+ import { Button, ButtonGroup } from "../components/ui";
15
+ import { RunView, RunsList } from "../components/blocks/run-view";
16
+
17
+ const DEF = {
18
+ format: 1,
19
+ key: "morning-read",
20
+ name: "Morning read",
21
+ trigger: { type: "schedule", cron: "0 7 * * 1-5", tz: "team" },
22
+ inputs: {},
23
+ settings: { overlap: "skip", on_failure: "retry_then_agent" },
24
+ steps: [
25
+ {
26
+ id: "gate",
27
+ kind: "condition",
28
+ label: "Anything new?",
29
+ if: "{{ trigger.at }}",
30
+ then: [{ id: "mail", kind: "tool", label: "Read the mail", needs: { category: "mail" }, tool: "list_messages", input: { limit: 200 } }],
31
+ else: [{ id: "off", kind: "stop", message: "Nothing new" }],
32
+ },
33
+ { id: "touches", kind: "action", label: "Save who wrote", action: "record_touches", input: { touches: "{{ steps.mail.output.messages }}" } },
34
+ {
35
+ id: "drafts",
36
+ kind: "loop",
37
+ over: "{{ steps.touches.output.owed }}",
38
+ max: 8,
39
+ steps: [
40
+ { id: "draft", kind: "llm", label: "Write the follow-up", tier: "smart", prompt: "Write a short follow-up." },
41
+ { id: "save", kind: "action", label: "Save the draft", action: "suggest", input: { body: "{{ steps.draft.output.text }}" } },
42
+ ],
43
+ },
44
+ { id: "tell", kind: "notify", message: "Done." },
45
+ ],
46
+ };
47
+
48
+ const t = (m) => `2026-10-${m}:00.000Z`; // all in the past, so "3d ago" reads right
49
+ const row = (step_id, over = {}) => ({ path: step_id, step_id, kind: "notify", attempt: 1, status: "done", started_at: t("08T07:00"), ended_at: t("08T07:01"), credits: 0, error: null, ...over });
50
+
51
+ const RUNS = [
52
+ {
53
+ id: "r3",
54
+ status: "done",
55
+ version: 2,
56
+ trigger_type: "schedule",
57
+ is_test: false,
58
+ created_at: t("08T07:00"),
59
+ started_at: t("08T07:00"),
60
+ ended_at: t("08T07:02"),
61
+ credits: 4.4,
62
+ cap_credits: 900,
63
+ result: { people_saved: 4, drafts_written: 2 },
64
+ fixes: [{ id: "a1", step_path: "touches", step_id: "touches", attempt: 1, status: "applied", credits: 0.4, drafts: [{ id: "d1", why: "Trim the address before it is saved.", status: "proposed", base_version: 2, new_version: null }] }],
65
+ steps: [
66
+ row("gate", { kind: "condition", output: { taken: "then" } }),
67
+ row("mail", { kind: "tool", input: { limit: 200 }, output: { count: 38 } }),
68
+ row("touches", { kind: "action", fix: { id: "f1", by: "agent", kind: "format", status: "applied", before: "Ana@x.com ", after: "ana@x.com", why: "The mail tool refuses spaces.", credits: 0.4, effect: "write", undo: true } }),
69
+ row("drafts", { kind: "loop" }),
70
+ row("draft", { path: "drafts[0]/draft", kind: "llm", credits: 1.9 }),
71
+ row("save", { path: "drafts[0]/save", kind: "action" }),
72
+ row("draft", { path: "drafts[1]/draft", kind: "llm", credits: 2.1 }),
73
+ row("save", { path: "drafts[1]/save", kind: "action", fix: { id: "f2", by: "member", kind: "input", status: "applied", before: { body: "Hi Ana" }, after: { body: "Hi Ana, a quick follow-up" }, why: "You changed this step's data for this run." } }),
74
+ row("tell"),
75
+ ],
76
+ },
77
+ {
78
+ id: "r2",
79
+ status: "failed",
80
+ version: 2,
81
+ trigger_type: "schedule",
82
+ is_test: false,
83
+ created_at: t("07T07:00"),
84
+ started_at: t("07T07:00"),
85
+ ended_at: t("07T07:01"),
86
+ credits: 2.1,
87
+ result: null,
88
+ error: { words: "A draft could not be saved: that person was removed." },
89
+ steps: [
90
+ row("gate", { kind: "condition", output: { taken: "then" } }),
91
+ row("mail", { kind: "tool" }),
92
+ row("touches", { kind: "action" }),
93
+ row("drafts", { kind: "loop", status: "failed" }),
94
+ row("draft", { path: "drafts[0]/draft", kind: "llm", credits: 2.1 }),
95
+ row("save", { path: "drafts[0]/save", kind: "action", status: "failed", error: { code: "gone", words: "That person was removed." } }),
96
+ ],
97
+ },
98
+ {
99
+ id: "r5",
100
+ status: "needs_you",
101
+ version: 2,
102
+ trigger_type: "schedule",
103
+ is_test: false,
104
+ created_at: t("09T07:00"),
105
+ started_at: t("09T07:00"),
106
+ ended_at: null,
107
+ credits: 1.2,
108
+ cap_credits: 900,
109
+ result: null,
110
+ error: { code: "step_failed", words: "“Save who wrote” was refused: the address is not valid." },
111
+ steps: [
112
+ row("gate", { kind: "condition", output: { taken: "then" } }),
113
+ row("mail", { kind: "tool", output: { count: 3 } }),
114
+ row("touches", { kind: "action", status: "failed", input: { touches: [{ email: "ana@" }] }, error: { code: "bad_address", words: "The address is not valid." } }),
115
+ ],
116
+ },
117
+ {
118
+ id: "r6",
119
+ status: "needs_you",
120
+ version: 2,
121
+ trigger_type: "schedule",
122
+ is_test: false,
123
+ created_at: t("09T08:00"),
124
+ started_at: t("09T08:00"),
125
+ ended_at: null,
126
+ credits: 3,
127
+ cap_credits: 900,
128
+ result: null,
129
+ error: { code: "step_unknown", words: "“Tell the team” was cut off while it was sending." },
130
+ steps: [
131
+ row("gate", { kind: "condition", output: { taken: "then" } }),
132
+ row("mail", { kind: "tool" }),
133
+ row("touches", { kind: "action" }),
134
+ row("drafts", { kind: "loop" }),
135
+ row("tell", { status: "unknown", error: { code: "unknown_effect", words: "It may have been sent." } }),
136
+ ],
137
+ },
138
+ {
139
+ id: "r7",
140
+ status: "needs_you",
141
+ version: 2,
142
+ trigger_type: "manual",
143
+ is_test: true,
144
+ created_at: t("09T09:00"),
145
+ started_at: t("09T09:00"),
146
+ ended_at: null,
147
+ credits: 900,
148
+ cap_credits: 900,
149
+ result: null,
150
+ error: { code: "run_cap", words: "This run reached its limit of 900 credits." },
151
+ steps: [row("gate", { kind: "condition", output: { taken: "then" } }), row("mail", { kind: "tool", credits: 900 })],
152
+ },
153
+ {
154
+ id: "r8",
155
+ status: "running",
156
+ paused: true,
157
+ version: 2,
158
+ trigger_type: "schedule",
159
+ is_test: false,
160
+ created_at: t("09T10:00"),
161
+ started_at: t("09T10:00"),
162
+ ended_at: null,
163
+ credits: 0.2,
164
+ cap_credits: 900,
165
+ result: null,
166
+ steps: [row("gate", { kind: "condition", output: { taken: "then" } }), row("mail", { kind: "tool", status: "running", ended_at: null })],
167
+ },
168
+ {
169
+ id: "r9",
170
+ status: "done",
171
+ dry: true,
172
+ version: 2,
173
+ trigger_type: "manual",
174
+ is_test: true,
175
+ created_at: t("10T07:00"),
176
+ started_at: t("10T07:00"),
177
+ ended_at: t("10T07:01"),
178
+ credits: 0.4,
179
+ result: {
180
+ dry: {
181
+ simulated: 3,
182
+ would: [
183
+ { step: "save", path: "drafts[0]/save", kind: "action", effect: "write", words: "Would save the draft with suggest." },
184
+ { step: "tell", path: "tell", kind: "notify", effect: "note", words: "Would leave the note “Done.”" },
185
+ ],
186
+ unchecked: ["tell"],
187
+ sampled: [{ step: "drafts", of: 38, looked_at: 5 }],
188
+ },
189
+ },
190
+ steps: [
191
+ row("gate", { kind: "condition", output: { taken: "then" } }),
192
+ row("mail", { kind: "tool" }),
193
+ row("touches", { kind: "action", simulated: true, output: { simulated: true, would: { kind: "action", effect: "write", words: "Would record who wrote with record_touches." } } }),
194
+ row("drafts", { kind: "loop" }),
195
+ row("draft", { path: "drafts[0]/draft", kind: "llm", credits: 0.4 }),
196
+ row("save", { path: "drafts[0]/save", kind: "action", simulated: true, output: { simulated: true, would: { kind: "action", effect: "write", words: "Would save the draft with suggest." } } }),
197
+ row("tell", { simulated: true, unchecked: true }),
198
+ ],
199
+ },
200
+ { id: "r1", status: "done", version: 1, trigger_type: "manual", is_test: true, created_at: t("06T10:00"), started_at: t("06T10:00"), ended_at: t("06T10:01"), credits: 0, result: null, steps: [row("gate", { kind: "condition", output: { taken: "else" } }), row("off", { kind: "stop" })] },
201
+ ];
202
+ const WIDTHS = [1280, 800, 368, 320];
203
+
204
+ // What a control does to a pretend run: enough to see each state's next screen.
205
+ function afterControl(run, op, extra) {
206
+ switch (op) {
207
+ case "pause":
208
+ return { ...run, paused: true };
209
+ case "stop":
210
+ return { ...run, status: "stopped", paused: false, ended_at: run.started_at };
211
+ case "resume":
212
+ return { ...run, paused: false, status: "running", cap_credits: (run.cap_credits ?? 0) + (extra.raiseBy ?? 0), error: null };
213
+ case "skip":
214
+ return { ...run, status: "running", error: null, steps: run.steps.map((s) => (s.path === extra.path ? { ...s, status: "skipped", error: null } : s)) };
215
+ case "retry_from": {
216
+ const at = DEF.steps.findIndex((top) => top.id === extra.path);
217
+ const after = new Set(DEF.steps.slice(at).map((top) => top.id));
218
+ return { ...run, status: "running", error: null, ended_at: null, steps: run.steps.filter((s) => !after.has(s.path.split("[")[0].split("/")[0])) };
219
+ }
220
+ case "retry":
221
+ case "edit":
222
+ return { ...run, status: "running", error: null, steps: run.steps.map((s) => (s.path === extra.path ? { ...s, status: "running", error: null, ...(extra.input ? { input: extra.input } : {}) } : s)) };
223
+ default:
224
+ return run;
225
+ }
226
+ }
227
+
228
+ export default function RunViewDemo() {
229
+ const [width, setWidth] = useState(1280);
230
+ const [id, setId] = useState("r3");
231
+ const [tab, setTab] = useState("run");
232
+ const [runs, setRuns] = useState(RUNS);
233
+ const [drafts, setDrafts] = useState({});
234
+ const run = runs.find((r) => r.id === id) ?? runs[0];
235
+ const fixes = (run.fixes ?? []).map((f) => ({ ...f, drafts: f.drafts.map((d) => (drafts[d.id] ? { ...d, ...drafts[d.id] } : d)) }));
236
+ return (
237
+ <div className="grid gap-4 p-4">
238
+ <ButtonGroup aria-label="The block's width">
239
+ {WIDTHS.map((w) => (
240
+ <Button key={w} size="sm" variant={w === width ? "primary" : "secondary"} onClick={() => setWidth(w)}>
241
+ {w} px
242
+ </Button>
243
+ ))}
244
+ </ButtonGroup>
245
+ <div className="flex h-[680px] w-full flex-col overflow-hidden rounded-lg border border-border" style={{ maxWidth: width }}>
246
+ {tab === "run" ? (
247
+ <RunView
248
+ key={run.id}
249
+ def={DEF}
250
+ detail={{ run, steps: run.steps, steps_visible: true, automation: { name: "Morning read" }, fixes }}
251
+ runs={runs}
252
+ tz="America/New_York"
253
+ name="Morning read"
254
+ tabs={
255
+ <Button size="sm" variant="secondary" onClick={() => setTab("runs")}>
256
+ Runs
257
+ </Button>
258
+ }
259
+ onBack={() => setTab("runs")}
260
+ onPickRun={setId}
261
+ onRunAgain={() => {}}
262
+ onControl={async (op, extra) => {
263
+ if (op === "skip" && extra.path === "touches" && run.id === "r5") return { ok: false, code: "output_needed", error: "A later step uses what this one makes, so it cannot be skipped." };
264
+ // A pretend send: starting over from "Save who wrote" or earlier asks first once.
265
+ if (op === "retry_from" && run.id === "r3" && !extra.confirmResend && ["gate", "touches", "drafts"].includes(extra.path)) return { ok: false, code: "needs_confirm_resend", error: "A step from here on already sent something." };
266
+ setRuns((all) => all.map((r) => (r.id === run.id ? afterControl(r, op, extra) : r)));
267
+ return { ok: true };
268
+ }}
269
+ onKeepFix={async () => (setDrafts((d) => ({ ...d, d1: { status: "kept", new_version: 3 } })), { ok: true })}
270
+ onDropFix={async () => (setDrafts((d) => ({ ...d, d1: { status: "dropped" } })), { ok: true })}
271
+ onUndoFix={async () => ({ ok: true })}
272
+ />
273
+ ) : (
274
+ <RunsList
275
+ runs={runs}
276
+ tz="America/New_York"
277
+ onOpen={(r) => {
278
+ setId(r);
279
+ setTab("run");
280
+ }}
281
+ />
282
+ )}
283
+ </div>
284
+ </div>
285
+ );
286
+ }
@@ -0,0 +1,5 @@
1
+ // The RunView block — `makersclaw add run-view`. Fixed: compose it
2
+ // through its props (README.md beside this file).
3
+ export { RunView } from "./run-view";
4
+ export { RunsList } from "./runs-list";
5
+ export { RetryFromStep, RunControls } from "./run-controls";
@@ -0,0 +1,266 @@
1
+ "use client";
2
+
3
+ // What a person can do with a run that is not over: pause it, let it go
4
+ // on, stop it; and when it is stuck on a step, try that step again, skip it,
5
+ // change the data it was given for this run, or raise the run's limit and
6
+ // go on. It offers only what the run's state allows (automation-model's
7
+ // controlsOf), says plainly what each does, and takes the platform's
8
+ // refusal in the platform's words. It changes nothing itself: every press
9
+ // is `onControl(op, extra)`, which resolves { ok } or { ok: false, error,
10
+ // code }. Props in, callbacks out.
11
+
12
+ import { useMemo, useState } from "react";
13
+ import { Button, Field, Input, Textarea, cx } from "../../ui";
14
+ import { CONTROL_DONE, CONTROL_REFUSED, PanelSection, RETRY_FROM, controlsOf, creditsWords, retryFromOf } from "../automation-model";
15
+
16
+ const jsonText = (v) => (v === undefined || v === null ? "{}" : JSON.stringify(v, null, 2));
17
+
18
+ /**
19
+ * run { status, paused, cap_credits, error }
20
+ * steps the run's step rows (for the step it is stuck at and its data)
21
+ * stepsVisible the member may read a step's data (so may change it)
22
+ * titleOf(id) a step's name
23
+ * onControl(op, { path?, input?, confirmNotSent?, raiseBy?, confirmResend? })
24
+ * op: pause · resume · stop · retry · skip · edit · retry_from
25
+ * busy the op that is out, or null
26
+ */
27
+ export function RunControls({ run, steps = [], stepsVisible = false, titleOf, onControl, busy = null, className }) {
28
+ const c = useMemo(() => controlsOf(run, steps, { stepsVisible }), [run, steps, stepsVisible]);
29
+ const [mode, setMode] = useState(null);
30
+ const [note, setNote] = useState(null);
31
+ const [text, setText] = useState("");
32
+ const [raise, setRaise] = useState("");
33
+ if (!onControl || c.state === "ended") return null;
34
+
35
+ const blockedRow = c.blocked ? steps.find((r) => r.path === c.blocked.path && r.status !== "done") : null;
36
+ const stuck = c.blocked ? (titleOf?.(c.blocked.stepId) ?? c.blocked.stepId) : null;
37
+
38
+ const send = async (op, extra = {}) => {
39
+ setNote(null);
40
+ let r;
41
+ try {
42
+ r = await onControl(op, extra);
43
+ } catch (e) {
44
+ r = { ok: false, error: e?.message ?? String(e) };
45
+ }
46
+ if (r && r.ok === false) {
47
+ setNote({ tone: "bad", text: r.error || CONTROL_REFUSED[r.code] || "That did not work. Try again." });
48
+ return false;
49
+ }
50
+ setMode(null);
51
+ setNote({ tone: "ok", text: CONTROL_DONE[op] ?? "Done." });
52
+ return true;
53
+ };
54
+
55
+ const openEdit = () => {
56
+ setText(jsonText(blockedRow?.input));
57
+ setNote(null);
58
+ setMode("edit");
59
+ };
60
+ const sendEdit = () => {
61
+ let input;
62
+ try {
63
+ input = JSON.parse(text);
64
+ } catch {
65
+ setNote({ tone: "bad", text: "That is not valid data. Check the commas and quotes." });
66
+ return;
67
+ }
68
+ if (input === null || typeof input !== "object" || Array.isArray(input)) {
69
+ setNote({ tone: "bad", text: "The data is a set of named values, like { \"limit\": 50 }." });
70
+ return;
71
+ }
72
+ void send("edit", { path: c.blocked.path, input });
73
+ };
74
+ const sendRaise = () => {
75
+ const by = Number(raise || c.raiseDefault);
76
+ if (!Number.isFinite(by) || by <= 0) {
77
+ setNote({ tone: "bad", text: "Say how many credits to add." });
78
+ return;
79
+ }
80
+ void send("resume", { raiseBy: by });
81
+ };
82
+ const off = busy !== null;
83
+
84
+ return (
85
+ <PanelSection title="What you can do">
86
+ <div className={cx("grid gap-2", className)}>
87
+ {c.state === "paused" ? <p className="m-0 text-[13px]">Paused. Nothing new starts until you resume it. A step that is already going finishes.</p> : null}
88
+ {c.state === "parked" && stuck ? (
89
+ <p className="m-0 text-[13px]">
90
+ {c.blocked.unknownSend ? `“${stuck}” was cut off while it was sending. Nobody knows whether it went.` : `It is stuck at “${stuck}”.`}
91
+ </p>
92
+ ) : null}
93
+ {c.state === "parked" && !stuck && !c.raise ? <p className="m-0 text-[13px]">It is waiting for its owner.</p> : null}
94
+
95
+ {mode === null ? (
96
+ <div className="flex flex-wrap gap-2">
97
+ {c.pause ? (
98
+ <Button size="sm" variant="secondary" icon="pause" loading={busy === "pause"} disabled={off} onClick={() => void send("pause")}>
99
+ Pause
100
+ </Button>
101
+ ) : null}
102
+ {c.resume && !c.raise ? (
103
+ <Button size="sm" variant="secondary" icon="play" loading={busy === "resume"} disabled={off} onClick={() => void send("resume")}>
104
+ {c.state === "paused" ? "Resume" : "Try again"}
105
+ </Button>
106
+ ) : null}
107
+ {c.raise ? (
108
+ <Button size="sm" variant="secondary" disabled={off} onClick={() => (setRaise(String(c.raiseDefault)), setMode("raise"))}>
109
+ Raise its limit
110
+ </Button>
111
+ ) : null}
112
+ {c.retry ? (
113
+ <Button size="sm" variant="secondary" icon="rotate-ccw" loading={busy === "retry"} disabled={off} onClick={() => void send("retry", { path: c.blocked.path, ...(c.blocked.unknownSend ? { confirmNotSent: true } : {}) })}>
114
+ {c.blocked.unknownSend ? "It did not go: send it again" : "Try this step again"}
115
+ </Button>
116
+ ) : null}
117
+ {c.skip ? (
118
+ <Button size="sm" variant="secondary" loading={busy === "skip"} disabled={off} onClick={() => void send("skip", { path: c.blocked.path })}>
119
+ {c.blocked.unknownSend ? "It did go: skip it" : "Skip this step"}
120
+ </Button>
121
+ ) : null}
122
+ {c.edit ? (
123
+ <Button size="sm" variant="secondary" icon="pencil" disabled={off} onClick={openEdit}>
124
+ Change its data
125
+ </Button>
126
+ ) : null}
127
+ {c.stop ? (
128
+ <Button size="sm" variant="quiet" icon="square" disabled={off} onClick={() => setMode("stop")}>
129
+ Stop
130
+ </Button>
131
+ ) : null}
132
+ </div>
133
+ ) : null}
134
+
135
+ {mode === "stop" ? (
136
+ <div className="grid gap-2">
137
+ <p className="m-0 text-[13px]">Stop this run? It ends here and cannot be started again. Run the automation again to get a new one.</p>
138
+ <div className="flex flex-wrap gap-2">
139
+ <Button size="sm" variant="danger" loading={busy === "stop"} disabled={off} onClick={() => void send("stop")}>
140
+ Stop it
141
+ </Button>
142
+ <Button size="sm" variant="quiet" disabled={off} onClick={() => setMode(null)}>
143
+ Let it go on
144
+ </Button>
145
+ </div>
146
+ </div>
147
+ ) : null}
148
+
149
+ {mode === "raise" ? (
150
+ <div className="grid gap-2">
151
+ <p className="m-0 text-[13px]">
152
+ It stopped at its limit{run.cap_credits ? ` of ${creditsWords(run.cap_credits)}` : ""}. Add credits to this run’s limit and it goes on from where it stopped. The automation’s own limit stays as it is.
153
+ </p>
154
+ <Field id="raise-by" label="Add credits">
155
+ <Input id="raise-by" type="number" inputMode="numeric" min={1} value={raise} onChange={(e) => setRaise(e.target.value)} className="w-32" />
156
+ </Field>
157
+ <div className="flex flex-wrap gap-2">
158
+ <Button size="sm" variant="primary" loading={busy === "resume"} disabled={off} onClick={sendRaise}>
159
+ Add and go on
160
+ </Button>
161
+ <Button size="sm" variant="quiet" disabled={off} onClick={() => setMode(null)}>
162
+ Cancel
163
+ </Button>
164
+ </div>
165
+ </div>
166
+ ) : null}
167
+
168
+ {mode === "edit" ? (
169
+ <div className="grid gap-2">
170
+ <p className="m-0 text-[13px]">What “{stuck}” is given, for this run only. The automation itself does not change.</p>
171
+ <Field id="run-data" label="Its data">
172
+ <Textarea id="run-data" rows={8} spellCheck={false} value={text} onChange={(e) => setText(e.target.value)} className="font-mono text-xs" />
173
+ </Field>
174
+ <div className="flex flex-wrap gap-2">
175
+ <Button size="sm" variant="primary" loading={busy === "edit"} disabled={off} onClick={sendEdit}>
176
+ Try it with this
177
+ </Button>
178
+ <Button size="sm" variant="quiet" disabled={off} onClick={() => setMode(null)}>
179
+ Cancel
180
+ </Button>
181
+ </div>
182
+ </div>
183
+ ) : null}
184
+
185
+ {note ? (
186
+ <p role={note.tone === "bad" ? "alert" : "status"} className={cx("m-0 text-xs", note.tone === "bad" ? "text-destructive" : "text-muted-foreground")}>
187
+ {note.text}
188
+ </p>
189
+ ) : null}
190
+ </div>
191
+ </PanelSection>
192
+ );
193
+ }
194
+
195
+ /**
196
+ * "Retry from this step", for the step a member is looking at in a run that
197
+ * is over (done, failed, stopped) or waiting on its owner: start the run over
198
+ * at that step, running it and every step after it again. A step inside a
199
+ * loop starts over from the loop. If a step from there on already sent
200
+ * something, it asks first, in its own words, and only then sends again.
201
+ * Quiet: the common press is a look, not a redo. Draws nothing when the run
202
+ * or the step does not allow it, or without `onControl`.
203
+ *
204
+ * run, steps, def the run, its step rows, the definition it used
205
+ * stepId the step shown
206
+ * onControl(op, { path, confirmResend? }) resolves { ok } or { ok: false, error, code }
207
+ * busy the op that is out, or null
208
+ */
209
+ export function RetryFromStep({ run, steps = [], def, stepId, onControl, busy = null, className }) {
210
+ const r = useMemo(() => retryFromOf(run, steps, def, stepId), [run, steps, def, stepId]);
211
+ const [asking, setAsking] = useState(false);
212
+ const [note, setNote] = useState(null);
213
+ if (!onControl || !r.show) return null;
214
+
215
+ const go = async (confirmResend) => {
216
+ setNote(null);
217
+ let out;
218
+ try {
219
+ out = await onControl("retry_from", { path: r.path, ...(confirmResend ? { confirmResend: true } : {}) });
220
+ } catch (e) {
221
+ out = { ok: false, error: e?.message ?? String(e) };
222
+ }
223
+ if (out && out.ok === false) {
224
+ if (out.code === "needs_confirm_resend") {
225
+ setAsking(true);
226
+ return;
227
+ }
228
+ setAsking(false);
229
+ setNote({ tone: "bad", text: out.error || CONTROL_REFUSED[out.code] || "That did not work. Try again." });
230
+ return;
231
+ }
232
+ setAsking(false);
233
+ setNote({ tone: "ok", text: CONTROL_DONE.retry_from });
234
+ };
235
+ const off = busy !== null;
236
+
237
+ return (
238
+ <div className={cx("grid gap-2", className)}>
239
+ {asking ? (
240
+ <div className="grid gap-2">
241
+ <p className="m-0 text-[13px]">{RETRY_FROM.ask}</p>
242
+ <div className="flex flex-wrap gap-2">
243
+ <Button size="sm" variant="primary" loading={busy === "retry_from"} disabled={off} onClick={() => void go(true)}>
244
+ {RETRY_FROM.yes}
245
+ </Button>
246
+ <Button size="sm" variant="quiet" disabled={off} onClick={() => setAsking(false)}>
247
+ {RETRY_FROM.no}
248
+ </Button>
249
+ </div>
250
+ </div>
251
+ ) : (
252
+ <div className="flex flex-wrap items-center gap-2">
253
+ <Button size="sm" variant="quiet" icon="rotate-ccw" loading={busy === "retry_from"} disabled={off} onClick={() => (r.sent ? setAsking(true) : void go(false))}>
254
+ {RETRY_FROM.button}
255
+ </Button>
256
+ </div>
257
+ )}
258
+ <p className="m-0 text-xs text-muted-foreground">{r.inLoop ? `${RETRY_FROM.inLoop(r.loopTitle)} ` : ""}{RETRY_FROM.what}</p>
259
+ {note ? (
260
+ <p role={note.tone === "bad" ? "alert" : "status"} className={cx("m-0 text-xs", note.tone === "bad" ? "text-destructive" : "text-muted-foreground")}>
261
+ {note.text}
262
+ </p>
263
+ ) : null}
264
+ </div>
265
+ );
266
+ }