makersclaw 0.7.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (419) hide show
  1. package/README.md +17 -4
  2. package/package.json +1 -1
  3. package/r/activity-log.json +52 -0
  4. package/r/agent-changes.json +51 -0
  5. package/r/agent-chat.json +53 -0
  6. package/r/agent-column.json +85 -0
  7. package/r/agent-dock.json +57 -0
  8. package/r/agent-kit.json +49 -0
  9. package/r/agent-marks.json +49 -0
  10. package/r/agent-pane.json +93 -0
  11. package/r/ai-action.json +56 -0
  12. package/r/annotate.json +4 -4
  13. package/r/approval-request.json +2 -2
  14. package/r/approval.json +54 -0
  15. package/r/ask-bar.json +50 -0
  16. package/r/audio-player.json +2 -2
  17. package/r/auth-form.json +2 -2
  18. package/r/automation-editor.json +66 -0
  19. package/r/automation-list.json +57 -0
  20. package/r/automation-model.json +118 -0
  21. package/r/automations-screen.json +71 -0
  22. package/r/board.json +2 -2
  23. package/r/calendar-view.json +3 -3
  24. package/r/cart.json +2 -2
  25. package/r/chart.json +5 -5
  26. package/r/chat-pane.json +84 -0
  27. package/r/chat.json +3 -3
  28. package/r/code-editor.json +2 -2
  29. package/r/comment-box.json +3 -3
  30. package/r/connect-card.json +51 -0
  31. package/r/contact-section.json +2 -2
  32. package/r/core.json +18 -6
  33. package/r/cost.json +51 -0
  34. package/r/csv-import.json +3 -3
  35. package/r/data-picker.json +60 -0
  36. package/r/data-table.json +2 -2
  37. package/r/diagram.json +2 -2
  38. package/r/doc-editor.json +2 -2
  39. package/r/doc-page.json +3 -3
  40. package/r/email-render.json +2 -2
  41. package/r/faq.json +2 -2
  42. package/r/file-upload.json +2 -2
  43. package/r/first-run.json +63 -0
  44. package/r/fix-note.json +57 -0
  45. package/r/flow-canvas.json +3 -3
  46. package/r/flow-editor.json +79 -0
  47. package/r/footer.json +3 -3
  48. package/r/gantt.json +3 -3
  49. package/r/job-panel.json +2 -2
  50. package/r/json-editor.json +3 -3
  51. package/r/library-shelf.json +56 -0
  52. package/r/map.json +2 -2
  53. package/r/margin-notes.json +67 -0
  54. package/r/menubar.json +2 -2
  55. package/r/mind-map.json +4 -4
  56. package/r/navigation-menu.json +2 -2
  57. package/r/needs-you.json +55 -0
  58. package/r/order-detail.json +2 -2
  59. package/r/org-chart.json +4 -4
  60. package/r/pace-bar.json +69 -0
  61. package/r/page-builder.json +3 -3
  62. package/r/payment-methods.json +2 -2
  63. package/r/pdf-document.json +2 -2
  64. package/r/pdf-viewer.json +3 -3
  65. package/r/product-detail.json +2 -2
  66. package/r/product-grid.json +3 -3
  67. package/r/record-form.json +2 -2
  68. package/r/record-grid.json +52 -0
  69. package/r/record-notes.json +4 -4
  70. package/r/registry.json +4089 -1510
  71. package/r/run-history.json +52 -0
  72. package/r/run-view.json +80 -0
  73. package/r/schedule-card.json +54 -0
  74. package/r/schedule-engine.json +79 -0
  75. package/r/schedule-gantt.json +83 -0
  76. package/r/schedule-ruler.json +64 -0
  77. package/r/search-dialog.json +2 -2
  78. package/r/settings-list.json +2 -2
  79. package/r/setup-checklist.json +2 -2
  80. package/r/share-dialog.json +2 -2
  81. package/r/sidebar.json +3 -3
  82. package/r/signature-pad.json +2 -2
  83. package/r/sketch-canvas.json +3 -3
  84. package/r/source-receipt.json +52 -0
  85. package/r/spreadsheet.json +3 -3
  86. package/r/stat-cards.json +3 -3
  87. package/r/step-picker.json +53 -0
  88. package/r/step-settings.json +72 -0
  89. package/r/suggestion.json +58 -0
  90. package/r/sum-bar.json +64 -0
  91. package/r/task-list.json +3 -3
  92. package/r/task-model.json +2 -2
  93. package/r/testimonials.json +2 -2
  94. package/r/tier-map.json +67 -0
  95. package/r/time-grid.json +73 -0
  96. package/r/time-strip.json +64 -0
  97. package/r/top-bar.json +66 -0
  98. package/r/transaction-list.json +2 -2
  99. package/r/trigger-picker.json +61 -0
  100. package/r/whiteboard.json +4 -4
  101. package/r/workflow-view.json +55 -0
  102. package/registry/blocks/activity-log/README.md +112 -0
  103. package/registry/blocks/activity-log/activity-log.jsx +351 -0
  104. package/registry/blocks/activity-log/block.json +33 -0
  105. package/registry/blocks/activity-log/demo.jsx +48 -0
  106. package/registry/blocks/activity-log/index.js +4 -0
  107. package/registry/blocks/agent-changes/README.md +94 -0
  108. package/registry/blocks/agent-changes/agent-changes.jsx +118 -0
  109. package/registry/blocks/agent-changes/block.json +28 -0
  110. package/registry/blocks/agent-changes/demo.jsx +39 -0
  111. package/registry/blocks/agent-changes/index.js +3 -0
  112. package/registry/blocks/agent-chat/README.md +145 -0
  113. package/registry/blocks/agent-chat/agent-chat.jsx +415 -0
  114. package/registry/blocks/agent-chat/block.json +30 -0
  115. package/registry/blocks/agent-chat/demo.jsx +165 -0
  116. package/registry/blocks/agent-chat/index.js +3 -0
  117. package/registry/blocks/agent-column/README.md +197 -0
  118. package/registry/blocks/agent-column/agent-column.jsx +492 -0
  119. package/registry/blocks/agent-column/block.json +67 -0
  120. package/registry/blocks/agent-column/column-picker.jsx +163 -0
  121. package/registry/blocks/agent-column/demo.jsx +50 -0
  122. package/registry/blocks/agent-column/index.js +7 -0
  123. package/registry/blocks/agent-column/model.js +164 -0
  124. package/registry/blocks/agent-column/receipt.jsx +483 -0
  125. package/registry/blocks/agent-column/spreadsheet-type.jsx +24 -0
  126. package/registry/blocks/agent-dock/README.md +210 -0
  127. package/registry/blocks/agent-dock/agent-dock.jsx +356 -0
  128. package/registry/blocks/agent-dock/block.json +47 -0
  129. package/registry/blocks/agent-dock/demo.jsx +153 -0
  130. package/registry/blocks/agent-dock/dock-model.js +118 -0
  131. package/registry/blocks/agent-dock/index.js +5 -0
  132. package/registry/blocks/agent-kit/README.md +73 -0
  133. package/registry/blocks/agent-kit/agent-kit.jsx +86 -0
  134. package/registry/blocks/agent-kit/block.json +10 -0
  135. package/registry/blocks/agent-kit/demo.jsx +35 -0
  136. package/registry/blocks/agent-kit/index.js +3 -0
  137. package/registry/blocks/agent-marks/README.md +80 -0
  138. package/registry/blocks/agent-marks/agent-marks.jsx +133 -0
  139. package/registry/blocks/agent-marks/block.json +27 -0
  140. package/registry/blocks/agent-marks/demo.jsx +49 -0
  141. package/registry/blocks/agent-marks/index.js +3 -0
  142. package/registry/blocks/agent-pane/README.md +225 -0
  143. package/registry/blocks/agent-pane/agent-pane.jsx +244 -0
  144. package/registry/blocks/agent-pane/block.json +41 -0
  145. package/registry/blocks/agent-pane/composer.jsx +6 -0
  146. package/registry/blocks/agent-pane/demo.jsx +233 -0
  147. package/registry/blocks/agent-pane/dock-context.js +10 -0
  148. package/registry/blocks/agent-pane/index.js +4 -0
  149. package/registry/blocks/agent-pane/prose.jsx +84 -0
  150. package/registry/blocks/agent-pane/questions.jsx +134 -0
  151. package/registry/blocks/agent-pane/transcript.jsx +268 -0
  152. package/registry/blocks/agent-pane/work.jsx +368 -0
  153. package/registry/blocks/ai-action/README.md +94 -0
  154. package/registry/blocks/ai-action/ai-action.jsx +188 -0
  155. package/registry/blocks/ai-action/block.json +34 -0
  156. package/registry/blocks/ai-action/demo.jsx +93 -0
  157. package/registry/blocks/ai-action/index.js +3 -0
  158. package/registry/blocks/annotate/README.md +14 -11
  159. package/registry/blocks/approval/README.md +145 -0
  160. package/registry/blocks/approval/approval.jsx +163 -0
  161. package/registry/blocks/approval/block.json +31 -0
  162. package/registry/blocks/approval/demo.jsx +121 -0
  163. package/registry/blocks/approval/index.js +3 -0
  164. package/registry/blocks/ask-bar/README.md +105 -0
  165. package/registry/blocks/ask-bar/ask-bar.jsx +166 -0
  166. package/registry/blocks/ask-bar/block.json +26 -0
  167. package/registry/blocks/ask-bar/demo.jsx +78 -0
  168. package/registry/blocks/ask-bar/index.js +3 -0
  169. package/registry/blocks/automation-editor/README.md +291 -0
  170. package/registry/blocks/automation-editor/automation-editor.jsx +656 -0
  171. package/registry/blocks/automation-editor/block.json +39 -0
  172. package/registry/blocks/automation-editor/demo.jsx +284 -0
  173. package/registry/blocks/automation-editor/index.js +4 -0
  174. package/registry/blocks/automation-editor/run-inputs.jsx +82 -0
  175. package/registry/blocks/automation-list/README.md +129 -0
  176. package/registry/blocks/automation-list/automation-list.jsx +476 -0
  177. package/registry/blocks/automation-list/block.json +35 -0
  178. package/registry/blocks/automation-list/demo.jsx +67 -0
  179. package/registry/blocks/automation-list/index.js +3 -0
  180. package/registry/blocks/automation-model/README.md +109 -0
  181. package/registry/blocks/automation-model/block.json +135 -0
  182. package/registry/blocks/automation-model/catalog.js +256 -0
  183. package/registry/blocks/automation-model/check.js +161 -0
  184. package/registry/blocks/automation-model/demo.jsx +42 -0
  185. package/registry/blocks/automation-model/edit.js +262 -0
  186. package/registry/blocks/automation-model/fixes.js +287 -0
  187. package/registry/blocks/automation-model/glyph.jsx +13 -0
  188. package/registry/blocks/automation-model/graph.js +410 -0
  189. package/registry/blocks/automation-model/index.js +33 -0
  190. package/registry/blocks/automation-model/overlay.js +175 -0
  191. package/registry/blocks/automation-model/parts.jsx +94 -0
  192. package/registry/blocks/automation-model/schedule.js +53 -0
  193. package/registry/blocks/automation-model/templates.js +128 -0
  194. package/registry/blocks/automation-model/values.js +29 -0
  195. package/registry/blocks/automation-model/words.js +439 -0
  196. package/registry/blocks/automations-screen/README.md +207 -0
  197. package/registry/blocks/automations-screen/automations-screen.jsx +452 -0
  198. package/registry/blocks/automations-screen/block.json +47 -0
  199. package/registry/blocks/automations-screen/demo.jsx +364 -0
  200. package/registry/blocks/automations-screen/index.js +4 -0
  201. package/registry/blocks/automations-screen/screen-model.js +129 -0
  202. package/registry/blocks/chart/cartesian.jsx +1 -1
  203. package/registry/blocks/chart/core.jsx +33 -23
  204. package/registry/blocks/chart/pie.jsx +1 -1
  205. package/registry/blocks/chat/README.md +4 -1
  206. package/registry/blocks/chat/demo.jsx +2 -2
  207. package/registry/blocks/chat-pane/README.md +143 -0
  208. package/registry/blocks/chat-pane/block.json +48 -0
  209. package/registry/blocks/chat-pane/chat-attach.js +166 -0
  210. package/registry/blocks/chat-pane/chat-composer.jsx +195 -0
  211. package/registry/blocks/chat-pane/chat-context.js +17 -0
  212. package/registry/blocks/chat-pane/chat-model.js +43 -0
  213. package/registry/blocks/chat-pane/chat-pane.jsx +398 -0
  214. package/registry/blocks/chat-pane/chats-list.jsx +52 -0
  215. package/registry/blocks/chat-pane/demo.jsx +103 -0
  216. package/registry/blocks/chat-pane/index.js +9 -0
  217. package/registry/blocks/connect-card/README.md +99 -0
  218. package/registry/blocks/connect-card/block.json +10 -0
  219. package/registry/blocks/connect-card/connect-card.jsx +103 -0
  220. package/registry/blocks/connect-card/demo.jsx +49 -0
  221. package/registry/blocks/connect-card/index.js +3 -0
  222. package/registry/blocks/cost/README.md +115 -0
  223. package/registry/blocks/cost/block.json +10 -0
  224. package/registry/blocks/cost/cost.jsx +176 -0
  225. package/registry/blocks/cost/demo.jsx +66 -0
  226. package/registry/blocks/cost/index.js +3 -0
  227. package/registry/blocks/data-picker/README.md +81 -0
  228. package/registry/blocks/data-picker/block.json +38 -0
  229. package/registry/blocks/data-picker/data-picker.jsx +210 -0
  230. package/registry/blocks/data-picker/demo.jsx +34 -0
  231. package/registry/blocks/data-picker/fields.js +89 -0
  232. package/registry/blocks/data-picker/index.js +4 -0
  233. package/registry/blocks/data-table/demo.jsx +1 -1
  234. package/registry/blocks/first-run/README.md +118 -0
  235. package/registry/blocks/first-run/block.json +11 -0
  236. package/registry/blocks/first-run/demo.jsx +88 -0
  237. package/registry/blocks/first-run/first-run-model.js +51 -0
  238. package/registry/blocks/first-run/first-run.jsx +156 -0
  239. package/registry/blocks/first-run/index.js +5 -0
  240. package/registry/blocks/first-run/probe-rules.js +26 -0
  241. package/registry/blocks/fix-note/README.md +79 -0
  242. package/registry/blocks/fix-note/block.json +35 -0
  243. package/registry/blocks/fix-note/demo.jsx +30 -0
  244. package/registry/blocks/fix-note/fix-note.jsx +235 -0
  245. package/registry/blocks/fix-note/index.js +3 -0
  246. package/registry/blocks/flow-canvas/README.md +15 -8
  247. package/registry/blocks/flow-editor/README.md +108 -0
  248. package/registry/blocks/flow-editor/block.json +44 -0
  249. package/registry/blocks/flow-editor/demo.jsx +115 -0
  250. package/registry/blocks/flow-editor/flow-canvas.jsx +568 -0
  251. package/registry/blocks/flow-editor/flow-editor.jsx +154 -0
  252. package/registry/blocks/flow-editor/index.js +6 -0
  253. package/registry/blocks/flow-editor/minimap.jsx +78 -0
  254. package/registry/blocks/flow-editor/outline.jsx +134 -0
  255. package/registry/blocks/footer/README.md +3 -2
  256. package/registry/blocks/library-shelf/README.md +117 -0
  257. package/registry/blocks/library-shelf/block.json +28 -0
  258. package/registry/blocks/library-shelf/demo.jsx +68 -0
  259. package/registry/blocks/library-shelf/index.js +3 -0
  260. package/registry/blocks/library-shelf/library-shelf.jsx +211 -0
  261. package/registry/blocks/library-shelf/probe-rules.js +15 -0
  262. package/registry/blocks/margin-notes/README.md +222 -0
  263. package/registry/blocks/margin-notes/block.json +10 -0
  264. package/registry/blocks/margin-notes/demo.jsx +144 -0
  265. package/registry/blocks/margin-notes/index.js +20 -0
  266. package/registry/blocks/margin-notes/margin-model.js +224 -0
  267. package/registry/blocks/margin-notes/margin-notes.jsx +465 -0
  268. package/registry/blocks/mind-map/README.md +4 -2
  269. package/registry/blocks/needs-you/README.md +177 -0
  270. package/registry/blocks/needs-you/block.json +34 -0
  271. package/registry/blocks/needs-you/demo.jsx +143 -0
  272. package/registry/blocks/needs-you/index.js +3 -0
  273. package/registry/blocks/needs-you/needs-you.jsx +441 -0
  274. package/registry/blocks/org-chart/README.md +4 -2
  275. package/registry/blocks/pace-bar/README.md +230 -0
  276. package/registry/blocks/pace-bar/block.json +10 -0
  277. package/registry/blocks/pace-bar/demo.jsx +255 -0
  278. package/registry/blocks/pace-bar/index.js +22 -0
  279. package/registry/blocks/pace-bar/pace-bar.jsx +461 -0
  280. package/registry/blocks/pace-bar/pace-model.js +288 -0
  281. package/registry/blocks/page-builder/README.md +1 -1
  282. package/registry/blocks/page-builder/demo.jsx +3 -3
  283. package/registry/blocks/pdf-viewer/README.md +4 -1
  284. package/registry/blocks/record-grid/README.md +100 -0
  285. package/registry/blocks/record-grid/block.json +28 -0
  286. package/registry/blocks/record-grid/demo.jsx +43 -0
  287. package/registry/blocks/record-grid/index.js +3 -0
  288. package/registry/blocks/record-grid/record-grid.jsx +251 -0
  289. package/registry/blocks/run-history/README.md +138 -0
  290. package/registry/blocks/run-history/block.json +10 -0
  291. package/registry/blocks/run-history/demo.jsx +74 -0
  292. package/registry/blocks/run-history/index.js +3 -0
  293. package/registry/blocks/run-history/run-history.jsx +218 -0
  294. package/registry/blocks/run-view/README.md +174 -0
  295. package/registry/blocks/run-view/block.json +50 -0
  296. package/registry/blocks/run-view/demo.jsx +286 -0
  297. package/registry/blocks/run-view/index.js +5 -0
  298. package/registry/blocks/run-view/run-controls.jsx +266 -0
  299. package/registry/blocks/run-view/run-view.jsx +236 -0
  300. package/registry/blocks/run-view/runs-list.jsx +99 -0
  301. package/registry/blocks/schedule-card/README.md +121 -0
  302. package/registry/blocks/schedule-card/block.json +10 -0
  303. package/registry/blocks/schedule-card/demo.jsx +82 -0
  304. package/registry/blocks/schedule-card/index.js +3 -0
  305. package/registry/blocks/schedule-card/schedule-card.jsx +136 -0
  306. package/registry/blocks/schedule-engine/README.md +137 -0
  307. package/registry/blocks/schedule-engine/block.json +10 -0
  308. package/registry/blocks/schedule-engine/demo.jsx +82 -0
  309. package/registry/blocks/schedule-engine/engine.js +769 -0
  310. package/registry/blocks/schedule-engine/index.js +9 -0
  311. package/registry/blocks/schedule-engine/ops.js +71 -0
  312. package/registry/blocks/schedule-engine/place.js +294 -0
  313. package/registry/blocks/schedule-engine/tree.js +79 -0
  314. package/registry/blocks/schedule-engine/waits.js +80 -0
  315. package/registry/blocks/schedule-gantt/README.md +159 -0
  316. package/registry/blocks/schedule-gantt/block.json +10 -0
  317. package/registry/blocks/schedule-gantt/demo.jsx +223 -0
  318. package/registry/blocks/schedule-gantt/gantt-model.js +219 -0
  319. package/registry/blocks/schedule-gantt/geometry.js +176 -0
  320. package/registry/blocks/schedule-gantt/index.js +26 -0
  321. package/registry/blocks/schedule-gantt/schedule-gantt.jsx +882 -0
  322. package/registry/blocks/schedule-gantt/sheet.jsx +372 -0
  323. package/registry/blocks/schedule-gantt/track.jsx +190 -0
  324. package/registry/blocks/schedule-ruler/README.md +148 -0
  325. package/registry/blocks/schedule-ruler/block.json +10 -0
  326. package/registry/blocks/schedule-ruler/demo.jsx +181 -0
  327. package/registry/blocks/schedule-ruler/index.js +21 -0
  328. package/registry/blocks/schedule-ruler/ruler-model.js +239 -0
  329. package/registry/blocks/schedule-ruler/schedule-ruler.jsx +548 -0
  330. package/registry/blocks/sidebar/README.md +23 -13
  331. package/registry/blocks/sketch-canvas/README.md +15 -9
  332. package/registry/blocks/source-receipt/README.md +97 -0
  333. package/registry/blocks/source-receipt/block.json +30 -0
  334. package/registry/blocks/source-receipt/demo.jsx +71 -0
  335. package/registry/blocks/source-receipt/index.js +3 -0
  336. package/registry/blocks/source-receipt/source-receipt.jsx +107 -0
  337. package/registry/blocks/spreadsheet/spreadsheet.jsx +15 -1
  338. package/registry/blocks/step-picker/README.md +78 -0
  339. package/registry/blocks/step-picker/block.json +31 -0
  340. package/registry/blocks/step-picker/demo.jsx +23 -0
  341. package/registry/blocks/step-picker/index.js +3 -0
  342. package/registry/blocks/step-picker/step-picker.jsx +144 -0
  343. package/registry/blocks/step-settings/README.md +100 -0
  344. package/registry/blocks/step-settings/block.json +44 -0
  345. package/registry/blocks/step-settings/demo.jsx +93 -0
  346. package/registry/blocks/step-settings/fields.jsx +58 -0
  347. package/registry/blocks/step-settings/flow-settings.jsx +115 -0
  348. package/registry/blocks/step-settings/index.js +5 -0
  349. package/registry/blocks/step-settings/step-settings.jsx +290 -0
  350. package/registry/blocks/suggestion/README.md +171 -0
  351. package/registry/blocks/suggestion/block.json +40 -0
  352. package/registry/blocks/suggestion/demo.jsx +91 -0
  353. package/registry/blocks/suggestion/index.js +3 -0
  354. package/registry/blocks/suggestion/suggestion.jsx +436 -0
  355. package/registry/blocks/sum-bar/README.md +122 -0
  356. package/registry/blocks/sum-bar/block.json +10 -0
  357. package/registry/blocks/sum-bar/demo.jsx +110 -0
  358. package/registry/blocks/sum-bar/index.js +5 -0
  359. package/registry/blocks/sum-bar/sum-bar.jsx +209 -0
  360. package/registry/blocks/sum-bar/sum-model.js +126 -0
  361. package/registry/blocks/tier-map/README.md +217 -0
  362. package/registry/blocks/tier-map/block.json +10 -0
  363. package/registry/blocks/tier-map/demo.jsx +222 -0
  364. package/registry/blocks/tier-map/index.js +24 -0
  365. package/registry/blocks/tier-map/tier-map.jsx +574 -0
  366. package/registry/blocks/tier-map/tier-model.js +318 -0
  367. package/registry/blocks/time-grid/README.md +305 -0
  368. package/registry/blocks/time-grid/block.json +10 -0
  369. package/registry/blocks/time-grid/demo.jsx +279 -0
  370. package/registry/blocks/time-grid/grid-model.js +322 -0
  371. package/registry/blocks/time-grid/index.js +25 -0
  372. package/registry/blocks/time-grid/time-grid.jsx +1325 -0
  373. package/registry/blocks/time-strip/README.md +141 -0
  374. package/registry/blocks/time-strip/block.json +10 -0
  375. package/registry/blocks/time-strip/demo.jsx +129 -0
  376. package/registry/blocks/time-strip/index.js +19 -0
  377. package/registry/blocks/time-strip/strip-model.js +178 -0
  378. package/registry/blocks/time-strip/time-strip.jsx +260 -0
  379. package/registry/blocks/top-bar/README.md +149 -0
  380. package/registry/blocks/top-bar/block.json +35 -0
  381. package/registry/blocks/top-bar/demo.jsx +78 -0
  382. package/registry/blocks/top-bar/index.js +5 -0
  383. package/registry/blocks/top-bar/probe-rules.js +74 -0
  384. package/registry/blocks/top-bar/top-bar-model.js +152 -0
  385. package/registry/blocks/top-bar/top-bar.jsx +244 -0
  386. package/registry/blocks/trigger-picker/README.md +98 -0
  387. package/registry/blocks/trigger-picker/block.json +38 -0
  388. package/registry/blocks/trigger-picker/demo.jsx +59 -0
  389. package/registry/blocks/trigger-picker/index.js +3 -0
  390. package/registry/blocks/trigger-picker/trigger-picker.jsx +374 -0
  391. package/registry/blocks/whiteboard/README.md +20 -14
  392. package/registry/blocks/workflow-view/README.md +123 -0
  393. package/registry/blocks/workflow-view/block.json +10 -0
  394. package/registry/blocks/workflow-view/demo.jsx +90 -0
  395. package/registry/blocks/workflow-view/index.js +3 -0
  396. package/registry/blocks/workflow-view/workflow-view.jsx +203 -0
  397. package/src/cli.mjs +2 -2
  398. package/src/install.mjs +100 -22
  399. package/src/registry.mjs +37 -3
  400. package/templates/next/browser/lib/data.js +6 -1
  401. package/templates/next/files/README.md +909 -26
  402. package/templates/next/files/app/shell.jsx +54 -37
  403. package/templates/next/files/check/automation-format.ts +2103 -0
  404. package/templates/next/files/check/automation-package.ts +142 -0
  405. package/templates/next/files/check/run.mjs +1043 -12
  406. package/templates/next/files/components/ui/field.jsx +17 -4
  407. package/templates/next/files/components/ui/icon.jsx +13 -0
  408. package/templates/next/files/components/ui/index.js +3 -1
  409. package/templates/next/files/components/ui/layout.jsx +382 -0
  410. package/templates/next/files/components/ui/notice.jsx +70 -0
  411. package/templates/next/files/components/ui/page.jsx +124 -0
  412. package/templates/next/files/components/ui/stat.jsx +22 -7
  413. package/templates/next/files/components/ui/toast.jsx +6 -3
  414. package/templates/next/files/lib/automations.js +660 -0
  415. package/templates/next/files/lib/claw.js +244 -5
  416. package/templates/next/files/lib/door.js +92 -0
  417. package/templates/next/files/lib/hooks.js +1694 -6
  418. package/templates/next/files/lib/platform.js +611 -14
  419. package/templates/next/template.json +22 -3
