aeon-ui-engine 1.0.3 → 1.1.0

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 (349) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/CONSUMER.md +39 -42
  3. package/README.md +47 -16
  4. package/package.json +9 -2
  5. package/packages/cli/README.md +17 -0
  6. package/packages/cli/dist/bin.d.ts +1 -0
  7. package/packages/cli/dist/bin.js +35 -0
  8. package/packages/cli/dist/chunk-IW5NT2Z2.js +103 -0
  9. package/packages/cli/dist/index.d.ts +10 -0
  10. package/packages/cli/dist/index.js +6 -0
  11. package/packages/cli/node_modules/.bin/esbuild +21 -0
  12. package/packages/cli/node_modules/.bin/jiti +21 -0
  13. package/packages/cli/node_modules/.bin/tsc +21 -0
  14. package/packages/cli/node_modules/.bin/tsserver +21 -0
  15. package/packages/cli/node_modules/.bin/tsup +21 -0
  16. package/packages/cli/node_modules/.bin/tsup-node +21 -0
  17. package/packages/cli/node_modules/.bin/tsx +21 -0
  18. package/packages/cli/node_modules/.bin/vite +21 -0
  19. package/packages/cli/node_modules/.bin/vitest +21 -0
  20. package/packages/cli/package.json +50 -0
  21. package/packages/cli/src/bin.ts +34 -0
  22. package/packages/cli/src/index.ts +1 -0
  23. package/packages/cli/src/init.ts +107 -0
  24. package/packages/cli/tsconfig.json +10 -0
  25. package/packages/core/README.md +7 -1
  26. package/packages/core/dist/index.d.ts +174 -6
  27. package/packages/core/dist/index.js +259 -2
  28. package/packages/core/node_modules/.bin/esbuild +4 -4
  29. package/packages/core/node_modules/.bin/vite +4 -4
  30. package/packages/core/node_modules/.bin/vitest +2 -2
  31. package/packages/core/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  32. package/packages/core/package.json +17 -5
  33. package/packages/core/src/anatomy.ts +196 -5
  34. package/packages/core/src/machine.test.ts +62 -1
  35. package/packages/core/src/machine.ts +93 -0
  36. package/packages/core/src/theme.ts +105 -0
  37. package/packages/panda/aeon.css +7 -0
  38. package/packages/panda/package.json +1 -1
  39. package/packages/panda/panda.config.ts +58 -1
  40. package/packages/panda/src/recipes/app-shell.ts +137 -0
  41. package/packages/panda/src/recipes/avatar.ts +131 -0
  42. package/packages/panda/src/recipes/bar.ts +206 -0
  43. package/packages/panda/src/recipes/button-group.ts +12 -4
  44. package/packages/panda/src/recipes/button.ts +1 -0
  45. package/packages/panda/src/recipes/combobox.ts +2 -1
  46. package/packages/panda/src/recipes/composer.ts +81 -0
  47. package/packages/panda/src/recipes/content.ts +104 -0
  48. package/packages/panda/src/recipes/conversation.ts +106 -0
  49. package/packages/panda/src/recipes/entry.ts +217 -0
  50. package/packages/panda/src/recipes/field.ts +12 -2
  51. package/packages/panda/src/recipes/floating.ts +26 -13
  52. package/packages/panda/src/recipes/identity.ts +73 -0
  53. package/packages/panda/src/recipes/index.ts +15 -0
  54. package/packages/panda/src/recipes/list-row.ts +109 -0
  55. package/packages/panda/src/recipes/metric-strip.ts +80 -0
  56. package/packages/panda/src/recipes/nav.ts +155 -0
  57. package/packages/panda/src/recipes/panel.ts +156 -0
  58. package/packages/panda/src/recipes/pin-input.ts +3 -2
  59. package/packages/panda/src/recipes/profile-header.ts +120 -0
  60. package/packages/panda/src/recipes/select.ts +2 -1
  61. package/packages/panda/src/recipes/slider.ts +6 -4
  62. package/packages/panda/src/recipes/theme-switcher.ts +110 -0
  63. package/packages/panda/src/recipes/thread.ts +88 -0
  64. package/packages/panda/src/theme/catalog-types.ts +2 -0
  65. package/packages/panda/src/theme/catalog.ts +23 -0
  66. package/packages/panda/src/theme/chrome.css +2 -1
  67. package/packages/panda/src/theme/global-theme-css.ts +9 -0
  68. package/packages/panda/src/theme/omarchy.themes.ts +607 -0
  69. package/packages/panda/src/theme/palette.ts +3 -0
  70. package/packages/panda/src/theme/scrollbars.css +58 -21
  71. package/packages/panda/src/theme/themes.config.ts +39 -1
  72. package/packages/panda/styled-system/css/conditions.mjs +1 -1
  73. package/packages/panda/styled-system/css/css.mjs +1 -1
  74. package/packages/panda/styled-system/css/sva.mjs +9 -4
  75. package/packages/panda/styled-system/helpers.mjs +11 -22
  76. package/packages/panda/styled-system/jsx/create-style-context.d.ts +54 -0
  77. package/packages/panda/styled-system/jsx/create-style-context.mjs +121 -0
  78. package/packages/panda/styled-system/jsx/factory.mjs +14 -5
  79. package/packages/panda/styled-system/jsx/index.d.ts +1 -0
  80. package/packages/panda/styled-system/jsx/index.mjs +1 -0
  81. package/packages/panda/styled-system/jsx/is-valid-prop.mjs +2 -2
  82. package/packages/panda/styled-system/patterns/aspect-ratio.d.ts +0 -1
  83. package/packages/panda/styled-system/patterns/bleed.d.ts +0 -1
  84. package/packages/panda/styled-system/patterns/box.d.ts +0 -1
  85. package/packages/panda/styled-system/patterns/center.d.ts +0 -1
  86. package/packages/panda/styled-system/patterns/circle.d.ts +0 -1
  87. package/packages/panda/styled-system/patterns/container.d.ts +0 -1
  88. package/packages/panda/styled-system/patterns/cq.d.ts +0 -1
  89. package/packages/panda/styled-system/patterns/divider.d.ts +0 -1
  90. package/packages/panda/styled-system/patterns/flex.d.ts +0 -1
  91. package/packages/panda/styled-system/patterns/float.d.ts +0 -1
  92. package/packages/panda/styled-system/patterns/grid-item.d.ts +0 -1
  93. package/packages/panda/styled-system/patterns/grid.d.ts +0 -1
  94. package/packages/panda/styled-system/patterns/grid.mjs +1 -1
  95. package/packages/panda/styled-system/patterns/hstack.d.ts +0 -1
  96. package/packages/panda/styled-system/patterns/hstack.mjs +1 -1
  97. package/packages/panda/styled-system/patterns/link-overlay.d.ts +0 -1
  98. package/packages/panda/styled-system/patterns/spacer.d.ts +0 -1
  99. package/packages/panda/styled-system/patterns/spacer.mjs +6 -2
  100. package/packages/panda/styled-system/patterns/square.d.ts +0 -1
  101. package/packages/panda/styled-system/patterns/stack.d.ts +0 -1
  102. package/packages/panda/styled-system/patterns/stack.mjs +1 -1
  103. package/packages/panda/styled-system/patterns/visually-hidden.d.ts +0 -1
  104. package/packages/panda/styled-system/patterns/vstack.d.ts +0 -1
  105. package/packages/panda/styled-system/patterns/vstack.mjs +1 -1
  106. package/packages/panda/styled-system/patterns/wrap.d.ts +0 -1
  107. package/packages/panda/styled-system/patterns/wrap.mjs +1 -1
  108. package/packages/panda/styled-system/recipes/aeon-accordion.d.ts +4 -3
  109. package/packages/panda/styled-system/recipes/aeon-accordion.mjs +1 -0
  110. package/packages/panda/styled-system/recipes/aeon-app-shell.d.ts +34 -0
  111. package/packages/panda/styled-system/recipes/aeon-app-shell.mjs +70 -0
  112. package/packages/panda/styled-system/recipes/aeon-async.d.ts +4 -3
  113. package/packages/panda/styled-system/recipes/aeon-async.mjs +1 -0
  114. package/packages/panda/styled-system/recipes/aeon-avatar.d.ts +36 -0
  115. package/packages/panda/styled-system/recipes/aeon-avatar.mjs +57 -0
  116. package/packages/panda/styled-system/recipes/aeon-badge.d.ts +3 -0
  117. package/packages/panda/styled-system/recipes/aeon-bar.d.ts +40 -0
  118. package/packages/panda/styled-system/recipes/aeon-bar.mjs +77 -0
  119. package/packages/panda/styled-system/recipes/aeon-button-group.d.ts +3 -2
  120. package/packages/panda/styled-system/recipes/aeon-button.d.ts +3 -2
  121. package/packages/panda/styled-system/recipes/aeon-checkbox.d.ts +4 -1
  122. package/packages/panda/styled-system/recipes/aeon-checkbox.mjs +1 -0
  123. package/packages/panda/styled-system/recipes/aeon-combobox.d.ts +4 -3
  124. package/packages/panda/styled-system/recipes/aeon-combobox.mjs +1 -0
  125. package/packages/panda/styled-system/recipes/aeon-composer.d.ts +31 -0
  126. package/packages/panda/styled-system/recipes/aeon-composer.mjs +45 -0
  127. package/packages/panda/styled-system/recipes/aeon-content.d.ts +34 -0
  128. package/packages/panda/styled-system/recipes/aeon-content.mjs +70 -0
  129. package/packages/panda/styled-system/recipes/aeon-conversation.d.ts +31 -0
  130. package/packages/panda/styled-system/recipes/aeon-conversation.mjs +61 -0
  131. package/packages/panda/styled-system/recipes/aeon-dialog.d.ts +4 -1
  132. package/packages/panda/styled-system/recipes/aeon-dialog.mjs +1 -0
  133. package/packages/panda/styled-system/recipes/aeon-entry.d.ts +38 -0
  134. package/packages/panda/styled-system/recipes/aeon-entry.mjs +100 -0
  135. package/packages/panda/styled-system/recipes/aeon-field.d.ts +4 -3
  136. package/packages/panda/styled-system/recipes/aeon-field.mjs +1 -0
  137. package/packages/panda/styled-system/recipes/aeon-identity.d.ts +36 -0
  138. package/packages/panda/styled-system/recipes/aeon-identity.mjs +63 -0
  139. package/packages/panda/styled-system/recipes/aeon-list-row.d.ts +33 -0
  140. package/packages/panda/styled-system/recipes/aeon-list-row.mjs +49 -0
  141. package/packages/panda/styled-system/recipes/aeon-menu.d.ts +4 -1
  142. package/packages/panda/styled-system/recipes/aeon-menu.mjs +1 -0
  143. package/packages/panda/styled-system/recipes/aeon-metric-strip.d.ts +36 -0
  144. package/packages/panda/styled-system/recipes/aeon-metric-strip.mjs +54 -0
  145. package/packages/panda/styled-system/recipes/aeon-nav.d.ts +38 -0
  146. package/packages/panda/styled-system/recipes/aeon-nav.mjs +69 -0
  147. package/packages/panda/styled-system/recipes/aeon-panel.d.ts +34 -0
  148. package/packages/panda/styled-system/recipes/aeon-panel.mjs +58 -0
  149. package/packages/panda/styled-system/recipes/aeon-pin-input.d.ts +4 -1
  150. package/packages/panda/styled-system/recipes/aeon-pin-input.mjs +1 -0
  151. package/packages/panda/styled-system/recipes/aeon-popover.d.ts +4 -1
  152. package/packages/panda/styled-system/recipes/aeon-popover.mjs +1 -0
  153. package/packages/panda/styled-system/recipes/aeon-profile-header.d.ts +36 -0
  154. package/packages/panda/styled-system/recipes/aeon-profile-header.mjs +62 -0
  155. package/packages/panda/styled-system/recipes/aeon-progress.d.ts +4 -1
  156. package/packages/panda/styled-system/recipes/aeon-progress.mjs +1 -0
  157. package/packages/panda/styled-system/recipes/aeon-radio-group.d.ts +4 -1
  158. package/packages/panda/styled-system/recipes/aeon-radio-group.mjs +1 -0
  159. package/packages/panda/styled-system/recipes/aeon-scroll.d.ts +4 -3
  160. package/packages/panda/styled-system/recipes/aeon-scroll.mjs +1 -0
  161. package/packages/panda/styled-system/recipes/aeon-select.d.ts +4 -3
  162. package/packages/panda/styled-system/recipes/aeon-select.mjs +1 -0
  163. package/packages/panda/styled-system/recipes/aeon-separator.d.ts +4 -1
  164. package/packages/panda/styled-system/recipes/aeon-separator.mjs +1 -0
  165. package/packages/panda/styled-system/recipes/aeon-slider.d.ts +4 -1
  166. package/packages/panda/styled-system/recipes/aeon-slider.mjs +1 -0
  167. package/packages/panda/styled-system/recipes/aeon-switch.d.ts +4 -1
  168. package/packages/panda/styled-system/recipes/aeon-switch.mjs +1 -0
  169. package/packages/panda/styled-system/recipes/aeon-tabs.d.ts +4 -1
  170. package/packages/panda/styled-system/recipes/aeon-tabs.mjs +1 -0
  171. package/packages/panda/styled-system/recipes/aeon-theme-switcher.d.ts +34 -0
  172. package/packages/panda/styled-system/recipes/aeon-theme-switcher.mjs +59 -0
  173. package/packages/panda/styled-system/recipes/aeon-thread.d.ts +31 -0
  174. package/packages/panda/styled-system/recipes/aeon-thread.mjs +53 -0
  175. package/packages/panda/styled-system/recipes/aeon-toast.d.ts +4 -1
  176. package/packages/panda/styled-system/recipes/aeon-toast.mjs +1 -0
  177. package/packages/panda/styled-system/recipes/aeon-tooltip.d.ts +4 -1
  178. package/packages/panda/styled-system/recipes/aeon-tooltip.mjs +1 -0
  179. package/packages/panda/styled-system/recipes/index.d.ts +16 -1
  180. package/packages/panda/styled-system/recipes/index.mjs +16 -1
  181. package/packages/panda/styled-system/styles.css +2317 -450
  182. package/packages/panda/styled-system/tokens/index.mjs +43 -7
  183. package/packages/panda/styled-system/tokens/tokens.d.ts +5 -5
  184. package/packages/panda/styled-system/types/composition.d.ts +86 -23
  185. package/packages/panda/styled-system/types/conditions.d.ts +34 -10
  186. package/packages/panda/styled-system/types/csstype.d.ts +6405 -5133
  187. package/packages/panda/styled-system/types/jsx.d.ts +27 -10
  188. package/packages/panda/styled-system/types/pattern.d.ts +4 -4
  189. package/packages/panda/styled-system/types/prop-type.d.ts +11 -1
  190. package/packages/panda/styled-system/types/style-props.d.ts +2763 -2165
  191. package/packages/panda/styled-system/types/system-types.d.ts +38 -80
  192. package/packages/panda/theme-runtime.css +945 -0
  193. package/packages/primitives/dist/chunk-R25CUHNF.js +46 -0
  194. package/packages/primitives/dist/chunk-RO2DMFN5.js +89 -0
  195. package/packages/primitives/dist/chunk-V5D7LS4J.js +61 -0
  196. package/packages/primitives/dist/chunk-YBPNI2LI.js +70 -0
  197. package/packages/primitives/dist/index.d.ts +4 -0
  198. package/packages/primitives/dist/index.js +30 -8
  199. package/packages/primitives/dist/machines/app-shell.d.ts +57 -0
  200. package/packages/primitives/dist/machines/app-shell.js +8 -0
  201. package/packages/primitives/dist/machines/async.d.ts +4 -4
  202. package/packages/primitives/dist/machines/content-region.d.ts +72 -0
  203. package/packages/primitives/dist/machines/content-region.js +8 -0
  204. package/packages/primitives/dist/machines/panel.d.ts +50 -0
  205. package/packages/primitives/dist/machines/panel.js +6 -0
  206. package/packages/primitives/dist/machines/sticky-bar.d.ts +62 -0
  207. package/packages/primitives/dist/machines/sticky-bar.js +8 -0
  208. package/packages/primitives/node_modules/.bin/esbuild +21 -0
  209. package/packages/primitives/node_modules/.bin/vite +21 -0
  210. package/packages/primitives/node_modules/.bin/vitest +2 -2
  211. package/packages/primitives/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  212. package/packages/primitives/package.json +15 -5
  213. package/packages/primitives/scripts/xstate-introspect.mjs +35 -0
  214. package/packages/primitives/src/index.ts +4 -0
  215. package/packages/primitives/src/machines/app-shell.ts +63 -0
  216. package/packages/primitives/src/machines/content-region.ts +107 -0
  217. package/packages/primitives/src/machines/panel.ts +71 -0
  218. package/packages/primitives/src/machines/sticky-bar.ts +89 -0
  219. package/packages/react/dist/index.d.ts +403 -16
  220. package/packages/react/dist/index.js +1505 -227
  221. package/packages/react/node_modules/.bin/esbuild +21 -0
  222. package/packages/react/node_modules/.bin/vite +21 -0
  223. package/packages/react/node_modules/.bin/vitest +2 -2
  224. package/packages/react/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  225. package/packages/react/package.json +18 -7
  226. package/packages/react/src/app-shell/index.tsx +154 -0
  227. package/packages/react/src/async/index.tsx +6 -1
  228. package/packages/react/src/async/map-content-state.ts +18 -0
  229. package/packages/react/src/avatar/index.tsx +19 -0
  230. package/packages/react/src/bar/index.tsx +101 -0
  231. package/packages/react/src/button/index.tsx +4 -2
  232. package/packages/react/src/composer/index.tsx +75 -0
  233. package/packages/react/src/content/index.tsx +149 -0
  234. package/packages/react/src/conversation/index.tsx +78 -0
  235. package/packages/react/src/entry/index.tsx +85 -0
  236. package/packages/react/src/field/index.tsx +31 -18
  237. package/packages/react/src/identity/index.tsx +110 -0
  238. package/packages/react/src/index.ts +15 -0
  239. package/packages/react/src/list-row/index.tsx +80 -0
  240. package/packages/react/src/metric-strip/index.tsx +88 -0
  241. package/packages/react/src/nav/index.tsx +155 -0
  242. package/packages/react/src/panel/index.tsx +267 -0
  243. package/packages/react/src/profile-header/index.tsx +91 -0
  244. package/packages/react/src/radio-group/index.tsx +19 -7
  245. package/packages/react/src/slider/index.tsx +3 -1
  246. package/packages/react/src/sticky-bar/index.tsx +135 -0
  247. package/packages/react/src/switch/index.tsx +7 -1
  248. package/packages/react/src/theme-switcher/index.tsx +227 -0
  249. package/packages/react/src/thread/index.tsx +95 -0
  250. package/packages/react/src/toast/primitives.tsx +2 -2
  251. package/packages/react/src/tooltip/tooltip.test.tsx +9 -1
  252. package/packages/react/tsconfig.json +2 -1
  253. package/packages/schemas/README.md +52 -0
  254. package/packages/schemas/dist/index.d.ts +287 -0
  255. package/packages/schemas/dist/index.js +701 -0
  256. package/packages/schemas/json/accordion.json +132 -0
  257. package/packages/schemas/json/async.json +161 -0
  258. package/packages/schemas/json/button.json +170 -0
  259. package/packages/schemas/json/catalog.json +2299 -0
  260. package/packages/schemas/json/checkbox.json +136 -0
  261. package/packages/schemas/json/combobox.json +130 -0
  262. package/packages/schemas/json/dialog.json +154 -0
  263. package/packages/schemas/json/field.json +171 -0
  264. package/packages/schemas/json/menu.json +138 -0
  265. package/packages/schemas/json/popover.json +133 -0
  266. package/packages/schemas/json/progress.json +137 -0
  267. package/packages/schemas/json/scroll.json +129 -0
  268. package/packages/schemas/json/select.json +140 -0
  269. package/packages/schemas/json/switch.json +136 -0
  270. package/packages/schemas/json/tabs.json +135 -0
  271. package/packages/schemas/json/toast.json +141 -0
  272. package/packages/schemas/json/tooltip.json +123 -0
  273. package/packages/schemas/node_modules/.bin/esbuild +21 -0
  274. package/packages/schemas/node_modules/.bin/jiti +21 -0
  275. package/packages/schemas/node_modules/.bin/tsc +21 -0
  276. package/packages/schemas/node_modules/.bin/tsserver +21 -0
  277. package/packages/schemas/node_modules/.bin/tsup +21 -0
  278. package/packages/schemas/node_modules/.bin/tsup-node +21 -0
  279. package/packages/schemas/node_modules/.bin/tsx +21 -0
  280. package/packages/schemas/node_modules/.bin/vite +21 -0
  281. package/packages/schemas/node_modules/.bin/vitest +21 -0
  282. package/packages/schemas/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  283. package/packages/schemas/package.json +56 -0
  284. package/packages/schemas/prompts/cursorrules.md +64 -0
  285. package/packages/schemas/prompts/statecharts.md +31 -0
  286. package/packages/schemas/prompts/system.md +30 -0
  287. package/packages/schemas/registry/catalog.json +54 -0
  288. package/packages/schemas/registry/components/accordion.json +132 -0
  289. package/packages/schemas/registry/components/async.json +161 -0
  290. package/packages/schemas/registry/components/button.json +170 -0
  291. package/packages/schemas/registry/components/checkbox.json +136 -0
  292. package/packages/schemas/registry/components/combobox.json +130 -0
  293. package/packages/schemas/registry/components/dialog.json +154 -0
  294. package/packages/schemas/registry/components/field.json +171 -0
  295. package/packages/schemas/registry/components/menu.json +138 -0
  296. package/packages/schemas/registry/components/popover.json +133 -0
  297. package/packages/schemas/registry/components/progress.json +137 -0
  298. package/packages/schemas/registry/components/scroll.json +129 -0
  299. package/packages/schemas/registry/components/select.json +140 -0
  300. package/packages/schemas/registry/components/switch.json +136 -0
  301. package/packages/schemas/registry/components/tabs.json +135 -0
  302. package/packages/schemas/registry/components/toast.json +141 -0
  303. package/packages/schemas/registry/components/tooltip.json +123 -0
  304. package/packages/schemas/registry/machines/async.json +219 -0
  305. package/packages/schemas/registry/machines/buttonLifecycle.json +224 -0
  306. package/packages/schemas/registry/machines/dialog.json +143 -0
  307. package/packages/schemas/registry/machines/field.json +275 -0
  308. package/packages/schemas/scripts/emit.ts +61 -0
  309. package/packages/schemas/src/aeon-to-schema.test.ts +70 -0
  310. package/packages/schemas/src/aeon-to-schema.ts +206 -0
  311. package/packages/schemas/src/agent-bridge.ts +82 -0
  312. package/packages/schemas/src/components.ts +307 -0
  313. package/packages/schemas/src/index.test.ts +25 -0
  314. package/packages/schemas/src/index.ts +25 -0
  315. package/packages/schemas/src/prompts.ts +121 -0
  316. package/packages/schemas/src/registry.ts +73 -0
  317. package/packages/schemas/src/schema-builder.ts +87 -0
  318. package/packages/schemas/tsconfig.json +9 -0
  319. package/packages/solid/package.json +2 -2
  320. package/packages/svelte/node_modules/.bin/esbuild +21 -0
  321. package/packages/svelte/node_modules/.bin/vite +4 -4
  322. package/packages/svelte/package.json +15 -5
  323. package/packages/ui/README.md +19 -6
  324. package/packages/ui/dist/index.d.ts +254 -9
  325. package/packages/ui/dist/index.js +690 -139
  326. package/packages/ui/src/app-shell.tsx +44 -0
  327. package/packages/ui/src/async.tsx +2 -1
  328. package/packages/ui/src/avatar.tsx +35 -0
  329. package/packages/ui/src/bar.tsx +34 -0
  330. package/packages/ui/src/composer.tsx +27 -0
  331. package/packages/ui/src/content.tsx +43 -0
  332. package/packages/ui/src/conversation.tsx +43 -0
  333. package/packages/ui/src/entry.tsx +76 -0
  334. package/packages/ui/src/field.tsx +5 -0
  335. package/packages/ui/src/identity.tsx +35 -0
  336. package/packages/ui/src/index.ts +16 -0
  337. package/packages/ui/src/list-row.tsx +30 -0
  338. package/packages/ui/src/metric-strip.tsx +29 -0
  339. package/packages/ui/src/nav.tsx +46 -0
  340. package/packages/ui/src/panel.tsx +39 -0
  341. package/packages/ui/src/profile-header.tsx +35 -0
  342. package/packages/ui/src/sticky-bar.tsx +42 -0
  343. package/packages/ui/src/switch.tsx +17 -4
  344. package/packages/ui/src/theme-switcher.tsx +41 -0
  345. package/packages/ui/src/thread.tsx +35 -0
  346. package/packages/vue/package.json +3 -3
  347. package/scripts/vite-aliases.mjs +57 -3
  348. package/scripts/xstate-introspect.mjs +68 -0
  349. package/packages/react/src/async/legacy-region.tsx +0 -38
