@kitn.ai/ui 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -45
- package/dist/components/artifact-card.d.ts +51 -0
- package/dist/components/artifact.d.ts +1 -1
- package/dist/components/attachments.d.ts +2 -2
- package/dist/components/audio-visualizer/index.d.ts +3 -3
- package/dist/components/audio-visualizer/labs/lab-choreography.d.ts +59 -0
- package/dist/components/audio-visualizer/labs/lab-shaders.d.ts +22 -0
- package/dist/components/audio-visualizer/labs/lab-visualizer.d.ts +18 -0
- package/dist/components/audio-visualizer/variant-aurora.d.ts +2 -2
- package/dist/components/audio-visualizer/variant-bar.d.ts +2 -2
- package/dist/components/audio-visualizer/variant-custom.d.ts +2 -2
- package/dist/components/audio-visualizer/variant-grid.d.ts +1 -1
- package/dist/components/audio-visualizer/variant-radial.d.ts +1 -1
- package/dist/components/audio-visualizer/variant-wave.d.ts +1 -1
- package/dist/components/card-fallback.d.ts +12 -2
- package/dist/components/card-renderer.d.ts +63 -2
- package/dist/components/chat-container.d.ts +3 -0
- package/dist/components/chat-scope-picker.d.ts +2 -2
- package/dist/components/chat-thread.d.ts +68 -18
- package/dist/components/choice-card.d.ts +3 -28
- package/dist/components/composer-dom.d.ts +1 -1
- package/dist/components/composer-highlight.d.ts +1 -1
- package/dist/components/composer-history.d.ts +1 -1
- package/dist/components/composer.d.ts +1 -1
- package/dist/components/confirm-card.d.ts +3 -18
- package/dist/components/context.d.ts +8 -4
- package/dist/components/conversation-item.d.ts +1 -1
- package/dist/components/conversation-list.d.ts +4 -3
- package/dist/components/embed.d.ts +3 -3
- package/dist/components/file-tree.d.ts +11 -22
- package/dist/components/form-widgets.d.ts +1 -1
- package/dist/components/form.d.ts +3 -44
- package/dist/components/link-preview.d.ts +3 -3
- package/dist/components/loader.d.ts +30 -48
- package/dist/components/message-skills.d.ts +4 -0
- package/dist/components/message.d.ts +84 -21
- package/dist/components/model-switcher.d.ts +2 -2
- package/dist/components/prompt-input.d.ts +2 -2
- package/dist/components/response-compare-types.d.ts +11 -2
- package/dist/components/response-compare.d.ts +3 -3
- package/dist/components/source.d.ts +12 -3
- package/dist/components/tasks-card.d.ts +3 -31
- package/dist/components/thread.d.ts +17 -5
- package/dist/components/toast.d.ts +2 -2
- package/dist/components/tool-classify.d.ts +8 -0
- package/dist/components/tool-types.d.ts +29 -1
- package/dist/components/tool.d.ts +3 -3
- package/dist/components/use-card-resolution.d.ts +1 -1
- package/dist/create-tween-D3Y5qiij.js +338 -0
- package/dist/create-tween-DGKY1FDY.js +341 -0
- package/dist/create-tween-paho5Rh-.js +7 -0
- package/dist/custom-elements.json +1681 -454
- package/dist/elements/agent-card.js +1 -1
- package/dist/elements/artifact.js +1 -1
- package/dist/elements/attachments.js +1 -1
- package/dist/elements/audio-visualizer.js +1 -1
- package/dist/elements/avatar.js +1 -1
- package/dist/elements/badge.js +1 -1
- package/dist/elements/button.js +1 -1
- package/dist/elements/card.js +1 -1
- package/dist/elements/cards.js +1 -1
- package/dist/elements/chain-of-thought.js +1 -1
- package/dist/elements/chat-scope-picker.js +1 -1
- package/dist/elements/chat-types.d.ts +70 -10
- package/dist/elements/chat-workspace.js +1 -1
- package/dist/elements/chat.js +1 -1
- package/dist/elements/checkpoint.js +1 -1
- package/dist/elements/choice.js +1 -1
- package/dist/elements/chunks/{Icon-Tj58ES_d.js → Icon-C-2LvGDG.js} +1 -1
- package/dist/elements/chunks/{action-icons-ns1Fnedj.js → action-icons-CaYoImEk.js} +1 -1
- package/dist/elements/chunks/arrow-left-Bb46H7w9.js +1 -0
- package/dist/elements/chunks/artifact-BBIscOxJ.js +1 -0
- package/dist/elements/chunks/{attachments-mCB5F1Fq.js → attachments-BB56zoji.js} +1 -1
- package/dist/elements/chunks/audio-visualizer-BxOx4THz.js +1 -0
- package/dist/elements/chunks/{badge-B4Zuajl2.js → badge-SxLSZ19R.js} +1 -1
- package/dist/elements/chunks/{button-ZWNif3--.js → button-CmkUkz6c.js} +1 -1
- package/dist/elements/chunks/card-renderer-Db4ffkWv.js +1 -0
- package/dist/elements/chunks/card-tags-D8lZ-C_U.js +1 -0
- package/dist/elements/chunks/chat-thread-B3Ks-cKr.js +1 -0
- package/dist/elements/chunks/check-C8desc_h.js +1 -0
- package/dist/elements/chunks/chevron-down-DKtc2HNB.js +1 -0
- package/dist/elements/chunks/chevron-right-Dw4GPhwL.js +1 -0
- package/dist/elements/chunks/choice-card-Q9cYYDyM.js +1 -0
- package/dist/elements/chunks/circle-BeokBsvB.js +1 -0
- package/dist/elements/chunks/circle-check-wJSqt859.js +1 -0
- package/dist/elements/chunks/{circle-x-B7faJFlY.js → circle-x-D0MEfxOM.js} +1 -1
- package/dist/elements/chunks/code-block-C8VzAraE.js +1 -0
- package/dist/elements/chunks/{collapsible-DM1Ckd4e.js → collapsible-Cvj61obE.js} +1 -1
- package/dist/elements/chunks/{composer-BguS0QL_.js → composer-D86ztyL0.js} +2 -2
- package/dist/elements/chunks/confirm-card-BdyDAGLw.js +1 -0
- package/dist/elements/chunks/context-WHDl-xSx.js +1 -0
- package/dist/elements/chunks/conversation-list-CdR14_Y4.js +1 -0
- package/dist/elements/chunks/create-tween-C_A_B638.js +7 -0
- package/dist/elements/chunks/{default-input-Cqqilg9t.js → default-input-CSZqUM81.js} +1 -1
- package/dist/elements/chunks/define-BzPnNsXg.js +1 -0
- package/dist/elements/chunks/{disclosure-CIZ5c8nO.js → disclosure-DVKsoc1F.js} +1 -1
- package/dist/elements/chunks/{download-Dsbg3ste.js → download-BjA54IMJ.js} +1 -1
- package/dist/elements/chunks/{dropdown-BDd1-Zgi.js → dropdown-BjVVHWXH.js} +1 -1
- package/dist/elements/chunks/{ellipsis-Dw6qrss-.js → ellipsis-BNedmqfi.js} +1 -1
- package/dist/elements/chunks/embed-DQsl4XEq.js +1 -0
- package/dist/elements/chunks/{external-link-Vt74zAoL.js → external-link-Di-dw2CU.js} +1 -1
- package/dist/elements/chunks/{file-text-CZrZF6_v.js → file-text-B3sAODCV.js} +1 -1
- package/dist/elements/chunks/{file-tree-DF4okKyo.js → file-tree-Dgto-bMn.js} +1 -1
- package/dist/elements/chunks/{folder-glP5rha4.js → folder-D6rMadFV.js} +1 -1
- package/dist/elements/chunks/form-CILxvhQ7.js +1 -0
- package/dist/elements/chunks/hover-card-BtiF4XiU.js +1 -0
- package/dist/elements/chunks/{icon-BLb8beoi.js → icon-DKkmze3y.js} +1 -1
- package/dist/elements/chunks/{info-CIsv92JK.js → info-CWRjZkuy.js} +1 -1
- package/dist/elements/chunks/{input-Dds1kFyt.js → input--QJBK6BA.js} +1 -1
- package/dist/elements/chunks/{kbd-De_xbgi9.js → kbd-C3zuKh8R.js} +1 -1
- package/dist/elements/chunks/{link-i4r_k7z4.js → link-BL5JA7Q0.js} +1 -1
- package/dist/elements/chunks/link-preview-CU37bbXh.js +1 -0
- package/dist/elements/chunks/{loader-BmQH4s3V.js → loader-XmpyxyRH.js} +1 -1
- package/dist/elements/chunks/{markdown-Zi21WhUz.js → markdown-3Gv5UZ_o.js} +1 -1
- package/dist/elements/chunks/message-CnBA2OUt.js +1 -0
- package/dist/elements/chunks/message-X5NZbq-W.js +1 -0
- package/dist/elements/chunks/message-square-CnpAm_P0.js +1 -0
- package/dist/elements/chunks/{minimize-2--ifeCGrl.js → minimize-2-DwyrUTcM.js} +1 -1
- package/dist/elements/chunks/{model-switcher-B94YAKsM.js → model-switcher-CclaJEHt.js} +1 -1
- package/dist/elements/chunks/{overlay-kD8dwRv_.js → overlay-Cepd-KcS.js} +1 -1
- package/dist/elements/chunks/{paperclip-q21dYOSK.js → paperclip-CdwKjrlu.js} +1 -1
- package/dist/elements/chunks/{progress-bar-BrAIIaaJ.js → progress-bar-DMVXBD3b.js} +1 -1
- package/dist/elements/chunks/{prompt-suggestion-Bjn2K-fR.js → prompt-suggestion-Di_WZE_5.js} +1 -1
- package/dist/elements/chunks/reasoning-D0jMch5u.js +1 -0
- package/dist/elements/chunks/{resizable-Dp4JExql.js → resizable-1znbL1Gv.js} +1 -1
- package/dist/elements/chunks/{rotate-cw-CFWWkpj2.js → rotate-cw-DVhhgx8n.js} +1 -1
- package/dist/elements/chunks/{scroll-area-Bb0kHH1j.js → scroll-area-Bs4bFS1P.js} +1 -1
- package/dist/elements/chunks/scroll-button-Bet5NLc4.js +1 -0
- package/dist/elements/chunks/{separator-9kRgr1X9.js → separator-C5Gh8qGC.js} +1 -1
- package/dist/elements/chunks/{settings-B8lmec4D.js → settings-5vmEFg0K.js} +1 -1
- package/dist/elements/chunks/{settings-group-I0hEuXiN.js → settings-group-BWLB38kz.js} +1 -1
- package/dist/elements/chunks/{share-C3lTiYGt.js → share-BZ3G_DaB.js} +1 -1
- package/dist/elements/chunks/skeleton-DafPJQTp.js +1 -0
- package/dist/elements/chunks/slots-CIw9RlAe.js +1 -0
- package/dist/elements/chunks/source-D_qj_6uJ.js +1 -0
- package/dist/elements/chunks/{star-CSJtGxgv.js → star-Cuv7j2IE.js} +1 -1
- package/dist/elements/chunks/{store-CHyW95TP.js → store-C1StPHfW.js} +1 -1
- package/dist/elements/chunks/tasks-card-EyoBZfpA.js +1 -0
- package/dist/elements/chunks/{text-shimmer-Cn9TmNpI.js → text-shimmer-D9gRSh34.js} +1 -1
- package/dist/elements/chunks/textarea-DuhtHfcm.js +1 -0
- package/dist/elements/chunks/{thumbs-up-PNVVThEF.js → thumbs-up-B9hwv43w.js} +1 -1
- package/dist/elements/chunks/{toast-store-DKbQn3Wn.js → toast-store-Bm3DUEDe.js} +1 -1
- package/dist/elements/chunks/{tool-DjTRpIpl.js → tool-CDtW7L0z.js} +1 -1
- package/dist/elements/chunks/tooltip-eB226mGK.js +1 -0
- package/dist/elements/chunks/{triangle-alert-DsHTHCPm.js → triangle-alert-C1SNzTqK.js} +1 -1
- package/dist/elements/chunks/use-card-resolution-YZh2MvI5.js +1 -0
- package/dist/elements/chunks/{variant-aurora-Dc4nQUia.js → variant-aurora-Cj1F7D0l.js} +2 -2
- package/dist/elements/chunks/{variant-custom-y_3kVQhS.js → variant-custom-T9gpt7QE.js} +1 -1
- package/dist/elements/chunks/{variant-wave-D5OR1-9Z.js → variant-wave-CxU9z-TE.js} +2 -2
- package/dist/elements/chunks/{video-B7vmenoC.js → video-CK4R7Rus.js} +1 -1
- package/dist/elements/chunks/x-D1qx0aLd.js +1 -0
- package/dist/elements/coachmark.js +1 -1
- package/dist/elements/code-block.js +1 -1
- package/dist/elements/command.js +1 -1
- package/dist/elements/compare.js +1 -1
- package/dist/elements/composer.js +1 -1
- package/dist/elements/confirm-card.js +1 -1
- package/dist/elements/context-meter.js +1 -1
- package/dist/elements/conversation-list.js +1 -1
- package/dist/elements/default-input.d.ts +7 -7
- package/dist/elements/define.d.ts +1 -0
- package/dist/elements/dialog.js +1 -1
- package/dist/elements/disclosure.d.ts +1 -1
- package/dist/elements/editable-label.js +1 -1
- package/dist/elements/element-data-types.d.ts +107 -0
- package/dist/elements/embed.js +1 -1
- package/dist/elements/empty.js +1 -1
- package/dist/elements/feedback-bar.js +1 -1
- package/dist/elements/file-tree.js +1 -1
- package/dist/elements/file-upload.js +1 -1
- package/dist/elements/form.js +1 -1
- package/dist/elements/hover-card.js +1 -1
- package/dist/elements/icon.js +1 -1
- package/dist/elements/image.js +1 -1
- package/dist/elements/input.js +1 -1
- package/dist/elements/kbd.js +1 -1
- package/dist/elements/link-preview.js +1 -1
- package/dist/elements/loader.js +1 -1
- package/dist/elements/markdown.js +1 -1
- package/dist/elements/menu.js +1 -1
- package/dist/elements/message-skills.js +1 -1
- package/dist/elements/message.js +1 -1
- package/dist/elements/model-switcher.js +1 -1
- package/dist/elements/nav.js +1 -1
- package/dist/elements/notice.js +1 -1
- package/dist/elements/pane-group.js +1 -1
- package/dist/elements/pane.js +1 -1
- package/dist/elements/popover.js +1 -1
- package/dist/elements/progress-bar.js +1 -1
- package/dist/elements/prompt-dock.js +1 -1
- package/dist/elements/prompt-input.js +1 -1
- package/dist/elements/prompt-suggestions.js +1 -1
- package/dist/elements/reasoning.js +1 -1
- package/dist/elements/register.d.ts +8 -6
- package/dist/elements/remote.js +1 -1
- package/dist/elements/resizable.js +1 -1
- package/dist/elements/response-stream.js +2 -2
- 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 +16 -0
- package/dist/elements/source.js +1 -1
- package/dist/elements/status.js +1 -1
- package/dist/elements/switch.js +1 -1
- package/dist/elements/tabs.js +1 -1
- package/dist/elements/tasks.js +1 -1
- package/dist/elements/text-shimmer.js +1 -1
- package/dist/elements/thinking-bar.js +1 -1
- package/dist/elements/thread.js +1 -1
- package/dist/elements/toast.js +1 -1
- package/dist/elements/tool.js +1 -1
- package/dist/elements/tooltip.js +1 -1
- package/dist/elements/validate-messages.d.ts +25 -0
- package/dist/elements/voice-input.js +1 -1
- package/dist/elements/voice-output.js +1 -1
- package/dist/elements.d.ts +2725 -214
- package/dist/index.d.ts +163 -125
- package/dist/index.js +6336 -5802
- package/dist/index.server.d.ts +5 -0
- package/dist/index.server.js +16913 -0
- package/dist/kai-provider.es.d.ts +5 -0
- package/dist/kai-provider.es.js +79 -77
- package/dist/kai.es.d.ts +5 -0
- package/dist/kai.es.js +1 -1
- package/dist/llms/llms-full.txt +762 -148
- package/dist/llms/llms.txt +57 -5
- package/dist/mcp.es.js +4010 -770
- package/dist/primitives/card-component-types.d.ts +11 -0
- package/dist/primitives/card-data-types.d.ts +196 -0
- package/dist/primitives/card-host.d.ts +1 -1
- package/dist/primitives/card-recovery.d.ts +3 -3
- package/dist/primitives/card-registry.d.ts +4 -14
- package/dist/primitives/card-resolution.d.ts +1 -1
- package/dist/primitives/card-routing.d.ts +1 -1
- package/dist/primitives/card-tags.d.ts +11 -0
- package/dist/primitives/card-validate-cards.d.ts +57 -0
- package/dist/primitives/card-validate-generator.testlib.d.ts +20 -0
- package/dist/primitives/card-validate-schemas.d.ts +17 -0
- package/dist/primitives/card-validate.d.ts +24 -0
- package/dist/primitives/create-kai-chat.d.ts +3 -3
- package/dist/primitives/embed-providers.d.ts +1 -1
- package/dist/primitives/link-preview.d.ts +1 -1
- package/dist/primitives/message-feedback.d.ts +2 -2
- package/dist/primitives/toast-store.d.ts +1 -1
- package/dist/react/index.d.ts +717 -299
- package/dist/react/use-kai-chat.d.ts +8 -4
- package/dist/react.d.ts +5 -0
- package/dist/react.js +417 -316
- package/dist/register-impl-bzrZ44ft.js +145 -0
- package/dist/remote/host-embed.d.ts +1 -1
- package/dist/remote/index.d.ts +2 -2
- package/dist/remote/provider-runtime.d.ts +2 -2
- package/dist/remote/provider.d.ts +2 -2
- package/dist/remote/validate.d.ts +1 -1
- package/dist/remote/wire.d.ts +1 -1
- package/dist/schemas/artifact.schema.json +92 -0
- package/dist/schemas/embed.schema.json +0 -2
- package/dist/schemas/from-tool-call.d.ts +48 -0
- package/dist/schemas/index.d.ts +48 -0
- package/dist/schemas/link.schema.json +0 -2
- package/dist/schemas/provider-subsets.d.ts +136 -0
- package/dist/schemas/registry.d.ts +140 -0
- package/dist/schemas/tool-defs.d.ts +121 -0
- package/dist/schemas.d.ts +5 -0
- package/dist/schemas.js +717 -0
- package/dist/solid-BCJUQqwS.js +22750 -0
- package/dist/solid-BdENBcEq.js +20108 -0
- package/dist/solid.d.ts +66 -0
- package/dist/solid.js +261 -0
- package/dist/solid.server.d.ts +5 -0
- package/dist/solid.server.js +261 -0
- package/dist/state/index.d.ts +14 -4
- package/dist/state/messages.d.ts +8 -3
- package/dist/state/mock.d.ts +46 -0
- package/dist/state/parts.d.ts +85 -0
- package/dist/state/stream.d.ts +15 -9
- package/dist/state.d.ts +5 -0
- package/dist/state.js +253 -84
- package/dist/ui/action-icons.d.ts +1 -1
- package/dist/ui/collapsible.d.ts +11 -6
- package/dist/ui/dropdown.d.ts +47 -42
- package/dist/ui/pane-group.d.ts +1 -1
- package/dist/variant-aurora-1wMcXRUS.js +381 -0
- package/dist/variant-aurora-BKHHiOgL.js +391 -0
- package/dist/{variant-aurora-DVtGqVH6.js → variant-aurora-DOb_o4pC.js} +1 -1
- package/dist/{variant-custom-Dif-IV4u.js → variant-custom-CJGB0Kbw.js} +1 -1
- package/dist/variant-custom-Co0CkXJF.js +200 -0
- package/dist/variant-custom-DWSSgmd2.js +170 -0
- package/dist/variant-wave-C3-45cL6.js +218 -0
- package/dist/{variant-wave-DbfNdvSi.js → variant-wave-CEODq-9q.js} +1 -1
- package/dist/variant-wave-jdXBnCUZ.js +208 -0
- package/dist/wire/chunk.d.ts +171 -0
- package/dist/wire/consume.d.ts +26 -0
- package/dist/wire/encode.d.ts +148 -0
- package/dist/wire/formats/anthropic.d.ts +2 -0
- package/dist/wire/formats/openai.d.ts +5 -0
- package/dist/wire/index.d.ts +14 -0
- package/dist/wire/read.d.ts +26 -0
- package/dist/wire/sink-helpers.d.ts +21 -0
- package/dist/wire/sse.d.ts +33 -0
- package/dist/wire.d.ts +5 -53
- package/dist/wire.js +898 -0
- package/frameworks/react/index.tsx +183 -154
- package/frameworks/react/runtime.tsx +21 -1
- package/frameworks/react/use-kai-chat.tsx +11 -1
- package/llms-full.txt +762 -148
- package/llms.txt +57 -5
- package/package.json +65 -7
- package/src/agent-tooling/archetypes.ts +96 -0
- package/src/agent-tooling/integrations/anthropic.ts +412 -0
- package/src/agent-tooling/integrations/cloudflare.ts +136 -52
- package/src/agent-tooling/integrations/langgraph.ts +67 -13
- package/src/agent-tooling/integrations/mastra.ts +120 -12
- package/src/agent-tooling/integrations/mock.ts +43 -8
- package/src/agent-tooling/integrations/ollama.ts +61 -24
- package/src/agent-tooling/integrations/openai.ts +87 -0
- package/src/agent-tooling/integrations/openrouter.ts +56 -8
- package/src/agent-tooling/integrations/pi.ts +79 -23
- package/src/agent-tooling/integrations/pydantic-ai.ts +24 -2
- package/src/agent-tooling/integrations/vercel-ai-sdk.ts +84 -13
- package/src/agent-tooling/mcp/manifest.ts +206 -25
- package/src/agent-tooling/mcp/tools/debug.ts +13 -7
- package/src/agent-tooling/mcp/tools/reference.ts +285 -6
- package/src/agent-tooling/mcp/tools/scaffold.ts +3345 -675
- package/src/agent-tooling/registry.ts +17 -0
- package/src/agent-tooling/types.ts +229 -1
- package/src/components/artifact-card.tsx +120 -0
- package/src/components/audio-visualizer/index.tsx +9 -0
- package/src/components/audio-visualizer/labs/lab-choreography.ts +187 -0
- package/src/components/audio-visualizer/labs/lab-shaders.ts +363 -0
- package/src/components/audio-visualizer/labs/lab-visualizer.tsx +102 -0
- package/src/components/audio-visualizer/shader-canvas.tsx +31 -1
- package/src/components/card-fallback.tsx +42 -10
- package/src/components/card-renderer.tsx +146 -9
- package/src/components/chat-container.tsx +4 -0
- package/src/components/chat-thread.tsx +118 -51
- package/src/components/choice-card.tsx +17 -29
- package/src/components/composer.tsx +12 -2
- package/src/components/confirm-card.tsx +24 -20
- package/src/components/context.tsx +12 -4
- package/src/components/conversation-list.tsx +18 -2
- package/src/components/file-tree.tsx +11 -22
- package/src/components/file-upload.tsx +14 -8
- package/src/components/form.tsx +14 -47
- package/src/components/loader.tsx +39 -12
- package/src/components/message-skills.tsx +4 -0
- package/src/components/message.tsx +294 -46
- package/src/components/reasoning.tsx +92 -5
- package/src/components/response-compare-types.ts +25 -0
- package/src/components/response-compare.tsx +4 -9
- package/src/components/source.tsx +50 -24
- package/src/components/tasks-card.tsx +10 -33
- package/src/components/thread.tsx +84 -42
- package/src/components/toast.tsx +11 -5
- package/src/components/tool-classify.ts +26 -0
- package/src/components/tool-types.ts +31 -1
- package/src/elements/agent-card.tsx +11 -11
- package/src/elements/artifact.tsx +15 -7
- package/src/elements/attachments.tsx +6 -4
- package/src/elements/avatar.tsx +1 -1
- package/src/elements/button.tsx +3 -3
- package/src/elements/card.tsx +2 -2
- package/src/elements/cards.tsx +109 -14
- package/src/elements/chain-of-thought.tsx +14 -10
- package/src/elements/chat-scope-picker.tsx +9 -7
- package/src/elements/chat-types.ts +59 -6
- package/src/elements/chat-workspace.tsx +50 -9
- package/src/elements/chat.tsx +64 -3
- package/src/elements/choice.tsx +8 -8
- package/src/elements/coachmark.tsx +1 -1
- package/src/elements/command.tsx +8 -23
- package/src/elements/compare.tsx +7 -6
- package/src/elements/compiled.css +1 -1
- package/src/elements/composer.tsx +8 -8
- package/src/elements/confirm-card.tsx +9 -9
- package/src/elements/context-meter.tsx +4 -18
- package/src/elements/conversation-list.tsx +14 -9
- package/src/elements/default-input.tsx +3 -3
- package/src/elements/define.tsx +178 -43
- package/src/elements/editable-label.tsx +17 -2
- package/src/elements/element-data-types.ts +112 -0
- package/src/elements/element-meta.json +1596 -304
- package/src/elements/element-types.d.ts +2636 -211
- package/src/elements/feedback-bar.tsx +1 -1
- package/src/elements/file-tree.tsx +1 -1
- package/src/elements/file-upload.tsx +1 -1
- package/src/elements/form.tsx +14 -6
- package/src/elements/input.tsx +1 -1
- package/src/elements/kbd.tsx +1 -1
- package/src/elements/menu.tsx +10 -29
- package/src/elements/message-skills.tsx +7 -9
- package/src/elements/message.tsx +200 -32
- package/src/elements/model-switcher.tsx +5 -3
- package/src/elements/pane.tsx +1 -1
- package/src/elements/prompt-dock.tsx +8 -8
- package/src/elements/prompt-input.tsx +10 -10
- package/src/elements/prompt-suggestions.tsx +7 -4
- package/src/elements/reasoning.tsx +1 -1
- package/src/elements/register.ts +9 -0
- package/src/elements/resizable.globals.d.ts +36 -0
- package/src/elements/resizable.tsx +24 -13
- package/src/elements/response-stream.tsx +1 -1
- package/src/elements/scroll-button.tsx +1 -1
- package/src/elements/search.tsx +6 -1
- package/src/elements/segmented.tsx +5 -11
- package/src/elements/separator.tsx +1 -1
- package/src/elements/slots.ts +57 -24
- package/src/elements/source.tsx +21 -22
- package/src/elements/switch.tsx +3 -3
- package/src/elements/tasks.tsx +5 -4
- package/src/elements/thread.tsx +36 -4
- package/src/elements/toast.tsx +3 -2
- package/src/elements/tool.tsx +1 -1
- package/src/elements/validate-messages.ts +76 -0
- package/src/elements/voice-input.tsx +7 -7
- package/src/elements/voice-output.tsx +4 -4
- package/src/index.ts +141 -6
- package/src/primitives/card-component-types.ts +63 -0
- package/src/primitives/card-data-types.ts +312 -0
- package/src/primitives/card-recovery.ts +13 -2
- package/src/primitives/card-registry.tsx +34 -23
- package/src/primitives/card-schemas/artifact.schema.json +92 -0
- package/src/primitives/card-schemas/embed.schema.json +0 -2
- package/src/primitives/card-schemas/link.schema.json +0 -2
- package/src/primitives/card-tags.ts +61 -0
- package/src/primitives/card-validate-cards.ts +255 -0
- package/src/primitives/card-validate-generator.testlib.ts +38 -0
- package/src/primitives/card-validate-schemas.ts +58 -0
- package/src/primitives/card-validate.ts +48 -20
- package/src/primitives/create-tween.ts +54 -2
- package/src/primitives/message-feedback.ts +3 -2
- package/src/primitives/use-audio-analysis.ts +20 -1
- package/src/primitives/use-sequencer.ts +20 -1
- package/src/schemas/from-tool-call.ts +151 -0
- package/src/schemas/index.ts +340 -0
- package/src/schemas/provider-subsets.ts +538 -0
- package/src/schemas/registry.ts +355 -0
- package/src/schemas/tool-defs.ts +492 -0
- package/src/solid.ts +150 -0
- package/src/state/index.ts +27 -1
- package/src/state/messages.ts +21 -4
- package/src/state/mock.ts +211 -0
- package/src/state/parts.ts +295 -0
- package/src/state/stream.ts +56 -58
- package/src/ui/collapsible.tsx +17 -5
- package/src/ui/dropdown.tsx +46 -12
- package/src/ui/overlay.tsx +10 -4
- package/src/wire/chunk.ts +201 -0
- package/src/wire/consume.ts +440 -0
- package/src/wire/encode.ts +474 -0
- package/src/wire/formats/anthropic.ts +267 -0
- package/src/wire/formats/openai.ts +187 -0
- package/src/wire/index.ts +52 -0
- package/src/wire/read.ts +152 -0
- package/src/wire/sink-helpers.ts +50 -0
- package/src/wire/sse.ts +140 -0
- package/dist/create-tween-hvpmSuwW.js +0 -7
- package/dist/elements/chunks/arrow-left-DQocUFvy.js +0 -1
- package/dist/elements/chunks/audio-visualizer-BqNy7dfm.js +0 -1
- package/dist/elements/chunks/card-BkHbp4BA.js +0 -1
- package/dist/elements/chunks/chat-thread-CkRN6pZ7.js +0 -1
- package/dist/elements/chunks/check-B9-gn6SS.js +0 -1
- package/dist/elements/chunks/chevron-down-BNsxc2hk.js +0 -1
- package/dist/elements/chunks/chevron-right-Hv00StBO.js +0 -1
- package/dist/elements/chunks/circle-0e3KJTDr.js +0 -1
- package/dist/elements/chunks/circle-check-BNAS0JEy.js +0 -1
- package/dist/elements/chunks/code-block-BFUHn6Va.js +0 -1
- package/dist/elements/chunks/context-Cb7k4F-v.js +0 -1
- package/dist/elements/chunks/conversation-list-CvoAkWhN.js +0 -1
- package/dist/elements/chunks/create-tween-oVvAIG8r.js +0 -7
- package/dist/elements/chunks/define-D1din7Ld.js +0 -1
- package/dist/elements/chunks/hover-card-Cmm6Q53m.js +0 -1
- package/dist/elements/chunks/message-BqyXDN3-.js +0 -1
- package/dist/elements/chunks/message-feedback-Djr3z6Yb.js +0 -1
- package/dist/elements/chunks/message-square-vFAgbDaX.js +0 -1
- package/dist/elements/chunks/reasoning-DTpCGtnY.js +0 -1
- package/dist/elements/chunks/scroll-button-B0cH5fXf.js +0 -1
- package/dist/elements/chunks/skeleton-DSXW5Yya.js +0 -1
- package/dist/elements/chunks/slots--V19HwUb.js +0 -1
- package/dist/elements/chunks/textarea-CUwqAX0G.js +0 -1
- package/dist/elements/chunks/tooltip-CgBZCVKp.js +0 -1
- package/dist/elements/chunks/use-card-resolution-BSu_XHjH.js +0 -1
- package/dist/elements/chunks/x-GRUeeQFT.js +0 -1
- package/dist/host-embed.d.ts +0 -33
- package/dist/kai-provider.d.ts +0 -2
- package/dist/origin.d.ts +0 -5
- package/dist/provider-runtime.d.ts +0 -27
- package/dist/register-impl-DQyejdfb.js +0 -145
- package/dist/validate.d.ts +0 -4
- package/dist/version.d.ts +0 -4
- package/src/components/component-meta.json +0 -4550
- package/src/elements/card-media.jpg +0 -0
- package/src/elements/resizable.d.ts +0 -27
- package/src/elements/video-poster.jpg +0 -0
package/src/elements/cards.tsx
CHANGED
|
@@ -4,12 +4,15 @@
|
|
|
4
4
|
// `kai-card` events through an optional `policy`. The raw events keep bubbling past
|
|
5
5
|
// <kai-cards> (composed) so document-level listeners still work. Unknown types render
|
|
6
6
|
// the Solid CardFallback inline and emit a contract `error`.
|
|
7
|
-
import { For, Show, createEffect, createSignal, on, onCleanup, onMount, type JSX } from 'solid-js';
|
|
7
|
+
import { For, Show, createEffect, createMemo, createSignal, on, onCleanup, onMount, type JSX } from 'solid-js';
|
|
8
8
|
import { Dynamic } from 'solid-js/web';
|
|
9
9
|
import { defineWebComponent } from './define';
|
|
10
10
|
import type { CardEnvelope, CardEvent, CardPolicy, CardResolution } from '../primitives/card-contract';
|
|
11
11
|
import { CARD_EVENT_NAME, emitCardEvent, routeCardEvent } from '../primitives/card-routing';
|
|
12
|
-
import { mergeCardTags } from '../primitives/card-registry';
|
|
12
|
+
import { BUILTIN_CARD_TAGS, mergeCardTags } from '../primitives/card-registry';
|
|
13
|
+
import type { JsonSchema } from '../primitives/card-validate';
|
|
14
|
+
import { cardValidationMessage, validateCardData, type CardValidationReport } from '../primitives/card-validate-cards';
|
|
15
|
+
import { hasConsumerSchema } from '../components/card-renderer';
|
|
13
16
|
import { CardFallback } from '../components/card-fallback';
|
|
14
17
|
// Register the built-in child card elements so that importing <kai-cards> is self-contained.
|
|
15
18
|
import './form';
|
|
@@ -26,18 +29,45 @@ interface Props extends Record<string, unknown> {
|
|
|
26
29
|
* Typed as a plain string map (not the `CardTagMap` alias) so the generated React
|
|
27
30
|
* wrapper inlines it instead of emitting an unresolved named type. */
|
|
28
31
|
types?: Record<string, string>;
|
|
32
|
+
/** JSON Schemas for the card types this app renders, keyed by envelope type. The
|
|
33
|
+
* companion of `types`, which says what DRAWS a card while this says what a
|
|
34
|
+
* VALID one looks like. An OBJECT, so it is a JS property only: `el.schemas = {
|
|
35
|
+
* 'pricing-table': pricingSchema }`, never an attribute.
|
|
36
|
+
* `createCardRegistry(...).validationSchemas` is exactly this shape.
|
|
37
|
+
*
|
|
38
|
+
* Without it the kit validates its own seven built-ins and leaves your own card
|
|
39
|
+
* type, the one your app actually cares about, as the only unchecked thing on
|
|
40
|
+
* screen. A schema here WINS over a built-in of the same name, matching
|
|
41
|
+
* `mergeCardTags`, where your entry is spread over ours.
|
|
42
|
+
*
|
|
43
|
+
* Typed `Record<string, object>` rather than `Record<string, JsonSchema>`
|
|
44
|
+
* deliberately: an imported `.json` schema widens `"type"` to `string`, and an
|
|
45
|
+
* authored one carries `$schema`/`title`/`description`/`additionalProperties`,
|
|
46
|
+
* so the tighter type would reject both of the normal ways to supply one. See
|
|
47
|
+
* `CardSchemaMap` in components/card-renderer.tsx. */
|
|
48
|
+
schemas?: Record<string, object>;
|
|
29
49
|
/** Optional CardPolicy handling child events. Property: `el.policy`. */
|
|
30
50
|
policy?: CardPolicy;
|
|
51
|
+
/** Validate each envelope's `data` against the schema for its type before
|
|
52
|
+
* rendering it, using a built-in's own schema or yours from `schemas`. Default
|
|
53
|
+
* `true`; set `validate-cards="false"` (or `el.validateCards = false`) to opt
|
|
54
|
+
* out. A hard failure (wrong type, a missing required field) renders a
|
|
55
|
+
* diagnostic naming the field instead of the card; a soft failure (bounds)
|
|
56
|
+
* renders the card unchanged. Both emit a contract `error` event. On in
|
|
57
|
+
* production too: a model emitting a bad shape is a production failure mode,
|
|
58
|
+
* so stripping the check there would hide it from exactly the person who needs
|
|
59
|
+
* to see it. */
|
|
60
|
+
validateCards?: boolean;
|
|
31
61
|
}
|
|
32
62
|
|
|
33
63
|
/** Events fired by `<kai-cards>`. */
|
|
34
64
|
interface Events {
|
|
35
|
-
/** A child card transitioned to a resolved/deferred state (an action was chosen,
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* this
|
|
65
|
+
/** A child card transitioned to a resolved/deferred state (an action was chosen, a
|
|
66
|
+
* form/tasks submission landed, or it was dismissed). Re-emitted off the host as
|
|
67
|
+
* a non-bubbling convenience event so a consumer can observe resolution centrally
|
|
68
|
+
* without diffing the cards array. `detail` = `{ cardId, resolution }`. (A
|
|
69
|
+
* `reopen` un-resolves a card and has no `CardResolution`, so it does NOT fire
|
|
70
|
+
* this; observe reopen via the underlying bubbling `kai-card` event.) */
|
|
41
71
|
'kai-card-resolved': { cardId: string; resolution: CardResolution };
|
|
42
72
|
}
|
|
43
73
|
|
|
@@ -57,9 +87,47 @@ function resolutionFromEvent(e: CardEvent): CardResolution | undefined {
|
|
|
57
87
|
}
|
|
58
88
|
}
|
|
59
89
|
|
|
60
|
-
/** A single resolved child: a known kai-* tag (props set imperatively)
|
|
61
|
-
|
|
90
|
+
/** A single resolved child: a known kai-* tag (props set imperatively), a diagnostic
|
|
91
|
+
* for data that cannot render, or the unknown-type fallback. */
|
|
92
|
+
function CardSlot(props: {
|
|
93
|
+
envelope: CardEnvelope;
|
|
94
|
+
tag?: string;
|
|
95
|
+
theme: string;
|
|
96
|
+
validate: boolean;
|
|
97
|
+
schemas?: Record<string, object>;
|
|
98
|
+
emit: (e: CardEvent) => void;
|
|
99
|
+
}): JSX.Element {
|
|
62
100
|
let ref: HTMLElement | undefined;
|
|
101
|
+
|
|
102
|
+
// MIRRORS src/remote/provider-runtime.ts:139-147, the same way
|
|
103
|
+
// components/card-renderer.tsx does. The remote (iframe) transport has validated
|
|
104
|
+
// every incoming envelope since the contract landed and this native one did not,
|
|
105
|
+
// so the same bad payload was caught in one transport and rendered silently in the
|
|
106
|
+
// other. Two tiers: `hard` (nothing to render) replaces the card with a diagnostic
|
|
107
|
+
// naming the field, `soft` (bounds) renders the card untouched. Both emit `error`.
|
|
108
|
+
//
|
|
109
|
+
// OUR schema applies only to OUR element: `types` lets a consumer point a built-in
|
|
110
|
+
// card type at their own element (`el.types = { confirm: 'my-confirm-el' }`), and
|
|
111
|
+
// our schema describes our element's data, not theirs.
|
|
112
|
+
//
|
|
113
|
+
// A schema the CONSUMER registered through `el.schemas` runs the other way: they
|
|
114
|
+
// wrote it about their own card, and it is the shape their model was told to
|
|
115
|
+
// emit, so it applies whichever element draws the type. That is what validates a
|
|
116
|
+
// `pricing-table` — nobody's built-in, and until this prop existed the one card in
|
|
117
|
+
// the app that nothing checked. Same rule as components/card-renderer.tsx, which
|
|
118
|
+
// compares component identity where this compares tag identity; `hasConsumerSchema`
|
|
119
|
+
// is shared with it so the gate is spelled once.
|
|
120
|
+
const report = createMemo<CardValidationReport | null>(() => {
|
|
121
|
+
if (!props.validate) return null;
|
|
122
|
+
if (!hasConsumerSchema(props.schemas, props.envelope.type) && props.tag !== BUILTIN_CARD_TAGS[props.envelope.type]) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
// `schemas` is passed even when the gate opened on tag identity, so a consumer
|
|
126
|
+
// schema for a built-in type wins over ours — `schemaFor`'s rule.
|
|
127
|
+
return validateCardData(props.envelope.type, props.envelope.data, props.schemas as Record<string, JsonSchema> | undefined);
|
|
128
|
+
});
|
|
129
|
+
const invalid = () => report()?.tier === 'hard';
|
|
130
|
+
|
|
63
131
|
// Set object/string props as DOM properties on the custom element (reactive).
|
|
64
132
|
createEffect(() => {
|
|
65
133
|
if (!ref) return;
|
|
@@ -79,19 +147,44 @@ function CardSlot(props: { envelope: CardEnvelope; tag?: string; theme: string;
|
|
|
79
147
|
props.emit({ kind: 'error', cardId: props.envelope.id, message: `Unsupported card type: ${props.envelope.type}` });
|
|
80
148
|
}
|
|
81
149
|
});
|
|
150
|
+
// One `error` per distinct problem, both tiers. Keyed on the message, not on
|
|
151
|
+
// mount: a consumer re-assigning `el.cards` per stream chunk hands this a new
|
|
152
|
+
// envelope object each time, so an identity-triggered emit would fire per chunk.
|
|
153
|
+
let lastEmitted: string | null = null;
|
|
154
|
+
createEffect(() => {
|
|
155
|
+
const r = report();
|
|
156
|
+
if (!props.tag) return; // an unknown TYPE already reported itself in onMount
|
|
157
|
+
if (!r || r.ok) {
|
|
158
|
+
lastEmitted = null;
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const message = cardValidationMessage(r);
|
|
162
|
+
if (message === lastEmitted) return;
|
|
163
|
+
lastEmitted = message;
|
|
164
|
+
props.emit({ kind: 'error', cardId: props.envelope.id, message });
|
|
165
|
+
});
|
|
166
|
+
|
|
82
167
|
return (
|
|
83
168
|
<Show
|
|
84
169
|
when={props.tag}
|
|
85
170
|
fallback={<CardFallback type={props.envelope.type} cardId={props.envelope.id} />}
|
|
86
171
|
>
|
|
87
|
-
{(tag) =>
|
|
172
|
+
{(tag) => (
|
|
173
|
+
<Show
|
|
174
|
+
when={invalid()}
|
|
175
|
+
// SOFT and valid both take this branch: the card renders as it does today.
|
|
176
|
+
fallback={<Dynamic component={tag()} ref={ref} />}
|
|
177
|
+
>
|
|
178
|
+
<CardFallback type={props.envelope.type} cardId={props.envelope.id} reason={report()!.summary} />
|
|
179
|
+
</Show>
|
|
180
|
+
)}
|
|
88
181
|
</Show>
|
|
89
182
|
);
|
|
90
183
|
}
|
|
91
184
|
|
|
92
185
|
defineWebComponent<Props, Events>(
|
|
93
186
|
'kai-cards',
|
|
94
|
-
{ cards: undefined, types: undefined, policy: undefined },
|
|
187
|
+
{ cards: undefined, types: undefined, schemas: undefined, policy: undefined, validateCards: true },
|
|
95
188
|
(props, { element, dispatch, expose }) => {
|
|
96
189
|
// Local working copy of the card list. The `cards` PROP still drives rendering
|
|
97
190
|
// (a new prop array re-seeds this), but holding a settable copy lets the
|
|
@@ -134,11 +227,11 @@ defineWebComponent<Props, Events>(
|
|
|
134
227
|
);
|
|
135
228
|
expose({
|
|
136
229
|
/** Programmatically resolve a child card by id: set that envelope's
|
|
137
|
-
* `resolution` so the child re-renders into its read-only/resolved view
|
|
230
|
+
* `resolution` so the child re-renders into its read-only/resolved view. The
|
|
138
231
|
* imperative twin of the consumer mutating the cards array. No-op for an
|
|
139
232
|
* unknown id. */
|
|
140
233
|
resolve: (cardId: string, resolution: CardResolution) => resolveCard(cardId, resolution),
|
|
141
|
-
/** Collapse a card to its re-openable stub from the host side
|
|
234
|
+
/** Collapse a card to its re-openable stub from the host side. Convenience for
|
|
142
235
|
* `resolve(cardId, { kind: 'dismissed' })`. */
|
|
143
236
|
dismiss: (cardId: string) => resolveCard(cardId, { kind: 'dismissed' }),
|
|
144
237
|
/** Return the live child element node for a card id (or null) so consumers can
|
|
@@ -161,6 +254,8 @@ defineWebComponent<Props, Events>(
|
|
|
161
254
|
envelope={env}
|
|
162
255
|
tag={tags()[env.type]}
|
|
163
256
|
theme={theme()}
|
|
257
|
+
validate={props.validateCards !== false}
|
|
258
|
+
schemas={props.schemas}
|
|
164
259
|
emit={(e) => emitCardEvent(element, e)}
|
|
165
260
|
/>
|
|
166
261
|
)}
|
|
@@ -19,23 +19,25 @@ type Step = ChainOfThoughtStepData;
|
|
|
19
19
|
|
|
20
20
|
interface Props extends Record<string, unknown> {
|
|
21
21
|
/** The reasoning steps. Set as a JS property. Compound sub-parts collapse to
|
|
22
|
-
* this one data model (Route 1). Each `{ label, content?, id? }`.
|
|
23
|
-
steps
|
|
24
|
-
|
|
22
|
+
* this one data model (Route 1). Each `{ label, content?, id? }`. Omit to
|
|
23
|
+
* supply the steps as `<kai-step>` light-DOM children instead; when both are
|
|
24
|
+
* present the property's steps come first. */
|
|
25
|
+
steps?: Step[];
|
|
26
|
+
/** Open mode: `'multiple'` (default, any number of steps open at once) or
|
|
25
27
|
* `'single'` (at most one open; opening a step closes the others). */
|
|
26
28
|
type?: ChainOfThoughtType;
|
|
27
29
|
/** Controlled open step key(s). When set, it WINS over user interaction (the
|
|
28
30
|
* consumer owns the open set). String in `single` mode, string[] in
|
|
29
31
|
* `multiple` mode. Set as a JS property. */
|
|
30
32
|
value?: string | string[];
|
|
31
|
-
/** Uncontrolled INITIAL open step key(s)
|
|
32
|
-
* Ignored once `value` is provided. Set as a JS property. */
|
|
33
|
+
/** Uncontrolled INITIAL open step key(s), seeding which steps render
|
|
34
|
+
* expanded. Ignored once `value` is provided. Set as a JS property. */
|
|
33
35
|
defaultValue?: string | string[];
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
/** Events fired by `<kai-chain-of-thought>`. */
|
|
37
39
|
interface Events {
|
|
38
|
-
/** The open set changed
|
|
40
|
+
/** The open set changed, by user click OR an expand()/collapse()/toggle()
|
|
39
41
|
* call. `value` is a string in `single` mode, a string[] in `multiple` mode.
|
|
40
42
|
* (Maps Radix Accordion's onValueChange.) */
|
|
41
43
|
'kai-value-change': { value: string | string[] };
|
|
@@ -99,7 +101,7 @@ defineWebComponent<Props, Events>('kai-chain-of-thought', {
|
|
|
99
101
|
});
|
|
100
102
|
|
|
101
103
|
// Prop steps first; declarative children appended after.
|
|
102
|
-
const allSteps = () => [...props.steps, ...slottedSteps()];
|
|
104
|
+
const allSteps = () => [...(props.steps ?? []), ...slottedSteps()];
|
|
103
105
|
|
|
104
106
|
// ── Imperative API (instance methods on the host) ──────────────────────────
|
|
105
107
|
// Pattern C: the Accordion component owns the open-set; the facade captures its
|
|
@@ -109,10 +111,12 @@ defineWebComponent<Props, Events>('kai-chain-of-thought', {
|
|
|
109
111
|
// the only props are steps/type/value/defaultValue.
|
|
110
112
|
let controller: ChainOfThoughtController | undefined;
|
|
111
113
|
expose({
|
|
112
|
-
/** Open one step's detail by index, or
|
|
113
|
-
* mode opening one step closes the others (expand-all keeps the
|
|
114
|
+
/** Open one step's detail by index, or ALL steps when called with no arg. In
|
|
115
|
+
* `single` mode opening one step closes the others (expand-all keeps the
|
|
116
|
+
* last). */
|
|
114
117
|
expand: (index?: number) => controller?.expand(index),
|
|
115
|
-
/** Close one step's detail by index, or
|
|
118
|
+
/** Close one step's detail by index, or ALL steps when called with no
|
|
119
|
+
* arg. */
|
|
116
120
|
collapse: (index?: number) => controller?.collapse(index),
|
|
117
121
|
/** Flip one step's open state by index. */
|
|
118
122
|
toggle: (index?: number) => controller?.toggle(index),
|
|
@@ -5,10 +5,12 @@ import type { DropdownController } from '../ui/dropdown';
|
|
|
5
5
|
import type { SearchFilters } from '../types';
|
|
6
6
|
|
|
7
7
|
interface Props extends Record<string, unknown> {
|
|
8
|
-
/** Authors to offer as scope filters.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
/** Authors to offer as scope filters. Omit to drop the Authors section (for a
|
|
9
|
+
* tag-only picker). Set as a JS property. */
|
|
10
|
+
availableAuthors?: string[];
|
|
11
|
+
/** Tags to offer as scope filters. Omit to drop the Tags section (for an
|
|
12
|
+
* author-only picker). Set as a JS property. */
|
|
13
|
+
availableTags?: string[];
|
|
12
14
|
/** The label shown on the trigger for the active scope. */
|
|
13
15
|
currentLabel?: string;
|
|
14
16
|
/** Drive/observe the dropdown's open state (Shoelace-style: settable + reflected
|
|
@@ -17,7 +19,7 @@ interface Props extends Record<string, unknown> {
|
|
|
17
19
|
open?: boolean;
|
|
18
20
|
/** Initial open state on mount (uncontrolled seed). */
|
|
19
21
|
defaultOpen?: boolean;
|
|
20
|
-
/** Disable the trigger
|
|
22
|
+
/** Disable the trigger: click/keyboard and `show()` no longer open the dropdown. */
|
|
21
23
|
disabled?: boolean;
|
|
22
24
|
}
|
|
23
25
|
|
|
@@ -52,8 +54,8 @@ defineWebComponent<Props, Events>('kai-scope-picker', {
|
|
|
52
54
|
return (
|
|
53
55
|
<ChatScopePicker
|
|
54
56
|
currentLabel={props.currentLabel ?? 'All Content'}
|
|
55
|
-
availableAuthors={props.availableAuthors}
|
|
56
|
-
availableTags={props.availableTags}
|
|
57
|
+
availableAuthors={props.availableAuthors ?? []}
|
|
58
|
+
availableTags={props.availableTags ?? []}
|
|
57
59
|
onScopeChange={(filters) => dispatch('kai-scope-change', { filters })}
|
|
58
60
|
defaultOpen={flag('defaultOpen')}
|
|
59
61
|
disabled={flag('disabled')}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import type { ToolPart } from '../components/tool-types';
|
|
1
|
+
import type { ToolPart, RawOrigin } from '../components/tool-types';
|
|
2
2
|
import type { AttachmentData } from '../components/attachment-types';
|
|
3
|
+
import type { CardEnvelope } from '../primitives/card-contract';
|
|
4
|
+
|
|
5
|
+
/** Re-exported so consumers of chat-types (and MessagePart) can keep using
|
|
6
|
+
* RawOrigin unqualified. It is defined in components/tool-types.ts, not here,
|
|
7
|
+
* to keep the components -> elements import direction one-way. */
|
|
8
|
+
export type { RawOrigin };
|
|
3
9
|
|
|
4
10
|
/** The five built-in action buttons (each carries its own curated icon + label). */
|
|
5
11
|
export type ChatMessageAction = 'copy' | 'like' | 'dislike' | 'regenerate' | 'edit';
|
|
@@ -31,14 +37,61 @@ export interface AvatarData {
|
|
|
31
37
|
alt?: string;
|
|
32
38
|
}
|
|
33
39
|
|
|
40
|
+
/** A citation the model produced. */
|
|
41
|
+
export interface Source {
|
|
42
|
+
id?: string;
|
|
43
|
+
url?: string;
|
|
44
|
+
title?: string;
|
|
45
|
+
snippet?: string;
|
|
46
|
+
/** Citation marker number, when the model numbers its citations. */
|
|
47
|
+
index?: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** The public name for the citation carried by a `source` part, and the argument
|
|
51
|
+
* type of `AssistantStream.addSource`. The bare `Source` name is already taken
|
|
52
|
+
* on the public entry by the citation-chip COMPONENT (`./components/source`),
|
|
53
|
+
* so exporting this interface unaliased would be a duplicate identifier and the
|
|
54
|
+
* type would be unnameable from `@kitn.ai/ui`. */
|
|
55
|
+
export type MessageSource = Source;
|
|
56
|
+
|
|
57
|
+
/** One ordered piece of message content. Closed union: extension happens at the CARD
|
|
58
|
+
* layer via the card registry, not by adding variants here. */
|
|
59
|
+
export type MessagePart =
|
|
60
|
+
| { type: 'text'; text: string; raw?: RawOrigin }
|
|
61
|
+
| {
|
|
62
|
+
type: 'reasoning';
|
|
63
|
+
text: string;
|
|
64
|
+
label?: string;
|
|
65
|
+
/** Provider block index. Keeps parallel reasoning blocks distinct. */
|
|
66
|
+
index?: number;
|
|
67
|
+
/** Which provider RESPONSE STREAM `index` was counted in. Anthropic restarts
|
|
68
|
+
* content-block indices at 0 for every message, and a multi-round tool loop
|
|
69
|
+
* folds several of those messages into ONE assistant turn, so `index` alone
|
|
70
|
+
* is not unique within `parts`. Set by the wire adapter, one value per
|
|
71
|
+
* `consumeModelStream` call. See `appendReasoningPart`. */
|
|
72
|
+
streamId?: string;
|
|
73
|
+
/** Load-bearing on the OpenAI wire, informational on the Anthropic one.
|
|
74
|
+
* `toOpenAIMessages({ reasoning: 'include' })` REBUILDS a signed
|
|
75
|
+
* `reasoning_details` entry from `text` plus this, because `raw` after a
|
|
76
|
+
* streamed turn is a textless fragment: only the final frame carries the
|
|
77
|
+
* signature and it has no text, and `appendReasoningPart` resolves `raw`
|
|
78
|
+
* last-write-wins. `toAnthropicMessages` ignores this field and echoes
|
|
79
|
+
* `raw.payload` verbatim — a thinking block rebuilt from text plus
|
|
80
|
+
* signature is a hard 400. */
|
|
81
|
+
signature?: string;
|
|
82
|
+
raw?: RawOrigin;
|
|
83
|
+
}
|
|
84
|
+
| { type: 'tool'; tool: ToolPart; raw?: RawOrigin }
|
|
85
|
+
| { type: 'card'; envelope: CardEnvelope; raw?: RawOrigin }
|
|
86
|
+
| { type: 'source'; source: Source; raw?: RawOrigin }
|
|
87
|
+
| { type: 'file'; attachment: AttachmentData; raw?: RawOrigin };
|
|
88
|
+
|
|
34
89
|
export interface ChatMessage {
|
|
35
90
|
id: string;
|
|
36
91
|
role: 'user' | 'assistant';
|
|
37
|
-
content
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
attachments?: AttachmentData[];
|
|
41
|
-
/** Action buttons under the message — built-in names and/or custom descriptors. */
|
|
92
|
+
/** The ONLY content channel. Ordered. */
|
|
93
|
+
parts: MessagePart[];
|
|
94
|
+
/** Action buttons under the message. Chrome, not content. */
|
|
42
95
|
actions?: (ChatMessageAction | CustomAction)[];
|
|
43
96
|
/** Optional speaker avatar shown to the left of the message column. */
|
|
44
97
|
avatar?: AvatarData;
|
|
@@ -5,6 +5,8 @@ import { readSlots, WORKSPACE_SLOTS } from './slots';
|
|
|
5
5
|
import { ChatThread, type ChatThreadContextUsage, type ChatThreadController } from '../components/chat-thread';
|
|
6
6
|
import { ConversationList, CollapsedRail } from '../components/conversation-list';
|
|
7
7
|
import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '../ui/resizable';
|
|
8
|
+
import { cardComponentsFromTags } from './message';
|
|
9
|
+
import { createMessagesGuard } from './validate-messages';
|
|
8
10
|
import type { AttachmentData } from '../components/attachments';
|
|
9
11
|
import type { TriggerDef } from '../components/composer';
|
|
10
12
|
import type { ChatMessage } from './chat-types';
|
|
@@ -12,14 +14,25 @@ import type { ProseSize } from '../primitives/chat-config';
|
|
|
12
14
|
import type { ModelOption, ConversationGroup, ConversationSummary } from '../types';
|
|
13
15
|
|
|
14
16
|
interface Props extends Record<string, unknown> {
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
/** The sidebar's section headers, rendered in array order. A group carries no
|
|
18
|
+
* conversations of its own; it is matched against `conversations` by id, so
|
|
19
|
+
* the two props are complementary rather than alternatives. Omit for an
|
|
20
|
+
* ungrouped sidebar. Set as a JS property. */
|
|
21
|
+
groups?: ConversationGroup[];
|
|
22
|
+
/** Every conversation in the sidebar, flat. Each one is filed under the group
|
|
23
|
+
* whose `id` equals its `groupId`; one with no `groupId`, or with a `groupId`
|
|
24
|
+
* matching no entry in `groups`, falls into a trailing ungrouped section
|
|
25
|
+
* (headerless when `compact`), so nothing you pass in is ever dropped. There is
|
|
26
|
+
* no recency bucketing. Set as a JS property. Omit for an empty sidebar, or
|
|
27
|
+
* when `no-conversations` replaces the built-in list with your own
|
|
28
|
+
* `sidebar-header` content. */
|
|
29
|
+
conversations?: ConversationSummary[];
|
|
19
30
|
/** Id of the open conversation, highlighted in the sidebar. */
|
|
20
31
|
activeId?: string;
|
|
21
|
-
/** The active conversation's message thread, newest last. Set as a JS property
|
|
22
|
-
messages
|
|
32
|
+
/** The active conversation's message thread, newest last. Set as a JS property
|
|
33
|
+
* (`el.messages = [...]`); a NEW array reference per streaming chunk
|
|
34
|
+
* re-renders (mutating in place does not). Omit for an empty thread. */
|
|
35
|
+
messages?: ChatMessage[];
|
|
23
36
|
value?: string;
|
|
24
37
|
placeholder?: string;
|
|
25
38
|
loading?: boolean;
|
|
@@ -63,6 +76,26 @@ interface Props extends Record<string, unknown> {
|
|
|
63
76
|
* whole rail flex region (for apps that supply their own rail nav). Default
|
|
64
77
|
* false. Attribute: `no-conversations`. */
|
|
65
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>;
|
|
66
99
|
}
|
|
67
100
|
|
|
68
101
|
interface Events {
|
|
@@ -99,8 +132,14 @@ defineWebComponent<Props, Events>('kai-workspace', {
|
|
|
99
132
|
search: false, voice: false, triggers: undefined, kindIcons: undefined,
|
|
100
133
|
sidebarWidth: 26, sidebarMinWidth: 240, sidebarMaxWidth: 420,
|
|
101
134
|
sidebarCollapsed: undefined, defaultSidebarCollapsed: undefined, collapseBelow: undefined, compact: undefined,
|
|
102
|
-
noConversations: undefined,
|
|
135
|
+
noConversations: undefined, cardTypes: undefined, cardSchemas: undefined,
|
|
103
136
|
}, (props, { dispatch, flag, expose, element }) => {
|
|
137
|
+
// `messages` is an untyped boundary: a consumer can hand it anything at
|
|
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
|
+
|
|
104
143
|
// Which injection slots the consumer has filled. A bare <slot> is always a
|
|
105
144
|
// truthy JSX node, so we render each region wrapper ONLY when readSlots reports
|
|
106
145
|
// projected light-DOM content (re-read on childList mutation).
|
|
@@ -180,7 +219,7 @@ defineWebComponent<Props, Events>('kai-workspace', {
|
|
|
180
219
|
// own state (e.g. an uncontrolled draft) survives the collapse/expand.
|
|
181
220
|
const threadEl = (
|
|
182
221
|
<ChatThread
|
|
183
|
-
messages={props.messages} value={props.value as string | undefined} placeholder={props.placeholder as string}
|
|
222
|
+
messages={validMessages(props.messages)} value={props.value as string | undefined} placeholder={props.placeholder as string}
|
|
184
223
|
loading={flag('loading')} suggestions={props.suggestions as string[] | undefined}
|
|
185
224
|
suggestionMode={props.suggestionMode as 'submit' | 'fill'} proseSize={props.proseSize as ProseSize}
|
|
186
225
|
codeTheme={props.codeTheme as string} codeHighlight={flag('codeHighlight')}
|
|
@@ -189,6 +228,8 @@ defineWebComponent<Props, Events>('kai-workspace', {
|
|
|
189
228
|
scrollButton={props.scrollButton !== false} search={flag('search')} voice={flag('voice')}
|
|
190
229
|
triggers={props.triggers as TriggerDef[] | undefined}
|
|
191
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}
|
|
192
233
|
onValueChange={(value) => dispatch('kai-value-change', { value })}
|
|
193
234
|
onSubmit={(detail) => dispatch('kai-submit', detail)}
|
|
194
235
|
onSuggestionClick={(value) => dispatch('kai-suggestion-click', { value })}
|
|
@@ -253,7 +294,7 @@ defineWebComponent<Props, Events>('kai-workspace', {
|
|
|
253
294
|
<div class="min-h-0 flex-1">
|
|
254
295
|
<ConversationList
|
|
255
296
|
class="bg-transparent"
|
|
256
|
-
groups={props.groups} conversations={props.conversations} activeId={props.activeId as string | undefined}
|
|
297
|
+
groups={props.groups ?? []} conversations={props.conversations ?? []} activeId={props.activeId as string | undefined}
|
|
257
298
|
compact={flag('compact')}
|
|
258
299
|
onSelect={(id) => dispatch('kai-conversation-select', { id })}
|
|
259
300
|
onNewChat={() => dispatch('kai-new-chat', {})}
|
package/src/elements/chat.tsx
CHANGED
|
@@ -2,7 +2,10 @@ import { createEffect, 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';
|
|
5
|
+
import { cardComponentsFromTags } from './message';
|
|
6
|
+
import { createMessagesGuard } from './validate-messages';
|
|
5
7
|
import type { AttachmentData } from '../components/attachments';
|
|
8
|
+
import type { ChatMessage } from './chat-types';
|
|
6
9
|
import type { TriggerDef } from '../components/composer';
|
|
7
10
|
import type { ComposerDoc } from '../primitives/composer-model';
|
|
8
11
|
import type { ProseSize } from '../primitives/chat-config';
|
|
@@ -10,7 +13,38 @@ import type { ModelOption } from '../types';
|
|
|
10
13
|
|
|
11
14
|
type Props = Omit<ChatThreadProps,
|
|
12
15
|
'class' | 'onValueChange' | 'onSubmit' | 'onAttachmentsChange' | 'onSuggestionClick' | 'onModelChange'
|
|
13
|
-
| 'onMessageAction' | 'onSearch' | 'onVoice' | 'controllerRef'> & Record<string, unknown
|
|
16
|
+
| 'onMessageAction' | 'onSearch' | 'onVoice' | 'controllerRef' | 'cardTypes' | 'cardSchemas' | 'messages'> & Record<string, unknown> & {
|
|
17
|
+
/** The full message thread to render, newest last. Each entry carries its
|
|
18
|
+
* role, ordered `parts`, and optional actions/avatar/feedback. Set as a JS
|
|
19
|
+
* property (`el.messages = [...]`); a NEW array reference per streaming
|
|
20
|
+
* chunk re-renders (mutating in place does not). Omit for an empty thread.
|
|
21
|
+
*
|
|
22
|
+
* Re-declared here (rather than inherited from `ChatThreadProps`) because
|
|
23
|
+
* the ELEMENT registers a `[]` default and renders the empty state without
|
|
24
|
+
* it, while the SolidJS `<ChatThread>` component still requires it. The
|
|
25
|
+
* facade hands it a validated array either way. Matches `<kai-thread>`. */
|
|
26
|
+
messages?: ChatMessage[];
|
|
27
|
+
/** Optional card type -> custom-element tag overrides/additions for `card`
|
|
28
|
+
* parts (merged over the built-ins). Property: `el.cardTypes`. Typed as a
|
|
29
|
+
* plain string map (not the `CardTagMap` alias) so the generated React
|
|
30
|
+
* wrapper inlines it instead of emitting an unresolved named type. */
|
|
31
|
+
cardTypes?: Record<string, string>;
|
|
32
|
+
/** JSON Schemas for the card types this app renders, keyed by envelope type. The
|
|
33
|
+
* companion of `cardTypes`, which says what DRAWS a card while this says what a
|
|
34
|
+
* VALID one looks like. An OBJECT, so it is a JS property only: `el.cardSchemas
|
|
35
|
+
* = { 'pricing-table': pricingSchema }`, never an attribute.
|
|
36
|
+
* `createCardRegistry(...).validationSchemas` is exactly this shape.
|
|
37
|
+
*
|
|
38
|
+
* Without it the kit validates its own seven built-ins and leaves your own card
|
|
39
|
+
* type, the one your app actually cares about, as the only unchecked thing on
|
|
40
|
+
* screen. A schema here WINS over a built-in of the same name.
|
|
41
|
+
*
|
|
42
|
+
* Typed `Record<string, object>` rather than `Record<string, JsonSchema>`
|
|
43
|
+
* deliberately: an imported `.json` schema widens `"type"` to `string`, and an
|
|
44
|
+
* authored one carries `$schema`/`title`/`description`/`additionalProperties`,
|
|
45
|
+
* so the tighter type would reject both of the normal ways to supply one. */
|
|
46
|
+
cardSchemas?: Record<string, object>;
|
|
47
|
+
};
|
|
14
48
|
|
|
15
49
|
interface Events {
|
|
16
50
|
/** User submitted a message. */
|
|
@@ -40,8 +74,14 @@ defineWebComponent<Props, Events>('kai-chat', {
|
|
|
40
74
|
codeTheme: 'github-dark-dimmed', codeHighlight: true, chatTitle: undefined,
|
|
41
75
|
models: undefined, currentModel: undefined, context: undefined, scrollButton: true,
|
|
42
76
|
search: false, voice: false, triggers: undefined, kindIcons: undefined,
|
|
43
|
-
actionsReveal: 'always',
|
|
77
|
+
actionsReveal: 'always', cardTypes: undefined, cardSchemas: undefined,
|
|
44
78
|
}, (props, { dispatch, flag, element, expose }) => {
|
|
79
|
+
// `messages` is an untyped boundary: a consumer can hand it anything at
|
|
80
|
+
// runtime (a pre-0.20.0 `{ id, role, content }` array, in particular). Skip
|
|
81
|
+
// the invalid entries rather than let `groupMessageParts` throw deep inside a
|
|
82
|
+
// render pass, which would blank the whole chat instead of one message.
|
|
83
|
+
const validMessages = createMessagesGuard('kai-chat');
|
|
84
|
+
|
|
45
85
|
// Slot detection is driven by the CHAT_SLOTS registry (single source of truth)
|
|
46
86
|
// so slot names never drift between the view, the facade, and the docs.
|
|
47
87
|
const [slots, setSlots] = createSignal<Record<string, boolean>>({});
|
|
@@ -62,16 +102,35 @@ defineWebComponent<Props, Events>('kai-chat', {
|
|
|
62
102
|
// (focus the composer, clear it, send programmatically, scroll the thread).
|
|
63
103
|
let controller: ChatThreadController | undefined;
|
|
64
104
|
expose({
|
|
105
|
+
/** Focus the composer, meaning the contenteditable (or textarea) inside the
|
|
106
|
+
* shadow root. A native `focus()` on the host lands on the host itself and
|
|
107
|
+
* never reaches it, so this is the only way to focus the input
|
|
108
|
+
* programmatically. */
|
|
65
109
|
focus: (options?: FocusOptions) => controller?.focus(options),
|
|
110
|
+
/** Blur whatever currently holds focus inside the shadow root. The companion
|
|
111
|
+
* to `focus()`, for the same reason: a native `blur()` on the host misses
|
|
112
|
+
* the real focus target. */
|
|
66
113
|
blur: () => (element.shadowRoot?.activeElement as HTMLElement | null)?.blur(),
|
|
114
|
+
/** Empty the COMPOSER: drops the draft text and every staged attachment, then
|
|
115
|
+
* fires `kai-value-change` with `''`. It does NOT touch the thread. `messages`
|
|
116
|
+
* is the consumer's own state, so clearing history stays the consumer's call. */
|
|
67
117
|
clear: () => controller?.clear(),
|
|
118
|
+
/** Submit whatever the composer currently holds, on the same path as Enter or
|
|
119
|
+
* the send button: fires `kai-submit` with that value plus the staged
|
|
120
|
+
* attachments, then drops the attachments. It takes no argument, so to send
|
|
121
|
+
* text the user never typed, set `el.value` first. There is no empty-check,
|
|
122
|
+
* so an empty composer still fires. The draft is cleared afterwards only when
|
|
123
|
+
* `value` is uncontrolled; a controlled host owns its value and clears it
|
|
124
|
+
* itself. Named `send`, not `submit`, to match the shared vocabulary. */
|
|
68
125
|
send: () => controller?.send(),
|
|
126
|
+
/** Scroll the message viewport to the newest message. Defaults to `'smooth'`;
|
|
127
|
+
* pass `'instant'` to jump without animating. */
|
|
69
128
|
scrollToBottom: (behavior?: ScrollBehavior) => controller?.scrollToBottom(behavior),
|
|
70
129
|
});
|
|
71
130
|
|
|
72
131
|
return (
|
|
73
132
|
<ChatThread
|
|
74
|
-
messages={props.messages} value={props.value as string | ComposerDoc | undefined} placeholder={props.placeholder as string}
|
|
133
|
+
messages={validMessages(props.messages)} value={props.value as string | ComposerDoc | undefined} placeholder={props.placeholder as string}
|
|
75
134
|
loading={flag('loading')} suggestions={props.suggestions as string[] | undefined}
|
|
76
135
|
suggestionMode={props.suggestionMode as 'submit' | 'fill'} persistSuggestions={flag('persistSuggestions')}
|
|
77
136
|
proseSize={props.proseSize as ProseSize}
|
|
@@ -82,6 +141,8 @@ defineWebComponent<Props, Events>('kai-chat', {
|
|
|
82
141
|
triggers={props.triggers as TriggerDef[] | undefined}
|
|
83
142
|
kindIcons={props.kindIcons as Record<string, string> | undefined}
|
|
84
143
|
actionsReveal={props.actionsReveal as 'always' | 'hover'}
|
|
144
|
+
cardTypes={cardComponentsFromTags(props.cardTypes as Record<string, string> | undefined, (props as { theme?: string }).theme)}
|
|
145
|
+
cardSchemas={props.cardSchemas as Record<string, object> | undefined}
|
|
85
146
|
onValueChange={(value) => dispatch('kai-value-change', { value })}
|
|
86
147
|
onSubmit={(detail) => dispatch('kai-submit', detail)}
|
|
87
148
|
onAttachmentsChange={(attachments) => dispatch('kai-attachments-change', { attachments })}
|
package/src/elements/choice.tsx
CHANGED
|
@@ -6,7 +6,7 @@ interface Props extends Record<string, unknown> {
|
|
|
6
6
|
/** The choice definition (the CardEnvelope.data). Set as a JS PROPERTY:
|
|
7
7
|
* `el.data = { prompt, options:[…], allowOther?, submitLabel? }`. Import
|
|
8
8
|
* `ChoiceCardData` from `@kitn.ai/ui` for the full shape. */
|
|
9
|
-
data?:
|
|
9
|
+
data?: ChoiceCardData;
|
|
10
10
|
/** Stable card id correlating every emitted CardEvent. Attribute: `card-id`. */
|
|
11
11
|
cardId?: string;
|
|
12
12
|
/** Heading rendered in the card chrome (= CardEnvelope.title). Attribute: `heading`. */
|
|
@@ -14,7 +14,7 @@ interface Props extends Record<string, unknown> {
|
|
|
14
14
|
/** Set when the user resolved this card; renders the read-only view. Property:
|
|
15
15
|
* `el.resolution = { kind:'action', action:'…' }`. */
|
|
16
16
|
resolution?: Record<string, unknown>;
|
|
17
|
-
/** Controlled selection
|
|
17
|
+
/** Controlled selection: the selected option id. When set, the consumer owns
|
|
18
18
|
* the current pick (RadioGroup `value`). Attribute: `value`. */
|
|
19
19
|
value?: string;
|
|
20
20
|
/** Option id to pre-select on mount (uncontrolled seed). Attribute: `default-value`. */
|
|
@@ -68,23 +68,23 @@ defineWebComponent<Props, Events>(
|
|
|
68
68
|
expose({
|
|
69
69
|
/** Focus the radiogroup roving tab stop (or the Other input when selected). */
|
|
70
70
|
focus: (options?: FocusOptions) => controller?.focus(options),
|
|
71
|
-
/** Select an option by id locally
|
|
72
|
-
*
|
|
71
|
+
/** Select an option by id locally: no emit, fires kai-value-change (same as a
|
|
72
|
+
* row click). Lets a consumer pre-highlight or drive selection externally. */
|
|
73
73
|
select: (optionId: string) => controller?.select(optionId),
|
|
74
|
-
/** Submit the current selection
|
|
74
|
+
/** Submit the current selection: emits the `action` verb on kai-card and
|
|
75
75
|
* resolves the card (single-shot). Named `send`, not `submit`, per the shared
|
|
76
76
|
* vocabulary. */
|
|
77
77
|
send: () => controller?.send(),
|
|
78
|
-
/** Trigger the dismiss path
|
|
78
|
+
/** Trigger the dismiss path: emits `dismiss` on kai-card and optimistically
|
|
79
79
|
* collapses the card to its re-openable stub. */
|
|
80
80
|
dismiss: () => controller?.dismiss(),
|
|
81
|
-
/** Re-open a dismissed card from its stub
|
|
81
|
+
/** Re-open a dismissed card from its stub: emits `reopen` on kai-card. */
|
|
82
82
|
reopen: () => controller?.reopen(),
|
|
83
83
|
});
|
|
84
84
|
|
|
85
85
|
return (
|
|
86
86
|
<ChoiceCard
|
|
87
|
-
data={props.data
|
|
87
|
+
data={props.data}
|
|
88
88
|
cardId={props.cardId ?? (element.id || 'kai-choice')}
|
|
89
89
|
heading={props.heading}
|
|
90
90
|
resolution={props.resolution as CardResolution | undefined}
|
|
@@ -17,7 +17,7 @@ interface Props extends Record<string, unknown> {
|
|
|
17
17
|
/** Floating placement relative to the anchor (default `bottom`). */
|
|
18
18
|
placement?: string;
|
|
19
19
|
/** Color tone: `primary` (default, theme accent), `info` (blue), `success`
|
|
20
|
-
* (green), `warning` (amber), or `error` (red)
|
|
20
|
+
* (green), `warning` (amber), or `error` (red), reusing the kit's tool hues. */
|
|
21
21
|
tone?: 'primary' | 'info' | 'success' | 'warning' | 'error';
|
|
22
22
|
/** Render the arrow that points at the anchor (default `true`). Set
|
|
23
23
|
* `arrow="false"` for a plain bubble with no pointer. */
|