@@ -0,0 +1,143 @@
1
+ # ChatPane
2
+
3
+ The desk's chat pane, as the app's own, in the app's theme (0.8.1). The
4
+ founder, after reviewing the app agent's message box next to the
5
+ Automations window's: "add claw's ChatPane as a block in the makersclaw
6
+ template". This is that port: claw's `web/src/os/windows/artifact/ChatPane`
7
+ and the composer of its `EveChat`, in JSX, with the kit's `Icon` and
8
+ `Button` and the app's tokens, talking to the agent through the app's own
9
+ hook (`useAgentPane`, `lib/hooks.js`) instead of `eve/client`.
10
+
11
+ It is the **chrome around a conversation**:
12
+
13
+ - **The head**: the title, **New chat**, **Chats** (the past chats drop over
14
+ the conversation, newest first, with a dot on one that needs you or is
15
+ working), and a close.
16
+ - **The empty state**: before the first ask, one line, the recent chats
17
+ ("No chats yet. Your first message starts one." when there are none), and
18
+ the app's suggestions.
19
+ - **The conversation**: its lines are the children. It stays at the newest
20
+ words until the member scrolls up, then offers a jump to latest.
21
+ - **The bar** between the conversation and the box: what waits on the member,
22
+ or that the agent is working.
23
+ - **The message box**: the desk's composer. **One rounded box.** The words
24
+ on top, full width, growing with what is typed. Under them a row: **+**
25
+ (attach) at the left, and at the right the **microphone** and a **round
26
+ arrow** to send. **While a turn runs, a round stop takes the arrow's
27
+ place** (once the member types, the arrow comes back: a message sent then
28
+ waits its turn, as before). A quiet `hint` can sit under the box.
29
+ - **Files** by the + button, by paste and by a drop anywhere on the pane (up
30
+ to 4 files and 3 MB together); **dictation** where the browser has speech
31
+ recognition; the box **closed** while something waits on the member, with
32
+ the reason in its placeholder.
33
+ - **A starting line** from the dock: `openAgent({ ask })` (blocks/agent-dock).
34
+ The pane sends it as the member's first words in a new chat, or puts it
35
+ in the box. See "Have the agent do it" below.
36
+
37
+ ```jsx
38
+ import { ChatPane } from "../components/blocks/chat-pane"; // a Makersclaw app ("./blocks/chat-pane" from components/)
39
+ import { ChatPane } from "@/components/makersclaw/blocks/chat-pane"; // a shadcn project
40
+ ```
41
+
42
+ A client component. It needs the kit and nothing else; it is not tied to the
43
+ agent's lines. **For the agent's conversation use `agent-pane`**, which
44
+ draws the plan, the work folded into "Worked through N steps", the
45
+ questions, the yes and what the agent made, inside this pane. Use `ChatPane`
46
+ itself for lines of your own in the desk's frame.
47
+
48
+ ## What was ported, and what was not
49
+
50
+ Ported: the head (New chat, Chats), the past chats list and its marks, the
51
+ empty state, the scroll that follows, the composer (its layout, the
52
+ attachments, the dictation, the send and stop), the closed box, and the
53
+ hand-off seam in a form the app needs (the starting line).
54
+
55
+ Not ported, because the app has no such thing: the desk's **rail** beside the
56
+ chat (an app's agent lives in the dock, a column; the Chats overlay is the
57
+ column mode's), the **binding** (headers, scope, the session pointer: the
58
+ app's `useAgentPane` holds those), **`openSession`/`pendingLine`** (the desk's
59
+ hand-off of a request into the agent's chat; the app's starting line does
60
+ that job), **`chatMarks` "In Makersclaw"** (an ask made in Makersclaw shows
61
+ as a pointer in the conversation instead) and the wallet gate (the platform
62
+ refuses a turn with no credits and says so).
63
+
64
+ ## Props
65
+
66
+ - `chat` — what `useAgentPane()` returns. Required. The pane calls its
67
+ `send(text, { files })`, `stop()`, `newChat()` and `openSession(id)` and
68
+ reads `sessionId`, `request`, `chats`, `view`/`turns`/`pending`/`state`
69
+ (to follow the newest words), `sameConversation`, `sending`, `loading`,
70
+ `error`, `notice`, `unavailable`.
71
+ - `title` — the head's words, and the box's label. Default `"Ask the agent"`.
72
+ - `suggestions` — asks that fit the moment, as chips before the first ask.
73
+ - `empty` — one line before the first ask.
74
+ - `placeholder` — the box's words before the first ask. Once there is a
75
+ conversation it says "Ask a follow-up…" unless `chat.sameConversation` is
76
+ false.
77
+ - `closedWords` — the box's words while `blocked` ("Answer above first").
78
+ - `hint` — a quiet line under the box ("Enter sends · Shift+Enter is a new
79
+ line").
80
+ - `recent` — past chats listed before the first ask. Default `5`; `0` none.
81
+ - `bare` — no head, inside a `Sheet` or a `Card` that has its own.
82
+ - `fill` — default `true`: the pane takes its container's height and the
83
+ conversation scrolls inside it. `false`: compact, a capped height.
84
+ - `onClose` — a close in the head. Inside an `agent-dock` it is the dock's.
85
+ - `started` — there is a conversation to draw (else the empty state).
86
+ - `busy` — a turn runs: the arrow is a stop while the box is empty.
87
+ - `blocked` — something waits on the member: the whole box is closed.
88
+ - `bar` — a node between the conversation and the box.
89
+ - `children` — the conversation's lines.
90
+ - `className` — layout around it. Never colour.
91
+
92
+ `ChatComposer` is also exported, for a box of your own around the same
93
+ frame: `value`, `onChange`, `onSubmit`, `onStop`, `onAttach`, `files`,
94
+ `onRemoveFile`, `busy`, `canStop`, `stopping`, `blocked`, `sending`,
95
+ `encoding`, `dictation` (`useDictation()`), `placeholder`, `label`, `hint`,
96
+ `textareaRef`, `fileInputRef`. `ChatsList` draws the past chats.
97
+
98
+ ## Have the agent do it
99
+
100
+ A button that says the agent will do the work does not open a form. It calls
101
+ `openAgent("Draft a project plan for me")` (blocks/agent-dock). The dock
102
+ opens, tells this pane the line through `ChatDockContext`, and the pane:
103
+
104
+ 1. starts a new chat (if one is open; `fresh: false` carries on in it),
105
+ 2. sends the line as the member's first words, once,
106
+ 3. and tells the dock it took it.
107
+
108
+ With `send: false` it puts the line in the box instead, with the cursor at
109
+ its end (words the member already typed stay, and the line goes under them). A closed box (something waits on the member) always takes the line
110
+ as a prefill. The pure rule is `startStep(...)` in `chat-model.js`.
111
+
112
+ ## The model (plain functions)
113
+
114
+ `ago(iso)`, `startStep({ start, handled, sessionId, blocked, canNew, newed })`,
115
+ and the composer's parts: `addFiles`, `filesFromTransfer`, `readFile`,
116
+ `formatBytes`, `MAX_FILES`, `MAX_BYTES`, `useDictation`.
117
+
118
+ ## Example
119
+
120
+ ```jsx
121
+ "use client";
122
+ import { useAgentPane } from "../lib/hooks";
123
+ import { ChatPane } from "../components/blocks/chat-pane";
124
+
125
+ export default function Notes() {
126
+ const chat = useAgentPane({ key: "notes" });
127
+ const messages = chat.view?.messages ?? [];
128
+ return (
129
+ <ChatPane
130
+ chat={chat}
131
+ title="Ask about your notes"
132
+ suggestions={["Summarise this week"]}
133
+ hint="Enter sends · Shift+Enter is a new line"
134
+ started={messages.length > 0}
135
+ busy={chat.state === "working"}
136
+ >
137
+ {messages.map((m) => (
138
+ <p key={m.id}>{m.text}</p>
139
+ ))}
140
+ </ChatPane>
141
+ );
142
+ }
143
+ ```
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "chat-pane",
3
+ "title": "ChatPane",
4
+ "description": "The desk's chat pane as the app's own, in the app's theme: the chrome around a conversation. A head (title, New chat, Chats, close) with the past chats dropping over the chat; before the first ask one line, the recent chats and the suggestions; the conversation, kept at the newest words until the member scrolls up, with a jump to latest; a bar for what waits on the member; and the desk's composer: ONE rounded box with the words on top and under them a row, + (attach) at the left and the microphone and a round arrow to send at the right, the arrow a stop while a turn runs, a quiet hint under the box. Files by + or paste or drop, dictation, the box closed while something waits. A starting line handed down by the dock (openAgent) is sent as the member's first words in a fresh chat, or put in the box. It draws what useAgentPane() returns (lib/hooks.js) and decides nothing about the lines of the conversation: those are its children (agent-pane draws the agent's).",
5
+ "useWhen": "Any app chat with the agent: the pane inside an agent-dock, a compact card beside a record, a sheet. Use agent-pane when the conversation is the agent's (it puts the plan, the work, the questions and the yes inside this pane); use chat-pane itself to draw your own lines in the desk's frame, or just the composer (ChatComposer). Not for a chat between people (chat) or an agent run that is commissioned from a verb and watched (job-panel).",
6
+ "tags": [
7
+ "chat",
8
+ "composer",
9
+ "message box",
10
+ "ask",
11
+ "assistant",
12
+ "conversation",
13
+ "new chat",
14
+ "chats",
15
+ "send",
16
+ "stop",
17
+ "attach",
18
+ "dictate",
19
+ "copilot",
20
+ "sidebar"
21
+ ],
22
+ "exports": [
23
+ "ChatPane",
24
+ "ChatComposer",
25
+ "ChatsList",
26
+ "ChatDockContext",
27
+ "ago",
28
+ "startStep",
29
+ "MAX_BYTES",
30
+ "MAX_FILES",
31
+ "addFiles",
32
+ "filesFromTransfer",
33
+ "formatBytes",
34
+ "readFile",
35
+ "useDictation"
36
+ ],
37
+ "files": [
38
+ "index.js",
39
+ "chat-pane.jsx",
40
+ "chat-composer.jsx",
41
+ "chats-list.jsx",
42
+ "chat-context.js",
43
+ "chat-model.js",
44
+ "chat-attach.js"
45
+ ],
46
+ "requires": [],
47
+ "offer": { "since": "0.8.1", "why": "the desk's chat pane and message box as the app's own, for a chat of the app's own lines (agent-pane already lays it)" }
48
+ }
@@ -0,0 +1,166 @@
1
+ "use client";
2
+
3
+ import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
4
+
5
+ // The composer's parts (0.8.1, D27 phase 4): files to send with the words,
6
+ // and dictation. Both are the browser's own — nothing here reads a door. The
7
+ // platform checks the files again (agent-app app-attachments.ts) and the
8
+ // limits below are its. They lived in agent-pane/composer.jsx until the
9
+ // chat-pane block (X5); that file now re-exports them from here.
10
+
11
+ /** At most this many files, and this many bytes together, per message. */
12
+ export const MAX_FILES = 4;
13
+ export const MAX_BYTES = 3 * 1024 * 1024;
14
+
15
+ export function formatBytes(bytes) {
16
+ if (bytes < 1024) return `${bytes} B`;
17
+ if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
18
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
19
+ }
20
+
21
+ /**
22
+ * Add `incoming` files to `current`, within the limits.
23
+ * → { files, error } `error` is words for the member, or null
24
+ */
25
+ export function addFiles(current, incoming) {
26
+ const files = [...current];
27
+ let error = null;
28
+ let total = files.reduce((n, f) => n + f.size, 0);
29
+ for (const file of incoming) {
30
+ if (files.length >= MAX_FILES) {
31
+ error = `Send at most ${MAX_FILES} files at a time.`;
32
+ break;
33
+ }
34
+ if (file.size === 0) {
35
+ error = `${file.name} is empty.`;
36
+ continue;
37
+ }
38
+ if (total + file.size > MAX_BYTES) {
39
+ error = `Files can be up to ${formatBytes(MAX_BYTES)} together here. Attach a smaller one, or attach it in the Makersclaw window.`;
40
+ continue;
41
+ }
42
+ total += file.size;
43
+ files.push(file);
44
+ }
45
+ return { files, error };
46
+ }
47
+
48
+ /** A File as the ask takes it: { name, type, data } with a base64 data URL. */
49
+ export function readFile(file) {
50
+ return new Promise((resolve, reject) => {
51
+ const reader = new FileReader();
52
+ reader.onload = () => resolve({ name: file.name, type: file.type || "application/octet-stream", data: String(reader.result) });
53
+ reader.onerror = () => reject(reader.error ?? new Error("read failed"));
54
+ reader.readAsDataURL(file);
55
+ });
56
+ }
57
+
58
+ /** Files off a paste or a drop. A pasted image is named "image.png" by the
59
+ * browser; stamp it so several stay apart in the thread. */
60
+ export function filesFromTransfer(dt) {
61
+ if (!dt) return [];
62
+ const out = [];
63
+ for (const item of Array.from(dt.items ?? [])) {
64
+ if (item.kind !== "file") continue;
65
+ const file = item.getAsFile();
66
+ if (!file) continue;
67
+ out.push(
68
+ file.name === "image.png" && file.type.startsWith("image/")
69
+ ? new File([file], `pasted-${new Date().toISOString().replace(/[:.]/g, "-")}.png`, { type: file.type })
70
+ : file,
71
+ );
72
+ }
73
+ return out;
74
+ }
75
+
76
+ function recognitionCtor() {
77
+ if (typeof window === "undefined") return null;
78
+ return window.SpeechRecognition ?? window.webkitSpeechRecognition ?? null;
79
+ }
80
+
81
+ /**
82
+ * Dictation: the microphone to text through the browser's speech
83
+ * recognition (the desk's composer does the same). `onText(words)` hears
84
+ * each finished phrase. `supported` is false where the browser has none,
85
+ * and the pane draws no microphone. `error` says when the microphone is
86
+ * refused (a frame the desk has not allowed it in, or the member said no).
87
+ */
88
+ export function useDictation(onText) {
89
+ const [supported] = useState(() => recognitionCtor() !== null);
90
+ const [listening, setListening] = useState(false);
91
+ const [interim, setInterim] = useState("");
92
+ const [error, setError] = useState(null);
93
+ const recRef = useRef(null);
94
+ const wantRef = useRef(false);
95
+ const onTextRef = useRef(onText);
96
+ useLayoutEffect(() => {
97
+ onTextRef.current = onText;
98
+ }, [onText]);
99
+
100
+ const stop = useCallback(() => {
101
+ wantRef.current = false;
102
+ recRef.current?.stop();
103
+ recRef.current = null;
104
+ setListening(false);
105
+ setInterim("");
106
+ }, []);
107
+
108
+ const start = useCallback(() => {
109
+ const Ctor = recognitionCtor();
110
+ if (!Ctor || recRef.current) return;
111
+ setError(null);
112
+ const rec = new Ctor();
113
+ rec.continuous = true;
114
+ rec.interimResults = true;
115
+ rec.lang = (typeof navigator !== "undefined" && navigator.language) || "en-US";
116
+ rec.onresult = (event) => {
117
+ let interimText = "";
118
+ for (let i = event.resultIndex; i < event.results.length; i += 1) {
119
+ const result = event.results[i];
120
+ const transcript = result[0]?.transcript ?? "";
121
+ if (result.isFinal) {
122
+ if (transcript.trim()) onTextRef.current(transcript.trim());
123
+ } else {
124
+ interimText += transcript;
125
+ }
126
+ }
127
+ setInterim(interimText);
128
+ };
129
+ rec.onend = () => {
130
+ recRef.current = null;
131
+ setInterim("");
132
+ if (wantRef.current) {
133
+ // Silence ends a recognition; while the toggle is on, listen again.
134
+ try {
135
+ rec.start();
136
+ recRef.current = rec;
137
+ return;
138
+ } catch {
139
+ wantRef.current = false;
140
+ }
141
+ }
142
+ setListening(false);
143
+ };
144
+ rec.onerror = (event) => {
145
+ if (event.error === "not-allowed" || event.error === "service-not-allowed") {
146
+ wantRef.current = false;
147
+ setListening(false);
148
+ setError("The microphone is not allowed here. Allow it for this site, or type instead.");
149
+ }
150
+ };
151
+ wantRef.current = true;
152
+ try {
153
+ rec.start();
154
+ } catch {
155
+ wantRef.current = false;
156
+ setError("The microphone could not start.");
157
+ return;
158
+ }
159
+ recRef.current = rec;
160
+ setListening(true);
161
+ }, []);
162
+
163
+ const toggle = useCallback(() => (listening ? stop() : start()), [listening, start, stop]);
164
+ useEffect(() => stop, [stop]);
165
+ return { supported, listening, interim, error, toggle, stop };
166
+ }
@@ -0,0 +1,195 @@
1
+ "use client";
2
+
3
+ import { useEffect } from "react";
4
+ import { Icon, cx } from "../../ui";
5
+ import { filesFromTransfer, formatBytes } from "./chat-attach";
6
+
7
+ // ChatComposer — the desk's message box (claw's ChatComposer, as the app
8
+ // draws it): ONE rounded box. The words on top, full width, growing with
9
+ // what is typed; under them a row with + (attach) at the left, and at the
10
+ // right the microphone and a round arrow to send. While a turn runs, a round
11
+ // stop takes the arrow's place. A quiet hint can sit under the box.
12
+ //
13
+ // It draws the box and nothing else: the words, the files and the dictation
14
+ // are the pane's (so a drop anywhere on the pane, a prefilled line and a
15
+ // sent suggestion all reach the same box).
16
+ //
17
+ // value, onChange the words (controlled)
18
+ // onSubmit() Enter, or the arrow
19
+ // onStop() the stop (shown while `busy` and `canStop`)
20
+ // onAttach(File[]) the + and a paste
21
+ // files, onRemoveFile(i) what is attached, as chips inside the box
22
+ // busy a turn runs: the arrow is a stop while the box is empty
23
+ // canStop, stopping the stop can be pressed / has been
24
+ // blocked something waits on the member: the whole box is closed
25
+ // sending, encoding the arrow waits
26
+ // dictation useDictation()'s object (no microphone where the
27
+ // browser has none)
28
+ // placeholder, label the box's words, and its name for a screen reader
29
+ // hint a quiet line under the box
30
+ // textareaRef the pane's handle on the box (focus, caret)
31
+
32
+ const ROUND = "inline-flex size-8 shrink-0 items-center justify-center outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-card disabled:cursor-not-allowed disabled:opacity-40";
33
+
34
+ export function ChatComposer({
35
+ value,
36
+ onChange,
37
+ onSubmit,
38
+ onStop,
39
+ onAttach,
40
+ files = [],
41
+ onRemoveFile,
42
+ busy = false,
43
+ canStop = false,
44
+ stopping = false,
45
+ blocked = false,
46
+ sending = false,
47
+ encoding = false,
48
+ dictation,
49
+ placeholder,
50
+ label = "Message",
51
+ hint,
52
+ textareaRef,
53
+ fileInputRef,
54
+ className,
55
+ }) {
56
+ const empty = !value.trim() && files.length === 0;
57
+ const stopShown = busy && canStop && empty;
58
+
59
+ // The box grows with its words, up to its max-h; a hidden box measures 0
60
+ // and is left natural (pinning 0px would stick).
61
+ useEffect(() => {
62
+ const el = textareaRef?.current;
63
+ if (!el) return;
64
+ el.style.height = "auto";
65
+ if (el.scrollHeight > 0) el.style.height = `${el.scrollHeight}px`;
66
+ }, [value, textareaRef]);
67
+
68
+ return (
69
+ <div className={cx("grid min-w-0 gap-1.5", className)}>
70
+ <form
71
+ data-chat-composer=""
72
+ className="grid min-w-0 gap-2 rounded-xl border border-border bg-card px-3 pb-2 pt-2.5 text-card-foreground shadow-sm transition-colors focus-within:border-ring motion-reduce:transition-none"
73
+ onSubmit={(e) => {
74
+ e.preventDefault();
75
+ onSubmit?.();
76
+ }}
77
+ >
78
+ {files.length > 0 ? (
79
+ <ul aria-label="Files to send" className="flex min-w-0 flex-wrap gap-1.5">
80
+ {files.map((f, i) => (
81
+ <li key={`${f.name}-${i}`} className="inline-flex max-w-full min-w-0 items-center gap-1.5 rounded-md border border-border py-0.5 pl-2 pr-1 text-xs">
82
+ <Icon name="paperclip" size={12} className="shrink-0 text-muted-foreground" />
83
+ <span className="min-w-0 truncate">{f.name}</span>
84
+ <span className="shrink-0 text-muted-foreground">{formatBytes(f.size)}</span>
85
+ <button
86
+ type="button"
87
+ aria-label={`Remove ${f.name}`}
88
+ title={`Remove ${f.name}`}
89
+ onClick={() => onRemoveFile?.(i)}
90
+ className="inline-flex size-5 shrink-0 items-center justify-center rounded-sm text-muted-foreground outline-none hover:bg-accent hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring"
91
+ >
92
+ <Icon name="x" size={12} />
93
+ </button>
94
+ </li>
95
+ ))}
96
+ </ul>
97
+ ) : null}
98
+
99
+ <textarea
100
+ ref={textareaRef}
101
+ aria-label={label}
102
+ rows={1}
103
+ placeholder={placeholder}
104
+ value={value}
105
+ disabled={blocked}
106
+ onChange={(e) => onChange?.(e.target.value)}
107
+ onPaste={(e) => {
108
+ const pasted = filesFromTransfer(e.clipboardData);
109
+ if (pasted.length > 0) {
110
+ e.preventDefault();
111
+ onAttach?.(pasted);
112
+ }
113
+ }}
114
+ onKeyDown={(e) => {
115
+ if (e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
116
+ e.preventDefault();
117
+ onSubmit?.();
118
+ }
119
+ }}
120
+ className="block max-h-40 min-h-6 w-full min-w-0 resize-none overflow-y-auto bg-transparent text-sm leading-6 text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed"
121
+ />
122
+
123
+ {dictation?.listening ? (
124
+ <p role="status" className="flex min-w-0 items-center gap-1.5 text-xs text-muted-foreground">
125
+ <span aria-hidden="true" className="size-1.5 shrink-0 animate-pulse rounded-full bg-destructive motion-reduce:animate-none" />
126
+ Listening…
127
+ {dictation.interim ? <span className="min-w-0 truncate italic">{dictation.interim}</span> : null}
128
+ </p>
129
+ ) : null}
130
+
131
+ <div className="flex items-center gap-1.5">
132
+ <input
133
+ ref={fileInputRef}
134
+ type="file"
135
+ multiple
136
+ hidden
137
+ aria-hidden="true"
138
+ tabIndex={-1}
139
+ onChange={(e) => {
140
+ onAttach?.(Array.from(e.target.files ?? []));
141
+ e.target.value = "";
142
+ }}
143
+ />
144
+ <button
145
+ type="button"
146
+ aria-label="Attach a file"
147
+ title="Attach a file"
148
+ disabled={blocked || encoding}
149
+ onClick={() => fileInputRef?.current?.click()}
150
+ className={cx(ROUND, "rounded-lg border border-border text-muted-foreground hover:bg-accent hover:text-foreground")}
151
+ >
152
+ <Icon name="plus" size={16} />
153
+ </button>
154
+ <span className="flex-1" />
155
+ {dictation?.supported ? (
156
+ <button
157
+ type="button"
158
+ aria-label={dictation.listening ? "Stop dictating" : "Dictate"}
159
+ title={dictation.listening ? "Stop dictating" : "Dictate"}
160
+ aria-pressed={dictation.listening}
161
+ disabled={blocked}
162
+ onClick={dictation.toggle}
163
+ className={cx(ROUND, "rounded-lg hover:bg-accent", dictation.listening ? "text-destructive" : "text-muted-foreground hover:text-foreground")}
164
+ >
165
+ <Icon name="mic" size={16} />
166
+ </button>
167
+ ) : null}
168
+ {stopShown ? (
169
+ <button
170
+ type="button"
171
+ aria-label={stopping ? "Stopping…" : "Stop"}
172
+ title={stopping ? "Stopping…" : "Stop"}
173
+ disabled={stopping}
174
+ onClick={onStop}
175
+ className={cx(ROUND, "rounded-full bg-primary text-primary-foreground hover:opacity-90")}
176
+ >
177
+ <Icon name="stop" size={12} />
178
+ </button>
179
+ ) : (
180
+ <button
181
+ type="submit"
182
+ aria-label="Send"
183
+ title="Send"
184
+ disabled={blocked || encoding || sending || empty}
185
+ className={cx(ROUND, "rounded-full bg-primary text-primary-foreground hover:opacity-90")}
186
+ >
187
+ <Icon name="arrow-up" size={16} />
188
+ </button>
189
+ )}
190
+ </div>
191
+ </form>
192
+ {hint ? <p className="px-1 text-xs text-muted-foreground">{hint}</p> : null}
193
+ </div>
194
+ );
195
+ }
@@ -0,0 +1,17 @@
1
+ "use client";
2
+
3
+ import { createContext } from "react";
4
+
5
+ // What a ChatPane placed inside an AgentDock (blocks/agent-dock) is told:
6
+ //
7
+ // close folds the dock (the head's close, when the app gave no onClose)
8
+ // mode "column" or "sheet"
9
+ // start the starting line a "have the agent do it" button asked for
10
+ // (openAgent({ ask }), blocks/agent-dock), or null:
11
+ // { ask, send, fresh, nonce }
12
+ // taken (nonce) => void — the pane took it; the dock drops it
13
+ //
14
+ // Null outside a dock, where nothing changes. It lives here, beside the
15
+ // pane, so the pane never imports the dock; agent-pane re-exports it as
16
+ // AgentDockContext, which is the name the dock and apps have always used.
17
+ export const ChatDockContext = createContext(null);
@@ -0,0 +1,43 @@
1
+ // chat-pane: the rules that need no React, as plain functions (they work on
2
+ // the server too, and test/chat-pane.test.mjs holds them).
3
+
4
+ /** "now", "5m", "3h", "2d", else the date: a past chat's age. */
5
+ export function ago(iso, now = Date.now()) {
6
+ const t = iso ? Date.parse(iso) : Number.NaN;
7
+ if (!Number.isFinite(t)) return "";
8
+ const s = Math.max(0, Math.round((now - t) / 1000));
9
+ if (s < 60) return "now";
10
+ if (s < 3600) return `${Math.floor(s / 60)}m`;
11
+ if (s < 86400) return `${Math.floor(s / 3600)}h`;
12
+ if (s < 7 * 86400) return `${Math.floor(s / 86400)}d`;
13
+ return new Date(t).toLocaleDateString(undefined, { month: "short", day: "numeric" });
14
+ }
15
+
16
+ /**
17
+ * What the pane does next with a starting line the dock holds (openAgent in
18
+ * blocks/agent-dock). A "have the agent do it" button does not open a form:
19
+ * it hands the agent its first line, and the agent asks only for what it is
20
+ * missing, in the chat.
21
+ *
22
+ * start { ask, send, fresh, nonce } or null
23
+ * handled the nonce this pane already took, or null
24
+ * sessionId the conversation open now (null: a fresh one)
25
+ * blocked the box is closed (something waits on the member)
26
+ * canNew the chat can start a new conversation (chat.newChat)
27
+ * newed newChat was already called for this nonce
28
+ *
29
+ * → "none" nothing to do
30
+ * "new-chat" start a fresh conversation first (fresh, and one is open)
31
+ * "wait" the fresh conversation has not replaced the old one yet
32
+ * "send" send the line as the member's first words
33
+ * "prefill" put the line in the box for the member to finish (send is
34
+ * false, or the box is closed and cannot send)
35
+ */
36
+ export function startStep({ start, handled = null, sessionId = null, blocked = false, canNew = true, newed = false } = {}) {
37
+ if (!start || !String(start.ask ?? "").trim()) return "none";
38
+ if (handled !== null && handled === start.nonce) return "none";
39
+ if (start.send === false || blocked) return "prefill";
40
+ const fresh = start.fresh !== false && canNew;
41
+ if (fresh && sessionId) return newed ? "wait" : "new-chat";
42
+ return "send";
43
+ }