@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.
- package/README.md +9 -0
- package/bin/mcp.js +22 -0
- package/dist/bash-InADTalH.js +6 -1
- package/dist/components/artifact.d.ts +58 -0
- package/dist/components/attachments.d.ts +67 -0
- package/dist/components/card-fallback.d.ts +10 -0
- package/dist/components/card-renderer.d.ts +13 -0
- package/dist/components/card.d.ts +28 -0
- package/dist/components/chain-of-thought.d.ts +29 -0
- package/dist/components/chat-container.d.ts +19 -0
- package/dist/components/chat-scope-picker.d.ts +9 -0
- package/dist/components/chat-thread.d.ts +93 -0
- package/dist/components/checkpoint.d.ts +20 -0
- package/dist/components/choice-card.d.ts +77 -0
- package/dist/components/code-block.d.ts +16 -0
- package/dist/components/confirm-card.d.ts +57 -0
- package/dist/components/context.d.ts +65 -0
- package/dist/components/conversation-item.d.ts +8 -0
- package/dist/components/conversation-list.d.ts +11 -0
- package/dist/components/embed.d.ts +21 -0
- package/dist/components/empty.d.ts +43 -0
- package/dist/components/feedback-bar.d.ts +45 -0
- package/dist/components/file-tree.d.ts +57 -0
- package/dist/components/file-upload.d.ts +16 -0
- package/dist/components/form-widgets.d.ts +31 -0
- package/dist/components/form.d.ts +103 -0
- package/dist/components/image.d.ts +12 -0
- package/dist/components/link-preview.d.ts +23 -0
- package/dist/components/loader.d.ts +60 -0
- package/dist/components/markdown.d.ts +8 -0
- package/dist/components/message-skills.d.ts +15 -0
- package/dist/components/message.d.ts +54 -0
- package/dist/components/model-switcher.d.ts +8 -0
- package/dist/components/prompt-input.d.ts +38 -0
- package/dist/components/prompt-suggestion.d.ts +13 -0
- package/dist/components/reasoning.d.ts +20 -0
- package/dist/components/response-stream.d.ts +14 -0
- package/dist/components/scroll-button.d.ts +7 -0
- package/dist/components/slash-command.d.ts +15 -0
- package/dist/components/source.d.ts +23 -0
- package/dist/components/tasks-card.d.ts +71 -0
- package/dist/components/text-shimmer.d.ts +9 -0
- package/dist/components/thinking-bar.d.ts +10 -0
- package/dist/components/tool.d.ts +16 -0
- package/dist/components/use-card-resolution.d.ts +12 -0
- package/dist/components/voice-input.d.ts +7 -0
- package/dist/core-AYMC6_lb.js +5874 -12
- package/dist/css-M7EaDHN_.js +6 -1
- package/dist/elements/artifact.d.ts +1 -0
- package/dist/elements/attachments.d.ts +1 -0
- package/dist/elements/card.d.ts +1 -0
- package/dist/elements/cards.d.ts +0 -0
- package/dist/elements/chain-of-thought.d.ts +13 -0
- package/dist/elements/chat-scope-picker.d.ts +1 -0
- package/dist/elements/chat-types.d.ts +41 -0
- package/dist/elements/chat-workspace.d.ts +1 -0
- package/dist/elements/chat.d.ts +1 -0
- package/dist/elements/checkpoint.d.ts +1 -0
- package/dist/elements/choice.d.ts +1 -0
- package/dist/elements/code-block.d.ts +1 -0
- package/dist/elements/confirm-card.d.ts +1 -0
- package/dist/elements/context-meter.d.ts +1 -0
- package/dist/elements/conversation-list.d.ts +11 -0
- package/dist/elements/css.d.ts +1 -0
- package/dist/elements/default-input.d.ts +40 -0
- package/dist/elements/define.d.ts +42 -0
- package/dist/elements/embed.d.ts +1 -0
- package/dist/elements/empty.d.ts +1 -0
- package/dist/elements/feedback-bar.d.ts +1 -0
- package/dist/elements/file-tree.d.ts +1 -0
- package/dist/elements/file-upload.d.ts +1 -0
- package/dist/elements/form.d.ts +1 -0
- package/dist/elements/image.d.ts +1 -0
- package/dist/elements/link-preview.d.ts +1 -0
- package/dist/elements/loader.d.ts +1 -0
- package/dist/elements/markdown.d.ts +1 -0
- package/dist/elements/message-skills.d.ts +17 -0
- package/dist/elements/message.d.ts +1 -0
- package/dist/elements/model-switcher.d.ts +11 -0
- package/dist/elements/popover.d.ts +1 -0
- package/dist/elements/prompt-input.d.ts +9 -0
- package/dist/elements/prompt-suggestions.d.ts +7 -0
- package/dist/elements/reasoning.d.ts +1 -0
- package/dist/elements/register-impl.d.ts +0 -0
- package/dist/elements/register.d.ts +3 -0
- package/dist/elements/remote.d.ts +1 -0
- package/dist/elements/resizable.d.ts +17 -0
- package/dist/elements/response-stream.d.ts +1 -0
- package/dist/elements/scroll-button.d.ts +1 -0
- package/dist/elements/source.d.ts +18 -0
- package/dist/elements/switch.d.ts +1 -0
- package/dist/elements/tasks.d.ts +1 -0
- package/dist/elements/text-shimmer.d.ts +1 -0
- package/dist/elements/thinking-bar.d.ts +1 -0
- package/dist/elements/tool.d.ts +1 -0
- package/dist/elements/voice-input.d.ts +1 -0
- package/dist/elements.d.ts +732 -0
- package/dist/engine-javascript-vq0WuIJl.js +2516 -14
- package/dist/github-dark-dimmed-DUshB20C.js +4 -1
- package/dist/github-light-JYsPkUQd.js +4 -1
- package/dist/html-CPZ3oZQ7.js +10 -1
- package/dist/index.d.ts +112 -2
- package/dist/index.js +13551 -0
- package/dist/javascript-C25yR2R2.js +6 -1
- package/dist/json-DxJze_jm.js +6 -1
- package/dist/kitn-chat.es.js +1 -77
- package/dist/llms/llms-full.txt +1 -1
- package/dist/llms/llms.txt +1 -1
- package/dist/mcp.es.js +2140 -0
- package/dist/primitives/card-contract.d.ts +103 -0
- package/dist/primitives/card-host.d.ts +12 -0
- package/dist/primitives/card-registry.d.ts +17 -0
- package/dist/primitives/card-resolution.d.ts +8 -0
- package/dist/primitives/card-routing.d.ts +12 -0
- package/dist/primitives/card-validate.d.ts +25 -0
- package/dist/primitives/chat-config.d.ts +31 -0
- package/dist/primitives/controllable.d.ts +13 -0
- package/dist/primitives/embed-providers.d.ts +65 -0
- package/dist/primitives/highlighter.d.ts +23 -0
- package/dist/primitives/link-preview.d.ts +47 -0
- package/dist/primitives/pdf-preview.d.ts +50 -0
- package/dist/primitives/use-auto-resize.d.ts +8 -0
- package/dist/primitives/use-resize-observer.d.ts +1 -0
- package/dist/primitives/use-stick-to-bottom.d.ts +5 -0
- package/dist/primitives/use-text-stream.d.ts +19 -0
- package/dist/primitives/use-voice-recorder.d.ts +9 -0
- package/dist/react/index.d.ts +1118 -0
- package/dist/react/runtime.d.ts +15 -0
- package/dist/react.js +265 -0
- package/dist/register-impl-wCsFPoh9.js +77 -0
- package/dist/register-ujhr1nBS.js +1 -0
- package/dist/remote/host-embed.d.ts +33 -0
- package/dist/remote/index.d.ts +2 -0
- package/dist/remote/origin.d.ts +5 -0
- package/dist/remote/provider-runtime.d.ts +27 -0
- package/dist/remote/provider.d.ts +2 -0
- package/dist/remote/validate.d.ts +4 -0
- package/dist/remote/version.d.ts +4 -0
- package/dist/remote/wire.d.ts +53 -0
- package/dist/svelte--5p79yCD.js +15 -1
- package/dist/tsx-B8rCNbgL.js +6 -1
- package/dist/types.d.ts +42 -0
- package/dist/typescript-RycA9KXf.js +6 -1
- package/dist/ui/action-icons.d.ts +11 -0
- package/dist/ui/avatar.d.ts +8 -0
- package/dist/ui/badge.d.ts +9 -0
- package/dist/ui/button.d.ts +10 -0
- package/dist/ui/collapsible.d.ts +27 -0
- package/dist/ui/dropdown.d.ts +20 -0
- package/dist/ui/hover-card.d.ts +28 -0
- package/dist/ui/overlay.d.ts +67 -0
- package/dist/ui/popover.d.ts +32 -0
- package/dist/ui/resizable.d.ts +76 -0
- package/dist/ui/scroll-area.d.ts +5 -0
- package/dist/ui/separator.d.ts +5 -0
- package/dist/ui/skeleton.d.ts +5 -0
- package/dist/ui/switch.d.ts +19 -0
- package/dist/ui/textarea.d.ts +6 -0
- package/dist/ui/tooltip.d.ts +8 -0
- package/dist/utils/cn.d.ts +2 -0
- package/dist/vue-BmIZj4XD.js +33 -1
- package/frameworks/react/index.tsx +4 -0
- package/frameworks/react/runtime.tsx +16 -2
- package/llms-full.txt +1 -1
- package/llms.txt +1 -1
- package/package.json +29 -11
- package/src/agent-tooling/archetypes.ts +46 -0
- package/src/agent-tooling/integrations/cloudflare.ts +88 -0
- package/src/agent-tooling/integrations/langgraph.ts +60 -0
- package/src/agent-tooling/integrations/mastra.ts +27 -0
- package/src/agent-tooling/integrations/mock.ts +34 -0
- package/src/agent-tooling/integrations/ollama.ts +47 -0
- package/src/agent-tooling/integrations/openrouter.ts +26 -0
- package/src/agent-tooling/integrations/pi.ts +40 -0
- package/src/agent-tooling/integrations/pydantic-ai.ts +52 -0
- package/src/agent-tooling/integrations/vercel-ai-sdk.ts +44 -0
- package/src/agent-tooling/mcp/manifest.ts +128 -0
- package/src/agent-tooling/mcp/server.ts +59 -0
- package/src/agent-tooling/mcp/stdio.ts +18 -0
- package/src/agent-tooling/mcp/tools/debug.ts +305 -0
- package/src/agent-tooling/mcp/tools/reference.ts +132 -0
- package/src/agent-tooling/mcp/tools/scaffold.ts +1627 -0
- package/src/agent-tooling/mcp/tools/theme.ts +340 -0
- package/src/agent-tooling/mcp/tools/types.ts +14 -0
- package/src/agent-tooling/registry.ts +41 -0
- package/src/agent-tooling/types.ts +30 -0
- package/src/elements/compiled.css +1 -1
- package/src/elements/define.tsx +7 -1
- package/src/elements/element-types.d.ts +2 -1
- package/src/elements/register-impl.ts +55 -0
- package/src/elements/register.ts +17 -51
- package/theme.css +4 -2
- package/src/components/artifact.stories.tsx +0 -138
- package/src/components/attachments.stories.tsx +0 -303
- package/src/components/attachments.test.tsx +0 -64
- package/src/components/chain-of-thought.stories.tsx +0 -211
- package/src/components/chat-container.stories.tsx +0 -187
- package/src/components/chat-thread.test.tsx +0 -58
- package/src/components/checkpoint.stories.tsx +0 -102
- package/src/components/code-block.stories.tsx +0 -150
- package/src/components/confirm-card.stories.tsx +0 -74
- package/src/components/context.stories.tsx +0 -229
- package/src/components/context.test.tsx +0 -133
- package/src/components/conversation-item.stories.tsx +0 -125
- package/src/components/conversation-list.stories.tsx +0 -133
- package/src/components/default-input.test.tsx +0 -111
- package/src/components/empty.stories.tsx +0 -434
- package/src/components/feedback-bar.stories.tsx +0 -138
- package/src/components/feedback-bar.test.tsx +0 -103
- package/src/components/file-tree.stories.tsx +0 -73
- package/src/components/file-upload.stories.tsx +0 -156
- package/src/components/image.stories.tsx +0 -89
- package/src/components/loader.stories.tsx +0 -181
- package/src/components/markdown.stories.tsx +0 -180
- package/src/components/message-action-bar.test.tsx +0 -128
- package/src/components/message-narrow.stories.tsx +0 -329
- package/src/components/message-skills.stories.tsx +0 -211
- package/src/components/message.stories.tsx +0 -281
- package/src/components/model-switcher.stories.tsx +0 -123
- package/src/components/model-switcher.test.tsx +0 -65
- package/src/components/prompt-input.stories.tsx +0 -222
- package/src/components/prompt-suggestion.stories.tsx +0 -142
- package/src/components/reasoning.stories.tsx +0 -140
- package/src/components/resizable.test.tsx +0 -226
- package/src/components/scroll-button.stories.tsx +0 -100
- package/src/components/slash-command.stories.tsx +0 -163
- package/src/components/source-list.test.tsx +0 -152
- package/src/components/source.stories.tsx +0 -124
- package/src/components/tasks-card.stories.tsx +0 -78
- package/src/components/text-shimmer.stories.tsx +0 -87
- package/src/components/thinking-bar.stories.tsx +0 -87
- package/src/components/tool.stories.tsx +0 -153
- package/src/components/voice-input.stories.tsx +0 -83
- package/src/elements/artifact.stories.tsx +0 -506
- package/src/elements/attachments.stories.tsx +0 -190
- package/src/elements/card.stories.tsx +0 -113
- package/src/elements/cards.stories.tsx +0 -59
- package/src/elements/catalog.stories.tsx +0 -491
- package/src/elements/chain-of-thought.declarative.test.tsx +0 -153
- package/src/elements/chain-of-thought.stories.tsx +0 -113
- package/src/elements/chat-scope-picker.stories.tsx +0 -73
- package/src/elements/chat-workspace.stories.tsx +0 -288
- package/src/elements/chat.stories.tsx +0 -151
- package/src/elements/checkpoint.stories.tsx +0 -72
- package/src/elements/choice.stories.tsx +0 -240
- package/src/elements/code-block.stories.tsx +0 -83
- package/src/elements/composed-shell.stories.tsx +0 -316
- package/src/elements/confirm-card.stories.tsx +0 -227
- package/src/elements/context-meter.stories.tsx +0 -151
- package/src/elements/conversation-list.declarative.test.tsx +0 -137
- package/src/elements/conversation-list.stories.tsx +0 -243
- package/src/elements/embed.stories.tsx +0 -213
- package/src/elements/empty.stories.tsx +0 -111
- package/src/elements/feedback-bar.stories.tsx +0 -114
- package/src/elements/file-tree.stories.tsx +0 -134
- package/src/elements/file-upload.stories.tsx +0 -82
- package/src/elements/form.stories.tsx +0 -248
- package/src/elements/image.stories.tsx +0 -71
- package/src/elements/link-preview.stories.tsx +0 -209
- package/src/elements/loader.stories.tsx +0 -88
- package/src/elements/markdown.stories.tsx +0 -76
- package/src/elements/message-skills.declarative.test.tsx +0 -104
- package/src/elements/message-skills.stories.tsx +0 -114
- package/src/elements/message.stories.tsx +0 -218
- package/src/elements/model-switcher.declarative.test.tsx +0 -130
- package/src/elements/model-switcher.stories.tsx +0 -198
- package/src/elements/popover.stories.tsx +0 -80
- package/src/elements/prompt-input-slash-command.test.tsx +0 -128
- package/src/elements/prompt-input-stoppable.test.tsx +0 -88
- package/src/elements/prompt-input-toolbar-actions.test.tsx +0 -120
- package/src/elements/prompt-input.stories.tsx +0 -331
- package/src/elements/prompt-suggestions.declarative.test.tsx +0 -164
- package/src/elements/prompt-suggestions.stories.tsx +0 -213
- package/src/elements/reasoning.stories.tsx +0 -77
- package/src/elements/remote.stories.tsx +0 -314
- package/src/elements/resizable.stories.tsx +0 -426
- package/src/elements/response-stream.stories.tsx +0 -79
- package/src/elements/scroll-button.stories.tsx +0 -202
- package/src/elements/scroll-button.test.tsx +0 -148
- package/src/elements/source-list.stories.tsx +0 -143
- package/src/elements/source.stories.tsx +0 -88
- package/src/elements/switch.stories.tsx +0 -56
- package/src/elements/tasks.stories.tsx +0 -237
- package/src/elements/text-shimmer.stories.tsx +0 -64
- package/src/elements/thinking-bar.stories.tsx +0 -72
- package/src/elements/tool.stories.tsx +0 -89
- package/src/elements/voice-input.stories.tsx +0 -88
- package/src/primitives/controllable.test.ts +0 -47
- package/src/stories/chat-panel-layout.stories.tsx +0 -145
- package/src/stories/chat-scene.tsx +0 -571
- package/src/stories/checkpoint-restore.stories.tsx +0 -256
- package/src/stories/context-usage.stories.tsx +0 -212
- package/src/stories/conversation-with-reasoning.stories.tsx +0 -182
- package/src/stories/conversation-with-sources.stories.tsx +0 -471
- package/src/stories/docs/Accessibility.mdx +0 -119
- package/src/stories/docs/ChildElements.mdx +0 -269
- package/src/stories/docs/ForAIAgents.mdx +0 -162
- package/src/stories/docs/GettingStarted.mdx +0 -65
- package/src/stories/docs/Installation.mdx +0 -83
- package/src/stories/docs/Introduction.mdx +0 -50
- package/src/stories/docs/SolidJsAdvanced.mdx +0 -17
- package/src/stories/docs/Theming.mdx +0 -85
- package/src/stories/docs/element-controls.ts +0 -121
- package/src/stories/docs/frameworks/Angular.mdx +0 -245
- package/src/stories/docs/frameworks/Html.mdx +0 -227
- package/src/stories/docs/frameworks/Overview.mdx +0 -47
- package/src/stories/docs/frameworks/React.mdx +0 -227
- package/src/stories/docs/frameworks/Solid.mdx +0 -173
- package/src/stories/docs/frameworks/Svelte.mdx +0 -194
- package/src/stories/docs/frameworks/Vue.mdx +0 -238
- package/src/stories/docs/generative-ui-overview.mdx +0 -186
- package/src/stories/docs/recipes/SpeechToText.mdx +0 -7
- package/src/stories/docs/recipes/Streaming.mdx +0 -68
- package/src/stories/docs/recipes/TextToSpeech.mdx +0 -35
- package/src/stories/docs/theme-editor/canvas.tsx +0 -32
- package/src/stories/docs/theme-editor/inspector.tsx +0 -66
- package/src/stories/docs/theme-editor/presets.test.ts +0 -32
- package/src/stories/docs/theme-editor/presets.ts +0 -64
- package/src/stories/docs/theme-editor/theme-css.test.ts +0 -19
- package/src/stories/docs/theme-editor/theme-css.ts +0 -15
- package/src/stories/docs/theme-editor/theme-editor.tsx +0 -146
- package/src/stories/docs/theme-tokens.tsx +0 -174
- package/src/stories/examples/ChoosingComponents.mdx +0 -106
- package/src/stories/examples/sample-data.ts +0 -79
- package/src/stories/examples/usage/checkpoint-restore.ts +0 -156
- package/src/stories/examples/usage/context-usage.ts +0 -591
- package/src/stories/examples/usage/conversation-with-reasoning.ts +0 -224
- package/src/stories/examples/usage/conversation-with-sources.ts +0 -589
- package/src/stories/examples/usage/empty-state.ts +0 -144
- package/src/stories/examples/usage/full-chat-app.ts +0 -277
- package/src/stories/examples/usage/index.ts +0 -63
- package/src/stories/examples/usage/message-actions.ts +0 -704
- package/src/stories/examples/usage/pattern-centered-conversation.ts +0 -446
- package/src/stories/examples/usage/pattern-chat-panel-layout.ts +0 -442
- package/src/stories/examples/usage/pattern-docked-widget.ts +0 -479
- package/src/stories/examples/usage/prompt-input-variants.ts +0 -1356
- package/src/stories/examples/usage/streaming-response.ts +0 -687
- package/src/stories/examples/usage/types.ts +0 -33
- package/src/stories/full-chat.stories.tsx +0 -18
- package/src/stories/message-actions.stories.tsx +0 -230
- package/src/stories/pattern-centered-conversation.stories.tsx +0 -93
- package/src/stories/pattern-docked-widget.stories.tsx +0 -93
- package/src/stories/pattern-empty-state.stories.tsx +0 -76
- package/src/stories/prompt-input-variants.stories.tsx +0 -456
- package/src/stories/streaming-response.stories.tsx +0 -438
- package/src/stories/theme-editor.stories.tsx +0 -16
- package/src/stories/token-reference.stories.tsx +0 -18
- package/src/stories/typography.stories.tsx +0 -78
- package/src/ui/avatar.stories.tsx +0 -103
- package/src/ui/badge.stories.tsx +0 -86
- package/src/ui/button.stories.tsx +0 -145
- package/src/ui/collapsible.stories.tsx +0 -69
- package/src/ui/dropdown.stories.tsx +0 -59
- package/src/ui/hover-card.stories.tsx +0 -77
- package/src/ui/hover-card.test.tsx +0 -30
- package/src/ui/overlay.stories.tsx +0 -115
- package/src/ui/popover.stories.tsx +0 -81
- package/src/ui/popover.test.tsx +0 -99
- package/src/ui/resizable.stories.tsx +0 -236
- package/src/ui/scroll-area.stories.tsx +0 -50
- package/src/ui/separator.stories.tsx +0 -81
- package/src/ui/skeleton.stories.tsx +0 -337
- package/src/ui/switch.stories.tsx +0 -51
- package/src/ui/switch.test.tsx +0 -59
- package/src/ui/textarea.stories.tsx +0 -76
- 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 `
|
|
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 `
|
|
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.
|
|
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": "
|
|
34
|
-
"
|
|
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
|
-
".":
|
|
43
|
+
".": {
|
|
44
|
+
"types": "./dist/index.d.ts",
|
|
45
|
+
"default": "./dist/index.js"
|
|
46
|
+
},
|
|
40
47
|
"./elements": {
|
|
41
|
-
"types": "./
|
|
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":
|
|
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;
|