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
@@ -60,7 +60,7 @@ leaves out four (Per mode, below). Which to build: §4.
60
60
  Yours — write and rewrite freely:
61
61
 
62
62
  ```
63
- app/shell.jsx the inside of the window: nav, layout, type, density
63
+ app/shell.jsx the inside of the window: nav, layout, type, density — an AppLayout (§3b, Layouts)
64
64
  app/DESIGN.md the design, written before the code (§3)
65
65
  surfaces/<key>.jsx one file per domain surface
66
66
  surfaces.js the manifest entries (import + component when built)
@@ -78,7 +78,7 @@ app/page.jsx / → the home surface (or "No surfaces yet" while the ma
78
78
  app/s/[key]/page.jsx renders the surface with that key; planned ones say so
79
79
  app/error.jsx, app/global-error.jsx, app/not-found.jsx, app/error-relay.jsx, app/auto-refresh.jsx,
80
80
  app/escape-relay.jsx, app/frame.js, app/claw-alive/route.js the app inside its window: refresh while shown (a surface opts out, §7), Escape from the desk
81
- components/ui/ the kit: Button, Field, Input, Select, Sheet, Tabs, Menu, Notice, Icon, Depiction… (§3b, §3c)
81
+ components/ui/ the kit: AppLayout, DocumentLayout, Button, Field, Input, Select, Sheet, Tabs, Menu, Notice, Icon, Depiction… (§3b, §3c)
82
82
  components/parts/ the parts: RecordSwitcher, LiveEmpty + LiveWork, useFixture + FixtureNotice (§3a, §3b)
83
83
  check/pins.json the fixed files by hash; `npm run check` refuses one that differs
84
84
  check/ `npm run check` (§6)
@@ -99,7 +99,7 @@ lib/brain.js the company brain from the browser, in both modes; its ho
99
99
  lib/brain-server.js the brain's reads for a server component — a server app's
100
100
  lib/claw.js the _claw API the gateway answers, from the browser
101
101
  lib/platform.js typed wrappers over lib/claw.js (Platform)
102
- lib/hooks.js the React hooks over them: useJob, useArtifact… (Hooks)
102
+ lib/hooks.js the React hooks over them: useJob, useLlm, useLibraryItems, useArtifact… (Hooks)
103
103
  lib/sample.js markSample, for sample rows (§3a)
104
104
  ```
105
105
 
@@ -147,7 +147,12 @@ Before any code, write `app/DESIGN.md` — one screen of text:
147
147
  - Type: scale and weight within the workspace's faces (`font-sans`,
148
148
  `font-mono`, `font-display`). Numbers tabular (`data-nums` on the element).
149
149
  - Layout and nav: where the surfaces live, what the home surface shows in
150
- the first second.
150
+ the first second. Who scrolls: the shell is an `AppLayout` (§3b,
151
+ Layouts), the one owner of the window's height; say for each surface
152
+ whether its content scrolls (a list, an article) or fills (a canvas, a
153
+ grid that scrolls itself), whether it has an inspector and how wide,
154
+ and what sits in a footer that must stay in view. Decide it before
155
+ the shell, not after a long page has pushed a button out of reach.
151
156
  - Density, empty states (§3a: what each surface says while its table is
152
157
  empty), error states.
153
158
  - What makes this app look like ITS domain and not another.
@@ -159,7 +164,8 @@ to design: Agent, Runs and Activity are tabs the OS draws on the window,
159
164
  and the app's settings — model, prompt, skills, connections, schedule —
160
165
  are the window's Settings tab, the same for every artifact. The keys
161
166
  `agent`, `runs` and `activity` are reserved; a surface may not take one.
162
- The starter `app/shell.jsx` is a placeholder; replace it first.
167
+ The starter `app/shell.jsx` is a placeholder; replace it first, and
168
+ keep it an `AppLayout`.
163
169
 
164
170
  What the OS does **not** own is asking the agent for something. Those
165
171
  tabs are where the founder goes to look back; the app is where they set
@@ -249,19 +255,125 @@ import { Button, IconButton, ButtonGroup, ButtonGroupSeparator, Toggle, ToggleGr
249
255
  InputGroup, PasswordInput, InputOTP, Slider, Image, FileInput, FileDrop, fileMatches, Combobox, Command, CommandDialog, Calendar, DatePicker, DateInput, DATE_PRESETS,
250
256
  parseDate, isDateString, toDateString, todayString, addDays, addMonths,
251
257
  startOfMonth, endOfMonth, dayOfWeek, formatDate, toLocalDate, firstDayOfWeek,
252
- Card, Notice, Badge, Kicker, Empty, Item, ItemGroup, Avatar, AvatarGroup,
258
+ Card, ActionCard, Notice, Badge, Kicker, Empty, Item, ItemGroup, Avatar, AvatarGroup,
253
259
  Sheet, Confirm, Tabs, TabPanel, Menu, ContextMenu, Popover, Tooltip, HoverCard,
254
260
  Breadcrumb, Pagination, Collapsible, Accordion, Carousel, ScrollArea,
255
261
  ResizablePanelGroup, ResizablePanel, ResizableHandle,
256
262
  Table, TableHeader, TableBody, TableFooter, TableRow, TableHead, TableCell, TableCaption,
257
263
  Spinner, Skeleton, Progress, Separator, Kbd, KbdGroup, AspectRatio,
258
264
  Stat, StatGroup, Delta, StatusDot, Legend, Meter, Distribution, Swatch, Steps,
259
- toast, Toaster, Depiction, Icon, ICON_NAMES, usePopoverPosition, panelClass, cx }
265
+ toast, Toaster, Depiction, Icon, ICON_NAMES, usePopoverPosition, panelClass, cx,
266
+ AppLayout, DocumentLayout, PageLayout }
260
267
  from "../components/ui"; // "./ui" from a component
261
268
  import { RecordSwitcher, LiveEmpty, LiveWork, liveWords, useFixture, FixtureNotice, isSample,
262
269
  Examples, useExamples } from "../components/parts";
