makersclaw 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (401) hide show
  1. package/README.md +9 -3
  2. package/package.json +1 -1
  3. package/r/activity-log.json +52 -0
  4. package/r/agent-changes.json +51 -0
  5. package/r/agent-chat.json +53 -0
  6. package/r/agent-column.json +85 -0
  7. package/r/agent-dock.json +57 -0
  8. package/r/agent-kit.json +49 -0
  9. package/r/agent-marks.json +49 -0
  10. package/r/agent-pane.json +93 -0
  11. package/r/ai-action.json +56 -0
  12. package/r/annotate.json +3 -3
  13. package/r/approval-request.json +2 -2
  14. package/r/approval.json +54 -0
  15. package/r/ask-bar.json +50 -0
  16. package/r/audio-player.json +2 -2
  17. package/r/auth-form.json +2 -2
  18. package/r/automation-editor.json +66 -0
  19. package/r/automation-list.json +57 -0
  20. package/r/automation-model.json +118 -0
  21. package/r/automations-screen.json +71 -0
  22. package/r/board.json +2 -2
  23. package/r/calendar-view.json +3 -3
  24. package/r/cart.json +2 -2
  25. package/r/chart.json +2 -2
  26. package/r/chat-pane.json +84 -0
  27. package/r/chat.json +2 -2
  28. package/r/code-editor.json +2 -2
  29. package/r/comment-box.json +3 -3
  30. package/r/connect-card.json +51 -0
  31. package/r/contact-section.json +2 -2
  32. package/r/core.json +13 -7
  33. package/r/cost.json +51 -0
  34. package/r/csv-import.json +3 -3
  35. package/r/data-picker.json +60 -0
  36. package/r/data-table.json +2 -2
  37. package/r/diagram.json +2 -2
  38. package/r/doc-editor.json +2 -2
  39. package/r/doc-page.json +3 -3
  40. package/r/email-render.json +2 -2
  41. package/r/faq.json +2 -2
  42. package/r/file-upload.json +2 -2
  43. package/r/first-run.json +63 -0
  44. package/r/fix-note.json +57 -0
  45. package/r/flow-canvas.json +2 -2
  46. package/r/flow-editor.json +79 -0
  47. package/r/footer.json +2 -2
  48. package/r/gantt.json +3 -3
  49. package/r/job-panel.json +2 -2
  50. package/r/json-editor.json +3 -3
  51. package/r/library-shelf.json +56 -0
  52. package/r/map.json +2 -2
  53. package/r/margin-notes.json +67 -0
  54. package/r/menubar.json +2 -2
  55. package/r/mind-map.json +3 -3
  56. package/r/navigation-menu.json +2 -2
  57. package/r/needs-you.json +55 -0
  58. package/r/order-detail.json +2 -2
  59. package/r/org-chart.json +3 -3
  60. package/r/pace-bar.json +69 -0
  61. package/r/page-builder.json +2 -2
  62. package/r/payment-methods.json +2 -2
  63. package/r/pdf-document.json +2 -2
  64. package/r/pdf-viewer.json +2 -2
  65. package/r/product-detail.json +2 -2
  66. package/r/product-grid.json +3 -3
  67. package/r/record-form.json +2 -2
  68. package/r/record-grid.json +52 -0
  69. package/r/record-notes.json +4 -4
  70. package/r/registry.json +4086 -1512
  71. package/r/run-history.json +52 -0
  72. package/r/run-view.json +80 -0
  73. package/r/schedule-card.json +54 -0
  74. package/r/schedule-engine.json +79 -0
  75. package/r/schedule-gantt.json +83 -0
  76. package/r/schedule-ruler.json +64 -0
  77. package/r/search-dialog.json +2 -2
  78. package/r/settings-list.json +2 -2
  79. package/r/setup-checklist.json +2 -2
  80. package/r/share-dialog.json +2 -2
  81. package/r/sidebar.json +2 -2
  82. package/r/signature-pad.json +2 -2
  83. package/r/sketch-canvas.json +2 -2
  84. package/r/source-receipt.json +52 -0
  85. package/r/spreadsheet.json +3 -3
  86. package/r/stat-cards.json +3 -3
  87. package/r/step-picker.json +53 -0
  88. package/r/step-settings.json +72 -0
  89. package/r/suggestion.json +58 -0
  90. package/r/sum-bar.json +64 -0
  91. package/r/task-list.json +3 -3
  92. package/r/task-model.json +2 -2
  93. package/r/testimonials.json +2 -2
  94. package/r/tier-map.json +67 -0
  95. package/r/time-grid.json +73 -0
  96. package/r/time-strip.json +64 -0
  97. package/r/top-bar.json +66 -0
  98. package/r/transaction-list.json +2 -2
  99. package/r/trigger-picker.json +61 -0
  100. package/r/whiteboard.json +3 -3
  101. package/r/workflow-view.json +55 -0
  102. package/registry/blocks/activity-log/README.md +112 -0
  103. package/registry/blocks/activity-log/activity-log.jsx +351 -0
  104. package/registry/blocks/activity-log/block.json +33 -0
  105. package/registry/blocks/activity-log/demo.jsx +48 -0
  106. package/registry/blocks/activity-log/index.js +4 -0
  107. package/registry/blocks/agent-changes/README.md +94 -0
  108. package/registry/blocks/agent-changes/agent-changes.jsx +118 -0
  109. package/registry/blocks/agent-changes/block.json +28 -0
  110. package/registry/blocks/agent-changes/demo.jsx +39 -0
  111. package/registry/blocks/agent-changes/index.js +3 -0
  112. package/registry/blocks/agent-chat/README.md +145 -0
  113. package/registry/blocks/agent-chat/agent-chat.jsx +415 -0
  114. package/registry/blocks/agent-chat/block.json +30 -0
  115. package/registry/blocks/agent-chat/demo.jsx +165 -0
  116. package/registry/blocks/agent-chat/index.js +3 -0
  117. package/registry/blocks/agent-column/README.md +197 -0
  118. package/registry/blocks/agent-column/agent-column.jsx +492 -0
  119. package/registry/blocks/agent-column/block.json +67 -0
  120. package/registry/blocks/agent-column/column-picker.jsx +163 -0
  121. package/registry/blocks/agent-column/demo.jsx +50 -0
  122. package/registry/blocks/agent-column/index.js +7 -0
  123. package/registry/blocks/agent-column/model.js +164 -0
  124. package/registry/blocks/agent-column/receipt.jsx +483 -0
  125. package/registry/blocks/agent-column/spreadsheet-type.jsx +24 -0
  126. package/registry/blocks/agent-dock/README.md +210 -0
  127. package/registry/blocks/agent-dock/agent-dock.jsx +356 -0
  128. package/registry/blocks/agent-dock/block.json +47 -0
  129. package/registry/blocks/agent-dock/demo.jsx +153 -0
  130. package/registry/blocks/agent-dock/dock-model.js +118 -0
  131. package/registry/blocks/agent-dock/index.js +5 -0
  132. package/registry/blocks/agent-kit/README.md +73 -0
  133. package/registry/blocks/agent-kit/agent-kit.jsx +86 -0
  134. package/registry/blocks/agent-kit/block.json +10 -0
  135. package/registry/blocks/agent-kit/demo.jsx +35 -0
  136. package/registry/blocks/agent-kit/index.js +3 -0
  137. package/registry/blocks/agent-marks/README.md +80 -0
  138. package/registry/blocks/agent-marks/agent-marks.jsx +133 -0
  139. package/registry/blocks/agent-marks/block.json +27 -0
  140. package/registry/blocks/agent-marks/demo.jsx +49 -0
  141. package/registry/blocks/agent-marks/index.js +3 -0
  142. package/registry/blocks/agent-pane/README.md +225 -0
  143. package/registry/blocks/agent-pane/agent-pane.jsx +244 -0
  144. package/registry/blocks/agent-pane/block.json +41 -0
  145. package/registry/blocks/agent-pane/composer.jsx +6 -0
  146. package/registry/blocks/agent-pane/demo.jsx +233 -0
  147. package/registry/blocks/agent-pane/dock-context.js +10 -0
  148. package/registry/blocks/agent-pane/index.js +4 -0
  149. package/registry/blocks/agent-pane/prose.jsx +84 -0
  150. package/registry/blocks/agent-pane/questions.jsx +134 -0
  151. package/registry/blocks/agent-pane/transcript.jsx +268 -0
  152. package/registry/blocks/agent-pane/work.jsx +368 -0
  153. package/registry/blocks/ai-action/README.md +94 -0
  154. package/registry/blocks/ai-action/ai-action.jsx +188 -0
  155. package/registry/blocks/ai-action/block.json +34 -0
  156. package/registry/blocks/ai-action/demo.jsx +93 -0
  157. package/registry/blocks/ai-action/index.js +3 -0
  158. package/registry/blocks/approval/README.md +145 -0
  159. package/registry/blocks/approval/approval.jsx +163 -0
  160. package/registry/blocks/approval/block.json +31 -0
  161. package/registry/blocks/approval/demo.jsx +121 -0
  162. package/registry/blocks/approval/index.js +3 -0
  163. package/registry/blocks/ask-bar/README.md +105 -0
  164. package/registry/blocks/ask-bar/ask-bar.jsx +166 -0
  165. package/registry/blocks/ask-bar/block.json +26 -0
  166. package/registry/blocks/ask-bar/demo.jsx +78 -0
  167. package/registry/blocks/ask-bar/index.js +3 -0
  168. package/registry/blocks/automation-editor/README.md +291 -0
  169. package/registry/blocks/automation-editor/automation-editor.jsx +656 -0
  170. package/registry/blocks/automation-editor/block.json +39 -0
  171. package/registry/blocks/automation-editor/demo.jsx +284 -0
  172. package/registry/blocks/automation-editor/index.js +4 -0
  173. package/registry/blocks/automation-editor/run-inputs.jsx +82 -0
  174. package/registry/blocks/automation-list/README.md +129 -0
  175. package/registry/blocks/automation-list/automation-list.jsx +476 -0
  176. package/registry/blocks/automation-list/block.json +35 -0
  177. package/registry/blocks/automation-list/demo.jsx +67 -0
  178. package/registry/blocks/automation-list/index.js +3 -0
  179. package/registry/blocks/automation-model/README.md +109 -0
  180. package/registry/blocks/automation-model/block.json +135 -0
  181. package/registry/blocks/automation-model/catalog.js +256 -0
  182. package/registry/blocks/automation-model/check.js +161 -0
  183. package/registry/blocks/automation-model/demo.jsx +42 -0
  184. package/registry/blocks/automation-model/edit.js +262 -0
  185. package/registry/blocks/automation-model/fixes.js +287 -0
  186. package/registry/blocks/automation-model/glyph.jsx +13 -0
  187. package/registry/blocks/automation-model/graph.js +410 -0
  188. package/registry/blocks/automation-model/index.js +33 -0
  189. package/registry/blocks/automation-model/overlay.js +175 -0
  190. package/registry/blocks/automation-model/parts.jsx +94 -0
  191. package/registry/blocks/automation-model/schedule.js +53 -0
  192. package/registry/blocks/automation-model/templates.js +128 -0
  193. package/registry/blocks/automation-model/values.js +29 -0
  194. package/registry/blocks/automation-model/words.js +439 -0
  195. package/registry/blocks/automations-screen/README.md +207 -0
  196. package/registry/blocks/automations-screen/automations-screen.jsx +452 -0
  197. package/registry/blocks/automations-screen/block.json +47 -0
  198. package/registry/blocks/automations-screen/demo.jsx +364 -0
  199. package/registry/blocks/automations-screen/index.js +4 -0
  200. package/registry/blocks/automations-screen/screen-model.js +129 -0
  201. package/registry/blocks/chat-pane/README.md +143 -0
  202. package/registry/blocks/chat-pane/block.json +48 -0
  203. package/registry/blocks/chat-pane/chat-attach.js +166 -0
  204. package/registry/blocks/chat-pane/chat-composer.jsx +195 -0
  205. package/registry/blocks/chat-pane/chat-context.js +17 -0
  206. package/registry/blocks/chat-pane/chat-model.js +43 -0
  207. package/registry/blocks/chat-pane/chat-pane.jsx +398 -0
  208. package/registry/blocks/chat-pane/chats-list.jsx +52 -0
  209. package/registry/blocks/chat-pane/demo.jsx +103 -0
  210. package/registry/blocks/chat-pane/index.js +9 -0
  211. package/registry/blocks/connect-card/README.md +99 -0
  212. package/registry/blocks/connect-card/block.json +10 -0
  213. package/registry/blocks/connect-card/connect-card.jsx +103 -0
  214. package/registry/blocks/connect-card/demo.jsx +49 -0
  215. package/registry/blocks/connect-card/index.js +3 -0
  216. package/registry/blocks/cost/README.md +115 -0
  217. package/registry/blocks/cost/block.json +10 -0
  218. package/registry/blocks/cost/cost.jsx +176 -0
  219. package/registry/blocks/cost/demo.jsx +66 -0
  220. package/registry/blocks/cost/index.js +3 -0
  221. package/registry/blocks/data-picker/README.md +81 -0
  222. package/registry/blocks/data-picker/block.json +38 -0
  223. package/registry/blocks/data-picker/data-picker.jsx +210 -0
  224. package/registry/blocks/data-picker/demo.jsx +34 -0
  225. package/registry/blocks/data-picker/fields.js +89 -0
  226. package/registry/blocks/data-picker/index.js +4 -0
  227. package/registry/blocks/data-table/demo.jsx +1 -1
  228. package/registry/blocks/first-run/README.md +118 -0
  229. package/registry/blocks/first-run/block.json +11 -0
  230. package/registry/blocks/first-run/demo.jsx +88 -0
  231. package/registry/blocks/first-run/first-run-model.js +51 -0
  232. package/registry/blocks/first-run/first-run.jsx +156 -0
  233. package/registry/blocks/first-run/index.js +5 -0
  234. package/registry/blocks/first-run/probe-rules.js +26 -0
  235. package/registry/blocks/fix-note/README.md +79 -0
  236. package/registry/blocks/fix-note/block.json +35 -0
  237. package/registry/blocks/fix-note/demo.jsx +30 -0
  238. package/registry/blocks/fix-note/fix-note.jsx +235 -0
  239. package/registry/blocks/fix-note/index.js +3 -0
  240. package/registry/blocks/flow-editor/README.md +108 -0
  241. package/registry/blocks/flow-editor/block.json +44 -0
  242. package/registry/blocks/flow-editor/demo.jsx +115 -0
  243. package/registry/blocks/flow-editor/flow-canvas.jsx +568 -0
  244. package/registry/blocks/flow-editor/flow-editor.jsx +154 -0
  245. package/registry/blocks/flow-editor/index.js +6 -0
  246. package/registry/blocks/flow-editor/minimap.jsx +78 -0
  247. package/registry/blocks/flow-editor/outline.jsx +134 -0
  248. package/registry/blocks/library-shelf/README.md +117 -0
  249. package/registry/blocks/library-shelf/block.json +28 -0
  250. package/registry/blocks/library-shelf/demo.jsx +68 -0
  251. package/registry/blocks/library-shelf/index.js +3 -0
  252. package/registry/blocks/library-shelf/library-shelf.jsx +211 -0
  253. package/registry/blocks/library-shelf/probe-rules.js +15 -0
  254. package/registry/blocks/margin-notes/README.md +222 -0
  255. package/registry/blocks/margin-notes/block.json +10 -0
  256. package/registry/blocks/margin-notes/demo.jsx +144 -0
  257. package/registry/blocks/margin-notes/index.js +20 -0
  258. package/registry/blocks/margin-notes/margin-model.js +224 -0
  259. package/registry/blocks/margin-notes/margin-notes.jsx +465 -0
  260. package/registry/blocks/needs-you/README.md +177 -0
  261. package/registry/blocks/needs-you/block.json +34 -0
  262. package/registry/blocks/needs-you/demo.jsx +143 -0
  263. package/registry/blocks/needs-you/index.js +3 -0
  264. package/registry/blocks/needs-you/needs-you.jsx +441 -0
  265. package/registry/blocks/pace-bar/README.md +230 -0
  266. package/registry/blocks/pace-bar/block.json +10 -0
  267. package/registry/blocks/pace-bar/demo.jsx +255 -0
  268. package/registry/blocks/pace-bar/index.js +22 -0
  269. package/registry/blocks/pace-bar/pace-bar.jsx +461 -0
  270. package/registry/blocks/pace-bar/pace-model.js +288 -0
  271. package/registry/blocks/record-grid/README.md +100 -0
  272. package/registry/blocks/record-grid/block.json +28 -0
  273. package/registry/blocks/record-grid/demo.jsx +43 -0
  274. package/registry/blocks/record-grid/index.js +3 -0
  275. package/registry/blocks/record-grid/record-grid.jsx +251 -0
  276. package/registry/blocks/run-history/README.md +138 -0
  277. package/registry/blocks/run-history/block.json +10 -0
  278. package/registry/blocks/run-history/demo.jsx +74 -0
  279. package/registry/blocks/run-history/index.js +3 -0
  280. package/registry/blocks/run-history/run-history.jsx +218 -0
  281. package/registry/blocks/run-view/README.md +174 -0
  282. package/registry/blocks/run-view/block.json +50 -0
  283. package/registry/blocks/run-view/demo.jsx +286 -0
  284. package/registry/blocks/run-view/index.js +5 -0
  285. package/registry/blocks/run-view/run-controls.jsx +266 -0
  286. package/registry/blocks/run-view/run-view.jsx +236 -0
  287. package/registry/blocks/run-view/runs-list.jsx +99 -0
  288. package/registry/blocks/schedule-card/README.md +121 -0
  289. package/registry/blocks/schedule-card/block.json +10 -0
  290. package/registry/blocks/schedule-card/demo.jsx +82 -0
  291. package/registry/blocks/schedule-card/index.js +3 -0
  292. package/registry/blocks/schedule-card/schedule-card.jsx +136 -0
  293. package/registry/blocks/schedule-engine/README.md +137 -0
  294. package/registry/blocks/schedule-engine/block.json +10 -0
  295. package/registry/blocks/schedule-engine/demo.jsx +82 -0
  296. package/registry/blocks/schedule-engine/engine.js +769 -0
  297. package/registry/blocks/schedule-engine/index.js +9 -0
  298. package/registry/blocks/schedule-engine/ops.js +71 -0
  299. package/registry/blocks/schedule-engine/place.js +294 -0
  300. package/registry/blocks/schedule-engine/tree.js +79 -0
  301. package/registry/blocks/schedule-engine/waits.js +80 -0
  302. package/registry/blocks/schedule-gantt/README.md +159 -0
  303. package/registry/blocks/schedule-gantt/block.json +10 -0
  304. package/registry/blocks/schedule-gantt/demo.jsx +223 -0
  305. package/registry/blocks/schedule-gantt/gantt-model.js +219 -0
  306. package/registry/blocks/schedule-gantt/geometry.js +176 -0
  307. package/registry/blocks/schedule-gantt/index.js +26 -0
  308. package/registry/blocks/schedule-gantt/schedule-gantt.jsx +882 -0
  309. package/registry/blocks/schedule-gantt/sheet.jsx +372 -0
  310. package/registry/blocks/schedule-gantt/track.jsx +190 -0
  311. package/registry/blocks/schedule-ruler/README.md +148 -0
  312. package/registry/blocks/schedule-ruler/block.json +10 -0
  313. package/registry/blocks/schedule-ruler/demo.jsx +181 -0
  314. package/registry/blocks/schedule-ruler/index.js +21 -0
  315. package/registry/blocks/schedule-ruler/ruler-model.js +239 -0
  316. package/registry/blocks/schedule-ruler/schedule-ruler.jsx +548 -0
  317. package/registry/blocks/source-receipt/README.md +97 -0
  318. package/registry/blocks/source-receipt/block.json +30 -0
  319. package/registry/blocks/source-receipt/demo.jsx +71 -0
  320. package/registry/blocks/source-receipt/index.js +3 -0
  321. package/registry/blocks/source-receipt/source-receipt.jsx +107 -0
  322. package/registry/blocks/spreadsheet/spreadsheet.jsx +15 -1
  323. package/registry/blocks/step-picker/README.md +78 -0
  324. package/registry/blocks/step-picker/block.json +31 -0
  325. package/registry/blocks/step-picker/demo.jsx +23 -0
  326. package/registry/blocks/step-picker/index.js +3 -0
  327. package/registry/blocks/step-picker/step-picker.jsx +144 -0
  328. package/registry/blocks/step-settings/README.md +100 -0
  329. package/registry/blocks/step-settings/block.json +44 -0
  330. package/registry/blocks/step-settings/demo.jsx +93 -0
  331. package/registry/blocks/step-settings/fields.jsx +58 -0
  332. package/registry/blocks/step-settings/flow-settings.jsx +115 -0
  333. package/registry/blocks/step-settings/index.js +5 -0
  334. package/registry/blocks/step-settings/step-settings.jsx +290 -0
  335. package/registry/blocks/suggestion/README.md +171 -0
  336. package/registry/blocks/suggestion/block.json +40 -0
  337. package/registry/blocks/suggestion/demo.jsx +91 -0
  338. package/registry/blocks/suggestion/index.js +3 -0
  339. package/registry/blocks/suggestion/suggestion.jsx +436 -0
  340. package/registry/blocks/sum-bar/README.md +122 -0
  341. package/registry/blocks/sum-bar/block.json +10 -0
  342. package/registry/blocks/sum-bar/demo.jsx +110 -0
  343. package/registry/blocks/sum-bar/index.js +5 -0
  344. package/registry/blocks/sum-bar/sum-bar.jsx +209 -0
  345. package/registry/blocks/sum-bar/sum-model.js +126 -0
  346. package/registry/blocks/tier-map/README.md +217 -0
  347. package/registry/blocks/tier-map/block.json +10 -0
  348. package/registry/blocks/tier-map/demo.jsx +222 -0
  349. package/registry/blocks/tier-map/index.js +24 -0
  350. package/registry/blocks/tier-map/tier-map.jsx +574 -0
  351. package/registry/blocks/tier-map/tier-model.js +318 -0
  352. package/registry/blocks/time-grid/README.md +305 -0
  353. package/registry/blocks/time-grid/block.json +10 -0
  354. package/registry/blocks/time-grid/demo.jsx +279 -0
  355. package/registry/blocks/time-grid/grid-model.js +322 -0
  356. package/registry/blocks/time-grid/index.js +25 -0
  357. package/registry/blocks/time-grid/time-grid.jsx +1325 -0
  358. package/registry/blocks/time-strip/README.md +141 -0
  359. package/registry/blocks/time-strip/block.json +10 -0
  360. package/registry/blocks/time-strip/demo.jsx +129 -0
  361. package/registry/blocks/time-strip/index.js +19 -0
  362. package/registry/blocks/time-strip/strip-model.js +178 -0
  363. package/registry/blocks/time-strip/time-strip.jsx +260 -0
  364. package/registry/blocks/top-bar/README.md +149 -0
  365. package/registry/blocks/top-bar/block.json +35 -0
  366. package/registry/blocks/top-bar/demo.jsx +78 -0
  367. package/registry/blocks/top-bar/index.js +5 -0
  368. package/registry/blocks/top-bar/probe-rules.js +74 -0
  369. package/registry/blocks/top-bar/top-bar-model.js +152 -0
  370. package/registry/blocks/top-bar/top-bar.jsx +244 -0
  371. package/registry/blocks/trigger-picker/README.md +98 -0
  372. package/registry/blocks/trigger-picker/block.json +38 -0
  373. package/registry/blocks/trigger-picker/demo.jsx +59 -0
  374. package/registry/blocks/trigger-picker/index.js +3 -0
  375. package/registry/blocks/trigger-picker/trigger-picker.jsx +374 -0
  376. package/registry/blocks/workflow-view/README.md +123 -0
  377. package/registry/blocks/workflow-view/block.json +10 -0
  378. package/registry/blocks/workflow-view/demo.jsx +90 -0
  379. package/registry/blocks/workflow-view/index.js +3 -0
  380. package/registry/blocks/workflow-view/workflow-view.jsx +203 -0
  381. package/src/install.mjs +77 -16
  382. package/src/registry.mjs +3 -0
  383. package/templates/next/browser/lib/data.js +6 -1
  384. package/templates/next/files/README.md +627 -24
  385. package/templates/next/files/check/automation-format.ts +2103 -0
  386. package/templates/next/files/check/automation-package.ts +142 -0
  387. package/templates/next/files/check/run.mjs +968 -9
  388. package/templates/next/files/components/ui/field.jsx +17 -4
  389. package/templates/next/files/components/ui/icon.jsx +13 -0
  390. package/templates/next/files/components/ui/index.js +2 -1
  391. package/templates/next/files/components/ui/layout.jsx +77 -2
  392. package/templates/next/files/components/ui/notice.jsx +70 -0
  393. package/templates/next/files/components/ui/page.jsx +124 -0
  394. package/templates/next/files/components/ui/stat.jsx +22 -7
  395. package/templates/next/files/components/ui/toast.jsx +6 -3
  396. package/templates/next/files/lib/automations.js +660 -0
  397. package/templates/next/files/lib/claw.js +241 -5
  398. package/templates/next/files/lib/door.js +92 -0
  399. package/templates/next/files/lib/hooks.js +1627 -8
  400. package/templates/next/files/lib/platform.js +529 -21
  401. package/templates/next/template.json +13 -3
