@kitn.ai/ui 0.15.0 → 0.16.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 (366) hide show
  1. package/README.md +9 -0
  2. package/bin/mcp.js +22 -0
  3. package/dist/bash-InADTalH.js +6 -1
  4. package/dist/components/artifact.d.ts +58 -0
  5. package/dist/components/attachments.d.ts +67 -0
  6. package/dist/components/card-fallback.d.ts +10 -0
  7. package/dist/components/card-renderer.d.ts +13 -0
  8. package/dist/components/card.d.ts +28 -0
  9. package/dist/components/chain-of-thought.d.ts +29 -0
  10. package/dist/components/chat-container.d.ts +19 -0
  11. package/dist/components/chat-scope-picker.d.ts +9 -0
  12. package/dist/components/chat-thread.d.ts +93 -0
  13. package/dist/components/checkpoint.d.ts +20 -0
  14. package/dist/components/choice-card.d.ts +77 -0
  15. package/dist/components/code-block.d.ts +16 -0
  16. package/dist/components/confirm-card.d.ts +57 -0
  17. package/dist/components/context.d.ts +65 -0
  18. package/dist/components/conversation-item.d.ts +8 -0
  19. package/dist/components/conversation-list.d.ts +11 -0
  20. package/dist/components/embed.d.ts +21 -0
  21. package/dist/components/empty.d.ts +43 -0
  22. package/dist/components/feedback-bar.d.ts +45 -0
  23. package/dist/components/file-tree.d.ts +57 -0
  24. package/dist/components/file-upload.d.ts +16 -0
  25. package/dist/components/form-widgets.d.ts +31 -0
  26. package/dist/components/form.d.ts +103 -0
  27. package/dist/components/image.d.ts +12 -0
  28. package/dist/components/link-preview.d.ts +23 -0
  29. package/dist/components/loader.d.ts +60 -0
  30. package/dist/components/markdown.d.ts +8 -0
  31. package/dist/components/message-skills.d.ts +15 -0
  32. package/dist/components/message.d.ts +54 -0
  33. package/dist/components/model-switcher.d.ts +8 -0
  34. package/dist/components/prompt-input.d.ts +38 -0
  35. package/dist/components/prompt-suggestion.d.ts +13 -0
  36. package/dist/components/reasoning.d.ts +20 -0
  37. package/dist/components/response-stream.d.ts +14 -0
  38. package/dist/components/scroll-button.d.ts +7 -0
  39. package/dist/components/slash-command.d.ts +15 -0
  40. package/dist/components/source.d.ts +23 -0
  41. package/dist/components/tasks-card.d.ts +71 -0
  42. package/dist/components/text-shimmer.d.ts +9 -0
  43. package/dist/components/thinking-bar.d.ts +10 -0
  44. package/dist/components/tool.d.ts +16 -0
  45. package/dist/components/use-card-resolution.d.ts +12 -0
  46. package/dist/components/voice-input.d.ts +7 -0
  47. package/dist/core-AYMC6_lb.js +5874 -12
  48. package/dist/css-M7EaDHN_.js +6 -1
  49. package/dist/elements/artifact.d.ts +1 -0
  50. package/dist/elements/attachments.d.ts +1 -0
  51. package/dist/elements/card.d.ts +1 -0
  52. package/dist/elements/cards.d.ts +0 -0
  53. package/dist/elements/chain-of-thought.d.ts +13 -0
  54. package/dist/elements/chat-scope-picker.d.ts +1 -0
  55. package/dist/elements/chat-types.d.ts +41 -0
  56. package/dist/elements/chat-workspace.d.ts +1 -0
  57. package/dist/elements/chat.d.ts +1 -0
  58. package/dist/elements/checkpoint.d.ts +1 -0
  59. package/dist/elements/choice.d.ts +1 -0
  60. package/dist/elements/code-block.d.ts +1 -0
  61. package/dist/elements/confirm-card.d.ts +1 -0
  62. package/dist/elements/context-meter.d.ts +1 -0
  63. package/dist/elements/conversation-list.d.ts +11 -0
  64. package/dist/elements/css.d.ts +1 -0
  65. package/dist/elements/default-input.d.ts +40 -0
  66. package/dist/elements/define.d.ts +42 -0
  67. package/dist/elements/embed.d.ts +1 -0
  68. package/dist/elements/empty.d.ts +1 -0
  69. package/dist/elements/feedback-bar.d.ts +1 -0
  70. package/dist/elements/file-tree.d.ts +1 -0
  71. package/dist/elements/file-upload.d.ts +1 -0
  72. package/dist/elements/form.d.ts +1 -0
  73. package/dist/elements/image.d.ts +1 -0
  74. package/dist/elements/link-preview.d.ts +1 -0
  75. package/dist/elements/loader.d.ts +1 -0
  76. package/dist/elements/markdown.d.ts +1 -0
  77. package/dist/elements/message-skills.d.ts +17 -0
  78. package/dist/elements/message.d.ts +1 -0
  79. package/dist/elements/model-switcher.d.ts +11 -0
  80. package/dist/elements/popover.d.ts +1 -0
  81. package/dist/elements/prompt-input.d.ts +9 -0
  82. package/dist/elements/prompt-suggestions.d.ts +7 -0
  83. package/dist/elements/reasoning.d.ts +1 -0
  84. package/dist/elements/register-impl.d.ts +0 -0
  85. package/dist/elements/register.d.ts +3 -0
  86. package/dist/elements/remote.d.ts +1 -0
  87. package/dist/elements/resizable.d.ts +17 -0
  88. package/dist/elements/response-stream.d.ts +1 -0
  89. package/dist/elements/scroll-button.d.ts +1 -0
  90. package/dist/elements/source.d.ts +18 -0
  91. package/dist/elements/switch.d.ts +1 -0
  92. package/dist/elements/tasks.d.ts +1 -0
  93. package/dist/elements/text-shimmer.d.ts +1 -0
  94. package/dist/elements/thinking-bar.d.ts +1 -0
  95. package/dist/elements/tool.d.ts +1 -0
  96. package/dist/elements/voice-input.d.ts +1 -0
  97. package/dist/elements.d.ts +732 -0
  98. package/dist/engine-javascript-vq0WuIJl.js +2516 -14
  99. package/dist/github-dark-dimmed-DUshB20C.js +4 -1
  100. package/dist/github-light-JYsPkUQd.js +4 -1
  101. package/dist/html-CPZ3oZQ7.js +10 -1
  102. package/dist/index.d.ts +112 -2
  103. package/dist/index.js +13551 -0
  104. package/dist/javascript-C25yR2R2.js +6 -1
  105. package/dist/json-DxJze_jm.js +6 -1
  106. package/dist/kitn-chat.es.js +1 -77
  107. package/dist/llms/llms-full.txt +1 -1
  108. package/dist/llms/llms.txt +1 -1
  109. package/dist/mcp.es.js +2140 -0
  110. package/dist/primitives/card-contract.d.ts +103 -0
  111. package/dist/primitives/card-host.d.ts +12 -0
  112. package/dist/primitives/card-registry.d.ts +17 -0
  113. package/dist/primitives/card-resolution.d.ts +8 -0
  114. package/dist/primitives/card-routing.d.ts +12 -0
  115. package/dist/primitives/card-validate.d.ts +25 -0
  116. package/dist/primitives/chat-config.d.ts +31 -0
  117. package/dist/primitives/controllable.d.ts +13 -0
  118. package/dist/primitives/embed-providers.d.ts +65 -0
  119. package/dist/primitives/highlighter.d.ts +23 -0
  120. package/dist/primitives/link-preview.d.ts +47 -0
  121. package/dist/primitives/pdf-preview.d.ts +50 -0
  122. package/dist/primitives/use-auto-resize.d.ts +8 -0
  123. package/dist/primitives/use-resize-observer.d.ts +1 -0
  124. package/dist/primitives/use-stick-to-bottom.d.ts +5 -0
  125. package/dist/primitives/use-text-stream.d.ts +19 -0
  126. package/dist/primitives/use-voice-recorder.d.ts +9 -0
  127. package/dist/react/index.d.ts +1118 -0
  128. package/dist/react/runtime.d.ts +15 -0
  129. package/dist/react.js +265 -0
  130. package/dist/register-impl-wCsFPoh9.js +77 -0
  131. package/dist/register-ujhr1nBS.js +1 -0
  132. package/dist/remote/host-embed.d.ts +33 -0
  133. package/dist/remote/index.d.ts +2 -0
  134. package/dist/remote/origin.d.ts +5 -0
  135. package/dist/remote/provider-runtime.d.ts +27 -0
  136. package/dist/remote/provider.d.ts +2 -0
  137. package/dist/remote/validate.d.ts +4 -0
  138. package/dist/remote/version.d.ts +4 -0
  139. package/dist/remote/wire.d.ts +53 -0
  140. package/dist/svelte--5p79yCD.js +15 -1
  141. package/dist/tsx-B8rCNbgL.js +6 -1
  142. package/dist/types.d.ts +42 -0
  143. package/dist/typescript-RycA9KXf.js +6 -1
  144. package/dist/ui/action-icons.d.ts +11 -0
  145. package/dist/ui/avatar.d.ts +8 -0
  146. package/dist/ui/badge.d.ts +9 -0
  147. package/dist/ui/button.d.ts +10 -0
  148. package/dist/ui/collapsible.d.ts +27 -0
  149. package/dist/ui/dropdown.d.ts +20 -0
  150. package/dist/ui/hover-card.d.ts +28 -0
  151. package/dist/ui/overlay.d.ts +67 -0
  152. package/dist/ui/popover.d.ts +32 -0
  153. package/dist/ui/resizable.d.ts +76 -0
  154. package/dist/ui/scroll-area.d.ts +5 -0
  155. package/dist/ui/separator.d.ts +5 -0
  156. package/dist/ui/skeleton.d.ts +5 -0
  157. package/dist/ui/switch.d.ts +19 -0
  158. package/dist/ui/textarea.d.ts +6 -0
  159. package/dist/ui/tooltip.d.ts +8 -0
  160. package/dist/utils/cn.d.ts +2 -0
  161. package/dist/vue-BmIZj4XD.js +33 -1
  162. package/frameworks/react/index.tsx +4 -0
  163. package/frameworks/react/runtime.tsx +16 -2
  164. package/llms-full.txt +1 -1
  165. package/llms.txt +1 -1
  166. package/package.json +29 -11
  167. package/src/agent-tooling/archetypes.ts +46 -0
  168. package/src/agent-tooling/integrations/cloudflare.ts +88 -0
  169. package/src/agent-tooling/integrations/langgraph.ts +60 -0
  170. package/src/agent-tooling/integrations/mastra.ts +27 -0
  171. package/src/agent-tooling/integrations/mock.ts +34 -0
  172. package/src/agent-tooling/integrations/ollama.ts +47 -0
  173. package/src/agent-tooling/integrations/openrouter.ts +26 -0
  174. package/src/agent-tooling/integrations/pi.ts +40 -0
  175. package/src/agent-tooling/integrations/pydantic-ai.ts +52 -0
  176. package/src/agent-tooling/integrations/vercel-ai-sdk.ts +44 -0
  177. package/src/agent-tooling/mcp/manifest.ts +128 -0
  178. package/src/agent-tooling/mcp/server.ts +59 -0
  179. package/src/agent-tooling/mcp/stdio.ts +18 -0
  180. package/src/agent-tooling/mcp/tools/debug.ts +305 -0
  181. package/src/agent-tooling/mcp/tools/reference.ts +132 -0
  182. package/src/agent-tooling/mcp/tools/scaffold.ts +1627 -0
  183. package/src/agent-tooling/mcp/tools/theme.ts +340 -0
  184. package/src/agent-tooling/mcp/tools/types.ts +14 -0
  185. package/src/agent-tooling/registry.ts +41 -0
  186. package/src/agent-tooling/types.ts +30 -0
  187. package/src/elements/compiled.css +1 -1
  188. package/src/elements/define.tsx +7 -1
  189. package/src/elements/element-types.d.ts +2 -1
  190. package/src/elements/register-impl.ts +55 -0
  191. package/src/elements/register.ts +17 -51
  192. package/theme.css +4 -2
  193. package/src/components/artifact.stories.tsx +0 -138
  194. package/src/components/attachments.stories.tsx +0 -303
  195. package/src/components/attachments.test.tsx +0 -64
  196. package/src/components/chain-of-thought.stories.tsx +0 -211
  197. package/src/components/chat-container.stories.tsx +0 -187
  198. package/src/components/chat-thread.test.tsx +0 -58
  199. package/src/components/checkpoint.stories.tsx +0 -102
  200. package/src/components/code-block.stories.tsx +0 -150
  201. package/src/components/confirm-card.stories.tsx +0 -74
  202. package/src/components/context.stories.tsx +0 -229
  203. package/src/components/context.test.tsx +0 -133
  204. package/src/components/conversation-item.stories.tsx +0 -125
  205. package/src/components/conversation-list.stories.tsx +0 -133
  206. package/src/components/default-input.test.tsx +0 -111
  207. package/src/components/empty.stories.tsx +0 -434
  208. package/src/components/feedback-bar.stories.tsx +0 -138
  209. package/src/components/feedback-bar.test.tsx +0 -103
  210. package/src/components/file-tree.stories.tsx +0 -73
  211. package/src/components/file-upload.stories.tsx +0 -156
  212. package/src/components/image.stories.tsx +0 -89
  213. package/src/components/loader.stories.tsx +0 -181
  214. package/src/components/markdown.stories.tsx +0 -180
  215. package/src/components/message-action-bar.test.tsx +0 -128
  216. package/src/components/message-narrow.stories.tsx +0 -329
  217. package/src/components/message-skills.stories.tsx +0 -211
  218. package/src/components/message.stories.tsx +0 -281
  219. package/src/components/model-switcher.stories.tsx +0 -123
  220. package/src/components/model-switcher.test.tsx +0 -65
  221. package/src/components/prompt-input.stories.tsx +0 -222
  222. package/src/components/prompt-suggestion.stories.tsx +0 -142
  223. package/src/components/reasoning.stories.tsx +0 -140
  224. package/src/components/resizable.test.tsx +0 -226
  225. package/src/components/scroll-button.stories.tsx +0 -100
  226. package/src/components/slash-command.stories.tsx +0 -163
  227. package/src/components/source-list.test.tsx +0 -152
  228. package/src/components/source.stories.tsx +0 -124
  229. package/src/components/tasks-card.stories.tsx +0 -78
  230. package/src/components/text-shimmer.stories.tsx +0 -87
  231. package/src/components/thinking-bar.stories.tsx +0 -87
  232. package/src/components/tool.stories.tsx +0 -153
  233. package/src/components/voice-input.stories.tsx +0 -83
  234. package/src/elements/artifact.stories.tsx +0 -506
  235. package/src/elements/attachments.stories.tsx +0 -190
  236. package/src/elements/card.stories.tsx +0 -113
  237. package/src/elements/cards.stories.tsx +0 -59
  238. package/src/elements/catalog.stories.tsx +0 -491
  239. package/src/elements/chain-of-thought.declarative.test.tsx +0 -153
  240. package/src/elements/chain-of-thought.stories.tsx +0 -113
  241. package/src/elements/chat-scope-picker.stories.tsx +0 -73
  242. package/src/elements/chat-workspace.stories.tsx +0 -288
  243. package/src/elements/chat.stories.tsx +0 -151
  244. package/src/elements/checkpoint.stories.tsx +0 -72
  245. package/src/elements/choice.stories.tsx +0 -240
  246. package/src/elements/code-block.stories.tsx +0 -83
  247. package/src/elements/composed-shell.stories.tsx +0 -316
  248. package/src/elements/confirm-card.stories.tsx +0 -227
  249. package/src/elements/context-meter.stories.tsx +0 -151
  250. package/src/elements/conversation-list.declarative.test.tsx +0 -137
  251. package/src/elements/conversation-list.stories.tsx +0 -243
  252. package/src/elements/embed.stories.tsx +0 -213
  253. package/src/elements/empty.stories.tsx +0 -111
  254. package/src/elements/feedback-bar.stories.tsx +0 -114
  255. package/src/elements/file-tree.stories.tsx +0 -134
  256. package/src/elements/file-upload.stories.tsx +0 -82
  257. package/src/elements/form.stories.tsx +0 -248
  258. package/src/elements/image.stories.tsx +0 -71
  259. package/src/elements/link-preview.stories.tsx +0 -209
  260. package/src/elements/loader.stories.tsx +0 -88
  261. package/src/elements/markdown.stories.tsx +0 -76
  262. package/src/elements/message-skills.declarative.test.tsx +0 -104
  263. package/src/elements/message-skills.stories.tsx +0 -114
  264. package/src/elements/message.stories.tsx +0 -218
  265. package/src/elements/model-switcher.declarative.test.tsx +0 -130
  266. package/src/elements/model-switcher.stories.tsx +0 -198
  267. package/src/elements/popover.stories.tsx +0 -80
  268. package/src/elements/prompt-input-slash-command.test.tsx +0 -128
  269. package/src/elements/prompt-input-stoppable.test.tsx +0 -88
  270. package/src/elements/prompt-input-toolbar-actions.test.tsx +0 -120
  271. package/src/elements/prompt-input.stories.tsx +0 -331
  272. package/src/elements/prompt-suggestions.declarative.test.tsx +0 -164
  273. package/src/elements/prompt-suggestions.stories.tsx +0 -213
  274. package/src/elements/reasoning.stories.tsx +0 -77
  275. package/src/elements/remote.stories.tsx +0 -314
  276. package/src/elements/resizable.stories.tsx +0 -426
  277. package/src/elements/response-stream.stories.tsx +0 -79
  278. package/src/elements/scroll-button.stories.tsx +0 -202
  279. package/src/elements/scroll-button.test.tsx +0 -148
  280. package/src/elements/source-list.stories.tsx +0 -143
  281. package/src/elements/source.stories.tsx +0 -88
  282. package/src/elements/switch.stories.tsx +0 -56
  283. package/src/elements/tasks.stories.tsx +0 -237
  284. package/src/elements/text-shimmer.stories.tsx +0 -64
  285. package/src/elements/thinking-bar.stories.tsx +0 -72
  286. package/src/elements/tool.stories.tsx +0 -89
  287. package/src/elements/voice-input.stories.tsx +0 -88
  288. package/src/primitives/controllable.test.ts +0 -47
  289. package/src/stories/chat-panel-layout.stories.tsx +0 -145
  290. package/src/stories/chat-scene.tsx +0 -571
  291. package/src/stories/checkpoint-restore.stories.tsx +0 -256
  292. package/src/stories/context-usage.stories.tsx +0 -212
  293. package/src/stories/conversation-with-reasoning.stories.tsx +0 -182
  294. package/src/stories/conversation-with-sources.stories.tsx +0 -471
  295. package/src/stories/docs/Accessibility.mdx +0 -119
  296. package/src/stories/docs/ChildElements.mdx +0 -269
  297. package/src/stories/docs/ForAIAgents.mdx +0 -162
  298. package/src/stories/docs/GettingStarted.mdx +0 -65
  299. package/src/stories/docs/Installation.mdx +0 -83
  300. package/src/stories/docs/Introduction.mdx +0 -50
  301. package/src/stories/docs/SolidJsAdvanced.mdx +0 -17
  302. package/src/stories/docs/Theming.mdx +0 -85
  303. package/src/stories/docs/element-controls.ts +0 -121
  304. package/src/stories/docs/frameworks/Angular.mdx +0 -245
  305. package/src/stories/docs/frameworks/Html.mdx +0 -227
  306. package/src/stories/docs/frameworks/Overview.mdx +0 -47
  307. package/src/stories/docs/frameworks/React.mdx +0 -227
  308. package/src/stories/docs/frameworks/Solid.mdx +0 -173
  309. package/src/stories/docs/frameworks/Svelte.mdx +0 -194
  310. package/src/stories/docs/frameworks/Vue.mdx +0 -238
  311. package/src/stories/docs/generative-ui-overview.mdx +0 -186
  312. package/src/stories/docs/recipes/SpeechToText.mdx +0 -7
  313. package/src/stories/docs/recipes/Streaming.mdx +0 -68
  314. package/src/stories/docs/recipes/TextToSpeech.mdx +0 -35
  315. package/src/stories/docs/theme-editor/canvas.tsx +0 -32
  316. package/src/stories/docs/theme-editor/inspector.tsx +0 -66
  317. package/src/stories/docs/theme-editor/presets.test.ts +0 -32
  318. package/src/stories/docs/theme-editor/presets.ts +0 -64
  319. package/src/stories/docs/theme-editor/theme-css.test.ts +0 -19
  320. package/src/stories/docs/theme-editor/theme-css.ts +0 -15
  321. package/src/stories/docs/theme-editor/theme-editor.tsx +0 -146
  322. package/src/stories/docs/theme-tokens.tsx +0 -174
  323. package/src/stories/examples/ChoosingComponents.mdx +0 -106
  324. package/src/stories/examples/sample-data.ts +0 -79
  325. package/src/stories/examples/usage/checkpoint-restore.ts +0 -156
  326. package/src/stories/examples/usage/context-usage.ts +0 -591
  327. package/src/stories/examples/usage/conversation-with-reasoning.ts +0 -224
  328. package/src/stories/examples/usage/conversation-with-sources.ts +0 -589
  329. package/src/stories/examples/usage/empty-state.ts +0 -144
  330. package/src/stories/examples/usage/full-chat-app.ts +0 -277
  331. package/src/stories/examples/usage/index.ts +0 -63
  332. package/src/stories/examples/usage/message-actions.ts +0 -704
  333. package/src/stories/examples/usage/pattern-centered-conversation.ts +0 -446
  334. package/src/stories/examples/usage/pattern-chat-panel-layout.ts +0 -442
  335. package/src/stories/examples/usage/pattern-docked-widget.ts +0 -479
  336. package/src/stories/examples/usage/prompt-input-variants.ts +0 -1356
  337. package/src/stories/examples/usage/streaming-response.ts +0 -687
  338. package/src/stories/examples/usage/types.ts +0 -33
  339. package/src/stories/full-chat.stories.tsx +0 -18
  340. package/src/stories/message-actions.stories.tsx +0 -230
  341. package/src/stories/pattern-centered-conversation.stories.tsx +0 -93
  342. package/src/stories/pattern-docked-widget.stories.tsx +0 -93
  343. package/src/stories/pattern-empty-state.stories.tsx +0 -76
  344. package/src/stories/prompt-input-variants.stories.tsx +0 -456
  345. package/src/stories/streaming-response.stories.tsx +0 -438
  346. package/src/stories/theme-editor.stories.tsx +0 -16
  347. package/src/stories/token-reference.stories.tsx +0 -18
  348. package/src/stories/typography.stories.tsx +0 -78
  349. package/src/ui/avatar.stories.tsx +0 -103
  350. package/src/ui/badge.stories.tsx +0 -86
  351. package/src/ui/button.stories.tsx +0 -145
  352. package/src/ui/collapsible.stories.tsx +0 -69
  353. package/src/ui/dropdown.stories.tsx +0 -59
  354. package/src/ui/hover-card.stories.tsx +0 -77
  355. package/src/ui/hover-card.test.tsx +0 -30
  356. package/src/ui/overlay.stories.tsx +0 -115
  357. package/src/ui/popover.stories.tsx +0 -81
  358. package/src/ui/popover.test.tsx +0 -99
  359. package/src/ui/resizable.stories.tsx +0 -236
  360. package/src/ui/scroll-area.stories.tsx +0 -50
  361. package/src/ui/separator.stories.tsx +0 -81
  362. package/src/ui/skeleton.stories.tsx +0 -337
  363. package/src/ui/switch.stories.tsx +0 -51
  364. package/src/ui/switch.test.tsx +0 -59
  365. package/src/ui/textarea.stories.tsx +0 -76
  366. package/src/ui/tooltip.stories.tsx +0 -74
