@tai42/studio-sdk 0.2.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 (422) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +15 -0
  3. package/README.md +318 -0
  4. package/SECURITY.md +51 -0
  5. package/dist/components/badge.d.ts +13 -0
  6. package/dist/components/badge.d.ts.map +1 -0
  7. package/dist/components/badge.js +14 -0
  8. package/dist/components/badge.js.map +1 -0
  9. package/dist/components/checkbox.d.ts +24 -0
  10. package/dist/components/checkbox.d.ts.map +1 -0
  11. package/dist/components/checkbox.js +31 -0
  12. package/dist/components/checkbox.js.map +1 -0
  13. package/dist/components/code-block.d.ts +7 -0
  14. package/dist/components/code-block.d.ts.map +1 -0
  15. package/dist/components/code-block.js +23 -0
  16. package/dist/components/code-block.js.map +1 -0
  17. package/dist/components/completion-input.d.ts +31 -0
  18. package/dist/components/completion-input.d.ts.map +1 -0
  19. package/dist/components/completion-input.js +61 -0
  20. package/dist/components/completion-input.js.map +1 -0
  21. package/dist/components/components.css +2212 -0
  22. package/dist/components/confirm-dialog.d.ts +40 -0
  23. package/dist/components/confirm-dialog.d.ts.map +1 -0
  24. package/dist/components/confirm-dialog.js +11 -0
  25. package/dist/components/confirm-dialog.js.map +1 -0
  26. package/dist/components/control-styles.d.ts +12 -0
  27. package/dist/components/control-styles.d.ts.map +1 -0
  28. package/dist/components/control-styles.js +14 -0
  29. package/dist/components/control-styles.js.map +1 -0
  30. package/dist/components/copy-field.d.ts +8 -0
  31. package/dist/components/copy-field.d.ts.map +1 -0
  32. package/dist/components/copy-field.js +106 -0
  33. package/dist/components/copy-field.js.map +1 -0
  34. package/dist/components/dialog.d.ts +21 -0
  35. package/dist/components/dialog.d.ts.map +1 -0
  36. package/dist/components/dialog.js +25 -0
  37. package/dist/components/dialog.js.map +1 -0
  38. package/dist/components/drawer.d.ts +22 -0
  39. package/dist/components/drawer.d.ts.map +1 -0
  40. package/dist/components/drawer.js +32 -0
  41. package/dist/components/drawer.js.map +1 -0
  42. package/dist/components/error-boundary.d.ts +33 -0
  43. package/dist/components/error-boundary.d.ts.map +1 -0
  44. package/dist/components/error-boundary.js +36 -0
  45. package/dist/components/error-boundary.js.map +1 -0
  46. package/dist/components/extension-combo-builder.d.ts +70 -0
  47. package/dist/components/extension-combo-builder.d.ts.map +1 -0
  48. package/dist/components/extension-combo-builder.js +154 -0
  49. package/dist/components/extension-combo-builder.js.map +1 -0
  50. package/dist/components/extension-grouping.d.ts +65 -0
  51. package/dist/components/extension-grouping.d.ts.map +1 -0
  52. package/dist/components/extension-grouping.js +78 -0
  53. package/dist/components/extension-grouping.js.map +1 -0
  54. package/dist/components/extension-picker.d.ts +35 -0
  55. package/dist/components/extension-picker.d.ts.map +1 -0
  56. package/dist/components/extension-picker.js +31 -0
  57. package/dist/components/extension-picker.js.map +1 -0
  58. package/dist/components/external-link.d.ts +19 -0
  59. package/dist/components/external-link.d.ts.map +1 -0
  60. package/dist/components/external-link.js +12 -0
  61. package/dist/components/external-link.js.map +1 -0
  62. package/dist/components/field.d.ts +64 -0
  63. package/dist/components/field.d.ts.map +1 -0
  64. package/dist/components/field.js +56 -0
  65. package/dist/components/field.js.map +1 -0
  66. package/dist/components/fleet-report.d.ts +39 -0
  67. package/dist/components/fleet-report.d.ts.map +1 -0
  68. package/dist/components/fleet-report.js +50 -0
  69. package/dist/components/fleet-report.js.map +1 -0
  70. package/dist/components/fonts.css +22 -0
  71. package/dist/components/icons.d.ts +142 -0
  72. package/dist/components/icons.d.ts.map +1 -0
  73. package/dist/components/icons.js +139 -0
  74. package/dist/components/icons.js.map +1 -0
  75. package/dist/components/inputs.d.ts +52 -0
  76. package/dist/components/inputs.d.ts.map +1 -0
  77. package/dist/components/inputs.js +35 -0
  78. package/dist/components/inputs.js.map +1 -0
  79. package/dist/components/json-diff.d.ts +40 -0
  80. package/dist/components/json-diff.d.ts.map +1 -0
  81. package/dist/components/json-diff.js +119 -0
  82. package/dist/components/json-diff.js.map +1 -0
  83. package/dist/components/json-tree.d.ts +8 -0
  84. package/dist/components/json-tree.d.ts.map +1 -0
  85. package/dist/components/json-tree.js +70 -0
  86. package/dist/components/json-tree.js.map +1 -0
  87. package/dist/components/modal-focus.d.ts +15 -0
  88. package/dist/components/modal-focus.d.ts.map +1 -0
  89. package/dist/components/modal-focus.js +136 -0
  90. package/dist/components/modal-focus.js.map +1 -0
  91. package/dist/components/page-header.d.ts +56 -0
  92. package/dist/components/page-header.d.ts.map +1 -0
  93. package/dist/components/page-header.js +24 -0
  94. package/dist/components/page-header.js.map +1 -0
  95. package/dist/components/primitives.d.ts +186 -0
  96. package/dist/components/primitives.d.ts.map +1 -0
  97. package/dist/components/primitives.js +204 -0
  98. package/dist/components/primitives.js.map +1 -0
  99. package/dist/components/progress-bar.d.ts +29 -0
  100. package/dist/components/progress-bar.d.ts.map +1 -0
  101. package/dist/components/progress-bar.js +48 -0
  102. package/dist/components/progress-bar.js.map +1 -0
  103. package/dist/components/radio-group.d.ts +37 -0
  104. package/dist/components/radio-group.d.ts.map +1 -0
  105. package/dist/components/radio-group.js +56 -0
  106. package/dist/components/radio-group.js.map +1 -0
  107. package/dist/components/reveal-input.d.ts +13 -0
  108. package/dist/components/reveal-input.d.ts.map +1 -0
  109. package/dist/components/reveal-input.js +31 -0
  110. package/dist/components/reveal-input.js.map +1 -0
  111. package/dist/components/scroll-region.d.ts +85 -0
  112. package/dist/components/scroll-region.d.ts.map +1 -0
  113. package/dist/components/scroll-region.js +574 -0
  114. package/dist/components/scroll-region.js.map +1 -0
  115. package/dist/components/select.d.ts +53 -0
  116. package/dist/components/select.d.ts.map +1 -0
  117. package/dist/components/select.js +33 -0
  118. package/dist/components/select.js.map +1 -0
  119. package/dist/components/table.d.ts +59 -0
  120. package/dist/components/table.d.ts.map +1 -0
  121. package/dist/components/table.js +20 -0
  122. package/dist/components/table.js.map +1 -0
  123. package/dist/components/tabs.d.ts +15 -0
  124. package/dist/components/tabs.d.ts.map +1 -0
  125. package/dist/components/tabs.js +13 -0
  126. package/dist/components/tabs.js.map +1 -0
  127. package/dist/components/tags.d.ts +46 -0
  128. package/dist/components/tags.d.ts.map +1 -0
  129. package/dist/components/tags.js +68 -0
  130. package/dist/components/tags.js.map +1 -0
  131. package/dist/components/tokens.css +392 -0
  132. package/dist/components/tokens.d.ts +15 -0
  133. package/dist/components/tokens.d.ts.map +1 -0
  134. package/dist/components/tokens.js +101 -0
  135. package/dist/components/tokens.js.map +1 -0
  136. package/dist/components/tool-picker.d.ts +24 -0
  137. package/dist/components/tool-picker.d.ts.map +1 -0
  138. package/dist/components/tool-picker.js +97 -0
  139. package/dist/components/tool-picker.js.map +1 -0
  140. package/dist/components/tooltip.d.ts +17 -0
  141. package/dist/components/tooltip.d.ts.map +1 -0
  142. package/dist/components/tooltip.js +18 -0
  143. package/dist/components/tooltip.js.map +1 -0
  144. package/dist/components/version-history-panel.d.ts +71 -0
  145. package/dist/components/version-history-panel.d.ts.map +1 -0
  146. package/dist/components/version-history-panel.js +148 -0
  147. package/dist/components/version-history-panel.js.map +1 -0
  148. package/dist/download.d.ts +7 -0
  149. package/dist/download.d.ts.map +1 -0
  150. package/dist/download.js +18 -0
  151. package/dist/download.js.map +1 -0
  152. package/dist/element-slot.d.ts +4 -0
  153. package/dist/element-slot.d.ts.map +1 -0
  154. package/dist/element-slot.js +20 -0
  155. package/dist/element-slot.js.map +1 -0
  156. package/dist/elicitation/ElicitationForm.d.ts +34 -0
  157. package/dist/elicitation/ElicitationForm.d.ts.map +1 -0
  158. package/dist/elicitation/ElicitationForm.js +24 -0
  159. package/dist/elicitation/ElicitationForm.js.map +1 -0
  160. package/dist/errors.d.ts +9 -0
  161. package/dist/errors.d.ts.map +1 -0
  162. package/dist/errors.js +15 -0
  163. package/dist/errors.js.map +1 -0
  164. package/dist/extension-combos.d.ts +13 -0
  165. package/dist/extension-combos.d.ts.map +1 -0
  166. package/dist/extension-combos.js +9 -0
  167. package/dist/extension-combos.js.map +1 -0
  168. package/dist/hooks/useApi.d.ts +1222 -0
  169. package/dist/hooks/useApi.d.ts.map +1 -0
  170. package/dist/hooks/useApi.js +22 -0
  171. package/dist/hooks/useApi.js.map +1 -0
  172. package/dist/hooks/useAuth.d.ts +13 -0
  173. package/dist/hooks/useAuth.d.ts.map +1 -0
  174. package/dist/hooks/useAuth.js +53 -0
  175. package/dist/hooks/useAuth.js.map +1 -0
  176. package/dist/hooks/useBreakpoint.d.ts +10 -0
  177. package/dist/hooks/useBreakpoint.d.ts.map +1 -0
  178. package/dist/hooks/useBreakpoint.js +66 -0
  179. package/dist/hooks/useBreakpoint.js.map +1 -0
  180. package/dist/hooks/useCapabilities.d.ts +88 -0
  181. package/dist/hooks/useCapabilities.d.ts.map +1 -0
  182. package/dist/hooks/useCapabilities.js +203 -0
  183. package/dist/hooks/useCapabilities.js.map +1 -0
  184. package/dist/hooks/useSse.d.ts +13 -0
  185. package/dist/hooks/useSse.d.ts.map +1 -0
  186. package/dist/hooks/useSse.js +298 -0
  187. package/dist/hooks/useSse.js.map +1 -0
  188. package/dist/hooks/useTheme.d.ts +20 -0
  189. package/dist/hooks/useTheme.d.ts.map +1 -0
  190. package/dist/hooks/useTheme.js +97 -0
  191. package/dist/hooks/useTheme.js.map +1 -0
  192. package/dist/hooks/useUnauthorized.d.ts +3 -0
  193. package/dist/hooks/useUnauthorized.d.ts.map +1 -0
  194. package/dist/hooks/useUnauthorized.js +18 -0
  195. package/dist/hooks/useUnauthorized.js.map +1 -0
  196. package/dist/host.d.ts +11 -0
  197. package/dist/host.d.ts.map +1 -0
  198. package/dist/host.js +10 -0
  199. package/dist/host.js.map +1 -0
  200. package/dist/index.d.ts +118 -0
  201. package/dist/index.d.ts.map +1 -0
  202. package/dist/index.js +91 -0
  203. package/dist/index.js.map +1 -0
  204. package/dist/navigation/context.d.ts +25 -0
  205. package/dist/navigation/context.d.ts.map +1 -0
  206. package/dist/navigation/context.js +45 -0
  207. package/dist/navigation/context.js.map +1 -0
  208. package/dist/navigation/index.d.ts +4 -0
  209. package/dist/navigation/index.d.ts.map +1 -0
  210. package/dist/navigation/index.js +2 -0
  211. package/dist/navigation/index.js.map +1 -0
  212. package/dist/navigation/types.d.ts +97 -0
  213. package/dist/navigation/types.d.ts.map +1 -0
  214. package/dist/navigation/types.js +16 -0
  215. package/dist/navigation/types.js.map +1 -0
  216. package/dist/plugin/host-state.d.ts +45 -0
  217. package/dist/plugin/host-state.d.ts.map +1 -0
  218. package/dist/plugin/host-state.js +62 -0
  219. package/dist/plugin/host-state.js.map +1 -0
  220. package/dist/plugin/registry.d.ts +35 -0
  221. package/dist/plugin/registry.d.ts.map +1 -0
  222. package/dist/plugin/registry.js +129 -0
  223. package/dist/plugin/registry.js.map +1 -0
  224. package/dist/plugin/types.d.ts +165 -0
  225. package/dist/plugin/types.d.ts.map +1 -0
  226. package/dist/plugin/types.js +2 -0
  227. package/dist/plugin/types.js.map +1 -0
  228. package/dist/plugin/version.d.ts +34 -0
  229. package/dist/plugin/version.d.ts.map +1 -0
  230. package/dist/plugin/version.js +37 -0
  231. package/dist/plugin/version.js.map +1 -0
  232. package/dist/query-keys.d.ts +31 -0
  233. package/dist/query-keys.d.ts.map +1 -0
  234. package/dist/query-keys.js +31 -0
  235. package/dist/query-keys.js.map +1 -0
  236. package/dist/schema-editor/SchemaEditor.d.ts +43 -0
  237. package/dist/schema-editor/SchemaEditor.d.ts.map +1 -0
  238. package/dist/schema-editor/SchemaEditor.js +106 -0
  239. package/dist/schema-editor/SchemaEditor.js.map +1 -0
  240. package/dist/schema-editor/index.d.ts +10 -0
  241. package/dist/schema-editor/index.d.ts.map +1 -0
  242. package/dist/schema-editor/index.js +8 -0
  243. package/dist/schema-editor/index.js.map +1 -0
  244. package/dist/schema-editor/lint.d.ts +37 -0
  245. package/dist/schema-editor/lint.d.ts.map +1 -0
  246. package/dist/schema-editor/lint.js +49 -0
  247. package/dist/schema-editor/lint.js.map +1 -0
  248. package/dist/schema-form/SchemaForm.d.ts +70 -0
  249. package/dist/schema-form/SchemaForm.d.ts.map +1 -0
  250. package/dist/schema-form/SchemaForm.js +13 -0
  251. package/dist/schema-form/SchemaForm.js.map +1 -0
  252. package/dist/schema-form/array-field.d.ts +20 -0
  253. package/dist/schema-form/array-field.d.ts.map +1 -0
  254. package/dist/schema-form/array-field.js +39 -0
  255. package/dist/schema-form/array-field.js.map +1 -0
  256. package/dist/schema-form/classify.d.ts +87 -0
  257. package/dist/schema-form/classify.d.ts.map +1 -0
  258. package/dist/schema-form/classify.js +199 -0
  259. package/dist/schema-form/classify.js.map +1 -0
  260. package/dist/schema-form/context.d.ts +4 -0
  261. package/dist/schema-form/context.d.ts.map +1 -0
  262. package/dist/schema-form/context.js +14 -0
  263. package/dist/schema-form/context.js.map +1 -0
  264. package/dist/schema-form/default-value.d.ts +8 -0
  265. package/dist/schema-form/default-value.d.ts.map +1 -0
  266. package/dist/schema-form/default-value.js +64 -0
  267. package/dist/schema-form/default-value.js.map +1 -0
  268. package/dist/schema-form/enum-field.d.ts +19 -0
  269. package/dist/schema-form/enum-field.d.ts.map +1 -0
  270. package/dist/schema-form/enum-field.js +26 -0
  271. package/dist/schema-form/enum-field.js.map +1 -0
  272. package/dist/schema-form/field-group.d.ts +9 -0
  273. package/dist/schema-form/field-group.d.ts.map +1 -0
  274. package/dist/schema-form/field-group.js +32 -0
  275. package/dist/schema-form/field-group.js.map +1 -0
  276. package/dist/schema-form/field-node.d.ts +24 -0
  277. package/dist/schema-form/field-node.d.ts.map +1 -0
  278. package/dist/schema-form/field-node.js +51 -0
  279. package/dist/schema-form/field-node.js.map +1 -0
  280. package/dist/schema-form/index.d.ts +13 -0
  281. package/dist/schema-form/index.d.ts.map +1 -0
  282. package/dist/schema-form/index.js +11 -0
  283. package/dist/schema-form/index.js.map +1 -0
  284. package/dist/schema-form/media-field.d.ts +24 -0
  285. package/dist/schema-form/media-field.d.ts.map +1 -0
  286. package/dist/schema-form/media-field.js +169 -0
  287. package/dist/schema-form/media-field.js.map +1 -0
  288. package/dist/schema-form/media.d.ts +40 -0
  289. package/dist/schema-form/media.d.ts.map +1 -0
  290. package/dist/schema-form/media.js +65 -0
  291. package/dist/schema-form/media.js.map +1 -0
  292. package/dist/schema-form/object-fields.d.ts +20 -0
  293. package/dist/schema-form/object-fields.d.ts.map +1 -0
  294. package/dist/schema-form/object-fields.js +24 -0
  295. package/dist/schema-form/object-fields.js.map +1 -0
  296. package/dist/schema-form/resolve.d.ts +41 -0
  297. package/dist/schema-form/resolve.d.ts.map +1 -0
  298. package/dist/schema-form/resolve.js +102 -0
  299. package/dist/schema-form/resolve.js.map +1 -0
  300. package/dist/schema-form/string-field.d.ts +20 -0
  301. package/dist/schema-form/string-field.d.ts.map +1 -0
  302. package/dist/schema-form/string-field.js +68 -0
  303. package/dist/schema-form/string-field.js.map +1 -0
  304. package/dist/schema-form/styles.d.ts +18 -0
  305. package/dist/schema-form/styles.d.ts.map +1 -0
  306. package/dist/schema-form/styles.js +18 -0
  307. package/dist/schema-form/styles.js.map +1 -0
  308. package/dist/schema-form/types.d.ts +67 -0
  309. package/dist/schema-form/types.d.ts.map +1 -0
  310. package/dist/schema-form/types.js +10 -0
  311. package/dist/schema-form/types.js.map +1 -0
  312. package/dist/schema-form/union-field.d.ts +24 -0
  313. package/dist/schema-form/union-field.d.ts.map +1 -0
  314. package/dist/schema-form/union-field.js +55 -0
  315. package/dist/schema-form/union-field.js.map +1 -0
  316. package/dist/schema-form/union.d.ts +4 -0
  317. package/dist/schema-form/union.d.ts.map +1 -0
  318. package/dist/schema-form/union.js +68 -0
  319. package/dist/schema-form/union.js.map +1 -0
  320. package/dist/schema-form/unsupported-notice.d.ts +18 -0
  321. package/dist/schema-form/unsupported-notice.d.ts.map +1 -0
  322. package/dist/schema-form/unsupported-notice.js +8 -0
  323. package/dist/schema-form/unsupported-notice.js.map +1 -0
  324. package/dist/schema-form/validate.d.ts +18 -0
  325. package/dist/schema-form/validate.d.ts.map +1 -0
  326. package/dist/schema-form/validate.js +162 -0
  327. package/dist/schema-form/validate.js.map +1 -0
  328. package/dist/structured-output/StructuredOutput.d.ts +27 -0
  329. package/dist/structured-output/StructuredOutput.d.ts.map +1 -0
  330. package/dist/structured-output/StructuredOutput.js +41 -0
  331. package/dist/structured-output/StructuredOutput.js.map +1 -0
  332. package/dist/testing.d.ts +80 -0
  333. package/dist/testing.d.ts.map +1 -0
  334. package/dist/testing.js +207 -0
  335. package/dist/testing.js.map +1 -0
  336. package/package.json +101 -0
  337. package/src/components/badge.tsx +31 -0
  338. package/src/components/checkbox.tsx +93 -0
  339. package/src/components/code-block.tsx +37 -0
  340. package/src/components/completion-input.tsx +137 -0
  341. package/src/components/components.css +2212 -0
  342. package/src/components/confirm-dialog.tsx +77 -0
  343. package/src/components/control-styles.ts +14 -0
  344. package/src/components/copy-field.tsx +178 -0
  345. package/src/components/dialog.tsx +76 -0
  346. package/src/components/drawer.tsx +83 -0
  347. package/src/components/error-boundary.tsx +56 -0
  348. package/src/components/extension-combo-builder.tsx +305 -0
  349. package/src/components/extension-grouping.ts +116 -0
  350. package/src/components/extension-picker.tsx +97 -0
  351. package/src/components/external-link.tsx +40 -0
  352. package/src/components/field.tsx +169 -0
  353. package/src/components/fleet-report.tsx +136 -0
  354. package/src/components/fonts.css +22 -0
  355. package/src/components/icons.tsx +504 -0
  356. package/src/components/inputs.tsx +125 -0
  357. package/src/components/json-diff.tsx +192 -0
  358. package/src/components/json-tree.tsx +129 -0
  359. package/src/components/modal-focus.ts +150 -0
  360. package/src/components/page-header.tsx +107 -0
  361. package/src/components/primitives.tsx +489 -0
  362. package/src/components/progress-bar.tsx +100 -0
  363. package/src/components/radio-group.tsx +160 -0
  364. package/src/components/reveal-input.tsx +87 -0
  365. package/src/components/scroll-region.tsx +703 -0
  366. package/src/components/select.tsx +149 -0
  367. package/src/components/table.tsx +94 -0
  368. package/src/components/tabs.tsx +51 -0
  369. package/src/components/tags.tsx +137 -0
  370. package/src/components/tokens.css +392 -0
  371. package/src/components/tokens.ts +102 -0
  372. package/src/components/tool-picker.tsx +175 -0
  373. package/src/components/tooltip.tsx +46 -0
  374. package/src/components/version-history-panel.tsx +407 -0
  375. package/src/css.d.ts +2 -0
  376. package/src/download.ts +17 -0
  377. package/src/element-slot.ts +22 -0
  378. package/src/elicitation/ElicitationForm.tsx +87 -0
  379. package/src/errors.ts +12 -0
  380. package/src/extension-combos.ts +18 -0
  381. package/src/hooks/useApi.ts +27 -0
  382. package/src/hooks/useAuth.ts +67 -0
  383. package/src/hooks/useBreakpoint.ts +78 -0
  384. package/src/hooks/useCapabilities.ts +242 -0
  385. package/src/hooks/useSse.ts +314 -0
  386. package/src/hooks/useTheme.ts +133 -0
  387. package/src/hooks/useUnauthorized.ts +20 -0
  388. package/src/host.ts +15 -0
  389. package/src/index.ts +267 -0
  390. package/src/navigation/context.tsx +90 -0
  391. package/src/navigation/index.ts +9 -0
  392. package/src/navigation/types.ts +90 -0
  393. package/src/plugin/host-state.ts +93 -0
  394. package/src/plugin/registry.ts +174 -0
  395. package/src/plugin/types.ts +178 -0
  396. package/src/plugin/version.ts +44 -0
  397. package/src/query-keys.ts +34 -0
  398. package/src/schema-editor/SchemaEditor.tsx +186 -0
  399. package/src/schema-editor/index.ts +9 -0
  400. package/src/schema-editor/lint.ts +70 -0
  401. package/src/schema-form/SchemaForm.tsx +107 -0
  402. package/src/schema-form/array-field.tsx +110 -0
  403. package/src/schema-form/classify.ts +302 -0
  404. package/src/schema-form/context.ts +17 -0
  405. package/src/schema-form/default-value.ts +65 -0
  406. package/src/schema-form/enum-field.tsx +65 -0
  407. package/src/schema-form/field-group.tsx +71 -0
  408. package/src/schema-form/field-node.tsx +161 -0
  409. package/src/schema-form/index.ts +12 -0
  410. package/src/schema-form/media-field.tsx +281 -0
  411. package/src/schema-form/media.ts +69 -0
  412. package/src/schema-form/object-fields.tsx +74 -0
  413. package/src/schema-form/resolve.ts +114 -0
  414. package/src/schema-form/string-field.tsx +161 -0
  415. package/src/schema-form/styles.ts +20 -0
  416. package/src/schema-form/types.ts +71 -0
  417. package/src/schema-form/union-field.tsx +122 -0
  418. package/src/schema-form/union.ts +78 -0
  419. package/src/schema-form/unsupported-notice.tsx +39 -0
  420. package/src/schema-form/validate.ts +183 -0
  421. package/src/structured-output/StructuredOutput.tsx +81 -0
  422. package/src/testing.ts +235 -0