@@ -0,0 +1,415 @@
1
+ "use client";
2
+
3
+ import { Fragment, useEffect, useRef, useState } from "react";
4
+ import { Button, Icon, IconButton, Notice, Spinner, Textarea, cx } from "../../ui";
5
+ import { QuestionBox } from "../needs-you";
6
+
7
+ // AgentChat — the app's own chat with its agent, in the app's look (0.8.1,
8
+ // the workspace's docs/APP-AGENT-BLOCKS-PLAN.md phase 1). It draws the
9
+ // object `useAgentThread()` returns (lib/hooks.js): the member's words,
10
+ // the agent's answer as it is written, one line per step, and where the
11
+ // thread stands. It is the SAME conversation the desk's agent column
12
+ // shows — one session, two views — so an app that places it says so in
13
+ // its package (`"agent_in_app": true` in the blueprint), and the desk then
14
+ // keeps its column folded for the app.
15
+ //
16
+ // const chat = useAgentThread({ row: { kind: "person", id, name } });
17
+ // <AgentChat chat={chat} title={`Ask about ${name}`} suggestions={[…]} />
18
+ //
19
+ // What waits on the member is settled in the chat, where it was asked
20
+ // (0.8.1, D18/D19): the agent's QUESTION is answered in place (its options,
21
+ // and the member's own words where it welcomes them: `chat.answer`), and
22
+ // its YES is the `approval` block's press frame, handed in as `yes`. The
23
+ // chat never draws an Approve of its own — the press is Makersclaw's, in
24
+ // a frame app code cannot script. Without `yes`, or for a need the app
25
+ // cannot settle (connecting an account, spending money, several questions
26
+ // at once), the bar says so and opens the desk: "Waiting for your yes on
27
+ // the desk".
28
+
29
+ const STATE_LINE = {
30
+ queued: "Queued — it starts when the one before it ends",
31
+ working: "Working on it",
32
+ };
33
+
34
+ /** What waits on the member, as the bar under the thread says it. */
35
+ function needsTitle(kind, inApp) {
36
+ if (kind === "yes" || kind === "approval") return inApp === "press" ? "Waiting for your yes" : "Waiting for your yes on the desk";
37
+ if (kind === "question") return inApp === "answer" ? "A question for you" : "Waiting for your answer on the desk";
38
+ if (kind === "connect") return "Waiting for you to connect an account on the desk";
39
+ if (kind === "limit") return "Paused for credits — see the desk";
40
+ return "Needs you on the desk";
41
+ }
42
+
43
+ // ---------------------------------------------------------------------------
44
+ // The agent's text: plain words with the little markdown agents write —
45
+ // paragraphs, lists, **bold**, `code`, [links](https://…). React nodes
46
+ // only, never HTML.
47
+
48
+ const INLINE = /(\*\*[^*]+\*\*|`[^`]+`|\[[^\]]+\]\((?:https?:\/\/)[^)\s]+\))/g;
49
+
50
+ function inline(text, key) {
51
+ const out = [];
52
+ let last = 0;
53
+ let i = 0;
54
+ for (const m of String(text).matchAll(INLINE)) {
55
+ if (m.index > last) out.push(text.slice(last, m.index));
56
+ const tok = m[0];
57
+ const k = `${key}-${i++}`;
58
+ if (tok.startsWith("**")) out.push(<strong key={k}>{tok.slice(2, -2)}</strong>);
59
+ else if (tok.startsWith("`")) out.push(<code key={k} className="rounded bg-muted px-1 font-mono text-[0.92em]">{tok.slice(1, -1)}</code>);
60
+ else {
61
+ const label = tok.slice(1, tok.indexOf("]("));
62
+ const href = tok.slice(tok.indexOf("](") + 2, -1);
63
+ out.push(
64
+ <a key={k} href={href} target="_blank" rel="noopener noreferrer" className="break-all text-primary underline underline-offset-2">
65
+ {label}
66
+ </a>,
67
+ );
68
+ }
69
+ last = m.index + tok.length;
70
+ }
71
+ if (last < text.length) out.push(text.slice(last));
72
+ return out;
73
+ }
74
+
75
+ const LIST_ITEM = /^\s*(?:[-*•]|\d+[.)])\s+/;
76
+
77
+ /** Paragraphs and lists from the agent's text. */
78
+ function Prose({ text, className }) {
79
+ const blocks = String(text ?? "").replace(/\r/g, "").split(/\n{2,}/);
80
+ return (
81
+ <div className={cx("grid min-w-0 gap-2 break-words", className)}>
82
+ {blocks.map((block, b) => {
83
+ const lines = block.split("\n").filter((l) => l.trim());
84
+ if (!lines.length) return null;
85
+ if (lines.every((l) => LIST_ITEM.test(l))) {
86
+ const ordered = /^\s*\d/.test(lines[0]);
87
+ const List = ordered ? "ol" : "ul";
88
+ return (
89
+ <List key={b} className={cx("grid gap-1 pl-5", ordered ? "list-decimal" : "list-disc")}>
90
+ {lines.map((l, j) => (
91
+ <li key={j}>{inline(l.replace(LIST_ITEM, ""), `${b}-${j}`)}</li>
92
+ ))}
93
+ </List>
94
+ );
95
+ }
96
+ return (
97
+ <p key={b} className="whitespace-pre-wrap">
98
+ {lines.map((l, j) => (
99
+ <Fragment key={j}>
100
+ {j > 0 ? "\n" : null}
101
+ {/^#{1,6}\s/.test(l) ? <strong>{inline(l.replace(/^#{1,6}\s+/, ""), `${b}-${j}`)}</strong> : inline(l, `${b}-${j}`)}
102
+ </Fragment>
103
+ ))}
104
+ </p>
105
+ );
106
+ })}
107
+ </div>
108
+ );
109
+ }
110
+
111
+ // ---------------------------------------------------------------------------
112
+
113
+ function StepMark({ status }) {
114
+ if (status === "done") return <Icon name="check" size={14} className="shrink-0 text-success" />;
115
+ if (status === "failed") return <Icon name="warning" size={14} className="shrink-0 text-destructive" />;
116
+ return <Spinner size="sm" label="Working" className="shrink-0 text-muted-foreground" />;
117
+ }
118
+
119
+ /** A run of steps: the one running now while the turn works, else one
120
+ * line that opens to the list. */
121
+ function Steps({ steps, live }) {
122
+ const [open, setOpen] = useState(false);
123
+ const running = live ? steps.filter((s) => s.status === "running").at(-1) : null;
124
+ const count = `${steps.length} ${steps.length === 1 ? "step" : "steps"}`;
125
+ if (running) {
126
+ return (
127
+ <div className="flex min-w-0 items-center gap-2 text-xs text-muted-foreground">
128
+ <StepMark status="running" />
129
+ <span className="min-w-0 truncate">{running.label}</span>
130
+ {steps.length > 1 ? <span className="shrink-0">· {count}</span> : null}
131
+ </div>
132
+ );
133
+ }
134
+ return (
135
+ <div className="min-w-0 text-xs text-muted-foreground">
136
+ <button
137
+ type="button"
138
+ className="flex min-w-0 items-center gap-1.5 rounded-sm hover:text-foreground focus-visible:outline-2 focus-visible:outline-ring"
139
+ aria-expanded={open}
140
+ onClick={() => setOpen((v) => !v)}
141
+ >
142
+ <Icon name={open ? "chevron-down" : "chevron-right"} size={14} className="shrink-0" />
143
+ <span className="truncate">Worked through {count}</span>
144
+ </button>
145
+ {open ? (
146
+ <ul className="mt-1.5 grid gap-1 pl-5">
147
+ {steps.map((s, i) => (
148
+ <li key={i} className="flex min-w-0 items-center gap-2">
149
+ <StepMark status={s.status} />
150
+ <span className="min-w-0 truncate">{s.label}</span>
151
+ </li>
152
+ ))}
153
+ </ul>
154
+ ) : null}
155
+ </div>
156
+ );
157
+ }
158
+
159
+ function MemberWords({ children }) {
160
+ return (
161
+ <div className="ml-auto max-w-[85%] min-w-0 whitespace-pre-wrap break-words rounded-[var(--radius)] bg-muted px-2.5 py-1.5">
162
+ {children}
163
+ </div>
164
+ );
165
+ }
166
+
167
+ /** One turn: the member's words, then the agent's text and steps in the
168
+ * order they came, steps that follow each other folded into one line. */
169
+ function Turn({ turn, last }) {
170
+ const live = last && turn.status === "working";
171
+ const groups = [];
172
+ for (const part of turn.parts ?? []) {
173
+ const prev = groups[groups.length - 1];
174
+ if (part.type === "step") {
175
+ if (prev?.type === "steps") prev.steps.push(part);
176
+ else groups.push({ type: "steps", steps: [part] });
177
+ } else if (part.text?.trim()) groups.push(part);
178
+ }
179
+ return (
180
+ <div className="grid min-w-0 gap-2">
181
+ {turn.member ? <MemberWords>{turn.member}</MemberWords> : null}
182
+ {groups.map((g, i) =>
183
+ g.type === "steps" ? (
184
+ <Steps key={i} steps={g.steps} live={live && i === groups.length - 1 && !turn.writing} />
185
+ ) : (
186
+ <Prose key={i} text={g.text} />
187
+ ),
188
+ )}
189
+ {turn.writing ? (
190
+ <Prose text={`${turn.writing}▍`} />
191
+ ) : live && !groups.length ? (
192
+ <div className="flex items-center gap-2 text-xs text-muted-foreground">
193
+ <Spinner size="sm" label="Working" /> Thinking…
194
+ </div>
195
+ ) : null}
196
+ {turn.status === "stopped" ? <p className="text-xs text-muted-foreground">Stopped.</p> : null}
197
+ {turn.status === "failed" ? <p className="text-xs text-destructive">It didn't finish. Ask again, or open it on the desk.</p> : null}
198
+ </div>
199
+ );
200
+ }
201
+
202
+ /**
203
+ * chat what useAgentThread() returns (required)
204
+ * title the head's words ("Ask about Pinewood"); default "Ask the agent"
205
+ * suggestions asks that fit the moment, shown before the first ask
206
+ * empty one line before the first ask
207
+ * placeholder the box's words
208
+ * yes a node drawn in the needs slot when the agent waits on a
209
+ * yes the app can take (`chat.needs.in_app === "press"`):
210
+ * the `approval` block, fed by useApproval(chat.request.id)
211
+ * (D18). Without it that yes opens the desk
212
+ * onClose a close in the head (a panel beside a record)
213
+ * bare no head (inside a Sheet or a Card that has its own)
214
+ * fill take the height of its container (default). false: a
215
+ * compact chat whose thread scrolls inside a capped height,
216
+ * for a card in a column
217
+ * className layout around it. Never colour.
218
+ */
219
+ export function AgentChat({
220
+ chat,
221
+ title = "Ask the agent",
222
+ suggestions = [],
223
+ empty,
224
+ placeholder,
225
+ yes,
226
+ onClose,
227
+ bare = false,
228
+ fill = true,
229
+ className,
230
+ }) {
231
+ const [text, setText] = useState("");
232
+ const listRef = useRef(null);
233
+ const turns = chat?.turns ?? [];
234
+ const pending = chat?.pending && !turns.some((t) => t.member === chat.pending) ? chat.pending : null;
235
+ const lastTurn = turns[turns.length - 1];
236
+ const writing = lastTurn?.writing ?? "";
237
+ const needs = chat?.state === "needs_you" ? (chat.needs ?? { kind: "other", text: "" }) : null;
238
+ const live = chat?.state === "working" || chat?.state === "queued" || Boolean(pending);
239
+ const started = turns.length > 0 || Boolean(pending);
240
+ const inMakersclaw = chat?.place === "makersclaw";
241
+
242
+ // The newest words stay in view while the agent writes.
243
+ useEffect(() => {
244
+ const el = listRef.current;
245
+ if (el) el.scrollTop = el.scrollHeight;
246
+ }, [turns.length, writing, pending, lastTurn?.parts?.length, chat?.state]);
247
+
248
+ const send = (words) => {
249
+ const t = String(words ?? text).trim();
250
+ if (!t || !chat?.send) return;
251
+ setText("");
252
+ chat.send(t);
253
+ };
254
+ const answerHere = needs?.in_app === "answer" && typeof chat?.answer === "function";
255
+ const pressHere = needs?.in_app === "press" && yes != null && yes !== false;
256
+ const blocked = Boolean(needs) || inMakersclaw;
257
+
258
+ return (
259
+ <div className={cx("flex min-w-0 flex-col bg-background text-sm", fill && "h-full min-h-0", className)}>
260
+ {!bare ? (
261
+ <div className="flex h-10 shrink-0 items-center gap-2 border-b border-border pl-3.5 pr-2 font-semibold">
262
+ <Icon name="sparkles" size={16} className="shrink-0 text-primary" />
263
+ <span className="min-w-0 flex-1 truncate">{title}</span>
264
+ {started && chat?.newChat ? <IconButton icon="plus" size="sm" label="New chat" onClick={chat.newChat} /> : null}
265
+ {onClose ? <IconButton icon="x" size="sm" label="Close" onClick={onClose} /> : null}
266
+ </div>
267
+ ) : null}
268
+
269
+ <div
270
+ ref={listRef}
271
+ role="log"
272
+ aria-live="polite"
273
+ aria-label={title}
274
+ className={cx(
275
+ "grid min-w-0 content-start gap-3 overflow-y-auto overscroll-contain p-3.5",
276
+ fill ? "min-h-0 flex-1" : started ? "max-h-96" : "",
277
+ )}
278
+ >
279
+ {inMakersclaw ? (
280
+ <Notice
281
+ tone="info"
282
+ title="This ask is in Makersclaw"
283
+ action={
284
+ <Button size="sm" variant="secondary" onClick={() => chat.openOnDesk?.()}>
285
+ Open <Icon name="external" size={12} />
286
+ </Button>
287
+ }
288
+ >
289
+ {chat.request?.title ?? "It is followed there."}
290
+ </Notice>
291
+ ) : (
292
+ <>
293
+ {turns.map((t, i) => (
294
+ <Turn key={t.id ?? i} turn={t} last={i === turns.length - 1 && !pending} />
295
+ ))}
296
+ {pending ? (
297
+ <div className="grid min-w-0 gap-2">
298
+ <MemberWords>{pending}</MemberWords>
299
+ <div className="flex items-center gap-2 text-xs text-muted-foreground">
300
+ <Spinner size="sm" label="Starting" /> Starting…
301
+ </div>
302
+ </div>
303
+ ) : null}
304
+ </>
305
+ )}
306
+ {!started && !inMakersclaw ? (
307
+ <>
308
+ {empty ? <p className="text-muted-foreground">{empty}</p> : null}
309
+ {chat?.loading ? (
310
+ <div className="flex items-center gap-2 text-xs text-muted-foreground">
311
+ <Spinner size="sm" label="Loading" /> Opening the chat…
312
+ </div>
313
+ ) : null}
314
+ {suggestions.length ? (
315
+ <div className="flex min-w-0 flex-wrap gap-1.5">
316
+ {suggestions.map((s) => (
317
+ <button
318
+ key={s}
319
+ type="button"
320
+ onClick={() => send(s)}
321
+ className="flex max-w-full min-w-0 items-start gap-1.5 rounded-[var(--radius)] border border-border px-2.5 py-1 text-left text-xs hover:bg-muted focus-visible:outline-2 focus-visible:outline-ring"
322
+ >
323
+ <Icon name="sparkles" size={12} className="mt-0.5 shrink-0 text-muted-foreground" />
324
+ <span className="min-w-0 break-words">{s}</span>
325
+ </button>
326
+ ))}
327
+ </div>
328
+ ) : null}
329
+ </>
330
+ ) : null}
331
+ </div>
332
+
333
+ {needs && pressHere ? (
334
+ <div className="max-h-[70%] shrink-0 overflow-y-auto border-t border-border p-2.5">{yes}</div>
335
+ ) : needs ? (
336
+ <div className="shrink-0 border-t border-border p-2.5">
337
+ <div className="grid min-w-0 gap-2 rounded-[var(--radius)] border border-warning p-2.5">
338
+ <div className="flex min-w-0 items-start gap-2">
339
+ <Icon name="warning" size={16} className="mt-px shrink-0 text-warning" />
340
+ <div className="grid min-w-0 gap-0.5">
341
+ <span className="font-medium">{needsTitle(needs.kind, answerHere ? "answer" : needs.in_app)}</span>
342
+ {needs.text ? <span className={cx("break-words text-muted-foreground", !answerHere && "line-clamp-3")}>{needs.text}</span> : null}
343
+ </div>
344
+ </div>
345
+ {answerHere ? (
346
+ <QuestionBox options={needs.options ?? []} free={needs.free} onAnswer={(payload) => chat.answer(payload)} />
347
+ ) : (
348
+ <Button size="sm" variant="primary" className="justify-self-start" onClick={() => chat.openOnDesk?.()}>
349
+ Open on the desk <Icon name="external" size={12} />
350
+ </Button>
351
+ )}
352
+ </div>
353
+ </div>
354
+ ) : live && !inMakersclaw ? (
355
+ <div className="flex shrink-0 items-center gap-2 border-t border-border px-3.5 py-1.5 text-xs text-muted-foreground">
356
+ <Spinner size="sm" label="Working" />
357
+ <span className="min-w-0 flex-1 truncate">{STATE_LINE[chat?.state] ?? STATE_LINE.working}</span>
358
+ {chat?.request?.id && chat?.stop ? (
359
+ <Button size="sm" variant="quiet" onClick={() => chat.stop()}>
360
+ <Icon name="stop" size={12} /> Stop
361
+ </Button>
362
+ ) : null}
363
+ </div>
364
+ ) : null}
365
+ {chat?.error ? <p className="shrink-0 px-3.5 pt-2 text-xs text-destructive">{chat.error}</p> : null}
366
+ {chat?.unavailable ? (
367
+ <p className="shrink-0 px-3.5 pt-2 text-xs text-muted-foreground">
368
+ This chat needs a newer Makersclaw.{" "}
369
+ {chat.request ? (
370
+ <Button variant="link" size="inherit" onClick={() => chat.openOnDesk?.()}>
371
+ Open it on the desk
372
+ </Button>
373
+ ) : null}
374
+ </p>
375
+ ) : null}
376
+
377
+ <form
378
+ className="flex shrink-0 items-end gap-2 border-t border-border px-3 py-2.5"
379
+ onSubmit={(e) => {
380
+ e.preventDefault();
381
+ send();
382
+ }}
383
+ >
384
+ <Textarea
385
+ aria-label={title}
386
+ autoGrow
387
+ minRows={1}
388
+ maxRows={6}
389
+ placeholder={
390
+ blocked
391
+ ? needs
392
+ ? answerHere
393
+ ? "Answer above first"
394
+ : pressHere
395
+ ? "Say yes above first"
396
+ : "Answer on the desk first"
397
+ : "This ask is in Makersclaw"
398
+ : (placeholder ?? "Ask anything…")
399
+ }
400
+ value={text}
401
+ disabled={blocked}
402
+ onChange={(e) => setText(e.target.value)}
403
+ onKeyDown={(e) => {
404
+ if (e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
405
+ e.preventDefault();
406
+ send();
407
+ }
408
+ }}
409
+ className="min-w-0 flex-1"
410
+ />
411
+ <IconButton icon="arrow-up" label="Send" variant="primary" size="sm" type="submit" disabled={blocked || !text.trim() || chat?.sending} />
412
+ </form>
413
+ </div>
414
+ );
415
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "agent-chat",
3
+ "title": "AgentChat",
4
+ "description": "The app's own chat with its agent, in the app's look: the member's words, the agent's answer as it is written, one line per step (\"Worked through 6 steps\"), Stop while it works, and what waits on the member settled in place — the agent's question is answered in the chat (its options, and the member's own words where it welcomes them), and its yes is the `approval` block's press frame, handed in as `yes`; a need the app cannot settle (connecting an account, spending money) says so and links to the desk. It draws what useAgentThread() returns (lib/hooks.js): the same conversation the desk's agent column shows, one session, two views. Optional row makes it a chat about one record. fill=false for a compact card in a column.",
5
+ "useWhen": "The app should hold its conversation with its agent: an Ask panel beside a record, an ask box on a home screen, a sheet behind an Ask button. Place it and set \"agent_in_app\": true in the package's blueprint, so the desk keeps its agent column folded for the app. For work the founder commissions from a verb and watches land, use job-panel.",
6
+ "tags": [
7
+ "chat",
8
+ "ask",
9
+ "assistant",
10
+ "conversation",
11
+ "thread",
12
+ "messages",
13
+ "ai",
14
+ "copilot",
15
+ "stop",
16
+ "needs-you",
17
+ "inspector",
18
+ "record"
19
+ ],
20
+ "exports": [
21
+ "AgentChat"
22
+ ],
23
+ "files": [
24
+ "index.js",
25
+ "agent-chat.jsx"
26
+ ],
27
+ "requires": [
28
+ "needs-you"
29
+ ]
30
+ }
@@ -0,0 +1,165 @@
1
+ "use client";
2
+
3
+ // AgentChat driven by a pretend thread — the gallery's and the smoke
4
+ // test's surface. Not installed into apps. A send answers with two steps
5
+ // and a reply written a few words at a time; "send them" stops for a yes,
6
+ // pressed in the approval card above the box; "which list" stops for a
7
+ // question, answered in the chat's bar (0.8.1, D18/D19). The same chat as
8
+ // a compact card sits beside it.
9
+ import { useEffect, useRef, useState } from "react";
10
+ import { Card } from "../components/ui";
11
+ import { AgentChat } from "../components/blocks/agent-chat";
12
+ import { Approval } from "../components/blocks/approval";
13
+
14
+ // A stand-in for the Makersclaw press frame (a page in another origin in
15
+ // an app): inline styles and the browser's colour names only.
16
+ const FRAME = (scheme) =>
17
+ `<!doctype html><meta charset="utf-8"><meta name="color-scheme" content="${scheme}">` +
18
+ `<body style="margin:0;font:14px/1.45 system-ui,sans-serif"><main style="border:1px solid GrayText;border-radius:10px;padding:12px 14px;display:grid;gap:8px">` +
19
+ `<b>Send 12 follow-ups from ada@acme.com to the investors on the list?</b>` +
20
+ `<span style="display:flex;gap:8px;justify-content:flex-end"><button style="font:inherit;padding:8px 14px;border-radius:8px;border:1px solid GrayText;background:transparent;color:inherit">Not now</button>` +
21
+ `<button style="font:inherit;font-weight:600;padding:8px 14px;border-radius:8px;border:0;background:Highlight;color:HighlightText">Send 12</button></span></main>`;
22
+
23
+ function usePretendThread() {
24
+ const [turns, setTurns] = useState([]);
25
+ const [state, setState] = useState(null);
26
+ const [needs, setNeeds] = useState(null);
27
+ const timers = useRef([]);
28
+ useEffect(() => () => timers.current.forEach(clearTimeout), []);
29
+ const later = (ms, fn) => timers.current.push(setTimeout(fn, ms));
30
+ const patchLast = (fn) => setTurns((ts) => ts.map((t, i) => (i === ts.length - 1 ? fn(t) : t)));
31
+
32
+ const send = (text) => {
33
+ const id = `t${Date.now()}`;
34
+ setState("working");
35
+ setNeeds(null);
36
+ setTurns((ts) => [...ts, { id, member: text, parts: [], writing: "", status: "working" }]);
37
+ later(400, () => patchLast((t) => ({ ...t, parts: [{ type: "step", label: "Reading the people", status: "running" }] })));
38
+ later(1100, () =>
39
+ patchLast((t) => ({
40
+ ...t,
41
+ parts: [
42
+ { type: "step", label: "Reading the people", status: "done" },
43
+ { type: "step", label: "Searching the web", status: "running" },
44
+ ],
45
+ })),
46
+ );
47
+ if (/send/i.test(text)) {
48
+ later(1900, () => {
49
+ patchLast((t) => ({ ...t, parts: t.parts.map((p) => ({ ...p, status: "done" })), status: "waiting" }));
50
+ setState("needs_you");
51
+ setNeeds({ kind: "yes", in_app: "press", text: "Send 12 follow-ups from ada@acme.com to the investors on the list?" });
52
+ });
53
+ return;
54
+ }
55
+ if (/which|list/i.test(text)) {
56
+ later(1900, () => {
57
+ patchLast((t) => ({ ...t, parts: t.parts.map((p) => ({ ...p, status: "done" })), status: "waiting" }));
58
+ setState("needs_you");
59
+ setNeeds({
60
+ kind: "question",
61
+ in_app: "answer",
62
+ text: "Which list should I start with?",
63
+ options: [
64
+ { id: "warm", label: "Warm leads" },
65
+ { id: "cold", label: "Cold" },
66
+ ],
67
+ free: true,
68
+ });
69
+ });
70
+ return;
71
+ }
72
+ const reply = "I found **12 investors** who back seed-stage fintech:\n\n- Pennant Capital — met in March\n- Harbor Seed — warm intro from Ana\n- Lowline Ventures\n\nWant me to draft a first note to each?";
73
+ const words = reply.split(" ");
74
+ words.forEach((_, i) =>
75
+ later(1800 + i * 60, () => patchLast((t) => ({ ...t, writing: words.slice(0, i + 1).join(" ") }))),
76
+ );
77
+ later(1900 + words.length * 60, () => {
78
+ patchLast((t) => ({
79
+ ...t,
80
+ parts: [...t.parts.map((p) => ({ ...p, status: "done" })), { type: "text", text: reply }],
81
+ writing: "",
82
+ status: "done",
83
+ }));
84
+ setState("done");
85
+ });
86
+ };
87
+
88
+ return {
89
+ sessionId: turns.length ? "demo" : null,
90
+ state,
91
+ needs,
92
+ turns,
93
+ place: "app",
94
+ request: turns.length ? { id: "demo-request", title: "Investors" } : null,
95
+ pending: null,
96
+ sending: false,
97
+ loading: false,
98
+ error: null,
99
+ unavailable: false,
100
+ send,
101
+ // The agent's question, answered where it was asked (D19).
102
+ answer: async ({ optionId, text }) => {
103
+ setNeeds(null);
104
+ setState("working");
105
+ later(900, () => {
106
+ patchLast((t) => ({
107
+ ...t,
108
+ parts: [...t.parts, { type: "text", text: `Starting with ${optionId ? optionId : `“${text}”`}. I'll draft the first three now.` }],
109
+ status: "done",
110
+ }));
111
+ setState("done");
112
+ });
113
+ return { ok: true };
114
+ },
115
+ needsAt: "demo",
116
+ stop: () => {
117
+ timers.current.forEach(clearTimeout);
118
+ patchLast((t) => ({ ...t, writing: "", status: "stopped" }));
119
+ setState("stopped");
120
+ },
121
+ openOnDesk: () => true,
122
+ newChat: () => {
123
+ setTurns([]);
124
+ setState(null);
125
+ setNeeds(null);
126
+ },
127
+ reload: () => undefined,
128
+ };
129
+ }
130
+
131
+ export default function AgentChatDemo() {
132
+ const chat = usePretendThread();
133
+ const card = usePretendThread();
134
+ // The yes, as useApproval(chat.request.id) would hand it: the frame is a stand-in.
135
+ const [scheme, setScheme] = useState("light dark");
136
+ useEffect(() => {
137
+ const read = getComputedStyle(document.documentElement).colorScheme;
138
+ if (read && read !== "normal") setScheme(read);
139
+ }, []);
140
+ const frameRef = useRef(null);
141
+ const approval = {
142
+ approval: { request_id: "demo-request", question: "Send 12?", label: "Send 12" },
143
+ state: "ready",
144
+ always: false,
145
+ fallback: false,
146
+ frame: { srcDoc: FRAME(scheme), ref: frameRef, title: "Approve" },
147
+ height: 170,
148
+ };
149
+ return (
150
+ <div className="grid gap-6 p-6 lg:grid-cols-[minmax(0,1fr)_320px]">
151
+ <div className="h-[560px] min-w-0 overflow-hidden rounded-lg border border-border">
152
+ <AgentChat
153
+ chat={chat}
154
+ title="Ask about Pinewood"
155
+ empty="The agent reads Pinewood's story, its deals and its people."
156
+ suggestions={["Who should we follow up with?", "Find restaurant groups in New England with 10 or more sites", "Send them a note", "Which list first?"]}
157
+ yes={<Approval approval={approval} title="Send 12 follow-ups" />}
158
+ />
159
+ </div>
160
+ <Card title="Or ask" padding="none" className="min-w-0 overflow-hidden">
161
+ <AgentChat chat={card} title="Ask the agent" bare fill={false} suggestions={["Who is waiting on me?", "What closes this month?"]} />
162
+ </Card>
163
+ </div>
164
+ );
165
+ }
@@ -0,0 +1,3 @@
1
+ // The AgentChat block — `makersclaw add agent-chat`. Fixed: compose it
2
+ // through its props (README.md beside this file).
3
+ export { AgentChat } from "./agent-chat";