package/llms-full.txt CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # @kitn.ai/ui
5
5
 
6
- > Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. 44 `kitn-*` custom elements: streaming responses, markdown + code rendering, reasoning/tool panels, attachments, conversation sidebar, voice input. Zero framework dependency for consumers; the SolidJS runtime it is authored in is bundled in, so the host needs nothing.
6
+ > Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. 44 custom elements, every one prefixed `kai-` (e.g. `<kai-chat>`, `<kai-artifact>`): streaming responses, markdown + code rendering, reasoning/tool panels, attachments, conversation sidebar, voice input. Zero framework dependency for consumers; the SolidJS runtime it is authored in is bundled in, so the host needs nothing.
7
7
 
8
8
  ## Install
9
9
 
package/llms.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  <!-- AUTO-GENERATED by scripts/gen-llms.mjs — do not edit by hand. Run `npm run build`. -->
2
2
  # @kitn.ai/ui
3
3
 
4
- > Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. 44 `kitn-*` custom elements: streaming responses, markdown + code rendering, reasoning/tool panels, attachments, conversation sidebar, voice input. Zero framework dependency for consumers; the SolidJS runtime it is authored in is bundled in, so the host needs nothing.
4
+ > Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. 44 custom elements, every one prefixed `kai-` (e.g. `<kai-chat>`, `<kai-artifact>`): streaming responses, markdown + code rendering, reasoning/tool panels, attachments, conversation sidebar, voice input. Zero framework dependency for consumers; the SolidJS runtime it is authored in is bundled in, so the host needs nothing.
5
5
 
