@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
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// isolation.
|
|
7
7
|
import type { ToolPart } from './tool';
|
|
8
8
|
import type { AttachmentData } from './attachments';
|
|
9
|
+
import type { MessagePart } from '../elements/chat-types';
|
|
9
10
|
|
|
10
11
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
11
12
|
// Types
|
|
@@ -125,3 +126,27 @@ export function isAnyStreaming(pair: ComparePair | null): boolean {
|
|
|
125
126
|
if (!pair) return false;
|
|
126
127
|
return pair.some((c) => c.streaming === true);
|
|
127
128
|
}
|
|
129
|
+
|
|
130
|
+
/** Map a `CompareCandidate`'s flat legacy fields (content/reasoning/tools/
|
|
131
|
+
* attachments) into the ordered `MessagePart[]` `MessageBody` now renders.
|
|
132
|
+
* `CompareCandidate` stays its own independent shape (it is `<kai-compare>`'s
|
|
133
|
+
* public `data` JSON, not a `ChatMessage`). This is purely a render-time
|
|
134
|
+
* adapter, applied at each `MessageBody` call site. Order: reasoning (the
|
|
135
|
+
* thinking trace) → tool calls (the actions taken) → attachments (anything
|
|
136
|
+
* produced) → the final text answer, mirroring how an assistant turn reads. */
|
|
137
|
+
export function candidateToParts(candidate: CompareCandidate): MessagePart[] {
|
|
138
|
+
const parts: MessagePart[] = [];
|
|
139
|
+
if (candidate.reasoning) {
|
|
140
|
+
parts.push({ type: 'reasoning', text: candidate.reasoning.text, label: candidate.reasoning.label });
|
|
141
|
+
}
|
|
142
|
+
for (const tool of candidate.tools ?? []) {
|
|
143
|
+
parts.push({ type: 'tool', tool });
|
|
144
|
+
}
|
|
145
|
+
for (const attachment of candidate.attachments ?? []) {
|
|
146
|
+
parts.push({ type: 'file', attachment });
|
|
147
|
+
}
|
|
148
|
+
if (candidate.content) {
|
|
149
|
+
parts.push({ type: 'text', text: candidate.content });
|
|
150
|
+
}
|
|
151
|
+
return parts;
|
|
152
|
+
}
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
type CompareSelection,
|
|
25
25
|
type ResponseCompareData,
|
|
26
26
|
buildSelection,
|
|
27
|
+
candidateToParts,
|
|
27
28
|
isAnyStreaming,
|
|
28
29
|
normalizeCandidates,
|
|
29
30
|
} from './response-compare-types';
|
|
@@ -37,7 +38,7 @@ export type {
|
|
|
37
38
|
ResponseCompareData,
|
|
38
39
|
CompareSelection,
|
|
39
40
|
} from './response-compare-types';
|
|
40
|
-
export { normalizeCandidates, buildSelection, isAnyStreaming } from './response-compare-types';
|
|
41
|
+
export { normalizeCandidates, buildSelection, isAnyStreaming, candidateToParts } from './response-compare-types';
|
|
41
42
|
|
|
42
43
|
export type CompareLayout = 'auto' | 'columns' | 'tabs';
|
|
43
44
|
|
|
@@ -386,10 +387,7 @@ function CompareColumn(props: ColumnProps): JSX.Element {
|
|
|
386
387
|
when={props.candidate.streaming}
|
|
387
388
|
fallback={
|
|
388
389
|
<MessageBody
|
|
389
|
-
|
|
390
|
-
reasoning={props.candidate.reasoning}
|
|
391
|
-
tools={props.candidate.tools}
|
|
392
|
-
attachments={props.candidate.attachments}
|
|
390
|
+
parts={candidateToParts(props.candidate)}
|
|
393
391
|
isUser={false}
|
|
394
392
|
markdown={true}
|
|
395
393
|
/>
|
|
@@ -445,10 +443,7 @@ function CollapsedWinner(props: {
|
|
|
445
443
|
{(c) => (
|
|
446
444
|
<div class="min-w-0">
|
|
447
445
|
<MessageBody
|
|
448
|
-
|
|
449
|
-
reasoning={c().reasoning}
|
|
450
|
-
tools={c().tools}
|
|
451
|
-
attachments={c().attachments}
|
|
446
|
+
parts={candidateToParts(c())}
|
|
452
447
|
isUser={false}
|
|
453
448
|
markdown={true}
|
|
454
449
|
/>
|
|
@@ -20,21 +20,29 @@ function useSourceContext() {
|
|
|
20
20
|
// --- Source (Root) ---
|
|
21
21
|
|
|
22
22
|
export interface SourceProps {
|
|
23
|
-
|
|
23
|
+
/** The citation's URL. OPTIONAL: every field of a model-produced citation is,
|
|
24
|
+
* so a source can arrive with a title and no url. In that case the chip
|
|
25
|
+
* renders as a plain, inert `<a>` with NO `href` attribute — which is valid
|
|
26
|
+
* HTML and simply not a link — rather than `<a href="">`, which would
|
|
27
|
+
* navigate to the current page. */
|
|
28
|
+
href?: string;
|
|
24
29
|
children: JSX.Element;
|
|
25
30
|
}
|
|
26
31
|
|
|
27
32
|
function Source(props: SourceProps) {
|
|
33
|
+
const href = () => props.href ?? '';
|
|
28
34
|
const domain = () => {
|
|
35
|
+
const h = href();
|
|
36
|
+
if (!h) return '';
|
|
29
37
|
try {
|
|
30
|
-
return new URL(
|
|
38
|
+
return new URL(h).hostname;
|
|
31
39
|
} catch {
|
|
32
|
-
return
|
|
40
|
+
return h.split('/').pop() || h;
|
|
33
41
|
}
|
|
34
42
|
};
|
|
35
43
|
|
|
36
44
|
return (
|
|
37
|
-
<SourceContext.Provider value={{ get href() { return
|
|
45
|
+
<SourceContext.Provider value={{ get href() { return href(); }, get domain() { return domain(); } }}>
|
|
38
46
|
<HoverCardRoot openDelay={150}>
|
|
39
47
|
{props.children}
|
|
40
48
|
</HoverCardRoot>
|
|
@@ -57,7 +65,8 @@ function SourceTrigger(props: SourceTriggerProps) {
|
|
|
57
65
|
return (
|
|
58
66
|
<HoverCardTrigger>
|
|
59
67
|
<a
|
|
60
|
-
href
|
|
68
|
+
// `undefined` OMITS the attribute — see SourceProps.href.
|
|
69
|
+
href={ctx.href || undefined}
|
|
61
70
|
target="_blank"
|
|
62
71
|
rel="noopener noreferrer"
|
|
63
72
|
class={cn(
|
|
@@ -66,7 +75,8 @@ function SourceTrigger(props: SourceTriggerProps) {
|
|
|
66
75
|
props.class
|
|
67
76
|
)}
|
|
68
77
|
>
|
|
69
|
-
|
|
78
|
+
{/* No url, no favicon to look up. */}
|
|
79
|
+
<Show when={props.showFavicon && ctx.href}>
|
|
70
80
|
<img
|
|
71
81
|
src={`https://www.google.com/s2/favicons?sz=64&domain_url=${encodeURIComponent(ctx.href)}`}
|
|
72
82
|
alt="favicon"
|
|
@@ -94,27 +104,35 @@ function SourceContent(props: SourceContentProps) {
|
|
|
94
104
|
return (
|
|
95
105
|
<HoverCardContent class={cn('w-80 p-0 shadow-xs', props.class)}>
|
|
96
106
|
<a
|
|
97
|
-
href
|
|
107
|
+
// `undefined` OMITS the attribute — see SourceProps.href.
|
|
108
|
+
href={ctx.href || undefined}
|
|
98
109
|
target="_blank"
|
|
99
110
|
rel="noopener noreferrer"
|
|
100
111
|
class="flex flex-col gap-2 p-3"
|
|
101
112
|
>
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
113
|
+
{/* The domain header row only means anything when there IS a url. */}
|
|
114
|
+
<Show when={ctx.href}>
|
|
115
|
+
<div class="flex items-center gap-1.5">
|
|
116
|
+
<img
|
|
117
|
+
src={`https://www.google.com/s2/favicons?sz=64&domain_url=${encodeURIComponent(ctx.href)}`}
|
|
118
|
+
alt="favicon"
|
|
119
|
+
class="size-4 rounded-full"
|
|
120
|
+
width={16}
|
|
121
|
+
height={16}
|
|
122
|
+
/>
|
|
123
|
+
<div class="text-primary truncate text-sm">
|
|
124
|
+
{ctx.domain.replace('www.', '')}
|
|
125
|
+
</div>
|
|
112
126
|
</div>
|
|
113
|
-
</
|
|
114
|
-
<
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
127
|
+
</Show>
|
|
128
|
+
<Show when={props.title}>
|
|
129
|
+
<div class="line-clamp-2 text-sm font-medium">{props.title}</div>
|
|
130
|
+
</Show>
|
|
131
|
+
<Show when={props.description}>
|
|
132
|
+
<div class="text-muted-foreground line-clamp-2 text-sm">
|
|
133
|
+
{props.description}
|
|
134
|
+
</div>
|
|
135
|
+
</Show>
|
|
118
136
|
</a>
|
|
119
137
|
</HoverCardContent>
|
|
120
138
|
);
|
|
@@ -122,8 +140,16 @@ function SourceContent(props: SourceContentProps) {
|
|
|
122
140
|
|
|
123
141
|
// --- SourceList (convenience) ---
|
|
124
142
|
|
|
125
|
-
|
|
126
|
-
|
|
143
|
+
export interface SourceListProps {
|
|
144
|
+
children: JSX.Element;
|
|
145
|
+
class?: string;
|
|
146
|
+
/** `::part` name(s) exposed on the row. The message body passes `"citations"`
|
|
147
|
+
* so consumers can target the citation row from outside the shadow boundary. */
|
|
148
|
+
part?: string;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function SourceList(props: SourceListProps) {
|
|
152
|
+
return <div part={props.part} class={cn('flex flex-wrap gap-1.5 mt-3', props.class)}>{props.children}</div>;
|
|
127
153
|
}
|
|
128
154
|
|
|
129
155
|
export { Source, SourceTrigger, SourceContent, SourceList };
|
|
@@ -24,42 +24,19 @@ import { useCardHost } from '../primitives/card-host';
|
|
|
24
24
|
import { Check, Circle, CircleCheck, X } from 'lucide-solid';
|
|
25
25
|
|
|
26
26
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
27
|
-
// Types (tasks.schema.json) —
|
|
27
|
+
// Types (tasks.schema.json) — AUTHORED IN ../primitives/card-data-types.ts.
|
|
28
|
+
// See the note in confirm-card.tsx, or that file's header, for why they left a
|
|
29
|
+
// `.tsx` and why they are `type` aliases. Re-exported here unchanged.
|
|
28
30
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
id: string;
|
|
32
|
-
label: string;
|
|
33
|
-
description?: string;
|
|
34
|
-
checked?: boolean;
|
|
35
|
-
disabled?: boolean;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface TasksCardData {
|
|
39
|
-
/**
|
|
40
|
-
* `select` (default) = checkbox rows + a confirm button that emits the contract
|
|
41
|
-
* `submit`. `progress` = an onboarding/checklist look: a header `done / total`
|
|
42
|
-
* count, circular indicators, per-item title + muted description, and NO confirm
|
|
43
|
-
* button (checking a row is itself the terminal action). Both share the same
|
|
44
|
-
* selection model (toggle by id, the `max` gate, `kai-value-change`); `progress`
|
|
45
|
-
* is purely a presentational variant.
|
|
46
|
-
*/
|
|
47
|
-
mode?: 'select' | 'progress';
|
|
48
|
-
heading?: string;
|
|
49
|
-
tasks: TasksTask[]; // >=1
|
|
50
|
-
selectAll?: boolean;
|
|
51
|
-
confirmLabel?: string;
|
|
52
|
-
allowEmpty?: boolean;
|
|
53
|
-
min?: number;
|
|
54
|
-
max?: number;
|
|
55
|
-
dismissible?: boolean; // show a close affordance that emits `dismiss`
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface TasksCardResult {
|
|
59
|
-
selected: string[];
|
|
60
|
-
}
|
|
32
|
+
import type { TasksCardData, TasksCardResult, TasksTask } from '../primitives/card-data-types';
|
|
61
33
|
|
|
62
|
-
export type
|
|
34
|
+
export type {
|
|
35
|
+
TasksCardData,
|
|
36
|
+
TasksCardEnvelope,
|
|
37
|
+
TasksCardResult,
|
|
38
|
+
TasksTask,
|
|
39
|
+
} from '../primitives/card-data-types';
|
|
63
40
|
|
|
64
41
|
export const TASKS_CARD_TYPE = 'tasks' as const;
|
|
65
42
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { For, Show, onMount, type JSX } from 'solid-js';
|
|
1
|
+
import { For, Show, createMemo, onMount, type JSX } from 'solid-js';
|
|
2
2
|
import { ChatConfig, useChatConfig } from '../primitives/chat-config';
|
|
3
3
|
import { ChatContainer, ChatContainerContent, ChatContainerScrollAnchor } from './chat-container';
|
|
4
4
|
import { Message, MessageAvatar, MessageBody } from './message';
|
|
@@ -7,6 +7,8 @@ import { ScrollButton } from './scroll-button';
|
|
|
7
7
|
import { Loader } from './loader';
|
|
8
8
|
import type { ChatMessage } from '../elements/chat-types';
|
|
9
9
|
import type { ProseSize } from '../primitives/chat-config';
|
|
10
|
+
import type { CardComponentMap } from '../primitives/card-registry';
|
|
11
|
+
import type { CardSchemaMap } from './card-renderer';
|
|
10
12
|
|
|
11
13
|
/** Imperative handle exposed via `controllerRef` — the thread's scroll control,
|
|
12
14
|
* forwarded onto `<kai-thread>` as the `scrollToBottom()` instance method. */
|
|
@@ -19,9 +21,19 @@ export interface ThreadProps {
|
|
|
19
21
|
/** Extra classes for the thread root (e.g. `rounded-xl`). */
|
|
20
22
|
class?: string;
|
|
21
23
|
/** The full message thread to render, newest last. Each entry carries its role,
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
+
* ordered `parts`, and optional actions/avatar/feedback. A new array reference
|
|
25
|
+
* per streaming chunk re-renders (mutating in place does not). */
|
|
24
26
|
messages: ChatMessage[];
|
|
27
|
+
/** Add/override card type -> component entries, forwarded to `CardRenderer`
|
|
28
|
+
* for `card` parts. */
|
|
29
|
+
cardTypes?: CardComponentMap;
|
|
30
|
+
/** JSON Schemas for the card types this app renders, keyed by envelope type,
|
|
31
|
+
* forwarded to `CardRenderer` for `card` parts. The companion of `cardTypes`:
|
|
32
|
+
* that says what DRAWS a card, this says what a VALID one looks like.
|
|
33
|
+
* `createCardRegistry(...).validationSchemas` is exactly this shape. Without it
|
|
34
|
+
* the kit checks its own seven built-ins and leaves your own card type
|
|
35
|
+
* unvalidated. A schema here WINS over a built-in of the same name. */
|
|
36
|
+
cardSchemas?: CardSchemaMap;
|
|
25
37
|
/** Show a typing indicator on the pending assistant turn — use while awaiting
|
|
26
38
|
* the assistant's reply. */
|
|
27
39
|
loading?: boolean;
|
|
@@ -85,6 +97,11 @@ export function Thread(props: ThreadProps) {
|
|
|
85
97
|
});
|
|
86
98
|
const showScrollButton = () => props.scrollButton !== false;
|
|
87
99
|
const showEmpty = () => props.messages.length === 0 && !props.loading;
|
|
100
|
+
// Keyed by message id, NOT by object reference: a streaming message is a new
|
|
101
|
+
// object every delta, and a reference-keyed <For> rebuilds the whole row for
|
|
102
|
+
// each one — which is why expanding a tool/reasoning panel mid-stream used to
|
|
103
|
+
// do nothing. Full rationale (and why not `<Index>`) in `chat-thread.tsx`.
|
|
104
|
+
const messageKeys = createMemo(() => props.messages.map((m) => m.id));
|
|
88
105
|
|
|
89
106
|
// Hand the imperative controller to the facade once mounted (rootEl is set).
|
|
90
107
|
onMount(() => {
|
|
@@ -116,46 +133,71 @@ export function Thread(props: ThreadProps) {
|
|
|
116
133
|
{props.empty}
|
|
117
134
|
</Show>
|
|
118
135
|
</Show>
|
|
119
|
-
<For each={
|
|
120
|
-
{(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
136
|
+
<For each={messageKeys()}>
|
|
137
|
+
{(_id, i) => (
|
|
138
|
+
// Read the message through <For>'s index accessor, never through
|
|
139
|
+
// a captured value — the row outlives the delta that replaced its
|
|
140
|
+
// object. <Show> supplies the non-null accessor and covers the
|
|
141
|
+
// frame where a removal has shortened the array.
|
|
142
|
+
<Show when={props.messages[i()]}>
|
|
143
|
+
{(m) => {
|
|
144
|
+
const body = (
|
|
145
|
+
<MessageBody
|
|
146
|
+
parts={m().parts}
|
|
147
|
+
cardTypes={props.cardTypes}
|
|
148
|
+
cardSchemas={props.cardSchemas}
|
|
149
|
+
isUser={m().role === 'user'}
|
|
150
|
+
markdown={m().role === 'assistant'}
|
|
151
|
+
actions={m().actions}
|
|
152
|
+
actionsReveal={reveal()}
|
|
153
|
+
activeFeedback={feedback.resolveFeedback(m())}
|
|
154
|
+
copied={feedback.isCopied(m().id)}
|
|
155
|
+
onAction={(action) => feedback.handleAction(m(), action)}
|
|
156
|
+
/>
|
|
157
|
+
);
|
|
158
|
+
const rowGroup = () => (reveal() === 'hover' ? 'group ' : '');
|
|
159
|
+
return (
|
|
160
|
+
// `role` is the SPEAKER, and it has to be forwarded on BOTH
|
|
161
|
+
// branches. `Message` turns it into `role="article"` + an
|
|
162
|
+
// `aria-label` naming the speaker; without it the row is a
|
|
163
|
+
// bare div that chromium prunes from the accessibility tree
|
|
164
|
+
// as "uninteresting", so a screen reader gets no speaker at
|
|
165
|
+
// all. Every other read of `m().role` here is cosmetic
|
|
166
|
+
// (alignment, markdown), which is exactly how it went
|
|
167
|
+
// missing: the value was in hand and used for styling while
|
|
168
|
+
// being dropped for semantics.
|
|
169
|
+
<Show
|
|
170
|
+
when={m().avatar}
|
|
171
|
+
fallback={
|
|
172
|
+
<Message role={m().role} class={`${rowGroup()}${m().role === 'user' ? 'flex-col items-end' : 'flex-col items-start'}`}>
|
|
173
|
+
{body}
|
|
174
|
+
</Message>
|
|
175
|
+
}
|
|
176
|
+
>
|
|
177
|
+
{(av) => (
|
|
178
|
+
<Message role={m().role} class={rowGroup()}>
|
|
179
|
+
<MessageAvatar src={av().src ?? ''} alt={av().alt ?? ''} fallback={av().fallback} />
|
|
180
|
+
<div class={`flex min-w-0 flex-1 flex-col ${m().role === 'user' ? 'items-end' : 'items-start'}`}>
|
|
181
|
+
{body}
|
|
182
|
+
</div>
|
|
183
|
+
</Message>
|
|
184
|
+
)}
|
|
185
|
+
</Show>
|
|
186
|
+
);
|
|
187
|
+
}}
|
|
188
|
+
</Show>
|
|
189
|
+
)}
|
|
157
190
|
</For>
|
|
158
|
-
{/* Typing indicator on the pending assistant turn.
|
|
191
|
+
{/* Typing indicator on the pending assistant turn.
|
|
192
|
+
DELIBERATELY role-less, unlike the rows above — this is not an
|
|
193
|
+
oversight of the same kind. There is no message here yet, so
|
|
194
|
+
`role="assistant"` would announce an empty article named
|
|
195
|
+
"Assistant message". What a pending indicator needs instead is a
|
|
196
|
+
live region, so its ARRIVAL and departure are announced. The
|
|
197
|
+
Loader already carries an accessible name — an sr-only "Loading"
|
|
198
|
+
on all nine shape variants — and what it lacks is the
|
|
199
|
+
`role="status"` / aria-live wrapper around it. A real but
|
|
200
|
+
SEPARATE gap, and it lives in loader.tsx. Filed, not fixed here. */}
|
|
159
201
|
<Show when={props.loading}>
|
|
160
202
|
<Message class="flex-col items-start">
|
|
161
203
|
<div class="rounded-lg px-1 py-2">
|
package/src/components/toast.tsx
CHANGED
|
@@ -59,7 +59,7 @@ function usePrefersReducedMotion() {
|
|
|
59
59
|
|
|
60
60
|
// ── Single toast pill ────────────────────────────────────────────────────────
|
|
61
61
|
|
|
62
|
-
interface ToastProps {
|
|
62
|
+
export interface ToastProps {
|
|
63
63
|
item: ToastItem;
|
|
64
64
|
onDismiss: (reason: ToastDismissReason) => void;
|
|
65
65
|
onAction?: (label: string) => void;
|
|
@@ -214,7 +214,12 @@ export function Toast(props: ToastProps) {
|
|
|
214
214
|
<Show when={presence.present()}>
|
|
215
215
|
<div
|
|
216
216
|
ref={presence.setRef}
|
|
217
|
-
|
|
217
|
+
// `variant` already picks the error ICON; it has to pick the ROLE too, or
|
|
218
|
+
// a failure is announced with the same (polite, easily missed) urgency as
|
|
219
|
+
// a success. `alert` is implicitly assertive and interrupts, which is what
|
|
220
|
+
// the region's `aria-live="polite"` alone will not do for the toast that
|
|
221
|
+
// actually matters. Same expression as ui/notice.tsx.
|
|
222
|
+
role={variant() === 'error' ? 'alert' : 'status'}
|
|
218
223
|
data-appearance={appearance()}
|
|
219
224
|
data-inverse={inverse() ? '' : undefined}
|
|
220
225
|
data-closed={presence.state() === 'closed' ? '' : undefined}
|
|
@@ -388,6 +393,12 @@ export function ToastRegion(props: ToastRegionProps) {
|
|
|
388
393
|
createEffect(() => {
|
|
389
394
|
const t = props.target;
|
|
390
395
|
if (!t || typeof window === 'undefined') { setAnchor(null); return; }
|
|
396
|
+
// Captured at SETUP and closed over, never re-resolved as a global inside
|
|
397
|
+
// `onCleanup`: cleanup can run after the host removed the DOM globals (a
|
|
398
|
+
// `kai-*` release is deferred one microtask past detachment, so an
|
|
399
|
+
// environment teardown gets in between), and a bare `window` there throws.
|
|
400
|
+
// See tests/components/teardown-without-dom-globals.test.tsx.
|
|
401
|
+
const win = window;
|
|
391
402
|
const update = () => {
|
|
392
403
|
const r = t.getBoundingClientRect();
|
|
393
404
|
setAnchor({ top: r.top, left: r.left, right: r.right, bottom: r.bottom, width: r.width });
|
|
@@ -395,12 +406,12 @@ export function ToastRegion(props: ToastRegionProps) {
|
|
|
395
406
|
update();
|
|
396
407
|
const ro = new ResizeObserver(update);
|
|
397
408
|
ro.observe(t);
|
|
398
|
-
|
|
399
|
-
|
|
409
|
+
win.addEventListener('scroll', update, true);
|
|
410
|
+
win.addEventListener('resize', update);
|
|
400
411
|
onCleanup(() => {
|
|
401
412
|
ro.disconnect();
|
|
402
|
-
|
|
403
|
-
|
|
413
|
+
win.removeEventListener('scroll', update, true);
|
|
414
|
+
win.removeEventListener('resize', update);
|
|
404
415
|
});
|
|
405
416
|
});
|
|
406
417
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Semantic classification of a tool call, used to pick a rendering. Derived from
|
|
2
|
+
* the provider-chosen tool NAME, which is arbitrary, so this stays conservative and
|
|
3
|
+
* prefers 'generic' over a confident wrong answer. */
|
|
4
|
+
export type ToolKind =
|
|
5
|
+
| 'command'
|
|
6
|
+
| 'file-change'
|
|
7
|
+
| 'search'
|
|
8
|
+
| 'fetch'
|
|
9
|
+
| 'mcp'
|
|
10
|
+
| 'image'
|
|
11
|
+
| 'generic';
|
|
12
|
+
|
|
13
|
+
/** Total, deterministic, side-effect free. ALWAYS terminates in 'generic' so an
|
|
14
|
+
* unrecognized tool still renders a panel instead of a blank. Order matters:
|
|
15
|
+
* 'search' is tested before 'fetch' so `web_search` classifies as a search. */
|
|
16
|
+
export function classifyTool(name: string): ToolKind {
|
|
17
|
+
const n = name.toLowerCase();
|
|
18
|
+
if (!n) return 'generic';
|
|
19
|
+
if (n.includes('bash') || n.includes('command') || n.includes('shell') || n.includes('terminal') || n.includes('exec')) return 'command';
|
|
20
|
+
if (n.includes('edit') || n.includes('write') || n.includes('patch') || n.includes('replace') || n.includes('delete')) return 'file-change';
|
|
21
|
+
if (n.includes('search') || n.includes('grep') || n.includes('glob') || n.includes('find')) return 'search';
|
|
22
|
+
if (n.includes('fetch') || n.includes('http') || n.includes('browse') || n.includes('crawl')) return 'fetch';
|
|
23
|
+
if (n.includes('mcp')) return 'mcp';
|
|
24
|
+
if (n.includes('image') || n.includes('screenshot') || n.includes('vision')) return 'image';
|
|
25
|
+
return 'generic';
|
|
26
|
+
}
|
|
@@ -1,10 +1,40 @@
|
|
|
1
|
+
import type { ToolKind } from './tool-classify';
|
|
2
|
+
|
|
3
|
+
/** The untranslated provider payload a part was normalized from.
|
|
4
|
+
*
|
|
5
|
+
* Optional in the type but REQUIRED in practice for round-trip fidelity. Anthropic
|
|
6
|
+
* returns a 400 invalid_request_error if `thinking` blocks are modified, reordered,
|
|
7
|
+
* filtered or RECONSTRUCTED, so an encoder must send `raw.payload` back verbatim
|
|
8
|
+
* rather than rebuilding a block from `text` + `signature`. */
|
|
9
|
+
export interface RawOrigin {
|
|
10
|
+
/** Tagged origin, e.g. 'anthropic.content_block', 'openai.delta', `custom.${string}`. */
|
|
11
|
+
source: string;
|
|
12
|
+
payload: unknown;
|
|
13
|
+
}
|
|
14
|
+
|
|
1
15
|
/** A tool-call part rendered by <Tool>. Pure type — kept JSX-free so it can be
|
|
2
|
-
* imported by the framework-neutral state core and the React typecheck pass.
|
|
16
|
+
* imported by the framework-neutral state core and the React typecheck pass.
|
|
17
|
+
*
|
|
18
|
+
* Adding a field here also requires adding it to `TOOL_KEYS` (and a comparator
|
|
19
|
+
* in `TOOL_COMPARATORS`) in `state/parts.ts`, or `tsc` fails to compile: those
|
|
20
|
+
* drive `upsertToolPart`'s dedupe check, and a field missing from them would
|
|
21
|
+
* silently make that check ignore the new field, keeping a stale array
|
|
22
|
+
* reference alive when only that field changed. */
|
|
3
23
|
export interface ToolPart {
|
|
24
|
+
/** The tool name exactly as the provider reported it. */
|
|
4
25
|
type: string;
|
|
26
|
+
/** Semantic classification for rendering. Derive with classifyTool(type). */
|
|
27
|
+
kind?: ToolKind;
|
|
5
28
|
state: 'input-streaming' | 'input-available' | 'output-available' | 'output-error';
|
|
29
|
+
/** Last VALID parsed snapshot, fingerprint-deduped. The primary channel: this is
|
|
30
|
+
* what the kit renders. */
|
|
6
31
|
input?: Record<string, unknown>;
|
|
32
|
+
/** Raw accumulated argument fragments, for consumers wanting character-level
|
|
33
|
+
* streaming. Most consumers should read `input` instead. */
|
|
34
|
+
rawInput?: string;
|
|
7
35
|
output?: Record<string, unknown>;
|
|
8
36
|
toolCallId?: string;
|
|
9
37
|
errorText?: string;
|
|
38
|
+
/** The untranslated provider payload this was normalized from. */
|
|
39
|
+
raw?: RawOrigin;
|
|
10
40
|
}
|
|
@@ -2,26 +2,26 @@ import { defineWebComponent } from './define';
|
|
|
2
2
|
import { AgentCard, type AgentStatus } from '../ui/agent-card';
|
|
3
3
|
|
|
4
4
|
interface Props extends Record<string, unknown> {
|
|
5
|
-
/** The agent's name
|
|
5
|
+
/** The agent's name, the primary label. Attribute: `name`. */
|
|
6
6
|
name?: string;
|
|
7
7
|
/** Selected / focused state: highlighted border + surface. Attribute: `active`. */
|
|
8
8
|
active?: boolean;
|
|
9
|
-
/** Raise a prominent "Needs you" pill plus a glowing amber edge
|
|
10
|
-
* attention-routing signal that pulls focus to this agent.
|
|
11
|
-
* `needs-attention`. */
|
|
9
|
+
/** Raise a prominent "Needs you" pill plus a glowing amber edge. This
|
|
10
|
+
* is the attention-routing signal that pulls focus to this agent.
|
|
11
|
+
* Attribute: `needs-attention`. */
|
|
12
12
|
needsAttention?: boolean;
|
|
13
|
-
/** Run status
|
|
14
|
-
*
|
|
15
|
-
* `
|
|
16
|
-
*
|
|
17
|
-
*
|
|
13
|
+
/** Run status. A JS PROPERTY (object), not an attribute. Shape: `{ tone,
|
|
14
|
+
* label?, pulse? }`, where `tone` is one of `working` | `idle` | `done` |
|
|
15
|
+
* `error` | `blocked` (maps to the kit's tool hues), `label` is an optional
|
|
16
|
+
* short string beside the dot, and `pulse` animates the dot. Set it with
|
|
17
|
+
* `el.status = { tone: 'working', label: 'Working', pulse: true }`. */
|
|
18
18
|
status?: AgentStatus;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/** Events fired by `<kai-agent-card>`. */
|
|
22
22
|
interface Events {
|
|
23
|
-
/** The card was activated
|
|
24
|
-
* this agent back to focus. */
|
|
23
|
+
/** The card was activated by a click, or by Enter / Space while focused.
|
|
24
|
+
* Promote this agent back to focus. */
|
|
25
25
|
'kai-activate': void;
|
|
26
26
|
/** The trailing "..." kebab was clicked. The consumer opens its own menu; the
|
|
27
27
|
* card only surfaces the affordance (the click does not also activate the card). */
|
|
@@ -5,8 +5,10 @@ import { Artifact, type ArtifactController, type ArtifactFile, type ArtifactTab
|
|
|
5
5
|
interface Props extends Record<string, unknown> {
|
|
6
6
|
/** URL the preview iframe frames. Consumer-controlled. */
|
|
7
7
|
src?: string;
|
|
8
|
-
/** Files for the Code tab tree + each file's preview `url`.
|
|
9
|
-
|
|
8
|
+
/** Files for the Code tab tree + each file's preview `url`. Omit for a
|
|
9
|
+
* preview-only artifact (the Code tab then has nothing to show; pair it with
|
|
10
|
+
* `no-tabs` to hide the toggle). Set as a JS property (array). */
|
|
11
|
+
files?: ArtifactFile[];
|
|
10
12
|
/** Controlled active tab: `preview` or `code`. When set, the artifact follows it
|
|
11
13
|
* (re-asserted on change). Leave unset for an uncontrolled tab (see `defaultTab`). */
|
|
12
14
|
tab?: ArtifactTab;
|
|
@@ -14,7 +16,7 @@ interface Props extends Record<string, unknown> {
|
|
|
14
16
|
* Seeds the starting tab; the user can then switch freely without the consumer
|
|
15
17
|
* re-asserting a controlled `tab`. */
|
|
16
18
|
defaultTab?: ArtifactTab;
|
|
17
|
-
/** Selected file path
|
|
19
|
+
/** Selected file path. Syncs the tree highlight, Code source, and preview. */
|
|
18
20
|
activeFile?: string;
|
|
19
21
|
/** iframe `sandbox` override. Secure default `allow-scripts allow-forms` (NOT `allow-same-origin`). */
|
|
20
22
|
sandbox?: string;
|
|
@@ -56,6 +58,12 @@ interface Events extends Record<string, unknown> {
|
|
|
56
58
|
'kai-file-select': { path: string };
|
|
57
59
|
/** Artifact's own maximize button toggled (consumer-observable; non-bubbling). */
|
|
58
60
|
'kai-maximize-change': { maximized: boolean };
|
|
61
|
+
/** The maximize PROTOCOL intent, raised as a raw bubbling + composed CustomEvent
|
|
62
|
+
* (not through `dispatch`) so an enclosing `<kai-resizable>` can catch it and
|
|
63
|
+
* maximize the containing panel. Declared here so it is typed and reaches the
|
|
64
|
+
* generated API. Listen for it to drive maximize from your own chrome, or
|
|
65
|
+
* re-emit it to trigger one. */
|
|
66
|
+
'kai-maximize-intent': { requested: boolean };
|
|
59
67
|
}
|
|
60
68
|
|
|
61
69
|
/**
|
|
@@ -106,17 +114,17 @@ defineWebComponent<Props, Events>('kai-artifact', {
|
|
|
106
114
|
reload: () => controller?.reload(),
|
|
107
115
|
/** Navigate to the `src` home url (no-op when there's no `src`). */
|
|
108
116
|
home: () => controller?.home(),
|
|
109
|
-
/** Push + load a url in the preview
|
|
117
|
+
/** Push + load a url in the preview, the path-field submit path (fires kai-navigate). */
|
|
110
118
|
navigate: (url: string) => controller?.navigate(url),
|
|
111
119
|
/** Select a file by path: highlights the tree, shows its source, navigates the
|
|
112
120
|
* preview (fires kai-file-select + kai-navigate). Named selectFile to avoid the
|
|
113
121
|
* `activeFile` prop. */
|
|
114
122
|
selectFile: (path: string) => controller?.selectFile(path),
|
|
115
123
|
/** Open the current url in a new browser tab (no-op when there's no concrete url).
|
|
116
|
-
* Named openExternal, NOT openInTab
|
|
124
|
+
* Named openExternal, NOT openInTab, which is a prop (toolbar button visibility). */
|
|
117
125
|
openExternal: () => controller?.openExternal(),
|
|
118
126
|
/** Enter the maximized view-state (fires kai-maximize-change{maximized:true}).
|
|
119
|
-
* Named maximize, NOT maximized
|
|
127
|
+
* Named maximize, NOT maximized, which is a prop. */
|
|
120
128
|
maximize: () => controller?.maximize(),
|
|
121
129
|
/** Exit the maximized view-state (fires kai-maximize-change{maximized:false}). */
|
|
122
130
|
restore: () => controller?.restore(),
|
|
@@ -157,7 +165,7 @@ defineWebComponent<Props, Events>('kai-artifact', {
|
|
|
157
165
|
>
|
|
158
166
|
<Artifact
|
|
159
167
|
src={props.src}
|
|
160
|
-
files={props.files}
|
|
168
|
+
files={props.files ?? []}
|
|
161
169
|
tab={props.tab}
|
|
162
170
|
defaultTab={props.defaultTab}
|
|
163
171
|
activeFile={props.activeFile}
|