@kitn.ai/ui 0.25.1 → 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 +5 -7
- 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 +27 -7
- 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
|
@@ -1,148 +1,125 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createSignal, onMount, onCleanup, untrack } from 'solid-js';
|
|
2
2
|
import { defineWebComponent } from './define';
|
|
3
|
-
import { createControllableSignal } from '../primitives/controllable';
|
|
4
3
|
import { readSlots, WORKSPACE_SLOTS } from './slots';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
import type { ChatMessage } from './chat-types';
|
|
13
|
-
import type { ProseSize } from '../primitives/chat-config';
|
|
14
|
-
import type { ModelOption, ConversationGroup, ConversationSummary } from '../types';
|
|
4
|
+
import {
|
|
5
|
+
WorkspaceShell,
|
|
6
|
+
type WorkspaceShellController,
|
|
7
|
+
type WorkspaceAsideSide,
|
|
8
|
+
type WorkspaceAsideToggleDetail,
|
|
9
|
+
type WorkspaceAsideResizeDetail,
|
|
10
|
+
} from '../components/workspace-shell';
|
|
15
11
|
|
|
16
12
|
interface Props extends Record<string, unknown> {
|
|
17
|
-
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
*
|
|
28
|
-
* `
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
*
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
suggestions?: string[];
|
|
40
|
-
suggestionMode?: 'submit' | 'fill';
|
|
41
|
-
proseSize?: ProseSize;
|
|
42
|
-
codeTheme?: string;
|
|
43
|
-
codeHighlight?: boolean;
|
|
44
|
-
chatTitle?: string;
|
|
45
|
-
models?: ModelOption[];
|
|
46
|
-
currentModel?: string;
|
|
47
|
-
context?: ChatThreadContextUsage;
|
|
48
|
-
scrollButton?: boolean;
|
|
49
|
-
search?: boolean;
|
|
50
|
-
voice?: boolean;
|
|
51
|
-
/** Rich entity triggers (`/` skills, `@` agents/plugins) forwarded to the input. */
|
|
52
|
-
triggers?: TriggerDef[];
|
|
53
|
-
/** Default icon per entity kind (kind → image src) forwarded to the input. */
|
|
54
|
-
kindIcons?: Record<string, string>;
|
|
55
|
-
/** Sidebar default width as a percent of the workspace (default 26). */
|
|
56
|
-
sidebarWidth?: number;
|
|
57
|
-
/** Sidebar min width in px (default 240). */
|
|
58
|
-
sidebarMinWidth?: number;
|
|
59
|
-
/** Sidebar max width in px (default 420). */
|
|
60
|
-
sidebarMaxWidth?: number;
|
|
61
|
-
/** Controlled collapsed state. Set this as a JS property (`el.sidebarCollapsed
|
|
62
|
-
* = true`) to drive the sidebar from your app, updating it in response to the
|
|
63
|
-
* `kai-sidebar-toggle` event. Omit for uncontrolled (the element manages it). */
|
|
64
|
-
sidebarCollapsed?: boolean;
|
|
65
|
-
/** Initial collapsed state when uncontrolled (default false). Use the
|
|
66
|
-
* `default-sidebar-collapsed` attribute to start collapsed in plain HTML. */
|
|
67
|
-
defaultSidebarCollapsed?: boolean;
|
|
68
|
-
/** Auto-collapse the rail when the workspace's own width drops below this many
|
|
69
|
-
* px, and re-expand when it grows back above. Uncontrolled only (it never
|
|
70
|
-
* fights an app-driven `sidebarCollapsed`); omit to disable. Fires
|
|
71
|
-
* `kai-sidebar-toggle`. Attribute: `collapse-below`. */
|
|
13
|
+
/** Controlled collapsed state of the start aside. Set this as a JS property
|
|
14
|
+
* (`el.startCollapsed = true`) to drive the aside from your app, updating it
|
|
15
|
+
* in response to the `kai-aside-toggle` event. Omit for uncontrolled (the
|
|
16
|
+
* element manages it). */
|
|
17
|
+
startCollapsed?: boolean;
|
|
18
|
+
/** Initial collapsed state of the start aside when uncontrolled (default
|
|
19
|
+
* false). Use the `default-start-collapsed` attribute to start collapsed in
|
|
20
|
+
* plain HTML. */
|
|
21
|
+
defaultStartCollapsed?: boolean;
|
|
22
|
+
/** Controlled collapsed state of the end aside. Set this as a JS property
|
|
23
|
+
* (`el.endCollapsed = true`) to drive the aside from your app, updating it
|
|
24
|
+
* in response to the `kai-aside-toggle` event. Omit for uncontrolled (the
|
|
25
|
+
* element manages it). */
|
|
26
|
+
endCollapsed?: boolean;
|
|
27
|
+
/** Initial collapsed state of the end aside when uncontrolled (default
|
|
28
|
+
* false). Use the `default-end-collapsed` attribute to start collapsed in
|
|
29
|
+
* plain HTML. */
|
|
30
|
+
defaultEndCollapsed?: boolean;
|
|
31
|
+
/** Auto-collapse both asides when the shell's own width drops below this many
|
|
32
|
+
* px, and re-expand when it grows back above. Applies to uncontrolled asides
|
|
33
|
+
* only (it never fights an app-driven collapsed prop); omit to disable.
|
|
34
|
+
* Fires `kai-aside-toggle`. Attribute: `collapse-below`. */
|
|
72
35
|
collapseBelow?: number;
|
|
73
|
-
/**
|
|
36
|
+
/** Below this shell width in px, an expanded aside renders as an overlay
|
|
37
|
+
* drawer over the main region instead of a column beside it. Escape inside
|
|
38
|
+
* the drawer closes it and returns focus to the element focused before it
|
|
39
|
+
* opened. Omit to disable. Attribute: `drawer-below`. */
|
|
40
|
+
drawerBelow?: number;
|
|
41
|
+
/** Density hint. Reflected as a `data-compact` hook on the root (and as the
|
|
42
|
+
* `compact` attribute on the element) for your CSS and slotted content; the
|
|
43
|
+
* shell itself keeps no other opinion about density. */
|
|
74
44
|
compact?: boolean;
|
|
75
|
-
/** Suppress the built-in ConversationList so the `sidebar-header` slot owns the
|
|
76
|
-
* whole rail flex region (for apps that supply their own rail nav). Default
|
|
77
|
-
* false. Attribute: `no-conversations`. */
|
|
78
|
-
noConversations?: boolean;
|
|
79
|
-
/** Optional card type -> custom-element tag overrides/additions for `card`
|
|
80
|
-
* parts (merged over the built-ins). Property: `el.cardTypes`. Typed as a
|
|
81
|
-
* plain string map (not the `CardTagMap` alias) so the generated React
|
|
82
|
-
* wrapper inlines it instead of emitting an unresolved named type. */
|
|
83
|
-
cardTypes?: Record<string, string>;
|
|
84
|
-
/** JSON Schemas for the card types this app renders, keyed by envelope type. The
|
|
85
|
-
* companion of `cardTypes`, which says what DRAWS a card while this says what a
|
|
86
|
-
* VALID one looks like. An OBJECT, so it is a JS property only: `el.cardSchemas
|
|
87
|
-
* = { 'pricing-table': pricingSchema }`, never an attribute.
|
|
88
|
-
* `createCardRegistry(...).validationSchemas` is exactly this shape.
|
|
89
|
-
*
|
|
90
|
-
* Without it the kit validates its own seven built-ins and leaves your own card
|
|
91
|
-
* type, the one your app actually cares about, as the only unchecked thing on
|
|
92
|
-
* screen. A schema here WINS over a built-in of the same name.
|
|
93
|
-
*
|
|
94
|
-
* Typed `Record<string, object>` rather than `Record<string, JsonSchema>`
|
|
95
|
-
* deliberately: an imported `.json` schema widens `"type"` to `string`, and an
|
|
96
|
-
* authored one carries `$schema`/`title`/`description`/`additionalProperties`,
|
|
97
|
-
* so the tighter type would reject both of the normal ways to supply one. */
|
|
98
|
-
cardSchemas?: Record<string, object>;
|
|
99
45
|
}
|
|
100
46
|
|
|
47
|
+
/** Events fired by `<kai-workspace>`. Layout only: every chat event now belongs
|
|
48
|
+
* to the part that fires it, inside your own markup. */
|
|
101
49
|
interface Events {
|
|
102
|
-
/**
|
|
103
|
-
'kai-
|
|
104
|
-
/** The
|
|
105
|
-
'kai-
|
|
106
|
-
/** The sidebar was collapsed or expanded. */
|
|
107
|
-
'kai-sidebar-toggle': { collapsed: boolean };
|
|
108
|
-
/** User submitted a message. */
|
|
109
|
-
'kai-submit': { value: string; attachments: AttachmentData[] };
|
|
110
|
-
/** Fired on every input change. */
|
|
111
|
-
'kai-value-change': { value: string };
|
|
112
|
-
/** The header model switcher changed. */
|
|
113
|
-
'kai-model-change': { modelId: string };
|
|
114
|
-
/** An action button on a message was clicked. `state` is present only for the
|
|
115
|
-
* toggleable feedback votes: `'on'` when a like/dislike is set, `'off'` when
|
|
116
|
-
* re-tapped to clear. */
|
|
117
|
-
'kai-message-action': { messageId: string; action: string; state?: 'on' | 'off' };
|
|
118
|
-
/** The Search button was clicked. */
|
|
119
|
-
'kai-search': Record<string, never>;
|
|
120
|
-
/** The Mic / voice button was clicked. */
|
|
121
|
-
'kai-voice': Record<string, never>;
|
|
122
|
-
/** A suggestion chip was clicked (only in `suggestion-mode="fill"`). */
|
|
123
|
-
'kai-suggestion-click': { value: string };
|
|
50
|
+
/** An aside collapsed or expanded (a method, the breakpoint, the drawer's Escape). */
|
|
51
|
+
'kai-aside-toggle': WorkspaceAsideToggleDetail;
|
|
52
|
+
/** The aside was resized (fires per drag step, keyboard nudge, or a handle double-click reset), width in px. */
|
|
53
|
+
'kai-aside-resize': WorkspaceAsideResizeDetail;
|
|
124
54
|
}
|
|
125
55
|
|
|
56
|
+
/**
|
|
57
|
+
* `<kai-workspace>` — the chat-agnostic layout shell: five slots (`header` ·
|
|
58
|
+
* `start` · `main` · `end` · `footer`), resize handles between the columns,
|
|
59
|
+
* per-aside collapse, collapse-below-breakpoint, and a mobile drawer mode for
|
|
60
|
+
* the asides. It knows nothing about chat: a file tree in `start` is as valid
|
|
61
|
+
* as `<kai-conversations>`, and the workspace app slots `<kai-conversations>`
|
|
62
|
+
* and `<kai-chat>` into it.
|
|
63
|
+
*
|
|
64
|
+
* ```html
|
|
65
|
+
* <kai-workspace collapse-below="720" drawer-below="640">
|
|
66
|
+
* <kai-conversations slot="start"></kai-conversations>
|
|
67
|
+
* <kai-chat></kai-chat>
|
|
68
|
+
* </kai-workspace>
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* Aside geometry is CSS custom properties, not props (the `kai-dock` rule):
|
|
72
|
+
* `--kai-workspace-start-width` (280px) · `--kai-workspace-start-min-width`
|
|
73
|
+
* (200px) · `--kai-workspace-start-max-width` (480px) · `--kai-workspace-end-width`
|
|
74
|
+
* (320px) · `--kai-workspace-end-min-width` (200px) · `--kai-workspace-end-max-width`
|
|
75
|
+
* (480px). Read once at upgrade. Parts: `header` · `start` · `main` · `end` ·
|
|
76
|
+
* `footer` (the asides also match `::part(aside)`).
|
|
77
|
+
*
|
|
78
|
+
* **BREAKING (the 0.24 re-cast, spec 2026-08-20):** this element was a chat
|
|
79
|
+
* preset; it is now a layout shell, and everything chat-shaped is gone from its
|
|
80
|
+
* surface. Where each removed prop went:
|
|
81
|
+
*
|
|
82
|
+
* - `conversations` / `activeId` / `groups` / `noConversations`: set them on your
|
|
83
|
+
* own `<kai-conversations slot="start">`.
|
|
84
|
+
* - `messages` / `loading` / `proseSize` / `codeTheme` / `codeHighlight` /
|
|
85
|
+
* `chatTitle` / `scrollButton` / `cardTypes` / `cardSchemas`: set them on your
|
|
86
|
+
* own `<kai-chat>` in the main region.
|
|
87
|
+
* - `value` / `placeholder` / `suggestions` / `suggestionMode` / `voice` /
|
|
88
|
+
* `triggers` / `kindIcons` and the renamed `webSearch` (was `search`): the
|
|
89
|
+
* composer surface on `<kai-chat>` or `<kai-prompt-input>`.
|
|
90
|
+
* - `models` / `currentModel` / `context`: header chrome you slot (a model
|
|
91
|
+
* picker is a part in a slot, not three orchestrator props).
|
|
92
|
+
* - `sidebarWidth` / `sidebarMinWidth` / `sidebarMaxWidth`: the
|
|
93
|
+
* `--kai-workspace-start-*` custom properties above.
|
|
94
|
+
* - `sidebarCollapsed` / `defaultSidebarCollapsed`: `startCollapsed` /
|
|
95
|
+
* `defaultStartCollapsed` (per-aside; the end aside has its own pair).
|
|
96
|
+
* - `collapseBelow`: kept, now collapsing both asides.
|
|
97
|
+
* - `compact`: kept as a reflected density hint; the rail's row density is
|
|
98
|
+
* `<kai-conversations>`' own `compact`.
|
|
99
|
+
* - Chat events (`kai-submit`, `kai-conversation-select`, `kai-message-action`,
|
|
100
|
+
* `kai-model-change`, `kai-search`, `kai-voice`, `kai-value-change`,
|
|
101
|
+
* `kai-suggestion-click`): listen on the part that fires them.
|
|
102
|
+
* `kai-sidebar-toggle` is now `kai-aside-toggle` with a `side`.
|
|
103
|
+
* - Methods: `toggleSidebar()` / `collapseSidebar()` / `expandSidebar()` are now
|
|
104
|
+
* `toggleAside(side)` / `collapseAside(side)` / `expandAside(side)`; the
|
|
105
|
+
* thread methods (`focus`/`clear`/`send`/`scrollToBottom`) live on your
|
|
106
|
+
* `<kai-chat>`.
|
|
107
|
+
*
|
|
108
|
+
* The migration path for a full app is the `workspace` block scaffold (the kai
|
|
109
|
+
* MCP `scaffold` tool), which emits this composition wired.
|
|
110
|
+
*/
|
|
126
111
|
defineWebComponent<Props, Events>('kai-workspace', {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
//
|
|
138
|
-
// runtime (a pre-0.20.0 `{ id, role, content }` array, in particular). Skip
|
|
139
|
-
// the invalid entries rather than let `groupMessageParts` throw deep inside a
|
|
140
|
-
// render pass, which would blank the whole workspace instead of one message.
|
|
141
|
-
const validMessages = createMessagesGuard('kai-workspace');
|
|
142
|
-
|
|
143
|
-
// Which injection slots the consumer has filled. A bare <slot> is always a
|
|
144
|
-
// truthy JSX node, so we render each region wrapper ONLY when readSlots reports
|
|
145
|
-
// projected light-DOM content (re-read on childList mutation).
|
|
112
|
+
startCollapsed: undefined,
|
|
113
|
+
defaultStartCollapsed: undefined,
|
|
114
|
+
endCollapsed: undefined,
|
|
115
|
+
defaultEndCollapsed: undefined,
|
|
116
|
+
collapseBelow: undefined,
|
|
117
|
+
drawerBelow: undefined,
|
|
118
|
+
compact: undefined,
|
|
119
|
+
}, (props, { dispatch, flag, expose, element, reflectFlag }) => {
|
|
120
|
+
// Which slots the consumer has filled. A bare <slot> is always a truthy JSX
|
|
121
|
+
// node, so each optional region renders ONLY when readSlots reports projected
|
|
122
|
+
// light-DOM content (re-read on childList mutation). Main always renders.
|
|
146
123
|
const [slots, setSlots] = createSignal<Record<string, boolean>>({});
|
|
147
124
|
onMount(() => {
|
|
148
125
|
const read = () => setSlots(readSlots(element, WORKSPACE_SLOTS));
|
|
@@ -152,165 +129,60 @@ defineWebComponent<Props, Events>('kai-workspace', {
|
|
|
152
129
|
onCleanup(() => observer.disconnect());
|
|
153
130
|
});
|
|
154
131
|
|
|
155
|
-
//
|
|
156
|
-
//
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const [collapsed, setCollapsed] = createControllableSignal(
|
|
161
|
-
() => props.sidebarCollapsed as boolean | undefined,
|
|
162
|
-
flag('defaultSidebarCollapsed'),
|
|
163
|
-
);
|
|
164
|
-
const setCollapsedTo = (next: boolean) => { setCollapsed(next); dispatch('kai-sidebar-toggle', { collapsed: next }); };
|
|
165
|
-
const toggle = () => setCollapsedTo(!collapsed());
|
|
132
|
+
// Reflect the read-back flags (the G-05 rule: a bare attribute parses to
|
|
133
|
+
// `undefined`, so without this the property would contradict the attribute).
|
|
134
|
+
reflectFlag('compact');
|
|
135
|
+
reflectFlag('defaultStartCollapsed');
|
|
136
|
+
reflectFlag('defaultEndCollapsed');
|
|
166
137
|
|
|
167
|
-
//
|
|
168
|
-
//
|
|
169
|
-
//
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
} else if (!isBelow && collapsed() && autoCollapsed) {
|
|
185
|
-
autoCollapsed = false;
|
|
186
|
-
setCollapsedTo(false);
|
|
187
|
-
}
|
|
188
|
-
});
|
|
189
|
-
ro.observe(rootEl);
|
|
190
|
-
onCleanup(() => ro.disconnect());
|
|
191
|
-
});
|
|
138
|
+
// Aside geometry from the element's CSS custom properties, read once at
|
|
139
|
+
// upgrade (inline style first so jsdom, which does not resolve custom
|
|
140
|
+
// properties through getComputedStyle, still honors a direct set).
|
|
141
|
+
const readVar = (name: string, fallback: number): number => {
|
|
142
|
+
const inline = element.style.getPropertyValue(name).trim();
|
|
143
|
+
const computed = inline || getComputedStyle(element).getPropertyValue(name).trim();
|
|
144
|
+
const n = parseFloat(computed);
|
|
145
|
+
return Number.isFinite(n) ? n : fallback;
|
|
146
|
+
};
|
|
147
|
+
const geometry = untrack(() => ({
|
|
148
|
+
startWidth: readVar('--kai-workspace-start-width', 280),
|
|
149
|
+
startMinWidth: readVar('--kai-workspace-start-min-width', 200),
|
|
150
|
+
startMaxWidth: readVar('--kai-workspace-start-max-width', 480),
|
|
151
|
+
endWidth: readVar('--kai-workspace-end-width', 320),
|
|
152
|
+
endMinWidth: readVar('--kai-workspace-end-min-width', 200),
|
|
153
|
+
endMaxWidth: readVar('--kai-workspace-end-max-width', 480),
|
|
154
|
+
}));
|
|
192
155
|
|
|
193
|
-
|
|
194
|
-
// in-UI toggle (named *Sidebar to avoid the `sidebarCollapsed` prop accessor).
|
|
195
|
-
// The thread methods delegate to the embedded ChatThread's controller, captured
|
|
196
|
-
// once below — the thread node is shared across both <Show> branches, so a single
|
|
197
|
-
// controllerRef is stable across collapse/expand.
|
|
198
|
-
let controller: ChatThreadController | undefined;
|
|
156
|
+
let controller: WorkspaceShellController | undefined;
|
|
199
157
|
expose({
|
|
200
|
-
/** Collapse/expand
|
|
201
|
-
|
|
202
|
-
/** Force
|
|
203
|
-
|
|
204
|
-
/** Force
|
|
205
|
-
|
|
206
|
-
/** Focus the thread's composer. */
|
|
207
|
-
focus: (options?: FocusOptions) => controller?.focus(options),
|
|
208
|
-
/** Clear the thread draft + staged attachments. */
|
|
209
|
-
clear: () => controller?.clear(),
|
|
210
|
-
/** Submit the current thread draft programmatically (fires `kai-submit`). */
|
|
211
|
-
send: () => controller?.send(),
|
|
212
|
-
/** Scroll the thread to the newest message. */
|
|
213
|
-
scrollToBottom: (behavior?: ScrollBehavior) => controller?.scrollToBottom(behavior),
|
|
158
|
+
/** Collapse/expand one aside (fires `kai-aside-toggle`). */
|
|
159
|
+
toggleAside: (side: WorkspaceAsideSide) => controller?.toggleAside(side),
|
|
160
|
+
/** Force one aside collapsed (fires `kai-aside-toggle`). */
|
|
161
|
+
collapseAside: (side: WorkspaceAsideSide) => controller?.collapseAside(side),
|
|
162
|
+
/** Force one aside expanded (fires `kai-aside-toggle`). */
|
|
163
|
+
expandAside: (side: WorkspaceAsideSide) => controller?.expandAside(side),
|
|
214
164
|
});
|
|
215
165
|
|
|
216
|
-
// Create the thread ONCE and reference the same node in both <Show> branches.
|
|
217
|
-
// It's owned by this component root (not by a Show branch), so toggling the
|
|
218
|
-
// sidebar moves the node between branches without disposing it — the thread's
|
|
219
|
-
// own state (e.g. an uncontrolled draft) survives the collapse/expand.
|
|
220
|
-
const threadEl = (
|
|
221
|
-
<ChatThread
|
|
222
|
-
messages={validMessages(props.messages)} value={props.value as string | undefined} placeholder={props.placeholder as string}
|
|
223
|
-
loading={flag('loading')} suggestions={props.suggestions as string[] | undefined}
|
|
224
|
-
suggestionMode={props.suggestionMode as 'submit' | 'fill'} proseSize={props.proseSize as ProseSize}
|
|
225
|
-
codeTheme={props.codeTheme as string} codeHighlight={flag('codeHighlight')}
|
|
226
|
-
chatTitle={props.chatTitle as string | undefined} models={props.models as ModelOption[] | undefined}
|
|
227
|
-
currentModel={props.currentModel as string | undefined} context={props.context as ChatThreadContextUsage | undefined}
|
|
228
|
-
scrollButton={props.scrollButton !== false} search={flag('search')} voice={flag('voice')}
|
|
229
|
-
triggers={props.triggers as TriggerDef[] | undefined}
|
|
230
|
-
kindIcons={props.kindIcons as Record<string, string> | undefined}
|
|
231
|
-
cardTypes={cardComponentsFromTags(props.cardTypes as Record<string, string> | undefined, (props as { theme?: string }).theme)}
|
|
232
|
-
cardSchemas={props.cardSchemas as Record<string, object> | undefined}
|
|
233
|
-
onValueChange={(value) => dispatch('kai-value-change', { value })}
|
|
234
|
-
onSubmit={(detail) => dispatch('kai-submit', detail)}
|
|
235
|
-
onSuggestionClick={(value) => dispatch('kai-suggestion-click', { value })}
|
|
236
|
-
onModelChange={(modelId) => dispatch('kai-model-change', { modelId })}
|
|
237
|
-
onMessageAction={(detail) => dispatch('kai-message-action', detail)}
|
|
238
|
-
onSearch={() => dispatch('kai-search', {})}
|
|
239
|
-
onVoice={() => dispatch('kai-voice', {})}
|
|
240
|
-
controllerRef={(c) => (controller = c)}
|
|
241
|
-
/>
|
|
242
|
-
);
|
|
243
|
-
|
|
244
|
-
// The main region: an optional top-placed `main-header` band above the thread.
|
|
245
|
-
// Shared across both collapse branches (the thread node is the same instance).
|
|
246
|
-
const mainRegion = (
|
|
247
|
-
<div class="flex h-full flex-col overflow-hidden">
|
|
248
|
-
<Show when={slots()['main-header']}>
|
|
249
|
-
<div class="shrink-0 border-b border-border"><slot name="main-header" /></div>
|
|
250
|
-
</Show>
|
|
251
|
-
<div class="min-h-0 flex-1">
|
|
252
|
-
<Show when={slots()['main']} fallback={threadEl}>
|
|
253
|
-
<slot name="main" />
|
|
254
|
-
</Show>
|
|
255
|
-
</div>
|
|
256
|
-
</div>
|
|
257
|
-
);
|
|
258
|
-
|
|
259
166
|
return (
|
|
260
|
-
<
|
|
261
|
-
<
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
<ResizablePanel defaultSize={props.sidebarWidth as number} data-min-size={String(props.sidebarMinWidth)} data-max-size={String(props.sidebarMaxWidth)}>
|
|
281
|
-
{/* The rail: an optional injected header above the list and footer
|
|
282
|
-
below it (upgrade card / Design trigger / user menu). Carries a
|
|
283
|
-
subtle, theme-aware default background (bg-surface), exposed as
|
|
284
|
-
::part(sidebar) so a consumer can override it. The inner list is
|
|
285
|
-
made transparent so the part background reads uniformly. */}
|
|
286
|
-
<div part="sidebar" class="flex h-full flex-col overflow-hidden bg-surface">
|
|
287
|
-
<Show when={slots()['sidebar-header']}>
|
|
288
|
-
{/* When `no-conversations` suppresses the built-in list, the
|
|
289
|
-
projected header owns the whole rail flex region; otherwise it
|
|
290
|
-
sits as a fixed band above the list. */}
|
|
291
|
-
<div class={flag('noConversations') ? 'min-h-0 flex-1' : 'shrink-0'}><slot name="sidebar-header" /></div>
|
|
292
|
-
</Show>
|
|
293
|
-
<Show when={!flag('noConversations')}>
|
|
294
|
-
<div class="min-h-0 flex-1">
|
|
295
|
-
<ConversationList
|
|
296
|
-
class="bg-transparent"
|
|
297
|
-
groups={props.groups ?? []} conversations={props.conversations ?? []} activeId={props.activeId as string | undefined}
|
|
298
|
-
compact={flag('compact')}
|
|
299
|
-
onSelect={(id) => dispatch('kai-conversation-select', { id })}
|
|
300
|
-
onNewChat={() => dispatch('kai-new-chat', {})}
|
|
301
|
-
onToggleSidebar={toggle}
|
|
302
|
-
/>
|
|
303
|
-
</div>
|
|
304
|
-
</Show>
|
|
305
|
-
<Show when={slots()['sidebar-footer']}>
|
|
306
|
-
<div class="shrink-0"><slot name="sidebar-footer" /></div>
|
|
307
|
-
</Show>
|
|
308
|
-
</div>
|
|
309
|
-
</ResizablePanel>
|
|
310
|
-
<ResizableHandle />
|
|
311
|
-
<ResizablePanel>{mainRegion}</ResizablePanel>
|
|
312
|
-
</ResizablePanelGroup>
|
|
313
|
-
</Show>
|
|
314
|
-
</div>
|
|
167
|
+
<WorkspaceShell
|
|
168
|
+
header={slots()['header'] ? <slot name="header" /> : undefined}
|
|
169
|
+
start={slots()['start'] ? <slot name="start" /> : undefined}
|
|
170
|
+
end={slots()['end'] ? <slot name="end" /> : undefined}
|
|
171
|
+
footer={slots()['footer'] ? <slot name="footer" /> : undefined}
|
|
172
|
+
startCollapsed={props.startCollapsed as boolean | undefined}
|
|
173
|
+
defaultStartCollapsed={flag('defaultStartCollapsed')}
|
|
174
|
+
endCollapsed={props.endCollapsed as boolean | undefined}
|
|
175
|
+
defaultEndCollapsed={flag('defaultEndCollapsed')}
|
|
176
|
+
collapseBelow={props.collapseBelow as number | undefined}
|
|
177
|
+
drawerBelow={props.drawerBelow as number | undefined}
|
|
178
|
+
compact={flag('compact')}
|
|
179
|
+
{...geometry}
|
|
180
|
+
onAsideToggle={(detail) => dispatch('kai-aside-toggle', detail)}
|
|
181
|
+
onAsideResize={(detail) => dispatch('kai-aside-resize', detail)}
|
|
182
|
+
controllerRef={(c) => (controller = c)}
|
|
183
|
+
>
|
|
184
|
+
<slot name="main" />
|
|
185
|
+
<slot />
|
|
186
|
+
</WorkspaceShell>
|
|
315
187
|
);
|
|
316
188
|
});
|
package/src/elements/chat.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createSignal, onCleanup, onMount } from 'solid-js';
|
|
2
2
|
import { defineWebComponent } from './define';
|
|
3
3
|
import { CHAT_SLOTS, readSlots } from './slots';
|
|
4
4
|
import { ChatThread, type ChatThreadProps, type ChatThreadContextUsage, type ChatThreadController } from '../components/chat-thread';
|
|
@@ -14,7 +14,7 @@ import type { ModelOption } from '../types';
|
|
|
14
14
|
|
|
15
15
|
type Props = Omit<ChatThreadProps,
|
|
16
16
|
'class' | 'onValueChange' | 'onSubmit' | 'onAttachmentsChange' | 'onSuggestionClick' | 'onModelChange'
|
|
17
|
-
| 'onMessageAction' | '
|
|
17
|
+
| 'onMessageAction' | 'onWebSearch' | 'onVoice' | 'controllerRef' | 'cardTypes' | 'cardSchemas' | 'messages'
|
|
18
18
|
| 'accept' | 'onAttachmentsRejected'> & Record<string, unknown> & {
|
|
19
19
|
/** Which attachment media types the user may stage, in HTML `accept` syntax:
|
|
20
20
|
* `<kai-chat accept="image/*,application/pdf">`. A plain string, so unlike
|
|
@@ -86,8 +86,8 @@ interface Events {
|
|
|
86
86
|
'kai-message-action': { messageId: string; action: string; state?: 'on' | 'off' };
|
|
87
87
|
/** The header model switcher changed. */
|
|
88
88
|
'kai-model-change': { modelId: string };
|
|
89
|
-
/** The
|
|
90
|
-
'kai-search': Record<string, never>;
|
|
89
|
+
/** The web-search (Globe) toolbar button was clicked. */
|
|
90
|
+
'kai-web-search': Record<string, never>;
|
|
91
91
|
/** The Mic / voice button was clicked. */
|
|
92
92
|
'kai-voice': Record<string, never>;
|
|
93
93
|
}
|
|
@@ -97,9 +97,9 @@ defineWebComponent<Props, Events>('kai-chat', {
|
|
|
97
97
|
suggestions: undefined, suggestionMode: 'submit', persistSuggestions: false, proseSize: 'sm',
|
|
98
98
|
codeTheme: 'github-dark-dimmed', codeHighlight: true, chatTitle: undefined,
|
|
99
99
|
models: undefined, currentModel: undefined, context: undefined, scrollButton: true,
|
|
100
|
-
|
|
100
|
+
webSearch: false, voice: false, triggers: undefined, kindIcons: undefined,
|
|
101
101
|
actionsReveal: 'always', cardTypes: undefined, cardSchemas: undefined, accept: undefined,
|
|
102
|
-
}, (props, { dispatch, flag, element, expose }) => {
|
|
102
|
+
}, (props, { dispatch, flag, reflectFlag, element, expose }) => {
|
|
103
103
|
// `messages` is an untyped boundary: a consumer can hand it anything at
|
|
104
104
|
// runtime (a pre-0.20.0 `{ id, role, content }` array, in particular). Skip
|
|
105
105
|
// the invalid entries rather than let `groupMessageParts` throw deep inside a
|
|
@@ -120,7 +120,10 @@ defineWebComponent<Props, Events>('kai-chat', {
|
|
|
120
120
|
|
|
121
121
|
// Reflect streaming state to a host attribute so slotted composer/notice CSS
|
|
122
122
|
// can react without reading internals (e.g. :host([loading]) ::slotted(...)).
|
|
123
|
-
|
|
123
|
+
// reflectFlag, not a hand-rolled toggleAttribute effect: the reflection is what
|
|
124
|
+
// makes the property read back `undefined`, so the two belong in one call. See
|
|
125
|
+
// WebComponentContext.reflectFlag.
|
|
126
|
+
reflectFlag('loading');
|
|
124
127
|
|
|
125
128
|
// Imperative method API — forward the chat-thread controller onto the host
|
|
126
129
|
// (focus the composer, clear it, send programmatically, scroll the thread).
|
|
@@ -161,7 +164,7 @@ defineWebComponent<Props, Events>('kai-chat', {
|
|
|
161
164
|
codeTheme={props.codeTheme as string} codeHighlight={flag('codeHighlight')}
|
|
162
165
|
chatTitle={props.chatTitle as string | undefined} models={props.models as ModelOption[] | undefined}
|
|
163
166
|
currentModel={props.currentModel as string | undefined} context={props.context as ChatThreadContextUsage | undefined}
|
|
164
|
-
scrollButton={props.scrollButton !== false}
|
|
167
|
+
scrollButton={props.scrollButton !== false} webSearch={flag('webSearch')} voice={flag('voice')}
|
|
165
168
|
triggers={props.triggers as TriggerDef[] | undefined}
|
|
166
169
|
kindIcons={props.kindIcons as Record<string, string> | undefined}
|
|
167
170
|
actionsReveal={props.actionsReveal as 'always' | 'hover'}
|
|
@@ -175,7 +178,7 @@ defineWebComponent<Props, Events>('kai-chat', {
|
|
|
175
178
|
onSuggestionClick={(value) => dispatch('kai-suggestion-click', { value })}
|
|
176
179
|
onModelChange={(modelId) => dispatch('kai-model-change', { modelId })}
|
|
177
180
|
onMessageAction={(detail) => dispatch('kai-message-action', detail)}
|
|
178
|
-
|
|
181
|
+
onWebSearch={() => dispatch('kai-web-search', {})}
|
|
179
182
|
onVoice={() => dispatch('kai-voice', {})}
|
|
180
183
|
controllerRef={(c) => (controller = c)}
|
|
181
184
|
headerStart={slot('header-start')}
|
|
@@ -11,6 +11,11 @@ interface Props extends Record<string, unknown> {
|
|
|
11
11
|
codeTheme?: string;
|
|
12
12
|
/** Disable syntax highlighting (renders plain text, no Shiki). */
|
|
13
13
|
codeHighlight?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Show the copy button. **Defaults to ON**, because this element is documented
|
|
16
|
+
* as shipping one. Opt out with `copy="false"` or `el.copy = false`.
|
|
17
|
+
*/
|
|
18
|
+
copy?: boolean;
|
|
14
19
|
/** Code text sizing. */
|
|
15
20
|
proseSize?: ProseSize;
|
|
16
21
|
}
|
|
@@ -18,12 +23,17 @@ interface Props extends Record<string, unknown> {
|
|
|
18
23
|
/**
|
|
19
24
|
* `<kai-code-block>` — one syntax-highlighted code block (with a copy button).
|
|
20
25
|
* Code via the `code` property; `language`/`code-theme` via attributes.
|
|
26
|
+
*
|
|
27
|
+
* The copy button is ON by default and writes the raw `code` property, never the
|
|
28
|
+
* highlighted markup. Turn it off with `copy="false"`. Style it via
|
|
29
|
+
* `kai-code-block::part(copy)`.
|
|
21
30
|
*/
|
|
22
31
|
defineWebComponent<Props>('kai-code-block', {
|
|
23
32
|
code: '',
|
|
24
33
|
language: undefined,
|
|
25
34
|
codeTheme: 'github-dark-dimmed',
|
|
26
35
|
codeHighlight: true,
|
|
36
|
+
copy: true,
|
|
27
37
|
proseSize: 'sm',
|
|
28
38
|
}, (props, { flag }) => {
|
|
29
39
|
const outer = useChatConfig();
|
|
@@ -34,7 +44,15 @@ defineWebComponent<Props>('kai-code-block', {
|
|
|
34
44
|
codeHighlight={flag('codeHighlight')}
|
|
35
45
|
portalMount={outer.portalMount()}
|
|
36
46
|
>
|
|
37
|
-
|
|
47
|
+
{/* The ELEMENT opts in; the Solid `CodeBlock` default stays OFF so markdown and
|
|
48
|
+
artifact are untouched. `copyText` is the raw property — the button must
|
|
49
|
+
never copy what Shiki produced. `copy` is NOT reflected, matching
|
|
50
|
+
`codeHighlight` beside it: reflecting a default-ON flag would stamp `copy=""`
|
|
51
|
+
on every instance for no benefit, and the runtime-attribute hazard that
|
|
52
|
+
earned `reflectFlag` elsewhere needs a BARE attribute, which is a no-op on a
|
|
53
|
+
flag that is already on. The meaningful spelling, `copy="false"`, is a real
|
|
54
|
+
prop change and is pinned as one. */}
|
|
55
|
+
<CodeBlock copy={flag('copy')} copyText={props.code}>
|
|
38
56
|
<CodeBlockCode code={props.code} language={props.language} />
|
|
39
57
|
</CodeBlock>
|
|
40
58
|
</ChatConfig>
|
package/src/elements/command.tsx
CHANGED
|
@@ -174,7 +174,10 @@ defineWebComponent<Props, Events>('kai-command', {
|
|
|
174
174
|
aria-controls={listboxId}
|
|
175
175
|
value={query()}
|
|
176
176
|
placeholder={(props.placeholder as string | undefined) ?? 'Search…'}
|
|
177
|
-
|
|
177
|
+
// No `focus-visible:outline-none` here. It used to suppress the base
|
|
178
|
+
// focus ring and put nothing in its place, so keyboard users had no
|
|
179
|
+
// indication of where they were in the palette.
|
|
180
|
+
class="w-full bg-transparent text-sm text-foreground placeholder:text-muted-foreground"
|
|
178
181
|
onInput={handleInput}
|
|
179
182
|
onKeyDown={handleKeyDown}
|
|
180
183
|
/>
|