@lynx-js/genui 0.0.1-rc.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 (254) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +170 -0
  3. package/a2ui/README.md +140 -0
  4. package/a2ui/dist/catalog/Button/catalog.json +156 -0
  5. package/a2ui/dist/catalog/Button/index.d.ts +35 -0
  6. package/a2ui/dist/catalog/Button/index.js +35 -0
  7. package/a2ui/dist/catalog/Button/index.js.map +1 -0
  8. package/a2ui/dist/catalog/Card/catalog.json +24 -0
  9. package/a2ui/dist/catalog/Card/index.d.ts +11 -0
  10. package/a2ui/dist/catalog/Card/index.js +19 -0
  11. package/a2ui/dist/catalog/Card/index.js.map +1 -0
  12. package/a2ui/dist/catalog/CheckBox/catalog.json +170 -0
  13. package/a2ui/dist/catalog/CheckBox/index.d.ts +32 -0
  14. package/a2ui/dist/catalog/CheckBox/index.js +24 -0
  15. package/a2ui/dist/catalog/CheckBox/index.js.map +1 -0
  16. package/a2ui/dist/catalog/Column/catalog.json +57 -0
  17. package/a2ui/dist/catalog/Column/index.d.ts +15 -0
  18. package/a2ui/dist/catalog/Column/index.js +55 -0
  19. package/a2ui/dist/catalog/Column/index.js.map +1 -0
  20. package/a2ui/dist/catalog/Divider/catalog.json +14 -0
  21. package/a2ui/dist/catalog/Divider/index.d.ts +9 -0
  22. package/a2ui/dist/catalog/Divider/index.js +8 -0
  23. package/a2ui/dist/catalog/Divider/index.js.map +1 -0
  24. package/a2ui/dist/catalog/Icon/catalog.json +45 -0
  25. package/a2ui/dist/catalog/Icon/index.d.ts +14 -0
  26. package/a2ui/dist/catalog/Icon/index.js +11 -0
  27. package/a2ui/dist/catalog/Icon/index.js.map +1 -0
  28. package/a2ui/dist/catalog/Image/catalog.json +62 -0
  29. package/a2ui/dist/catalog/Image/index.d.ts +16 -0
  30. package/a2ui/dist/catalog/Image/index.js +30 -0
  31. package/a2ui/dist/catalog/Image/index.js.map +1 -0
  32. package/a2ui/dist/catalog/LineChart/catalog.json +98 -0
  33. package/a2ui/dist/catalog/LineChart/index.d.ts +31 -0
  34. package/a2ui/dist/catalog/LineChart/index.js +195 -0
  35. package/a2ui/dist/catalog/LineChart/index.js.map +1 -0
  36. package/a2ui/dist/catalog/List/catalog.json +52 -0
  37. package/a2ui/dist/catalog/List/index.d.ts +15 -0
  38. package/a2ui/dist/catalog/List/index.js +53 -0
  39. package/a2ui/dist/catalog/List/index.js.map +1 -0
  40. package/a2ui/dist/catalog/Modal/catalog.json +18 -0
  41. package/a2ui/dist/catalog/Modal/index.d.ts +12 -0
  42. package/a2ui/dist/catalog/Modal/index.js +33 -0
  43. package/a2ui/dist/catalog/Modal/index.js.map +1 -0
  44. package/a2ui/dist/catalog/PieChart/catalog.json +87 -0
  45. package/a2ui/dist/catalog/PieChart/index.d.ts +37 -0
  46. package/a2ui/dist/catalog/PieChart/index.js +131 -0
  47. package/a2ui/dist/catalog/PieChart/index.js.map +1 -0
  48. package/a2ui/dist/catalog/RadioGroup/catalog.json +184 -0
  49. package/a2ui/dist/catalog/RadioGroup/index.d.ts +36 -0
  50. package/a2ui/dist/catalog/RadioGroup/index.js +36 -0
  51. package/a2ui/dist/catalog/RadioGroup/index.js.map +1 -0
  52. package/a2ui/dist/catalog/Row/catalog.json +57 -0
  53. package/a2ui/dist/catalog/Row/index.d.ts +15 -0
  54. package/a2ui/dist/catalog/Row/index.js +28 -0
  55. package/a2ui/dist/catalog/Row/index.js.map +1 -0
  56. package/a2ui/dist/catalog/Slider/catalog.json +183 -0
  57. package/a2ui/dist/catalog/Slider/index.d.ts +41 -0
  58. package/a2ui/dist/catalog/Slider/index.js +39 -0
  59. package/a2ui/dist/catalog/Slider/index.js.map +1 -0
  60. package/a2ui/dist/catalog/Slider/utils.d.ts +11 -0
  61. package/a2ui/dist/catalog/Slider/utils.js +58 -0
  62. package/a2ui/dist/catalog/Slider/utils.js.map +1 -0
  63. package/a2ui/dist/catalog/Tabs/catalog.json +28 -0
  64. package/a2ui/dist/catalog/Tabs/index.d.ts +12 -0
  65. package/a2ui/dist/catalog/Tabs/index.js +32 -0
  66. package/a2ui/dist/catalog/Tabs/index.js.map +1 -0
  67. package/a2ui/dist/catalog/Text/catalog.json +74 -0
  68. package/a2ui/dist/catalog/Text/index.d.ts +18 -0
  69. package/a2ui/dist/catalog/Text/index.js +27 -0
  70. package/a2ui/dist/catalog/Text/index.js.map +1 -0
  71. package/a2ui/dist/catalog/TextField/catalog.json +147 -0
  72. package/a2ui/dist/catalog/TextField/index.d.ts +35 -0
  73. package/a2ui/dist/catalog/TextField/index.js +43 -0
  74. package/a2ui/dist/catalog/TextField/index.js.map +1 -0
  75. package/a2ui/dist/catalog/TextField/utils.d.ts +7 -0
  76. package/a2ui/dist/catalog/TextField/utils.js +51 -0
  77. package/a2ui/dist/catalog/TextField/utils.js.map +1 -0
  78. package/a2ui/dist/catalog/defineCatalog.d.ts +119 -0
  79. package/a2ui/dist/catalog/defineCatalog.js +196 -0
  80. package/a2ui/dist/catalog/defineCatalog.js.map +1 -0
  81. package/a2ui/dist/catalog/index.d.ts +20 -0
  82. package/a2ui/dist/catalog/index.js +26 -0
  83. package/a2ui/dist/catalog/index.js.map +1 -0
  84. package/a2ui/dist/catalog/utils/chart.d.ts +3 -0
  85. package/a2ui/dist/catalog/utils/chart.js +28 -0
  86. package/a2ui/dist/catalog/utils/chart.js.map +1 -0
  87. package/a2ui/dist/functions/index.d.ts +19 -0
  88. package/a2ui/dist/functions/index.js +87 -0
  89. package/a2ui/dist/functions/index.js.map +1 -0
  90. package/a2ui/dist/index.d.ts +11 -0
  91. package/a2ui/dist/index.js +35 -0
  92. package/a2ui/dist/index.js.map +1 -0
  93. package/a2ui/dist/react/A2UI.d.ts +77 -0
  94. package/a2ui/dist/react/A2UI.js +159 -0
  95. package/a2ui/dist/react/A2UI.js.map +1 -0
  96. package/a2ui/dist/react/A2UIProvider.d.ts +25 -0
  97. package/a2ui/dist/react/A2UIProvider.js +20 -0
  98. package/a2ui/dist/react/A2UIProvider.js.map +1 -0
  99. package/a2ui/dist/react/A2UIRenderer.d.ts +34 -0
  100. package/a2ui/dist/react/A2UIRenderer.js +161 -0
  101. package/a2ui/dist/react/A2UIRenderer.js.map +1 -0
  102. package/a2ui/dist/react/FormContext.d.ts +10 -0
  103. package/a2ui/dist/react/FormContext.js +12 -0
  104. package/a2ui/dist/react/FormContext.js.map +1 -0
  105. package/a2ui/dist/react/index.d.ts +8 -0
  106. package/a2ui/dist/react/index.js +23 -0
  107. package/a2ui/dist/react/index.js.map +1 -0
  108. package/a2ui/dist/react/useA2UIContext.d.ts +7 -0
  109. package/a2ui/dist/react/useA2UIContext.js +19 -0
  110. package/a2ui/dist/react/useA2UIContext.js.map +1 -0
  111. package/a2ui/dist/react/useAction.d.ts +9 -0
  112. package/a2ui/dist/react/useAction.js +38 -0
  113. package/a2ui/dist/react/useAction.js.map +1 -0
  114. package/a2ui/dist/react/useCatalog.d.ts +7 -0
  115. package/a2ui/dist/react/useCatalog.js +13 -0
  116. package/a2ui/dist/react/useCatalog.js.map +1 -0
  117. package/a2ui/dist/react/useChecks.d.ts +27 -0
  118. package/a2ui/dist/react/useChecks.js +76 -0
  119. package/a2ui/dist/react/useChecks.js.map +1 -0
  120. package/a2ui/dist/react/useDataBinding.d.ts +10 -0
  121. package/a2ui/dist/react/useDataBinding.js +175 -0
  122. package/a2ui/dist/react/useDataBinding.js.map +1 -0
  123. package/a2ui/dist/store/FormController.d.ts +23 -0
  124. package/a2ui/dist/store/FormController.js +40 -0
  125. package/a2ui/dist/store/FormController.js.map +1 -0
  126. package/a2ui/dist/store/FunctionRegistry.d.ts +47 -0
  127. package/a2ui/dist/store/FunctionRegistry.js +23 -0
  128. package/a2ui/dist/store/FunctionRegistry.js.map +1 -0
  129. package/a2ui/dist/store/MessageProcessor.d.ts +28 -0
  130. package/a2ui/dist/store/MessageProcessor.js +408 -0
  131. package/a2ui/dist/store/MessageProcessor.js.map +1 -0
  132. package/a2ui/dist/store/MessageStore.d.ts +38 -0
  133. package/a2ui/dist/store/MessageStore.js +37 -0
  134. package/a2ui/dist/store/MessageStore.js.map +1 -0
  135. package/a2ui/dist/store/Resource.d.ts +45 -0
  136. package/a2ui/dist/store/Resource.js +80 -0
  137. package/a2ui/dist/store/Resource.js.map +1 -0
  138. package/a2ui/dist/store/SignalStore.d.ts +10 -0
  139. package/a2ui/dist/store/SignalStore.js +29 -0
  140. package/a2ui/dist/store/SignalStore.js.map +1 -0
  141. package/a2ui/dist/store/index.d.ts +14 -0
  142. package/a2ui/dist/store/index.js +15 -0
  143. package/a2ui/dist/store/index.js.map +1 -0
  144. package/a2ui/dist/store/payloadNormalizer.d.ts +27 -0
  145. package/a2ui/dist/store/payloadNormalizer.js +179 -0
  146. package/a2ui/dist/store/payloadNormalizer.js.map +1 -0
  147. package/a2ui/dist/store/resolveFunctionCall.d.ts +18 -0
  148. package/a2ui/dist/store/resolveFunctionCall.js +131 -0
  149. package/a2ui/dist/store/resolveFunctionCall.js.map +1 -0
  150. package/a2ui/dist/store/types.d.ts +68 -0
  151. package/a2ui/dist/store/types.js +2 -0
  152. package/a2ui/dist/store/types.js.map +1 -0
  153. package/a2ui/dist/tsconfig.build.tsbuildinfo +1 -0
  154. package/a2ui/styles/catalog/Button.css +83 -0
  155. package/a2ui/styles/catalog/Card.css +49 -0
  156. package/a2ui/styles/catalog/CheckBox.css +46 -0
  157. package/a2ui/styles/catalog/Column.css +89 -0
  158. package/a2ui/styles/catalog/Divider.css +20 -0
  159. package/a2ui/styles/catalog/Icon.css +39 -0
  160. package/a2ui/styles/catalog/Image.css +54 -0
  161. package/a2ui/styles/catalog/LineChart.css +116 -0
  162. package/a2ui/styles/catalog/List.css +38 -0
  163. package/a2ui/styles/catalog/Modal.css +60 -0
  164. package/a2ui/styles/catalog/PieChart.css +109 -0
  165. package/a2ui/styles/catalog/RadioGroup.css +123 -0
  166. package/a2ui/styles/catalog/Row.css +83 -0
  167. package/a2ui/styles/catalog/Slider.css +96 -0
  168. package/a2ui/styles/catalog/Tabs.css +46 -0
  169. package/a2ui/styles/catalog/Text.css +121 -0
  170. package/a2ui/styles/catalog/TextField.css +48 -0
  171. package/a2ui/styles/theme.css +62 -0
  172. package/a2ui-catalog-extractor/README.md +605 -0
  173. package/a2ui-catalog-extractor/bin/a2ui-catalog-extractor.js +6 -0
  174. package/a2ui-catalog-extractor/dist/cli.d.ts +12 -0
  175. package/a2ui-catalog-extractor/dist/cli.js +171 -0
  176. package/a2ui-catalog-extractor/dist/cli.js.map +1 -0
  177. package/a2ui-catalog-extractor/dist/index.d.ts +140 -0
  178. package/a2ui-catalog-extractor/dist/index.js +755 -0
  179. package/a2ui-catalog-extractor/dist/index.js.map +1 -0
  180. package/a2ui-catalog-extractor/dist/tsconfig.build.tsbuildinfo +1 -0
  181. package/a2ui-catalog-extractor/skills/a2ui-catalog-extractor/SKILL.md +30 -0
  182. package/a2ui-prompt/README.md +65 -0
  183. package/a2ui-prompt/dist/index.d.ts +91 -0
  184. package/a2ui-prompt/dist/index.js +767 -0
  185. package/cli/README.md +88 -0
  186. package/cli/bin/cli.js +271 -0
  187. package/dist/index.d.ts +10 -0
  188. package/dist/index.js +10 -0
  189. package/dist/index.js.map +1 -0
  190. package/dist/tsconfig.build.tsbuildinfo +1 -0
  191. package/index.ts +114 -0
  192. package/openui/README.md +211 -0
  193. package/openui/dist/catalog/Action/index.d.ts +20 -0
  194. package/openui/dist/catalog/Action/index.js +23 -0
  195. package/openui/dist/catalog/Action/index.js.map +1 -0
  196. package/openui/dist/catalog/Button/index.d.ts +64 -0
  197. package/openui/dist/catalog/Button/index.js +75 -0
  198. package/openui/dist/catalog/Button/index.js.map +1 -0
  199. package/openui/dist/catalog/Card/index.d.ts +34 -0
  200. package/openui/dist/catalog/Card/index.js +69 -0
  201. package/openui/dist/catalog/Card/index.js.map +1 -0
  202. package/openui/dist/catalog/CardHeader/index.d.ts +5 -0
  203. package/openui/dist/catalog/CardHeader/index.js +18 -0
  204. package/openui/dist/catalog/CardHeader/index.js.map +1 -0
  205. package/openui/dist/catalog/Separator/index.d.ts +2 -0
  206. package/openui/dist/catalog/Separator/index.js +13 -0
  207. package/openui/dist/catalog/Separator/index.js.map +1 -0
  208. package/openui/dist/catalog/Stack/index.d.ts +29 -0
  209. package/openui/dist/catalog/Stack/index.js +61 -0
  210. package/openui/dist/catalog/Stack/index.js.map +1 -0
  211. package/openui/dist/catalog/Tag/index.d.ts +4 -0
  212. package/openui/dist/catalog/Tag/index.js +15 -0
  213. package/openui/dist/catalog/Tag/index.js.map +1 -0
  214. package/openui/dist/catalog/TextContent/index.d.ts +11 -0
  215. package/openui/dist/catalog/TextContent/index.js +33 -0
  216. package/openui/dist/catalog/TextContent/index.js.map +1 -0
  217. package/openui/dist/catalog/index.d.ts +7 -0
  218. package/openui/dist/catalog/index.js +11 -0
  219. package/openui/dist/catalog/index.js.map +1 -0
  220. package/openui/dist/catalog/utils.d.ts +2 -0
  221. package/openui/dist/catalog/utils.js +17 -0
  222. package/openui/dist/catalog/utils.js.map +1 -0
  223. package/openui/dist/core/context.d.ts +112 -0
  224. package/openui/dist/core/context.js +99 -0
  225. package/openui/dist/core/context.js.map +1 -0
  226. package/openui/dist/core/createLibrary.d.ts +10 -0
  227. package/openui/dist/core/createLibrary.js +36 -0
  228. package/openui/dist/core/createLibrary.js.map +1 -0
  229. package/openui/dist/core/hooks/index.d.ts +4 -0
  230. package/openui/dist/core/hooks/index.js +6 -0
  231. package/openui/dist/core/hooks/index.js.map +1 -0
  232. package/openui/dist/core/hooks/useFormValidation.d.ts +13 -0
  233. package/openui/dist/core/hooks/useFormValidation.js +76 -0
  234. package/openui/dist/core/hooks/useFormValidation.js.map +1 -0
  235. package/openui/dist/core/hooks/useOpenUIState.d.ts +33 -0
  236. package/openui/dist/core/hooks/useOpenUIState.js +413 -0
  237. package/openui/dist/core/hooks/useOpenUIState.js.map +1 -0
  238. package/openui/dist/core/hooks/useStateField.d.ts +2 -0
  239. package/openui/dist/core/hooks/useStateField.js +11 -0
  240. package/openui/dist/core/hooks/useStateField.js.map +1 -0
  241. package/openui/dist/core/index.d.ts +7 -0
  242. package/openui/dist/core/index.js +8 -0
  243. package/openui/dist/core/index.js.map +1 -0
  244. package/openui/dist/core/library.d.ts +20 -0
  245. package/openui/dist/core/library.js +13 -0
  246. package/openui/dist/core/library.js.map +1 -0
  247. package/openui/dist/core/renderer.css +271 -0
  248. package/openui/dist/core/renderer.d.ts +9 -0
  249. package/openui/dist/core/renderer.js +139 -0
  250. package/openui/dist/core/renderer.js.map +1 -0
  251. package/openui/dist/core/utils.d.ts +1 -0
  252. package/openui/dist/core/utils.js +76 -0
  253. package/openui/dist/core/utils.js.map +1 -0
  254. package/package.json +120 -0