@@ -0,0 +1,275 @@
1
+ {
2
+ "id": "field",
3
+ "events": [
4
+ "INPUT",
5
+ "BLUR",
6
+ "RESET",
7
+ "VALIDATE",
8
+ "SUBMIT",
9
+ "SUBMIT_DONE",
10
+ "SUBMIT_FAIL"
11
+ ],
12
+ "tree": {
13
+ "key": "field",
14
+ "id": "field",
15
+ "type": "parallel",
16
+ "events": [
17
+ "INPUT",
18
+ "BLUR",
19
+ "RESET",
20
+ "VALIDATE",
21
+ "SUBMIT",
22
+ "SUBMIT_DONE",
23
+ "SUBMIT_FAIL"
24
+ ],
25
+ "transitions": [],
26
+ "children": [
27
+ {
28
+ "key": "interaction",
29
+ "id": "field.interaction",
30
+ "type": "compound",
31
+ "events": [
32
+ "INPUT",
33
+ "BLUR",
34
+ "RESET"
35
+ ],
36
+ "transitions": [],
37
+ "children": [
38
+ {
39
+ "key": "pristine",
40
+ "id": "field.interaction.pristine",
41
+ "type": "atomic",
42
+ "events": [
43
+ "INPUT",
44
+ "BLUR"
45
+ ],
46
+ "transitions": [
47
+ {
48
+ "event": "INPUT",
49
+ "target": [
50
+ "dirty"
51
+ ],
52
+ "guarded": false
53
+ },
54
+ {
55
+ "event": "BLUR",
56
+ "target": [
57
+ "dirty"
58
+ ],
59
+ "guarded": false
60
+ }
61
+ ],
62
+ "children": []
63
+ },
64
+ {
65
+ "key": "dirty",
66
+ "id": "field.interaction.dirty",
67
+ "type": "atomic",
68
+ "events": [
69
+ "RESET"
70
+ ],
71
+ "transitions": [
72
+ {
73
+ "event": "RESET",
74
+ "target": [
75
+ "pristine"
76
+ ],
77
+ "guarded": false
78
+ }
79
+ ],
80
+ "children": []
81
+ }
82
+ ]
83
+ },
84
+ {
85
+ "key": "validation",
86
+ "id": "field.validation",
87
+ "type": "compound",
88
+ "events": [
89
+ "VALIDATE",
90
+ "RESET"
91
+ ],
92
+ "transitions": [],
93
+ "children": [
94
+ {
95
+ "key": "valid",
96
+ "id": "field.validation.valid",
97
+ "type": "atomic",
98
+ "events": [
99
+ "VALIDATE"
100
+ ],
101
+ "transitions": [
102
+ {
103
+ "event": "VALIDATE",
104
+ "target": [
105
+ "invalid"
106
+ ],
107
+ "guarded": true
108
+ }
109
+ ],
110
+ "children": []
111
+ },
112
+ {
113
+ "key": "invalid",
114
+ "id": "field.validation.invalid",
115
+ "type": "atomic",
116
+ "events": [
117
+ "VALIDATE",
118
+ "RESET"
119
+ ],
120
+ "transitions": [
121
+ {
122
+ "event": "VALIDATE",
123
+ "target": [
124
+ "valid"
125
+ ],
126
+ "guarded": true
127
+ },
128
+ {
129
+ "event": "RESET",
130
+ "target": [
131
+ "valid"
132
+ ],
133
+ "guarded": false
134
+ }
135
+ ],
136
+ "children": []
137
+ }
138
+ ]
139
+ },
140
+ {
141
+ "key": "submission",
142
+ "id": "field.submission",
143
+ "type": "compound",
144
+ "events": [
145
+ "SUBMIT",
146
+ "SUBMIT_DONE",
147
+ "SUBMIT_FAIL"
148
+ ],
149
+ "transitions": [],
150
+ "children": [
151
+ {
152
+ "key": "idle",
153
+ "id": "field.submission.idle",
154
+ "type": "atomic",
155
+ "events": [
156
+ "SUBMIT"
157
+ ],
158
+ "transitions": [
159
+ {
160
+ "event": "SUBMIT",
161
+ "target": [
162
+ "pending"
163
+ ],
164
+ "guarded": false
165
+ }
166
+ ],
167
+ "children": []
168
+ },
169
+ {
170
+ "key": "pending",
171
+ "id": "field.submission.pending",
172
+ "type": "atomic",
173
+ "events": [
174
+ "SUBMIT_DONE",
175
+ "SUBMIT_FAIL"
176
+ ],
177
+ "transitions": [
178
+ {
179
+ "event": "SUBMIT_DONE",
180
+ "target": [
181
+ "idle"
182
+ ],
183
+ "guarded": false
184
+ },
185
+ {
186
+ "event": "SUBMIT_FAIL",
187
+ "target": [
188
+ "idle"
189
+ ],
190
+ "guarded": false
191
+ }
192
+ ],
193
+ "children": []
194
+ }
195
+ ]
196
+ }
197
+ ]
198
+ },
199
+ "states": {
200
+ "field": {
201
+ "events": [
202
+ "INPUT",
203
+ "BLUR",
204
+ "RESET",
205
+ "VALIDATE",
206
+ "SUBMIT",
207
+ "SUBMIT_DONE",
208
+ "SUBMIT_FAIL"
209
+ ],
210
+ "type": "parallel"
211
+ },
212
+ "field.interaction": {
213
+ "events": [
214
+ "INPUT",
215
+ "BLUR",
216
+ "RESET"
217
+ ],
218
+ "type": "compound"
219
+ },
220
+ "field.interaction.pristine": {
221
+ "events": [
222
+ "INPUT",
223
+ "BLUR"
224
+ ],
225
+ "type": "atomic"
226
+ },
227
+ "field.interaction.dirty": {
228
+ "events": [
229
+ "RESET"
230
+ ],
231
+ "type": "atomic"
232
+ },
233
+ "field.validation": {
234
+ "events": [
235
+ "VALIDATE",
236
+ "RESET"
237
+ ],
238
+ "type": "compound"
239
+ },
240
+ "field.validation.valid": {
241
+ "events": [
242
+ "VALIDATE"
243
+ ],
244
+ "type": "atomic"
245
+ },
246
+ "field.validation.invalid": {
247
+ "events": [
248
+ "VALIDATE",
249
+ "RESET"
250
+ ],
251
+ "type": "atomic"
252
+ },
253
+ "field.submission": {
254
+ "events": [
255
+ "SUBMIT",
256
+ "SUBMIT_DONE",
257
+ "SUBMIT_FAIL"
258
+ ],
259
+ "type": "compound"
260
+ },
261
+ "field.submission.idle": {
262
+ "events": [
263
+ "SUBMIT"
264
+ ],
265
+ "type": "atomic"
266
+ },
267
+ "field.submission.pending": {
268
+ "events": [
269
+ "SUBMIT_DONE",
270
+ "SUBMIT_FAIL"
271
+ ],
272
+ "type": "atomic"
273
+ }
274
+ }
275
+ }
@@ -0,0 +1,61 @@
1
+ import { mkdirSync, writeFileSync, cpSync, existsSync } from 'node:fs'
2
+ import { dirname, join } from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+ import {
5
+ asyncMachine,
6
+ buttonLifecycleMachine,
7
+ dialogMachine,
8
+ fieldMachine,
9
+ } from '@aeon-ui/primitives'
10
+ import { catalog, componentSchemas } from '../src/components.js'
11
+ import { AEON_SYSTEM_PROMPT, CURSOR_RULES_SNIPPET, STATECHART_PROMPTS } from '../src/prompts.js'
12
+ import { aeonToSchema } from '../src/aeon-to-schema.js'
13
+ import { registryCatalog } from '../src/registry.js'
14
+
15
+ const root = join(dirname(fileURLToPath(import.meta.url)), '..')
16
+ const jsonDir = join(root, 'json')
17
+ const promptsDir = join(root, 'prompts')
18
+ const registryDir = join(root, 'registry')
19
+ const demoRegistry = join(root, '../../apps/demo/public/registry')
20
+
21
+ mkdirSync(jsonDir, { recursive: true })
22
+ mkdirSync(promptsDir, { recursive: true })
23
+ mkdirSync(join(registryDir, 'components'), { recursive: true })
24
+ mkdirSync(join(registryDir, 'machines'), { recursive: true })
25
+
26
+ writeFileSync(join(jsonDir, 'catalog.json'), `${JSON.stringify(catalog, null, 2)}\n`)
27
+
28
+ for (const [id, schema] of Object.entries(componentSchemas)) {
29
+ writeFileSync(join(jsonDir, `${id}.json`), `${JSON.stringify(schema, null, 2)}\n`)
30
+ writeFileSync(join(registryDir, 'components', `${id}.json`), `${JSON.stringify(schema, null, 2)}\n`)
31
+ }
32
+
33
+ const machines = {
34
+ async: asyncMachine,
35
+ buttonLifecycle: buttonLifecycleMachine,
36
+ dialog: dialogMachine,
37
+ field: fieldMachine,
38
+ } as const
39
+
40
+ for (const [id, machine] of Object.entries(machines)) {
41
+ const schema = aeonToSchema(machine)
42
+ writeFileSync(join(registryDir, 'machines', `${id}.json`), `${JSON.stringify(schema, null, 2)}\n`)
43
+ }
44
+
45
+ writeFileSync(join(registryDir, 'catalog.json'), `${JSON.stringify(registryCatalog, null, 2)}\n`)
46
+
47
+ writeFileSync(join(promptsDir, 'system.md'), `${AEON_SYSTEM_PROMPT.trim()}\n`)
48
+ writeFileSync(join(promptsDir, 'cursorrules.md'), `${CURSOR_RULES_SNIPPET.trim()}\n`)
49
+ writeFileSync(
50
+ join(promptsDir, 'statecharts.md'),
51
+ `# Aeon UI statecharts (agent prompts)\n\n${Object.values(STATECHART_PROMPTS).join('\n\n')}\n`,
52
+ )
53
+
54
+ mkdirSync(demoRegistry, { recursive: true })
55
+ if (existsSync(registryDir)) {
56
+ cpSync(registryDir, demoRegistry, { recursive: true })
57
+ }
58
+
59
+ console.log(
60
+ `Emitted ${Object.keys(componentSchemas).length} schemas + ${Object.keys(machines).length} machines → registry/ (+ demo public)`,
61
+ )
@@ -0,0 +1,70 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { createActor } from 'xstate'
3
+ import { asyncMachine, buttonLifecycleMachine } from '@aeon-ui/primitives'
4
+ import { aeonSnapshotSchema, aeonToPrompt, aeonToSchema } from './aeon-to-schema.js'
5
+ import { createAgentEventBridge } from './agent-bridge.js'
6
+
7
+ describe('aeonToSchema', () => {
8
+ it('builds a hierarchical state tree for async', () => {
9
+ const schema = aeonToSchema(asyncMachine)
10
+ expect(schema.id).toBe('async')
11
+ expect(schema.events).toEqual(expect.arrayContaining(['FETCH', 'RESOLVE', 'REJECT', 'RESET']))
12
+ expect(schema.tree.children.map((c) => c.key)).toEqual(
13
+ expect.arrayContaining(['idle', 'loading', 'success', 'failure', 'empty']),
14
+ )
15
+ const idle = schema.tree.children.find((c) => c.key === 'idle')
16
+ expect(idle?.events).toEqual(expect.arrayContaining(['FETCH', 'RESET']))
17
+ })
18
+
19
+ it('omits internal xstate.* events from the public tree', () => {
20
+ const schema = aeonToSchema(asyncMachine)
21
+ expect(schema.events.every((e) => !e.startsWith('xstate.'))).toBe(true)
22
+ })
23
+
24
+ it('lists only valid events for the live snapshot', () => {
25
+ const actor = createActor(asyncMachine)
26
+ actor.start()
27
+ const live = aeonSnapshotSchema(asyncMachine, actor.getSnapshot())
28
+ expect(live.value).toBe('idle')
29
+ expect(live.validEvents).toEqual(expect.arrayContaining(['FETCH', 'RESET']))
30
+ expect(live.validEvents).not.toContain('RESOLVE')
31
+ actor.stop()
32
+ })
33
+
34
+ it('produces a prompt with JSON tree', () => {
35
+ const prompt = aeonToPrompt(buttonLifecycleMachine)
36
+ expect(prompt).toContain('buttonLifecycle')
37
+ expect(prompt).toContain('```json')
38
+ expect(prompt).toContain('PRESS')
39
+ })
40
+ })
41
+
42
+ describe('createAgentEventBridge', () => {
43
+ it('maps AGENT_STREAM_START → FETCH and blocks illegal events', () => {
44
+ const actor = createActor(asyncMachine)
45
+ actor.start()
46
+ const illegal: string[] = []
47
+ const bridge = createAgentEventBridge(actor, {
48
+ map: {
49
+ AGENT_STREAM_START: 'FETCH',
50
+ AGENT_STREAM_ERROR: (e) =>
51
+ e.type === 'AGENT_STREAM_ERROR' ? { type: 'REJECT', error: e.error } : null,
52
+ },
53
+ onIllegal: (ev, reason) => illegal.push(`${ev.type}:${reason}`),
54
+ })
55
+
56
+ expect(bridge.push({ type: 'AGENT_STREAM_START' })).toBe(true)
57
+ expect(actor.getSnapshot().value).toBe('loading')
58
+
59
+ // RESOLVE is valid in loading — but AGENT_STREAM_ERROR maps to REJECT which is also valid
60
+ expect(bridge.push({ type: 'AGENT_STREAM_ERROR', error: 'boom' })).toBe(true)
61
+ expect(actor.getSnapshot().value).toBe('failure')
62
+
63
+ // FETCH is valid from failure
64
+ expect(bridge.push({ type: 'AGENT_STREAM_START' })).toBe(true)
65
+ expect(actor.getSnapshot().value).toBe('loading')
66
+
67
+ actor.stop()
68
+ expect(illegal).toEqual([])
69
+ })
70
+ })
@@ -0,0 +1,206 @@
1
+ import type { AnyStateMachine, AnyStateNode, SnapshotFrom } from 'xstate'
2
+ import {
3
+ createActor,
4
+ getNextTransitions,
5
+ getStateNodes,
6
+ __unsafe_getAllOwnEventDescriptors,
7
+ } from 'xstate'
8
+
9
+ /** Hierarchical state-tree node for LLM / Generative UI consumption. */
10
+ export type AeonStateTreeNode = {
11
+ key: string
12
+ id: string
13
+ type: string
14
+ events: string[]
15
+ transitions: Array<{
16
+ event: string
17
+ target: string[]
18
+ guarded: boolean
19
+ }>
20
+ children: AeonStateTreeNode[]
21
+ }
22
+
23
+ /** Deterministic statechart JSON an agent can read at any micro-moment. */
24
+ export type AeonMachineSchema = {
25
+ id: string
26
+ initial: string | undefined
27
+ events: string[]
28
+ tree: AeonStateTreeNode
29
+ /** Flat map: state id → events defined on that node */
30
+ states: Record<string, { events: string[]; type: string }>
31
+ }
32
+
33
+ export type AeonSnapshotSchema = {
34
+ machineId: string
35
+ value: unknown
36
+ /** Event types valid from the active configuration (no getNextEvents in XState v5). */
37
+ validEvents: string[]
38
+ /** Transition rows including guard presence — agents should prefer unguarded or known payloads. */
39
+ nextTransitions: Array<{
40
+ event: string
41
+ target: string[]
42
+ guarded: boolean
43
+ }>
44
+ activeStateIds: string[]
45
+ }
46
+
47
+ function isPublicEvent(event: string): boolean {
48
+ return !event.startsWith('xstate.')
49
+ }
50
+
51
+ function filterPublicEvents(events: readonly string[]): string[] {
52
+ return events.filter(isPublicEvent)
53
+ }
54
+
55
+ function walkNode(node: AnyStateNode): AeonStateTreeNode {
56
+ const on = node.config.on ?? {}
57
+ const transitionEntries = Object.entries(on as Record<string, unknown>)
58
+ .filter(([event]) => isPublicEvent(event))
59
+ .map(([event, def]) => {
60
+ const targets: string[] = []
61
+ const list = Array.isArray(def) ? def : [def]
62
+ let guarded = false
63
+ for (const item of list) {
64
+ if (item == null) continue
65
+ if (typeof item === 'string') {
66
+ targets.push(item)
67
+ continue
68
+ }
69
+ if (typeof item === 'object') {
70
+ const row = item as { target?: string | string[]; guard?: unknown }
71
+ if (row.guard != null) guarded = true
72
+ if (typeof row.target === 'string') targets.push(row.target)
73
+ else if (Array.isArray(row.target)) targets.push(...row.target)
74
+ }
75
+ }
76
+ return { event, target: targets, guarded }
77
+ })
78
+
79
+ return {
80
+ key: node.key,
81
+ id: node.id,
82
+ type: node.type,
83
+ events: filterPublicEvents([...(node.events ?? [])]),
84
+ transitions: transitionEntries,
85
+ children: Object.values(node.states ?? {}).map(walkNode),
86
+ }
87
+ }
88
+
89
+ function flattenNodes(node: AnyStateNode, out: AeonMachineSchema['states']) {
90
+ out[node.id] = {
91
+ events: filterPublicEvents([...(node.events ?? [])]),
92
+ type: node.type,
93
+ }
94
+ for (const child of Object.values(node.states ?? {})) {
95
+ flattenNodes(child, out)
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Stringify an XState machine into a clean hierarchical state-tree JSON.
101
+ * Use this as the runtime contract for agents that must know which events
102
+ * (TOGGLE, SUBMIT, FETCH, …) are legal before calling `send`.
103
+ * Internal timers (`xstate.after.*`) are omitted — agents send public events only.
104
+ */
105
+ export function aeonToSchema(machine: AnyStateMachine): AeonMachineSchema {
106
+ const tree = walkNode(machine.root)
107
+ const flat: AeonMachineSchema['states'] = {}
108
+ flattenNodes(machine.root, flat)
109
+
110
+ const initial =
111
+ typeof machine.config.initial === 'string' ? machine.config.initial : undefined
112
+
113
+ return {
114
+ id: machine.id,
115
+ initial,
116
+ events: filterPublicEvents([...(machine.events ?? [])]),
117
+ tree,
118
+ states: flat,
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Snapshot-aware companion to `aeonToSchema`.
124
+ * Call whenever the actor advances so the LLM only proposes legal next events.
125
+ */
126
+ export function aeonSnapshotSchema(
127
+ machine: AnyStateMachine,
128
+ snapshot: SnapshotFrom<AnyStateMachine>,
129
+ ): AeonSnapshotSchema {
130
+ const active = getStateNodes(machine.root, snapshot.value)
131
+ const next = getNextTransitions(snapshot)
132
+
133
+ return {
134
+ machineId: machine.id,
135
+ value: snapshot.value,
136
+ validEvents: [...__unsafe_getAllOwnEventDescriptors(snapshot)].filter(
137
+ (e) => !e.startsWith('xstate.'),
138
+ ),
139
+ nextTransitions: next
140
+ .filter((t) => !t.eventType.startsWith('xstate.'))
141
+ .map((t) => ({
142
+ event: t.eventType,
143
+ target: (t.target ?? []).map((n) => n.id),
144
+ guarded: Boolean(t.guard),
145
+ })),
146
+ activeStateIds: active.map((n) => n.id),
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Turn a machine (+ optional live snapshot) into a deterministic system-prompt fragment.
152
+ */
153
+ export function aeonToPrompt(
154
+ machine: AnyStateMachine,
155
+ snapshot?: SnapshotFrom<AnyStateMachine>,
156
+ ): string {
157
+ const schema = aeonToSchema(machine)
158
+ const lines = [
159
+ `## Aeon statechart: ${schema.id}`,
160
+ `Initial: ${schema.initial ?? '(none)'}`,
161
+ `All events: ${schema.events.join(', ') || '(none)'}`,
162
+ '',
163
+ '### State tree (JSON)',
164
+ '```json',
165
+ JSON.stringify(schema.tree, null, 2),
166
+ '```',
167
+ '',
168
+ 'Rules for agents:',
169
+ '- Only send event types listed under the *active* configuration.',
170
+ '- Never invent events or targets not present in this tree.',
171
+ '- Prefer events with guarded:false unless you can satisfy the guard payload.',
172
+ ]
173
+
174
+ if (snapshot) {
175
+ const live = aeonSnapshotSchema(machine, snapshot)
176
+ lines.push(
177
+ '',
178
+ '### Live snapshot',
179
+ `- value: ${JSON.stringify(live.value)}`,
180
+ `- validEvents now: ${live.validEvents.join(', ') || '(none)'}`,
181
+ `- nextTransitions: ${JSON.stringify(live.nextTransitions)}`,
182
+ )
183
+ }
184
+
185
+ return lines.join('\n')
186
+ }
187
+
188
+ /**
189
+ * Convenience: start a throwaway actor at the initial state and return both
190
+ * static schema + snapshot schema for prompt injection.
191
+ */
192
+ export function aeonInitialAgentContext(machine: AnyStateMachine): {
193
+ schema: AeonMachineSchema
194
+ snapshot: AeonSnapshotSchema
195
+ prompt: string
196
+ } {
197
+ const actor = createActor(machine)
198
+ actor.start()
199
+ const snap = actor.getSnapshot()
200
+ actor.stop()
201
+ return {
202
+ schema: aeonToSchema(machine),
203
+ snapshot: aeonSnapshotSchema(machine, snap),
204
+ prompt: aeonToPrompt(machine, snap),
205
+ }
206
+ }
@@ -0,0 +1,82 @@
1
+ import type { AnyEventObject, AnyActorRef } from 'xstate'
2
+
3
+ /** Streaming / tool-loop events from an LLM or automation. */
4
+ export type AgentStreamEvent =
5
+ | { type: 'AGENT_STREAM_START'; taskId?: string }
6
+ | { type: 'AGENT_STREAM_CHUNK'; taskId?: string; data?: unknown }
7
+ | { type: 'AGENT_STREAM_END'; taskId?: string; data?: unknown }
8
+ | { type: 'AGENT_STREAM_ERROR'; taskId?: string; error: string }
9
+ | { type: 'AGENT_TOOL_CALL'; name: string; args?: unknown }
10
+ | { type: 'AGENT_TOOL_RESULT'; name: string; result?: unknown }
11
+ | { type: string; [key: string]: unknown }
12
+
13
+ export type AgentEventMap = Record<string, string | ((event: AgentStreamEvent) => AnyEventObject | null)>
14
+
15
+ export type AgentBridgeOptions = {
16
+ /**
17
+ * Map inbound agent event types → machine event types or transformers.
18
+ * Example: `{ AGENT_STREAM_START: 'FETCH', AGENT_STREAM_ERROR: (e) => ({ type: 'REJECT', error: e.error }) }`
19
+ */
20
+ map: AgentEventMap
21
+ /** Optional filter — return false to drop the event. */
22
+ accept?: (event: AgentStreamEvent) => boolean
23
+ /** Called when a mapped event is not allowed by `snapshot.can` (if actor exposes getSnapshot). */
24
+ onIllegal?: (event: AnyEventObject, reason: string) => void
25
+ }
26
+
27
+ type Sendable = {
28
+ send: (event: AnyEventObject) => void
29
+ getSnapshot?: () => { can: (event: AnyEventObject) => boolean }
30
+ }
31
+
32
+ /**
33
+ * Bind streaming LLM / tool-loop events to an Aeon machine actor.
34
+ * Prevents agents from firing transitions the chart will reject.
35
+ */
36
+ export function createAgentEventBridge(actor: Sendable | AnyActorRef, options: AgentBridgeOptions) {
37
+ const { map, accept, onIllegal } = options
38
+
39
+ const resolve = (incoming: AgentStreamEvent): AnyEventObject | null => {
40
+ if (accept && !accept(incoming)) return null
41
+ const binding = map[incoming.type]
42
+ if (binding == null) return null
43
+ if (typeof binding === 'function') return binding(incoming)
44
+ return { type: binding }
45
+ }
46
+
47
+ const push = (incoming: AgentStreamEvent): boolean => {
48
+ const event = resolve(incoming)
49
+ if (!event) return false
50
+
51
+ const snap = typeof actor.getSnapshot === 'function' ? actor.getSnapshot() : undefined
52
+ if (snap && !snap.can(event)) {
53
+ onIllegal?.(event, `Event ${event.type} is not valid in the current configuration`)
54
+ return false
55
+ }
56
+
57
+ actor.send(event)
58
+ return true
59
+ }
60
+
61
+ return {
62
+ /** Push one agent/stream event through the map into `machine.send`. */
63
+ push,
64
+ /** Map of known agent → machine bindings (for prompts / docs). */
65
+ map,
66
+ /** Describe the bridge for system prompts. */
67
+ toPrompt(): string {
68
+ const rows = Object.entries(map).map(([from, to]) => {
69
+ const dest = typeof to === 'string' ? to : '(transform)'
70
+ return `- ${from} → ${dest}`
71
+ })
72
+ return [
73
+ '## Agent event bridge',
74
+ 'Inbound stream events map to machine events:',
75
+ ...rows,
76
+ 'Illegal events (rejected by snapshot.can) are dropped.',
77
+ ].join('\n')
78
+ },
79
+ }
80
+ }
81
+
82
+ export type AgentEventBridge = ReturnType<typeof createAgentEventBridge>