@kitn.ai/ui 0.20.1 → 0.22.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 +44 -45
- package/dist/components/artifact-card.d.ts +51 -0
- package/dist/components/artifact.d.ts +1 -1
- package/dist/components/attachments.d.ts +2 -2
- package/dist/components/audio-visualizer/index.d.ts +3 -3
- package/dist/components/audio-visualizer/labs/lab-choreography.d.ts +59 -0
- package/dist/components/audio-visualizer/labs/lab-shaders.d.ts +22 -0
- package/dist/components/audio-visualizer/labs/lab-visualizer.d.ts +18 -0
- package/dist/components/audio-visualizer/variant-aurora.d.ts +2 -2
- package/dist/components/audio-visualizer/variant-bar.d.ts +2 -2
- package/dist/components/audio-visualizer/variant-custom.d.ts +2 -2
- package/dist/components/audio-visualizer/variant-grid.d.ts +1 -1
- package/dist/components/audio-visualizer/variant-radial.d.ts +1 -1
- package/dist/components/audio-visualizer/variant-wave.d.ts +1 -1
- package/dist/components/card-fallback.d.ts +12 -2
- package/dist/components/card-renderer.d.ts +63 -2
- package/dist/components/chat-container.d.ts +3 -0
- package/dist/components/chat-scope-picker.d.ts +2 -2
- package/dist/components/chat-thread.d.ts +77 -18
- package/dist/components/choice-card.d.ts +3 -28
- package/dist/components/composer-dom.d.ts +1 -1
- package/dist/components/composer-highlight.d.ts +1 -1
- package/dist/components/composer-history.d.ts +1 -1
- package/dist/components/composer.d.ts +1 -1
- package/dist/components/confirm-card.d.ts +3 -18
- package/dist/components/context.d.ts +8 -4
- package/dist/components/conversation-item.d.ts +1 -1
- package/dist/components/conversation-list.d.ts +4 -3
- package/dist/components/embed.d.ts +3 -3
- package/dist/components/file-tree.d.ts +11 -22
- package/dist/components/form-widgets.d.ts +1 -1
- package/dist/components/form.d.ts +3 -44
- package/dist/components/link-preview.d.ts +3 -3
- package/dist/components/loader.d.ts +30 -48
- package/dist/components/message-skills.d.ts +4 -0
- package/dist/components/message.d.ts +84 -21
- package/dist/components/model-switcher.d.ts +2 -2
- package/dist/components/prompt-input.d.ts +2 -2
- package/dist/components/response-compare-types.d.ts +11 -2
- package/dist/components/response-compare.d.ts +3 -3
- package/dist/components/source.d.ts +12 -3
- package/dist/components/tasks-card.d.ts +3 -31
- package/dist/components/thread.d.ts +17 -5
- package/dist/components/toast.d.ts +2 -2
- package/dist/components/tool-classify.d.ts +8 -0
- package/dist/components/tool-types.d.ts +29 -1
- package/dist/components/tool.d.ts +3 -3
- package/dist/components/use-card-resolution.d.ts +1 -1
- package/dist/create-tween-COnPwAQN.js +338 -0
- package/dist/create-tween-DmTUaXWE.js +341 -0
- package/dist/create-tween-qs-jjvNA.js +7 -0
- package/dist/custom-elements.json +1726 -463
- package/dist/elements/agent-card.js +1 -1
- package/dist/elements/artifact.js +1 -1
- package/dist/elements/attachments.js +1 -1
- package/dist/elements/audio-visualizer.js +1 -1
- package/dist/elements/avatar.js +1 -1
- package/dist/elements/badge.js +1 -1
- package/dist/elements/button.js +1 -1
- package/dist/elements/card.js +1 -1
- package/dist/elements/cards.js +1 -1
- package/dist/elements/chain-of-thought.js +1 -1
- package/dist/elements/chat-scope-picker.js +1 -1
- package/dist/elements/chat-types.d.ts +70 -10
- package/dist/elements/chat-workspace.js +1 -1
- package/dist/elements/chat.js +1 -1
- package/dist/elements/checkpoint.js +1 -1
- package/dist/elements/choice.js +1 -1
- package/dist/elements/chunks/{Icon-Tj58ES_d.js → Icon-CHG5z5L7.js} +1 -1
- package/dist/elements/chunks/{action-icons-ns1Fnedj.js → action-icons-BAtCEEgg.js} +1 -1
- package/dist/elements/chunks/arrow-left-CFPTeL1Y.js +1 -0
- package/dist/elements/chunks/artifact-fBZOE4SO.js +1 -0
- package/dist/elements/chunks/{attachments-mCB5F1Fq.js → attachments-DpYMe5VQ.js} +1 -1
- package/dist/elements/chunks/audio-visualizer-DFwzAcuL.js +1 -0
- package/dist/elements/chunks/{badge-B4Zuajl2.js → badge-D6zodm6E.js} +1 -1
- package/dist/elements/chunks/{button-ZWNif3--.js → button-C42vrGvO.js} +1 -1
- package/dist/elements/chunks/card-renderer-DMZsSuvU.js +1 -0
- package/dist/elements/chunks/card-tags-D8lZ-C_U.js +1 -0
- package/dist/elements/chunks/chat-thread-CNNEhol-.js +1 -0
- package/dist/elements/chunks/check-7Q3K-iXE.js +1 -0
- package/dist/elements/chunks/chevron-down-CpNYLn7E.js +1 -0
- package/dist/elements/chunks/chevron-right-DrH85Fha.js +1 -0
- package/dist/elements/chunks/choice-card-YoWjpsFV.js +1 -0
- package/dist/elements/chunks/circle-C9KRjKYv.js +1 -0
- package/dist/elements/chunks/circle-check-Dmi7Y4zw.js +1 -0
- package/dist/elements/chunks/{circle-x-B7faJFlY.js → circle-x-QIxXda6k.js} +1 -1
- package/dist/elements/chunks/code-block-CqeugReY.js +1 -0
- package/dist/elements/chunks/{collapsible-DM1Ckd4e.js → collapsible-sTv-_5lF.js} +1 -1
- package/dist/elements/chunks/{composer-BguS0QL_.js → composer-ldQyeVEB.js} +2 -2
- package/dist/elements/chunks/confirm-card-C0RNOwfn.js +1 -0
- package/dist/elements/chunks/context-5qgypNHC.js +1 -0
- package/dist/elements/chunks/conversation-list-DLzOacXz.js +1 -0
- package/dist/elements/chunks/create-tween-V4TXZ93X.js +7 -0
- package/dist/elements/chunks/default-input-DeeRSDHc.js +1 -0
- package/dist/elements/chunks/define-lE-QvQFn.js +1 -0
- package/dist/elements/chunks/{disclosure-CIZ5c8nO.js → disclosure-DZSa9jog.js} +1 -1
- package/dist/elements/chunks/{download-Dsbg3ste.js → download-B2ZmnGqW.js} +1 -1
- package/dist/elements/chunks/{dropdown-BDd1-Zgi.js → dropdown-R3B7cSRE.js} +1 -1
- package/dist/elements/chunks/{ellipsis-Dw6qrss-.js → ellipsis-BmxceY4l.js} +1 -1
- package/dist/elements/chunks/embed-BVrtTZPo.js +1 -0
- package/dist/elements/chunks/{external-link-Vt74zAoL.js → external-link-BbdR7YO7.js} +1 -1
- package/dist/elements/chunks/{file-text-CZrZF6_v.js → file-text-D7dijo1A.js} +1 -1
- package/dist/elements/chunks/{file-tree-DF4okKyo.js → file-tree-0upJ5jeb.js} +1 -1
- package/dist/elements/chunks/{folder-glP5rha4.js → folder-D8z58t7B.js} +1 -1
- package/dist/elements/chunks/form-p5BKJNw5.js +1 -0
- package/dist/elements/chunks/hover-card-CN9s2md5.js +1 -0
- package/dist/elements/chunks/{icon-BLb8beoi.js → icon-CNiKP37E.js} +1 -1
- package/dist/elements/chunks/{info-CIsv92JK.js → info-BSnuJiHI.js} +1 -1
- package/dist/elements/chunks/{input-Dds1kFyt.js → input-BauDmzxX.js} +1 -1
- package/dist/elements/chunks/{kbd-De_xbgi9.js → kbd-BlHJaP9b.js} +1 -1
- package/dist/elements/chunks/{link-i4r_k7z4.js → link-DEi5iUWC.js} +1 -1
- package/dist/elements/chunks/link-preview-BaHyM6W4.js +1 -0
- package/dist/elements/chunks/{loader-BmQH4s3V.js → loader-CmJG_Fkq.js} +1 -1
- package/dist/elements/chunks/{markdown-Zi21WhUz.js → markdown-D2jaMpCN.js} +1 -1
- package/dist/elements/chunks/message-C5UfXZ2Z.js +1 -0
- package/dist/elements/chunks/message-CXWLmmLn.js +1 -0
- package/dist/elements/chunks/message-square-hXylwsy0.js +1 -0
- package/dist/elements/chunks/{minimize-2--ifeCGrl.js → minimize-2-C9ytZFMU.js} +1 -1
- package/dist/elements/chunks/model-switcher-CivGfD7-.js +1 -0
- package/dist/elements/chunks/{overlay-kD8dwRv_.js → overlay-DJL_sbOm.js} +1 -1
- package/dist/elements/chunks/{paperclip-q21dYOSK.js → paperclip-CFaB8naM.js} +1 -1
- package/dist/elements/chunks/{progress-bar-BrAIIaaJ.js → progress-bar-Br5SksfR.js} +1 -1
- package/dist/elements/chunks/{prompt-suggestion-Bjn2K-fR.js → prompt-suggestion-CMIvtAhU.js} +1 -1
- package/dist/elements/chunks/reasoning-DpZcNzLq.js +1 -0
- package/dist/elements/chunks/{resizable-Dp4JExql.js → resizable-Q8i3T9a_.js} +1 -1
- package/dist/elements/chunks/{rotate-cw-CFWWkpj2.js → rotate-cw-B5IHCBFV.js} +1 -1
- package/dist/elements/chunks/{scroll-area-Bb0kHH1j.js → scroll-area-eLeydBje.js} +1 -1
- package/dist/elements/chunks/scroll-button-DWbz0yA1.js +1 -0
- package/dist/elements/chunks/{separator-9kRgr1X9.js → separator-Xic78AD_.js} +1 -1
- package/dist/elements/chunks/{settings-B8lmec4D.js → settings-B8H51pAx.js} +1 -1
- package/dist/elements/chunks/{settings-group-I0hEuXiN.js → settings-group-CsG9eYLe.js} +1 -1
- package/dist/elements/chunks/{share-C3lTiYGt.js → share-CNTx0z__.js} +1 -1
- package/dist/elements/chunks/skeleton-CLlHTcMI.js +1 -0
- package/dist/elements/chunks/slots-CIw9RlAe.js +1 -0
- package/dist/elements/chunks/source-BoVcU5ok.js +1 -0
- package/dist/elements/chunks/{star-CSJtGxgv.js → star-CxQVTVhI.js} +1 -1
- package/dist/elements/chunks/{store-CHyW95TP.js → store-CLtS5CUG.js} +1 -1
- package/dist/elements/chunks/tasks-card-CzlkLmUt.js +1 -0
- package/dist/elements/chunks/{text-shimmer-Cn9TmNpI.js → text-shimmer-D5NhpIQ1.js} +1 -1
- package/dist/elements/chunks/textarea-x5Uxsmtm.js +1 -0
- package/dist/elements/chunks/{thumbs-up-PNVVThEF.js → thumbs-up-UobcJnx9.js} +1 -1
- package/dist/elements/chunks/{toast-store-DKbQn3Wn.js → toast-store-BOfs9eXq.js} +1 -1
- package/dist/elements/chunks/{tool-DjTRpIpl.js → tool-Be6Dh_dt.js} +1 -1
- package/dist/elements/chunks/tooltip-RxMxyCLF.js +1 -0
- package/dist/elements/chunks/{triangle-alert-DsHTHCPm.js → triangle-alert-C4yxH2XN.js} +1 -1
- package/dist/elements/chunks/use-card-resolution-jva9ehH6.js +1 -0
- package/dist/elements/chunks/{variant-aurora-Dc4nQUia.js → variant-aurora-Dx4VRcjS.js} +2 -2
- package/dist/elements/chunks/{variant-custom-y_3kVQhS.js → variant-custom-Y1ZTWgEa.js} +1 -1
- package/dist/elements/chunks/{variant-wave-D5OR1-9Z.js → variant-wave-B9gml9Cg.js} +2 -2
- package/dist/elements/chunks/{video-B7vmenoC.js → video-CrPHsytT.js} +1 -1
- package/dist/elements/chunks/x-_-OPHept.js +1 -0
- package/dist/elements/coachmark.js +1 -1
- package/dist/elements/code-block.js +1 -1
- package/dist/elements/command.js +1 -1
- package/dist/elements/compare.js +1 -1
- package/dist/elements/composer.js +1 -1
- package/dist/elements/confirm-card.js +1 -1
- package/dist/elements/context-meter.js +1 -1
- package/dist/elements/conversation-list.js +1 -1
- package/dist/elements/default-input.d.ts +34 -7
- package/dist/elements/define.d.ts +1 -0
- package/dist/elements/dialog.js +1 -1
- package/dist/elements/disclosure.d.ts +1 -1
- package/dist/elements/editable-label.js +1 -1
- package/dist/elements/element-data-types.d.ts +107 -0
- package/dist/elements/embed.js +1 -1
- package/dist/elements/empty.js +1 -1
- package/dist/elements/feedback-bar.js +1 -1
- package/dist/elements/file-tree.js +1 -1
- package/dist/elements/file-upload.js +1 -1
- package/dist/elements/form.js +1 -1
- package/dist/elements/hover-card.js +1 -1
- package/dist/elements/icon.js +1 -1
- package/dist/elements/image.js +1 -1
- package/dist/elements/input.js +1 -1
- package/dist/elements/kbd.js +1 -1
- package/dist/elements/link-preview.js +1 -1
- package/dist/elements/loader.js +1 -1
- package/dist/elements/markdown.js +1 -1
- package/dist/elements/menu.js +1 -1
- package/dist/elements/message-skills.js +1 -1
- package/dist/elements/message.js +1 -1
- package/dist/elements/model-switcher.js +1 -1
- package/dist/elements/nav.js +1 -1
- package/dist/elements/notice.js +1 -1
- package/dist/elements/pane-group.js +1 -1
- package/dist/elements/pane.js +1 -1
- package/dist/elements/popover.js +1 -1
- package/dist/elements/progress-bar.js +1 -1
- package/dist/elements/prompt-dock.js +1 -1
- package/dist/elements/prompt-input.js +1 -1
- package/dist/elements/prompt-suggestions.js +1 -1
- package/dist/elements/reasoning.js +1 -1
- package/dist/elements/register.d.ts +8 -6
- package/dist/elements/remote.js +1 -1
- package/dist/elements/resizable.js +1 -1
- package/dist/elements/response-stream.js +1 -1
- package/dist/elements/screen.js +1 -1
- package/dist/elements/scroll-area.js +1 -1
- package/dist/elements/scroll-button.js +1 -1
- package/dist/elements/search.js +1 -1
- package/dist/elements/segmented.js +1 -1
- package/dist/elements/separator.js +1 -1
- package/dist/elements/setting-item.js +1 -1
- package/dist/elements/settings-group.js +1 -1
- package/dist/elements/skeleton.js +1 -1
- package/dist/elements/slot-text.d.ts +51 -0
- package/dist/elements/slots.d.ts +21 -0
- package/dist/elements/source.js +1 -1
- package/dist/elements/status.js +1 -1
- package/dist/elements/switch.js +1 -1
- package/dist/elements/tabs.js +1 -1
- package/dist/elements/tasks.js +1 -1
- package/dist/elements/text-shimmer.js +1 -1
- package/dist/elements/thinking-bar.js +1 -1
- package/dist/elements/thread.js +1 -1
- package/dist/elements/toast.js +1 -1
- package/dist/elements/tool.js +1 -1
- package/dist/elements/tooltip.js +1 -1
- package/dist/elements/validate-messages.d.ts +25 -0
- package/dist/elements/voice-input.js +1 -1
- package/dist/elements/voice-output.js +1 -1
- package/dist/elements.d.ts +2734 -217
- package/dist/index.d.ts +163 -125
- package/dist/index.js +6572 -5990
- package/dist/index.server.d.ts +5 -0
- package/dist/index.server.js +5403 -4860
- package/dist/kai-provider.es.d.ts +5 -0
- package/dist/kai-provider.es.js +79 -77
- package/dist/kai.es.d.ts +5 -0
- package/dist/kai.es.js +1 -1
- package/dist/llms/llms-full.txt +774 -151
- package/dist/llms/llms.txt +57 -5
- package/dist/mcp.es.js +4756 -782
- package/dist/primitives/card-component-types.d.ts +11 -0
- package/dist/primitives/card-data-types.d.ts +196 -0
- package/dist/primitives/card-host.d.ts +1 -1
- package/dist/primitives/card-recovery.d.ts +3 -3
- package/dist/primitives/card-registry.d.ts +4 -14
- package/dist/primitives/card-resolution.d.ts +1 -1
- package/dist/primitives/card-routing.d.ts +1 -1
- package/dist/primitives/card-tags.d.ts +11 -0
- package/dist/primitives/card-validate-cards.d.ts +57 -0
- package/dist/primitives/card-validate-generator.testlib.d.ts +20 -0
- package/dist/primitives/card-validate-schemas.d.ts +17 -0
- package/dist/primitives/card-validate.d.ts +24 -0
- package/dist/primitives/create-kai-chat.d.ts +3 -3
- package/dist/primitives/embed-providers.d.ts +1 -1
- package/dist/primitives/link-preview.d.ts +1 -1
- package/dist/primitives/message-feedback.d.ts +2 -2
- package/dist/primitives/toast-store.d.ts +1 -1
- package/dist/react/index.d.ts +730 -302
- package/dist/react/use-kai-chat.d.ts +8 -4
- package/dist/react.d.ts +5 -0
- package/dist/react.js +418 -317
- package/dist/register-impl-AxIlqjo7.js +145 -0
- package/dist/remote/host-embed.d.ts +1 -1
- package/dist/remote/index.d.ts +2 -2
- package/dist/remote/provider-runtime.d.ts +2 -2
- package/dist/remote/provider.d.ts +2 -2
- package/dist/remote/validate.d.ts +1 -1
- package/dist/remote/wire.d.ts +1 -1
- package/dist/schemas/artifact.schema.json +92 -0
- package/dist/schemas/embed.schema.json +0 -2
- package/dist/schemas/from-tool-call.d.ts +48 -0
- package/dist/schemas/index.d.ts +48 -0
- package/dist/schemas/link.schema.json +0 -2
- package/dist/schemas/provider-subsets.d.ts +136 -0
- package/dist/schemas/registry.d.ts +140 -0
- package/dist/schemas/tool-defs.d.ts +121 -0
- package/dist/schemas.d.ts +5 -0
- package/dist/schemas.js +717 -0
- package/dist/solid-BGYSJyHG.js +22960 -0
- package/dist/solid-Dt2nEwfl.js +20194 -0
- package/dist/solid.d.ts +66 -0
- package/dist/solid.js +261 -0
- package/dist/solid.server.d.ts +5 -0
- package/dist/solid.server.js +261 -0
- package/dist/state/index.d.ts +14 -4
- package/dist/state/messages.d.ts +8 -3
- package/dist/state/mock.d.ts +46 -0
- package/dist/state/parts.d.ts +85 -0
- package/dist/state/stream.d.ts +15 -9
- package/dist/state.d.ts +5 -0
- package/dist/state.js +253 -84
- package/dist/ui/action-icons.d.ts +1 -1
- package/dist/ui/collapsible.d.ts +11 -6
- package/dist/ui/dropdown.d.ts +47 -42
- package/dist/ui/pane-group.d.ts +1 -1
- package/dist/{variant-aurora-DVtGqVH6.js → variant-aurora-B44X69AG.js} +1 -1
- package/dist/variant-aurora-BRhV8Flk.js +391 -0
- package/dist/variant-aurora-Ds5ou9BH.js +381 -0
- package/dist/variant-custom-B20FhtYj.js +170 -0
- package/dist/{variant-custom-Dif-IV4u.js → variant-custom-BvA1Schl.js} +1 -1
- package/dist/variant-custom-D6Rtvneb.js +200 -0
- package/dist/{variant-wave-DbfNdvSi.js → variant-wave-BUQtkryq.js} +1 -1
- package/dist/variant-wave-BVYnqy9L.js +218 -0
- package/dist/variant-wave-DXC6_LcH.js +208 -0
- package/dist/wire/chunk.d.ts +171 -0
- package/dist/wire/consume.d.ts +26 -0
- package/dist/wire/encode.d.ts +221 -0
- package/dist/wire/files.d.ts +116 -0
- package/dist/wire/formats/anthropic.d.ts +2 -0
- package/dist/wire/formats/openai.d.ts +5 -0
- package/dist/wire/index.d.ts +16 -0
- package/dist/wire/media-types.d.ts +106 -0
- package/dist/wire/read.d.ts +26 -0
- package/dist/wire/sink-helpers.d.ts +21 -0
- package/dist/wire/sse.d.ts +33 -0
- package/dist/wire.d.ts +5 -53
- package/dist/wire.js +1126 -0
- package/frameworks/react/index.tsx +191 -158
- package/frameworks/react/runtime.tsx +21 -1
- package/frameworks/react/use-kai-chat.tsx +11 -1
- package/llms-full.txt +774 -151
- package/llms.txt +57 -5
- package/package.json +62 -8
- package/src/agent-tooling/archetypes.ts +127 -0
- package/src/agent-tooling/integrations/anthropic.ts +436 -0
- package/src/agent-tooling/integrations/cloudflare.ts +141 -52
- package/src/agent-tooling/integrations/langgraph.ts +80 -13
- package/src/agent-tooling/integrations/mastra.ts +161 -12
- package/src/agent-tooling/integrations/mock.ts +47 -8
- package/src/agent-tooling/integrations/ollama.ts +68 -24
- package/src/agent-tooling/integrations/openai.ts +89 -0
- package/src/agent-tooling/integrations/openrouter.ts +58 -8
- package/src/agent-tooling/integrations/pi.ts +104 -23
- package/src/agent-tooling/integrations/pydantic-ai.ts +61 -5
- package/src/agent-tooling/integrations/vercel-ai-sdk.ts +120 -13
- package/src/agent-tooling/mcp/manifest.ts +206 -25
- package/src/agent-tooling/mcp/tools/debug.ts +13 -7
- package/src/agent-tooling/mcp/tools/reference.ts +285 -6
- package/src/agent-tooling/mcp/tools/scaffold.ts +4152 -661
- package/src/agent-tooling/registry.ts +74 -0
- package/src/agent-tooling/types.ts +361 -1
- package/src/components/artifact-card.tsx +120 -0
- package/src/components/audio-visualizer/index.tsx +9 -0
- package/src/components/audio-visualizer/labs/lab-choreography.ts +187 -0
- package/src/components/audio-visualizer/labs/lab-shaders.ts +363 -0
- package/src/components/audio-visualizer/labs/lab-visualizer.tsx +102 -0
- package/src/components/audio-visualizer/shader-canvas.tsx +31 -1
- package/src/components/card-fallback.tsx +42 -10
- package/src/components/card-renderer.tsx +146 -9
- package/src/components/chat-container.tsx +4 -0
- package/src/components/chat-thread.tsx +128 -52
- package/src/components/choice-card.tsx +17 -29
- package/src/components/composer.tsx +12 -2
- package/src/components/confirm-card.tsx +24 -20
- package/src/components/context.tsx +30 -16
- package/src/components/conversation-item.tsx +6 -0
- package/src/components/conversation-list.tsx +18 -2
- package/src/components/file-tree.tsx +11 -22
- package/src/components/file-upload.tsx +14 -8
- package/src/components/form.tsx +14 -47
- package/src/components/loader.tsx +39 -12
- package/src/components/message-skills.tsx +4 -0
- package/src/components/message.tsx +294 -46
- package/src/components/model-switcher.tsx +38 -8
- package/src/components/reasoning.tsx +92 -5
- package/src/components/response-compare-types.ts +25 -0
- package/src/components/response-compare.tsx +4 -9
- package/src/components/source.tsx +50 -24
- package/src/components/tasks-card.tsx +10 -33
- package/src/components/thread.tsx +84 -42
- package/src/components/toast.tsx +17 -6
- package/src/components/tool-classify.ts +26 -0
- package/src/components/tool-types.ts +31 -1
- package/src/elements/agent-card.tsx +11 -11
- package/src/elements/artifact.tsx +15 -7
- package/src/elements/attachments.tsx +6 -4
- package/src/elements/avatar.tsx +1 -1
- package/src/elements/button.tsx +29 -6
- package/src/elements/card.tsx +2 -2
- package/src/elements/cards.tsx +109 -14
- package/src/elements/chain-of-thought.tsx +14 -10
- package/src/elements/chat-scope-picker.tsx +9 -7
- package/src/elements/chat-types.ts +59 -6
- package/src/elements/chat-workspace.tsx +50 -9
- package/src/elements/chat.tsx +90 -3
- package/src/elements/choice.tsx +8 -8
- package/src/elements/coachmark.tsx +1 -1
- package/src/elements/command.tsx +8 -23
- package/src/elements/compare.tsx +7 -6
- package/src/elements/compiled.css +1 -1
- package/src/elements/composer.tsx +8 -8
- package/src/elements/confirm-card.tsx +9 -9
- package/src/elements/context-meter.tsx +4 -18
- package/src/elements/conversation-list.tsx +14 -9
- package/src/elements/default-input.tsx +131 -8
- package/src/elements/define.tsx +178 -43
- package/src/elements/editable-label.tsx +17 -2
- package/src/elements/element-data-types.ts +112 -0
- package/src/elements/element-meta.json +1624 -306
- package/src/elements/element-types.d.ts +2645 -214
- package/src/elements/feedback-bar.tsx +1 -1
- package/src/elements/file-tree.tsx +1 -1
- package/src/elements/file-upload.tsx +1 -1
- package/src/elements/form.tsx +14 -6
- package/src/elements/input.tsx +1 -1
- package/src/elements/kbd.tsx +1 -1
- package/src/elements/menu.tsx +40 -32
- package/src/elements/message-skills.tsx +7 -9
- package/src/elements/message.tsx +200 -32
- package/src/elements/model-switcher.tsx +5 -3
- package/src/elements/pane.tsx +1 -1
- package/src/elements/prompt-dock.tsx +8 -8
- package/src/elements/prompt-input.tsx +10 -10
- package/src/elements/prompt-suggestions.tsx +7 -4
- package/src/elements/reasoning.tsx +1 -1
- package/src/elements/register.ts +9 -0
- package/src/elements/resizable.globals.d.ts +36 -0
- package/src/elements/resizable.tsx +24 -13
- package/src/elements/response-stream.tsx +1 -1
- package/src/elements/scroll-button.tsx +1 -1
- package/src/elements/search.tsx +6 -1
- package/src/elements/segmented.tsx +5 -11
- package/src/elements/separator.tsx +1 -1
- package/src/elements/slot-text.ts +73 -0
- package/src/elements/slots.ts +67 -24
- package/src/elements/source.tsx +21 -22
- package/src/elements/switch.tsx +3 -3
- package/src/elements/tasks.tsx +5 -4
- package/src/elements/thread.tsx +36 -4
- package/src/elements/toast.tsx +3 -2
- package/src/elements/tool.tsx +1 -1
- package/src/elements/validate-messages.ts +76 -0
- package/src/elements/voice-input.tsx +7 -7
- package/src/elements/voice-output.tsx +4 -4
- package/src/index.ts +145 -6
- package/src/primitives/card-component-types.ts +63 -0
- package/src/primitives/card-data-types.ts +312 -0
- package/src/primitives/card-recovery.ts +13 -2
- package/src/primitives/card-registry.tsx +34 -23
- package/src/primitives/card-schemas/artifact.schema.json +92 -0
- package/src/primitives/card-schemas/embed.schema.json +0 -2
- package/src/primitives/card-schemas/link.schema.json +0 -2
- package/src/primitives/card-tags.ts +61 -0
- package/src/primitives/card-validate-cards.ts +255 -0
- package/src/primitives/card-validate-generator.testlib.ts +38 -0
- package/src/primitives/card-validate-schemas.ts +58 -0
- package/src/primitives/card-validate.ts +48 -20
- package/src/primitives/create-tween.ts +54 -2
- package/src/primitives/message-feedback.ts +3 -2
- package/src/primitives/use-audio-analysis.ts +20 -1
- package/src/primitives/use-sequencer.ts +20 -1
- package/src/schemas/from-tool-call.ts +151 -0
- package/src/schemas/index.ts +340 -0
- package/src/schemas/provider-subsets.ts +538 -0
- package/src/schemas/registry.ts +355 -0
- package/src/schemas/tool-defs.ts +492 -0
- package/src/solid.ts +150 -0
- package/src/state/index.ts +27 -1
- package/src/state/messages.ts +21 -4
- package/src/state/mock.ts +211 -0
- package/src/state/parts.ts +295 -0
- package/src/state/stream.ts +56 -58
- package/src/ui/collapsible.tsx +17 -5
- package/src/ui/dropdown.tsx +46 -12
- package/src/ui/overlay.tsx +10 -4
- package/src/wire/chunk.ts +201 -0
- package/src/wire/consume.ts +440 -0
- package/src/wire/encode.ts +689 -0
- package/src/wire/files.ts +342 -0
- package/src/wire/formats/anthropic.ts +267 -0
- package/src/wire/formats/openai.ts +187 -0
- package/src/wire/index.ts +73 -0
- package/src/wire/media-types.ts +344 -0
- package/src/wire/read.ts +152 -0
- package/src/wire/sink-helpers.ts +50 -0
- package/src/wire/sse.ts +140 -0
- package/dist/create-tween-hvpmSuwW.js +0 -7
- package/dist/elements/chunks/arrow-left-DQocUFvy.js +0 -1
- package/dist/elements/chunks/audio-visualizer-BqNy7dfm.js +0 -1
- package/dist/elements/chunks/card-BkHbp4BA.js +0 -1
- package/dist/elements/chunks/chat-thread-CkRN6pZ7.js +0 -1
- package/dist/elements/chunks/check-B9-gn6SS.js +0 -1
- package/dist/elements/chunks/chevron-down-BNsxc2hk.js +0 -1
- package/dist/elements/chunks/chevron-right-Hv00StBO.js +0 -1
- package/dist/elements/chunks/circle-0e3KJTDr.js +0 -1
- package/dist/elements/chunks/circle-check-BNAS0JEy.js +0 -1
- package/dist/elements/chunks/code-block-BFUHn6Va.js +0 -1
- package/dist/elements/chunks/context-Cb7k4F-v.js +0 -1
- package/dist/elements/chunks/conversation-list-CvoAkWhN.js +0 -1
- package/dist/elements/chunks/create-tween-oVvAIG8r.js +0 -7
- package/dist/elements/chunks/default-input-Cqqilg9t.js +0 -1
- package/dist/elements/chunks/define-D1din7Ld.js +0 -1
- package/dist/elements/chunks/hover-card-Cmm6Q53m.js +0 -1
- package/dist/elements/chunks/message-BqyXDN3-.js +0 -1
- package/dist/elements/chunks/message-feedback-Djr3z6Yb.js +0 -1
- package/dist/elements/chunks/message-square-vFAgbDaX.js +0 -1
- package/dist/elements/chunks/model-switcher-B94YAKsM.js +0 -1
- package/dist/elements/chunks/reasoning-DTpCGtnY.js +0 -1
- package/dist/elements/chunks/scroll-button-B0cH5fXf.js +0 -1
- package/dist/elements/chunks/skeleton-DSXW5Yya.js +0 -1
- package/dist/elements/chunks/slots--V19HwUb.js +0 -1
- package/dist/elements/chunks/textarea-CUwqAX0G.js +0 -1
- package/dist/elements/chunks/tooltip-CgBZCVKp.js +0 -1
- package/dist/elements/chunks/use-card-resolution-BSu_XHjH.js +0 -1
- package/dist/elements/chunks/x-GRUeeQFT.js +0 -1
- package/dist/host-embed.d.ts +0 -33
- package/dist/kai-provider.d.ts +0 -2
- package/dist/origin.d.ts +0 -5
- package/dist/provider-runtime.d.ts +0 -27
- package/dist/register-impl-DQyejdfb.js +0 -145
- package/dist/validate.d.ts +0 -4
- package/dist/version.d.ts +0 -4
- package/src/components/component-meta.json +0 -4550
- package/src/elements/card-media.jpg +0 -0
- package/src/elements/resizable.d.ts +0 -27
- package/src/elements/video-poster.jpg +0 -0
package/src/state/stream.ts
CHANGED
|
@@ -1,73 +1,72 @@
|
|
|
1
1
|
// src/state/stream.ts
|
|
2
|
-
import type { ChatMessage } from '../elements/chat-types';
|
|
2
|
+
import type { ChatMessage, MessagePart, Source } from '../elements/chat-types';
|
|
3
3
|
import type { ToolPart } from '../components/tool-types';
|
|
4
|
+
import type { CardEnvelope } from '../primitives/card-contract';
|
|
5
|
+
import type { AttachmentData } from '../components/attachment-types';
|
|
6
|
+
import { appendReasoningPart, appendTextPart, upsertCardPart, upsertToolPart, type ReasoningOpts } from './parts';
|
|
4
7
|
|
|
5
8
|
/** The one universal contract: a functional-updater setter (React setState shape). */
|
|
6
9
|
export type SetMessages = (updater: (prev: ChatMessage[]) => ChatMessage[]) => void;
|
|
7
10
|
|
|
11
|
+
function newId(): string {
|
|
12
|
+
if (typeof crypto !== 'undefined' && crypto.randomUUID) return crypto.randomUUID();
|
|
13
|
+
return 'kai-' + Math.random().toString(36).slice(2);
|
|
14
|
+
}
|
|
15
|
+
|
|
8
16
|
/** A fluent builder for one in-flight assistant message. Owns no state. */
|
|
9
17
|
export interface AssistantStream {
|
|
10
18
|
readonly id: string;
|
|
11
19
|
appendText(delta: string): AssistantStream;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
appendReasoning(delta: string, opts?: ReasoningOpts): AssistantStream;
|
|
21
|
+
upsertTool(toolCallId: string, patch: Partial<ToolPart>): AssistantStream;
|
|
22
|
+
/** Adds a card, or REPLACES the existing one with the same `envelope.id`. A
|
|
23
|
+
* model that revises a card mid-turn re-sends the whole envelope, so a second
|
|
24
|
+
* call with a known id revises that card in place rather than rendering a
|
|
25
|
+
* second copy of it. See `upsertCardPart`. */
|
|
26
|
+
addCard(envelope: CardEnvelope): AssistantStream;
|
|
27
|
+
addSource(source: Source): AssistantStream;
|
|
28
|
+
addFile(attachment: AttachmentData): AssistantStream;
|
|
29
|
+
done(): void;
|
|
19
30
|
abort(reason?: string): void;
|
|
20
31
|
}
|
|
21
32
|
|
|
22
|
-
function newId(): string {
|
|
23
|
-
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') return crypto.randomUUID();
|
|
24
|
-
return 'kai-' + Math.random().toString(36).slice(2);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
33
|
/** Start an assistant message and drive it through `set`. New refs on every mutation. */
|
|
28
|
-
export function createAssistantStream(
|
|
34
|
+
export function createAssistantStream(
|
|
35
|
+
set: SetMessages,
|
|
36
|
+
init: Partial<ChatMessage> = {},
|
|
37
|
+
): AssistantStream {
|
|
29
38
|
const id = init.id ?? newId();
|
|
30
|
-
|
|
31
|
-
|
|
39
|
+
let settled = false;
|
|
40
|
+
|
|
41
|
+
set((prev) => [...prev, { id, role: 'assistant', parts: [], ...init }]);
|
|
32
42
|
|
|
33
|
-
const mutate = (fn: (
|
|
34
|
-
|
|
43
|
+
const mutate = (fn: (parts: MessagePart[]) => MessagePart[]) => {
|
|
44
|
+
if (settled) return;
|
|
45
|
+
set((prev) => {
|
|
46
|
+
const i = prev.findIndex((m) => m.id === id);
|
|
47
|
+
if (i < 0) return prev;
|
|
48
|
+
const next = fn(prev[i].parts);
|
|
49
|
+
if (next === prev[i].parts) return prev;
|
|
50
|
+
return [...prev.slice(0, i), { ...prev[i], parts: next }, ...prev.slice(i + 1)];
|
|
51
|
+
});
|
|
52
|
+
};
|
|
35
53
|
|
|
36
54
|
const stream: AssistantStream = {
|
|
37
55
|
id,
|
|
38
|
-
appendText(delta) { mutate((
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
},
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return stream;
|
|
47
|
-
},
|
|
48
|
-
upsertTool(tool) {
|
|
49
|
-
mutate((m) => {
|
|
50
|
-
const tools = m.tools ? m.tools.slice() : [];
|
|
51
|
-
const i = tool.toolCallId != null
|
|
52
|
-
? tools.findIndex((t) => t.toolCallId === tool.toolCallId)
|
|
53
|
-
: tools.findIndex((t) => t.type === tool.type);
|
|
54
|
-
if (i === -1) tools.push(tool); else tools[i] = tool;
|
|
55
|
-
return { ...m, tools };
|
|
56
|
-
});
|
|
57
|
-
return stream;
|
|
58
|
-
},
|
|
59
|
-
updateTool(toolCallId, patch) {
|
|
60
|
-
mutate((m) => ({ ...m, tools: (m.tools ?? []).map((t) => (t.toolCallId === toolCallId ? { ...t, ...patch } : t)) }));
|
|
61
|
-
return stream;
|
|
62
|
-
},
|
|
63
|
-
patch(patch) { mutate((m) => ({ ...m, ...patch })); return stream; },
|
|
64
|
-
done(final) { if (final) mutate((m) => ({ ...m, ...final })); },
|
|
56
|
+
appendText(delta) { mutate((p) => appendTextPart(p, delta)); return stream; },
|
|
57
|
+
appendReasoning(delta, opts) { mutate((p) => appendReasoningPart(p, delta, opts)); return stream; },
|
|
58
|
+
upsertTool(toolCallId, patch) { mutate((p) => upsertToolPart(p, toolCallId, patch)); return stream; },
|
|
59
|
+
// Upsert, not append: keyed on envelope.id so a revised card replaces itself.
|
|
60
|
+
addCard(envelope) { mutate((p) => upsertCardPart(p, envelope)); return stream; },
|
|
61
|
+
addSource(source) { mutate((p) => [...p, { type: 'source', source }]); return stream; },
|
|
62
|
+
addFile(attachment) { mutate((p) => [...p, { type: 'file', attachment }]); return stream; },
|
|
63
|
+
done() { settled = true; },
|
|
65
64
|
abort(reason) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
mutate((p) => p.map((part) =>
|
|
66
|
+
part.type === 'tool' && part.tool.state !== 'output-available'
|
|
67
|
+
? { ...part, tool: { ...part.tool, state: 'output-error' as const, errorText: reason } }
|
|
68
|
+
: part));
|
|
69
|
+
settled = true;
|
|
71
70
|
},
|
|
72
71
|
};
|
|
73
72
|
return stream;
|
|
@@ -78,14 +77,13 @@ export function createAssistantStream(set: SetMessages, init: Partial<ChatMessag
|
|
|
78
77
|
export function onStreamSettled(inner: AssistantStream, onSettle: () => void): AssistantStream {
|
|
79
78
|
const wrapper: AssistantStream = {
|
|
80
79
|
id: inner.id,
|
|
81
|
-
appendText(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
done(final) { inner.done(final); onSettle(); },
|
|
80
|
+
appendText(delta) { inner.appendText(delta); return wrapper; },
|
|
81
|
+
appendReasoning(delta, opts) { inner.appendReasoning(delta, opts); return wrapper; },
|
|
82
|
+
upsertTool(toolCallId, patch) { inner.upsertTool(toolCallId, patch); return wrapper; },
|
|
83
|
+
addCard(envelope) { inner.addCard(envelope); return wrapper; },
|
|
84
|
+
addSource(source) { inner.addSource(source); return wrapper; },
|
|
85
|
+
addFile(attachment) { inner.addFile(attachment); return wrapper; },
|
|
86
|
+
done() { inner.done(); onSettle(); },
|
|
89
87
|
abort(reason) { inner.abort(reason); onSettle(); },
|
|
90
88
|
};
|
|
91
89
|
return wrapper;
|
package/src/ui/collapsible.tsx
CHANGED
|
@@ -39,7 +39,7 @@ const useCollapsible = () => {
|
|
|
39
39
|
* (no `open` prop); in controlled mode the parent already owns the state. */
|
|
40
40
|
export interface CollapsibleController { open: Accessor<boolean>; setOpen: (v: boolean) => void; }
|
|
41
41
|
|
|
42
|
-
export
|
|
42
|
+
export interface CollapsibleProps {
|
|
43
43
|
open?: boolean;
|
|
44
44
|
defaultOpen?: boolean;
|
|
45
45
|
onOpenChange?: (open: boolean) => void;
|
|
@@ -51,7 +51,9 @@ export function Collapsible(props: {
|
|
|
51
51
|
controllerRef?: (api: CollapsibleController) => void;
|
|
52
52
|
children: JSX.Element;
|
|
53
53
|
class?: string;
|
|
54
|
-
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function Collapsible(props: CollapsibleProps) {
|
|
55
57
|
const [local, rest] = splitProps(props, ['open', 'defaultOpen', 'onOpenChange', 'disabled', 'controllerRef', 'children', 'class']);
|
|
56
58
|
const [uncontrolled, setUncontrolled] = createSignal(local.defaultOpen ?? false);
|
|
57
59
|
const isControlled = () => local.open !== undefined;
|
|
@@ -88,13 +90,16 @@ export function Collapsible(props: {
|
|
|
88
90
|
);
|
|
89
91
|
}
|
|
90
92
|
|
|
91
|
-
export
|
|
93
|
+
export interface CollapsibleTriggerProps {
|
|
92
94
|
children?: JSX.Element;
|
|
93
95
|
class?: string;
|
|
94
96
|
as?: (props: Record<string, any>) => JSX.Element;
|
|
95
97
|
onClick?: JSX.EventHandlerUnion<HTMLButtonElement, MouseEvent>;
|
|
98
|
+
/** Remaining attributes are spread onto the rendered trigger. */
|
|
96
99
|
[k: string]: any;
|
|
97
|
-
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function CollapsibleTrigger(props: CollapsibleTriggerProps) {
|
|
98
103
|
const ctx = useCollapsible();
|
|
99
104
|
const [local, rest] = splitProps(props, ['children', 'class', 'as', 'onClick']);
|
|
100
105
|
|
|
@@ -130,7 +135,14 @@ export function CollapsibleTrigger(props: {
|
|
|
130
135
|
);
|
|
131
136
|
}
|
|
132
137
|
|
|
133
|
-
export
|
|
138
|
+
export interface CollapsibleContentProps {
|
|
139
|
+
children?: JSX.Element;
|
|
140
|
+
class?: string;
|
|
141
|
+
/** Remaining attributes are spread onto the rendered panel. */
|
|
142
|
+
[k: string]: any;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function CollapsibleContent(props: CollapsibleContentProps) {
|
|
134
146
|
const ctx = useCollapsible();
|
|
135
147
|
const [local, rest] = splitProps(props, ['children', 'class']);
|
|
136
148
|
return (
|
package/src/ui/dropdown.tsx
CHANGED
|
@@ -41,7 +41,7 @@ const ITEM_SELECTOR = '[role="menuitem"]:not([aria-disabled="true"]), [role="men
|
|
|
41
41
|
* `controllerRef` so it can drive/observe the Dropdown's open state. */
|
|
42
42
|
export interface DropdownController { open: Accessor<boolean>; setOpen: (v: boolean) => void; }
|
|
43
43
|
|
|
44
|
-
export
|
|
44
|
+
export interface DropdownProps {
|
|
45
45
|
children: JSX.Element;
|
|
46
46
|
/** Initial open state (uncontrolled seed). */
|
|
47
47
|
defaultOpen?: boolean;
|
|
@@ -49,7 +49,41 @@ export function Dropdown(props: {
|
|
|
49
49
|
disabled?: boolean;
|
|
50
50
|
/** Receive the open controller (open accessor + setOpen) once mounted. */
|
|
51
51
|
controllerRef?: (api: DropdownController) => void;
|
|
52
|
-
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface DropdownTriggerProps {
|
|
55
|
+
/** Render as a different tag/component; defaults to a button. */
|
|
56
|
+
as?: AsTag;
|
|
57
|
+
children?: JSX.Element;
|
|
58
|
+
class?: string;
|
|
59
|
+
/** Remaining attributes are spread onto the rendered trigger. */
|
|
60
|
+
[k: string]: unknown;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface DropdownContentProps { children: JSX.Element; class?: string }
|
|
64
|
+
|
|
65
|
+
export interface DropdownItemProps {
|
|
66
|
+
children: JSX.Element;
|
|
67
|
+
class?: string;
|
|
68
|
+
onSelect?: () => void;
|
|
69
|
+
disabled?: boolean;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface DropdownSeparatorProps { class?: string }
|
|
73
|
+
|
|
74
|
+
export interface DropdownLabelProps { children: JSX.Element; class?: string }
|
|
75
|
+
|
|
76
|
+
export interface DropdownCheckboxItemProps extends DropdownItemProps { checked?: boolean }
|
|
77
|
+
|
|
78
|
+
export interface DropdownRadioItemProps extends DropdownItemProps { checked?: boolean }
|
|
79
|
+
|
|
80
|
+
export interface DropdownSubProps { children: JSX.Element }
|
|
81
|
+
|
|
82
|
+
export interface DropdownSubTriggerProps { children: JSX.Element; class?: string }
|
|
83
|
+
|
|
84
|
+
export interface DropdownSubContentProps { children: JSX.Element; class?: string }
|
|
85
|
+
|
|
86
|
+
export function Dropdown(props: DropdownProps) {
|
|
53
87
|
const [open, setOpenSig] = createSignal(props.defaultOpen ?? false);
|
|
54
88
|
const [viaKb, setViaKb] = createSignal(false);
|
|
55
89
|
const [trigger, setTrigger] = createSignal<HTMLElement>();
|
|
@@ -95,7 +129,7 @@ export function Dropdown(props: {
|
|
|
95
129
|
);
|
|
96
130
|
}
|
|
97
131
|
|
|
98
|
-
export function DropdownTrigger(props:
|
|
132
|
+
export function DropdownTrigger(props: DropdownTriggerProps) {
|
|
99
133
|
const ctx = useDropdown();
|
|
100
134
|
// Forward extra attributes (e.g. aria-label for an icon-only trigger). The
|
|
101
135
|
// controlled wiring below (id/aria-*/onClick/onKeyDown/class/type) is applied
|
|
@@ -126,7 +160,7 @@ export function DropdownTrigger(props: { as?: AsTag; children?: JSX.Element; cla
|
|
|
126
160
|
);
|
|
127
161
|
}
|
|
128
162
|
|
|
129
|
-
export function DropdownContent(props:
|
|
163
|
+
export function DropdownContent(props: DropdownContentProps) {
|
|
130
164
|
const ctx = useDropdown();
|
|
131
165
|
const config = useChatConfig();
|
|
132
166
|
const presence = createPresence(ctx.open);
|
|
@@ -221,7 +255,7 @@ export function DropdownContent(props: { children: JSX.Element; class?: string }
|
|
|
221
255
|
);
|
|
222
256
|
}
|
|
223
257
|
|
|
224
|
-
export function DropdownItem(props:
|
|
258
|
+
export function DropdownItem(props: DropdownItemProps) {
|
|
225
259
|
const ctx = useDropdown();
|
|
226
260
|
const activate = () => {
|
|
227
261
|
if (props.disabled) return;
|
|
@@ -253,7 +287,7 @@ export function DropdownItem(props: { children: JSX.Element; class?: string; onS
|
|
|
253
287
|
* a11y: `role="separator"` — exposed to AT as a group boundary; not in the
|
|
254
288
|
* roving-focus tab order (the `[role="menuitem"]` query skips it).
|
|
255
289
|
*/
|
|
256
|
-
export function DropdownSeparator(props:
|
|
290
|
+
export function DropdownSeparator(props: DropdownSeparatorProps) {
|
|
257
291
|
return <div role="separator" class={cn('-mx-1 my-1 h-px bg-border', props.class)} />;
|
|
258
292
|
}
|
|
259
293
|
|
|
@@ -262,7 +296,7 @@ export function DropdownSeparator(props: { class?: string }) {
|
|
|
262
296
|
* a11y: a plain muted label — NOT a menuitem and NOT focusable, so roving focus
|
|
263
297
|
* skips it; it labels the items that follow visually only (`select-none`).
|
|
264
298
|
*/
|
|
265
|
-
export function DropdownLabel(props:
|
|
299
|
+
export function DropdownLabel(props: DropdownLabelProps) {
|
|
266
300
|
return (
|
|
267
301
|
<div class={cn('select-none px-2 py-1.5 text-xs font-medium text-muted-foreground', props.class)}>
|
|
268
302
|
{props.children}
|
|
@@ -278,7 +312,7 @@ export function DropdownLabel(props: { children: JSX.Element; class?: string })
|
|
|
278
312
|
* present — aligns with the plain items above it instead of being pushed in by a
|
|
279
313
|
* reserved leading check column.
|
|
280
314
|
*/
|
|
281
|
-
export function DropdownCheckboxItem(props:
|
|
315
|
+
export function DropdownCheckboxItem(props: DropdownCheckboxItemProps) {
|
|
282
316
|
const activate = () => {
|
|
283
317
|
if (props.disabled) return;
|
|
284
318
|
props.onSelect?.(); /* stay open — consumer owns `checked` */
|
|
@@ -315,7 +349,7 @@ export function DropdownCheckboxItem(props: { children: JSX.Element; class?: str
|
|
|
315
349
|
* content aligns with plain items. Group membership is the consumer's concern;
|
|
316
350
|
* this primitive just renders the selected state and reports the click.
|
|
317
351
|
*/
|
|
318
|
-
export function DropdownRadioItem(props:
|
|
352
|
+
export function DropdownRadioItem(props: DropdownRadioItemProps) {
|
|
319
353
|
const activate = () => {
|
|
320
354
|
if (props.disabled) return;
|
|
321
355
|
props.onSelect?.(); /* stay open — consumer owns the group selection */
|
|
@@ -377,7 +411,7 @@ const useDropdownSub = () => {
|
|
|
377
411
|
* (Escape/outside-click/select), `useDismiss` on the parent unmounts the whole
|
|
378
412
|
* content tree, which tears this provider down and drops the sub with it.
|
|
379
413
|
*/
|
|
380
|
-
export function DropdownSub(props:
|
|
414
|
+
export function DropdownSub(props: DropdownSubProps) {
|
|
381
415
|
const [open, setOpenSig] = createSignal(false);
|
|
382
416
|
const [viaKb, setViaKb] = createSignal(false);
|
|
383
417
|
const [trigger, setTrigger] = createSignal<HTMLElement>();
|
|
@@ -422,7 +456,7 @@ export function DropdownSub(props: { children: JSX.Element }) {
|
|
|
422
456
|
* keyboard-open also moves focus into the sub's first item. ArrowRight/Enter are
|
|
423
457
|
* swallowed so the parent menu doesn't also act on them.
|
|
424
458
|
*/
|
|
425
|
-
export function DropdownSubTrigger(props:
|
|
459
|
+
export function DropdownSubTrigger(props: DropdownSubTriggerProps) {
|
|
426
460
|
const sub = useDropdownSub();
|
|
427
461
|
const onKeyDown = (e: KeyboardEvent) => {
|
|
428
462
|
if (e.key === 'ArrowRight' || e.key === 'Enter' || e.key === ' ') {
|
|
@@ -465,7 +499,7 @@ export function DropdownSubTrigger(props: { children: JSX.Element; class?: strin
|
|
|
465
499
|
* ArrowUp/Down/Home/End rove within; typeahead included (matches DropdownContent).
|
|
466
500
|
* Keyboard-open focuses the first item.
|
|
467
501
|
*/
|
|
468
|
-
export function DropdownSubContent(props:
|
|
502
|
+
export function DropdownSubContent(props: DropdownSubContentProps) {
|
|
469
503
|
const sub = useDropdownSub();
|
|
470
504
|
const parent = useDropdown();
|
|
471
505
|
const config = useChatConfig();
|
package/src/ui/overlay.tsx
CHANGED
|
@@ -261,11 +261,17 @@ export function useDismiss(opts: UseDismissOptions) {
|
|
|
261
261
|
const inside = opts.refs().some((el) => el && el.contains(target));
|
|
262
262
|
if (!inside) opts.onDismiss('outside');
|
|
263
263
|
};
|
|
264
|
-
|
|
265
|
-
|
|
264
|
+
// Captured at SETUP and closed over, never re-resolved as a global inside
|
|
265
|
+
// `onCleanup`: cleanup can run after the host removed the DOM globals (a
|
|
266
|
+
// `kai-*` release is deferred one microtask past detachment, so an
|
|
267
|
+
// environment teardown gets in between), and a bare `document` there throws.
|
|
268
|
+
// See tests/components/teardown-without-dom-globals.test.tsx.
|
|
269
|
+
const doc = document;
|
|
270
|
+
doc.addEventListener('keydown', onKey);
|
|
271
|
+
doc.addEventListener('pointerdown', onPointer, true);
|
|
266
272
|
onCleanup(() => {
|
|
267
|
-
|
|
268
|
-
|
|
273
|
+
doc.removeEventListener('keydown', onKey);
|
|
274
|
+
doc.removeEventListener('pointerdown', onPointer, true);
|
|
269
275
|
});
|
|
270
276
|
});
|
|
271
277
|
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
// The provider-neutral chunk surface. Everything the adapter needs out of one
|
|
2
|
+
// streaming chunk, and nothing else. A WireFormat maps a decoded provider frame
|
|
3
|
+
// onto these; nothing below this line knows a provider exists.
|
|
4
|
+
import type { RawOrigin, ToolPart } from '../components/tool-types';
|
|
5
|
+
import type { MessagePart, MessageSource } from '../elements/chat-types';
|
|
6
|
+
import type { ReasoningOpts } from '../state/parts';
|
|
7
|
+
|
|
8
|
+
/** One fragment of a tool call. */
|
|
9
|
+
export interface ModelToolCallDelta {
|
|
10
|
+
/**
|
|
11
|
+
* The ONLY thing correlating fragments, and its NAMESPACE IS FORMAT-DEFINED.
|
|
12
|
+
* `openaiChatFormat` uses the position in `delta.tool_calls`;
|
|
13
|
+
* `anthropicMessagesFormat` uses the content-block index. Both are correct and
|
|
14
|
+
* both are stable within one stream, but they are not the same number, so a
|
|
15
|
+
* third-party format must pick one and stay consistent with itself.
|
|
16
|
+
*/
|
|
17
|
+
index: number;
|
|
18
|
+
id?: string;
|
|
19
|
+
/** Usually whole on the first fragment; a few providers split it. */
|
|
20
|
+
name?: string;
|
|
21
|
+
/** A FRAGMENT of the JSON arguments string, not valid JSON on its own. */
|
|
22
|
+
arguments?: string;
|
|
23
|
+
/** A result the PROVIDER executed (Anthropic web_search_tool_result, an OpenAI
|
|
24
|
+
* built-in). Completes the panel with no host work. */
|
|
25
|
+
output?: Record<string, unknown>;
|
|
26
|
+
/** A provider-executed tool that failed. */
|
|
27
|
+
outputError?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Field names are deliberately provider-neutral. OpenAI says prompt/completion,
|
|
31
|
+
* Anthropic says input/output; input/output is the one that reads correctly for
|
|
32
|
+
* both. */
|
|
33
|
+
export interface ModelUsage {
|
|
34
|
+
inputTokens?: number;
|
|
35
|
+
outputTokens?: number;
|
|
36
|
+
totalTokens?: number;
|
|
37
|
+
/** Non-zero proves the model reasoned even when no reasoning text streamed. */
|
|
38
|
+
reasoningTokens?: number;
|
|
39
|
+
cachedInputTokens?: number;
|
|
40
|
+
costUsd?: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface ModelStreamChunk {
|
|
44
|
+
text?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Reasoning delta. `''` is MEANINGFUL, not a no-op: a redacted block has no
|
|
47
|
+
* readable text but still carries a payload that must round-trip, and a format
|
|
48
|
+
* uses an empty delta to OPEN a reasoning part at the right position in the
|
|
49
|
+
* stream so block order survives into `parts`.
|
|
50
|
+
*/
|
|
51
|
+
reasoning?: string;
|
|
52
|
+
/** The provider's BLOCK index. Keeps parallel reasoning blocks distinct.
|
|
53
|
+
* Omitted means block 0, the single-block case every provider degrades to. */
|
|
54
|
+
reasoningIndex?: number;
|
|
55
|
+
/**
|
|
56
|
+
* The UNTRANSLATED provider payload for this reasoning block. Valid on a chunk
|
|
57
|
+
* with NO reasoning text at all, which is the whole point: Anthropic returns
|
|
58
|
+
* 400 if a `thinking` block is modified, reordered or RECONSTRUCTED, so an
|
|
59
|
+
* encoder has to echo the original block rather than rebuild one from `text`
|
|
60
|
+
* plus `signature`.
|
|
61
|
+
*/
|
|
62
|
+
reasoningRaw?: RawOrigin;
|
|
63
|
+
/** Informational. `reasoningRaw` is the round-trip channel, not this. */
|
|
64
|
+
reasoningSignature?: string;
|
|
65
|
+
toolCalls?: ModelToolCallDelta[];
|
|
66
|
+
/** Citations the model produced. A run of consecutive `source` parts renders
|
|
67
|
+
* as one citation row (`part="citations"`), outside the message bubble. */
|
|
68
|
+
sources?: MessageSource[];
|
|
69
|
+
/** Provider VERBATIM: 'stop' | 'tool_calls' | 'end_turn' | 'max_tokens' | ...
|
|
70
|
+
* Normalizing in place would destroy information consumers branch on. */
|
|
71
|
+
finishReason?: string | null;
|
|
72
|
+
usage?: ModelUsage;
|
|
73
|
+
/** An in-band provider error (the HTTP response was already 200). */
|
|
74
|
+
error?: { code?: string | number; message: string };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** One vocabulary across formats, for code that has to BRANCH. `finishReason`
|
|
78
|
+
* stays beside it, verbatim, for code that has to REPORT. */
|
|
79
|
+
export type StopReason = 'stop' | 'length' | 'tool-calls' | 'content-filter' | 'error' | 'other';
|
|
80
|
+
|
|
81
|
+
const STOP_REASONS: Record<string, StopReason> = {
|
|
82
|
+
// OpenAI chat completions
|
|
83
|
+
stop: 'stop',
|
|
84
|
+
length: 'length',
|
|
85
|
+
tool_calls: 'tool-calls',
|
|
86
|
+
function_call: 'tool-calls',
|
|
87
|
+
content_filter: 'content-filter',
|
|
88
|
+
error: 'error',
|
|
89
|
+
// Anthropic Messages
|
|
90
|
+
end_turn: 'stop',
|
|
91
|
+
stop_sequence: 'stop',
|
|
92
|
+
max_tokens: 'length',
|
|
93
|
+
tool_use: 'tool-calls',
|
|
94
|
+
refusal: 'content-filter',
|
|
95
|
+
pause_turn: 'other',
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/** Unknown reasons degrade to 'other' rather than throwing: providers add stop
|
|
99
|
+
* reasons without warning and a new one must not take a turn down. */
|
|
100
|
+
export function normalizeStopReason(
|
|
101
|
+
finishReason: string | null | undefined,
|
|
102
|
+
): StopReason | undefined {
|
|
103
|
+
if (!finishReason) return undefined;
|
|
104
|
+
return STOP_REASONS[finishReason] ?? 'other';
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* The subset of the kit's `AssistantStream` the adapter drives. Declared
|
|
109
|
+
* STRUCTURALLY so the adapter has no runtime dependency on a stream
|
|
110
|
+
* implementation and can be tested against a recorder. The kit's real
|
|
111
|
+
* `AssistantStream` satisfies it as-is: same method names, same arities, and its
|
|
112
|
+
* `AssistantStream` returns are assignable to `unknown`.
|
|
113
|
+
*
|
|
114
|
+
* `addSource` is optional so a hand-rolled three-method sink still compiles.
|
|
115
|
+
*/
|
|
116
|
+
export interface AssistantStreamSink {
|
|
117
|
+
appendText(delta: string): unknown;
|
|
118
|
+
appendReasoning(delta: string, opts?: ReasoningOpts): unknown;
|
|
119
|
+
/** Create-or-merge. There is no separate "announce" call: handing a patch for
|
|
120
|
+
* an unknown `toolCallId` creates the ToolPart, and every later patch merges. */
|
|
121
|
+
upsertTool(toolCallId: string, patch: Partial<ToolPart>): unknown;
|
|
122
|
+
addSource?(source: MessageSource): unknown;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** One tool call reassembled out of the stream's fragments. */
|
|
126
|
+
export interface ModelToolCall {
|
|
127
|
+
/** The delta index that correlated this call's fragments. */
|
|
128
|
+
index: number;
|
|
129
|
+
/** Provider call id (synthesised as `call_<index>` if the provider omits it). */
|
|
130
|
+
id: string;
|
|
131
|
+
name: string;
|
|
132
|
+
/** The RAW accumulated argument fragments. Echo THIS back on the next turn,
|
|
133
|
+
* not a re-stringified parse. */
|
|
134
|
+
argumentsText: string;
|
|
135
|
+
/** Parsed arguments: present only when `argumentsText` was a valid JSON object. */
|
|
136
|
+
input?: Record<string, unknown>;
|
|
137
|
+
/** Present only for a call the PROVIDER executed. */
|
|
138
|
+
output?: Record<string, unknown>;
|
|
139
|
+
/** True when the provider ran the tool and returned its result in-stream. The
|
|
140
|
+
* host must NOT execute these. */
|
|
141
|
+
providerExecuted?: boolean;
|
|
142
|
+
/** Why this call is unusable (malformed or truncated args, missing name). */
|
|
143
|
+
error?: string;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** Everything one assistant turn produced. */
|
|
147
|
+
export interface ModelTurn {
|
|
148
|
+
/** The turn as ORDERED MESSAGE PARTS, built with the kit's own part builders,
|
|
149
|
+
* so it is exactly what the sink was driven with. Covers this turn only. */
|
|
150
|
+
parts: MessagePart[];
|
|
151
|
+
/** Flat concatenation of the text deltas. The provider wire format is a flat
|
|
152
|
+
* string, so this is kept for encoders. Not the content model. */
|
|
153
|
+
text: string;
|
|
154
|
+
/** Flat concatenation of the reasoning deltas, for the same reason. */
|
|
155
|
+
reasoning: string;
|
|
156
|
+
toolCalls: ModelToolCall[];
|
|
157
|
+
sources: MessageSource[];
|
|
158
|
+
/** The provider's own word for why it stopped. Never normalized. */
|
|
159
|
+
finishReason: string | null;
|
|
160
|
+
/** The same fact in one vocabulary. Branch on this. */
|
|
161
|
+
stopReason?: StopReason;
|
|
162
|
+
error?: { code?: string | number; message: string };
|
|
163
|
+
usage?: ModelUsage;
|
|
164
|
+
/** How many chunks carried a NON-EMPTY reasoning delta. Zero with a non-zero
|
|
165
|
+
* `usage.reasoningTokens` means the provider hid the thinking text. */
|
|
166
|
+
reasoningChunks: number;
|
|
167
|
+
chunks: number;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface ConsumeOptions {
|
|
171
|
+
/** Label for the reasoning disclosure. Defaults to 'Thinking'. */
|
|
172
|
+
reasoningLabel?: string;
|
|
173
|
+
/** Fires once per tool call the moment its arguments parse cleanly. This is
|
|
174
|
+
* the hook a host's tool loop waits on. There is deliberately no
|
|
175
|
+
* per-fragment callback: `ToolPart.rawInput` is written on every fragment,
|
|
176
|
+
* so the streaming text is already on the part. */
|
|
177
|
+
onToolCallReady?: (call: ModelToolCall) => void;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** Per-stream state for one format. */
|
|
181
|
+
export interface WireFormatReader {
|
|
182
|
+
/**
|
|
183
|
+
* Map one decoded frame onto zero or more neutral chunks. Returns an ARRAY
|
|
184
|
+
* because the mapping is not one-to-one: an Anthropic `message_start` yields
|
|
185
|
+
* usage, a `content_block_start` for `tool_use` yields an id-plus-name delta,
|
|
186
|
+
* a `ping` yields nothing.
|
|
187
|
+
*
|
|
188
|
+
* MUST NOT throw on an unrecognized frame. Return `[]` instead: providers add
|
|
189
|
+
* event types without warning.
|
|
190
|
+
*/
|
|
191
|
+
push(frame: unknown): ModelStreamChunk[];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** A pluggable wire format. Values, not a flag, so a third party can add one
|
|
195
|
+
* without a PR to this repo. */
|
|
196
|
+
export interface WireFormat {
|
|
197
|
+
readonly id: string;
|
|
198
|
+
/** Called once per stream so a format can hold per-stream state. Two calls
|
|
199
|
+
* must share NOTHING. */
|
|
200
|
+
open(): WireFormatReader;
|
|
201
|
+
}
|