@@ -0,0 +1,77 @@
1
+ /**
2
+ * `ConfirmDialog` — a modal that asks the operator to confirm an action and then
3
+ * runs it. It owns the scaffolding every confirm shares: a Cancel button, the
4
+ * confirm button (showing a pending Spinner while the action runs and disabled
5
+ * meanwhile), and a loud `ErrorState` when the action fails. The caller supplies
6
+ * the prompt as `children` and drives the action through `onConfirm` /
7
+ * `isPending` / `error`.
8
+ *
9
+ * Mount it only while the confirmation is active; any close gesture — Cancel,
10
+ * Escape, the overlay — calls `onClose`. The confirm button is destructive
11
+ * (`danger`) by default; pass `confirmVariant` for a non-destructive confirm.
12
+ *
13
+ * The footer is the design system's `tai-dialog-actions` row, so every confirm
14
+ * across Studio lands its buttons in the same place.
15
+ */
16
+ import type { ReactNode } from 'react';
17
+
18
+ import { Dialog } from './dialog';
19
+ import { Button, ErrorState, Spinner } from './primitives';
20
+ import { errorMessage } from '../errors';
21
+
22
+ export interface ConfirmDialogProps {
23
+ readonly title: string;
24
+ /** The confirm button's resting label (e.g. `Delete scope`). */
25
+ readonly confirmLabel: string;
26
+ /** The Spinner's accessible label while the action runs (e.g. `Deleting`). */
27
+ readonly pendingLabel: string;
28
+ readonly onConfirm: () => void;
29
+ readonly onClose: () => void;
30
+ readonly isPending: boolean;
31
+ /**
32
+ * The failed action's error, rendered loudly; omit/`null` while there is none.
33
+ *
34
+ * A thrown `Error` or the message on its own — `Field`'s `error` is a plain
35
+ * string, and the two props sit side by side on a form, so this one accepts
36
+ * that spelling too rather than making one surface's `error` unassignable to
37
+ * the other's.
38
+ */
39
+ readonly error?: Error | string | null;
40
+ readonly confirmVariant?: 'primary' | 'danger';
41
+ /** The prompt body — what the operator is confirming. */
42
+ readonly children: ReactNode;
43
+ }
44
+
45
+ export function ConfirmDialog({
46
+ title,
47
+ confirmLabel,
48
+ pendingLabel,
49
+ onConfirm,
50
+ onClose,
51
+ isPending,
52
+ error,
53
+ confirmVariant = 'danger',
54
+ children,
55
+ }: ConfirmDialogProps): ReactNode {
56
+ return (
57
+ <Dialog
58
+ title={title}
59
+ open
60
+ onOpenChange={(next) => {
61
+ if (!next) onClose();
62
+ }}
63
+ >
64
+ {children}
65
+ {error != null ? <ErrorState message={errorMessage(error)} /> : null}
66
+ <div className="tai-dialog-actions">
67
+ <Button type="button" onClick={onClose}>
68
+ Cancel
69
+ </Button>
70
+ <Button type="button" variant={confirmVariant} disabled={isPending} onClick={onConfirm}>
71
+ {isPending ? <Spinner label={pendingLabel} /> : null}
72
+ {confirmLabel}
73
+ </Button>
74
+ </div>
75
+ </Dialog>
76
+ );
77
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The design-system class each form control wears. The 36 px geometry, the
3
+ * boundary, the placeholder, and the hover/disabled/invalid states all live in
4
+ * `components.css` under these names — this module is the single place a
5
+ * control names the class, so no control re-derives that geometry inline.
6
+ */
7
+ export const INPUT_CLASS = 'tai-input';
8
+ export const TEXTAREA_CLASS = 'tai-textarea';
9
+ export const SELECT_TRIGGER_CLASS = 'tai-select-trigger';
10
+
11
+ /** A control's class plus the caller's, which sorts last so it can override. */
12
+ export function controlClassName(base: string, className: string | undefined): string {
13
+ return className === undefined ? base : `${base} ${className}`;
14
+ }
@@ -0,0 +1,178 @@
1
+ /**
2
+ * `CopyField` — a show-once box for a freshly-minted secret (an API key or a
3
+ * minted backup key). It renders the value in a monospace, break-all,
4
+ * select-all box beside a copy button that writes the value to the clipboard and
5
+ * shows a transient "Copied" affordance. It is PRESENTATIONAL: the caller owns
6
+ * the value; this component fetches nothing and never re-reads the secret.
7
+ *
8
+ * The button holds BOTH states stacked in one grid cell, so the widest of them
9
+ * sets the width once and the flip never reflows the row. Only the active state
10
+ * is exposed to assistive tech, and that state's own words are the button's
11
+ * accessible name: a constant `aria-label` would leave a button reading "Copied"
12
+ * named "Copy", which fails WCAG 2.5.3 (Label in Name) and leaves a voice-control
13
+ * user naming a control they cannot see. The polite live region beside the button
14
+ * is what actually announces the flip.
15
+ *
16
+ * A clipboard write can FAIL — a permissions policy blocks it, or the page is
17
+ * not in a secure context, where `navigator.clipboard` does not exist at all.
18
+ * Either way the value is a secret shown once, so the failure is rendered as a
19
+ * visible `role="alert"` telling the reader to copy it by hand: throwing it at
20
+ * the console would leave the button looking inert and the secret unrecoverable.
21
+ *
22
+ * SAFETY: the value and caption render as TEXT (React escapes them) — never an
23
+ * HTML sink. The value is never logged, and neither is a failure — the alert
24
+ * names the reason, never the value. Pinned by a test.
25
+ */
26
+ import { useEffect, useRef, useState } from 'react';
27
+ import type { CSSProperties } from 'react';
28
+
29
+ import { CheckIcon, CopyIcon, XCircleIcon } from './icons';
30
+
31
+ export interface CopyFieldProps {
32
+ readonly value: string;
33
+ readonly caption?: string;
34
+ readonly idPrefix?: string;
35
+ readonly label?: string;
36
+ }
37
+
38
+ const COPIED_RESET_MS = 2000;
39
+
40
+ /** The button's two faces. Whichever is exposed is also its accessible name. */
41
+ const COPY_LABEL = 'Copy';
42
+ const COPIED_LABEL = 'Copied';
43
+
44
+ /** Announced once, and worded so it is never mistaken for the visible label. */
45
+ const COPIED_ANNOUNCEMENT = 'Copied to clipboard';
46
+
47
+ /**
48
+ * `lib.dom` declares `navigator.clipboard` as always present, but the platform
49
+ * exposes it only in a SECURE CONTEXT — over plain http it is not there at all.
50
+ * Reading the navigator through this shape admits the absence the DOM types deny,
51
+ * so the guard below is a real check rather than a cast around one.
52
+ */
53
+ interface MaybeClipboard {
54
+ readonly clipboard?: Clipboard;
55
+ }
56
+
57
+ /** The clipboard this browser actually offers, or `undefined` when it offers none. */
58
+ function clipboardOf(host: MaybeClipboard): Clipboard | undefined {
59
+ return host.clipboard;
60
+ }
61
+
62
+ /** Shown when the browser offers no clipboard at all (any non-secure context). */
63
+ const NO_CLIPBOARD =
64
+ 'This browser will not write to the clipboard here. Select the value above and copy it.';
65
+
66
+ /** Shown when the write is offered and refused. */
67
+ function writeFailed(reason: unknown): string {
68
+ const detail = reason instanceof Error ? reason.message : String(reason);
69
+ return `Copy failed: ${detail}. Select the value above and copy it.`;
70
+ }
71
+
72
+ const valueStyle: CSSProperties = {
73
+ flex: 1,
74
+ padding: 'var(--tai-space-2) var(--tai-space-3)',
75
+ wordBreak: 'break-all',
76
+ userSelect: 'all',
77
+ };
78
+
79
+ /** Both states share one grid cell, so the button is as wide as the wider one. */
80
+ const statesStyle: CSSProperties = {
81
+ display: 'grid',
82
+ alignItems: 'center',
83
+ justifyItems: 'center',
84
+ };
85
+
86
+ const stateStyle: CSSProperties = {
87
+ gridArea: '1 / 1',
88
+ display: 'inline-flex',
89
+ alignItems: 'center',
90
+ gap: 'var(--tai-space-2)',
91
+ };
92
+
93
+ export function CopyField({ value, caption, idPrefix = 'copy-field', label }: CopyFieldProps) {
94
+ const [copied, setCopied] = useState(false);
95
+ const [copyError, setCopyError] = useState<string | undefined>(undefined);
96
+ const resetTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
97
+ // The clipboard write is async, so a copy can still be in flight when the
98
+ // component goes away — the caller's dialog closes on the same click. Clearing
99
+ // the timer alone would not cover that: at unmount there is no timer yet, and
100
+ // the resolution that follows would start one nothing is left to clear. This
101
+ // flag is what the resolution checks before it touches state at all.
102
+ const mounted = useRef(true);
103
+
104
+ useEffect(() => {
105
+ mounted.current = true;
106
+ return () => {
107
+ mounted.current = false;
108
+ if (resetTimer.current !== null) clearTimeout(resetTimer.current);
109
+ };
110
+ }, []);
111
+
112
+ const handleCopy = (): void => {
113
+ const clipboard = clipboardOf(navigator);
114
+ if (clipboard === undefined) {
115
+ setCopyError(NO_CLIPBOARD);
116
+ return;
117
+ }
118
+ setCopyError(undefined);
119
+ void clipboard.writeText(value).then(
120
+ () => {
121
+ if (!mounted.current) return;
122
+ setCopied(true);
123
+ if (resetTimer.current !== null) clearTimeout(resetTimer.current);
124
+ resetTimer.current = setTimeout(() => {
125
+ setCopied(false);
126
+ }, COPIED_RESET_MS);
127
+ },
128
+ (error: unknown) => {
129
+ if (!mounted.current) return;
130
+ setCopyError(writeFailed(error));
131
+ },
132
+ );
133
+ };
134
+
135
+ return (
136
+ <div data-testid={idPrefix} className="tai-stack tai-stack-2">
137
+ {label !== undefined ? <span className="tai-field-label">{label}</span> : null}
138
+ <div className="tai-row">
139
+ <code className="tai-code" style={valueStyle}>
140
+ {value}
141
+ </code>
142
+ <button
143
+ type="button"
144
+ className="tai-btn tai-btn-secondary"
145
+ data-testid={`${idPrefix}-copy`}
146
+ onClick={handleCopy}
147
+ >
148
+ <span style={statesStyle}>
149
+ <span
150
+ aria-hidden={copied}
151
+ style={{ ...stateStyle, visibility: copied ? 'hidden' : 'visible' }}
152
+ >
153
+ <CopyIcon />
154
+ {COPY_LABEL}
155
+ </span>
156
+ <span
157
+ aria-hidden={!copied}
158
+ style={{ ...stateStyle, visibility: copied ? 'visible' : 'hidden' }}
159
+ >
160
+ <CheckIcon />
161
+ {COPIED_LABEL}
162
+ </span>
163
+ </span>
164
+ </button>
165
+ <span aria-live="polite" className="tai-visually-hidden">
166
+ {copied ? COPIED_ANNOUNCEMENT : ''}
167
+ </span>
168
+ </div>
169
+ {copyError !== undefined ? (
170
+ <span role="alert" className="tai-field-error">
171
+ <XCircleIcon />
172
+ {copyError}
173
+ </span>
174
+ ) : null}
175
+ {caption !== undefined ? <span className="tai-field-hint">{caption}</span> : null}
176
+ </div>
177
+ );
178
+ }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * `Dialog` — a design-system wrapper over Radix Dialog: an accessible modal (role
3
+ * `dialog`, focus trap, Escape to close) labelled by its title. Modality is
4
+ * enforced by the focus trap and by Radix marking the rest of the page inert, not
5
+ * by an `aria-modal` attribute — the panel ships none.
6
+ *
7
+ * Radix owns every modal behaviour — the focus trap, the background scroll lock,
8
+ * Escape, and focus return to the trigger — so this component adds no second
9
+ * mechanism. It contributes only the design-system surface: `tai-overlay` paints
10
+ * the scrim from `--tai-color-scrim`, and `tai-dialog` sizes the panel with a
11
+ * `min()` so it still fits a 320 px viewport. The one gap Radix leaves — focus
12
+ * return for a dialog that renders no trigger — is filled by
13
+ * `useModalFocusReturn`, which stands down whenever a trigger IS rendered.
14
+ */
15
+ import * as RadixDialog from '@radix-ui/react-dialog';
16
+ import type { ReactElement, ReactNode } from 'react';
17
+
18
+ import { assertSlotElement } from '../element-slot';
19
+ import { useModalFocusReturn } from './modal-focus';
20
+
21
+ export interface DialogProps {
22
+ readonly title: string;
23
+ readonly description?: string;
24
+ readonly children?: ReactNode;
25
+ /**
26
+ * A trigger element; when omitted, control the dialog via `open`/`onOpenChange`.
27
+ *
28
+ * It is a single ELEMENT, not any node: Radix clones its props onto it, so a
29
+ * string throws. The type admits a FRAGMENT — `<></>` is a `ReactElement` —
30
+ * which would render openers carrying neither the
31
+ * `aria-haspopup`/`aria-expanded`/`aria-controls` wiring nor a click handler,
32
+ * so {@link assertSlotElement} rejects that one at runtime.
33
+ */
34
+ readonly trigger?: ReactElement;
35
+ readonly open?: boolean;
36
+ readonly defaultOpen?: boolean;
37
+ readonly onOpenChange?: (open: boolean) => void;
38
+ }
39
+
40
+ export function Dialog({
41
+ title,
42
+ description,
43
+ children,
44
+ trigger,
45
+ open,
46
+ defaultOpen,
47
+ onOpenChange,
48
+ }: DialogProps) {
49
+ const focusReturn = useModalFocusReturn(trigger !== undefined);
50
+ if (trigger !== undefined) assertSlotElement(trigger, 'Dialog `trigger`');
51
+ return (
52
+ <RadixDialog.Root open={open} defaultOpen={defaultOpen} onOpenChange={onOpenChange}>
53
+ {trigger !== undefined ? <RadixDialog.Trigger asChild>{trigger}</RadixDialog.Trigger> : null}
54
+ <RadixDialog.Portal>
55
+ <RadixDialog.Overlay className="tai-overlay" />
56
+ {/* Radix wires `aria-describedby` to its Description's id unconditionally,
57
+ so a dialog that renders no Description would ship a dangling IDREF.
58
+ Passing the prop as `undefined` is Radix's opt-out — it has to be
59
+ ABSENT when a description IS rendered, or it would clear the wiring. */}
60
+ <RadixDialog.Content
61
+ className="tai-dialog"
62
+ {...focusReturn}
63
+ {...(description === undefined ? { 'aria-describedby': undefined } : {})}
64
+ >
65
+ <RadixDialog.Title className="tai-dialog-title">{title}</RadixDialog.Title>
66
+ <div className="tai-stack">
67
+ {description !== undefined ? (
68
+ <RadixDialog.Description className="tai-muted">{description}</RadixDialog.Description>
69
+ ) : null}
70
+ {children}
71
+ </div>
72
+ </RadixDialog.Content>
73
+ </RadixDialog.Portal>
74
+ </RadixDialog.Root>
75
+ );
76
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * `Drawer` — a side-anchored, full-height modal panel, published for a screen
3
+ * that wants a modal it can anchor to an edge rather than centre. Nothing in
4
+ * Studio renders one today; it is SDK surface a plugin can reach for. It is the
5
+ * same Radix Dialog machinery `Dialog` uses, so
6
+ * the focus trap, the scroll lock, Escape and overlay dismissal, the inert
7
+ * background, and focus return to the opener all come from the primitive; only
8
+ * the anchoring differs, and that lives entirely in `.tai-drawer`.
9
+ *
10
+ * Pass the opener as `trigger` where there is one (as `Dialog` does): Radix's own
11
+ * trigger is what carries `aria-haspopup`/`aria-expanded`/`aria-controls` and
12
+ * what its close sequence hands focus back to. A drawer opened purely by flipping
13
+ * `open` renders no trigger, so `useModalFocusReturn` returns focus to the opener
14
+ * in that case alone — with a trigger present it stands down and Radix's own
15
+ * restore is the only mechanism.
16
+ *
17
+ * Open state takes either form, the same three props `Dialog` publishes:
18
+ * `open`/`onOpenChange` to drive it from the caller's state, `defaultOpen` (or
19
+ * nothing at all) to let Radix own it behind a `trigger`.
20
+ */
21
+ import * as RadixDialog from '@radix-ui/react-dialog';
22
+ import type { ReactElement, ReactNode } from 'react';
23
+
24
+ import { assertSlotElement } from '../element-slot';
25
+ import { CloseIcon } from './icons';
26
+ import { useModalFocusReturn } from './modal-focus';
27
+
28
+ export interface DrawerProps {
29
+ /** The dialog's accessible name. */
30
+ readonly title: string;
31
+ readonly children: ReactNode;
32
+ readonly side?: 'left' | 'right';
33
+ /**
34
+ * The opener. Radix labels it and returns focus to it when the drawer closes.
35
+ *
36
+ * It is a single ELEMENT, not any node: Radix clones its props onto it, so a
37
+ * string throws. The type admits a FRAGMENT — `<></>` is a `ReactElement` —
38
+ * which would render openers carrying neither the
39
+ * `aria-haspopup`/`aria-expanded`/`aria-controls` wiring nor a click handler,
40
+ * so {@link assertSlotElement} rejects that one at runtime.
41
+ */
42
+ readonly trigger?: ReactElement;
43
+ readonly open?: boolean;
44
+ readonly defaultOpen?: boolean;
45
+ readonly onOpenChange?: (open: boolean) => void;
46
+ }
47
+
48
+ export function Drawer({
49
+ title,
50
+ children,
51
+ side = 'left',
52
+ trigger,
53
+ open,
54
+ defaultOpen,
55
+ onOpenChange,
56
+ }: DrawerProps) {
57
+ const focusReturn = useModalFocusReturn(trigger !== undefined);
58
+ if (trigger !== undefined) assertSlotElement(trigger, 'Drawer `trigger`');
59
+ return (
60
+ <RadixDialog.Root open={open} defaultOpen={defaultOpen} onOpenChange={onOpenChange}>
61
+ {trigger === undefined ? null : <RadixDialog.Trigger asChild>{trigger}</RadixDialog.Trigger>}
62
+ <RadixDialog.Portal>
63
+ <RadixDialog.Overlay className="tai-overlay" />
64
+ {/* The panel is named by its title alone; `aria-describedby={undefined}`
65
+ is Radix's opt-out for a dialog that carries no description. */}
66
+ <RadixDialog.Content
67
+ className="tai-drawer"
68
+ data-side={side}
69
+ aria-describedby={undefined}
70
+ {...focusReturn}
71
+ >
72
+ <div className="tai-drawer-header">
73
+ <RadixDialog.Title className="tai-section-title">{title}</RadixDialog.Title>
74
+ <RadixDialog.Close className="tai-icon-btn" aria-label="Close">
75
+ <CloseIcon />
76
+ </RadixDialog.Close>
77
+ </div>
78
+ {children}
79
+ </RadixDialog.Content>
80
+ </RadixDialog.Portal>
81
+ </RadixDialog.Root>
82
+ );
83
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * A generic render-error boundary: it contains a throw from its subtree and shows
3
+ * a loud `role="alert"` panel in its place, so one failing region never blanks the
4
+ * page around it. `label` prefixes the caught message to name the contained region
5
+ * (e.g. the plugin whose content threw); `onError` observes the error for logging.
6
+ * There is no in-place retry — the boundary resets by remounting, so callers that
7
+ * want a reset give it a fresh `key`.
8
+ *
9
+ * The fallback is the design system's `ErrorState`, so a contained render error
10
+ * looks exactly like a failed fetch: one `role="alert"` surface headed by a mark
11
+ * and words, never color alone. It is rendered without a retry, since the
12
+ * boundary resets by remounting.
13
+ */
14
+ import { Component, type ErrorInfo, type ReactNode } from 'react';
15
+
16
+ import { errorMessage } from '../errors';
17
+ import { ErrorState } from './primitives';
18
+
19
+ export interface ErrorBoundaryProps {
20
+ readonly children: ReactNode;
21
+ /** Prefixed to the caught error message, naming the contained region. */
22
+ readonly label?: string;
23
+ /** Called with the caught error and React's component stack, for logging. */
24
+ readonly onError?: (error: unknown, info: ErrorInfo) => void;
25
+ }
26
+
27
+ // React passes whatever the subtree threw — an `Error`, but also a bare string
28
+ // or any object a plugin chose to throw — so the caught value is `unknown` and
29
+ // coerced to a readable string only for display. `hasError` is the caught flag
30
+ // (not a sentinel on `error`), so even a falsy throw such as `null` is contained.
31
+ interface ErrorBoundaryState {
32
+ readonly hasError: boolean;
33
+ readonly error: unknown;
34
+ }
35
+
36
+ export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
37
+ override state: ErrorBoundaryState = { hasError: false, error: null };
38
+
39
+ static getDerivedStateFromError(error: unknown): ErrorBoundaryState {
40
+ return { hasError: true, error };
41
+ }
42
+
43
+ override componentDidCatch(error: unknown, info: ErrorInfo): void {
44
+ this.props.onError?.(error, info);
45
+ }
46
+
47
+ override render(): ReactNode {
48
+ if (this.state.hasError) {
49
+ const { label } = this.props;
50
+ const text = errorMessage(this.state.error);
51
+ const message = label !== undefined ? `${label}: ${text}` : text;
52
+ return <ErrorState message={message} />;
53
+ }
54
+ return this.props.children;
55
+ }
56
+ }