@@ -0,0 +1,605 @@
1
+ # A2UI Catalog Extractor
2
+
3
+ English | [简体中文](./readme.zh_cn.md)
4
+
5
+ `@lynx-js/genui/a2ui-catalog-extractor` turns TypeScript component
6
+ interfaces into A2UI component catalog JSON. You write the public
7
+ component contract once as a TypeScript `interface`, describe it with
8
+ normal TypeDoc comments, and let this package generate the JSON Schema
9
+ that an A2UI agent can read.
10
+
11
+ ## What It Does
12
+
13
+ A2UI catalogs describe what components a renderer supports. For each
14
+ component, the catalog tells an agent which props are valid, which props
15
+ are required, which enum values are allowed, and what each field means.
16
+
17
+ This extractor generates the `components` part of an A2UI v0.9 catalog:
18
+
19
+ ```json
20
+ {
21
+ "QuickStartCard": {
22
+ "properties": {
23
+ "title": { "type": "string" }
24
+ },
25
+ "required": ["title"]
26
+ }
27
+ }
28
+ ```
29
+
30
+ It can also wrap those generated components with a `catalogId`,
31
+ `functions`, and `theme` through `createA2UICatalog`.
32
+
33
+ ## What It Does Not Do
34
+
35
+ - It does not render A2UI UI.
36
+ - It does not parse TypeScript source text by hand.
37
+ - It does not use the TypeScript compiler API directly.
38
+ - It does not ask you to write JSON Schema in comments.
39
+ - It does not expand arbitrary imported type aliases or external
40
+ interfaces.
41
+ - It does not call an LLM or choose a model.
42
+
43
+ The package consumes TypeDoc reflection data. This keeps the implementation
44
+ small, but it also means catalog-facing shapes should be written inline in
45
+ the marked interface.
46
+
47
+ ## Requirements
48
+
49
+ - Node.js 22 or newer.
50
+ - TypeScript or TSX source files that TypeDoc can read.
51
+ - One TypeScript `interface` per catalog-facing component contract.
52
+
53
+ ## Installation
54
+
55
+ ### Package manager
56
+
57
+ Install the extractor as a development dependency:
58
+
59
+ ```bash
60
+ pnpm add -D @lynx-js/genui
61
+ ```
62
+
63
+ Then add a script to your package:
64
+
65
+ ```json
66
+ {
67
+ "scripts": {
68
+ "build:catalog": "a2ui-catalog-extractor --catalog-dir src/catalog --out-dir dist/catalog"
69
+ }
70
+ }
71
+ ```
72
+
73
+ Run it with:
74
+
75
+ ```bash
76
+ pnpm build:catalog
77
+ ```
78
+
79
+ ## Quick Start
80
+
81
+ This example walks through a complete component contract from TypeScript
82
+ interface to generated catalog JSON.
83
+
84
+ ### 1. Create a catalog-facing interface
85
+
86
+ Create `src/catalog/QuickStartCard.tsx`:
87
+
88
+ ```tsx
89
+ /**
90
+ * Quick start card.
91
+ *
92
+ * @remarks Use this contract as a compact card example.
93
+ * @a2uiCatalog QuickStartCard
94
+ */
95
+ export interface QuickStartCardProps {
96
+ /** Card title text or data binding. */
97
+ title: string | { path: string };
98
+ /** Visual tone used by the renderer. */
99
+ tone?: 'neutral' | 'accent';
100
+ /**
101
+ * Tags shown below the title.
102
+ *
103
+ * @defaultValue `[]`
104
+ */
105
+ tags?: string[];
106
+ /** Author metadata rendered in the card footer. */
107
+ author: {
108
+ /** Display name. */
109
+ name: string;
110
+ /** Optional profile URL. */
111
+ url?: string;
112
+ };
113
+ /**
114
+ * Extra analytics context sent with user actions.
115
+ *
116
+ * @defaultValue `{}`
117
+ */
118
+ context?: Record<string, string | number | boolean>;
119
+ }
120
+ ```
121
+
122
+ The important part is `@a2uiCatalog QuickStartCard`. It tells the
123
+ extractor that this interface should become a catalog component named
124
+ `QuickStartCard`.
125
+
126
+ ### 2. Generate catalog files
127
+
128
+ Run:
129
+
130
+ ```bash
131
+ a2ui-catalog-extractor --catalog-dir src/catalog --out-dir dist/catalog
132
+ ```
133
+
134
+ The extractor scans the catalog directory, finds interfaces marked with
135
+ `@a2uiCatalog`, and writes one file per component:
136
+
137
+ ```text
138
+ dist/catalog/
139
+ QuickStartCard/
140
+ catalog.json
141
+ ```
142
+
143
+ ### 3. Read the generated schema
144
+
145
+ `dist/catalog/QuickStartCard/catalog.json` will look like this:
146
+
147
+ ```json
148
+ {
149
+ "QuickStartCard": {
150
+ "properties": {
151
+ "title": {
152
+ "oneOf": [
153
+ {
154
+ "type": "string"
155
+ },
156
+ {
157
+ "type": "object",
158
+ "properties": {
159
+ "path": {
160
+ "type": "string"
161
+ }
162
+ },
163
+ "required": [
164
+ "path"
165
+ ],
166
+ "additionalProperties": false
167
+ }
168
+ ],
169
+ "description": "Card title text or data binding."
170
+ },
171
+ "tone": {
172
+ "type": "string",
173
+ "enum": [
174
+ "neutral",
175
+ "accent"
176
+ ],
177
+ "description": "Visual tone used by the renderer."
178
+ },
179
+ "tags": {
180
+ "type": "array",
181
+ "items": {
182
+ "type": "string"
183
+ },
184
+ "description": "Tags shown below the title.",
185
+ "default": []
186
+ },
187
+ "author": {
188
+ "type": "object",
189
+ "properties": {
190
+ "name": {
191
+ "type": "string",
192
+ "description": "Display name."
193
+ },
194
+ "url": {
195
+ "type": "string",
196
+ "description": "Optional profile URL."
197
+ }
198
+ },
199
+ "required": [
200
+ "name"
201
+ ],
202
+ "additionalProperties": false,
203
+ "description": "Author metadata rendered in the card footer."
204
+ },
205
+ "context": {
206
+ "type": "object",
207
+ "additionalProperties": {
208
+ "oneOf": [
209
+ {
210
+ "type": "string"
211
+ },
212
+ {
213
+ "type": "number"
214
+ },
215
+ {
216
+ "type": "boolean"
217
+ }
218
+ ]
219
+ },
220
+ "description": "Extra analytics context sent with user actions.",
221
+ "default": {}
222
+ }
223
+ },
224
+ "required": [
225
+ "title",
226
+ "author"
227
+ ],
228
+ "description": "Quick start card.\n\nUse this contract as a compact card example."
229
+ }
230
+ }
231
+ ```
232
+
233
+ Notice the main conversions:
234
+
235
+ - `title` is required because it does not use `?`.
236
+ - `tone` becomes a string enum.
237
+ - `tags?: string[]` becomes an optional array of strings.
238
+ - `author` becomes a strict inline object with
239
+ `additionalProperties: false`.
240
+ - `context?: Record<string, string | number | boolean>` becomes an object
241
+ map with `additionalProperties`.
242
+ - TypeDoc comments become JSON Schema descriptions.
243
+
244
+ ## Authoring Guide
245
+
246
+ ### Mark only the catalog contract
247
+
248
+ Only TypeScript `interface` reflections are converted. Put
249
+ `@a2uiCatalog` on the interface that describes the props an agent is
250
+ allowed to send:
251
+
252
+ ```tsx
253
+ /**
254
+ * @a2uiCatalog Text
255
+ */
256
+ export interface TextProps {
257
+ text: string;
258
+ }
259
+ ```
260
+
261
+ Do not put the tag on the component function:
262
+
263
+ ```tsx
264
+ export function Text(_props: TextProps) {
265
+ return null;
266
+ }
267
+ ```
268
+
269
+ ### Component names
270
+
271
+ You can write the component name explicitly:
272
+
273
+ ```tsx
274
+ /**
275
+ * @a2uiCatalog Text
276
+ */
277
+ export interface TextProps {}
278
+ ```
279
+
280
+ If the tag is empty, the extractor infers the name from the interface by
281
+ removing a trailing `Props` or `ComponentProps`:
282
+
283
+ ```tsx
284
+ /**
285
+ * @a2uiCatalog
286
+ */
287
+ export interface DemoTextProps {}
288
+ ```
289
+
290
+ This becomes `DemoText`.
291
+
292
+ ### Comments become schema metadata
293
+
294
+ Use normal TypeDoc comments:
295
+
296
+ ```tsx
297
+ /**
298
+ * User-facing card.
299
+ *
300
+ * @remarks Use this for compact summaries.
301
+ * @a2uiCatalog SummaryCard
302
+ */
303
+ export interface SummaryCardProps {
304
+ /**
305
+ * Optional display density.
306
+ *
307
+ * @defaultValue `"comfortable"`
308
+ */
309
+ density?: 'compact' | 'comfortable';
310
+ }
311
+ ```
312
+
313
+ The extractor maps comments like this:
314
+
315
+ | TypeDoc comment | JSON Schema output |
316
+ | ----------------------------- | -------------------------------- |
317
+ | Summary text | `description` |
318
+ | `@remarks` | Appended to `description` |
319
+ | `@defaultValue` or `@default` | `default` |
320
+ | `@deprecated` | `deprecated: true` |
321
+ | Optional property `?` | Property omitted from `required` |
322
+
323
+ For object and array defaults, put JSON inside a code span:
324
+
325
+ ```tsx
326
+ /**
327
+ * @defaultValue `{}`
328
+ */
329
+ context?: Record<string, string>;
330
+ ```
331
+
332
+ Without the code span, TypeDoc may pass formatted text instead of the raw
333
+ JSON value.
334
+
335
+ ### Supported TypeScript shapes
336
+
337
+ | TypeScript shape | JSON Schema shape |
338
+ | ---------------------------- | ------------------------------------------------ |
339
+ | `string` | `{ "type": "string" }` |
340
+ | `number` | `{ "type": "number" }` |
341
+ | `boolean` | `{ "type": "boolean" }` |
342
+ | `'a' \| 'b'` | `{ "type": "string", "enum": ["a", "b"] }` |
343
+ | `string \| { path: string }` | `{ "oneOf": [...] }` |
344
+ | `T[]` | `{ "type": "array", "items": ... }` |
345
+ | `Array<T>` | `{ "type": "array", "items": ... }` |
346
+ | `ReadonlyArray<T>` | `{ "type": "array", "items": ... }` |
347
+ | `{ name: string }` | Strict object with `additionalProperties: false` |
348
+ | `Record<string, T>` | Object map with `additionalProperties: ...` |
349
+
350
+ ### Unsupported or ambiguous types
351
+
352
+ These types intentionally fail:
353
+
354
+ - `any`
355
+ - `unknown`
356
+ - `null`
357
+ - `undefined`
358
+ - `never`
359
+ - `void`
360
+ - nullable unions such as `string | null`
361
+ - most imported aliases and referenced external interfaces
362
+ - `Record<number, T>` or other non-string record keys
363
+
364
+ Prefer explicit catalog contracts:
365
+
366
+ ```tsx
367
+ // Avoid this in catalog-facing interfaces.
368
+ type ExternalCardData = {
369
+ title: string;
370
+ };
371
+
372
+ export interface CardProps {
373
+ data: ExternalCardData;
374
+ }
375
+ ```
376
+
377
+ Write the shape inline instead:
378
+
379
+ ```tsx
380
+ export interface CardProps {
381
+ data: {
382
+ title: string;
383
+ };
384
+ }
385
+ ```
386
+
387
+ ## CLI Reference
388
+
389
+ The package exposes the standalone `a2ui-catalog-extractor` binary. The
390
+ `@lynx-js/genui-cli` also exposes this flow as
391
+ `genui a2ui generate catalog`.
392
+
393
+ ### Generate catalog artifacts
394
+
395
+ ```bash
396
+ a2ui-catalog-extractor [options]
397
+ # or
398
+ genui a2ui generate catalog [options]
399
+ ```
400
+
401
+ | Option | Description | Default |
402
+ | ----------------------- | ---------------------------------------------------------------------------- | -------------- |
403
+ | `--catalog-dir <dir>` | Directory to scan for source files. Repeatable. | `src/catalog` |
404
+ | `--source <path>` | Source file or directory to scan. Repeatable. | None |
405
+ | `--typedoc-json <file>` | Read an existing TypeDoc JSON project instead of running TypeDoc conversion. | None |
406
+ | `--out-dir <dir>` | Directory where component catalog files are written. | `dist/catalog` |
407
+ | `--version`, `-v` | Print the package version. | None |
408
+ | `--help`, `-h` | Print usage. | None |
409
+
410
+ `--source` and `--catalog-dir` can be used together. The extractor merges
411
+ all inputs, removes duplicates, sorts them, and then runs TypeDoc.
412
+
413
+ The scanner accepts `.ts`, `.tsx`, `.js`, `.jsx`, `.mts`, and `.cts`
414
+ files. It ignores `.d.ts`, `node_modules`, `dist`, and `.turbo`.
415
+
416
+ ## Programmatic API
417
+
418
+ ### Generate components from source files
419
+
420
+ ```ts
421
+ import {
422
+ extractCatalogComponents,
423
+ writeComponentCatalogs,
424
+ } from '@lynx-js/genui/a2ui-catalog-extractor';
425
+
426
+ const components = await extractCatalogComponents({
427
+ sourceFiles: ['src/catalog/QuickStartCard.tsx'],
428
+ });
429
+
430
+ await writeComponentCatalogs({
431
+ sourceFiles: ['src/catalog/QuickStartCard.tsx'],
432
+ outDir: 'dist/catalog',
433
+ });
434
+ ```
435
+
436
+ Use `cwd` when paths should be resolved relative to a specific project
437
+ directory:
438
+
439
+ ```ts
440
+ await writeComponentCatalogs({
441
+ cwd: process.cwd(),
442
+ sourceFiles: ['src/catalog/QuickStartCard.tsx'],
443
+ outDir: 'dist/catalog',
444
+ });
445
+ ```
446
+
447
+ Use `tsconfig` when the project needs a specific TypeScript config:
448
+
449
+ ```ts
450
+ const components = await extractCatalogComponents({
451
+ cwd: process.cwd(),
452
+ sourceFiles: ['src/catalog/QuickStartCard.tsx'],
453
+ tsconfig: 'tsconfig.json',
454
+ });
455
+ ```
456
+
457
+ ### Generate components from TypeDoc JSON
458
+
459
+ If your build already produces a TypeDoc JSON project, reuse it:
460
+
461
+ ```ts
462
+ import * as fs from 'node:fs';
463
+
464
+ import {
465
+ extractCatalogComponentsFromTypeDocJson,
466
+ writeCatalogComponents,
467
+ } from '@lynx-js/genui/a2ui-catalog-extractor';
468
+
469
+ const projectJson = JSON.parse(
470
+ await fs.promises.readFile('typedoc.json', 'utf8'),
471
+ );
472
+ const components = extractCatalogComponentsFromTypeDocJson(projectJson);
473
+
474
+ writeCatalogComponents(components, {
475
+ outDir: 'dist/catalog',
476
+ });
477
+ ```
478
+
479
+ The equivalent CLI command is:
480
+
481
+ ```bash
482
+ a2ui-catalog-extractor --typedoc-json typedoc.json --out-dir dist/catalog
483
+ ```
484
+
485
+ ### Create a full A2UI catalog object
486
+
487
+ `createA2UICatalog` is a small helper that wraps generated components with
488
+ the other top-level A2UI catalog fields:
489
+
490
+ ```ts
491
+ import {
492
+ createA2UICatalog,
493
+ extractCatalogComponents,
494
+ } from '@lynx-js/genui/a2ui-catalog-extractor';
495
+
496
+ const components = await extractCatalogComponents({
497
+ sourceFiles: ['src/catalog/QuickStartCard.tsx'],
498
+ });
499
+
500
+ const catalog = createA2UICatalog({
501
+ catalogId: 'https://example.com/catalogs/basic/v1/catalog.json',
502
+ components,
503
+ functions: [
504
+ {
505
+ name: 'formatDisplayValue',
506
+ description: 'Format a raw value for display.',
507
+ parameters: {
508
+ type: 'object',
509
+ properties: {
510
+ value: { type: 'string' },
511
+ },
512
+ required: ['value'],
513
+ additionalProperties: false,
514
+ },
515
+ returnType: 'string',
516
+ },
517
+ ],
518
+ theme: {
519
+ accentColor: { type: 'string' },
520
+ },
521
+ });
522
+ ```
523
+
524
+ `functions` and `theme` are not extracted from TypeScript. Pass them
525
+ explicitly if your catalog needs them.
526
+
527
+ ## Troubleshooting
528
+
529
+ ### `Unsupported ambiguous intrinsic TypeDoc type "unknown"`
530
+
531
+ The catalog needs a concrete schema. Replace `unknown` or `any` with a
532
+ specific type:
533
+
534
+ ```tsx
535
+ // Fails.
536
+ payload: unknown;
537
+
538
+ // Works.
539
+ payload: {
540
+ id: string;
541
+ count: number;
542
+ }
543
+ ```
544
+
545
+ ### `Unsupported nullable union`
546
+
547
+ Nullable unions are not accepted:
548
+
549
+ ```tsx
550
+ // Fails.
551
+ label: string | null;
552
+ ```
553
+
554
+ Make the property optional if it can be omitted:
555
+
556
+ ```tsx
557
+ label?: string;
558
+ ```
559
+
560
+ Or model the state explicitly:
561
+
562
+ ```tsx
563
+ label: string | { path: string };
564
+ ```
565
+
566
+ ### `Unsupported TypeDoc reference`
567
+
568
+ The extractor only understands a small set of references:
569
+ `Array<T>`, `ReadonlyArray<T>`, and `Record<string, T>`. Inline object
570
+ shapes in the catalog-facing interface instead of importing aliases.
571
+
572
+ ### My output directory is empty
573
+
574
+ Check these points:
575
+
576
+ - The scanned files contain an `interface`, not only a `type`.
577
+ - The interface has `@a2uiCatalog`.
578
+ - The path passed to `--catalog-dir` or `--source` exists.
579
+ - The files are not `.d.ts`.
580
+ - TypeDoc can parse the files with your `tsconfig`.
581
+
582
+ ### The generated schema does not include inherited props
583
+
584
+ Inherited members are skipped. This is intentional because runtime-only
585
+ props such as renderer context should not be part of the agent-facing
586
+ catalog. Put every catalog-facing prop directly on the marked interface.
587
+
588
+ ### Should I hand-write JSON Schema instead?
589
+
590
+ No. Keep the contract in TypeScript and comments. Hand-written schema tends
591
+ to drift away from component props, while this package makes the catalog a
592
+ repeatable build artifact.
593
+
594
+ ### Does this replace TypeScript type checking?
595
+
596
+ No. TypeDoc conversion is used to read reflection data, not to validate
597
+ your full application. Continue running your normal TypeScript, lint, and
598
+ test commands.
599
+
600
+ ## References
601
+
602
+ - [A2UI Catalogs](https://a2ui.org/concepts/catalogs/)
603
+ - [A2UI v0.9 protocol](https://a2ui.org/specification/v0.9-a2ui/)
604
+ - [TypeDoc custom tags](https://typedoc.org/documents/Tags.html)
605
+ - [TypeDoc JSON output](https://typedoc.org/documents/Options.Output.html)
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ // Copyright 2026 The Lynx Authors. All rights reserved.
3
+ // Licensed under the Apache License Version 2.0 that can be found in the
4
+ // LICENSE file in the root directory of this source tree.
5
+ // eslint-disable-next-line import/no-unresolved -- Generated by the package build.
6
+ import '../dist/cli.js';
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ interface CliOptions {
3
+ catalogDirs: string[];
4
+ help: boolean;
5
+ outDir: string;
6
+ sourceInputs: string[];
7
+ typedocJson?: string;
8
+ version: boolean;
9
+ }
10
+ export declare function parseCliArgs(args: string[]): CliOptions;
11
+ export declare function runCli(args: string[], cwd?: string): Promise<number>;
12
+ export {};