@kitn.ai/ui 0.25.2 → 0.26.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 +2 -2
- package/dist/components/attachment-types.d.ts +46 -1
- package/dist/components/attachments.d.ts +31 -0
- package/dist/components/audio-visualizer/fit-scale.d.ts +50 -0
- package/dist/components/audio-visualizer/index.d.ts +15 -1
- package/dist/components/audio-visualizer/variant-bar.d.ts +24 -1
- package/dist/components/chat-thread.d.ts +3 -41
- package/dist/components/code-block.d.ts +22 -0
- package/dist/components/conversation-item.d.ts +54 -1
- package/dist/components/conversation-list.d.ts +65 -0
- package/dist/components/form.d.ts +42 -0
- package/dist/components/message.d.ts +7 -0
- package/dist/components/toast.d.ts +2 -1
- package/dist/components/voice-input.d.ts +8 -0
- package/dist/components/voice-output.d.ts +12 -1
- package/dist/components/workspace-shell.d.ts +87 -0
- package/dist/{create-tween-B5Y4Im8G.js → create-tween-BFT6c-Y8.js} +1 -1
- package/dist/{create-tween-4z1XYLkR.js → create-tween-CJNlzoaO.js} +1 -1
- package/dist/{create-tween-CUzOlaMS.js → create-tween-CQED4T0g.js} +1 -1
- package/dist/custom-elements.json +2931 -2572
- package/dist/diagnostics/hook.d.ts +81 -0
- package/dist/diagnostics/index.d.ts +7 -0
- package/dist/diagnostics/report-request.d.ts +61 -0
- package/dist/diagnostics.d.ts +5 -0
- package/dist/diagnostics.js +209 -0
- 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/autoloader.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-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-b5A8hlHs.js → Icon--Y8vsFal.js} +1 -1
- package/dist/elements/chunks/action-icons-D9u3OzYW.js +1 -0
- package/dist/elements/chunks/arrow-left-CVh1TeN7.js +1 -0
- package/dist/elements/chunks/{artifact-BSuPYFHY.js → artifact-BkYcfIlZ.js} +1 -1
- package/dist/elements/chunks/attachments-DwfNlubq.js +1 -0
- package/dist/elements/chunks/audio-visualizer-D7lB6mvR.js +1 -0
- package/dist/elements/chunks/{badge-TIMiJFKc.js → badge-Q0-Cmwzz.js} +1 -1
- package/dist/elements/chunks/{button-B9okqG73.js → button-flUbeufF.js} +1 -1
- package/dist/elements/chunks/{card-renderer-CSoTL_e1.js → card-renderer-3Dyl-FpN.js} +1 -1
- package/dist/elements/chunks/check-B5kBPKeo.js +1 -0
- package/dist/elements/chunks/chevron-down-DZ1GS39h.js +1 -0
- package/dist/elements/chunks/chevron-right-CvP7OUd2.js +1 -0
- package/dist/elements/chunks/{choice-card-CGMc3kek.js → choice-card-D4QUIOWZ.js} +1 -1
- package/dist/elements/chunks/circle-CDf9g6MQ.js +1 -0
- package/dist/elements/chunks/circle-check-CA47Nqbz.js +1 -0
- package/dist/elements/chunks/{circle-x-mhH7pOK2.js → circle-x-CJ_HVbC8.js} +1 -1
- package/dist/elements/chunks/code-block-BdLiTitd.js +1 -0
- package/dist/elements/chunks/collapsible-BzbXpPzr.js +1 -0
- package/dist/elements/chunks/{composer-CZZmtYOT.js → composer-Byve-n8K.js} +2 -2
- package/dist/elements/chunks/{confirm-card-BWjf2-xo.js → confirm-card-B0flE3MN.js} +1 -1
- package/dist/elements/chunks/context-VLIL3sJ-.js +1 -0
- package/dist/elements/chunks/controllable-DTwTIlwp.js +1 -0
- package/dist/elements/chunks/conversation-item-BDztezOG.js +1 -0
- package/dist/elements/chunks/copy-Nf-kqxXH.js +1 -0
- package/dist/elements/chunks/{create-tween-CUrM6D_o.js → create-tween-c4Z8TDYz.js} +2 -2
- package/dist/elements/chunks/default-input-C2iLFq0b.js +1 -0
- package/dist/elements/chunks/define-wjHR1MkU.js +1 -0
- package/dist/elements/chunks/disclosure-CcNbyLy0.js +1 -0
- package/dist/elements/chunks/{download-DnCyWFJE.js → download-C4V7tBdb.js} +1 -1
- package/dist/elements/chunks/dropdown-BgWTthUx.js +1 -0
- package/dist/elements/chunks/{ellipsis-CVxqfsDZ.js → ellipsis-7gU33mL2.js} +1 -1
- package/dist/elements/chunks/embed-D3KewsIJ.js +1 -0
- package/dist/elements/chunks/{external-link-DG2sRdQL.js → external-link-CSOEsNlx.js} +1 -1
- package/dist/elements/chunks/{file-text-D0J9F6M7.js → file-text-D1G8khle.js} +1 -1
- package/dist/elements/chunks/{file-tree-yGWNK0Js.js → file-tree-zvB2i7P9.js} +1 -1
- package/dist/elements/chunks/{folder-NV1pi_ud.js → folder-WW2LGLid.js} +1 -1
- package/dist/elements/chunks/form-CQirdC4W.js +1 -0
- package/dist/elements/chunks/hover-card-CJJkfHTK.js +1 -0
- package/dist/elements/chunks/icon-Cfgmf4fa.js +1 -0
- package/dist/elements/chunks/{info-C8r5Q6cc.js → info-DX3YMOt6.js} +1 -1
- package/dist/elements/chunks/input-BtW9U6Sq.js +1 -0
- package/dist/elements/chunks/{kbd-OGJDUT-O.js → kbd-LGXwuT_V.js} +1 -1
- package/dist/elements/chunks/{link-BdsfLB7b.js → link-2My69BqT.js} +1 -1
- package/dist/elements/chunks/{link-preview-Cf5KOP-i.js → link-preview-OQ9IEq0f.js} +1 -1
- package/dist/elements/chunks/{loader-B5QzK_8_.js → loader-iOxc_Tu-.js} +1 -1
- package/dist/elements/chunks/{markdown-DbozyYqa.js → markdown-DgBFaGAz.js} +1 -1
- package/dist/elements/chunks/{message-DtXKPqiR.js → message-VMZohrXx.js} +1 -1
- package/dist/elements/chunks/message-circle-CpXMM-_n.js +1 -0
- package/dist/elements/chunks/message-square-DxcWtETQ.js +1 -0
- package/dist/elements/chunks/message-tZmV2A3p.js +1 -0
- package/dist/elements/chunks/{minimize-2-SegJ_oku.js → minimize-2-DPIUKTrT.js} +1 -1
- package/dist/elements/chunks/{model-switcher-D7JrFFHp.js → model-switcher-DsT8tFB0.js} +1 -1
- package/dist/elements/chunks/{overlay-CV7z2YuX.js → overlay-DuiwdXjm.js} +1 -1
- package/dist/elements/chunks/{paperclip-Bg0ITU3b.js → paperclip-CRZVp4z_.js} +1 -1
- package/dist/elements/chunks/{progress-bar-D1_rzt6N.js → progress-bar-DNy66e_E.js} +1 -1
- package/dist/elements/chunks/{prompt-suggestion-D5Sm8xF1.js → prompt-suggestion-Bn64Nl7L.js} +1 -1
- package/dist/elements/chunks/reasoning-Emn9N4-T.js +1 -0
- package/dist/elements/chunks/{resizable-Dpzjlvp4.js → resizable-D181b4fM.js} +1 -1
- package/dist/elements/chunks/{rotate-cw-DzVDJOA1.js → rotate-cw-CPWe37D9.js} +1 -1
- package/dist/elements/chunks/{scroll-area-93A1bbeG.js → scroll-area-ClZkZxIk.js} +1 -1
- package/dist/elements/chunks/scroll-button-DPE-t3x_.js +1 -0
- package/dist/elements/chunks/{separator-DH2r_ZSZ.js → separator-CeJHQqLW.js} +1 -1
- package/dist/elements/chunks/{settings-BFMOd6yB.js → settings-CqaHgJF9.js} +1 -1
- package/dist/elements/chunks/{settings-group-B3VZKIcz.js → settings-group-CjqjLCOn.js} +1 -1
- package/dist/elements/chunks/share-CyfnNEqp.js +1 -0
- package/dist/elements/chunks/{skeleton-N8BuWYmf.js → skeleton-D8akBnKS.js} +1 -1
- package/dist/elements/chunks/slots-DaNjX0rc.js +1 -0
- package/dist/elements/chunks/{source-w9V0NnBn.js → source-UWCvmVak.js} +1 -1
- package/dist/elements/chunks/{star-DHvACxtm.js → star-DoHFAikQ.js} +1 -1
- package/dist/elements/chunks/store-Cjq0qwYN.js +1 -0
- package/dist/elements/chunks/{tasks-card-lPxoodlA.js → tasks-card-CmZ5xh6v.js} +1 -1
- package/dist/elements/chunks/{text-shimmer-BY_rI3s5.js → text-shimmer-DYn09zrz.js} +1 -1
- package/dist/elements/chunks/textarea-skiGHURM.js +1 -0
- package/dist/elements/chunks/{thumbs-up-DQe0hvkZ.js → thumbs-up-DX2Ijk3H.js} +1 -1
- package/dist/elements/chunks/{toast-store-VUZZBhzH.js → toast-store-CFnQpThX.js} +1 -1
- package/dist/elements/chunks/{tool-C1YtxwPu.js → tool-DKQ2D1DP.js} +1 -1
- package/dist/elements/chunks/{tooltip-BqwnFWhn.js → tooltip-B0G99y8w.js} +1 -1
- package/dist/elements/chunks/{triangle-alert-B6or7F5u.js → triangle-alert-F9cyUEyy.js} +1 -1
- package/dist/elements/chunks/{use-card-resolution-DJg32jGH.js → use-card-resolution-DoA2f_EU.js} +1 -1
- package/dist/elements/chunks/{variant-aurora-QXTZPyST.js → variant-aurora-qt6Zct8M.js} +2 -2
- package/dist/elements/chunks/variant-custom-tJp22_BQ.js +1 -0
- package/dist/{variant-wave-BwzrHD1s.js → elements/chunks/variant-wave-CaQ5ti39.js} +2 -2
- package/dist/elements/chunks/x-B6UnOiLw.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-item.d.ts +1 -0
- package/dist/elements/conversation-item.js +1 -0
- package/dist/elements/conversation-list.js +1 -1
- package/dist/elements/default-input.d.ts +3 -3
- package/dist/elements/define.d.ts +27 -0
- package/dist/elements/diagnostic-events.d.ts +74 -0
- package/dist/elements/dialog.js +1 -1
- package/dist/elements/dock.d.ts +1 -0
- package/dist/elements/dock.js +149 -0
- package/dist/elements/dropdown.d.ts +1 -0
- package/dist/elements/dropdown.js +1 -0
- package/dist/elements/editable-label.js +1 -1
- package/dist/elements/element-diagnostics.d.ts +81 -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 +2 -0
- package/dist/elements/remote.js +1 -1
- package/dist/elements/resizable.js +1 -1
- package/dist/elements/response-stream.js +3 -3
- 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/slots.d.ts +35 -3
- 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/voice-input.js +1 -1
- package/dist/elements/voice-output.js +1 -1
- package/dist/elements.d.ts +232 -148
- package/dist/index.d.ts +2 -0
- package/dist/index.js +5456 -4931
- package/dist/index.server.js +4142 -3669
- package/dist/kai-provider.es.js +40 -40
- package/dist/kai.es.js +1 -1
- package/dist/llms/llms-full.txt +184 -69
- package/dist/llms/llms.txt +3 -3
- package/dist/mcp.es.js +2669 -546
- package/dist/primitives/use-resize-observer.d.ts +23 -0
- package/dist/primitives/use-speech-recognition.d.ts +8 -0
- package/dist/primitives/use-text-stream.d.ts +5 -0
- package/dist/react/index.d.ts +115 -266
- package/dist/react.js +247 -221
- package/dist/register-impl-DpE7icIb.js +293 -0
- package/dist/schemas/index.d.ts +1 -1
- package/dist/schemas/tool-defs.d.ts +35 -0
- package/dist/schemas.js +403 -310
- package/dist/{solid-BMuDmFo_.js → solid-BtdqNZI7.js} +8435 -7394
- package/dist/{solid-CGYNdLRR.js → solid-CnavwBye.js} +5987 -5035
- package/dist/solid.d.ts +5 -0
- package/dist/solid.js +210 -203
- package/dist/solid.server.js +210 -203
- package/dist/state/index.d.ts +4 -0
- package/dist/state/persistence.d.ts +51 -0
- package/dist/state/stream.d.ts +50 -0
- package/dist/state/threads.d.ts +71 -0
- package/dist/state.js +269 -169
- package/dist/types.d.ts +4 -2
- package/dist/ui/dock.d.ts +109 -0
- package/dist/ui/hover-card.d.ts +44 -0
- package/dist/{variant-aurora-DwSOfraQ.js → variant-aurora-B8II3-I1.js} +27 -27
- package/dist/{variant-aurora-wKvAQ5wp.js → variant-aurora-CMNWOSJR.js} +28 -28
- package/dist/{variant-aurora-XEkPT0_z.js → variant-aurora-CcuDMWwQ.js} +2 -2
- package/dist/{variant-custom-eFIg2XWQ.js → variant-custom-BdvYC7af.js} +40 -40
- package/dist/{variant-custom-BhS9wIpU.js → variant-custom-C714mqKl.js} +65 -65
- package/dist/variant-custom-L16JLLZy.js +1 -0
- package/dist/{elements/chunks/variant-wave-DDCwhLas.js → variant-wave-2S4La2Ka.js} +2 -2
- package/dist/{variant-wave-CbVsmgwT.js → variant-wave-D7ruiA1W.js} +25 -25
- package/dist/{variant-wave-CUWGx9Bn.js → variant-wave-ecwykeyL.js} +21 -21
- package/dist/wire/chunk.d.ts +47 -0
- package/dist/wire/diagnostics.d.ts +575 -0
- package/dist/wire/encode-probe.d.ts +70 -0
- package/dist/wire/encode.d.ts +24 -0
- package/dist/wire/index.d.ts +2 -0
- package/dist/wire/sse.d.ts +10 -2
- package/dist/wire.js +917 -480
- package/frameworks/react/index.tsx +132 -93
- package/llms-full.txt +184 -69
- package/llms.txt +3 -3
- package/package.json +26 -6
- package/src/agent-tooling/archetypes.ts +41 -9
- package/src/agent-tooling/catalog/README.md +676 -0
- package/src/agent-tooling/catalog/catalog-types.ts +231 -0
- package/src/agent-tooling/catalog/fabrications.ts +96 -0
- package/src/agent-tooling/catalog/invariants.ts +284 -0
- package/src/agent-tooling/catalog/labs-titles.ts +114 -0
- package/src/agent-tooling/catalog/scenarios.ts +87 -0
- package/src/agent-tooling/catalog/surfaces.ts +275 -0
- package/src/agent-tooling/integrations/anthropic.ts +7 -1
- package/src/agent-tooling/integrations/cloudflare.ts +43 -2
- package/src/agent-tooling/integrations/langgraph.ts +7 -1
- package/src/agent-tooling/integrations/mastra.ts +7 -1
- package/src/agent-tooling/integrations/mock.ts +92 -17
- package/src/agent-tooling/integrations/ollama.ts +7 -1
- package/src/agent-tooling/integrations/openai.ts +7 -1
- package/src/agent-tooling/integrations/openrouter.ts +7 -1
- package/src/agent-tooling/integrations/pi.ts +56 -1
- package/src/agent-tooling/integrations/vercel-ai-sdk.ts +7 -1
- package/src/agent-tooling/mcp/css-raw.d.ts +12 -0
- package/src/agent-tooling/mcp/manifest.ts +100 -1
- package/src/agent-tooling/mcp/server.ts +61 -5
- package/src/agent-tooling/mcp/tools/reference.ts +440 -4
- package/src/agent-tooling/mcp/tools/scaffold.ts +1834 -307
- package/src/agent-tooling/mcp/tools/theme.ts +146 -30
- package/src/agent-tooling/mcp/validate-args.ts +141 -0
- package/src/agent-tooling/registry.ts +19 -7
- package/src/agent-tooling/route-emit.ts +26 -2
- package/src/components/attachment-types.ts +47 -1
- package/src/components/attachments.tsx +169 -22
- package/src/components/audio-visualizer/fit-scale.ts +112 -0
- package/src/components/audio-visualizer/index.tsx +80 -3
- package/src/components/audio-visualizer/variant-aurora.tsx +10 -4
- package/src/components/audio-visualizer/variant-bar.tsx +38 -6
- package/src/components/audio-visualizer/variant-custom.tsx +8 -2
- package/src/components/audio-visualizer/variant-grid.tsx +16 -11
- package/src/components/audio-visualizer/variant-radial.tsx +15 -10
- package/src/components/audio-visualizer/variant-wave.tsx +7 -2
- package/src/components/chat-container.tsx +4 -1
- package/src/components/chat-thread.tsx +36 -7
- package/src/components/code-block.tsx +79 -3
- package/src/components/composer.tsx +8 -1
- package/src/components/conversation-item.tsx +114 -4
- package/src/components/conversation-list.tsx +212 -12
- package/src/components/embed.tsx +4 -0
- package/src/components/form.tsx +41 -14
- package/src/components/message.tsx +75 -5
- package/src/components/response-stream.tsx +13 -7
- package/src/components/screen.tsx +5 -0
- package/src/components/scroll-button.tsx +7 -0
- package/src/components/toast.tsx +11 -5
- package/src/components/voice-input.tsx +35 -3
- package/src/components/voice-output.tsx +46 -6
- package/src/components/workspace-shell.tsx +285 -0
- package/src/diagnostics/hook.ts +352 -0
- package/src/diagnostics/index.ts +82 -0
- package/src/diagnostics/report-request.ts +296 -0
- package/src/elements/attachments.tsx +6 -7
- package/src/elements/audio-visualizer.tsx +48 -4
- package/src/elements/chat-workspace.tsx +159 -287
- package/src/elements/chat.tsx +12 -9
- package/src/elements/code-block.tsx +19 -1
- package/src/elements/command.tsx +4 -1
- package/src/elements/compiled.css +1 -1
- package/src/elements/conversation-item.tsx +80 -0
- package/src/elements/conversation-list.tsx +60 -11
- package/src/elements/default-input.tsx +5 -5
- package/src/elements/define.tsx +168 -8
- package/src/elements/diagnostic-events.ts +114 -0
- package/src/elements/dialog.tsx +47 -0
- package/src/elements/disclosure.ts +34 -12
- package/src/elements/dock.tsx +204 -0
- package/src/elements/dropdown.tsx +123 -0
- package/src/elements/element-diagnostics.ts +392 -0
- package/src/elements/element-manifest.json +12 -0
- package/src/elements/element-meta.json +672 -439
- package/src/elements/element-nonscalar.json +170 -0
- package/src/elements/element-types.d.ts +232 -148
- package/src/elements/menu.tsx +13 -0
- package/src/elements/prompt-dock.tsx +2 -1
- package/src/elements/prompt-input.tsx +8 -8
- package/src/elements/register-impl.ts +46 -0
- package/src/elements/register.ts +28 -0
- package/src/elements/resizable.tsx +52 -25
- package/src/elements/scroll-button.tsx +5 -0
- package/src/elements/slots.ts +107 -12
- package/src/elements/styles.css +30 -6
- package/src/elements/thinking-bar.tsx +16 -7
- package/src/elements/toast.tsx +3 -0
- package/src/elements/tool.tsx +26 -5
- package/src/elements/voice-input.tsx +11 -2
- package/src/elements/voice-output.tsx +16 -3
- package/src/index.ts +2 -0
- package/src/primitives/use-resize-observer.ts +33 -0
- package/src/primitives/use-speech-recognition.ts +12 -1
- package/src/primitives/use-stick-to-bottom.ts +34 -2
- package/src/primitives/use-text-stream.ts +33 -2
- package/src/remote/provider-runtime.ts +6 -3
- package/src/schemas/index.ts +1 -0
- package/src/schemas/tool-defs.ts +297 -6
- package/src/solid.ts +5 -0
- package/src/state/index.ts +12 -0
- package/src/state/persistence.ts +180 -0
- package/src/state/stream.ts +71 -4
- package/src/state/threads.ts +142 -0
- package/src/types.ts +4 -2
- package/src/ui/dialog.tsx +6 -0
- package/src/ui/dock.tsx +445 -0
- package/src/ui/dropdown.tsx +67 -23
- package/src/ui/hover-card.tsx +156 -6
- package/src/ui/input.tsx +29 -10
- package/src/ui/resizable.tsx +11 -0
- package/src/wire/chunk.ts +47 -0
- package/src/wire/consume.ts +185 -26
- package/src/wire/diagnostics.ts +727 -0
- package/src/wire/encode-probe.ts +214 -0
- package/src/wire/encode.ts +267 -14
- package/src/wire/formats/anthropic.ts +8 -1
- package/src/wire/formats/openai.ts +5 -0
- package/src/wire/index.ts +22 -0
- package/src/wire/read.ts +250 -6
- package/src/wire/sse.ts +16 -3
- package/dist/elements/chunks/action-icons-DW9muWrY.js +0 -1
- package/dist/elements/chunks/arrow-left-iJVnQmxA.js +0 -1
- package/dist/elements/chunks/attachments-CL6TaqIb.js +0 -1
- package/dist/elements/chunks/audio-visualizer-BuUqQmaO.js +0 -1
- package/dist/elements/chunks/chat-thread-DxoKaStk.js +0 -1
- package/dist/elements/chunks/check-MdLzbxrm.js +0 -1
- package/dist/elements/chunks/chevron-down-MK7IzDqe.js +0 -1
- package/dist/elements/chunks/chevron-right-C5jXhmtV.js +0 -1
- package/dist/elements/chunks/circle-BG7VkPep.js +0 -1
- package/dist/elements/chunks/circle-check-GqvO2UBs.js +0 -1
- package/dist/elements/chunks/code-block-ClhQO9RW.js +0 -1
- package/dist/elements/chunks/collapsible-DBcBkFPh.js +0 -1
- package/dist/elements/chunks/context-hKjNqiyQ.js +0 -1
- package/dist/elements/chunks/conversation-list-CsGJjSKG.js +0 -1
- package/dist/elements/chunks/default-input-B1Mem5wu.js +0 -1
- package/dist/elements/chunks/define-B_tXMYRm.js +0 -1
- package/dist/elements/chunks/disclosure-DAoYOKew.js +0 -1
- package/dist/elements/chunks/dropdown-CmNna5lT.js +0 -1
- package/dist/elements/chunks/embed-CjAD2jSi.js +0 -1
- package/dist/elements/chunks/form-Cp8Y00Wn.js +0 -1
- package/dist/elements/chunks/hover-card-6KtXpLwT.js +0 -1
- package/dist/elements/chunks/icon-97R8SR2p.js +0 -1
- package/dist/elements/chunks/input-DrseEjhp.js +0 -1
- package/dist/elements/chunks/message-CE4k-qaj.js +0 -1
- package/dist/elements/chunks/message-square-C9ovmtOo.js +0 -1
- package/dist/elements/chunks/reasoning-BrxQfpfI.js +0 -1
- package/dist/elements/chunks/scroll-button-CrTo7wm4.js +0 -1
- package/dist/elements/chunks/share-DgNbkJKY.js +0 -1
- package/dist/elements/chunks/slots-CIw9RlAe.js +0 -1
- package/dist/elements/chunks/store-HIPGhNz9.js +0 -1
- package/dist/elements/chunks/textarea-DPfuhswM.js +0 -1
- package/dist/elements/chunks/variant-custom-D5ZlmziF.js +0 -1
- package/dist/elements/chunks/video-Bb86fVYI.js +0 -1
- package/dist/elements/chunks/x-BOhjBeOd.js +0 -1
- package/dist/primitives/card-validate-generator.testlib.d.ts +0 -20
- package/dist/register-impl-DGmGzrEM.js +0 -145
- package/dist/variant-custom-MkTNTycd.js +0 -1
- package/src/primitives/card-validate-generator.testlib.ts +0 -38
package/README.md
CHANGED
|
@@ -75,7 +75,7 @@ The element bundle is a self-contained ES module — load it directly from [jsDe
|
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
<!-- x-release-please-start-version -->
|
|
78
|
-
The URLs above track the **latest** release — handy for trying things out. **For production, pin an exact version** (e.g. `@kitn.ai/ui@0.
|
|
78
|
+
The URLs above track the **latest** release — handy for trying things out. **For production, pin an exact version** (e.g. `@kitn.ai/ui@0.26.0/dist/kai.es.js`): pinned URLs are immutable and cached far more aggressively, and — since this package is pre-1.0 — pinning shields you from breaking changes in a future minor release.
|
|
79
79
|
<!-- x-release-please-end -->
|
|
80
80
|
|
|
81
81
|
> **Pin `0.25.0` or newer.** Every version from `0.14.1` through `0.24.0` is covered by a [critical security advisory](https://github.com/kitn-ai/ui/security/advisories) and is deprecated on npm. `npm install` warns you about a deprecated version; **a CDN fetch does not**, so an old pinned URL in a page keeps serving the vulnerable bundle silently.
|
|
@@ -191,7 +191,7 @@ The components are deliberately **transport-agnostic**: `<kai-chat>` just render
|
|
|
191
191
|
</script>
|
|
192
192
|
```
|
|
193
193
|
|
|
194
|
-
Key point: `chat.messages` has to be reassigned with a **new array
|
|
194
|
+
Key point, and it is not only a streaming rule: `chat.messages` has to be reassigned with a **new array**, and any message you changed has to be a **new object**. The array reference is what tells the element something changed — reassigning the same array is a no-op even if you swapped a message inside it. The new message object is what makes the change visible, because the list keys its rows by item identity. Adds, removes and reorders need only the fresh array; editing an existing message needs both, and mutating one in place won't update the view even inside a fresh array. `createAssistantStream` satisfies both halves for you; if you drive `messages` by hand — editing a message, renaming a conversation — you own it.
|
|
195
195
|
|
|
196
196
|
`@kitn.ai/ui/wire` also ships `readAnthropicStream`, the helpers for a multi-round tool loop, and a seam for a custom wire format. See the [wire adapter recipe](https://ui.kitn.ai/guides/recipes/wire-adapter/).
|
|
197
197
|
|
|
@@ -8,5 +8,50 @@ export interface AttachmentData {
|
|
|
8
8
|
url?: string;
|
|
9
9
|
title?: string;
|
|
10
10
|
}
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* How an attachment is DRAWN, derived from what the wire can do with it.
|
|
13
|
+
*
|
|
14
|
+
* ★ THIS IS NOT A LIST OF MEDIA TYPES, and that is the whole point. It used to
|
|
15
|
+
* be one in disguise (`image | video | audio | document`, decided by a prefix
|
|
16
|
+
* switch in `attachments.tsx`), and it disagreed with `wire/media-types.ts` in
|
|
17
|
+
* both directions: SVG and MP4 drew a convincing preview that then threw at
|
|
18
|
+
* encode time, while PDF and text — the formats the wire handles best — drew
|
|
19
|
+
* the same anonymous icon as a `.zip`. `getMediaCategory` now asks the media
|
|
20
|
+
* policy and returns what it says, so there is one declaration and this is a
|
|
21
|
+
* projection of it.
|
|
22
|
+
*
|
|
23
|
+
* `image` / `document` / `text` ARE `EncodableKind` from `wire/media-types.ts`.
|
|
24
|
+
* They are spelled out rather than imported because this module is deliberately
|
|
25
|
+
* JSX-free and dependency-free for the framework-neutral consumers; the runtime
|
|
26
|
+
* agreement is pinned by `attachment-media-policy.test.tsx`, whose drift guard
|
|
27
|
+
* derives both sides from the policy.
|
|
28
|
+
*
|
|
29
|
+
* `video` and `audio` are GONE on purpose. No wire this kit ships can carry
|
|
30
|
+
* either, so they were categories whose only job was to make an unsendable file
|
|
31
|
+
* look sendable; both now land in `unsendable`.
|
|
32
|
+
*/
|
|
33
|
+
export type AttachmentMediaCategory =
|
|
34
|
+
/** A raster image in one of the four formats both APIs document. */
|
|
35
|
+
'image'
|
|
36
|
+
/** A PDF. Named for the Anthropic `document` block it becomes. */
|
|
37
|
+
| 'document'
|
|
38
|
+
/** Text content — `text/*`, JSON, XML, YAML. Rides as text on both wires. */
|
|
39
|
+
| 'text'
|
|
40
|
+
/** A RAG citation chip, not something the user staged. Never encoded. */
|
|
41
|
+
| 'source'
|
|
42
|
+
/**
|
|
43
|
+
* No wire format this kit ships can carry this type — SVG, BMP, video, audio,
|
|
44
|
+
* archives. That is a fact about the kit's encoders, knowable at render time
|
|
45
|
+
* and true of every provider, which is why it is safe to show the user.
|
|
46
|
+
*
|
|
47
|
+
* It is NOT "this will fail to send": the renderer does not know which
|
|
48
|
+
* provider a thread is bound for, and must not pretend to.
|
|
49
|
+
*/
|
|
50
|
+
| 'unsendable'
|
|
51
|
+
/**
|
|
52
|
+
* Nobody named this file, so nothing is known yet. Its bytes decide it (see
|
|
53
|
+
* `classifyAttachment`), and they have not been read at render time. Marking
|
|
54
|
+
* it `unsendable` would be a guess wearing a fact's clothes.
|
|
55
|
+
*/
|
|
56
|
+
| 'unknown';
|
|
12
57
|
export type AttachmentVariant = 'grid' | 'inline' | 'list';
|
|
@@ -1,7 +1,38 @@
|
|
|
1
1
|
import { JSX } from 'solid-js';
|
|
2
2
|
import { AttachmentData, AttachmentMediaCategory, AttachmentVariant } from './attachment-types.js';
|
|
3
3
|
export type { AttachmentData, AttachmentMediaCategory, AttachmentVariant } from './attachment-types.js';
|
|
4
|
+
/**
|
|
5
|
+
* What to DRAW for this attachment, asked of the one module that knows.
|
|
6
|
+
*
|
|
7
|
+
* ★ NO MEDIA TYPES APPEAR BELOW, and that is the fix. This function used to be
|
|
8
|
+
* a prefix switch — `image/` → image, `video/` → video, `application/` or
|
|
9
|
+
* `text/` → document — a second list of media types in a repo whose media-type
|
|
10
|
+
* declaration says, at its own definition, "if you find yourself writing a
|
|
11
|
+
* second list of media types anywhere in this repo, delete it and read this".
|
|
12
|
+
* It had drifted in both directions: `image/svg+xml` came back `image` and drew
|
|
13
|
+
* a real thumbnail for a format the encoder refuses outright, while
|
|
14
|
+
* `application/json` came back `document` when the wire carries it as text.
|
|
15
|
+
*
|
|
16
|
+
* `DEFAULT_MEDIA_POLICY` and not a narrowed one, on purpose. A developer's
|
|
17
|
+
* `accept` filter says what a user may STAGE; it says nothing about what an
|
|
18
|
+
* already-staged attachment IS, and narrowing here would redraw a message
|
|
19
|
+
* retroactively when a host changed a prop. The default policy is the kit's
|
|
20
|
+
* full capability set, so `unsupported` against it means exactly "no wire
|
|
21
|
+
* format this kit ships can carry this" — which is the only claim about
|
|
22
|
+
* sendability the renderer can honestly make without knowing the provider.
|
|
23
|
+
*/
|
|
4
24
|
export declare const getMediaCategory: (data: AttachmentData) => AttachmentMediaCategory;
|
|
25
|
+
/**
|
|
26
|
+
* The fact, written out, for the one category where the kit knows something the
|
|
27
|
+
* user needs to know.
|
|
28
|
+
*
|
|
29
|
+
* A FACT ABOUT THE FORMATS, NOT A PREDICTION ABOUT THIS REQUEST. At render time
|
|
30
|
+
* the kit does not know which provider the thread is bound for, so "this will
|
|
31
|
+
* fail" is not its to say. What it does know is that no wire format it ships
|
|
32
|
+
* has any representation for the type at all, which is true of every provider
|
|
33
|
+
* and is what this sentence claims.
|
|
34
|
+
*/
|
|
35
|
+
export declare const getUnsendableNote: (data: AttachmentData) => string | undefined;
|
|
5
36
|
export declare const getAttachmentLabel: (data: AttachmentData) => string;
|
|
6
37
|
interface AttachmentsContextValue {
|
|
7
38
|
variant: AttachmentVariant;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Accessor } from 'solid-js';
|
|
2
|
+
/**
|
|
3
|
+
* Fit-to-container scaling (owner finding, rung 2): the size tiers are fixed
|
|
4
|
+
* px by design (`sizes.ts`), so a container narrower than a tier's natural
|
|
5
|
+
* footprint used to CLIP the picture at its edges. The dispatcher now scales
|
|
6
|
+
* the WHOLE visualization down proportionally to fit, and renders byte-equal
|
|
7
|
+
* to the designed px metrics whenever the container is at least natural size.
|
|
8
|
+
*
|
|
9
|
+
* Why a transform-scale wrapper rather than relative units or reflow:
|
|
10
|
+
* - The px tiers ARE the design (LiveKit parity); switching the geometry to
|
|
11
|
+
* relative units would change rendering at every container size, not just
|
|
12
|
+
* the overflowing ones.
|
|
13
|
+
* - Reflowing (fewer bars, smaller gaps) changes what the animation MEANS;
|
|
14
|
+
* proportional scale keeps the exact picture, just smaller.
|
|
15
|
+
* - A transform also covers the shader variants for free: their canvases size
|
|
16
|
+
* their backing store from layout size (`clientWidth`), which a transform
|
|
17
|
+
* does not change, so the bitmap stays at full natural resolution and only
|
|
18
|
+
* the composited output shrinks. No variant needs an exception.
|
|
19
|
+
*
|
|
20
|
+
* Both sizes are MEASURED (one ResizeObserver watching both wrappers), never
|
|
21
|
+
* restated from `sizes.ts`: the natural footprint depends on variant, size
|
|
22
|
+
* tier, barCount/count/radius and the consumer's own part styling, and a
|
|
23
|
+
* hand-derived width table would rot the day any of those moved.
|
|
24
|
+
*
|
|
25
|
+
* Where ResizeObserver does not exist (SSR, jsdom) this is inert: scale stays
|
|
26
|
+
* 1 and nothing is written, which is exactly the pre-fix rendering.
|
|
27
|
+
*/
|
|
28
|
+
export declare function computeFitScale(available: number | undefined, natural: number | undefined): number;
|
|
29
|
+
export interface FitScale {
|
|
30
|
+
/** Ref for the outer wrapper (the host box, clamped by `max-width: 100%`). */
|
|
31
|
+
observeOuter: (el: HTMLElement) => void;
|
|
32
|
+
/** Ref for the inner wrapper (the natural-size content that gets scaled). */
|
|
33
|
+
observeInner: (el: HTMLElement) => void;
|
|
34
|
+
/** 1 when the content fits; the proportional shrink factor when it does not. */
|
|
35
|
+
scale: Accessor<number>;
|
|
36
|
+
/** The scaled content height in px while shrunk, else undefined: the outer
|
|
37
|
+
* wrapper adopts it so the page never reserves the unscaled height. */
|
|
38
|
+
scaledHeight: Accessor<number | undefined>;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* One ResizeObserver over both wrappers. ResizeObserver reports layout
|
|
42
|
+
* (border-box/content-box) sizes, which CSS transforms do not affect, so the
|
|
43
|
+
* inner wrapper keeps reporting its NATURAL size even while scaled, and the
|
|
44
|
+
* outer wrapper (whose `max-width: 100%` is what lets a narrow parent
|
|
45
|
+
* actually constrain it) reports the width the container is offering. The
|
|
46
|
+
* ratio of the two is the scale, with `computeFitScale` guarding the
|
|
47
|
+
* unmeasured/degenerate cases to 1 so a bad reading can never blank the
|
|
48
|
+
* element.
|
|
49
|
+
*/
|
|
50
|
+
export declare function createFitScale(): FitScale;
|
|
@@ -52,10 +52,24 @@ export interface AudioVisualizerProps {
|
|
|
52
52
|
complexity?: number;
|
|
53
53
|
/** Setting this makes the element an announced image instead of decorative. */
|
|
54
54
|
label?: string;
|
|
55
|
+
/** Live audio to analyze. NOTE: amplitude renders only while
|
|
56
|
+
* `state === 'speaking'` unless `listeningAmplitude` is set; every other
|
|
57
|
+
* state plays its scripted animation and the analysis output is unused. */
|
|
55
58
|
stream?: MediaStream;
|
|
59
|
+
/** Same speaking-only amplitude rule as `stream`: see `listeningAmplitude`. */
|
|
56
60
|
audioElement?: HTMLMediaElement;
|
|
57
|
-
/** Pre-computed levels. Set this and no AudioContext is ever constructed.
|
|
61
|
+
/** Pre-computed levels. Set this and no AudioContext is ever constructed.
|
|
62
|
+
* Same speaking-only amplitude rule as `stream`: see `listeningAmplitude`. */
|
|
58
63
|
bands?: number[];
|
|
64
|
+
/**
|
|
65
|
+
* Opt in to rendering live amplitude during `listening` as well, using the
|
|
66
|
+
* same presentation as `speaking`. Default off, which keeps LiveKit parity:
|
|
67
|
+
* amplitude (from `stream`, `audioElement` or `bands`) renders only while
|
|
68
|
+
* `state === 'speaking'`. Set this to show a real mic-level picture while
|
|
69
|
+
* the USER is the one talking. Forwarded to every variant; see
|
|
70
|
+
* `amplitudeRenderState` in variant-bar for the single mapping they share.
|
|
71
|
+
*/
|
|
72
|
+
listeningAmplitude?: boolean;
|
|
59
73
|
/**
|
|
60
74
|
* Custom fragment shader for `variant="custom"`. See `ShaderSpec` for the
|
|
61
75
|
* full contract -- most importantly, `fragment` MUST output premultiplied
|
|
@@ -5,8 +5,18 @@ import { VisualizerSize } from './sizes.js';
|
|
|
5
5
|
export interface VariantProps {
|
|
6
6
|
state: VisualizerState;
|
|
7
7
|
size: VisualizerSize;
|
|
8
|
-
/** Multiband levels, 0..1. Only read while `state === 'speaking'
|
|
8
|
+
/** Multiband levels, 0..1. Only read while `state === 'speaking'`, or also
|
|
9
|
+
* while `'listening'` when `listeningAmplitude` is set. */
|
|
9
10
|
bands: number[];
|
|
11
|
+
/**
|
|
12
|
+
* Opt in to rendering live amplitude during `listening` as well: the
|
|
13
|
+
* variant presents `listening` exactly as it presents `speaking` (live
|
|
14
|
+
* levels, lit geometry) while the host keeps reporting the real state via
|
|
15
|
+
* `data-kai-state`. Default off, which preserves LiveKit parity: amplitude
|
|
16
|
+
* renders only while `state === 'speaking'`, and every other state plays
|
|
17
|
+
* its scripted sequence. See `amplitudeRenderState`.
|
|
18
|
+
*/
|
|
19
|
+
listeningAmplitude?: boolean;
|
|
10
20
|
/** `prefers-reduced-motion`: pin the sequencer at its first frame. */
|
|
11
21
|
frozen: boolean;
|
|
12
22
|
/** Overrides the inherited `currentColor` the bars are painted with. */
|
|
@@ -41,6 +51,19 @@ export interface VariantProps {
|
|
|
41
51
|
* `packages/shadcn/components/agents-ui/agent-audio-visualizer-bar.tsx`
|
|
42
52
|
* (Apache License 2.0).
|
|
43
53
|
*/
|
|
54
|
+
/**
|
|
55
|
+
* The state the RENDERING follows, as opposed to the state the consumer set.
|
|
56
|
+
*
|
|
57
|
+
* `listeningAmplitude` opts the `listening` state into the full speaking
|
|
58
|
+
* presentation: every variant routes its state-driven decisions (levels,
|
|
59
|
+
* highlight sequence, thresholds, volume overrides) through this ONE mapping
|
|
60
|
+
* rather than each patching its own `=== 'speaking'` gates, so the opt-in
|
|
61
|
+
* cannot half-apply within a variant. The host's `data-kai-state` deliberately
|
|
62
|
+
* keeps the REAL state, so CSS hooks and consumers observing the element are
|
|
63
|
+
* never lied to. With the flag absent or false this is the identity mapping,
|
|
64
|
+
* which is what keeps the default byte-identical to LiveKit parity.
|
|
65
|
+
*/
|
|
66
|
+
export declare function amplitudeRenderState(state: VisualizerState, listeningAmplitude: boolean | undefined): VisualizerState;
|
|
44
67
|
export declare function BarVisualizer(props: VariantProps & {
|
|
45
68
|
barCount?: number;
|
|
46
69
|
}): JSX.Element;
|
|
@@ -98,8 +98,8 @@ export interface ChatThreadProps {
|
|
|
98
98
|
accept?: MediaTypeFilter;
|
|
99
99
|
/** Files the composer refused because `accept` excluded them. */
|
|
100
100
|
onAttachmentsRejected?: (rejected: RejectedAttachment[]) => void;
|
|
101
|
-
/** Show a
|
|
102
|
-
|
|
101
|
+
/** Show a web-search (Globe) button in the input toolbar; calls `onWebSearch`. */
|
|
102
|
+
webSearch?: boolean;
|
|
103
103
|
/** Show a Voice (Mic) button in the input toolbar; fires a `voice` event. */
|
|
104
104
|
voice?: boolean;
|
|
105
105
|
/** Rich entity triggers. Each `{ char, kind, items }` opens a caret-anchored
|
|
@@ -120,7 +120,7 @@ export interface ChatThreadProps {
|
|
|
120
120
|
onSuggestionClick?: (value: string) => void;
|
|
121
121
|
onModelChange?: (modelId: string) => void;
|
|
122
122
|
onMessageAction?: (detail: MessageActionDetail) => void;
|
|
123
|
-
|
|
123
|
+
onWebSearch?: () => void;
|
|
124
124
|
onVoice?: () => void;
|
|
125
125
|
/** Receive the imperative controller once mounted. The kai-chat facade forwards
|
|
126
126
|
* these as element methods (focus/clear/send/scrollToBottom). */
|
|
@@ -134,42 +134,4 @@ export interface ChatThreadController {
|
|
|
134
134
|
send(): void;
|
|
135
135
|
scrollToBottom(behavior?: ScrollBehavior): void;
|
|
136
136
|
}
|
|
137
|
-
/**
|
|
138
|
-
* THE MESSAGE LIST'S KEY, and the reason it is not the message object. This is
|
|
139
|
-
* the canonical note; `thread.tsx` keys its identical list the same way and
|
|
140
|
-
* points here.
|
|
141
|
-
*
|
|
142
|
-
* `<For>` is REFERENCE-keyed, and a streaming assistant message gets a brand
|
|
143
|
-
* new object identity on every delta — `createAssistantStream` rebuilds it as
|
|
144
|
-
* `{ ...prev[i], parts: next }` because a new reference IS the re-render
|
|
145
|
-
* signal. Keyed on the objects, every chunk therefore looks like an entirely
|
|
146
|
-
* new list: the whole message row is torn down and rebuilt, and everything the
|
|
147
|
-
* user did inside it dies with it. Expanding a tool or reasoning panel
|
|
148
|
-
* mid-stream did nothing at all — the disclosure opened and was discarded
|
|
149
|
-
* microseconds later by the next token. (`MessageBody` keys its PARTS by
|
|
150
|
-
* position for exactly this reason; that fix was dead while its parent kept
|
|
151
|
-
* destroying the subtree above it.)
|
|
152
|
-
*
|
|
153
|
-
* So key on `message.id`, which is stable across the object churn: `<For>` over
|
|
154
|
-
* the id array diffs by string value, a delta produces an identical id list,
|
|
155
|
-
* and no row moves. The row then reads its message through `messages[i()]` —
|
|
156
|
-
* `<For>`'s index accessor, which it keeps current across inserts, removals and
|
|
157
|
-
* moves — so the CONTENT keeps updating through accessors while the DOM stays
|
|
158
|
-
* put.
|
|
159
|
-
*
|
|
160
|
-
* WHY NOT `<Index>`, the other way to survive the churn: `<Index>` keys by
|
|
161
|
-
* POSITION, so a row's local state (an open panel, a half-filled form card)
|
|
162
|
-
* belongs to the slot rather than to the message. Appends and tail truncations
|
|
163
|
-
* (regenerate/edit) are fine, but prepending older turns — load-earlier-history,
|
|
164
|
-
* which every real chat grows — shifts every row, and each open disclosure
|
|
165
|
-
* stays behind with the wrong message. Position IS a valid key inside a
|
|
166
|
-
* message, where the folds only ever append or patch a part in place; it is not
|
|
167
|
-
* one for the message list, where the host owns the array and splices it.
|
|
168
|
-
* Both approaches require the row to read through accessors — that is inherent
|
|
169
|
-
* in keeping a row mounted while its object is replaced, not a cost unique to
|
|
170
|
-
* either.
|
|
171
|
-
*
|
|
172
|
-
* Contract: `id` must be unique per message. It already had to be — the
|
|
173
|
-
* feedback/copy state above this list is keyed by it.
|
|
174
|
-
*/
|
|
175
137
|
export declare function ChatThread(props: ChatThreadProps): import("solid-js").JSX.Element;
|
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
import { JSX } from 'solid-js';
|
|
2
2
|
export interface CodeBlockProps extends JSX.HTMLAttributes<HTMLDivElement> {
|
|
3
3
|
children?: JSX.Element;
|
|
4
|
+
/**
|
|
5
|
+
* Render a copy button in a header row above the code.
|
|
6
|
+
*
|
|
7
|
+
* DEFAULT OFF, and deliberately. This component is shared by three surfaces —
|
|
8
|
+
* `markdown.tsx` (every fenced block in every assistant message), `artifact.tsx`
|
|
9
|
+
* (the code panel), and the `<kai-code-block>` facade — and only the ELEMENT is
|
|
10
|
+
* documented as shipping a copy button. Defaulting on would add one to every code
|
|
11
|
+
* block in every message, a kit-wide visible change. The facade opts in; the other
|
|
12
|
+
* two are untouched, which `tests/elements/code-block.test.tsx` pins both
|
|
13
|
+
* behaviourally and at the call sites.
|
|
14
|
+
*/
|
|
15
|
+
copy?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* The exact text the copy button puts on the clipboard.
|
|
18
|
+
*
|
|
19
|
+
* Named for what it DOES rather than what it holds, because the distinction is the
|
|
20
|
+
* whole contract: by the time the button is clicked the source has been through
|
|
21
|
+
* Shiki, so anything read back out of the DOM is either `<span>`-laden HTML or a
|
|
22
|
+
* `textContent` reconstruction — and the reconstruction is where tabs, blank lines
|
|
23
|
+
* and trailing newlines quietly change. This prop never goes near the highlighter.
|
|
24
|
+
*/
|
|
25
|
+
copyText?: string;
|
|
4
26
|
}
|
|
5
27
|
declare function CodeBlock(props: CodeBlockProps): JSX.Element;
|
|
6
28
|
export interface CodeBlockCodeProps extends JSX.HTMLAttributes<HTMLDivElement> {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { JSX } from 'solid-js';
|
|
1
2
|
import { ConversationSummary } from '../types.js';
|
|
2
3
|
export interface ConversationItemProps {
|
|
3
4
|
conversation: ConversationSummary;
|
|
@@ -14,4 +15,56 @@ export interface ConversationItemProps {
|
|
|
14
15
|
* ticking clock. Returns '' for a missing or unparseable date.
|
|
15
16
|
*/
|
|
16
17
|
export declare function relativeTimeShort(iso?: string, now?: number): string;
|
|
17
|
-
|
|
18
|
+
/**
|
|
19
|
+
* The slotted-item shape rendered by `<kai-conversation-item>` — the composed
|
|
20
|
+
* row of the consumer-owned loop (spec 2026-08-20 § 2a). Distinct from the
|
|
21
|
+
* data-mode `ConversationItem` above, which batteries mode keeps rendering
|
|
22
|
+
* unchanged: this one takes REGIONS, not a `ConversationSummary`.
|
|
23
|
+
*
|
|
24
|
+
* Regions map 1:1 to the element's slots: `children` = the default slot (the
|
|
25
|
+
* title), plus `leading`, `meta`, and `menu`. The `menu` region takes the
|
|
26
|
+
* consumer's OWN popover (rename / fork / archive live there); the component
|
|
27
|
+
* provides only the region plus focus and ARIA plumbing, never a declarative
|
|
28
|
+
* actions prop. Activation semantics live in the CONTAINER
|
|
29
|
+
* (`createConversationItemsController` in conversation-list.tsx): this row is
|
|
30
|
+
* presentational, and the `data-kai-item-menu` marker on the menu region is what
|
|
31
|
+
* the container's activation guard keys off so a click in the consumer's menu
|
|
32
|
+
* never also selects the row.
|
|
33
|
+
*
|
|
34
|
+
* ARIA contract for direct Solid use: the row renders `role="listitem"` holding
|
|
35
|
+
* a `role="button"` body (`aria-current` marks the active row, the same dialect
|
|
36
|
+
* as the batteries-mode row above) with the menu as the body's tabbable SIBLING
|
|
37
|
+
* (ratified 2026-08-20; axe `nested-interactive` bans focusable descendants of
|
|
38
|
+
* a control, and `aria-required-children` outlaws non-option content anywhere
|
|
39
|
+
* inside a listbox, which is why the vocabulary is not listbox/option). Render
|
|
40
|
+
* your loop's rows inside a `role="list"` ancestor; element mode has no such
|
|
41
|
+
* burden: `<kai-conversations>`' items region provides it for slotted items.
|
|
42
|
+
*/
|
|
43
|
+
export interface SlottedConversationItemProps {
|
|
44
|
+
/** The row's identity, handed to the container's selection contract. In the
|
|
45
|
+
* element this is the `conversation-id` attribute (host `id` is the fallback). */
|
|
46
|
+
conversationId?: string;
|
|
47
|
+
/** Selected state. Reflected as `aria-current` on the row body and a
|
|
48
|
+
* `data-active` styling hook on the row; the container drives it from its
|
|
49
|
+
* `activeId`. */
|
|
50
|
+
active?: boolean;
|
|
51
|
+
/** Dense single-line row padding. */
|
|
52
|
+
compact?: boolean;
|
|
53
|
+
/** Leading region before the title (an icon or avatar). */
|
|
54
|
+
leading?: JSX.Element;
|
|
55
|
+
/** Meta region under the title (a timestamp or status line). */
|
|
56
|
+
meta?: JSX.Element;
|
|
57
|
+
/** Your own row menu (a popover trigger). Never selects the row. */
|
|
58
|
+
menu?: JSX.Element;
|
|
59
|
+
/** The title (the element's default slot). */
|
|
60
|
+
children?: JSX.Element;
|
|
61
|
+
/** Set when the element HOST carries the row-group semantics: the inner row
|
|
62
|
+
* then renders `role="presentation"` so the accessibility tree sees one
|
|
63
|
+
* group (the host), never two. The `kai-conversation-item` facade sets it;
|
|
64
|
+
* Solid consumers rendering the component directly leave it off and the row
|
|
65
|
+
* itself is the group. */
|
|
66
|
+
hostSemantics?: boolean;
|
|
67
|
+
class?: string;
|
|
68
|
+
}
|
|
69
|
+
export declare function SlottedConversationItem(props: SlottedConversationItemProps): JSX.Element;
|
|
70
|
+
export declare function ConversationItem(props: ConversationItemProps): JSX.Element;
|
|
@@ -13,6 +13,57 @@ export interface CollapsedRailProps {
|
|
|
13
13
|
class?: string;
|
|
14
14
|
}
|
|
15
15
|
export declare function CollapsedRail(props: CollapsedRailProps): JSX.Element;
|
|
16
|
+
/** Read a conversation item's identity the way the container does: the
|
|
17
|
+
* `conversationId` property, else the `conversation-id` attribute, else the
|
|
18
|
+
* host `id`. The property is what a framework loop sets; the attributes are
|
|
19
|
+
* the plain-HTML spellings (host `id` matches the `<kai-conversation>`
|
|
20
|
+
* data-carrier precedent). */
|
|
21
|
+
export declare function readConversationItemId(el: Element): string;
|
|
22
|
+
export interface ConversationItemsControllerOptions {
|
|
23
|
+
/** The current slotted item hosts, in DOM order. */
|
|
24
|
+
getItems: () => HTMLElement[];
|
|
25
|
+
/** The container's active conversation id. */
|
|
26
|
+
getActiveId: () => string | undefined;
|
|
27
|
+
/** Item activation (click / Enter / Space). Surfaces as
|
|
28
|
+
* `kai-conversation-select` on the element. */
|
|
29
|
+
onSelect: (id: string) => void;
|
|
30
|
+
}
|
|
31
|
+
export interface ConversationItemsController {
|
|
32
|
+
/** Re-derive the ARIA/roving-tabindex bookkeeping over the current items.
|
|
33
|
+
* Call on slotchange / child mutation and whenever `activeId` changes. */
|
|
34
|
+
sync(): void;
|
|
35
|
+
/** The container's items-region click handler (composed-path aware). */
|
|
36
|
+
handleClick(e: MouseEvent): void;
|
|
37
|
+
/** The container's items-region keydown handler (arrows, Home/End,
|
|
38
|
+
* Enter/Space). */
|
|
39
|
+
handleKeyDown(e: KeyboardEvent): void;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The parent-item contract of item mode (spec 2026-08-20 § 2a), as a pure-DOM
|
|
43
|
+
* controller so it is host-agnostic: the `kai-conversations` facade wires it over
|
|
44
|
+
* its slotted `kai-conversation-item` children, and the jsdom contract tests
|
|
45
|
+
* drive it over plain nodes. Solid context cannot cross the element boundary
|
|
46
|
+
* (each facade is its own Solid root), so the channel is DOM traversal by
|
|
47
|
+
* construction:
|
|
48
|
+
*
|
|
49
|
+
* - selection flows container to item — exactly one item's BODY node (the
|
|
50
|
+
* shadow body of a `kai-conversation-item`, else the node itself; see
|
|
51
|
+
* `bodyOf`) is `aria-current="true"`, plus the `active` property on the
|
|
52
|
+
* host for the item's own styling hook;
|
|
53
|
+
* - `role="button"` is ensured on each item's body node (an authored role is
|
|
54
|
+
* left alone);
|
|
55
|
+
* - roving tabindex — exactly one body node `tabindex="0"` (the active
|
|
56
|
+
* item's, else the first's), the rest `-1`, re-derived on every `sync()`;
|
|
57
|
+
* menu content keeps its natural tab order (it is the body's SIBLING, per
|
|
58
|
+
* the ratified 2026-08-20 sibling restructure);
|
|
59
|
+
* - activation (click / Enter / Space) calls `onSelect` with the item's id, and
|
|
60
|
+
* is SUPPRESSED when the composed path crosses the item's `menu` region
|
|
61
|
+
* (light-DOM `slot="menu"` content or the shadow `data-kai-item-menu`
|
|
62
|
+
* wrapper), so the consumer's own popover never also selects the row;
|
|
63
|
+
* - ArrowUp/ArrowDown/Home/End move focus item-to-item, tabindex following the
|
|
64
|
+
* focused item.
|
|
65
|
+
*/
|
|
66
|
+
export declare function createConversationItemsController(opts: ConversationItemsControllerOptions): ConversationItemsController;
|
|
16
67
|
export interface ConversationListProps {
|
|
17
68
|
groups: ConversationGroup[];
|
|
18
69
|
conversations: ConversationSummary[];
|
|
@@ -34,6 +85,20 @@ export interface ConversationListProps {
|
|
|
34
85
|
/** Receive the imperative controller once mounted. The `kai-conversations`
|
|
35
86
|
* facade uses it to focus / clear the internal search input. */
|
|
36
87
|
controllerRef?: (controller: ConversationListController) => void;
|
|
88
|
+
/** Item mode (spec 2026-08-20 § 2a): the consumer's OWN rows, rendered inside
|
|
89
|
+
* a list region in place of the data rows. When set, the built-in search
|
|
90
|
+
* filter, grouping and empty/no-match states do not apply — the consumer's
|
|
91
|
+
* loop owns them — while the chrome (header, search box, new-chat, footer)
|
|
92
|
+
* still renders and `onSearchChange` still reports queries. The
|
|
93
|
+
* `kai-conversations` facade passes its default `<slot>` here when it detects
|
|
94
|
+
* `kai-conversation-item` children. */
|
|
95
|
+
items?: JSX.Element;
|
|
96
|
+
/** Keydown handler for the item-mode list region (the facade wires
|
|
97
|
+
* `createConversationItemsController.handleKeyDown`). */
|
|
98
|
+
itemsKeyDown?: (e: KeyboardEvent) => void;
|
|
99
|
+
/** Click handler for the item-mode list region (the facade wires
|
|
100
|
+
* `createConversationItemsController.handleClick`). */
|
|
101
|
+
itemsClick?: (e: MouseEvent) => void;
|
|
37
102
|
class?: string;
|
|
38
103
|
}
|
|
39
104
|
/** Imperative handle exposed via `controllerRef` — surfaces the internal search
|
|
@@ -94,3 +94,45 @@ export interface FormProps {
|
|
|
94
94
|
* `kai-card` CustomEvent.
|
|
95
95
|
*/
|
|
96
96
|
export declare function Form(props: FormProps): JSX.Element;
|
|
97
|
+
interface FieldRowProps {
|
|
98
|
+
fieldKey: string;
|
|
99
|
+
field: FormField;
|
|
100
|
+
required: boolean;
|
|
101
|
+
inlineMax: number;
|
|
102
|
+
value: () => unknown;
|
|
103
|
+
error: () => string | undefined;
|
|
104
|
+
disabled: boolean;
|
|
105
|
+
onInput: (value: unknown) => void;
|
|
106
|
+
onBlur: () => void;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The widget prop bag for one field row. **Internal** — exported only so the
|
|
110
|
+
* subscription contract can be pinned directly
|
|
111
|
+
* (`tests/components/form-field-subscriptions.test.tsx`); it is not re-exported
|
|
112
|
+
* from the package.
|
|
113
|
+
*
|
|
114
|
+
* GETTERS, NOT AN OBJECT FACTORY, and this is the whole point (K-D12b). The
|
|
115
|
+
* factory read `props.value()` alongside everything else and rebuilt the bag on
|
|
116
|
+
* every call, so a reader of ANY prop — `invalid`, say — subscribed to `value`
|
|
117
|
+
* too and re-ran on every keystroke. Combined with the `<input>` being rebuilt
|
|
118
|
+
* when its class expression re-ran (K-D12a), that is what made typing into a
|
|
119
|
+
* `kai-form` text field lose focus after each character.
|
|
120
|
+
*
|
|
121
|
+
* One stable object with one getter per prop: each reader tracks exactly the
|
|
122
|
+
* signal behind the prop it read. The object identity is constant, so the
|
|
123
|
+
* `WidgetSwitch` prop below never changes either.
|
|
124
|
+
*/
|
|
125
|
+
export declare function fieldCommon(props: FieldRowProps, id: string, placeholder: () => string | undefined, label: () => string, describedBy?: () => string | undefined): ReturnType<FieldRowCommon>;
|
|
126
|
+
type FieldRowCommon = () => {
|
|
127
|
+
id: string;
|
|
128
|
+
value: unknown;
|
|
129
|
+
field: FormField;
|
|
130
|
+
disabled: boolean;
|
|
131
|
+
placeholder?: string;
|
|
132
|
+
required: boolean;
|
|
133
|
+
invalid: boolean;
|
|
134
|
+
describedBy?: string;
|
|
135
|
+
label: string;
|
|
136
|
+
onInput: (v: unknown) => void;
|
|
137
|
+
onBlur: () => void;
|
|
138
|
+
};
|
|
@@ -123,6 +123,13 @@ export interface MessageBodyProps {
|
|
|
123
123
|
activeFeedback?: FeedbackVote;
|
|
124
124
|
/** When true, the copy button shows its "copied" check icon. */
|
|
125
125
|
copied?: boolean;
|
|
126
|
+
/** Whether this message is the one currently streaming. Forwarded to each
|
|
127
|
+
* reasoning part's `<Reasoning>` so the disclosure auto-opens while the
|
|
128
|
+
* model is thinking and settles back once the stream ends (F-21: without it
|
|
129
|
+
* the user watches a static collapsed "Reasoning" label for the whole
|
|
130
|
+
* thinking window). The caller owns the definition of "streaming" — for
|
|
131
|
+
* `ChatThread` that is `loading` + being the last assistant message. */
|
|
132
|
+
isStreaming?: boolean;
|
|
126
133
|
/** INJECT slot projected at the TOP of the body — above the reasoning / tools /
|
|
127
134
|
* content. A per-message header: a model-name label, a role + timestamp line.
|
|
128
135
|
* In the `<kai-message>` shadow this is `<slot name="before-body" />`. */
|
|
@@ -53,6 +53,7 @@ export declare function Toast(props: ToastProps): import("solid-js").JSX.Element
|
|
|
53
53
|
* Renders a stack of toasts at a viewport edge. Caps the visible count at `max`
|
|
54
54
|
* (newest on top); overflow waits in a queue and is promoted as visible toasts
|
|
55
55
|
* leave. `aria-live=polite` / `role=region` so screen readers announce new
|
|
56
|
-
* toasts without stealing focus.
|
|
56
|
+
* toasts without stealing focus. Your app chrome must stay below the toast
|
|
57
|
+
* layer; set `--kai-toast-z` (default 100) on the host to move the layer.
|
|
57
58
|
*/
|
|
58
59
|
export declare function ToastRegion(props: ToastRegionProps): import("solid-js").JSX.Element;
|
|
@@ -30,5 +30,13 @@ export interface VoiceInputProps {
|
|
|
30
30
|
/** Receive the imperative controller once mounted. The `<kai-voice-input>`
|
|
31
31
|
* facade forwards these as element methods (start/stop). */
|
|
32
32
|
controllerRef?: (controller: VoiceInputController) => void;
|
|
33
|
+
/** A recognition session failed or produced nothing. `error` is the platform
|
|
34
|
+
* error code, the thrown exception's name, or `no-result` when the session
|
|
35
|
+
* ended with no error and no text. The facade maps this to kai-voice-error. */
|
|
36
|
+
onError?: (detail: {
|
|
37
|
+
source: 'recognition';
|
|
38
|
+
error: string;
|
|
39
|
+
message: string;
|
|
40
|
+
}) => void;
|
|
33
41
|
}
|
|
34
42
|
export declare function VoiceInput(props: VoiceInputProps): import("solid-js").JSX.Element;
|
|
@@ -20,8 +20,19 @@ export interface VoiceOutputProps {
|
|
|
20
20
|
/** TTS model seam: given text, return an audio Blob to play. When set, the
|
|
21
21
|
* native speechSynthesis path is bypassed. Mirrors VoiceInput's `onTranscribe`. */
|
|
22
22
|
onSynthesize?: (text: string) => Promise<Blob>;
|
|
23
|
-
/** Fires whenever playback starts or stops.
|
|
23
|
+
/** Fires whenever playback starts or stops. `speaking: true` means audio has
|
|
24
|
+
* actually started (utterance.onstart on the native path; audio.play()
|
|
25
|
+
* resolving on the model path), not that speak() was called. */
|
|
24
26
|
onSpeakingChange?: (speaking: boolean) => void;
|
|
27
|
+
/** Synthesis failed: a native utterance error, a rejecting `onSynthesize`, or
|
|
28
|
+
* audio playback failing to start. `error` is the platform error code or the
|
|
29
|
+
* exception's name. Deliberate cancellation (stop(), a new speak()) is not a
|
|
30
|
+
* failure and does not fire. The facade maps this to kai-voice-error. */
|
|
31
|
+
onError?: (detail: {
|
|
32
|
+
source: 'synthesis';
|
|
33
|
+
error: string;
|
|
34
|
+
message: string;
|
|
35
|
+
}) => void;
|
|
25
36
|
/** Fires once the model path resolves audio (model path only). */
|
|
26
37
|
onSynthesized?: (blob: Blob) => void;
|
|
27
38
|
disabled?: boolean;
|