263
270
  ```
264
271
 
272
+ - **Layouts** — who owns the window's height, and who scrolls. Every
273
+ design-first build of 2026-10-07 shipped a shell of `min-h-dvh` that
274
+ grew with its content: no pane scrolled on its own, and a footer or a
275
+ button after a long article sat past the end of the window, where
276
+ nothing could reach it. So the kit owns the window, once, and `npm
277
+ run check` refuses anything else that sizes by it (`viewport`, §6).
278
+
279
+ `AppLayout` is the app frame and the one viewport owner: the
280
+ outermost one is exactly the window's height; one inside another
281
+ fills the slot it is in instead, so there is never a second owner.
282
+ The shell is one. Slots and props:
283
+ `header` (the top bar, in view; it draws its own bottom border) ·
284
+ `navigation` (a rail from 768px, `navigationWidth` px, 176 by default;
285
+ below 768px a Sheet behind the menu button, titled `navigationLabel`;
286
+ a press on a link closes it) · `children`, the content, with
287
+ `contentMode` `scroll` (the default: its region scrolls) or `fill` (a
288
+ bounded column whose child scrolls itself: a canvas, a grid, a
289
+ spreadsheet), `contentLabel`, `contentClassName` (spacing and token
290
+ backgrounds only) and `scrollKey` (pass the route: when it changes the
291
+ content scrolls back to its top and the drawer closes) · `inspector`
292
+ (beside the content from `inspectorAt` md · lg · xl, lg by default, of
293
+ the window's width; `inspectorIn="frame"` counts the body between the
294
+ rail and the dock instead, 42 · 48 · 64 rem, so an agent dock that
295
+ takes a quarter of the window sends the inspector under the work
296
+ rather than squeezing it; `inspectorWidth` px, 360 by default, 240 to
297
+ 560; `inspectorLabel`) ·
298
+ `footer` (under the content, in view) · `height` viewport · parent.
299
+ Below `inspectorAt` there is no room for two columns: in `scroll` mode
300
+ the content and the inspector share one scroll, the inspector after
301
+ the content, so everything is reachable and nothing hides behind a
302
+ button; in `fill` mode the inspector is a bounded pane under the
303
+ content (at most 45% of the height) that scrolls on its own. A
304
+ surface that needs an inspector or a fill of its own returns an
305
+ `AppLayout` as its outermost element; inside the shell it fills the
306
+ content edge to edge (the content's padding drops for it):
307
+ ```jsx
308
+ <AppLayout
309
+ header={<EditorBar draft={draft} />}
310
+ inspector={<ReviewPanel notes={notes} />}
311
+ inspectorWidth={440}
312
+ footer={<SaveState saved={saved} />}
313
+ contentClassName="p-6"
314
+ contentLabel="Draft"
315
+ >
316
+ <DraftText draft={draft} />
317
+ </AppLayout>
318
+ ```
319
+ `DocumentLayout` is a page that flows, for print and export: no
320
+ height of its own, it sits in the content and the content scrolls it.
321
+ `toolbar` (held at the top, never printed), `width` prose · page (A4)
322
+ · letter · full, `paper` (a sheet on screen, plain in print), `align`
323
+ start · center, `label`. In print the frame lets go (no bound, no
324
+ navigation, header, inspector or footer) and the document flows onto
325
+ pages. Inside either, bound a box by its parent (`h-full`, `flex-1
326
+ min-h-0`) or by a size (`max-h-96`, `ScrollArea`), never by the window.
327
+
328
+ `PageLayout` is a screen's main area with an optional side column,
329
+ full height. The main is the column that scrolls; the side is the fixed
330
+ one. Roadmap's Today ended at
331
+ 680px in a 1240px window because it drew its own two-column grid
332
+ inside the scrolling content: only as tall as its words, the side's
333
+ divider stopped halfway and the bottom of the window was empty. Put it
334
+ inside an `AppLayout` with `contentMode="fill"` and no padding on the
335
+ content; the columns pad themselves, so the divider runs to the edges.
336
+ `side` (the side column) · `sideWidth` px (304; 220 to 560) · `sideAt`
337
+ md · lg · xl (the page's own width from which the side sits beside the
338
+ main, 42 · 48 · 64 rem: a measure of the page, so an open agent dock
339
+ does not squeeze it; narrower, the side goes under the main in one
340
+ scroll) · `mainLabel`, `sideLabel` · `padded` · `fill` (the main is a
341
+ flex column, so a child with `flex-1` grows into the height) ·
342
+ `className`, `mainClassName`, `sideClassName` (spacing, never a height).
343
+ `npm run check` refuses a screen that draws its own main + side
344
+ (`grid-cols-[minmax(0,1fr)_19rem]` and a ruled `<aside>`, rule `page`).
345
+
346
+ **What belongs in the side, and what never does** (the founder, looking
347
+ at a first run that was a short intro on the left and a long "Name it"
348
+ form in the right column: "this can only work if one column is fixed,
349
+ usually the 3rd column, and the middle one is scrolling"). The side is
350
+ the fixed column: it stays put while the main scrolls, so it is short
351
+ and never needs a scroll of its own.
352
+ - In the side: a summary, the next step, a few facts about the record,
353
+ a small panel (an allowance, "needs you" with a few lines), a short
354
+ list that says its bound (`items.slice(0, 5)` and "and 3 more").
355
+ - Never in the side: a form (`<form`, several `Field` or `Input`, a
356
+ `Textarea`, a paste box), a list that grows with the data, a shelf of
357
+ examples. They go in the main, where the page scrolls. A "Name it" or
358
+ "Paste a list" step that opens reveals its own card in the main flow;
359
+ it does not open a form in the side.
360
+ - The side's own scroll (thin) is a last resort for a window shorter
361
+ than the side. It is not how anything is meant to be read.
362
+ - Narrower than `sideAt`, the side goes under the main in one scroll.
363
+ `npm run check` rule `sidelong` refuses a `side` or an `<aside>` that
364
+ holds a form, a `Textarea`, three or more fields, or a `.map(` of data
365
+ that is not bounded by a `.slice(`. It reads the side's own markup and
366
+ the components defined in the app that the side draws (three levels
367
+ deep). It cannot see a block or kit component's insides, content that
368
+ arrives from props or context, or how long a list really is at run time;
369
+ the docs and review carry those. A screen:
370
+ ```jsx
371
+ <AppLayout header={<TopBar crumb={crumb} />} contentMode="fill">
372
+ <PageLayout side={<Projects />} fill>
373
+ <NeedsALook />
374
+ </PageLayout>
375
+ </AppLayout>
376
+ ```
265
377
  - `Button` — `variant` primary (one per surface, in the app's accent —
266
378
  say it: a Button with no `variant` is secondary) · secondary · quiet ·
267
379
  danger · link (inline text: no padding or height, wraps and truncates
@@ -369,6 +481,14 @@ import { RecordSwitcher, LiveEmpty, LiveWork, liveWords, useFixture, FixtureNoti
369
481
  — a table that scrolls inside itself on a phone.
370
482
  - `Card` (`padding` md · sm · none — none for a table or rows that run
371
483
  to the border, never `p-0!`; `titleSize` md · lg for a 20px title),
484
+ `ActionCard` (one step the member takes: `icon`, `title`,
485
+ `description`, `children`, `status` = `{ tone, children }` above the
486
+ one full-width `action`; in a row it stretches to the row's height and
487
+ pins its status and action to the bottom, so the buttons line up (`fit`
488
+ is the old only-as-tall-as-its-words, for one lone card; never
489
+ `self-start` on a card in a row) — a connect-and-first-read card, "Add one person", "Bring in a
490
+ file". A screen's boxes are Card, ActionCard or Notice, never a
491
+ hand-drawn bordered div),
372
492
  `Notice` (tone neutral · info · success · warning · danger),
373
493
  `Badge` (tone neutral · primary · success · warning · danger · info;
374
494
  `variant` label — small caps · soft — the case as written, every tone
@@ -395,7 +515,9 @@ import { RecordSwitcher, LiveEmpty, LiveWork, liveWords, useFixture, FixtureNoti
395
515
  `Meter value max unit target thresholds` (a role=meter; over the limit
396
516
  turns danger; `direction` higher · lower picks the tone against the
397
517
  target; `valueTone`; `targetMark={false}`; tone `muted` for a plain
398
- grey share) — numbers and states, never a hand-drawn tile or bar.
518
+ grey share; `compact` the bar (or ring) alone, its label and numbers
519
+ kept for screen readers and as the tooltip — a labelled Meter in a box of
520
+ 8rem or less must be `compact`) — numbers and states, never a hand-drawn tile or bar.
399
521
  `Delta hideValue` is the arrow alone; `StatusDot` and Legend items take
400
522
  `hue` (1..5) for a category. `Distribution segments={[{ label, value,
401
523
  tone, hue }]} legend label size` (thin · md) — parts of one whole as
@@ -990,6 +1112,130 @@ the check refuses a raw `INSERT INTO` anywhere outside `lib/`, and, in
990
1112
  an app on its own tables, any SQL that writes in the app's code (§6,
991
1113
  `agent`).
992
1114
 
1115
+ ### Declared actions — `makersclaw.json` `actions` (0.8.1)
1116
+
1117
+ Every write a screen makes is a declared action: the screens call it by
1118
+ name with `runAction({ name, args })`, and the app's agent calls the same
1119
+ name as one of its tools, run by the platform's one runner. Once an app
1120
+ declares any, its agent can write no other way, so `npm run check`
1121
+ (§6, `actions`) fails a screen write that is not one: an undeclared
1122
+ name, a one-row write (`insertRow`, `updateRow`, `moveRow`, `deleteRow`,
1123
+ `saveSetting`: make it a function) and a company brain write from
1124
+ `lib/brain.js` (erase, confirm and merge stay a person's press).
1125
+
1126
+ ```json
1127
+ "actions": [
1128
+ {
1129
+ "name": "add_people",
1130
+ "description": "Add up to 100 people, each linked to their company.",
1131
+ "input": {
1132
+ "type": "object",
1133
+ "properties": {
1134
+ "people": {
1135
+ "type": "array", "maxItems": 100,
1136
+ "items": { "type": "object", "properties": {
1137
+ "name": { "type": "string" }, "email": { "type": "string" },
1138
+ "company": { "type": "string" }, "company_domain": { "type": "string" } },
1139
+ "required": ["name"] }
1140
+ },
1141
+ "list_id": { "type": "string" }
1142
+ },
1143
+ "required": ["people"]
1144
+ },
1145
+ "brain": {
1146
+ "each": "people",
1147
+ "writes": [
1148
+ { "as": "company", "kind": "company", "when": "company", "fields": { "name": "company", "domain": "company_domain" } },
1149
+ { "as": "person", "kind": "contact", "fields": { "name": "name", "email": "email", "company_name": "company" } }
1150
+ ],
1151
+ "links": [{ "from": "person", "to": "company", "type": "works_at" }]
1152
+ },
1153
+ "sql": "crm_people_added"
1154
+ },
1155
+ { "name": "make_list", "description": "Make a list of people or companies.",
1156
+ "input": { "type": "object", "properties": { "name": { "type": "string" } }, "required": ["name"] },
1157
+ "sql": "crm_make_list" }
1158
+ ]
1159
+ ```
1160
+
1161
+ - `input` is a JSON Schema object (type, properties, required, items,
1162
+ enum, min/max, descriptions); the agent reads it whole, so keep it
1163
+ under 12,000 characters.
1164
+ - `sql` is a function `<name>(args jsonb) returns jsonb` in the app's
1165
+ schema, run as the app, with the member set, after the `brain` steps.
1166
+ - `brain` writes company records as the member and the app: each write
1167
+ is `{ as, kind, fields }`, each field read from an input key (`"name"`:
1168
+ the item's, with `each`; `"$.list_id"`: the input's top level;
1169
+ `{ "value": "lead" }`: a constant). An empty value is left out, never
1170
+ cleared. `when` writes it only when that key has a value; `each` runs
1171
+ the writes once per item of a list of at most 100; `links` join two
1172
+ writes (`from`/`to` an `as`, or `{ "id": <key> }`, a record id the
1173
+ input holds) by a link type the kind declares. Every kind is one the
1174
+ app writes (`brain.writes`), every field one of its fields. The `sql`
1175
+ function gets the input plus `records`: for each `as`, `{ id, created
1176
+ }` (a list in item order with `each`; null where `when` skipped it).
1177
+ If the function refuses, the records the call made are taken back.
1178
+ - A write with `"id"` changes the record that input key names (an edit,
1179
+ never a create), as the member and the app may: one they cannot both
1180
+ read, or of another kind, is not found and nothing is written.
1181
+ `"if_version"` names a key holding the version the screen read
1182
+ (refused `changed` when it moved on); `{ "value": null }` empties a
1183
+ field, and `"clear"` names a key listing fields to empty (an array of
1184
+ strings whose `items.enum` are among the write's fields); `{ "now":
1185
+ true }` is the time of the call. If a later step fails, the fields it
1186
+ changed get their old values back.
1187
+ - A link with `"op": "remove"` takes one off (removals run first, so one
1188
+ call moves a link), and an action may be `links` only, with no
1189
+ `writes`. Archive is an edit of the kind's own field (`archived_at`:
1190
+ `{ "now": true }`, back with `{ "value": null }`); erase and merge stay
1191
+ a person's press, from `lib/brain.js`.
1192
+
1193
+ ```json
1194
+ { "name": "move_deal", "description": "Move a deal to a stage and another company.",
1195
+ "input": { "type": "object", "properties": {
1196
+ "deal_id": { "type": "string" }, "version": { "type": "integer" }, "stage": { "type": "string" },
1197
+ "from_company": { "type": "string" }, "to_company": { "type": "string" } },
1198
+ "required": ["deal_id", "stage"] },
1199
+ "brain": {
1200
+ "writes": [{ "as": "deal", "kind": "deal", "id": "$.deal_id", "if_version": "$.version",
1201
+ "fields": { "stage": "$.stage", "stage_changed_at": { "now": true }, "closed_at": { "value": null } } }],
1202
+ "links": [
1203
+ { "from": "deal", "to": { "id": "$.from_company" }, "type": "for_company", "op": "remove" },
1204
+ { "from": "deal", "to": { "id": "$.to_company" }, "type": "for_company" }] },
1205
+ "sql": "crm_deal_moved" }
1206
+ ```
1207
+
1208
+ - `agent: false` only for a write the agent must never make.
1209
+ - `references/actions.md` says, per action, when and why: never a recipe.
1210
+
1211
+ ### Shipped automations — `makersclaw.json` `automations` (0.8.1)
1212
+
1213
+ An app may ship automations: flows the platform runs for it on a schedule
1214
+ or by hand, made of its own declared actions. List them in
1215
+ `makersclaw.json`, under `automations`, next to `actions`. The store ships
1216
+ the same list as `seeds.automations` in `store.json`.
1217
+
1218
+ - Each entry is a definition in the platform's automation format (format
1219
+ 1: `key`, `name`, `trigger`, `inputs`, `settings`, `steps`), exactly as
1220
+ the automations blocks draw and save one.
1221
+ - An `action` step names one of the app's declared `actions` (its `app`
1222
+ stays out: an app's automation runs its own app's actions).
1223
+ - `replaces_wake` is the one field that is not part of the definition. It
1224
+ is the name of a legacy wake (an older scheduled job of the app, in its
1225
+ `store.json` `seeds.wakes`) that this automation takes over: when the app
1226
+ is installed or updated the wake is switched off, so the job never fires
1227
+ twice. Leave it out for a new automation. Name a scheduled wake (advance
1228
+ or review), never an event wake, and one automation per wake. The
1229
+ app's `store.json` lists the same name.
1230
+ - At most 20 automations, keys unique.
1231
+
1232
+ `npm run check` runs the list through the platform's own validator (rule
1233
+ `automations`), so a flow the platform would refuse at install is refused
1234
+ at build. It checks the shape, the kinds of step, the expressions and that
1235
+ every `action` step names a declared action. Which wakes exist and which
1236
+ kinds of account a `tool` step may ask for are checked where the whole
1237
+ package is known (the store's publish).
1238
+
993
1239
  ### Door — `lib/door.js` (browser, both modes)
994
1240
 
995
1241
  The app's own tables, read and written from the browser through the
@@ -1049,7 +1295,10 @@ whenLanded() resolves once those reads have landed
1049
1295
  Actions did. A slow save never lands after the newer one.
1050
1296
  - A write that answers ok calls `dataChanged()`: every hook on the page
1051
1297
  reads again, the brain's too. When the next step needs the new rows
1052
- (open the row just made), `await whenLanded()` first.
1298
+ (open the row just made), `await whenLanded()` first. Use
1299
+ `afterWrite(write)`: it answers with the write's answer after the hooks
1300
+ hold the new rows; a record page asks `useNotFound(found, { loading })`
1301
+ before it says "not found".
1053
1302
  - `loading` is true until a hook's first answer, and again when its
1054
1303
  options change. A re-read keeps the last rows, and `loading` false,
1055
1304
  until the new ones land; each answer is a new array. A failed re-read
@@ -1274,6 +1523,14 @@ import { platform } from "../lib/platform"; // or the named functions
1274
1523
  platform.me() GET _claw/me → { artifact: { id, name, vehicle, status, home }, user: { id, email }, blueprint, desk_origin }
1275
1524
  platform.ask({ text, row, how, job, list, surface, sessionId, open })
1276
1525
  POST _claw/ask → { ok, request, desk_origin }, and the column opens on it
1526
+ platform.llm(input, { system, schema, maxTokens, tier, task, signal })
1527
+ POST _claw/llm → { ok: true, text } | { ok: true, data } | { ok: false, error, code } (Calling a model)
1528
+ platform.library.collections({ q, shelf }) GET _claw/library/collections → { collections } (Showing the Library)
1529
+ platform.library.collection(id) GET _claw/library/collections/<id> → { collection }
1530
+ platform.library.items(id, { q, tag, cursor, limit }) GET _claw/library/collections/<id>/items → { items, next_cursor, total, preview_only }
1531
+ platform.library.rows(id, { q, filters, cursor, limit })
1532
+ GET _claw/library/collections/<id>/rows → { rows, next_cursor, total, preview_only }
1533
+ platform.library.item(id) GET _claw/library/items/<id> → { item, file_url?, text_excerpt? }
1277
1534
  platform.requests() GET _claw/requests → { requests, run, desk_origin }
1278
1535
  platform.requests({ id }) GET _claw/requests?id=<id> → { request }
1279
1536
  platform.stopRequest(id) POST _claw/requests/<id>/stop → { ok, request }
@@ -1282,6 +1539,24 @@ platform.surfaceOfPath(pathname) the <key> of /s/<key> in
1282
1539
  platform.reportError({ message, stack, url, source }) POST _claw/events
1283
1540
  platform.startJob(message, { sessionId, onEvent }) POST _claw/chat → streams session · delta · tool · done · error (legacy)
1284
1541
  platform.cancelJob(sessionId) POST _claw/cancel (legacy)
1542
+
1543
+ // The kit (0.8.1) — what the kit's blocks draw; lib/hooks.js follows each one
1544
+ platform.jobs() GET _claw/jobs → { app: { status, live }, jobs: [{ id, name, kind, topic, does, cron, tz, words,
1545
+ enabled, next_run_at, last_run_at, last_run, plan }], budget, credits, may: { run, switch, pause } }
1546
+ platform.setJob(id, { enabled }) PATCH _claw/jobs/<id> → { ok, job } (not_allowed 403 · unknown_job 404)
1547
+ platform.runNow(wakeId) POST _claw/run → { ok, run_id, wake } (spends: its price on the button)
1548
+ platform.pauseApp() · platform.resumeApp() POST _claw/pause · _claw/resume → { status } (the Live switch)
1549
+ platform.runs({ job, limit }) GET _claw/runs → { runs: [{ id, title, state, wake_id, job, trigger, by, number,
1550
+ started_at, ended_at, duration_ms, credits, report, status }], overview }
1551
+ platform.run(id) GET _claw/runs/<id> → { run, steps: [{ label, status }], text, needs }
1552
+ platform.activity({ row, surface, since, limit }) GET _claw/data/activity → { rows: [{ id, at, action, surface, row_ref, detail, data, by }] }
1553
+ platform.connections() GET _claw/connect → { connections: [{ key, label, required, connected, accounts, category, category_label }] }
1554
+ platform.connectLink(key) POST _claw/connect → { ok, key, label, connected, url } (outside the desk)
1555
+ platform.openConnections(key) ask the desk to open its connections panel for that need → true when the desk was asked
1556
+ platform.agentKit() GET _claw/agent → { own_skills: [{ name, title, when }], skills: [{ name, installed }],
1557
+ actions: [{ name, description, agent }], … }
1558
+ platform.llmEstimate(input, { system, schema, maxTokens, tier, task })
1559
+ POST _claw/llm, estimate: true → { ok: true, estimate: { credits, credits_max } } (never sent to a model, never charged)
1285
1560
  ```
1286
1561
 
1287
1562
  A request, as `ask` and `requests` hand it back: `{ id, title, words,
@@ -1297,13 +1572,32 @@ didnt_finish. `line` is the one line every screen shows for it
1297
1572
  show it as it is, never a status word of your own. `app_session_id` is
1298
1573
  set only on your own requests.
1299
1574
 
1300
- Named exports: `me, ask, requests, stopRequest, openRequest,
1301
- surfaceOfPath, startJob, cancelJob, reportError, platform`. That is the
1302
- whole list. Note what is **not** there: the runs, the chat history, Run
1303
- now, Pause / Resume. Those are MONITORING and they are the OS's — the
1304
- window's tabs and title bar — so an app never calls `_claw/agent`,
1305
- `_claw/runs`, `_claw/run`, `_claw/pause` or `_claw/resume`. Asking is the
1306
- opposite thing, and it belongs here (`ask()` and `useJob`, below).
1575
+ Named exports: `me, ask, llm, llmEstimate, library, requests,
1576
+ stopRequest, openRequest, threads, thread, surfaceOfPath, startJob,
1577
+ cancelJob, reportError, jobs, setJob, runNow, pauseApp, resumeApp, runs,
1578
+ run, activity, connections, connectLink, openConnections, agentKit,
1579
+ platform`. That is the whole list.
1580
+
1581
+ Up to 0.8.1 the runs, Run now, Pause / Resume and the agent's settings
1582
+ were not here: they were MONITORING, and the OS drew them as the window's
1583
+ tabs so that every app showed its agent's work in one look. The kit
1584
+ (0.8.1) moved that one look into the template's blocks (The agent and AI
1585
+ kit, below), so the app now shows its agent's work itself, beside the
1586
+ rows the work wrote, and calls `_claw/jobs`, `_claw/runs`, `_claw/run`,
1587
+ `_claw/pause`, `_claw/resume`, `_claw/agent` and `_claw/connect` through
1588
+ these wrappers. The window's tabs stay, as the full history. Two things
1589
+ never move into the app: **the account sign-in and money** stay on the
1590
+ desk. The agent's questions are answered in the app (`answer`), and the
1591
+ yes is given in the app too, but never by the app: it is a press in a
1592
+ Makersclaw-held frame (`approval`, the `approval` block). The door decides
1593
+ who may press what (`may` on `jobs`): hide what the member may not press,
1594
+ and the door refuses it anyway.
1595
+ Asking is its own thing, and it belongs here too (`ask()` and `useJob`,
1596
+ below). `llm()` is neither: one call to a model, answered in the page
1597
+ (Calling a model, below). It is the one wrapper that resolves the platform's answer
1598
+ as it is, `{ ok: true, text }` and not `{ ok: true, status, data }`.
1599
+ `library` is neither asking nor monitoring: it reads what Makersclaw
1600
+ keeps, read only (Showing the Library, below).
1307
1601
  `requests` is not monitoring either: it is this app's asks in flight, so
1308
1602
  an empty surface can show the work coming (§3a). `startJob` and
1309
1603
  `cancelJob` are the 0.3.x door to the same work, kept so `useJob` can
@@ -1316,10 +1610,13 @@ that exact origin — never `"*"` — and only while the app is framed.
1316
1610
 
1317
1611
  ### Hooks — `lib/hooks.js` ("use client")
1318
1612
 
1319
- Four hooks: a generic fetch over one `_claw` route, the app's identity,
1320
- a job, and the app's requests. Each owns fetching, polling (while the
1321
- tab is visible; once a minute while `unavailable`), streaming and cleanup
1322
- on unmount. A surface renders what comes back and owns every pixel.
1613
+ A generic fetch over one `_claw` route, the app's identity, a job, the
1614
+ app's requests, a model call, five that read the Library, the app's own
1615
+ chat, and the kit's eight (0.8.1). Each owns
1616
+ fetching, polling (while the tab is visible; once a minute while
1617
+ `unavailable`; the Library's read once and have nothing to poll),
1618
+ streaming and cleanup on unmount. A surface renders what comes back and
1619
+ owns every pixel.
1323
1620
 
1324
1621
  ```js
1325
1622
  useClaw(path, { every, enabled = true }) → { data, error, loading, unavailable, reload }
@@ -1328,9 +1625,50 @@ useJob() → { running, status, queued, que
1328
1625
  steps, text, progress, error, sessionId, requestId, request, finishedAt,
1329
1626
  start, cancel, reset, open }
1330
1627
  useRequests({ surface, job, every = 5000 }) → { requests, live, run, loading, error, unavailable, reload, open, stop }
1628
+ useLlm() → { run, loading, result, error, unavailable } (Calling a model)
1629
+ useLibraryCollections({ q, shelf }) → { collections, loading, error, code, unavailable, reload } (Showing the Library)
1630
+ useLibraryCollection(id) → { collection, loading, error, code, unavailable, reload }
1631
+ useLibraryItems(id, { q, tag, limit }) → { items, total, previewOnly, hasMore, loading, loadingMore, error, code, unavailable, loadMore, reload }
1632
+ useLibraryRows(id, { q, filters, limit }) → { rows, total, previewOnly, hasMore, loading, loadingMore, error, code, unavailable, loadMore, reload }
1633
+ useLibraryItem(id) → { item, fileUrl, textExcerpt, loading, error, code, unavailable, reload }
1634
+ useAgentThread({ row, how, job, key, view }) → { sessionId, state, needs, turns, view, pending, place, request, sending, loading, error,
1635
+ code, unavailable, send, stop, answer({ optionId, text } | { answers }), openOnDesk, newChat,
1636
+ openSession(sessionId), reload } (the agent-chat block)
1637
+ useAgentPane({ row, how, job, key }) → useAgentThread with the desk sidebar's view, plus { chats: { items, loading, error, unavailable },
1638
+ callDetail(callId), openRequest(id) } (the agent-pane block, D27; GET _claw/threads/<session>?view=1)
1639
+ useThreadList({ every = 30000 }) → { items: [{ sessionId, requestId, title, mark, at }], loading, error, unavailable, reload } (the pane's Chats list)
1331
1640
  jobFromRequest(request) → what useJob shows for one request (pure; for tests)
1641
+
1642
+ // The kit (0.8.1): each also returns { loading, error, code, unavailable, reload }
1643
+ useJobs({ every = 30000 }) → { jobs, app, budget, credits, may, busy, appBusy, runNow(id), setEnabled(id, on), pause(), resume() }
1644
+ useRuns({ job, limit = 20, every = 30000 }) → { runs, overview } every 5 s while a run is going
1645
+ useRun(id) → { run, steps, text, needs } every 2.5 s while it runs; nothing without an id
1646
+ useNeedsYou({ every = 8000 }) → { items: [{ id, request, kind, text, title, at, via, options, free, needsAt }], working, open(item), answer(item, { optionId, text }), takeBack(item), stop(request) }
1647
+ useApproval(requestId) → { approval, state, always, fallback, frame: { src, ref, title }, height } (the approval block; GET _claw/requests/<id>/approval)
1648
+ useActivity({ row, surface, since, limit = 50, agent = false, every = 20000 })
1649
+ → { rows } agent: true keeps the agent's lines
1650
+ useConnections({ every }) → { connections, connecting, connect(key) → { opened: "desk" | "tab" | false, error? } }
1651
+ useAgentKit() → { skills: [{ name, title, when, from: "app" | "added", installed }], tools: [{ name, description }] }
1652
+ useLlmAction({ input, system, schema, tier, task, maxTokens, estimate = true })
1653
+ → { estimate: { credits, credits_max } | null, estimating, run(), result, loading, error, unavailable, reset() }
1654
+ needsYouItem(request) · agentKitOf(data) · connectAccount(key) the kit hooks' pure parts (for tests)
1655
+
1656
+ // The automations engine (lib/automations.js, re-exported here): an app's own automations, from its own page
1657
+ useAutomations({ every = 30000 }) → { automations, busy, creating, setStatus(id, on), create(definition, { note, goLive }) } every 5 s while one runs
1658
+ useAutomation(id) → { automation, live, draft, definition, versions, estimate, estimateDraft, runs, busy: "save" | "keep" | "live" | "test" | null,
1659
+ save(definition), keep(), setLive(on), test(inputs) } resolve the platform's answer; a refusal carries `problems`
1660
+ useAutomationRun(runId) → { run, steps, stepsVisible, automation, definition, detail } every 2.5 s while it runs
1332
1661
  ```
1333
1662
 
1663
+ The kit's hooks poll only while the page is shown (not behind the
1664
+ window's other tabs, not in a hidden browser tab; coming back looks at
1665
+ once), look once a minute while their door is missing, abort on unmount
1666
+ and never throw. A missing door is `unavailable` with `error` null: a
1667
+ quiet "not connected yet". `useJobs`' Run now makes every `useRuns`,
1668
+ `useRequests` and `useNeedsYou` on the page look at once. `useActivity`
1669
+ here is the kit's: polled, with `row` and `agent`; `lib/door.js`'s
1670
+ `useActivity` (§5 Door) reads the same lines once.
1671
+
1334
1672
  `useRequests` is the work asked of this app's agent — from a screen or
1335
1673
  from the desk, by anyone in the workspace. `requests` is every one the
1336
1674
  gateway returned (the live ones and those that ended in the last day);
@@ -1344,10 +1682,11 @@ while the App tab is on screen (behind the window's other tabs it asks
1344
1682
  nothing; coming back looks at once); a start through `useJob` on the
1345
1683
  same page makes it look at once. Hand it to `LiveEmpty` (§3a).
1346
1684
 
1347
- There is no chat or runs hook: the OS draws those tabs. A domain
1348
- surface that wants a slice of the activity (a row's history beside the
1349
- row, say) reads it with `loadActivity`: on the server in a server app,
1350
- or with `useActivity` (`lib/door.js`, §5 Door) from the browser.
1685
+ Up to 0.8.1 this said there was no chat or runs hook, because the OS
1686
+ drew those tabs. Since the kit there are both, and the blocks that draw
1687
+ them: a record's history beside the record is the `activity-log` block
1688
+ over `useActivity({ row })`; on the server in a server app it is
1689
+ `loadActivity`.
1351
1690
 
1352
1691
  ### Commissioning work — `useJob()`
1353
1692
 
@@ -1504,6 +1843,506 @@ if (!r.ok) setError(r.error); // r.code: needs_answer, queue_fu
1504
1843
  It resolves once the platform took the ask (`{ ok: true, data: {
1505
1844
  request, desk_origin } }`) or refused it; it never waits for the work.
1506
1845
 
1846
+ ### The agent and AI kit — blocks (0.8.1)
1847
+
1848
+ The app shows its agent's work and its AI features itself, in its own
1849
+ look: a chat beside the record, the schedule and its runs, what waits on
1850
+ the member, the price before a press. Up to 0.8.1 the OS drew most of
1851
+ this as the window's tabs, so every app looked the same; now the same
1852
+ look lives in these blocks, and the tabs stay as the full history. Each
1853
+ block is `makersclaw add <name>`, reads nothing itself, and takes the
1854
+ hook's answer as props (a block never imports `lib/`):
1855
+
1856
+ - `agent-chat` (`AgentChat`) — the app's own chat with its agent, about
1857
+ the app or one record. `useAgentThread`.
1858
+ - `ask-bar` (`AskBar`) — one line to ask, with chips; it starts the
1859
+ thread and opens the chat. `useAgentThread`.
1860
+ - `needs-you` (`NeedsYou`, `QuestionBox`, `WaitingYes`, `AgentWorking`) —
1861
+ what waits on this member (a question answered in place, a yes through
1862
+ the `approval` block), the frozen "Ready to send" with Take back, the
1863
+ working strip with Stop. `useNeedsYou`.
1864
+ - `approval` (`Approval`) — the yes, given in the app: the app's own card
1865
+ (what goes out, to whom, the cost) over a Makersclaw-held press frame in
1866
+ the app's theme that app code cannot script, with "Always allow this
1867
+ kind". `useApproval`.
1868
+ - `activity-log` (`ActivityLog`) — who did what, newest first, the
1869
+ agent as an author; with `row`, one record's timeline. `useActivity`.
1870
+ - `agent-marks` (`AgentMark`, `CallMark`, `Byline`) — the agent's mark,
1871
+ a model call's mark, "By the agent, on Priya's ask". No hook.
1872
+ - `schedule-card` (`ScheduleCard`) — one job: its schedule in words, its
1873
+ last run, next run, Run now with its price, the on/off switch.
1874
+ `useJobs`.
1875
+ - `run-history` (`RunHistory`, `RunAccount`, `RunOverview`) — the runs,
1876
+ one run's account, the overview against the week's cap. `useRuns`,
1877
+ `useRun`.
1878
+ - `workflow-view` (`WorkflowView`) — the job as a graph: Trigger → steps
1879
+ → result, the run picker, Live, Trigger manually, its runs beside.
1880
+ `useJobs`, `useRuns`, `useRun`.
1881
+ - `suggestion` (`FieldSuggestion`, `InlineSuggestion`, `TextSuggestion`,
1882
+ `Pencil`, `SuggestionGroup`, `Looking`) — a value the agent proposes,
1883
+ in pencil until kept. No hook: Keep and Drop call the app's declared
1884
+ actions (`runAction`).
1885
+ - `source-receipt` (`SourceReceipt`) — where a value came from, as a
1886
+ clipping. No hook: the source is app data.
1887
+ - `agent-column` — a column the agent fills, each answer with its state,
1888
+ how sure it is, and its receipt. The app's rows (`lib/data.js`).
1889
+ - `record-grid` — a virtualised grid of many records. The app's rows
1890
+ (`lib/data.js`).
1891
+ - `ai-action` (`AiAction`) — one model call on what the screen holds,
1892
+ its price on the button, the answer in place with Use. `useLlmAction`.
1893
+ - `cost` (`CostTag`, `CostConfirm`, `Allowance`) — the price on a
1894
+ control, the confirm before a big spend, the week's allowance.
1895
+ `useLlmAction`'s estimate, `useJobs`' budget.
1896
+ - `agent-changes` (`AgentChanges`) — the receipt of one ask, with Undo
1897
+ this ask. `useActivity({ agent: true, since })`.
1898
+ - `connect-card` (`ConnectCard`, `ConnectRow`) — the app's accounts,
1899
+ live or not, Connect. `useConnections`.
1900
+ - `agent-kit` (`AgentKit`) — what the agent knows and what it can do.
1901
+ `useAgentKit`.
1902
+ - `library-shelf` (`LibraryShelf`) — "Start from a template": a Library
1903
+ collection's items. `useLibraryItems`.
1904
+
1905
+ The rules:
1906
+
1907
+ 1. **Use the kit.** Never redraw a chat, a schedule, a run list, a
1908
+ needs-you queue, a suggestion or a price tag by hand: the block is
1909
+ the one look every app shares, and it grows in the template.
1910
+ 2. **The sign-in and money stay on the desk; the yes is the press
1911
+ frame's.** The agent's question is answered in the app (`QuestionBox`,
1912
+ `answer`). The agent's yes is the `approval` block: you draw what goes
1913
+ out, the frame holds the press, and when it cannot load the block falls
1914
+ back to "Waiting for your yes on the desk" and opens it
1915
+ (`openRequest`). Connect opens the desk's connections panel; topping up
1916
+ opens the desk. Never an Approve, Yes or Send of your own that gives
1917
+ the yes, a password field or a payment form in the app.
1918
+ 3. **Cost on every control that spends.** Run now, Read now, Enrich,
1919
+ Summarize: the price is on the button (`CostTag`, `useLlmAction`'s
1920
+ estimate) before the press, and a big spend asks first
1921
+ (`CostConfirm`).
1922
+ 4. **The door decides who may press.** `useJobs().may` says who may run,
1923
+ switch and pause; hide what the member may not press. The door
1924
+ refuses it anyway.
1925
+ 5. **A missing door is quiet.** On a claw from before a door the hook is
1926
+ `unavailable`: the block shows its empty state ("No runs yet", "Not
1927
+ set up"), never an error.
1928
+ 6. **Its own width decides its layout.** Every kit block lays itself out
1929
+ by `@container`, at 320, 368, 800 and 1280 px of its own width; give
1930
+ it the width, never a viewport breakpoint of yours.
1931
+
1932
+ ### Calling a model — `llm()`
1933
+
1934
+ `llm()` is for one-shot text work on what is on screen: sort these
1935
+ mails, draft this reply, translate this note, summarise this thread,
1936
+ pull the date out of this line. The answer comes back in the page, and
1937
+ the screen does what it likes with it.
1938
+
1939
+ **`llm()` for one-shot text work on what the screen holds; `ask()` for
1940
+ work that needs tools, the workspace, or more than one step.** Finding
1941
+ leads, reading the Wiki, writing rows for forty threads, anything that
1942
+ should show in the agent column and the Requests list: that is `ask()`.
1943
+ The app's agent does it, with its tools. `llm()` has none: it sees the
1944
+ words you hand it and nothing else.
1945
+
1946
+ ```js
1947
+ "use client";
1948
+ import { updateRow } from "../lib/actions";
1949
+ import { llm } from "../lib/platform";
1950
+
1951
+ // Text.
1952
+ const r = await llm(thread.body, {
1953
+ system: "Draft a short, warm reply from the founder. Plain text, no greeting.",
1954
+ task: "draft-reply",
1955
+ });
1956
+ if (r.ok) setDraft(r.text); // r.error says why not
1957
+
1958
+ // Data: a schema in, an answer checked against it out.
1959
+ const SORT = {
1960
+ type: "object",
1961
+ required: ["label", "urgent"],
1962
+ properties: { label: { enum: ["sales", "support", "billing", "other"] }, urgent: { type: "boolean" } },
1963
+ };
1964
+ const s = await llm(`From: ${mail.from}\nSubject: ${mail.subject}\n\n${mail.body}`, { system: "Sort this mail.", schema: SORT, task: "sort-mail" });
1965
+ if (s.ok) await updateRow({ source: "mail", id: mail.id, patch: { label: s.data.label, urgent: s.data.urgent } });
1966
+ ```
1967
+
1968
+ `data` is the model's JSON as it came: **a key your schema does not name
1969
+ is kept**. Read the keys you asked for, as above, and do not spread
1970
+ `data` into a row.
1971
+
1972
+ `llm(input, opts)` takes:
1973
+
1974
+ - `input` — what to work on: a string, or a conversation, `[{ role:
1975
+ "user" | "assistant", content }]`: at most 100 messages, none empty,
1976
+ the last one the user's (the one to answer). Required. An empty one
1977
+ asks nothing of the platform and resolves `bad_input`.
1978
+ - `system` — how to go about it, at most 8,000 characters.
1979
+ - `schema` — a JSON Schema for the answer, an object, at most 16 KB
1980
+ once written out. The answer then comes back as `data`, checked
1981
+ against it, not as `text`. If the model's reply misses, the platform
1982
+ sends it back once with what was wrong; a second miss is
1983
+ `schema_mismatch`. The platform runs your schema on the model's words,
1984
+ so what it may hold is bounded (below).
1985
+ - `maxTokens` — the answer's ceiling, a whole number, 1 or more. 1,024
1986
+ unless you say; over 4,096 is cut to 4,096. (It travels as
1987
+ `max_tokens`.)
1988
+ - `tier` — `"fast"` (the default) or `"smart"` for the harder job. An
1989
+ app never names a model. `smart` costs more and is slower: a long
1990
+ answer from it can run into the 60 second limit, so keep `maxTokens`
1991
+ modest there.
1992
+ - `task` — a short label for the usage line, `a-z`, `0-9` and `-`, at
1993
+ most 40 characters (`"sort-mail"`).
1994
+ - `signal` — an `AbortSignal`. An abort resolves `{ ok: false, aborted:
1995
+ true }`.
1996
+
1997
+ **What a schema may hold.** Write it out as a tree, small. The call
1998
+ refuses a schema with:
1999
+
2000
+ - `pattern` or `patternProperties` (`bad_input`): a regular expression
2001
+ run on a model's words can hang the platform. Use `enum`, `format` or
2002
+ length bounds.
2003
+ - `$ref`, `$defs` or `definitions` (`bad_input`; `$dynamicRef` and
2004
+ `$recursiveRef` too): each reference is checked in full where it is
2005
+ used, so a few can mean a tree of any size. Write the shape out where
2006
+ it is used.
2007
+ - nesting deeper than 20 levels, a list inside a list counted
2008
+ (`bad_input`).
2009
+ - more than 1,000 parts (`too_large`): every object in it, every `enum`
2010
+ value and every type listed in a `type` array. A real answer's schema
2011
+ is a few dozen.
2012
+ - a schema it cannot read, such as a `type` it does not know
2013
+ (`bad_input`).
2014
+
2015
+ A reply with so many values that checking it against the schema would
2016
+ cost too much is a miss like any other (`schema_mismatch`, and the
2017
+ model is told why): ask for fewer values, or a smaller schema. Make the
2018
+ root an object (`type: "object"`): providers' structured answers mostly
2019
+ want one, and when one refuses the format the platform asks again in
2020
+ words alone, which is less sure. Everything else in JSON Schema is let
2021
+ through.
2022
+
2023
+ It resolves, and never throws:
2024
+
2025
+ - `{ ok: true, text }` — no schema.
2026
+ - `{ ok: true, data }` — with a schema.
2027
+ - `{ ok: false, error, code, status }` — a refusal, as the platform
2028
+ sent it. Branch on `code`. **Show `error` as it is for the codes that
2029
+ speak to the member, and a plain line of your own for the rest.** The
2030
+ rest speak to you, the developer ("schema uses "pattern""), and a
2031
+ member should not read them.
2032
+
2033
+ Words for the member, shown as they are:
2034
+
2035
+ - `no_credits` (402): the workspace's wallet is empty, the workspace
2036
+ is suspended, or the Free plan's daily limit is used up.
2037
+ `member_cap` (402): the member's monthly spend cap is used up.
2038
+ `app_cap` (402): this app's weekly cap is used up. Say so and stop;
2039
+ do not retry.
2040
+ - `rate_limited` (429): 30 calls a minute per member. Wait a moment,
2041
+ then again.
2042
+ - `model_failed` (502), `try_again` (503) and `failed` (500): the
2043
+ model, the membership check or the platform could not answer just
2044
+ now. Try again.
2045
+ - `timeout` (504): a call is held to 60 seconds, a schema retry
2046
+ included, and one the clock cuts is still charged. Ask for less (a
2047
+ lower `maxTokens`, a shorter input) rather than the same again.
2048
+ - `no_member_identity` (401) and `not_a_member` (403): the page is not
2049
+ running in a member's own session (`no_member_identity` says to open
2050
+ the app from the desk again), or the member was removed from the
2051
+ workspace.
2052
+
2053
+ Words for you, not shown:
2054
+
2055
+ - `bad_input` (400): the call itself is wrong; fix the code.
2056
+ - `too_large` (413): the body is over 128 KB, `system` over 8,000
2057
+ characters, `schema` over 16 KB or 1,000 parts, or `input` over 100
2058
+ messages. Send less.
2059
+ - `schema_mismatch` (422): the model could not fit the schema, twice;
2060
+ `error` names where it missed. Loosen the schema or ask for less.
2061
+ - `cross_origin` (403): not the app's own page (a typed URL, a form
2062
+ post).
2063
+ - `not_configured` (503): the platform has no model to give.
2064
+ - `{ ok: false, unavailable: true }` — the platform has no such door (a
2065
+ claw from before it) or there is no network. Render the quiet "not
2066
+ connected yet" of every `_claw` door, or leave the button out.
2067
+
2068
+ `useLlm()` is the same call from a component: `{ run, loading, result,
2069
+ error, unavailable }`. `run(input, opts)` takes the same arguments and
2070
+ resolves the same answer; `result` is that answer when it was ok, `error`
2071
+ the refusal's words, and `unavailable` is true on a claw with no door (or
2072
+ no network), when `error` stays null: that is the quiet "not connected
2073
+ yet", not an alert, as for `useClaw`. A new run aborts the one before it,
2074
+ so a slow answer never lands over a newer one, and leaving the page
2075
+ aborts the call in flight. `error` is the sentence whatever the code, so
2076
+ a screen that must tell the money (`no_credits`, `member_cap`, `app_cap`)
2077
+ from the rest reads `code` from what `run()` resolves.
2078
+
2079
+ ```jsx
2080
+ "use client";
2081
+ import { Button, Notice } from "../components/ui";
2082
+ import { useLlm } from "../lib/hooks";
2083
+
2084
+ export default function Translate({ note }) {
2085
+ const { run, loading, result, error, unavailable } = useLlm();
2086
+ if (unavailable) return <p className="text-sm text-muted-foreground">Translation is not connected yet.</p>;
2087
+ return (
2088
+ <div className="grid gap-2">
2089
+ <Button loading={loading} onClick={() => run(`Translate to French:\n${note.text}`, { task: "translate" })}>
2090
+ Translate
2091
+ </Button>
2092
+ {error ? <Notice tone="danger">{error}</Notice> : result ? <p className="text-sm">{result.text}</p> : null}
2093
+ </div>
2094
+ );
2095
+ }
2096
+ ```
2097
+
2098
+ What to keep in mind:
2099
+
2100
+ - **Browser only, in both modes.** The call rides the member's session:
2101
+ `llm()` and `useLlm()` run in a `"use client"` file. A server
2102
+ component or a server action has no member to charge and cannot call
2103
+ it.
2104
+ - **It spends the workspace's credits**, like any inference, and counts
2105
+ against the member's monthly cap and the app's weekly cap. A schema
2106
+ call the model misses is asked again once, and both are charged; so is
2107
+ a call the 60 second clock cuts. Call it on a press, never on every
2108
+ render or every keystroke, and never once per row of a long list: that
2109
+ is a batch, and a batch is `ask()`'s.
2110
+ - **The answer is words, not markup.** Render `text` as text. Never put a
2111
+ model's answer in `dangerouslySetInnerHTML`.
2112
+ - **The answer is not saved.** What matters goes into a row
2113
+ (`updateRow`, `insertRow`) before the page closes.
2114
+ - **No streaming.** The answer arrives whole.
2115
+ - **Nothing appears on the desk.** No request, no thread, no run: the
2116
+ agent column and the Requests list are `ask()`'s. The call is metered
2117
+ to the member who made it; the usage line names the app, the tier and
2118
+ the `task` label. Claw does not log the request or the reply.
2119
+ - **Never by its path.** A string naming `_claw/llm` fails
2120
+ `npm run check` (§6, `llm`): the two functions are the contract, and
2121
+ they handle what a bare `fetch` would not (a claw without the door, a
2122
+ dropped network, an abort).
2123
+
2124
+ ### Showing the Library — `library`
2125
+
2126
+ The Library is what Makersclaw keeps for every workspace: **collections of
2127
+ files** (pitch decks, PDFs, HTML website templates, graphics) and
2128
+ **collections of rows** (a dataset: a list of investors, growth
2129
+ examples). Members browse it in the Library window on the desk. An app
2130
+ can show the same content inside a screen, read live from the platform.
2131
+
2132
+ Use it when the app **shows examples, templates or a dataset that
2133
+ Makersclaw keeps**: a gallery of pitch decks, a picker of website
2134
+ templates to start from, a table of investors to choose from. The screen
2135
+ asks the Library when it opens, so what it shows is what the Library
2136
+ holds today.
2137
+
2138
+ Not for:
2139
+
2140
+ - **The app's own data.** That is your tables (§5, Your tables) and the
2141
+ company brain. The Library is Makersclaw's, the same for every
2142
+ workspace; nothing a member does in the app is written to it.
2143
+ - **Sample rows for an empty screen.** Examples of your own app's data
2144
+ are `useFixture` (§3a), never the Library.
2145
+ - **Copying into the workspace.** The Library is read only: the door has
2146
+ no write. A member who wants a collection's rows in their company
2147
+ data, or a file in their Files, asks the agent, which has the Library's
2148
+ tools and records the copy:
2149
+
2150
+ ```js
2151
+ import { ask } from "../lib/platform";
2152
+
2153
+ ask({ text: `Copy the "${collection.title}" list into our company data`, how: `The Library collection is "${collection.slug}".` });
2154
+ ```
2155
+
2156
+ #### Reading it
2157
+
2158
+ ```js
2159
+ import { library } from "../lib/platform";
2160
+
2161
+ library.collections({ q, shelf }) → data { collections: [card] }
2162
+ library.collection(id) → data { collection }
2163
+ library.items(id, { q, tag, cursor, limit }) → data { items, next_cursor, total, preview_only }
2164
+ library.rows(id, { q, filters, cursor, limit }) → data { rows, next_cursor, total, preview_only }
2165
+ library.item(id) → data { item, file_url?, text_excerpt? }
2166
+ ```
2167
+
2168
+ Each resolves `{ ok, status, data }` or `{ ok: false, status, error,
2169
+ unavailable, code }` like `me`, and never throws. A collection's `id` is
2170
+ its slug (`"pitch-decks"`) or its uuid; an item's is its uuid. An id that
2171
+ names nothing asks nothing of the platform. Every call takes `signal`
2172
+ among its options.
2173
+
2174
+ - `shelf` is one of `decks`, `websites`, `designs`, `documents`,
2175
+ `datasets`, `examples`. `q` is a search. A card is `{ id, slug, title,
2176
+ blurb, kind: "files" | "rows", shelf, tags, access: "free" | "paid",
2177
+ status, public_page, cover_url, item_count, row_count, usable,
2178
+ preview_only }`; `collection` adds `body`, `columns`, `source`,
2179
+ `licence`, `preview_count`, `personal_data`, `published_at`.
2180
+ - **Items** (a files collection): `{ id, title, description, tags,
2181
+ format, mime, bytes, preview_url, source_url, licence, position,
2182
+ locked }`. `format` is `pdf`, `image`, `html`, `slides`, `document`,
2183
+ `sheet`, `archive` or `other`. `tag` narrows by a tag. `limit` is a
2184
+ whole number: 30 items a page unless you say, and more than 60 is cut
2185
+ to 60.
2186
+ - **Rows** (a rows collection): `{ id, data, source_url }`. `data` is
2187
+ keyed by the collection's `columns` (`{ key, label, type, filter, … }`;
2188
+ `type` is `text`, `long_text`, `number`, `url`, `email`, `image`,
2189
+ `tags` or `date`). `filters` is `{ <column key>: value }` for the
2190
+ columns with `filter: true`, an exact match (for a `tags` column, rows
2191
+ that have the tag); any other column is refused in words. `limit`: 50
2192
+ rows a page unless you say, and more than 100 is cut to 100.
2193
+ `source_url` is where the row
2194
+ was found: show it beside a person, an investor or a figure.
2195
+ - **Paging.** A page with more answers `next_cursor`: pass it back as
2196
+ `cursor`. Take it as given; do not read or build one.
2197
+ - `item(id)` is the item whole: its file's signed address as `file_url`
2198
+ and the first 4,000 characters of its text as `text_excerpt` (the
2199
+ start of a PDF's words, an HTML page's source).
2200
+
2201
+ The hooks read once, when the screen opens or an argument changes, and
2202
+ page for you:
2203
+
2204
+ ```js
2205
+ useLibraryCollections({ q, shelf }) → { collections, loading, error, code, unavailable, reload }
2206
+ useLibraryCollection(id) → { collection, loading, error, code, unavailable, reload }
2207
+ useLibraryItems(id, { q, tag, limit }) → { items, total, previewOnly, hasMore, loading, loadingMore, error, code, unavailable, loadMore, reload }
2208
+ useLibraryRows(id, { q, filters, limit }) → { rows, total, previewOnly, hasMore, loading, loadingMore, error, code, unavailable, loadMore, reload }
2209
+ useLibraryItem(id) → { item, fileUrl, textExcerpt, loading, error, code, unavailable, reload }
2210
+ ```
2211
+
2212
+ `items` and `rows` hold the pages read so far; `loadMore()` reads the
2213
+ next and adds it (`hasMore` says there is one; it does nothing while a
2214
+ page is out). A new `id`, `q`, `tag`, `filters` or `limit` starts the
2215
+ list over, showing `loading` and no rows, never the last list: type-ahead
2216
+ should wait for a pause before it changes `q`. Nothing is read until
2217
+ there is an `id` (and `enabled: false` reads nothing). `unavailable` and
2218
+ `error` are never both set: `unavailable` is a claw from before the door
2219
+ or no network (show the quiet "not connected yet"), `error` is the
2220
+ platform's words and `code` its code when it named one.
2221
+
2222
+ ```jsx
2223
+ "use client";
2224
+ import { Badge, Button, Card, Empty, Image, Notice } from "../components/ui";
2225
+ import { useLibraryItems } from "../lib/hooks";
2226
+
2227
+ export default function Decks() {
2228
+ const { items, total, previewOnly, hasMore, loadMore, loading, loadingMore, error, unavailable } =
2229
+ useLibraryItems("pitch-decks", { limit: 24 });
2230
+ if (unavailable) return <p className="text-sm text-muted-foreground">The Library is not connected yet.</p>;
2231
+ if (error) return <Notice tone="danger">{error}</Notice>;
2232
+ if (!loading && !items.length) return <Empty title="No decks yet" body="Nothing in this collection matches." />;
2233
+ return (
2234
+ <div className="grid gap-4">
2235
+ <div className="grid grid-cols-2 gap-4 lg:grid-cols-4">
2236
+ {items.map((item) => (
2237
+ <Card key={item.id} padding="sm" className="grid gap-2">
2238
+ <Image src={item.preview_url} alt="" ratio="photo" />
2239
+ <p className="text-sm font-medium">{item.title}</p>
2240
+ <Badge>{item.format}</Badge>
2241
+ </Card>
2242
+ ))}
2243
+ </div>
2244
+ {previewOnly && total > items.length ? <Notice>{total - items.length} more come with a paid plan.</Notice> : null}
2245
+ {hasMore ? <Button loading={loadingMore} onClick={loadMore}>Show more</Button> : null}
2246
+ </div>
2247
+ );
2248
+ }
2249
+ ```
2250
+
2251
+ #### A paid collection on a Free plan
2252
+
2253
+ A collection with `access: "paid"` is for paid workspaces. On a Free plan
2254
+ it is a **preview**, not a refusal: the card says `usable: false` and
2255
+ `preview_only: true`, and `items` or `rows` answer only the first
2256
+ `preview_count` of them (a search or a filter runs over those), with
2257
+ `preview_only: true` and the **true** `total`. `total` minus what you
2258
+ hold is what "comes with a paid plan". The items past the preview are
2259
+ not in the list (the item's `locked` flag is for such an item, and a
2260
+ list of a preview carries only the preview's, so it reads `false`
2261
+ there); asking for one by its id, `library.item(id)`, is a 403 with
2262
+ `code: "needs_plan"` and the platform's words ("This collection comes
2263
+ with a paid plan."): show them, and stop. The Library window on the desk
2264
+ has the Upgrade button; an app has none to offer. On a paid plan the
2265
+ same calls answer the whole collection.
2266
+
2267
+ #### Files
2268
+
2269
+ - **`file_url` is a signed address, good for ten minutes.** Show or
2270
+ download from it when the member asks, and never keep it: not in a row,
2271
+ not in `localStorage`, not in a link that outlives the screen. A new
2272
+ `library.item(id)` (or `reload()`) signs another. Row cells of type
2273
+ `image` are signed the same way, so a table of rows with pictures that
2274
+ stays open should read its page again now and then.
2275
+ - **`preview_url` and `cover_url` are plain pictures** that stay: use
2276
+ them in `Image` for a card or a thumbnail. A row's image is not one;
2277
+ it is a signed address.
2278
+ - A PDF opens in a new tab (`<Button href={fileUrl} target="_blank"
2279
+ rel="noreferrer">`); an image is an `Image` of `fileUrl`; the other
2280
+ formats are a download link.
2281
+ - **An `html` item (a website template) is shown only in a sandboxed
2282
+ frame, never in the app's own page.** Read its file as text and give
2283
+ it to an `iframe` as `srcDoc` with `sandbox="allow-scripts"`, so its
2284
+ own scripts run. **Never add `allow-same-origin`**: with it the
2285
+ template's scripts run as your app, with the member's session and
2286
+ every `_claw` door. Never `dangerouslySetInnerHTML`, never
2287
+ `iframe src={fileUrl}`, and never your own origin: Makersclaw does not
2288
+ serve these files from it either.
2289
+
2290
+ ```jsx
2291
+ "use client";
2292
+ import { useEffect, useState } from "react";
2293
+ import { Notice, Spinner } from "../components/ui";
2294
+ import { useLibraryItem } from "../lib/hooks";
2295
+
2296
+ export default function TemplatePreview({ id }) {
2297
+ const { item, fileUrl, code, error, unavailable } = useLibraryItem(id);
2298
+ const [html, setHtml] = useState(null);
2299
+ const [failed, setFailed] = useState(false);
2300
+ useEffect(() => {
2301
+ if (!fileUrl) return undefined;
2302
+ const controller = new AbortController();
2303
+ fetch(fileUrl, { signal: controller.signal })
2304
+ .then((res) => (res.ok ? res.text() : Promise.reject(new Error("no file"))))
2305
+ .then(setHtml)
2306
+ .catch(() => {
2307
+ if (!controller.signal.aborted) setFailed(true);
2308
+ });
2309
+ return () => controller.abort();
2310
+ }, [fileUrl]);
2311
+ if (unavailable) return <p className="text-sm text-muted-foreground">The Library is not connected yet.</p>;
2312
+ if (error) return <Notice tone={code === "needs_plan" ? "info" : "danger"}>{error}</Notice>;
2313
+ if (failed) return <Notice tone="danger">This template did not open. Try again.</Notice>;
2314
+ if (html === null) return <Spinner />;
2315
+ return <iframe title={item.title} srcDoc={html} sandbox="allow-scripts" className="h-96 w-full rounded-md border border-border" />;
2316
+ }
2317
+ ```
2318
+
2319
+ #### What to keep in mind
2320
+
2321
+ - **Browser only, in both modes.** The read rides the member's session:
2322
+ `library` and the hooks run in a `"use client"` file. A server
2323
+ component or a server action has no member and cannot call it.
2324
+ - **Never by its path.** A string naming `_claw/library` fails `npm run
2325
+ check` (§6, `library`): the functions handle a claw without the door, a
2326
+ dropped network and an abort, which a bare `fetch` does not.
2327
+ - **A claw from before the door** answers a 404 that names no refusal:
2328
+ `unavailable: true`, from every call and every hook. A collection or
2329
+ item that is not there (or is a draft the member cannot see) is a 404
2330
+ that names its code, so `unavailable` stays false and `error` says so.
2331
+ Show a missing door as "not connected yet", and a missing collection as
2332
+ "not found".
2333
+ - **Show where it came from.** An item's `licence` and `source_url`, a
2334
+ row's `source_url` and a collection's `source` are in the answer for a
2335
+ reason: print them where the content is shown.
2336
+ - **A rows collection can list people** (`personal_data: true`). It is
2337
+ shown to the member who has the app open. Do not copy it anywhere
2338
+ yourself: no `insertRow` of its rows, no export, no sending it to your
2339
+ own server. Using it in the company's data is a copy through the
2340
+ agent.
2341
+ - **The platform notes that the app showed a collection**, once a day
2342
+ per app and collection.
2343
+ - **Read it when the screen needs it.** Not on every keystroke, and not
2344
+ in a loop over every collection: a shelf is one `collections` call.
2345
+
1507
2346
  ### Activity — the contract
1508
2347
 
1509
2348
  `claw_app.activity` is how the founder sees the work. It is the
@@ -1577,11 +2416,15 @@ ok controls every control is a kit part
1577
2416
  ok examples examples show only outside a workspace (useFixture); a workspace app opens empty
1578
2417
  ok manifest 2 surfaces: drafts, sent
1579
2418
  ok icons every icon name exists
1580
- ok kit 70 fixed files match the template
2419
+ ok kit 74 fixed files match the template
1581
2420
  ok depictions 1 picture of elsewhere, framed on 1 surface: x-post
1582
2421
  ok agent no SQL write in app code; the agent's brief names every action with its call (1), every table written (2) and every server action that writes (0)
1583
2422
  ok tables its own schema (makersclaw.json): every table named bare, and each bare name one of the 2 its schema makes (../install/schema.sql); claw. and claw_app. are the platform's
1584
2423
  ok brain no brain block in makersclaw.json; no lib/brain.js call names a kind
2424
+ ok viewport nothing in the app sizes itself by the window
2425
+ ok llm no screen names _claw/llm: a model is called through llm() or useLlm() (README §5)
2426
+ ok library no screen names _claw/library: the Library is read through library() or its hooks (README §5)
2427
+ ok actions no actions declared in makersclaw.json: the app's agent writes as references/actions.md says
1585
2428
  ok smoke built in 41s · / → 307 · /s/drafts 200 · /s/sent 200 (0.6s)
1586
2429
  all clear
1587
2430
  ```
@@ -1593,9 +2436,25 @@ ok browser files and a door: 2 client surfaces; no server code, route, pro
1593
2436
  ok smoke built in 38s (copy at ~/.claw-check/app) · export 2.1 MB in 64 files · / → 200 to /s/drafts · /s/drafts 200 · /s/sent 200 (0.1s)
1594
2437
  ```
1595
2438
 
2439
+ `actions` holds `makersclaw.json` `actions` to the platform's rules
2440
+ (§5, Declared actions) and, once any is declared, refuses every write a
2441
+ screen makes that is not one.
2442
+
2443
+ `automations` runs `makersclaw.json` `automations` (§5, Shipped
2444
+ automations) through the platform's own validator, one line per problem
2445
+ (its place, then what is wrong; at most 8, then "and N more"). It reads
2446
+ two copies of claw's format kept in `check/` and is skipped, not failed,
2447
+ on a node older than 22.18 (it cannot read them).
2448
+
1596
2449
  `kit` refuses a fixed file that differs from the template (they are
1597
2450
  hashed in `check/pins.json`) and any file of yours under `components/ui`
1598
- or `components/parts`. `depictions` reads both directions: nothing of
2451
+ or `components/parts`. `viewport` refuses anything in your code that
2452
+ sizes itself by the window: `min-h-dvh`, `min-h-screen`, `h-screen`,
2453
+ `h-dvh` (and their `svh`, `lvh` and `max-h-` kin), and any `vh` unit —
2454
+ `h-[80vh]`, `max-h-[60vh]`, `h-[calc(100vh-4rem)]`, `style={{ height:
2455
+ "100vh" }}`. The window has one owner, the kit's `AppLayout` (§3b,
2456
+ Layouts); a box inside it is bounded by its parent (`h-full`, `flex-1
2457
+ min-h-0`) or by a size (`max-h-96`). `depictions` reads both directions: nothing of
1599
2458
  the workspace inside a depiction (a token, `font-sans`, `dark:`, a rem
1600
2459
  utility), nothing of the depiction outside its frame (a named import, a
1601
2460
  picture in the shell or a `Card`, a dead file nobody renders).
@@ -1692,6 +2551,24 @@ kind has `kind`, `label`, `plural` and `fields`. A read's kind
1692
2551
  hands the app only what `reads` and `writes` name. A kind held in a
1693
2552
  variable is not read here; the door refuses it on the member's screen.
1694
2553
 
2554
+ `llm` reads every app, in both modes: no string in the code names
2555
+ `_claw/llm`, and none handed to `claw()`, `clawUrl()` or `clawStream()`
2556
+ starts `llm`. A model is called with `llm()` or `useLlm()` (§5, Calling a
2557
+ model), which handle a claw without the door, a dropped network and an
2558
+ abort; a `fetch` of the path handles none of them. The path is read as
2559
+ a browser reads it (`claw("//llm")`, `claw("./llm")` and `"/_claw/./llm"`
2560
+ are the door too). A path built from pieces or held in a variable is not
2561
+ read here, as for rule 8. A longer name (`_claw/llm-notes`) is another
2562
+ route, and a comment or text in JSX is not a string of code.
2563
+
2564
+ `library` is the same rule for the Library's door: no string in the code
2565
+ names `_claw/library`, and none handed to `claw()`, `clawUrl()` or
2566
+ `clawStream()` starts `library`. The Library is read with `library` from
2567
+ `lib/platform.js` or the `useLibrary…` hooks (§5, Showing the Library),
2568
+ which handle a claw without the door, a dropped network, an id that
2569
+ names nothing and an abort. It reads every app, in both modes, and the
2570
+ path as a browser reads it (`claw("./library/items")` is the door too).
2571
+
1695
2572
  `browser` reads a browser app only (`"mode": "browser"`): its pages are
1696
2573
  files built once, and everything they read or write goes through the
1697
2574
  platform's data door. So it refuses, file and line, a `"use server"`
@@ -1713,6 +2590,12 @@ page. That proves every page prerenders, not that a surface renders
1713
2590
  with data: the rows come in the browser. Then, by eye:
1714
2591
 
1715
2592
  - Renders at 360px, 768px and 1280px without horizontal scroll.
2593
+ - The page itself never scrolls: the shell is the window's height
2594
+ (`AppLayout`), and each pane scrolls inside it. With the longest
2595
+ content a surface can hold (a 30-page article, a 40-message thread,
2596
+ a tall inspector), the last line and every button after it are
2597
+ reachable, at 375px and at 1280px; the header and the footer stay in
2598
+ view.
1716
2599
  - In a workspace, an empty table shows `LiveEmpty`: the work in flight,
1717
2600
  else what would be here and the manual way to add it — never an
1718
2601
  example (§3a). A saved row replaces it.