6
6
  ## Install
7
7
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitn.ai/ui",
3
- "version": "0.15.0",
3
+ "version": "0.16.0",
4
4
  "type": "module",
5
5
  "description": "Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. Authored in SolidJS.",
6
6
  "keywords": [
@@ -30,20 +30,30 @@
30
30
  "bugs": {
31
31
  "url": "https://github.com/kitn-ai/ui/issues"
32
32
  },
33
- "main": "src/index.ts",
34
- "types": "src/index.ts",
33
+ "main": "./dist/index.js",
34
+ "module": "./dist/index.js",
35
+ "types": "./dist/index.d.ts",
35
36
  "unpkg": "./dist/kitn-chat.es.js",
36
37
  "jsdelivr": "./dist/kitn-chat.es.js",
37
38
  "customElements": "dist/custom-elements.json",
39
+ "bin": {
40
+ "kai-mcp": "./bin/mcp.js"
41
+ },
38
42
  "exports": {
39
- ".": "./src/index.ts",
43
+ ".": {
44
+ "types": "./dist/index.d.ts",
45
+ "default": "./dist/index.js"
46
+ },
40
47
  "./elements": {
41
- "types": "./src/elements/element-types.d.ts",
48
+ "types": "./dist/elements.d.ts",
42
49
  "default": "./dist/kitn-chat.es.js"
43
50
  },
44
51
  "./theme.css": "./theme.css",
45
52
  "./theme.tokens.css": "./dist/theme.tokens.css",
46
- "./react": "./frameworks/react/index.tsx",
53
+ "./react": {
54
+ "types": "./dist/react/index.d.ts",
55
+ "default": "./dist/react.js"
56
+ },
47
57
  "./provider": {
48
58
  "types": "./dist/kitn-chat-provider.d.ts",
49
59
  "default": "./dist/kitn-chat-provider.es.js"
@@ -52,6 +62,12 @@
52
62
  "files": [
53
63
  "dist",
54
64
  "src",
65
+ "bin",
66
+ "!src/**/*.stories.tsx",
67
+ "!src/**/*.test.ts",
68
+ "!src/**/*.test.tsx",
69
+ "!src/**/*.mdx",
70
+ "!src/stories",
55
71
  "frameworks",
56
72
  "theme.css",
57
73
  "llms.txt",
@@ -60,7 +76,7 @@
60
76
  "scripts": {
61
77
  "prepublishOnly": "npm run build",
62
78
  "prebuild": "npm run build:css",
63
- "build": "vite build --config vite.config.ts && vite build --config vite.config.provider.ts",
79
+ "build": "vite build --config vite.config.ts && vite build --config vite.config.provider.ts && vite build --config vite.config.react.ts && vite build --config vite.config.barrel.ts && vite build --config vite.config.mcp.ts",
64
80
  "postbuild": "npm run build:theme && npm run build:api && npm run build:schemas",
65
81
  "build:theme": "node scripts/build-theme-tokens.mjs",
66
82
  "build:api": "node scripts/gen-element-api.mjs",
@@ -69,7 +85,7 @@
69
85
  "test:react": "vitest run --config vitest.react.config.ts",
70
86
  "test:storybook": "vitest run --project=storybook",
71
87
  "test:watch": "vitest",
72
- "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.react.json && tsc --noEmit -p tsconfig.react.test.json",
88
+ "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.react.json && tsc --noEmit -p tsconfig.react.test.json && tsc --noEmit -p tsconfig.mcp.json",
73
89
  "examples": "echo 'Serving repo root on http://localhost:8000 — open http://localhost:8000/examples/composable/index.html' && python3 -m http.server 8000",
74
90
  "dev": "npm run build:css && storybook dev -p 6006",
75
91
  "storybook": "npm run build:css && storybook dev -p 6006",
@@ -82,6 +98,7 @@
82
98
  },
83
99
  "dependencies": {
84
100
  "@floating-ui/dom": "^1.7.6",
101
+ "@modelcontextprotocol/sdk": "^1.29.0",
85
102
  "@shikijs/langs": "^4.2.0",
86
103
  "@shikijs/themes": "^4.2.0",
87
104
  "class-variance-authority": "^0.7.0",
@@ -91,7 +108,8 @@
91
108
  "shiki": "^4.0.2",
92
109
  "solid-element": "^1.9.1",
93
110
  "solid-js": "^1.9.0",
94
- "tailwind-merge": "^2.5.0"
111
+ "tailwind-merge": "^2.5.0",
112
+ "zod": "^4.4.3"
95
113
  },
96
114
  "devDependencies": {
97
115
  "@playwright/test": "^1.60.0",
@@ -105,6 +123,7 @@
105
123
  "@tailwindcss/typography": "^0.5.19",
106
124
  "@testing-library/jest-dom": "^6.0.0",
107
125
  "@testing-library/react": "^16.3.2",
126
+ "@types/node": "^26.0.0",
108
127
  "@types/react": "^19.2.17",
109
128
  "@types/react-dom": "^19.2.3",
110
129
  "@vitejs/plugin-react": "^4.7.0",
@@ -130,8 +149,7 @@
130
149
  "vitest": "^4.1.0"
131
150
  },
132
151
  "peerDependencies": {
133
- "react": ">=18",
134
- "solid-js": "^1.9.0"
152
+ "react": ">=18"
135
153
  },
136
154
  "peerDependenciesMeta": {
137
155
  "react": {
@@ -0,0 +1,46 @@
1
+ import type { Archetype } from './types';
2
+
3
+ export const archetypes: Archetype[] = [
4
+ {
5
+ id: 'drop-in-chat',
6
+ title: 'Drop-in chat',
7
+ components: ['kai-chat'],
8
+ defaultPlacement: 'full-page',
9
+ docsSlug: 'examples/drop-in-chat',
10
+ },
11
+ {
12
+ id: 'support-widget',
13
+ title: 'Support widget',
14
+ components: ['kai-chat'],
15
+ defaultPlacement: 'docked-widget',
16
+ docsSlug: 'examples/support-widget',
17
+ },
18
+ {
19
+ id: 'knowledge-base',
20
+ title: 'Knowledge base / RAG',
21
+ components: ['kai-chat', 'kai-sources'],
22
+ defaultPlacement: 'full-page',
23
+ docsSlug: 'examples/knowledge-base',
24
+ },
25
+ {
26
+ id: 'agentic',
27
+ title: 'Agentic assistant',
28
+ components: ['kai-chat', 'kai-tool', 'kai-reasoning'],
29
+ defaultPlacement: 'side',
30
+ docsSlug: 'examples/agentic-assistant',
31
+ },
32
+ {
33
+ id: 'workspace',
34
+ title: 'Agentic workspace',
35
+ components: ['kai-chat', 'kai-artifact', 'kai-resizable'],
36
+ defaultPlacement: 'side',
37
+ docsSlug: 'examples/workspace',
38
+ },
39
+ {
40
+ id: 'voice',
41
+ title: 'Voice assistant',
42
+ components: ['kai-chat', 'kai-voice-input'],
43
+ defaultPlacement: 'full-page',
44
+ docsSlug: 'examples/voice-assistant',
45
+ },
46
+ ];
@@ -0,0 +1,88 @@
1
+ import type { Integration } from '../types';
2
+
3
+ const cloudflare: Integration = {
4
+ id: 'cloudflare',
5
+ title: 'Cloudflare AI',
6
+ category: 'provider',
7
+ language: 'ts',
8
+ streamFormat: 'openai-sse',
9
+ envVars: ['CF_ACCOUNT_ID', 'CF_API_TOKEN'],
10
+ routeTemplates: {
11
+ next: `// app/api/chat/route.ts — proxy Workers AI, keep the token server-side
12
+ export async function POST(req: Request) {
13
+ const { messages } = await req.json();
14
+
15
+ const upstream = await fetch(
16
+ \`https://api.cloudflare.com/client/v4/accounts/\${process.env.CF_ACCOUNT_ID}/ai/v1/chat/completions\`,
17
+ {
18
+ method: 'POST',
19
+ headers: {
20
+ Authorization: \`Bearer \${process.env.CF_API_TOKEN}\`,
21
+ 'Content-Type': 'application/json',
22
+ },
23
+ body: JSON.stringify({
24
+ model: '@cf/meta/llama-3.1-8b-instruct',
25
+ messages,
26
+ stream: true,
27
+ }),
28
+ },
29
+ );
30
+
31
+ // Workers AI returns OpenAI-format SSE — pass it straight through.
32
+ return new Response(upstream.body, { headers: { 'Content-Type': 'text/event-stream' } });
33
+ }`,
34
+ worker: `// Worker handler — env.AI is bound in wrangler.toml
35
+ // env.AI.run emits Cloudflare-native SSE (data: {"response":"<token>"}).
36
+ // The TransformStream below re-frames each chunk to OpenAI-format SSE so
37
+ // kai-chat's reader works without any client-side changes.
38
+ export default {
39
+ async fetch(req: Request, env: Env): Promise<Response> {
40
+ const { messages } = await req.json();
41
+
42
+ const nativeStream = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
43
+ messages,
44
+ stream: true,
45
+ });
46
+
47
+ // Re-frame Cloudflare-native SSE → OpenAI-format SSE
48
+ const { readable, writable } = new TransformStream();
49
+ const writer = writable.getWriter();
50
+ const encoder = new TextEncoder();
51
+ const decoder = new TextDecoder();
52
+
53
+ (async () => {
54
+ const reader = (nativeStream as ReadableStream<Uint8Array>).getReader();
55
+ let buffer = '';
56
+ while (true) {
57
+ const { value, done } = await reader.read();
58
+ if (done) break;
59
+ buffer += decoder.decode(value, { stream: true });
60
+ const lines = buffer.split('\\n');
61
+ buffer = lines.pop() ?? '';
62
+ for (const line of lines) {
63
+ const s = line.trim();
64
+ if (!s.startsWith('data:')) continue;
65
+ const payload = s.slice(5).trim();
66
+ if (payload === '[DONE]') continue;
67
+ try {
68
+ const { response } = JSON.parse(payload) as { response?: string };
69
+ if (response == null) continue;
70
+ const openaiChunk = JSON.stringify({ choices: [{ delta: { content: response } }] });
71
+ await writer.write(encoder.encode(\`data: \${openaiChunk}\\n\\n\`));
72
+ } catch { /* skip malformed lines */ }
73
+ }
74
+ }
75
+ await writer.write(encoder.encode('data: [DONE]\\n\\n'));
76
+ await writer.close();
77
+ })();
78
+
79
+ return new Response(readable, { headers: { 'Content-Type': 'text/event-stream' } });
80
+ },
81
+ };`,
82
+ },
83
+ streamMapping: "Workers AI via the OpenAI-compatible HTTP endpoint returns OpenAI-format SSE — pipe upstream.body straight to the browser; kai-chat's reader handles it. The native env.AI binding streams Cloudflare's own format (data: {\"response\":\"...token...\"}); the worker route template re-frames these chunks to OpenAI-format SSE via a TransformStream before returning.",
84
+ runNote: 'Set CF_ACCOUNT_ID and CF_API_TOKEN. Model ids are prefixed with @cf/, e.g. @cf/meta/llama-3.1-8b-instruct. For the AI binding (worker key), add an [ai] block with binding = "AI" in wrangler.toml.',
85
+ docsSlug: 'integrations/cloudflare-ai',
86
+ };
87
+
88
+ export default cloudflare;
@@ -0,0 +1,60 @@
1
+ import type { Integration } from '../types';
2
+
3
+ const langgraph: Integration = {
4
+ id: 'langgraph',
5
+ title: 'LangGraph',
6
+ category: 'framework',
7
+ language: 'ts',
8
+ streamFormat: 'openai-sse',
9
+ envVars: ['OPENAI_API_KEY'],
10
+ routeTemplates: {
11
+ next: `// POST /api/chat — stream a compiled LangGraph agent to the browser
12
+ import { createReactAgent } from '@langchain/langgraph/prebuilt';
13
+ import { ChatOpenAI } from '@langchain/openai';
14
+ import { tool } from '@langchain/core/tools';
15
+ import { z } from 'zod';
16
+
17
+ const getWeather = tool(
18
+ async ({ city }) => \`It's 18°C and clear in \${city}.\`,
19
+ {
20
+ name: 'get_weather',
21
+ description: 'Get the current weather for a city.',
22
+ schema: z.object({ city: z.string() }),
23
+ },
24
+ );
25
+
26
+ const agent = createReactAgent({
27
+ llm: new ChatOpenAI({ model: 'gpt-4o' }),
28
+ tools: [getWeather],
29
+ });
30
+
31
+ export async function POST(req: Request) {
32
+ const { messages } = await req.json();
33
+
34
+ const stream = await agent.stream({ messages }, { streamMode: 'messages' });
35
+
36
+ const encoder = new TextEncoder();
37
+ const body = new ReadableStream({
38
+ async start(controller) {
39
+ const send = (obj: unknown) =>
40
+ controller.enqueue(encoder.encode(\`data: \${JSON.stringify(obj)}\\n\\n\`));
41
+
42
+ for await (const [chunk] of stream) {
43
+ if (typeof chunk.content === 'string' && chunk.content) {
44
+ send({ choices: [{ delta: { content: chunk.content } }] });
45
+ }
46
+ }
47
+ controller.enqueue(encoder.encode('data: [DONE]\\n\\n'));
48
+ controller.close();
49
+ },
50
+ });
51
+
52
+ return new Response(body, { headers: { 'Content-Type': 'text/event-stream' } });
53
+ }`,
54
+ },
55
+ streamMapping: "Use graph.stream(input, { streamMode: 'messages' }) to get [messageChunk, metadata] tuples. Extract chunk.content (string) and forward as OpenAI-format SSE frames: data: {choices:[{delta:{content}}]}. Close with data: [DONE]. The kai-chat reader handles it.",
56
+ runNote: 'Set OPENAI_API_KEY (or the key for your chosen model provider). Install @langchain/langgraph, @langchain/openai, @langchain/core.',
57
+ docsSlug: 'integrations/langgraph',
58
+ };
59
+
60
+ export default langgraph;
@@ -0,0 +1,27 @@
1
+ import type { Integration } from '../types';
2
+
3
+ const mastra: Integration = {
4
+ id: 'mastra',
5
+ title: 'Mastra',
6
+ category: 'harness',
7
+ language: 'ts',
8
+ streamFormat: 'openai-sse',
9
+ envVars: ['MASTRA_URL'],
10
+ routeTemplates: {
11
+ express: `// POST /api/chat — your server proxies a Mastra agent to the browser
12
+ import { MastraClient } from '@mastra/client-js';
13
+
14
+ const mastra = new MastraClient({ baseUrl: process.env.MASTRA_URL });
15
+
16
+ const stream = await mastra.getAgent('supportAgent').stream({ messages });
17
+ for await (const delta of stream.textStream) {
18
+ res.write(\`data: \${JSON.stringify({ choices: [{ delta: { content: delta } }] })}\\n\\n\`);
19
+ }
20
+ res.write('data: [DONE]\\n\\n');`,
21
+ },
22
+ streamMapping: "Mastra agents speak Vercel AI SDK v5 and expose stream.textStream (async iterable of string deltas). Iterate textStream and emit data: {choices:[{delta:{content}}]} frames; close with data: [DONE]. kai-chat's SSE reader handles it. For tool calls and reasoning, convert the agent to a UI message stream with @mastra/ai-sdk.",
23
+ runNote: 'Set MASTRA_URL to your Mastra server base URL (mastra dev exposes POST /api/agents/:agentId/stream on port 4111). Install @mastra/client-js.',
24
+ docsSlug: 'integrations/harnesses',
25
+ };
26
+
27
+ export default mastra;
@@ -0,0 +1,34 @@
1
+ import type { Integration } from '../types';
2
+
3
+ /**
4
+ * mock — the zero-config first-win.
5
+ *
6
+ * Not a real backend: there's no provider, no API key, no `/api` route. The
7
+ * scaffolder special-cases `integration === 'mock'` and emits a front-end whose
8
+ * `onSubmit` SIMULATES a streamed assistant reply CLIENT-SIDE (token-by-token,
9
+ * a new array/object reference per chunk — honouring the messages contract).
10
+ *
11
+ * This lets `scaffold(useCase, integration: 'mock', framework: 'react')` run with
12
+ * zero config so a developer sees a live, streaming chat before wiring a model.
13
+ * Swap `integration` for a real provider (openrouter, ollama, …) when ready.
14
+ *
15
+ * It carries an empty `routeTemplates` on purpose: there is no server route to
16
+ * emit. `category: 'mock'` keeps it out of the real provider/gateway/framework/
17
+ * harness catalogs.
18
+ */
19
+ const mock: Integration = {
20
+ id: 'mock',
21
+ title: 'Mock (local preview)',
22
+ category: 'mock',
23
+ language: 'ts',
24
+ streamFormat: 'native',
25
+ envVars: [],
26
+ routeTemplates: {},
27
+ streamMapping:
28
+ 'No backend. onSubmit streams a canned assistant reply client-side, one token at a time, reassigning messages (new array/object reference) per chunk so kai-chat re-renders. Swap integration for a real provider when ready.',
29
+ runNote:
30
+ 'No backend or API key needed — replies stream locally for preview. Run the front-end as-is; swap `integration` for a real provider (e.g. openrouter, ollama) when ready.',
31
+ docsSlug: 'integrations/mock',
32
+ };
33
+
34
+ export default mock;
@@ -0,0 +1,47 @@
1
+ import type { Integration } from '../types';
2
+
3
+ const ollama: Integration = {
4
+ id: 'ollama',
5
+ title: 'Ollama',
6
+ category: 'provider',
7
+ language: 'ts',
8
+ streamFormat: 'openai-sse',
9
+ envVars: [],
10
+ routeTemplates: {
11
+ next: `// app/api/chat/route.ts — proxy the browser to local Ollama
12
+ export async function POST(req: Request) {
13
+ const { messages } = await req.json();
14
+
15
+ const upstream = await fetch('http://localhost:11434/v1/chat/completions', {
16
+ method: 'POST',
17
+ headers: { 'Content-Type': 'application/json' },
18
+ body: JSON.stringify({ model: 'llama3.2', messages, stream: true }),
19
+ });
20
+
21
+ // Ollama returns OpenAI-format SSE — stream it straight to the browser.
22
+ return new Response(upstream.body, { headers: { 'Content-Type': 'text/event-stream' } });
23
+ }`,
24
+ html: `<kai-chat id="chat"></kai-chat>
25
+
26
+ <script type="module">
27
+ import '@kitn.ai/ui/elements';
28
+ const chat = document.getElementById('chat');
29
+
30
+ chat.addEventListener('kai-submit', async (e) => {
31
+ const history = [...chat.messages, { id: crypto.randomUUID(), role: 'user', content: e.detail.value }];
32
+ chat.messages = [...history, { id: crypto.randomUUID(), role: 'assistant', content: '' }];
33
+ await fetch('/api/chat', {
34
+ method: 'POST',
35
+ headers: { 'Content-Type': 'application/json' },
36
+ body: JSON.stringify({ messages: history }),
37
+ });
38
+ // stream the reply into the last message — see the Streaming recipe
39
+ });
40
+ </script>`,
41
+ },
42
+ streamMapping: "Ollama's OpenAI-compatible endpoint (http://localhost:11434/v1/chat/completions) returns OpenAI-format SSE — pipe upstream.body straight to the browser; kai-chat's reader handles it. No API key needed; pass any string if a client requires one (Ollama ignores it).",
43
+ runNote: 'No API key required. Run: ollama serve (starts on 127.0.0.1:11434), then ollama pull <model>. For browser-direct access, set OLLAMA_ORIGINS to allow the page origin; restart Ollama after any env change.',
44
+ docsSlug: 'integrations/ollama',
45
+ };
46
+
47
+ export default ollama;
@@ -0,0 +1,26 @@
1
+ import type { Integration } from '../types';
2
+
3
+ const openrouter: Integration = {
4
+ id: 'openrouter',
5
+ title: 'OpenRouter',
6
+ category: 'gateway',
7
+ language: 'ts',
8
+ streamFormat: 'openai-sse',
9
+ envVars: ['OPENROUTER_API_KEY'],
10
+ routeTemplates: {
11
+ next: `export async function POST(req: Request) {
12
+ const { model, messages } = await req.json();
13
+ const upstream = await fetch('https://openrouter.ai/api/v1/chat/completions', {
14
+ method: 'POST',
15
+ headers: { Authorization: \`Bearer \${process.env.OPENROUTER_API_KEY}\`, 'Content-Type': 'application/json' },
16
+ body: JSON.stringify({ model, messages, stream: true }),
17
+ });
18
+ return new Response(upstream.body, { headers: { 'Content-Type': 'text/event-stream' } });
19
+ }`,
20
+ },
21
+ streamMapping: 'OpenRouter returns OpenAI-format SSE — pipe upstream.body straight to the browser; the Streaming-recipe reader handles it.',
22
+ runNote: 'Set OPENROUTER_API_KEY. Model ids are vendor/model, e.g. openai/gpt-4o.',
23
+ docsSlug: 'integrations/connect-any-model',
24
+ };
25
+
26
+ export default openrouter;
@@ -0,0 +1,40 @@
1
+ import type { Integration } from '../types';
2
+
3
+ const pi: Integration = {
4
+ id: 'pi',
5
+ title: 'Pi',
6
+ category: 'harness',
7
+ language: 'ts',
8
+ streamFormat: 'native',
9
+ envVars: [],
10
+ routeTemplates: {
11
+ express: `import { spawn } from 'node:child_process';
12
+
13
+ // POST /api/chat — bridge a Pi RPC session to the browser as SSE
14
+ const pi = spawn('pi', ['--mode', 'rpc', '--no-session']);
15
+
16
+ // Send the user's turn. Pi commands are { type, message }.
17
+ pi.stdin.write(JSON.stringify({ type: 'prompt', message: prompt }) + '\\n');
18
+
19
+ let buffer = '';
20
+ pi.stdout.on('data', (chunk) => {
21
+ buffer += chunk.toString();
22
+ const lines = buffer.split('\\n');
23
+ buffer = lines.pop(); // hold the partial line for the next chunk
24
+ for (const line of lines) {
25
+ if (!line) continue;
26
+ const event = JSON.parse(line);
27
+ const part = event.assistantMessageEvent;
28
+ if (event.type === 'message_update' && part?.type === 'text_delta') {
29
+ res.write(\`data: \${JSON.stringify({ choices: [{ delta: { content: part.delta } }] })}\\n\\n\`);
30
+ }
31
+ }
32
+ });
33
+ pi.on('close', () => { res.write('data: [DONE]\\n\\n'); res.end(); });`,
34
+ },
35
+ streamMapping: "Pi runs as a local stdio process in RPC mode (pi --mode rpc --no-session). It emits newline-delimited JSON events on stdout. Map message_update events where assistantMessageEvent.type === 'text_delta' to data: {choices:[{delta:{content:part.delta}}]} SSE frames; send data: [DONE] on close. Split stdout on \\n (not readline, which breaks on Unicode separators U+2028/U+2029). Pi also emits thinking_delta (map to reasoning) and toolcall_* events (map to tool calls).",
36
+ runNote: "Pi must be installed locally and available on PATH as 'pi'. No API key is required by the bridge itself; Pi uses its own credentials. Pi runs with full user permissions — sandbox before exposing to a public endpoint. See the RPC reference: https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/rpc.md",
37
+ docsSlug: 'integrations/harnesses',
38
+ };
39
+
40
+ export default pi;
@@ -0,0 +1,52 @@
1
+ import type { Integration } from '../types';
2
+
3
+ const pydanticAi: Integration = {
4
+ id: 'pydantic-ai',
5
+ title: 'Pydantic AI',
6
+ category: 'framework',
7
+ language: 'python',
8
+ streamFormat: 'openai-sse',
9
+ envVars: ['OPENAI_API_KEY'],
10
+ routeTemplates: {
11
+ fastapi: `# main.py
12
+ import json
13
+ from fastapi import FastAPI
14
+ from fastapi.middleware.cors import CORSMiddleware
15
+ from fastapi.responses import StreamingResponse
16
+ from pydantic import BaseModel
17
+ from pydantic_ai import Agent
18
+
19
+ agent = Agent('openai:gpt-4o')
20
+
21
+ app = FastAPI()
22
+ app.add_middleware(
23
+ CORSMiddleware, allow_origins=['*'], allow_methods=['*'], allow_headers=['*']
24
+ )
25
+
26
+ class Message(BaseModel):
27
+ role: str
28
+ content: str
29
+
30
+ class ChatRequest(BaseModel):
31
+ messages: list[Message]
32
+
33
+ async def openai_sse(messages: list[Message]):
34
+ prompt = messages[-1].content if messages else ''
35
+ async with agent.run_stream(prompt) as result:
36
+ async for delta in result.stream_text(delta=True):
37
+ chunk = {'choices': [{'delta': {'content': delta}}]}
38
+ yield f'data: {json.dumps(chunk)}\\n\\n'
39
+ yield 'data: [DONE]\\n\\n'
40
+
41
+ @app.post('/api/chat')
42
+ async def chat(req: ChatRequest):
43
+ return StreamingResponse(openai_sse(req.messages), media_type='text/event-stream')`,
44
+ },
45
+ streamMapping:
46
+ "Pydantic AI's agent.run_stream() yields text deltas via result.stream_text(delta=True). Each delta is re-framed as a data: {choices:[{delta:{content}}]} SSE line and the stream closes with data: [DONE]. The kai-chat reader is unchanged — it sees standard OpenAI-format SSE.",
47
+ runNote:
48
+ 'Install: pip install pydantic-ai fastapi uvicorn. Set OPENAI_API_KEY. Run: uvicorn main:app --reload (default port 8000). Point kai-chat at http://localhost:8000/api/chat.',
49
+ docsSlug: 'integrations/pydantic-ai',
50
+ };
51
+
52
+ export default pydanticAi;
@@ -0,0 +1,44 @@
1
+ import type { Integration } from '../types';
2
+
3
+ const vercelAiSdk: Integration = {
4
+ id: 'vercel-ai-sdk',
5
+ title: 'Vercel AI SDK',
6
+ category: 'framework',
7
+ language: 'ts',
8
+ streamFormat: 'ai-sdk',
9
+ envVars: ['AI_GATEWAY_API_KEY'],
10
+ routeTemplates: {
11
+ next: `// app/api/chat/route.ts
12
+ import { streamText } from 'ai';
13
+
14
+ export const maxDuration = 30; // allow long streaming responses
15
+
16
+ export async function POST(req: Request) {
17
+ const { messages } = await req.json();
18
+
19
+ const result = streamText({
20
+ model: 'openai/gpt-4o', // AI Gateway id; needs AI_GATEWAY_API_KEY
21
+ messages,
22
+ });
23
+
24
+ const encoder = new TextEncoder();
25
+ const sse = new ReadableStream({
26
+ async start(controller) {
27
+ for await (const delta of result.textStream) {
28
+ const chunk = { choices: [{ delta: { content: delta } }] };
29
+ controller.enqueue(encoder.encode(\`data: \${JSON.stringify(chunk)}\\n\\n\`));
30
+ }
31
+ controller.enqueue(encoder.encode('data: [DONE]\\n\\n'));
32
+ controller.close();
33
+ },
34
+ });
35
+
36
+ return new Response(sse, { headers: { 'Content-Type': 'text/event-stream' } });
37
+ }`,
38
+ },
39
+ streamMapping: "The Vercel AI SDK's toUIMessageStreamResponse() and toTextStreamResponse() don't emit OpenAI-format SSE. Wrap result.textStream manually: iterate text deltas and emit data: {choices:[{delta:{content}}]} frames, closing with data: [DONE]. The kai-chat SSE reader handles it.",
40
+ runNote: 'Set AI_GATEWAY_API_KEY for the AI Gateway (string model id form: creator/model-name). For direct provider access, import its provider package (e.g. @ai-sdk/openai) and set the corresponding key (e.g. OPENAI_API_KEY).',
41
+ docsSlug: 'integrations/vercel-ai-sdk',
42
+ };
43
+
44
+ export default vercelAiSdk;